wg-backend-django/dell-env/lib/python3.11/site-packages/dash_cytoscape/dash_cytoscape.dev.js
2023-10-30 14:40:43 +07:00

353 lines
3.9 MiB
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

window["dash_cytoscape"] =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/lib/index.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./node_modules/cytoscape/dist/cytoscape.cjs.js":
/*!******************************************************!*\
!*** ./node_modules/cytoscape/dist/cytoscape.cjs.js ***!
\******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("/* WEBPACK VAR INJECTION */(function(setImmediate) {/**\n * Copyright (c) 2016-2020, The Cytoscape Consortium.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this software and associated documentation files (the “Software”), to deal in\n * the Software without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Software, and to permit persons to whom the Software is furnished to do\n * so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n\n\nfunction _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar util = _interopDefault(__webpack_require__(/*! lodash.debounce */ \"./node_modules/lodash.debounce/index.js\"));\nvar Heap = _interopDefault(__webpack_require__(/*! heap */ \"./node_modules/heap/index.js\"));\n\nfunction _typeof(obj) {\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function (obj) {\n return typeof obj;\n };\n } else {\n _typeof = function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}\n\nfunction _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\n\nfunction _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\nfunction _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nfunction _slicedToArray(arr, i) {\n return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();\n}\n\nfunction _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\n\nfunction _iterableToArrayLimit(arr, i) {\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n\n return _arr;\n}\n\nfunction _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n}\n\nvar window$1 = typeof window === 'undefined' ? null : window; // eslint-disable-line no-undef\n\nvar navigator = window$1 ? window$1.navigator : null;\nvar document$1 = window$1 ? window$1.document : null;\n\nvar typeofstr = _typeof('');\n\nvar typeofobj = _typeof({});\n\nvar typeoffn = _typeof(function () {});\n\nvar typeofhtmlele = typeof HTMLElement === \"undefined\" ? \"undefined\" : _typeof(HTMLElement);\n\nvar instanceStr = function instanceStr(obj) {\n return obj && obj.instanceString && fn(obj.instanceString) ? obj.instanceString() : null;\n};\n\nvar string = function string(obj) {\n return obj != null && _typeof(obj) == typeofstr;\n};\nvar fn = function fn(obj) {\n return obj != null && _typeof(obj) === typeoffn;\n};\nvar array = function array(obj) {\n return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;\n};\nvar plainObject = function plainObject(obj) {\n return obj != null && _typeof(obj) === typeofobj && !array(obj) && obj.constructor === Object;\n};\nvar object = function object(obj) {\n return obj != null && _typeof(obj) === typeofobj;\n};\nvar number = function number(obj) {\n return obj != null && _typeof(obj) === _typeof(1) && !isNaN(obj);\n};\nvar integer = function integer(obj) {\n return number(obj) && Math.floor(obj) === obj;\n};\nvar htmlElement = function htmlElement(obj) {\n if ('undefined' === typeofhtmlele) {\n return undefined;\n } else {\n return null != obj && obj instanceof HTMLElement;\n }\n};\nvar elementOrCollection = function elementOrCollection(obj) {\n return element(obj) || collection(obj);\n};\nvar element = function element(obj) {\n return instanceStr(obj) === 'collection' && obj._private.single;\n};\nvar collection = function collection(obj) {\n return instanceStr(obj) === 'collection' && !obj._private.single;\n};\nvar core = function core(obj) {\n return instanceStr(obj) === 'core';\n};\nvar stylesheet = function stylesheet(obj) {\n return instanceStr(obj) === 'stylesheet';\n};\nvar event = function event(obj) {\n return instanceStr(obj) === 'event';\n};\nvar emptyString = function emptyString(obj) {\n if (obj === undefined || obj === null) {\n // null is empty\n return true;\n } else if (obj === '' || obj.match(/^\\s+$/)) {\n return true; // empty string is empty\n }\n\n return false; // otherwise, we don't know what we've got\n};\nvar domElement = function domElement(obj) {\n if (typeof HTMLElement === 'undefined') {\n return false; // we're not in a browser so it doesn't matter\n } else {\n return obj instanceof HTMLElement;\n }\n};\nvar boundingBox = function boundingBox(obj) {\n return plainObject(obj) && number(obj.x1) && number(obj.x2) && number(obj.y1) && number(obj.y2);\n};\nvar promise = function promise(obj) {\n return object(obj) && fn(obj.then);\n};\nvar ms = function ms() {\n return navigator && navigator.userAgent.match(/msie|trident|edge/i);\n}; // probably a better way to detect this...\n\nvar memoize = function memoize(fn, keyFn) {\n if (!keyFn) {\n keyFn = function keyFn() {\n if (arguments.length === 1) {\n return arguments[0];\n } else if (arguments.length === 0) {\n return 'undefined';\n }\n\n var args = [];\n\n for (var i = 0; i < arguments.length; i++) {\n args.push(arguments[i]);\n }\n\n return args.join('$');\n };\n }\n\n var memoizedFn = function memoizedFn() {\n var self = this;\n var args = arguments;\n var ret;\n var k = keyFn.apply(self, args);\n var cache = memoizedFn.cache;\n\n if (!(ret = cache[k])) {\n ret = cache[k] = fn.apply(self, args);\n }\n\n return ret;\n };\n\n memoizedFn.cache = {};\n return memoizedFn;\n};\n\nvar camel2dash = memoize(function (str) {\n return str.replace(/([A-Z])/g, function (v) {\n return '-' + v.toLowerCase();\n });\n});\nvar dash2camel = memoize(function (str) {\n return str.replace(/(-\\w)/g, function (v) {\n return v[1].toUpperCase();\n });\n});\nvar prependCamel = memoize(function (prefix, str) {\n return prefix + str[0].toUpperCase() + str.substring(1);\n}, function (prefix, str) {\n return prefix + '$' + str;\n});\nvar capitalize = function capitalize(str) {\n if (emptyString(str)) {\n return str;\n }\n\n return str.charAt(0).toUpperCase() + str.substring(1);\n};\n\nvar number$1 = '(?:[-+]?(?:(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[Ee][+-]?\\\\d+)?))';\nvar rgba = 'rgb[a]?\\\\((' + number$1 + '[%]?)\\\\s*,\\\\s*(' + number$1 + '[%]?)\\\\s*,\\\\s*(' + number$1 + '[%]?)(?:\\\\s*,\\\\s*(' + number$1 + '))?\\\\)';\nvar rgbaNoBackRefs = 'rgb[a]?\\\\((?:' + number$1 + '[%]?)\\\\s*,\\\\s*(?:' + number$1 + '[%]?)\\\\s*,\\\\s*(?:' + number$1 + '[%]?)(?:\\\\s*,\\\\s*(?:' + number$1 + '))?\\\\)';\nvar hsla = 'hsl[a]?\\\\((' + number$1 + ')\\\\s*,\\\\s*(' + number$1 + '[%])\\\\s*,\\\\s*(' + number$1 + '[%])(?:\\\\s*,\\\\s*(' + number$1 + '))?\\\\)';\nvar hslaNoBackRefs = 'hsl[a]?\\\\((?:' + number$1 + ')\\\\s*,\\\\s*(?:' + number$1 + '[%])\\\\s*,\\\\s*(?:' + number$1 + '[%])(?:\\\\s*,\\\\s*(?:' + number$1 + '))?\\\\)';\nvar hex3 = '\\\\#[0-9a-fA-F]{3}';\nvar hex6 = '\\\\#[0-9a-fA-F]{6}';\n\nvar ascending = function ascending(a, b) {\n if (a < b) {\n return -1;\n } else if (a > b) {\n return 1;\n } else {\n return 0;\n }\n};\nvar descending = function descending(a, b) {\n return -1 * ascending(a, b);\n};\n\nvar extend = Object.assign != null ? Object.assign.bind(Object) : function (tgt) {\n var args = arguments;\n\n for (var i = 1; i < args.length; i++) {\n var obj = args[i];\n\n if (obj == null) {\n continue;\n }\n\n var keys = Object.keys(obj);\n\n for (var j = 0; j < keys.length; j++) {\n var k = keys[j];\n tgt[k] = obj[k];\n }\n }\n\n return tgt;\n};\n\nvar hex2tuple = function hex2tuple(hex) {\n if (!(hex.length === 4 || hex.length === 7) || hex[0] !== '#') {\n return;\n }\n\n var shortHex = hex.length === 4;\n var r, g, b;\n var base = 16;\n\n if (shortHex) {\n r = parseInt(hex[1] + hex[1], base);\n g = parseInt(hex[2] + hex[2], base);\n b = parseInt(hex[3] + hex[3], base);\n } else {\n r = parseInt(hex[1] + hex[2], base);\n g = parseInt(hex[3] + hex[4], base);\n b = parseInt(hex[5] + hex[6], base);\n }\n\n return [r, g, b];\n}; // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0)\n\nvar hsl2tuple = function hsl2tuple(hsl) {\n var ret;\n var h, s, l, a, r, g, b;\n\n function hue2rgb(p, q, t) {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n }\n\n var m = new RegExp('^' + hsla + '$').exec(hsl);\n\n if (m) {\n // get hue\n h = parseInt(m[1]);\n\n if (h < 0) {\n h = (360 - -1 * h % 360) % 360;\n } else if (h > 360) {\n h = h % 360;\n }\n\n h /= 360; // normalise on [0, 1]\n\n s = parseFloat(m[2]);\n\n if (s < 0 || s > 100) {\n return;\n } // saturation is [0, 100]\n\n\n s = s / 100; // normalise on [0, 1]\n\n l = parseFloat(m[3]);\n\n if (l < 0 || l > 100) {\n return;\n } // lightness is [0, 100]\n\n\n l = l / 100; // normalise on [0, 1]\n\n a = m[4];\n\n if (a !== undefined) {\n a = parseFloat(a);\n\n if (a < 0 || a > 1) {\n return;\n } // alpha is [0, 1]\n\n } // now, convert to rgb\n // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript\n\n\n if (s === 0) {\n r = g = b = Math.round(l * 255); // achromatic\n } else {\n var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n var p = 2 * l - q;\n r = Math.round(255 * hue2rgb(p, q, h + 1 / 3));\n g = Math.round(255 * hue2rgb(p, q, h));\n b = Math.round(255 * hue2rgb(p, q, h - 1 / 3));\n }\n\n ret = [r, g, b, a];\n }\n\n return ret;\n}; // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0)\n\nvar rgb2tuple = function rgb2tuple(rgb) {\n var ret;\n var m = new RegExp('^' + rgba + '$').exec(rgb);\n\n if (m) {\n ret = [];\n var isPct = [];\n\n for (var i = 1; i <= 3; i++) {\n var channel = m[i];\n\n if (channel[channel.length - 1] === '%') {\n isPct[i] = true;\n }\n\n channel = parseFloat(channel);\n\n if (isPct[i]) {\n channel = channel / 100 * 255; // normalise to [0, 255]\n }\n\n if (channel < 0 || channel > 255) {\n return;\n } // invalid channel value\n\n\n ret.push(Math.floor(channel));\n }\n\n var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3];\n var allArePct = isPct[1] && isPct[2] && isPct[3];\n\n if (atLeastOneIsPct && !allArePct) {\n return;\n } // must all be percent values if one is\n\n\n var alpha = m[4];\n\n if (alpha !== undefined) {\n alpha = parseFloat(alpha);\n\n if (alpha < 0 || alpha > 1) {\n return;\n } // invalid alpha value\n\n\n ret.push(alpha);\n }\n }\n\n return ret;\n};\nvar colorname2tuple = function colorname2tuple(color) {\n return colors[color.toLowerCase()];\n};\nvar color2tuple = function color2tuple(color) {\n return (array(color) ? color : null) || colorname2tuple(color) || hex2tuple(color) || rgb2tuple(color) || hsl2tuple(color);\n};\nvar colors = {\n // special colour names\n transparent: [0, 0, 0, 0],\n // NB alpha === 0\n // regular colours\n aliceblue: [240, 248, 255],\n antiquewhite: [250, 235, 215],\n aqua: [0, 255, 255],\n aquamarine: [127, 255, 212],\n azure: [240, 255, 255],\n beige: [245, 245, 220],\n bisque: [255, 228, 196],\n black: [0, 0, 0],\n blanchedalmond: [255, 235, 205],\n blue: [0, 0, 255],\n blueviolet: [138, 43, 226],\n brown: [165, 42, 42],\n burlywood: [222, 184, 135],\n cadetblue: [95, 158, 160],\n chartreuse: [127, 255, 0],\n chocolate: [210, 105, 30],\n coral: [255, 127, 80],\n cornflowerblue: [100, 149, 237],\n cornsilk: [255, 248, 220],\n crimson: [220, 20, 60],\n cyan: [0, 255, 255],\n darkblue: [0, 0, 139],\n darkcyan: [0, 139, 139],\n darkgoldenrod: [184, 134, 11],\n darkgray: [169, 169, 169],\n darkgreen: [0, 100, 0],\n darkgrey: [169, 169, 169],\n darkkhaki: [189, 183, 107],\n darkmagenta: [139, 0, 139],\n darkolivegreen: [85, 107, 47],\n darkorange: [255, 140, 0],\n darkorchid: [153, 50, 204],\n darkred: [139, 0, 0],\n darksalmon: [233, 150, 122],\n darkseagreen: [143, 188, 143],\n darkslateblue: [72, 61, 139],\n darkslategray: [47, 79, 79],\n darkslategrey: [47, 79, 79],\n darkturquoise: [0, 206, 209],\n darkviolet: [148, 0, 211],\n deeppink: [255, 20, 147],\n deepskyblue: [0, 191, 255],\n dimgray: [105, 105, 105],\n dimgrey: [105, 105, 105],\n dodgerblue: [30, 144, 255],\n firebrick: [178, 34, 34],\n floralwhite: [255, 250, 240],\n forestgreen: [34, 139, 34],\n fuchsia: [255, 0, 255],\n gainsboro: [220, 220, 220],\n ghostwhite: [248, 248, 255],\n gold: [255, 215, 0],\n goldenrod: [218, 165, 32],\n gray: [128, 128, 128],\n grey: [128, 128, 128],\n green: [0, 128, 0],\n greenyellow: [173, 255, 47],\n honeydew: [240, 255, 240],\n hotpink: [255, 105, 180],\n indianred: [205, 92, 92],\n indigo: [75, 0, 130],\n ivory: [255, 255, 240],\n khaki: [240, 230, 140],\n lavender: [230, 230, 250],\n lavenderblush: [255, 240, 245],\n lawngreen: [124, 252, 0],\n lemonchiffon: [255, 250, 205],\n lightblue: [173, 216, 230],\n lightcoral: [240, 128, 128],\n lightcyan: [224, 255, 255],\n lightgoldenrodyellow: [250, 250, 210],\n lightgray: [211, 211, 211],\n lightgreen: [144, 238, 144],\n lightgrey: [211, 211, 211],\n lightpink: [255, 182, 193],\n lightsalmon: [255, 160, 122],\n lightseagreen: [32, 178, 170],\n lightskyblue: [135, 206, 250],\n lightslategray: [119, 136, 153],\n lightslategrey: [119, 136, 153],\n lightsteelblue: [176, 196, 222],\n lightyellow: [255, 255, 224],\n lime: [0, 255, 0],\n limegreen: [50, 205, 50],\n linen: [250, 240, 230],\n magenta: [255, 0, 255],\n maroon: [128, 0, 0],\n mediumaquamarine: [102, 205, 170],\n mediumblue: [0, 0, 205],\n mediumorchid: [186, 85, 211],\n mediumpurple: [147, 112, 219],\n mediumseagreen: [60, 179, 113],\n mediumslateblue: [123, 104, 238],\n mediumspringgreen: [0, 250, 154],\n mediumturquoise: [72, 209, 204],\n mediumvioletred: [199, 21, 133],\n midnightblue: [25, 25, 112],\n mintcream: [245, 255, 250],\n mistyrose: [255, 228, 225],\n moccasin: [255, 228, 181],\n navajowhite: [255, 222, 173],\n navy: [0, 0, 128],\n oldlace: [253, 245, 230],\n olive: [128, 128, 0],\n olivedrab: [107, 142, 35],\n orange: [255, 165, 0],\n orangered: [255, 69, 0],\n orchid: [218, 112, 214],\n palegoldenrod: [238, 232, 170],\n palegreen: [152, 251, 152],\n paleturquoise: [175, 238, 238],\n palevioletred: [219, 112, 147],\n papayawhip: [255, 239, 213],\n peachpuff: [255, 218, 185],\n peru: [205, 133, 63],\n pink: [255, 192, 203],\n plum: [221, 160, 221],\n powderblue: [176, 224, 230],\n purple: [128, 0, 128],\n red: [255, 0, 0],\n rosybrown: [188, 143, 143],\n royalblue: [65, 105, 225],\n saddlebrown: [139, 69, 19],\n salmon: [250, 128, 114],\n sandybrown: [244, 164, 96],\n seagreen: [46, 139, 87],\n seashell: [255, 245, 238],\n sienna: [160, 82, 45],\n silver: [192, 192, 192],\n skyblue: [135, 206, 235],\n slateblue: [106, 90, 205],\n slategray: [112, 128, 144],\n slategrey: [112, 128, 144],\n snow: [255, 250, 250],\n springgreen: [0, 255, 127],\n steelblue: [70, 130, 180],\n tan: [210, 180, 140],\n teal: [0, 128, 128],\n thistle: [216, 191, 216],\n tomato: [255, 99, 71],\n turquoise: [64, 224, 208],\n violet: [238, 130, 238],\n wheat: [245, 222, 179],\n white: [255, 255, 255],\n whitesmoke: [245, 245, 245],\n yellow: [255, 255, 0],\n yellowgreen: [154, 205, 50]\n};\n\nvar setMap = function setMap(options) {\n var obj = options.map;\n var keys = options.keys;\n var l = keys.length;\n\n for (var i = 0; i < l; i++) {\n var key = keys[i];\n\n if (plainObject(key)) {\n throw Error('Tried to set map with object key');\n }\n\n if (i < keys.length - 1) {\n // extend the map if necessary\n if (obj[key] == null) {\n obj[key] = {};\n }\n\n obj = obj[key];\n } else {\n // set the value\n obj[key] = options.value;\n }\n }\n}; // gets the value in a map even if it's not built in places\n\nvar getMap = function getMap(options) {\n var obj = options.map;\n var keys = options.keys;\n var l = keys.length;\n\n for (var i = 0; i < l; i++) {\n var key = keys[i];\n\n if (plainObject(key)) {\n throw Error('Tried to get map with object key');\n }\n\n obj = obj[key];\n\n if (obj == null) {\n return obj;\n }\n }\n\n return obj;\n}; // deletes the entry in the map\n\nvar performance = window$1 ? window$1.performance : null;\nvar pnow = performance && performance.now ? function () {\n return performance.now();\n} : function () {\n return Date.now();\n};\n\nvar raf = function () {\n if (window$1) {\n if (window$1.requestAnimationFrame) {\n return function (fn) {\n window$1.requestAnimationFrame(fn);\n };\n } else if (window$1.mozRequestAnimationFrame) {\n return function (fn) {\n window$1.mozRequestAnimationFrame(fn);\n };\n } else if (window$1.webkitRequestAnimationFrame) {\n return function (fn) {\n window$1.webkitRequestAnimationFrame(fn);\n };\n } else if (window$1.msRequestAnimationFrame) {\n return function (fn) {\n window$1.msRequestAnimationFrame(fn);\n };\n }\n }\n\n return function (fn) {\n if (fn) {\n setTimeout(function () {\n fn(pnow());\n }, 1000 / 60);\n }\n };\n}();\n\nvar requestAnimationFrame = function requestAnimationFrame(fn) {\n return raf(fn);\n};\nvar performanceNow = pnow;\n\nvar DEFAULT_HASH_SEED = 9261;\nvar K = 65599; // 37 also works pretty well\n\nvar DEFAULT_HASH_SEED_ALT = 5381;\nvar hashIterableInts = function hashIterableInts(iterator) {\n var seed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_HASH_SEED;\n // sdbm/string-hash\n var hash = seed;\n var entry;\n\n for (;;) {\n entry = iterator.next();\n\n if (entry.done) {\n break;\n }\n\n hash = hash * K + entry.value | 0;\n }\n\n return hash;\n};\nvar hashInt = function hashInt(num) {\n var seed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_HASH_SEED;\n // sdbm/string-hash\n return seed * K + num | 0;\n};\nvar hashIntAlt = function hashIntAlt(num) {\n var seed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_HASH_SEED_ALT;\n // djb2/string-hash\n return (seed << 5) + seed + num | 0;\n};\nvar combineHashes = function combineHashes(hash1, hash2) {\n return hash1 * 0x200000 + hash2;\n};\nvar combineHashesArray = function combineHashesArray(hashes) {\n return hashes[0] * 0x200000 + hashes[1];\n};\nvar hashArrays = function hashArrays(hashes1, hashes2) {\n return [hashInt(hashes1[0], hashes2[0]), hashIntAlt(hashes1[1], hashes2[1])];\n};\nvar hashIntsArray = function hashIntsArray(ints, seed) {\n var entry = {\n value: 0,\n done: false\n };\n var i = 0;\n var length = ints.length;\n var iterator = {\n next: function next() {\n if (i < length) {\n entry.value = ints[i++];\n } else {\n entry.done = true;\n }\n\n return entry;\n }\n };\n return hashIterableInts(iterator, seed);\n};\nvar hashString = function hashString(str, seed) {\n var entry = {\n value: 0,\n done: false\n };\n var i = 0;\n var length = str.length;\n var iterator = {\n next: function next() {\n if (i < length) {\n entry.value = str.charCodeAt(i++);\n } else {\n entry.done = true;\n }\n\n return entry;\n }\n };\n return hashIterableInts(iterator, seed);\n};\nvar hashStrings = function hashStrings() {\n return hashStringsArray(arguments);\n};\nvar hashStringsArray = function hashStringsArray(strs) {\n var hash;\n\n for (var i = 0; i < strs.length; i++) {\n var str = strs[i];\n\n if (i === 0) {\n hash = hashString(str);\n } else {\n hash = hashString(str, hash);\n }\n }\n\n return hash;\n};\n\n/*global console */\nvar warningsEnabled = true;\nvar warnSupported = console.warn != null; // eslint-disable-line no-console\n\nvar traceSupported = console.trace != null; // eslint-disable-line no-console\n\nvar MAX_INT = Number.MAX_SAFE_INTEGER || 9007199254740991;\nvar trueify = function trueify() {\n return true;\n};\nvar falsify = function falsify() {\n return false;\n};\nvar zeroify = function zeroify() {\n return 0;\n};\nvar noop = function noop() {};\nvar error = function error(msg) {\n throw new Error(msg);\n};\nvar warnings = function warnings(enabled) {\n if (enabled !== undefined) {\n warningsEnabled = !!enabled;\n } else {\n return warningsEnabled;\n }\n};\nvar warn = function warn(msg) {\n /* eslint-disable no-console */\n if (!warnings()) {\n return;\n }\n\n if (warnSupported) {\n console.warn(msg);\n } else {\n console.log(msg);\n\n if (traceSupported) {\n console.trace();\n }\n }\n};\n/* eslint-enable */\n\nvar clone = function clone(obj) {\n return extend({}, obj);\n}; // gets a shallow copy of the argument\n\nvar copy = function copy(obj) {\n if (obj == null) {\n return obj;\n }\n\n if (array(obj)) {\n return obj.slice();\n } else if (plainObject(obj)) {\n return clone(obj);\n } else {\n return obj;\n }\n};\nvar copyArray = function copyArray(arr) {\n return arr.slice();\n};\nvar uuid = function uuid(a, b\n/* placeholders */\n) {\n for ( // loop :)\n b = a = ''; // b - result , a - numeric letiable\n a++ < 36; //\n b += a * 51 & 52 // if \"a\" is not 9 or 14 or 19 or 24\n ? // return a random number or 4\n (a ^ 15 // if \"a\" is not 15\n ? // genetate a random number from 0 to 15\n 8 ^ Math.random() * (a ^ 20 ? 16 : 4) // unless \"a\" is 20, in which case a random number from 8 to 11\n : 4 // otherwise 4\n ).toString(16) : '-' // in other cases (if \"a\" is 9,14,19,24) insert \"-\"\n ) {\n }\n\n return b;\n};\nvar _staticEmptyObject = {};\nvar staticEmptyObject = function staticEmptyObject() {\n return _staticEmptyObject;\n};\nvar defaults = function defaults(_defaults) {\n var keys = Object.keys(_defaults);\n return function (opts) {\n var filledOpts = {};\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n var optVal = opts == null ? undefined : opts[key];\n filledOpts[key] = optVal === undefined ? _defaults[key] : optVal;\n }\n\n return filledOpts;\n };\n};\nvar removeFromArray = function removeFromArray(arr, ele, manyCopies) {\n for (var i = arr.length; i >= 0; i--) {\n if (arr[i] === ele) {\n arr.splice(i, 1);\n\n if (!manyCopies) {\n break;\n }\n }\n }\n};\nvar clearArray = function clearArray(arr) {\n arr.splice(0, arr.length);\n};\nvar push = function push(arr, otherArr) {\n for (var i = 0; i < otherArr.length; i++) {\n var el = otherArr[i];\n arr.push(el);\n }\n};\nvar getPrefixedProperty = function getPrefixedProperty(obj, propName, prefix) {\n if (prefix) {\n propName = prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth\n }\n\n return obj[propName];\n};\nvar setPrefixedProperty = function setPrefixedProperty(obj, propName, prefix, value) {\n if (prefix) {\n propName = prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth\n }\n\n obj[propName] = value;\n};\n\n/* global Map */\nvar ObjectMap =\n/*#__PURE__*/\nfunction () {\n function ObjectMap() {\n _classCallCheck(this, ObjectMap);\n\n this._obj = {};\n }\n\n _createClass(ObjectMap, [{\n key: \"set\",\n value: function set(key, val) {\n this._obj[key] = val;\n return this;\n }\n }, {\n key: \"delete\",\n value: function _delete(key) {\n this._obj[key] = undefined;\n return this;\n }\n }, {\n key: \"clear\",\n value: function clear() {\n this._obj = {};\n }\n }, {\n key: \"has\",\n value: function has(key) {\n return this._obj[key] !== undefined;\n }\n }, {\n key: \"get\",\n value: function get(key) {\n return this._obj[key];\n }\n }]);\n\n return ObjectMap;\n}();\n\nvar Map$1 = typeof Map !== 'undefined' ? Map : ObjectMap;\n\n/* global Set */\nvar undef = \"undefined\" ;\n\nvar ObjectSet =\n/*#__PURE__*/\nfunction () {\n function ObjectSet(arrayOrObjectSet) {\n _classCallCheck(this, ObjectSet);\n\n this._obj = Object.create(null);\n this.size = 0;\n\n if (arrayOrObjectSet != null) {\n var arr;\n\n if (arrayOrObjectSet.instanceString != null && arrayOrObjectSet.instanceString() === this.instanceString()) {\n arr = arrayOrObjectSet.toArray();\n } else {\n arr = arrayOrObjectSet;\n }\n\n for (var i = 0; i < arr.length; i++) {\n this.add(arr[i]);\n }\n }\n }\n\n _createClass(ObjectSet, [{\n key: \"instanceString\",\n value: function instanceString() {\n return 'set';\n }\n }, {\n key: \"add\",\n value: function add(val) {\n var o = this._obj;\n\n if (o[val] !== 1) {\n o[val] = 1;\n this.size++;\n }\n }\n }, {\n key: \"delete\",\n value: function _delete(val) {\n var o = this._obj;\n\n if (o[val] === 1) {\n o[val] = 0;\n this.size--;\n }\n }\n }, {\n key: \"clear\",\n value: function clear() {\n this._obj = Object.create(null);\n }\n }, {\n key: \"has\",\n value: function has(val) {\n return this._obj[val] === 1;\n }\n }, {\n key: \"toArray\",\n value: function toArray() {\n var _this = this;\n\n return Object.keys(this._obj).filter(function (key) {\n return _this.has(key);\n });\n }\n }, {\n key: \"forEach\",\n value: function forEach(callback, thisArg) {\n return this.toArray().forEach(callback, thisArg);\n }\n }]);\n\n return ObjectSet;\n}();\n\nvar Set$1 = (typeof Set === \"undefined\" ? \"undefined\" : _typeof(Set)) !== undef ? Set : ObjectSet;\n\nvar Element = function Element(cy, params, restore) {\n restore = restore === undefined || restore ? true : false;\n\n if (cy === undefined || params === undefined || !core(cy)) {\n error('An element must have a core reference and parameters set');\n return;\n }\n\n var group = params.group; // try to automatically infer the group if unspecified\n\n if (group == null) {\n if (params.data && params.data.source != null && params.data.target != null) {\n group = 'edges';\n } else {\n group = 'nodes';\n }\n } // validate group\n\n\n if (group !== 'nodes' && group !== 'edges') {\n error('An element must be of type `nodes` or `edges`; you specified `' + group + '`');\n return;\n } // make the element array-like, just like a collection\n\n\n this.length = 1;\n this[0] = this; // NOTE: when something is added here, add also to ele.json()\n\n var _p = this._private = {\n cy: cy,\n single: true,\n // indicates this is an element\n data: params.data || {},\n // data object\n position: params.position || {\n x: 0,\n y: 0\n },\n // (x, y) position pair\n autoWidth: undefined,\n // width and height of nodes calculated by the renderer when set to special 'auto' value\n autoHeight: undefined,\n autoPadding: undefined,\n compoundBoundsClean: false,\n // whether the compound dimensions need to be recalculated the next time dimensions are read\n listeners: [],\n // array of bound listeners\n group: group,\n // string; 'nodes' or 'edges'\n style: {},\n // properties as set by the style\n rstyle: {},\n // properties for style sent from the renderer to the core\n styleCxts: [],\n // applied style contexts from the styler\n styleKeys: {},\n // per-group keys of style property values\n removed: true,\n // whether it's inside the vis; true if removed (set true here since we call restore)\n selected: params.selected ? true : false,\n // whether it's selected\n selectable: params.selectable === undefined ? true : params.selectable ? true : false,\n // whether it's selectable\n locked: params.locked ? true : false,\n // whether the element is locked (cannot be moved)\n grabbed: false,\n // whether the element is grabbed by the mouse; renderer sets this privately\n grabbable: params.grabbable === undefined ? true : params.grabbable ? true : false,\n // whether the element can be grabbed\n pannable: params.pannable === undefined ? group === 'edges' ? true : false : params.pannable ? true : false,\n // whether the element has passthrough panning enabled\n active: false,\n // whether the element is active from user interaction\n classes: new Set$1(),\n // map ( className => true )\n animation: {\n // object for currently-running animations\n current: [],\n queue: []\n },\n rscratch: {},\n // object in which the renderer can store information\n scratch: params.scratch || {},\n // scratch objects\n edges: [],\n // array of connected edges\n children: [],\n // array of children\n parent: null,\n // parent ref\n traversalCache: {},\n // cache of output of traversal functions\n backgrounding: false,\n // whether background images are loading\n bbCache: null,\n // cache of the current bounding box\n bbCacheShift: {\n x: 0,\n y: 0\n },\n // shift applied to cached bb to be applied on next get\n bodyBounds: null,\n // bounds cache of element body, w/o overlay\n overlayBounds: null,\n // bounds cache of element body, including overlay\n labelBounds: {\n // bounds cache of labels\n all: null,\n source: null,\n target: null,\n main: null\n },\n arrowBounds: {\n // bounds cache of edge arrows\n source: null,\n target: null,\n 'mid-source': null,\n 'mid-target': null\n }\n };\n\n if (_p.position.x == null) {\n _p.position.x = 0;\n }\n\n if (_p.position.y == null) {\n _p.position.y = 0;\n } // renderedPosition overrides if specified\n\n\n if (params.renderedPosition) {\n var rpos = params.renderedPosition;\n var pan = cy.pan();\n var zoom = cy.zoom();\n _p.position = {\n x: (rpos.x - pan.x) / zoom,\n y: (rpos.y - pan.y) / zoom\n };\n }\n\n var classes = [];\n\n if (array(params.classes)) {\n classes = params.classes;\n } else if (string(params.classes)) {\n classes = params.classes.split(/\\s+/);\n }\n\n for (var i = 0, l = classes.length; i < l; i++) {\n var cls = classes[i];\n\n if (!cls || cls === '') {\n continue;\n }\n\n _p.classes.add(cls);\n }\n\n this.createEmitter();\n var bypass = params.style || params.css;\n\n if (bypass) {\n warn('Setting a `style` bypass at element creation is deprecated');\n this.style(bypass);\n }\n\n if (restore === undefined || restore) {\n this.restore();\n }\n};\n\nvar defineSearch = function defineSearch(params) {\n params = {\n bfs: params.bfs || !params.dfs,\n dfs: params.dfs || !params.bfs\n }; // from pseudocode on wikipedia\n\n return function searchFn(roots, fn$1, directed) {\n var options;\n\n if (plainObject(roots) && !elementOrCollection(roots)) {\n options = roots;\n roots = options.roots || options.root;\n fn$1 = options.visit;\n directed = options.directed;\n }\n\n directed = arguments.length === 2 && !fn(fn$1) ? fn$1 : directed;\n fn$1 = fn(fn$1) ? fn$1 : function () {};\n var cy = this._private.cy;\n var v = roots = string(roots) ? this.filter(roots) : roots;\n var Q = [];\n var connectedNodes = [];\n var connectedBy = {};\n var id2depth = {};\n var V = {};\n var j = 0;\n var found;\n\n var _this$byGroup = this.byGroup(),\n nodes = _this$byGroup.nodes,\n edges = _this$byGroup.edges; // enqueue v\n\n\n for (var i = 0; i < v.length; i++) {\n var vi = v[i];\n var viId = vi.id();\n\n if (vi.isNode()) {\n Q.unshift(vi);\n\n if (params.bfs) {\n V[viId] = true;\n connectedNodes.push(vi);\n }\n\n id2depth[viId] = 0;\n }\n }\n\n var _loop2 = function _loop2() {\n var v = params.bfs ? Q.shift() : Q.pop();\n var vId = v.id();\n\n if (params.dfs) {\n if (V[vId]) {\n return \"continue\";\n }\n\n V[vId] = true;\n connectedNodes.push(v);\n }\n\n var depth = id2depth[vId];\n var prevEdge = connectedBy[vId];\n var src = prevEdge != null ? prevEdge.source() : null;\n var tgt = prevEdge != null ? prevEdge.target() : null;\n var prevNode = prevEdge == null ? undefined : v.same(src) ? tgt[0] : src[0];\n var ret = void 0;\n ret = fn$1(v, prevEdge, prevNode, j++, depth);\n\n if (ret === true) {\n found = v;\n return \"break\";\n }\n\n if (ret === false) {\n return \"break\";\n }\n\n var vwEdges = v.connectedEdges().filter(function (e) {\n return (!directed || e.source().same(v)) && edges.has(e);\n });\n\n for (var _i2 = 0; _i2 < vwEdges.length; _i2++) {\n var e = vwEdges[_i2];\n var w = e.connectedNodes().filter(function (n) {\n return !n.same(v) && nodes.has(n);\n });\n var wId = w.id();\n\n if (w.length !== 0 && !V[wId]) {\n w = w[0];\n Q.push(w);\n\n if (params.bfs) {\n V[wId] = true;\n connectedNodes.push(w);\n }\n\n connectedBy[wId] = e;\n id2depth[wId] = id2depth[vId] + 1;\n }\n }\n };\n\n _loop: while (Q.length !== 0) {\n var _ret = _loop2();\n\n switch (_ret) {\n case \"continue\":\n continue;\n\n case \"break\":\n break _loop;\n }\n }\n\n var connectedEles = cy.collection();\n\n for (var _i = 0; _i < connectedNodes.length; _i++) {\n var node = connectedNodes[_i];\n var edge = connectedBy[node.id()];\n\n if (edge != null) {\n connectedEles.merge(edge);\n }\n\n connectedEles.merge(node);\n }\n\n return {\n path: cy.collection(connectedEles),\n found: cy.collection(found)\n };\n };\n}; // search, spanning trees, etc\n\n\nvar elesfn = {\n breadthFirstSearch: defineSearch({\n bfs: true\n }),\n depthFirstSearch: defineSearch({\n dfs: true\n })\n}; // nice, short mathemathical alias\n\nelesfn.bfs = elesfn.breadthFirstSearch;\nelesfn.dfs = elesfn.depthFirstSearch;\n\nvar dijkstraDefaults = defaults({\n root: null,\n weight: function weight(edge) {\n return 1;\n },\n directed: false\n});\nvar elesfn$1 = {\n dijkstra: function dijkstra(options) {\n if (!plainObject(options)) {\n var args = arguments;\n options = {\n root: args[0],\n weight: args[1],\n directed: args[2]\n };\n }\n\n var _dijkstraDefaults = dijkstraDefaults(options),\n root = _dijkstraDefaults.root,\n weight = _dijkstraDefaults.weight,\n directed = _dijkstraDefaults.directed;\n\n var eles = this;\n var weightFn = weight;\n var source = string(root) ? this.filter(root)[0] : root[0];\n var dist = {};\n var prev = {};\n var knownDist = {};\n\n var _this$byGroup = this.byGroup(),\n nodes = _this$byGroup.nodes,\n edges = _this$byGroup.edges;\n\n edges.unmergeBy(function (ele) {\n return ele.isLoop();\n });\n\n var getDist = function getDist(node) {\n return dist[node.id()];\n };\n\n var setDist = function setDist(node, d) {\n dist[node.id()] = d;\n Q.updateItem(node);\n };\n\n var Q = new Heap(function (a, b) {\n return getDist(a) - getDist(b);\n });\n\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n dist[node.id()] = node.same(source) ? 0 : Infinity;\n Q.push(node);\n }\n\n var distBetween = function distBetween(u, v) {\n var uvs = (directed ? u.edgesTo(v) : u.edgesWith(v)).intersect(edges);\n var smallestDistance = Infinity;\n var smallestEdge;\n\n for (var _i = 0; _i < uvs.length; _i++) {\n var edge = uvs[_i];\n\n var _weight = weightFn(edge);\n\n if (_weight < smallestDistance || !smallestEdge) {\n smallestDistance = _weight;\n smallestEdge = edge;\n }\n }\n\n return {\n edge: smallestEdge,\n dist: smallestDistance\n };\n };\n\n while (Q.size() > 0) {\n var u = Q.pop();\n var smalletsDist = getDist(u);\n var uid = u.id();\n knownDist[uid] = smalletsDist;\n\n if (smalletsDist === Infinity) {\n continue;\n }\n\n var neighbors = u.neighborhood().intersect(nodes);\n\n for (var _i2 = 0; _i2 < neighbors.length; _i2++) {\n var v = neighbors[_i2];\n var vid = v.id();\n var vDist = distBetween(u, v);\n var alt = smalletsDist + vDist.dist;\n\n if (alt < getDist(v)) {\n setDist(v, alt);\n prev[vid] = {\n node: u,\n edge: vDist.edge\n };\n }\n } // for\n\n } // while\n\n\n return {\n distanceTo: function distanceTo(node) {\n var target = string(node) ? nodes.filter(node)[0] : node[0];\n return knownDist[target.id()];\n },\n pathTo: function pathTo(node) {\n var target = string(node) ? nodes.filter(node)[0] : node[0];\n var S = [];\n var u = target;\n var uid = u.id();\n\n if (target.length > 0) {\n S.unshift(target);\n\n while (prev[uid]) {\n var p = prev[uid];\n S.unshift(p.edge);\n S.unshift(p.node);\n u = p.node;\n uid = u.id();\n }\n }\n\n return eles.spawn(S);\n }\n };\n }\n};\n\nvar elesfn$2 = {\n // kruskal's algorithm (finds min spanning tree, assuming undirected graph)\n // implemented from pseudocode from wikipedia\n kruskal: function kruskal(weightFn) {\n weightFn = weightFn || function (edge) {\n return 1;\n };\n\n var _this$byGroup = this.byGroup(),\n nodes = _this$byGroup.nodes,\n edges = _this$byGroup.edges;\n\n var numNodes = nodes.length;\n var forest = new Array(numNodes);\n var A = nodes; // assumes byGroup() creates new collections that can be safely mutated\n\n var findSetIndex = function findSetIndex(ele) {\n for (var i = 0; i < forest.length; i++) {\n var eles = forest[i];\n\n if (eles.has(ele)) {\n return i;\n }\n }\n }; // start with one forest per node\n\n\n for (var i = 0; i < numNodes; i++) {\n forest[i] = this.spawn(nodes[i]);\n }\n\n var S = edges.sort(function (a, b) {\n return weightFn(a) - weightFn(b);\n });\n\n for (var _i = 0; _i < S.length; _i++) {\n var edge = S[_i];\n var u = edge.source()[0];\n var v = edge.target()[0];\n var setUIndex = findSetIndex(u);\n var setVIndex = findSetIndex(v);\n var setU = forest[setUIndex];\n var setV = forest[setVIndex];\n\n if (setUIndex !== setVIndex) {\n A.merge(edge); // combine forests for u and v\n\n setU.merge(setV);\n forest.splice(setVIndex, 1);\n }\n }\n\n return A;\n }\n};\n\nvar aStarDefaults = defaults({\n root: null,\n goal: null,\n weight: function weight(edge) {\n return 1;\n },\n heuristic: function heuristic(edge) {\n return 0;\n },\n directed: false\n});\nvar elesfn$3 = {\n // Implemented from pseudocode from wikipedia\n aStar: function aStar(options) {\n var cy = this.cy();\n\n var _aStarDefaults = aStarDefaults(options),\n root = _aStarDefaults.root,\n goal = _aStarDefaults.goal,\n heuristic = _aStarDefaults.heuristic,\n directed = _aStarDefaults.directed,\n weight = _aStarDefaults.weight;\n\n root = cy.collection(root)[0];\n goal = cy.collection(goal)[0];\n var sid = root.id();\n var tid = goal.id();\n var gScore = {};\n var fScore = {};\n var closedSetIds = {};\n var openSet = new Heap(function (a, b) {\n return fScore[a.id()] - fScore[b.id()];\n });\n var openSetIds = new Set$1();\n var cameFrom = {};\n var cameFromEdge = {};\n\n var addToOpenSet = function addToOpenSet(ele, id) {\n openSet.push(ele);\n openSetIds.add(id);\n };\n\n var cMin, cMinId;\n\n var popFromOpenSet = function popFromOpenSet() {\n cMin = openSet.pop();\n cMinId = cMin.id();\n openSetIds[\"delete\"](cMinId);\n };\n\n var isInOpenSet = function isInOpenSet(id) {\n return openSetIds.has(id);\n };\n\n addToOpenSet(root, sid);\n gScore[sid] = 0;\n fScore[sid] = heuristic(root); // Counter\n\n var steps = 0; // Main loop\n\n while (openSet.size() > 0) {\n popFromOpenSet();\n steps++; // If we've found our goal, then we are done\n\n if (cMinId === tid) {\n var path = [];\n var pathNode = goal;\n var pathNodeId = tid;\n var pathEdge = cameFromEdge[pathNodeId];\n\n for (;;) {\n path.unshift(pathNode);\n\n if (pathEdge != null) {\n path.unshift(pathEdge);\n }\n\n pathNode = cameFrom[pathNodeId];\n\n if (pathNode == null) {\n break;\n }\n\n pathNodeId = pathNode.id();\n pathEdge = cameFromEdge[pathNodeId];\n }\n\n return {\n found: true,\n distance: gScore[cMinId],\n path: this.spawn(path),\n steps: steps\n };\n } // Add cMin to processed nodes\n\n\n closedSetIds[cMinId] = true; // Update scores for neighbors of cMin\n // Take into account if graph is directed or not\n\n var vwEdges = cMin._private.edges;\n\n for (var i = 0; i < vwEdges.length; i++) {\n var e = vwEdges[i]; // edge must be in set of calling eles\n\n if (!this.hasElementWithId(e.id())) {\n continue;\n } // cMin must be the source of edge if directed\n\n\n if (directed && e.data('source') !== cMinId) {\n continue;\n }\n\n var wSrc = e.source();\n var wTgt = e.target();\n var w = wSrc.id() !== cMinId ? wSrc : wTgt;\n var wid = w.id(); // node must be in set of calling eles\n\n if (!this.hasElementWithId(wid)) {\n continue;\n } // if node is in closedSet, ignore it\n\n\n if (closedSetIds[wid]) {\n continue;\n } // New tentative score for node w\n\n\n var tempScore = gScore[cMinId] + weight(e); // Update gScore for node w if:\n // w not present in openSet\n // OR\n // tentative gScore is less than previous value\n // w not in openSet\n\n if (!isInOpenSet(wid)) {\n gScore[wid] = tempScore;\n fScore[wid] = tempScore + heuristic(w);\n addToOpenSet(w, wid);\n cameFrom[wid] = cMin;\n cameFromEdge[wid] = e;\n continue;\n } // w already in openSet, but with greater gScore\n\n\n if (tempScore < gScore[wid]) {\n gScore[wid] = tempScore;\n fScore[wid] = tempScore + heuristic(w);\n cameFrom[wid] = cMin;\n }\n } // End of neighbors update\n\n } // End of main loop\n // If we've reached here, then we've not reached our goal\n\n\n return {\n found: false,\n distance: undefined,\n path: undefined,\n steps: steps\n };\n }\n}; // elesfn\n\nvar floydWarshallDefaults = defaults({\n weight: function weight(edge) {\n return 1;\n },\n directed: false\n});\nvar elesfn$4 = {\n // Implemented from pseudocode from wikipedia\n floydWarshall: function floydWarshall(options) {\n var cy = this.cy();\n\n var _floydWarshallDefault = floydWarshallDefaults(options),\n weight = _floydWarshallDefault.weight,\n directed = _floydWarshallDefault.directed;\n\n var weightFn = weight;\n\n var _this$byGroup = this.byGroup(),\n nodes = _this$byGroup.nodes,\n edges = _this$byGroup.edges;\n\n var N = nodes.length;\n var Nsq = N * N;\n\n var indexOf = function indexOf(node) {\n return nodes.indexOf(node);\n };\n\n var atIndex = function atIndex(i) {\n return nodes[i];\n }; // Initialize distance matrix\n\n\n var dist = new Array(Nsq);\n\n for (var n = 0; n < Nsq; n++) {\n var j = n % N;\n var i = (n - j) / N;\n\n if (i === j) {\n dist[n] = 0;\n } else {\n dist[n] = Infinity;\n }\n } // Initialize matrix used for path reconstruction\n // Initialize distance matrix\n\n\n var next = new Array(Nsq);\n var edgeNext = new Array(Nsq); // Process edges\n\n for (var _i = 0; _i < edges.length; _i++) {\n var edge = edges[_i];\n var src = edge.source()[0];\n var tgt = edge.target()[0];\n\n if (src === tgt) {\n continue;\n } // exclude loops\n\n\n var s = indexOf(src);\n var t = indexOf(tgt);\n var st = s * N + t; // source to target index\n\n var _weight = weightFn(edge); // Check if already process another edge between same 2 nodes\n\n\n if (dist[st] > _weight) {\n dist[st] = _weight;\n next[st] = t;\n edgeNext[st] = edge;\n } // If undirected graph, process 'reversed' edge\n\n\n if (!directed) {\n var ts = t * N + s; // target to source index\n\n if (!directed && dist[ts] > _weight) {\n dist[ts] = _weight;\n next[ts] = s;\n edgeNext[ts] = edge;\n }\n }\n } // Main loop\n\n\n for (var k = 0; k < N; k++) {\n for (var _i2 = 0; _i2 < N; _i2++) {\n var ik = _i2 * N + k;\n\n for (var _j = 0; _j < N; _j++) {\n var ij = _i2 * N + _j;\n var kj = k * N + _j;\n\n if (dist[ik] + dist[kj] < dist[ij]) {\n dist[ij] = dist[ik] + dist[kj];\n next[ij] = next[ik];\n }\n }\n }\n }\n\n var getArgEle = function getArgEle(ele) {\n return (string(ele) ? cy.filter(ele) : ele)[0];\n };\n\n var indexOfArgEle = function indexOfArgEle(ele) {\n return indexOf(getArgEle(ele));\n };\n\n var res = {\n distance: function distance(from, to) {\n var i = indexOfArgEle(from);\n var j = indexOfArgEle(to);\n return dist[i * N + j];\n },\n path: function path(from, to) {\n var i = indexOfArgEle(from);\n var j = indexOfArgEle(to);\n var fromNode = atIndex(i);\n\n if (i === j) {\n return fromNode.collection();\n }\n\n if (next[i * N + j] == null) {\n return cy.collection();\n }\n\n var path = cy.collection();\n var prev = i;\n var edge;\n path.merge(fromNode);\n\n while (i !== j) {\n prev = i;\n i = next[i * N + j];\n edge = edgeNext[prev * N + i];\n path.merge(edge);\n path.merge(atIndex(i));\n }\n\n return path;\n }\n };\n return res;\n } // floydWarshall\n\n}; // elesfn\n\nvar bellmanFordDefaults = defaults({\n weight: function weight(edge) {\n return 1;\n },\n directed: false,\n root: null\n});\nvar elesfn$5 = {\n // Implemented from pseudocode from wikipedia\n bellmanFord: function bellmanFord(options) {\n var _this = this;\n\n var _bellmanFordDefaults = bellmanFordDefaults(options),\n weight = _bellmanFordDefaults.weight,\n directed = _bellmanFordDefaults.directed,\n root = _bellmanFordDefaults.root;\n\n var weightFn = weight;\n var eles = this;\n var cy = this.cy();\n\n var _this$byGroup = this.byGroup(),\n edges = _this$byGroup.edges,\n nodes = _this$byGroup.nodes;\n\n var numNodes = nodes.length;\n var infoMap = new Map$1();\n var hasNegativeWeightCycle = false;\n var negativeWeightCycles = [];\n root = cy.collection(root)[0]; // in case selector passed\n\n edges.unmergeBy(function (edge) {\n return edge.isLoop();\n });\n var numEdges = edges.length;\n\n var getInfo = function getInfo(node) {\n var obj = infoMap.get(node.id());\n\n if (!obj) {\n obj = {};\n infoMap.set(node.id(), obj);\n }\n\n return obj;\n };\n\n var getNodeFromTo = function getNodeFromTo(to) {\n return (string(to) ? cy.$(to) : to)[0];\n };\n\n var distanceTo = function distanceTo(to) {\n return getInfo(getNodeFromTo(to)).dist;\n };\n\n var pathTo = function pathTo(to) {\n var thisStart = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : root;\n var end = getNodeFromTo(to);\n var path = [];\n var node = end;\n\n for (;;) {\n if (node == null) {\n return _this.spawn();\n }\n\n var _getInfo = getInfo(node),\n edge = _getInfo.edge,\n pred = _getInfo.pred;\n\n path.unshift(node[0]);\n\n if (node.same(thisStart) && path.length > 0) {\n break;\n }\n\n if (edge != null) {\n path.unshift(edge);\n }\n\n node = pred;\n }\n\n return eles.spawn(path);\n }; // Initializations { dist, pred, edge }\n\n\n for (var i = 0; i < numNodes; i++) {\n var node = nodes[i];\n var info = getInfo(node);\n\n if (node.same(root)) {\n info.dist = 0;\n } else {\n info.dist = Infinity;\n }\n\n info.pred = null;\n info.edge = null;\n } // Edges relaxation\n\n\n var replacedEdge = false;\n\n var checkForEdgeReplacement = function checkForEdgeReplacement(node1, node2, edge, info1, info2, weight) {\n var dist = info1.dist + weight;\n\n if (dist < info2.dist && !edge.same(info1.edge)) {\n info2.dist = dist;\n info2.pred = node1;\n info2.edge = edge;\n replacedEdge = true;\n }\n };\n\n for (var _i = 1; _i < numNodes; _i++) {\n replacedEdge = false;\n\n for (var e = 0; e < numEdges; e++) {\n var edge = edges[e];\n var src = edge.source();\n var tgt = edge.target();\n\n var _weight = weightFn(edge);\n\n var srcInfo = getInfo(src);\n var tgtInfo = getInfo(tgt);\n checkForEdgeReplacement(src, tgt, edge, srcInfo, tgtInfo, _weight); // If undirected graph, we need to take into account the 'reverse' edge\n\n if (!directed) {\n checkForEdgeReplacement(tgt, src, edge, tgtInfo, srcInfo, _weight);\n }\n }\n\n if (!replacedEdge) {\n break;\n }\n }\n\n if (replacedEdge) {\n // Check for negative weight cycles\n for (var _e = 0; _e < numEdges; _e++) {\n var _edge = edges[_e];\n\n var _src = _edge.source();\n\n var _tgt = _edge.target();\n\n var _weight2 = weightFn(_edge);\n\n var srcDist = getInfo(_src).dist;\n var tgtDist = getInfo(_tgt).dist;\n\n if (srcDist + _weight2 < tgtDist || !directed && tgtDist + _weight2 < srcDist) {\n warn('Graph contains a negative weight cycle for Bellman-Ford');\n hasNegativeWeightCycle = true;\n break;\n }\n }\n }\n\n return {\n distanceTo: distanceTo,\n pathTo: pathTo,\n hasNegativeWeightCycle: hasNegativeWeightCycle,\n negativeWeightCycles: negativeWeightCycles\n };\n } // bellmanFord\n\n}; // elesfn\n\nvar sqrt2 = Math.sqrt(2); // Function which colapses 2 (meta) nodes into one\n// Updates the remaining edge lists\n// Receives as a paramater the edge which causes the collapse\n\nvar collapse = function collapse(edgeIndex, nodeMap, remainingEdges) {\n if (remainingEdges.length === 0) {\n error(\"Karger-Stein must be run on a connected (sub)graph\");\n }\n\n var edgeInfo = remainingEdges[edgeIndex];\n var sourceIn = edgeInfo[1];\n var targetIn = edgeInfo[2];\n var partition1 = nodeMap[sourceIn];\n var partition2 = nodeMap[targetIn];\n var newEdges = remainingEdges; // re-use array\n // Delete all edges between partition1 and partition2\n\n for (var i = newEdges.length - 1; i >= 0; i--) {\n var edge = newEdges[i];\n var src = edge[1];\n var tgt = edge[2];\n\n if (nodeMap[src] === partition1 && nodeMap[tgt] === partition2 || nodeMap[src] === partition2 && nodeMap[tgt] === partition1) {\n newEdges.splice(i, 1);\n }\n } // All edges pointing to partition2 should now point to partition1\n\n\n for (var _i = 0; _i < newEdges.length; _i++) {\n var _edge = newEdges[_i];\n\n if (_edge[1] === partition2) {\n // Check source\n newEdges[_i] = _edge.slice(); // copy\n\n newEdges[_i][1] = partition1;\n } else if (_edge[2] === partition2) {\n // Check target\n newEdges[_i] = _edge.slice(); // copy\n\n newEdges[_i][2] = partition1;\n }\n } // Move all nodes from partition2 to partition1\n\n\n for (var _i2 = 0; _i2 < nodeMap.length; _i2++) {\n if (nodeMap[_i2] === partition2) {\n nodeMap[_i2] = partition1;\n }\n }\n\n return newEdges;\n}; // Contracts a graph until we reach a certain number of meta nodes\n\n\nvar contractUntil = function contractUntil(metaNodeMap, remainingEdges, size, sizeLimit) {\n while (size > sizeLimit) {\n // Choose an edge randomly\n var edgeIndex = Math.floor(Math.random() * remainingEdges.length); // Collapse graph based on edge\n\n remainingEdges = collapse(edgeIndex, metaNodeMap, remainingEdges);\n size--;\n }\n\n return remainingEdges;\n};\n\nvar elesfn$6 = {\n // Computes the minimum cut of an undirected graph\n // Returns the correct answer with high probability\n kargerStein: function kargerStein() {\n var _this = this;\n\n var _this$byGroup = this.byGroup(),\n nodes = _this$byGroup.nodes,\n edges = _this$byGroup.edges;\n\n edges.unmergeBy(function (edge) {\n return edge.isLoop();\n });\n var numNodes = nodes.length;\n var numEdges = edges.length;\n var numIter = Math.ceil(Math.pow(Math.log(numNodes) / Math.LN2, 2));\n var stopSize = Math.floor(numNodes / sqrt2);\n\n if (numNodes < 2) {\n error('At least 2 nodes are required for Karger-Stein algorithm');\n return undefined;\n } // Now store edge destination as indexes\n // Format for each edge (edge index, source node index, target node index)\n\n\n var edgeIndexes = [];\n\n for (var i = 0; i < numEdges; i++) {\n var e = edges[i];\n edgeIndexes.push([i, nodes.indexOf(e.source()), nodes.indexOf(e.target())]);\n } // We will store the best cut found here\n\n\n var minCutSize = Infinity;\n var minCutEdgeIndexes = [];\n var minCutNodeMap = new Array(numNodes); // Initial meta node partition\n\n var metaNodeMap = new Array(numNodes);\n var metaNodeMap2 = new Array(numNodes);\n\n var copyNodesMap = function copyNodesMap(from, to) {\n for (var _i3 = 0; _i3 < numNodes; _i3++) {\n to[_i3] = from[_i3];\n }\n }; // Main loop\n\n\n for (var iter = 0; iter <= numIter; iter++) {\n // Reset meta node partition\n for (var _i4 = 0; _i4 < numNodes; _i4++) {\n metaNodeMap[_i4] = _i4;\n } // Contract until stop point (stopSize nodes)\n\n\n var edgesState = contractUntil(metaNodeMap, edgeIndexes.slice(), numNodes, stopSize);\n var edgesState2 = edgesState.slice(); // copy\n // Create a copy of the colapsed nodes state\n\n copyNodesMap(metaNodeMap, metaNodeMap2); // Run 2 iterations starting in the stop state\n\n var res1 = contractUntil(metaNodeMap, edgesState, stopSize, 2);\n var res2 = contractUntil(metaNodeMap2, edgesState2, stopSize, 2); // Is any of the 2 results the best cut so far?\n\n if (res1.length <= res2.length && res1.length < minCutSize) {\n minCutSize = res1.length;\n minCutEdgeIndexes = res1;\n copyNodesMap(metaNodeMap, minCutNodeMap);\n } else if (res2.length <= res1.length && res2.length < minCutSize) {\n minCutSize = res2.length;\n minCutEdgeIndexes = res2;\n copyNodesMap(metaNodeMap2, minCutNodeMap);\n }\n } // end of main loop\n // Construct result\n\n\n var cut = this.spawn(minCutEdgeIndexes.map(function (e) {\n return edges[e[0]];\n }));\n var partition1 = this.spawn();\n var partition2 = this.spawn(); // traverse metaNodeMap for best cut\n\n var witnessNodePartition = minCutNodeMap[0];\n\n for (var _i5 = 0; _i5 < minCutNodeMap.length; _i5++) {\n var partitionId = minCutNodeMap[_i5];\n var node = nodes[_i5];\n\n if (partitionId === witnessNodePartition) {\n partition1.merge(node);\n } else {\n partition2.merge(node);\n }\n } // construct components corresponding to each disjoint subset of nodes\n\n\n var constructComponent = function constructComponent(subset) {\n var component = _this.spawn();\n\n subset.forEach(function (node) {\n component.merge(node);\n node.connectedEdges().forEach(function (edge) {\n // ensure edge is within calling collection and edge is not in cut\n if (_this.contains(edge) && !cut.contains(edge)) {\n component.merge(edge);\n }\n });\n });\n return component;\n };\n\n var components = [constructComponent(partition1), constructComponent(partition2)];\n var ret = {\n cut: cut,\n components: components,\n // n.b. partitions are included to be compatible with the old api spec\n // (could be removed in a future major version)\n partition1: partition1,\n partition2: partition2\n };\n return ret;\n }\n}; // elesfn\n\nvar copyPosition = function copyPosition(p) {\n return {\n x: p.x,\n y: p.y\n };\n};\nvar modelToRenderedPosition = function modelToRenderedPosition(p, zoom, pan) {\n return {\n x: p.x * zoom + pan.x,\n y: p.y * zoom + pan.y\n };\n};\nvar renderedToModelPosition = function renderedToModelPosition(p, zoom, pan) {\n return {\n x: (p.x - pan.x) / zoom,\n y: (p.y - pan.y) / zoom\n };\n};\nvar array2point = function array2point(arr) {\n return {\n x: arr[0],\n y: arr[1]\n };\n};\nvar min = function min(arr) {\n var begin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : arr.length;\n var min = Infinity;\n\n for (var i = begin; i < end; i++) {\n var val = arr[i];\n\n if (isFinite(val)) {\n min = Math.min(val, min);\n }\n }\n\n return min;\n};\nvar max = function max(arr) {\n var begin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : arr.length;\n var max = -Infinity;\n\n for (var i = begin; i < end; i++) {\n var val = arr[i];\n\n if (isFinite(val)) {\n max = Math.max(val, max);\n }\n }\n\n return max;\n};\nvar mean = function mean(arr) {\n var begin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : arr.length;\n var total = 0;\n var n = 0;\n\n for (var i = begin; i < end; i++) {\n var val = arr[i];\n\n if (isFinite(val)) {\n total += val;\n n++;\n }\n }\n\n return total / n;\n};\nvar median = function median(arr) {\n var begin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : arr.length;\n var copy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n var sort = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;\n var includeHoles = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;\n\n if (copy) {\n arr = arr.slice(begin, end);\n } else {\n if (end < arr.length) {\n arr.splice(end, arr.length - end);\n }\n\n if (begin > 0) {\n arr.splice(0, begin);\n }\n } // all non finite (e.g. Infinity, NaN) elements must be -Infinity so they go to the start\n\n\n var off = 0; // offset from non-finite values\n\n for (var i = arr.length - 1; i >= 0; i--) {\n var v = arr[i];\n\n if (includeHoles) {\n if (!isFinite(v)) {\n arr[i] = -Infinity;\n off++;\n }\n } else {\n // just remove it if we don't want to consider holes\n arr.splice(i, 1);\n }\n }\n\n if (sort) {\n arr.sort(function (a, b) {\n return a - b;\n }); // requires copy = true if you don't want to change the orig\n }\n\n var len = arr.length;\n var mid = Math.floor(len / 2);\n\n if (len % 2 !== 0) {\n return arr[mid + 1 + off];\n } else {\n return (arr[mid - 1 + off] + arr[mid + off]) / 2;\n }\n};\nvar deg2rad = function deg2rad(deg) {\n return Math.PI * deg / 180;\n};\nvar getAngleFromDisp = function getAngleFromDisp(dispX, dispY) {\n return Math.atan2(dispY, dispX) - Math.PI / 2;\n};\nvar log2 = Math.log2 || function (n) {\n return Math.log(n) / Math.log(2);\n};\nvar signum = function signum(x) {\n if (x > 0) {\n return 1;\n } else if (x < 0) {\n return -1;\n } else {\n return 0;\n }\n};\nvar dist = function dist(p1, p2) {\n return Math.sqrt(sqdist(p1, p2));\n};\nvar sqdist = function sqdist(p1, p2) {\n var dx = p2.x - p1.x;\n var dy = p2.y - p1.y;\n return dx * dx + dy * dy;\n};\nvar inPlaceSumNormalize = function inPlaceSumNormalize(v) {\n var length = v.length; // First, get sum of all elements\n\n var total = 0;\n\n for (var i = 0; i < length; i++) {\n total += v[i];\n } // Now, divide each by the sum of all elements\n\n\n for (var _i = 0; _i < length; _i++) {\n v[_i] = v[_i] / total;\n }\n\n return v;\n};\n\nvar qbezierAt = function qbezierAt(p0, p1, p2, t) {\n return (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2;\n};\nvar qbezierPtAt = function qbezierPtAt(p0, p1, p2, t) {\n return {\n x: qbezierAt(p0.x, p1.x, p2.x, t),\n y: qbezierAt(p0.y, p1.y, p2.y, t)\n };\n};\nvar lineAt = function lineAt(p0, p1, t, d) {\n var vec = {\n x: p1.x - p0.x,\n y: p1.y - p0.y\n };\n var vecDist = dist(p0, p1);\n var normVec = {\n x: vec.x / vecDist,\n y: vec.y / vecDist\n };\n t = t == null ? 0 : t;\n d = d != null ? d : t * vecDist;\n return {\n x: p0.x + normVec.x * d,\n y: p0.y + normVec.y * d\n };\n};\nvar bound = function bound(min, val, max) {\n return Math.max(min, Math.min(max, val));\n}; // makes a full bb (x1, y1, x2, y2, w, h) from implicit params\n\nvar makeBoundingBox = function makeBoundingBox(bb) {\n if (bb == null) {\n return {\n x1: Infinity,\n y1: Infinity,\n x2: -Infinity,\n y2: -Infinity,\n w: 0,\n h: 0\n };\n } else if (bb.x1 != null && bb.y1 != null) {\n if (bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1) {\n return {\n x1: bb.x1,\n y1: bb.y1,\n x2: bb.x2,\n y2: bb.y2,\n w: bb.x2 - bb.x1,\n h: bb.y2 - bb.y1\n };\n } else if (bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0) {\n return {\n x1: bb.x1,\n y1: bb.y1,\n x2: bb.x1 + bb.w,\n y2: bb.y1 + bb.h,\n w: bb.w,\n h: bb.h\n };\n }\n }\n};\nvar copyBoundingBox = function copyBoundingBox(bb) {\n return {\n x1: bb.x1,\n x2: bb.x2,\n w: bb.w,\n y1: bb.y1,\n y2: bb.y2,\n h: bb.h\n };\n};\nvar clearBoundingBox = function clearBoundingBox(bb) {\n bb.x1 = Infinity;\n bb.y1 = Infinity;\n bb.x2 = -Infinity;\n bb.y2 = -Infinity;\n bb.w = 0;\n bb.h = 0;\n};\nvar updateBoundingBox = function updateBoundingBox(bb1, bb2) {\n // update bb1 with bb2 bounds\n bb1.x1 = Math.min(bb1.x1, bb2.x1);\n bb1.x2 = Math.max(bb1.x2, bb2.x2);\n bb1.w = bb1.x2 - bb1.x1;\n bb1.y1 = Math.min(bb1.y1, bb2.y1);\n bb1.y2 = Math.max(bb1.y2, bb2.y2);\n bb1.h = bb1.y2 - bb1.y1;\n};\nvar expandBoundingBoxByPoint = function expandBoundingBoxByPoint(bb, x, y) {\n bb.x1 = Math.min(bb.x1, x);\n bb.x2 = Math.max(bb.x2, x);\n bb.w = bb.x2 - bb.x1;\n bb.y1 = Math.min(bb.y1, y);\n bb.y2 = Math.max(bb.y2, y);\n bb.h = bb.y2 - bb.y1;\n};\nvar expandBoundingBox = function expandBoundingBox(bb) {\n var padding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n bb.x1 -= padding;\n bb.x2 += padding;\n bb.y1 -= padding;\n bb.y2 += padding;\n bb.w = bb.x2 - bb.x1;\n bb.h = bb.y2 - bb.y1;\n return bb;\n};\nvar expandBoundingBoxSides = function expandBoundingBoxSides(bb) {\n var padding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0];\n var top, right, bottom, left;\n\n if (padding.length === 1) {\n top = right = bottom = left = padding[0];\n } else if (padding.length === 2) {\n top = bottom = padding[0];\n left = right = padding[1];\n } else if (padding.length === 4) {\n var _padding = _slicedToArray(padding, 4);\n\n top = _padding[0];\n right = _padding[1];\n bottom = _padding[2];\n left = _padding[3];\n }\n\n bb.x1 -= left;\n bb.x2 += right;\n bb.y1 -= top;\n bb.y2 += bottom;\n bb.w = bb.x2 - bb.x1;\n bb.h = bb.y2 - bb.y1;\n return bb;\n};\n\nvar assignBoundingBox = function assignBoundingBox(bb1, bb2) {\n bb1.x1 = bb2.x1;\n bb1.y1 = bb2.y1;\n bb1.x2 = bb2.x2;\n bb1.y2 = bb2.y2;\n bb1.w = bb1.x2 - bb1.x1;\n bb1.h = bb1.y2 - bb1.y1;\n};\nvar assignShiftToBoundingBox = function assignShiftToBoundingBox(bb, delta) {\n bb.x1 += delta.x;\n bb.x2 += delta.x;\n bb.y1 += delta.y;\n bb.y2 += delta.y;\n};\nvar boundingBoxesIntersect = function boundingBoxesIntersect(bb1, bb2) {\n // case: one bb to right of other\n if (bb1.x1 > bb2.x2) {\n return false;\n }\n\n if (bb2.x1 > bb1.x2) {\n return false;\n } // case: one bb to left of other\n\n\n if (bb1.x2 < bb2.x1) {\n return false;\n }\n\n if (bb2.x2 < bb1.x1) {\n return false;\n } // case: one bb above other\n\n\n if (bb1.y2 < bb2.y1) {\n return false;\n }\n\n if (bb2.y2 < bb1.y1) {\n return false;\n } // case: one bb below other\n\n\n if (bb1.y1 > bb2.y2) {\n return false;\n }\n\n if (bb2.y1 > bb1.y2) {\n return false;\n } // otherwise, must have some overlap\n\n\n return true;\n};\nvar inBoundingBox = function inBoundingBox(bb, x, y) {\n return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2;\n};\nvar pointInBoundingBox = function pointInBoundingBox(bb, pt) {\n return inBoundingBox(bb, pt.x, pt.y);\n};\nvar boundingBoxInBoundingBox = function boundingBoxInBoundingBox(bb1, bb2) {\n return inBoundingBox(bb1, bb2.x1, bb2.y1) && inBoundingBox(bb1, bb2.x2, bb2.y2);\n};\nvar roundRectangleIntersectLine = function roundRectangleIntersectLine(x, y, nodeX, nodeY, width, height, padding) {\n var cornerRadius = getRoundRectangleRadius(width, height);\n var halfWidth = width / 2;\n var halfHeight = height / 2; // Check intersections with straight line segments\n\n var straightLineIntersections; // Top segment, left to right\n\n {\n var topStartX = nodeX - halfWidth + cornerRadius - padding;\n var topStartY = nodeY - halfHeight - padding;\n var topEndX = nodeX + halfWidth - cornerRadius + padding;\n var topEndY = topStartY;\n straightLineIntersections = finiteLinesIntersect(x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n } // Right segment, top to bottom\n\n {\n var rightStartX = nodeX + halfWidth + padding;\n var rightStartY = nodeY - halfHeight + cornerRadius - padding;\n var rightEndX = rightStartX;\n var rightEndY = nodeY + halfHeight - cornerRadius + padding;\n straightLineIntersections = finiteLinesIntersect(x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n } // Bottom segment, left to right\n\n {\n var bottomStartX = nodeX - halfWidth + cornerRadius - padding;\n var bottomStartY = nodeY + halfHeight + padding;\n var bottomEndX = nodeX + halfWidth - cornerRadius + padding;\n var bottomEndY = bottomStartY;\n straightLineIntersections = finiteLinesIntersect(x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n } // Left segment, top to bottom\n\n {\n var leftStartX = nodeX - halfWidth - padding;\n var leftStartY = nodeY - halfHeight + cornerRadius - padding;\n var leftEndX = leftStartX;\n var leftEndY = nodeY + halfHeight - cornerRadius + padding;\n straightLineIntersections = finiteLinesIntersect(x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n } // Check intersections with arc segments\n\n var arcIntersections; // Top Left\n\n {\n var topLeftCenterX = nodeX - halfWidth + cornerRadius;\n var topLeftCenterY = nodeY - halfHeight + cornerRadius;\n arcIntersections = intersectLineCircle(x, y, nodeX, nodeY, topLeftCenterX, topLeftCenterY, cornerRadius + padding); // Ensure the intersection is on the desired quarter of the circle\n\n if (arcIntersections.length > 0 && arcIntersections[0] <= topLeftCenterX && arcIntersections[1] <= topLeftCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n } // Top Right\n\n {\n var topRightCenterX = nodeX + halfWidth - cornerRadius;\n var topRightCenterY = nodeY - halfHeight + cornerRadius;\n arcIntersections = intersectLineCircle(x, y, nodeX, nodeY, topRightCenterX, topRightCenterY, cornerRadius + padding); // Ensure the intersection is on the desired quarter of the circle\n\n if (arcIntersections.length > 0 && arcIntersections[0] >= topRightCenterX && arcIntersections[1] <= topRightCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n } // Bottom Right\n\n {\n var bottomRightCenterX = nodeX + halfWidth - cornerRadius;\n var bottomRightCenterY = nodeY + halfHeight - cornerRadius;\n arcIntersections = intersectLineCircle(x, y, nodeX, nodeY, bottomRightCenterX, bottomRightCenterY, cornerRadius + padding); // Ensure the intersection is on the desired quarter of the circle\n\n if (arcIntersections.length > 0 && arcIntersections[0] >= bottomRightCenterX && arcIntersections[1] >= bottomRightCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n } // Bottom Left\n\n {\n var bottomLeftCenterX = nodeX - halfWidth + cornerRadius;\n var bottomLeftCenterY = nodeY + halfHeight - cornerRadius;\n arcIntersections = intersectLineCircle(x, y, nodeX, nodeY, bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding); // Ensure the intersection is on the desired quarter of the circle\n\n if (arcIntersections.length > 0 && arcIntersections[0] <= bottomLeftCenterX && arcIntersections[1] >= bottomLeftCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n }\n return []; // if nothing\n};\nvar inLineVicinity = function inLineVicinity(x, y, lx1, ly1, lx2, ly2, tolerance) {\n var t = tolerance;\n var x1 = Math.min(lx1, lx2);\n var x2 = Math.max(lx1, lx2);\n var y1 = Math.min(ly1, ly2);\n var y2 = Math.max(ly1, ly2);\n return x1 - t <= x && x <= x2 + t && y1 - t <= y && y <= y2 + t;\n};\nvar inBezierVicinity = function inBezierVicinity(x, y, x1, y1, x2, y2, x3, y3, tolerance) {\n var bb = {\n x1: Math.min(x1, x3, x2) - tolerance,\n x2: Math.max(x1, x3, x2) + tolerance,\n y1: Math.min(y1, y3, y2) - tolerance,\n y2: Math.max(y1, y3, y2) + tolerance\n }; // if outside the rough bounding box for the bezier, then it can't be a hit\n\n if (x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2) {\n // console.log('bezier out of rough bb')\n return false;\n } else {\n // console.log('do more expensive check');\n return true;\n }\n};\nvar solveQuadratic = function solveQuadratic(a, b, c, val) {\n c -= val;\n var r = b * b - 4 * a * c;\n\n if (r < 0) {\n return [];\n }\n\n var sqrtR = Math.sqrt(r);\n var denom = 2 * a;\n var root1 = (-b + sqrtR) / denom;\n var root2 = (-b - sqrtR) / denom;\n return [root1, root2];\n};\nvar solveCubic = function solveCubic(a, b, c, d, result) {\n // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where\n // r is the real component, i is the imaginary component\n // An implementation of the Cardano method from the year 1545\n // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots\n var epsilon = 0.00001; // avoid division by zero while keeping the overall expression close in value\n\n if (a === 0) {\n a = epsilon;\n }\n\n b /= a;\n c /= a;\n d /= a;\n var discriminant, q, r, dum1, s, t, term1, r13;\n q = (3.0 * c - b * b) / 9.0;\n r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b));\n r /= 54.0;\n discriminant = q * q * q + r * r;\n result[1] = 0;\n term1 = b / 3.0;\n\n if (discriminant > 0) {\n s = r + Math.sqrt(discriminant);\n s = s < 0 ? -Math.pow(-s, 1.0 / 3.0) : Math.pow(s, 1.0 / 3.0);\n t = r - Math.sqrt(discriminant);\n t = t < 0 ? -Math.pow(-t, 1.0 / 3.0) : Math.pow(t, 1.0 / 3.0);\n result[0] = -term1 + s + t;\n term1 += (s + t) / 2.0;\n result[4] = result[2] = -term1;\n term1 = Math.sqrt(3.0) * (-t + s) / 2;\n result[3] = term1;\n result[5] = -term1;\n return;\n }\n\n result[5] = result[3] = 0;\n\n if (discriminant === 0) {\n r13 = r < 0 ? -Math.pow(-r, 1.0 / 3.0) : Math.pow(r, 1.0 / 3.0);\n result[0] = -term1 + 2.0 * r13;\n result[4] = result[2] = -(r13 + term1);\n return;\n }\n\n q = -q;\n dum1 = q * q * q;\n dum1 = Math.acos(r / Math.sqrt(dum1));\n r13 = 2.0 * Math.sqrt(q);\n result[0] = -term1 + r13 * Math.cos(dum1 / 3.0);\n result[2] = -term1 + r13 * Math.cos((dum1 + 2.0 * Math.PI) / 3.0);\n result[4] = -term1 + r13 * Math.cos((dum1 + 4.0 * Math.PI) / 3.0);\n return;\n};\nvar sqdistToQuadraticBezier = function sqdistToQuadraticBezier(x, y, x1, y1, x2, y2, x3, y3) {\n // Find minimum distance by using the minimum of the distance\n // function between the given point and the curve\n // This gives the coefficients of the resulting cubic equation\n // whose roots tell us where a possible minimum is\n // (Coefficients are divided by 4)\n var a = 1.0 * x1 * x1 - 4 * x1 * x2 + 2 * x1 * x3 + 4 * x2 * x2 - 4 * x2 * x3 + x3 * x3 + y1 * y1 - 4 * y1 * y2 + 2 * y1 * y3 + 4 * y2 * y2 - 4 * y2 * y3 + y3 * y3;\n var b = 1.0 * 9 * x1 * x2 - 3 * x1 * x1 - 3 * x1 * x3 - 6 * x2 * x2 + 3 * x2 * x3 + 9 * y1 * y2 - 3 * y1 * y1 - 3 * y1 * y3 - 6 * y2 * y2 + 3 * y2 * y3;\n var c = 1.0 * 3 * x1 * x1 - 6 * x1 * x2 + x1 * x3 - x1 * x + 2 * x2 * x2 + 2 * x2 * x - x3 * x + 3 * y1 * y1 - 6 * y1 * y2 + y1 * y3 - y1 * y + 2 * y2 * y2 + 2 * y2 * y - y3 * y;\n var d = 1.0 * x1 * x2 - x1 * x1 + x1 * x - x2 * x + y1 * y2 - y1 * y1 + y1 * y - y2 * y; // debug(\"coefficients: \" + a / a + \", \" + b / a + \", \" + c / a + \", \" + d / a);\n\n var roots = []; // Use the cubic solving algorithm\n\n solveCubic(a, b, c, d, roots);\n var zeroThreshold = 0.0000001;\n var params = [];\n\n for (var index = 0; index < 6; index += 2) {\n if (Math.abs(roots[index + 1]) < zeroThreshold && roots[index] >= 0 && roots[index] <= 1.0) {\n params.push(roots[index]);\n }\n }\n\n params.push(1.0);\n params.push(0.0);\n var minDistanceSquared = -1;\n var curX, curY, distSquared;\n\n for (var i = 0; i < params.length; i++) {\n curX = Math.pow(1.0 - params[i], 2.0) * x1 + 2.0 * (1 - params[i]) * params[i] * x2 + params[i] * params[i] * x3;\n curY = Math.pow(1 - params[i], 2.0) * y1 + 2 * (1.0 - params[i]) * params[i] * y2 + params[i] * params[i] * y3;\n distSquared = Math.pow(curX - x, 2) + Math.pow(curY - y, 2); // debug('distance for param ' + params[i] + \": \" + Math.sqrt(distSquared));\n\n if (minDistanceSquared >= 0) {\n if (distSquared < minDistanceSquared) {\n minDistanceSquared = distSquared;\n }\n } else {\n minDistanceSquared = distSquared;\n }\n }\n\n return minDistanceSquared;\n};\nvar sqdistToFiniteLine = function sqdistToFiniteLine(x, y, x1, y1, x2, y2) {\n var offset = [x - x1, y - y1];\n var line = [x2 - x1, y2 - y1];\n var lineSq = line[0] * line[0] + line[1] * line[1];\n var hypSq = offset[0] * offset[0] + offset[1] * offset[1];\n var dotProduct = offset[0] * line[0] + offset[1] * line[1];\n var adjSq = dotProduct * dotProduct / lineSq;\n\n if (dotProduct < 0) {\n return hypSq;\n }\n\n if (adjSq > lineSq) {\n return (x - x2) * (x - x2) + (y - y2) * (y - y2);\n }\n\n return hypSq - adjSq;\n};\nvar pointInsidePolygonPoints = function pointInsidePolygonPoints(x, y, points) {\n var x1, y1, x2, y2;\n var y3; // Intersect with vertical line through (x, y)\n\n var up = 0; // let down = 0;\n\n for (var i = 0; i < points.length / 2; i++) {\n x1 = points[i * 2];\n y1 = points[i * 2 + 1];\n\n if (i + 1 < points.length / 2) {\n x2 = points[(i + 1) * 2];\n y2 = points[(i + 1) * 2 + 1];\n } else {\n x2 = points[(i + 1 - points.length / 2) * 2];\n y2 = points[(i + 1 - points.length / 2) * 2 + 1];\n }\n\n if (x1 == x && x2 == x) ; else if (x1 >= x && x >= x2 || x1 <= x && x <= x2) {\n y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1;\n\n if (y3 > y) {\n up++;\n } // if( y3 < y ){\n // down++;\n // }\n\n } else {\n continue;\n }\n }\n\n if (up % 2 === 0) {\n return false;\n } else {\n return true;\n }\n};\nvar pointInsidePolygon = function pointInsidePolygon(x, y, basePoints, centerX, centerY, width, height, direction, padding) {\n var transformedPoints = new Array(basePoints.length); // Gives negative angle\n\n var angle;\n\n if (direction[0] != null) {\n angle = Math.atan(direction[1] / direction[0]);\n\n if (direction[0] < 0) {\n angle = angle + Math.PI / 2;\n } else {\n angle = -angle - Math.PI / 2;\n }\n } else {\n angle = direction;\n }\n\n var cos = Math.cos(-angle);\n var sin = Math.sin(-angle); // console.log(\"base: \" + basePoints);\n\n for (var i = 0; i < transformedPoints.length / 2; i++) {\n transformedPoints[i * 2] = width / 2 * (basePoints[i * 2] * cos - basePoints[i * 2 + 1] * sin);\n transformedPoints[i * 2 + 1] = height / 2 * (basePoints[i * 2 + 1] * cos + basePoints[i * 2] * sin);\n transformedPoints[i * 2] += centerX;\n transformedPoints[i * 2 + 1] += centerY;\n }\n\n var points;\n\n if (padding > 0) {\n var expandedLineSet = expandPolygon(transformedPoints, -padding);\n points = joinLines(expandedLineSet);\n } else {\n points = transformedPoints;\n }\n\n return pointInsidePolygonPoints(x, y, points);\n};\nvar pointInsideRoundPolygon = function pointInsideRoundPolygon(x, y, basePoints, centerX, centerY, width, height) {\n var cutPolygonPoints = new Array(basePoints.length);\n var halfW = width / 2;\n var halfH = height / 2;\n var cornerRadius = getRoundPolygonRadius(width, height);\n var squaredCornerRadius = cornerRadius * cornerRadius;\n\n for (var i = 0; i < basePoints.length / 4; i++) {\n var sourceUv = void 0,\n destUv = void 0;\n\n if (i === 0) {\n sourceUv = basePoints.length - 2;\n } else {\n sourceUv = i * 4 - 2;\n }\n\n destUv = i * 4 + 2;\n var px = centerX + halfW * basePoints[i * 4];\n var py = centerY + halfH * basePoints[i * 4 + 1];\n var cosTheta = -basePoints[sourceUv] * basePoints[destUv] - basePoints[sourceUv + 1] * basePoints[destUv + 1];\n var offset = cornerRadius / Math.tan(Math.acos(cosTheta) / 2);\n var cp0x = px - offset * basePoints[sourceUv];\n var cp0y = py - offset * basePoints[sourceUv + 1];\n var cp1x = px + offset * basePoints[destUv];\n var cp1y = py + offset * basePoints[destUv + 1];\n cutPolygonPoints[i * 4] = cp0x;\n cutPolygonPoints[i * 4 + 1] = cp0y;\n cutPolygonPoints[i * 4 + 2] = cp1x;\n cutPolygonPoints[i * 4 + 3] = cp1y;\n var orthx = basePoints[sourceUv + 1];\n var orthy = -basePoints[sourceUv];\n var cosAlpha = orthx * basePoints[destUv] + orthy * basePoints[destUv + 1];\n\n if (cosAlpha < 0) {\n orthx *= -1;\n orthy *= -1;\n }\n\n var cx = cp0x + orthx * cornerRadius;\n var cy = cp0y + orthy * cornerRadius;\n var squaredDistance = Math.pow(cx - x, 2) + Math.pow(cy - y, 2);\n\n if (squaredDistance <= squaredCornerRadius) {\n return true;\n }\n }\n\n return pointInsidePolygonPoints(x, y, cutPolygonPoints);\n};\nvar joinLines = function joinLines(lineSet) {\n var vertices = new Array(lineSet.length / 2);\n var currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY;\n var nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY;\n\n for (var i = 0; i < lineSet.length / 4; i++) {\n currentLineStartX = lineSet[i * 4];\n currentLineStartY = lineSet[i * 4 + 1];\n currentLineEndX = lineSet[i * 4 + 2];\n currentLineEndY = lineSet[i * 4 + 3];\n\n if (i < lineSet.length / 4 - 1) {\n nextLineStartX = lineSet[(i + 1) * 4];\n nextLineStartY = lineSet[(i + 1) * 4 + 1];\n nextLineEndX = lineSet[(i + 1) * 4 + 2];\n nextLineEndY = lineSet[(i + 1) * 4 + 3];\n } else {\n nextLineStartX = lineSet[0];\n nextLineStartY = lineSet[1];\n nextLineEndX = lineSet[2];\n nextLineEndY = lineSet[3];\n }\n\n var intersection = finiteLinesIntersect(currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY, nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY, true);\n vertices[i * 2] = intersection[0];\n vertices[i * 2 + 1] = intersection[1];\n }\n\n return vertices;\n};\nvar expandPolygon = function expandPolygon(points, pad) {\n var expandedLineSet = new Array(points.length * 2);\n var currentPointX, currentPointY, nextPointX, nextPointY;\n\n for (var i = 0; i < points.length / 2; i++) {\n currentPointX = points[i * 2];\n currentPointY = points[i * 2 + 1];\n\n if (i < points.length / 2 - 1) {\n nextPointX = points[(i + 1) * 2];\n nextPointY = points[(i + 1) * 2 + 1];\n } else {\n nextPointX = points[0];\n nextPointY = points[1];\n } // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY]\n // Assume CCW polygon winding\n\n\n var offsetX = nextPointY - currentPointY;\n var offsetY = -(nextPointX - currentPointX); // Normalize\n\n var offsetLength = Math.sqrt(offsetX * offsetX + offsetY * offsetY);\n var normalizedOffsetX = offsetX / offsetLength;\n var normalizedOffsetY = offsetY / offsetLength;\n expandedLineSet[i * 4] = currentPointX + normalizedOffsetX * pad;\n expandedLineSet[i * 4 + 1] = currentPointY + normalizedOffsetY * pad;\n expandedLineSet[i * 4 + 2] = nextPointX + normalizedOffsetX * pad;\n expandedLineSet[i * 4 + 3] = nextPointY + normalizedOffsetY * pad;\n }\n\n return expandedLineSet;\n};\nvar intersectLineEllipse = function intersectLineEllipse(x, y, centerX, centerY, ellipseWradius, ellipseHradius) {\n var dispX = centerX - x;\n var dispY = centerY - y;\n dispX /= ellipseWradius;\n dispY /= ellipseHradius;\n var len = Math.sqrt(dispX * dispX + dispY * dispY);\n var newLength = len - 1;\n\n if (newLength < 0) {\n return [];\n }\n\n var lenProportion = newLength / len;\n return [(centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y];\n};\nvar checkInEllipse = function checkInEllipse(x, y, width, height, centerX, centerY, padding) {\n x -= centerX;\n y -= centerY;\n x /= width / 2 + padding;\n y /= height / 2 + padding;\n return x * x + y * y <= 1;\n}; // Returns intersections of increasing distance from line's start point\n\nvar intersectLineCircle = function intersectLineCircle(x1, y1, x2, y2, centerX, centerY, radius) {\n // Calculate d, direction vector of line\n var d = [x2 - x1, y2 - y1]; // Direction vector of line\n\n var f = [x1 - centerX, y1 - centerY];\n var a = d[0] * d[0] + d[1] * d[1];\n var b = 2 * (f[0] * d[0] + f[1] * d[1]);\n var c = f[0] * f[0] + f[1] * f[1] - radius * radius;\n var discriminant = b * b - 4 * a * c;\n\n if (discriminant < 0) {\n return [];\n }\n\n var t1 = (-b + Math.sqrt(discriminant)) / (2 * a);\n var t2 = (-b - Math.sqrt(discriminant)) / (2 * a);\n var tMin = Math.min(t1, t2);\n var tMax = Math.max(t1, t2);\n var inRangeParams = [];\n\n if (tMin >= 0 && tMin <= 1) {\n inRangeParams.push(tMin);\n }\n\n if (tMax >= 0 && tMax <= 1) {\n inRangeParams.push(tMax);\n }\n\n if (inRangeParams.length === 0) {\n return [];\n }\n\n var nearIntersectionX = inRangeParams[0] * d[0] + x1;\n var nearIntersectionY = inRangeParams[0] * d[1] + y1;\n\n if (inRangeParams.length > 1) {\n if (inRangeParams[0] == inRangeParams[1]) {\n return [nearIntersectionX, nearIntersectionY];\n } else {\n var farIntersectionX = inRangeParams[1] * d[0] + x1;\n var farIntersectionY = inRangeParams[1] * d[1] + y1;\n return [nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY];\n }\n } else {\n return [nearIntersectionX, nearIntersectionY];\n }\n};\nvar midOfThree = function midOfThree(a, b, c) {\n if (b <= a && a <= c || c <= a && a <= b) {\n return a;\n } else if (a <= b && b <= c || c <= b && b <= a) {\n return b;\n } else {\n return c;\n }\n}; // (x1,y1)=>(x2,y2) intersect with (x3,y3)=>(x4,y4)\n\nvar finiteLinesIntersect = function finiteLinesIntersect(x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines) {\n var dx13 = x1 - x3;\n var dx21 = x2 - x1;\n var dx43 = x4 - x3;\n var dy13 = y1 - y3;\n var dy21 = y2 - y1;\n var dy43 = y4 - y3;\n var ua_t = dx43 * dy13 - dy43 * dx13;\n var ub_t = dx21 * dy13 - dy21 * dx13;\n var u_b = dy43 * dx21 - dx43 * dy21;\n\n if (u_b !== 0) {\n var ua = ua_t / u_b;\n var ub = ub_t / u_b;\n var flptThreshold = 0.001;\n\n var _min = 0 - flptThreshold;\n\n var _max = 1 + flptThreshold;\n\n if (_min <= ua && ua <= _max && _min <= ub && ub <= _max) {\n return [x1 + ua * dx21, y1 + ua * dy21];\n } else {\n if (!infiniteLines) {\n return [];\n } else {\n return [x1 + ua * dx21, y1 + ua * dy21];\n }\n }\n } else {\n if (ua_t === 0 || ub_t === 0) {\n // Parallel, coincident lines. Check if overlap\n // Check endpoint of second line\n if (midOfThree(x1, x2, x4) === x4) {\n return [x4, y4];\n } // Check start point of second line\n\n\n if (midOfThree(x1, x2, x3) === x3) {\n return [x3, y3];\n } // Endpoint of first line\n\n\n if (midOfThree(x3, x4, x2) === x2) {\n return [x2, y2];\n }\n\n return [];\n } else {\n // Parallel, non-coincident\n return [];\n }\n }\n}; // math.polygonIntersectLine( x, y, basePoints, centerX, centerY, width, height, padding )\n// intersect a node polygon (pts transformed)\n//\n// math.polygonIntersectLine( x, y, basePoints, centerX, centerY )\n// intersect the points (no transform)\n\nvar polygonIntersectLine = function polygonIntersectLine(x, y, basePoints, centerX, centerY, width, height, padding) {\n var intersections = [];\n var intersection;\n var transformedPoints = new Array(basePoints.length);\n var doTransform = true;\n\n if (width == null) {\n doTransform = false;\n }\n\n var points;\n\n if (doTransform) {\n for (var i = 0; i < transformedPoints.length / 2; i++) {\n transformedPoints[i * 2] = basePoints[i * 2] * width + centerX;\n transformedPoints[i * 2 + 1] = basePoints[i * 2 + 1] * height + centerY;\n }\n\n if (padding > 0) {\n var expandedLineSet = expandPolygon(transformedPoints, -padding);\n points = joinLines(expandedLineSet);\n } else {\n points = transformedPoints;\n }\n } else {\n points = basePoints;\n }\n\n var currentX, currentY, nextX, nextY;\n\n for (var _i2 = 0; _i2 < points.length / 2; _i2++) {\n currentX = points[_i2 * 2];\n currentY = points[_i2 * 2 + 1];\n\n if (_i2 < points.length / 2 - 1) {\n nextX = points[(_i2 + 1) * 2];\n nextY = points[(_i2 + 1) * 2 + 1];\n } else {\n nextX = points[0];\n nextY = points[1];\n }\n\n intersection = finiteLinesIntersect(x, y, centerX, centerY, currentX, currentY, nextX, nextY);\n\n if (intersection.length !== 0) {\n intersections.push(intersection[0], intersection[1]);\n }\n }\n\n return intersections;\n};\nvar roundPolygonIntersectLine = function roundPolygonIntersectLine(x, y, basePoints, centerX, centerY, width, height, padding) {\n var intersections = [];\n var intersection;\n var lines = new Array(basePoints.length);\n var halfW = width / 2;\n var halfH = height / 2;\n var cornerRadius = getRoundPolygonRadius(width, height);\n\n for (var i = 0; i < basePoints.length / 4; i++) {\n var sourceUv = void 0,\n destUv = void 0;\n\n if (i === 0) {\n sourceUv = basePoints.length - 2;\n } else {\n sourceUv = i * 4 - 2;\n }\n\n destUv = i * 4 + 2;\n var px = centerX + halfW * basePoints[i * 4];\n var py = centerY + halfH * basePoints[i * 4 + 1];\n var cosTheta = -basePoints[sourceUv] * basePoints[destUv] - basePoints[sourceUv + 1] * basePoints[destUv + 1];\n var offset = cornerRadius / Math.tan(Math.acos(cosTheta) / 2);\n var cp0x = px - offset * basePoints[sourceUv];\n var cp0y = py - offset * basePoints[sourceUv + 1];\n var cp1x = px + offset * basePoints[destUv];\n var cp1y = py + offset * basePoints[destUv + 1];\n\n if (i === 0) {\n lines[basePoints.length - 2] = cp0x;\n lines[basePoints.length - 1] = cp0y;\n } else {\n lines[i * 4 - 2] = cp0x;\n lines[i * 4 - 1] = cp0y;\n }\n\n lines[i * 4] = cp1x;\n lines[i * 4 + 1] = cp1y;\n var orthx = basePoints[sourceUv + 1];\n var orthy = -basePoints[sourceUv];\n var cosAlpha = orthx * basePoints[destUv] + orthy * basePoints[destUv + 1];\n\n if (cosAlpha < 0) {\n orthx *= -1;\n orthy *= -1;\n }\n\n var cx = cp0x + orthx * cornerRadius;\n var cy = cp0y + orthy * cornerRadius;\n intersection = intersectLineCircle(x, y, centerX, centerY, cx, cy, cornerRadius);\n\n if (intersection.length !== 0) {\n intersections.push(intersection[0], intersection[1]);\n }\n }\n\n for (var _i3 = 0; _i3 < lines.length / 4; _i3++) {\n intersection = finiteLinesIntersect(x, y, centerX, centerY, lines[_i3 * 4], lines[_i3 * 4 + 1], lines[_i3 * 4 + 2], lines[_i3 * 4 + 3], false);\n\n if (intersection.length !== 0) {\n intersections.push(intersection[0], intersection[1]);\n }\n }\n\n if (intersections.length > 2) {\n var lowestIntersection = [intersections[0], intersections[1]];\n var lowestSquaredDistance = Math.pow(lowestIntersection[0] - x, 2) + Math.pow(lowestIntersection[1] - y, 2);\n\n for (var _i4 = 1; _i4 < intersections.length / 2; _i4++) {\n var squaredDistance = Math.pow(intersections[_i4 * 2] - x, 2) + Math.pow(intersections[_i4 * 2 + 1] - y, 2);\n\n if (squaredDistance <= lowestSquaredDistance) {\n lowestIntersection[0] = intersections[_i4 * 2];\n lowestIntersection[1] = intersections[_i4 * 2 + 1];\n lowestSquaredDistance = squaredDistance;\n }\n }\n\n return lowestIntersection;\n }\n\n return intersections;\n};\nvar shortenIntersection = function shortenIntersection(intersection, offset, amount) {\n var disp = [intersection[0] - offset[0], intersection[1] - offset[1]];\n var length = Math.sqrt(disp[0] * disp[0] + disp[1] * disp[1]);\n var lenRatio = (length - amount) / length;\n\n if (lenRatio < 0) {\n lenRatio = 0.00001;\n }\n\n return [offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1]];\n};\nvar generateUnitNgonPointsFitToSquare = function generateUnitNgonPointsFitToSquare(sides, rotationRadians) {\n var points = generateUnitNgonPoints(sides, rotationRadians);\n points = fitPolygonToSquare(points);\n return points;\n};\nvar fitPolygonToSquare = function fitPolygonToSquare(points) {\n var x, y;\n var sides = points.length / 2;\n var minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n\n for (var i = 0; i < sides; i++) {\n x = points[2 * i];\n y = points[2 * i + 1];\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n } // stretch factors\n\n\n var sx = 2 / (maxX - minX);\n var sy = 2 / (maxY - minY);\n\n for (var _i5 = 0; _i5 < sides; _i5++) {\n x = points[2 * _i5] = points[2 * _i5] * sx;\n y = points[2 * _i5 + 1] = points[2 * _i5 + 1] * sy;\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n }\n\n if (minY < -1) {\n for (var _i6 = 0; _i6 < sides; _i6++) {\n y = points[2 * _i6 + 1] = points[2 * _i6 + 1] + (-1 - minY);\n }\n }\n\n return points;\n};\nvar generateUnitNgonPoints = function generateUnitNgonPoints(sides, rotationRadians) {\n var increment = 1.0 / sides * 2 * Math.PI;\n var startAngle = sides % 2 === 0 ? Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0;\n startAngle += rotationRadians;\n var points = new Array(sides * 2);\n var currentAngle;\n\n for (var i = 0; i < sides; i++) {\n currentAngle = i * increment + startAngle;\n points[2 * i] = Math.cos(currentAngle); // x\n\n points[2 * i + 1] = Math.sin(-currentAngle); // y\n }\n\n return points;\n}; // Set the default radius, unless half of width or height is smaller than default\n\nvar getRoundRectangleRadius = function getRoundRectangleRadius(width, height) {\n return Math.min(width / 4, height / 4, 8);\n}; // Set the default radius\n\nvar getRoundPolygonRadius = function getRoundPolygonRadius(width, height) {\n return Math.min(width / 10, height / 10, 8);\n};\nvar getCutRectangleCornerLength = function getCutRectangleCornerLength() {\n return 8;\n};\nvar bezierPtsToQuadCoeff = function bezierPtsToQuadCoeff(p0, p1, p2) {\n return [p0 - 2 * p1 + p2, 2 * (p1 - p0), p0];\n}; // get curve width, height, and control point position offsets as a percentage of node height / width\n\nvar getBarrelCurveConstants = function getBarrelCurveConstants(width, height) {\n return {\n heightOffset: Math.min(15, 0.05 * height),\n widthOffset: Math.min(100, 0.25 * width),\n ctrlPtOffsetPct: 0.05\n };\n};\n\nvar pageRankDefaults = defaults({\n dampingFactor: 0.8,\n precision: 0.000001,\n iterations: 200,\n weight: function weight(edge) {\n return 1;\n }\n});\nvar elesfn$7 = {\n pageRank: function pageRank(options) {\n var _pageRankDefaults = pageRankDefaults(options),\n dampingFactor = _pageRankDefaults.dampingFactor,\n precision = _pageRankDefaults.precision,\n iterations = _pageRankDefaults.iterations,\n weight = _pageRankDefaults.weight;\n\n var cy = this._private.cy;\n\n var _this$byGroup = this.byGroup(),\n nodes = _this$byGroup.nodes,\n edges = _this$byGroup.edges;\n\n var numNodes = nodes.length;\n var numNodesSqd = numNodes * numNodes;\n var numEdges = edges.length; // Construct transposed adjacency matrix\n // First lets have a zeroed matrix of the right size\n // We'll also keep track of the sum of each column\n\n var matrix = new Array(numNodesSqd);\n var columnSum = new Array(numNodes);\n var additionalProb = (1 - dampingFactor) / numNodes; // Create null matrix\n\n for (var i = 0; i < numNodes; i++) {\n for (var j = 0; j < numNodes; j++) {\n var n = i * numNodes + j;\n matrix[n] = 0;\n }\n\n columnSum[i] = 0;\n } // Now, process edges\n\n\n for (var _i = 0; _i < numEdges; _i++) {\n var edge = edges[_i];\n var srcId = edge.data('source');\n var tgtId = edge.data('target'); // Don't include loops in the matrix\n\n if (srcId === tgtId) {\n continue;\n }\n\n var s = nodes.indexOfId(srcId);\n var t = nodes.indexOfId(tgtId);\n var w = weight(edge);\n\n var _n = t * numNodes + s; // Update matrix\n\n\n matrix[_n] += w; // Update column sum\n\n columnSum[s] += w;\n } // Add additional probability based on damping factor\n // Also, take into account columns that have sum = 0\n\n\n var p = 1.0 / numNodes + additionalProb; // Shorthand\n // Traverse matrix, column by column\n\n for (var _j = 0; _j < numNodes; _j++) {\n if (columnSum[_j] === 0) {\n // No 'links' out from node jth, assume equal probability for each possible node\n for (var _i2 = 0; _i2 < numNodes; _i2++) {\n var _n2 = _i2 * numNodes + _j;\n\n matrix[_n2] = p;\n }\n } else {\n // Node jth has outgoing link, compute normalized probabilities\n for (var _i3 = 0; _i3 < numNodes; _i3++) {\n var _n3 = _i3 * numNodes + _j;\n\n matrix[_n3] = matrix[_n3] / columnSum[_j] + additionalProb;\n }\n }\n } // Compute dominant eigenvector using power method\n\n\n var eigenvector = new Array(numNodes);\n var temp = new Array(numNodes);\n var previous; // Start with a vector of all 1's\n // Also, initialize a null vector which will be used as shorthand\n\n for (var _i4 = 0; _i4 < numNodes; _i4++) {\n eigenvector[_i4] = 1;\n }\n\n for (var iter = 0; iter < iterations; iter++) {\n // Temp array with all 0's\n for (var _i5 = 0; _i5 < numNodes; _i5++) {\n temp[_i5] = 0;\n } // Multiply matrix with previous result\n\n\n for (var _i6 = 0; _i6 < numNodes; _i6++) {\n for (var _j2 = 0; _j2 < numNodes; _j2++) {\n var _n4 = _i6 * numNodes + _j2;\n\n temp[_i6] += matrix[_n4] * eigenvector[_j2];\n }\n }\n\n inPlaceSumNormalize(temp);\n previous = eigenvector;\n eigenvector = temp;\n temp = previous;\n var diff = 0; // Compute difference (squared module) of both vectors\n\n for (var _i7 = 0; _i7 < numNodes; _i7++) {\n var delta = previous[_i7] - eigenvector[_i7];\n diff += delta * delta;\n } // If difference is less than the desired threshold, stop iterating\n\n\n if (diff < precision) {\n break;\n }\n } // Construct result\n\n\n var res = {\n rank: function rank(node) {\n node = cy.collection(node)[0];\n return eigenvector[nodes.indexOf(node)];\n }\n };\n return res;\n } // pageRank\n\n}; // elesfn\n\nvar defaults$1 = defaults({\n root: null,\n weight: function weight(edge) {\n return 1;\n },\n directed: false,\n alpha: 0\n});\nvar elesfn$8 = {\n degreeCentralityNormalized: function degreeCentralityNormalized(options) {\n options = defaults$1(options);\n var cy = this.cy();\n var nodes = this.nodes();\n var numNodes = nodes.length;\n\n if (!options.directed) {\n var degrees = {};\n var maxDegree = 0;\n\n for (var i = 0; i < numNodes; i++) {\n var node = nodes[i]; // add current node to the current options object and call degreeCentrality\n\n options.root = node;\n var currDegree = this.degreeCentrality(options);\n\n if (maxDegree < currDegree.degree) {\n maxDegree = currDegree.degree;\n }\n\n degrees[node.id()] = currDegree.degree;\n }\n\n return {\n degree: function degree(node) {\n if (maxDegree === 0) {\n return 0;\n }\n\n if (string(node)) {\n // from is a selector string\n node = cy.filter(node);\n }\n\n return degrees[node.id()] / maxDegree;\n }\n };\n } else {\n var indegrees = {};\n var outdegrees = {};\n var maxIndegree = 0;\n var maxOutdegree = 0;\n\n for (var _i = 0; _i < numNodes; _i++) {\n var _node = nodes[_i];\n\n var id = _node.id(); // add current node to the current options object and call degreeCentrality\n\n\n options.root = _node;\n\n var _currDegree = this.degreeCentrality(options);\n\n if (maxIndegree < _currDegree.indegree) maxIndegree = _currDegree.indegree;\n if (maxOutdegree < _currDegree.outdegree) maxOutdegree = _currDegree.outdegree;\n indegrees[id] = _currDegree.indegree;\n outdegrees[id] = _currDegree.outdegree;\n }\n\n return {\n indegree: function indegree(node) {\n if (maxIndegree == 0) {\n return 0;\n }\n\n if (string(node)) {\n // from is a selector string\n node = cy.filter(node);\n }\n\n return indegrees[node.id()] / maxIndegree;\n },\n outdegree: function outdegree(node) {\n if (maxOutdegree === 0) {\n return 0;\n }\n\n if (string(node)) {\n // from is a selector string\n node = cy.filter(node);\n }\n\n return outdegrees[node.id()] / maxOutdegree;\n }\n };\n }\n },\n // degreeCentralityNormalized\n // Implemented from the algorithm in Opsahl's paper\n // \"Node centrality in weighted networks: Generalizing degree and shortest paths\"\n // check the heading 2 \"Degree\"\n degreeCentrality: function degreeCentrality(options) {\n options = defaults$1(options);\n var cy = this.cy();\n var callingEles = this;\n var _options = options,\n root = _options.root,\n weight = _options.weight,\n directed = _options.directed,\n alpha = _options.alpha;\n root = cy.collection(root)[0];\n\n if (!directed) {\n var connEdges = root.connectedEdges().intersection(callingEles);\n var k = connEdges.length;\n var s = 0; // Now, sum edge weights\n\n for (var i = 0; i < connEdges.length; i++) {\n s += weight(connEdges[i]);\n }\n\n return {\n degree: Math.pow(k, 1 - alpha) * Math.pow(s, alpha)\n };\n } else {\n var edges = root.connectedEdges();\n var incoming = edges.filter(function (edge) {\n return edge.target().same(root) && callingEles.has(edge);\n });\n var outgoing = edges.filter(function (edge) {\n return edge.source().same(root) && callingEles.has(edge);\n });\n var k_in = incoming.length;\n var k_out = outgoing.length;\n var s_in = 0;\n var s_out = 0; // Now, sum incoming edge weights\n\n for (var _i2 = 0; _i2 < incoming.length; _i2++) {\n s_in += weight(incoming[_i2]);\n } // Now, sum outgoing edge weights\n\n\n for (var _i3 = 0; _i3 < outgoing.length; _i3++) {\n s_out += weight(outgoing[_i3]);\n }\n\n return {\n indegree: Math.pow(k_in, 1 - alpha) * Math.pow(s_in, alpha),\n outdegree: Math.pow(k_out, 1 - alpha) * Math.pow(s_out, alpha)\n };\n }\n } // degreeCentrality\n\n}; // elesfn\n// nice, short mathemathical alias\n\nelesfn$8.dc = elesfn$8.degreeCentrality;\nelesfn$8.dcn = elesfn$8.degreeCentralityNormalised = elesfn$8.degreeCentralityNormalized;\n\nvar defaults$2 = defaults({\n harmonic: true,\n weight: function weight() {\n return 1;\n },\n directed: false,\n root: null\n});\nvar elesfn$9 = {\n closenessCentralityNormalized: function closenessCentralityNormalized(options) {\n var _defaults = defaults$2(options),\n harmonic = _defaults.harmonic,\n weight = _defaults.weight,\n directed = _defaults.directed;\n\n var cy = this.cy();\n var closenesses = {};\n var maxCloseness = 0;\n var nodes = this.nodes();\n var fw = this.floydWarshall({\n weight: weight,\n directed: directed\n }); // Compute closeness for every node and find the maximum closeness\n\n for (var i = 0; i < nodes.length; i++) {\n var currCloseness = 0;\n var node_i = nodes[i];\n\n for (var j = 0; j < nodes.length; j++) {\n if (i !== j) {\n var d = fw.distance(node_i, nodes[j]);\n\n if (harmonic) {\n currCloseness += 1 / d;\n } else {\n currCloseness += d;\n }\n }\n }\n\n if (!harmonic) {\n currCloseness = 1 / currCloseness;\n }\n\n if (maxCloseness < currCloseness) {\n maxCloseness = currCloseness;\n }\n\n closenesses[node_i.id()] = currCloseness;\n }\n\n return {\n closeness: function closeness(node) {\n if (maxCloseness == 0) {\n return 0;\n }\n\n if (string(node)) {\n // from is a selector string\n node = cy.filter(node)[0].id();\n } else {\n // from is a node\n node = node.id();\n }\n\n return closenesses[node] / maxCloseness;\n }\n };\n },\n // Implemented from pseudocode from wikipedia\n closenessCentrality: function closenessCentrality(options) {\n var _defaults2 = defaults$2(options),\n root = _defaults2.root,\n weight = _defaults2.weight,\n directed = _defaults2.directed,\n harmonic = _defaults2.harmonic;\n\n root = this.filter(root)[0]; // we need distance from this node to every other node\n\n var dijkstra = this.dijkstra({\n root: root,\n weight: weight,\n directed: directed\n });\n var totalDistance = 0;\n var nodes = this.nodes();\n\n for (var i = 0; i < nodes.length; i++) {\n var n = nodes[i];\n\n if (!n.same(root)) {\n var d = dijkstra.distanceTo(n);\n\n if (harmonic) {\n totalDistance += 1 / d;\n } else {\n totalDistance += d;\n }\n }\n }\n\n return harmonic ? totalDistance : 1 / totalDistance;\n } // closenessCentrality\n\n}; // elesfn\n// nice, short mathemathical alias\n\nelesfn$9.cc = elesfn$9.closenessCentrality;\nelesfn$9.ccn = elesfn$9.closenessCentralityNormalised = elesfn$9.closenessCentralityNormalized;\n\nvar defaults$3 = defaults({\n weight: null,\n directed: false\n});\nvar elesfn$a = {\n // Implemented from the algorithm in the paper \"On Variants of Shortest-Path Betweenness Centrality and their Generic Computation\" by Ulrik Brandes\n betweennessCentrality: function betweennessCentrality(options) {\n var _defaults = defaults$3(options),\n directed = _defaults.directed,\n weight = _defaults.weight;\n\n var weighted = weight != null;\n var cy = this.cy(); // starting\n\n var V = this.nodes();\n var A = {};\n var _C = {};\n var max = 0;\n var C = {\n set: function set(key, val) {\n _C[key] = val;\n\n if (val > max) {\n max = val;\n }\n },\n get: function get(key) {\n return _C[key];\n }\n }; // A contains the neighborhoods of every node\n\n for (var i = 0; i < V.length; i++) {\n var v = V[i];\n var vid = v.id();\n\n if (directed) {\n A[vid] = v.outgoers().nodes(); // get outgoers of every node\n } else {\n A[vid] = v.openNeighborhood().nodes(); // get neighbors of every node\n }\n\n C.set(vid, 0);\n }\n\n var _loop = function _loop(s) {\n var sid = V[s].id();\n var S = []; // stack\n\n var P = {};\n var g = {};\n var d = {};\n var Q = new Heap(function (a, b) {\n return d[a] - d[b];\n }); // queue\n // init dictionaries\n\n for (var _i = 0; _i < V.length; _i++) {\n var _vid = V[_i].id();\n\n P[_vid] = [];\n g[_vid] = 0;\n d[_vid] = Infinity;\n }\n\n g[sid] = 1; // sigma\n\n d[sid] = 0; // distance to s\n\n Q.push(sid);\n\n while (!Q.empty()) {\n var _v = Q.pop();\n\n S.push(_v);\n\n if (weighted) {\n for (var j = 0; j < A[_v].length; j++) {\n var w = A[_v][j];\n var vEle = cy.getElementById(_v);\n var edge = void 0;\n\n if (vEle.edgesTo(w).length > 0) {\n edge = vEle.edgesTo(w)[0];\n } else {\n edge = w.edgesTo(vEle)[0];\n }\n\n var edgeWeight = weight(edge);\n w = w.id();\n\n if (d[w] > d[_v] + edgeWeight) {\n d[w] = d[_v] + edgeWeight;\n\n if (Q.nodes.indexOf(w) < 0) {\n //if w is not in Q\n Q.push(w);\n } else {\n // update position if w is in Q\n Q.updateItem(w);\n }\n\n g[w] = 0;\n P[w] = [];\n }\n\n if (d[w] == d[_v] + edgeWeight) {\n g[w] = g[w] + g[_v];\n P[w].push(_v);\n }\n }\n } else {\n for (var _j = 0; _j < A[_v].length; _j++) {\n var _w = A[_v][_j].id();\n\n if (d[_w] == Infinity) {\n Q.push(_w);\n d[_w] = d[_v] + 1;\n }\n\n if (d[_w] == d[_v] + 1) {\n g[_w] = g[_w] + g[_v];\n\n P[_w].push(_v);\n }\n }\n }\n }\n\n var e = {};\n\n for (var _i2 = 0; _i2 < V.length; _i2++) {\n e[V[_i2].id()] = 0;\n }\n\n while (S.length > 0) {\n var _w2 = S.pop();\n\n for (var _j2 = 0; _j2 < P[_w2].length; _j2++) {\n var _v2 = P[_w2][_j2];\n e[_v2] = e[_v2] + g[_v2] / g[_w2] * (1 + e[_w2]);\n\n if (_w2 != V[s].id()) {\n C.set(_w2, C.get(_w2) + e[_w2]);\n }\n }\n }\n };\n\n for (var s = 0; s < V.length; s++) {\n _loop(s);\n }\n\n var ret = {\n betweenness: function betweenness(node) {\n var id = cy.collection(node).id();\n return C.get(id);\n },\n betweennessNormalized: function betweennessNormalized(node) {\n if (max == 0) {\n return 0;\n }\n\n var id = cy.collection(node).id();\n return C.get(id) / max;\n }\n }; // alias\n\n ret.betweennessNormalised = ret.betweennessNormalized;\n return ret;\n } // betweennessCentrality\n\n}; // elesfn\n// nice, short mathemathical alias\n\nelesfn$a.bc = elesfn$a.betweennessCentrality;\n\n// Implemented by Zoe Xi @zoexi for GSOC 2016\n/* eslint-disable no-unused-vars */\n\nvar defaults$4 = defaults({\n expandFactor: 2,\n // affects time of computation and cluster granularity to some extent: M * M\n inflateFactor: 2,\n // affects cluster granularity (the greater the value, the more clusters): M(i,j) / E(j)\n multFactor: 1,\n // optional self loops for each node. Use a neutral value to improve cluster computations.\n maxIterations: 20,\n // maximum number of iterations of the MCL algorithm in a single run\n attributes: [// attributes/features used to group nodes, ie. similarity values between nodes\n function (edge) {\n return 1;\n }]\n});\n/* eslint-enable */\n\nvar setOptions = function setOptions(options) {\n return defaults$4(options);\n};\n/* eslint-enable */\n\n\nvar getSimilarity = function getSimilarity(edge, attributes) {\n var total = 0;\n\n for (var i = 0; i < attributes.length; i++) {\n total += attributes[i](edge);\n }\n\n return total;\n};\n\nvar addLoops = function addLoops(M, n, val) {\n for (var i = 0; i < n; i++) {\n M[i * n + i] = val;\n }\n};\n\nvar normalize = function normalize(M, n) {\n var sum;\n\n for (var col = 0; col < n; col++) {\n sum = 0;\n\n for (var row = 0; row < n; row++) {\n sum += M[row * n + col];\n }\n\n for (var _row = 0; _row < n; _row++) {\n M[_row * n + col] = M[_row * n + col] / sum;\n }\n }\n}; // TODO: blocked matrix multiplication?\n\n\nvar mmult = function mmult(A, B, n) {\n var C = new Array(n * n);\n\n for (var i = 0; i < n; i++) {\n for (var j = 0; j < n; j++) {\n C[i * n + j] = 0;\n }\n\n for (var k = 0; k < n; k++) {\n for (var _j = 0; _j < n; _j++) {\n C[i * n + _j] += A[i * n + k] * B[k * n + _j];\n }\n }\n }\n\n return C;\n};\n\nvar expand = function expand(M, n, expandFactor\n/** power **/\n) {\n var _M = M.slice(0);\n\n for (var p = 1; p < expandFactor; p++) {\n M = mmult(M, _M, n);\n }\n\n return M;\n};\n\nvar inflate = function inflate(M, n, inflateFactor\n/** r **/\n) {\n var _M = new Array(n * n); // M(i,j) ^ inflatePower\n\n\n for (var i = 0; i < n * n; i++) {\n _M[i] = Math.pow(M[i], inflateFactor);\n }\n\n normalize(_M, n);\n return _M;\n};\n\nvar hasConverged = function hasConverged(M, _M, n2, roundFactor) {\n // Check that both matrices have the same elements (i,j)\n for (var i = 0; i < n2; i++) {\n var v1 = Math.round(M[i] * Math.pow(10, roundFactor)) / Math.pow(10, roundFactor); // truncate to 'roundFactor' decimal places\n\n var v2 = Math.round(_M[i] * Math.pow(10, roundFactor)) / Math.pow(10, roundFactor);\n\n if (v1 !== v2) {\n return false;\n }\n }\n\n return true;\n};\n\nvar assign = function assign(M, n, nodes, cy) {\n var clusters = [];\n\n for (var i = 0; i < n; i++) {\n var cluster = [];\n\n for (var j = 0; j < n; j++) {\n // Row-wise attractors and elements that they attract belong in same cluster\n if (Math.round(M[i * n + j] * 1000) / 1000 > 0) {\n cluster.push(nodes[j]);\n }\n }\n\n if (cluster.length !== 0) {\n clusters.push(cy.collection(cluster));\n }\n }\n\n return clusters;\n};\n\nvar isDuplicate = function isDuplicate(c1, c2) {\n for (var i = 0; i < c1.length; i++) {\n if (!c2[i] || c1[i].id() !== c2[i].id()) {\n return false;\n }\n }\n\n return true;\n};\n\nvar removeDuplicates = function removeDuplicates(clusters) {\n for (var i = 0; i < clusters.length; i++) {\n for (var j = 0; j < clusters.length; j++) {\n if (i != j && isDuplicate(clusters[i], clusters[j])) {\n clusters.splice(j, 1);\n }\n }\n }\n\n return clusters;\n};\n\nvar markovClustering = function markovClustering(options) {\n var nodes = this.nodes();\n var edges = this.edges();\n var cy = this.cy(); // Set parameters of algorithm:\n\n var opts = setOptions(options); // Map each node to its position in node array\n\n var id2position = {};\n\n for (var i = 0; i < nodes.length; i++) {\n id2position[nodes[i].id()] = i;\n } // Generate stochastic matrix M from input graph G (should be symmetric/undirected)\n\n\n var n = nodes.length,\n n2 = n * n;\n\n var M = new Array(n2),\n _M;\n\n for (var _i = 0; _i < n2; _i++) {\n M[_i] = 0;\n }\n\n for (var e = 0; e < edges.length; e++) {\n var edge = edges[e];\n var _i2 = id2position[edge.source().id()];\n var j = id2position[edge.target().id()];\n var sim = getSimilarity(edge, opts.attributes);\n M[_i2 * n + j] += sim; // G should be symmetric and undirected\n\n M[j * n + _i2] += sim;\n } // Begin Markov cluster algorithm\n // Step 1: Add self loops to each node, ie. add multFactor to matrix diagonal\n\n\n addLoops(M, n, opts.multFactor); // Step 2: M = normalize( M );\n\n normalize(M, n);\n var isStillMoving = true;\n var iterations = 0;\n\n while (isStillMoving && iterations < opts.maxIterations) {\n isStillMoving = false; // Step 3:\n\n _M = expand(M, n, opts.expandFactor); // Step 4:\n\n M = inflate(_M, n, opts.inflateFactor); // Step 5: check to see if ~steady state has been reached\n\n if (!hasConverged(M, _M, n2, 4)) {\n isStillMoving = true;\n }\n\n iterations++;\n } // Build clusters from matrix\n\n\n var clusters = assign(M, n, nodes, cy); // Remove duplicate clusters due to symmetry of graph and M matrix\n\n clusters = removeDuplicates(clusters);\n return clusters;\n};\n\nvar markovClustering$1 = {\n markovClustering: markovClustering,\n mcl: markovClustering\n};\n\n// Common distance metrics for clustering algorithms\n\nvar identity = function identity(x) {\n return x;\n};\n\nvar absDiff = function absDiff(p, q) {\n return Math.abs(q - p);\n};\n\nvar addAbsDiff = function addAbsDiff(total, p, q) {\n return total + absDiff(p, q);\n};\n\nvar addSquaredDiff = function addSquaredDiff(total, p, q) {\n return total + Math.pow(q - p, 2);\n};\n\nvar sqrt = function sqrt(x) {\n return Math.sqrt(x);\n};\n\nvar maxAbsDiff = function maxAbsDiff(currentMax, p, q) {\n return Math.max(currentMax, absDiff(p, q));\n};\n\nvar getDistance = function getDistance(length, getP, getQ, init, visit) {\n var post = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : identity;\n var ret = init;\n var p, q;\n\n for (var dim = 0; dim < length; dim++) {\n p = getP(dim);\n q = getQ(dim);\n ret = visit(ret, p, q);\n }\n\n return post(ret);\n};\n\nvar distances = {\n euclidean: function euclidean(length, getP, getQ) {\n if (length >= 2) {\n return getDistance(length, getP, getQ, 0, addSquaredDiff, sqrt);\n } else {\n // for single attr case, more efficient to avoid sqrt\n return getDistance(length, getP, getQ, 0, addAbsDiff);\n }\n },\n squaredEuclidean: function squaredEuclidean(length, getP, getQ) {\n return getDistance(length, getP, getQ, 0, addSquaredDiff);\n },\n manhattan: function manhattan(length, getP, getQ) {\n return getDistance(length, getP, getQ, 0, addAbsDiff);\n },\n max: function max(length, getP, getQ) {\n return getDistance(length, getP, getQ, -Infinity, maxAbsDiff);\n }\n}; // in case the user accidentally doesn't use camel case\n\ndistances['squared-euclidean'] = distances['squaredEuclidean'];\ndistances['squaredeuclidean'] = distances['squaredEuclidean'];\nfunction clusteringDistance (method, length, getP, getQ, nodeP, nodeQ) {\n var impl;\n\n if (fn(method)) {\n impl = method;\n } else {\n impl = distances[method] || distances.euclidean;\n }\n\n if (length === 0 && fn(method)) {\n return impl(nodeP, nodeQ);\n } else {\n return impl(length, getP, getQ, nodeP, nodeQ);\n }\n}\n\nvar defaults$5 = defaults({\n k: 2,\n m: 2,\n sensitivityThreshold: 0.0001,\n distance: 'euclidean',\n maxIterations: 10,\n attributes: [],\n testMode: false,\n testCentroids: null\n});\n\nvar setOptions$1 = function setOptions(options) {\n return defaults$5(options);\n};\n/* eslint-enable */\n\n\nvar getDist = function getDist(type, node, centroid, attributes, mode) {\n var noNodeP = mode !== 'kMedoids';\n var getP = noNodeP ? function (i) {\n return centroid[i];\n } : function (i) {\n return attributes[i](centroid);\n };\n\n var getQ = function getQ(i) {\n return attributes[i](node);\n };\n\n var nodeP = centroid;\n var nodeQ = node;\n return clusteringDistance(type, attributes.length, getP, getQ, nodeP, nodeQ);\n};\n\nvar randomCentroids = function randomCentroids(nodes, k, attributes) {\n var ndim = attributes.length;\n var min = new Array(ndim);\n var max = new Array(ndim);\n var centroids = new Array(k);\n var centroid = null; // Find min, max values for each attribute dimension\n\n for (var i = 0; i < ndim; i++) {\n min[i] = nodes.min(attributes[i]).value;\n max[i] = nodes.max(attributes[i]).value;\n } // Build k centroids, each represented as an n-dim feature vector\n\n\n for (var c = 0; c < k; c++) {\n centroid = [];\n\n for (var _i = 0; _i < ndim; _i++) {\n centroid[_i] = Math.random() * (max[_i] - min[_i]) + min[_i]; // random initial value\n }\n\n centroids[c] = centroid;\n }\n\n return centroids;\n};\n\nvar classify = function classify(node, centroids, distance, attributes, type) {\n var min = Infinity;\n var index = 0;\n\n for (var i = 0; i < centroids.length; i++) {\n var dist = getDist(distance, node, centroids[i], attributes, type);\n\n if (dist < min) {\n min = dist;\n index = i;\n }\n }\n\n return index;\n};\n\nvar buildCluster = function buildCluster(centroid, nodes, assignment) {\n var cluster = [];\n var node = null;\n\n for (var n = 0; n < nodes.length; n++) {\n node = nodes[n];\n\n if (assignment[node.id()] === centroid) {\n //console.log(\"Node \" + node.id() + \" is associated with medoid #: \" + m);\n cluster.push(node);\n }\n }\n\n return cluster;\n};\n\nvar haveValuesConverged = function haveValuesConverged(v1, v2, sensitivityThreshold) {\n return Math.abs(v2 - v1) <= sensitivityThreshold;\n};\n\nvar haveMatricesConverged = function haveMatricesConverged(v1, v2, sensitivityThreshold) {\n for (var i = 0; i < v1.length; i++) {\n for (var j = 0; j < v1[i].length; j++) {\n var diff = Math.abs(v1[i][j] - v2[i][j]);\n\n if (diff > sensitivityThreshold) {\n return false;\n }\n }\n }\n\n return true;\n};\n\nvar seenBefore = function seenBefore(node, medoids, n) {\n for (var i = 0; i < n; i++) {\n if (node === medoids[i]) return true;\n }\n\n return false;\n};\n\nvar randomMedoids = function randomMedoids(nodes, k) {\n var medoids = new Array(k); // For small data sets, the probability of medoid conflict is greater,\n // so we need to check to see if we've already seen or chose this node before.\n\n if (nodes.length < 50) {\n // Randomly select k medoids from the n nodes\n for (var i = 0; i < k; i++) {\n var node = nodes[Math.floor(Math.random() * nodes.length)]; // If we've already chosen this node to be a medoid, don't choose it again (for small data sets).\n // Instead choose a different random node.\n\n while (seenBefore(node, medoids, i)) {\n node = nodes[Math.floor(Math.random() * nodes.length)];\n }\n\n medoids[i] = node;\n }\n } else {\n // Relatively large data set, so pretty safe to not check and just select random nodes\n for (var _i2 = 0; _i2 < k; _i2++) {\n medoids[_i2] = nodes[Math.floor(Math.random() * nodes.length)];\n }\n }\n\n return medoids;\n};\n\nvar findCost = function findCost(potentialNewMedoid, cluster, attributes) {\n var cost = 0;\n\n for (var n = 0; n < cluster.length; n++) {\n cost += getDist('manhattan', cluster[n], potentialNewMedoid, attributes, 'kMedoids');\n }\n\n return cost;\n};\n\nvar kMeans = function kMeans(options) {\n var cy = this.cy();\n var nodes = this.nodes();\n var node = null; // Set parameters of algorithm: # of clusters, distance metric, etc.\n\n var opts = setOptions$1(options); // Begin k-means algorithm\n\n var clusters = new Array(opts.k);\n var assignment = {};\n var centroids; // Step 1: Initialize centroid positions\n\n if (opts.testMode) {\n if (typeof opts.testCentroids === 'number') {\n centroids = randomCentroids(nodes, opts.k, opts.attributes);\n } else if (_typeof(opts.testCentroids) === 'object') {\n centroids = opts.testCentroids;\n } else {\n centroids = randomCentroids(nodes, opts.k, opts.attributes);\n }\n } else {\n centroids = randomCentroids(nodes, opts.k, opts.attributes);\n }\n\n var isStillMoving = true;\n var iterations = 0;\n\n while (isStillMoving && iterations < opts.maxIterations) {\n // Step 2: Assign nodes to the nearest centroid\n for (var n = 0; n < nodes.length; n++) {\n node = nodes[n]; // Determine which cluster this node belongs to: node id => cluster #\n\n assignment[node.id()] = classify(node, centroids, opts.distance, opts.attributes, 'kMeans');\n } // Step 3: For each of the k clusters, update its centroid\n\n\n isStillMoving = false;\n\n for (var c = 0; c < opts.k; c++) {\n // Get all nodes that belong to this cluster\n var cluster = buildCluster(c, nodes, assignment);\n\n if (cluster.length === 0) {\n // If cluster is empty, break out early & move to next cluster\n continue;\n } // Update centroids by calculating avg of all nodes within the cluster.\n\n\n var ndim = opts.attributes.length;\n var centroid = centroids[c]; // [ dim_1, dim_2, dim_3, ... , dim_n ]\n\n var newCentroid = new Array(ndim);\n var sum = new Array(ndim);\n\n for (var d = 0; d < ndim; d++) {\n sum[d] = 0.0;\n\n for (var i = 0; i < cluster.length; i++) {\n node = cluster[i];\n sum[d] += opts.attributes[d](node);\n }\n\n newCentroid[d] = sum[d] / cluster.length; // Check to see if algorithm has converged, i.e. when centroids no longer change\n\n if (!haveValuesConverged(newCentroid[d], centroid[d], opts.sensitivityThreshold)) {\n isStillMoving = true;\n }\n }\n\n centroids[c] = newCentroid;\n clusters[c] = cy.collection(cluster);\n }\n\n iterations++;\n }\n\n return clusters;\n};\n\nvar kMedoids = function kMedoids(options) {\n var cy = this.cy();\n var nodes = this.nodes();\n var node = null;\n var opts = setOptions$1(options); // Begin k-medoids algorithm\n\n var clusters = new Array(opts.k);\n var medoids;\n var assignment = {};\n var curCost;\n var minCosts = new Array(opts.k); // minimum cost configuration for each cluster\n // Step 1: Initialize k medoids\n\n if (opts.testMode) {\n if (typeof opts.testCentroids === 'number') ; else if (_typeof(opts.testCentroids) === 'object') {\n medoids = opts.testCentroids;\n } else {\n medoids = randomMedoids(nodes, opts.k);\n }\n } else {\n medoids = randomMedoids(nodes, opts.k);\n }\n\n var isStillMoving = true;\n var iterations = 0;\n\n while (isStillMoving && iterations < opts.maxIterations) {\n // Step 2: Assign nodes to the nearest medoid\n for (var n = 0; n < nodes.length; n++) {\n node = nodes[n]; // Determine which cluster this node belongs to: node id => cluster #\n\n assignment[node.id()] = classify(node, medoids, opts.distance, opts.attributes, 'kMedoids');\n }\n\n isStillMoving = false; // Step 3: For each medoid m, and for each node assciated with mediod m,\n // select the node with the lowest configuration cost as new medoid.\n\n for (var m = 0; m < medoids.length; m++) {\n // Get all nodes that belong to this medoid\n var cluster = buildCluster(m, nodes, assignment);\n\n if (cluster.length === 0) {\n // If cluster is empty, break out early & move to next cluster\n continue;\n }\n\n minCosts[m] = findCost(medoids[m], cluster, opts.attributes); // original cost\n // Select different medoid if its configuration has the lowest cost\n\n for (var _n = 0; _n < cluster.length; _n++) {\n curCost = findCost(cluster[_n], cluster, opts.attributes);\n\n if (curCost < minCosts[m]) {\n minCosts[m] = curCost;\n medoids[m] = cluster[_n];\n isStillMoving = true;\n }\n }\n\n clusters[m] = cy.collection(cluster);\n }\n\n iterations++;\n }\n\n return clusters;\n};\n\nvar updateCentroids = function updateCentroids(centroids, nodes, U, weight, opts) {\n var numerator, denominator;\n\n for (var n = 0; n < nodes.length; n++) {\n for (var c = 0; c < centroids.length; c++) {\n weight[n][c] = Math.pow(U[n][c], opts.m);\n }\n }\n\n for (var _c = 0; _c < centroids.length; _c++) {\n for (var dim = 0; dim < opts.attributes.length; dim++) {\n numerator = 0;\n denominator = 0;\n\n for (var _n2 = 0; _n2 < nodes.length; _n2++) {\n numerator += weight[_n2][_c] * opts.attributes[dim](nodes[_n2]);\n denominator += weight[_n2][_c];\n }\n\n centroids[_c][dim] = numerator / denominator;\n }\n }\n};\n\nvar updateMembership = function updateMembership(U, _U, centroids, nodes, opts) {\n // Save previous step\n for (var i = 0; i < U.length; i++) {\n _U[i] = U[i].slice();\n }\n\n var sum, numerator, denominator;\n var pow = 2 / (opts.m - 1);\n\n for (var c = 0; c < centroids.length; c++) {\n for (var n = 0; n < nodes.length; n++) {\n sum = 0;\n\n for (var k = 0; k < centroids.length; k++) {\n // against all other centroids\n numerator = getDist(opts.distance, nodes[n], centroids[c], opts.attributes, 'cmeans');\n denominator = getDist(opts.distance, nodes[n], centroids[k], opts.attributes, 'cmeans');\n sum += Math.pow(numerator / denominator, pow);\n }\n\n U[n][c] = 1 / sum;\n }\n }\n};\n\nvar assign$1 = function assign(nodes, U, opts, cy) {\n var clusters = new Array(opts.k);\n\n for (var c = 0; c < clusters.length; c++) {\n clusters[c] = [];\n }\n\n var max;\n var index;\n\n for (var n = 0; n < U.length; n++) {\n // for each node (U is N x C matrix)\n max = -Infinity;\n index = -1; // Determine which cluster the node is most likely to belong in\n\n for (var _c2 = 0; _c2 < U[0].length; _c2++) {\n if (U[n][_c2] > max) {\n max = U[n][_c2];\n index = _c2;\n }\n }\n\n clusters[index].push(nodes[n]);\n } // Turn every array into a collection of nodes\n\n\n for (var _c3 = 0; _c3 < clusters.length; _c3++) {\n clusters[_c3] = cy.collection(clusters[_c3]);\n }\n\n return clusters;\n};\n\nvar fuzzyCMeans = function fuzzyCMeans(options) {\n var cy = this.cy();\n var nodes = this.nodes();\n var opts = setOptions$1(options); // Begin fuzzy c-means algorithm\n\n var clusters;\n var centroids;\n var U;\n\n var _U;\n\n var weight; // Step 1: Initialize letiables.\n\n _U = new Array(nodes.length);\n\n for (var i = 0; i < nodes.length; i++) {\n // N x C matrix\n _U[i] = new Array(opts.k);\n }\n\n U = new Array(nodes.length);\n\n for (var _i3 = 0; _i3 < nodes.length; _i3++) {\n // N x C matrix\n U[_i3] = new Array(opts.k);\n }\n\n for (var _i4 = 0; _i4 < nodes.length; _i4++) {\n var total = 0;\n\n for (var j = 0; j < opts.k; j++) {\n U[_i4][j] = Math.random();\n total += U[_i4][j];\n }\n\n for (var _j = 0; _j < opts.k; _j++) {\n U[_i4][_j] = U[_i4][_j] / total;\n }\n }\n\n centroids = new Array(opts.k);\n\n for (var _i5 = 0; _i5 < opts.k; _i5++) {\n centroids[_i5] = new Array(opts.attributes.length);\n }\n\n weight = new Array(nodes.length);\n\n for (var _i6 = 0; _i6 < nodes.length; _i6++) {\n // N x C matrix\n weight[_i6] = new Array(opts.k);\n } // end init FCM\n\n\n var isStillMoving = true;\n var iterations = 0;\n\n while (isStillMoving && iterations < opts.maxIterations) {\n isStillMoving = false; // Step 2: Calculate the centroids for each step.\n\n updateCentroids(centroids, nodes, U, weight, opts); // Step 3: Update the partition matrix U.\n\n updateMembership(U, _U, centroids, nodes, opts); // Step 4: Check for convergence.\n\n if (!haveMatricesConverged(U, _U, opts.sensitivityThreshold)) {\n isStillMoving = true;\n }\n\n iterations++;\n } // Assign nodes to clusters with highest probability.\n\n\n clusters = assign$1(nodes, U, opts, cy);\n return {\n clusters: clusters,\n degreeOfMembership: U\n };\n};\n\nvar kClustering = {\n kMeans: kMeans,\n kMedoids: kMedoids,\n fuzzyCMeans: fuzzyCMeans,\n fcm: fuzzyCMeans\n};\n\n// Implemented by Zoe Xi @zoexi for GSOC 2016\nvar defaults$6 = defaults({\n distance: 'euclidean',\n // distance metric to compare nodes\n linkage: 'min',\n // linkage criterion : how to determine the distance between clusters of nodes\n mode: 'threshold',\n // mode:'threshold' => clusters must be threshold distance apart\n threshold: Infinity,\n // the distance threshold\n // mode:'dendrogram' => the nodes are organised as leaves in a tree (siblings are close), merging makes clusters\n addDendrogram: false,\n // whether to add the dendrogram to the graph for viz\n dendrogramDepth: 0,\n // depth at which dendrogram branches are merged into the returned clusters\n attributes: [] // array of attr functions\n\n});\nvar linkageAliases = {\n 'single': 'min',\n 'complete': 'max'\n};\n\nvar setOptions$2 = function setOptions(options) {\n var opts = defaults$6(options);\n var preferredAlias = linkageAliases[opts.linkage];\n\n if (preferredAlias != null) {\n opts.linkage = preferredAlias;\n }\n\n return opts;\n};\n\nvar mergeClosest = function mergeClosest(clusters, index, dists, mins, opts) {\n // Find two closest clusters from cached mins\n var minKey = 0;\n var min = Infinity;\n var dist;\n var attrs = opts.attributes;\n\n var getDist = function getDist(n1, n2) {\n return clusteringDistance(opts.distance, attrs.length, function (i) {\n return attrs[i](n1);\n }, function (i) {\n return attrs[i](n2);\n }, n1, n2);\n };\n\n for (var i = 0; i < clusters.length; i++) {\n var key = clusters[i].key;\n var _dist = dists[key][mins[key]];\n\n if (_dist < min) {\n minKey = key;\n min = _dist;\n }\n }\n\n if (opts.mode === 'threshold' && min >= opts.threshold || opts.mode === 'dendrogram' && clusters.length === 1) {\n return false;\n }\n\n var c1 = index[minKey];\n var c2 = index[mins[minKey]];\n var merged; // Merge two closest clusters\n\n if (opts.mode === 'dendrogram') {\n merged = {\n left: c1,\n right: c2,\n key: c1.key\n };\n } else {\n merged = {\n value: c1.value.concat(c2.value),\n key: c1.key\n };\n }\n\n clusters[c1.index] = merged;\n clusters.splice(c2.index, 1);\n index[c1.key] = merged; // Update distances with new merged cluster\n\n for (var _i = 0; _i < clusters.length; _i++) {\n var cur = clusters[_i];\n\n if (c1.key === cur.key) {\n dist = Infinity;\n } else if (opts.linkage === 'min') {\n dist = dists[c1.key][cur.key];\n\n if (dists[c1.key][cur.key] > dists[c2.key][cur.key]) {\n dist = dists[c2.key][cur.key];\n }\n } else if (opts.linkage === 'max') {\n dist = dists[c1.key][cur.key];\n\n if (dists[c1.key][cur.key] < dists[c2.key][cur.key]) {\n dist = dists[c2.key][cur.key];\n }\n } else if (opts.linkage === 'mean') {\n dist = (dists[c1.key][cur.key] * c1.size + dists[c2.key][cur.key] * c2.size) / (c1.size + c2.size);\n } else {\n if (opts.mode === 'dendrogram') dist = getDist(cur.value, c1.value);else dist = getDist(cur.value[0], c1.value[0]);\n }\n\n dists[c1.key][cur.key] = dists[cur.key][c1.key] = dist; // distance matrix is symmetric\n } // Update cached mins\n\n\n for (var _i2 = 0; _i2 < clusters.length; _i2++) {\n var key1 = clusters[_i2].key;\n\n if (mins[key1] === c1.key || mins[key1] === c2.key) {\n var _min = key1;\n\n for (var j = 0; j < clusters.length; j++) {\n var key2 = clusters[j].key;\n\n if (dists[key1][key2] < dists[key1][_min]) {\n _min = key2;\n }\n }\n\n mins[key1] = _min;\n }\n\n clusters[_i2].index = _i2;\n } // Clean up meta data used for clustering\n\n\n c1.key = c2.key = c1.index = c2.index = null;\n return true;\n};\n\nvar getAllChildren = function getAllChildren(root, arr, cy) {\n if (!root) return;\n\n if (root.value) {\n arr.push(root.value);\n } else {\n if (root.left) getAllChildren(root.left, arr);\n if (root.right) getAllChildren(root.right, arr);\n }\n};\n\nvar buildDendrogram = function buildDendrogram(root, cy) {\n if (!root) return '';\n\n if (root.left && root.right) {\n var leftStr = buildDendrogram(root.left, cy);\n var rightStr = buildDendrogram(root.right, cy);\n var node = cy.add({\n group: 'nodes',\n data: {\n id: leftStr + ',' + rightStr\n }\n });\n cy.add({\n group: 'edges',\n data: {\n source: leftStr,\n target: node.id()\n }\n });\n cy.add({\n group: 'edges',\n data: {\n source: rightStr,\n target: node.id()\n }\n });\n return node.id();\n } else if (root.value) {\n return root.value.id();\n }\n};\n\nvar buildClustersFromTree = function buildClustersFromTree(root, k, cy) {\n if (!root) return [];\n var left = [],\n right = [],\n leaves = [];\n\n if (k === 0) {\n // don't cut tree, simply return all nodes as 1 single cluster\n if (root.left) getAllChildren(root.left, left);\n if (root.right) getAllChildren(root.right, right);\n leaves = left.concat(right);\n return [cy.collection(leaves)];\n } else if (k === 1) {\n // cut at root\n if (root.value) {\n // leaf node\n return [cy.collection(root.value)];\n } else {\n if (root.left) getAllChildren(root.left, left);\n if (root.right) getAllChildren(root.right, right);\n return [cy.collection(left), cy.collection(right)];\n }\n } else {\n if (root.value) {\n return [cy.collection(root.value)];\n } else {\n if (root.left) left = buildClustersFromTree(root.left, k - 1, cy);\n if (root.right) right = buildClustersFromTree(root.right, k - 1, cy);\n return left.concat(right);\n }\n }\n};\n/* eslint-enable */\n\n\nvar hierarchicalClustering = function hierarchicalClustering(options) {\n var cy = this.cy();\n var nodes = this.nodes(); // Set parameters of algorithm: linkage type, distance metric, etc.\n\n var opts = setOptions$2(options);\n var attrs = opts.attributes;\n\n var getDist = function getDist(n1, n2) {\n return clusteringDistance(opts.distance, attrs.length, function (i) {\n return attrs[i](n1);\n }, function (i) {\n return attrs[i](n2);\n }, n1, n2);\n }; // Begin hierarchical algorithm\n\n\n var clusters = [];\n var dists = []; // distances between each pair of clusters\n\n var mins = []; // closest cluster for each cluster\n\n var index = []; // hash of all clusters by key\n // In agglomerative (bottom-up) clustering, each node starts as its own cluster\n\n for (var n = 0; n < nodes.length; n++) {\n var cluster = {\n value: opts.mode === 'dendrogram' ? nodes[n] : [nodes[n]],\n key: n,\n index: n\n };\n clusters[n] = cluster;\n index[n] = cluster;\n dists[n] = [];\n mins[n] = 0;\n } // Calculate the distance between each pair of clusters\n\n\n for (var i = 0; i < clusters.length; i++) {\n for (var j = 0; j <= i; j++) {\n var dist = void 0;\n\n if (opts.mode === 'dendrogram') {\n // modes store cluster values differently\n dist = i === j ? Infinity : getDist(clusters[i].value, clusters[j].value);\n } else {\n dist = i === j ? Infinity : getDist(clusters[i].value[0], clusters[j].value[0]);\n }\n\n dists[i][j] = dist;\n dists[j][i] = dist;\n\n if (dist < dists[i][mins[i]]) {\n mins[i] = j; // Cache mins: closest cluster to cluster i is cluster j\n }\n }\n } // Find the closest pair of clusters and merge them into a single cluster.\n // Update distances between new cluster and each of the old clusters, and loop until threshold reached.\n\n\n var merged = mergeClosest(clusters, index, dists, mins, opts);\n\n while (merged) {\n merged = mergeClosest(clusters, index, dists, mins, opts);\n }\n\n var retClusters; // Dendrogram mode builds the hierarchy and adds intermediary nodes + edges\n // in addition to returning the clusters.\n\n if (opts.mode === 'dendrogram') {\n retClusters = buildClustersFromTree(clusters[0], opts.dendrogramDepth, cy);\n if (opts.addDendrogram) buildDendrogram(clusters[0], cy);\n } else {\n // Regular mode simply returns the clusters\n retClusters = new Array(clusters.length);\n clusters.forEach(function (cluster, i) {\n // Clean up meta data used for clustering\n cluster.key = cluster.index = null;\n retClusters[i] = cy.collection(cluster.value);\n });\n }\n\n return retClusters;\n};\n\nvar hierarchicalClustering$1 = {\n hierarchicalClustering: hierarchicalClustering,\n hca: hierarchicalClustering\n};\n\n// Implemented by Zoe Xi @zoexi for GSOC 2016\nvar defaults$7 = defaults({\n distance: 'euclidean',\n // distance metric to compare attributes between two nodes\n preference: 'median',\n // suitability of a data point to serve as an exemplar\n damping: 0.8,\n // damping factor between [0.5, 1)\n maxIterations: 1000,\n // max number of iterations to run\n minIterations: 100,\n // min number of iterations to run in order for clustering to stop\n attributes: [// functions to quantify the similarity between any two points\n // e.g. node => node.data('weight')\n ]\n});\n\nvar setOptions$3 = function setOptions(options) {\n var dmp = options.damping;\n var pref = options.preference;\n\n if (!(0.5 <= dmp && dmp < 1)) {\n error(\"Damping must range on [0.5, 1). Got: \".concat(dmp));\n }\n\n var validPrefs = ['median', 'mean', 'min', 'max'];\n\n if (!(validPrefs.some(function (v) {\n return v === pref;\n }) || number(pref))) {\n error(\"Preference must be one of [\".concat(validPrefs.map(function (p) {\n return \"'\".concat(p, \"'\");\n }).join(', '), \"] or a number. Got: \").concat(pref));\n }\n\n return defaults$7(options);\n};\n/* eslint-enable */\n\n\nvar getSimilarity$1 = function getSimilarity(type, n1, n2, attributes) {\n var attr = function attr(n, i) {\n return attributes[i](n);\n }; // nb negative because similarity should have an inverse relationship to distance\n\n\n return -clusteringDistance(type, attributes.length, function (i) {\n return attr(n1, i);\n }, function (i) {\n return attr(n2, i);\n }, n1, n2);\n};\n\nvar getPreference = function getPreference(S, preference) {\n // larger preference = greater # of clusters\n var p = null;\n\n if (preference === 'median') {\n p = median(S);\n } else if (preference === 'mean') {\n p = mean(S);\n } else if (preference === 'min') {\n p = min(S);\n } else if (preference === 'max') {\n p = max(S);\n } else {\n // Custom preference number, as set by user\n p = preference;\n }\n\n return p;\n};\n\nvar findExemplars = function findExemplars(n, R, A) {\n var indices = [];\n\n for (var i = 0; i < n; i++) {\n if (R[i * n + i] + A[i * n + i] > 0) {\n indices.push(i);\n }\n }\n\n return indices;\n};\n\nvar assignClusters = function assignClusters(n, S, exemplars) {\n var clusters = [];\n\n for (var i = 0; i < n; i++) {\n var index = -1;\n var max = -Infinity;\n\n for (var ei = 0; ei < exemplars.length; ei++) {\n var e = exemplars[ei];\n\n if (S[i * n + e] > max) {\n index = e;\n max = S[i * n + e];\n }\n }\n\n if (index > 0) {\n clusters.push(index);\n }\n }\n\n for (var _ei = 0; _ei < exemplars.length; _ei++) {\n clusters[exemplars[_ei]] = exemplars[_ei];\n }\n\n return clusters;\n};\n\nvar assign$2 = function assign(n, S, exemplars) {\n var clusters = assignClusters(n, S, exemplars);\n\n for (var ei = 0; ei < exemplars.length; ei++) {\n var ii = [];\n\n for (var c = 0; c < clusters.length; c++) {\n if (clusters[c] === exemplars[ei]) {\n ii.push(c);\n }\n }\n\n var maxI = -1;\n var maxSum = -Infinity;\n\n for (var i = 0; i < ii.length; i++) {\n var sum = 0;\n\n for (var j = 0; j < ii.length; j++) {\n sum += S[ii[j] * n + ii[i]];\n }\n\n if (sum > maxSum) {\n maxI = i;\n maxSum = sum;\n }\n }\n\n exemplars[ei] = ii[maxI];\n }\n\n clusters = assignClusters(n, S, exemplars);\n return clusters;\n};\n\nvar affinityPropagation = function affinityPropagation(options) {\n var cy = this.cy();\n var nodes = this.nodes();\n var opts = setOptions$3(options); // Map each node to its position in node array\n\n var id2position = {};\n\n for (var i = 0; i < nodes.length; i++) {\n id2position[nodes[i].id()] = i;\n } // Begin affinity propagation algorithm\n\n\n var n; // number of data points\n\n var n2; // size of matrices\n\n var S; // similarity matrix (1D array)\n\n var p; // preference/suitability of a data point to serve as an exemplar\n\n var R; // responsibility matrix (1D array)\n\n var A; // availability matrix (1D array)\n\n n = nodes.length;\n n2 = n * n; // Initialize and build S similarity matrix\n\n S = new Array(n2);\n\n for (var _i = 0; _i < n2; _i++) {\n S[_i] = -Infinity; // for cases where two data points shouldn't be linked together\n }\n\n for (var _i2 = 0; _i2 < n; _i2++) {\n for (var j = 0; j < n; j++) {\n if (_i2 !== j) {\n S[_i2 * n + j] = getSimilarity$1(opts.distance, nodes[_i2], nodes[j], opts.attributes);\n }\n }\n } // Place preferences on the diagonal of S\n\n\n p = getPreference(S, opts.preference);\n\n for (var _i3 = 0; _i3 < n; _i3++) {\n S[_i3 * n + _i3] = p;\n } // Initialize R responsibility matrix\n\n\n R = new Array(n2);\n\n for (var _i4 = 0; _i4 < n2; _i4++) {\n R[_i4] = 0.0;\n } // Initialize A availability matrix\n\n\n A = new Array(n2);\n\n for (var _i5 = 0; _i5 < n2; _i5++) {\n A[_i5] = 0.0;\n }\n\n var old = new Array(n);\n var Rp = new Array(n);\n var se = new Array(n);\n\n for (var _i6 = 0; _i6 < n; _i6++) {\n old[_i6] = 0.0;\n Rp[_i6] = 0.0;\n se[_i6] = 0;\n }\n\n var e = new Array(n * opts.minIterations);\n\n for (var _i7 = 0; _i7 < e.length; _i7++) {\n e[_i7] = 0;\n }\n\n var iter;\n\n for (iter = 0; iter < opts.maxIterations; iter++) {\n // main algorithmic loop\n // Update R responsibility matrix\n for (var _i8 = 0; _i8 < n; _i8++) {\n var max = -Infinity,\n max2 = -Infinity,\n maxI = -1,\n AS = 0.0;\n\n for (var _j = 0; _j < n; _j++) {\n old[_j] = R[_i8 * n + _j];\n AS = A[_i8 * n + _j] + S[_i8 * n + _j];\n\n if (AS >= max) {\n max2 = max;\n max = AS;\n maxI = _j;\n } else if (AS > max2) {\n max2 = AS;\n }\n }\n\n for (var _j2 = 0; _j2 < n; _j2++) {\n R[_i8 * n + _j2] = (1 - opts.damping) * (S[_i8 * n + _j2] - max) + opts.damping * old[_j2];\n }\n\n R[_i8 * n + maxI] = (1 - opts.damping) * (S[_i8 * n + maxI] - max2) + opts.damping * old[maxI];\n } // Update A availability matrix\n\n\n for (var _i9 = 0; _i9 < n; _i9++) {\n var sum = 0;\n\n for (var _j3 = 0; _j3 < n; _j3++) {\n old[_j3] = A[_j3 * n + _i9];\n Rp[_j3] = Math.max(0, R[_j3 * n + _i9]);\n sum += Rp[_j3];\n }\n\n sum -= Rp[_i9];\n Rp[_i9] = R[_i9 * n + _i9];\n sum += Rp[_i9];\n\n for (var _j4 = 0; _j4 < n; _j4++) {\n A[_j4 * n + _i9] = (1 - opts.damping) * Math.min(0, sum - Rp[_j4]) + opts.damping * old[_j4];\n }\n\n A[_i9 * n + _i9] = (1 - opts.damping) * (sum - Rp[_i9]) + opts.damping * old[_i9];\n } // Check for convergence\n\n\n var K = 0;\n\n for (var _i10 = 0; _i10 < n; _i10++) {\n var E = A[_i10 * n + _i10] + R[_i10 * n + _i10] > 0 ? 1 : 0;\n e[iter % opts.minIterations * n + _i10] = E;\n K += E;\n }\n\n if (K > 0 && (iter >= opts.minIterations - 1 || iter == opts.maxIterations - 1)) {\n var _sum = 0;\n\n for (var _i11 = 0; _i11 < n; _i11++) {\n se[_i11] = 0;\n\n for (var _j5 = 0; _j5 < opts.minIterations; _j5++) {\n se[_i11] += e[_j5 * n + _i11];\n }\n\n if (se[_i11] === 0 || se[_i11] === opts.minIterations) {\n _sum++;\n }\n }\n\n if (_sum === n) {\n // then we have convergence\n break;\n }\n }\n } // Identify exemplars (cluster centers)\n\n\n var exemplarsIndices = findExemplars(n, R, A); // Assign nodes to clusters\n\n var clusterIndices = assign$2(n, S, exemplarsIndices);\n var clusters = {};\n\n for (var c = 0; c < exemplarsIndices.length; c++) {\n clusters[exemplarsIndices[c]] = [];\n }\n\n for (var _i12 = 0; _i12 < nodes.length; _i12++) {\n var pos = id2position[nodes[_i12].id()];\n\n var clusterIndex = clusterIndices[pos];\n\n if (clusterIndex != null) {\n // the node may have not been assigned a cluster if no valid attributes were specified\n clusters[clusterIndex].push(nodes[_i12]);\n }\n }\n\n var retClusters = new Array(exemplarsIndices.length);\n\n for (var _c = 0; _c < exemplarsIndices.length; _c++) {\n retClusters[_c] = cy.collection(clusters[exemplarsIndices[_c]]);\n }\n\n return retClusters;\n};\n\nvar affinityPropagation$1 = {\n affinityPropagation: affinityPropagation,\n ap: affinityPropagation\n};\n\nvar hierholzerDefaults = defaults({\n root: undefined,\n directed: false\n});\nvar elesfn$b = {\n hierholzer: function hierholzer(options) {\n if (!plainObject(options)) {\n var args = arguments;\n options = {\n root: args[0],\n directed: args[1]\n };\n }\n\n var _hierholzerDefaults = hierholzerDefaults(options),\n root = _hierholzerDefaults.root,\n directed = _hierholzerDefaults.directed;\n\n var eles = this;\n var dflag = false;\n var oddIn;\n var oddOut;\n var startVertex;\n if (root) startVertex = string(root) ? this.filter(root)[0].id() : root[0].id();\n var nodes = {};\n var edges = {};\n\n if (directed) {\n eles.forEach(function (ele) {\n var id = ele.id();\n\n if (ele.isNode()) {\n var ind = ele.indegree(true);\n var outd = ele.outdegree(true);\n var d1 = ind - outd;\n var d2 = outd - ind;\n\n if (d1 == 1) {\n if (oddIn) dflag = true;else oddIn = id;\n } else if (d2 == 1) {\n if (oddOut) dflag = true;else oddOut = id;\n } else if (d2 > 1 || d1 > 1) {\n dflag = true;\n }\n\n nodes[id] = [];\n ele.outgoers().forEach(function (e) {\n if (e.isEdge()) nodes[id].push(e.id());\n });\n } else {\n edges[id] = [undefined, ele.target().id()];\n }\n });\n } else {\n eles.forEach(function (ele) {\n var id = ele.id();\n\n if (ele.isNode()) {\n var d = ele.degree(true);\n\n if (d % 2) {\n if (!oddIn) oddIn = id;else if (!oddOut) oddOut = id;else dflag = true;\n }\n\n nodes[id] = [];\n ele.connectedEdges().forEach(function (e) {\n return nodes[id].push(e.id());\n });\n } else {\n edges[id] = [ele.source().id(), ele.target().id()];\n }\n });\n }\n\n var result = {\n found: false,\n trail: undefined\n };\n if (dflag) return result;else if (oddOut && oddIn) {\n if (directed) {\n if (startVertex && oddOut != startVertex) {\n return result;\n }\n\n startVertex = oddOut;\n } else {\n if (startVertex && oddOut != startVertex && oddIn != startVertex) {\n return result;\n } else if (!startVertex) {\n startVertex = oddOut;\n }\n }\n } else {\n if (!startVertex) startVertex = eles[0].id();\n }\n\n var walk = function walk(v) {\n var currentNode = v;\n var subtour = [v];\n var adj, adjTail, adjHead;\n\n while (nodes[currentNode].length) {\n adj = nodes[currentNode].shift();\n adjTail = edges[adj][0];\n adjHead = edges[adj][1];\n\n if (currentNode != adjHead) {\n nodes[adjHead] = nodes[adjHead].filter(function (e) {\n return e != adj;\n });\n currentNode = adjHead;\n } else if (!directed && currentNode != adjTail) {\n nodes[adjTail] = nodes[adjTail].filter(function (e) {\n return e != adj;\n });\n currentNode = adjTail;\n }\n\n subtour.unshift(adj);\n subtour.unshift(currentNode);\n }\n\n return subtour;\n };\n\n var trail = [];\n var subtour = [];\n subtour = walk(startVertex);\n\n while (subtour.length != 1) {\n if (nodes[subtour[0]].length == 0) {\n trail.unshift(eles.getElementById(subtour.shift()));\n trail.unshift(eles.getElementById(subtour.shift()));\n } else {\n subtour = walk(subtour.shift()).concat(subtour);\n }\n }\n\n trail.unshift(eles.getElementById(subtour.shift())); // final node\n\n for (var d in nodes) {\n if (nodes[d].length) {\n return result;\n }\n }\n\n result.found = true;\n result.trail = this.spawn(trail);\n return result;\n }\n};\n\nvar hopcroftTarjanBiconnected = function hopcroftTarjanBiconnected() {\n var eles = this;\n var nodes = {};\n var id = 0;\n var edgeCount = 0;\n var components = [];\n var stack = [];\n var visitedEdges = {};\n\n var buildComponent = function buildComponent(x, y) {\n var i = stack.length - 1;\n var cutset = [];\n var component = eles.spawn();\n\n while (stack[i].x != x || stack[i].y != y) {\n cutset.push(stack.pop().edge);\n i--;\n }\n\n cutset.push(stack.pop().edge);\n cutset.forEach(function (edge) {\n var connectedNodes = edge.connectedNodes().intersection(eles);\n component.merge(edge);\n connectedNodes.forEach(function (node) {\n var nodeId = node.id();\n var connectedEdges = node.connectedEdges().intersection(eles);\n component.merge(node);\n\n if (!nodes[nodeId].cutVertex) {\n component.merge(connectedEdges);\n } else {\n component.merge(connectedEdges.filter(function (edge) {\n return edge.isLoop();\n }));\n }\n });\n });\n components.push(component);\n };\n\n var biconnectedSearch = function biconnectedSearch(root, currentNode, parent) {\n if (root === parent) edgeCount += 1;\n nodes[currentNode] = {\n id: id,\n low: id++,\n cutVertex: false\n };\n var edges = eles.getElementById(currentNode).connectedEdges().intersection(eles);\n\n if (edges.size() === 0) {\n components.push(eles.spawn(eles.getElementById(currentNode)));\n } else {\n var sourceId, targetId, otherNodeId, edgeId;\n edges.forEach(function (edge) {\n sourceId = edge.source().id();\n targetId = edge.target().id();\n otherNodeId = sourceId === currentNode ? targetId : sourceId;\n\n if (otherNodeId !== parent) {\n edgeId = edge.id();\n\n if (!visitedEdges[edgeId]) {\n visitedEdges[edgeId] = true;\n stack.push({\n x: currentNode,\n y: otherNodeId,\n edge: edge\n });\n }\n\n if (!(otherNodeId in nodes)) {\n biconnectedSearch(root, otherNodeId, currentNode);\n nodes[currentNode].low = Math.min(nodes[currentNode].low, nodes[otherNodeId].low);\n\n if (nodes[currentNode].id <= nodes[otherNodeId].low) {\n nodes[currentNode].cutVertex = true;\n buildComponent(currentNode, otherNodeId);\n }\n } else {\n nodes[currentNode].low = Math.min(nodes[currentNode].low, nodes[otherNodeId].id);\n }\n }\n });\n }\n };\n\n eles.forEach(function (ele) {\n if (ele.isNode()) {\n var nodeId = ele.id();\n\n if (!(nodeId in nodes)) {\n edgeCount = 0;\n biconnectedSearch(nodeId, nodeId);\n nodes[nodeId].cutVertex = edgeCount > 1;\n }\n }\n });\n var cutVertices = Object.keys(nodes).filter(function (id) {\n return nodes[id].cutVertex;\n }).map(function (id) {\n return eles.getElementById(id);\n });\n return {\n cut: eles.spawn(cutVertices),\n components: components\n };\n};\n\nvar hopcroftTarjanBiconnected$1 = {\n hopcroftTarjanBiconnected: hopcroftTarjanBiconnected,\n htbc: hopcroftTarjanBiconnected,\n htb: hopcroftTarjanBiconnected,\n hopcroftTarjanBiconnectedComponents: hopcroftTarjanBiconnected\n};\n\nvar tarjanStronglyConnected = function tarjanStronglyConnected() {\n var eles = this;\n var nodes = {};\n var index = 0;\n var components = [];\n var stack = [];\n var cut = eles.spawn(eles);\n\n var stronglyConnectedSearch = function stronglyConnectedSearch(sourceNodeId) {\n stack.push(sourceNodeId);\n nodes[sourceNodeId] = {\n index: index,\n low: index++,\n explored: false\n };\n var connectedEdges = eles.getElementById(sourceNodeId).connectedEdges().intersection(eles);\n connectedEdges.forEach(function (edge) {\n var targetNodeId = edge.target().id();\n\n if (targetNodeId !== sourceNodeId) {\n if (!(targetNodeId in nodes)) {\n stronglyConnectedSearch(targetNodeId);\n }\n\n if (!nodes[targetNodeId].explored) {\n nodes[sourceNodeId].low = Math.min(nodes[sourceNodeId].low, nodes[targetNodeId].low);\n }\n }\n });\n\n if (nodes[sourceNodeId].index === nodes[sourceNodeId].low) {\n var componentNodes = eles.spawn();\n\n for (;;) {\n var nodeId = stack.pop();\n componentNodes.merge(eles.getElementById(nodeId));\n nodes[nodeId].low = nodes[sourceNodeId].index;\n nodes[nodeId].explored = true;\n\n if (nodeId === sourceNodeId) {\n break;\n }\n }\n\n var componentEdges = componentNodes.edgesWith(componentNodes);\n var component = componentNodes.merge(componentEdges);\n components.push(component);\n cut = cut.difference(component);\n }\n };\n\n eles.forEach(function (ele) {\n if (ele.isNode()) {\n var nodeId = ele.id();\n\n if (!(nodeId in nodes)) {\n stronglyConnectedSearch(nodeId);\n }\n }\n });\n return {\n cut: cut,\n components: components\n };\n};\n\nvar tarjanStronglyConnected$1 = {\n tarjanStronglyConnected: tarjanStronglyConnected,\n tsc: tarjanStronglyConnected,\n tscc: tarjanStronglyConnected,\n tarjanStronglyConnectedComponents: tarjanStronglyConnected\n};\n\nvar elesfn$c = {};\n[elesfn, elesfn$1, elesfn$2, elesfn$3, elesfn$4, elesfn$5, elesfn$6, elesfn$7, elesfn$8, elesfn$9, elesfn$a, markovClustering$1, kClustering, hierarchicalClustering$1, affinityPropagation$1, elesfn$b, hopcroftTarjanBiconnected$1, tarjanStronglyConnected$1].forEach(function (props) {\n extend(elesfn$c, props);\n});\n\n/*!\nEmbeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable\nCopyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com)\nLicensed under The MIT License (http://opensource.org/licenses/MIT)\n*/\n\n/* promise states [Promises/A+ 2.1] */\nvar STATE_PENDING = 0;\n/* [Promises/A+ 2.1.1] */\n\nvar STATE_FULFILLED = 1;\n/* [Promises/A+ 2.1.2] */\n\nvar STATE_REJECTED = 2;\n/* [Promises/A+ 2.1.3] */\n\n/* promise object constructor */\n\nvar api = function api(executor) {\n /* optionally support non-constructor/plain-function call */\n if (!(this instanceof api)) return new api(executor);\n /* initialize object */\n\n this.id = 'Thenable/1.0.7';\n this.state = STATE_PENDING;\n /* initial state */\n\n this.fulfillValue = undefined;\n /* initial value */\n\n /* [Promises/A+ 1.3, 2.1.2.2] */\n\n this.rejectReason = undefined;\n /* initial reason */\n\n /* [Promises/A+ 1.5, 2.1.3.2] */\n\n this.onFulfilled = [];\n /* initial handlers */\n\n this.onRejected = [];\n /* initial handlers */\n\n /* provide optional information-hiding proxy */\n\n this.proxy = {\n then: this.then.bind(this)\n };\n /* support optional executor function */\n\n if (typeof executor === 'function') executor.call(this, this.fulfill.bind(this), this.reject.bind(this));\n};\n/* promise API methods */\n\n\napi.prototype = {\n /* promise resolving methods */\n fulfill: function fulfill(value) {\n return deliver(this, STATE_FULFILLED, 'fulfillValue', value);\n },\n reject: function reject(value) {\n return deliver(this, STATE_REJECTED, 'rejectReason', value);\n },\n\n /* \"The then Method\" [Promises/A+ 1.1, 1.2, 2.2] */\n then: function then(onFulfilled, onRejected) {\n var curr = this;\n var next = new api();\n /* [Promises/A+ 2.2.7] */\n\n curr.onFulfilled.push(resolver(onFulfilled, next, 'fulfill'));\n /* [Promises/A+ 2.2.2/2.2.6] */\n\n curr.onRejected.push(resolver(onRejected, next, 'reject'));\n /* [Promises/A+ 2.2.3/2.2.6] */\n\n execute(curr);\n return next.proxy;\n /* [Promises/A+ 2.2.7, 3.3] */\n }\n};\n/* deliver an action */\n\nvar deliver = function deliver(curr, state, name, value) {\n if (curr.state === STATE_PENDING) {\n curr.state = state;\n /* [Promises/A+ 2.1.2.1, 2.1.3.1] */\n\n curr[name] = value;\n /* [Promises/A+ 2.1.2.2, 2.1.3.2] */\n\n execute(curr);\n }\n\n return curr;\n};\n/* execute all handlers */\n\n\nvar execute = function execute(curr) {\n if (curr.state === STATE_FULFILLED) execute_handlers(curr, 'onFulfilled', curr.fulfillValue);else if (curr.state === STATE_REJECTED) execute_handlers(curr, 'onRejected', curr.rejectReason);\n};\n/* execute particular set of handlers */\n\n\nvar execute_handlers = function execute_handlers(curr, name, value) {\n /* global setImmediate: true */\n\n /* global setTimeout: true */\n\n /* short-circuit processing */\n if (curr[name].length === 0) return;\n /* iterate over all handlers, exactly once */\n\n var handlers = curr[name];\n curr[name] = [];\n /* [Promises/A+ 2.2.2.3, 2.2.3.3] */\n\n var func = function func() {\n for (var i = 0; i < handlers.length; i++) {\n handlers[i](value);\n }\n /* [Promises/A+ 2.2.5] */\n\n };\n /* execute procedure asynchronously */\n\n /* [Promises/A+ 2.2.4, 3.1] */\n\n\n if (typeof setImmediate === 'function') setImmediate(func);else setTimeout(func, 0);\n};\n/* generate a resolver function */\n\n\nvar resolver = function resolver(cb, next, method) {\n return function (value) {\n if (typeof cb !== 'function')\n /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */\n next[method].call(next, value);\n /* [Promises/A+ 2.2.7.3, 2.2.7.4] */\n else {\n var result;\n\n try {\n result = cb(value);\n }\n /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */\n catch (e) {\n next.reject(e);\n /* [Promises/A+ 2.2.7.2] */\n\n return;\n }\n\n resolve(next, result);\n /* [Promises/A+ 2.2.7.1] */\n }\n };\n};\n/* \"Promise Resolution Procedure\" */\n\n/* [Promises/A+ 2.3] */\n\n\nvar resolve = function resolve(promise, x) {\n /* sanity check arguments */\n\n /* [Promises/A+ 2.3.1] */\n if (promise === x || promise.proxy === x) {\n promise.reject(new TypeError('cannot resolve promise with itself'));\n return;\n }\n /* surgically check for a \"then\" method\n (mainly to just call the \"getter\" of \"then\" only once) */\n\n\n var then;\n\n if (_typeof(x) === 'object' && x !== null || typeof x === 'function') {\n try {\n then = x.then;\n }\n /* [Promises/A+ 2.3.3.1, 3.5] */\n catch (e) {\n promise.reject(e);\n /* [Promises/A+ 2.3.3.2] */\n\n return;\n }\n }\n /* handle own Thenables [Promises/A+ 2.3.2]\n and similar \"thenables\" [Promises/A+ 2.3.3] */\n\n\n if (typeof then === 'function') {\n var resolved = false;\n\n try {\n /* call retrieved \"then\" method */\n\n /* [Promises/A+ 2.3.3.3] */\n then.call(x,\n /* resolvePromise */\n\n /* [Promises/A+ 2.3.3.3.1] */\n function (y) {\n if (resolved) return;\n resolved = true;\n /* [Promises/A+ 2.3.3.3.3] */\n\n if (y === x)\n /* [Promises/A+ 3.6] */\n promise.reject(new TypeError('circular thenable chain'));else resolve(promise, y);\n },\n /* rejectPromise */\n\n /* [Promises/A+ 2.3.3.3.2] */\n function (r) {\n if (resolved) return;\n resolved = true;\n /* [Promises/A+ 2.3.3.3.3] */\n\n promise.reject(r);\n });\n } catch (e) {\n if (!resolved)\n /* [Promises/A+ 2.3.3.3.3] */\n promise.reject(e);\n /* [Promises/A+ 2.3.3.3.4] */\n }\n\n return;\n }\n /* handle other values */\n\n\n promise.fulfill(x);\n /* [Promises/A+ 2.3.4, 2.3.3.4] */\n}; // so we always have Promise.all()\n\n\napi.all = function (ps) {\n return new api(function (resolveAll, rejectAll) {\n var vals = new Array(ps.length);\n var doneCount = 0;\n\n var fulfill = function fulfill(i, val) {\n vals[i] = val;\n doneCount++;\n\n if (doneCount === ps.length) {\n resolveAll(vals);\n }\n };\n\n for (var i = 0; i < ps.length; i++) {\n (function (i) {\n var p = ps[i];\n var isPromise = p != null && p.then != null;\n\n if (isPromise) {\n p.then(function (val) {\n fulfill(i, val);\n }, function (err) {\n rejectAll(err);\n });\n } else {\n var val = p;\n fulfill(i, val);\n }\n })(i);\n }\n });\n};\n\napi.resolve = function (val) {\n return new api(function (resolve, reject) {\n resolve(val);\n });\n};\n\napi.reject = function (val) {\n return new api(function (resolve, reject) {\n reject(val);\n });\n};\n\nvar Promise$1 = typeof Promise !== 'undefined' ? Promise : api; // eslint-disable-line no-undef\n\nvar Animation = function Animation(target, opts, opts2) {\n var isCore = core(target);\n var isEle = !isCore;\n\n var _p = this._private = extend({\n duration: 1000\n }, opts, opts2);\n\n _p.target = target;\n _p.style = _p.style || _p.css;\n _p.started = false;\n _p.playing = false;\n _p.hooked = false;\n _p.applying = false;\n _p.progress = 0;\n _p.completes = [];\n _p.frames = [];\n\n if (_p.complete && fn(_p.complete)) {\n _p.completes.push(_p.complete);\n }\n\n if (isEle) {\n var pos = target.position();\n _p.startPosition = _p.startPosition || {\n x: pos.x,\n y: pos.y\n };\n _p.startStyle = _p.startStyle || target.cy().style().getAnimationStartStyle(target, _p.style);\n }\n\n if (isCore) {\n var pan = target.pan();\n _p.startPan = {\n x: pan.x,\n y: pan.y\n };\n _p.startZoom = target.zoom();\n } // for future timeline/animations impl\n\n\n this.length = 1;\n this[0] = this;\n};\n\nvar anifn = Animation.prototype;\nextend(anifn, {\n instanceString: function instanceString() {\n return 'animation';\n },\n hook: function hook() {\n var _p = this._private;\n\n if (!_p.hooked) {\n // add to target's animation queue\n var q;\n var tAni = _p.target._private.animation;\n\n if (_p.queue) {\n q = tAni.queue;\n } else {\n q = tAni.current;\n }\n\n q.push(this); // add to the animation loop pool\n\n if (elementOrCollection(_p.target)) {\n _p.target.cy().addToAnimationPool(_p.target);\n }\n\n _p.hooked = true;\n }\n\n return this;\n },\n play: function play() {\n var _p = this._private; // autorewind\n\n if (_p.progress === 1) {\n _p.progress = 0;\n }\n\n _p.playing = true;\n _p.started = false; // needs to be started by animation loop\n\n _p.stopped = false;\n this.hook(); // the animation loop will start the animation...\n\n return this;\n },\n playing: function playing() {\n return this._private.playing;\n },\n apply: function apply() {\n var _p = this._private;\n _p.applying = true;\n _p.started = false; // needs to be started by animation loop\n\n _p.stopped = false;\n this.hook(); // the animation loop will apply the animation at this progress\n\n return this;\n },\n applying: function applying() {\n return this._private.applying;\n },\n pause: function pause() {\n var _p = this._private;\n _p.playing = false;\n _p.started = false;\n return this;\n },\n stop: function stop() {\n var _p = this._private;\n _p.playing = false;\n _p.started = false;\n _p.stopped = true; // to be removed from animation queues\n\n return this;\n },\n rewind: function rewind() {\n return this.progress(0);\n },\n fastforward: function fastforward() {\n return this.progress(1);\n },\n time: function time(t) {\n var _p = this._private;\n\n if (t === undefined) {\n return _p.progress * _p.duration;\n } else {\n return this.progress(t / _p.duration);\n }\n },\n progress: function progress(p) {\n var _p = this._private;\n var wasPlaying = _p.playing;\n\n if (p === undefined) {\n return _p.progress;\n } else {\n if (wasPlaying) {\n this.pause();\n }\n\n _p.progress = p;\n _p.started = false;\n\n if (wasPlaying) {\n this.play();\n }\n }\n\n return this;\n },\n completed: function completed() {\n return this._private.progress === 1;\n },\n reverse: function reverse() {\n var _p = this._private;\n var wasPlaying = _p.playing;\n\n if (wasPlaying) {\n this.pause();\n }\n\n _p.progress = 1 - _p.progress;\n _p.started = false;\n\n var swap = function swap(a, b) {\n var _pa = _p[a];\n\n if (_pa == null) {\n return;\n }\n\n _p[a] = _p[b];\n _p[b] = _pa;\n };\n\n swap('zoom', 'startZoom');\n swap('pan', 'startPan');\n swap('position', 'startPosition'); // swap styles\n\n if (_p.style) {\n for (var i = 0; i < _p.style.length; i++) {\n var prop = _p.style[i];\n var name = prop.name;\n var startStyleProp = _p.startStyle[name];\n _p.startStyle[name] = prop;\n _p.style[i] = startStyleProp;\n }\n }\n\n if (wasPlaying) {\n this.play();\n }\n\n return this;\n },\n promise: function promise(type) {\n var _p = this._private;\n var arr;\n\n switch (type) {\n case 'frame':\n arr = _p.frames;\n break;\n\n default:\n case 'complete':\n case 'completed':\n arr = _p.completes;\n }\n\n return new Promise$1(function (resolve, reject) {\n arr.push(function () {\n resolve();\n });\n });\n }\n});\nanifn.complete = anifn.completed;\nanifn.run = anifn.play;\nanifn.running = anifn.playing;\n\nvar define = {\n animated: function animated() {\n return function animatedImpl() {\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n var cy = this._private.cy || this;\n\n if (!cy.styleEnabled()) {\n return false;\n }\n\n var ele = all[0];\n\n if (ele) {\n return ele._private.animation.current.length > 0;\n }\n };\n },\n // animated\n clearQueue: function clearQueue() {\n return function clearQueueImpl() {\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n var cy = this._private.cy || this;\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n for (var i = 0; i < all.length; i++) {\n var ele = all[i];\n ele._private.animation.queue = [];\n }\n\n return this;\n };\n },\n // clearQueue\n delay: function delay() {\n return function delayImpl(time, complete) {\n var cy = this._private.cy || this;\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n return this.animate({\n delay: time,\n duration: time,\n complete: complete\n });\n };\n },\n // delay\n delayAnimation: function delayAnimation() {\n return function delayAnimationImpl(time, complete) {\n var cy = this._private.cy || this;\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n return this.animation({\n delay: time,\n duration: time,\n complete: complete\n });\n };\n },\n // delay\n animation: function animation() {\n return function animationImpl(properties, params) {\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n var cy = this._private.cy || this;\n var isCore = !selfIsArrayLike;\n var isEles = !isCore;\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n var style = cy.style();\n properties = extend({}, properties, params);\n var propertiesEmpty = Object.keys(properties).length === 0;\n\n if (propertiesEmpty) {\n return new Animation(all[0], properties); // nothing to animate\n }\n\n if (properties.duration === undefined) {\n properties.duration = 400;\n }\n\n switch (properties.duration) {\n case 'slow':\n properties.duration = 600;\n break;\n\n case 'fast':\n properties.duration = 200;\n break;\n }\n\n if (isEles) {\n properties.style = style.getPropsList(properties.style || properties.css);\n properties.css = undefined;\n }\n\n if (isEles && properties.renderedPosition != null) {\n var rpos = properties.renderedPosition;\n var pan = cy.pan();\n var zoom = cy.zoom();\n properties.position = renderedToModelPosition(rpos, zoom, pan);\n } // override pan w/ panBy if set\n\n\n if (isCore && properties.panBy != null) {\n var panBy = properties.panBy;\n var cyPan = cy.pan();\n properties.pan = {\n x: cyPan.x + panBy.x,\n y: cyPan.y + panBy.y\n };\n } // override pan w/ center if set\n\n\n var center = properties.center || properties.centre;\n\n if (isCore && center != null) {\n var centerPan = cy.getCenterPan(center.eles, properties.zoom);\n\n if (centerPan != null) {\n properties.pan = centerPan;\n }\n } // override pan & zoom w/ fit if set\n\n\n if (isCore && properties.fit != null) {\n var fit = properties.fit;\n var fitVp = cy.getFitViewport(fit.eles || fit.boundingBox, fit.padding);\n\n if (fitVp != null) {\n properties.pan = fitVp.pan;\n properties.zoom = fitVp.zoom;\n }\n } // override zoom (& potentially pan) w/ zoom obj if set\n\n\n if (isCore && plainObject(properties.zoom)) {\n var vp = cy.getZoomedViewport(properties.zoom);\n\n if (vp != null) {\n if (vp.zoomed) {\n properties.zoom = vp.zoom;\n }\n\n if (vp.panned) {\n properties.pan = vp.pan;\n }\n } else {\n properties.zoom = null; // an inavalid zoom (e.g. no delta) gets automatically destroyed\n }\n }\n\n return new Animation(all[0], properties);\n };\n },\n // animate\n animate: function animate() {\n return function animateImpl(properties, params) {\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n var cy = this._private.cy || this;\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n if (params) {\n properties = extend({}, properties, params);\n } // manually hook and run the animation\n\n\n for (var i = 0; i < all.length; i++) {\n var ele = all[i];\n var queue = ele.animated() && (properties.queue === undefined || properties.queue);\n var ani = ele.animation(properties, queue ? {\n queue: true\n } : undefined);\n ani.play();\n }\n\n return this; // chaining\n };\n },\n // animate\n stop: function stop() {\n return function stopImpl(clearQueue, jumpToEnd) {\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n var cy = this._private.cy || this;\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n for (var i = 0; i < all.length; i++) {\n var ele = all[i];\n var _p = ele._private;\n var anis = _p.animation.current;\n\n for (var j = 0; j < anis.length; j++) {\n var ani = anis[j];\n var ani_p = ani._private;\n\n if (jumpToEnd) {\n // next iteration of the animation loop, the animation\n // will go straight to the end and be removed\n ani_p.duration = 0;\n }\n } // clear the queue of future animations\n\n\n if (clearQueue) {\n _p.animation.queue = [];\n }\n\n if (!jumpToEnd) {\n _p.animation.current = [];\n }\n } // we have to notify (the animation loop doesn't do it for us on `stop`)\n\n\n cy.notify('draw');\n return this;\n };\n } // stop\n\n}; // define\n\nvar define$1 = {\n // access data field\n data: function data(params) {\n var defaults = {\n field: 'data',\n bindingEvent: 'data',\n allowBinding: false,\n allowSetting: false,\n allowGetting: false,\n settingEvent: 'data',\n settingTriggersEvent: false,\n triggerFnName: 'trigger',\n immutableKeys: {},\n // key => true if immutable\n updateStyle: false,\n beforeGet: function beforeGet(self) {},\n beforeSet: function beforeSet(self, obj) {},\n onSet: function onSet(self) {},\n canSet: function canSet(self) {\n return true;\n }\n };\n params = extend({}, defaults, params);\n return function dataImpl(name, value) {\n var p = params;\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n var single = selfIsArrayLike ? self[0] : self; // .data('foo', ...)\n\n if (string(name)) {\n // set or get property\n // .data('foo')\n if (p.allowGetting && value === undefined) {\n // get\n var ret;\n\n if (single) {\n p.beforeGet(single);\n ret = single._private[p.field][name];\n }\n\n return ret; // .data('foo', 'bar')\n } else if (p.allowSetting && value !== undefined) {\n // set\n var valid = !p.immutableKeys[name];\n\n if (valid) {\n var change = _defineProperty({}, name, value);\n\n p.beforeSet(self, change);\n\n for (var i = 0, l = all.length; i < l; i++) {\n var ele = all[i];\n\n if (p.canSet(ele)) {\n ele._private[p.field][name] = value;\n }\n } // update mappers if asked\n\n\n if (p.updateStyle) {\n self.updateStyle();\n } // call onSet callback\n\n\n p.onSet(self);\n\n if (p.settingTriggersEvent) {\n self[p.triggerFnName](p.settingEvent);\n }\n }\n } // .data({ 'foo': 'bar' })\n\n } else if (p.allowSetting && plainObject(name)) {\n // extend\n var obj = name;\n var k, v;\n var keys = Object.keys(obj);\n p.beforeSet(self, obj);\n\n for (var _i = 0; _i < keys.length; _i++) {\n k = keys[_i];\n v = obj[k];\n\n var _valid = !p.immutableKeys[k];\n\n if (_valid) {\n for (var j = 0; j < all.length; j++) {\n var _ele = all[j];\n\n if (p.canSet(_ele)) {\n _ele._private[p.field][k] = v;\n }\n }\n }\n } // update mappers if asked\n\n\n if (p.updateStyle) {\n self.updateStyle();\n } // call onSet callback\n\n\n p.onSet(self);\n\n if (p.settingTriggersEvent) {\n self[p.triggerFnName](p.settingEvent);\n } // .data(function(){ ... })\n\n } else if (p.allowBinding && fn(name)) {\n // bind to event\n var fn$1 = name;\n self.on(p.bindingEvent, fn$1); // .data()\n } else if (p.allowGetting && name === undefined) {\n // get whole object\n var _ret;\n\n if (single) {\n p.beforeGet(single);\n _ret = single._private[p.field];\n }\n\n return _ret;\n }\n\n return self; // maintain chainability\n }; // function\n },\n // data\n // remove data field\n removeData: function removeData(params) {\n var defaults = {\n field: 'data',\n event: 'data',\n triggerFnName: 'trigger',\n triggerEvent: false,\n immutableKeys: {} // key => true if immutable\n\n };\n params = extend({}, defaults, params);\n return function removeDataImpl(names) {\n var p = params;\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n // .removeData('foo bar')\n\n if (string(names)) {\n // then get the list of keys, and delete them\n var keys = names.split(/\\s+/);\n var l = keys.length;\n\n for (var i = 0; i < l; i++) {\n // delete each non-empty key\n var key = keys[i];\n\n if (emptyString(key)) {\n continue;\n }\n\n var valid = !p.immutableKeys[key]; // not valid if immutable\n\n if (valid) {\n for (var i_a = 0, l_a = all.length; i_a < l_a; i_a++) {\n all[i_a]._private[p.field][key] = undefined;\n }\n }\n }\n\n if (p.triggerEvent) {\n self[p.triggerFnName](p.event);\n } // .removeData()\n\n } else if (names === undefined) {\n // then delete all keys\n for (var _i_a = 0, _l_a = all.length; _i_a < _l_a; _i_a++) {\n var _privateFields = all[_i_a]._private[p.field];\n\n var _keys = Object.keys(_privateFields);\n\n for (var _i2 = 0; _i2 < _keys.length; _i2++) {\n var _key = _keys[_i2];\n var validKeyToDelete = !p.immutableKeys[_key];\n\n if (validKeyToDelete) {\n _privateFields[_key] = undefined;\n }\n }\n }\n\n if (p.triggerEvent) {\n self[p.triggerFnName](p.event);\n }\n }\n\n return self; // maintain chaining\n }; // function\n } // removeData\n\n}; // define\n\nvar define$2 = {\n eventAliasesOn: function eventAliasesOn(proto) {\n var p = proto;\n p.addListener = p.listen = p.bind = p.on;\n p.unlisten = p.unbind = p.off = p.removeListener;\n p.trigger = p.emit; // this is just a wrapper alias of .on()\n\n p.pon = p.promiseOn = function (events, selector) {\n var self = this;\n var args = Array.prototype.slice.call(arguments, 0);\n return new Promise$1(function (resolve, reject) {\n var callback = function callback(e) {\n self.off.apply(self, offArgs);\n resolve(e);\n };\n\n var onArgs = args.concat([callback]);\n var offArgs = onArgs.concat([]);\n self.on.apply(self, onArgs);\n });\n };\n }\n}; // define\n\n// use this module to cherry pick functions into your prototype\nvar define$3 = {};\n[define, define$1, define$2].forEach(function (m) {\n extend(define$3, m);\n});\n\nvar elesfn$d = {\n animate: define$3.animate(),\n animation: define$3.animation(),\n animated: define$3.animated(),\n clearQueue: define$3.clearQueue(),\n delay: define$3.delay(),\n delayAnimation: define$3.delayAnimation(),\n stop: define$3.stop()\n};\n\nvar elesfn$e = {\n classes: function classes(_classes) {\n var self = this;\n\n if (_classes === undefined) {\n var ret = [];\n\n self[0]._private.classes.forEach(function (cls) {\n return ret.push(cls);\n });\n\n return ret;\n } else if (!array(_classes)) {\n // extract classes from string\n _classes = (_classes || '').match(/\\S+/g) || [];\n }\n\n var changed = [];\n var classesSet = new Set$1(_classes); // check and update each ele\n\n for (var j = 0; j < self.length; j++) {\n var ele = self[j];\n var _p = ele._private;\n var eleClasses = _p.classes;\n var changedEle = false; // check if ele has all of the passed classes\n\n for (var i = 0; i < _classes.length; i++) {\n var cls = _classes[i];\n var eleHasClass = eleClasses.has(cls);\n\n if (!eleHasClass) {\n changedEle = true;\n break;\n }\n } // check if ele has classes outside of those passed\n\n\n if (!changedEle) {\n changedEle = eleClasses.size !== _classes.length;\n }\n\n if (changedEle) {\n _p.classes = classesSet;\n changed.push(ele);\n }\n } // trigger update style on those eles that had class changes\n\n\n if (changed.length > 0) {\n this.spawn(changed).updateStyle().emit('class');\n }\n\n return self;\n },\n addClass: function addClass(classes) {\n return this.toggleClass(classes, true);\n },\n hasClass: function hasClass(className) {\n var ele = this[0];\n return ele != null && ele._private.classes.has(className);\n },\n toggleClass: function toggleClass(classes, toggle) {\n if (!array(classes)) {\n // extract classes from string\n classes = classes.match(/\\S+/g) || [];\n }\n\n var self = this;\n var toggleUndefd = toggle === undefined;\n var changed = []; // eles who had classes changed\n\n for (var i = 0, il = self.length; i < il; i++) {\n var ele = self[i];\n var eleClasses = ele._private.classes;\n var changedEle = false;\n\n for (var j = 0; j < classes.length; j++) {\n var cls = classes[j];\n var hasClass = eleClasses.has(cls);\n var changedNow = false;\n\n if (toggle || toggleUndefd && !hasClass) {\n eleClasses.add(cls);\n changedNow = true;\n } else if (!toggle || toggleUndefd && hasClass) {\n eleClasses[\"delete\"](cls);\n changedNow = true;\n }\n\n if (!changedEle && changedNow) {\n changed.push(ele);\n changedEle = true;\n }\n } // for j classes\n\n } // for i eles\n // trigger update style on those eles that had class changes\n\n\n if (changed.length > 0) {\n this.spawn(changed).updateStyle().emit('class');\n }\n\n return self;\n },\n removeClass: function removeClass(classes) {\n return this.toggleClass(classes, false);\n },\n flashClass: function flashClass(classes, duration) {\n var self = this;\n\n if (duration == null) {\n duration = 250;\n } else if (duration === 0) {\n return self; // nothing to do really\n }\n\n self.addClass(classes);\n setTimeout(function () {\n self.removeClass(classes);\n }, duration);\n return self;\n }\n};\nelesfn$e.className = elesfn$e.classNames = elesfn$e.classes;\n\nvar tokens = {\n metaChar: '[\\\\!\\\\\"\\\\#\\\\$\\\\%\\\\&\\\\\\'\\\\(\\\\)\\\\*\\\\+\\\\,\\\\.\\\\/\\\\:\\\\;\\\\<\\\\=\\\\>\\\\?\\\\@\\\\[\\\\]\\\\^\\\\`\\\\{\\\\|\\\\}\\\\~]',\n // chars we need to escape in let names, etc\n comparatorOp: '=|\\\\!=|>|>=|<|<=|\\\\$=|\\\\^=|\\\\*=',\n // binary comparison op (used in data selectors)\n boolOp: '\\\\?|\\\\!|\\\\^',\n // boolean (unary) operators (used in data selectors)\n string: '\"(?:\\\\\\\\\"|[^\"])*\"' + '|' + \"'(?:\\\\\\\\'|[^'])*'\",\n // string literals (used in data selectors) -- doublequotes | singlequotes\n number: number$1,\n // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123\n meta: 'degree|indegree|outdegree',\n // allowed metadata fields (i.e. allowed functions to use from Collection)\n separator: '\\\\s*,\\\\s*',\n // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass\n descendant: '\\\\s+',\n child: '\\\\s+>\\\\s+',\n subject: '\\\\$',\n group: 'node|edge|\\\\*',\n directedEdge: '\\\\s+->\\\\s+',\n undirectedEdge: '\\\\s+<->\\\\s+'\n};\ntokens.variable = '(?:[\\\\w-]|(?:\\\\\\\\' + tokens.metaChar + '))+'; // a variable name\n\ntokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number\n\ntokens.className = tokens.variable; // a class name (follows variable conventions)\n\ntokens.id = tokens.variable; // an element id (follows variable conventions)\n\n(function () {\n var ops, op, i; // add @ variants to comparatorOp\n\n ops = tokens.comparatorOp.split('|');\n\n for (i = 0; i < ops.length; i++) {\n op = ops[i];\n tokens.comparatorOp += '|@' + op;\n } // add ! variants to comparatorOp\n\n\n ops = tokens.comparatorOp.split('|');\n\n for (i = 0; i < ops.length; i++) {\n op = ops[i];\n\n if (op.indexOf('!') >= 0) {\n continue;\n } // skip ops that explicitly contain !\n\n\n if (op === '=') {\n continue;\n } // skip = b/c != is explicitly defined\n\n\n tokens.comparatorOp += '|\\\\!' + op;\n }\n})();\n\n/**\n * Make a new query object\n *\n * @prop type {Type} The type enum (int) of the query\n * @prop checks List of checks to make against an ele to test for a match\n */\nvar newQuery = function newQuery() {\n return {\n checks: []\n };\n};\n\n/**\n * A check type enum-like object. Uses integer values for fast match() lookup.\n * The ordering does not matter as long as the ints are unique.\n */\nvar Type = {\n /** E.g. node */\n GROUP: 0,\n\n /** A collection of elements */\n COLLECTION: 1,\n\n /** A filter(ele) function */\n FILTER: 2,\n\n /** E.g. [foo > 1] */\n DATA_COMPARE: 3,\n\n /** E.g. [foo] */\n DATA_EXIST: 4,\n\n /** E.g. [?foo] */\n DATA_BOOL: 5,\n\n /** E.g. [[degree > 2]] */\n META_COMPARE: 6,\n\n /** E.g. :selected */\n STATE: 7,\n\n /** E.g. #foo */\n ID: 8,\n\n /** E.g. .foo */\n CLASS: 9,\n\n /** E.g. #foo <-> #bar */\n UNDIRECTED_EDGE: 10,\n\n /** E.g. #foo -> #bar */\n DIRECTED_EDGE: 11,\n\n /** E.g. $#foo -> #bar */\n NODE_SOURCE: 12,\n\n /** E.g. #foo -> $#bar */\n NODE_TARGET: 13,\n\n /** E.g. $#foo <-> #bar */\n NODE_NEIGHBOR: 14,\n\n /** E.g. #foo > #bar */\n CHILD: 15,\n\n /** E.g. #foo #bar */\n DESCENDANT: 16,\n\n /** E.g. $#foo > #bar */\n PARENT: 17,\n\n /** E.g. $#foo #bar */\n ANCESTOR: 18,\n\n /** E.g. #foo > $bar > #baz */\n COMPOUND_SPLIT: 19,\n\n /** Always matches, useful placeholder for subject in `COMPOUND_SPLIT` */\n TRUE: 20\n};\n\nvar stateSelectors = [{\n selector: ':selected',\n matches: function matches(ele) {\n return ele.selected();\n }\n}, {\n selector: ':unselected',\n matches: function matches(ele) {\n return !ele.selected();\n }\n}, {\n selector: ':selectable',\n matches: function matches(ele) {\n return ele.selectable();\n }\n}, {\n selector: ':unselectable',\n matches: function matches(ele) {\n return !ele.selectable();\n }\n}, {\n selector: ':locked',\n matches: function matches(ele) {\n return ele.locked();\n }\n}, {\n selector: ':unlocked',\n matches: function matches(ele) {\n return !ele.locked();\n }\n}, {\n selector: ':visible',\n matches: function matches(ele) {\n return ele.visible();\n }\n}, {\n selector: ':hidden',\n matches: function matches(ele) {\n return !ele.visible();\n }\n}, {\n selector: ':transparent',\n matches: function matches(ele) {\n return ele.transparent();\n }\n}, {\n selector: ':grabbed',\n matches: function matches(ele) {\n return ele.grabbed();\n }\n}, {\n selector: ':free',\n matches: function matches(ele) {\n return !ele.grabbed();\n }\n}, {\n selector: ':removed',\n matches: function matches(ele) {\n return ele.removed();\n }\n}, {\n selector: ':inside',\n matches: function matches(ele) {\n return !ele.removed();\n }\n}, {\n selector: ':grabbable',\n matches: function matches(ele) {\n return ele.grabbable();\n }\n}, {\n selector: ':ungrabbable',\n matches: function matches(ele) {\n return !ele.grabbable();\n }\n}, {\n selector: ':animated',\n matches: function matches(ele) {\n return ele.animated();\n }\n}, {\n selector: ':unanimated',\n matches: function matches(ele) {\n return !ele.animated();\n }\n}, {\n selector: ':parent',\n matches: function matches(ele) {\n return ele.isParent();\n }\n}, {\n selector: ':childless',\n matches: function matches(ele) {\n return ele.isChildless();\n }\n}, {\n selector: ':child',\n matches: function matches(ele) {\n return ele.isChild();\n }\n}, {\n selector: ':orphan',\n matches: function matches(ele) {\n return ele.isOrphan();\n }\n}, {\n selector: ':nonorphan',\n matches: function matches(ele) {\n return ele.isChild();\n }\n}, {\n selector: ':compound',\n matches: function matches(ele) {\n if (ele.isNode()) {\n return ele.isParent();\n } else {\n return ele.source().isParent() || ele.target().isParent();\n }\n }\n}, {\n selector: ':loop',\n matches: function matches(ele) {\n return ele.isLoop();\n }\n}, {\n selector: ':simple',\n matches: function matches(ele) {\n return ele.isSimple();\n }\n}, {\n selector: ':active',\n matches: function matches(ele) {\n return ele.active();\n }\n}, {\n selector: ':inactive',\n matches: function matches(ele) {\n return !ele.active();\n }\n}, {\n selector: ':backgrounding',\n matches: function matches(ele) {\n return ele.backgrounding();\n }\n}, {\n selector: ':nonbackgrounding',\n matches: function matches(ele) {\n return !ele.backgrounding();\n }\n}].sort(function (a, b) {\n // n.b. selectors that are starting substrings of others must have the longer ones first\n return descending(a.selector, b.selector);\n});\n\nvar lookup = function () {\n var selToFn = {};\n var s;\n\n for (var i = 0; i < stateSelectors.length; i++) {\n s = stateSelectors[i];\n selToFn[s.selector] = s.matches;\n }\n\n return selToFn;\n}();\n\nvar stateSelectorMatches = function stateSelectorMatches(sel, ele) {\n return lookup[sel](ele);\n};\nvar stateSelectorRegex = '(' + stateSelectors.map(function (s) {\n return s.selector;\n}).join('|') + ')';\n\n// so that values get compared properly in Selector.filter()\n\nvar cleanMetaChars = function cleanMetaChars(str) {\n return str.replace(new RegExp('\\\\\\\\(' + tokens.metaChar + ')', 'g'), function (match, $1) {\n return $1;\n });\n};\n\nvar replaceLastQuery = function replaceLastQuery(selector, examiningQuery, replacementQuery) {\n selector[selector.length - 1] = replacementQuery;\n}; // NOTE: add new expression syntax here to have it recognised by the parser;\n// - a query contains all adjacent (i.e. no separator in between) expressions;\n// - the current query is stored in selector[i]\n// - you need to check the query objects in match() for it actually filter properly, but that's pretty straight forward\n\n\nvar exprs = [{\n name: 'group',\n // just used for identifying when debugging\n query: true,\n regex: '(' + tokens.group + ')',\n populate: function populate(selector, query, _ref) {\n var _ref2 = _slicedToArray(_ref, 1),\n group = _ref2[0];\n\n query.checks.push({\n type: Type.GROUP,\n value: group === '*' ? group : group + 's'\n });\n }\n}, {\n name: 'state',\n query: true,\n regex: stateSelectorRegex,\n populate: function populate(selector, query, _ref3) {\n var _ref4 = _slicedToArray(_ref3, 1),\n state = _ref4[0];\n\n query.checks.push({\n type: Type.STATE,\n value: state\n });\n }\n}, {\n name: 'id',\n query: true,\n regex: '\\\\#(' + tokens.id + ')',\n populate: function populate(selector, query, _ref5) {\n var _ref6 = _slicedToArray(_ref5, 1),\n id = _ref6[0];\n\n query.checks.push({\n type: Type.ID,\n value: cleanMetaChars(id)\n });\n }\n}, {\n name: 'className',\n query: true,\n regex: '\\\\.(' + tokens.className + ')',\n populate: function populate(selector, query, _ref7) {\n var _ref8 = _slicedToArray(_ref7, 1),\n className = _ref8[0];\n\n query.checks.push({\n type: Type.CLASS,\n value: cleanMetaChars(className)\n });\n }\n}, {\n name: 'dataExists',\n query: true,\n regex: '\\\\[\\\\s*(' + tokens.variable + ')\\\\s*\\\\]',\n populate: function populate(selector, query, _ref9) {\n var _ref10 = _slicedToArray(_ref9, 1),\n variable = _ref10[0];\n\n query.checks.push({\n type: Type.DATA_EXIST,\n field: cleanMetaChars(variable)\n });\n }\n}, {\n name: 'dataCompare',\n query: true,\n regex: '\\\\[\\\\s*(' + tokens.variable + ')\\\\s*(' + tokens.comparatorOp + ')\\\\s*(' + tokens.value + ')\\\\s*\\\\]',\n populate: function populate(selector, query, _ref11) {\n var _ref12 = _slicedToArray(_ref11, 3),\n variable = _ref12[0],\n comparatorOp = _ref12[1],\n value = _ref12[2];\n\n var valueIsString = new RegExp('^' + tokens.string + '$').exec(value) != null;\n\n if (valueIsString) {\n value = value.substring(1, value.length - 1);\n } else {\n value = parseFloat(value);\n }\n\n query.checks.push({\n type: Type.DATA_COMPARE,\n field: cleanMetaChars(variable),\n operator: comparatorOp,\n value: value\n });\n }\n}, {\n name: 'dataBool',\n query: true,\n regex: '\\\\[\\\\s*(' + tokens.boolOp + ')\\\\s*(' + tokens.variable + ')\\\\s*\\\\]',\n populate: function populate(selector, query, _ref13) {\n var _ref14 = _slicedToArray(_ref13, 2),\n boolOp = _ref14[0],\n variable = _ref14[1];\n\n query.checks.push({\n type: Type.DATA_BOOL,\n field: cleanMetaChars(variable),\n operator: boolOp\n });\n }\n}, {\n name: 'metaCompare',\n query: true,\n regex: '\\\\[\\\\[\\\\s*(' + tokens.meta + ')\\\\s*(' + tokens.comparatorOp + ')\\\\s*(' + tokens.number + ')\\\\s*\\\\]\\\\]',\n populate: function populate(selector, query, _ref15) {\n var _ref16 = _slicedToArray(_ref15, 3),\n meta = _ref16[0],\n comparatorOp = _ref16[1],\n number = _ref16[2];\n\n query.checks.push({\n type: Type.META_COMPARE,\n field: cleanMetaChars(meta),\n operator: comparatorOp,\n value: parseFloat(number)\n });\n }\n}, {\n name: 'nextQuery',\n separator: true,\n regex: tokens.separator,\n populate: function populate(selector, query) {\n var currentSubject = selector.currentSubject;\n var edgeCount = selector.edgeCount;\n var compoundCount = selector.compoundCount;\n var lastQ = selector[selector.length - 1];\n\n if (currentSubject != null) {\n lastQ.subject = currentSubject;\n selector.currentSubject = null;\n }\n\n lastQ.edgeCount = edgeCount;\n lastQ.compoundCount = compoundCount;\n selector.edgeCount = 0;\n selector.compoundCount = 0; // go on to next query\n\n var nextQuery = selector[selector.length++] = newQuery();\n return nextQuery; // this is the new query to be filled by the following exprs\n }\n}, {\n name: 'directedEdge',\n separator: true,\n regex: tokens.directedEdge,\n populate: function populate(selector, query) {\n if (selector.currentSubject == null) {\n // undirected edge\n var edgeQuery = newQuery();\n var source = query;\n var target = newQuery();\n edgeQuery.checks.push({\n type: Type.DIRECTED_EDGE,\n source: source,\n target: target\n }); // the query in the selector should be the edge rather than the source\n\n replaceLastQuery(selector, query, edgeQuery);\n selector.edgeCount++; // we're now populating the target query with expressions that follow\n\n return target;\n } else {\n // source/target\n var srcTgtQ = newQuery();\n var _source = query;\n\n var _target = newQuery();\n\n srcTgtQ.checks.push({\n type: Type.NODE_SOURCE,\n source: _source,\n target: _target\n }); // the query in the selector should be the neighbourhood rather than the node\n\n replaceLastQuery(selector, query, srcTgtQ);\n selector.edgeCount++;\n return _target; // now populating the target with the following expressions\n }\n }\n}, {\n name: 'undirectedEdge',\n separator: true,\n regex: tokens.undirectedEdge,\n populate: function populate(selector, query) {\n if (selector.currentSubject == null) {\n // undirected edge\n var edgeQuery = newQuery();\n var source = query;\n var target = newQuery();\n edgeQuery.checks.push({\n type: Type.UNDIRECTED_EDGE,\n nodes: [source, target]\n }); // the query in the selector should be the edge rather than the source\n\n replaceLastQuery(selector, query, edgeQuery);\n selector.edgeCount++; // we're now populating the target query with expressions that follow\n\n return target;\n } else {\n // neighbourhood\n var nhoodQ = newQuery();\n var node = query;\n var neighbor = newQuery();\n nhoodQ.checks.push({\n type: Type.NODE_NEIGHBOR,\n node: node,\n neighbor: neighbor\n }); // the query in the selector should be the neighbourhood rather than the node\n\n replaceLastQuery(selector, query, nhoodQ);\n return neighbor; // now populating the neighbor with following expressions\n }\n }\n}, {\n name: 'child',\n separator: true,\n regex: tokens.child,\n populate: function populate(selector, query) {\n if (selector.currentSubject == null) {\n // default: child query\n var parentChildQuery = newQuery();\n var child = newQuery();\n var parent = selector[selector.length - 1];\n parentChildQuery.checks.push({\n type: Type.CHILD,\n parent: parent,\n child: child\n }); // the query in the selector should be the '>' itself\n\n replaceLastQuery(selector, query, parentChildQuery);\n selector.compoundCount++; // we're now populating the child query with expressions that follow\n\n return child;\n } else if (selector.currentSubject === query) {\n // compound split query\n var compound = newQuery();\n var left = selector[selector.length - 1];\n var right = newQuery();\n var subject = newQuery();\n\n var _child = newQuery();\n\n var _parent = newQuery(); // set up the root compound q\n\n\n compound.checks.push({\n type: Type.COMPOUND_SPLIT,\n left: left,\n right: right,\n subject: subject\n }); // populate the subject and replace the q at the old spot (within left) with TRUE\n\n subject.checks = query.checks; // take the checks from the left\n\n query.checks = [{\n type: Type.TRUE\n }]; // checks under left refs the subject implicitly\n // set up the right q\n\n _parent.checks.push({\n type: Type.TRUE\n }); // parent implicitly refs the subject\n\n\n right.checks.push({\n type: Type.PARENT,\n // type is swapped on right side queries\n parent: _parent,\n child: _child // empty for now\n\n });\n replaceLastQuery(selector, left, compound); // update the ref since we moved things around for `query`\n\n selector.currentSubject = subject;\n selector.compoundCount++;\n return _child; // now populating the right side's child\n } else {\n // parent query\n // info for parent query\n var _parent2 = newQuery();\n\n var _child2 = newQuery();\n\n var pcQChecks = [{\n type: Type.PARENT,\n parent: _parent2,\n child: _child2\n }]; // the parent-child query takes the place of the query previously being populated\n\n _parent2.checks = query.checks; // the previous query contains the checks for the parent\n\n query.checks = pcQChecks; // pc query takes over\n\n selector.compoundCount++;\n return _child2; // we're now populating the child\n }\n }\n}, {\n name: 'descendant',\n separator: true,\n regex: tokens.descendant,\n populate: function populate(selector, query) {\n if (selector.currentSubject == null) {\n // default: descendant query\n var ancChQuery = newQuery();\n var descendant = newQuery();\n var ancestor = selector[selector.length - 1];\n ancChQuery.checks.push({\n type: Type.DESCENDANT,\n ancestor: ancestor,\n descendant: descendant\n }); // the query in the selector should be the '>' itself\n\n replaceLastQuery(selector, query, ancChQuery);\n selector.compoundCount++; // we're now populating the descendant query with expressions that follow\n\n return descendant;\n } else if (selector.currentSubject === query) {\n // compound split query\n var compound = newQuery();\n var left = selector[selector.length - 1];\n var right = newQuery();\n var subject = newQuery();\n\n var _descendant = newQuery();\n\n var _ancestor = newQuery(); // set up the root compound q\n\n\n compound.checks.push({\n type: Type.COMPOUND_SPLIT,\n left: left,\n right: right,\n subject: subject\n }); // populate the subject and replace the q at the old spot (within left) with TRUE\n\n subject.checks = query.checks; // take the checks from the left\n\n query.checks = [{\n type: Type.TRUE\n }]; // checks under left refs the subject implicitly\n // set up the right q\n\n _ancestor.checks.push({\n type: Type.TRUE\n }); // ancestor implicitly refs the subject\n\n\n right.checks.push({\n type: Type.ANCESTOR,\n // type is swapped on right side queries\n ancestor: _ancestor,\n descendant: _descendant // empty for now\n\n });\n replaceLastQuery(selector, left, compound); // update the ref since we moved things around for `query`\n\n selector.currentSubject = subject;\n selector.compoundCount++;\n return _descendant; // now populating the right side's descendant\n } else {\n // ancestor query\n // info for parent query\n var _ancestor2 = newQuery();\n\n var _descendant2 = newQuery();\n\n var adQChecks = [{\n type: Type.ANCESTOR,\n ancestor: _ancestor2,\n descendant: _descendant2\n }]; // the parent-child query takes the place of the query previously being populated\n\n _ancestor2.checks = query.checks; // the previous query contains the checks for the parent\n\n query.checks = adQChecks; // pc query takes over\n\n selector.compoundCount++;\n return _descendant2; // we're now populating the child\n }\n }\n}, {\n name: 'subject',\n modifier: true,\n regex: tokens.subject,\n populate: function populate(selector, query) {\n if (selector.currentSubject != null && selector.currentSubject !== query) {\n warn('Redefinition of subject in selector `' + selector.toString() + '`');\n return false;\n }\n\n selector.currentSubject = query;\n var topQ = selector[selector.length - 1];\n var topChk = topQ.checks[0];\n var topType = topChk == null ? null : topChk.type;\n\n if (topType === Type.DIRECTED_EDGE) {\n // directed edge with subject on the target\n // change to target node check\n topChk.type = Type.NODE_TARGET;\n } else if (topType === Type.UNDIRECTED_EDGE) {\n // undirected edge with subject on the second node\n // change to neighbor check\n topChk.type = Type.NODE_NEIGHBOR;\n topChk.node = topChk.nodes[1]; // second node is subject\n\n topChk.neighbor = topChk.nodes[0]; // clean up unused fields for new type\n\n topChk.nodes = null;\n }\n }\n}];\nexprs.forEach(function (e) {\n return e.regexObj = new RegExp('^' + e.regex);\n});\n\n/**\n * Of all the expressions, find the first match in the remaining text.\n * @param {string} remaining The remaining text to parse\n * @returns The matched expression and the newly remaining text `{ expr, match, name, remaining }`\n */\n\nvar consumeExpr = function consumeExpr(remaining) {\n var expr;\n var match;\n var name;\n\n for (var j = 0; j < exprs.length; j++) {\n var e = exprs[j];\n var n = e.name;\n var m = remaining.match(e.regexObj);\n\n if (m != null) {\n match = m;\n expr = e;\n name = n;\n var consumed = m[0];\n remaining = remaining.substring(consumed.length);\n break; // we've consumed one expr, so we can return now\n }\n }\n\n return {\n expr: expr,\n match: match,\n name: name,\n remaining: remaining\n };\n};\n/**\n * Consume all the leading whitespace\n * @param {string} remaining The text to consume\n * @returns The text with the leading whitespace removed\n */\n\n\nvar consumeWhitespace = function consumeWhitespace(remaining) {\n var match = remaining.match(/^\\s+/);\n\n if (match) {\n var consumed = match[0];\n remaining = remaining.substring(consumed.length);\n }\n\n return remaining;\n};\n/**\n * Parse the string and store the parsed representation in the Selector.\n * @param {string} selector The selector string\n * @returns `true` if the selector was successfully parsed, `false` otherwise\n */\n\n\nvar parse = function parse(selector) {\n var self = this;\n var remaining = self.inputText = selector;\n var currentQuery = self[0] = newQuery();\n self.length = 1;\n remaining = consumeWhitespace(remaining); // get rid of leading whitespace\n\n for (;;) {\n var exprInfo = consumeExpr(remaining);\n\n if (exprInfo.expr == null) {\n warn('The selector `' + selector + '`is invalid');\n return false;\n } else {\n var args = exprInfo.match.slice(1); // let the token populate the selector object in currentQuery\n\n var ret = exprInfo.expr.populate(self, currentQuery, args);\n\n if (ret === false) {\n return false; // exit if population failed\n } else if (ret != null) {\n currentQuery = ret; // change the current query to be filled if the expr specifies\n }\n }\n\n remaining = exprInfo.remaining; // we're done when there's nothing left to parse\n\n if (remaining.match(/^\\s*$/)) {\n break;\n }\n }\n\n var lastQ = self[self.length - 1];\n\n if (self.currentSubject != null) {\n lastQ.subject = self.currentSubject;\n }\n\n lastQ.edgeCount = self.edgeCount;\n lastQ.compoundCount = self.compoundCount;\n\n for (var i = 0; i < self.length; i++) {\n var q = self[i]; // in future, this could potentially be allowed if there were operator precedence and detection of invalid combinations\n\n if (q.compoundCount > 0 && q.edgeCount > 0) {\n warn('The selector `' + selector + '` is invalid because it uses both a compound selector and an edge selector');\n return false;\n }\n\n if (q.edgeCount > 1) {\n warn('The selector `' + selector + '` is invalid because it uses multiple edge selectors');\n return false;\n } else if (q.edgeCount === 1) {\n warn('The selector `' + selector + '` is deprecated. Edge selectors do not take effect on changes to source and target nodes after an edge is added, for performance reasons. Use a class or data selector on edges instead, updating the class or data of an edge when your app detects a change in source or target nodes.');\n }\n }\n\n return true; // success\n};\n/**\n * Get the selector represented as a string. This value uses default formatting,\n * so things like spacing may differ from the input text passed to the constructor.\n * @returns {string} The selector string\n */\n\n\nvar toString = function toString() {\n if (this.toStringCache != null) {\n return this.toStringCache;\n }\n\n var clean = function clean(obj) {\n if (obj == null) {\n return '';\n } else {\n return obj;\n }\n };\n\n var cleanVal = function cleanVal(val) {\n if (string(val)) {\n return '\"' + val + '\"';\n } else {\n return clean(val);\n }\n };\n\n var space = function space(val) {\n return ' ' + val + ' ';\n };\n\n var checkToString = function checkToString(check, subject) {\n var type = check.type,\n value = check.value;\n\n switch (type) {\n case Type.GROUP:\n {\n var group = clean(value);\n return group.substring(0, group.length - 1);\n }\n\n case Type.DATA_COMPARE:\n {\n var field = check.field,\n operator = check.operator;\n return '[' + field + space(clean(operator)) + cleanVal(value) + ']';\n }\n\n case Type.DATA_BOOL:\n {\n var _operator = check.operator,\n _field = check.field;\n return '[' + clean(_operator) + _field + ']';\n }\n\n case Type.DATA_EXIST:\n {\n var _field2 = check.field;\n return '[' + _field2 + ']';\n }\n\n case Type.META_COMPARE:\n {\n var _operator2 = check.operator,\n _field3 = check.field;\n return '[[' + _field3 + space(clean(_operator2)) + cleanVal(value) + ']]';\n }\n\n case Type.STATE:\n {\n return value;\n }\n\n case Type.ID:\n {\n return '#' + value;\n }\n\n case Type.CLASS:\n {\n return '.' + value;\n }\n\n case Type.PARENT:\n case Type.CHILD:\n {\n return queryToString(check.parent, subject) + space('>') + queryToString(check.child, subject);\n }\n\n case Type.ANCESTOR:\n case Type.DESCENDANT:\n {\n return queryToString(check.ancestor, subject) + ' ' + queryToString(check.descendant, subject);\n }\n\n case Type.COMPOUND_SPLIT:\n {\n var lhs = queryToString(check.left, subject);\n var sub = queryToString(check.subject, subject);\n var rhs = queryToString(check.right, subject);\n return lhs + (lhs.length > 0 ? ' ' : '') + sub + rhs;\n }\n\n case Type.TRUE:\n {\n return '';\n }\n }\n };\n\n var queryToString = function queryToString(query, subject) {\n return query.checks.reduce(function (str, chk, i) {\n return str + (subject === query && i === 0 ? '$' : '') + checkToString(chk, subject);\n }, '');\n };\n\n var str = '';\n\n for (var i = 0; i < this.length; i++) {\n var query = this[i];\n str += queryToString(query, query.subject);\n\n if (this.length > 1 && i < this.length - 1) {\n str += ', ';\n }\n }\n\n this.toStringCache = str;\n return str;\n};\nvar parse$1 = {\n parse: parse,\n toString: toString\n};\n\nvar valCmp = function valCmp(fieldVal, operator, value) {\n var matches;\n var isFieldStr = string(fieldVal);\n var isFieldNum = number(fieldVal);\n var isValStr = string(value);\n var fieldStr, valStr;\n var caseInsensitive = false;\n var notExpr = false;\n var isIneqCmp = false;\n\n if (operator.indexOf('!') >= 0) {\n operator = operator.replace('!', '');\n notExpr = true;\n }\n\n if (operator.indexOf('@') >= 0) {\n operator = operator.replace('@', '');\n caseInsensitive = true;\n }\n\n if (isFieldStr || isValStr || caseInsensitive) {\n fieldStr = !isFieldStr && !isFieldNum ? '' : '' + fieldVal;\n valStr = '' + value;\n } // if we're doing a case insensitive comparison, then we're using a STRING comparison\n // even if we're comparing numbers\n\n\n if (caseInsensitive) {\n fieldVal = fieldStr = fieldStr.toLowerCase();\n value = valStr = valStr.toLowerCase();\n }\n\n switch (operator) {\n case '*=':\n matches = fieldStr.indexOf(valStr) >= 0;\n break;\n\n case '$=':\n matches = fieldStr.indexOf(valStr, fieldStr.length - valStr.length) >= 0;\n break;\n\n case '^=':\n matches = fieldStr.indexOf(valStr) === 0;\n break;\n\n case '=':\n matches = fieldVal === value;\n break;\n\n case '>':\n isIneqCmp = true;\n matches = fieldVal > value;\n break;\n\n case '>=':\n isIneqCmp = true;\n matches = fieldVal >= value;\n break;\n\n case '<':\n isIneqCmp = true;\n matches = fieldVal < value;\n break;\n\n case '<=':\n isIneqCmp = true;\n matches = fieldVal <= value;\n break;\n\n default:\n matches = false;\n break;\n } // apply the not op, but null vals for inequalities should always stay non-matching\n\n\n if (notExpr && (fieldVal != null || !isIneqCmp)) {\n matches = !matches;\n }\n\n return matches;\n};\nvar boolCmp = function boolCmp(fieldVal, operator) {\n switch (operator) {\n case '?':\n return fieldVal ? true : false;\n\n case '!':\n return fieldVal ? false : true;\n\n case '^':\n return fieldVal === undefined;\n }\n};\nvar existCmp = function existCmp(fieldVal) {\n return fieldVal !== undefined;\n};\nvar data = function data(ele, field) {\n return ele.data(field);\n};\nvar meta = function meta(ele, field) {\n return ele[field]();\n};\n\n/** A lookup of `match(check, ele)` functions by `Type` int */\n\nvar match = [];\n/**\n * Returns whether the query matches for the element\n * @param query The `{ type, value, ... }` query object\n * @param ele The element to compare against\n*/\n\nvar matches = function matches(query, ele) {\n return query.checks.every(function (chk) {\n return match[chk.type](chk, ele);\n });\n};\n\nmatch[Type.GROUP] = function (check, ele) {\n var group = check.value;\n return group === '*' || group === ele.group();\n};\n\nmatch[Type.STATE] = function (check, ele) {\n var stateSelector = check.value;\n return stateSelectorMatches(stateSelector, ele);\n};\n\nmatch[Type.ID] = function (check, ele) {\n var id = check.value;\n return ele.id() === id;\n};\n\nmatch[Type.CLASS] = function (check, ele) {\n var cls = check.value;\n return ele.hasClass(cls);\n};\n\nmatch[Type.META_COMPARE] = function (check, ele) {\n var field = check.field,\n operator = check.operator,\n value = check.value;\n return valCmp(meta(ele, field), operator, value);\n};\n\nmatch[Type.DATA_COMPARE] = function (check, ele) {\n var field = check.field,\n operator = check.operator,\n value = check.value;\n return valCmp(data(ele, field), operator, value);\n};\n\nmatch[Type.DATA_BOOL] = function (check, ele) {\n var field = check.field,\n operator = check.operator;\n return boolCmp(data(ele, field), operator);\n};\n\nmatch[Type.DATA_EXIST] = function (check, ele) {\n var field = check.field,\n operator = check.operator;\n return existCmp(data(ele, field));\n};\n\nmatch[Type.UNDIRECTED_EDGE] = function (check, ele) {\n var qA = check.nodes[0];\n var qB = check.nodes[1];\n var src = ele.source();\n var tgt = ele.target();\n return matches(qA, src) && matches(qB, tgt) || matches(qB, src) && matches(qA, tgt);\n};\n\nmatch[Type.NODE_NEIGHBOR] = function (check, ele) {\n return matches(check.node, ele) && ele.neighborhood().some(function (n) {\n return n.isNode() && matches(check.neighbor, n);\n });\n};\n\nmatch[Type.DIRECTED_EDGE] = function (check, ele) {\n return matches(check.source, ele.source()) && matches(check.target, ele.target());\n};\n\nmatch[Type.NODE_SOURCE] = function (check, ele) {\n return matches(check.source, ele) && ele.outgoers().some(function (n) {\n return n.isNode() && matches(check.target, n);\n });\n};\n\nmatch[Type.NODE_TARGET] = function (check, ele) {\n return matches(check.target, ele) && ele.incomers().some(function (n) {\n return n.isNode() && matches(check.source, n);\n });\n};\n\nmatch[Type.CHILD] = function (check, ele) {\n return matches(check.child, ele) && matches(check.parent, ele.parent());\n};\n\nmatch[Type.PARENT] = function (check, ele) {\n return matches(check.parent, ele) && ele.children().some(function (c) {\n return matches(check.child, c);\n });\n};\n\nmatch[Type.DESCENDANT] = function (check, ele) {\n return matches(check.descendant, ele) && ele.ancestors().some(function (a) {\n return matches(check.ancestor, a);\n });\n};\n\nmatch[Type.ANCESTOR] = function (check, ele) {\n return matches(check.ancestor, ele) && ele.descendants().some(function (d) {\n return matches(check.descendant, d);\n });\n};\n\nmatch[Type.COMPOUND_SPLIT] = function (check, ele) {\n return matches(check.subject, ele) && matches(check.left, ele) && matches(check.right, ele);\n};\n\nmatch[Type.TRUE] = function () {\n return true;\n};\n\nmatch[Type.COLLECTION] = function (check, ele) {\n var collection = check.value;\n return collection.has(ele);\n};\n\nmatch[Type.FILTER] = function (check, ele) {\n var filter = check.value;\n return filter(ele);\n};\n\nvar filter = function filter(collection) {\n var self = this; // for 1 id #foo queries, just get the element\n\n if (self.length === 1 && self[0].checks.length === 1 && self[0].checks[0].type === Type.ID) {\n return collection.getElementById(self[0].checks[0].value).collection();\n }\n\n var selectorFunction = function selectorFunction(element) {\n for (var j = 0; j < self.length; j++) {\n var query = self[j];\n\n if (matches(query, element)) {\n return true;\n }\n }\n\n return false;\n };\n\n if (self.text() == null) {\n selectorFunction = function selectorFunction() {\n return true;\n };\n }\n\n return collection.filter(selectorFunction);\n}; // filter\n// does selector match a single element?\n\n\nvar matches$1 = function matches$1(ele) {\n var self = this;\n\n for (var j = 0; j < self.length; j++) {\n var query = self[j];\n\n if (matches(query, ele)) {\n return true;\n }\n }\n\n return false;\n}; // matches\n\n\nvar matching = {\n matches: matches$1,\n filter: filter\n};\n\nvar Selector = function Selector(selector) {\n this.inputText = selector;\n this.currentSubject = null;\n this.compoundCount = 0;\n this.edgeCount = 0;\n this.length = 0;\n\n if (selector == null || string(selector) && selector.match(/^\\s*$/)) ; else if (elementOrCollection(selector)) {\n this.addQuery({\n checks: [{\n type: Type.COLLECTION,\n value: selector.collection()\n }]\n });\n } else if (fn(selector)) {\n this.addQuery({\n checks: [{\n type: Type.FILTER,\n value: selector\n }]\n });\n } else if (string(selector)) {\n if (!this.parse(selector)) {\n this.invalid = true;\n }\n } else {\n error('A selector must be created from a string; found ');\n }\n};\n\nvar selfn = Selector.prototype;\n[parse$1, matching].forEach(function (p) {\n return extend(selfn, p);\n});\n\nselfn.text = function () {\n return this.inputText;\n};\n\nselfn.size = function () {\n return this.length;\n};\n\nselfn.eq = function (i) {\n return this[i];\n};\n\nselfn.sameText = function (otherSel) {\n return !this.invalid && !otherSel.invalid && this.text() === otherSel.text();\n};\n\nselfn.addQuery = function (q) {\n this[this.length++] = q;\n};\n\nselfn.selector = selfn.toString;\n\nvar elesfn$f = {\n allAre: function allAre(selector) {\n var selObj = new Selector(selector);\n return this.every(function (ele) {\n return selObj.matches(ele);\n });\n },\n is: function is(selector) {\n var selObj = new Selector(selector);\n return this.some(function (ele) {\n return selObj.matches(ele);\n });\n },\n some: function some(fn, thisArg) {\n for (var i = 0; i < this.length; i++) {\n var ret = !thisArg ? fn(this[i], i, this) : fn.apply(thisArg, [this[i], i, this]);\n\n if (ret) {\n return true;\n }\n }\n\n return false;\n },\n every: function every(fn, thisArg) {\n for (var i = 0; i < this.length; i++) {\n var ret = !thisArg ? fn(this[i], i, this) : fn.apply(thisArg, [this[i], i, this]);\n\n if (!ret) {\n return false;\n }\n }\n\n return true;\n },\n same: function same(collection) {\n // cheap collection ref check\n if (this === collection) {\n return true;\n }\n\n collection = this.cy().collection(collection);\n var thisLength = this.length;\n var collectionLength = collection.length; // cheap length check\n\n if (thisLength !== collectionLength) {\n return false;\n } // cheap element ref check\n\n\n if (thisLength === 1) {\n return this[0] === collection[0];\n }\n\n return this.every(function (ele) {\n return collection.hasElementWithId(ele.id());\n });\n },\n anySame: function anySame(collection) {\n collection = this.cy().collection(collection);\n return this.some(function (ele) {\n return collection.hasElementWithId(ele.id());\n });\n },\n allAreNeighbors: function allAreNeighbors(collection) {\n collection = this.cy().collection(collection);\n var nhood = this.neighborhood();\n return collection.every(function (ele) {\n return nhood.hasElementWithId(ele.id());\n });\n },\n contains: function contains(collection) {\n collection = this.cy().collection(collection);\n var self = this;\n return collection.every(function (ele) {\n return self.hasElementWithId(ele.id());\n });\n }\n};\nelesfn$f.allAreNeighbours = elesfn$f.allAreNeighbors;\nelesfn$f.has = elesfn$f.contains;\nelesfn$f.equal = elesfn$f.equals = elesfn$f.same;\n\nvar cache = function cache(fn, name) {\n return function traversalCache(arg1, arg2, arg3, arg4) {\n var selectorOrEles = arg1;\n var eles = this;\n var key;\n\n if (selectorOrEles == null) {\n key = '';\n } else if (elementOrCollection(selectorOrEles) && selectorOrEles.length === 1) {\n key = selectorOrEles.id();\n }\n\n if (eles.length === 1 && key) {\n var _p = eles[0]._private;\n var tch = _p.traversalCache = _p.traversalCache || {};\n var ch = tch[name] = tch[name] || [];\n var hash = hashString(key);\n var cacheHit = ch[hash];\n\n if (cacheHit) {\n return cacheHit;\n } else {\n return ch[hash] = fn.call(eles, arg1, arg2, arg3, arg4);\n }\n } else {\n return fn.call(eles, arg1, arg2, arg3, arg4);\n }\n };\n};\n\nvar elesfn$g = {\n parent: function parent(selector) {\n var parents = []; // optimisation for single ele call\n\n if (this.length === 1) {\n var parent = this[0]._private.parent;\n\n if (parent) {\n return parent;\n }\n }\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var _parent = ele._private.parent;\n\n if (_parent) {\n parents.push(_parent);\n }\n }\n\n return this.spawn(parents, {\n unique: true\n }).filter(selector);\n },\n parents: function parents(selector) {\n var parents = [];\n var eles = this.parent();\n\n while (eles.nonempty()) {\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n parents.push(ele);\n }\n\n eles = eles.parent();\n }\n\n return this.spawn(parents, {\n unique: true\n }).filter(selector);\n },\n commonAncestors: function commonAncestors(selector) {\n var ancestors;\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var parents = ele.parents();\n ancestors = ancestors || parents;\n ancestors = ancestors.intersect(parents); // current list must be common with current ele parents set\n }\n\n return ancestors.filter(selector);\n },\n orphans: function orphans(selector) {\n return this.stdFilter(function (ele) {\n return ele.isOrphan();\n }).filter(selector);\n },\n nonorphans: function nonorphans(selector) {\n return this.stdFilter(function (ele) {\n return ele.isChild();\n }).filter(selector);\n },\n children: cache(function (selector) {\n var children = [];\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var eleChildren = ele._private.children;\n\n for (var j = 0; j < eleChildren.length; j++) {\n children.push(eleChildren[j]);\n }\n }\n\n return this.spawn(children, {\n unique: true\n }).filter(selector);\n }, 'children'),\n siblings: function siblings(selector) {\n return this.parent().children().not(this).filter(selector);\n },\n isParent: function isParent() {\n var ele = this[0];\n\n if (ele) {\n return ele.isNode() && ele._private.children.length !== 0;\n }\n },\n isChildless: function isChildless() {\n var ele = this[0];\n\n if (ele) {\n return ele.isNode() && ele._private.children.length === 0;\n }\n },\n isChild: function isChild() {\n var ele = this[0];\n\n if (ele) {\n return ele.isNode() && ele._private.parent != null;\n }\n },\n isOrphan: function isOrphan() {\n var ele = this[0];\n\n if (ele) {\n return ele.isNode() && ele._private.parent == null;\n }\n },\n descendants: function descendants(selector) {\n var elements = [];\n\n function add(eles) {\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n elements.push(ele);\n\n if (ele.children().nonempty()) {\n add(ele.children());\n }\n }\n }\n\n add(this.children());\n return this.spawn(elements, {\n unique: true\n }).filter(selector);\n }\n};\n\nfunction forEachCompound(eles, fn, includeSelf, recursiveStep) {\n var q = [];\n var did = new Set$1();\n var cy = eles.cy();\n var hasCompounds = cy.hasCompoundNodes();\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n\n if (includeSelf) {\n q.push(ele);\n } else if (hasCompounds) {\n recursiveStep(q, did, ele);\n }\n }\n\n while (q.length > 0) {\n var _ele = q.shift();\n\n fn(_ele);\n did.add(_ele.id());\n\n if (hasCompounds) {\n recursiveStep(q, did, _ele);\n }\n }\n\n return eles;\n}\n\nfunction addChildren(q, did, ele) {\n if (ele.isParent()) {\n var children = ele._private.children;\n\n for (var i = 0; i < children.length; i++) {\n var child = children[i];\n\n if (!did.has(child.id())) {\n q.push(child);\n }\n }\n }\n} // very efficient version of eles.add( eles.descendants() ).forEach()\n// for internal use\n\n\nelesfn$g.forEachDown = function (fn) {\n var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n return forEachCompound(this, fn, includeSelf, addChildren);\n};\n\nfunction addParent(q, did, ele) {\n if (ele.isChild()) {\n var parent = ele._private.parent;\n\n if (!did.has(parent.id())) {\n q.push(parent);\n }\n }\n}\n\nelesfn$g.forEachUp = function (fn) {\n var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n return forEachCompound(this, fn, includeSelf, addParent);\n};\n\nfunction addParentAndChildren(q, did, ele) {\n addParent(q, did, ele);\n addChildren(q, did, ele);\n}\n\nelesfn$g.forEachUpAndDown = function (fn) {\n var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n return forEachCompound(this, fn, includeSelf, addParentAndChildren);\n}; // aliases\n\n\nelesfn$g.ancestors = elesfn$g.parents;\n\nvar fn$1, elesfn$h;\nfn$1 = elesfn$h = {\n data: define$3.data({\n field: 'data',\n bindingEvent: 'data',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'data',\n settingTriggersEvent: true,\n triggerFnName: 'trigger',\n allowGetting: true,\n immutableKeys: {\n 'id': true,\n 'source': true,\n 'target': true,\n 'parent': true\n },\n updateStyle: true\n }),\n removeData: define$3.removeData({\n field: 'data',\n event: 'data',\n triggerFnName: 'trigger',\n triggerEvent: true,\n immutableKeys: {\n 'id': true,\n 'source': true,\n 'target': true,\n 'parent': true\n },\n updateStyle: true\n }),\n scratch: define$3.data({\n field: 'scratch',\n bindingEvent: 'scratch',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'scratch',\n settingTriggersEvent: true,\n triggerFnName: 'trigger',\n allowGetting: true,\n updateStyle: true\n }),\n removeScratch: define$3.removeData({\n field: 'scratch',\n event: 'scratch',\n triggerFnName: 'trigger',\n triggerEvent: true,\n updateStyle: true\n }),\n rscratch: define$3.data({\n field: 'rscratch',\n allowBinding: false,\n allowSetting: true,\n settingTriggersEvent: false,\n allowGetting: true\n }),\n removeRscratch: define$3.removeData({\n field: 'rscratch',\n triggerEvent: false\n }),\n id: function id() {\n var ele = this[0];\n\n if (ele) {\n return ele._private.data.id;\n }\n }\n}; // aliases\n\nfn$1.attr = fn$1.data;\nfn$1.removeAttr = fn$1.removeData;\nvar data$1 = elesfn$h;\n\nvar elesfn$i = {};\n\nfunction defineDegreeFunction(callback) {\n return function (includeLoops) {\n var self = this;\n\n if (includeLoops === undefined) {\n includeLoops = true;\n }\n\n if (self.length === 0) {\n return;\n }\n\n if (self.isNode() && !self.removed()) {\n var degree = 0;\n var node = self[0];\n var connectedEdges = node._private.edges;\n\n for (var i = 0; i < connectedEdges.length; i++) {\n var edge = connectedEdges[i];\n\n if (!includeLoops && edge.isLoop()) {\n continue;\n }\n\n degree += callback(node, edge);\n }\n\n return degree;\n } else {\n return;\n }\n };\n}\n\nextend(elesfn$i, {\n degree: defineDegreeFunction(function (node, edge) {\n if (edge.source().same(edge.target())) {\n return 2;\n } else {\n return 1;\n }\n }),\n indegree: defineDegreeFunction(function (node, edge) {\n if (edge.target().same(node)) {\n return 1;\n } else {\n return 0;\n }\n }),\n outdegree: defineDegreeFunction(function (node, edge) {\n if (edge.source().same(node)) {\n return 1;\n } else {\n return 0;\n }\n })\n});\n\nfunction defineDegreeBoundsFunction(degreeFn, callback) {\n return function (includeLoops) {\n var ret;\n var nodes = this.nodes();\n\n for (var i = 0; i < nodes.length; i++) {\n var ele = nodes[i];\n var degree = ele[degreeFn](includeLoops);\n\n if (degree !== undefined && (ret === undefined || callback(degree, ret))) {\n ret = degree;\n }\n }\n\n return ret;\n };\n}\n\nextend(elesfn$i, {\n minDegree: defineDegreeBoundsFunction('degree', function (degree, min) {\n return degree < min;\n }),\n maxDegree: defineDegreeBoundsFunction('degree', function (degree, max) {\n return degree > max;\n }),\n minIndegree: defineDegreeBoundsFunction('indegree', function (degree, min) {\n return degree < min;\n }),\n maxIndegree: defineDegreeBoundsFunction('indegree', function (degree, max) {\n return degree > max;\n }),\n minOutdegree: defineDegreeBoundsFunction('outdegree', function (degree, min) {\n return degree < min;\n }),\n maxOutdegree: defineDegreeBoundsFunction('outdegree', function (degree, max) {\n return degree > max;\n })\n});\nextend(elesfn$i, {\n totalDegree: function totalDegree(includeLoops) {\n var total = 0;\n var nodes = this.nodes();\n\n for (var i = 0; i < nodes.length; i++) {\n total += nodes[i].degree(includeLoops);\n }\n\n return total;\n }\n});\n\nvar fn$2, elesfn$j;\n\nvar beforePositionSet = function beforePositionSet(eles, newPos, silent) {\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n\n if (!ele.locked()) {\n var oldPos = ele._private.position;\n var delta = {\n x: newPos.x != null ? newPos.x - oldPos.x : 0,\n y: newPos.y != null ? newPos.y - oldPos.y : 0\n };\n\n if (ele.isParent() && !(delta.x === 0 && delta.y === 0)) {\n ele.children().shift(delta, silent);\n }\n\n ele.shiftCachedBoundingBox(delta);\n }\n }\n};\n\nvar positionDef = {\n field: 'position',\n bindingEvent: 'position',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'position',\n settingTriggersEvent: true,\n triggerFnName: 'emitAndNotify',\n allowGetting: true,\n validKeys: ['x', 'y'],\n beforeGet: function beforeGet(ele) {\n ele.updateCompoundBounds();\n },\n beforeSet: function beforeSet(eles, newPos) {\n beforePositionSet(eles, newPos, false);\n },\n onSet: function onSet(eles) {\n eles.dirtyCompoundBoundsCache();\n },\n canSet: function canSet(ele) {\n return !ele.locked();\n }\n};\nfn$2 = elesfn$j = {\n position: define$3.data(positionDef),\n // position but no notification to renderer\n silentPosition: define$3.data(extend({}, positionDef, {\n allowBinding: false,\n allowSetting: true,\n settingTriggersEvent: false,\n allowGetting: false,\n beforeSet: function beforeSet(eles, newPos) {\n beforePositionSet(eles, newPos, true);\n }\n })),\n positions: function positions(pos, silent) {\n if (plainObject(pos)) {\n if (silent) {\n this.silentPosition(pos);\n } else {\n this.position(pos);\n }\n } else if (fn(pos)) {\n var _fn = pos;\n var cy = this.cy();\n cy.startBatch();\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n\n var _pos = void 0;\n\n if (_pos = _fn(ele, i)) {\n if (silent) {\n ele.silentPosition(_pos);\n } else {\n ele.position(_pos);\n }\n }\n }\n\n cy.endBatch();\n }\n\n return this; // chaining\n },\n silentPositions: function silentPositions(pos) {\n return this.positions(pos, true);\n },\n shift: function shift(dim, val, silent) {\n var delta;\n\n if (plainObject(dim)) {\n delta = {\n x: number(dim.x) ? dim.x : 0,\n y: number(dim.y) ? dim.y : 0\n };\n silent = val;\n } else if (string(dim) && number(val)) {\n delta = {\n x: 0,\n y: 0\n };\n delta[dim] = val;\n }\n\n if (delta != null) {\n var cy = this.cy();\n cy.startBatch();\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var pos = ele.position();\n var newPos = {\n x: pos.x + delta.x,\n y: pos.y + delta.y\n };\n\n if (silent) {\n ele.silentPosition(newPos);\n } else {\n ele.position(newPos);\n }\n }\n\n cy.endBatch();\n }\n\n return this;\n },\n silentShift: function silentShift(dim, val) {\n if (plainObject(dim)) {\n this.shift(dim, true);\n } else if (string(dim) && number(val)) {\n this.shift(dim, val, true);\n }\n\n return this;\n },\n // get/set the rendered (i.e. on screen) positon of the element\n renderedPosition: function renderedPosition(dim, val) {\n var ele = this[0];\n var cy = this.cy();\n var zoom = cy.zoom();\n var pan = cy.pan();\n var rpos = plainObject(dim) ? dim : undefined;\n var setting = rpos !== undefined || val !== undefined && string(dim);\n\n if (ele && ele.isNode()) {\n // must have an element and must be a node to return position\n if (setting) {\n for (var i = 0; i < this.length; i++) {\n var _ele = this[i];\n\n if (val !== undefined) {\n // set one dimension\n _ele.position(dim, (val - pan[dim]) / zoom);\n } else if (rpos !== undefined) {\n // set whole position\n _ele.position(renderedToModelPosition(rpos, zoom, pan));\n }\n }\n } else {\n // getting\n var pos = ele.position();\n rpos = modelToRenderedPosition(pos, zoom, pan);\n\n if (dim === undefined) {\n // then return the whole rendered position\n return rpos;\n } else {\n // then return the specified dimension\n return rpos[dim];\n }\n }\n } else if (!setting) {\n return undefined; // for empty collection case\n }\n\n return this; // chaining\n },\n // get/set the position relative to the parent\n relativePosition: function relativePosition(dim, val) {\n var ele = this[0];\n var cy = this.cy();\n var ppos = plainObject(dim) ? dim : undefined;\n var setting = ppos !== undefined || val !== undefined && string(dim);\n var hasCompoundNodes = cy.hasCompoundNodes();\n\n if (ele && ele.isNode()) {\n // must have an element and must be a node to return position\n if (setting) {\n for (var i = 0; i < this.length; i++) {\n var _ele2 = this[i];\n var parent = hasCompoundNodes ? _ele2.parent() : null;\n var hasParent = parent && parent.length > 0;\n var relativeToParent = hasParent;\n\n if (hasParent) {\n parent = parent[0];\n }\n\n var origin = relativeToParent ? parent.position() : {\n x: 0,\n y: 0\n };\n\n if (val !== undefined) {\n // set one dimension\n _ele2.position(dim, val + origin[dim]);\n } else if (ppos !== undefined) {\n // set whole position\n _ele2.position({\n x: ppos.x + origin.x,\n y: ppos.y + origin.y\n });\n }\n }\n } else {\n // getting\n var pos = ele.position();\n\n var _parent = hasCompoundNodes ? ele.parent() : null;\n\n var _hasParent = _parent && _parent.length > 0;\n\n var _relativeToParent = _hasParent;\n\n if (_hasParent) {\n _parent = _parent[0];\n }\n\n var _origin = _relativeToParent ? _parent.position() : {\n x: 0,\n y: 0\n };\n\n ppos = {\n x: pos.x - _origin.x,\n y: pos.y - _origin.y\n };\n\n if (dim === undefined) {\n // then return the whole rendered position\n return ppos;\n } else {\n // then return the specified dimension\n return ppos[dim];\n }\n }\n } else if (!setting) {\n return undefined; // for empty collection case\n }\n\n return this; // chaining\n }\n}; // aliases\n\nfn$2.modelPosition = fn$2.point = fn$2.position;\nfn$2.modelPositions = fn$2.points = fn$2.positions;\nfn$2.renderedPoint = fn$2.renderedPosition;\nfn$2.relativePoint = fn$2.relativePosition;\nvar position = elesfn$j;\n\nvar fn$3, elesfn$k;\nfn$3 = elesfn$k = {};\n\nelesfn$k.renderedBoundingBox = function (options) {\n var bb = this.boundingBox(options);\n var cy = this.cy();\n var zoom = cy.zoom();\n var pan = cy.pan();\n var x1 = bb.x1 * zoom + pan.x;\n var x2 = bb.x2 * zoom + pan.x;\n var y1 = bb.y1 * zoom + pan.y;\n var y2 = bb.y2 * zoom + pan.y;\n return {\n x1: x1,\n x2: x2,\n y1: y1,\n y2: y2,\n w: x2 - x1,\n h: y2 - y1\n };\n};\n\nelesfn$k.dirtyCompoundBoundsCache = function () {\n var cy = this.cy();\n\n if (!cy.styleEnabled() || !cy.hasCompoundNodes()) {\n return this;\n }\n\n this.forEachUp(function (ele) {\n if (ele.isParent()) {\n var _p = ele._private;\n _p.compoundBoundsClean = false;\n _p.bbCache = null;\n ele.emitAndNotify('bounds');\n }\n });\n return this;\n};\n\nelesfn$k.updateCompoundBounds = function () {\n var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n var cy = this.cy(); // not possible to do on non-compound graphs or with the style disabled\n\n if (!cy.styleEnabled() || !cy.hasCompoundNodes()) {\n return this;\n } // save cycles when batching -- but bounds will be stale (or not exist yet)\n\n\n if (!force && cy.batching()) {\n return this;\n }\n\n function update(parent) {\n if (!parent.isParent()) {\n return;\n }\n\n var _p = parent._private;\n var children = parent.children();\n var includeLabels = parent.pstyle('compound-sizing-wrt-labels').value === 'include';\n var min = {\n width: {\n val: parent.pstyle('min-width').pfValue,\n left: parent.pstyle('min-width-bias-left'),\n right: parent.pstyle('min-width-bias-right')\n },\n height: {\n val: parent.pstyle('min-height').pfValue,\n top: parent.pstyle('min-height-bias-top'),\n bottom: parent.pstyle('min-height-bias-bottom')\n }\n };\n var bb = children.boundingBox({\n includeLabels: includeLabels,\n includeOverlays: false,\n // updating the compound bounds happens outside of the regular\n // cache cycle (i.e. before fired events)\n useCache: false\n });\n var pos = _p.position; // if children take up zero area then keep position and fall back on stylesheet w/h\n\n if (bb.w === 0 || bb.h === 0) {\n bb = {\n w: parent.pstyle('width').pfValue,\n h: parent.pstyle('height').pfValue\n };\n bb.x1 = pos.x - bb.w / 2;\n bb.x2 = pos.x + bb.w / 2;\n bb.y1 = pos.y - bb.h / 2;\n bb.y2 = pos.y + bb.h / 2;\n }\n\n function computeBiasValues(propDiff, propBias, propBiasComplement) {\n var biasDiff = 0;\n var biasComplementDiff = 0;\n var biasTotal = propBias + propBiasComplement;\n\n if (propDiff > 0 && biasTotal > 0) {\n biasDiff = propBias / biasTotal * propDiff;\n biasComplementDiff = propBiasComplement / biasTotal * propDiff;\n }\n\n return {\n biasDiff: biasDiff,\n biasComplementDiff: biasComplementDiff\n };\n }\n\n function computePaddingValues(width, height, paddingObject, relativeTo) {\n // Assuming percentage is number from 0 to 1\n if (paddingObject.units === '%') {\n switch (relativeTo) {\n case 'width':\n return width > 0 ? paddingObject.pfValue * width : 0;\n\n case 'height':\n return height > 0 ? paddingObject.pfValue * height : 0;\n\n case 'average':\n return width > 0 && height > 0 ? paddingObject.pfValue * (width + height) / 2 : 0;\n\n case 'min':\n return width > 0 && height > 0 ? width > height ? paddingObject.pfValue * height : paddingObject.pfValue * width : 0;\n\n case 'max':\n return width > 0 && height > 0 ? width > height ? paddingObject.pfValue * width : paddingObject.pfValue * height : 0;\n\n default:\n return 0;\n }\n } else if (paddingObject.units === 'px') {\n return paddingObject.pfValue;\n } else {\n return 0;\n }\n }\n\n var leftVal = min.width.left.value;\n\n if (min.width.left.units === 'px' && min.width.val > 0) {\n leftVal = leftVal * 100 / min.width.val;\n }\n\n var rightVal = min.width.right.value;\n\n if (min.width.right.units === 'px' && min.width.val > 0) {\n rightVal = rightVal * 100 / min.width.val;\n }\n\n var topVal = min.height.top.value;\n\n if (min.height.top.units === 'px' && min.height.val > 0) {\n topVal = topVal * 100 / min.height.val;\n }\n\n var bottomVal = min.height.bottom.value;\n\n if (min.height.bottom.units === 'px' && min.height.val > 0) {\n bottomVal = bottomVal * 100 / min.height.val;\n }\n\n var widthBiasDiffs = computeBiasValues(min.width.val - bb.w, leftVal, rightVal);\n var diffLeft = widthBiasDiffs.biasDiff;\n var diffRight = widthBiasDiffs.biasComplementDiff;\n var heightBiasDiffs = computeBiasValues(min.height.val - bb.h, topVal, bottomVal);\n var diffTop = heightBiasDiffs.biasDiff;\n var diffBottom = heightBiasDiffs.biasComplementDiff;\n _p.autoPadding = computePaddingValues(bb.w, bb.h, parent.pstyle('padding'), parent.pstyle('padding-relative-to').value);\n _p.autoWidth = Math.max(bb.w, min.width.val);\n pos.x = (-diffLeft + bb.x1 + bb.x2 + diffRight) / 2;\n _p.autoHeight = Math.max(bb.h, min.height.val);\n pos.y = (-diffTop + bb.y1 + bb.y2 + diffBottom) / 2;\n }\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var _p = ele._private;\n\n if (!_p.compoundBoundsClean) {\n update(ele);\n\n if (!cy.batching()) {\n _p.compoundBoundsClean = true;\n }\n }\n }\n\n return this;\n};\n\nvar noninf = function noninf(x) {\n if (x === Infinity || x === -Infinity) {\n return 0;\n }\n\n return x;\n};\n\nvar updateBounds = function updateBounds(b, x1, y1, x2, y2) {\n // don't update with zero area boxes\n if (x2 - x1 === 0 || y2 - y1 === 0) {\n return;\n } // don't update with null dim\n\n\n if (x1 == null || y1 == null || x2 == null || y2 == null) {\n return;\n }\n\n b.x1 = x1 < b.x1 ? x1 : b.x1;\n b.x2 = x2 > b.x2 ? x2 : b.x2;\n b.y1 = y1 < b.y1 ? y1 : b.y1;\n b.y2 = y2 > b.y2 ? y2 : b.y2;\n b.w = b.x2 - b.x1;\n b.h = b.y2 - b.y1;\n};\n\nvar updateBoundsFromBox = function updateBoundsFromBox(b, b2) {\n if (b2 == null) {\n return b;\n }\n\n return updateBounds(b, b2.x1, b2.y1, b2.x2, b2.y2);\n};\n\nvar prefixedProperty = function prefixedProperty(obj, field, prefix) {\n return getPrefixedProperty(obj, field, prefix);\n};\n\nvar updateBoundsFromArrow = function updateBoundsFromArrow(bounds, ele, prefix) {\n if (ele.cy().headless()) {\n return;\n }\n\n var _p = ele._private;\n var rstyle = _p.rstyle;\n var halfArW = rstyle.arrowWidth / 2;\n var arrowType = ele.pstyle(prefix + '-arrow-shape').value;\n var x;\n var y;\n\n if (arrowType !== 'none') {\n if (prefix === 'source') {\n x = rstyle.srcX;\n y = rstyle.srcY;\n } else if (prefix === 'target') {\n x = rstyle.tgtX;\n y = rstyle.tgtY;\n } else {\n x = rstyle.midX;\n y = rstyle.midY;\n } // always store the individual arrow bounds\n\n\n var bbs = _p.arrowBounds = _p.arrowBounds || {};\n var bb = bbs[prefix] = bbs[prefix] || {};\n bb.x1 = x - halfArW;\n bb.y1 = y - halfArW;\n bb.x2 = x + halfArW;\n bb.y2 = y + halfArW;\n bb.w = bb.x2 - bb.x1;\n bb.h = bb.y2 - bb.y1;\n expandBoundingBox(bb, 1);\n updateBounds(bounds, bb.x1, bb.y1, bb.x2, bb.y2);\n }\n};\n\nvar updateBoundsFromLabel = function updateBoundsFromLabel(bounds, ele, prefix) {\n if (ele.cy().headless()) {\n return;\n }\n\n var prefixDash;\n\n if (prefix) {\n prefixDash = prefix + '-';\n } else {\n prefixDash = '';\n }\n\n var _p = ele._private;\n var rstyle = _p.rstyle;\n var label = ele.pstyle(prefixDash + 'label').strValue;\n\n if (label) {\n var halign = ele.pstyle('text-halign');\n var valign = ele.pstyle('text-valign');\n var labelWidth = prefixedProperty(rstyle, 'labelWidth', prefix);\n var labelHeight = prefixedProperty(rstyle, 'labelHeight', prefix);\n var labelX = prefixedProperty(rstyle, 'labelX', prefix);\n var labelY = prefixedProperty(rstyle, 'labelY', prefix);\n var marginX = ele.pstyle(prefixDash + 'text-margin-x').pfValue;\n var marginY = ele.pstyle(prefixDash + 'text-margin-y').pfValue;\n var isEdge = ele.isEdge();\n var rotation = ele.pstyle(prefixDash + 'text-rotation');\n var outlineWidth = ele.pstyle('text-outline-width').pfValue;\n var borderWidth = ele.pstyle('text-border-width').pfValue;\n var halfBorderWidth = borderWidth / 2;\n var padding = ele.pstyle('text-background-padding').pfValue;\n var lh = labelHeight;\n var lw = labelWidth;\n var lw_2 = lw / 2;\n var lh_2 = lh / 2;\n var lx1, lx2, ly1, ly2;\n\n if (isEdge) {\n lx1 = labelX - lw_2;\n lx2 = labelX + lw_2;\n ly1 = labelY - lh_2;\n ly2 = labelY + lh_2;\n } else {\n switch (halign.value) {\n case 'left':\n lx1 = labelX - lw;\n lx2 = labelX;\n break;\n\n case 'center':\n lx1 = labelX - lw_2;\n lx2 = labelX + lw_2;\n break;\n\n case 'right':\n lx1 = labelX;\n lx2 = labelX + lw;\n break;\n }\n\n switch (valign.value) {\n case 'top':\n ly1 = labelY - lh;\n ly2 = labelY;\n break;\n\n case 'center':\n ly1 = labelY - lh_2;\n ly2 = labelY + lh_2;\n break;\n\n case 'bottom':\n ly1 = labelY;\n ly2 = labelY + lh;\n break;\n }\n } // shift by margin and expand by outline and border\n\n\n lx1 += marginX - Math.max(outlineWidth, halfBorderWidth) - padding;\n lx2 += marginX + Math.max(outlineWidth, halfBorderWidth) + padding;\n ly1 += marginY - Math.max(outlineWidth, halfBorderWidth) - padding;\n ly2 += marginY + Math.max(outlineWidth, halfBorderWidth) + padding; // always store the unrotated label bounds separately\n\n var bbPrefix = prefix || 'main';\n var bbs = _p.labelBounds;\n var bb = bbs[bbPrefix] = bbs[bbPrefix] || {};\n bb.x1 = lx1;\n bb.y1 = ly1;\n bb.x2 = lx2;\n bb.y2 = ly2;\n bb.w = lx2 - lx1;\n bb.h = ly2 - ly1;\n expandBoundingBox(bb, 1); // expand to work around browser dimension inaccuracies\n\n var isAutorotate = isEdge && rotation.strValue === 'autorotate';\n var isPfValue = rotation.pfValue != null && rotation.pfValue !== 0;\n\n if (isAutorotate || isPfValue) {\n var theta = isAutorotate ? prefixedProperty(_p.rstyle, 'labelAngle', prefix) : rotation.pfValue;\n var cos = Math.cos(theta);\n var sin = Math.sin(theta); // rotation point (default value for center-center)\n\n var xo = (lx1 + lx2) / 2;\n var yo = (ly1 + ly2) / 2;\n\n if (!isEdge) {\n switch (halign.value) {\n case 'left':\n xo = lx2;\n break;\n\n case 'right':\n xo = lx1;\n break;\n }\n\n switch (valign.value) {\n case 'top':\n yo = ly2;\n break;\n\n case 'bottom':\n yo = ly1;\n break;\n }\n }\n\n var rotate = function rotate(x, y) {\n x = x - xo;\n y = y - yo;\n return {\n x: x * cos - y * sin + xo,\n y: x * sin + y * cos + yo\n };\n };\n\n var px1y1 = rotate(lx1, ly1);\n var px1y2 = rotate(lx1, ly2);\n var px2y1 = rotate(lx2, ly1);\n var px2y2 = rotate(lx2, ly2);\n lx1 = Math.min(px1y1.x, px1y2.x, px2y1.x, px2y2.x);\n lx2 = Math.max(px1y1.x, px1y2.x, px2y1.x, px2y2.x);\n ly1 = Math.min(px1y1.y, px1y2.y, px2y1.y, px2y2.y);\n ly2 = Math.max(px1y1.y, px1y2.y, px2y1.y, px2y2.y);\n }\n\n var bbPrefixRot = bbPrefix + 'Rot';\n var bbRot = bbs[bbPrefixRot] = bbs[bbPrefixRot] || {};\n bbRot.x1 = lx1;\n bbRot.y1 = ly1;\n bbRot.x2 = lx2;\n bbRot.y2 = ly2;\n bbRot.w = lx2 - lx1;\n bbRot.h = ly2 - ly1;\n updateBounds(bounds, lx1, ly1, lx2, ly2);\n updateBounds(_p.labelBounds.all, lx1, ly1, lx2, ly2);\n }\n\n return bounds;\n}; // get the bounding box of the elements (in raw model position)\n\n\nvar boundingBoxImpl = function boundingBoxImpl(ele, options) {\n var cy = ele._private.cy;\n var styleEnabled = cy.styleEnabled();\n var headless = cy.headless();\n var bounds = makeBoundingBox();\n var _p = ele._private;\n var isNode = ele.isNode();\n var isEdge = ele.isEdge();\n var ex1, ex2, ey1, ey2; // extrema of body / lines\n\n var x, y; // node pos\n\n var rstyle = _p.rstyle;\n var manualExpansion = isNode && styleEnabled ? ele.pstyle('bounds-expansion').pfValue : [0]; // must use `display` prop only, as reading `compound.width()` causes recursion\n // (other factors like width values will be considered later in this function anyway)\n\n var isDisplayed = function isDisplayed(ele) {\n return ele.pstyle('display').value !== 'none';\n };\n\n var displayed = !styleEnabled || isDisplayed(ele) // must take into account connected nodes b/c of implicit edge hiding on display:none node\n && (!isEdge || isDisplayed(ele.source()) && isDisplayed(ele.target()));\n\n if (displayed) {\n // displayed suffices, since we will find zero area eles anyway\n var overlayOpacity = 0;\n var overlayPadding = 0;\n\n if (styleEnabled && options.includeOverlays) {\n overlayOpacity = ele.pstyle('overlay-opacity').value;\n\n if (overlayOpacity !== 0) {\n overlayPadding = ele.pstyle('overlay-padding').value;\n }\n }\n\n var w = 0;\n var wHalf = 0;\n\n if (styleEnabled) {\n w = ele.pstyle('width').pfValue;\n wHalf = w / 2;\n }\n\n if (isNode && options.includeNodes) {\n var pos = ele.position();\n x = pos.x;\n y = pos.y;\n\n var _w = ele.outerWidth();\n\n var halfW = _w / 2;\n var h = ele.outerHeight();\n var halfH = h / 2; // handle node dimensions\n /////////////////////////\n\n ex1 = x - halfW;\n ex2 = x + halfW;\n ey1 = y - halfH;\n ey2 = y + halfH;\n updateBounds(bounds, ex1, ey1, ex2, ey2);\n } else if (isEdge && options.includeEdges) {\n if (styleEnabled && !headless) {\n var curveStyle = ele.pstyle('curve-style').strValue; // handle edge dimensions (rough box estimate)\n //////////////////////////////////////////////\n\n ex1 = Math.min(rstyle.srcX, rstyle.midX, rstyle.tgtX);\n ex2 = Math.max(rstyle.srcX, rstyle.midX, rstyle.tgtX);\n ey1 = Math.min(rstyle.srcY, rstyle.midY, rstyle.tgtY);\n ey2 = Math.max(rstyle.srcY, rstyle.midY, rstyle.tgtY); // take into account edge width\n\n ex1 -= wHalf;\n ex2 += wHalf;\n ey1 -= wHalf;\n ey2 += wHalf;\n updateBounds(bounds, ex1, ey1, ex2, ey2); // precise edges\n ////////////////\n\n if (curveStyle === 'haystack') {\n var hpts = rstyle.haystackPts;\n\n if (hpts && hpts.length === 2) {\n ex1 = hpts[0].x;\n ey1 = hpts[0].y;\n ex2 = hpts[1].x;\n ey2 = hpts[1].y;\n\n if (ex1 > ex2) {\n var temp = ex1;\n ex1 = ex2;\n ex2 = temp;\n }\n\n if (ey1 > ey2) {\n var _temp = ey1;\n ey1 = ey2;\n ey2 = _temp;\n }\n\n updateBounds(bounds, ex1 - wHalf, ey1 - wHalf, ex2 + wHalf, ey2 + wHalf);\n }\n } else if (curveStyle === 'bezier' || curveStyle === 'unbundled-bezier' || curveStyle === 'segments' || curveStyle === 'taxi') {\n var pts;\n\n switch (curveStyle) {\n case 'bezier':\n case 'unbundled-bezier':\n pts = rstyle.bezierPts;\n break;\n\n case 'segments':\n case 'taxi':\n pts = rstyle.linePts;\n break;\n }\n\n if (pts != null) {\n for (var j = 0; j < pts.length; j++) {\n var pt = pts[j];\n ex1 = pt.x - wHalf;\n ex2 = pt.x + wHalf;\n ey1 = pt.y - wHalf;\n ey2 = pt.y + wHalf;\n updateBounds(bounds, ex1, ey1, ex2, ey2);\n }\n }\n } // bezier-like or segment-like edge\n\n } else {\n // headless or style disabled\n // fallback on source and target positions\n //////////////////////////////////////////\n var n1 = ele.source();\n var n1pos = n1.position();\n var n2 = ele.target();\n var n2pos = n2.position();\n ex1 = n1pos.x;\n ex2 = n2pos.x;\n ey1 = n1pos.y;\n ey2 = n2pos.y;\n\n if (ex1 > ex2) {\n var _temp2 = ex1;\n ex1 = ex2;\n ex2 = _temp2;\n }\n\n if (ey1 > ey2) {\n var _temp3 = ey1;\n ey1 = ey2;\n ey2 = _temp3;\n } // take into account edge width\n\n\n ex1 -= wHalf;\n ex2 += wHalf;\n ey1 -= wHalf;\n ey2 += wHalf;\n updateBounds(bounds, ex1, ey1, ex2, ey2);\n } // headless or style disabled\n\n } // edges\n // handle edge arrow size\n /////////////////////////\n\n\n if (styleEnabled && options.includeEdges && isEdge) {\n updateBoundsFromArrow(bounds, ele, 'mid-source');\n updateBoundsFromArrow(bounds, ele, 'mid-target');\n updateBoundsFromArrow(bounds, ele, 'source');\n updateBoundsFromArrow(bounds, ele, 'target');\n } // ghost\n ////////\n\n\n if (styleEnabled) {\n var ghost = ele.pstyle('ghost').value === 'yes';\n\n if (ghost) {\n var gx = ele.pstyle('ghost-offset-x').pfValue;\n var gy = ele.pstyle('ghost-offset-y').pfValue;\n updateBounds(bounds, bounds.x1 + gx, bounds.y1 + gy, bounds.x2 + gx, bounds.y2 + gy);\n }\n } // always store the body bounds separately from the labels\n\n\n var bbBody = _p.bodyBounds = _p.bodyBounds || {};\n assignBoundingBox(bbBody, bounds);\n expandBoundingBoxSides(bbBody, manualExpansion);\n expandBoundingBox(bbBody, 1); // expand to work around browser dimension inaccuracies\n // overlay\n //////////\n\n if (styleEnabled) {\n ex1 = bounds.x1;\n ex2 = bounds.x2;\n ey1 = bounds.y1;\n ey2 = bounds.y2;\n updateBounds(bounds, ex1 - overlayPadding, ey1 - overlayPadding, ex2 + overlayPadding, ey2 + overlayPadding);\n } // always store the body bounds separately from the labels\n\n\n var bbOverlay = _p.overlayBounds = _p.overlayBounds || {};\n assignBoundingBox(bbOverlay, bounds);\n expandBoundingBoxSides(bbOverlay, manualExpansion);\n expandBoundingBox(bbOverlay, 1); // expand to work around browser dimension inaccuracies\n // handle label dimensions\n //////////////////////////\n\n var bbLabels = _p.labelBounds = _p.labelBounds || {};\n\n if (bbLabels.all != null) {\n clearBoundingBox(bbLabels.all);\n } else {\n bbLabels.all = makeBoundingBox();\n }\n\n if (styleEnabled && options.includeLabels) {\n if (options.includeMainLabels) {\n updateBoundsFromLabel(bounds, ele, null);\n }\n\n if (isEdge) {\n if (options.includeSourceLabels) {\n updateBoundsFromLabel(bounds, ele, 'source');\n }\n\n if (options.includeTargetLabels) {\n updateBoundsFromLabel(bounds, ele, 'target');\n }\n }\n } // style enabled for labels\n\n } // if displayed\n\n\n bounds.x1 = noninf(bounds.x1);\n bounds.y1 = noninf(bounds.y1);\n bounds.x2 = noninf(bounds.x2);\n bounds.y2 = noninf(bounds.y2);\n bounds.w = noninf(bounds.x2 - bounds.x1);\n bounds.h = noninf(bounds.y2 - bounds.y1);\n\n if (bounds.w > 0 && bounds.h > 0 && displayed) {\n expandBoundingBoxSides(bounds, manualExpansion); // expand bounds by 1 because antialiasing can increase the visual/effective size by 1 on all sides\n\n expandBoundingBox(bounds, 1);\n }\n\n return bounds;\n};\n\nvar getKey = function getKey(opts) {\n var i = 0;\n\n var tf = function tf(val) {\n return (val ? 1 : 0) << i++;\n };\n\n var key = 0;\n key += tf(opts.incudeNodes);\n key += tf(opts.includeEdges);\n key += tf(opts.includeLabels);\n key += tf(opts.includeMainLabels);\n key += tf(opts.includeSourceLabels);\n key += tf(opts.includeTargetLabels);\n key += tf(opts.includeOverlays);\n return key;\n};\n\nvar getBoundingBoxPosKey = function getBoundingBoxPosKey(ele) {\n if (ele.isEdge()) {\n var p1 = ele.source().position();\n var p2 = ele.target().position();\n\n var r = function r(x) {\n return Math.round(x);\n };\n\n return hashIntsArray([r(p1.x), r(p1.y), r(p2.x), r(p2.y)]);\n } else {\n return 0;\n }\n};\n\nvar cachedBoundingBoxImpl = function cachedBoundingBoxImpl(ele, opts) {\n var _p = ele._private;\n var bb;\n var isEdge = ele.isEdge();\n var key = opts == null ? defBbOptsKey : getKey(opts);\n var usingDefOpts = key === defBbOptsKey;\n var currPosKey = getBoundingBoxPosKey(ele);\n var isPosKeySame = _p.bbCachePosKey === currPosKey;\n var useCache = opts.useCache && isPosKeySame;\n\n var isDirty = function isDirty(ele) {\n return ele._private.bbCache == null;\n };\n\n var needRecalc = !useCache || isDirty(ele) || isEdge && isDirty(ele.source()) || isDirty(ele.target());\n\n if (needRecalc) {\n if (!isPosKeySame) {\n ele.recalculateRenderedStyle();\n }\n\n bb = boundingBoxImpl(ele, defBbOpts);\n _p.bbCache = bb;\n _p.bbCacheShift.x = _p.bbCacheShift.y = 0;\n _p.bbCachePosKey = currPosKey;\n } else {\n bb = _p.bbCache;\n }\n\n if (!needRecalc && (_p.bbCacheShift.x !== 0 || _p.bbCacheShift.y !== 0)) {\n var shift = assignShiftToBoundingBox;\n var delta = _p.bbCacheShift;\n\n var safeShift = function safeShift(bb, delta) {\n if (bb != null) {\n shift(bb, delta);\n }\n };\n\n shift(bb, delta);\n var bodyBounds = _p.bodyBounds,\n overlayBounds = _p.overlayBounds,\n labelBounds = _p.labelBounds,\n arrowBounds = _p.arrowBounds;\n safeShift(bodyBounds, delta);\n safeShift(overlayBounds, delta);\n\n if (arrowBounds != null) {\n safeShift(arrowBounds.source, delta);\n safeShift(arrowBounds.target, delta);\n safeShift(arrowBounds['mid-source'], delta);\n safeShift(arrowBounds['mid-target'], delta);\n }\n\n if (labelBounds != null) {\n safeShift(labelBounds.main, delta);\n safeShift(labelBounds.all, delta);\n safeShift(labelBounds.source, delta);\n safeShift(labelBounds.target, delta);\n }\n } // always reset the shift, because we either applied the shift or cleared it by doing a fresh recalc\n\n\n _p.bbCacheShift.x = _p.bbCacheShift.y = 0; // not using def opts => need to build up bb from combination of sub bbs\n\n if (!usingDefOpts) {\n var isNode = ele.isNode();\n bb = makeBoundingBox();\n\n if (opts.includeNodes && isNode || opts.includeEdges && !isNode) {\n if (opts.includeOverlays) {\n updateBoundsFromBox(bb, _p.overlayBounds);\n } else {\n updateBoundsFromBox(bb, _p.bodyBounds);\n }\n }\n\n if (opts.includeLabels) {\n if (opts.includeMainLabels && (!isEdge || opts.includeSourceLabels && opts.includeTargetLabels)) {\n updateBoundsFromBox(bb, _p.labelBounds.all);\n } else {\n if (opts.includeMainLabels) {\n updateBoundsFromBox(bb, _p.labelBounds.mainRot);\n }\n\n if (opts.includeSourceLabels) {\n updateBoundsFromBox(bb, _p.labelBounds.sourceRot);\n }\n\n if (opts.includeTargetLabels) {\n updateBoundsFromBox(bb, _p.labelBounds.targetRot);\n }\n }\n }\n\n bb.w = bb.x2 - bb.x1;\n bb.h = bb.y2 - bb.y1;\n }\n\n return bb;\n};\n\nvar defBbOpts = {\n includeNodes: true,\n includeEdges: true,\n includeLabels: true,\n includeMainLabels: true,\n includeSourceLabels: true,\n includeTargetLabels: true,\n includeOverlays: true,\n useCache: true\n};\nvar defBbOptsKey = getKey(defBbOpts);\nvar filledBbOpts = defaults(defBbOpts);\n\nelesfn$k.boundingBox = function (options) {\n var bounds; // the main usecase is ele.boundingBox() for a single element with no/def options\n // specified s.t. the cache is used, so check for this case to make it faster by\n // avoiding the overhead of the rest of the function\n\n if (this.length === 1 && this[0]._private.bbCache != null && (options === undefined || options.useCache === undefined || options.useCache === true)) {\n if (options === undefined) {\n options = defBbOpts;\n } else {\n options = filledBbOpts(options);\n }\n\n bounds = cachedBoundingBoxImpl(this[0], options);\n } else {\n bounds = makeBoundingBox();\n options = options || defBbOpts;\n var opts = filledBbOpts(options);\n var eles = this;\n var cy = eles.cy();\n var styleEnabled = cy.styleEnabled();\n\n if (styleEnabled) {\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var _p = ele._private;\n var currPosKey = getBoundingBoxPosKey(ele);\n var isPosKeySame = _p.bbCachePosKey === currPosKey;\n var useCache = opts.useCache && isPosKeySame;\n ele.recalculateRenderedStyle(useCache);\n }\n }\n\n this.updateCompoundBounds();\n\n for (var _i = 0; _i < eles.length; _i++) {\n var _ele = eles[_i];\n updateBoundsFromBox(bounds, cachedBoundingBoxImpl(_ele, opts));\n }\n }\n\n bounds.x1 = noninf(bounds.x1);\n bounds.y1 = noninf(bounds.y1);\n bounds.x2 = noninf(bounds.x2);\n bounds.y2 = noninf(bounds.y2);\n bounds.w = noninf(bounds.x2 - bounds.x1);\n bounds.h = noninf(bounds.y2 - bounds.y1);\n return bounds;\n};\n\nelesfn$k.dirtyBoundingBoxCache = function () {\n for (var i = 0; i < this.length; i++) {\n var _p = this[i]._private;\n _p.bbCache = null;\n _p.bbCacheShift.x = _p.bbCacheShift.y = 0;\n _p.bbCachePosKey = null;\n _p.bodyBounds = null;\n _p.overlayBounds = null;\n _p.labelBounds.all = null;\n _p.labelBounds.source = null;\n _p.labelBounds.target = null;\n _p.labelBounds.main = null;\n _p.labelBounds.sourceRot = null;\n _p.labelBounds.targetRot = null;\n _p.labelBounds.mainRot = null;\n _p.arrowBounds.source = null;\n _p.arrowBounds.target = null;\n _p.arrowBounds['mid-source'] = null;\n _p.arrowBounds['mid-target'] = null;\n }\n\n this.emitAndNotify('bounds');\n return this;\n};\n\nelesfn$k.shiftCachedBoundingBox = function (delta) {\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var _p = ele._private;\n var bb = _p.bbCache;\n\n if (bb != null) {\n _p.bbCacheShift.x += delta.x;\n _p.bbCacheShift.y += delta.y;\n }\n }\n\n this.emitAndNotify('bounds');\n return this;\n}; // private helper to get bounding box for custom node positions\n// - good for perf in certain cases but currently requires dirtying the rendered style\n// - would be better to not modify the nodes but the nodes are read directly everywhere in the renderer...\n// - try to use for only things like discrete layouts where the node position would change anyway\n\n\nelesfn$k.boundingBoxAt = function (fn) {\n var nodes = this.nodes();\n var cy = this.cy();\n var hasCompoundNodes = cy.hasCompoundNodes();\n\n if (hasCompoundNodes) {\n nodes = nodes.filter(function (node) {\n return !node.isParent();\n });\n }\n\n if (plainObject(fn)) {\n var obj = fn;\n\n fn = function fn() {\n return obj;\n };\n }\n\n var storeOldPos = function storeOldPos(node, i) {\n return node._private.bbAtOldPos = fn(node, i);\n };\n\n var getOldPos = function getOldPos(node) {\n return node._private.bbAtOldPos;\n };\n\n cy.startBatch();\n nodes.forEach(storeOldPos).silentPositions(fn);\n\n if (hasCompoundNodes) {\n this.updateCompoundBounds(true); // force update b/c we're inside a batch cycle\n }\n\n var bb = copyBoundingBox(this.boundingBox({\n useCache: false\n }));\n nodes.silentPositions(getOldPos);\n cy.endBatch();\n return bb;\n};\n\nfn$3.boundingbox = fn$3.bb = fn$3.boundingBox;\nfn$3.renderedBoundingbox = fn$3.renderedBoundingBox;\nvar bounds = elesfn$k;\n\nvar fn$4, elesfn$l;\nfn$4 = elesfn$l = {};\n\nvar defineDimFns = function defineDimFns(opts) {\n opts.uppercaseName = capitalize(opts.name);\n opts.autoName = 'auto' + opts.uppercaseName;\n opts.labelName = 'label' + opts.uppercaseName;\n opts.outerName = 'outer' + opts.uppercaseName;\n opts.uppercaseOuterName = capitalize(opts.outerName);\n\n fn$4[opts.name] = function dimImpl() {\n var ele = this[0];\n var _p = ele._private;\n var cy = _p.cy;\n var styleEnabled = cy._private.styleEnabled;\n\n if (ele) {\n if (styleEnabled) {\n if (ele.isParent()) {\n ele.updateCompoundBounds();\n return _p[opts.autoName] || 0;\n }\n\n var d = ele.pstyle(opts.name);\n\n switch (d.strValue) {\n case 'label':\n ele.recalculateRenderedStyle();\n return _p.rstyle[opts.labelName] || 0;\n\n default:\n return d.pfValue;\n }\n } else {\n return 1;\n }\n }\n };\n\n fn$4['outer' + opts.uppercaseName] = function outerDimImpl() {\n var ele = this[0];\n var _p = ele._private;\n var cy = _p.cy;\n var styleEnabled = cy._private.styleEnabled;\n\n if (ele) {\n if (styleEnabled) {\n var dim = ele[opts.name]();\n var border = ele.pstyle('border-width').pfValue; // n.b. 1/2 each side\n\n var padding = 2 * ele.padding();\n return dim + border + padding;\n } else {\n return 1;\n }\n }\n };\n\n fn$4['rendered' + opts.uppercaseName] = function renderedDimImpl() {\n var ele = this[0];\n\n if (ele) {\n var d = ele[opts.name]();\n return d * this.cy().zoom();\n }\n };\n\n fn$4['rendered' + opts.uppercaseOuterName] = function renderedOuterDimImpl() {\n var ele = this[0];\n\n if (ele) {\n var od = ele[opts.outerName]();\n return od * this.cy().zoom();\n }\n };\n};\n\ndefineDimFns({\n name: 'width'\n});\ndefineDimFns({\n name: 'height'\n});\n\nelesfn$l.padding = function () {\n var ele = this[0];\n var _p = ele._private;\n\n if (ele.isParent()) {\n ele.updateCompoundBounds();\n\n if (_p.autoPadding !== undefined) {\n return _p.autoPadding;\n } else {\n return ele.pstyle('padding').pfValue;\n }\n } else {\n return ele.pstyle('padding').pfValue;\n }\n};\n\nelesfn$l.paddedHeight = function () {\n var ele = this[0];\n return ele.height() + 2 * ele.padding();\n};\n\nelesfn$l.paddedWidth = function () {\n var ele = this[0];\n return ele.width() + 2 * ele.padding();\n};\n\nvar widthHeight = elesfn$l;\n\nvar ifEdge = function ifEdge(ele, getValue) {\n if (ele.isEdge()) {\n return getValue(ele);\n }\n};\n\nvar ifEdgeRenderedPosition = function ifEdgeRenderedPosition(ele, getPoint) {\n if (ele.isEdge()) {\n var cy = ele.cy();\n return modelToRenderedPosition(getPoint(ele), cy.zoom(), cy.pan());\n }\n};\n\nvar ifEdgeRenderedPositions = function ifEdgeRenderedPositions(ele, getPoints) {\n if (ele.isEdge()) {\n var cy = ele.cy();\n var pan = cy.pan();\n var zoom = cy.zoom();\n return getPoints(ele).map(function (p) {\n return modelToRenderedPosition(p, zoom, pan);\n });\n }\n};\n\nvar controlPoints = function controlPoints(ele) {\n return ele.renderer().getControlPoints(ele);\n};\n\nvar segmentPoints = function segmentPoints(ele) {\n return ele.renderer().getSegmentPoints(ele);\n};\n\nvar sourceEndpoint = function sourceEndpoint(ele) {\n return ele.renderer().getSourceEndpoint(ele);\n};\n\nvar targetEndpoint = function targetEndpoint(ele) {\n return ele.renderer().getTargetEndpoint(ele);\n};\n\nvar midpoint = function midpoint(ele) {\n return ele.renderer().getEdgeMidpoint(ele);\n};\n\nvar pts = {\n controlPoints: {\n get: controlPoints,\n mult: true\n },\n segmentPoints: {\n get: segmentPoints,\n mult: true\n },\n sourceEndpoint: {\n get: sourceEndpoint\n },\n targetEndpoint: {\n get: targetEndpoint\n },\n midpoint: {\n get: midpoint\n }\n};\n\nvar renderedName = function renderedName(name) {\n return 'rendered' + name[0].toUpperCase() + name.substr(1);\n};\n\nvar edgePoints = Object.keys(pts).reduce(function (obj, name) {\n var spec = pts[name];\n var rName = renderedName(name);\n\n obj[name] = function () {\n return ifEdge(this, spec.get);\n };\n\n if (spec.mult) {\n obj[rName] = function () {\n return ifEdgeRenderedPositions(this, spec.get);\n };\n } else {\n obj[rName] = function () {\n return ifEdgeRenderedPosition(this, spec.get);\n };\n }\n\n return obj;\n}, {});\n\nvar dimensions = extend({}, position, bounds, widthHeight, edgePoints);\n\n/*!\nEvent object based on jQuery events, MIT license\n\nhttps://jquery.org/license/\nhttps://tldrlegal.com/license/mit-license\nhttps://github.com/jquery/jquery/blob/master/src/event.js\n*/\nvar Event = function Event(src, props) {\n this.recycle(src, props);\n};\n\nfunction returnFalse() {\n return false;\n}\n\nfunction returnTrue() {\n return true;\n} // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\n\n\nEvent.prototype = {\n instanceString: function instanceString() {\n return 'event';\n },\n recycle: function recycle(src, props) {\n this.isImmediatePropagationStopped = this.isPropagationStopped = this.isDefaultPrevented = returnFalse;\n\n if (src != null && src.preventDefault) {\n // Browser Event object\n this.type = src.type; // Events bubbling up the document may have been marked as prevented\n // by a handler lower down the tree; reflect the correct value.\n\n this.isDefaultPrevented = src.defaultPrevented ? returnTrue : returnFalse;\n } else if (src != null && src.type) {\n // Plain object containing all event details\n props = src;\n } else {\n // Event string\n this.type = src;\n } // Put explicitly provided properties onto the event object\n\n\n if (props != null) {\n // more efficient to manually copy fields we use\n this.originalEvent = props.originalEvent;\n this.type = props.type != null ? props.type : this.type;\n this.cy = props.cy;\n this.target = props.target;\n this.position = props.position;\n this.renderedPosition = props.renderedPosition;\n this.namespace = props.namespace;\n this.layout = props.layout;\n }\n\n if (this.cy != null && this.position != null && this.renderedPosition == null) {\n // create a rendered position based on the passed position\n var pos = this.position;\n var zoom = this.cy.zoom();\n var pan = this.cy.pan();\n this.renderedPosition = {\n x: pos.x * zoom + pan.x,\n y: pos.y * zoom + pan.y\n };\n } // Create a timestamp if incoming event doesn't have one\n\n\n this.timeStamp = src && src.timeStamp || Date.now();\n },\n preventDefault: function preventDefault() {\n this.isDefaultPrevented = returnTrue;\n var e = this.originalEvent;\n\n if (!e) {\n return;\n } // if preventDefault exists run it on the original event\n\n\n if (e.preventDefault) {\n e.preventDefault();\n }\n },\n stopPropagation: function stopPropagation() {\n this.isPropagationStopped = returnTrue;\n var e = this.originalEvent;\n\n if (!e) {\n return;\n } // if stopPropagation exists run it on the original event\n\n\n if (e.stopPropagation) {\n e.stopPropagation();\n }\n },\n stopImmediatePropagation: function stopImmediatePropagation() {\n this.isImmediatePropagationStopped = returnTrue;\n this.stopPropagation();\n },\n isDefaultPrevented: returnFalse,\n isPropagationStopped: returnFalse,\n isImmediatePropagationStopped: returnFalse\n};\n\nvar eventRegex = /^([^.]+)(\\.(?:[^.]+))?$/; // regex for matching event strings (e.g. \"click.namespace\")\n\nvar universalNamespace = '.*'; // matches as if no namespace specified and prevents users from unbinding accidentally\n\nvar defaults$8 = {\n qualifierCompare: function qualifierCompare(q1, q2) {\n return q1 === q2;\n },\n eventMatches: function eventMatches()\n /*context, listener, eventObj*/\n {\n return true;\n },\n addEventFields: function addEventFields()\n /*context, evt*/\n {},\n callbackContext: function callbackContext(context\n /*, listener, eventObj*/\n ) {\n return context;\n },\n beforeEmit: function beforeEmit()\n /* context, listener, eventObj */\n {},\n afterEmit: function afterEmit()\n /* context, listener, eventObj */\n {},\n bubble: function bubble()\n /*context*/\n {\n return false;\n },\n parent: function parent()\n /*context*/\n {\n return null;\n },\n context: null\n};\nvar defaultsKeys = Object.keys(defaults$8);\nvar emptyOpts = {};\n\nfunction Emitter() {\n var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : emptyOpts;\n var context = arguments.length > 1 ? arguments[1] : undefined;\n\n // micro-optimisation vs Object.assign() -- reduces Element instantiation time\n for (var i = 0; i < defaultsKeys.length; i++) {\n var key = defaultsKeys[i];\n this[key] = opts[key] || defaults$8[key];\n }\n\n this.context = context || this.context;\n this.listeners = [];\n this.emitting = 0;\n}\n\nvar p = Emitter.prototype;\n\nvar forEachEvent = function forEachEvent(self, handler, events, qualifier, callback, conf, confOverrides) {\n if (fn(qualifier)) {\n callback = qualifier;\n qualifier = null;\n }\n\n if (confOverrides) {\n if (conf == null) {\n conf = confOverrides;\n } else {\n conf = extend({}, conf, confOverrides);\n }\n }\n\n var eventList = array(events) ? events : events.split(/\\s+/);\n\n for (var i = 0; i < eventList.length; i++) {\n var evt = eventList[i];\n\n if (emptyString(evt)) {\n continue;\n }\n\n var match = evt.match(eventRegex); // type[.namespace]\n\n if (match) {\n var type = match[1];\n var namespace = match[2] ? match[2] : null;\n var ret = handler(self, evt, type, namespace, qualifier, callback, conf);\n\n if (ret === false) {\n break;\n } // allow exiting early\n\n }\n }\n};\n\nvar makeEventObj = function makeEventObj(self, obj) {\n self.addEventFields(self.context, obj);\n return new Event(obj.type, obj);\n};\n\nvar forEachEventObj = function forEachEventObj(self, handler, events) {\n if (event(events)) {\n handler(self, events);\n return;\n } else if (plainObject(events)) {\n handler(self, makeEventObj(self, events));\n return;\n }\n\n var eventList = array(events) ? events : events.split(/\\s+/);\n\n for (var i = 0; i < eventList.length; i++) {\n var evt = eventList[i];\n\n if (emptyString(evt)) {\n continue;\n }\n\n var match = evt.match(eventRegex); // type[.namespace]\n\n if (match) {\n var type = match[1];\n var namespace = match[2] ? match[2] : null;\n var eventObj = makeEventObj(self, {\n type: type,\n namespace: namespace,\n target: self.context\n });\n handler(self, eventObj);\n }\n }\n};\n\np.on = p.addListener = function (events, qualifier, callback, conf, confOverrides) {\n forEachEvent(this, function (self, event, type, namespace, qualifier, callback, conf) {\n if (fn(callback)) {\n self.listeners.push({\n event: event,\n // full event string\n callback: callback,\n // callback to run\n type: type,\n // the event type (e.g. 'click')\n namespace: namespace,\n // the event namespace (e.g. \".foo\")\n qualifier: qualifier,\n // a restriction on whether to match this emitter\n conf: conf // additional configuration\n\n });\n }\n }, events, qualifier, callback, conf, confOverrides);\n return this;\n};\n\np.one = function (events, qualifier, callback, conf) {\n return this.on(events, qualifier, callback, conf, {\n one: true\n });\n};\n\np.removeListener = p.off = function (events, qualifier, callback, conf) {\n var _this = this;\n\n if (this.emitting !== 0) {\n this.listeners = copyArray(this.listeners);\n }\n\n var listeners = this.listeners;\n\n var _loop = function _loop(i) {\n var listener = listeners[i];\n forEachEvent(_this, function (self, event, type, namespace, qualifier, callback\n /*, conf*/\n ) {\n if ((listener.type === type || events === '*') && (!namespace && listener.namespace !== '.*' || listener.namespace === namespace) && (!qualifier || self.qualifierCompare(listener.qualifier, qualifier)) && (!callback || listener.callback === callback)) {\n listeners.splice(i, 1);\n return false;\n }\n }, events, qualifier, callback, conf);\n };\n\n for (var i = listeners.length - 1; i >= 0; i--) {\n _loop(i);\n }\n\n return this;\n};\n\np.removeAllListeners = function () {\n return this.removeListener('*');\n};\n\np.emit = p.trigger = function (events, extraParams, manualCallback) {\n var listeners = this.listeners;\n var numListenersBeforeEmit = listeners.length;\n this.emitting++;\n\n if (!array(extraParams)) {\n extraParams = [extraParams];\n }\n\n forEachEventObj(this, function (self, eventObj) {\n if (manualCallback != null) {\n listeners = [{\n event: eventObj.event,\n type: eventObj.type,\n namespace: eventObj.namespace,\n callback: manualCallback\n }];\n numListenersBeforeEmit = listeners.length;\n }\n\n var _loop2 = function _loop2(i) {\n var listener = listeners[i];\n\n if (listener.type === eventObj.type && (!listener.namespace || listener.namespace === eventObj.namespace || listener.namespace === universalNamespace) && self.eventMatches(self.context, listener, eventObj)) {\n var args = [eventObj];\n\n if (extraParams != null) {\n push(args, extraParams);\n }\n\n self.beforeEmit(self.context, listener, eventObj);\n\n if (listener.conf && listener.conf.one) {\n self.listeners = self.listeners.filter(function (l) {\n return l !== listener;\n });\n }\n\n var context = self.callbackContext(self.context, listener, eventObj);\n var ret = listener.callback.apply(context, args);\n self.afterEmit(self.context, listener, eventObj);\n\n if (ret === false) {\n eventObj.stopPropagation();\n eventObj.preventDefault();\n }\n } // if listener matches\n\n };\n\n for (var i = 0; i < numListenersBeforeEmit; i++) {\n _loop2(i);\n } // for listener\n\n\n if (self.bubble(self.context) && !eventObj.isPropagationStopped()) {\n self.parent(self.context).emit(eventObj, extraParams);\n }\n }, events);\n this.emitting--;\n return this;\n};\n\nvar emitterOptions = {\n qualifierCompare: function qualifierCompare(selector1, selector2) {\n if (selector1 == null || selector2 == null) {\n return selector1 == null && selector2 == null;\n } else {\n return selector1.sameText(selector2);\n }\n },\n eventMatches: function eventMatches(ele, listener, eventObj) {\n var selector = listener.qualifier;\n\n if (selector != null) {\n return ele !== eventObj.target && element(eventObj.target) && selector.matches(eventObj.target);\n }\n\n return true;\n },\n addEventFields: function addEventFields(ele, evt) {\n evt.cy = ele.cy();\n evt.target = ele;\n },\n callbackContext: function callbackContext(ele, listener, eventObj) {\n return listener.qualifier != null ? eventObj.target : ele;\n },\n beforeEmit: function beforeEmit(context, listener\n /*, eventObj*/\n ) {\n if (listener.conf && listener.conf.once) {\n listener.conf.onceCollection.removeListener(listener.event, listener.qualifier, listener.callback);\n }\n },\n bubble: function bubble() {\n return true;\n },\n parent: function parent(ele) {\n return ele.isChild() ? ele.parent() : ele.cy();\n }\n};\n\nvar argSelector = function argSelector(arg) {\n if (string(arg)) {\n return new Selector(arg);\n } else {\n return arg;\n }\n};\n\nvar elesfn$m = {\n createEmitter: function createEmitter() {\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var _p = ele._private;\n\n if (!_p.emitter) {\n _p.emitter = new Emitter(emitterOptions, ele);\n }\n }\n\n return this;\n },\n emitter: function emitter() {\n return this._private.emitter;\n },\n on: function on(events, selector, callback) {\n var argSel = argSelector(selector);\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n ele.emitter().on(events, argSel, callback);\n }\n\n return this;\n },\n removeListener: function removeListener(events, selector, callback) {\n var argSel = argSelector(selector);\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n ele.emitter().removeListener(events, argSel, callback);\n }\n\n return this;\n },\n removeAllListeners: function removeAllListeners() {\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n ele.emitter().removeAllListeners();\n }\n\n return this;\n },\n one: function one(events, selector, callback) {\n var argSel = argSelector(selector);\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n ele.emitter().one(events, argSel, callback);\n }\n\n return this;\n },\n once: function once(events, selector, callback) {\n var argSel = argSelector(selector);\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n ele.emitter().on(events, argSel, callback, {\n once: true,\n onceCollection: this\n });\n }\n },\n emit: function emit(events, extraParams) {\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n ele.emitter().emit(events, extraParams);\n }\n\n return this;\n },\n emitAndNotify: function emitAndNotify(event, extraParams) {\n // for internal use only\n if (this.length === 0) {\n return;\n } // empty collections don't need to notify anything\n // notify renderer\n\n\n this.cy().notify(event, this);\n this.emit(event, extraParams);\n return this;\n }\n};\ndefine$3.eventAliasesOn(elesfn$m);\n\nvar elesfn$n = {\n nodes: function nodes(selector) {\n return this.filter(function (ele) {\n return ele.isNode();\n }).filter(selector);\n },\n edges: function edges(selector) {\n return this.filter(function (ele) {\n return ele.isEdge();\n }).filter(selector);\n },\n // internal helper to get nodes and edges as separate collections with single iteration over elements\n byGroup: function byGroup() {\n var nodes = this.spawn();\n var edges = this.spawn();\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n\n if (ele.isNode()) {\n nodes.merge(ele);\n } else {\n edges.merge(ele);\n }\n }\n\n return {\n nodes: nodes,\n edges: edges\n };\n },\n filter: function filter(_filter, thisArg) {\n if (_filter === undefined) {\n // check this first b/c it's the most common/performant case\n return this;\n } else if (string(_filter) || elementOrCollection(_filter)) {\n return new Selector(_filter).filter(this);\n } else if (fn(_filter)) {\n var filterEles = this.spawn();\n var eles = this;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var include = thisArg ? _filter.apply(thisArg, [ele, i, eles]) : _filter(ele, i, eles);\n\n if (include) {\n filterEles.merge(ele);\n }\n }\n\n return filterEles;\n }\n\n return this.spawn(); // if not handled by above, give 'em an empty collection\n },\n not: function not(toRemove) {\n if (!toRemove) {\n return this;\n } else {\n if (string(toRemove)) {\n toRemove = this.filter(toRemove);\n }\n\n var elements = [];\n var rMap = toRemove._private.map;\n\n for (var i = 0; i < this.length; i++) {\n var element = this[i];\n var remove = rMap.has(element.id());\n\n if (!remove) {\n elements.push(element);\n }\n }\n\n return this.spawn(elements);\n }\n },\n absoluteComplement: function absoluteComplement() {\n var cy = this.cy();\n return cy.mutableElements().not(this);\n },\n intersect: function intersect(other) {\n // if a selector is specified, then filter by it instead\n if (string(other)) {\n var selector = other;\n return this.filter(selector);\n }\n\n var elements = [];\n var col1 = this;\n var col2 = other;\n var col1Smaller = this.length < other.length;\n var map2 = col1Smaller ? col2._private.map : col1._private.map;\n var col = col1Smaller ? col1 : col2;\n\n for (var i = 0; i < col.length; i++) {\n var id = col[i]._private.data.id;\n var entry = map2.get(id);\n\n if (entry) {\n elements.push(entry.ele);\n }\n }\n\n return this.spawn(elements);\n },\n xor: function xor(other) {\n var cy = this._private.cy;\n\n if (string(other)) {\n other = cy.$(other);\n }\n\n var elements = [];\n var col1 = this;\n var col2 = other;\n\n var add = function add(col, other) {\n for (var i = 0; i < col.length; i++) {\n var ele = col[i];\n var id = ele._private.data.id;\n var inOther = other.hasElementWithId(id);\n\n if (!inOther) {\n elements.push(ele);\n }\n }\n };\n\n add(col1, col2);\n add(col2, col1);\n return this.spawn(elements);\n },\n diff: function diff(other) {\n var cy = this._private.cy;\n\n if (string(other)) {\n other = cy.$(other);\n }\n\n var left = [];\n var right = [];\n var both = [];\n var col1 = this;\n var col2 = other;\n\n var add = function add(col, other, retEles) {\n for (var i = 0; i < col.length; i++) {\n var ele = col[i];\n var id = ele._private.data.id;\n var inOther = other.hasElementWithId(id);\n\n if (inOther) {\n both.push(ele);\n } else {\n retEles.push(ele);\n }\n }\n };\n\n add(col1, col2, left);\n add(col2, col1, right);\n return {\n left: this.spawn(left, {\n unique: true\n }),\n right: this.spawn(right, {\n unique: true\n }),\n both: this.spawn(both, {\n unique: true\n })\n };\n },\n add: function add(toAdd) {\n var cy = this._private.cy;\n\n if (!toAdd) {\n return this;\n }\n\n if (string(toAdd)) {\n var selector = toAdd;\n toAdd = cy.mutableElements().filter(selector);\n }\n\n var elements = [];\n\n for (var i = 0; i < this.length; i++) {\n elements.push(this[i]);\n }\n\n var map = this._private.map;\n\n for (var _i = 0; _i < toAdd.length; _i++) {\n var add = !map.has(toAdd[_i].id());\n\n if (add) {\n elements.push(toAdd[_i]);\n }\n }\n\n return this.spawn(elements);\n },\n // in place merge on calling collection\n merge: function merge(toAdd) {\n var _p = this._private;\n var cy = _p.cy;\n\n if (!toAdd) {\n return this;\n }\n\n if (toAdd && string(toAdd)) {\n var selector = toAdd;\n toAdd = cy.mutableElements().filter(selector);\n }\n\n var map = _p.map;\n\n for (var i = 0; i < toAdd.length; i++) {\n var toAddEle = toAdd[i];\n var id = toAddEle._private.data.id;\n var add = !map.has(id);\n\n if (add) {\n var index = this.length++;\n this[index] = toAddEle;\n map.set(id, {\n ele: toAddEle,\n index: index\n });\n } else {\n // replace\n var _index = map.get(id).index;\n this[_index] = toAddEle;\n map.set(id, {\n ele: toAddEle,\n index: _index\n });\n }\n }\n\n return this; // chaining\n },\n unmergeAt: function unmergeAt(i) {\n var ele = this[i];\n var id = ele.id();\n var _p = this._private;\n var map = _p.map; // remove ele\n\n this[i] = undefined;\n map[\"delete\"](id);\n var unmergedLastEle = i === this.length - 1; // replace empty spot with last ele in collection\n\n if (this.length > 1 && !unmergedLastEle) {\n var lastEleI = this.length - 1;\n var lastEle = this[lastEleI];\n var lastEleId = lastEle._private.data.id;\n this[lastEleI] = undefined;\n this[i] = lastEle;\n map.set(lastEleId, {\n ele: lastEle,\n index: i\n });\n } // the collection is now 1 ele smaller\n\n\n this.length--;\n return this;\n },\n // remove single ele in place in calling collection\n unmergeOne: function unmergeOne(ele) {\n ele = ele[0];\n var _p = this._private;\n var id = ele._private.data.id;\n var map = _p.map;\n var entry = map.get(id);\n\n if (!entry) {\n return this; // no need to remove\n }\n\n var i = entry.index;\n this.unmergeAt(i);\n return this;\n },\n // remove eles in place on calling collection\n unmerge: function unmerge(toRemove) {\n var cy = this._private.cy;\n\n if (!toRemove) {\n return this;\n }\n\n if (toRemove && string(toRemove)) {\n var selector = toRemove;\n toRemove = cy.mutableElements().filter(selector);\n }\n\n for (var i = 0; i < toRemove.length; i++) {\n this.unmergeOne(toRemove[i]);\n }\n\n return this; // chaining\n },\n unmergeBy: function unmergeBy(toRmFn) {\n for (var i = this.length - 1; i >= 0; i--) {\n var ele = this[i];\n\n if (toRmFn(ele)) {\n this.unmergeAt(i);\n }\n }\n\n return this;\n },\n map: function map(mapFn, thisArg) {\n var arr = [];\n var eles = this;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var ret = thisArg ? mapFn.apply(thisArg, [ele, i, eles]) : mapFn(ele, i, eles);\n arr.push(ret);\n }\n\n return arr;\n },\n reduce: function reduce(fn, initialValue) {\n var val = initialValue;\n var eles = this;\n\n for (var i = 0; i < eles.length; i++) {\n val = fn(val, eles[i], i, eles);\n }\n\n return val;\n },\n max: function max(valFn, thisArg) {\n var max = -Infinity;\n var maxEle;\n var eles = this;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var val = thisArg ? valFn.apply(thisArg, [ele, i, eles]) : valFn(ele, i, eles);\n\n if (val > max) {\n max = val;\n maxEle = ele;\n }\n }\n\n return {\n value: max,\n ele: maxEle\n };\n },\n min: function min(valFn, thisArg) {\n var min = Infinity;\n var minEle;\n var eles = this;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var val = thisArg ? valFn.apply(thisArg, [ele, i, eles]) : valFn(ele, i, eles);\n\n if (val < min) {\n min = val;\n minEle = ele;\n }\n }\n\n return {\n value: min,\n ele: minEle\n };\n }\n}; // aliases\n\nvar fn$5 = elesfn$n;\nfn$5['u'] = fn$5['|'] = fn$5['+'] = fn$5.union = fn$5.or = fn$5.add;\nfn$5['\\\\'] = fn$5['!'] = fn$5['-'] = fn$5.difference = fn$5.relativeComplement = fn$5.subtract = fn$5.not;\nfn$5['n'] = fn$5['&'] = fn$5['.'] = fn$5.and = fn$5.intersection = fn$5.intersect;\nfn$5['^'] = fn$5['(+)'] = fn$5['(-)'] = fn$5.symmetricDifference = fn$5.symdiff = fn$5.xor;\nfn$5.fnFilter = fn$5.filterFn = fn$5.stdFilter = fn$5.filter;\nfn$5.complement = fn$5.abscomp = fn$5.absoluteComplement;\n\nvar elesfn$o = {\n isNode: function isNode() {\n return this.group() === 'nodes';\n },\n isEdge: function isEdge() {\n return this.group() === 'edges';\n },\n isLoop: function isLoop() {\n return this.isEdge() && this.source()[0] === this.target()[0];\n },\n isSimple: function isSimple() {\n return this.isEdge() && this.source()[0] !== this.target()[0];\n },\n group: function group() {\n var ele = this[0];\n\n if (ele) {\n return ele._private.group;\n }\n }\n};\n\n/**\n * Elements are drawn in a specific order based on compound depth (low to high), the element type (nodes above edges),\n * and z-index (low to high). These styles affect how this applies:\n *\n * z-compound-depth: May be `bottom | orphan | auto | top`. The first drawn is `bottom`, then `orphan` which is the\n * same depth as the root of the compound graph, followed by the default value `auto` which draws in order from\n * root to leaves of the compound graph. The last drawn is `top`.\n * z-index-compare: May be `auto | manual`. The default value is `auto` which always draws edges under nodes.\n * `manual` ignores this convention and draws based on the `z-index` value setting.\n * z-index: An integer value that affects the relative draw order of elements. In general, an element with a higher\n * `z-index` will be drawn on top of an element with a lower `z-index`.\n */\n\nvar zIndexSort = function zIndexSort(a, b) {\n var cy = a.cy();\n var hasCompoundNodes = cy.hasCompoundNodes();\n\n function getDepth(ele) {\n var style = ele.pstyle('z-compound-depth');\n\n if (style.value === 'auto') {\n return hasCompoundNodes ? ele.zDepth() : 0;\n } else if (style.value === 'bottom') {\n return -1;\n } else if (style.value === 'top') {\n return MAX_INT;\n } // 'orphan'\n\n\n return 0;\n }\n\n var depthDiff = getDepth(a) - getDepth(b);\n\n if (depthDiff !== 0) {\n return depthDiff;\n }\n\n function getEleDepth(ele) {\n var style = ele.pstyle('z-index-compare');\n\n if (style.value === 'auto') {\n return ele.isNode() ? 1 : 0;\n } // 'manual'\n\n\n return 0;\n }\n\n var eleDiff = getEleDepth(a) - getEleDepth(b);\n\n if (eleDiff !== 0) {\n return eleDiff;\n }\n\n var zDiff = a.pstyle('z-index').value - b.pstyle('z-index').value;\n\n if (zDiff !== 0) {\n return zDiff;\n } // compare indices in the core (order added to graph w/ last on top)\n\n\n return a.poolIndex() - b.poolIndex();\n};\n\nvar elesfn$p = {\n forEach: function forEach(fn$1, thisArg) {\n if (fn(fn$1)) {\n var N = this.length;\n\n for (var i = 0; i < N; i++) {\n var ele = this[i];\n var ret = thisArg ? fn$1.apply(thisArg, [ele, i, this]) : fn$1(ele, i, this);\n\n if (ret === false) {\n break;\n } // exit each early on return false\n\n }\n }\n\n return this;\n },\n toArray: function toArray() {\n var array = [];\n\n for (var i = 0; i < this.length; i++) {\n array.push(this[i]);\n }\n\n return array;\n },\n slice: function slice(start, end) {\n var array = [];\n var thisSize = this.length;\n\n if (end == null) {\n end = thisSize;\n }\n\n if (start == null) {\n start = 0;\n }\n\n if (start < 0) {\n start = thisSize + start;\n }\n\n if (end < 0) {\n end = thisSize + end;\n }\n\n for (var i = start; i >= 0 && i < end && i < thisSize; i++) {\n array.push(this[i]);\n }\n\n return this.spawn(array);\n },\n size: function size() {\n return this.length;\n },\n eq: function eq(i) {\n return this[i] || this.spawn();\n },\n first: function first() {\n return this[0] || this.spawn();\n },\n last: function last() {\n return this[this.length - 1] || this.spawn();\n },\n empty: function empty() {\n return this.length === 0;\n },\n nonempty: function nonempty() {\n return !this.empty();\n },\n sort: function sort(sortFn) {\n if (!fn(sortFn)) {\n return this;\n }\n\n var sorted = this.toArray().sort(sortFn);\n return this.spawn(sorted);\n },\n sortByZIndex: function sortByZIndex() {\n return this.sort(zIndexSort);\n },\n zDepth: function zDepth() {\n var ele = this[0];\n\n if (!ele) {\n return undefined;\n } // let cy = ele.cy();\n\n\n var _p = ele._private;\n var group = _p.group;\n\n if (group === 'nodes') {\n var depth = _p.data.parent ? ele.parents().size() : 0;\n\n if (!ele.isParent()) {\n return MAX_INT - 1; // childless nodes always on top\n }\n\n return depth;\n } else {\n var src = _p.source;\n var tgt = _p.target;\n var srcDepth = src.zDepth();\n var tgtDepth = tgt.zDepth();\n return Math.max(srcDepth, tgtDepth, 0); // depth of deepest parent\n }\n }\n};\nelesfn$p.each = elesfn$p.forEach;\n\nvar defineSymbolIterator = function defineSymbolIterator() {\n var typeofUndef = \"undefined\" ;\n var isIteratorSupported = (typeof Symbol === \"undefined\" ? \"undefined\" : _typeof(Symbol)) != typeofUndef && _typeof(Symbol.iterator) != typeofUndef; // eslint-disable-line no-undef\n\n if (isIteratorSupported) {\n elesfn$p[Symbol.iterator] = function () {\n var _this = this;\n\n // eslint-disable-line no-undef\n var entry = {\n value: undefined,\n done: false\n };\n var i = 0;\n var length = this.length;\n return _defineProperty({\n next: function next() {\n if (i < length) {\n entry.value = _this[i++];\n } else {\n entry.value = undefined;\n entry.done = true;\n }\n\n return entry;\n }\n }, Symbol.iterator, function () {\n // eslint-disable-line no-undef\n return this;\n });\n };\n }\n};\n\ndefineSymbolIterator();\n\nvar getLayoutDimensionOptions = defaults({\n nodeDimensionsIncludeLabels: false\n});\nvar elesfn$q = {\n // Calculates and returns node dimensions { x, y } based on options given\n layoutDimensions: function layoutDimensions(options) {\n options = getLayoutDimensionOptions(options);\n var dims;\n\n if (!this.takesUpSpace()) {\n dims = {\n w: 0,\n h: 0\n };\n } else if (options.nodeDimensionsIncludeLabels) {\n var bbDim = this.boundingBox();\n dims = {\n w: bbDim.w,\n h: bbDim.h\n };\n } else {\n dims = {\n w: this.outerWidth(),\n h: this.outerHeight()\n };\n } // sanitise the dimensions for external layouts (avoid division by zero)\n\n\n if (dims.w === 0 || dims.h === 0) {\n dims.w = dims.h = 1;\n }\n\n return dims;\n },\n // using standard layout options, apply position function (w/ or w/o animation)\n layoutPositions: function layoutPositions(layout, options, fn) {\n var nodes = this.nodes();\n var cy = this.cy();\n var layoutEles = options.eles; // nodes & edges\n\n var getMemoizeKey = function getMemoizeKey(node) {\n return node.id();\n };\n\n var fnMem = memoize(fn, getMemoizeKey); // memoized version of position function\n\n layout.emit({\n type: 'layoutstart',\n layout: layout\n });\n layout.animations = [];\n\n var calculateSpacing = function calculateSpacing(spacing, nodesBb, pos) {\n var center = {\n x: nodesBb.x1 + nodesBb.w / 2,\n y: nodesBb.y1 + nodesBb.h / 2\n };\n var spacingVector = {\n // scale from center of bounding box (not necessarily 0,0)\n x: (pos.x - center.x) * spacing,\n y: (pos.y - center.y) * spacing\n };\n return {\n x: center.x + spacingVector.x,\n y: center.y + spacingVector.y\n };\n };\n\n var useSpacingFactor = options.spacingFactor && options.spacingFactor !== 1;\n\n var spacingBb = function spacingBb() {\n if (!useSpacingFactor) {\n return null;\n }\n\n var bb = makeBoundingBox();\n\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n var pos = fnMem(node, i);\n expandBoundingBoxByPoint(bb, pos.x, pos.y);\n }\n\n return bb;\n };\n\n var bb = spacingBb();\n var getFinalPos = memoize(function (node, i) {\n var newPos = fnMem(node, i);\n\n if (useSpacingFactor) {\n var spacing = Math.abs(options.spacingFactor);\n newPos = calculateSpacing(spacing, bb, newPos);\n }\n\n if (options.transform != null) {\n newPos = options.transform(node, newPos);\n }\n\n return newPos;\n }, getMemoizeKey);\n\n if (options.animate) {\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n var newPos = getFinalPos(node, i);\n var animateNode = options.animateFilter == null || options.animateFilter(node, i);\n\n if (animateNode) {\n var ani = node.animation({\n position: newPos,\n duration: options.animationDuration,\n easing: options.animationEasing\n });\n layout.animations.push(ani);\n } else {\n node.position(newPos);\n }\n }\n\n if (options.fit) {\n var fitAni = cy.animation({\n fit: {\n boundingBox: layoutEles.boundingBoxAt(getFinalPos),\n padding: options.padding\n },\n duration: options.animationDuration,\n easing: options.animationEasing\n });\n layout.animations.push(fitAni);\n } else if (options.zoom !== undefined && options.pan !== undefined) {\n var zoomPanAni = cy.animation({\n zoom: options.zoom,\n pan: options.pan,\n duration: options.animationDuration,\n easing: options.animationEasing\n });\n layout.animations.push(zoomPanAni);\n }\n\n layout.animations.forEach(function (ani) {\n return ani.play();\n });\n layout.one('layoutready', options.ready);\n layout.emit({\n type: 'layoutready',\n layout: layout\n });\n Promise$1.all(layout.animations.map(function (ani) {\n return ani.promise();\n })).then(function () {\n layout.one('layoutstop', options.stop);\n layout.emit({\n type: 'layoutstop',\n layout: layout\n });\n });\n } else {\n nodes.positions(getFinalPos);\n\n if (options.fit) {\n cy.fit(options.eles, options.padding);\n }\n\n if (options.zoom != null) {\n cy.zoom(options.zoom);\n }\n\n if (options.pan) {\n cy.pan(options.pan);\n }\n\n layout.one('layoutready', options.ready);\n layout.emit({\n type: 'layoutready',\n layout: layout\n });\n layout.one('layoutstop', options.stop);\n layout.emit({\n type: 'layoutstop',\n layout: layout\n });\n }\n\n return this; // chaining\n },\n layout: function layout(options) {\n var cy = this.cy();\n return cy.makeLayout(extend({}, options, {\n eles: this\n }));\n }\n}; // aliases:\n\nelesfn$q.createLayout = elesfn$q.makeLayout = elesfn$q.layout;\n\nfunction styleCache(key, fn, ele) {\n var _p = ele._private;\n var cache = _p.styleCache = _p.styleCache || [];\n var val;\n\n if ((val = cache[key]) != null) {\n return val;\n } else {\n val = cache[key] = fn(ele);\n return val;\n }\n}\n\nfunction cacheStyleFunction(key, fn) {\n key = hashString(key);\n return function cachedStyleFunction(ele) {\n return styleCache(key, fn, ele);\n };\n}\n\nfunction cachePrototypeStyleFunction(key, fn) {\n key = hashString(key);\n\n var selfFn = function selfFn(ele) {\n return fn.call(ele);\n };\n\n return function cachedPrototypeStyleFunction() {\n var ele = this[0];\n\n if (ele) {\n return styleCache(key, selfFn, ele);\n }\n };\n}\n\nvar elesfn$r = {\n recalculateRenderedStyle: function recalculateRenderedStyle(useCache) {\n var cy = this.cy();\n var renderer = cy.renderer();\n var styleEnabled = cy.styleEnabled();\n\n if (renderer && styleEnabled) {\n renderer.recalculateRenderedStyle(this, useCache);\n }\n\n return this;\n },\n dirtyStyleCache: function dirtyStyleCache() {\n var cy = this.cy();\n\n var dirty = function dirty(ele) {\n return ele._private.styleCache = null;\n };\n\n if (cy.hasCompoundNodes()) {\n var eles;\n eles = this.spawnSelf().merge(this.descendants()).merge(this.parents());\n eles.merge(eles.connectedEdges());\n eles.forEach(dirty);\n } else {\n this.forEach(function (ele) {\n dirty(ele);\n ele.connectedEdges().forEach(dirty);\n });\n }\n\n return this;\n },\n // fully updates (recalculates) the style for the elements\n updateStyle: function updateStyle(notifyRenderer) {\n var cy = this._private.cy;\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n if (cy.batching()) {\n var bEles = cy._private.batchStyleEles;\n bEles.merge(this);\n return this; // chaining and exit early when batching\n }\n\n var hasCompounds = cy.hasCompoundNodes();\n var style = cy.style();\n var updatedEles = this;\n notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;\n\n if (hasCompounds) {\n // then add everything up and down for compound selector checks\n updatedEles = this.spawnSelf().merge(this.descendants()).merge(this.parents());\n }\n\n var changedEles = style.apply(updatedEles);\n\n if (notifyRenderer) {\n changedEles.emitAndNotify('style'); // let renderer know we changed style\n } else {\n changedEles.emit('style'); // just fire the event\n }\n\n return this; // chaining\n },\n // get the internal parsed style object for the specified property\n parsedStyle: function parsedStyle(property) {\n var includeNonDefault = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var ele = this[0];\n var cy = ele.cy();\n\n if (!cy.styleEnabled()) {\n return;\n }\n\n if (ele) {\n var overriddenStyle = ele._private.style[property];\n\n if (overriddenStyle != null) {\n return overriddenStyle;\n } else if (includeNonDefault) {\n return cy.style().getDefaultProperty(property);\n } else {\n return null;\n }\n }\n },\n numericStyle: function numericStyle(property) {\n var ele = this[0];\n\n if (!ele.cy().styleEnabled()) {\n return;\n }\n\n if (ele) {\n var pstyle = ele.pstyle(property);\n return pstyle.pfValue !== undefined ? pstyle.pfValue : pstyle.value;\n }\n },\n numericStyleUnits: function numericStyleUnits(property) {\n var ele = this[0];\n\n if (!ele.cy().styleEnabled()) {\n return;\n }\n\n if (ele) {\n return ele.pstyle(property).units;\n }\n },\n // get the specified css property as a rendered value (i.e. on-screen value)\n // or get the whole rendered style if no property specified (NB doesn't allow setting)\n renderedStyle: function renderedStyle(property) {\n var cy = this.cy();\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n var ele = this[0];\n\n if (ele) {\n return cy.style().getRenderedStyle(ele, property);\n }\n },\n // read the calculated css style of the element or override the style (via a bypass)\n style: function style(name, value) {\n var cy = this.cy();\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n var updateTransitions = false;\n var style = cy.style();\n\n if (plainObject(name)) {\n // then extend the bypass\n var props = name;\n style.applyBypass(this, props, updateTransitions);\n this.emitAndNotify('style'); // let the renderer know we've updated style\n } else if (string(name)) {\n if (value === undefined) {\n // then get the property from the style\n var ele = this[0];\n\n if (ele) {\n return style.getStylePropertyValue(ele, name);\n } else {\n // empty collection => can't get any value\n return;\n }\n } else {\n // then set the bypass with the property value\n style.applyBypass(this, name, value, updateTransitions);\n this.emitAndNotify('style'); // let the renderer know we've updated style\n }\n } else if (name === undefined) {\n var _ele = this[0];\n\n if (_ele) {\n return style.getRawStyle(_ele);\n } else {\n // empty collection => can't get any value\n return;\n }\n }\n\n return this; // chaining\n },\n removeStyle: function removeStyle(names) {\n var cy = this.cy();\n\n if (!cy.styleEnabled()) {\n return this;\n }\n\n var updateTransitions = false;\n var style = cy.style();\n var eles = this;\n\n if (names === undefined) {\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n style.removeAllBypasses(ele, updateTransitions);\n }\n } else {\n names = names.split(/\\s+/);\n\n for (var _i = 0; _i < eles.length; _i++) {\n var _ele2 = eles[_i];\n style.removeBypasses(_ele2, names, updateTransitions);\n }\n }\n\n this.emitAndNotify('style'); // let the renderer know we've updated style\n\n return this; // chaining\n },\n show: function show() {\n this.css('display', 'element');\n return this; // chaining\n },\n hide: function hide() {\n this.css('display', 'none');\n return this; // chaining\n },\n effectiveOpacity: function effectiveOpacity() {\n var cy = this.cy();\n\n if (!cy.styleEnabled()) {\n return 1;\n }\n\n var hasCompoundNodes = cy.hasCompoundNodes();\n var ele = this[0];\n\n if (ele) {\n var _p = ele._private;\n var parentOpacity = ele.pstyle('opacity').value;\n\n if (!hasCompoundNodes) {\n return parentOpacity;\n }\n\n var parents = !_p.data.parent ? null : ele.parents();\n\n if (parents) {\n for (var i = 0; i < parents.length; i++) {\n var parent = parents[i];\n var opacity = parent.pstyle('opacity').value;\n parentOpacity = opacity * parentOpacity;\n }\n }\n\n return parentOpacity;\n }\n },\n transparent: function transparent() {\n var cy = this.cy();\n\n if (!cy.styleEnabled()) {\n return false;\n }\n\n var ele = this[0];\n var hasCompoundNodes = ele.cy().hasCompoundNodes();\n\n if (ele) {\n if (!hasCompoundNodes) {\n return ele.pstyle('opacity').value === 0;\n } else {\n return ele.effectiveOpacity() === 0;\n }\n }\n },\n backgrounding: function backgrounding() {\n var cy = this.cy();\n\n if (!cy.styleEnabled()) {\n return false;\n }\n\n var ele = this[0];\n return ele._private.backgrounding ? true : false;\n }\n};\n\nfunction checkCompound(ele, parentOk) {\n var _p = ele._private;\n var parents = _p.data.parent ? ele.parents() : null;\n\n if (parents) {\n for (var i = 0; i < parents.length; i++) {\n var parent = parents[i];\n\n if (!parentOk(parent)) {\n return false;\n }\n }\n }\n\n return true;\n}\n\nfunction defineDerivedStateFunction(specs) {\n var ok = specs.ok;\n var edgeOkViaNode = specs.edgeOkViaNode || specs.ok;\n var parentOk = specs.parentOk || specs.ok;\n return function () {\n var cy = this.cy();\n\n if (!cy.styleEnabled()) {\n return true;\n }\n\n var ele = this[0];\n var hasCompoundNodes = cy.hasCompoundNodes();\n\n if (ele) {\n var _p = ele._private;\n\n if (!ok(ele)) {\n return false;\n }\n\n if (ele.isNode()) {\n return !hasCompoundNodes || checkCompound(ele, parentOk);\n } else {\n var src = _p.source;\n var tgt = _p.target;\n return edgeOkViaNode(src) && (!hasCompoundNodes || checkCompound(src, edgeOkViaNode)) && (src === tgt || edgeOkViaNode(tgt) && (!hasCompoundNodes || checkCompound(tgt, edgeOkViaNode)));\n }\n }\n };\n}\n\nvar eleTakesUpSpace = cacheStyleFunction('eleTakesUpSpace', function (ele) {\n return ele.pstyle('display').value === 'element' && ele.width() !== 0 && (ele.isNode() ? ele.height() !== 0 : true);\n});\nelesfn$r.takesUpSpace = cachePrototypeStyleFunction('takesUpSpace', defineDerivedStateFunction({\n ok: eleTakesUpSpace\n}));\nvar eleInteractive = cacheStyleFunction('eleInteractive', function (ele) {\n return ele.pstyle('events').value === 'yes' && ele.pstyle('visibility').value === 'visible' && eleTakesUpSpace(ele);\n});\nvar parentInteractive = cacheStyleFunction('parentInteractive', function (parent) {\n return parent.pstyle('visibility').value === 'visible' && eleTakesUpSpace(parent);\n});\nelesfn$r.interactive = cachePrototypeStyleFunction('interactive', defineDerivedStateFunction({\n ok: eleInteractive,\n parentOk: parentInteractive,\n edgeOkViaNode: eleTakesUpSpace\n}));\n\nelesfn$r.noninteractive = function () {\n var ele = this[0];\n\n if (ele) {\n return !ele.interactive();\n }\n};\n\nvar eleVisible = cacheStyleFunction('eleVisible', function (ele) {\n return ele.pstyle('visibility').value === 'visible' && ele.pstyle('opacity').pfValue !== 0 && eleTakesUpSpace(ele);\n});\nvar edgeVisibleViaNode = eleTakesUpSpace;\nelesfn$r.visible = cachePrototypeStyleFunction('visible', defineDerivedStateFunction({\n ok: eleVisible,\n edgeOkViaNode: edgeVisibleViaNode\n}));\n\nelesfn$r.hidden = function () {\n var ele = this[0];\n\n if (ele) {\n return !ele.visible();\n }\n};\n\nelesfn$r.isBundledBezier = cachePrototypeStyleFunction('isBundledBezier', function () {\n if (!this.cy().styleEnabled()) {\n return false;\n }\n\n return !this.removed() && this.pstyle('curve-style').value === 'bezier' && this.takesUpSpace();\n});\nelesfn$r.bypass = elesfn$r.css = elesfn$r.style;\nelesfn$r.renderedCss = elesfn$r.renderedStyle;\nelesfn$r.removeBypass = elesfn$r.removeCss = elesfn$r.removeStyle;\nelesfn$r.pstyle = elesfn$r.parsedStyle;\n\nvar elesfn$s = {};\n\nfunction defineSwitchFunction(params) {\n return function () {\n var args = arguments;\n var changedEles = []; // e.g. cy.nodes().select( data, handler )\n\n if (args.length === 2) {\n var data = args[0];\n var handler = args[1];\n this.on(params.event, data, handler);\n } // e.g. cy.nodes().select( handler )\n else if (args.length === 1 && fn(args[0])) {\n var _handler = args[0];\n this.on(params.event, _handler);\n } // e.g. cy.nodes().select()\n // e.g. (private) cy.nodes().select(['tapselect'])\n else if (args.length === 0 || args.length === 1 && array(args[0])) {\n var addlEvents = args.length === 1 ? args[0] : null;\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var able = !params.ableField || ele._private[params.ableField];\n var changed = ele._private[params.field] != params.value;\n\n if (params.overrideAble) {\n var overrideAble = params.overrideAble(ele);\n\n if (overrideAble !== undefined) {\n able = overrideAble;\n\n if (!overrideAble) {\n return this;\n } // to save cycles assume not able for all on override\n\n }\n }\n\n if (able) {\n ele._private[params.field] = params.value;\n\n if (changed) {\n changedEles.push(ele);\n }\n }\n }\n\n var changedColl = this.spawn(changedEles);\n changedColl.updateStyle(); // change of state => possible change of style\n\n changedColl.emit(params.event);\n\n if (addlEvents) {\n changedColl.emit(addlEvents);\n }\n }\n\n return this;\n };\n}\n\nfunction defineSwitchSet(params) {\n elesfn$s[params.field] = function () {\n var ele = this[0];\n\n if (ele) {\n if (params.overrideField) {\n var val = params.overrideField(ele);\n\n if (val !== undefined) {\n return val;\n }\n }\n\n return ele._private[params.field];\n }\n };\n\n elesfn$s[params.on] = defineSwitchFunction({\n event: params.on,\n field: params.field,\n ableField: params.ableField,\n overrideAble: params.overrideAble,\n value: true\n });\n elesfn$s[params.off] = defineSwitchFunction({\n event: params.off,\n field: params.field,\n ableField: params.ableField,\n overrideAble: params.overrideAble,\n value: false\n });\n}\n\ndefineSwitchSet({\n field: 'locked',\n overrideField: function overrideField(ele) {\n return ele.cy().autolock() ? true : undefined;\n },\n on: 'lock',\n off: 'unlock'\n});\ndefineSwitchSet({\n field: 'grabbable',\n overrideField: function overrideField(ele) {\n return ele.cy().autoungrabify() || ele.pannable() ? false : undefined;\n },\n on: 'grabify',\n off: 'ungrabify'\n});\ndefineSwitchSet({\n field: 'selected',\n ableField: 'selectable',\n overrideAble: function overrideAble(ele) {\n return ele.cy().autounselectify() ? false : undefined;\n },\n on: 'select',\n off: 'unselect'\n});\ndefineSwitchSet({\n field: 'selectable',\n overrideField: function overrideField(ele) {\n return ele.cy().autounselectify() ? false : undefined;\n },\n on: 'selectify',\n off: 'unselectify'\n});\nelesfn$s.deselect = elesfn$s.unselect;\n\nelesfn$s.grabbed = function () {\n var ele = this[0];\n\n if (ele) {\n return ele._private.grabbed;\n }\n};\n\ndefineSwitchSet({\n field: 'active',\n on: 'activate',\n off: 'unactivate'\n});\ndefineSwitchSet({\n field: 'pannable',\n on: 'panify',\n off: 'unpanify'\n});\n\nelesfn$s.inactive = function () {\n var ele = this[0];\n\n if (ele) {\n return !ele._private.active;\n }\n};\n\nvar elesfn$t = {}; // DAG functions\n////////////////\n\nvar defineDagExtremity = function defineDagExtremity(params) {\n return function dagExtremityImpl(selector) {\n var eles = this;\n var ret = [];\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n\n if (!ele.isNode()) {\n continue;\n }\n\n var disqualified = false;\n var edges = ele.connectedEdges();\n\n for (var j = 0; j < edges.length; j++) {\n var edge = edges[j];\n var src = edge.source();\n var tgt = edge.target();\n\n if (params.noIncomingEdges && tgt === ele && src !== ele || params.noOutgoingEdges && src === ele && tgt !== ele) {\n disqualified = true;\n break;\n }\n }\n\n if (!disqualified) {\n ret.push(ele);\n }\n }\n\n return this.spawn(ret, {\n unique: true\n }).filter(selector);\n };\n};\n\nvar defineDagOneHop = function defineDagOneHop(params) {\n return function (selector) {\n var eles = this;\n var oEles = [];\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n\n if (!ele.isNode()) {\n continue;\n }\n\n var edges = ele.connectedEdges();\n\n for (var j = 0; j < edges.length; j++) {\n var edge = edges[j];\n var src = edge.source();\n var tgt = edge.target();\n\n if (params.outgoing && src === ele) {\n oEles.push(edge);\n oEles.push(tgt);\n } else if (params.incoming && tgt === ele) {\n oEles.push(edge);\n oEles.push(src);\n }\n }\n }\n\n return this.spawn(oEles, {\n unique: true\n }).filter(selector);\n };\n};\n\nvar defineDagAllHops = function defineDagAllHops(params) {\n return function (selector) {\n var eles = this;\n var sEles = [];\n var sElesIds = {};\n\n for (;;) {\n var next = params.outgoing ? eles.outgoers() : eles.incomers();\n\n if (next.length === 0) {\n break;\n } // done if none left\n\n\n var newNext = false;\n\n for (var i = 0; i < next.length; i++) {\n var n = next[i];\n var nid = n.id();\n\n if (!sElesIds[nid]) {\n sElesIds[nid] = true;\n sEles.push(n);\n newNext = true;\n }\n }\n\n if (!newNext) {\n break;\n } // done if touched all outgoers already\n\n\n eles = next;\n }\n\n return this.spawn(sEles, {\n unique: true\n }).filter(selector);\n };\n};\n\nelesfn$t.clearTraversalCache = function () {\n for (var i = 0; i < this.length; i++) {\n this[i]._private.traversalCache = null;\n }\n};\n\nextend(elesfn$t, {\n // get the root nodes in the DAG\n roots: defineDagExtremity({\n noIncomingEdges: true\n }),\n // get the leaf nodes in the DAG\n leaves: defineDagExtremity({\n noOutgoingEdges: true\n }),\n // normally called children in graph theory\n // these nodes =edges=> outgoing nodes\n outgoers: cache(defineDagOneHop({\n outgoing: true\n }), 'outgoers'),\n // aka DAG descendants\n successors: defineDagAllHops({\n outgoing: true\n }),\n // normally called parents in graph theory\n // these nodes <=edges= incoming nodes\n incomers: cache(defineDagOneHop({\n incoming: true\n }), 'incomers'),\n // aka DAG ancestors\n predecessors: defineDagAllHops({\n incoming: true\n })\n}); // Neighbourhood functions\n//////////////////////////\n\nextend(elesfn$t, {\n neighborhood: cache(function (selector) {\n var elements = [];\n var nodes = this.nodes();\n\n for (var i = 0; i < nodes.length; i++) {\n // for all nodes\n var node = nodes[i];\n var connectedEdges = node.connectedEdges(); // for each connected edge, add the edge and the other node\n\n for (var j = 0; j < connectedEdges.length; j++) {\n var edge = connectedEdges[j];\n var src = edge.source();\n var tgt = edge.target();\n var otherNode = node === src ? tgt : src; // need check in case of loop\n\n if (otherNode.length > 0) {\n elements.push(otherNode[0]); // add node 1 hop away\n } // add connected edge\n\n\n elements.push(edge[0]);\n }\n }\n\n return this.spawn(elements, {\n unique: true\n }).filter(selector);\n }, 'neighborhood'),\n closedNeighborhood: function closedNeighborhood(selector) {\n return this.neighborhood().add(this).filter(selector);\n },\n openNeighborhood: function openNeighborhood(selector) {\n return this.neighborhood(selector);\n }\n}); // aliases\n\nelesfn$t.neighbourhood = elesfn$t.neighborhood;\nelesfn$t.closedNeighbourhood = elesfn$t.closedNeighborhood;\nelesfn$t.openNeighbourhood = elesfn$t.openNeighborhood; // Edge functions\n/////////////////\n\nextend(elesfn$t, {\n source: cache(function sourceImpl(selector) {\n var ele = this[0];\n var src;\n\n if (ele) {\n src = ele._private.source || ele.cy().collection();\n }\n\n return src && selector ? src.filter(selector) : src;\n }, 'source'),\n target: cache(function targetImpl(selector) {\n var ele = this[0];\n var tgt;\n\n if (ele) {\n tgt = ele._private.target || ele.cy().collection();\n }\n\n return tgt && selector ? tgt.filter(selector) : tgt;\n }, 'target'),\n sources: defineSourceFunction({\n attr: 'source'\n }),\n targets: defineSourceFunction({\n attr: 'target'\n })\n});\n\nfunction defineSourceFunction(params) {\n return function sourceImpl(selector) {\n var sources = [];\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var src = ele._private[params.attr];\n\n if (src) {\n sources.push(src);\n }\n }\n\n return this.spawn(sources, {\n unique: true\n }).filter(selector);\n };\n}\n\nextend(elesfn$t, {\n edgesWith: cache(defineEdgesWithFunction(), 'edgesWith'),\n edgesTo: cache(defineEdgesWithFunction({\n thisIsSrc: true\n }), 'edgesTo')\n});\n\nfunction defineEdgesWithFunction(params) {\n return function edgesWithImpl(otherNodes) {\n var elements = [];\n var cy = this._private.cy;\n var p = params || {}; // get elements if a selector is specified\n\n if (string(otherNodes)) {\n otherNodes = cy.$(otherNodes);\n }\n\n for (var h = 0; h < otherNodes.length; h++) {\n var edges = otherNodes[h]._private.edges;\n\n for (var i = 0; i < edges.length; i++) {\n var edge = edges[i];\n var edgeData = edge._private.data;\n var thisToOther = this.hasElementWithId(edgeData.source) && otherNodes.hasElementWithId(edgeData.target);\n var otherToThis = otherNodes.hasElementWithId(edgeData.source) && this.hasElementWithId(edgeData.target);\n var edgeConnectsThisAndOther = thisToOther || otherToThis;\n\n if (!edgeConnectsThisAndOther) {\n continue;\n }\n\n if (p.thisIsSrc || p.thisIsTgt) {\n if (p.thisIsSrc && !thisToOther) {\n continue;\n }\n\n if (p.thisIsTgt && !otherToThis) {\n continue;\n }\n }\n\n elements.push(edge);\n }\n }\n\n return this.spawn(elements, {\n unique: true\n });\n };\n}\n\nextend(elesfn$t, {\n connectedEdges: cache(function (selector) {\n var retEles = [];\n var eles = this;\n\n for (var i = 0; i < eles.length; i++) {\n var node = eles[i];\n\n if (!node.isNode()) {\n continue;\n }\n\n var edges = node._private.edges;\n\n for (var j = 0; j < edges.length; j++) {\n var edge = edges[j];\n retEles.push(edge);\n }\n }\n\n return this.spawn(retEles, {\n unique: true\n }).filter(selector);\n }, 'connectedEdges'),\n connectedNodes: cache(function (selector) {\n var retEles = [];\n var eles = this;\n\n for (var i = 0; i < eles.length; i++) {\n var edge = eles[i];\n\n if (!edge.isEdge()) {\n continue;\n }\n\n retEles.push(edge.source()[0]);\n retEles.push(edge.target()[0]);\n }\n\n return this.spawn(retEles, {\n unique: true\n }).filter(selector);\n }, 'connectedNodes'),\n parallelEdges: cache(defineParallelEdgesFunction(), 'parallelEdges'),\n codirectedEdges: cache(defineParallelEdgesFunction({\n codirected: true\n }), 'codirectedEdges')\n});\n\nfunction defineParallelEdgesFunction(params) {\n var defaults = {\n codirected: false\n };\n params = extend({}, defaults, params);\n return function parallelEdgesImpl(selector) {\n // micro-optimised for renderer\n var elements = [];\n var edges = this.edges();\n var p = params; // look at all the edges in the collection\n\n for (var i = 0; i < edges.length; i++) {\n var edge1 = edges[i];\n var edge1_p = edge1._private;\n var src1 = edge1_p.source;\n var srcid1 = src1._private.data.id;\n var tgtid1 = edge1_p.data.target;\n var srcEdges1 = src1._private.edges; // look at edges connected to the src node of this edge\n\n for (var j = 0; j < srcEdges1.length; j++) {\n var edge2 = srcEdges1[j];\n var edge2data = edge2._private.data;\n var tgtid2 = edge2data.target;\n var srcid2 = edge2data.source;\n var codirected = tgtid2 === tgtid1 && srcid2 === srcid1;\n var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2;\n\n if (p.codirected && codirected || !p.codirected && (codirected || oppdirected)) {\n elements.push(edge2);\n }\n }\n }\n\n return this.spawn(elements, {\n unique: true\n }).filter(selector);\n };\n} // Misc functions\n/////////////////\n\n\nextend(elesfn$t, {\n components: function components(root) {\n var self = this;\n var cy = self.cy();\n var visited = cy.collection();\n var unvisited = root == null ? self.nodes() : root.nodes();\n var components = [];\n\n if (root != null && unvisited.empty()) {\n // root may contain only edges\n unvisited = root.sources(); // doesn't matter which node to use (undirected), so just use the source sides\n }\n\n var visitInComponent = function visitInComponent(node, component) {\n visited.merge(node);\n unvisited.unmerge(node);\n component.merge(node);\n };\n\n if (unvisited.empty()) {\n return self.spawn();\n }\n\n var _loop = function _loop() {\n // each iteration yields a component\n var cmpt = cy.collection();\n components.push(cmpt);\n var root = unvisited[0];\n visitInComponent(root, cmpt);\n self.bfs({\n directed: false,\n roots: root,\n visit: function visit(v) {\n return visitInComponent(v, cmpt);\n }\n });\n cmpt.forEach(function (node) {\n node.connectedEdges().forEach(function (e) {\n // connectedEdges() usually cached\n if (self.has(e) && cmpt.has(e.source()) && cmpt.has(e.target())) {\n // has() is cheap\n cmpt.merge(e); // forEach() only considers nodes -- sets N at call time\n }\n });\n });\n };\n\n do {\n _loop();\n } while (unvisited.length > 0);\n\n return components;\n },\n component: function component() {\n var ele = this[0];\n return ele.cy().mutableElements().components(ele)[0];\n }\n});\nelesfn$t.componentsOf = elesfn$t.components;\n\nvar idFactory = {\n generate: function generate(cy, element, tryThisId) {\n var id = tryThisId != null ? tryThisId : uuid();\n\n while (cy.hasElementWithId(id)) {\n id = uuid();\n }\n\n return id;\n }\n}; // represents a set of nodes, edges, or both together\n\nvar Collection = function Collection(cy, elements, options) {\n if (cy === undefined || !core(cy)) {\n error('A collection must have a reference to the core');\n return;\n }\n\n var map = new Map$1();\n var createdElements = false;\n\n if (!elements) {\n elements = [];\n } else if (elements.length > 0 && plainObject(elements[0]) && !element(elements[0])) {\n createdElements = true; // make elements from json and restore all at once later\n\n var eles = [];\n var elesIds = new Set$1();\n\n for (var i = 0, l = elements.length; i < l; i++) {\n var json = elements[i];\n\n if (json.data == null) {\n json.data = {};\n }\n\n var _data = json.data; // make sure newly created elements have valid ids\n\n if (_data.id == null) {\n _data.id = idFactory.generate(cy, json);\n } else if (cy.hasElementWithId(_data.id) || elesIds.has(_data.id)) {\n continue; // can't create element if prior id already exists\n }\n\n var ele = new Element(cy, json, false);\n eles.push(ele);\n elesIds.add(_data.id);\n }\n\n elements = eles;\n }\n\n this.length = 0;\n\n for (var _i = 0, _l = elements.length; _i < _l; _i++) {\n var element$1 = elements[_i][0]; // [0] in case elements is an array of collections, rather than array of elements\n\n if (element$1 == null) {\n continue;\n }\n\n var id = element$1._private.data.id;\n\n if (options == null || options.unique && !map.has(id)) {\n map.set(id, {\n index: this.length,\n ele: element$1\n });\n this[this.length] = element$1;\n this.length++;\n }\n }\n\n this._private = {\n cy: cy,\n map: map\n }; // restore the elements if we created them from json\n\n if (createdElements) {\n this.restore();\n }\n}; // Functions\n////////////////////////////////////////////////////////////////////////////////////////////////////\n// keep the prototypes in sync (an element has the same functions as a collection)\n// and use elefn and elesfn as shorthands to the prototypes\n\n\nvar elesfn$u = Element.prototype = Collection.prototype;\n\nelesfn$u.instanceString = function () {\n return 'collection';\n};\n\nelesfn$u.spawn = function (cy, eles, opts) {\n if (!core(cy)) {\n // cy is optional\n opts = eles;\n eles = cy;\n cy = this.cy();\n }\n\n return new Collection(cy, eles, opts);\n};\n\nelesfn$u.spawnSelf = function () {\n return this.spawn(this);\n};\n\nelesfn$u.cy = function () {\n return this._private.cy;\n};\n\nelesfn$u.renderer = function () {\n return this._private.cy.renderer();\n};\n\nelesfn$u.element = function () {\n return this[0];\n};\n\nelesfn$u.collection = function () {\n if (collection(this)) {\n return this;\n } else {\n // an element\n return new Collection(this._private.cy, [this]);\n }\n};\n\nelesfn$u.unique = function () {\n return new Collection(this._private.cy, this, {\n unique: true\n });\n};\n\nelesfn$u.hasElementWithId = function (id) {\n id = '' + id; // id must be string\n\n return this._private.map.has(id);\n};\n\nelesfn$u.getElementById = function (id) {\n id = '' + id; // id must be string\n\n var cy = this._private.cy;\n\n var entry = this._private.map.get(id);\n\n return entry ? entry.ele : new Collection(cy); // get ele or empty collection\n};\n\nelesfn$u.$id = elesfn$u.getElementById;\n\nelesfn$u.poolIndex = function () {\n var cy = this._private.cy;\n var eles = cy._private.elements;\n var id = this[0]._private.data.id;\n return eles._private.map.get(id).index;\n};\n\nelesfn$u.indexOf = function (ele) {\n var id = ele[0]._private.data.id;\n return this._private.map.get(id).index;\n};\n\nelesfn$u.indexOfId = function (id) {\n id = '' + id; // id must be string\n\n return this._private.map.get(id).index;\n};\n\nelesfn$u.json = function (obj) {\n var ele = this.element();\n var cy = this.cy();\n\n if (ele == null && obj) {\n return this;\n } // can't set to no eles\n\n\n if (ele == null) {\n return undefined;\n } // can't get from no eles\n\n\n var p = ele._private;\n\n if (plainObject(obj)) {\n // set\n cy.startBatch();\n\n if (obj.data) {\n ele.data(obj.data);\n var _data2 = p.data;\n\n if (ele.isEdge()) {\n // source and target are immutable via data()\n var move = false;\n var spec = {};\n var src = obj.data.source;\n var tgt = obj.data.target;\n\n if (src != null && src != _data2.source) {\n spec.source = '' + src; // id must be string\n\n move = true;\n }\n\n if (tgt != null && tgt != _data2.target) {\n spec.target = '' + tgt; // id must be string\n\n move = true;\n }\n\n if (move) {\n ele = ele.move(spec);\n }\n } else {\n // parent is immutable via data()\n var newParentValSpecd = 'parent' in obj.data;\n var parent = obj.data.parent;\n\n if (newParentValSpecd && (parent != null || _data2.parent != null) && parent != _data2.parent) {\n if (parent === undefined) {\n // can't set undefined imperatively, so use null\n parent = null;\n }\n\n if (parent != null) {\n parent = '' + parent; // id must be string\n }\n\n ele = ele.move({\n parent: parent\n });\n }\n }\n }\n\n if (obj.position) {\n ele.position(obj.position);\n } // ignore group -- immutable\n\n\n var checkSwitch = function checkSwitch(k, trueFnName, falseFnName) {\n var obj_k = obj[k];\n\n if (obj_k != null && obj_k !== p[k]) {\n if (obj_k) {\n ele[trueFnName]();\n } else {\n ele[falseFnName]();\n }\n }\n };\n\n checkSwitch('removed', 'remove', 'restore');\n checkSwitch('selected', 'select', 'unselect');\n checkSwitch('selectable', 'selectify', 'unselectify');\n checkSwitch('locked', 'lock', 'unlock');\n checkSwitch('grabbable', 'grabify', 'ungrabify');\n checkSwitch('pannable', 'panify', 'unpanify');\n\n if (obj.classes != null) {\n ele.classes(obj.classes);\n }\n\n cy.endBatch();\n return this;\n } else if (obj === undefined) {\n // get\n var json = {\n data: copy(p.data),\n position: copy(p.position),\n group: p.group,\n removed: p.removed,\n selected: p.selected,\n selectable: p.selectable,\n locked: p.locked,\n grabbable: p.grabbable,\n pannable: p.pannable,\n classes: null\n };\n json.classes = '';\n var i = 0;\n p.classes.forEach(function (cls) {\n return json.classes += i++ === 0 ? cls : ' ' + cls;\n });\n return json;\n }\n};\n\nelesfn$u.jsons = function () {\n var jsons = [];\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var json = ele.json();\n jsons.push(json);\n }\n\n return jsons;\n};\n\nelesfn$u.clone = function () {\n var cy = this.cy();\n var elesArr = [];\n\n for (var i = 0; i < this.length; i++) {\n var ele = this[i];\n var json = ele.json();\n var clone = new Element(cy, json, false); // NB no restore\n\n elesArr.push(clone);\n }\n\n return new Collection(cy, elesArr);\n};\n\nelesfn$u.copy = elesfn$u.clone;\n\nelesfn$u.restore = function () {\n var notifyRenderer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n var addToPool = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var self = this;\n var cy = self.cy();\n var cy_p = cy._private; // create arrays of nodes and edges, since we need to\n // restore the nodes first\n\n var nodes = [];\n var edges = [];\n var elements;\n\n for (var _i2 = 0, l = self.length; _i2 < l; _i2++) {\n var ele = self[_i2];\n\n if (addToPool && !ele.removed()) {\n // don't need to handle this ele\n continue;\n } // keep nodes first in the array and edges after\n\n\n if (ele.isNode()) {\n // put to front of array if node\n nodes.push(ele);\n } else {\n // put to end of array if edge\n edges.push(ele);\n }\n }\n\n elements = nodes.concat(edges);\n var i;\n\n var removeFromElements = function removeFromElements() {\n elements.splice(i, 1);\n i--;\n }; // now, restore each element\n\n\n for (i = 0; i < elements.length; i++) {\n var _ele = elements[i];\n var _private = _ele._private;\n var _data3 = _private.data; // the traversal cache should start fresh when ele is added\n\n _ele.clearTraversalCache(); // set id and validate\n\n\n if (!addToPool && !_private.removed) ; else if (_data3.id === undefined) {\n _data3.id = idFactory.generate(cy, _ele);\n } else if (number(_data3.id)) {\n _data3.id = '' + _data3.id; // now it's a string\n } else if (emptyString(_data3.id) || !string(_data3.id)) {\n error('Can not create element with invalid string ID `' + _data3.id + '`'); // can't create element if it has empty string as id or non-string id\n\n removeFromElements();\n continue;\n } else if (cy.hasElementWithId(_data3.id)) {\n error('Can not create second element with ID `' + _data3.id + '`'); // can't create element if one already has that id\n\n removeFromElements();\n continue;\n }\n\n var id = _data3.id; // id is finalised, now let's keep a ref\n\n if (_ele.isNode()) {\n // extra checks for nodes\n var pos = _private.position; // make sure the nodes have a defined position\n\n if (pos.x == null) {\n pos.x = 0;\n }\n\n if (pos.y == null) {\n pos.y = 0;\n }\n }\n\n if (_ele.isEdge()) {\n // extra checks for edges\n var edge = _ele;\n var fields = ['source', 'target'];\n var fieldsLength = fields.length;\n var badSourceOrTarget = false;\n\n for (var j = 0; j < fieldsLength; j++) {\n var field = fields[j];\n var val = _data3[field];\n\n if (number(val)) {\n val = _data3[field] = '' + _data3[field]; // now string\n }\n\n if (val == null || val === '') {\n // can't create if source or target is not defined properly\n error('Can not create edge `' + id + '` with unspecified ' + field);\n badSourceOrTarget = true;\n } else if (!cy.hasElementWithId(val)) {\n // can't create edge if one of its nodes doesn't exist\n error('Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`');\n badSourceOrTarget = true;\n }\n }\n\n if (badSourceOrTarget) {\n removeFromElements();\n continue;\n } // can't create this\n\n\n var src = cy.getElementById(_data3.source);\n var tgt = cy.getElementById(_data3.target); // only one edge in node if loop\n\n if (src.same(tgt)) {\n src._private.edges.push(edge);\n } else {\n src._private.edges.push(edge);\n\n tgt._private.edges.push(edge);\n }\n\n edge._private.source = src;\n edge._private.target = tgt;\n } // if is edge\n // create mock ids / indexes maps for element so it can be used like collections\n\n\n _private.map = new Map$1();\n\n _private.map.set(id, {\n ele: _ele,\n index: 0\n });\n\n _private.removed = false;\n\n if (addToPool) {\n cy.addToPool(_ele);\n }\n } // for each element\n // do compound node sanity checks\n\n\n for (var _i3 = 0; _i3 < nodes.length; _i3++) {\n // each node\n var node = nodes[_i3];\n var _data4 = node._private.data;\n\n if (number(_data4.parent)) {\n // then automake string\n _data4.parent = '' + _data4.parent;\n }\n\n var parentId = _data4.parent;\n var specifiedParent = parentId != null;\n\n if (specifiedParent) {\n var parent = cy.getElementById(parentId);\n\n if (parent.empty()) {\n // non-existant parent; just remove it\n _data4.parent = undefined;\n } else {\n var selfAsParent = false;\n var ancestor = parent;\n\n while (!ancestor.empty()) {\n if (node.same(ancestor)) {\n // mark self as parent and remove from data\n selfAsParent = true;\n _data4.parent = undefined; // remove parent reference\n // exit or we loop forever\n\n break;\n }\n\n ancestor = ancestor.parent();\n }\n\n if (!selfAsParent) {\n // connect with children\n parent[0]._private.children.push(node);\n\n node._private.parent = parent[0]; // let the core know we have a compound graph\n\n cy_p.hasCompoundNodes = true;\n }\n } // else\n\n } // if specified parent\n\n } // for each node\n\n\n if (elements.length > 0) {\n var restored = new Collection(cy, elements);\n\n for (var _i4 = 0; _i4 < restored.length; _i4++) {\n var _ele2 = restored[_i4];\n\n if (_ele2.isNode()) {\n continue;\n } // adding an edge invalidates the traversal caches for the parallel edges\n\n\n _ele2.parallelEdges().clearTraversalCache(); // adding an edge invalidates the traversal cache for the connected nodes\n\n\n _ele2.source().clearTraversalCache();\n\n _ele2.target().clearTraversalCache();\n }\n\n var toUpdateStyle;\n\n if (cy_p.hasCompoundNodes) {\n toUpdateStyle = cy.collection().merge(restored).merge(restored.connectedNodes()).merge(restored.parent());\n } else {\n toUpdateStyle = restored;\n }\n\n toUpdateStyle.dirtyCompoundBoundsCache().dirtyBoundingBoxCache().updateStyle(notifyRenderer);\n\n if (notifyRenderer) {\n restored.emitAndNotify('add');\n } else if (addToPool) {\n restored.emit('add');\n }\n }\n\n return self; // chainability\n};\n\nelesfn$u.removed = function () {\n var ele = this[0];\n return ele && ele._private.removed;\n};\n\nelesfn$u.inside = function () {\n var ele = this[0];\n return ele && !ele._private.removed;\n};\n\nelesfn$u.remove = function () {\n var notifyRenderer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n var removeFromPool = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var self = this;\n var elesToRemove = [];\n var elesToRemoveIds = {};\n var cy = self._private.cy; // add connected edges\n\n function addConnectedEdges(node) {\n var edges = node._private.edges;\n\n for (var i = 0; i < edges.length; i++) {\n add(edges[i]);\n }\n } // add descendant nodes\n\n\n function addChildren(node) {\n var children = node._private.children;\n\n for (var i = 0; i < children.length; i++) {\n add(children[i]);\n }\n }\n\n function add(ele) {\n var alreadyAdded = elesToRemoveIds[ele.id()];\n\n if (removeFromPool && ele.removed() || alreadyAdded) {\n return;\n } else {\n elesToRemoveIds[ele.id()] = true;\n }\n\n if (ele.isNode()) {\n elesToRemove.push(ele); // nodes are removed last\n\n addConnectedEdges(ele);\n addChildren(ele);\n } else {\n elesToRemove.unshift(ele); // edges are removed first\n }\n } // make the list of elements to remove\n // (may be removing more than specified due to connected edges etc)\n\n\n for (var i = 0, l = self.length; i < l; i++) {\n var ele = self[i];\n add(ele);\n }\n\n function removeEdgeRef(node, edge) {\n var connectedEdges = node._private.edges;\n removeFromArray(connectedEdges, edge); // removing an edges invalidates the traversal cache for its nodes\n\n node.clearTraversalCache();\n }\n\n function removeParallelRef(pllEdge) {\n // removing an edge invalidates the traversal caches for the parallel edges\n pllEdge.clearTraversalCache();\n }\n\n var alteredParents = [];\n alteredParents.ids = {};\n\n function removeChildRef(parent, ele) {\n ele = ele[0];\n parent = parent[0];\n var children = parent._private.children;\n var pid = parent.id();\n removeFromArray(children, ele); // remove parent => child ref\n\n ele._private.parent = null; // remove child => parent ref\n\n if (!alteredParents.ids[pid]) {\n alteredParents.ids[pid] = true;\n alteredParents.push(parent);\n }\n }\n\n self.dirtyCompoundBoundsCache();\n\n if (removeFromPool) {\n cy.removeFromPool(elesToRemove); // remove from core pool\n }\n\n for (var _i5 = 0; _i5 < elesToRemove.length; _i5++) {\n var _ele3 = elesToRemove[_i5];\n\n if (_ele3.isEdge()) {\n // remove references to this edge in its connected nodes\n var src = _ele3.source()[0];\n\n var tgt = _ele3.target()[0];\n\n removeEdgeRef(src, _ele3);\n removeEdgeRef(tgt, _ele3);\n\n var pllEdges = _ele3.parallelEdges();\n\n for (var j = 0; j < pllEdges.length; j++) {\n var pllEdge = pllEdges[j];\n removeParallelRef(pllEdge);\n\n if (pllEdge.isBundledBezier()) {\n pllEdge.dirtyBoundingBoxCache();\n }\n }\n } else {\n // remove reference to parent\n var parent = _ele3.parent();\n\n if (parent.length !== 0) {\n removeChildRef(parent, _ele3);\n }\n }\n\n if (removeFromPool) {\n // mark as removed\n _ele3._private.removed = true;\n }\n } // check to see if we have a compound graph or not\n\n\n var elesStillInside = cy._private.elements;\n cy._private.hasCompoundNodes = false;\n\n for (var _i6 = 0; _i6 < elesStillInside.length; _i6++) {\n var _ele4 = elesStillInside[_i6];\n\n if (_ele4.isParent()) {\n cy._private.hasCompoundNodes = true;\n break;\n }\n }\n\n var removedElements = new Collection(this.cy(), elesToRemove);\n\n if (removedElements.size() > 0) {\n // must manually notify since trigger won't do this automatically once removed\n if (notifyRenderer) {\n removedElements.emitAndNotify('remove');\n } else if (removeFromPool) {\n removedElements.emit('remove');\n }\n } // the parents who were modified by the removal need their style updated\n\n\n for (var _i7 = 0; _i7 < alteredParents.length; _i7++) {\n var _ele5 = alteredParents[_i7];\n\n if (!removeFromPool || !_ele5.removed()) {\n _ele5.updateStyle();\n }\n }\n\n return removedElements;\n};\n\nelesfn$u.move = function (struct) {\n var cy = this._private.cy;\n var eles = this; // just clean up refs, caches, etc. in the same way as when removing and then restoring\n // (our calls to remove/restore do not remove from the graph or make events)\n\n var notifyRenderer = false;\n var modifyPool = false;\n\n var toString = function toString(id) {\n return id == null ? id : '' + id;\n }; // id must be string\n\n\n if (struct.source !== undefined || struct.target !== undefined) {\n var srcId = toString(struct.source);\n var tgtId = toString(struct.target);\n var srcExists = srcId != null && cy.hasElementWithId(srcId);\n var tgtExists = tgtId != null && cy.hasElementWithId(tgtId);\n\n if (srcExists || tgtExists) {\n cy.batch(function () {\n // avoid duplicate style updates\n eles.remove(notifyRenderer, modifyPool); // clean up refs etc.\n\n eles.emitAndNotify('moveout');\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var _data5 = ele._private.data;\n\n if (ele.isEdge()) {\n if (srcExists) {\n _data5.source = srcId;\n }\n\n if (tgtExists) {\n _data5.target = tgtId;\n }\n }\n }\n\n eles.restore(notifyRenderer, modifyPool); // make new refs, style, etc.\n });\n eles.emitAndNotify('move');\n }\n } else if (struct.parent !== undefined) {\n // move node to new parent\n var parentId = toString(struct.parent);\n var parentExists = parentId === null || cy.hasElementWithId(parentId);\n\n if (parentExists) {\n var pidToAssign = parentId === null ? undefined : parentId;\n cy.batch(function () {\n // avoid duplicate style updates\n var updated = eles.remove(notifyRenderer, modifyPool); // clean up refs etc.\n\n updated.emitAndNotify('moveout');\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var _data6 = ele._private.data;\n\n if (ele.isNode()) {\n _data6.parent = pidToAssign;\n }\n }\n\n updated.restore(notifyRenderer, modifyPool); // make new refs, style, etc.\n });\n eles.emitAndNotify('move');\n }\n }\n\n return this;\n};\n\n[elesfn$c, elesfn$d, elesfn$e, elesfn$f, elesfn$g, data$1, elesfn$i, dimensions, elesfn$m, elesfn$n, elesfn$o, elesfn$p, elesfn$q, elesfn$r, elesfn$s, elesfn$t].forEach(function (props) {\n extend(elesfn$u, props);\n});\n\nvar corefn = {\n add: function add(opts) {\n var elements;\n var cy = this; // add the elements\n\n if (elementOrCollection(opts)) {\n var eles = opts;\n\n if (eles._private.cy === cy) {\n // same instance => just restore\n elements = eles.restore();\n } else {\n // otherwise, copy from json\n var jsons = [];\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n jsons.push(ele.json());\n }\n\n elements = new Collection(cy, jsons);\n }\n } // specify an array of options\n else if (array(opts)) {\n var _jsons = opts;\n elements = new Collection(cy, _jsons);\n } // specify via opts.nodes and opts.edges\n else if (plainObject(opts) && (array(opts.nodes) || array(opts.edges))) {\n var elesByGroup = opts;\n var _jsons2 = [];\n var grs = ['nodes', 'edges'];\n\n for (var _i = 0, il = grs.length; _i < il; _i++) {\n var group = grs[_i];\n var elesArray = elesByGroup[group];\n\n if (array(elesArray)) {\n for (var j = 0, jl = elesArray.length; j < jl; j++) {\n var json = extend({\n group: group\n }, elesArray[j]);\n\n _jsons2.push(json);\n }\n }\n }\n\n elements = new Collection(cy, _jsons2);\n } // specify options for one element\n else {\n var _json = opts;\n elements = new Element(cy, _json).collection();\n }\n\n return elements;\n },\n remove: function remove(collection) {\n if (elementOrCollection(collection)) ; else if (string(collection)) {\n var selector = collection;\n collection = this.$(selector);\n }\n\n return collection.remove();\n }\n};\n\n/* global Float32Array */\n\n/*! Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */\nfunction generateCubicBezier(mX1, mY1, mX2, mY2) {\n var NEWTON_ITERATIONS = 4,\n NEWTON_MIN_SLOPE = 0.001,\n SUBDIVISION_PRECISION = 0.0000001,\n SUBDIVISION_MAX_ITERATIONS = 10,\n kSplineTableSize = 11,\n kSampleStepSize = 1.0 / (kSplineTableSize - 1.0),\n float32ArraySupported = typeof Float32Array !== 'undefined';\n /* Must contain four arguments. */\n\n if (arguments.length !== 4) {\n return false;\n }\n /* Arguments must be numbers. */\n\n\n for (var i = 0; i < 4; ++i) {\n if (typeof arguments[i] !== \"number\" || isNaN(arguments[i]) || !isFinite(arguments[i])) {\n return false;\n }\n }\n /* X values must be in the [0, 1] range. */\n\n\n mX1 = Math.min(mX1, 1);\n mX2 = Math.min(mX2, 1);\n mX1 = Math.max(mX1, 0);\n mX2 = Math.max(mX2, 0);\n var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);\n\n function A(aA1, aA2) {\n return 1.0 - 3.0 * aA2 + 3.0 * aA1;\n }\n\n function B(aA1, aA2) {\n return 3.0 * aA2 - 6.0 * aA1;\n }\n\n function C(aA1) {\n return 3.0 * aA1;\n }\n\n function calcBezier(aT, aA1, aA2) {\n return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;\n }\n\n function getSlope(aT, aA1, aA2) {\n return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);\n }\n\n function newtonRaphsonIterate(aX, aGuessT) {\n for (var _i = 0; _i < NEWTON_ITERATIONS; ++_i) {\n var currentSlope = getSlope(aGuessT, mX1, mX2);\n\n if (currentSlope === 0.0) {\n return aGuessT;\n }\n\n var currentX = calcBezier(aGuessT, mX1, mX2) - aX;\n aGuessT -= currentX / currentSlope;\n }\n\n return aGuessT;\n }\n\n function calcSampleValues() {\n for (var _i2 = 0; _i2 < kSplineTableSize; ++_i2) {\n mSampleValues[_i2] = calcBezier(_i2 * kSampleStepSize, mX1, mX2);\n }\n }\n\n function binarySubdivide(aX, aA, aB) {\n var currentX,\n currentT,\n i = 0;\n\n do {\n currentT = aA + (aB - aA) / 2.0;\n currentX = calcBezier(currentT, mX1, mX2) - aX;\n\n if (currentX > 0.0) {\n aB = currentT;\n } else {\n aA = currentT;\n }\n } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);\n\n return currentT;\n }\n\n function getTForX(aX) {\n var intervalStart = 0.0,\n currentSample = 1,\n lastSample = kSplineTableSize - 1;\n\n for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {\n intervalStart += kSampleStepSize;\n }\n\n --currentSample;\n var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]),\n guessForT = intervalStart + dist * kSampleStepSize,\n initialSlope = getSlope(guessForT, mX1, mX2);\n\n if (initialSlope >= NEWTON_MIN_SLOPE) {\n return newtonRaphsonIterate(aX, guessForT);\n } else if (initialSlope === 0.0) {\n return guessForT;\n } else {\n return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);\n }\n }\n\n var _precomputed = false;\n\n function precompute() {\n _precomputed = true;\n\n if (mX1 !== mY1 || mX2 !== mY2) {\n calcSampleValues();\n }\n }\n\n var f = function f(aX) {\n if (!_precomputed) {\n precompute();\n }\n\n if (mX1 === mY1 && mX2 === mY2) {\n return aX;\n }\n\n if (aX === 0) {\n return 0;\n }\n\n if (aX === 1) {\n return 1;\n }\n\n return calcBezier(getTForX(aX), mY1, mY2);\n };\n\n f.getControlPoints = function () {\n return [{\n x: mX1,\n y: mY1\n }, {\n x: mX2,\n y: mY2\n }];\n };\n\n var str = \"generateBezier(\" + [mX1, mY1, mX2, mY2] + \")\";\n\n f.toString = function () {\n return str;\n };\n\n return f;\n}\n\n/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */\n\n/* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass\n then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */\nvar generateSpringRK4 = function () {\n function springAccelerationForState(state) {\n return -state.tension * state.x - state.friction * state.v;\n }\n\n function springEvaluateStateWithDerivative(initialState, dt, derivative) {\n var state = {\n x: initialState.x + derivative.dx * dt,\n v: initialState.v + derivative.dv * dt,\n tension: initialState.tension,\n friction: initialState.friction\n };\n return {\n dx: state.v,\n dv: springAccelerationForState(state)\n };\n }\n\n function springIntegrateState(state, dt) {\n var a = {\n dx: state.v,\n dv: springAccelerationForState(state)\n },\n b = springEvaluateStateWithDerivative(state, dt * 0.5, a),\n c = springEvaluateStateWithDerivative(state, dt * 0.5, b),\n d = springEvaluateStateWithDerivative(state, dt, c),\n dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),\n dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);\n state.x = state.x + dxdt * dt;\n state.v = state.v + dvdt * dt;\n return state;\n }\n\n return function springRK4Factory(tension, friction, duration) {\n var initState = {\n x: -1,\n v: 0,\n tension: null,\n friction: null\n },\n path = [0],\n time_lapsed = 0,\n tolerance = 1 / 10000,\n DT = 16 / 1000,\n have_duration,\n dt,\n last_state;\n tension = parseFloat(tension) || 500;\n friction = parseFloat(friction) || 20;\n duration = duration || null;\n initState.tension = tension;\n initState.friction = friction;\n have_duration = duration !== null;\n /* Calculate the actual time it takes for this animation to complete with the provided conditions. */\n\n if (have_duration) {\n /* Run the simulation without a duration. */\n time_lapsed = springRK4Factory(tension, friction);\n /* Compute the adjusted time delta. */\n\n dt = time_lapsed / duration * DT;\n } else {\n dt = DT;\n }\n\n for (;;) {\n /* Next/step function .*/\n last_state = springIntegrateState(last_state || initState, dt);\n /* Store the position. */\n\n path.push(1 + last_state.x);\n time_lapsed += 16;\n /* If the change threshold is reached, break. */\n\n if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {\n break;\n }\n }\n /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the\n computed path and returns a snapshot of the position according to a given percentComplete. */\n\n\n return !have_duration ? time_lapsed : function (percentComplete) {\n return path[percentComplete * (path.length - 1) | 0];\n };\n };\n}();\n\nvar cubicBezier = function cubicBezier(t1, p1, t2, p2) {\n var bezier = generateCubicBezier(t1, p1, t2, p2);\n return function (start, end, percent) {\n return start + (end - start) * bezier(percent);\n };\n};\n\nvar easings = {\n 'linear': function linear(start, end, percent) {\n return start + (end - start) * percent;\n },\n // default easings\n 'ease': cubicBezier(0.25, 0.1, 0.25, 1),\n 'ease-in': cubicBezier(0.42, 0, 1, 1),\n 'ease-out': cubicBezier(0, 0, 0.58, 1),\n 'ease-in-out': cubicBezier(0.42, 0, 0.58, 1),\n // sine\n 'ease-in-sine': cubicBezier(0.47, 0, 0.745, 0.715),\n 'ease-out-sine': cubicBezier(0.39, 0.575, 0.565, 1),\n 'ease-in-out-sine': cubicBezier(0.445, 0.05, 0.55, 0.95),\n // quad\n 'ease-in-quad': cubicBezier(0.55, 0.085, 0.68, 0.53),\n 'ease-out-quad': cubicBezier(0.25, 0.46, 0.45, 0.94),\n 'ease-in-out-quad': cubicBezier(0.455, 0.03, 0.515, 0.955),\n // cubic\n 'ease-in-cubic': cubicBezier(0.55, 0.055, 0.675, 0.19),\n 'ease-out-cubic': cubicBezier(0.215, 0.61, 0.355, 1),\n 'ease-in-out-cubic': cubicBezier(0.645, 0.045, 0.355, 1),\n // quart\n 'ease-in-quart': cubicBezier(0.895, 0.03, 0.685, 0.22),\n 'ease-out-quart': cubicBezier(0.165, 0.84, 0.44, 1),\n 'ease-in-out-quart': cubicBezier(0.77, 0, 0.175, 1),\n // quint\n 'ease-in-quint': cubicBezier(0.755, 0.05, 0.855, 0.06),\n 'ease-out-quint': cubicBezier(0.23, 1, 0.32, 1),\n 'ease-in-out-quint': cubicBezier(0.86, 0, 0.07, 1),\n // expo\n 'ease-in-expo': cubicBezier(0.95, 0.05, 0.795, 0.035),\n 'ease-out-expo': cubicBezier(0.19, 1, 0.22, 1),\n 'ease-in-out-expo': cubicBezier(1, 0, 0, 1),\n // circ\n 'ease-in-circ': cubicBezier(0.6, 0.04, 0.98, 0.335),\n 'ease-out-circ': cubicBezier(0.075, 0.82, 0.165, 1),\n 'ease-in-out-circ': cubicBezier(0.785, 0.135, 0.15, 0.86),\n // user param easings...\n 'spring': function spring(tension, friction, duration) {\n if (duration === 0) {\n // can't get a spring w/ duration 0\n return easings.linear; // duration 0 => jump to end so impl doesn't matter\n }\n\n var spring = generateSpringRK4(tension, friction, duration);\n return function (start, end, percent) {\n return start + (end - start) * spring(percent);\n };\n },\n 'cubic-bezier': cubicBezier\n};\n\nfunction getEasedValue(type, start, end, percent, easingFn) {\n if (percent === 1) {\n return end;\n }\n\n if (start === end) {\n return end;\n }\n\n var val = easingFn(start, end, percent);\n\n if (type == null) {\n return val;\n }\n\n if (type.roundValue || type.color) {\n val = Math.round(val);\n }\n\n if (type.min !== undefined) {\n val = Math.max(val, type.min);\n }\n\n if (type.max !== undefined) {\n val = Math.min(val, type.max);\n }\n\n return val;\n}\n\nfunction getValue(prop, spec) {\n if (prop.pfValue != null || prop.value != null) {\n if (prop.pfValue != null && (spec == null || spec.type.units !== '%')) {\n return prop.pfValue;\n } else {\n return prop.value;\n }\n } else {\n return prop;\n }\n}\n\nfunction ease(startProp, endProp, percent, easingFn, propSpec) {\n var type = propSpec != null ? propSpec.type : null;\n\n if (percent < 0) {\n percent = 0;\n } else if (percent > 1) {\n percent = 1;\n }\n\n var start = getValue(startProp, propSpec);\n var end = getValue(endProp, propSpec);\n\n if (number(start) && number(end)) {\n return getEasedValue(type, start, end, percent, easingFn);\n } else if (array(start) && array(end)) {\n var easedArr = [];\n\n for (var i = 0; i < end.length; i++) {\n var si = start[i];\n var ei = end[i];\n\n if (si != null && ei != null) {\n var val = getEasedValue(type, si, ei, percent, easingFn);\n easedArr.push(val);\n } else {\n easedArr.push(ei);\n }\n }\n\n return easedArr;\n }\n\n return undefined;\n}\n\nfunction step(self, ani, now, isCore) {\n var isEles = !isCore;\n var _p = self._private;\n var ani_p = ani._private;\n var pEasing = ani_p.easing;\n var startTime = ani_p.startTime;\n var cy = isCore ? self : self.cy();\n var style = cy.style();\n\n if (!ani_p.easingImpl) {\n if (pEasing == null) {\n // use default\n ani_p.easingImpl = easings['linear'];\n } else {\n // then define w/ name\n var easingVals;\n\n if (string(pEasing)) {\n var easingProp = style.parse('transition-timing-function', pEasing);\n easingVals = easingProp.value;\n } else {\n // then assume preparsed array\n easingVals = pEasing;\n }\n\n var name, args;\n\n if (string(easingVals)) {\n name = easingVals;\n args = [];\n } else {\n name = easingVals[1];\n args = easingVals.slice(2).map(function (n) {\n return +n;\n });\n }\n\n if (args.length > 0) {\n // create with args\n if (name === 'spring') {\n args.push(ani_p.duration); // need duration to generate spring\n }\n\n ani_p.easingImpl = easings[name].apply(null, args);\n } else {\n // static impl by name\n ani_p.easingImpl = easings[name];\n }\n }\n }\n\n var easing = ani_p.easingImpl;\n var percent;\n\n if (ani_p.duration === 0) {\n percent = 1;\n } else {\n percent = (now - startTime) / ani_p.duration;\n }\n\n if (ani_p.applying) {\n percent = ani_p.progress;\n }\n\n if (percent < 0) {\n percent = 0;\n } else if (percent > 1) {\n percent = 1;\n }\n\n if (ani_p.delay == null) {\n // then update\n var startPos = ani_p.startPosition;\n var endPos = ani_p.position;\n\n if (endPos && isEles && !self.locked()) {\n var newPos = {};\n\n if (valid(startPos.x, endPos.x)) {\n newPos.x = ease(startPos.x, endPos.x, percent, easing);\n }\n\n if (valid(startPos.y, endPos.y)) {\n newPos.y = ease(startPos.y, endPos.y, percent, easing);\n }\n\n self.position(newPos);\n }\n\n var startPan = ani_p.startPan;\n var endPan = ani_p.pan;\n var pan = _p.pan;\n var animatingPan = endPan != null && isCore;\n\n if (animatingPan) {\n if (valid(startPan.x, endPan.x)) {\n pan.x = ease(startPan.x, endPan.x, percent, easing);\n }\n\n if (valid(startPan.y, endPan.y)) {\n pan.y = ease(startPan.y, endPan.y, percent, easing);\n }\n\n self.emit('pan');\n }\n\n var startZoom = ani_p.startZoom;\n var endZoom = ani_p.zoom;\n var animatingZoom = endZoom != null && isCore;\n\n if (animatingZoom) {\n if (valid(startZoom, endZoom)) {\n _p.zoom = bound(_p.minZoom, ease(startZoom, endZoom, percent, easing), _p.maxZoom);\n }\n\n self.emit('zoom');\n }\n\n if (animatingPan || animatingZoom) {\n self.emit('viewport');\n }\n\n var props = ani_p.style;\n\n if (props && props.length > 0 && isEles) {\n for (var i = 0; i < props.length; i++) {\n var prop = props[i];\n var _name = prop.name;\n var end = prop;\n var start = ani_p.startStyle[_name];\n var propSpec = style.properties[start.name];\n var easedVal = ease(start, end, percent, easing, propSpec);\n style.overrideBypass(self, _name, easedVal);\n } // for props\n\n\n self.emit('style');\n } // if\n\n }\n\n ani_p.progress = percent;\n return percent;\n}\n\nfunction valid(start, end) {\n if (start == null || end == null) {\n return false;\n }\n\n if (number(start) && number(end)) {\n return true;\n } else if (start && end) {\n return true;\n }\n\n return false;\n}\n\nfunction startAnimation(self, ani, now, isCore) {\n var ani_p = ani._private;\n ani_p.started = true;\n ani_p.startTime = now - ani_p.progress * ani_p.duration;\n}\n\nfunction stepAll(now, cy) {\n var eles = cy._private.aniEles;\n var doneEles = [];\n\n function stepOne(ele, isCore) {\n var _p = ele._private;\n var current = _p.animation.current;\n var queue = _p.animation.queue;\n var ranAnis = false; // if nothing currently animating, get something from the queue\n\n if (current.length === 0) {\n var next = queue.shift();\n\n if (next) {\n current.push(next);\n }\n }\n\n var callbacks = function callbacks(_callbacks) {\n for (var j = _callbacks.length - 1; j >= 0; j--) {\n var cb = _callbacks[j];\n cb();\n }\n\n _callbacks.splice(0, _callbacks.length);\n }; // step and remove if done\n\n\n for (var i = current.length - 1; i >= 0; i--) {\n var ani = current[i];\n var ani_p = ani._private;\n\n if (ani_p.stopped) {\n current.splice(i, 1);\n ani_p.hooked = false;\n ani_p.playing = false;\n ani_p.started = false;\n callbacks(ani_p.frames);\n continue;\n }\n\n if (!ani_p.playing && !ani_p.applying) {\n continue;\n } // an apply() while playing shouldn't do anything\n\n\n if (ani_p.playing && ani_p.applying) {\n ani_p.applying = false;\n }\n\n if (!ani_p.started) {\n startAnimation(ele, ani, now);\n }\n\n step(ele, ani, now, isCore);\n\n if (ani_p.applying) {\n ani_p.applying = false;\n }\n\n callbacks(ani_p.frames);\n\n if (ani_p.step != null) {\n ani_p.step(now);\n }\n\n if (ani.completed()) {\n current.splice(i, 1);\n ani_p.hooked = false;\n ani_p.playing = false;\n ani_p.started = false;\n callbacks(ani_p.completes);\n }\n\n ranAnis = true;\n }\n\n if (!isCore && current.length === 0 && queue.length === 0) {\n doneEles.push(ele);\n }\n\n return ranAnis;\n } // stepElement\n // handle all eles\n\n\n var ranEleAni = false;\n\n for (var e = 0; e < eles.length; e++) {\n var ele = eles[e];\n var handledThisEle = stepOne(ele);\n ranEleAni = ranEleAni || handledThisEle;\n } // each element\n\n\n var ranCoreAni = stepOne(cy, true); // notify renderer\n\n if (ranEleAni || ranCoreAni) {\n if (eles.length > 0) {\n cy.notify('draw', eles);\n } else {\n cy.notify('draw');\n }\n } // remove elements from list of currently animating if its queues are empty\n\n\n eles.unmerge(doneEles);\n cy.emit('step');\n} // stepAll\n\nvar corefn$1 = {\n // pull in animation functions\n animate: define$3.animate(),\n animation: define$3.animation(),\n animated: define$3.animated(),\n clearQueue: define$3.clearQueue(),\n delay: define$3.delay(),\n delayAnimation: define$3.delayAnimation(),\n stop: define$3.stop(),\n addToAnimationPool: function addToAnimationPool(eles) {\n var cy = this;\n\n if (!cy.styleEnabled()) {\n return;\n } // save cycles when no style used\n\n\n cy._private.aniEles.merge(eles);\n },\n stopAnimationLoop: function stopAnimationLoop() {\n this._private.animationsRunning = false;\n },\n startAnimationLoop: function startAnimationLoop() {\n var cy = this;\n cy._private.animationsRunning = true;\n\n if (!cy.styleEnabled()) {\n return;\n } // save cycles when no style used\n // NB the animation loop will exec in headless environments if style enabled\n // and explicit cy.destroy() is necessary to stop the loop\n\n\n function headlessStep() {\n if (!cy._private.animationsRunning) {\n return;\n }\n\n requestAnimationFrame(function animationStep(now) {\n stepAll(now, cy);\n headlessStep();\n });\n }\n\n var renderer = cy.renderer();\n\n if (renderer && renderer.beforeRender) {\n // let the renderer schedule animations\n renderer.beforeRender(function rendererAnimationStep(willDraw, now) {\n stepAll(now, cy);\n }, renderer.beforeRenderPriorities.animations);\n } else {\n // manage the animation loop ourselves\n headlessStep(); // first call\n }\n }\n};\n\nvar emitterOptions$1 = {\n qualifierCompare: function qualifierCompare(selector1, selector2) {\n if (selector1 == null || selector2 == null) {\n return selector1 == null && selector2 == null;\n } else {\n return selector1.sameText(selector2);\n }\n },\n eventMatches: function eventMatches(cy, listener, eventObj) {\n var selector = listener.qualifier;\n\n if (selector != null) {\n return cy !== eventObj.target && element(eventObj.target) && selector.matches(eventObj.target);\n }\n\n return true;\n },\n addEventFields: function addEventFields(cy, evt) {\n evt.cy = cy;\n evt.target = cy;\n },\n callbackContext: function callbackContext(cy, listener, eventObj) {\n return listener.qualifier != null ? eventObj.target : cy;\n }\n};\n\nvar argSelector$1 = function argSelector(arg) {\n if (string(arg)) {\n return new Selector(arg);\n } else {\n return arg;\n }\n};\n\nvar elesfn$v = {\n createEmitter: function createEmitter() {\n var _p = this._private;\n\n if (!_p.emitter) {\n _p.emitter = new Emitter(emitterOptions$1, this);\n }\n\n return this;\n },\n emitter: function emitter() {\n return this._private.emitter;\n },\n on: function on(events, selector, callback) {\n this.emitter().on(events, argSelector$1(selector), callback);\n return this;\n },\n removeListener: function removeListener(events, selector, callback) {\n this.emitter().removeListener(events, argSelector$1(selector), callback);\n return this;\n },\n removeAllListeners: function removeAllListeners() {\n this.emitter().removeAllListeners();\n return this;\n },\n one: function one(events, selector, callback) {\n this.emitter().one(events, argSelector$1(selector), callback);\n return this;\n },\n once: function once(events, selector, callback) {\n this.emitter().one(events, argSelector$1(selector), callback);\n return this;\n },\n emit: function emit(events, extraParams) {\n this.emitter().emit(events, extraParams);\n return this;\n },\n emitAndNotify: function emitAndNotify(event, eles) {\n this.emit(event);\n this.notify(event, eles);\n return this;\n }\n};\ndefine$3.eventAliasesOn(elesfn$v);\n\nvar corefn$2 = {\n png: function png(options) {\n var renderer = this._private.renderer;\n options = options || {};\n return renderer.png(options);\n },\n jpg: function jpg(options) {\n var renderer = this._private.renderer;\n options = options || {};\n options.bg = options.bg || '#fff';\n return renderer.jpg(options);\n }\n};\ncorefn$2.jpeg = corefn$2.jpg;\n\nvar corefn$3 = {\n layout: function layout(options) {\n var cy = this;\n\n if (options == null) {\n error('Layout options must be specified to make a layout');\n return;\n }\n\n if (options.name == null) {\n error('A `name` must be specified to make a layout');\n return;\n }\n\n var name = options.name;\n var Layout = cy.extension('layout', name);\n\n if (Layout == null) {\n error('No such layout `' + name + '` found. Did you forget to import it and `cytoscape.use()` it?');\n return;\n }\n\n var eles;\n\n if (string(options.eles)) {\n eles = cy.$(options.eles);\n } else {\n eles = options.eles != null ? options.eles : cy.$();\n }\n\n var layout = new Layout(extend({}, options, {\n cy: cy,\n eles: eles\n }));\n return layout;\n }\n};\ncorefn$3.createLayout = corefn$3.makeLayout = corefn$3.layout;\n\nvar corefn$4 = {\n notify: function notify(eventName, eventEles) {\n var _p = this._private;\n\n if (this.batching()) {\n _p.batchNotifications = _p.batchNotifications || {};\n var eles = _p.batchNotifications[eventName] = _p.batchNotifications[eventName] || this.collection();\n\n if (eventEles != null) {\n eles.merge(eventEles);\n }\n\n return; // notifications are disabled during batching\n }\n\n if (!_p.notificationsEnabled) {\n return;\n } // exit on disabled\n\n\n var renderer = this.renderer(); // exit if destroy() called on core or renderer in between frames #1499 #1528\n\n if (this.destroyed() || !renderer) {\n return;\n }\n\n renderer.notify(eventName, eventEles);\n },\n notifications: function notifications(bool) {\n var p = this._private;\n\n if (bool === undefined) {\n return p.notificationsEnabled;\n } else {\n p.notificationsEnabled = bool ? true : false;\n }\n\n return this;\n },\n noNotifications: function noNotifications(callback) {\n this.notifications(false);\n callback();\n this.notifications(true);\n },\n batching: function batching() {\n return this._private.batchCount > 0;\n },\n startBatch: function startBatch() {\n var _p = this._private;\n\n if (_p.batchCount == null) {\n _p.batchCount = 0;\n }\n\n if (_p.batchCount === 0) {\n _p.batchStyleEles = this.collection();\n _p.batchNotifications = {};\n }\n\n _p.batchCount++;\n return this;\n },\n endBatch: function endBatch() {\n var _p = this._private;\n\n if (_p.batchCount === 0) {\n return this;\n }\n\n _p.batchCount--;\n\n if (_p.batchCount === 0) {\n // update style for dirty eles\n _p.batchStyleEles.updateStyle();\n\n var renderer = this.renderer(); // notify the renderer of queued eles and event types\n\n Object.keys(_p.batchNotifications).forEach(function (eventName) {\n var eles = _p.batchNotifications[eventName];\n\n if (eles.empty()) {\n renderer.notify(eventName);\n } else {\n renderer.notify(eventName, eles);\n }\n });\n }\n\n return this;\n },\n batch: function batch(callback) {\n this.startBatch();\n callback();\n this.endBatch();\n return this;\n },\n // for backwards compatibility\n batchData: function batchData(map) {\n var cy = this;\n return this.batch(function () {\n var ids = Object.keys(map);\n\n for (var i = 0; i < ids.length; i++) {\n var id = ids[i];\n var data = map[id];\n var ele = cy.getElementById(id);\n ele.data(data);\n }\n });\n }\n};\n\nvar rendererDefaults = defaults({\n hideEdgesOnViewport: false,\n textureOnViewport: false,\n motionBlur: false,\n motionBlurOpacity: 0.05,\n pixelRatio: undefined,\n desktopTapThreshold: 4,\n touchTapThreshold: 8,\n wheelSensitivity: 1,\n debug: false,\n showFps: false\n});\nvar corefn$5 = {\n renderTo: function renderTo(context, zoom, pan, pxRatio) {\n var r = this._private.renderer;\n r.renderTo(context, zoom, pan, pxRatio);\n return this;\n },\n renderer: function renderer() {\n return this._private.renderer;\n },\n forceRender: function forceRender() {\n this.notify('draw');\n return this;\n },\n resize: function resize() {\n this.invalidateSize();\n this.emitAndNotify('resize');\n return this;\n },\n initRenderer: function initRenderer(options) {\n var cy = this;\n var RendererProto = cy.extension('renderer', options.name);\n\n if (RendererProto == null) {\n error(\"Can not initialise: No such renderer `\".concat(options.name, \"` found. Did you forget to import it and `cytoscape.use()` it?\"));\n return;\n }\n\n if (options.wheelSensitivity !== undefined) {\n warn(\"You have set a custom wheel sensitivity. This will make your app zoom unnaturally when using mainstream mice. You should change this value from the default only if you can guarantee that all your users will use the same hardware and OS configuration as your current machine.\");\n }\n\n var rOpts = rendererDefaults(options);\n rOpts.cy = cy;\n cy._private.renderer = new RendererProto(rOpts);\n this.notify('init');\n },\n destroyRenderer: function destroyRenderer() {\n var cy = this;\n cy.notify('destroy'); // destroy the renderer\n\n var domEle = cy.container();\n\n if (domEle) {\n domEle._cyreg = null;\n\n while (domEle.childNodes.length > 0) {\n domEle.removeChild(domEle.childNodes[0]);\n }\n }\n\n cy._private.renderer = null; // to be extra safe, remove the ref\n\n cy.mutableElements().forEach(function (ele) {\n var _p = ele._private;\n _p.rscratch = {};\n _p.rstyle = {};\n _p.animation.current = [];\n _p.animation.queue = [];\n });\n },\n onRender: function onRender(fn) {\n return this.on('render', fn);\n },\n offRender: function offRender(fn) {\n return this.off('render', fn);\n }\n};\ncorefn$5.invalidateDimensions = corefn$5.resize;\n\nvar corefn$6 = {\n // get a collection\n // - empty collection on no args\n // - collection of elements in the graph on selector arg\n // - guarantee a returned collection when elements or collection specified\n collection: function collection(eles, opts) {\n if (string(eles)) {\n return this.$(eles);\n } else if (elementOrCollection(eles)) {\n return eles.collection();\n } else if (array(eles)) {\n return new Collection(this, eles, opts);\n }\n\n return new Collection(this);\n },\n nodes: function nodes(selector) {\n var nodes = this.$(function (ele) {\n return ele.isNode();\n });\n\n if (selector) {\n return nodes.filter(selector);\n }\n\n return nodes;\n },\n edges: function edges(selector) {\n var edges = this.$(function (ele) {\n return ele.isEdge();\n });\n\n if (selector) {\n return edges.filter(selector);\n }\n\n return edges;\n },\n // search the graph like jQuery\n $: function $(selector) {\n var eles = this._private.elements;\n\n if (selector) {\n return eles.filter(selector);\n } else {\n return eles.spawnSelf();\n }\n },\n mutableElements: function mutableElements() {\n return this._private.elements;\n }\n}; // aliases\n\ncorefn$6.elements = corefn$6.filter = corefn$6.$;\n\nvar styfn = {}; // keys for style blocks, e.g. ttfftt\n\nvar TRUE = 't';\nvar FALSE = 'f'; // (potentially expensive calculation)\n// apply the style to the element based on\n// - its bypass\n// - what selectors match it\n\nstyfn.apply = function (eles) {\n var self = this;\n var _p = self._private;\n var cy = _p.cy;\n var updatedEles = cy.collection();\n\n if (_p.newStyle) {\n // clear style caches\n _p.contextStyles = {};\n _p.propDiffs = {};\n self.cleanElements(eles, true);\n }\n\n for (var ie = 0; ie < eles.length; ie++) {\n var ele = eles[ie];\n var cxtMeta = self.getContextMeta(ele);\n\n if (cxtMeta.empty) {\n continue;\n }\n\n var cxtStyle = self.getContextStyle(cxtMeta);\n var app = self.applyContextStyle(cxtMeta, cxtStyle, ele);\n\n if (!_p.newStyle) {\n self.updateTransitions(ele, app.diffProps);\n }\n\n var hintsDiff = self.updateStyleHints(ele);\n\n if (hintsDiff) {\n updatedEles.merge(ele);\n }\n } // for elements\n\n\n _p.newStyle = false;\n return updatedEles;\n};\n\nstyfn.getPropertiesDiff = function (oldCxtKey, newCxtKey) {\n var self = this;\n var cache = self._private.propDiffs = self._private.propDiffs || {};\n var dualCxtKey = oldCxtKey + '-' + newCxtKey;\n var cachedVal = cache[dualCxtKey];\n\n if (cachedVal) {\n return cachedVal;\n }\n\n var diffProps = [];\n var addedProp = {};\n\n for (var i = 0; i < self.length; i++) {\n var cxt = self[i];\n var oldHasCxt = oldCxtKey[i] === TRUE;\n var newHasCxt = newCxtKey[i] === TRUE;\n var cxtHasDiffed = oldHasCxt !== newHasCxt;\n var cxtHasMappedProps = cxt.mappedProperties.length > 0;\n\n if (cxtHasDiffed || newHasCxt && cxtHasMappedProps) {\n var props = void 0;\n\n if (cxtHasDiffed && cxtHasMappedProps) {\n props = cxt.properties; // suffices b/c mappedProperties is a subset of properties\n } else if (cxtHasDiffed) {\n props = cxt.properties; // need to check them all\n } else if (cxtHasMappedProps) {\n props = cxt.mappedProperties; // only need to check mapped\n }\n\n for (var j = 0; j < props.length; j++) {\n var prop = props[j];\n var name = prop.name; // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter\n // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result\n // is cached)\n\n var laterCxtOverrides = false;\n\n for (var k = i + 1; k < self.length; k++) {\n var laterCxt = self[k];\n var hasLaterCxt = newCxtKey[k] === TRUE;\n\n if (!hasLaterCxt) {\n continue;\n } // can't override unless the context is active\n\n\n laterCxtOverrides = laterCxt.properties[prop.name] != null;\n\n if (laterCxtOverrides) {\n break;\n } // exit early as long as one later context overrides\n\n }\n\n if (!addedProp[name] && !laterCxtOverrides) {\n addedProp[name] = true;\n diffProps.push(name);\n }\n } // for props\n\n } // if\n\n } // for contexts\n\n\n cache[dualCxtKey] = diffProps;\n return diffProps;\n};\n\nstyfn.getContextMeta = function (ele) {\n var self = this;\n var cxtKey = '';\n var diffProps;\n var prevKey = ele._private.styleCxtKey || '';\n\n if (self._private.newStyle) {\n prevKey = ''; // since we need to apply all style if a fresh stylesheet\n } // get the cxt key\n\n\n for (var i = 0; i < self.length; i++) {\n var context = self[i];\n var contextSelectorMatches = context.selector && context.selector.matches(ele); // NB: context.selector may be null for 'core'\n\n if (contextSelectorMatches) {\n cxtKey += TRUE;\n } else {\n cxtKey += FALSE;\n }\n } // for context\n\n\n diffProps = self.getPropertiesDiff(prevKey, cxtKey);\n ele._private.styleCxtKey = cxtKey;\n return {\n key: cxtKey,\n diffPropNames: diffProps,\n empty: diffProps.length === 0\n };\n}; // gets a computed ele style object based on matched contexts\n\n\nstyfn.getContextStyle = function (cxtMeta) {\n var cxtKey = cxtMeta.key;\n var self = this;\n var cxtStyles = this._private.contextStyles = this._private.contextStyles || {}; // if already computed style, returned cached copy\n\n if (cxtStyles[cxtKey]) {\n return cxtStyles[cxtKey];\n }\n\n var style = {\n _private: {\n key: cxtKey\n }\n };\n\n for (var i = 0; i < self.length; i++) {\n var cxt = self[i];\n var hasCxt = cxtKey[i] === TRUE;\n\n if (!hasCxt) {\n continue;\n }\n\n for (var j = 0; j < cxt.properties.length; j++) {\n var prop = cxt.properties[j];\n style[prop.name] = prop;\n }\n }\n\n cxtStyles[cxtKey] = style;\n return style;\n};\n\nstyfn.applyContextStyle = function (cxtMeta, cxtStyle, ele) {\n var self = this;\n var diffProps = cxtMeta.diffPropNames;\n var retDiffProps = {};\n var types = self.types;\n\n for (var i = 0; i < diffProps.length; i++) {\n var diffPropName = diffProps[i];\n var cxtProp = cxtStyle[diffPropName];\n var eleProp = ele.pstyle(diffPropName);\n\n if (!cxtProp) {\n // no context prop means delete\n if (!eleProp) {\n continue; // no existing prop means nothing needs to be removed\n // nb affects initial application on mapped values like control-point-distances\n } else if (eleProp.bypass) {\n cxtProp = {\n name: diffPropName,\n deleteBypassed: true\n };\n } else {\n cxtProp = {\n name: diffPropName,\n \"delete\": true\n };\n }\n } // save cycles when the context prop doesn't need to be applied\n\n\n if (eleProp === cxtProp) {\n continue;\n } // save cycles when a mapped context prop doesn't need to be applied\n\n\n if (cxtProp.mapped === types.fn // context prop is function mapper\n && eleProp != null // some props can be null even by default (e.g. a prop that overrides another one)\n && eleProp.mapping != null // ele prop is a concrete value from from a mapper\n && eleProp.mapping.value === cxtProp.value // the current prop on the ele is a flat prop value for the function mapper\n ) {\n // NB don't write to cxtProp, as it's shared among eles (stored in stylesheet)\n var mapping = eleProp.mapping; // can write to mapping, as it's a per-ele copy\n\n var fnValue = mapping.fnValue = cxtProp.value(ele); // temporarily cache the value in case of a miss\n\n if (fnValue === mapping.prevFnValue) {\n continue;\n }\n }\n\n var retDiffProp = retDiffProps[diffPropName] = {\n prev: eleProp\n };\n self.applyParsedProperty(ele, cxtProp);\n retDiffProp.next = ele.pstyle(diffPropName);\n\n if (retDiffProp.next && retDiffProp.next.bypass) {\n retDiffProp.next = retDiffProp.next.bypassed;\n }\n }\n\n return {\n diffProps: retDiffProps\n };\n};\n\nstyfn.updateStyleHints = function (ele) {\n var _p = ele._private;\n var self = this;\n var propNames = self.propertyGroupNames;\n var propGrKeys = self.propertyGroupKeys;\n\n var propHash = function propHash(ele, propNames, seedKey) {\n return self.getPropertiesHash(ele, propNames, seedKey);\n };\n\n var oldStyleKey = _p.styleKey;\n\n if (ele.removed()) {\n return false;\n }\n\n var isNode = _p.group === 'nodes'; // get the style key hashes per prop group\n // but lazily -- only use non-default prop values to reduce the number of hashes\n //\n\n var overriddenStyles = ele._private.style;\n propNames = Object.keys(overriddenStyles);\n\n for (var i = 0; i < propGrKeys.length; i++) {\n var grKey = propGrKeys[i];\n _p.styleKeys[grKey] = [DEFAULT_HASH_SEED, DEFAULT_HASH_SEED_ALT];\n }\n\n var updateGrKey1 = function updateGrKey1(val, grKey) {\n return _p.styleKeys[grKey][0] = hashInt(val, _p.styleKeys[grKey][0]);\n };\n\n var updateGrKey2 = function updateGrKey2(val, grKey) {\n return _p.styleKeys[grKey][1] = hashIntAlt(val, _p.styleKeys[grKey][1]);\n };\n\n var updateGrKey = function updateGrKey(val, grKey) {\n updateGrKey1(val, grKey);\n updateGrKey2(val, grKey);\n };\n\n var updateGrKeyWStr = function updateGrKeyWStr(strVal, grKey) {\n for (var j = 0; j < strVal.length; j++) {\n var ch = strVal.charCodeAt(j);\n updateGrKey1(ch, grKey);\n updateGrKey2(ch, grKey);\n }\n }; // - hashing works on 32 bit ints b/c we use bitwise ops\n // - small numbers get cut off (e.g. 0.123 is seen as 0 by the hashing function)\n // - raise up small numbers so more significant digits are seen by hashing\n // - make small numbers larger than a normal value to avoid collisions\n // - works in practice and it's relatively cheap\n\n\n var N = 2000000000;\n\n var cleanNum = function cleanNum(val) {\n return -128 < val && val < 128 && Math.floor(val) !== val ? N - (val * 1024 | 0) : val;\n };\n\n for (var _i = 0; _i < propNames.length; _i++) {\n var name = propNames[_i];\n var parsedProp = overriddenStyles[name];\n\n if (parsedProp == null) {\n continue;\n }\n\n var propInfo = this.properties[name];\n var type = propInfo.type;\n var _grKey = propInfo.groupKey;\n var normalizedNumberVal = void 0;\n\n if (propInfo.hashOverride != null) {\n normalizedNumberVal = propInfo.hashOverride(ele, parsedProp);\n } else if (parsedProp.pfValue != null) {\n normalizedNumberVal = parsedProp.pfValue;\n } // might not be a number if it allows enums\n\n\n var numberVal = propInfo.enums == null ? parsedProp.value : null;\n var haveNormNum = normalizedNumberVal != null;\n var haveUnitedNum = numberVal != null;\n var haveNum = haveNormNum || haveUnitedNum;\n var units = parsedProp.units; // numbers are cheaper to hash than strings\n // 1 hash op vs n hash ops (for length n string)\n\n if (type.number && haveNum) {\n var v = haveNormNum ? normalizedNumberVal : numberVal;\n\n if (type.multiple) {\n for (var _i2 = 0; _i2 < v.length; _i2++) {\n updateGrKey(cleanNum(v[_i2]), _grKey);\n }\n } else {\n updateGrKey(cleanNum(v), _grKey);\n }\n\n if (!haveNormNum && units != null) {\n updateGrKeyWStr(units, _grKey);\n }\n } else {\n updateGrKeyWStr(parsedProp.strValue, _grKey);\n }\n } // overall style key\n //\n\n\n var hash = [DEFAULT_HASH_SEED, DEFAULT_HASH_SEED_ALT];\n\n for (var _i3 = 0; _i3 < propGrKeys.length; _i3++) {\n var _grKey2 = propGrKeys[_i3];\n var grHash = _p.styleKeys[_grKey2];\n hash[0] = hashInt(grHash[0], hash[0]);\n hash[1] = hashIntAlt(grHash[1], hash[1]);\n }\n\n _p.styleKey = combineHashes(hash[0], hash[1]); // label dims\n //\n\n var sk = _p.styleKeys;\n _p.labelDimsKey = combineHashesArray(sk.labelDimensions);\n var labelKeys = propHash(ele, ['label'], sk.labelDimensions);\n _p.labelKey = combineHashesArray(labelKeys);\n _p.labelStyleKey = combineHashesArray(hashArrays(sk.commonLabel, labelKeys));\n\n if (!isNode) {\n var sourceLabelKeys = propHash(ele, ['source-label'], sk.labelDimensions);\n _p.sourceLabelKey = combineHashesArray(sourceLabelKeys);\n _p.sourceLabelStyleKey = combineHashesArray(hashArrays(sk.commonLabel, sourceLabelKeys));\n var targetLabelKeys = propHash(ele, ['target-label'], sk.labelDimensions);\n _p.targetLabelKey = combineHashesArray(targetLabelKeys);\n _p.targetLabelStyleKey = combineHashesArray(hashArrays(sk.commonLabel, targetLabelKeys));\n } // node\n //\n\n\n if (isNode) {\n var _p$styleKeys = _p.styleKeys,\n nodeBody = _p$styleKeys.nodeBody,\n nodeBorder = _p$styleKeys.nodeBorder,\n backgroundImage = _p$styleKeys.backgroundImage,\n compound = _p$styleKeys.compound,\n pie = _p$styleKeys.pie;\n var nodeKeys = [nodeBorder, backgroundImage, compound, pie].reduce(hashArrays, nodeBody);\n _p.nodeKey = combineHashesArray(nodeKeys);\n _p.hasPie = pie[0] !== DEFAULT_HASH_SEED && pie[1] !== DEFAULT_HASH_SEED_ALT;\n }\n\n return oldStyleKey !== _p.styleKey;\n};\n\nstyfn.clearStyleHints = function (ele) {\n var _p = ele._private;\n _p.styleKeys = {};\n _p.styleKey = null;\n _p.labelKey = null;\n _p.labelStyleKey = null;\n _p.sourceLabelKey = null;\n _p.sourceLabelStyleKey = null;\n _p.targetLabelKey = null;\n _p.targetLabelStyleKey = null;\n _p.nodeKey = null;\n _p.hasPie = null;\n}; // apply a property to the style (for internal use)\n// returns whether application was successful\n//\n// now, this function flattens the property, and here's how:\n//\n// for parsedProp:{ bypass: true, deleteBypass: true }\n// no property is generated, instead the bypass property in the\n// element's style is replaced by what's pointed to by the `bypassed`\n// field in the bypass property (i.e. restoring the property the\n// bypass was overriding)\n//\n// for parsedProp:{ mapped: truthy }\n// the generated flattenedProp:{ mapping: prop }\n//\n// for parsedProp:{ bypass: true }\n// the generated flattenedProp:{ bypassed: parsedProp }\n\n\nstyfn.applyParsedProperty = function (ele, parsedProp) {\n var self = this;\n var prop = parsedProp;\n var style = ele._private.style;\n var flatProp;\n var types = self.types;\n var type = self.properties[prop.name].type;\n var propIsBypass = prop.bypass;\n var origProp = style[prop.name];\n var origPropIsBypass = origProp && origProp.bypass;\n var _p = ele._private;\n var flatPropMapping = 'mapping';\n\n var getVal = function getVal(p) {\n if (p == null) {\n return null;\n } else if (p.pfValue != null) {\n return p.pfValue;\n } else {\n return p.value;\n }\n };\n\n var checkTriggers = function checkTriggers() {\n var fromVal = getVal(origProp);\n var toVal = getVal(prop);\n self.checkTriggers(ele, prop.name, fromVal, toVal);\n }; // edge sanity checks to prevent the client from making serious mistakes\n\n\n if (parsedProp.name === 'curve-style' && ele.isEdge() && ( // loops must be bundled beziers\n parsedProp.value !== 'bezier' && ele.isLoop() || // edges connected to compound nodes can not be haystacks\n parsedProp.value === 'haystack' && (ele.source().isParent() || ele.target().isParent()))) {\n prop = parsedProp = this.parse(parsedProp.name, 'bezier', propIsBypass);\n }\n\n if (prop[\"delete\"]) {\n // delete the property and use the default value on falsey value\n style[prop.name] = undefined;\n checkTriggers();\n return true;\n }\n\n if (prop.deleteBypassed) {\n // delete the property that the\n if (!origProp) {\n checkTriggers();\n return true; // can't delete if no prop\n } else if (origProp.bypass) {\n // delete bypassed\n origProp.bypassed = undefined;\n checkTriggers();\n return true;\n } else {\n return false; // we're unsuccessful deleting the bypassed\n }\n } // check if we need to delete the current bypass\n\n\n if (prop.deleteBypass) {\n // then this property is just here to indicate we need to delete\n if (!origProp) {\n checkTriggers();\n return true; // property is already not defined\n } else if (origProp.bypass) {\n // then replace the bypass property with the original\n // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary)\n style[prop.name] = origProp.bypassed;\n checkTriggers();\n return true;\n } else {\n return false; // we're unsuccessful deleting the bypass\n }\n }\n\n var printMappingErr = function printMappingErr() {\n warn('Do not assign mappings to elements without corresponding data (i.e. ele `' + ele.id() + '` has no mapping for property `' + prop.name + '` with data field `' + prop.field + '`); try a `[' + prop.field + ']` selector to limit scope to elements with `' + prop.field + '` defined');\n }; // put the property in the style objects\n\n\n switch (prop.mapped) {\n // flatten the property if mapped\n case types.mapData:\n {\n // flatten the field (e.g. data.foo.bar)\n var fields = prop.field.split('.');\n var fieldVal = _p.data;\n\n for (var i = 0; i < fields.length && fieldVal; i++) {\n var field = fields[i];\n fieldVal = fieldVal[field];\n }\n\n if (fieldVal == null) {\n printMappingErr();\n return false;\n }\n\n var percent;\n\n if (!number(fieldVal)) {\n // then don't apply and fall back on the existing style\n warn('Do not use continuous mappers without specifying numeric data (i.e. `' + prop.field + ': ' + fieldVal + '` for `' + ele.id() + '` is non-numeric)');\n return false;\n } else {\n var fieldWidth = prop.fieldMax - prop.fieldMin;\n\n if (fieldWidth === 0) {\n // safety check -- not strictly necessary as no props of zero range should be passed here\n percent = 0;\n } else {\n percent = (fieldVal - prop.fieldMin) / fieldWidth;\n }\n } // make sure to bound percent value\n\n\n if (percent < 0) {\n percent = 0;\n } else if (percent > 1) {\n percent = 1;\n }\n\n if (type.color) {\n var r1 = prop.valueMin[0];\n var r2 = prop.valueMax[0];\n var g1 = prop.valueMin[1];\n var g2 = prop.valueMax[1];\n var b1 = prop.valueMin[2];\n var b2 = prop.valueMax[2];\n var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3];\n var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3];\n var clr = [Math.round(r1 + (r2 - r1) * percent), Math.round(g1 + (g2 - g1) * percent), Math.round(b1 + (b2 - b1) * percent), Math.round(a1 + (a2 - a1) * percent)];\n flatProp = {\n // colours are simple, so just create the flat property instead of expensive string parsing\n bypass: prop.bypass,\n // we're a bypass if the mapping property is a bypass\n name: prop.name,\n value: clr,\n strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')'\n };\n } else if (type.number) {\n var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent;\n flatProp = this.parse(prop.name, calcValue, prop.bypass, flatPropMapping);\n } else {\n return false; // can only map to colours and numbers\n }\n\n if (!flatProp) {\n // if we can't flatten the property, then don't apply the property and fall back on the existing style\n printMappingErr();\n return false;\n }\n\n flatProp.mapping = prop; // keep a reference to the mapping\n\n prop = flatProp; // the flattened (mapped) property is the one we want\n\n break;\n }\n // direct mapping\n\n case types.data:\n {\n // flatten the field (e.g. data.foo.bar)\n var _fields = prop.field.split('.');\n\n var _fieldVal = _p.data;\n\n for (var _i4 = 0; _i4 < _fields.length && _fieldVal; _i4++) {\n var _field = _fields[_i4];\n _fieldVal = _fieldVal[_field];\n }\n\n if (_fieldVal != null) {\n flatProp = this.parse(prop.name, _fieldVal, prop.bypass, flatPropMapping);\n }\n\n if (!flatProp) {\n // if we can't flatten the property, then don't apply and fall back on the existing style\n printMappingErr();\n return false;\n }\n\n flatProp.mapping = prop; // keep a reference to the mapping\n\n prop = flatProp; // the flattened (mapped) property is the one we want\n\n break;\n }\n\n case types.fn:\n {\n var fn = prop.value;\n var fnRetVal = prop.fnValue != null ? prop.fnValue : fn(ele); // check for cached value before calling function\n\n prop.prevFnValue = fnRetVal;\n\n if (fnRetVal == null) {\n warn('Custom function mappers may not return null (i.e. `' + prop.name + '` for ele `' + ele.id() + '` is null)');\n return false;\n }\n\n flatProp = this.parse(prop.name, fnRetVal, prop.bypass, flatPropMapping);\n\n if (!flatProp) {\n warn('Custom function mappers may not return invalid values for the property type (i.e. `' + prop.name + '` for ele `' + ele.id() + '` is invalid)');\n return false;\n }\n\n flatProp.mapping = copy(prop); // keep a reference to the mapping\n\n prop = flatProp; // the flattened (mapped) property is the one we want\n\n break;\n }\n\n case undefined:\n break;\n // just set the property\n\n default:\n return false;\n // not a valid mapping\n } // if the property is a bypass property, then link the resultant property to the original one\n\n\n if (propIsBypass) {\n if (origPropIsBypass) {\n // then this bypass overrides the existing one\n prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass\n } else {\n // then link the orig prop to the new bypass\n prop.bypassed = origProp;\n }\n\n style[prop.name] = prop; // and set\n } else {\n // prop is not bypass\n if (origPropIsBypass) {\n // then keep the orig prop (since it's a bypass) and link to the new prop\n origProp.bypassed = prop;\n } else {\n // then just replace the old prop with the new one\n style[prop.name] = prop;\n }\n }\n\n checkTriggers();\n return true;\n};\n\nstyfn.cleanElements = function (eles, keepBypasses) {\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n this.clearStyleHints(ele);\n ele.dirtyCompoundBoundsCache();\n ele.dirtyBoundingBoxCache();\n\n if (!keepBypasses) {\n ele._private.style = {};\n } else {\n var style = ele._private.style;\n var propNames = Object.keys(style);\n\n for (var j = 0; j < propNames.length; j++) {\n var propName = propNames[j];\n var eleProp = style[propName];\n\n if (eleProp != null) {\n if (eleProp.bypass) {\n eleProp.bypassed = null;\n } else {\n style[propName] = null;\n }\n }\n }\n }\n }\n}; // updates the visual style for all elements (useful for manual style modification after init)\n\n\nstyfn.update = function () {\n var cy = this._private.cy;\n var eles = cy.mutableElements();\n eles.updateStyle();\n}; // diffProps : { name => { prev, next } }\n\n\nstyfn.updateTransitions = function (ele, diffProps) {\n var self = this;\n var _p = ele._private;\n var props = ele.pstyle('transition-property').value;\n var duration = ele.pstyle('transition-duration').pfValue;\n var delay = ele.pstyle('transition-delay').pfValue;\n\n if (props.length > 0 && duration > 0) {\n var style = {}; // build up the style to animate towards\n\n var anyPrev = false;\n\n for (var i = 0; i < props.length; i++) {\n var prop = props[i];\n var styProp = ele.pstyle(prop);\n var diffProp = diffProps[prop];\n\n if (!diffProp) {\n continue;\n }\n\n var prevProp = diffProp.prev;\n var fromProp = prevProp;\n var toProp = diffProp.next != null ? diffProp.next : styProp;\n var diff = false;\n var initVal = void 0;\n var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity)\n\n if (!fromProp) {\n continue;\n } // consider px values\n\n\n if (number(fromProp.pfValue) && number(toProp.pfValue)) {\n diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy\n\n initVal = fromProp.pfValue + initDt * diff; // consider numerical values\n } else if (number(fromProp.value) && number(toProp.value)) {\n diff = toProp.value - fromProp.value; // nonzero is truthy\n\n initVal = fromProp.value + initDt * diff; // consider colour values\n } else if (array(fromProp.value) && array(toProp.value)) {\n diff = fromProp.value[0] !== toProp.value[0] || fromProp.value[1] !== toProp.value[1] || fromProp.value[2] !== toProp.value[2];\n initVal = fromProp.strValue;\n } // the previous value is good for an animation only if it's different\n\n\n if (diff) {\n style[prop] = toProp.strValue; // to val\n\n this.applyBypass(ele, prop, initVal); // from val\n\n anyPrev = true;\n }\n } // end if props allow ani\n // can't transition if there's nothing previous to transition from\n\n\n if (!anyPrev) {\n return;\n }\n\n _p.transitioning = true;\n new Promise$1(function (resolve) {\n if (delay > 0) {\n ele.delayAnimation(delay).play().promise().then(resolve);\n } else {\n resolve();\n }\n }).then(function () {\n return ele.animation({\n style: style,\n duration: duration,\n easing: ele.pstyle('transition-timing-function').value,\n queue: false\n }).play().promise();\n }).then(function () {\n // if( !isBypass ){\n self.removeBypasses(ele, props);\n ele.emitAndNotify('style'); // }\n\n _p.transitioning = false;\n });\n } else if (_p.transitioning) {\n this.removeBypasses(ele, props);\n ele.emitAndNotify('style');\n _p.transitioning = false;\n }\n};\n\nstyfn.checkTrigger = function (ele, name, fromValue, toValue, getTrigger, onTrigger) {\n var prop = this.properties[name];\n var triggerCheck = getTrigger(prop);\n\n if (triggerCheck != null && triggerCheck(fromValue, toValue)) {\n onTrigger(prop);\n }\n};\n\nstyfn.checkZOrderTrigger = function (ele, name, fromValue, toValue) {\n var _this = this;\n\n this.checkTrigger(ele, name, fromValue, toValue, function (prop) {\n return prop.triggersZOrder;\n }, function () {\n _this._private.cy.notify('zorder', ele);\n });\n};\n\nstyfn.checkBoundsTrigger = function (ele, name, fromValue, toValue) {\n this.checkTrigger(ele, name, fromValue, toValue, function (prop) {\n return prop.triggersBounds;\n }, function (prop) {\n ele.dirtyCompoundBoundsCache();\n ele.dirtyBoundingBoxCache(); // if the prop change makes the bb of pll bezier edges invalid,\n // then dirty the pll edge bb cache as well\n\n if ( // only for beziers -- so performance of other edges isn't affected\n (ele.pstyle('curve-style').value === 'bezier' // already a bezier\n // was just now changed to or from a bezier:\n || name === 'curve-style' && (fromValue === 'bezier' || toValue === 'bezier')) && prop.triggersBoundsOfParallelBeziers) {\n ele.parallelEdges().forEach(function (pllEdge) {\n if (pllEdge.isBundledBezier()) {\n pllEdge.dirtyBoundingBoxCache();\n }\n });\n }\n });\n};\n\nstyfn.checkTriggers = function (ele, name, fromValue, toValue) {\n ele.dirtyStyleCache();\n this.checkZOrderTrigger(ele, name, fromValue, toValue);\n this.checkBoundsTrigger(ele, name, fromValue, toValue);\n};\n\nvar styfn$1 = {}; // bypasses are applied to an existing style on an element, and just tacked on temporarily\n// returns true iff application was successful for at least 1 specified property\n\nstyfn$1.applyBypass = function (eles, name, value, updateTransitions) {\n var self = this;\n var props = [];\n var isBypass = true; // put all the properties (can specify one or many) in an array after parsing them\n\n if (name === '*' || name === '**') {\n // apply to all property names\n if (value !== undefined) {\n for (var i = 0; i < self.properties.length; i++) {\n var prop = self.properties[i];\n var _name = prop.name;\n var parsedProp = this.parse(_name, value, true);\n\n if (parsedProp) {\n props.push(parsedProp);\n }\n }\n }\n } else if (string(name)) {\n // then parse the single property\n var _parsedProp = this.parse(name, value, true);\n\n if (_parsedProp) {\n props.push(_parsedProp);\n }\n } else if (plainObject(name)) {\n // then parse each property\n var specifiedProps = name;\n updateTransitions = value;\n var names = Object.keys(specifiedProps);\n\n for (var _i = 0; _i < names.length; _i++) {\n var _name2 = names[_i];\n var _value = specifiedProps[_name2];\n\n if (_value === undefined) {\n // try camel case name too\n _value = specifiedProps[dash2camel(_name2)];\n }\n\n if (_value !== undefined) {\n var _parsedProp2 = this.parse(_name2, _value, true);\n\n if (_parsedProp2) {\n props.push(_parsedProp2);\n }\n }\n }\n } else {\n // can't do anything without well defined properties\n return false;\n } // we've failed if there are no valid properties\n\n\n if (props.length === 0) {\n return false;\n } // now, apply the bypass properties on the elements\n\n\n var ret = false; // return true if at least one succesful bypass applied\n\n for (var _i2 = 0; _i2 < eles.length; _i2++) {\n // for each ele\n var ele = eles[_i2];\n var diffProps = {};\n var diffProp = void 0;\n\n for (var j = 0; j < props.length; j++) {\n // for each prop\n var _prop = props[j];\n\n if (updateTransitions) {\n var prevProp = ele.pstyle(_prop.name);\n diffProp = diffProps[_prop.name] = {\n prev: prevProp\n };\n }\n\n ret = this.applyParsedProperty(ele, _prop) || ret;\n\n if (updateTransitions) {\n diffProp.next = ele.pstyle(_prop.name);\n }\n } // for props\n\n\n if (ret) {\n this.updateStyleHints(ele);\n }\n\n if (updateTransitions) {\n this.updateTransitions(ele, diffProps, isBypass);\n }\n } // for eles\n\n\n return ret;\n}; // only useful in specific cases like animation\n\n\nstyfn$1.overrideBypass = function (eles, name, value) {\n name = camel2dash(name);\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var prop = ele._private.style[name];\n var type = this.properties[name].type;\n var isColor = type.color;\n var isMulti = type.mutiple;\n var oldValue = !prop ? null : prop.pfValue != null ? prop.pfValue : prop.value;\n\n if (!prop || !prop.bypass) {\n // need a bypass if one doesn't exist\n this.applyBypass(ele, name, value);\n } else {\n prop.value = value;\n\n if (prop.pfValue != null) {\n prop.pfValue = value;\n }\n\n if (isColor) {\n prop.strValue = 'rgb(' + value.join(',') + ')';\n } else if (isMulti) {\n prop.strValue = value.join(' ');\n } else {\n prop.strValue = '' + value;\n }\n\n this.updateStyleHints(ele);\n }\n\n this.checkTriggers(ele, name, oldValue, value);\n }\n};\n\nstyfn$1.removeAllBypasses = function (eles, updateTransitions) {\n return this.removeBypasses(eles, this.propertyNames, updateTransitions);\n};\n\nstyfn$1.removeBypasses = function (eles, props, updateTransitions) {\n var isBypass = true;\n\n for (var j = 0; j < eles.length; j++) {\n var ele = eles[j];\n var diffProps = {};\n\n for (var i = 0; i < props.length; i++) {\n var name = props[i];\n var prop = this.properties[name];\n var prevProp = ele.pstyle(prop.name);\n\n if (!prevProp || !prevProp.bypass) {\n // if a bypass doesn't exist for the prop, nothing needs to be removed\n continue;\n }\n\n var value = ''; // empty => remove bypass\n\n var parsedProp = this.parse(name, value, true);\n var diffProp = diffProps[prop.name] = {\n prev: prevProp\n };\n this.applyParsedProperty(ele, parsedProp);\n diffProp.next = ele.pstyle(prop.name);\n } // for props\n\n\n this.updateStyleHints(ele);\n\n if (updateTransitions) {\n this.updateTransitions(ele, diffProps, isBypass);\n }\n } // for eles\n\n};\n\nvar styfn$2 = {}; // gets what an em size corresponds to in pixels relative to a dom element\n\nstyfn$2.getEmSizeInPixels = function () {\n var px = this.containerCss('font-size');\n\n if (px != null) {\n return parseFloat(px);\n } else {\n return 1; // for headless\n }\n}; // gets css property from the core container\n\n\nstyfn$2.containerCss = function (propName) {\n var cy = this._private.cy;\n var domElement = cy.container();\n\n if (window$1 && domElement && window$1.getComputedStyle) {\n return window$1.getComputedStyle(domElement).getPropertyValue(propName);\n }\n};\n\nvar styfn$3 = {}; // gets the rendered style for an element\n\nstyfn$3.getRenderedStyle = function (ele, prop) {\n if (prop) {\n return this.getStylePropertyValue(ele, prop, true);\n } else {\n return this.getRawStyle(ele, true);\n }\n}; // gets the raw style for an element\n\n\nstyfn$3.getRawStyle = function (ele, isRenderedVal) {\n var self = this;\n ele = ele[0]; // insure it's an element\n\n if (ele) {\n var rstyle = {};\n\n for (var i = 0; i < self.properties.length; i++) {\n var prop = self.properties[i];\n var val = self.getStylePropertyValue(ele, prop.name, isRenderedVal);\n\n if (val != null) {\n rstyle[prop.name] = val;\n rstyle[dash2camel(prop.name)] = val;\n }\n }\n\n return rstyle;\n }\n};\n\nstyfn$3.getIndexedStyle = function (ele, property, subproperty, index) {\n var pstyle = ele.pstyle(property)[subproperty][index];\n return pstyle != null ? pstyle : ele.cy().style().getDefaultProperty(property)[subproperty][0];\n};\n\nstyfn$3.getStylePropertyValue = function (ele, propName, isRenderedVal) {\n var self = this;\n ele = ele[0]; // insure it's an element\n\n if (ele) {\n var prop = self.properties[propName];\n\n if (prop.alias) {\n prop = prop.pointsTo;\n }\n\n var type = prop.type;\n var styleProp = ele.pstyle(prop.name);\n\n if (styleProp) {\n var value = styleProp.value,\n units = styleProp.units,\n strValue = styleProp.strValue;\n\n if (isRenderedVal && type.number && value != null && number(value)) {\n var zoom = ele.cy().zoom();\n\n var getRenderedValue = function getRenderedValue(val) {\n return val * zoom;\n };\n\n var getValueStringWithUnits = function getValueStringWithUnits(val, units) {\n return getRenderedValue(val) + units;\n };\n\n var isArrayValue = array(value);\n var haveUnits = isArrayValue ? units.every(function (u) {\n return u != null;\n }) : units != null;\n\n if (haveUnits) {\n if (isArrayValue) {\n return value.map(function (v, i) {\n return getValueStringWithUnits(v, units[i]);\n }).join(' ');\n } else {\n return getValueStringWithUnits(value, units);\n }\n } else {\n if (isArrayValue) {\n return value.map(function (v) {\n return string(v) ? v : '' + getRenderedValue(v);\n }).join(' ');\n } else {\n return '' + getRenderedValue(value);\n }\n }\n } else if (strValue != null) {\n return strValue;\n }\n }\n\n return null;\n }\n};\n\nstyfn$3.getAnimationStartStyle = function (ele, aniProps) {\n var rstyle = {};\n\n for (var i = 0; i < aniProps.length; i++) {\n var aniProp = aniProps[i];\n var name = aniProp.name;\n var styleProp = ele.pstyle(name);\n\n if (styleProp !== undefined) {\n // then make a prop of it\n if (plainObject(styleProp)) {\n styleProp = this.parse(name, styleProp.strValue);\n } else {\n styleProp = this.parse(name, styleProp);\n }\n }\n\n if (styleProp) {\n rstyle[name] = styleProp;\n }\n }\n\n return rstyle;\n};\n\nstyfn$3.getPropsList = function (propsObj) {\n var self = this;\n var rstyle = [];\n var style = propsObj;\n var props = self.properties;\n\n if (style) {\n var names = Object.keys(style);\n\n for (var i = 0; i < names.length; i++) {\n var name = names[i];\n var val = style[name];\n var prop = props[name] || props[camel2dash(name)];\n var styleProp = this.parse(prop.name, val);\n\n if (styleProp) {\n rstyle.push(styleProp);\n }\n }\n }\n\n return rstyle;\n};\n\nstyfn$3.getNonDefaultPropertiesHash = function (ele, propNames, seed) {\n var hash = seed.slice();\n var name, val, strVal, chVal;\n var i, j;\n\n for (i = 0; i < propNames.length; i++) {\n name = propNames[i];\n val = ele.pstyle(name, false);\n\n if (val == null) {\n continue;\n } else if (val.pfValue != null) {\n hash[0] = hashInt(chVal, hash[0]);\n hash[1] = hashIntAlt(chVal, hash[1]);\n } else {\n strVal = val.strValue;\n\n for (j = 0; j < strVal.length; j++) {\n chVal = strVal.charCodeAt(j);\n hash[0] = hashInt(chVal, hash[0]);\n hash[1] = hashIntAlt(chVal, hash[1]);\n }\n }\n }\n\n return hash;\n};\n\nstyfn$3.getPropertiesHash = styfn$3.getNonDefaultPropertiesHash;\n\nvar styfn$4 = {};\n\nstyfn$4.appendFromJson = function (json) {\n var style = this;\n\n for (var i = 0; i < json.length; i++) {\n var context = json[i];\n var selector = context.selector;\n var props = context.style || context.css;\n var names = Object.keys(props);\n style.selector(selector); // apply selector\n\n for (var j = 0; j < names.length; j++) {\n var name = names[j];\n var value = props[name];\n style.css(name, value); // apply property\n }\n }\n\n return style;\n}; // accessible cy.style() function\n\n\nstyfn$4.fromJson = function (json) {\n var style = this;\n style.resetToDefault();\n style.appendFromJson(json);\n return style;\n}; // get json from cy.style() api\n\n\nstyfn$4.json = function () {\n var json = [];\n\n for (var i = this.defaultLength; i < this.length; i++) {\n var cxt = this[i];\n var selector = cxt.selector;\n var props = cxt.properties;\n var css = {};\n\n for (var j = 0; j < props.length; j++) {\n var prop = props[j];\n css[prop.name] = prop.strValue;\n }\n\n json.push({\n selector: !selector ? 'core' : selector.toString(),\n style: css\n });\n }\n\n return json;\n};\n\nvar styfn$5 = {};\n\nstyfn$5.appendFromString = function (string) {\n var self = this;\n var style = this;\n var remaining = '' + string;\n var selAndBlockStr;\n var blockRem;\n var propAndValStr; // remove comments from the style string\n\n remaining = remaining.replace(/[/][*](\\s|.)+?[*][/]/g, '');\n\n function removeSelAndBlockFromRemaining() {\n // remove the parsed selector and block from the remaining text to parse\n if (remaining.length > selAndBlockStr.length) {\n remaining = remaining.substr(selAndBlockStr.length);\n } else {\n remaining = '';\n }\n }\n\n function removePropAndValFromRem() {\n // remove the parsed property and value from the remaining block text to parse\n if (blockRem.length > propAndValStr.length) {\n blockRem = blockRem.substr(propAndValStr.length);\n } else {\n blockRem = '';\n }\n }\n\n for (;;) {\n var nothingLeftToParse = remaining.match(/^\\s*$/);\n\n if (nothingLeftToParse) {\n break;\n }\n\n var selAndBlock = remaining.match(/^\\s*((?:.|\\s)+?)\\s*\\{((?:.|\\s)+?)\\}/);\n\n if (!selAndBlock) {\n warn('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);\n break;\n }\n\n selAndBlockStr = selAndBlock[0]; // parse the selector\n\n var selectorStr = selAndBlock[1];\n\n if (selectorStr !== 'core') {\n var selector = new Selector(selectorStr);\n\n if (selector.invalid) {\n warn('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr); // skip this selector and block\n\n removeSelAndBlockFromRemaining();\n continue;\n }\n } // parse the block of properties and values\n\n\n var blockStr = selAndBlock[2];\n var invalidBlock = false;\n blockRem = blockStr;\n var props = [];\n\n for (;;) {\n var _nothingLeftToParse = blockRem.match(/^\\s*$/);\n\n if (_nothingLeftToParse) {\n break;\n }\n\n var propAndVal = blockRem.match(/^\\s*(.+?)\\s*:\\s*(.+?)\\s*;/);\n\n if (!propAndVal) {\n warn('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);\n invalidBlock = true;\n break;\n }\n\n propAndValStr = propAndVal[0];\n var propStr = propAndVal[1];\n var valStr = propAndVal[2];\n var prop = self.properties[propStr];\n\n if (!prop) {\n warn('Skipping property: Invalid property name in: ' + propAndValStr); // skip this property in the block\n\n removePropAndValFromRem();\n continue;\n }\n\n var parsedProp = style.parse(propStr, valStr);\n\n if (!parsedProp) {\n warn('Skipping property: Invalid property definition in: ' + propAndValStr); // skip this property in the block\n\n removePropAndValFromRem();\n continue;\n }\n\n props.push({\n name: propStr,\n val: valStr\n });\n removePropAndValFromRem();\n }\n\n if (invalidBlock) {\n removeSelAndBlockFromRemaining();\n break;\n } // put the parsed block in the style\n\n\n style.selector(selectorStr);\n\n for (var i = 0; i < props.length; i++) {\n var _prop = props[i];\n style.css(_prop.name, _prop.val);\n }\n\n removeSelAndBlockFromRemaining();\n }\n\n return style;\n};\n\nstyfn$5.fromString = function (string) {\n var style = this;\n style.resetToDefault();\n style.appendFromString(string);\n return style;\n};\n\nvar styfn$6 = {};\n\n(function () {\n var number = number$1;\n var rgba = rgbaNoBackRefs;\n var hsla = hslaNoBackRefs;\n var hex3$1 = hex3;\n var hex6$1 = hex6;\n\n var data = function data(prefix) {\n return '^' + prefix + '\\\\s*\\\\(\\\\s*([\\\\w\\\\.]+)\\\\s*\\\\)$';\n };\n\n var mapData = function mapData(prefix) {\n var mapArg = number + '|\\\\w+|' + rgba + '|' + hsla + '|' + hex3$1 + '|' + hex6$1;\n return '^' + prefix + '\\\\s*\\\\(([\\\\w\\\\.]+)\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + mapArg + ')\\\\s*\\\\,\\\\s*(' + mapArg + ')\\\\)$';\n };\n\n var urlRegexes = ['^url\\\\s*\\\\(\\\\s*[\\'\"]?(.+?)[\\'\"]?\\\\s*\\\\)$', '^(none)$', '^(.+)$']; // each visual style property has a type and needs to be validated according to it\n\n styfn$6.types = {\n time: {\n number: true,\n min: 0,\n units: 's|ms',\n implicitUnits: 'ms'\n },\n percent: {\n number: true,\n min: 0,\n max: 100,\n units: '%',\n implicitUnits: '%'\n },\n percentages: {\n number: true,\n min: 0,\n max: 100,\n units: '%',\n implicitUnits: '%',\n multiple: true\n },\n zeroOneNumber: {\n number: true,\n min: 0,\n max: 1,\n unitless: true\n },\n zeroOneNumbers: {\n number: true,\n min: 0,\n max: 1,\n unitless: true,\n multiple: true\n },\n nOneOneNumber: {\n number: true,\n min: -1,\n max: 1,\n unitless: true\n },\n nonNegativeInt: {\n number: true,\n min: 0,\n integer: true,\n unitless: true\n },\n position: {\n enums: ['parent', 'origin']\n },\n nodeSize: {\n number: true,\n min: 0,\n enums: ['label']\n },\n number: {\n number: true,\n unitless: true\n },\n numbers: {\n number: true,\n unitless: true,\n multiple: true\n },\n positiveNumber: {\n number: true,\n unitless: true,\n min: 0,\n strictMin: true\n },\n size: {\n number: true,\n min: 0\n },\n bidirectionalSize: {\n number: true\n },\n // allows negative\n bidirectionalSizeMaybePercent: {\n number: true,\n allowPercent: true\n },\n // allows negative\n bidirectionalSizes: {\n number: true,\n multiple: true\n },\n // allows negative\n sizeMaybePercent: {\n number: true,\n min: 0,\n allowPercent: true\n },\n axisDirection: {\n enums: ['horizontal', 'leftward', 'rightward', 'vertical', 'upward', 'downward', 'auto']\n },\n paddingRelativeTo: {\n enums: ['width', 'height', 'average', 'min', 'max']\n },\n bgWH: {\n number: true,\n min: 0,\n allowPercent: true,\n enums: ['auto'],\n multiple: true\n },\n bgPos: {\n number: true,\n allowPercent: true,\n multiple: true\n },\n bgRelativeTo: {\n enums: ['inner', 'include-padding'],\n multiple: true\n },\n bgRepeat: {\n enums: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'],\n multiple: true\n },\n bgFit: {\n enums: ['none', 'contain', 'cover'],\n multiple: true\n },\n bgCrossOrigin: {\n enums: ['anonymous', 'use-credentials'],\n multiple: true\n },\n bgClip: {\n enums: ['none', 'node'],\n multiple: true\n },\n color: {\n color: true\n },\n colors: {\n color: true,\n multiple: true\n },\n fill: {\n enums: ['solid', 'linear-gradient', 'radial-gradient']\n },\n bool: {\n enums: ['yes', 'no']\n },\n lineStyle: {\n enums: ['solid', 'dotted', 'dashed']\n },\n lineCap: {\n enums: ['butt', 'round', 'square']\n },\n borderStyle: {\n enums: ['solid', 'dotted', 'dashed', 'double']\n },\n curveStyle: {\n enums: ['bezier', 'unbundled-bezier', 'haystack', 'segments', 'straight', 'taxi']\n },\n fontFamily: {\n regex: '^([\\\\w- \\\\\"]+(?:\\\\s*,\\\\s*[\\\\w- \\\\\"]+)*)$'\n },\n fontStyle: {\n enums: ['italic', 'normal', 'oblique']\n },\n fontWeight: {\n enums: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900]\n },\n textDecoration: {\n enums: ['none', 'underline', 'overline', 'line-through']\n },\n textTransform: {\n enums: ['none', 'uppercase', 'lowercase']\n },\n textWrap: {\n enums: ['none', 'wrap', 'ellipsis']\n },\n textOverflowWrap: {\n enums: ['whitespace', 'anywhere']\n },\n textBackgroundShape: {\n enums: ['rectangle', 'roundrectangle', 'round-rectangle']\n },\n nodeShape: {\n enums: ['rectangle', 'roundrectangle', 'round-rectangle', 'cutrectangle', 'cut-rectangle', 'bottomroundrectangle', 'bottom-round-rectangle', 'barrel', 'ellipse', 'triangle', 'round-triangle', 'square', 'pentagon', 'round-pentagon', 'hexagon', 'round-hexagon', 'concavehexagon', 'concave-hexagon', 'heptagon', 'round-heptagon', 'octagon', 'round-octagon', 'tag', 'round-tag', 'star', 'diamond', 'round-diamond', 'vee', 'rhomboid', 'polygon']\n },\n compoundIncludeLabels: {\n enums: ['include', 'exclude']\n },\n arrowShape: {\n enums: ['tee', 'triangle', 'triangle-tee', 'circle-triangle', 'triangle-cross', 'triangle-backcurve', 'vee', 'square', 'circle', 'diamond', 'chevron', 'none']\n },\n arrowFill: {\n enums: ['filled', 'hollow']\n },\n display: {\n enums: ['element', 'none']\n },\n visibility: {\n enums: ['hidden', 'visible']\n },\n zCompoundDepth: {\n enums: ['bottom', 'orphan', 'auto', 'top']\n },\n zIndexCompare: {\n enums: ['auto', 'manual']\n },\n valign: {\n enums: ['top', 'center', 'bottom']\n },\n halign: {\n enums: ['left', 'center', 'right']\n },\n justification: {\n enums: ['left', 'center', 'right', 'auto']\n },\n text: {\n string: true\n },\n data: {\n mapping: true,\n regex: data('data')\n },\n layoutData: {\n mapping: true,\n regex: data('layoutData')\n },\n scratch: {\n mapping: true,\n regex: data('scratch')\n },\n mapData: {\n mapping: true,\n regex: mapData('mapData')\n },\n mapLayoutData: {\n mapping: true,\n regex: mapData('mapLayoutData')\n },\n mapScratch: {\n mapping: true,\n regex: mapData('mapScratch')\n },\n fn: {\n mapping: true,\n fn: true\n },\n url: {\n regexes: urlRegexes,\n singleRegexMatchValue: true\n },\n urls: {\n regexes: urlRegexes,\n singleRegexMatchValue: true,\n multiple: true\n },\n propList: {\n propList: true\n },\n angle: {\n number: true,\n units: 'deg|rad',\n implicitUnits: 'rad'\n },\n textRotation: {\n number: true,\n units: 'deg|rad',\n implicitUnits: 'rad',\n enums: ['none', 'autorotate']\n },\n polygonPointList: {\n number: true,\n multiple: true,\n evenMultiple: true,\n min: -1,\n max: 1,\n unitless: true\n },\n edgeDistances: {\n enums: ['intersection', 'node-position']\n },\n edgeEndpoint: {\n number: true,\n multiple: true,\n units: '%|px|em|deg|rad',\n implicitUnits: 'px',\n enums: ['inside-to-node', 'outside-to-node', 'outside-to-node-or-label', 'outside-to-line', 'outside-to-line-or-label'],\n singleEnum: true,\n validate: function validate(valArr, unitsArr) {\n switch (valArr.length) {\n case 2:\n // can be % or px only\n return unitsArr[0] !== 'deg' && unitsArr[0] !== 'rad' && unitsArr[1] !== 'deg' && unitsArr[1] !== 'rad';\n\n case 1:\n // can be enum, deg, or rad only\n return string(valArr[0]) || unitsArr[0] === 'deg' || unitsArr[0] === 'rad';\n\n default:\n return false;\n }\n }\n },\n easing: {\n regexes: ['^(spring)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$', '^(cubic-bezier)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$'],\n enums: ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine', 'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad', 'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic', 'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart', 'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint', 'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo', 'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ']\n },\n gradientDirection: {\n enums: ['to-bottom', 'to-top', 'to-left', 'to-right', 'to-bottom-right', 'to-bottom-left', 'to-top-right', 'to-top-left', 'to-right-bottom', 'to-left-bottom', 'to-right-top', 'to-left-top']\n },\n boundsExpansion: {\n number: true,\n multiple: true,\n min: 0,\n validate: function validate(valArr) {\n var length = valArr.length;\n return length === 1 || length === 2 || length === 4;\n }\n }\n };\n var diff = {\n zeroNonZero: function zeroNonZero(val1, val2) {\n if ((val1 == null || val2 == null) && val1 !== val2) {\n return true; // null cases could represent any value\n }\n\n if (val1 == 0 && val2 != 0) {\n return true;\n } else if (val1 != 0 && val2 == 0) {\n return true;\n } else {\n return false;\n }\n },\n any: function any(val1, val2) {\n return val1 != val2;\n },\n emptyNonEmpty: function emptyNonEmpty(str1, str2) {\n var empty1 = emptyString(str1);\n var empty2 = emptyString(str2);\n return empty1 && !empty2 || !empty1 && empty2;\n }\n }; // define visual style properties\n //\n // - n.b. adding a new group of props may require updates to updateStyleHints()\n // - adding new props to an existing group gets handled automatically\n\n var t = styfn$6.types;\n var mainLabel = [{\n name: 'label',\n type: t.text,\n triggersBounds: diff.any,\n triggersZOrder: diff.emptyNonEmpty\n }, {\n name: 'text-rotation',\n type: t.textRotation,\n triggersBounds: diff.any\n }, {\n name: 'text-margin-x',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }, {\n name: 'text-margin-y',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }];\n var sourceLabel = [{\n name: 'source-label',\n type: t.text,\n triggersBounds: diff.any\n }, {\n name: 'source-text-rotation',\n type: t.textRotation,\n triggersBounds: diff.any\n }, {\n name: 'source-text-margin-x',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }, {\n name: 'source-text-margin-y',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }, {\n name: 'source-text-offset',\n type: t.size,\n triggersBounds: diff.any\n }];\n var targetLabel = [{\n name: 'target-label',\n type: t.text,\n triggersBounds: diff.any\n }, {\n name: 'target-text-rotation',\n type: t.textRotation,\n triggersBounds: diff.any\n }, {\n name: 'target-text-margin-x',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }, {\n name: 'target-text-margin-y',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }, {\n name: 'target-text-offset',\n type: t.size,\n triggersBounds: diff.any\n }];\n var labelDimensions = [{\n name: 'font-family',\n type: t.fontFamily,\n triggersBounds: diff.any\n }, {\n name: 'font-style',\n type: t.fontStyle,\n triggersBounds: diff.any\n }, {\n name: 'font-weight',\n type: t.fontWeight,\n triggersBounds: diff.any\n }, {\n name: 'font-size',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'text-transform',\n type: t.textTransform,\n triggersBounds: diff.any\n }, {\n name: 'text-wrap',\n type: t.textWrap,\n triggersBounds: diff.any\n }, {\n name: 'text-overflow-wrap',\n type: t.textOverflowWrap,\n triggersBounds: diff.any\n }, {\n name: 'text-max-width',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'text-outline-width',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'line-height',\n type: t.positiveNumber,\n triggersBounds: diff.any\n }];\n var commonLabel = [{\n name: 'text-valign',\n type: t.valign,\n triggersBounds: diff.any\n }, {\n name: 'text-halign',\n type: t.halign,\n triggersBounds: diff.any\n }, {\n name: 'color',\n type: t.color\n }, {\n name: 'text-outline-color',\n type: t.color\n }, {\n name: 'text-outline-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'text-background-color',\n type: t.color\n }, {\n name: 'text-background-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'text-background-padding',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'text-border-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'text-border-color',\n type: t.color\n }, {\n name: 'text-border-width',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'text-border-style',\n type: t.borderStyle,\n triggersBounds: diff.any\n }, {\n name: 'text-background-shape',\n type: t.textBackgroundShape,\n triggersBounds: diff.any\n }, {\n name: 'text-justification',\n type: t.justification\n }];\n var behavior = [{\n name: 'events',\n type: t.bool\n }, {\n name: 'text-events',\n type: t.bool\n }];\n var visibility = [{\n name: 'display',\n type: t.display,\n triggersZOrder: diff.any,\n triggersBounds: diff.any,\n triggersBoundsOfParallelBeziers: true\n }, {\n name: 'visibility',\n type: t.visibility,\n triggersZOrder: diff.any\n }, {\n name: 'opacity',\n type: t.zeroOneNumber,\n triggersZOrder: diff.zeroNonZero\n }, {\n name: 'text-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'min-zoomed-font-size',\n type: t.size\n }, {\n name: 'z-compound-depth',\n type: t.zCompoundDepth,\n triggersZOrder: diff.any\n }, {\n name: 'z-index-compare',\n type: t.zIndexCompare,\n triggersZOrder: diff.any\n }, {\n name: 'z-index',\n type: t.nonNegativeInt,\n triggersZOrder: diff.any\n }];\n var overlay = [{\n name: 'overlay-padding',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'overlay-color',\n type: t.color\n }, {\n name: 'overlay-opacity',\n type: t.zeroOneNumber,\n triggersBounds: diff.zeroNonZero\n }];\n var transition = [{\n name: 'transition-property',\n type: t.propList\n }, {\n name: 'transition-duration',\n type: t.time\n }, {\n name: 'transition-delay',\n type: t.time\n }, {\n name: 'transition-timing-function',\n type: t.easing\n }];\n\n var nodeSizeHashOverride = function nodeSizeHashOverride(ele, parsedProp) {\n if (parsedProp.value === 'label') {\n return -ele.poolIndex(); // no hash key hits is using label size (hitrate for perf probably low anyway)\n } else {\n return parsedProp.pfValue;\n }\n };\n\n var nodeBody = [{\n name: 'height',\n type: t.nodeSize,\n triggersBounds: diff.any,\n hashOverride: nodeSizeHashOverride\n }, {\n name: 'width',\n type: t.nodeSize,\n triggersBounds: diff.any,\n hashOverride: nodeSizeHashOverride\n }, {\n name: 'shape',\n type: t.nodeShape,\n triggersBounds: diff.any\n }, {\n name: 'shape-polygon-points',\n type: t.polygonPointList,\n triggersBounds: diff.any\n }, {\n name: 'background-color',\n type: t.color\n }, {\n name: 'background-fill',\n type: t.fill\n }, {\n name: 'background-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'background-blacken',\n type: t.nOneOneNumber\n }, {\n name: 'background-gradient-stop-colors',\n type: t.colors\n }, {\n name: 'background-gradient-stop-positions',\n type: t.percentages\n }, {\n name: 'background-gradient-direction',\n type: t.gradientDirection\n }, {\n name: 'padding',\n type: t.sizeMaybePercent,\n triggersBounds: diff.any\n }, {\n name: 'padding-relative-to',\n type: t.paddingRelativeTo,\n triggersBounds: diff.any\n }, {\n name: 'bounds-expansion',\n type: t.boundsExpansion,\n triggersBounds: diff.any\n }];\n var nodeBorder = [{\n name: 'border-color',\n type: t.color\n }, {\n name: 'border-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'border-width',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'border-style',\n type: t.borderStyle\n }];\n var backgroundImage = [{\n name: 'background-image',\n type: t.urls\n }, {\n name: 'background-image-crossorigin',\n type: t.bgCrossOrigin\n }, {\n name: 'background-image-opacity',\n type: t.zeroOneNumbers\n }, {\n name: 'background-position-x',\n type: t.bgPos\n }, {\n name: 'background-position-y',\n type: t.bgPos\n }, {\n name: 'background-width-relative-to',\n type: t.bgRelativeTo\n }, {\n name: 'background-height-relative-to',\n type: t.bgRelativeTo\n }, {\n name: 'background-repeat',\n type: t.bgRepeat\n }, {\n name: 'background-fit',\n type: t.bgFit\n }, {\n name: 'background-clip',\n type: t.bgClip\n }, {\n name: 'background-width',\n type: t.bgWH\n }, {\n name: 'background-height',\n type: t.bgWH\n }, {\n name: 'background-offset-x',\n type: t.bgPos\n }, {\n name: 'background-offset-y',\n type: t.bgPos\n }];\n var compound = [{\n name: 'position',\n type: t.position,\n triggersBounds: diff.any\n }, {\n name: 'compound-sizing-wrt-labels',\n type: t.compoundIncludeLabels,\n triggersBounds: diff.any\n }, {\n name: 'min-width',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'min-width-bias-left',\n type: t.sizeMaybePercent,\n triggersBounds: diff.any\n }, {\n name: 'min-width-bias-right',\n type: t.sizeMaybePercent,\n triggersBounds: diff.any\n }, {\n name: 'min-height',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'min-height-bias-top',\n type: t.sizeMaybePercent,\n triggersBounds: diff.any\n }, {\n name: 'min-height-bias-bottom',\n type: t.sizeMaybePercent,\n triggersBounds: diff.any\n }];\n var edgeLine = [{\n name: 'line-style',\n type: t.lineStyle\n }, {\n name: 'line-color',\n type: t.color\n }, {\n name: 'line-fill',\n type: t.fill\n }, {\n name: 'line-cap',\n type: t.lineCap\n }, {\n name: 'line-dash-pattern',\n type: t.numbers\n }, {\n name: 'line-dash-offset',\n type: t.number\n }, {\n name: 'line-gradient-stop-colors',\n type: t.colors\n }, {\n name: 'line-gradient-stop-positions',\n type: t.percentages\n }, {\n name: 'curve-style',\n type: t.curveStyle,\n triggersBounds: diff.any,\n triggersBoundsOfParallelBeziers: true\n }, {\n name: 'haystack-radius',\n type: t.zeroOneNumber,\n triggersBounds: diff.any\n }, {\n name: 'source-endpoint',\n type: t.edgeEndpoint,\n triggersBounds: diff.any\n }, {\n name: 'target-endpoint',\n type: t.edgeEndpoint,\n triggersBounds: diff.any\n }, {\n name: 'control-point-step-size',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'control-point-distances',\n type: t.bidirectionalSizes,\n triggersBounds: diff.any\n }, {\n name: 'control-point-weights',\n type: t.numbers,\n triggersBounds: diff.any\n }, {\n name: 'segment-distances',\n type: t.bidirectionalSizes,\n triggersBounds: diff.any\n }, {\n name: 'segment-weights',\n type: t.numbers,\n triggersBounds: diff.any\n }, {\n name: 'taxi-turn',\n type: t.bidirectionalSizeMaybePercent,\n triggersBounds: diff.any\n }, {\n name: 'taxi-turn-min-distance',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'taxi-direction',\n type: t.axisDirection,\n triggersBounds: diff.any\n }, {\n name: 'edge-distances',\n type: t.edgeDistances,\n triggersBounds: diff.any\n }, {\n name: 'arrow-scale',\n type: t.positiveNumber,\n triggersBounds: diff.any\n }, {\n name: 'loop-direction',\n type: t.angle,\n triggersBounds: diff.any\n }, {\n name: 'loop-sweep',\n type: t.angle,\n triggersBounds: diff.any\n }, {\n name: 'source-distance-from-node',\n type: t.size,\n triggersBounds: diff.any\n }, {\n name: 'target-distance-from-node',\n type: t.size,\n triggersBounds: diff.any\n }];\n var ghost = [{\n name: 'ghost',\n type: t.bool,\n triggersBounds: diff.any\n }, {\n name: 'ghost-offset-x',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }, {\n name: 'ghost-offset-y',\n type: t.bidirectionalSize,\n triggersBounds: diff.any\n }, {\n name: 'ghost-opacity',\n type: t.zeroOneNumber\n }];\n var core = [{\n name: 'selection-box-color',\n type: t.color\n }, {\n name: 'selection-box-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'selection-box-border-color',\n type: t.color\n }, {\n name: 'selection-box-border-width',\n type: t.size\n }, {\n name: 'active-bg-color',\n type: t.color\n }, {\n name: 'active-bg-opacity',\n type: t.zeroOneNumber\n }, {\n name: 'active-bg-size',\n type: t.size\n }, {\n name: 'outside-texture-bg-color',\n type: t.color\n }, {\n name: 'outside-texture-bg-opacity',\n type: t.zeroOneNumber\n }]; // pie backgrounds for nodes\n\n var pie = [];\n styfn$6.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use)\n\n pie.push({\n name: 'pie-size',\n type: t.sizeMaybePercent\n });\n\n for (var i = 1; i <= styfn$6.pieBackgroundN; i++) {\n pie.push({\n name: 'pie-' + i + '-background-color',\n type: t.color\n });\n pie.push({\n name: 'pie-' + i + '-background-size',\n type: t.percent\n });\n pie.push({\n name: 'pie-' + i + '-background-opacity',\n type: t.zeroOneNumber\n });\n } // edge arrows\n\n\n var edgeArrow = [];\n var arrowPrefixes = styfn$6.arrowPrefixes = ['source', 'mid-source', 'target', 'mid-target'];\n [{\n name: 'arrow-shape',\n type: t.arrowShape,\n triggersBounds: diff.any\n }, {\n name: 'arrow-color',\n type: t.color\n }, {\n name: 'arrow-fill',\n type: t.arrowFill\n }].forEach(function (prop) {\n arrowPrefixes.forEach(function (prefix) {\n var name = prefix + '-' + prop.name;\n var type = prop.type,\n triggersBounds = prop.triggersBounds;\n edgeArrow.push({\n name: name,\n type: type,\n triggersBounds: triggersBounds\n });\n });\n }, {});\n var props = styfn$6.properties = [].concat(behavior, transition, visibility, overlay, ghost, commonLabel, labelDimensions, mainLabel, sourceLabel, targetLabel, nodeBody, nodeBorder, backgroundImage, pie, compound, edgeLine, edgeArrow, core);\n var propGroups = styfn$6.propertyGroups = {\n // common to all eles\n behavior: behavior,\n transition: transition,\n visibility: visibility,\n overlay: overlay,\n ghost: ghost,\n // labels\n commonLabel: commonLabel,\n labelDimensions: labelDimensions,\n mainLabel: mainLabel,\n sourceLabel: sourceLabel,\n targetLabel: targetLabel,\n // node props\n nodeBody: nodeBody,\n nodeBorder: nodeBorder,\n backgroundImage: backgroundImage,\n pie: pie,\n compound: compound,\n // edge props\n edgeLine: edgeLine,\n edgeArrow: edgeArrow,\n core: core\n };\n var propGroupNames = styfn$6.propertyGroupNames = {};\n var propGroupKeys = styfn$6.propertyGroupKeys = Object.keys(propGroups);\n propGroupKeys.forEach(function (key) {\n propGroupNames[key] = propGroups[key].map(function (prop) {\n return prop.name;\n });\n propGroups[key].forEach(function (prop) {\n return prop.groupKey = key;\n });\n }); // define aliases\n\n var aliases = styfn$6.aliases = [{\n name: 'content',\n pointsTo: 'label'\n }, {\n name: 'control-point-distance',\n pointsTo: 'control-point-distances'\n }, {\n name: 'control-point-weight',\n pointsTo: 'control-point-weights'\n }, {\n name: 'edge-text-rotation',\n pointsTo: 'text-rotation'\n }, {\n name: 'padding-left',\n pointsTo: 'padding'\n }, {\n name: 'padding-right',\n pointsTo: 'padding'\n }, {\n name: 'padding-top',\n pointsTo: 'padding'\n }, {\n name: 'padding-bottom',\n pointsTo: 'padding'\n }]; // list of property names\n\n styfn$6.propertyNames = props.map(function (p) {\n return p.name;\n }); // allow access of properties by name ( e.g. style.properties.height )\n\n for (var _i = 0; _i < props.length; _i++) {\n var prop = props[_i];\n props[prop.name] = prop; // allow lookup by name\n } // map aliases\n\n\n for (var _i2 = 0; _i2 < aliases.length; _i2++) {\n var alias = aliases[_i2];\n var pointsToProp = props[alias.pointsTo];\n var aliasProp = {\n name: alias.name,\n alias: true,\n pointsTo: pointsToProp\n }; // add alias prop for parsing\n\n props.push(aliasProp);\n props[alias.name] = aliasProp; // allow lookup by name\n }\n})();\n\nstyfn$6.getDefaultProperty = function (name) {\n return this.getDefaultProperties()[name];\n};\n\nstyfn$6.getDefaultProperties = function () {\n var _p = this._private;\n\n if (_p.defaultProperties != null) {\n return _p.defaultProperties;\n }\n\n var rawProps = extend({\n // core props\n 'selection-box-color': '#ddd',\n 'selection-box-opacity': 0.65,\n 'selection-box-border-color': '#aaa',\n 'selection-box-border-width': 1,\n 'active-bg-color': 'black',\n 'active-bg-opacity': 0.15,\n 'active-bg-size': 30,\n 'outside-texture-bg-color': '#000',\n 'outside-texture-bg-opacity': 0.125,\n // common node/edge props\n 'events': 'yes',\n 'text-events': 'no',\n 'text-valign': 'top',\n 'text-halign': 'center',\n 'text-justification': 'auto',\n 'line-height': 1,\n 'color': '#000',\n 'text-outline-color': '#000',\n 'text-outline-width': 0,\n 'text-outline-opacity': 1,\n 'text-opacity': 1,\n 'text-decoration': 'none',\n 'text-transform': 'none',\n 'text-wrap': 'none',\n 'text-overflow-wrap': 'whitespace',\n 'text-max-width': 9999,\n 'text-background-color': '#000',\n 'text-background-opacity': 0,\n 'text-background-shape': 'rectangle',\n 'text-background-padding': 0,\n 'text-border-opacity': 0,\n 'text-border-width': 0,\n 'text-border-style': 'solid',\n 'text-border-color': '#000',\n 'font-family': 'Helvetica Neue, Helvetica, sans-serif',\n 'font-style': 'normal',\n 'font-weight': 'normal',\n 'font-size': 16,\n 'min-zoomed-font-size': 0,\n 'text-rotation': 'none',\n 'source-text-rotation': 'none',\n 'target-text-rotation': 'none',\n 'visibility': 'visible',\n 'display': 'element',\n 'opacity': 1,\n 'z-compound-depth': 'auto',\n 'z-index-compare': 'auto',\n 'z-index': 0,\n 'label': '',\n 'text-margin-x': 0,\n 'text-margin-y': 0,\n 'source-label': '',\n 'source-text-offset': 0,\n 'source-text-margin-x': 0,\n 'source-text-margin-y': 0,\n 'target-label': '',\n 'target-text-offset': 0,\n 'target-text-margin-x': 0,\n 'target-text-margin-y': 0,\n 'overlay-opacity': 0,\n 'overlay-color': '#000',\n 'overlay-padding': 10,\n 'transition-property': 'none',\n 'transition-duration': 0,\n 'transition-delay': 0,\n 'transition-timing-function': 'linear',\n // node props\n 'background-blacken': 0,\n 'background-color': '#999',\n 'background-fill': 'solid',\n 'background-opacity': 1,\n 'background-image': 'none',\n 'background-image-crossorigin': 'anonymous',\n 'background-image-opacity': 1,\n 'background-position-x': '50%',\n 'background-position-y': '50%',\n 'background-offset-x': 0,\n 'background-offset-y': 0,\n 'background-width-relative-to': 'include-padding',\n 'background-height-relative-to': 'include-padding',\n 'background-repeat': 'no-repeat',\n 'background-fit': 'none',\n 'background-clip': 'node',\n 'background-width': 'auto',\n 'background-height': 'auto',\n 'border-color': '#000',\n 'border-opacity': 1,\n 'border-width': 0,\n 'border-style': 'solid',\n 'height': 30,\n 'width': 30,\n 'shape': 'ellipse',\n 'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1',\n 'bounds-expansion': 0,\n // node gradient\n 'background-gradient-direction': 'to-bottom',\n 'background-gradient-stop-colors': '#999',\n 'background-gradient-stop-positions': '0%',\n // ghost props\n 'ghost': 'no',\n 'ghost-offset-y': 0,\n 'ghost-offset-x': 0,\n 'ghost-opacity': 0,\n // compound props\n 'padding': 0,\n 'padding-relative-to': 'width',\n 'position': 'origin',\n 'compound-sizing-wrt-labels': 'include',\n 'min-width': 0,\n 'min-width-bias-left': 0,\n 'min-width-bias-right': 0,\n 'min-height': 0,\n 'min-height-bias-top': 0,\n 'min-height-bias-bottom': 0\n }, {\n // node pie bg\n 'pie-size': '100%'\n }, [{\n name: 'pie-{{i}}-background-color',\n value: 'black'\n }, {\n name: 'pie-{{i}}-background-size',\n value: '0%'\n }, {\n name: 'pie-{{i}}-background-opacity',\n value: 1\n }].reduce(function (css, prop) {\n for (var i = 1; i <= styfn$6.pieBackgroundN; i++) {\n var name = prop.name.replace('{{i}}', i);\n var val = prop.value;\n css[name] = val;\n }\n\n return css;\n }, {}), {\n // edge props\n 'line-style': 'solid',\n 'line-color': '#999',\n 'line-fill': 'solid',\n 'line-cap': 'butt',\n 'line-gradient-stop-colors': '#999',\n 'line-gradient-stop-positions': '0%',\n 'control-point-step-size': 40,\n 'control-point-weights': 0.5,\n 'segment-weights': 0.5,\n 'segment-distances': 20,\n 'taxi-turn': '50%',\n 'taxi-turn-min-distance': 10,\n 'taxi-direction': 'auto',\n 'edge-distances': 'intersection',\n 'curve-style': 'haystack',\n 'haystack-radius': 0,\n 'arrow-scale': 1,\n 'loop-direction': '-45deg',\n 'loop-sweep': '-90deg',\n 'source-distance-from-node': 0,\n 'target-distance-from-node': 0,\n 'source-endpoint': 'outside-to-node',\n 'target-endpoint': 'outside-to-node',\n 'line-dash-pattern': [6, 3],\n 'line-dash-offset': 0\n }, [{\n name: 'arrow-shape',\n value: 'none'\n }, {\n name: 'arrow-color',\n value: '#999'\n }, {\n name: 'arrow-fill',\n value: 'filled'\n }].reduce(function (css, prop) {\n styfn$6.arrowPrefixes.forEach(function (prefix) {\n var name = prefix + '-' + prop.name;\n var val = prop.value;\n css[name] = val;\n });\n return css;\n }, {}));\n var parsedProps = {};\n\n for (var i = 0; i < this.properties.length; i++) {\n var prop = this.properties[i];\n\n if (prop.pointsTo) {\n continue;\n }\n\n var name = prop.name;\n var val = rawProps[name];\n var parsedProp = this.parse(name, val);\n parsedProps[name] = parsedProp;\n }\n\n _p.defaultProperties = parsedProps;\n return _p.defaultProperties;\n};\n\nstyfn$6.addDefaultStylesheet = function () {\n this.selector(':parent').css({\n 'shape': 'rectangle',\n 'padding': 10,\n 'background-color': '#eee',\n 'border-color': '#ccc',\n 'border-width': 1\n }).selector('edge').css({\n 'width': 3\n }).selector(':loop').css({\n 'curve-style': 'bezier'\n }).selector('edge:compound').css({\n 'curve-style': 'bezier',\n 'source-endpoint': 'outside-to-line',\n 'target-endpoint': 'outside-to-line'\n }).selector(':selected').css({\n 'background-color': '#0169D9',\n 'line-color': '#0169D9',\n 'source-arrow-color': '#0169D9',\n 'target-arrow-color': '#0169D9',\n 'mid-source-arrow-color': '#0169D9',\n 'mid-target-arrow-color': '#0169D9'\n }).selector(':parent:selected').css({\n 'background-color': '#CCE1F9',\n 'border-color': '#aec8e5'\n }).selector(':active').css({\n 'overlay-color': 'black',\n 'overlay-padding': 10,\n 'overlay-opacity': 0.25\n });\n this.defaultLength = this.length;\n};\n\nvar styfn$7 = {}; // a caching layer for property parsing\n\nstyfn$7.parse = function (name, value, propIsBypass, propIsFlat) {\n var self = this; // function values can't be cached in all cases, and there isn't much benefit of caching them anyway\n\n if (fn(value)) {\n return self.parseImplWarn(name, value, propIsBypass, propIsFlat);\n }\n\n var flatKey = propIsFlat === 'mapping' || propIsFlat === true || propIsFlat === false || propIsFlat == null ? 'dontcare' : propIsFlat;\n var bypassKey = propIsBypass ? 't' : 'f';\n var valueKey = '' + value;\n var argHash = hashStrings(name, valueKey, bypassKey, flatKey);\n var propCache = self.propCache = self.propCache || [];\n var ret;\n\n if (!(ret = propCache[argHash])) {\n ret = propCache[argHash] = self.parseImplWarn(name, value, propIsBypass, propIsFlat);\n } // - bypasses can't be shared b/c the value can be changed by animations or otherwise overridden\n // - mappings can't be shared b/c mappings are per-element\n\n\n if (propIsBypass || propIsFlat === 'mapping') {\n // need a copy since props are mutated later in their lifecycles\n ret = copy(ret);\n\n if (ret) {\n ret.value = copy(ret.value); // because it could be an array, e.g. colour\n }\n }\n\n return ret;\n};\n\nstyfn$7.parseImplWarn = function (name, value, propIsBypass, propIsFlat) {\n var prop = this.parseImpl(name, value, propIsBypass, propIsFlat);\n\n if (!prop && value != null) {\n warn(\"The style property `\".concat(name, \": \").concat(value, \"` is invalid\"));\n }\n\n return prop;\n}; // parse a property; return null on invalid; return parsed property otherwise\n// fields :\n// - name : the name of the property\n// - value : the parsed, native-typed value of the property\n// - strValue : a string value that represents the property value in valid css\n// - bypass : true iff the property is a bypass property\n\n\nstyfn$7.parseImpl = function (name, value, propIsBypass, propIsFlat) {\n var self = this;\n name = camel2dash(name); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName')\n\n var property = self.properties[name];\n var passedValue = value;\n var types = self.types;\n\n if (!property) {\n return null;\n } // return null on property of unknown name\n\n\n if (value === undefined) {\n return null;\n } // can't assign undefined\n // the property may be an alias\n\n\n if (property.alias) {\n property = property.pointsTo;\n name = property.name;\n }\n\n var valueIsString = string(value);\n\n if (valueIsString) {\n // trim the value to make parsing easier\n value = value.trim();\n }\n\n var type = property.type;\n\n if (!type) {\n return null;\n } // no type, no luck\n // check if bypass is null or empty string (i.e. indication to delete bypass property)\n\n\n if (propIsBypass && (value === '' || value === null)) {\n return {\n name: name,\n value: value,\n bypass: true,\n deleteBypass: true\n };\n } // check if value is a function used as a mapper\n\n\n if (fn(value)) {\n return {\n name: name,\n value: value,\n strValue: 'fn',\n mapped: types.fn,\n bypass: propIsBypass\n };\n } // check if value is mapped\n\n\n var data, mapData;\n\n if (!valueIsString || propIsFlat || value.length < 7 || value[1] !== 'a') ; else if (value.length >= 7 && value[0] === 'd' && (data = new RegExp(types.data.regex).exec(value))) {\n if (propIsBypass) {\n return false;\n } // mappers not allowed in bypass\n\n\n var mapped = types.data;\n return {\n name: name,\n value: data,\n strValue: '' + value,\n mapped: mapped,\n field: data[1],\n bypass: propIsBypass\n };\n } else if (value.length >= 10 && value[0] === 'm' && (mapData = new RegExp(types.mapData.regex).exec(value))) {\n if (propIsBypass) {\n return false;\n } // mappers not allowed in bypass\n\n\n if (type.multiple) {\n return false;\n } // impossible to map to num\n\n\n var _mapped = types.mapData; // we can map only if the type is a colour or a number\n\n if (!(type.color || type.number)) {\n return false;\n }\n\n var valueMin = this.parse(name, mapData[4]); // parse to validate\n\n if (!valueMin || valueMin.mapped) {\n return false;\n } // can't be invalid or mapped\n\n\n var valueMax = this.parse(name, mapData[5]); // parse to validate\n\n if (!valueMax || valueMax.mapped) {\n return false;\n } // can't be invalid or mapped\n // check if valueMin and valueMax are the same\n\n\n if (valueMin.pfValue === valueMax.pfValue || valueMin.strValue === valueMax.strValue) {\n warn('`' + name + ': ' + value + '` is not a valid mapper because the output range is zero; converting to `' + name + ': ' + valueMin.strValue + '`');\n return this.parse(name, valueMin.strValue); // can't make much of a mapper without a range\n } else if (type.color) {\n var c1 = valueMin.value;\n var c2 = valueMax.value;\n var same = c1[0] === c2[0] // red\n && c1[1] === c2[1] // green\n && c1[2] === c2[2] // blue\n && ( // optional alpha\n c1[3] === c2[3] // same alpha outright\n || (c1[3] == null || c1[3] === 1) && ( // full opacity for colour 1?\n c2[3] == null || c2[3] === 1) // full opacity for colour 2?\n );\n\n if (same) {\n return false;\n } // can't make a mapper without a range\n\n }\n\n return {\n name: name,\n value: mapData,\n strValue: '' + value,\n mapped: _mapped,\n field: mapData[1],\n fieldMin: parseFloat(mapData[2]),\n // min & max are numeric\n fieldMax: parseFloat(mapData[3]),\n valueMin: valueMin.value,\n valueMax: valueMax.value,\n bypass: propIsBypass\n };\n }\n\n if (type.multiple && propIsFlat !== 'multiple') {\n var vals;\n\n if (valueIsString) {\n vals = value.split(/\\s+/);\n } else if (array(value)) {\n vals = value;\n } else {\n vals = [value];\n }\n\n if (type.evenMultiple && vals.length % 2 !== 0) {\n return null;\n }\n\n var valArr = [];\n var unitsArr = [];\n var pfValArr = [];\n var strVal = '';\n var hasEnum = false;\n\n for (var i = 0; i < vals.length; i++) {\n var p = self.parse(name, vals[i], propIsBypass, 'multiple');\n hasEnum = hasEnum || string(p.value);\n valArr.push(p.value);\n pfValArr.push(p.pfValue != null ? p.pfValue : p.value);\n unitsArr.push(p.units);\n strVal += (i > 0 ? ' ' : '') + p.strValue;\n }\n\n if (type.validate && !type.validate(valArr, unitsArr)) {\n return null;\n }\n\n if (type.singleEnum && hasEnum) {\n if (valArr.length === 1 && string(valArr[0])) {\n return {\n name: name,\n value: valArr[0],\n strValue: valArr[0],\n bypass: propIsBypass\n };\n } else {\n return null;\n }\n }\n\n return {\n name: name,\n value: valArr,\n pfValue: pfValArr,\n strValue: strVal,\n bypass: propIsBypass,\n units: unitsArr\n };\n } // several types also allow enums\n\n\n var checkEnums = function checkEnums() {\n for (var _i = 0; _i < type.enums.length; _i++) {\n var en = type.enums[_i];\n\n if (en === value) {\n return {\n name: name,\n value: value,\n strValue: '' + value,\n bypass: propIsBypass\n };\n }\n }\n\n return null;\n }; // check the type and return the appropriate object\n\n\n if (type.number) {\n var units;\n var implicitUnits = 'px'; // not set => px\n\n if (type.units) {\n // use specified units if set\n units = type.units;\n }\n\n if (type.implicitUnits) {\n implicitUnits = type.implicitUnits;\n }\n\n if (!type.unitless) {\n if (valueIsString) {\n var unitsRegex = 'px|em' + (type.allowPercent ? '|\\\\%' : '');\n\n if (units) {\n unitsRegex = units;\n } // only allow explicit units if so set\n\n\n var match = value.match('^(' + number$1 + ')(' + unitsRegex + ')?' + '$');\n\n if (match) {\n value = match[1];\n units = match[2] || implicitUnits;\n }\n } else if (!units || type.implicitUnits) {\n units = implicitUnits; // implicitly px if unspecified\n }\n }\n\n value = parseFloat(value); // if not a number and enums not allowed, then the value is invalid\n\n if (isNaN(value) && type.enums === undefined) {\n return null;\n } // check if this number type also accepts special keywords in place of numbers\n // (i.e. `left`, `auto`, etc)\n\n\n if (isNaN(value) && type.enums !== undefined) {\n value = passedValue;\n return checkEnums();\n } // check if value must be an integer\n\n\n if (type.integer && !integer(value)) {\n return null;\n } // check value is within range\n\n\n if (type.min !== undefined && (value < type.min || type.strictMin && value === type.min) || type.max !== undefined && (value > type.max || type.strictMax && value === type.max)) {\n return null;\n }\n\n var ret = {\n name: name,\n value: value,\n strValue: '' + value + (units ? units : ''),\n units: units,\n bypass: propIsBypass\n }; // normalise value in pixels\n\n if (type.unitless || units !== 'px' && units !== 'em') {\n ret.pfValue = value;\n } else {\n ret.pfValue = units === 'px' || !units ? value : this.getEmSizeInPixels() * value;\n } // normalise value in ms\n\n\n if (units === 'ms' || units === 's') {\n ret.pfValue = units === 'ms' ? value : 1000 * value;\n } // normalise value in rad\n\n\n if (units === 'deg' || units === 'rad') {\n ret.pfValue = units === 'rad' ? value : deg2rad(value);\n } // normalize value in %\n\n\n if (units === '%') {\n ret.pfValue = value / 100;\n }\n\n return ret;\n } else if (type.propList) {\n var props = [];\n var propsStr = '' + value;\n\n if (propsStr === 'none') ; else {\n // go over each prop\n var propsSplit = propsStr.split(/\\s*,\\s*|\\s+/);\n\n for (var _i2 = 0; _i2 < propsSplit.length; _i2++) {\n var propName = propsSplit[_i2].trim();\n\n if (self.properties[propName]) {\n props.push(propName);\n } else {\n warn('`' + propName + '` is not a valid property name');\n }\n }\n\n if (props.length === 0) {\n return null;\n }\n }\n\n return {\n name: name,\n value: props,\n strValue: props.length === 0 ? 'none' : props.join(' '),\n bypass: propIsBypass\n };\n } else if (type.color) {\n var tuple = color2tuple(value);\n\n if (!tuple) {\n return null;\n }\n\n return {\n name: name,\n value: tuple,\n pfValue: tuple,\n strValue: 'rgb(' + tuple[0] + ',' + tuple[1] + ',' + tuple[2] + ')',\n // n.b. no spaces b/c of multiple support\n bypass: propIsBypass\n };\n } else if (type.regex || type.regexes) {\n // first check enums\n if (type.enums) {\n var enumProp = checkEnums();\n\n if (enumProp) {\n return enumProp;\n }\n }\n\n var regexes = type.regexes ? type.regexes : [type.regex];\n\n for (var _i3 = 0; _i3 < regexes.length; _i3++) {\n var regex = new RegExp(regexes[_i3]); // make a regex from the type string\n\n var m = regex.exec(value);\n\n if (m) {\n // regex matches\n return {\n name: name,\n value: type.singleRegexMatchValue ? m[1] : m,\n strValue: '' + value,\n bypass: propIsBypass\n };\n }\n }\n\n return null; // didn't match any\n } else if (type.string) {\n // just return\n return {\n name: name,\n value: '' + value,\n strValue: '' + value,\n bypass: propIsBypass\n };\n } else if (type.enums) {\n // check enums last because it's a combo type in others\n return checkEnums();\n } else {\n return null; // not a type we can handle\n }\n};\n\nvar Style = function Style(cy) {\n if (!(this instanceof Style)) {\n return new Style(cy);\n }\n\n if (!core(cy)) {\n error('A style must have a core reference');\n return;\n }\n\n this._private = {\n cy: cy,\n coreStyle: {}\n };\n this.length = 0;\n this.resetToDefault();\n};\n\nvar styfn$8 = Style.prototype;\n\nstyfn$8.instanceString = function () {\n return 'style';\n}; // remove all contexts\n\n\nstyfn$8.clear = function () {\n for (var i = 0; i < this.length; i++) {\n this[i] = undefined;\n }\n\n this.length = 0;\n var _p = this._private;\n _p.newStyle = true;\n return this; // chaining\n};\n\nstyfn$8.resetToDefault = function () {\n this.clear();\n this.addDefaultStylesheet();\n return this;\n}; // builds a style object for the 'core' selector\n\n\nstyfn$8.core = function (propName) {\n return this._private.coreStyle[propName] || this.getDefaultProperty(propName);\n}; // create a new context from the specified selector string and switch to that context\n\n\nstyfn$8.selector = function (selectorStr) {\n // 'core' is a special case and does not need a selector\n var selector = selectorStr === 'core' ? null : new Selector(selectorStr);\n var i = this.length++; // new context means new index\n\n this[i] = {\n selector: selector,\n properties: [],\n mappedProperties: [],\n index: i\n };\n return this; // chaining\n}; // add one or many css rules to the current context\n\n\nstyfn$8.css = function () {\n var self = this;\n var args = arguments;\n\n if (args.length === 1) {\n var map = args[0];\n\n for (var i = 0; i < self.properties.length; i++) {\n var prop = self.properties[i];\n var mapVal = map[prop.name];\n\n if (mapVal === undefined) {\n mapVal = map[dash2camel(prop.name)];\n }\n\n if (mapVal !== undefined) {\n this.cssRule(prop.name, mapVal);\n }\n }\n } else if (args.length === 2) {\n this.cssRule(args[0], args[1]);\n } // do nothing if args are invalid\n\n\n return this; // chaining\n};\n\nstyfn$8.style = styfn$8.css; // add a single css rule to the current context\n\nstyfn$8.cssRule = function (name, value) {\n // name-value pair\n var property = this.parse(name, value); // add property to current context if valid\n\n if (property) {\n var i = this.length - 1;\n this[i].properties.push(property);\n this[i].properties[property.name] = property; // allow access by name as well\n\n if (property.name.match(/pie-(\\d+)-background-size/) && property.value) {\n this._private.hasPie = true;\n }\n\n if (property.mapped) {\n this[i].mappedProperties.push(property);\n } // add to core style if necessary\n\n\n var currentSelectorIsCore = !this[i].selector;\n\n if (currentSelectorIsCore) {\n this._private.coreStyle[property.name] = property;\n }\n }\n\n return this; // chaining\n};\n\nstyfn$8.append = function (style) {\n if (stylesheet(style)) {\n style.appendToStyle(this);\n } else if (array(style)) {\n this.appendFromJson(style);\n } else if (string(style)) {\n this.appendFromString(style);\n } // you probably wouldn't want to append a Style, since you'd duplicate the default parts\n\n\n return this;\n}; // static function\n\n\nStyle.fromJson = function (cy, json) {\n var style = new Style(cy);\n style.fromJson(json);\n return style;\n};\n\nStyle.fromString = function (cy, string) {\n return new Style(cy).fromString(string);\n};\n\n[styfn, styfn$1, styfn$2, styfn$3, styfn$4, styfn$5, styfn$6, styfn$7].forEach(function (props) {\n extend(styfn$8, props);\n});\nStyle.types = styfn$8.types;\nStyle.properties = styfn$8.properties;\nStyle.propertyGroups = styfn$8.propertyGroups;\nStyle.propertyGroupNames = styfn$8.propertyGroupNames;\nStyle.propertyGroupKeys = styfn$8.propertyGroupKeys;\n\nvar corefn$7 = {\n style: function style(newStyle) {\n if (newStyle) {\n var s = this.setStyle(newStyle);\n s.update();\n }\n\n return this._private.style;\n },\n setStyle: function setStyle(style) {\n var _p = this._private;\n\n if (stylesheet(style)) {\n _p.style = style.generateStyle(this);\n } else if (array(style)) {\n _p.style = Style.fromJson(this, style);\n } else if (string(style)) {\n _p.style = Style.fromString(this, style);\n } else {\n _p.style = Style(this);\n }\n\n return _p.style;\n }\n};\n\nvar defaultSelectionType = 'single';\nvar corefn$8 = {\n autolock: function autolock(bool) {\n if (bool !== undefined) {\n this._private.autolock = bool ? true : false;\n } else {\n return this._private.autolock;\n }\n\n return this; // chaining\n },\n autoungrabify: function autoungrabify(bool) {\n if (bool !== undefined) {\n this._private.autoungrabify = bool ? true : false;\n } else {\n return this._private.autoungrabify;\n }\n\n return this; // chaining\n },\n autounselectify: function autounselectify(bool) {\n if (bool !== undefined) {\n this._private.autounselectify = bool ? true : false;\n } else {\n return this._private.autounselectify;\n }\n\n return this; // chaining\n },\n selectionType: function selectionType(selType) {\n var _p = this._private;\n\n if (_p.selectionType == null) {\n _p.selectionType = defaultSelectionType;\n }\n\n if (selType !== undefined) {\n if (selType === 'additive' || selType === 'single') {\n _p.selectionType = selType;\n }\n } else {\n return _p.selectionType;\n }\n\n return this;\n },\n panningEnabled: function panningEnabled(bool) {\n if (bool !== undefined) {\n this._private.panningEnabled = bool ? true : false;\n } else {\n return this._private.panningEnabled;\n }\n\n return this; // chaining\n },\n userPanningEnabled: function userPanningEnabled(bool) {\n if (bool !== undefined) {\n this._private.userPanningEnabled = bool ? true : false;\n } else {\n return this._private.userPanningEnabled;\n }\n\n return this; // chaining\n },\n zoomingEnabled: function zoomingEnabled(bool) {\n if (bool !== undefined) {\n this._private.zoomingEnabled = bool ? true : false;\n } else {\n return this._private.zoomingEnabled;\n }\n\n return this; // chaining\n },\n userZoomingEnabled: function userZoomingEnabled(bool) {\n if (bool !== undefined) {\n this._private.userZoomingEnabled = bool ? true : false;\n } else {\n return this._private.userZoomingEnabled;\n }\n\n return this; // chaining\n },\n boxSelectionEnabled: function boxSelectionEnabled(bool) {\n if (bool !== undefined) {\n this._private.boxSelectionEnabled = bool ? true : false;\n } else {\n return this._private.boxSelectionEnabled;\n }\n\n return this; // chaining\n },\n pan: function pan() {\n var args = arguments;\n var pan = this._private.pan;\n var dim, val, dims, x, y;\n\n switch (args.length) {\n case 0:\n // .pan()\n return pan;\n\n case 1:\n if (string(args[0])) {\n // .pan('x')\n dim = args[0];\n return pan[dim];\n } else if (plainObject(args[0])) {\n // .pan({ x: 0, y: 100 })\n if (!this._private.panningEnabled) {\n return this;\n }\n\n dims = args[0];\n x = dims.x;\n y = dims.y;\n\n if (number(x)) {\n pan.x = x;\n }\n\n if (number(y)) {\n pan.y = y;\n }\n\n this.emit('pan viewport');\n }\n\n break;\n\n case 2:\n // .pan('x', 100)\n if (!this._private.panningEnabled) {\n return this;\n }\n\n dim = args[0];\n val = args[1];\n\n if ((dim === 'x' || dim === 'y') && number(val)) {\n pan[dim] = val;\n }\n\n this.emit('pan viewport');\n break;\n // invalid\n }\n\n this.notify('viewport');\n return this; // chaining\n },\n panBy: function panBy(arg0, arg1) {\n var args = arguments;\n var pan = this._private.pan;\n var dim, val, dims, x, y;\n\n if (!this._private.panningEnabled) {\n return this;\n }\n\n switch (args.length) {\n case 1:\n if (plainObject(arg0)) {\n // .panBy({ x: 0, y: 100 })\n dims = args[0];\n x = dims.x;\n y = dims.y;\n\n if (number(x)) {\n pan.x += x;\n }\n\n if (number(y)) {\n pan.y += y;\n }\n\n this.emit('pan viewport');\n }\n\n break;\n\n case 2:\n // .panBy('x', 100)\n dim = arg0;\n val = arg1;\n\n if ((dim === 'x' || dim === 'y') && number(val)) {\n pan[dim] += val;\n }\n\n this.emit('pan viewport');\n break;\n // invalid\n }\n\n this.notify('viewport');\n return this; // chaining\n },\n fit: function fit(elements, padding) {\n var viewportState = this.getFitViewport(elements, padding);\n\n if (viewportState) {\n var _p = this._private;\n _p.zoom = viewportState.zoom;\n _p.pan = viewportState.pan;\n this.emit('pan zoom viewport');\n this.notify('viewport');\n }\n\n return this; // chaining\n },\n getFitViewport: function getFitViewport(elements, padding) {\n if (number(elements) && padding === undefined) {\n // elements is optional\n padding = elements;\n elements = undefined;\n }\n\n if (!this._private.panningEnabled || !this._private.zoomingEnabled) {\n return;\n }\n\n var bb;\n\n if (string(elements)) {\n var sel = elements;\n elements = this.$(sel);\n } else if (boundingBox(elements)) {\n // assume bb\n var bbe = elements;\n bb = {\n x1: bbe.x1,\n y1: bbe.y1,\n x2: bbe.x2,\n y2: bbe.y2\n };\n bb.w = bb.x2 - bb.x1;\n bb.h = bb.y2 - bb.y1;\n } else if (!elementOrCollection(elements)) {\n elements = this.mutableElements();\n }\n\n if (elementOrCollection(elements) && elements.empty()) {\n return;\n } // can't fit to nothing\n\n\n bb = bb || elements.boundingBox();\n var w = this.width();\n var h = this.height();\n var zoom;\n padding = number(padding) ? padding : 0;\n\n if (!isNaN(w) && !isNaN(h) && w > 0 && h > 0 && !isNaN(bb.w) && !isNaN(bb.h) && bb.w > 0 && bb.h > 0) {\n zoom = Math.min((w - 2 * padding) / bb.w, (h - 2 * padding) / bb.h); // crop zoom\n\n zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;\n zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;\n var pan = {\n // now pan to middle\n x: (w - zoom * (bb.x1 + bb.x2)) / 2,\n y: (h - zoom * (bb.y1 + bb.y2)) / 2\n };\n return {\n zoom: zoom,\n pan: pan\n };\n }\n\n return;\n },\n zoomRange: function zoomRange(min, max) {\n var _p = this._private;\n\n if (max == null) {\n var opts = min;\n min = opts.min;\n max = opts.max;\n }\n\n if (number(min) && number(max) && min <= max) {\n _p.minZoom = min;\n _p.maxZoom = max;\n } else if (number(min) && max === undefined && min <= _p.maxZoom) {\n _p.minZoom = min;\n } else if (number(max) && min === undefined && max >= _p.minZoom) {\n _p.maxZoom = max;\n }\n\n return this;\n },\n minZoom: function minZoom(zoom) {\n if (zoom === undefined) {\n return this._private.minZoom;\n } else {\n return this.zoomRange({\n min: zoom\n });\n }\n },\n maxZoom: function maxZoom(zoom) {\n if (zoom === undefined) {\n return this._private.maxZoom;\n } else {\n return this.zoomRange({\n max: zoom\n });\n }\n },\n getZoomedViewport: function getZoomedViewport(params) {\n var _p = this._private;\n var currentPan = _p.pan;\n var currentZoom = _p.zoom;\n var pos; // in rendered px\n\n var zoom;\n var bail = false;\n\n if (!_p.zoomingEnabled) {\n // zooming disabled\n bail = true;\n }\n\n if (number(params)) {\n // then set the zoom\n zoom = params;\n } else if (plainObject(params)) {\n // then zoom about a point\n zoom = params.level;\n\n if (params.position != null) {\n pos = modelToRenderedPosition(params.position, currentZoom, currentPan);\n } else if (params.renderedPosition != null) {\n pos = params.renderedPosition;\n }\n\n if (pos != null && !_p.panningEnabled) {\n // panning disabled\n bail = true;\n }\n } // crop zoom\n\n\n zoom = zoom > _p.maxZoom ? _p.maxZoom : zoom;\n zoom = zoom < _p.minZoom ? _p.minZoom : zoom; // can't zoom with invalid params\n\n if (bail || !number(zoom) || zoom === currentZoom || pos != null && (!number(pos.x) || !number(pos.y))) {\n return null;\n }\n\n if (pos != null) {\n // set zoom about position\n var pan1 = currentPan;\n var zoom1 = currentZoom;\n var zoom2 = zoom;\n var pan2 = {\n x: -zoom2 / zoom1 * (pos.x - pan1.x) + pos.x,\n y: -zoom2 / zoom1 * (pos.y - pan1.y) + pos.y\n };\n return {\n zoomed: true,\n panned: true,\n zoom: zoom2,\n pan: pan2\n };\n } else {\n // just set the zoom\n return {\n zoomed: true,\n panned: false,\n zoom: zoom,\n pan: currentPan\n };\n }\n },\n zoom: function zoom(params) {\n if (params === undefined) {\n // get\n return this._private.zoom;\n } else {\n // set\n var vp = this.getZoomedViewport(params);\n var _p = this._private;\n\n if (vp == null || !vp.zoomed) {\n return this;\n }\n\n _p.zoom = vp.zoom;\n\n if (vp.panned) {\n _p.pan.x = vp.pan.x;\n _p.pan.y = vp.pan.y;\n }\n\n this.emit('zoom' + (vp.panned ? ' pan' : '') + ' viewport');\n this.notify('viewport');\n return this; // chaining\n }\n },\n viewport: function viewport(opts) {\n var _p = this._private;\n var zoomDefd = true;\n var panDefd = true;\n var events = []; // to trigger\n\n var zoomFailed = false;\n var panFailed = false;\n\n if (!opts) {\n return this;\n }\n\n if (!number(opts.zoom)) {\n zoomDefd = false;\n }\n\n if (!plainObject(opts.pan)) {\n panDefd = false;\n }\n\n if (!zoomDefd && !panDefd) {\n return this;\n }\n\n if (zoomDefd) {\n var z = opts.zoom;\n\n if (z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled) {\n zoomFailed = true;\n } else {\n _p.zoom = z;\n events.push('zoom');\n }\n }\n\n if (panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled) {\n var p = opts.pan;\n\n if (number(p.x)) {\n _p.pan.x = p.x;\n panFailed = false;\n }\n\n if (number(p.y)) {\n _p.pan.y = p.y;\n panFailed = false;\n }\n\n if (!panFailed) {\n events.push('pan');\n }\n }\n\n if (events.length > 0) {\n events.push('viewport');\n this.emit(events.join(' '));\n this.notify('viewport');\n }\n\n return this; // chaining\n },\n center: function center(elements) {\n var pan = this.getCenterPan(elements);\n\n if (pan) {\n this._private.pan = pan;\n this.emit('pan viewport');\n this.notify('viewport');\n }\n\n return this; // chaining\n },\n getCenterPan: function getCenterPan(elements, zoom) {\n if (!this._private.panningEnabled) {\n return;\n }\n\n if (string(elements)) {\n var selector = elements;\n elements = this.mutableElements().filter(selector);\n } else if (!elementOrCollection(elements)) {\n elements = this.mutableElements();\n }\n\n if (elements.length === 0) {\n return;\n } // can't centre pan to nothing\n\n\n var bb = elements.boundingBox();\n var w = this.width();\n var h = this.height();\n zoom = zoom === undefined ? this._private.zoom : zoom;\n var pan = {\n // middle\n x: (w - zoom * (bb.x1 + bb.x2)) / 2,\n y: (h - zoom * (bb.y1 + bb.y2)) / 2\n };\n return pan;\n },\n reset: function reset() {\n if (!this._private.panningEnabled || !this._private.zoomingEnabled) {\n return this;\n }\n\n this.viewport({\n pan: {\n x: 0,\n y: 0\n },\n zoom: 1\n });\n return this; // chaining\n },\n invalidateSize: function invalidateSize() {\n this._private.sizeCache = null;\n },\n size: function size() {\n var _p = this._private;\n var container = _p.container;\n return _p.sizeCache = _p.sizeCache || (container ? function () {\n var style = window$1.getComputedStyle(container);\n\n var val = function val(name) {\n return parseFloat(style.getPropertyValue(name));\n };\n\n return {\n width: container.clientWidth - val('padding-left') - val('padding-right'),\n height: container.clientHeight - val('padding-top') - val('padding-bottom')\n };\n }() : {\n // fallback if no container (not 0 b/c can be used for dividing etc)\n width: 1,\n height: 1\n });\n },\n width: function width() {\n return this.size().width;\n },\n height: function height() {\n return this.size().height;\n },\n extent: function extent() {\n var pan = this._private.pan;\n var zoom = this._private.zoom;\n var rb = this.renderedExtent();\n var b = {\n x1: (rb.x1 - pan.x) / zoom,\n x2: (rb.x2 - pan.x) / zoom,\n y1: (rb.y1 - pan.y) / zoom,\n y2: (rb.y2 - pan.y) / zoom\n };\n b.w = b.x2 - b.x1;\n b.h = b.y2 - b.y1;\n return b;\n },\n renderedExtent: function renderedExtent() {\n var width = this.width();\n var height = this.height();\n return {\n x1: 0,\n y1: 0,\n x2: width,\n y2: height,\n w: width,\n h: height\n };\n }\n}; // aliases\n\ncorefn$8.centre = corefn$8.center; // backwards compatibility\n\ncorefn$8.autolockNodes = corefn$8.autolock;\ncorefn$8.autoungrabifyNodes = corefn$8.autoungrabify;\n\nvar fn$6 = {\n data: define$3.data({\n field: 'data',\n bindingEvent: 'data',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'data',\n settingTriggersEvent: true,\n triggerFnName: 'trigger',\n allowGetting: true\n }),\n removeData: define$3.removeData({\n field: 'data',\n event: 'data',\n triggerFnName: 'trigger',\n triggerEvent: true\n }),\n scratch: define$3.data({\n field: 'scratch',\n bindingEvent: 'scratch',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'scratch',\n settingTriggersEvent: true,\n triggerFnName: 'trigger',\n allowGetting: true\n }),\n removeScratch: define$3.removeData({\n field: 'scratch',\n event: 'scratch',\n triggerFnName: 'trigger',\n triggerEvent: true\n })\n}; // aliases\n\nfn$6.attr = fn$6.data;\nfn$6.removeAttr = fn$6.removeData;\n\nvar Core = function Core(opts) {\n var cy = this;\n opts = extend({}, opts);\n var container = opts.container; // allow for passing a wrapped jquery object\n // e.g. cytoscape({ container: $('#cy') })\n\n if (container && !htmlElement(container) && htmlElement(container[0])) {\n container = container[0];\n }\n\n var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery\n\n reg = reg || {};\n\n if (reg && reg.cy) {\n reg.cy.destroy();\n reg = {}; // old instance => replace reg completely\n }\n\n var readies = reg.readies = reg.readies || [];\n\n if (container) {\n container._cyreg = reg;\n } // make sure container assoc'd reg points to this cy\n\n\n reg.cy = cy;\n var head = window$1 !== undefined && container !== undefined && !opts.headless;\n var options = opts;\n options.layout = extend({\n name: head ? 'grid' : 'null'\n }, options.layout);\n options.renderer = extend({\n name: head ? 'canvas' : 'null'\n }, options.renderer);\n\n var defVal = function defVal(def, val, altVal) {\n if (val !== undefined) {\n return val;\n } else if (altVal !== undefined) {\n return altVal;\n } else {\n return def;\n }\n };\n\n var _p = this._private = {\n container: container,\n // html dom ele container\n ready: false,\n // whether ready has been triggered\n options: options,\n // cached options\n elements: new Collection(this),\n // elements in the graph\n listeners: [],\n // list of listeners\n aniEles: new Collection(this),\n // elements being animated\n data: {},\n // data for the core\n scratch: {},\n // scratch object for core\n layout: null,\n renderer: null,\n destroyed: false,\n // whether destroy was called\n notificationsEnabled: true,\n // whether notifications are sent to the renderer\n minZoom: 1e-50,\n maxZoom: 1e50,\n zoomingEnabled: defVal(true, options.zoomingEnabled),\n userZoomingEnabled: defVal(true, options.userZoomingEnabled),\n panningEnabled: defVal(true, options.panningEnabled),\n userPanningEnabled: defVal(true, options.userPanningEnabled),\n boxSelectionEnabled: defVal(true, options.boxSelectionEnabled),\n autolock: defVal(false, options.autolock, options.autolockNodes),\n autoungrabify: defVal(false, options.autoungrabify, options.autoungrabifyNodes),\n autounselectify: defVal(false, options.autounselectify),\n styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,\n zoom: number(options.zoom) ? options.zoom : 1,\n pan: {\n x: plainObject(options.pan) && number(options.pan.x) ? options.pan.x : 0,\n y: plainObject(options.pan) && number(options.pan.y) ? options.pan.y : 0\n },\n animation: {\n // object for currently-running animations\n current: [],\n queue: []\n },\n hasCompoundNodes: false\n };\n\n this.createEmitter(); // set selection type\n\n this.selectionType(options.selectionType); // init zoom bounds\n\n this.zoomRange({\n min: options.minZoom,\n max: options.maxZoom\n });\n\n var loadExtData = function loadExtData(extData, next) {\n var anyIsPromise = extData.some(promise);\n\n if (anyIsPromise) {\n return Promise$1.all(extData).then(next); // load all data asynchronously, then exec rest of init\n } else {\n next(extData); // exec synchronously for convenience\n }\n }; // start with the default stylesheet so we have something before loading an external stylesheet\n\n\n if (_p.styleEnabled) {\n cy.setStyle([]);\n } // create the renderer\n\n\n var rendererOptions = extend({}, options, options.renderer); // allow rendering hints in top level options\n\n cy.initRenderer(rendererOptions);\n\n var setElesAndLayout = function setElesAndLayout(elements, onload, ondone) {\n cy.notifications(false); // remove old elements\n\n var oldEles = cy.mutableElements();\n\n if (oldEles.length > 0) {\n oldEles.remove();\n }\n\n if (elements != null) {\n if (plainObject(elements) || array(elements)) {\n cy.add(elements);\n }\n }\n\n cy.one('layoutready', function (e) {\n cy.notifications(true);\n cy.emit(e); // we missed this event by turning notifications off, so pass it on\n\n cy.one('load', onload);\n cy.emitAndNotify('load');\n }).one('layoutstop', function () {\n cy.one('done', ondone);\n cy.emit('done');\n });\n var layoutOpts = extend({}, cy._private.options.layout);\n layoutOpts.eles = cy.elements();\n cy.layout(layoutOpts).run();\n };\n\n loadExtData([options.style, options.elements], function (thens) {\n var initStyle = thens[0];\n var initEles = thens[1]; // init style\n\n if (_p.styleEnabled) {\n cy.style().append(initStyle);\n } // initial load\n\n\n setElesAndLayout(initEles, function () {\n // onready\n cy.startAnimationLoop();\n _p.ready = true; // if a ready callback is specified as an option, the bind it\n\n if (fn(options.ready)) {\n cy.on('ready', options.ready);\n } // bind all the ready handlers registered before creating this instance\n\n\n for (var i = 0; i < readies.length; i++) {\n var fn$1 = readies[i];\n cy.on('ready', fn$1);\n }\n\n if (reg) {\n reg.readies = [];\n } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc\n\n\n cy.emit('ready');\n }, options.done);\n });\n};\n\nvar corefn$9 = Core.prototype; // short alias\n\nextend(corefn$9, {\n instanceString: function instanceString() {\n return 'core';\n },\n isReady: function isReady() {\n return this._private.ready;\n },\n destroyed: function destroyed() {\n return this._private.destroyed;\n },\n ready: function ready(fn) {\n if (this.isReady()) {\n this.emitter().emit('ready', [], fn); // just calls fn as though triggered via ready event\n } else {\n this.on('ready', fn);\n }\n\n return this;\n },\n destroy: function destroy() {\n var cy = this;\n if (cy.destroyed()) return;\n cy.stopAnimationLoop();\n cy.destroyRenderer();\n this.emit('destroy');\n cy._private.destroyed = true;\n return cy;\n },\n hasElementWithId: function hasElementWithId(id) {\n return this._private.elements.hasElementWithId(id);\n },\n getElementById: function getElementById(id) {\n return this._private.elements.getElementById(id);\n },\n hasCompoundNodes: function hasCompoundNodes() {\n return this._private.hasCompoundNodes;\n },\n headless: function headless() {\n return this._private.renderer.isHeadless();\n },\n styleEnabled: function styleEnabled() {\n return this._private.styleEnabled;\n },\n addToPool: function addToPool(eles) {\n this._private.elements.merge(eles);\n\n return this; // chaining\n },\n removeFromPool: function removeFromPool(eles) {\n this._private.elements.unmerge(eles);\n\n return this;\n },\n container: function container() {\n return this._private.container || null;\n },\n mount: function mount(container) {\n if (container == null) {\n return;\n }\n\n var cy = this;\n var _p = cy._private;\n var options = _p.options;\n\n if (!htmlElement(container) && htmlElement(container[0])) {\n container = container[0];\n }\n\n cy.stopAnimationLoop();\n cy.destroyRenderer();\n _p.container = container;\n _p.styleEnabled = true;\n cy.invalidateSize();\n cy.initRenderer(extend({}, options, options.renderer, {\n // allow custom renderer name to be re-used, otherwise use canvas\n name: options.renderer.name === 'null' ? 'canvas' : options.renderer.name\n }));\n cy.startAnimationLoop();\n cy.style(options.style);\n cy.emit('mount');\n return cy;\n },\n unmount: function unmount() {\n var cy = this;\n cy.stopAnimationLoop();\n cy.destroyRenderer();\n cy.initRenderer({\n name: 'null'\n });\n cy.emit('unmount');\n return cy;\n },\n options: function options() {\n return copy(this._private.options);\n },\n json: function json(obj) {\n var cy = this;\n var _p = cy._private;\n var eles = cy.mutableElements();\n\n var getFreshRef = function getFreshRef(ele) {\n return cy.getElementById(ele.id());\n };\n\n if (plainObject(obj)) {\n // set\n cy.startBatch();\n\n if (obj.elements) {\n var idInJson = {};\n\n var updateEles = function updateEles(jsons, gr) {\n var toAdd = [];\n var toMod = [];\n\n for (var i = 0; i < jsons.length; i++) {\n var json = jsons[i];\n var id = '' + json.data.id; // id must be string\n\n var ele = cy.getElementById(id);\n idInJson[id] = true;\n\n if (ele.length !== 0) {\n // existing element should be updated\n toMod.push({\n ele: ele,\n json: json\n });\n } else {\n // otherwise should be added\n if (gr) {\n json.group = gr;\n toAdd.push(json);\n } else {\n toAdd.push(json);\n }\n }\n }\n\n cy.add(toAdd);\n\n for (var _i = 0; _i < toMod.length; _i++) {\n var _toMod$_i = toMod[_i],\n _ele = _toMod$_i.ele,\n _json = _toMod$_i.json;\n\n _ele.json(_json);\n }\n };\n\n if (array(obj.elements)) {\n // elements: []\n updateEles(obj.elements);\n } else {\n // elements: { nodes: [], edges: [] }\n var grs = ['nodes', 'edges'];\n\n for (var i = 0; i < grs.length; i++) {\n var gr = grs[i];\n var elements = obj.elements[gr];\n\n if (array(elements)) {\n updateEles(elements, gr);\n }\n }\n }\n\n var parentsToRemove = cy.collection();\n eles.filter(function (ele) {\n return !idInJson[ele.id()];\n }).forEach(function (ele) {\n if (ele.isParent()) {\n parentsToRemove.merge(ele);\n } else {\n ele.remove();\n }\n }); // so that children are not removed w/parent\n\n parentsToRemove.forEach(function (ele) {\n return ele.children().move({\n parent: null\n });\n }); // intermediate parents may be moved by prior line, so make sure we remove by fresh refs\n\n parentsToRemove.forEach(function (ele) {\n return getFreshRef(ele).remove();\n });\n }\n\n if (obj.style) {\n cy.style(obj.style);\n }\n\n if (obj.zoom != null && obj.zoom !== _p.zoom) {\n cy.zoom(obj.zoom);\n }\n\n if (obj.pan) {\n if (obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y) {\n cy.pan(obj.pan);\n }\n }\n\n if (obj.data) {\n cy.data(obj.data);\n }\n\n var fields = ['minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled', 'panningEnabled', 'userPanningEnabled', 'boxSelectionEnabled', 'autolock', 'autoungrabify', 'autounselectify'];\n\n for (var _i2 = 0; _i2 < fields.length; _i2++) {\n var f = fields[_i2];\n\n if (obj[f] != null) {\n cy[f](obj[f]);\n }\n }\n\n cy.endBatch();\n return this; // chaining\n } else {\n // get\n var flat = !!obj;\n var json = {};\n\n if (flat) {\n json.elements = this.elements().map(function (ele) {\n return ele.json();\n });\n } else {\n json.elements = {};\n eles.forEach(function (ele) {\n var group = ele.group();\n\n if (!json.elements[group]) {\n json.elements[group] = [];\n }\n\n json.elements[group].push(ele.json());\n });\n }\n\n if (this._private.styleEnabled) {\n json.style = cy.style().json();\n }\n\n json.data = copy(cy.data());\n var options = _p.options;\n json.zoomingEnabled = _p.zoomingEnabled;\n json.userZoomingEnabled = _p.userZoomingEnabled;\n json.zoom = _p.zoom;\n json.minZoom = _p.minZoom;\n json.maxZoom = _p.maxZoom;\n json.panningEnabled = _p.panningEnabled;\n json.userPanningEnabled = _p.userPanningEnabled;\n json.pan = copy(_p.pan);\n json.boxSelectionEnabled = _p.boxSelectionEnabled;\n json.renderer = copy(options.renderer);\n json.hideEdgesOnViewport = options.hideEdgesOnViewport;\n json.textureOnViewport = options.textureOnViewport;\n json.wheelSensitivity = options.wheelSensitivity;\n json.motionBlur = options.motionBlur;\n return json;\n }\n }\n});\ncorefn$9.$id = corefn$9.getElementById;\n[corefn, corefn$1, elesfn$v, corefn$2, corefn$3, corefn$4, corefn$5, corefn$6, corefn$7, corefn$8, fn$6].forEach(function (props) {\n extend(corefn$9, props);\n});\n\n/* eslint-disable no-unused-vars */\n\nvar defaults$9 = {\n fit: true,\n // whether to fit the viewport to the graph\n directed: false,\n // whether the tree is directed downwards (or edges can point in any direction if false)\n padding: 30,\n // padding on fit\n circle: false,\n // put depths in concentric circles if true, put depths top down if false\n grid: false,\n // whether to create an even grid into which the DAG is placed (circle:false only)\n spacingFactor: 1.75,\n // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap)\n boundingBox: undefined,\n // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true,\n // prevents node overlap, may overflow boundingBox if not enough space\n nodeDimensionsIncludeLabels: false,\n // Excludes the label when calculating node bounding boxes for the layout algorithm\n roots: undefined,\n // the roots of the trees\n maximal: false,\n // whether to shift nodes down their natural BFS depths in order to avoid upwards edges (DAGS only)\n animate: false,\n // whether to transition the node positions\n animationDuration: 500,\n // duration of animation in ms if enabled\n animationEasing: undefined,\n // easing of animation if enabled,\n animateFilter: function animateFilter(node, i) {\n return true;\n },\n // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts\n ready: undefined,\n // callback on layoutready\n stop: undefined,\n // callback on layoutstop\n transform: function transform(node, position) {\n return position;\n } // transform a given node position. Useful for changing flow direction in discrete layouts\n\n};\n/* eslint-enable */\n\nvar getInfo = function getInfo(ele) {\n return ele.scratch('breadthfirst');\n};\n\nvar setInfo = function setInfo(ele, obj) {\n return ele.scratch('breadthfirst', obj);\n};\n\nfunction BreadthFirstLayout(options) {\n this.options = extend({}, defaults$9, options);\n}\n\nBreadthFirstLayout.prototype.run = function () {\n var params = this.options;\n var options = params;\n var cy = params.cy;\n var eles = options.eles;\n var nodes = eles.nodes().filter(function (n) {\n return !n.isParent();\n });\n var graph = eles;\n var directed = options.directed;\n var maximal = options.maximal || options.maximalAdjustments > 0; // maximalAdjustments for compat. w/ old code\n\n var bb = makeBoundingBox(options.boundingBox ? options.boundingBox : {\n x1: 0,\n y1: 0,\n w: cy.width(),\n h: cy.height()\n });\n var roots;\n\n if (elementOrCollection(options.roots)) {\n roots = options.roots;\n } else if (array(options.roots)) {\n var rootsArray = [];\n\n for (var i = 0; i < options.roots.length; i++) {\n var id = options.roots[i];\n var ele = cy.getElementById(id);\n rootsArray.push(ele);\n }\n\n roots = cy.collection(rootsArray);\n } else if (string(options.roots)) {\n roots = cy.$(options.roots);\n } else {\n if (directed) {\n roots = nodes.roots();\n } else {\n var components = eles.components();\n roots = cy.collection();\n\n var _loop = function _loop(_i) {\n var comp = components[_i];\n var maxDegree = comp.maxDegree(false);\n var compRoots = comp.filter(function (ele) {\n return ele.degree(false) === maxDegree;\n });\n roots = roots.add(compRoots);\n };\n\n for (var _i = 0; _i < components.length; _i++) {\n _loop(_i);\n }\n }\n }\n\n var depths = [];\n var foundByBfs = {};\n\n var addToDepth = function addToDepth(ele, d) {\n if (depths[d] == null) {\n depths[d] = [];\n }\n\n var i = depths[d].length;\n depths[d].push(ele);\n setInfo(ele, {\n index: i,\n depth: d\n });\n };\n\n var changeDepth = function changeDepth(ele, newDepth) {\n var _getInfo = getInfo(ele),\n depth = _getInfo.depth,\n index = _getInfo.index;\n\n depths[depth][index] = null;\n addToDepth(ele, newDepth);\n }; // find the depths of the nodes\n\n\n graph.bfs({\n roots: roots,\n directed: options.directed,\n visit: function visit(node, edge, pNode, i, depth) {\n var ele = node[0];\n var id = ele.id();\n addToDepth(ele, depth);\n foundByBfs[id] = true;\n }\n }); // check for nodes not found by bfs\n\n var orphanNodes = [];\n\n for (var _i2 = 0; _i2 < nodes.length; _i2++) {\n var _ele = nodes[_i2];\n\n if (foundByBfs[_ele.id()]) {\n continue;\n } else {\n orphanNodes.push(_ele);\n }\n } // assign the nodes a depth and index\n\n\n var assignDepthsAt = function assignDepthsAt(i) {\n var eles = depths[i];\n\n for (var j = 0; j < eles.length; j++) {\n var _ele2 = eles[j];\n\n if (_ele2 == null) {\n eles.splice(j, 1);\n j--;\n continue;\n }\n\n setInfo(_ele2, {\n depth: i,\n index: j\n });\n }\n };\n\n var assignDepths = function assignDepths() {\n for (var _i3 = 0; _i3 < depths.length; _i3++) {\n assignDepthsAt(_i3);\n }\n };\n\n var adjustMaximally = function adjustMaximally(ele, shifted) {\n var eInfo = getInfo(ele);\n var incomers = ele.incomers().filter(function (el) {\n return el.isNode() && eles.has(el);\n });\n var maxDepth = -1;\n var id = ele.id();\n\n for (var k = 0; k < incomers.length; k++) {\n var incmr = incomers[k];\n var iInfo = getInfo(incmr);\n maxDepth = Math.max(maxDepth, iInfo.depth);\n }\n\n if (eInfo.depth <= maxDepth) {\n if (shifted[id]) {\n return null;\n }\n\n changeDepth(ele, maxDepth + 1);\n shifted[id] = true;\n return true;\n }\n\n return false;\n }; // for the directed case, try to make the edges all go down (i.e. depth i => depth i + 1)\n\n\n if (directed && maximal) {\n var Q = [];\n var shifted = {};\n\n var enqueue = function enqueue(n) {\n return Q.push(n);\n };\n\n var dequeue = function dequeue() {\n return Q.shift();\n };\n\n nodes.forEach(function (n) {\n return Q.push(n);\n });\n\n while (Q.length > 0) {\n var _ele3 = dequeue();\n\n var didShift = adjustMaximally(_ele3, shifted);\n\n if (didShift) {\n _ele3.outgoers().filter(function (el) {\n return el.isNode() && eles.has(el);\n }).forEach(enqueue);\n } else if (didShift === null) {\n warn('Detected double maximal shift for node `' + _ele3.id() + '`. Bailing maximal adjustment due to cycle. Use `options.maximal: true` only on DAGs.');\n break; // exit on failure\n }\n }\n }\n\n assignDepths(); // clear holes\n // find min distance we need to leave between nodes\n\n var minDistance = 0;\n\n if (options.avoidOverlap) {\n for (var _i4 = 0; _i4 < nodes.length; _i4++) {\n var n = nodes[_i4];\n var nbb = n.layoutDimensions(options);\n var w = nbb.w;\n var h = nbb.h;\n minDistance = Math.max(minDistance, w, h);\n }\n } // get the weighted percent for an element based on its connectivity to other levels\n\n\n var cachedWeightedPercent = {};\n\n var getWeightedPercent = function getWeightedPercent(ele) {\n if (cachedWeightedPercent[ele.id()]) {\n return cachedWeightedPercent[ele.id()];\n }\n\n var eleDepth = getInfo(ele).depth;\n var neighbors = ele.neighborhood();\n var percent = 0;\n var samples = 0;\n\n for (var _i5 = 0; _i5 < neighbors.length; _i5++) {\n var neighbor = neighbors[_i5];\n\n if (neighbor.isEdge() || neighbor.isParent() || !nodes.has(neighbor)) {\n continue;\n }\n\n var bf = getInfo(neighbor);\n var index = bf.index;\n var depth = bf.depth; // unassigned neighbours shouldn't affect the ordering\n\n if (index == null || depth == null) {\n continue;\n }\n\n var nDepth = depths[depth].length;\n\n if (depth < eleDepth) {\n // only get influenced by elements above\n percent += index / nDepth;\n samples++;\n }\n }\n\n samples = Math.max(1, samples);\n percent = percent / samples;\n\n if (samples === 0) {\n // put lone nodes at the start\n percent = 0;\n }\n\n cachedWeightedPercent[ele.id()] = percent;\n return percent;\n }; // rearrange the indices in each depth level based on connectivity\n\n\n var sortFn = function sortFn(a, b) {\n var apct = getWeightedPercent(a);\n var bpct = getWeightedPercent(b);\n var diff = apct - bpct;\n\n if (diff === 0) {\n return ascending(a.id(), b.id()); // make sure sort doesn't have don't-care comparisons\n } else {\n return diff;\n }\n }; // sort each level to make connected nodes closer\n\n\n for (var _i6 = 0; _i6 < depths.length; _i6++) {\n depths[_i6].sort(sortFn);\n\n assignDepthsAt(_i6);\n } // assign orphan nodes to a new top-level depth\n\n\n var orphanDepth = [];\n\n for (var _i7 = 0; _i7 < orphanNodes.length; _i7++) {\n orphanDepth.push(orphanNodes[_i7]);\n }\n\n depths.unshift(orphanDepth);\n assignDepths();\n var biggestDepthSize = 0;\n\n for (var _i8 = 0; _i8 < depths.length; _i8++) {\n biggestDepthSize = Math.max(depths[_i8].length, biggestDepthSize);\n }\n\n var center = {\n x: bb.x1 + bb.w / 2,\n y: bb.x1 + bb.h / 2\n };\n var maxDepthSize = depths.reduce(function (max, eles) {\n return Math.max(max, eles.length);\n }, 0);\n\n var getPosition = function getPosition(ele) {\n var _getInfo2 = getInfo(ele),\n depth = _getInfo2.depth,\n index = _getInfo2.index;\n\n var depthSize = depths[depth].length;\n var distanceX = Math.max(bb.w / ((options.grid ? maxDepthSize : depthSize) + 1), minDistance);\n var distanceY = Math.max(bb.h / (depths.length + 1), minDistance);\n var radiusStepSize = Math.min(bb.w / 2 / depths.length, bb.h / 2 / depths.length);\n radiusStepSize = Math.max(radiusStepSize, minDistance);\n\n if (!options.circle) {\n var epos = {\n x: center.x + (index + 1 - (depthSize + 1) / 2) * distanceX,\n y: (depth + 1) * distanceY\n };\n return epos;\n } else {\n var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize / 2 : 0);\n var theta = 2 * Math.PI / depths[depth].length * index;\n\n if (depth === 0 && depths[0].length === 1) {\n radius = 1;\n }\n\n return {\n x: center.x + radius * Math.cos(theta),\n y: center.y + radius * Math.sin(theta)\n };\n }\n };\n\n nodes.layoutPositions(this, options, getPosition);\n return this; // chaining\n};\n\nvar defaults$a = {\n fit: true,\n // whether to fit the viewport to the graph\n padding: 30,\n // the padding on fit\n boundingBox: undefined,\n // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true,\n // prevents node overlap, may overflow boundingBox and radius if not enough space\n nodeDimensionsIncludeLabels: false,\n // Excludes the label when calculating node bounding boxes for the layout algorithm\n spacingFactor: undefined,\n // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up\n radius: undefined,\n // the radius of the circle\n startAngle: 3 / 2 * Math.PI,\n // where nodes start in radians\n sweep: undefined,\n // how many radians should be between the first and last node (defaults to full circle)\n clockwise: true,\n // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n sort: undefined,\n // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n animate: false,\n // whether to transition the node positions\n animationDuration: 500,\n // duration of animation in ms if enabled\n animationEasing: undefined,\n // easing of animation if enabled\n animateFilter: function animateFilter(node, i) {\n return true;\n },\n // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts\n ready: undefined,\n // callback on layoutready\n stop: undefined,\n // callback on layoutstop\n transform: function transform(node, position) {\n return position;\n } // transform a given node position. Useful for changing flow direction in discrete layouts \n\n};\n\nfunction CircleLayout(options) {\n this.options = extend({}, defaults$a, options);\n}\n\nCircleLayout.prototype.run = function () {\n var params = this.options;\n var options = params;\n var cy = params.cy;\n var eles = options.eles;\n var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n var nodes = eles.nodes().not(':parent');\n\n if (options.sort) {\n nodes = nodes.sort(options.sort);\n }\n\n var bb = makeBoundingBox(options.boundingBox ? options.boundingBox : {\n x1: 0,\n y1: 0,\n w: cy.width(),\n h: cy.height()\n });\n var center = {\n x: bb.x1 + bb.w / 2,\n y: bb.y1 + bb.h / 2\n };\n var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / nodes.length : options.sweep;\n var dTheta = sweep / Math.max(1, nodes.length - 1);\n var r;\n var minDistance = 0;\n\n for (var i = 0; i < nodes.length; i++) {\n var n = nodes[i];\n var nbb = n.layoutDimensions(options);\n var w = nbb.w;\n var h = nbb.h;\n minDistance = Math.max(minDistance, w, h);\n }\n\n if (number(options.radius)) {\n r = options.radius;\n } else if (nodes.length <= 1) {\n r = 0;\n } else {\n r = Math.min(bb.h, bb.w) / 2 - minDistance;\n } // calculate the radius\n\n\n if (nodes.length > 1 && options.avoidOverlap) {\n // but only if more than one node (can't overlap)\n minDistance *= 1.75; // just to have some nice spacing\n\n var dcos = Math.cos(dTheta) - Math.cos(0);\n var dsin = Math.sin(dTheta) - Math.sin(0);\n var rMin = Math.sqrt(minDistance * minDistance / (dcos * dcos + dsin * dsin)); // s.t. no nodes overlapping\n\n r = Math.max(rMin, r);\n }\n\n var getPos = function getPos(ele, i) {\n var theta = options.startAngle + i * dTheta * (clockwise ? 1 : -1);\n var rx = r * Math.cos(theta);\n var ry = r * Math.sin(theta);\n var pos = {\n x: center.x + rx,\n y: center.y + ry\n };\n return pos;\n };\n\n nodes.layoutPositions(this, options, getPos);\n return this; // chaining\n};\n\nvar defaults$b = {\n fit: true,\n // whether to fit the viewport to the graph\n padding: 30,\n // the padding on fit\n startAngle: 3 / 2 * Math.PI,\n // where nodes start in radians\n sweep: undefined,\n // how many radians should be between the first and last node (defaults to full circle)\n clockwise: true,\n // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n equidistant: false,\n // whether levels have an equal radial distance betwen them, may cause bounding box overflow\n minNodeSpacing: 10,\n // min spacing between outside of nodes (used for radius adjustment)\n boundingBox: undefined,\n // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true,\n // prevents node overlap, may overflow boundingBox if not enough space\n nodeDimensionsIncludeLabels: false,\n // Excludes the label when calculating node bounding boxes for the layout algorithm\n height: undefined,\n // height of layout area (overrides container height)\n width: undefined,\n // width of layout area (overrides container width)\n spacingFactor: undefined,\n // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up\n concentric: function concentric(node) {\n // returns numeric value for each node, placing higher nodes in levels towards the centre\n return node.degree();\n },\n levelWidth: function levelWidth(nodes) {\n // the letiation of concentric values in each level\n return nodes.maxDegree() / 4;\n },\n animate: false,\n // whether to transition the node positions\n animationDuration: 500,\n // duration of animation in ms if enabled\n animationEasing: undefined,\n // easing of animation if enabled\n animateFilter: function animateFilter(node, i) {\n return true;\n },\n // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts\n ready: undefined,\n // callback on layoutready\n stop: undefined,\n // callback on layoutstop\n transform: function transform(node, position) {\n return position;\n } // transform a given node position. Useful for changing flow direction in discrete layouts\n\n};\n\nfunction ConcentricLayout(options) {\n this.options = extend({}, defaults$b, options);\n}\n\nConcentricLayout.prototype.run = function () {\n var params = this.options;\n var options = params;\n var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n var cy = params.cy;\n var eles = options.eles;\n var nodes = eles.nodes().not(':parent');\n var bb = makeBoundingBox(options.boundingBox ? options.boundingBox : {\n x1: 0,\n y1: 0,\n w: cy.width(),\n h: cy.height()\n });\n var center = {\n x: bb.x1 + bb.w / 2,\n y: bb.y1 + bb.h / 2\n };\n var nodeValues = []; // { node, value }\n\n var maxNodeSize = 0;\n\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n var value = void 0; // calculate the node value\n\n value = options.concentric(node);\n nodeValues.push({\n value: value,\n node: node\n }); // for style mapping\n\n node._private.scratch.concentric = value;\n } // in case we used the `concentric` in style\n\n\n nodes.updateStyle(); // calculate max size now based on potentially updated mappers\n\n for (var _i = 0; _i < nodes.length; _i++) {\n var _node = nodes[_i];\n\n var nbb = _node.layoutDimensions(options);\n\n maxNodeSize = Math.max(maxNodeSize, nbb.w, nbb.h);\n } // sort node values in descreasing order\n\n\n nodeValues.sort(function (a, b) {\n return b.value - a.value;\n });\n var levelWidth = options.levelWidth(nodes); // put the values into levels\n\n var levels = [[]];\n var currentLevel = levels[0];\n\n for (var _i2 = 0; _i2 < nodeValues.length; _i2++) {\n var val = nodeValues[_i2];\n\n if (currentLevel.length > 0) {\n var diff = Math.abs(currentLevel[0].value - val.value);\n\n if (diff >= levelWidth) {\n currentLevel = [];\n levels.push(currentLevel);\n }\n }\n\n currentLevel.push(val);\n } // create positions from levels\n\n\n var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes\n\n if (!options.avoidOverlap) {\n // then strictly constrain to bb\n var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1;\n var maxR = Math.min(bb.w, bb.h) / 2 - minDist;\n var rStep = maxR / (levels.length + firstLvlHasMulti ? 1 : 0);\n minDist = Math.min(minDist, rStep);\n } // find the metrics for each level\n\n\n var r = 0;\n\n for (var _i3 = 0; _i3 < levels.length; _i3++) {\n var level = levels[_i3];\n var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / level.length : options.sweep;\n var dTheta = level.dTheta = sweep / Math.max(1, level.length - 1); // calculate the radius\n\n if (level.length > 1 && options.avoidOverlap) {\n // but only if more than one node (can't overlap)\n var dcos = Math.cos(dTheta) - Math.cos(0);\n var dsin = Math.sin(dTheta) - Math.sin(0);\n var rMin = Math.sqrt(minDist * minDist / (dcos * dcos + dsin * dsin)); // s.t. no nodes overlapping\n\n r = Math.max(rMin, r);\n }\n\n level.r = r;\n r += minDist;\n }\n\n if (options.equidistant) {\n var rDeltaMax = 0;\n var _r = 0;\n\n for (var _i4 = 0; _i4 < levels.length; _i4++) {\n var _level = levels[_i4];\n var rDelta = _level.r - _r;\n rDeltaMax = Math.max(rDeltaMax, rDelta);\n }\n\n _r = 0;\n\n for (var _i5 = 0; _i5 < levels.length; _i5++) {\n var _level2 = levels[_i5];\n\n if (_i5 === 0) {\n _r = _level2.r;\n }\n\n _level2.r = _r;\n _r += rDeltaMax;\n }\n } // calculate the node positions\n\n\n var pos = {}; // id => position\n\n for (var _i6 = 0; _i6 < levels.length; _i6++) {\n var _level3 = levels[_i6];\n var _dTheta = _level3.dTheta;\n var _r2 = _level3.r;\n\n for (var j = 0; j < _level3.length; j++) {\n var _val = _level3[j];\n var theta = options.startAngle + (clockwise ? 1 : -1) * _dTheta * j;\n var p = {\n x: center.x + _r2 * Math.cos(theta),\n y: center.y + _r2 * Math.sin(theta)\n };\n pos[_val.node.id()] = p;\n }\n } // position the nodes\n\n\n nodes.layoutPositions(this, options, function (ele) {\n var id = ele.id();\n return pos[id];\n });\n return this; // chaining\n};\n\n/*\nThe CoSE layout was written by Gerardo Huck.\nhttps://www.linkedin.com/in/gerardohuck/\n\nBased on the following article:\nhttp://dl.acm.org/citation.cfm?id=1498047\n\nModifications tracked on Github.\n*/\nvar DEBUG;\n/**\n * @brief : default layout options\n */\n\nvar defaults$c = {\n // Called on `layoutready`\n ready: function ready() {},\n // Called on `layoutstop`\n stop: function stop() {},\n // Whether to animate while running the layout\n // true : Animate continuously as the layout is running\n // false : Just show the end result\n // 'end' : Animate with the end result, from the initial positions to the end positions\n animate: true,\n // Easing of the animation for animate:'end'\n animationEasing: undefined,\n // The duration of the animation for animate:'end'\n animationDuration: undefined,\n // A function that determines whether the node should be animated\n // All nodes animated by default on animate enabled\n // Non-animated nodes are positioned immediately when the layout starts\n animateFilter: function animateFilter(node, i) {\n return true;\n },\n // The layout animates only after this many milliseconds for animate:true\n // (prevents flashing on fast runs)\n animationThreshold: 250,\n // Number of iterations between consecutive screen positions update\n refresh: 20,\n // Whether to fit the network view after when done\n fit: true,\n // Padding on fit\n padding: 30,\n // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n boundingBox: undefined,\n // Excludes the label when calculating node bounding boxes for the layout algorithm\n nodeDimensionsIncludeLabels: false,\n // Randomize the initial positions of the nodes (true) or use existing positions (false)\n randomize: false,\n // Extra spacing between components in non-compound graphs\n componentSpacing: 40,\n // Node repulsion (non overlapping) multiplier\n nodeRepulsion: function nodeRepulsion(node) {\n return 2048;\n },\n // Node repulsion (overlapping) multiplier\n nodeOverlap: 4,\n // Ideal edge (non nested) length\n idealEdgeLength: function idealEdgeLength(edge) {\n return 32;\n },\n // Divisor to compute edge forces\n edgeElasticity: function edgeElasticity(edge) {\n return 32;\n },\n // Nesting factor (multiplier) to compute ideal edge length for nested edges\n nestingFactor: 1.2,\n // Gravity force (constant)\n gravity: 1,\n // Maximum number of iterations to perform\n numIter: 1000,\n // Initial temperature (maximum node displacement)\n initialTemp: 1000,\n // Cooling factor (how the temperature is reduced between consecutive iterations\n coolingFactor: 0.99,\n // Lower temperature threshold (below this point the layout will end)\n minTemp: 1.0\n};\n/**\n * @brief : constructor\n * @arg options : object containing layout options\n */\n\nfunction CoseLayout(options) {\n this.options = extend({}, defaults$c, options);\n this.options.layout = this;\n}\n/**\n * @brief : runs the layout\n */\n\n\nCoseLayout.prototype.run = function () {\n var options = this.options;\n var cy = options.cy;\n var layout = this;\n layout.stopped = false;\n\n if (options.animate === true || options.animate === false) {\n layout.emit({\n type: 'layoutstart',\n layout: layout\n });\n } // Set DEBUG - Global variable\n\n\n if (true === options.debug) {\n DEBUG = true;\n } else {\n DEBUG = false;\n } // Initialize layout info\n\n\n var layoutInfo = createLayoutInfo(cy, layout, options); // Show LayoutInfo contents if debugging\n\n if (DEBUG) {\n printLayoutInfo(layoutInfo);\n } // If required, randomize node positions\n\n\n if (options.randomize) {\n randomizePositions(layoutInfo);\n }\n\n var startTime = performanceNow();\n\n var refresh = function refresh() {\n refreshPositions(layoutInfo, cy, options); // Fit the graph if necessary\n\n if (true === options.fit) {\n cy.fit(options.padding);\n }\n };\n\n var mainLoop = function mainLoop(i) {\n if (layout.stopped || i >= options.numIter) {\n // logDebug(\"Layout manually stopped. Stopping computation in step \" + i);\n return false;\n } // Do one step in the phisical simulation\n\n\n step$1(layoutInfo, options); // Update temperature\n\n layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor; // logDebug(\"New temperature: \" + layoutInfo.temperature);\n\n if (layoutInfo.temperature < options.minTemp) {\n // logDebug(\"Temperature drop below minimum threshold. Stopping computation in step \" + i);\n return false;\n }\n\n return true;\n };\n\n var done = function done() {\n if (options.animate === true || options.animate === false) {\n refresh(); // Layout has finished\n\n layout.one('layoutstop', options.stop);\n layout.emit({\n type: 'layoutstop',\n layout: layout\n });\n } else {\n var nodes = options.eles.nodes();\n var getScaledPos = getScaleInBoundsFn(layoutInfo, options, nodes);\n nodes.layoutPositions(layout, options, getScaledPos);\n }\n };\n\n var i = 0;\n var loopRet = true;\n\n if (options.animate === true) {\n var frame = function frame() {\n var f = 0;\n\n while (loopRet && f < options.refresh) {\n loopRet = mainLoop(i);\n i++;\n f++;\n }\n\n if (!loopRet) {\n // it's done\n separateComponents(layoutInfo, options);\n done();\n } else {\n var now = performanceNow();\n\n if (now - startTime >= options.animationThreshold) {\n refresh();\n }\n\n requestAnimationFrame(frame);\n }\n };\n\n frame();\n } else {\n while (loopRet) {\n loopRet = mainLoop(i);\n i++;\n }\n\n separateComponents(layoutInfo, options);\n done();\n }\n\n return this; // chaining\n};\n/**\n * @brief : called on continuous layouts to stop them before they finish\n */\n\n\nCoseLayout.prototype.stop = function () {\n this.stopped = true;\n\n if (this.thread) {\n this.thread.stop();\n }\n\n this.emit('layoutstop');\n return this; // chaining\n};\n\nCoseLayout.prototype.destroy = function () {\n if (this.thread) {\n this.thread.stop();\n }\n\n return this; // chaining\n};\n/**\n * @brief : Creates an object which is contains all the data\n * used in the layout process\n * @arg cy : cytoscape.js object\n * @return : layoutInfo object initialized\n */\n\n\nvar createLayoutInfo = function createLayoutInfo(cy, layout, options) {\n // Shortcut\n var edges = options.eles.edges();\n var nodes = options.eles.nodes();\n var layoutInfo = {\n isCompound: cy.hasCompoundNodes(),\n layoutNodes: [],\n idToIndex: {},\n nodeSize: nodes.size(),\n graphSet: [],\n indexToGraph: [],\n layoutEdges: [],\n edgeSize: edges.size(),\n temperature: options.initialTemp,\n clientWidth: cy.width(),\n clientHeight: cy.width(),\n boundingBox: makeBoundingBox(options.boundingBox ? options.boundingBox : {\n x1: 0,\n y1: 0,\n w: cy.width(),\n h: cy.height()\n })\n };\n var components = options.eles.components();\n var id2cmptId = {};\n\n for (var i = 0; i < components.length; i++) {\n var component = components[i];\n\n for (var j = 0; j < component.length; j++) {\n var node = component[j];\n id2cmptId[node.id()] = i;\n }\n } // Iterate over all nodes, creating layout nodes\n\n\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = nodes[i];\n var nbb = n.layoutDimensions(options);\n var tempNode = {};\n tempNode.isLocked = n.locked();\n tempNode.id = n.data('id');\n tempNode.parentId = n.data('parent');\n tempNode.cmptId = id2cmptId[n.id()];\n tempNode.children = [];\n tempNode.positionX = n.position('x');\n tempNode.positionY = n.position('y');\n tempNode.offsetX = 0;\n tempNode.offsetY = 0;\n tempNode.height = nbb.w;\n tempNode.width = nbb.h;\n tempNode.maxX = tempNode.positionX + tempNode.width / 2;\n tempNode.minX = tempNode.positionX - tempNode.width / 2;\n tempNode.maxY = tempNode.positionY + tempNode.height / 2;\n tempNode.minY = tempNode.positionY - tempNode.height / 2;\n tempNode.padLeft = parseFloat(n.style('padding'));\n tempNode.padRight = parseFloat(n.style('padding'));\n tempNode.padTop = parseFloat(n.style('padding'));\n tempNode.padBottom = parseFloat(n.style('padding')); // forces\n\n tempNode.nodeRepulsion = fn(options.nodeRepulsion) ? options.nodeRepulsion(n) : options.nodeRepulsion; // Add new node\n\n layoutInfo.layoutNodes.push(tempNode); // Add entry to id-index map\n\n layoutInfo.idToIndex[tempNode.id] = i;\n } // Inline implementation of a queue, used for traversing the graph in BFS order\n\n\n var queue = [];\n var start = 0; // Points to the start the queue\n\n var end = -1; // Points to the end of the queue\n\n var tempGraph = []; // Second pass to add child information and\n // initialize queue for hierarchical traversal\n\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n var p_id = n.parentId; // Check if node n has a parent node\n\n if (null != p_id) {\n // Add node Id to parent's list of children\n layoutInfo.layoutNodes[layoutInfo.idToIndex[p_id]].children.push(n.id);\n } else {\n // If a node doesn't have a parent, then it's in the root graph\n queue[++end] = n.id;\n tempGraph.push(n.id);\n }\n } // Add root graph to graphSet\n\n\n layoutInfo.graphSet.push(tempGraph); // Traverse the graph, level by level,\n\n while (start <= end) {\n // Get the node to visit and remove it from queue\n var node_id = queue[start++];\n var node_ix = layoutInfo.idToIndex[node_id];\n var node = layoutInfo.layoutNodes[node_ix];\n var children = node.children;\n\n if (children.length > 0) {\n // Add children nodes as a new graph to graph set\n layoutInfo.graphSet.push(children); // Add children to que queue to be visited\n\n for (var i = 0; i < children.length; i++) {\n queue[++end] = children[i];\n }\n }\n } // Create indexToGraph map\n\n\n for (var i = 0; i < layoutInfo.graphSet.length; i++) {\n var graph = layoutInfo.graphSet[i];\n\n for (var j = 0; j < graph.length; j++) {\n var index = layoutInfo.idToIndex[graph[j]];\n layoutInfo.indexToGraph[index] = i;\n }\n } // Iterate over all edges, creating Layout Edges\n\n\n for (var i = 0; i < layoutInfo.edgeSize; i++) {\n var e = edges[i];\n var tempEdge = {};\n tempEdge.id = e.data('id');\n tempEdge.sourceId = e.data('source');\n tempEdge.targetId = e.data('target'); // Compute ideal length\n\n var idealLength = fn(options.idealEdgeLength) ? options.idealEdgeLength(e) : options.idealEdgeLength;\n var elasticity = fn(options.edgeElasticity) ? options.edgeElasticity(e) : options.edgeElasticity; // Check if it's an inter graph edge\n\n var sourceIx = layoutInfo.idToIndex[tempEdge.sourceId];\n var targetIx = layoutInfo.idToIndex[tempEdge.targetId];\n var sourceGraph = layoutInfo.indexToGraph[sourceIx];\n var targetGraph = layoutInfo.indexToGraph[targetIx];\n\n if (sourceGraph != targetGraph) {\n // Find lowest common graph ancestor\n var lca = findLCA(tempEdge.sourceId, tempEdge.targetId, layoutInfo); // Compute sum of node depths, relative to lca graph\n\n var lcaGraph = layoutInfo.graphSet[lca];\n var depth = 0; // Source depth\n\n var tempNode = layoutInfo.layoutNodes[sourceIx];\n\n while (-1 === lcaGraph.indexOf(tempNode.id)) {\n tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n depth++;\n } // Target depth\n\n\n tempNode = layoutInfo.layoutNodes[targetIx];\n\n while (-1 === lcaGraph.indexOf(tempNode.id)) {\n tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n depth++;\n } // logDebug('LCA of nodes ' + tempEdge.sourceId + ' and ' + tempEdge.targetId +\n // \". Index: \" + lca + \" Contents: \" + lcaGraph.toString() +\n // \". Depth: \" + depth);\n // Update idealLength\n\n\n idealLength *= depth * options.nestingFactor;\n }\n\n tempEdge.idealLength = idealLength;\n tempEdge.elasticity = elasticity;\n layoutInfo.layoutEdges.push(tempEdge);\n } // Finally, return layoutInfo object\n\n\n return layoutInfo;\n};\n/**\n * @brief : This function finds the index of the lowest common\n * graph ancestor between 2 nodes in the subtree\n * (from the graph hierarchy induced tree) whose\n * root is graphIx\n *\n * @arg node1: node1's ID\n * @arg node2: node2's ID\n * @arg layoutInfo: layoutInfo object\n *\n */\n\n\nvar findLCA = function findLCA(node1, node2, layoutInfo) {\n // Find their common ancester, starting from the root graph\n var res = findLCA_aux(node1, node2, 0, layoutInfo);\n\n if (2 > res.count) {\n // If aux function couldn't find the common ancester,\n // then it is the root graph\n return 0;\n } else {\n return res.graph;\n }\n};\n/**\n * @brief : Auxiliary function used for LCA computation\n *\n * @arg node1 : node1's ID\n * @arg node2 : node2's ID\n * @arg graphIx : subgraph index\n * @arg layoutInfo : layoutInfo object\n *\n * @return : object of the form {count: X, graph: Y}, where:\n * X is the number of ancesters (max: 2) found in\n * graphIx (and it's subgraphs),\n * Y is the graph index of the lowest graph containing\n * all X nodes\n */\n\n\nvar findLCA_aux = function findLCA_aux(node1, node2, graphIx, layoutInfo) {\n var graph = layoutInfo.graphSet[graphIx]; // If both nodes belongs to graphIx\n\n if (-1 < graph.indexOf(node1) && -1 < graph.indexOf(node2)) {\n return {\n count: 2,\n graph: graphIx\n };\n } // Make recursive calls for all subgraphs\n\n\n var c = 0;\n\n for (var i = 0; i < graph.length; i++) {\n var nodeId = graph[i];\n var nodeIx = layoutInfo.idToIndex[nodeId];\n var children = layoutInfo.layoutNodes[nodeIx].children; // If the node has no child, skip it\n\n if (0 === children.length) {\n continue;\n }\n\n var childGraphIx = layoutInfo.indexToGraph[layoutInfo.idToIndex[children[0]]];\n var result = findLCA_aux(node1, node2, childGraphIx, layoutInfo);\n\n if (0 === result.count) {\n // Neither node1 nor node2 are present in this subgraph\n continue;\n } else if (1 === result.count) {\n // One of (node1, node2) is present in this subgraph\n c++;\n\n if (2 === c) {\n // We've already found both nodes, no need to keep searching\n break;\n }\n } else {\n // Both nodes are present in this subgraph\n return result;\n }\n }\n\n return {\n count: c,\n graph: graphIx\n };\n};\n/**\n * @brief: printsLayoutInfo into js console\n * Only used for debbuging\n */\n\n\nif (false) { var printLayoutInfo; }\n/**\n * @brief : Randomizes the position of all nodes\n */\n\n\nvar randomizePositions = function randomizePositions(layoutInfo, cy) {\n var width = layoutInfo.clientWidth;\n var height = layoutInfo.clientHeight;\n\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i]; // No need to randomize compound nodes or locked nodes\n\n if (0 === n.children.length && !n.isLocked) {\n n.positionX = Math.random() * width;\n n.positionY = Math.random() * height;\n }\n }\n};\n\nvar getScaleInBoundsFn = function getScaleInBoundsFn(layoutInfo, options, nodes) {\n var bb = layoutInfo.boundingBox;\n var coseBB = {\n x1: Infinity,\n x2: -Infinity,\n y1: Infinity,\n y2: -Infinity\n };\n\n if (options.boundingBox) {\n nodes.forEach(function (node) {\n var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]];\n coseBB.x1 = Math.min(coseBB.x1, lnode.positionX);\n coseBB.x2 = Math.max(coseBB.x2, lnode.positionX);\n coseBB.y1 = Math.min(coseBB.y1, lnode.positionY);\n coseBB.y2 = Math.max(coseBB.y2, lnode.positionY);\n });\n coseBB.w = coseBB.x2 - coseBB.x1;\n coseBB.h = coseBB.y2 - coseBB.y1;\n }\n\n return function (ele, i) {\n var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[ele.data('id')]];\n\n if (options.boundingBox) {\n // then add extra bounding box constraint\n var pctX = (lnode.positionX - coseBB.x1) / coseBB.w;\n var pctY = (lnode.positionY - coseBB.y1) / coseBB.h;\n return {\n x: bb.x1 + pctX * bb.w,\n y: bb.y1 + pctY * bb.h\n };\n } else {\n return {\n x: lnode.positionX,\n y: lnode.positionY\n };\n }\n };\n};\n/**\n * @brief : Updates the positions of nodes in the network\n * @arg layoutInfo : LayoutInfo object\n * @arg cy : Cytoscape object\n * @arg options : Layout options\n */\n\n\nvar refreshPositions = function refreshPositions(layoutInfo, cy, options) {\n // var s = 'Refreshing positions';\n // logDebug(s);\n var layout = options.layout;\n var nodes = options.eles.nodes();\n var getScaledPos = getScaleInBoundsFn(layoutInfo, options, nodes);\n nodes.positions(getScaledPos); // Trigger layoutReady only on first call\n\n if (true !== layoutInfo.ready) {\n // s = 'Triggering layoutready';\n // logDebug(s);\n layoutInfo.ready = true;\n layout.one('layoutready', options.ready);\n layout.emit({\n type: 'layoutready',\n layout: this\n });\n }\n};\n/**\n * @brief : Logs a debug message in JS console, if DEBUG is ON\n */\n// var logDebug = function(text) {\n// if (DEBUG) {\n// console.debug(text);\n// }\n// };\n\n/**\n * @brief : Performs one iteration of the physical simulation\n * @arg layoutInfo : LayoutInfo object already initialized\n * @arg cy : Cytoscape object\n * @arg options : Layout options\n */\n\n\nvar step$1 = function step(layoutInfo, options, _step) {\n // var s = \"\\n\\n###############################\";\n // s += \"\\nSTEP: \" + step;\n // s += \"\\n###############################\\n\";\n // logDebug(s);\n // Calculate node repulsions\n calculateNodeForces(layoutInfo, options); // Calculate edge forces\n\n calculateEdgeForces(layoutInfo); // Calculate gravity forces\n\n calculateGravityForces(layoutInfo, options); // Propagate forces from parent to child\n\n propagateForces(layoutInfo); // Update positions based on calculated forces\n\n updatePositions(layoutInfo);\n};\n/**\n * @brief : Computes the node repulsion forces\n */\n\n\nvar calculateNodeForces = function calculateNodeForces(layoutInfo, options) {\n // Go through each of the graphs in graphSet\n // Nodes only repel each other if they belong to the same graph\n // var s = 'calculateNodeForces';\n // logDebug(s);\n for (var i = 0; i < layoutInfo.graphSet.length; i++) {\n var graph = layoutInfo.graphSet[i];\n var numNodes = graph.length; // s = \"Set: \" + graph.toString();\n // logDebug(s);\n // Now get all the pairs of nodes\n // Only get each pair once, (A, B) = (B, A)\n\n for (var j = 0; j < numNodes; j++) {\n var node1 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];\n\n for (var k = j + 1; k < numNodes; k++) {\n var node2 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[k]]];\n nodeRepulsion(node1, node2, layoutInfo, options);\n }\n }\n }\n};\n\nvar randomDistance = function randomDistance(max) {\n return -max + 2 * max * Math.random();\n};\n/**\n * @brief : Compute the node repulsion forces between a pair of nodes\n */\n\n\nvar nodeRepulsion = function nodeRepulsion(node1, node2, layoutInfo, options) {\n // var s = \"Node repulsion. Node1: \" + node1.id + \" Node2: \" + node2.id;\n var cmptId1 = node1.cmptId;\n var cmptId2 = node2.cmptId;\n\n if (cmptId1 !== cmptId2 && !layoutInfo.isCompound) {\n return;\n } // Get direction of line connecting both node centers\n\n\n var directionX = node2.positionX - node1.positionX;\n var directionY = node2.positionY - node1.positionY;\n var maxRandDist = 1; // s += \"\\ndirectionX: \" + directionX + \", directionY: \" + directionY;\n // If both centers are the same, apply a random force\n\n if (0 === directionX && 0 === directionY) {\n directionX = randomDistance(maxRandDist);\n directionY = randomDistance(maxRandDist);\n }\n\n var overlap = nodesOverlap(node1, node2, directionX, directionY);\n\n if (overlap > 0) {\n // s += \"\\nNodes DO overlap.\";\n // s += \"\\nOverlap: \" + overlap;\n // If nodes overlap, repulsion force is proportional\n // to the overlap\n var force = options.nodeOverlap * overlap; // Compute the module and components of the force vector\n\n var distance = Math.sqrt(directionX * directionX + directionY * directionY); // s += \"\\nDistance: \" + distance;\n\n var forceX = force * directionX / distance;\n var forceY = force * directionY / distance;\n } else {\n // s += \"\\nNodes do NOT overlap.\";\n // If there's no overlap, force is inversely proportional\n // to squared distance\n // Get clipping points for both nodes\n var point1 = findClippingPoint(node1, directionX, directionY);\n var point2 = findClippingPoint(node2, -1 * directionX, -1 * directionY); // Use clipping points to compute distance\n\n var distanceX = point2.x - point1.x;\n var distanceY = point2.y - point1.y;\n var distanceSqr = distanceX * distanceX + distanceY * distanceY;\n var distance = Math.sqrt(distanceSqr); // s += \"\\nDistance: \" + distance;\n // Compute the module and components of the force vector\n\n var force = (node1.nodeRepulsion + node2.nodeRepulsion) / distanceSqr;\n var forceX = force * distanceX / distance;\n var forceY = force * distanceY / distance;\n } // Apply force\n\n\n if (!node1.isLocked) {\n node1.offsetX -= forceX;\n node1.offsetY -= forceY;\n }\n\n if (!node2.isLocked) {\n node2.offsetX += forceX;\n node2.offsetY += forceY;\n } // s += \"\\nForceX: \" + forceX + \" ForceY: \" + forceY;\n // logDebug(s);\n\n\n return;\n};\n/**\n * @brief : Determines whether two nodes overlap or not\n * @return : Amount of overlapping (0 => no overlap)\n */\n\n\nvar nodesOverlap = function nodesOverlap(node1, node2, dX, dY) {\n if (dX > 0) {\n var overlapX = node1.maxX - node2.minX;\n } else {\n var overlapX = node2.maxX - node1.minX;\n }\n\n if (dY > 0) {\n var overlapY = node1.maxY - node2.minY;\n } else {\n var overlapY = node2.maxY - node1.minY;\n }\n\n if (overlapX >= 0 && overlapY >= 0) {\n return Math.sqrt(overlapX * overlapX + overlapY * overlapY);\n } else {\n return 0;\n }\n};\n/**\n * @brief : Finds the point in which an edge (direction dX, dY) intersects\n * the rectangular bounding box of it's source/target node\n */\n\n\nvar findClippingPoint = function findClippingPoint(node, dX, dY) {\n // Shorcuts\n var X = node.positionX;\n var Y = node.positionY;\n var H = node.height || 1;\n var W = node.width || 1;\n var dirSlope = dY / dX;\n var nodeSlope = H / W; // var s = 'Computing clipping point of node ' + node.id +\n // \" . Height: \" + H + \", Width: \" + W +\n // \"\\nDirection \" + dX + \", \" + dY;\n //\n // Compute intersection\n\n var res = {}; // Case: Vertical direction (up)\n\n if (0 === dX && 0 < dY) {\n res.x = X; // s += \"\\nUp direction\";\n\n res.y = Y + H / 2;\n return res;\n } // Case: Vertical direction (down)\n\n\n if (0 === dX && 0 > dY) {\n res.x = X;\n res.y = Y + H / 2; // s += \"\\nDown direction\";\n\n return res;\n } // Case: Intersects the right border\n\n\n if (0 < dX && -1 * nodeSlope <= dirSlope && dirSlope <= nodeSlope) {\n res.x = X + W / 2;\n res.y = Y + W * dY / 2 / dX; // s += \"\\nRightborder\";\n\n return res;\n } // Case: Intersects the left border\n\n\n if (0 > dX && -1 * nodeSlope <= dirSlope && dirSlope <= nodeSlope) {\n res.x = X - W / 2;\n res.y = Y - W * dY / 2 / dX; // s += \"\\nLeftborder\";\n\n return res;\n } // Case: Intersects the top border\n\n\n if (0 < dY && (dirSlope <= -1 * nodeSlope || dirSlope >= nodeSlope)) {\n res.x = X + H * dX / 2 / dY;\n res.y = Y + H / 2; // s += \"\\nTop border\";\n\n return res;\n } // Case: Intersects the bottom border\n\n\n if (0 > dY && (dirSlope <= -1 * nodeSlope || dirSlope >= nodeSlope)) {\n res.x = X - H * dX / 2 / dY;\n res.y = Y - H / 2; // s += \"\\nBottom border\";\n\n return res;\n } // s += \"\\nClipping point found at \" + res.x + \", \" + res.y;\n // logDebug(s);\n\n\n return res;\n};\n/**\n * @brief : Calculates all edge forces\n */\n\n\nvar calculateEdgeForces = function calculateEdgeForces(layoutInfo, options) {\n // Iterate over all edges\n for (var i = 0; i < layoutInfo.edgeSize; i++) {\n // Get edge, source & target nodes\n var edge = layoutInfo.layoutEdges[i];\n var sourceIx = layoutInfo.idToIndex[edge.sourceId];\n var source = layoutInfo.layoutNodes[sourceIx];\n var targetIx = layoutInfo.idToIndex[edge.targetId];\n var target = layoutInfo.layoutNodes[targetIx]; // Get direction of line connecting both node centers\n\n var directionX = target.positionX - source.positionX;\n var directionY = target.positionY - source.positionY; // If both centers are the same, do nothing.\n // A random force has already been applied as node repulsion\n\n if (0 === directionX && 0 === directionY) {\n continue;\n } // Get clipping points for both nodes\n\n\n var point1 = findClippingPoint(source, directionX, directionY);\n var point2 = findClippingPoint(target, -1 * directionX, -1 * directionY);\n var lx = point2.x - point1.x;\n var ly = point2.y - point1.y;\n var l = Math.sqrt(lx * lx + ly * ly);\n var force = Math.pow(edge.idealLength - l, 2) / edge.elasticity;\n\n if (0 !== l) {\n var forceX = force * lx / l;\n var forceY = force * ly / l;\n } else {\n var forceX = 0;\n var forceY = 0;\n } // Add this force to target and source nodes\n\n\n if (!source.isLocked) {\n source.offsetX += forceX;\n source.offsetY += forceY;\n }\n\n if (!target.isLocked) {\n target.offsetX -= forceX;\n target.offsetY -= forceY;\n } // var s = 'Edge force between nodes ' + source.id + ' and ' + target.id;\n // s += \"\\nDistance: \" + l + \" Force: (\" + forceX + \", \" + forceY + \")\";\n // logDebug(s);\n\n }\n};\n/**\n * @brief : Computes gravity forces for all nodes\n */\n\n\nvar calculateGravityForces = function calculateGravityForces(layoutInfo, options) {\n var distThreshold = 1; // var s = 'calculateGravityForces';\n // logDebug(s);\n\n for (var i = 0; i < layoutInfo.graphSet.length; i++) {\n var graph = layoutInfo.graphSet[i];\n var numNodes = graph.length; // s = \"Set: \" + graph.toString();\n // logDebug(s);\n // Compute graph center\n\n if (0 === i) {\n var centerX = layoutInfo.clientHeight / 2;\n var centerY = layoutInfo.clientWidth / 2;\n } else {\n // Get Parent node for this graph, and use its position as center\n var temp = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[0]]];\n var parent = layoutInfo.layoutNodes[layoutInfo.idToIndex[temp.parentId]];\n var centerX = parent.positionX;\n var centerY = parent.positionY;\n } // s = \"Center found at: \" + centerX + \", \" + centerY;\n // logDebug(s);\n // Apply force to all nodes in graph\n\n\n for (var j = 0; j < numNodes; j++) {\n var node = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]]; // s = \"Node: \" + node.id;\n\n if (node.isLocked) {\n continue;\n }\n\n var dx = centerX - node.positionX;\n var dy = centerY - node.positionY;\n var d = Math.sqrt(dx * dx + dy * dy);\n\n if (d > distThreshold) {\n var fx = options.gravity * dx / d;\n var fy = options.gravity * dy / d;\n node.offsetX += fx;\n node.offsetY += fy; // s += \": Applied force: \" + fx + \", \" + fy;\n } // s += \": skypped since it's too close to center\";\n // logDebug(s);\n\n }\n }\n};\n/**\n * @brief : This function propagates the existing offsets from\n * parent nodes to its descendents.\n * @arg layoutInfo : layoutInfo Object\n * @arg cy : cytoscape Object\n * @arg options : Layout options\n */\n\n\nvar propagateForces = function propagateForces(layoutInfo, options) {\n // Inline implementation of a queue, used for traversing the graph in BFS order\n var queue = [];\n var start = 0; // Points to the start the queue\n\n var end = -1; // Points to the end of the queue\n // logDebug('propagateForces');\n // Start by visiting the nodes in the root graph\n\n queue.push.apply(queue, layoutInfo.graphSet[0]);\n end += layoutInfo.graphSet[0].length; // Traverse the graph, level by level,\n\n while (start <= end) {\n // Get the node to visit and remove it from queue\n var nodeId = queue[start++];\n var nodeIndex = layoutInfo.idToIndex[nodeId];\n var node = layoutInfo.layoutNodes[nodeIndex];\n var children = node.children; // We only need to process the node if it's compound\n\n if (0 < children.length && !node.isLocked) {\n var offX = node.offsetX;\n var offY = node.offsetY; // var s = \"Propagating offset from parent node : \" + node.id +\n // \". OffsetX: \" + offX + \". OffsetY: \" + offY;\n // s += \"\\n Children: \" + children.toString();\n // logDebug(s);\n\n for (var i = 0; i < children.length; i++) {\n var childNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[children[i]]]; // Propagate offset\n\n childNode.offsetX += offX;\n childNode.offsetY += offY; // Add children to queue to be visited\n\n queue[++end] = children[i];\n } // Reset parent offsets\n\n\n node.offsetX = 0;\n node.offsetY = 0;\n }\n }\n};\n/**\n * @brief : Updates the layout model positions, based on\n * the accumulated forces\n */\n\n\nvar updatePositions = function updatePositions(layoutInfo, options) {\n // var s = 'Updating positions';\n // logDebug(s);\n // Reset boundaries for compound nodes\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n\n if (0 < n.children.length) {\n // logDebug(\"Resetting boundaries of compound node: \" + n.id);\n n.maxX = undefined;\n n.minX = undefined;\n n.maxY = undefined;\n n.minY = undefined;\n }\n }\n\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n\n if (0 < n.children.length || n.isLocked) {\n // No need to set compound or locked node position\n // logDebug(\"Skipping position update of node: \" + n.id);\n continue;\n } // s = \"Node: \" + n.id + \" Previous position: (\" +\n // n.positionX + \", \" + n.positionY + \").\";\n // Limit displacement in order to improve stability\n\n\n var tempForce = limitForce(n.offsetX, n.offsetY, layoutInfo.temperature);\n n.positionX += tempForce.x;\n n.positionY += tempForce.y;\n n.offsetX = 0;\n n.offsetY = 0;\n n.minX = n.positionX - n.width;\n n.maxX = n.positionX + n.width;\n n.minY = n.positionY - n.height;\n n.maxY = n.positionY + n.height; // s += \" New Position: (\" + n.positionX + \", \" + n.positionY + \").\";\n // logDebug(s);\n // Update ancestry boudaries\n\n updateAncestryBoundaries(n, layoutInfo);\n } // Update size, position of compund nodes\n\n\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n\n if (0 < n.children.length && !n.isLocked) {\n n.positionX = (n.maxX + n.minX) / 2;\n n.positionY = (n.maxY + n.minY) / 2;\n n.width = n.maxX - n.minX;\n n.height = n.maxY - n.minY; // s = \"Updating position, size of compound node \" + n.id;\n // s += \"\\nPositionX: \" + n.positionX + \", PositionY: \" + n.positionY;\n // s += \"\\nWidth: \" + n.width + \", Height: \" + n.height;\n // logDebug(s);\n }\n }\n};\n/**\n * @brief : Limits a force (forceX, forceY) to be not\n * greater (in modulo) than max.\n 8 Preserves force direction.\n */\n\n\nvar limitForce = function limitForce(forceX, forceY, max) {\n // var s = \"Limiting force: (\" + forceX + \", \" + forceY + \"). Max: \" + max;\n var force = Math.sqrt(forceX * forceX + forceY * forceY);\n\n if (force > max) {\n var res = {\n x: max * forceX / force,\n y: max * forceY / force\n };\n } else {\n var res = {\n x: forceX,\n y: forceY\n };\n } // s += \".\\nResult: (\" + res.x + \", \" + res.y + \")\";\n // logDebug(s);\n\n\n return res;\n};\n/**\n * @brief : Function used for keeping track of compound node\n * sizes, since they should bound all their subnodes.\n */\n\n\nvar updateAncestryBoundaries = function updateAncestryBoundaries(node, layoutInfo) {\n // var s = \"Propagating new position/size of node \" + node.id;\n var parentId = node.parentId;\n\n if (null == parentId) {\n // If there's no parent, we are done\n // s += \". No parent node.\";\n // logDebug(s);\n return;\n } // Get Parent Node\n\n\n var p = layoutInfo.layoutNodes[layoutInfo.idToIndex[parentId]];\n var flag = false; // MaxX\n\n if (null == p.maxX || node.maxX + p.padRight > p.maxX) {\n p.maxX = node.maxX + p.padRight;\n flag = true; // s += \"\\nNew maxX for parent node \" + p.id + \": \" + p.maxX;\n } // MinX\n\n\n if (null == p.minX || node.minX - p.padLeft < p.minX) {\n p.minX = node.minX - p.padLeft;\n flag = true; // s += \"\\nNew minX for parent node \" + p.id + \": \" + p.minX;\n } // MaxY\n\n\n if (null == p.maxY || node.maxY + p.padBottom > p.maxY) {\n p.maxY = node.maxY + p.padBottom;\n flag = true; // s += \"\\nNew maxY for parent node \" + p.id + \": \" + p.maxY;\n } // MinY\n\n\n if (null == p.minY || node.minY - p.padTop < p.minY) {\n p.minY = node.minY - p.padTop;\n flag = true; // s += \"\\nNew minY for parent node \" + p.id + \": \" + p.minY;\n } // If updated boundaries, propagate changes upward\n\n\n if (flag) {\n // logDebug(s);\n return updateAncestryBoundaries(p, layoutInfo);\n } // s += \". No changes in boundaries/position of parent node \" + p.id;\n // logDebug(s);\n\n\n return;\n};\n\nvar separateComponents = function separateComponents(layoutInfo, options) {\n var nodes = layoutInfo.layoutNodes;\n var components = [];\n\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n var cid = node.cmptId;\n var component = components[cid] = components[cid] || [];\n component.push(node);\n }\n\n var totalA = 0;\n\n for (var i = 0; i < components.length; i++) {\n var c = components[i];\n\n if (!c) {\n continue;\n }\n\n c.x1 = Infinity;\n c.x2 = -Infinity;\n c.y1 = Infinity;\n c.y2 = -Infinity;\n\n for (var j = 0; j < c.length; j++) {\n var n = c[j];\n c.x1 = Math.min(c.x1, n.positionX - n.width / 2);\n c.x2 = Math.max(c.x2, n.positionX + n.width / 2);\n c.y1 = Math.min(c.y1, n.positionY - n.height / 2);\n c.y2 = Math.max(c.y2, n.positionY + n.height / 2);\n }\n\n c.w = c.x2 - c.x1;\n c.h = c.y2 - c.y1;\n totalA += c.w * c.h;\n }\n\n components.sort(function (c1, c2) {\n return c2.w * c2.h - c1.w * c1.h;\n });\n var x = 0;\n var y = 0;\n var usedW = 0;\n var rowH = 0;\n var maxRowW = Math.sqrt(totalA) * layoutInfo.clientWidth / layoutInfo.clientHeight;\n\n for (var i = 0; i < components.length; i++) {\n var c = components[i];\n\n if (!c) {\n continue;\n }\n\n for (var j = 0; j < c.length; j++) {\n var n = c[j];\n\n if (!n.isLocked) {\n n.positionX += x - c.x1;\n n.positionY += y - c.y1;\n }\n }\n\n x += c.w + options.componentSpacing;\n usedW += c.w + options.componentSpacing;\n rowH = Math.max(rowH, c.h);\n\n if (usedW > maxRowW) {\n y += rowH + options.componentSpacing;\n x = 0;\n usedW = 0;\n rowH = 0;\n }\n }\n};\n\nvar defaults$d = {\n fit: true,\n // whether to fit the viewport to the graph\n padding: 30,\n // padding used on fit\n boundingBox: undefined,\n // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true,\n // prevents node overlap, may overflow boundingBox if not enough space\n avoidOverlapPadding: 10,\n // extra spacing around nodes when avoidOverlap: true\n nodeDimensionsIncludeLabels: false,\n // Excludes the label when calculating node bounding boxes for the layout algorithm\n spacingFactor: undefined,\n // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up\n condense: false,\n // uses all available space on false, uses minimal space on true\n rows: undefined,\n // force num of rows in the grid\n cols: undefined,\n // force num of columns in the grid\n position: function position(node) {},\n // returns { row, col } for element\n sort: undefined,\n // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n animate: false,\n // whether to transition the node positions\n animationDuration: 500,\n // duration of animation in ms if enabled\n animationEasing: undefined,\n // easing of animation if enabled\n animateFilter: function animateFilter(node, i) {\n return true;\n },\n // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts\n ready: undefined,\n // callback on layoutready\n stop: undefined,\n // callback on layoutstop\n transform: function transform(node, position) {\n return position;\n } // transform a given node position. Useful for changing flow direction in discrete layouts \n\n};\n\nfunction GridLayout(options) {\n this.options = extend({}, defaults$d, options);\n}\n\nGridLayout.prototype.run = function () {\n var params = this.options;\n var options = params;\n var cy = params.cy;\n var eles = options.eles;\n var nodes = eles.nodes().not(':parent');\n\n if (options.sort) {\n nodes = nodes.sort(options.sort);\n }\n\n var bb = makeBoundingBox(options.boundingBox ? options.boundingBox : {\n x1: 0,\n y1: 0,\n w: cy.width(),\n h: cy.height()\n });\n\n if (bb.h === 0 || bb.w === 0) {\n nodes.layoutPositions(this, options, function (ele) {\n return {\n x: bb.x1,\n y: bb.y1\n };\n });\n } else {\n // width/height * splits^2 = cells where splits is number of times to split width\n var cells = nodes.size();\n var splits = Math.sqrt(cells * bb.h / bb.w);\n var rows = Math.round(splits);\n var cols = Math.round(bb.w / bb.h * splits);\n\n var small = function small(val) {\n if (val == null) {\n return Math.min(rows, cols);\n } else {\n var min = Math.min(rows, cols);\n\n if (min == rows) {\n rows = val;\n } else {\n cols = val;\n }\n }\n };\n\n var large = function large(val) {\n if (val == null) {\n return Math.max(rows, cols);\n } else {\n var max = Math.max(rows, cols);\n\n if (max == rows) {\n rows = val;\n } else {\n cols = val;\n }\n }\n };\n\n var oRows = options.rows;\n var oCols = options.cols != null ? options.cols : options.columns; // if rows or columns were set in options, use those values\n\n if (oRows != null && oCols != null) {\n rows = oRows;\n cols = oCols;\n } else if (oRows != null && oCols == null) {\n rows = oRows;\n cols = Math.ceil(cells / rows);\n } else if (oRows == null && oCols != null) {\n cols = oCols;\n rows = Math.ceil(cells / cols);\n } // otherwise use the automatic values and adjust accordingly\n // if rounding was up, see if we can reduce rows or columns\n else if (cols * rows > cells) {\n var sm = small();\n var lg = large(); // reducing the small side takes away the most cells, so try it first\n\n if ((sm - 1) * lg >= cells) {\n small(sm - 1);\n } else if ((lg - 1) * sm >= cells) {\n large(lg - 1);\n }\n } else {\n // if rounding was too low, add rows or columns\n while (cols * rows < cells) {\n var _sm = small();\n\n var _lg = large(); // try to add to larger side first (adds less in multiplication)\n\n\n if ((_lg + 1) * _sm >= cells) {\n large(_lg + 1);\n } else {\n small(_sm + 1);\n }\n }\n }\n\n var cellWidth = bb.w / cols;\n var cellHeight = bb.h / rows;\n\n if (options.condense) {\n cellWidth = 0;\n cellHeight = 0;\n }\n\n if (options.avoidOverlap) {\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n var pos = node._private.position;\n\n if (pos.x == null || pos.y == null) {\n // for bb\n pos.x = 0;\n pos.y = 0;\n }\n\n var nbb = node.layoutDimensions(options);\n var p = options.avoidOverlapPadding;\n var w = nbb.w + p;\n var h = nbb.h + p;\n cellWidth = Math.max(cellWidth, w);\n cellHeight = Math.max(cellHeight, h);\n }\n }\n\n var cellUsed = {}; // e.g. 'c-0-2' => true\n\n var used = function used(row, col) {\n return cellUsed['c-' + row + '-' + col] ? true : false;\n };\n\n var use = function use(row, col) {\n cellUsed['c-' + row + '-' + col] = true;\n }; // to keep track of current cell position\n\n\n var row = 0;\n var col = 0;\n\n var moveToNextCell = function moveToNextCell() {\n col++;\n\n if (col >= cols) {\n col = 0;\n row++;\n }\n }; // get a cache of all the manual positions\n\n\n var id2manPos = {};\n\n for (var _i = 0; _i < nodes.length; _i++) {\n var _node = nodes[_i];\n var rcPos = options.position(_node);\n\n if (rcPos && (rcPos.row !== undefined || rcPos.col !== undefined)) {\n // must have at least row or col def'd\n var _pos = {\n row: rcPos.row,\n col: rcPos.col\n };\n\n if (_pos.col === undefined) {\n // find unused col\n _pos.col = 0;\n\n while (used(_pos.row, _pos.col)) {\n _pos.col++;\n }\n } else if (_pos.row === undefined) {\n // find unused row\n _pos.row = 0;\n\n while (used(_pos.row, _pos.col)) {\n _pos.row++;\n }\n }\n\n id2manPos[_node.id()] = _pos;\n use(_pos.row, _pos.col);\n }\n }\n\n var getPos = function getPos(element, i) {\n var x, y;\n\n if (element.locked() || element.isParent()) {\n return false;\n } // see if we have a manual position set\n\n\n var rcPos = id2manPos[element.id()];\n\n if (rcPos) {\n x = rcPos.col * cellWidth + cellWidth / 2 + bb.x1;\n y = rcPos.row * cellHeight + cellHeight / 2 + bb.y1;\n } else {\n // otherwise set automatically\n while (used(row, col)) {\n moveToNextCell();\n }\n\n x = col * cellWidth + cellWidth / 2 + bb.x1;\n y = row * cellHeight + cellHeight / 2 + bb.y1;\n use(row, col);\n moveToNextCell();\n }\n\n return {\n x: x,\n y: y\n };\n };\n\n nodes.layoutPositions(this, options, getPos);\n }\n\n return this; // chaining\n};\n\nvar defaults$e = {\n ready: function ready() {},\n // on layoutready\n stop: function stop() {} // on layoutstop\n\n}; // constructor\n// options : object containing layout options\n\nfunction NullLayout(options) {\n this.options = extend({}, defaults$e, options);\n} // runs the layout\n\n\nNullLayout.prototype.run = function () {\n var options = this.options;\n var eles = options.eles; // elements to consider in the layout\n\n var layout = this; // cy is automatically populated for us in the constructor\n // (disable eslint for next line as this serves as example layout code to external developers)\n // eslint-disable-next-line no-unused-vars\n\n var cy = options.cy;\n layout.emit('layoutstart'); // puts all nodes at (0, 0)\n // n.b. most layouts would use layoutPositions(), instead of positions() and manual events\n\n eles.nodes().positions(function () {\n return {\n x: 0,\n y: 0\n };\n }); // trigger layoutready when each node has had its position set at least once\n\n layout.one('layoutready', options.ready);\n layout.emit('layoutready'); // trigger layoutstop when the layout stops (e.g. finishes)\n\n layout.one('layoutstop', options.stop);\n layout.emit('layoutstop');\n return this; // chaining\n}; // called on continuous layouts to stop them before they finish\n\n\nNullLayout.prototype.stop = function () {\n return this; // chaining\n};\n\nvar defaults$f = {\n positions: undefined,\n // map of (node id) => (position obj); or function(node){ return somPos; }\n zoom: undefined,\n // the zoom level to set (prob want fit = false if set)\n pan: undefined,\n // the pan level to set (prob want fit = false if set)\n fit: true,\n // whether to fit to viewport\n padding: 30,\n // padding on fit\n animate: false,\n // whether to transition the node positions\n animationDuration: 500,\n // duration of animation in ms if enabled\n animationEasing: undefined,\n // easing of animation if enabled\n animateFilter: function animateFilter(node, i) {\n return true;\n },\n // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts\n ready: undefined,\n // callback on layoutready\n stop: undefined,\n // callback on layoutstop\n transform: function transform(node, position) {\n return position;\n } // transform a given node position. Useful for changing flow direction in discrete layouts\n\n};\n\nfunction PresetLayout(options) {\n this.options = extend({}, defaults$f, options);\n}\n\nPresetLayout.prototype.run = function () {\n var options = this.options;\n var eles = options.eles;\n var nodes = eles.nodes();\n var posIsFn = fn(options.positions);\n\n function getPosition(node) {\n if (options.positions == null) {\n return copyPosition(node.position());\n }\n\n if (posIsFn) {\n return options.positions(node);\n }\n\n var pos = options.positions[node._private.data.id];\n\n if (pos == null) {\n return null;\n }\n\n return pos;\n }\n\n nodes.layoutPositions(this, options, function (node, i) {\n var position = getPosition(node);\n\n if (node.locked() || position == null) {\n return false;\n }\n\n return position;\n });\n return this; // chaining\n};\n\nvar defaults$g = {\n fit: true,\n // whether to fit to viewport\n padding: 30,\n // fit padding\n boundingBox: undefined,\n // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n animate: false,\n // whether to transition the node positions\n animationDuration: 500,\n // duration of animation in ms if enabled\n animationEasing: undefined,\n // easing of animation if enabled\n animateFilter: function animateFilter(node, i) {\n return true;\n },\n // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts\n ready: undefined,\n // callback on layoutready\n stop: undefined,\n // callback on layoutstop\n transform: function transform(node, position) {\n return position;\n } // transform a given node position. Useful for changing flow direction in discrete layouts \n\n};\n\nfunction RandomLayout(options) {\n this.options = extend({}, defaults$g, options);\n}\n\nRandomLayout.prototype.run = function () {\n var options = this.options;\n var cy = options.cy;\n var eles = options.eles;\n var nodes = eles.nodes().not(':parent');\n var bb = makeBoundingBox(options.boundingBox ? options.boundingBox : {\n x1: 0,\n y1: 0,\n w: cy.width(),\n h: cy.height()\n });\n\n var getPos = function getPos(node, i) {\n return {\n x: bb.x1 + Math.round(Math.random() * bb.w),\n y: bb.y1 + Math.round(Math.random() * bb.h)\n };\n };\n\n nodes.layoutPositions(this, options, getPos);\n return this; // chaining\n};\n\nvar layout = [{\n name: 'breadthfirst',\n impl: BreadthFirstLayout\n}, {\n name: 'circle',\n impl: CircleLayout\n}, {\n name: 'concentric',\n impl: ConcentricLayout\n}, {\n name: 'cose',\n impl: CoseLayout\n}, {\n name: 'grid',\n impl: GridLayout\n}, {\n name: 'null',\n impl: NullLayout\n}, {\n name: 'preset',\n impl: PresetLayout\n}, {\n name: 'random',\n impl: RandomLayout\n}];\n\nfunction NullRenderer(options) {\n this.options = options;\n this.notifications = 0; // for testing\n}\n\nvar noop$1 = function noop() {};\n\nvar throwImgErr = function throwImgErr() {\n throw new Error('A headless instance can not render images');\n};\n\nNullRenderer.prototype = {\n recalculateRenderedStyle: noop$1,\n notify: function notify() {\n this.notifications++;\n },\n init: noop$1,\n isHeadless: function isHeadless() {\n return true;\n },\n png: throwImgErr,\n jpg: throwImgErr\n};\n\nvar BRp = {};\nBRp.arrowShapeWidth = 0.3;\n\nBRp.registerArrowShapes = function () {\n var arrowShapes = this.arrowShapes = {};\n var renderer = this; // Contract for arrow shapes:\n // 0, 0 is arrow tip\n // (0, 1) is direction towards node\n // (1, 0) is right\n //\n // functional api:\n // collide: check x, y in shape\n // roughCollide: called before collide, no false negatives\n // draw: draw\n // spacing: dist(arrowTip, nodeBoundary)\n // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip\n\n var bbCollide = function bbCollide(x, y, size, angle, translation, edgeWidth, padding) {\n var x1 = translation.x - size / 2 - padding;\n var x2 = translation.x + size / 2 + padding;\n var y1 = translation.y - size / 2 - padding;\n var y2 = translation.y + size / 2 + padding;\n var inside = x1 <= x && x <= x2 && y1 <= y && y <= y2;\n return inside;\n };\n\n var transform = function transform(x, y, size, angle, translation) {\n var xRotated = x * Math.cos(angle) - y * Math.sin(angle);\n var yRotated = x * Math.sin(angle) + y * Math.cos(angle);\n var xScaled = xRotated * size;\n var yScaled = yRotated * size;\n var xTranslated = xScaled + translation.x;\n var yTranslated = yScaled + translation.y;\n return {\n x: xTranslated,\n y: yTranslated\n };\n };\n\n var transformPoints = function transformPoints(pts, size, angle, translation) {\n var retPts = [];\n\n for (var i = 0; i < pts.length; i += 2) {\n var x = pts[i];\n var y = pts[i + 1];\n retPts.push(transform(x, y, size, angle, translation));\n }\n\n return retPts;\n };\n\n var pointsToArr = function pointsToArr(pts) {\n var ret = [];\n\n for (var i = 0; i < pts.length; i++) {\n var p = pts[i];\n ret.push(p.x, p.y);\n }\n\n return ret;\n };\n\n var standardGap = function standardGap(edge) {\n return edge.pstyle('width').pfValue * edge.pstyle('arrow-scale').pfValue * 2;\n };\n\n var defineArrowShape = function defineArrowShape(name, defn) {\n if (string(defn)) {\n defn = arrowShapes[defn];\n }\n\n arrowShapes[name] = extend({\n name: name,\n points: [-0.15, -0.3, 0.15, -0.3, 0.15, 0.3, -0.15, 0.3],\n collide: function collide(x, y, size, angle, translation, padding) {\n var points = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation));\n var inside = pointInsidePolygonPoints(x, y, points);\n return inside;\n },\n roughCollide: bbCollide,\n draw: function draw(context, size, angle, translation) {\n var points = transformPoints(this.points, size, angle, translation);\n renderer.arrowShapeImpl('polygon')(context, points);\n },\n spacing: function spacing(edge) {\n return 0;\n },\n gap: standardGap\n }, defn);\n };\n\n defineArrowShape('none', {\n collide: falsify,\n roughCollide: falsify,\n draw: noop,\n spacing: zeroify,\n gap: zeroify\n });\n defineArrowShape('triangle', {\n points: [-0.15, -0.3, 0, 0, 0.15, -0.3]\n });\n defineArrowShape('arrow', 'triangle');\n defineArrowShape('triangle-backcurve', {\n points: arrowShapes['triangle'].points,\n controlPoint: [0, -0.15],\n roughCollide: bbCollide,\n draw: function draw(context, size, angle, translation, edgeWidth) {\n var ptsTrans = transformPoints(this.points, size, angle, translation);\n var ctrlPt = this.controlPoint;\n var ctrlPtTrans = transform(ctrlPt[0], ctrlPt[1], size, angle, translation);\n renderer.arrowShapeImpl(this.name)(context, ptsTrans, ctrlPtTrans);\n },\n gap: function gap(edge) {\n return standardGap(edge) * 0.8;\n }\n });\n defineArrowShape('triangle-tee', {\n points: [0, 0, 0.15, -0.3, -0.15, -0.3, 0, 0],\n pointsTee: [-0.15, -0.4, -0.15, -0.5, 0.15, -0.5, 0.15, -0.4],\n collide: function collide(x, y, size, angle, translation, edgeWidth, padding) {\n var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation));\n var teePts = pointsToArr(transformPoints(this.pointsTee, size + 2 * padding, angle, translation));\n var inside = pointInsidePolygonPoints(x, y, triPts) || pointInsidePolygonPoints(x, y, teePts);\n return inside;\n },\n draw: function draw(context, size, angle, translation, edgeWidth) {\n var triPts = transformPoints(this.points, size, angle, translation);\n var teePts = transformPoints(this.pointsTee, size, angle, translation);\n renderer.arrowShapeImpl(this.name)(context, triPts, teePts);\n }\n });\n defineArrowShape('circle-triangle', {\n radius: 0.15,\n pointsTr: [0, -0.15, 0.15, -0.45, -0.15, -0.45, 0, -0.15],\n collide: function collide(x, y, size, angle, translation, edgeWidth, padding) {\n var t = translation;\n var circleInside = Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2 * padding) * this.radius, 2);\n var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation));\n return pointInsidePolygonPoints(x, y, triPts) || circleInside;\n },\n draw: function draw(context, size, angle, translation, edgeWidth) {\n var triPts = transformPoints(this.pointsTr, size, angle, translation);\n renderer.arrowShapeImpl(this.name)(context, triPts, translation.x, translation.y, this.radius * size);\n },\n spacing: function spacing(edge) {\n return renderer.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.radius;\n }\n });\n defineArrowShape('triangle-cross', {\n points: [0, 0, 0.15, -0.3, -0.15, -0.3, 0, 0],\n baseCrossLinePts: [-0.15, -0.4, // first half of the rectangle\n -0.15, -0.4, 0.15, -0.4, // second half of the rectangle\n 0.15, -0.4],\n crossLinePts: function crossLinePts(size, edgeWidth) {\n // shift points so that the distance between the cross points matches edge width\n var p = this.baseCrossLinePts.slice();\n var shiftFactor = edgeWidth / size;\n var y0 = 3;\n var y1 = 5;\n p[y0] = p[y0] - shiftFactor;\n p[y1] = p[y1] - shiftFactor;\n return p;\n },\n collide: function collide(x, y, size, angle, translation, edgeWidth, padding) {\n var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation));\n var teePts = pointsToArr(transformPoints(this.crossLinePts(size, edgeWidth), size + 2 * padding, angle, translation));\n var inside = pointInsidePolygonPoints(x, y, triPts) || pointInsidePolygonPoints(x, y, teePts);\n return inside;\n },\n draw: function draw(context, size, angle, translation, edgeWidth) {\n var triPts = transformPoints(this.points, size, angle, translation);\n var crossLinePts = transformPoints(this.crossLinePts(size, edgeWidth), size, angle, translation);\n renderer.arrowShapeImpl(this.name)(context, triPts, crossLinePts);\n }\n });\n defineArrowShape('vee', {\n points: [-0.15, -0.3, 0, 0, 0.15, -0.3, 0, -0.15],\n gap: function gap(edge) {\n return standardGap(edge) * 0.525;\n }\n });\n defineArrowShape('circle', {\n radius: 0.15,\n collide: function collide(x, y, size, angle, translation, edgeWidth, padding) {\n var t = translation;\n var inside = Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2 * padding) * this.radius, 2);\n return inside;\n },\n draw: function draw(context, size, angle, translation, edgeWidth) {\n renderer.arrowShapeImpl(this.name)(context, translation.x, translation.y, this.radius * size);\n },\n spacing: function spacing(edge) {\n return renderer.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.radius;\n }\n });\n defineArrowShape('tee', {\n points: [-0.15, 0, -0.15, -0.1, 0.15, -0.1, 0.15, 0],\n spacing: function spacing(edge) {\n return 1;\n },\n gap: function gap(edge) {\n return 1;\n }\n });\n defineArrowShape('square', {\n points: [-0.15, 0.00, 0.15, 0.00, 0.15, -0.3, -0.15, -0.3]\n });\n defineArrowShape('diamond', {\n points: [-0.15, -0.15, 0, -0.3, 0.15, -0.15, 0, 0],\n gap: function gap(edge) {\n return edge.pstyle('width').pfValue * edge.pstyle('arrow-scale').value;\n }\n });\n defineArrowShape('chevron', {\n points: [0, 0, -0.15, -0.15, -0.1, -0.2, 0, -0.1, 0.1, -0.2, 0.15, -0.15],\n gap: function gap(edge) {\n return 0.95 * edge.pstyle('width').pfValue * edge.pstyle('arrow-scale').value;\n }\n });\n};\n\nvar BRp$1 = {}; // Project mouse\n\nBRp$1.projectIntoViewport = function (clientX, clientY) {\n var cy = this.cy;\n var offsets = this.findContainerClientCoords();\n var offsetLeft = offsets[0];\n var offsetTop = offsets[1];\n var scale = offsets[4];\n var pan = cy.pan();\n var zoom = cy.zoom();\n var x = ((clientX - offsetLeft) / scale - pan.x) / zoom;\n var y = ((clientY - offsetTop) / scale - pan.y) / zoom;\n return [x, y];\n};\n\nBRp$1.findContainerClientCoords = function () {\n if (this.containerBB) {\n return this.containerBB;\n }\n\n var container = this.container;\n var rect = container.getBoundingClientRect();\n var style = window$1.getComputedStyle(container);\n\n var styleValue = function styleValue(name) {\n return parseFloat(style.getPropertyValue(name));\n };\n\n var padding = {\n left: styleValue('padding-left'),\n right: styleValue('padding-right'),\n top: styleValue('padding-top'),\n bottom: styleValue('padding-bottom')\n };\n var border = {\n left: styleValue('border-left-width'),\n right: styleValue('border-right-width'),\n top: styleValue('border-top-width'),\n bottom: styleValue('border-bottom-width')\n };\n var clientWidth = container.clientWidth;\n var clientHeight = container.clientHeight;\n var paddingHor = padding.left + padding.right;\n var paddingVer = padding.top + padding.bottom;\n var borderHor = border.left + border.right;\n var scale = rect.width / (clientWidth + borderHor);\n var unscaledW = clientWidth - paddingHor;\n var unscaledH = clientHeight - paddingVer;\n var left = rect.left + padding.left + border.left;\n var top = rect.top + padding.top + border.top;\n return this.containerBB = [left, top, unscaledW, unscaledH, scale];\n};\n\nBRp$1.invalidateContainerClientCoordsCache = function () {\n this.containerBB = null;\n};\n\nBRp$1.findNearestElement = function (x, y, interactiveElementsOnly, isTouch) {\n return this.findNearestElements(x, y, interactiveElementsOnly, isTouch)[0];\n};\n\nBRp$1.findNearestElements = function (x, y, interactiveElementsOnly, isTouch) {\n var self = this;\n var r = this;\n var eles = r.getCachedZSortedEles();\n var near = []; // 1 node max, 1 edge max\n\n var zoom = r.cy.zoom();\n var hasCompounds = r.cy.hasCompoundNodes();\n var edgeThreshold = (isTouch ? 24 : 8) / zoom;\n var nodeThreshold = (isTouch ? 8 : 2) / zoom;\n var labelThreshold = (isTouch ? 8 : 2) / zoom;\n var minSqDist = Infinity;\n var nearEdge;\n var nearNode;\n\n if (interactiveElementsOnly) {\n eles = eles.interactive;\n }\n\n function addEle(ele, sqDist) {\n if (ele.isNode()) {\n if (nearNode) {\n return; // can't replace node\n } else {\n nearNode = ele;\n near.push(ele);\n }\n }\n\n if (ele.isEdge() && (sqDist == null || sqDist < minSqDist)) {\n if (nearEdge) {\n // then replace existing edge\n // can replace only if same z-index\n if (nearEdge.pstyle('z-compound-depth').value === ele.pstyle('z-compound-depth').value && nearEdge.pstyle('z-compound-depth').value === ele.pstyle('z-compound-depth').value) {\n for (var i = 0; i < near.length; i++) {\n if (near[i].isEdge()) {\n near[i] = ele;\n nearEdge = ele;\n minSqDist = sqDist != null ? sqDist : minSqDist;\n break;\n }\n }\n }\n } else {\n near.push(ele);\n nearEdge = ele;\n minSqDist = sqDist != null ? sqDist : minSqDist;\n }\n }\n }\n\n function checkNode(node) {\n var width = node.outerWidth() + 2 * nodeThreshold;\n var height = node.outerHeight() + 2 * nodeThreshold;\n var hw = width / 2;\n var hh = height / 2;\n var pos = node.position();\n\n if (pos.x - hw <= x && x <= pos.x + hw // bb check x\n && pos.y - hh <= y && y <= pos.y + hh // bb check y\n ) {\n var shape = r.nodeShapes[self.getNodeShape(node)];\n\n if (shape.checkPoint(x, y, 0, width, height, pos.x, pos.y)) {\n addEle(node, 0);\n return true;\n }\n }\n }\n\n function checkEdge(edge) {\n var _p = edge._private;\n var rs = _p.rscratch;\n var styleWidth = edge.pstyle('width').pfValue;\n var scale = edge.pstyle('arrow-scale').value;\n var width = styleWidth / 2 + edgeThreshold; // more like a distance radius from centre\n\n var widthSq = width * width;\n var width2 = width * 2;\n var src = _p.source;\n var tgt = _p.target;\n var sqDist;\n\n if (rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack') {\n var pts = rs.allpts;\n\n for (var i = 0; i + 3 < pts.length; i += 2) {\n if (inLineVicinity(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], width2) && widthSq > (sqDist = sqdistToFiniteLine(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3]))) {\n addEle(edge, sqDist);\n return true;\n }\n }\n } else if (rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound') {\n var pts = rs.allpts;\n\n for (var i = 0; i + 5 < rs.allpts.length; i += 4) {\n if (inBezierVicinity(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], pts[i + 5], width2) && widthSq > (sqDist = sqdistToQuadraticBezier(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], pts[i + 5]))) {\n addEle(edge, sqDist);\n return true;\n }\n }\n } // if we're close to the edge but didn't hit it, maybe we hit its arrows\n\n\n var src = src || _p.source;\n var tgt = tgt || _p.target;\n var arSize = self.getArrowWidth(styleWidth, scale);\n var arrows = [{\n name: 'source',\n x: rs.arrowStartX,\n y: rs.arrowStartY,\n angle: rs.srcArrowAngle\n }, {\n name: 'target',\n x: rs.arrowEndX,\n y: rs.arrowEndY,\n angle: rs.tgtArrowAngle\n }, {\n name: 'mid-source',\n x: rs.midX,\n y: rs.midY,\n angle: rs.midsrcArrowAngle\n }, {\n name: 'mid-target',\n x: rs.midX,\n y: rs.midY,\n angle: rs.midtgtArrowAngle\n }];\n\n for (var i = 0; i < arrows.length; i++) {\n var ar = arrows[i];\n var shape = r.arrowShapes[edge.pstyle(ar.name + '-arrow-shape').value];\n var edgeWidth = edge.pstyle('width').pfValue;\n\n if (shape.roughCollide(x, y, arSize, ar.angle, {\n x: ar.x,\n y: ar.y\n }, edgeWidth, edgeThreshold) && shape.collide(x, y, arSize, ar.angle, {\n x: ar.x,\n y: ar.y\n }, edgeWidth, edgeThreshold)) {\n addEle(edge);\n return true;\n }\n } // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence)\n\n\n if (hasCompounds && near.length > 0) {\n checkNode(src);\n checkNode(tgt);\n }\n }\n\n function preprop(obj, name, pre) {\n return getPrefixedProperty(obj, name, pre);\n }\n\n function checkLabel(ele, prefix) {\n var _p = ele._private;\n var th = labelThreshold;\n var prefixDash;\n\n if (prefix) {\n prefixDash = prefix + '-';\n } else {\n prefixDash = '';\n }\n\n ele.boundingBox();\n var bb = _p.labelBounds[prefix || 'main'];\n var text = ele.pstyle(prefixDash + 'label').value;\n var eventsEnabled = ele.pstyle('text-events').strValue === 'yes';\n\n if (!eventsEnabled || !text) {\n return;\n }\n\n var rstyle = _p.rstyle;\n var lx = preprop(rstyle, 'labelX', prefix);\n var ly = preprop(rstyle, 'labelY', prefix);\n var theta = preprop(_p.rscratch, 'labelAngle', prefix);\n var lx1 = bb.x1 - th;\n var lx2 = bb.x2 + th;\n var ly1 = bb.y1 - th;\n var ly2 = bb.y2 + th;\n\n if (theta) {\n var cos = Math.cos(theta);\n var sin = Math.sin(theta);\n\n var rotate = function rotate(x, y) {\n x = x - lx;\n y = y - ly;\n return {\n x: x * cos - y * sin + lx,\n y: x * sin + y * cos + ly\n };\n };\n\n var px1y1 = rotate(lx1, ly1);\n var px1y2 = rotate(lx1, ly2);\n var px2y1 = rotate(lx2, ly1);\n var px2y2 = rotate(lx2, ly2);\n var points = [px1y1.x, px1y1.y, px2y1.x, px2y1.y, px2y2.x, px2y2.y, px1y2.x, px1y2.y];\n\n if (pointInsidePolygonPoints(x, y, points)) {\n addEle(ele);\n return true;\n }\n } else {\n // do a cheaper bb check\n if (inBoundingBox(bb, x, y)) {\n addEle(ele);\n return true;\n }\n }\n }\n\n for (var i = eles.length - 1; i >= 0; i--) {\n // reverse order for precedence\n var ele = eles[i];\n\n if (ele.isNode()) {\n checkNode(ele) || checkLabel(ele);\n } else {\n // then edge\n checkEdge(ele) || checkLabel(ele) || checkLabel(ele, 'source') || checkLabel(ele, 'target');\n }\n }\n\n return near;\n}; // 'Give me everything from this box'\n\n\nBRp$1.getAllInBox = function (x1, y1, x2, y2) {\n var eles = this.getCachedZSortedEles().interactive;\n var box = [];\n var x1c = Math.min(x1, x2);\n var x2c = Math.max(x1, x2);\n var y1c = Math.min(y1, y2);\n var y2c = Math.max(y1, y2);\n x1 = x1c;\n x2 = x2c;\n y1 = y1c;\n y2 = y2c;\n var boxBb = makeBoundingBox({\n x1: x1,\n y1: y1,\n x2: x2,\n y2: y2\n });\n\n for (var e = 0; e < eles.length; e++) {\n var ele = eles[e];\n\n if (ele.isNode()) {\n var node = ele;\n var nodeBb = node.boundingBox({\n includeNodes: true,\n includeEdges: false,\n includeLabels: false\n });\n\n if (boundingBoxesIntersect(boxBb, nodeBb) && !boundingBoxInBoundingBox(nodeBb, boxBb)) {\n box.push(node);\n }\n } else {\n var edge = ele;\n var _p = edge._private;\n var rs = _p.rscratch;\n\n if (rs.startX != null && rs.startY != null && !inBoundingBox(boxBb, rs.startX, rs.startY)) {\n continue;\n }\n\n if (rs.endX != null && rs.endY != null && !inBoundingBox(boxBb, rs.endX, rs.endY)) {\n continue;\n }\n\n if (rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack') {\n var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts;\n var allInside = true;\n\n for (var i = 0; i < pts.length; i++) {\n if (!pointInBoundingBox(boxBb, pts[i])) {\n allInside = false;\n break;\n }\n }\n\n if (allInside) {\n box.push(edge);\n }\n } else if (rs.edgeType === 'haystack' || rs.edgeType === 'straight') {\n box.push(edge);\n }\n }\n }\n\n return box;\n};\n\nvar BRp$2 = {};\n\nBRp$2.calculateArrowAngles = function (edge) {\n var rs = edge._private.rscratch;\n var isHaystack = rs.edgeType === 'haystack';\n var isBezier = rs.edgeType === 'bezier';\n var isMultibezier = rs.edgeType === 'multibezier';\n var isSegments = rs.edgeType === 'segments';\n var isCompound = rs.edgeType === 'compound';\n var isSelf = rs.edgeType === 'self'; // Displacement gives direction for arrowhead orientation\n\n var dispX, dispY;\n var startX, startY, endX, endY, midX, midY;\n\n if (isHaystack) {\n startX = rs.haystackPts[0];\n startY = rs.haystackPts[1];\n endX = rs.haystackPts[2];\n endY = rs.haystackPts[3];\n } else {\n startX = rs.arrowStartX;\n startY = rs.arrowStartY;\n endX = rs.arrowEndX;\n endY = rs.arrowEndY;\n }\n\n midX = rs.midX;\n midY = rs.midY; // source\n //\n\n if (isSegments) {\n dispX = startX - rs.segpts[0];\n dispY = startY - rs.segpts[1];\n } else if (isMultibezier || isCompound || isSelf || isBezier) {\n var pts = rs.allpts;\n var bX = qbezierAt(pts[0], pts[2], pts[4], 0.1);\n var bY = qbezierAt(pts[1], pts[3], pts[5], 0.1);\n dispX = startX - bX;\n dispY = startY - bY;\n } else {\n dispX = startX - midX;\n dispY = startY - midY;\n }\n\n rs.srcArrowAngle = getAngleFromDisp(dispX, dispY); // mid target\n //\n\n var midX = rs.midX;\n var midY = rs.midY;\n\n if (isHaystack) {\n midX = (startX + endX) / 2;\n midY = (startY + endY) / 2;\n }\n\n dispX = endX - startX;\n dispY = endY - startY;\n\n if (isSegments) {\n var pts = rs.allpts;\n\n if (pts.length / 2 % 2 === 0) {\n var i2 = pts.length / 2;\n var i1 = i2 - 2;\n dispX = pts[i2] - pts[i1];\n dispY = pts[i2 + 1] - pts[i1 + 1];\n } else {\n var i2 = pts.length / 2 - 1;\n var i1 = i2 - 2;\n var i3 = i2 + 2;\n dispX = pts[i2] - pts[i1];\n dispY = pts[i2 + 1] - pts[i1 + 1];\n }\n } else if (isMultibezier || isCompound || isSelf) {\n var pts = rs.allpts;\n var cpts = rs.ctrlpts;\n var bp0x, bp0y;\n var bp1x, bp1y;\n\n if (cpts.length / 2 % 2 === 0) {\n var p0 = pts.length / 2 - 1; // startpt\n\n var ic = p0 + 2;\n var p1 = ic + 2;\n bp0x = qbezierAt(pts[p0], pts[ic], pts[p1], 0.0);\n bp0y = qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.0);\n bp1x = qbezierAt(pts[p0], pts[ic], pts[p1], 0.0001);\n bp1y = qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.0001);\n } else {\n var ic = pts.length / 2 - 1; // ctrpt\n\n var p0 = ic - 2; // startpt\n\n var p1 = ic + 2; // endpt\n\n bp0x = qbezierAt(pts[p0], pts[ic], pts[p1], 0.4999);\n bp0y = qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.4999);\n bp1x = qbezierAt(pts[p0], pts[ic], pts[p1], 0.5);\n bp1y = qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.5);\n }\n\n dispX = bp1x - bp0x;\n dispY = bp1y - bp0y;\n }\n\n rs.midtgtArrowAngle = getAngleFromDisp(dispX, dispY);\n rs.midDispX = dispX;\n rs.midDispY = dispY; // mid source\n //\n\n dispX *= -1;\n dispY *= -1;\n\n if (isSegments) {\n var pts = rs.allpts;\n\n if (pts.length / 2 % 2 === 0) ; else {\n var i2 = pts.length / 2 - 1;\n var i3 = i2 + 2;\n dispX = -(pts[i3] - pts[i2]);\n dispY = -(pts[i3 + 1] - pts[i2 + 1]);\n }\n }\n\n rs.midsrcArrowAngle = getAngleFromDisp(dispX, dispY); // target\n //\n\n if (isSegments) {\n dispX = endX - rs.segpts[rs.segpts.length - 2];\n dispY = endY - rs.segpts[rs.segpts.length - 1];\n } else if (isMultibezier || isCompound || isSelf || isBezier) {\n var pts = rs.allpts;\n var l = pts.length;\n var bX = qbezierAt(pts[l - 6], pts[l - 4], pts[l - 2], 0.9);\n var bY = qbezierAt(pts[l - 5], pts[l - 3], pts[l - 1], 0.9);\n dispX = endX - bX;\n dispY = endY - bY;\n } else {\n dispX = endX - midX;\n dispY = endY - midY;\n }\n\n rs.tgtArrowAngle = getAngleFromDisp(dispX, dispY);\n};\n\nBRp$2.getArrowWidth = BRp$2.getArrowHeight = function (edgeWidth, scale) {\n var cache = this.arrowWidthCache = this.arrowWidthCache || {};\n var cachedVal = cache[edgeWidth + ', ' + scale];\n\n if (cachedVal) {\n return cachedVal;\n }\n\n cachedVal = Math.max(Math.pow(edgeWidth * 13.37, 0.9), 29) * scale;\n cache[edgeWidth + ', ' + scale] = cachedVal;\n return cachedVal;\n};\n\nvar BRp$3 = {};\n\nBRp$3.findHaystackPoints = function (edges) {\n for (var i = 0; i < edges.length; i++) {\n var edge = edges[i];\n var _p = edge._private;\n var rs = _p.rscratch;\n\n if (!rs.haystack) {\n var angle = Math.random() * 2 * Math.PI;\n rs.source = {\n x: Math.cos(angle),\n y: Math.sin(angle)\n };\n angle = Math.random() * 2 * Math.PI;\n rs.target = {\n x: Math.cos(angle),\n y: Math.sin(angle)\n };\n }\n\n var src = _p.source;\n var tgt = _p.target;\n var srcPos = src.position();\n var tgtPos = tgt.position();\n var srcW = src.width();\n var tgtW = tgt.width();\n var srcH = src.height();\n var tgtH = tgt.height();\n var radius = edge.pstyle('haystack-radius').value;\n var halfRadius = radius / 2; // b/c have to half width/height\n\n rs.haystackPts = rs.allpts = [rs.source.x * srcW * halfRadius + srcPos.x, rs.source.y * srcH * halfRadius + srcPos.y, rs.target.x * tgtW * halfRadius + tgtPos.x, rs.target.y * tgtH * halfRadius + tgtPos.y];\n rs.midX = (rs.allpts[0] + rs.allpts[2]) / 2;\n rs.midY = (rs.allpts[1] + rs.allpts[3]) / 2; // always override as haystack in case set to different type previously\n\n rs.edgeType = 'haystack';\n rs.haystack = true;\n this.storeEdgeProjections(edge);\n this.calculateArrowAngles(edge);\n this.recalculateEdgeLabelProjections(edge);\n this.calculateLabelAngles(edge);\n }\n};\n\nBRp$3.findSegmentsPoints = function (edge, pairInfo) {\n // Segments (multiple straight lines)\n var rs = edge._private.rscratch;\n var posPts = pairInfo.posPts,\n intersectionPts = pairInfo.intersectionPts,\n vectorNormInverse = pairInfo.vectorNormInverse;\n var edgeDistances = edge.pstyle('edge-distances').value;\n var segmentWs = edge.pstyle('segment-weights');\n var segmentDs = edge.pstyle('segment-distances');\n var segmentsN = Math.min(segmentWs.pfValue.length, segmentDs.pfValue.length);\n rs.edgeType = 'segments';\n rs.segpts = [];\n\n for (var s = 0; s < segmentsN; s++) {\n var w = segmentWs.pfValue[s];\n var d = segmentDs.pfValue[s];\n var w1 = 1 - w;\n var w2 = w;\n var midptPts = edgeDistances === 'node-position' ? posPts : intersectionPts;\n var adjustedMidpt = {\n x: midptPts.x1 * w1 + midptPts.x2 * w2,\n y: midptPts.y1 * w1 + midptPts.y2 * w2\n };\n rs.segpts.push(adjustedMidpt.x + vectorNormInverse.x * d, adjustedMidpt.y + vectorNormInverse.y * d);\n }\n};\n\nBRp$3.findLoopPoints = function (edge, pairInfo, i, edgeIsUnbundled) {\n // Self-edge\n var rs = edge._private.rscratch;\n var dirCounts = pairInfo.dirCounts,\n srcPos = pairInfo.srcPos;\n var ctrlptDists = edge.pstyle('control-point-distances');\n var ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[0] : undefined;\n var loopDir = edge.pstyle('loop-direction').pfValue;\n var loopSwp = edge.pstyle('loop-sweep').pfValue;\n var stepSize = edge.pstyle('control-point-step-size').pfValue;\n rs.edgeType = 'self';\n var j = i;\n var loopDist = stepSize;\n\n if (edgeIsUnbundled) {\n j = 0;\n loopDist = ctrlptDist;\n }\n\n var loopAngle = loopDir - Math.PI / 2;\n var outAngle = loopAngle - loopSwp / 2;\n var inAngle = loopAngle + loopSwp / 2; // increase by step size for overlapping loops, keyed on direction and sweep values\n\n var dc = String(loopDir + '_' + loopSwp);\n j = dirCounts[dc] === undefined ? dirCounts[dc] = 0 : ++dirCounts[dc];\n rs.ctrlpts = [srcPos.x + Math.cos(outAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.y + Math.sin(outAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.x + Math.cos(inAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.y + Math.sin(inAngle) * 1.4 * loopDist * (j / 3 + 1)];\n};\n\nBRp$3.findCompoundLoopPoints = function (edge, pairInfo, i, edgeIsUnbundled) {\n // Compound edge\n var rs = edge._private.rscratch;\n rs.edgeType = 'compound';\n var srcPos = pairInfo.srcPos,\n tgtPos = pairInfo.tgtPos,\n srcW = pairInfo.srcW,\n srcH = pairInfo.srcH,\n tgtW = pairInfo.tgtW,\n tgtH = pairInfo.tgtH;\n var stepSize = edge.pstyle('control-point-step-size').pfValue;\n var ctrlptDists = edge.pstyle('control-point-distances');\n var ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[0] : undefined;\n var j = i;\n var loopDist = stepSize;\n\n if (edgeIsUnbundled) {\n j = 0;\n loopDist = ctrlptDist;\n }\n\n var loopW = 50;\n var loopaPos = {\n x: srcPos.x - srcW / 2,\n y: srcPos.y - srcH / 2\n };\n var loopbPos = {\n x: tgtPos.x - tgtW / 2,\n y: tgtPos.y - tgtH / 2\n };\n var loopPos = {\n x: Math.min(loopaPos.x, loopbPos.x),\n y: Math.min(loopaPos.y, loopbPos.y)\n }; // avoids cases with impossible beziers\n\n var minCompoundStretch = 0.5;\n var compoundStretchA = Math.max(minCompoundStretch, Math.log(srcW * 0.01));\n var compoundStretchB = Math.max(minCompoundStretch, Math.log(tgtW * 0.01));\n rs.ctrlpts = [loopPos.x, loopPos.y - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchA, loopPos.x - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchB, loopPos.y];\n};\n\nBRp$3.findStraightEdgePoints = function (edge) {\n // Straight edge within bundle\n edge._private.rscratch.edgeType = 'straight';\n};\n\nBRp$3.findBezierPoints = function (edge, pairInfo, i, edgeIsUnbundled, edgeIsSwapped) {\n var rs = edge._private.rscratch;\n var vectorNormInverse = pairInfo.vectorNormInverse,\n posPts = pairInfo.posPts,\n intersectionPts = pairInfo.intersectionPts;\n var edgeDistances = edge.pstyle('edge-distances').value;\n var stepSize = edge.pstyle('control-point-step-size').pfValue;\n var ctrlptDists = edge.pstyle('control-point-distances');\n var ctrlptWs = edge.pstyle('control-point-weights');\n var bezierN = ctrlptDists && ctrlptWs ? Math.min(ctrlptDists.value.length, ctrlptWs.value.length) : 1;\n var ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[0] : undefined;\n var ctrlptWeight = ctrlptWs.value[0]; // (Multi)bezier\n\n var multi = edgeIsUnbundled;\n rs.edgeType = multi ? 'multibezier' : 'bezier';\n rs.ctrlpts = [];\n\n for (var b = 0; b < bezierN; b++) {\n var normctrlptDist = (0.5 - pairInfo.eles.length / 2 + i) * stepSize * (edgeIsSwapped ? -1 : 1);\n var manctrlptDist = void 0;\n var sign = signum(normctrlptDist);\n\n if (multi) {\n ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[b] : stepSize; // fall back on step size\n\n ctrlptWeight = ctrlptWs.value[b];\n }\n\n if (edgeIsUnbundled) {\n // multi or single unbundled\n manctrlptDist = ctrlptDist;\n } else {\n manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined;\n }\n\n var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist;\n var w1 = 1 - ctrlptWeight;\n var w2 = ctrlptWeight;\n var midptPts = edgeDistances === 'node-position' ? posPts : intersectionPts;\n var adjustedMidpt = {\n x: midptPts.x1 * w1 + midptPts.x2 * w2,\n y: midptPts.y1 * w1 + midptPts.y2 * w2\n };\n rs.ctrlpts.push(adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint, adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint);\n }\n};\n\nBRp$3.findTaxiPoints = function (edge, pairInfo) {\n // Taxicab geometry with two turns maximum\n var rs = edge._private.rscratch;\n rs.edgeType = 'segments';\n var VERTICAL = 'vertical';\n var HORIZONTAL = 'horizontal';\n var LEFTWARD = 'leftward';\n var RIGHTWARD = 'rightward';\n var DOWNWARD = 'downward';\n var UPWARD = 'upward';\n var AUTO = 'auto';\n var posPts = pairInfo.posPts,\n srcW = pairInfo.srcW,\n srcH = pairInfo.srcH,\n tgtW = pairInfo.tgtW,\n tgtH = pairInfo.tgtH;\n var edgeDistances = edge.pstyle('edge-distances').value;\n var dIncludesNodeBody = edgeDistances !== 'node-position';\n var taxiDir = edge.pstyle('taxi-direction').value;\n var rawTaxiDir = taxiDir; // unprocessed value\n\n var taxiTurn = edge.pstyle('taxi-turn');\n var turnIsPercent = taxiTurn.units === '%';\n var taxiTurnPfVal = taxiTurn.pfValue;\n var turnIsNegative = taxiTurnPfVal < 0; // i.e. from target side\n\n var minD = edge.pstyle('taxi-turn-min-distance').pfValue;\n var dw = dIncludesNodeBody ? (srcW + tgtW) / 2 : 0;\n var dh = dIncludesNodeBody ? (srcH + tgtH) / 2 : 0;\n var pdx = posPts.x2 - posPts.x1;\n var pdy = posPts.y2 - posPts.y1; // take away the effective w/h from the magnitude of the delta value\n\n var subDWH = function subDWH(dxy, dwh) {\n if (dxy > 0) {\n return Math.max(dxy - dwh, 0);\n } else {\n return Math.min(dxy + dwh, 0);\n }\n };\n\n var dx = subDWH(pdx, dw);\n var dy = subDWH(pdy, dh);\n var isExplicitDir = false;\n\n if (rawTaxiDir === AUTO) {\n taxiDir = Math.abs(dx) > Math.abs(dy) ? HORIZONTAL : VERTICAL;\n } else if (rawTaxiDir === UPWARD || rawTaxiDir === DOWNWARD) {\n taxiDir = VERTICAL;\n isExplicitDir = true;\n } else if (rawTaxiDir === LEFTWARD || rawTaxiDir === RIGHTWARD) {\n taxiDir = HORIZONTAL;\n isExplicitDir = true;\n }\n\n var isVert = taxiDir === VERTICAL;\n var l = isVert ? dy : dx;\n var pl = isVert ? pdy : pdx;\n var sgnL = signum(pl);\n var forcedDir = false;\n\n if (!(isExplicitDir && (turnIsPercent || turnIsNegative)) // forcing in this case would cause weird growing in the opposite direction\n && (rawTaxiDir === DOWNWARD && pl < 0 || rawTaxiDir === UPWARD && pl > 0 || rawTaxiDir === LEFTWARD && pl > 0 || rawTaxiDir === RIGHTWARD && pl < 0)) {\n sgnL *= -1;\n l = sgnL * Math.abs(l);\n forcedDir = true;\n }\n\n var d;\n\n if (turnIsPercent) {\n var p = taxiTurnPfVal < 0 ? 1 + taxiTurnPfVal : taxiTurnPfVal;\n d = p * l;\n } else {\n var k = taxiTurnPfVal < 0 ? l : 0;\n d = k + taxiTurnPfVal * sgnL;\n }\n\n var getIsTooClose = function getIsTooClose(d) {\n return Math.abs(d) < minD || Math.abs(d) >= Math.abs(l);\n };\n\n var isTooCloseSrc = getIsTooClose(d);\n var isTooCloseTgt = getIsTooClose(Math.abs(l) - Math.abs(d));\n var isTooClose = isTooCloseSrc || isTooCloseTgt;\n\n if (isTooClose && !forcedDir) {\n // non-ideal routing\n if (isVert) {\n // vertical fallbacks\n var lShapeInsideSrc = Math.abs(pl) <= srcH / 2;\n var lShapeInsideTgt = Math.abs(pdx) <= tgtW / 2;\n\n if (lShapeInsideSrc) {\n // horizontal Z-shape (direction not respected)\n var x = (posPts.x1 + posPts.x2) / 2;\n var y1 = posPts.y1,\n y2 = posPts.y2;\n rs.segpts = [x, y1, x, y2];\n } else if (lShapeInsideTgt) {\n // vertical Z-shape (distance not respected)\n var y = (posPts.y1 + posPts.y2) / 2;\n var x1 = posPts.x1,\n x2 = posPts.x2;\n rs.segpts = [x1, y, x2, y];\n } else {\n // L-shape fallback (turn distance not respected, but works well with tree siblings)\n rs.segpts = [posPts.x1, posPts.y2];\n }\n } else {\n // horizontal fallbacks\n var _lShapeInsideSrc = Math.abs(pl) <= srcW / 2;\n\n var _lShapeInsideTgt = Math.abs(pdy) <= tgtH / 2;\n\n if (_lShapeInsideSrc) {\n // vertical Z-shape (direction not respected)\n var _y = (posPts.y1 + posPts.y2) / 2;\n\n var _x = posPts.x1,\n _x2 = posPts.x2;\n rs.segpts = [_x, _y, _x2, _y];\n } else if (_lShapeInsideTgt) {\n // horizontal Z-shape (turn distance not respected)\n var _x3 = (posPts.x1 + posPts.x2) / 2;\n\n var _y2 = posPts.y1,\n _y3 = posPts.y2;\n rs.segpts = [_x3, _y2, _x3, _y3];\n } else {\n // L-shape (turn distance not respected, but works well for tree siblings)\n rs.segpts = [posPts.x2, posPts.y1];\n }\n }\n } else {\n // ideal routing\n if (isVert) {\n var _y4 = posPts.y1 + d + (dIncludesNodeBody ? srcH / 2 * sgnL : 0);\n\n var _x4 = posPts.x1,\n _x5 = posPts.x2;\n rs.segpts = [_x4, _y4, _x5, _y4];\n } else {\n // horizontal\n var _x6 = posPts.x1 + d + (dIncludesNodeBody ? srcW / 2 * sgnL : 0);\n\n var _y5 = posPts.y1,\n _y6 = posPts.y2;\n rs.segpts = [_x6, _y5, _x6, _y6];\n }\n }\n};\n\nBRp$3.tryToCorrectInvalidPoints = function (edge, pairInfo) {\n var rs = edge._private.rscratch; // can only correct beziers for now...\n\n if (rs.edgeType === 'bezier') {\n var srcPos = pairInfo.srcPos,\n tgtPos = pairInfo.tgtPos,\n srcW = pairInfo.srcW,\n srcH = pairInfo.srcH,\n tgtW = pairInfo.tgtW,\n tgtH = pairInfo.tgtH,\n srcShape = pairInfo.srcShape,\n tgtShape = pairInfo.tgtShape;\n var badStart = !number(rs.startX) || !number(rs.startY);\n var badAStart = !number(rs.arrowStartX) || !number(rs.arrowStartY);\n var badEnd = !number(rs.endX) || !number(rs.endY);\n var badAEnd = !number(rs.arrowEndX) || !number(rs.arrowEndY);\n var minCpADistFactor = 3;\n var arrowW = this.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.arrowShapeWidth;\n var minCpADist = minCpADistFactor * arrowW;\n var startACpDist = dist({\n x: rs.ctrlpts[0],\n y: rs.ctrlpts[1]\n }, {\n x: rs.startX,\n y: rs.startY\n });\n var closeStartACp = startACpDist < minCpADist;\n var endACpDist = dist({\n x: rs.ctrlpts[0],\n y: rs.ctrlpts[1]\n }, {\n x: rs.endX,\n y: rs.endY\n });\n var closeEndACp = endACpDist < minCpADist;\n var overlapping = false;\n\n if (badStart || badAStart || closeStartACp) {\n overlapping = true; // project control point along line from src centre to outside the src shape\n // (otherwise intersection will yield nothing)\n\n var cpD = {\n // delta\n x: rs.ctrlpts[0] - srcPos.x,\n y: rs.ctrlpts[1] - srcPos.y\n };\n var cpL = Math.sqrt(cpD.x * cpD.x + cpD.y * cpD.y); // length of line\n\n var cpM = {\n // normalised delta\n x: cpD.x / cpL,\n y: cpD.y / cpL\n };\n var radius = Math.max(srcW, srcH);\n var cpProj = {\n // *2 radius guarantees outside shape\n x: rs.ctrlpts[0] + cpM.x * 2 * radius,\n y: rs.ctrlpts[1] + cpM.y * 2 * radius\n };\n var srcCtrlPtIntn = srcShape.intersectLine(srcPos.x, srcPos.y, srcW, srcH, cpProj.x, cpProj.y, 0);\n\n if (closeStartACp) {\n rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist);\n rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist);\n } else {\n rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist;\n rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist;\n }\n }\n\n if (badEnd || badAEnd || closeEndACp) {\n overlapping = true; // project control point along line from tgt centre to outside the tgt shape\n // (otherwise intersection will yield nothing)\n\n var _cpD = {\n // delta\n x: rs.ctrlpts[0] - tgtPos.x,\n y: rs.ctrlpts[1] - tgtPos.y\n };\n\n var _cpL = Math.sqrt(_cpD.x * _cpD.x + _cpD.y * _cpD.y); // length of line\n\n\n var _cpM = {\n // normalised delta\n x: _cpD.x / _cpL,\n y: _cpD.y / _cpL\n };\n\n var _radius = Math.max(srcW, srcH);\n\n var _cpProj = {\n // *2 radius guarantees outside shape\n x: rs.ctrlpts[0] + _cpM.x * 2 * _radius,\n y: rs.ctrlpts[1] + _cpM.y * 2 * _radius\n };\n var tgtCtrlPtIntn = tgtShape.intersectLine(tgtPos.x, tgtPos.y, tgtW, tgtH, _cpProj.x, _cpProj.y, 0);\n\n if (closeEndACp) {\n rs.ctrlpts[0] = rs.ctrlpts[0] + _cpM.x * (minCpADist - endACpDist);\n rs.ctrlpts[1] = rs.ctrlpts[1] + _cpM.y * (minCpADist - endACpDist);\n } else {\n rs.ctrlpts[0] = tgtCtrlPtIntn[0] + _cpM.x * minCpADist;\n rs.ctrlpts[1] = tgtCtrlPtIntn[1] + _cpM.y * minCpADist;\n }\n }\n\n if (overlapping) {\n // recalc endpts\n this.findEndpoints(edge);\n }\n }\n};\n\nBRp$3.storeAllpts = function (edge) {\n var rs = edge._private.rscratch;\n\n if (rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound') {\n rs.allpts = [];\n rs.allpts.push(rs.startX, rs.startY);\n\n for (var b = 0; b + 1 < rs.ctrlpts.length; b += 2) {\n // ctrl pt itself\n rs.allpts.push(rs.ctrlpts[b], rs.ctrlpts[b + 1]); // the midpt between ctrlpts as intermediate destination pts\n\n if (b + 3 < rs.ctrlpts.length) {\n rs.allpts.push((rs.ctrlpts[b] + rs.ctrlpts[b + 2]) / 2, (rs.ctrlpts[b + 1] + rs.ctrlpts[b + 3]) / 2);\n }\n }\n\n rs.allpts.push(rs.endX, rs.endY);\n var m, mt;\n\n if (rs.ctrlpts.length / 2 % 2 === 0) {\n m = rs.allpts.length / 2 - 1;\n rs.midX = rs.allpts[m];\n rs.midY = rs.allpts[m + 1];\n } else {\n m = rs.allpts.length / 2 - 3;\n mt = 0.5;\n rs.midX = qbezierAt(rs.allpts[m], rs.allpts[m + 2], rs.allpts[m + 4], mt);\n rs.midY = qbezierAt(rs.allpts[m + 1], rs.allpts[m + 3], rs.allpts[m + 5], mt);\n }\n } else if (rs.edgeType === 'straight') {\n // need to calc these after endpts\n rs.allpts = [rs.startX, rs.startY, rs.endX, rs.endY]; // default midpt for labels etc\n\n rs.midX = (rs.startX + rs.endX + rs.arrowStartX + rs.arrowEndX) / 4;\n rs.midY = (rs.startY + rs.endY + rs.arrowStartY + rs.arrowEndY) / 4;\n } else if (rs.edgeType === 'segments') {\n rs.allpts = [];\n rs.allpts.push(rs.startX, rs.startY);\n rs.allpts.push.apply(rs.allpts, rs.segpts);\n rs.allpts.push(rs.endX, rs.endY);\n\n if (rs.segpts.length % 4 === 0) {\n var i2 = rs.segpts.length / 2;\n var i1 = i2 - 2;\n rs.midX = (rs.segpts[i1] + rs.segpts[i2]) / 2;\n rs.midY = (rs.segpts[i1 + 1] + rs.segpts[i2 + 1]) / 2;\n } else {\n var _i = rs.segpts.length / 2 - 1;\n\n rs.midX = rs.segpts[_i];\n rs.midY = rs.segpts[_i + 1];\n }\n }\n};\n\nBRp$3.checkForInvalidEdgeWarning = function (edge) {\n var rs = edge[0]._private.rscratch;\n\n if (rs.nodesOverlap || number(rs.startX) && number(rs.startY) && number(rs.endX) && number(rs.endY)) {\n rs.loggedErr = false;\n } else {\n if (!rs.loggedErr) {\n rs.loggedErr = true;\n warn('Edge `' + edge.id() + '` has invalid endpoints and so it is impossible to draw. Adjust your edge style (e.g. control points) accordingly or use an alternative edge type. This is expected behaviour when the source node and the target node overlap.');\n }\n }\n};\n\nBRp$3.findEdgeControlPoints = function (edges) {\n var _this = this;\n\n if (!edges || edges.length === 0) {\n return;\n }\n\n var r = this;\n var cy = r.cy;\n var hasCompounds = cy.hasCompoundNodes();\n var hashTable = {\n map: new Map$1(),\n get: function get(pairId) {\n var map2 = this.map.get(pairId[0]);\n\n if (map2 != null) {\n return map2.get(pairId[1]);\n } else {\n return null;\n }\n },\n set: function set(pairId, val) {\n var map2 = this.map.get(pairId[0]);\n\n if (map2 == null) {\n map2 = new Map$1();\n this.map.set(pairId[0], map2);\n }\n\n map2.set(pairId[1], val);\n }\n };\n var pairIds = [];\n var haystackEdges = []; // create a table of edge (src, tgt) => list of edges between them\n\n for (var i = 0; i < edges.length; i++) {\n var edge = edges[i];\n var _p = edge._private;\n var curveStyle = edge.pstyle('curve-style').value; // ignore edges who are not to be displayed\n // they shouldn't take up space\n\n if (edge.removed() || !edge.takesUpSpace()) {\n continue;\n }\n\n if (curveStyle === 'haystack') {\n haystackEdges.push(edge);\n continue;\n }\n\n var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments' || curveStyle === 'straight' || curveStyle === 'taxi';\n var edgeIsBezier = curveStyle === 'unbundled-bezier' || curveStyle === 'bezier';\n var src = _p.source;\n var tgt = _p.target;\n var srcIndex = src.poolIndex();\n var tgtIndex = tgt.poolIndex();\n var pairId = [srcIndex, tgtIndex].sort();\n var tableEntry = hashTable.get(pairId);\n\n if (tableEntry == null) {\n tableEntry = {\n eles: []\n };\n hashTable.set(pairId, tableEntry);\n pairIds.push(pairId);\n }\n\n tableEntry.eles.push(edge);\n\n if (edgeIsUnbundled) {\n tableEntry.hasUnbundled = true;\n }\n\n if (edgeIsBezier) {\n tableEntry.hasBezier = true;\n }\n } // for each pair (src, tgt), create the ctrl pts\n // Nested for loop is OK; total number of iterations for both loops = edgeCount\n\n\n var _loop = function _loop(p) {\n var pairId = pairIds[p];\n var pairInfo = hashTable.get(pairId);\n var swappedpairInfo = void 0;\n\n if (!pairInfo.hasUnbundled) {\n var pllEdges = pairInfo.eles[0].parallelEdges().filter(function (e) {\n return e.isBundledBezier();\n });\n clearArray(pairInfo.eles);\n pllEdges.forEach(function (edge) {\n return pairInfo.eles.push(edge);\n }); // for each pair id, the edges should be sorted by index\n\n pairInfo.eles.sort(function (edge1, edge2) {\n return edge1.poolIndex() - edge2.poolIndex();\n });\n }\n\n var firstEdge = pairInfo.eles[0];\n var src = firstEdge.source();\n var tgt = firstEdge.target(); // make sure src/tgt distinction is consistent w.r.t. pairId\n\n if (src.poolIndex() > tgt.poolIndex()) {\n var temp = src;\n src = tgt;\n tgt = temp;\n }\n\n var srcPos = pairInfo.srcPos = src.position();\n var tgtPos = pairInfo.tgtPos = tgt.position();\n var srcW = pairInfo.srcW = src.outerWidth();\n var srcH = pairInfo.srcH = src.outerHeight();\n var tgtW = pairInfo.tgtW = tgt.outerWidth();\n var tgtH = pairInfo.tgtH = tgt.outerHeight();\n\n var srcShape = pairInfo.srcShape = r.nodeShapes[_this.getNodeShape(src)];\n\n var tgtShape = pairInfo.tgtShape = r.nodeShapes[_this.getNodeShape(tgt)];\n\n pairInfo.dirCounts = {\n 'north': 0,\n 'west': 0,\n 'south': 0,\n 'east': 0,\n 'northwest': 0,\n 'southwest': 0,\n 'northeast': 0,\n 'southeast': 0\n };\n\n for (var _i2 = 0; _i2 < pairInfo.eles.length; _i2++) {\n var _edge = pairInfo.eles[_i2];\n var rs = _edge[0]._private.rscratch;\n\n var _curveStyle = _edge.pstyle('curve-style').value;\n\n var _edgeIsUnbundled = _curveStyle === 'unbundled-bezier' || _curveStyle === 'segments' || _curveStyle === 'taxi'; // whether the normalised pair order is the reverse of the edge's src-tgt order\n\n\n var edgeIsSwapped = !src.same(_edge.source());\n\n if (!pairInfo.calculatedIntersection && src !== tgt && (pairInfo.hasBezier || pairInfo.hasUnbundled)) {\n pairInfo.calculatedIntersection = true; // pt outside src shape to calc distance/displacement from src to tgt\n\n var srcOutside = srcShape.intersectLine(srcPos.x, srcPos.y, srcW, srcH, tgtPos.x, tgtPos.y, 0);\n var srcIntn = pairInfo.srcIntn = srcOutside; // pt outside tgt shape to calc distance/displacement from src to tgt\n\n var tgtOutside = tgtShape.intersectLine(tgtPos.x, tgtPos.y, tgtW, tgtH, srcPos.x, srcPos.y, 0);\n var tgtIntn = pairInfo.tgtIntn = tgtOutside;\n var intersectionPts = pairInfo.intersectionPts = {\n x1: srcOutside[0],\n x2: tgtOutside[0],\n y1: srcOutside[1],\n y2: tgtOutside[1]\n };\n var posPts = pairInfo.posPts = {\n x1: srcPos.x,\n x2: tgtPos.x,\n y1: srcPos.y,\n y2: tgtPos.y\n };\n var dy = tgtOutside[1] - srcOutside[1];\n var dx = tgtOutside[0] - srcOutside[0];\n var l = Math.sqrt(dx * dx + dy * dy);\n var vector = pairInfo.vector = {\n x: dx,\n y: dy\n };\n var vectorNorm = pairInfo.vectorNorm = {\n x: vector.x / l,\n y: vector.y / l\n };\n var vectorNormInverse = {\n x: -vectorNorm.y,\n y: vectorNorm.x\n }; // if node shapes overlap, then no ctrl pts to draw\n\n pairInfo.nodesOverlap = !number(l) || tgtShape.checkPoint(srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y) || srcShape.checkPoint(tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y);\n pairInfo.vectorNormInverse = vectorNormInverse;\n swappedpairInfo = {\n nodesOverlap: pairInfo.nodesOverlap,\n dirCounts: pairInfo.dirCounts,\n calculatedIntersection: true,\n hasBezier: pairInfo.hasBezier,\n hasUnbundled: pairInfo.hasUnbundled,\n eles: pairInfo.eles,\n srcPos: tgtPos,\n tgtPos: srcPos,\n srcW: tgtW,\n srcH: tgtH,\n tgtW: srcW,\n tgtH: srcH,\n srcIntn: tgtIntn,\n tgtIntn: srcIntn,\n srcShape: tgtShape,\n tgtShape: srcShape,\n posPts: {\n x1: posPts.x2,\n y1: posPts.y2,\n x2: posPts.x1,\n y2: posPts.y1\n },\n intersectionPts: {\n x1: intersectionPts.x2,\n y1: intersectionPts.y2,\n x2: intersectionPts.x1,\n y2: intersectionPts.y1\n },\n vector: {\n x: -vector.x,\n y: -vector.y\n },\n vectorNorm: {\n x: -vectorNorm.x,\n y: -vectorNorm.y\n },\n vectorNormInverse: {\n x: -vectorNormInverse.x,\n y: -vectorNormInverse.y\n }\n };\n }\n\n var passedPairInfo = edgeIsSwapped ? swappedpairInfo : pairInfo;\n rs.nodesOverlap = passedPairInfo.nodesOverlap;\n rs.srcIntn = passedPairInfo.srcIntn;\n rs.tgtIntn = passedPairInfo.tgtIntn;\n\n if (hasCompounds && (src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild()) && (src.parents().anySame(tgt) || tgt.parents().anySame(src) || src.same(tgt) && src.isParent())) {\n _this.findCompoundLoopPoints(_edge, passedPairInfo, _i2, _edgeIsUnbundled);\n } else if (src === tgt) {\n _this.findLoopPoints(_edge, passedPairInfo, _i2, _edgeIsUnbundled);\n } else if (_curveStyle === 'segments') {\n _this.findSegmentsPoints(_edge, passedPairInfo);\n } else if (_curveStyle === 'taxi') {\n _this.findTaxiPoints(_edge, passedPairInfo);\n } else if (_curveStyle === 'straight' || !_edgeIsUnbundled && pairInfo.eles.length % 2 === 1 && _i2 === Math.floor(pairInfo.eles.length / 2)) {\n _this.findStraightEdgePoints(_edge);\n } else {\n _this.findBezierPoints(_edge, passedPairInfo, _i2, _edgeIsUnbundled, edgeIsSwapped);\n }\n\n _this.findEndpoints(_edge);\n\n _this.tryToCorrectInvalidPoints(_edge, passedPairInfo);\n\n _this.checkForInvalidEdgeWarning(_edge);\n\n _this.storeAllpts(_edge);\n\n _this.storeEdgeProjections(_edge);\n\n _this.calculateArrowAngles(_edge);\n\n _this.recalculateEdgeLabelProjections(_edge);\n\n _this.calculateLabelAngles(_edge);\n } // for pair edges\n\n };\n\n for (var p = 0; p < pairIds.length; p++) {\n _loop(p);\n } // for pair ids\n // haystacks avoid the expense of pairInfo stuff (intersections etc.)\n\n\n this.findHaystackPoints(haystackEdges);\n};\n\nfunction getPts(pts) {\n var retPts = [];\n\n if (pts == null) {\n return;\n }\n\n for (var i = 0; i < pts.length; i += 2) {\n var x = pts[i];\n var y = pts[i + 1];\n retPts.push({\n x: x,\n y: y\n });\n }\n\n return retPts;\n}\n\nBRp$3.getSegmentPoints = function (edge) {\n var rs = edge[0]._private.rscratch;\n var type = rs.edgeType;\n\n if (type === 'segments') {\n this.recalculateRenderedStyle(edge);\n return getPts(rs.segpts);\n }\n};\n\nBRp$3.getControlPoints = function (edge) {\n var rs = edge[0]._private.rscratch;\n var type = rs.edgeType;\n\n if (type === 'bezier' || type === 'multibezier' || type === 'self' || type === 'compound') {\n this.recalculateRenderedStyle(edge);\n return getPts(rs.ctrlpts);\n }\n};\n\nBRp$3.getEdgeMidpoint = function (edge) {\n var rs = edge[0]._private.rscratch;\n this.recalculateRenderedStyle(edge);\n return {\n x: rs.midX,\n y: rs.midY\n };\n};\n\nvar BRp$4 = {};\n\nBRp$4.manualEndptToPx = function (node, prop) {\n var r = this;\n var npos = node.position();\n var w = node.outerWidth();\n var h = node.outerHeight();\n\n if (prop.value.length === 2) {\n var p = [prop.pfValue[0], prop.pfValue[1]];\n\n if (prop.units[0] === '%') {\n p[0] = p[0] * w;\n }\n\n if (prop.units[1] === '%') {\n p[1] = p[1] * h;\n }\n\n p[0] += npos.x;\n p[1] += npos.y;\n return p;\n } else {\n var angle = prop.pfValue[0];\n angle = -Math.PI / 2 + angle; // start at 12 o'clock\n\n var l = 2 * Math.max(w, h);\n var _p = [npos.x + Math.cos(angle) * l, npos.y + Math.sin(angle) * l];\n return r.nodeShapes[this.getNodeShape(node)].intersectLine(npos.x, npos.y, w, h, _p[0], _p[1], 0);\n }\n};\n\nBRp$4.findEndpoints = function (edge) {\n var r = this;\n var intersect;\n var source = edge.source()[0];\n var target = edge.target()[0];\n var srcPos = source.position();\n var tgtPos = target.position();\n var tgtArShape = edge.pstyle('target-arrow-shape').value;\n var srcArShape = edge.pstyle('source-arrow-shape').value;\n var tgtDist = edge.pstyle('target-distance-from-node').pfValue;\n var srcDist = edge.pstyle('source-distance-from-node').pfValue;\n var curveStyle = edge.pstyle('curve-style').value;\n var rs = edge._private.rscratch;\n var et = rs.edgeType;\n var taxi = curveStyle === 'taxi';\n var self = et === 'self' || et === 'compound';\n var bezier = et === 'bezier' || et === 'multibezier' || self;\n var multi = et !== 'bezier';\n var lines = et === 'straight' || et === 'segments';\n var segments = et === 'segments';\n var hasEndpts = bezier || multi || lines;\n var overrideEndpts = self || taxi;\n var srcManEndpt = edge.pstyle('source-endpoint');\n var srcManEndptVal = overrideEndpts ? 'outside-to-node' : srcManEndpt.value;\n var tgtManEndpt = edge.pstyle('target-endpoint');\n var tgtManEndptVal = overrideEndpts ? 'outside-to-node' : tgtManEndpt.value;\n rs.srcManEndpt = srcManEndpt;\n rs.tgtManEndpt = tgtManEndpt;\n var p1; // last known point of edge on target side\n\n var p2; // last known point of edge on source side\n\n var p1_i; // point to intersect with target shape\n\n var p2_i; // point to intersect with source shape\n\n if (bezier) {\n var cpStart = [rs.ctrlpts[0], rs.ctrlpts[1]];\n var cpEnd = multi ? [rs.ctrlpts[rs.ctrlpts.length - 2], rs.ctrlpts[rs.ctrlpts.length - 1]] : cpStart;\n p1 = cpEnd;\n p2 = cpStart;\n } else if (lines) {\n var srcArrowFromPt = !segments ? [tgtPos.x, tgtPos.y] : rs.segpts.slice(0, 2);\n var tgtArrowFromPt = !segments ? [srcPos.x, srcPos.y] : rs.segpts.slice(rs.segpts.length - 2);\n p1 = tgtArrowFromPt;\n p2 = srcArrowFromPt;\n }\n\n if (tgtManEndptVal === 'inside-to-node') {\n intersect = [tgtPos.x, tgtPos.y];\n } else if (tgtManEndpt.units) {\n intersect = this.manualEndptToPx(target, tgtManEndpt);\n } else if (tgtManEndptVal === 'outside-to-line') {\n intersect = rs.tgtIntn; // use cached value from ctrlpt calc\n } else {\n if (tgtManEndptVal === 'outside-to-node' || tgtManEndptVal === 'outside-to-node-or-label') {\n p1_i = p1;\n } else if (tgtManEndptVal === 'outside-to-line' || tgtManEndptVal === 'outside-to-line-or-label') {\n p1_i = [srcPos.x, srcPos.y];\n }\n\n intersect = r.nodeShapes[this.getNodeShape(target)].intersectLine(tgtPos.x, tgtPos.y, target.outerWidth(), target.outerHeight(), p1_i[0], p1_i[1], 0);\n\n if (tgtManEndptVal === 'outside-to-node-or-label' || tgtManEndptVal === 'outside-to-line-or-label') {\n var trs = target._private.rscratch;\n var lw = trs.labelWidth;\n var lh = trs.labelHeight;\n var lx = trs.labelX;\n var ly = trs.labelY;\n var lw2 = lw / 2;\n var lh2 = lh / 2;\n var va = target.pstyle('text-valign').value;\n\n if (va === 'top') {\n ly -= lh2;\n } else if (va === 'bottom') {\n ly += lh2;\n }\n\n var ha = target.pstyle('text-halign').value;\n\n if (ha === 'left') {\n lx -= lw2;\n } else if (ha === 'right') {\n lx += lw2;\n }\n\n var labelIntersect = polygonIntersectLine(p1_i[0], p1_i[1], [lx - lw2, ly - lh2, lx + lw2, ly - lh2, lx + lw2, ly + lh2, lx - lw2, ly + lh2], tgtPos.x, tgtPos.y);\n\n if (labelIntersect.length > 0) {\n var refPt = srcPos;\n var intSqdist = sqdist(refPt, array2point(intersect));\n var labIntSqdist = sqdist(refPt, array2point(labelIntersect));\n var minSqDist = intSqdist;\n\n if (labIntSqdist < intSqdist) {\n intersect = labelIntersect;\n minSqDist = labIntSqdist;\n }\n\n if (labelIntersect.length > 2) {\n var labInt2SqDist = sqdist(refPt, {\n x: labelIntersect[2],\n y: labelIntersect[3]\n });\n\n if (labInt2SqDist < minSqDist) {\n intersect = [labelIntersect[2], labelIntersect[3]];\n }\n }\n }\n }\n }\n\n var arrowEnd = shortenIntersection(intersect, p1, r.arrowShapes[tgtArShape].spacing(edge) + tgtDist);\n var edgeEnd = shortenIntersection(intersect, p1, r.arrowShapes[tgtArShape].gap(edge) + tgtDist);\n rs.endX = edgeEnd[0];\n rs.endY = edgeEnd[1];\n rs.arrowEndX = arrowEnd[0];\n rs.arrowEndY = arrowEnd[1];\n\n if (srcManEndptVal === 'inside-to-node') {\n intersect = [srcPos.x, srcPos.y];\n } else if (srcManEndpt.units) {\n intersect = this.manualEndptToPx(source, srcManEndpt);\n } else if (srcManEndptVal === 'outside-to-line') {\n intersect = rs.srcIntn; // use cached value from ctrlpt calc\n } else {\n if (srcManEndptVal === 'outside-to-node' || srcManEndptVal === 'outside-to-node-or-label') {\n p2_i = p2;\n } else if (srcManEndptVal === 'outside-to-line' || srcManEndptVal === 'outside-to-line-or-label') {\n p2_i = [tgtPos.x, tgtPos.y];\n }\n\n intersect = r.nodeShapes[this.getNodeShape(source)].intersectLine(srcPos.x, srcPos.y, source.outerWidth(), source.outerHeight(), p2_i[0], p2_i[1], 0);\n\n if (srcManEndptVal === 'outside-to-node-or-label' || srcManEndptVal === 'outside-to-line-or-label') {\n var srs = source._private.rscratch;\n var _lw = srs.labelWidth;\n var _lh = srs.labelHeight;\n var _lx = srs.labelX;\n var _ly = srs.labelY;\n\n var _lw2 = _lw / 2;\n\n var _lh2 = _lh / 2;\n\n var _va = source.pstyle('text-valign').value;\n\n if (_va === 'top') {\n _ly -= _lh2;\n } else if (_va === 'bottom') {\n _ly += _lh2;\n }\n\n var _ha = source.pstyle('text-halign').value;\n\n if (_ha === 'left') {\n _lx -= _lw2;\n } else if (_ha === 'right') {\n _lx += _lw2;\n }\n\n var _labelIntersect = polygonIntersectLine(p2_i[0], p2_i[1], [_lx - _lw2, _ly - _lh2, _lx + _lw2, _ly - _lh2, _lx + _lw2, _ly + _lh2, _lx - _lw2, _ly + _lh2], srcPos.x, srcPos.y);\n\n if (_labelIntersect.length > 0) {\n var _refPt = tgtPos;\n\n var _intSqdist = sqdist(_refPt, array2point(intersect));\n\n var _labIntSqdist = sqdist(_refPt, array2point(_labelIntersect));\n\n var _minSqDist = _intSqdist;\n\n if (_labIntSqdist < _intSqdist) {\n intersect = [_labelIntersect[0], _labelIntersect[1]];\n _minSqDist = _labIntSqdist;\n }\n\n if (_labelIntersect.length > 2) {\n var _labInt2SqDist = sqdist(_refPt, {\n x: _labelIntersect[2],\n y: _labelIntersect[3]\n });\n\n if (_labInt2SqDist < _minSqDist) {\n intersect = [_labelIntersect[2], _labelIntersect[3]];\n }\n }\n }\n }\n }\n\n var arrowStart = shortenIntersection(intersect, p2, r.arrowShapes[srcArShape].spacing(edge) + srcDist);\n var edgeStart = shortenIntersection(intersect, p2, r.arrowShapes[srcArShape].gap(edge) + srcDist);\n rs.startX = edgeStart[0];\n rs.startY = edgeStart[1];\n rs.arrowStartX = arrowStart[0];\n rs.arrowStartY = arrowStart[1];\n\n if (hasEndpts) {\n if (!number(rs.startX) || !number(rs.startY) || !number(rs.endX) || !number(rs.endY)) {\n rs.badLine = true;\n } else {\n rs.badLine = false;\n }\n }\n};\n\nBRp$4.getSourceEndpoint = function (edge) {\n var rs = edge[0]._private.rscratch;\n this.recalculateRenderedStyle(edge);\n\n switch (rs.edgeType) {\n case 'haystack':\n return {\n x: rs.haystackPts[0],\n y: rs.haystackPts[1]\n };\n\n default:\n return {\n x: rs.arrowStartX,\n y: rs.arrowStartY\n };\n }\n};\n\nBRp$4.getTargetEndpoint = function (edge) {\n var rs = edge[0]._private.rscratch;\n this.recalculateRenderedStyle(edge);\n\n switch (rs.edgeType) {\n case 'haystack':\n return {\n x: rs.haystackPts[2],\n y: rs.haystackPts[3]\n };\n\n default:\n return {\n x: rs.arrowEndX,\n y: rs.arrowEndY\n };\n }\n};\n\nvar BRp$5 = {};\n\nfunction pushBezierPts(r, edge, pts) {\n var qbezierAt$1 = function qbezierAt$1(p1, p2, p3, t) {\n return qbezierAt(p1, p2, p3, t);\n };\n\n var _p = edge._private;\n var bpts = _p.rstyle.bezierPts;\n\n for (var i = 0; i < r.bezierProjPcts.length; i++) {\n var p = r.bezierProjPcts[i];\n bpts.push({\n x: qbezierAt$1(pts[0], pts[2], pts[4], p),\n y: qbezierAt$1(pts[1], pts[3], pts[5], p)\n });\n }\n}\n\nBRp$5.storeEdgeProjections = function (edge) {\n var _p = edge._private;\n var rs = _p.rscratch;\n var et = rs.edgeType; // clear the cached points state\n\n _p.rstyle.bezierPts = null;\n _p.rstyle.linePts = null;\n _p.rstyle.haystackPts = null;\n\n if (et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound') {\n _p.rstyle.bezierPts = [];\n\n for (var i = 0; i + 5 < rs.allpts.length; i += 4) {\n pushBezierPts(this, edge, rs.allpts.slice(i, i + 6));\n }\n } else if (et === 'segments') {\n var lpts = _p.rstyle.linePts = [];\n\n for (var i = 0; i + 1 < rs.allpts.length; i += 2) {\n lpts.push({\n x: rs.allpts[i],\n y: rs.allpts[i + 1]\n });\n }\n } else if (et === 'haystack') {\n var hpts = rs.haystackPts;\n _p.rstyle.haystackPts = [{\n x: hpts[0],\n y: hpts[1]\n }, {\n x: hpts[2],\n y: hpts[3]\n }];\n }\n\n _p.rstyle.arrowWidth = this.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.arrowShapeWidth;\n};\n\nBRp$5.recalculateEdgeProjections = function (edges) {\n this.findEdgeControlPoints(edges);\n};\n\nvar BRp$6 = {};\n\nBRp$6.recalculateNodeLabelProjection = function (node) {\n var content = node.pstyle('label').strValue;\n\n if (emptyString(content)) {\n return;\n }\n\n var textX, textY;\n var _p = node._private;\n var nodeWidth = node.width();\n var nodeHeight = node.height();\n var padding = node.padding();\n var nodePos = node.position();\n var textHalign = node.pstyle('text-halign').strValue;\n var textValign = node.pstyle('text-valign').strValue;\n var rs = _p.rscratch;\n var rstyle = _p.rstyle;\n\n switch (textHalign) {\n case 'left':\n textX = nodePos.x - nodeWidth / 2 - padding;\n break;\n\n case 'right':\n textX = nodePos.x + nodeWidth / 2 + padding;\n break;\n\n default:\n // e.g. center\n textX = nodePos.x;\n }\n\n switch (textValign) {\n case 'top':\n textY = nodePos.y - nodeHeight / 2 - padding;\n break;\n\n case 'bottom':\n textY = nodePos.y + nodeHeight / 2 + padding;\n break;\n\n default:\n // e.g. middle\n textY = nodePos.y;\n }\n\n rs.labelX = textX;\n rs.labelY = textY;\n rstyle.labelX = textX;\n rstyle.labelY = textY;\n this.applyLabelDimensions(node);\n};\n\nvar lineAngleFromDelta = function lineAngleFromDelta(dx, dy) {\n var angle = Math.atan(dy / dx);\n\n if (dx === 0 && angle < 0) {\n angle = angle * -1;\n }\n\n return angle;\n};\n\nvar lineAngle = function lineAngle(p0, p1) {\n var dx = p1.x - p0.x;\n var dy = p1.y - p0.y;\n return lineAngleFromDelta(dx, dy);\n};\n\nvar bezierAngle = function bezierAngle(p0, p1, p2, t) {\n var t0 = bound(0, t - 0.001, 1);\n var t1 = bound(0, t + 0.001, 1);\n var lp0 = qbezierPtAt(p0, p1, p2, t0);\n var lp1 = qbezierPtAt(p0, p1, p2, t1);\n return lineAngle(lp0, lp1);\n};\n\nBRp$6.recalculateEdgeLabelProjections = function (edge) {\n var p;\n var _p = edge._private;\n var rs = _p.rscratch;\n var r = this;\n var content = {\n mid: edge.pstyle('label').strValue,\n source: edge.pstyle('source-label').strValue,\n target: edge.pstyle('target-label').strValue\n };\n\n if (content.mid || content.source || content.target) ; else {\n return; // no labels => no calcs\n } // add center point to style so bounding box calculations can use it\n //\n\n\n p = {\n x: rs.midX,\n y: rs.midY\n };\n\n var setRs = function setRs(propName, prefix, value) {\n setPrefixedProperty(_p.rscratch, propName, prefix, value);\n setPrefixedProperty(_p.rstyle, propName, prefix, value);\n };\n\n setRs('labelX', null, p.x);\n setRs('labelY', null, p.y);\n var midAngle = lineAngleFromDelta(rs.midDispX, rs.midDispY);\n setRs('labelAutoAngle', null, midAngle);\n\n var createControlPointInfo = function createControlPointInfo() {\n if (createControlPointInfo.cache) {\n return createControlPointInfo.cache;\n } // use cache so only 1x per edge\n\n\n var ctrlpts = []; // store each ctrlpt info init\n\n for (var i = 0; i + 5 < rs.allpts.length; i += 4) {\n var p0 = {\n x: rs.allpts[i],\n y: rs.allpts[i + 1]\n };\n var p1 = {\n x: rs.allpts[i + 2],\n y: rs.allpts[i + 3]\n }; // ctrlpt\n\n var p2 = {\n x: rs.allpts[i + 4],\n y: rs.allpts[i + 5]\n };\n ctrlpts.push({\n p0: p0,\n p1: p1,\n p2: p2,\n startDist: 0,\n length: 0,\n segments: []\n });\n }\n\n var bpts = _p.rstyle.bezierPts;\n var nProjs = r.bezierProjPcts.length;\n\n function addSegment(cp, p0, p1, t0, t1) {\n var length = dist(p0, p1);\n var prevSegment = cp.segments[cp.segments.length - 1];\n var segment = {\n p0: p0,\n p1: p1,\n t0: t0,\n t1: t1,\n startDist: prevSegment ? prevSegment.startDist + prevSegment.length : 0,\n length: length\n };\n cp.segments.push(segment);\n cp.length += length;\n } // update each ctrlpt with segment info\n\n\n for (var _i = 0; _i < ctrlpts.length; _i++) {\n var cp = ctrlpts[_i];\n var prevCp = ctrlpts[_i - 1];\n\n if (prevCp) {\n cp.startDist = prevCp.startDist + prevCp.length;\n }\n\n addSegment(cp, cp.p0, bpts[_i * nProjs], 0, r.bezierProjPcts[0]); // first\n\n for (var j = 0; j < nProjs - 1; j++) {\n addSegment(cp, bpts[_i * nProjs + j], bpts[_i * nProjs + j + 1], r.bezierProjPcts[j], r.bezierProjPcts[j + 1]);\n }\n\n addSegment(cp, bpts[_i * nProjs + nProjs - 1], cp.p2, r.bezierProjPcts[nProjs - 1], 1); // last\n }\n\n return createControlPointInfo.cache = ctrlpts;\n };\n\n var calculateEndProjection = function calculateEndProjection(prefix) {\n var angle;\n var isSrc = prefix === 'source';\n\n if (!content[prefix]) {\n return;\n }\n\n var offset = edge.pstyle(prefix + '-text-offset').pfValue;\n\n switch (rs.edgeType) {\n case 'self':\n case 'compound':\n case 'bezier':\n case 'multibezier':\n {\n var cps = createControlPointInfo();\n var selected;\n var startDist = 0;\n var totalDist = 0; // find the segment we're on\n\n for (var i = 0; i < cps.length; i++) {\n var _cp = cps[isSrc ? i : cps.length - 1 - i];\n\n for (var j = 0; j < _cp.segments.length; j++) {\n var _seg = _cp.segments[isSrc ? j : _cp.segments.length - 1 - j];\n var lastSeg = i === cps.length - 1 && j === _cp.segments.length - 1;\n startDist = totalDist;\n totalDist += _seg.length;\n\n if (totalDist >= offset || lastSeg) {\n selected = {\n cp: _cp,\n segment: _seg\n };\n break;\n }\n }\n\n if (selected) {\n break;\n }\n }\n\n var cp = selected.cp;\n var seg = selected.segment;\n var tSegment = (offset - startDist) / seg.length;\n var segDt = seg.t1 - seg.t0;\n var t = isSrc ? seg.t0 + segDt * tSegment : seg.t1 - segDt * tSegment;\n t = bound(0, t, 1);\n p = qbezierPtAt(cp.p0, cp.p1, cp.p2, t);\n angle = bezierAngle(cp.p0, cp.p1, cp.p2, t);\n break;\n }\n\n case 'straight':\n case 'segments':\n case 'haystack':\n {\n var d = 0,\n di,\n d0;\n var p0, p1;\n var l = rs.allpts.length;\n\n for (var _i2 = 0; _i2 + 3 < l; _i2 += 2) {\n if (isSrc) {\n p0 = {\n x: rs.allpts[_i2],\n y: rs.allpts[_i2 + 1]\n };\n p1 = {\n x: rs.allpts[_i2 + 2],\n y: rs.allpts[_i2 + 3]\n };\n } else {\n p0 = {\n x: rs.allpts[l - 2 - _i2],\n y: rs.allpts[l - 1 - _i2]\n };\n p1 = {\n x: rs.allpts[l - 4 - _i2],\n y: rs.allpts[l - 3 - _i2]\n };\n }\n\n di = dist(p0, p1);\n d0 = d;\n d += di;\n\n if (d >= offset) {\n break;\n }\n }\n\n var pD = offset - d0;\n\n var _t = pD / di;\n\n _t = bound(0, _t, 1);\n p = lineAt(p0, p1, _t);\n angle = lineAngle(p0, p1);\n break;\n }\n }\n\n setRs('labelX', prefix, p.x);\n setRs('labelY', prefix, p.y);\n setRs('labelAutoAngle', prefix, angle);\n };\n\n calculateEndProjection('source');\n calculateEndProjection('target');\n this.applyLabelDimensions(edge);\n};\n\nBRp$6.applyLabelDimensions = function (ele) {\n this.applyPrefixedLabelDimensions(ele);\n\n if (ele.isEdge()) {\n this.applyPrefixedLabelDimensions(ele, 'source');\n this.applyPrefixedLabelDimensions(ele, 'target');\n }\n};\n\nBRp$6.applyPrefixedLabelDimensions = function (ele, prefix) {\n var _p = ele._private;\n var text = this.getLabelText(ele, prefix);\n var labelDims = this.calculateLabelDimensions(ele, text);\n var lineHeight = ele.pstyle('line-height').pfValue;\n var textWrap = ele.pstyle('text-wrap').strValue;\n var lines = getPrefixedProperty(_p.rscratch, 'labelWrapCachedLines', prefix) || [];\n var numLines = textWrap !== 'wrap' ? 1 : Math.max(lines.length, 1);\n var normPerLineHeight = labelDims.height / numLines;\n var labelLineHeight = normPerLineHeight * lineHeight;\n var width = labelDims.width;\n var height = labelDims.height + (numLines - 1) * (lineHeight - 1) * normPerLineHeight;\n setPrefixedProperty(_p.rstyle, 'labelWidth', prefix, width);\n setPrefixedProperty(_p.rscratch, 'labelWidth', prefix, width);\n setPrefixedProperty(_p.rstyle, 'labelHeight', prefix, height);\n setPrefixedProperty(_p.rscratch, 'labelHeight', prefix, height);\n setPrefixedProperty(_p.rscratch, 'labelLineHeight', prefix, labelLineHeight);\n};\n\nBRp$6.getLabelText = function (ele, prefix) {\n var _p = ele._private;\n var pfd = prefix ? prefix + '-' : '';\n var text = ele.pstyle(pfd + 'label').strValue;\n var textTransform = ele.pstyle('text-transform').value;\n\n var rscratch = function rscratch(propName, value) {\n if (value) {\n setPrefixedProperty(_p.rscratch, propName, prefix, value);\n return value;\n } else {\n return getPrefixedProperty(_p.rscratch, propName, prefix);\n }\n }; // for empty text, skip all processing\n\n\n if (!text) {\n return '';\n }\n\n if (textTransform == 'none') ; else if (textTransform == 'uppercase') {\n text = text.toUpperCase();\n } else if (textTransform == 'lowercase') {\n text = text.toLowerCase();\n }\n\n var wrapStyle = ele.pstyle('text-wrap').value;\n\n if (wrapStyle === 'wrap') {\n var labelKey = rscratch('labelKey'); // save recalc if the label is the same as before\n\n if (labelKey != null && rscratch('labelWrapKey') === labelKey) {\n return rscratch('labelWrapCachedText');\n }\n\n var zwsp = \"\\u200B\";\n var lines = text.split('\\n');\n var maxW = ele.pstyle('text-max-width').pfValue;\n var overflow = ele.pstyle('text-overflow-wrap').value;\n var overflowAny = overflow === 'anywhere';\n var wrappedLines = [];\n var wordsRegex = /[\\s\\u200b]+/;\n var wordSeparator = overflowAny ? '' : ' ';\n\n for (var l = 0; l < lines.length; l++) {\n var line = lines[l];\n var lineDims = this.calculateLabelDimensions(ele, line);\n var lineW = lineDims.width;\n\n if (overflowAny) {\n var processedLine = line.split('').join(zwsp);\n line = processedLine;\n }\n\n if (lineW > maxW) {\n // line is too long\n var words = line.split(wordsRegex);\n var subline = '';\n\n for (var w = 0; w < words.length; w++) {\n var word = words[w];\n var testLine = subline.length === 0 ? word : subline + wordSeparator + word;\n var testDims = this.calculateLabelDimensions(ele, testLine);\n var testW = testDims.width;\n\n if (testW <= maxW) {\n // word fits on current line\n subline += word + wordSeparator;\n } else {\n // word starts new line\n if (subline) {\n wrappedLines.push(subline);\n }\n\n subline = word + wordSeparator;\n }\n } // if there's remaining text, put it in a wrapped line\n\n\n if (!subline.match(/^[\\s\\u200b]+$/)) {\n wrappedLines.push(subline);\n }\n } else {\n // line is already short enough\n wrappedLines.push(line);\n }\n } // for\n\n\n rscratch('labelWrapCachedLines', wrappedLines);\n text = rscratch('labelWrapCachedText', wrappedLines.join('\\n'));\n rscratch('labelWrapKey', labelKey);\n } else if (wrapStyle === 'ellipsis') {\n var _maxW = ele.pstyle('text-max-width').pfValue;\n var ellipsized = '';\n var ellipsis = \"\\u2026\";\n var incLastCh = false;\n\n for (var i = 0; i < text.length; i++) {\n var widthWithNextCh = this.calculateLabelDimensions(ele, ellipsized + text[i] + ellipsis).width;\n\n if (widthWithNextCh > _maxW) {\n break;\n }\n\n ellipsized += text[i];\n\n if (i === text.length - 1) {\n incLastCh = true;\n }\n }\n\n if (!incLastCh) {\n ellipsized += ellipsis;\n }\n\n return ellipsized;\n } // if ellipsize\n\n\n return text;\n};\n\nBRp$6.getLabelJustification = function (ele) {\n var justification = ele.pstyle('text-justification').strValue;\n var textHalign = ele.pstyle('text-halign').strValue;\n\n if (justification === 'auto') {\n if (ele.isNode()) {\n switch (textHalign) {\n case 'left':\n return 'right';\n\n case 'right':\n return 'left';\n\n default:\n return 'center';\n }\n } else {\n return 'center';\n }\n } else {\n return justification;\n }\n};\n\nBRp$6.calculateLabelDimensions = function (ele, text) {\n var r = this;\n var cacheKey = hashString(text, ele._private.labelDimsKey);\n var cache = r.labelDimCache || (r.labelDimCache = []);\n var existingVal = cache[cacheKey];\n\n if (existingVal != null) {\n return existingVal;\n }\n\n var sizeMult = 1; // increase the scale to increase accuracy w.r.t. zoomed text\n\n var fStyle = ele.pstyle('font-style').strValue;\n var size = sizeMult * ele.pstyle('font-size').pfValue + 'px';\n var family = ele.pstyle('font-family').strValue;\n var weight = ele.pstyle('font-weight').strValue;\n var div = this.labelCalcDiv;\n\n if (!div) {\n div = this.labelCalcDiv = document.createElement('div'); // eslint-disable-line no-undef\n\n document.body.appendChild(div); // eslint-disable-line no-undef\n }\n\n var ds = div.style; // from ele style\n\n ds.fontFamily = family;\n ds.fontStyle = fStyle;\n ds.fontSize = size;\n ds.fontWeight = weight; // forced style\n\n ds.position = 'absolute';\n ds.left = '-9999px';\n ds.top = '-9999px';\n ds.zIndex = '-1';\n ds.visibility = 'hidden';\n ds.pointerEvents = 'none';\n ds.padding = '0';\n ds.lineHeight = '1'; // - newlines must be taken into account for text-wrap:wrap\n // - since spaces are not collapsed, each space must be taken into account\n\n ds.whiteSpace = 'pre'; // put label content in div\n\n div.textContent = text;\n return cache[cacheKey] = {\n width: Math.ceil(div.clientWidth / sizeMult),\n height: Math.ceil(div.clientHeight / sizeMult)\n };\n};\n\nBRp$6.calculateLabelAngle = function (ele, prefix) {\n var _p = ele._private;\n var rs = _p.rscratch;\n var isEdge = ele.isEdge();\n var prefixDash = prefix ? prefix + '-' : '';\n var rot = ele.pstyle(prefixDash + 'text-rotation');\n var rotStr = rot.strValue;\n\n if (rotStr === 'none') {\n return 0;\n } else if (isEdge && rotStr === 'autorotate') {\n return rs.labelAutoAngle;\n } else if (rotStr === 'autorotate') {\n return 0;\n } else {\n return rot.pfValue;\n }\n};\n\nBRp$6.calculateLabelAngles = function (ele) {\n var r = this;\n var isEdge = ele.isEdge();\n var _p = ele._private;\n var rs = _p.rscratch;\n rs.labelAngle = r.calculateLabelAngle(ele);\n\n if (isEdge) {\n rs.sourceLabelAngle = r.calculateLabelAngle(ele, 'source');\n rs.targetLabelAngle = r.calculateLabelAngle(ele, 'target');\n }\n};\n\nvar BRp$7 = {};\nvar TOO_SMALL_CUT_RECT = 28;\nvar warnedCutRect = false;\n\nBRp$7.getNodeShape = function (node) {\n var r = this;\n var shape = node.pstyle('shape').value;\n\n if (shape === 'cutrectangle' && (node.width() < TOO_SMALL_CUT_RECT || node.height() < TOO_SMALL_CUT_RECT)) {\n if (!warnedCutRect) {\n warn('The `cutrectangle` node shape can not be used at small sizes so `rectangle` is used instead');\n warnedCutRect = true;\n }\n\n return 'rectangle';\n }\n\n if (node.isParent()) {\n if (shape === 'rectangle' || shape === 'roundrectangle' || shape === 'round-rectangle' || shape === 'cutrectangle' || shape === 'cut-rectangle' || shape === 'barrel') {\n return shape;\n } else {\n return 'rectangle';\n }\n }\n\n if (shape === 'polygon') {\n var points = node.pstyle('shape-polygon-points').value;\n return r.nodeShapes.makePolygon(points).name;\n }\n\n return shape;\n};\n\nvar BRp$8 = {};\n\nBRp$8.registerCalculationListeners = function () {\n var cy = this.cy;\n var elesToUpdate = cy.collection();\n var r = this;\n\n var enqueue = function enqueue(eles) {\n var dirtyStyleCaches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n elesToUpdate.merge(eles);\n\n if (dirtyStyleCaches) {\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var _p = ele._private;\n var rstyle = _p.rstyle;\n rstyle.clean = false;\n rstyle.cleanConnected = false;\n }\n }\n };\n\n r.binder(cy).on('bounds.* dirty.*', function onDirtyBounds(e) {\n var ele = e.target;\n enqueue(ele);\n }).on('style.* background.*', function onDirtyStyle(e) {\n var ele = e.target;\n enqueue(ele, false);\n });\n\n var updateEleCalcs = function updateEleCalcs(willDraw) {\n if (willDraw) {\n var fns = r.onUpdateEleCalcsFns;\n\n for (var i = 0; i < elesToUpdate.length; i++) {\n var ele = elesToUpdate[i];\n var rstyle = ele._private.rstyle;\n\n if (ele.isNode() && !rstyle.cleanConnected) {\n enqueue(ele.connectedEdges());\n rstyle.cleanConnected = true;\n }\n }\n\n if (fns) {\n for (var _i = 0; _i < fns.length; _i++) {\n var fn = fns[_i];\n fn(willDraw, elesToUpdate);\n }\n }\n\n r.recalculateRenderedStyle(elesToUpdate);\n elesToUpdate = cy.collection();\n }\n };\n\n r.flushRenderedStyleQueue = function () {\n updateEleCalcs(true);\n };\n\n r.beforeRender(updateEleCalcs, r.beforeRenderPriorities.eleCalcs);\n};\n\nBRp$8.onUpdateEleCalcs = function (fn) {\n var fns = this.onUpdateEleCalcsFns = this.onUpdateEleCalcsFns || [];\n fns.push(fn);\n};\n\nBRp$8.recalculateRenderedStyle = function (eles, useCache) {\n var isCleanConnected = function isCleanConnected(ele) {\n return ele._private.rstyle.cleanConnected;\n };\n\n var edges = [];\n var nodes = []; // the renderer can't be used for calcs when destroyed, e.g. ele.boundingBox()\n\n if (this.destroyed) {\n return;\n } // use cache by default for perf\n\n\n if (useCache === undefined) {\n useCache = true;\n }\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var _p = ele._private;\n var rstyle = _p.rstyle; // an edge may be implicitly dirty b/c of one of its connected nodes\n // (and a request for recalc may come in between frames)\n\n if (ele.isEdge() && (!isCleanConnected(ele.source()) || !isCleanConnected(ele.target()))) {\n rstyle.clean = false;\n } // only update if dirty and in graph\n\n\n if (useCache && rstyle.clean || ele.removed()) {\n continue;\n } // only update if not display: none\n\n\n if (ele.pstyle('display').value === 'none') {\n continue;\n }\n\n if (_p.group === 'nodes') {\n nodes.push(ele);\n } else {\n // edges\n edges.push(ele);\n }\n\n rstyle.clean = true;\n } // update node data from projections\n\n\n for (var _i2 = 0; _i2 < nodes.length; _i2++) {\n var _ele = nodes[_i2];\n var _p2 = _ele._private;\n var _rstyle = _p2.rstyle;\n\n var pos = _ele.position();\n\n this.recalculateNodeLabelProjection(_ele);\n _rstyle.nodeX = pos.x;\n _rstyle.nodeY = pos.y;\n _rstyle.nodeW = _ele.pstyle('width').pfValue;\n _rstyle.nodeH = _ele.pstyle('height').pfValue;\n }\n\n this.recalculateEdgeProjections(edges); // update edge data from projections\n\n for (var _i3 = 0; _i3 < edges.length; _i3++) {\n var _ele2 = edges[_i3];\n var _p3 = _ele2._private;\n var _rstyle2 = _p3.rstyle;\n var rs = _p3.rscratch; // update rstyle positions\n\n _rstyle2.srcX = rs.arrowStartX;\n _rstyle2.srcY = rs.arrowStartY;\n _rstyle2.tgtX = rs.arrowEndX;\n _rstyle2.tgtY = rs.arrowEndY;\n _rstyle2.midX = rs.midX;\n _rstyle2.midY = rs.midY;\n _rstyle2.labelAngle = rs.labelAngle;\n _rstyle2.sourceLabelAngle = rs.sourceLabelAngle;\n _rstyle2.targetLabelAngle = rs.targetLabelAngle;\n }\n};\n\nvar BRp$9 = {};\n\nBRp$9.updateCachedGrabbedEles = function () {\n var eles = this.cachedZSortedEles;\n\n if (!eles) {\n // just let this be recalculated on the next z sort tick\n return;\n }\n\n eles.drag = [];\n eles.nondrag = [];\n var grabTargets = [];\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var rs = ele._private.rscratch;\n\n if (ele.grabbed() && !ele.isParent()) {\n grabTargets.push(ele);\n } else if (rs.inDragLayer) {\n eles.drag.push(ele);\n } else {\n eles.nondrag.push(ele);\n }\n } // put the grab target nodes last so it's on top of its neighbourhood\n\n\n for (var i = 0; i < grabTargets.length; i++) {\n var ele = grabTargets[i];\n eles.drag.push(ele);\n }\n};\n\nBRp$9.invalidateCachedZSortedEles = function () {\n this.cachedZSortedEles = null;\n};\n\nBRp$9.getCachedZSortedEles = function (forceRecalc) {\n if (forceRecalc || !this.cachedZSortedEles) {\n var eles = this.cy.mutableElements().toArray();\n eles.sort(zIndexSort);\n eles.interactive = eles.filter(function (ele) {\n return ele.interactive();\n });\n this.cachedZSortedEles = eles;\n this.updateCachedGrabbedEles();\n } else {\n eles = this.cachedZSortedEles;\n }\n\n return eles;\n};\n\nvar BRp$a = {};\n[BRp$1, BRp$2, BRp$3, BRp$4, BRp$5, BRp$6, BRp$7, BRp$8, BRp$9].forEach(function (props) {\n extend(BRp$a, props);\n});\n\nvar BRp$b = {};\n\nBRp$b.getCachedImage = function (url, crossOrigin, onLoad) {\n var r = this;\n var imageCache = r.imageCache = r.imageCache || {};\n var cache = imageCache[url];\n\n if (cache) {\n if (!cache.image.complete) {\n cache.image.addEventListener('load', onLoad);\n }\n\n return cache.image;\n } else {\n cache = imageCache[url] = imageCache[url] || {};\n var image = cache.image = new Image(); // eslint-disable-line no-undef\n\n image.addEventListener('load', onLoad);\n image.addEventListener('error', function () {\n image.error = true;\n }); // #1582 safari doesn't load data uris with crossOrigin properly\n // https://bugs.webkit.org/show_bug.cgi?id=123978\n\n var dataUriPrefix = 'data:';\n var isDataUri = url.substring(0, dataUriPrefix.length).toLowerCase() === dataUriPrefix;\n\n if (!isDataUri) {\n image.crossOrigin = crossOrigin; // prevent tainted canvas\n }\n\n image.src = url;\n return image;\n }\n};\n\nvar BRp$c = {};\n/* global document, window, ResizeObserver, MutationObserver */\n\nBRp$c.registerBinding = function (target, event, handler, useCapture) {\n // eslint-disable-line no-unused-vars\n var args = Array.prototype.slice.apply(arguments, [1]); // copy\n\n var b = this.binder(target);\n return b.on.apply(b, args);\n};\n\nBRp$c.binder = function (tgt) {\n var r = this;\n var tgtIsDom = tgt === window || tgt === document || tgt === document.body || domElement(tgt);\n\n if (r.supportsPassiveEvents == null) {\n // from https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection\n var supportsPassive = false;\n\n try {\n var opts = Object.defineProperty({}, 'passive', {\n get: function get() {\n supportsPassive = true;\n return true;\n }\n });\n window.addEventListener('test', null, opts);\n } catch (err) {// not supported\n }\n\n r.supportsPassiveEvents = supportsPassive;\n }\n\n var on = function on(event, handler, useCapture) {\n var args = Array.prototype.slice.call(arguments);\n\n if (tgtIsDom && r.supportsPassiveEvents) {\n // replace useCapture w/ opts obj\n args[2] = {\n capture: useCapture != null ? useCapture : false,\n passive: false,\n once: false\n };\n }\n\n r.bindings.push({\n target: tgt,\n args: args\n });\n (tgt.addEventListener || tgt.on).apply(tgt, args);\n return this;\n };\n\n return {\n on: on,\n addEventListener: on,\n addListener: on,\n bind: on\n };\n};\n\nBRp$c.nodeIsDraggable = function (node) {\n return node && node.isNode() && !node.locked() && node.grabbable();\n};\n\nBRp$c.nodeIsGrabbable = function (node) {\n return this.nodeIsDraggable(node) && node.interactive();\n};\n\nBRp$c.load = function () {\n var r = this;\n\n var isSelected = function isSelected(ele) {\n return ele.selected();\n };\n\n var triggerEvents = function triggerEvents(target, names, e, position) {\n if (target == null) {\n target = r.cy;\n }\n\n for (var i = 0; i < names.length; i++) {\n var name = names[i];\n target.emit({\n originalEvent: e,\n type: name,\n position: position\n });\n }\n };\n\n var isMultSelKeyDown = function isMultSelKeyDown(e) {\n return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey\n };\n\n var allowPanningPassthrough = function allowPanningPassthrough(down, downs) {\n var allowPassthrough = true;\n\n if (r.cy.hasCompoundNodes() && down && down.pannable()) {\n // a grabbable compound node below the ele => no passthrough panning\n for (var i = 0; downs && i < downs.length; i++) {\n var down = downs[i];\n\n if (down.isNode() && down.isParent()) {\n allowPassthrough = false;\n break;\n }\n }\n } else {\n allowPassthrough = true;\n }\n\n return allowPassthrough;\n };\n\n var setGrabbed = function setGrabbed(ele) {\n ele[0]._private.grabbed = true;\n };\n\n var setFreed = function setFreed(ele) {\n ele[0]._private.grabbed = false;\n };\n\n var setInDragLayer = function setInDragLayer(ele) {\n ele[0]._private.rscratch.inDragLayer = true;\n };\n\n var setOutDragLayer = function setOutDragLayer(ele) {\n ele[0]._private.rscratch.inDragLayer = false;\n };\n\n var setGrabTarget = function setGrabTarget(ele) {\n ele[0]._private.rscratch.isGrabTarget = true;\n };\n\n var removeGrabTarget = function removeGrabTarget(ele) {\n ele[0]._private.rscratch.isGrabTarget = false;\n };\n\n var addToDragList = function addToDragList(ele, opts) {\n var list = opts.addToList;\n var listHasEle = list.has(ele);\n\n if (!listHasEle) {\n list.merge(ele);\n setGrabbed(ele);\n }\n }; // helper function to determine which child nodes and inner edges\n // of a compound node to be dragged as well as the grabbed and selected nodes\n\n\n var addDescendantsToDrag = function addDescendantsToDrag(node, opts) {\n if (!node.cy().hasCompoundNodes()) {\n return;\n }\n\n if (opts.inDragLayer == null && opts.addToList == null) {\n return;\n } // nothing to do\n\n\n var innerNodes = node.descendants();\n\n if (opts.inDragLayer) {\n innerNodes.forEach(setInDragLayer);\n innerNodes.connectedEdges().forEach(setInDragLayer);\n }\n\n if (opts.addToList) {\n opts.addToList.unmerge(innerNodes);\n }\n }; // adds the given nodes and its neighbourhood to the drag layer\n\n\n var addNodesToDrag = function addNodesToDrag(nodes, opts) {\n opts = opts || {};\n var hasCompoundNodes = nodes.cy().hasCompoundNodes();\n\n if (opts.inDragLayer) {\n nodes.forEach(setInDragLayer);\n nodes.neighborhood().stdFilter(function (ele) {\n return !hasCompoundNodes || ele.isEdge();\n }).forEach(setInDragLayer);\n }\n\n if (opts.addToList) {\n nodes.forEach(function (ele) {\n addToDragList(ele, opts);\n });\n }\n\n addDescendantsToDrag(nodes, opts); // always add to drag\n // also add nodes and edges related to the topmost ancestor\n\n updateAncestorsInDragLayer(nodes, {\n inDragLayer: opts.inDragLayer\n });\n r.updateCachedGrabbedEles();\n };\n\n var addNodeToDrag = addNodesToDrag;\n\n var freeDraggedElements = function freeDraggedElements(grabbedEles) {\n if (!grabbedEles) {\n return;\n } // just go over all elements rather than doing a bunch of (possibly expensive) traversals\n\n\n r.getCachedZSortedEles().forEach(function (ele) {\n setFreed(ele);\n setOutDragLayer(ele);\n removeGrabTarget(ele);\n });\n r.updateCachedGrabbedEles();\n }; // helper function to determine which ancestor nodes and edges should go\n // to the drag layer (or should be removed from drag layer).\n\n\n var updateAncestorsInDragLayer = function updateAncestorsInDragLayer(node, opts) {\n if (opts.inDragLayer == null && opts.addToList == null) {\n return;\n } // nothing to do\n\n\n if (!node.cy().hasCompoundNodes()) {\n return;\n } // find top-level parent\n\n\n var parent = node.ancestors().orphans(); // no parent node: no nodes to add to the drag layer\n\n if (parent.same(node)) {\n return;\n }\n\n var nodes = parent.descendants().spawnSelf().merge(parent).unmerge(node).unmerge(node.descendants());\n var edges = nodes.connectedEdges();\n\n if (opts.inDragLayer) {\n edges.forEach(setInDragLayer);\n nodes.forEach(setInDragLayer);\n }\n\n if (opts.addToList) {\n nodes.forEach(function (ele) {\n addToDragList(ele, opts);\n });\n }\n };\n\n var blurActiveDomElement = function blurActiveDomElement() {\n if (document.activeElement != null && document.activeElement.blur != null) {\n document.activeElement.blur();\n }\n };\n\n var haveMutationsApi = typeof MutationObserver !== 'undefined';\n var haveResizeObserverApi = typeof ResizeObserver !== 'undefined'; // watch for when the cy container is removed from the dom\n\n if (haveMutationsApi) {\n r.removeObserver = new MutationObserver(function (mutns) {\n // eslint-disable-line no-undef\n for (var i = 0; i < mutns.length; i++) {\n var mutn = mutns[i];\n var rNodes = mutn.removedNodes;\n\n if (rNodes) {\n for (var j = 0; j < rNodes.length; j++) {\n var rNode = rNodes[j];\n\n if (rNode === r.container) {\n r.destroy();\n break;\n }\n }\n }\n }\n });\n\n if (r.container.parentNode) {\n r.removeObserver.observe(r.container.parentNode, {\n childList: true\n });\n }\n } else {\n r.registerBinding(r.container, 'DOMNodeRemoved', function (e) {\n // eslint-disable-line no-unused-vars\n r.destroy();\n });\n }\n\n var onResize = util(function () {\n r.cy.resize();\n }, 100);\n\n if (haveMutationsApi) {\n r.styleObserver = new MutationObserver(onResize); // eslint-disable-line no-undef\n\n r.styleObserver.observe(r.container, {\n attributes: true\n });\n } // auto resize\n\n\n r.registerBinding(window, 'resize', onResize); // eslint-disable-line no-undef\n\n if (haveResizeObserverApi) {\n r.resizeObserver = new ResizeObserver(onResize); // eslint-disable-line no-undef\n\n r.resizeObserver.observe(r.container);\n }\n\n var forEachUp = function forEachUp(domEle, fn) {\n while (domEle != null) {\n fn(domEle);\n domEle = domEle.parentNode;\n }\n };\n\n var invalidateCoords = function invalidateCoords() {\n r.invalidateContainerClientCoordsCache();\n };\n\n forEachUp(r.container, function (domEle) {\n r.registerBinding(domEle, 'transitionend', invalidateCoords);\n r.registerBinding(domEle, 'animationend', invalidateCoords);\n r.registerBinding(domEle, 'scroll', invalidateCoords);\n }); // stop right click menu from appearing on cy\n\n r.registerBinding(r.container, 'contextmenu', function (e) {\n e.preventDefault();\n });\n\n var inBoxSelection = function inBoxSelection() {\n return r.selection[4] !== 0;\n };\n\n var eventInContainer = function eventInContainer(e) {\n // save cycles if mouse events aren't to be captured\n var containerPageCoords = r.findContainerClientCoords();\n var x = containerPageCoords[0];\n var y = containerPageCoords[1];\n var width = containerPageCoords[2];\n var height = containerPageCoords[3];\n var positions = e.touches ? e.touches : [e];\n var atLeastOnePosInside = false;\n\n for (var i = 0; i < positions.length; i++) {\n var p = positions[i];\n\n if (x <= p.clientX && p.clientX <= x + width && y <= p.clientY && p.clientY <= y + height) {\n atLeastOnePosInside = true;\n break;\n }\n }\n\n if (!atLeastOnePosInside) {\n return false;\n }\n\n var container = r.container;\n var target = e.target;\n var tParent = target.parentNode;\n var containerIsTarget = false;\n\n while (tParent) {\n if (tParent === container) {\n containerIsTarget = true;\n break;\n }\n\n tParent = tParent.parentNode;\n }\n\n if (!containerIsTarget) {\n return false;\n } // if target is outisde cy container, then this event is not for us\n\n\n return true;\n }; // Primary key\n\n\n r.registerBinding(r.container, 'mousedown', function mousedownHandler(e) {\n if (!eventInContainer(e)) {\n return;\n }\n\n e.preventDefault();\n blurActiveDomElement();\n r.hoverData.capture = true;\n r.hoverData.which = e.which;\n var cy = r.cy;\n var gpos = [e.clientX, e.clientY];\n var pos = r.projectIntoViewport(gpos[0], gpos[1]);\n var select = r.selection;\n var nears = r.findNearestElements(pos[0], pos[1], true, false);\n var near = nears[0];\n var draggedElements = r.dragData.possibleDragElements;\n r.hoverData.mdownPos = pos;\n r.hoverData.mdownGPos = gpos;\n\n var checkForTaphold = function checkForTaphold() {\n r.hoverData.tapholdCancelled = false;\n clearTimeout(r.hoverData.tapholdTimeout);\n r.hoverData.tapholdTimeout = setTimeout(function () {\n if (r.hoverData.tapholdCancelled) {\n return;\n } else {\n var ele = r.hoverData.down;\n\n if (ele) {\n ele.emit({\n originalEvent: e,\n type: 'taphold',\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n } else {\n cy.emit({\n originalEvent: e,\n type: 'taphold',\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n }\n }\n }, r.tapholdDuration);\n }; // Right click button\n\n\n if (e.which == 3) {\n r.hoverData.cxtStarted = true;\n var cxtEvt = {\n originalEvent: e,\n type: 'cxttapstart',\n position: {\n x: pos[0],\n y: pos[1]\n }\n };\n\n if (near) {\n near.activate();\n near.emit(cxtEvt);\n r.hoverData.down = near;\n } else {\n cy.emit(cxtEvt);\n }\n\n r.hoverData.downTime = new Date().getTime();\n r.hoverData.cxtDragged = false; // Primary button\n } else if (e.which == 1) {\n if (near) {\n near.activate();\n } // Element dragging\n\n\n {\n // If something is under the cursor and it is draggable, prepare to grab it\n if (near != null) {\n if (r.nodeIsGrabbable(near)) {\n var makeEvent = function makeEvent(type) {\n return {\n originalEvent: e,\n type: type,\n position: {\n x: pos[0],\n y: pos[1]\n }\n };\n };\n\n var triggerGrab = function triggerGrab(ele) {\n ele.emit(makeEvent('grab'));\n };\n\n setGrabTarget(near);\n\n if (!near.selected()) {\n draggedElements = r.dragData.possibleDragElements = cy.collection();\n addNodeToDrag(near, {\n addToList: draggedElements\n });\n near.emit(makeEvent('grabon')).emit(makeEvent('grab'));\n } else {\n draggedElements = r.dragData.possibleDragElements = cy.collection();\n var selectedNodes = cy.$(function (ele) {\n return ele.isNode() && ele.selected() && r.nodeIsGrabbable(ele);\n });\n addNodesToDrag(selectedNodes, {\n addToList: draggedElements\n });\n near.emit(makeEvent('grabon'));\n selectedNodes.forEach(triggerGrab);\n }\n\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n }\n }\n\n r.hoverData.down = near;\n r.hoverData.downs = nears;\n r.hoverData.downTime = new Date().getTime();\n }\n triggerEvents(near, ['mousedown', 'tapstart', 'vmousedown'], e, {\n x: pos[0],\n y: pos[1]\n });\n\n if (near == null) {\n select[4] = 1;\n r.data.bgActivePosistion = {\n x: pos[0],\n y: pos[1]\n };\n r.redrawHint('select', true);\n r.redraw();\n } else if (near.pannable()) {\n select[4] = 1; // for future pan\n }\n\n checkForTaphold();\n } // Initialize selection box coordinates\n\n\n select[0] = select[2] = pos[0];\n select[1] = select[3] = pos[1];\n }, false);\n r.registerBinding(window, 'mousemove', function mousemoveHandler(e) {\n // eslint-disable-line no-undef\n var capture = r.hoverData.capture;\n\n if (!capture && !eventInContainer(e)) {\n return;\n }\n\n var preventDefault = false;\n var cy = r.cy;\n var zoom = cy.zoom();\n var gpos = [e.clientX, e.clientY];\n var pos = r.projectIntoViewport(gpos[0], gpos[1]);\n var mdownPos = r.hoverData.mdownPos;\n var mdownGPos = r.hoverData.mdownGPos;\n var select = r.selection;\n var near = null;\n\n if (!r.hoverData.draggingEles && !r.hoverData.dragging && !r.hoverData.selecting) {\n near = r.findNearestElement(pos[0], pos[1], true, false);\n }\n\n var last = r.hoverData.last;\n var down = r.hoverData.down;\n var disp = [pos[0] - select[2], pos[1] - select[3]];\n var draggedElements = r.dragData.possibleDragElements;\n var isOverThresholdDrag;\n\n if (mdownGPos) {\n var dx = gpos[0] - mdownGPos[0];\n var dx2 = dx * dx;\n var dy = gpos[1] - mdownGPos[1];\n var dy2 = dy * dy;\n var dist2 = dx2 + dy2;\n r.hoverData.isOverThresholdDrag = isOverThresholdDrag = dist2 >= r.desktopTapThreshold2;\n }\n\n var multSelKeyDown = isMultSelKeyDown(e);\n\n if (isOverThresholdDrag) {\n r.hoverData.tapholdCancelled = true;\n }\n\n var updateDragDelta = function updateDragDelta() {\n var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || [];\n\n if (dragDelta.length === 0) {\n dragDelta.push(disp[0]);\n dragDelta.push(disp[1]);\n } else {\n dragDelta[0] += disp[0];\n dragDelta[1] += disp[1];\n }\n };\n\n preventDefault = true;\n triggerEvents(near, ['mousemove', 'vmousemove', 'tapdrag'], e, {\n x: pos[0],\n y: pos[1]\n });\n\n var goIntoBoxMode = function goIntoBoxMode() {\n r.data.bgActivePosistion = undefined;\n\n if (!r.hoverData.selecting) {\n cy.emit({\n originalEvent: e,\n type: 'boxstart',\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n }\n\n select[4] = 1;\n r.hoverData.selecting = true;\n r.redrawHint('select', true);\n r.redraw();\n }; // trigger context drag if rmouse down\n\n\n if (r.hoverData.which === 3) {\n // but only if over threshold\n if (isOverThresholdDrag) {\n var cxtEvt = {\n originalEvent: e,\n type: 'cxtdrag',\n position: {\n x: pos[0],\n y: pos[1]\n }\n };\n\n if (down) {\n down.emit(cxtEvt);\n } else {\n cy.emit(cxtEvt);\n }\n\n r.hoverData.cxtDragged = true;\n\n if (!r.hoverData.cxtOver || near !== r.hoverData.cxtOver) {\n if (r.hoverData.cxtOver) {\n r.hoverData.cxtOver.emit({\n originalEvent: e,\n type: 'cxtdragout',\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n }\n\n r.hoverData.cxtOver = near;\n\n if (near) {\n near.emit({\n originalEvent: e,\n type: 'cxtdragover',\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n }\n }\n } // Check if we are drag panning the entire graph\n\n } else if (r.hoverData.dragging) {\n preventDefault = true;\n\n if (cy.panningEnabled() && cy.userPanningEnabled()) {\n var deltaP;\n\n if (r.hoverData.justStartedPan) {\n var mdPos = r.hoverData.mdownPos;\n deltaP = {\n x: (pos[0] - mdPos[0]) * zoom,\n y: (pos[1] - mdPos[1]) * zoom\n };\n r.hoverData.justStartedPan = false;\n } else {\n deltaP = {\n x: disp[0] * zoom,\n y: disp[1] * zoom\n };\n }\n\n cy.panBy(deltaP);\n r.hoverData.dragged = true;\n } // Needs reproject due to pan changing viewport\n\n\n pos = r.projectIntoViewport(e.clientX, e.clientY); // Checks primary button down & out of time & mouse not moved much\n } else if (select[4] == 1 && (down == null || down.pannable())) {\n if (isOverThresholdDrag) {\n if (!r.hoverData.dragging && cy.boxSelectionEnabled() && (multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled())) {\n goIntoBoxMode();\n } else if (!r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled()) {\n var allowPassthrough = allowPanningPassthrough(down, r.hoverData.downs);\n\n if (allowPassthrough) {\n r.hoverData.dragging = true;\n r.hoverData.justStartedPan = true;\n select[4] = 0;\n r.data.bgActivePosistion = array2point(mdownPos);\n r.redrawHint('select', true);\n r.redraw();\n }\n }\n\n if (down && down.pannable() && down.active()) {\n down.unactivate();\n }\n }\n } else {\n if (down && down.pannable() && down.active()) {\n down.unactivate();\n }\n\n if ((!down || !down.grabbed()) && near != last) {\n if (last) {\n triggerEvents(last, ['mouseout', 'tapdragout'], e, {\n x: pos[0],\n y: pos[1]\n });\n }\n\n if (near) {\n triggerEvents(near, ['mouseover', 'tapdragover'], e, {\n x: pos[0],\n y: pos[1]\n });\n }\n\n r.hoverData.last = near;\n }\n\n if (down) {\n if (isOverThresholdDrag) {\n // then we can take action\n if (cy.boxSelectionEnabled() && multSelKeyDown) {\n // then selection overrides\n if (down && down.grabbed()) {\n freeDraggedElements(draggedElements);\n down.emit('freeon');\n draggedElements.emit('free');\n\n if (r.dragData.didDrag) {\n down.emit('dragfreeon');\n draggedElements.emit('dragfree');\n }\n }\n\n goIntoBoxMode();\n } else if (down && down.grabbed() && r.nodeIsDraggable(down)) {\n // drag node\n var justStartedDrag = !r.dragData.didDrag;\n\n if (justStartedDrag) {\n r.redrawHint('eles', true);\n }\n\n r.dragData.didDrag = true; // indicate that we actually did drag the node\n\n var toTrigger = cy.collection(); // now, add the elements to the drag layer if not done already\n\n if (!r.hoverData.draggingEles) {\n addNodesToDrag(draggedElements, {\n inDragLayer: true\n });\n }\n\n var totalShift = {\n x: 0,\n y: 0\n };\n\n if (number(disp[0]) && number(disp[1])) {\n totalShift.x += disp[0];\n totalShift.y += disp[1];\n\n if (justStartedDrag) {\n var dragDelta = r.hoverData.dragDelta;\n\n if (dragDelta && number(dragDelta[0]) && number(dragDelta[1])) {\n totalShift.x += dragDelta[0];\n totalShift.y += dragDelta[1];\n }\n }\n }\n\n for (var i = 0; i < draggedElements.length; i++) {\n var dEle = draggedElements[i];\n\n if (r.nodeIsDraggable(dEle) && dEle.grabbed()) {\n toTrigger.merge(dEle);\n }\n }\n\n r.hoverData.draggingEles = true;\n toTrigger.silentShift(totalShift).emit('position drag');\n r.redrawHint('drag', true);\n r.redraw();\n }\n } else {\n // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant\n updateDragDelta();\n }\n } // prevent the dragging from triggering text selection on the page\n\n\n preventDefault = true;\n }\n\n select[2] = pos[0];\n select[3] = pos[1];\n\n if (preventDefault) {\n if (e.stopPropagation) e.stopPropagation();\n if (e.preventDefault) e.preventDefault();\n return false;\n }\n }, false);\n r.registerBinding(window, 'mouseup', function mouseupHandler(e) {\n // eslint-disable-line no-undef\n var capture = r.hoverData.capture;\n\n if (!capture) {\n return;\n }\n\n r.hoverData.capture = false;\n var cy = r.cy;\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n var select = r.selection;\n var near = r.findNearestElement(pos[0], pos[1], true, false);\n var draggedElements = r.dragData.possibleDragElements;\n var down = r.hoverData.down;\n var multSelKeyDown = isMultSelKeyDown(e);\n\n if (r.data.bgActivePosistion) {\n r.redrawHint('select', true);\n r.redraw();\n }\n\n r.hoverData.tapholdCancelled = true;\n r.data.bgActivePosistion = undefined; // not active bg now\n\n if (down) {\n down.unactivate();\n }\n\n if (r.hoverData.which === 3) {\n var cxtEvt = {\n originalEvent: e,\n type: 'cxttapend',\n position: {\n x: pos[0],\n y: pos[1]\n }\n };\n\n if (down) {\n down.emit(cxtEvt);\n } else {\n cy.emit(cxtEvt);\n }\n\n if (!r.hoverData.cxtDragged) {\n var cxtTap = {\n originalEvent: e,\n type: 'cxttap',\n position: {\n x: pos[0],\n y: pos[1]\n }\n };\n\n if (down) {\n down.emit(cxtTap);\n } else {\n cy.emit(cxtTap);\n }\n }\n\n r.hoverData.cxtDragged = false;\n r.hoverData.which = null;\n } else if (r.hoverData.which === 1) {\n triggerEvents(near, ['mouseup', 'tapend', 'vmouseup'], e, {\n x: pos[0],\n y: pos[1]\n });\n\n if (!r.dragData.didDrag // didn't move a node around\n && !r.hoverData.dragged // didn't pan\n && !r.hoverData.selecting // not box selection\n && !r.hoverData.isOverThresholdDrag // didn't move too much\n ) {\n triggerEvents(down, ['click', 'tap', 'vclick'], e, {\n x: pos[0],\n y: pos[1]\n });\n } // Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something\n\n\n if (down == null && // not mousedown on node\n !r.dragData.didDrag // didn't move the node around\n && !r.hoverData.selecting // not box selection\n && !r.hoverData.dragged // didn't pan\n && !isMultSelKeyDown(e)) {\n cy.$(isSelected).unselect(['tapunselect']);\n\n if (draggedElements.length > 0) {\n r.redrawHint('eles', true);\n }\n\n r.dragData.possibleDragElements = draggedElements = cy.collection();\n } // Single selection\n\n\n if (near == down && !r.dragData.didDrag && !r.hoverData.selecting) {\n if (near != null && near._private.selectable) {\n if (r.hoverData.dragging) ; else if (cy.selectionType() === 'additive' || multSelKeyDown) {\n if (near.selected()) {\n near.unselect(['tapunselect']);\n } else {\n near.select(['tapselect']);\n }\n } else {\n if (!multSelKeyDown) {\n cy.$(isSelected).unmerge(near).unselect(['tapunselect']);\n near.select(['tapselect']);\n }\n }\n\n r.redrawHint('eles', true);\n }\n }\n\n if (r.hoverData.selecting) {\n var box = cy.collection(r.getAllInBox(select[0], select[1], select[2], select[3]));\n r.redrawHint('select', true);\n\n if (box.length > 0) {\n r.redrawHint('eles', true);\n }\n\n cy.emit({\n type: 'boxend',\n originalEvent: e,\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n\n var eleWouldBeSelected = function eleWouldBeSelected(ele) {\n return ele.selectable() && !ele.selected();\n };\n\n if (cy.selectionType() === 'additive') {\n box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect');\n } else {\n if (!multSelKeyDown) {\n cy.$(isSelected).unmerge(box).unselect();\n }\n\n box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect');\n } // always need redraw in case eles unselectable\n\n\n r.redraw();\n } // Cancel drag pan\n\n\n if (r.hoverData.dragging) {\n r.hoverData.dragging = false;\n r.redrawHint('select', true);\n r.redrawHint('eles', true);\n r.redraw();\n }\n\n if (!select[4]) {\n r.redrawHint('drag', true);\n r.redrawHint('eles', true);\n var downWasGrabbed = down && down.grabbed();\n freeDraggedElements(draggedElements);\n\n if (downWasGrabbed) {\n down.emit('freeon');\n draggedElements.emit('free');\n\n if (r.dragData.didDrag) {\n down.emit('dragfreeon');\n draggedElements.emit('dragfree');\n }\n }\n }\n } // else not right mouse\n\n\n select[4] = 0;\n r.hoverData.down = null;\n r.hoverData.cxtStarted = false;\n r.hoverData.draggingEles = false;\n r.hoverData.selecting = false;\n r.hoverData.isOverThresholdDrag = false;\n r.dragData.didDrag = false;\n r.hoverData.dragged = false;\n r.hoverData.dragDelta = [];\n r.hoverData.mdownPos = null;\n r.hoverData.mdownGPos = null;\n }, false);\n\n var wheelHandler = function wheelHandler(e) {\n if (r.scrollingPage) {\n return;\n } // while scrolling, ignore wheel-to-zoom\n\n\n var cy = r.cy;\n var zoom = cy.zoom();\n var pan = cy.pan();\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n var rpos = [pos[0] * zoom + pan.x, pos[1] * zoom + pan.y];\n\n if (r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection()) {\n // if pan dragging or cxt dragging, wheel movements make no zoom\n e.preventDefault();\n return;\n }\n\n if (cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled()) {\n e.preventDefault();\n r.data.wheelZooming = true;\n clearTimeout(r.data.wheelTimeout);\n r.data.wheelTimeout = setTimeout(function () {\n r.data.wheelZooming = false;\n r.redrawHint('eles', true);\n r.redraw();\n }, 150);\n var diff;\n\n if (e.deltaY != null) {\n diff = e.deltaY / -250;\n } else if (e.wheelDeltaY != null) {\n diff = e.wheelDeltaY / 1000;\n } else {\n diff = e.wheelDelta / 1000;\n }\n\n diff = diff * r.wheelSensitivity;\n var needsWheelFix = e.deltaMode === 1;\n\n if (needsWheelFix) {\n // fixes slow wheel events on ff/linux and ff/windows\n diff *= 33;\n }\n\n var newZoom = cy.zoom() * Math.pow(10, diff);\n\n if (e.type === 'gesturechange') {\n newZoom = r.gestureStartZoom * e.scale;\n }\n\n cy.zoom({\n level: newZoom,\n renderedPosition: {\n x: rpos[0],\n y: rpos[1]\n }\n });\n }\n }; // Functions to help with whether mouse wheel should trigger zooming\n // --\n\n\n r.registerBinding(r.container, 'wheel', wheelHandler, true); // disable nonstandard wheel events\n // r.registerBinding(r.container, 'mousewheel', wheelHandler, true);\n // r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true);\n // r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox\n\n r.registerBinding(window, 'scroll', function scrollHandler(e) {\n // eslint-disable-line no-unused-vars\n r.scrollingPage = true;\n clearTimeout(r.scrollingPageTimeout);\n r.scrollingPageTimeout = setTimeout(function () {\n r.scrollingPage = false;\n }, 250);\n }, true); // desktop safari pinch to zoom start\n\n r.registerBinding(r.container, 'gesturestart', function gestureStartHandler(e) {\n r.gestureStartZoom = r.cy.zoom();\n\n if (!r.hasTouchStarted) {\n // don't affect touch devices like iphone\n e.preventDefault();\n }\n }, true);\n r.registerBinding(r.container, 'gesturechange', function (e) {\n if (!r.hasTouchStarted) {\n // don't affect touch devices like iphone\n wheelHandler(e);\n }\n }, true); // Functions to help with handling mouseout/mouseover on the Cytoscape container\n // Handle mouseout on Cytoscape container\n\n r.registerBinding(r.container, 'mouseout', function mouseOutHandler(e) {\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n r.cy.emit({\n originalEvent: e,\n type: 'mouseout',\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n }, false);\n r.registerBinding(r.container, 'mouseover', function mouseOverHandler(e) {\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n r.cy.emit({\n originalEvent: e,\n type: 'mouseover',\n position: {\n x: pos[0],\n y: pos[1]\n }\n });\n }, false);\n var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom\n\n var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom\n\n var center1, modelCenter1; // center point on start pinch to zoom\n\n var offsetLeft, offsetTop;\n var containerWidth, containerHeight;\n var twoFingersStartInside;\n\n var distance = function distance(x1, y1, x2, y2) {\n return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\n };\n\n var distanceSq = function distanceSq(x1, y1, x2, y2) {\n return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);\n };\n\n var touchstartHandler;\n r.registerBinding(r.container, 'touchstart', touchstartHandler = function touchstartHandler(e) {\n r.hasTouchStarted = true;\n\n if (!eventInContainer(e)) {\n return;\n }\n\n blurActiveDomElement();\n r.touchData.capture = true;\n r.data.bgActivePosistion = undefined;\n var cy = r.cy;\n var now = r.touchData.now;\n var earlier = r.touchData.earlier;\n\n if (e.touches[0]) {\n var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n now[0] = pos[0];\n now[1] = pos[1];\n }\n\n if (e.touches[1]) {\n var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);\n now[2] = pos[0];\n now[3] = pos[1];\n }\n\n if (e.touches[2]) {\n var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);\n now[4] = pos[0];\n now[5] = pos[1];\n } // record starting points for pinch-to-zoom\n\n\n if (e.touches[1]) {\n r.touchData.singleTouchMoved = true;\n freeDraggedElements(r.dragData.touchDragEles);\n var offsets = r.findContainerClientCoords();\n offsetLeft = offsets[0];\n offsetTop = offsets[1];\n containerWidth = offsets[2];\n containerHeight = offsets[3];\n f1x1 = e.touches[0].clientX - offsetLeft;\n f1y1 = e.touches[0].clientY - offsetTop;\n f2x1 = e.touches[1].clientX - offsetLeft;\n f2y1 = e.touches[1].clientY - offsetTop;\n twoFingersStartInside = 0 <= f1x1 && f1x1 <= containerWidth && 0 <= f2x1 && f2x1 <= containerWidth && 0 <= f1y1 && f1y1 <= containerHeight && 0 <= f2y1 && f2y1 <= containerHeight;\n var pan = cy.pan();\n var zoom = cy.zoom();\n distance1 = distance(f1x1, f1y1, f2x1, f2y1);\n distance1Sq = distanceSq(f1x1, f1y1, f2x1, f2y1);\n center1 = [(f1x1 + f2x1) / 2, (f1y1 + f2y1) / 2];\n modelCenter1 = [(center1[0] - pan.x) / zoom, (center1[1] - pan.y) / zoom]; // consider context tap\n\n var cxtDistThreshold = 200;\n var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold;\n\n if (distance1Sq < cxtDistThresholdSq && !e.touches[2]) {\n var near1 = r.findNearestElement(now[0], now[1], true, true);\n var near2 = r.findNearestElement(now[2], now[3], true, true);\n\n if (near1 && near1.isNode()) {\n near1.activate().emit({\n originalEvent: e,\n type: 'cxttapstart',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n r.touchData.start = near1;\n } else if (near2 && near2.isNode()) {\n near2.activate().emit({\n originalEvent: e,\n type: 'cxttapstart',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n r.touchData.start = near2;\n } else {\n cy.emit({\n originalEvent: e,\n type: 'cxttapstart',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n }\n\n if (r.touchData.start) {\n r.touchData.start._private.grabbed = false;\n }\n\n r.touchData.cxt = true;\n r.touchData.cxtDragged = false;\n r.data.bgActivePosistion = undefined;\n r.redraw();\n return;\n }\n }\n\n if (e.touches[2]) {\n // ignore\n // safari on ios pans the page otherwise (normally you should be able to preventdefault on touchmove...)\n if (cy.boxSelectionEnabled()) {\n e.preventDefault();\n }\n } else if (e.touches[1]) ; else if (e.touches[0]) {\n var nears = r.findNearestElements(now[0], now[1], true, true);\n var near = nears[0];\n\n if (near != null) {\n near.activate();\n r.touchData.start = near;\n r.touchData.starts = nears;\n\n if (r.nodeIsGrabbable(near)) {\n var draggedEles = r.dragData.touchDragEles = cy.collection();\n var selectedNodes = null;\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n\n if (near.selected()) {\n // reset drag elements, since near will be added again\n selectedNodes = cy.$(function (ele) {\n return ele.selected() && r.nodeIsGrabbable(ele);\n });\n addNodesToDrag(selectedNodes, {\n addToList: draggedEles\n });\n } else {\n addNodeToDrag(near, {\n addToList: draggedEles\n });\n }\n\n setGrabTarget(near);\n\n var makeEvent = function makeEvent(type) {\n return {\n originalEvent: e,\n type: type,\n position: {\n x: now[0],\n y: now[1]\n }\n };\n };\n\n near.emit(makeEvent('grabon'));\n\n if (selectedNodes) {\n selectedNodes.forEach(function (n) {\n n.emit(makeEvent('grab'));\n });\n } else {\n near.emit(makeEvent('grab'));\n }\n }\n }\n\n triggerEvents(near, ['touchstart', 'tapstart', 'vmousedown'], e, {\n x: now[0],\n y: now[1]\n });\n\n if (near == null) {\n r.data.bgActivePosistion = {\n x: pos[0],\n y: pos[1]\n };\n r.redrawHint('select', true);\n r.redraw();\n } // Tap, taphold\n // -----\n\n\n r.touchData.singleTouchMoved = false;\n r.touchData.singleTouchStartTime = +new Date();\n clearTimeout(r.touchData.tapholdTimeout);\n r.touchData.tapholdTimeout = setTimeout(function () {\n if (r.touchData.singleTouchMoved === false && !r.pinching // if pinching, then taphold unselect shouldn't take effect\n && !r.touchData.selecting // box selection shouldn't allow taphold through\n ) {\n triggerEvents(r.touchData.start, ['taphold'], e, {\n x: now[0],\n y: now[1]\n });\n }\n }, r.tapholdDuration);\n }\n\n if (e.touches.length >= 1) {\n var sPos = r.touchData.startPosition = [];\n\n for (var i = 0; i < now.length; i++) {\n sPos[i] = earlier[i] = now[i];\n }\n\n var touch0 = e.touches[0];\n r.touchData.startGPosition = [touch0.clientX, touch0.clientY];\n }\n }, false);\n var touchmoveHandler;\n r.registerBinding(window, 'touchmove', touchmoveHandler = function touchmoveHandler(e) {\n // eslint-disable-line no-undef\n var capture = r.touchData.capture;\n\n if (!capture && !eventInContainer(e)) {\n return;\n }\n\n var select = r.selection;\n var cy = r.cy;\n var now = r.touchData.now;\n var earlier = r.touchData.earlier;\n var zoom = cy.zoom();\n\n if (e.touches[0]) {\n var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n now[0] = pos[0];\n now[1] = pos[1];\n }\n\n if (e.touches[1]) {\n var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);\n now[2] = pos[0];\n now[3] = pos[1];\n }\n\n if (e.touches[2]) {\n var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);\n now[4] = pos[0];\n now[5] = pos[1];\n }\n\n var startGPos = r.touchData.startGPosition;\n var isOverThresholdDrag;\n\n if (capture && e.touches[0] && startGPos) {\n var disp = [];\n\n for (var j = 0; j < now.length; j++) {\n disp[j] = now[j] - earlier[j];\n }\n\n var dx = e.touches[0].clientX - startGPos[0];\n var dx2 = dx * dx;\n var dy = e.touches[0].clientY - startGPos[1];\n var dy2 = dy * dy;\n var dist2 = dx2 + dy2;\n isOverThresholdDrag = dist2 >= r.touchTapThreshold2;\n } // context swipe cancelling\n\n\n if (capture && r.touchData.cxt) {\n e.preventDefault();\n var f1x2 = e.touches[0].clientX - offsetLeft,\n f1y2 = e.touches[0].clientY - offsetTop;\n var f2x2 = e.touches[1].clientX - offsetLeft,\n f2y2 = e.touches[1].clientY - offsetTop; // var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );\n\n var distance2Sq = distanceSq(f1x2, f1y2, f2x2, f2y2);\n var factorSq = distance2Sq / distance1Sq;\n var distThreshold = 150;\n var distThresholdSq = distThreshold * distThreshold;\n var factorThreshold = 1.5;\n var factorThresholdSq = factorThreshold * factorThreshold; // cancel ctx gestures if the distance b/t the fingers increases\n\n if (factorSq >= factorThresholdSq || distance2Sq >= distThresholdSq) {\n r.touchData.cxt = false;\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n var cxtEvt = {\n originalEvent: e,\n type: 'cxttapend',\n position: {\n x: now[0],\n y: now[1]\n }\n };\n\n if (r.touchData.start) {\n r.touchData.start.unactivate().emit(cxtEvt);\n r.touchData.start = null;\n } else {\n cy.emit(cxtEvt);\n }\n }\n } // context swipe\n\n\n if (capture && r.touchData.cxt) {\n var cxtEvt = {\n originalEvent: e,\n type: 'cxtdrag',\n position: {\n x: now[0],\n y: now[1]\n }\n };\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n\n if (r.touchData.start) {\n r.touchData.start.emit(cxtEvt);\n } else {\n cy.emit(cxtEvt);\n }\n\n if (r.touchData.start) {\n r.touchData.start._private.grabbed = false;\n }\n\n r.touchData.cxtDragged = true;\n var near = r.findNearestElement(now[0], now[1], true, true);\n\n if (!r.touchData.cxtOver || near !== r.touchData.cxtOver) {\n if (r.touchData.cxtOver) {\n r.touchData.cxtOver.emit({\n originalEvent: e,\n type: 'cxtdragout',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n }\n\n r.touchData.cxtOver = near;\n\n if (near) {\n near.emit({\n originalEvent: e,\n type: 'cxtdragover',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n }\n } // box selection\n\n } else if (capture && e.touches[2] && cy.boxSelectionEnabled()) {\n e.preventDefault();\n r.data.bgActivePosistion = undefined;\n this.lastThreeTouch = +new Date();\n\n if (!r.touchData.selecting) {\n cy.emit({\n originalEvent: e,\n type: 'boxstart',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n }\n\n r.touchData.selecting = true;\n r.touchData.didSelect = true;\n select[4] = 1;\n\n if (!select || select.length === 0 || select[0] === undefined) {\n select[0] = (now[0] + now[2] + now[4]) / 3;\n select[1] = (now[1] + now[3] + now[5]) / 3;\n select[2] = (now[0] + now[2] + now[4]) / 3 + 1;\n select[3] = (now[1] + now[3] + now[5]) / 3 + 1;\n } else {\n select[2] = (now[0] + now[2] + now[4]) / 3;\n select[3] = (now[1] + now[3] + now[5]) / 3;\n }\n\n r.redrawHint('select', true);\n r.redraw(); // pinch to zoom\n } else if (capture && e.touches[1] && !r.touchData.didSelect // don't allow box selection to degrade to pinch-to-zoom\n && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled()) {\n // two fingers => pinch to zoom\n e.preventDefault();\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n var draggedEles = r.dragData.touchDragEles;\n\n if (draggedEles) {\n r.redrawHint('drag', true);\n\n for (var i = 0; i < draggedEles.length; i++) {\n var de_p = draggedEles[i]._private;\n de_p.grabbed = false;\n de_p.rscratch.inDragLayer = false;\n }\n }\n\n var _start = r.touchData.start; // (x2, y2) for fingers 1 and 2\n\n var f1x2 = e.touches[0].clientX - offsetLeft,\n f1y2 = e.touches[0].clientY - offsetTop;\n var f2x2 = e.touches[1].clientX - offsetLeft,\n f2y2 = e.touches[1].clientY - offsetTop;\n var distance2 = distance(f1x2, f1y2, f2x2, f2y2); // var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );\n // var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq );\n\n var factor = distance2 / distance1;\n\n if (twoFingersStartInside) {\n // delta finger1\n var df1x = f1x2 - f1x1;\n var df1y = f1y2 - f1y1; // delta finger 2\n\n var df2x = f2x2 - f2x1;\n var df2y = f2y2 - f2y1; // translation is the normalised vector of the two fingers movement\n // i.e. so pinching cancels out and moving together pans\n\n var tx = (df1x + df2x) / 2;\n var ty = (df1y + df2y) / 2; // now calculate the zoom\n\n var zoom1 = cy.zoom();\n var zoom2 = zoom1 * factor;\n var pan1 = cy.pan(); // the model center point converted to the current rendered pos\n\n var ctrx = modelCenter1[0] * zoom1 + pan1.x;\n var ctry = modelCenter1[1] * zoom1 + pan1.y;\n var pan2 = {\n x: -zoom2 / zoom1 * (ctrx - pan1.x - tx) + ctrx,\n y: -zoom2 / zoom1 * (ctry - pan1.y - ty) + ctry\n }; // remove dragged eles\n\n if (_start && _start.active()) {\n var draggedEles = r.dragData.touchDragEles;\n freeDraggedElements(draggedEles);\n r.redrawHint('drag', true);\n r.redrawHint('eles', true);\n\n _start.unactivate().emit('freeon');\n\n draggedEles.emit('free');\n\n if (r.dragData.didDrag) {\n _start.emit('dragfreeon');\n\n draggedEles.emit('dragfree');\n }\n }\n\n cy.viewport({\n zoom: zoom2,\n pan: pan2,\n cancelOnFailedZoom: true\n });\n distance1 = distance2;\n f1x1 = f1x2;\n f1y1 = f1y2;\n f2x1 = f2x2;\n f2y1 = f2y2;\n r.pinching = true;\n } // Re-project\n\n\n if (e.touches[0]) {\n var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n now[0] = pos[0];\n now[1] = pos[1];\n }\n\n if (e.touches[1]) {\n var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);\n now[2] = pos[0];\n now[3] = pos[1];\n }\n\n if (e.touches[2]) {\n var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);\n now[4] = pos[0];\n now[5] = pos[1];\n }\n } else if (e.touches[0] && !r.touchData.didSelect // don't allow box selection to degrade to single finger events like panning\n ) {\n var start = r.touchData.start;\n var last = r.touchData.last;\n var near;\n\n if (!r.hoverData.draggingEles && !r.swipePanning) {\n near = r.findNearestElement(now[0], now[1], true, true);\n }\n\n if (capture && start != null) {\n e.preventDefault();\n } // dragging nodes\n\n\n if (capture && start != null && r.nodeIsDraggable(start)) {\n if (isOverThresholdDrag) {\n // then dragging can happen\n var draggedEles = r.dragData.touchDragEles;\n var justStartedDrag = !r.dragData.didDrag;\n\n if (justStartedDrag) {\n addNodesToDrag(draggedEles, {\n inDragLayer: true\n });\n }\n\n r.dragData.didDrag = true;\n var totalShift = {\n x: 0,\n y: 0\n };\n\n if (number(disp[0]) && number(disp[1])) {\n totalShift.x += disp[0];\n totalShift.y += disp[1];\n\n if (justStartedDrag) {\n r.redrawHint('eles', true);\n var dragDelta = r.touchData.dragDelta;\n\n if (dragDelta && number(dragDelta[0]) && number(dragDelta[1])) {\n totalShift.x += dragDelta[0];\n totalShift.y += dragDelta[1];\n }\n }\n }\n\n r.hoverData.draggingEles = true;\n draggedEles.silentShift(totalShift).emit('position drag');\n r.redrawHint('drag', true);\n\n if (r.touchData.startPosition[0] == earlier[0] && r.touchData.startPosition[1] == earlier[1]) {\n r.redrawHint('eles', true);\n }\n\n r.redraw();\n } else {\n // otherise keep track of drag delta for later\n var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || [];\n\n if (dragDelta.length === 0) {\n dragDelta.push(disp[0]);\n dragDelta.push(disp[1]);\n } else {\n dragDelta[0] += disp[0];\n dragDelta[1] += disp[1];\n }\n }\n } // touchmove\n\n\n {\n triggerEvents(start || near, ['touchmove', 'tapdrag', 'vmousemove'], e, {\n x: now[0],\n y: now[1]\n });\n\n if ((!start || !start.grabbed()) && near != last) {\n if (last) {\n last.emit({\n originalEvent: e,\n type: 'tapdragout',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n }\n\n if (near) {\n near.emit({\n originalEvent: e,\n type: 'tapdragover',\n position: {\n x: now[0],\n y: now[1]\n }\n });\n }\n }\n\n r.touchData.last = near;\n } // check to cancel taphold\n\n if (capture) {\n for (var i = 0; i < now.length; i++) {\n if (now[i] && r.touchData.startPosition[i] && isOverThresholdDrag) {\n r.touchData.singleTouchMoved = true;\n }\n }\n } // panning\n\n\n if (capture && (start == null || start.pannable()) && cy.panningEnabled() && cy.userPanningEnabled()) {\n var allowPassthrough = allowPanningPassthrough(start, r.touchData.starts);\n\n if (allowPassthrough) {\n e.preventDefault();\n\n if (!r.data.bgActivePosistion) {\n r.data.bgActivePosistion = array2point(r.touchData.startPosition);\n }\n\n if (r.swipePanning) {\n cy.panBy({\n x: disp[0] * zoom,\n y: disp[1] * zoom\n });\n } else if (isOverThresholdDrag) {\n r.swipePanning = true;\n cy.panBy({\n x: dx * zoom,\n y: dy * zoom\n });\n\n if (start) {\n start.unactivate();\n r.redrawHint('select', true);\n r.touchData.start = null;\n }\n }\n } // Re-project\n\n\n var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n now[0] = pos[0];\n now[1] = pos[1];\n }\n }\n\n for (var j = 0; j < now.length; j++) {\n earlier[j] = now[j];\n } // the active bg indicator should be removed when making a swipe that is neither for dragging nodes or panning\n\n\n if (capture && e.touches.length > 0 && !r.hoverData.draggingEles && !r.swipePanning && r.data.bgActivePosistion != null) {\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n r.redraw();\n }\n }, false);\n var touchcancelHandler;\n r.registerBinding(window, 'touchcancel', touchcancelHandler = function touchcancelHandler(e) {\n // eslint-disable-line no-unused-vars\n var start = r.touchData.start;\n r.touchData.capture = false;\n\n if (start) {\n start.unactivate();\n }\n });\n var touchendHandler;\n r.registerBinding(window, 'touchend', touchendHandler = function touchendHandler(e) {\n // eslint-disable-line no-unused-vars\n var start = r.touchData.start;\n var capture = r.touchData.capture;\n\n if (capture) {\n if (e.touches.length === 0) {\n r.touchData.capture = false;\n }\n\n e.preventDefault();\n } else {\n return;\n }\n\n var select = r.selection;\n r.swipePanning = false;\n r.hoverData.draggingEles = false;\n var cy = r.cy;\n var zoom = cy.zoom();\n var now = r.touchData.now;\n var earlier = r.touchData.earlier;\n\n if (e.touches[0]) {\n var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n now[0] = pos[0];\n now[1] = pos[1];\n }\n\n if (e.touches[1]) {\n var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);\n now[2] = pos[0];\n now[3] = pos[1];\n }\n\n if (e.touches[2]) {\n var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);\n now[4] = pos[0];\n now[5] = pos[1];\n }\n\n if (start) {\n start.unactivate();\n }\n\n var ctxTapend;\n\n if (r.touchData.cxt) {\n ctxTapend = {\n originalEvent: e,\n type: 'cxttapend',\n position: {\n x: now[0],\n y: now[1]\n }\n };\n\n if (start) {\n start.emit(ctxTapend);\n } else {\n cy.emit(ctxTapend);\n }\n\n if (!r.touchData.cxtDragged) {\n var ctxTap = {\n originalEvent: e,\n type: 'cxttap',\n position: {\n x: now[0],\n y: now[1]\n }\n };\n\n if (start) {\n start.emit(ctxTap);\n } else {\n cy.emit(ctxTap);\n }\n }\n\n if (r.touchData.start) {\n r.touchData.start._private.grabbed = false;\n }\n\n r.touchData.cxt = false;\n r.touchData.start = null;\n r.redraw();\n return;\n } // no more box selection if we don't have three fingers\n\n\n if (!e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting) {\n r.touchData.selecting = false;\n var box = cy.collection(r.getAllInBox(select[0], select[1], select[2], select[3]));\n select[0] = undefined;\n select[1] = undefined;\n select[2] = undefined;\n select[3] = undefined;\n select[4] = 0;\n r.redrawHint('select', true);\n cy.emit({\n type: 'boxend',\n originalEvent: e,\n position: {\n x: now[0],\n y: now[1]\n }\n });\n\n var eleWouldBeSelected = function eleWouldBeSelected(ele) {\n return ele.selectable() && !ele.selected();\n };\n\n box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect');\n\n if (box.nonempty()) {\n r.redrawHint('eles', true);\n }\n\n r.redraw();\n }\n\n if (start != null) {\n start.unactivate();\n }\n\n if (e.touches[2]) {\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n } else if (e.touches[1]) ; else if (e.touches[0]) ; else if (!e.touches[0]) {\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n var draggedEles = r.dragData.touchDragEles;\n\n if (start != null) {\n var startWasGrabbed = start._private.grabbed;\n freeDraggedElements(draggedEles);\n r.redrawHint('drag', true);\n r.redrawHint('eles', true);\n\n if (startWasGrabbed) {\n start.emit('freeon');\n draggedEles.emit('free');\n\n if (r.dragData.didDrag) {\n start.emit('dragfreeon');\n draggedEles.emit('dragfree');\n }\n }\n\n triggerEvents(start, ['touchend', 'tapend', 'vmouseup', 'tapdragout'], e, {\n x: now[0],\n y: now[1]\n });\n start.unactivate();\n r.touchData.start = null;\n } else {\n var near = r.findNearestElement(now[0], now[1], true, true);\n triggerEvents(near, ['touchend', 'tapend', 'vmouseup', 'tapdragout'], e, {\n x: now[0],\n y: now[1]\n });\n }\n\n var dx = r.touchData.startPosition[0] - now[0];\n var dx2 = dx * dx;\n var dy = r.touchData.startPosition[1] - now[1];\n var dy2 = dy * dy;\n var dist2 = dx2 + dy2;\n var rdist2 = dist2 * zoom * zoom; // Tap event, roughly same as mouse click event for touch\n\n if (!r.touchData.singleTouchMoved) {\n if (!start) {\n cy.$(':selected').unselect(['tapunselect']);\n }\n\n triggerEvents(start, ['tap', 'vclick'], e, {\n x: now[0],\n y: now[1]\n });\n } // Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance\n\n\n if (start != null && !r.dragData.didDrag // didn't drag nodes around\n && start._private.selectable && rdist2 < r.touchTapThreshold2 && !r.pinching // pinch to zoom should not affect selection\n ) {\n if (cy.selectionType() === 'single') {\n cy.$(isSelected).unmerge(start).unselect(['tapunselect']);\n start.select(['tapselect']);\n } else {\n if (start.selected()) {\n start.unselect(['tapunselect']);\n } else {\n start.select(['tapselect']);\n }\n }\n\n r.redrawHint('eles', true);\n }\n\n r.touchData.singleTouchMoved = true;\n }\n\n for (var j = 0; j < now.length; j++) {\n earlier[j] = now[j];\n }\n\n r.dragData.didDrag = false; // reset for next touchstart\n\n if (e.touches.length === 0) {\n r.touchData.dragDelta = [];\n r.touchData.startPosition = null;\n r.touchData.startGPosition = null;\n r.touchData.didSelect = false;\n }\n\n if (e.touches.length < 2) {\n if (e.touches.length === 1) {\n // the old start global pos'n may not be the same finger that remains\n r.touchData.startGPosition = [e.touches[0].clientX, e.touches[0].clientY];\n }\n\n r.pinching = false;\n r.redrawHint('eles', true);\n r.redraw();\n } //r.redraw();\n\n }, false); // fallback compatibility layer for ms pointer events\n\n if (typeof TouchEvent === 'undefined') {\n var pointers = [];\n\n var makeTouch = function makeTouch(e) {\n return {\n clientX: e.clientX,\n clientY: e.clientY,\n force: 1,\n identifier: e.pointerId,\n pageX: e.pageX,\n pageY: e.pageY,\n radiusX: e.width / 2,\n radiusY: e.height / 2,\n screenX: e.screenX,\n screenY: e.screenY,\n target: e.target\n };\n };\n\n var makePointer = function makePointer(e) {\n return {\n event: e,\n touch: makeTouch(e)\n };\n };\n\n var addPointer = function addPointer(e) {\n pointers.push(makePointer(e));\n };\n\n var removePointer = function removePointer(e) {\n for (var i = 0; i < pointers.length; i++) {\n var p = pointers[i];\n\n if (p.event.pointerId === e.pointerId) {\n pointers.splice(i, 1);\n return;\n }\n }\n };\n\n var updatePointer = function updatePointer(e) {\n var p = pointers.filter(function (p) {\n return p.event.pointerId === e.pointerId;\n })[0];\n p.event = e;\n p.touch = makeTouch(e);\n };\n\n var addTouchesToEvent = function addTouchesToEvent(e) {\n e.touches = pointers.map(function (p) {\n return p.touch;\n });\n };\n\n var pointerIsMouse = function pointerIsMouse(e) {\n return e.pointerType === 'mouse' || e.pointerType === 4;\n };\n\n r.registerBinding(r.container, 'pointerdown', function (e) {\n if (pointerIsMouse(e)) {\n return;\n } // mouse already handled\n\n\n e.preventDefault();\n addPointer(e);\n addTouchesToEvent(e);\n touchstartHandler(e);\n });\n r.registerBinding(r.container, 'pointerup', function (e) {\n if (pointerIsMouse(e)) {\n return;\n } // mouse already handled\n\n\n removePointer(e);\n addTouchesToEvent(e);\n touchendHandler(e);\n });\n r.registerBinding(r.container, 'pointercancel', function (e) {\n if (pointerIsMouse(e)) {\n return;\n } // mouse already handled\n\n\n removePointer(e);\n addTouchesToEvent(e);\n touchcancelHandler(e);\n });\n r.registerBinding(r.container, 'pointermove', function (e) {\n if (pointerIsMouse(e)) {\n return;\n } // mouse already handled\n\n\n e.preventDefault();\n updatePointer(e);\n addTouchesToEvent(e);\n touchmoveHandler(e);\n });\n }\n};\n\nvar BRp$d = {};\n\nBRp$d.generatePolygon = function (name, points) {\n return this.nodeShapes[name] = {\n renderer: this,\n name: name,\n points: points,\n draw: function draw(context, centerX, centerY, width, height) {\n this.renderer.nodeShapeImpl('polygon', context, centerX, centerY, width, height, this.points);\n },\n intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {\n return polygonIntersectLine(x, y, this.points, nodeX, nodeY, width / 2, height / 2, padding);\n },\n checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {\n return pointInsidePolygon(x, y, this.points, centerX, centerY, width, height, [0, -1], padding);\n }\n };\n};\n\nBRp$d.generateEllipse = function () {\n return this.nodeShapes['ellipse'] = {\n renderer: this,\n name: 'ellipse',\n draw: function draw(context, centerX, centerY, width, height) {\n this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);\n },\n intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {\n return intersectLineEllipse(x, y, nodeX, nodeY, width / 2 + padding, height / 2 + padding);\n },\n checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {\n return checkInEllipse(x, y, width, height, centerX, centerY, padding);\n }\n };\n};\n\nBRp$d.generateRoundPolygon = function (name, points) {\n // Pre-compute control points\n // Since these points depend on the radius length (which in turns depend on the width/height of the node) we will only pre-compute\n // the unit vectors.\n // For simplicity the layout will be:\n // [ p0, UnitVectorP0P1, p1, UniVectorP1P2, ..., pn, UnitVectorPnP0 ]\n var allPoints = new Array(points.length * 2);\n\n for (var i = 0; i < points.length / 2; i++) {\n var sourceIndex = i * 2;\n var destIndex = void 0;\n\n if (i < points.length / 2 - 1) {\n destIndex = (i + 1) * 2;\n } else {\n destIndex = 0;\n }\n\n allPoints[i * 4] = points[sourceIndex];\n allPoints[i * 4 + 1] = points[sourceIndex + 1];\n var xDest = points[destIndex] - points[sourceIndex];\n var yDest = points[destIndex + 1] - points[sourceIndex + 1];\n var norm = Math.sqrt(xDest * xDest + yDest * yDest);\n allPoints[i * 4 + 2] = xDest / norm;\n allPoints[i * 4 + 3] = yDest / norm;\n }\n\n return this.nodeShapes[name] = {\n renderer: this,\n name: name,\n points: allPoints,\n draw: function draw(context, centerX, centerY, width, height) {\n this.renderer.nodeShapeImpl('round-polygon', context, centerX, centerY, width, height, this.points);\n },\n intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {\n return roundPolygonIntersectLine(x, y, this.points, nodeX, nodeY, width, height);\n },\n checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {\n return pointInsideRoundPolygon(x, y, this.points, centerX, centerY, width, height);\n }\n };\n};\n\nBRp$d.generateRoundRectangle = function () {\n return this.nodeShapes['round-rectangle'] = this.nodeShapes['roundrectangle'] = {\n renderer: this,\n name: 'round-rectangle',\n points: generateUnitNgonPointsFitToSquare(4, 0),\n draw: function draw(context, centerX, centerY, width, height) {\n this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);\n },\n intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {\n return roundRectangleIntersectLine(x, y, nodeX, nodeY, width, height, padding);\n },\n checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {\n var cornerRadius = getRoundRectangleRadius(width, height);\n var diam = cornerRadius * 2; // Check hBox\n\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - diam, [0, -1], padding)) {\n return true;\n } // Check vBox\n\n\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width - diam, height, [0, -1], padding)) {\n return true;\n } // Check top left quarter circle\n\n\n if (checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY - height / 2 + cornerRadius, padding)) {\n return true;\n } // Check top right quarter circle\n\n\n if (checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY - height / 2 + cornerRadius, padding)) {\n return true;\n } // Check bottom right quarter circle\n\n\n if (checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY + height / 2 - cornerRadius, padding)) {\n return true;\n } // Check bottom left quarter circle\n\n\n if (checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY + height / 2 - cornerRadius, padding)) {\n return true;\n }\n\n return false;\n }\n };\n};\n\nBRp$d.generateCutRectangle = function () {\n return this.nodeShapes['cut-rectangle'] = this.nodeShapes['cutrectangle'] = {\n renderer: this,\n name: 'cut-rectangle',\n cornerLength: getCutRectangleCornerLength(),\n points: generateUnitNgonPointsFitToSquare(4, 0),\n draw: function draw(context, centerX, centerY, width, height) {\n this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);\n },\n generateCutTrianglePts: function generateCutTrianglePts(width, height, centerX, centerY) {\n var cl = this.cornerLength;\n var hh = height / 2;\n var hw = width / 2;\n var xBegin = centerX - hw;\n var xEnd = centerX + hw;\n var yBegin = centerY - hh;\n var yEnd = centerY + hh; // points are in clockwise order, inner (imaginary) triangle pt on [4, 5]\n\n return {\n topLeft: [xBegin, yBegin + cl, xBegin + cl, yBegin, xBegin + cl, yBegin + cl],\n topRight: [xEnd - cl, yBegin, xEnd, yBegin + cl, xEnd - cl, yBegin + cl],\n bottomRight: [xEnd, yEnd - cl, xEnd - cl, yEnd, xEnd - cl, yEnd - cl],\n bottomLeft: [xBegin + cl, yEnd, xBegin, yEnd - cl, xBegin + cl, yEnd - cl]\n };\n },\n intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {\n var cPts = this.generateCutTrianglePts(width + 2 * padding, height + 2 * padding, nodeX, nodeY);\n var pts = [].concat.apply([], [cPts.topLeft.splice(0, 4), cPts.topRight.splice(0, 4), cPts.bottomRight.splice(0, 4), cPts.bottomLeft.splice(0, 4)]);\n return polygonIntersectLine(x, y, pts, nodeX, nodeY);\n },\n checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {\n // Check hBox\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - 2 * this.cornerLength, [0, -1], padding)) {\n return true;\n } // Check vBox\n\n\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width - 2 * this.cornerLength, height, [0, -1], padding)) {\n return true;\n }\n\n var cutTrianglePts = this.generateCutTrianglePts(width, height, centerX, centerY);\n return pointInsidePolygonPoints(x, y, cutTrianglePts.topLeft) || pointInsidePolygonPoints(x, y, cutTrianglePts.topRight) || pointInsidePolygonPoints(x, y, cutTrianglePts.bottomRight) || pointInsidePolygonPoints(x, y, cutTrianglePts.bottomLeft);\n }\n };\n};\n\nBRp$d.generateBarrel = function () {\n return this.nodeShapes['barrel'] = {\n renderer: this,\n name: 'barrel',\n points: generateUnitNgonPointsFitToSquare(4, 0),\n draw: function draw(context, centerX, centerY, width, height) {\n this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);\n },\n intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {\n // use two fixed t values for the bezier curve approximation\n var t0 = 0.15;\n var t1 = 0.5;\n var t2 = 0.85;\n var bPts = this.generateBarrelBezierPts(width + 2 * padding, height + 2 * padding, nodeX, nodeY);\n\n var approximateBarrelCurvePts = function approximateBarrelCurvePts(pts) {\n // approximate curve pts based on the two t values\n var m0 = qbezierPtAt({\n x: pts[0],\n y: pts[1]\n }, {\n x: pts[2],\n y: pts[3]\n }, {\n x: pts[4],\n y: pts[5]\n }, t0);\n var m1 = qbezierPtAt({\n x: pts[0],\n y: pts[1]\n }, {\n x: pts[2],\n y: pts[3]\n }, {\n x: pts[4],\n y: pts[5]\n }, t1);\n var m2 = qbezierPtAt({\n x: pts[0],\n y: pts[1]\n }, {\n x: pts[2],\n y: pts[3]\n }, {\n x: pts[4],\n y: pts[5]\n }, t2);\n return [pts[0], pts[1], m0.x, m0.y, m1.x, m1.y, m2.x, m2.y, pts[4], pts[5]];\n };\n\n var pts = [].concat(approximateBarrelCurvePts(bPts.topLeft), approximateBarrelCurvePts(bPts.topRight), approximateBarrelCurvePts(bPts.bottomRight), approximateBarrelCurvePts(bPts.bottomLeft));\n return polygonIntersectLine(x, y, pts, nodeX, nodeY);\n },\n generateBarrelBezierPts: function generateBarrelBezierPts(width, height, centerX, centerY) {\n var hh = height / 2;\n var hw = width / 2;\n var xBegin = centerX - hw;\n var xEnd = centerX + hw;\n var yBegin = centerY - hh;\n var yEnd = centerY + hh;\n var curveConstants = getBarrelCurveConstants(width, height);\n var hOffset = curveConstants.heightOffset;\n var wOffset = curveConstants.widthOffset;\n var ctrlPtXOffset = curveConstants.ctrlPtOffsetPct * width; // points are in clockwise order, inner (imaginary) control pt on [4, 5]\n\n var pts = {\n topLeft: [xBegin, yBegin + hOffset, xBegin + ctrlPtXOffset, yBegin, xBegin + wOffset, yBegin],\n topRight: [xEnd - wOffset, yBegin, xEnd - ctrlPtXOffset, yBegin, xEnd, yBegin + hOffset],\n bottomRight: [xEnd, yEnd - hOffset, xEnd - ctrlPtXOffset, yEnd, xEnd - wOffset, yEnd],\n bottomLeft: [xBegin + wOffset, yEnd, xBegin + ctrlPtXOffset, yEnd, xBegin, yEnd - hOffset]\n };\n pts.topLeft.isTop = true;\n pts.topRight.isTop = true;\n pts.bottomLeft.isBottom = true;\n pts.bottomRight.isBottom = true;\n return pts;\n },\n checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {\n var curveConstants = getBarrelCurveConstants(width, height);\n var hOffset = curveConstants.heightOffset;\n var wOffset = curveConstants.widthOffset; // Check hBox\n\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - 2 * hOffset, [0, -1], padding)) {\n return true;\n } // Check vBox\n\n\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width - 2 * wOffset, height, [0, -1], padding)) {\n return true;\n }\n\n var barrelCurvePts = this.generateBarrelBezierPts(width, height, centerX, centerY);\n\n var getCurveT = function getCurveT(x, y, curvePts) {\n var x0 = curvePts[4];\n var x1 = curvePts[2];\n var x2 = curvePts[0];\n var y0 = curvePts[5]; // var y1 = curvePts[ 3 ];\n\n var y2 = curvePts[1];\n var xMin = Math.min(x0, x2);\n var xMax = Math.max(x0, x2);\n var yMin = Math.min(y0, y2);\n var yMax = Math.max(y0, y2);\n\n if (xMin <= x && x <= xMax && yMin <= y && y <= yMax) {\n var coeff = bezierPtsToQuadCoeff(x0, x1, x2);\n var roots = solveQuadratic(coeff[0], coeff[1], coeff[2], x);\n var validRoots = roots.filter(function (r) {\n return 0 <= r && r <= 1;\n });\n\n if (validRoots.length > 0) {\n return validRoots[0];\n }\n }\n\n return null;\n };\n\n var curveRegions = Object.keys(barrelCurvePts);\n\n for (var i = 0; i < curveRegions.length; i++) {\n var corner = curveRegions[i];\n var cornerPts = barrelCurvePts[corner];\n var t = getCurveT(x, y, cornerPts);\n\n if (t == null) {\n continue;\n }\n\n var y0 = cornerPts[5];\n var y1 = cornerPts[3];\n var y2 = cornerPts[1];\n var bezY = qbezierAt(y0, y1, y2, t);\n\n if (cornerPts.isTop && bezY <= y) {\n return true;\n }\n\n if (cornerPts.isBottom && y <= bezY) {\n return true;\n }\n }\n\n return false;\n }\n };\n};\n\nBRp$d.generateBottomRoundrectangle = function () {\n return this.nodeShapes['bottom-round-rectangle'] = this.nodeShapes['bottomroundrectangle'] = {\n renderer: this,\n name: 'bottom-round-rectangle',\n points: generateUnitNgonPointsFitToSquare(4, 0),\n draw: function draw(context, centerX, centerY, width, height) {\n this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);\n },\n intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {\n var topStartX = nodeX - (width / 2 + padding);\n var topStartY = nodeY - (height / 2 + padding);\n var topEndY = topStartY;\n var topEndX = nodeX + (width / 2 + padding);\n var topIntersections = finiteLinesIntersect(x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);\n\n if (topIntersections.length > 0) {\n return topIntersections;\n }\n\n return roundRectangleIntersectLine(x, y, nodeX, nodeY, width, height, padding);\n },\n checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {\n var cornerRadius = getRoundRectangleRadius(width, height);\n var diam = 2 * cornerRadius; // Check hBox\n\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - diam, [0, -1], padding)) {\n return true;\n } // Check vBox\n\n\n if (pointInsidePolygon(x, y, this.points, centerX, centerY, width - diam, height, [0, -1], padding)) {\n return true;\n } // check non-rounded top side\n\n\n var outerWidth = width / 2 + 2 * padding;\n var outerHeight = height / 2 + 2 * padding;\n var points = [centerX - outerWidth, centerY - outerHeight, centerX - outerWidth, centerY, centerX + outerWidth, centerY, centerX + outerWidth, centerY - outerHeight];\n\n if (pointInsidePolygonPoints(x, y, points)) {\n return true;\n } // Check bottom right quarter circle\n\n\n if (checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY + height / 2 - cornerRadius, padding)) {\n return true;\n } // Check bottom left quarter circle\n\n\n if (checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY + height / 2 - cornerRadius, padding)) {\n return true;\n }\n\n return false;\n }\n };\n};\n\nBRp$d.registerNodeShapes = function () {\n var nodeShapes = this.nodeShapes = {};\n var renderer = this;\n this.generateEllipse();\n this.generatePolygon('triangle', generateUnitNgonPointsFitToSquare(3, 0));\n this.generateRoundPolygon('round-triangle', generateUnitNgonPointsFitToSquare(3, 0));\n this.generatePolygon('rectangle', generateUnitNgonPointsFitToSquare(4, 0));\n nodeShapes['square'] = nodeShapes['rectangle'];\n this.generateRoundRectangle();\n this.generateCutRectangle();\n this.generateBarrel();\n this.generateBottomRoundrectangle();\n {\n var diamondPoints = [0, 1, 1, 0, 0, -1, -1, 0];\n this.generatePolygon('diamond', diamondPoints);\n this.generateRoundPolygon('round-diamond', diamondPoints);\n }\n this.generatePolygon('pentagon', generateUnitNgonPointsFitToSquare(5, 0));\n this.generateRoundPolygon('round-pentagon', generateUnitNgonPointsFitToSquare(5, 0));\n this.generatePolygon('hexagon', generateUnitNgonPointsFitToSquare(6, 0));\n this.generateRoundPolygon('round-hexagon', generateUnitNgonPointsFitToSquare(6, 0));\n this.generatePolygon('heptagon', generateUnitNgonPointsFitToSquare(7, 0));\n this.generateRoundPolygon('round-heptagon', generateUnitNgonPointsFitToSquare(7, 0));\n this.generatePolygon('octagon', generateUnitNgonPointsFitToSquare(8, 0));\n this.generateRoundPolygon('round-octagon', generateUnitNgonPointsFitToSquare(8, 0));\n var star5Points = new Array(20);\n {\n var outerPoints = generateUnitNgonPoints(5, 0);\n var innerPoints = generateUnitNgonPoints(5, Math.PI / 5); // Outer radius is 1; inner radius of star is smaller\n\n var innerRadius = 0.5 * (3 - Math.sqrt(5));\n innerRadius *= 1.57;\n\n for (var i = 0; i < innerPoints.length / 2; i++) {\n innerPoints[i * 2] *= innerRadius;\n innerPoints[i * 2 + 1] *= innerRadius;\n }\n\n for (var i = 0; i < 20 / 4; i++) {\n star5Points[i * 4] = outerPoints[i * 2];\n star5Points[i * 4 + 1] = outerPoints[i * 2 + 1];\n star5Points[i * 4 + 2] = innerPoints[i * 2];\n star5Points[i * 4 + 3] = innerPoints[i * 2 + 1];\n }\n }\n star5Points = fitPolygonToSquare(star5Points);\n this.generatePolygon('star', star5Points);\n this.generatePolygon('vee', [-1, -1, 0, -0.333, 1, -1, 0, 1]);\n this.generatePolygon('rhomboid', [-1, -1, 0.333, -1, 1, 1, -0.333, 1]);\n this.nodeShapes['concavehexagon'] = this.generatePolygon('concave-hexagon', [-1, -0.95, -0.75, 0, -1, 0.95, 1, 0.95, 0.75, 0, 1, -0.95]);\n {\n var tagPoints = [-1, -1, 0.25, -1, 1, 0, 0.25, 1, -1, 1];\n this.generatePolygon('tag', tagPoints);\n this.generateRoundPolygon('round-tag', tagPoints);\n }\n\n nodeShapes.makePolygon = function (points) {\n // use caching on user-specified polygons so they are as fast as native shapes\n var key = points.join('$');\n var name = 'polygon-' + key;\n var shape;\n\n if (shape = this[name]) {\n // got cached shape\n return shape;\n } // create and cache new shape\n\n\n return renderer.generatePolygon(name, points);\n };\n};\n\nvar BRp$e = {};\n\nBRp$e.timeToRender = function () {\n return this.redrawTotalTime / this.redrawCount;\n};\n\nBRp$e.redraw = function (options) {\n options = options || staticEmptyObject();\n var r = this;\n\n if (r.averageRedrawTime === undefined) {\n r.averageRedrawTime = 0;\n }\n\n if (r.lastRedrawTime === undefined) {\n r.lastRedrawTime = 0;\n }\n\n if (r.lastDrawTime === undefined) {\n r.lastDrawTime = 0;\n }\n\n r.requestedFrame = true;\n r.renderOptions = options;\n};\n\nBRp$e.beforeRender = function (fn, priority) {\n // the renderer can't add tick callbacks when destroyed\n if (this.destroyed) {\n return;\n }\n\n if (priority == null) {\n error('Priority is not optional for beforeRender');\n }\n\n var cbs = this.beforeRenderCallbacks;\n cbs.push({\n fn: fn,\n priority: priority\n }); // higher priority callbacks executed first\n\n cbs.sort(function (a, b) {\n return b.priority - a.priority;\n });\n};\n\nvar beforeRenderCallbacks = function beforeRenderCallbacks(r, willDraw, startTime) {\n var cbs = r.beforeRenderCallbacks;\n\n for (var i = 0; i < cbs.length; i++) {\n cbs[i].fn(willDraw, startTime);\n }\n};\n\nBRp$e.startRenderLoop = function () {\n var r = this;\n var cy = r.cy;\n\n if (r.renderLoopStarted) {\n return;\n } else {\n r.renderLoopStarted = true;\n }\n\n var renderFn = function renderFn(requestTime) {\n if (r.destroyed) {\n return;\n }\n\n if (cy.batching()) ; else if (r.requestedFrame && !r.skipFrame) {\n beforeRenderCallbacks(r, true, requestTime);\n var startTime = performanceNow();\n r.render(r.renderOptions);\n var endTime = r.lastDrawTime = performanceNow();\n\n if (r.averageRedrawTime === undefined) {\n r.averageRedrawTime = endTime - startTime;\n }\n\n if (r.redrawCount === undefined) {\n r.redrawCount = 0;\n }\n\n r.redrawCount++;\n\n if (r.redrawTotalTime === undefined) {\n r.redrawTotalTime = 0;\n }\n\n var duration = endTime - startTime;\n r.redrawTotalTime += duration;\n r.lastRedrawTime = duration; // use a weighted average with a bias from the previous average so we don't spike so easily\n\n r.averageRedrawTime = r.averageRedrawTime / 2 + duration / 2;\n r.requestedFrame = false;\n } else {\n beforeRenderCallbacks(r, false, requestTime);\n }\n\n r.skipFrame = false;\n requestAnimationFrame(renderFn);\n };\n\n requestAnimationFrame(renderFn);\n};\n\nvar BaseRenderer = function BaseRenderer(options) {\n this.init(options);\n};\n\nvar BR = BaseRenderer;\nvar BRp$f = BR.prototype;\nBRp$f.clientFunctions = ['redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl'];\n\nBRp$f.init = function (options) {\n var r = this;\n r.options = options;\n r.cy = options.cy;\n var ctr = r.container = options.cy.container(); // prepend a stylesheet in the head such that\n\n if (window$1) {\n var document = window$1.document;\n var head = document.head;\n var stylesheetId = '__________cytoscape_stylesheet';\n var className = '__________cytoscape_container';\n var stylesheetAlreadyExists = document.getElementById(stylesheetId) != null;\n\n if (ctr.className.indexOf(className) < 0) {\n ctr.className = (ctr.className || '') + ' ' + className;\n }\n\n if (!stylesheetAlreadyExists) {\n var stylesheet = document.createElement('style');\n stylesheet.id = stylesheetId;\n stylesheet.innerHTML = '.' + className + ' { position: relative; }';\n head.insertBefore(stylesheet, head.children[0]); // first so lowest priority\n }\n\n var computedStyle = window$1.getComputedStyle(ctr);\n var position = computedStyle.getPropertyValue('position');\n\n if (position === 'static') {\n warn('A Cytoscape container has style position:static and so can not use UI extensions properly');\n }\n }\n\n r.selection = [undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag\n\n r.bezierProjPcts = [0.05, 0.225, 0.4, 0.5, 0.6, 0.775, 0.95]; //--Pointer-related data\n\n r.hoverData = {\n down: null,\n last: null,\n downTime: null,\n triggerMode: null,\n dragging: false,\n initialPan: [null, null],\n capture: false\n };\n r.dragData = {\n possibleDragElements: []\n };\n r.touchData = {\n start: null,\n capture: false,\n // These 3 fields related to tap, taphold events\n startPosition: [null, null, null, null, null, null],\n singleTouchStartTime: null,\n singleTouchMoved: true,\n now: [null, null, null, null, null, null],\n earlier: [null, null, null, null, null, null]\n };\n r.redraws = 0;\n r.showFps = options.showFps;\n r.debug = options.debug;\n r.hideEdgesOnViewport = options.hideEdgesOnViewport;\n r.textureOnViewport = options.textureOnViewport;\n r.wheelSensitivity = options.wheelSensitivity;\n r.motionBlurEnabled = options.motionBlur; // on by default\n\n r.forcedPixelRatio = number(options.pixelRatio) ? options.pixelRatio : null;\n r.motionBlur = options.motionBlur; // for initial kick off\n\n r.motionBlurOpacity = options.motionBlurOpacity;\n r.motionBlurTransparency = 1 - r.motionBlurOpacity;\n r.motionBlurPxRatio = 1;\n r.mbPxRBlurry = 1; //0.8;\n\n r.minMbLowQualFrames = 4;\n r.fullQualityMb = false;\n r.clearedForMotionBlur = [];\n r.desktopTapThreshold = options.desktopTapThreshold;\n r.desktopTapThreshold2 = options.desktopTapThreshold * options.desktopTapThreshold;\n r.touchTapThreshold = options.touchTapThreshold;\n r.touchTapThreshold2 = options.touchTapThreshold * options.touchTapThreshold;\n r.tapholdDuration = 500;\n r.bindings = [];\n r.beforeRenderCallbacks = [];\n r.beforeRenderPriorities = {\n // higher priority execs before lower one\n animations: 400,\n eleCalcs: 300,\n eleTxrDeq: 200,\n lyrTxrDeq: 150,\n lyrTxrSkip: 100\n };\n r.registerNodeShapes();\n r.registerArrowShapes();\n r.registerCalculationListeners();\n};\n\nBRp$f.notify = function (eventName, eles) {\n var r = this;\n var cy = r.cy; // the renderer can't be notified after it's destroyed\n\n if (this.destroyed) {\n return;\n }\n\n if (eventName === 'init') {\n r.load();\n return;\n }\n\n if (eventName === 'destroy') {\n r.destroy();\n return;\n }\n\n if (eventName === 'add' || eventName === 'remove' || eventName === 'move' && cy.hasCompoundNodes() || eventName === 'load' || eventName === 'zorder' || eventName === 'mount') {\n r.invalidateCachedZSortedEles();\n }\n\n if (eventName === 'viewport') {\n r.redrawHint('select', true);\n }\n\n if (eventName === 'load' || eventName === 'resize' || eventName === 'mount') {\n r.invalidateContainerClientCoordsCache();\n r.matchCanvasSize(r.container);\n }\n\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n this.startRenderLoop();\n this.redraw();\n};\n\nBRp$f.destroy = function () {\n var r = this;\n r.destroyed = true;\n r.cy.stopAnimationLoop();\n\n for (var i = 0; i < r.bindings.length; i++) {\n var binding = r.bindings[i];\n var b = binding;\n var tgt = b.target;\n (tgt.off || tgt.removeEventListener).apply(tgt, b.args);\n }\n\n r.bindings = [];\n r.beforeRenderCallbacks = [];\n r.onUpdateEleCalcsFns = [];\n\n if (r.removeObserver) {\n r.removeObserver.disconnect();\n }\n\n if (r.styleObserver) {\n r.styleObserver.disconnect();\n }\n\n if (r.resizeObserver) {\n r.resizeObserver.disconnect();\n }\n\n if (r.labelCalcDiv) {\n try {\n document.body.removeChild(r.labelCalcDiv); // eslint-disable-line no-undef\n } catch (e) {// ie10 issue #1014\n }\n }\n};\n\nBRp$f.isHeadless = function () {\n return false;\n};\n\n[BRp, BRp$a, BRp$b, BRp$c, BRp$d, BRp$e].forEach(function (props) {\n extend(BRp$f, props);\n});\n\nvar fullFpsTime = 1000 / 60; // assume 60 frames per second\n\nvar defs = {\n setupDequeueing: function setupDequeueing(opts) {\n return function setupDequeueingImpl() {\n var self = this;\n var r = this.renderer;\n\n if (self.dequeueingSetup) {\n return;\n } else {\n self.dequeueingSetup = true;\n }\n\n var queueRedraw = util(function () {\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n r.redraw();\n }, opts.deqRedrawThreshold);\n\n var dequeue = function dequeue(willDraw, frameStartTime) {\n var startTime = performanceNow();\n var avgRenderTime = r.averageRedrawTime;\n var renderTime = r.lastRedrawTime;\n var deqd = [];\n var extent = r.cy.extent();\n var pixelRatio = r.getPixelRatio(); // if we aren't in a tick that causes a draw, then the rendered style\n // queue won't automatically be flushed before dequeueing starts\n\n if (!willDraw) {\n r.flushRenderedStyleQueue();\n }\n\n while (true) {\n // eslint-disable-line no-constant-condition\n var now = performanceNow();\n var duration = now - startTime;\n var frameDuration = now - frameStartTime;\n\n if (renderTime < fullFpsTime) {\n // if we're rendering faster than the ideal fps, then do dequeueing\n // during all of the remaining frame time\n var timeAvailable = fullFpsTime - (willDraw ? avgRenderTime : 0);\n\n if (frameDuration >= opts.deqFastCost * timeAvailable) {\n break;\n }\n } else {\n if (willDraw) {\n if (duration >= opts.deqCost * renderTime || duration >= opts.deqAvgCost * avgRenderTime) {\n break;\n }\n } else if (frameDuration >= opts.deqNoDrawCost * fullFpsTime) {\n break;\n }\n }\n\n var thisDeqd = opts.deq(self, pixelRatio, extent);\n\n if (thisDeqd.length > 0) {\n for (var i = 0; i < thisDeqd.length; i++) {\n deqd.push(thisDeqd[i]);\n }\n } else {\n break;\n }\n } // callbacks on dequeue\n\n\n if (deqd.length > 0) {\n opts.onDeqd(self, deqd);\n\n if (!willDraw && opts.shouldRedraw(self, deqd, pixelRatio, extent)) {\n queueRedraw();\n }\n }\n };\n\n var priority = opts.priority || noop;\n r.beforeRender(dequeue, priority(self));\n };\n }\n};\n\n// Uses keys so elements may share the same cache.\n\nvar ElementTextureCacheLookup =\n/*#__PURE__*/\nfunction () {\n function ElementTextureCacheLookup(getKey) {\n var doesEleInvalidateKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : falsify;\n\n _classCallCheck(this, ElementTextureCacheLookup);\n\n this.idsByKey = new Map$1();\n this.keyForId = new Map$1();\n this.cachesByLvl = new Map$1();\n this.lvls = [];\n this.getKey = getKey;\n this.doesEleInvalidateKey = doesEleInvalidateKey;\n }\n\n _createClass(ElementTextureCacheLookup, [{\n key: \"getIdsFor\",\n value: function getIdsFor(key) {\n if (key == null) {\n error(\"Can not get id list for null key\");\n }\n\n var idsByKey = this.idsByKey;\n var ids = this.idsByKey.get(key);\n\n if (!ids) {\n ids = new Set$1();\n idsByKey.set(key, ids);\n }\n\n return ids;\n }\n }, {\n key: \"addIdForKey\",\n value: function addIdForKey(key, id) {\n if (key != null) {\n this.getIdsFor(key).add(id);\n }\n }\n }, {\n key: \"deleteIdForKey\",\n value: function deleteIdForKey(key, id) {\n if (key != null) {\n this.getIdsFor(key)[\"delete\"](id);\n }\n }\n }, {\n key: \"getNumberOfIdsForKey\",\n value: function getNumberOfIdsForKey(key) {\n if (key == null) {\n return 0;\n } else {\n return this.getIdsFor(key).size;\n }\n }\n }, {\n key: \"updateKeyMappingFor\",\n value: function updateKeyMappingFor(ele) {\n var id = ele.id();\n var prevKey = this.keyForId.get(id);\n var currKey = this.getKey(ele);\n this.deleteIdForKey(prevKey, id);\n this.addIdForKey(currKey, id);\n this.keyForId.set(id, currKey);\n }\n }, {\n key: \"deleteKeyMappingFor\",\n value: function deleteKeyMappingFor(ele) {\n var id = ele.id();\n var prevKey = this.keyForId.get(id);\n this.deleteIdForKey(prevKey, id);\n this.keyForId[\"delete\"](id);\n }\n }, {\n key: \"keyHasChangedFor\",\n value: function keyHasChangedFor(ele) {\n var id = ele.id();\n var prevKey = this.keyForId.get(id);\n var newKey = this.getKey(ele);\n return prevKey !== newKey;\n }\n }, {\n key: \"isInvalid\",\n value: function isInvalid(ele) {\n return this.keyHasChangedFor(ele) || this.doesEleInvalidateKey(ele);\n }\n }, {\n key: \"getCachesAt\",\n value: function getCachesAt(lvl) {\n var cachesByLvl = this.cachesByLvl,\n lvls = this.lvls;\n var caches = cachesByLvl.get(lvl);\n\n if (!caches) {\n caches = new Map$1();\n cachesByLvl.set(lvl, caches);\n lvls.push(lvl);\n }\n\n return caches;\n }\n }, {\n key: \"getCache\",\n value: function getCache(key, lvl) {\n return this.getCachesAt(lvl).get(key);\n }\n }, {\n key: \"get\",\n value: function get(ele, lvl) {\n var key = this.getKey(ele);\n var cache = this.getCache(key, lvl); // getting for an element may need to add to the id list b/c eles can share keys\n\n if (cache != null) {\n this.updateKeyMappingFor(ele);\n }\n\n return cache;\n }\n }, {\n key: \"getForCachedKey\",\n value: function getForCachedKey(ele, lvl) {\n var key = this.keyForId.get(ele.id()); // n.b. use cached key, not newly computed key\n\n var cache = this.getCache(key, lvl);\n return cache;\n }\n }, {\n key: \"hasCache\",\n value: function hasCache(key, lvl) {\n return this.getCachesAt(lvl).has(key);\n }\n }, {\n key: \"has\",\n value: function has(ele, lvl) {\n var key = this.getKey(ele);\n return this.hasCache(key, lvl);\n }\n }, {\n key: \"setCache\",\n value: function setCache(key, lvl, cache) {\n cache.key = key;\n this.getCachesAt(lvl).set(key, cache);\n }\n }, {\n key: \"set\",\n value: function set(ele, lvl, cache) {\n var key = this.getKey(ele);\n this.setCache(key, lvl, cache);\n this.updateKeyMappingFor(ele);\n }\n }, {\n key: \"deleteCache\",\n value: function deleteCache(key, lvl) {\n this.getCachesAt(lvl)[\"delete\"](key);\n }\n }, {\n key: \"delete\",\n value: function _delete(ele, lvl) {\n var key = this.getKey(ele);\n this.deleteCache(key, lvl);\n }\n }, {\n key: \"invalidateKey\",\n value: function invalidateKey(key) {\n var _this = this;\n\n this.lvls.forEach(function (lvl) {\n return _this.deleteCache(key, lvl);\n });\n } // returns true if no other eles reference the invalidated cache (n.b. other eles may need the cache with the same key)\n\n }, {\n key: \"invalidate\",\n value: function invalidate(ele) {\n var id = ele.id();\n var key = this.keyForId.get(id); // n.b. use stored key rather than current (potential key)\n\n this.deleteKeyMappingFor(ele);\n var entireKeyInvalidated = this.doesEleInvalidateKey(ele);\n\n if (entireKeyInvalidated) {\n // clear mapping for current key\n this.invalidateKey(key);\n }\n\n return entireKeyInvalidated || this.getNumberOfIdsForKey(key) === 0;\n }\n }]);\n\n return ElementTextureCacheLookup;\n}();\n\nvar minTxrH = 25; // the size of the texture cache for small height eles (special case)\n\nvar txrStepH = 50; // the min size of the regular cache, and the size it increases with each step up\n\nvar minLvl = -4; // when scaling smaller than that we don't need to re-render\n\nvar maxLvl = 3; // when larger than this scale just render directly (caching is not helpful)\n\nvar maxZoom = 7.99; // beyond this zoom level, layered textures are not used\n\nvar eleTxrSpacing = 8; // spacing between elements on textures to avoid blitting overlaps\n\nvar defTxrWidth = 1024; // default/minimum texture width\n\nvar maxTxrW = 1024; // the maximum width of a texture\n\nvar maxTxrH = 1024; // the maximum height of a texture\n\nvar minUtility = 0.2; // if usage of texture is less than this, it is retired\n\nvar maxFullness = 0.8; // fullness of texture after which queue removal is checked\n\nvar maxFullnessChecks = 10; // dequeued after this many checks\n\nvar deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame\n\nvar deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time\n\nvar deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing\n\nvar deqFastCost = 0.9; // % of frame time to be used when >60fps\n\nvar deqRedrawThreshold = 100; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile\n\nvar maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch\n\nvar getTxrReasons = {\n dequeue: 'dequeue',\n downscale: 'downscale',\n highQuality: 'highQuality'\n};\nvar initDefaults = defaults({\n getKey: null,\n doesEleInvalidateKey: falsify,\n drawElement: null,\n getBoundingBox: null,\n getRotationPoint: null,\n getRotationOffset: null,\n isVisible: trueify,\n allowEdgeTxrCaching: true,\n allowParentTxrCaching: true\n});\n\nvar ElementTextureCache = function ElementTextureCache(renderer, initOptions) {\n var self = this;\n self.renderer = renderer;\n self.onDequeues = [];\n var opts = initDefaults(initOptions);\n extend(self, opts);\n self.lookup = new ElementTextureCacheLookup(opts.getKey, opts.doesEleInvalidateKey);\n self.setupDequeueing();\n};\n\nvar ETCp = ElementTextureCache.prototype;\nETCp.reasons = getTxrReasons; // the list of textures in which new subtextures for elements can be placed\n\nETCp.getTextureQueue = function (txrH) {\n var self = this;\n self.eleImgCaches = self.eleImgCaches || {};\n return self.eleImgCaches[txrH] = self.eleImgCaches[txrH] || [];\n}; // the list of usused textures which can be recycled (in use in texture queue)\n\n\nETCp.getRetiredTextureQueue = function (txrH) {\n var self = this;\n var rtxtrQs = self.eleImgCaches.retired = self.eleImgCaches.retired || {};\n var rtxtrQ = rtxtrQs[txrH] = rtxtrQs[txrH] || [];\n return rtxtrQ;\n}; // queue of element draw requests at different scale levels\n\n\nETCp.getElementQueue = function () {\n var self = this;\n var q = self.eleCacheQueue = self.eleCacheQueue || new Heap(function (a, b) {\n return b.reqs - a.reqs;\n });\n return q;\n}; // queue of element draw requests at different scale levels (element id lookup)\n\n\nETCp.getElementKeyToQueue = function () {\n var self = this;\n var k2q = self.eleKeyToCacheQueue = self.eleKeyToCacheQueue || {};\n return k2q;\n};\n\nETCp.getElement = function (ele, bb, pxRatio, lvl, reason) {\n var self = this;\n var r = this.renderer;\n var zoom = r.cy.zoom();\n var lookup = this.lookup;\n\n if (bb.w === 0 || bb.h === 0 || isNaN(bb.w) || isNaN(bb.h) || !ele.visible()) {\n return null;\n }\n\n if (!self.allowEdgeTxrCaching && ele.isEdge() || !self.allowParentTxrCaching && ele.isParent()) {\n return null;\n }\n\n if (lvl == null) {\n lvl = Math.ceil(log2(zoom * pxRatio));\n }\n\n if (lvl < minLvl) {\n lvl = minLvl;\n } else if (zoom >= maxZoom || lvl > maxLvl) {\n return null;\n }\n\n var scale = Math.pow(2, lvl);\n var eleScaledH = bb.h * scale;\n var eleScaledW = bb.w * scale;\n var scaledLabelShown = r.eleTextBiggerThanMin(ele, scale);\n\n if (!this.isVisible(ele, scaledLabelShown)) {\n return null;\n }\n\n var eleCache = lookup.get(ele, lvl); // if this get was on an unused/invalidated cache, then restore the texture usage metric\n\n if (eleCache && eleCache.invalidated) {\n eleCache.invalidated = false;\n eleCache.texture.invalidatedWidth -= eleCache.width;\n }\n\n if (eleCache) {\n return eleCache;\n }\n\n var txrH; // which texture height this ele belongs to\n\n if (eleScaledH <= minTxrH) {\n txrH = minTxrH;\n } else if (eleScaledH <= txrStepH) {\n txrH = txrStepH;\n } else {\n txrH = Math.ceil(eleScaledH / txrStepH) * txrStepH;\n }\n\n if (eleScaledH > maxTxrH || eleScaledW > maxTxrW) {\n return null; // caching large elements is not efficient\n }\n\n var txrQ = self.getTextureQueue(txrH); // first try the second last one in case it has space at the end\n\n var txr = txrQ[txrQ.length - 2];\n\n var addNewTxr = function addNewTxr() {\n return self.recycleTexture(txrH, eleScaledW) || self.addTexture(txrH, eleScaledW);\n }; // try the last one if there is no second last one\n\n\n if (!txr) {\n txr = txrQ[txrQ.length - 1];\n } // if the last one doesn't exist, we need a first one\n\n\n if (!txr) {\n txr = addNewTxr();\n } // if there's no room in the current texture, we need a new one\n\n\n if (txr.width - txr.usedWidth < eleScaledW) {\n txr = addNewTxr();\n }\n\n var scalableFrom = function scalableFrom(otherCache) {\n return otherCache && otherCache.scaledLabelShown === scaledLabelShown;\n };\n\n var deqing = reason && reason === getTxrReasons.dequeue;\n var highQualityReq = reason && reason === getTxrReasons.highQuality;\n var downscaleReq = reason && reason === getTxrReasons.downscale;\n var higherCache; // the nearest cache with a higher level\n\n for (var l = lvl + 1; l <= maxLvl; l++) {\n var c = lookup.get(ele, l);\n\n if (c) {\n higherCache = c;\n break;\n }\n }\n\n var oneUpCache = higherCache && higherCache.level === lvl + 1 ? higherCache : null;\n\n var downscale = function downscale() {\n txr.context.drawImage(oneUpCache.texture.canvas, oneUpCache.x, 0, oneUpCache.width, oneUpCache.height, txr.usedWidth, 0, eleScaledW, eleScaledH);\n }; // reset ele area in texture\n\n\n txr.context.setTransform(1, 0, 0, 1, 0, 0);\n txr.context.clearRect(txr.usedWidth, 0, eleScaledW, txrH);\n\n if (scalableFrom(oneUpCache)) {\n // then we can relatively cheaply rescale the existing image w/o rerendering\n downscale();\n } else if (scalableFrom(higherCache)) {\n // then use the higher cache for now and queue the next level down\n // to cheaply scale towards the smaller level\n if (highQualityReq) {\n for (var _l = higherCache.level; _l > lvl; _l--) {\n oneUpCache = self.getElement(ele, bb, pxRatio, _l, getTxrReasons.downscale);\n }\n\n downscale();\n } else {\n self.queueElement(ele, higherCache.level - 1);\n return higherCache;\n }\n } else {\n var lowerCache; // the nearest cache with a lower level\n\n if (!deqing && !highQualityReq && !downscaleReq) {\n for (var _l2 = lvl - 1; _l2 >= minLvl; _l2--) {\n var _c = lookup.get(ele, _l2);\n\n if (_c) {\n lowerCache = _c;\n break;\n }\n }\n }\n\n if (scalableFrom(lowerCache)) {\n // then use the lower quality cache for now and queue the better one for later\n self.queueElement(ele, lvl);\n return lowerCache;\n }\n\n txr.context.translate(txr.usedWidth, 0);\n txr.context.scale(scale, scale);\n this.drawElement(txr.context, ele, bb, scaledLabelShown, false);\n txr.context.scale(1 / scale, 1 / scale);\n txr.context.translate(-txr.usedWidth, 0);\n }\n\n eleCache = {\n x: txr.usedWidth,\n texture: txr,\n level: lvl,\n scale: scale,\n width: eleScaledW,\n height: eleScaledH,\n scaledLabelShown: scaledLabelShown\n };\n txr.usedWidth += Math.ceil(eleScaledW + eleTxrSpacing);\n txr.eleCaches.push(eleCache);\n lookup.set(ele, lvl, eleCache);\n self.checkTextureFullness(txr);\n return eleCache;\n};\n\nETCp.invalidateElements = function (eles) {\n for (var i = 0; i < eles.length; i++) {\n this.invalidateElement(eles[i]);\n }\n};\n\nETCp.invalidateElement = function (ele) {\n var self = this;\n var lookup = self.lookup;\n var caches = [];\n var invalid = lookup.isInvalid(ele);\n\n if (!invalid) {\n return; // override the invalidation request if the element key has not changed\n }\n\n for (var lvl = minLvl; lvl <= maxLvl; lvl++) {\n var cache = lookup.getForCachedKey(ele, lvl);\n\n if (cache) {\n caches.push(cache);\n }\n }\n\n var noOtherElesUseCache = lookup.invalidate(ele);\n\n if (noOtherElesUseCache) {\n for (var i = 0; i < caches.length; i++) {\n var _cache = caches[i];\n var txr = _cache.texture; // remove space from the texture it belongs to\n\n txr.invalidatedWidth += _cache.width; // mark the cache as invalidated\n\n _cache.invalidated = true; // retire the texture if its utility is low\n\n self.checkTextureUtility(txr);\n }\n } // remove from queue since the old req was for the old state\n\n\n self.removeFromQueue(ele);\n};\n\nETCp.checkTextureUtility = function (txr) {\n // invalidate all entries in the cache if the cache size is small\n if (txr.invalidatedWidth >= minUtility * txr.width) {\n this.retireTexture(txr);\n }\n};\n\nETCp.checkTextureFullness = function (txr) {\n // if texture has been mostly filled and passed over several times, remove\n // it from the queue so we don't need to waste time looking at it to put new things\n var self = this;\n var txrQ = self.getTextureQueue(txr.height);\n\n if (txr.usedWidth / txr.width > maxFullness && txr.fullnessChecks >= maxFullnessChecks) {\n removeFromArray(txrQ, txr);\n } else {\n txr.fullnessChecks++;\n }\n};\n\nETCp.retireTexture = function (txr) {\n var self = this;\n var txrH = txr.height;\n var txrQ = self.getTextureQueue(txrH);\n var lookup = this.lookup; // retire the texture from the active / searchable queue:\n\n removeFromArray(txrQ, txr);\n txr.retired = true; // remove the refs from the eles to the caches:\n\n var eleCaches = txr.eleCaches;\n\n for (var i = 0; i < eleCaches.length; i++) {\n var eleCache = eleCaches[i];\n lookup.deleteCache(eleCache.key, eleCache.level);\n }\n\n clearArray(eleCaches); // add the texture to a retired queue so it can be recycled in future:\n\n var rtxtrQ = self.getRetiredTextureQueue(txrH);\n rtxtrQ.push(txr);\n};\n\nETCp.addTexture = function (txrH, minW) {\n var self = this;\n var txrQ = self.getTextureQueue(txrH);\n var txr = {};\n txrQ.push(txr);\n txr.eleCaches = [];\n txr.height = txrH;\n txr.width = Math.max(defTxrWidth, minW);\n txr.usedWidth = 0;\n txr.invalidatedWidth = 0;\n txr.fullnessChecks = 0;\n txr.canvas = self.renderer.makeOffscreenCanvas(txr.width, txr.height);\n txr.context = txr.canvas.getContext('2d');\n return txr;\n};\n\nETCp.recycleTexture = function (txrH, minW) {\n var self = this;\n var txrQ = self.getTextureQueue(txrH);\n var rtxtrQ = self.getRetiredTextureQueue(txrH);\n\n for (var i = 0; i < rtxtrQ.length; i++) {\n var txr = rtxtrQ[i];\n\n if (txr.width >= minW) {\n txr.retired = false;\n txr.usedWidth = 0;\n txr.invalidatedWidth = 0;\n txr.fullnessChecks = 0;\n clearArray(txr.eleCaches);\n txr.context.setTransform(1, 0, 0, 1, 0, 0);\n txr.context.clearRect(0, 0, txr.width, txr.height);\n removeFromArray(rtxtrQ, txr);\n txrQ.push(txr);\n return txr;\n }\n }\n};\n\nETCp.queueElement = function (ele, lvl) {\n var self = this;\n var q = self.getElementQueue();\n var k2q = self.getElementKeyToQueue();\n var key = this.getKey(ele);\n var existingReq = k2q[key];\n\n if (existingReq) {\n // use the max lvl b/c in between lvls are cheap to make\n existingReq.level = Math.max(existingReq.level, lvl);\n existingReq.eles.merge(ele);\n existingReq.reqs++;\n q.updateItem(existingReq);\n } else {\n var req = {\n eles: ele.spawn().merge(ele),\n level: lvl,\n reqs: 1,\n key: key\n };\n q.push(req);\n k2q[key] = req;\n }\n};\n\nETCp.dequeue = function (pxRatio\n/*, extent*/\n) {\n var self = this;\n var q = self.getElementQueue();\n var k2q = self.getElementKeyToQueue();\n var dequeued = [];\n var lookup = self.lookup;\n\n for (var i = 0; i < maxDeqSize; i++) {\n if (q.size() > 0) {\n var req = q.pop();\n var key = req.key;\n var ele = req.eles[0]; // all eles have the same key\n\n var cacheExists = lookup.hasCache(ele, req.level); // clear out the key to req lookup\n\n k2q[key] = null; // dequeueing isn't necessary with an existing cache\n\n if (cacheExists) {\n continue;\n }\n\n dequeued.push(req);\n var bb = self.getBoundingBox(ele);\n self.getElement(ele, bb, pxRatio, req.level, getTxrReasons.dequeue);\n } else {\n break;\n }\n }\n\n return dequeued;\n};\n\nETCp.removeFromQueue = function (ele) {\n var self = this;\n var q = self.getElementQueue();\n var k2q = self.getElementKeyToQueue();\n var key = this.getKey(ele);\n var req = k2q[key];\n\n if (req != null) {\n if (req.eles.length === 1) {\n // remove if last ele in the req\n // bring to front of queue\n req.reqs = MAX_INT;\n q.updateItem(req);\n q.pop(); // remove from queue\n\n k2q[key] = null; // remove from lookup map\n } else {\n // otherwise just remove ele from req\n req.eles.unmerge(ele);\n }\n }\n};\n\nETCp.onDequeue = function (fn) {\n this.onDequeues.push(fn);\n};\n\nETCp.offDequeue = function (fn) {\n removeFromArray(this.onDequeues, fn);\n};\n\nETCp.setupDequeueing = defs.setupDequeueing({\n deqRedrawThreshold: deqRedrawThreshold,\n deqCost: deqCost,\n deqAvgCost: deqAvgCost,\n deqNoDrawCost: deqNoDrawCost,\n deqFastCost: deqFastCost,\n deq: function deq(self, pxRatio, extent) {\n return self.dequeue(pxRatio, extent);\n },\n onDeqd: function onDeqd(self, deqd) {\n for (var i = 0; i < self.onDequeues.length; i++) {\n var fn = self.onDequeues[i];\n fn(deqd);\n }\n },\n shouldRedraw: function shouldRedraw(self, deqd, pxRatio, extent) {\n for (var i = 0; i < deqd.length; i++) {\n var eles = deqd[i].eles;\n\n for (var j = 0; j < eles.length; j++) {\n var bb = eles[j].boundingBox();\n\n if (boundingBoxesIntersect(bb, extent)) {\n return true;\n }\n }\n }\n\n return false;\n },\n priority: function priority(self) {\n return self.renderer.beforeRenderPriorities.eleTxrDeq;\n }\n});\n\nvar defNumLayers = 1; // default number of layers to use\n\nvar minLvl$1 = -4; // when scaling smaller than that we don't need to re-render\n\nvar maxLvl$1 = 2; // when larger than this scale just render directly (caching is not helpful)\n\nvar maxZoom$1 = 3.99; // beyond this zoom level, layered textures are not used\n\nvar deqRedrawThreshold$1 = 50; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile\n\nvar refineEleDebounceTime = 50; // time to debounce sharper ele texture updates\n\nvar deqCost$1 = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame\n\nvar deqAvgCost$1 = 0.1; // % of add'l rendering cost compared to average overall redraw time\n\nvar deqNoDrawCost$1 = 0.9; // % of avg frame time that can be used for dequeueing when not drawing\n\nvar deqFastCost$1 = 0.9; // % of frame time to be used when >60fps\n\nvar maxDeqSize$1 = 1; // number of eles to dequeue and render at higher texture in each batch\n\nvar invalidThreshold = 250; // time threshold for disabling b/c of invalidations\n\nvar maxLayerArea = 4000 * 4000; // layers can't be bigger than this\n\nvar useHighQualityEleTxrReqs = true; // whether to use high quality ele txr requests (generally faster and cheaper in the longterm)\n// var log = function(){ console.log.apply( console, arguments ); };\n\nvar LayeredTextureCache = function LayeredTextureCache(renderer) {\n var self = this;\n var r = self.renderer = renderer;\n var cy = r.cy;\n self.layersByLevel = {}; // e.g. 2 => [ layer1, layer2, ..., layerN ]\n\n self.firstGet = true;\n self.lastInvalidationTime = performanceNow() - 2 * invalidThreshold;\n self.skipping = false;\n self.eleTxrDeqs = cy.collection();\n self.scheduleElementRefinement = util(function () {\n self.refineElementTextures(self.eleTxrDeqs);\n self.eleTxrDeqs.unmerge(self.eleTxrDeqs);\n }, refineEleDebounceTime);\n r.beforeRender(function (willDraw, now) {\n if (now - self.lastInvalidationTime <= invalidThreshold) {\n self.skipping = true;\n } else {\n self.skipping = false;\n }\n }, r.beforeRenderPriorities.lyrTxrSkip);\n\n var qSort = function qSort(a, b) {\n return b.reqs - a.reqs;\n };\n\n self.layersQueue = new Heap(qSort);\n self.setupDequeueing();\n};\n\nvar LTCp = LayeredTextureCache.prototype;\nvar layerIdPool = 0;\nvar MAX_INT$1 = Math.pow(2, 53) - 1;\n\nLTCp.makeLayer = function (bb, lvl) {\n var scale = Math.pow(2, lvl);\n var w = Math.ceil(bb.w * scale);\n var h = Math.ceil(bb.h * scale);\n var canvas = this.renderer.makeOffscreenCanvas(w, h);\n var layer = {\n id: layerIdPool = ++layerIdPool % MAX_INT$1,\n bb: bb,\n level: lvl,\n width: w,\n height: h,\n canvas: canvas,\n context: canvas.getContext('2d'),\n eles: [],\n elesQueue: [],\n reqs: 0\n }; // log('make layer %s with w %s and h %s and lvl %s', layer.id, layer.width, layer.height, layer.level);\n\n var cxt = layer.context;\n var dx = -layer.bb.x1;\n var dy = -layer.bb.y1; // do the transform on creation to save cycles (it's the same for all eles)\n\n cxt.scale(scale, scale);\n cxt.translate(dx, dy);\n return layer;\n};\n\nLTCp.getLayers = function (eles, pxRatio, lvl) {\n var self = this;\n var r = self.renderer;\n var cy = r.cy;\n var zoom = cy.zoom();\n var firstGet = self.firstGet;\n self.firstGet = false; // log('--\\nget layers with %s eles', eles.length);\n //log eles.map(function(ele){ return ele.id() }) );\n\n if (lvl == null) {\n lvl = Math.ceil(log2(zoom * pxRatio));\n\n if (lvl < minLvl$1) {\n lvl = minLvl$1;\n } else if (zoom >= maxZoom$1 || lvl > maxLvl$1) {\n return null;\n }\n }\n\n self.validateLayersElesOrdering(lvl, eles);\n var layersByLvl = self.layersByLevel;\n var scale = Math.pow(2, lvl);\n var layers = layersByLvl[lvl] = layersByLvl[lvl] || [];\n var bb;\n var lvlComplete = self.levelIsComplete(lvl, eles);\n var tmpLayers;\n\n var checkTempLevels = function checkTempLevels() {\n var canUseAsTmpLvl = function canUseAsTmpLvl(l) {\n self.validateLayersElesOrdering(l, eles);\n\n if (self.levelIsComplete(l, eles)) {\n tmpLayers = layersByLvl[l];\n return true;\n }\n };\n\n var checkLvls = function checkLvls(dir) {\n if (tmpLayers) {\n return;\n }\n\n for (var l = lvl + dir; minLvl$1 <= l && l <= maxLvl$1; l += dir) {\n if (canUseAsTmpLvl(l)) {\n break;\n }\n }\n };\n\n checkLvls(+1);\n checkLvls(-1); // remove the invalid layers; they will be replaced as needed later in this function\n\n for (var i = layers.length - 1; i >= 0; i--) {\n var layer = layers[i];\n\n if (layer.invalid) {\n removeFromArray(layers, layer);\n }\n }\n };\n\n if (!lvlComplete) {\n // if the current level is incomplete, then use the closest, best quality layerset temporarily\n // and later queue the current layerset so we can get the proper quality level soon\n checkTempLevels();\n } else {\n // log('level complete, using existing layers\\n--');\n return layers;\n }\n\n var getBb = function getBb() {\n if (!bb) {\n bb = makeBoundingBox();\n\n for (var i = 0; i < eles.length; i++) {\n updateBoundingBox(bb, eles[i].boundingBox());\n }\n }\n\n return bb;\n };\n\n var makeLayer = function makeLayer(opts) {\n opts = opts || {};\n var after = opts.after;\n getBb();\n var area = bb.w * scale * (bb.h * scale);\n\n if (area > maxLayerArea) {\n return null;\n }\n\n var layer = self.makeLayer(bb, lvl);\n\n if (after != null) {\n var index = layers.indexOf(after) + 1;\n layers.splice(index, 0, layer);\n } else if (opts.insert === undefined || opts.insert) {\n // no after specified => first layer made so put at start\n layers.unshift(layer);\n } // if( tmpLayers ){\n //self.queueLayer( layer );\n // }\n\n\n return layer;\n };\n\n if (self.skipping && !firstGet) {\n // log('skip layers');\n return null;\n } // log('do layers');\n\n\n var layer = null;\n var maxElesPerLayer = eles.length / defNumLayers;\n var allowLazyQueueing = !firstGet;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n var rs = ele._private.rscratch;\n var caches = rs.imgLayerCaches = rs.imgLayerCaches || {}; // log('look at ele', ele.id());\n\n var existingLayer = caches[lvl];\n\n if (existingLayer) {\n // reuse layer for later eles\n // log('reuse layer for', ele.id());\n layer = existingLayer;\n continue;\n }\n\n if (!layer || layer.eles.length >= maxElesPerLayer || !boundingBoxInBoundingBox(layer.bb, ele.boundingBox())) {\n // log('make new layer for ele %s', ele.id());\n layer = makeLayer({\n insert: true,\n after: layer\n }); // if now layer can be built then we can't use layers at this level\n\n if (!layer) {\n return null;\n } // log('new layer with id %s', layer.id);\n\n }\n\n if (tmpLayers || allowLazyQueueing) {\n // log('queue ele %s in layer %s', ele.id(), layer.id);\n self.queueLayer(layer, ele);\n } else {\n // log('draw ele %s in layer %s', ele.id(), layer.id);\n self.drawEleInLayer(layer, ele, lvl, pxRatio);\n }\n\n layer.eles.push(ele);\n caches[lvl] = layer;\n } // log('--');\n\n\n if (tmpLayers) {\n // then we only queued the current layerset and can't draw it yet\n return tmpLayers;\n }\n\n if (allowLazyQueueing) {\n // log('lazy queue level', lvl);\n return null;\n }\n\n return layers;\n}; // a layer may want to use an ele cache of a higher level to avoid blurriness\n// so the layer level might not equal the ele level\n\n\nLTCp.getEleLevelForLayerLevel = function (lvl, pxRatio) {\n return lvl;\n};\n\nLTCp.drawEleInLayer = function (layer, ele, lvl, pxRatio) {\n var self = this;\n var r = this.renderer;\n var context = layer.context;\n var bb = ele.boundingBox();\n\n if (bb.w === 0 || bb.h === 0 || !ele.visible()) {\n return;\n }\n\n lvl = self.getEleLevelForLayerLevel(lvl, pxRatio);\n\n {\n r.setImgSmoothing(context, false);\n }\n\n {\n r.drawCachedElement(context, ele, null, null, lvl, useHighQualityEleTxrReqs);\n }\n\n {\n r.setImgSmoothing(context, true);\n }\n};\n\nLTCp.levelIsComplete = function (lvl, eles) {\n var self = this;\n var layers = self.layersByLevel[lvl];\n\n if (!layers || layers.length === 0) {\n return false;\n }\n\n var numElesInLayers = 0;\n\n for (var i = 0; i < layers.length; i++) {\n var layer = layers[i]; // if there are any eles needed to be drawn yet, the level is not complete\n\n if (layer.reqs > 0) {\n return false;\n } // if the layer is invalid, the level is not complete\n\n\n if (layer.invalid) {\n return false;\n }\n\n numElesInLayers += layer.eles.length;\n } // we should have exactly the number of eles passed in to be complete\n\n\n if (numElesInLayers !== eles.length) {\n return false;\n }\n\n return true;\n};\n\nLTCp.validateLayersElesOrdering = function (lvl, eles) {\n var layers = this.layersByLevel[lvl];\n\n if (!layers) {\n return;\n } // if in a layer the eles are not in the same order, then the layer is invalid\n // (i.e. there is an ele in between the eles in the layer)\n\n\n for (var i = 0; i < layers.length; i++) {\n var layer = layers[i];\n var offset = -1; // find the offset\n\n for (var j = 0; j < eles.length; j++) {\n if (layer.eles[0] === eles[j]) {\n offset = j;\n break;\n }\n }\n\n if (offset < 0) {\n // then the layer has nonexistant elements and is invalid\n this.invalidateLayer(layer);\n continue;\n } // the eles in the layer must be in the same continuous order, else the layer is invalid\n\n\n var o = offset;\n\n for (var j = 0; j < layer.eles.length; j++) {\n if (layer.eles[j] !== eles[o + j]) {\n // log('invalidate based on ordering', layer.id);\n this.invalidateLayer(layer);\n break;\n }\n }\n }\n};\n\nLTCp.updateElementsInLayers = function (eles, update) {\n var self = this;\n var isEles = element(eles[0]); // collect udpated elements (cascaded from the layers) and update each\n // layer itself along the way\n\n for (var i = 0; i < eles.length; i++) {\n var req = isEles ? null : eles[i];\n var ele = isEles ? eles[i] : eles[i].ele;\n var rs = ele._private.rscratch;\n var caches = rs.imgLayerCaches = rs.imgLayerCaches || {};\n\n for (var l = minLvl$1; l <= maxLvl$1; l++) {\n var layer = caches[l];\n\n if (!layer) {\n continue;\n } // if update is a request from the ele cache, then it affects only\n // the matching level\n\n\n if (req && self.getEleLevelForLayerLevel(layer.level) !== req.level) {\n continue;\n }\n\n update(layer, ele, req);\n }\n }\n};\n\nLTCp.haveLayers = function () {\n var self = this;\n var haveLayers = false;\n\n for (var l = minLvl$1; l <= maxLvl$1; l++) {\n var layers = self.layersByLevel[l];\n\n if (layers && layers.length > 0) {\n haveLayers = true;\n break;\n }\n }\n\n return haveLayers;\n};\n\nLTCp.invalidateElements = function (eles) {\n var self = this;\n\n if (eles.length === 0) {\n return;\n }\n\n self.lastInvalidationTime = performanceNow(); // log('update invalidate layer time from eles');\n\n if (eles.length === 0 || !self.haveLayers()) {\n return;\n }\n\n self.updateElementsInLayers(eles, function invalAssocLayers(layer, ele, req) {\n self.invalidateLayer(layer);\n });\n};\n\nLTCp.invalidateLayer = function (layer) {\n // log('update invalidate layer time');\n this.lastInvalidationTime = performanceNow();\n\n if (layer.invalid) {\n return;\n } // save cycles\n\n\n var lvl = layer.level;\n var eles = layer.eles;\n var layers = this.layersByLevel[lvl]; // log('invalidate layer', layer.id );\n\n removeFromArray(layers, layer); // layer.eles = [];\n\n layer.elesQueue = [];\n layer.invalid = true;\n\n if (layer.replacement) {\n layer.replacement.invalid = true;\n }\n\n for (var i = 0; i < eles.length; i++) {\n var caches = eles[i]._private.rscratch.imgLayerCaches;\n\n if (caches) {\n caches[lvl] = null;\n }\n }\n};\n\nLTCp.refineElementTextures = function (eles) {\n var self = this; // log('refine', eles.length);\n\n self.updateElementsInLayers(eles, function refineEachEle(layer, ele, req) {\n var rLyr = layer.replacement;\n\n if (!rLyr) {\n rLyr = layer.replacement = self.makeLayer(layer.bb, layer.level);\n rLyr.replaces = layer;\n rLyr.eles = layer.eles; // log('make replacement layer %s for %s with level %s', rLyr.id, layer.id, rLyr.level);\n }\n\n if (!rLyr.reqs) {\n for (var i = 0; i < rLyr.eles.length; i++) {\n self.queueLayer(rLyr, rLyr.eles[i]);\n } // log('queue replacement layer refinement', rLyr.id);\n\n }\n });\n};\n\nLTCp.enqueueElementRefinement = function (ele) {\n\n this.eleTxrDeqs.merge(ele);\n this.scheduleElementRefinement();\n};\n\nLTCp.queueLayer = function (layer, ele) {\n var self = this;\n var q = self.layersQueue;\n var elesQ = layer.elesQueue;\n var hasId = elesQ.hasId = elesQ.hasId || {}; // if a layer is going to be replaced, queuing is a waste of time\n\n if (layer.replacement) {\n return;\n }\n\n if (ele) {\n if (hasId[ele.id()]) {\n return;\n }\n\n elesQ.push(ele);\n hasId[ele.id()] = true;\n }\n\n if (layer.reqs) {\n layer.reqs++;\n q.updateItem(layer);\n } else {\n layer.reqs = 1;\n q.push(layer);\n }\n};\n\nLTCp.dequeue = function (pxRatio) {\n var self = this;\n var q = self.layersQueue;\n var deqd = [];\n var eleDeqs = 0;\n\n while (eleDeqs < maxDeqSize$1) {\n if (q.size() === 0) {\n break;\n }\n\n var layer = q.peek(); // if a layer has been or will be replaced, then don't waste time with it\n\n if (layer.replacement) {\n // log('layer %s in queue skipped b/c it already has a replacement', layer.id);\n q.pop();\n continue;\n } // if this is a replacement layer that has been superceded, then forget it\n\n\n if (layer.replaces && layer !== layer.replaces.replacement) {\n // log('layer is no longer the most uptodate replacement; dequeued', layer.id)\n q.pop();\n continue;\n }\n\n if (layer.invalid) {\n // log('replacement layer %s is invalid; dequeued', layer.id);\n q.pop();\n continue;\n }\n\n var ele = layer.elesQueue.shift();\n\n if (ele) {\n // log('dequeue layer %s', layer.id);\n self.drawEleInLayer(layer, ele, layer.level, pxRatio);\n eleDeqs++;\n }\n\n if (deqd.length === 0) {\n // we need only one entry in deqd to queue redrawing etc\n deqd.push(true);\n } // if the layer has all its eles done, then remove from the queue\n\n\n if (layer.elesQueue.length === 0) {\n q.pop();\n layer.reqs = 0; // log('dequeue of layer %s complete', layer.id);\n // when a replacement layer is dequeued, it replaces the old layer in the level\n\n if (layer.replaces) {\n self.applyLayerReplacement(layer);\n }\n\n self.requestRedraw();\n }\n }\n\n return deqd;\n};\n\nLTCp.applyLayerReplacement = function (layer) {\n var self = this;\n var layersInLevel = self.layersByLevel[layer.level];\n var replaced = layer.replaces;\n var index = layersInLevel.indexOf(replaced); // if the replaced layer is not in the active list for the level, then replacing\n // refs would be a mistake (i.e. overwriting the true active layer)\n\n if (index < 0 || replaced.invalid) {\n // log('replacement layer would have no effect', layer.id);\n return;\n }\n\n layersInLevel[index] = layer; // replace level ref\n // replace refs in eles\n\n for (var i = 0; i < layer.eles.length; i++) {\n var _p = layer.eles[i]._private;\n var cache = _p.imgLayerCaches = _p.imgLayerCaches || {};\n\n if (cache) {\n cache[layer.level] = layer;\n }\n } // log('apply replacement layer %s over %s', layer.id, replaced.id);\n\n\n self.requestRedraw();\n};\n\nLTCp.requestRedraw = util(function () {\n var r = this.renderer;\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n r.redraw();\n}, 100);\nLTCp.setupDequeueing = defs.setupDequeueing({\n deqRedrawThreshold: deqRedrawThreshold$1,\n deqCost: deqCost$1,\n deqAvgCost: deqAvgCost$1,\n deqNoDrawCost: deqNoDrawCost$1,\n deqFastCost: deqFastCost$1,\n deq: function deq(self, pxRatio) {\n return self.dequeue(pxRatio);\n },\n onDeqd: noop,\n shouldRedraw: trueify,\n priority: function priority(self) {\n return self.renderer.beforeRenderPriorities.lyrTxrDeq;\n }\n});\n\nvar CRp = {};\nvar impl;\n\nfunction polygon(context, points) {\n for (var i = 0; i < points.length; i++) {\n var pt = points[i];\n context.lineTo(pt.x, pt.y);\n }\n}\n\nfunction triangleBackcurve(context, points, controlPoint) {\n var firstPt;\n\n for (var i = 0; i < points.length; i++) {\n var pt = points[i];\n\n if (i === 0) {\n firstPt = pt;\n }\n\n context.lineTo(pt.x, pt.y);\n }\n\n context.quadraticCurveTo(controlPoint.x, controlPoint.y, firstPt.x, firstPt.y);\n}\n\nfunction triangleTee(context, trianglePoints, teePoints) {\n if (context.beginPath) {\n context.beginPath();\n }\n\n var triPts = trianglePoints;\n\n for (var i = 0; i < triPts.length; i++) {\n var pt = triPts[i];\n context.lineTo(pt.x, pt.y);\n }\n\n var teePts = teePoints;\n var firstTeePt = teePoints[0];\n context.moveTo(firstTeePt.x, firstTeePt.y);\n\n for (var i = 1; i < teePts.length; i++) {\n var pt = teePts[i];\n context.lineTo(pt.x, pt.y);\n }\n\n if (context.closePath) {\n context.closePath();\n }\n}\n\nfunction circleTriangle(context, trianglePoints, rx, ry, r) {\n if (context.beginPath) {\n context.beginPath();\n }\n\n context.arc(rx, ry, r, 0, Math.PI * 2, false);\n var triPts = trianglePoints;\n var firstTrPt = triPts[0];\n context.moveTo(firstTrPt.x, firstTrPt.y);\n\n for (var i = 0; i < triPts.length; i++) {\n var pt = triPts[i];\n context.lineTo(pt.x, pt.y);\n }\n\n if (context.closePath) {\n context.closePath();\n }\n}\n\nfunction circle(context, rx, ry, r) {\n context.arc(rx, ry, r, 0, Math.PI * 2, false);\n}\n\nCRp.arrowShapeImpl = function (name) {\n return (impl || (impl = {\n 'polygon': polygon,\n 'triangle-backcurve': triangleBackcurve,\n 'triangle-tee': triangleTee,\n 'circle-triangle': circleTriangle,\n 'triangle-cross': triangleTee,\n 'circle': circle\n }))[name];\n};\n\nvar CRp$1 = {};\n\nCRp$1.drawElement = function (context, ele, shiftToOriginWithBb, showLabel, showOverlay, showOpacity) {\n var r = this;\n\n if (ele.isNode()) {\n r.drawNode(context, ele, shiftToOriginWithBb, showLabel, showOverlay, showOpacity);\n } else {\n r.drawEdge(context, ele, shiftToOriginWithBb, showLabel, showOverlay, showOpacity);\n }\n};\n\nCRp$1.drawElementOverlay = function (context, ele) {\n var r = this;\n\n if (ele.isNode()) {\n r.drawNodeOverlay(context, ele);\n } else {\n r.drawEdgeOverlay(context, ele);\n }\n};\n\nCRp$1.drawCachedElementPortion = function (context, ele, eleTxrCache, pxRatio, lvl, reason, getRotation, getOpacity) {\n var r = this;\n var bb = eleTxrCache.getBoundingBox(ele);\n\n if (bb.w === 0 || bb.h === 0) {\n return;\n } // ignore zero size case\n\n\n var eleCache = eleTxrCache.getElement(ele, bb, pxRatio, lvl, reason);\n\n if (eleCache != null) {\n var opacity = getOpacity(r, ele);\n\n if (opacity === 0) {\n return;\n }\n\n var theta = getRotation(r, ele);\n var x1 = bb.x1,\n y1 = bb.y1,\n w = bb.w,\n h = bb.h;\n var x, y, sx, sy, smooth;\n\n if (theta !== 0) {\n var rotPt = eleTxrCache.getRotationPoint(ele);\n sx = rotPt.x;\n sy = rotPt.y;\n context.translate(sx, sy);\n context.rotate(theta);\n smooth = r.getImgSmoothing(context);\n\n if (!smooth) {\n r.setImgSmoothing(context, true);\n }\n\n var off = eleTxrCache.getRotationOffset(ele);\n x = off.x;\n y = off.y;\n } else {\n x = x1;\n y = y1;\n }\n\n var oldGlobalAlpha;\n\n if (opacity !== 1) {\n oldGlobalAlpha = context.globalAlpha;\n context.globalAlpha = oldGlobalAlpha * opacity;\n }\n\n context.drawImage(eleCache.texture.canvas, eleCache.x, 0, eleCache.width, eleCache.height, x, y, w, h);\n\n if (opacity !== 1) {\n context.globalAlpha = oldGlobalAlpha;\n }\n\n if (theta !== 0) {\n context.rotate(-theta);\n context.translate(-sx, -sy);\n\n if (!smooth) {\n r.setImgSmoothing(context, false);\n }\n }\n } else {\n eleTxrCache.drawElement(context, ele); // direct draw fallback\n }\n};\n\nvar getZeroRotation = function getZeroRotation() {\n return 0;\n};\n\nvar getLabelRotation = function getLabelRotation(r, ele) {\n return r.getTextAngle(ele, null);\n};\n\nvar getSourceLabelRotation = function getSourceLabelRotation(r, ele) {\n return r.getTextAngle(ele, 'source');\n};\n\nvar getTargetLabelRotation = function getTargetLabelRotation(r, ele) {\n return r.getTextAngle(ele, 'target');\n};\n\nvar getOpacity = function getOpacity(r, ele) {\n return ele.effectiveOpacity();\n};\n\nvar getTextOpacity = function getTextOpacity(e, ele) {\n return ele.pstyle('text-opacity').pfValue * ele.effectiveOpacity();\n};\n\nCRp$1.drawCachedElement = function (context, ele, pxRatio, extent, lvl, requestHighQuality) {\n var r = this;\n var _r$data = r.data,\n eleTxrCache = _r$data.eleTxrCache,\n lblTxrCache = _r$data.lblTxrCache,\n slbTxrCache = _r$data.slbTxrCache,\n tlbTxrCache = _r$data.tlbTxrCache;\n var bb = ele.boundingBox();\n var reason = requestHighQuality === true ? eleTxrCache.reasons.highQuality : null;\n\n if (bb.w === 0 || bb.h === 0 || !ele.visible()) {\n return;\n }\n\n if (!extent || boundingBoxesIntersect(bb, extent)) {\n var isEdge = ele.isEdge();\n\n var badLine = ele.element()._private.rscratch.badLine;\n\n r.drawCachedElementPortion(context, ele, eleTxrCache, pxRatio, lvl, reason, getZeroRotation, getOpacity);\n\n if (!isEdge || !badLine) {\n r.drawCachedElementPortion(context, ele, lblTxrCache, pxRatio, lvl, reason, getLabelRotation, getTextOpacity);\n }\n\n if (isEdge && !badLine) {\n r.drawCachedElementPortion(context, ele, slbTxrCache, pxRatio, lvl, reason, getSourceLabelRotation, getTextOpacity);\n r.drawCachedElementPortion(context, ele, tlbTxrCache, pxRatio, lvl, reason, getTargetLabelRotation, getTextOpacity);\n }\n\n r.drawElementOverlay(context, ele);\n }\n};\n\nCRp$1.drawElements = function (context, eles) {\n var r = this;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n r.drawElement(context, ele);\n }\n};\n\nCRp$1.drawCachedElements = function (context, eles, pxRatio, extent) {\n var r = this;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n r.drawCachedElement(context, ele, pxRatio, extent);\n }\n};\n\nCRp$1.drawCachedNodes = function (context, eles, pxRatio, extent) {\n var r = this;\n\n for (var i = 0; i < eles.length; i++) {\n var ele = eles[i];\n\n if (!ele.isNode()) {\n continue;\n }\n\n r.drawCachedElement(context, ele, pxRatio, extent);\n }\n};\n\nCRp$1.drawLayeredElements = function (context, eles, pxRatio, extent) {\n var r = this;\n var layers = r.data.lyrTxrCache.getLayers(eles, pxRatio);\n\n if (layers) {\n for (var i = 0; i < layers.length; i++) {\n var layer = layers[i];\n var bb = layer.bb;\n\n if (bb.w === 0 || bb.h === 0) {\n continue;\n }\n\n context.drawImage(layer.canvas, bb.x1, bb.y1, bb.w, bb.h);\n }\n } else {\n // fall back on plain caching if no layers\n r.drawCachedElements(context, eles, pxRatio, extent);\n }\n};\n\n/* global Path2D */\nvar CRp$2 = {};\n\nCRp$2.drawEdge = function (context, edge, shiftToOriginWithBb) {\n var drawLabel = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n var shouldDrawOverlay = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;\n var shouldDrawOpacity = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;\n var r = this;\n var rs = edge._private.rscratch;\n\n if (shouldDrawOpacity && !edge.visible()) {\n return;\n } // if bezier ctrl pts can not be calculated, then die\n\n\n if (rs.badLine || rs.allpts == null || isNaN(rs.allpts[0])) {\n // isNaN in case edge is impossible and browser bugs (e.g. safari)\n return;\n }\n\n var bb;\n\n if (shiftToOriginWithBb) {\n bb = shiftToOriginWithBb;\n context.translate(-bb.x1, -bb.y1);\n }\n\n var opacity = shouldDrawOpacity ? edge.pstyle('opacity').value : 1;\n var lineStyle = edge.pstyle('line-style').value;\n var edgeWidth = edge.pstyle('width').pfValue;\n var lineCap = edge.pstyle('line-cap').value;\n\n var drawLine = function drawLine() {\n var strokeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : opacity;\n context.lineWidth = edgeWidth;\n context.lineCap = lineCap;\n r.eleStrokeStyle(context, edge, strokeOpacity);\n r.drawEdgePath(edge, context, rs.allpts, lineStyle);\n context.lineCap = 'butt'; // reset for other drawing functions\n };\n\n var drawOverlay = function drawOverlay() {\n if (!shouldDrawOverlay) {\n return;\n }\n\n r.drawEdgeOverlay(context, edge);\n };\n\n var drawArrows = function drawArrows() {\n var arrowOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : opacity;\n r.drawArrowheads(context, edge, arrowOpacity);\n };\n\n var drawText = function drawText() {\n r.drawElementText(context, edge, null, drawLabel);\n };\n\n context.lineJoin = 'round';\n var ghost = edge.pstyle('ghost').value === 'yes';\n\n if (ghost) {\n var gx = edge.pstyle('ghost-offset-x').pfValue;\n var gy = edge.pstyle('ghost-offset-y').pfValue;\n var ghostOpacity = edge.pstyle('ghost-opacity').value;\n var effectiveGhostOpacity = opacity * ghostOpacity;\n context.translate(gx, gy);\n drawLine(effectiveGhostOpacity);\n drawArrows(effectiveGhostOpacity);\n context.translate(-gx, -gy);\n }\n\n drawLine();\n drawArrows();\n drawOverlay();\n drawText();\n\n if (shiftToOriginWithBb) {\n context.translate(bb.x1, bb.y1);\n }\n};\n\nCRp$2.drawEdgeOverlay = function (context, edge) {\n if (!edge.visible()) {\n return;\n }\n\n var overlayOpacity = edge.pstyle('overlay-opacity').value;\n\n if (overlayOpacity === 0) {\n return;\n }\n\n var r = this;\n var usePaths = r.usePaths();\n var rs = edge._private.rscratch;\n var overlayPadding = edge.pstyle('overlay-padding').pfValue;\n var overlayWidth = 2 * overlayPadding;\n var overlayColor = edge.pstyle('overlay-color').value;\n context.lineWidth = overlayWidth;\n\n if (rs.edgeType === 'self' && !usePaths) {\n context.lineCap = 'butt';\n } else {\n context.lineCap = 'round';\n }\n\n r.colorStrokeStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n r.drawEdgePath(edge, context, rs.allpts, 'solid');\n};\n\nCRp$2.drawEdgePath = function (edge, context, pts, type) {\n var rs = edge._private.rscratch;\n var canvasCxt = context;\n var path;\n var pathCacheHit = false;\n var usePaths = this.usePaths();\n var lineDashPattern = edge.pstyle('line-dash-pattern').pfValue;\n var lineDashOffset = edge.pstyle('line-dash-offset').pfValue;\n\n if (usePaths) {\n var pathCacheKey = pts.join('$');\n var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey;\n\n if (keyMatches) {\n path = context = rs.pathCache;\n pathCacheHit = true;\n } else {\n path = context = new Path2D();\n rs.pathCacheKey = pathCacheKey;\n rs.pathCache = path;\n }\n }\n\n if (canvasCxt.setLineDash) {\n // for very outofdate browsers\n switch (type) {\n case 'dotted':\n canvasCxt.setLineDash([1, 1]);\n break;\n\n case 'dashed':\n canvasCxt.setLineDash(lineDashPattern);\n canvasCxt.lineDashOffset = lineDashOffset;\n break;\n\n case 'solid':\n canvasCxt.setLineDash([]);\n break;\n }\n }\n\n if (!pathCacheHit && !rs.badLine) {\n if (context.beginPath) {\n context.beginPath();\n }\n\n context.moveTo(pts[0], pts[1]);\n\n switch (rs.edgeType) {\n case 'bezier':\n case 'self':\n case 'compound':\n case 'multibezier':\n for (var i = 2; i + 3 < pts.length; i += 4) {\n context.quadraticCurveTo(pts[i], pts[i + 1], pts[i + 2], pts[i + 3]);\n }\n\n break;\n\n case 'straight':\n case 'segments':\n case 'haystack':\n for (var _i = 2; _i + 1 < pts.length; _i += 2) {\n context.lineTo(pts[_i], pts[_i + 1]);\n }\n\n break;\n }\n }\n\n context = canvasCxt;\n\n if (usePaths) {\n context.stroke(path);\n } else {\n context.stroke();\n } // reset any line dashes\n\n\n if (context.setLineDash) {\n // for very outofdate browsers\n context.setLineDash([]);\n }\n};\n\nCRp$2.drawArrowheads = function (context, edge, opacity) {\n var rs = edge._private.rscratch;\n var isHaystack = rs.edgeType === 'haystack';\n\n if (!isHaystack) {\n this.drawArrowhead(context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle, opacity);\n }\n\n this.drawArrowhead(context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle, opacity);\n this.drawArrowhead(context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle, opacity);\n\n if (!isHaystack) {\n this.drawArrowhead(context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle, opacity);\n }\n};\n\nCRp$2.drawArrowhead = function (context, edge, prefix, x, y, angle, opacity) {\n if (isNaN(x) || x == null || isNaN(y) || y == null || isNaN(angle) || angle == null) {\n return;\n }\n\n var self = this;\n var arrowShape = edge.pstyle(prefix + '-arrow-shape').value;\n\n if (arrowShape === 'none') {\n return;\n }\n\n var arrowClearFill = edge.pstyle(prefix + '-arrow-fill').value === 'hollow' ? 'both' : 'filled';\n var arrowFill = edge.pstyle(prefix + '-arrow-fill').value;\n var edgeWidth = edge.pstyle('width').pfValue;\n var edgeOpacity = edge.pstyle('opacity').value;\n\n if (opacity === undefined) {\n opacity = edgeOpacity;\n }\n\n var gco = context.globalCompositeOperation;\n\n if (opacity !== 1 || arrowFill === 'hollow') {\n // then extra clear is needed\n context.globalCompositeOperation = 'destination-out';\n self.colorFillStyle(context, 255, 255, 255, 1);\n self.colorStrokeStyle(context, 255, 255, 255, 1);\n self.drawArrowShape(edge, context, arrowClearFill, edgeWidth, arrowShape, x, y, angle);\n context.globalCompositeOperation = gco;\n } // otherwise, the opaque arrow clears it for free :)\n\n\n var color = edge.pstyle(prefix + '-arrow-color').value;\n self.colorFillStyle(context, color[0], color[1], color[2], opacity);\n self.colorStrokeStyle(context, color[0], color[1], color[2], opacity);\n self.drawArrowShape(edge, context, arrowFill, edgeWidth, arrowShape, x, y, angle);\n};\n\nCRp$2.drawArrowShape = function (edge, context, fill, edgeWidth, shape, x, y, angle) {\n var r = this;\n var usePaths = this.usePaths() && shape !== 'triangle-cross';\n var pathCacheHit = false;\n var path;\n var canvasContext = context;\n var translation = {\n x: x,\n y: y\n };\n var scale = edge.pstyle('arrow-scale').value;\n var size = this.getArrowWidth(edgeWidth, scale);\n var shapeImpl = r.arrowShapes[shape];\n\n if (usePaths) {\n var cache = r.arrowPathCache = r.arrowPathCache || [];\n var key = hashString(shape);\n var cachedPath = cache[key];\n\n if (cachedPath != null) {\n path = context = cachedPath;\n pathCacheHit = true;\n } else {\n path = context = new Path2D();\n cache[key] = path;\n }\n }\n\n if (!pathCacheHit) {\n if (context.beginPath) {\n context.beginPath();\n }\n\n if (usePaths) {\n // store in the path cache with values easily manipulated later\n shapeImpl.draw(context, 1, 0, {\n x: 0,\n y: 0\n }, 1);\n } else {\n shapeImpl.draw(context, size, angle, translation, edgeWidth);\n }\n\n if (context.closePath) {\n context.closePath();\n }\n }\n\n context = canvasContext;\n\n if (usePaths) {\n // set transform to arrow position/orientation\n context.translate(x, y);\n context.rotate(angle);\n context.scale(size, size);\n }\n\n if (fill === 'filled' || fill === 'both') {\n if (usePaths) {\n context.fill(path);\n } else {\n context.fill();\n }\n }\n\n if (fill === 'hollow' || fill === 'both') {\n context.lineWidth = (shapeImpl.matchEdgeWidth ? edgeWidth : 1) / (usePaths ? size : 1);\n context.lineJoin = 'miter';\n\n if (usePaths) {\n context.stroke(path);\n } else {\n context.stroke();\n }\n }\n\n if (usePaths) {\n // reset transform by applying inverse\n context.scale(1 / size, 1 / size);\n context.rotate(-angle);\n context.translate(-x, -y);\n }\n};\n\nvar CRp$3 = {};\n\nCRp$3.safeDrawImage = function (context, img, ix, iy, iw, ih, x, y, w, h) {\n // detect problematic cases for old browsers with bad images (cheaper than try-catch)\n if (iw <= 0 || ih <= 0 || w <= 0 || h <= 0) {\n return;\n }\n\n context.drawImage(img, ix, iy, iw, ih, x, y, w, h);\n};\n\nCRp$3.drawInscribedImage = function (context, img, node, index, nodeOpacity) {\n var r = this;\n var pos = node.position();\n var nodeX = pos.x;\n var nodeY = pos.y;\n var styleObj = node.cy().style();\n var getIndexedStyle = styleObj.getIndexedStyle.bind(styleObj);\n var fit = getIndexedStyle(node, 'background-fit', 'value', index);\n var repeat = getIndexedStyle(node, 'background-repeat', 'value', index);\n var nodeW = node.width();\n var nodeH = node.height();\n var paddingX2 = node.padding() * 2;\n var nodeTW = nodeW + (getIndexedStyle(node, 'background-width-relative-to', 'value', index) === 'inner' ? 0 : paddingX2);\n var nodeTH = nodeH + (getIndexedStyle(node, 'background-height-relative-to', 'value', index) === 'inner' ? 0 : paddingX2);\n var rs = node._private.rscratch;\n var clip = getIndexedStyle(node, 'background-clip', 'value', index);\n var shouldClip = clip === 'node';\n var imgOpacity = getIndexedStyle(node, 'background-image-opacity', 'value', index) * nodeOpacity;\n var imgW = img.width || img.cachedW;\n var imgH = img.height || img.cachedH; // workaround for broken browsers like ie\n\n if (null == imgW || null == imgH) {\n document.body.appendChild(img); // eslint-disable-line no-undef\n\n imgW = img.cachedW = img.width || img.offsetWidth;\n imgH = img.cachedH = img.height || img.offsetHeight;\n document.body.removeChild(img); // eslint-disable-line no-undef\n }\n\n var w = imgW;\n var h = imgH;\n\n if (getIndexedStyle(node, 'background-width', 'value', index) !== 'auto') {\n if (getIndexedStyle(node, 'background-width', 'units', index) === '%') {\n w = getIndexedStyle(node, 'background-width', 'pfValue', index) * nodeTW;\n } else {\n w = getIndexedStyle(node, 'background-width', 'pfValue', index);\n }\n }\n\n if (getIndexedStyle(node, 'background-height', 'value', index) !== 'auto') {\n if (getIndexedStyle(node, 'background-height', 'units', index) === '%') {\n h = getIndexedStyle(node, 'background-height', 'pfValue', index) * nodeTH;\n } else {\n h = getIndexedStyle(node, 'background-height', 'pfValue', index);\n }\n }\n\n if (w === 0 || h === 0) {\n return; // no point in drawing empty image (and chrome is broken in this case)\n }\n\n if (fit === 'contain') {\n var scale = Math.min(nodeTW / w, nodeTH / h);\n w *= scale;\n h *= scale;\n } else if (fit === 'cover') {\n var scale = Math.max(nodeTW / w, nodeTH / h);\n w *= scale;\n h *= scale;\n }\n\n var x = nodeX - nodeTW / 2; // left\n\n var posXUnits = getIndexedStyle(node, 'background-position-x', 'units', index);\n var posXPfVal = getIndexedStyle(node, 'background-position-x', 'pfValue', index);\n\n if (posXUnits === '%') {\n x += (nodeTW - w) * posXPfVal;\n } else {\n x += posXPfVal;\n }\n\n var offXUnits = getIndexedStyle(node, 'background-offset-x', 'units', index);\n var offXPfVal = getIndexedStyle(node, 'background-offset-x', 'pfValue', index);\n\n if (offXUnits === '%') {\n x += (nodeTW - w) * offXPfVal;\n } else {\n x += offXPfVal;\n }\n\n var y = nodeY - nodeTH / 2; // top\n\n var posYUnits = getIndexedStyle(node, 'background-position-y', 'units', index);\n var posYPfVal = getIndexedStyle(node, 'background-position-y', 'pfValue', index);\n\n if (posYUnits === '%') {\n y += (nodeTH - h) * posYPfVal;\n } else {\n y += posYPfVal;\n }\n\n var offYUnits = getIndexedStyle(node, 'background-offset-y', 'units', index);\n var offYPfVal = getIndexedStyle(node, 'background-offset-y', 'pfValue', index);\n\n if (offYUnits === '%') {\n y += (nodeTH - h) * offYPfVal;\n } else {\n y += offYPfVal;\n }\n\n if (rs.pathCache) {\n x -= nodeX;\n y -= nodeY;\n nodeX = 0;\n nodeY = 0;\n }\n\n var gAlpha = context.globalAlpha;\n context.globalAlpha = imgOpacity;\n\n if (repeat === 'no-repeat') {\n if (shouldClip) {\n context.save();\n\n if (rs.pathCache) {\n context.clip(rs.pathCache);\n } else {\n r.nodeShapes[r.getNodeShape(node)].draw(context, nodeX, nodeY, nodeTW, nodeTH);\n context.clip();\n }\n }\n\n r.safeDrawImage(context, img, 0, 0, imgW, imgH, x, y, w, h);\n\n if (shouldClip) {\n context.restore();\n }\n } else {\n var pattern = context.createPattern(img, repeat);\n context.fillStyle = pattern;\n r.nodeShapes[r.getNodeShape(node)].draw(context, nodeX, nodeY, nodeTW, nodeTH);\n context.translate(x, y);\n context.fill();\n context.translate(-x, -y);\n }\n\n context.globalAlpha = gAlpha;\n};\n\nvar CRp$4 = {};\n\nCRp$4.eleTextBiggerThanMin = function (ele, scale) {\n if (!scale) {\n var zoom = ele.cy().zoom();\n var pxRatio = this.getPixelRatio();\n var lvl = Math.ceil(log2(zoom * pxRatio)); // the effective texture level\n\n scale = Math.pow(2, lvl);\n }\n\n var computedSize = ele.pstyle('font-size').pfValue * scale;\n var minSize = ele.pstyle('min-zoomed-font-size').pfValue;\n\n if (computedSize < minSize) {\n return false;\n }\n\n return true;\n};\n\nCRp$4.drawElementText = function (context, ele, shiftToOriginWithBb, force, prefix) {\n var useEleOpacity = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;\n var r = this;\n\n if (force == null) {\n if (useEleOpacity && !r.eleTextBiggerThanMin(ele)) {\n return;\n }\n } else if (force === false) {\n return;\n }\n\n if (ele.isNode()) {\n var label = ele.pstyle('label');\n\n if (!label || !label.value) {\n return;\n }\n\n var justification = r.getLabelJustification(ele);\n context.textAlign = justification;\n context.textBaseline = 'bottom';\n } else {\n var badLine = ele.element()._private.rscratch.badLine;\n\n var _label = ele.pstyle('label');\n\n var srcLabel = ele.pstyle('source-label');\n var tgtLabel = ele.pstyle('target-label');\n\n if (badLine || (!_label || !_label.value) && (!srcLabel || !srcLabel.value) && (!tgtLabel || !tgtLabel.value)) {\n return;\n }\n\n context.textAlign = 'center';\n context.textBaseline = 'bottom';\n }\n\n var applyRotation = !shiftToOriginWithBb;\n var bb;\n\n if (shiftToOriginWithBb) {\n bb = shiftToOriginWithBb;\n context.translate(-bb.x1, -bb.y1);\n }\n\n if (prefix == null) {\n r.drawText(context, ele, null, applyRotation, useEleOpacity);\n\n if (ele.isEdge()) {\n r.drawText(context, ele, 'source', applyRotation, useEleOpacity);\n r.drawText(context, ele, 'target', applyRotation, useEleOpacity);\n }\n } else {\n r.drawText(context, ele, prefix, applyRotation, useEleOpacity);\n }\n\n if (shiftToOriginWithBb) {\n context.translate(bb.x1, bb.y1);\n }\n};\n\nCRp$4.getFontCache = function (context) {\n var cache;\n this.fontCaches = this.fontCaches || [];\n\n for (var i = 0; i < this.fontCaches.length; i++) {\n cache = this.fontCaches[i];\n\n if (cache.context === context) {\n return cache;\n }\n }\n\n cache = {\n context: context\n };\n this.fontCaches.push(cache);\n return cache;\n}; // set up canvas context with font\n// returns transformed text string\n\n\nCRp$4.setupTextStyle = function (context, ele) {\n var useEleOpacity = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n // Font style\n var labelStyle = ele.pstyle('font-style').strValue;\n var labelSize = ele.pstyle('font-size').pfValue + 'px';\n var labelFamily = ele.pstyle('font-family').strValue;\n var labelWeight = ele.pstyle('font-weight').strValue;\n var opacity = useEleOpacity ? ele.effectiveOpacity() * ele.pstyle('text-opacity').value : 1;\n var outlineOpacity = ele.pstyle('text-outline-opacity').value * opacity;\n var color = ele.pstyle('color').value;\n var outlineColor = ele.pstyle('text-outline-color').value;\n context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily;\n context.lineJoin = 'round'; // so text outlines aren't jagged\n\n this.colorFillStyle(context, color[0], color[1], color[2], opacity);\n this.colorStrokeStyle(context, outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity);\n}; // TODO ensure re-used\n\n\nfunction roundRect(ctx, x, y, width, height) {\n var radius = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 5;\n ctx.beginPath();\n ctx.moveTo(x + radius, y);\n ctx.lineTo(x + width - radius, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n ctx.lineTo(x + width, y + height - radius);\n ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n ctx.lineTo(x + radius, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n ctx.lineTo(x, y + radius);\n ctx.quadraticCurveTo(x, y, x + radius, y);\n ctx.closePath();\n ctx.fill();\n}\n\nCRp$4.getTextAngle = function (ele, prefix) {\n var theta;\n var _p = ele._private;\n var rscratch = _p.rscratch;\n var pdash = prefix ? prefix + '-' : '';\n var rotation = ele.pstyle(pdash + 'text-rotation');\n var textAngle = getPrefixedProperty(rscratch, 'labelAngle', prefix);\n\n if (rotation.strValue === 'autorotate') {\n theta = ele.isEdge() ? textAngle : 0;\n } else if (rotation.strValue === 'none') {\n theta = 0;\n } else {\n theta = rotation.pfValue;\n }\n\n return theta;\n};\n\nCRp$4.drawText = function (context, ele, prefix) {\n var applyRotation = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n var useEleOpacity = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;\n var _p = ele._private;\n var rscratch = _p.rscratch;\n var parentOpacity = useEleOpacity ? ele.effectiveOpacity() : 1;\n\n if (useEleOpacity && (parentOpacity === 0 || ele.pstyle('text-opacity').value === 0)) {\n return;\n } // use 'main' as an alias for the main label (i.e. null prefix)\n\n\n if (prefix === 'main') {\n prefix = null;\n }\n\n var textX = getPrefixedProperty(rscratch, 'labelX', prefix);\n var textY = getPrefixedProperty(rscratch, 'labelY', prefix);\n var orgTextX, orgTextY; // used for rotation\n\n var text = this.getLabelText(ele, prefix);\n\n if (text != null && text !== '' && !isNaN(textX) && !isNaN(textY)) {\n this.setupTextStyle(context, ele, useEleOpacity);\n var pdash = prefix ? prefix + '-' : '';\n var textW = getPrefixedProperty(rscratch, 'labelWidth', prefix);\n var textH = getPrefixedProperty(rscratch, 'labelHeight', prefix);\n var marginX = ele.pstyle(pdash + 'text-margin-x').pfValue;\n var marginY = ele.pstyle(pdash + 'text-margin-y').pfValue;\n var isEdge = ele.isEdge();\n var halign = ele.pstyle('text-halign').value;\n var valign = ele.pstyle('text-valign').value;\n\n if (isEdge) {\n halign = 'center';\n valign = 'center';\n }\n\n textX += marginX;\n textY += marginY;\n var theta;\n\n if (!applyRotation) {\n theta = 0;\n } else {\n theta = this.getTextAngle(ele, prefix);\n }\n\n if (theta !== 0) {\n orgTextX = textX;\n orgTextY = textY;\n context.translate(orgTextX, orgTextY);\n context.rotate(theta);\n textX = 0;\n textY = 0;\n }\n\n switch (valign) {\n case 'top':\n break;\n\n case 'center':\n textY += textH / 2;\n break;\n\n case 'bottom':\n textY += textH;\n break;\n }\n\n var backgroundOpacity = ele.pstyle('text-background-opacity').value;\n var borderOpacity = ele.pstyle('text-border-opacity').value;\n var textBorderWidth = ele.pstyle('text-border-width').pfValue;\n var backgroundPadding = ele.pstyle('text-background-padding').pfValue;\n\n if (backgroundOpacity > 0 || textBorderWidth > 0 && borderOpacity > 0) {\n var bgX = textX - backgroundPadding;\n\n switch (halign) {\n case 'left':\n bgX -= textW;\n break;\n\n case 'center':\n bgX -= textW / 2;\n break;\n }\n\n var bgY = textY - textH - backgroundPadding;\n var bgW = textW + 2 * backgroundPadding;\n var bgH = textH + 2 * backgroundPadding;\n\n if (backgroundOpacity > 0) {\n var textFill = context.fillStyle;\n var textBackgroundColor = ele.pstyle('text-background-color').value;\n context.fillStyle = 'rgba(' + textBackgroundColor[0] + ',' + textBackgroundColor[1] + ',' + textBackgroundColor[2] + ',' + backgroundOpacity * parentOpacity + ')';\n var styleShape = ele.pstyle('text-background-shape').strValue;\n\n if (styleShape.indexOf('round') === 0) {\n roundRect(context, bgX, bgY, bgW, bgH, 2);\n } else {\n context.fillRect(bgX, bgY, bgW, bgH);\n }\n\n context.fillStyle = textFill;\n }\n\n if (textBorderWidth > 0 && borderOpacity > 0) {\n var textStroke = context.strokeStyle;\n var textLineWidth = context.lineWidth;\n var textBorderColor = ele.pstyle('text-border-color').value;\n var textBorderStyle = ele.pstyle('text-border-style').value;\n context.strokeStyle = 'rgba(' + textBorderColor[0] + ',' + textBorderColor[1] + ',' + textBorderColor[2] + ',' + borderOpacity * parentOpacity + ')';\n context.lineWidth = textBorderWidth;\n\n if (context.setLineDash) {\n // for very outofdate browsers\n switch (textBorderStyle) {\n case 'dotted':\n context.setLineDash([1, 1]);\n break;\n\n case 'dashed':\n context.setLineDash([4, 2]);\n break;\n\n case 'double':\n context.lineWidth = textBorderWidth / 4; // 50% reserved for white between the two borders\n\n context.setLineDash([]);\n break;\n\n case 'solid':\n context.setLineDash([]);\n break;\n }\n }\n\n context.strokeRect(bgX, bgY, bgW, bgH);\n\n if (textBorderStyle === 'double') {\n var whiteWidth = textBorderWidth / 2;\n context.strokeRect(bgX + whiteWidth, bgY + whiteWidth, bgW - whiteWidth * 2, bgH - whiteWidth * 2);\n }\n\n if (context.setLineDash) {\n // for very outofdate browsers\n context.setLineDash([]);\n }\n\n context.lineWidth = textLineWidth;\n context.strokeStyle = textStroke;\n }\n }\n\n var lineWidth = 2 * ele.pstyle('text-outline-width').pfValue; // *2 b/c the stroke is drawn centred on the middle\n\n if (lineWidth > 0) {\n context.lineWidth = lineWidth;\n }\n\n if (ele.pstyle('text-wrap').value === 'wrap') {\n var lines = getPrefixedProperty(rscratch, 'labelWrapCachedLines', prefix);\n var lineHeight = getPrefixedProperty(rscratch, 'labelLineHeight', prefix);\n var halfTextW = textW / 2;\n var justification = this.getLabelJustification(ele);\n\n if (justification === 'auto') ; else if (halign === 'left') {\n // auto justification : right\n if (justification === 'left') {\n textX += -textW;\n } else if (justification === 'center') {\n textX += -halfTextW;\n } // else same as auto\n\n } else if (halign === 'center') {\n // auto justfication : center\n if (justification === 'left') {\n textX += -halfTextW;\n } else if (justification === 'right') {\n textX += halfTextW;\n } // else same as auto\n\n } else if (halign === 'right') {\n // auto justification : left\n if (justification === 'center') {\n textX += halfTextW;\n } else if (justification === 'right') {\n textX += textW;\n } // else same as auto\n\n }\n\n switch (valign) {\n case 'top':\n textY -= (lines.length - 1) * lineHeight;\n break;\n\n case 'center':\n case 'bottom':\n textY -= (lines.length - 1) * lineHeight;\n break;\n }\n\n for (var l = 0; l < lines.length; l++) {\n if (lineWidth > 0) {\n context.strokeText(lines[l], textX, textY);\n }\n\n context.fillText(lines[l], textX, textY);\n textY += lineHeight;\n }\n } else {\n if (lineWidth > 0) {\n context.strokeText(text, textX, textY);\n }\n\n context.fillText(text, textX, textY);\n }\n\n if (theta !== 0) {\n context.rotate(-theta);\n context.translate(-orgTextX, -orgTextY);\n }\n }\n};\n\n/* global Path2D */\nvar CRp$5 = {};\n\nCRp$5.drawNode = function (context, node, shiftToOriginWithBb) {\n var drawLabel = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n var shouldDrawOverlay = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;\n var shouldDrawOpacity = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;\n var r = this;\n var nodeWidth, nodeHeight;\n var _p = node._private;\n var rs = _p.rscratch;\n var pos = node.position();\n\n if (!number(pos.x) || !number(pos.y)) {\n return; // can't draw node with undefined position\n }\n\n if (shouldDrawOpacity && !node.visible()) {\n return;\n }\n\n var eleOpacity = shouldDrawOpacity ? node.effectiveOpacity() : 1;\n var usePaths = r.usePaths();\n var path;\n var pathCacheHit = false;\n var padding = node.padding();\n nodeWidth = node.width() + 2 * padding;\n nodeHeight = node.height() + 2 * padding; //\n // setup shift\n\n var bb;\n\n if (shiftToOriginWithBb) {\n bb = shiftToOriginWithBb;\n context.translate(-bb.x1, -bb.y1);\n } //\n // load bg image\n\n\n var bgImgProp = node.pstyle('background-image');\n var urls = bgImgProp.value;\n var urlDefined = new Array(urls.length);\n var image = new Array(urls.length);\n var numImages = 0;\n\n for (var i = 0; i < urls.length; i++) {\n var url = urls[i];\n var defd = urlDefined[i] = url != null && url !== 'none';\n\n if (defd) {\n var bgImgCrossOrigin = node.cy().style().getIndexedStyle(node, 'background-image-crossorigin', 'value', i);\n numImages++; // get image, and if not loaded then ask to redraw when later loaded\n\n image[i] = r.getCachedImage(url, bgImgCrossOrigin, function () {\n _p.backgroundTimestamp = Date.now();\n node.emitAndNotify('background');\n });\n }\n } //\n // setup styles\n\n\n var darkness = node.pstyle('background-blacken').value;\n var borderWidth = node.pstyle('border-width').pfValue;\n var bgOpacity = node.pstyle('background-opacity').value * eleOpacity;\n var borderColor = node.pstyle('border-color').value;\n var borderStyle = node.pstyle('border-style').value;\n var borderOpacity = node.pstyle('border-opacity').value * eleOpacity;\n context.lineJoin = 'miter'; // so borders are square with the node shape\n\n var setupShapeColor = function setupShapeColor() {\n var bgOpy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : bgOpacity;\n r.eleFillStyle(context, node, bgOpy);\n };\n\n var setupBorderColor = function setupBorderColor() {\n var bdrOpy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : borderOpacity;\n r.colorStrokeStyle(context, borderColor[0], borderColor[1], borderColor[2], bdrOpy);\n }; //\n // setup shape\n\n\n var styleShape = node.pstyle('shape').strValue;\n var shapePts = node.pstyle('shape-polygon-points').pfValue;\n\n if (usePaths) {\n context.translate(pos.x, pos.y);\n var pathCache = r.nodePathCache = r.nodePathCache || [];\n var key = hashStrings(styleShape === 'polygon' ? styleShape + ',' + shapePts.join(',') : styleShape, '' + nodeHeight, '' + nodeWidth);\n var cachedPath = pathCache[key];\n\n if (cachedPath != null) {\n path = cachedPath;\n pathCacheHit = true;\n rs.pathCache = path;\n } else {\n path = new Path2D();\n pathCache[key] = rs.pathCache = path;\n }\n }\n\n var drawShape = function drawShape() {\n if (!pathCacheHit) {\n var npos = pos;\n\n if (usePaths) {\n npos = {\n x: 0,\n y: 0\n };\n }\n\n r.nodeShapes[r.getNodeShape(node)].draw(path || context, npos.x, npos.y, nodeWidth, nodeHeight);\n }\n\n if (usePaths) {\n context.fill(path);\n } else {\n context.fill();\n }\n };\n\n var drawImages = function drawImages() {\n var nodeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : eleOpacity;\n var prevBging = _p.backgrounding;\n var totalCompleted = 0;\n\n for (var _i = 0; _i < image.length; _i++) {\n if (urlDefined[_i] && image[_i].complete && !image[_i].error) {\n totalCompleted++;\n r.drawInscribedImage(context, image[_i], node, _i, nodeOpacity);\n }\n }\n\n _p.backgrounding = !(totalCompleted === numImages);\n\n if (prevBging !== _p.backgrounding) {\n // update style b/c :backgrounding state changed\n node.updateStyle(false);\n }\n };\n\n var drawPie = function drawPie() {\n var redrawShape = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n var pieOpacity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : eleOpacity;\n\n if (r.hasPie(node)) {\n r.drawPie(context, node, pieOpacity); // redraw/restore path if steps after pie need it\n\n if (redrawShape) {\n if (!usePaths) {\n r.nodeShapes[r.getNodeShape(node)].draw(context, pos.x, pos.y, nodeWidth, nodeHeight);\n }\n }\n }\n };\n\n var darken = function darken() {\n var darkenOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : eleOpacity;\n var opacity = (darkness > 0 ? darkness : -darkness) * darkenOpacity;\n var c = darkness > 0 ? 0 : 255;\n\n if (darkness !== 0) {\n r.colorFillStyle(context, c, c, c, opacity);\n\n if (usePaths) {\n context.fill(path);\n } else {\n context.fill();\n }\n }\n };\n\n var drawBorder = function drawBorder() {\n if (borderWidth > 0) {\n context.lineWidth = borderWidth;\n context.lineCap = 'butt';\n\n if (context.setLineDash) {\n // for very outofdate browsers\n switch (borderStyle) {\n case 'dotted':\n context.setLineDash([1, 1]);\n break;\n\n case 'dashed':\n context.setLineDash([4, 2]);\n break;\n\n case 'solid':\n case 'double':\n context.setLineDash([]);\n break;\n }\n }\n\n if (usePaths) {\n context.stroke(path);\n } else {\n context.stroke();\n }\n\n if (borderStyle === 'double') {\n context.lineWidth = borderWidth / 3;\n var gco = context.globalCompositeOperation;\n context.globalCompositeOperation = 'destination-out';\n\n if (usePaths) {\n context.stroke(path);\n } else {\n context.stroke();\n }\n\n context.globalCompositeOperation = gco;\n } // reset in case we changed the border style\n\n\n if (context.setLineDash) {\n // for very outofdate browsers\n context.setLineDash([]);\n }\n }\n };\n\n var drawOverlay = function drawOverlay() {\n if (shouldDrawOverlay) {\n r.drawNodeOverlay(context, node, pos, nodeWidth, nodeHeight);\n }\n };\n\n var drawText = function drawText() {\n r.drawElementText(context, node, null, drawLabel);\n };\n\n var ghost = node.pstyle('ghost').value === 'yes';\n\n if (ghost) {\n var gx = node.pstyle('ghost-offset-x').pfValue;\n var gy = node.pstyle('ghost-offset-y').pfValue;\n var ghostOpacity = node.pstyle('ghost-opacity').value;\n var effGhostOpacity = ghostOpacity * eleOpacity;\n context.translate(gx, gy);\n setupShapeColor(ghostOpacity * bgOpacity);\n drawShape();\n drawImages(effGhostOpacity);\n drawPie(darkness !== 0 || borderWidth !== 0);\n darken(effGhostOpacity);\n setupBorderColor(ghostOpacity * borderOpacity);\n drawBorder();\n context.translate(-gx, -gy);\n }\n\n setupShapeColor();\n drawShape();\n drawImages();\n drawPie(darkness !== 0 || borderWidth !== 0);\n darken();\n setupBorderColor();\n drawBorder();\n\n if (usePaths) {\n context.translate(-pos.x, -pos.y);\n }\n\n drawText();\n drawOverlay(); //\n // clean up shift\n\n if (shiftToOriginWithBb) {\n context.translate(bb.x1, bb.y1);\n }\n};\n\nCRp$5.drawNodeOverlay = function (context, node, pos, nodeWidth, nodeHeight) {\n var r = this;\n\n if (!node.visible()) {\n return;\n }\n\n var overlayPadding = node.pstyle('overlay-padding').pfValue;\n var overlayOpacity = node.pstyle('overlay-opacity').value;\n var overlayColor = node.pstyle('overlay-color').value;\n\n if (overlayOpacity > 0) {\n pos = pos || node.position();\n\n if (nodeWidth == null || nodeHeight == null) {\n var padding = node.padding();\n nodeWidth = node.width() + 2 * padding;\n nodeHeight = node.height() + 2 * padding;\n }\n\n r.colorFillStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n r.nodeShapes['roundrectangle'].draw(context, pos.x, pos.y, nodeWidth + overlayPadding * 2, nodeHeight + overlayPadding * 2);\n context.fill();\n }\n}; // does the node have at least one pie piece?\n\n\nCRp$5.hasPie = function (node) {\n node = node[0]; // ensure ele ref\n\n return node._private.hasPie;\n};\n\nCRp$5.drawPie = function (context, node, nodeOpacity, pos) {\n node = node[0]; // ensure ele ref\n\n pos = pos || node.position();\n var cyStyle = node.cy().style();\n var pieSize = node.pstyle('pie-size');\n var x = pos.x;\n var y = pos.y;\n var nodeW = node.width();\n var nodeH = node.height();\n var radius = Math.min(nodeW, nodeH) / 2; // must fit in node\n\n var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]\n\n var usePaths = this.usePaths();\n\n if (usePaths) {\n x = 0;\n y = 0;\n }\n\n if (pieSize.units === '%') {\n radius = radius * pieSize.pfValue;\n } else if (pieSize.pfValue !== undefined) {\n radius = pieSize.pfValue / 2;\n }\n\n for (var i = 1; i <= cyStyle.pieBackgroundN; i++) {\n // 1..N\n var size = node.pstyle('pie-' + i + '-background-size').value;\n var color = node.pstyle('pie-' + i + '-background-color').value;\n var opacity = node.pstyle('pie-' + i + '-background-opacity').value * nodeOpacity;\n var percent = size / 100; // map integer range [0, 100] to [0, 1]\n // percent can't push beyond 1\n\n if (percent + lastPercent > 1) {\n percent = 1 - lastPercent;\n }\n\n var angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise\n\n var angleDelta = 2 * Math.PI * percent;\n var angleEnd = angleStart + angleDelta; // ignore if\n // - zero size\n // - we're already beyond the full circle\n // - adding the current slice would go beyond the full circle\n\n if (size === 0 || lastPercent >= 1 || lastPercent + percent > 1) {\n continue;\n }\n\n context.beginPath();\n context.moveTo(x, y);\n context.arc(x, y, radius, angleStart, angleEnd);\n context.closePath();\n this.colorFillStyle(context, color[0], color[1], color[2], opacity);\n context.fill();\n lastPercent += percent;\n }\n};\n\nvar CRp$6 = {};\nvar motionBlurDelay = 100; // var isFirefox = typeof InstallTrigger !== 'undefined';\n\nCRp$6.getPixelRatio = function () {\n var context = this.data.contexts[0];\n\n if (this.forcedPixelRatio != null) {\n return this.forcedPixelRatio;\n }\n\n var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1;\n return (window.devicePixelRatio || 1) / backingStore; // eslint-disable-line no-undef\n};\n\nCRp$6.paintCache = function (context) {\n var caches = this.paintCaches = this.paintCaches || [];\n var needToCreateCache = true;\n var cache;\n\n for (var i = 0; i < caches.length; i++) {\n cache = caches[i];\n\n if (cache.context === context) {\n needToCreateCache = false;\n break;\n }\n }\n\n if (needToCreateCache) {\n cache = {\n context: context\n };\n caches.push(cache);\n }\n\n return cache;\n};\n\nCRp$6.createGradientStyleFor = function (context, shapeStyleName, ele, fill, opacity) {\n var gradientStyle;\n var usePaths = this.usePaths();\n var colors = ele.pstyle(shapeStyleName + '-gradient-stop-colors').value,\n positions = ele.pstyle(shapeStyleName + '-gradient-stop-positions').pfValue;\n\n if (fill === 'radial-gradient') {\n if (ele.isEdge()) {\n var start = ele.sourceEndpoint(),\n end = ele.targetEndpoint(),\n mid = ele.midpoint();\n var d1 = dist(start, mid);\n var d2 = dist(end, mid);\n gradientStyle = context.createRadialGradient(mid.x, mid.y, 0, mid.x, mid.y, Math.max(d1, d2));\n } else {\n var pos = usePaths ? {\n x: 0,\n y: 0\n } : ele.position(),\n width = ele.paddedWidth(),\n height = ele.paddedHeight();\n gradientStyle = context.createRadialGradient(pos.x, pos.y, 0, pos.x, pos.y, Math.max(width, height));\n }\n } else {\n if (ele.isEdge()) {\n var _start = ele.sourceEndpoint(),\n _end = ele.targetEndpoint();\n\n gradientStyle = context.createLinearGradient(_start.x, _start.y, _end.x, _end.y);\n } else {\n var _pos = usePaths ? {\n x: 0,\n y: 0\n } : ele.position(),\n _width = ele.paddedWidth(),\n _height = ele.paddedHeight(),\n halfWidth = _width / 2,\n halfHeight = _height / 2;\n\n var direction = ele.pstyle('background-gradient-direction').value;\n\n switch (direction) {\n case 'to-bottom':\n gradientStyle = context.createLinearGradient(_pos.x, _pos.y - halfHeight, _pos.x, _pos.y + halfHeight);\n break;\n\n case 'to-top':\n gradientStyle = context.createLinearGradient(_pos.x, _pos.y + halfHeight, _pos.x, _pos.y - halfHeight);\n break;\n\n case 'to-left':\n gradientStyle = context.createLinearGradient(_pos.x + halfWidth, _pos.y, _pos.x - halfWidth, _pos.y);\n break;\n\n case 'to-right':\n gradientStyle = context.createLinearGradient(_pos.x - halfWidth, _pos.y, _pos.x + halfWidth, _pos.y);\n break;\n\n case 'to-bottom-right':\n case 'to-right-bottom':\n gradientStyle = context.createLinearGradient(_pos.x - halfWidth, _pos.y - halfHeight, _pos.x + halfWidth, _pos.y + halfHeight);\n break;\n\n case 'to-top-right':\n case 'to-right-top':\n gradientStyle = context.createLinearGradient(_pos.x - halfWidth, _pos.y + halfHeight, _pos.x + halfWidth, _pos.y - halfHeight);\n break;\n\n case 'to-bottom-left':\n case 'to-left-bottom':\n gradientStyle = context.createLinearGradient(_pos.x + halfWidth, _pos.y - halfHeight, _pos.x - halfWidth, _pos.y + halfHeight);\n break;\n\n case 'to-top-left':\n case 'to-left-top':\n gradientStyle = context.createLinearGradient(_pos.x + halfWidth, _pos.y + halfHeight, _pos.x - halfWidth, _pos.y - halfHeight);\n break;\n }\n }\n }\n\n if (!gradientStyle) return null; // invalid gradient style\n\n var hasPositions = positions.length === colors.length;\n var length = colors.length;\n\n for (var i = 0; i < length; i++) {\n gradientStyle.addColorStop(hasPositions ? positions[i] : i / (length - 1), 'rgba(' + colors[i][0] + ',' + colors[i][1] + ',' + colors[i][2] + ',' + opacity + ')');\n }\n\n return gradientStyle;\n};\n\nCRp$6.gradientFillStyle = function (context, ele, fill, opacity) {\n var gradientStyle = this.createGradientStyleFor(context, 'background', ele, fill, opacity);\n if (!gradientStyle) return null; // error\n\n context.fillStyle = gradientStyle;\n};\n\nCRp$6.colorFillStyle = function (context, r, g, b, a) {\n context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; // turn off for now, seems context does its own caching\n // var cache = this.paintCache(context);\n // var fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n // if( cache.fillStyle !== fillStyle ){\n // context.fillStyle = cache.fillStyle = fillStyle;\n // }\n};\n\nCRp$6.eleFillStyle = function (context, ele, opacity) {\n var backgroundFill = ele.pstyle('background-fill').value;\n\n if (backgroundFill === 'linear-gradient' || backgroundFill === 'radial-gradient') {\n this.gradientFillStyle(context, ele, backgroundFill, opacity);\n } else {\n var backgroundColor = ele.pstyle('background-color').value;\n this.colorFillStyle(context, backgroundColor[0], backgroundColor[1], backgroundColor[2], opacity);\n }\n};\n\nCRp$6.gradientStrokeStyle = function (context, ele, fill, opacity) {\n var gradientStyle = this.createGradientStyleFor(context, 'line', ele, fill, opacity);\n if (!gradientStyle) return null; // error\n\n context.strokeStyle = gradientStyle;\n};\n\nCRp$6.colorStrokeStyle = function (context, r, g, b, a) {\n context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; // turn off for now, seems context does its own caching\n // var cache = this.paintCache(context);\n // var strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n // if( cache.strokeStyle !== strokeStyle ){\n // context.strokeStyle = cache.strokeStyle = strokeStyle;\n // }\n};\n\nCRp$6.eleStrokeStyle = function (context, ele, opacity) {\n var lineFill = ele.pstyle('line-fill').value;\n\n if (lineFill === 'linear-gradient' || lineFill === 'radial-gradient') {\n this.gradientStrokeStyle(context, ele, lineFill, opacity);\n } else {\n var lineColor = ele.pstyle('line-color').value;\n this.colorStrokeStyle(context, lineColor[0], lineColor[1], lineColor[2], opacity);\n }\n}; // Resize canvas\n\n\nCRp$6.matchCanvasSize = function (container) {\n var r = this;\n var data = r.data;\n var bb = r.findContainerClientCoords();\n var width = bb[2];\n var height = bb[3];\n var pixelRatio = r.getPixelRatio();\n var mbPxRatio = r.motionBlurPxRatio;\n\n if (container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE] || container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]) {\n pixelRatio = mbPxRatio;\n }\n\n var canvasWidth = width * pixelRatio;\n var canvasHeight = height * pixelRatio;\n var canvas;\n\n if (canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight) {\n return; // save cycles if same\n }\n\n r.fontCaches = null; // resizing resets the style\n\n var canvasContainer = data.canvasContainer;\n canvasContainer.style.width = width + 'px';\n canvasContainer.style.height = height + 'px';\n\n for (var i = 0; i < r.CANVAS_LAYERS; i++) {\n canvas = data.canvases[i];\n canvas.width = canvasWidth;\n canvas.height = canvasHeight;\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n }\n\n for (var i = 0; i < r.BUFFER_COUNT; i++) {\n canvas = data.bufferCanvases[i];\n canvas.width = canvasWidth;\n canvas.height = canvasHeight;\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n }\n\n r.textureMult = 1;\n\n if (pixelRatio <= 1) {\n canvas = data.bufferCanvases[r.TEXTURE_BUFFER];\n r.textureMult = 2;\n canvas.width = canvasWidth * r.textureMult;\n canvas.height = canvasHeight * r.textureMult;\n }\n\n r.canvasWidth = canvasWidth;\n r.canvasHeight = canvasHeight;\n};\n\nCRp$6.renderTo = function (cxt, zoom, pan, pxRatio) {\n this.render({\n forcedContext: cxt,\n forcedZoom: zoom,\n forcedPan: pan,\n drawAllLayers: true,\n forcedPxRatio: pxRatio\n });\n};\n\nCRp$6.render = function (options) {\n options = options || staticEmptyObject();\n var forcedContext = options.forcedContext;\n var drawAllLayers = options.drawAllLayers;\n var drawOnlyNodeLayer = options.drawOnlyNodeLayer;\n var forcedZoom = options.forcedZoom;\n var forcedPan = options.forcedPan;\n var r = this;\n var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio;\n var cy = r.cy;\n var data = r.data;\n var needDraw = data.canvasNeedsRedraw;\n var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming);\n var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur;\n var mbPxRatio = r.motionBlurPxRatio;\n var hasCompoundNodes = cy.hasCompoundNodes();\n var inNodeDragGesture = r.hoverData.draggingEles;\n var inBoxSelection = r.hoverData.selecting || r.touchData.selecting ? true : false;\n motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection;\n var motionBlurFadeEffect = motionBlur;\n\n if (!forcedContext) {\n if (r.prevPxRatio !== pixelRatio) {\n r.invalidateContainerClientCoordsCache();\n r.matchCanvasSize(r.container);\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n }\n\n r.prevPxRatio = pixelRatio;\n }\n\n if (!forcedContext && r.motionBlurTimeout) {\n clearTimeout(r.motionBlurTimeout);\n }\n\n if (motionBlur) {\n if (r.mbFrames == null) {\n r.mbFrames = 0;\n }\n\n r.mbFrames++;\n\n if (r.mbFrames < 3) {\n // need several frames before even high quality motionblur\n motionBlurFadeEffect = false;\n } // go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing)\n\n\n if (r.mbFrames > r.minMbLowQualFrames) {\n //r.fullQualityMb = false;\n r.motionBlurPxRatio = r.mbPxRBlurry;\n }\n }\n\n if (r.clearingMotionBlur) {\n r.motionBlurPxRatio = 1;\n } // b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame\n // because a rogue async texture frame would clear needDraw\n\n\n if (r.textureDrawLastFrame && !textureDraw) {\n needDraw[r.NODE] = true;\n needDraw[r.SELECT_BOX] = true;\n }\n\n var style = cy.style();\n var zoom = cy.zoom();\n var effectiveZoom = forcedZoom !== undefined ? forcedZoom : zoom;\n var pan = cy.pan();\n var effectivePan = {\n x: pan.x,\n y: pan.y\n };\n var vp = {\n zoom: zoom,\n pan: {\n x: pan.x,\n y: pan.y\n }\n };\n var prevVp = r.prevViewport;\n var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y; // we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed)\n\n if (!viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes)) {\n r.motionBlurPxRatio = 1;\n }\n\n if (forcedPan) {\n effectivePan = forcedPan;\n } // apply pixel ratio\n\n\n effectiveZoom *= pixelRatio;\n effectivePan.x *= pixelRatio;\n effectivePan.y *= pixelRatio;\n var eles = r.getCachedZSortedEles();\n\n function mbclear(context, x, y, w, h) {\n var gco = context.globalCompositeOperation;\n context.globalCompositeOperation = 'destination-out';\n r.colorFillStyle(context, 255, 255, 255, r.motionBlurTransparency);\n context.fillRect(x, y, w, h);\n context.globalCompositeOperation = gco;\n }\n\n function setContextTransform(context, clear) {\n var ePan, eZoom, w, h;\n\n if (!r.clearingMotionBlur && (context === data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] || context === data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG])) {\n ePan = {\n x: pan.x * mbPxRatio,\n y: pan.y * mbPxRatio\n };\n eZoom = zoom * mbPxRatio;\n w = r.canvasWidth * mbPxRatio;\n h = r.canvasHeight * mbPxRatio;\n } else {\n ePan = effectivePan;\n eZoom = effectiveZoom;\n w = r.canvasWidth;\n h = r.canvasHeight;\n }\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n if (clear === 'motionBlur') {\n mbclear(context, 0, 0, w, h);\n } else if (!forcedContext && (clear === undefined || clear)) {\n context.clearRect(0, 0, w, h);\n }\n\n if (!drawAllLayers) {\n context.translate(ePan.x, ePan.y);\n context.scale(eZoom, eZoom);\n }\n\n if (forcedPan) {\n context.translate(forcedPan.x, forcedPan.y);\n }\n\n if (forcedZoom) {\n context.scale(forcedZoom, forcedZoom);\n }\n }\n\n if (!textureDraw) {\n r.textureDrawLastFrame = false;\n }\n\n if (textureDraw) {\n r.textureDrawLastFrame = true;\n\n if (!r.textureCache) {\n r.textureCache = {};\n r.textureCache.bb = cy.mutableElements().boundingBox();\n r.textureCache.texture = r.data.bufferCanvases[r.TEXTURE_BUFFER];\n var cxt = r.data.bufferContexts[r.TEXTURE_BUFFER];\n cxt.setTransform(1, 0, 0, 1, 0, 0);\n cxt.clearRect(0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult);\n r.render({\n forcedContext: cxt,\n drawOnlyNodeLayer: true,\n forcedPxRatio: pixelRatio * r.textureMult\n });\n var vp = r.textureCache.viewport = {\n zoom: cy.zoom(),\n pan: cy.pan(),\n width: r.canvasWidth,\n height: r.canvasHeight\n };\n vp.mpan = {\n x: (0 - vp.pan.x) / vp.zoom,\n y: (0 - vp.pan.y) / vp.zoom\n };\n }\n\n needDraw[r.DRAG] = false;\n needDraw[r.NODE] = false;\n var context = data.contexts[r.NODE];\n var texture = r.textureCache.texture;\n var vp = r.textureCache.viewport;\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n if (motionBlur) {\n mbclear(context, 0, 0, vp.width, vp.height);\n } else {\n context.clearRect(0, 0, vp.width, vp.height);\n }\n\n var outsideBgColor = style.core('outside-texture-bg-color').value;\n var outsideBgOpacity = style.core('outside-texture-bg-opacity').value;\n r.colorFillStyle(context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity);\n context.fillRect(0, 0, vp.width, vp.height);\n var zoom = cy.zoom();\n setContextTransform(context, false);\n context.clearRect(vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio);\n context.drawImage(texture, vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio);\n } else if (r.textureOnViewport && !forcedContext) {\n // clear the cache since we don't need it\n r.textureCache = null;\n }\n\n var extent = cy.extent();\n var vpManip = r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles || r.cy.animated();\n var hideEdges = r.hideEdgesOnViewport && vpManip;\n var needMbClear = [];\n needMbClear[r.NODE] = !needDraw[r.NODE] && motionBlur && !r.clearedForMotionBlur[r.NODE] || r.clearingMotionBlur;\n\n if (needMbClear[r.NODE]) {\n r.clearedForMotionBlur[r.NODE] = true;\n }\n\n needMbClear[r.DRAG] = !needDraw[r.DRAG] && motionBlur && !r.clearedForMotionBlur[r.DRAG] || r.clearingMotionBlur;\n\n if (needMbClear[r.DRAG]) {\n r.clearedForMotionBlur[r.DRAG] = true;\n }\n\n if (needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer || needMbClear[r.NODE]) {\n var useBuffer = motionBlur && !needMbClear[r.NODE] && mbPxRatio !== 1;\n var context = forcedContext || (useBuffer ? r.data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] : data.contexts[r.NODE]);\n var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined;\n setContextTransform(context, clear);\n\n if (hideEdges) {\n r.drawCachedNodes(context, eles.nondrag, pixelRatio, extent);\n } else {\n r.drawLayeredElements(context, eles.nondrag, pixelRatio, extent);\n }\n\n if (r.debug) {\n r.drawDebugPoints(context, eles.nondrag);\n }\n\n if (!drawAllLayers && !motionBlur) {\n needDraw[r.NODE] = false;\n }\n }\n\n if (!drawOnlyNodeLayer && (needDraw[r.DRAG] || drawAllLayers || needMbClear[r.DRAG])) {\n var useBuffer = motionBlur && !needMbClear[r.DRAG] && mbPxRatio !== 1;\n var context = forcedContext || (useBuffer ? r.data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG] : data.contexts[r.DRAG]);\n setContextTransform(context, motionBlur && !useBuffer ? 'motionBlur' : undefined);\n\n if (hideEdges) {\n r.drawCachedNodes(context, eles.drag, pixelRatio, extent);\n } else {\n r.drawCachedElements(context, eles.drag, pixelRatio, extent);\n }\n\n if (r.debug) {\n r.drawDebugPoints(context, eles.drag);\n }\n\n if (!drawAllLayers && !motionBlur) {\n needDraw[r.DRAG] = false;\n }\n }\n\n if (r.showFps || !drawOnlyNodeLayer && needDraw[r.SELECT_BOX] && !drawAllLayers) {\n var context = forcedContext || data.contexts[r.SELECT_BOX];\n setContextTransform(context);\n\n if (r.selection[4] == 1 && (r.hoverData.selecting || r.touchData.selecting)) {\n var zoom = r.cy.zoom();\n var borderWidth = style.core('selection-box-border-width').value / zoom;\n context.lineWidth = borderWidth;\n context.fillStyle = 'rgba(' + style.core('selection-box-color').value[0] + ',' + style.core('selection-box-color').value[1] + ',' + style.core('selection-box-color').value[2] + ',' + style.core('selection-box-opacity').value + ')';\n context.fillRect(r.selection[0], r.selection[1], r.selection[2] - r.selection[0], r.selection[3] - r.selection[1]);\n\n if (borderWidth > 0) {\n context.strokeStyle = 'rgba(' + style.core('selection-box-border-color').value[0] + ',' + style.core('selection-box-border-color').value[1] + ',' + style.core('selection-box-border-color').value[2] + ',' + style.core('selection-box-opacity').value + ')';\n context.strokeRect(r.selection[0], r.selection[1], r.selection[2] - r.selection[0], r.selection[3] - r.selection[1]);\n }\n }\n\n if (data.bgActivePosistion && !r.hoverData.selecting) {\n var zoom = r.cy.zoom();\n var pos = data.bgActivePosistion;\n context.fillStyle = 'rgba(' + style.core('active-bg-color').value[0] + ',' + style.core('active-bg-color').value[1] + ',' + style.core('active-bg-color').value[2] + ',' + style.core('active-bg-opacity').value + ')';\n context.beginPath();\n context.arc(pos.x, pos.y, style.core('active-bg-size').pfValue / zoom, 0, 2 * Math.PI);\n context.fill();\n }\n\n var timeToRender = r.lastRedrawTime;\n\n if (r.showFps && timeToRender) {\n timeToRender = Math.round(timeToRender);\n var fps = Math.round(1000 / timeToRender);\n context.setTransform(1, 0, 0, 1, 0, 0);\n context.fillStyle = 'rgba(255, 0, 0, 0.75)';\n context.strokeStyle = 'rgba(255, 0, 0, 0.75)';\n context.lineWidth = 1;\n context.fillText('1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20);\n var maxFps = 60;\n context.strokeRect(0, 30, 250, 20);\n context.fillRect(0, 30, 250 * Math.min(fps / maxFps, 1), 20);\n }\n\n if (!drawAllLayers) {\n needDraw[r.SELECT_BOX] = false;\n }\n } // motionblur: blit rendered blurry frames\n\n\n if (motionBlur && mbPxRatio !== 1) {\n var cxtNode = data.contexts[r.NODE];\n var txtNode = r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE];\n var cxtDrag = data.contexts[r.DRAG];\n var txtDrag = r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG];\n\n var drawMotionBlur = function drawMotionBlur(cxt, txt, needClear) {\n cxt.setTransform(1, 0, 0, 1, 0, 0);\n\n if (needClear || !motionBlurFadeEffect) {\n cxt.clearRect(0, 0, r.canvasWidth, r.canvasHeight);\n } else {\n mbclear(cxt, 0, 0, r.canvasWidth, r.canvasHeight);\n }\n\n var pxr = mbPxRatio;\n cxt.drawImage(txt, // img\n 0, 0, // sx, sy\n r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh\n 0, 0, // x, y\n r.canvasWidth, r.canvasHeight // w, h\n );\n };\n\n if (needDraw[r.NODE] || needMbClear[r.NODE]) {\n drawMotionBlur(cxtNode, txtNode, needMbClear[r.NODE]);\n needDraw[r.NODE] = false;\n }\n\n if (needDraw[r.DRAG] || needMbClear[r.DRAG]) {\n drawMotionBlur(cxtDrag, txtDrag, needMbClear[r.DRAG]);\n needDraw[r.DRAG] = false;\n }\n }\n\n r.prevViewport = vp;\n\n if (r.clearingMotionBlur) {\n r.clearingMotionBlur = false;\n r.motionBlurCleared = true;\n r.motionBlur = true;\n }\n\n if (motionBlur) {\n r.motionBlurTimeout = setTimeout(function () {\n r.motionBlurTimeout = null;\n r.clearedForMotionBlur[r.NODE] = false;\n r.clearedForMotionBlur[r.DRAG] = false;\n r.motionBlur = false;\n r.clearingMotionBlur = !textureDraw;\n r.mbFrames = 0;\n needDraw[r.NODE] = true;\n needDraw[r.DRAG] = true;\n r.redraw();\n }, motionBlurDelay);\n }\n\n if (!forcedContext) {\n cy.emit('render');\n }\n};\n\nvar CRp$7 = {}; // @O Polygon drawing\n\nCRp$7.drawPolygonPath = function (context, x, y, width, height, points) {\n var halfW = width / 2;\n var halfH = height / 2;\n\n if (context.beginPath) {\n context.beginPath();\n }\n\n context.moveTo(x + halfW * points[0], y + halfH * points[1]);\n\n for (var i = 1; i < points.length / 2; i++) {\n context.lineTo(x + halfW * points[i * 2], y + halfH * points[i * 2 + 1]);\n }\n\n context.closePath();\n};\n\nCRp$7.drawRoundPolygonPath = function (context, x, y, width, height, points) {\n var halfW = width / 2;\n var halfH = height / 2;\n var cornerRadius = getRoundPolygonRadius(width, height);\n\n if (context.beginPath) {\n context.beginPath();\n }\n\n for (var _i = 0; _i < points.length / 4; _i++) {\n var sourceUv = void 0,\n destUv = void 0;\n\n if (_i === 0) {\n sourceUv = points.length - 2;\n } else {\n sourceUv = _i * 4 - 2;\n }\n\n destUv = _i * 4 + 2;\n var px = x + halfW * points[_i * 4];\n var py = y + halfH * points[_i * 4 + 1];\n var cosTheta = -points[sourceUv] * points[destUv] - points[sourceUv + 1] * points[destUv + 1];\n var offset = cornerRadius / Math.tan(Math.acos(cosTheta) / 2);\n var cp0x = px - offset * points[sourceUv];\n var cp0y = py - offset * points[sourceUv + 1];\n var cp1x = px + offset * points[destUv];\n var cp1y = py + offset * points[destUv + 1];\n\n if (_i === 0) {\n context.moveTo(cp0x, cp0y);\n } else {\n context.lineTo(cp0x, cp0y);\n }\n\n context.arcTo(px, py, cp1x, cp1y, cornerRadius);\n }\n\n context.closePath();\n}; // Round rectangle drawing\n\n\nCRp$7.drawRoundRectanglePath = function (context, x, y, width, height) {\n var halfWidth = width / 2;\n var halfHeight = height / 2;\n var cornerRadius = getRoundRectangleRadius(width, height);\n\n if (context.beginPath) {\n context.beginPath();\n } // Start at top middle\n\n\n context.moveTo(x, y - halfHeight); // Arc from middle top to right side\n\n context.arcTo(x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius); // Arc from right side to bottom\n\n context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius); // Arc from bottom to left side\n\n context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius); // Arc from left side to topBorder\n\n context.arcTo(x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius); // Join line\n\n context.lineTo(x, y - halfHeight);\n context.closePath();\n};\n\nCRp$7.drawBottomRoundRectanglePath = function (context, x, y, width, height) {\n var halfWidth = width / 2;\n var halfHeight = height / 2;\n var cornerRadius = getRoundRectangleRadius(width, height);\n\n if (context.beginPath) {\n context.beginPath();\n } // Start at top middle\n\n\n context.moveTo(x, y - halfHeight);\n context.lineTo(x + halfWidth, y - halfHeight);\n context.lineTo(x + halfWidth, y);\n context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius);\n context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius);\n context.lineTo(x - halfWidth, y - halfHeight);\n context.lineTo(x, y - halfHeight);\n context.closePath();\n};\n\nCRp$7.drawCutRectanglePath = function (context, x, y, width, height) {\n var halfWidth = width / 2;\n var halfHeight = height / 2;\n var cornerLength = getCutRectangleCornerLength();\n\n if (context.beginPath) {\n context.beginPath();\n }\n\n context.moveTo(x - halfWidth + cornerLength, y - halfHeight);\n context.lineTo(x + halfWidth - cornerLength, y - halfHeight);\n context.lineTo(x + halfWidth, y - halfHeight + cornerLength);\n context.lineTo(x + halfWidth, y + halfHeight - cornerLength);\n context.lineTo(x + halfWidth - cornerLength, y + halfHeight);\n context.lineTo(x - halfWidth + cornerLength, y + halfHeight);\n context.lineTo(x - halfWidth, y + halfHeight - cornerLength);\n context.lineTo(x - halfWidth, y - halfHeight + cornerLength);\n context.closePath();\n};\n\nCRp$7.drawBarrelPath = function (context, x, y, width, height) {\n var halfWidth = width / 2;\n var halfHeight = height / 2;\n var xBegin = x - halfWidth;\n var xEnd = x + halfWidth;\n var yBegin = y - halfHeight;\n var yEnd = y + halfHeight;\n var barrelCurveConstants = getBarrelCurveConstants(width, height);\n var wOffset = barrelCurveConstants.widthOffset;\n var hOffset = barrelCurveConstants.heightOffset;\n var ctrlPtXOffset = barrelCurveConstants.ctrlPtOffsetPct * wOffset;\n\n if (context.beginPath) {\n context.beginPath();\n }\n\n context.moveTo(xBegin, yBegin + hOffset);\n context.lineTo(xBegin, yEnd - hOffset);\n context.quadraticCurveTo(xBegin + ctrlPtXOffset, yEnd, xBegin + wOffset, yEnd);\n context.lineTo(xEnd - wOffset, yEnd);\n context.quadraticCurveTo(xEnd - ctrlPtXOffset, yEnd, xEnd, yEnd - hOffset);\n context.lineTo(xEnd, yBegin + hOffset);\n context.quadraticCurveTo(xEnd - ctrlPtXOffset, yBegin, xEnd - wOffset, yBegin);\n context.lineTo(xBegin + wOffset, yBegin);\n context.quadraticCurveTo(xBegin + ctrlPtXOffset, yBegin, xBegin, yBegin + hOffset);\n context.closePath();\n};\n\nvar sin0 = Math.sin(0);\nvar cos0 = Math.cos(0);\nvar sin = {};\nvar cos = {};\nvar ellipseStepSize = Math.PI / 40;\n\nfor (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize) {\n sin[i] = Math.sin(i);\n cos[i] = Math.cos(i);\n}\n\nCRp$7.drawEllipsePath = function (context, centerX, centerY, width, height) {\n if (context.beginPath) {\n context.beginPath();\n }\n\n if (context.ellipse) {\n context.ellipse(centerX, centerY, width / 2, height / 2, 0, 0, 2 * Math.PI);\n } else {\n var xPos, yPos;\n var rw = width / 2;\n var rh = height / 2;\n\n for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize) {\n xPos = centerX - rw * sin[i] * sin0 + rw * cos[i] * cos0;\n yPos = centerY + rh * cos[i] * sin0 + rh * sin[i] * cos0;\n\n if (i === 0) {\n context.moveTo(xPos, yPos);\n } else {\n context.lineTo(xPos, yPos);\n }\n }\n }\n\n context.closePath();\n};\n\n/* global atob, ArrayBuffer, Uint8Array, Blob */\nvar CRp$8 = {};\n\nCRp$8.createBuffer = function (w, h) {\n var buffer = document.createElement('canvas'); // eslint-disable-line no-undef\n\n buffer.width = w;\n buffer.height = h;\n return [buffer, buffer.getContext('2d')];\n};\n\nCRp$8.bufferCanvasImage = function (options) {\n var cy = this.cy;\n var eles = cy.mutableElements();\n var bb = eles.boundingBox();\n var ctrRect = this.findContainerClientCoords();\n var width = options.full ? Math.ceil(bb.w) : ctrRect[2];\n var height = options.full ? Math.ceil(bb.h) : ctrRect[3];\n var specdMaxDims = number(options.maxWidth) || number(options.maxHeight);\n var pxRatio = this.getPixelRatio();\n var scale = 1;\n\n if (options.scale !== undefined) {\n width *= options.scale;\n height *= options.scale;\n scale = options.scale;\n } else if (specdMaxDims) {\n var maxScaleW = Infinity;\n var maxScaleH = Infinity;\n\n if (number(options.maxWidth)) {\n maxScaleW = scale * options.maxWidth / width;\n }\n\n if (number(options.maxHeight)) {\n maxScaleH = scale * options.maxHeight / height;\n }\n\n scale = Math.min(maxScaleW, maxScaleH);\n width *= scale;\n height *= scale;\n }\n\n if (!specdMaxDims) {\n width *= pxRatio;\n height *= pxRatio;\n scale *= pxRatio;\n }\n\n var buffCanvas = document.createElement('canvas'); // eslint-disable-line no-undef\n\n buffCanvas.width = width;\n buffCanvas.height = height;\n buffCanvas.style.width = width + 'px';\n buffCanvas.style.height = height + 'px';\n var buffCxt = buffCanvas.getContext('2d'); // Rasterize the layers, but only if container has nonzero size\n\n if (width > 0 && height > 0) {\n buffCxt.clearRect(0, 0, width, height);\n buffCxt.globalCompositeOperation = 'source-over';\n var zsortedEles = this.getCachedZSortedEles();\n\n if (options.full) {\n // draw the full bounds of the graph\n buffCxt.translate(-bb.x1 * scale, -bb.y1 * scale);\n buffCxt.scale(scale, scale);\n this.drawElements(buffCxt, zsortedEles);\n buffCxt.scale(1 / scale, 1 / scale);\n buffCxt.translate(bb.x1 * scale, bb.y1 * scale);\n } else {\n // draw the current view\n var pan = cy.pan();\n var translation = {\n x: pan.x * scale,\n y: pan.y * scale\n };\n scale *= cy.zoom();\n buffCxt.translate(translation.x, translation.y);\n buffCxt.scale(scale, scale);\n this.drawElements(buffCxt, zsortedEles);\n buffCxt.scale(1 / scale, 1 / scale);\n buffCxt.translate(-translation.x, -translation.y);\n } // need to fill bg at end like this in order to fill cleared transparent pixels in jpgs\n\n\n if (options.bg) {\n buffCxt.globalCompositeOperation = 'destination-over';\n buffCxt.fillStyle = options.bg;\n buffCxt.rect(0, 0, width, height);\n buffCxt.fill();\n }\n }\n\n return buffCanvas;\n};\n\nfunction b64ToBlob(b64, mimeType) {\n var bytes = atob(b64);\n var buff = new ArrayBuffer(bytes.length);\n var buffUint8 = new Uint8Array(buff);\n\n for (var i = 0; i < bytes.length; i++) {\n buffUint8[i] = bytes.charCodeAt(i);\n }\n\n return new Blob([buff], {\n type: mimeType\n });\n}\n\nfunction b64UriToB64(b64uri) {\n var i = b64uri.indexOf(',');\n return b64uri.substr(i + 1);\n}\n\nfunction output(options, canvas, mimeType) {\n var getB64Uri = function getB64Uri() {\n return canvas.toDataURL(mimeType, options.quality);\n };\n\n switch (options.output) {\n case 'blob-promise':\n return new Promise$1(function (resolve, reject) {\n try {\n canvas.toBlob(function (blob) {\n if (blob != null) {\n resolve(blob);\n } else {\n reject(new Error('`canvas.toBlob()` sent a null value in its callback'));\n }\n }, mimeType, options.quality);\n } catch (err) {\n reject(err);\n }\n });\n\n case 'blob':\n return b64ToBlob(b64UriToB64(getB64Uri()), mimeType);\n\n case 'base64':\n return b64UriToB64(getB64Uri());\n\n case 'base64uri':\n default:\n return getB64Uri();\n }\n}\n\nCRp$8.png = function (options) {\n return output(options, this.bufferCanvasImage(options), 'image/png');\n};\n\nCRp$8.jpg = function (options) {\n return output(options, this.bufferCanvasImage(options), 'image/jpeg');\n};\n\nvar CRp$9 = {};\n\nCRp$9.nodeShapeImpl = function (name, context, centerX, centerY, width, height, points) {\n switch (name) {\n case 'ellipse':\n return this.drawEllipsePath(context, centerX, centerY, width, height);\n\n case 'polygon':\n return this.drawPolygonPath(context, centerX, centerY, width, height, points);\n\n case 'round-polygon':\n return this.drawRoundPolygonPath(context, centerX, centerY, width, height, points);\n\n case 'roundrectangle':\n case 'round-rectangle':\n return this.drawRoundRectanglePath(context, centerX, centerY, width, height);\n\n case 'cutrectangle':\n case 'cut-rectangle':\n return this.drawCutRectanglePath(context, centerX, centerY, width, height);\n\n case 'bottomroundrectangle':\n case 'bottom-round-rectangle':\n return this.drawBottomRoundRectanglePath(context, centerX, centerY, width, height);\n\n case 'barrel':\n return this.drawBarrelPath(context, centerX, centerY, width, height);\n }\n};\n\nvar CR = CanvasRenderer;\nvar CRp$a = CanvasRenderer.prototype;\nCRp$a.CANVAS_LAYERS = 3; //\n\nCRp$a.SELECT_BOX = 0;\nCRp$a.DRAG = 1;\nCRp$a.NODE = 2;\nCRp$a.BUFFER_COUNT = 3; //\n\nCRp$a.TEXTURE_BUFFER = 0;\nCRp$a.MOTIONBLUR_BUFFER_NODE = 1;\nCRp$a.MOTIONBLUR_BUFFER_DRAG = 2;\n\nfunction CanvasRenderer(options) {\n var r = this;\n r.data = {\n canvases: new Array(CRp$a.CANVAS_LAYERS),\n contexts: new Array(CRp$a.CANVAS_LAYERS),\n canvasNeedsRedraw: new Array(CRp$a.CANVAS_LAYERS),\n bufferCanvases: new Array(CRp$a.BUFFER_COUNT),\n bufferContexts: new Array(CRp$a.CANVAS_LAYERS)\n };\n var tapHlOffAttr = '-webkit-tap-highlight-color';\n var tapHlOffStyle = 'rgba(0,0,0,0)';\n r.data.canvasContainer = document.createElement('div'); // eslint-disable-line no-undef\n\n var containerStyle = r.data.canvasContainer.style;\n r.data.canvasContainer.style[tapHlOffAttr] = tapHlOffStyle;\n containerStyle.position = 'relative';\n containerStyle.zIndex = '0';\n containerStyle.overflow = 'hidden';\n var container = options.cy.container();\n container.appendChild(r.data.canvasContainer);\n container.style[tapHlOffAttr] = tapHlOffStyle;\n var styleMap = {\n '-webkit-user-select': 'none',\n '-moz-user-select': '-moz-none',\n 'user-select': 'none',\n '-webkit-tap-highlight-color': 'rgba(0,0,0,0)',\n 'outline-style': 'none'\n };\n\n if (ms()) {\n styleMap['-ms-touch-action'] = 'none';\n styleMap['touch-action'] = 'none';\n }\n\n for (var i = 0; i < CRp$a.CANVAS_LAYERS; i++) {\n var canvas = r.data.canvases[i] = document.createElement('canvas'); // eslint-disable-line no-undef\n\n r.data.contexts[i] = canvas.getContext('2d');\n Object.keys(styleMap).forEach(function (k) {\n canvas.style[k] = styleMap[k];\n });\n canvas.style.position = 'absolute';\n canvas.setAttribute('data-id', 'layer' + i);\n canvas.style.zIndex = String(CRp$a.CANVAS_LAYERS - i);\n r.data.canvasContainer.appendChild(canvas);\n r.data.canvasNeedsRedraw[i] = false;\n }\n\n r.data.topCanvas = r.data.canvases[0];\n r.data.canvases[CRp$a.NODE].setAttribute('data-id', 'layer' + CRp$a.NODE + '-node');\n r.data.canvases[CRp$a.SELECT_BOX].setAttribute('data-id', 'layer' + CRp$a.SELECT_BOX + '-selectbox');\n r.data.canvases[CRp$a.DRAG].setAttribute('data-id', 'layer' + CRp$a.DRAG + '-drag');\n\n for (var i = 0; i < CRp$a.BUFFER_COUNT; i++) {\n r.data.bufferCanvases[i] = document.createElement('canvas'); // eslint-disable-line no-undef\n\n r.data.bufferContexts[i] = r.data.bufferCanvases[i].getContext('2d');\n r.data.bufferCanvases[i].style.position = 'absolute';\n r.data.bufferCanvases[i].setAttribute('data-id', 'buffer' + i);\n r.data.bufferCanvases[i].style.zIndex = String(-i - 1);\n r.data.bufferCanvases[i].style.visibility = 'hidden'; //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]);\n }\n\n r.pathsEnabled = true;\n var emptyBb = makeBoundingBox();\n\n var getBoxCenter = function getBoxCenter(bb) {\n return {\n x: (bb.x1 + bb.x2) / 2,\n y: (bb.y1 + bb.y2) / 2\n };\n };\n\n var getCenterOffset = function getCenterOffset(bb) {\n return {\n x: -bb.w / 2,\n y: -bb.h / 2\n };\n };\n\n var backgroundTimestampHasChanged = function backgroundTimestampHasChanged(ele) {\n var _p = ele[0]._private;\n var same = _p.oldBackgroundTimestamp === _p.backgroundTimestamp;\n return !same;\n };\n\n var getStyleKey = function getStyleKey(ele) {\n return ele[0]._private.nodeKey;\n };\n\n var getLabelKey = function getLabelKey(ele) {\n return ele[0]._private.labelStyleKey;\n };\n\n var getSourceLabelKey = function getSourceLabelKey(ele) {\n return ele[0]._private.sourceLabelStyleKey;\n };\n\n var getTargetLabelKey = function getTargetLabelKey(ele) {\n return ele[0]._private.targetLabelStyleKey;\n };\n\n var drawElement = function drawElement(context, ele, bb, scaledLabelShown, useEleOpacity) {\n return r.drawElement(context, ele, bb, false, false, useEleOpacity);\n };\n\n var drawLabel = function drawLabel(context, ele, bb, scaledLabelShown, useEleOpacity) {\n return r.drawElementText(context, ele, bb, scaledLabelShown, 'main', useEleOpacity);\n };\n\n var drawSourceLabel = function drawSourceLabel(context, ele, bb, scaledLabelShown, useEleOpacity) {\n return r.drawElementText(context, ele, bb, scaledLabelShown, 'source', useEleOpacity);\n };\n\n var drawTargetLabel = function drawTargetLabel(context, ele, bb, scaledLabelShown, useEleOpacity) {\n return r.drawElementText(context, ele, bb, scaledLabelShown, 'target', useEleOpacity);\n };\n\n var getElementBox = function getElementBox(ele) {\n ele.boundingBox();\n return ele[0]._private.bodyBounds;\n };\n\n var getLabelBox = function getLabelBox(ele) {\n ele.boundingBox();\n return ele[0]._private.labelBounds.main || emptyBb;\n };\n\n var getSourceLabelBox = function getSourceLabelBox(ele) {\n ele.boundingBox();\n return ele[0]._private.labelBounds.source || emptyBb;\n };\n\n var getTargetLabelBox = function getTargetLabelBox(ele) {\n ele.boundingBox();\n return ele[0]._private.labelBounds.target || emptyBb;\n };\n\n var isLabelVisibleAtScale = function isLabelVisibleAtScale(ele, scaledLabelShown) {\n return scaledLabelShown;\n };\n\n var getElementRotationPoint = function getElementRotationPoint(ele) {\n return getBoxCenter(getElementBox(ele));\n };\n\n var addTextMargin = function addTextMargin(prefix, pt, ele) {\n var pre = prefix ? prefix + '-' : '';\n return {\n x: pt.x + ele.pstyle(pre + 'text-margin-x').pfValue,\n y: pt.y + ele.pstyle(pre + 'text-margin-y').pfValue\n };\n };\n\n var getRsPt = function getRsPt(ele, x, y) {\n var rs = ele[0]._private.rscratch;\n return {\n x: rs[x],\n y: rs[y]\n };\n };\n\n var getLabelRotationPoint = function getLabelRotationPoint(ele) {\n return addTextMargin('', getRsPt(ele, 'labelX', 'labelY'), ele);\n };\n\n var getSourceLabelRotationPoint = function getSourceLabelRotationPoint(ele) {\n return addTextMargin('source', getRsPt(ele, 'sourceLabelX', 'sourceLabelY'), ele);\n };\n\n var getTargetLabelRotationPoint = function getTargetLabelRotationPoint(ele) {\n return addTextMargin('target', getRsPt(ele, 'targetLabelX', 'targetLabelY'), ele);\n };\n\n var getElementRotationOffset = function getElementRotationOffset(ele) {\n return getCenterOffset(getElementBox(ele));\n };\n\n var getSourceLabelRotationOffset = function getSourceLabelRotationOffset(ele) {\n return getCenterOffset(getSourceLabelBox(ele));\n };\n\n var getTargetLabelRotationOffset = function getTargetLabelRotationOffset(ele) {\n return getCenterOffset(getTargetLabelBox(ele));\n };\n\n var getLabelRotationOffset = function getLabelRotationOffset(ele) {\n var bb = getLabelBox(ele);\n var p = getCenterOffset(getLabelBox(ele));\n\n if (ele.isNode()) {\n switch (ele.pstyle('text-halign').value) {\n case 'left':\n p.x = -bb.w;\n break;\n\n case 'right':\n p.x = 0;\n break;\n }\n\n switch (ele.pstyle('text-valign').value) {\n case 'top':\n p.y = -bb.h;\n break;\n\n case 'bottom':\n p.y = 0;\n break;\n }\n }\n\n return p;\n };\n\n var eleTxrCache = r.data.eleTxrCache = new ElementTextureCache(r, {\n getKey: getStyleKey,\n doesEleInvalidateKey: backgroundTimestampHasChanged,\n drawElement: drawElement,\n getBoundingBox: getElementBox,\n getRotationPoint: getElementRotationPoint,\n getRotationOffset: getElementRotationOffset,\n allowEdgeTxrCaching: false,\n allowParentTxrCaching: false\n });\n var lblTxrCache = r.data.lblTxrCache = new ElementTextureCache(r, {\n getKey: getLabelKey,\n drawElement: drawLabel,\n getBoundingBox: getLabelBox,\n getRotationPoint: getLabelRotationPoint,\n getRotationOffset: getLabelRotationOffset,\n isVisible: isLabelVisibleAtScale\n });\n var slbTxrCache = r.data.slbTxrCache = new ElementTextureCache(r, {\n getKey: getSourceLabelKey,\n drawElement: drawSourceLabel,\n getBoundingBox: getSourceLabelBox,\n getRotationPoint: getSourceLabelRotationPoint,\n getRotationOffset: getSourceLabelRotationOffset,\n isVisible: isLabelVisibleAtScale\n });\n var tlbTxrCache = r.data.tlbTxrCache = new ElementTextureCache(r, {\n getKey: getTargetLabelKey,\n drawElement: drawTargetLabel,\n getBoundingBox: getTargetLabelBox,\n getRotationPoint: getTargetLabelRotationPoint,\n getRotationOffset: getTargetLabelRotationOffset,\n isVisible: isLabelVisibleAtScale\n });\n var lyrTxrCache = r.data.lyrTxrCache = new LayeredTextureCache(r);\n r.onUpdateEleCalcs(function invalidateTextureCaches(willDraw, eles) {\n // each cache should check for sub-key diff to see that the update affects that cache particularly\n eleTxrCache.invalidateElements(eles);\n lblTxrCache.invalidateElements(eles);\n slbTxrCache.invalidateElements(eles);\n tlbTxrCache.invalidateElements(eles); // any change invalidates the layers\n\n lyrTxrCache.invalidateElements(eles); // update the old bg timestamp so diffs can be done in the ele txr caches\n\n for (var _i = 0; _i < eles.length; _i++) {\n var _p = eles[_i]._private;\n _p.oldBackgroundTimestamp = _p.backgroundTimestamp;\n }\n });\n\n var refineInLayers = function refineInLayers(reqs) {\n for (var i = 0; i < reqs.length; i++) {\n lyrTxrCache.enqueueElementRefinement(reqs[i].ele);\n }\n };\n\n eleTxrCache.onDequeue(refineInLayers);\n lblTxrCache.onDequeue(refineInLayers);\n slbTxrCache.onDequeue(refineInLayers);\n tlbTxrCache.onDequeue(refineInLayers);\n}\n\nCRp$a.redrawHint = function (group, bool) {\n var r = this;\n\n switch (group) {\n case 'eles':\n r.data.canvasNeedsRedraw[CRp$a.NODE] = bool;\n break;\n\n case 'drag':\n r.data.canvasNeedsRedraw[CRp$a.DRAG] = bool;\n break;\n\n case 'select':\n r.data.canvasNeedsRedraw[CRp$a.SELECT_BOX] = bool;\n break;\n }\n}; // whether to use Path2D caching for drawing\n\n\nvar pathsImpld = typeof Path2D !== 'undefined';\n\nCRp$a.path2dEnabled = function (on) {\n if (on === undefined) {\n return this.pathsEnabled;\n }\n\n this.pathsEnabled = on ? true : false;\n};\n\nCRp$a.usePaths = function () {\n return pathsImpld && this.pathsEnabled;\n};\n\nCRp$a.setImgSmoothing = function (context, bool) {\n if (context.imageSmoothingEnabled != null) {\n context.imageSmoothingEnabled = bool;\n } else {\n context.webkitImageSmoothingEnabled = bool;\n context.mozImageSmoothingEnabled = bool;\n context.msImageSmoothingEnabled = bool;\n }\n};\n\nCRp$a.getImgSmoothing = function (context) {\n if (context.imageSmoothingEnabled != null) {\n return context.imageSmoothingEnabled;\n } else {\n return context.webkitImageSmoothingEnabled || context.mozImageSmoothingEnabled || context.msImageSmoothingEnabled;\n }\n};\n\nCRp$a.makeOffscreenCanvas = function (width, height) {\n var canvas;\n\n if ((typeof OffscreenCanvas === \"undefined\" ? \"undefined\" : _typeof(OffscreenCanvas)) !== ( \"undefined\" )) {\n canvas = new OffscreenCanvas(width, height);\n } else {\n canvas = document.createElement('canvas'); // eslint-disable-line no-undef\n\n canvas.width = width;\n canvas.height = height;\n }\n\n return canvas;\n};\n\n[CRp, CRp$1, CRp$2, CRp$3, CRp$4, CRp$5, CRp$6, CRp$7, CRp$8, CRp$9].forEach(function (props) {\n extend(CRp$a, props);\n});\n\nvar renderer = [{\n name: 'null',\n impl: NullRenderer\n}, {\n name: 'base',\n impl: BR\n}, {\n name: 'canvas',\n impl: CR\n}];\n\nvar incExts = [{\n type: 'layout',\n extensions: layout\n}, {\n type: 'renderer',\n extensions: renderer\n}];\n\nvar extensions = {}; // registered modules for extensions, indexed by name\n\nvar modules = {};\n\nfunction setExtension(type, name, registrant) {\n var ext = registrant;\n\n var overrideErr = function overrideErr(field) {\n error('Can not register `' + name + '` for `' + type + '` since `' + field + '` already exists in the prototype and can not be overridden');\n };\n\n if (type === 'core') {\n if (Core.prototype[name]) {\n return overrideErr(name);\n } else {\n Core.prototype[name] = registrant;\n }\n } else if (type === 'collection') {\n if (Collection.prototype[name]) {\n return overrideErr(name);\n } else {\n Collection.prototype[name] = registrant;\n }\n } else if (type === 'layout') {\n // fill in missing layout functions in the prototype\n var Layout = function Layout(options) {\n this.options = options;\n registrant.call(this, options); // make sure layout has _private for use w/ std apis like .on()\n\n if (!plainObject(this._private)) {\n this._private = {};\n }\n\n this._private.cy = options.cy;\n this._private.listeners = [];\n this.createEmitter();\n };\n\n var layoutProto = Layout.prototype = Object.create(registrant.prototype);\n var optLayoutFns = [];\n\n for (var i = 0; i < optLayoutFns.length; i++) {\n var fnName = optLayoutFns[i];\n\n layoutProto[fnName] = layoutProto[fnName] || function () {\n return this;\n };\n } // either .start() or .run() is defined, so autogen the other\n\n\n if (layoutProto.start && !layoutProto.run) {\n layoutProto.run = function () {\n this.start();\n return this;\n };\n } else if (!layoutProto.start && layoutProto.run) {\n layoutProto.start = function () {\n this.run();\n return this;\n };\n }\n\n var regStop = registrant.prototype.stop;\n\n layoutProto.stop = function () {\n var opts = this.options;\n\n if (opts && opts.animate) {\n var anis = this.animations;\n\n if (anis) {\n for (var _i = 0; _i < anis.length; _i++) {\n anis[_i].stop();\n }\n }\n }\n\n if (regStop) {\n regStop.call(this);\n } else {\n this.emit('layoutstop');\n }\n\n return this;\n };\n\n if (!layoutProto.destroy) {\n layoutProto.destroy = function () {\n return this;\n };\n }\n\n layoutProto.cy = function () {\n return this._private.cy;\n };\n\n var getCy = function getCy(layout) {\n return layout._private.cy;\n };\n\n var emitterOpts = {\n addEventFields: function addEventFields(layout, evt) {\n evt.layout = layout;\n evt.cy = getCy(layout);\n evt.target = layout;\n },\n bubble: function bubble() {\n return true;\n },\n parent: function parent(layout) {\n return getCy(layout);\n }\n };\n extend(layoutProto, {\n createEmitter: function createEmitter() {\n this._private.emitter = new Emitter(emitterOpts, this);\n return this;\n },\n emitter: function emitter() {\n return this._private.emitter;\n },\n on: function on(evt, cb) {\n this.emitter().on(evt, cb);\n return this;\n },\n one: function one(evt, cb) {\n this.emitter().one(evt, cb);\n return this;\n },\n once: function once(evt, cb) {\n this.emitter().one(evt, cb);\n return this;\n },\n removeListener: function removeListener(evt, cb) {\n this.emitter().removeListener(evt, cb);\n return this;\n },\n removeAllListeners: function removeAllListeners() {\n this.emitter().removeAllListeners();\n return this;\n },\n emit: function emit(evt, params) {\n this.emitter().emit(evt, params);\n return this;\n }\n });\n define$3.eventAliasesOn(layoutProto);\n ext = Layout; // replace with our wrapped layout\n } else if (type === 'renderer' && name !== 'null' && name !== 'base') {\n // user registered renderers inherit from base\n var BaseRenderer = getExtension('renderer', 'base');\n var bProto = BaseRenderer.prototype;\n var RegistrantRenderer = registrant;\n var rProto = registrant.prototype;\n\n var Renderer = function Renderer() {\n BaseRenderer.apply(this, arguments);\n RegistrantRenderer.apply(this, arguments);\n };\n\n var proto = Renderer.prototype;\n\n for (var pName in bProto) {\n var pVal = bProto[pName];\n var existsInR = rProto[pName] != null;\n\n if (existsInR) {\n return overrideErr(pName);\n }\n\n proto[pName] = pVal; // take impl from base\n }\n\n for (var _pName in rProto) {\n proto[_pName] = rProto[_pName]; // take impl from registrant\n }\n\n bProto.clientFunctions.forEach(function (name) {\n proto[name] = proto[name] || function () {\n error('Renderer does not implement `renderer.' + name + '()` on its prototype');\n };\n });\n ext = Renderer;\n }\n\n return setMap({\n map: extensions,\n keys: [type, name],\n value: ext\n });\n}\n\nfunction getExtension(type, name) {\n return getMap({\n map: extensions,\n keys: [type, name]\n });\n}\n\nfunction setModule(type, name, moduleType, moduleName, registrant) {\n return setMap({\n map: modules,\n keys: [type, name, moduleType, moduleName],\n value: registrant\n });\n}\n\nfunction getModule(type, name, moduleType, moduleName) {\n return getMap({\n map: modules,\n keys: [type, name, moduleType, moduleName]\n });\n}\n\nvar extension = function extension() {\n // e.g. extension('renderer', 'svg')\n if (arguments.length === 2) {\n return getExtension.apply(null, arguments);\n } // e.g. extension('renderer', 'svg', { ... })\n else if (arguments.length === 3) {\n return setExtension.apply(null, arguments);\n } // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')\n else if (arguments.length === 4) {\n return getModule.apply(null, arguments);\n } // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })\n else if (arguments.length === 5) {\n return setModule.apply(null, arguments);\n } else {\n error('Invalid extension access syntax');\n }\n}; // allows a core instance to access extensions internally\n\n\nCore.prototype.extension = extension; // included extensions\n\nincExts.forEach(function (group) {\n group.extensions.forEach(function (ext) {\n setExtension(group.type, ext.name, ext.impl);\n });\n});\n\n// (useful for init)\n\nvar Stylesheet = function Stylesheet() {\n if (!(this instanceof Stylesheet)) {\n return new Stylesheet();\n }\n\n this.length = 0;\n};\n\nvar sheetfn = Stylesheet.prototype;\n\nsheetfn.instanceString = function () {\n return 'stylesheet';\n}; // just store the selector to be parsed later\n\n\nsheetfn.selector = function (selector) {\n var i = this.length++;\n this[i] = {\n selector: selector,\n properties: []\n };\n return this; // chaining\n}; // just store the property to be parsed later\n\n\nsheetfn.css = function (name, value) {\n var i = this.length - 1;\n\n if (string(name)) {\n this[i].properties.push({\n name: name,\n value: value\n });\n } else if (plainObject(name)) {\n var map = name;\n var propNames = Object.keys(map);\n\n for (var j = 0; j < propNames.length; j++) {\n var key = propNames[j];\n var mapVal = map[key];\n\n if (mapVal == null) {\n continue;\n }\n\n var prop = Style.properties[key] || Style.properties[dash2camel(key)];\n\n if (prop == null) {\n continue;\n }\n\n var _name = prop.name;\n var _value = mapVal;\n this[i].properties.push({\n name: _name,\n value: _value\n });\n }\n }\n\n return this; // chaining\n};\n\nsheetfn.style = sheetfn.css; // generate a real style object from the dummy stylesheet\n\nsheetfn.generateStyle = function (cy) {\n var style = new Style(cy);\n return this.appendToStyle(style);\n}; // append a dummy stylesheet object on a real style object\n\n\nsheetfn.appendToStyle = function (style) {\n for (var i = 0; i < this.length; i++) {\n var context = this[i];\n var selector = context.selector;\n var props = context.properties;\n style.selector(selector); // apply selector\n\n for (var j = 0; j < props.length; j++) {\n var prop = props[j];\n style.css(prop.name, prop.value); // apply property\n }\n }\n\n return style;\n};\n\nvar version = \"3.15.1\";\n\nvar cytoscape = function cytoscape(options) {\n // if no options specified, use default\n if (options === undefined) {\n options = {};\n } // create instance\n\n\n if (plainObject(options)) {\n return new Core(options);\n } // allow for registration of extensions\n else if (string(options)) {\n return extension.apply(extension, arguments);\n }\n}; // e.g. cytoscape.use( require('cytoscape-foo'), bar )\n\n\ncytoscape.use = function (ext) {\n var args = Array.prototype.slice.call(arguments, 1); // args to pass to ext\n\n args.unshift(cytoscape); // cytoscape is first arg to ext\n\n ext.apply(null, args);\n return this;\n};\n\ncytoscape.warnings = function (bool) {\n return warnings(bool);\n}; // replaced by build system\n\n\ncytoscape.version = version; // expose public apis (mostly for extensions)\n\ncytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet;\n\nmodule.exports = cytoscape;\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../timers-browserify/main.js */ \"./node_modules/timers-browserify/main.js\").setImmediate))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9jeXRvc2NhcGUvZGlzdC9jeXRvc2NhcGUuY2pzLmpzPzQ0ZTEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVhOztBQUViLCtCQUErQixpRkFBaUY7O0FBRWhILDJCQUEyQixtQkFBTyxDQUFDLGdFQUFpQjtBQUNwRCwyQkFBMkIsbUJBQU8sQ0FBQywwQ0FBTTs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsa0JBQWtCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2Q0FBNkMsK0JBQStCO0FBQzVFOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSw2REFBNkQ7O0FBRTdEO0FBQ0E7O0FBRUE7O0FBRUEsMEJBQTBCOztBQUUxQixxQ0FBcUM7O0FBRXJDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsZ0JBQWdCO0FBQ2hCOztBQUVBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTs7QUFFQSxxQkFBcUIsc0JBQXNCO0FBQzNDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsQ0FBQztBQUNEO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLEVBQUU7QUFDN0IsMkJBQTJCLEVBQUU7O0FBRTdCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQkFBaUIsaUJBQWlCO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxtQkFBbUIsaUJBQWlCO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBLGFBQWE7O0FBRWI7O0FBRUE7QUFDQTtBQUNBLEtBQUs7OztBQUdMLGdCQUFnQjs7QUFFaEI7O0FBRUE7QUFDQTtBQUNBLEtBQUs7OztBQUdMLGdCQUFnQjs7QUFFaEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxLQUFLO0FBQ0w7OztBQUdBO0FBQ0Esc0NBQXNDO0FBQ3RDLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsUUFBUTtBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxzQ0FBc0M7QUFDdEM7O0FBRUE7QUFDQTtBQUNBLE9BQU87OztBQUdQO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLE9BQU87QUFDeEI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixPQUFPO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNM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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0NBQW9DO0FBQ3BDLFdBQVc7QUFDWCxxQ0FBcUM7QUFDckMsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxtQ0FBbUMsOEJBQThCO0FBQ2pFOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQSx3REFBd0Q7O0FBRXhEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQSwrRkFBK0Y7QUFDL0Y7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLHFCQUFxQjtBQUN4QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7O0FBR0EsNkRBQTZEO0FBQzdEO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtRUFBbUU7QUFDbkUsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtB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QUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIsMkJBQTJCO0FBQzVDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7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Q0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQSxpQkFBaUIsaUJBQWlCO0FBQ2xDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixtQkFBbUI7QUFDekM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVB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QUNBLEVBQUU7OztBQUdGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQkFBcUIsMkJBQTJCO0FBQ2hEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsa0JBQWtCO0FBQ3JDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtB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O0FBR0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLDBCQUEwQjs7QUFFMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLGlCQUFpQjtBQUNsQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7QUFDQTtBQUNBO0FBQ0EsdUVBQXVFOztBQUV2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7O0FBRTdCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDOztBQUVoQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qjs7QUFFekIsV0FBVzs7QUFFWDtBQUNBLDhGQUE4RjtBQUM5Rjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLHdCQUF3QjtBQUN4Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsNERBQTREO0FBQzVEOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDhEQUE4RDs7QUFFOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQ7QUFDakQ7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQixnQkFBZ0I7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQLEtBQUs7QUFDTDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOzs7QUFHTDtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOzs7QUFHTDtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9EQUFvRDs7QUFFcEQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSCw0Q0FBNEM7O0FBRTVDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EscUJBQXFCLGlCQUFpQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLG9CQUFvQixrQkFBa0I7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLG9DQUFvQztBQUNwQzs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx3REFBd0Q7O0FBRXhEO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUMsSUFBSTs7QUFFTCwwQkFBMEI7O0FBRTFCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtB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QSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBLGVBQWU7O0FBRWY7QUFDQTs7QUFFQTtBQUNBLGVBQWU7O0FBRWY7O0FBRUE7O0FBRUEsZ0RBQWdEO0FBQ2hEOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGVBQWU7O0FBRWY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlDQUFpQzs7QUFFakM7QUFDQTs7QUFFQTtBQUNBLGlDQUFpQzs7QUFFakM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUM7QUFDakM7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLGlCQUFpQjtBQUNsQztBQUNBO0FBQ0EsNkNBQTZDOztBQUU3QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DLFNBQVM7QUFDN0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7O0FBR0osYUFBYSxxQkFBcUI7QUFDbEM7QUFDQTtBQUNBLCtCQUErQjs7QUFFL0IsK0JBQStCOzs7QUFHL0IsMENBQTBDO0FBQzFDO0FBQ0EsS0FBSztBQUNMLGlDQUFpQztBQUNqQyxLQUFLO0FBQ0wsaUZBQWlGOztBQUVqRjtBQUNBO0FBQ0EsS0FBSztBQUNMLHlFQUF5RTs7QUFFekU7QUFDQTtBQUNBOztBQUVBLHVCQUF1Qjs7QUFFdkI7QUFDQTtBQUNBLGtDQUFrQzs7QUFFbEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQkFBcUIsa0JBQWtCO0FBQ3ZDO0FBQ0E7O0FBRUE7QUFDQSxtREFBbUQ7QUFDbkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDtBQUNBLGlEQUFpRDs7QUFFakQ7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOzs7QUFHQSxtQkFBbUIsb0JBQW9CO0FBQ3ZDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQztBQUN0Qzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDJDQUEyQzs7QUFFM0M7QUFDQTtBQUNBLE9BQU87O0FBRVAsS0FBSzs7QUFFTCxHQUFHOzs7QUFHSDtBQUNBOztBQUVBLHFCQUFxQix1QkFBdUI7QUFDNUM7O0FBRUE7QUFDQTtBQUNBLE9BQU87OztBQUdQLGtEQUFrRDs7O0FBR2xEOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLGNBQWM7QUFDZDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7O0FBRTVCO0FBQ0E7O0FBRUEsbUJBQW1CLGtCQUFrQjtBQUNyQztBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTs7QUFFQSxtQkFBbUIscUJBQXFCO0FBQ3hDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBLDZCQUE2Qjs7QUFFN0I7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0M7QUFDaEM7QUFDQSxHQUFHO0FBQ0g7OztBQUdBLGtDQUFrQyxPQUFPO0FBQ3pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMENBQTBDOztBQUUxQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQzs7QUFFbkMsK0JBQStCOztBQUUvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esb0NBQW9DO0FBQ3BDOztBQUVBLG1CQUFtQiwyQkFBMkI7QUFDOUM7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEscUJBQXFCLHFCQUFxQjtBQUMxQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBOztBQUVBLG1CQUFtQiw4QkFBOEI7QUFDakQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRzs7O0FBR0gsbUJBQW1CLDZCQUE2QjtBQUNoRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7O0FBR0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7O0FBRWhEOztBQUVBLHVCQUF1QixpQkFBaUI7QUFDeEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlEQUFpRDtBQUNqRCxPQUFPO0FBQ1A7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7O0FBRTlEOztBQUVBLHVCQUF1QixpQkFBaUI7QUFDeEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvREFBb0Q7QUFDcEQsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjs7QUFFbEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQSx1QkFBdUIsaUJBQWlCO0FBQ3hDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyQ0FBMkMsU0FBUztBQUNwRDtBQUNBOztBQUVBO0FBQ0Esb0RBQW9ELFFBQVE7QUFDNUQ7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQSwwQ0FBMEM7QUFDMUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW9CLHdCQUF3QjtBQUM1Qzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUIsd0JBQXdCO0FBQzdDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsb0VBQW9FO0FBQzlFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQSxtQkFBbUIsZ0JBQWdCO0FBQ25DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHFCQUFxQixrQkFBa0I7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCOztBQUV4QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUNBQXlDLFFBQVE7QUFDakQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsTUFBTTs7O0FBR04sb0NBQW9DLFFBQVE7QUFDNUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7OztBQUdBOztBQUVBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0gscUNBQXFDOztBQUVyQztBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FB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QUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLDhCQUE4QjtBQUM5QixLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRyxFQUFFOztBQUVMO0FBQ0EsOEJBQThCOztBQUU5QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVILGlCQUFpQiw2QkFBNkI7QUFDOUM7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTCxHQUFHLElBQUk7QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHLEVBQUU7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHLEVBQUU7O0FBRUw7QUFDQTtBQUNBLEdBQUcsRUFBRTs7QUFFTCxrQkFBa0IsbUJBQW1CO0FBQ3JDO0FBQ0EsNEJBQTRCO0FBQzVCLEdBQUc7OztBQUdILG1CQUFtQixzQkFBc0I7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBLGtDQUFrQztBQUNsQztBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSCxpQkFBaUIsR0FBRztBQUNwQjtBQUNBLEdBQUc7QUFDSCxpQkFBaUIsR0FBRztBQUNwQjtBQUNBLEdBQUc7QUFDSCxpQkFBaUIsR0FBRztBQUNwQjtBQUNBLEdBQUc7QUFDSCxtQkFBbUIsNkJBQTZCO0FBQ2hELHNDQUFzQyxHQUFHO0FBQ3pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUcsSUFBSTtBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHLElBQUk7QUFDUDs7QUFFQSxpQkFBaUIsNEJBQTRCO0FB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O0FBQ2hCLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOzs7QUFHTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEVBQTBFOztBQUUxRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTs7QUFFWjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0EsaURBQWlEOztBQUVqRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtB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O0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUEsZUFBZTs7QUFFZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FB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QUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQzs7QUFFbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQSx5QkFBeUI7QUFDekI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RDs7QUFFekQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHlCQUF5QjtBQUN6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O0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0gsMkJBQTJCO0FBQzNCLEdBQUc7QUFDSDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQkFBaUIsNkJBQTZCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCOztBQUV2QjtBQUNBO0FBQ0E7O0FBRUE7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O0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOzs7QUFHTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnRkFBZ0Y7O0FBRWhGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUsseUJBQXlCO0FBQzlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFD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Q0FBa0M7O0FBRWxDO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7QUFDQTtBQUNBLE9BQU87OztBQUdQO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7O0FBRTlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87OztBQUdQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFOztBQUVqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLCtDQUErQzs7QUFFL0M7QUFDQTtBQUNBLE9BQU87OztBQUdQO0FBQ0E7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Ozs7QUFHVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQzs7QUFFMUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLDRDQUE0Qzs7QUFFNUM7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7O0FBRXRDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxDQUFDOztBQUVELGlCQUFpQjs7QUFFakIsa0JBQWtCOztBQUVsQixnQkFBZ0I7O0FBRWhCLGVBQWU7O0FBRWYsbUJBQW1COztBQUVuQixzQkFBc0I7O0FBRXRCLHVCQUF1Qjs7QUFFdkIsbUJBQW1COztBQUVuQixtQkFBbUI7O0FBRW5CLHFCQUFxQjs7QUFFckIsc0JBQXNCOztBQUV0QiwyQkFBMkI7O0FBRTNCLG1CQUFtQjs7QUFFbkIscUJBQXFCOztBQUVyQix3QkFBd0I7O0FBRXhCLHNCQUFzQjs7QUFFdEIsNkJBQTZCOztBQUU3QixtQkFBbUI7O0FBRW5CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNkJBQTZCOztBQUU3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHNDQUFzQzs7QUFFdEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFdBQVc7O0FBRVg7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCO0FBQ2hCOztBQUVBLHdDQUF3Qzs7QUFFeEM7O0FBRUE7QUFDQTtBQUNBLElBQUk7OztBQUdKO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7O0FBRWxCLHVCQUF1QixhQUFhO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLElBQUk7OztBQUdKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxVQUFVO0FBQ2hEO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILG1CQUFtQjs7QUFFbkI7QUFDQSw2QkFBNkIsZUFBZTtBQUM1Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGlCQUFpQjtBQUNsQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7QUFDWDs7QUFFQSx3QkFBd0IsZUFBZTtBQUN2Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLG1CQUFtQixtQkFBbUI7QUFDdEM7QUFDQSwrQkFBK0I7O0FBRS9CLDJDQUEyQzs7QUFFM0MsZ0NBQWdDOztBQUVoQztBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjs7QUFFM0I7QUFDQSxxQkFBcUI7O0FBRXJCOztBQUVBLGlCQUFpQixzQkFBc0I7QUFDdkM7QUFDQTtBQUNBOztBQUVBLHdCQUF3Qjs7QUFFeEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIsbUJBQW1CO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixnQkFBZ0I7QUFDakM7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCOztBQUU1Qix3REFBd0Q7O0FBRXhELHNCQUFzQjs7QUFFdEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYzs7QUFFZCxzQkFBc0I7QUFDdEIsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsbUJBQW1CLDRCQUE0QjtBQUMvQztBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxtQkFBbUIsaUJBQWlCO0FBQ3BDOztBQUVBLHFCQUFxQixpQkFBaUI7QUFDdEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVELHFCQUFxQjs7QUFFckIsa0JBQWtCOztBQUVsQixpQkFBaUI7O0FBRWpCLHFCQUFxQjs7QUFFckIsOEJBQThCOztBQUU5QiwrQkFBK0I7O0FBRS9CLHFCQUFxQjs7QUFFckIsdUJBQXVCOztBQUV2QiwwQkFBMEI7O0FBRTFCLHdCQUF3Qjs7QUFFeEIscUJBQXFCOztBQUVyQiwyQkFBMkI7O0FBRTNCLCtCQUErQjs7QUFFL0Isb0NBQW9DO0FBQ3BDLHdCQUF3Qix5Q0FBeUM7O0FBRWpFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCOztBQUUxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSx3QkFBd0I7O0FBRXhCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QiwrQkFBK0Isa0JBQWtCOztBQUVqRDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDZCQUE2QixnQ0FBZ0M7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQiw4QkFBOEI7O0FBRWhELG1DQUFtQyxRQUFRO0FBQzNDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxxQkFBcUIsaUJBQWlCO0FBQ3RDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBLDZEQUE2RDs7QUFFN0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLEVBQUU7O0FBRVQ7QUFDQTtBQUNBLE9BQU87O0FBRVA7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsaUJBQWlCLG1CQUFtQjtBQUNwQywwQkFBMEI7O0FBRTFCO0FBQ0E7QUFDQSxLQUFLOzs7QUFHTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7OztBQUdBLGlCQUFpQixtQkFBbUI7QUFDcEM7QUFDQSxvQkFBb0I7O0FBRXBCLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMOztBQUVBLG1CQUFtQix1QkFBdUI7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDOztBQUVBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsMEJBQTBCLGVBQWU7QUFDekM7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSx3QkFBd0IsZUFBZTtBQUN2Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsK0NBQStDOztBQUUvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQSx1Q0FBdUM7O0FBRXZDLGlDQUFpQzs7QUFFakM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLGlCQUFpQjtBQUNsQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCOztBQUVsQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3Qjs7QUFFQTtBQUNBLHFCQUFxQixzQkFBc0I7QUFDM0M7QUFDQSxPQUFPOztBQUVQO0FBQ0EsR0FBRztBQUNIOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4Qzs7QUFFOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx5QkFBeUI7O0FBRXpCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7QUFDQSwrREFBK0Q7QUFDL0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOENBQThDO0FBQzlDO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQjtBQUMvQjs7QUFFQSxpQkFBaUIsdUJBQXVCO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixtQkFBbUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQkFBaUIsbUJBQW1CO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsaUJBQWlCLG1CQUFtQjtBQUNwQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixtQkFBbUI7QUFDcEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixtQkFBbUI7QUFDcEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7OztBQUdIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILDBDQUEwQztBQUMxQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsaUJBQWlCLGlCQUFpQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQkFBaUIsaUJBQWlCO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLG9CQUFvQjtBQUMzQztBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixxQkFBcUI7QUFDN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1Qzs7QUFFdkM7QUFDQSxtQ0FBbUM7O0FBRW5DO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNkJBQTZCOztBQUU3QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQSw2QkFBNkI7O0FBRTdCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDOztBQUU5QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLDRCQUE0QjtBQUM3Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7O0FBRTdCO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHlCQUF5Qjs7QUFFekI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esc0RBQXNEOztBQUV0RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUVBQWlFOztBQUVqRTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUzs7QUFFVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUzs7QUFFVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUzs7QUFFVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFCQUFxQixrQkFBa0I7QUFDdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQztBQUMzQzs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7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QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlJQUFpSTs7QUFFakk7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztB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QUVBO0FBQ0E7QUFDQSx3QkFBd0I7O0FBRXhCO0FBQ0E7QUFDQTtBQUNBLHVCQUF1Qjs7QUFFdkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQ7O0FBRXpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIseUJBQXlCO0FBQzFDLHVFQUF1RTs7QUFFdkU7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIsd0JBQXdCO0FBQ3pDLGdFQUFnRTs7QUFFaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQ7QUFDekQ7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFF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QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0Esc0RBQXNEOztBQUV0RCwwQkFBMEI7O0FBRTFCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0YsNEJBQTRCOztBQUU1Qjs7QUFFQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9jeXRvc2NhcGUvZGlzdC9jeXRvc2NhcGUuY2pzLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTYtMjAyMCwgVGhlIEN5dG9zY2FwZSBDb25zb3J0aXVtLlxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkgb2ZcbiAqIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIOKAnFNvZnR3YXJl4oCdKSwgdG8gZGVhbCBpblxuICogdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0b1xuICogdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXNcbiAqIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkb1xuICogc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuICogY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQg4oCcQVMgSVPigJ0sIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICogT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEVcbiAqIFNPRlRXQVJFLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gX2ludGVyb3BEZWZhdWx0IChleCkgeyByZXR1cm4gKGV4ICYmICh0eXBlb2YgZXggPT09ICdvYmplY3QnKSAmJiAnZGVmYXVsdCcgaW4gZXgpID8gZXhbJ2RlZmF1bHQnXSA6IGV4OyB9XG5cbnZhciB1dGlsID0gX2ludGVyb3BEZWZhdWx0KHJlcXVpcmUoJ2xvZGFzaC5kZWJvdW5jZScpKTtcbnZhciBIZWFwID0gX2ludGVyb3BEZWZhdWx0KHJlcXVpcmUoJ2hlYXAnKSk7XG5cbmZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gIGlmICh0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIikge1xuICAgIF90eXBlb2YgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIF90eXBlb2YgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIF90eXBlb2Yob2JqKTtcbn1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3Rvcikge1xuICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7XG4gIH1cbn1cblxuZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7XG4gICAgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlO1xuICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHtcbiAgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7XG4gIGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgcmV0dXJuIENvbnN0cnVjdG9yO1xufVxuXG5mdW5jdGlvbiBfZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gb2JqKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5LCB7XG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgd3JpdGFibGU6IHRydWVcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBvYmpba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuZnVuY3Rpb24gX3NsaWNlZFRvQXJyYXkoYXJyLCBpKSB7XG4gIHJldHVybiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5TGltaXQoYXJyLCBpKSB8fCBfbm9uSXRlcmFibGVSZXN0KCk7XG59XG5cbmZ1bmN0aW9uIF9hcnJheVdpdGhIb2xlcyhhcnIpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgcmV0dXJuIGFycjtcbn1cblxuZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkge1xuICB2YXIgX2FyciA9IFtdO1xuICB2YXIgX24gPSB0cnVlO1xuICB2YXIgX2QgPSBmYWxzZTtcbiAgdmFyIF9lID0gdW5kZWZpbmVkO1xuXG4gIHRyeSB7XG4gICAgZm9yICh2YXIgX2kgPSBhcnJbU3ltYm9sLml0ZXJhdG9yXSgpLCBfczsgIShfbiA9IChfcyA9IF9pLm5leHQoKSkuZG9uZSk7IF9uID0gdHJ1ZSkge1xuICAgICAgX2Fyci5wdXNoKF9zLnZhbHVlKTtcblxuICAgICAgaWYgKGkgJiYgX2Fyci5sZW5ndGggPT09IGkpIGJyZWFrO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgX2QgPSB0cnVlO1xuICAgIF9lID0gZXJyO1xuICB9IGZpbmFsbHkge1xuICAgIHRyeSB7XG4gICAgICBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdICE9IG51bGwpIF9pW1wicmV0dXJuXCJdKCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChfZCkgdGhyb3cgX2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9hcnI7XG59XG5cbmZ1bmN0aW9uIF9ub25JdGVyYWJsZVJlc3QoKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gZGVzdHJ1Y3R1cmUgbm9uLWl0ZXJhYmxlIGluc3RhbmNlXCIpO1xufVxuXG52YXIgd2luZG93JDEgPSB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJyA/IG51bGwgOiB3aW5kb3c7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxudmFyIG5hdmlnYXRvciA9IHdpbmRvdyQxID8gd2luZG93JDEubmF2aWdhdG9yIDogbnVsbDtcbnZhciBkb2N1bWVudCQxID0gd2luZG93JDEgPyB3aW5kb3ckMS5kb2N1bWVudCA6IG51bGw7XG5cbnZhciB0eXBlb2ZzdHIgPSBfdHlwZW9mKCcnKTtcblxudmFyIHR5cGVvZm9iaiA9IF90eXBlb2Yoe30pO1xuXG52YXIgdHlwZW9mZm4gPSBfdHlwZW9mKGZ1bmN0aW9uICgpIHt9KTtcblxudmFyIHR5cGVvZmh0bWxlbGUgPSB0eXBlb2YgSFRNTEVsZW1lbnQgPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihIVE1MRWxlbWVudCk7XG5cbnZhciBpbnN0YW5jZVN0ciA9IGZ1bmN0aW9uIGluc3RhbmNlU3RyKG9iaikge1xuICByZXR1cm4gb2JqICYmIG9iai5pbnN0YW5jZVN0cmluZyAmJiBmbihvYmouaW5zdGFuY2VTdHJpbmcpID8gb2JqLmluc3RhbmNlU3RyaW5nKCkgOiBudWxsO1xufTtcblxudmFyIHN0cmluZyA9IGZ1bmN0aW9uIHN0cmluZyhvYmopIHtcbiAgcmV0dXJuIG9iaiAhPSBudWxsICYmIF90eXBlb2Yob2JqKSA9PSB0eXBlb2ZzdHI7XG59O1xudmFyIGZuID0gZnVuY3Rpb24gZm4ob2JqKSB7XG4gIHJldHVybiBvYmogIT0gbnVsbCAmJiBfdHlwZW9mKG9iaikgPT09IHR5cGVvZmZuO1xufTtcbnZhciBhcnJheSA9IGZ1bmN0aW9uIGFycmF5KG9iaikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSA/IEFycmF5LmlzQXJyYXkob2JqKSA6IG9iaiAhPSBudWxsICYmIG9iaiBpbnN0YW5jZW9mIEFycmF5O1xufTtcbnZhciBwbGFpbk9iamVjdCA9IGZ1bmN0aW9uIHBsYWluT2JqZWN0KG9iaikge1xuICByZXR1cm4gb2JqICE9IG51bGwgJiYgX3R5cGVvZihvYmopID09PSB0eXBlb2ZvYmogJiYgIWFycmF5KG9iaikgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBPYmplY3Q7XG59O1xudmFyIG9iamVjdCA9IGZ1bmN0aW9uIG9iamVjdChvYmopIHtcbiAgcmV0dXJuIG9iaiAhPSBudWxsICYmIF90eXBlb2Yob2JqKSA9PT0gdHlwZW9mb2JqO1xufTtcbnZhciBudW1iZXIgPSBmdW5jdGlvbiBudW1iZXIob2JqKSB7XG4gIHJldHVybiBvYmogIT0gbnVsbCAmJiBfdHlwZW9mKG9iaikgPT09IF90eXBlb2YoMSkgJiYgIWlzTmFOKG9iaik7XG59O1xudmFyIGludGVnZXIgPSBmdW5jdGlvbiBpbnRlZ2VyKG9iaikge1xuICByZXR1cm4gbnVtYmVyKG9iaikgJiYgTWF0aC5mbG9vcihvYmopID09PSBvYmo7XG59O1xudmFyIGh0bWxFbGVtZW50ID0gZnVuY3Rpb24gaHRtbEVsZW1lbnQob2JqKSB7XG4gIGlmICgndW5kZWZpbmVkJyA9PT0gdHlwZW9maHRtbGVsZSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG51bGwgIT0gb2JqICYmIG9iaiBpbnN0YW5jZW9mIEhUTUxFbGVtZW50O1xuICB9XG59O1xudmFyIGVsZW1lbnRPckNvbGxlY3Rpb24gPSBmdW5jdGlvbiBlbGVtZW50T3JDb2xsZWN0aW9uKG9iaikge1xuICByZXR1cm4gZWxlbWVudChvYmopIHx8IGNvbGxlY3Rpb24ob2JqKTtcbn07XG52YXIgZWxlbWVudCA9IGZ1bmN0aW9uIGVsZW1lbnQob2JqKSB7XG4gIHJldHVybiBpbnN0YW5jZVN0cihvYmopID09PSAnY29sbGVjdGlvbicgJiYgb2JqLl9wcml2YXRlLnNpbmdsZTtcbn07XG52YXIgY29sbGVjdGlvbiA9IGZ1bmN0aW9uIGNvbGxlY3Rpb24ob2JqKSB7XG4gIHJldHVybiBpbnN0YW5jZVN0cihvYmopID09PSAnY29sbGVjdGlvbicgJiYgIW9iai5fcHJpdmF0ZS5zaW5nbGU7XG59O1xudmFyIGNvcmUgPSBmdW5jdGlvbiBjb3JlKG9iaikge1xuICByZXR1cm4gaW5zdGFuY2VTdHIob2JqKSA9PT0gJ2NvcmUnO1xufTtcbnZhciBzdHlsZXNoZWV0ID0gZnVuY3Rpb24gc3R5bGVzaGVldChvYmopIHtcbiAgcmV0dXJuIGluc3RhbmNlU3RyKG9iaikgPT09ICdzdHlsZXNoZWV0Jztcbn07XG52YXIgZXZlbnQgPSBmdW5jdGlvbiBldmVudChvYmopIHtcbiAgcmV0dXJuIGluc3RhbmNlU3RyKG9iaikgPT09ICdldmVudCc7XG59O1xudmFyIGVtcHR5U3RyaW5nID0gZnVuY3Rpb24gZW1wdHlTdHJpbmcob2JqKSB7XG4gIGlmIChvYmogPT09IHVuZGVmaW5lZCB8fCBvYmogPT09IG51bGwpIHtcbiAgICAvLyBudWxsIGlzIGVtcHR5XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAob2JqID09PSAnJyB8fCBvYmoubWF0Y2goL15cXHMrJC8pKSB7XG4gICAgcmV0dXJuIHRydWU7IC8vIGVtcHR5IHN0cmluZyBpcyBlbXB0eVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlOyAvLyBvdGhlcndpc2UsIHdlIGRvbid0IGtub3cgd2hhdCB3ZSd2ZSBnb3Rcbn07XG52YXIgZG9tRWxlbWVudCA9IGZ1bmN0aW9uIGRvbUVsZW1lbnQob2JqKSB7XG4gIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGZhbHNlOyAvLyB3ZSdyZSBub3QgaW4gYSBicm93c2VyIHNvIGl0IGRvZXNuJ3QgbWF0dGVyXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iaiBpbnN0YW5jZW9mIEhUTUxFbGVtZW50O1xuICB9XG59O1xudmFyIGJvdW5kaW5nQm94ID0gZnVuY3Rpb24gYm91bmRpbmdCb3gob2JqKSB7XG4gIHJldHVybiBwbGFpbk9iamVjdChvYmopICYmIG51bWJlcihvYmoueDEpICYmIG51bWJlcihvYmoueDIpICYmIG51bWJlcihvYmoueTEpICYmIG51bWJlcihvYmoueTIpO1xufTtcbnZhciBwcm9taXNlID0gZnVuY3Rpb24gcHJvbWlzZShvYmopIHtcbiAgcmV0dXJuIG9iamVjdChvYmopICYmIGZuKG9iai50aGVuKTtcbn07XG52YXIgbXMgPSBmdW5jdGlvbiBtcygpIHtcbiAgcmV0dXJuIG5hdmlnYXRvciAmJiBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9tc2llfHRyaWRlbnR8ZWRnZS9pKTtcbn07IC8vIHByb2JhYmx5IGEgYmV0dGVyIHdheSB0byBkZXRlY3QgdGhpcy4uLlxuXG52YXIgbWVtb2l6ZSA9IGZ1bmN0aW9uIG1lbW9pemUoZm4sIGtleUZuKSB7XG4gIGlmICgha2V5Rm4pIHtcbiAgICBrZXlGbiA9IGZ1bmN0aW9uIGtleUZuKCkge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIGFyZ3VtZW50c1swXTtcbiAgICAgIH0gZWxzZSBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7XG4gICAgICB9XG5cbiAgICAgIHZhciBhcmdzID0gW107XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFyZ3MucHVzaChhcmd1bWVudHNbaV0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYXJncy5qb2luKCckJyk7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBtZW1vaXplZEZuID0gZnVuY3Rpb24gbWVtb2l6ZWRGbigpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgdmFyIHJldDtcbiAgICB2YXIgayA9IGtleUZuLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICAgIHZhciBjYWNoZSA9IG1lbW9pemVkRm4uY2FjaGU7XG5cbiAgICBpZiAoIShyZXQgPSBjYWNoZVtrXSkpIHtcbiAgICAgIHJldCA9IGNhY2hlW2tdID0gZm4uYXBwbHkoc2VsZiwgYXJncyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfTtcblxuICBtZW1vaXplZEZuLmNhY2hlID0ge307XG4gIHJldHVybiBtZW1vaXplZEZuO1xufTtcblxudmFyIGNhbWVsMmRhc2ggPSBtZW1vaXplKGZ1bmN0aW9uIChzdHIpIHtcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC8oW0EtWl0pL2csIGZ1bmN0aW9uICh2KSB7XG4gICAgcmV0dXJuICctJyArIHYudG9Mb3dlckNhc2UoKTtcbiAgfSk7XG59KTtcbnZhciBkYXNoMmNhbWVsID0gbWVtb2l6ZShmdW5jdGlvbiAoc3RyKSB7XG4gIHJldHVybiBzdHIucmVwbGFjZSgvKC1cXHcpL2csIGZ1bmN0aW9uICh2KSB7XG4gICAgcmV0dXJuIHZbMV0udG9VcHBlckNhc2UoKTtcbiAgfSk7XG59KTtcbnZhciBwcmVwZW5kQ2FtZWwgPSBtZW1vaXplKGZ1bmN0aW9uIChwcmVmaXgsIHN0cikge1xuICByZXR1cm4gcHJlZml4ICsgc3RyWzBdLnRvVXBwZXJDYXNlKCkgKyBzdHIuc3Vic3RyaW5nKDEpO1xufSwgZnVuY3Rpb24gKHByZWZpeCwgc3RyKSB7XG4gIHJldHVybiBwcmVmaXggKyAnJCcgKyBzdHI7XG59KTtcbnZhciBjYXBpdGFsaXplID0gZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHIpIHtcbiAgaWYgKGVtcHR5U3RyaW5nKHN0cikpIHtcbiAgICByZXR1cm4gc3RyO1xuICB9XG5cbiAgcmV0dXJuIHN0ci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0ci5zdWJzdHJpbmcoMSk7XG59O1xuXG52YXIgbnVtYmVyJDEgPSAnKD86Wy0rXT8oPzooPzpcXFxcZCt8XFxcXGQqXFxcXC5cXFxcZCspKD86W0VlXVsrLV0/XFxcXGQrKT8pKSc7XG52YXIgcmdiYSA9ICdyZ2JbYV0/XFxcXCgoJyArIG51bWJlciQxICsgJ1slXT8pXFxcXHMqLFxcXFxzKignICsgbnVtYmVyJDEgKyAnWyVdPylcXFxccyosXFxcXHMqKCcgKyBudW1iZXIkMSArICdbJV0/KSg/OlxcXFxzKixcXFxccyooJyArIG51bWJlciQxICsgJykpP1xcXFwpJztcbnZhciByZ2JhTm9CYWNrUmVmcyA9ICdyZ2JbYV0/XFxcXCgoPzonICsgbnVtYmVyJDEgKyAnWyVdPylcXFxccyosXFxcXHMqKD86JyArIG51bWJlciQxICsgJ1slXT8pXFxcXHMqLFxcXFxzKig/OicgKyBudW1iZXIkMSArICdbJV0/KSg/OlxcXFxzKixcXFxccyooPzonICsgbnVtYmVyJDEgKyAnKSk/XFxcXCknO1xudmFyIGhzbGEgPSAnaHNsW2FdP1xcXFwoKCcgKyBudW1iZXIkMSArICcpXFxcXHMqLFxcXFxzKignICsgbnVtYmVyJDEgKyAnWyVdKVxcXFxzKixcXFxccyooJyArIG51bWJlciQxICsgJ1slXSkoPzpcXFxccyosXFxcXHMqKCcgKyBudW1iZXIkMSArICcpKT9cXFxcKSc7XG52YXIgaHNsYU5vQmFja1JlZnMgPSAnaHNsW2FdP1xcXFwoKD86JyArIG51bWJlciQxICsgJylcXFxccyosXFxcXHMqKD86JyArIG51bWJlciQxICsgJ1slXSlcXFxccyosXFxcXHMqKD86JyArIG51bWJlciQxICsgJ1slXSkoPzpcXFxccyosXFxcXHMqKD86JyArIG51bWJlciQxICsgJykpP1xcXFwpJztcbnZhciBoZXgzID0gJ1xcXFwjWzAtOWEtZkEtRl17M30nO1xudmFyIGhleDYgPSAnXFxcXCNbMC05YS1mQS1GXXs2fSc7XG5cbnZhciBhc2NlbmRpbmcgPSBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICBpZiAoYSA8IGIpIHtcbiAgICByZXR1cm4gLTE7XG4gIH0gZWxzZSBpZiAoYSA+IGIpIHtcbiAgICByZXR1cm4gMTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gMDtcbiAgfVxufTtcbnZhciBkZXNjZW5kaW5nID0gZnVuY3Rpb24gZGVzY2VuZGluZyhhLCBiKSB7XG4gIHJldHVybiAtMSAqIGFzY2VuZGluZyhhLCBiKTtcbn07XG5cbnZhciBleHRlbmQgPSBPYmplY3QuYXNzaWduICE9IG51bGwgPyBPYmplY3QuYXNzaWduLmJpbmQoT2JqZWN0KSA6IGZ1bmN0aW9uICh0Z3QpIHtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG5cbiAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIG9iaiA9IGFyZ3NbaV07XG5cbiAgICBpZiAob2JqID09IG51bGwpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIGsgPSBrZXlzW2pdO1xuICAgICAgdGd0W2tdID0gb2JqW2tdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0Z3Q7XG59O1xuXG52YXIgaGV4MnR1cGxlID0gZnVuY3Rpb24gaGV4MnR1cGxlKGhleCkge1xuICBpZiAoIShoZXgubGVuZ3RoID09PSA0IHx8IGhleC5sZW5ndGggPT09IDcpIHx8IGhleFswXSAhPT0gJyMnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHNob3J0SGV4ID0gaGV4Lmxlbmd0aCA9PT0gNDtcbiAgdmFyIHIsIGcsIGI7XG4gIHZhciBiYXNlID0gMTY7XG5cbiAgaWYgKHNob3J0SGV4KSB7XG4gICAgciA9IHBhcnNlSW50KGhleFsxXSArIGhleFsxXSwgYmFzZSk7XG4gICAgZyA9IHBhcnNlSW50KGhleFsyXSArIGhleFsyXSwgYmFzZSk7XG4gICAgYiA9IHBhcnNlSW50KGhleFszXSArIGhleFszXSwgYmFzZSk7XG4gIH0gZWxzZSB7XG4gICAgciA9IHBhcnNlSW50KGhleFsxXSArIGhleFsyXSwgYmFzZSk7XG4gICAgZyA9IHBhcnNlSW50KGhleFszXSArIGhleFs0XSwgYmFzZSk7XG4gICAgYiA9IHBhcnNlSW50KGhleFs1XSArIGhleFs2XSwgYmFzZSk7XG4gIH1cblxuICByZXR1cm4gW3IsIGcsIGJdO1xufTsgLy8gZ2V0IFtyLCBnLCBiLCBhXSBmcm9tIGhzbCgwLCAwLCAwKSBvciBoc2xhKDAsIDAsIDAsIDApXG5cbnZhciBoc2wydHVwbGUgPSBmdW5jdGlvbiBoc2wydHVwbGUoaHNsKSB7XG4gIHZhciByZXQ7XG4gIHZhciBoLCBzLCBsLCBhLCByLCBnLCBiO1xuXG4gIGZ1bmN0aW9uIGh1ZTJyZ2IocCwgcSwgdCkge1xuICAgIGlmICh0IDwgMCkgdCArPSAxO1xuICAgIGlmICh0ID4gMSkgdCAtPSAxO1xuICAgIGlmICh0IDwgMSAvIDYpIHJldHVybiBwICsgKHEgLSBwKSAqIDYgKiB0O1xuICAgIGlmICh0IDwgMSAvIDIpIHJldHVybiBxO1xuICAgIGlmICh0IDwgMiAvIDMpIHJldHVybiBwICsgKHEgLSBwKSAqICgyIC8gMyAtIHQpICogNjtcbiAgICByZXR1cm4gcDtcbiAgfVxuXG4gIHZhciBtID0gbmV3IFJlZ0V4cCgnXicgKyBoc2xhICsgJyQnKS5leGVjKGhzbCk7XG5cbiAgaWYgKG0pIHtcbiAgICAvLyBnZXQgaHVlXG4gICAgaCA9IHBhcnNlSW50KG1bMV0pO1xuXG4gICAgaWYgKGggPCAwKSB7XG4gICAgICBoID0gKDM2MCAtIC0xICogaCAlIDM2MCkgJSAzNjA7XG4gICAgfSBlbHNlIGlmIChoID4gMzYwKSB7XG4gICAgICBoID0gaCAlIDM2MDtcbiAgICB9XG5cbiAgICBoIC89IDM2MDsgLy8gbm9ybWFsaXNlIG9uIFswLCAxXVxuXG4gICAgcyA9IHBhcnNlRmxvYXQobVsyXSk7XG5cbiAgICBpZiAocyA8IDAgfHwgcyA+IDEwMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gc2F0dXJhdGlvbiBpcyBbMCwgMTAwXVxuXG5cbiAgICBzID0gcyAvIDEwMDsgLy8gbm9ybWFsaXNlIG9uIFswLCAxXVxuXG4gICAgbCA9IHBhcnNlRmxvYXQobVszXSk7XG5cbiAgICBpZiAobCA8IDAgfHwgbCA+IDEwMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gbGlnaHRuZXNzIGlzIFswLCAxMDBdXG5cblxuICAgIGwgPSBsIC8gMTAwOyAvLyBub3JtYWxpc2Ugb24gWzAsIDFdXG5cbiAgICBhID0gbVs0XTtcblxuICAgIGlmIChhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGEgPSBwYXJzZUZsb2F0KGEpO1xuXG4gICAgICBpZiAoYSA8IDAgfHwgYSA+IDEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBhbHBoYSBpcyBbMCwgMV1cblxuICAgIH0gLy8gbm93LCBjb252ZXJ0IHRvIHJnYlxuICAgIC8vIGNvZGUgZnJvbSBodHRwOi8vbWppamFja3Nvbi5jb20vMjAwOC8wMi9yZ2ItdG8taHNsLWFuZC1yZ2ItdG8taHN2LWNvbG9yLW1vZGVsLWNvbnZlcnNpb24tYWxnb3JpdGhtcy1pbi1qYXZhc2NyaXB0XG5cblxuICAgIGlmIChzID09PSAwKSB7XG4gICAgICByID0gZyA9IGIgPSBNYXRoLnJvdW5kKGwgKiAyNTUpOyAvLyBhY2hyb21hdGljXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBxID0gbCA8IDAuNSA/IGwgKiAoMSArIHMpIDogbCArIHMgLSBsICogcztcbiAgICAgIHZhciBwID0gMiAqIGwgLSBxO1xuICAgICAgciA9IE1hdGgucm91bmQoMjU1ICogaHVlMnJnYihwLCBxLCBoICsgMSAvIDMpKTtcbiAgICAgIGcgPSBNYXRoLnJvdW5kKDI1NSAqIGh1ZTJyZ2IocCwgcSwgaCkpO1xuICAgICAgYiA9IE1hdGgucm91bmQoMjU1ICogaHVlMnJnYihwLCBxLCBoIC0gMSAvIDMpKTtcbiAgICB9XG5cbiAgICByZXQgPSBbciwgZywgYiwgYV07XG4gIH1cblxuICByZXR1cm4gcmV0O1xufTsgLy8gZ2V0IFtyLCBnLCBiLCBhXSBmcm9tIHJnYigwLCAwLCAwKSBvciByZ2JhKDAsIDAsIDAsIDApXG5cbnZhciByZ2IydHVwbGUgPSBmdW5jdGlvbiByZ2IydHVwbGUocmdiKSB7XG4gIHZhciByZXQ7XG4gIHZhciBtID0gbmV3IFJlZ0V4cCgnXicgKyByZ2JhICsgJyQnKS5leGVjKHJnYik7XG5cbiAgaWYgKG0pIHtcbiAgICByZXQgPSBbXTtcbiAgICB2YXIgaXNQY3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IDM7IGkrKykge1xuICAgICAgdmFyIGNoYW5uZWwgPSBtW2ldO1xuXG4gICAgICBpZiAoY2hhbm5lbFtjaGFubmVsLmxlbmd0aCAtIDFdID09PSAnJScpIHtcbiAgICAgICAgaXNQY3RbaV0gPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBjaGFubmVsID0gcGFyc2VGbG9hdChjaGFubmVsKTtcblxuICAgICAgaWYgKGlzUGN0W2ldKSB7XG4gICAgICAgIGNoYW5uZWwgPSBjaGFubmVsIC8gMTAwICogMjU1OyAvLyBub3JtYWxpc2UgdG8gWzAsIDI1NV1cbiAgICAgIH1cblxuICAgICAgaWYgKGNoYW5uZWwgPCAwIHx8IGNoYW5uZWwgPiAyNTUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBpbnZhbGlkIGNoYW5uZWwgdmFsdWVcblxuXG4gICAgICByZXQucHVzaChNYXRoLmZsb29yKGNoYW5uZWwpKTtcbiAgICB9XG5cbiAgICB2YXIgYXRMZWFzdE9uZUlzUGN0ID0gaXNQY3RbMV0gfHwgaXNQY3RbMl0gfHwgaXNQY3RbM107XG4gICAgdmFyIGFsbEFyZVBjdCA9IGlzUGN0WzFdICYmIGlzUGN0WzJdICYmIGlzUGN0WzNdO1xuXG4gICAgaWYgKGF0TGVhc3RPbmVJc1BjdCAmJiAhYWxsQXJlUGN0KSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyBtdXN0IGFsbCBiZSBwZXJjZW50IHZhbHVlcyBpZiBvbmUgaXNcblxuXG4gICAgdmFyIGFscGhhID0gbVs0XTtcblxuICAgIGlmIChhbHBoYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBhbHBoYSA9IHBhcnNlRmxvYXQoYWxwaGEpO1xuXG4gICAgICBpZiAoYWxwaGEgPCAwIHx8IGFscGhhID4gMSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIGludmFsaWQgYWxwaGEgdmFsdWVcblxuXG4gICAgICByZXQucHVzaChhbHBoYSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn07XG52YXIgY29sb3JuYW1lMnR1cGxlID0gZnVuY3Rpb24gY29sb3JuYW1lMnR1cGxlKGNvbG9yKSB7XG4gIHJldHVybiBjb2xvcnNbY29sb3IudG9Mb3dlckNhc2UoKV07XG59O1xudmFyIGNvbG9yMnR1cGxlID0gZnVuY3Rpb24gY29sb3IydHVwbGUoY29sb3IpIHtcbiAgcmV0dXJuIChhcnJheShjb2xvcikgPyBjb2xvciA6IG51bGwpIHx8IGNvbG9ybmFtZTJ0dXBsZShjb2xvcikgfHwgaGV4MnR1cGxlKGNvbG9yKSB8fCByZ2IydHVwbGUoY29sb3IpIHx8IGhzbDJ0dXBsZShjb2xvcik7XG59O1xudmFyIGNvbG9ycyA9IHtcbiAgLy8gc3BlY2lhbCBjb2xvdXIgbmFtZXNcbiAgdHJhbnNwYXJlbnQ6IFswLCAwLCAwLCAwXSxcbiAgLy8gTkIgYWxwaGEgPT09IDBcbiAgLy8gcmVndWxhciBjb2xvdXJzXG4gIGFsaWNlYmx1ZTogWzI0MCwgMjQ4LCAyNTVdLFxuICBhbnRpcXVld2hpdGU6IFsyNTAsIDIzNSwgMjE1XSxcbiAgYXF1YTogWzAsIDI1NSwgMjU1XSxcbiAgYXF1YW1hcmluZTogWzEyNywgMjU1LCAyMTJdLFxuICBhenVyZTogWzI0MCwgMjU1LCAyNTVdLFxuICBiZWlnZTogWzI0NSwgMjQ1LCAyMjBdLFxuICBiaXNxdWU6IFsyNTUsIDIyOCwgMTk2XSxcbiAgYmxhY2s6IFswLCAwLCAwXSxcbiAgYmxhbmNoZWRhbG1vbmQ6IFsyNTUsIDIzNSwgMjA1XSxcbiAgYmx1ZTogWzAsIDAsIDI1NV0sXG4gIGJsdWV2aW9sZXQ6IFsxMzgsIDQzLCAyMjZdLFxuICBicm93bjogWzE2NSwgNDIsIDQyXSxcbiAgYnVybHl3b29kOiBbMjIyLCAxODQsIDEzNV0sXG4gIGNhZGV0Ymx1ZTogWzk1LCAxNTgsIDE2MF0sXG4gIGNoYXJ0cmV1c2U6IFsxMjcsIDI1NSwgMF0sXG4gIGNob2NvbGF0ZTogWzIxMCwgMTA1LCAzMF0sXG4gIGNvcmFsOiBbMjU1LCAxMjcsIDgwXSxcbiAgY29ybmZsb3dlcmJsdWU6IFsxMDAsIDE0OSwgMjM3XSxcbiAgY29ybnNpbGs6IFsyNTUsIDI0OCwgMjIwXSxcbiAgY3JpbXNvbjogWzIyMCwgMjAsIDYwXSxcbiAgY3lhbjogWzAsIDI1NSwgMjU1XSxcbiAgZGFya2JsdWU6IFswLCAwLCAxMzldLFxuICBkYXJrY3lhbjogWzAsIDEzOSwgMTM5XSxcbiAgZGFya2dvbGRlbnJvZDogWzE4NCwgMTM0LCAxMV0sXG4gIGRhcmtncmF5OiBbMTY5LCAxNjksIDE2OV0sXG4gIGRhcmtncmVlbjogWzAsIDEwMCwgMF0sXG4gIGRhcmtncmV5OiBbMTY5LCAxNjksIDE2OV0sXG4gIGRhcmtraGFraTogWzE4OSwgMTgzLCAxMDddLFxuICBkYXJrbWFnZW50YTogWzEzOSwgMCwgMTM5XSxcbiAgZGFya29saXZlZ3JlZW46IFs4NSwgMTA3LCA0N10sXG4gIGRhcmtvcmFuZ2U6IFsyNTUsIDE0MCwgMF0sXG4gIGRhcmtvcmNoaWQ6IFsxNTMsIDUwLCAyMDRdLFxuICBkYXJrcmVkOiBbMTM5LCAwLCAwXSxcbiAgZGFya3NhbG1vbjogWzIzMywgMTUwLCAxMjJdLFxuICBkYXJrc2VhZ3JlZW46IFsxNDMsIDE4OCwgMTQzXSxcbiAgZGFya3NsYXRlYmx1ZTogWzcyLCA2MSwgMTM5XSxcbiAgZGFya3NsYXRlZ3JheTogWzQ3LCA3OSwgNzldLFxuICBkYXJrc2xhdGVncmV5OiBbNDcsIDc5LCA3OV0sXG4gIGRhcmt0dXJxdW9pc2U6IFswLCAyMDYsIDIwOV0sXG4gIGRhcmt2aW9sZXQ6IFsxNDgsIDAsIDIxMV0sXG4gIGRlZXBwaW5rOiBbMjU1LCAyMCwgMTQ3XSxcbiAgZGVlcHNreWJsdWU6IFswLCAxOTEsIDI1NV0sXG4gIGRpbWdyYXk6IFsxMDUsIDEwNSwgMTA1XSxcbiAgZGltZ3JleTogWzEwNSwgMTA1LCAxMDVdLFxuICBkb2RnZXJibHVlOiBbMzAsIDE0NCwgMjU1XSxcbiAgZmlyZWJyaWNrOiBbMTc4LCAzNCwgMzRdLFxuICBmbG9yYWx3aGl0ZTogWzI1NSwgMjUwLCAyNDBdLFxuICBmb3Jlc3RncmVlbjogWzM0LCAxMzksIDM0XSxcbiAgZnVjaHNpYTogWzI1NSwgMCwgMjU1XSxcbiAgZ2FpbnNib3JvOiBbMjIwLCAyMjAsIDIyMF0sXG4gIGdob3N0d2hpdGU6IFsyNDgsIDI0OCwgMjU1XSxcbiAgZ29sZDogWzI1NSwgMjE1LCAwXSxcbiAgZ29sZGVucm9kOiBbMjE4LCAxNjUsIDMyXSxcbiAgZ3JheTogWzEyOCwgMTI4LCAxMjhdLFxuICBncmV5OiBbMTI4LCAxMjgsIDEyOF0sXG4gIGdyZWVuOiBbMCwgMTI4LCAwXSxcbiAgZ3JlZW55ZWxsb3c6IFsxNzMsIDI1NSwgNDddLFxuICBob25leWRldzogWzI0MCwgMjU1LCAyNDBdLFxuICBob3RwaW5rOiBbMjU1LCAxMDUsIDE4MF0sXG4gIGluZGlhbnJlZDogWzIwNSwgOTIsIDkyXSxcbiAgaW5kaWdvOiBbNzUsIDAsIDEzMF0sXG4gIGl2b3J5OiBbMjU1LCAyNTUsIDI0MF0sXG4gIGtoYWtpOiBbMjQwLCAyMzAsIDE0MF0sXG4gIGxhdmVuZGVyOiBbMjMwLCAyMzAsIDI1MF0sXG4gIGxhdmVuZGVyYmx1c2g6IFsyNTUsIDI0MCwgMjQ1XSxcbiAgbGF3bmdyZWVuOiBbMTI0LCAyNTIsIDBdLFxuICBsZW1vbmNoaWZmb246IFsyNTUsIDI1MCwgMjA1XSxcbiAgbGlnaHRibHVlOiBbMTczLCAyMTYsIDIzMF0sXG4gIGxpZ2h0Y29yYWw6IFsyNDAsIDEyOCwgMTI4XSxcbiAgbGlnaHRjeWFuOiBbMjI0LCAyNTUsIDI1NV0sXG4gIGxpZ2h0Z29sZGVucm9keWVsbG93OiBbMjUwLCAyNTAsIDIxMF0sXG4gIGxpZ2h0Z3JheTogWzIxMSwgMjExLCAyMTFdLFxuICBsaWdodGdyZWVuOiBbMTQ0LCAyMzgsIDE0NF0sXG4gIGxpZ2h0Z3JleTogWzIxMSwgMjExLCAyMTFdLFxuICBsaWdodHBpbms6IFsyNTUsIDE4MiwgMTkzXSxcbiAgbGlnaHRzYWxtb246IFsyNTUsIDE2MCwgMTIyXSxcbiAgbGlnaHRzZWFncmVlbjogWzMyLCAxNzgsIDE3MF0sXG4gIGxpZ2h0c2t5Ymx1ZTogWzEzNSwgMjA2LCAyNTBdLFxuICBsaWdodHNsYXRlZ3JheTogWzExOSwgMTM2LCAxNTNdLFxuICBsaWdodHNsYXRlZ3JleTogWzExOSwgMTM2LCAxNTNdLFxuICBsaWdodHN0ZWVsYmx1ZTogWzE3NiwgMTk2LCAyMjJdLFxuICBsaWdodHllbGxvdzogWzI1NSwgMjU1LCAyMjRdLFxuICBsaW1lOiBbMCwgMjU1LCAwXSxcbiAgbGltZWdyZWVuOiBbNTAsIDIwNSwgNTBdLFxuICBsaW5lbjogWzI1MCwgMjQwLCAyMzBdLFxuICBtYWdlbnRhOiBbMjU1LCAwLCAyNTVdLFxuICBtYXJvb246IFsxMjgsIDAsIDBdLFxuICBtZWRpdW1hcXVhbWFyaW5lOiBbMTAyLCAyMDUsIDE3MF0sXG4gIG1lZGl1bWJsdWU6IFswLCAwLCAyMDVdLFxuICBtZWRpdW1vcmNoaWQ6IFsxODYsIDg1LCAyMTFdLFxuICBtZWRpdW1wdXJwbGU6IFsxNDcsIDExMiwgMjE5XSxcbiAgbWVkaXVtc2VhZ3JlZW46IFs2MCwgMTc5LCAxMTNdLFxuICBtZWRpdW1zbGF0ZWJsdWU6IFsxMjMsIDEwNCwgMjM4XSxcbiAgbWVkaXVtc3ByaW5nZ3JlZW46IFswLCAyNTAsIDE1NF0sXG4gIG1lZGl1bXR1cnF1b2lzZTogWzcyLCAyMDksIDIwNF0sXG4gIG1lZGl1bXZpb2xldHJlZDogWzE5OSwgMjEsIDEzM10sXG4gIG1pZG5pZ2h0Ymx1ZTogWzI1LCAyNSwgMTEyXSxcbiAgbWludGNyZWFtOiBbMjQ1LCAyNTUsIDI1MF0sXG4gIG1pc3R5cm9zZTogWzI1NSwgMjI4LCAyMjVdLFxuICBtb2NjYXNpbjogWzI1NSwgMjI4LCAxODFdLFxuICBuYXZham93aGl0ZTogWzI1NSwgMjIyLCAxNzNdLFxuICBuYXZ5OiBbMCwgMCwgMTI4XSxcbiAgb2xkbGFjZTogWzI1MywgMjQ1LCAyMzBdLFxuICBvbGl2ZTogWzEyOCwgMTI4LCAwXSxcbiAgb2xpdmVkcmFiOiBbMTA3LCAxNDIsIDM1XSxcbiAgb3JhbmdlOiBbMjU1LCAxNjUsIDBdLFxuICBvcmFuZ2VyZWQ6IFsyNTUsIDY5LCAwXSxcbiAgb3JjaGlkOiBbMjE4LCAxMTIsIDIxNF0sXG4gIHBhbGVnb2xkZW5yb2Q6IFsyMzgsIDIzMiwgMTcwXSxcbiAgcGFsZWdyZWVuOiBbMTUyLCAyNTEsIDE1Ml0sXG4gIHBhbGV0dXJxdW9pc2U6IFsxNzUsIDIzOCwgMjM4XSxcbiAgcGFsZXZpb2xldHJlZDogWzIxOSwgMTEyLCAxNDddLFxuICBwYXBheWF3aGlwOiBbMjU1LCAyMzksIDIxM10sXG4gIHBlYWNocHVmZjogWzI1NSwgMjE4LCAxODVdLFxuICBwZXJ1OiBbMjA1LCAxMzMsIDYzXSxcbiAgcGluazogWzI1NSwgMTkyLCAyMDNdLFxuICBwbHVtOiBbMjIxLCAxNjAsIDIyMV0sXG4gIHBvd2RlcmJsdWU6IFsxNzYsIDIyNCwgMjMwXSxcbiAgcHVycGxlOiBbMTI4LCAwLCAxMjhdLFxuICByZWQ6IFsyNTUsIDAsIDBdLFxuICByb3N5YnJvd246IFsxODgsIDE0MywgMTQzXSxcbiAgcm95YWxibHVlOiBbNjUsIDEwNSwgMjI1XSxcbiAgc2FkZGxlYnJvd246IFsxMzksIDY5LCAxOV0sXG4gIHNhbG1vbjogWzI1MCwgMTI4LCAxMTRdLFxuICBzYW5keWJyb3duOiBbMjQ0LCAxNjQsIDk2XSxcbiAgc2VhZ3JlZW46IFs0NiwgMTM5LCA4N10sXG4gIHNlYXNoZWxsOiBbMjU1LCAyNDUsIDIzOF0sXG4gIHNpZW5uYTogWzE2MCwgODIsIDQ1XSxcbiAgc2lsdmVyOiBbMTkyLCAxOTIsIDE5Ml0sXG4gIHNreWJsdWU6IFsxMzUsIDIwNiwgMjM1XSxcbiAgc2xhdGVibHVlOiBbMTA2LCA5MCwgMjA1XSxcbiAgc2xhdGVncmF5OiBbMTEyLCAxMjgsIDE0NF0sXG4gIHNsYXRlZ3JleTogWzExMiwgMTI4LCAxNDRdLFxuICBzbm93OiBbMjU1LCAyNTAsIDI1MF0sXG4gIHNwcmluZ2dyZWVuOiBbMCwgMjU1LCAxMjddLFxuICBzdGVlbGJsdWU6IFs3MCwgMTMwLCAxODBdLFxuICB0YW46IFsyMTAsIDE4MCwgMTQwXSxcbiAgdGVhbDogWzAsIDEyOCwgMTI4XSxcbiAgdGhpc3RsZTogWzIxNiwgMTkxLCAyMTZdLFxuICB0b21hdG86IFsyNTUsIDk5LCA3MV0sXG4gIHR1cnF1b2lzZTogWzY0LCAyMjQsIDIwOF0sXG4gIHZpb2xldDogWzIzOCwgMTMwLCAyMzhdLFxuICB3aGVhdDogWzI0NSwgMjIyLCAxNzldLFxuICB3aGl0ZTogWzI1NSwgMjU1LCAyNTVdLFxuICB3aGl0ZXNtb2tlOiBbMjQ1LCAyNDUsIDI0NV0sXG4gIHllbGxvdzogWzI1NSwgMjU1LCAwXSxcbiAgeWVsbG93Z3JlZW46IFsxNTQsIDIwNSwgNTBdXG59O1xuXG52YXIgc2V0TWFwID0gZnVuY3Rpb24gc2V0TWFwKG9wdGlvbnMpIHtcbiAgdmFyIG9iaiA9IG9wdGlvbnMubWFwO1xuICB2YXIga2V5cyA9IG9wdGlvbnMua2V5cztcbiAgdmFyIGwgPSBrZXlzLmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuXG4gICAgaWYgKHBsYWluT2JqZWN0KGtleSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdUcmllZCB0byBzZXQgbWFwIHdpdGggb2JqZWN0IGtleScpO1xuICAgIH1cblxuICAgIGlmIChpIDwga2V5cy5sZW5ndGggLSAxKSB7XG4gICAgICAvLyBleHRlbmQgdGhlIG1hcCBpZiBuZWNlc3NhcnlcbiAgICAgIGlmIChvYmpba2V5XSA9PSBudWxsKSB7XG4gICAgICAgIG9ialtrZXldID0ge307XG4gICAgICB9XG5cbiAgICAgIG9iaiA9IG9ialtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBzZXQgdGhlIHZhbHVlXG4gICAgICBvYmpba2V5XSA9IG9wdGlvbnMudmFsdWU7XG4gICAgfVxuICB9XG59OyAvLyBnZXRzIHRoZSB2YWx1ZSBpbiBhIG1hcCBldmVuIGlmIGl0J3Mgbm90IGJ1aWx0IGluIHBsYWNlc1xuXG52YXIgZ2V0TWFwID0gZnVuY3Rpb24gZ2V0TWFwKG9wdGlvbnMpIHtcbiAgdmFyIG9iaiA9IG9wdGlvbnMubWFwO1xuICB2YXIga2V5cyA9IG9wdGlvbnMua2V5cztcbiAgdmFyIGwgPSBrZXlzLmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuXG4gICAgaWYgKHBsYWluT2JqZWN0KGtleSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdUcmllZCB0byBnZXQgbWFwIHdpdGggb2JqZWN0IGtleScpO1xuICAgIH1cblxuICAgIG9iaiA9IG9ialtrZXldO1xuXG4gICAgaWYgKG9iaiA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gb2JqO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvYmo7XG59OyAvLyBkZWxldGVzIHRoZSBlbnRyeSBpbiB0aGUgbWFwXG5cbnZhciBwZXJmb3JtYW5jZSA9IHdpbmRvdyQxID8gd2luZG93JDEucGVyZm9ybWFuY2UgOiBudWxsO1xudmFyIHBub3cgPSBwZXJmb3JtYW5jZSAmJiBwZXJmb3JtYW5jZS5ub3cgPyBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBwZXJmb3JtYW5jZS5ub3coKTtcbn0gOiBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBEYXRlLm5vdygpO1xufTtcblxudmFyIHJhZiA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKHdpbmRvdyQxKSB7XG4gICAgaWYgKHdpbmRvdyQxLnJlcXVlc3RBbmltYXRpb25GcmFtZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIChmbikge1xuICAgICAgICB3aW5kb3ckMS5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZm4pO1xuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKHdpbmRvdyQxLm1velJlcXVlc3RBbmltYXRpb25GcmFtZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIChmbikge1xuICAgICAgICB3aW5kb3ckMS5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZm4pO1xuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKHdpbmRvdyQxLndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIChmbikge1xuICAgICAgICB3aW5kb3ckMS53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZm4pO1xuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKHdpbmRvdyQxLm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgIHdpbmRvdyQxLm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZuKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChmbikge1xuICAgIGlmIChmbikge1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZuKHBub3coKSk7XG4gICAgICB9LCAxMDAwIC8gNjApO1xuICAgIH1cbiAgfTtcbn0oKTtcblxudmFyIHJlcXVlc3RBbmltYXRpb25GcmFtZSA9IGZ1bmN0aW9uIHJlcXVlc3RBbmltYXRpb25GcmFtZShmbikge1xuICByZXR1cm4gcmFmKGZuKTtcbn07XG52YXIgcGVyZm9ybWFuY2VOb3cgPSBwbm93O1xuXG52YXIgREVGQVVMVF9IQVNIX1NFRUQgPSA5MjYxO1xudmFyIEsgPSA2NTU5OTsgLy8gMzcgYWxzbyB3b3JrcyBwcmV0dHkgd2VsbFxuXG52YXIgREVGQVVMVF9IQVNIX1NFRURfQUxUID0gNTM4MTtcbnZhciBoYXNoSXRlcmFibGVJbnRzID0gZnVuY3Rpb24gaGFzaEl0ZXJhYmxlSW50cyhpdGVyYXRvcikge1xuICB2YXIgc2VlZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogREVGQVVMVF9IQVNIX1NFRUQ7XG4gIC8vIHNkYm0vc3RyaW5nLWhhc2hcbiAgdmFyIGhhc2ggPSBzZWVkO1xuICB2YXIgZW50cnk7XG5cbiAgZm9yICg7Oykge1xuICAgIGVudHJ5ID0gaXRlcmF0b3IubmV4dCgpO1xuXG4gICAgaWYgKGVudHJ5LmRvbmUpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGhhc2ggPSBoYXNoICogSyArIGVudHJ5LnZhbHVlIHwgMDtcbiAgfVxuXG4gIHJldHVybiBoYXNoO1xufTtcbnZhciBoYXNoSW50ID0gZnVuY3Rpb24gaGFzaEludChudW0pIHtcbiAgdmFyIHNlZWQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IERFRkFVTFRfSEFTSF9TRUVEO1xuICAvLyBzZGJtL3N0cmluZy1oYXNoXG4gIHJldHVybiBzZWVkICogSyArIG51bSB8IDA7XG59O1xudmFyIGhhc2hJbnRBbHQgPSBmdW5jdGlvbiBoYXNoSW50QWx0KG51bSkge1xuICB2YXIgc2VlZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogREVGQVVMVF9IQVNIX1NFRURfQUxUO1xuICAvLyBkamIyL3N0cmluZy1oYXNoXG4gIHJldHVybiAoc2VlZCA8PCA1KSArIHNlZWQgKyBudW0gfCAwO1xufTtcbnZhciBjb21iaW5lSGFzaGVzID0gZnVuY3Rpb24gY29tYmluZUhhc2hlcyhoYXNoMSwgaGFzaDIpIHtcbiAgcmV0dXJuIGhhc2gxICogMHgyMDAwMDAgKyBoYXNoMjtcbn07XG52YXIgY29tYmluZUhhc2hlc0FycmF5ID0gZnVuY3Rpb24gY29tYmluZUhhc2hlc0FycmF5KGhhc2hlcykge1xuICByZXR1cm4gaGFzaGVzWzBdICogMHgyMDAwMDAgKyBoYXNoZXNbMV07XG59O1xudmFyIGhhc2hBcnJheXMgPSBmdW5jdGlvbiBoYXNoQXJyYXlzKGhhc2hlczEsIGhhc2hlczIpIHtcbiAgcmV0dXJuIFtoYXNoSW50KGhhc2hlczFbMF0sIGhhc2hlczJbMF0pLCBoYXNoSW50QWx0KGhhc2hlczFbMV0sIGhhc2hlczJbMV0pXTtcbn07XG52YXIgaGFzaEludHNBcnJheSA9IGZ1bmN0aW9uIGhhc2hJbnRzQXJyYXkoaW50cywgc2VlZCkge1xuICB2YXIgZW50cnkgPSB7XG4gICAgdmFsdWU6IDAsXG4gICAgZG9uZTogZmFsc2VcbiAgfTtcbiAgdmFyIGkgPSAwO1xuICB2YXIgbGVuZ3RoID0gaW50cy5sZW5ndGg7XG4gIHZhciBpdGVyYXRvciA9IHtcbiAgICBuZXh0OiBmdW5jdGlvbiBuZXh0KCkge1xuICAgICAgaWYgKGkgPCBsZW5ndGgpIHtcbiAgICAgICAgZW50cnkudmFsdWUgPSBpbnRzW2krK107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbnRyeS5kb25lID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGVudHJ5O1xuICAgIH1cbiAgfTtcbiAgcmV0dXJuIGhhc2hJdGVyYWJsZUludHMoaXRlcmF0b3IsIHNlZWQpO1xufTtcbnZhciBoYXNoU3RyaW5nID0gZnVuY3Rpb24gaGFzaFN0cmluZyhzdHIsIHNlZWQpIHtcbiAgdmFyIGVudHJ5ID0ge1xuICAgIHZhbHVlOiAwLFxuICAgIGRvbmU6IGZhbHNlXG4gIH07XG4gIHZhciBpID0gMDtcbiAgdmFyIGxlbmd0aCA9IHN0ci5sZW5ndGg7XG4gIHZhciBpdGVyYXRvciA9IHtcbiAgICBuZXh0OiBmdW5jdGlvbiBuZXh0KCkge1xuICAgICAgaWYgKGkgPCBsZW5ndGgpIHtcbiAgICAgICAgZW50cnkudmFsdWUgPSBzdHIuY2hhckNvZGVBdChpKyspO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW50cnkuZG9uZSA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBlbnRyeTtcbiAgICB9XG4gIH07XG4gIHJldHVybiBoYXNoSXRlcmFibGVJbnRzKGl0ZXJhdG9yLCBzZWVkKTtcbn07XG52YXIgaGFzaFN0cmluZ3MgPSBmdW5jdGlvbiBoYXNoU3RyaW5ncygpIHtcbiAgcmV0dXJuIGhhc2hTdHJpbmdzQXJyYXkoYXJndW1lbnRzKTtcbn07XG52YXIgaGFzaFN0cmluZ3NBcnJheSA9IGZ1bmN0aW9uIGhhc2hTdHJpbmdzQXJyYXkoc3Rycykge1xuICB2YXIgaGFzaDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgc3RyID0gc3Ryc1tpXTtcblxuICAgIGlmIChpID09PSAwKSB7XG4gICAgICBoYXNoID0gaGFzaFN0cmluZyhzdHIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBoYXNoID0gaGFzaFN0cmluZyhzdHIsIGhhc2gpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBoYXNoO1xufTtcblxuLypnbG9iYWwgY29uc29sZSAqL1xudmFyIHdhcm5pbmdzRW5hYmxlZCA9IHRydWU7XG52YXIgd2FyblN1cHBvcnRlZCA9IGNvbnNvbGUud2FybiAhPSBudWxsOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcblxudmFyIHRyYWNlU3VwcG9ydGVkID0gY29uc29sZS50cmFjZSAhPSBudWxsOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcblxudmFyIE1BWF9JTlQgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiB8fCA5MDA3MTk5MjU0NzQwOTkxO1xudmFyIHRydWVpZnkgPSBmdW5jdGlvbiB0cnVlaWZ5KCkge1xuICByZXR1cm4gdHJ1ZTtcbn07XG52YXIgZmFsc2lmeSA9IGZ1bmN0aW9uIGZhbHNpZnkoKSB7XG4gIHJldHVybiBmYWxzZTtcbn07XG52YXIgemVyb2lmeSA9IGZ1bmN0aW9uIHplcm9pZnkoKSB7XG4gIHJldHVybiAwO1xufTtcbnZhciBub29wID0gZnVuY3Rpb24gbm9vcCgpIHt9O1xudmFyIGVycm9yID0gZnVuY3Rpb24gZXJyb3IobXNnKSB7XG4gIHRocm93IG5ldyBFcnJvcihtc2cpO1xufTtcbnZhciB3YXJuaW5ncyA9IGZ1bmN0aW9uIHdhcm5pbmdzKGVuYWJsZWQpIHtcbiAgaWYgKGVuYWJsZWQgIT09IHVuZGVmaW5lZCkge1xuICAgIHdhcm5pbmdzRW5hYmxlZCA9ICEhZW5hYmxlZDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gd2FybmluZ3NFbmFibGVkO1xuICB9XG59O1xudmFyIHdhcm4gPSBmdW5jdGlvbiB3YXJuKG1zZykge1xuICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG4gIGlmICghd2FybmluZ3MoKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICh3YXJuU3VwcG9ydGVkKSB7XG4gICAgY29uc29sZS53YXJuKG1zZyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5sb2cobXNnKTtcblxuICAgIGlmICh0cmFjZVN1cHBvcnRlZCkge1xuICAgICAgY29uc29sZS50cmFjZSgpO1xuICAgIH1cbiAgfVxufTtcbi8qIGVzbGludC1lbmFibGUgKi9cblxudmFyIGNsb25lID0gZnVuY3Rpb24gY2xvbmUob2JqKSB7XG4gIHJldHVybiBleHRlbmQoe30sIG9iaik7XG59OyAvLyBnZXRzIGEgc2hhbGxvdyBjb3B5IG9mIHRoZSBhcmd1bWVudFxuXG52YXIgY29weSA9IGZ1bmN0aW9uIGNvcHkob2JqKSB7XG4gIGlmIChvYmogPT0gbnVsbCkge1xuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICBpZiAoYXJyYXkob2JqKSkge1xuICAgIHJldHVybiBvYmouc2xpY2UoKTtcbiAgfSBlbHNlIGlmIChwbGFpbk9iamVjdChvYmopKSB7XG4gICAgcmV0dXJuIGNsb25lKG9iaik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxufTtcbnZhciBjb3B5QXJyYXkgPSBmdW5jdGlvbiBjb3B5QXJyYXkoYXJyKSB7XG4gIHJldHVybiBhcnIuc2xpY2UoKTtcbn07XG52YXIgdXVpZCA9IGZ1bmN0aW9uIHV1aWQoYSwgYlxuLyogcGxhY2Vob2xkZXJzICovXG4pIHtcbiAgZm9yICggLy8gbG9vcCA6KVxuICBiID0gYSA9ICcnOyAvLyBiIC0gcmVzdWx0ICwgYSAtIG51bWVyaWMgbGV0aWFibGVcbiAgYSsrIDwgMzY7IC8vXG4gIGIgKz0gYSAqIDUxICYgNTIgLy8gaWYgXCJhXCIgaXMgbm90IDkgb3IgMTQgb3IgMTkgb3IgMjRcbiAgPyAvLyAgcmV0dXJuIGEgcmFuZG9tIG51bWJlciBvciA0XG4gIChhIF4gMTUgLy8gaWYgXCJhXCIgaXMgbm90IDE1XG4gID8gLy8gZ2VuZXRhdGUgYSByYW5kb20gbnVtYmVyIGZyb20gMCB0byAxNVxuICA4IF4gTWF0aC5yYW5kb20oKSAqIChhIF4gMjAgPyAxNiA6IDQpIC8vIHVubGVzcyBcImFcIiBpcyAyMCwgaW4gd2hpY2ggY2FzZSBhIHJhbmRvbSBudW1iZXIgZnJvbSA4IHRvIDExXG4gIDogNCAvLyAgb3RoZXJ3aXNlIDRcbiAgKS50b1N0cmluZygxNikgOiAnLScgLy8gIGluIG90aGVyIGNhc2VzIChpZiBcImFcIiBpcyA5LDE0LDE5LDI0KSBpbnNlcnQgXCItXCJcbiAgKSB7XG4gIH1cblxuICByZXR1cm4gYjtcbn07XG52YXIgX3N0YXRpY0VtcHR5T2JqZWN0ID0ge307XG52YXIgc3RhdGljRW1wdHlPYmplY3QgPSBmdW5jdGlvbiBzdGF0aWNFbXB0eU9iamVjdCgpIHtcbiAgcmV0dXJuIF9zdGF0aWNFbXB0eU9iamVjdDtcbn07XG52YXIgZGVmYXVsdHMgPSBmdW5jdGlvbiBkZWZhdWx0cyhfZGVmYXVsdHMpIHtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhfZGVmYXVsdHMpO1xuICByZXR1cm4gZnVuY3Rpb24gKG9wdHMpIHtcbiAgICB2YXIgZmlsbGVkT3B0cyA9IHt9O1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIga2V5ID0ga2V5c1tpXTtcbiAgICAgIHZhciBvcHRWYWwgPSBvcHRzID09IG51bGwgPyB1bmRlZmluZWQgOiBvcHRzW2tleV07XG4gICAgICBmaWxsZWRPcHRzW2tleV0gPSBvcHRWYWwgPT09IHVuZGVmaW5lZCA/IF9kZWZhdWx0c1trZXldIDogb3B0VmFsO1xuICAgIH1cblxuICAgIHJldHVybiBmaWxsZWRPcHRzO1xuICB9O1xufTtcbnZhciByZW1vdmVGcm9tQXJyYXkgPSBmdW5jdGlvbiByZW1vdmVGcm9tQXJyYXkoYXJyLCBlbGUsIG1hbnlDb3BpZXMpIHtcbiAgZm9yICh2YXIgaSA9IGFyci5sZW5ndGg7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKGFycltpXSA9PT0gZWxlKSB7XG4gICAgICBhcnIuc3BsaWNlKGksIDEpO1xuXG4gICAgICBpZiAoIW1hbnlDb3BpZXMpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xudmFyIGNsZWFyQXJyYXkgPSBmdW5jdGlvbiBjbGVhckFycmF5KGFycikge1xuICBhcnIuc3BsaWNlKDAsIGFyci5sZW5ndGgpO1xufTtcbnZhciBwdXNoID0gZnVuY3Rpb24gcHVzaChhcnIsIG90aGVyQXJyKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgb3RoZXJBcnIubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWwgPSBvdGhlckFycltpXTtcbiAgICBhcnIucHVzaChlbCk7XG4gIH1cbn07XG52YXIgZ2V0UHJlZml4ZWRQcm9wZXJ0eSA9IGZ1bmN0aW9uIGdldFByZWZpeGVkUHJvcGVydHkob2JqLCBwcm9wTmFtZSwgcHJlZml4KSB7XG4gIGlmIChwcmVmaXgpIHtcbiAgICBwcm9wTmFtZSA9IHByZXBlbmRDYW1lbChwcmVmaXgsIHByb3BOYW1lKTsgLy8gZS5nLiAobGFiZWxXaWR0aCwgc291cmNlKSA9PiBzb3VyY2VMYWJlbFdpZHRoXG4gIH1cblxuICByZXR1cm4gb2JqW3Byb3BOYW1lXTtcbn07XG52YXIgc2V0UHJlZml4ZWRQcm9wZXJ0eSA9IGZ1bmN0aW9uIHNldFByZWZpeGVkUHJvcGVydHkob2JqLCBwcm9wTmFtZSwgcHJlZml4LCB2YWx1ZSkge1xuICBpZiAocHJlZml4KSB7XG4gICAgcHJvcE5hbWUgPSBwcmVwZW5kQ2FtZWwocHJlZml4LCBwcm9wTmFtZSk7IC8vIGUuZy4gKGxhYmVsV2lkdGgsIHNvdXJjZSkgPT4gc291cmNlTGFiZWxXaWR0aFxuICB9XG5cbiAgb2JqW3Byb3BOYW1lXSA9IHZhbHVlO1xufTtcblxuLyogZ2xvYmFsIE1hcCAqL1xudmFyIE9iamVjdE1hcCA9XG4vKiNfX1BVUkVfXyovXG5mdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIE9iamVjdE1hcCgpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgT2JqZWN0TWFwKTtcblxuICAgIHRoaXMuX29iaiA9IHt9O1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKE9iamVjdE1hcCwgW3tcbiAgICBrZXk6IFwic2V0XCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNldChrZXksIHZhbCkge1xuICAgICAgdGhpcy5fb2JqW2tleV0gPSB2YWw7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiZGVsZXRlXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9kZWxldGUoa2V5KSB7XG4gICAgICB0aGlzLl9vYmpba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJjbGVhclwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICAgIHRoaXMuX29iaiA9IHt9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJoYXNcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gaGFzKGtleSkge1xuICAgICAgcmV0dXJuIHRoaXMuX29ialtrZXldICE9PSB1bmRlZmluZWQ7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcImdldFwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXQoa2V5KSB7XG4gICAgICByZXR1cm4gdGhpcy5fb2JqW2tleV07XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIE9iamVjdE1hcDtcbn0oKTtcblxudmFyIE1hcCQxID0gdHlwZW9mIE1hcCAhPT0gJ3VuZGVmaW5lZCcgPyBNYXAgOiBPYmplY3RNYXA7XG5cbi8qIGdsb2JhbCBTZXQgKi9cbnZhciB1bmRlZiA9ICBcInVuZGVmaW5lZFwiIDtcblxudmFyIE9iamVjdFNldCA9XG4vKiNfX1BVUkVfXyovXG5mdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIE9iamVjdFNldChhcnJheU9yT2JqZWN0U2V0KSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIE9iamVjdFNldCk7XG5cbiAgICB0aGlzLl9vYmogPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIHRoaXMuc2l6ZSA9IDA7XG5cbiAgICBpZiAoYXJyYXlPck9iamVjdFNldCAhPSBudWxsKSB7XG4gICAgICB2YXIgYXJyO1xuXG4gICAgICBpZiAoYXJyYXlPck9iamVjdFNldC5pbnN0YW5jZVN0cmluZyAhPSBudWxsICYmIGFycmF5T3JPYmplY3RTZXQuaW5zdGFuY2VTdHJpbmcoKSA9PT0gdGhpcy5pbnN0YW5jZVN0cmluZygpKSB7XG4gICAgICAgIGFyciA9IGFycmF5T3JPYmplY3RTZXQudG9BcnJheSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXJyID0gYXJyYXlPck9iamVjdFNldDtcbiAgICAgIH1cblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5hZGQoYXJyW2ldKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoT2JqZWN0U2V0LCBbe1xuICAgIGtleTogXCJpbnN0YW5jZVN0cmluZ1wiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBpbnN0YW5jZVN0cmluZygpIHtcbiAgICAgIHJldHVybiAnc2V0JztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiYWRkXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGFkZCh2YWwpIHtcbiAgICAgIHZhciBvID0gdGhpcy5fb2JqO1xuXG4gICAgICBpZiAob1t2YWxdICE9PSAxKSB7XG4gICAgICAgIG9bdmFsXSA9IDE7XG4gICAgICAgIHRoaXMuc2l6ZSsrO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJkZWxldGVcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2RlbGV0ZSh2YWwpIHtcbiAgICAgIHZhciBvID0gdGhpcy5fb2JqO1xuXG4gICAgICBpZiAob1t2YWxdID09PSAxKSB7XG4gICAgICAgIG9bdmFsXSA9IDA7XG4gICAgICAgIHRoaXMuc2l6ZS0tO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJjbGVhclwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICAgIHRoaXMuX29iaiA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcImhhc1wiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBoYXModmFsKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb2JqW3ZhbF0gPT09IDE7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcInRvQXJyYXlcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gdG9BcnJheSgpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9vYmopLmZpbHRlcihmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHJldHVybiBfdGhpcy5oYXMoa2V5KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJmb3JFYWNoXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGZvckVhY2goY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHJldHVybiB0aGlzLnRvQXJyYXkoKS5mb3JFYWNoKGNhbGxiYWNrLCB0aGlzQXJnKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gT2JqZWN0U2V0O1xufSgpO1xuXG52YXIgU2V0JDEgPSAodHlwZW9mIFNldCA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiBfdHlwZW9mKFNldCkpICE9PSB1bmRlZiA/IFNldCA6IE9iamVjdFNldDtcblxudmFyIEVsZW1lbnQgPSBmdW5jdGlvbiBFbGVtZW50KGN5LCBwYXJhbXMsIHJlc3RvcmUpIHtcbiAgcmVzdG9yZSA9IHJlc3RvcmUgPT09IHVuZGVmaW5lZCB8fCByZXN0b3JlID8gdHJ1ZSA6IGZhbHNlO1xuXG4gIGlmIChjeSA9PT0gdW5kZWZpbmVkIHx8IHBhcmFtcyA9PT0gdW5kZWZpbmVkIHx8ICFjb3JlKGN5KSkge1xuICAgIGVycm9yKCdBbiBlbGVtZW50IG11c3QgaGF2ZSBhIGNvcmUgcmVmZXJlbmNlIGFuZCBwYXJhbWV0ZXJzIHNldCcpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBncm91cCA9IHBhcmFtcy5ncm91cDsgLy8gdHJ5IHRvIGF1dG9tYXRpY2FsbHkgaW5mZXIgdGhlIGdyb3VwIGlmIHVuc3BlY2lmaWVkXG5cbiAgaWYgKGdyb3VwID09IG51bGwpIHtcbiAgICBpZiAocGFyYW1zLmRhdGEgJiYgcGFyYW1zLmRhdGEuc291cmNlICE9IG51bGwgJiYgcGFyYW1zLmRhdGEudGFyZ2V0ICE9IG51bGwpIHtcbiAgICAgIGdyb3VwID0gJ2VkZ2VzJztcbiAgICB9IGVsc2Uge1xuICAgICAgZ3JvdXAgPSAnbm9kZXMnO1xuICAgIH1cbiAgfSAvLyB2YWxpZGF0ZSBncm91cFxuXG5cbiAgaWYgKGdyb3VwICE9PSAnbm9kZXMnICYmIGdyb3VwICE9PSAnZWRnZXMnKSB7XG4gICAgZXJyb3IoJ0FuIGVsZW1lbnQgbXVzdCBiZSBvZiB0eXBlIGBub2Rlc2Agb3IgYGVkZ2VzYDsgeW91IHNwZWNpZmllZCBgJyArIGdyb3VwICsgJ2AnKTtcbiAgICByZXR1cm47XG4gIH0gLy8gbWFrZSB0aGUgZWxlbWVudCBhcnJheS1saWtlLCBqdXN0IGxpa2UgYSBjb2xsZWN0aW9uXG5cblxuICB0aGlzLmxlbmd0aCA9IDE7XG4gIHRoaXNbMF0gPSB0aGlzOyAvLyBOT1RFOiB3aGVuIHNvbWV0aGluZyBpcyBhZGRlZCBoZXJlLCBhZGQgYWxzbyB0byBlbGUuanNvbigpXG5cbiAgdmFyIF9wID0gdGhpcy5fcHJpdmF0ZSA9IHtcbiAgICBjeTogY3ksXG4gICAgc2luZ2xlOiB0cnVlLFxuICAgIC8vIGluZGljYXRlcyB0aGlzIGlzIGFuIGVsZW1lbnRcbiAgICBkYXRhOiBwYXJhbXMuZGF0YSB8fCB7fSxcbiAgICAvLyBkYXRhIG9iamVjdFxuICAgIHBvc2l0aW9uOiBwYXJhbXMucG9zaXRpb24gfHwge1xuICAgICAgeDogMCxcbiAgICAgIHk6IDBcbiAgICB9LFxuICAgIC8vICh4LCB5KSBwb3NpdGlvbiBwYWlyXG4gICAgYXV0b1dpZHRoOiB1bmRlZmluZWQsXG4gICAgLy8gd2lkdGggYW5kIGhlaWdodCBvZiBub2RlcyBjYWxjdWxhdGVkIGJ5IHRoZSByZW5kZXJlciB3aGVuIHNldCB0byBzcGVjaWFsICdhdXRvJyB2YWx1ZVxuICAgIGF1dG9IZWlnaHQ6IHVuZGVmaW5lZCxcbiAgICBhdXRvUGFkZGluZzogdW5kZWZpbmVkLFxuICAgIGNvbXBvdW5kQm91bmRzQ2xlYW46IGZhbHNlLFxuICAgIC8vIHdoZXRoZXIgdGhlIGNvbXBvdW5kIGRpbWVuc2lvbnMgbmVlZCB0byBiZSByZWNhbGN1bGF0ZWQgdGhlIG5leHQgdGltZSBkaW1lbnNpb25zIGFyZSByZWFkXG4gICAgbGlzdGVuZXJzOiBbXSxcbiAgICAvLyBhcnJheSBvZiBib3VuZCBsaXN0ZW5lcnNcbiAgICBncm91cDogZ3JvdXAsXG4gICAgLy8gc3RyaW5nOyAnbm9kZXMnIG9yICdlZGdlcydcbiAgICBzdHlsZToge30sXG4gICAgLy8gcHJvcGVydGllcyBhcyBzZXQgYnkgdGhlIHN0eWxlXG4gICAgcnN0eWxlOiB7fSxcbiAgICAvLyBwcm9wZXJ0aWVzIGZvciBzdHlsZSBzZW50IGZyb20gdGhlIHJlbmRlcmVyIHRvIHRoZSBjb3JlXG4gICAgc3R5bGVDeHRzOiBbXSxcbiAgICAvLyBhcHBsaWVkIHN0eWxlIGNvbnRleHRzIGZyb20gdGhlIHN0eWxlclxuICAgIHN0eWxlS2V5czoge30sXG4gICAgLy8gcGVyLWdyb3VwIGtleXMgb2Ygc3R5bGUgcHJvcGVydHkgdmFsdWVzXG4gICAgcmVtb3ZlZDogdHJ1ZSxcbiAgICAvLyB3aGV0aGVyIGl0J3MgaW5zaWRlIHRoZSB2aXM7IHRydWUgaWYgcmVtb3ZlZCAoc2V0IHRydWUgaGVyZSBzaW5jZSB3ZSBjYWxsIHJlc3RvcmUpXG4gICAgc2VsZWN0ZWQ6IHBhcmFtcy5zZWxlY3RlZCA/IHRydWUgOiBmYWxzZSxcbiAgICAvLyB3aGV0aGVyIGl0J3Mgc2VsZWN0ZWRcbiAgICBzZWxlY3RhYmxlOiBwYXJhbXMuc2VsZWN0YWJsZSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHBhcmFtcy5zZWxlY3RhYmxlID8gdHJ1ZSA6IGZhbHNlLFxuICAgIC8vIHdoZXRoZXIgaXQncyBzZWxlY3RhYmxlXG4gICAgbG9ja2VkOiBwYXJhbXMubG9ja2VkID8gdHJ1ZSA6IGZhbHNlLFxuICAgIC8vIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgbG9ja2VkIChjYW5ub3QgYmUgbW92ZWQpXG4gICAgZ3JhYmJlZDogZmFsc2UsXG4gICAgLy8gd2hldGhlciB0aGUgZWxlbWVudCBpcyBncmFiYmVkIGJ5IHRoZSBtb3VzZTsgcmVuZGVyZXIgc2V0cyB0aGlzIHByaXZhdGVseVxuICAgIGdyYWJiYWJsZTogcGFyYW1zLmdyYWJiYWJsZSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHBhcmFtcy5ncmFiYmFibGUgPyB0cnVlIDogZmFsc2UsXG4gICAgLy8gd2hldGhlciB0aGUgZWxlbWVudCBjYW4gYmUgZ3JhYmJlZFxuICAgIHBhbm5hYmxlOiBwYXJhbXMucGFubmFibGUgPT09IHVuZGVmaW5lZCA/IGdyb3VwID09PSAnZWRnZXMnID8gdHJ1ZSA6IGZhbHNlIDogcGFyYW1zLnBhbm5hYmxlID8gdHJ1ZSA6IGZhbHNlLFxuICAgIC8vIHdoZXRoZXIgdGhlIGVsZW1lbnQgaGFzIHBhc3N0aHJvdWdoIHBhbm5pbmcgZW5hYmxlZFxuICAgIGFjdGl2ZTogZmFsc2UsXG4gICAgLy8gd2hldGhlciB0aGUgZWxlbWVudCBpcyBhY3RpdmUgZnJvbSB1c2VyIGludGVyYWN0aW9uXG4gICAgY2xhc3NlczogbmV3IFNldCQxKCksXG4gICAgLy8gbWFwICggY2xhc3NOYW1lID0+IHRydWUgKVxuICAgIGFuaW1hdGlvbjoge1xuICAgICAgLy8gb2JqZWN0IGZvciBjdXJyZW50bHktcnVubmluZyBhbmltYXRpb25zXG4gICAgICBjdXJyZW50OiBbXSxcbiAgICAgIHF1ZXVlOiBbXVxuICAgIH0sXG4gICAgcnNjcmF0Y2g6IHt9LFxuICAgIC8vIG9iamVjdCBpbiB3aGljaCB0aGUgcmVuZGVyZXIgY2FuIHN0b3JlIGluZm9ybWF0aW9uXG4gICAgc2NyYXRjaDogcGFyYW1zLnNjcmF0Y2ggfHwge30sXG4gICAgLy8gc2NyYXRjaCBvYmplY3RzXG4gICAgZWRnZXM6IFtdLFxuICAgIC8vIGFycmF5IG9mIGNvbm5lY3RlZCBlZGdlc1xuICAgIGNoaWxkcmVuOiBbXSxcbiAgICAvLyBhcnJheSBvZiBjaGlsZHJlblxuICAgIHBhcmVudDogbnVsbCxcbiAgICAvLyBwYXJlbnQgcmVmXG4gICAgdHJhdmVyc2FsQ2FjaGU6IHt9LFxuICAgIC8vIGNhY2hlIG9mIG91dHB1dCBvZiB0cmF2ZXJzYWwgZnVuY3Rpb25zXG4gICAgYmFja2dyb3VuZGluZzogZmFsc2UsXG4gICAgLy8gd2hldGhlciBiYWNrZ3JvdW5kIGltYWdlcyBhcmUgbG9hZGluZ1xuICAgIGJiQ2FjaGU6IG51bGwsXG4gICAgLy8gY2FjaGUgb2YgdGhlIGN1cnJlbnQgYm91bmRpbmcgYm94XG4gICAgYmJDYWNoZVNoaWZ0OiB7XG4gICAgICB4OiAwLFxuICAgICAgeTogMFxuICAgIH0sXG4gICAgLy8gc2hpZnQgYXBwbGllZCB0byBjYWNoZWQgYmIgdG8gYmUgYXBwbGllZCBvbiBuZXh0IGdldFxuICAgIGJvZHlCb3VuZHM6IG51bGwsXG4gICAgLy8gYm91bmRzIGNhY2hlIG9mIGVsZW1lbnQgYm9keSwgdy9vIG92ZXJsYXlcbiAgICBvdmVybGF5Qm91bmRzOiBudWxsLFxuICAgIC8vIGJvdW5kcyBjYWNoZSBvZiBlbGVtZW50IGJvZHksIGluY2x1ZGluZyBvdmVybGF5XG4gICAgbGFiZWxCb3VuZHM6IHtcbiAgICAgIC8vIGJvdW5kcyBjYWNoZSBvZiBsYWJlbHNcbiAgICAgIGFsbDogbnVsbCxcbiAgICAgIHNvdXJjZTogbnVsbCxcbiAgICAgIHRhcmdldDogbnVsbCxcbiAgICAgIG1haW46IG51bGxcbiAgICB9LFxuICAgIGFycm93Qm91bmRzOiB7XG4gICAgICAvLyBib3VuZHMgY2FjaGUgb2YgZWRnZSBhcnJvd3NcbiAgICAgIHNvdXJjZTogbnVsbCxcbiAgICAgIHRhcmdldDogbnVsbCxcbiAgICAgICdtaWQtc291cmNlJzogbnVsbCxcbiAgICAgICdtaWQtdGFyZ2V0JzogbnVsbFxuICAgIH1cbiAgfTtcblxuICBpZiAoX3AucG9zaXRpb24ueCA9PSBudWxsKSB7XG4gICAgX3AucG9zaXRpb24ueCA9IDA7XG4gIH1cblxuICBpZiAoX3AucG9zaXRpb24ueSA9PSBudWxsKSB7XG4gICAgX3AucG9zaXRpb24ueSA9IDA7XG4gIH0gLy8gcmVuZGVyZWRQb3NpdGlvbiBvdmVycmlkZXMgaWYgc3BlY2lmaWVkXG5cblxuICBpZiAocGFyYW1zLnJlbmRlcmVkUG9zaXRpb24pIHtcbiAgICB2YXIgcnBvcyA9IHBhcmFtcy5yZW5kZXJlZFBvc2l0aW9uO1xuICAgIHZhciBwYW4gPSBjeS5wYW4oKTtcbiAgICB2YXIgem9vbSA9IGN5Lnpvb20oKTtcbiAgICBfcC5wb3NpdGlvbiA9IHtcbiAgICAgIHg6IChycG9zLnggLSBwYW4ueCkgLyB6b29tLFxuICAgICAgeTogKHJwb3MueSAtIHBhbi55KSAvIHpvb21cbiAgICB9O1xuICB9XG5cbiAgdmFyIGNsYXNzZXMgPSBbXTtcblxuICBpZiAoYXJyYXkocGFyYW1zLmNsYXNzZXMpKSB7XG4gICAgY2xhc3NlcyA9IHBhcmFtcy5jbGFzc2VzO1xuICB9IGVsc2UgaWYgKHN0cmluZyhwYXJhbXMuY2xhc3NlcykpIHtcbiAgICBjbGFzc2VzID0gcGFyYW1zLmNsYXNzZXMuc3BsaXQoL1xccysvKTtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwLCBsID0gY2xhc3Nlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICB2YXIgY2xzID0gY2xhc3Nlc1tpXTtcblxuICAgIGlmICghY2xzIHx8IGNscyA9PT0gJycpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIF9wLmNsYXNzZXMuYWRkKGNscyk7XG4gIH1cblxuICB0aGlzLmNyZWF0ZUVtaXR0ZXIoKTtcbiAgdmFyIGJ5cGFzcyA9IHBhcmFtcy5zdHlsZSB8fCBwYXJhbXMuY3NzO1xuXG4gIGlmIChieXBhc3MpIHtcbiAgICB3YXJuKCdTZXR0aW5nIGEgYHN0eWxlYCBieXBhc3MgYXQgZWxlbWVudCBjcmVhdGlvbiBpcyBkZXByZWNhdGVkJyk7XG4gICAgdGhpcy5zdHlsZShieXBhc3MpO1xuICB9XG5cbiAgaWYgKHJlc3RvcmUgPT09IHVuZGVmaW5lZCB8fCByZXN0b3JlKSB7XG4gICAgdGhpcy5yZXN0b3JlKCk7XG4gIH1cbn07XG5cbnZhciBkZWZpbmVTZWFyY2ggPSBmdW5jdGlvbiBkZWZpbmVTZWFyY2gocGFyYW1zKSB7XG4gIHBhcmFtcyA9IHtcbiAgICBiZnM6IHBhcmFtcy5iZnMgfHwgIXBhcmFtcy5kZnMsXG4gICAgZGZzOiBwYXJhbXMuZGZzIHx8ICFwYXJhbXMuYmZzXG4gIH07IC8vIGZyb20gcHNldWRvY29kZSBvbiB3aWtpcGVkaWFcblxuICByZXR1cm4gZnVuY3Rpb24gc2VhcmNoRm4ocm9vdHMsIGZuJDEsIGRpcmVjdGVkKSB7XG4gICAgdmFyIG9wdGlvbnM7XG5cbiAgICBpZiAocGxhaW5PYmplY3Qocm9vdHMpICYmICFlbGVtZW50T3JDb2xsZWN0aW9uKHJvb3RzKSkge1xuICAgICAgb3B0aW9ucyA9IHJvb3RzO1xuICAgICAgcm9vdHMgPSBvcHRpb25zLnJvb3RzIHx8IG9wdGlvbnMucm9vdDtcbiAgICAgIGZuJDEgPSBvcHRpb25zLnZpc2l0O1xuICAgICAgZGlyZWN0ZWQgPSBvcHRpb25zLmRpcmVjdGVkO1xuICAgIH1cblxuICAgIGRpcmVjdGVkID0gYXJndW1lbnRzLmxlbmd0aCA9PT0gMiAmJiAhZm4oZm4kMSkgPyBmbiQxIDogZGlyZWN0ZWQ7XG4gICAgZm4kMSA9IGZuKGZuJDEpID8gZm4kMSA6IGZ1bmN0aW9uICgpIHt9O1xuICAgIHZhciBjeSA9IHRoaXMuX3ByaXZhdGUuY3k7XG4gICAgdmFyIHYgPSByb290cyA9IHN0cmluZyhyb290cykgPyB0aGlzLmZpbHRlcihyb290cykgOiByb290cztcbiAgICB2YXIgUSA9IFtdO1xuICAgIHZhciBjb25uZWN0ZWROb2RlcyA9IFtdO1xuICAgIHZhciBjb25uZWN0ZWRCeSA9IHt9O1xuICAgIHZhciBpZDJkZXB0aCA9IHt9O1xuICAgIHZhciBWID0ge307XG4gICAgdmFyIGogPSAwO1xuICAgIHZhciBmb3VuZDtcblxuICAgIHZhciBfdGhpcyRieUdyb3VwID0gdGhpcy5ieUdyb3VwKCksXG4gICAgICAgIG5vZGVzID0gX3RoaXMkYnlHcm91cC5ub2RlcyxcbiAgICAgICAgZWRnZXMgPSBfdGhpcyRieUdyb3VwLmVkZ2VzOyAvLyBlbnF1ZXVlIHZcblxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdmkgPSB2W2ldO1xuICAgICAgdmFyIHZpSWQgPSB2aS5pZCgpO1xuXG4gICAgICBpZiAodmkuaXNOb2RlKCkpIHtcbiAgICAgICAgUS51bnNoaWZ0KHZpKTtcblxuICAgICAgICBpZiAocGFyYW1zLmJmcykge1xuICAgICAgICAgIFZbdmlJZF0gPSB0cnVlO1xuICAgICAgICAgIGNvbm5lY3RlZE5vZGVzLnB1c2godmkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWQyZGVwdGhbdmlJZF0gPSAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBfbG9vcDIgPSBmdW5jdGlvbiBfbG9vcDIoKSB7XG4gICAgICB2YXIgdiA9IHBhcmFtcy5iZnMgPyBRLnNoaWZ0KCkgOiBRLnBvcCgpO1xuICAgICAgdmFyIHZJZCA9IHYuaWQoKTtcblxuICAgICAgaWYgKHBhcmFtcy5kZnMpIHtcbiAgICAgICAgaWYgKFZbdklkXSkge1xuICAgICAgICAgIHJldHVybiBcImNvbnRpbnVlXCI7XG4gICAgICAgIH1cblxuICAgICAgICBWW3ZJZF0gPSB0cnVlO1xuICAgICAgICBjb25uZWN0ZWROb2Rlcy5wdXNoKHYpO1xuICAgICAgfVxuXG4gICAgICB2YXIgZGVwdGggPSBpZDJkZXB0aFt2SWRdO1xuICAgICAgdmFyIHByZXZFZGdlID0gY29ubmVjdGVkQnlbdklkXTtcbiAgICAgIHZhciBzcmMgPSBwcmV2RWRnZSAhPSBudWxsID8gcHJldkVkZ2Uuc291cmNlKCkgOiBudWxsO1xuICAgICAgdmFyIHRndCA9IHByZXZFZGdlICE9IG51bGwgPyBwcmV2RWRnZS50YXJnZXQoKSA6IG51bGw7XG4gICAgICB2YXIgcHJldk5vZGUgPSBwcmV2RWRnZSA9PSBudWxsID8gdW5kZWZpbmVkIDogdi5zYW1lKHNyYykgPyB0Z3RbMF0gOiBzcmNbMF07XG4gICAgICB2YXIgcmV0ID0gdm9pZCAwO1xuICAgICAgcmV0ID0gZm4kMSh2LCBwcmV2RWRnZSwgcHJldk5vZGUsIGorKywgZGVwdGgpO1xuXG4gICAgICBpZiAocmV0ID09PSB0cnVlKSB7XG4gICAgICAgIGZvdW5kID0gdjtcbiAgICAgICAgcmV0dXJuIFwiYnJlYWtcIjtcbiAgICAgIH1cblxuICAgICAgaWYgKHJldCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIFwiYnJlYWtcIjtcbiAgICAgIH1cblxuICAgICAgdmFyIHZ3RWRnZXMgPSB2LmNvbm5lY3RlZEVkZ2VzKCkuZmlsdGVyKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHJldHVybiAoIWRpcmVjdGVkIHx8IGUuc291cmNlKCkuc2FtZSh2KSkgJiYgZWRnZXMuaGFzKGUpO1xuICAgICAgfSk7XG5cbiAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IHZ3RWRnZXMubGVuZ3RoOyBfaTIrKykge1xuICAgICAgICB2YXIgZSA9IHZ3RWRnZXNbX2kyXTtcbiAgICAgICAgdmFyIHcgPSBlLmNvbm5lY3RlZE5vZGVzKCkuZmlsdGVyKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgcmV0dXJuICFuLnNhbWUodikgJiYgbm9kZXMuaGFzKG4pO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHdJZCA9IHcuaWQoKTtcblxuICAgICAgICBpZiAody5sZW5ndGggIT09IDAgJiYgIVZbd0lkXSkge1xuICAgICAgICAgIHcgPSB3WzBdO1xuICAgICAgICAgIFEucHVzaCh3KTtcblxuICAgICAgICAgIGlmIChwYXJhbXMuYmZzKSB7XG4gICAgICAgICAgICBWW3dJZF0gPSB0cnVlO1xuICAgICAgICAgICAgY29ubmVjdGVkTm9kZXMucHVzaCh3KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25uZWN0ZWRCeVt3SWRdID0gZTtcbiAgICAgICAgICBpZDJkZXB0aFt3SWRdID0gaWQyZGVwdGhbdklkXSArIDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX2xvb3A6IHdoaWxlIChRLmxlbmd0aCAhPT0gMCkge1xuICAgICAgdmFyIF9yZXQgPSBfbG9vcDIoKTtcblxuICAgICAgc3dpdGNoIChfcmV0KSB7XG4gICAgICAgIGNhc2UgXCJjb250aW51ZVwiOlxuICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIGNhc2UgXCJicmVha1wiOlxuICAgICAgICAgIGJyZWFrIF9sb29wO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBjb25uZWN0ZWRFbGVzID0gY3kuY29sbGVjdGlvbigpO1xuXG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGNvbm5lY3RlZE5vZGVzLmxlbmd0aDsgX2krKykge1xuICAgICAgdmFyIG5vZGUgPSBjb25uZWN0ZWROb2Rlc1tfaV07XG4gICAgICB2YXIgZWRnZSA9IGNvbm5lY3RlZEJ5W25vZGUuaWQoKV07XG5cbiAgICAgIGlmIChlZGdlICE9IG51bGwpIHtcbiAgICAgICAgY29ubmVjdGVkRWxlcy5tZXJnZShlZGdlKTtcbiAgICAgIH1cblxuICAgICAgY29ubmVjdGVkRWxlcy5tZXJnZShub2RlKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGF0aDogY3kuY29sbGVjdGlvbihjb25uZWN0ZWRFbGVzKSxcbiAgICAgIGZvdW5kOiBjeS5jb2xsZWN0aW9uKGZvdW5kKVxuICAgIH07XG4gIH07XG59OyAvLyBzZWFyY2gsIHNwYW5uaW5nIHRyZWVzLCBldGNcblxuXG52YXIgZWxlc2ZuID0ge1xuICBicmVhZHRoRmlyc3RTZWFyY2g6IGRlZmluZVNlYXJjaCh7XG4gICAgYmZzOiB0cnVlXG4gIH0pLFxuICBkZXB0aEZpcnN0U2VhcmNoOiBkZWZpbmVTZWFyY2goe1xuICAgIGRmczogdHJ1ZVxuICB9KVxufTsgLy8gbmljZSwgc2hvcnQgbWF0aGVtYXRoaWNhbCBhbGlhc1xuXG5lbGVzZm4uYmZzID0gZWxlc2ZuLmJyZWFkdGhGaXJzdFNlYXJjaDtcbmVsZXNmbi5kZnMgPSBlbGVzZm4uZGVwdGhGaXJzdFNlYXJjaDtcblxudmFyIGRpamtzdHJhRGVmYXVsdHMgPSBkZWZhdWx0cyh7XG4gIHJvb3Q6IG51bGwsXG4gIHdlaWdodDogZnVuY3Rpb24gd2VpZ2h0KGVkZ2UpIHtcbiAgICByZXR1cm4gMTtcbiAgfSxcbiAgZGlyZWN0ZWQ6IGZhbHNlXG59KTtcbnZhciBlbGVzZm4kMSA9IHtcbiAgZGlqa3N0cmE6IGZ1bmN0aW9uIGRpamtzdHJhKG9wdGlvbnMpIHtcbiAgICBpZiAoIXBsYWluT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgIHJvb3Q6IGFyZ3NbMF0sXG4gICAgICAgIHdlaWdodDogYXJnc1sxXSxcbiAgICAgICAgZGlyZWN0ZWQ6IGFyZ3NbMl1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIF9kaWprc3RyYURlZmF1bHRzID0gZGlqa3N0cmFEZWZhdWx0cyhvcHRpb25zKSxcbiAgICAgICAgcm9vdCA9IF9kaWprc3RyYURlZmF1bHRzLnJvb3QsXG4gICAgICAgIHdlaWdodCA9IF9kaWprc3RyYURlZmF1bHRzLndlaWdodCxcbiAgICAgICAgZGlyZWN0ZWQgPSBfZGlqa3N0cmFEZWZhdWx0cy5kaXJlY3RlZDtcblxuICAgIHZhciBlbGVzID0gdGhpcztcbiAgICB2YXIgd2VpZ2h0Rm4gPSB3ZWlnaHQ7XG4gICAgdmFyIHNvdXJjZSA9IHN0cmluZyhyb290KSA/IHRoaXMuZmlsdGVyKHJvb3QpWzBdIDogcm9vdFswXTtcbiAgICB2YXIgZGlzdCA9IHt9O1xuICAgIHZhciBwcmV2ID0ge307XG4gICAgdmFyIGtub3duRGlzdCA9IHt9O1xuXG4gICAgdmFyIF90aGlzJGJ5R3JvdXAgPSB0aGlzLmJ5R3JvdXAoKSxcbiAgICAgICAgbm9kZXMgPSBfdGhpcyRieUdyb3VwLm5vZGVzLFxuICAgICAgICBlZGdlcyA9IF90aGlzJGJ5R3JvdXAuZWRnZXM7XG5cbiAgICBlZGdlcy51bm1lcmdlQnkoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgcmV0dXJuIGVsZS5pc0xvb3AoKTtcbiAgICB9KTtcblxuICAgIHZhciBnZXREaXN0ID0gZnVuY3Rpb24gZ2V0RGlzdChub2RlKSB7XG4gICAgICByZXR1cm4gZGlzdFtub2RlLmlkKCldO1xuICAgIH07XG5cbiAgICB2YXIgc2V0RGlzdCA9IGZ1bmN0aW9uIHNldERpc3Qobm9kZSwgZCkge1xuICAgICAgZGlzdFtub2RlLmlkKCldID0gZDtcbiAgICAgIFEudXBkYXRlSXRlbShub2RlKTtcbiAgICB9O1xuXG4gICAgdmFyIFEgPSBuZXcgSGVhcChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGdldERpc3QoYSkgLSBnZXREaXN0KGIpO1xuICAgIH0pO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgIGRpc3Rbbm9kZS5pZCgpXSA9IG5vZGUuc2FtZShzb3VyY2UpID8gMCA6IEluZmluaXR5O1xuICAgICAgUS5wdXNoKG5vZGUpO1xuICAgIH1cblxuICAgIHZhciBkaXN0QmV0d2VlbiA9IGZ1bmN0aW9uIGRpc3RCZXR3ZWVuKHUsIHYpIHtcbiAgICAgIHZhciB1dnMgPSAoZGlyZWN0ZWQgPyB1LmVkZ2VzVG8odikgOiB1LmVkZ2VzV2l0aCh2KSkuaW50ZXJzZWN0KGVkZ2VzKTtcbiAgICAgIHZhciBzbWFsbGVzdERpc3RhbmNlID0gSW5maW5pdHk7XG4gICAgICB2YXIgc21hbGxlc3RFZGdlO1xuXG4gICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgdXZzLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgZWRnZSA9IHV2c1tfaV07XG5cbiAgICAgICAgdmFyIF93ZWlnaHQgPSB3ZWlnaHRGbihlZGdlKTtcblxuICAgICAgICBpZiAoX3dlaWdodCA8IHNtYWxsZXN0RGlzdGFuY2UgfHwgIXNtYWxsZXN0RWRnZSkge1xuICAgICAgICAgIHNtYWxsZXN0RGlzdGFuY2UgPSBfd2VpZ2h0O1xuICAgICAgICAgIHNtYWxsZXN0RWRnZSA9IGVkZ2U7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZWRnZTogc21hbGxlc3RFZGdlLFxuICAgICAgICBkaXN0OiBzbWFsbGVzdERpc3RhbmNlXG4gICAgICB9O1xuICAgIH07XG5cbiAgICB3aGlsZSAoUS5zaXplKCkgPiAwKSB7XG4gICAgICB2YXIgdSA9IFEucG9wKCk7XG4gICAgICB2YXIgc21hbGxldHNEaXN0ID0gZ2V0RGlzdCh1KTtcbiAgICAgIHZhciB1aWQgPSB1LmlkKCk7XG4gICAgICBrbm93bkRpc3RbdWlkXSA9IHNtYWxsZXRzRGlzdDtcblxuICAgICAgaWYgKHNtYWxsZXRzRGlzdCA9PT0gSW5maW5pdHkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBuZWlnaGJvcnMgPSB1Lm5laWdoYm9yaG9vZCgpLmludGVyc2VjdChub2Rlcyk7XG5cbiAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IG5laWdoYm9ycy5sZW5ndGg7IF9pMisrKSB7XG4gICAgICAgIHZhciB2ID0gbmVpZ2hib3JzW19pMl07XG4gICAgICAgIHZhciB2aWQgPSB2LmlkKCk7XG4gICAgICAgIHZhciB2RGlzdCA9IGRpc3RCZXR3ZWVuKHUsIHYpO1xuICAgICAgICB2YXIgYWx0ID0gc21hbGxldHNEaXN0ICsgdkRpc3QuZGlzdDtcblxuICAgICAgICBpZiAoYWx0IDwgZ2V0RGlzdCh2KSkge1xuICAgICAgICAgIHNldERpc3QodiwgYWx0KTtcbiAgICAgICAgICBwcmV2W3ZpZF0gPSB7XG4gICAgICAgICAgICBub2RlOiB1LFxuICAgICAgICAgICAgZWRnZTogdkRpc3QuZWRnZVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH0gLy8gZm9yXG5cbiAgICB9IC8vIHdoaWxlXG5cblxuICAgIHJldHVybiB7XG4gICAgICBkaXN0YW5jZVRvOiBmdW5jdGlvbiBkaXN0YW5jZVRvKG5vZGUpIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IHN0cmluZyhub2RlKSA/IG5vZGVzLmZpbHRlcihub2RlKVswXSA6IG5vZGVbMF07XG4gICAgICAgIHJldHVybiBrbm93bkRpc3RbdGFyZ2V0LmlkKCldO1xuICAgICAgfSxcbiAgICAgIHBhdGhUbzogZnVuY3Rpb24gcGF0aFRvKG5vZGUpIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IHN0cmluZyhub2RlKSA/IG5vZGVzLmZpbHRlcihub2RlKVswXSA6IG5vZGVbMF07XG4gICAgICAgIHZhciBTID0gW107XG4gICAgICAgIHZhciB1ID0gdGFyZ2V0O1xuICAgICAgICB2YXIgdWlkID0gdS5pZCgpO1xuXG4gICAgICAgIGlmICh0YXJnZXQubGVuZ3RoID4gMCkge1xuICAgICAgICAgIFMudW5zaGlmdCh0YXJnZXQpO1xuXG4gICAgICAgICAgd2hpbGUgKHByZXZbdWlkXSkge1xuICAgICAgICAgICAgdmFyIHAgPSBwcmV2W3VpZF07XG4gICAgICAgICAgICBTLnVuc2hpZnQocC5lZGdlKTtcbiAgICAgICAgICAgIFMudW5zaGlmdChwLm5vZGUpO1xuICAgICAgICAgICAgdSA9IHAubm9kZTtcbiAgICAgICAgICAgIHVpZCA9IHUuaWQoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZWxlcy5zcGF3bihTKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG59O1xuXG52YXIgZWxlc2ZuJDIgPSB7XG4gIC8vIGtydXNrYWwncyBhbGdvcml0aG0gKGZpbmRzIG1pbiBzcGFubmluZyB0cmVlLCBhc3N1bWluZyB1bmRpcmVjdGVkIGdyYXBoKVxuICAvLyBpbXBsZW1lbnRlZCBmcm9tIHBzZXVkb2NvZGUgZnJvbSB3aWtpcGVkaWFcbiAga3J1c2thbDogZnVuY3Rpb24ga3J1c2thbCh3ZWlnaHRGbikge1xuICAgIHdlaWdodEZuID0gd2VpZ2h0Rm4gfHwgZnVuY3Rpb24gKGVkZ2UpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH07XG5cbiAgICB2YXIgX3RoaXMkYnlHcm91cCA9IHRoaXMuYnlHcm91cCgpLFxuICAgICAgICBub2RlcyA9IF90aGlzJGJ5R3JvdXAubm9kZXMsXG4gICAgICAgIGVkZ2VzID0gX3RoaXMkYnlHcm91cC5lZGdlcztcblxuICAgIHZhciBudW1Ob2RlcyA9IG5vZGVzLmxlbmd0aDtcbiAgICB2YXIgZm9yZXN0ID0gbmV3IEFycmF5KG51bU5vZGVzKTtcbiAgICB2YXIgQSA9IG5vZGVzOyAvLyBhc3N1bWVzIGJ5R3JvdXAoKSBjcmVhdGVzIG5ldyBjb2xsZWN0aW9ucyB0aGF0IGNhbiBiZSBzYWZlbHkgbXV0YXRlZFxuXG4gICAgdmFyIGZpbmRTZXRJbmRleCA9IGZ1bmN0aW9uIGZpbmRTZXRJbmRleChlbGUpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZm9yZXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGVzID0gZm9yZXN0W2ldO1xuXG4gICAgICAgIGlmIChlbGVzLmhhcyhlbGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9OyAvLyBzdGFydCB3aXRoIG9uZSBmb3Jlc3QgcGVyIG5vZGVcblxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1Ob2RlczsgaSsrKSB7XG4gICAgICBmb3Jlc3RbaV0gPSB0aGlzLnNwYXduKG5vZGVzW2ldKTtcbiAgICB9XG5cbiAgICB2YXIgUyA9IGVkZ2VzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIHJldHVybiB3ZWlnaHRGbihhKSAtIHdlaWdodEZuKGIpO1xuICAgIH0pO1xuXG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IFMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICB2YXIgZWRnZSA9IFNbX2ldO1xuICAgICAgdmFyIHUgPSBlZGdlLnNvdXJjZSgpWzBdO1xuICAgICAgdmFyIHYgPSBlZGdlLnRhcmdldCgpWzBdO1xuICAgICAgdmFyIHNldFVJbmRleCA9IGZpbmRTZXRJbmRleCh1KTtcbiAgICAgIHZhciBzZXRWSW5kZXggPSBmaW5kU2V0SW5kZXgodik7XG4gICAgICB2YXIgc2V0VSA9IGZvcmVzdFtzZXRVSW5kZXhdO1xuICAgICAgdmFyIHNldFYgPSBmb3Jlc3Rbc2V0VkluZGV4XTtcblxuICAgICAgaWYgKHNldFVJbmRleCAhPT0gc2V0VkluZGV4KSB7XG4gICAgICAgIEEubWVyZ2UoZWRnZSk7IC8vIGNvbWJpbmUgZm9yZXN0cyBmb3IgdSBhbmQgdlxuXG4gICAgICAgIHNldFUubWVyZ2Uoc2V0Vik7XG4gICAgICAgIGZvcmVzdC5zcGxpY2Uoc2V0VkluZGV4LCAxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gQTtcbiAgfVxufTtcblxudmFyIGFTdGFyRGVmYXVsdHMgPSBkZWZhdWx0cyh7XG4gIHJvb3Q6IG51bGwsXG4gIGdvYWw6IG51bGwsXG4gIHdlaWdodDogZnVuY3Rpb24gd2VpZ2h0KGVkZ2UpIHtcbiAgICByZXR1cm4gMTtcbiAgfSxcbiAgaGV1cmlzdGljOiBmdW5jdGlvbiBoZXVyaXN0aWMoZWRnZSkge1xuICAgIHJldHVybiAwO1xuICB9LFxuICBkaXJlY3RlZDogZmFsc2Vcbn0pO1xudmFyIGVsZXNmbiQzID0ge1xuICAvLyBJbXBsZW1lbnRlZCBmcm9tIHBzZXVkb2NvZGUgZnJvbSB3aWtpcGVkaWFcbiAgYVN0YXI6IGZ1bmN0aW9uIGFTdGFyKG9wdGlvbnMpIHtcbiAgICB2YXIgY3kgPSB0aGlzLmN5KCk7XG5cbiAgICB2YXIgX2FTdGFyRGVmYXVsdHMgPSBhU3RhckRlZmF1bHRzKG9wdGlvbnMpLFxuICAgICAgICByb290ID0gX2FTdGFyRGVmYXVsdHMucm9vdCxcbiAgICAgICAgZ29hbCA9IF9hU3RhckRlZmF1bHRzLmdvYWwsXG4gICAgICAgIGhldXJpc3RpYyA9IF9hU3RhckRlZmF1bHRzLmhldXJpc3RpYyxcbiAgICAgICAgZGlyZWN0ZWQgPSBfYVN0YXJEZWZhdWx0cy5kaXJlY3RlZCxcbiAgICAgICAgd2VpZ2h0ID0gX2FTdGFyRGVmYXVsdHMud2VpZ2h0O1xuXG4gICAgcm9vdCA9IGN5LmNvbGxlY3Rpb24ocm9vdClbMF07XG4gICAgZ29hbCA9IGN5LmNvbGxlY3Rpb24oZ29hbClbMF07XG4gICAgdmFyIHNpZCA9IHJvb3QuaWQoKTtcbiAgICB2YXIgdGlkID0gZ29hbC5pZCgpO1xuICAgIHZhciBnU2NvcmUgPSB7fTtcbiAgICB2YXIgZlNjb3JlID0ge307XG4gICAgdmFyIGNsb3NlZFNldElkcyA9IHt9O1xuICAgIHZhciBvcGVuU2V0ID0gbmV3IEhlYXAoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIHJldHVybiBmU2NvcmVbYS5pZCgpXSAtIGZTY29yZVtiLmlkKCldO1xuICAgIH0pO1xuICAgIHZhciBvcGVuU2V0SWRzID0gbmV3IFNldCQxKCk7XG4gICAgdmFyIGNhbWVGcm9tID0ge307XG4gICAgdmFyIGNhbWVGcm9tRWRnZSA9IHt9O1xuXG4gICAgdmFyIGFkZFRvT3BlblNldCA9IGZ1bmN0aW9uIGFkZFRvT3BlblNldChlbGUsIGlkKSB7XG4gICAgICBvcGVuU2V0LnB1c2goZWxlKTtcbiAgICAgIG9wZW5TZXRJZHMuYWRkKGlkKTtcbiAgICB9O1xuXG4gICAgdmFyIGNNaW4sIGNNaW5JZDtcblxuICAgIHZhciBwb3BGcm9tT3BlblNldCA9IGZ1bmN0aW9uIHBvcEZyb21PcGVuU2V0KCkge1xuICAgICAgY01pbiA9IG9wZW5TZXQucG9wKCk7XG4gICAgICBjTWluSWQgPSBjTWluLmlkKCk7XG4gICAgICBvcGVuU2V0SWRzW1wiZGVsZXRlXCJdKGNNaW5JZCk7XG4gICAgfTtcblxuICAgIHZhciBpc0luT3BlblNldCA9IGZ1bmN0aW9uIGlzSW5PcGVuU2V0KGlkKSB7XG4gICAgICByZXR1cm4gb3BlblNldElkcy5oYXMoaWQpO1xuICAgIH07XG5cbiAgICBhZGRUb09wZW5TZXQocm9vdCwgc2lkKTtcbiAgICBnU2NvcmVbc2lkXSA9IDA7XG4gICAgZlNjb3JlW3NpZF0gPSBoZXVyaXN0aWMocm9vdCk7IC8vIENvdW50ZXJcblxuICAgIHZhciBzdGVwcyA9IDA7IC8vIE1haW4gbG9vcFxuXG4gICAgd2hpbGUgKG9wZW5TZXQuc2l6ZSgpID4gMCkge1xuICAgICAgcG9wRnJvbU9wZW5TZXQoKTtcbiAgICAgIHN0ZXBzKys7IC8vIElmIHdlJ3ZlIGZvdW5kIG91ciBnb2FsLCB0aGVuIHdlIGFyZSBkb25lXG5cbiAgICAgIGlmIChjTWluSWQgPT09IHRpZCkge1xuICAgICAgICB2YXIgcGF0aCA9IFtdO1xuICAgICAgICB2YXIgcGF0aE5vZGUgPSBnb2FsO1xuICAgICAgICB2YXIgcGF0aE5vZGVJZCA9IHRpZDtcbiAgICAgICAgdmFyIHBhdGhFZGdlID0gY2FtZUZyb21FZGdlW3BhdGhOb2RlSWRdO1xuXG4gICAgICAgIGZvciAoOzspIHtcbiAgICAgICAgICBwYXRoLnVuc2hpZnQocGF0aE5vZGUpO1xuXG4gICAgICAgICAgaWYgKHBhdGhFZGdlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHBhdGgudW5zaGlmdChwYXRoRWRnZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcGF0aE5vZGUgPSBjYW1lRnJvbVtwYXRoTm9kZUlkXTtcblxuICAgICAgICAgIGlmIChwYXRoTm9kZSA9PSBudWxsKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBwYXRoTm9kZUlkID0gcGF0aE5vZGUuaWQoKTtcbiAgICAgICAgICBwYXRoRWRnZSA9IGNhbWVGcm9tRWRnZVtwYXRoTm9kZUlkXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZm91bmQ6IHRydWUsXG4gICAgICAgICAgZGlzdGFuY2U6IGdTY29yZVtjTWluSWRdLFxuICAgICAgICAgIHBhdGg6IHRoaXMuc3Bhd24ocGF0aCksXG4gICAgICAgICAgc3RlcHM6IHN0ZXBzXG4gICAgICAgIH07XG4gICAgICB9IC8vIEFkZCBjTWluIHRvIHByb2Nlc3NlZCBub2Rlc1xuXG5cbiAgICAgIGNsb3NlZFNldElkc1tjTWluSWRdID0gdHJ1ZTsgLy8gVXBkYXRlIHNjb3JlcyBmb3IgbmVpZ2hib3JzIG9mIGNNaW5cbiAgICAgIC8vIFRha2UgaW50byBhY2NvdW50IGlmIGdyYXBoIGlzIGRpcmVjdGVkIG9yIG5vdFxuXG4gICAgICB2YXIgdndFZGdlcyA9IGNNaW4uX3ByaXZhdGUuZWRnZXM7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdndFZGdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZSA9IHZ3RWRnZXNbaV07IC8vIGVkZ2UgbXVzdCBiZSBpbiBzZXQgb2YgY2FsbGluZyBlbGVzXG5cbiAgICAgICAgaWYgKCF0aGlzLmhhc0VsZW1lbnRXaXRoSWQoZS5pZCgpKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IC8vIGNNaW4gbXVzdCBiZSB0aGUgc291cmNlIG9mIGVkZ2UgaWYgZGlyZWN0ZWRcblxuXG4gICAgICAgIGlmIChkaXJlY3RlZCAmJiBlLmRhdGEoJ3NvdXJjZScpICE9PSBjTWluSWQpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB3U3JjID0gZS5zb3VyY2UoKTtcbiAgICAgICAgdmFyIHdUZ3QgPSBlLnRhcmdldCgpO1xuICAgICAgICB2YXIgdyA9IHdTcmMuaWQoKSAhPT0gY01pbklkID8gd1NyYyA6IHdUZ3Q7XG4gICAgICAgIHZhciB3aWQgPSB3LmlkKCk7IC8vIG5vZGUgbXVzdCBiZSBpbiBzZXQgb2YgY2FsbGluZyBlbGVzXG5cbiAgICAgICAgaWYgKCF0aGlzLmhhc0VsZW1lbnRXaXRoSWQod2lkKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IC8vIGlmIG5vZGUgaXMgaW4gY2xvc2VkU2V0LCBpZ25vcmUgaXRcblxuXG4gICAgICAgIGlmIChjbG9zZWRTZXRJZHNbd2lkXSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IC8vIE5ldyB0ZW50YXRpdmUgc2NvcmUgZm9yIG5vZGUgd1xuXG5cbiAgICAgICAgdmFyIHRlbXBTY29yZSA9IGdTY29yZVtjTWluSWRdICsgd2VpZ2h0KGUpOyAvLyBVcGRhdGUgZ1Njb3JlIGZvciBub2RlIHcgaWY6XG4gICAgICAgIC8vICAgdyBub3QgcHJlc2VudCBpbiBvcGVuU2V0XG4gICAgICAgIC8vIE9SXG4gICAgICAgIC8vICAgdGVudGF0aXZlIGdTY29yZSBpcyBsZXNzIHRoYW4gcHJldmlvdXMgdmFsdWVcbiAgICAgICAgLy8gdyBub3QgaW4gb3BlblNldFxuXG4gICAgICAgIGlmICghaXNJbk9wZW5TZXQod2lkKSkge1xuICAgICAgICAgIGdTY29yZVt3aWRdID0gdGVtcFNjb3JlO1xuICAgICAgICAgIGZTY29yZVt3aWRdID0gdGVtcFNjb3JlICsgaGV1cmlzdGljKHcpO1xuICAgICAgICAgIGFkZFRvT3BlblNldCh3LCB3aWQpO1xuICAgICAgICAgIGNhbWVGcm9tW3dpZF0gPSBjTWluO1xuICAgICAgICAgIGNhbWVGcm9tRWRnZVt3aWRdID0gZTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfSAvLyB3IGFscmVhZHkgaW4gb3BlblNldCwgYnV0IHdpdGggZ3JlYXRlciBnU2NvcmVcblxuXG4gICAgICAgIGlmICh0ZW1wU2NvcmUgPCBnU2NvcmVbd2lkXSkge1xuICAgICAgICAgIGdTY29yZVt3aWRdID0gdGVtcFNjb3JlO1xuICAgICAgICAgIGZTY29yZVt3aWRdID0gdGVtcFNjb3JlICsgaGV1cmlzdGljKHcpO1xuICAgICAgICAgIGNhbWVGcm9tW3dpZF0gPSBjTWluO1xuICAgICAgICB9XG4gICAgICB9IC8vIEVuZCBvZiBuZWlnaGJvcnMgdXBkYXRlXG5cbiAgICB9IC8vIEVuZCBvZiBtYWluIGxvb3BcbiAgICAvLyBJZiB3ZSd2ZSByZWFjaGVkIGhlcmUsIHRoZW4gd2UndmUgbm90IHJlYWNoZWQgb3VyIGdvYWxcblxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGZvdW5kOiBmYWxzZSxcbiAgICAgIGRpc3RhbmNlOiB1bmRlZmluZWQsXG4gICAgICBwYXRoOiB1bmRlZmluZWQsXG4gICAgICBzdGVwczogc3RlcHNcbiAgICB9O1xuICB9XG59OyAvLyBlbGVzZm5cblxudmFyIGZsb3lkV2Fyc2hhbGxEZWZhdWx0cyA9IGRlZmF1bHRzKHtcbiAgd2VpZ2h0OiBmdW5jdGlvbiB3ZWlnaHQoZWRnZSkge1xuICAgIHJldHVybiAxO1xuICB9LFxuICBkaXJlY3RlZDogZmFsc2Vcbn0pO1xudmFyIGVsZXNmbiQ0ID0ge1xuICAvLyBJbXBsZW1lbnRlZCBmcm9tIHBzZXVkb2NvZGUgZnJvbSB3aWtpcGVkaWFcbiAgZmxveWRXYXJzaGFsbDogZnVuY3Rpb24gZmxveWRXYXJzaGFsbChvcHRpb25zKSB7XG4gICAgdmFyIGN5ID0gdGhpcy5jeSgpO1xuXG4gICAgdmFyIF9mbG95ZFdhcnNoYWxsRGVmYXVsdCA9IGZsb3lkV2Fyc2hhbGxEZWZhdWx0cyhvcHRpb25zKSxcbiAgICAgICAgd2VpZ2h0ID0gX2Zsb3lkV2Fyc2hhbGxEZWZhdWx0LndlaWdodCxcbiAgICAgICAgZGlyZWN0ZWQgPSBfZmxveWRXYXJzaGFsbERlZmF1bHQuZGlyZWN0ZWQ7XG5cbiAgICB2YXIgd2VpZ2h0Rm4gPSB3ZWlnaHQ7XG5cbiAgICB2YXIgX3RoaXMkYnlHcm91cCA9IHRoaXMuYnlHcm91cCgpLFxuICAgICAgICBub2RlcyA9IF90aGlzJGJ5R3JvdXAubm9kZXMsXG4gICAgICAgIGVkZ2VzID0gX3RoaXMkYnlHcm91cC5lZGdlcztcblxuICAgIHZhciBOID0gbm9kZXMubGVuZ3RoO1xuICAgIHZhciBOc3EgPSBOICogTjtcblxuICAgIHZhciBpbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZihub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZXMuaW5kZXhPZihub2RlKTtcbiAgICB9O1xuXG4gICAgdmFyIGF0SW5kZXggPSBmdW5jdGlvbiBhdEluZGV4KGkpIHtcbiAgICAgIHJldHVybiBub2Rlc1tpXTtcbiAgICB9OyAvLyBJbml0aWFsaXplIGRpc3RhbmNlIG1hdHJpeFxuXG5cbiAgICB2YXIgZGlzdCA9IG5ldyBBcnJheShOc3EpO1xuXG4gICAgZm9yICh2YXIgbiA9IDA7IG4gPCBOc3E7IG4rKykge1xuICAgICAgdmFyIGogPSBuICUgTjtcbiAgICAgIHZhciBpID0gKG4gLSBqKSAvIE47XG5cbiAgICAgIGlmIChpID09PSBqKSB7XG4gICAgICAgIGRpc3Rbbl0gPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGlzdFtuXSA9IEluZmluaXR5O1xuICAgICAgfVxuICAgIH0gLy8gSW5pdGlhbGl6ZSBtYXRyaXggdXNlZCBmb3IgcGF0aCByZWNvbnN0cnVjdGlvblxuICAgIC8vIEluaXRpYWxpemUgZGlzdGFuY2UgbWF0cml4XG5cblxuICAgIHZhciBuZXh0ID0gbmV3IEFycmF5KE5zcSk7XG4gICAgdmFyIGVkZ2VOZXh0ID0gbmV3IEFycmF5KE5zcSk7IC8vIFByb2Nlc3MgZWRnZXNcblxuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBlZGdlcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgIHZhciBlZGdlID0gZWRnZXNbX2ldO1xuICAgICAgdmFyIHNyYyA9IGVkZ2Uuc291cmNlKClbMF07XG4gICAgICB2YXIgdGd0ID0gZWRnZS50YXJnZXQoKVswXTtcblxuICAgICAgaWYgKHNyYyA9PT0gdGd0KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfSAvLyBleGNsdWRlIGxvb3BzXG5cblxuICAgICAgdmFyIHMgPSBpbmRleE9mKHNyYyk7XG4gICAgICB2YXIgdCA9IGluZGV4T2YodGd0KTtcbiAgICAgIHZhciBzdCA9IHMgKiBOICsgdDsgLy8gc291cmNlIHRvIHRhcmdldCBpbmRleFxuXG4gICAgICB2YXIgX3dlaWdodCA9IHdlaWdodEZuKGVkZ2UpOyAvLyBDaGVjayBpZiBhbHJlYWR5IHByb2Nlc3MgYW5vdGhlciBlZGdlIGJldHdlZW4gc2FtZSAyIG5vZGVzXG5cblxuICAgICAgaWYgKGRpc3Rbc3RdID4gX3dlaWdodCkge1xuICAgICAgICBkaXN0W3N0XSA9IF93ZWlnaHQ7XG4gICAgICAgIG5leHRbc3RdID0gdDtcbiAgICAgICAgZWRnZU5leHRbc3RdID0gZWRnZTtcbiAgICAgIH0gLy8gSWYgdW5kaXJlY3RlZCBncmFwaCwgcHJvY2VzcyAncmV2ZXJzZWQnIGVkZ2VcblxuXG4gICAgICBpZiAoIWRpcmVjdGVkKSB7XG4gICAgICAgIHZhciB0cyA9IHQgKiBOICsgczsgLy8gdGFyZ2V0IHRvIHNvdXJjZSBpbmRleFxuXG4gICAgICAgIGlmICghZGlyZWN0ZWQgJiYgZGlzdFt0c10gPiBfd2VpZ2h0KSB7XG4gICAgICAgICAgZGlzdFt0c10gPSBfd2VpZ2h0O1xuICAgICAgICAgIG5leHRbdHNdID0gcztcbiAgICAgICAgICBlZGdlTmV4dFt0c10gPSBlZGdlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSAvLyBNYWluIGxvb3BcblxuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBOOyBrKyspIHtcbiAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IE47IF9pMisrKSB7XG4gICAgICAgIHZhciBpayA9IF9pMiAqIE4gKyBrO1xuXG4gICAgICAgIGZvciAodmFyIF9qID0gMDsgX2ogPCBOOyBfaisrKSB7XG4gICAgICAgICAgdmFyIGlqID0gX2kyICogTiArIF9qO1xuICAgICAgICAgIHZhciBraiA9IGsgKiBOICsgX2o7XG5cbiAgICAgICAgICBpZiAoZGlzdFtpa10gKyBkaXN0W2tqXSA8IGRpc3RbaWpdKSB7XG4gICAgICAgICAgICBkaXN0W2lqXSA9IGRpc3RbaWtdICsgZGlzdFtral07XG4gICAgICAgICAgICBuZXh0W2lqXSA9IG5leHRbaWtdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBnZXRBcmdFbGUgPSBmdW5jdGlvbiBnZXRBcmdFbGUoZWxlKSB7XG4gICAgICByZXR1cm4gKHN0cmluZyhlbGUpID8gY3kuZmlsdGVyKGVsZSkgOiBlbGUpWzBdO1xuICAgIH07XG5cbiAgICB2YXIgaW5kZXhPZkFyZ0VsZSA9IGZ1bmN0aW9uIGluZGV4T2ZBcmdFbGUoZWxlKSB7XG4gICAgICByZXR1cm4gaW5kZXhPZihnZXRBcmdFbGUoZWxlKSk7XG4gICAgfTtcblxuICAgIHZhciByZXMgPSB7XG4gICAgICBkaXN0YW5jZTogZnVuY3Rpb24gZGlzdGFuY2UoZnJvbSwgdG8pIHtcbiAgICAgICAgdmFyIGkgPSBpbmRleE9mQXJnRWxlKGZyb20pO1xuICAgICAgICB2YXIgaiA9IGluZGV4T2ZBcmdFbGUodG8pO1xuICAgICAgICByZXR1cm4gZGlzdFtpICogTiArIGpdO1xuICAgICAgfSxcbiAgICAgIHBhdGg6IGZ1bmN0aW9uIHBhdGgoZnJvbSwgdG8pIHtcbiAgICAgICAgdmFyIGkgPSBpbmRleE9mQXJnRWxlKGZyb20pO1xuICAgICAgICB2YXIgaiA9IGluZGV4T2ZBcmdFbGUodG8pO1xuICAgICAgICB2YXIgZnJvbU5vZGUgPSBhdEluZGV4KGkpO1xuXG4gICAgICAgIGlmIChpID09PSBqKSB7XG4gICAgICAgICAgcmV0dXJuIGZyb21Ob2RlLmNvbGxlY3Rpb24oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZXh0W2kgKiBOICsgal0gPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiBjeS5jb2xsZWN0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcGF0aCA9IGN5LmNvbGxlY3Rpb24oKTtcbiAgICAgICAgdmFyIHByZXYgPSBpO1xuICAgICAgICB2YXIgZWRnZTtcbiAgICAgICAgcGF0aC5tZXJnZShmcm9tTm9kZSk7XG5cbiAgICAgICAgd2hpbGUgKGkgIT09IGopIHtcbiAgICAgICAgICBwcmV2ID0gaTtcbiAgICAgICAgICBpID0gbmV4dFtpICogTiArIGpdO1xuICAgICAgICAgIGVkZ2UgPSBlZGdlTmV4dFtwcmV2ICogTiArIGldO1xuICAgICAgICAgIHBhdGgubWVyZ2UoZWRnZSk7XG4gICAgICAgICAgcGF0aC5tZXJnZShhdEluZGV4KGkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIHJlcztcbiAgfSAvLyBmbG95ZFdhcnNoYWxsXG5cbn07IC8vIGVsZXNmblxuXG52YXIgYmVsbG1hbkZvcmREZWZhdWx0cyA9IGRlZmF1bHRzKHtcbiAgd2VpZ2h0OiBmdW5jdGlvbiB3ZWlnaHQoZWRnZSkge1xuICAgIHJldHVybiAxO1xuICB9LFxuICBkaXJlY3RlZDogZmFsc2UsXG4gIHJvb3Q6IG51bGxcbn0pO1xudmFyIGVsZXNmbiQ1ID0ge1xuICAvLyBJbXBsZW1lbnRlZCBmcm9tIHBzZXVkb2NvZGUgZnJvbSB3aWtpcGVkaWFcbiAgYmVsbG1hbkZvcmQ6IGZ1bmN0aW9uIGJlbGxtYW5Gb3JkKG9wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIF9iZWxsbWFuRm9yZERlZmF1bHRzID0gYmVsbG1hbkZvcmREZWZhdWx0cyhvcHRpb25zKSxcbiAgICAgICAgd2VpZ2h0ID0gX2JlbGxtYW5Gb3JkRGVmYXVsdHMud2VpZ2h0LFxuICAgICAgICBkaXJlY3RlZCA9IF9iZWxsbWFuRm9yZERlZmF1bHRzLmRpcmVjdGVkLFxuICAgICAgICByb290ID0gX2JlbGxtYW5Gb3JkRGVmYXVsdHMucm9vdDtcblxuICAgIHZhciB3ZWlnaHRGbiA9IHdlaWdodDtcbiAgICB2YXIgZWxlcyA9IHRoaXM7XG4gICAgdmFyIGN5ID0gdGhpcy5jeSgpO1xuXG4gICAgdmFyIF90aGlzJGJ5R3JvdXAgPSB0aGlzLmJ5R3JvdXAoKSxcbiAgICAgICAgZWRnZXMgPSBfdGhpcyRieUdyb3VwLmVkZ2VzLFxuICAgICAgICBub2RlcyA9IF90aGlzJGJ5R3JvdXAubm9kZXM7XG5cbiAgICB2YXIgbnVtTm9kZXMgPSBub2Rlcy5sZW5ndGg7XG4gICAgdmFyIGluZm9NYXAgPSBuZXcgTWFwJDEoKTtcbiAgICB2YXIgaGFzTmVnYXRpdmVXZWlnaHRDeWNsZSA9IGZhbHNlO1xuICAgIHZhciBuZWdhdGl2ZVdlaWdodEN5Y2xlcyA9IFtdO1xuICAgIHJvb3QgPSBjeS5jb2xsZWN0aW9uKHJvb3QpWzBdOyAvLyBpbiBjYXNlIHNlbGVjdG9yIHBhc3NlZFxuXG4gICAgZWRnZXMudW5tZXJnZUJ5KGZ1bmN0aW9uIChlZGdlKSB7XG4gICAgICByZXR1cm4gZWRnZS5pc0xvb3AoKTtcbiAgICB9KTtcbiAgICB2YXIgbnVtRWRnZXMgPSBlZGdlcy5sZW5ndGg7XG5cbiAgICB2YXIgZ2V0SW5mbyA9IGZ1bmN0aW9uIGdldEluZm8obm9kZSkge1xuICAgICAgdmFyIG9iaiA9IGluZm9NYXAuZ2V0KG5vZGUuaWQoKSk7XG5cbiAgICAgIGlmICghb2JqKSB7XG4gICAgICAgIG9iaiA9IHt9O1xuICAgICAgICBpbmZvTWFwLnNldChub2RlLmlkKCksIG9iaik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmo7XG4gICAgfTtcblxuICAgIHZhciBnZXROb2RlRnJvbVRvID0gZnVuY3Rpb24gZ2V0Tm9kZUZyb21Ubyh0bykge1xuICAgICAgcmV0dXJuIChzdHJpbmcodG8pID8gY3kuJCh0bykgOiB0bylbMF07XG4gICAgfTtcblxuICAgIHZhciBkaXN0YW5jZVRvID0gZnVuY3Rpb24gZGlzdGFuY2VUbyh0bykge1xuICAgICAgcmV0dXJuIGdldEluZm8oZ2V0Tm9kZUZyb21Ubyh0bykpLmRpc3Q7XG4gICAgfTtcblxuICAgIHZhciBwYXRoVG8gPSBmdW5jdGlvbiBwYXRoVG8odG8pIHtcbiAgICAgIHZhciB0aGlzU3RhcnQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHJvb3Q7XG4gICAgICB2YXIgZW5kID0gZ2V0Tm9kZUZyb21Ubyh0byk7XG4gICAgICB2YXIgcGF0aCA9IFtdO1xuICAgICAgdmFyIG5vZGUgPSBlbmQ7XG5cbiAgICAgIGZvciAoOzspIHtcbiAgICAgICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiBfdGhpcy5zcGF3bigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIF9nZXRJbmZvID0gZ2V0SW5mbyhub2RlKSxcbiAgICAgICAgICAgIGVkZ2UgPSBfZ2V0SW5mby5lZGdlLFxuICAgICAgICAgICAgcHJlZCA9IF9nZXRJbmZvLnByZWQ7XG5cbiAgICAgICAgcGF0aC51bnNoaWZ0KG5vZGVbMF0pO1xuXG4gICAgICAgIGlmIChub2RlLnNhbWUodGhpc1N0YXJ0KSAmJiBwYXRoLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlZGdlICE9IG51bGwpIHtcbiAgICAgICAgICBwYXRoLnVuc2hpZnQoZWRnZSk7XG4gICAgICAgIH1cblxuICAgICAgICBub2RlID0gcHJlZDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGVsZXMuc3Bhd24ocGF0aCk7XG4gICAgfTsgLy8gSW5pdGlhbGl6YXRpb25zIHsgZGlzdCwgcHJlZCwgZWRnZSB9XG5cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtTm9kZXM7IGkrKykge1xuICAgICAgdmFyIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgIHZhciBpbmZvID0gZ2V0SW5mbyhub2RlKTtcblxuICAgICAgaWYgKG5vZGUuc2FtZShyb290KSkge1xuICAgICAgICBpbmZvLmRpc3QgPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5mby5kaXN0ID0gSW5maW5pdHk7XG4gICAgICB9XG5cbiAgICAgIGluZm8ucHJlZCA9IG51bGw7XG4gICAgICBpbmZvLmVkZ2UgPSBudWxsO1xuICAgIH0gLy8gRWRnZXMgcmVsYXhhdGlvblxuXG5cbiAgICB2YXIgcmVwbGFjZWRFZGdlID0gZmFsc2U7XG5cbiAgICB2YXIgY2hlY2tGb3JFZGdlUmVwbGFjZW1lbnQgPSBmdW5jdGlvbiBjaGVja0ZvckVkZ2VSZXBsYWNlbWVudChub2RlMSwgbm9kZTIsIGVkZ2UsIGluZm8xLCBpbmZvMiwgd2VpZ2h0KSB7XG4gICAgICB2YXIgZGlzdCA9IGluZm8xLmRpc3QgKyB3ZWlnaHQ7XG5cbiAgICAgIGlmIChkaXN0IDwgaW5mbzIuZGlzdCAmJiAhZWRnZS5zYW1lKGluZm8xLmVkZ2UpKSB7XG4gICAgICAgIGluZm8yLmRpc3QgPSBkaXN0O1xuICAgICAgICBpbmZvMi5wcmVkID0gbm9kZTE7XG4gICAgICAgIGluZm8yLmVkZ2UgPSBlZGdlO1xuICAgICAgICByZXBsYWNlZEVkZ2UgPSB0cnVlO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBmb3IgKHZhciBfaSA9IDE7IF9pIDwgbnVtTm9kZXM7IF9pKyspIHtcbiAgICAgIHJlcGxhY2VkRWRnZSA9IGZhbHNlO1xuXG4gICAgICBmb3IgKHZhciBlID0gMDsgZSA8IG51bUVkZ2VzOyBlKyspIHtcbiAgICAgICAgdmFyIGVkZ2UgPSBlZGdlc1tlXTtcbiAgICAgICAgdmFyIHNyYyA9IGVkZ2Uuc291cmNlKCk7XG4gICAgICAgIHZhciB0Z3QgPSBlZGdlLnRhcmdldCgpO1xuXG4gICAgICAgIHZhciBfd2VpZ2h0ID0gd2VpZ2h0Rm4oZWRnZSk7XG5cbiAgICAgICAgdmFyIHNyY0luZm8gPSBnZXRJbmZvKHNyYyk7XG4gICAgICAgIHZhciB0Z3RJbmZvID0gZ2V0SW5mbyh0Z3QpO1xuICAgICAgICBjaGVja0ZvckVkZ2VSZXBsYWNlbWVudChzcmMsIHRndCwgZWRnZSwgc3JjSW5mbywgdGd0SW5mbywgX3dlaWdodCk7IC8vIElmIHVuZGlyZWN0ZWQgZ3JhcGgsIHdlIG5lZWQgdG8gdGFrZSBpbnRvIGFjY291bnQgdGhlICdyZXZlcnNlJyBlZGdlXG5cbiAgICAgICAgaWYgKCFkaXJlY3RlZCkge1xuICAgICAgICAgIGNoZWNrRm9yRWRnZVJlcGxhY2VtZW50KHRndCwgc3JjLCBlZGdlLCB0Z3RJbmZvLCBzcmNJbmZvLCBfd2VpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIXJlcGxhY2VkRWRnZSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocmVwbGFjZWRFZGdlKSB7XG4gICAgICAvLyBDaGVjayBmb3IgbmVnYXRpdmUgd2VpZ2h0IGN5Y2xlc1xuICAgICAgZm9yICh2YXIgX2UgPSAwOyBfZSA8IG51bUVkZ2VzOyBfZSsrKSB7XG4gICAgICAgIHZhciBfZWRnZSA9IGVkZ2VzW19lXTtcblxuICAgICAgICB2YXIgX3NyYyA9IF9lZGdlLnNvdXJjZSgpO1xuXG4gICAgICAgIHZhciBfdGd0ID0gX2VkZ2UudGFyZ2V0KCk7XG5cbiAgICAgICAgdmFyIF93ZWlnaHQyID0gd2VpZ2h0Rm4oX2VkZ2UpO1xuXG4gICAgICAgIHZhciBzcmNEaXN0ID0gZ2V0SW5mbyhfc3JjKS5kaXN0O1xuICAgICAgICB2YXIgdGd0RGlzdCA9IGdldEluZm8oX3RndCkuZGlzdDtcblxuICAgICAgICBpZiAoc3JjRGlzdCArIF93ZWlnaHQyIDwgdGd0RGlzdCB8fCAhZGlyZWN0ZWQgJiYgdGd0RGlzdCArIF93ZWlnaHQyIDwgc3JjRGlzdCkge1xuICAgICAgICAgIHdhcm4oJ0dyYXBoIGNvbnRhaW5zIGEgbmVnYXRpdmUgd2VpZ2h0IGN5Y2xlIGZvciBCZWxsbWFuLUZvcmQnKTtcbiAgICAgICAgICBoYXNOZWdhdGl2ZVdlaWdodEN5Y2xlID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkaXN0YW5jZVRvOiBkaXN0YW5jZVRvLFxuICAgICAgcGF0aFRvOiBwYXRoVG8sXG4gICAgICBoYXNOZWdhdGl2ZVdlaWdodEN5Y2xlOiBoYXNOZWdhdGl2ZVdlaWdodEN5Y2xlLFxuICAgICAgbmVnYXRpdmVXZWlnaHRDeWNsZXM6IG5lZ2F0aXZlV2VpZ2h0Q3ljbGVzXG4gICAgfTtcbiAgfSAvLyBiZWxsbWFuRm9yZFxuXG59OyAvLyBlbGVzZm5cblxudmFyIHNxcnQyID0gTWF0aC5zcXJ0KDIpOyAvLyBGdW5jdGlvbiB3aGljaCBjb2xhcHNlcyAyIChtZXRhKSBub2RlcyBpbnRvIG9uZVxuLy8gVXBkYXRlcyB0aGUgcmVtYWluaW5nIGVkZ2UgbGlzdHNcbi8vIFJlY2VpdmVzIGFzIGEgcGFyYW1hdGVyIHRoZSBlZGdlIHdoaWNoIGNhdXNlcyB0aGUgY29sbGFwc2VcblxudmFyIGNvbGxhcHNlID0gZnVuY3Rpb24gY29sbGFwc2UoZWRnZUluZGV4LCBub2RlTWFwLCByZW1haW5pbmdFZGdlcykge1xuICBpZiAocmVtYWluaW5nRWRnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgZXJyb3IoXCJLYXJnZXItU3RlaW4gbXVzdCBiZSBydW4gb24gYSBjb25uZWN0ZWQgKHN1YilncmFwaFwiKTtcbiAgfVxuXG4gIHZhciBlZGdlSW5mbyA9IHJlbWFpbmluZ0VkZ2VzW2VkZ2VJbmRleF07XG4gIHZhciBzb3VyY2VJbiA9IGVkZ2VJbmZvWzFdO1xuICB2YXIgdGFyZ2V0SW4gPSBlZGdlSW5mb1syXTtcbiAgdmFyIHBhcnRpdGlvbjEgPSBub2RlTWFwW3NvdXJjZUluXTtcbiAgdmFyIHBhcnRpdGlvbjIgPSBub2RlTWFwW3RhcmdldEluXTtcbiAgdmFyIG5ld0VkZ2VzID0gcmVtYWluaW5nRWRnZXM7IC8vIHJlLXVzZSBhcnJheVxuICAvLyBEZWxldGUgYWxsIGVkZ2VzIGJldHdlZW4gcGFydGl0aW9uMSBhbmQgcGFydGl0aW9uMlxuXG4gIGZvciAodmFyIGkgPSBuZXdFZGdlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHZhciBlZGdlID0gbmV3RWRnZXNbaV07XG4gICAgdmFyIHNyYyA9IGVkZ2VbMV07XG4gICAgdmFyIHRndCA9IGVkZ2VbMl07XG5cbiAgICBpZiAobm9kZU1hcFtzcmNdID09PSBwYXJ0aXRpb24xICYmIG5vZGVNYXBbdGd0XSA9PT0gcGFydGl0aW9uMiB8fCBub2RlTWFwW3NyY10gPT09IHBhcnRpdGlvbjIgJiYgbm9kZU1hcFt0Z3RdID09PSBwYXJ0aXRpb24xKSB7XG4gICAgICBuZXdFZGdlcy5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9IC8vIEFsbCBlZGdlcyBwb2ludGluZyB0byBwYXJ0aXRpb24yIHNob3VsZCBub3cgcG9pbnQgdG8gcGFydGl0aW9uMVxuXG5cbiAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IG5ld0VkZ2VzLmxlbmd0aDsgX2krKykge1xuICAgIHZhciBfZWRnZSA9IG5ld0VkZ2VzW19pXTtcblxuICAgIGlmIChfZWRnZVsxXSA9PT0gcGFydGl0aW9uMikge1xuICAgICAgLy8gQ2hlY2sgc291cmNlXG4gICAgICBuZXdFZGdlc1tfaV0gPSBfZWRnZS5zbGljZSgpOyAvLyBjb3B5XG5cbiAgICAgIG5ld0VkZ2VzW19pXVsxXSA9IHBhcnRpdGlvbjE7XG4gICAgfSBlbHNlIGlmIChfZWRnZVsyXSA9PT0gcGFydGl0aW9uMikge1xuICAgICAgLy8gQ2hlY2sgdGFyZ2V0XG4gICAgICBuZXdFZGdlc1tfaV0gPSBfZWRnZS5zbGljZSgpOyAvLyBjb3B5XG5cbiAgICAgIG5ld0VkZ2VzW19pXVsyXSA9IHBhcnRpdGlvbjE7XG4gICAgfVxuICB9IC8vIE1vdmUgYWxsIG5vZGVzIGZyb20gcGFydGl0aW9uMiB0byBwYXJ0aXRpb24xXG5cblxuICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBub2RlTWFwLmxlbmd0aDsgX2kyKyspIHtcbiAgICBpZiAobm9kZU1hcFtfaTJdID09PSBwYXJ0aXRpb24yKSB7XG4gICAgICBub2RlTWFwW19pMl0gPSBwYXJ0aXRpb24xO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdFZGdlcztcbn07IC8vIENvbnRyYWN0cyBhIGdyYXBoIHVudGlsIHdlIHJlYWNoIGEgY2VydGFpbiBudW1iZXIgb2YgbWV0YSBub2Rlc1xuXG5cbnZhciBjb250cmFjdFVudGlsID0gZnVuY3Rpb24gY29udHJhY3RVbnRpbChtZXRhTm9kZU1hcCwgcmVtYWluaW5nRWRnZXMsIHNpemUsIHNpemVMaW1pdCkge1xuICB3aGlsZSAoc2l6ZSA+IHNpemVMaW1pdCkge1xuICAgIC8vIENob29zZSBhbiBlZGdlIHJhbmRvbWx5XG4gICAgdmFyIGVkZ2VJbmRleCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHJlbWFpbmluZ0VkZ2VzLmxlbmd0aCk7IC8vIENvbGxhcHNlIGdyYXBoIGJhc2VkIG9uIGVkZ2VcblxuICAgIHJlbWFpbmluZ0VkZ2VzID0gY29sbGFwc2UoZWRnZUluZGV4LCBtZXRhTm9kZU1hcCwgcmVtYWluaW5nRWRnZXMpO1xuICAgIHNpemUtLTtcbiAgfVxuXG4gIHJldHVybiByZW1haW5pbmdFZGdlcztcbn07XG5cbnZhciBlbGVzZm4kNiA9IHtcbiAgLy8gQ29tcHV0ZXMgdGhlIG1pbmltdW0gY3V0IG9mIGFuIHVuZGlyZWN0ZWQgZ3JhcGhcbiAgLy8gUmV0dXJucyB0aGUgY29ycmVjdCBhbnN3ZXIgd2l0aCBoaWdoIHByb2JhYmlsaXR5XG4gIGthcmdlclN0ZWluOiBmdW5jdGlvbiBrYXJnZXJTdGVpbigpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIF90aGlzJGJ5R3JvdXAgPSB0aGlzLmJ5R3JvdXAoKSxcbiAgICAgICAgbm9kZXMgPSBfdGhpcyRieUdyb3VwLm5vZGVzLFxuICAgICAgICBlZGdlcyA9IF90aGlzJGJ5R3JvdXAuZWRnZXM7XG5cbiAgICBlZGdlcy51bm1lcmdlQnkoZnVuY3Rpb24gKGVkZ2UpIHtcbiAgICAgIHJldHVybiBlZGdlLmlzTG9vcCgpO1xuICAgIH0pO1xuICAgIHZhciBudW1Ob2RlcyA9IG5vZGVzLmxlbmd0aDtcbiAgICB2YXIgbnVtRWRnZXMgPSBlZGdlcy5sZW5ndGg7XG4gICAgdmFyIG51bUl0ZXIgPSBNYXRoLmNlaWwoTWF0aC5wb3coTWF0aC5sb2cobnVtTm9kZXMpIC8gTWF0aC5MTjIsIDIpKTtcbiAgICB2YXIgc3RvcFNpemUgPSBNYXRoLmZsb29yKG51bU5vZGVzIC8gc3FydDIpO1xuXG4gICAgaWYgKG51bU5vZGVzIDwgMikge1xuICAgICAgZXJyb3IoJ0F0IGxlYXN0IDIgbm9kZXMgYXJlIHJlcXVpcmVkIGZvciBLYXJnZXItU3RlaW4gYWxnb3JpdGhtJyk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH0gLy8gTm93IHN0b3JlIGVkZ2UgZGVzdGluYXRpb24gYXMgaW5kZXhlc1xuICAgIC8vIEZvcm1hdCBmb3IgZWFjaCBlZGdlIChlZGdlIGluZGV4LCBzb3VyY2Ugbm9kZSBpbmRleCwgdGFyZ2V0IG5vZGUgaW5kZXgpXG5cblxuICAgIHZhciBlZGdlSW5kZXhlcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1FZGdlczsgaSsrKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldO1xuICAgICAgZWRnZUluZGV4ZXMucHVzaChbaSwgbm9kZXMuaW5kZXhPZihlLnNvdXJjZSgpKSwgbm9kZXMuaW5kZXhPZihlLnRhcmdldCgpKV0pO1xuICAgIH0gLy8gV2Ugd2lsbCBzdG9yZSB0aGUgYmVzdCBjdXQgZm91bmQgaGVyZVxuXG5cbiAgICB2YXIgbWluQ3V0U2l6ZSA9IEluZmluaXR5O1xuICAgIHZhciBtaW5DdXRFZGdlSW5kZXhlcyA9IFtdO1xuICAgIHZhciBtaW5DdXROb2RlTWFwID0gbmV3IEFycmF5KG51bU5vZGVzKTsgLy8gSW5pdGlhbCBtZXRhIG5vZGUgcGFydGl0aW9uXG5cbiAgICB2YXIgbWV0YU5vZGVNYXAgPSBuZXcgQXJyYXkobnVtTm9kZXMpO1xuICAgIHZhciBtZXRhTm9kZU1hcDIgPSBuZXcgQXJyYXkobnVtTm9kZXMpO1xuXG4gICAgdmFyIGNvcHlOb2Rlc01hcCA9IGZ1bmN0aW9uIGNvcHlOb2Rlc01hcChmcm9tLCB0bykge1xuICAgICAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgbnVtTm9kZXM7IF9pMysrKSB7XG4gICAgICAgIHRvW19pM10gPSBmcm9tW19pM107XG4gICAgICB9XG4gICAgfTsgLy8gTWFpbiBsb29wXG5cblxuICAgIGZvciAodmFyIGl0ZXIgPSAwOyBpdGVyIDw9IG51bUl0ZXI7IGl0ZXIrKykge1xuICAgICAgLy8gUmVzZXQgbWV0YSBub2RlIHBhcnRpdGlvblxuICAgICAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgbnVtTm9kZXM7IF9pNCsrKSB7XG4gICAgICAgIG1ldGFOb2RlTWFwW19pNF0gPSBfaTQ7XG4gICAgICB9IC8vIENvbnRyYWN0IHVudGlsIHN0b3AgcG9pbnQgKHN0b3BTaXplIG5vZGVzKVxuXG5cbiAgICAgIHZhciBlZGdlc1N0YXRlID0gY29udHJhY3RVbnRpbChtZXRhTm9kZU1hcCwgZWRnZUluZGV4ZXMuc2xpY2UoKSwgbnVtTm9kZXMsIHN0b3BTaXplKTtcbiAgICAgIHZhciBlZGdlc1N0YXRlMiA9IGVkZ2VzU3RhdGUuc2xpY2UoKTsgLy8gY29weVxuICAgICAgLy8gQ3JlYXRlIGEgY29weSBvZiB0aGUgY29sYXBzZWQgbm9kZXMgc3RhdGVcblxuICAgICAgY29weU5vZGVzTWFwKG1ldGFOb2RlTWFwLCBtZXRhTm9kZU1hcDIpOyAvLyBSdW4gMiBpdGVyYXRpb25zIHN0YXJ0aW5nIGluIHRoZSBzdG9wIHN0YXRlXG5cbiAgICAgIHZhciByZXMxID0gY29udHJhY3RVbnRpbChtZXRhTm9kZU1hcCwgZWRnZXNTdGF0ZSwgc3RvcFNpemUsIDIpO1xuICAgICAgdmFyIHJlczIgPSBjb250cmFjdFVudGlsKG1ldGFOb2RlTWFwMiwgZWRnZXNTdGF0ZTIsIHN0b3BTaXplLCAyKTsgLy8gSXMgYW55IG9mIHRoZSAyIHJlc3VsdHMgdGhlIGJlc3QgY3V0IHNvIGZhcj9cblxuICAgICAgaWYgKHJlczEubGVuZ3RoIDw9IHJlczIubGVuZ3RoICYmIHJlczEubGVuZ3RoIDwgbWluQ3V0U2l6ZSkge1xuICAgICAgICBtaW5DdXRTaXplID0gcmVzMS5sZW5ndGg7XG4gICAgICAgIG1pbkN1dEVkZ2VJbmRleGVzID0gcmVzMTtcbiAgICAgICAgY29weU5vZGVzTWFwKG1ldGFOb2RlTWFwLCBtaW5DdXROb2RlTWFwKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzMi5sZW5ndGggPD0gcmVzMS5sZW5ndGggJiYgcmVzMi5sZW5ndGggPCBtaW5DdXRTaXplKSB7XG4gICAgICAgIG1pbkN1dFNpemUgPSByZXMyLmxlbmd0aDtcbiAgICAgICAgbWluQ3V0RWRnZUluZGV4ZXMgPSByZXMyO1xuICAgICAgICBjb3B5Tm9kZXNNYXAobWV0YU5vZGVNYXAyLCBtaW5DdXROb2RlTWFwKTtcbiAgICAgIH1cbiAgICB9IC8vIGVuZCBvZiBtYWluIGxvb3BcbiAgICAvLyBDb25zdHJ1Y3QgcmVzdWx0XG5cblxuICAgIHZhciBjdXQgPSB0aGlzLnNwYXduKG1pbkN1dEVkZ2VJbmRleGVzLm1hcChmdW5jdGlvbiAoZSkge1xuICAgICAgcmV0dXJuIGVkZ2VzW2VbMF1dO1xuICAgIH0pKTtcbiAgICB2YXIgcGFydGl0aW9uMSA9IHRoaXMuc3Bhd24oKTtcbiAgICB2YXIgcGFydGl0aW9uMiA9IHRoaXMuc3Bhd24oKTsgLy8gdHJhdmVyc2UgbWV0YU5vZGVNYXAgZm9yIGJlc3QgY3V0XG5cbiAgICB2YXIgd2l0bmVzc05vZGVQYXJ0aXRpb24gPSBtaW5DdXROb2RlTWFwWzBdO1xuXG4gICAgZm9yICh2YXIgX2k1ID0gMDsgX2k1IDwgbWluQ3V0Tm9kZU1hcC5sZW5ndGg7IF9pNSsrKSB7XG4gICAgICB2YXIgcGFydGl0aW9uSWQgPSBtaW5DdXROb2RlTWFwW19pNV07XG4gICAgICB2YXIgbm9kZSA9IG5vZGVzW19pNV07XG5cbiAgICAgIGlmIChwYXJ0aXRpb25JZCA9PT0gd2l0bmVzc05vZGVQYXJ0aXRpb24pIHtcbiAgICAgICAgcGFydGl0aW9uMS5tZXJnZShub2RlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcnRpdGlvbjIubWVyZ2Uobm9kZSk7XG4gICAgICB9XG4gICAgfSAvLyBjb25zdHJ1Y3QgY29tcG9uZW50cyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggZGlzam9pbnQgc3Vic2V0IG9mIG5vZGVzXG5cblxuICAgIHZhciBjb25zdHJ1Y3RDb21wb25lbnQgPSBmdW5jdGlvbiBjb25zdHJ1Y3RDb21wb25lbnQoc3Vic2V0KSB7XG4gICAgICB2YXIgY29tcG9uZW50ID0gX3RoaXMuc3Bhd24oKTtcblxuICAgICAgc3Vic2V0LmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgY29tcG9uZW50Lm1lcmdlKG5vZGUpO1xuICAgICAgICBub2RlLmNvbm5lY3RlZEVkZ2VzKCkuZm9yRWFjaChmdW5jdGlvbiAoZWRnZSkge1xuICAgICAgICAgIC8vIGVuc3VyZSBlZGdlIGlzIHdpdGhpbiBjYWxsaW5nIGNvbGxlY3Rpb24gYW5kIGVkZ2UgaXMgbm90IGluIGN1dFxuICAgICAgICAgIGlmIChfdGhpcy5jb250YWlucyhlZGdlKSAmJiAhY3V0LmNvbnRhaW5zKGVkZ2UpKSB7XG4gICAgICAgICAgICBjb21wb25lbnQubWVyZ2UoZWRnZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgICB9O1xuXG4gICAgdmFyIGNvbXBvbmVudHMgPSBbY29uc3RydWN0Q29tcG9uZW50KHBhcnRpdGlvbjEpLCBjb25zdHJ1Y3RDb21wb25lbnQocGFydGl0aW9uMildO1xuICAgIHZhciByZXQgPSB7XG4gICAgICBjdXQ6IGN1dCxcbiAgICAgIGNvbXBvbmVudHM6IGNvbXBvbmVudHMsXG4gICAgICAvLyBuLmIuIHBhcnRpdGlvbnMgYXJlIGluY2x1ZGVkIHRvIGJlIGNvbXBhdGlibGUgd2l0aCB0aGUgb2xkIGFwaSBzcGVjXG4gICAgICAvLyAoY291bGQgYmUgcmVtb3ZlZCBpbiBhIGZ1dHVyZSBtYWpvciB2ZXJzaW9uKVxuICAgICAgcGFydGl0aW9uMTogcGFydGl0aW9uMSxcbiAgICAgIHBhcnRpdGlvbjI6IHBhcnRpdGlvbjJcbiAgICB9O1xuICAgIHJldHVybiByZXQ7XG4gIH1cbn07IC8vIGVsZXNmblxuXG52YXIgY29weVBvc2l0aW9uID0gZnVuY3Rpb24gY29weVBvc2l0aW9uKHApIHtcbiAgcmV0dXJuIHtcbiAgICB4OiBwLngsXG4gICAgeTogcC55XG4gIH07XG59O1xudmFyIG1vZGVsVG9SZW5kZXJlZFBvc2l0aW9uID0gZnVuY3Rpb24gbW9kZWxUb1JlbmRlcmVkUG9zaXRpb24ocCwgem9vbSwgcGFuKSB7XG4gIHJldHVybiB7XG4gICAgeDogcC54ICogem9vbSArIHBhbi54LFxuICAgIHk6IHAueSAqIHpvb20gKyBwYW4ueVxuICB9O1xufTtcbnZhciByZW5kZXJlZFRvTW9kZWxQb3NpdGlvbiA9IGZ1bmN0aW9uIHJlbmRlcmVkVG9Nb2RlbFBvc2l0aW9uKHAsIHpvb20sIHBhbikge1xuICByZXR1cm4ge1xuICAgIHg6IChwLnggLSBwYW4ueCkgLyB6b29tLFxuICAgIHk6IChwLnkgLSBwYW4ueSkgLyB6b29tXG4gIH07XG59O1xudmFyIGFycmF5MnBvaW50ID0gZnVuY3Rpb24gYXJyYXkycG9pbnQoYXJyKSB7XG4gIHJldHVybiB7XG4gICAgeDogYXJyWzBdLFxuICAgIHk6IGFyclsxXVxuICB9O1xufTtcbnZhciBtaW4gPSBmdW5jdGlvbiBtaW4oYXJyKSB7XG4gIHZhciBiZWdpbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogMDtcbiAgdmFyIGVuZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogYXJyLmxlbmd0aDtcbiAgdmFyIG1pbiA9IEluZmluaXR5O1xuXG4gIGZvciAodmFyIGkgPSBiZWdpbjsgaSA8IGVuZDsgaSsrKSB7XG4gICAgdmFyIHZhbCA9IGFycltpXTtcblxuICAgIGlmIChpc0Zpbml0ZSh2YWwpKSB7XG4gICAgICBtaW4gPSBNYXRoLm1pbih2YWwsIG1pbik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1pbjtcbn07XG52YXIgbWF4ID0gZnVuY3Rpb24gbWF4KGFycikge1xuICB2YXIgYmVnaW4gPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDA7XG4gIHZhciBlbmQgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGFyci5sZW5ndGg7XG4gIHZhciBtYXggPSAtSW5maW5pdHk7XG5cbiAgZm9yICh2YXIgaSA9IGJlZ2luOyBpIDwgZW5kOyBpKyspIHtcbiAgICB2YXIgdmFsID0gYXJyW2ldO1xuXG4gICAgaWYgKGlzRmluaXRlKHZhbCkpIHtcbiAgICAgIG1heCA9IE1hdGgubWF4KHZhbCwgbWF4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWF4O1xufTtcbnZhciBtZWFuID0gZnVuY3Rpb24gbWVhbihhcnIpIHtcbiAgdmFyIGJlZ2luID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAwO1xuICB2YXIgZW5kID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBhcnIubGVuZ3RoO1xuICB2YXIgdG90YWwgPSAwO1xuICB2YXIgbiA9IDA7XG5cbiAgZm9yICh2YXIgaSA9IGJlZ2luOyBpIDwgZW5kOyBpKyspIHtcbiAgICB2YXIgdmFsID0gYXJyW2ldO1xuXG4gICAgaWYgKGlzRmluaXRlKHZhbCkpIHtcbiAgICAgIHRvdGFsICs9IHZhbDtcbiAgICAgIG4rKztcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdG90YWwgLyBuO1xufTtcbnZhciBtZWRpYW4gPSBmdW5jdGlvbiBtZWRpYW4oYXJyKSB7XG4gIHZhciBiZWdpbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogMDtcbiAgdmFyIGVuZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogYXJyLmxlbmd0aDtcbiAgdmFyIGNvcHkgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IHRydWU7XG4gIHZhciBzb3J0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDQgJiYgYXJndW1lbnRzWzRdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNF0gOiB0cnVlO1xuICB2YXIgaW5jbHVkZUhvbGVzID0gYXJndW1lbnRzLmxlbmd0aCA+IDUgJiYgYXJndW1lbnRzWzVdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNV0gOiB0cnVlO1xuXG4gIGlmIChjb3B5KSB7XG4gICAgYXJyID0gYXJyLnNsaWNlKGJlZ2luLCBlbmQpO1xuICB9IGVsc2Uge1xuICAgIGlmIChlbmQgPCBhcnIubGVuZ3RoKSB7XG4gICAgICBhcnIuc3BsaWNlKGVuZCwgYXJyLmxlbmd0aCAtIGVuZCk7XG4gICAgfVxuXG4gICAgaWYgKGJlZ2luID4gMCkge1xuICAgICAgYXJyLnNwbGljZSgwLCBiZWdpbik7XG4gICAgfVxuICB9IC8vIGFsbCBub24gZmluaXRlIChlLmcuIEluZmluaXR5LCBOYU4pIGVsZW1lbnRzIG11c3QgYmUgLUluZmluaXR5IHNvIHRoZXkgZ28gdG8gdGhlIHN0YXJ0XG5cblxuICB2YXIgb2ZmID0gMDsgLy8gb2Zmc2V0IGZyb20gbm9uLWZpbml0ZSB2YWx1ZXNcblxuICBmb3IgKHZhciBpID0gYXJyLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgdmFyIHYgPSBhcnJbaV07XG5cbiAgICBpZiAoaW5jbHVkZUhvbGVzKSB7XG4gICAgICBpZiAoIWlzRmluaXRlKHYpKSB7XG4gICAgICAgIGFycltpXSA9IC1JbmZpbml0eTtcbiAgICAgICAgb2ZmKys7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGp1c3QgcmVtb3ZlIGl0IGlmIHdlIGRvbid0IHdhbnQgdG8gY29uc2lkZXIgaG9sZXNcbiAgICAgIGFyci5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHNvcnQpIHtcbiAgICBhcnIuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGEgLSBiO1xuICAgIH0pOyAvLyByZXF1aXJlcyBjb3B5ID0gdHJ1ZSBpZiB5b3UgZG9uJ3Qgd2FudCB0byBjaGFuZ2UgdGhlIG9yaWdcbiAgfVxuXG4gIHZhciBsZW4gPSBhcnIubGVuZ3RoO1xuICB2YXIgbWlkID0gTWF0aC5mbG9vcihsZW4gLyAyKTtcblxuICBpZiAobGVuICUgMiAhPT0gMCkge1xuICAgIHJldHVybiBhcnJbbWlkICsgMSArIG9mZl07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIChhcnJbbWlkIC0gMSArIG9mZl0gKyBhcnJbbWlkICsgb2ZmXSkgLyAyO1xuICB9XG59O1xudmFyIGRlZzJyYWQgPSBmdW5jdGlvbiBkZWcycmFkKGRlZykge1xuICByZXR1cm4gTWF0aC5QSSAqIGRlZyAvIDE4MDtcbn07XG52YXIgZ2V0QW5nbGVGcm9tRGlzcCA9IGZ1bmN0aW9uIGdldEFuZ2xlRnJvbURpc3AoZGlzcFgsIGRpc3BZKSB7XG4gIHJldHVybiBNYXRoLmF0YW4yKGRpc3BZLCBkaXNwWCkgLSBNYXRoLlBJIC8gMjtcbn07XG52YXIgbG9nMiA9IE1hdGgubG9nMiB8fCBmdW5jdGlvbiAobikge1xuICByZXR1cm4gTWF0aC5sb2cobikgLyBNYXRoLmxvZygyKTtcbn07XG52YXIgc2lnbnVtID0gZnVuY3Rpb24gc2lnbnVtKHgpIHtcbiAgaWYgKHggPiAwKSB7XG4gICAgcmV0dXJuIDE7XG4gIH0gZWxzZSBpZiAoeCA8IDApIHtcbiAgICByZXR1cm4gLTE7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbn07XG52YXIgZGlzdCA9IGZ1bmN0aW9uIGRpc3QocDEsIHAyKSB7XG4gIHJldHVybiBNYXRoLnNxcnQoc3FkaXN0KHAxLCBwMikpO1xufTtcbnZhciBzcWRpc3QgPSBmdW5jdGlvbiBzcWRpc3QocDEsIHAyKSB7XG4gIHZhciBkeCA9IHAyLnggLSBwMS54O1xuICB2YXIgZHkgPSBwMi55IC0gcDEueTtcbiAgcmV0dXJuIGR4ICogZHggKyBkeSAqIGR5O1xufTtcbnZhciBpblBsYWNlU3VtTm9ybWFsaXplID0gZnVuY3Rpb24gaW5QbGFjZVN1bU5vcm1hbGl6ZSh2KSB7XG4gIHZhciBsZW5ndGggPSB2Lmxlbmd0aDsgLy8gRmlyc3QsIGdldCBzdW0gb2YgYWxsIGVsZW1lbnRzXG5cbiAgdmFyIHRvdGFsID0gMDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdG90YWwgKz0gdltpXTtcbiAgfSAvLyBOb3csIGRpdmlkZSBlYWNoIGJ5IHRoZSBzdW0gb2YgYWxsIGVsZW1lbnRzXG5cblxuICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbGVuZ3RoOyBfaSsrKSB7XG4gICAgdltfaV0gPSB2W19pXSAvIHRvdGFsO1xuICB9XG5cbiAgcmV0dXJuIHY7XG59O1xuXG52YXIgcWJlemllckF0ID0gZnVuY3Rpb24gcWJlemllckF0KHAwLCBwMSwgcDIsIHQpIHtcbiAgcmV0dXJuICgxIC0gdCkgKiAoMSAtIHQpICogcDAgKyAyICogKDEgLSB0KSAqIHQgKiBwMSArIHQgKiB0ICogcDI7XG59O1xudmFyIHFiZXppZXJQdEF0ID0gZnVuY3Rpb24gcWJlemllclB0QXQocDAsIHAxLCBwMiwgdCkge1xuICByZXR1cm4ge1xuICAgIHg6IHFiZXppZXJBdChwMC54LCBwMS54LCBwMi54LCB0KSxcbiAgICB5OiBxYmV6aWVyQXQocDAueSwgcDEueSwgcDIueSwgdClcbiAgfTtcbn07XG52YXIgbGluZUF0ID0gZnVuY3Rpb24gbGluZUF0KHAwLCBwMSwgdCwgZCkge1xuICB2YXIgdmVjID0ge1xuICAgIHg6IHAxLnggLSBwMC54LFxuICAgIHk6IHAxLnkgLSBwMC55XG4gIH07XG4gIHZhciB2ZWNEaXN0ID0gZGlzdChwMCwgcDEpO1xuICB2YXIgbm9ybVZlYyA9IHtcbiAgICB4OiB2ZWMueCAvIHZlY0Rpc3QsXG4gICAgeTogdmVjLnkgLyB2ZWNEaXN0XG4gIH07XG4gIHQgPSB0ID09IG51bGwgPyAwIDogdDtcbiAgZCA9IGQgIT0gbnVsbCA/IGQgOiB0ICogdmVjRGlzdDtcbiAgcmV0dXJuIHtcbiAgICB4OiBwMC54ICsgbm9ybVZlYy54ICogZCxcbiAgICB5OiBwMC55ICsgbm9ybVZlYy55ICogZFxuICB9O1xufTtcbnZhciBib3VuZCA9IGZ1bmN0aW9uIGJvdW5kKG1pbiwgdmFsLCBtYXgpIHtcbiAgcmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4obWF4LCB2YWwpKTtcbn07IC8vIG1ha2VzIGEgZnVsbCBiYiAoeDEsIHkxLCB4MiwgeTIsIHcsIGgpIGZyb20gaW1wbGljaXQgcGFyYW1zXG5cbnZhciBtYWtlQm91bmRpbmdCb3ggPSBmdW5jdGlvbiBtYWtlQm91bmRpbmdCb3goYmIpIHtcbiAgaWYgKGJiID09IG51bGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgeDE6IEluZmluaXR5LFxuICAgICAgeTE6IEluZmluaXR5LFxuICAgICAgeDI6IC1JbmZpbml0eSxcbiAgICAgIHkyOiAtSW5maW5pdHksXG4gICAgICB3OiAwLFxuICAgICAgaDogMFxuICAgIH07XG4gIH0gZWxzZSBpZiAoYmIueDEgIT0gbnVsbCAmJiBiYi55MSAhPSBudWxsKSB7XG4gICAgaWYgKGJiLngyICE9IG51bGwgJiYgYmIueTIgIT0gbnVsbCAmJiBiYi54MiA+PSBiYi54MSAmJiBiYi55MiA+PSBiYi55MSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgeDE6IGJiLngxLFxuICAgICAgICB5MTogYmIueTEsXG4gICAgICAgIHgyOiBiYi54MixcbiAgICAgICAgeTI6IGJiLnkyLFxuICAgICAgICB3OiBiYi54MiAtIGJiLngxLFxuICAgICAgICBoOiBiYi55MiAtIGJiLnkxXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAoYmIudyAhPSBudWxsICYmIGJiLmggIT0gbnVsbCAmJiBiYi53ID49IDAgJiYgYmIuaCA+PSAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB4MTogYmIueDEsXG4gICAgICAgIHkxOiBiYi55MSxcbiAgICAgICAgeDI6IGJiLngxICsgYmIudyxcbiAgICAgICAgeTI6IGJiLnkxICsgYmIuaCxcbiAgICAgICAgdzogYmIudyxcbiAgICAgICAgaDogYmIuaFxuICAgICAgfTtcbiAgICB9XG4gIH1cbn07XG52YXIgY29weUJvdW5kaW5nQm94ID0gZnVuY3Rpb24gY29weUJvdW5kaW5nQm94KGJiKSB7XG4gIHJldHVybiB7XG4gICAgeDE6IGJiLngxLFxuICAgIHgyOiBiYi54MixcbiAgICB3OiBiYi53LFxuICAgIHkxOiBiYi55MSxcbiAgICB5MjogYmIueTIsXG4gICAgaDogYmIuaFxuICB9O1xufTtcbnZhciBjbGVhckJvdW5kaW5nQm94ID0gZnVuY3Rpb24gY2xlYXJCb3VuZGluZ0JveChiYikge1xuICBiYi54MSA9IEluZmluaXR5O1xuICBiYi55MSA9IEluZmluaXR5O1xuICBiYi54MiA9IC1JbmZpbml0eTtcbiAgYmIueTIgPSAtSW5maW5pdHk7XG4gIGJiLncgPSAwO1xuICBiYi5oID0gMDtcbn07XG52YXIgdXBkYXRlQm91bmRpbmdCb3ggPSBmdW5jdGlvbiB1cGRhdGVCb3VuZGluZ0JveChiYjEsIGJiMikge1xuICAvLyB1cGRhdGUgYmIxIHdpdGggYmIyIGJvdW5kc1xuICBiYjEueDEgPSBNYXRoLm1pbihiYjEueDEsIGJiMi54MSk7XG4gIGJiMS54MiA9IE1hdGgubWF4KGJiMS54MiwgYmIyLngyKTtcbiAgYmIxLncgPSBiYjEueDIgLSBiYjEueDE7XG4gIGJiMS55MSA9IE1hdGgubWluKGJiMS55MSwgYmIyLnkxKTtcbiAgYmIxLnkyID0gTWF0aC5tYXgoYmIxLnkyLCBiYjIueTIpO1xuICBiYjEuaCA9IGJiMS55MiAtIGJiMS55MTtcbn07XG52YXIgZXhwYW5kQm91bmRpbmdCb3hCeVBvaW50ID0gZnVuY3Rpb24gZXhwYW5kQm91bmRpbmdCb3hCeVBvaW50KGJiLCB4LCB5KSB7XG4gIGJiLngxID0gTWF0aC5taW4oYmIueDEsIHgpO1xuICBiYi54MiA9IE1hdGgubWF4KGJiLngyLCB4KTtcbiAgYmIudyA9IGJiLngyIC0gYmIueDE7XG4gIGJiLnkxID0gTWF0aC5taW4oYmIueTEsIHkpO1xuICBiYi55MiA9IE1hdGgubWF4KGJiLnkyLCB5KTtcbiAgYmIuaCA9IGJiLnkyIC0gYmIueTE7XG59O1xudmFyIGV4cGFuZEJvdW5kaW5nQm94ID0gZnVuY3Rpb24gZXhwYW5kQm91bmRpbmdCb3goYmIpIHtcbiAgdmFyIHBhZGRpbmcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDA7XG4gIGJiLngxIC09IHBhZGRpbmc7XG4gIGJiLngyICs9IHBhZGRpbmc7XG4gIGJiLnkxIC09IHBhZGRpbmc7XG4gIGJiLnkyICs9IHBhZGRpbmc7XG4gIGJiLncgPSBiYi54MiAtIGJiLngxO1xuICBiYi5oID0gYmIueTIgLSBiYi55MTtcbiAgcmV0dXJuIGJiO1xufTtcbnZhciBleHBhbmRCb3VuZGluZ0JveFNpZGVzID0gZnVuY3Rpb24gZXhwYW5kQm91bmRpbmdCb3hTaWRlcyhiYikge1xuICB2YXIgcGFkZGluZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogWzBdO1xuICB2YXIgdG9wLCByaWdodCwgYm90dG9tLCBsZWZ0O1xuXG4gIGlmIChwYWRkaW5nLmxlbmd0aCA9PT0gMSkge1xuICAgIHRvcCA9IHJpZ2h0ID0gYm90dG9tID0gbGVmdCA9IHBhZGRpbmdbMF07XG4gIH0gZWxzZSBpZiAocGFkZGluZy5sZW5ndGggPT09IDIpIHtcbiAgICB0b3AgPSBib3R0b20gPSBwYWRkaW5nWzBdO1xuICAgIGxlZnQgPSByaWdodCA9IHBhZGRpbmdbMV07XG4gIH0gZWxzZSBpZiAocGFkZGluZy5sZW5ndGggPT09IDQpIHtcbiAgICB2YXIgX3BhZGRpbmcgPSBfc2xpY2VkVG9BcnJheShwYWRkaW5nLCA0KTtcblxuICAgIHRvcCA9IF9wYWRkaW5nWzBdO1xuICAgIHJpZ2h0ID0gX3BhZGRpbmdbMV07XG4gICAgYm90dG9tID0gX3BhZGRpbmdbMl07XG4gICAgbGVmdCA9IF9wYWRkaW5nWzNdO1xuICB9XG5cbiAgYmIueDEgLT0gbGVmdDtcbiAgYmIueDIgKz0gcmlnaHQ7XG4gIGJiLnkxIC09IHRvcDtcbiAgYmIueTIgKz0gYm90dG9tO1xuICBiYi53ID0gYmIueDIgLSBiYi54MTtcbiAgYmIuaCA9IGJiLnkyIC0gYmIueTE7XG4gIHJldHVybiBiYjtcbn07XG5cbnZhciBhc3NpZ25Cb3VuZGluZ0JveCA9IGZ1bmN0aW9uIGFzc2lnbkJvdW5kaW5nQm94KGJiMSwgYmIyKSB7XG4gIGJiMS54MSA9IGJiMi54MTtcbiAgYmIxLnkxID0gYmIyLnkxO1xuICBiYjEueDIgPSBiYjIueDI7XG4gIGJiMS55MiA9IGJiMi55MjtcbiAgYmIxLncgPSBiYjEueDIgLSBiYjEueDE7XG4gIGJiMS5oID0gYmIxLnkyIC0gYmIxLnkxO1xufTtcbnZhciBhc3NpZ25TaGlmdFRvQm91bmRpbmdCb3ggPSBmdW5jdGlvbiBhc3NpZ25TaGlmdFRvQm91bmRpbmdCb3goYmIsIGRlbHRhKSB7XG4gIGJiLngxICs9IGRlbHRhLng7XG4gIGJiLngyICs9IGRlbHRhLng7XG4gIGJiLnkxICs9IGRlbHRhLnk7XG4gIGJiLnkyICs9IGRlbHRhLnk7XG59O1xudmFyIGJvdW5kaW5nQm94ZXNJbnRlcnNlY3QgPSBmdW5jdGlvbiBib3VuZGluZ0JveGVzSW50ZXJzZWN0KGJiMSwgYmIyKSB7XG4gIC8vIGNhc2U6IG9uZSBiYiB0byByaWdodCBvZiBvdGhlclxuICBpZiAoYmIxLngxID4gYmIyLngyKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGJiMi54MSA+IGJiMS54Mikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSAvLyBjYXNlOiBvbmUgYmIgdG8gbGVmdCBvZiBvdGhlclxuXG5cbiAgaWYgKGJiMS54MiA8IGJiMi54MSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChiYjIueDIgPCBiYjEueDEpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0gLy8gY2FzZTogb25lIGJiIGFib3ZlIG90aGVyXG5cblxuICBpZiAoYmIxLnkyIDwgYmIyLnkxKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGJiMi55MiA8IGJiMS55MSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSAvLyBjYXNlOiBvbmUgYmIgYmVsb3cgb3RoZXJcblxuXG4gIGlmIChiYjEueTEgPiBiYjIueTIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoYmIyLnkxID4gYmIxLnkyKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IC8vIG90aGVyd2lzZSwgbXVzdCBoYXZlIHNvbWUgb3ZlcmxhcFxuXG5cbiAgcmV0dXJuIHRydWU7XG59O1xudmFyIGluQm91bmRpbmdCb3ggPSBmdW5jdGlvbiBpbkJvdW5kaW5nQm94KGJiLCB4LCB5KSB7XG4gIHJldHVybiBiYi54MSA8PSB4ICYmIHggPD0gYmIueDIgJiYgYmIueTEgPD0geSAmJiB5IDw9IGJiLnkyO1xufTtcbnZhciBwb2ludEluQm91bmRpbmdCb3ggPSBmdW5jdGlvbiBwb2ludEluQm91bmRpbmdCb3goYmIsIHB0KSB7XG4gIHJldHVybiBpbkJvdW5kaW5nQm94KGJiLCBwdC54LCBwdC55KTtcbn07XG52YXIgYm91bmRpbmdCb3hJbkJvdW5kaW5nQm94ID0gZnVuY3Rpb24gYm91bmRpbmdCb3hJbkJvdW5kaW5nQm94KGJiMSwgYmIyKSB7XG4gIHJldHVybiBpbkJvdW5kaW5nQm94KGJiMSwgYmIyLngxLCBiYjIueTEpICYmIGluQm91bmRpbmdCb3goYmIxLCBiYjIueDIsIGJiMi55Mik7XG59O1xudmFyIHJvdW5kUmVjdGFuZ2xlSW50ZXJzZWN0TGluZSA9IGZ1bmN0aW9uIHJvdW5kUmVjdGFuZ2xlSW50ZXJzZWN0TGluZSh4LCB5LCBub2RlWCwgbm9kZVksIHdpZHRoLCBoZWlnaHQsIHBhZGRpbmcpIHtcbiAgdmFyIGNvcm5lclJhZGl1cyA9IGdldFJvdW5kUmVjdGFuZ2xlUmFkaXVzKHdpZHRoLCBoZWlnaHQpO1xuICB2YXIgaGFsZldpZHRoID0gd2lkdGggLyAyO1xuICB2YXIgaGFsZkhlaWdodCA9IGhlaWdodCAvIDI7IC8vIENoZWNrIGludGVyc2VjdGlvbnMgd2l0aCBzdHJhaWdodCBsaW5lIHNlZ21lbnRzXG5cbiAgdmFyIHN0cmFpZ2h0TGluZUludGVyc2VjdGlvbnM7IC8vIFRvcCBzZWdtZW50LCBsZWZ0IHRvIHJpZ2h0XG5cbiAge1xuICAgIHZhciB0b3BTdGFydFggPSBub2RlWCAtIGhhbGZXaWR0aCArIGNvcm5lclJhZGl1cyAtIHBhZGRpbmc7XG4gICAgdmFyIHRvcFN0YXJ0WSA9IG5vZGVZIC0gaGFsZkhlaWdodCAtIHBhZGRpbmc7XG4gICAgdmFyIHRvcEVuZFggPSBub2RlWCArIGhhbGZXaWR0aCAtIGNvcm5lclJhZGl1cyArIHBhZGRpbmc7XG4gICAgdmFyIHRvcEVuZFkgPSB0b3BTdGFydFk7XG4gICAgc3RyYWlnaHRMaW5lSW50ZXJzZWN0aW9ucyA9IGZpbml0ZUxpbmVzSW50ZXJzZWN0KHgsIHksIG5vZGVYLCBub2RlWSwgdG9wU3RhcnRYLCB0b3BTdGFydFksIHRvcEVuZFgsIHRvcEVuZFksIGZhbHNlKTtcblxuICAgIGlmIChzdHJhaWdodExpbmVJbnRlcnNlY3Rpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBzdHJhaWdodExpbmVJbnRlcnNlY3Rpb25zO1xuICAgIH1cbiAgfSAvLyBSaWdodCBzZWdtZW50LCB0b3AgdG8gYm90dG9tXG5cbiAge1xuICAgIHZhciByaWdodFN0YXJ0WCA9IG5vZGVYICsgaGFsZldpZHRoICsgcGFkZGluZztcbiAgICB2YXIgcmlnaHRTdGFydFkgPSBub2RlWSAtIGhhbGZIZWlnaHQgKyBjb3JuZXJSYWRpdXMgLSBwYWRkaW5nO1xuICAgIHZhciByaWdodEVuZFggPSByaWdodFN0YXJ0WDtcbiAgICB2YXIgcmlnaHRFbmRZID0gbm9kZVkgKyBoYWxmSGVpZ2h0IC0gY29ybmVyUmFkaXVzICsgcGFkZGluZztcbiAgICBzdHJhaWdodExpbmVJbnRlcnNlY3Rpb25zID0gZmluaXRlTGluZXNJbnRlcnNlY3QoeCwgeSwgbm9kZVgsIG5vZGVZLCByaWdodFN0YXJ0WCwgcmlnaHRTdGFydFksIHJpZ2h0RW5kWCwgcmlnaHRFbmRZLCBmYWxzZSk7XG5cbiAgICBpZiAoc3RyYWlnaHRMaW5lSW50ZXJzZWN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gc3RyYWlnaHRMaW5lSW50ZXJzZWN0aW9ucztcbiAgICB9XG4gIH0gLy8gQm90dG9tIHNlZ21lbnQsIGxlZnQgdG8gcmlnaHRcblxuICB7XG4gICAgdmFyIGJvdHRvbVN0YXJ0WCA9IG5vZGVYIC0gaGFsZldpZHRoICsgY29ybmVyUmFkaXVzIC0gcGFkZGluZztcbiAgICB2YXIgYm90dG9tU3RhcnRZID0gbm9kZVkgKyBoYWxmSGVpZ2h0ICsgcGFkZGluZztcbiAgICB2YXIgYm90dG9tRW5kWCA9IG5vZGVYICsgaGFsZldpZHRoIC0gY29ybmVyUmFkaXVzICsgcGFkZGluZztcbiAgICB2YXIgYm90dG9tRW5kWSA9IGJvdHRvbVN0YXJ0WTtcbiAgICBzdHJhaWdodExpbmVJbnRlcnNlY3Rpb25zID0gZmluaXRlTGluZXNJbnRlcnNlY3QoeCwgeSwgbm9kZVgsIG5vZGVZLCBib3R0b21TdGFydFgsIGJvdHRvbVN0YXJ0WSwgYm90dG9tRW5kWCwgYm90dG9tRW5kWSwgZmFsc2UpO1xuXG4gICAgaWYgKHN0cmFpZ2h0TGluZUludGVyc2VjdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHN0cmFpZ2h0TGluZUludGVyc2VjdGlvbnM7XG4gICAgfVxuICB9IC8vIExlZnQgc2VnbWVudCwgdG9wIHRvIGJvdHRvbVxuXG4gIHtcbiAgICB2YXIgbGVmdFN0YXJ0WCA9IG5vZGVYIC0gaGFsZldpZHRoIC0gcGFkZGluZztcbiAgICB2YXIgbGVmdFN0YXJ0WSA9IG5vZGVZIC0gaGFsZkhlaWdodCArIGNvcm5lclJhZGl1cyAtIHBhZGRpbmc7XG4gICAgdmFyIGxlZnRFbmRYID0gbGVmdFN0YXJ0WDtcbiAgICB2YXIgbGVmdEVuZFkgPSBub2RlWSArIGhhbGZIZWlnaHQgLSBjb3JuZXJSYWRpdXMgKyBwYWRkaW5nO1xuICAgIHN0cmFpZ2h0TGluZUludGVyc2VjdGlvbnMgPSBmaW5pdGVMaW5lc0ludGVyc2VjdCh4LCB5LCBub2RlWCwgbm9kZVksIGxlZnRTdGFydFgsIGxlZnRTdGFydFksIGxlZnRFbmRYLCBsZWZ0RW5kWSwgZmFsc2UpO1xuXG4gICAgaWYgKHN0cmFpZ2h0TGluZUludGVyc2VjdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHN0cmFpZ2h0TGluZUludGVyc2VjdGlvbnM7XG4gICAgfVxuICB9IC8vIENoZWNrIGludGVyc2VjdGlvbnMgd2l0aCBhcmMgc2VnbWVudHNcblxuICB2YXIgYXJjSW50ZXJzZWN0aW9uczsgLy8gVG9wIExlZnRcblxuICB7XG4gICAgdmFyIHRvcExlZnRDZW50ZXJYID0gbm9kZVggLSBoYWxmV2lkdGggKyBjb3JuZXJSYWRpdXM7XG4gICAgdmFyIHRvcExlZnRDZW50ZXJZID0gbm9kZVkgLSBoYWxmSGVpZ2h0ICsgY29ybmVyUmFkaXVzO1xuICAgIGFyY0ludGVyc2VjdGlvbnMgPSBpbnRlcnNlY3RMaW5lQ2lyY2xlKHgsIHksIG5vZGVYLCBub2RlWSwgdG9wTGVmdENlbnRlclgsIHRvcExlZnRDZW50ZXJZLCBjb3JuZXJSYWRpdXMgKyBwYWRkaW5nKTsgLy8gRW5zdXJlIHRoZSBpbnRlcnNlY3Rpb24gaXMgb24gdGhlIGRlc2lyZWQgcXVhcnRlciBvZiB0aGUgY2lyY2xlXG5cbiAgICBpZiAoYXJjSW50ZXJzZWN0aW9ucy5sZW5ndGggPiAwICYmIGFyY0ludGVyc2VjdGlvbnNbMF0gPD0gdG9wTGVmdENlbnRlclggJiYgYXJjSW50ZXJzZWN0aW9uc1sxXSA8PSB0b3BMZWZ0Q2VudGVyWSkge1xuICAgICAgcmV0dXJuIFthcmNJbnRlcnNlY3Rpb25zWzBdLCBhcmNJbnRlcnNlY3Rpb25zWzFdXTtcbiAgICB9XG4gIH0gLy8gVG9wIFJpZ2h0XG5cbiAge1xuICAgIHZhciB0b3BSaWdodENlbnRlclggPSBub2RlWCArIGhhbGZXaWR0aCAtIGNvcm5lclJhZGl1cztcbiAgICB2YXIgdG9wUmlnaHRDZW50ZXJZID0gbm9kZVkgLSBoYWxmSGVpZ2h0ICsgY29ybmVyUmFkaXVzO1xuICAgIGFyY0ludGVyc2VjdGlvbnMgPSBpbnRlcnNlY3RMaW5lQ2lyY2xlKHgsIHksIG5vZGVYLCBub2RlWSwgdG9wUmlnaHRDZW50ZXJYLCB0b3BSaWdodENlbnRlclksIGNvcm5lclJhZGl1cyArIHBhZGRpbmcpOyAvLyBFbnN1cmUgdGhlIGludGVyc2VjdGlvbiBpcyBvbiB0aGUgZGVzaXJlZCBxdWFydGVyIG9mIHRoZSBjaXJjbGVcblxuICAgIGlmIChhcmNJbnRlcnNlY3Rpb25zLmxlbmd0aCA+IDAgJiYgYXJjSW50ZXJzZWN0aW9uc1swXSA+PSB0b3BSaWdodENlbnRlclggJiYgYXJjSW50ZXJzZWN0aW9uc1sxXSA8PSB0b3BSaWdodENlbnRlclkpIHtcbiAgICAgIHJldHVybiBbYXJjSW50ZXJzZWN0aW9uc1swXSwgYXJjSW50ZXJzZWN0aW9uc1sxXV07XG4gICAgfVxuICB9IC8vIEJvdHRvbSBSaWdodFxuXG4gIHtcbiAgICB2YXIgYm90dG9tUmlnaHRDZW50ZXJYID0gbm9kZVggKyBoYWxmV2lkdGggLSBjb3JuZXJSYWRpdXM7XG4gICAgdmFyIGJvdHRvbVJpZ2h0Q2VudGVyWSA9IG5vZGVZICsgaGFsZkhlaWdodCAtIGNvcm5lclJhZGl1cztcbiAgICBhcmNJbnRlcnNlY3Rpb25zID0gaW50ZXJzZWN0TGluZUNpcmNsZSh4LCB5LCBub2RlWCwgbm9kZVksIGJvdHRvbVJpZ2h0Q2VudGVyWCwgYm90dG9tUmlnaHRDZW50ZXJZLCBjb3JuZXJSYWRpdXMgKyBwYWRkaW5nKTsgLy8gRW5zdXJlIHRoZSBpbnRlcnNlY3Rpb24gaXMgb24gdGhlIGRlc2lyZWQgcXVhcnRlciBvZiB0aGUgY2lyY2xlXG5cbiAgICBpZiAoYXJjSW50ZXJzZWN0aW9ucy5sZW5ndGggPiAwICYmIGFyY0ludGVyc2VjdGlvbnNbMF0gPj0gYm90dG9tUmlnaHRDZW50ZXJYICYmIGFyY0ludGVyc2VjdGlvbnNbMV0gPj0gYm90dG9tUmlnaHRDZW50ZXJZKSB7XG4gICAgICByZXR1cm4gW2FyY0ludGVyc2VjdGlvbnNbMF0sIGFyY0ludGVyc2VjdGlvbnNbMV1dO1xuICAgIH1cbiAgfSAvLyBCb3R0b20gTGVmdFxuXG4gIHtcbiAgICB2YXIgYm90dG9tTGVmdENlbnRlclggPSBub2RlWCAtIGhhbGZXaWR0aCArIGNvcm5lclJhZGl1cztcbiAgICB2YXIgYm90dG9tTGVmdENlbnRlclkgPSBub2RlWSArIGhhbGZIZWlnaHQgLSBjb3JuZXJSYWRpdXM7XG4gICAgYXJjSW50ZXJzZWN0aW9ucyA9IGludGVyc2VjdExpbmVDaXJjbGUoeCwgeSwgbm9kZVgsIG5vZGVZLCBib3R0b21MZWZ0Q2VudGVyWCwgYm90dG9tTGVmdENlbnRlclksIGNvcm5lclJhZGl1cyArIHBhZGRpbmcpOyAvLyBFbnN1cmUgdGhlIGludGVyc2VjdGlvbiBpcyBvbiB0aGUgZGVzaXJlZCBxdWFydGVyIG9mIHRoZSBjaXJjbGVcblxuICAgIGlmIChhcmNJbnRlcnNlY3Rpb25zLmxlbmd0aCA+IDAgJiYgYXJjSW50ZXJzZWN0aW9uc1swXSA8PSBib3R0b21MZWZ0Q2VudGVyWCAmJiBhcmNJbnRlcnNlY3Rpb25zWzFdID49IGJvdHRvbUxlZnRDZW50ZXJZKSB7XG4gICAgICByZXR1cm4gW2FyY0ludGVyc2VjdGlvbnNbMF0sIGFyY0ludGVyc2VjdGlvbnNbMV1dO1xuICAgIH1cbiAgfVxuICByZXR1cm4gW107IC8vIGlmIG5vdGhpbmdcbn07XG52YXIgaW5MaW5lVmljaW5pdHkgPSBmdW5jdGlvbiBpbkxpbmVWaWNpbml0eSh4LCB5LCBseDEsIGx5MSwgbHgyLCBseTIsIHRvbGVyYW5jZSkge1xuICB2YXIgdCA9IHRvbGVyYW5jZTtcbiAgdmFyIHgxID0gTWF0aC5taW4obHgxLCBseDIpO1xuICB2YXIgeDIgPSBNYXRoLm1heChseDEsIGx4Mik7XG4gIHZhciB5MSA9IE1hdGgubWluKGx5MSwgbHkyKTtcbiAgdmFyIHkyID0gTWF0aC5tYXgobHkxLCBseTIpO1xuICByZXR1cm4geDEgLSB0IDw9IHggJiYgeCA8PSB4MiArIHQgJiYgeTEgLSB0IDw9IHkgJiYgeSA8PSB5MiArIHQ7XG59O1xudmFyIGluQmV6aWVyVmljaW5pdHkgPSBmdW5jdGlvbiBpbkJlemllclZpY2luaXR5KHgsIHksIHgxLCB5MSwgeDIsIHkyLCB4MywgeTMsIHRvbGVyYW5jZSkge1xuICB2YXIgYmIgPSB7XG4gICAgeDE6IE1hdGgubWluKHgxLCB4MywgeDIpIC0gdG9sZXJhbmNlLFxuICAgIHgyOiBNYXRoLm1heCh4MSwgeDMsIHgyKSArIHRvbGVyYW5jZSxcbiAgICB5MTogTWF0aC5taW4oeTEsIHkzLCB5MikgLSB0b2xlcmFuY2UsXG4gICAgeTI6IE1hdGgubWF4KHkxLCB5MywgeTIpICsgdG9sZXJhbmNlXG4gIH07IC8vIGlmIG91dHNpZGUgdGhlIHJvdWdoIGJvdW5kaW5nIGJveCBmb3IgdGhlIGJlemllciwgdGhlbiBpdCBjYW4ndCBiZSBhIGhpdFxuXG4gIGlmICh4IDwgYmIueDEgfHwgeCA+IGJiLngyIHx8IHkgPCBiYi55MSB8fCB5ID4gYmIueTIpIHtcbiAgICAvLyBjb25zb2xlLmxvZygnYmV6aWVyIG91dCBvZiByb3VnaCBiYicpXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IGVsc2Uge1xuICAgIC8vIGNvbnNvbGUubG9nKCdkbyBtb3JlIGV4cGVuc2l2ZSBjaGVjaycpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59O1xudmFyIHNvbHZlUXVhZHJhdGljID0gZnVuY3Rpb24gc29sdmVRdWFkcmF0aWMoYSwgYiwgYywgdmFsKSB7XG4gIGMgLT0gdmFsO1xuICB2YXIgciA9IGIgKiBiIC0gNCAqIGEgKiBjO1xuXG4gIGlmIChyIDwgMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHZhciBzcXJ0UiA9IE1hdGguc3FydChyKTtcbiAgdmFyIGRlbm9tID0gMiAqIGE7XG4gIHZhciByb290MSA9ICgtYiArIHNxcnRSKSAvIGRlbm9tO1xuICB2YXIgcm9vdDIgPSAoLWIgLSBzcXJ0UikgLyBkZW5vbTtcbiAgcmV0dXJuIFtyb290MSwgcm9vdDJdO1xufTtcbnZhciBzb2x2ZUN1YmljID0gZnVuY3Rpb24gc29sdmVDdWJpYyhhLCBiLCBjLCBkLCByZXN1bHQpIHtcbiAgLy8gU29sdmVzIGEgY3ViaWMgZnVuY3Rpb24sIHJldHVybnMgcm9vdCBpbiBmb3JtIFtyMSwgaTEsIHIyLCBpMiwgcjMsIGkzXSwgd2hlcmVcbiAgLy8gciBpcyB0aGUgcmVhbCBjb21wb25lbnQsIGkgaXMgdGhlIGltYWdpbmFyeSBjb21wb25lbnRcbiAgLy8gQW4gaW1wbGVtZW50YXRpb24gb2YgdGhlIENhcmRhbm8gbWV0aG9kIGZyb20gdGhlIHllYXIgMTU0NVxuICAvLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0N1YmljX2Z1bmN0aW9uI1RoZV9uYXR1cmVfb2ZfdGhlX3Jvb3RzXG4gIHZhciBlcHNpbG9uID0gMC4wMDAwMTsgLy8gYXZvaWQgZGl2aXNpb24gYnkgemVybyB3aGlsZSBrZWVwaW5nIHRoZSBvdmVyYWxsIGV4cHJlc3Npb24gY2xvc2UgaW4gdmFsdWVcblxuICBpZiAoYSA9PT0gMCkge1xuICAgIGEgPSBlcHNpbG9uO1xuICB9XG5cbiAgYiAvPSBhO1xuICBjIC89IGE7XG4gIGQgLz0gYTtcbiAgdmFyIGRpc2NyaW1pbmFudCwgcSwgciwgZHVtMSwgcywgdCwgdGVybTEsIHIxMztcbiAgcSA9ICgzLjAgKiBjIC0gYiAqIGIpIC8gOS4wO1xuICByID0gLSgyNy4wICogZCkgKyBiICogKDkuMCAqIGMgLSAyLjAgKiAoYiAqIGIpKTtcbiAgciAvPSA1NC4wO1xuICBkaXNjcmltaW5hbnQgPSBxICogcSAqIHEgKyByICogcjtcbiAgcmVzdWx0WzFdID0gMDtcbiAgdGVybTEgPSBiIC8gMy4wO1xuXG4gIGlmIChkaXNjcmltaW5hbnQgPiAwKSB7XG4gICAgcyA9IHIgKyBNYXRoLnNxcnQoZGlzY3JpbWluYW50KTtcbiAgICBzID0gcyA8IDAgPyAtTWF0aC5wb3coLXMsIDEuMCAvIDMuMCkgOiBNYXRoLnBvdyhzLCAxLjAgLyAzLjApO1xuICAgIHQgPSByIC0gTWF0aC5zcXJ0KGRpc2NyaW1pbmFudCk7XG4gICAgdCA9IHQgPCAwID8gLU1hdGgucG93KC10LCAxLjAgLyAzLjApIDogTWF0aC5wb3codCwgMS4wIC8gMy4wKTtcbiAgICByZXN1bHRbMF0gPSAtdGVybTEgKyBzICsgdDtcbiAgICB0ZXJtMSArPSAocyArIHQpIC8gMi4wO1xuICAgIHJlc3VsdFs0XSA9IHJlc3VsdFsyXSA9IC10ZXJtMTtcbiAgICB0ZXJtMSA9IE1hdGguc3FydCgzLjApICogKC10ICsgcykgLyAyO1xuICAgIHJlc3VsdFszXSA9IHRlcm0xO1xuICAgIHJlc3VsdFs1XSA9IC10ZXJtMTtcbiAgICByZXR1cm47XG4gIH1cblxuICByZXN1bHRbNV0gPSByZXN1bHRbM10gPSAwO1xuXG4gIGlmIChkaXNjcmltaW5hbnQgPT09IDApIHtcbiAgICByMTMgPSByIDwgMCA/IC1NYXRoLnBvdygtciwgMS4wIC8gMy4wKSA6IE1hdGgucG93KHIsIDEuMCAvIDMuMCk7XG4gICAgcmVzdWx0WzBdID0gLXRlcm0xICsgMi4wICogcjEzO1xuICAgIHJlc3VsdFs0XSA9IHJlc3VsdFsyXSA9IC0ocjEzICsgdGVybTEpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHEgPSAtcTtcbiAgZHVtMSA9IHEgKiBxICogcTtcbiAgZHVtMSA9IE1hdGguYWNvcyhyIC8gTWF0aC5zcXJ0KGR1bTEpKTtcbiAgcjEzID0gMi4wICogTWF0aC5zcXJ0KHEpO1xuICByZXN1bHRbMF0gPSAtdGVybTEgKyByMTMgKiBNYXRoLmNvcyhkdW0xIC8gMy4wKTtcbiAgcmVzdWx0WzJdID0gLXRlcm0xICsgcjEzICogTWF0aC5jb3MoKGR1bTEgKyAyLjAgKiBNYXRoLlBJKSAvIDMuMCk7XG4gIHJlc3VsdFs0XSA9IC10ZXJtMSArIHIxMyAqIE1hdGguY29zKChkdW0xICsgNC4wICogTWF0aC5QSSkgLyAzLjApO1xuICByZXR1cm47XG59O1xudmFyIHNxZGlzdFRvUXVhZHJhdGljQmV6aWVyID0gZnVuY3Rpb24gc3FkaXN0VG9RdWFkcmF0aWNCZXppZXIoeCwgeSwgeDEsIHkxLCB4MiwgeTIsIHgzLCB5Mykge1xuICAvLyBGaW5kIG1pbmltdW0gZGlzdGFuY2UgYnkgdXNpbmcgdGhlIG1pbmltdW0gb2YgdGhlIGRpc3RhbmNlXG4gIC8vIGZ1bmN0aW9uIGJldHdlZW4gdGhlIGdpdmVuIHBvaW50IGFuZCB0aGUgY3VydmVcbiAgLy8gVGhpcyBnaXZlcyB0aGUgY29lZmZpY2llbnRzIG9mIHRoZSByZXN1bHRpbmcgY3ViaWMgZXF1YXRpb25cbiAgLy8gd2hvc2Ugcm9vdHMgdGVsbCB1cyB3aGVyZSBhIHBvc3NpYmxlIG1pbmltdW0gaXNcbiAgLy8gKENvZWZmaWNpZW50cyBhcmUgZGl2aWRlZCBieSA0KVxuICB2YXIgYSA9IDEuMCAqIHgxICogeDEgLSA0ICogeDEgKiB4MiArIDIgKiB4MSAqIHgzICsgNCAqIHgyICogeDIgLSA0ICogeDIgKiB4MyArIHgzICogeDMgKyB5MSAqIHkxIC0gNCAqIHkxICogeTIgKyAyICogeTEgKiB5MyArIDQgKiB5MiAqIHkyIC0gNCAqIHkyICogeTMgKyB5MyAqIHkzO1xuICB2YXIgYiA9IDEuMCAqIDkgKiB4MSAqIHgyIC0gMyAqIHgxICogeDEgLSAzICogeDEgKiB4MyAtIDYgKiB4MiAqIHgyICsgMyAqIHgyICogeDMgKyA5ICogeTEgKiB5MiAtIDMgKiB5MSAqIHkxIC0gMyAqIHkxICogeTMgLSA2ICogeTIgKiB5MiArIDMgKiB5MiAqIHkzO1xuICB2YXIgYyA9IDEuMCAqIDMgKiB4MSAqIHgxIC0gNiAqIHgxICogeDIgKyB4MSAqIHgzIC0geDEgKiB4ICsgMiAqIHgyICogeDIgKyAyICogeDIgKiB4IC0geDMgKiB4ICsgMyAqIHkxICogeTEgLSA2ICogeTEgKiB5MiArIHkxICogeTMgLSB5MSAqIHkgKyAyICogeTIgKiB5MiArIDIgKiB5MiAqIHkgLSB5MyAqIHk7XG4gIHZhciBkID0gMS4wICogeDEgKiB4MiAtIHgxICogeDEgKyB4MSAqIHggLSB4MiAqIHggKyB5MSAqIHkyIC0geTEgKiB5MSArIHkxICogeSAtIHkyICogeTsgLy8gZGVidWcoXCJjb2VmZmljaWVudHM6IFwiICsgYSAvIGEgKyBcIiwgXCIgKyBiIC8gYSArIFwiLCBcIiArIGMgLyBhICsgXCIsIFwiICsgZCAvIGEpO1xuXG4gIHZhciByb290cyA9IFtdOyAvLyBVc2UgdGhlIGN1YmljIHNvbHZpbmcgYWxnb3JpdGhtXG5cbiAgc29sdmVDdWJpYyhhLCBiLCBjLCBkLCByb290cyk7XG4gIHZhciB6ZXJvVGhyZXNob2xkID0gMC4wMDAwMDAxO1xuICB2YXIgcGFyYW1zID0gW107XG5cbiAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IDY7IGluZGV4ICs9IDIpIHtcbiAgICBpZiAoTWF0aC5hYnMocm9vdHNbaW5kZXggKyAxXSkgPCB6ZXJvVGhyZXNob2xkICYmIHJvb3RzW2luZGV4XSA+PSAwICYmIHJvb3RzW2luZGV4XSA8PSAxLjApIHtcbiAgICAgIHBhcmFtcy5wdXNoKHJvb3RzW2luZGV4XSk7XG4gICAgfVxuICB9XG5cbiAgcGFyYW1zLnB1c2goMS4wKTtcbiAgcGFyYW1zLnB1c2goMC4wKTtcbiAgdmFyIG1pbkRpc3RhbmNlU3F1YXJlZCA9IC0xO1xuICB2YXIgY3VyWCwgY3VyWSwgZGlzdFNxdWFyZWQ7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJhbXMubGVuZ3RoOyBpKyspIHtcbiAgICBjdXJYID0gTWF0aC5wb3coMS4wIC0gcGFyYW1zW2ldLCAyLjApICogeDEgKyAyLjAgKiAoMSAtIHBhcmFtc1tpXSkgKiBwYXJhbXNbaV0gKiB4MiArIHBhcmFtc1tpXSAqIHBhcmFtc1tpXSAqIHgzO1xuICAgIGN1clkgPSBNYXRoLnBvdygxIC0gcGFyYW1zW2ldLCAyLjApICogeTEgKyAyICogKDEuMCAtIHBhcmFtc1tpXSkgKiBwYXJhbXNbaV0gKiB5MiArIHBhcmFtc1tpXSAqIHBhcmFtc1tpXSAqIHkzO1xuICAgIGRpc3RTcXVhcmVkID0gTWF0aC5wb3coY3VyWCAtIHgsIDIpICsgTWF0aC5wb3coY3VyWSAtIHksIDIpOyAvLyBkZWJ1ZygnZGlzdGFuY2UgZm9yIHBhcmFtICcgKyBwYXJhbXNbaV0gKyBcIjogXCIgKyBNYXRoLnNxcnQoZGlzdFNxdWFyZWQpKTtcblxuICAgIGlmIChtaW5EaXN0YW5jZVNxdWFyZWQgPj0gMCkge1xuICAgICAgaWYgKGRpc3RTcXVhcmVkIDwgbWluRGlzdGFuY2VTcXVhcmVkKSB7XG4gICAgICAgIG1pbkRpc3RhbmNlU3F1YXJlZCA9IGRpc3RTcXVhcmVkO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBtaW5EaXN0YW5jZVNxdWFyZWQgPSBkaXN0U3F1YXJlZDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWluRGlzdGFuY2VTcXVhcmVkO1xufTtcbnZhciBzcWRpc3RUb0Zpbml0ZUxpbmUgPSBmdW5jdGlvbiBzcWRpc3RUb0Zpbml0ZUxpbmUoeCwgeSwgeDEsIHkxLCB4MiwgeTIpIHtcbiAgdmFyIG9mZnNldCA9IFt4IC0geDEsIHkgLSB5MV07XG4gIHZhciBsaW5lID0gW3gyIC0geDEsIHkyIC0geTFdO1xuICB2YXIgbGluZVNxID0gbGluZVswXSAqIGxpbmVbMF0gKyBsaW5lWzFdICogbGluZVsxXTtcbiAgdmFyIGh5cFNxID0gb2Zmc2V0WzBdICogb2Zmc2V0WzBdICsgb2Zmc2V0WzFdICogb2Zmc2V0WzFdO1xuICB2YXIgZG90UHJvZHVjdCA9IG9mZnNldFswXSAqIGxpbmVbMF0gKyBvZmZzZXRbMV0gKiBsaW5lWzFdO1xuICB2YXIgYWRqU3EgPSBkb3RQcm9kdWN0ICogZG90UHJvZHVjdCAvIGxpbmVTcTtcblxuICBpZiAoZG90UHJvZHVjdCA8IDApIHtcbiAgICByZXR1cm4gaHlwU3E7XG4gIH1cblxuICBpZiAoYWRqU3EgPiBsaW5lU3EpIHtcbiAgICByZXR1cm4gKHggLSB4MikgKiAoeCAtIHgyKSArICh5IC0geTIpICogKHkgLSB5Mik7XG4gIH1cblxuICByZXR1cm4gaHlwU3EgLSBhZGpTcTtcbn07XG52YXIgcG9pbnRJbnNpZGVQb2x5Z29uUG9pbnRzID0gZnVuY3Rpb24gcG9pbnRJbnNpZGVQb2x5Z29uUG9pbnRzKHgsIHksIHBvaW50cykge1xuICB2YXIgeDEsIHkxLCB4MiwgeTI7XG4gIHZhciB5MzsgLy8gSW50ZXJzZWN0IHdpdGggdmVydGljYWwgbGluZSB0aHJvdWdoICh4LCB5KVxuXG4gIHZhciB1cCA9IDA7IC8vIGxldCBkb3duID0gMDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHBvaW50cy5sZW5ndGggLyAyOyBpKyspIHtcbiAgICB4MSA9IHBvaW50c1tpICogMl07XG4gICAgeTEgPSBwb2ludHNbaSAqIDIgKyAxXTtcblxuICAgIGlmIChpICsgMSA8IHBvaW50cy5sZW5ndGggLyAyKSB7XG4gICAgICB4MiA9IHBvaW50c1soaSArIDEpICogMl07XG4gICAgICB5MiA9IHBvaW50c1soaSArIDEpICogMiArIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICB4MiA9IHBvaW50c1soaSArIDEgLSBwb2ludHMubGVuZ3RoIC8gMikgKiAyXTtcbiAgICAgIHkyID0gcG9pbnRzWyhpICsgMSAtIHBvaW50cy5sZW5ndGggLyAyKSAqIDIgKyAxXTtcbiAgICB9XG5cbiAgICBpZiAoeDEgPT0geCAmJiB4MiA9PSB4KSA7IGVsc2UgaWYgKHgxID49IHggJiYgeCA+PSB4MiB8fCB4MSA8PSB4ICYmIHggPD0geDIpIHtcbiAgICAgIHkzID0gKHggLSB4MSkgLyAoeDIgLSB4MSkgKiAoeTIgLSB5MSkgKyB5MTtcblxuICAgICAgaWYgKHkzID4geSkge1xuICAgICAgICB1cCsrO1xuICAgICAgfSAvLyBpZiggeTMgPCB5ICl7XG4gICAgICAvLyBkb3duKys7XG4gICAgICAvLyB9XG5cbiAgICB9IGVsc2Uge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKHVwICUgMiA9PT0gMCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufTtcbnZhciBwb2ludEluc2lkZVBvbHlnb24gPSBmdW5jdGlvbiBwb2ludEluc2lkZVBvbHlnb24oeCwgeSwgYmFzZVBvaW50cywgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCwgZGlyZWN0aW9uLCBwYWRkaW5nKSB7XG4gIHZhciB0cmFuc2Zvcm1lZFBvaW50cyA9IG5ldyBBcnJheShiYXNlUG9pbnRzLmxlbmd0aCk7IC8vIEdpdmVzIG5lZ2F0aXZlIGFuZ2xlXG5cbiAgdmFyIGFuZ2xlO1xuXG4gIGlmIChkaXJlY3Rpb25bMF0gIT0gbnVsbCkge1xuICAgIGFuZ2xlID0gTWF0aC5hdGFuKGRpcmVjdGlvblsxXSAvIGRpcmVjdGlvblswXSk7XG5cbiAgICBpZiAoZGlyZWN0aW9uWzBdIDwgMCkge1xuICAgICAgYW5nbGUgPSBhbmdsZSArIE1hdGguUEkgLyAyO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbmdsZSA9IC1hbmdsZSAtIE1hdGguUEkgLyAyO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBhbmdsZSA9IGRpcmVjdGlvbjtcbiAgfVxuXG4gIHZhciBjb3MgPSBNYXRoLmNvcygtYW5nbGUpO1xuICB2YXIgc2luID0gTWF0aC5zaW4oLWFuZ2xlKTsgLy8gICAgY29uc29sZS5sb2coXCJiYXNlOiBcIiArIGJhc2VQb2ludHMpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHJhbnNmb3JtZWRQb2ludHMubGVuZ3RoIC8gMjsgaSsrKSB7XG4gICAgdHJhbnNmb3JtZWRQb2ludHNbaSAqIDJdID0gd2lkdGggLyAyICogKGJhc2VQb2ludHNbaSAqIDJdICogY29zIC0gYmFzZVBvaW50c1tpICogMiArIDFdICogc2luKTtcbiAgICB0cmFuc2Zvcm1lZFBvaW50c1tpICogMiArIDFdID0gaGVpZ2h0IC8gMiAqIChiYXNlUG9pbnRzW2kgKiAyICsgMV0gKiBjb3MgKyBiYXNlUG9pbnRzW2kgKiAyXSAqIHNpbik7XG4gICAgdHJhbnNmb3JtZWRQb2ludHNbaSAqIDJdICs9IGNlbnRlclg7XG4gICAgdHJhbnNmb3JtZWRQb2ludHNbaSAqIDIgKyAxXSArPSBjZW50ZXJZO1xuICB9XG5cbiAgdmFyIHBvaW50cztcblxuICBpZiAocGFkZGluZyA+IDApIHtcbiAgICB2YXIgZXhwYW5kZWRMaW5lU2V0ID0gZXhwYW5kUG9seWdvbih0cmFuc2Zvcm1lZFBvaW50cywgLXBhZGRpbmcpO1xuICAgIHBvaW50cyA9IGpvaW5MaW5lcyhleHBhbmRlZExpbmVTZXQpO1xuICB9IGVsc2Uge1xuICAgIHBvaW50cyA9IHRyYW5zZm9ybWVkUG9pbnRzO1xuICB9XG5cbiAgcmV0dXJuIHBvaW50SW5zaWRlUG9seWdvblBvaW50cyh4LCB5LCBwb2ludHMpO1xufTtcbnZhciBwb2ludEluc2lkZVJvdW5kUG9seWdvbiA9IGZ1bmN0aW9uIHBvaW50SW5zaWRlUm91bmRQb2x5Z29uKHgsIHksIGJhc2VQb2ludHMsIGNlbnRlclgsIGNlbnRlclksIHdpZHRoLCBoZWlnaHQpIHtcbiAgdmFyIGN1dFBvbHlnb25Qb2ludHMgPSBuZXcgQXJyYXkoYmFzZVBvaW50cy5sZW5ndGgpO1xuICB2YXIgaGFsZlcgPSB3aWR0aCAvIDI7XG4gIHZhciBoYWxmSCA9IGhlaWdodCAvIDI7XG4gIHZhciBjb3JuZXJSYWRpdXMgPSBnZXRSb3VuZFBvbHlnb25SYWRpdXMod2lkdGgsIGhlaWdodCk7XG4gIHZhciBzcXVhcmVkQ29ybmVyUmFkaXVzID0gY29ybmVyUmFkaXVzICogY29ybmVyUmFkaXVzO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYmFzZVBvaW50cy5sZW5ndGggLyA0OyBpKyspIHtcbiAgICB2YXIgc291cmNlVXYgPSB2b2lkIDAsXG4gICAgICAgIGRlc3RVdiA9IHZvaWQgMDtcblxuICAgIGlmIChpID09PSAwKSB7XG4gICAgICBzb3VyY2VVdiA9IGJhc2VQb2ludHMubGVuZ3RoIC0gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgc291cmNlVXYgPSBpICogNCAtIDI7XG4gICAgfVxuXG4gICAgZGVzdFV2ID0gaSAqIDQgKyAyO1xuICAgIHZhciBweCA9IGNlbnRlclggKyBoYWxmVyAqIGJhc2VQb2ludHNbaSAqIDRdO1xuICAgIHZhciBweSA9IGNlbnRlclkgKyBoYWxmSCAqIGJhc2VQb2ludHNbaSAqIDQgKyAxXTtcbiAgICB2YXIgY29zVGhldGEgPSAtYmFzZVBvaW50c1tzb3VyY2VVdl0gKiBiYXNlUG9pbnRzW2Rlc3RVdl0gLSBiYXNlUG9pbnRzW3NvdXJjZVV2ICsgMV0gKiBiYXNlUG9pbnRzW2Rlc3RVdiArIDFdO1xuICAgIHZhciBvZmZzZXQgPSBjb3JuZXJSYWRpdXMgLyBNYXRoLnRhbihNYXRoLmFjb3MoY29zVGhldGEpIC8gMik7XG4gICAgdmFyIGNwMHggPSBweCAtIG9mZnNldCAqIGJhc2VQb2ludHNbc291cmNlVXZdO1xuICAgIHZhciBjcDB5ID0gcHkgLSBvZmZzZXQgKiBiYXNlUG9pbnRzW3NvdXJjZVV2ICsgMV07XG4gICAgdmFyIGNwMXggPSBweCArIG9mZnNldCAqIGJhc2VQb2ludHNbZGVzdFV2XTtcbiAgICB2YXIgY3AxeSA9IHB5ICsgb2Zmc2V0ICogYmFzZVBvaW50c1tkZXN0VXYgKyAxXTtcbiAgICBjdXRQb2x5Z29uUG9pbnRzW2kgKiA0XSA9IGNwMHg7XG4gICAgY3V0UG9seWdvblBvaW50c1tpICogNCArIDFdID0gY3AweTtcbiAgICBjdXRQb2x5Z29uUG9pbnRzW2kgKiA0ICsgMl0gPSBjcDF4O1xuICAgIGN1dFBvbHlnb25Qb2ludHNbaSAqIDQgKyAzXSA9IGNwMXk7XG4gICAgdmFyIG9ydGh4ID0gYmFzZVBvaW50c1tzb3VyY2VVdiArIDFdO1xuICAgIHZhciBvcnRoeSA9IC1iYXNlUG9pbnRzW3NvdXJjZVV2XTtcbiAgICB2YXIgY29zQWxwaGEgPSBvcnRoeCAqIGJhc2VQb2ludHNbZGVzdFV2XSArIG9ydGh5ICogYmFzZVBvaW50c1tkZXN0VXYgKyAxXTtcblxuICAgIGlmIChjb3NBbHBoYSA8IDApIHtcbiAgICAgIG9ydGh4ICo9IC0xO1xuICAgICAgb3J0aHkgKj0gLTE7XG4gICAgfVxuXG4gICAgdmFyIGN4ID0gY3AweCArIG9ydGh4ICogY29ybmVyUmFkaXVzO1xuICAgIHZhciBjeSA9IGNwMHkgKyBvcnRoeSAqIGNvcm5lclJhZGl1cztcbiAgICB2YXIgc3F1YXJlZERpc3RhbmNlID0gTWF0aC5wb3coY3ggLSB4LCAyKSArIE1hdGgucG93KGN5IC0geSwgMik7XG5cbiAgICBpZiAoc3F1YXJlZERpc3RhbmNlIDw9IHNxdWFyZWRDb3JuZXJSYWRpdXMpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwb2ludEluc2lkZVBvbHlnb25Qb2ludHMoeCwgeSwgY3V0UG9seWdvblBvaW50cyk7XG59O1xudmFyIGpvaW5MaW5lcyA9IGZ1bmN0aW9uIGpvaW5MaW5lcyhsaW5lU2V0KSB7XG4gIHZhciB2ZXJ0aWNlcyA9IG5ldyBBcnJheShsaW5lU2V0Lmxlbmd0aCAvIDIpO1xuICB2YXIgY3VycmVudExpbmVTdGFydFgsIGN1cnJlbnRMaW5lU3RhcnRZLCBjdXJyZW50TGluZUVuZFgsIGN1cnJlbnRMaW5lRW5kWTtcbiAgdmFyIG5leHRMaW5lU3RhcnRYLCBuZXh0TGluZVN0YXJ0WSwgbmV4dExpbmVFbmRYLCBuZXh0TGluZUVuZFk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lU2V0Lmxlbmd0aCAvIDQ7IGkrKykge1xuICAgIGN1cnJlbnRMaW5lU3RhcnRYID0gbGluZVNldFtpICogNF07XG4gICAgY3VycmVudExpbmVTdGFydFkgPSBsaW5lU2V0W2kgKiA0ICsgMV07XG4gICAgY3VycmVudExpbmVFbmRYID0gbGluZVNldFtpICogNCArIDJdO1xuICAgIGN1cnJlbnRMaW5lRW5kWSA9IGxpbmVTZXRbaSAqIDQgKyAzXTtcblxuICAgIGlmIChpIDwgbGluZVNldC5sZW5ndGggLyA0IC0gMSkge1xuICAgICAgbmV4dExpbmVTdGFydFggPSBsaW5lU2V0WyhpICsgMSkgKiA0XTtcbiAgICAgIG5leHRMaW5lU3RhcnRZID0gbGluZVNldFsoaSArIDEpICogNCArIDFdO1xuICAgICAgbmV4dExpbmVFbmRYID0gbGluZVNldFsoaSArIDEpICogNCArIDJdO1xuICAgICAgbmV4dExpbmVFbmRZID0gbGluZVNldFsoaSArIDEpICogNCArIDNdO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXh0TGluZVN0YXJ0WCA9IGxpbmVTZXRbMF07XG4gICAgICBuZXh0TGluZVN0YXJ0WSA9IGxpbmVTZXRbMV07XG4gICAgICBuZXh0TGluZUVuZFggPSBsaW5lU2V0WzJdO1xuICAgICAgbmV4dExpbmVFbmRZID0gbGluZVNldFszXTtcbiAgICB9XG5cbiAgICB2YXIgaW50ZXJzZWN0aW9uID0gZmluaXRlTGluZXNJbnRlcnNlY3QoY3VycmVudExpbmVTdGFydFgsIGN1cnJlbnRMaW5lU3RhcnRZLCBjdXJyZW50TGluZUVuZFgsIGN1cnJlbnRMaW5lRW5kWSwgbmV4dExpbmVTdGFydFgsIG5leHRMaW5lU3RhcnRZLCBuZXh0TGluZUVuZFgsIG5leHRMaW5lRW5kWSwgdHJ1ZSk7XG4gICAgdmVydGljZXNbaSAqIDJdID0gaW50ZXJzZWN0aW9uWzBdO1xuICAgIHZlcnRpY2VzW2kgKiAyICsgMV0gPSBpbnRlcnNlY3Rpb25bMV07XG4gIH1cblxuICByZXR1cm4gdmVydGljZXM7XG59O1xudmFyIGV4cGFuZFBvbHlnb24gPSBmdW5jdGlvbiBleHBhbmRQb2x5Z29uKHBvaW50cywgcGFkKSB7XG4gIHZhciBleHBhbmRlZExpbmVTZXQgPSBuZXcgQXJyYXkocG9pbnRzLmxlbmd0aCAqIDIpO1xuICB2YXIgY3VycmVudFBvaW50WCwgY3VycmVudFBvaW50WSwgbmV4dFBvaW50WCwgbmV4dFBvaW50WTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHBvaW50cy5sZW5ndGggLyAyOyBpKyspIHtcbiAgICBjdXJyZW50UG9pbnRYID0gcG9pbnRzW2kgKiAyXTtcbiAgICBjdXJyZW50UG9pbnRZID0gcG9pbnRzW2kgKiAyICsgMV07XG5cbiAgICBpZiAoaSA8IHBvaW50cy5sZW5ndGggLyAyIC0gMSkge1xuICAgICAgbmV4dFBvaW50WCA9IHBvaW50c1soaSArIDEpICogMl07XG4gICAgICBuZXh0UG9pbnRZID0gcG9pbnRzWyhpICsgMSkgKiAyICsgMV07XG4gICAgfSBlbHNlIHtcbiAgICAgIG5leHRQb2ludFggPSBwb2ludHNbMF07XG4gICAgICBuZXh0UG9pbnRZID0gcG9pbnRzWzFdO1xuICAgIH0gLy8gQ3VycmVudCBsaW5lOiBbY3VycmVudFBvaW50WCwgY3VycmVudFBvaW50WV0gdG8gW25leHRQb2ludFgsIG5leHRQb2ludFldXG4gICAgLy8gQXNzdW1lIENDVyBwb2x5Z29uIHdpbmRpbmdcblxuXG4gICAgdmFyIG9mZnNldFggPSBuZXh0UG9pbnRZIC0gY3VycmVudFBvaW50WTtcbiAgICB2YXIgb2Zmc2V0WSA9IC0obmV4dFBvaW50WCAtIGN1cnJlbnRQb2ludFgpOyAvLyBOb3JtYWxpemVcblxuICAgIHZhciBvZmZzZXRMZW5ndGggPSBNYXRoLnNxcnQob2Zmc2V0WCAqIG9mZnNldFggKyBvZmZzZXRZICogb2Zmc2V0WSk7XG4gICAgdmFyIG5vcm1hbGl6ZWRPZmZzZXRYID0gb2Zmc2V0WCAvIG9mZnNldExlbmd0aDtcbiAgICB2YXIgbm9ybWFsaXplZE9mZnNldFkgPSBvZmZzZXRZIC8gb2Zmc2V0TGVuZ3RoO1xuICAgIGV4cGFuZGVkTGluZVNldFtpICogNF0gPSBjdXJyZW50UG9pbnRYICsgbm9ybWFsaXplZE9mZnNldFggKiBwYWQ7XG4gICAgZXhwYW5kZWRMaW5lU2V0W2kgKiA0ICsgMV0gPSBjdXJyZW50UG9pbnRZICsgbm9ybWFsaXplZE9mZnNldFkgKiBwYWQ7XG4gICAgZXhwYW5kZWRMaW5lU2V0W2kgKiA0ICsgMl0gPSBuZXh0UG9pbnRYICsgbm9ybWFsaXplZE9mZnNldFggKiBwYWQ7XG4gICAgZXhwYW5kZWRMaW5lU2V0W2kgKiA0ICsgM10gPSBuZXh0UG9pbnRZICsgbm9ybWFsaXplZE9mZnNldFkgKiBwYWQ7XG4gIH1cblxuICByZXR1cm4gZXhwYW5kZWRMaW5lU2V0O1xufTtcbnZhciBpbnRlcnNlY3RMaW5lRWxsaXBzZSA9IGZ1bmN0aW9uIGludGVyc2VjdExpbmVFbGxpcHNlKHgsIHksIGNlbnRlclgsIGNlbnRlclksIGVsbGlwc2VXcmFkaXVzLCBlbGxpcHNlSHJhZGl1cykge1xuICB2YXIgZGlzcFggPSBjZW50ZXJYIC0geDtcbiAgdmFyIGRpc3BZID0gY2VudGVyWSAtIHk7XG4gIGRpc3BYIC89IGVsbGlwc2VXcmFkaXVzO1xuICBkaXNwWSAvPSBlbGxpcHNlSHJhZGl1cztcbiAgdmFyIGxlbiA9IE1hdGguc3FydChkaXNwWCAqIGRpc3BYICsgZGlzcFkgKiBkaXNwWSk7XG4gIHZhciBuZXdMZW5ndGggPSBsZW4gLSAxO1xuXG4gIGlmIChuZXdMZW5ndGggPCAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgdmFyIGxlblByb3BvcnRpb24gPSBuZXdMZW5ndGggLyBsZW47XG4gIHJldHVybiBbKGNlbnRlclggLSB4KSAqIGxlblByb3BvcnRpb24gKyB4LCAoY2VudGVyWSAtIHkpICogbGVuUHJvcG9ydGlvbiArIHldO1xufTtcbnZhciBjaGVja0luRWxsaXBzZSA9IGZ1bmN0aW9uIGNoZWNrSW5FbGxpcHNlKHgsIHksIHdpZHRoLCBoZWlnaHQsIGNlbnRlclgsIGNlbnRlclksIHBhZGRpbmcpIHtcbiAgeCAtPSBjZW50ZXJYO1xuICB5IC09IGNlbnRlclk7XG4gIHggLz0gd2lkdGggLyAyICsgcGFkZGluZztcbiAgeSAvPSBoZWlnaHQgLyAyICsgcGFkZGluZztcbiAgcmV0dXJuIHggKiB4ICsgeSAqIHkgPD0gMTtcbn07IC8vIFJldHVybnMgaW50ZXJzZWN0aW9ucyBvZiBpbmNyZWFzaW5nIGRpc3RhbmNlIGZyb20gbGluZSdzIHN0YXJ0IHBvaW50XG5cbnZhciBpbnRlcnNlY3RMaW5lQ2lyY2xlID0gZnVuY3Rpb24gaW50ZXJzZWN0TGluZUNpcmNsZSh4MSwgeTEsIHgyLCB5MiwgY2VudGVyWCwgY2VudGVyWSwgcmFkaXVzKSB7XG4gIC8vIENhbGN1bGF0ZSBkLCBkaXJlY3Rpb24gdmVjdG9yIG9mIGxpbmVcbiAgdmFyIGQgPSBbeDIgLSB4MSwgeTIgLSB5MV07IC8vIERpcmVjdGlvbiB2ZWN0b3Igb2YgbGluZVxuXG4gIHZhciBmID0gW3gxIC0gY2VudGVyWCwgeTEgLSBjZW50ZXJZXTtcbiAgdmFyIGEgPSBkWzBdICogZFswXSArIGRbMV0gKiBkWzFdO1xuICB2YXIgYiA9IDIgKiAoZlswXSAqIGRbMF0gKyBmWzFdICogZFsxXSk7XG4gIHZhciBjID0gZlswXSAqIGZbMF0gKyBmWzFdICogZlsxXSAtIHJhZGl1cyAqIHJhZGl1cztcbiAgdmFyIGRpc2NyaW1pbmFudCA9IGIgKiBiIC0gNCAqIGEgKiBjO1xuXG4gIGlmIChkaXNjcmltaW5hbnQgPCAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgdmFyIHQxID0gKC1iICsgTWF0aC5zcXJ0KGRpc2NyaW1pbmFudCkpIC8gKDIgKiBhKTtcbiAgdmFyIHQyID0gKC1iIC0gTWF0aC5zcXJ0KGRpc2NyaW1pbmFudCkpIC8gKDIgKiBhKTtcbiAgdmFyIHRNaW4gPSBNYXRoLm1pbih0MSwgdDIpO1xuICB2YXIgdE1heCA9IE1hdGgubWF4KHQxLCB0Mik7XG4gIHZhciBpblJhbmdlUGFyYW1zID0gW107XG5cbiAgaWYgKHRNaW4gPj0gMCAmJiB0TWluIDw9IDEpIHtcbiAgICBpblJhbmdlUGFyYW1zLnB1c2godE1pbik7XG4gIH1cblxuICBpZiAodE1heCA+PSAwICYmIHRNYXggPD0gMSkge1xuICAgIGluUmFuZ2VQYXJhbXMucHVzaCh0TWF4KTtcbiAgfVxuXG4gIGlmIChpblJhbmdlUGFyYW1zLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHZhciBuZWFySW50ZXJzZWN0aW9uWCA9IGluUmFuZ2VQYXJhbXNbMF0gKiBkWzBdICsgeDE7XG4gIHZhciBuZWFySW50ZXJzZWN0aW9uWSA9IGluUmFuZ2VQYXJhbXNbMF0gKiBkWzFdICsgeTE7XG5cbiAgaWYgKGluUmFuZ2VQYXJhbXMubGVuZ3RoID4gMSkge1xuICAgIGlmIChpblJhbmdlUGFyYW1zWzBdID09IGluUmFuZ2VQYXJhbXNbMV0pIHtcbiAgICAgIHJldHVybiBbbmVhckludGVyc2VjdGlvblgsIG5lYXJJbnRlcnNlY3Rpb25ZXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGZhckludGVyc2VjdGlvblggPSBpblJhbmdlUGFyYW1zWzFdICogZFswXSArIHgxO1xuICAgICAgdmFyIGZhckludGVyc2VjdGlvblkgPSBpblJhbmdlUGFyYW1zWzFdICogZFsxXSArIHkxO1xuICAgICAgcmV0dXJuIFtuZWFySW50ZXJzZWN0aW9uWCwgbmVhckludGVyc2VjdGlvblksIGZhckludGVyc2VjdGlvblgsIGZhckludGVyc2VjdGlvblldO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gW25lYXJJbnRlcnNlY3Rpb25YLCBuZWFySW50ZXJzZWN0aW9uWV07XG4gIH1cbn07XG52YXIgbWlkT2ZUaHJlZSA9IGZ1bmN0aW9uIG1pZE9mVGhyZWUoYSwgYiwgYykge1xuICBpZiAoYiA8PSBhICYmIGEgPD0gYyB8fCBjIDw9IGEgJiYgYSA8PSBiKSB7XG4gICAgcmV0dXJuIGE7XG4gIH0gZWxzZSBpZiAoYSA8PSBiICYmIGIgPD0gYyB8fCBjIDw9IGIgJiYgYiA8PSBhKSB7XG4gICAgcmV0dXJuIGI7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGM7XG4gIH1cbn07IC8vICh4MSx5MSk9Pih4Mix5MikgaW50ZXJzZWN0IHdpdGggKHgzLHkzKT0+KHg0LHk0KVxuXG52YXIgZmluaXRlTGluZXNJbnRlcnNlY3QgPSBmdW5jdGlvbiBmaW5pdGVMaW5lc0ludGVyc2VjdCh4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQsIGluZmluaXRlTGluZXMpIHtcbiAgdmFyIGR4MTMgPSB4MSAtIHgzO1xuICB2YXIgZHgyMSA9IHgyIC0geDE7XG4gIHZhciBkeDQzID0geDQgLSB4MztcbiAgdmFyIGR5MTMgPSB5MSAtIHkzO1xuICB2YXIgZHkyMSA9IHkyIC0geTE7XG4gIHZhciBkeTQzID0geTQgLSB5MztcbiAgdmFyIHVhX3QgPSBkeDQzICogZHkxMyAtIGR5NDMgKiBkeDEzO1xuICB2YXIgdWJfdCA9IGR4MjEgKiBkeTEzIC0gZHkyMSAqIGR4MTM7XG4gIHZhciB1X2IgPSBkeTQzICogZHgyMSAtIGR4NDMgKiBkeTIxO1xuXG4gIGlmICh1X2IgIT09IDApIHtcbiAgICB2YXIgdWEgPSB1YV90IC8gdV9iO1xuICAgIHZhciB1YiA9IHViX3QgLyB1X2I7XG4gICAgdmFyIGZscHRUaHJlc2hvbGQgPSAwLjAwMTtcblxuICAgIHZhciBfbWluID0gMCAtIGZscHRUaHJlc2hvbGQ7XG5cbiAgICB2YXIgX21heCA9IDEgKyBmbHB0VGhyZXNob2xkO1xuXG4gICAgaWYgKF9taW4gPD0gdWEgJiYgdWEgPD0gX21heCAmJiBfbWluIDw9IHViICYmIHViIDw9IF9tYXgpIHtcbiAgICAgIHJldHVybiBbeDEgKyB1YSAqIGR4MjEsIHkxICsgdWEgKiBkeTIxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFpbmZpbml0ZUxpbmVzKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbeDEgKyB1YSAqIGR4MjEsIHkxICsgdWEgKiBkeTIxXTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKHVhX3QgPT09IDAgfHwgdWJfdCA9PT0gMCkge1xuICAgICAgLy8gUGFyYWxsZWwsIGNvaW5jaWRlbnQgbGluZXMuIENoZWNrIGlmIG92ZXJsYXBcbiAgICAgIC8vIENoZWNrIGVuZHBvaW50IG9mIHNlY29uZCBsaW5lXG4gICAgICBpZiAobWlkT2ZUaHJlZSh4MSwgeDIsIHg0KSA9PT0geDQpIHtcbiAgICAgICAgcmV0dXJuIFt4NCwgeTRdO1xuICAgICAgfSAvLyBDaGVjayBzdGFydCBwb2ludCBvZiBzZWNvbmQgbGluZVxuXG5cbiAgICAgIGlmIChtaWRPZlRocmVlKHgxLCB4MiwgeDMpID09PSB4Mykge1xuICAgICAgICByZXR1cm4gW3gzLCB5M107XG4gICAgICB9IC8vIEVuZHBvaW50IG9mIGZpcnN0IGxpbmVcblxuXG4gICAgICBpZiAobWlkT2ZUaHJlZSh4MywgeDQsIHgyKSA9PT0geDIpIHtcbiAgICAgICAgcmV0dXJuIFt4MiwgeTJdO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gW107XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFBhcmFsbGVsLCBub24tY29pbmNpZGVudFxuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxufTsgLy8gbWF0aC5wb2x5Z29uSW50ZXJzZWN0TGluZSggeCwgeSwgYmFzZVBvaW50cywgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCwgcGFkZGluZyApXG4vLyBpbnRlcnNlY3QgYSBub2RlIHBvbHlnb24gKHB0cyB0cmFuc2Zvcm1lZClcbi8vXG4vLyBtYXRoLnBvbHlnb25JbnRlcnNlY3RMaW5lKCB4LCB5LCBiYXNlUG9pbnRzLCBjZW50ZXJYLCBjZW50ZXJZIClcbi8vIGludGVyc2VjdCB0aGUgcG9pbnRzIChubyB0cmFuc2Zvcm0pXG5cbnZhciBwb2x5Z29uSW50ZXJzZWN0TGluZSA9IGZ1bmN0aW9uIHBvbHlnb25JbnRlcnNlY3RMaW5lKHgsIHksIGJhc2VQb2ludHMsIGNlbnRlclgsIGNlbnRlclksIHdpZHRoLCBoZWlnaHQsIHBhZGRpbmcpIHtcbiAgdmFyIGludGVyc2VjdGlvbnMgPSBbXTtcbiAgdmFyIGludGVyc2VjdGlvbjtcbiAgdmFyIHRyYW5zZm9ybWVkUG9pbnRzID0gbmV3IEFycmF5KGJhc2VQb2ludHMubGVuZ3RoKTtcbiAgdmFyIGRvVHJhbnNmb3JtID0gdHJ1ZTtcblxuICBpZiAod2lkdGggPT0gbnVsbCkge1xuICAgIGRvVHJhbnNmb3JtID0gZmFsc2U7XG4gIH1cblxuICB2YXIgcG9pbnRzO1xuXG4gIGlmIChkb1RyYW5zZm9ybSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJhbnNmb3JtZWRQb2ludHMubGVuZ3RoIC8gMjsgaSsrKSB7XG4gICAgICB0cmFuc2Zvcm1lZFBvaW50c1tpICogMl0gPSBiYXNlUG9pbnRzW2kgKiAyXSAqIHdpZHRoICsgY2VudGVyWDtcbiAgICAgIHRyYW5zZm9ybWVkUG9pbnRzW2kgKiAyICsgMV0gPSBiYXNlUG9pbnRzW2kgKiAyICsgMV0gKiBoZWlnaHQgKyBjZW50ZXJZO1xuICAgIH1cblxuICAgIGlmIChwYWRkaW5nID4gMCkge1xuICAgICAgdmFyIGV4cGFuZGVkTGluZVNldCA9IGV4cGFuZFBvbHlnb24odHJhbnNmb3JtZWRQb2ludHMsIC1wYWRkaW5nKTtcbiAgICAgIHBvaW50cyA9IGpvaW5MaW5lcyhleHBhbmRlZExpbmVTZXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBwb2ludHMgPSB0cmFuc2Zvcm1lZFBvaW50cztcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcG9pbnRzID0gYmFzZVBvaW50cztcbiAgfVxuXG4gIHZhciBjdXJyZW50WCwgY3VycmVudFksIG5leHRYLCBuZXh0WTtcblxuICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBwb2ludHMubGVuZ3RoIC8gMjsgX2kyKyspIHtcbiAgICBjdXJyZW50WCA9IHBvaW50c1tfaTIgKiAyXTtcbiAgICBjdXJyZW50WSA9IHBvaW50c1tfaTIgKiAyICsgMV07XG5cbiAgICBpZiAoX2kyIDwgcG9pbnRzLmxlbmd0aCAvIDIgLSAxKSB7XG4gICAgICBuZXh0WCA9IHBvaW50c1soX2kyICsgMSkgKiAyXTtcbiAgICAgIG5leHRZID0gcG9pbnRzWyhfaTIgKyAxKSAqIDIgKyAxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV4dFggPSBwb2ludHNbMF07XG4gICAgICBuZXh0WSA9IHBvaW50c1sxXTtcbiAgICB9XG5cbiAgICBpbnRlcnNlY3Rpb24gPSBmaW5pdGVMaW5lc0ludGVyc2VjdCh4LCB5LCBjZW50ZXJYLCBjZW50ZXJZLCBjdXJyZW50WCwgY3VycmVudFksIG5leHRYLCBuZXh0WSk7XG5cbiAgICBpZiAoaW50ZXJzZWN0aW9uLmxlbmd0aCAhPT0gMCkge1xuICAgICAgaW50ZXJzZWN0aW9ucy5wdXNoKGludGVyc2VjdGlvblswXSwgaW50ZXJzZWN0aW9uWzFdKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gaW50ZXJzZWN0aW9ucztcbn07XG52YXIgcm91bmRQb2x5Z29uSW50ZXJzZWN0TGluZSA9IGZ1bmN0aW9uIHJvdW5kUG9seWdvbkludGVyc2VjdExpbmUoeCwgeSwgYmFzZVBvaW50cywgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCwgcGFkZGluZykge1xuICB2YXIgaW50ZXJzZWN0aW9ucyA9IFtdO1xuICB2YXIgaW50ZXJzZWN0aW9uO1xuICB2YXIgbGluZXMgPSBuZXcgQXJyYXkoYmFzZVBvaW50cy5sZW5ndGgpO1xuICB2YXIgaGFsZlcgPSB3aWR0aCAvIDI7XG4gIHZhciBoYWxmSCA9IGhlaWdodCAvIDI7XG4gIHZhciBjb3JuZXJSYWRpdXMgPSBnZXRSb3VuZFBvbHlnb25SYWRpdXMod2lkdGgsIGhlaWdodCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBiYXNlUG9pbnRzLmxlbmd0aCAvIDQ7IGkrKykge1xuICAgIHZhciBzb3VyY2VVdiA9IHZvaWQgMCxcbiAgICAgICAgZGVzdFV2ID0gdm9pZCAwO1xuXG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHNvdXJjZVV2ID0gYmFzZVBvaW50cy5sZW5ndGggLSAyO1xuICAgIH0gZWxzZSB7XG4gICAgICBzb3VyY2VVdiA9IGkgKiA0IC0gMjtcbiAgICB9XG5cbiAgICBkZXN0VXYgPSBpICogNCArIDI7XG4gICAgdmFyIHB4ID0gY2VudGVyWCArIGhhbGZXICogYmFzZVBvaW50c1tpICogNF07XG4gICAgdmFyIHB5ID0gY2VudGVyWSArIGhhbGZIICogYmFzZVBvaW50c1tpICogNCArIDFdO1xuICAgIHZhciBjb3NUaGV0YSA9IC1iYXNlUG9pbnRzW3NvdXJjZVV2XSAqIGJhc2VQb2ludHNbZGVzdFV2XSAtIGJhc2VQb2ludHNbc291cmNlVXYgKyAxXSAqIGJhc2VQb2ludHNbZGVzdFV2ICsgMV07XG4gICAgdmFyIG9mZnNldCA9IGNvcm5lclJhZGl1cyAvIE1hdGgudGFuKE1hdGguYWNvcyhjb3NUaGV0YSkgLyAyKTtcbiAgICB2YXIgY3AweCA9IHB4IC0gb2Zmc2V0ICogYmFzZVBvaW50c1tzb3VyY2VVdl07XG4gICAgdmFyIGNwMHkgPSBweSAtIG9mZnNldCAqIGJhc2VQb2ludHNbc291cmNlVXYgKyAxXTtcbiAgICB2YXIgY3AxeCA9IHB4ICsgb2Zmc2V0ICogYmFzZVBvaW50c1tkZXN0VXZdO1xuICAgIHZhciBjcDF5ID0gcHkgKyBvZmZzZXQgKiBiYXNlUG9pbnRzW2Rlc3RVdiArIDFdO1xuXG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIGxpbmVzW2Jhc2VQb2ludHMubGVuZ3RoIC0gMl0gPSBjcDB4O1xuICAgICAgbGluZXNbYmFzZVBvaW50cy5sZW5ndGggLSAxXSA9IGNwMHk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpbmVzW2kgKiA0IC0gMl0gPSBjcDB4O1xuICAgICAgbGluZXNbaSAqIDQgLSAxXSA9IGNwMHk7XG4gICAgfVxuXG4gICAgbGluZXNbaSAqIDRdID0gY3AxeDtcbiAgICBsaW5lc1tpICogNCArIDFdID0gY3AxeTtcbiAgICB2YXIgb3J0aHggPSBiYXNlUG9pbnRzW3NvdXJjZVV2ICsgMV07XG4gICAgdmFyIG9ydGh5ID0gLWJhc2VQb2ludHNbc291cmNlVXZdO1xuICAgIHZhciBjb3NBbHBoYSA9IG9ydGh4ICogYmFzZVBvaW50c1tkZXN0VXZdICsgb3J0aHkgKiBiYXNlUG9pbnRzW2Rlc3RVdiArIDFdO1xuXG4gICAgaWYgKGNvc0FscGhhIDwgMCkge1xuICAgICAgb3J0aHggKj0gLTE7XG4gICAgICBvcnRoeSAqPSAtMTtcbiAgICB9XG5cbiAgICB2YXIgY3ggPSBjcDB4ICsgb3J0aHggKiBjb3JuZXJSYWRpdXM7XG4gICAgdmFyIGN5ID0gY3AweSArIG9ydGh5ICogY29ybmVyUmFkaXVzO1xuICAgIGludGVyc2VjdGlvbiA9IGludGVyc2VjdExpbmVDaXJjbGUoeCwgeSwgY2VudGVyWCwgY2VudGVyWSwgY3gsIGN5LCBjb3JuZXJSYWRpdXMpO1xuXG4gICAgaWYgKGludGVyc2VjdGlvbi5sZW5ndGggIT09IDApIHtcbiAgICAgIGludGVyc2VjdGlvbnMucHVzaChpbnRlcnNlY3Rpb25bMF0sIGludGVyc2VjdGlvblsxXSk7XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgbGluZXMubGVuZ3RoIC8gNDsgX2kzKyspIHtcbiAgICBpbnRlcnNlY3Rpb24gPSBmaW5pdGVMaW5lc0ludGVyc2VjdCh4LCB5LCBjZW50ZXJYLCBjZW50ZXJZLCBsaW5lc1tfaTMgKiA0XSwgbGluZXNbX2kzICogNCArIDFdLCBsaW5lc1tfaTMgKiA0ICsgMl0sIGxpbmVzW19pMyAqIDQgKyAzXSwgZmFsc2UpO1xuXG4gICAgaWYgKGludGVyc2VjdGlvbi5sZW5ndGggIT09IDApIHtcbiAgICAgIGludGVyc2VjdGlvbnMucHVzaChpbnRlcnNlY3Rpb25bMF0sIGludGVyc2VjdGlvblsxXSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGludGVyc2VjdGlvbnMubGVuZ3RoID4gMikge1xuICAgIHZhciBsb3dlc3RJbnRlcnNlY3Rpb24gPSBbaW50ZXJzZWN0aW9uc1swXSwgaW50ZXJzZWN0aW9uc1sxXV07XG4gICAgdmFyIGxvd2VzdFNxdWFyZWREaXN0YW5jZSA9IE1hdGgucG93KGxvd2VzdEludGVyc2VjdGlvblswXSAtIHgsIDIpICsgTWF0aC5wb3cobG93ZXN0SW50ZXJzZWN0aW9uWzFdIC0geSwgMik7XG5cbiAgICBmb3IgKHZhciBfaTQgPSAxOyBfaTQgPCBpbnRlcnNlY3Rpb25zLmxlbmd0aCAvIDI7IF9pNCsrKSB7XG4gICAgICB2YXIgc3F1YXJlZERpc3RhbmNlID0gTWF0aC5wb3coaW50ZXJzZWN0aW9uc1tfaTQgKiAyXSAtIHgsIDIpICsgTWF0aC5wb3coaW50ZXJzZWN0aW9uc1tfaTQgKiAyICsgMV0gLSB5LCAyKTtcblxuICAgICAgaWYgKHNxdWFyZWREaXN0YW5jZSA8PSBsb3dlc3RTcXVhcmVkRGlzdGFuY2UpIHtcbiAgICAgICAgbG93ZXN0SW50ZXJzZWN0aW9uWzBdID0gaW50ZXJzZWN0aW9uc1tfaTQgKiAyXTtcbiAgICAgICAgbG93ZXN0SW50ZXJzZWN0aW9uWzFdID0gaW50ZXJzZWN0aW9uc1tfaTQgKiAyICsgMV07XG4gICAgICAgIGxvd2VzdFNxdWFyZWREaXN0YW5jZSA9IHNxdWFyZWREaXN0YW5jZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbG93ZXN0SW50ZXJzZWN0aW9uO1xuICB9XG5cbiAgcmV0dXJuIGludGVyc2VjdGlvbnM7XG59O1xudmFyIHNob3J0ZW5JbnRlcnNlY3Rpb24gPSBmdW5jdGlvbiBzaG9ydGVuSW50ZXJzZWN0aW9uKGludGVyc2VjdGlvbiwgb2Zmc2V0LCBhbW91bnQpIHtcbiAgdmFyIGRpc3AgPSBbaW50ZXJzZWN0aW9uWzBdIC0gb2Zmc2V0WzBdLCBpbnRlcnNlY3Rpb25bMV0gLSBvZmZzZXRbMV1dO1xuICB2YXIgbGVuZ3RoID0gTWF0aC5zcXJ0KGRpc3BbMF0gKiBkaXNwWzBdICsgZGlzcFsxXSAqIGRpc3BbMV0pO1xuICB2YXIgbGVuUmF0aW8gPSAobGVuZ3RoIC0gYW1vdW50KSAvIGxlbmd0aDtcblxuICBpZiAobGVuUmF0aW8gPCAwKSB7XG4gICAgbGVuUmF0aW8gPSAwLjAwMDAxO1xuICB9XG5cbiAgcmV0dXJuIFtvZmZzZXRbMF0gKyBsZW5SYXRpbyAqIGRpc3BbMF0sIG9mZnNldFsxXSArIGxlblJhdGlvICogZGlzcFsxXV07XG59O1xudmFyIGdlbmVyYXRlVW5pdE5nb25Qb2ludHNGaXRUb1NxdWFyZSA9IGZ1bmN0aW9uIGdlbmVyYXRlVW5pdE5nb25Qb2ludHNGaXRUb1NxdWFyZShzaWRlcywgcm90YXRpb25SYWRpYW5zKSB7XG4gIHZhciBwb2ludHMgPSBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzKHNpZGVzLCByb3RhdGlvblJhZGlhbnMpO1xuICBwb2ludHMgPSBmaXRQb2x5Z29uVG9TcXVhcmUocG9pbnRzKTtcbiAgcmV0dXJuIHBvaW50cztcbn07XG52YXIgZml0UG9seWdvblRvU3F1YXJlID0gZnVuY3Rpb24gZml0UG9seWdvblRvU3F1YXJlKHBvaW50cykge1xuICB2YXIgeCwgeTtcbiAgdmFyIHNpZGVzID0gcG9pbnRzLmxlbmd0aCAvIDI7XG4gIHZhciBtaW5YID0gSW5maW5pdHksXG4gICAgICBtaW5ZID0gSW5maW5pdHksXG4gICAgICBtYXhYID0gLUluZmluaXR5LFxuICAgICAgbWF4WSA9IC1JbmZpbml0eTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHNpZGVzOyBpKyspIHtcbiAgICB4ID0gcG9pbnRzWzIgKiBpXTtcbiAgICB5ID0gcG9pbnRzWzIgKiBpICsgMV07XG4gICAgbWluWCA9IE1hdGgubWluKG1pblgsIHgpO1xuICAgIG1heFggPSBNYXRoLm1heChtYXhYLCB4KTtcbiAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgeSk7XG4gICAgbWF4WSA9IE1hdGgubWF4KG1heFksIHkpO1xuICB9IC8vIHN0cmV0Y2ggZmFjdG9yc1xuXG5cbiAgdmFyIHN4ID0gMiAvIChtYXhYIC0gbWluWCk7XG4gIHZhciBzeSA9IDIgLyAobWF4WSAtIG1pblkpO1xuXG4gIGZvciAodmFyIF9pNSA9IDA7IF9pNSA8IHNpZGVzOyBfaTUrKykge1xuICAgIHggPSBwb2ludHNbMiAqIF9pNV0gPSBwb2ludHNbMiAqIF9pNV0gKiBzeDtcbiAgICB5ID0gcG9pbnRzWzIgKiBfaTUgKyAxXSA9IHBvaW50c1syICogX2k1ICsgMV0gKiBzeTtcbiAgICBtaW5YID0gTWF0aC5taW4obWluWCwgeCk7XG4gICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIHgpO1xuICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCB5KTtcbiAgICBtYXhZID0gTWF0aC5tYXgobWF4WSwgeSk7XG4gIH1cblxuICBpZiAobWluWSA8IC0xKSB7XG4gICAgZm9yICh2YXIgX2k2ID0gMDsgX2k2IDwgc2lkZXM7IF9pNisrKSB7XG4gICAgICB5ID0gcG9pbnRzWzIgKiBfaTYgKyAxXSA9IHBvaW50c1syICogX2k2ICsgMV0gKyAoLTEgLSBtaW5ZKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcG9pbnRzO1xufTtcbnZhciBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzID0gZnVuY3Rpb24gZ2VuZXJhdGVVbml0TmdvblBvaW50cyhzaWRlcywgcm90YXRpb25SYWRpYW5zKSB7XG4gIHZhciBpbmNyZW1lbnQgPSAxLjAgLyBzaWRlcyAqIDIgKiBNYXRoLlBJO1xuICB2YXIgc3RhcnRBbmdsZSA9IHNpZGVzICUgMiA9PT0gMCA/IE1hdGguUEkgLyAyLjAgKyBpbmNyZW1lbnQgLyAyLjAgOiBNYXRoLlBJIC8gMi4wO1xuICBzdGFydEFuZ2xlICs9IHJvdGF0aW9uUmFkaWFucztcbiAgdmFyIHBvaW50cyA9IG5ldyBBcnJheShzaWRlcyAqIDIpO1xuICB2YXIgY3VycmVudEFuZ2xlO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc2lkZXM7IGkrKykge1xuICAgIGN1cnJlbnRBbmdsZSA9IGkgKiBpbmNyZW1lbnQgKyBzdGFydEFuZ2xlO1xuICAgIHBvaW50c1syICogaV0gPSBNYXRoLmNvcyhjdXJyZW50QW5nbGUpOyAvLyB4XG5cbiAgICBwb2ludHNbMiAqIGkgKyAxXSA9IE1hdGguc2luKC1jdXJyZW50QW5nbGUpOyAvLyB5XG4gIH1cblxuICByZXR1cm4gcG9pbnRzO1xufTsgLy8gU2V0IHRoZSBkZWZhdWx0IHJhZGl1cywgdW5sZXNzIGhhbGYgb2Ygd2lkdGggb3IgaGVpZ2h0IGlzIHNtYWxsZXIgdGhhbiBkZWZhdWx0XG5cbnZhciBnZXRSb3VuZFJlY3RhbmdsZVJhZGl1cyA9IGZ1bmN0aW9uIGdldFJvdW5kUmVjdGFuZ2xlUmFkaXVzKHdpZHRoLCBoZWlnaHQpIHtcbiAgcmV0dXJuIE1hdGgubWluKHdpZHRoIC8gNCwgaGVpZ2h0IC8gNCwgOCk7XG59OyAvLyBTZXQgdGhlIGRlZmF1bHQgcmFkaXVzXG5cbnZhciBnZXRSb3VuZFBvbHlnb25SYWRpdXMgPSBmdW5jdGlvbiBnZXRSb3VuZFBvbHlnb25SYWRpdXMod2lkdGgsIGhlaWdodCkge1xuICByZXR1cm4gTWF0aC5taW4od2lkdGggLyAxMCwgaGVpZ2h0IC8gMTAsIDgpO1xufTtcbnZhciBnZXRDdXRSZWN0YW5nbGVDb3JuZXJMZW5ndGggPSBmdW5jdGlvbiBnZXRDdXRSZWN0YW5nbGVDb3JuZXJMZW5ndGgoKSB7XG4gIHJldHVybiA4O1xufTtcbnZhciBiZXppZXJQdHNUb1F1YWRDb2VmZiA9IGZ1bmN0aW9uIGJlemllclB0c1RvUXVhZENvZWZmKHAwLCBwMSwgcDIpIHtcbiAgcmV0dXJuIFtwMCAtIDIgKiBwMSArIHAyLCAyICogKHAxIC0gcDApLCBwMF07XG59OyAvLyBnZXQgY3VydmUgd2lkdGgsIGhlaWdodCwgYW5kIGNvbnRyb2wgcG9pbnQgcG9zaXRpb24gb2Zmc2V0cyBhcyBhIHBlcmNlbnRhZ2Ugb2Ygbm9kZSBoZWlnaHQgLyB3aWR0aFxuXG52YXIgZ2V0QmFycmVsQ3VydmVDb25zdGFudHMgPSBmdW5jdGlvbiBnZXRCYXJyZWxDdXJ2ZUNvbnN0YW50cyh3aWR0aCwgaGVpZ2h0KSB7XG4gIHJldHVybiB7XG4gICAgaGVpZ2h0T2Zmc2V0OiBNYXRoLm1pbigxNSwgMC4wNSAqIGhlaWdodCksXG4gICAgd2lkdGhPZmZzZXQ6IE1hdGgubWluKDEwMCwgMC4yNSAqIHdpZHRoKSxcbiAgICBjdHJsUHRPZmZzZXRQY3Q6IDAuMDVcbiAgfTtcbn07XG5cbnZhciBwYWdlUmFua0RlZmF1bHRzID0gZGVmYXVsdHMoe1xuICBkYW1waW5nRmFjdG9yOiAwLjgsXG4gIHByZWNpc2lvbjogMC4wMDAwMDEsXG4gIGl0ZXJhdGlvbnM6IDIwMCxcbiAgd2VpZ2h0OiBmdW5jdGlvbiB3ZWlnaHQoZWRnZSkge1xuICAgIHJldHVybiAxO1xuICB9XG59KTtcbnZhciBlbGVzZm4kNyA9IHtcbiAgcGFnZVJhbms6IGZ1bmN0aW9uIHBhZ2VSYW5rKG9wdGlvbnMpIHtcbiAgICB2YXIgX3BhZ2VSYW5rRGVmYXVsdHMgPSBwYWdlUmFua0RlZmF1bHRzKG9wdGlvbnMpLFxuICAgICAgICBkYW1waW5nRmFjdG9yID0gX3BhZ2VSYW5rRGVmYXVsdHMuZGFtcGluZ0ZhY3RvcixcbiAgICAgICAgcHJlY2lzaW9uID0gX3BhZ2VSYW5rRGVmYXVsdHMucHJlY2lzaW9uLFxuICAgICAgICBpdGVyYXRpb25zID0gX3BhZ2VSYW5rRGVmYXVsdHMuaXRlcmF0aW9ucyxcbiAgICAgICAgd2VpZ2h0ID0gX3BhZ2VSYW5rRGVmYXVsdHMud2VpZ2h0O1xuXG4gICAgdmFyIGN5ID0gdGhpcy5fcHJpdmF0ZS5jeTtcblxuICAgIHZhciBfdGhpcyRieUdyb3VwID0gdGhpcy5ieUdyb3VwKCksXG4gICAgICAgIG5vZGVzID0gX3RoaXMkYnlHcm91cC5ub2RlcyxcbiAgICAgICAgZWRnZXMgPSBfdGhpcyRieUdyb3VwLmVkZ2VzO1xuXG4gICAgdmFyIG51bU5vZGVzID0gbm9kZXMubGVuZ3RoO1xuICAgIHZhciBudW1Ob2Rlc1NxZCA9IG51bU5vZGVzICogbnVtTm9kZXM7XG4gICAgdmFyIG51bUVkZ2VzID0gZWRnZXMubGVuZ3RoOyAvLyBDb25zdHJ1Y3QgdHJhbnNwb3NlZCBhZGphY2VuY3kgbWF0cml4XG4gICAgLy8gRmlyc3QgbGV0cyBoYXZlIGEgemVyb2VkIG1hdHJpeCBvZiB0aGUgcmlnaHQgc2l6ZVxuICAgIC8vIFdlJ2xsIGFsc28ga2VlcCB0cmFjayBvZiB0aGUgc3VtIG9mIGVhY2ggY29sdW1uXG5cbiAgICB2YXIgbWF0cml4ID0gbmV3IEFycmF5KG51bU5vZGVzU3FkKTtcbiAgICB2YXIgY29sdW1uU3VtID0gbmV3IEFycmF5KG51bU5vZGVzKTtcbiAgICB2YXIgYWRkaXRpb25hbFByb2IgPSAoMSAtIGRhbXBpbmdGYWN0b3IpIC8gbnVtTm9kZXM7IC8vIENyZWF0ZSBudWxsIG1hdHJpeFxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1Ob2RlczsgaSsrKSB7XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG51bU5vZGVzOyBqKyspIHtcbiAgICAgICAgdmFyIG4gPSBpICogbnVtTm9kZXMgKyBqO1xuICAgICAgICBtYXRyaXhbbl0gPSAwO1xuICAgICAgfVxuXG4gICAgICBjb2x1bW5TdW1baV0gPSAwO1xuICAgIH0gLy8gTm93LCBwcm9jZXNzIGVkZ2VzXG5cblxuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBudW1FZGdlczsgX2krKykge1xuICAgICAgdmFyIGVkZ2UgPSBlZGdlc1tfaV07XG4gICAgICB2YXIgc3JjSWQgPSBlZGdlLmRhdGEoJ3NvdXJjZScpO1xuICAgICAgdmFyIHRndElkID0gZWRnZS5kYXRhKCd0YXJnZXQnKTsgLy8gRG9uJ3QgaW5jbHVkZSBsb29wcyBpbiB0aGUgbWF0cml4XG5cbiAgICAgIGlmIChzcmNJZCA9PT0gdGd0SWQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBzID0gbm9kZXMuaW5kZXhPZklkKHNyY0lkKTtcbiAgICAgIHZhciB0ID0gbm9kZXMuaW5kZXhPZklkKHRndElkKTtcbiAgICAgIHZhciB3ID0gd2VpZ2h0KGVkZ2UpO1xuXG4gICAgICB2YXIgX24gPSB0ICogbnVtTm9kZXMgKyBzOyAvLyBVcGRhdGUgbWF0cml4XG5cblxuICAgICAgbWF0cml4W19uXSArPSB3OyAvLyBVcGRhdGUgY29sdW1uIHN1bVxuXG4gICAgICBjb2x1bW5TdW1bc10gKz0gdztcbiAgICB9IC8vIEFkZCBhZGRpdGlvbmFsIHByb2JhYmlsaXR5IGJhc2VkIG9uIGRhbXBpbmcgZmFjdG9yXG4gICAgLy8gQWxzbywgdGFrZSBpbnRvIGFjY291bnQgY29sdW1ucyB0aGF0IGhhdmUgc3VtID0gMFxuXG5cbiAgICB2YXIgcCA9IDEuMCAvIG51bU5vZGVzICsgYWRkaXRpb25hbFByb2I7IC8vIFNob3J0aGFuZFxuICAgIC8vIFRyYXZlcnNlIG1hdHJpeCwgY29sdW1uIGJ5IGNvbHVtblxuXG4gICAgZm9yICh2YXIgX2ogPSAwOyBfaiA8IG51bU5vZGVzOyBfaisrKSB7XG4gICAgICBpZiAoY29sdW1uU3VtW19qXSA9PT0gMCkge1xuICAgICAgICAvLyBObyAnbGlua3MnIG91dCBmcm9tIG5vZGUganRoLCBhc3N1bWUgZXF1YWwgcHJvYmFiaWxpdHkgZm9yIGVhY2ggcG9zc2libGUgbm9kZVxuICAgICAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBudW1Ob2RlczsgX2kyKyspIHtcbiAgICAgICAgICB2YXIgX24yID0gX2kyICogbnVtTm9kZXMgKyBfajtcblxuICAgICAgICAgIG1hdHJpeFtfbjJdID0gcDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gTm9kZSBqdGggaGFzIG91dGdvaW5nIGxpbmssIGNvbXB1dGUgbm9ybWFsaXplZCBwcm9iYWJpbGl0aWVzXG4gICAgICAgIGZvciAodmFyIF9pMyA9IDA7IF9pMyA8IG51bU5vZGVzOyBfaTMrKykge1xuICAgICAgICAgIHZhciBfbjMgPSBfaTMgKiBudW1Ob2RlcyArIF9qO1xuXG4gICAgICAgICAgbWF0cml4W19uM10gPSBtYXRyaXhbX24zXSAvIGNvbHVtblN1bVtfal0gKyBhZGRpdGlvbmFsUHJvYjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gLy8gQ29tcHV0ZSBkb21pbmFudCBlaWdlbnZlY3RvciB1c2luZyBwb3dlciBtZXRob2RcblxuXG4gICAgdmFyIGVpZ2VudmVjdG9yID0gbmV3IEFycmF5KG51bU5vZGVzKTtcbiAgICB2YXIgdGVtcCA9IG5ldyBBcnJheShudW1Ob2Rlcyk7XG4gICAgdmFyIHByZXZpb3VzOyAvLyBTdGFydCB3aXRoIGEgdmVjdG9yIG9mIGFsbCAxJ3NcbiAgICAvLyBBbHNvLCBpbml0aWFsaXplIGEgbnVsbCB2ZWN0b3Igd2hpY2ggd2lsbCBiZSB1c2VkIGFzIHNob3J0aGFuZFxuXG4gICAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgbnVtTm9kZXM7IF9pNCsrKSB7XG4gICAgICBlaWdlbnZlY3RvcltfaTRdID0gMTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpdGVyID0gMDsgaXRlciA8IGl0ZXJhdGlvbnM7IGl0ZXIrKykge1xuICAgICAgLy8gVGVtcCBhcnJheSB3aXRoIGFsbCAwJ3NcbiAgICAgIGZvciAodmFyIF9pNSA9IDA7IF9pNSA8IG51bU5vZGVzOyBfaTUrKykge1xuICAgICAgICB0ZW1wW19pNV0gPSAwO1xuICAgICAgfSAvLyBNdWx0aXBseSBtYXRyaXggd2l0aCBwcmV2aW91cyByZXN1bHRcblxuXG4gICAgICBmb3IgKHZhciBfaTYgPSAwOyBfaTYgPCBudW1Ob2RlczsgX2k2KyspIHtcbiAgICAgICAgZm9yICh2YXIgX2oyID0gMDsgX2oyIDwgbnVtTm9kZXM7IF9qMisrKSB7XG4gICAgICAgICAgdmFyIF9uNCA9IF9pNiAqIG51bU5vZGVzICsgX2oyO1xuXG4gICAgICAgICAgdGVtcFtfaTZdICs9IG1hdHJpeFtfbjRdICogZWlnZW52ZWN0b3JbX2oyXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpblBsYWNlU3VtTm9ybWFsaXplKHRlbXApO1xuICAgICAgcHJldmlvdXMgPSBlaWdlbnZlY3RvcjtcbiAgICAgIGVpZ2VudmVjdG9yID0gdGVtcDtcbiAgICAgIHRlbXAgPSBwcmV2aW91cztcbiAgICAgIHZhciBkaWZmID0gMDsgLy8gQ29tcHV0ZSBkaWZmZXJlbmNlIChzcXVhcmVkIG1vZHVsZSkgb2YgYm90aCB2ZWN0b3JzXG5cbiAgICAgIGZvciAodmFyIF9pNyA9IDA7IF9pNyA8IG51bU5vZGVzOyBfaTcrKykge1xuICAgICAgICB2YXIgZGVsdGEgPSBwcmV2aW91c1tfaTddIC0gZWlnZW52ZWN0b3JbX2k3XTtcbiAgICAgICAgZGlmZiArPSBkZWx0YSAqIGRlbHRhO1xuICAgICAgfSAvLyBJZiBkaWZmZXJlbmNlIGlzIGxlc3MgdGhhbiB0aGUgZGVzaXJlZCB0aHJlc2hvbGQsIHN0b3AgaXRlcmF0aW5nXG5cblxuICAgICAgaWYgKGRpZmYgPCBwcmVjaXNpb24pIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSAvLyBDb25zdHJ1Y3QgcmVzdWx0XG5cblxuICAgIHZhciByZXMgPSB7XG4gICAgICByYW5rOiBmdW5jdGlvbiByYW5rKG5vZGUpIHtcbiAgICAgICAgbm9kZSA9IGN5LmNvbGxlY3Rpb24obm9kZSlbMF07XG4gICAgICAgIHJldHVybiBlaWdlbnZlY3Rvcltub2Rlcy5pbmRleE9mKG5vZGUpXTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiByZXM7XG4gIH0gLy8gcGFnZVJhbmtcblxufTsgLy8gZWxlc2ZuXG5cbnZhciBkZWZhdWx0cyQxID0gZGVmYXVsdHMoe1xuICByb290OiBudWxsLFxuICB3ZWlnaHQ6IGZ1bmN0aW9uIHdlaWdodChlZGdlKSB7XG4gICAgcmV0dXJuIDE7XG4gIH0sXG4gIGRpcmVjdGVkOiBmYWxzZSxcbiAgYWxwaGE6IDBcbn0pO1xudmFyIGVsZXNmbiQ4ID0ge1xuICBkZWdyZWVDZW50cmFsaXR5Tm9ybWFsaXplZDogZnVuY3Rpb24gZGVncmVlQ2VudHJhbGl0eU5vcm1hbGl6ZWQob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBkZWZhdWx0cyQxKG9wdGlvbnMpO1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgICB2YXIgbm9kZXMgPSB0aGlzLm5vZGVzKCk7XG4gICAgdmFyIG51bU5vZGVzID0gbm9kZXMubGVuZ3RoO1xuXG4gICAgaWYgKCFvcHRpb25zLmRpcmVjdGVkKSB7XG4gICAgICB2YXIgZGVncmVlcyA9IHt9O1xuICAgICAgdmFyIG1heERlZ3JlZSA9IDA7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtTm9kZXM7IGkrKykge1xuICAgICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldOyAvLyBhZGQgY3VycmVudCBub2RlIHRvIHRoZSBjdXJyZW50IG9wdGlvbnMgb2JqZWN0IGFuZCBjYWxsIGRlZ3JlZUNlbnRyYWxpdHlcblxuICAgICAgICBvcHRpb25zLnJvb3QgPSBub2RlO1xuICAgICAgICB2YXIgY3VyckRlZ3JlZSA9IHRoaXMuZGVncmVlQ2VudHJhbGl0eShvcHRpb25zKTtcblxuICAgICAgICBpZiAobWF4RGVncmVlIDwgY3VyckRlZ3JlZS5kZWdyZWUpIHtcbiAgICAgICAgICBtYXhEZWdyZWUgPSBjdXJyRGVncmVlLmRlZ3JlZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRlZ3JlZXNbbm9kZS5pZCgpXSA9IGN1cnJEZWdyZWUuZGVncmVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBkZWdyZWU6IGZ1bmN0aW9uIGRlZ3JlZShub2RlKSB7XG4gICAgICAgICAgaWYgKG1heERlZ3JlZSA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHN0cmluZyhub2RlKSkge1xuICAgICAgICAgICAgLy8gZnJvbSBpcyBhIHNlbGVjdG9yIHN0cmluZ1xuICAgICAgICAgICAgbm9kZSA9IGN5LmZpbHRlcihub2RlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZGVncmVlc1tub2RlLmlkKCldIC8gbWF4RGVncmVlO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgaW5kZWdyZWVzID0ge307XG4gICAgICB2YXIgb3V0ZGVncmVlcyA9IHt9O1xuICAgICAgdmFyIG1heEluZGVncmVlID0gMDtcbiAgICAgIHZhciBtYXhPdXRkZWdyZWUgPSAwO1xuXG4gICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbnVtTm9kZXM7IF9pKyspIHtcbiAgICAgICAgdmFyIF9ub2RlID0gbm9kZXNbX2ldO1xuXG4gICAgICAgIHZhciBpZCA9IF9ub2RlLmlkKCk7IC8vIGFkZCBjdXJyZW50IG5vZGUgdG8gdGhlIGN1cnJlbnQgb3B0aW9ucyBvYmplY3QgYW5kIGNhbGwgZGVncmVlQ2VudHJhbGl0eVxuXG5cbiAgICAgICAgb3B0aW9ucy5yb290ID0gX25vZGU7XG5cbiAgICAgICAgdmFyIF9jdXJyRGVncmVlID0gdGhpcy5kZWdyZWVDZW50cmFsaXR5KG9wdGlvbnMpO1xuXG4gICAgICAgIGlmIChtYXhJbmRlZ3JlZSA8IF9jdXJyRGVncmVlLmluZGVncmVlKSBtYXhJbmRlZ3JlZSA9IF9jdXJyRGVncmVlLmluZGVncmVlO1xuICAgICAgICBpZiAobWF4T3V0ZGVncmVlIDwgX2N1cnJEZWdyZWUub3V0ZGVncmVlKSBtYXhPdXRkZWdyZWUgPSBfY3VyckRlZ3JlZS5vdXRkZWdyZWU7XG4gICAgICAgIGluZGVncmVlc1tpZF0gPSBfY3VyckRlZ3JlZS5pbmRlZ3JlZTtcbiAgICAgICAgb3V0ZGVncmVlc1tpZF0gPSBfY3VyckRlZ3JlZS5vdXRkZWdyZWU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGluZGVncmVlOiBmdW5jdGlvbiBpbmRlZ3JlZShub2RlKSB7XG4gICAgICAgICAgaWYgKG1heEluZGVncmVlID09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChzdHJpbmcobm9kZSkpIHtcbiAgICAgICAgICAgIC8vIGZyb20gaXMgYSBzZWxlY3RvciBzdHJpbmdcbiAgICAgICAgICAgIG5vZGUgPSBjeS5maWx0ZXIobm9kZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGluZGVncmVlc1tub2RlLmlkKCldIC8gbWF4SW5kZWdyZWU7XG4gICAgICAgIH0sXG4gICAgICAgIG91dGRlZ3JlZTogZnVuY3Rpb24gb3V0ZGVncmVlKG5vZGUpIHtcbiAgICAgICAgICBpZiAobWF4T3V0ZGVncmVlID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoc3RyaW5nKG5vZGUpKSB7XG4gICAgICAgICAgICAvLyBmcm9tIGlzIGEgc2VsZWN0b3Igc3RyaW5nXG4gICAgICAgICAgICBub2RlID0gY3kuZmlsdGVyKG5vZGUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBvdXRkZWdyZWVzW25vZGUuaWQoKV0gLyBtYXhPdXRkZWdyZWU7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICB9LFxuICAvLyBkZWdyZWVDZW50cmFsaXR5Tm9ybWFsaXplZFxuICAvLyBJbXBsZW1lbnRlZCBmcm9tIHRoZSBhbGdvcml0aG0gaW4gT3BzYWhsJ3MgcGFwZXJcbiAgLy8gXCJOb2RlIGNlbnRyYWxpdHkgaW4gd2VpZ2h0ZWQgbmV0d29ya3M6IEdlbmVyYWxpemluZyBkZWdyZWUgYW5kIHNob3J0ZXN0IHBhdGhzXCJcbiAgLy8gY2hlY2sgdGhlIGhlYWRpbmcgMiBcIkRlZ3JlZVwiXG4gIGRlZ3JlZUNlbnRyYWxpdHk6IGZ1bmN0aW9uIGRlZ3JlZUNlbnRyYWxpdHkob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBkZWZhdWx0cyQxKG9wdGlvbnMpO1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgICB2YXIgY2FsbGluZ0VsZXMgPSB0aGlzO1xuICAgIHZhciBfb3B0aW9ucyA9IG9wdGlvbnMsXG4gICAgICAgIHJvb3QgPSBfb3B0aW9ucy5yb290LFxuICAgICAgICB3ZWlnaHQgPSBfb3B0aW9ucy53ZWlnaHQsXG4gICAgICAgIGRpcmVjdGVkID0gX29wdGlvbnMuZGlyZWN0ZWQsXG4gICAgICAgIGFscGhhID0gX29wdGlvbnMuYWxwaGE7XG4gICAgcm9vdCA9IGN5LmNvbGxlY3Rpb24ocm9vdClbMF07XG5cbiAgICBpZiAoIWRpcmVjdGVkKSB7XG4gICAgICB2YXIgY29ubkVkZ2VzID0gcm9vdC5jb25uZWN0ZWRFZGdlcygpLmludGVyc2VjdGlvbihjYWxsaW5nRWxlcyk7XG4gICAgICB2YXIgayA9IGNvbm5FZGdlcy5sZW5ndGg7XG4gICAgICB2YXIgcyA9IDA7IC8vIE5vdywgc3VtIGVkZ2Ugd2VpZ2h0c1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbm5FZGdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzICs9IHdlaWdodChjb25uRWRnZXNbaV0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBkZWdyZWU6IE1hdGgucG93KGssIDEgLSBhbHBoYSkgKiBNYXRoLnBvdyhzLCBhbHBoYSlcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBlZGdlcyA9IHJvb3QuY29ubmVjdGVkRWRnZXMoKTtcbiAgICAgIHZhciBpbmNvbWluZyA9IGVkZ2VzLmZpbHRlcihmdW5jdGlvbiAoZWRnZSkge1xuICAgICAgICByZXR1cm4gZWRnZS50YXJnZXQoKS5zYW1lKHJvb3QpICYmIGNhbGxpbmdFbGVzLmhhcyhlZGdlKTtcbiAgICAgIH0pO1xuICAgICAgdmFyIG91dGdvaW5nID0gZWRnZXMuZmlsdGVyKGZ1bmN0aW9uIChlZGdlKSB7XG4gICAgICAgIHJldHVybiBlZGdlLnNvdXJjZSgpLnNhbWUocm9vdCkgJiYgY2FsbGluZ0VsZXMuaGFzKGVkZ2UpO1xuICAgICAgfSk7XG4gICAgICB2YXIga19pbiA9IGluY29taW5nLmxlbmd0aDtcbiAgICAgIHZhciBrX291dCA9IG91dGdvaW5nLmxlbmd0aDtcbiAgICAgIHZhciBzX2luID0gMDtcbiAgICAgIHZhciBzX291dCA9IDA7IC8vIE5vdywgc3VtIGluY29taW5nIGVkZ2Ugd2VpZ2h0c1xuXG4gICAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBpbmNvbWluZy5sZW5ndGg7IF9pMisrKSB7XG4gICAgICAgIHNfaW4gKz0gd2VpZ2h0KGluY29taW5nW19pMl0pO1xuICAgICAgfSAvLyBOb3csIHN1bSBvdXRnb2luZyBlZGdlIHdlaWdodHNcblxuXG4gICAgICBmb3IgKHZhciBfaTMgPSAwOyBfaTMgPCBvdXRnb2luZy5sZW5ndGg7IF9pMysrKSB7XG4gICAgICAgIHNfb3V0ICs9IHdlaWdodChvdXRnb2luZ1tfaTNdKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaW5kZWdyZWU6IE1hdGgucG93KGtfaW4sIDEgLSBhbHBoYSkgKiBNYXRoLnBvdyhzX2luLCBhbHBoYSksXG4gICAgICAgIG91dGRlZ3JlZTogTWF0aC5wb3coa19vdXQsIDEgLSBhbHBoYSkgKiBNYXRoLnBvdyhzX291dCwgYWxwaGEpXG4gICAgICB9O1xuICAgIH1cbiAgfSAvLyBkZWdyZWVDZW50cmFsaXR5XG5cbn07IC8vIGVsZXNmblxuLy8gbmljZSwgc2hvcnQgbWF0aGVtYXRoaWNhbCBhbGlhc1xuXG5lbGVzZm4kOC5kYyA9IGVsZXNmbiQ4LmRlZ3JlZUNlbnRyYWxpdHk7XG5lbGVzZm4kOC5kY24gPSBlbGVzZm4kOC5kZWdyZWVDZW50cmFsaXR5Tm9ybWFsaXNlZCA9IGVsZXNmbiQ4LmRlZ3JlZUNlbnRyYWxpdHlOb3JtYWxpemVkO1xuXG52YXIgZGVmYXVsdHMkMiA9IGRlZmF1bHRzKHtcbiAgaGFybW9uaWM6IHRydWUsXG4gIHdlaWdodDogZnVuY3Rpb24gd2VpZ2h0KCkge1xuICAgIHJldHVybiAxO1xuICB9LFxuICBkaXJlY3RlZDogZmFsc2UsXG4gIHJvb3Q6IG51bGxcbn0pO1xudmFyIGVsZXNmbiQ5ID0ge1xuICBjbG9zZW5lc3NDZW50cmFsaXR5Tm9ybWFsaXplZDogZnVuY3Rpb24gY2xvc2VuZXNzQ2VudHJhbGl0eU5vcm1hbGl6ZWQob3B0aW9ucykge1xuICAgIHZhciBfZGVmYXVsdHMgPSBkZWZhdWx0cyQyKG9wdGlvbnMpLFxuICAgICAgICBoYXJtb25pYyA9IF9kZWZhdWx0cy5oYXJtb25pYyxcbiAgICAgICAgd2VpZ2h0ID0gX2RlZmF1bHRzLndlaWdodCxcbiAgICAgICAgZGlyZWN0ZWQgPSBfZGVmYXVsdHMuZGlyZWN0ZWQ7XG5cbiAgICB2YXIgY3kgPSB0aGlzLmN5KCk7XG4gICAgdmFyIGNsb3NlbmVzc2VzID0ge307XG4gICAgdmFyIG1heENsb3NlbmVzcyA9IDA7XG4gICAgdmFyIG5vZGVzID0gdGhpcy5ub2RlcygpO1xuICAgIHZhciBmdyA9IHRoaXMuZmxveWRXYXJzaGFsbCh7XG4gICAgICB3ZWlnaHQ6IHdlaWdodCxcbiAgICAgIGRpcmVjdGVkOiBkaXJlY3RlZFxuICAgIH0pOyAvLyBDb21wdXRlIGNsb3NlbmVzcyBmb3IgZXZlcnkgbm9kZSBhbmQgZmluZCB0aGUgbWF4aW11bSBjbG9zZW5lc3NcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjdXJyQ2xvc2VuZXNzID0gMDtcbiAgICAgIHZhciBub2RlX2kgPSBub2Rlc1tpXTtcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBub2Rlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBpZiAoaSAhPT0gaikge1xuICAgICAgICAgIHZhciBkID0gZncuZGlzdGFuY2Uobm9kZV9pLCBub2Rlc1tqXSk7XG5cbiAgICAgICAgICBpZiAoaGFybW9uaWMpIHtcbiAgICAgICAgICAgIGN1cnJDbG9zZW5lc3MgKz0gMSAvIGQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN1cnJDbG9zZW5lc3MgKz0gZDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKCFoYXJtb25pYykge1xuICAgICAgICBjdXJyQ2xvc2VuZXNzID0gMSAvIGN1cnJDbG9zZW5lc3M7XG4gICAgICB9XG5cbiAgICAgIGlmIChtYXhDbG9zZW5lc3MgPCBjdXJyQ2xvc2VuZXNzKSB7XG4gICAgICAgIG1heENsb3NlbmVzcyA9IGN1cnJDbG9zZW5lc3M7XG4gICAgICB9XG5cbiAgICAgIGNsb3NlbmVzc2VzW25vZGVfaS5pZCgpXSA9IGN1cnJDbG9zZW5lc3M7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNsb3NlbmVzczogZnVuY3Rpb24gY2xvc2VuZXNzKG5vZGUpIHtcbiAgICAgICAgaWYgKG1heENsb3NlbmVzcyA9PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RyaW5nKG5vZGUpKSB7XG4gICAgICAgICAgLy8gZnJvbSBpcyBhIHNlbGVjdG9yIHN0cmluZ1xuICAgICAgICAgIG5vZGUgPSBjeS5maWx0ZXIobm9kZSlbMF0uaWQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBmcm9tIGlzIGEgbm9kZVxuICAgICAgICAgIG5vZGUgPSBub2RlLmlkKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2xvc2VuZXNzZXNbbm9kZV0gLyBtYXhDbG9zZW5lc3M7XG4gICAgICB9XG4gICAgfTtcbiAgfSxcbiAgLy8gSW1wbGVtZW50ZWQgZnJvbSBwc2V1ZG9jb2RlIGZyb20gd2lraXBlZGlhXG4gIGNsb3NlbmVzc0NlbnRyYWxpdHk6IGZ1bmN0aW9uIGNsb3NlbmVzc0NlbnRyYWxpdHkob3B0aW9ucykge1xuICAgIHZhciBfZGVmYXVsdHMyID0gZGVmYXVsdHMkMihvcHRpb25zKSxcbiAgICAgICAgcm9vdCA9IF9kZWZhdWx0czIucm9vdCxcbiAgICAgICAgd2VpZ2h0ID0gX2RlZmF1bHRzMi53ZWlnaHQsXG4gICAgICAgIGRpcmVjdGVkID0gX2RlZmF1bHRzMi5kaXJlY3RlZCxcbiAgICAgICAgaGFybW9uaWMgPSBfZGVmYXVsdHMyLmhhcm1vbmljO1xuXG4gICAgcm9vdCA9IHRoaXMuZmlsdGVyKHJvb3QpWzBdOyAvLyB3ZSBuZWVkIGRpc3RhbmNlIGZyb20gdGhpcyBub2RlIHRvIGV2ZXJ5IG90aGVyIG5vZGVcblxuICAgIHZhciBkaWprc3RyYSA9IHRoaXMuZGlqa3N0cmEoe1xuICAgICAgcm9vdDogcm9vdCxcbiAgICAgIHdlaWdodDogd2VpZ2h0LFxuICAgICAgZGlyZWN0ZWQ6IGRpcmVjdGVkXG4gICAgfSk7XG4gICAgdmFyIHRvdGFsRGlzdGFuY2UgPSAwO1xuICAgIHZhciBub2RlcyA9IHRoaXMubm9kZXMoKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBuID0gbm9kZXNbaV07XG5cbiAgICAgIGlmICghbi5zYW1lKHJvb3QpKSB7XG4gICAgICAgIHZhciBkID0gZGlqa3N0cmEuZGlzdGFuY2VUbyhuKTtcblxuICAgICAgICBpZiAoaGFybW9uaWMpIHtcbiAgICAgICAgICB0b3RhbERpc3RhbmNlICs9IDEgLyBkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRvdGFsRGlzdGFuY2UgKz0gZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBoYXJtb25pYyA/IHRvdGFsRGlzdGFuY2UgOiAxIC8gdG90YWxEaXN0YW5jZTtcbiAgfSAvLyBjbG9zZW5lc3NDZW50cmFsaXR5XG5cbn07IC8vIGVsZXNmblxuLy8gbmljZSwgc2hvcnQgbWF0aGVtYXRoaWNhbCBhbGlhc1xuXG5lbGVzZm4kOS5jYyA9IGVsZXNmbiQ5LmNsb3NlbmVzc0NlbnRyYWxpdHk7XG5lbGVzZm4kOS5jY24gPSBlbGVzZm4kOS5jbG9zZW5lc3NDZW50cmFsaXR5Tm9ybWFsaXNlZCA9IGVsZXNmbiQ5LmNsb3NlbmVzc0NlbnRyYWxpdHlOb3JtYWxpemVkO1xuXG52YXIgZGVmYXVsdHMkMyA9IGRlZmF1bHRzKHtcbiAgd2VpZ2h0OiBudWxsLFxuICBkaXJlY3RlZDogZmFsc2Vcbn0pO1xudmFyIGVsZXNmbiRhID0ge1xuICAvLyBJbXBsZW1lbnRlZCBmcm9tIHRoZSBhbGdvcml0aG0gaW4gdGhlIHBhcGVyIFwiT24gVmFyaWFudHMgb2YgU2hvcnRlc3QtUGF0aCBCZXR3ZWVubmVzcyBDZW50cmFsaXR5IGFuZCB0aGVpciBHZW5lcmljIENvbXB1dGF0aW9uXCIgYnkgVWxyaWsgQnJhbmRlc1xuICBiZXR3ZWVubmVzc0NlbnRyYWxpdHk6IGZ1bmN0aW9uIGJldHdlZW5uZXNzQ2VudHJhbGl0eShvcHRpb25zKSB7XG4gICAgdmFyIF9kZWZhdWx0cyA9IGRlZmF1bHRzJDMob3B0aW9ucyksXG4gICAgICAgIGRpcmVjdGVkID0gX2RlZmF1bHRzLmRpcmVjdGVkLFxuICAgICAgICB3ZWlnaHQgPSBfZGVmYXVsdHMud2VpZ2h0O1xuXG4gICAgdmFyIHdlaWdodGVkID0gd2VpZ2h0ICE9IG51bGw7XG4gICAgdmFyIGN5ID0gdGhpcy5jeSgpOyAvLyBzdGFydGluZ1xuXG4gICAgdmFyIFYgPSB0aGlzLm5vZGVzKCk7XG4gICAgdmFyIEEgPSB7fTtcbiAgICB2YXIgX0MgPSB7fTtcbiAgICB2YXIgbWF4ID0gMDtcbiAgICB2YXIgQyA9IHtcbiAgICAgIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsKSB7XG4gICAgICAgIF9DW2tleV0gPSB2YWw7XG5cbiAgICAgICAgaWYgKHZhbCA+IG1heCkge1xuICAgICAgICAgIG1heCA9IHZhbDtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGtleSkge1xuICAgICAgICByZXR1cm4gX0Nba2V5XTtcbiAgICAgIH1cbiAgICB9OyAvLyBBIGNvbnRhaW5zIHRoZSBuZWlnaGJvcmhvb2RzIG9mIGV2ZXJ5IG5vZGVcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgVi5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHYgPSBWW2ldO1xuICAgICAgdmFyIHZpZCA9IHYuaWQoKTtcblxuICAgICAgaWYgKGRpcmVjdGVkKSB7XG4gICAgICAgIEFbdmlkXSA9IHYub3V0Z29lcnMoKS5ub2RlcygpOyAvLyBnZXQgb3V0Z29lcnMgb2YgZXZlcnkgbm9kZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgQVt2aWRdID0gdi5vcGVuTmVpZ2hib3Job29kKCkubm9kZXMoKTsgLy8gZ2V0IG5laWdoYm9ycyBvZiBldmVyeSBub2RlXG4gICAgICB9XG5cbiAgICAgIEMuc2V0KHZpZCwgMCk7XG4gICAgfVxuXG4gICAgdmFyIF9sb29wID0gZnVuY3Rpb24gX2xvb3Aocykge1xuICAgICAgdmFyIHNpZCA9IFZbc10uaWQoKTtcbiAgICAgIHZhciBTID0gW107IC8vIHN0YWNrXG5cbiAgICAgIHZhciBQID0ge307XG4gICAgICB2YXIgZyA9IHt9O1xuICAgICAgdmFyIGQgPSB7fTtcbiAgICAgIHZhciBRID0gbmV3IEhlYXAoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGRbYV0gLSBkW2JdO1xuICAgICAgfSk7IC8vIHF1ZXVlXG4gICAgICAvLyBpbml0IGRpY3Rpb25hcmllc1xuXG4gICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgVi5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIF92aWQgPSBWW19pXS5pZCgpO1xuXG4gICAgICAgIFBbX3ZpZF0gPSBbXTtcbiAgICAgICAgZ1tfdmlkXSA9IDA7XG4gICAgICAgIGRbX3ZpZF0gPSBJbmZpbml0eTtcbiAgICAgIH1cblxuICAgICAgZ1tzaWRdID0gMTsgLy8gc2lnbWFcblxuICAgICAgZFtzaWRdID0gMDsgLy8gZGlzdGFuY2UgdG8gc1xuXG4gICAgICBRLnB1c2goc2lkKTtcblxuICAgICAgd2hpbGUgKCFRLmVtcHR5KCkpIHtcbiAgICAgICAgdmFyIF92ID0gUS5wb3AoKTtcblxuICAgICAgICBTLnB1c2goX3YpO1xuXG4gICAgICAgIGlmICh3ZWlnaHRlZCkge1xuICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgQVtfdl0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciB3ID0gQVtfdl1bal07XG4gICAgICAgICAgICB2YXIgdkVsZSA9IGN5LmdldEVsZW1lbnRCeUlkKF92KTtcbiAgICAgICAgICAgIHZhciBlZGdlID0gdm9pZCAwO1xuXG4gICAgICAgICAgICBpZiAodkVsZS5lZGdlc1RvKHcpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgZWRnZSA9IHZFbGUuZWRnZXNUbyh3KVswXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGVkZ2UgPSB3LmVkZ2VzVG8odkVsZSlbMF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBlZGdlV2VpZ2h0ID0gd2VpZ2h0KGVkZ2UpO1xuICAgICAgICAgICAgdyA9IHcuaWQoKTtcblxuICAgICAgICAgICAgaWYgKGRbd10gPiBkW192XSArIGVkZ2VXZWlnaHQpIHtcbiAgICAgICAgICAgICAgZFt3XSA9IGRbX3ZdICsgZWRnZVdlaWdodDtcblxuICAgICAgICAgICAgICBpZiAoUS5ub2Rlcy5pbmRleE9mKHcpIDwgMCkge1xuICAgICAgICAgICAgICAgIC8vaWYgdyBpcyBub3QgaW4gUVxuICAgICAgICAgICAgICAgIFEucHVzaCh3KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB1cGRhdGUgcG9zaXRpb24gaWYgdyBpcyBpbiBRXG4gICAgICAgICAgICAgICAgUS51cGRhdGVJdGVtKHcpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgZ1t3XSA9IDA7XG4gICAgICAgICAgICAgIFBbd10gPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGRbd10gPT0gZFtfdl0gKyBlZGdlV2VpZ2h0KSB7XG4gICAgICAgICAgICAgIGdbd10gPSBnW3ddICsgZ1tfdl07XG4gICAgICAgICAgICAgIFBbd10ucHVzaChfdik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZvciAodmFyIF9qID0gMDsgX2ogPCBBW192XS5sZW5ndGg7IF9qKyspIHtcbiAgICAgICAgICAgIHZhciBfdyA9IEFbX3ZdW19qXS5pZCgpO1xuXG4gICAgICAgICAgICBpZiAoZFtfd10gPT0gSW5maW5pdHkpIHtcbiAgICAgICAgICAgICAgUS5wdXNoKF93KTtcbiAgICAgICAgICAgICAgZFtfd10gPSBkW192XSArIDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChkW193XSA9PSBkW192XSArIDEpIHtcbiAgICAgICAgICAgICAgZ1tfd10gPSBnW193XSArIGdbX3ZdO1xuXG4gICAgICAgICAgICAgIFBbX3ddLnB1c2goX3YpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgZSA9IHt9O1xuXG4gICAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBWLmxlbmd0aDsgX2kyKyspIHtcbiAgICAgICAgZVtWW19pMl0uaWQoKV0gPSAwO1xuICAgICAgfVxuXG4gICAgICB3aGlsZSAoUy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHZhciBfdzIgPSBTLnBvcCgpO1xuXG4gICAgICAgIGZvciAodmFyIF9qMiA9IDA7IF9qMiA8IFBbX3cyXS5sZW5ndGg7IF9qMisrKSB7XG4gICAgICAgICAgdmFyIF92MiA9IFBbX3cyXVtfajJdO1xuICAgICAgICAgIGVbX3YyXSA9IGVbX3YyXSArIGdbX3YyXSAvIGdbX3cyXSAqICgxICsgZVtfdzJdKTtcblxuICAgICAgICAgIGlmIChfdzIgIT0gVltzXS5pZCgpKSB7XG4gICAgICAgICAgICBDLnNldChfdzIsIEMuZ2V0KF93MikgKyBlW193Ml0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBmb3IgKHZhciBzID0gMDsgcyA8IFYubGVuZ3RoOyBzKyspIHtcbiAgICAgIF9sb29wKHMpO1xuICAgIH1cblxuICAgIHZhciByZXQgPSB7XG4gICAgICBiZXR3ZWVubmVzczogZnVuY3Rpb24gYmV0d2Vlbm5lc3Mobm9kZSkge1xuICAgICAgICB2YXIgaWQgPSBjeS5jb2xsZWN0aW9uKG5vZGUpLmlkKCk7XG4gICAgICAgIHJldHVybiBDLmdldChpZCk7XG4gICAgICB9LFxuICAgICAgYmV0d2Vlbm5lc3NOb3JtYWxpemVkOiBmdW5jdGlvbiBiZXR3ZWVubmVzc05vcm1hbGl6ZWQobm9kZSkge1xuICAgICAgICBpZiAobWF4ID09IDApIHtcbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpZCA9IGN5LmNvbGxlY3Rpb24obm9kZSkuaWQoKTtcbiAgICAgICAgcmV0dXJuIEMuZ2V0KGlkKSAvIG1heDtcbiAgICAgIH1cbiAgICB9OyAvLyBhbGlhc1xuXG4gICAgcmV0LmJldHdlZW5uZXNzTm9ybWFsaXNlZCA9IHJldC5iZXR3ZWVubmVzc05vcm1hbGl6ZWQ7XG4gICAgcmV0dXJuIHJldDtcbiAgfSAvLyBiZXR3ZWVubmVzc0NlbnRyYWxpdHlcblxufTsgLy8gZWxlc2ZuXG4vLyBuaWNlLCBzaG9ydCBtYXRoZW1hdGhpY2FsIGFsaWFzXG5cbmVsZXNmbiRhLmJjID0gZWxlc2ZuJGEuYmV0d2Vlbm5lc3NDZW50cmFsaXR5O1xuXG4vLyBJbXBsZW1lbnRlZCBieSBab2UgWGkgQHpvZXhpIGZvciBHU09DIDIwMTZcbi8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG5cbnZhciBkZWZhdWx0cyQ0ID0gZGVmYXVsdHMoe1xuICBleHBhbmRGYWN0b3I6IDIsXG4gIC8vIGFmZmVjdHMgdGltZSBvZiBjb21wdXRhdGlvbiBhbmQgY2x1c3RlciBncmFudWxhcml0eSB0byBzb21lIGV4dGVudDogTSAqIE1cbiAgaW5mbGF0ZUZhY3RvcjogMixcbiAgLy8gYWZmZWN0cyBjbHVzdGVyIGdyYW51bGFyaXR5ICh0aGUgZ3JlYXRlciB0aGUgdmFsdWUsIHRoZSBtb3JlIGNsdXN0ZXJzKTogTShpLGopIC8gRShqKVxuICBtdWx0RmFjdG9yOiAxLFxuICAvLyBvcHRpb25hbCBzZWxmIGxvb3BzIGZvciBlYWNoIG5vZGUuIFVzZSBhIG5ldXRyYWwgdmFsdWUgdG8gaW1wcm92ZSBjbHVzdGVyIGNvbXB1dGF0aW9ucy5cbiAgbWF4SXRlcmF0aW9uczogMjAsXG4gIC8vIG1heGltdW0gbnVtYmVyIG9mIGl0ZXJhdGlvbnMgb2YgdGhlIE1DTCBhbGdvcml0aG0gaW4gYSBzaW5nbGUgcnVuXG4gIGF0dHJpYnV0ZXM6IFsvLyBhdHRyaWJ1dGVzL2ZlYXR1cmVzIHVzZWQgdG8gZ3JvdXAgbm9kZXMsIGllLiBzaW1pbGFyaXR5IHZhbHVlcyBiZXR3ZWVuIG5vZGVzXG4gIGZ1bmN0aW9uIChlZGdlKSB7XG4gICAgcmV0dXJuIDE7XG4gIH1dXG59KTtcbi8qIGVzbGludC1lbmFibGUgKi9cblxudmFyIHNldE9wdGlvbnMgPSBmdW5jdGlvbiBzZXRPcHRpb25zKG9wdGlvbnMpIHtcbiAgcmV0dXJuIGRlZmF1bHRzJDQob3B0aW9ucyk7XG59O1xuLyogZXNsaW50LWVuYWJsZSAqL1xuXG5cbnZhciBnZXRTaW1pbGFyaXR5ID0gZnVuY3Rpb24gZ2V0U2ltaWxhcml0eShlZGdlLCBhdHRyaWJ1dGVzKSB7XG4gIHZhciB0b3RhbCA9IDA7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdHRyaWJ1dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdG90YWwgKz0gYXR0cmlidXRlc1tpXShlZGdlKTtcbiAgfVxuXG4gIHJldHVybiB0b3RhbDtcbn07XG5cbnZhciBhZGRMb29wcyA9IGZ1bmN0aW9uIGFkZExvb3BzKE0sIG4sIHZhbCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIE1baSAqIG4gKyBpXSA9IHZhbDtcbiAgfVxufTtcblxudmFyIG5vcm1hbGl6ZSA9IGZ1bmN0aW9uIG5vcm1hbGl6ZShNLCBuKSB7XG4gIHZhciBzdW07XG5cbiAgZm9yICh2YXIgY29sID0gMDsgY29sIDwgbjsgY29sKyspIHtcbiAgICBzdW0gPSAwO1xuXG4gICAgZm9yICh2YXIgcm93ID0gMDsgcm93IDwgbjsgcm93KyspIHtcbiAgICAgIHN1bSArPSBNW3JvdyAqIG4gKyBjb2xdO1xuICAgIH1cblxuICAgIGZvciAodmFyIF9yb3cgPSAwOyBfcm93IDwgbjsgX3JvdysrKSB7XG4gICAgICBNW19yb3cgKiBuICsgY29sXSA9IE1bX3JvdyAqIG4gKyBjb2xdIC8gc3VtO1xuICAgIH1cbiAgfVxufTsgLy8gVE9ETzogYmxvY2tlZCBtYXRyaXggbXVsdGlwbGljYXRpb24/XG5cblxudmFyIG1tdWx0ID0gZnVuY3Rpb24gbW11bHQoQSwgQiwgbikge1xuICB2YXIgQyA9IG5ldyBBcnJheShuICogbik7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG47IGorKykge1xuICAgICAgQ1tpICogbiArIGpdID0gMDtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IG47IGsrKykge1xuICAgICAgZm9yICh2YXIgX2ogPSAwOyBfaiA8IG47IF9qKyspIHtcbiAgICAgICAgQ1tpICogbiArIF9qXSArPSBBW2kgKiBuICsga10gKiBCW2sgKiBuICsgX2pdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBDO1xufTtcblxudmFyIGV4cGFuZCA9IGZ1bmN0aW9uIGV4cGFuZChNLCBuLCBleHBhbmRGYWN0b3Jcbi8qKiBwb3dlciAqKi9cbikge1xuICB2YXIgX00gPSBNLnNsaWNlKDApO1xuXG4gIGZvciAodmFyIHAgPSAxOyBwIDwgZXhwYW5kRmFjdG9yOyBwKyspIHtcbiAgICBNID0gbW11bHQoTSwgX00sIG4pO1xuICB9XG5cbiAgcmV0dXJuIE07XG59O1xuXG52YXIgaW5mbGF0ZSA9IGZ1bmN0aW9uIGluZmxhdGUoTSwgbiwgaW5mbGF0ZUZhY3RvclxuLyoqIHIgKiovXG4pIHtcbiAgdmFyIF9NID0gbmV3IEFycmF5KG4gKiBuKTsgLy8gTShpLGopIF4gaW5mbGF0ZVBvd2VyXG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG4gKiBuOyBpKyspIHtcbiAgICBfTVtpXSA9IE1hdGgucG93KE1baV0sIGluZmxhdGVGYWN0b3IpO1xuICB9XG5cbiAgbm9ybWFsaXplKF9NLCBuKTtcbiAgcmV0dXJuIF9NO1xufTtcblxudmFyIGhhc0NvbnZlcmdlZCA9IGZ1bmN0aW9uIGhhc0NvbnZlcmdlZChNLCBfTSwgbjIsIHJvdW5kRmFjdG9yKSB7XG4gIC8vIENoZWNrIHRoYXQgYm90aCBtYXRyaWNlcyBoYXZlIHRoZSBzYW1lIGVsZW1lbnRzIChpLGopXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjI7IGkrKykge1xuICAgIHZhciB2MSA9IE1hdGgucm91bmQoTVtpXSAqIE1hdGgucG93KDEwLCByb3VuZEZhY3RvcikpIC8gTWF0aC5wb3coMTAsIHJvdW5kRmFjdG9yKTsgLy8gdHJ1bmNhdGUgdG8gJ3JvdW5kRmFjdG9yJyBkZWNpbWFsIHBsYWNlc1xuXG4gICAgdmFyIHYyID0gTWF0aC5yb3VuZChfTVtpXSAqIE1hdGgucG93KDEwLCByb3VuZEZhY3RvcikpIC8gTWF0aC5wb3coMTAsIHJvdW5kRmFjdG9yKTtcblxuICAgIGlmICh2MSAhPT0gdjIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbnZhciBhc3NpZ24gPSBmdW5jdGlvbiBhc3NpZ24oTSwgbiwgbm9kZXMsIGN5KSB7XG4gIHZhciBjbHVzdGVycyA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgdmFyIGNsdXN0ZXIgPSBbXTtcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbjsgaisrKSB7XG4gICAgICAvLyBSb3ctd2lzZSBhdHRyYWN0b3JzIGFuZCBlbGVtZW50cyB0aGF0IHRoZXkgYXR0cmFjdCBiZWxvbmcgaW4gc2FtZSBjbHVzdGVyXG4gICAgICBpZiAoTWF0aC5yb3VuZChNW2kgKiBuICsgal0gKiAxMDAwKSAvIDEwMDAgPiAwKSB7XG4gICAgICAgIGNsdXN0ZXIucHVzaChub2Rlc1tqXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNsdXN0ZXIubGVuZ3RoICE9PSAwKSB7XG4gICAgICBjbHVzdGVycy5wdXNoKGN5LmNvbGxlY3Rpb24oY2x1c3RlcikpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjbHVzdGVycztcbn07XG5cbnZhciBpc0R1cGxpY2F0ZSA9IGZ1bmN0aW9uIGlzRHVwbGljYXRlKGMxLCBjMikge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGMxLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFjMltpXSB8fCBjMVtpXS5pZCgpICE9PSBjMltpXS5pZCgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG52YXIgcmVtb3ZlRHVwbGljYXRlcyA9IGZ1bmN0aW9uIHJlbW92ZUR1cGxpY2F0ZXMoY2x1c3RlcnMpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBjbHVzdGVycy5sZW5ndGg7IGkrKykge1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgY2x1c3RlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGlmIChpICE9IGogJiYgaXNEdXBsaWNhdGUoY2x1c3RlcnNbaV0sIGNsdXN0ZXJzW2pdKSkge1xuICAgICAgICBjbHVzdGVycy5zcGxpY2UoaiwgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNsdXN0ZXJzO1xufTtcblxudmFyIG1hcmtvdkNsdXN0ZXJpbmcgPSBmdW5jdGlvbiBtYXJrb3ZDbHVzdGVyaW5nKG9wdGlvbnMpIHtcbiAgdmFyIG5vZGVzID0gdGhpcy5ub2RlcygpO1xuICB2YXIgZWRnZXMgPSB0aGlzLmVkZ2VzKCk7XG4gIHZhciBjeSA9IHRoaXMuY3koKTsgLy8gU2V0IHBhcmFtZXRlcnMgb2YgYWxnb3JpdGhtOlxuXG4gIHZhciBvcHRzID0gc2V0T3B0aW9ucyhvcHRpb25zKTsgLy8gTWFwIGVhY2ggbm9kZSB0byBpdHMgcG9zaXRpb24gaW4gbm9kZSBhcnJheVxuXG4gIHZhciBpZDJwb3NpdGlvbiA9IHt9O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBpZDJwb3NpdGlvbltub2Rlc1tpXS5pZCgpXSA9IGk7XG4gIH0gLy8gR2VuZXJhdGUgc3RvY2hhc3RpYyBtYXRyaXggTSBmcm9tIGlucHV0IGdyYXBoIEcgKHNob3VsZCBiZSBzeW1tZXRyaWMvdW5kaXJlY3RlZClcblxuXG4gIHZhciBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgbjIgPSBuICogbjtcblxuICB2YXIgTSA9IG5ldyBBcnJheShuMiksXG4gICAgICBfTTtcblxuICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbjI7IF9pKyspIHtcbiAgICBNW19pXSA9IDA7XG4gIH1cblxuICBmb3IgKHZhciBlID0gMDsgZSA8IGVkZ2VzLmxlbmd0aDsgZSsrKSB7XG4gICAgdmFyIGVkZ2UgPSBlZGdlc1tlXTtcbiAgICB2YXIgX2kyID0gaWQycG9zaXRpb25bZWRnZS5zb3VyY2UoKS5pZCgpXTtcbiAgICB2YXIgaiA9IGlkMnBvc2l0aW9uW2VkZ2UudGFyZ2V0KCkuaWQoKV07XG4gICAgdmFyIHNpbSA9IGdldFNpbWlsYXJpdHkoZWRnZSwgb3B0cy5hdHRyaWJ1dGVzKTtcbiAgICBNW19pMiAqIG4gKyBqXSArPSBzaW07IC8vIEcgc2hvdWxkIGJlIHN5bW1ldHJpYyBhbmQgdW5kaXJlY3RlZFxuXG4gICAgTVtqICogbiArIF9pMl0gKz0gc2ltO1xuICB9IC8vIEJlZ2luIE1hcmtvdiBjbHVzdGVyIGFsZ29yaXRobVxuICAvLyBTdGVwIDE6IEFkZCBzZWxmIGxvb3BzIHRvIGVhY2ggbm9kZSwgaWUuIGFkZCBtdWx0RmFjdG9yIHRvIG1hdHJpeCBkaWFnb25hbFxuXG5cbiAgYWRkTG9vcHMoTSwgbiwgb3B0cy5tdWx0RmFjdG9yKTsgLy8gU3RlcCAyOiBNID0gbm9ybWFsaXplKCBNICk7XG5cbiAgbm9ybWFsaXplKE0sIG4pO1xuICB2YXIgaXNTdGlsbE1vdmluZyA9IHRydWU7XG4gIHZhciBpdGVyYXRpb25zID0gMDtcblxuICB3aGlsZSAoaXNTdGlsbE1vdmluZyAmJiBpdGVyYXRpb25zIDwgb3B0cy5tYXhJdGVyYXRpb25zKSB7XG4gICAgaXNTdGlsbE1vdmluZyA9IGZhbHNlOyAvLyBTdGVwIDM6XG5cbiAgICBfTSA9IGV4cGFuZChNLCBuLCBvcHRzLmV4cGFuZEZhY3Rvcik7IC8vIFN0ZXAgNDpcblxuICAgIE0gPSBpbmZsYXRlKF9NLCBuLCBvcHRzLmluZmxhdGVGYWN0b3IpOyAvLyBTdGVwIDU6IGNoZWNrIHRvIHNlZSBpZiB+c3RlYWR5IHN0YXRlIGhhcyBiZWVuIHJlYWNoZWRcblxuICAgIGlmICghaGFzQ29udmVyZ2VkKE0sIF9NLCBuMiwgNCkpIHtcbiAgICAgIGlzU3RpbGxNb3ZpbmcgPSB0cnVlO1xuICAgIH1cblxuICAgIGl0ZXJhdGlvbnMrKztcbiAgfSAvLyBCdWlsZCBjbHVzdGVycyBmcm9tIG1hdHJpeFxuXG5cbiAgdmFyIGNsdXN0ZXJzID0gYXNzaWduKE0sIG4sIG5vZGVzLCBjeSk7IC8vIFJlbW92ZSBkdXBsaWNhdGUgY2x1c3RlcnMgZHVlIHRvIHN5bW1ldHJ5IG9mIGdyYXBoIGFuZCBNIG1hdHJpeFxuXG4gIGNsdXN0ZXJzID0gcmVtb3ZlRHVwbGljYXRlcyhjbHVzdGVycyk7XG4gIHJldHVybiBjbHVzdGVycztcbn07XG5cbnZhciBtYXJrb3ZDbHVzdGVyaW5nJDEgPSB7XG4gIG1hcmtvdkNsdXN0ZXJpbmc6IG1hcmtvdkNsdXN0ZXJpbmcsXG4gIG1jbDogbWFya292Q2x1c3RlcmluZ1xufTtcblxuLy8gQ29tbW9uIGRpc3RhbmNlIG1ldHJpY3MgZm9yIGNsdXN0ZXJpbmcgYWxnb3JpdGhtc1xuXG52YXIgaWRlbnRpdHkgPSBmdW5jdGlvbiBpZGVudGl0eSh4KSB7XG4gIHJldHVybiB4O1xufTtcblxudmFyIGFic0RpZmYgPSBmdW5jdGlvbiBhYnNEaWZmKHAsIHEpIHtcbiAgcmV0dXJuIE1hdGguYWJzKHEgLSBwKTtcbn07XG5cbnZhciBhZGRBYnNEaWZmID0gZnVuY3Rpb24gYWRkQWJzRGlmZih0b3RhbCwgcCwgcSkge1xuICByZXR1cm4gdG90YWwgKyBhYnNEaWZmKHAsIHEpO1xufTtcblxudmFyIGFkZFNxdWFyZWREaWZmID0gZnVuY3Rpb24gYWRkU3F1YXJlZERpZmYodG90YWwsIHAsIHEpIHtcbiAgcmV0dXJuIHRvdGFsICsgTWF0aC5wb3cocSAtIHAsIDIpO1xufTtcblxudmFyIHNxcnQgPSBmdW5jdGlvbiBzcXJ0KHgpIHtcbiAgcmV0dXJuIE1hdGguc3FydCh4KTtcbn07XG5cbnZhciBtYXhBYnNEaWZmID0gZnVuY3Rpb24gbWF4QWJzRGlmZihjdXJyZW50TWF4LCBwLCBxKSB7XG4gIHJldHVybiBNYXRoLm1heChjdXJyZW50TWF4LCBhYnNEaWZmKHAsIHEpKTtcbn07XG5cbnZhciBnZXREaXN0YW5jZSA9IGZ1bmN0aW9uIGdldERpc3RhbmNlKGxlbmd0aCwgZ2V0UCwgZ2V0USwgaW5pdCwgdmlzaXQpIHtcbiAgdmFyIHBvc3QgPSBhcmd1bWVudHMubGVuZ3RoID4gNSAmJiBhcmd1bWVudHNbNV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s1XSA6IGlkZW50aXR5O1xuICB2YXIgcmV0ID0gaW5pdDtcbiAgdmFyIHAsIHE7XG5cbiAgZm9yICh2YXIgZGltID0gMDsgZGltIDwgbGVuZ3RoOyBkaW0rKykge1xuICAgIHAgPSBnZXRQKGRpbSk7XG4gICAgcSA9IGdldFEoZGltKTtcbiAgICByZXQgPSB2aXNpdChyZXQsIHAsIHEpO1xuICB9XG5cbiAgcmV0dXJuIHBvc3QocmV0KTtcbn07XG5cbnZhciBkaXN0YW5jZXMgPSB7XG4gIGV1Y2xpZGVhbjogZnVuY3Rpb24gZXVjbGlkZWFuKGxlbmd0aCwgZ2V0UCwgZ2V0USkge1xuICAgIGlmIChsZW5ndGggPj0gMikge1xuICAgICAgcmV0dXJuIGdldERpc3RhbmNlKGxlbmd0aCwgZ2V0UCwgZ2V0USwgMCwgYWRkU3F1YXJlZERpZmYsIHNxcnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBmb3Igc2luZ2xlIGF0dHIgY2FzZSwgbW9yZSBlZmZpY2llbnQgdG8gYXZvaWQgc3FydFxuICAgICAgcmV0dXJuIGdldERpc3RhbmNlKGxlbmd0aCwgZ2V0UCwgZ2V0USwgMCwgYWRkQWJzRGlmZik7XG4gICAgfVxuICB9LFxuICBzcXVhcmVkRXVjbGlkZWFuOiBmdW5jdGlvbiBzcXVhcmVkRXVjbGlkZWFuKGxlbmd0aCwgZ2V0UCwgZ2V0USkge1xuICAgIHJldHVybiBnZXREaXN0YW5jZShsZW5ndGgsIGdldFAsIGdldFEsIDAsIGFkZFNxdWFyZWREaWZmKTtcbiAgfSxcbiAgbWFuaGF0dGFuOiBmdW5jdGlvbiBtYW5oYXR0YW4obGVuZ3RoLCBnZXRQLCBnZXRRKSB7XG4gICAgcmV0dXJuIGdldERpc3RhbmNlKGxlbmd0aCwgZ2V0UCwgZ2V0USwgMCwgYWRkQWJzRGlmZik7XG4gIH0sXG4gIG1heDogZnVuY3Rpb24gbWF4KGxlbmd0aCwgZ2V0UCwgZ2V0USkge1xuICAgIHJldHVybiBnZXREaXN0YW5jZShsZW5ndGgsIGdldFAsIGdldFEsIC1JbmZpbml0eSwgbWF4QWJzRGlmZik7XG4gIH1cbn07IC8vIGluIGNhc2UgdGhlIHVzZXIgYWNjaWRlbnRhbGx5IGRvZXNuJ3QgdXNlIGNhbWVsIGNhc2VcblxuZGlzdGFuY2VzWydzcXVhcmVkLWV1Y2xpZGVhbiddID0gZGlzdGFuY2VzWydzcXVhcmVkRXVjbGlkZWFuJ107XG5kaXN0YW5jZXNbJ3NxdWFyZWRldWNsaWRlYW4nXSA9IGRpc3RhbmNlc1snc3F1YXJlZEV1Y2xpZGVhbiddO1xuZnVuY3Rpb24gY2x1c3RlcmluZ0Rpc3RhbmNlIChtZXRob2QsIGxlbmd0aCwgZ2V0UCwgZ2V0USwgbm9kZVAsIG5vZGVRKSB7XG4gIHZhciBpbXBsO1xuXG4gIGlmIChmbihtZXRob2QpKSB7XG4gICAgaW1wbCA9IG1ldGhvZDtcbiAgfSBlbHNlIHtcbiAgICBpbXBsID0gZGlzdGFuY2VzW21ldGhvZF0gfHwgZGlzdGFuY2VzLmV1Y2xpZGVhbjtcbiAgfVxuXG4gIGlmIChsZW5ndGggPT09IDAgJiYgZm4obWV0aG9kKSkge1xuICAgIHJldHVybiBpbXBsKG5vZGVQLCBub2RlUSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGltcGwobGVuZ3RoLCBnZXRQLCBnZXRRLCBub2RlUCwgbm9kZVEpO1xuICB9XG59XG5cbnZhciBkZWZhdWx0cyQ1ID0gZGVmYXVsdHMoe1xuICBrOiAyLFxuICBtOiAyLFxuICBzZW5zaXRpdml0eVRocmVzaG9sZDogMC4wMDAxLFxuICBkaXN0YW5jZTogJ2V1Y2xpZGVhbicsXG4gIG1heEl0ZXJhdGlvbnM6IDEwLFxuICBhdHRyaWJ1dGVzOiBbXSxcbiAgdGVzdE1vZGU6IGZhbHNlLFxuICB0ZXN0Q2VudHJvaWRzOiBudWxsXG59KTtcblxudmFyIHNldE9wdGlvbnMkMSA9IGZ1bmN0aW9uIHNldE9wdGlvbnMob3B0aW9ucykge1xuICByZXR1cm4gZGVmYXVsdHMkNShvcHRpb25zKTtcbn07XG4vKiBlc2xpbnQtZW5hYmxlICovXG5cblxudmFyIGdldERpc3QgPSBmdW5jdGlvbiBnZXREaXN0KHR5cGUsIG5vZGUsIGNlbnRyb2lkLCBhdHRyaWJ1dGVzLCBtb2RlKSB7XG4gIHZhciBub05vZGVQID0gbW9kZSAhPT0gJ2tNZWRvaWRzJztcbiAgdmFyIGdldFAgPSBub05vZGVQID8gZnVuY3Rpb24gKGkpIHtcbiAgICByZXR1cm4gY2VudHJvaWRbaV07XG4gIH0gOiBmdW5jdGlvbiAoaSkge1xuICAgIHJldHVybiBhdHRyaWJ1dGVzW2ldKGNlbnRyb2lkKTtcbiAgfTtcblxuICB2YXIgZ2V0USA9IGZ1bmN0aW9uIGdldFEoaSkge1xuICAgIHJldHVybiBhdHRyaWJ1dGVzW2ldKG5vZGUpO1xuICB9O1xuXG4gIHZhciBub2RlUCA9IGNlbnRyb2lkO1xuICB2YXIgbm9kZVEgPSBub2RlO1xuICByZXR1cm4gY2x1c3RlcmluZ0Rpc3RhbmNlKHR5cGUsIGF0dHJpYnV0ZXMubGVuZ3RoLCBnZXRQLCBnZXRRLCBub2RlUCwgbm9kZVEpO1xufTtcblxudmFyIHJhbmRvbUNlbnRyb2lkcyA9IGZ1bmN0aW9uIHJhbmRvbUNlbnRyb2lkcyhub2RlcywgaywgYXR0cmlidXRlcykge1xuICB2YXIgbmRpbSA9IGF0dHJpYnV0ZXMubGVuZ3RoO1xuICB2YXIgbWluID0gbmV3IEFycmF5KG5kaW0pO1xuICB2YXIgbWF4ID0gbmV3IEFycmF5KG5kaW0pO1xuICB2YXIgY2VudHJvaWRzID0gbmV3IEFycmF5KGspO1xuICB2YXIgY2VudHJvaWQgPSBudWxsOyAvLyBGaW5kIG1pbiwgbWF4IHZhbHVlcyBmb3IgZWFjaCBhdHRyaWJ1dGUgZGltZW5zaW9uXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuZGltOyBpKyspIHtcbiAgICBtaW5baV0gPSBub2Rlcy5taW4oYXR0cmlidXRlc1tpXSkudmFsdWU7XG4gICAgbWF4W2ldID0gbm9kZXMubWF4KGF0dHJpYnV0ZXNbaV0pLnZhbHVlO1xuICB9IC8vIEJ1aWxkIGsgY2VudHJvaWRzLCBlYWNoIHJlcHJlc2VudGVkIGFzIGFuIG4tZGltIGZlYXR1cmUgdmVjdG9yXG5cblxuICBmb3IgKHZhciBjID0gMDsgYyA8IGs7IGMrKykge1xuICAgIGNlbnRyb2lkID0gW107XG5cbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbmRpbTsgX2krKykge1xuICAgICAgY2VudHJvaWRbX2ldID0gTWF0aC5yYW5kb20oKSAqIChtYXhbX2ldIC0gbWluW19pXSkgKyBtaW5bX2ldOyAvLyByYW5kb20gaW5pdGlhbCB2YWx1ZVxuICAgIH1cblxuICAgIGNlbnRyb2lkc1tjXSA9IGNlbnRyb2lkO1xuICB9XG5cbiAgcmV0dXJuIGNlbnRyb2lkcztcbn07XG5cbnZhciBjbGFzc2lmeSA9IGZ1bmN0aW9uIGNsYXNzaWZ5KG5vZGUsIGNlbnRyb2lkcywgZGlzdGFuY2UsIGF0dHJpYnV0ZXMsIHR5cGUpIHtcbiAgdmFyIG1pbiA9IEluZmluaXR5O1xuICB2YXIgaW5kZXggPSAwO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2VudHJvaWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGRpc3QgPSBnZXREaXN0KGRpc3RhbmNlLCBub2RlLCBjZW50cm9pZHNbaV0sIGF0dHJpYnV0ZXMsIHR5cGUpO1xuXG4gICAgaWYgKGRpc3QgPCBtaW4pIHtcbiAgICAgIG1pbiA9IGRpc3Q7XG4gICAgICBpbmRleCA9IGk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGluZGV4O1xufTtcblxudmFyIGJ1aWxkQ2x1c3RlciA9IGZ1bmN0aW9uIGJ1aWxkQ2x1c3RlcihjZW50cm9pZCwgbm9kZXMsIGFzc2lnbm1lbnQpIHtcbiAgdmFyIGNsdXN0ZXIgPSBbXTtcbiAgdmFyIG5vZGUgPSBudWxsO1xuXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgbm9kZXMubGVuZ3RoOyBuKyspIHtcbiAgICBub2RlID0gbm9kZXNbbl07XG5cbiAgICBpZiAoYXNzaWdubWVudFtub2RlLmlkKCldID09PSBjZW50cm9pZCkge1xuICAgICAgLy9jb25zb2xlLmxvZyhcIk5vZGUgXCIgKyBub2RlLmlkKCkgKyBcIiBpcyBhc3NvY2lhdGVkIHdpdGggbWVkb2lkICM6IFwiICsgbSk7XG4gICAgICBjbHVzdGVyLnB1c2gobm9kZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNsdXN0ZXI7XG59O1xuXG52YXIgaGF2ZVZhbHVlc0NvbnZlcmdlZCA9IGZ1bmN0aW9uIGhhdmVWYWx1ZXNDb252ZXJnZWQodjEsIHYyLCBzZW5zaXRpdml0eVRocmVzaG9sZCkge1xuICByZXR1cm4gTWF0aC5hYnModjIgLSB2MSkgPD0gc2Vuc2l0aXZpdHlUaHJlc2hvbGQ7XG59O1xuXG52YXIgaGF2ZU1hdHJpY2VzQ29udmVyZ2VkID0gZnVuY3Rpb24gaGF2ZU1hdHJpY2VzQ29udmVyZ2VkKHYxLCB2Miwgc2Vuc2l0aXZpdHlUaHJlc2hvbGQpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB2MS5sZW5ndGg7IGkrKykge1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgdjFbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgIHZhciBkaWZmID0gTWF0aC5hYnModjFbaV1bal0gLSB2MltpXVtqXSk7XG5cbiAgICAgIGlmIChkaWZmID4gc2Vuc2l0aXZpdHlUaHJlc2hvbGQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxudmFyIHNlZW5CZWZvcmUgPSBmdW5jdGlvbiBzZWVuQmVmb3JlKG5vZGUsIG1lZG9pZHMsIG4pIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBpZiAobm9kZSA9PT0gbWVkb2lkc1tpXSkgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59O1xuXG52YXIgcmFuZG9tTWVkb2lkcyA9IGZ1bmN0aW9uIHJhbmRvbU1lZG9pZHMobm9kZXMsIGspIHtcbiAgdmFyIG1lZG9pZHMgPSBuZXcgQXJyYXkoayk7IC8vIEZvciBzbWFsbCBkYXRhIHNldHMsIHRoZSBwcm9iYWJpbGl0eSBvZiBtZWRvaWQgY29uZmxpY3QgaXMgZ3JlYXRlcixcbiAgLy8gc28gd2UgbmVlZCB0byBjaGVjayB0byBzZWUgaWYgd2UndmUgYWxyZWFkeSBzZWVuIG9yIGNob3NlIHRoaXMgbm9kZSBiZWZvcmUuXG5cbiAgaWYgKG5vZGVzLmxlbmd0aCA8IDUwKSB7XG4gICAgLy8gUmFuZG9tbHkgc2VsZWN0IGsgbWVkb2lkcyBmcm9tIHRoZSBuIG5vZGVzXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrOyBpKyspIHtcbiAgICAgIHZhciBub2RlID0gbm9kZXNbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbm9kZXMubGVuZ3RoKV07IC8vIElmIHdlJ3ZlIGFscmVhZHkgY2hvc2VuIHRoaXMgbm9kZSB0byBiZSBhIG1lZG9pZCwgZG9uJ3QgY2hvb3NlIGl0IGFnYWluIChmb3Igc21hbGwgZGF0YSBzZXRzKS5cbiAgICAgIC8vIEluc3RlYWQgY2hvb3NlIGEgZGlmZmVyZW50IHJhbmRvbSBub2RlLlxuXG4gICAgICB3aGlsZSAoc2VlbkJlZm9yZShub2RlLCBtZWRvaWRzLCBpKSkge1xuICAgICAgICBub2RlID0gbm9kZXNbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbm9kZXMubGVuZ3RoKV07XG4gICAgICB9XG5cbiAgICAgIG1lZG9pZHNbaV0gPSBub2RlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBSZWxhdGl2ZWx5IGxhcmdlIGRhdGEgc2V0LCBzbyBwcmV0dHkgc2FmZSB0byBub3QgY2hlY2sgYW5kIGp1c3Qgc2VsZWN0IHJhbmRvbSBub2Rlc1xuICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IGs7IF9pMisrKSB7XG4gICAgICBtZWRvaWRzW19pMl0gPSBub2Rlc1tNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBub2Rlcy5sZW5ndGgpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWVkb2lkcztcbn07XG5cbnZhciBmaW5kQ29zdCA9IGZ1bmN0aW9uIGZpbmRDb3N0KHBvdGVudGlhbE5ld01lZG9pZCwgY2x1c3RlciwgYXR0cmlidXRlcykge1xuICB2YXIgY29zdCA9IDA7XG5cbiAgZm9yICh2YXIgbiA9IDA7IG4gPCBjbHVzdGVyLmxlbmd0aDsgbisrKSB7XG4gICAgY29zdCArPSBnZXREaXN0KCdtYW5oYXR0YW4nLCBjbHVzdGVyW25dLCBwb3RlbnRpYWxOZXdNZWRvaWQsIGF0dHJpYnV0ZXMsICdrTWVkb2lkcycpO1xuICB9XG5cbiAgcmV0dXJuIGNvc3Q7XG59O1xuXG52YXIga01lYW5zID0gZnVuY3Rpb24ga01lYW5zKG9wdGlvbnMpIHtcbiAgdmFyIGN5ID0gdGhpcy5jeSgpO1xuICB2YXIgbm9kZXMgPSB0aGlzLm5vZGVzKCk7XG4gIHZhciBub2RlID0gbnVsbDsgLy8gU2V0IHBhcmFtZXRlcnMgb2YgYWxnb3JpdGhtOiAjIG9mIGNsdXN0ZXJzLCBkaXN0YW5jZSBtZXRyaWMsIGV0Yy5cblxuICB2YXIgb3B0cyA9IHNldE9wdGlvbnMkMShvcHRpb25zKTsgLy8gQmVnaW4gay1tZWFucyBhbGdvcml0aG1cblxuICB2YXIgY2x1c3RlcnMgPSBuZXcgQXJyYXkob3B0cy5rKTtcbiAgdmFyIGFzc2lnbm1lbnQgPSB7fTtcbiAgdmFyIGNlbnRyb2lkczsgLy8gU3RlcCAxOiBJbml0aWFsaXplIGNlbnRyb2lkIHBvc2l0aW9uc1xuXG4gIGlmIChvcHRzLnRlc3RNb2RlKSB7XG4gICAgaWYgKHR5cGVvZiBvcHRzLnRlc3RDZW50cm9pZHMgPT09ICdudW1iZXInKSB7XG4gICAgICBjZW50cm9pZHMgPSByYW5kb21DZW50cm9pZHMobm9kZXMsIG9wdHMuaywgb3B0cy5hdHRyaWJ1dGVzKTtcbiAgICB9IGVsc2UgaWYgKF90eXBlb2Yob3B0cy50ZXN0Q2VudHJvaWRzKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGNlbnRyb2lkcyA9IG9wdHMudGVzdENlbnRyb2lkcztcbiAgICB9IGVsc2Uge1xuICAgICAgY2VudHJvaWRzID0gcmFuZG9tQ2VudHJvaWRzKG5vZGVzLCBvcHRzLmssIG9wdHMuYXR0cmlidXRlcyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNlbnRyb2lkcyA9IHJhbmRvbUNlbnRyb2lkcyhub2Rlcywgb3B0cy5rLCBvcHRzLmF0dHJpYnV0ZXMpO1xuICB9XG5cbiAgdmFyIGlzU3RpbGxNb3ZpbmcgPSB0cnVlO1xuICB2YXIgaXRlcmF0aW9ucyA9IDA7XG5cbiAgd2hpbGUgKGlzU3RpbGxNb3ZpbmcgJiYgaXRlcmF0aW9ucyA8IG9wdHMubWF4SXRlcmF0aW9ucykge1xuICAgIC8vIFN0ZXAgMjogQXNzaWduIG5vZGVzIHRvIHRoZSBuZWFyZXN0IGNlbnRyb2lkXG4gICAgZm9yICh2YXIgbiA9IDA7IG4gPCBub2Rlcy5sZW5ndGg7IG4rKykge1xuICAgICAgbm9kZSA9IG5vZGVzW25dOyAvLyBEZXRlcm1pbmUgd2hpY2ggY2x1c3RlciB0aGlzIG5vZGUgYmVsb25ncyB0bzogbm9kZSBpZCA9PiBjbHVzdGVyICNcblxuICAgICAgYXNzaWdubWVudFtub2RlLmlkKCldID0gY2xhc3NpZnkobm9kZSwgY2VudHJvaWRzLCBvcHRzLmRpc3RhbmNlLCBvcHRzLmF0dHJpYnV0ZXMsICdrTWVhbnMnKTtcbiAgICB9IC8vIFN0ZXAgMzogRm9yIGVhY2ggb2YgdGhlIGsgY2x1c3RlcnMsIHVwZGF0ZSBpdHMgY2VudHJvaWRcblxuXG4gICAgaXNTdGlsbE1vdmluZyA9IGZhbHNlO1xuXG4gICAgZm9yICh2YXIgYyA9IDA7IGMgPCBvcHRzLms7IGMrKykge1xuICAgICAgLy8gR2V0IGFsbCBub2RlcyB0aGF0IGJlbG9uZyB0byB0aGlzIGNsdXN0ZXJcbiAgICAgIHZhciBjbHVzdGVyID0gYnVpbGRDbHVzdGVyKGMsIG5vZGVzLCBhc3NpZ25tZW50KTtcblxuICAgICAgaWYgKGNsdXN0ZXIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIC8vIElmIGNsdXN0ZXIgaXMgZW1wdHksIGJyZWFrIG91dCBlYXJseSAmIG1vdmUgdG8gbmV4dCBjbHVzdGVyXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfSAvLyBVcGRhdGUgY2VudHJvaWRzIGJ5IGNhbGN1bGF0aW5nIGF2ZyBvZiBhbGwgbm9kZXMgd2l0aGluIHRoZSBjbHVzdGVyLlxuXG5cbiAgICAgIHZhciBuZGltID0gb3B0cy5hdHRyaWJ1dGVzLmxlbmd0aDtcbiAgICAgIHZhciBjZW50cm9pZCA9IGNlbnRyb2lkc1tjXTsgLy8gWyBkaW1fMSwgZGltXzIsIGRpbV8zLCAuLi4gLCBkaW1fbiBdXG5cbiAgICAgIHZhciBuZXdDZW50cm9pZCA9IG5ldyBBcnJheShuZGltKTtcbiAgICAgIHZhciBzdW0gPSBuZXcgQXJyYXkobmRpbSk7XG5cbiAgICAgIGZvciAodmFyIGQgPSAwOyBkIDwgbmRpbTsgZCsrKSB7XG4gICAgICAgIHN1bVtkXSA9IDAuMDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNsdXN0ZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBub2RlID0gY2x1c3RlcltpXTtcbiAgICAgICAgICBzdW1bZF0gKz0gb3B0cy5hdHRyaWJ1dGVzW2RdKG5vZGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgbmV3Q2VudHJvaWRbZF0gPSBzdW1bZF0gLyBjbHVzdGVyLmxlbmd0aDsgLy8gQ2hlY2sgdG8gc2VlIGlmIGFsZ29yaXRobSBoYXMgY29udmVyZ2VkLCBpLmUuIHdoZW4gY2VudHJvaWRzIG5vIGxvbmdlciBjaGFuZ2VcblxuICAgICAgICBpZiAoIWhhdmVWYWx1ZXNDb252ZXJnZWQobmV3Q2VudHJvaWRbZF0sIGNlbnRyb2lkW2RdLCBvcHRzLnNlbnNpdGl2aXR5VGhyZXNob2xkKSkge1xuICAgICAgICAgIGlzU3RpbGxNb3ZpbmcgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNlbnRyb2lkc1tjXSA9IG5ld0NlbnRyb2lkO1xuICAgICAgY2x1c3RlcnNbY10gPSBjeS5jb2xsZWN0aW9uKGNsdXN0ZXIpO1xuICAgIH1cblxuICAgIGl0ZXJhdGlvbnMrKztcbiAgfVxuXG4gIHJldHVybiBjbHVzdGVycztcbn07XG5cbnZhciBrTWVkb2lkcyA9IGZ1bmN0aW9uIGtNZWRvaWRzKG9wdGlvbnMpIHtcbiAgdmFyIGN5ID0gdGhpcy5jeSgpO1xuICB2YXIgbm9kZXMgPSB0aGlzLm5vZGVzKCk7XG4gIHZhciBub2RlID0gbnVsbDtcbiAgdmFyIG9wdHMgPSBzZXRPcHRpb25zJDEob3B0aW9ucyk7IC8vIEJlZ2luIGstbWVkb2lkcyBhbGdvcml0aG1cblxuICB2YXIgY2x1c3RlcnMgPSBuZXcgQXJyYXkob3B0cy5rKTtcbiAgdmFyIG1lZG9pZHM7XG4gIHZhciBhc3NpZ25tZW50ID0ge307XG4gIHZhciBjdXJDb3N0O1xuICB2YXIgbWluQ29zdHMgPSBuZXcgQXJyYXkob3B0cy5rKTsgLy8gbWluaW11bSBjb3N0IGNvbmZpZ3VyYXRpb24gZm9yIGVhY2ggY2x1c3RlclxuICAvLyBTdGVwIDE6IEluaXRpYWxpemUgayBtZWRvaWRzXG5cbiAgaWYgKG9wdHMudGVzdE1vZGUpIHtcbiAgICBpZiAodHlwZW9mIG9wdHMudGVzdENlbnRyb2lkcyA9PT0gJ251bWJlcicpIDsgZWxzZSBpZiAoX3R5cGVvZihvcHRzLnRlc3RDZW50cm9pZHMpID09PSAnb2JqZWN0Jykge1xuICAgICAgbWVkb2lkcyA9IG9wdHMudGVzdENlbnRyb2lkcztcbiAgICB9IGVsc2Uge1xuICAgICAgbWVkb2lkcyA9IHJhbmRvbU1lZG9pZHMobm9kZXMsIG9wdHMuayk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIG1lZG9pZHMgPSByYW5kb21NZWRvaWRzKG5vZGVzLCBvcHRzLmspO1xuICB9XG5cbiAgdmFyIGlzU3RpbGxNb3ZpbmcgPSB0cnVlO1xuICB2YXIgaXRlcmF0aW9ucyA9IDA7XG5cbiAgd2hpbGUgKGlzU3RpbGxNb3ZpbmcgJiYgaXRlcmF0aW9ucyA8IG9wdHMubWF4SXRlcmF0aW9ucykge1xuICAgIC8vIFN0ZXAgMjogQXNzaWduIG5vZGVzIHRvIHRoZSBuZWFyZXN0IG1lZG9pZFxuICAgIGZvciAodmFyIG4gPSAwOyBuIDwgbm9kZXMubGVuZ3RoOyBuKyspIHtcbiAgICAgIG5vZGUgPSBub2Rlc1tuXTsgLy8gRGV0ZXJtaW5lIHdoaWNoIGNsdXN0ZXIgdGhpcyBub2RlIGJlbG9uZ3MgdG86IG5vZGUgaWQgPT4gY2x1c3RlciAjXG5cbiAgICAgIGFzc2lnbm1lbnRbbm9kZS5pZCgpXSA9IGNsYXNzaWZ5KG5vZGUsIG1lZG9pZHMsIG9wdHMuZGlzdGFuY2UsIG9wdHMuYXR0cmlidXRlcywgJ2tNZWRvaWRzJyk7XG4gICAgfVxuXG4gICAgaXNTdGlsbE1vdmluZyA9IGZhbHNlOyAvLyBTdGVwIDM6IEZvciBlYWNoIG1lZG9pZCBtLCBhbmQgZm9yIGVhY2ggbm9kZSBhc3NjaWF0ZWQgd2l0aCBtZWRpb2QgbSxcbiAgICAvLyBzZWxlY3QgdGhlIG5vZGUgd2l0aCB0aGUgbG93ZXN0IGNvbmZpZ3VyYXRpb24gY29zdCBhcyBuZXcgbWVkb2lkLlxuXG4gICAgZm9yICh2YXIgbSA9IDA7IG0gPCBtZWRvaWRzLmxlbmd0aDsgbSsrKSB7XG4gICAgICAvLyBHZXQgYWxsIG5vZGVzIHRoYXQgYmVsb25nIHRvIHRoaXMgbWVkb2lkXG4gICAgICB2YXIgY2x1c3RlciA9IGJ1aWxkQ2x1c3RlcihtLCBub2RlcywgYXNzaWdubWVudCk7XG5cbiAgICAgIGlmIChjbHVzdGVyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAvLyBJZiBjbHVzdGVyIGlzIGVtcHR5LCBicmVhayBvdXQgZWFybHkgJiBtb3ZlIHRvIG5leHQgY2x1c3RlclxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgbWluQ29zdHNbbV0gPSBmaW5kQ29zdChtZWRvaWRzW21dLCBjbHVzdGVyLCBvcHRzLmF0dHJpYnV0ZXMpOyAvLyBvcmlnaW5hbCBjb3N0XG4gICAgICAvLyBTZWxlY3QgZGlmZmVyZW50IG1lZG9pZCBpZiBpdHMgY29uZmlndXJhdGlvbiBoYXMgdGhlIGxvd2VzdCBjb3N0XG5cbiAgICAgIGZvciAodmFyIF9uID0gMDsgX24gPCBjbHVzdGVyLmxlbmd0aDsgX24rKykge1xuICAgICAgICBjdXJDb3N0ID0gZmluZENvc3QoY2x1c3Rlcltfbl0sIGNsdXN0ZXIsIG9wdHMuYXR0cmlidXRlcyk7XG5cbiAgICAgICAgaWYgKGN1ckNvc3QgPCBtaW5Db3N0c1ttXSkge1xuICAgICAgICAgIG1pbkNvc3RzW21dID0gY3VyQ29zdDtcbiAgICAgICAgICBtZWRvaWRzW21dID0gY2x1c3Rlcltfbl07XG4gICAgICAgICAgaXNTdGlsbE1vdmluZyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY2x1c3RlcnNbbV0gPSBjeS5jb2xsZWN0aW9uKGNsdXN0ZXIpO1xuICAgIH1cblxuICAgIGl0ZXJhdGlvbnMrKztcbiAgfVxuXG4gIHJldHVybiBjbHVzdGVycztcbn07XG5cbnZhciB1cGRhdGVDZW50cm9pZHMgPSBmdW5jdGlvbiB1cGRhdGVDZW50cm9pZHMoY2VudHJvaWRzLCBub2RlcywgVSwgd2VpZ2h0LCBvcHRzKSB7XG4gIHZhciBudW1lcmF0b3IsIGRlbm9taW5hdG9yO1xuXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgbm9kZXMubGVuZ3RoOyBuKyspIHtcbiAgICBmb3IgKHZhciBjID0gMDsgYyA8IGNlbnRyb2lkcy5sZW5ndGg7IGMrKykge1xuICAgICAgd2VpZ2h0W25dW2NdID0gTWF0aC5wb3coVVtuXVtjXSwgb3B0cy5tKTtcbiAgICB9XG4gIH1cblxuICBmb3IgKHZhciBfYyA9IDA7IF9jIDwgY2VudHJvaWRzLmxlbmd0aDsgX2MrKykge1xuICAgIGZvciAodmFyIGRpbSA9IDA7IGRpbSA8IG9wdHMuYXR0cmlidXRlcy5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBudW1lcmF0b3IgPSAwO1xuICAgICAgZGVub21pbmF0b3IgPSAwO1xuXG4gICAgICBmb3IgKHZhciBfbjIgPSAwOyBfbjIgPCBub2Rlcy5sZW5ndGg7IF9uMisrKSB7XG4gICAgICAgIG51bWVyYXRvciArPSB3ZWlnaHRbX24yXVtfY10gKiBvcHRzLmF0dHJpYnV0ZXNbZGltXShub2Rlc1tfbjJdKTtcbiAgICAgICAgZGVub21pbmF0b3IgKz0gd2VpZ2h0W19uMl1bX2NdO1xuICAgICAgfVxuXG4gICAgICBjZW50cm9pZHNbX2NdW2RpbV0gPSBudW1lcmF0b3IgLyBkZW5vbWluYXRvcjtcbiAgICB9XG4gIH1cbn07XG5cbnZhciB1cGRhdGVNZW1iZXJzaGlwID0gZnVuY3Rpb24gdXBkYXRlTWVtYmVyc2hpcChVLCBfVSwgY2VudHJvaWRzLCBub2Rlcywgb3B0cykge1xuICAvLyBTYXZlIHByZXZpb3VzIHN0ZXBcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBVLmxlbmd0aDsgaSsrKSB7XG4gICAgX1VbaV0gPSBVW2ldLnNsaWNlKCk7XG4gIH1cblxuICB2YXIgc3VtLCBudW1lcmF0b3IsIGRlbm9taW5hdG9yO1xuICB2YXIgcG93ID0gMiAvIChvcHRzLm0gLSAxKTtcblxuICBmb3IgKHZhciBjID0gMDsgYyA8IGNlbnRyb2lkcy5sZW5ndGg7IGMrKykge1xuICAgIGZvciAodmFyIG4gPSAwOyBuIDwgbm9kZXMubGVuZ3RoOyBuKyspIHtcbiAgICAgIHN1bSA9IDA7XG5cbiAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgY2VudHJvaWRzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIC8vIGFnYWluc3QgYWxsIG90aGVyIGNlbnRyb2lkc1xuICAgICAgICBudW1lcmF0b3IgPSBnZXREaXN0KG9wdHMuZGlzdGFuY2UsIG5vZGVzW25dLCBjZW50cm9pZHNbY10sIG9wdHMuYXR0cmlidXRlcywgJ2NtZWFucycpO1xuICAgICAgICBkZW5vbWluYXRvciA9IGdldERpc3Qob3B0cy5kaXN0YW5jZSwgbm9kZXNbbl0sIGNlbnRyb2lkc1trXSwgb3B0cy5hdHRyaWJ1dGVzLCAnY21lYW5zJyk7XG4gICAgICAgIHN1bSArPSBNYXRoLnBvdyhudW1lcmF0b3IgLyBkZW5vbWluYXRvciwgcG93KTtcbiAgICAgIH1cblxuICAgICAgVVtuXVtjXSA9IDEgLyBzdW07XG4gICAgfVxuICB9XG59O1xuXG52YXIgYXNzaWduJDEgPSBmdW5jdGlvbiBhc3NpZ24obm9kZXMsIFUsIG9wdHMsIGN5KSB7XG4gIHZhciBjbHVzdGVycyA9IG5ldyBBcnJheShvcHRzLmspO1xuXG4gIGZvciAodmFyIGMgPSAwOyBjIDwgY2x1c3RlcnMubGVuZ3RoOyBjKyspIHtcbiAgICBjbHVzdGVyc1tjXSA9IFtdO1xuICB9XG5cbiAgdmFyIG1heDtcbiAgdmFyIGluZGV4O1xuXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgVS5sZW5ndGg7IG4rKykge1xuICAgIC8vIGZvciBlYWNoIG5vZGUgKFUgaXMgTiB4IEMgbWF0cml4KVxuICAgIG1heCA9IC1JbmZpbml0eTtcbiAgICBpbmRleCA9IC0xOyAvLyBEZXRlcm1pbmUgd2hpY2ggY2x1c3RlciB0aGUgbm9kZSBpcyBtb3N0IGxpa2VseSB0byBiZWxvbmcgaW5cblxuICAgIGZvciAodmFyIF9jMiA9IDA7IF9jMiA8IFVbMF0ubGVuZ3RoOyBfYzIrKykge1xuICAgICAgaWYgKFVbbl1bX2MyXSA+IG1heCkge1xuICAgICAgICBtYXggPSBVW25dW19jMl07XG4gICAgICAgIGluZGV4ID0gX2MyO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNsdXN0ZXJzW2luZGV4XS5wdXNoKG5vZGVzW25dKTtcbiAgfSAvLyBUdXJuIGV2ZXJ5IGFycmF5IGludG8gYSBjb2xsZWN0aW9uIG9mIG5vZGVzXG5cblxuICBmb3IgKHZhciBfYzMgPSAwOyBfYzMgPCBjbHVzdGVycy5sZW5ndGg7IF9jMysrKSB7XG4gICAgY2x1c3RlcnNbX2MzXSA9IGN5LmNvbGxlY3Rpb24oY2x1c3RlcnNbX2MzXSk7XG4gIH1cblxuICByZXR1cm4gY2x1c3RlcnM7XG59O1xuXG52YXIgZnV6enlDTWVhbnMgPSBmdW5jdGlvbiBmdXp6eUNNZWFucyhvcHRpb25zKSB7XG4gIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgdmFyIG5vZGVzID0gdGhpcy5ub2RlcygpO1xuICB2YXIgb3B0cyA9IHNldE9wdGlvbnMkMShvcHRpb25zKTsgLy8gQmVnaW4gZnV6enkgYy1tZWFucyBhbGdvcml0aG1cblxuICB2YXIgY2x1c3RlcnM7XG4gIHZhciBjZW50cm9pZHM7XG4gIHZhciBVO1xuXG4gIHZhciBfVTtcblxuICB2YXIgd2VpZ2h0OyAvLyBTdGVwIDE6IEluaXRpYWxpemUgbGV0aWFibGVzLlxuXG4gIF9VID0gbmV3IEFycmF5KG5vZGVzLmxlbmd0aCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIC8vIE4geCBDIG1hdHJpeFxuICAgIF9VW2ldID0gbmV3IEFycmF5KG9wdHMuayk7XG4gIH1cblxuICBVID0gbmV3IEFycmF5KG5vZGVzLmxlbmd0aCk7XG5cbiAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgbm9kZXMubGVuZ3RoOyBfaTMrKykge1xuICAgIC8vIE4geCBDIG1hdHJpeFxuICAgIFVbX2kzXSA9IG5ldyBBcnJheShvcHRzLmspO1xuICB9XG5cbiAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgbm9kZXMubGVuZ3RoOyBfaTQrKykge1xuICAgIHZhciB0b3RhbCA9IDA7XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG9wdHMuazsgaisrKSB7XG4gICAgICBVW19pNF1bal0gPSBNYXRoLnJhbmRvbSgpO1xuICAgICAgdG90YWwgKz0gVVtfaTRdW2pdO1xuICAgIH1cblxuICAgIGZvciAodmFyIF9qID0gMDsgX2ogPCBvcHRzLms7IF9qKyspIHtcbiAgICAgIFVbX2k0XVtfal0gPSBVW19pNF1bX2pdIC8gdG90YWw7XG4gICAgfVxuICB9XG5cbiAgY2VudHJvaWRzID0gbmV3IEFycmF5KG9wdHMuayk7XG5cbiAgZm9yICh2YXIgX2k1ID0gMDsgX2k1IDwgb3B0cy5rOyBfaTUrKykge1xuICAgIGNlbnRyb2lkc1tfaTVdID0gbmV3IEFycmF5KG9wdHMuYXR0cmlidXRlcy5sZW5ndGgpO1xuICB9XG5cbiAgd2VpZ2h0ID0gbmV3IEFycmF5KG5vZGVzLmxlbmd0aCk7XG5cbiAgZm9yICh2YXIgX2k2ID0gMDsgX2k2IDwgbm9kZXMubGVuZ3RoOyBfaTYrKykge1xuICAgIC8vIE4geCBDIG1hdHJpeFxuICAgIHdlaWdodFtfaTZdID0gbmV3IEFycmF5KG9wdHMuayk7XG4gIH0gLy8gZW5kIGluaXQgRkNNXG5cblxuICB2YXIgaXNTdGlsbE1vdmluZyA9IHRydWU7XG4gIHZhciBpdGVyYXRpb25zID0gMDtcblxuICB3aGlsZSAoaXNTdGlsbE1vdmluZyAmJiBpdGVyYXRpb25zIDwgb3B0cy5tYXhJdGVyYXRpb25zKSB7XG4gICAgaXNTdGlsbE1vdmluZyA9IGZhbHNlOyAvLyBTdGVwIDI6IENhbGN1bGF0ZSB0aGUgY2VudHJvaWRzIGZvciBlYWNoIHN0ZXAuXG5cbiAgICB1cGRhdGVDZW50cm9pZHMoY2VudHJvaWRzLCBub2RlcywgVSwgd2VpZ2h0LCBvcHRzKTsgLy8gU3RlcCAzOiBVcGRhdGUgdGhlIHBhcnRpdGlvbiBtYXRyaXggVS5cblxuICAgIHVwZGF0ZU1lbWJlcnNoaXAoVSwgX1UsIGNlbnRyb2lkcywgbm9kZXMsIG9wdHMpOyAvLyBTdGVwIDQ6IENoZWNrIGZvciBjb252ZXJnZW5jZS5cblxuICAgIGlmICghaGF2ZU1hdHJpY2VzQ29udmVyZ2VkKFUsIF9VLCBvcHRzLnNlbnNpdGl2aXR5VGhyZXNob2xkKSkge1xuICAgICAgaXNTdGlsbE1vdmluZyA9IHRydWU7XG4gICAgfVxuXG4gICAgaXRlcmF0aW9ucysrO1xuICB9IC8vIEFzc2lnbiBub2RlcyB0byBjbHVzdGVycyB3aXRoIGhpZ2hlc3QgcHJvYmFiaWxpdHkuXG5cblxuICBjbHVzdGVycyA9IGFzc2lnbiQxKG5vZGVzLCBVLCBvcHRzLCBjeSk7XG4gIHJldHVybiB7XG4gICAgY2x1c3RlcnM6IGNsdXN0ZXJzLFxuICAgIGRlZ3JlZU9mTWVtYmVyc2hpcDogVVxuICB9O1xufTtcblxudmFyIGtDbHVzdGVyaW5nID0ge1xuICBrTWVhbnM6IGtNZWFucyxcbiAga01lZG9pZHM6IGtNZWRvaWRzLFxuICBmdXp6eUNNZWFuczogZnV6enlDTWVhbnMsXG4gIGZjbTogZnV6enlDTWVhbnNcbn07XG5cbi8vIEltcGxlbWVudGVkIGJ5IFpvZSBYaSBAem9leGkgZm9yIEdTT0MgMjAxNlxudmFyIGRlZmF1bHRzJDYgPSBkZWZhdWx0cyh7XG4gIGRpc3RhbmNlOiAnZXVjbGlkZWFuJyxcbiAgLy8gZGlzdGFuY2UgbWV0cmljIHRvIGNvbXBhcmUgbm9kZXNcbiAgbGlua2FnZTogJ21pbicsXG4gIC8vIGxpbmthZ2UgY3JpdGVyaW9uIDogaG93IHRvIGRldGVybWluZSB0aGUgZGlzdGFuY2UgYmV0d2VlbiBjbHVzdGVycyBvZiBub2Rlc1xuICBtb2RlOiAndGhyZXNob2xkJyxcbiAgLy8gbW9kZTondGhyZXNob2xkJyA9PiBjbHVzdGVycyBtdXN0IGJlIHRocmVzaG9sZCBkaXN0YW5jZSBhcGFydFxuICB0aHJlc2hvbGQ6IEluZmluaXR5LFxuICAvLyB0aGUgZGlzdGFuY2UgdGhyZXNob2xkXG4gIC8vIG1vZGU6J2RlbmRyb2dyYW0nID0+IHRoZSBub2RlcyBhcmUgb3JnYW5pc2VkIGFzIGxlYXZlcyBpbiBhIHRyZWUgKHNpYmxpbmdzIGFyZSBjbG9zZSksIG1lcmdpbmcgbWFrZXMgY2x1c3RlcnNcbiAgYWRkRGVuZHJvZ3JhbTogZmFsc2UsXG4gIC8vIHdoZXRoZXIgdG8gYWRkIHRoZSBkZW5kcm9ncmFtIHRvIHRoZSBncmFwaCBmb3Igdml6XG4gIGRlbmRyb2dyYW1EZXB0aDogMCxcbiAgLy8gZGVwdGggYXQgd2hpY2ggZGVuZHJvZ3JhbSBicmFuY2hlcyBhcmUgbWVyZ2VkIGludG8gdGhlIHJldHVybmVkIGNsdXN0ZXJzXG4gIGF0dHJpYnV0ZXM6IFtdIC8vIGFycmF5IG9mIGF0dHIgZnVuY3Rpb25zXG5cbn0pO1xudmFyIGxpbmthZ2VBbGlhc2VzID0ge1xuICAnc2luZ2xlJzogJ21pbicsXG4gICdjb21wbGV0ZSc6ICdtYXgnXG59O1xuXG52YXIgc2V0T3B0aW9ucyQyID0gZnVuY3Rpb24gc2V0T3B0aW9ucyhvcHRpb25zKSB7XG4gIHZhciBvcHRzID0gZGVmYXVsdHMkNihvcHRpb25zKTtcbiAgdmFyIHByZWZlcnJlZEFsaWFzID0gbGlua2FnZUFsaWFzZXNbb3B0cy5saW5rYWdlXTtcblxuICBpZiAocHJlZmVycmVkQWxpYXMgIT0gbnVsbCkge1xuICAgIG9wdHMubGlua2FnZSA9IHByZWZlcnJlZEFsaWFzO1xuICB9XG5cbiAgcmV0dXJuIG9wdHM7XG59O1xuXG52YXIgbWVyZ2VDbG9zZXN0ID0gZnVuY3Rpb24gbWVyZ2VDbG9zZXN0KGNsdXN0ZXJzLCBpbmRleCwgZGlzdHMsIG1pbnMsIG9wdHMpIHtcbiAgLy8gRmluZCB0d28gY2xvc2VzdCBjbHVzdGVycyBmcm9tIGNhY2hlZCBtaW5zXG4gIHZhciBtaW5LZXkgPSAwO1xuICB2YXIgbWluID0gSW5maW5pdHk7XG4gIHZhciBkaXN0O1xuICB2YXIgYXR0cnMgPSBvcHRzLmF0dHJpYnV0ZXM7XG5cbiAgdmFyIGdldERpc3QgPSBmdW5jdGlvbiBnZXREaXN0KG4xLCBuMikge1xuICAgIHJldHVybiBjbHVzdGVyaW5nRGlzdGFuY2Uob3B0cy5kaXN0YW5jZSwgYXR0cnMubGVuZ3RoLCBmdW5jdGlvbiAoaSkge1xuICAgICAgcmV0dXJuIGF0dHJzW2ldKG4xKTtcbiAgICB9LCBmdW5jdGlvbiAoaSkge1xuICAgICAgcmV0dXJuIGF0dHJzW2ldKG4yKTtcbiAgICB9LCBuMSwgbjIpO1xuICB9O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2x1c3RlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIga2V5ID0gY2x1c3RlcnNbaV0ua2V5O1xuICAgIHZhciBfZGlzdCA9IGRpc3RzW2tleV1bbWluc1trZXldXTtcblxuICAgIGlmIChfZGlzdCA8IG1pbikge1xuICAgICAgbWluS2V5ID0ga2V5O1xuICAgICAgbWluID0gX2Rpc3Q7XG4gICAgfVxuICB9XG5cbiAgaWYgKG9wdHMubW9kZSA9PT0gJ3RocmVzaG9sZCcgJiYgbWluID49IG9wdHMudGhyZXNob2xkIHx8IG9wdHMubW9kZSA9PT0gJ2RlbmRyb2dyYW0nICYmIGNsdXN0ZXJzLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciBjMSA9IGluZGV4W21pbktleV07XG4gIHZhciBjMiA9IGluZGV4W21pbnNbbWluS2V5XV07XG4gIHZhciBtZXJnZWQ7IC8vIE1lcmdlIHR3byBjbG9zZXN0IGNsdXN0ZXJzXG5cbiAgaWYgKG9wdHMubW9kZSA9PT0gJ2RlbmRyb2dyYW0nKSB7XG4gICAgbWVyZ2VkID0ge1xuICAgICAgbGVmdDogYzEsXG4gICAgICByaWdodDogYzIsXG4gICAgICBrZXk6IGMxLmtleVxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgbWVyZ2VkID0ge1xuICAgICAgdmFsdWU6IGMxLnZhbHVlLmNvbmNhdChjMi52YWx1ZSksXG4gICAgICBrZXk6IGMxLmtleVxuICAgIH07XG4gIH1cblxuICBjbHVzdGVyc1tjMS5pbmRleF0gPSBtZXJnZWQ7XG4gIGNsdXN0ZXJzLnNwbGljZShjMi5pbmRleCwgMSk7XG4gIGluZGV4W2MxLmtleV0gPSBtZXJnZWQ7IC8vIFVwZGF0ZSBkaXN0YW5jZXMgd2l0aCBuZXcgbWVyZ2VkIGNsdXN0ZXJcblxuICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgY2x1c3RlcnMubGVuZ3RoOyBfaSsrKSB7XG4gICAgdmFyIGN1ciA9IGNsdXN0ZXJzW19pXTtcblxuICAgIGlmIChjMS5rZXkgPT09IGN1ci5rZXkpIHtcbiAgICAgIGRpc3QgPSBJbmZpbml0eTtcbiAgICB9IGVsc2UgaWYgKG9wdHMubGlua2FnZSA9PT0gJ21pbicpIHtcbiAgICAgIGRpc3QgPSBkaXN0c1tjMS5rZXldW2N1ci5rZXldO1xuXG4gICAgICBpZiAoZGlzdHNbYzEua2V5XVtjdXIua2V5XSA+IGRpc3RzW2MyLmtleV1bY3VyLmtleV0pIHtcbiAgICAgICAgZGlzdCA9IGRpc3RzW2MyLmtleV1bY3VyLmtleV07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChvcHRzLmxpbmthZ2UgPT09ICdtYXgnKSB7XG4gICAgICBkaXN0ID0gZGlzdHNbYzEua2V5XVtjdXIua2V5XTtcblxuICAgICAgaWYgKGRpc3RzW2MxLmtleV1bY3VyLmtleV0gPCBkaXN0c1tjMi5rZXldW2N1ci5rZXldKSB7XG4gICAgICAgIGRpc3QgPSBkaXN0c1tjMi5rZXldW2N1ci5rZXldO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0cy5saW5rYWdlID09PSAnbWVhbicpIHtcbiAgICAgIGRpc3QgPSAoZGlzdHNbYzEua2V5XVtjdXIua2V5XSAqIGMxLnNpemUgKyBkaXN0c1tjMi5rZXldW2N1ci5rZXldICogYzIuc2l6ZSkgLyAoYzEuc2l6ZSArIGMyLnNpemUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAob3B0cy5tb2RlID09PSAnZGVuZHJvZ3JhbScpIGRpc3QgPSBnZXREaXN0KGN1ci52YWx1ZSwgYzEudmFsdWUpO2Vsc2UgZGlzdCA9IGdldERpc3QoY3VyLnZhbHVlWzBdLCBjMS52YWx1ZVswXSk7XG4gICAgfVxuXG4gICAgZGlzdHNbYzEua2V5XVtjdXIua2V5XSA9IGRpc3RzW2N1ci5rZXldW2MxLmtleV0gPSBkaXN0OyAvLyBkaXN0YW5jZSBtYXRyaXggaXMgc3ltbWV0cmljXG4gIH0gLy8gVXBkYXRlIGNhY2hlZCBtaW5zXG5cblxuICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBjbHVzdGVycy5sZW5ndGg7IF9pMisrKSB7XG4gICAgdmFyIGtleTEgPSBjbHVzdGVyc1tfaTJdLmtleTtcblxuICAgIGlmIChtaW5zW2tleTFdID09PSBjMS5rZXkgfHwgbWluc1trZXkxXSA9PT0gYzIua2V5KSB7XG4gICAgICB2YXIgX21pbiA9IGtleTE7XG5cbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgY2x1c3RlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIGtleTIgPSBjbHVzdGVyc1tqXS5rZXk7XG5cbiAgICAgICAgaWYgKGRpc3RzW2tleTFdW2tleTJdIDwgZGlzdHNba2V5MV1bX21pbl0pIHtcbiAgICAgICAgICBfbWluID0ga2V5MjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBtaW5zW2tleTFdID0gX21pbjtcbiAgICB9XG5cbiAgICBjbHVzdGVyc1tfaTJdLmluZGV4ID0gX2kyO1xuICB9IC8vIENsZWFuIHVwIG1ldGEgZGF0YSB1c2VkIGZvciBjbHVzdGVyaW5nXG5cblxuICBjMS5rZXkgPSBjMi5rZXkgPSBjMS5pbmRleCA9IGMyLmluZGV4ID0gbnVsbDtcbiAgcmV0dXJuIHRydWU7XG59O1xuXG52YXIgZ2V0QWxsQ2hpbGRyZW4gPSBmdW5jdGlvbiBnZXRBbGxDaGlsZHJlbihyb290LCBhcnIsIGN5KSB7XG4gIGlmICghcm9vdCkgcmV0dXJuO1xuXG4gIGlmIChyb290LnZhbHVlKSB7XG4gICAgYXJyLnB1c2gocm9vdC52YWx1ZSk7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHJvb3QubGVmdCkgZ2V0QWxsQ2hpbGRyZW4ocm9vdC5sZWZ0LCBhcnIpO1xuICAgIGlmIChyb290LnJpZ2h0KSBnZXRBbGxDaGlsZHJlbihyb290LnJpZ2h0LCBhcnIpO1xuICB9XG59O1xuXG52YXIgYnVpbGREZW5kcm9ncmFtID0gZnVuY3Rpb24gYnVpbGREZW5kcm9ncmFtKHJvb3QsIGN5KSB7XG4gIGlmICghcm9vdCkgcmV0dXJuICcnO1xuXG4gIGlmIChyb290LmxlZnQgJiYgcm9vdC5yaWdodCkge1xuICAgIHZhciBsZWZ0U3RyID0gYnVpbGREZW5kcm9ncmFtKHJvb3QubGVmdCwgY3kpO1xuICAgIHZhciByaWdodFN0ciA9IGJ1aWxkRGVuZHJvZ3JhbShyb290LnJpZ2h0LCBjeSk7XG4gICAgdmFyIG5vZGUgPSBjeS5hZGQoe1xuICAgICAgZ3JvdXA6ICdub2RlcycsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIGlkOiBsZWZ0U3RyICsgJywnICsgcmlnaHRTdHJcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjeS5hZGQoe1xuICAgICAgZ3JvdXA6ICdlZGdlcycsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIHNvdXJjZTogbGVmdFN0cixcbiAgICAgICAgdGFyZ2V0OiBub2RlLmlkKClcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjeS5hZGQoe1xuICAgICAgZ3JvdXA6ICdlZGdlcycsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIHNvdXJjZTogcmlnaHRTdHIsXG4gICAgICAgIHRhcmdldDogbm9kZS5pZCgpXG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG5vZGUuaWQoKTtcbiAgfSBlbHNlIGlmIChyb290LnZhbHVlKSB7XG4gICAgcmV0dXJuIHJvb3QudmFsdWUuaWQoKTtcbiAgfVxufTtcblxudmFyIGJ1aWxkQ2x1c3RlcnNGcm9tVHJlZSA9IGZ1bmN0aW9uIGJ1aWxkQ2x1c3RlcnNGcm9tVHJlZShyb290LCBrLCBjeSkge1xuICBpZiAoIXJvb3QpIHJldHVybiBbXTtcbiAgdmFyIGxlZnQgPSBbXSxcbiAgICAgIHJpZ2h0ID0gW10sXG4gICAgICBsZWF2ZXMgPSBbXTtcblxuICBpZiAoayA9PT0gMCkge1xuICAgIC8vIGRvbid0IGN1dCB0cmVlLCBzaW1wbHkgcmV0dXJuIGFsbCBub2RlcyBhcyAxIHNpbmdsZSBjbHVzdGVyXG4gICAgaWYgKHJvb3QubGVmdCkgZ2V0QWxsQ2hpbGRyZW4ocm9vdC5sZWZ0LCBsZWZ0KTtcbiAgICBpZiAocm9vdC5yaWdodCkgZ2V0QWxsQ2hpbGRyZW4ocm9vdC5yaWdodCwgcmlnaHQpO1xuICAgIGxlYXZlcyA9IGxlZnQuY29uY2F0KHJpZ2h0KTtcbiAgICByZXR1cm4gW2N5LmNvbGxlY3Rpb24obGVhdmVzKV07XG4gIH0gZWxzZSBpZiAoayA9PT0gMSkge1xuICAgIC8vIGN1dCBhdCByb290XG4gICAgaWYgKHJvb3QudmFsdWUpIHtcbiAgICAgIC8vIGxlYWYgbm9kZVxuICAgICAgcmV0dXJuIFtjeS5jb2xsZWN0aW9uKHJvb3QudmFsdWUpXTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHJvb3QubGVmdCkgZ2V0QWxsQ2hpbGRyZW4ocm9vdC5sZWZ0LCBsZWZ0KTtcbiAgICAgIGlmIChyb290LnJpZ2h0KSBnZXRBbGxDaGlsZHJlbihyb290LnJpZ2h0LCByaWdodCk7XG4gICAgICByZXR1cm4gW2N5LmNvbGxlY3Rpb24obGVmdCksIGN5LmNvbGxlY3Rpb24ocmlnaHQpXTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKHJvb3QudmFsdWUpIHtcbiAgICAgIHJldHVybiBbY3kuY29sbGVjdGlvbihyb290LnZhbHVlKV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChyb290LmxlZnQpIGxlZnQgPSBidWlsZENsdXN0ZXJzRnJvbVRyZWUocm9vdC5sZWZ0LCBrIC0gMSwgY3kpO1xuICAgICAgaWYgKHJvb3QucmlnaHQpIHJpZ2h0ID0gYnVpbGRDbHVzdGVyc0Zyb21UcmVlKHJvb3QucmlnaHQsIGsgLSAxLCBjeSk7XG4gICAgICByZXR1cm4gbGVmdC5jb25jYXQocmlnaHQpO1xuICAgIH1cbiAgfVxufTtcbi8qIGVzbGludC1lbmFibGUgKi9cblxuXG52YXIgaGllcmFyY2hpY2FsQ2x1c3RlcmluZyA9IGZ1bmN0aW9uIGhpZXJhcmNoaWNhbENsdXN0ZXJpbmcob3B0aW9ucykge1xuICB2YXIgY3kgPSB0aGlzLmN5KCk7XG4gIHZhciBub2RlcyA9IHRoaXMubm9kZXMoKTsgLy8gU2V0IHBhcmFtZXRlcnMgb2YgYWxnb3JpdGhtOiBsaW5rYWdlIHR5cGUsIGRpc3RhbmNlIG1ldHJpYywgZXRjLlxuXG4gIHZhciBvcHRzID0gc2V0T3B0aW9ucyQyKG9wdGlvbnMpO1xuICB2YXIgYXR0cnMgPSBvcHRzLmF0dHJpYnV0ZXM7XG5cbiAgdmFyIGdldERpc3QgPSBmdW5jdGlvbiBnZXREaXN0KG4xLCBuMikge1xuICAgIHJldHVybiBjbHVzdGVyaW5nRGlzdGFuY2Uob3B0cy5kaXN0YW5jZSwgYXR0cnMubGVuZ3RoLCBmdW5jdGlvbiAoaSkge1xuICAgICAgcmV0dXJuIGF0dHJzW2ldKG4xKTtcbiAgICB9LCBmdW5jdGlvbiAoaSkge1xuICAgICAgcmV0dXJuIGF0dHJzW2ldKG4yKTtcbiAgICB9LCBuMSwgbjIpO1xuICB9OyAvLyBCZWdpbiBoaWVyYXJjaGljYWwgYWxnb3JpdGhtXG5cblxuICB2YXIgY2x1c3RlcnMgPSBbXTtcbiAgdmFyIGRpc3RzID0gW107IC8vIGRpc3RhbmNlcyBiZXR3ZWVuIGVhY2ggcGFpciBvZiBjbHVzdGVyc1xuXG4gIHZhciBtaW5zID0gW107IC8vIGNsb3Nlc3QgY2x1c3RlciBmb3IgZWFjaCBjbHVzdGVyXG5cbiAgdmFyIGluZGV4ID0gW107IC8vIGhhc2ggb2YgYWxsIGNsdXN0ZXJzIGJ5IGtleVxuICAvLyBJbiBhZ2dsb21lcmF0aXZlIChib3R0b20tdXApIGNsdXN0ZXJpbmcsIGVhY2ggbm9kZSBzdGFydHMgYXMgaXRzIG93biBjbHVzdGVyXG5cbiAgZm9yICh2YXIgbiA9IDA7IG4gPCBub2Rlcy5sZW5ndGg7IG4rKykge1xuICAgIHZhciBjbHVzdGVyID0ge1xuICAgICAgdmFsdWU6IG9wdHMubW9kZSA9PT0gJ2RlbmRyb2dyYW0nID8gbm9kZXNbbl0gOiBbbm9kZXNbbl1dLFxuICAgICAga2V5OiBuLFxuICAgICAgaW5kZXg6IG5cbiAgICB9O1xuICAgIGNsdXN0ZXJzW25dID0gY2x1c3RlcjtcbiAgICBpbmRleFtuXSA9IGNsdXN0ZXI7XG4gICAgZGlzdHNbbl0gPSBbXTtcbiAgICBtaW5zW25dID0gMDtcbiAgfSAvLyBDYWxjdWxhdGUgdGhlIGRpc3RhbmNlIGJldHdlZW4gZWFjaCBwYWlyIG9mIGNsdXN0ZXJzXG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNsdXN0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgZm9yICh2YXIgaiA9IDA7IGogPD0gaTsgaisrKSB7XG4gICAgICB2YXIgZGlzdCA9IHZvaWQgMDtcblxuICAgICAgaWYgKG9wdHMubW9kZSA9PT0gJ2RlbmRyb2dyYW0nKSB7XG4gICAgICAgIC8vIG1vZGVzIHN0b3JlIGNsdXN0ZXIgdmFsdWVzIGRpZmZlcmVudGx5XG4gICAgICAgIGRpc3QgPSBpID09PSBqID8gSW5maW5pdHkgOiBnZXREaXN0KGNsdXN0ZXJzW2ldLnZhbHVlLCBjbHVzdGVyc1tqXS52YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkaXN0ID0gaSA9PT0gaiA/IEluZmluaXR5IDogZ2V0RGlzdChjbHVzdGVyc1tpXS52YWx1ZVswXSwgY2x1c3RlcnNbal0udmFsdWVbMF0pO1xuICAgICAgfVxuXG4gICAgICBkaXN0c1tpXVtqXSA9IGRpc3Q7XG4gICAgICBkaXN0c1tqXVtpXSA9IGRpc3Q7XG5cbiAgICAgIGlmIChkaXN0IDwgZGlzdHNbaV1bbWluc1tpXV0pIHtcbiAgICAgICAgbWluc1tpXSA9IGo7IC8vIENhY2hlIG1pbnM6IGNsb3Nlc3QgY2x1c3RlciB0byBjbHVzdGVyIGkgaXMgY2x1c3RlciBqXG4gICAgICB9XG4gICAgfVxuICB9IC8vIEZpbmQgdGhlIGNsb3Nlc3QgcGFpciBvZiBjbHVzdGVycyBhbmQgbWVyZ2UgdGhlbSBpbnRvIGEgc2luZ2xlIGNsdXN0ZXIuXG4gIC8vIFVwZGF0ZSBkaXN0YW5jZXMgYmV0d2VlbiBuZXcgY2x1c3RlciBhbmQgZWFjaCBvZiB0aGUgb2xkIGNsdXN0ZXJzLCBhbmQgbG9vcCB1bnRpbCB0aHJlc2hvbGQgcmVhY2hlZC5cblxuXG4gIHZhciBtZXJnZWQgPSBtZXJnZUNsb3Nlc3QoY2x1c3RlcnMsIGluZGV4LCBkaXN0cywgbWlucywgb3B0cyk7XG5cbiAgd2hpbGUgKG1lcmdlZCkge1xuICAgIG1lcmdlZCA9IG1lcmdlQ2xvc2VzdChjbHVzdGVycywgaW5kZXgsIGRpc3RzLCBtaW5zLCBvcHRzKTtcbiAgfVxuXG4gIHZhciByZXRDbHVzdGVyczsgLy8gRGVuZHJvZ3JhbSBtb2RlIGJ1aWxkcyB0aGUgaGllcmFyY2h5IGFuZCBhZGRzIGludGVybWVkaWFyeSBub2RlcyArIGVkZ2VzXG4gIC8vIGluIGFkZGl0aW9uIHRvIHJldHVybmluZyB0aGUgY2x1c3RlcnMuXG5cbiAgaWYgKG9wdHMubW9kZSA9PT0gJ2RlbmRyb2dyYW0nKSB7XG4gICAgcmV0Q2x1c3RlcnMgPSBidWlsZENsdXN0ZXJzRnJvbVRyZWUoY2x1c3RlcnNbMF0sIG9wdHMuZGVuZHJvZ3JhbURlcHRoLCBjeSk7XG4gICAgaWYgKG9wdHMuYWRkRGVuZHJvZ3JhbSkgYnVpbGREZW5kcm9ncmFtKGNsdXN0ZXJzWzBdLCBjeSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gUmVndWxhciBtb2RlIHNpbXBseSByZXR1cm5zIHRoZSBjbHVzdGVyc1xuICAgIHJldENsdXN0ZXJzID0gbmV3IEFycmF5KGNsdXN0ZXJzLmxlbmd0aCk7XG4gICAgY2x1c3RlcnMuZm9yRWFjaChmdW5jdGlvbiAoY2x1c3RlciwgaSkge1xuICAgICAgLy8gQ2xlYW4gdXAgbWV0YSBkYXRhIHVzZWQgZm9yIGNsdXN0ZXJpbmdcbiAgICAgIGNsdXN0ZXIua2V5ID0gY2x1c3Rlci5pbmRleCA9IG51bGw7XG4gICAgICByZXRDbHVzdGVyc1tpXSA9IGN5LmNvbGxlY3Rpb24oY2x1c3Rlci52YWx1ZSk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcmV0Q2x1c3RlcnM7XG59O1xuXG52YXIgaGllcmFyY2hpY2FsQ2x1c3RlcmluZyQxID0ge1xuICBoaWVyYXJjaGljYWxDbHVzdGVyaW5nOiBoaWVyYXJjaGljYWxDbHVzdGVyaW5nLFxuICBoY2E6IGhpZXJhcmNoaWNhbENsdXN0ZXJpbmdcbn07XG5cbi8vIEltcGxlbWVudGVkIGJ5IFpvZSBYaSBAem9leGkgZm9yIEdTT0MgMjAxNlxudmFyIGRlZmF1bHRzJDcgPSBkZWZhdWx0cyh7XG4gIGRpc3RhbmNlOiAnZXVjbGlkZWFuJyxcbiAgLy8gZGlzdGFuY2UgbWV0cmljIHRvIGNvbXBhcmUgYXR0cmlidXRlcyBiZXR3ZWVuIHR3byBub2Rlc1xuICBwcmVmZXJlbmNlOiAnbWVkaWFuJyxcbiAgLy8gc3VpdGFiaWxpdHkgb2YgYSBkYXRhIHBvaW50IHRvIHNlcnZlIGFzIGFuIGV4ZW1wbGFyXG4gIGRhbXBpbmc6IDAuOCxcbiAgLy8gZGFtcGluZyBmYWN0b3IgYmV0d2VlbiBbMC41LCAxKVxuICBtYXhJdGVyYXRpb25zOiAxMDAwLFxuICAvLyBtYXggbnVtYmVyIG9mIGl0ZXJhdGlvbnMgdG8gcnVuXG4gIG1pbkl0ZXJhdGlvbnM6IDEwMCxcbiAgLy8gbWluIG51bWJlciBvZiBpdGVyYXRpb25zIHRvIHJ1biBpbiBvcmRlciBmb3IgY2x1c3RlcmluZyB0byBzdG9wXG4gIGF0dHJpYnV0ZXM6IFsvLyBmdW5jdGlvbnMgdG8gcXVhbnRpZnkgdGhlIHNpbWlsYXJpdHkgYmV0d2VlbiBhbnkgdHdvIHBvaW50c1xuICAgIC8vIGUuZy4gbm9kZSA9PiBub2RlLmRhdGEoJ3dlaWdodCcpXG4gIF1cbn0pO1xuXG52YXIgc2V0T3B0aW9ucyQzID0gZnVuY3Rpb24gc2V0T3B0aW9ucyhvcHRpb25zKSB7XG4gIHZhciBkbXAgPSBvcHRpb25zLmRhbXBpbmc7XG4gIHZhciBwcmVmID0gb3B0aW9ucy5wcmVmZXJlbmNlO1xuXG4gIGlmICghKDAuNSA8PSBkbXAgJiYgZG1wIDwgMSkpIHtcbiAgICBlcnJvcihcIkRhbXBpbmcgbXVzdCByYW5nZSBvbiBbMC41LCAxKS4gIEdvdDogXCIuY29uY2F0KGRtcCkpO1xuICB9XG5cbiAgdmFyIHZhbGlkUHJlZnMgPSBbJ21lZGlhbicsICdtZWFuJywgJ21pbicsICdtYXgnXTtcblxuICBpZiAoISh2YWxpZFByZWZzLnNvbWUoZnVuY3Rpb24gKHYpIHtcbiAgICByZXR1cm4gdiA9PT0gcHJlZjtcbiAgfSkgfHwgbnVtYmVyKHByZWYpKSkge1xuICAgIGVycm9yKFwiUHJlZmVyZW5jZSBtdXN0IGJlIG9uZSBvZiBbXCIuY29uY2F0KHZhbGlkUHJlZnMubWFwKGZ1bmN0aW9uIChwKSB7XG4gICAgICByZXR1cm4gXCInXCIuY29uY2F0KHAsIFwiJ1wiKTtcbiAgICB9KS5qb2luKCcsICcpLCBcIl0gb3IgYSBudW1iZXIuICBHb3Q6IFwiKS5jb25jYXQocHJlZikpO1xuICB9XG5cbiAgcmV0dXJuIGRlZmF1bHRzJDcob3B0aW9ucyk7XG59O1xuLyogZXNsaW50LWVuYWJsZSAqL1xuXG5cbnZhciBnZXRTaW1pbGFyaXR5JDEgPSBmdW5jdGlvbiBnZXRTaW1pbGFyaXR5KHR5cGUsIG4xLCBuMiwgYXR0cmlidXRlcykge1xuICB2YXIgYXR0ciA9IGZ1bmN0aW9uIGF0dHIobiwgaSkge1xuICAgIHJldHVybiBhdHRyaWJ1dGVzW2ldKG4pO1xuICB9OyAvLyBuYiBuZWdhdGl2ZSBiZWNhdXNlIHNpbWlsYXJpdHkgc2hvdWxkIGhhdmUgYW4gaW52ZXJzZSByZWxhdGlvbnNoaXAgdG8gZGlzdGFuY2VcblxuXG4gIHJldHVybiAtY2x1c3RlcmluZ0Rpc3RhbmNlKHR5cGUsIGF0dHJpYnV0ZXMubGVuZ3RoLCBmdW5jdGlvbiAoaSkge1xuICAgIHJldHVybiBhdHRyKG4xLCBpKTtcbiAgfSwgZnVuY3Rpb24gKGkpIHtcbiAgICByZXR1cm4gYXR0cihuMiwgaSk7XG4gIH0sIG4xLCBuMik7XG59O1xuXG52YXIgZ2V0UHJlZmVyZW5jZSA9IGZ1bmN0aW9uIGdldFByZWZlcmVuY2UoUywgcHJlZmVyZW5jZSkge1xuICAvLyBsYXJnZXIgcHJlZmVyZW5jZSA9IGdyZWF0ZXIgIyBvZiBjbHVzdGVyc1xuICB2YXIgcCA9IG51bGw7XG5cbiAgaWYgKHByZWZlcmVuY2UgPT09ICdtZWRpYW4nKSB7XG4gICAgcCA9IG1lZGlhbihTKTtcbiAgfSBlbHNlIGlmIChwcmVmZXJlbmNlID09PSAnbWVhbicpIHtcbiAgICBwID0gbWVhbihTKTtcbiAgfSBlbHNlIGlmIChwcmVmZXJlbmNlID09PSAnbWluJykge1xuICAgIHAgPSBtaW4oUyk7XG4gIH0gZWxzZSBpZiAocHJlZmVyZW5jZSA9PT0gJ21heCcpIHtcbiAgICBwID0gbWF4KFMpO1xuICB9IGVsc2Uge1xuICAgIC8vIEN1c3RvbSBwcmVmZXJlbmNlIG51bWJlciwgYXMgc2V0IGJ5IHVzZXJcbiAgICBwID0gcHJlZmVyZW5jZTtcbiAgfVxuXG4gIHJldHVybiBwO1xufTtcblxudmFyIGZpbmRFeGVtcGxhcnMgPSBmdW5jdGlvbiBmaW5kRXhlbXBsYXJzKG4sIFIsIEEpIHtcbiAgdmFyIGluZGljZXMgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIGlmIChSW2kgKiBuICsgaV0gKyBBW2kgKiBuICsgaV0gPiAwKSB7XG4gICAgICBpbmRpY2VzLnB1c2goaSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGluZGljZXM7XG59O1xuXG52YXIgYXNzaWduQ2x1c3RlcnMgPSBmdW5jdGlvbiBhc3NpZ25DbHVzdGVycyhuLCBTLCBleGVtcGxhcnMpIHtcbiAgdmFyIGNsdXN0ZXJzID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICB2YXIgaW5kZXggPSAtMTtcbiAgICB2YXIgbWF4ID0gLUluZmluaXR5O1xuXG4gICAgZm9yICh2YXIgZWkgPSAwOyBlaSA8IGV4ZW1wbGFycy5sZW5ndGg7IGVpKyspIHtcbiAgICAgIHZhciBlID0gZXhlbXBsYXJzW2VpXTtcblxuICAgICAgaWYgKFNbaSAqIG4gKyBlXSA+IG1heCkge1xuICAgICAgICBpbmRleCA9IGU7XG4gICAgICAgIG1heCA9IFNbaSAqIG4gKyBlXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaW5kZXggPiAwKSB7XG4gICAgICBjbHVzdGVycy5wdXNoKGluZGV4KTtcbiAgICB9XG4gIH1cblxuICBmb3IgKHZhciBfZWkgPSAwOyBfZWkgPCBleGVtcGxhcnMubGVuZ3RoOyBfZWkrKykge1xuICAgIGNsdXN0ZXJzW2V4ZW1wbGFyc1tfZWldXSA9IGV4ZW1wbGFyc1tfZWldO1xuICB9XG5cbiAgcmV0dXJuIGNsdXN0ZXJzO1xufTtcblxudmFyIGFzc2lnbiQyID0gZnVuY3Rpb24gYXNzaWduKG4sIFMsIGV4ZW1wbGFycykge1xuICB2YXIgY2x1c3RlcnMgPSBhc3NpZ25DbHVzdGVycyhuLCBTLCBleGVtcGxhcnMpO1xuXG4gIGZvciAodmFyIGVpID0gMDsgZWkgPCBleGVtcGxhcnMubGVuZ3RoOyBlaSsrKSB7XG4gICAgdmFyIGlpID0gW107XG5cbiAgICBmb3IgKHZhciBjID0gMDsgYyA8IGNsdXN0ZXJzLmxlbmd0aDsgYysrKSB7XG4gICAgICBpZiAoY2x1c3RlcnNbY10gPT09IGV4ZW1wbGFyc1tlaV0pIHtcbiAgICAgICAgaWkucHVzaChjKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbWF4SSA9IC0xO1xuICAgIHZhciBtYXhTdW0gPSAtSW5maW5pdHk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlpLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgc3VtID0gMDtcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBpaS5sZW5ndGg7IGorKykge1xuICAgICAgICBzdW0gKz0gU1tpaVtqXSAqIG4gKyBpaVtpXV07XG4gICAgICB9XG5cbiAgICAgIGlmIChzdW0gPiBtYXhTdW0pIHtcbiAgICAgICAgbWF4SSA9IGk7XG4gICAgICAgIG1heFN1bSA9IHN1bTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBleGVtcGxhcnNbZWldID0gaWlbbWF4SV07XG4gIH1cblxuICBjbHVzdGVycyA9IGFzc2lnbkNsdXN0ZXJzKG4sIFMsIGV4ZW1wbGFycyk7XG4gIHJldHVybiBjbHVzdGVycztcbn07XG5cbnZhciBhZmZpbml0eVByb3BhZ2F0aW9uID0gZnVuY3Rpb24gYWZmaW5pdHlQcm9wYWdhdGlvbihvcHRpb25zKSB7XG4gIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgdmFyIG5vZGVzID0gdGhpcy5ub2RlcygpO1xuICB2YXIgb3B0cyA9IHNldE9wdGlvbnMkMyhvcHRpb25zKTsgLy8gTWFwIGVhY2ggbm9kZSB0byBpdHMgcG9zaXRpb24gaW4gbm9kZSBhcnJheVxuXG4gIHZhciBpZDJwb3NpdGlvbiA9IHt9O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBpZDJwb3NpdGlvbltub2Rlc1tpXS5pZCgpXSA9IGk7XG4gIH0gLy8gQmVnaW4gYWZmaW5pdHkgcHJvcGFnYXRpb24gYWxnb3JpdGhtXG5cblxuICB2YXIgbjsgLy8gbnVtYmVyIG9mIGRhdGEgcG9pbnRzXG5cbiAgdmFyIG4yOyAvLyBzaXplIG9mIG1hdHJpY2VzXG5cbiAgdmFyIFM7IC8vIHNpbWlsYXJpdHkgbWF0cml4ICgxRCBhcnJheSlcblxuICB2YXIgcDsgLy8gcHJlZmVyZW5jZS9zdWl0YWJpbGl0eSBvZiBhIGRhdGEgcG9pbnQgdG8gc2VydmUgYXMgYW4gZXhlbXBsYXJcblxuICB2YXIgUjsgLy8gcmVzcG9uc2liaWxpdHkgbWF0cml4ICgxRCBhcnJheSlcblxuICB2YXIgQTsgLy8gYXZhaWxhYmlsaXR5IG1hdHJpeCAoMUQgYXJyYXkpXG5cbiAgbiA9IG5vZGVzLmxlbmd0aDtcbiAgbjIgPSBuICogbjsgLy8gSW5pdGlhbGl6ZSBhbmQgYnVpbGQgUyBzaW1pbGFyaXR5IG1hdHJpeFxuXG4gIFMgPSBuZXcgQXJyYXkobjIpO1xuXG4gIGZvciAodmFyIF9pID0gMDsgX2kgPCBuMjsgX2krKykge1xuICAgIFNbX2ldID0gLUluZmluaXR5OyAvLyBmb3IgY2FzZXMgd2hlcmUgdHdvIGRhdGEgcG9pbnRzIHNob3VsZG4ndCBiZSBsaW5rZWQgdG9nZXRoZXJcbiAgfVxuXG4gIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IG47IF9pMisrKSB7XG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBuOyBqKyspIHtcbiAgICAgIGlmIChfaTIgIT09IGopIHtcbiAgICAgICAgU1tfaTIgKiBuICsgal0gPSBnZXRTaW1pbGFyaXR5JDEob3B0cy5kaXN0YW5jZSwgbm9kZXNbX2kyXSwgbm9kZXNbal0sIG9wdHMuYXR0cmlidXRlcyk7XG4gICAgICB9XG4gICAgfVxuICB9IC8vIFBsYWNlIHByZWZlcmVuY2VzIG9uIHRoZSBkaWFnb25hbCBvZiBTXG5cblxuICBwID0gZ2V0UHJlZmVyZW5jZShTLCBvcHRzLnByZWZlcmVuY2UpO1xuXG4gIGZvciAodmFyIF9pMyA9IDA7IF9pMyA8IG47IF9pMysrKSB7XG4gICAgU1tfaTMgKiBuICsgX2kzXSA9IHA7XG4gIH0gLy8gSW5pdGlhbGl6ZSBSIHJlc3BvbnNpYmlsaXR5IG1hdHJpeFxuXG5cbiAgUiA9IG5ldyBBcnJheShuMik7XG5cbiAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgbjI7IF9pNCsrKSB7XG4gICAgUltfaTRdID0gMC4wO1xuICB9IC8vIEluaXRpYWxpemUgQSBhdmFpbGFiaWxpdHkgbWF0cml4XG5cblxuICBBID0gbmV3IEFycmF5KG4yKTtcblxuICBmb3IgKHZhciBfaTUgPSAwOyBfaTUgPCBuMjsgX2k1KyspIHtcbiAgICBBW19pNV0gPSAwLjA7XG4gIH1cblxuICB2YXIgb2xkID0gbmV3IEFycmF5KG4pO1xuICB2YXIgUnAgPSBuZXcgQXJyYXkobik7XG4gIHZhciBzZSA9IG5ldyBBcnJheShuKTtcblxuICBmb3IgKHZhciBfaTYgPSAwOyBfaTYgPCBuOyBfaTYrKykge1xuICAgIG9sZFtfaTZdID0gMC4wO1xuICAgIFJwW19pNl0gPSAwLjA7XG4gICAgc2VbX2k2XSA9IDA7XG4gIH1cblxuICB2YXIgZSA9IG5ldyBBcnJheShuICogb3B0cy5taW5JdGVyYXRpb25zKTtcblxuICBmb3IgKHZhciBfaTcgPSAwOyBfaTcgPCBlLmxlbmd0aDsgX2k3KyspIHtcbiAgICBlW19pN10gPSAwO1xuICB9XG5cbiAgdmFyIGl0ZXI7XG5cbiAgZm9yIChpdGVyID0gMDsgaXRlciA8IG9wdHMubWF4SXRlcmF0aW9uczsgaXRlcisrKSB7XG4gICAgLy8gbWFpbiBhbGdvcml0aG1pYyBsb29wXG4gICAgLy8gVXBkYXRlIFIgcmVzcG9uc2liaWxpdHkgbWF0cml4XG4gICAgZm9yICh2YXIgX2k4ID0gMDsgX2k4IDwgbjsgX2k4KyspIHtcbiAgICAgIHZhciBtYXggPSAtSW5maW5pdHksXG4gICAgICAgICAgbWF4MiA9IC1JbmZpbml0eSxcbiAgICAgICAgICBtYXhJID0gLTEsXG4gICAgICAgICAgQVMgPSAwLjA7XG5cbiAgICAgIGZvciAodmFyIF9qID0gMDsgX2ogPCBuOyBfaisrKSB7XG4gICAgICAgIG9sZFtfal0gPSBSW19pOCAqIG4gKyBfal07XG4gICAgICAgIEFTID0gQVtfaTggKiBuICsgX2pdICsgU1tfaTggKiBuICsgX2pdO1xuXG4gICAgICAgIGlmIChBUyA+PSBtYXgpIHtcbiAgICAgICAgICBtYXgyID0gbWF4O1xuICAgICAgICAgIG1heCA9IEFTO1xuICAgICAgICAgIG1heEkgPSBfajtcbiAgICAgICAgfSBlbHNlIGlmIChBUyA+IG1heDIpIHtcbiAgICAgICAgICBtYXgyID0gQVM7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZm9yICh2YXIgX2oyID0gMDsgX2oyIDwgbjsgX2oyKyspIHtcbiAgICAgICAgUltfaTggKiBuICsgX2oyXSA9ICgxIC0gb3B0cy5kYW1waW5nKSAqIChTW19pOCAqIG4gKyBfajJdIC0gbWF4KSArIG9wdHMuZGFtcGluZyAqIG9sZFtfajJdO1xuICAgICAgfVxuXG4gICAgICBSW19pOCAqIG4gKyBtYXhJXSA9ICgxIC0gb3B0cy5kYW1waW5nKSAqIChTW19pOCAqIG4gKyBtYXhJXSAtIG1heDIpICsgb3B0cy5kYW1waW5nICogb2xkW21heEldO1xuICAgIH0gLy8gVXBkYXRlIEEgYXZhaWxhYmlsaXR5IG1hdHJpeFxuXG5cbiAgICBmb3IgKHZhciBfaTkgPSAwOyBfaTkgPCBuOyBfaTkrKykge1xuICAgICAgdmFyIHN1bSA9IDA7XG5cbiAgICAgIGZvciAodmFyIF9qMyA9IDA7IF9qMyA8IG47IF9qMysrKSB7XG4gICAgICAgIG9sZFtfajNdID0gQVtfajMgKiBuICsgX2k5XTtcbiAgICAgICAgUnBbX2ozXSA9IE1hdGgubWF4KDAsIFJbX2ozICogbiArIF9pOV0pO1xuICAgICAgICBzdW0gKz0gUnBbX2ozXTtcbiAgICAgIH1cblxuICAgICAgc3VtIC09IFJwW19pOV07XG4gICAgICBScFtfaTldID0gUltfaTkgKiBuICsgX2k5XTtcbiAgICAgIHN1bSArPSBScFtfaTldO1xuXG4gICAgICBmb3IgKHZhciBfajQgPSAwOyBfajQgPCBuOyBfajQrKykge1xuICAgICAgICBBW19qNCAqIG4gKyBfaTldID0gKDEgLSBvcHRzLmRhbXBpbmcpICogTWF0aC5taW4oMCwgc3VtIC0gUnBbX2o0XSkgKyBvcHRzLmRhbXBpbmcgKiBvbGRbX2o0XTtcbiAgICAgIH1cblxuICAgICAgQVtfaTkgKiBuICsgX2k5XSA9ICgxIC0gb3B0cy5kYW1waW5nKSAqIChzdW0gLSBScFtfaTldKSArIG9wdHMuZGFtcGluZyAqIG9sZFtfaTldO1xuICAgIH0gLy8gQ2hlY2sgZm9yIGNvbnZlcmdlbmNlXG5cblxuICAgIHZhciBLID0gMDtcblxuICAgIGZvciAodmFyIF9pMTAgPSAwOyBfaTEwIDwgbjsgX2kxMCsrKSB7XG4gICAgICB2YXIgRSA9IEFbX2kxMCAqIG4gKyBfaTEwXSArIFJbX2kxMCAqIG4gKyBfaTEwXSA+IDAgPyAxIDogMDtcbiAgICAgIGVbaXRlciAlIG9wdHMubWluSXRlcmF0aW9ucyAqIG4gKyBfaTEwXSA9IEU7XG4gICAgICBLICs9IEU7XG4gICAgfVxuXG4gICAgaWYgKEsgPiAwICYmIChpdGVyID49IG9wdHMubWluSXRlcmF0aW9ucyAtIDEgfHwgaXRlciA9PSBvcHRzLm1heEl0ZXJhdGlvbnMgLSAxKSkge1xuICAgICAgdmFyIF9zdW0gPSAwO1xuXG4gICAgICBmb3IgKHZhciBfaTExID0gMDsgX2kxMSA8IG47IF9pMTErKykge1xuICAgICAgICBzZVtfaTExXSA9IDA7XG5cbiAgICAgICAgZm9yICh2YXIgX2o1ID0gMDsgX2o1IDwgb3B0cy5taW5JdGVyYXRpb25zOyBfajUrKykge1xuICAgICAgICAgIHNlW19pMTFdICs9IGVbX2o1ICogbiArIF9pMTFdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlW19pMTFdID09PSAwIHx8IHNlW19pMTFdID09PSBvcHRzLm1pbkl0ZXJhdGlvbnMpIHtcbiAgICAgICAgICBfc3VtKys7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKF9zdW0gPT09IG4pIHtcbiAgICAgICAgLy8gdGhlbiB3ZSBoYXZlIGNvbnZlcmdlbmNlXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfSAvLyBJZGVudGlmeSBleGVtcGxhcnMgKGNsdXN0ZXIgY2VudGVycylcblxuXG4gIHZhciBleGVtcGxhcnNJbmRpY2VzID0gZmluZEV4ZW1wbGFycyhuLCBSLCBBKTsgLy8gQXNzaWduIG5vZGVzIHRvIGNsdXN0ZXJzXG5cbiAgdmFyIGNsdXN0ZXJJbmRpY2VzID0gYXNzaWduJDIobiwgUywgZXhlbXBsYXJzSW5kaWNlcyk7XG4gIHZhciBjbHVzdGVycyA9IHt9O1xuXG4gIGZvciAodmFyIGMgPSAwOyBjIDwgZXhlbXBsYXJzSW5kaWNlcy5sZW5ndGg7IGMrKykge1xuICAgIGNsdXN0ZXJzW2V4ZW1wbGFyc0luZGljZXNbY11dID0gW107XG4gIH1cblxuICBmb3IgKHZhciBfaTEyID0gMDsgX2kxMiA8IG5vZGVzLmxlbmd0aDsgX2kxMisrKSB7XG4gICAgdmFyIHBvcyA9IGlkMnBvc2l0aW9uW25vZGVzW19pMTJdLmlkKCldO1xuXG4gICAgdmFyIGNsdXN0ZXJJbmRleCA9IGNsdXN0ZXJJbmRpY2VzW3Bvc107XG5cbiAgICBpZiAoY2x1c3RlckluZGV4ICE9IG51bGwpIHtcbiAgICAgIC8vIHRoZSBub2RlIG1heSBoYXZlIG5vdCBiZWVuIGFzc2lnbmVkIGEgY2x1c3RlciBpZiBubyB2YWxpZCBhdHRyaWJ1dGVzIHdlcmUgc3BlY2lmaWVkXG4gICAgICBjbHVzdGVyc1tjbHVzdGVySW5kZXhdLnB1c2gobm9kZXNbX2kxMl0pO1xuICAgIH1cbiAgfVxuXG4gIHZhciByZXRDbHVzdGVycyA9IG5ldyBBcnJheShleGVtcGxhcnNJbmRpY2VzLmxlbmd0aCk7XG5cbiAgZm9yICh2YXIgX2MgPSAwOyBfYyA8IGV4ZW1wbGFyc0luZGljZXMubGVuZ3RoOyBfYysrKSB7XG4gICAgcmV0Q2x1c3RlcnNbX2NdID0gY3kuY29sbGVjdGlvbihjbHVzdGVyc1tleGVtcGxhcnNJbmRpY2VzW19jXV0pO1xuICB9XG5cbiAgcmV0dXJuIHJldENsdXN0ZXJzO1xufTtcblxudmFyIGFmZmluaXR5UHJvcGFnYXRpb24kMSA9IHtcbiAgYWZmaW5pdHlQcm9wYWdhdGlvbjogYWZmaW5pdHlQcm9wYWdhdGlvbixcbiAgYXA6IGFmZmluaXR5UHJvcGFnYXRpb25cbn07XG5cbnZhciBoaWVyaG9semVyRGVmYXVsdHMgPSBkZWZhdWx0cyh7XG4gIHJvb3Q6IHVuZGVmaW5lZCxcbiAgZGlyZWN0ZWQ6IGZhbHNlXG59KTtcbnZhciBlbGVzZm4kYiA9IHtcbiAgaGllcmhvbHplcjogZnVuY3Rpb24gaGllcmhvbHplcihvcHRpb25zKSB7XG4gICAgaWYgKCFwbGFpbk9iamVjdChvcHRpb25zKSkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBvcHRpb25zID0ge1xuICAgICAgICByb290OiBhcmdzWzBdLFxuICAgICAgICBkaXJlY3RlZDogYXJnc1sxXVxuICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgX2hpZXJob2x6ZXJEZWZhdWx0cyA9IGhpZXJob2x6ZXJEZWZhdWx0cyhvcHRpb25zKSxcbiAgICAgICAgcm9vdCA9IF9oaWVyaG9semVyRGVmYXVsdHMucm9vdCxcbiAgICAgICAgZGlyZWN0ZWQgPSBfaGllcmhvbHplckRlZmF1bHRzLmRpcmVjdGVkO1xuXG4gICAgdmFyIGVsZXMgPSB0aGlzO1xuICAgIHZhciBkZmxhZyA9IGZhbHNlO1xuICAgIHZhciBvZGRJbjtcbiAgICB2YXIgb2RkT3V0O1xuICAgIHZhciBzdGFydFZlcnRleDtcbiAgICBpZiAocm9vdCkgc3RhcnRWZXJ0ZXggPSBzdHJpbmcocm9vdCkgPyB0aGlzLmZpbHRlcihyb290KVswXS5pZCgpIDogcm9vdFswXS5pZCgpO1xuICAgIHZhciBub2RlcyA9IHt9O1xuICAgIHZhciBlZGdlcyA9IHt9O1xuXG4gICAgaWYgKGRpcmVjdGVkKSB7XG4gICAgICBlbGVzLmZvckVhY2goZnVuY3Rpb24gKGVsZSkge1xuICAgICAgICB2YXIgaWQgPSBlbGUuaWQoKTtcblxuICAgICAgICBpZiAoZWxlLmlzTm9kZSgpKSB7XG4gICAgICAgICAgdmFyIGluZCA9IGVsZS5pbmRlZ3JlZSh0cnVlKTtcbiAgICAgICAgICB2YXIgb3V0ZCA9IGVsZS5vdXRkZWdyZWUodHJ1ZSk7XG4gICAgICAgICAgdmFyIGQxID0gaW5kIC0gb3V0ZDtcbiAgICAgICAgICB2YXIgZDIgPSBvdXRkIC0gaW5kO1xuXG4gICAgICAgICAgaWYgKGQxID09IDEpIHtcbiAgICAgICAgICAgIGlmIChvZGRJbikgZGZsYWcgPSB0cnVlO2Vsc2Ugb2RkSW4gPSBpZDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGQyID09IDEpIHtcbiAgICAgICAgICAgIGlmIChvZGRPdXQpIGRmbGFnID0gdHJ1ZTtlbHNlIG9kZE91dCA9IGlkO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZDIgPiAxIHx8IGQxID4gMSkge1xuICAgICAgICAgICAgZGZsYWcgPSB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIG5vZGVzW2lkXSA9IFtdO1xuICAgICAgICAgIGVsZS5vdXRnb2VycygpLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmIChlLmlzRWRnZSgpKSBub2Rlc1tpZF0ucHVzaChlLmlkKCkpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVkZ2VzW2lkXSA9IFt1bmRlZmluZWQsIGVsZS50YXJnZXQoKS5pZCgpXTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsZXMuZm9yRWFjaChmdW5jdGlvbiAoZWxlKSB7XG4gICAgICAgIHZhciBpZCA9IGVsZS5pZCgpO1xuXG4gICAgICAgIGlmIChlbGUuaXNOb2RlKCkpIHtcbiAgICAgICAgICB2YXIgZCA9IGVsZS5kZWdyZWUodHJ1ZSk7XG5cbiAgICAgICAgICBpZiAoZCAlIDIpIHtcbiAgICAgICAgICAgIGlmICghb2RkSW4pIG9kZEluID0gaWQ7ZWxzZSBpZiAoIW9kZE91dCkgb2RkT3V0ID0gaWQ7ZWxzZSBkZmxhZyA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbm9kZXNbaWRdID0gW107XG4gICAgICAgICAgZWxlLmNvbm5lY3RlZEVkZ2VzKCkuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGVzW2lkXS5wdXNoKGUuaWQoKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZWRnZXNbaWRdID0gW2VsZS5zb3VyY2UoKS5pZCgpLCBlbGUudGFyZ2V0KCkuaWQoKV07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciByZXN1bHQgPSB7XG4gICAgICBmb3VuZDogZmFsc2UsXG4gICAgICB0cmFpbDogdW5kZWZpbmVkXG4gICAgfTtcbiAgICBpZiAoZGZsYWcpIHJldHVybiByZXN1bHQ7ZWxzZSBpZiAob2RkT3V0ICYmIG9kZEluKSB7XG4gICAgICBpZiAoZGlyZWN0ZWQpIHtcbiAgICAgICAgaWYgKHN0YXJ0VmVydGV4ICYmIG9kZE91dCAhPSBzdGFydFZlcnRleCkge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBzdGFydFZlcnRleCA9IG9kZE91dDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChzdGFydFZlcnRleCAmJiBvZGRPdXQgIT0gc3RhcnRWZXJ0ZXggJiYgb2RkSW4gIT0gc3RhcnRWZXJ0ZXgpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9IGVsc2UgaWYgKCFzdGFydFZlcnRleCkge1xuICAgICAgICAgIHN0YXJ0VmVydGV4ID0gb2RkT3V0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghc3RhcnRWZXJ0ZXgpIHN0YXJ0VmVydGV4ID0gZWxlc1swXS5pZCgpO1xuICAgIH1cblxuICAgIHZhciB3YWxrID0gZnVuY3Rpb24gd2Fsayh2KSB7XG4gICAgICB2YXIgY3VycmVudE5vZGUgPSB2O1xuICAgICAgdmFyIHN1YnRvdXIgPSBbdl07XG4gICAgICB2YXIgYWRqLCBhZGpUYWlsLCBhZGpIZWFkO1xuXG4gICAgICB3aGlsZSAobm9kZXNbY3VycmVudE5vZGVdLmxlbmd0aCkge1xuICAgICAgICBhZGogPSBub2Rlc1tjdXJyZW50Tm9kZV0uc2hpZnQoKTtcbiAgICAgICAgYWRqVGFpbCA9IGVkZ2VzW2Fkal1bMF07XG4gICAgICAgIGFkakhlYWQgPSBlZGdlc1thZGpdWzFdO1xuXG4gICAgICAgIGlmIChjdXJyZW50Tm9kZSAhPSBhZGpIZWFkKSB7XG4gICAgICAgICAgbm9kZXNbYWRqSGVhZF0gPSBub2Rlc1thZGpIZWFkXS5maWx0ZXIoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBlICE9IGFkajtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjdXJyZW50Tm9kZSA9IGFkakhlYWQ7XG4gICAgICAgIH0gZWxzZSBpZiAoIWRpcmVjdGVkICYmIGN1cnJlbnROb2RlICE9IGFkalRhaWwpIHtcbiAgICAgICAgICBub2Rlc1thZGpUYWlsXSA9IG5vZGVzW2FkalRhaWxdLmZpbHRlcihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGUgIT0gYWRqO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGN1cnJlbnROb2RlID0gYWRqVGFpbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHN1YnRvdXIudW5zaGlmdChhZGopO1xuICAgICAgICBzdWJ0b3VyLnVuc2hpZnQoY3VycmVudE5vZGUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3VidG91cjtcbiAgICB9O1xuXG4gICAgdmFyIHRyYWlsID0gW107XG4gICAgdmFyIHN1YnRvdXIgPSBbXTtcbiAgICBzdWJ0b3VyID0gd2FsayhzdGFydFZlcnRleCk7XG5cbiAgICB3aGlsZSAoc3VidG91ci5sZW5ndGggIT0gMSkge1xuICAgICAgaWYgKG5vZGVzW3N1YnRvdXJbMF1dLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgIHRyYWlsLnVuc2hpZnQoZWxlcy5nZXRFbGVtZW50QnlJZChzdWJ0b3VyLnNoaWZ0KCkpKTtcbiAgICAgICAgdHJhaWwudW5zaGlmdChlbGVzLmdldEVsZW1lbnRCeUlkKHN1YnRvdXIuc2hpZnQoKSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3VidG91ciA9IHdhbGsoc3VidG91ci5zaGlmdCgpKS5jb25jYXQoc3VidG91cik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdHJhaWwudW5zaGlmdChlbGVzLmdldEVsZW1lbnRCeUlkKHN1YnRvdXIuc2hpZnQoKSkpOyAvLyBmaW5hbCBub2RlXG5cbiAgICBmb3IgKHZhciBkIGluIG5vZGVzKSB7XG4gICAgICBpZiAobm9kZXNbZF0ubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmVzdWx0LmZvdW5kID0gdHJ1ZTtcbiAgICByZXN1bHQudHJhaWwgPSB0aGlzLnNwYXduKHRyYWlsKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59O1xuXG52YXIgaG9wY3JvZnRUYXJqYW5CaWNvbm5lY3RlZCA9IGZ1bmN0aW9uIGhvcGNyb2Z0VGFyamFuQmljb25uZWN0ZWQoKSB7XG4gIHZhciBlbGVzID0gdGhpcztcbiAgdmFyIG5vZGVzID0ge307XG4gIHZhciBpZCA9IDA7XG4gIHZhciBlZGdlQ291bnQgPSAwO1xuICB2YXIgY29tcG9uZW50cyA9IFtdO1xuICB2YXIgc3RhY2sgPSBbXTtcbiAgdmFyIHZpc2l0ZWRFZGdlcyA9IHt9O1xuXG4gIHZhciBidWlsZENvbXBvbmVudCA9IGZ1bmN0aW9uIGJ1aWxkQ29tcG9uZW50KHgsIHkpIHtcbiAgICB2YXIgaSA9IHN0YWNrLmxlbmd0aCAtIDE7XG4gICAgdmFyIGN1dHNldCA9IFtdO1xuICAgIHZhciBjb21wb25lbnQgPSBlbGVzLnNwYXduKCk7XG5cbiAgICB3aGlsZSAoc3RhY2tbaV0ueCAhPSB4IHx8IHN0YWNrW2ldLnkgIT0geSkge1xuICAgICAgY3V0c2V0LnB1c2goc3RhY2sucG9wKCkuZWRnZSk7XG4gICAgICBpLS07XG4gICAgfVxuXG4gICAgY3V0c2V0LnB1c2goc3RhY2sucG9wKCkuZWRnZSk7XG4gICAgY3V0c2V0LmZvckVhY2goZnVuY3Rpb24gKGVkZ2UpIHtcbiAgICAgIHZhciBjb25uZWN0ZWROb2RlcyA9IGVkZ2UuY29ubmVjdGVkTm9kZXMoKS5pbnRlcnNlY3Rpb24oZWxlcyk7XG4gICAgICBjb21wb25lbnQubWVyZ2UoZWRnZSk7XG4gICAgICBjb25uZWN0ZWROb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIHZhciBub2RlSWQgPSBub2RlLmlkKCk7XG4gICAgICAgIHZhciBjb25uZWN0ZWRFZGdlcyA9IG5vZGUuY29ubmVjdGVkRWRnZXMoKS5pbnRlcnNlY3Rpb24oZWxlcyk7XG4gICAgICAgIGNvbXBvbmVudC5tZXJnZShub2RlKTtcblxuICAgICAgICBpZiAoIW5vZGVzW25vZGVJZF0uY3V0VmVydGV4KSB7XG4gICAgICAgICAgY29tcG9uZW50Lm1lcmdlKGNvbm5lY3RlZEVkZ2VzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb21wb25lbnQubWVyZ2UoY29ubmVjdGVkRWRnZXMuZmlsdGVyKGZ1bmN0aW9uIChlZGdlKSB7XG4gICAgICAgICAgICByZXR1cm4gZWRnZS5pc0xvb3AoKTtcbiAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGNvbXBvbmVudHMucHVzaChjb21wb25lbnQpO1xuICB9O1xuXG4gIHZhciBiaWNvbm5lY3RlZFNlYXJjaCA9IGZ1bmN0aW9uIGJpY29ubmVjdGVkU2VhcmNoKHJvb3QsIGN1cnJlbnROb2RlLCBwYXJlbnQpIHtcbiAgICBpZiAocm9vdCA9PT0gcGFyZW50KSBlZGdlQ291bnQgKz0gMTtcbiAgICBub2Rlc1tjdXJyZW50Tm9kZV0gPSB7XG4gICAgICBpZDogaWQsXG4gICAgICBsb3c6IGlkKyssXG4gICAgICBjdXRWZXJ0ZXg6IGZhbHNlXG4gICAgfTtcbiAgICB2YXIgZWRnZXMgPSBlbGVzLmdldEVsZW1lbnRCeUlkKGN1cnJlbnROb2RlKS5jb25uZWN0ZWRFZGdlcygpLmludGVyc2VjdGlvbihlbGVzKTtcblxuICAgIGlmIChlZGdlcy5zaXplKCkgPT09IDApIHtcbiAgICAgIGNvbXBvbmVudHMucHVzaChlbGVzLnNwYXduKGVsZXMuZ2V0RWxlbWVudEJ5SWQoY3VycmVudE5vZGUpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBzb3VyY2VJZCwgdGFyZ2V0SWQsIG90aGVyTm9kZUlkLCBlZGdlSWQ7XG4gICAgICBlZGdlcy5mb3JFYWNoKGZ1bmN0aW9uIChlZGdlKSB7XG4gICAgICAgIHNvdXJjZUlkID0gZWRnZS5zb3VyY2UoKS5pZCgpO1xuICAgICAgICB0YXJnZXRJZCA9IGVkZ2UudGFyZ2V0KCkuaWQoKTtcbiAgICAgICAgb3RoZXJOb2RlSWQgPSBzb3VyY2VJZCA9PT0gY3VycmVudE5vZGUgPyB0YXJnZXRJZCA6IHNvdXJjZUlkO1xuXG4gICAgICAgIGlmIChvdGhlck5vZGVJZCAhPT0gcGFyZW50KSB7XG4gICAgICAgICAgZWRnZUlkID0gZWRnZS5pZCgpO1xuXG4gICAgICAgICAgaWYgKCF2aXNpdGVkRWRnZXNbZWRnZUlkXSkge1xuICAgICAgICAgICAgdmlzaXRlZEVkZ2VzW2VkZ2VJZF0gPSB0cnVlO1xuICAgICAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgICAgIHg6IGN1cnJlbnROb2RlLFxuICAgICAgICAgICAgICB5OiBvdGhlck5vZGVJZCxcbiAgICAgICAgICAgICAgZWRnZTogZWRnZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCEob3RoZXJOb2RlSWQgaW4gbm9kZXMpKSB7XG4gICAgICAgICAgICBiaWNvbm5lY3RlZFNlYXJjaChyb290LCBvdGhlck5vZGVJZCwgY3VycmVudE5vZGUpO1xuICAgICAgICAgICAgbm9kZXNbY3VycmVudE5vZGVdLmxvdyA9IE1hdGgubWluKG5vZGVzW2N1cnJlbnROb2RlXS5sb3csIG5vZGVzW290aGVyTm9kZUlkXS5sb3cpO1xuXG4gICAgICAgICAgICBpZiAobm9kZXNbY3VycmVudE5vZGVdLmlkIDw9IG5vZGVzW290aGVyTm9kZUlkXS5sb3cpIHtcbiAgICAgICAgICAgICAgbm9kZXNbY3VycmVudE5vZGVdLmN1dFZlcnRleCA9IHRydWU7XG4gICAgICAgICAgICAgIGJ1aWxkQ29tcG9uZW50KGN1cnJlbnROb2RlLCBvdGhlck5vZGVJZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5vZGVzW2N1cnJlbnROb2RlXS5sb3cgPSBNYXRoLm1pbihub2Rlc1tjdXJyZW50Tm9kZV0ubG93LCBub2Rlc1tvdGhlck5vZGVJZF0uaWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIGVsZXMuZm9yRWFjaChmdW5jdGlvbiAoZWxlKSB7XG4gICAgaWYgKGVsZS5pc05vZGUoKSkge1xuICAgICAgdmFyIG5vZGVJZCA9IGVsZS5pZCgpO1xuXG4gICAgICBpZiAoIShub2RlSWQgaW4gbm9kZXMpKSB7XG4gICAgICAgIGVkZ2VDb3VudCA9IDA7XG4gICAgICAgIGJpY29ubmVjdGVkU2VhcmNoKG5vZGVJZCwgbm9kZUlkKTtcbiAgICAgICAgbm9kZXNbbm9kZUlkXS5jdXRWZXJ0ZXggPSBlZGdlQ291bnQgPiAxO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG4gIHZhciBjdXRWZXJ0aWNlcyA9IE9iamVjdC5rZXlzKG5vZGVzKS5maWx0ZXIoZnVuY3Rpb24gKGlkKSB7XG4gICAgcmV0dXJuIG5vZGVzW2lkXS5jdXRWZXJ0ZXg7XG4gIH0pLm1hcChmdW5jdGlvbiAoaWQpIHtcbiAgICByZXR1cm4gZWxlcy5nZXRFbGVtZW50QnlJZChpZCk7XG4gIH0pO1xuICByZXR1cm4ge1xuICAgIGN1dDogZWxlcy5zcGF3bihjdXRWZXJ0aWNlcyksXG4gICAgY29tcG9uZW50czogY29tcG9uZW50c1xuICB9O1xufTtcblxudmFyIGhvcGNyb2Z0VGFyamFuQmljb25uZWN0ZWQkMSA9IHtcbiAgaG9wY3JvZnRUYXJqYW5CaWNvbm5lY3RlZDogaG9wY3JvZnRUYXJqYW5CaWNvbm5lY3RlZCxcbiAgaHRiYzogaG9wY3JvZnRUYXJqYW5CaWNvbm5lY3RlZCxcbiAgaHRiOiBob3Bjcm9mdFRhcmphbkJpY29ubmVjdGVkLFxuICBob3Bjcm9mdFRhcmphbkJpY29ubmVjdGVkQ29tcG9uZW50czogaG9wY3JvZnRUYXJqYW5CaWNvbm5lY3RlZFxufTtcblxudmFyIHRhcmphblN0cm9uZ2x5Q29ubmVjdGVkID0gZnVuY3Rpb24gdGFyamFuU3Ryb25nbHlDb25uZWN0ZWQoKSB7XG4gIHZhciBlbGVzID0gdGhpcztcbiAgdmFyIG5vZGVzID0ge307XG4gIHZhciBpbmRleCA9IDA7XG4gIHZhciBjb21wb25lbnRzID0gW107XG4gIHZhciBzdGFjayA9IFtdO1xuICB2YXIgY3V0ID0gZWxlcy5zcGF3bihlbGVzKTtcblxuICB2YXIgc3Ryb25nbHlDb25uZWN0ZWRTZWFyY2ggPSBmdW5jdGlvbiBzdHJvbmdseUNvbm5lY3RlZFNlYXJjaChzb3VyY2VOb2RlSWQpIHtcbiAgICBzdGFjay5wdXNoKHNvdXJjZU5vZGVJZCk7XG4gICAgbm9kZXNbc291cmNlTm9kZUlkXSA9IHtcbiAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgIGxvdzogaW5kZXgrKyxcbiAgICAgIGV4cGxvcmVkOiBmYWxzZVxuICAgIH07XG4gICAgdmFyIGNvbm5lY3RlZEVkZ2VzID0gZWxlcy5nZXRFbGVtZW50QnlJZChzb3VyY2VOb2RlSWQpLmNvbm5lY3RlZEVkZ2VzKCkuaW50ZXJzZWN0aW9uKGVsZXMpO1xuICAgIGNvbm5lY3RlZEVkZ2VzLmZvckVhY2goZnVuY3Rpb24gKGVkZ2UpIHtcbiAgICAgIHZhciB0YXJnZXROb2RlSWQgPSBlZGdlLnRhcmdldCgpLmlkKCk7XG5cbiAgICAgIGlmICh0YXJnZXROb2RlSWQgIT09IHNvdXJjZU5vZGVJZCkge1xuICAgICAgICBpZiAoISh0YXJnZXROb2RlSWQgaW4gbm9kZXMpKSB7XG4gICAgICAgICAgc3Ryb25nbHlDb25uZWN0ZWRTZWFyY2godGFyZ2V0Tm9kZUlkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghbm9kZXNbdGFyZ2V0Tm9kZUlkXS5leHBsb3JlZCkge1xuICAgICAgICAgIG5vZGVzW3NvdXJjZU5vZGVJZF0ubG93ID0gTWF0aC5taW4obm9kZXNbc291cmNlTm9kZUlkXS5sb3csIG5vZGVzW3RhcmdldE5vZGVJZF0ubG93KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKG5vZGVzW3NvdXJjZU5vZGVJZF0uaW5kZXggPT09IG5vZGVzW3NvdXJjZU5vZGVJZF0ubG93KSB7XG4gICAgICB2YXIgY29tcG9uZW50Tm9kZXMgPSBlbGVzLnNwYXduKCk7XG5cbiAgICAgIGZvciAoOzspIHtcbiAgICAgICAgdmFyIG5vZGVJZCA9IHN0YWNrLnBvcCgpO1xuICAgICAgICBjb21wb25lbnROb2Rlcy5tZXJnZShlbGVzLmdldEVsZW1lbnRCeUlkKG5vZGVJZCkpO1xuICAgICAgICBub2Rlc1tub2RlSWRdLmxvdyA9IG5vZGVzW3NvdXJjZU5vZGVJZF0uaW5kZXg7XG4gICAgICAgIG5vZGVzW25vZGVJZF0uZXhwbG9yZWQgPSB0cnVlO1xuXG4gICAgICAgIGlmIChub2RlSWQgPT09IHNvdXJjZU5vZGVJZCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBjb21wb25lbnRFZGdlcyA9IGNvbXBvbmVudE5vZGVzLmVkZ2VzV2l0aChjb21wb25lbnROb2Rlcyk7XG4gICAgICB2YXIgY29tcG9uZW50ID0gY29tcG9uZW50Tm9kZXMubWVyZ2UoY29tcG9uZW50RWRnZXMpO1xuICAgICAgY29tcG9uZW50cy5wdXNoKGNvbXBvbmVudCk7XG4gICAgICBjdXQgPSBjdXQuZGlmZmVyZW5jZShjb21wb25lbnQpO1xuICAgIH1cbiAgfTtcblxuICBlbGVzLmZvckVhY2goZnVuY3Rpb24gKGVsZSkge1xuICAgIGlmIChlbGUuaXNOb2RlKCkpIHtcbiAgICAgIHZhciBub2RlSWQgPSBlbGUuaWQoKTtcblxuICAgICAgaWYgKCEobm9kZUlkIGluIG5vZGVzKSkge1xuICAgICAgICBzdHJvbmdseUNvbm5lY3RlZFNlYXJjaChub2RlSWQpO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG4gIHJldHVybiB7XG4gICAgY3V0OiBjdXQsXG4gICAgY29tcG9uZW50czogY29tcG9uZW50c1xuICB9O1xufTtcblxudmFyIHRhcmphblN0cm9uZ2x5Q29ubmVjdGVkJDEgPSB7XG4gIHRhcmphblN0cm9uZ2x5Q29ubmVjdGVkOiB0YXJqYW5TdHJvbmdseUNvbm5lY3RlZCxcbiAgdHNjOiB0YXJqYW5TdHJvbmdseUNvbm5lY3RlZCxcbiAgdHNjYzogdGFyamFuU3Ryb25nbHlDb25uZWN0ZWQsXG4gIHRhcmphblN0cm9uZ2x5Q29ubmVjdGVkQ29tcG9uZW50czogdGFyamFuU3Ryb25nbHlDb25uZWN0ZWRcbn07XG5cbnZhciBlbGVzZm4kYyA9IHt9O1xuW2VsZXNmbiwgZWxlc2ZuJDEsIGVsZXNmbiQyLCBlbGVzZm4kMywgZWxlc2ZuJDQsIGVsZXNmbiQ1LCBlbGVzZm4kNiwgZWxlc2ZuJDcsIGVsZXNmbiQ4LCBlbGVzZm4kOSwgZWxlc2ZuJGEsIG1hcmtvdkNsdXN0ZXJpbmckMSwga0NsdXN0ZXJpbmcsIGhpZXJhcmNoaWNhbENsdXN0ZXJpbmckMSwgYWZmaW5pdHlQcm9wYWdhdGlvbiQxLCBlbGVzZm4kYiwgaG9wY3JvZnRUYXJqYW5CaWNvbm5lY3RlZCQxLCB0YXJqYW5TdHJvbmdseUNvbm5lY3RlZCQxXS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wcykge1xuICBleHRlbmQoZWxlc2ZuJGMsIHByb3BzKTtcbn0pO1xuXG4vKiFcbkVtYmVkZGFibGUgTWluaW11bSBTdHJpY3RseS1Db21wbGlhbnQgUHJvbWlzZXMvQSsgMS4xLjEgVGhlbmFibGVcbkNvcHlyaWdodCAoYykgMjAxMy0yMDE0IFJhbGYgUy4gRW5nZWxzY2hhbGwgKGh0dHA6Ly9lbmdlbHNjaGFsbC5jb20pXG5MaWNlbnNlZCB1bmRlciBUaGUgTUlUIExpY2Vuc2UgKGh0dHA6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9NSVQpXG4qL1xuXG4vKiAgcHJvbWlzZSBzdGF0ZXMgW1Byb21pc2VzL0ErIDIuMV0gICovXG52YXIgU1RBVEVfUEVORElORyA9IDA7XG4vKiAgW1Byb21pc2VzL0ErIDIuMS4xXSAgKi9cblxudmFyIFNUQVRFX0ZVTEZJTExFRCA9IDE7XG4vKiAgW1Byb21pc2VzL0ErIDIuMS4yXSAgKi9cblxudmFyIFNUQVRFX1JFSkVDVEVEID0gMjtcbi8qICBbUHJvbWlzZXMvQSsgMi4xLjNdICAqL1xuXG4vKiAgcHJvbWlzZSBvYmplY3QgY29uc3RydWN0b3IgICovXG5cbnZhciBhcGkgPSBmdW5jdGlvbiBhcGkoZXhlY3V0b3IpIHtcbiAgLyogIG9wdGlvbmFsbHkgc3VwcG9ydCBub24tY29uc3RydWN0b3IvcGxhaW4tZnVuY3Rpb24gY2FsbCAgKi9cbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIGFwaSkpIHJldHVybiBuZXcgYXBpKGV4ZWN1dG9yKTtcbiAgLyogIGluaXRpYWxpemUgb2JqZWN0ICAqL1xuXG4gIHRoaXMuaWQgPSAnVGhlbmFibGUvMS4wLjcnO1xuICB0aGlzLnN0YXRlID0gU1RBVEVfUEVORElORztcbiAgLyogIGluaXRpYWwgc3RhdGUgICovXG5cbiAgdGhpcy5mdWxmaWxsVmFsdWUgPSB1bmRlZmluZWQ7XG4gIC8qICBpbml0aWFsIHZhbHVlICAqL1xuXG4gIC8qICBbUHJvbWlzZXMvQSsgMS4zLCAyLjEuMi4yXSAgKi9cblxuICB0aGlzLnJlamVjdFJlYXNvbiA9IHVuZGVmaW5lZDtcbiAgLyogIGluaXRpYWwgcmVhc29uICovXG5cbiAgLyogIFtQcm9taXNlcy9BKyAxLjUsIDIuMS4zLjJdICAqL1xuXG4gIHRoaXMub25GdWxmaWxsZWQgPSBbXTtcbiAgLyogIGluaXRpYWwgaGFuZGxlcnMgICovXG5cbiAgdGhpcy5vblJlamVjdGVkID0gW107XG4gIC8qICBpbml0aWFsIGhhbmRsZXJzICAqL1xuXG4gIC8qICBwcm92aWRlIG9wdGlvbmFsIGluZm9ybWF0aW9uLWhpZGluZyBwcm94eSAgKi9cblxuICB0aGlzLnByb3h5ID0ge1xuICAgIHRoZW46IHRoaXMudGhlbi5iaW5kKHRoaXMpXG4gIH07XG4gIC8qICBzdXBwb3J0IG9wdGlvbmFsIGV4ZWN1dG9yIGZ1bmN0aW9uICAqL1xuXG4gIGlmICh0eXBlb2YgZXhlY3V0b3IgPT09ICdmdW5jdGlvbicpIGV4ZWN1dG9yLmNhbGwodGhpcywgdGhpcy5mdWxmaWxsLmJpbmQodGhpcyksIHRoaXMucmVqZWN0LmJpbmQodGhpcykpO1xufTtcbi8qICBwcm9taXNlIEFQSSBtZXRob2RzICAqL1xuXG5cbmFwaS5wcm90b3R5cGUgPSB7XG4gIC8qICBwcm9taXNlIHJlc29sdmluZyBtZXRob2RzICAqL1xuICBmdWxmaWxsOiBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7XG4gICAgcmV0dXJuIGRlbGl2ZXIodGhpcywgU1RBVEVfRlVMRklMTEVELCAnZnVsZmlsbFZhbHVlJywgdmFsdWUpO1xuICB9LFxuICByZWplY3Q6IGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkge1xuICAgIHJldHVybiBkZWxpdmVyKHRoaXMsIFNUQVRFX1JFSkVDVEVELCAncmVqZWN0UmVhc29uJywgdmFsdWUpO1xuICB9LFxuXG4gIC8qICBcIlRoZSB0aGVuIE1ldGhvZFwiIFtQcm9taXNlcy9BKyAxLjEsIDEuMiwgMi4yXSAgKi9cbiAgdGhlbjogZnVuY3Rpb24gdGhlbihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkge1xuICAgIHZhciBjdXJyID0gdGhpcztcbiAgICB2YXIgbmV4dCA9IG5ldyBhcGkoKTtcbiAgICAvKiAgW1Byb21pc2VzL0ErIDIuMi43XSAgKi9cblxuICAgIGN1cnIub25GdWxmaWxsZWQucHVzaChyZXNvbHZlcihvbkZ1bGZpbGxlZCwgbmV4dCwgJ2Z1bGZpbGwnKSk7XG4gICAgLyogIFtQcm9taXNlcy9BKyAyLjIuMi8yLjIuNl0gICovXG5cbiAgICBjdXJyLm9uUmVqZWN0ZWQucHVzaChyZXNvbHZlcihvblJlamVjdGVkLCBuZXh0LCAncmVqZWN0JykpO1xuICAgIC8qICBbUHJvbWlzZXMvQSsgMi4yLjMvMi4yLjZdICAqL1xuXG4gICAgZXhlY3V0ZShjdXJyKTtcbiAgICByZXR1cm4gbmV4dC5wcm94eTtcbiAgICAvKiAgW1Byb21pc2VzL0ErIDIuMi43LCAzLjNdICAqL1xuICB9XG59O1xuLyogIGRlbGl2ZXIgYW4gYWN0aW9uICAqL1xuXG52YXIgZGVsaXZlciA9IGZ1bmN0aW9uIGRlbGl2ZXIoY3Vyciwgc3RhdGUsIG5hbWUsIHZhbHVlKSB7XG4gIGlmIChjdXJyLnN0YXRlID09PSBTVEFURV9QRU5ESU5HKSB7XG4gICAgY3Vyci5zdGF0ZSA9IHN0YXRlO1xuICAgIC8qICBbUHJvbWlzZXMvQSsgMi4xLjIuMSwgMi4xLjMuMV0gICovXG5cbiAgICBjdXJyW25hbWVdID0gdmFsdWU7XG4gICAgLyogIFtQcm9taXNlcy9BKyAyLjEuMi4yLCAyLjEuMy4yXSAgKi9cblxuICAgIGV4ZWN1dGUoY3Vycik7XG4gIH1cblxuICByZXR1cm4gY3Vycjtcbn07XG4vKiAgZXhlY3V0ZSBhbGwgaGFuZGxlcnMgICovXG5cblxudmFyIGV4ZWN1dGUgPSBmdW5jdGlvbiBleGVjdXRlKGN1cnIpIHtcbiAgaWYgKGN1cnIuc3RhdGUgPT09IFNUQVRFX0ZVTEZJTExFRCkgZXhlY3V0ZV9oYW5kbGVycyhjdXJyLCAnb25GdWxmaWxsZWQnLCBjdXJyLmZ1bGZpbGxWYWx1ZSk7ZWxzZSBpZiAoY3Vyci5zdGF0ZSA9PT0gU1RBVEVfUkVKRUNURUQpIGV4ZWN1dGVfaGFuZGxlcnMoY3VyciwgJ29uUmVqZWN0ZWQnLCBjdXJyLnJlamVjdFJlYXNvbik7XG59O1xuLyogIGV4ZWN1dGUgcGFydGljdWxhciBzZXQgb2YgaGFuZGxlcnMgICovXG5cblxudmFyIGV4ZWN1dGVfaGFuZGxlcnMgPSBmdW5jdGlvbiBleGVjdXRlX2hhbmRsZXJzKGN1cnIsIG5hbWUsIHZhbHVlKSB7XG4gIC8qIGdsb2JhbCBzZXRJbW1lZGlhdGU6IHRydWUgKi9cblxuICAvKiBnbG9iYWwgc2V0VGltZW91dDogdHJ1ZSAqL1xuXG4gIC8qICBzaG9ydC1jaXJjdWl0IHByb2Nlc3NpbmcgICovXG4gIGlmIChjdXJyW25hbWVdLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAvKiAgaXRlcmF0ZSBvdmVyIGFsbCBoYW5kbGVycywgZXhhY3RseSBvbmNlICAqL1xuXG4gIHZhciBoYW5kbGVycyA9IGN1cnJbbmFtZV07XG4gIGN1cnJbbmFtZV0gPSBbXTtcbiAgLyogIFtQcm9taXNlcy9BKyAyLjIuMi4zLCAyLjIuMy4zXSAgKi9cblxuICB2YXIgZnVuYyA9IGZ1bmN0aW9uIGZ1bmMoKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYW5kbGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlcnNbaV0odmFsdWUpO1xuICAgIH1cbiAgICAvKiAgW1Byb21pc2VzL0ErIDIuMi41XSAgKi9cblxuICB9O1xuICAvKiAgZXhlY3V0ZSBwcm9jZWR1cmUgYXN5bmNocm9ub3VzbHkgICovXG5cbiAgLyogIFtQcm9taXNlcy9BKyAyLjIuNCwgMy4xXSAgKi9cblxuXG4gIGlmICh0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSAnZnVuY3Rpb24nKSBzZXRJbW1lZGlhdGUoZnVuYyk7ZWxzZSBzZXRUaW1lb3V0KGZ1bmMsIDApO1xufTtcbi8qICBnZW5lcmF0ZSBhIHJlc29sdmVyIGZ1bmN0aW9uICAqL1xuXG5cbnZhciByZXNvbHZlciA9IGZ1bmN0aW9uIHJlc29sdmVyKGNiLCBuZXh0LCBtZXRob2QpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgY2IgIT09ICdmdW5jdGlvbicpXG4gICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMi4xLCAyLjIuNy4zLCAyLjIuNy40XSAgKi9cbiAgICAgIG5leHRbbWV0aG9kXS5jYWxsKG5leHQsIHZhbHVlKTtcbiAgICAgIC8qICBbUHJvbWlzZXMvQSsgMi4yLjcuMywgMi4yLjcuNF0gICovXG4gICAgZWxzZSB7XG4gICAgICAgIHZhciByZXN1bHQ7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXN1bHQgPSBjYih2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyogIFtQcm9taXNlcy9BKyAyLjIuMi4xLCAyLjIuMy4xLCAyLjIuNSwgMy4yXSAgKi9cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICBuZXh0LnJlamVjdChlKTtcbiAgICAgICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMi43LjJdICAqL1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzb2x2ZShuZXh0LCByZXN1bHQpO1xuICAgICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMi43LjFdICAqL1xuICAgICAgfVxuICB9O1xufTtcbi8qICBcIlByb21pc2UgUmVzb2x1dGlvbiBQcm9jZWR1cmVcIiAgKi9cblxuLyogIFtQcm9taXNlcy9BKyAyLjNdICAqL1xuXG5cbnZhciByZXNvbHZlID0gZnVuY3Rpb24gcmVzb2x2ZShwcm9taXNlLCB4KSB7XG4gIC8qICBzYW5pdHkgY2hlY2sgYXJndW1lbnRzICAqL1xuXG4gIC8qICBbUHJvbWlzZXMvQSsgMi4zLjFdICAqL1xuICBpZiAocHJvbWlzZSA9PT0geCB8fCBwcm9taXNlLnByb3h5ID09PSB4KSB7XG4gICAgcHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcignY2Fubm90IHJlc29sdmUgcHJvbWlzZSB3aXRoIGl0c2VsZicpKTtcbiAgICByZXR1cm47XG4gIH1cbiAgLyogIHN1cmdpY2FsbHkgY2hlY2sgZm9yIGEgXCJ0aGVuXCIgbWV0aG9kXG4gICAgKG1haW5seSB0byBqdXN0IGNhbGwgdGhlIFwiZ2V0dGVyXCIgb2YgXCJ0aGVuXCIgb25seSBvbmNlKSAgKi9cblxuXG4gIHZhciB0aGVuO1xuXG4gIGlmIChfdHlwZW9mKHgpID09PSAnb2JqZWN0JyAmJiB4ICE9PSBudWxsIHx8IHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdHJ5IHtcbiAgICAgIHRoZW4gPSB4LnRoZW47XG4gICAgfVxuICAgIC8qICBbUHJvbWlzZXMvQSsgMi4zLjMuMSwgMy41XSAgKi9cbiAgICBjYXRjaCAoZSkge1xuICAgICAgcHJvbWlzZS5yZWplY3QoZSk7XG4gICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMy4zLjJdICAqL1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG4gIC8qICBoYW5kbGUgb3duIFRoZW5hYmxlcyAgICBbUHJvbWlzZXMvQSsgMi4zLjJdXG4gICAgYW5kIHNpbWlsYXIgXCJ0aGVuYWJsZXNcIiBbUHJvbWlzZXMvQSsgMi4zLjNdICAqL1xuXG5cbiAgaWYgKHR5cGVvZiB0aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdmFyIHJlc29sdmVkID0gZmFsc2U7XG5cbiAgICB0cnkge1xuICAgICAgLyogIGNhbGwgcmV0cmlldmVkIFwidGhlblwiIG1ldGhvZCAqL1xuXG4gICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMy4zLjNdICAqL1xuICAgICAgdGhlbi5jYWxsKHgsXG4gICAgICAvKiAgcmVzb2x2ZVByb21pc2UgICovXG5cbiAgICAgIC8qICBbUHJvbWlzZXMvQSsgMi4zLjMuMy4xXSAgKi9cbiAgICAgIGZ1bmN0aW9uICh5KSB7XG4gICAgICAgIGlmIChyZXNvbHZlZCkgcmV0dXJuO1xuICAgICAgICByZXNvbHZlZCA9IHRydWU7XG4gICAgICAgIC8qICBbUHJvbWlzZXMvQSsgMi4zLjMuMy4zXSAgKi9cblxuICAgICAgICBpZiAoeSA9PT0geClcbiAgICAgICAgICAvKiAgW1Byb21pc2VzL0ErIDMuNl0gICovXG4gICAgICAgICAgcHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcignY2lyY3VsYXIgdGhlbmFibGUgY2hhaW4nKSk7ZWxzZSByZXNvbHZlKHByb21pc2UsIHkpO1xuICAgICAgfSxcbiAgICAgIC8qICByZWplY3RQcm9taXNlICAqL1xuXG4gICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMy4zLjMuMl0gICovXG4gICAgICBmdW5jdGlvbiAocikge1xuICAgICAgICBpZiAocmVzb2x2ZWQpIHJldHVybjtcbiAgICAgICAgcmVzb2x2ZWQgPSB0cnVlO1xuICAgICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMy4zLjMuM10gICovXG5cbiAgICAgICAgcHJvbWlzZS5yZWplY3Qocik7XG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIXJlc29sdmVkKVxuICAgICAgICAvKiAgW1Byb21pc2VzL0ErIDIuMy4zLjMuM10gICovXG4gICAgICAgIHByb21pc2UucmVqZWN0KGUpO1xuICAgICAgLyogIFtQcm9taXNlcy9BKyAyLjMuMy4zLjRdICAqL1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuICAvKiAgaGFuZGxlIG90aGVyIHZhbHVlcyAgKi9cblxuXG4gIHByb21pc2UuZnVsZmlsbCh4KTtcbiAgLyogIFtQcm9taXNlcy9BKyAyLjMuNCwgMi4zLjMuNF0gICovXG59OyAvLyBzbyB3ZSBhbHdheXMgaGF2ZSBQcm9taXNlLmFsbCgpXG5cblxuYXBpLmFsbCA9IGZ1bmN0aW9uIChwcykge1xuICByZXR1cm4gbmV3IGFwaShmdW5jdGlvbiAocmVzb2x2ZUFsbCwgcmVqZWN0QWxsKSB7XG4gICAgdmFyIHZhbHMgPSBuZXcgQXJyYXkocHMubGVuZ3RoKTtcbiAgICB2YXIgZG9uZUNvdW50ID0gMDtcblxuICAgIHZhciBmdWxmaWxsID0gZnVuY3Rpb24gZnVsZmlsbChpLCB2YWwpIHtcbiAgICAgIHZhbHNbaV0gPSB2YWw7XG4gICAgICBkb25lQ291bnQrKztcblxuICAgICAgaWYgKGRvbmVDb3VudCA9PT0gcHMubGVuZ3RoKSB7XG4gICAgICAgIHJlc29sdmVBbGwodmFscyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIChmdW5jdGlvbiAoaSkge1xuICAgICAgICB2YXIgcCA9IHBzW2ldO1xuICAgICAgICB2YXIgaXNQcm9taXNlID0gcCAhPSBudWxsICYmIHAudGhlbiAhPSBudWxsO1xuXG4gICAgICAgIGlmIChpc1Byb21pc2UpIHtcbiAgICAgICAgICBwLnRoZW4oZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICAgICAgZnVsZmlsbChpLCB2YWwpO1xuICAgICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIHJlamVjdEFsbChlcnIpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB2YWwgPSBwO1xuICAgICAgICAgIGZ1bGZpbGwoaSwgdmFsKTtcbiAgICAgICAgfVxuICAgICAgfSkoaSk7XG4gICAgfVxuICB9KTtcbn07XG5cbmFwaS5yZXNvbHZlID0gZnVuY3Rpb24gKHZhbCkge1xuICByZXR1cm4gbmV3IGFwaShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgcmVzb2x2ZSh2YWwpO1xuICB9KTtcbn07XG5cbmFwaS5yZWplY3QgPSBmdW5jdGlvbiAodmFsKSB7XG4gIHJldHVybiBuZXcgYXBpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICByZWplY3QodmFsKTtcbiAgfSk7XG59O1xuXG52YXIgUHJvbWlzZSQxID0gdHlwZW9mIFByb21pc2UgIT09ICd1bmRlZmluZWQnID8gUHJvbWlzZSA6IGFwaTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG52YXIgQW5pbWF0aW9uID0gZnVuY3Rpb24gQW5pbWF0aW9uKHRhcmdldCwgb3B0cywgb3B0czIpIHtcbiAgdmFyIGlzQ29yZSA9IGNvcmUodGFyZ2V0KTtcbiAgdmFyIGlzRWxlID0gIWlzQ29yZTtcblxuICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlID0gZXh0ZW5kKHtcbiAgICBkdXJhdGlvbjogMTAwMFxuICB9LCBvcHRzLCBvcHRzMik7XG5cbiAgX3AudGFyZ2V0ID0gdGFyZ2V0O1xuICBfcC5zdHlsZSA9IF9wLnN0eWxlIHx8IF9wLmNzcztcbiAgX3Auc3RhcnRlZCA9IGZhbHNlO1xuICBfcC5wbGF5aW5nID0gZmFsc2U7XG4gIF9wLmhvb2tlZCA9IGZhbHNlO1xuICBfcC5hcHBseWluZyA9IGZhbHNlO1xuICBfcC5wcm9ncmVzcyA9IDA7XG4gIF9wLmNvbXBsZXRlcyA9IFtdO1xuICBfcC5mcmFtZXMgPSBbXTtcblxuICBpZiAoX3AuY29tcGxldGUgJiYgZm4oX3AuY29tcGxldGUpKSB7XG4gICAgX3AuY29tcGxldGVzLnB1c2goX3AuY29tcGxldGUpO1xuICB9XG5cbiAgaWYgKGlzRWxlKSB7XG4gICAgdmFyIHBvcyA9IHRhcmdldC5wb3NpdGlvbigpO1xuICAgIF9wLnN0YXJ0UG9zaXRpb24gPSBfcC5zdGFydFBvc2l0aW9uIHx8IHtcbiAgICAgIHg6IHBvcy54LFxuICAgICAgeTogcG9zLnlcbiAgICB9O1xuICAgIF9wLnN0YXJ0U3R5bGUgPSBfcC5zdGFydFN0eWxlIHx8IHRhcmdldC5jeSgpLnN0eWxlKCkuZ2V0QW5pbWF0aW9uU3RhcnRTdHlsZSh0YXJnZXQsIF9wLnN0eWxlKTtcbiAgfVxuXG4gIGlmIChpc0NvcmUpIHtcbiAgICB2YXIgcGFuID0gdGFyZ2V0LnBhbigpO1xuICAgIF9wLnN0YXJ0UGFuID0ge1xuICAgICAgeDogcGFuLngsXG4gICAgICB5OiBwYW4ueVxuICAgIH07XG4gICAgX3Auc3RhcnRab29tID0gdGFyZ2V0Lnpvb20oKTtcbiAgfSAvLyBmb3IgZnV0dXJlIHRpbWVsaW5lL2FuaW1hdGlvbnMgaW1wbFxuXG5cbiAgdGhpcy5sZW5ndGggPSAxO1xuICB0aGlzWzBdID0gdGhpcztcbn07XG5cbnZhciBhbmlmbiA9IEFuaW1hdGlvbi5wcm90b3R5cGU7XG5leHRlbmQoYW5pZm4sIHtcbiAgaW5zdGFuY2VTdHJpbmc6IGZ1bmN0aW9uIGluc3RhbmNlU3RyaW5nKCkge1xuICAgIHJldHVybiAnYW5pbWF0aW9uJztcbiAgfSxcbiAgaG9vazogZnVuY3Rpb24gaG9vaygpIHtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuXG4gICAgaWYgKCFfcC5ob29rZWQpIHtcbiAgICAgIC8vIGFkZCB0byB0YXJnZXQncyBhbmltYXRpb24gcXVldWVcbiAgICAgIHZhciBxO1xuICAgICAgdmFyIHRBbmkgPSBfcC50YXJnZXQuX3ByaXZhdGUuYW5pbWF0aW9uO1xuXG4gICAgICBpZiAoX3AucXVldWUpIHtcbiAgICAgICAgcSA9IHRBbmkucXVldWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBxID0gdEFuaS5jdXJyZW50O1xuICAgICAgfVxuXG4gICAgICBxLnB1c2godGhpcyk7IC8vIGFkZCB0byB0aGUgYW5pbWF0aW9uIGxvb3AgcG9vbFxuXG4gICAgICBpZiAoZWxlbWVudE9yQ29sbGVjdGlvbihfcC50YXJnZXQpKSB7XG4gICAgICAgIF9wLnRhcmdldC5jeSgpLmFkZFRvQW5pbWF0aW9uUG9vbChfcC50YXJnZXQpO1xuICAgICAgfVxuXG4gICAgICBfcC5ob29rZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBwbGF5OiBmdW5jdGlvbiBwbGF5KCkge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7IC8vIGF1dG9yZXdpbmRcblxuICAgIGlmIChfcC5wcm9ncmVzcyA9PT0gMSkge1xuICAgICAgX3AucHJvZ3Jlc3MgPSAwO1xuICAgIH1cblxuICAgIF9wLnBsYXlpbmcgPSB0cnVlO1xuICAgIF9wLnN0YXJ0ZWQgPSBmYWxzZTsgLy8gbmVlZHMgdG8gYmUgc3RhcnRlZCBieSBhbmltYXRpb24gbG9vcFxuXG4gICAgX3Auc3RvcHBlZCA9IGZhbHNlO1xuICAgIHRoaXMuaG9vaygpOyAvLyB0aGUgYW5pbWF0aW9uIGxvb3Agd2lsbCBzdGFydCB0aGUgYW5pbWF0aW9uLi4uXG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcGxheWluZzogZnVuY3Rpb24gcGxheWluZygpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5wbGF5aW5nO1xuICB9LFxuICBhcHBseTogZnVuY3Rpb24gYXBwbHkoKSB7XG4gICAgdmFyIF9wID0gdGhpcy5fcHJpdmF0ZTtcbiAgICBfcC5hcHBseWluZyA9IHRydWU7XG4gICAgX3Auc3RhcnRlZCA9IGZhbHNlOyAvLyBuZWVkcyB0byBiZSBzdGFydGVkIGJ5IGFuaW1hdGlvbiBsb29wXG5cbiAgICBfcC5zdG9wcGVkID0gZmFsc2U7XG4gICAgdGhpcy5ob29rKCk7IC8vIHRoZSBhbmltYXRpb24gbG9vcCB3aWxsIGFwcGx5IHRoZSBhbmltYXRpb24gYXQgdGhpcyBwcm9ncmVzc1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIGFwcGx5aW5nOiBmdW5jdGlvbiBhcHBseWluZygpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5hcHBseWluZztcbiAgfSxcbiAgcGF1c2U6IGZ1bmN0aW9uIHBhdXNlKCkge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG4gICAgX3AucGxheWluZyA9IGZhbHNlO1xuICAgIF9wLnN0YXJ0ZWQgPSBmYWxzZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgc3RvcDogZnVuY3Rpb24gc3RvcCgpIHtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuICAgIF9wLnBsYXlpbmcgPSBmYWxzZTtcbiAgICBfcC5zdGFydGVkID0gZmFsc2U7XG4gICAgX3Auc3RvcHBlZCA9IHRydWU7IC8vIHRvIGJlIHJlbW92ZWQgZnJvbSBhbmltYXRpb24gcXVldWVzXG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcmV3aW5kOiBmdW5jdGlvbiByZXdpbmQoKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvZ3Jlc3MoMCk7XG4gIH0sXG4gIGZhc3Rmb3J3YXJkOiBmdW5jdGlvbiBmYXN0Zm9yd2FyZCgpIHtcbiAgICByZXR1cm4gdGhpcy5wcm9ncmVzcygxKTtcbiAgfSxcbiAgdGltZTogZnVuY3Rpb24gdGltZSh0KSB7XG4gICAgdmFyIF9wID0gdGhpcy5fcHJpdmF0ZTtcblxuICAgIGlmICh0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBfcC5wcm9ncmVzcyAqIF9wLmR1cmF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5wcm9ncmVzcyh0IC8gX3AuZHVyYXRpb24pO1xuICAgIH1cbiAgfSxcbiAgcHJvZ3Jlc3M6IGZ1bmN0aW9uIHByb2dyZXNzKHApIHtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuICAgIHZhciB3YXNQbGF5aW5nID0gX3AucGxheWluZztcblxuICAgIGlmIChwID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBfcC5wcm9ncmVzcztcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHdhc1BsYXlpbmcpIHtcbiAgICAgICAgdGhpcy5wYXVzZSgpO1xuICAgICAgfVxuXG4gICAgICBfcC5wcm9ncmVzcyA9IHA7XG4gICAgICBfcC5zdGFydGVkID0gZmFsc2U7XG5cbiAgICAgIGlmICh3YXNQbGF5aW5nKSB7XG4gICAgICAgIHRoaXMucGxheSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBjb21wbGV0ZWQ6IGZ1bmN0aW9uIGNvbXBsZXRlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5wcm9ncmVzcyA9PT0gMTtcbiAgfSxcbiAgcmV2ZXJzZTogZnVuY3Rpb24gcmV2ZXJzZSgpIHtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuICAgIHZhciB3YXNQbGF5aW5nID0gX3AucGxheWluZztcblxuICAgIGlmICh3YXNQbGF5aW5nKSB7XG4gICAgICB0aGlzLnBhdXNlKCk7XG4gICAgfVxuXG4gICAgX3AucHJvZ3Jlc3MgPSAxIC0gX3AucHJvZ3Jlc3M7XG4gICAgX3Auc3RhcnRlZCA9IGZhbHNlO1xuXG4gICAgdmFyIHN3YXAgPSBmdW5jdGlvbiBzd2FwKGEsIGIpIHtcbiAgICAgIHZhciBfcGEgPSBfcFthXTtcblxuICAgICAgaWYgKF9wYSA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgX3BbYV0gPSBfcFtiXTtcbiAgICAgIF9wW2JdID0gX3BhO1xuICAgIH07XG5cbiAgICBzd2FwKCd6b29tJywgJ3N0YXJ0Wm9vbScpO1xuICAgIHN3YXAoJ3BhbicsICdzdGFydFBhbicpO1xuICAgIHN3YXAoJ3Bvc2l0aW9uJywgJ3N0YXJ0UG9zaXRpb24nKTsgLy8gc3dhcCBzdHlsZXNcblxuICAgIGlmIChfcC5zdHlsZSkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBfcC5zdHlsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcHJvcCA9IF9wLnN0eWxlW2ldO1xuICAgICAgICB2YXIgbmFtZSA9IHByb3AubmFtZTtcbiAgICAgICAgdmFyIHN0YXJ0U3R5bGVQcm9wID0gX3Auc3RhcnRTdHlsZVtuYW1lXTtcbiAgICAgICAgX3Auc3RhcnRTdHlsZVtuYW1lXSA9IHByb3A7XG4gICAgICAgIF9wLnN0eWxlW2ldID0gc3RhcnRTdHlsZVByb3A7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHdhc1BsYXlpbmcpIHtcbiAgICAgIHRoaXMucGxheSgpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBwcm9taXNlOiBmdW5jdGlvbiBwcm9taXNlKHR5cGUpIHtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuICAgIHZhciBhcnI7XG5cbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2ZyYW1lJzpcbiAgICAgICAgYXJyID0gX3AuZnJhbWVzO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgIGNhc2UgJ2NvbXBsZXRlJzpcbiAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6XG4gICAgICAgIGFyciA9IF9wLmNvbXBsZXRlcztcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UkMShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBhcnIucHVzaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59KTtcbmFuaWZuLmNvbXBsZXRlID0gYW5pZm4uY29tcGxldGVkO1xuYW5pZm4ucnVuID0gYW5pZm4ucGxheTtcbmFuaWZuLnJ1bm5pbmcgPSBhbmlmbi5wbGF5aW5nO1xuXG52YXIgZGVmaW5lID0ge1xuICBhbmltYXRlZDogZnVuY3Rpb24gYW5pbWF0ZWQoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIGFuaW1hdGVkSW1wbCgpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHZhciBzZWxmSXNBcnJheUxpa2UgPSBzZWxmLmxlbmd0aCAhPT0gdW5kZWZpbmVkO1xuICAgICAgdmFyIGFsbCA9IHNlbGZJc0FycmF5TGlrZSA/IHNlbGYgOiBbc2VsZl07IC8vIHB1dCBpbiBhcnJheSBpZiBub3QgYXJyYXktbGlrZVxuXG4gICAgICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5IHx8IHRoaXM7XG5cbiAgICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICB2YXIgZWxlID0gYWxsWzBdO1xuXG4gICAgICBpZiAoZWxlKSB7XG4gICAgICAgIHJldHVybiBlbGUuX3ByaXZhdGUuYW5pbWF0aW9uLmN1cnJlbnQubGVuZ3RoID4gMDtcbiAgICAgIH1cbiAgICB9O1xuICB9LFxuICAvLyBhbmltYXRlZFxuICBjbGVhclF1ZXVlOiBmdW5jdGlvbiBjbGVhclF1ZXVlKCkge1xuICAgIHJldHVybiBmdW5jdGlvbiBjbGVhclF1ZXVlSW1wbCgpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHZhciBzZWxmSXNBcnJheUxpa2UgPSBzZWxmLmxlbmd0aCAhPT0gdW5kZWZpbmVkO1xuICAgICAgdmFyIGFsbCA9IHNlbGZJc0FycmF5TGlrZSA/IHNlbGYgOiBbc2VsZl07IC8vIHB1dCBpbiBhcnJheSBpZiBub3QgYXJyYXktbGlrZVxuXG4gICAgICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5IHx8IHRoaXM7XG5cbiAgICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYWxsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSBhbGxbaV07XG4gICAgICAgIGVsZS5fcHJpdmF0ZS5hbmltYXRpb24ucXVldWUgPSBbXTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgfSxcbiAgLy8gY2xlYXJRdWV1ZVxuICBkZWxheTogZnVuY3Rpb24gZGVsYXkoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIGRlbGF5SW1wbCh0aW1lLCBjb21wbGV0ZSkge1xuICAgICAgdmFyIGN5ID0gdGhpcy5fcHJpdmF0ZS5jeSB8fCB0aGlzO1xuXG4gICAgICBpZiAoIWN5LnN0eWxlRW5hYmxlZCgpKSB7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5hbmltYXRlKHtcbiAgICAgICAgZGVsYXk6IHRpbWUsXG4gICAgICAgIGR1cmF0aW9uOiB0aW1lLFxuICAgICAgICBjb21wbGV0ZTogY29tcGxldGVcbiAgICAgIH0pO1xuICAgIH07XG4gIH0sXG4gIC8vIGRlbGF5XG4gIGRlbGF5QW5pbWF0aW9uOiBmdW5jdGlvbiBkZWxheUFuaW1hdGlvbigpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gZGVsYXlBbmltYXRpb25JbXBsKHRpbWUsIGNvbXBsZXRlKSB7XG4gICAgICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5IHx8IHRoaXM7XG5cbiAgICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLmFuaW1hdGlvbih7XG4gICAgICAgIGRlbGF5OiB0aW1lLFxuICAgICAgICBkdXJhdGlvbjogdGltZSxcbiAgICAgICAgY29tcGxldGU6IGNvbXBsZXRlXG4gICAgICB9KTtcbiAgICB9O1xuICB9LFxuICAvLyBkZWxheVxuICBhbmltYXRpb246IGZ1bmN0aW9uIGFuaW1hdGlvbigpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gYW5pbWF0aW9uSW1wbChwcm9wZXJ0aWVzLCBwYXJhbXMpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHZhciBzZWxmSXNBcnJheUxpa2UgPSBzZWxmLmxlbmd0aCAhPT0gdW5kZWZpbmVkO1xuICAgICAgdmFyIGFsbCA9IHNlbGZJc0FycmF5TGlrZSA/IHNlbGYgOiBbc2VsZl07IC8vIHB1dCBpbiBhcnJheSBpZiBub3QgYXJyYXktbGlrZVxuXG4gICAgICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5IHx8IHRoaXM7XG4gICAgICB2YXIgaXNDb3JlID0gIXNlbGZJc0FycmF5TGlrZTtcbiAgICAgIHZhciBpc0VsZXMgPSAhaXNDb3JlO1xuXG4gICAgICBpZiAoIWN5LnN0eWxlRW5hYmxlZCgpKSB7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICB2YXIgc3R5bGUgPSBjeS5zdHlsZSgpO1xuICAgICAgcHJvcGVydGllcyA9IGV4dGVuZCh7fSwgcHJvcGVydGllcywgcGFyYW1zKTtcbiAgICAgIHZhciBwcm9wZXJ0aWVzRW1wdHkgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKS5sZW5ndGggPT09IDA7XG5cbiAgICAgIGlmIChwcm9wZXJ0aWVzRW1wdHkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBBbmltYXRpb24oYWxsWzBdLCBwcm9wZXJ0aWVzKTsgLy8gbm90aGluZyB0byBhbmltYXRlXG4gICAgICB9XG5cbiAgICAgIGlmIChwcm9wZXJ0aWVzLmR1cmF0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcHJvcGVydGllcy5kdXJhdGlvbiA9IDQwMDtcbiAgICAgIH1cblxuICAgICAgc3dpdGNoIChwcm9wZXJ0aWVzLmR1cmF0aW9uKSB7XG4gICAgICAgIGNhc2UgJ3Nsb3cnOlxuICAgICAgICAgIHByb3BlcnRpZXMuZHVyYXRpb24gPSA2MDA7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnZmFzdCc6XG4gICAgICAgICAgcHJvcGVydGllcy5kdXJhdGlvbiA9IDIwMDtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRWxlcykge1xuICAgICAgICBwcm9wZXJ0aWVzLnN0eWxlID0gc3R5bGUuZ2V0UHJvcHNMaXN0KHByb3BlcnRpZXMuc3R5bGUgfHwgcHJvcGVydGllcy5jc3MpO1xuICAgICAgICBwcm9wZXJ0aWVzLmNzcyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRWxlcyAmJiBwcm9wZXJ0aWVzLnJlbmRlcmVkUG9zaXRpb24gIT0gbnVsbCkge1xuICAgICAgICB2YXIgcnBvcyA9IHByb3BlcnRpZXMucmVuZGVyZWRQb3NpdGlvbjtcbiAgICAgICAgdmFyIHBhbiA9IGN5LnBhbigpO1xuICAgICAgICB2YXIgem9vbSA9IGN5Lnpvb20oKTtcbiAgICAgICAgcHJvcGVydGllcy5wb3NpdGlvbiA9IHJlbmRlcmVkVG9Nb2RlbFBvc2l0aW9uKHJwb3MsIHpvb20sIHBhbik7XG4gICAgICB9IC8vIG92ZXJyaWRlIHBhbiB3LyBwYW5CeSBpZiBzZXRcblxuXG4gICAgICBpZiAoaXNDb3JlICYmIHByb3BlcnRpZXMucGFuQnkgIT0gbnVsbCkge1xuICAgICAgICB2YXIgcGFuQnkgPSBwcm9wZXJ0aWVzLnBhbkJ5O1xuICAgICAgICB2YXIgY3lQYW4gPSBjeS5wYW4oKTtcbiAgICAgICAgcHJvcGVydGllcy5wYW4gPSB7XG4gICAgICAgICAgeDogY3lQYW4ueCArIHBhbkJ5LngsXG4gICAgICAgICAgeTogY3lQYW4ueSArIHBhbkJ5LnlcbiAgICAgICAgfTtcbiAgICAgIH0gLy8gb3ZlcnJpZGUgcGFuIHcvIGNlbnRlciBpZiBzZXRcblxuXG4gICAgICB2YXIgY2VudGVyID0gcHJvcGVydGllcy5jZW50ZXIgfHwgcHJvcGVydGllcy5jZW50cmU7XG5cbiAgICAgIGlmIChpc0NvcmUgJiYgY2VudGVyICE9IG51bGwpIHtcbiAgICAgICAgdmFyIGNlbnRlclBhbiA9IGN5LmdldENlbnRlclBhbihjZW50ZXIuZWxlcywgcHJvcGVydGllcy56b29tKTtcblxuICAgICAgICBpZiAoY2VudGVyUGFuICE9IG51bGwpIHtcbiAgICAgICAgICBwcm9wZXJ0aWVzLnBhbiA9IGNlbnRlclBhbjtcbiAgICAgICAgfVxuICAgICAgfSAvLyBvdmVycmlkZSBwYW4gJiB6b29tIHcvIGZpdCBpZiBzZXRcblxuXG4gICAgICBpZiAoaXNDb3JlICYmIHByb3BlcnRpZXMuZml0ICE9IG51bGwpIHtcbiAgICAgICAgdmFyIGZpdCA9IHByb3BlcnRpZXMuZml0O1xuICAgICAgICB2YXIgZml0VnAgPSBjeS5nZXRGaXRWaWV3cG9ydChmaXQuZWxlcyB8fCBmaXQuYm91bmRpbmdCb3gsIGZpdC5wYWRkaW5nKTtcblxuICAgICAgICBpZiAoZml0VnAgIT0gbnVsbCkge1xuICAgICAgICAgIHByb3BlcnRpZXMucGFuID0gZml0VnAucGFuO1xuICAgICAgICAgIHByb3BlcnRpZXMuem9vbSA9IGZpdFZwLnpvb207XG4gICAgICAgIH1cbiAgICAgIH0gLy8gb3ZlcnJpZGUgem9vbSAoJiBwb3RlbnRpYWxseSBwYW4pIHcvIHpvb20gb2JqIGlmIHNldFxuXG5cbiAgICAgIGlmIChpc0NvcmUgJiYgcGxhaW5PYmplY3QocHJvcGVydGllcy56b29tKSkge1xuICAgICAgICB2YXIgdnAgPSBjeS5nZXRab29tZWRWaWV3cG9ydChwcm9wZXJ0aWVzLnpvb20pO1xuXG4gICAgICAgIGlmICh2cCAhPSBudWxsKSB7XG4gICAgICAgICAgaWYgKHZwLnpvb21lZCkge1xuICAgICAgICAgICAgcHJvcGVydGllcy56b29tID0gdnAuem9vbTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodnAucGFubmVkKSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLnBhbiA9IHZwLnBhbjtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcHJvcGVydGllcy56b29tID0gbnVsbDsgLy8gYW4gaW5hdmFsaWQgem9vbSAoZS5nLiBubyBkZWx0YSkgZ2V0cyBhdXRvbWF0aWNhbGx5IGRlc3Ryb3llZFxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXcgQW5pbWF0aW9uKGFsbFswXSwgcHJvcGVydGllcyk7XG4gICAgfTtcbiAgfSxcbiAgLy8gYW5pbWF0ZVxuICBhbmltYXRlOiBmdW5jdGlvbiBhbmltYXRlKCkge1xuICAgIHJldHVybiBmdW5jdGlvbiBhbmltYXRlSW1wbChwcm9wZXJ0aWVzLCBwYXJhbXMpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHZhciBzZWxmSXNBcnJheUxpa2UgPSBzZWxmLmxlbmd0aCAhPT0gdW5kZWZpbmVkO1xuICAgICAgdmFyIGFsbCA9IHNlbGZJc0FycmF5TGlrZSA/IHNlbGYgOiBbc2VsZl07IC8vIHB1dCBpbiBhcnJheSBpZiBub3QgYXJyYXktbGlrZVxuXG4gICAgICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5IHx8IHRoaXM7XG5cbiAgICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMpIHtcbiAgICAgICAgcHJvcGVydGllcyA9IGV4dGVuZCh7fSwgcHJvcGVydGllcywgcGFyYW1zKTtcbiAgICAgIH0gLy8gbWFudWFsbHkgaG9vayBhbmQgcnVuIHRoZSBhbmltYXRpb25cblxuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFsbC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWxlID0gYWxsW2ldO1xuICAgICAgICB2YXIgcXVldWUgPSBlbGUuYW5pbWF0ZWQoKSAmJiAocHJvcGVydGllcy5xdWV1ZSA9PT0gdW5kZWZpbmVkIHx8IHByb3BlcnRpZXMucXVldWUpO1xuICAgICAgICB2YXIgYW5pID0gZWxlLmFuaW1hdGlvbihwcm9wZXJ0aWVzLCBxdWV1ZSA/IHtcbiAgICAgICAgICBxdWV1ZTogdHJ1ZVxuICAgICAgICB9IDogdW5kZWZpbmVkKTtcbiAgICAgICAgYW5pLnBsYXkoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gICAgfTtcbiAgfSxcbiAgLy8gYW5pbWF0ZVxuICBzdG9wOiBmdW5jdGlvbiBzdG9wKCkge1xuICAgIHJldHVybiBmdW5jdGlvbiBzdG9wSW1wbChjbGVhclF1ZXVlLCBqdW1wVG9FbmQpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHZhciBzZWxmSXNBcnJheUxpa2UgPSBzZWxmLmxlbmd0aCAhPT0gdW5kZWZpbmVkO1xuICAgICAgdmFyIGFsbCA9IHNlbGZJc0FycmF5TGlrZSA/IHNlbGYgOiBbc2VsZl07IC8vIHB1dCBpbiBhcnJheSBpZiBub3QgYXJyYXktbGlrZVxuXG4gICAgICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5IHx8IHRoaXM7XG5cbiAgICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYWxsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSBhbGxbaV07XG4gICAgICAgIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgICAgICAgdmFyIGFuaXMgPSBfcC5hbmltYXRpb24uY3VycmVudDtcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGFuaXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICB2YXIgYW5pID0gYW5pc1tqXTtcbiAgICAgICAgICB2YXIgYW5pX3AgPSBhbmkuX3ByaXZhdGU7XG5cbiAgICAgICAgICBpZiAoanVtcFRvRW5kKSB7XG4gICAgICAgICAgICAvLyBuZXh0IGl0ZXJhdGlvbiBvZiB0aGUgYW5pbWF0aW9uIGxvb3AsIHRoZSBhbmltYXRpb25cbiAgICAgICAgICAgIC8vIHdpbGwgZ28gc3RyYWlnaHQgdG8gdGhlIGVuZCBhbmQgYmUgcmVtb3ZlZFxuICAgICAgICAgICAgYW5pX3AuZHVyYXRpb24gPSAwO1xuICAgICAgICAgIH1cbiAgICAgICAgfSAvLyBjbGVhciB0aGUgcXVldWUgb2YgZnV0dXJlIGFuaW1hdGlvbnNcblxuXG4gICAgICAgIGlmIChjbGVhclF1ZXVlKSB7XG4gICAgICAgICAgX3AuYW5pbWF0aW9uLnF1ZXVlID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWp1bXBUb0VuZCkge1xuICAgICAgICAgIF9wLmFuaW1hdGlvbi5jdXJyZW50ID0gW107XG4gICAgICAgIH1cbiAgICAgIH0gLy8gd2UgaGF2ZSB0byBub3RpZnkgKHRoZSBhbmltYXRpb24gbG9vcCBkb2Vzbid0IGRvIGl0IGZvciB1cyBvbiBgc3RvcGApXG5cblxuICAgICAgY3kubm90aWZ5KCdkcmF3Jyk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICB9IC8vIHN0b3BcblxufTsgLy8gZGVmaW5lXG5cbnZhciBkZWZpbmUkMSA9IHtcbiAgLy8gYWNjZXNzIGRhdGEgZmllbGRcbiAgZGF0YTogZnVuY3Rpb24gZGF0YShwYXJhbXMpIHtcbiAgICB2YXIgZGVmYXVsdHMgPSB7XG4gICAgICBmaWVsZDogJ2RhdGEnLFxuICAgICAgYmluZGluZ0V2ZW50OiAnZGF0YScsXG4gICAgICBhbGxvd0JpbmRpbmc6IGZhbHNlLFxuICAgICAgYWxsb3dTZXR0aW5nOiBmYWxzZSxcbiAgICAgIGFsbG93R2V0dGluZzogZmFsc2UsXG4gICAgICBzZXR0aW5nRXZlbnQ6ICdkYXRhJyxcbiAgICAgIHNldHRpbmdUcmlnZ2Vyc0V2ZW50OiBmYWxzZSxcbiAgICAgIHRyaWdnZXJGbk5hbWU6ICd0cmlnZ2VyJyxcbiAgICAgIGltbXV0YWJsZUtleXM6IHt9LFxuICAgICAgLy8ga2V5ID0+IHRydWUgaWYgaW1tdXRhYmxlXG4gICAgICB1cGRhdGVTdHlsZTogZmFsc2UsXG4gICAgICBiZWZvcmVHZXQ6IGZ1bmN0aW9uIGJlZm9yZUdldChzZWxmKSB7fSxcbiAgICAgIGJlZm9yZVNldDogZnVuY3Rpb24gYmVmb3JlU2V0KHNlbGYsIG9iaikge30sXG4gICAgICBvblNldDogZnVuY3Rpb24gb25TZXQoc2VsZikge30sXG4gICAgICBjYW5TZXQ6IGZ1bmN0aW9uIGNhblNldChzZWxmKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH07XG4gICAgcGFyYW1zID0gZXh0ZW5kKHt9LCBkZWZhdWx0cywgcGFyYW1zKTtcbiAgICByZXR1cm4gZnVuY3Rpb24gZGF0YUltcGwobmFtZSwgdmFsdWUpIHtcbiAgICAgIHZhciBwID0gcGFyYW1zO1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgdmFyIHNlbGZJc0FycmF5TGlrZSA9IHNlbGYubGVuZ3RoICE9PSB1bmRlZmluZWQ7XG4gICAgICB2YXIgYWxsID0gc2VsZklzQXJyYXlMaWtlID8gc2VsZiA6IFtzZWxmXTsgLy8gcHV0IGluIGFycmF5IGlmIG5vdCBhcnJheS1saWtlXG5cbiAgICAgIHZhciBzaW5nbGUgPSBzZWxmSXNBcnJheUxpa2UgPyBzZWxmWzBdIDogc2VsZjsgLy8gLmRhdGEoJ2ZvbycsIC4uLilcblxuICAgICAgaWYgKHN0cmluZyhuYW1lKSkge1xuICAgICAgICAvLyBzZXQgb3IgZ2V0IHByb3BlcnR5XG4gICAgICAgIC8vIC5kYXRhKCdmb28nKVxuICAgICAgICBpZiAocC5hbGxvd0dldHRpbmcgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIC8vIGdldFxuICAgICAgICAgIHZhciByZXQ7XG5cbiAgICAgICAgICBpZiAoc2luZ2xlKSB7XG4gICAgICAgICAgICBwLmJlZm9yZUdldChzaW5nbGUpO1xuICAgICAgICAgICAgcmV0ID0gc2luZ2xlLl9wcml2YXRlW3AuZmllbGRdW25hbWVdO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiByZXQ7IC8vIC5kYXRhKCdmb28nLCAnYmFyJylcbiAgICAgICAgfSBlbHNlIGlmIChwLmFsbG93U2V0dGluZyAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgLy8gc2V0XG4gICAgICAgICAgdmFyIHZhbGlkID0gIXAuaW1tdXRhYmxlS2V5c1tuYW1lXTtcblxuICAgICAgICAgIGlmICh2YWxpZCkge1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IF9kZWZpbmVQcm9wZXJ0eSh7fSwgbmFtZSwgdmFsdWUpO1xuXG4gICAgICAgICAgICBwLmJlZm9yZVNldChzZWxmLCBjaGFuZ2UpO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFsbC5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgdmFyIGVsZSA9IGFsbFtpXTtcblxuICAgICAgICAgICAgICBpZiAocC5jYW5TZXQoZWxlKSkge1xuICAgICAgICAgICAgICAgIGVsZS5fcHJpdmF0ZVtwLmZpZWxkXVtuYW1lXSA9IHZhbHVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IC8vIHVwZGF0ZSBtYXBwZXJzIGlmIGFza2VkXG5cblxuICAgICAgICAgICAgaWYgKHAudXBkYXRlU3R5bGUpIHtcbiAgICAgICAgICAgICAgc2VsZi51cGRhdGVTdHlsZSgpO1xuICAgICAgICAgICAgfSAvLyBjYWxsIG9uU2V0IGNhbGxiYWNrXG5cblxuICAgICAgICAgICAgcC5vblNldChzZWxmKTtcblxuICAgICAgICAgICAgaWYgKHAuc2V0dGluZ1RyaWdnZXJzRXZlbnQpIHtcbiAgICAgICAgICAgICAgc2VsZltwLnRyaWdnZXJGbk5hbWVdKHAuc2V0dGluZ0V2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gLmRhdGEoeyAnZm9vJzogJ2JhcicgfSlcblxuICAgICAgfSBlbHNlIGlmIChwLmFsbG93U2V0dGluZyAmJiBwbGFpbk9iamVjdChuYW1lKSkge1xuICAgICAgICAvLyBleHRlbmRcbiAgICAgICAgdmFyIG9iaiA9IG5hbWU7XG4gICAgICAgIHZhciBrLCB2O1xuICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG4gICAgICAgIHAuYmVmb3JlU2V0KHNlbGYsIG9iaik7XG5cbiAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGtleXMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgayA9IGtleXNbX2ldO1xuICAgICAgICAgIHYgPSBvYmpba107XG5cbiAgICAgICAgICB2YXIgX3ZhbGlkID0gIXAuaW1tdXRhYmxlS2V5c1trXTtcblxuICAgICAgICAgIGlmIChfdmFsaWQpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYWxsLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgIHZhciBfZWxlID0gYWxsW2pdO1xuXG4gICAgICAgICAgICAgIGlmIChwLmNhblNldChfZWxlKSkge1xuICAgICAgICAgICAgICAgIF9lbGUuX3ByaXZhdGVbcC5maWVsZF1ba10gPSB2O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIHVwZGF0ZSBtYXBwZXJzIGlmIGFza2VkXG5cblxuICAgICAgICBpZiAocC51cGRhdGVTdHlsZSkge1xuICAgICAgICAgIHNlbGYudXBkYXRlU3R5bGUoKTtcbiAgICAgICAgfSAvLyBjYWxsIG9uU2V0IGNhbGxiYWNrXG5cblxuICAgICAgICBwLm9uU2V0KHNlbGYpO1xuXG4gICAgICAgIGlmIChwLnNldHRpbmdUcmlnZ2Vyc0V2ZW50KSB7XG4gICAgICAgICAgc2VsZltwLnRyaWdnZXJGbk5hbWVdKHAuc2V0dGluZ0V2ZW50KTtcbiAgICAgICAgfSAvLyAuZGF0YShmdW5jdGlvbigpeyAuLi4gfSlcblxuICAgICAgfSBlbHNlIGlmIChwLmFsbG93QmluZGluZyAmJiBmbihuYW1lKSkge1xuICAgICAgICAvLyBiaW5kIHRvIGV2ZW50XG4gICAgICAgIHZhciBmbiQxID0gbmFtZTtcbiAgICAgICAgc2VsZi5vbihwLmJpbmRpbmdFdmVudCwgZm4kMSk7IC8vIC5kYXRhKClcbiAgICAgIH0gZWxzZSBpZiAocC5hbGxvd0dldHRpbmcgJiYgbmFtZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIGdldCB3aG9sZSBvYmplY3RcbiAgICAgICAgdmFyIF9yZXQ7XG5cbiAgICAgICAgaWYgKHNpbmdsZSkge1xuICAgICAgICAgIHAuYmVmb3JlR2V0KHNpbmdsZSk7XG4gICAgICAgICAgX3JldCA9IHNpbmdsZS5fcHJpdmF0ZVtwLmZpZWxkXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBfcmV0O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VsZjsgLy8gbWFpbnRhaW4gY2hhaW5hYmlsaXR5XG4gICAgfTsgLy8gZnVuY3Rpb25cbiAgfSxcbiAgLy8gZGF0YVxuICAvLyByZW1vdmUgZGF0YSBmaWVsZFxuICByZW1vdmVEYXRhOiBmdW5jdGlvbiByZW1vdmVEYXRhKHBhcmFtcykge1xuICAgIHZhciBkZWZhdWx0cyA9IHtcbiAgICAgIGZpZWxkOiAnZGF0YScsXG4gICAgICBldmVudDogJ2RhdGEnLFxuICAgICAgdHJpZ2dlckZuTmFtZTogJ3RyaWdnZXInLFxuICAgICAgdHJpZ2dlckV2ZW50OiBmYWxzZSxcbiAgICAgIGltbXV0YWJsZUtleXM6IHt9IC8vIGtleSA9PiB0cnVlIGlmIGltbXV0YWJsZVxuXG4gICAgfTtcbiAgICBwYXJhbXMgPSBleHRlbmQoe30sIGRlZmF1bHRzLCBwYXJhbXMpO1xuICAgIHJldHVybiBmdW5jdGlvbiByZW1vdmVEYXRhSW1wbChuYW1lcykge1xuICAgICAgdmFyIHAgPSBwYXJhbXM7XG4gICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICB2YXIgc2VsZklzQXJyYXlMaWtlID0gc2VsZi5sZW5ndGggIT09IHVuZGVmaW5lZDtcbiAgICAgIHZhciBhbGwgPSBzZWxmSXNBcnJheUxpa2UgPyBzZWxmIDogW3NlbGZdOyAvLyBwdXQgaW4gYXJyYXkgaWYgbm90IGFycmF5LWxpa2VcbiAgICAgIC8vIC5yZW1vdmVEYXRhKCdmb28gYmFyJylcblxuICAgICAgaWYgKHN0cmluZyhuYW1lcykpIHtcbiAgICAgICAgLy8gdGhlbiBnZXQgdGhlIGxpc3Qgb2Yga2V5cywgYW5kIGRlbGV0ZSB0aGVtXG4gICAgICAgIHZhciBrZXlzID0gbmFtZXMuc3BsaXQoL1xccysvKTtcbiAgICAgICAgdmFyIGwgPSBrZXlzLmxlbmd0aDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgIC8vIGRlbGV0ZSBlYWNoIG5vbi1lbXB0eSBrZXlcbiAgICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTtcblxuICAgICAgICAgIGlmIChlbXB0eVN0cmluZyhrZXkpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgdmFsaWQgPSAhcC5pbW11dGFibGVLZXlzW2tleV07IC8vIG5vdCB2YWxpZCBpZiBpbW11dGFibGVcblxuICAgICAgICAgIGlmICh2YWxpZCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaV9hID0gMCwgbF9hID0gYWxsLmxlbmd0aDsgaV9hIDwgbF9hOyBpX2ErKykge1xuICAgICAgICAgICAgICBhbGxbaV9hXS5fcHJpdmF0ZVtwLmZpZWxkXVtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwLnRyaWdnZXJFdmVudCkge1xuICAgICAgICAgIHNlbGZbcC50cmlnZ2VyRm5OYW1lXShwLmV2ZW50KTtcbiAgICAgICAgfSAvLyAucmVtb3ZlRGF0YSgpXG5cbiAgICAgIH0gZWxzZSBpZiAobmFtZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyB0aGVuIGRlbGV0ZSBhbGwga2V5c1xuICAgICAgICBmb3IgKHZhciBfaV9hID0gMCwgX2xfYSA9IGFsbC5sZW5ndGg7IF9pX2EgPCBfbF9hOyBfaV9hKyspIHtcbiAgICAgICAgICB2YXIgX3ByaXZhdGVGaWVsZHMgPSBhbGxbX2lfYV0uX3ByaXZhdGVbcC5maWVsZF07XG5cbiAgICAgICAgICB2YXIgX2tleXMgPSBPYmplY3Qua2V5cyhfcHJpdmF0ZUZpZWxkcyk7XG5cbiAgICAgICAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBfa2V5cy5sZW5ndGg7IF9pMisrKSB7XG4gICAgICAgICAgICB2YXIgX2tleSA9IF9rZXlzW19pMl07XG4gICAgICAgICAgICB2YXIgdmFsaWRLZXlUb0RlbGV0ZSA9ICFwLmltbXV0YWJsZUtleXNbX2tleV07XG5cbiAgICAgICAgICAgIGlmICh2YWxpZEtleVRvRGVsZXRlKSB7XG4gICAgICAgICAgICAgIF9wcml2YXRlRmllbGRzW19rZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwLnRyaWdnZXJFdmVudCkge1xuICAgICAgICAgIHNlbGZbcC50cmlnZ2VyRm5OYW1lXShwLmV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VsZjsgLy8gbWFpbnRhaW4gY2hhaW5pbmdcbiAgICB9OyAvLyBmdW5jdGlvblxuICB9IC8vIHJlbW92ZURhdGFcblxufTsgLy8gZGVmaW5lXG5cbnZhciBkZWZpbmUkMiA9IHtcbiAgZXZlbnRBbGlhc2VzT246IGZ1bmN0aW9uIGV2ZW50QWxpYXNlc09uKHByb3RvKSB7XG4gICAgdmFyIHAgPSBwcm90bztcbiAgICBwLmFkZExpc3RlbmVyID0gcC5saXN0ZW4gPSBwLmJpbmQgPSBwLm9uO1xuICAgIHAudW5saXN0ZW4gPSBwLnVuYmluZCA9IHAub2ZmID0gcC5yZW1vdmVMaXN0ZW5lcjtcbiAgICBwLnRyaWdnZXIgPSBwLmVtaXQ7IC8vIHRoaXMgaXMganVzdCBhIHdyYXBwZXIgYWxpYXMgb2YgLm9uKClcblxuICAgIHAucG9uID0gcC5wcm9taXNlT24gPSBmdW5jdGlvbiAoZXZlbnRzLCBzZWxlY3Rvcikge1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlJDEoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICB2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbiBjYWxsYmFjayhlKSB7XG4gICAgICAgICAgc2VsZi5vZmYuYXBwbHkoc2VsZiwgb2ZmQXJncyk7XG4gICAgICAgICAgcmVzb2x2ZShlKTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25BcmdzID0gYXJncy5jb25jYXQoW2NhbGxiYWNrXSk7XG4gICAgICAgIHZhciBvZmZBcmdzID0gb25BcmdzLmNvbmNhdChbXSk7XG4gICAgICAgIHNlbGYub24uYXBwbHkoc2VsZiwgb25BcmdzKTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cbn07IC8vIGRlZmluZVxuXG4vLyB1c2UgdGhpcyBtb2R1bGUgdG8gY2hlcnJ5IHBpY2sgZnVuY3Rpb25zIGludG8geW91ciBwcm90b3R5cGVcbnZhciBkZWZpbmUkMyA9IHt9O1xuW2RlZmluZSwgZGVmaW5lJDEsIGRlZmluZSQyXS5mb3JFYWNoKGZ1bmN0aW9uIChtKSB7XG4gIGV4dGVuZChkZWZpbmUkMywgbSk7XG59KTtcblxudmFyIGVsZXNmbiRkID0ge1xuICBhbmltYXRlOiBkZWZpbmUkMy5hbmltYXRlKCksXG4gIGFuaW1hdGlvbjogZGVmaW5lJDMuYW5pbWF0aW9uKCksXG4gIGFuaW1hdGVkOiBkZWZpbmUkMy5hbmltYXRlZCgpLFxuICBjbGVhclF1ZXVlOiBkZWZpbmUkMy5jbGVhclF1ZXVlKCksXG4gIGRlbGF5OiBkZWZpbmUkMy5kZWxheSgpLFxuICBkZWxheUFuaW1hdGlvbjogZGVmaW5lJDMuZGVsYXlBbmltYXRpb24oKSxcbiAgc3RvcDogZGVmaW5lJDMuc3RvcCgpXG59O1xuXG52YXIgZWxlc2ZuJGUgPSB7XG4gIGNsYXNzZXM6IGZ1bmN0aW9uIGNsYXNzZXMoX2NsYXNzZXMpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBpZiAoX2NsYXNzZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdmFyIHJldCA9IFtdO1xuXG4gICAgICBzZWxmWzBdLl9wcml2YXRlLmNsYXNzZXMuZm9yRWFjaChmdW5jdGlvbiAoY2xzKSB7XG4gICAgICAgIHJldHVybiByZXQucHVzaChjbHMpO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiByZXQ7XG4gICAgfSBlbHNlIGlmICghYXJyYXkoX2NsYXNzZXMpKSB7XG4gICAgICAvLyBleHRyYWN0IGNsYXNzZXMgZnJvbSBzdHJpbmdcbiAgICAgIF9jbGFzc2VzID0gKF9jbGFzc2VzIHx8ICcnKS5tYXRjaCgvXFxTKy9nKSB8fCBbXTtcbiAgICB9XG5cbiAgICB2YXIgY2hhbmdlZCA9IFtdO1xuICAgIHZhciBjbGFzc2VzU2V0ID0gbmV3IFNldCQxKF9jbGFzc2VzKTsgLy8gY2hlY2sgYW5kIHVwZGF0ZSBlYWNoIGVsZVxuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBzZWxmLmxlbmd0aDsgaisrKSB7XG4gICAgICB2YXIgZWxlID0gc2VsZltqXTtcbiAgICAgIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgICAgIHZhciBlbGVDbGFzc2VzID0gX3AuY2xhc3NlcztcbiAgICAgIHZhciBjaGFuZ2VkRWxlID0gZmFsc2U7IC8vIGNoZWNrIGlmIGVsZSBoYXMgYWxsIG9mIHRoZSBwYXNzZWQgY2xhc3Nlc1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IF9jbGFzc2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjbHMgPSBfY2xhc3Nlc1tpXTtcbiAgICAgICAgdmFyIGVsZUhhc0NsYXNzID0gZWxlQ2xhc3Nlcy5oYXMoY2xzKTtcblxuICAgICAgICBpZiAoIWVsZUhhc0NsYXNzKSB7XG4gICAgICAgICAgY2hhbmdlZEVsZSA9IHRydWU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gY2hlY2sgaWYgZWxlIGhhcyBjbGFzc2VzIG91dHNpZGUgb2YgdGhvc2UgcGFzc2VkXG5cblxuICAgICAgaWYgKCFjaGFuZ2VkRWxlKSB7XG4gICAgICAgIGNoYW5nZWRFbGUgPSBlbGVDbGFzc2VzLnNpemUgIT09IF9jbGFzc2VzLmxlbmd0aDtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYW5nZWRFbGUpIHtcbiAgICAgICAgX3AuY2xhc3NlcyA9IGNsYXNzZXNTZXQ7XG4gICAgICAgIGNoYW5nZWQucHVzaChlbGUpO1xuICAgICAgfVxuICAgIH0gLy8gdHJpZ2dlciB1cGRhdGUgc3R5bGUgb24gdGhvc2UgZWxlcyB0aGF0IGhhZCBjbGFzcyBjaGFuZ2VzXG5cblxuICAgIGlmIChjaGFuZ2VkLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc3Bhd24oY2hhbmdlZCkudXBkYXRlU3R5bGUoKS5lbWl0KCdjbGFzcycpO1xuICAgIH1cblxuICAgIHJldHVybiBzZWxmO1xuICB9LFxuICBhZGRDbGFzczogZnVuY3Rpb24gYWRkQ2xhc3MoY2xhc3Nlcykge1xuICAgIHJldHVybiB0aGlzLnRvZ2dsZUNsYXNzKGNsYXNzZXMsIHRydWUpO1xuICB9LFxuICBoYXNDbGFzczogZnVuY3Rpb24gaGFzQ2xhc3MoY2xhc3NOYW1lKSB7XG4gICAgdmFyIGVsZSA9IHRoaXNbMF07XG4gICAgcmV0dXJuIGVsZSAhPSBudWxsICYmIGVsZS5fcHJpdmF0ZS5jbGFzc2VzLmhhcyhjbGFzc05hbWUpO1xuICB9LFxuICB0b2dnbGVDbGFzczogZnVuY3Rpb24gdG9nZ2xlQ2xhc3MoY2xhc3NlcywgdG9nZ2xlKSB7XG4gICAgaWYgKCFhcnJheShjbGFzc2VzKSkge1xuICAgICAgLy8gZXh0cmFjdCBjbGFzc2VzIGZyb20gc3RyaW5nXG4gICAgICBjbGFzc2VzID0gY2xhc3Nlcy5tYXRjaCgvXFxTKy9nKSB8fCBbXTtcbiAgICB9XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIHRvZ2dsZVVuZGVmZCA9IHRvZ2dsZSA9PT0gdW5kZWZpbmVkO1xuICAgIHZhciBjaGFuZ2VkID0gW107IC8vIGVsZXMgd2hvIGhhZCBjbGFzc2VzIGNoYW5nZWRcblxuICAgIGZvciAodmFyIGkgPSAwLCBpbCA9IHNlbGYubGVuZ3RoOyBpIDwgaWw7IGkrKykge1xuICAgICAgdmFyIGVsZSA9IHNlbGZbaV07XG4gICAgICB2YXIgZWxlQ2xhc3NlcyA9IGVsZS5fcHJpdmF0ZS5jbGFzc2VzO1xuICAgICAgdmFyIGNoYW5nZWRFbGUgPSBmYWxzZTtcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjbGFzc2VzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBjbHMgPSBjbGFzc2VzW2pdO1xuICAgICAgICB2YXIgaGFzQ2xhc3MgPSBlbGVDbGFzc2VzLmhhcyhjbHMpO1xuICAgICAgICB2YXIgY2hhbmdlZE5vdyA9IGZhbHNlO1xuXG4gICAgICAgIGlmICh0b2dnbGUgfHwgdG9nZ2xlVW5kZWZkICYmICFoYXNDbGFzcykge1xuICAgICAgICAgIGVsZUNsYXNzZXMuYWRkKGNscyk7XG4gICAgICAgICAgY2hhbmdlZE5vdyA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRvZ2dsZSB8fCB0b2dnbGVVbmRlZmQgJiYgaGFzQ2xhc3MpIHtcbiAgICAgICAgICBlbGVDbGFzc2VzW1wiZGVsZXRlXCJdKGNscyk7XG4gICAgICAgICAgY2hhbmdlZE5vdyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWNoYW5nZWRFbGUgJiYgY2hhbmdlZE5vdykge1xuICAgICAgICAgIGNoYW5nZWQucHVzaChlbGUpO1xuICAgICAgICAgIGNoYW5nZWRFbGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9IC8vIGZvciBqIGNsYXNzZXNcblxuICAgIH0gLy8gZm9yIGkgZWxlc1xuICAgIC8vIHRyaWdnZXIgdXBkYXRlIHN0eWxlIG9uIHRob3NlIGVsZXMgdGhhdCBoYWQgY2xhc3MgY2hhbmdlc1xuXG5cbiAgICBpZiAoY2hhbmdlZC5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnNwYXduKGNoYW5nZWQpLnVwZGF0ZVN0eWxlKCkuZW1pdCgnY2xhc3MnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZjtcbiAgfSxcbiAgcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uIHJlbW92ZUNsYXNzKGNsYXNzZXMpIHtcbiAgICByZXR1cm4gdGhpcy50b2dnbGVDbGFzcyhjbGFzc2VzLCBmYWxzZSk7XG4gIH0sXG4gIGZsYXNoQ2xhc3M6IGZ1bmN0aW9uIGZsYXNoQ2xhc3MoY2xhc3NlcywgZHVyYXRpb24pIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBpZiAoZHVyYXRpb24gPT0gbnVsbCkge1xuICAgICAgZHVyYXRpb24gPSAyNTA7XG4gICAgfSBlbHNlIGlmIChkdXJhdGlvbiA9PT0gMCkge1xuICAgICAgcmV0dXJuIHNlbGY7IC8vIG5vdGhpbmcgdG8gZG8gcmVhbGx5XG4gICAgfVxuXG4gICAgc2VsZi5hZGRDbGFzcyhjbGFzc2VzKTtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYucmVtb3ZlQ2xhc3MoY2xhc3Nlcyk7XG4gICAgfSwgZHVyYXRpb24pO1xuICAgIHJldHVybiBzZWxmO1xuICB9XG59O1xuZWxlc2ZuJGUuY2xhc3NOYW1lID0gZWxlc2ZuJGUuY2xhc3NOYW1lcyA9IGVsZXNmbiRlLmNsYXNzZXM7XG5cbnZhciB0b2tlbnMgPSB7XG4gIG1ldGFDaGFyOiAnW1xcXFwhXFxcXFwiXFxcXCNcXFxcJFxcXFwlXFxcXCZcXFxcXFwnXFxcXChcXFxcKVxcXFwqXFxcXCtcXFxcLFxcXFwuXFxcXC9cXFxcOlxcXFw7XFxcXDxcXFxcPVxcXFw+XFxcXD9cXFxcQFxcXFxbXFxcXF1cXFxcXlxcXFxgXFxcXHtcXFxcfFxcXFx9XFxcXH5dJyxcbiAgLy8gY2hhcnMgd2UgbmVlZCB0byBlc2NhcGUgaW4gbGV0IG5hbWVzLCBldGNcbiAgY29tcGFyYXRvck9wOiAnPXxcXFxcIT18Pnw+PXw8fDw9fFxcXFwkPXxcXFxcXj18XFxcXCo9JyxcbiAgLy8gYmluYXJ5IGNvbXBhcmlzb24gb3AgKHVzZWQgaW4gZGF0YSBzZWxlY3RvcnMpXG4gIGJvb2xPcDogJ1xcXFw/fFxcXFwhfFxcXFxeJyxcbiAgLy8gYm9vbGVhbiAodW5hcnkpIG9wZXJhdG9ycyAodXNlZCBpbiBkYXRhIHNlbGVjdG9ycylcbiAgc3RyaW5nOiAnXCIoPzpcXFxcXFxcXFwifFteXCJdKSpcIicgKyAnfCcgKyBcIicoPzpcXFxcXFxcXCd8W14nXSkqJ1wiLFxuICAvLyBzdHJpbmcgbGl0ZXJhbHMgKHVzZWQgaW4gZGF0YSBzZWxlY3RvcnMpIC0tIGRvdWJsZXF1b3RlcyB8IHNpbmdsZXF1b3Rlc1xuICBudW1iZXI6IG51bWJlciQxLFxuICAvLyBudW1iZXIgbGl0ZXJhbCAodXNlZCBpbiBkYXRhIHNlbGVjdG9ycykgLS0tIGUuZy4gMC4xMjM0LCAxMjM0LCAxMmUxMjNcbiAgbWV0YTogJ2RlZ3JlZXxpbmRlZ3JlZXxvdXRkZWdyZWUnLFxuICAvLyBhbGxvd2VkIG1ldGFkYXRhIGZpZWxkcyAoaS5lLiBhbGxvd2VkIGZ1bmN0aW9ucyB0byB1c2UgZnJvbSBDb2xsZWN0aW9uKVxuICBzZXBhcmF0b3I6ICdcXFxccyosXFxcXHMqJyxcbiAgLy8gcXVlcmllcyBhcmUgc2VwYXJhdGVkIGJ5IGNvbW1hcywgZS5nLiBlZGdlW2ZvbyA9ICdiYXInXSwgbm9kZS5zb21lQ2xhc3NcbiAgZGVzY2VuZGFudDogJ1xcXFxzKycsXG4gIGNoaWxkOiAnXFxcXHMrPlxcXFxzKycsXG4gIHN1YmplY3Q6ICdcXFxcJCcsXG4gIGdyb3VwOiAnbm9kZXxlZGdlfFxcXFwqJyxcbiAgZGlyZWN0ZWRFZGdlOiAnXFxcXHMrLT5cXFxccysnLFxuICB1bmRpcmVjdGVkRWRnZTogJ1xcXFxzKzwtPlxcXFxzKydcbn07XG50b2tlbnMudmFyaWFibGUgPSAnKD86W1xcXFx3LV18KD86XFxcXFxcXFwnICsgdG9rZW5zLm1ldGFDaGFyICsgJykpKyc7IC8vIGEgdmFyaWFibGUgbmFtZVxuXG50b2tlbnMudmFsdWUgPSB0b2tlbnMuc3RyaW5nICsgJ3wnICsgdG9rZW5zLm51bWJlcjsgLy8gYSB2YWx1ZSBsaXRlcmFsLCBlaXRoZXIgYSBzdHJpbmcgb3IgbnVtYmVyXG5cbnRva2Vucy5jbGFzc05hbWUgPSB0b2tlbnMudmFyaWFibGU7IC8vIGEgY2xhc3MgbmFtZSAoZm9sbG93cyB2YXJpYWJsZSBjb252ZW50aW9ucylcblxudG9rZW5zLmlkID0gdG9rZW5zLnZhcmlhYmxlOyAvLyBhbiBlbGVtZW50IGlkIChmb2xsb3dzIHZhcmlhYmxlIGNvbnZlbnRpb25zKVxuXG4oZnVuY3Rpb24gKCkge1xuICB2YXIgb3BzLCBvcCwgaTsgLy8gYWRkIEAgdmFyaWFudHMgdG8gY29tcGFyYXRvck9wXG5cbiAgb3BzID0gdG9rZW5zLmNvbXBhcmF0b3JPcC5zcGxpdCgnfCcpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCBvcHMubGVuZ3RoOyBpKyspIHtcbiAgICBvcCA9IG9wc1tpXTtcbiAgICB0b2tlbnMuY29tcGFyYXRvck9wICs9ICd8QCcgKyBvcDtcbiAgfSAvLyBhZGQgISB2YXJpYW50cyB0byBjb21wYXJhdG9yT3BcblxuXG4gIG9wcyA9IHRva2Vucy5jb21wYXJhdG9yT3Auc3BsaXQoJ3wnKTtcblxuICBmb3IgKGkgPSAwOyBpIDwgb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgb3AgPSBvcHNbaV07XG5cbiAgICBpZiAob3AuaW5kZXhPZignIScpID49IDApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH0gLy8gc2tpcCBvcHMgdGhhdCBleHBsaWNpdGx5IGNvbnRhaW4gIVxuXG5cbiAgICBpZiAob3AgPT09ICc9Jykge1xuICAgICAgY29udGludWU7XG4gICAgfSAvLyBza2lwID0gYi9jICE9IGlzIGV4cGxpY2l0bHkgZGVmaW5lZFxuXG5cbiAgICB0b2tlbnMuY29tcGFyYXRvck9wICs9ICd8XFxcXCEnICsgb3A7XG4gIH1cbn0pKCk7XG5cbi8qKlxuICogTWFrZSBhIG5ldyBxdWVyeSBvYmplY3RcbiAqXG4gKiBAcHJvcCB0eXBlIHtUeXBlfSBUaGUgdHlwZSBlbnVtIChpbnQpIG9mIHRoZSBxdWVyeVxuICogQHByb3AgY2hlY2tzIExpc3Qgb2YgY2hlY2tzIHRvIG1ha2UgYWdhaW5zdCBhbiBlbGUgdG8gdGVzdCBmb3IgYSBtYXRjaFxuICovXG52YXIgbmV3UXVlcnkgPSBmdW5jdGlvbiBuZXdRdWVyeSgpIHtcbiAgcmV0dXJuIHtcbiAgICBjaGVja3M6IFtdXG4gIH07XG59O1xuXG4vKipcbiAqIEEgY2hlY2sgdHlwZSBlbnVtLWxpa2Ugb2JqZWN0LiAgVXNlcyBpbnRlZ2VyIHZhbHVlcyBmb3IgZmFzdCBtYXRjaCgpIGxvb2t1cC5cbiAqIFRoZSBvcmRlcmluZyBkb2VzIG5vdCBtYXR0ZXIgYXMgbG9uZyBhcyB0aGUgaW50cyBhcmUgdW5pcXVlLlxuICovXG52YXIgVHlwZSA9IHtcbiAgLyoqIEUuZy4gbm9kZSAqL1xuICBHUk9VUDogMCxcblxuICAvKiogQSBjb2xsZWN0aW9uIG9mIGVsZW1lbnRzICovXG4gIENPTExFQ1RJT046IDEsXG5cbiAgLyoqIEEgZmlsdGVyKGVsZSkgZnVuY3Rpb24gKi9cbiAgRklMVEVSOiAyLFxuXG4gIC8qKiBFLmcuIFtmb28gPiAxXSAqL1xuICBEQVRBX0NPTVBBUkU6IDMsXG5cbiAgLyoqIEUuZy4gW2Zvb10gKi9cbiAgREFUQV9FWElTVDogNCxcblxuICAvKiogRS5nLiBbP2Zvb10gKi9cbiAgREFUQV9CT09MOiA1LFxuXG4gIC8qKiBFLmcuIFtbZGVncmVlID4gMl1dICovXG4gIE1FVEFfQ09NUEFSRTogNixcblxuICAvKiogRS5nLiA6c2VsZWN0ZWQgKi9cbiAgU1RBVEU6IDcsXG5cbiAgLyoqIEUuZy4gI2ZvbyAqL1xuICBJRDogOCxcblxuICAvKiogRS5nLiAuZm9vICovXG4gIENMQVNTOiA5LFxuXG4gIC8qKiBFLmcuICNmb28gPC0+ICNiYXIgKi9cbiAgVU5ESVJFQ1RFRF9FREdFOiAxMCxcblxuICAvKiogRS5nLiAjZm9vIC0+ICNiYXIgKi9cbiAgRElSRUNURURfRURHRTogMTEsXG5cbiAgLyoqIEUuZy4gJCNmb28gLT4gI2JhciAqL1xuICBOT0RFX1NPVVJDRTogMTIsXG5cbiAgLyoqIEUuZy4gI2ZvbyAtPiAkI2JhciAqL1xuICBOT0RFX1RBUkdFVDogMTMsXG5cbiAgLyoqIEUuZy4gJCNmb28gPC0+ICNiYXIgKi9cbiAgTk9ERV9ORUlHSEJPUjogMTQsXG5cbiAgLyoqIEUuZy4gI2ZvbyA+ICNiYXIgKi9cbiAgQ0hJTEQ6IDE1LFxuXG4gIC8qKiBFLmcuICNmb28gI2JhciAqL1xuICBERVNDRU5EQU5UOiAxNixcblxuICAvKiogRS5nLiAkI2ZvbyA+ICNiYXIgKi9cbiAgUEFSRU5UOiAxNyxcblxuICAvKiogRS5nLiAkI2ZvbyAjYmFyICovXG4gIEFOQ0VTVE9SOiAxOCxcblxuICAvKiogRS5nLiAjZm9vID4gJGJhciA+ICNiYXogKi9cbiAgQ09NUE9VTkRfU1BMSVQ6IDE5LFxuXG4gIC8qKiBBbHdheXMgbWF0Y2hlcywgdXNlZnVsIHBsYWNlaG9sZGVyIGZvciBzdWJqZWN0IGluIGBDT01QT1VORF9TUExJVGAgKi9cbiAgVFJVRTogMjBcbn07XG5cbnZhciBzdGF0ZVNlbGVjdG9ycyA9IFt7XG4gIHNlbGVjdG9yOiAnOnNlbGVjdGVkJyxcbiAgbWF0Y2hlczogZnVuY3Rpb24gbWF0Y2hlcyhlbGUpIHtcbiAgICByZXR1cm4gZWxlLnNlbGVjdGVkKCk7XG4gIH1cbn0sIHtcbiAgc2VsZWN0b3I6ICc6dW5zZWxlY3RlZCcsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUuc2VsZWN0ZWQoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzpzZWxlY3RhYmxlJyxcbiAgbWF0Y2hlczogZnVuY3Rpb24gbWF0Y2hlcyhlbGUpIHtcbiAgICByZXR1cm4gZWxlLnNlbGVjdGFibGUoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzp1bnNlbGVjdGFibGUnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiAhZWxlLnNlbGVjdGFibGUoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzpsb2NrZWQnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUubG9ja2VkKCk7XG4gIH1cbn0sIHtcbiAgc2VsZWN0b3I6ICc6dW5sb2NrZWQnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiAhZWxlLmxvY2tlZCgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOnZpc2libGUnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUudmlzaWJsZSgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOmhpZGRlbicsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUudmlzaWJsZSgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOnRyYW5zcGFyZW50JyxcbiAgbWF0Y2hlczogZnVuY3Rpb24gbWF0Y2hlcyhlbGUpIHtcbiAgICByZXR1cm4gZWxlLnRyYW5zcGFyZW50KCk7XG4gIH1cbn0sIHtcbiAgc2VsZWN0b3I6ICc6Z3JhYmJlZCcsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5ncmFiYmVkKCk7XG4gIH1cbn0sIHtcbiAgc2VsZWN0b3I6ICc6ZnJlZScsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUuZ3JhYmJlZCgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOnJlbW92ZWQnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUucmVtb3ZlZCgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOmluc2lkZScsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUucmVtb3ZlZCgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOmdyYWJiYWJsZScsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5ncmFiYmFibGUoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzp1bmdyYWJiYWJsZScsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUuZ3JhYmJhYmxlKCk7XG4gIH1cbn0sIHtcbiAgc2VsZWN0b3I6ICc6YW5pbWF0ZWQnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUuYW5pbWF0ZWQoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzp1bmFuaW1hdGVkJyxcbiAgbWF0Y2hlczogZnVuY3Rpb24gbWF0Y2hlcyhlbGUpIHtcbiAgICByZXR1cm4gIWVsZS5hbmltYXRlZCgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOnBhcmVudCcsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5pc1BhcmVudCgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOmNoaWxkbGVzcycsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5pc0NoaWxkbGVzcygpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOmNoaWxkJyxcbiAgbWF0Y2hlczogZnVuY3Rpb24gbWF0Y2hlcyhlbGUpIHtcbiAgICByZXR1cm4gZWxlLmlzQ2hpbGQoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzpvcnBoYW4nLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUuaXNPcnBoYW4oKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzpub25vcnBoYW4nLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUuaXNDaGlsZCgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOmNvbXBvdW5kJyxcbiAgbWF0Y2hlczogZnVuY3Rpb24gbWF0Y2hlcyhlbGUpIHtcbiAgICBpZiAoZWxlLmlzTm9kZSgpKSB7XG4gICAgICByZXR1cm4gZWxlLmlzUGFyZW50KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBlbGUuc291cmNlKCkuaXNQYXJlbnQoKSB8fCBlbGUudGFyZ2V0KCkuaXNQYXJlbnQoKTtcbiAgICB9XG4gIH1cbn0sIHtcbiAgc2VsZWN0b3I6ICc6bG9vcCcsXG4gIG1hdGNoZXM6IGZ1bmN0aW9uIG1hdGNoZXMoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5pc0xvb3AoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzpzaW1wbGUnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUuaXNTaW1wbGUoKTtcbiAgfVxufSwge1xuICBzZWxlY3RvcjogJzphY3RpdmUnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUuYWN0aXZlKCk7XG4gIH1cbn0sIHtcbiAgc2VsZWN0b3I6ICc6aW5hY3RpdmUnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiAhZWxlLmFjdGl2ZSgpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOmJhY2tncm91bmRpbmcnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiBlbGUuYmFja2dyb3VuZGluZygpO1xuICB9XG59LCB7XG4gIHNlbGVjdG9yOiAnOm5vbmJhY2tncm91bmRpbmcnLFxuICBtYXRjaGVzOiBmdW5jdGlvbiBtYXRjaGVzKGVsZSkge1xuICAgIHJldHVybiAhZWxlLmJhY2tncm91bmRpbmcoKTtcbiAgfVxufV0uc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAvLyBuLmIuIHNlbGVjdG9ycyB0aGF0IGFyZSBzdGFydGluZyBzdWJzdHJpbmdzIG9mIG90aGVycyBtdXN0IGhhdmUgdGhlIGxvbmdlciBvbmVzIGZpcnN0XG4gIHJldHVybiBkZXNjZW5kaW5nKGEuc2VsZWN0b3IsIGIuc2VsZWN0b3IpO1xufSk7XG5cbnZhciBsb29rdXAgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBzZWxUb0ZuID0ge307XG4gIHZhciBzO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RhdGVTZWxlY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICBzID0gc3RhdGVTZWxlY3RvcnNbaV07XG4gICAgc2VsVG9GbltzLnNlbGVjdG9yXSA9IHMubWF0Y2hlcztcbiAgfVxuXG4gIHJldHVybiBzZWxUb0ZuO1xufSgpO1xuXG52YXIgc3RhdGVTZWxlY3Rvck1hdGNoZXMgPSBmdW5jdGlvbiBzdGF0ZVNlbGVjdG9yTWF0Y2hlcyhzZWwsIGVsZSkge1xuICByZXR1cm4gbG9va3VwW3NlbF0oZWxlKTtcbn07XG52YXIgc3RhdGVTZWxlY3RvclJlZ2V4ID0gJygnICsgc3RhdGVTZWxlY3RvcnMubWFwKGZ1bmN0aW9uIChzKSB7XG4gIHJldHVybiBzLnNlbGVjdG9yO1xufSkuam9pbignfCcpICsgJyknO1xuXG4vLyBzbyB0aGF0IHZhbHVlcyBnZXQgY29tcGFyZWQgcHJvcGVybHkgaW4gU2VsZWN0b3IuZmlsdGVyKClcblxudmFyIGNsZWFuTWV0YUNoYXJzID0gZnVuY3Rpb24gY2xlYW5NZXRhQ2hhcnMoc3RyKSB7XG4gIHJldHVybiBzdHIucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFxcXCgnICsgdG9rZW5zLm1ldGFDaGFyICsgJyknLCAnZycpLCBmdW5jdGlvbiAobWF0Y2gsICQxKSB7XG4gICAgcmV0dXJuICQxO1xuICB9KTtcbn07XG5cbnZhciByZXBsYWNlTGFzdFF1ZXJ5ID0gZnVuY3Rpb24gcmVwbGFjZUxhc3RRdWVyeShzZWxlY3RvciwgZXhhbWluaW5nUXVlcnksIHJlcGxhY2VtZW50UXVlcnkpIHtcbiAgc2VsZWN0b3Jbc2VsZWN0b3IubGVuZ3RoIC0gMV0gPSByZXBsYWNlbWVudFF1ZXJ5O1xufTsgLy8gTk9URTogYWRkIG5ldyBleHByZXNzaW9uIHN5bnRheCBoZXJlIHRvIGhhdmUgaXQgcmVjb2duaXNlZCBieSB0aGUgcGFyc2VyO1xuLy8gLSBhIHF1ZXJ5IGNvbnRhaW5zIGFsbCBhZGphY2VudCAoaS5lLiBubyBzZXBhcmF0b3IgaW4gYmV0d2VlbikgZXhwcmVzc2lvbnM7XG4vLyAtIHRoZSBjdXJyZW50IHF1ZXJ5IGlzIHN0b3JlZCBpbiBzZWxlY3RvcltpXVxuLy8gLSB5b3UgbmVlZCB0byBjaGVjayB0aGUgcXVlcnkgb2JqZWN0cyBpbiBtYXRjaCgpIGZvciBpdCBhY3R1YWxseSBmaWx0ZXIgcHJvcGVybHksIGJ1dCB0aGF0J3MgcHJldHR5IHN0cmFpZ2h0IGZvcndhcmRcblxuXG52YXIgZXhwcnMgPSBbe1xuICBuYW1lOiAnZ3JvdXAnLFxuICAvLyBqdXN0IHVzZWQgZm9yIGlkZW50aWZ5aW5nIHdoZW4gZGVidWdnaW5nXG4gIHF1ZXJ5OiB0cnVlLFxuICByZWdleDogJygnICsgdG9rZW5zLmdyb3VwICsgJyknLFxuICBwb3B1bGF0ZTogZnVuY3Rpb24gcG9wdWxhdGUoc2VsZWN0b3IsIHF1ZXJ5LCBfcmVmKSB7XG4gICAgdmFyIF9yZWYyID0gX3NsaWNlZFRvQXJyYXkoX3JlZiwgMSksXG4gICAgICAgIGdyb3VwID0gX3JlZjJbMF07XG5cbiAgICBxdWVyeS5jaGVja3MucHVzaCh7XG4gICAgICB0eXBlOiBUeXBlLkdST1VQLFxuICAgICAgdmFsdWU6IGdyb3VwID09PSAnKicgPyBncm91cCA6IGdyb3VwICsgJ3MnXG4gICAgfSk7XG4gIH1cbn0sIHtcbiAgbmFtZTogJ3N0YXRlJyxcbiAgcXVlcnk6IHRydWUsXG4gIHJlZ2V4OiBzdGF0ZVNlbGVjdG9yUmVnZXgsXG4gIHBvcHVsYXRlOiBmdW5jdGlvbiBwb3B1bGF0ZShzZWxlY3RvciwgcXVlcnksIF9yZWYzKSB7XG4gICAgdmFyIF9yZWY0ID0gX3NsaWNlZFRvQXJyYXkoX3JlZjMsIDEpLFxuICAgICAgICBzdGF0ZSA9IF9yZWY0WzBdO1xuXG4gICAgcXVlcnkuY2hlY2tzLnB1c2goe1xuICAgICAgdHlwZTogVHlwZS5TVEFURSxcbiAgICAgIHZhbHVlOiBzdGF0ZVxuICAgIH0pO1xuICB9XG59LCB7XG4gIG5hbWU6ICdpZCcsXG4gIHF1ZXJ5OiB0cnVlLFxuICByZWdleDogJ1xcXFwjKCcgKyB0b2tlbnMuaWQgKyAnKScsXG4gIHBvcHVsYXRlOiBmdW5jdGlvbiBwb3B1bGF0ZShzZWxlY3RvciwgcXVlcnksIF9yZWY1KSB7XG4gICAgdmFyIF9yZWY2ID0gX3NsaWNlZFRvQXJyYXkoX3JlZjUsIDEpLFxuICAgICAgICBpZCA9IF9yZWY2WzBdO1xuXG4gICAgcXVlcnkuY2hlY2tzLnB1c2goe1xuICAgICAgdHlwZTogVHlwZS5JRCxcbiAgICAgIHZhbHVlOiBjbGVhbk1ldGFDaGFycyhpZClcbiAgICB9KTtcbiAgfVxufSwge1xuICBuYW1lOiAnY2xhc3NOYW1lJyxcbiAgcXVlcnk6IHRydWUsXG4gIHJlZ2V4OiAnXFxcXC4oJyArIHRva2Vucy5jbGFzc05hbWUgKyAnKScsXG4gIHBvcHVsYXRlOiBmdW5jdGlvbiBwb3B1bGF0ZShzZWxlY3RvciwgcXVlcnksIF9yZWY3KSB7XG4gICAgdmFyIF9yZWY4ID0gX3NsaWNlZFRvQXJyYXkoX3JlZjcsIDEpLFxuICAgICAgICBjbGFzc05hbWUgPSBfcmVmOFswXTtcblxuICAgIHF1ZXJ5LmNoZWNrcy5wdXNoKHtcbiAgICAgIHR5cGU6IFR5cGUuQ0xBU1MsXG4gICAgICB2YWx1ZTogY2xlYW5NZXRhQ2hhcnMoY2xhc3NOYW1lKVxuICAgIH0pO1xuICB9XG59LCB7XG4gIG5hbWU6ICdkYXRhRXhpc3RzJyxcbiAgcXVlcnk6IHRydWUsXG4gIHJlZ2V4OiAnXFxcXFtcXFxccyooJyArIHRva2Vucy52YXJpYWJsZSArICcpXFxcXHMqXFxcXF0nLFxuICBwb3B1bGF0ZTogZnVuY3Rpb24gcG9wdWxhdGUoc2VsZWN0b3IsIHF1ZXJ5LCBfcmVmOSkge1xuICAgIHZhciBfcmVmMTAgPSBfc2xpY2VkVG9BcnJheShfcmVmOSwgMSksXG4gICAgICAgIHZhcmlhYmxlID0gX3JlZjEwWzBdO1xuXG4gICAgcXVlcnkuY2hlY2tzLnB1c2goe1xuICAgICAgdHlwZTogVHlwZS5EQVRBX0VYSVNULFxuICAgICAgZmllbGQ6IGNsZWFuTWV0YUNoYXJzKHZhcmlhYmxlKVxuICAgIH0pO1xuICB9XG59LCB7XG4gIG5hbWU6ICdkYXRhQ29tcGFyZScsXG4gIHF1ZXJ5OiB0cnVlLFxuICByZWdleDogJ1xcXFxbXFxcXHMqKCcgKyB0b2tlbnMudmFyaWFibGUgKyAnKVxcXFxzKignICsgdG9rZW5zLmNvbXBhcmF0b3JPcCArICcpXFxcXHMqKCcgKyB0b2tlbnMudmFsdWUgKyAnKVxcXFxzKlxcXFxdJyxcbiAgcG9wdWxhdGU6IGZ1bmN0aW9uIHBvcHVsYXRlKHNlbGVjdG9yLCBxdWVyeSwgX3JlZjExKSB7XG4gICAgdmFyIF9yZWYxMiA9IF9zbGljZWRUb0FycmF5KF9yZWYxMSwgMyksXG4gICAgICAgIHZhcmlhYmxlID0gX3JlZjEyWzBdLFxuICAgICAgICBjb21wYXJhdG9yT3AgPSBfcmVmMTJbMV0sXG4gICAgICAgIHZhbHVlID0gX3JlZjEyWzJdO1xuXG4gICAgdmFyIHZhbHVlSXNTdHJpbmcgPSBuZXcgUmVnRXhwKCdeJyArIHRva2Vucy5zdHJpbmcgKyAnJCcpLmV4ZWModmFsdWUpICE9IG51bGw7XG5cbiAgICBpZiAodmFsdWVJc1N0cmluZykge1xuICAgICAgdmFsdWUgPSB2YWx1ZS5zdWJzdHJpbmcoMSwgdmFsdWUubGVuZ3RoIC0gMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlID0gcGFyc2VGbG9hdCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgcXVlcnkuY2hlY2tzLnB1c2goe1xuICAgICAgdHlwZTogVHlwZS5EQVRBX0NPTVBBUkUsXG4gICAgICBmaWVsZDogY2xlYW5NZXRhQ2hhcnModmFyaWFibGUpLFxuICAgICAgb3BlcmF0b3I6IGNvbXBhcmF0b3JPcCxcbiAgICAgIHZhbHVlOiB2YWx1ZVxuICAgIH0pO1xuICB9XG59LCB7XG4gIG5hbWU6ICdkYXRhQm9vbCcsXG4gIHF1ZXJ5OiB0cnVlLFxuICByZWdleDogJ1xcXFxbXFxcXHMqKCcgKyB0b2tlbnMuYm9vbE9wICsgJylcXFxccyooJyArIHRva2Vucy52YXJpYWJsZSArICcpXFxcXHMqXFxcXF0nLFxuICBwb3B1bGF0ZTogZnVuY3Rpb24gcG9wdWxhdGUoc2VsZWN0b3IsIHF1ZXJ5LCBfcmVmMTMpIHtcbiAgICB2YXIgX3JlZjE0ID0gX3NsaWNlZFRvQXJyYXkoX3JlZjEzLCAyKSxcbiAgICAgICAgYm9vbE9wID0gX3JlZjE0WzBdLFxuICAgICAgICB2YXJpYWJsZSA9IF9yZWYxNFsxXTtcblxuICAgIHF1ZXJ5LmNoZWNrcy5wdXNoKHtcbiAgICAgIHR5cGU6IFR5cGUuREFUQV9CT09MLFxuICAgICAgZmllbGQ6IGNsZWFuTWV0YUNoYXJzKHZhcmlhYmxlKSxcbiAgICAgIG9wZXJhdG9yOiBib29sT3BcbiAgICB9KTtcbiAgfVxufSwge1xuICBuYW1lOiAnbWV0YUNvbXBhcmUnLFxuICBxdWVyeTogdHJ1ZSxcbiAgcmVnZXg6ICdcXFxcW1xcXFxbXFxcXHMqKCcgKyB0b2tlbnMubWV0YSArICcpXFxcXHMqKCcgKyB0b2tlbnMuY29tcGFyYXRvck9wICsgJylcXFxccyooJyArIHRva2Vucy5udW1iZXIgKyAnKVxcXFxzKlxcXFxdXFxcXF0nLFxuICBwb3B1bGF0ZTogZnVuY3Rpb24gcG9wdWxhdGUoc2VsZWN0b3IsIHF1ZXJ5LCBfcmVmMTUpIHtcbiAgICB2YXIgX3JlZjE2ID0gX3NsaWNlZFRvQXJyYXkoX3JlZjE1LCAzKSxcbiAgICAgICAgbWV0YSA9IF9yZWYxNlswXSxcbiAgICAgICAgY29tcGFyYXRvck9wID0gX3JlZjE2WzFdLFxuICAgICAgICBudW1iZXIgPSBfcmVmMTZbMl07XG5cbiAgICBxdWVyeS5jaGVja3MucHVzaCh7XG4gICAgICB0eXBlOiBUeXBlLk1FVEFfQ09NUEFSRSxcbiAgICAgIGZpZWxkOiBjbGVhbk1ldGFDaGFycyhtZXRhKSxcbiAgICAgIG9wZXJhdG9yOiBjb21wYXJhdG9yT3AsXG4gICAgICB2YWx1ZTogcGFyc2VGbG9hdChudW1iZXIpXG4gICAgfSk7XG4gIH1cbn0sIHtcbiAgbmFtZTogJ25leHRRdWVyeScsXG4gIHNlcGFyYXRvcjogdHJ1ZSxcbiAgcmVnZXg6IHRva2Vucy5zZXBhcmF0b3IsXG4gIHBvcHVsYXRlOiBmdW5jdGlvbiBwb3B1bGF0ZShzZWxlY3RvciwgcXVlcnkpIHtcbiAgICB2YXIgY3VycmVudFN1YmplY3QgPSBzZWxlY3Rvci5jdXJyZW50U3ViamVjdDtcbiAgICB2YXIgZWRnZUNvdW50ID0gc2VsZWN0b3IuZWRnZUNvdW50O1xuICAgIHZhciBjb21wb3VuZENvdW50ID0gc2VsZWN0b3IuY29tcG91bmRDb3VudDtcbiAgICB2YXIgbGFzdFEgPSBzZWxlY3RvcltzZWxlY3Rvci5sZW5ndGggLSAxXTtcblxuICAgIGlmIChjdXJyZW50U3ViamVjdCAhPSBudWxsKSB7XG4gICAgICBsYXN0US5zdWJqZWN0ID0gY3VycmVudFN1YmplY3Q7XG4gICAgICBzZWxlY3Rvci5jdXJyZW50U3ViamVjdCA9IG51bGw7XG4gICAgfVxuXG4gICAgbGFzdFEuZWRnZUNvdW50ID0gZWRnZUNvdW50O1xuICAgIGxhc3RRLmNvbXBvdW5kQ291bnQgPSBjb21wb3VuZENvdW50O1xuICAgIHNlbGVjdG9yLmVkZ2VDb3VudCA9IDA7XG4gICAgc2VsZWN0b3IuY29tcG91bmRDb3VudCA9IDA7IC8vIGdvIG9uIHRvIG5leHQgcXVlcnlcblxuICAgIHZhciBuZXh0UXVlcnkgPSBzZWxlY3RvcltzZWxlY3Rvci5sZW5ndGgrK10gPSBuZXdRdWVyeSgpO1xuICAgIHJldHVybiBuZXh0UXVlcnk7IC8vIHRoaXMgaXMgdGhlIG5ldyBxdWVyeSB0byBiZSBmaWxsZWQgYnkgdGhlIGZvbGxvd2luZyBleHByc1xuICB9XG59LCB7XG4gIG5hbWU6ICdkaXJlY3RlZEVkZ2UnLFxuICBzZXBhcmF0b3I6IHRydWUsXG4gIHJlZ2V4OiB0b2tlbnMuZGlyZWN0ZWRFZGdlLFxuICBwb3B1bGF0ZTogZnVuY3Rpb24gcG9wdWxhdGUoc2VsZWN0b3IsIHF1ZXJ5KSB7XG4gICAgaWYgKHNlbGVjdG9yLmN1cnJlbnRTdWJqZWN0ID09IG51bGwpIHtcbiAgICAgIC8vIHVuZGlyZWN0ZWQgZWRnZVxuICAgICAgdmFyIGVkZ2VRdWVyeSA9IG5ld1F1ZXJ5KCk7XG4gICAgICB2YXIgc291cmNlID0gcXVlcnk7XG4gICAgICB2YXIgdGFyZ2V0ID0gbmV3UXVlcnkoKTtcbiAgICAgIGVkZ2VRdWVyeS5jaGVja3MucHVzaCh7XG4gICAgICAgIHR5cGU6IFR5cGUuRElSRUNURURfRURHRSxcbiAgICAgICAgc291cmNlOiBzb3VyY2UsXG4gICAgICAgIHRhcmdldDogdGFyZ2V0XG4gICAgICB9KTsgLy8gdGhlIHF1ZXJ5IGluIHRoZSBzZWxlY3RvciBzaG91bGQgYmUgdGhlIGVkZ2UgcmF0aGVyIHRoYW4gdGhlIHNvdXJjZVxuXG4gICAgICByZXBsYWNlTGFzdFF1ZXJ5KHNlbGVjdG9yLCBxdWVyeSwgZWRnZVF1ZXJ5KTtcbiAgICAgIHNlbGVjdG9yLmVkZ2VDb3VudCsrOyAvLyB3ZSdyZSBub3cgcG9wdWxhdGluZyB0aGUgdGFyZ2V0IHF1ZXJ5IHdpdGggZXhwcmVzc2lvbnMgdGhhdCBmb2xsb3dcblxuICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gc291cmNlL3RhcmdldFxuICAgICAgdmFyIHNyY1RndFEgPSBuZXdRdWVyeSgpO1xuICAgICAgdmFyIF9zb3VyY2UgPSBxdWVyeTtcblxuICAgICAgdmFyIF90YXJnZXQgPSBuZXdRdWVyeSgpO1xuXG4gICAgICBzcmNUZ3RRLmNoZWNrcy5wdXNoKHtcbiAgICAgICAgdHlwZTogVHlwZS5OT0RFX1NPVVJDRSxcbiAgICAgICAgc291cmNlOiBfc291cmNlLFxuICAgICAgICB0YXJnZXQ6IF90YXJnZXRcbiAgICAgIH0pOyAvLyB0aGUgcXVlcnkgaW4gdGhlIHNlbGVjdG9yIHNob3VsZCBiZSB0aGUgbmVpZ2hib3VyaG9vZCByYXRoZXIgdGhhbiB0aGUgbm9kZVxuXG4gICAgICByZXBsYWNlTGFzdFF1ZXJ5KHNlbGVjdG9yLCBxdWVyeSwgc3JjVGd0USk7XG4gICAgICBzZWxlY3Rvci5lZGdlQ291bnQrKztcbiAgICAgIHJldHVybiBfdGFyZ2V0OyAvLyBub3cgcG9wdWxhdGluZyB0aGUgdGFyZ2V0IHdpdGggdGhlIGZvbGxvd2luZyBleHByZXNzaW9uc1xuICAgIH1cbiAgfVxufSwge1xuICBuYW1lOiAndW5kaXJlY3RlZEVkZ2UnLFxuICBzZXBhcmF0b3I6IHRydWUsXG4gIHJlZ2V4OiB0b2tlbnMudW5kaXJlY3RlZEVkZ2UsXG4gIHBvcHVsYXRlOiBmdW5jdGlvbiBwb3B1bGF0ZShzZWxlY3RvciwgcXVlcnkpIHtcbiAgICBpZiAoc2VsZWN0b3IuY3VycmVudFN1YmplY3QgPT0gbnVsbCkge1xuICAgICAgLy8gdW5kaXJlY3RlZCBlZGdlXG4gICAgICB2YXIgZWRnZVF1ZXJ5ID0gbmV3UXVlcnkoKTtcbiAgICAgIHZhciBzb3VyY2UgPSBxdWVyeTtcbiAgICAgIHZhciB0YXJnZXQgPSBuZXdRdWVyeSgpO1xuICAgICAgZWRnZVF1ZXJ5LmNoZWNrcy5wdXNoKHtcbiAgICAgICAgdHlwZTogVHlwZS5VTkRJUkVDVEVEX0VER0UsXG4gICAgICAgIG5vZGVzOiBbc291cmNlLCB0YXJnZXRdXG4gICAgICB9KTsgLy8gdGhlIHF1ZXJ5IGluIHRoZSBzZWxlY3RvciBzaG91bGQgYmUgdGhlIGVkZ2UgcmF0aGVyIHRoYW4gdGhlIHNvdXJjZVxuXG4gICAgICByZXBsYWNlTGFzdFF1ZXJ5KHNlbGVjdG9yLCBxdWVyeSwgZWRnZVF1ZXJ5KTtcbiAgICAgIHNlbGVjdG9yLmVkZ2VDb3VudCsrOyAvLyB3ZSdyZSBub3cgcG9wdWxhdGluZyB0aGUgdGFyZ2V0IHF1ZXJ5IHdpdGggZXhwcmVzc2lvbnMgdGhhdCBmb2xsb3dcblxuICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gbmVpZ2hib3VyaG9vZFxuICAgICAgdmFyIG5ob29kUSA9IG5ld1F1ZXJ5KCk7XG4gICAgICB2YXIgbm9kZSA9IHF1ZXJ5O1xuICAgICAgdmFyIG5laWdoYm9yID0gbmV3UXVlcnkoKTtcbiAgICAgIG5ob29kUS5jaGVja3MucHVzaCh7XG4gICAgICAgIHR5cGU6IFR5cGUuTk9ERV9ORUlHSEJPUixcbiAgICAgICAgbm9kZTogbm9kZSxcbiAgICAgICAgbmVpZ2hib3I6IG5laWdoYm9yXG4gICAgICB9KTsgLy8gdGhlIHF1ZXJ5IGluIHRoZSBzZWxlY3RvciBzaG91bGQgYmUgdGhlIG5laWdoYm91cmhvb2QgcmF0aGVyIHRoYW4gdGhlIG5vZGVcblxuICAgICAgcmVwbGFjZUxhc3RRdWVyeShzZWxlY3RvciwgcXVlcnksIG5ob29kUSk7XG4gICAgICByZXR1cm4gbmVpZ2hib3I7IC8vIG5vdyBwb3B1bGF0aW5nIHRoZSBuZWlnaGJvciB3aXRoIGZvbGxvd2luZyBleHByZXNzaW9uc1xuICAgIH1cbiAgfVxufSwge1xuICBuYW1lOiAnY2hpbGQnLFxuICBzZXBhcmF0b3I6IHRydWUsXG4gIHJlZ2V4OiB0b2tlbnMuY2hpbGQsXG4gIHBvcHVsYXRlOiBmdW5jdGlvbiBwb3B1bGF0ZShzZWxlY3RvciwgcXVlcnkpIHtcbiAgICBpZiAoc2VsZWN0b3IuY3VycmVudFN1YmplY3QgPT0gbnVsbCkge1xuICAgICAgLy8gZGVmYXVsdDogY2hpbGQgcXVlcnlcbiAgICAgIHZhciBwYXJlbnRDaGlsZFF1ZXJ5ID0gbmV3UXVlcnkoKTtcbiAgICAgIHZhciBjaGlsZCA9IG5ld1F1ZXJ5KCk7XG4gICAgICB2YXIgcGFyZW50ID0gc2VsZWN0b3Jbc2VsZWN0b3IubGVuZ3RoIC0gMV07XG4gICAgICBwYXJlbnRDaGlsZFF1ZXJ5LmNoZWNrcy5wdXNoKHtcbiAgICAgICAgdHlwZTogVHlwZS5DSElMRCxcbiAgICAgICAgcGFyZW50OiBwYXJlbnQsXG4gICAgICAgIGNoaWxkOiBjaGlsZFxuICAgICAgfSk7IC8vIHRoZSBxdWVyeSBpbiB0aGUgc2VsZWN0b3Igc2hvdWxkIGJlIHRoZSAnPicgaXRzZWxmXG5cbiAgICAgIHJlcGxhY2VMYXN0UXVlcnkoc2VsZWN0b3IsIHF1ZXJ5LCBwYXJlbnRDaGlsZFF1ZXJ5KTtcbiAgICAgIHNlbGVjdG9yLmNvbXBvdW5kQ291bnQrKzsgLy8gd2UncmUgbm93IHBvcHVsYXRpbmcgdGhlIGNoaWxkIHF1ZXJ5IHdpdGggZXhwcmVzc2lvbnMgdGhhdCBmb2xsb3dcblxuICAgICAgcmV0dXJuIGNoaWxkO1xuICAgIH0gZWxzZSBpZiAoc2VsZWN0b3IuY3VycmVudFN1YmplY3QgPT09IHF1ZXJ5KSB7XG4gICAgICAvLyBjb21wb3VuZCBzcGxpdCBxdWVyeVxuICAgICAgdmFyIGNvbXBvdW5kID0gbmV3UXVlcnkoKTtcbiAgICAgIHZhciBsZWZ0ID0gc2VsZWN0b3Jbc2VsZWN0b3IubGVuZ3RoIC0gMV07XG4gICAgICB2YXIgcmlnaHQgPSBuZXdRdWVyeSgpO1xuICAgICAgdmFyIHN1YmplY3QgPSBuZXdRdWVyeSgpO1xuXG4gICAgICB2YXIgX2NoaWxkID0gbmV3UXVlcnkoKTtcblxuICAgICAgdmFyIF9wYXJlbnQgPSBuZXdRdWVyeSgpOyAvLyBzZXQgdXAgdGhlIHJvb3QgY29tcG91bmQgcVxuXG5cbiAgICAgIGNvbXBvdW5kLmNoZWNrcy5wdXNoKHtcbiAgICAgICAgdHlwZTogVHlwZS5DT01QT1VORF9TUExJVCxcbiAgICAgICAgbGVmdDogbGVmdCxcbiAgICAgICAgcmlnaHQ6IHJpZ2h0LFxuICAgICAgICBzdWJqZWN0OiBzdWJqZWN0XG4gICAgICB9KTsgLy8gcG9wdWxhdGUgdGhlIHN1YmplY3QgYW5kIHJlcGxhY2UgdGhlIHEgYXQgdGhlIG9sZCBzcG90ICh3aXRoaW4gbGVmdCkgd2l0aCBUUlVFXG5cbiAgICAgIHN1YmplY3QuY2hlY2tzID0gcXVlcnkuY2hlY2tzOyAvLyB0YWtlIHRoZSBjaGVja3MgZnJvbSB0aGUgbGVmdFxuXG4gICAgICBxdWVyeS5jaGVja3MgPSBbe1xuICAgICAgICB0eXBlOiBUeXBlLlRSVUVcbiAgICAgIH1dOyAvLyBjaGVja3MgdW5kZXIgbGVmdCByZWZzIHRoZSBzdWJqZWN0IGltcGxpY2l0bHlcbiAgICAgIC8vIHNldCB1cCB0aGUgcmlnaHQgcVxuXG4gICAgICBfcGFyZW50LmNoZWNrcy5wdXNoKHtcbiAgICAgICAgdHlwZTogVHlwZS5UUlVFXG4gICAgICB9KTsgLy8gcGFyZW50IGltcGxpY2l0bHkgcmVmcyB0aGUgc3ViamVjdFxuXG5cbiAgICAgIHJpZ2h0LmNoZWNrcy5wdXNoKHtcbiAgICAgICAgdHlwZTogVHlwZS5QQVJFTlQsXG4gICAgICAgIC8vIHR5cGUgaXMgc3dhcHBlZCBvbiByaWdodCBzaWRlIHF1ZXJpZXNcbiAgICAgICAgcGFyZW50OiBfcGFyZW50LFxuICAgICAgICBjaGlsZDogX2NoaWxkIC8vIGVtcHR5IGZvciBub3dcblxuICAgICAgfSk7XG4gICAgICByZXBsYWNlTGFzdFF1ZXJ5KHNlbGVjdG9yLCBsZWZ0LCBjb21wb3VuZCk7IC8vIHVwZGF0ZSB0aGUgcmVmIHNpbmNlIHdlIG1vdmVkIHRoaW5ncyBhcm91bmQgZm9yIGBxdWVyeWBcblxuICAgICAgc2VsZWN0b3IuY3VycmVudFN1YmplY3QgPSBzdWJqZWN0O1xuICAgICAgc2VsZWN0b3IuY29tcG91bmRDb3VudCsrO1xuICAgICAgcmV0dXJuIF9jaGlsZDsgLy8gbm93IHBvcHVsYXRpbmcgdGhlIHJpZ2h0IHNpZGUncyBjaGlsZFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBwYXJlbnQgcXVlcnlcbiAgICAgIC8vIGluZm8gZm9yIHBhcmVudCBxdWVyeVxuICAgICAgdmFyIF9wYXJlbnQyID0gbmV3UXVlcnkoKTtcblxuICAgICAgdmFyIF9jaGlsZDIgPSBuZXdRdWVyeSgpO1xuXG4gICAgICB2YXIgcGNRQ2hlY2tzID0gW3tcbiAgICAgICAgdHlwZTogVHlwZS5QQVJFTlQsXG4gICAgICAgIHBhcmVudDogX3BhcmVudDIsXG4gICAgICAgIGNoaWxkOiBfY2hpbGQyXG4gICAgICB9XTsgLy8gdGhlIHBhcmVudC1jaGlsZCBxdWVyeSB0YWtlcyB0aGUgcGxhY2Ugb2YgdGhlIHF1ZXJ5IHByZXZpb3VzbHkgYmVpbmcgcG9wdWxhdGVkXG5cbiAgICAgIF9wYXJlbnQyLmNoZWNrcyA9IHF1ZXJ5LmNoZWNrczsgLy8gdGhlIHByZXZpb3VzIHF1ZXJ5IGNvbnRhaW5zIHRoZSBjaGVja3MgZm9yIHRoZSBwYXJlbnRcblxuICAgICAgcXVlcnkuY2hlY2tzID0gcGNRQ2hlY2tzOyAvLyBwYyBxdWVyeSB0YWtlcyBvdmVyXG5cbiAgICAgIHNlbGVjdG9yLmNvbXBvdW5kQ291bnQrKztcbiAgICAgIHJldHVybiBfY2hpbGQyOyAvLyB3ZSdyZSBub3cgcG9wdWxhdGluZyB0aGUgY2hpbGRcbiAgICB9XG4gIH1cbn0sIHtcbiAgbmFtZTogJ2Rlc2NlbmRhbnQnLFxuICBzZXBhcmF0b3I6IHRydWUsXG4gIHJlZ2V4OiB0b2tlbnMuZGVzY2VuZGFudCxcbiAgcG9wdWxhdGU6IGZ1bmN0aW9uIHBvcHVsYXRlKHNlbGVjdG9yLCBxdWVyeSkge1xuICAgIGlmIChzZWxlY3Rvci5jdXJyZW50U3ViamVjdCA9PSBudWxsKSB7XG4gICAgICAvLyBkZWZhdWx0OiBkZXNjZW5kYW50IHF1ZXJ5XG4gICAgICB2YXIgYW5jQ2hRdWVyeSA9IG5ld1F1ZXJ5KCk7XG4gICAgICB2YXIgZGVzY2VuZGFudCA9IG5ld1F1ZXJ5KCk7XG4gICAgICB2YXIgYW5jZXN0b3IgPSBzZWxlY3RvcltzZWxlY3Rvci5sZW5ndGggLSAxXTtcbiAgICAgIGFuY0NoUXVlcnkuY2hlY2tzLnB1c2goe1xuICAgICAgICB0eXBlOiBUeXBlLkRFU0NFTkRBTlQsXG4gICAgICAgIGFuY2VzdG9yOiBhbmNlc3RvcixcbiAgICAgICAgZGVzY2VuZGFudDogZGVzY2VuZGFudFxuICAgICAgfSk7IC8vIHRoZSBxdWVyeSBpbiB0aGUgc2VsZWN0b3Igc2hvdWxkIGJlIHRoZSAnPicgaXRzZWxmXG5cbiAgICAgIHJlcGxhY2VMYXN0UXVlcnkoc2VsZWN0b3IsIHF1ZXJ5LCBhbmNDaFF1ZXJ5KTtcbiAgICAgIHNlbGVjdG9yLmNvbXBvdW5kQ291bnQrKzsgLy8gd2UncmUgbm93IHBvcHVsYXRpbmcgdGhlIGRlc2NlbmRhbnQgcXVlcnkgd2l0aCBleHByZXNzaW9ucyB0aGF0IGZvbGxvd1xuXG4gICAgICByZXR1cm4gZGVzY2VuZGFudDtcbiAgICB9IGVsc2UgaWYgKHNlbGVjdG9yLmN1cnJlbnRTdWJqZWN0ID09PSBxdWVyeSkge1xuICAgICAgLy8gY29tcG91bmQgc3BsaXQgcXVlcnlcbiAgICAgIHZhciBjb21wb3VuZCA9IG5ld1F1ZXJ5KCk7XG4gICAgICB2YXIgbGVmdCA9IHNlbGVjdG9yW3NlbGVjdG9yLmxlbmd0aCAtIDFdO1xuICAgICAgdmFyIHJpZ2h0ID0gbmV3UXVlcnkoKTtcbiAgICAgIHZhciBzdWJqZWN0ID0gbmV3UXVlcnkoKTtcblxuICAgICAgdmFyIF9kZXNjZW5kYW50ID0gbmV3UXVlcnkoKTtcblxuICAgICAgdmFyIF9hbmNlc3RvciA9IG5ld1F1ZXJ5KCk7IC8vIHNldCB1cCB0aGUgcm9vdCBjb21wb3VuZCBxXG5cblxuICAgICAgY29tcG91bmQuY2hlY2tzLnB1c2goe1xuICAgICAgICB0eXBlOiBUeXBlLkNPTVBPVU5EX1NQTElULFxuICAgICAgICBsZWZ0OiBsZWZ0LFxuICAgICAgICByaWdodDogcmlnaHQsXG4gICAgICAgIHN1YmplY3Q6IHN1YmplY3RcbiAgICAgIH0pOyAvLyBwb3B1bGF0ZSB0aGUgc3ViamVjdCBhbmQgcmVwbGFjZSB0aGUgcSBhdCB0aGUgb2xkIHNwb3QgKHdpdGhpbiBsZWZ0KSB3aXRoIFRSVUVcblxuICAgICAgc3ViamVjdC5jaGVja3MgPSBxdWVyeS5jaGVja3M7IC8vIHRha2UgdGhlIGNoZWNrcyBmcm9tIHRoZSBsZWZ0XG5cbiAgICAgIHF1ZXJ5LmNoZWNrcyA9IFt7XG4gICAgICAgIHR5cGU6IFR5cGUuVFJVRVxuICAgICAgfV07IC8vIGNoZWNrcyB1bmRlciBsZWZ0IHJlZnMgdGhlIHN1YmplY3QgaW1wbGljaXRseVxuICAgICAgLy8gc2V0IHVwIHRoZSByaWdodCBxXG5cbiAgICAgIF9hbmNlc3Rvci5jaGVja3MucHVzaCh7XG4gICAgICAgIHR5cGU6IFR5cGUuVFJVRVxuICAgICAgfSk7IC8vIGFuY2VzdG9yIGltcGxpY2l0bHkgcmVmcyB0aGUgc3ViamVjdFxuXG5cbiAgICAgIHJpZ2h0LmNoZWNrcy5wdXNoKHtcbiAgICAgICAgdHlwZTogVHlwZS5BTkNFU1RPUixcbiAgICAgICAgLy8gdHlwZSBpcyBzd2FwcGVkIG9uIHJpZ2h0IHNpZGUgcXVlcmllc1xuICAgICAgICBhbmNlc3RvcjogX2FuY2VzdG9yLFxuICAgICAgICBkZXNjZW5kYW50OiBfZGVzY2VuZGFudCAvLyBlbXB0eSBmb3Igbm93XG5cbiAgICAgIH0pO1xuICAgICAgcmVwbGFjZUxhc3RRdWVyeShzZWxlY3RvciwgbGVmdCwgY29tcG91bmQpOyAvLyB1cGRhdGUgdGhlIHJlZiBzaW5jZSB3ZSBtb3ZlZCB0aGluZ3MgYXJvdW5kIGZvciBgcXVlcnlgXG5cbiAgICAgIHNlbGVjdG9yLmN1cnJlbnRTdWJqZWN0ID0gc3ViamVjdDtcbiAgICAgIHNlbGVjdG9yLmNvbXBvdW5kQ291bnQrKztcbiAgICAgIHJldHVybiBfZGVzY2VuZGFudDsgLy8gbm93IHBvcHVsYXRpbmcgdGhlIHJpZ2h0IHNpZGUncyBkZXNjZW5kYW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGFuY2VzdG9yIHF1ZXJ5XG4gICAgICAvLyBpbmZvIGZvciBwYXJlbnQgcXVlcnlcbiAgICAgIHZhciBfYW5jZXN0b3IyID0gbmV3UXVlcnkoKTtcblxuICAgICAgdmFyIF9kZXNjZW5kYW50MiA9IG5ld1F1ZXJ5KCk7XG5cbiAgICAgIHZhciBhZFFDaGVja3MgPSBbe1xuICAgICAgICB0eXBlOiBUeXBlLkFOQ0VTVE9SLFxuICAgICAgICBhbmNlc3RvcjogX2FuY2VzdG9yMixcbiAgICAgICAgZGVzY2VuZGFudDogX2Rlc2NlbmRhbnQyXG4gICAgICB9XTsgLy8gdGhlIHBhcmVudC1jaGlsZCBxdWVyeSB0YWtlcyB0aGUgcGxhY2Ugb2YgdGhlIHF1ZXJ5IHByZXZpb3VzbHkgYmVpbmcgcG9wdWxhdGVkXG5cbiAgICAgIF9hbmNlc3RvcjIuY2hlY2tzID0gcXVlcnkuY2hlY2tzOyAvLyB0aGUgcHJldmlvdXMgcXVlcnkgY29udGFpbnMgdGhlIGNoZWNrcyBmb3IgdGhlIHBhcmVudFxuXG4gICAgICBxdWVyeS5jaGVja3MgPSBhZFFDaGVja3M7IC8vIHBjIHF1ZXJ5IHRha2VzIG92ZXJcblxuICAgICAgc2VsZWN0b3IuY29tcG91bmRDb3VudCsrO1xuICAgICAgcmV0dXJuIF9kZXNjZW5kYW50MjsgLy8gd2UncmUgbm93IHBvcHVsYXRpbmcgdGhlIGNoaWxkXG4gICAgfVxuICB9XG59LCB7XG4gIG5hbWU6ICdzdWJqZWN0JyxcbiAgbW9kaWZpZXI6IHRydWUsXG4gIHJlZ2V4OiB0b2tlbnMuc3ViamVjdCxcbiAgcG9wdWxhdGU6IGZ1bmN0aW9uIHBvcHVsYXRlKHNlbGVjdG9yLCBxdWVyeSkge1xuICAgIGlmIChzZWxlY3Rvci5jdXJyZW50U3ViamVjdCAhPSBudWxsICYmIHNlbGVjdG9yLmN1cnJlbnRTdWJqZWN0ICE9PSBxdWVyeSkge1xuICAgICAgd2FybignUmVkZWZpbml0aW9uIG9mIHN1YmplY3QgaW4gc2VsZWN0b3IgYCcgKyBzZWxlY3Rvci50b1N0cmluZygpICsgJ2AnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzZWxlY3Rvci5jdXJyZW50U3ViamVjdCA9IHF1ZXJ5O1xuICAgIHZhciB0b3BRID0gc2VsZWN0b3Jbc2VsZWN0b3IubGVuZ3RoIC0gMV07XG4gICAgdmFyIHRvcENoayA9IHRvcFEuY2hlY2tzWzBdO1xuICAgIHZhciB0b3BUeXBlID0gdG9wQ2hrID09IG51bGwgPyBudWxsIDogdG9wQ2hrLnR5cGU7XG5cbiAgICBpZiAodG9wVHlwZSA9PT0gVHlwZS5ESVJFQ1RFRF9FREdFKSB7XG4gICAgICAvLyBkaXJlY3RlZCBlZGdlIHdpdGggc3ViamVjdCBvbiB0aGUgdGFyZ2V0XG4gICAgICAvLyBjaGFuZ2UgdG8gdGFyZ2V0IG5vZGUgY2hlY2tcbiAgICAgIHRvcENoay50eXBlID0gVHlwZS5OT0RFX1RBUkdFVDtcbiAgICB9IGVsc2UgaWYgKHRvcFR5cGUgPT09IFR5cGUuVU5ESVJFQ1RFRF9FREdFKSB7XG4gICAgICAvLyB1bmRpcmVjdGVkIGVkZ2Ugd2l0aCBzdWJqZWN0IG9uIHRoZSBzZWNvbmQgbm9kZVxuICAgICAgLy8gY2hhbmdlIHRvIG5laWdoYm9yIGNoZWNrXG4gICAgICB0b3BDaGsudHlwZSA9IFR5cGUuTk9ERV9ORUlHSEJPUjtcbiAgICAgIHRvcENoay5ub2RlID0gdG9wQ2hrLm5vZGVzWzFdOyAvLyBzZWNvbmQgbm9kZSBpcyBzdWJqZWN0XG5cbiAgICAgIHRvcENoay5uZWlnaGJvciA9IHRvcENoay5ub2Rlc1swXTsgLy8gY2xlYW4gdXAgdW51c2VkIGZpZWxkcyBmb3IgbmV3IHR5cGVcblxuICAgICAgdG9wQ2hrLm5vZGVzID0gbnVsbDtcbiAgICB9XG4gIH1cbn1dO1xuZXhwcnMuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICByZXR1cm4gZS5yZWdleE9iaiA9IG5ldyBSZWdFeHAoJ14nICsgZS5yZWdleCk7XG59KTtcblxuLyoqXG4gKiBPZiBhbGwgdGhlIGV4cHJlc3Npb25zLCBmaW5kIHRoZSBmaXJzdCBtYXRjaCBpbiB0aGUgcmVtYWluaW5nIHRleHQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVtYWluaW5nIFRoZSByZW1haW5pbmcgdGV4dCB0byBwYXJzZVxuICogQHJldHVybnMgVGhlIG1hdGNoZWQgZXhwcmVzc2lvbiBhbmQgdGhlIG5ld2x5IHJlbWFpbmluZyB0ZXh0IGB7IGV4cHIsIG1hdGNoLCBuYW1lLCByZW1haW5pbmcgfWBcbiAqL1xuXG52YXIgY29uc3VtZUV4cHIgPSBmdW5jdGlvbiBjb25zdW1lRXhwcihyZW1haW5pbmcpIHtcbiAgdmFyIGV4cHI7XG4gIHZhciBtYXRjaDtcbiAgdmFyIG5hbWU7XG5cbiAgZm9yICh2YXIgaiA9IDA7IGogPCBleHBycy5sZW5ndGg7IGorKykge1xuICAgIHZhciBlID0gZXhwcnNbal07XG4gICAgdmFyIG4gPSBlLm5hbWU7XG4gICAgdmFyIG0gPSByZW1haW5pbmcubWF0Y2goZS5yZWdleE9iaik7XG5cbiAgICBpZiAobSAhPSBudWxsKSB7XG4gICAgICBtYXRjaCA9IG07XG4gICAgICBleHByID0gZTtcbiAgICAgIG5hbWUgPSBuO1xuICAgICAgdmFyIGNvbnN1bWVkID0gbVswXTtcbiAgICAgIHJlbWFpbmluZyA9IHJlbWFpbmluZy5zdWJzdHJpbmcoY29uc3VtZWQubGVuZ3RoKTtcbiAgICAgIGJyZWFrOyAvLyB3ZSd2ZSBjb25zdW1lZCBvbmUgZXhwciwgc28gd2UgY2FuIHJldHVybiBub3dcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGV4cHI6IGV4cHIsXG4gICAgbWF0Y2g6IG1hdGNoLFxuICAgIG5hbWU6IG5hbWUsXG4gICAgcmVtYWluaW5nOiByZW1haW5pbmdcbiAgfTtcbn07XG4vKipcbiAqIENvbnN1bWUgYWxsIHRoZSBsZWFkaW5nIHdoaXRlc3BhY2VcbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1haW5pbmcgVGhlIHRleHQgdG8gY29uc3VtZVxuICogQHJldHVybnMgVGhlIHRleHQgd2l0aCB0aGUgbGVhZGluZyB3aGl0ZXNwYWNlIHJlbW92ZWRcbiAqL1xuXG5cbnZhciBjb25zdW1lV2hpdGVzcGFjZSA9IGZ1bmN0aW9uIGNvbnN1bWVXaGl0ZXNwYWNlKHJlbWFpbmluZykge1xuICB2YXIgbWF0Y2ggPSByZW1haW5pbmcubWF0Y2goL15cXHMrLyk7XG5cbiAgaWYgKG1hdGNoKSB7XG4gICAgdmFyIGNvbnN1bWVkID0gbWF0Y2hbMF07XG4gICAgcmVtYWluaW5nID0gcmVtYWluaW5nLnN1YnN0cmluZyhjb25zdW1lZC5sZW5ndGgpO1xuICB9XG5cbiAgcmV0dXJuIHJlbWFpbmluZztcbn07XG4vKipcbiAqIFBhcnNlIHRoZSBzdHJpbmcgYW5kIHN0b3JlIHRoZSBwYXJzZWQgcmVwcmVzZW50YXRpb24gaW4gdGhlIFNlbGVjdG9yLlxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yIFRoZSBzZWxlY3RvciBzdHJpbmdcbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgc2VsZWN0b3Igd2FzIHN1Y2Nlc3NmdWxseSBwYXJzZWQsIGBmYWxzZWAgb3RoZXJ3aXNlXG4gKi9cblxuXG52YXIgcGFyc2UgPSBmdW5jdGlvbiBwYXJzZShzZWxlY3Rvcikge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciByZW1haW5pbmcgPSBzZWxmLmlucHV0VGV4dCA9IHNlbGVjdG9yO1xuICB2YXIgY3VycmVudFF1ZXJ5ID0gc2VsZlswXSA9IG5ld1F1ZXJ5KCk7XG4gIHNlbGYubGVuZ3RoID0gMTtcbiAgcmVtYWluaW5nID0gY29uc3VtZVdoaXRlc3BhY2UocmVtYWluaW5nKTsgLy8gZ2V0IHJpZCBvZiBsZWFkaW5nIHdoaXRlc3BhY2VcblxuICBmb3IgKDs7KSB7XG4gICAgdmFyIGV4cHJJbmZvID0gY29uc3VtZUV4cHIocmVtYWluaW5nKTtcblxuICAgIGlmIChleHBySW5mby5leHByID09IG51bGwpIHtcbiAgICAgIHdhcm4oJ1RoZSBzZWxlY3RvciBgJyArIHNlbGVjdG9yICsgJ2BpcyBpbnZhbGlkJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBhcmdzID0gZXhwckluZm8ubWF0Y2guc2xpY2UoMSk7IC8vIGxldCB0aGUgdG9rZW4gcG9wdWxhdGUgdGhlIHNlbGVjdG9yIG9iamVjdCBpbiBjdXJyZW50UXVlcnlcblxuICAgICAgdmFyIHJldCA9IGV4cHJJbmZvLmV4cHIucG9wdWxhdGUoc2VsZiwgY3VycmVudFF1ZXJ5LCBhcmdzKTtcblxuICAgICAgaWYgKHJldCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBleGl0IGlmIHBvcHVsYXRpb24gZmFpbGVkXG4gICAgICB9IGVsc2UgaWYgKHJldCAhPSBudWxsKSB7XG4gICAgICAgIGN1cnJlbnRRdWVyeSA9IHJldDsgLy8gY2hhbmdlIHRoZSBjdXJyZW50IHF1ZXJ5IHRvIGJlIGZpbGxlZCBpZiB0aGUgZXhwciBzcGVjaWZpZXNcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZW1haW5pbmcgPSBleHBySW5mby5yZW1haW5pbmc7IC8vIHdlJ3JlIGRvbmUgd2hlbiB0aGVyZSdzIG5vdGhpbmcgbGVmdCB0byBwYXJzZVxuXG4gICAgaWYgKHJlbWFpbmluZy5tYXRjaCgvXlxccyokLykpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHZhciBsYXN0USA9IHNlbGZbc2VsZi5sZW5ndGggLSAxXTtcblxuICBpZiAoc2VsZi5jdXJyZW50U3ViamVjdCAhPSBudWxsKSB7XG4gICAgbGFzdFEuc3ViamVjdCA9IHNlbGYuY3VycmVudFN1YmplY3Q7XG4gIH1cblxuICBsYXN0US5lZGdlQ291bnQgPSBzZWxmLmVkZ2VDb3VudDtcbiAgbGFzdFEuY29tcG91bmRDb3VudCA9IHNlbGYuY29tcG91bmRDb3VudDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHNlbGYubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcSA9IHNlbGZbaV07IC8vIGluIGZ1dHVyZSwgdGhpcyBjb3VsZCBwb3RlbnRpYWxseSBiZSBhbGxvd2VkIGlmIHRoZXJlIHdlcmUgb3BlcmF0b3IgcHJlY2VkZW5jZSBhbmQgZGV0ZWN0aW9uIG9mIGludmFsaWQgY29tYmluYXRpb25zXG5cbiAgICBpZiAocS5jb21wb3VuZENvdW50ID4gMCAmJiBxLmVkZ2VDb3VudCA+IDApIHtcbiAgICAgIHdhcm4oJ1RoZSBzZWxlY3RvciBgJyArIHNlbGVjdG9yICsgJ2AgaXMgaW52YWxpZCBiZWNhdXNlIGl0IHVzZXMgYm90aCBhIGNvbXBvdW5kIHNlbGVjdG9yIGFuZCBhbiBlZGdlIHNlbGVjdG9yJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHEuZWRnZUNvdW50ID4gMSkge1xuICAgICAgd2FybignVGhlIHNlbGVjdG9yIGAnICsgc2VsZWN0b3IgKyAnYCBpcyBpbnZhbGlkIGJlY2F1c2UgaXQgdXNlcyBtdWx0aXBsZSBlZGdlIHNlbGVjdG9ycycpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSBpZiAocS5lZGdlQ291bnQgPT09IDEpIHtcbiAgICAgIHdhcm4oJ1RoZSBzZWxlY3RvciBgJyArIHNlbGVjdG9yICsgJ2AgaXMgZGVwcmVjYXRlZC4gIEVkZ2Ugc2VsZWN0b3JzIGRvIG5vdCB0YWtlIGVmZmVjdCBvbiBjaGFuZ2VzIHRvIHNvdXJjZSBhbmQgdGFyZ2V0IG5vZGVzIGFmdGVyIGFuIGVkZ2UgaXMgYWRkZWQsIGZvciBwZXJmb3JtYW5jZSByZWFzb25zLiAgVXNlIGEgY2xhc3Mgb3IgZGF0YSBzZWxlY3RvciBvbiBlZGdlcyBpbnN0ZWFkLCB1cGRhdGluZyB0aGUgY2xhc3Mgb3IgZGF0YSBvZiBhbiBlZGdlIHdoZW4geW91ciBhcHAgZGV0ZWN0cyBhIGNoYW5nZSBpbiBzb3VyY2Ugb3IgdGFyZ2V0IG5vZGVzLicpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlOyAvLyBzdWNjZXNzXG59O1xuLyoqXG4gKiBHZXQgdGhlIHNlbGVjdG9yIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nLiAgVGhpcyB2YWx1ZSB1c2VzIGRlZmF1bHQgZm9ybWF0dGluZyxcbiAqIHNvIHRoaW5ncyBsaWtlIHNwYWNpbmcgbWF5IGRpZmZlciBmcm9tIHRoZSBpbnB1dCB0ZXh0IHBhc3NlZCB0byB0aGUgY29uc3RydWN0b3IuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgc2VsZWN0b3Igc3RyaW5nXG4gKi9cblxuXG52YXIgdG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgaWYgKHRoaXMudG9TdHJpbmdDYWNoZSAhPSBudWxsKSB7XG4gICAgcmV0dXJuIHRoaXMudG9TdHJpbmdDYWNoZTtcbiAgfVxuXG4gIHZhciBjbGVhbiA9IGZ1bmN0aW9uIGNsZWFuKG9iaikge1xuICAgIGlmIChvYmogPT0gbnVsbCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gb2JqO1xuICAgIH1cbiAgfTtcblxuICB2YXIgY2xlYW5WYWwgPSBmdW5jdGlvbiBjbGVhblZhbCh2YWwpIHtcbiAgICBpZiAoc3RyaW5nKHZhbCkpIHtcbiAgICAgIHJldHVybiAnXCInICsgdmFsICsgJ1wiJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNsZWFuKHZhbCk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBzcGFjZSA9IGZ1bmN0aW9uIHNwYWNlKHZhbCkge1xuICAgIHJldHVybiAnICcgKyB2YWwgKyAnICc7XG4gIH07XG5cbiAgdmFyIGNoZWNrVG9TdHJpbmcgPSBmdW5jdGlvbiBjaGVja1RvU3RyaW5nKGNoZWNrLCBzdWJqZWN0KSB7XG4gICAgdmFyIHR5cGUgPSBjaGVjay50eXBlLFxuICAgICAgICB2YWx1ZSA9IGNoZWNrLnZhbHVlO1xuXG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlIFR5cGUuR1JPVVA6XG4gICAgICAgIHtcbiAgICAgICAgICB2YXIgZ3JvdXAgPSBjbGVhbih2YWx1ZSk7XG4gICAgICAgICAgcmV0dXJuIGdyb3VwLnN1YnN0cmluZygwLCBncm91cC5sZW5ndGggLSAxKTtcbiAgICAgICAgfVxuXG4gICAgICBjYXNlIFR5cGUuREFUQV9DT01QQVJFOlxuICAgICAgICB7XG4gICAgICAgICAgdmFyIGZpZWxkID0gY2hlY2suZmllbGQsXG4gICAgICAgICAgICAgIG9wZXJhdG9yID0gY2hlY2sub3BlcmF0b3I7XG4gICAgICAgICAgcmV0dXJuICdbJyArIGZpZWxkICsgc3BhY2UoY2xlYW4ob3BlcmF0b3IpKSArIGNsZWFuVmFsKHZhbHVlKSArICddJztcbiAgICAgICAgfVxuXG4gICAgICBjYXNlIFR5cGUuREFUQV9CT09MOlxuICAgICAgICB7XG4gICAgICAgICAgdmFyIF9vcGVyYXRvciA9IGNoZWNrLm9wZXJhdG9yLFxuICAgICAgICAgICAgICBfZmllbGQgPSBjaGVjay5maWVsZDtcbiAgICAgICAgICByZXR1cm4gJ1snICsgY2xlYW4oX29wZXJhdG9yKSArIF9maWVsZCArICddJztcbiAgICAgICAgfVxuXG4gICAgICBjYXNlIFR5cGUuREFUQV9FWElTVDpcbiAgICAgICAge1xuICAgICAgICAgIHZhciBfZmllbGQyID0gY2hlY2suZmllbGQ7XG4gICAgICAgICAgcmV0dXJuICdbJyArIF9maWVsZDIgKyAnXSc7XG4gICAgICAgIH1cblxuICAgICAgY2FzZSBUeXBlLk1FVEFfQ09NUEFSRTpcbiAgICAgICAge1xuICAgICAgICAgIHZhciBfb3BlcmF0b3IyID0gY2hlY2sub3BlcmF0b3IsXG4gICAgICAgICAgICAgIF9maWVsZDMgPSBjaGVjay5maWVsZDtcbiAgICAgICAgICByZXR1cm4gJ1tbJyArIF9maWVsZDMgKyBzcGFjZShjbGVhbihfb3BlcmF0b3IyKSkgKyBjbGVhblZhbCh2YWx1ZSkgKyAnXV0nO1xuICAgICAgICB9XG5cbiAgICAgIGNhc2UgVHlwZS5TVEFURTpcbiAgICAgICAge1xuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICBjYXNlIFR5cGUuSUQ6XG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gJyMnICsgdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgY2FzZSBUeXBlLkNMQVNTOlxuICAgICAgICB7XG4gICAgICAgICAgcmV0dXJuICcuJyArIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgIGNhc2UgVHlwZS5QQVJFTlQ6XG4gICAgICBjYXNlIFR5cGUuQ0hJTEQ6XG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gcXVlcnlUb1N0cmluZyhjaGVjay5wYXJlbnQsIHN1YmplY3QpICsgc3BhY2UoJz4nKSArIHF1ZXJ5VG9TdHJpbmcoY2hlY2suY2hpbGQsIHN1YmplY3QpO1xuICAgICAgICB9XG5cbiAgICAgIGNhc2UgVHlwZS5BTkNFU1RPUjpcbiAgICAgIGNhc2UgVHlwZS5ERVNDRU5EQU5UOlxuICAgICAgICB7XG4gICAgICAgICAgcmV0dXJuIHF1ZXJ5VG9TdHJpbmcoY2hlY2suYW5jZXN0b3IsIHN1YmplY3QpICsgJyAnICsgcXVlcnlUb1N0cmluZyhjaGVjay5kZXNjZW5kYW50LCBzdWJqZWN0KTtcbiAgICAgICAgfVxuXG4gICAgICBjYXNlIFR5cGUuQ09NUE9VTkRfU1BMSVQ6XG4gICAgICAgIHtcbiAgICAgICAgICB2YXIgbGhzID0gcXVlcnlUb1N0cmluZyhjaGVjay5sZWZ0LCBzdWJqZWN0KTtcbiAgICAgICAgICB2YXIgc3ViID0gcXVlcnlUb1N0cmluZyhjaGVjay5zdWJqZWN0LCBzdWJqZWN0KTtcbiAgICAgICAgICB2YXIgcmhzID0gcXVlcnlUb1N0cmluZyhjaGVjay5yaWdodCwgc3ViamVjdCk7XG4gICAgICAgICAgcmV0dXJuIGxocyArIChsaHMubGVuZ3RoID4gMCA/ICcgJyA6ICcnKSArIHN1YiArIHJocztcbiAgICAgICAgfVxuXG4gICAgICBjYXNlIFR5cGUuVFJVRTpcbiAgICAgICAge1xuICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB2YXIgcXVlcnlUb1N0cmluZyA9IGZ1bmN0aW9uIHF1ZXJ5VG9TdHJpbmcocXVlcnksIHN1YmplY3QpIHtcbiAgICByZXR1cm4gcXVlcnkuY2hlY2tzLnJlZHVjZShmdW5jdGlvbiAoc3RyLCBjaGssIGkpIHtcbiAgICAgIHJldHVybiBzdHIgKyAoc3ViamVjdCA9PT0gcXVlcnkgJiYgaSA9PT0gMCA/ICckJyA6ICcnKSArIGNoZWNrVG9TdHJpbmcoY2hrLCBzdWJqZWN0KTtcbiAgICB9LCAnJyk7XG4gIH07XG5cbiAgdmFyIHN0ciA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBxdWVyeSA9IHRoaXNbaV07XG4gICAgc3RyICs9IHF1ZXJ5VG9TdHJpbmcocXVlcnksIHF1ZXJ5LnN1YmplY3QpO1xuXG4gICAgaWYgKHRoaXMubGVuZ3RoID4gMSAmJiBpIDwgdGhpcy5sZW5ndGggLSAxKSB7XG4gICAgICBzdHIgKz0gJywgJztcbiAgICB9XG4gIH1cblxuICB0aGlzLnRvU3RyaW5nQ2FjaGUgPSBzdHI7XG4gIHJldHVybiBzdHI7XG59O1xudmFyIHBhcnNlJDEgPSB7XG4gIHBhcnNlOiBwYXJzZSxcbiAgdG9TdHJpbmc6IHRvU3RyaW5nXG59O1xuXG52YXIgdmFsQ21wID0gZnVuY3Rpb24gdmFsQ21wKGZpZWxkVmFsLCBvcGVyYXRvciwgdmFsdWUpIHtcbiAgdmFyIG1hdGNoZXM7XG4gIHZhciBpc0ZpZWxkU3RyID0gc3RyaW5nKGZpZWxkVmFsKTtcbiAgdmFyIGlzRmllbGROdW0gPSBudW1iZXIoZmllbGRWYWwpO1xuICB2YXIgaXNWYWxTdHIgPSBzdHJpbmcodmFsdWUpO1xuICB2YXIgZmllbGRTdHIsIHZhbFN0cjtcbiAgdmFyIGNhc2VJbnNlbnNpdGl2ZSA9IGZhbHNlO1xuICB2YXIgbm90RXhwciA9IGZhbHNlO1xuICB2YXIgaXNJbmVxQ21wID0gZmFsc2U7XG5cbiAgaWYgKG9wZXJhdG9yLmluZGV4T2YoJyEnKSA+PSAwKSB7XG4gICAgb3BlcmF0b3IgPSBvcGVyYXRvci5yZXBsYWNlKCchJywgJycpO1xuICAgIG5vdEV4cHIgPSB0cnVlO1xuICB9XG5cbiAgaWYgKG9wZXJhdG9yLmluZGV4T2YoJ0AnKSA+PSAwKSB7XG4gICAgb3BlcmF0b3IgPSBvcGVyYXRvci5yZXBsYWNlKCdAJywgJycpO1xuICAgIGNhc2VJbnNlbnNpdGl2ZSA9IHRydWU7XG4gIH1cblxuICBpZiAoaXNGaWVsZFN0ciB8fCBpc1ZhbFN0ciB8fCBjYXNlSW5zZW5zaXRpdmUpIHtcbiAgICBmaWVsZFN0ciA9ICFpc0ZpZWxkU3RyICYmICFpc0ZpZWxkTnVtID8gJycgOiAnJyArIGZpZWxkVmFsO1xuICAgIHZhbFN0ciA9ICcnICsgdmFsdWU7XG4gIH0gLy8gaWYgd2UncmUgZG9pbmcgYSBjYXNlIGluc2Vuc2l0aXZlIGNvbXBhcmlzb24sIHRoZW4gd2UncmUgdXNpbmcgYSBTVFJJTkcgY29tcGFyaXNvblxuICAvLyBldmVuIGlmIHdlJ3JlIGNvbXBhcmluZyBudW1iZXJzXG5cblxuICBpZiAoY2FzZUluc2Vuc2l0aXZlKSB7XG4gICAgZmllbGRWYWwgPSBmaWVsZFN0ciA9IGZpZWxkU3RyLnRvTG93ZXJDYXNlKCk7XG4gICAgdmFsdWUgPSB2YWxTdHIgPSB2YWxTdHIudG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIHN3aXRjaCAob3BlcmF0b3IpIHtcbiAgICBjYXNlICcqPSc6XG4gICAgICBtYXRjaGVzID0gZmllbGRTdHIuaW5kZXhPZih2YWxTdHIpID49IDA7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJyQ9JzpcbiAgICAgIG1hdGNoZXMgPSBmaWVsZFN0ci5pbmRleE9mKHZhbFN0ciwgZmllbGRTdHIubGVuZ3RoIC0gdmFsU3RyLmxlbmd0aCkgPj0gMDtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnXj0nOlxuICAgICAgbWF0Y2hlcyA9IGZpZWxkU3RyLmluZGV4T2YodmFsU3RyKSA9PT0gMDtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnPSc6XG4gICAgICBtYXRjaGVzID0gZmllbGRWYWwgPT09IHZhbHVlO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICc+JzpcbiAgICAgIGlzSW5lcUNtcCA9IHRydWU7XG4gICAgICBtYXRjaGVzID0gZmllbGRWYWwgPiB2YWx1ZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnPj0nOlxuICAgICAgaXNJbmVxQ21wID0gdHJ1ZTtcbiAgICAgIG1hdGNoZXMgPSBmaWVsZFZhbCA+PSB2YWx1ZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnPCc6XG4gICAgICBpc0luZXFDbXAgPSB0cnVlO1xuICAgICAgbWF0Y2hlcyA9IGZpZWxkVmFsIDwgdmFsdWU7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJzw9JzpcbiAgICAgIGlzSW5lcUNtcCA9IHRydWU7XG4gICAgICBtYXRjaGVzID0gZmllbGRWYWwgPD0gdmFsdWU7XG4gICAgICBicmVhaztcblxuICAgIGRlZmF1bHQ6XG4gICAgICBtYXRjaGVzID0gZmFsc2U7XG4gICAgICBicmVhaztcbiAgfSAvLyBhcHBseSB0aGUgbm90IG9wLCBidXQgbnVsbCB2YWxzIGZvciBpbmVxdWFsaXRpZXMgc2hvdWxkIGFsd2F5cyBzdGF5IG5vbi1tYXRjaGluZ1xuXG5cbiAgaWYgKG5vdEV4cHIgJiYgKGZpZWxkVmFsICE9IG51bGwgfHwgIWlzSW5lcUNtcCkpIHtcbiAgICBtYXRjaGVzID0gIW1hdGNoZXM7XG4gIH1cblxuICByZXR1cm4gbWF0Y2hlcztcbn07XG52YXIgYm9vbENtcCA9IGZ1bmN0aW9uIGJvb2xDbXAoZmllbGRWYWwsIG9wZXJhdG9yKSB7XG4gIHN3aXRjaCAob3BlcmF0b3IpIHtcbiAgICBjYXNlICc/JzpcbiAgICAgIHJldHVybiBmaWVsZFZhbCA/IHRydWUgOiBmYWxzZTtcblxuICAgIGNhc2UgJyEnOlxuICAgICAgcmV0dXJuIGZpZWxkVmFsID8gZmFsc2UgOiB0cnVlO1xuXG4gICAgY2FzZSAnXic6XG4gICAgICByZXR1cm4gZmllbGRWYWwgPT09IHVuZGVmaW5lZDtcbiAgfVxufTtcbnZhciBleGlzdENtcCA9IGZ1bmN0aW9uIGV4aXN0Q21wKGZpZWxkVmFsKSB7XG4gIHJldHVybiBmaWVsZFZhbCAhPT0gdW5kZWZpbmVkO1xufTtcbnZhciBkYXRhID0gZnVuY3Rpb24gZGF0YShlbGUsIGZpZWxkKSB7XG4gIHJldHVybiBlbGUuZGF0YShmaWVsZCk7XG59O1xudmFyIG1ldGEgPSBmdW5jdGlvbiBtZXRhKGVsZSwgZmllbGQpIHtcbiAgcmV0dXJuIGVsZVtmaWVsZF0oKTtcbn07XG5cbi8qKiBBIGxvb2t1cCBvZiBgbWF0Y2goY2hlY2ssIGVsZSlgIGZ1bmN0aW9ucyBieSBgVHlwZWAgaW50ICovXG5cbnZhciBtYXRjaCA9IFtdO1xuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHF1ZXJ5IG1hdGNoZXMgZm9yIHRoZSBlbGVtZW50XG4gKiBAcGFyYW0gcXVlcnkgVGhlIGB7IHR5cGUsIHZhbHVlLCAuLi4gfWAgcXVlcnkgb2JqZWN0XG4gKiBAcGFyYW0gZWxlIFRoZSBlbGVtZW50IHRvIGNvbXBhcmUgYWdhaW5zdFxuKi9cblxudmFyIG1hdGNoZXMgPSBmdW5jdGlvbiBtYXRjaGVzKHF1ZXJ5LCBlbGUpIHtcbiAgcmV0dXJuIHF1ZXJ5LmNoZWNrcy5ldmVyeShmdW5jdGlvbiAoY2hrKSB7XG4gICAgcmV0dXJuIG1hdGNoW2Noay50eXBlXShjaGssIGVsZSk7XG4gIH0pO1xufTtcblxubWF0Y2hbVHlwZS5HUk9VUF0gPSBmdW5jdGlvbiAoY2hlY2ssIGVsZSkge1xuICB2YXIgZ3JvdXAgPSBjaGVjay52YWx1ZTtcbiAgcmV0dXJuIGdyb3VwID09PSAnKicgfHwgZ3JvdXAgPT09IGVsZS5ncm91cCgpO1xufTtcblxubWF0Y2hbVHlwZS5TVEFURV0gPSBmdW5jdGlvbiAoY2hlY2ssIGVsZSkge1xuICB2YXIgc3RhdGVTZWxlY3RvciA9IGNoZWNrLnZhbHVlO1xuICByZXR1cm4gc3RhdGVTZWxlY3Rvck1hdGNoZXMoc3RhdGVTZWxlY3RvciwgZWxlKTtcbn07XG5cbm1hdGNoW1R5cGUuSURdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgdmFyIGlkID0gY2hlY2sudmFsdWU7XG4gIHJldHVybiBlbGUuaWQoKSA9PT0gaWQ7XG59O1xuXG5tYXRjaFtUeXBlLkNMQVNTXSA9IGZ1bmN0aW9uIChjaGVjaywgZWxlKSB7XG4gIHZhciBjbHMgPSBjaGVjay52YWx1ZTtcbiAgcmV0dXJuIGVsZS5oYXNDbGFzcyhjbHMpO1xufTtcblxubWF0Y2hbVHlwZS5NRVRBX0NPTVBBUkVdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgdmFyIGZpZWxkID0gY2hlY2suZmllbGQsXG4gICAgICBvcGVyYXRvciA9IGNoZWNrLm9wZXJhdG9yLFxuICAgICAgdmFsdWUgPSBjaGVjay52YWx1ZTtcbiAgcmV0dXJuIHZhbENtcChtZXRhKGVsZSwgZmllbGQpLCBvcGVyYXRvciwgdmFsdWUpO1xufTtcblxubWF0Y2hbVHlwZS5EQVRBX0NPTVBBUkVdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgdmFyIGZpZWxkID0gY2hlY2suZmllbGQsXG4gICAgICBvcGVyYXRvciA9IGNoZWNrLm9wZXJhdG9yLFxuICAgICAgdmFsdWUgPSBjaGVjay52YWx1ZTtcbiAgcmV0dXJuIHZhbENtcChkYXRhKGVsZSwgZmllbGQpLCBvcGVyYXRvciwgdmFsdWUpO1xufTtcblxubWF0Y2hbVHlwZS5EQVRBX0JPT0xdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgdmFyIGZpZWxkID0gY2hlY2suZmllbGQsXG4gICAgICBvcGVyYXRvciA9IGNoZWNrLm9wZXJhdG9yO1xuICByZXR1cm4gYm9vbENtcChkYXRhKGVsZSwgZmllbGQpLCBvcGVyYXRvcik7XG59O1xuXG5tYXRjaFtUeXBlLkRBVEFfRVhJU1RdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgdmFyIGZpZWxkID0gY2hlY2suZmllbGQsXG4gICAgICBvcGVyYXRvciA9IGNoZWNrLm9wZXJhdG9yO1xuICByZXR1cm4gZXhpc3RDbXAoZGF0YShlbGUsIGZpZWxkKSk7XG59O1xuXG5tYXRjaFtUeXBlLlVORElSRUNURURfRURHRV0gPSBmdW5jdGlvbiAoY2hlY2ssIGVsZSkge1xuICB2YXIgcUEgPSBjaGVjay5ub2Rlc1swXTtcbiAgdmFyIHFCID0gY2hlY2subm9kZXNbMV07XG4gIHZhciBzcmMgPSBlbGUuc291cmNlKCk7XG4gIHZhciB0Z3QgPSBlbGUudGFyZ2V0KCk7XG4gIHJldHVybiBtYXRjaGVzKHFBLCBzcmMpICYmIG1hdGNoZXMocUIsIHRndCkgfHwgbWF0Y2hlcyhxQiwgc3JjKSAmJiBtYXRjaGVzKHFBLCB0Z3QpO1xufTtcblxubWF0Y2hbVHlwZS5OT0RFX05FSUdIQk9SXSA9IGZ1bmN0aW9uIChjaGVjaywgZWxlKSB7XG4gIHJldHVybiBtYXRjaGVzKGNoZWNrLm5vZGUsIGVsZSkgJiYgZWxlLm5laWdoYm9yaG9vZCgpLnNvbWUoZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbi5pc05vZGUoKSAmJiBtYXRjaGVzKGNoZWNrLm5laWdoYm9yLCBuKTtcbiAgfSk7XG59O1xuXG5tYXRjaFtUeXBlLkRJUkVDVEVEX0VER0VdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgcmV0dXJuIG1hdGNoZXMoY2hlY2suc291cmNlLCBlbGUuc291cmNlKCkpICYmIG1hdGNoZXMoY2hlY2sudGFyZ2V0LCBlbGUudGFyZ2V0KCkpO1xufTtcblxubWF0Y2hbVHlwZS5OT0RFX1NPVVJDRV0gPSBmdW5jdGlvbiAoY2hlY2ssIGVsZSkge1xuICByZXR1cm4gbWF0Y2hlcyhjaGVjay5zb3VyY2UsIGVsZSkgJiYgZWxlLm91dGdvZXJzKCkuc29tZShmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuLmlzTm9kZSgpICYmIG1hdGNoZXMoY2hlY2sudGFyZ2V0LCBuKTtcbiAgfSk7XG59O1xuXG5tYXRjaFtUeXBlLk5PREVfVEFSR0VUXSA9IGZ1bmN0aW9uIChjaGVjaywgZWxlKSB7XG4gIHJldHVybiBtYXRjaGVzKGNoZWNrLnRhcmdldCwgZWxlKSAmJiBlbGUuaW5jb21lcnMoKS5zb21lKGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4uaXNOb2RlKCkgJiYgbWF0Y2hlcyhjaGVjay5zb3VyY2UsIG4pO1xuICB9KTtcbn07XG5cbm1hdGNoW1R5cGUuQ0hJTERdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgcmV0dXJuIG1hdGNoZXMoY2hlY2suY2hpbGQsIGVsZSkgJiYgbWF0Y2hlcyhjaGVjay5wYXJlbnQsIGVsZS5wYXJlbnQoKSk7XG59O1xuXG5tYXRjaFtUeXBlLlBBUkVOVF0gPSBmdW5jdGlvbiAoY2hlY2ssIGVsZSkge1xuICByZXR1cm4gbWF0Y2hlcyhjaGVjay5wYXJlbnQsIGVsZSkgJiYgZWxlLmNoaWxkcmVuKCkuc29tZShmdW5jdGlvbiAoYykge1xuICAgIHJldHVybiBtYXRjaGVzKGNoZWNrLmNoaWxkLCBjKTtcbiAgfSk7XG59O1xuXG5tYXRjaFtUeXBlLkRFU0NFTkRBTlRdID0gZnVuY3Rpb24gKGNoZWNrLCBlbGUpIHtcbiAgcmV0dXJuIG1hdGNoZXMoY2hlY2suZGVzY2VuZGFudCwgZWxlKSAmJiBlbGUuYW5jZXN0b3JzKCkuc29tZShmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiBtYXRjaGVzKGNoZWNrLmFuY2VzdG9yLCBhKTtcbiAgfSk7XG59O1xuXG5tYXRjaFtUeXBlLkFOQ0VTVE9SXSA9IGZ1bmN0aW9uIChjaGVjaywgZWxlKSB7XG4gIHJldHVybiBtYXRjaGVzKGNoZWNrLmFuY2VzdG9yLCBlbGUpICYmIGVsZS5kZXNjZW5kYW50cygpLnNvbWUoZnVuY3Rpb24gKGQpIHtcbiAgICByZXR1cm4gbWF0Y2hlcyhjaGVjay5kZXNjZW5kYW50LCBkKTtcbiAgfSk7XG59O1xuXG5tYXRjaFtUeXBlLkNPTVBPVU5EX1NQTElUXSA9IGZ1bmN0aW9uIChjaGVjaywgZWxlKSB7XG4gIHJldHVybiBtYXRjaGVzKGNoZWNrLnN1YmplY3QsIGVsZSkgJiYgbWF0Y2hlcyhjaGVjay5sZWZ0LCBlbGUpICYmIG1hdGNoZXMoY2hlY2sucmlnaHQsIGVsZSk7XG59O1xuXG5tYXRjaFtUeXBlLlRSVUVdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdHJ1ZTtcbn07XG5cbm1hdGNoW1R5cGUuQ09MTEVDVElPTl0gPSBmdW5jdGlvbiAoY2hlY2ssIGVsZSkge1xuICB2YXIgY29sbGVjdGlvbiA9IGNoZWNrLnZhbHVlO1xuICByZXR1cm4gY29sbGVjdGlvbi5oYXMoZWxlKTtcbn07XG5cbm1hdGNoW1R5cGUuRklMVEVSXSA9IGZ1bmN0aW9uIChjaGVjaywgZWxlKSB7XG4gIHZhciBmaWx0ZXIgPSBjaGVjay52YWx1ZTtcbiAgcmV0dXJuIGZpbHRlcihlbGUpO1xufTtcblxudmFyIGZpbHRlciA9IGZ1bmN0aW9uIGZpbHRlcihjb2xsZWN0aW9uKSB7XG4gIHZhciBzZWxmID0gdGhpczsgLy8gZm9yIDEgaWQgI2ZvbyBxdWVyaWVzLCBqdXN0IGdldCB0aGUgZWxlbWVudFxuXG4gIGlmIChzZWxmLmxlbmd0aCA9PT0gMSAmJiBzZWxmWzBdLmNoZWNrcy5sZW5ndGggPT09IDEgJiYgc2VsZlswXS5jaGVja3NbMF0udHlwZSA9PT0gVHlwZS5JRCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmdldEVsZW1lbnRCeUlkKHNlbGZbMF0uY2hlY2tzWzBdLnZhbHVlKS5jb2xsZWN0aW9uKCk7XG4gIH1cblxuICB2YXIgc2VsZWN0b3JGdW5jdGlvbiA9IGZ1bmN0aW9uIHNlbGVjdG9yRnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgc2VsZi5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIHF1ZXJ5ID0gc2VsZltqXTtcblxuICAgICAgaWYgKG1hdGNoZXMocXVlcnksIGVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICBpZiAoc2VsZi50ZXh0KCkgPT0gbnVsbCkge1xuICAgIHNlbGVjdG9yRnVuY3Rpb24gPSBmdW5jdGlvbiBzZWxlY3RvckZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihzZWxlY3RvckZ1bmN0aW9uKTtcbn07IC8vIGZpbHRlclxuLy8gZG9lcyBzZWxlY3RvciBtYXRjaCBhIHNpbmdsZSBlbGVtZW50P1xuXG5cbnZhciBtYXRjaGVzJDEgPSBmdW5jdGlvbiBtYXRjaGVzJDEoZWxlKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICBmb3IgKHZhciBqID0gMDsgaiA8IHNlbGYubGVuZ3RoOyBqKyspIHtcbiAgICB2YXIgcXVlcnkgPSBzZWxmW2pdO1xuXG4gICAgaWYgKG1hdGNoZXMocXVlcnksIGVsZSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07IC8vIG1hdGNoZXNcblxuXG52YXIgbWF0Y2hpbmcgPSB7XG4gIG1hdGNoZXM6IG1hdGNoZXMkMSxcbiAgZmlsdGVyOiBmaWx0ZXJcbn07XG5cbnZhciBTZWxlY3RvciA9IGZ1bmN0aW9uIFNlbGVjdG9yKHNlbGVjdG9yKSB7XG4gIHRoaXMuaW5wdXRUZXh0ID0gc2VsZWN0b3I7XG4gIHRoaXMuY3VycmVudFN1YmplY3QgPSBudWxsO1xuICB0aGlzLmNvbXBvdW5kQ291bnQgPSAwO1xuICB0aGlzLmVkZ2VDb3VudCA9IDA7XG4gIHRoaXMubGVuZ3RoID0gMDtcblxuICBpZiAoc2VsZWN0b3IgPT0gbnVsbCB8fCBzdHJpbmcoc2VsZWN0b3IpICYmIHNlbGVjdG9yLm1hdGNoKC9eXFxzKiQvKSkgOyBlbHNlIGlmIChlbGVtZW50T3JDb2xsZWN0aW9uKHNlbGVjdG9yKSkge1xuICAgIHRoaXMuYWRkUXVlcnkoe1xuICAgICAgY2hlY2tzOiBbe1xuICAgICAgICB0eXBlOiBUeXBlLkNPTExFQ1RJT04sXG4gICAgICAgIHZhbHVlOiBzZWxlY3Rvci5jb2xsZWN0aW9uKClcbiAgICAgIH1dXG4gICAgfSk7XG4gIH0gZWxzZSBpZiAoZm4oc2VsZWN0b3IpKSB7XG4gICAgdGhpcy5hZGRRdWVyeSh7XG4gICAgICBjaGVja3M6IFt7XG4gICAgICAgIHR5cGU6IFR5cGUuRklMVEVSLFxuICAgICAgICB2YWx1ZTogc2VsZWN0b3JcbiAgICAgIH1dXG4gICAgfSk7XG4gIH0gZWxzZSBpZiAoc3RyaW5nKHNlbGVjdG9yKSkge1xuICAgIGlmICghdGhpcy5wYXJzZShzZWxlY3RvcikpIHtcbiAgICAgIHRoaXMuaW52YWxpZCA9IHRydWU7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGVycm9yKCdBIHNlbGVjdG9yIG11c3QgYmUgY3JlYXRlZCBmcm9tIGEgc3RyaW5nOyBmb3VuZCAnKTtcbiAgfVxufTtcblxudmFyIHNlbGZuID0gU2VsZWN0b3IucHJvdG90eXBlO1xuW3BhcnNlJDEsIG1hdGNoaW5nXS5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7XG4gIHJldHVybiBleHRlbmQoc2VsZm4sIHApO1xufSk7XG5cbnNlbGZuLnRleHQgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLmlucHV0VGV4dDtcbn07XG5cbnNlbGZuLnNpemUgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLmxlbmd0aDtcbn07XG5cbnNlbGZuLmVxID0gZnVuY3Rpb24gKGkpIHtcbiAgcmV0dXJuIHRoaXNbaV07XG59O1xuXG5zZWxmbi5zYW1lVGV4dCA9IGZ1bmN0aW9uIChvdGhlclNlbCkge1xuICByZXR1cm4gIXRoaXMuaW52YWxpZCAmJiAhb3RoZXJTZWwuaW52YWxpZCAmJiB0aGlzLnRleHQoKSA9PT0gb3RoZXJTZWwudGV4dCgpO1xufTtcblxuc2VsZm4uYWRkUXVlcnkgPSBmdW5jdGlvbiAocSkge1xuICB0aGlzW3RoaXMubGVuZ3RoKytdID0gcTtcbn07XG5cbnNlbGZuLnNlbGVjdG9yID0gc2VsZm4udG9TdHJpbmc7XG5cbnZhciBlbGVzZm4kZiA9IHtcbiAgYWxsQXJlOiBmdW5jdGlvbiBhbGxBcmUoc2VsZWN0b3IpIHtcbiAgICB2YXIgc2VsT2JqID0gbmV3IFNlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICByZXR1cm4gdGhpcy5ldmVyeShmdW5jdGlvbiAoZWxlKSB7XG4gICAgICByZXR1cm4gc2VsT2JqLm1hdGNoZXMoZWxlKTtcbiAgICB9KTtcbiAgfSxcbiAgaXM6IGZ1bmN0aW9uIGlzKHNlbGVjdG9yKSB7XG4gICAgdmFyIHNlbE9iaiA9IG5ldyBTZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgcmV0dXJuIHRoaXMuc29tZShmdW5jdGlvbiAoZWxlKSB7XG4gICAgICByZXR1cm4gc2VsT2JqLm1hdGNoZXMoZWxlKTtcbiAgICB9KTtcbiAgfSxcbiAgc29tZTogZnVuY3Rpb24gc29tZShmbiwgdGhpc0FyZykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHJldCA9ICF0aGlzQXJnID8gZm4odGhpc1tpXSwgaSwgdGhpcykgOiBmbi5hcHBseSh0aGlzQXJnLCBbdGhpc1tpXSwgaSwgdGhpc10pO1xuXG4gICAgICBpZiAocmV0KSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcbiAgZXZlcnk6IGZ1bmN0aW9uIGV2ZXJ5KGZuLCB0aGlzQXJnKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcmV0ID0gIXRoaXNBcmcgPyBmbih0aGlzW2ldLCBpLCB0aGlzKSA6IGZuLmFwcGx5KHRoaXNBcmcsIFt0aGlzW2ldLCBpLCB0aGlzXSk7XG5cbiAgICAgIGlmICghcmV0KSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgc2FtZTogZnVuY3Rpb24gc2FtZShjb2xsZWN0aW9uKSB7XG4gICAgLy8gY2hlYXAgY29sbGVjdGlvbiByZWYgY2hlY2tcbiAgICBpZiAodGhpcyA9PT0gY29sbGVjdGlvbikge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29sbGVjdGlvbiA9IHRoaXMuY3koKS5jb2xsZWN0aW9uKGNvbGxlY3Rpb24pO1xuICAgIHZhciB0aGlzTGVuZ3RoID0gdGhpcy5sZW5ndGg7XG4gICAgdmFyIGNvbGxlY3Rpb25MZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDsgLy8gY2hlYXAgbGVuZ3RoIGNoZWNrXG5cbiAgICBpZiAodGhpc0xlbmd0aCAhPT0gY29sbGVjdGlvbkxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gLy8gY2hlYXAgZWxlbWVudCByZWYgY2hlY2tcblxuXG4gICAgaWYgKHRoaXNMZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiB0aGlzWzBdID09PSBjb2xsZWN0aW9uWzBdO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmV2ZXJ5KGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmhhc0VsZW1lbnRXaXRoSWQoZWxlLmlkKCkpO1xuICAgIH0pO1xuICB9LFxuICBhbnlTYW1lOiBmdW5jdGlvbiBhbnlTYW1lKGNvbGxlY3Rpb24pIHtcbiAgICBjb2xsZWN0aW9uID0gdGhpcy5jeSgpLmNvbGxlY3Rpb24oY29sbGVjdGlvbik7XG4gICAgcmV0dXJuIHRoaXMuc29tZShmdW5jdGlvbiAoZWxlKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5oYXNFbGVtZW50V2l0aElkKGVsZS5pZCgpKTtcbiAgICB9KTtcbiAgfSxcbiAgYWxsQXJlTmVpZ2hib3JzOiBmdW5jdGlvbiBhbGxBcmVOZWlnaGJvcnMoY29sbGVjdGlvbikge1xuICAgIGNvbGxlY3Rpb24gPSB0aGlzLmN5KCkuY29sbGVjdGlvbihjb2xsZWN0aW9uKTtcbiAgICB2YXIgbmhvb2QgPSB0aGlzLm5laWdoYm9yaG9vZCgpO1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmV2ZXJ5KGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgIHJldHVybiBuaG9vZC5oYXNFbGVtZW50V2l0aElkKGVsZS5pZCgpKTtcbiAgICB9KTtcbiAgfSxcbiAgY29udGFpbnM6IGZ1bmN0aW9uIGNvbnRhaW5zKGNvbGxlY3Rpb24pIHtcbiAgICBjb2xsZWN0aW9uID0gdGhpcy5jeSgpLmNvbGxlY3Rpb24oY29sbGVjdGlvbik7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmV2ZXJ5KGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgIHJldHVybiBzZWxmLmhhc0VsZW1lbnRXaXRoSWQoZWxlLmlkKCkpO1xuICAgIH0pO1xuICB9XG59O1xuZWxlc2ZuJGYuYWxsQXJlTmVpZ2hib3VycyA9IGVsZXNmbiRmLmFsbEFyZU5laWdoYm9ycztcbmVsZXNmbiRmLmhhcyA9IGVsZXNmbiRmLmNvbnRhaW5zO1xuZWxlc2ZuJGYuZXF1YWwgPSBlbGVzZm4kZi5lcXVhbHMgPSBlbGVzZm4kZi5zYW1lO1xuXG52YXIgY2FjaGUgPSBmdW5jdGlvbiBjYWNoZShmbiwgbmFtZSkge1xuICByZXR1cm4gZnVuY3Rpb24gdHJhdmVyc2FsQ2FjaGUoYXJnMSwgYXJnMiwgYXJnMywgYXJnNCkge1xuICAgIHZhciBzZWxlY3Rvck9yRWxlcyA9IGFyZzE7XG4gICAgdmFyIGVsZXMgPSB0aGlzO1xuICAgIHZhciBrZXk7XG5cbiAgICBpZiAoc2VsZWN0b3JPckVsZXMgPT0gbnVsbCkge1xuICAgICAga2V5ID0gJyc7XG4gICAgfSBlbHNlIGlmIChlbGVtZW50T3JDb2xsZWN0aW9uKHNlbGVjdG9yT3JFbGVzKSAmJiBzZWxlY3Rvck9yRWxlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgIGtleSA9IHNlbGVjdG9yT3JFbGVzLmlkKCk7XG4gICAgfVxuXG4gICAgaWYgKGVsZXMubGVuZ3RoID09PSAxICYmIGtleSkge1xuICAgICAgdmFyIF9wID0gZWxlc1swXS5fcHJpdmF0ZTtcbiAgICAgIHZhciB0Y2ggPSBfcC50cmF2ZXJzYWxDYWNoZSA9IF9wLnRyYXZlcnNhbENhY2hlIHx8IHt9O1xuICAgICAgdmFyIGNoID0gdGNoW25hbWVdID0gdGNoW25hbWVdIHx8IFtdO1xuICAgICAgdmFyIGhhc2ggPSBoYXNoU3RyaW5nKGtleSk7XG4gICAgICB2YXIgY2FjaGVIaXQgPSBjaFtoYXNoXTtcblxuICAgICAgaWYgKGNhY2hlSGl0KSB7XG4gICAgICAgIHJldHVybiBjYWNoZUhpdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBjaFtoYXNoXSA9IGZuLmNhbGwoZWxlcywgYXJnMSwgYXJnMiwgYXJnMywgYXJnNCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmbi5jYWxsKGVsZXMsIGFyZzEsIGFyZzIsIGFyZzMsIGFyZzQpO1xuICAgIH1cbiAgfTtcbn07XG5cbnZhciBlbGVzZm4kZyA9IHtcbiAgcGFyZW50OiBmdW5jdGlvbiBwYXJlbnQoc2VsZWN0b3IpIHtcbiAgICB2YXIgcGFyZW50cyA9IFtdOyAvLyBvcHRpbWlzYXRpb24gZm9yIHNpbmdsZSBlbGUgY2FsbFxuXG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAxKSB7XG4gICAgICB2YXIgcGFyZW50ID0gdGhpc1swXS5fcHJpdmF0ZS5wYXJlbnQ7XG5cbiAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBlbGUgPSB0aGlzW2ldO1xuICAgICAgdmFyIF9wYXJlbnQgPSBlbGUuX3ByaXZhdGUucGFyZW50O1xuXG4gICAgICBpZiAoX3BhcmVudCkge1xuICAgICAgICBwYXJlbnRzLnB1c2goX3BhcmVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24ocGFyZW50cywge1xuICAgICAgdW5pcXVlOiB0cnVlXG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSxcbiAgcGFyZW50czogZnVuY3Rpb24gcGFyZW50cyhzZWxlY3Rvcikge1xuICAgIHZhciBwYXJlbnRzID0gW107XG4gICAgdmFyIGVsZXMgPSB0aGlzLnBhcmVudCgpO1xuXG4gICAgd2hpbGUgKGVsZXMubm9uZW1wdHkoKSkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSBlbGVzW2ldO1xuICAgICAgICBwYXJlbnRzLnB1c2goZWxlKTtcbiAgICAgIH1cblxuICAgICAgZWxlcyA9IGVsZXMucGFyZW50KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24ocGFyZW50cywge1xuICAgICAgdW5pcXVlOiB0cnVlXG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSxcbiAgY29tbW9uQW5jZXN0b3JzOiBmdW5jdGlvbiBjb21tb25BbmNlc3RvcnMoc2VsZWN0b3IpIHtcbiAgICB2YXIgYW5jZXN0b3JzO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICAgIHZhciBwYXJlbnRzID0gZWxlLnBhcmVudHMoKTtcbiAgICAgIGFuY2VzdG9ycyA9IGFuY2VzdG9ycyB8fCBwYXJlbnRzO1xuICAgICAgYW5jZXN0b3JzID0gYW5jZXN0b3JzLmludGVyc2VjdChwYXJlbnRzKTsgLy8gY3VycmVudCBsaXN0IG11c3QgYmUgY29tbW9uIHdpdGggY3VycmVudCBlbGUgcGFyZW50cyBzZXRcbiAgICB9XG5cbiAgICByZXR1cm4gYW5jZXN0b3JzLmZpbHRlcihzZWxlY3Rvcik7XG4gIH0sXG4gIG9ycGhhbnM6IGZ1bmN0aW9uIG9ycGhhbnMoc2VsZWN0b3IpIHtcbiAgICByZXR1cm4gdGhpcy5zdGRGaWx0ZXIoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgcmV0dXJuIGVsZS5pc09ycGhhbigpO1xuICAgIH0pLmZpbHRlcihzZWxlY3Rvcik7XG4gIH0sXG4gIG5vbm9ycGhhbnM6IGZ1bmN0aW9uIG5vbm9ycGhhbnMoc2VsZWN0b3IpIHtcbiAgICByZXR1cm4gdGhpcy5zdGRGaWx0ZXIoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgcmV0dXJuIGVsZS5pc0NoaWxkKCk7XG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSxcbiAgY2hpbGRyZW46IGNhY2hlKGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICAgIHZhciBjaGlsZHJlbiA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICAgIHZhciBlbGVDaGlsZHJlbiA9IGVsZS5fcHJpdmF0ZS5jaGlsZHJlbjtcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBlbGVDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICBjaGlsZHJlbi5wdXNoKGVsZUNoaWxkcmVuW2pdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zcGF3bihjaGlsZHJlbiwge1xuICAgICAgdW5pcXVlOiB0cnVlXG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSwgJ2NoaWxkcmVuJyksXG4gIHNpYmxpbmdzOiBmdW5jdGlvbiBzaWJsaW5ncyhzZWxlY3Rvcikge1xuICAgIHJldHVybiB0aGlzLnBhcmVudCgpLmNoaWxkcmVuKCkubm90KHRoaXMpLmZpbHRlcihzZWxlY3Rvcik7XG4gIH0sXG4gIGlzUGFyZW50OiBmdW5jdGlvbiBpc1BhcmVudCgpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIHJldHVybiBlbGUuaXNOb2RlKCkgJiYgZWxlLl9wcml2YXRlLmNoaWxkcmVuLmxlbmd0aCAhPT0gMDtcbiAgICB9XG4gIH0sXG4gIGlzQ2hpbGRsZXNzOiBmdW5jdGlvbiBpc0NoaWxkbGVzcygpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIHJldHVybiBlbGUuaXNOb2RlKCkgJiYgZWxlLl9wcml2YXRlLmNoaWxkcmVuLmxlbmd0aCA9PT0gMDtcbiAgICB9XG4gIH0sXG4gIGlzQ2hpbGQ6IGZ1bmN0aW9uIGlzQ2hpbGQoKSB7XG4gICAgdmFyIGVsZSA9IHRoaXNbMF07XG5cbiAgICBpZiAoZWxlKSB7XG4gICAgICByZXR1cm4gZWxlLmlzTm9kZSgpICYmIGVsZS5fcHJpdmF0ZS5wYXJlbnQgIT0gbnVsbDtcbiAgICB9XG4gIH0sXG4gIGlzT3JwaGFuOiBmdW5jdGlvbiBpc09ycGhhbigpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIHJldHVybiBlbGUuaXNOb2RlKCkgJiYgZWxlLl9wcml2YXRlLnBhcmVudCA9PSBudWxsO1xuICAgIH1cbiAgfSxcbiAgZGVzY2VuZGFudHM6IGZ1bmN0aW9uIGRlc2NlbmRhbnRzKHNlbGVjdG9yKSB7XG4gICAgdmFyIGVsZW1lbnRzID0gW107XG5cbiAgICBmdW5jdGlvbiBhZGQoZWxlcykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSBlbGVzW2ldO1xuICAgICAgICBlbGVtZW50cy5wdXNoKGVsZSk7XG5cbiAgICAgICAgaWYgKGVsZS5jaGlsZHJlbigpLm5vbmVtcHR5KCkpIHtcbiAgICAgICAgICBhZGQoZWxlLmNoaWxkcmVuKCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgYWRkKHRoaXMuY2hpbGRyZW4oKSk7XG4gICAgcmV0dXJuIHRoaXMuc3Bhd24oZWxlbWVudHMsIHtcbiAgICAgIHVuaXF1ZTogdHJ1ZVxuICAgIH0pLmZpbHRlcihzZWxlY3Rvcik7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGZvckVhY2hDb21wb3VuZChlbGVzLCBmbiwgaW5jbHVkZVNlbGYsIHJlY3Vyc2l2ZVN0ZXApIHtcbiAgdmFyIHEgPSBbXTtcbiAgdmFyIGRpZCA9IG5ldyBTZXQkMSgpO1xuICB2YXIgY3kgPSBlbGVzLmN5KCk7XG4gIHZhciBoYXNDb21wb3VuZHMgPSBjeS5oYXNDb21wb3VuZE5vZGVzKCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IGVsZXNbaV07XG5cbiAgICBpZiAoaW5jbHVkZVNlbGYpIHtcbiAgICAgIHEucHVzaChlbGUpO1xuICAgIH0gZWxzZSBpZiAoaGFzQ29tcG91bmRzKSB7XG4gICAgICByZWN1cnNpdmVTdGVwKHEsIGRpZCwgZWxlKTtcbiAgICB9XG4gIH1cblxuICB3aGlsZSAocS5sZW5ndGggPiAwKSB7XG4gICAgdmFyIF9lbGUgPSBxLnNoaWZ0KCk7XG5cbiAgICBmbihfZWxlKTtcbiAgICBkaWQuYWRkKF9lbGUuaWQoKSk7XG5cbiAgICBpZiAoaGFzQ29tcG91bmRzKSB7XG4gICAgICByZWN1cnNpdmVTdGVwKHEsIGRpZCwgX2VsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGVsZXM7XG59XG5cbmZ1bmN0aW9uIGFkZENoaWxkcmVuKHEsIGRpZCwgZWxlKSB7XG4gIGlmIChlbGUuaXNQYXJlbnQoKSkge1xuICAgIHZhciBjaGlsZHJlbiA9IGVsZS5fcHJpdmF0ZS5jaGlsZHJlbjtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICBpZiAoIWRpZC5oYXMoY2hpbGQuaWQoKSkpIHtcbiAgICAgICAgcS5wdXNoKGNoaWxkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn0gLy8gdmVyeSBlZmZpY2llbnQgdmVyc2lvbiBvZiBlbGVzLmFkZCggZWxlcy5kZXNjZW5kYW50cygpICkuZm9yRWFjaCgpXG4vLyBmb3IgaW50ZXJuYWwgdXNlXG5cblxuZWxlc2ZuJGcuZm9yRWFjaERvd24gPSBmdW5jdGlvbiAoZm4pIHtcbiAgdmFyIGluY2x1ZGVTZWxmID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB0cnVlO1xuICByZXR1cm4gZm9yRWFjaENvbXBvdW5kKHRoaXMsIGZuLCBpbmNsdWRlU2VsZiwgYWRkQ2hpbGRyZW4pO1xufTtcblxuZnVuY3Rpb24gYWRkUGFyZW50KHEsIGRpZCwgZWxlKSB7XG4gIGlmIChlbGUuaXNDaGlsZCgpKSB7XG4gICAgdmFyIHBhcmVudCA9IGVsZS5fcHJpdmF0ZS5wYXJlbnQ7XG5cbiAgICBpZiAoIWRpZC5oYXMocGFyZW50LmlkKCkpKSB7XG4gICAgICBxLnB1c2gocGFyZW50KTtcbiAgICB9XG4gIH1cbn1cblxuZWxlc2ZuJGcuZm9yRWFjaFVwID0gZnVuY3Rpb24gKGZuKSB7XG4gIHZhciBpbmNsdWRlU2VsZiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogdHJ1ZTtcbiAgcmV0dXJuIGZvckVhY2hDb21wb3VuZCh0aGlzLCBmbiwgaW5jbHVkZVNlbGYsIGFkZFBhcmVudCk7XG59O1xuXG5mdW5jdGlvbiBhZGRQYXJlbnRBbmRDaGlsZHJlbihxLCBkaWQsIGVsZSkge1xuICBhZGRQYXJlbnQocSwgZGlkLCBlbGUpO1xuICBhZGRDaGlsZHJlbihxLCBkaWQsIGVsZSk7XG59XG5cbmVsZXNmbiRnLmZvckVhY2hVcEFuZERvd24gPSBmdW5jdGlvbiAoZm4pIHtcbiAgdmFyIGluY2x1ZGVTZWxmID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB0cnVlO1xuICByZXR1cm4gZm9yRWFjaENvbXBvdW5kKHRoaXMsIGZuLCBpbmNsdWRlU2VsZiwgYWRkUGFyZW50QW5kQ2hpbGRyZW4pO1xufTsgLy8gYWxpYXNlc1xuXG5cbmVsZXNmbiRnLmFuY2VzdG9ycyA9IGVsZXNmbiRnLnBhcmVudHM7XG5cbnZhciBmbiQxLCBlbGVzZm4kaDtcbmZuJDEgPSBlbGVzZm4kaCA9IHtcbiAgZGF0YTogZGVmaW5lJDMuZGF0YSh7XG4gICAgZmllbGQ6ICdkYXRhJyxcbiAgICBiaW5kaW5nRXZlbnQ6ICdkYXRhJyxcbiAgICBhbGxvd0JpbmRpbmc6IHRydWUsXG4gICAgYWxsb3dTZXR0aW5nOiB0cnVlLFxuICAgIHNldHRpbmdFdmVudDogJ2RhdGEnLFxuICAgIHNldHRpbmdUcmlnZ2Vyc0V2ZW50OiB0cnVlLFxuICAgIHRyaWdnZXJGbk5hbWU6ICd0cmlnZ2VyJyxcbiAgICBhbGxvd0dldHRpbmc6IHRydWUsXG4gICAgaW1tdXRhYmxlS2V5czoge1xuICAgICAgJ2lkJzogdHJ1ZSxcbiAgICAgICdzb3VyY2UnOiB0cnVlLFxuICAgICAgJ3RhcmdldCc6IHRydWUsXG4gICAgICAncGFyZW50JzogdHJ1ZVxuICAgIH0sXG4gICAgdXBkYXRlU3R5bGU6IHRydWVcbiAgfSksXG4gIHJlbW92ZURhdGE6IGRlZmluZSQzLnJlbW92ZURhdGEoe1xuICAgIGZpZWxkOiAnZGF0YScsXG4gICAgZXZlbnQ6ICdkYXRhJyxcbiAgICB0cmlnZ2VyRm5OYW1lOiAndHJpZ2dlcicsXG4gICAgdHJpZ2dlckV2ZW50OiB0cnVlLFxuICAgIGltbXV0YWJsZUtleXM6IHtcbiAgICAgICdpZCc6IHRydWUsXG4gICAgICAnc291cmNlJzogdHJ1ZSxcbiAgICAgICd0YXJnZXQnOiB0cnVlLFxuICAgICAgJ3BhcmVudCc6IHRydWVcbiAgICB9LFxuICAgIHVwZGF0ZVN0eWxlOiB0cnVlXG4gIH0pLFxuICBzY3JhdGNoOiBkZWZpbmUkMy5kYXRhKHtcbiAgICBmaWVsZDogJ3NjcmF0Y2gnLFxuICAgIGJpbmRpbmdFdmVudDogJ3NjcmF0Y2gnLFxuICAgIGFsbG93QmluZGluZzogdHJ1ZSxcbiAgICBhbGxvd1NldHRpbmc6IHRydWUsXG4gICAgc2V0dGluZ0V2ZW50OiAnc2NyYXRjaCcsXG4gICAgc2V0dGluZ1RyaWdnZXJzRXZlbnQ6IHRydWUsXG4gICAgdHJpZ2dlckZuTmFtZTogJ3RyaWdnZXInLFxuICAgIGFsbG93R2V0dGluZzogdHJ1ZSxcbiAgICB1cGRhdGVTdHlsZTogdHJ1ZVxuICB9KSxcbiAgcmVtb3ZlU2NyYXRjaDogZGVmaW5lJDMucmVtb3ZlRGF0YSh7XG4gICAgZmllbGQ6ICdzY3JhdGNoJyxcbiAgICBldmVudDogJ3NjcmF0Y2gnLFxuICAgIHRyaWdnZXJGbk5hbWU6ICd0cmlnZ2VyJyxcbiAgICB0cmlnZ2VyRXZlbnQ6IHRydWUsXG4gICAgdXBkYXRlU3R5bGU6IHRydWVcbiAgfSksXG4gIHJzY3JhdGNoOiBkZWZpbmUkMy5kYXRhKHtcbiAgICBmaWVsZDogJ3JzY3JhdGNoJyxcbiAgICBhbGxvd0JpbmRpbmc6IGZhbHNlLFxuICAgIGFsbG93U2V0dGluZzogdHJ1ZSxcbiAgICBzZXR0aW5nVHJpZ2dlcnNFdmVudDogZmFsc2UsXG4gICAgYWxsb3dHZXR0aW5nOiB0cnVlXG4gIH0pLFxuICByZW1vdmVSc2NyYXRjaDogZGVmaW5lJDMucmVtb3ZlRGF0YSh7XG4gICAgZmllbGQ6ICdyc2NyYXRjaCcsXG4gICAgdHJpZ2dlckV2ZW50OiBmYWxzZVxuICB9KSxcbiAgaWQ6IGZ1bmN0aW9uIGlkKCkge1xuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuXG4gICAgaWYgKGVsZSkge1xuICAgICAgcmV0dXJuIGVsZS5fcHJpdmF0ZS5kYXRhLmlkO1xuICAgIH1cbiAgfVxufTsgLy8gYWxpYXNlc1xuXG5mbiQxLmF0dHIgPSBmbiQxLmRhdGE7XG5mbiQxLnJlbW92ZUF0dHIgPSBmbiQxLnJlbW92ZURhdGE7XG52YXIgZGF0YSQxID0gZWxlc2ZuJGg7XG5cbnZhciBlbGVzZm4kaSA9IHt9O1xuXG5mdW5jdGlvbiBkZWZpbmVEZWdyZWVGdW5jdGlvbihjYWxsYmFjaykge1xuICByZXR1cm4gZnVuY3Rpb24gKGluY2x1ZGVMb29wcykge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIGlmIChpbmNsdWRlTG9vcHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgaW5jbHVkZUxvb3BzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoc2VsZi5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoc2VsZi5pc05vZGUoKSAmJiAhc2VsZi5yZW1vdmVkKCkpIHtcbiAgICAgIHZhciBkZWdyZWUgPSAwO1xuICAgICAgdmFyIG5vZGUgPSBzZWxmWzBdO1xuICAgICAgdmFyIGNvbm5lY3RlZEVkZ2VzID0gbm9kZS5fcHJpdmF0ZS5lZGdlcztcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb25uZWN0ZWRFZGdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWRnZSA9IGNvbm5lY3RlZEVkZ2VzW2ldO1xuXG4gICAgICAgIGlmICghaW5jbHVkZUxvb3BzICYmIGVkZ2UuaXNMb29wKCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRlZ3JlZSArPSBjYWxsYmFjayhub2RlLCBlZGdlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGRlZ3JlZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfTtcbn1cblxuZXh0ZW5kKGVsZXNmbiRpLCB7XG4gIGRlZ3JlZTogZGVmaW5lRGVncmVlRnVuY3Rpb24oZnVuY3Rpb24gKG5vZGUsIGVkZ2UpIHtcbiAgICBpZiAoZWRnZS5zb3VyY2UoKS5zYW1lKGVkZ2UudGFyZ2V0KCkpKSB7XG4gICAgICByZXR1cm4gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICB9KSxcbiAgaW5kZWdyZWU6IGRlZmluZURlZ3JlZUZ1bmN0aW9uKGZ1bmN0aW9uIChub2RlLCBlZGdlKSB7XG4gICAgaWYgKGVkZ2UudGFyZ2V0KCkuc2FtZShub2RlKSkge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSksXG4gIG91dGRlZ3JlZTogZGVmaW5lRGVncmVlRnVuY3Rpb24oZnVuY3Rpb24gKG5vZGUsIGVkZ2UpIHtcbiAgICBpZiAoZWRnZS5zb3VyY2UoKS5zYW1lKG5vZGUpKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICB9KVxufSk7XG5cbmZ1bmN0aW9uIGRlZmluZURlZ3JlZUJvdW5kc0Z1bmN0aW9uKGRlZ3JlZUZuLCBjYWxsYmFjaykge1xuICByZXR1cm4gZnVuY3Rpb24gKGluY2x1ZGVMb29wcykge1xuICAgIHZhciByZXQ7XG4gICAgdmFyIG5vZGVzID0gdGhpcy5ub2RlcygpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGVsZSA9IG5vZGVzW2ldO1xuICAgICAgdmFyIGRlZ3JlZSA9IGVsZVtkZWdyZWVGbl0oaW5jbHVkZUxvb3BzKTtcblxuICAgICAgaWYgKGRlZ3JlZSAhPT0gdW5kZWZpbmVkICYmIChyZXQgPT09IHVuZGVmaW5lZCB8fCBjYWxsYmFjayhkZWdyZWUsIHJldCkpKSB7XG4gICAgICAgIHJldCA9IGRlZ3JlZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xuICB9O1xufVxuXG5leHRlbmQoZWxlc2ZuJGksIHtcbiAgbWluRGVncmVlOiBkZWZpbmVEZWdyZWVCb3VuZHNGdW5jdGlvbignZGVncmVlJywgZnVuY3Rpb24gKGRlZ3JlZSwgbWluKSB7XG4gICAgcmV0dXJuIGRlZ3JlZSA8IG1pbjtcbiAgfSksXG4gIG1heERlZ3JlZTogZGVmaW5lRGVncmVlQm91bmRzRnVuY3Rpb24oJ2RlZ3JlZScsIGZ1bmN0aW9uIChkZWdyZWUsIG1heCkge1xuICAgIHJldHVybiBkZWdyZWUgPiBtYXg7XG4gIH0pLFxuICBtaW5JbmRlZ3JlZTogZGVmaW5lRGVncmVlQm91bmRzRnVuY3Rpb24oJ2luZGVncmVlJywgZnVuY3Rpb24gKGRlZ3JlZSwgbWluKSB7XG4gICAgcmV0dXJuIGRlZ3JlZSA8IG1pbjtcbiAgfSksXG4gIG1heEluZGVncmVlOiBkZWZpbmVEZWdyZWVCb3VuZHNGdW5jdGlvbignaW5kZWdyZWUnLCBmdW5jdGlvbiAoZGVncmVlLCBtYXgpIHtcbiAgICByZXR1cm4gZGVncmVlID4gbWF4O1xuICB9KSxcbiAgbWluT3V0ZGVncmVlOiBkZWZpbmVEZWdyZWVCb3VuZHNGdW5jdGlvbignb3V0ZGVncmVlJywgZnVuY3Rpb24gKGRlZ3JlZSwgbWluKSB7XG4gICAgcmV0dXJuIGRlZ3JlZSA8IG1pbjtcbiAgfSksXG4gIG1heE91dGRlZ3JlZTogZGVmaW5lRGVncmVlQm91bmRzRnVuY3Rpb24oJ291dGRlZ3JlZScsIGZ1bmN0aW9uIChkZWdyZWUsIG1heCkge1xuICAgIHJldHVybiBkZWdyZWUgPiBtYXg7XG4gIH0pXG59KTtcbmV4dGVuZChlbGVzZm4kaSwge1xuICB0b3RhbERlZ3JlZTogZnVuY3Rpb24gdG90YWxEZWdyZWUoaW5jbHVkZUxvb3BzKSB7XG4gICAgdmFyIHRvdGFsID0gMDtcbiAgICB2YXIgbm9kZXMgPSB0aGlzLm5vZGVzKCk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0b3RhbCArPSBub2Rlc1tpXS5kZWdyZWUoaW5jbHVkZUxvb3BzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdG90YWw7XG4gIH1cbn0pO1xuXG52YXIgZm4kMiwgZWxlc2ZuJGo7XG5cbnZhciBiZWZvcmVQb3NpdGlvblNldCA9IGZ1bmN0aW9uIGJlZm9yZVBvc2l0aW9uU2V0KGVsZXMsIG5ld1Bvcywgc2lsZW50KSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBlbGUgPSBlbGVzW2ldO1xuXG4gICAgaWYgKCFlbGUubG9ja2VkKCkpIHtcbiAgICAgIHZhciBvbGRQb3MgPSBlbGUuX3ByaXZhdGUucG9zaXRpb247XG4gICAgICB2YXIgZGVsdGEgPSB7XG4gICAgICAgIHg6IG5ld1Bvcy54ICE9IG51bGwgPyBuZXdQb3MueCAtIG9sZFBvcy54IDogMCxcbiAgICAgICAgeTogbmV3UG9zLnkgIT0gbnVsbCA/IG5ld1Bvcy55IC0gb2xkUG9zLnkgOiAwXG4gICAgICB9O1xuXG4gICAgICBpZiAoZWxlLmlzUGFyZW50KCkgJiYgIShkZWx0YS54ID09PSAwICYmIGRlbHRhLnkgPT09IDApKSB7XG4gICAgICAgIGVsZS5jaGlsZHJlbigpLnNoaWZ0KGRlbHRhLCBzaWxlbnQpO1xuICAgICAgfVxuXG4gICAgICBlbGUuc2hpZnRDYWNoZWRCb3VuZGluZ0JveChkZWx0YSk7XG4gICAgfVxuICB9XG59O1xuXG52YXIgcG9zaXRpb25EZWYgPSB7XG4gIGZpZWxkOiAncG9zaXRpb24nLFxuICBiaW5kaW5nRXZlbnQ6ICdwb3NpdGlvbicsXG4gIGFsbG93QmluZGluZzogdHJ1ZSxcbiAgYWxsb3dTZXR0aW5nOiB0cnVlLFxuICBzZXR0aW5nRXZlbnQ6ICdwb3NpdGlvbicsXG4gIHNldHRpbmdUcmlnZ2Vyc0V2ZW50OiB0cnVlLFxuICB0cmlnZ2VyRm5OYW1lOiAnZW1pdEFuZE5vdGlmeScsXG4gIGFsbG93R2V0dGluZzogdHJ1ZSxcbiAgdmFsaWRLZXlzOiBbJ3gnLCAneSddLFxuICBiZWZvcmVHZXQ6IGZ1bmN0aW9uIGJlZm9yZUdldChlbGUpIHtcbiAgICBlbGUudXBkYXRlQ29tcG91bmRCb3VuZHMoKTtcbiAgfSxcbiAgYmVmb3JlU2V0OiBmdW5jdGlvbiBiZWZvcmVTZXQoZWxlcywgbmV3UG9zKSB7XG4gICAgYmVmb3JlUG9zaXRpb25TZXQoZWxlcywgbmV3UG9zLCBmYWxzZSk7XG4gIH0sXG4gIG9uU2V0OiBmdW5jdGlvbiBvblNldChlbGVzKSB7XG4gICAgZWxlcy5kaXJ0eUNvbXBvdW5kQm91bmRzQ2FjaGUoKTtcbiAgfSxcbiAgY2FuU2V0OiBmdW5jdGlvbiBjYW5TZXQoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUubG9ja2VkKCk7XG4gIH1cbn07XG5mbiQyID0gZWxlc2ZuJGogPSB7XG4gIHBvc2l0aW9uOiBkZWZpbmUkMy5kYXRhKHBvc2l0aW9uRGVmKSxcbiAgLy8gcG9zaXRpb24gYnV0IG5vIG5vdGlmaWNhdGlvbiB0byByZW5kZXJlclxuICBzaWxlbnRQb3NpdGlvbjogZGVmaW5lJDMuZGF0YShleHRlbmQoe30sIHBvc2l0aW9uRGVmLCB7XG4gICAgYWxsb3dCaW5kaW5nOiBmYWxzZSxcbiAgICBhbGxvd1NldHRpbmc6IHRydWUsXG4gICAgc2V0dGluZ1RyaWdnZXJzRXZlbnQ6IGZhbHNlLFxuICAgIGFsbG93R2V0dGluZzogZmFsc2UsXG4gICAgYmVmb3JlU2V0OiBmdW5jdGlvbiBiZWZvcmVTZXQoZWxlcywgbmV3UG9zKSB7XG4gICAgICBiZWZvcmVQb3NpdGlvblNldChlbGVzLCBuZXdQb3MsIHRydWUpO1xuICAgIH1cbiAgfSkpLFxuICBwb3NpdGlvbnM6IGZ1bmN0aW9uIHBvc2l0aW9ucyhwb3MsIHNpbGVudCkge1xuICAgIGlmIChwbGFpbk9iamVjdChwb3MpKSB7XG4gICAgICBpZiAoc2lsZW50KSB7XG4gICAgICAgIHRoaXMuc2lsZW50UG9zaXRpb24ocG9zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucG9zaXRpb24ocG9zKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGZuKHBvcykpIHtcbiAgICAgIHZhciBfZm4gPSBwb3M7XG4gICAgICB2YXIgY3kgPSB0aGlzLmN5KCk7XG4gICAgICBjeS5zdGFydEJhdGNoKCk7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWxlID0gdGhpc1tpXTtcblxuICAgICAgICB2YXIgX3BvcyA9IHZvaWQgMDtcblxuICAgICAgICBpZiAoX3BvcyA9IF9mbihlbGUsIGkpKSB7XG4gICAgICAgICAgaWYgKHNpbGVudCkge1xuICAgICAgICAgICAgZWxlLnNpbGVudFBvc2l0aW9uKF9wb3MpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGUucG9zaXRpb24oX3Bvcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGN5LmVuZEJhdGNoKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gIH0sXG4gIHNpbGVudFBvc2l0aW9uczogZnVuY3Rpb24gc2lsZW50UG9zaXRpb25zKHBvcykge1xuICAgIHJldHVybiB0aGlzLnBvc2l0aW9ucyhwb3MsIHRydWUpO1xuICB9LFxuICBzaGlmdDogZnVuY3Rpb24gc2hpZnQoZGltLCB2YWwsIHNpbGVudCkge1xuICAgIHZhciBkZWx0YTtcblxuICAgIGlmIChwbGFpbk9iamVjdChkaW0pKSB7XG4gICAgICBkZWx0YSA9IHtcbiAgICAgICAgeDogbnVtYmVyKGRpbS54KSA/IGRpbS54IDogMCxcbiAgICAgICAgeTogbnVtYmVyKGRpbS55KSA/IGRpbS55IDogMFxuICAgICAgfTtcbiAgICAgIHNpbGVudCA9IHZhbDtcbiAgICB9IGVsc2UgaWYgKHN0cmluZyhkaW0pICYmIG51bWJlcih2YWwpKSB7XG4gICAgICBkZWx0YSA9IHtcbiAgICAgICAgeDogMCxcbiAgICAgICAgeTogMFxuICAgICAgfTtcbiAgICAgIGRlbHRhW2RpbV0gPSB2YWw7XG4gICAgfVxuXG4gICAgaWYgKGRlbHRhICE9IG51bGwpIHtcbiAgICAgIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgICAgIGN5LnN0YXJ0QmF0Y2goKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSB0aGlzW2ldO1xuICAgICAgICB2YXIgcG9zID0gZWxlLnBvc2l0aW9uKCk7XG4gICAgICAgIHZhciBuZXdQb3MgPSB7XG4gICAgICAgICAgeDogcG9zLnggKyBkZWx0YS54LFxuICAgICAgICAgIHk6IHBvcy55ICsgZGVsdGEueVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChzaWxlbnQpIHtcbiAgICAgICAgICBlbGUuc2lsZW50UG9zaXRpb24obmV3UG9zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbGUucG9zaXRpb24obmV3UG9zKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjeS5lbmRCYXRjaCgpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBzaWxlbnRTaGlmdDogZnVuY3Rpb24gc2lsZW50U2hpZnQoZGltLCB2YWwpIHtcbiAgICBpZiAocGxhaW5PYmplY3QoZGltKSkge1xuICAgICAgdGhpcy5zaGlmdChkaW0sIHRydWUpO1xuICAgIH0gZWxzZSBpZiAoc3RyaW5nKGRpbSkgJiYgbnVtYmVyKHZhbCkpIHtcbiAgICAgIHRoaXMuc2hpZnQoZGltLCB2YWwsIHRydWUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICAvLyBnZXQvc2V0IHRoZSByZW5kZXJlZCAoaS5lLiBvbiBzY3JlZW4pIHBvc2l0b24gb2YgdGhlIGVsZW1lbnRcbiAgcmVuZGVyZWRQb3NpdGlvbjogZnVuY3Rpb24gcmVuZGVyZWRQb3NpdGlvbihkaW0sIHZhbCkge1xuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgICB2YXIgem9vbSA9IGN5Lnpvb20oKTtcbiAgICB2YXIgcGFuID0gY3kucGFuKCk7XG4gICAgdmFyIHJwb3MgPSBwbGFpbk9iamVjdChkaW0pID8gZGltIDogdW5kZWZpbmVkO1xuICAgIHZhciBzZXR0aW5nID0gcnBvcyAhPT0gdW5kZWZpbmVkIHx8IHZhbCAhPT0gdW5kZWZpbmVkICYmIHN0cmluZyhkaW0pO1xuXG4gICAgaWYgKGVsZSAmJiBlbGUuaXNOb2RlKCkpIHtcbiAgICAgIC8vIG11c3QgaGF2ZSBhbiBlbGVtZW50IGFuZCBtdXN0IGJlIGEgbm9kZSB0byByZXR1cm4gcG9zaXRpb25cbiAgICAgIGlmIChzZXR0aW5nKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBfZWxlID0gdGhpc1tpXTtcblxuICAgICAgICAgIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gc2V0IG9uZSBkaW1lbnNpb25cbiAgICAgICAgICAgIF9lbGUucG9zaXRpb24oZGltLCAodmFsIC0gcGFuW2RpbV0pIC8gem9vbSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChycG9zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIHNldCB3aG9sZSBwb3NpdGlvblxuICAgICAgICAgICAgX2VsZS5wb3NpdGlvbihyZW5kZXJlZFRvTW9kZWxQb3NpdGlvbihycG9zLCB6b29tLCBwYW4pKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGdldHRpbmdcbiAgICAgICAgdmFyIHBvcyA9IGVsZS5wb3NpdGlvbigpO1xuICAgICAgICBycG9zID0gbW9kZWxUb1JlbmRlcmVkUG9zaXRpb24ocG9zLCB6b29tLCBwYW4pO1xuXG4gICAgICAgIGlmIChkaW0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIC8vIHRoZW4gcmV0dXJuIHRoZSB3aG9sZSByZW5kZXJlZCBwb3NpdGlvblxuICAgICAgICAgIHJldHVybiBycG9zO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHRoZW4gcmV0dXJuIHRoZSBzcGVjaWZpZWQgZGltZW5zaW9uXG4gICAgICAgICAgcmV0dXJuIHJwb3NbZGltXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIXNldHRpbmcpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7IC8vIGZvciBlbXB0eSBjb2xsZWN0aW9uIGNhc2VcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgLy8gZ2V0L3NldCB0aGUgcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlIHBhcmVudFxuICByZWxhdGl2ZVBvc2l0aW9uOiBmdW5jdGlvbiByZWxhdGl2ZVBvc2l0aW9uKGRpbSwgdmFsKSB7XG4gICAgdmFyIGVsZSA9IHRoaXNbMF07XG4gICAgdmFyIGN5ID0gdGhpcy5jeSgpO1xuICAgIHZhciBwcG9zID0gcGxhaW5PYmplY3QoZGltKSA/IGRpbSA6IHVuZGVmaW5lZDtcbiAgICB2YXIgc2V0dGluZyA9IHBwb3MgIT09IHVuZGVmaW5lZCB8fCB2YWwgIT09IHVuZGVmaW5lZCAmJiBzdHJpbmcoZGltKTtcbiAgICB2YXIgaGFzQ29tcG91bmROb2RlcyA9IGN5Lmhhc0NvbXBvdW5kTm9kZXMoKTtcblxuICAgIGlmIChlbGUgJiYgZWxlLmlzTm9kZSgpKSB7XG4gICAgICAvLyBtdXN0IGhhdmUgYW4gZWxlbWVudCBhbmQgbXVzdCBiZSBhIG5vZGUgdG8gcmV0dXJuIHBvc2l0aW9uXG4gICAgICBpZiAoc2V0dGluZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgX2VsZTIgPSB0aGlzW2ldO1xuICAgICAgICAgIHZhciBwYXJlbnQgPSBoYXNDb21wb3VuZE5vZGVzID8gX2VsZTIucGFyZW50KCkgOiBudWxsO1xuICAgICAgICAgIHZhciBoYXNQYXJlbnQgPSBwYXJlbnQgJiYgcGFyZW50Lmxlbmd0aCA+IDA7XG4gICAgICAgICAgdmFyIHJlbGF0aXZlVG9QYXJlbnQgPSBoYXNQYXJlbnQ7XG5cbiAgICAgICAgICBpZiAoaGFzUGFyZW50KSB7XG4gICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnRbMF07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIG9yaWdpbiA9IHJlbGF0aXZlVG9QYXJlbnQgPyBwYXJlbnQucG9zaXRpb24oKSA6IHtcbiAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICB5OiAwXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gc2V0IG9uZSBkaW1lbnNpb25cbiAgICAgICAgICAgIF9lbGUyLnBvc2l0aW9uKGRpbSwgdmFsICsgb3JpZ2luW2RpbV0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAocHBvcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBzZXQgd2hvbGUgcG9zaXRpb25cbiAgICAgICAgICAgIF9lbGUyLnBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgeDogcHBvcy54ICsgb3JpZ2luLngsXG4gICAgICAgICAgICAgIHk6IHBwb3MueSArIG9yaWdpbi55XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGdldHRpbmdcbiAgICAgICAgdmFyIHBvcyA9IGVsZS5wb3NpdGlvbigpO1xuXG4gICAgICAgIHZhciBfcGFyZW50ID0gaGFzQ29tcG91bmROb2RlcyA/IGVsZS5wYXJlbnQoKSA6IG51bGw7XG5cbiAgICAgICAgdmFyIF9oYXNQYXJlbnQgPSBfcGFyZW50ICYmIF9wYXJlbnQubGVuZ3RoID4gMDtcblxuICAgICAgICB2YXIgX3JlbGF0aXZlVG9QYXJlbnQgPSBfaGFzUGFyZW50O1xuXG4gICAgICAgIGlmIChfaGFzUGFyZW50KSB7XG4gICAgICAgICAgX3BhcmVudCA9IF9wYXJlbnRbMF07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgX29yaWdpbiA9IF9yZWxhdGl2ZVRvUGFyZW50ID8gX3BhcmVudC5wb3NpdGlvbigpIDoge1xuICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgeTogMFxuICAgICAgICB9O1xuXG4gICAgICAgIHBwb3MgPSB7XG4gICAgICAgICAgeDogcG9zLnggLSBfb3JpZ2luLngsXG4gICAgICAgICAgeTogcG9zLnkgLSBfb3JpZ2luLnlcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoZGltID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAvLyB0aGVuIHJldHVybiB0aGUgd2hvbGUgcmVuZGVyZWQgcG9zaXRpb25cbiAgICAgICAgICByZXR1cm4gcHBvcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyB0aGVuIHJldHVybiB0aGUgc3BlY2lmaWVkIGRpbWVuc2lvblxuICAgICAgICAgIHJldHVybiBwcG9zW2RpbV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKCFzZXR0aW5nKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkOyAvLyBmb3IgZW1wdHkgY29sbGVjdGlvbiBjYXNlXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gIH1cbn07IC8vIGFsaWFzZXNcblxuZm4kMi5tb2RlbFBvc2l0aW9uID0gZm4kMi5wb2ludCA9IGZuJDIucG9zaXRpb247XG5mbiQyLm1vZGVsUG9zaXRpb25zID0gZm4kMi5wb2ludHMgPSBmbiQyLnBvc2l0aW9ucztcbmZuJDIucmVuZGVyZWRQb2ludCA9IGZuJDIucmVuZGVyZWRQb3NpdGlvbjtcbmZuJDIucmVsYXRpdmVQb2ludCA9IGZuJDIucmVsYXRpdmVQb3NpdGlvbjtcbnZhciBwb3NpdGlvbiA9IGVsZXNmbiRqO1xuXG52YXIgZm4kMywgZWxlc2ZuJGs7XG5mbiQzID0gZWxlc2ZuJGsgPSB7fTtcblxuZWxlc2ZuJGsucmVuZGVyZWRCb3VuZGluZ0JveCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIHZhciBiYiA9IHRoaXMuYm91bmRpbmdCb3gob3B0aW9ucyk7XG4gIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgdmFyIHpvb20gPSBjeS56b29tKCk7XG4gIHZhciBwYW4gPSBjeS5wYW4oKTtcbiAgdmFyIHgxID0gYmIueDEgKiB6b29tICsgcGFuLng7XG4gIHZhciB4MiA9IGJiLngyICogem9vbSArIHBhbi54O1xuICB2YXIgeTEgPSBiYi55MSAqIHpvb20gKyBwYW4ueTtcbiAgdmFyIHkyID0gYmIueTIgKiB6b29tICsgcGFuLnk7XG4gIHJldHVybiB7XG4gICAgeDE6IHgxLFxuICAgIHgyOiB4MixcbiAgICB5MTogeTEsXG4gICAgeTI6IHkyLFxuICAgIHc6IHgyIC0geDEsXG4gICAgaDogeTIgLSB5MVxuICB9O1xufTtcblxuZWxlc2ZuJGsuZGlydHlDb21wb3VuZEJvdW5kc0NhY2hlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgY3kgPSB0aGlzLmN5KCk7XG5cbiAgaWYgKCFjeS5zdHlsZUVuYWJsZWQoKSB8fCAhY3kuaGFzQ29tcG91bmROb2RlcygpKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICB0aGlzLmZvckVhY2hVcChmdW5jdGlvbiAoZWxlKSB7XG4gICAgaWYgKGVsZS5pc1BhcmVudCgpKSB7XG4gICAgICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gICAgICBfcC5jb21wb3VuZEJvdW5kc0NsZWFuID0gZmFsc2U7XG4gICAgICBfcC5iYkNhY2hlID0gbnVsbDtcbiAgICAgIGVsZS5lbWl0QW5kTm90aWZ5KCdib3VuZHMnKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmVsZXNmbiRrLnVwZGF0ZUNvbXBvdW5kQm91bmRzID0gZnVuY3Rpb24gKCkge1xuICB2YXIgZm9yY2UgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlO1xuICB2YXIgY3kgPSB0aGlzLmN5KCk7IC8vIG5vdCBwb3NzaWJsZSB0byBkbyBvbiBub24tY29tcG91bmQgZ3JhcGhzIG9yIHdpdGggdGhlIHN0eWxlIGRpc2FibGVkXG5cbiAgaWYgKCFjeS5zdHlsZUVuYWJsZWQoKSB8fCAhY3kuaGFzQ29tcG91bmROb2RlcygpKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0gLy8gc2F2ZSBjeWNsZXMgd2hlbiBiYXRjaGluZyAtLSBidXQgYm91bmRzIHdpbGwgYmUgc3RhbGUgKG9yIG5vdCBleGlzdCB5ZXQpXG5cblxuICBpZiAoIWZvcmNlICYmIGN5LmJhdGNoaW5nKCkpIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZShwYXJlbnQpIHtcbiAgICBpZiAoIXBhcmVudC5pc1BhcmVudCgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIF9wID0gcGFyZW50Ll9wcml2YXRlO1xuICAgIHZhciBjaGlsZHJlbiA9IHBhcmVudC5jaGlsZHJlbigpO1xuICAgIHZhciBpbmNsdWRlTGFiZWxzID0gcGFyZW50LnBzdHlsZSgnY29tcG91bmQtc2l6aW5nLXdydC1sYWJlbHMnKS52YWx1ZSA9PT0gJ2luY2x1ZGUnO1xuICAgIHZhciBtaW4gPSB7XG4gICAgICB3aWR0aDoge1xuICAgICAgICB2YWw6IHBhcmVudC5wc3R5bGUoJ21pbi13aWR0aCcpLnBmVmFsdWUsXG4gICAgICAgIGxlZnQ6IHBhcmVudC5wc3R5bGUoJ21pbi13aWR0aC1iaWFzLWxlZnQnKSxcbiAgICAgICAgcmlnaHQ6IHBhcmVudC5wc3R5bGUoJ21pbi13aWR0aC1iaWFzLXJpZ2h0JylcbiAgICAgIH0sXG4gICAgICBoZWlnaHQ6IHtcbiAgICAgICAgdmFsOiBwYXJlbnQucHN0eWxlKCdtaW4taGVpZ2h0JykucGZWYWx1ZSxcbiAgICAgICAgdG9wOiBwYXJlbnQucHN0eWxlKCdtaW4taGVpZ2h0LWJpYXMtdG9wJyksXG4gICAgICAgIGJvdHRvbTogcGFyZW50LnBzdHlsZSgnbWluLWhlaWdodC1iaWFzLWJvdHRvbScpXG4gICAgICB9XG4gICAgfTtcbiAgICB2YXIgYmIgPSBjaGlsZHJlbi5ib3VuZGluZ0JveCh7XG4gICAgICBpbmNsdWRlTGFiZWxzOiBpbmNsdWRlTGFiZWxzLFxuICAgICAgaW5jbHVkZU92ZXJsYXlzOiBmYWxzZSxcbiAgICAgIC8vIHVwZGF0aW5nIHRoZSBjb21wb3VuZCBib3VuZHMgaGFwcGVucyBvdXRzaWRlIG9mIHRoZSByZWd1bGFyXG4gICAgICAvLyBjYWNoZSBjeWNsZSAoaS5lLiBiZWZvcmUgZmlyZWQgZXZlbnRzKVxuICAgICAgdXNlQ2FjaGU6IGZhbHNlXG4gICAgfSk7XG4gICAgdmFyIHBvcyA9IF9wLnBvc2l0aW9uOyAvLyBpZiBjaGlsZHJlbiB0YWtlIHVwIHplcm8gYXJlYSB0aGVuIGtlZXAgcG9zaXRpb24gYW5kIGZhbGwgYmFjayBvbiBzdHlsZXNoZWV0IHcvaFxuXG4gICAgaWYgKGJiLncgPT09IDAgfHwgYmIuaCA9PT0gMCkge1xuICAgICAgYmIgPSB7XG4gICAgICAgIHc6IHBhcmVudC5wc3R5bGUoJ3dpZHRoJykucGZWYWx1ZSxcbiAgICAgICAgaDogcGFyZW50LnBzdHlsZSgnaGVpZ2h0JykucGZWYWx1ZVxuICAgICAgfTtcbiAgICAgIGJiLngxID0gcG9zLnggLSBiYi53IC8gMjtcbiAgICAgIGJiLngyID0gcG9zLnggKyBiYi53IC8gMjtcbiAgICAgIGJiLnkxID0gcG9zLnkgLSBiYi5oIC8gMjtcbiAgICAgIGJiLnkyID0gcG9zLnkgKyBiYi5oIC8gMjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wdXRlQmlhc1ZhbHVlcyhwcm9wRGlmZiwgcHJvcEJpYXMsIHByb3BCaWFzQ29tcGxlbWVudCkge1xuICAgICAgdmFyIGJpYXNEaWZmID0gMDtcbiAgICAgIHZhciBiaWFzQ29tcGxlbWVudERpZmYgPSAwO1xuICAgICAgdmFyIGJpYXNUb3RhbCA9IHByb3BCaWFzICsgcHJvcEJpYXNDb21wbGVtZW50O1xuXG4gICAgICBpZiAocHJvcERpZmYgPiAwICYmIGJpYXNUb3RhbCA+IDApIHtcbiAgICAgICAgYmlhc0RpZmYgPSBwcm9wQmlhcyAvIGJpYXNUb3RhbCAqIHByb3BEaWZmO1xuICAgICAgICBiaWFzQ29tcGxlbWVudERpZmYgPSBwcm9wQmlhc0NvbXBsZW1lbnQgLyBiaWFzVG90YWwgKiBwcm9wRGlmZjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYmlhc0RpZmY6IGJpYXNEaWZmLFxuICAgICAgICBiaWFzQ29tcGxlbWVudERpZmY6IGJpYXNDb21wbGVtZW50RGlmZlxuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wdXRlUGFkZGluZ1ZhbHVlcyh3aWR0aCwgaGVpZ2h0LCBwYWRkaW5nT2JqZWN0LCByZWxhdGl2ZVRvKSB7XG4gICAgICAvLyBBc3N1bWluZyBwZXJjZW50YWdlIGlzIG51bWJlciBmcm9tIDAgdG8gMVxuICAgICAgaWYgKHBhZGRpbmdPYmplY3QudW5pdHMgPT09ICclJykge1xuICAgICAgICBzd2l0Y2ggKHJlbGF0aXZlVG8pIHtcbiAgICAgICAgICBjYXNlICd3aWR0aCc6XG4gICAgICAgICAgICByZXR1cm4gd2lkdGggPiAwID8gcGFkZGluZ09iamVjdC5wZlZhbHVlICogd2lkdGggOiAwO1xuXG4gICAgICAgICAgY2FzZSAnaGVpZ2h0JzpcbiAgICAgICAgICAgIHJldHVybiBoZWlnaHQgPiAwID8gcGFkZGluZ09iamVjdC5wZlZhbHVlICogaGVpZ2h0IDogMDtcblxuICAgICAgICAgIGNhc2UgJ2F2ZXJhZ2UnOlxuICAgICAgICAgICAgcmV0dXJuIHdpZHRoID4gMCAmJiBoZWlnaHQgPiAwID8gcGFkZGluZ09iamVjdC5wZlZhbHVlICogKHdpZHRoICsgaGVpZ2h0KSAvIDIgOiAwO1xuXG4gICAgICAgICAgY2FzZSAnbWluJzpcbiAgICAgICAgICAgIHJldHVybiB3aWR0aCA+IDAgJiYgaGVpZ2h0ID4gMCA/IHdpZHRoID4gaGVpZ2h0ID8gcGFkZGluZ09iamVjdC5wZlZhbHVlICogaGVpZ2h0IDogcGFkZGluZ09iamVjdC5wZlZhbHVlICogd2lkdGggOiAwO1xuXG4gICAgICAgICAgY2FzZSAnbWF4JzpcbiAgICAgICAgICAgIHJldHVybiB3aWR0aCA+IDAgJiYgaGVpZ2h0ID4gMCA/IHdpZHRoID4gaGVpZ2h0ID8gcGFkZGluZ09iamVjdC5wZlZhbHVlICogd2lkdGggOiBwYWRkaW5nT2JqZWN0LnBmVmFsdWUgKiBoZWlnaHQgOiAwO1xuXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHBhZGRpbmdPYmplY3QudW5pdHMgPT09ICdweCcpIHtcbiAgICAgICAgcmV0dXJuIHBhZGRpbmdPYmplY3QucGZWYWx1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsZWZ0VmFsID0gbWluLndpZHRoLmxlZnQudmFsdWU7XG5cbiAgICBpZiAobWluLndpZHRoLmxlZnQudW5pdHMgPT09ICdweCcgJiYgbWluLndpZHRoLnZhbCA+IDApIHtcbiAgICAgIGxlZnRWYWwgPSBsZWZ0VmFsICogMTAwIC8gbWluLndpZHRoLnZhbDtcbiAgICB9XG5cbiAgICB2YXIgcmlnaHRWYWwgPSBtaW4ud2lkdGgucmlnaHQudmFsdWU7XG5cbiAgICBpZiAobWluLndpZHRoLnJpZ2h0LnVuaXRzID09PSAncHgnICYmIG1pbi53aWR0aC52YWwgPiAwKSB7XG4gICAgICByaWdodFZhbCA9IHJpZ2h0VmFsICogMTAwIC8gbWluLndpZHRoLnZhbDtcbiAgICB9XG5cbiAgICB2YXIgdG9wVmFsID0gbWluLmhlaWdodC50b3AudmFsdWU7XG5cbiAgICBpZiAobWluLmhlaWdodC50b3AudW5pdHMgPT09ICdweCcgJiYgbWluLmhlaWdodC52YWwgPiAwKSB7XG4gICAgICB0b3BWYWwgPSB0b3BWYWwgKiAxMDAgLyBtaW4uaGVpZ2h0LnZhbDtcbiAgICB9XG5cbiAgICB2YXIgYm90dG9tVmFsID0gbWluLmhlaWdodC5ib3R0b20udmFsdWU7XG5cbiAgICBpZiAobWluLmhlaWdodC5ib3R0b20udW5pdHMgPT09ICdweCcgJiYgbWluLmhlaWdodC52YWwgPiAwKSB7XG4gICAgICBib3R0b21WYWwgPSBib3R0b21WYWwgKiAxMDAgLyBtaW4uaGVpZ2h0LnZhbDtcbiAgICB9XG5cbiAgICB2YXIgd2lkdGhCaWFzRGlmZnMgPSBjb21wdXRlQmlhc1ZhbHVlcyhtaW4ud2lkdGgudmFsIC0gYmIudywgbGVmdFZhbCwgcmlnaHRWYWwpO1xuICAgIHZhciBkaWZmTGVmdCA9IHdpZHRoQmlhc0RpZmZzLmJpYXNEaWZmO1xuICAgIHZhciBkaWZmUmlnaHQgPSB3aWR0aEJpYXNEaWZmcy5iaWFzQ29tcGxlbWVudERpZmY7XG4gICAgdmFyIGhlaWdodEJpYXNEaWZmcyA9IGNvbXB1dGVCaWFzVmFsdWVzKG1pbi5oZWlnaHQudmFsIC0gYmIuaCwgdG9wVmFsLCBib3R0b21WYWwpO1xuICAgIHZhciBkaWZmVG9wID0gaGVpZ2h0Qmlhc0RpZmZzLmJpYXNEaWZmO1xuICAgIHZhciBkaWZmQm90dG9tID0gaGVpZ2h0Qmlhc0RpZmZzLmJpYXNDb21wbGVtZW50RGlmZjtcbiAgICBfcC5hdXRvUGFkZGluZyA9IGNvbXB1dGVQYWRkaW5nVmFsdWVzKGJiLncsIGJiLmgsIHBhcmVudC5wc3R5bGUoJ3BhZGRpbmcnKSwgcGFyZW50LnBzdHlsZSgncGFkZGluZy1yZWxhdGl2ZS10bycpLnZhbHVlKTtcbiAgICBfcC5hdXRvV2lkdGggPSBNYXRoLm1heChiYi53LCBtaW4ud2lkdGgudmFsKTtcbiAgICBwb3MueCA9ICgtZGlmZkxlZnQgKyBiYi54MSArIGJiLngyICsgZGlmZlJpZ2h0KSAvIDI7XG4gICAgX3AuYXV0b0hlaWdodCA9IE1hdGgubWF4KGJiLmgsIG1pbi5oZWlnaHQudmFsKTtcbiAgICBwb3MueSA9ICgtZGlmZlRvcCArIGJiLnkxICsgYmIueTIgKyBkaWZmQm90dG9tKSAvIDI7XG4gIH1cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG5cbiAgICBpZiAoIV9wLmNvbXBvdW5kQm91bmRzQ2xlYW4pIHtcbiAgICAgIHVwZGF0ZShlbGUpO1xuXG4gICAgICBpZiAoIWN5LmJhdGNoaW5nKCkpIHtcbiAgICAgICAgX3AuY29tcG91bmRCb3VuZHNDbGVhbiA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG52YXIgbm9uaW5mID0gZnVuY3Rpb24gbm9uaW5mKHgpIHtcbiAgaWYgKHggPT09IEluZmluaXR5IHx8IHggPT09IC1JbmZpbml0eSkge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgcmV0dXJuIHg7XG59O1xuXG52YXIgdXBkYXRlQm91bmRzID0gZnVuY3Rpb24gdXBkYXRlQm91bmRzKGIsIHgxLCB5MSwgeDIsIHkyKSB7XG4gIC8vIGRvbid0IHVwZGF0ZSB3aXRoIHplcm8gYXJlYSBib3hlc1xuICBpZiAoeDIgLSB4MSA9PT0gMCB8fCB5MiAtIHkxID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9IC8vIGRvbid0IHVwZGF0ZSB3aXRoIG51bGwgZGltXG5cblxuICBpZiAoeDEgPT0gbnVsbCB8fCB5MSA9PSBudWxsIHx8IHgyID09IG51bGwgfHwgeTIgPT0gbnVsbCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGIueDEgPSB4MSA8IGIueDEgPyB4MSA6IGIueDE7XG4gIGIueDIgPSB4MiA+IGIueDIgPyB4MiA6IGIueDI7XG4gIGIueTEgPSB5MSA8IGIueTEgPyB5MSA6IGIueTE7XG4gIGIueTIgPSB5MiA+IGIueTIgPyB5MiA6IGIueTI7XG4gIGIudyA9IGIueDIgLSBiLngxO1xuICBiLmggPSBiLnkyIC0gYi55MTtcbn07XG5cbnZhciB1cGRhdGVCb3VuZHNGcm9tQm94ID0gZnVuY3Rpb24gdXBkYXRlQm91bmRzRnJvbUJveChiLCBiMikge1xuICBpZiAoYjIgPT0gbnVsbCkge1xuICAgIHJldHVybiBiO1xuICB9XG5cbiAgcmV0dXJuIHVwZGF0ZUJvdW5kcyhiLCBiMi54MSwgYjIueTEsIGIyLngyLCBiMi55Mik7XG59O1xuXG52YXIgcHJlZml4ZWRQcm9wZXJ0eSA9IGZ1bmN0aW9uIHByZWZpeGVkUHJvcGVydHkob2JqLCBmaWVsZCwgcHJlZml4KSB7XG4gIHJldHVybiBnZXRQcmVmaXhlZFByb3BlcnR5KG9iaiwgZmllbGQsIHByZWZpeCk7XG59O1xuXG52YXIgdXBkYXRlQm91bmRzRnJvbUFycm93ID0gZnVuY3Rpb24gdXBkYXRlQm91bmRzRnJvbUFycm93KGJvdW5kcywgZWxlLCBwcmVmaXgpIHtcbiAgaWYgKGVsZS5jeSgpLmhlYWRsZXNzKCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciByc3R5bGUgPSBfcC5yc3R5bGU7XG4gIHZhciBoYWxmQXJXID0gcnN0eWxlLmFycm93V2lkdGggLyAyO1xuICB2YXIgYXJyb3dUeXBlID0gZWxlLnBzdHlsZShwcmVmaXggKyAnLWFycm93LXNoYXBlJykudmFsdWU7XG4gIHZhciB4O1xuICB2YXIgeTtcblxuICBpZiAoYXJyb3dUeXBlICE9PSAnbm9uZScpIHtcbiAgICBpZiAocHJlZml4ID09PSAnc291cmNlJykge1xuICAgICAgeCA9IHJzdHlsZS5zcmNYO1xuICAgICAgeSA9IHJzdHlsZS5zcmNZO1xuICAgIH0gZWxzZSBpZiAocHJlZml4ID09PSAndGFyZ2V0Jykge1xuICAgICAgeCA9IHJzdHlsZS50Z3RYO1xuICAgICAgeSA9IHJzdHlsZS50Z3RZO1xuICAgIH0gZWxzZSB7XG4gICAgICB4ID0gcnN0eWxlLm1pZFg7XG4gICAgICB5ID0gcnN0eWxlLm1pZFk7XG4gICAgfSAvLyBhbHdheXMgc3RvcmUgdGhlIGluZGl2aWR1YWwgYXJyb3cgYm91bmRzXG5cblxuICAgIHZhciBiYnMgPSBfcC5hcnJvd0JvdW5kcyA9IF9wLmFycm93Qm91bmRzIHx8IHt9O1xuICAgIHZhciBiYiA9IGJic1twcmVmaXhdID0gYmJzW3ByZWZpeF0gfHwge307XG4gICAgYmIueDEgPSB4IC0gaGFsZkFyVztcbiAgICBiYi55MSA9IHkgLSBoYWxmQXJXO1xuICAgIGJiLngyID0geCArIGhhbGZBclc7XG4gICAgYmIueTIgPSB5ICsgaGFsZkFyVztcbiAgICBiYi53ID0gYmIueDIgLSBiYi54MTtcbiAgICBiYi5oID0gYmIueTIgLSBiYi55MTtcbiAgICBleHBhbmRCb3VuZGluZ0JveChiYiwgMSk7XG4gICAgdXBkYXRlQm91bmRzKGJvdW5kcywgYmIueDEsIGJiLnkxLCBiYi54MiwgYmIueTIpO1xuICB9XG59O1xuXG52YXIgdXBkYXRlQm91bmRzRnJvbUxhYmVsID0gZnVuY3Rpb24gdXBkYXRlQm91bmRzRnJvbUxhYmVsKGJvdW5kcywgZWxlLCBwcmVmaXgpIHtcbiAgaWYgKGVsZS5jeSgpLmhlYWRsZXNzKCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgcHJlZml4RGFzaDtcblxuICBpZiAocHJlZml4KSB7XG4gICAgcHJlZml4RGFzaCA9IHByZWZpeCArICctJztcbiAgfSBlbHNlIHtcbiAgICBwcmVmaXhEYXNoID0gJyc7XG4gIH1cblxuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciByc3R5bGUgPSBfcC5yc3R5bGU7XG4gIHZhciBsYWJlbCA9IGVsZS5wc3R5bGUocHJlZml4RGFzaCArICdsYWJlbCcpLnN0clZhbHVlO1xuXG4gIGlmIChsYWJlbCkge1xuICAgIHZhciBoYWxpZ24gPSBlbGUucHN0eWxlKCd0ZXh0LWhhbGlnbicpO1xuICAgIHZhciB2YWxpZ24gPSBlbGUucHN0eWxlKCd0ZXh0LXZhbGlnbicpO1xuICAgIHZhciBsYWJlbFdpZHRoID0gcHJlZml4ZWRQcm9wZXJ0eShyc3R5bGUsICdsYWJlbFdpZHRoJywgcHJlZml4KTtcbiAgICB2YXIgbGFiZWxIZWlnaHQgPSBwcmVmaXhlZFByb3BlcnR5KHJzdHlsZSwgJ2xhYmVsSGVpZ2h0JywgcHJlZml4KTtcbiAgICB2YXIgbGFiZWxYID0gcHJlZml4ZWRQcm9wZXJ0eShyc3R5bGUsICdsYWJlbFgnLCBwcmVmaXgpO1xuICAgIHZhciBsYWJlbFkgPSBwcmVmaXhlZFByb3BlcnR5KHJzdHlsZSwgJ2xhYmVsWScsIHByZWZpeCk7XG4gICAgdmFyIG1hcmdpblggPSBlbGUucHN0eWxlKHByZWZpeERhc2ggKyAndGV4dC1tYXJnaW4teCcpLnBmVmFsdWU7XG4gICAgdmFyIG1hcmdpblkgPSBlbGUucHN0eWxlKHByZWZpeERhc2ggKyAndGV4dC1tYXJnaW4teScpLnBmVmFsdWU7XG4gICAgdmFyIGlzRWRnZSA9IGVsZS5pc0VkZ2UoKTtcbiAgICB2YXIgcm90YXRpb24gPSBlbGUucHN0eWxlKHByZWZpeERhc2ggKyAndGV4dC1yb3RhdGlvbicpO1xuICAgIHZhciBvdXRsaW5lV2lkdGggPSBlbGUucHN0eWxlKCd0ZXh0LW91dGxpbmUtd2lkdGgnKS5wZlZhbHVlO1xuICAgIHZhciBib3JkZXJXaWR0aCA9IGVsZS5wc3R5bGUoJ3RleHQtYm9yZGVyLXdpZHRoJykucGZWYWx1ZTtcbiAgICB2YXIgaGFsZkJvcmRlcldpZHRoID0gYm9yZGVyV2lkdGggLyAyO1xuICAgIHZhciBwYWRkaW5nID0gZWxlLnBzdHlsZSgndGV4dC1iYWNrZ3JvdW5kLXBhZGRpbmcnKS5wZlZhbHVlO1xuICAgIHZhciBsaCA9IGxhYmVsSGVpZ2h0O1xuICAgIHZhciBsdyA9IGxhYmVsV2lkdGg7XG4gICAgdmFyIGx3XzIgPSBsdyAvIDI7XG4gICAgdmFyIGxoXzIgPSBsaCAvIDI7XG4gICAgdmFyIGx4MSwgbHgyLCBseTEsIGx5MjtcblxuICAgIGlmIChpc0VkZ2UpIHtcbiAgICAgIGx4MSA9IGxhYmVsWCAtIGx3XzI7XG4gICAgICBseDIgPSBsYWJlbFggKyBsd18yO1xuICAgICAgbHkxID0gbGFiZWxZIC0gbGhfMjtcbiAgICAgIGx5MiA9IGxhYmVsWSArIGxoXzI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN3aXRjaCAoaGFsaWduLnZhbHVlKSB7XG4gICAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICAgIGx4MSA9IGxhYmVsWCAtIGx3O1xuICAgICAgICAgIGx4MiA9IGxhYmVsWDtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdjZW50ZXInOlxuICAgICAgICAgIGx4MSA9IGxhYmVsWCAtIGx3XzI7XG4gICAgICAgICAgbHgyID0gbGFiZWxYICsgbHdfMjtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgICAgbHgxID0gbGFiZWxYO1xuICAgICAgICAgIGx4MiA9IGxhYmVsWCArIGx3O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBzd2l0Y2ggKHZhbGlnbi52YWx1ZSkge1xuICAgICAgICBjYXNlICd0b3AnOlxuICAgICAgICAgIGx5MSA9IGxhYmVsWSAtIGxoO1xuICAgICAgICAgIGx5MiA9IGxhYmVsWTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdjZW50ZXInOlxuICAgICAgICAgIGx5MSA9IGxhYmVsWSAtIGxoXzI7XG4gICAgICAgICAgbHkyID0gbGFiZWxZICsgbGhfMjtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdib3R0b20nOlxuICAgICAgICAgIGx5MSA9IGxhYmVsWTtcbiAgICAgICAgICBseTIgPSBsYWJlbFkgKyBsaDtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9IC8vIHNoaWZ0IGJ5IG1hcmdpbiBhbmQgZXhwYW5kIGJ5IG91dGxpbmUgYW5kIGJvcmRlclxuXG5cbiAgICBseDEgKz0gbWFyZ2luWCAtIE1hdGgubWF4KG91dGxpbmVXaWR0aCwgaGFsZkJvcmRlcldpZHRoKSAtIHBhZGRpbmc7XG4gICAgbHgyICs9IG1hcmdpblggKyBNYXRoLm1heChvdXRsaW5lV2lkdGgsIGhhbGZCb3JkZXJXaWR0aCkgKyBwYWRkaW5nO1xuICAgIGx5MSArPSBtYXJnaW5ZIC0gTWF0aC5tYXgob3V0bGluZVdpZHRoLCBoYWxmQm9yZGVyV2lkdGgpIC0gcGFkZGluZztcbiAgICBseTIgKz0gbWFyZ2luWSArIE1hdGgubWF4KG91dGxpbmVXaWR0aCwgaGFsZkJvcmRlcldpZHRoKSArIHBhZGRpbmc7IC8vIGFsd2F5cyBzdG9yZSB0aGUgdW5yb3RhdGVkIGxhYmVsIGJvdW5kcyBzZXBhcmF0ZWx5XG5cbiAgICB2YXIgYmJQcmVmaXggPSBwcmVmaXggfHwgJ21haW4nO1xuICAgIHZhciBiYnMgPSBfcC5sYWJlbEJvdW5kcztcbiAgICB2YXIgYmIgPSBiYnNbYmJQcmVmaXhdID0gYmJzW2JiUHJlZml4XSB8fCB7fTtcbiAgICBiYi54MSA9IGx4MTtcbiAgICBiYi55MSA9IGx5MTtcbiAgICBiYi54MiA9IGx4MjtcbiAgICBiYi55MiA9IGx5MjtcbiAgICBiYi53ID0gbHgyIC0gbHgxO1xuICAgIGJiLmggPSBseTIgLSBseTE7XG4gICAgZXhwYW5kQm91bmRpbmdCb3goYmIsIDEpOyAvLyBleHBhbmQgdG8gd29yayBhcm91bmQgYnJvd3NlciBkaW1lbnNpb24gaW5hY2N1cmFjaWVzXG5cbiAgICB2YXIgaXNBdXRvcm90YXRlID0gaXNFZGdlICYmIHJvdGF0aW9uLnN0clZhbHVlID09PSAnYXV0b3JvdGF0ZSc7XG4gICAgdmFyIGlzUGZWYWx1ZSA9IHJvdGF0aW9uLnBmVmFsdWUgIT0gbnVsbCAmJiByb3RhdGlvbi5wZlZhbHVlICE9PSAwO1xuXG4gICAgaWYgKGlzQXV0b3JvdGF0ZSB8fCBpc1BmVmFsdWUpIHtcbiAgICAgIHZhciB0aGV0YSA9IGlzQXV0b3JvdGF0ZSA/IHByZWZpeGVkUHJvcGVydHkoX3AucnN0eWxlLCAnbGFiZWxBbmdsZScsIHByZWZpeCkgOiByb3RhdGlvbi5wZlZhbHVlO1xuICAgICAgdmFyIGNvcyA9IE1hdGguY29zKHRoZXRhKTtcbiAgICAgIHZhciBzaW4gPSBNYXRoLnNpbih0aGV0YSk7IC8vIHJvdGF0aW9uIHBvaW50IChkZWZhdWx0IHZhbHVlIGZvciBjZW50ZXItY2VudGVyKVxuXG4gICAgICB2YXIgeG8gPSAobHgxICsgbHgyKSAvIDI7XG4gICAgICB2YXIgeW8gPSAobHkxICsgbHkyKSAvIDI7XG5cbiAgICAgIGlmICghaXNFZGdlKSB7XG4gICAgICAgIHN3aXRjaCAoaGFsaWduLnZhbHVlKSB7XG4gICAgICAgICAgY2FzZSAnbGVmdCc6XG4gICAgICAgICAgICB4byA9IGx4MjtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICAgICAgeG8gPSBseDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAodmFsaWduLnZhbHVlKSB7XG4gICAgICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgICAgIHlvID0gbHkyO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdib3R0b20nOlxuICAgICAgICAgICAgeW8gPSBseTE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgcm90YXRlID0gZnVuY3Rpb24gcm90YXRlKHgsIHkpIHtcbiAgICAgICAgeCA9IHggLSB4bztcbiAgICAgICAgeSA9IHkgLSB5bztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB4OiB4ICogY29zIC0geSAqIHNpbiArIHhvLFxuICAgICAgICAgIHk6IHggKiBzaW4gKyB5ICogY29zICsgeW9cbiAgICAgICAgfTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBweDF5MSA9IHJvdGF0ZShseDEsIGx5MSk7XG4gICAgICB2YXIgcHgxeTIgPSByb3RhdGUobHgxLCBseTIpO1xuICAgICAgdmFyIHB4MnkxID0gcm90YXRlKGx4MiwgbHkxKTtcbiAgICAgIHZhciBweDJ5MiA9IHJvdGF0ZShseDIsIGx5Mik7XG4gICAgICBseDEgPSBNYXRoLm1pbihweDF5MS54LCBweDF5Mi54LCBweDJ5MS54LCBweDJ5Mi54KTtcbiAgICAgIGx4MiA9IE1hdGgubWF4KHB4MXkxLngsIHB4MXkyLngsIHB4MnkxLngsIHB4MnkyLngpO1xuICAgICAgbHkxID0gTWF0aC5taW4ocHgxeTEueSwgcHgxeTIueSwgcHgyeTEueSwgcHgyeTIueSk7XG4gICAgICBseTIgPSBNYXRoLm1heChweDF5MS55LCBweDF5Mi55LCBweDJ5MS55LCBweDJ5Mi55KTtcbiAgICB9XG5cbiAgICB2YXIgYmJQcmVmaXhSb3QgPSBiYlByZWZpeCArICdSb3QnO1xuICAgIHZhciBiYlJvdCA9IGJic1tiYlByZWZpeFJvdF0gPSBiYnNbYmJQcmVmaXhSb3RdIHx8IHt9O1xuICAgIGJiUm90LngxID0gbHgxO1xuICAgIGJiUm90LnkxID0gbHkxO1xuICAgIGJiUm90LngyID0gbHgyO1xuICAgIGJiUm90LnkyID0gbHkyO1xuICAgIGJiUm90LncgPSBseDIgLSBseDE7XG4gICAgYmJSb3QuaCA9IGx5MiAtIGx5MTtcbiAgICB1cGRhdGVCb3VuZHMoYm91bmRzLCBseDEsIGx5MSwgbHgyLCBseTIpO1xuICAgIHVwZGF0ZUJvdW5kcyhfcC5sYWJlbEJvdW5kcy5hbGwsIGx4MSwgbHkxLCBseDIsIGx5Mik7XG4gIH1cblxuICByZXR1cm4gYm91bmRzO1xufTsgLy8gZ2V0IHRoZSBib3VuZGluZyBib3ggb2YgdGhlIGVsZW1lbnRzIChpbiByYXcgbW9kZWwgcG9zaXRpb24pXG5cblxudmFyIGJvdW5kaW5nQm94SW1wbCA9IGZ1bmN0aW9uIGJvdW5kaW5nQm94SW1wbChlbGUsIG9wdGlvbnMpIHtcbiAgdmFyIGN5ID0gZWxlLl9wcml2YXRlLmN5O1xuICB2YXIgc3R5bGVFbmFibGVkID0gY3kuc3R5bGVFbmFibGVkKCk7XG4gIHZhciBoZWFkbGVzcyA9IGN5LmhlYWRsZXNzKCk7XG4gIHZhciBib3VuZHMgPSBtYWtlQm91bmRpbmdCb3goKTtcbiAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICB2YXIgaXNOb2RlID0gZWxlLmlzTm9kZSgpO1xuICB2YXIgaXNFZGdlID0gZWxlLmlzRWRnZSgpO1xuICB2YXIgZXgxLCBleDIsIGV5MSwgZXkyOyAvLyBleHRyZW1hIG9mIGJvZHkgLyBsaW5lc1xuXG4gIHZhciB4LCB5OyAvLyBub2RlIHBvc1xuXG4gIHZhciByc3R5bGUgPSBfcC5yc3R5bGU7XG4gIHZhciBtYW51YWxFeHBhbnNpb24gPSBpc05vZGUgJiYgc3R5bGVFbmFibGVkID8gZWxlLnBzdHlsZSgnYm91bmRzLWV4cGFuc2lvbicpLnBmVmFsdWUgOiBbMF07IC8vIG11c3QgdXNlIGBkaXNwbGF5YCBwcm9wIG9ubHksIGFzIHJlYWRpbmcgYGNvbXBvdW5kLndpZHRoKClgIGNhdXNlcyByZWN1cnNpb25cbiAgLy8gKG90aGVyIGZhY3RvcnMgbGlrZSB3aWR0aCB2YWx1ZXMgd2lsbCBiZSBjb25zaWRlcmVkIGxhdGVyIGluIHRoaXMgZnVuY3Rpb24gYW55d2F5KVxuXG4gIHZhciBpc0Rpc3BsYXllZCA9IGZ1bmN0aW9uIGlzRGlzcGxheWVkKGVsZSkge1xuICAgIHJldHVybiBlbGUucHN0eWxlKCdkaXNwbGF5JykudmFsdWUgIT09ICdub25lJztcbiAgfTtcblxuICB2YXIgZGlzcGxheWVkID0gIXN0eWxlRW5hYmxlZCB8fCBpc0Rpc3BsYXllZChlbGUpIC8vIG11c3QgdGFrZSBpbnRvIGFjY291bnQgY29ubmVjdGVkIG5vZGVzIGIvYyBvZiBpbXBsaWNpdCBlZGdlIGhpZGluZyBvbiBkaXNwbGF5Om5vbmUgbm9kZVxuICAmJiAoIWlzRWRnZSB8fCBpc0Rpc3BsYXllZChlbGUuc291cmNlKCkpICYmIGlzRGlzcGxheWVkKGVsZS50YXJnZXQoKSkpO1xuXG4gIGlmIChkaXNwbGF5ZWQpIHtcbiAgICAvLyBkaXNwbGF5ZWQgc3VmZmljZXMsIHNpbmNlIHdlIHdpbGwgZmluZCB6ZXJvIGFyZWEgZWxlcyBhbnl3YXlcbiAgICB2YXIgb3ZlcmxheU9wYWNpdHkgPSAwO1xuICAgIHZhciBvdmVybGF5UGFkZGluZyA9IDA7XG5cbiAgICBpZiAoc3R5bGVFbmFibGVkICYmIG9wdGlvbnMuaW5jbHVkZU92ZXJsYXlzKSB7XG4gICAgICBvdmVybGF5T3BhY2l0eSA9IGVsZS5wc3R5bGUoJ292ZXJsYXktb3BhY2l0eScpLnZhbHVlO1xuXG4gICAgICBpZiAob3ZlcmxheU9wYWNpdHkgIT09IDApIHtcbiAgICAgICAgb3ZlcmxheVBhZGRpbmcgPSBlbGUucHN0eWxlKCdvdmVybGF5LXBhZGRpbmcnKS52YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdyA9IDA7XG4gICAgdmFyIHdIYWxmID0gMDtcblxuICAgIGlmIChzdHlsZUVuYWJsZWQpIHtcbiAgICAgIHcgPSBlbGUucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWU7XG4gICAgICB3SGFsZiA9IHcgLyAyO1xuICAgIH1cblxuICAgIGlmIChpc05vZGUgJiYgb3B0aW9ucy5pbmNsdWRlTm9kZXMpIHtcbiAgICAgIHZhciBwb3MgPSBlbGUucG9zaXRpb24oKTtcbiAgICAgIHggPSBwb3MueDtcbiAgICAgIHkgPSBwb3MueTtcblxuICAgICAgdmFyIF93ID0gZWxlLm91dGVyV2lkdGgoKTtcblxuICAgICAgdmFyIGhhbGZXID0gX3cgLyAyO1xuICAgICAgdmFyIGggPSBlbGUub3V0ZXJIZWlnaHQoKTtcbiAgICAgIHZhciBoYWxmSCA9IGggLyAyOyAvLyBoYW5kbGUgbm9kZSBkaW1lbnNpb25zXG4gICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgICAgIGV4MSA9IHggLSBoYWxmVztcbiAgICAgIGV4MiA9IHggKyBoYWxmVztcbiAgICAgIGV5MSA9IHkgLSBoYWxmSDtcbiAgICAgIGV5MiA9IHkgKyBoYWxmSDtcbiAgICAgIHVwZGF0ZUJvdW5kcyhib3VuZHMsIGV4MSwgZXkxLCBleDIsIGV5Mik7XG4gICAgfSBlbHNlIGlmIChpc0VkZ2UgJiYgb3B0aW9ucy5pbmNsdWRlRWRnZXMpIHtcbiAgICAgIGlmIChzdHlsZUVuYWJsZWQgJiYgIWhlYWRsZXNzKSB7XG4gICAgICAgIHZhciBjdXJ2ZVN0eWxlID0gZWxlLnBzdHlsZSgnY3VydmUtc3R5bGUnKS5zdHJWYWx1ZTsgLy8gaGFuZGxlIGVkZ2UgZGltZW5zaW9ucyAocm91Z2ggYm94IGVzdGltYXRlKVxuICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgICAgICAgZXgxID0gTWF0aC5taW4ocnN0eWxlLnNyY1gsIHJzdHlsZS5taWRYLCByc3R5bGUudGd0WCk7XG4gICAgICAgIGV4MiA9IE1hdGgubWF4KHJzdHlsZS5zcmNYLCByc3R5bGUubWlkWCwgcnN0eWxlLnRndFgpO1xuICAgICAgICBleTEgPSBNYXRoLm1pbihyc3R5bGUuc3JjWSwgcnN0eWxlLm1pZFksIHJzdHlsZS50Z3RZKTtcbiAgICAgICAgZXkyID0gTWF0aC5tYXgocnN0eWxlLnNyY1ksIHJzdHlsZS5taWRZLCByc3R5bGUudGd0WSk7IC8vIHRha2UgaW50byBhY2NvdW50IGVkZ2Ugd2lkdGhcblxuICAgICAgICBleDEgLT0gd0hhbGY7XG4gICAgICAgIGV4MiArPSB3SGFsZjtcbiAgICAgICAgZXkxIC09IHdIYWxmO1xuICAgICAgICBleTIgKz0gd0hhbGY7XG4gICAgICAgIHVwZGF0ZUJvdW5kcyhib3VuZHMsIGV4MSwgZXkxLCBleDIsIGV5Mik7IC8vIHByZWNpc2UgZWRnZXNcbiAgICAgICAgLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgIGlmIChjdXJ2ZVN0eWxlID09PSAnaGF5c3RhY2snKSB7XG4gICAgICAgICAgdmFyIGhwdHMgPSByc3R5bGUuaGF5c3RhY2tQdHM7XG5cbiAgICAgICAgICBpZiAoaHB0cyAmJiBocHRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgZXgxID0gaHB0c1swXS54O1xuICAgICAgICAgICAgZXkxID0gaHB0c1swXS55O1xuICAgICAgICAgICAgZXgyID0gaHB0c1sxXS54O1xuICAgICAgICAgICAgZXkyID0gaHB0c1sxXS55O1xuXG4gICAgICAgICAgICBpZiAoZXgxID4gZXgyKSB7XG4gICAgICAgICAgICAgIHZhciB0ZW1wID0gZXgxO1xuICAgICAgICAgICAgICBleDEgPSBleDI7XG4gICAgICAgICAgICAgIGV4MiA9IHRlbXA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChleTEgPiBleTIpIHtcbiAgICAgICAgICAgICAgdmFyIF90ZW1wID0gZXkxO1xuICAgICAgICAgICAgICBleTEgPSBleTI7XG4gICAgICAgICAgICAgIGV5MiA9IF90ZW1wO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cGRhdGVCb3VuZHMoYm91bmRzLCBleDEgLSB3SGFsZiwgZXkxIC0gd0hhbGYsIGV4MiArIHdIYWxmLCBleTIgKyB3SGFsZik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGN1cnZlU3R5bGUgPT09ICdiZXppZXInIHx8IGN1cnZlU3R5bGUgPT09ICd1bmJ1bmRsZWQtYmV6aWVyJyB8fCBjdXJ2ZVN0eWxlID09PSAnc2VnbWVudHMnIHx8IGN1cnZlU3R5bGUgPT09ICd0YXhpJykge1xuICAgICAgICAgIHZhciBwdHM7XG5cbiAgICAgICAgICBzd2l0Y2ggKGN1cnZlU3R5bGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2Jlemllcic6XG4gICAgICAgICAgICBjYXNlICd1bmJ1bmRsZWQtYmV6aWVyJzpcbiAgICAgICAgICAgICAgcHRzID0gcnN0eWxlLmJlemllclB0cztcbiAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ3NlZ21lbnRzJzpcbiAgICAgICAgICAgIGNhc2UgJ3RheGknOlxuICAgICAgICAgICAgICBwdHMgPSByc3R5bGUubGluZVB0cztcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHB0cyAhPSBudWxsKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHB0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICB2YXIgcHQgPSBwdHNbal07XG4gICAgICAgICAgICAgIGV4MSA9IHB0LnggLSB3SGFsZjtcbiAgICAgICAgICAgICAgZXgyID0gcHQueCArIHdIYWxmO1xuICAgICAgICAgICAgICBleTEgPSBwdC55IC0gd0hhbGY7XG4gICAgICAgICAgICAgIGV5MiA9IHB0LnkgKyB3SGFsZjtcbiAgICAgICAgICAgICAgdXBkYXRlQm91bmRzKGJvdW5kcywgZXgxLCBleTEsIGV4MiwgZXkyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gYmV6aWVyLWxpa2Ugb3Igc2VnbWVudC1saWtlIGVkZ2VcblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaGVhZGxlc3Mgb3Igc3R5bGUgZGlzYWJsZWRcbiAgICAgICAgLy8gZmFsbGJhY2sgb24gc291cmNlIGFuZCB0YXJnZXQgcG9zaXRpb25zXG4gICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICB2YXIgbjEgPSBlbGUuc291cmNlKCk7XG4gICAgICAgIHZhciBuMXBvcyA9IG4xLnBvc2l0aW9uKCk7XG4gICAgICAgIHZhciBuMiA9IGVsZS50YXJnZXQoKTtcbiAgICAgICAgdmFyIG4ycG9zID0gbjIucG9zaXRpb24oKTtcbiAgICAgICAgZXgxID0gbjFwb3MueDtcbiAgICAgICAgZXgyID0gbjJwb3MueDtcbiAgICAgICAgZXkxID0gbjFwb3MueTtcbiAgICAgICAgZXkyID0gbjJwb3MueTtcblxuICAgICAgICBpZiAoZXgxID4gZXgyKSB7XG4gICAgICAgICAgdmFyIF90ZW1wMiA9IGV4MTtcbiAgICAgICAgICBleDEgPSBleDI7XG4gICAgICAgICAgZXgyID0gX3RlbXAyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV5MSA+IGV5Mikge1xuICAgICAgICAgIHZhciBfdGVtcDMgPSBleTE7XG4gICAgICAgICAgZXkxID0gZXkyO1xuICAgICAgICAgIGV5MiA9IF90ZW1wMztcbiAgICAgICAgfSAvLyB0YWtlIGludG8gYWNjb3VudCBlZGdlIHdpZHRoXG5cblxuICAgICAgICBleDEgLT0gd0hhbGY7XG4gICAgICAgIGV4MiArPSB3SGFsZjtcbiAgICAgICAgZXkxIC09IHdIYWxmO1xuICAgICAgICBleTIgKz0gd0hhbGY7XG4gICAgICAgIHVwZGF0ZUJvdW5kcyhib3VuZHMsIGV4MSwgZXkxLCBleDIsIGV5Mik7XG4gICAgICB9IC8vIGhlYWRsZXNzIG9yIHN0eWxlIGRpc2FibGVkXG5cbiAgICB9IC8vIGVkZ2VzXG4gICAgLy8gaGFuZGxlIGVkZ2UgYXJyb3cgc2l6ZVxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuXG4gICAgaWYgKHN0eWxlRW5hYmxlZCAmJiBvcHRpb25zLmluY2x1ZGVFZGdlcyAmJiBpc0VkZ2UpIHtcbiAgICAgIHVwZGF0ZUJvdW5kc0Zyb21BcnJvdyhib3VuZHMsIGVsZSwgJ21pZC1zb3VyY2UnKTtcbiAgICAgIHVwZGF0ZUJvdW5kc0Zyb21BcnJvdyhib3VuZHMsIGVsZSwgJ21pZC10YXJnZXQnKTtcbiAgICAgIHVwZGF0ZUJvdW5kc0Zyb21BcnJvdyhib3VuZHMsIGVsZSwgJ3NvdXJjZScpO1xuICAgICAgdXBkYXRlQm91bmRzRnJvbUFycm93KGJvdW5kcywgZWxlLCAndGFyZ2V0Jyk7XG4gICAgfSAvLyBnaG9zdFxuICAgIC8vLy8vLy8vXG5cblxuICAgIGlmIChzdHlsZUVuYWJsZWQpIHtcbiAgICAgIHZhciBnaG9zdCA9IGVsZS5wc3R5bGUoJ2dob3N0JykudmFsdWUgPT09ICd5ZXMnO1xuXG4gICAgICBpZiAoZ2hvc3QpIHtcbiAgICAgICAgdmFyIGd4ID0gZWxlLnBzdHlsZSgnZ2hvc3Qtb2Zmc2V0LXgnKS5wZlZhbHVlO1xuICAgICAgICB2YXIgZ3kgPSBlbGUucHN0eWxlKCdnaG9zdC1vZmZzZXQteScpLnBmVmFsdWU7XG4gICAgICAgIHVwZGF0ZUJvdW5kcyhib3VuZHMsIGJvdW5kcy54MSArIGd4LCBib3VuZHMueTEgKyBneSwgYm91bmRzLngyICsgZ3gsIGJvdW5kcy55MiArIGd5KTtcbiAgICAgIH1cbiAgICB9IC8vIGFsd2F5cyBzdG9yZSB0aGUgYm9keSBib3VuZHMgc2VwYXJhdGVseSBmcm9tIHRoZSBsYWJlbHNcblxuXG4gICAgdmFyIGJiQm9keSA9IF9wLmJvZHlCb3VuZHMgPSBfcC5ib2R5Qm91bmRzIHx8IHt9O1xuICAgIGFzc2lnbkJvdW5kaW5nQm94KGJiQm9keSwgYm91bmRzKTtcbiAgICBleHBhbmRCb3VuZGluZ0JveFNpZGVzKGJiQm9keSwgbWFudWFsRXhwYW5zaW9uKTtcbiAgICBleHBhbmRCb3VuZGluZ0JveChiYkJvZHksIDEpOyAvLyBleHBhbmQgdG8gd29yayBhcm91bmQgYnJvd3NlciBkaW1lbnNpb24gaW5hY2N1cmFjaWVzXG4gICAgLy8gb3ZlcmxheVxuICAgIC8vLy8vLy8vLy9cblxuICAgIGlmIChzdHlsZUVuYWJsZWQpIHtcbiAgICAgIGV4MSA9IGJvdW5kcy54MTtcbiAgICAgIGV4MiA9IGJvdW5kcy54MjtcbiAgICAgIGV5MSA9IGJvdW5kcy55MTtcbiAgICAgIGV5MiA9IGJvdW5kcy55MjtcbiAgICAgIHVwZGF0ZUJvdW5kcyhib3VuZHMsIGV4MSAtIG92ZXJsYXlQYWRkaW5nLCBleTEgLSBvdmVybGF5UGFkZGluZywgZXgyICsgb3ZlcmxheVBhZGRpbmcsIGV5MiArIG92ZXJsYXlQYWRkaW5nKTtcbiAgICB9IC8vIGFsd2F5cyBzdG9yZSB0aGUgYm9keSBib3VuZHMgc2VwYXJhdGVseSBmcm9tIHRoZSBsYWJlbHNcblxuXG4gICAgdmFyIGJiT3ZlcmxheSA9IF9wLm92ZXJsYXlCb3VuZHMgPSBfcC5vdmVybGF5Qm91bmRzIHx8IHt9O1xuICAgIGFzc2lnbkJvdW5kaW5nQm94KGJiT3ZlcmxheSwgYm91bmRzKTtcbiAgICBleHBhbmRCb3VuZGluZ0JveFNpZGVzKGJiT3ZlcmxheSwgbWFudWFsRXhwYW5zaW9uKTtcbiAgICBleHBhbmRCb3VuZGluZ0JveChiYk92ZXJsYXksIDEpOyAvLyBleHBhbmQgdG8gd29yayBhcm91bmQgYnJvd3NlciBkaW1lbnNpb24gaW5hY2N1cmFjaWVzXG4gICAgLy8gaGFuZGxlIGxhYmVsIGRpbWVuc2lvbnNcbiAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgdmFyIGJiTGFiZWxzID0gX3AubGFiZWxCb3VuZHMgPSBfcC5sYWJlbEJvdW5kcyB8fCB7fTtcblxuICAgIGlmIChiYkxhYmVscy5hbGwgIT0gbnVsbCkge1xuICAgICAgY2xlYXJCb3VuZGluZ0JveChiYkxhYmVscy5hbGwpO1xuICAgIH0gZWxzZSB7XG4gICAgICBiYkxhYmVscy5hbGwgPSBtYWtlQm91bmRpbmdCb3goKTtcbiAgICB9XG5cbiAgICBpZiAoc3R5bGVFbmFibGVkICYmIG9wdGlvbnMuaW5jbHVkZUxhYmVscykge1xuICAgICAgaWYgKG9wdGlvbnMuaW5jbHVkZU1haW5MYWJlbHMpIHtcbiAgICAgICAgdXBkYXRlQm91bmRzRnJvbUxhYmVsKGJvdW5kcywgZWxlLCBudWxsKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRWRnZSkge1xuICAgICAgICBpZiAob3B0aW9ucy5pbmNsdWRlU291cmNlTGFiZWxzKSB7XG4gICAgICAgICAgdXBkYXRlQm91bmRzRnJvbUxhYmVsKGJvdW5kcywgZWxlLCAnc291cmNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5pbmNsdWRlVGFyZ2V0TGFiZWxzKSB7XG4gICAgICAgICAgdXBkYXRlQm91bmRzRnJvbUxhYmVsKGJvdW5kcywgZWxlLCAndGFyZ2V0Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IC8vIHN0eWxlIGVuYWJsZWQgZm9yIGxhYmVsc1xuXG4gIH0gLy8gaWYgZGlzcGxheWVkXG5cblxuICBib3VuZHMueDEgPSBub25pbmYoYm91bmRzLngxKTtcbiAgYm91bmRzLnkxID0gbm9uaW5mKGJvdW5kcy55MSk7XG4gIGJvdW5kcy54MiA9IG5vbmluZihib3VuZHMueDIpO1xuICBib3VuZHMueTIgPSBub25pbmYoYm91bmRzLnkyKTtcbiAgYm91bmRzLncgPSBub25pbmYoYm91bmRzLngyIC0gYm91bmRzLngxKTtcbiAgYm91bmRzLmggPSBub25pbmYoYm91bmRzLnkyIC0gYm91bmRzLnkxKTtcblxuICBpZiAoYm91bmRzLncgPiAwICYmIGJvdW5kcy5oID4gMCAmJiBkaXNwbGF5ZWQpIHtcbiAgICBleHBhbmRCb3VuZGluZ0JveFNpZGVzKGJvdW5kcywgbWFudWFsRXhwYW5zaW9uKTsgLy8gZXhwYW5kIGJvdW5kcyBieSAxIGJlY2F1c2UgYW50aWFsaWFzaW5nIGNhbiBpbmNyZWFzZSB0aGUgdmlzdWFsL2VmZmVjdGl2ZSBzaXplIGJ5IDEgb24gYWxsIHNpZGVzXG5cbiAgICBleHBhbmRCb3VuZGluZ0JveChib3VuZHMsIDEpO1xuICB9XG5cbiAgcmV0dXJuIGJvdW5kcztcbn07XG5cbnZhciBnZXRLZXkgPSBmdW5jdGlvbiBnZXRLZXkob3B0cykge1xuICB2YXIgaSA9IDA7XG5cbiAgdmFyIHRmID0gZnVuY3Rpb24gdGYodmFsKSB7XG4gICAgcmV0dXJuICh2YWwgPyAxIDogMCkgPDwgaSsrO1xuICB9O1xuXG4gIHZhciBrZXkgPSAwO1xuICBrZXkgKz0gdGYob3B0cy5pbmN1ZGVOb2Rlcyk7XG4gIGtleSArPSB0ZihvcHRzLmluY2x1ZGVFZGdlcyk7XG4gIGtleSArPSB0ZihvcHRzLmluY2x1ZGVMYWJlbHMpO1xuICBrZXkgKz0gdGYob3B0cy5pbmNsdWRlTWFpbkxhYmVscyk7XG4gIGtleSArPSB0ZihvcHRzLmluY2x1ZGVTb3VyY2VMYWJlbHMpO1xuICBrZXkgKz0gdGYob3B0cy5pbmNsdWRlVGFyZ2V0TGFiZWxzKTtcbiAga2V5ICs9IHRmKG9wdHMuaW5jbHVkZU92ZXJsYXlzKTtcbiAgcmV0dXJuIGtleTtcbn07XG5cbnZhciBnZXRCb3VuZGluZ0JveFBvc0tleSA9IGZ1bmN0aW9uIGdldEJvdW5kaW5nQm94UG9zS2V5KGVsZSkge1xuICBpZiAoZWxlLmlzRWRnZSgpKSB7XG4gICAgdmFyIHAxID0gZWxlLnNvdXJjZSgpLnBvc2l0aW9uKCk7XG4gICAgdmFyIHAyID0gZWxlLnRhcmdldCgpLnBvc2l0aW9uKCk7XG5cbiAgICB2YXIgciA9IGZ1bmN0aW9uIHIoeCkge1xuICAgICAgcmV0dXJuIE1hdGgucm91bmQoeCk7XG4gICAgfTtcblxuICAgIHJldHVybiBoYXNoSW50c0FycmF5KFtyKHAxLngpLCByKHAxLnkpLCByKHAyLngpLCByKHAyLnkpXSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbn07XG5cbnZhciBjYWNoZWRCb3VuZGluZ0JveEltcGwgPSBmdW5jdGlvbiBjYWNoZWRCb3VuZGluZ0JveEltcGwoZWxlLCBvcHRzKSB7XG4gIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgdmFyIGJiO1xuICB2YXIgaXNFZGdlID0gZWxlLmlzRWRnZSgpO1xuICB2YXIga2V5ID0gb3B0cyA9PSBudWxsID8gZGVmQmJPcHRzS2V5IDogZ2V0S2V5KG9wdHMpO1xuICB2YXIgdXNpbmdEZWZPcHRzID0ga2V5ID09PSBkZWZCYk9wdHNLZXk7XG4gIHZhciBjdXJyUG9zS2V5ID0gZ2V0Qm91bmRpbmdCb3hQb3NLZXkoZWxlKTtcbiAgdmFyIGlzUG9zS2V5U2FtZSA9IF9wLmJiQ2FjaGVQb3NLZXkgPT09IGN1cnJQb3NLZXk7XG4gIHZhciB1c2VDYWNoZSA9IG9wdHMudXNlQ2FjaGUgJiYgaXNQb3NLZXlTYW1lO1xuXG4gIHZhciBpc0RpcnR5ID0gZnVuY3Rpb24gaXNEaXJ0eShlbGUpIHtcbiAgICByZXR1cm4gZWxlLl9wcml2YXRlLmJiQ2FjaGUgPT0gbnVsbDtcbiAgfTtcblxuICB2YXIgbmVlZFJlY2FsYyA9ICF1c2VDYWNoZSB8fCBpc0RpcnR5KGVsZSkgfHwgaXNFZGdlICYmIGlzRGlydHkoZWxlLnNvdXJjZSgpKSB8fCBpc0RpcnR5KGVsZS50YXJnZXQoKSk7XG5cbiAgaWYgKG5lZWRSZWNhbGMpIHtcbiAgICBpZiAoIWlzUG9zS2V5U2FtZSkge1xuICAgICAgZWxlLnJlY2FsY3VsYXRlUmVuZGVyZWRTdHlsZSgpO1xuICAgIH1cblxuICAgIGJiID0gYm91bmRpbmdCb3hJbXBsKGVsZSwgZGVmQmJPcHRzKTtcbiAgICBfcC5iYkNhY2hlID0gYmI7XG4gICAgX3AuYmJDYWNoZVNoaWZ0LnggPSBfcC5iYkNhY2hlU2hpZnQueSA9IDA7XG4gICAgX3AuYmJDYWNoZVBvc0tleSA9IGN1cnJQb3NLZXk7XG4gIH0gZWxzZSB7XG4gICAgYmIgPSBfcC5iYkNhY2hlO1xuICB9XG5cbiAgaWYgKCFuZWVkUmVjYWxjICYmIChfcC5iYkNhY2hlU2hpZnQueCAhPT0gMCB8fCBfcC5iYkNhY2hlU2hpZnQueSAhPT0gMCkpIHtcbiAgICB2YXIgc2hpZnQgPSBhc3NpZ25TaGlmdFRvQm91bmRpbmdCb3g7XG4gICAgdmFyIGRlbHRhID0gX3AuYmJDYWNoZVNoaWZ0O1xuXG4gICAgdmFyIHNhZmVTaGlmdCA9IGZ1bmN0aW9uIHNhZmVTaGlmdChiYiwgZGVsdGEpIHtcbiAgICAgIGlmIChiYiAhPSBudWxsKSB7XG4gICAgICAgIHNoaWZ0KGJiLCBkZWx0YSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHNoaWZ0KGJiLCBkZWx0YSk7XG4gICAgdmFyIGJvZHlCb3VuZHMgPSBfcC5ib2R5Qm91bmRzLFxuICAgICAgICBvdmVybGF5Qm91bmRzID0gX3Aub3ZlcmxheUJvdW5kcyxcbiAgICAgICAgbGFiZWxCb3VuZHMgPSBfcC5sYWJlbEJvdW5kcyxcbiAgICAgICAgYXJyb3dCb3VuZHMgPSBfcC5hcnJvd0JvdW5kcztcbiAgICBzYWZlU2hpZnQoYm9keUJvdW5kcywgZGVsdGEpO1xuICAgIHNhZmVTaGlmdChvdmVybGF5Qm91bmRzLCBkZWx0YSk7XG5cbiAgICBpZiAoYXJyb3dCb3VuZHMgIT0gbnVsbCkge1xuICAgICAgc2FmZVNoaWZ0KGFycm93Qm91bmRzLnNvdXJjZSwgZGVsdGEpO1xuICAgICAgc2FmZVNoaWZ0KGFycm93Qm91bmRzLnRhcmdldCwgZGVsdGEpO1xuICAgICAgc2FmZVNoaWZ0KGFycm93Qm91bmRzWydtaWQtc291cmNlJ10sIGRlbHRhKTtcbiAgICAgIHNhZmVTaGlmdChhcnJvd0JvdW5kc1snbWlkLXRhcmdldCddLCBkZWx0YSk7XG4gICAgfVxuXG4gICAgaWYgKGxhYmVsQm91bmRzICE9IG51bGwpIHtcbiAgICAgIHNhZmVTaGlmdChsYWJlbEJvdW5kcy5tYWluLCBkZWx0YSk7XG4gICAgICBzYWZlU2hpZnQobGFiZWxCb3VuZHMuYWxsLCBkZWx0YSk7XG4gICAgICBzYWZlU2hpZnQobGFiZWxCb3VuZHMuc291cmNlLCBkZWx0YSk7XG4gICAgICBzYWZlU2hpZnQobGFiZWxCb3VuZHMudGFyZ2V0LCBkZWx0YSk7XG4gICAgfVxuICB9IC8vIGFsd2F5cyByZXNldCB0aGUgc2hpZnQsIGJlY2F1c2Ugd2UgZWl0aGVyIGFwcGxpZWQgdGhlIHNoaWZ0IG9yIGNsZWFyZWQgaXQgYnkgZG9pbmcgYSBmcmVzaCByZWNhbGNcblxuXG4gIF9wLmJiQ2FjaGVTaGlmdC54ID0gX3AuYmJDYWNoZVNoaWZ0LnkgPSAwOyAvLyBub3QgdXNpbmcgZGVmIG9wdHMgPT4gbmVlZCB0byBidWlsZCB1cCBiYiBmcm9tIGNvbWJpbmF0aW9uIG9mIHN1YiBiYnNcblxuICBpZiAoIXVzaW5nRGVmT3B0cykge1xuICAgIHZhciBpc05vZGUgPSBlbGUuaXNOb2RlKCk7XG4gICAgYmIgPSBtYWtlQm91bmRpbmdCb3goKTtcblxuICAgIGlmIChvcHRzLmluY2x1ZGVOb2RlcyAmJiBpc05vZGUgfHwgb3B0cy5pbmNsdWRlRWRnZXMgJiYgIWlzTm9kZSkge1xuICAgICAgaWYgKG9wdHMuaW5jbHVkZU92ZXJsYXlzKSB7XG4gICAgICAgIHVwZGF0ZUJvdW5kc0Zyb21Cb3goYmIsIF9wLm92ZXJsYXlCb3VuZHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXBkYXRlQm91bmRzRnJvbUJveChiYiwgX3AuYm9keUJvdW5kcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuaW5jbHVkZUxhYmVscykge1xuICAgICAgaWYgKG9wdHMuaW5jbHVkZU1haW5MYWJlbHMgJiYgKCFpc0VkZ2UgfHwgb3B0cy5pbmNsdWRlU291cmNlTGFiZWxzICYmIG9wdHMuaW5jbHVkZVRhcmdldExhYmVscykpIHtcbiAgICAgICAgdXBkYXRlQm91bmRzRnJvbUJveChiYiwgX3AubGFiZWxCb3VuZHMuYWxsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChvcHRzLmluY2x1ZGVNYWluTGFiZWxzKSB7XG4gICAgICAgICAgdXBkYXRlQm91bmRzRnJvbUJveChiYiwgX3AubGFiZWxCb3VuZHMubWFpblJvdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0cy5pbmNsdWRlU291cmNlTGFiZWxzKSB7XG4gICAgICAgICAgdXBkYXRlQm91bmRzRnJvbUJveChiYiwgX3AubGFiZWxCb3VuZHMuc291cmNlUm90KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRzLmluY2x1ZGVUYXJnZXRMYWJlbHMpIHtcbiAgICAgICAgICB1cGRhdGVCb3VuZHNGcm9tQm94KGJiLCBfcC5sYWJlbEJvdW5kcy50YXJnZXRSb3QpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgYmIudyA9IGJiLngyIC0gYmIueDE7XG4gICAgYmIuaCA9IGJiLnkyIC0gYmIueTE7XG4gIH1cblxuICByZXR1cm4gYmI7XG59O1xuXG52YXIgZGVmQmJPcHRzID0ge1xuICBpbmNsdWRlTm9kZXM6IHRydWUsXG4gIGluY2x1ZGVFZGdlczogdHJ1ZSxcbiAgaW5jbHVkZUxhYmVsczogdHJ1ZSxcbiAgaW5jbHVkZU1haW5MYWJlbHM6IHRydWUsXG4gIGluY2x1ZGVTb3VyY2VMYWJlbHM6IHRydWUsXG4gIGluY2x1ZGVUYXJnZXRMYWJlbHM6IHRydWUsXG4gIGluY2x1ZGVPdmVybGF5czogdHJ1ZSxcbiAgdXNlQ2FjaGU6IHRydWVcbn07XG52YXIgZGVmQmJPcHRzS2V5ID0gZ2V0S2V5KGRlZkJiT3B0cyk7XG52YXIgZmlsbGVkQmJPcHRzID0gZGVmYXVsdHMoZGVmQmJPcHRzKTtcblxuZWxlc2ZuJGsuYm91bmRpbmdCb3ggPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICB2YXIgYm91bmRzOyAvLyB0aGUgbWFpbiB1c2VjYXNlIGlzIGVsZS5ib3VuZGluZ0JveCgpIGZvciBhIHNpbmdsZSBlbGVtZW50IHdpdGggbm8vZGVmIG9wdGlvbnNcbiAgLy8gc3BlY2lmaWVkIHMudC4gdGhlIGNhY2hlIGlzIHVzZWQsIHNvIGNoZWNrIGZvciB0aGlzIGNhc2UgdG8gbWFrZSBpdCBmYXN0ZXIgYnlcbiAgLy8gYXZvaWRpbmcgdGhlIG92ZXJoZWFkIG9mIHRoZSByZXN0IG9mIHRoZSBmdW5jdGlvblxuXG4gIGlmICh0aGlzLmxlbmd0aCA9PT0gMSAmJiB0aGlzWzBdLl9wcml2YXRlLmJiQ2FjaGUgIT0gbnVsbCAmJiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkIHx8IG9wdGlvbnMudXNlQ2FjaGUgPT09IHVuZGVmaW5lZCB8fCBvcHRpb25zLnVzZUNhY2hlID09PSB0cnVlKSkge1xuICAgIGlmIChvcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG9wdGlvbnMgPSBkZWZCYk9wdHM7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wdGlvbnMgPSBmaWxsZWRCYk9wdHMob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgYm91bmRzID0gY2FjaGVkQm91bmRpbmdCb3hJbXBsKHRoaXNbMF0sIG9wdGlvbnMpO1xuICB9IGVsc2Uge1xuICAgIGJvdW5kcyA9IG1ha2VCb3VuZGluZ0JveCgpO1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IGRlZkJiT3B0cztcbiAgICB2YXIgb3B0cyA9IGZpbGxlZEJiT3B0cyhvcHRpb25zKTtcbiAgICB2YXIgZWxlcyA9IHRoaXM7XG4gICAgdmFyIGN5ID0gZWxlcy5jeSgpO1xuICAgIHZhciBzdHlsZUVuYWJsZWQgPSBjeS5zdHlsZUVuYWJsZWQoKTtcblxuICAgIGlmIChzdHlsZUVuYWJsZWQpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICAgICAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICAgICAgICB2YXIgY3VyclBvc0tleSA9IGdldEJvdW5kaW5nQm94UG9zS2V5KGVsZSk7XG4gICAgICAgIHZhciBpc1Bvc0tleVNhbWUgPSBfcC5iYkNhY2hlUG9zS2V5ID09PSBjdXJyUG9zS2V5O1xuICAgICAgICB2YXIgdXNlQ2FjaGUgPSBvcHRzLnVzZUNhY2hlICYmIGlzUG9zS2V5U2FtZTtcbiAgICAgICAgZWxlLnJlY2FsY3VsYXRlUmVuZGVyZWRTdHlsZSh1c2VDYWNoZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGVDb21wb3VuZEJvdW5kcygpO1xuXG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGVsZXMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICB2YXIgX2VsZSA9IGVsZXNbX2ldO1xuICAgICAgdXBkYXRlQm91bmRzRnJvbUJveChib3VuZHMsIGNhY2hlZEJvdW5kaW5nQm94SW1wbChfZWxlLCBvcHRzKSk7XG4gICAgfVxuICB9XG5cbiAgYm91bmRzLngxID0gbm9uaW5mKGJvdW5kcy54MSk7XG4gIGJvdW5kcy55MSA9IG5vbmluZihib3VuZHMueTEpO1xuICBib3VuZHMueDIgPSBub25pbmYoYm91bmRzLngyKTtcbiAgYm91bmRzLnkyID0gbm9uaW5mKGJvdW5kcy55Mik7XG4gIGJvdW5kcy53ID0gbm9uaW5mKGJvdW5kcy54MiAtIGJvdW5kcy54MSk7XG4gIGJvdW5kcy5oID0gbm9uaW5mKGJvdW5kcy55MiAtIGJvdW5kcy55MSk7XG4gIHJldHVybiBib3VuZHM7XG59O1xuXG5lbGVzZm4kay5kaXJ0eUJvdW5kaW5nQm94Q2FjaGUgPSBmdW5jdGlvbiAoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBfcCA9IHRoaXNbaV0uX3ByaXZhdGU7XG4gICAgX3AuYmJDYWNoZSA9IG51bGw7XG4gICAgX3AuYmJDYWNoZVNoaWZ0LnggPSBfcC5iYkNhY2hlU2hpZnQueSA9IDA7XG4gICAgX3AuYmJDYWNoZVBvc0tleSA9IG51bGw7XG4gICAgX3AuYm9keUJvdW5kcyA9IG51bGw7XG4gICAgX3Aub3ZlcmxheUJvdW5kcyA9IG51bGw7XG4gICAgX3AubGFiZWxCb3VuZHMuYWxsID0gbnVsbDtcbiAgICBfcC5sYWJlbEJvdW5kcy5zb3VyY2UgPSBudWxsO1xuICAgIF9wLmxhYmVsQm91bmRzLnRhcmdldCA9IG51bGw7XG4gICAgX3AubGFiZWxCb3VuZHMubWFpbiA9IG51bGw7XG4gICAgX3AubGFiZWxCb3VuZHMuc291cmNlUm90ID0gbnVsbDtcbiAgICBfcC5sYWJlbEJvdW5kcy50YXJnZXRSb3QgPSBudWxsO1xuICAgIF9wLmxhYmVsQm91bmRzLm1haW5Sb3QgPSBudWxsO1xuICAgIF9wLmFycm93Qm91bmRzLnNvdXJjZSA9IG51bGw7XG4gICAgX3AuYXJyb3dCb3VuZHMudGFyZ2V0ID0gbnVsbDtcbiAgICBfcC5hcnJvd0JvdW5kc1snbWlkLXNvdXJjZSddID0gbnVsbDtcbiAgICBfcC5hcnJvd0JvdW5kc1snbWlkLXRhcmdldCddID0gbnVsbDtcbiAgfVxuXG4gIHRoaXMuZW1pdEFuZE5vdGlmeSgnYm91bmRzJyk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuZWxlc2ZuJGsuc2hpZnRDYWNoZWRCb3VuZGluZ0JveCA9IGZ1bmN0aW9uIChkZWx0YSkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gICAgdmFyIGJiID0gX3AuYmJDYWNoZTtcblxuICAgIGlmIChiYiAhPSBudWxsKSB7XG4gICAgICBfcC5iYkNhY2hlU2hpZnQueCArPSBkZWx0YS54O1xuICAgICAgX3AuYmJDYWNoZVNoaWZ0LnkgKz0gZGVsdGEueTtcbiAgICB9XG4gIH1cblxuICB0aGlzLmVtaXRBbmROb3RpZnkoJ2JvdW5kcycpO1xuICByZXR1cm4gdGhpcztcbn07IC8vIHByaXZhdGUgaGVscGVyIHRvIGdldCBib3VuZGluZyBib3ggZm9yIGN1c3RvbSBub2RlIHBvc2l0aW9uc1xuLy8gLSBnb29kIGZvciBwZXJmIGluIGNlcnRhaW4gY2FzZXMgYnV0IGN1cnJlbnRseSByZXF1aXJlcyBkaXJ0eWluZyB0aGUgcmVuZGVyZWQgc3R5bGVcbi8vIC0gd291bGQgYmUgYmV0dGVyIHRvIG5vdCBtb2RpZnkgdGhlIG5vZGVzIGJ1dCB0aGUgbm9kZXMgYXJlIHJlYWQgZGlyZWN0bHkgZXZlcnl3aGVyZSBpbiB0aGUgcmVuZGVyZXIuLi5cbi8vIC0gdHJ5IHRvIHVzZSBmb3Igb25seSB0aGluZ3MgbGlrZSBkaXNjcmV0ZSBsYXlvdXRzIHdoZXJlIHRoZSBub2RlIHBvc2l0aW9uIHdvdWxkIGNoYW5nZSBhbnl3YXlcblxuXG5lbGVzZm4kay5ib3VuZGluZ0JveEF0ID0gZnVuY3Rpb24gKGZuKSB7XG4gIHZhciBub2RlcyA9IHRoaXMubm9kZXMoKTtcbiAgdmFyIGN5ID0gdGhpcy5jeSgpO1xuICB2YXIgaGFzQ29tcG91bmROb2RlcyA9IGN5Lmhhc0NvbXBvdW5kTm9kZXMoKTtcblxuICBpZiAoaGFzQ29tcG91bmROb2Rlcykge1xuICAgIG5vZGVzID0gbm9kZXMuZmlsdGVyKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gIW5vZGUuaXNQYXJlbnQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChwbGFpbk9iamVjdChmbikpIHtcbiAgICB2YXIgb2JqID0gZm47XG5cbiAgICBmbiA9IGZ1bmN0aW9uIGZuKCkge1xuICAgICAgcmV0dXJuIG9iajtcbiAgICB9O1xuICB9XG5cbiAgdmFyIHN0b3JlT2xkUG9zID0gZnVuY3Rpb24gc3RvcmVPbGRQb3Mobm9kZSwgaSkge1xuICAgIHJldHVybiBub2RlLl9wcml2YXRlLmJiQXRPbGRQb3MgPSBmbihub2RlLCBpKTtcbiAgfTtcblxuICB2YXIgZ2V0T2xkUG9zID0gZnVuY3Rpb24gZ2V0T2xkUG9zKG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZS5fcHJpdmF0ZS5iYkF0T2xkUG9zO1xuICB9O1xuXG4gIGN5LnN0YXJ0QmF0Y2goKTtcbiAgbm9kZXMuZm9yRWFjaChzdG9yZU9sZFBvcykuc2lsZW50UG9zaXRpb25zKGZuKTtcblxuICBpZiAoaGFzQ29tcG91bmROb2Rlcykge1xuICAgIHRoaXMudXBkYXRlQ29tcG91bmRCb3VuZHModHJ1ZSk7IC8vIGZvcmNlIHVwZGF0ZSBiL2Mgd2UncmUgaW5zaWRlIGEgYmF0Y2ggY3ljbGVcbiAgfVxuXG4gIHZhciBiYiA9IGNvcHlCb3VuZGluZ0JveCh0aGlzLmJvdW5kaW5nQm94KHtcbiAgICB1c2VDYWNoZTogZmFsc2VcbiAgfSkpO1xuICBub2Rlcy5zaWxlbnRQb3NpdGlvbnMoZ2V0T2xkUG9zKTtcbiAgY3kuZW5kQmF0Y2goKTtcbiAgcmV0dXJuIGJiO1xufTtcblxuZm4kMy5ib3VuZGluZ2JveCA9IGZuJDMuYmIgPSBmbiQzLmJvdW5kaW5nQm94O1xuZm4kMy5yZW5kZXJlZEJvdW5kaW5nYm94ID0gZm4kMy5yZW5kZXJlZEJvdW5kaW5nQm94O1xudmFyIGJvdW5kcyA9IGVsZXNmbiRrO1xuXG52YXIgZm4kNCwgZWxlc2ZuJGw7XG5mbiQ0ID0gZWxlc2ZuJGwgPSB7fTtcblxudmFyIGRlZmluZURpbUZucyA9IGZ1bmN0aW9uIGRlZmluZURpbUZucyhvcHRzKSB7XG4gIG9wdHMudXBwZXJjYXNlTmFtZSA9IGNhcGl0YWxpemUob3B0cy5uYW1lKTtcbiAgb3B0cy5hdXRvTmFtZSA9ICdhdXRvJyArIG9wdHMudXBwZXJjYXNlTmFtZTtcbiAgb3B0cy5sYWJlbE5hbWUgPSAnbGFiZWwnICsgb3B0cy51cHBlcmNhc2VOYW1lO1xuICBvcHRzLm91dGVyTmFtZSA9ICdvdXRlcicgKyBvcHRzLnVwcGVyY2FzZU5hbWU7XG4gIG9wdHMudXBwZXJjYXNlT3V0ZXJOYW1lID0gY2FwaXRhbGl6ZShvcHRzLm91dGVyTmFtZSk7XG5cbiAgZm4kNFtvcHRzLm5hbWVdID0gZnVuY3Rpb24gZGltSW1wbCgpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcbiAgICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gICAgdmFyIGN5ID0gX3AuY3k7XG4gICAgdmFyIHN0eWxlRW5hYmxlZCA9IGN5Ll9wcml2YXRlLnN0eWxlRW5hYmxlZDtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIGlmIChzdHlsZUVuYWJsZWQpIHtcbiAgICAgICAgaWYgKGVsZS5pc1BhcmVudCgpKSB7XG4gICAgICAgICAgZWxlLnVwZGF0ZUNvbXBvdW5kQm91bmRzKCk7XG4gICAgICAgICAgcmV0dXJuIF9wW29wdHMuYXV0b05hbWVdIHx8IDA7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZCA9IGVsZS5wc3R5bGUob3B0cy5uYW1lKTtcblxuICAgICAgICBzd2l0Y2ggKGQuc3RyVmFsdWUpIHtcbiAgICAgICAgICBjYXNlICdsYWJlbCc6XG4gICAgICAgICAgICBlbGUucmVjYWxjdWxhdGVSZW5kZXJlZFN0eWxlKCk7XG4gICAgICAgICAgICByZXR1cm4gX3AucnN0eWxlW29wdHMubGFiZWxOYW1lXSB8fCAwO1xuXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBkLnBmVmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBmbiQ0WydvdXRlcicgKyBvcHRzLnVwcGVyY2FzZU5hbWVdID0gZnVuY3Rpb24gb3V0ZXJEaW1JbXBsKCkge1xuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuICAgIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgICB2YXIgY3kgPSBfcC5jeTtcbiAgICB2YXIgc3R5bGVFbmFibGVkID0gY3kuX3ByaXZhdGUuc3R5bGVFbmFibGVkO1xuXG4gICAgaWYgKGVsZSkge1xuICAgICAgaWYgKHN0eWxlRW5hYmxlZCkge1xuICAgICAgICB2YXIgZGltID0gZWxlW29wdHMubmFtZV0oKTtcbiAgICAgICAgdmFyIGJvcmRlciA9IGVsZS5wc3R5bGUoJ2JvcmRlci13aWR0aCcpLnBmVmFsdWU7IC8vIG4uYi4gMS8yIGVhY2ggc2lkZVxuXG4gICAgICAgIHZhciBwYWRkaW5nID0gMiAqIGVsZS5wYWRkaW5nKCk7XG4gICAgICAgIHJldHVybiBkaW0gKyBib3JkZXIgKyBwYWRkaW5nO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGZuJDRbJ3JlbmRlcmVkJyArIG9wdHMudXBwZXJjYXNlTmFtZV0gPSBmdW5jdGlvbiByZW5kZXJlZERpbUltcGwoKSB7XG4gICAgdmFyIGVsZSA9IHRoaXNbMF07XG5cbiAgICBpZiAoZWxlKSB7XG4gICAgICB2YXIgZCA9IGVsZVtvcHRzLm5hbWVdKCk7XG4gICAgICByZXR1cm4gZCAqIHRoaXMuY3koKS56b29tKCk7XG4gICAgfVxuICB9O1xuXG4gIGZuJDRbJ3JlbmRlcmVkJyArIG9wdHMudXBwZXJjYXNlT3V0ZXJOYW1lXSA9IGZ1bmN0aW9uIHJlbmRlcmVkT3V0ZXJEaW1JbXBsKCkge1xuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuXG4gICAgaWYgKGVsZSkge1xuICAgICAgdmFyIG9kID0gZWxlW29wdHMub3V0ZXJOYW1lXSgpO1xuICAgICAgcmV0dXJuIG9kICogdGhpcy5jeSgpLnpvb20oKTtcbiAgICB9XG4gIH07XG59O1xuXG5kZWZpbmVEaW1GbnMoe1xuICBuYW1lOiAnd2lkdGgnXG59KTtcbmRlZmluZURpbUZucyh7XG4gIG5hbWU6ICdoZWlnaHQnXG59KTtcblxuZWxlc2ZuJGwucGFkZGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGVsZSA9IHRoaXNbMF07XG4gIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcblxuICBpZiAoZWxlLmlzUGFyZW50KCkpIHtcbiAgICBlbGUudXBkYXRlQ29tcG91bmRCb3VuZHMoKTtcblxuICAgIGlmIChfcC5hdXRvUGFkZGluZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gX3AuYXV0b1BhZGRpbmc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBlbGUucHN0eWxlKCdwYWRkaW5nJykucGZWYWx1ZTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGVsZS5wc3R5bGUoJ3BhZGRpbmcnKS5wZlZhbHVlO1xuICB9XG59O1xuXG5lbGVzZm4kbC5wYWRkZWRIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBlbGUgPSB0aGlzWzBdO1xuICByZXR1cm4gZWxlLmhlaWdodCgpICsgMiAqIGVsZS5wYWRkaW5nKCk7XG59O1xuXG5lbGVzZm4kbC5wYWRkZWRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGVsZSA9IHRoaXNbMF07XG4gIHJldHVybiBlbGUud2lkdGgoKSArIDIgKiBlbGUucGFkZGluZygpO1xufTtcblxudmFyIHdpZHRoSGVpZ2h0ID0gZWxlc2ZuJGw7XG5cbnZhciBpZkVkZ2UgPSBmdW5jdGlvbiBpZkVkZ2UoZWxlLCBnZXRWYWx1ZSkge1xuICBpZiAoZWxlLmlzRWRnZSgpKSB7XG4gICAgcmV0dXJuIGdldFZhbHVlKGVsZSk7XG4gIH1cbn07XG5cbnZhciBpZkVkZ2VSZW5kZXJlZFBvc2l0aW9uID0gZnVuY3Rpb24gaWZFZGdlUmVuZGVyZWRQb3NpdGlvbihlbGUsIGdldFBvaW50KSB7XG4gIGlmIChlbGUuaXNFZGdlKCkpIHtcbiAgICB2YXIgY3kgPSBlbGUuY3koKTtcbiAgICByZXR1cm4gbW9kZWxUb1JlbmRlcmVkUG9zaXRpb24oZ2V0UG9pbnQoZWxlKSwgY3kuem9vbSgpLCBjeS5wYW4oKSk7XG4gIH1cbn07XG5cbnZhciBpZkVkZ2VSZW5kZXJlZFBvc2l0aW9ucyA9IGZ1bmN0aW9uIGlmRWRnZVJlbmRlcmVkUG9zaXRpb25zKGVsZSwgZ2V0UG9pbnRzKSB7XG4gIGlmIChlbGUuaXNFZGdlKCkpIHtcbiAgICB2YXIgY3kgPSBlbGUuY3koKTtcbiAgICB2YXIgcGFuID0gY3kucGFuKCk7XG4gICAgdmFyIHpvb20gPSBjeS56b29tKCk7XG4gICAgcmV0dXJuIGdldFBvaW50cyhlbGUpLm1hcChmdW5jdGlvbiAocCkge1xuICAgICAgcmV0dXJuIG1vZGVsVG9SZW5kZXJlZFBvc2l0aW9uKHAsIHpvb20sIHBhbik7XG4gICAgfSk7XG4gIH1cbn07XG5cbnZhciBjb250cm9sUG9pbnRzID0gZnVuY3Rpb24gY29udHJvbFBvaW50cyhlbGUpIHtcbiAgcmV0dXJuIGVsZS5yZW5kZXJlcigpLmdldENvbnRyb2xQb2ludHMoZWxlKTtcbn07XG5cbnZhciBzZWdtZW50UG9pbnRzID0gZnVuY3Rpb24gc2VnbWVudFBvaW50cyhlbGUpIHtcbiAgcmV0dXJuIGVsZS5yZW5kZXJlcigpLmdldFNlZ21lbnRQb2ludHMoZWxlKTtcbn07XG5cbnZhciBzb3VyY2VFbmRwb2ludCA9IGZ1bmN0aW9uIHNvdXJjZUVuZHBvaW50KGVsZSkge1xuICByZXR1cm4gZWxlLnJlbmRlcmVyKCkuZ2V0U291cmNlRW5kcG9pbnQoZWxlKTtcbn07XG5cbnZhciB0YXJnZXRFbmRwb2ludCA9IGZ1bmN0aW9uIHRhcmdldEVuZHBvaW50KGVsZSkge1xuICByZXR1cm4gZWxlLnJlbmRlcmVyKCkuZ2V0VGFyZ2V0RW5kcG9pbnQoZWxlKTtcbn07XG5cbnZhciBtaWRwb2ludCA9IGZ1bmN0aW9uIG1pZHBvaW50KGVsZSkge1xuICByZXR1cm4gZWxlLnJlbmRlcmVyKCkuZ2V0RWRnZU1pZHBvaW50KGVsZSk7XG59O1xuXG52YXIgcHRzID0ge1xuICBjb250cm9sUG9pbnRzOiB7XG4gICAgZ2V0OiBjb250cm9sUG9pbnRzLFxuICAgIG11bHQ6IHRydWVcbiAgfSxcbiAgc2VnbWVudFBvaW50czoge1xuICAgIGdldDogc2VnbWVudFBvaW50cyxcbiAgICBtdWx0OiB0cnVlXG4gIH0sXG4gIHNvdXJjZUVuZHBvaW50OiB7XG4gICAgZ2V0OiBzb3VyY2VFbmRwb2ludFxuICB9LFxuICB0YXJnZXRFbmRwb2ludDoge1xuICAgIGdldDogdGFyZ2V0RW5kcG9pbnRcbiAgfSxcbiAgbWlkcG9pbnQ6IHtcbiAgICBnZXQ6IG1pZHBvaW50XG4gIH1cbn07XG5cbnZhciByZW5kZXJlZE5hbWUgPSBmdW5jdGlvbiByZW5kZXJlZE5hbWUobmFtZSkge1xuICByZXR1cm4gJ3JlbmRlcmVkJyArIG5hbWVbMF0udG9VcHBlckNhc2UoKSArIG5hbWUuc3Vic3RyKDEpO1xufTtcblxudmFyIGVkZ2VQb2ludHMgPSBPYmplY3Qua2V5cyhwdHMpLnJlZHVjZShmdW5jdGlvbiAob2JqLCBuYW1lKSB7XG4gIHZhciBzcGVjID0gcHRzW25hbWVdO1xuICB2YXIgck5hbWUgPSByZW5kZXJlZE5hbWUobmFtZSk7XG5cbiAgb2JqW25hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBpZkVkZ2UodGhpcywgc3BlYy5nZXQpO1xuICB9O1xuXG4gIGlmIChzcGVjLm11bHQpIHtcbiAgICBvYmpbck5hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGlmRWRnZVJlbmRlcmVkUG9zaXRpb25zKHRoaXMsIHNwZWMuZ2V0KTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIG9ialtyTmFtZV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gaWZFZGdlUmVuZGVyZWRQb3NpdGlvbih0aGlzLCBzcGVjLmdldCk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBvYmo7XG59LCB7fSk7XG5cbnZhciBkaW1lbnNpb25zID0gZXh0ZW5kKHt9LCBwb3NpdGlvbiwgYm91bmRzLCB3aWR0aEhlaWdodCwgZWRnZVBvaW50cyk7XG5cbi8qIVxuRXZlbnQgb2JqZWN0IGJhc2VkIG9uIGpRdWVyeSBldmVudHMsIE1JVCBsaWNlbnNlXG5cbmh0dHBzOi8vanF1ZXJ5Lm9yZy9saWNlbnNlL1xuaHR0cHM6Ly90bGRybGVnYWwuY29tL2xpY2Vuc2UvbWl0LWxpY2Vuc2Vcbmh0dHBzOi8vZ2l0aHViLmNvbS9qcXVlcnkvanF1ZXJ5L2Jsb2IvbWFzdGVyL3NyYy9ldmVudC5qc1xuKi9cbnZhciBFdmVudCA9IGZ1bmN0aW9uIEV2ZW50KHNyYywgcHJvcHMpIHtcbiAgdGhpcy5yZWN5Y2xlKHNyYywgcHJvcHMpO1xufTtcblxuZnVuY3Rpb24gcmV0dXJuRmFsc2UoKSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gcmV0dXJuVHJ1ZSgpIHtcbiAgcmV0dXJuIHRydWU7XG59IC8vIGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMDMvV0QtRE9NLUxldmVsLTMtRXZlbnRzLTIwMDMwMzMxL2VjbWEtc2NyaXB0LWJpbmRpbmcuaHRtbFxuXG5cbkV2ZW50LnByb3RvdHlwZSA9IHtcbiAgaW5zdGFuY2VTdHJpbmc6IGZ1bmN0aW9uIGluc3RhbmNlU3RyaW5nKCkge1xuICAgIHJldHVybiAnZXZlbnQnO1xuICB9LFxuICByZWN5Y2xlOiBmdW5jdGlvbiByZWN5Y2xlKHNyYywgcHJvcHMpIHtcbiAgICB0aGlzLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkID0gdGhpcy5pc1Byb3BhZ2F0aW9uU3RvcHBlZCA9IHRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gcmV0dXJuRmFsc2U7XG5cbiAgICBpZiAoc3JjICE9IG51bGwgJiYgc3JjLnByZXZlbnREZWZhdWx0KSB7XG4gICAgICAvLyBCcm93c2VyIEV2ZW50IG9iamVjdFxuICAgICAgdGhpcy50eXBlID0gc3JjLnR5cGU7IC8vIEV2ZW50cyBidWJibGluZyB1cCB0aGUgZG9jdW1lbnQgbWF5IGhhdmUgYmVlbiBtYXJrZWQgYXMgcHJldmVudGVkXG4gICAgICAvLyBieSBhIGhhbmRsZXIgbG93ZXIgZG93biB0aGUgdHJlZTsgcmVmbGVjdCB0aGUgY29ycmVjdCB2YWx1ZS5cblxuICAgICAgdGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSBzcmMuZGVmYXVsdFByZXZlbnRlZCA/IHJldHVyblRydWUgOiByZXR1cm5GYWxzZTtcbiAgICB9IGVsc2UgaWYgKHNyYyAhPSBudWxsICYmIHNyYy50eXBlKSB7XG4gICAgICAvLyBQbGFpbiBvYmplY3QgY29udGFpbmluZyBhbGwgZXZlbnQgZGV0YWlsc1xuICAgICAgcHJvcHMgPSBzcmM7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEV2ZW50IHN0cmluZ1xuICAgICAgdGhpcy50eXBlID0gc3JjO1xuICAgIH0gLy8gUHV0IGV4cGxpY2l0bHkgcHJvdmlkZWQgcHJvcGVydGllcyBvbnRvIHRoZSBldmVudCBvYmplY3RcblxuXG4gICAgaWYgKHByb3BzICE9IG51bGwpIHtcbiAgICAgIC8vIG1vcmUgZWZmaWNpZW50IHRvIG1hbnVhbGx5IGNvcHkgZmllbGRzIHdlIHVzZVxuICAgICAgdGhpcy5vcmlnaW5hbEV2ZW50ID0gcHJvcHMub3JpZ2luYWxFdmVudDtcbiAgICAgIHRoaXMudHlwZSA9IHByb3BzLnR5cGUgIT0gbnVsbCA/IHByb3BzLnR5cGUgOiB0aGlzLnR5cGU7XG4gICAgICB0aGlzLmN5ID0gcHJvcHMuY3k7XG4gICAgICB0aGlzLnRhcmdldCA9IHByb3BzLnRhcmdldDtcbiAgICAgIHRoaXMucG9zaXRpb24gPSBwcm9wcy5wb3NpdGlvbjtcbiAgICAgIHRoaXMucmVuZGVyZWRQb3NpdGlvbiA9IHByb3BzLnJlbmRlcmVkUG9zaXRpb247XG4gICAgICB0aGlzLm5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgIHRoaXMubGF5b3V0ID0gcHJvcHMubGF5b3V0O1xuICAgIH1cblxuICAgIGlmICh0aGlzLmN5ICE9IG51bGwgJiYgdGhpcy5wb3NpdGlvbiAhPSBudWxsICYmIHRoaXMucmVuZGVyZWRQb3NpdGlvbiA9PSBudWxsKSB7XG4gICAgICAvLyBjcmVhdGUgYSByZW5kZXJlZCBwb3NpdGlvbiBiYXNlZCBvbiB0aGUgcGFzc2VkIHBvc2l0aW9uXG4gICAgICB2YXIgcG9zID0gdGhpcy5wb3NpdGlvbjtcbiAgICAgIHZhciB6b29tID0gdGhpcy5jeS56b29tKCk7XG4gICAgICB2YXIgcGFuID0gdGhpcy5jeS5wYW4oKTtcbiAgICAgIHRoaXMucmVuZGVyZWRQb3NpdGlvbiA9IHtcbiAgICAgICAgeDogcG9zLnggKiB6b29tICsgcGFuLngsXG4gICAgICAgIHk6IHBvcy55ICogem9vbSArIHBhbi55XG4gICAgICB9O1xuICAgIH0gLy8gQ3JlYXRlIGEgdGltZXN0YW1wIGlmIGluY29taW5nIGV2ZW50IGRvZXNuJ3QgaGF2ZSBvbmVcblxuXG4gICAgdGhpcy50aW1lU3RhbXAgPSBzcmMgJiYgc3JjLnRpbWVTdGFtcCB8fCBEYXRlLm5vdygpO1xuICB9LFxuICBwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24gcHJldmVudERlZmF1bHQoKSB7XG4gICAgdGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSByZXR1cm5UcnVlO1xuICAgIHZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50O1xuXG4gICAgaWYgKCFlKSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyBpZiBwcmV2ZW50RGVmYXVsdCBleGlzdHMgcnVuIGl0IG9uIHRoZSBvcmlnaW5hbCBldmVudFxuXG5cbiAgICBpZiAoZS5wcmV2ZW50RGVmYXVsdCkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfSxcbiAgc3RvcFByb3BhZ2F0aW9uOiBmdW5jdGlvbiBzdG9wUHJvcGFnYXRpb24oKSB7XG4gICAgdGhpcy5pc1Byb3BhZ2F0aW9uU3RvcHBlZCA9IHJldHVyblRydWU7XG4gICAgdmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7XG5cbiAgICBpZiAoIWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9IC8vIGlmIHN0b3BQcm9wYWdhdGlvbiBleGlzdHMgcnVuIGl0IG9uIHRoZSBvcmlnaW5hbCBldmVudFxuXG5cbiAgICBpZiAoZS5zdG9wUHJvcGFnYXRpb24pIHtcbiAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuICB9LFxuICBzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb246IGZ1bmN0aW9uIHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpIHtcbiAgICB0aGlzLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTtcbiAgICB0aGlzLnN0b3BQcm9wYWdhdGlvbigpO1xuICB9LFxuICBpc0RlZmF1bHRQcmV2ZW50ZWQ6IHJldHVybkZhbHNlLFxuICBpc1Byb3BhZ2F0aW9uU3RvcHBlZDogcmV0dXJuRmFsc2UsXG4gIGlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZVxufTtcblxudmFyIGV2ZW50UmVnZXggPSAvXihbXi5dKykoXFwuKD86W14uXSspKT8kLzsgLy8gcmVnZXggZm9yIG1hdGNoaW5nIGV2ZW50IHN0cmluZ3MgKGUuZy4gXCJjbGljay5uYW1lc3BhY2VcIilcblxudmFyIHVuaXZlcnNhbE5hbWVzcGFjZSA9ICcuKic7IC8vIG1hdGNoZXMgYXMgaWYgbm8gbmFtZXNwYWNlIHNwZWNpZmllZCBhbmQgcHJldmVudHMgdXNlcnMgZnJvbSB1bmJpbmRpbmcgYWNjaWRlbnRhbGx5XG5cbnZhciBkZWZhdWx0cyQ4ID0ge1xuICBxdWFsaWZpZXJDb21wYXJlOiBmdW5jdGlvbiBxdWFsaWZpZXJDb21wYXJlKHExLCBxMikge1xuICAgIHJldHVybiBxMSA9PT0gcTI7XG4gIH0sXG4gIGV2ZW50TWF0Y2hlczogZnVuY3Rpb24gZXZlbnRNYXRjaGVzKClcbiAgLypjb250ZXh0LCBsaXN0ZW5lciwgZXZlbnRPYmoqL1xuICB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGFkZEV2ZW50RmllbGRzOiBmdW5jdGlvbiBhZGRFdmVudEZpZWxkcygpXG4gIC8qY29udGV4dCwgZXZ0Ki9cbiAge30sXG4gIGNhbGxiYWNrQ29udGV4dDogZnVuY3Rpb24gY2FsbGJhY2tDb250ZXh0KGNvbnRleHRcbiAgLyosIGxpc3RlbmVyLCBldmVudE9iaiovXG4gICkge1xuICAgIHJldHVybiBjb250ZXh0O1xuICB9LFxuICBiZWZvcmVFbWl0OiBmdW5jdGlvbiBiZWZvcmVFbWl0KClcbiAgLyogY29udGV4dCwgbGlzdGVuZXIsIGV2ZW50T2JqICovXG4gIHt9LFxuICBhZnRlckVtaXQ6IGZ1bmN0aW9uIGFmdGVyRW1pdCgpXG4gIC8qIGNvbnRleHQsIGxpc3RlbmVyLCBldmVudE9iaiAqL1xuICB7fSxcbiAgYnViYmxlOiBmdW5jdGlvbiBidWJibGUoKVxuICAvKmNvbnRleHQqL1xuICB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuICBwYXJlbnQ6IGZ1bmN0aW9uIHBhcmVudCgpXG4gIC8qY29udGV4dCovXG4gIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcbiAgY29udGV4dDogbnVsbFxufTtcbnZhciBkZWZhdWx0c0tleXMgPSBPYmplY3Qua2V5cyhkZWZhdWx0cyQ4KTtcbnZhciBlbXB0eU9wdHMgPSB7fTtcblxuZnVuY3Rpb24gRW1pdHRlcigpIHtcbiAgdmFyIG9wdHMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGVtcHR5T3B0cztcbiAgdmFyIGNvbnRleHQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDtcblxuICAvLyBtaWNyby1vcHRpbWlzYXRpb24gdnMgT2JqZWN0LmFzc2lnbigpIC0tIHJlZHVjZXMgRWxlbWVudCBpbnN0YW50aWF0aW9uIHRpbWVcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZWZhdWx0c0tleXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIga2V5ID0gZGVmYXVsdHNLZXlzW2ldO1xuICAgIHRoaXNba2V5XSA9IG9wdHNba2V5XSB8fCBkZWZhdWx0cyQ4W2tleV07XG4gIH1cblxuICB0aGlzLmNvbnRleHQgPSBjb250ZXh0IHx8IHRoaXMuY29udGV4dDtcbiAgdGhpcy5saXN0ZW5lcnMgPSBbXTtcbiAgdGhpcy5lbWl0dGluZyA9IDA7XG59XG5cbnZhciBwID0gRW1pdHRlci5wcm90b3R5cGU7XG5cbnZhciBmb3JFYWNoRXZlbnQgPSBmdW5jdGlvbiBmb3JFYWNoRXZlbnQoc2VsZiwgaGFuZGxlciwgZXZlbnRzLCBxdWFsaWZpZXIsIGNhbGxiYWNrLCBjb25mLCBjb25mT3ZlcnJpZGVzKSB7XG4gIGlmIChmbihxdWFsaWZpZXIpKSB7XG4gICAgY2FsbGJhY2sgPSBxdWFsaWZpZXI7XG4gICAgcXVhbGlmaWVyID0gbnVsbDtcbiAgfVxuXG4gIGlmIChjb25mT3ZlcnJpZGVzKSB7XG4gICAgaWYgKGNvbmYgPT0gbnVsbCkge1xuICAgICAgY29uZiA9IGNvbmZPdmVycmlkZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbmYgPSBleHRlbmQoe30sIGNvbmYsIGNvbmZPdmVycmlkZXMpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBldmVudExpc3QgPSBhcnJheShldmVudHMpID8gZXZlbnRzIDogZXZlbnRzLnNwbGl0KC9cXHMrLyk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBldmVudExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZXZ0ID0gZXZlbnRMaXN0W2ldO1xuXG4gICAgaWYgKGVtcHR5U3RyaW5nKGV2dCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBtYXRjaCA9IGV2dC5tYXRjaChldmVudFJlZ2V4KTsgLy8gdHlwZVsubmFtZXNwYWNlXVxuXG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICB2YXIgdHlwZSA9IG1hdGNoWzFdO1xuICAgICAgdmFyIG5hbWVzcGFjZSA9IG1hdGNoWzJdID8gbWF0Y2hbMl0gOiBudWxsO1xuICAgICAgdmFyIHJldCA9IGhhbmRsZXIoc2VsZiwgZXZ0LCB0eXBlLCBuYW1lc3BhY2UsIHF1YWxpZmllciwgY2FsbGJhY2ssIGNvbmYpO1xuXG4gICAgICBpZiAocmV0ID09PSBmYWxzZSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH0gLy8gYWxsb3cgZXhpdGluZyBlYXJseVxuXG4gICAgfVxuICB9XG59O1xuXG52YXIgbWFrZUV2ZW50T2JqID0gZnVuY3Rpb24gbWFrZUV2ZW50T2JqKHNlbGYsIG9iaikge1xuICBzZWxmLmFkZEV2ZW50RmllbGRzKHNlbGYuY29udGV4dCwgb2JqKTtcbiAgcmV0dXJuIG5ldyBFdmVudChvYmoudHlwZSwgb2JqKTtcbn07XG5cbnZhciBmb3JFYWNoRXZlbnRPYmogPSBmdW5jdGlvbiBmb3JFYWNoRXZlbnRPYmooc2VsZiwgaGFuZGxlciwgZXZlbnRzKSB7XG4gIGlmIChldmVudChldmVudHMpKSB7XG4gICAgaGFuZGxlcihzZWxmLCBldmVudHMpO1xuICAgIHJldHVybjtcbiAgfSBlbHNlIGlmIChwbGFpbk9iamVjdChldmVudHMpKSB7XG4gICAgaGFuZGxlcihzZWxmLCBtYWtlRXZlbnRPYmooc2VsZiwgZXZlbnRzKSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGV2ZW50TGlzdCA9IGFycmF5KGV2ZW50cykgPyBldmVudHMgOiBldmVudHMuc3BsaXQoL1xccysvKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGV2ZW50TGlzdC5sZW5ndGg7IGkrKykge1xuICAgIHZhciBldnQgPSBldmVudExpc3RbaV07XG5cbiAgICBpZiAoZW1wdHlTdHJpbmcoZXZ0KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgdmFyIG1hdGNoID0gZXZ0Lm1hdGNoKGV2ZW50UmVnZXgpOyAvLyB0eXBlWy5uYW1lc3BhY2VdXG5cbiAgICBpZiAobWF0Y2gpIHtcbiAgICAgIHZhciB0eXBlID0gbWF0Y2hbMV07XG4gICAgICB2YXIgbmFtZXNwYWNlID0gbWF0Y2hbMl0gPyBtYXRjaFsyXSA6IG51bGw7XG4gICAgICB2YXIgZXZlbnRPYmogPSBtYWtlRXZlbnRPYmooc2VsZiwge1xuICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZSxcbiAgICAgICAgdGFyZ2V0OiBzZWxmLmNvbnRleHRcbiAgICAgIH0pO1xuICAgICAgaGFuZGxlcihzZWxmLCBldmVudE9iaik7XG4gICAgfVxuICB9XG59O1xuXG5wLm9uID0gcC5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudHMsIHF1YWxpZmllciwgY2FsbGJhY2ssIGNvbmYsIGNvbmZPdmVycmlkZXMpIHtcbiAgZm9yRWFjaEV2ZW50KHRoaXMsIGZ1bmN0aW9uIChzZWxmLCBldmVudCwgdHlwZSwgbmFtZXNwYWNlLCBxdWFsaWZpZXIsIGNhbGxiYWNrLCBjb25mKSB7XG4gICAgaWYgKGZuKGNhbGxiYWNrKSkge1xuICAgICAgc2VsZi5saXN0ZW5lcnMucHVzaCh7XG4gICAgICAgIGV2ZW50OiBldmVudCxcbiAgICAgICAgLy8gZnVsbCBldmVudCBzdHJpbmdcbiAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrLFxuICAgICAgICAvLyBjYWxsYmFjayB0byBydW5cbiAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgLy8gdGhlIGV2ZW50IHR5cGUgKGUuZy4gJ2NsaWNrJylcbiAgICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UsXG4gICAgICAgIC8vIHRoZSBldmVudCBuYW1lc3BhY2UgKGUuZy4gXCIuZm9vXCIpXG4gICAgICAgIHF1YWxpZmllcjogcXVhbGlmaWVyLFxuICAgICAgICAvLyBhIHJlc3RyaWN0aW9uIG9uIHdoZXRoZXIgdG8gbWF0Y2ggdGhpcyBlbWl0dGVyXG4gICAgICAgIGNvbmY6IGNvbmYgLy8gYWRkaXRpb25hbCBjb25maWd1cmF0aW9uXG5cbiAgICAgIH0pO1xuICAgIH1cbiAgfSwgZXZlbnRzLCBxdWFsaWZpZXIsIGNhbGxiYWNrLCBjb25mLCBjb25mT3ZlcnJpZGVzKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wLm9uZSA9IGZ1bmN0aW9uIChldmVudHMsIHF1YWxpZmllciwgY2FsbGJhY2ssIGNvbmYpIHtcbiAgcmV0dXJuIHRoaXMub24oZXZlbnRzLCBxdWFsaWZpZXIsIGNhbGxiYWNrLCBjb25mLCB7XG4gICAgb25lOiB0cnVlXG4gIH0pO1xufTtcblxucC5yZW1vdmVMaXN0ZW5lciA9IHAub2ZmID0gZnVuY3Rpb24gKGV2ZW50cywgcXVhbGlmaWVyLCBjYWxsYmFjaywgY29uZikge1xuICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gIGlmICh0aGlzLmVtaXR0aW5nICE9PSAwKSB7XG4gICAgdGhpcy5saXN0ZW5lcnMgPSBjb3B5QXJyYXkodGhpcy5saXN0ZW5lcnMpO1xuICB9XG5cbiAgdmFyIGxpc3RlbmVycyA9IHRoaXMubGlzdGVuZXJzO1xuXG4gIHZhciBfbG9vcCA9IGZ1bmN0aW9uIF9sb29wKGkpIHtcbiAgICB2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG4gICAgZm9yRWFjaEV2ZW50KF90aGlzLCBmdW5jdGlvbiAoc2VsZiwgZXZlbnQsIHR5cGUsIG5hbWVzcGFjZSwgcXVhbGlmaWVyLCBjYWxsYmFja1xuICAgIC8qLCBjb25mKi9cbiAgICApIHtcbiAgICAgIGlmICgobGlzdGVuZXIudHlwZSA9PT0gdHlwZSB8fCBldmVudHMgPT09ICcqJykgJiYgKCFuYW1lc3BhY2UgJiYgbGlzdGVuZXIubmFtZXNwYWNlICE9PSAnLionIHx8IGxpc3RlbmVyLm5hbWVzcGFjZSA9PT0gbmFtZXNwYWNlKSAmJiAoIXF1YWxpZmllciB8fCBzZWxmLnF1YWxpZmllckNvbXBhcmUobGlzdGVuZXIucXVhbGlmaWVyLCBxdWFsaWZpZXIpKSAmJiAoIWNhbGxiYWNrIHx8IGxpc3RlbmVyLmNhbGxiYWNrID09PSBjYWxsYmFjaykpIHtcbiAgICAgICAgbGlzdGVuZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sIGV2ZW50cywgcXVhbGlmaWVyLCBjYWxsYmFjaywgY29uZik7XG4gIH07XG5cbiAgZm9yICh2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIF9sb29wKGkpO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wLnJlbW92ZUFsbExpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMucmVtb3ZlTGlzdGVuZXIoJyonKTtcbn07XG5cbnAuZW1pdCA9IHAudHJpZ2dlciA9IGZ1bmN0aW9uIChldmVudHMsIGV4dHJhUGFyYW1zLCBtYW51YWxDYWxsYmFjaykge1xuICB2YXIgbGlzdGVuZXJzID0gdGhpcy5saXN0ZW5lcnM7XG4gIHZhciBudW1MaXN0ZW5lcnNCZWZvcmVFbWl0ID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgdGhpcy5lbWl0dGluZysrO1xuXG4gIGlmICghYXJyYXkoZXh0cmFQYXJhbXMpKSB7XG4gICAgZXh0cmFQYXJhbXMgPSBbZXh0cmFQYXJhbXNdO1xuICB9XG5cbiAgZm9yRWFjaEV2ZW50T2JqKHRoaXMsIGZ1bmN0aW9uIChzZWxmLCBldmVudE9iaikge1xuICAgIGlmIChtYW51YWxDYWxsYmFjayAhPSBudWxsKSB7XG4gICAgICBsaXN0ZW5lcnMgPSBbe1xuICAgICAgICBldmVudDogZXZlbnRPYmouZXZlbnQsXG4gICAgICAgIHR5cGU6IGV2ZW50T2JqLnR5cGUsXG4gICAgICAgIG5hbWVzcGFjZTogZXZlbnRPYmoubmFtZXNwYWNlLFxuICAgICAgICBjYWxsYmFjazogbWFudWFsQ2FsbGJhY2tcbiAgICAgIH1dO1xuICAgICAgbnVtTGlzdGVuZXJzQmVmb3JlRW1pdCA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgfVxuXG4gICAgdmFyIF9sb29wMiA9IGZ1bmN0aW9uIF9sb29wMihpKSB7XG4gICAgICB2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgIGlmIChsaXN0ZW5lci50eXBlID09PSBldmVudE9iai50eXBlICYmICghbGlzdGVuZXIubmFtZXNwYWNlIHx8IGxpc3RlbmVyLm5hbWVzcGFjZSA9PT0gZXZlbnRPYmoubmFtZXNwYWNlIHx8IGxpc3RlbmVyLm5hbWVzcGFjZSA9PT0gdW5pdmVyc2FsTmFtZXNwYWNlKSAmJiBzZWxmLmV2ZW50TWF0Y2hlcyhzZWxmLmNvbnRleHQsIGxpc3RlbmVyLCBldmVudE9iaikpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbZXZlbnRPYmpdO1xuXG4gICAgICAgIGlmIChleHRyYVBhcmFtcyAhPSBudWxsKSB7XG4gICAgICAgICAgcHVzaChhcmdzLCBleHRyYVBhcmFtcyk7XG4gICAgICAgIH1cblxuICAgICAgICBzZWxmLmJlZm9yZUVtaXQoc2VsZi5jb250ZXh0LCBsaXN0ZW5lciwgZXZlbnRPYmopO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lci5jb25mICYmIGxpc3RlbmVyLmNvbmYub25lKSB7XG4gICAgICAgICAgc2VsZi5saXN0ZW5lcnMgPSBzZWxmLmxpc3RlbmVycy5maWx0ZXIoZnVuY3Rpb24gKGwpIHtcbiAgICAgICAgICAgIHJldHVybiBsICE9PSBsaXN0ZW5lcjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjb250ZXh0ID0gc2VsZi5jYWxsYmFja0NvbnRleHQoc2VsZi5jb250ZXh0LCBsaXN0ZW5lciwgZXZlbnRPYmopO1xuICAgICAgICB2YXIgcmV0ID0gbGlzdGVuZXIuY2FsbGJhY2suYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgIHNlbGYuYWZ0ZXJFbWl0KHNlbGYuY29udGV4dCwgbGlzdGVuZXIsIGV2ZW50T2JqKTtcblxuICAgICAgICBpZiAocmV0ID09PSBmYWxzZSkge1xuICAgICAgICAgIGV2ZW50T2JqLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgIGV2ZW50T2JqLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gaWYgbGlzdGVuZXIgbWF0Y2hlc1xuXG4gICAgfTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtTGlzdGVuZXJzQmVmb3JlRW1pdDsgaSsrKSB7XG4gICAgICBfbG9vcDIoaSk7XG4gICAgfSAvLyBmb3IgbGlzdGVuZXJcblxuXG4gICAgaWYgKHNlbGYuYnViYmxlKHNlbGYuY29udGV4dCkgJiYgIWV2ZW50T2JqLmlzUHJvcGFnYXRpb25TdG9wcGVkKCkpIHtcbiAgICAgIHNlbGYucGFyZW50KHNlbGYuY29udGV4dCkuZW1pdChldmVudE9iaiwgZXh0cmFQYXJhbXMpO1xuICAgIH1cbiAgfSwgZXZlbnRzKTtcbiAgdGhpcy5lbWl0dGluZy0tO1xuICByZXR1cm4gdGhpcztcbn07XG5cbnZhciBlbWl0dGVyT3B0aW9ucyA9IHtcbiAgcXVhbGlmaWVyQ29tcGFyZTogZnVuY3Rpb24gcXVhbGlmaWVyQ29tcGFyZShzZWxlY3RvcjEsIHNlbGVjdG9yMikge1xuICAgIGlmIChzZWxlY3RvcjEgPT0gbnVsbCB8fCBzZWxlY3RvcjIgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHNlbGVjdG9yMSA9PSBudWxsICYmIHNlbGVjdG9yMiA9PSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc2VsZWN0b3IxLnNhbWVUZXh0KHNlbGVjdG9yMik7XG4gICAgfVxuICB9LFxuICBldmVudE1hdGNoZXM6IGZ1bmN0aW9uIGV2ZW50TWF0Y2hlcyhlbGUsIGxpc3RlbmVyLCBldmVudE9iaikge1xuICAgIHZhciBzZWxlY3RvciA9IGxpc3RlbmVyLnF1YWxpZmllcjtcblxuICAgIGlmIChzZWxlY3RvciAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gZWxlICE9PSBldmVudE9iai50YXJnZXQgJiYgZWxlbWVudChldmVudE9iai50YXJnZXQpICYmIHNlbGVjdG9yLm1hdGNoZXMoZXZlbnRPYmoudGFyZ2V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgYWRkRXZlbnRGaWVsZHM6IGZ1bmN0aW9uIGFkZEV2ZW50RmllbGRzKGVsZSwgZXZ0KSB7XG4gICAgZXZ0LmN5ID0gZWxlLmN5KCk7XG4gICAgZXZ0LnRhcmdldCA9IGVsZTtcbiAgfSxcbiAgY2FsbGJhY2tDb250ZXh0OiBmdW5jdGlvbiBjYWxsYmFja0NvbnRleHQoZWxlLCBsaXN0ZW5lciwgZXZlbnRPYmopIHtcbiAgICByZXR1cm4gbGlzdGVuZXIucXVhbGlmaWVyICE9IG51bGwgPyBldmVudE9iai50YXJnZXQgOiBlbGU7XG4gIH0sXG4gIGJlZm9yZUVtaXQ6IGZ1bmN0aW9uIGJlZm9yZUVtaXQoY29udGV4dCwgbGlzdGVuZXJcbiAgLyosIGV2ZW50T2JqKi9cbiAgKSB7XG4gICAgaWYgKGxpc3RlbmVyLmNvbmYgJiYgbGlzdGVuZXIuY29uZi5vbmNlKSB7XG4gICAgICBsaXN0ZW5lci5jb25mLm9uY2VDb2xsZWN0aW9uLnJlbW92ZUxpc3RlbmVyKGxpc3RlbmVyLmV2ZW50LCBsaXN0ZW5lci5xdWFsaWZpZXIsIGxpc3RlbmVyLmNhbGxiYWNrKTtcbiAgICB9XG4gIH0sXG4gIGJ1YmJsZTogZnVuY3Rpb24gYnViYmxlKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICBwYXJlbnQ6IGZ1bmN0aW9uIHBhcmVudChlbGUpIHtcbiAgICByZXR1cm4gZWxlLmlzQ2hpbGQoKSA/IGVsZS5wYXJlbnQoKSA6IGVsZS5jeSgpO1xuICB9XG59O1xuXG52YXIgYXJnU2VsZWN0b3IgPSBmdW5jdGlvbiBhcmdTZWxlY3RvcihhcmcpIHtcbiAgaWYgKHN0cmluZyhhcmcpKSB7XG4gICAgcmV0dXJuIG5ldyBTZWxlY3RvcihhcmcpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBhcmc7XG4gIH1cbn07XG5cbnZhciBlbGVzZm4kbSA9IHtcbiAgY3JlYXRlRW1pdHRlcjogZnVuY3Rpb24gY3JlYXRlRW1pdHRlcigpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBlbGUgPSB0aGlzW2ldO1xuICAgICAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuXG4gICAgICBpZiAoIV9wLmVtaXR0ZXIpIHtcbiAgICAgICAgX3AuZW1pdHRlciA9IG5ldyBFbWl0dGVyKGVtaXR0ZXJPcHRpb25zLCBlbGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBlbWl0dGVyOiBmdW5jdGlvbiBlbWl0dGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9wcml2YXRlLmVtaXR0ZXI7XG4gIH0sXG4gIG9uOiBmdW5jdGlvbiBvbihldmVudHMsIHNlbGVjdG9yLCBjYWxsYmFjaykge1xuICAgIHZhciBhcmdTZWwgPSBhcmdTZWxlY3RvcihzZWxlY3Rvcik7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBlbGUgPSB0aGlzW2ldO1xuICAgICAgZWxlLmVtaXR0ZXIoKS5vbihldmVudHMsIGFyZ1NlbCwgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICByZW1vdmVMaXN0ZW5lcjogZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZlbnRzLCBzZWxlY3RvciwgY2FsbGJhY2spIHtcbiAgICB2YXIgYXJnU2VsID0gYXJnU2VsZWN0b3Ioc2VsZWN0b3IpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICAgIGVsZS5lbWl0dGVyKCkucmVtb3ZlTGlzdGVuZXIoZXZlbnRzLCBhcmdTZWwsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcmVtb3ZlQWxsTGlzdGVuZXJzOiBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnMoKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICAgIGVsZS5lbWl0dGVyKCkucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIG9uZTogZnVuY3Rpb24gb25lKGV2ZW50cywgc2VsZWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGFyZ1NlbCA9IGFyZ1NlbGVjdG9yKHNlbGVjdG9yKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGVsZSA9IHRoaXNbaV07XG4gICAgICBlbGUuZW1pdHRlcigpLm9uZShldmVudHMsIGFyZ1NlbCwgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBvbmNlOiBmdW5jdGlvbiBvbmNlKGV2ZW50cywgc2VsZWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGFyZ1NlbCA9IGFyZ1NlbGVjdG9yKHNlbGVjdG9yKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGVsZSA9IHRoaXNbaV07XG4gICAgICBlbGUuZW1pdHRlcigpLm9uKGV2ZW50cywgYXJnU2VsLCBjYWxsYmFjaywge1xuICAgICAgICBvbmNlOiB0cnVlLFxuICAgICAgICBvbmNlQ29sbGVjdGlvbjogdGhpc1xuICAgICAgfSk7XG4gICAgfVxuICB9LFxuICBlbWl0OiBmdW5jdGlvbiBlbWl0KGV2ZW50cywgZXh0cmFQYXJhbXMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBlbGUgPSB0aGlzW2ldO1xuICAgICAgZWxlLmVtaXR0ZXIoKS5lbWl0KGV2ZW50cywgZXh0cmFQYXJhbXMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBlbWl0QW5kTm90aWZ5OiBmdW5jdGlvbiBlbWl0QW5kTm90aWZ5KGV2ZW50LCBleHRyYVBhcmFtcykge1xuICAgIC8vIGZvciBpbnRlcm5hbCB1c2Ugb25seVxuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gZW1wdHkgY29sbGVjdGlvbnMgZG9uJ3QgbmVlZCB0byBub3RpZnkgYW55dGhpbmdcbiAgICAvLyBub3RpZnkgcmVuZGVyZXJcblxuXG4gICAgdGhpcy5jeSgpLm5vdGlmeShldmVudCwgdGhpcyk7XG4gICAgdGhpcy5lbWl0KGV2ZW50LCBleHRyYVBhcmFtcyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn07XG5kZWZpbmUkMy5ldmVudEFsaWFzZXNPbihlbGVzZm4kbSk7XG5cbnZhciBlbGVzZm4kbiA9IHtcbiAgbm9kZXM6IGZ1bmN0aW9uIG5vZGVzKHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgIHJldHVybiBlbGUuaXNOb2RlKCk7XG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSxcbiAgZWRnZXM6IGZ1bmN0aW9uIGVkZ2VzKHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgIHJldHVybiBlbGUuaXNFZGdlKCk7XG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSxcbiAgLy8gaW50ZXJuYWwgaGVscGVyIHRvIGdldCBub2RlcyBhbmQgZWRnZXMgYXMgc2VwYXJhdGUgY29sbGVjdGlvbnMgd2l0aCBzaW5nbGUgaXRlcmF0aW9uIG92ZXIgZWxlbWVudHNcbiAgYnlHcm91cDogZnVuY3Rpb24gYnlHcm91cCgpIHtcbiAgICB2YXIgbm9kZXMgPSB0aGlzLnNwYXduKCk7XG4gICAgdmFyIGVkZ2VzID0gdGhpcy5zcGF3bigpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlID0gdGhpc1tpXTtcblxuICAgICAgaWYgKGVsZS5pc05vZGUoKSkge1xuICAgICAgICBub2Rlcy5tZXJnZShlbGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWRnZXMubWVyZ2UoZWxlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbm9kZXM6IG5vZGVzLFxuICAgICAgZWRnZXM6IGVkZ2VzXG4gICAgfTtcbiAgfSxcbiAgZmlsdGVyOiBmdW5jdGlvbiBmaWx0ZXIoX2ZpbHRlciwgdGhpc0FyZykge1xuICAgIGlmIChfZmlsdGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIGNoZWNrIHRoaXMgZmlyc3QgYi9jIGl0J3MgdGhlIG1vc3QgY29tbW9uL3BlcmZvcm1hbnQgY2FzZVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSBlbHNlIGlmIChzdHJpbmcoX2ZpbHRlcikgfHwgZWxlbWVudE9yQ29sbGVjdGlvbihfZmlsdGVyKSkge1xuICAgICAgcmV0dXJuIG5ldyBTZWxlY3RvcihfZmlsdGVyKS5maWx0ZXIodGhpcyk7XG4gICAgfSBlbHNlIGlmIChmbihfZmlsdGVyKSkge1xuICAgICAgdmFyIGZpbHRlckVsZXMgPSB0aGlzLnNwYXduKCk7XG4gICAgICB2YXIgZWxlcyA9IHRoaXM7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICAgICAgdmFyIGluY2x1ZGUgPSB0aGlzQXJnID8gX2ZpbHRlci5hcHBseSh0aGlzQXJnLCBbZWxlLCBpLCBlbGVzXSkgOiBfZmlsdGVyKGVsZSwgaSwgZWxlcyk7XG5cbiAgICAgICAgaWYgKGluY2x1ZGUpIHtcbiAgICAgICAgICBmaWx0ZXJFbGVzLm1lcmdlKGVsZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZpbHRlckVsZXM7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24oKTsgLy8gaWYgbm90IGhhbmRsZWQgYnkgYWJvdmUsIGdpdmUgJ2VtIGFuIGVtcHR5IGNvbGxlY3Rpb25cbiAgfSxcbiAgbm90OiBmdW5jdGlvbiBub3QodG9SZW1vdmUpIHtcbiAgICBpZiAoIXRvUmVtb3ZlKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHN0cmluZyh0b1JlbW92ZSkpIHtcbiAgICAgICAgdG9SZW1vdmUgPSB0aGlzLmZpbHRlcih0b1JlbW92ZSk7XG4gICAgICB9XG5cbiAgICAgIHZhciBlbGVtZW50cyA9IFtdO1xuICAgICAgdmFyIHJNYXAgPSB0b1JlbW92ZS5fcHJpdmF0ZS5tYXA7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXNbaV07XG4gICAgICAgIHZhciByZW1vdmUgPSByTWFwLmhhcyhlbGVtZW50LmlkKCkpO1xuXG4gICAgICAgIGlmICghcmVtb3ZlKSB7XG4gICAgICAgICAgZWxlbWVudHMucHVzaChlbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5zcGF3bihlbGVtZW50cyk7XG4gICAgfVxuICB9LFxuICBhYnNvbHV0ZUNvbXBsZW1lbnQ6IGZ1bmN0aW9uIGFic29sdXRlQ29tcGxlbWVudCgpIHtcbiAgICB2YXIgY3kgPSB0aGlzLmN5KCk7XG4gICAgcmV0dXJuIGN5Lm11dGFibGVFbGVtZW50cygpLm5vdCh0aGlzKTtcbiAgfSxcbiAgaW50ZXJzZWN0OiBmdW5jdGlvbiBpbnRlcnNlY3Qob3RoZXIpIHtcbiAgICAvLyBpZiBhIHNlbGVjdG9yIGlzIHNwZWNpZmllZCwgdGhlbiBmaWx0ZXIgYnkgaXQgaW5zdGVhZFxuICAgIGlmIChzdHJpbmcob3RoZXIpKSB7XG4gICAgICB2YXIgc2VsZWN0b3IgPSBvdGhlcjtcbiAgICAgIHJldHVybiB0aGlzLmZpbHRlcihzZWxlY3Rvcik7XG4gICAgfVxuXG4gICAgdmFyIGVsZW1lbnRzID0gW107XG4gICAgdmFyIGNvbDEgPSB0aGlzO1xuICAgIHZhciBjb2wyID0gb3RoZXI7XG4gICAgdmFyIGNvbDFTbWFsbGVyID0gdGhpcy5sZW5ndGggPCBvdGhlci5sZW5ndGg7XG4gICAgdmFyIG1hcDIgPSBjb2wxU21hbGxlciA/IGNvbDIuX3ByaXZhdGUubWFwIDogY29sMS5fcHJpdmF0ZS5tYXA7XG4gICAgdmFyIGNvbCA9IGNvbDFTbWFsbGVyID8gY29sMSA6IGNvbDI7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbC5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGlkID0gY29sW2ldLl9wcml2YXRlLmRhdGEuaWQ7XG4gICAgICB2YXIgZW50cnkgPSBtYXAyLmdldChpZCk7XG5cbiAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICBlbGVtZW50cy5wdXNoKGVudHJ5LmVsZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24oZWxlbWVudHMpO1xuICB9LFxuICB4b3I6IGZ1bmN0aW9uIHhvcihvdGhlcikge1xuICAgIHZhciBjeSA9IHRoaXMuX3ByaXZhdGUuY3k7XG5cbiAgICBpZiAoc3RyaW5nKG90aGVyKSkge1xuICAgICAgb3RoZXIgPSBjeS4kKG90aGVyKTtcbiAgICB9XG5cbiAgICB2YXIgZWxlbWVudHMgPSBbXTtcbiAgICB2YXIgY29sMSA9IHRoaXM7XG4gICAgdmFyIGNvbDIgPSBvdGhlcjtcblxuICAgIHZhciBhZGQgPSBmdW5jdGlvbiBhZGQoY29sLCBvdGhlcikge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2wubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGVsZSA9IGNvbFtpXTtcbiAgICAgICAgdmFyIGlkID0gZWxlLl9wcml2YXRlLmRhdGEuaWQ7XG4gICAgICAgIHZhciBpbk90aGVyID0gb3RoZXIuaGFzRWxlbWVudFdpdGhJZChpZCk7XG5cbiAgICAgICAgaWYgKCFpbk90aGVyKSB7XG4gICAgICAgICAgZWxlbWVudHMucHVzaChlbGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIGFkZChjb2wxLCBjb2wyKTtcbiAgICBhZGQoY29sMiwgY29sMSk7XG4gICAgcmV0dXJuIHRoaXMuc3Bhd24oZWxlbWVudHMpO1xuICB9LFxuICBkaWZmOiBmdW5jdGlvbiBkaWZmKG90aGVyKSB7XG4gICAgdmFyIGN5ID0gdGhpcy5fcHJpdmF0ZS5jeTtcblxuICAgIGlmIChzdHJpbmcob3RoZXIpKSB7XG4gICAgICBvdGhlciA9IGN5LiQob3RoZXIpO1xuICAgIH1cblxuICAgIHZhciBsZWZ0ID0gW107XG4gICAgdmFyIHJpZ2h0ID0gW107XG4gICAgdmFyIGJvdGggPSBbXTtcbiAgICB2YXIgY29sMSA9IHRoaXM7XG4gICAgdmFyIGNvbDIgPSBvdGhlcjtcblxuICAgIHZhciBhZGQgPSBmdW5jdGlvbiBhZGQoY29sLCBvdGhlciwgcmV0RWxlcykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2wubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGVsZSA9IGNvbFtpXTtcbiAgICAgICAgdmFyIGlkID0gZWxlLl9wcml2YXRlLmRhdGEuaWQ7XG4gICAgICAgIHZhciBpbk90aGVyID0gb3RoZXIuaGFzRWxlbWVudFdpdGhJZChpZCk7XG5cbiAgICAgICAgaWYgKGluT3RoZXIpIHtcbiAgICAgICAgICBib3RoLnB1c2goZWxlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXRFbGVzLnB1c2goZWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBhZGQoY29sMSwgY29sMiwgbGVmdCk7XG4gICAgYWRkKGNvbDIsIGNvbDEsIHJpZ2h0KTtcbiAgICByZXR1cm4ge1xuICAgICAgbGVmdDogdGhpcy5zcGF3bihsZWZ0LCB7XG4gICAgICAgIHVuaXF1ZTogdHJ1ZVxuICAgICAgfSksXG4gICAgICByaWdodDogdGhpcy5zcGF3bihyaWdodCwge1xuICAgICAgICB1bmlxdWU6IHRydWVcbiAgICAgIH0pLFxuICAgICAgYm90aDogdGhpcy5zcGF3bihib3RoLCB7XG4gICAgICAgIHVuaXF1ZTogdHJ1ZVxuICAgICAgfSlcbiAgICB9O1xuICB9LFxuICBhZGQ6IGZ1bmN0aW9uIGFkZCh0b0FkZCkge1xuICAgIHZhciBjeSA9IHRoaXMuX3ByaXZhdGUuY3k7XG5cbiAgICBpZiAoIXRvQWRkKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBpZiAoc3RyaW5nKHRvQWRkKSkge1xuICAgICAgdmFyIHNlbGVjdG9yID0gdG9BZGQ7XG4gICAgICB0b0FkZCA9IGN5Lm11dGFibGVFbGVtZW50cygpLmZpbHRlcihzZWxlY3Rvcik7XG4gICAgfVxuXG4gICAgdmFyIGVsZW1lbnRzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGVsZW1lbnRzLnB1c2godGhpc1tpXSk7XG4gICAgfVxuXG4gICAgdmFyIG1hcCA9IHRoaXMuX3ByaXZhdGUubWFwO1xuXG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IHRvQWRkLmxlbmd0aDsgX2krKykge1xuICAgICAgdmFyIGFkZCA9ICFtYXAuaGFzKHRvQWRkW19pXS5pZCgpKTtcblxuICAgICAgaWYgKGFkZCkge1xuICAgICAgICBlbGVtZW50cy5wdXNoKHRvQWRkW19pXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24oZWxlbWVudHMpO1xuICB9LFxuICAvLyBpbiBwbGFjZSBtZXJnZSBvbiBjYWxsaW5nIGNvbGxlY3Rpb25cbiAgbWVyZ2U6IGZ1bmN0aW9uIG1lcmdlKHRvQWRkKSB7XG4gICAgdmFyIF9wID0gdGhpcy5fcHJpdmF0ZTtcbiAgICB2YXIgY3kgPSBfcC5jeTtcblxuICAgIGlmICghdG9BZGQpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGlmICh0b0FkZCAmJiBzdHJpbmcodG9BZGQpKSB7XG4gICAgICB2YXIgc2VsZWN0b3IgPSB0b0FkZDtcbiAgICAgIHRvQWRkID0gY3kubXV0YWJsZUVsZW1lbnRzKCkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgICB9XG5cbiAgICB2YXIgbWFwID0gX3AubWFwO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b0FkZC5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHRvQWRkRWxlID0gdG9BZGRbaV07XG4gICAgICB2YXIgaWQgPSB0b0FkZEVsZS5fcHJpdmF0ZS5kYXRhLmlkO1xuICAgICAgdmFyIGFkZCA9ICFtYXAuaGFzKGlkKTtcblxuICAgICAgaWYgKGFkZCkge1xuICAgICAgICB2YXIgaW5kZXggPSB0aGlzLmxlbmd0aCsrO1xuICAgICAgICB0aGlzW2luZGV4XSA9IHRvQWRkRWxlO1xuICAgICAgICBtYXAuc2V0KGlkLCB7XG4gICAgICAgICAgZWxlOiB0b0FkZEVsZSxcbiAgICAgICAgICBpbmRleDogaW5kZXhcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyByZXBsYWNlXG4gICAgICAgIHZhciBfaW5kZXggPSBtYXAuZ2V0KGlkKS5pbmRleDtcbiAgICAgICAgdGhpc1tfaW5kZXhdID0gdG9BZGRFbGU7XG4gICAgICAgIG1hcC5zZXQoaWQsIHtcbiAgICAgICAgICBlbGU6IHRvQWRkRWxlLFxuICAgICAgICAgIGluZGV4OiBfaW5kZXhcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gIH0sXG4gIHVubWVyZ2VBdDogZnVuY3Rpb24gdW5tZXJnZUF0KGkpIHtcbiAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICB2YXIgaWQgPSBlbGUuaWQoKTtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuICAgIHZhciBtYXAgPSBfcC5tYXA7IC8vIHJlbW92ZSBlbGVcblxuICAgIHRoaXNbaV0gPSB1bmRlZmluZWQ7XG4gICAgbWFwW1wiZGVsZXRlXCJdKGlkKTtcbiAgICB2YXIgdW5tZXJnZWRMYXN0RWxlID0gaSA9PT0gdGhpcy5sZW5ndGggLSAxOyAvLyByZXBsYWNlIGVtcHR5IHNwb3Qgd2l0aCBsYXN0IGVsZSBpbiBjb2xsZWN0aW9uXG5cbiAgICBpZiAodGhpcy5sZW5ndGggPiAxICYmICF1bm1lcmdlZExhc3RFbGUpIHtcbiAgICAgIHZhciBsYXN0RWxlSSA9IHRoaXMubGVuZ3RoIC0gMTtcbiAgICAgIHZhciBsYXN0RWxlID0gdGhpc1tsYXN0RWxlSV07XG4gICAgICB2YXIgbGFzdEVsZUlkID0gbGFzdEVsZS5fcHJpdmF0ZS5kYXRhLmlkO1xuICAgICAgdGhpc1tsYXN0RWxlSV0gPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzW2ldID0gbGFzdEVsZTtcbiAgICAgIG1hcC5zZXQobGFzdEVsZUlkLCB7XG4gICAgICAgIGVsZTogbGFzdEVsZSxcbiAgICAgICAgaW5kZXg6IGlcbiAgICAgIH0pO1xuICAgIH0gLy8gdGhlIGNvbGxlY3Rpb24gaXMgbm93IDEgZWxlIHNtYWxsZXJcblxuXG4gICAgdGhpcy5sZW5ndGgtLTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgLy8gcmVtb3ZlIHNpbmdsZSBlbGUgaW4gcGxhY2UgaW4gY2FsbGluZyBjb2xsZWN0aW9uXG4gIHVubWVyZ2VPbmU6IGZ1bmN0aW9uIHVubWVyZ2VPbmUoZWxlKSB7XG4gICAgZWxlID0gZWxlWzBdO1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG4gICAgdmFyIGlkID0gZWxlLl9wcml2YXRlLmRhdGEuaWQ7XG4gICAgdmFyIG1hcCA9IF9wLm1hcDtcbiAgICB2YXIgZW50cnkgPSBtYXAuZ2V0KGlkKTtcblxuICAgIGlmICghZW50cnkpIHtcbiAgICAgIHJldHVybiB0aGlzOyAvLyBubyBuZWVkIHRvIHJlbW92ZVxuICAgIH1cblxuICAgIHZhciBpID0gZW50cnkuaW5kZXg7XG4gICAgdGhpcy51bm1lcmdlQXQoaSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIC8vIHJlbW92ZSBlbGVzIGluIHBsYWNlIG9uIGNhbGxpbmcgY29sbGVjdGlvblxuICB1bm1lcmdlOiBmdW5jdGlvbiB1bm1lcmdlKHRvUmVtb3ZlKSB7XG4gICAgdmFyIGN5ID0gdGhpcy5fcHJpdmF0ZS5jeTtcblxuICAgIGlmICghdG9SZW1vdmUpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGlmICh0b1JlbW92ZSAmJiBzdHJpbmcodG9SZW1vdmUpKSB7XG4gICAgICB2YXIgc2VsZWN0b3IgPSB0b1JlbW92ZTtcbiAgICAgIHRvUmVtb3ZlID0gY3kubXV0YWJsZUVsZW1lbnRzKCkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRvUmVtb3ZlLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnVubWVyZ2VPbmUodG9SZW1vdmVbaV0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICB1bm1lcmdlQnk6IGZ1bmN0aW9uIHVubWVyZ2VCeSh0b1JtRm4pIHtcbiAgICBmb3IgKHZhciBpID0gdGhpcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIGVsZSA9IHRoaXNbaV07XG5cbiAgICAgIGlmICh0b1JtRm4oZWxlKSkge1xuICAgICAgICB0aGlzLnVubWVyZ2VBdChpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgbWFwOiBmdW5jdGlvbiBtYXAobWFwRm4sIHRoaXNBcmcpIHtcbiAgICB2YXIgYXJyID0gW107XG4gICAgdmFyIGVsZXMgPSB0aGlzO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICAgIHZhciByZXQgPSB0aGlzQXJnID8gbWFwRm4uYXBwbHkodGhpc0FyZywgW2VsZSwgaSwgZWxlc10pIDogbWFwRm4oZWxlLCBpLCBlbGVzKTtcbiAgICAgIGFyci5wdXNoKHJldCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycjtcbiAgfSxcbiAgcmVkdWNlOiBmdW5jdGlvbiByZWR1Y2UoZm4sIGluaXRpYWxWYWx1ZSkge1xuICAgIHZhciB2YWwgPSBpbml0aWFsVmFsdWU7XG4gICAgdmFyIGVsZXMgPSB0aGlzO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YWwgPSBmbih2YWwsIGVsZXNbaV0sIGksIGVsZXMpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWw7XG4gIH0sXG4gIG1heDogZnVuY3Rpb24gbWF4KHZhbEZuLCB0aGlzQXJnKSB7XG4gICAgdmFyIG1heCA9IC1JbmZpbml0eTtcbiAgICB2YXIgbWF4RWxlO1xuICAgIHZhciBlbGVzID0gdGhpcztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGVsZSA9IGVsZXNbaV07XG4gICAgICB2YXIgdmFsID0gdGhpc0FyZyA/IHZhbEZuLmFwcGx5KHRoaXNBcmcsIFtlbGUsIGksIGVsZXNdKSA6IHZhbEZuKGVsZSwgaSwgZWxlcyk7XG5cbiAgICAgIGlmICh2YWwgPiBtYXgpIHtcbiAgICAgICAgbWF4ID0gdmFsO1xuICAgICAgICBtYXhFbGUgPSBlbGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbHVlOiBtYXgsXG4gICAgICBlbGU6IG1heEVsZVxuICAgIH07XG4gIH0sXG4gIG1pbjogZnVuY3Rpb24gbWluKHZhbEZuLCB0aGlzQXJnKSB7XG4gICAgdmFyIG1pbiA9IEluZmluaXR5O1xuICAgIHZhciBtaW5FbGU7XG4gICAgdmFyIGVsZXMgPSB0aGlzO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICAgIHZhciB2YWwgPSB0aGlzQXJnID8gdmFsRm4uYXBwbHkodGhpc0FyZywgW2VsZSwgaSwgZWxlc10pIDogdmFsRm4oZWxlLCBpLCBlbGVzKTtcblxuICAgICAgaWYgKHZhbCA8IG1pbikge1xuICAgICAgICBtaW4gPSB2YWw7XG4gICAgICAgIG1pbkVsZSA9IGVsZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdmFsdWU6IG1pbixcbiAgICAgIGVsZTogbWluRWxlXG4gICAgfTtcbiAgfVxufTsgLy8gYWxpYXNlc1xuXG52YXIgZm4kNSA9IGVsZXNmbiRuO1xuZm4kNVsndSddID0gZm4kNVsnfCddID0gZm4kNVsnKyddID0gZm4kNS51bmlvbiA9IGZuJDUub3IgPSBmbiQ1LmFkZDtcbmZuJDVbJ1xcXFwnXSA9IGZuJDVbJyEnXSA9IGZuJDVbJy0nXSA9IGZuJDUuZGlmZmVyZW5jZSA9IGZuJDUucmVsYXRpdmVDb21wbGVtZW50ID0gZm4kNS5zdWJ0cmFjdCA9IGZuJDUubm90O1xuZm4kNVsnbiddID0gZm4kNVsnJiddID0gZm4kNVsnLiddID0gZm4kNS5hbmQgPSBmbiQ1LmludGVyc2VjdGlvbiA9IGZuJDUuaW50ZXJzZWN0O1xuZm4kNVsnXiddID0gZm4kNVsnKCspJ10gPSBmbiQ1WycoLSknXSA9IGZuJDUuc3ltbWV0cmljRGlmZmVyZW5jZSA9IGZuJDUuc3ltZGlmZiA9IGZuJDUueG9yO1xuZm4kNS5mbkZpbHRlciA9IGZuJDUuZmlsdGVyRm4gPSBmbiQ1LnN0ZEZpbHRlciA9IGZuJDUuZmlsdGVyO1xuZm4kNS5jb21wbGVtZW50ID0gZm4kNS5hYnNjb21wID0gZm4kNS5hYnNvbHV0ZUNvbXBsZW1lbnQ7XG5cbnZhciBlbGVzZm4kbyA9IHtcbiAgaXNOb2RlOiBmdW5jdGlvbiBpc05vZGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ3JvdXAoKSA9PT0gJ25vZGVzJztcbiAgfSxcbiAgaXNFZGdlOiBmdW5jdGlvbiBpc0VkZ2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ3JvdXAoKSA9PT0gJ2VkZ2VzJztcbiAgfSxcbiAgaXNMb29wOiBmdW5jdGlvbiBpc0xvb3AoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNFZGdlKCkgJiYgdGhpcy5zb3VyY2UoKVswXSA9PT0gdGhpcy50YXJnZXQoKVswXTtcbiAgfSxcbiAgaXNTaW1wbGU6IGZ1bmN0aW9uIGlzU2ltcGxlKCkge1xuICAgIHJldHVybiB0aGlzLmlzRWRnZSgpICYmIHRoaXMuc291cmNlKClbMF0gIT09IHRoaXMudGFyZ2V0KClbMF07XG4gIH0sXG4gIGdyb3VwOiBmdW5jdGlvbiBncm91cCgpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIHJldHVybiBlbGUuX3ByaXZhdGUuZ3JvdXA7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqICBFbGVtZW50cyBhcmUgZHJhd24gaW4gYSBzcGVjaWZpYyBvcmRlciBiYXNlZCBvbiBjb21wb3VuZCBkZXB0aCAobG93IHRvIGhpZ2gpLCB0aGUgZWxlbWVudCB0eXBlIChub2RlcyBhYm92ZSBlZGdlcyksXG4gKiAgYW5kIHotaW5kZXggKGxvdyB0byBoaWdoKS4gIFRoZXNlIHN0eWxlcyBhZmZlY3QgaG93IHRoaXMgYXBwbGllczpcbiAqXG4gKiAgei1jb21wb3VuZC1kZXB0aDogTWF5IGJlIGBib3R0b20gfCBvcnBoYW4gfCBhdXRvIHwgdG9wYC4gIFRoZSBmaXJzdCBkcmF3biBpcyBgYm90dG9tYCwgdGhlbiBgb3JwaGFuYCB3aGljaCBpcyB0aGVcbiAqICAgICAgc2FtZSBkZXB0aCBhcyB0aGUgcm9vdCBvZiB0aGUgY29tcG91bmQgZ3JhcGgsIGZvbGxvd2VkIGJ5IHRoZSBkZWZhdWx0IHZhbHVlIGBhdXRvYCB3aGljaCBkcmF3cyBpbiBvcmRlciBmcm9tXG4gKiAgICAgIHJvb3QgdG8gbGVhdmVzIG9mIHRoZSBjb21wb3VuZCBncmFwaC4gIFRoZSBsYXN0IGRyYXduIGlzIGB0b3BgLlxuICogIHotaW5kZXgtY29tcGFyZTogTWF5IGJlIGBhdXRvIHwgbWFudWFsYC4gIFRoZSBkZWZhdWx0IHZhbHVlIGlzIGBhdXRvYCB3aGljaCBhbHdheXMgZHJhd3MgZWRnZXMgdW5kZXIgbm9kZXMuXG4gKiAgICAgIGBtYW51YWxgIGlnbm9yZXMgdGhpcyBjb252ZW50aW9uIGFuZCBkcmF3cyBiYXNlZCBvbiB0aGUgYHotaW5kZXhgIHZhbHVlIHNldHRpbmcuXG4gKiAgei1pbmRleDogQW4gaW50ZWdlciB2YWx1ZSB0aGF0IGFmZmVjdHMgdGhlIHJlbGF0aXZlIGRyYXcgb3JkZXIgb2YgZWxlbWVudHMuICBJbiBnZW5lcmFsLCBhbiBlbGVtZW50IHdpdGggYSBoaWdoZXJcbiAqICAgICAgYHotaW5kZXhgIHdpbGwgYmUgZHJhd24gb24gdG9wIG9mIGFuIGVsZW1lbnQgd2l0aCBhIGxvd2VyIGB6LWluZGV4YC5cbiAqL1xuXG52YXIgekluZGV4U29ydCA9IGZ1bmN0aW9uIHpJbmRleFNvcnQoYSwgYikge1xuICB2YXIgY3kgPSBhLmN5KCk7XG4gIHZhciBoYXNDb21wb3VuZE5vZGVzID0gY3kuaGFzQ29tcG91bmROb2RlcygpO1xuXG4gIGZ1bmN0aW9uIGdldERlcHRoKGVsZSkge1xuICAgIHZhciBzdHlsZSA9IGVsZS5wc3R5bGUoJ3otY29tcG91bmQtZGVwdGgnKTtcblxuICAgIGlmIChzdHlsZS52YWx1ZSA9PT0gJ2F1dG8nKSB7XG4gICAgICByZXR1cm4gaGFzQ29tcG91bmROb2RlcyA/IGVsZS56RGVwdGgoKSA6IDA7XG4gICAgfSBlbHNlIGlmIChzdHlsZS52YWx1ZSA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIHJldHVybiAtMTtcbiAgICB9IGVsc2UgaWYgKHN0eWxlLnZhbHVlID09PSAndG9wJykge1xuICAgICAgcmV0dXJuIE1BWF9JTlQ7XG4gICAgfSAvLyAnb3JwaGFuJ1xuXG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIHZhciBkZXB0aERpZmYgPSBnZXREZXB0aChhKSAtIGdldERlcHRoKGIpO1xuXG4gIGlmIChkZXB0aERpZmYgIT09IDApIHtcbiAgICByZXR1cm4gZGVwdGhEaWZmO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0RWxlRGVwdGgoZWxlKSB7XG4gICAgdmFyIHN0eWxlID0gZWxlLnBzdHlsZSgnei1pbmRleC1jb21wYXJlJyk7XG5cbiAgICBpZiAoc3R5bGUudmFsdWUgPT09ICdhdXRvJykge1xuICAgICAgcmV0dXJuIGVsZS5pc05vZGUoKSA/IDEgOiAwO1xuICAgIH0gLy8gJ21hbnVhbCdcblxuXG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICB2YXIgZWxlRGlmZiA9IGdldEVsZURlcHRoKGEpIC0gZ2V0RWxlRGVwdGgoYik7XG5cbiAgaWYgKGVsZURpZmYgIT09IDApIHtcbiAgICByZXR1cm4gZWxlRGlmZjtcbiAgfVxuXG4gIHZhciB6RGlmZiA9IGEucHN0eWxlKCd6LWluZGV4JykudmFsdWUgLSBiLnBzdHlsZSgnei1pbmRleCcpLnZhbHVlO1xuXG4gIGlmICh6RGlmZiAhPT0gMCkge1xuICAgIHJldHVybiB6RGlmZjtcbiAgfSAvLyBjb21wYXJlIGluZGljZXMgaW4gdGhlIGNvcmUgKG9yZGVyIGFkZGVkIHRvIGdyYXBoIHcvIGxhc3Qgb24gdG9wKVxuXG5cbiAgcmV0dXJuIGEucG9vbEluZGV4KCkgLSBiLnBvb2xJbmRleCgpO1xufTtcblxudmFyIGVsZXNmbiRwID0ge1xuICBmb3JFYWNoOiBmdW5jdGlvbiBmb3JFYWNoKGZuJDEsIHRoaXNBcmcpIHtcbiAgICBpZiAoZm4oZm4kMSkpIHtcbiAgICAgIHZhciBOID0gdGhpcy5sZW5ndGg7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgTjsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSB0aGlzW2ldO1xuICAgICAgICB2YXIgcmV0ID0gdGhpc0FyZyA/IGZuJDEuYXBwbHkodGhpc0FyZywgW2VsZSwgaSwgdGhpc10pIDogZm4kMShlbGUsIGksIHRoaXMpO1xuXG4gICAgICAgIGlmIChyZXQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gLy8gZXhpdCBlYWNoIGVhcmx5IG9uIHJldHVybiBmYWxzZVxuXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHRvQXJyYXk6IGZ1bmN0aW9uIHRvQXJyYXkoKSB7XG4gICAgdmFyIGFycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGFycmF5LnB1c2godGhpc1tpXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycmF5O1xuICB9LFxuICBzbGljZTogZnVuY3Rpb24gc2xpY2Uoc3RhcnQsIGVuZCkge1xuICAgIHZhciBhcnJheSA9IFtdO1xuICAgIHZhciB0aGlzU2l6ZSA9IHRoaXMubGVuZ3RoO1xuXG4gICAgaWYgKGVuZCA9PSBudWxsKSB7XG4gICAgICBlbmQgPSB0aGlzU2l6ZTtcbiAgICB9XG5cbiAgICBpZiAoc3RhcnQgPT0gbnVsbCkge1xuICAgICAgc3RhcnQgPSAwO1xuICAgIH1cblxuICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgIHN0YXJ0ID0gdGhpc1NpemUgKyBzdGFydDtcbiAgICB9XG5cbiAgICBpZiAoZW5kIDwgMCkge1xuICAgICAgZW5kID0gdGhpc1NpemUgKyBlbmQ7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpID49IDAgJiYgaSA8IGVuZCAmJiBpIDwgdGhpc1NpemU7IGkrKykge1xuICAgICAgYXJyYXkucHVzaCh0aGlzW2ldKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zcGF3bihhcnJheSk7XG4gIH0sXG4gIHNpemU6IGZ1bmN0aW9uIHNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMubGVuZ3RoO1xuICB9LFxuICBlcTogZnVuY3Rpb24gZXEoaSkge1xuICAgIHJldHVybiB0aGlzW2ldIHx8IHRoaXMuc3Bhd24oKTtcbiAgfSxcbiAgZmlyc3Q6IGZ1bmN0aW9uIGZpcnN0KCkge1xuICAgIHJldHVybiB0aGlzWzBdIHx8IHRoaXMuc3Bhd24oKTtcbiAgfSxcbiAgbGFzdDogZnVuY3Rpb24gbGFzdCgpIHtcbiAgICByZXR1cm4gdGhpc1t0aGlzLmxlbmd0aCAtIDFdIHx8IHRoaXMuc3Bhd24oKTtcbiAgfSxcbiAgZW1wdHk6IGZ1bmN0aW9uIGVtcHR5KCkge1xuICAgIHJldHVybiB0aGlzLmxlbmd0aCA9PT0gMDtcbiAgfSxcbiAgbm9uZW1wdHk6IGZ1bmN0aW9uIG5vbmVtcHR5KCkge1xuICAgIHJldHVybiAhdGhpcy5lbXB0eSgpO1xuICB9LFxuICBzb3J0OiBmdW5jdGlvbiBzb3J0KHNvcnRGbikge1xuICAgIGlmICghZm4oc29ydEZuKSkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdmFyIHNvcnRlZCA9IHRoaXMudG9BcnJheSgpLnNvcnQoc29ydEZuKTtcbiAgICByZXR1cm4gdGhpcy5zcGF3bihzb3J0ZWQpO1xuICB9LFxuICBzb3J0QnlaSW5kZXg6IGZ1bmN0aW9uIHNvcnRCeVpJbmRleCgpIHtcbiAgICByZXR1cm4gdGhpcy5zb3J0KHpJbmRleFNvcnQpO1xuICB9LFxuICB6RGVwdGg6IGZ1bmN0aW9uIHpEZXB0aCgpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmICghZWxlKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH0gLy8gbGV0IGN5ID0gZWxlLmN5KCk7XG5cblxuICAgIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgICB2YXIgZ3JvdXAgPSBfcC5ncm91cDtcblxuICAgIGlmIChncm91cCA9PT0gJ25vZGVzJykge1xuICAgICAgdmFyIGRlcHRoID0gX3AuZGF0YS5wYXJlbnQgPyBlbGUucGFyZW50cygpLnNpemUoKSA6IDA7XG5cbiAgICAgIGlmICghZWxlLmlzUGFyZW50KCkpIHtcbiAgICAgICAgcmV0dXJuIE1BWF9JTlQgLSAxOyAvLyBjaGlsZGxlc3Mgbm9kZXMgYWx3YXlzIG9uIHRvcFxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZGVwdGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBzcmMgPSBfcC5zb3VyY2U7XG4gICAgICB2YXIgdGd0ID0gX3AudGFyZ2V0O1xuICAgICAgdmFyIHNyY0RlcHRoID0gc3JjLnpEZXB0aCgpO1xuICAgICAgdmFyIHRndERlcHRoID0gdGd0LnpEZXB0aCgpO1xuICAgICAgcmV0dXJuIE1hdGgubWF4KHNyY0RlcHRoLCB0Z3REZXB0aCwgMCk7IC8vIGRlcHRoIG9mIGRlZXBlc3QgcGFyZW50XG4gICAgfVxuICB9XG59O1xuZWxlc2ZuJHAuZWFjaCA9IGVsZXNmbiRwLmZvckVhY2g7XG5cbnZhciBkZWZpbmVTeW1ib2xJdGVyYXRvciA9IGZ1bmN0aW9uIGRlZmluZVN5bWJvbEl0ZXJhdG9yKCkge1xuICB2YXIgdHlwZW9mVW5kZWYgPSAgXCJ1bmRlZmluZWRcIiA7XG4gIHZhciBpc0l0ZXJhdG9yU3VwcG9ydGVkID0gKHR5cGVvZiBTeW1ib2wgPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihTeW1ib2wpKSAhPSB0eXBlb2ZVbmRlZiAmJiBfdHlwZW9mKFN5bWJvbC5pdGVyYXRvcikgIT0gdHlwZW9mVW5kZWY7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBpZiAoaXNJdGVyYXRvclN1cHBvcnRlZCkge1xuICAgIGVsZXNmbiRwW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4gICAgICB2YXIgZW50cnkgPSB7XG4gICAgICAgIHZhbHVlOiB1bmRlZmluZWQsXG4gICAgICAgIGRvbmU6IGZhbHNlXG4gICAgICB9O1xuICAgICAgdmFyIGkgPSAwO1xuICAgICAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoO1xuICAgICAgcmV0dXJuIF9kZWZpbmVQcm9wZXJ0eSh7XG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uIG5leHQoKSB7XG4gICAgICAgICAgaWYgKGkgPCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGVudHJ5LnZhbHVlID0gX3RoaXNbaSsrXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZW50cnkudmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBlbnRyeS5kb25lID0gdHJ1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZW50cnk7XG4gICAgICAgIH1cbiAgICAgIH0sIFN5bWJvbC5pdGVyYXRvciwgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfVxufTtcblxuZGVmaW5lU3ltYm9sSXRlcmF0b3IoKTtcblxudmFyIGdldExheW91dERpbWVuc2lvbk9wdGlvbnMgPSBkZWZhdWx0cyh7XG4gIG5vZGVEaW1lbnNpb25zSW5jbHVkZUxhYmVsczogZmFsc2Vcbn0pO1xudmFyIGVsZXNmbiRxID0ge1xuICAvLyBDYWxjdWxhdGVzIGFuZCByZXR1cm5zIG5vZGUgZGltZW5zaW9ucyB7IHgsIHkgfSBiYXNlZCBvbiBvcHRpb25zIGdpdmVuXG4gIGxheW91dERpbWVuc2lvbnM6IGZ1bmN0aW9uIGxheW91dERpbWVuc2lvbnMob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBnZXRMYXlvdXREaW1lbnNpb25PcHRpb25zKG9wdGlvbnMpO1xuICAgIHZhciBkaW1zO1xuXG4gICAgaWYgKCF0aGlzLnRha2VzVXBTcGFjZSgpKSB7XG4gICAgICBkaW1zID0ge1xuICAgICAgICB3OiAwLFxuICAgICAgICBoOiAwXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5ub2RlRGltZW5zaW9uc0luY2x1ZGVMYWJlbHMpIHtcbiAgICAgIHZhciBiYkRpbSA9IHRoaXMuYm91bmRpbmdCb3goKTtcbiAgICAgIGRpbXMgPSB7XG4gICAgICAgIHc6IGJiRGltLncsXG4gICAgICAgIGg6IGJiRGltLmhcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpbXMgPSB7XG4gICAgICAgIHc6IHRoaXMub3V0ZXJXaWR0aCgpLFxuICAgICAgICBoOiB0aGlzLm91dGVySGVpZ2h0KClcbiAgICAgIH07XG4gICAgfSAvLyBzYW5pdGlzZSB0aGUgZGltZW5zaW9ucyBmb3IgZXh0ZXJuYWwgbGF5b3V0cyAoYXZvaWQgZGl2aXNpb24gYnkgemVybylcblxuXG4gICAgaWYgKGRpbXMudyA9PT0gMCB8fCBkaW1zLmggPT09IDApIHtcbiAgICAgIGRpbXMudyA9IGRpbXMuaCA9IDE7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRpbXM7XG4gIH0sXG4gIC8vIHVzaW5nIHN0YW5kYXJkIGxheW91dCBvcHRpb25zLCBhcHBseSBwb3NpdGlvbiBmdW5jdGlvbiAody8gb3Igdy9vIGFuaW1hdGlvbilcbiAgbGF5b3V0UG9zaXRpb25zOiBmdW5jdGlvbiBsYXlvdXRQb3NpdGlvbnMobGF5b3V0LCBvcHRpb25zLCBmbikge1xuICAgIHZhciBub2RlcyA9IHRoaXMubm9kZXMoKTtcbiAgICB2YXIgY3kgPSB0aGlzLmN5KCk7XG4gICAgdmFyIGxheW91dEVsZXMgPSBvcHRpb25zLmVsZXM7IC8vIG5vZGVzICYgZWRnZXNcblxuICAgIHZhciBnZXRNZW1vaXplS2V5ID0gZnVuY3Rpb24gZ2V0TWVtb2l6ZUtleShub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5pZCgpO1xuICAgIH07XG5cbiAgICB2YXIgZm5NZW0gPSBtZW1vaXplKGZuLCBnZXRNZW1vaXplS2V5KTsgLy8gbWVtb2l6ZWQgdmVyc2lvbiBvZiBwb3NpdGlvbiBmdW5jdGlvblxuXG4gICAgbGF5b3V0LmVtaXQoe1xuICAgICAgdHlwZTogJ2xheW91dHN0YXJ0JyxcbiAgICAgIGxheW91dDogbGF5b3V0XG4gICAgfSk7XG4gICAgbGF5b3V0LmFuaW1hdGlvbnMgPSBbXTtcblxuICAgIHZhciBjYWxjdWxhdGVTcGFjaW5nID0gZnVuY3Rpb24gY2FsY3VsYXRlU3BhY2luZyhzcGFjaW5nLCBub2Rlc0JiLCBwb3MpIHtcbiAgICAgIHZhciBjZW50ZXIgPSB7XG4gICAgICAgIHg6IG5vZGVzQmIueDEgKyBub2Rlc0JiLncgLyAyLFxuICAgICAgICB5OiBub2Rlc0JiLnkxICsgbm9kZXNCYi5oIC8gMlxuICAgICAgfTtcbiAgICAgIHZhciBzcGFjaW5nVmVjdG9yID0ge1xuICAgICAgICAvLyBzY2FsZSBmcm9tIGNlbnRlciBvZiBib3VuZGluZyBib3ggKG5vdCBuZWNlc3NhcmlseSAwLDApXG4gICAgICAgIHg6IChwb3MueCAtIGNlbnRlci54KSAqIHNwYWNpbmcsXG4gICAgICAgIHk6IChwb3MueSAtIGNlbnRlci55KSAqIHNwYWNpbmdcbiAgICAgIH07XG4gICAgICByZXR1cm4ge1xuICAgICAgICB4OiBjZW50ZXIueCArIHNwYWNpbmdWZWN0b3IueCxcbiAgICAgICAgeTogY2VudGVyLnkgKyBzcGFjaW5nVmVjdG9yLnlcbiAgICAgIH07XG4gICAgfTtcblxuICAgIHZhciB1c2VTcGFjaW5nRmFjdG9yID0gb3B0aW9ucy5zcGFjaW5nRmFjdG9yICYmIG9wdGlvbnMuc3BhY2luZ0ZhY3RvciAhPT0gMTtcblxuICAgIHZhciBzcGFjaW5nQmIgPSBmdW5jdGlvbiBzcGFjaW5nQmIoKSB7XG4gICAgICBpZiAoIXVzZVNwYWNpbmdGYWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIHZhciBiYiA9IG1ha2VCb3VuZGluZ0JveCgpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIHZhciBwb3MgPSBmbk1lbShub2RlLCBpKTtcbiAgICAgICAgZXhwYW5kQm91bmRpbmdCb3hCeVBvaW50KGJiLCBwb3MueCwgcG9zLnkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYmI7XG4gICAgfTtcblxuICAgIHZhciBiYiA9IHNwYWNpbmdCYigpO1xuICAgIHZhciBnZXRGaW5hbFBvcyA9IG1lbW9pemUoZnVuY3Rpb24gKG5vZGUsIGkpIHtcbiAgICAgIHZhciBuZXdQb3MgPSBmbk1lbShub2RlLCBpKTtcblxuICAgICAgaWYgKHVzZVNwYWNpbmdGYWN0b3IpIHtcbiAgICAgICAgdmFyIHNwYWNpbmcgPSBNYXRoLmFicyhvcHRpb25zLnNwYWNpbmdGYWN0b3IpO1xuICAgICAgICBuZXdQb3MgPSBjYWxjdWxhdGVTcGFjaW5nKHNwYWNpbmcsIGJiLCBuZXdQb3MpO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy50cmFuc2Zvcm0gIT0gbnVsbCkge1xuICAgICAgICBuZXdQb3MgPSBvcHRpb25zLnRyYW5zZm9ybShub2RlLCBuZXdQb3MpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3UG9zO1xuICAgIH0sIGdldE1lbW9pemVLZXkpO1xuXG4gICAgaWYgKG9wdGlvbnMuYW5pbWF0ZSkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICB2YXIgbmV3UG9zID0gZ2V0RmluYWxQb3Mobm9kZSwgaSk7XG4gICAgICAgIHZhciBhbmltYXRlTm9kZSA9IG9wdGlvbnMuYW5pbWF0ZUZpbHRlciA9PSBudWxsIHx8IG9wdGlvbnMuYW5pbWF0ZUZpbHRlcihub2RlLCBpKTtcblxuICAgICAgICBpZiAoYW5pbWF0ZU5vZGUpIHtcbiAgICAgICAgICB2YXIgYW5pID0gbm9kZS5hbmltYXRpb24oe1xuICAgICAgICAgICAgcG9zaXRpb246IG5ld1BvcyxcbiAgICAgICAgICAgIGR1cmF0aW9uOiBvcHRpb25zLmFuaW1hdGlvbkR1cmF0aW9uLFxuICAgICAgICAgICAgZWFzaW5nOiBvcHRpb25zLmFuaW1hdGlvbkVhc2luZ1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGxheW91dC5hbmltYXRpb25zLnB1c2goYW5pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBub2RlLnBvc2l0aW9uKG5ld1Bvcyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuZml0KSB7XG4gICAgICAgIHZhciBmaXRBbmkgPSBjeS5hbmltYXRpb24oe1xuICAgICAgICAgIGZpdDoge1xuICAgICAgICAgICAgYm91bmRpbmdCb3g6IGxheW91dEVsZXMuYm91bmRpbmdCb3hBdChnZXRGaW5hbFBvcyksXG4gICAgICAgICAgICBwYWRkaW5nOiBvcHRpb25zLnBhZGRpbmdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiBvcHRpb25zLmFuaW1hdGlvbkR1cmF0aW9uLFxuICAgICAgICAgIGVhc2luZzogb3B0aW9ucy5hbmltYXRpb25FYXNpbmdcbiAgICAgICAgfSk7XG4gICAgICAgIGxheW91dC5hbmltYXRpb25zLnB1c2goZml0QW5pKTtcbiAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy56b29tICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5wYW4gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgem9vbVBhbkFuaSA9IGN5LmFuaW1hdGlvbih7XG4gICAgICAgICAgem9vbTogb3B0aW9ucy56b29tLFxuICAgICAgICAgIHBhbjogb3B0aW9ucy5wYW4sXG4gICAgICAgICAgZHVyYXRpb246IG9wdGlvbnMuYW5pbWF0aW9uRHVyYXRpb24sXG4gICAgICAgICAgZWFzaW5nOiBvcHRpb25zLmFuaW1hdGlvbkVhc2luZ1xuICAgICAgICB9KTtcbiAgICAgICAgbGF5b3V0LmFuaW1hdGlvbnMucHVzaCh6b29tUGFuQW5pKTtcbiAgICAgIH1cblxuICAgICAgbGF5b3V0LmFuaW1hdGlvbnMuZm9yRWFjaChmdW5jdGlvbiAoYW5pKSB7XG4gICAgICAgIHJldHVybiBhbmkucGxheSgpO1xuICAgICAgfSk7XG4gICAgICBsYXlvdXQub25lKCdsYXlvdXRyZWFkeScsIG9wdGlvbnMucmVhZHkpO1xuICAgICAgbGF5b3V0LmVtaXQoe1xuICAgICAgICB0eXBlOiAnbGF5b3V0cmVhZHknLFxuICAgICAgICBsYXlvdXQ6IGxheW91dFxuICAgICAgfSk7XG4gICAgICBQcm9taXNlJDEuYWxsKGxheW91dC5hbmltYXRpb25zLm1hcChmdW5jdGlvbiAoYW5pKSB7XG4gICAgICAgIHJldHVybiBhbmkucHJvbWlzZSgpO1xuICAgICAgfSkpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICBsYXlvdXQub25lKCdsYXlvdXRzdG9wJywgb3B0aW9ucy5zdG9wKTtcbiAgICAgICAgbGF5b3V0LmVtaXQoe1xuICAgICAgICAgIHR5cGU6ICdsYXlvdXRzdG9wJyxcbiAgICAgICAgICBsYXlvdXQ6IGxheW91dFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBub2Rlcy5wb3NpdGlvbnMoZ2V0RmluYWxQb3MpO1xuXG4gICAgICBpZiAob3B0aW9ucy5maXQpIHtcbiAgICAgICAgY3kuZml0KG9wdGlvbnMuZWxlcywgb3B0aW9ucy5wYWRkaW5nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuem9vbSAhPSBudWxsKSB7XG4gICAgICAgIGN5Lnpvb20ob3B0aW9ucy56b29tKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMucGFuKSB7XG4gICAgICAgIGN5LnBhbihvcHRpb25zLnBhbik7XG4gICAgICB9XG5cbiAgICAgIGxheW91dC5vbmUoJ2xheW91dHJlYWR5Jywgb3B0aW9ucy5yZWFkeSk7XG4gICAgICBsYXlvdXQuZW1pdCh7XG4gICAgICAgIHR5cGU6ICdsYXlvdXRyZWFkeScsXG4gICAgICAgIGxheW91dDogbGF5b3V0XG4gICAgICB9KTtcbiAgICAgIGxheW91dC5vbmUoJ2xheW91dHN0b3AnLCBvcHRpb25zLnN0b3ApO1xuICAgICAgbGF5b3V0LmVtaXQoe1xuICAgICAgICB0eXBlOiAnbGF5b3V0c3RvcCcsXG4gICAgICAgIGxheW91dDogbGF5b3V0XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgbGF5b3V0OiBmdW5jdGlvbiBsYXlvdXQob3B0aW9ucykge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgICByZXR1cm4gY3kubWFrZUxheW91dChleHRlbmQoe30sIG9wdGlvbnMsIHtcbiAgICAgIGVsZXM6IHRoaXNcbiAgICB9KSk7XG4gIH1cbn07IC8vIGFsaWFzZXM6XG5cbmVsZXNmbiRxLmNyZWF0ZUxheW91dCA9IGVsZXNmbiRxLm1ha2VMYXlvdXQgPSBlbGVzZm4kcS5sYXlvdXQ7XG5cbmZ1bmN0aW9uIHN0eWxlQ2FjaGUoa2V5LCBmbiwgZWxlKSB7XG4gIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgdmFyIGNhY2hlID0gX3Auc3R5bGVDYWNoZSA9IF9wLnN0eWxlQ2FjaGUgfHwgW107XG4gIHZhciB2YWw7XG5cbiAgaWYgKCh2YWwgPSBjYWNoZVtrZXldKSAhPSBudWxsKSB7XG4gICAgcmV0dXJuIHZhbDtcbiAgfSBlbHNlIHtcbiAgICB2YWwgPSBjYWNoZVtrZXldID0gZm4oZWxlKTtcbiAgICByZXR1cm4gdmFsO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNhY2hlU3R5bGVGdW5jdGlvbihrZXksIGZuKSB7XG4gIGtleSA9IGhhc2hTdHJpbmcoa2V5KTtcbiAgcmV0dXJuIGZ1bmN0aW9uIGNhY2hlZFN0eWxlRnVuY3Rpb24oZWxlKSB7XG4gICAgcmV0dXJuIHN0eWxlQ2FjaGUoa2V5LCBmbiwgZWxlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gY2FjaGVQcm90b3R5cGVTdHlsZUZ1bmN0aW9uKGtleSwgZm4pIHtcbiAga2V5ID0gaGFzaFN0cmluZyhrZXkpO1xuXG4gIHZhciBzZWxmRm4gPSBmdW5jdGlvbiBzZWxmRm4oZWxlKSB7XG4gICAgcmV0dXJuIGZuLmNhbGwoZWxlKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gY2FjaGVkUHJvdG90eXBlU3R5bGVGdW5jdGlvbigpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIHJldHVybiBzdHlsZUNhY2hlKGtleSwgc2VsZkZuLCBlbGUpO1xuICAgIH1cbiAgfTtcbn1cblxudmFyIGVsZXNmbiRyID0ge1xuICByZWNhbGN1bGF0ZVJlbmRlcmVkU3R5bGU6IGZ1bmN0aW9uIHJlY2FsY3VsYXRlUmVuZGVyZWRTdHlsZSh1c2VDYWNoZSkge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcbiAgICB2YXIgcmVuZGVyZXIgPSBjeS5yZW5kZXJlcigpO1xuICAgIHZhciBzdHlsZUVuYWJsZWQgPSBjeS5zdHlsZUVuYWJsZWQoKTtcblxuICAgIGlmIChyZW5kZXJlciAmJiBzdHlsZUVuYWJsZWQpIHtcbiAgICAgIHJlbmRlcmVyLnJlY2FsY3VsYXRlUmVuZGVyZWRTdHlsZSh0aGlzLCB1c2VDYWNoZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIGRpcnR5U3R5bGVDYWNoZTogZnVuY3Rpb24gZGlydHlTdHlsZUNhY2hlKCkge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICAgIHZhciBkaXJ0eSA9IGZ1bmN0aW9uIGRpcnR5KGVsZSkge1xuICAgICAgcmV0dXJuIGVsZS5fcHJpdmF0ZS5zdHlsZUNhY2hlID0gbnVsbDtcbiAgICB9O1xuXG4gICAgaWYgKGN5Lmhhc0NvbXBvdW5kTm9kZXMoKSkge1xuICAgICAgdmFyIGVsZXM7XG4gICAgICBlbGVzID0gdGhpcy5zcGF3blNlbGYoKS5tZXJnZSh0aGlzLmRlc2NlbmRhbnRzKCkpLm1lcmdlKHRoaXMucGFyZW50cygpKTtcbiAgICAgIGVsZXMubWVyZ2UoZWxlcy5jb25uZWN0ZWRFZGdlcygpKTtcbiAgICAgIGVsZXMuZm9yRWFjaChkaXJ0eSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWxlKSB7XG4gICAgICAgIGRpcnR5KGVsZSk7XG4gICAgICAgIGVsZS5jb25uZWN0ZWRFZGdlcygpLmZvckVhY2goZGlydHkpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIC8vIGZ1bGx5IHVwZGF0ZXMgKHJlY2FsY3VsYXRlcykgdGhlIHN0eWxlIGZvciB0aGUgZWxlbWVudHNcbiAgdXBkYXRlU3R5bGU6IGZ1bmN0aW9uIHVwZGF0ZVN0eWxlKG5vdGlmeVJlbmRlcmVyKSB7XG4gICAgdmFyIGN5ID0gdGhpcy5fcHJpdmF0ZS5jeTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGlmIChjeS5iYXRjaGluZygpKSB7XG4gICAgICB2YXIgYkVsZXMgPSBjeS5fcHJpdmF0ZS5iYXRjaFN0eWxlRWxlcztcbiAgICAgIGJFbGVzLm1lcmdlKHRoaXMpO1xuICAgICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nIGFuZCBleGl0IGVhcmx5IHdoZW4gYmF0Y2hpbmdcbiAgICB9XG5cbiAgICB2YXIgaGFzQ29tcG91bmRzID0gY3kuaGFzQ29tcG91bmROb2RlcygpO1xuICAgIHZhciBzdHlsZSA9IGN5LnN0eWxlKCk7XG4gICAgdmFyIHVwZGF0ZWRFbGVzID0gdGhpcztcbiAgICBub3RpZnlSZW5kZXJlciA9IG5vdGlmeVJlbmRlcmVyIHx8IG5vdGlmeVJlbmRlcmVyID09PSB1bmRlZmluZWQgPyB0cnVlIDogZmFsc2U7XG5cbiAgICBpZiAoaGFzQ29tcG91bmRzKSB7XG4gICAgICAvLyB0aGVuIGFkZCBldmVyeXRoaW5nIHVwIGFuZCBkb3duIGZvciBjb21wb3VuZCBzZWxlY3RvciBjaGVja3NcbiAgICAgIHVwZGF0ZWRFbGVzID0gdGhpcy5zcGF3blNlbGYoKS5tZXJnZSh0aGlzLmRlc2NlbmRhbnRzKCkpLm1lcmdlKHRoaXMucGFyZW50cygpKTtcbiAgICB9XG5cbiAgICB2YXIgY2hhbmdlZEVsZXMgPSBzdHlsZS5hcHBseSh1cGRhdGVkRWxlcyk7XG5cbiAgICBpZiAobm90aWZ5UmVuZGVyZXIpIHtcbiAgICAgIGNoYW5nZWRFbGVzLmVtaXRBbmROb3RpZnkoJ3N0eWxlJyk7IC8vIGxldCByZW5kZXJlciBrbm93IHdlIGNoYW5nZWQgc3R5bGVcbiAgICB9IGVsc2Uge1xuICAgICAgY2hhbmdlZEVsZXMuZW1pdCgnc3R5bGUnKTsgLy8ganVzdCBmaXJlIHRoZSBldmVudFxuICAgIH1cblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICAvLyBnZXQgdGhlIGludGVybmFsIHBhcnNlZCBzdHlsZSBvYmplY3QgZm9yIHRoZSBzcGVjaWZpZWQgcHJvcGVydHlcbiAgcGFyc2VkU3R5bGU6IGZ1bmN0aW9uIHBhcnNlZFN0eWxlKHByb3BlcnR5KSB7XG4gICAgdmFyIGluY2x1ZGVOb25EZWZhdWx0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB0cnVlO1xuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuICAgIHZhciBjeSA9IGVsZS5jeSgpO1xuXG4gICAgaWYgKCFjeS5zdHlsZUVuYWJsZWQoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChlbGUpIHtcbiAgICAgIHZhciBvdmVycmlkZGVuU3R5bGUgPSBlbGUuX3ByaXZhdGUuc3R5bGVbcHJvcGVydHldO1xuXG4gICAgICBpZiAob3ZlcnJpZGRlblN0eWxlICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG92ZXJyaWRkZW5TdHlsZTtcbiAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZU5vbkRlZmF1bHQpIHtcbiAgICAgICAgcmV0dXJuIGN5LnN0eWxlKCkuZ2V0RGVmYXVsdFByb3BlcnR5KHByb3BlcnR5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgbnVtZXJpY1N0eWxlOiBmdW5jdGlvbiBudW1lcmljU3R5bGUocHJvcGVydHkpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmICghZWxlLmN5KCkuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZWxlKSB7XG4gICAgICB2YXIgcHN0eWxlID0gZWxlLnBzdHlsZShwcm9wZXJ0eSk7XG4gICAgICByZXR1cm4gcHN0eWxlLnBmVmFsdWUgIT09IHVuZGVmaW5lZCA/IHBzdHlsZS5wZlZhbHVlIDogcHN0eWxlLnZhbHVlO1xuICAgIH1cbiAgfSxcbiAgbnVtZXJpY1N0eWxlVW5pdHM6IGZ1bmN0aW9uIG51bWVyaWNTdHlsZVVuaXRzKHByb3BlcnR5KSB7XG4gICAgdmFyIGVsZSA9IHRoaXNbMF07XG5cbiAgICBpZiAoIWVsZS5jeSgpLnN0eWxlRW5hYmxlZCgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGVsZSkge1xuICAgICAgcmV0dXJuIGVsZS5wc3R5bGUocHJvcGVydHkpLnVuaXRzO1xuICAgIH1cbiAgfSxcbiAgLy8gZ2V0IHRoZSBzcGVjaWZpZWQgY3NzIHByb3BlcnR5IGFzIGEgcmVuZGVyZWQgdmFsdWUgKGkuZS4gb24tc2NyZWVuIHZhbHVlKVxuICAvLyBvciBnZXQgdGhlIHdob2xlIHJlbmRlcmVkIHN0eWxlIGlmIG5vIHByb3BlcnR5IHNwZWNpZmllZCAoTkIgZG9lc24ndCBhbGxvdyBzZXR0aW5nKVxuICByZW5kZXJlZFN0eWxlOiBmdW5jdGlvbiByZW5kZXJlZFN0eWxlKHByb3BlcnR5KSB7XG4gICAgdmFyIGN5ID0gdGhpcy5jeSgpO1xuXG4gICAgaWYgKCFjeS5zdHlsZUVuYWJsZWQoKSkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdmFyIGVsZSA9IHRoaXNbMF07XG5cbiAgICBpZiAoZWxlKSB7XG4gICAgICByZXR1cm4gY3kuc3R5bGUoKS5nZXRSZW5kZXJlZFN0eWxlKGVsZSwgcHJvcGVydHkpO1xuICAgIH1cbiAgfSxcbiAgLy8gcmVhZCB0aGUgY2FsY3VsYXRlZCBjc3Mgc3R5bGUgb2YgdGhlIGVsZW1lbnQgb3Igb3ZlcnJpZGUgdGhlIHN0eWxlICh2aWEgYSBieXBhc3MpXG4gIHN0eWxlOiBmdW5jdGlvbiBzdHlsZShuYW1lLCB2YWx1ZSkge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHZhciB1cGRhdGVUcmFuc2l0aW9ucyA9IGZhbHNlO1xuICAgIHZhciBzdHlsZSA9IGN5LnN0eWxlKCk7XG5cbiAgICBpZiAocGxhaW5PYmplY3QobmFtZSkpIHtcbiAgICAgIC8vIHRoZW4gZXh0ZW5kIHRoZSBieXBhc3NcbiAgICAgIHZhciBwcm9wcyA9IG5hbWU7XG4gICAgICBzdHlsZS5hcHBseUJ5cGFzcyh0aGlzLCBwcm9wcywgdXBkYXRlVHJhbnNpdGlvbnMpO1xuICAgICAgdGhpcy5lbWl0QW5kTm90aWZ5KCdzdHlsZScpOyAvLyBsZXQgdGhlIHJlbmRlcmVyIGtub3cgd2UndmUgdXBkYXRlZCBzdHlsZVxuICAgIH0gZWxzZSBpZiAoc3RyaW5nKG5hbWUpKSB7XG4gICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyB0aGVuIGdldCB0aGUgcHJvcGVydHkgZnJvbSB0aGUgc3R5bGVcbiAgICAgICAgdmFyIGVsZSA9IHRoaXNbMF07XG5cbiAgICAgICAgaWYgKGVsZSkge1xuICAgICAgICAgIHJldHVybiBzdHlsZS5nZXRTdHlsZVByb3BlcnR5VmFsdWUoZWxlLCBuYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBlbXB0eSBjb2xsZWN0aW9uID0+IGNhbid0IGdldCBhbnkgdmFsdWVcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRoZW4gc2V0IHRoZSBieXBhc3Mgd2l0aCB0aGUgcHJvcGVydHkgdmFsdWVcbiAgICAgICAgc3R5bGUuYXBwbHlCeXBhc3ModGhpcywgbmFtZSwgdmFsdWUsIHVwZGF0ZVRyYW5zaXRpb25zKTtcbiAgICAgICAgdGhpcy5lbWl0QW5kTm90aWZ5KCdzdHlsZScpOyAvLyBsZXQgdGhlIHJlbmRlcmVyIGtub3cgd2UndmUgdXBkYXRlZCBzdHlsZVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YXIgX2VsZSA9IHRoaXNbMF07XG5cbiAgICAgIGlmIChfZWxlKSB7XG4gICAgICAgIHJldHVybiBzdHlsZS5nZXRSYXdTdHlsZShfZWxlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGVtcHR5IGNvbGxlY3Rpb24gPT4gY2FuJ3QgZ2V0IGFueSB2YWx1ZVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gIH0sXG4gIHJlbW92ZVN0eWxlOiBmdW5jdGlvbiByZW1vdmVTdHlsZShuYW1lcykge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHZhciB1cGRhdGVUcmFuc2l0aW9ucyA9IGZhbHNlO1xuICAgIHZhciBzdHlsZSA9IGN5LnN0eWxlKCk7XG4gICAgdmFyIGVsZXMgPSB0aGlzO1xuXG4gICAgaWYgKG5hbWVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICAgICAgc3R5bGUucmVtb3ZlQWxsQnlwYXNzZXMoZWxlLCB1cGRhdGVUcmFuc2l0aW9ucyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIG5hbWVzID0gbmFtZXMuc3BsaXQoL1xccysvKTtcblxuICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGVsZXMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBfZWxlMiA9IGVsZXNbX2ldO1xuICAgICAgICBzdHlsZS5yZW1vdmVCeXBhc3NlcyhfZWxlMiwgbmFtZXMsIHVwZGF0ZVRyYW5zaXRpb25zKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmVtaXRBbmROb3RpZnkoJ3N0eWxlJyk7IC8vIGxldCB0aGUgcmVuZGVyZXIga25vdyB3ZSd2ZSB1cGRhdGVkIHN0eWxlXG5cbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgc2hvdzogZnVuY3Rpb24gc2hvdygpIHtcbiAgICB0aGlzLmNzcygnZGlzcGxheScsICdlbGVtZW50Jyk7XG4gICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gIH0sXG4gIGhpZGU6IGZ1bmN0aW9uIGhpZGUoKSB7XG4gICAgdGhpcy5jc3MoJ2Rpc3BsYXknLCAnbm9uZScpO1xuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICBlZmZlY3RpdmVPcGFjaXR5OiBmdW5jdGlvbiBlZmZlY3RpdmVPcGFjaXR5KCkge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIHZhciBoYXNDb21wb3VuZE5vZGVzID0gY3kuaGFzQ29tcG91bmROb2RlcygpO1xuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuXG4gICAgaWYgKGVsZSkge1xuICAgICAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICAgICAgdmFyIHBhcmVudE9wYWNpdHkgPSBlbGUucHN0eWxlKCdvcGFjaXR5JykudmFsdWU7XG5cbiAgICAgIGlmICghaGFzQ29tcG91bmROb2Rlcykge1xuICAgICAgICByZXR1cm4gcGFyZW50T3BhY2l0eTtcbiAgICAgIH1cblxuICAgICAgdmFyIHBhcmVudHMgPSAhX3AuZGF0YS5wYXJlbnQgPyBudWxsIDogZWxlLnBhcmVudHMoKTtcblxuICAgICAgaWYgKHBhcmVudHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHBhcmVudCA9IHBhcmVudHNbaV07XG4gICAgICAgICAgdmFyIG9wYWNpdHkgPSBwYXJlbnQucHN0eWxlKCdvcGFjaXR5JykudmFsdWU7XG4gICAgICAgICAgcGFyZW50T3BhY2l0eSA9IG9wYWNpdHkgKiBwYXJlbnRPcGFjaXR5O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwYXJlbnRPcGFjaXR5O1xuICAgIH1cbiAgfSxcbiAgdHJhbnNwYXJlbnQ6IGZ1bmN0aW9uIHRyYW5zcGFyZW50KCkge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgZWxlID0gdGhpc1swXTtcbiAgICB2YXIgaGFzQ29tcG91bmROb2RlcyA9IGVsZS5jeSgpLmhhc0NvbXBvdW5kTm9kZXMoKTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIGlmICghaGFzQ29tcG91bmROb2Rlcykge1xuICAgICAgICByZXR1cm4gZWxlLnBzdHlsZSgnb3BhY2l0eScpLnZhbHVlID09PSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGVsZS5lZmZlY3RpdmVPcGFjaXR5KCkgPT09IDA7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBiYWNrZ3JvdW5kaW5nOiBmdW5jdGlvbiBiYWNrZ3JvdW5kaW5nKCkge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgZWxlID0gdGhpc1swXTtcbiAgICByZXR1cm4gZWxlLl9wcml2YXRlLmJhY2tncm91bmRpbmcgPyB0cnVlIDogZmFsc2U7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGNoZWNrQ29tcG91bmQoZWxlLCBwYXJlbnRPaykge1xuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciBwYXJlbnRzID0gX3AuZGF0YS5wYXJlbnQgPyBlbGUucGFyZW50cygpIDogbnVsbDtcblxuICBpZiAocGFyZW50cykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFyZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHBhcmVudCA9IHBhcmVudHNbaV07XG5cbiAgICAgIGlmICghcGFyZW50T2socGFyZW50KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGRlZmluZURlcml2ZWRTdGF0ZUZ1bmN0aW9uKHNwZWNzKSB7XG4gIHZhciBvayA9IHNwZWNzLm9rO1xuICB2YXIgZWRnZU9rVmlhTm9kZSA9IHNwZWNzLmVkZ2VPa1ZpYU5vZGUgfHwgc3BlY3Mub2s7XG4gIHZhciBwYXJlbnRPayA9IHNwZWNzLnBhcmVudE9rIHx8IHNwZWNzLm9rO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuICAgIHZhciBoYXNDb21wb3VuZE5vZGVzID0gY3kuaGFzQ29tcG91bmROb2RlcygpO1xuXG4gICAgaWYgKGVsZSkge1xuICAgICAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuXG4gICAgICBpZiAoIW9rKGVsZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoZWxlLmlzTm9kZSgpKSB7XG4gICAgICAgIHJldHVybiAhaGFzQ29tcG91bmROb2RlcyB8fCBjaGVja0NvbXBvdW5kKGVsZSwgcGFyZW50T2spO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHNyYyA9IF9wLnNvdXJjZTtcbiAgICAgICAgdmFyIHRndCA9IF9wLnRhcmdldDtcbiAgICAgICAgcmV0dXJuIGVkZ2VPa1ZpYU5vZGUoc3JjKSAmJiAoIWhhc0NvbXBvdW5kTm9kZXMgfHwgY2hlY2tDb21wb3VuZChzcmMsIGVkZ2VPa1ZpYU5vZGUpKSAmJiAoc3JjID09PSB0Z3QgfHwgZWRnZU9rVmlhTm9kZSh0Z3QpICYmICghaGFzQ29tcG91bmROb2RlcyB8fCBjaGVja0NvbXBvdW5kKHRndCwgZWRnZU9rVmlhTm9kZSkpKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbnZhciBlbGVUYWtlc1VwU3BhY2UgPSBjYWNoZVN0eWxlRnVuY3Rpb24oJ2VsZVRha2VzVXBTcGFjZScsIGZ1bmN0aW9uIChlbGUpIHtcbiAgcmV0dXJuIGVsZS5wc3R5bGUoJ2Rpc3BsYXknKS52YWx1ZSA9PT0gJ2VsZW1lbnQnICYmIGVsZS53aWR0aCgpICE9PSAwICYmIChlbGUuaXNOb2RlKCkgPyBlbGUuaGVpZ2h0KCkgIT09IDAgOiB0cnVlKTtcbn0pO1xuZWxlc2ZuJHIudGFrZXNVcFNwYWNlID0gY2FjaGVQcm90b3R5cGVTdHlsZUZ1bmN0aW9uKCd0YWtlc1VwU3BhY2UnLCBkZWZpbmVEZXJpdmVkU3RhdGVGdW5jdGlvbih7XG4gIG9rOiBlbGVUYWtlc1VwU3BhY2Vcbn0pKTtcbnZhciBlbGVJbnRlcmFjdGl2ZSA9IGNhY2hlU3R5bGVGdW5jdGlvbignZWxlSW50ZXJhY3RpdmUnLCBmdW5jdGlvbiAoZWxlKSB7XG4gIHJldHVybiBlbGUucHN0eWxlKCdldmVudHMnKS52YWx1ZSA9PT0gJ3llcycgJiYgZWxlLnBzdHlsZSgndmlzaWJpbGl0eScpLnZhbHVlID09PSAndmlzaWJsZScgJiYgZWxlVGFrZXNVcFNwYWNlKGVsZSk7XG59KTtcbnZhciBwYXJlbnRJbnRlcmFjdGl2ZSA9IGNhY2hlU3R5bGVGdW5jdGlvbigncGFyZW50SW50ZXJhY3RpdmUnLCBmdW5jdGlvbiAocGFyZW50KSB7XG4gIHJldHVybiBwYXJlbnQucHN0eWxlKCd2aXNpYmlsaXR5JykudmFsdWUgPT09ICd2aXNpYmxlJyAmJiBlbGVUYWtlc1VwU3BhY2UocGFyZW50KTtcbn0pO1xuZWxlc2ZuJHIuaW50ZXJhY3RpdmUgPSBjYWNoZVByb3RvdHlwZVN0eWxlRnVuY3Rpb24oJ2ludGVyYWN0aXZlJywgZGVmaW5lRGVyaXZlZFN0YXRlRnVuY3Rpb24oe1xuICBvazogZWxlSW50ZXJhY3RpdmUsXG4gIHBhcmVudE9rOiBwYXJlbnRJbnRlcmFjdGl2ZSxcbiAgZWRnZU9rVmlhTm9kZTogZWxlVGFrZXNVcFNwYWNlXG59KSk7XG5cbmVsZXNmbiRyLm5vbmludGVyYWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgZWxlID0gdGhpc1swXTtcblxuICBpZiAoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUuaW50ZXJhY3RpdmUoKTtcbiAgfVxufTtcblxudmFyIGVsZVZpc2libGUgPSBjYWNoZVN0eWxlRnVuY3Rpb24oJ2VsZVZpc2libGUnLCBmdW5jdGlvbiAoZWxlKSB7XG4gIHJldHVybiBlbGUucHN0eWxlKCd2aXNpYmlsaXR5JykudmFsdWUgPT09ICd2aXNpYmxlJyAmJiBlbGUucHN0eWxlKCdvcGFjaXR5JykucGZWYWx1ZSAhPT0gMCAmJiBlbGVUYWtlc1VwU3BhY2UoZWxlKTtcbn0pO1xudmFyIGVkZ2VWaXNpYmxlVmlhTm9kZSA9IGVsZVRha2VzVXBTcGFjZTtcbmVsZXNmbiRyLnZpc2libGUgPSBjYWNoZVByb3RvdHlwZVN0eWxlRnVuY3Rpb24oJ3Zpc2libGUnLCBkZWZpbmVEZXJpdmVkU3RhdGVGdW5jdGlvbih7XG4gIG9rOiBlbGVWaXNpYmxlLFxuICBlZGdlT2tWaWFOb2RlOiBlZGdlVmlzaWJsZVZpYU5vZGVcbn0pKTtcblxuZWxlc2ZuJHIuaGlkZGVuID0gZnVuY3Rpb24gKCkge1xuICB2YXIgZWxlID0gdGhpc1swXTtcblxuICBpZiAoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUudmlzaWJsZSgpO1xuICB9XG59O1xuXG5lbGVzZm4kci5pc0J1bmRsZWRCZXppZXIgPSBjYWNoZVByb3RvdHlwZVN0eWxlRnVuY3Rpb24oJ2lzQnVuZGxlZEJlemllcicsIGZ1bmN0aW9uICgpIHtcbiAgaWYgKCF0aGlzLmN5KCkuc3R5bGVFbmFibGVkKCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gIXRoaXMucmVtb3ZlZCgpICYmIHRoaXMucHN0eWxlKCdjdXJ2ZS1zdHlsZScpLnZhbHVlID09PSAnYmV6aWVyJyAmJiB0aGlzLnRha2VzVXBTcGFjZSgpO1xufSk7XG5lbGVzZm4kci5ieXBhc3MgPSBlbGVzZm4kci5jc3MgPSBlbGVzZm4kci5zdHlsZTtcbmVsZXNmbiRyLnJlbmRlcmVkQ3NzID0gZWxlc2ZuJHIucmVuZGVyZWRTdHlsZTtcbmVsZXNmbiRyLnJlbW92ZUJ5cGFzcyA9IGVsZXNmbiRyLnJlbW92ZUNzcyA9IGVsZXNmbiRyLnJlbW92ZVN0eWxlO1xuZWxlc2ZuJHIucHN0eWxlID0gZWxlc2ZuJHIucGFyc2VkU3R5bGU7XG5cbnZhciBlbGVzZm4kcyA9IHt9O1xuXG5mdW5jdGlvbiBkZWZpbmVTd2l0Y2hGdW5jdGlvbihwYXJhbXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICB2YXIgY2hhbmdlZEVsZXMgPSBbXTsgLy8gZS5nLiBjeS5ub2RlcygpLnNlbGVjdCggZGF0YSwgaGFuZGxlciApXG5cbiAgICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICAgIHZhciBkYXRhID0gYXJnc1swXTtcbiAgICAgIHZhciBoYW5kbGVyID0gYXJnc1sxXTtcbiAgICAgIHRoaXMub24ocGFyYW1zLmV2ZW50LCBkYXRhLCBoYW5kbGVyKTtcbiAgICB9IC8vIGUuZy4gY3kubm9kZXMoKS5zZWxlY3QoIGhhbmRsZXIgKVxuICAgIGVsc2UgaWYgKGFyZ3MubGVuZ3RoID09PSAxICYmIGZuKGFyZ3NbMF0pKSB7XG4gICAgICAgIHZhciBfaGFuZGxlciA9IGFyZ3NbMF07XG4gICAgICAgIHRoaXMub24ocGFyYW1zLmV2ZW50LCBfaGFuZGxlcik7XG4gICAgICB9IC8vIGUuZy4gY3kubm9kZXMoKS5zZWxlY3QoKVxuICAgICAgLy8gZS5nLiAocHJpdmF0ZSkgY3kubm9kZXMoKS5zZWxlY3QoWyd0YXBzZWxlY3QnXSlcbiAgICAgIGVsc2UgaWYgKGFyZ3MubGVuZ3RoID09PSAwIHx8IGFyZ3MubGVuZ3RoID09PSAxICYmIGFycmF5KGFyZ3NbMF0pKSB7XG4gICAgICAgICAgdmFyIGFkZGxFdmVudHMgPSBhcmdzLmxlbmd0aCA9PT0gMSA/IGFyZ3NbMF0gOiBudWxsO1xuXG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICAgICAgICAgIHZhciBhYmxlID0gIXBhcmFtcy5hYmxlRmllbGQgfHwgZWxlLl9wcml2YXRlW3BhcmFtcy5hYmxlRmllbGRdO1xuICAgICAgICAgICAgdmFyIGNoYW5nZWQgPSBlbGUuX3ByaXZhdGVbcGFyYW1zLmZpZWxkXSAhPSBwYXJhbXMudmFsdWU7XG5cbiAgICAgICAgICAgIGlmIChwYXJhbXMub3ZlcnJpZGVBYmxlKSB7XG4gICAgICAgICAgICAgIHZhciBvdmVycmlkZUFibGUgPSBwYXJhbXMub3ZlcnJpZGVBYmxlKGVsZSk7XG5cbiAgICAgICAgICAgICAgaWYgKG92ZXJyaWRlQWJsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgYWJsZSA9IG92ZXJyaWRlQWJsZTtcblxuICAgICAgICAgICAgICAgIGlmICghb3ZlcnJpZGVBYmxlKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgICAgICB9IC8vIHRvIHNhdmUgY3ljbGVzIGFzc3VtZSBub3QgYWJsZSBmb3IgYWxsIG9uIG92ZXJyaWRlXG5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoYWJsZSkge1xuICAgICAgICAgICAgICBlbGUuX3ByaXZhdGVbcGFyYW1zLmZpZWxkXSA9IHBhcmFtcy52YWx1ZTtcblxuICAgICAgICAgICAgICBpZiAoY2hhbmdlZCkge1xuICAgICAgICAgICAgICAgIGNoYW5nZWRFbGVzLnB1c2goZWxlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBjaGFuZ2VkQ29sbCA9IHRoaXMuc3Bhd24oY2hhbmdlZEVsZXMpO1xuICAgICAgICAgIGNoYW5nZWRDb2xsLnVwZGF0ZVN0eWxlKCk7IC8vIGNoYW5nZSBvZiBzdGF0ZSA9PiBwb3NzaWJsZSBjaGFuZ2Ugb2Ygc3R5bGVcblxuICAgICAgICAgIGNoYW5nZWRDb2xsLmVtaXQocGFyYW1zLmV2ZW50KTtcblxuICAgICAgICAgIGlmIChhZGRsRXZlbnRzKSB7XG4gICAgICAgICAgICBjaGFuZ2VkQ29sbC5lbWl0KGFkZGxFdmVudHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmluZVN3aXRjaFNldChwYXJhbXMpIHtcbiAgZWxlc2ZuJHNbcGFyYW1zLmZpZWxkXSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIGlmIChwYXJhbXMub3ZlcnJpZGVGaWVsZCkge1xuICAgICAgICB2YXIgdmFsID0gcGFyYW1zLm92ZXJyaWRlRmllbGQoZWxlKTtcblxuICAgICAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBlbGUuX3ByaXZhdGVbcGFyYW1zLmZpZWxkXTtcbiAgICB9XG4gIH07XG5cbiAgZWxlc2ZuJHNbcGFyYW1zLm9uXSA9IGRlZmluZVN3aXRjaEZ1bmN0aW9uKHtcbiAgICBldmVudDogcGFyYW1zLm9uLFxuICAgIGZpZWxkOiBwYXJhbXMuZmllbGQsXG4gICAgYWJsZUZpZWxkOiBwYXJhbXMuYWJsZUZpZWxkLFxuICAgIG92ZXJyaWRlQWJsZTogcGFyYW1zLm92ZXJyaWRlQWJsZSxcbiAgICB2YWx1ZTogdHJ1ZVxuICB9KTtcbiAgZWxlc2ZuJHNbcGFyYW1zLm9mZl0gPSBkZWZpbmVTd2l0Y2hGdW5jdGlvbih7XG4gICAgZXZlbnQ6IHBhcmFtcy5vZmYsXG4gICAgZmllbGQ6IHBhcmFtcy5maWVsZCxcbiAgICBhYmxlRmllbGQ6IHBhcmFtcy5hYmxlRmllbGQsXG4gICAgb3ZlcnJpZGVBYmxlOiBwYXJhbXMub3ZlcnJpZGVBYmxlLFxuICAgIHZhbHVlOiBmYWxzZVxuICB9KTtcbn1cblxuZGVmaW5lU3dpdGNoU2V0KHtcbiAgZmllbGQ6ICdsb2NrZWQnLFxuICBvdmVycmlkZUZpZWxkOiBmdW5jdGlvbiBvdmVycmlkZUZpZWxkKGVsZSkge1xuICAgIHJldHVybiBlbGUuY3koKS5hdXRvbG9jaygpID8gdHJ1ZSA6IHVuZGVmaW5lZDtcbiAgfSxcbiAgb246ICdsb2NrJyxcbiAgb2ZmOiAndW5sb2NrJ1xufSk7XG5kZWZpbmVTd2l0Y2hTZXQoe1xuICBmaWVsZDogJ2dyYWJiYWJsZScsXG4gIG92ZXJyaWRlRmllbGQ6IGZ1bmN0aW9uIG92ZXJyaWRlRmllbGQoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5jeSgpLmF1dG91bmdyYWJpZnkoKSB8fCBlbGUucGFubmFibGUoKSA/IGZhbHNlIDogdW5kZWZpbmVkO1xuICB9LFxuICBvbjogJ2dyYWJpZnknLFxuICBvZmY6ICd1bmdyYWJpZnknXG59KTtcbmRlZmluZVN3aXRjaFNldCh7XG4gIGZpZWxkOiAnc2VsZWN0ZWQnLFxuICBhYmxlRmllbGQ6ICdzZWxlY3RhYmxlJyxcbiAgb3ZlcnJpZGVBYmxlOiBmdW5jdGlvbiBvdmVycmlkZUFibGUoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5jeSgpLmF1dG91bnNlbGVjdGlmeSgpID8gZmFsc2UgOiB1bmRlZmluZWQ7XG4gIH0sXG4gIG9uOiAnc2VsZWN0JyxcbiAgb2ZmOiAndW5zZWxlY3QnXG59KTtcbmRlZmluZVN3aXRjaFNldCh7XG4gIGZpZWxkOiAnc2VsZWN0YWJsZScsXG4gIG92ZXJyaWRlRmllbGQ6IGZ1bmN0aW9uIG92ZXJyaWRlRmllbGQoZWxlKSB7XG4gICAgcmV0dXJuIGVsZS5jeSgpLmF1dG91bnNlbGVjdGlmeSgpID8gZmFsc2UgOiB1bmRlZmluZWQ7XG4gIH0sXG4gIG9uOiAnc2VsZWN0aWZ5JyxcbiAgb2ZmOiAndW5zZWxlY3RpZnknXG59KTtcbmVsZXNmbiRzLmRlc2VsZWN0ID0gZWxlc2ZuJHMudW5zZWxlY3Q7XG5cbmVsZXNmbiRzLmdyYWJiZWQgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBlbGUgPSB0aGlzWzBdO1xuXG4gIGlmIChlbGUpIHtcbiAgICByZXR1cm4gZWxlLl9wcml2YXRlLmdyYWJiZWQ7XG4gIH1cbn07XG5cbmRlZmluZVN3aXRjaFNldCh7XG4gIGZpZWxkOiAnYWN0aXZlJyxcbiAgb246ICdhY3RpdmF0ZScsXG4gIG9mZjogJ3VuYWN0aXZhdGUnXG59KTtcbmRlZmluZVN3aXRjaFNldCh7XG4gIGZpZWxkOiAncGFubmFibGUnLFxuICBvbjogJ3BhbmlmeScsXG4gIG9mZjogJ3VucGFuaWZ5J1xufSk7XG5cbmVsZXNmbiRzLmluYWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgZWxlID0gdGhpc1swXTtcblxuICBpZiAoZWxlKSB7XG4gICAgcmV0dXJuICFlbGUuX3ByaXZhdGUuYWN0aXZlO1xuICB9XG59O1xuXG52YXIgZWxlc2ZuJHQgPSB7fTsgLy8gREFHIGZ1bmN0aW9uc1xuLy8vLy8vLy8vLy8vLy8vL1xuXG52YXIgZGVmaW5lRGFnRXh0cmVtaXR5ID0gZnVuY3Rpb24gZGVmaW5lRGFnRXh0cmVtaXR5KHBhcmFtcykge1xuICByZXR1cm4gZnVuY3Rpb24gZGFnRXh0cmVtaXR5SW1wbChzZWxlY3Rvcikge1xuICAgIHZhciBlbGVzID0gdGhpcztcbiAgICB2YXIgcmV0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBlbGUgPSBlbGVzW2ldO1xuXG4gICAgICBpZiAoIWVsZS5pc05vZGUoKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIGRpc3F1YWxpZmllZCA9IGZhbHNlO1xuICAgICAgdmFyIGVkZ2VzID0gZWxlLmNvbm5lY3RlZEVkZ2VzKCk7XG5cbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZWRnZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIGVkZ2UgPSBlZGdlc1tqXTtcbiAgICAgICAgdmFyIHNyYyA9IGVkZ2Uuc291cmNlKCk7XG4gICAgICAgIHZhciB0Z3QgPSBlZGdlLnRhcmdldCgpO1xuXG4gICAgICAgIGlmIChwYXJhbXMubm9JbmNvbWluZ0VkZ2VzICYmIHRndCA9PT0gZWxlICYmIHNyYyAhPT0gZWxlIHx8IHBhcmFtcy5ub091dGdvaW5nRWRnZXMgJiYgc3JjID09PSBlbGUgJiYgdGd0ICE9PSBlbGUpIHtcbiAgICAgICAgICBkaXNxdWFsaWZpZWQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghZGlzcXVhbGlmaWVkKSB7XG4gICAgICAgIHJldC5wdXNoKGVsZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24ocmV0LCB7XG4gICAgICB1bmlxdWU6IHRydWVcbiAgICB9KS5maWx0ZXIoc2VsZWN0b3IpO1xuICB9O1xufTtcblxudmFyIGRlZmluZURhZ09uZUhvcCA9IGZ1bmN0aW9uIGRlZmluZURhZ09uZUhvcChwYXJhbXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICAgIHZhciBlbGVzID0gdGhpcztcbiAgICB2YXIgb0VsZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGVsZSA9IGVsZXNbaV07XG5cbiAgICAgIGlmICghZWxlLmlzTm9kZSgpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgZWRnZXMgPSBlbGUuY29ubmVjdGVkRWRnZXMoKTtcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBlZGdlcy5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgZWRnZSA9IGVkZ2VzW2pdO1xuICAgICAgICB2YXIgc3JjID0gZWRnZS5zb3VyY2UoKTtcbiAgICAgICAgdmFyIHRndCA9IGVkZ2UudGFyZ2V0KCk7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5vdXRnb2luZyAmJiBzcmMgPT09IGVsZSkge1xuICAgICAgICAgIG9FbGVzLnB1c2goZWRnZSk7XG4gICAgICAgICAgb0VsZXMucHVzaCh0Z3QpO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcmFtcy5pbmNvbWluZyAmJiB0Z3QgPT09IGVsZSkge1xuICAgICAgICAgIG9FbGVzLnB1c2goZWRnZSk7XG4gICAgICAgICAgb0VsZXMucHVzaChzcmMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24ob0VsZXMsIHtcbiAgICAgIHVuaXF1ZTogdHJ1ZVxuICAgIH0pLmZpbHRlcihzZWxlY3Rvcik7XG4gIH07XG59O1xuXG52YXIgZGVmaW5lRGFnQWxsSG9wcyA9IGZ1bmN0aW9uIGRlZmluZURhZ0FsbEhvcHMocGFyYW1zKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICB2YXIgZWxlcyA9IHRoaXM7XG4gICAgdmFyIHNFbGVzID0gW107XG4gICAgdmFyIHNFbGVzSWRzID0ge307XG5cbiAgICBmb3IgKDs7KSB7XG4gICAgICB2YXIgbmV4dCA9IHBhcmFtcy5vdXRnb2luZyA/IGVsZXMub3V0Z29lcnMoKSA6IGVsZXMuaW5jb21lcnMoKTtcblxuICAgICAgaWYgKG5leHQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSAvLyBkb25lIGlmIG5vbmUgbGVmdFxuXG5cbiAgICAgIHZhciBuZXdOZXh0ID0gZmFsc2U7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbiA9IG5leHRbaV07XG4gICAgICAgIHZhciBuaWQgPSBuLmlkKCk7XG5cbiAgICAgICAgaWYgKCFzRWxlc0lkc1tuaWRdKSB7XG4gICAgICAgICAgc0VsZXNJZHNbbmlkXSA9IHRydWU7XG4gICAgICAgICAgc0VsZXMucHVzaChuKTtcbiAgICAgICAgICBuZXdOZXh0ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIW5ld05leHQpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9IC8vIGRvbmUgaWYgdG91Y2hlZCBhbGwgb3V0Z29lcnMgYWxyZWFkeVxuXG5cbiAgICAgIGVsZXMgPSBuZXh0O1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNwYXduKHNFbGVzLCB7XG4gICAgICB1bmlxdWU6IHRydWVcbiAgICB9KS5maWx0ZXIoc2VsZWN0b3IpO1xuICB9O1xufTtcblxuZWxlc2ZuJHQuY2xlYXJUcmF2ZXJzYWxDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgdGhpc1tpXS5fcHJpdmF0ZS50cmF2ZXJzYWxDYWNoZSA9IG51bGw7XG4gIH1cbn07XG5cbmV4dGVuZChlbGVzZm4kdCwge1xuICAvLyBnZXQgdGhlIHJvb3Qgbm9kZXMgaW4gdGhlIERBR1xuICByb290czogZGVmaW5lRGFnRXh0cmVtaXR5KHtcbiAgICBub0luY29taW5nRWRnZXM6IHRydWVcbiAgfSksXG4gIC8vIGdldCB0aGUgbGVhZiBub2RlcyBpbiB0aGUgREFHXG4gIGxlYXZlczogZGVmaW5lRGFnRXh0cmVtaXR5KHtcbiAgICBub091dGdvaW5nRWRnZXM6IHRydWVcbiAgfSksXG4gIC8vIG5vcm1hbGx5IGNhbGxlZCBjaGlsZHJlbiBpbiBncmFwaCB0aGVvcnlcbiAgLy8gdGhlc2Ugbm9kZXMgPWVkZ2VzPT4gb3V0Z29pbmcgbm9kZXNcbiAgb3V0Z29lcnM6IGNhY2hlKGRlZmluZURhZ09uZUhvcCh7XG4gICAgb3V0Z29pbmc6IHRydWVcbiAgfSksICdvdXRnb2VycycpLFxuICAvLyBha2EgREFHIGRlc2NlbmRhbnRzXG4gIHN1Y2Nlc3NvcnM6IGRlZmluZURhZ0FsbEhvcHMoe1xuICAgIG91dGdvaW5nOiB0cnVlXG4gIH0pLFxuICAvLyBub3JtYWxseSBjYWxsZWQgcGFyZW50cyBpbiBncmFwaCB0aGVvcnlcbiAgLy8gdGhlc2Ugbm9kZXMgPD1lZGdlcz0gaW5jb21pbmcgbm9kZXNcbiAgaW5jb21lcnM6IGNhY2hlKGRlZmluZURhZ09uZUhvcCh7XG4gICAgaW5jb21pbmc6IHRydWVcbiAgfSksICdpbmNvbWVycycpLFxuICAvLyBha2EgREFHIGFuY2VzdG9yc1xuICBwcmVkZWNlc3NvcnM6IGRlZmluZURhZ0FsbEhvcHMoe1xuICAgIGluY29taW5nOiB0cnVlXG4gIH0pXG59KTsgLy8gTmVpZ2hib3VyaG9vZCBmdW5jdGlvbnNcbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbmV4dGVuZChlbGVzZm4kdCwge1xuICBuZWlnaGJvcmhvb2Q6IGNhY2hlKGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICAgIHZhciBlbGVtZW50cyA9IFtdO1xuICAgIHZhciBub2RlcyA9IHRoaXMubm9kZXMoKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIC8vIGZvciBhbGwgbm9kZXNcbiAgICAgIHZhciBub2RlID0gbm9kZXNbaV07XG4gICAgICB2YXIgY29ubmVjdGVkRWRnZXMgPSBub2RlLmNvbm5lY3RlZEVkZ2VzKCk7IC8vIGZvciBlYWNoIGNvbm5lY3RlZCBlZGdlLCBhZGQgdGhlIGVkZ2UgYW5kIHRoZSBvdGhlciBub2RlXG5cbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgY29ubmVjdGVkRWRnZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIGVkZ2UgPSBjb25uZWN0ZWRFZGdlc1tqXTtcbiAgICAgICAgdmFyIHNyYyA9IGVkZ2Uuc291cmNlKCk7XG4gICAgICAgIHZhciB0Z3QgPSBlZGdlLnRhcmdldCgpO1xuICAgICAgICB2YXIgb3RoZXJOb2RlID0gbm9kZSA9PT0gc3JjID8gdGd0IDogc3JjOyAvLyBuZWVkIGNoZWNrIGluIGNhc2Ugb2YgbG9vcFxuXG4gICAgICAgIGlmIChvdGhlck5vZGUubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGVsZW1lbnRzLnB1c2gob3RoZXJOb2RlWzBdKTsgLy8gYWRkIG5vZGUgMSBob3AgYXdheVxuICAgICAgICB9IC8vIGFkZCBjb25uZWN0ZWQgZWRnZVxuXG5cbiAgICAgICAgZWxlbWVudHMucHVzaChlZGdlWzBdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zcGF3bihlbGVtZW50cywge1xuICAgICAgdW5pcXVlOiB0cnVlXG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSwgJ25laWdoYm9yaG9vZCcpLFxuICBjbG9zZWROZWlnaGJvcmhvb2Q6IGZ1bmN0aW9uIGNsb3NlZE5laWdoYm9yaG9vZChzZWxlY3Rvcikge1xuICAgIHJldHVybiB0aGlzLm5laWdoYm9yaG9vZCgpLmFkZCh0aGlzKS5maWx0ZXIoc2VsZWN0b3IpO1xuICB9LFxuICBvcGVuTmVpZ2hib3Job29kOiBmdW5jdGlvbiBvcGVuTmVpZ2hib3Job29kKHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIHRoaXMubmVpZ2hib3Job29kKHNlbGVjdG9yKTtcbiAgfVxufSk7IC8vIGFsaWFzZXNcblxuZWxlc2ZuJHQubmVpZ2hib3VyaG9vZCA9IGVsZXNmbiR0Lm5laWdoYm9yaG9vZDtcbmVsZXNmbiR0LmNsb3NlZE5laWdoYm91cmhvb2QgPSBlbGVzZm4kdC5jbG9zZWROZWlnaGJvcmhvb2Q7XG5lbGVzZm4kdC5vcGVuTmVpZ2hib3VyaG9vZCA9IGVsZXNmbiR0Lm9wZW5OZWlnaGJvcmhvb2Q7IC8vIEVkZ2UgZnVuY3Rpb25zXG4vLy8vLy8vLy8vLy8vLy8vL1xuXG5leHRlbmQoZWxlc2ZuJHQsIHtcbiAgc291cmNlOiBjYWNoZShmdW5jdGlvbiBzb3VyY2VJbXBsKHNlbGVjdG9yKSB7XG4gICAgdmFyIGVsZSA9IHRoaXNbMF07XG4gICAgdmFyIHNyYztcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIHNyYyA9IGVsZS5fcHJpdmF0ZS5zb3VyY2UgfHwgZWxlLmN5KCkuY29sbGVjdGlvbigpO1xuICAgIH1cblxuICAgIHJldHVybiBzcmMgJiYgc2VsZWN0b3IgPyBzcmMuZmlsdGVyKHNlbGVjdG9yKSA6IHNyYztcbiAgfSwgJ3NvdXJjZScpLFxuICB0YXJnZXQ6IGNhY2hlKGZ1bmN0aW9uIHRhcmdldEltcGwoc2VsZWN0b3IpIHtcbiAgICB2YXIgZWxlID0gdGhpc1swXTtcbiAgICB2YXIgdGd0O1xuXG4gICAgaWYgKGVsZSkge1xuICAgICAgdGd0ID0gZWxlLl9wcml2YXRlLnRhcmdldCB8fCBlbGUuY3koKS5jb2xsZWN0aW9uKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRndCAmJiBzZWxlY3RvciA/IHRndC5maWx0ZXIoc2VsZWN0b3IpIDogdGd0O1xuICB9LCAndGFyZ2V0JyksXG4gIHNvdXJjZXM6IGRlZmluZVNvdXJjZUZ1bmN0aW9uKHtcbiAgICBhdHRyOiAnc291cmNlJ1xuICB9KSxcbiAgdGFyZ2V0czogZGVmaW5lU291cmNlRnVuY3Rpb24oe1xuICAgIGF0dHI6ICd0YXJnZXQnXG4gIH0pXG59KTtcblxuZnVuY3Rpb24gZGVmaW5lU291cmNlRnVuY3Rpb24ocGFyYW1zKSB7XG4gIHJldHVybiBmdW5jdGlvbiBzb3VyY2VJbXBsKHNlbGVjdG9yKSB7XG4gICAgdmFyIHNvdXJjZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGVsZSA9IHRoaXNbaV07XG4gICAgICB2YXIgc3JjID0gZWxlLl9wcml2YXRlW3BhcmFtcy5hdHRyXTtcblxuICAgICAgaWYgKHNyYykge1xuICAgICAgICBzb3VyY2VzLnB1c2goc3JjKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zcGF3bihzb3VyY2VzLCB7XG4gICAgICB1bmlxdWU6IHRydWVcbiAgICB9KS5maWx0ZXIoc2VsZWN0b3IpO1xuICB9O1xufVxuXG5leHRlbmQoZWxlc2ZuJHQsIHtcbiAgZWRnZXNXaXRoOiBjYWNoZShkZWZpbmVFZGdlc1dpdGhGdW5jdGlvbigpLCAnZWRnZXNXaXRoJyksXG4gIGVkZ2VzVG86IGNhY2hlKGRlZmluZUVkZ2VzV2l0aEZ1bmN0aW9uKHtcbiAgICB0aGlzSXNTcmM6IHRydWVcbiAgfSksICdlZGdlc1RvJylcbn0pO1xuXG5mdW5jdGlvbiBkZWZpbmVFZGdlc1dpdGhGdW5jdGlvbihwYXJhbXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGVkZ2VzV2l0aEltcGwob3RoZXJOb2Rlcykge1xuICAgIHZhciBlbGVtZW50cyA9IFtdO1xuICAgIHZhciBjeSA9IHRoaXMuX3ByaXZhdGUuY3k7XG4gICAgdmFyIHAgPSBwYXJhbXMgfHwge307IC8vIGdldCBlbGVtZW50cyBpZiBhIHNlbGVjdG9yIGlzIHNwZWNpZmllZFxuXG4gICAgaWYgKHN0cmluZyhvdGhlck5vZGVzKSkge1xuICAgICAgb3RoZXJOb2RlcyA9IGN5LiQob3RoZXJOb2Rlcyk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaCA9IDA7IGggPCBvdGhlck5vZGVzLmxlbmd0aDsgaCsrKSB7XG4gICAgICB2YXIgZWRnZXMgPSBvdGhlck5vZGVzW2hdLl9wcml2YXRlLmVkZ2VzO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlZGdlID0gZWRnZXNbaV07XG4gICAgICAgIHZhciBlZGdlRGF0YSA9IGVkZ2UuX3ByaXZhdGUuZGF0YTtcbiAgICAgICAgdmFyIHRoaXNUb090aGVyID0gdGhpcy5oYXNFbGVtZW50V2l0aElkKGVkZ2VEYXRhLnNvdXJjZSkgJiYgb3RoZXJOb2Rlcy5oYXNFbGVtZW50V2l0aElkKGVkZ2VEYXRhLnRhcmdldCk7XG4gICAgICAgIHZhciBvdGhlclRvVGhpcyA9IG90aGVyTm9kZXMuaGFzRWxlbWVudFdpdGhJZChlZGdlRGF0YS5zb3VyY2UpICYmIHRoaXMuaGFzRWxlbWVudFdpdGhJZChlZGdlRGF0YS50YXJnZXQpO1xuICAgICAgICB2YXIgZWRnZUNvbm5lY3RzVGhpc0FuZE90aGVyID0gdGhpc1RvT3RoZXIgfHwgb3RoZXJUb1RoaXM7XG5cbiAgICAgICAgaWYgKCFlZGdlQ29ubmVjdHNUaGlzQW5kT3RoZXIpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwLnRoaXNJc1NyYyB8fCBwLnRoaXNJc1RndCkge1xuICAgICAgICAgIGlmIChwLnRoaXNJc1NyYyAmJiAhdGhpc1RvT3RoZXIpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChwLnRoaXNJc1RndCAmJiAhb3RoZXJUb1RoaXMpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGVsZW1lbnRzLnB1c2goZWRnZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24oZWxlbWVudHMsIHtcbiAgICAgIHVuaXF1ZTogdHJ1ZVxuICAgIH0pO1xuICB9O1xufVxuXG5leHRlbmQoZWxlc2ZuJHQsIHtcbiAgY29ubmVjdGVkRWRnZXM6IGNhY2hlKGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICAgIHZhciByZXRFbGVzID0gW107XG4gICAgdmFyIGVsZXMgPSB0aGlzO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbm9kZSA9IGVsZXNbaV07XG5cbiAgICAgIGlmICghbm9kZS5pc05vZGUoKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIGVkZ2VzID0gbm9kZS5fcHJpdmF0ZS5lZGdlcztcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBlZGdlcy5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgZWRnZSA9IGVkZ2VzW2pdO1xuICAgICAgICByZXRFbGVzLnB1c2goZWRnZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24ocmV0RWxlcywge1xuICAgICAgdW5pcXVlOiB0cnVlXG4gICAgfSkuZmlsdGVyKHNlbGVjdG9yKTtcbiAgfSwgJ2Nvbm5lY3RlZEVkZ2VzJyksXG4gIGNvbm5lY3RlZE5vZGVzOiBjYWNoZShmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICB2YXIgcmV0RWxlcyA9IFtdO1xuICAgIHZhciBlbGVzID0gdGhpcztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGVkZ2UgPSBlbGVzW2ldO1xuXG4gICAgICBpZiAoIWVkZ2UuaXNFZGdlKCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHJldEVsZXMucHVzaChlZGdlLnNvdXJjZSgpWzBdKTtcbiAgICAgIHJldEVsZXMucHVzaChlZGdlLnRhcmdldCgpWzBdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zcGF3bihyZXRFbGVzLCB7XG4gICAgICB1bmlxdWU6IHRydWVcbiAgICB9KS5maWx0ZXIoc2VsZWN0b3IpO1xuICB9LCAnY29ubmVjdGVkTm9kZXMnKSxcbiAgcGFyYWxsZWxFZGdlczogY2FjaGUoZGVmaW5lUGFyYWxsZWxFZGdlc0Z1bmN0aW9uKCksICdwYXJhbGxlbEVkZ2VzJyksXG4gIGNvZGlyZWN0ZWRFZGdlczogY2FjaGUoZGVmaW5lUGFyYWxsZWxFZGdlc0Z1bmN0aW9uKHtcbiAgICBjb2RpcmVjdGVkOiB0cnVlXG4gIH0pLCAnY29kaXJlY3RlZEVkZ2VzJylcbn0pO1xuXG5mdW5jdGlvbiBkZWZpbmVQYXJhbGxlbEVkZ2VzRnVuY3Rpb24ocGFyYW1zKSB7XG4gIHZhciBkZWZhdWx0cyA9IHtcbiAgICBjb2RpcmVjdGVkOiBmYWxzZVxuICB9O1xuICBwYXJhbXMgPSBleHRlbmQoe30sIGRlZmF1bHRzLCBwYXJhbXMpO1xuICByZXR1cm4gZnVuY3Rpb24gcGFyYWxsZWxFZGdlc0ltcGwoc2VsZWN0b3IpIHtcbiAgICAvLyBtaWNyby1vcHRpbWlzZWQgZm9yIHJlbmRlcmVyXG4gICAgdmFyIGVsZW1lbnRzID0gW107XG4gICAgdmFyIGVkZ2VzID0gdGhpcy5lZGdlcygpO1xuICAgIHZhciBwID0gcGFyYW1zOyAvLyBsb29rIGF0IGFsbCB0aGUgZWRnZXMgaW4gdGhlIGNvbGxlY3Rpb25cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWRnZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBlZGdlMSA9IGVkZ2VzW2ldO1xuICAgICAgdmFyIGVkZ2UxX3AgPSBlZGdlMS5fcHJpdmF0ZTtcbiAgICAgIHZhciBzcmMxID0gZWRnZTFfcC5zb3VyY2U7XG4gICAgICB2YXIgc3JjaWQxID0gc3JjMS5fcHJpdmF0ZS5kYXRhLmlkO1xuICAgICAgdmFyIHRndGlkMSA9IGVkZ2UxX3AuZGF0YS50YXJnZXQ7XG4gICAgICB2YXIgc3JjRWRnZXMxID0gc3JjMS5fcHJpdmF0ZS5lZGdlczsgLy8gbG9vayBhdCBlZGdlcyBjb25uZWN0ZWQgdG8gdGhlIHNyYyBub2RlIG9mIHRoaXMgZWRnZVxuXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHNyY0VkZ2VzMS5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgZWRnZTIgPSBzcmNFZGdlczFbal07XG4gICAgICAgIHZhciBlZGdlMmRhdGEgPSBlZGdlMi5fcHJpdmF0ZS5kYXRhO1xuICAgICAgICB2YXIgdGd0aWQyID0gZWRnZTJkYXRhLnRhcmdldDtcbiAgICAgICAgdmFyIHNyY2lkMiA9IGVkZ2UyZGF0YS5zb3VyY2U7XG4gICAgICAgIHZhciBjb2RpcmVjdGVkID0gdGd0aWQyID09PSB0Z3RpZDEgJiYgc3JjaWQyID09PSBzcmNpZDE7XG4gICAgICAgIHZhciBvcHBkaXJlY3RlZCA9IHNyY2lkMSA9PT0gdGd0aWQyICYmIHRndGlkMSA9PT0gc3JjaWQyO1xuXG4gICAgICAgIGlmIChwLmNvZGlyZWN0ZWQgJiYgY29kaXJlY3RlZCB8fCAhcC5jb2RpcmVjdGVkICYmIChjb2RpcmVjdGVkIHx8IG9wcGRpcmVjdGVkKSkge1xuICAgICAgICAgIGVsZW1lbnRzLnB1c2goZWRnZTIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3Bhd24oZWxlbWVudHMsIHtcbiAgICAgIHVuaXF1ZTogdHJ1ZVxuICAgIH0pLmZpbHRlcihzZWxlY3Rvcik7XG4gIH07XG59IC8vIE1pc2MgZnVuY3Rpb25zXG4vLy8vLy8vLy8vLy8vLy8vL1xuXG5cbmV4dGVuZChlbGVzZm4kdCwge1xuICBjb21wb25lbnRzOiBmdW5jdGlvbiBjb21wb25lbnRzKHJvb3QpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIGN5ID0gc2VsZi5jeSgpO1xuICAgIHZhciB2aXNpdGVkID0gY3kuY29sbGVjdGlvbigpO1xuICAgIHZhciB1bnZpc2l0ZWQgPSByb290ID09IG51bGwgPyBzZWxmLm5vZGVzKCkgOiByb290Lm5vZGVzKCk7XG4gICAgdmFyIGNvbXBvbmVudHMgPSBbXTtcblxuICAgIGlmIChyb290ICE9IG51bGwgJiYgdW52aXNpdGVkLmVtcHR5KCkpIHtcbiAgICAgIC8vIHJvb3QgbWF5IGNvbnRhaW4gb25seSBlZGdlc1xuICAgICAgdW52aXNpdGVkID0gcm9vdC5zb3VyY2VzKCk7IC8vIGRvZXNuJ3QgbWF0dGVyIHdoaWNoIG5vZGUgdG8gdXNlICh1bmRpcmVjdGVkKSwgc28ganVzdCB1c2UgdGhlIHNvdXJjZSBzaWRlc1xuICAgIH1cblxuICAgIHZhciB2aXNpdEluQ29tcG9uZW50ID0gZnVuY3Rpb24gdmlzaXRJbkNvbXBvbmVudChub2RlLCBjb21wb25lbnQpIHtcbiAgICAgIHZpc2l0ZWQubWVyZ2Uobm9kZSk7XG4gICAgICB1bnZpc2l0ZWQudW5tZXJnZShub2RlKTtcbiAgICAgIGNvbXBvbmVudC5tZXJnZShub2RlKTtcbiAgICB9O1xuXG4gICAgaWYgKHVudmlzaXRlZC5lbXB0eSgpKSB7XG4gICAgICByZXR1cm4gc2VsZi5zcGF3bigpO1xuICAgIH1cblxuICAgIHZhciBfbG9vcCA9IGZ1bmN0aW9uIF9sb29wKCkge1xuICAgICAgLy8gZWFjaCBpdGVyYXRpb24geWllbGRzIGEgY29tcG9uZW50XG4gICAgICB2YXIgY21wdCA9IGN5LmNvbGxlY3Rpb24oKTtcbiAgICAgIGNvbXBvbmVudHMucHVzaChjbXB0KTtcbiAgICAgIHZhciByb290ID0gdW52aXNpdGVkWzBdO1xuICAgICAgdmlzaXRJbkNvbXBvbmVudChyb290LCBjbXB0KTtcbiAgICAgIHNlbGYuYmZzKHtcbiAgICAgICAgZGlyZWN0ZWQ6IGZhbHNlLFxuICAgICAgICByb290czogcm9vdCxcbiAgICAgICAgdmlzaXQ6IGZ1bmN0aW9uIHZpc2l0KHYpIHtcbiAgICAgICAgICByZXR1cm4gdmlzaXRJbkNvbXBvbmVudCh2LCBjbXB0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBjbXB0LmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgbm9kZS5jb25uZWN0ZWRFZGdlcygpLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAvLyBjb25uZWN0ZWRFZGdlcygpIHVzdWFsbHkgY2FjaGVkXG4gICAgICAgICAgaWYgKHNlbGYuaGFzKGUpICYmIGNtcHQuaGFzKGUuc291cmNlKCkpICYmIGNtcHQuaGFzKGUudGFyZ2V0KCkpKSB7XG4gICAgICAgICAgICAvLyBoYXMoKSBpcyBjaGVhcFxuICAgICAgICAgICAgY21wdC5tZXJnZShlKTsgLy8gZm9yRWFjaCgpIG9ubHkgY29uc2lkZXJzIG5vZGVzIC0tIHNldHMgTiBhdCBjYWxsIHRpbWVcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIGRvIHtcbiAgICAgIF9sb29wKCk7XG4gICAgfSB3aGlsZSAodW52aXNpdGVkLmxlbmd0aCA+IDApO1xuXG4gICAgcmV0dXJuIGNvbXBvbmVudHM7XG4gIH0sXG4gIGNvbXBvbmVudDogZnVuY3Rpb24gY29tcG9uZW50KCkge1xuICAgIHZhciBlbGUgPSB0aGlzWzBdO1xuICAgIHJldHVybiBlbGUuY3koKS5tdXRhYmxlRWxlbWVudHMoKS5jb21wb25lbnRzKGVsZSlbMF07XG4gIH1cbn0pO1xuZWxlc2ZuJHQuY29tcG9uZW50c09mID0gZWxlc2ZuJHQuY29tcG9uZW50cztcblxudmFyIGlkRmFjdG9yeSA9IHtcbiAgZ2VuZXJhdGU6IGZ1bmN0aW9uIGdlbmVyYXRlKGN5LCBlbGVtZW50LCB0cnlUaGlzSWQpIHtcbiAgICB2YXIgaWQgPSB0cnlUaGlzSWQgIT0gbnVsbCA/IHRyeVRoaXNJZCA6IHV1aWQoKTtcblxuICAgIHdoaWxlIChjeS5oYXNFbGVtZW50V2l0aElkKGlkKSkge1xuICAgICAgaWQgPSB1dWlkKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGlkO1xuICB9XG59OyAvLyByZXByZXNlbnRzIGEgc2V0IG9mIG5vZGVzLCBlZGdlcywgb3IgYm90aCB0b2dldGhlclxuXG52YXIgQ29sbGVjdGlvbiA9IGZ1bmN0aW9uIENvbGxlY3Rpb24oY3ksIGVsZW1lbnRzLCBvcHRpb25zKSB7XG4gIGlmIChjeSA9PT0gdW5kZWZpbmVkIHx8ICFjb3JlKGN5KSkge1xuICAgIGVycm9yKCdBIGNvbGxlY3Rpb24gbXVzdCBoYXZlIGEgcmVmZXJlbmNlIHRvIHRoZSBjb3JlJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIG1hcCA9IG5ldyBNYXAkMSgpO1xuICB2YXIgY3JlYXRlZEVsZW1lbnRzID0gZmFsc2U7XG5cbiAgaWYgKCFlbGVtZW50cykge1xuICAgIGVsZW1lbnRzID0gW107XG4gIH0gZWxzZSBpZiAoZWxlbWVudHMubGVuZ3RoID4gMCAmJiBwbGFpbk9iamVjdChlbGVtZW50c1swXSkgJiYgIWVsZW1lbnQoZWxlbWVudHNbMF0pKSB7XG4gICAgY3JlYXRlZEVsZW1lbnRzID0gdHJ1ZTsgLy8gbWFrZSBlbGVtZW50cyBmcm9tIGpzb24gYW5kIHJlc3RvcmUgYWxsIGF0IG9uY2UgbGF0ZXJcblxuICAgIHZhciBlbGVzID0gW107XG4gICAgdmFyIGVsZXNJZHMgPSBuZXcgU2V0JDEoKTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gZWxlbWVudHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICB2YXIganNvbiA9IGVsZW1lbnRzW2ldO1xuXG4gICAgICBpZiAoanNvbi5kYXRhID09IG51bGwpIHtcbiAgICAgICAganNvbi5kYXRhID0ge307XG4gICAgICB9XG5cbiAgICAgIHZhciBfZGF0YSA9IGpzb24uZGF0YTsgLy8gbWFrZSBzdXJlIG5ld2x5IGNyZWF0ZWQgZWxlbWVudHMgaGF2ZSB2YWxpZCBpZHNcblxuICAgICAgaWYgKF9kYXRhLmlkID09IG51bGwpIHtcbiAgICAgICAgX2RhdGEuaWQgPSBpZEZhY3RvcnkuZ2VuZXJhdGUoY3ksIGpzb24pO1xuICAgICAgfSBlbHNlIGlmIChjeS5oYXNFbGVtZW50V2l0aElkKF9kYXRhLmlkKSB8fCBlbGVzSWRzLmhhcyhfZGF0YS5pZCkpIHtcbiAgICAgICAgY29udGludWU7IC8vIGNhbid0IGNyZWF0ZSBlbGVtZW50IGlmIHByaW9yIGlkIGFscmVhZHkgZXhpc3RzXG4gICAgICB9XG5cbiAgICAgIHZhciBlbGUgPSBuZXcgRWxlbWVudChjeSwganNvbiwgZmFsc2UpO1xuICAgICAgZWxlcy5wdXNoKGVsZSk7XG4gICAgICBlbGVzSWRzLmFkZChfZGF0YS5pZCk7XG4gICAgfVxuXG4gICAgZWxlbWVudHMgPSBlbGVzO1xuICB9XG5cbiAgdGhpcy5sZW5ndGggPSAwO1xuXG4gIGZvciAodmFyIF9pID0gMCwgX2wgPSBlbGVtZW50cy5sZW5ndGg7IF9pIDwgX2w7IF9pKyspIHtcbiAgICB2YXIgZWxlbWVudCQxID0gZWxlbWVudHNbX2ldWzBdOyAvLyBbMF0gaW4gY2FzZSBlbGVtZW50cyBpcyBhbiBhcnJheSBvZiBjb2xsZWN0aW9ucywgcmF0aGVyIHRoYW4gYXJyYXkgb2YgZWxlbWVudHNcblxuICAgIGlmIChlbGVtZW50JDEgPT0gbnVsbCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgdmFyIGlkID0gZWxlbWVudCQxLl9wcml2YXRlLmRhdGEuaWQ7XG5cbiAgICBpZiAob3B0aW9ucyA9PSBudWxsIHx8IG9wdGlvbnMudW5pcXVlICYmICFtYXAuaGFzKGlkKSkge1xuICAgICAgbWFwLnNldChpZCwge1xuICAgICAgICBpbmRleDogdGhpcy5sZW5ndGgsXG4gICAgICAgIGVsZTogZWxlbWVudCQxXG4gICAgICB9KTtcbiAgICAgIHRoaXNbdGhpcy5sZW5ndGhdID0gZWxlbWVudCQxO1xuICAgICAgdGhpcy5sZW5ndGgrKztcbiAgICB9XG4gIH1cblxuICB0aGlzLl9wcml2YXRlID0ge1xuICAgIGN5OiBjeSxcbiAgICBtYXA6IG1hcFxuICB9OyAvLyByZXN0b3JlIHRoZSBlbGVtZW50cyBpZiB3ZSBjcmVhdGVkIHRoZW0gZnJvbSBqc29uXG5cbiAgaWYgKGNyZWF0ZWRFbGVtZW50cykge1xuICAgIHRoaXMucmVzdG9yZSgpO1xuICB9XG59OyAvLyBGdW5jdGlvbnNcbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIGtlZXAgdGhlIHByb3RvdHlwZXMgaW4gc3luYyAoYW4gZWxlbWVudCBoYXMgdGhlIHNhbWUgZnVuY3Rpb25zIGFzIGEgY29sbGVjdGlvbilcbi8vIGFuZCB1c2UgZWxlZm4gYW5kIGVsZXNmbiBhcyBzaG9ydGhhbmRzIHRvIHRoZSBwcm90b3R5cGVzXG5cblxudmFyIGVsZXNmbiR1ID0gRWxlbWVudC5wcm90b3R5cGUgPSBDb2xsZWN0aW9uLnByb3RvdHlwZTtcblxuZWxlc2ZuJHUuaW5zdGFuY2VTdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiAnY29sbGVjdGlvbic7XG59O1xuXG5lbGVzZm4kdS5zcGF3biA9IGZ1bmN0aW9uIChjeSwgZWxlcywgb3B0cykge1xuICBpZiAoIWNvcmUoY3kpKSB7XG4gICAgLy8gY3kgaXMgb3B0aW9uYWxcbiAgICBvcHRzID0gZWxlcztcbiAgICBlbGVzID0gY3k7XG4gICAgY3kgPSB0aGlzLmN5KCk7XG4gIH1cblxuICByZXR1cm4gbmV3IENvbGxlY3Rpb24oY3ksIGVsZXMsIG9wdHMpO1xufTtcblxuZWxlc2ZuJHUuc3Bhd25TZWxmID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5zcGF3bih0aGlzKTtcbn07XG5cbmVsZXNmbiR1LmN5ID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5jeTtcbn07XG5cbmVsZXNmbiR1LnJlbmRlcmVyID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5jeS5yZW5kZXJlcigpO1xufTtcblxuZWxlc2ZuJHUuZWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXNbMF07XG59O1xuXG5lbGVzZm4kdS5jb2xsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICBpZiAoY29sbGVjdGlvbih0aGlzKSkge1xuICAgIHJldHVybiB0aGlzO1xuICB9IGVsc2Uge1xuICAgIC8vIGFuIGVsZW1lbnRcbiAgICByZXR1cm4gbmV3IENvbGxlY3Rpb24odGhpcy5fcHJpdmF0ZS5jeSwgW3RoaXNdKTtcbiAgfVxufTtcblxuZWxlc2ZuJHUudW5pcXVlID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gbmV3IENvbGxlY3Rpb24odGhpcy5fcHJpdmF0ZS5jeSwgdGhpcywge1xuICAgIHVuaXF1ZTogdHJ1ZVxuICB9KTtcbn07XG5cbmVsZXNmbiR1Lmhhc0VsZW1lbnRXaXRoSWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgaWQgPSAnJyArIGlkOyAvLyBpZCBtdXN0IGJlIHN0cmluZ1xuXG4gIHJldHVybiB0aGlzLl9wcml2YXRlLm1hcC5oYXMoaWQpO1xufTtcblxuZWxlc2ZuJHUuZ2V0RWxlbWVudEJ5SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgaWQgPSAnJyArIGlkOyAvLyBpZCBtdXN0IGJlIHN0cmluZ1xuXG4gIHZhciBjeSA9IHRoaXMuX3ByaXZhdGUuY3k7XG5cbiAgdmFyIGVudHJ5ID0gdGhpcy5fcHJpdmF0ZS5tYXAuZ2V0KGlkKTtcblxuICByZXR1cm4gZW50cnkgPyBlbnRyeS5lbGUgOiBuZXcgQ29sbGVjdGlvbihjeSk7IC8vIGdldCBlbGUgb3IgZW1wdHkgY29sbGVjdGlvblxufTtcblxuZWxlc2ZuJHUuJGlkID0gZWxlc2ZuJHUuZ2V0RWxlbWVudEJ5SWQ7XG5cbmVsZXNmbiR1LnBvb2xJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGN5ID0gdGhpcy5fcHJpdmF0ZS5jeTtcbiAgdmFyIGVsZXMgPSBjeS5fcHJpdmF0ZS5lbGVtZW50cztcbiAgdmFyIGlkID0gdGhpc1swXS5fcHJpdmF0ZS5kYXRhLmlkO1xuICByZXR1cm4gZWxlcy5fcHJpdmF0ZS5tYXAuZ2V0KGlkKS5pbmRleDtcbn07XG5cbmVsZXNmbiR1LmluZGV4T2YgPSBmdW5jdGlvbiAoZWxlKSB7XG4gIHZhciBpZCA9IGVsZVswXS5fcHJpdmF0ZS5kYXRhLmlkO1xuICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5tYXAuZ2V0KGlkKS5pbmRleDtcbn07XG5cbmVsZXNmbiR1LmluZGV4T2ZJZCA9IGZ1bmN0aW9uIChpZCkge1xuICBpZCA9ICcnICsgaWQ7IC8vIGlkIG11c3QgYmUgc3RyaW5nXG5cbiAgcmV0dXJuIHRoaXMuX3ByaXZhdGUubWFwLmdldChpZCkuaW5kZXg7XG59O1xuXG5lbGVzZm4kdS5qc29uID0gZnVuY3Rpb24gKG9iaikge1xuICB2YXIgZWxlID0gdGhpcy5lbGVtZW50KCk7XG4gIHZhciBjeSA9IHRoaXMuY3koKTtcblxuICBpZiAoZWxlID09IG51bGwgJiYgb2JqKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0gLy8gY2FuJ3Qgc2V0IHRvIG5vIGVsZXNcblxuXG4gIGlmIChlbGUgPT0gbnVsbCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0gLy8gY2FuJ3QgZ2V0IGZyb20gbm8gZWxlc1xuXG5cbiAgdmFyIHAgPSBlbGUuX3ByaXZhdGU7XG5cbiAgaWYgKHBsYWluT2JqZWN0KG9iaikpIHtcbiAgICAvLyBzZXRcbiAgICBjeS5zdGFydEJhdGNoKCk7XG5cbiAgICBpZiAob2JqLmRhdGEpIHtcbiAgICAgIGVsZS5kYXRhKG9iai5kYXRhKTtcbiAgICAgIHZhciBfZGF0YTIgPSBwLmRhdGE7XG5cbiAgICAgIGlmIChlbGUuaXNFZGdlKCkpIHtcbiAgICAgICAgLy8gc291cmNlIGFuZCB0YXJnZXQgYXJlIGltbXV0YWJsZSB2aWEgZGF0YSgpXG4gICAgICAgIHZhciBtb3ZlID0gZmFsc2U7XG4gICAgICAgIHZhciBzcGVjID0ge307XG4gICAgICAgIHZhciBzcmMgPSBvYmouZGF0YS5zb3VyY2U7XG4gICAgICAgIHZhciB0Z3QgPSBvYmouZGF0YS50YXJnZXQ7XG5cbiAgICAgICAgaWYgKHNyYyAhPSBudWxsICYmIHNyYyAhPSBfZGF0YTIuc291cmNlKSB7XG4gICAgICAgICAgc3BlYy5zb3VyY2UgPSAnJyArIHNyYzsgLy8gaWQgbXVzdCBiZSBzdHJpbmdcblxuICAgICAgICAgIG1vdmUgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRndCAhPSBudWxsICYmIHRndCAhPSBfZGF0YTIudGFyZ2V0KSB7XG4gICAgICAgICAgc3BlYy50YXJnZXQgPSAnJyArIHRndDsgLy8gaWQgbXVzdCBiZSBzdHJpbmdcblxuICAgICAgICAgIG1vdmUgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1vdmUpIHtcbiAgICAgICAgICBlbGUgPSBlbGUubW92ZShzcGVjKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyZW50IGlzIGltbXV0YWJsZSB2aWEgZGF0YSgpXG4gICAgICAgIHZhciBuZXdQYXJlbnRWYWxTcGVjZCA9ICdwYXJlbnQnIGluIG9iai5kYXRhO1xuICAgICAgICB2YXIgcGFyZW50ID0gb2JqLmRhdGEucGFyZW50O1xuXG4gICAgICAgIGlmIChuZXdQYXJlbnRWYWxTcGVjZCAmJiAocGFyZW50ICE9IG51bGwgfHwgX2RhdGEyLnBhcmVudCAhPSBudWxsKSAmJiBwYXJlbnQgIT0gX2RhdGEyLnBhcmVudCkge1xuICAgICAgICAgIGlmIChwYXJlbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gY2FuJ3Qgc2V0IHVuZGVmaW5lZCBpbXBlcmF0aXZlbHksIHNvIHVzZSBudWxsXG4gICAgICAgICAgICBwYXJlbnQgPSBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChwYXJlbnQgIT0gbnVsbCkge1xuICAgICAgICAgICAgcGFyZW50ID0gJycgKyBwYXJlbnQ7IC8vIGlkIG11c3QgYmUgc3RyaW5nXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZWxlID0gZWxlLm1vdmUoe1xuICAgICAgICAgICAgcGFyZW50OiBwYXJlbnRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChvYmoucG9zaXRpb24pIHtcbiAgICAgIGVsZS5wb3NpdGlvbihvYmoucG9zaXRpb24pO1xuICAgIH0gLy8gaWdub3JlIGdyb3VwIC0tIGltbXV0YWJsZVxuXG5cbiAgICB2YXIgY2hlY2tTd2l0Y2ggPSBmdW5jdGlvbiBjaGVja1N3aXRjaChrLCB0cnVlRm5OYW1lLCBmYWxzZUZuTmFtZSkge1xuICAgICAgdmFyIG9ial9rID0gb2JqW2tdO1xuXG4gICAgICBpZiAob2JqX2sgIT0gbnVsbCAmJiBvYmpfayAhPT0gcFtrXSkge1xuICAgICAgICBpZiAob2JqX2spIHtcbiAgICAgICAgICBlbGVbdHJ1ZUZuTmFtZV0oKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbGVbZmFsc2VGbk5hbWVdKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY2hlY2tTd2l0Y2goJ3JlbW92ZWQnLCAncmVtb3ZlJywgJ3Jlc3RvcmUnKTtcbiAgICBjaGVja1N3aXRjaCgnc2VsZWN0ZWQnLCAnc2VsZWN0JywgJ3Vuc2VsZWN0Jyk7XG4gICAgY2hlY2tTd2l0Y2goJ3NlbGVjdGFibGUnLCAnc2VsZWN0aWZ5JywgJ3Vuc2VsZWN0aWZ5Jyk7XG4gICAgY2hlY2tTd2l0Y2goJ2xvY2tlZCcsICdsb2NrJywgJ3VubG9jaycpO1xuICAgIGNoZWNrU3dpdGNoKCdncmFiYmFibGUnLCAnZ3JhYmlmeScsICd1bmdyYWJpZnknKTtcbiAgICBjaGVja1N3aXRjaCgncGFubmFibGUnLCAncGFuaWZ5JywgJ3VucGFuaWZ5Jyk7XG5cbiAgICBpZiAob2JqLmNsYXNzZXMgIT0gbnVsbCkge1xuICAgICAgZWxlLmNsYXNzZXMob2JqLmNsYXNzZXMpO1xuICAgIH1cblxuICAgIGN5LmVuZEJhdGNoKCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0gZWxzZSBpZiAob2JqID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBnZXRcbiAgICB2YXIganNvbiA9IHtcbiAgICAgIGRhdGE6IGNvcHkocC5kYXRhKSxcbiAgICAgIHBvc2l0aW9uOiBjb3B5KHAucG9zaXRpb24pLFxuICAgICAgZ3JvdXA6IHAuZ3JvdXAsXG4gICAgICByZW1vdmVkOiBwLnJlbW92ZWQsXG4gICAgICBzZWxlY3RlZDogcC5zZWxlY3RlZCxcbiAgICAgIHNlbGVjdGFibGU6IHAuc2VsZWN0YWJsZSxcbiAgICAgIGxvY2tlZDogcC5sb2NrZWQsXG4gICAgICBncmFiYmFibGU6IHAuZ3JhYmJhYmxlLFxuICAgICAgcGFubmFibGU6IHAucGFubmFibGUsXG4gICAgICBjbGFzc2VzOiBudWxsXG4gICAgfTtcbiAgICBqc29uLmNsYXNzZXMgPSAnJztcbiAgICB2YXIgaSA9IDA7XG4gICAgcC5jbGFzc2VzLmZvckVhY2goZnVuY3Rpb24gKGNscykge1xuICAgICAgcmV0dXJuIGpzb24uY2xhc3NlcyArPSBpKysgPT09IDAgPyBjbHMgOiAnICcgKyBjbHM7XG4gICAgfSk7XG4gICAgcmV0dXJuIGpzb247XG4gIH1cbn07XG5cbmVsZXNmbiR1Lmpzb25zID0gZnVuY3Rpb24gKCkge1xuICB2YXIganNvbnMgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWxlID0gdGhpc1tpXTtcbiAgICB2YXIganNvbiA9IGVsZS5qc29uKCk7XG4gICAganNvbnMucHVzaChqc29uKTtcbiAgfVxuXG4gIHJldHVybiBqc29ucztcbn07XG5cbmVsZXNmbiR1LmNsb25lID0gZnVuY3Rpb24gKCkge1xuICB2YXIgY3kgPSB0aGlzLmN5KCk7XG4gIHZhciBlbGVzQXJyID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IHRoaXNbaV07XG4gICAgdmFyIGpzb24gPSBlbGUuanNvbigpO1xuICAgIHZhciBjbG9uZSA9IG5ldyBFbGVtZW50KGN5LCBqc29uLCBmYWxzZSk7IC8vIE5CIG5vIHJlc3RvcmVcblxuICAgIGVsZXNBcnIucHVzaChjbG9uZSk7XG4gIH1cblxuICByZXR1cm4gbmV3IENvbGxlY3Rpb24oY3ksIGVsZXNBcnIpO1xufTtcblxuZWxlc2ZuJHUuY29weSA9IGVsZXNmbiR1LmNsb25lO1xuXG5lbGVzZm4kdS5yZXN0b3JlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgbm90aWZ5UmVuZGVyZXIgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHRydWU7XG4gIHZhciBhZGRUb1Bvb2wgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHRydWU7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGN5ID0gc2VsZi5jeSgpO1xuICB2YXIgY3lfcCA9IGN5Ll9wcml2YXRlOyAvLyBjcmVhdGUgYXJyYXlzIG9mIG5vZGVzIGFuZCBlZGdlcywgc2luY2Ugd2UgbmVlZCB0b1xuICAvLyByZXN0b3JlIHRoZSBub2RlcyBmaXJzdFxuXG4gIHZhciBub2RlcyA9IFtdO1xuICB2YXIgZWRnZXMgPSBbXTtcbiAgdmFyIGVsZW1lbnRzO1xuXG4gIGZvciAodmFyIF9pMiA9IDAsIGwgPSBzZWxmLmxlbmd0aDsgX2kyIDwgbDsgX2kyKyspIHtcbiAgICB2YXIgZWxlID0gc2VsZltfaTJdO1xuXG4gICAgaWYgKGFkZFRvUG9vbCAmJiAhZWxlLnJlbW92ZWQoKSkge1xuICAgICAgLy8gZG9uJ3QgbmVlZCB0byBoYW5kbGUgdGhpcyBlbGVcbiAgICAgIGNvbnRpbnVlO1xuICAgIH0gLy8ga2VlcCBub2RlcyBmaXJzdCBpbiB0aGUgYXJyYXkgYW5kIGVkZ2VzIGFmdGVyXG5cblxuICAgIGlmIChlbGUuaXNOb2RlKCkpIHtcbiAgICAgIC8vIHB1dCB0byBmcm9udCBvZiBhcnJheSBpZiBub2RlXG4gICAgICBub2Rlcy5wdXNoKGVsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHB1dCB0byBlbmQgb2YgYXJyYXkgaWYgZWRnZVxuICAgICAgZWRnZXMucHVzaChlbGUpO1xuICAgIH1cbiAgfVxuXG4gIGVsZW1lbnRzID0gbm9kZXMuY29uY2F0KGVkZ2VzKTtcbiAgdmFyIGk7XG5cbiAgdmFyIHJlbW92ZUZyb21FbGVtZW50cyA9IGZ1bmN0aW9uIHJlbW92ZUZyb21FbGVtZW50cygpIHtcbiAgICBlbGVtZW50cy5zcGxpY2UoaSwgMSk7XG4gICAgaS0tO1xuICB9OyAvLyBub3csIHJlc3RvcmUgZWFjaCBlbGVtZW50XG5cblxuICBmb3IgKGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgX2VsZSA9IGVsZW1lbnRzW2ldO1xuICAgIHZhciBfcHJpdmF0ZSA9IF9lbGUuX3ByaXZhdGU7XG4gICAgdmFyIF9kYXRhMyA9IF9wcml2YXRlLmRhdGE7IC8vIHRoZSB0cmF2ZXJzYWwgY2FjaGUgc2hvdWxkIHN0YXJ0IGZyZXNoIHdoZW4gZWxlIGlzIGFkZGVkXG5cbiAgICBfZWxlLmNsZWFyVHJhdmVyc2FsQ2FjaGUoKTsgLy8gc2V0IGlkIGFuZCB2YWxpZGF0ZVxuXG5cbiAgICBpZiAoIWFkZFRvUG9vbCAmJiAhX3ByaXZhdGUucmVtb3ZlZCkgOyBlbHNlIGlmIChfZGF0YTMuaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgX2RhdGEzLmlkID0gaWRGYWN0b3J5LmdlbmVyYXRlKGN5LCBfZWxlKTtcbiAgICB9IGVsc2UgaWYgKG51bWJlcihfZGF0YTMuaWQpKSB7XG4gICAgICBfZGF0YTMuaWQgPSAnJyArIF9kYXRhMy5pZDsgLy8gbm93IGl0J3MgYSBzdHJpbmdcbiAgICB9IGVsc2UgaWYgKGVtcHR5U3RyaW5nKF9kYXRhMy5pZCkgfHwgIXN0cmluZyhfZGF0YTMuaWQpKSB7XG4gICAgICBlcnJvcignQ2FuIG5vdCBjcmVhdGUgZWxlbWVudCB3aXRoIGludmFsaWQgc3RyaW5nIElEIGAnICsgX2RhdGEzLmlkICsgJ2AnKTsgLy8gY2FuJ3QgY3JlYXRlIGVsZW1lbnQgaWYgaXQgaGFzIGVtcHR5IHN0cmluZyBhcyBpZCBvciBub24tc3RyaW5nIGlkXG5cbiAgICAgIHJlbW92ZUZyb21FbGVtZW50cygpO1xuICAgICAgY29udGludWU7XG4gICAgfSBlbHNlIGlmIChjeS5oYXNFbGVtZW50V2l0aElkKF9kYXRhMy5pZCkpIHtcbiAgICAgIGVycm9yKCdDYW4gbm90IGNyZWF0ZSBzZWNvbmQgZWxlbWVudCB3aXRoIElEIGAnICsgX2RhdGEzLmlkICsgJ2AnKTsgLy8gY2FuJ3QgY3JlYXRlIGVsZW1lbnQgaWYgb25lIGFscmVhZHkgaGFzIHRoYXQgaWRcblxuICAgICAgcmVtb3ZlRnJvbUVsZW1lbnRzKCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB2YXIgaWQgPSBfZGF0YTMuaWQ7IC8vIGlkIGlzIGZpbmFsaXNlZCwgbm93IGxldCdzIGtlZXAgYSByZWZcblxuICAgIGlmIChfZWxlLmlzTm9kZSgpKSB7XG4gICAgICAvLyBleHRyYSBjaGVja3MgZm9yIG5vZGVzXG4gICAgICB2YXIgcG9zID0gX3ByaXZhdGUucG9zaXRpb247IC8vIG1ha2Ugc3VyZSB0aGUgbm9kZXMgaGF2ZSBhIGRlZmluZWQgcG9zaXRpb25cblxuICAgICAgaWYgKHBvcy54ID09IG51bGwpIHtcbiAgICAgICAgcG9zLnggPSAwO1xuICAgICAgfVxuXG4gICAgICBpZiAocG9zLnkgPT0gbnVsbCkge1xuICAgICAgICBwb3MueSA9IDA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKF9lbGUuaXNFZGdlKCkpIHtcbiAgICAgIC8vIGV4dHJhIGNoZWNrcyBmb3IgZWRnZXNcbiAgICAgIHZhciBlZGdlID0gX2VsZTtcbiAgICAgIHZhciBmaWVsZHMgPSBbJ3NvdXJjZScsICd0YXJnZXQnXTtcbiAgICAgIHZhciBmaWVsZHNMZW5ndGggPSBmaWVsZHMubGVuZ3RoO1xuICAgICAgdmFyIGJhZFNvdXJjZU9yVGFyZ2V0ID0gZmFsc2U7XG5cbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZmllbGRzTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIGZpZWxkID0gZmllbGRzW2pdO1xuICAgICAgICB2YXIgdmFsID0gX2RhdGEzW2ZpZWxkXTtcblxuICAgICAgICBpZiAobnVtYmVyKHZhbCkpIHtcbiAgICAgICAgICB2YWwgPSBfZGF0YTNbZmllbGRdID0gJycgKyBfZGF0YTNbZmllbGRdOyAvLyBub3cgc3RyaW5nXG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsID09IG51bGwgfHwgdmFsID09PSAnJykge1xuICAgICAgICAgIC8vIGNhbid0IGNyZWF0ZSBpZiBzb3VyY2Ugb3IgdGFyZ2V0IGlzIG5vdCBkZWZpbmVkIHByb3Blcmx5XG4gICAgICAgICAgZXJyb3IoJ0NhbiBub3QgY3JlYXRlIGVkZ2UgYCcgKyBpZCArICdgIHdpdGggdW5zcGVjaWZpZWQgJyArIGZpZWxkKTtcbiAgICAgICAgICBiYWRTb3VyY2VPclRhcmdldCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoIWN5Lmhhc0VsZW1lbnRXaXRoSWQodmFsKSkge1xuICAgICAgICAgIC8vIGNhbid0IGNyZWF0ZSBlZGdlIGlmIG9uZSBvZiBpdHMgbm9kZXMgZG9lc24ndCBleGlzdFxuICAgICAgICAgIGVycm9yKCdDYW4gbm90IGNyZWF0ZSBlZGdlIGAnICsgaWQgKyAnYCB3aXRoIG5vbmV4aXN0YW50ICcgKyBmaWVsZCArICcgYCcgKyB2YWwgKyAnYCcpO1xuICAgICAgICAgIGJhZFNvdXJjZU9yVGFyZ2V0ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoYmFkU291cmNlT3JUYXJnZXQpIHtcbiAgICAgICAgcmVtb3ZlRnJvbUVsZW1lbnRzKCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfSAvLyBjYW4ndCBjcmVhdGUgdGhpc1xuXG5cbiAgICAgIHZhciBzcmMgPSBjeS5nZXRFbGVtZW50QnlJZChfZGF0YTMuc291cmNlKTtcbiAgICAgIHZhciB0Z3QgPSBjeS5nZXRFbGVtZW50QnlJZChfZGF0YTMudGFyZ2V0KTsgLy8gb25seSBvbmUgZWRnZSBpbiBub2RlIGlmIGxvb3BcblxuICAgICAgaWYgKHNyYy5zYW1lKHRndCkpIHtcbiAgICAgICAgc3JjLl9wcml2YXRlLmVkZ2VzLnB1c2goZWRnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzcmMuX3ByaXZhdGUuZWRnZXMucHVzaChlZGdlKTtcblxuICAgICAgICB0Z3QuX3ByaXZhdGUuZWRnZXMucHVzaChlZGdlKTtcbiAgICAgIH1cblxuICAgICAgZWRnZS5fcHJpdmF0ZS5zb3VyY2UgPSBzcmM7XG4gICAgICBlZGdlLl9wcml2YXRlLnRhcmdldCA9IHRndDtcbiAgICB9IC8vIGlmIGlzIGVkZ2VcbiAgICAvLyBjcmVhdGUgbW9jayBpZHMgLyBpbmRleGVzIG1hcHMgZm9yIGVsZW1lbnQgc28gaXQgY2FuIGJlIHVzZWQgbGlrZSBjb2xsZWN0aW9uc1xuXG5cbiAgICBfcHJpdmF0ZS5tYXAgPSBuZXcgTWFwJDEoKTtcblxuICAgIF9wcml2YXRlLm1hcC5zZXQoaWQsIHtcbiAgICAgIGVsZTogX2VsZSxcbiAgICAgIGluZGV4OiAwXG4gICAgfSk7XG5cbiAgICBfcHJpdmF0ZS5yZW1vdmVkID0gZmFsc2U7XG5cbiAgICBpZiAoYWRkVG9Qb29sKSB7XG4gICAgICBjeS5hZGRUb1Bvb2woX2VsZSk7XG4gICAgfVxuICB9IC8vIGZvciBlYWNoIGVsZW1lbnRcbiAgLy8gZG8gY29tcG91bmQgbm9kZSBzYW5pdHkgY2hlY2tzXG5cblxuICBmb3IgKHZhciBfaTMgPSAwOyBfaTMgPCBub2Rlcy5sZW5ndGg7IF9pMysrKSB7XG4gICAgLy8gZWFjaCBub2RlXG4gICAgdmFyIG5vZGUgPSBub2Rlc1tfaTNdO1xuICAgIHZhciBfZGF0YTQgPSBub2RlLl9wcml2YXRlLmRhdGE7XG5cbiAgICBpZiAobnVtYmVyKF9kYXRhNC5wYXJlbnQpKSB7XG4gICAgICAvLyB0aGVuIGF1dG9tYWtlIHN0cmluZ1xuICAgICAgX2RhdGE0LnBhcmVudCA9ICcnICsgX2RhdGE0LnBhcmVudDtcbiAgICB9XG5cbiAgICB2YXIgcGFyZW50SWQgPSBfZGF0YTQucGFyZW50O1xuICAgIHZhciBzcGVjaWZpZWRQYXJlbnQgPSBwYXJlbnRJZCAhPSBudWxsO1xuXG4gICAgaWYgKHNwZWNpZmllZFBhcmVudCkge1xuICAgICAgdmFyIHBhcmVudCA9IGN5LmdldEVsZW1lbnRCeUlkKHBhcmVudElkKTtcblxuICAgICAgaWYgKHBhcmVudC5lbXB0eSgpKSB7XG4gICAgICAgIC8vIG5vbi1leGlzdGFudCBwYXJlbnQ7IGp1c3QgcmVtb3ZlIGl0XG4gICAgICAgIF9kYXRhNC5wYXJlbnQgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgc2VsZkFzUGFyZW50ID0gZmFsc2U7XG4gICAgICAgIHZhciBhbmNlc3RvciA9IHBhcmVudDtcblxuICAgICAgICB3aGlsZSAoIWFuY2VzdG9yLmVtcHR5KCkpIHtcbiAgICAgICAgICBpZiAobm9kZS5zYW1lKGFuY2VzdG9yKSkge1xuICAgICAgICAgICAgLy8gbWFyayBzZWxmIGFzIHBhcmVudCBhbmQgcmVtb3ZlIGZyb20gZGF0YVxuICAgICAgICAgICAgc2VsZkFzUGFyZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgIF9kYXRhNC5wYXJlbnQgPSB1bmRlZmluZWQ7IC8vIHJlbW92ZSBwYXJlbnQgcmVmZXJlbmNlXG4gICAgICAgICAgICAvLyBleGl0IG9yIHdlIGxvb3AgZm9yZXZlclxuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhbmNlc3RvciA9IGFuY2VzdG9yLnBhcmVudCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzZWxmQXNQYXJlbnQpIHtcbiAgICAgICAgICAvLyBjb25uZWN0IHdpdGggY2hpbGRyZW5cbiAgICAgICAgICBwYXJlbnRbMF0uX3ByaXZhdGUuY2hpbGRyZW4ucHVzaChub2RlKTtcblxuICAgICAgICAgIG5vZGUuX3ByaXZhdGUucGFyZW50ID0gcGFyZW50WzBdOyAvLyBsZXQgdGhlIGNvcmUga25vdyB3ZSBoYXZlIGEgY29tcG91bmQgZ3JhcGhcblxuICAgICAgICAgIGN5X3AuaGFzQ29tcG91bmROb2RlcyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gZWxzZVxuXG4gICAgfSAvLyBpZiBzcGVjaWZpZWQgcGFyZW50XG5cbiAgfSAvLyBmb3IgZWFjaCBub2RlXG5cblxuICBpZiAoZWxlbWVudHMubGVuZ3RoID4gMCkge1xuICAgIHZhciByZXN0b3JlZCA9IG5ldyBDb2xsZWN0aW9uKGN5LCBlbGVtZW50cyk7XG5cbiAgICBmb3IgKHZhciBfaTQgPSAwOyBfaTQgPCByZXN0b3JlZC5sZW5ndGg7IF9pNCsrKSB7XG4gICAgICB2YXIgX2VsZTIgPSByZXN0b3JlZFtfaTRdO1xuXG4gICAgICBpZiAoX2VsZTIuaXNOb2RlKCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IC8vIGFkZGluZyBhbiBlZGdlIGludmFsaWRhdGVzIHRoZSB0cmF2ZXJzYWwgY2FjaGVzIGZvciB0aGUgcGFyYWxsZWwgZWRnZXNcblxuXG4gICAgICBfZWxlMi5wYXJhbGxlbEVkZ2VzKCkuY2xlYXJUcmF2ZXJzYWxDYWNoZSgpOyAvLyBhZGRpbmcgYW4gZWRnZSBpbnZhbGlkYXRlcyB0aGUgdHJhdmVyc2FsIGNhY2hlIGZvciB0aGUgY29ubmVjdGVkIG5vZGVzXG5cblxuICAgICAgX2VsZTIuc291cmNlKCkuY2xlYXJUcmF2ZXJzYWxDYWNoZSgpO1xuXG4gICAgICBfZWxlMi50YXJnZXQoKS5jbGVhclRyYXZlcnNhbENhY2hlKCk7XG4gICAgfVxuXG4gICAgdmFyIHRvVXBkYXRlU3R5bGU7XG5cbiAgICBpZiAoY3lfcC5oYXNDb21wb3VuZE5vZGVzKSB7XG4gICAgICB0b1VwZGF0ZVN0eWxlID0gY3kuY29sbGVjdGlvbigpLm1lcmdlKHJlc3RvcmVkKS5tZXJnZShyZXN0b3JlZC5jb25uZWN0ZWROb2RlcygpKS5tZXJnZShyZXN0b3JlZC5wYXJlbnQoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRvVXBkYXRlU3R5bGUgPSByZXN0b3JlZDtcbiAgICB9XG5cbiAgICB0b1VwZGF0ZVN0eWxlLmRpcnR5Q29tcG91bmRCb3VuZHNDYWNoZSgpLmRpcnR5Qm91bmRpbmdCb3hDYWNoZSgpLnVwZGF0ZVN0eWxlKG5vdGlmeVJlbmRlcmVyKTtcblxuICAgIGlmIChub3RpZnlSZW5kZXJlcikge1xuICAgICAgcmVzdG9yZWQuZW1pdEFuZE5vdGlmeSgnYWRkJyk7XG4gICAgfSBlbHNlIGlmIChhZGRUb1Bvb2wpIHtcbiAgICAgIHJlc3RvcmVkLmVtaXQoJ2FkZCcpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzZWxmOyAvLyBjaGFpbmFiaWxpdHlcbn07XG5cbmVsZXNmbiR1LnJlbW92ZWQgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBlbGUgPSB0aGlzWzBdO1xuICByZXR1cm4gZWxlICYmIGVsZS5fcHJpdmF0ZS5yZW1vdmVkO1xufTtcblxuZWxlc2ZuJHUuaW5zaWRlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgZWxlID0gdGhpc1swXTtcbiAgcmV0dXJuIGVsZSAmJiAhZWxlLl9wcml2YXRlLnJlbW92ZWQ7XG59O1xuXG5lbGVzZm4kdS5yZW1vdmUgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBub3RpZnlSZW5kZXJlciA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogdHJ1ZTtcbiAgdmFyIHJlbW92ZUZyb21Qb29sID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB0cnVlO1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBlbGVzVG9SZW1vdmUgPSBbXTtcbiAgdmFyIGVsZXNUb1JlbW92ZUlkcyA9IHt9O1xuICB2YXIgY3kgPSBzZWxmLl9wcml2YXRlLmN5OyAvLyBhZGQgY29ubmVjdGVkIGVkZ2VzXG5cbiAgZnVuY3Rpb24gYWRkQ29ubmVjdGVkRWRnZXMobm9kZSkge1xuICAgIHZhciBlZGdlcyA9IG5vZGUuX3ByaXZhdGUuZWRnZXM7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhZGQoZWRnZXNbaV0pO1xuICAgIH1cbiAgfSAvLyBhZGQgZGVzY2VuZGFudCBub2Rlc1xuXG5cbiAgZnVuY3Rpb24gYWRkQ2hpbGRyZW4obm9kZSkge1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuX3ByaXZhdGUuY2hpbGRyZW47XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhZGQoY2hpbGRyZW5baV0pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZChlbGUpIHtcbiAgICB2YXIgYWxyZWFkeUFkZGVkID0gZWxlc1RvUmVtb3ZlSWRzW2VsZS5pZCgpXTtcblxuICAgIGlmIChyZW1vdmVGcm9tUG9vbCAmJiBlbGUucmVtb3ZlZCgpIHx8IGFscmVhZHlBZGRlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbGVzVG9SZW1vdmVJZHNbZWxlLmlkKCldID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoZWxlLmlzTm9kZSgpKSB7XG4gICAgICBlbGVzVG9SZW1vdmUucHVzaChlbGUpOyAvLyBub2RlcyBhcmUgcmVtb3ZlZCBsYXN0XG5cbiAgICAgIGFkZENvbm5lY3RlZEVkZ2VzKGVsZSk7XG4gICAgICBhZGRDaGlsZHJlbihlbGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbGVzVG9SZW1vdmUudW5zaGlmdChlbGUpOyAvLyBlZGdlcyBhcmUgcmVtb3ZlZCBmaXJzdFxuICAgIH1cbiAgfSAvLyBtYWtlIHRoZSBsaXN0IG9mIGVsZW1lbnRzIHRvIHJlbW92ZVxuICAvLyAobWF5IGJlIHJlbW92aW5nIG1vcmUgdGhhbiBzcGVjaWZpZWQgZHVlIHRvIGNvbm5lY3RlZCBlZGdlcyBldGMpXG5cblxuICBmb3IgKHZhciBpID0gMCwgbCA9IHNlbGYubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IHNlbGZbaV07XG4gICAgYWRkKGVsZSk7XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVFZGdlUmVmKG5vZGUsIGVkZ2UpIHtcbiAgICB2YXIgY29ubmVjdGVkRWRnZXMgPSBub2RlLl9wcml2YXRlLmVkZ2VzO1xuICAgIHJlbW92ZUZyb21BcnJheShjb25uZWN0ZWRFZGdlcywgZWRnZSk7IC8vIHJlbW92aW5nIGFuIGVkZ2VzIGludmFsaWRhdGVzIHRoZSB0cmF2ZXJzYWwgY2FjaGUgZm9yIGl0cyBub2Rlc1xuXG4gICAgbm9kZS5jbGVhclRyYXZlcnNhbENhY2hlKCk7XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVQYXJhbGxlbFJlZihwbGxFZGdlKSB7XG4gICAgLy8gcmVtb3ZpbmcgYW4gZWRnZSBpbnZhbGlkYXRlcyB0aGUgdHJhdmVyc2FsIGNhY2hlcyBmb3IgdGhlIHBhcmFsbGVsIGVkZ2VzXG4gICAgcGxsRWRnZS5jbGVhclRyYXZlcnNhbENhY2hlKCk7XG4gIH1cblxuICB2YXIgYWx0ZXJlZFBhcmVudHMgPSBbXTtcbiAgYWx0ZXJlZFBhcmVudHMuaWRzID0ge307XG5cbiAgZnVuY3Rpb24gcmVtb3ZlQ2hpbGRSZWYocGFyZW50LCBlbGUpIHtcbiAgICBlbGUgPSBlbGVbMF07XG4gICAgcGFyZW50ID0gcGFyZW50WzBdO1xuICAgIHZhciBjaGlsZHJlbiA9IHBhcmVudC5fcHJpdmF0ZS5jaGlsZHJlbjtcbiAgICB2YXIgcGlkID0gcGFyZW50LmlkKCk7XG4gICAgcmVtb3ZlRnJvbUFycmF5KGNoaWxkcmVuLCBlbGUpOyAvLyByZW1vdmUgcGFyZW50ID0+IGNoaWxkIHJlZlxuXG4gICAgZWxlLl9wcml2YXRlLnBhcmVudCA9IG51bGw7IC8vIHJlbW92ZSBjaGlsZCA9PiBwYXJlbnQgcmVmXG5cbiAgICBpZiAoIWFsdGVyZWRQYXJlbnRzLmlkc1twaWRdKSB7XG4gICAgICBhbHRlcmVkUGFyZW50cy5pZHNbcGlkXSA9IHRydWU7XG4gICAgICBhbHRlcmVkUGFyZW50cy5wdXNoKHBhcmVudCk7XG4gICAgfVxuICB9XG5cbiAgc2VsZi5kaXJ0eUNvbXBvdW5kQm91bmRzQ2FjaGUoKTtcblxuICBpZiAocmVtb3ZlRnJvbVBvb2wpIHtcbiAgICBjeS5yZW1vdmVGcm9tUG9vbChlbGVzVG9SZW1vdmUpOyAvLyByZW1vdmUgZnJvbSBjb3JlIHBvb2xcbiAgfVxuXG4gIGZvciAodmFyIF9pNSA9IDA7IF9pNSA8IGVsZXNUb1JlbW92ZS5sZW5ndGg7IF9pNSsrKSB7XG4gICAgdmFyIF9lbGUzID0gZWxlc1RvUmVtb3ZlW19pNV07XG5cbiAgICBpZiAoX2VsZTMuaXNFZGdlKCkpIHtcbiAgICAgIC8vIHJlbW92ZSByZWZlcmVuY2VzIHRvIHRoaXMgZWRnZSBpbiBpdHMgY29ubmVjdGVkIG5vZGVzXG4gICAgICB2YXIgc3JjID0gX2VsZTMuc291cmNlKClbMF07XG5cbiAgICAgIHZhciB0Z3QgPSBfZWxlMy50YXJnZXQoKVswXTtcblxuICAgICAgcmVtb3ZlRWRnZVJlZihzcmMsIF9lbGUzKTtcbiAgICAgIHJlbW92ZUVkZ2VSZWYodGd0LCBfZWxlMyk7XG5cbiAgICAgIHZhciBwbGxFZGdlcyA9IF9lbGUzLnBhcmFsbGVsRWRnZXMoKTtcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBwbGxFZGdlcy5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgcGxsRWRnZSA9IHBsbEVkZ2VzW2pdO1xuICAgICAgICByZW1vdmVQYXJhbGxlbFJlZihwbGxFZGdlKTtcblxuICAgICAgICBpZiAocGxsRWRnZS5pc0J1bmRsZWRCZXppZXIoKSkge1xuICAgICAgICAgIHBsbEVkZ2UuZGlydHlCb3VuZGluZ0JveENhY2hlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gcmVtb3ZlIHJlZmVyZW5jZSB0byBwYXJlbnRcbiAgICAgIHZhciBwYXJlbnQgPSBfZWxlMy5wYXJlbnQoKTtcblxuICAgICAgaWYgKHBhcmVudC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgcmVtb3ZlQ2hpbGRSZWYocGFyZW50LCBfZWxlMyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHJlbW92ZUZyb21Qb29sKSB7XG4gICAgICAvLyBtYXJrIGFzIHJlbW92ZWRcbiAgICAgIF9lbGUzLl9wcml2YXRlLnJlbW92ZWQgPSB0cnVlO1xuICAgIH1cbiAgfSAvLyBjaGVjayB0byBzZWUgaWYgd2UgaGF2ZSBhIGNvbXBvdW5kIGdyYXBoIG9yIG5vdFxuXG5cbiAgdmFyIGVsZXNTdGlsbEluc2lkZSA9IGN5Ll9wcml2YXRlLmVsZW1lbnRzO1xuICBjeS5fcHJpdmF0ZS5oYXNDb21wb3VuZE5vZGVzID0gZmFsc2U7XG5cbiAgZm9yICh2YXIgX2k2ID0gMDsgX2k2IDwgZWxlc1N0aWxsSW5zaWRlLmxlbmd0aDsgX2k2KyspIHtcbiAgICB2YXIgX2VsZTQgPSBlbGVzU3RpbGxJbnNpZGVbX2k2XTtcblxuICAgIGlmIChfZWxlNC5pc1BhcmVudCgpKSB7XG4gICAgICBjeS5fcHJpdmF0ZS5oYXNDb21wb3VuZE5vZGVzID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHZhciByZW1vdmVkRWxlbWVudHMgPSBuZXcgQ29sbGVjdGlvbih0aGlzLmN5KCksIGVsZXNUb1JlbW92ZSk7XG5cbiAgaWYgKHJlbW92ZWRFbGVtZW50cy5zaXplKCkgPiAwKSB7XG4gICAgLy8gbXVzdCBtYW51YWxseSBub3RpZnkgc2luY2UgdHJpZ2dlciB3b24ndCBkbyB0aGlzIGF1dG9tYXRpY2FsbHkgb25jZSByZW1vdmVkXG4gICAgaWYgKG5vdGlmeVJlbmRlcmVyKSB7XG4gICAgICByZW1vdmVkRWxlbWVudHMuZW1pdEFuZE5vdGlmeSgncmVtb3ZlJyk7XG4gICAgfSBlbHNlIGlmIChyZW1vdmVGcm9tUG9vbCkge1xuICAgICAgcmVtb3ZlZEVsZW1lbnRzLmVtaXQoJ3JlbW92ZScpO1xuICAgIH1cbiAgfSAvLyB0aGUgcGFyZW50cyB3aG8gd2VyZSBtb2RpZmllZCBieSB0aGUgcmVtb3ZhbCBuZWVkIHRoZWlyIHN0eWxlIHVwZGF0ZWRcblxuXG4gIGZvciAodmFyIF9pNyA9IDA7IF9pNyA8IGFsdGVyZWRQYXJlbnRzLmxlbmd0aDsgX2k3KyspIHtcbiAgICB2YXIgX2VsZTUgPSBhbHRlcmVkUGFyZW50c1tfaTddO1xuXG4gICAgaWYgKCFyZW1vdmVGcm9tUG9vbCB8fCAhX2VsZTUucmVtb3ZlZCgpKSB7XG4gICAgICBfZWxlNS51cGRhdGVTdHlsZSgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZW1vdmVkRWxlbWVudHM7XG59O1xuXG5lbGVzZm4kdS5tb3ZlID0gZnVuY3Rpb24gKHN0cnVjdCkge1xuICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5O1xuICB2YXIgZWxlcyA9IHRoaXM7IC8vIGp1c3QgY2xlYW4gdXAgcmVmcywgY2FjaGVzLCBldGMuIGluIHRoZSBzYW1lIHdheSBhcyB3aGVuIHJlbW92aW5nIGFuZCB0aGVuIHJlc3RvcmluZ1xuICAvLyAob3VyIGNhbGxzIHRvIHJlbW92ZS9yZXN0b3JlIGRvIG5vdCByZW1vdmUgZnJvbSB0aGUgZ3JhcGggb3IgbWFrZSBldmVudHMpXG5cbiAgdmFyIG5vdGlmeVJlbmRlcmVyID0gZmFsc2U7XG4gIHZhciBtb2RpZnlQb29sID0gZmFsc2U7XG5cbiAgdmFyIHRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoaWQpIHtcbiAgICByZXR1cm4gaWQgPT0gbnVsbCA/IGlkIDogJycgKyBpZDtcbiAgfTsgLy8gaWQgbXVzdCBiZSBzdHJpbmdcblxuXG4gIGlmIChzdHJ1Y3Quc291cmNlICE9PSB1bmRlZmluZWQgfHwgc3RydWN0LnRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdmFyIHNyY0lkID0gdG9TdHJpbmcoc3RydWN0LnNvdXJjZSk7XG4gICAgdmFyIHRndElkID0gdG9TdHJpbmcoc3RydWN0LnRhcmdldCk7XG4gICAgdmFyIHNyY0V4aXN0cyA9IHNyY0lkICE9IG51bGwgJiYgY3kuaGFzRWxlbWVudFdpdGhJZChzcmNJZCk7XG4gICAgdmFyIHRndEV4aXN0cyA9IHRndElkICE9IG51bGwgJiYgY3kuaGFzRWxlbWVudFdpdGhJZCh0Z3RJZCk7XG5cbiAgICBpZiAoc3JjRXhpc3RzIHx8IHRndEV4aXN0cykge1xuICAgICAgY3kuYmF0Y2goZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBhdm9pZCBkdXBsaWNhdGUgc3R5bGUgdXBkYXRlc1xuICAgICAgICBlbGVzLnJlbW92ZShub3RpZnlSZW5kZXJlciwgbW9kaWZ5UG9vbCk7IC8vIGNsZWFuIHVwIHJlZnMgZXRjLlxuXG4gICAgICAgIGVsZXMuZW1pdEFuZE5vdGlmeSgnbW92ZW91dCcpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBlbGUgPSBlbGVzW2ldO1xuICAgICAgICAgIHZhciBfZGF0YTUgPSBlbGUuX3ByaXZhdGUuZGF0YTtcblxuICAgICAgICAgIGlmIChlbGUuaXNFZGdlKCkpIHtcbiAgICAgICAgICAgIGlmIChzcmNFeGlzdHMpIHtcbiAgICAgICAgICAgICAgX2RhdGE1LnNvdXJjZSA9IHNyY0lkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGd0RXhpc3RzKSB7XG4gICAgICAgICAgICAgIF9kYXRhNS50YXJnZXQgPSB0Z3RJZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBlbGVzLnJlc3RvcmUobm90aWZ5UmVuZGVyZXIsIG1vZGlmeVBvb2wpOyAvLyBtYWtlIG5ldyByZWZzLCBzdHlsZSwgZXRjLlxuICAgICAgfSk7XG4gICAgICBlbGVzLmVtaXRBbmROb3RpZnkoJ21vdmUnKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoc3RydWN0LnBhcmVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gbW92ZSBub2RlIHRvIG5ldyBwYXJlbnRcbiAgICB2YXIgcGFyZW50SWQgPSB0b1N0cmluZyhzdHJ1Y3QucGFyZW50KTtcbiAgICB2YXIgcGFyZW50RXhpc3RzID0gcGFyZW50SWQgPT09IG51bGwgfHwgY3kuaGFzRWxlbWVudFdpdGhJZChwYXJlbnRJZCk7XG5cbiAgICBpZiAocGFyZW50RXhpc3RzKSB7XG4gICAgICB2YXIgcGlkVG9Bc3NpZ24gPSBwYXJlbnRJZCA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IHBhcmVudElkO1xuICAgICAgY3kuYmF0Y2goZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBhdm9pZCBkdXBsaWNhdGUgc3R5bGUgdXBkYXRlc1xuICAgICAgICB2YXIgdXBkYXRlZCA9IGVsZXMucmVtb3ZlKG5vdGlmeVJlbmRlcmVyLCBtb2RpZnlQb29sKTsgLy8gY2xlYW4gdXAgcmVmcyBldGMuXG5cbiAgICAgICAgdXBkYXRlZC5lbWl0QW5kTm90aWZ5KCdtb3Zlb3V0Jyk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGVsZSA9IGVsZXNbaV07XG4gICAgICAgICAgdmFyIF9kYXRhNiA9IGVsZS5fcHJpdmF0ZS5kYXRhO1xuXG4gICAgICAgICAgaWYgKGVsZS5pc05vZGUoKSkge1xuICAgICAgICAgICAgX2RhdGE2LnBhcmVudCA9IHBpZFRvQXNzaWduO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHVwZGF0ZWQucmVzdG9yZShub3RpZnlSZW5kZXJlciwgbW9kaWZ5UG9vbCk7IC8vIG1ha2UgbmV3IHJlZnMsIHN0eWxlLCBldGMuXG4gICAgICB9KTtcbiAgICAgIGVsZXMuZW1pdEFuZE5vdGlmeSgnbW92ZScpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuW2VsZXNmbiRjLCBlbGVzZm4kZCwgZWxlc2ZuJGUsIGVsZXNmbiRmLCBlbGVzZm4kZywgZGF0YSQxLCBlbGVzZm4kaSwgZGltZW5zaW9ucywgZWxlc2ZuJG0sIGVsZXNmbiRuLCBlbGVzZm4kbywgZWxlc2ZuJHAsIGVsZXNmbiRxLCBlbGVzZm4kciwgZWxlc2ZuJHMsIGVsZXNmbiR0XS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wcykge1xuICBleHRlbmQoZWxlc2ZuJHUsIHByb3BzKTtcbn0pO1xuXG52YXIgY29yZWZuID0ge1xuICBhZGQ6IGZ1bmN0aW9uIGFkZChvcHRzKSB7XG4gICAgdmFyIGVsZW1lbnRzO1xuICAgIHZhciBjeSA9IHRoaXM7IC8vIGFkZCB0aGUgZWxlbWVudHNcblxuICAgIGlmIChlbGVtZW50T3JDb2xsZWN0aW9uKG9wdHMpKSB7XG4gICAgICB2YXIgZWxlcyA9IG9wdHM7XG5cbiAgICAgIGlmIChlbGVzLl9wcml2YXRlLmN5ID09PSBjeSkge1xuICAgICAgICAvLyBzYW1lIGluc3RhbmNlID0+IGp1c3QgcmVzdG9yZVxuICAgICAgICBlbGVtZW50cyA9IGVsZXMucmVzdG9yZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBjb3B5IGZyb20ganNvblxuICAgICAgICB2YXIganNvbnMgPSBbXTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICAgICAgICBqc29ucy5wdXNoKGVsZS5qc29uKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZWxlbWVudHMgPSBuZXcgQ29sbGVjdGlvbihjeSwganNvbnMpO1xuICAgICAgfVxuICAgIH0gLy8gc3BlY2lmeSBhbiBhcnJheSBvZiBvcHRpb25zXG4gICAgZWxzZSBpZiAoYXJyYXkob3B0cykpIHtcbiAgICAgICAgdmFyIF9qc29ucyA9IG9wdHM7XG4gICAgICAgIGVsZW1lbnRzID0gbmV3IENvbGxlY3Rpb24oY3ksIF9qc29ucyk7XG4gICAgICB9IC8vIHNwZWNpZnkgdmlhIG9wdHMubm9kZXMgYW5kIG9wdHMuZWRnZXNcbiAgICAgIGVsc2UgaWYgKHBsYWluT2JqZWN0KG9wdHMpICYmIChhcnJheShvcHRzLm5vZGVzKSB8fCBhcnJheShvcHRzLmVkZ2VzKSkpIHtcbiAgICAgICAgICB2YXIgZWxlc0J5R3JvdXAgPSBvcHRzO1xuICAgICAgICAgIHZhciBfanNvbnMyID0gW107XG4gICAgICAgICAgdmFyIGdycyA9IFsnbm9kZXMnLCAnZWRnZXMnXTtcblxuICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgaWwgPSBncnMubGVuZ3RoOyBfaSA8IGlsOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgZ3JvdXAgPSBncnNbX2ldO1xuICAgICAgICAgICAgdmFyIGVsZXNBcnJheSA9IGVsZXNCeUdyb3VwW2dyb3VwXTtcblxuICAgICAgICAgICAgaWYgKGFycmF5KGVsZXNBcnJheSkpIHtcbiAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpsID0gZWxlc0FycmF5Lmxlbmd0aDsgaiA8IGpsOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIganNvbiA9IGV4dGVuZCh7XG4gICAgICAgICAgICAgICAgICBncm91cDogZ3JvdXBcbiAgICAgICAgICAgICAgICB9LCBlbGVzQXJyYXlbal0pO1xuXG4gICAgICAgICAgICAgICAgX2pzb25zMi5wdXNoKGpzb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZWxlbWVudHMgPSBuZXcgQ29sbGVjdGlvbihjeSwgX2pzb25zMik7XG4gICAgICAgIH0gLy8gc3BlY2lmeSBvcHRpb25zIGZvciBvbmUgZWxlbWVudFxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBfanNvbiA9IG9wdHM7XG4gICAgICAgICAgICBlbGVtZW50cyA9IG5ldyBFbGVtZW50KGN5LCBfanNvbikuY29sbGVjdGlvbigpO1xuICAgICAgICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50cztcbiAgfSxcbiAgcmVtb3ZlOiBmdW5jdGlvbiByZW1vdmUoY29sbGVjdGlvbikge1xuICAgIGlmIChlbGVtZW50T3JDb2xsZWN0aW9uKGNvbGxlY3Rpb24pKSA7IGVsc2UgaWYgKHN0cmluZyhjb2xsZWN0aW9uKSkge1xuICAgICAgdmFyIHNlbGVjdG9yID0gY29sbGVjdGlvbjtcbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLiQoc2VsZWN0b3IpO1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnJlbW92ZSgpO1xuICB9XG59O1xuXG4vKiBnbG9iYWwgRmxvYXQzMkFycmF5ICovXG5cbi8qISBCZXppZXIgY3VydmUgZnVuY3Rpb24gZ2VuZXJhdG9yLiBDb3B5cmlnaHQgR2FldGFuIFJlbmF1ZGVhdS4gTUlUIExpY2Vuc2U6IGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTUlUX0xpY2Vuc2UgKi9cbmZ1bmN0aW9uIGdlbmVyYXRlQ3ViaWNCZXppZXIobVgxLCBtWTEsIG1YMiwgbVkyKSB7XG4gIHZhciBORVdUT05fSVRFUkFUSU9OUyA9IDQsXG4gICAgICBORVdUT05fTUlOX1NMT1BFID0gMC4wMDEsXG4gICAgICBTVUJESVZJU0lPTl9QUkVDSVNJT04gPSAwLjAwMDAwMDEsXG4gICAgICBTVUJESVZJU0lPTl9NQVhfSVRFUkFUSU9OUyA9IDEwLFxuICAgICAga1NwbGluZVRhYmxlU2l6ZSA9IDExLFxuICAgICAga1NhbXBsZVN0ZXBTaXplID0gMS4wIC8gKGtTcGxpbmVUYWJsZVNpemUgLSAxLjApLFxuICAgICAgZmxvYXQzMkFycmF5U3VwcG9ydGVkID0gdHlwZW9mIEZsb2F0MzJBcnJheSAhPT0gJ3VuZGVmaW5lZCc7XG4gIC8qIE11c3QgY29udGFpbiBmb3VyIGFyZ3VtZW50cy4gKi9cblxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCAhPT0gNCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvKiBBcmd1bWVudHMgbXVzdCBiZSBudW1iZXJzLiAqL1xuXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyArK2kpIHtcbiAgICBpZiAodHlwZW9mIGFyZ3VtZW50c1tpXSAhPT0gXCJudW1iZXJcIiB8fCBpc05hTihhcmd1bWVudHNbaV0pIHx8ICFpc0Zpbml0ZShhcmd1bWVudHNbaV0pKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIC8qIFggdmFsdWVzIG11c3QgYmUgaW4gdGhlIFswLCAxXSByYW5nZS4gKi9cblxuXG4gIG1YMSA9IE1hdGgubWluKG1YMSwgMSk7XG4gIG1YMiA9IE1hdGgubWluKG1YMiwgMSk7XG4gIG1YMSA9IE1hdGgubWF4KG1YMSwgMCk7XG4gIG1YMiA9IE1hdGgubWF4KG1YMiwgMCk7XG4gIHZhciBtU2FtcGxlVmFsdWVzID0gZmxvYXQzMkFycmF5U3VwcG9ydGVkID8gbmV3IEZsb2F0MzJBcnJheShrU3BsaW5lVGFibGVTaXplKSA6IG5ldyBBcnJheShrU3BsaW5lVGFibGVTaXplKTtcblxuICBmdW5jdGlvbiBBKGFBMSwgYUEyKSB7XG4gICAgcmV0dXJuIDEuMCAtIDMuMCAqIGFBMiArIDMuMCAqIGFBMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEIoYUExLCBhQTIpIHtcbiAgICByZXR1cm4gMy4wICogYUEyIC0gNi4wICogYUExO1xuICB9XG5cbiAgZnVuY3Rpb24gQyhhQTEpIHtcbiAgICByZXR1cm4gMy4wICogYUExO1xuICB9XG5cbiAgZnVuY3Rpb24gY2FsY0JlemllcihhVCwgYUExLCBhQTIpIHtcbiAgICByZXR1cm4gKChBKGFBMSwgYUEyKSAqIGFUICsgQihhQTEsIGFBMikpICogYVQgKyBDKGFBMSkpICogYVQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTbG9wZShhVCwgYUExLCBhQTIpIHtcbiAgICByZXR1cm4gMy4wICogQShhQTEsIGFBMikgKiBhVCAqIGFUICsgMi4wICogQihhQTEsIGFBMikgKiBhVCArIEMoYUExKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG5ld3RvblJhcGhzb25JdGVyYXRlKGFYLCBhR3Vlc3NUKSB7XG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IE5FV1RPTl9JVEVSQVRJT05TOyArK19pKSB7XG4gICAgICB2YXIgY3VycmVudFNsb3BlID0gZ2V0U2xvcGUoYUd1ZXNzVCwgbVgxLCBtWDIpO1xuXG4gICAgICBpZiAoY3VycmVudFNsb3BlID09PSAwLjApIHtcbiAgICAgICAgcmV0dXJuIGFHdWVzc1Q7XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50WCA9IGNhbGNCZXppZXIoYUd1ZXNzVCwgbVgxLCBtWDIpIC0gYVg7XG4gICAgICBhR3Vlc3NUIC09IGN1cnJlbnRYIC8gY3VycmVudFNsb3BlO1xuICAgIH1cblxuICAgIHJldHVybiBhR3Vlc3NUO1xuICB9XG5cbiAgZnVuY3Rpb24gY2FsY1NhbXBsZVZhbHVlcygpIHtcbiAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBrU3BsaW5lVGFibGVTaXplOyArK19pMikge1xuICAgICAgbVNhbXBsZVZhbHVlc1tfaTJdID0gY2FsY0JlemllcihfaTIgKiBrU2FtcGxlU3RlcFNpemUsIG1YMSwgbVgyKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBiaW5hcnlTdWJkaXZpZGUoYVgsIGFBLCBhQikge1xuICAgIHZhciBjdXJyZW50WCxcbiAgICAgICAgY3VycmVudFQsXG4gICAgICAgIGkgPSAwO1xuXG4gICAgZG8ge1xuICAgICAgY3VycmVudFQgPSBhQSArIChhQiAtIGFBKSAvIDIuMDtcbiAgICAgIGN1cnJlbnRYID0gY2FsY0JlemllcihjdXJyZW50VCwgbVgxLCBtWDIpIC0gYVg7XG5cbiAgICAgIGlmIChjdXJyZW50WCA+IDAuMCkge1xuICAgICAgICBhQiA9IGN1cnJlbnRUO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYUEgPSBjdXJyZW50VDtcbiAgICAgIH1cbiAgICB9IHdoaWxlIChNYXRoLmFicyhjdXJyZW50WCkgPiBTVUJESVZJU0lPTl9QUkVDSVNJT04gJiYgKytpIDwgU1VCRElWSVNJT05fTUFYX0lURVJBVElPTlMpO1xuXG4gICAgcmV0dXJuIGN1cnJlbnRUO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0VEZvclgoYVgpIHtcbiAgICB2YXIgaW50ZXJ2YWxTdGFydCA9IDAuMCxcbiAgICAgICAgY3VycmVudFNhbXBsZSA9IDEsXG4gICAgICAgIGxhc3RTYW1wbGUgPSBrU3BsaW5lVGFibGVTaXplIC0gMTtcblxuICAgIGZvciAoOyBjdXJyZW50U2FtcGxlICE9PSBsYXN0U2FtcGxlICYmIG1TYW1wbGVWYWx1ZXNbY3VycmVudFNhbXBsZV0gPD0gYVg7ICsrY3VycmVudFNhbXBsZSkge1xuICAgICAgaW50ZXJ2YWxTdGFydCArPSBrU2FtcGxlU3RlcFNpemU7XG4gICAgfVxuXG4gICAgLS1jdXJyZW50U2FtcGxlO1xuICAgIHZhciBkaXN0ID0gKGFYIC0gbVNhbXBsZVZhbHVlc1tjdXJyZW50U2FtcGxlXSkgLyAobVNhbXBsZVZhbHVlc1tjdXJyZW50U2FtcGxlICsgMV0gLSBtU2FtcGxlVmFsdWVzW2N1cnJlbnRTYW1wbGVdKSxcbiAgICAgICAgZ3Vlc3NGb3JUID0gaW50ZXJ2YWxTdGFydCArIGRpc3QgKiBrU2FtcGxlU3RlcFNpemUsXG4gICAgICAgIGluaXRpYWxTbG9wZSA9IGdldFNsb3BlKGd1ZXNzRm9yVCwgbVgxLCBtWDIpO1xuXG4gICAgaWYgKGluaXRpYWxTbG9wZSA+PSBORVdUT05fTUlOX1NMT1BFKSB7XG4gICAgICByZXR1cm4gbmV3dG9uUmFwaHNvbkl0ZXJhdGUoYVgsIGd1ZXNzRm9yVCk7XG4gICAgfSBlbHNlIGlmIChpbml0aWFsU2xvcGUgPT09IDAuMCkge1xuICAgICAgcmV0dXJuIGd1ZXNzRm9yVDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGJpbmFyeVN1YmRpdmlkZShhWCwgaW50ZXJ2YWxTdGFydCwgaW50ZXJ2YWxTdGFydCArIGtTYW1wbGVTdGVwU2l6ZSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIF9wcmVjb21wdXRlZCA9IGZhbHNlO1xuXG4gIGZ1bmN0aW9uIHByZWNvbXB1dGUoKSB7XG4gICAgX3ByZWNvbXB1dGVkID0gdHJ1ZTtcblxuICAgIGlmIChtWDEgIT09IG1ZMSB8fCBtWDIgIT09IG1ZMikge1xuICAgICAgY2FsY1NhbXBsZVZhbHVlcygpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBmID0gZnVuY3Rpb24gZihhWCkge1xuICAgIGlmICghX3ByZWNvbXB1dGVkKSB7XG4gICAgICBwcmVjb21wdXRlKCk7XG4gICAgfVxuXG4gICAgaWYgKG1YMSA9PT0gbVkxICYmIG1YMiA9PT0gbVkyKSB7XG4gICAgICByZXR1cm4gYVg7XG4gICAgfVxuXG4gICAgaWYgKGFYID09PSAwKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBpZiAoYVggPT09IDEpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIHJldHVybiBjYWxjQmV6aWVyKGdldFRGb3JYKGFYKSwgbVkxLCBtWTIpO1xuICB9O1xuXG4gIGYuZ2V0Q29udHJvbFBvaW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gW3tcbiAgICAgIHg6IG1YMSxcbiAgICAgIHk6IG1ZMVxuICAgIH0sIHtcbiAgICAgIHg6IG1YMixcbiAgICAgIHk6IG1ZMlxuICAgIH1dO1xuICB9O1xuXG4gIHZhciBzdHIgPSBcImdlbmVyYXRlQmV6aWVyKFwiICsgW21YMSwgbVkxLCBtWDIsIG1ZMl0gKyBcIilcIjtcblxuICBmLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBzdHI7XG4gIH07XG5cbiAgcmV0dXJuIGY7XG59XG5cbi8qISBSdW5nZS1LdXR0YSBzcHJpbmcgcGh5c2ljcyBmdW5jdGlvbiBnZW5lcmF0b3IuIEFkYXB0ZWQgZnJvbSBGcmFtZXIuanMsIGNvcHlyaWdodCBLb2VuIEJvay4gTUlUIExpY2Vuc2U6IGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTUlUX0xpY2Vuc2UgKi9cblxuLyogR2l2ZW4gYSB0ZW5zaW9uLCBmcmljdGlvbiwgYW5kIGR1cmF0aW9uLCBhIHNpbXVsYXRpb24gYXQgNjBGUFMgd2lsbCBmaXJzdCBydW4gd2l0aG91dCBhIGRlZmluZWQgZHVyYXRpb24gaW4gb3JkZXIgdG8gY2FsY3VsYXRlIHRoZSBmdWxsIHBhdGguIEEgc2Vjb25kIHBhc3NcbiAgIHRoZW4gYWRqdXN0cyB0aGUgdGltZSBkZWx0YSAtLSB1c2luZyB0aGUgcmVsYXRpb24gYmV0d2VlbiBhY3R1YWwgdGltZSBhbmQgZHVyYXRpb24gLS0gdG8gY2FsY3VsYXRlIHRoZSBwYXRoIGZvciB0aGUgZHVyYXRpb24tY29uc3RyYWluZWQgYW5pbWF0aW9uLiAqL1xudmFyIGdlbmVyYXRlU3ByaW5nUks0ID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBzcHJpbmdBY2NlbGVyYXRpb25Gb3JTdGF0ZShzdGF0ZSkge1xuICAgIHJldHVybiAtc3RhdGUudGVuc2lvbiAqIHN0YXRlLnggLSBzdGF0ZS5mcmljdGlvbiAqIHN0YXRlLnY7XG4gIH1cblxuICBmdW5jdGlvbiBzcHJpbmdFdmFsdWF0ZVN0YXRlV2l0aERlcml2YXRpdmUoaW5pdGlhbFN0YXRlLCBkdCwgZGVyaXZhdGl2ZSkge1xuICAgIHZhciBzdGF0ZSA9IHtcbiAgICAgIHg6IGluaXRpYWxTdGF0ZS54ICsgZGVyaXZhdGl2ZS5keCAqIGR0LFxuICAgICAgdjogaW5pdGlhbFN0YXRlLnYgKyBkZXJpdmF0aXZlLmR2ICogZHQsXG4gICAgICB0ZW5zaW9uOiBpbml0aWFsU3RhdGUudGVuc2lvbixcbiAgICAgIGZyaWN0aW9uOiBpbml0aWFsU3RhdGUuZnJpY3Rpb25cbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBkeDogc3RhdGUudixcbiAgICAgIGR2OiBzcHJpbmdBY2NlbGVyYXRpb25Gb3JTdGF0ZShzdGF0ZSlcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gc3ByaW5nSW50ZWdyYXRlU3RhdGUoc3RhdGUsIGR0KSB7XG4gICAgdmFyIGEgPSB7XG4gICAgICBkeDogc3RhdGUudixcbiAgICAgIGR2OiBzcHJpbmdBY2NlbGVyYXRpb25Gb3JTdGF0ZShzdGF0ZSlcbiAgICB9LFxuICAgICAgICBiID0gc3ByaW5nRXZhbHVhdGVTdGF0ZVdpdGhEZXJpdmF0aXZlKHN0YXRlLCBkdCAqIDAuNSwgYSksXG4gICAgICAgIGMgPSBzcHJpbmdFdmFsdWF0ZVN0YXRlV2l0aERlcml2YXRpdmUoc3RhdGUsIGR0ICogMC41LCBiKSxcbiAgICAgICAgZCA9IHNwcmluZ0V2YWx1YXRlU3RhdGVXaXRoRGVyaXZhdGl2ZShzdGF0ZSwgZHQsIGMpLFxuICAgICAgICBkeGR0ID0gMS4wIC8gNi4wICogKGEuZHggKyAyLjAgKiAoYi5keCArIGMuZHgpICsgZC5keCksXG4gICAgICAgIGR2ZHQgPSAxLjAgLyA2LjAgKiAoYS5kdiArIDIuMCAqIChiLmR2ICsgYy5kdikgKyBkLmR2KTtcbiAgICBzdGF0ZS54ID0gc3RhdGUueCArIGR4ZHQgKiBkdDtcbiAgICBzdGF0ZS52ID0gc3RhdGUudiArIGR2ZHQgKiBkdDtcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gc3ByaW5nUks0RmFjdG9yeSh0ZW5zaW9uLCBmcmljdGlvbiwgZHVyYXRpb24pIHtcbiAgICB2YXIgaW5pdFN0YXRlID0ge1xuICAgICAgeDogLTEsXG4gICAgICB2OiAwLFxuICAgICAgdGVuc2lvbjogbnVsbCxcbiAgICAgIGZyaWN0aW9uOiBudWxsXG4gICAgfSxcbiAgICAgICAgcGF0aCA9IFswXSxcbiAgICAgICAgdGltZV9sYXBzZWQgPSAwLFxuICAgICAgICB0b2xlcmFuY2UgPSAxIC8gMTAwMDAsXG4gICAgICAgIERUID0gMTYgLyAxMDAwLFxuICAgICAgICBoYXZlX2R1cmF0aW9uLFxuICAgICAgICBkdCxcbiAgICAgICAgbGFzdF9zdGF0ZTtcbiAgICB0ZW5zaW9uID0gcGFyc2VGbG9hdCh0ZW5zaW9uKSB8fCA1MDA7XG4gICAgZnJpY3Rpb24gPSBwYXJzZUZsb2F0KGZyaWN0aW9uKSB8fCAyMDtcbiAgICBkdXJhdGlvbiA9IGR1cmF0aW9uIHx8IG51bGw7XG4gICAgaW5pdFN0YXRlLnRlbnNpb24gPSB0ZW5zaW9uO1xuICAgIGluaXRTdGF0ZS5mcmljdGlvbiA9IGZyaWN0aW9uO1xuICAgIGhhdmVfZHVyYXRpb24gPSBkdXJhdGlvbiAhPT0gbnVsbDtcbiAgICAvKiBDYWxjdWxhdGUgdGhlIGFjdHVhbCB0aW1lIGl0IHRha2VzIGZvciB0aGlzIGFuaW1hdGlvbiB0byBjb21wbGV0ZSB3aXRoIHRoZSBwcm92aWRlZCBjb25kaXRpb25zLiAqL1xuXG4gICAgaWYgKGhhdmVfZHVyYXRpb24pIHtcbiAgICAgIC8qIFJ1biB0aGUgc2ltdWxhdGlvbiB3aXRob3V0IGEgZHVyYXRpb24uICovXG4gICAgICB0aW1lX2xhcHNlZCA9IHNwcmluZ1JLNEZhY3RvcnkodGVuc2lvbiwgZnJpY3Rpb24pO1xuICAgICAgLyogQ29tcHV0ZSB0aGUgYWRqdXN0ZWQgdGltZSBkZWx0YS4gKi9cblxuICAgICAgZHQgPSB0aW1lX2xhcHNlZCAvIGR1cmF0aW9uICogRFQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGR0ID0gRFQ7XG4gICAgfVxuXG4gICAgZm9yICg7Oykge1xuICAgICAgLyogTmV4dC9zdGVwIGZ1bmN0aW9uIC4qL1xuICAgICAgbGFzdF9zdGF0ZSA9IHNwcmluZ0ludGVncmF0ZVN0YXRlKGxhc3Rfc3RhdGUgfHwgaW5pdFN0YXRlLCBkdCk7XG4gICAgICAvKiBTdG9yZSB0aGUgcG9zaXRpb24uICovXG5cbiAgICAgIHBhdGgucHVzaCgxICsgbGFzdF9zdGF0ZS54KTtcbiAgICAgIHRpbWVfbGFwc2VkICs9IDE2O1xuICAgICAgLyogSWYgdGhlIGNoYW5nZSB0aHJlc2hvbGQgaXMgcmVhY2hlZCwgYnJlYWsuICovXG5cbiAgICAgIGlmICghKE1hdGguYWJzKGxhc3Rfc3RhdGUueCkgPiB0b2xlcmFuY2UgJiYgTWF0aC5hYnMobGFzdF9zdGF0ZS52KSA+IHRvbGVyYW5jZSkpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIC8qIElmIGR1cmF0aW9uIGlzIG5vdCBkZWZpbmVkLCByZXR1cm4gdGhlIGFjdHVhbCB0aW1lIHJlcXVpcmVkIGZvciBjb21wbGV0aW5nIHRoaXMgYW5pbWF0aW9uLiBPdGhlcndpc2UsIHJldHVybiBhIGNsb3N1cmUgdGhhdCBob2xkcyB0aGVcbiAgICAgICBjb21wdXRlZCBwYXRoIGFuZCByZXR1cm5zIGEgc25hcHNob3Qgb2YgdGhlIHBvc2l0aW9uIGFjY29yZGluZyB0byBhIGdpdmVuIHBlcmNlbnRDb21wbGV0ZS4gKi9cblxuXG4gICAgcmV0dXJuICFoYXZlX2R1cmF0aW9uID8gdGltZV9sYXBzZWQgOiBmdW5jdGlvbiAocGVyY2VudENvbXBsZXRlKSB7XG4gICAgICByZXR1cm4gcGF0aFtwZXJjZW50Q29tcGxldGUgKiAocGF0aC5sZW5ndGggLSAxKSB8IDBdO1xuICAgIH07XG4gIH07XG59KCk7XG5cbnZhciBjdWJpY0JlemllciA9IGZ1bmN0aW9uIGN1YmljQmV6aWVyKHQxLCBwMSwgdDIsIHAyKSB7XG4gIHZhciBiZXppZXIgPSBnZW5lcmF0ZUN1YmljQmV6aWVyKHQxLCBwMSwgdDIsIHAyKTtcbiAgcmV0dXJuIGZ1bmN0aW9uIChzdGFydCwgZW5kLCBwZXJjZW50KSB7XG4gICAgcmV0dXJuIHN0YXJ0ICsgKGVuZCAtIHN0YXJ0KSAqIGJlemllcihwZXJjZW50KTtcbiAgfTtcbn07XG5cbnZhciBlYXNpbmdzID0ge1xuICAnbGluZWFyJzogZnVuY3Rpb24gbGluZWFyKHN0YXJ0LCBlbmQsIHBlcmNlbnQpIHtcbiAgICByZXR1cm4gc3RhcnQgKyAoZW5kIC0gc3RhcnQpICogcGVyY2VudDtcbiAgfSxcbiAgLy8gZGVmYXVsdCBlYXNpbmdzXG4gICdlYXNlJzogY3ViaWNCZXppZXIoMC4yNSwgMC4xLCAwLjI1LCAxKSxcbiAgJ2Vhc2UtaW4nOiBjdWJpY0JlemllcigwLjQyLCAwLCAxLCAxKSxcbiAgJ2Vhc2Utb3V0JzogY3ViaWNCZXppZXIoMCwgMCwgMC41OCwgMSksXG4gICdlYXNlLWluLW91dCc6IGN1YmljQmV6aWVyKDAuNDIsIDAsIDAuNTgsIDEpLFxuICAvLyBzaW5lXG4gICdlYXNlLWluLXNpbmUnOiBjdWJpY0JlemllcigwLjQ3LCAwLCAwLjc0NSwgMC43MTUpLFxuICAnZWFzZS1vdXQtc2luZSc6IGN1YmljQmV6aWVyKDAuMzksIDAuNTc1LCAwLjU2NSwgMSksXG4gICdlYXNlLWluLW91dC1zaW5lJzogY3ViaWNCZXppZXIoMC40NDUsIDAuMDUsIDAuNTUsIDAuOTUpLFxuICAvLyBxdWFkXG4gICdlYXNlLWluLXF1YWQnOiBjdWJpY0JlemllcigwLjU1LCAwLjA4NSwgMC42OCwgMC41MyksXG4gICdlYXNlLW91dC1xdWFkJzogY3ViaWNCZXppZXIoMC4yNSwgMC40NiwgMC40NSwgMC45NCksXG4gICdlYXNlLWluLW91dC1xdWFkJzogY3ViaWNCZXppZXIoMC40NTUsIDAuMDMsIDAuNTE1LCAwLjk1NSksXG4gIC8vIGN1YmljXG4gICdlYXNlLWluLWN1YmljJzogY3ViaWNCZXppZXIoMC41NSwgMC4wNTUsIDAuNjc1LCAwLjE5KSxcbiAgJ2Vhc2Utb3V0LWN1YmljJzogY3ViaWNCZXppZXIoMC4yMTUsIDAuNjEsIDAuMzU1LCAxKSxcbiAgJ2Vhc2UtaW4tb3V0LWN1YmljJzogY3ViaWNCZXppZXIoMC42NDUsIDAuMDQ1LCAwLjM1NSwgMSksXG4gIC8vIHF1YXJ0XG4gICdlYXNlLWluLXF1YXJ0JzogY3ViaWNCZXppZXIoMC44OTUsIDAuMDMsIDAuNjg1LCAwLjIyKSxcbiAgJ2Vhc2Utb3V0LXF1YXJ0JzogY3ViaWNCZXppZXIoMC4xNjUsIDAuODQsIDAuNDQsIDEpLFxuICAnZWFzZS1pbi1vdXQtcXVhcnQnOiBjdWJpY0JlemllcigwLjc3LCAwLCAwLjE3NSwgMSksXG4gIC8vIHF1aW50XG4gICdlYXNlLWluLXF1aW50JzogY3ViaWNCZXppZXIoMC43NTUsIDAuMDUsIDAuODU1LCAwLjA2KSxcbiAgJ2Vhc2Utb3V0LXF1aW50JzogY3ViaWNCZXppZXIoMC4yMywgMSwgMC4zMiwgMSksXG4gICdlYXNlLWluLW91dC1xdWludCc6IGN1YmljQmV6aWVyKDAuODYsIDAsIDAuMDcsIDEpLFxuICAvLyBleHBvXG4gICdlYXNlLWluLWV4cG8nOiBjdWJpY0JlemllcigwLjk1LCAwLjA1LCAwLjc5NSwgMC4wMzUpLFxuICAnZWFzZS1vdXQtZXhwbyc6IGN1YmljQmV6aWVyKDAuMTksIDEsIDAuMjIsIDEpLFxuICAnZWFzZS1pbi1vdXQtZXhwbyc6IGN1YmljQmV6aWVyKDEsIDAsIDAsIDEpLFxuICAvLyBjaXJjXG4gICdlYXNlLWluLWNpcmMnOiBjdWJpY0JlemllcigwLjYsIDAuMDQsIDAuOTgsIDAuMzM1KSxcbiAgJ2Vhc2Utb3V0LWNpcmMnOiBjdWJpY0JlemllcigwLjA3NSwgMC44MiwgMC4xNjUsIDEpLFxuICAnZWFzZS1pbi1vdXQtY2lyYyc6IGN1YmljQmV6aWVyKDAuNzg1LCAwLjEzNSwgMC4xNSwgMC44NiksXG4gIC8vIHVzZXIgcGFyYW0gZWFzaW5ncy4uLlxuICAnc3ByaW5nJzogZnVuY3Rpb24gc3ByaW5nKHRlbnNpb24sIGZyaWN0aW9uLCBkdXJhdGlvbikge1xuICAgIGlmIChkdXJhdGlvbiA9PT0gMCkge1xuICAgICAgLy8gY2FuJ3QgZ2V0IGEgc3ByaW5nIHcvIGR1cmF0aW9uIDBcbiAgICAgIHJldHVybiBlYXNpbmdzLmxpbmVhcjsgLy8gZHVyYXRpb24gMCA9PiBqdW1wIHRvIGVuZCBzbyBpbXBsIGRvZXNuJ3QgbWF0dGVyXG4gICAgfVxuXG4gICAgdmFyIHNwcmluZyA9IGdlbmVyYXRlU3ByaW5nUks0KHRlbnNpb24sIGZyaWN0aW9uLCBkdXJhdGlvbik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChzdGFydCwgZW5kLCBwZXJjZW50KSB7XG4gICAgICByZXR1cm4gc3RhcnQgKyAoZW5kIC0gc3RhcnQpICogc3ByaW5nKHBlcmNlbnQpO1xuICAgIH07XG4gIH0sXG4gICdjdWJpYy1iZXppZXInOiBjdWJpY0JlemllclxufTtcblxuZnVuY3Rpb24gZ2V0RWFzZWRWYWx1ZSh0eXBlLCBzdGFydCwgZW5kLCBwZXJjZW50LCBlYXNpbmdGbikge1xuICBpZiAocGVyY2VudCA9PT0gMSkge1xuICAgIHJldHVybiBlbmQ7XG4gIH1cblxuICBpZiAoc3RhcnQgPT09IGVuZCkge1xuICAgIHJldHVybiBlbmQ7XG4gIH1cblxuICB2YXIgdmFsID0gZWFzaW5nRm4oc3RhcnQsIGVuZCwgcGVyY2VudCk7XG5cbiAgaWYgKHR5cGUgPT0gbnVsbCkge1xuICAgIHJldHVybiB2YWw7XG4gIH1cblxuICBpZiAodHlwZS5yb3VuZFZhbHVlIHx8IHR5cGUuY29sb3IpIHtcbiAgICB2YWwgPSBNYXRoLnJvdW5kKHZhbCk7XG4gIH1cblxuICBpZiAodHlwZS5taW4gIT09IHVuZGVmaW5lZCkge1xuICAgIHZhbCA9IE1hdGgubWF4KHZhbCwgdHlwZS5taW4pO1xuICB9XG5cbiAgaWYgKHR5cGUubWF4ICE9PSB1bmRlZmluZWQpIHtcbiAgICB2YWwgPSBNYXRoLm1pbih2YWwsIHR5cGUubWF4KTtcbiAgfVxuXG4gIHJldHVybiB2YWw7XG59XG5cbmZ1bmN0aW9uIGdldFZhbHVlKHByb3AsIHNwZWMpIHtcbiAgaWYgKHByb3AucGZWYWx1ZSAhPSBudWxsIHx8IHByb3AudmFsdWUgIT0gbnVsbCkge1xuICAgIGlmIChwcm9wLnBmVmFsdWUgIT0gbnVsbCAmJiAoc3BlYyA9PSBudWxsIHx8IHNwZWMudHlwZS51bml0cyAhPT0gJyUnKSkge1xuICAgICAgcmV0dXJuIHByb3AucGZWYWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb3AudmFsdWU7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBwcm9wO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVhc2Uoc3RhcnRQcm9wLCBlbmRQcm9wLCBwZXJjZW50LCBlYXNpbmdGbiwgcHJvcFNwZWMpIHtcbiAgdmFyIHR5cGUgPSBwcm9wU3BlYyAhPSBudWxsID8gcHJvcFNwZWMudHlwZSA6IG51bGw7XG5cbiAgaWYgKHBlcmNlbnQgPCAwKSB7XG4gICAgcGVyY2VudCA9IDA7XG4gIH0gZWxzZSBpZiAocGVyY2VudCA+IDEpIHtcbiAgICBwZXJjZW50ID0gMTtcbiAgfVxuXG4gIHZhciBzdGFydCA9IGdldFZhbHVlKHN0YXJ0UHJvcCwgcHJvcFNwZWMpO1xuICB2YXIgZW5kID0gZ2V0VmFsdWUoZW5kUHJvcCwgcHJvcFNwZWMpO1xuXG4gIGlmIChudW1iZXIoc3RhcnQpICYmIG51bWJlcihlbmQpKSB7XG4gICAgcmV0dXJuIGdldEVhc2VkVmFsdWUodHlwZSwgc3RhcnQsIGVuZCwgcGVyY2VudCwgZWFzaW5nRm4pO1xuICB9IGVsc2UgaWYgKGFycmF5KHN0YXJ0KSAmJiBhcnJheShlbmQpKSB7XG4gICAgdmFyIGVhc2VkQXJyID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVuZC5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHNpID0gc3RhcnRbaV07XG4gICAgICB2YXIgZWkgPSBlbmRbaV07XG5cbiAgICAgIGlmIChzaSAhPSBudWxsICYmIGVpICE9IG51bGwpIHtcbiAgICAgICAgdmFyIHZhbCA9IGdldEVhc2VkVmFsdWUodHlwZSwgc2ksIGVpLCBwZXJjZW50LCBlYXNpbmdGbik7XG4gICAgICAgIGVhc2VkQXJyLnB1c2godmFsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVhc2VkQXJyLnB1c2goZWkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBlYXNlZEFycjtcbiAgfVxuXG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHN0ZXAoc2VsZiwgYW5pLCBub3csIGlzQ29yZSkge1xuICB2YXIgaXNFbGVzID0gIWlzQ29yZTtcbiAgdmFyIF9wID0gc2VsZi5fcHJpdmF0ZTtcbiAgdmFyIGFuaV9wID0gYW5pLl9wcml2YXRlO1xuICB2YXIgcEVhc2luZyA9IGFuaV9wLmVhc2luZztcbiAgdmFyIHN0YXJ0VGltZSA9IGFuaV9wLnN0YXJ0VGltZTtcbiAgdmFyIGN5ID0gaXNDb3JlID8gc2VsZiA6IHNlbGYuY3koKTtcbiAgdmFyIHN0eWxlID0gY3kuc3R5bGUoKTtcblxuICBpZiAoIWFuaV9wLmVhc2luZ0ltcGwpIHtcbiAgICBpZiAocEVhc2luZyA9PSBudWxsKSB7XG4gICAgICAvLyB1c2UgZGVmYXVsdFxuICAgICAgYW5pX3AuZWFzaW5nSW1wbCA9IGVhc2luZ3NbJ2xpbmVhciddO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyB0aGVuIGRlZmluZSB3LyBuYW1lXG4gICAgICB2YXIgZWFzaW5nVmFscztcblxuICAgICAgaWYgKHN0cmluZyhwRWFzaW5nKSkge1xuICAgICAgICB2YXIgZWFzaW5nUHJvcCA9IHN0eWxlLnBhcnNlKCd0cmFuc2l0aW9uLXRpbWluZy1mdW5jdGlvbicsIHBFYXNpbmcpO1xuICAgICAgICBlYXNpbmdWYWxzID0gZWFzaW5nUHJvcC52YWx1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRoZW4gYXNzdW1lIHByZXBhcnNlZCBhcnJheVxuICAgICAgICBlYXNpbmdWYWxzID0gcEVhc2luZztcbiAgICAgIH1cblxuICAgICAgdmFyIG5hbWUsIGFyZ3M7XG5cbiAgICAgIGlmIChzdHJpbmcoZWFzaW5nVmFscykpIHtcbiAgICAgICAgbmFtZSA9IGVhc2luZ1ZhbHM7XG4gICAgICAgIGFyZ3MgPSBbXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hbWUgPSBlYXNpbmdWYWxzWzFdO1xuICAgICAgICBhcmdzID0gZWFzaW5nVmFscy5zbGljZSgyKS5tYXAoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICByZXR1cm4gK247XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoYXJncy5sZW5ndGggPiAwKSB7XG4gICAgICAgIC8vIGNyZWF0ZSB3aXRoIGFyZ3NcbiAgICAgICAgaWYgKG5hbWUgPT09ICdzcHJpbmcnKSB7XG4gICAgICAgICAgYXJncy5wdXNoKGFuaV9wLmR1cmF0aW9uKTsgLy8gbmVlZCBkdXJhdGlvbiB0byBnZW5lcmF0ZSBzcHJpbmdcbiAgICAgICAgfVxuXG4gICAgICAgIGFuaV9wLmVhc2luZ0ltcGwgPSBlYXNpbmdzW25hbWVdLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gc3RhdGljIGltcGwgYnkgbmFtZVxuICAgICAgICBhbmlfcC5lYXNpbmdJbXBsID0gZWFzaW5nc1tuYW1lXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB2YXIgZWFzaW5nID0gYW5pX3AuZWFzaW5nSW1wbDtcbiAgdmFyIHBlcmNlbnQ7XG5cbiAgaWYgKGFuaV9wLmR1cmF0aW9uID09PSAwKSB7XG4gICAgcGVyY2VudCA9IDE7XG4gIH0gZWxzZSB7XG4gICAgcGVyY2VudCA9IChub3cgLSBzdGFydFRpbWUpIC8gYW5pX3AuZHVyYXRpb247XG4gIH1cblxuICBpZiAoYW5pX3AuYXBwbHlpbmcpIHtcbiAgICBwZXJjZW50ID0gYW5pX3AucHJvZ3Jlc3M7XG4gIH1cblxuICBpZiAocGVyY2VudCA8IDApIHtcbiAgICBwZXJjZW50ID0gMDtcbiAgfSBlbHNlIGlmIChwZXJjZW50ID4gMSkge1xuICAgIHBlcmNlbnQgPSAxO1xuICB9XG5cbiAgaWYgKGFuaV9wLmRlbGF5ID09IG51bGwpIHtcbiAgICAvLyB0aGVuIHVwZGF0ZVxuICAgIHZhciBzdGFydFBvcyA9IGFuaV9wLnN0YXJ0UG9zaXRpb247XG4gICAgdmFyIGVuZFBvcyA9IGFuaV9wLnBvc2l0aW9uO1xuXG4gICAgaWYgKGVuZFBvcyAmJiBpc0VsZXMgJiYgIXNlbGYubG9ja2VkKCkpIHtcbiAgICAgIHZhciBuZXdQb3MgPSB7fTtcblxuICAgICAgaWYgKHZhbGlkKHN0YXJ0UG9zLngsIGVuZFBvcy54KSkge1xuICAgICAgICBuZXdQb3MueCA9IGVhc2Uoc3RhcnRQb3MueCwgZW5kUG9zLngsIHBlcmNlbnQsIGVhc2luZyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh2YWxpZChzdGFydFBvcy55LCBlbmRQb3MueSkpIHtcbiAgICAgICAgbmV3UG9zLnkgPSBlYXNlKHN0YXJ0UG9zLnksIGVuZFBvcy55LCBwZXJjZW50LCBlYXNpbmcpO1xuICAgICAgfVxuXG4gICAgICBzZWxmLnBvc2l0aW9uKG5ld1Bvcyk7XG4gICAgfVxuXG4gICAgdmFyIHN0YXJ0UGFuID0gYW5pX3Auc3RhcnRQYW47XG4gICAgdmFyIGVuZFBhbiA9IGFuaV9wLnBhbjtcbiAgICB2YXIgcGFuID0gX3AucGFuO1xuICAgIHZhciBhbmltYXRpbmdQYW4gPSBlbmRQYW4gIT0gbnVsbCAmJiBpc0NvcmU7XG5cbiAgICBpZiAoYW5pbWF0aW5nUGFuKSB7XG4gICAgICBpZiAodmFsaWQoc3RhcnRQYW4ueCwgZW5kUGFuLngpKSB7XG4gICAgICAgIHBhbi54ID0gZWFzZShzdGFydFBhbi54LCBlbmRQYW4ueCwgcGVyY2VudCwgZWFzaW5nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHZhbGlkKHN0YXJ0UGFuLnksIGVuZFBhbi55KSkge1xuICAgICAgICBwYW4ueSA9IGVhc2Uoc3RhcnRQYW4ueSwgZW5kUGFuLnksIHBlcmNlbnQsIGVhc2luZyk7XG4gICAgICB9XG5cbiAgICAgIHNlbGYuZW1pdCgncGFuJyk7XG4gICAgfVxuXG4gICAgdmFyIHN0YXJ0Wm9vbSA9IGFuaV9wLnN0YXJ0Wm9vbTtcbiAgICB2YXIgZW5kWm9vbSA9IGFuaV9wLnpvb207XG4gICAgdmFyIGFuaW1hdGluZ1pvb20gPSBlbmRab29tICE9IG51bGwgJiYgaXNDb3JlO1xuXG4gICAgaWYgKGFuaW1hdGluZ1pvb20pIHtcbiAgICAgIGlmICh2YWxpZChzdGFydFpvb20sIGVuZFpvb20pKSB7XG4gICAgICAgIF9wLnpvb20gPSBib3VuZChfcC5taW5ab29tLCBlYXNlKHN0YXJ0Wm9vbSwgZW5kWm9vbSwgcGVyY2VudCwgZWFzaW5nKSwgX3AubWF4Wm9vbSk7XG4gICAgICB9XG5cbiAgICAgIHNlbGYuZW1pdCgnem9vbScpO1xuICAgIH1cblxuICAgIGlmIChhbmltYXRpbmdQYW4gfHwgYW5pbWF0aW5nWm9vbSkge1xuICAgICAgc2VsZi5lbWl0KCd2aWV3cG9ydCcpO1xuICAgIH1cblxuICAgIHZhciBwcm9wcyA9IGFuaV9wLnN0eWxlO1xuXG4gICAgaWYgKHByb3BzICYmIHByb3BzLmxlbmd0aCA+IDAgJiYgaXNFbGVzKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwcm9wID0gcHJvcHNbaV07XG4gICAgICAgIHZhciBfbmFtZSA9IHByb3AubmFtZTtcbiAgICAgICAgdmFyIGVuZCA9IHByb3A7XG4gICAgICAgIHZhciBzdGFydCA9IGFuaV9wLnN0YXJ0U3R5bGVbX25hbWVdO1xuICAgICAgICB2YXIgcHJvcFNwZWMgPSBzdHlsZS5wcm9wZXJ0aWVzW3N0YXJ0Lm5hbWVdO1xuICAgICAgICB2YXIgZWFzZWRWYWwgPSBlYXNlKHN0YXJ0LCBlbmQsIHBlcmNlbnQsIGVhc2luZywgcHJvcFNwZWMpO1xuICAgICAgICBzdHlsZS5vdmVycmlkZUJ5cGFzcyhzZWxmLCBfbmFtZSwgZWFzZWRWYWwpO1xuICAgICAgfSAvLyBmb3IgcHJvcHNcblxuXG4gICAgICBzZWxmLmVtaXQoJ3N0eWxlJyk7XG4gICAgfSAvLyBpZlxuXG4gIH1cblxuICBhbmlfcC5wcm9ncmVzcyA9IHBlcmNlbnQ7XG4gIHJldHVybiBwZXJjZW50O1xufVxuXG5mdW5jdGlvbiB2YWxpZChzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PSBudWxsIHx8IGVuZCA9PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKG51bWJlcihzdGFydCkgJiYgbnVtYmVyKGVuZCkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmIChzdGFydCAmJiBlbmQpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gc3RhcnRBbmltYXRpb24oc2VsZiwgYW5pLCBub3csIGlzQ29yZSkge1xuICB2YXIgYW5pX3AgPSBhbmkuX3ByaXZhdGU7XG4gIGFuaV9wLnN0YXJ0ZWQgPSB0cnVlO1xuICBhbmlfcC5zdGFydFRpbWUgPSBub3cgLSBhbmlfcC5wcm9ncmVzcyAqIGFuaV9wLmR1cmF0aW9uO1xufVxuXG5mdW5jdGlvbiBzdGVwQWxsKG5vdywgY3kpIHtcbiAgdmFyIGVsZXMgPSBjeS5fcHJpdmF0ZS5hbmlFbGVzO1xuICB2YXIgZG9uZUVsZXMgPSBbXTtcblxuICBmdW5jdGlvbiBzdGVwT25lKGVsZSwgaXNDb3JlKSB7XG4gICAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICAgIHZhciBjdXJyZW50ID0gX3AuYW5pbWF0aW9uLmN1cnJlbnQ7XG4gICAgdmFyIHF1ZXVlID0gX3AuYW5pbWF0aW9uLnF1ZXVlO1xuICAgIHZhciByYW5BbmlzID0gZmFsc2U7IC8vIGlmIG5vdGhpbmcgY3VycmVudGx5IGFuaW1hdGluZywgZ2V0IHNvbWV0aGluZyBmcm9tIHRoZSBxdWV1ZVxuXG4gICAgaWYgKGN1cnJlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgICB2YXIgbmV4dCA9IHF1ZXVlLnNoaWZ0KCk7XG5cbiAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgIGN1cnJlbnQucHVzaChuZXh0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY2FsbGJhY2tzID0gZnVuY3Rpb24gY2FsbGJhY2tzKF9jYWxsYmFja3MpIHtcbiAgICAgIGZvciAodmFyIGogPSBfY2FsbGJhY2tzLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSB7XG4gICAgICAgIHZhciBjYiA9IF9jYWxsYmFja3Nbal07XG4gICAgICAgIGNiKCk7XG4gICAgICB9XG5cbiAgICAgIF9jYWxsYmFja3Muc3BsaWNlKDAsIF9jYWxsYmFja3MubGVuZ3RoKTtcbiAgICB9OyAvLyBzdGVwIGFuZCByZW1vdmUgaWYgZG9uZVxuXG5cbiAgICBmb3IgKHZhciBpID0gY3VycmVudC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIGFuaSA9IGN1cnJlbnRbaV07XG4gICAgICB2YXIgYW5pX3AgPSBhbmkuX3ByaXZhdGU7XG5cbiAgICAgIGlmIChhbmlfcC5zdG9wcGVkKSB7XG4gICAgICAgIGN1cnJlbnQuc3BsaWNlKGksIDEpO1xuICAgICAgICBhbmlfcC5ob29rZWQgPSBmYWxzZTtcbiAgICAgICAgYW5pX3AucGxheWluZyA9IGZhbHNlO1xuICAgICAgICBhbmlfcC5zdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGNhbGxiYWNrcyhhbmlfcC5mcmFtZXMpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFhbmlfcC5wbGF5aW5nICYmICFhbmlfcC5hcHBseWluZykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH0gLy8gYW4gYXBwbHkoKSB3aGlsZSBwbGF5aW5nIHNob3VsZG4ndCBkbyBhbnl0aGluZ1xuXG5cbiAgICAgIGlmIChhbmlfcC5wbGF5aW5nICYmIGFuaV9wLmFwcGx5aW5nKSB7XG4gICAgICAgIGFuaV9wLmFwcGx5aW5nID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICghYW5pX3Auc3RhcnRlZCkge1xuICAgICAgICBzdGFydEFuaW1hdGlvbihlbGUsIGFuaSwgbm93KTtcbiAgICAgIH1cblxuICAgICAgc3RlcChlbGUsIGFuaSwgbm93LCBpc0NvcmUpO1xuXG4gICAgICBpZiAoYW5pX3AuYXBwbHlpbmcpIHtcbiAgICAgICAgYW5pX3AuYXBwbHlpbmcgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY2FsbGJhY2tzKGFuaV9wLmZyYW1lcyk7XG5cbiAgICAgIGlmIChhbmlfcC5zdGVwICE9IG51bGwpIHtcbiAgICAgICAgYW5pX3Auc3RlcChub3cpO1xuICAgICAgfVxuXG4gICAgICBpZiAoYW5pLmNvbXBsZXRlZCgpKSB7XG4gICAgICAgIGN1cnJlbnQuc3BsaWNlKGksIDEpO1xuICAgICAgICBhbmlfcC5ob29rZWQgPSBmYWxzZTtcbiAgICAgICAgYW5pX3AucGxheWluZyA9IGZhbHNlO1xuICAgICAgICBhbmlfcC5zdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGNhbGxiYWNrcyhhbmlfcC5jb21wbGV0ZXMpO1xuICAgICAgfVxuXG4gICAgICByYW5BbmlzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoIWlzQ29yZSAmJiBjdXJyZW50Lmxlbmd0aCA9PT0gMCAmJiBxdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgIGRvbmVFbGVzLnB1c2goZWxlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmFuQW5pcztcbiAgfSAvLyBzdGVwRWxlbWVudFxuICAvLyBoYW5kbGUgYWxsIGVsZXNcblxuXG4gIHZhciByYW5FbGVBbmkgPSBmYWxzZTtcblxuICBmb3IgKHZhciBlID0gMDsgZSA8IGVsZXMubGVuZ3RoOyBlKyspIHtcbiAgICB2YXIgZWxlID0gZWxlc1tlXTtcbiAgICB2YXIgaGFuZGxlZFRoaXNFbGUgPSBzdGVwT25lKGVsZSk7XG4gICAgcmFuRWxlQW5pID0gcmFuRWxlQW5pIHx8IGhhbmRsZWRUaGlzRWxlO1xuICB9IC8vIGVhY2ggZWxlbWVudFxuXG5cbiAgdmFyIHJhbkNvcmVBbmkgPSBzdGVwT25lKGN5LCB0cnVlKTsgLy8gbm90aWZ5IHJlbmRlcmVyXG5cbiAgaWYgKHJhbkVsZUFuaSB8fCByYW5Db3JlQW5pKSB7XG4gICAgaWYgKGVsZXMubGVuZ3RoID4gMCkge1xuICAgICAgY3kubm90aWZ5KCdkcmF3JywgZWxlcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN5Lm5vdGlmeSgnZHJhdycpO1xuICAgIH1cbiAgfSAvLyByZW1vdmUgZWxlbWVudHMgZnJvbSBsaXN0IG9mIGN1cnJlbnRseSBhbmltYXRpbmcgaWYgaXRzIHF1ZXVlcyBhcmUgZW1wdHlcblxuXG4gIGVsZXMudW5tZXJnZShkb25lRWxlcyk7XG4gIGN5LmVtaXQoJ3N0ZXAnKTtcbn0gLy8gc3RlcEFsbFxuXG52YXIgY29yZWZuJDEgPSB7XG4gIC8vIHB1bGwgaW4gYW5pbWF0aW9uIGZ1bmN0aW9uc1xuICBhbmltYXRlOiBkZWZpbmUkMy5hbmltYXRlKCksXG4gIGFuaW1hdGlvbjogZGVmaW5lJDMuYW5pbWF0aW9uKCksXG4gIGFuaW1hdGVkOiBkZWZpbmUkMy5hbmltYXRlZCgpLFxuICBjbGVhclF1ZXVlOiBkZWZpbmUkMy5jbGVhclF1ZXVlKCksXG4gIGRlbGF5OiBkZWZpbmUkMy5kZWxheSgpLFxuICBkZWxheUFuaW1hdGlvbjogZGVmaW5lJDMuZGVsYXlBbmltYXRpb24oKSxcbiAgc3RvcDogZGVmaW5lJDMuc3RvcCgpLFxuICBhZGRUb0FuaW1hdGlvblBvb2w6IGZ1bmN0aW9uIGFkZFRvQW5pbWF0aW9uUG9vbChlbGVzKSB7XG4gICAgdmFyIGN5ID0gdGhpcztcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9IC8vIHNhdmUgY3ljbGVzIHdoZW4gbm8gc3R5bGUgdXNlZFxuXG5cbiAgICBjeS5fcHJpdmF0ZS5hbmlFbGVzLm1lcmdlKGVsZXMpO1xuICB9LFxuICBzdG9wQW5pbWF0aW9uTG9vcDogZnVuY3Rpb24gc3RvcEFuaW1hdGlvbkxvb3AoKSB7XG4gICAgdGhpcy5fcHJpdmF0ZS5hbmltYXRpb25zUnVubmluZyA9IGZhbHNlO1xuICB9LFxuICBzdGFydEFuaW1hdGlvbkxvb3A6IGZ1bmN0aW9uIHN0YXJ0QW5pbWF0aW9uTG9vcCgpIHtcbiAgICB2YXIgY3kgPSB0aGlzO1xuICAgIGN5Ll9wcml2YXRlLmFuaW1hdGlvbnNSdW5uaW5nID0gdHJ1ZTtcblxuICAgIGlmICghY3kuc3R5bGVFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9IC8vIHNhdmUgY3ljbGVzIHdoZW4gbm8gc3R5bGUgdXNlZFxuICAgIC8vIE5CIHRoZSBhbmltYXRpb24gbG9vcCB3aWxsIGV4ZWMgaW4gaGVhZGxlc3MgZW52aXJvbm1lbnRzIGlmIHN0eWxlIGVuYWJsZWRcbiAgICAvLyBhbmQgZXhwbGljaXQgY3kuZGVzdHJveSgpIGlzIG5lY2Vzc2FyeSB0byBzdG9wIHRoZSBsb29wXG5cblxuICAgIGZ1bmN0aW9uIGhlYWRsZXNzU3RlcCgpIHtcbiAgICAgIGlmICghY3kuX3ByaXZhdGUuYW5pbWF0aW9uc1J1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZnVuY3Rpb24gYW5pbWF0aW9uU3RlcChub3cpIHtcbiAgICAgICAgc3RlcEFsbChub3csIGN5KTtcbiAgICAgICAgaGVhZGxlc3NTdGVwKCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVuZGVyZXIgPSBjeS5yZW5kZXJlcigpO1xuXG4gICAgaWYgKHJlbmRlcmVyICYmIHJlbmRlcmVyLmJlZm9yZVJlbmRlcikge1xuICAgICAgLy8gbGV0IHRoZSByZW5kZXJlciBzY2hlZHVsZSBhbmltYXRpb25zXG4gICAgICByZW5kZXJlci5iZWZvcmVSZW5kZXIoZnVuY3Rpb24gcmVuZGVyZXJBbmltYXRpb25TdGVwKHdpbGxEcmF3LCBub3cpIHtcbiAgICAgICAgc3RlcEFsbChub3csIGN5KTtcbiAgICAgIH0sIHJlbmRlcmVyLmJlZm9yZVJlbmRlclByaW9yaXRpZXMuYW5pbWF0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIG1hbmFnZSB0aGUgYW5pbWF0aW9uIGxvb3Agb3Vyc2VsdmVzXG4gICAgICBoZWFkbGVzc1N0ZXAoKTsgLy8gZmlyc3QgY2FsbFxuICAgIH1cbiAgfVxufTtcblxudmFyIGVtaXR0ZXJPcHRpb25zJDEgPSB7XG4gIHF1YWxpZmllckNvbXBhcmU6IGZ1bmN0aW9uIHF1YWxpZmllckNvbXBhcmUoc2VsZWN0b3IxLCBzZWxlY3RvcjIpIHtcbiAgICBpZiAoc2VsZWN0b3IxID09IG51bGwgfHwgc2VsZWN0b3IyID09IG51bGwpIHtcbiAgICAgIHJldHVybiBzZWxlY3RvcjEgPT0gbnVsbCAmJiBzZWxlY3RvcjIgPT0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHNlbGVjdG9yMS5zYW1lVGV4dChzZWxlY3RvcjIpO1xuICAgIH1cbiAgfSxcbiAgZXZlbnRNYXRjaGVzOiBmdW5jdGlvbiBldmVudE1hdGNoZXMoY3ksIGxpc3RlbmVyLCBldmVudE9iaikge1xuICAgIHZhciBzZWxlY3RvciA9IGxpc3RlbmVyLnF1YWxpZmllcjtcblxuICAgIGlmIChzZWxlY3RvciAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gY3kgIT09IGV2ZW50T2JqLnRhcmdldCAmJiBlbGVtZW50KGV2ZW50T2JqLnRhcmdldCkgJiYgc2VsZWN0b3IubWF0Y2hlcyhldmVudE9iai50YXJnZXQpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICBhZGRFdmVudEZpZWxkczogZnVuY3Rpb24gYWRkRXZlbnRGaWVsZHMoY3ksIGV2dCkge1xuICAgIGV2dC5jeSA9IGN5O1xuICAgIGV2dC50YXJnZXQgPSBjeTtcbiAgfSxcbiAgY2FsbGJhY2tDb250ZXh0OiBmdW5jdGlvbiBjYWxsYmFja0NvbnRleHQoY3ksIGxpc3RlbmVyLCBldmVudE9iaikge1xuICAgIHJldHVybiBsaXN0ZW5lci5xdWFsaWZpZXIgIT0gbnVsbCA/IGV2ZW50T2JqLnRhcmdldCA6IGN5O1xuICB9XG59O1xuXG52YXIgYXJnU2VsZWN0b3IkMSA9IGZ1bmN0aW9uIGFyZ1NlbGVjdG9yKGFyZykge1xuICBpZiAoc3RyaW5nKGFyZykpIHtcbiAgICByZXR1cm4gbmV3IFNlbGVjdG9yKGFyZyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGFyZztcbiAgfVxufTtcblxudmFyIGVsZXNmbiR2ID0ge1xuICBjcmVhdGVFbWl0dGVyOiBmdW5jdGlvbiBjcmVhdGVFbWl0dGVyKCkge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG5cbiAgICBpZiAoIV9wLmVtaXR0ZXIpIHtcbiAgICAgIF9wLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcihlbWl0dGVyT3B0aW9ucyQxLCB0aGlzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgZW1pdHRlcjogZnVuY3Rpb24gZW1pdHRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5lbWl0dGVyO1xuICB9LFxuICBvbjogZnVuY3Rpb24gb24oZXZlbnRzLCBzZWxlY3RvciwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmVtaXR0ZXIoKS5vbihldmVudHMsIGFyZ1NlbGVjdG9yJDEoc2VsZWN0b3IpLCBjYWxsYmFjayk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHJlbW92ZUxpc3RlbmVyOiBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldmVudHMsIHNlbGVjdG9yLCBjYWxsYmFjaykge1xuICAgIHRoaXMuZW1pdHRlcigpLnJlbW92ZUxpc3RlbmVyKGV2ZW50cywgYXJnU2VsZWN0b3IkMShzZWxlY3RvciksIGNhbGxiYWNrKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcmVtb3ZlQWxsTGlzdGVuZXJzOiBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5lbWl0dGVyKCkucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIG9uZTogZnVuY3Rpb24gb25lKGV2ZW50cywgc2VsZWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5lbWl0dGVyKCkub25lKGV2ZW50cywgYXJnU2VsZWN0b3IkMShzZWxlY3RvciksIGNhbGxiYWNrKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgb25jZTogZnVuY3Rpb24gb25jZShldmVudHMsIHNlbGVjdG9yLCBjYWxsYmFjaykge1xuICAgIHRoaXMuZW1pdHRlcigpLm9uZShldmVudHMsIGFyZ1NlbGVjdG9yJDEoc2VsZWN0b3IpLCBjYWxsYmFjayk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIGVtaXQ6IGZ1bmN0aW9uIGVtaXQoZXZlbnRzLCBleHRyYVBhcmFtcykge1xuICAgIHRoaXMuZW1pdHRlcigpLmVtaXQoZXZlbnRzLCBleHRyYVBhcmFtcyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIGVtaXRBbmROb3RpZnk6IGZ1bmN0aW9uIGVtaXRBbmROb3RpZnkoZXZlbnQsIGVsZXMpIHtcbiAgICB0aGlzLmVtaXQoZXZlbnQpO1xuICAgIHRoaXMubm90aWZ5KGV2ZW50LCBlbGVzKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxufTtcbmRlZmluZSQzLmV2ZW50QWxpYXNlc09uKGVsZXNmbiR2KTtcblxudmFyIGNvcmVmbiQyID0ge1xuICBwbmc6IGZ1bmN0aW9uIHBuZyhvcHRpb25zKSB7XG4gICAgdmFyIHJlbmRlcmVyID0gdGhpcy5fcHJpdmF0ZS5yZW5kZXJlcjtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICByZXR1cm4gcmVuZGVyZXIucG5nKG9wdGlvbnMpO1xuICB9LFxuICBqcGc6IGZ1bmN0aW9uIGpwZyhvcHRpb25zKSB7XG4gICAgdmFyIHJlbmRlcmVyID0gdGhpcy5fcHJpdmF0ZS5yZW5kZXJlcjtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICBvcHRpb25zLmJnID0gb3B0aW9ucy5iZyB8fCAnI2ZmZic7XG4gICAgcmV0dXJuIHJlbmRlcmVyLmpwZyhvcHRpb25zKTtcbiAgfVxufTtcbmNvcmVmbiQyLmpwZWcgPSBjb3JlZm4kMi5qcGc7XG5cbnZhciBjb3JlZm4kMyA9IHtcbiAgbGF5b3V0OiBmdW5jdGlvbiBsYXlvdXQob3B0aW9ucykge1xuICAgIHZhciBjeSA9IHRoaXM7XG5cbiAgICBpZiAob3B0aW9ucyA9PSBudWxsKSB7XG4gICAgICBlcnJvcignTGF5b3V0IG9wdGlvbnMgbXVzdCBiZSBzcGVjaWZpZWQgdG8gbWFrZSBhIGxheW91dCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLm5hbWUgPT0gbnVsbCkge1xuICAgICAgZXJyb3IoJ0EgYG5hbWVgIG11c3QgYmUgc3BlY2lmaWVkIHRvIG1ha2UgYSBsYXlvdXQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbmFtZSA9IG9wdGlvbnMubmFtZTtcbiAgICB2YXIgTGF5b3V0ID0gY3kuZXh0ZW5zaW9uKCdsYXlvdXQnLCBuYW1lKTtcblxuICAgIGlmIChMYXlvdXQgPT0gbnVsbCkge1xuICAgICAgZXJyb3IoJ05vIHN1Y2ggbGF5b3V0IGAnICsgbmFtZSArICdgIGZvdW5kLiAgRGlkIHlvdSBmb3JnZXQgdG8gaW1wb3J0IGl0IGFuZCBgY3l0b3NjYXBlLnVzZSgpYCBpdD8nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgZWxlcztcblxuICAgIGlmIChzdHJpbmcob3B0aW9ucy5lbGVzKSkge1xuICAgICAgZWxlcyA9IGN5LiQob3B0aW9ucy5lbGVzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZWxlcyA9IG9wdGlvbnMuZWxlcyAhPSBudWxsID8gb3B0aW9ucy5lbGVzIDogY3kuJCgpO1xuICAgIH1cblxuICAgIHZhciBsYXlvdXQgPSBuZXcgTGF5b3V0KGV4dGVuZCh7fSwgb3B0aW9ucywge1xuICAgICAgY3k6IGN5LFxuICAgICAgZWxlczogZWxlc1xuICAgIH0pKTtcbiAgICByZXR1cm4gbGF5b3V0O1xuICB9XG59O1xuY29yZWZuJDMuY3JlYXRlTGF5b3V0ID0gY29yZWZuJDMubWFrZUxheW91dCA9IGNvcmVmbiQzLmxheW91dDtcblxudmFyIGNvcmVmbiQ0ID0ge1xuICBub3RpZnk6IGZ1bmN0aW9uIG5vdGlmeShldmVudE5hbWUsIGV2ZW50RWxlcykge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG5cbiAgICBpZiAodGhpcy5iYXRjaGluZygpKSB7XG4gICAgICBfcC5iYXRjaE5vdGlmaWNhdGlvbnMgPSBfcC5iYXRjaE5vdGlmaWNhdGlvbnMgfHwge307XG4gICAgICB2YXIgZWxlcyA9IF9wLmJhdGNoTm90aWZpY2F0aW9uc1tldmVudE5hbWVdID0gX3AuYmF0Y2hOb3RpZmljYXRpb25zW2V2ZW50TmFtZV0gfHwgdGhpcy5jb2xsZWN0aW9uKCk7XG5cbiAgICAgIGlmIChldmVudEVsZXMgIT0gbnVsbCkge1xuICAgICAgICBlbGVzLm1lcmdlKGV2ZW50RWxlcyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjsgLy8gbm90aWZpY2F0aW9ucyBhcmUgZGlzYWJsZWQgZHVyaW5nIGJhdGNoaW5nXG4gICAgfVxuXG4gICAgaWYgKCFfcC5ub3RpZmljYXRpb25zRW5hYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gZXhpdCBvbiBkaXNhYmxlZFxuXG5cbiAgICB2YXIgcmVuZGVyZXIgPSB0aGlzLnJlbmRlcmVyKCk7IC8vIGV4aXQgaWYgZGVzdHJveSgpIGNhbGxlZCBvbiBjb3JlIG9yIHJlbmRlcmVyIGluIGJldHdlZW4gZnJhbWVzICMxNDk5ICMxNTI4XG5cbiAgICBpZiAodGhpcy5kZXN0cm95ZWQoKSB8fCAhcmVuZGVyZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICByZW5kZXJlci5ub3RpZnkoZXZlbnROYW1lLCBldmVudEVsZXMpO1xuICB9LFxuICBub3RpZmljYXRpb25zOiBmdW5jdGlvbiBub3RpZmljYXRpb25zKGJvb2wpIHtcbiAgICB2YXIgcCA9IHRoaXMuX3ByaXZhdGU7XG5cbiAgICBpZiAoYm9vbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcC5ub3RpZmljYXRpb25zRW5hYmxlZDtcbiAgICB9IGVsc2Uge1xuICAgICAgcC5ub3RpZmljYXRpb25zRW5hYmxlZCA9IGJvb2wgPyB0cnVlIDogZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIG5vTm90aWZpY2F0aW9uczogZnVuY3Rpb24gbm9Ob3RpZmljYXRpb25zKGNhbGxiYWNrKSB7XG4gICAgdGhpcy5ub3RpZmljYXRpb25zKGZhbHNlKTtcbiAgICBjYWxsYmFjaygpO1xuICAgIHRoaXMubm90aWZpY2F0aW9ucyh0cnVlKTtcbiAgfSxcbiAgYmF0Y2hpbmc6IGZ1bmN0aW9uIGJhdGNoaW5nKCkge1xuICAgIHJldHVybiB0aGlzLl9wcml2YXRlLmJhdGNoQ291bnQgPiAwO1xuICB9LFxuICBzdGFydEJhdGNoOiBmdW5jdGlvbiBzdGFydEJhdGNoKCkge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG5cbiAgICBpZiAoX3AuYmF0Y2hDb3VudCA9PSBudWxsKSB7XG4gICAgICBfcC5iYXRjaENvdW50ID0gMDtcbiAgICB9XG5cbiAgICBpZiAoX3AuYmF0Y2hDb3VudCA9PT0gMCkge1xuICAgICAgX3AuYmF0Y2hTdHlsZUVsZXMgPSB0aGlzLmNvbGxlY3Rpb24oKTtcbiAgICAgIF9wLmJhdGNoTm90aWZpY2F0aW9ucyA9IHt9O1xuICAgIH1cblxuICAgIF9wLmJhdGNoQ291bnQrKztcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgZW5kQmF0Y2g6IGZ1bmN0aW9uIGVuZEJhdGNoKCkge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG5cbiAgICBpZiAoX3AuYmF0Y2hDb3VudCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgX3AuYmF0Y2hDb3VudC0tO1xuXG4gICAgaWYgKF9wLmJhdGNoQ291bnQgPT09IDApIHtcbiAgICAgIC8vIHVwZGF0ZSBzdHlsZSBmb3IgZGlydHkgZWxlc1xuICAgICAgX3AuYmF0Y2hTdHlsZUVsZXMudXBkYXRlU3R5bGUoKTtcblxuICAgICAgdmFyIHJlbmRlcmVyID0gdGhpcy5yZW5kZXJlcigpOyAvLyBub3RpZnkgdGhlIHJlbmRlcmVyIG9mIHF1ZXVlZCBlbGVzIGFuZCBldmVudCB0eXBlc1xuXG4gICAgICBPYmplY3Qua2V5cyhfcC5iYXRjaE5vdGlmaWNhdGlvbnMpLmZvckVhY2goZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xuICAgICAgICB2YXIgZWxlcyA9IF9wLmJhdGNoTm90aWZpY2F0aW9uc1tldmVudE5hbWVdO1xuXG4gICAgICAgIGlmIChlbGVzLmVtcHR5KCkpIHtcbiAgICAgICAgICByZW5kZXJlci5ub3RpZnkoZXZlbnROYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZW5kZXJlci5ub3RpZnkoZXZlbnROYW1lLCBlbGVzKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIGJhdGNoOiBmdW5jdGlvbiBiYXRjaChjYWxsYmFjaykge1xuICAgIHRoaXMuc3RhcnRCYXRjaCgpO1xuICAgIGNhbGxiYWNrKCk7XG4gICAgdGhpcy5lbmRCYXRjaCgpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICAvLyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgYmF0Y2hEYXRhOiBmdW5jdGlvbiBiYXRjaERhdGEobWFwKSB7XG4gICAgdmFyIGN5ID0gdGhpcztcbiAgICByZXR1cm4gdGhpcy5iYXRjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgaWRzID0gT2JqZWN0LmtleXMobWFwKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkID0gaWRzW2ldO1xuICAgICAgICB2YXIgZGF0YSA9IG1hcFtpZF07XG4gICAgICAgIHZhciBlbGUgPSBjeS5nZXRFbGVtZW50QnlJZChpZCk7XG4gICAgICAgIGVsZS5kYXRhKGRhdGEpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59O1xuXG52YXIgcmVuZGVyZXJEZWZhdWx0cyA9IGRlZmF1bHRzKHtcbiAgaGlkZUVkZ2VzT25WaWV3cG9ydDogZmFsc2UsXG4gIHRleHR1cmVPblZpZXdwb3J0OiBmYWxzZSxcbiAgbW90aW9uQmx1cjogZmFsc2UsXG4gIG1vdGlvbkJsdXJPcGFjaXR5OiAwLjA1LFxuICBwaXhlbFJhdGlvOiB1bmRlZmluZWQsXG4gIGRlc2t0b3BUYXBUaHJlc2hvbGQ6IDQsXG4gIHRvdWNoVGFwVGhyZXNob2xkOiA4LFxuICB3aGVlbFNlbnNpdGl2aXR5OiAxLFxuICBkZWJ1ZzogZmFsc2UsXG4gIHNob3dGcHM6IGZhbHNlXG59KTtcbnZhciBjb3JlZm4kNSA9IHtcbiAgcmVuZGVyVG86IGZ1bmN0aW9uIHJlbmRlclRvKGNvbnRleHQsIHpvb20sIHBhbiwgcHhSYXRpbykge1xuICAgIHZhciByID0gdGhpcy5fcHJpdmF0ZS5yZW5kZXJlcjtcbiAgICByLnJlbmRlclRvKGNvbnRleHQsIHpvb20sIHBhbiwgcHhSYXRpbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHJlbmRlcmVyOiBmdW5jdGlvbiByZW5kZXJlcigpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5yZW5kZXJlcjtcbiAgfSxcbiAgZm9yY2VSZW5kZXI6IGZ1bmN0aW9uIGZvcmNlUmVuZGVyKCkge1xuICAgIHRoaXMubm90aWZ5KCdkcmF3Jyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHJlc2l6ZTogZnVuY3Rpb24gcmVzaXplKCkge1xuICAgIHRoaXMuaW52YWxpZGF0ZVNpemUoKTtcbiAgICB0aGlzLmVtaXRBbmROb3RpZnkoJ3Jlc2l6ZScpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBpbml0UmVuZGVyZXI6IGZ1bmN0aW9uIGluaXRSZW5kZXJlcihvcHRpb25zKSB7XG4gICAgdmFyIGN5ID0gdGhpcztcbiAgICB2YXIgUmVuZGVyZXJQcm90byA9IGN5LmV4dGVuc2lvbigncmVuZGVyZXInLCBvcHRpb25zLm5hbWUpO1xuXG4gICAgaWYgKFJlbmRlcmVyUHJvdG8gPT0gbnVsbCkge1xuICAgICAgZXJyb3IoXCJDYW4gbm90IGluaXRpYWxpc2U6IE5vIHN1Y2ggcmVuZGVyZXIgYFwiLmNvbmNhdChvcHRpb25zLm5hbWUsIFwiYCBmb3VuZC4gRGlkIHlvdSBmb3JnZXQgdG8gaW1wb3J0IGl0IGFuZCBgY3l0b3NjYXBlLnVzZSgpYCBpdD9cIikpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLndoZWVsU2Vuc2l0aXZpdHkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgd2FybihcIllvdSBoYXZlIHNldCBhIGN1c3RvbSB3aGVlbCBzZW5zaXRpdml0eS4gIFRoaXMgd2lsbCBtYWtlIHlvdXIgYXBwIHpvb20gdW5uYXR1cmFsbHkgd2hlbiB1c2luZyBtYWluc3RyZWFtIG1pY2UuICBZb3Ugc2hvdWxkIGNoYW5nZSB0aGlzIHZhbHVlIGZyb20gdGhlIGRlZmF1bHQgb25seSBpZiB5b3UgY2FuIGd1YXJhbnRlZSB0aGF0IGFsbCB5b3VyIHVzZXJzIHdpbGwgdXNlIHRoZSBzYW1lIGhhcmR3YXJlIGFuZCBPUyBjb25maWd1cmF0aW9uIGFzIHlvdXIgY3VycmVudCBtYWNoaW5lLlwiKTtcbiAgICB9XG5cbiAgICB2YXIgck9wdHMgPSByZW5kZXJlckRlZmF1bHRzKG9wdGlvbnMpO1xuICAgIHJPcHRzLmN5ID0gY3k7XG4gICAgY3kuX3ByaXZhdGUucmVuZGVyZXIgPSBuZXcgUmVuZGVyZXJQcm90byhyT3B0cyk7XG4gICAgdGhpcy5ub3RpZnkoJ2luaXQnKTtcbiAgfSxcbiAgZGVzdHJveVJlbmRlcmVyOiBmdW5jdGlvbiBkZXN0cm95UmVuZGVyZXIoKSB7XG4gICAgdmFyIGN5ID0gdGhpcztcbiAgICBjeS5ub3RpZnkoJ2Rlc3Ryb3knKTsgLy8gZGVzdHJveSB0aGUgcmVuZGVyZXJcblxuICAgIHZhciBkb21FbGUgPSBjeS5jb250YWluZXIoKTtcblxuICAgIGlmIChkb21FbGUpIHtcbiAgICAgIGRvbUVsZS5fY3lyZWcgPSBudWxsO1xuXG4gICAgICB3aGlsZSAoZG9tRWxlLmNoaWxkTm9kZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBkb21FbGUucmVtb3ZlQ2hpbGQoZG9tRWxlLmNoaWxkTm9kZXNbMF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGN5Ll9wcml2YXRlLnJlbmRlcmVyID0gbnVsbDsgLy8gdG8gYmUgZXh0cmEgc2FmZSwgcmVtb3ZlIHRoZSByZWZcblxuICAgIGN5Lm11dGFibGVFbGVtZW50cygpLmZvckVhY2goZnVuY3Rpb24gKGVsZSkge1xuICAgICAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICAgICAgX3AucnNjcmF0Y2ggPSB7fTtcbiAgICAgIF9wLnJzdHlsZSA9IHt9O1xuICAgICAgX3AuYW5pbWF0aW9uLmN1cnJlbnQgPSBbXTtcbiAgICAgIF9wLmFuaW1hdGlvbi5xdWV1ZSA9IFtdO1xuICAgIH0pO1xuICB9LFxuICBvblJlbmRlcjogZnVuY3Rpb24gb25SZW5kZXIoZm4pIHtcbiAgICByZXR1cm4gdGhpcy5vbigncmVuZGVyJywgZm4pO1xuICB9LFxuICBvZmZSZW5kZXI6IGZ1bmN0aW9uIG9mZlJlbmRlcihmbikge1xuICAgIHJldHVybiB0aGlzLm9mZigncmVuZGVyJywgZm4pO1xuICB9XG59O1xuY29yZWZuJDUuaW52YWxpZGF0ZURpbWVuc2lvbnMgPSBjb3JlZm4kNS5yZXNpemU7XG5cbnZhciBjb3JlZm4kNiA9IHtcbiAgLy8gZ2V0IGEgY29sbGVjdGlvblxuICAvLyAtIGVtcHR5IGNvbGxlY3Rpb24gb24gbm8gYXJnc1xuICAvLyAtIGNvbGxlY3Rpb24gb2YgZWxlbWVudHMgaW4gdGhlIGdyYXBoIG9uIHNlbGVjdG9yIGFyZ1xuICAvLyAtIGd1YXJhbnRlZSBhIHJldHVybmVkIGNvbGxlY3Rpb24gd2hlbiBlbGVtZW50cyBvciBjb2xsZWN0aW9uIHNwZWNpZmllZFxuICBjb2xsZWN0aW9uOiBmdW5jdGlvbiBjb2xsZWN0aW9uKGVsZXMsIG9wdHMpIHtcbiAgICBpZiAoc3RyaW5nKGVsZXMpKSB7XG4gICAgICByZXR1cm4gdGhpcy4kKGVsZXMpO1xuICAgIH0gZWxzZSBpZiAoZWxlbWVudE9yQ29sbGVjdGlvbihlbGVzKSkge1xuICAgICAgcmV0dXJuIGVsZXMuY29sbGVjdGlvbigpO1xuICAgIH0gZWxzZSBpZiAoYXJyYXkoZWxlcykpIHtcbiAgICAgIHJldHVybiBuZXcgQ29sbGVjdGlvbih0aGlzLCBlbGVzLCBvcHRzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvbGxlY3Rpb24odGhpcyk7XG4gIH0sXG4gIG5vZGVzOiBmdW5jdGlvbiBub2RlcyhzZWxlY3Rvcikge1xuICAgIHZhciBub2RlcyA9IHRoaXMuJChmdW5jdGlvbiAoZWxlKSB7XG4gICAgICByZXR1cm4gZWxlLmlzTm9kZSgpO1xuICAgIH0pO1xuXG4gICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICByZXR1cm4gbm9kZXMuZmlsdGVyKHNlbGVjdG9yKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZXM7XG4gIH0sXG4gIGVkZ2VzOiBmdW5jdGlvbiBlZGdlcyhzZWxlY3Rvcikge1xuICAgIHZhciBlZGdlcyA9IHRoaXMuJChmdW5jdGlvbiAoZWxlKSB7XG4gICAgICByZXR1cm4gZWxlLmlzRWRnZSgpO1xuICAgIH0pO1xuXG4gICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICByZXR1cm4gZWRnZXMuZmlsdGVyKHNlbGVjdG9yKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZWRnZXM7XG4gIH0sXG4gIC8vIHNlYXJjaCB0aGUgZ3JhcGggbGlrZSBqUXVlcnlcbiAgJDogZnVuY3Rpb24gJChzZWxlY3Rvcikge1xuICAgIHZhciBlbGVzID0gdGhpcy5fcHJpdmF0ZS5lbGVtZW50cztcblxuICAgIGlmIChzZWxlY3Rvcikge1xuICAgICAgcmV0dXJuIGVsZXMuZmlsdGVyKHNlbGVjdG9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGVsZXMuc3Bhd25TZWxmKCk7XG4gICAgfVxuICB9LFxuICBtdXRhYmxlRWxlbWVudHM6IGZ1bmN0aW9uIG11dGFibGVFbGVtZW50cygpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5lbGVtZW50cztcbiAgfVxufTsgLy8gYWxpYXNlc1xuXG5jb3JlZm4kNi5lbGVtZW50cyA9IGNvcmVmbiQ2LmZpbHRlciA9IGNvcmVmbiQ2LiQ7XG5cbnZhciBzdHlmbiA9IHt9OyAvLyBrZXlzIGZvciBzdHlsZSBibG9ja3MsIGUuZy4gdHRmZnR0XG5cbnZhciBUUlVFID0gJ3QnO1xudmFyIEZBTFNFID0gJ2YnOyAvLyAocG90ZW50aWFsbHkgZXhwZW5zaXZlIGNhbGN1bGF0aW9uKVxuLy8gYXBwbHkgdGhlIHN0eWxlIHRvIHRoZSBlbGVtZW50IGJhc2VkIG9uXG4vLyAtIGl0cyBieXBhc3Ncbi8vIC0gd2hhdCBzZWxlY3RvcnMgbWF0Y2ggaXRcblxuc3R5Zm4uYXBwbHkgPSBmdW5jdGlvbiAoZWxlcykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBfcCA9IHNlbGYuX3ByaXZhdGU7XG4gIHZhciBjeSA9IF9wLmN5O1xuICB2YXIgdXBkYXRlZEVsZXMgPSBjeS5jb2xsZWN0aW9uKCk7XG5cbiAgaWYgKF9wLm5ld1N0eWxlKSB7XG4gICAgLy8gY2xlYXIgc3R5bGUgY2FjaGVzXG4gICAgX3AuY29udGV4dFN0eWxlcyA9IHt9O1xuICAgIF9wLnByb3BEaWZmcyA9IHt9O1xuICAgIHNlbGYuY2xlYW5FbGVtZW50cyhlbGVzLCB0cnVlKTtcbiAgfVxuXG4gIGZvciAodmFyIGllID0gMDsgaWUgPCBlbGVzLmxlbmd0aDsgaWUrKykge1xuICAgIHZhciBlbGUgPSBlbGVzW2llXTtcbiAgICB2YXIgY3h0TWV0YSA9IHNlbGYuZ2V0Q29udGV4dE1ldGEoZWxlKTtcblxuICAgIGlmIChjeHRNZXRhLmVtcHR5KSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB2YXIgY3h0U3R5bGUgPSBzZWxmLmdldENvbnRleHRTdHlsZShjeHRNZXRhKTtcbiAgICB2YXIgYXBwID0gc2VsZi5hcHBseUNvbnRleHRTdHlsZShjeHRNZXRhLCBjeHRTdHlsZSwgZWxlKTtcblxuICAgIGlmICghX3AubmV3U3R5bGUpIHtcbiAgICAgIHNlbGYudXBkYXRlVHJhbnNpdGlvbnMoZWxlLCBhcHAuZGlmZlByb3BzKTtcbiAgICB9XG5cbiAgICB2YXIgaGludHNEaWZmID0gc2VsZi51cGRhdGVTdHlsZUhpbnRzKGVsZSk7XG5cbiAgICBpZiAoaGludHNEaWZmKSB7XG4gICAgICB1cGRhdGVkRWxlcy5tZXJnZShlbGUpO1xuICAgIH1cbiAgfSAvLyBmb3IgZWxlbWVudHNcblxuXG4gIF9wLm5ld1N0eWxlID0gZmFsc2U7XG4gIHJldHVybiB1cGRhdGVkRWxlcztcbn07XG5cbnN0eWZuLmdldFByb3BlcnRpZXNEaWZmID0gZnVuY3Rpb24gKG9sZEN4dEtleSwgbmV3Q3h0S2V5KSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGNhY2hlID0gc2VsZi5fcHJpdmF0ZS5wcm9wRGlmZnMgPSBzZWxmLl9wcml2YXRlLnByb3BEaWZmcyB8fCB7fTtcbiAgdmFyIGR1YWxDeHRLZXkgPSBvbGRDeHRLZXkgKyAnLScgKyBuZXdDeHRLZXk7XG4gIHZhciBjYWNoZWRWYWwgPSBjYWNoZVtkdWFsQ3h0S2V5XTtcblxuICBpZiAoY2FjaGVkVmFsKSB7XG4gICAgcmV0dXJuIGNhY2hlZFZhbDtcbiAgfVxuXG4gIHZhciBkaWZmUHJvcHMgPSBbXTtcbiAgdmFyIGFkZGVkUHJvcCA9IHt9O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5sZW5ndGg7IGkrKykge1xuICAgIHZhciBjeHQgPSBzZWxmW2ldO1xuICAgIHZhciBvbGRIYXNDeHQgPSBvbGRDeHRLZXlbaV0gPT09IFRSVUU7XG4gICAgdmFyIG5ld0hhc0N4dCA9IG5ld0N4dEtleVtpXSA9PT0gVFJVRTtcbiAgICB2YXIgY3h0SGFzRGlmZmVkID0gb2xkSGFzQ3h0ICE9PSBuZXdIYXNDeHQ7XG4gICAgdmFyIGN4dEhhc01hcHBlZFByb3BzID0gY3h0Lm1hcHBlZFByb3BlcnRpZXMubGVuZ3RoID4gMDtcblxuICAgIGlmIChjeHRIYXNEaWZmZWQgfHwgbmV3SGFzQ3h0ICYmIGN4dEhhc01hcHBlZFByb3BzKSB7XG4gICAgICB2YXIgcHJvcHMgPSB2b2lkIDA7XG5cbiAgICAgIGlmIChjeHRIYXNEaWZmZWQgJiYgY3h0SGFzTWFwcGVkUHJvcHMpIHtcbiAgICAgICAgcHJvcHMgPSBjeHQucHJvcGVydGllczsgLy8gc3VmZmljZXMgYi9jIG1hcHBlZFByb3BlcnRpZXMgaXMgYSBzdWJzZXQgb2YgcHJvcGVydGllc1xuICAgICAgfSBlbHNlIGlmIChjeHRIYXNEaWZmZWQpIHtcbiAgICAgICAgcHJvcHMgPSBjeHQucHJvcGVydGllczsgLy8gbmVlZCB0byBjaGVjayB0aGVtIGFsbFxuICAgICAgfSBlbHNlIGlmIChjeHRIYXNNYXBwZWRQcm9wcykge1xuICAgICAgICBwcm9wcyA9IGN4dC5tYXBwZWRQcm9wZXJ0aWVzOyAvLyBvbmx5IG5lZWQgdG8gY2hlY2sgbWFwcGVkXG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgcHJvcHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIHByb3AgPSBwcm9wc1tqXTtcbiAgICAgICAgdmFyIG5hbWUgPSBwcm9wLm5hbWU7IC8vIGlmIGEgbGF0ZXIgY29udGV4dCBvdmVycmlkZXMgdGhpcyBwcm9wZXJ0eSwgdGhlbiB0aGUgZmFjdCB0aGF0IHRoaXMgY29udGV4dCBoYXMgc3dpdGNoZWQvZGlmZmVkIGRvZXNuJ3QgbWF0dGVyXG4gICAgICAgIC8vIChzZW1pIGV4cGVuc2l2ZSBjaGVjayBzaW5jZSBpdCBtYWtlcyB0aGlzIGZ1bmN0aW9uIE8obl4yKSBvbiBjb250ZXh0IGxlbmd0aCwgYnV0IHdvcnRoIGl0IHNpbmNlIG92ZXJhbGwgcmVzdWx0XG4gICAgICAgIC8vIGlzIGNhY2hlZClcblxuICAgICAgICB2YXIgbGF0ZXJDeHRPdmVycmlkZXMgPSBmYWxzZTtcblxuICAgICAgICBmb3IgKHZhciBrID0gaSArIDE7IGsgPCBzZWxmLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgdmFyIGxhdGVyQ3h0ID0gc2VsZltrXTtcbiAgICAgICAgICB2YXIgaGFzTGF0ZXJDeHQgPSBuZXdDeHRLZXlba10gPT09IFRSVUU7XG5cbiAgICAgICAgICBpZiAoIWhhc0xhdGVyQ3h0KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9IC8vIGNhbid0IG92ZXJyaWRlIHVubGVzcyB0aGUgY29udGV4dCBpcyBhY3RpdmVcblxuXG4gICAgICAgICAgbGF0ZXJDeHRPdmVycmlkZXMgPSBsYXRlckN4dC5wcm9wZXJ0aWVzW3Byb3AubmFtZV0gIT0gbnVsbDtcblxuICAgICAgICAgIGlmIChsYXRlckN4dE92ZXJyaWRlcykge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfSAvLyBleGl0IGVhcmx5IGFzIGxvbmcgYXMgb25lIGxhdGVyIGNvbnRleHQgb3ZlcnJpZGVzXG5cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghYWRkZWRQcm9wW25hbWVdICYmICFsYXRlckN4dE92ZXJyaWRlcykge1xuICAgICAgICAgIGFkZGVkUHJvcFtuYW1lXSA9IHRydWU7XG4gICAgICAgICAgZGlmZlByb3BzLnB1c2gobmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gZm9yIHByb3BzXG5cbiAgICB9IC8vIGlmXG5cbiAgfSAvLyBmb3IgY29udGV4dHNcblxuXG4gIGNhY2hlW2R1YWxDeHRLZXldID0gZGlmZlByb3BzO1xuICByZXR1cm4gZGlmZlByb3BzO1xufTtcblxuc3R5Zm4uZ2V0Q29udGV4dE1ldGEgPSBmdW5jdGlvbiAoZWxlKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGN4dEtleSA9ICcnO1xuICB2YXIgZGlmZlByb3BzO1xuICB2YXIgcHJldktleSA9IGVsZS5fcHJpdmF0ZS5zdHlsZUN4dEtleSB8fCAnJztcblxuICBpZiAoc2VsZi5fcHJpdmF0ZS5uZXdTdHlsZSkge1xuICAgIHByZXZLZXkgPSAnJzsgLy8gc2luY2Ugd2UgbmVlZCB0byBhcHBseSBhbGwgc3R5bGUgaWYgYSBmcmVzaCBzdHlsZXNoZWV0XG4gIH0gLy8gZ2V0IHRoZSBjeHQga2V5XG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHNlbGYubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgY29udGV4dCA9IHNlbGZbaV07XG4gICAgdmFyIGNvbnRleHRTZWxlY3Rvck1hdGNoZXMgPSBjb250ZXh0LnNlbGVjdG9yICYmIGNvbnRleHQuc2VsZWN0b3IubWF0Y2hlcyhlbGUpOyAvLyBOQjogY29udGV4dC5zZWxlY3RvciBtYXkgYmUgbnVsbCBmb3IgJ2NvcmUnXG5cbiAgICBpZiAoY29udGV4dFNlbGVjdG9yTWF0Y2hlcykge1xuICAgICAgY3h0S2V5ICs9IFRSVUU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN4dEtleSArPSBGQUxTRTtcbiAgICB9XG4gIH0gLy8gZm9yIGNvbnRleHRcblxuXG4gIGRpZmZQcm9wcyA9IHNlbGYuZ2V0UHJvcGVydGllc0RpZmYocHJldktleSwgY3h0S2V5KTtcbiAgZWxlLl9wcml2YXRlLnN0eWxlQ3h0S2V5ID0gY3h0S2V5O1xuICByZXR1cm4ge1xuICAgIGtleTogY3h0S2V5LFxuICAgIGRpZmZQcm9wTmFtZXM6IGRpZmZQcm9wcyxcbiAgICBlbXB0eTogZGlmZlByb3BzLmxlbmd0aCA9PT0gMFxuICB9O1xufTsgLy8gZ2V0cyBhIGNvbXB1dGVkIGVsZSBzdHlsZSBvYmplY3QgYmFzZWQgb24gbWF0Y2hlZCBjb250ZXh0c1xuXG5cbnN0eWZuLmdldENvbnRleHRTdHlsZSA9IGZ1bmN0aW9uIChjeHRNZXRhKSB7XG4gIHZhciBjeHRLZXkgPSBjeHRNZXRhLmtleTtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgY3h0U3R5bGVzID0gdGhpcy5fcHJpdmF0ZS5jb250ZXh0U3R5bGVzID0gdGhpcy5fcHJpdmF0ZS5jb250ZXh0U3R5bGVzIHx8IHt9OyAvLyBpZiBhbHJlYWR5IGNvbXB1dGVkIHN0eWxlLCByZXR1cm5lZCBjYWNoZWQgY29weVxuXG4gIGlmIChjeHRTdHlsZXNbY3h0S2V5XSkge1xuICAgIHJldHVybiBjeHRTdHlsZXNbY3h0S2V5XTtcbiAgfVxuXG4gIHZhciBzdHlsZSA9IHtcbiAgICBfcHJpdmF0ZToge1xuICAgICAga2V5OiBjeHRLZXlcbiAgICB9XG4gIH07XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWxmLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGN4dCA9IHNlbGZbaV07XG4gICAgdmFyIGhhc0N4dCA9IGN4dEtleVtpXSA9PT0gVFJVRTtcblxuICAgIGlmICghaGFzQ3h0KSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IGN4dC5wcm9wZXJ0aWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICB2YXIgcHJvcCA9IGN4dC5wcm9wZXJ0aWVzW2pdO1xuICAgICAgc3R5bGVbcHJvcC5uYW1lXSA9IHByb3A7XG4gICAgfVxuICB9XG5cbiAgY3h0U3R5bGVzW2N4dEtleV0gPSBzdHlsZTtcbiAgcmV0dXJuIHN0eWxlO1xufTtcblxuc3R5Zm4uYXBwbHlDb250ZXh0U3R5bGUgPSBmdW5jdGlvbiAoY3h0TWV0YSwgY3h0U3R5bGUsIGVsZSkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBkaWZmUHJvcHMgPSBjeHRNZXRhLmRpZmZQcm9wTmFtZXM7XG4gIHZhciByZXREaWZmUHJvcHMgPSB7fTtcbiAgdmFyIHR5cGVzID0gc2VsZi50eXBlcztcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGRpZmZQcm9wcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBkaWZmUHJvcE5hbWUgPSBkaWZmUHJvcHNbaV07XG4gICAgdmFyIGN4dFByb3AgPSBjeHRTdHlsZVtkaWZmUHJvcE5hbWVdO1xuICAgIHZhciBlbGVQcm9wID0gZWxlLnBzdHlsZShkaWZmUHJvcE5hbWUpO1xuXG4gICAgaWYgKCFjeHRQcm9wKSB7XG4gICAgICAvLyBubyBjb250ZXh0IHByb3AgbWVhbnMgZGVsZXRlXG4gICAgICBpZiAoIWVsZVByb3ApIHtcbiAgICAgICAgY29udGludWU7IC8vIG5vIGV4aXN0aW5nIHByb3AgbWVhbnMgbm90aGluZyBuZWVkcyB0byBiZSByZW1vdmVkXG4gICAgICAgIC8vIG5iIGFmZmVjdHMgaW5pdGlhbCBhcHBsaWNhdGlvbiBvbiBtYXBwZWQgdmFsdWVzIGxpa2UgY29udHJvbC1wb2ludC1kaXN0YW5jZXNcbiAgICAgIH0gZWxzZSBpZiAoZWxlUHJvcC5ieXBhc3MpIHtcbiAgICAgICAgY3h0UHJvcCA9IHtcbiAgICAgICAgICBuYW1lOiBkaWZmUHJvcE5hbWUsXG4gICAgICAgICAgZGVsZXRlQnlwYXNzZWQ6IHRydWVcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGN4dFByb3AgPSB7XG4gICAgICAgICAgbmFtZTogZGlmZlByb3BOYW1lLFxuICAgICAgICAgIFwiZGVsZXRlXCI6IHRydWVcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IC8vIHNhdmUgY3ljbGVzIHdoZW4gdGhlIGNvbnRleHQgcHJvcCBkb2Vzbid0IG5lZWQgdG8gYmUgYXBwbGllZFxuXG5cbiAgICBpZiAoZWxlUHJvcCA9PT0gY3h0UHJvcCkge1xuICAgICAgY29udGludWU7XG4gICAgfSAvLyBzYXZlIGN5Y2xlcyB3aGVuIGEgbWFwcGVkIGNvbnRleHQgcHJvcCBkb2Vzbid0IG5lZWQgdG8gYmUgYXBwbGllZFxuXG5cbiAgICBpZiAoY3h0UHJvcC5tYXBwZWQgPT09IHR5cGVzLmZuIC8vIGNvbnRleHQgcHJvcCBpcyBmdW5jdGlvbiBtYXBwZXJcbiAgICAmJiBlbGVQcm9wICE9IG51bGwgLy8gc29tZSBwcm9wcyBjYW4gYmUgbnVsbCBldmVuIGJ5IGRlZmF1bHQgKGUuZy4gYSBwcm9wIHRoYXQgb3ZlcnJpZGVzIGFub3RoZXIgb25lKVxuICAgICYmIGVsZVByb3AubWFwcGluZyAhPSBudWxsIC8vIGVsZSBwcm9wIGlzIGEgY29uY3JldGUgdmFsdWUgZnJvbSBmcm9tIGEgbWFwcGVyXG4gICAgJiYgZWxlUHJvcC5tYXBwaW5nLnZhbHVlID09PSBjeHRQcm9wLnZhbHVlIC8vIHRoZSBjdXJyZW50IHByb3Agb24gdGhlIGVsZSBpcyBhIGZsYXQgcHJvcCB2YWx1ZSBmb3IgdGhlIGZ1bmN0aW9uIG1hcHBlclxuICAgICkge1xuICAgICAgICAvLyBOQiBkb24ndCB3cml0ZSB0byBjeHRQcm9wLCBhcyBpdCdzIHNoYXJlZCBhbW9uZyBlbGVzIChzdG9yZWQgaW4gc3R5bGVzaGVldClcbiAgICAgICAgdmFyIG1hcHBpbmcgPSBlbGVQcm9wLm1hcHBpbmc7IC8vIGNhbiB3cml0ZSB0byBtYXBwaW5nLCBhcyBpdCdzIGEgcGVyLWVsZSBjb3B5XG5cbiAgICAgICAgdmFyIGZuVmFsdWUgPSBtYXBwaW5nLmZuVmFsdWUgPSBjeHRQcm9wLnZhbHVlKGVsZSk7IC8vIHRlbXBvcmFyaWx5IGNhY2hlIHRoZSB2YWx1ZSBpbiBjYXNlIG9mIGEgbWlzc1xuXG4gICAgICAgIGlmIChmblZhbHVlID09PSBtYXBwaW5nLnByZXZGblZhbHVlKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgIHZhciByZXREaWZmUHJvcCA9IHJldERpZmZQcm9wc1tkaWZmUHJvcE5hbWVdID0ge1xuICAgICAgcHJldjogZWxlUHJvcFxuICAgIH07XG4gICAgc2VsZi5hcHBseVBhcnNlZFByb3BlcnR5KGVsZSwgY3h0UHJvcCk7XG4gICAgcmV0RGlmZlByb3AubmV4dCA9IGVsZS5wc3R5bGUoZGlmZlByb3BOYW1lKTtcblxuICAgIGlmIChyZXREaWZmUHJvcC5uZXh0ICYmIHJldERpZmZQcm9wLm5leHQuYnlwYXNzKSB7XG4gICAgICByZXREaWZmUHJvcC5uZXh0ID0gcmV0RGlmZlByb3AubmV4dC5ieXBhc3NlZDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGRpZmZQcm9wczogcmV0RGlmZlByb3BzXG4gIH07XG59O1xuXG5zdHlmbi51cGRhdGVTdHlsZUhpbnRzID0gZnVuY3Rpb24gKGVsZSkge1xuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHByb3BOYW1lcyA9IHNlbGYucHJvcGVydHlHcm91cE5hbWVzO1xuICB2YXIgcHJvcEdyS2V5cyA9IHNlbGYucHJvcGVydHlHcm91cEtleXM7XG5cbiAgdmFyIHByb3BIYXNoID0gZnVuY3Rpb24gcHJvcEhhc2goZWxlLCBwcm9wTmFtZXMsIHNlZWRLZXkpIHtcbiAgICByZXR1cm4gc2VsZi5nZXRQcm9wZXJ0aWVzSGFzaChlbGUsIHByb3BOYW1lcywgc2VlZEtleSk7XG4gIH07XG5cbiAgdmFyIG9sZFN0eWxlS2V5ID0gX3Auc3R5bGVLZXk7XG5cbiAgaWYgKGVsZS5yZW1vdmVkKCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgaXNOb2RlID0gX3AuZ3JvdXAgPT09ICdub2Rlcyc7IC8vIGdldCB0aGUgc3R5bGUga2V5IGhhc2hlcyBwZXIgcHJvcCBncm91cFxuICAvLyBidXQgbGF6aWx5IC0tIG9ubHkgdXNlIG5vbi1kZWZhdWx0IHByb3AgdmFsdWVzIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIGhhc2hlc1xuICAvL1xuXG4gIHZhciBvdmVycmlkZGVuU3R5bGVzID0gZWxlLl9wcml2YXRlLnN0eWxlO1xuICBwcm9wTmFtZXMgPSBPYmplY3Qua2V5cyhvdmVycmlkZGVuU3R5bGVzKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BHcktleXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZ3JLZXkgPSBwcm9wR3JLZXlzW2ldO1xuICAgIF9wLnN0eWxlS2V5c1tncktleV0gPSBbREVGQVVMVF9IQVNIX1NFRUQsIERFRkFVTFRfSEFTSF9TRUVEX0FMVF07XG4gIH1cblxuICB2YXIgdXBkYXRlR3JLZXkxID0gZnVuY3Rpb24gdXBkYXRlR3JLZXkxKHZhbCwgZ3JLZXkpIHtcbiAgICByZXR1cm4gX3Auc3R5bGVLZXlzW2dyS2V5XVswXSA9IGhhc2hJbnQodmFsLCBfcC5zdHlsZUtleXNbZ3JLZXldWzBdKTtcbiAgfTtcblxuICB2YXIgdXBkYXRlR3JLZXkyID0gZnVuY3Rpb24gdXBkYXRlR3JLZXkyKHZhbCwgZ3JLZXkpIHtcbiAgICByZXR1cm4gX3Auc3R5bGVLZXlzW2dyS2V5XVsxXSA9IGhhc2hJbnRBbHQodmFsLCBfcC5zdHlsZUtleXNbZ3JLZXldWzFdKTtcbiAgfTtcblxuICB2YXIgdXBkYXRlR3JLZXkgPSBmdW5jdGlvbiB1cGRhdGVHcktleSh2YWwsIGdyS2V5KSB7XG4gICAgdXBkYXRlR3JLZXkxKHZhbCwgZ3JLZXkpO1xuICAgIHVwZGF0ZUdyS2V5Mih2YWwsIGdyS2V5KTtcbiAgfTtcblxuICB2YXIgdXBkYXRlR3JLZXlXU3RyID0gZnVuY3Rpb24gdXBkYXRlR3JLZXlXU3RyKHN0clZhbCwgZ3JLZXkpIHtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IHN0clZhbC5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIGNoID0gc3RyVmFsLmNoYXJDb2RlQXQoaik7XG4gICAgICB1cGRhdGVHcktleTEoY2gsIGdyS2V5KTtcbiAgICAgIHVwZGF0ZUdyS2V5MihjaCwgZ3JLZXkpO1xuICAgIH1cbiAgfTsgLy8gLSBoYXNoaW5nIHdvcmtzIG9uIDMyIGJpdCBpbnRzIGIvYyB3ZSB1c2UgYml0d2lzZSBvcHNcbiAgLy8gLSBzbWFsbCBudW1iZXJzIGdldCBjdXQgb2ZmIChlLmcuIDAuMTIzIGlzIHNlZW4gYXMgMCBieSB0aGUgaGFzaGluZyBmdW5jdGlvbilcbiAgLy8gLSByYWlzZSB1cCBzbWFsbCBudW1iZXJzIHNvIG1vcmUgc2lnbmlmaWNhbnQgZGlnaXRzIGFyZSBzZWVuIGJ5IGhhc2hpbmdcbiAgLy8gLSBtYWtlIHNtYWxsIG51bWJlcnMgbGFyZ2VyIHRoYW4gYSBub3JtYWwgdmFsdWUgdG8gYXZvaWQgY29sbGlzaW9uc1xuICAvLyAtIHdvcmtzIGluIHByYWN0aWNlIGFuZCBpdCdzIHJlbGF0aXZlbHkgY2hlYXBcblxuXG4gIHZhciBOID0gMjAwMDAwMDAwMDtcblxuICB2YXIgY2xlYW5OdW0gPSBmdW5jdGlvbiBjbGVhbk51bSh2YWwpIHtcbiAgICByZXR1cm4gLTEyOCA8IHZhbCAmJiB2YWwgPCAxMjggJiYgTWF0aC5mbG9vcih2YWwpICE9PSB2YWwgPyBOIC0gKHZhbCAqIDEwMjQgfCAwKSA6IHZhbDtcbiAgfTtcblxuICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgcHJvcE5hbWVzLmxlbmd0aDsgX2krKykge1xuICAgIHZhciBuYW1lID0gcHJvcE5hbWVzW19pXTtcbiAgICB2YXIgcGFyc2VkUHJvcCA9IG92ZXJyaWRkZW5TdHlsZXNbbmFtZV07XG5cbiAgICBpZiAocGFyc2VkUHJvcCA9PSBudWxsKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB2YXIgcHJvcEluZm8gPSB0aGlzLnByb3BlcnRpZXNbbmFtZV07XG4gICAgdmFyIHR5cGUgPSBwcm9wSW5mby50eXBlO1xuICAgIHZhciBfZ3JLZXkgPSBwcm9wSW5mby5ncm91cEtleTtcbiAgICB2YXIgbm9ybWFsaXplZE51bWJlclZhbCA9IHZvaWQgMDtcblxuICAgIGlmIChwcm9wSW5mby5oYXNoT3ZlcnJpZGUgIT0gbnVsbCkge1xuICAgICAgbm9ybWFsaXplZE51bWJlclZhbCA9IHByb3BJbmZvLmhhc2hPdmVycmlkZShlbGUsIHBhcnNlZFByb3ApO1xuICAgIH0gZWxzZSBpZiAocGFyc2VkUHJvcC5wZlZhbHVlICE9IG51bGwpIHtcbiAgICAgIG5vcm1hbGl6ZWROdW1iZXJWYWwgPSBwYXJzZWRQcm9wLnBmVmFsdWU7XG4gICAgfSAvLyBtaWdodCBub3QgYmUgYSBudW1iZXIgaWYgaXQgYWxsb3dzIGVudW1zXG5cblxuICAgIHZhciBudW1iZXJWYWwgPSBwcm9wSW5mby5lbnVtcyA9PSBudWxsID8gcGFyc2VkUHJvcC52YWx1ZSA6IG51bGw7XG4gICAgdmFyIGhhdmVOb3JtTnVtID0gbm9ybWFsaXplZE51bWJlclZhbCAhPSBudWxsO1xuICAgIHZhciBoYXZlVW5pdGVkTnVtID0gbnVtYmVyVmFsICE9IG51bGw7XG4gICAgdmFyIGhhdmVOdW0gPSBoYXZlTm9ybU51bSB8fCBoYXZlVW5pdGVkTnVtO1xuICAgIHZhciB1bml0cyA9IHBhcnNlZFByb3AudW5pdHM7IC8vIG51bWJlcnMgYXJlIGNoZWFwZXIgdG8gaGFzaCB0aGFuIHN0cmluZ3NcbiAgICAvLyAxIGhhc2ggb3AgdnMgbiBoYXNoIG9wcyAoZm9yIGxlbmd0aCBuIHN0cmluZylcblxuICAgIGlmICh0eXBlLm51bWJlciAmJiBoYXZlTnVtKSB7XG4gICAgICB2YXIgdiA9IGhhdmVOb3JtTnVtID8gbm9ybWFsaXplZE51bWJlclZhbCA6IG51bWJlclZhbDtcblxuICAgICAgaWYgKHR5cGUubXVsdGlwbGUpIHtcbiAgICAgICAgZm9yICh2YXIgX2kyID0gMDsgX2kyIDwgdi5sZW5ndGg7IF9pMisrKSB7XG4gICAgICAgICAgdXBkYXRlR3JLZXkoY2xlYW5OdW0odltfaTJdKSwgX2dyS2V5KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXBkYXRlR3JLZXkoY2xlYW5OdW0odiksIF9ncktleSk7XG4gICAgICB9XG5cbiAgICAgIGlmICghaGF2ZU5vcm1OdW0gJiYgdW5pdHMgIT0gbnVsbCkge1xuICAgICAgICB1cGRhdGVHcktleVdTdHIodW5pdHMsIF9ncktleSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHVwZGF0ZUdyS2V5V1N0cihwYXJzZWRQcm9wLnN0clZhbHVlLCBfZ3JLZXkpO1xuICAgIH1cbiAgfSAvLyBvdmVyYWxsIHN0eWxlIGtleVxuICAvL1xuXG5cbiAgdmFyIGhhc2ggPSBbREVGQVVMVF9IQVNIX1NFRUQsIERFRkFVTFRfSEFTSF9TRUVEX0FMVF07XG5cbiAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgcHJvcEdyS2V5cy5sZW5ndGg7IF9pMysrKSB7XG4gICAgdmFyIF9ncktleTIgPSBwcm9wR3JLZXlzW19pM107XG4gICAgdmFyIGdySGFzaCA9IF9wLnN0eWxlS2V5c1tfZ3JLZXkyXTtcbiAgICBoYXNoWzBdID0gaGFzaEludChnckhhc2hbMF0sIGhhc2hbMF0pO1xuICAgIGhhc2hbMV0gPSBoYXNoSW50QWx0KGdySGFzaFsxXSwgaGFzaFsxXSk7XG4gIH1cblxuICBfcC5zdHlsZUtleSA9IGNvbWJpbmVIYXNoZXMoaGFzaFswXSwgaGFzaFsxXSk7IC8vIGxhYmVsIGRpbXNcbiAgLy9cblxuICB2YXIgc2sgPSBfcC5zdHlsZUtleXM7XG4gIF9wLmxhYmVsRGltc0tleSA9IGNvbWJpbmVIYXNoZXNBcnJheShzay5sYWJlbERpbWVuc2lvbnMpO1xuICB2YXIgbGFiZWxLZXlzID0gcHJvcEhhc2goZWxlLCBbJ2xhYmVsJ10sIHNrLmxhYmVsRGltZW5zaW9ucyk7XG4gIF9wLmxhYmVsS2V5ID0gY29tYmluZUhhc2hlc0FycmF5KGxhYmVsS2V5cyk7XG4gIF9wLmxhYmVsU3R5bGVLZXkgPSBjb21iaW5lSGFzaGVzQXJyYXkoaGFzaEFycmF5cyhzay5jb21tb25MYWJlbCwgbGFiZWxLZXlzKSk7XG5cbiAgaWYgKCFpc05vZGUpIHtcbiAgICB2YXIgc291cmNlTGFiZWxLZXlzID0gcHJvcEhhc2goZWxlLCBbJ3NvdXJjZS1sYWJlbCddLCBzay5sYWJlbERpbWVuc2lvbnMpO1xuICAgIF9wLnNvdXJjZUxhYmVsS2V5ID0gY29tYmluZUhhc2hlc0FycmF5KHNvdXJjZUxhYmVsS2V5cyk7XG4gICAgX3Auc291cmNlTGFiZWxTdHlsZUtleSA9IGNvbWJpbmVIYXNoZXNBcnJheShoYXNoQXJyYXlzKHNrLmNvbW1vbkxhYmVsLCBzb3VyY2VMYWJlbEtleXMpKTtcbiAgICB2YXIgdGFyZ2V0TGFiZWxLZXlzID0gcHJvcEhhc2goZWxlLCBbJ3RhcmdldC1sYWJlbCddLCBzay5sYWJlbERpbWVuc2lvbnMpO1xuICAgIF9wLnRhcmdldExhYmVsS2V5ID0gY29tYmluZUhhc2hlc0FycmF5KHRhcmdldExhYmVsS2V5cyk7XG4gICAgX3AudGFyZ2V0TGFiZWxTdHlsZUtleSA9IGNvbWJpbmVIYXNoZXNBcnJheShoYXNoQXJyYXlzKHNrLmNvbW1vbkxhYmVsLCB0YXJnZXRMYWJlbEtleXMpKTtcbiAgfSAvLyBub2RlXG4gIC8vXG5cblxuICBpZiAoaXNOb2RlKSB7XG4gICAgdmFyIF9wJHN0eWxlS2V5cyA9IF9wLnN0eWxlS2V5cyxcbiAgICAgICAgbm9kZUJvZHkgPSBfcCRzdHlsZUtleXMubm9kZUJvZHksXG4gICAgICAgIG5vZGVCb3JkZXIgPSBfcCRzdHlsZUtleXMubm9kZUJvcmRlcixcbiAgICAgICAgYmFja2dyb3VuZEltYWdlID0gX3Akc3R5bGVLZXlzLmJhY2tncm91bmRJbWFnZSxcbiAgICAgICAgY29tcG91bmQgPSBfcCRzdHlsZUtleXMuY29tcG91bmQsXG4gICAgICAgIHBpZSA9IF9wJHN0eWxlS2V5cy5waWU7XG4gICAgdmFyIG5vZGVLZXlzID0gW25vZGVCb3JkZXIsIGJhY2tncm91bmRJbWFnZSwgY29tcG91bmQsIHBpZV0ucmVkdWNlKGhhc2hBcnJheXMsIG5vZGVCb2R5KTtcbiAgICBfcC5ub2RlS2V5ID0gY29tYmluZUhhc2hlc0FycmF5KG5vZGVLZXlzKTtcbiAgICBfcC5oYXNQaWUgPSBwaWVbMF0gIT09IERFRkFVTFRfSEFTSF9TRUVEICYmIHBpZVsxXSAhPT0gREVGQVVMVF9IQVNIX1NFRURfQUxUO1xuICB9XG5cbiAgcmV0dXJuIG9sZFN0eWxlS2V5ICE9PSBfcC5zdHlsZUtleTtcbn07XG5cbnN0eWZuLmNsZWFyU3R5bGVIaW50cyA9IGZ1bmN0aW9uIChlbGUpIHtcbiAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICBfcC5zdHlsZUtleXMgPSB7fTtcbiAgX3Auc3R5bGVLZXkgPSBudWxsO1xuICBfcC5sYWJlbEtleSA9IG51bGw7XG4gIF9wLmxhYmVsU3R5bGVLZXkgPSBudWxsO1xuICBfcC5zb3VyY2VMYWJlbEtleSA9IG51bGw7XG4gIF9wLnNvdXJjZUxhYmVsU3R5bGVLZXkgPSBudWxsO1xuICBfcC50YXJnZXRMYWJlbEtleSA9IG51bGw7XG4gIF9wLnRhcmdldExhYmVsU3R5bGVLZXkgPSBudWxsO1xuICBfcC5ub2RlS2V5ID0gbnVsbDtcbiAgX3AuaGFzUGllID0gbnVsbDtcbn07IC8vIGFwcGx5IGEgcHJvcGVydHkgdG8gdGhlIHN0eWxlIChmb3IgaW50ZXJuYWwgdXNlKVxuLy8gcmV0dXJucyB3aGV0aGVyIGFwcGxpY2F0aW9uIHdhcyBzdWNjZXNzZnVsXG4vL1xuLy8gbm93LCB0aGlzIGZ1bmN0aW9uIGZsYXR0ZW5zIHRoZSBwcm9wZXJ0eSwgYW5kIGhlcmUncyBob3c6XG4vL1xuLy8gZm9yIHBhcnNlZFByb3A6eyBieXBhc3M6IHRydWUsIGRlbGV0ZUJ5cGFzczogdHJ1ZSB9XG4vLyBubyBwcm9wZXJ0eSBpcyBnZW5lcmF0ZWQsIGluc3RlYWQgdGhlIGJ5cGFzcyBwcm9wZXJ0eSBpbiB0aGVcbi8vIGVsZW1lbnQncyBzdHlsZSBpcyByZXBsYWNlZCBieSB3aGF0J3MgcG9pbnRlZCB0byBieSB0aGUgYGJ5cGFzc2VkYFxuLy8gZmllbGQgaW4gdGhlIGJ5cGFzcyBwcm9wZXJ0eSAoaS5lLiByZXN0b3JpbmcgdGhlIHByb3BlcnR5IHRoZVxuLy8gYnlwYXNzIHdhcyBvdmVycmlkaW5nKVxuLy9cbi8vIGZvciBwYXJzZWRQcm9wOnsgbWFwcGVkOiB0cnV0aHkgfVxuLy8gdGhlIGdlbmVyYXRlZCBmbGF0dGVuZWRQcm9wOnsgbWFwcGluZzogcHJvcCB9XG4vL1xuLy8gZm9yIHBhcnNlZFByb3A6eyBieXBhc3M6IHRydWUgfVxuLy8gdGhlIGdlbmVyYXRlZCBmbGF0dGVuZWRQcm9wOnsgYnlwYXNzZWQ6IHBhcnNlZFByb3AgfVxuXG5cbnN0eWZuLmFwcGx5UGFyc2VkUHJvcGVydHkgPSBmdW5jdGlvbiAoZWxlLCBwYXJzZWRQcm9wKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHByb3AgPSBwYXJzZWRQcm9wO1xuICB2YXIgc3R5bGUgPSBlbGUuX3ByaXZhdGUuc3R5bGU7XG4gIHZhciBmbGF0UHJvcDtcbiAgdmFyIHR5cGVzID0gc2VsZi50eXBlcztcbiAgdmFyIHR5cGUgPSBzZWxmLnByb3BlcnRpZXNbcHJvcC5uYW1lXS50eXBlO1xuICB2YXIgcHJvcElzQnlwYXNzID0gcHJvcC5ieXBhc3M7XG4gIHZhciBvcmlnUHJvcCA9IHN0eWxlW3Byb3AubmFtZV07XG4gIHZhciBvcmlnUHJvcElzQnlwYXNzID0gb3JpZ1Byb3AgJiYgb3JpZ1Byb3AuYnlwYXNzO1xuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciBmbGF0UHJvcE1hcHBpbmcgPSAnbWFwcGluZyc7XG5cbiAgdmFyIGdldFZhbCA9IGZ1bmN0aW9uIGdldFZhbChwKSB7XG4gICAgaWYgKHAgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIGlmIChwLnBmVmFsdWUgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHAucGZWYWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHAudmFsdWU7XG4gICAgfVxuICB9O1xuXG4gIHZhciBjaGVja1RyaWdnZXJzID0gZnVuY3Rpb24gY2hlY2tUcmlnZ2VycygpIHtcbiAgICB2YXIgZnJvbVZhbCA9IGdldFZhbChvcmlnUHJvcCk7XG4gICAgdmFyIHRvVmFsID0gZ2V0VmFsKHByb3ApO1xuICAgIHNlbGYuY2hlY2tUcmlnZ2VycyhlbGUsIHByb3AubmFtZSwgZnJvbVZhbCwgdG9WYWwpO1xuICB9OyAvLyBlZGdlIHNhbml0eSBjaGVja3MgdG8gcHJldmVudCB0aGUgY2xpZW50IGZyb20gbWFraW5nIHNlcmlvdXMgbWlzdGFrZXNcblxuXG4gIGlmIChwYXJzZWRQcm9wLm5hbWUgPT09ICdjdXJ2ZS1zdHlsZScgJiYgZWxlLmlzRWRnZSgpICYmICggLy8gbG9vcHMgbXVzdCBiZSBidW5kbGVkIGJlemllcnNcbiAgcGFyc2VkUHJvcC52YWx1ZSAhPT0gJ2JlemllcicgJiYgZWxlLmlzTG9vcCgpIHx8IC8vIGVkZ2VzIGNvbm5lY3RlZCB0byBjb21wb3VuZCBub2RlcyBjYW4gbm90IGJlIGhheXN0YWNrc1xuICBwYXJzZWRQcm9wLnZhbHVlID09PSAnaGF5c3RhY2snICYmIChlbGUuc291cmNlKCkuaXNQYXJlbnQoKSB8fCBlbGUudGFyZ2V0KCkuaXNQYXJlbnQoKSkpKSB7XG4gICAgcHJvcCA9IHBhcnNlZFByb3AgPSB0aGlzLnBhcnNlKHBhcnNlZFByb3AubmFtZSwgJ2JlemllcicsIHByb3BJc0J5cGFzcyk7XG4gIH1cblxuICBpZiAocHJvcFtcImRlbGV0ZVwiXSkge1xuICAgIC8vIGRlbGV0ZSB0aGUgcHJvcGVydHkgYW5kIHVzZSB0aGUgZGVmYXVsdCB2YWx1ZSBvbiBmYWxzZXkgdmFsdWVcbiAgICBzdHlsZVtwcm9wLm5hbWVdID0gdW5kZWZpbmVkO1xuICAgIGNoZWNrVHJpZ2dlcnMoKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChwcm9wLmRlbGV0ZUJ5cGFzc2VkKSB7XG4gICAgLy8gZGVsZXRlIHRoZSBwcm9wZXJ0eSB0aGF0IHRoZVxuICAgIGlmICghb3JpZ1Byb3ApIHtcbiAgICAgIGNoZWNrVHJpZ2dlcnMoKTtcbiAgICAgIHJldHVybiB0cnVlOyAvLyBjYW4ndCBkZWxldGUgaWYgbm8gcHJvcFxuICAgIH0gZWxzZSBpZiAob3JpZ1Byb3AuYnlwYXNzKSB7XG4gICAgICAvLyBkZWxldGUgYnlwYXNzZWRcbiAgICAgIG9yaWdQcm9wLmJ5cGFzc2VkID0gdW5kZWZpbmVkO1xuICAgICAgY2hlY2tUcmlnZ2VycygpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTsgLy8gd2UncmUgdW5zdWNjZXNzZnVsIGRlbGV0aW5nIHRoZSBieXBhc3NlZFxuICAgIH1cbiAgfSAvLyBjaGVjayBpZiB3ZSBuZWVkIHRvIGRlbGV0ZSB0aGUgY3VycmVudCBieXBhc3NcblxuXG4gIGlmIChwcm9wLmRlbGV0ZUJ5cGFzcykge1xuICAgIC8vIHRoZW4gdGhpcyBwcm9wZXJ0eSBpcyBqdXN0IGhlcmUgdG8gaW5kaWNhdGUgd2UgbmVlZCB0byBkZWxldGVcbiAgICBpZiAoIW9yaWdQcm9wKSB7XG4gICAgICBjaGVja1RyaWdnZXJzKCk7XG4gICAgICByZXR1cm4gdHJ1ZTsgLy8gcHJvcGVydHkgaXMgYWxyZWFkeSBub3QgZGVmaW5lZFxuICAgIH0gZWxzZSBpZiAob3JpZ1Byb3AuYnlwYXNzKSB7XG4gICAgICAvLyB0aGVuIHJlcGxhY2UgdGhlIGJ5cGFzcyBwcm9wZXJ0eSB3aXRoIHRoZSBvcmlnaW5hbFxuICAgICAgLy8gYmVjYXVzZSB0aGUgYnlwYXNzZWQgcHJvcGVydHkgd2FzIGFscmVhZHkgYXBwbGllZCAoYW5kIHRoZXJlZm9yZSBwYXJzZWQpLCB3ZSBjYW4ganVzdCByZXBsYWNlIGl0IChubyByZWFwcGx5aW5nIG5lY2Vzc2FyeSlcbiAgICAgIHN0eWxlW3Byb3AubmFtZV0gPSBvcmlnUHJvcC5ieXBhc3NlZDtcbiAgICAgIGNoZWNrVHJpZ2dlcnMoKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7IC8vIHdlJ3JlIHVuc3VjY2Vzc2Z1bCBkZWxldGluZyB0aGUgYnlwYXNzXG4gICAgfVxuICB9XG5cbiAgdmFyIHByaW50TWFwcGluZ0VyciA9IGZ1bmN0aW9uIHByaW50TWFwcGluZ0VycigpIHtcbiAgICB3YXJuKCdEbyBub3QgYXNzaWduIG1hcHBpbmdzIHRvIGVsZW1lbnRzIHdpdGhvdXQgY29ycmVzcG9uZGluZyBkYXRhIChpLmUuIGVsZSBgJyArIGVsZS5pZCgpICsgJ2AgaGFzIG5vIG1hcHBpbmcgZm9yIHByb3BlcnR5IGAnICsgcHJvcC5uYW1lICsgJ2Agd2l0aCBkYXRhIGZpZWxkIGAnICsgcHJvcC5maWVsZCArICdgKTsgdHJ5IGEgYFsnICsgcHJvcC5maWVsZCArICddYCBzZWxlY3RvciB0byBsaW1pdCBzY29wZSB0byBlbGVtZW50cyB3aXRoIGAnICsgcHJvcC5maWVsZCArICdgIGRlZmluZWQnKTtcbiAgfTsgLy8gcHV0IHRoZSBwcm9wZXJ0eSBpbiB0aGUgc3R5bGUgb2JqZWN0c1xuXG5cbiAgc3dpdGNoIChwcm9wLm1hcHBlZCkge1xuICAgIC8vIGZsYXR0ZW4gdGhlIHByb3BlcnR5IGlmIG1hcHBlZFxuICAgIGNhc2UgdHlwZXMubWFwRGF0YTpcbiAgICAgIHtcbiAgICAgICAgLy8gZmxhdHRlbiB0aGUgZmllbGQgKGUuZy4gZGF0YS5mb28uYmFyKVxuICAgICAgICB2YXIgZmllbGRzID0gcHJvcC5maWVsZC5zcGxpdCgnLicpO1xuICAgICAgICB2YXIgZmllbGRWYWwgPSBfcC5kYXRhO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmllbGRzLmxlbmd0aCAmJiBmaWVsZFZhbDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGZpZWxkID0gZmllbGRzW2ldO1xuICAgICAgICAgIGZpZWxkVmFsID0gZmllbGRWYWxbZmllbGRdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpZWxkVmFsID09IG51bGwpIHtcbiAgICAgICAgICBwcmludE1hcHBpbmdFcnIoKTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcGVyY2VudDtcblxuICAgICAgICBpZiAoIW51bWJlcihmaWVsZFZhbCkpIHtcbiAgICAgICAgICAvLyB0aGVuIGRvbid0IGFwcGx5IGFuZCBmYWxsIGJhY2sgb24gdGhlIGV4aXN0aW5nIHN0eWxlXG4gICAgICAgICAgd2FybignRG8gbm90IHVzZSBjb250aW51b3VzIG1hcHBlcnMgd2l0aG91dCBzcGVjaWZ5aW5nIG51bWVyaWMgZGF0YSAoaS5lLiBgJyArIHByb3AuZmllbGQgKyAnOiAnICsgZmllbGRWYWwgKyAnYCBmb3IgYCcgKyBlbGUuaWQoKSArICdgIGlzIG5vbi1udW1lcmljKScpO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgZmllbGRXaWR0aCA9IHByb3AuZmllbGRNYXggLSBwcm9wLmZpZWxkTWluO1xuXG4gICAgICAgICAgaWYgKGZpZWxkV2lkdGggPT09IDApIHtcbiAgICAgICAgICAgIC8vIHNhZmV0eSBjaGVjayAtLSBub3Qgc3RyaWN0bHkgbmVjZXNzYXJ5IGFzIG5vIHByb3BzIG9mIHplcm8gcmFuZ2Ugc2hvdWxkIGJlIHBhc3NlZCBoZXJlXG4gICAgICAgICAgICBwZXJjZW50ID0gMDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVyY2VudCA9IChmaWVsZFZhbCAtIHByb3AuZmllbGRNaW4pIC8gZmllbGRXaWR0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gbWFrZSBzdXJlIHRvIGJvdW5kIHBlcmNlbnQgdmFsdWVcblxuXG4gICAgICAgIGlmIChwZXJjZW50IDwgMCkge1xuICAgICAgICAgIHBlcmNlbnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKHBlcmNlbnQgPiAxKSB7XG4gICAgICAgICAgcGVyY2VudCA9IDE7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZS5jb2xvcikge1xuICAgICAgICAgIHZhciByMSA9IHByb3AudmFsdWVNaW5bMF07XG4gICAgICAgICAgdmFyIHIyID0gcHJvcC52YWx1ZU1heFswXTtcbiAgICAgICAgICB2YXIgZzEgPSBwcm9wLnZhbHVlTWluWzFdO1xuICAgICAgICAgIHZhciBnMiA9IHByb3AudmFsdWVNYXhbMV07XG4gICAgICAgICAgdmFyIGIxID0gcHJvcC52YWx1ZU1pblsyXTtcbiAgICAgICAgICB2YXIgYjIgPSBwcm9wLnZhbHVlTWF4WzJdO1xuICAgICAgICAgIHZhciBhMSA9IHByb3AudmFsdWVNaW5bM10gPT0gbnVsbCA/IDEgOiBwcm9wLnZhbHVlTWluWzNdO1xuICAgICAgICAgIHZhciBhMiA9IHByb3AudmFsdWVNYXhbM10gPT0gbnVsbCA/IDEgOiBwcm9wLnZhbHVlTWF4WzNdO1xuICAgICAgICAgIHZhciBjbHIgPSBbTWF0aC5yb3VuZChyMSArIChyMiAtIHIxKSAqIHBlcmNlbnQpLCBNYXRoLnJvdW5kKGcxICsgKGcyIC0gZzEpICogcGVyY2VudCksIE1hdGgucm91bmQoYjEgKyAoYjIgLSBiMSkgKiBwZXJjZW50KSwgTWF0aC5yb3VuZChhMSArIChhMiAtIGExKSAqIHBlcmNlbnQpXTtcbiAgICAgICAgICBmbGF0UHJvcCA9IHtcbiAgICAgICAgICAgIC8vIGNvbG91cnMgYXJlIHNpbXBsZSwgc28ganVzdCBjcmVhdGUgdGhlIGZsYXQgcHJvcGVydHkgaW5zdGVhZCBvZiBleHBlbnNpdmUgc3RyaW5nIHBhcnNpbmdcbiAgICAgICAgICAgIGJ5cGFzczogcHJvcC5ieXBhc3MsXG4gICAgICAgICAgICAvLyB3ZSdyZSBhIGJ5cGFzcyBpZiB0aGUgbWFwcGluZyBwcm9wZXJ0eSBpcyBhIGJ5cGFzc1xuICAgICAgICAgICAgbmFtZTogcHJvcC5uYW1lLFxuICAgICAgICAgICAgdmFsdWU6IGNscixcbiAgICAgICAgICAgIHN0clZhbHVlOiAncmdiKCcgKyBjbHJbMF0gKyAnLCAnICsgY2xyWzFdICsgJywgJyArIGNsclsyXSArICcpJ1xuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZS5udW1iZXIpIHtcbiAgICAgICAgICB2YXIgY2FsY1ZhbHVlID0gcHJvcC52YWx1ZU1pbiArIChwcm9wLnZhbHVlTWF4IC0gcHJvcC52YWx1ZU1pbikgKiBwZXJjZW50O1xuICAgICAgICAgIGZsYXRQcm9wID0gdGhpcy5wYXJzZShwcm9wLm5hbWUsIGNhbGNWYWx1ZSwgcHJvcC5ieXBhc3MsIGZsYXRQcm9wTWFwcGluZyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBjYW4gb25seSBtYXAgdG8gY29sb3VycyBhbmQgbnVtYmVyc1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFmbGF0UHJvcCkge1xuICAgICAgICAgIC8vIGlmIHdlIGNhbid0IGZsYXR0ZW4gdGhlIHByb3BlcnR5LCB0aGVuIGRvbid0IGFwcGx5IHRoZSBwcm9wZXJ0eSBhbmQgZmFsbCBiYWNrIG9uIHRoZSBleGlzdGluZyBzdHlsZVxuICAgICAgICAgIHByaW50TWFwcGluZ0VycigpO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZsYXRQcm9wLm1hcHBpbmcgPSBwcm9wOyAvLyBrZWVwIGEgcmVmZXJlbmNlIHRvIHRoZSBtYXBwaW5nXG5cbiAgICAgICAgcHJvcCA9IGZsYXRQcm9wOyAvLyB0aGUgZmxhdHRlbmVkIChtYXBwZWQpIHByb3BlcnR5IGlzIHRoZSBvbmUgd2Ugd2FudFxuXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIC8vIGRpcmVjdCBtYXBwaW5nXG5cbiAgICBjYXNlIHR5cGVzLmRhdGE6XG4gICAgICB7XG4gICAgICAgIC8vIGZsYXR0ZW4gdGhlIGZpZWxkIChlLmcuIGRhdGEuZm9vLmJhcilcbiAgICAgICAgdmFyIF9maWVsZHMgPSBwcm9wLmZpZWxkLnNwbGl0KCcuJyk7XG5cbiAgICAgICAgdmFyIF9maWVsZFZhbCA9IF9wLmRhdGE7XG5cbiAgICAgICAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgX2ZpZWxkcy5sZW5ndGggJiYgX2ZpZWxkVmFsOyBfaTQrKykge1xuICAgICAgICAgIHZhciBfZmllbGQgPSBfZmllbGRzW19pNF07XG4gICAgICAgICAgX2ZpZWxkVmFsID0gX2ZpZWxkVmFsW19maWVsZF07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoX2ZpZWxkVmFsICE9IG51bGwpIHtcbiAgICAgICAgICBmbGF0UHJvcCA9IHRoaXMucGFyc2UocHJvcC5uYW1lLCBfZmllbGRWYWwsIHByb3AuYnlwYXNzLCBmbGF0UHJvcE1hcHBpbmcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFmbGF0UHJvcCkge1xuICAgICAgICAgIC8vIGlmIHdlIGNhbid0IGZsYXR0ZW4gdGhlIHByb3BlcnR5LCB0aGVuIGRvbid0IGFwcGx5IGFuZCBmYWxsIGJhY2sgb24gdGhlIGV4aXN0aW5nIHN0eWxlXG4gICAgICAgICAgcHJpbnRNYXBwaW5nRXJyKCk7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgZmxhdFByb3AubWFwcGluZyA9IHByb3A7IC8vIGtlZXAgYSByZWZlcmVuY2UgdG8gdGhlIG1hcHBpbmdcblxuICAgICAgICBwcm9wID0gZmxhdFByb3A7IC8vIHRoZSBmbGF0dGVuZWQgKG1hcHBlZCkgcHJvcGVydHkgaXMgdGhlIG9uZSB3ZSB3YW50XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBjYXNlIHR5cGVzLmZuOlxuICAgICAge1xuICAgICAgICB2YXIgZm4gPSBwcm9wLnZhbHVlO1xuICAgICAgICB2YXIgZm5SZXRWYWwgPSBwcm9wLmZuVmFsdWUgIT0gbnVsbCA/IHByb3AuZm5WYWx1ZSA6IGZuKGVsZSk7IC8vIGNoZWNrIGZvciBjYWNoZWQgdmFsdWUgYmVmb3JlIGNhbGxpbmcgZnVuY3Rpb25cblxuICAgICAgICBwcm9wLnByZXZGblZhbHVlID0gZm5SZXRWYWw7XG5cbiAgICAgICAgaWYgKGZuUmV0VmFsID09IG51bGwpIHtcbiAgICAgICAgICB3YXJuKCdDdXN0b20gZnVuY3Rpb24gbWFwcGVycyBtYXkgbm90IHJldHVybiBudWxsIChpLmUuIGAnICsgcHJvcC5uYW1lICsgJ2AgZm9yIGVsZSBgJyArIGVsZS5pZCgpICsgJ2AgaXMgbnVsbCknKTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBmbGF0UHJvcCA9IHRoaXMucGFyc2UocHJvcC5uYW1lLCBmblJldFZhbCwgcHJvcC5ieXBhc3MsIGZsYXRQcm9wTWFwcGluZyk7XG5cbiAgICAgICAgaWYgKCFmbGF0UHJvcCkge1xuICAgICAgICAgIHdhcm4oJ0N1c3RvbSBmdW5jdGlvbiBtYXBwZXJzIG1heSBub3QgcmV0dXJuIGludmFsaWQgdmFsdWVzIGZvciB0aGUgcHJvcGVydHkgdHlwZSAoaS5lLiBgJyArIHByb3AubmFtZSArICdgIGZvciBlbGUgYCcgKyBlbGUuaWQoKSArICdgIGlzIGludmFsaWQpJyk7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgZmxhdFByb3AubWFwcGluZyA9IGNvcHkocHJvcCk7IC8vIGtlZXAgYSByZWZlcmVuY2UgdG8gdGhlIG1hcHBpbmdcblxuICAgICAgICBwcm9wID0gZmxhdFByb3A7IC8vIHRoZSBmbGF0dGVuZWQgKG1hcHBlZCkgcHJvcGVydHkgaXMgdGhlIG9uZSB3ZSB3YW50XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgIGJyZWFrO1xuICAgIC8vIGp1c3Qgc2V0IHRoZSBwcm9wZXJ0eVxuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICAvLyBub3QgYSB2YWxpZCBtYXBwaW5nXG4gIH0gLy8gaWYgdGhlIHByb3BlcnR5IGlzIGEgYnlwYXNzIHByb3BlcnR5LCB0aGVuIGxpbmsgdGhlIHJlc3VsdGFudCBwcm9wZXJ0eSB0byB0aGUgb3JpZ2luYWwgb25lXG5cblxuICBpZiAocHJvcElzQnlwYXNzKSB7XG4gICAgaWYgKG9yaWdQcm9wSXNCeXBhc3MpIHtcbiAgICAgIC8vIHRoZW4gdGhpcyBieXBhc3Mgb3ZlcnJpZGVzIHRoZSBleGlzdGluZyBvbmVcbiAgICAgIHByb3AuYnlwYXNzZWQgPSBvcmlnUHJvcC5ieXBhc3NlZDsgLy8gc3RlYWwgYnlwYXNzZWQgcHJvcCBmcm9tIG9sZCBieXBhc3NcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gdGhlbiBsaW5rIHRoZSBvcmlnIHByb3AgdG8gdGhlIG5ldyBieXBhc3NcbiAgICAgIHByb3AuYnlwYXNzZWQgPSBvcmlnUHJvcDtcbiAgICB9XG5cbiAgICBzdHlsZVtwcm9wLm5hbWVdID0gcHJvcDsgLy8gYW5kIHNldFxuICB9IGVsc2Uge1xuICAgIC8vIHByb3AgaXMgbm90IGJ5cGFzc1xuICAgIGlmIChvcmlnUHJvcElzQnlwYXNzKSB7XG4gICAgICAvLyB0aGVuIGtlZXAgdGhlIG9yaWcgcHJvcCAoc2luY2UgaXQncyBhIGJ5cGFzcykgYW5kIGxpbmsgdG8gdGhlIG5ldyBwcm9wXG4gICAgICBvcmlnUHJvcC5ieXBhc3NlZCA9IHByb3A7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHRoZW4ganVzdCByZXBsYWNlIHRoZSBvbGQgcHJvcCB3aXRoIHRoZSBuZXcgb25lXG4gICAgICBzdHlsZVtwcm9wLm5hbWVdID0gcHJvcDtcbiAgICB9XG4gIH1cblxuICBjaGVja1RyaWdnZXJzKCk7XG4gIHJldHVybiB0cnVlO1xufTtcblxuc3R5Zm4uY2xlYW5FbGVtZW50cyA9IGZ1bmN0aW9uIChlbGVzLCBrZWVwQnlwYXNzZXMpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IGVsZXNbaV07XG4gICAgdGhpcy5jbGVhclN0eWxlSGludHMoZWxlKTtcbiAgICBlbGUuZGlydHlDb21wb3VuZEJvdW5kc0NhY2hlKCk7XG4gICAgZWxlLmRpcnR5Qm91bmRpbmdCb3hDYWNoZSgpO1xuXG4gICAgaWYgKCFrZWVwQnlwYXNzZXMpIHtcbiAgICAgIGVsZS5fcHJpdmF0ZS5zdHlsZSA9IHt9O1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgc3R5bGUgPSBlbGUuX3ByaXZhdGUuc3R5bGU7XG4gICAgICB2YXIgcHJvcE5hbWVzID0gT2JqZWN0LmtleXMoc3R5bGUpO1xuXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHByb3BOYW1lcy5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wTmFtZXNbal07XG4gICAgICAgIHZhciBlbGVQcm9wID0gc3R5bGVbcHJvcE5hbWVdO1xuXG4gICAgICAgIGlmIChlbGVQcm9wICE9IG51bGwpIHtcbiAgICAgICAgICBpZiAoZWxlUHJvcC5ieXBhc3MpIHtcbiAgICAgICAgICAgIGVsZVByb3AuYnlwYXNzZWQgPSBudWxsO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdHlsZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufTsgLy8gdXBkYXRlcyB0aGUgdmlzdWFsIHN0eWxlIGZvciBhbGwgZWxlbWVudHMgKHVzZWZ1bCBmb3IgbWFudWFsIHN0eWxlIG1vZGlmaWNhdGlvbiBhZnRlciBpbml0KVxuXG5cbnN0eWZuLnVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGN5ID0gdGhpcy5fcHJpdmF0ZS5jeTtcbiAgdmFyIGVsZXMgPSBjeS5tdXRhYmxlRWxlbWVudHMoKTtcbiAgZWxlcy51cGRhdGVTdHlsZSgpO1xufTsgLy8gZGlmZlByb3BzIDogeyBuYW1lID0+IHsgcHJldiwgbmV4dCB9IH1cblxuXG5zdHlmbi51cGRhdGVUcmFuc2l0aW9ucyA9IGZ1bmN0aW9uIChlbGUsIGRpZmZQcm9wcykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgdmFyIHByb3BzID0gZWxlLnBzdHlsZSgndHJhbnNpdGlvbi1wcm9wZXJ0eScpLnZhbHVlO1xuICB2YXIgZHVyYXRpb24gPSBlbGUucHN0eWxlKCd0cmFuc2l0aW9uLWR1cmF0aW9uJykucGZWYWx1ZTtcbiAgdmFyIGRlbGF5ID0gZWxlLnBzdHlsZSgndHJhbnNpdGlvbi1kZWxheScpLnBmVmFsdWU7XG5cbiAgaWYgKHByb3BzLmxlbmd0aCA+IDAgJiYgZHVyYXRpb24gPiAwKSB7XG4gICAgdmFyIHN0eWxlID0ge307IC8vIGJ1aWxkIHVwIHRoZSBzdHlsZSB0byBhbmltYXRlIHRvd2FyZHNcblxuICAgIHZhciBhbnlQcmV2ID0gZmFsc2U7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcHJvcCA9IHByb3BzW2ldO1xuICAgICAgdmFyIHN0eVByb3AgPSBlbGUucHN0eWxlKHByb3ApO1xuICAgICAgdmFyIGRpZmZQcm9wID0gZGlmZlByb3BzW3Byb3BdO1xuXG4gICAgICBpZiAoIWRpZmZQcm9wKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgcHJldlByb3AgPSBkaWZmUHJvcC5wcmV2O1xuICAgICAgdmFyIGZyb21Qcm9wID0gcHJldlByb3A7XG4gICAgICB2YXIgdG9Qcm9wID0gZGlmZlByb3AubmV4dCAhPSBudWxsID8gZGlmZlByb3AubmV4dCA6IHN0eVByb3A7XG4gICAgICB2YXIgZGlmZiA9IGZhbHNlO1xuICAgICAgdmFyIGluaXRWYWwgPSB2b2lkIDA7XG4gICAgICB2YXIgaW5pdER0ID0gMC4wMDAwMDE7IC8vIGRlbHRhIHRpbWUgJSB2YWx1ZSBmb3IgaW5pdFZhbCAoYWxsb3dzIGFuaW1hdGluZyBvdXQgb2YgaW5pdCB6ZXJvIG9wYWNpdHkpXG5cbiAgICAgIGlmICghZnJvbVByb3ApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IC8vIGNvbnNpZGVyIHB4IHZhbHVlc1xuXG5cbiAgICAgIGlmIChudW1iZXIoZnJvbVByb3AucGZWYWx1ZSkgJiYgbnVtYmVyKHRvUHJvcC5wZlZhbHVlKSkge1xuICAgICAgICBkaWZmID0gdG9Qcm9wLnBmVmFsdWUgLSBmcm9tUHJvcC5wZlZhbHVlOyAvLyBub256ZXJvIGlzIHRydXRoeVxuXG4gICAgICAgIGluaXRWYWwgPSBmcm9tUHJvcC5wZlZhbHVlICsgaW5pdER0ICogZGlmZjsgLy8gY29uc2lkZXIgbnVtZXJpY2FsIHZhbHVlc1xuICAgICAgfSBlbHNlIGlmIChudW1iZXIoZnJvbVByb3AudmFsdWUpICYmIG51bWJlcih0b1Byb3AudmFsdWUpKSB7XG4gICAgICAgIGRpZmYgPSB0b1Byb3AudmFsdWUgLSBmcm9tUHJvcC52YWx1ZTsgLy8gbm9uemVybyBpcyB0cnV0aHlcblxuICAgICAgICBpbml0VmFsID0gZnJvbVByb3AudmFsdWUgKyBpbml0RHQgKiBkaWZmOyAvLyBjb25zaWRlciBjb2xvdXIgdmFsdWVzXG4gICAgICB9IGVsc2UgaWYgKGFycmF5KGZyb21Qcm9wLnZhbHVlKSAmJiBhcnJheSh0b1Byb3AudmFsdWUpKSB7XG4gICAgICAgIGRpZmYgPSBmcm9tUHJvcC52YWx1ZVswXSAhPT0gdG9Qcm9wLnZhbHVlWzBdIHx8IGZyb21Qcm9wLnZhbHVlWzFdICE9PSB0b1Byb3AudmFsdWVbMV0gfHwgZnJvbVByb3AudmFsdWVbMl0gIT09IHRvUHJvcC52YWx1ZVsyXTtcbiAgICAgICAgaW5pdFZhbCA9IGZyb21Qcm9wLnN0clZhbHVlO1xuICAgICAgfSAvLyB0aGUgcHJldmlvdXMgdmFsdWUgaXMgZ29vZCBmb3IgYW4gYW5pbWF0aW9uIG9ubHkgaWYgaXQncyBkaWZmZXJlbnRcblxuXG4gICAgICBpZiAoZGlmZikge1xuICAgICAgICBzdHlsZVtwcm9wXSA9IHRvUHJvcC5zdHJWYWx1ZTsgLy8gdG8gdmFsXG5cbiAgICAgICAgdGhpcy5hcHBseUJ5cGFzcyhlbGUsIHByb3AsIGluaXRWYWwpOyAvLyBmcm9tIHZhbFxuXG4gICAgICAgIGFueVByZXYgPSB0cnVlO1xuICAgICAgfVxuICAgIH0gLy8gZW5kIGlmIHByb3BzIGFsbG93IGFuaVxuICAgIC8vIGNhbid0IHRyYW5zaXRpb24gaWYgdGhlcmUncyBub3RoaW5nIHByZXZpb3VzIHRvIHRyYW5zaXRpb24gZnJvbVxuXG5cbiAgICBpZiAoIWFueVByZXYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBfcC50cmFuc2l0aW9uaW5nID0gdHJ1ZTtcbiAgICBuZXcgUHJvbWlzZSQxKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICBpZiAoZGVsYXkgPiAwKSB7XG4gICAgICAgIGVsZS5kZWxheUFuaW1hdGlvbihkZWxheSkucGxheSgpLnByb21pc2UoKS50aGVuKHJlc29sdmUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfVxuICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGVsZS5hbmltYXRpb24oe1xuICAgICAgICBzdHlsZTogc3R5bGUsXG4gICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgZWFzaW5nOiBlbGUucHN0eWxlKCd0cmFuc2l0aW9uLXRpbWluZy1mdW5jdGlvbicpLnZhbHVlLFxuICAgICAgICBxdWV1ZTogZmFsc2VcbiAgICAgIH0pLnBsYXkoKS5wcm9taXNlKCk7XG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBpZiggIWlzQnlwYXNzICl7XG4gICAgICBzZWxmLnJlbW92ZUJ5cGFzc2VzKGVsZSwgcHJvcHMpO1xuICAgICAgZWxlLmVtaXRBbmROb3RpZnkoJ3N0eWxlJyk7IC8vIH1cblxuICAgICAgX3AudHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKF9wLnRyYW5zaXRpb25pbmcpIHtcbiAgICB0aGlzLnJlbW92ZUJ5cGFzc2VzKGVsZSwgcHJvcHMpO1xuICAgIGVsZS5lbWl0QW5kTm90aWZ5KCdzdHlsZScpO1xuICAgIF9wLnRyYW5zaXRpb25pbmcgPSBmYWxzZTtcbiAgfVxufTtcblxuc3R5Zm4uY2hlY2tUcmlnZ2VyID0gZnVuY3Rpb24gKGVsZSwgbmFtZSwgZnJvbVZhbHVlLCB0b1ZhbHVlLCBnZXRUcmlnZ2VyLCBvblRyaWdnZXIpIHtcbiAgdmFyIHByb3AgPSB0aGlzLnByb3BlcnRpZXNbbmFtZV07XG4gIHZhciB0cmlnZ2VyQ2hlY2sgPSBnZXRUcmlnZ2VyKHByb3ApO1xuXG4gIGlmICh0cmlnZ2VyQ2hlY2sgIT0gbnVsbCAmJiB0cmlnZ2VyQ2hlY2soZnJvbVZhbHVlLCB0b1ZhbHVlKSkge1xuICAgIG9uVHJpZ2dlcihwcm9wKTtcbiAgfVxufTtcblxuc3R5Zm4uY2hlY2taT3JkZXJUcmlnZ2VyID0gZnVuY3Rpb24gKGVsZSwgbmFtZSwgZnJvbVZhbHVlLCB0b1ZhbHVlKSB7XG4gIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgdGhpcy5jaGVja1RyaWdnZXIoZWxlLCBuYW1lLCBmcm9tVmFsdWUsIHRvVmFsdWUsIGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgcmV0dXJuIHByb3AudHJpZ2dlcnNaT3JkZXI7XG4gIH0sIGZ1bmN0aW9uICgpIHtcbiAgICBfdGhpcy5fcHJpdmF0ZS5jeS5ub3RpZnkoJ3pvcmRlcicsIGVsZSk7XG4gIH0pO1xufTtcblxuc3R5Zm4uY2hlY2tCb3VuZHNUcmlnZ2VyID0gZnVuY3Rpb24gKGVsZSwgbmFtZSwgZnJvbVZhbHVlLCB0b1ZhbHVlKSB7XG4gIHRoaXMuY2hlY2tUcmlnZ2VyKGVsZSwgbmFtZSwgZnJvbVZhbHVlLCB0b1ZhbHVlLCBmdW5jdGlvbiAocHJvcCkge1xuICAgIHJldHVybiBwcm9wLnRyaWdnZXJzQm91bmRzO1xuICB9LCBmdW5jdGlvbiAocHJvcCkge1xuICAgIGVsZS5kaXJ0eUNvbXBvdW5kQm91bmRzQ2FjaGUoKTtcbiAgICBlbGUuZGlydHlCb3VuZGluZ0JveENhY2hlKCk7IC8vIGlmIHRoZSBwcm9wIGNoYW5nZSBtYWtlcyB0aGUgYmIgb2YgcGxsIGJlemllciBlZGdlcyBpbnZhbGlkLFxuICAgIC8vIHRoZW4gZGlydHkgdGhlIHBsbCBlZGdlIGJiIGNhY2hlIGFzIHdlbGxcblxuICAgIGlmICggLy8gb25seSBmb3IgYmV6aWVycyAtLSBzbyBwZXJmb3JtYW5jZSBvZiBvdGhlciBlZGdlcyBpc24ndCBhZmZlY3RlZFxuICAgIChlbGUucHN0eWxlKCdjdXJ2ZS1zdHlsZScpLnZhbHVlID09PSAnYmV6aWVyJyAvLyBhbHJlYWR5IGEgYmV6aWVyXG4gICAgLy8gd2FzIGp1c3Qgbm93IGNoYW5nZWQgdG8gb3IgZnJvbSBhIGJlemllcjpcbiAgICB8fCBuYW1lID09PSAnY3VydmUtc3R5bGUnICYmIChmcm9tVmFsdWUgPT09ICdiZXppZXInIHx8IHRvVmFsdWUgPT09ICdiZXppZXInKSkgJiYgcHJvcC50cmlnZ2Vyc0JvdW5kc09mUGFyYWxsZWxCZXppZXJzKSB7XG4gICAgICBlbGUucGFyYWxsZWxFZGdlcygpLmZvckVhY2goZnVuY3Rpb24gKHBsbEVkZ2UpIHtcbiAgICAgICAgaWYgKHBsbEVkZ2UuaXNCdW5kbGVkQmV6aWVyKCkpIHtcbiAgICAgICAgICBwbGxFZGdlLmRpcnR5Qm91bmRpbmdCb3hDYWNoZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0pO1xufTtcblxuc3R5Zm4uY2hlY2tUcmlnZ2VycyA9IGZ1bmN0aW9uIChlbGUsIG5hbWUsIGZyb21WYWx1ZSwgdG9WYWx1ZSkge1xuICBlbGUuZGlydHlTdHlsZUNhY2hlKCk7XG4gIHRoaXMuY2hlY2taT3JkZXJUcmlnZ2VyKGVsZSwgbmFtZSwgZnJvbVZhbHVlLCB0b1ZhbHVlKTtcbiAgdGhpcy5jaGVja0JvdW5kc1RyaWdnZXIoZWxlLCBuYW1lLCBmcm9tVmFsdWUsIHRvVmFsdWUpO1xufTtcblxudmFyIHN0eWZuJDEgPSB7fTsgLy8gYnlwYXNzZXMgYXJlIGFwcGxpZWQgdG8gYW4gZXhpc3Rpbmcgc3R5bGUgb24gYW4gZWxlbWVudCwgYW5kIGp1c3QgdGFja2VkIG9uIHRlbXBvcmFyaWx5XG4vLyByZXR1cm5zIHRydWUgaWZmIGFwcGxpY2F0aW9uIHdhcyBzdWNjZXNzZnVsIGZvciBhdCBsZWFzdCAxIHNwZWNpZmllZCBwcm9wZXJ0eVxuXG5zdHlmbiQxLmFwcGx5QnlwYXNzID0gZnVuY3Rpb24gKGVsZXMsIG5hbWUsIHZhbHVlLCB1cGRhdGVUcmFuc2l0aW9ucykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBwcm9wcyA9IFtdO1xuICB2YXIgaXNCeXBhc3MgPSB0cnVlOyAvLyBwdXQgYWxsIHRoZSBwcm9wZXJ0aWVzIChjYW4gc3BlY2lmeSBvbmUgb3IgbWFueSkgaW4gYW4gYXJyYXkgYWZ0ZXIgcGFyc2luZyB0aGVtXG5cbiAgaWYgKG5hbWUgPT09ICcqJyB8fCBuYW1lID09PSAnKionKSB7XG4gICAgLy8gYXBwbHkgdG8gYWxsIHByb3BlcnR5IG5hbWVzXG4gICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5wcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwcm9wID0gc2VsZi5wcm9wZXJ0aWVzW2ldO1xuICAgICAgICB2YXIgX25hbWUgPSBwcm9wLm5hbWU7XG4gICAgICAgIHZhciBwYXJzZWRQcm9wID0gdGhpcy5wYXJzZShfbmFtZSwgdmFsdWUsIHRydWUpO1xuXG4gICAgICAgIGlmIChwYXJzZWRQcm9wKSB7XG4gICAgICAgICAgcHJvcHMucHVzaChwYXJzZWRQcm9wKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChzdHJpbmcobmFtZSkpIHtcbiAgICAvLyB0aGVuIHBhcnNlIHRoZSBzaW5nbGUgcHJvcGVydHlcbiAgICB2YXIgX3BhcnNlZFByb3AgPSB0aGlzLnBhcnNlKG5hbWUsIHZhbHVlLCB0cnVlKTtcblxuICAgIGlmIChfcGFyc2VkUHJvcCkge1xuICAgICAgcHJvcHMucHVzaChfcGFyc2VkUHJvcCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKHBsYWluT2JqZWN0KG5hbWUpKSB7XG4gICAgLy8gdGhlbiBwYXJzZSBlYWNoIHByb3BlcnR5XG4gICAgdmFyIHNwZWNpZmllZFByb3BzID0gbmFtZTtcbiAgICB1cGRhdGVUcmFuc2l0aW9ucyA9IHZhbHVlO1xuICAgIHZhciBuYW1lcyA9IE9iamVjdC5rZXlzKHNwZWNpZmllZFByb3BzKTtcblxuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBuYW1lcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgIHZhciBfbmFtZTIgPSBuYW1lc1tfaV07XG4gICAgICB2YXIgX3ZhbHVlID0gc3BlY2lmaWVkUHJvcHNbX25hbWUyXTtcblxuICAgICAgaWYgKF92YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIHRyeSBjYW1lbCBjYXNlIG5hbWUgdG9vXG4gICAgICAgIF92YWx1ZSA9IHNwZWNpZmllZFByb3BzW2Rhc2gyY2FtZWwoX25hbWUyKV07XG4gICAgICB9XG5cbiAgICAgIGlmIChfdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgX3BhcnNlZFByb3AyID0gdGhpcy5wYXJzZShfbmFtZTIsIF92YWx1ZSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKF9wYXJzZWRQcm9wMikge1xuICAgICAgICAgIHByb3BzLnB1c2goX3BhcnNlZFByb3AyKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBjYW4ndCBkbyBhbnl0aGluZyB3aXRob3V0IHdlbGwgZGVmaW5lZCBwcm9wZXJ0aWVzXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IC8vIHdlJ3ZlIGZhaWxlZCBpZiB0aGVyZSBhcmUgbm8gdmFsaWQgcHJvcGVydGllc1xuXG5cbiAgaWYgKHByb3BzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSAvLyBub3csIGFwcGx5IHRoZSBieXBhc3MgcHJvcGVydGllcyBvbiB0aGUgZWxlbWVudHNcblxuXG4gIHZhciByZXQgPSBmYWxzZTsgLy8gcmV0dXJuIHRydWUgaWYgYXQgbGVhc3Qgb25lIHN1Y2Nlc2Z1bCBieXBhc3MgYXBwbGllZFxuXG4gIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IGVsZXMubGVuZ3RoOyBfaTIrKykge1xuICAgIC8vIGZvciBlYWNoIGVsZVxuICAgIHZhciBlbGUgPSBlbGVzW19pMl07XG4gICAgdmFyIGRpZmZQcm9wcyA9IHt9O1xuICAgIHZhciBkaWZmUHJvcCA9IHZvaWQgMDtcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgcHJvcHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIC8vIGZvciBlYWNoIHByb3BcbiAgICAgIHZhciBfcHJvcCA9IHByb3BzW2pdO1xuXG4gICAgICBpZiAodXBkYXRlVHJhbnNpdGlvbnMpIHtcbiAgICAgICAgdmFyIHByZXZQcm9wID0gZWxlLnBzdHlsZShfcHJvcC5uYW1lKTtcbiAgICAgICAgZGlmZlByb3AgPSBkaWZmUHJvcHNbX3Byb3AubmFtZV0gPSB7XG4gICAgICAgICAgcHJldjogcHJldlByb3BcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgcmV0ID0gdGhpcy5hcHBseVBhcnNlZFByb3BlcnR5KGVsZSwgX3Byb3ApIHx8IHJldDtcblxuICAgICAgaWYgKHVwZGF0ZVRyYW5zaXRpb25zKSB7XG4gICAgICAgIGRpZmZQcm9wLm5leHQgPSBlbGUucHN0eWxlKF9wcm9wLm5hbWUpO1xuICAgICAgfVxuICAgIH0gLy8gZm9yIHByb3BzXG5cblxuICAgIGlmIChyZXQpIHtcbiAgICAgIHRoaXMudXBkYXRlU3R5bGVIaW50cyhlbGUpO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVUcmFuc2l0aW9ucykge1xuICAgICAgdGhpcy51cGRhdGVUcmFuc2l0aW9ucyhlbGUsIGRpZmZQcm9wcywgaXNCeXBhc3MpO1xuICAgIH1cbiAgfSAvLyBmb3IgZWxlc1xuXG5cbiAgcmV0dXJuIHJldDtcbn07IC8vIG9ubHkgdXNlZnVsIGluIHNwZWNpZmljIGNhc2VzIGxpa2UgYW5pbWF0aW9uXG5cblxuc3R5Zm4kMS5vdmVycmlkZUJ5cGFzcyA9IGZ1bmN0aW9uIChlbGVzLCBuYW1lLCB2YWx1ZSkge1xuICBuYW1lID0gY2FtZWwyZGFzaChuYW1lKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICB2YXIgcHJvcCA9IGVsZS5fcHJpdmF0ZS5zdHlsZVtuYW1lXTtcbiAgICB2YXIgdHlwZSA9IHRoaXMucHJvcGVydGllc1tuYW1lXS50eXBlO1xuICAgIHZhciBpc0NvbG9yID0gdHlwZS5jb2xvcjtcbiAgICB2YXIgaXNNdWx0aSA9IHR5cGUubXV0aXBsZTtcbiAgICB2YXIgb2xkVmFsdWUgPSAhcHJvcCA/IG51bGwgOiBwcm9wLnBmVmFsdWUgIT0gbnVsbCA/IHByb3AucGZWYWx1ZSA6IHByb3AudmFsdWU7XG5cbiAgICBpZiAoIXByb3AgfHwgIXByb3AuYnlwYXNzKSB7XG4gICAgICAvLyBuZWVkIGEgYnlwYXNzIGlmIG9uZSBkb2Vzbid0IGV4aXN0XG4gICAgICB0aGlzLmFwcGx5QnlwYXNzKGVsZSwgbmFtZSwgdmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9wLnZhbHVlID0gdmFsdWU7XG5cbiAgICAgIGlmIChwcm9wLnBmVmFsdWUgIT0gbnVsbCkge1xuICAgICAgICBwcm9wLnBmVmFsdWUgPSB2YWx1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzQ29sb3IpIHtcbiAgICAgICAgcHJvcC5zdHJWYWx1ZSA9ICdyZ2IoJyArIHZhbHVlLmpvaW4oJywnKSArICcpJztcbiAgICAgIH0gZWxzZSBpZiAoaXNNdWx0aSkge1xuICAgICAgICBwcm9wLnN0clZhbHVlID0gdmFsdWUuam9pbignICcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJvcC5zdHJWYWx1ZSA9ICcnICsgdmFsdWU7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudXBkYXRlU3R5bGVIaW50cyhlbGUpO1xuICAgIH1cblxuICAgIHRoaXMuY2hlY2tUcmlnZ2VycyhlbGUsIG5hbWUsIG9sZFZhbHVlLCB2YWx1ZSk7XG4gIH1cbn07XG5cbnN0eWZuJDEucmVtb3ZlQWxsQnlwYXNzZXMgPSBmdW5jdGlvbiAoZWxlcywgdXBkYXRlVHJhbnNpdGlvbnMpIHtcbiAgcmV0dXJuIHRoaXMucmVtb3ZlQnlwYXNzZXMoZWxlcywgdGhpcy5wcm9wZXJ0eU5hbWVzLCB1cGRhdGVUcmFuc2l0aW9ucyk7XG59O1xuXG5zdHlmbiQxLnJlbW92ZUJ5cGFzc2VzID0gZnVuY3Rpb24gKGVsZXMsIHByb3BzLCB1cGRhdGVUcmFuc2l0aW9ucykge1xuICB2YXIgaXNCeXBhc3MgPSB0cnVlO1xuXG4gIGZvciAodmFyIGogPSAwOyBqIDwgZWxlcy5sZW5ndGg7IGorKykge1xuICAgIHZhciBlbGUgPSBlbGVzW2pdO1xuICAgIHZhciBkaWZmUHJvcHMgPSB7fTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBuYW1lID0gcHJvcHNbaV07XG4gICAgICB2YXIgcHJvcCA9IHRoaXMucHJvcGVydGllc1tuYW1lXTtcbiAgICAgIHZhciBwcmV2UHJvcCA9IGVsZS5wc3R5bGUocHJvcC5uYW1lKTtcblxuICAgICAgaWYgKCFwcmV2UHJvcCB8fCAhcHJldlByb3AuYnlwYXNzKSB7XG4gICAgICAgIC8vIGlmIGEgYnlwYXNzIGRvZXNuJ3QgZXhpc3QgZm9yIHRoZSBwcm9wLCBub3RoaW5nIG5lZWRzIHRvIGJlIHJlbW92ZWRcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciB2YWx1ZSA9ICcnOyAvLyBlbXB0eSA9PiByZW1vdmUgYnlwYXNzXG5cbiAgICAgIHZhciBwYXJzZWRQcm9wID0gdGhpcy5wYXJzZShuYW1lLCB2YWx1ZSwgdHJ1ZSk7XG4gICAgICB2YXIgZGlmZlByb3AgPSBkaWZmUHJvcHNbcHJvcC5uYW1lXSA9IHtcbiAgICAgICAgcHJldjogcHJldlByb3BcbiAgICAgIH07XG4gICAgICB0aGlzLmFwcGx5UGFyc2VkUHJvcGVydHkoZWxlLCBwYXJzZWRQcm9wKTtcbiAgICAgIGRpZmZQcm9wLm5leHQgPSBlbGUucHN0eWxlKHByb3AubmFtZSk7XG4gICAgfSAvLyBmb3IgcHJvcHNcblxuXG4gICAgdGhpcy51cGRhdGVTdHlsZUhpbnRzKGVsZSk7XG5cbiAgICBpZiAodXBkYXRlVHJhbnNpdGlvbnMpIHtcbiAgICAgIHRoaXMudXBkYXRlVHJhbnNpdGlvbnMoZWxlLCBkaWZmUHJvcHMsIGlzQnlwYXNzKTtcbiAgICB9XG4gIH0gLy8gZm9yIGVsZXNcblxufTtcblxudmFyIHN0eWZuJDIgPSB7fTsgLy8gZ2V0cyB3aGF0IGFuIGVtIHNpemUgY29ycmVzcG9uZHMgdG8gaW4gcGl4ZWxzIHJlbGF0aXZlIHRvIGEgZG9tIGVsZW1lbnRcblxuc3R5Zm4kMi5nZXRFbVNpemVJblBpeGVscyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHB4ID0gdGhpcy5jb250YWluZXJDc3MoJ2ZvbnQtc2l6ZScpO1xuXG4gIGlmIChweCAhPSBudWxsKSB7XG4gICAgcmV0dXJuIHBhcnNlRmxvYXQocHgpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiAxOyAvLyBmb3IgaGVhZGxlc3NcbiAgfVxufTsgLy8gZ2V0cyBjc3MgcHJvcGVydHkgZnJvbSB0aGUgY29yZSBjb250YWluZXJcblxuXG5zdHlmbiQyLmNvbnRhaW5lckNzcyA9IGZ1bmN0aW9uIChwcm9wTmFtZSkge1xuICB2YXIgY3kgPSB0aGlzLl9wcml2YXRlLmN5O1xuICB2YXIgZG9tRWxlbWVudCA9IGN5LmNvbnRhaW5lcigpO1xuXG4gIGlmICh3aW5kb3ckMSAmJiBkb21FbGVtZW50ICYmIHdpbmRvdyQxLmdldENvbXB1dGVkU3R5bGUpIHtcbiAgICByZXR1cm4gd2luZG93JDEuZ2V0Q29tcHV0ZWRTdHlsZShkb21FbGVtZW50KS5nZXRQcm9wZXJ0eVZhbHVlKHByb3BOYW1lKTtcbiAgfVxufTtcblxudmFyIHN0eWZuJDMgPSB7fTsgLy8gZ2V0cyB0aGUgcmVuZGVyZWQgc3R5bGUgZm9yIGFuIGVsZW1lbnRcblxuc3R5Zm4kMy5nZXRSZW5kZXJlZFN0eWxlID0gZnVuY3Rpb24gKGVsZSwgcHJvcCkge1xuICBpZiAocHJvcCkge1xuICAgIHJldHVybiB0aGlzLmdldFN0eWxlUHJvcGVydHlWYWx1ZShlbGUsIHByb3AsIHRydWUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB0aGlzLmdldFJhd1N0eWxlKGVsZSwgdHJ1ZSk7XG4gIH1cbn07IC8vIGdldHMgdGhlIHJhdyBzdHlsZSBmb3IgYW4gZWxlbWVudFxuXG5cbnN0eWZuJDMuZ2V0UmF3U3R5bGUgPSBmdW5jdGlvbiAoZWxlLCBpc1JlbmRlcmVkVmFsKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgZWxlID0gZWxlWzBdOyAvLyBpbnN1cmUgaXQncyBhbiBlbGVtZW50XG5cbiAgaWYgKGVsZSkge1xuICAgIHZhciByc3R5bGUgPSB7fTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5wcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcHJvcCA9IHNlbGYucHJvcGVydGllc1tpXTtcbiAgICAgIHZhciB2YWwgPSBzZWxmLmdldFN0eWxlUHJvcGVydHlWYWx1ZShlbGUsIHByb3AubmFtZSwgaXNSZW5kZXJlZFZhbCk7XG5cbiAgICAgIGlmICh2YWwgIT0gbnVsbCkge1xuICAgICAgICByc3R5bGVbcHJvcC5uYW1lXSA9IHZhbDtcbiAgICAgICAgcnN0eWxlW2Rhc2gyY2FtZWwocHJvcC5uYW1lKV0gPSB2YWw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJzdHlsZTtcbiAgfVxufTtcblxuc3R5Zm4kMy5nZXRJbmRleGVkU3R5bGUgPSBmdW5jdGlvbiAoZWxlLCBwcm9wZXJ0eSwgc3VicHJvcGVydHksIGluZGV4KSB7XG4gIHZhciBwc3R5bGUgPSBlbGUucHN0eWxlKHByb3BlcnR5KVtzdWJwcm9wZXJ0eV1baW5kZXhdO1xuICByZXR1cm4gcHN0eWxlICE9IG51bGwgPyBwc3R5bGUgOiBlbGUuY3koKS5zdHlsZSgpLmdldERlZmF1bHRQcm9wZXJ0eShwcm9wZXJ0eSlbc3VicHJvcGVydHldWzBdO1xufTtcblxuc3R5Zm4kMy5nZXRTdHlsZVByb3BlcnR5VmFsdWUgPSBmdW5jdGlvbiAoZWxlLCBwcm9wTmFtZSwgaXNSZW5kZXJlZFZhbCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIGVsZSA9IGVsZVswXTsgLy8gaW5zdXJlIGl0J3MgYW4gZWxlbWVudFxuXG4gIGlmIChlbGUpIHtcbiAgICB2YXIgcHJvcCA9IHNlbGYucHJvcGVydGllc1twcm9wTmFtZV07XG5cbiAgICBpZiAocHJvcC5hbGlhcykge1xuICAgICAgcHJvcCA9IHByb3AucG9pbnRzVG87XG4gICAgfVxuXG4gICAgdmFyIHR5cGUgPSBwcm9wLnR5cGU7XG4gICAgdmFyIHN0eWxlUHJvcCA9IGVsZS5wc3R5bGUocHJvcC5uYW1lKTtcblxuICAgIGlmIChzdHlsZVByb3ApIHtcbiAgICAgIHZhciB2YWx1ZSA9IHN0eWxlUHJvcC52YWx1ZSxcbiAgICAgICAgICB1bml0cyA9IHN0eWxlUHJvcC51bml0cyxcbiAgICAgICAgICBzdHJWYWx1ZSA9IHN0eWxlUHJvcC5zdHJWYWx1ZTtcblxuICAgICAgaWYgKGlzUmVuZGVyZWRWYWwgJiYgdHlwZS5udW1iZXIgJiYgdmFsdWUgIT0gbnVsbCAmJiBudW1iZXIodmFsdWUpKSB7XG4gICAgICAgIHZhciB6b29tID0gZWxlLmN5KCkuem9vbSgpO1xuXG4gICAgICAgIHZhciBnZXRSZW5kZXJlZFZhbHVlID0gZnVuY3Rpb24gZ2V0UmVuZGVyZWRWYWx1ZSh2YWwpIHtcbiAgICAgICAgICByZXR1cm4gdmFsICogem9vbTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgZ2V0VmFsdWVTdHJpbmdXaXRoVW5pdHMgPSBmdW5jdGlvbiBnZXRWYWx1ZVN0cmluZ1dpdGhVbml0cyh2YWwsIHVuaXRzKSB7XG4gICAgICAgICAgcmV0dXJuIGdldFJlbmRlcmVkVmFsdWUodmFsKSArIHVuaXRzO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBpc0FycmF5VmFsdWUgPSBhcnJheSh2YWx1ZSk7XG4gICAgICAgIHZhciBoYXZlVW5pdHMgPSBpc0FycmF5VmFsdWUgPyB1bml0cy5ldmVyeShmdW5jdGlvbiAodSkge1xuICAgICAgICAgIHJldHVybiB1ICE9IG51bGw7XG4gICAgICAgIH0pIDogdW5pdHMgIT0gbnVsbDtcblxuICAgICAgICBpZiAoaGF2ZVVuaXRzKSB7XG4gICAgICAgICAgaWYgKGlzQXJyYXlWYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlLm1hcChmdW5jdGlvbiAodiwgaSkge1xuICAgICAgICAgICAgICByZXR1cm4gZ2V0VmFsdWVTdHJpbmdXaXRoVW5pdHModiwgdW5pdHNbaV0pO1xuICAgICAgICAgICAgfSkuam9pbignICcpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0VmFsdWVTdHJpbmdXaXRoVW5pdHModmFsdWUsIHVuaXRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGlzQXJyYXlWYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlLm1hcChmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nKHYpID8gdiA6ICcnICsgZ2V0UmVuZGVyZWRWYWx1ZSh2KTtcbiAgICAgICAgICAgIH0pLmpvaW4oJyAnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICcnICsgZ2V0UmVuZGVyZWRWYWx1ZSh2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0clZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHN0clZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG59O1xuXG5zdHlmbiQzLmdldEFuaW1hdGlvblN0YXJ0U3R5bGUgPSBmdW5jdGlvbiAoZWxlLCBhbmlQcm9wcykge1xuICB2YXIgcnN0eWxlID0ge307XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbmlQcm9wcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBhbmlQcm9wID0gYW5pUHJvcHNbaV07XG4gICAgdmFyIG5hbWUgPSBhbmlQcm9wLm5hbWU7XG4gICAgdmFyIHN0eWxlUHJvcCA9IGVsZS5wc3R5bGUobmFtZSk7XG5cbiAgICBpZiAoc3R5bGVQcm9wICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIHRoZW4gbWFrZSBhIHByb3Agb2YgaXRcbiAgICAgIGlmIChwbGFpbk9iamVjdChzdHlsZVByb3ApKSB7XG4gICAgICAgIHN0eWxlUHJvcCA9IHRoaXMucGFyc2UobmFtZSwgc3R5bGVQcm9wLnN0clZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlUHJvcCA9IHRoaXMucGFyc2UobmFtZSwgc3R5bGVQcm9wKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc3R5bGVQcm9wKSB7XG4gICAgICByc3R5bGVbbmFtZV0gPSBzdHlsZVByb3A7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJzdHlsZTtcbn07XG5cbnN0eWZuJDMuZ2V0UHJvcHNMaXN0ID0gZnVuY3Rpb24gKHByb3BzT2JqKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHJzdHlsZSA9IFtdO1xuICB2YXIgc3R5bGUgPSBwcm9wc09iajtcbiAgdmFyIHByb3BzID0gc2VsZi5wcm9wZXJ0aWVzO1xuXG4gIGlmIChzdHlsZSkge1xuICAgIHZhciBuYW1lcyA9IE9iamVjdC5rZXlzKHN0eWxlKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBuYW1lID0gbmFtZXNbaV07XG4gICAgICB2YXIgdmFsID0gc3R5bGVbbmFtZV07XG4gICAgICB2YXIgcHJvcCA9IHByb3BzW25hbWVdIHx8IHByb3BzW2NhbWVsMmRhc2gobmFtZSldO1xuICAgICAgdmFyIHN0eWxlUHJvcCA9IHRoaXMucGFyc2UocHJvcC5uYW1lLCB2YWwpO1xuXG4gICAgICBpZiAoc3R5bGVQcm9wKSB7XG4gICAgICAgIHJzdHlsZS5wdXNoKHN0eWxlUHJvcCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJzdHlsZTtcbn07XG5cbnN0eWZuJDMuZ2V0Tm9uRGVmYXVsdFByb3BlcnRpZXNIYXNoID0gZnVuY3Rpb24gKGVsZSwgcHJvcE5hbWVzLCBzZWVkKSB7XG4gIHZhciBoYXNoID0gc2VlZC5zbGljZSgpO1xuICB2YXIgbmFtZSwgdmFsLCBzdHJWYWwsIGNoVmFsO1xuICB2YXIgaSwgajtcblxuICBmb3IgKGkgPSAwOyBpIDwgcHJvcE5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgbmFtZSA9IHByb3BOYW1lc1tpXTtcbiAgICB2YWwgPSBlbGUucHN0eWxlKG5hbWUsIGZhbHNlKTtcblxuICAgIGlmICh2YWwgPT0gbnVsbCkge1xuICAgICAgY29udGludWU7XG4gICAgfSBlbHNlIGlmICh2YWwucGZWYWx1ZSAhPSBudWxsKSB7XG4gICAgICBoYXNoWzBdID0gaGFzaEludChjaFZhbCwgaGFzaFswXSk7XG4gICAgICBoYXNoWzFdID0gaGFzaEludEFsdChjaFZhbCwgaGFzaFsxXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0clZhbCA9IHZhbC5zdHJWYWx1ZTtcblxuICAgICAgZm9yIChqID0gMDsgaiA8IHN0clZhbC5sZW5ndGg7IGorKykge1xuICAgICAgICBjaFZhbCA9IHN0clZhbC5jaGFyQ29kZUF0KGopO1xuICAgICAgICBoYXNoWzBdID0gaGFzaEludChjaFZhbCwgaGFzaFswXSk7XG4gICAgICAgIGhhc2hbMV0gPSBoYXNoSW50QWx0KGNoVmFsLCBoYXNoWzFdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gaGFzaDtcbn07XG5cbnN0eWZuJDMuZ2V0UHJvcGVydGllc0hhc2ggPSBzdHlmbiQzLmdldE5vbkRlZmF1bHRQcm9wZXJ0aWVzSGFzaDtcblxudmFyIHN0eWZuJDQgPSB7fTtcblxuc3R5Zm4kNC5hcHBlbmRGcm9tSnNvbiA9IGZ1bmN0aW9uIChqc29uKSB7XG4gIHZhciBzdHlsZSA9IHRoaXM7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBqc29uLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGNvbnRleHQgPSBqc29uW2ldO1xuICAgIHZhciBzZWxlY3RvciA9IGNvbnRleHQuc2VsZWN0b3I7XG4gICAgdmFyIHByb3BzID0gY29udGV4dC5zdHlsZSB8fCBjb250ZXh0LmNzcztcbiAgICB2YXIgbmFtZXMgPSBPYmplY3Qua2V5cyhwcm9wcyk7XG4gICAgc3R5bGUuc2VsZWN0b3Ioc2VsZWN0b3IpOyAvLyBhcHBseSBzZWxlY3RvclxuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBuYW1lcy5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIG5hbWUgPSBuYW1lc1tqXTtcbiAgICAgIHZhciB2YWx1ZSA9IHByb3BzW25hbWVdO1xuICAgICAgc3R5bGUuY3NzKG5hbWUsIHZhbHVlKTsgLy8gYXBwbHkgcHJvcGVydHlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gc3R5bGU7XG59OyAvLyBhY2Nlc3NpYmxlIGN5LnN0eWxlKCkgZnVuY3Rpb25cblxuXG5zdHlmbiQ0LmZyb21Kc29uID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgdmFyIHN0eWxlID0gdGhpcztcbiAgc3R5bGUucmVzZXRUb0RlZmF1bHQoKTtcbiAgc3R5bGUuYXBwZW5kRnJvbUpzb24oanNvbik7XG4gIHJldHVybiBzdHlsZTtcbn07IC8vIGdldCBqc29uIGZyb20gY3kuc3R5bGUoKSBhcGlcblxuXG5zdHlmbiQ0Lmpzb24gPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBqc29uID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHRoaXMuZGVmYXVsdExlbmd0aDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgY3h0ID0gdGhpc1tpXTtcbiAgICB2YXIgc2VsZWN0b3IgPSBjeHQuc2VsZWN0b3I7XG4gICAgdmFyIHByb3BzID0gY3h0LnByb3BlcnRpZXM7XG4gICAgdmFyIGNzcyA9IHt9O1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwcm9wcy5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIHByb3AgPSBwcm9wc1tqXTtcbiAgICAgIGNzc1twcm9wLm5hbWVdID0gcHJvcC5zdHJWYWx1ZTtcbiAgICB9XG5cbiAgICBqc29uLnB1c2goe1xuICAgICAgc2VsZWN0b3I6ICFzZWxlY3RvciA/ICdjb3JlJyA6IHNlbGVjdG9yLnRvU3RyaW5nKCksXG4gICAgICBzdHlsZTogY3NzXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4ganNvbjtcbn07XG5cbnZhciBzdHlmbiQ1ID0ge307XG5cbnN0eWZuJDUuYXBwZW5kRnJvbVN0cmluZyA9IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgc3R5bGUgPSB0aGlzO1xuICB2YXIgcmVtYWluaW5nID0gJycgKyBzdHJpbmc7XG4gIHZhciBzZWxBbmRCbG9ja1N0cjtcbiAgdmFyIGJsb2NrUmVtO1xuICB2YXIgcHJvcEFuZFZhbFN0cjsgLy8gcmVtb3ZlIGNvbW1lbnRzIGZyb20gdGhlIHN0eWxlIHN0cmluZ1xuXG4gIHJlbWFpbmluZyA9IHJlbWFpbmluZy5yZXBsYWNlKC9bL11bKl0oXFxzfC4pKz9bKl1bL10vZywgJycpO1xuXG4gIGZ1bmN0aW9uIHJlbW92ZVNlbEFuZEJsb2NrRnJvbVJlbWFpbmluZygpIHtcbiAgICAvLyByZW1vdmUgdGhlIHBhcnNlZCBzZWxlY3RvciBhbmQgYmxvY2sgZnJvbSB0aGUgcmVtYWluaW5nIHRleHQgdG8gcGFyc2VcbiAgICBpZiAocmVtYWluaW5nLmxlbmd0aCA+IHNlbEFuZEJsb2NrU3RyLmxlbmd0aCkge1xuICAgICAgcmVtYWluaW5nID0gcmVtYWluaW5nLnN1YnN0cihzZWxBbmRCbG9ja1N0ci5sZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZW1haW5pbmcgPSAnJztcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVQcm9wQW5kVmFsRnJvbVJlbSgpIHtcbiAgICAvLyByZW1vdmUgdGhlIHBhcnNlZCBwcm9wZXJ0eSBhbmQgdmFsdWUgZnJvbSB0aGUgcmVtYWluaW5nIGJsb2NrIHRleHQgdG8gcGFyc2VcbiAgICBpZiAoYmxvY2tSZW0ubGVuZ3RoID4gcHJvcEFuZFZhbFN0ci5sZW5ndGgpIHtcbiAgICAgIGJsb2NrUmVtID0gYmxvY2tSZW0uc3Vic3RyKHByb3BBbmRWYWxTdHIubGVuZ3RoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYmxvY2tSZW0gPSAnJztcbiAgICB9XG4gIH1cblxuICBmb3IgKDs7KSB7XG4gICAgdmFyIG5vdGhpbmdMZWZ0VG9QYXJzZSA9IHJlbWFpbmluZy5tYXRjaCgvXlxccyokLyk7XG5cbiAgICBpZiAobm90aGluZ0xlZnRUb1BhcnNlKSB7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICB2YXIgc2VsQW5kQmxvY2sgPSByZW1haW5pbmcubWF0Y2goL15cXHMqKCg/Oi58XFxzKSs/KVxccypcXHsoKD86LnxcXHMpKz8pXFx9Lyk7XG5cbiAgICBpZiAoIXNlbEFuZEJsb2NrKSB7XG4gICAgICB3YXJuKCdIYWx0aW5nIHN0eWxlc2hlZXQgcGFyc2luZzogU3RyaW5nIHN0eWxlc2hlZXQgY29udGFpbnMgbW9yZSB0byBwYXJzZSBidXQgbm8gc2VsZWN0b3IgYW5kIGJsb2NrIGZvdW5kIGluOiAnICsgcmVtYWluaW5nKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHNlbEFuZEJsb2NrU3RyID0gc2VsQW5kQmxvY2tbMF07IC8vIHBhcnNlIHRoZSBzZWxlY3RvclxuXG4gICAgdmFyIHNlbGVjdG9yU3RyID0gc2VsQW5kQmxvY2tbMV07XG5cbiAgICBpZiAoc2VsZWN0b3JTdHIgIT09ICdjb3JlJykge1xuICAgICAgdmFyIHNlbGVjdG9yID0gbmV3IFNlbGVjdG9yKHNlbGVjdG9yU3RyKTtcblxuICAgICAgaWYgKHNlbGVjdG9yLmludmFsaWQpIHtcbiAgICAgICAgd2FybignU2tpcHBpbmcgcGFyc2luZyBvZiBibG9jazogSW52YWxpZCBzZWxlY3RvciBmb3VuZCBpbiBzdHJpbmcgc3R5bGVzaGVldDogJyArIHNlbGVjdG9yU3RyKTsgLy8gc2tpcCB0aGlzIHNlbGVjdG9yIGFuZCBibG9ja1xuXG4gICAgICAgIHJlbW92ZVNlbEFuZEJsb2NrRnJvbVJlbWFpbmluZygpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9IC8vIHBhcnNlIHRoZSBibG9jayBvZiBwcm9wZXJ0aWVzIGFuZCB2YWx1ZXNcblxuXG4gICAgdmFyIGJsb2NrU3RyID0gc2VsQW5kQmxvY2tbMl07XG4gICAgdmFyIGludmFsaWRCbG9jayA9IGZhbHNlO1xuICAgIGJsb2NrUmVtID0gYmxvY2tTdHI7XG4gICAgdmFyIHByb3BzID0gW107XG5cbiAgICBmb3IgKDs7KSB7XG4gICAgICB2YXIgX25vdGhpbmdMZWZ0VG9QYXJzZSA9IGJsb2NrUmVtLm1hdGNoKC9eXFxzKiQvKTtcblxuICAgICAgaWYgKF9ub3RoaW5nTGVmdFRvUGFyc2UpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIHZhciBwcm9wQW5kVmFsID0gYmxvY2tSZW0ubWF0Y2goL15cXHMqKC4rPylcXHMqOlxccyooLis/KVxccyo7Lyk7XG5cbiAgICAgIGlmICghcHJvcEFuZFZhbCkge1xuICAgICAgICB3YXJuKCdTa2lwcGluZyBwYXJzaW5nIG9mIGJsb2NrOiBJbnZhbGlkIGZvcm1hdHRpbmcgb2Ygc3R5bGUgcHJvcGVydHkgYW5kIHZhbHVlIGRlZmluaXRpb25zIGZvdW5kIGluOicgKyBibG9ja1N0cik7XG4gICAgICAgIGludmFsaWRCbG9jayA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBwcm9wQW5kVmFsU3RyID0gcHJvcEFuZFZhbFswXTtcbiAgICAgIHZhciBwcm9wU3RyID0gcHJvcEFuZFZhbFsxXTtcbiAgICAgIHZhciB2YWxTdHIgPSBwcm9wQW5kVmFsWzJdO1xuICAgICAgdmFyIHByb3AgPSBzZWxmLnByb3BlcnRpZXNbcHJvcFN0cl07XG5cbiAgICAgIGlmICghcHJvcCkge1xuICAgICAgICB3YXJuKCdTa2lwcGluZyBwcm9wZXJ0eTogSW52YWxpZCBwcm9wZXJ0eSBuYW1lIGluOiAnICsgcHJvcEFuZFZhbFN0cik7IC8vIHNraXAgdGhpcyBwcm9wZXJ0eSBpbiB0aGUgYmxvY2tcblxuICAgICAgICByZW1vdmVQcm9wQW5kVmFsRnJvbVJlbSgpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIHBhcnNlZFByb3AgPSBzdHlsZS5wYXJzZShwcm9wU3RyLCB2YWxTdHIpO1xuXG4gICAgICBpZiAoIXBhcnNlZFByb3ApIHtcbiAgICAgICAgd2FybignU2tpcHBpbmcgcHJvcGVydHk6IEludmFsaWQgcHJvcGVydHkgZGVmaW5pdGlvbiBpbjogJyArIHByb3BBbmRWYWxTdHIpOyAvLyBza2lwIHRoaXMgcHJvcGVydHkgaW4gdGhlIGJsb2NrXG5cbiAgICAgICAgcmVtb3ZlUHJvcEFuZFZhbEZyb21SZW0oKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHByb3BzLnB1c2goe1xuICAgICAgICBuYW1lOiBwcm9wU3RyLFxuICAgICAgICB2YWw6IHZhbFN0clxuICAgICAgfSk7XG4gICAgICByZW1vdmVQcm9wQW5kVmFsRnJvbVJlbSgpO1xuICAgIH1cblxuICAgIGlmIChpbnZhbGlkQmxvY2spIHtcbiAgICAgIHJlbW92ZVNlbEFuZEJsb2NrRnJvbVJlbWFpbmluZygpO1xuICAgICAgYnJlYWs7XG4gICAgfSAvLyBwdXQgdGhlIHBhcnNlZCBibG9jayBpbiB0aGUgc3R5bGVcblxuXG4gICAgc3R5bGUuc2VsZWN0b3Ioc2VsZWN0b3JTdHIpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIF9wcm9wID0gcHJvcHNbaV07XG4gICAgICBzdHlsZS5jc3MoX3Byb3AubmFtZSwgX3Byb3AudmFsKTtcbiAgICB9XG5cbiAgICByZW1vdmVTZWxBbmRCbG9ja0Zyb21SZW1haW5pbmcoKTtcbiAgfVxuXG4gIHJldHVybiBzdHlsZTtcbn07XG5cbnN0eWZuJDUuZnJvbVN0cmluZyA9IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgdmFyIHN0eWxlID0gdGhpcztcbiAgc3R5bGUucmVzZXRUb0RlZmF1bHQoKTtcbiAgc3R5bGUuYXBwZW5kRnJvbVN0cmluZyhzdHJpbmcpO1xuICByZXR1cm4gc3R5bGU7XG59O1xuXG52YXIgc3R5Zm4kNiA9IHt9O1xuXG4oZnVuY3Rpb24gKCkge1xuICB2YXIgbnVtYmVyID0gbnVtYmVyJDE7XG4gIHZhciByZ2JhID0gcmdiYU5vQmFja1JlZnM7XG4gIHZhciBoc2xhID0gaHNsYU5vQmFja1JlZnM7XG4gIHZhciBoZXgzJDEgPSBoZXgzO1xuICB2YXIgaGV4NiQxID0gaGV4NjtcblxuICB2YXIgZGF0YSA9IGZ1bmN0aW9uIGRhdGEocHJlZml4KSB7XG4gICAgcmV0dXJuICdeJyArIHByZWZpeCArICdcXFxccypcXFxcKFxcXFxzKihbXFxcXHdcXFxcLl0rKVxcXFxzKlxcXFwpJCc7XG4gIH07XG5cbiAgdmFyIG1hcERhdGEgPSBmdW5jdGlvbiBtYXBEYXRhKHByZWZpeCkge1xuICAgIHZhciBtYXBBcmcgPSBudW1iZXIgKyAnfFxcXFx3K3wnICsgcmdiYSArICd8JyArIGhzbGEgKyAnfCcgKyBoZXgzJDEgKyAnfCcgKyBoZXg2JDE7XG4gICAgcmV0dXJuICdeJyArIHByZWZpeCArICdcXFxccypcXFxcKChbXFxcXHdcXFxcLl0rKVxcXFxzKlxcXFwsXFxcXHMqKCcgKyBudW1iZXIgKyAnKVxcXFxzKlxcXFwsXFxcXHMqKCcgKyBudW1iZXIgKyAnKVxcXFxzKixcXFxccyooJyArIG1hcEFyZyArICcpXFxcXHMqXFxcXCxcXFxccyooJyArIG1hcEFyZyArICcpXFxcXCkkJztcbiAgfTtcblxuICB2YXIgdXJsUmVnZXhlcyA9IFsnXnVybFxcXFxzKlxcXFwoXFxcXHMqW1xcJ1wiXT8oLis/KVtcXCdcIl0/XFxcXHMqXFxcXCkkJywgJ14obm9uZSkkJywgJ14oLispJCddOyAvLyBlYWNoIHZpc3VhbCBzdHlsZSBwcm9wZXJ0eSBoYXMgYSB0eXBlIGFuZCBuZWVkcyB0byBiZSB2YWxpZGF0ZWQgYWNjb3JkaW5nIHRvIGl0XG5cbiAgc3R5Zm4kNi50eXBlcyA9IHtcbiAgICB0aW1lOiB7XG4gICAgICBudW1iZXI6IHRydWUsXG4gICAgICBtaW46IDAsXG4gICAgICB1bml0czogJ3N8bXMnLFxuICAgICAgaW1wbGljaXRVbml0czogJ21zJ1xuICAgIH0sXG4gICAgcGVyY2VudDoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbWluOiAwLFxuICAgICAgbWF4OiAxMDAsXG4gICAgICB1bml0czogJyUnLFxuICAgICAgaW1wbGljaXRVbml0czogJyUnXG4gICAgfSxcbiAgICBwZXJjZW50YWdlczoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbWluOiAwLFxuICAgICAgbWF4OiAxMDAsXG4gICAgICB1bml0czogJyUnLFxuICAgICAgaW1wbGljaXRVbml0czogJyUnLFxuICAgICAgbXVsdGlwbGU6IHRydWVcbiAgICB9LFxuICAgIHplcm9PbmVOdW1iZXI6IHtcbiAgICAgIG51bWJlcjogdHJ1ZSxcbiAgICAgIG1pbjogMCxcbiAgICAgIG1heDogMSxcbiAgICAgIHVuaXRsZXNzOiB0cnVlXG4gICAgfSxcbiAgICB6ZXJvT25lTnVtYmVyczoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbWluOiAwLFxuICAgICAgbWF4OiAxLFxuICAgICAgdW5pdGxlc3M6IHRydWUsXG4gICAgICBtdWx0aXBsZTogdHJ1ZVxuICAgIH0sXG4gICAgbk9uZU9uZU51bWJlcjoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbWluOiAtMSxcbiAgICAgIG1heDogMSxcbiAgICAgIHVuaXRsZXNzOiB0cnVlXG4gICAgfSxcbiAgICBub25OZWdhdGl2ZUludDoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbWluOiAwLFxuICAgICAgaW50ZWdlcjogdHJ1ZSxcbiAgICAgIHVuaXRsZXNzOiB0cnVlXG4gICAgfSxcbiAgICBwb3NpdGlvbjoge1xuICAgICAgZW51bXM6IFsncGFyZW50JywgJ29yaWdpbiddXG4gICAgfSxcbiAgICBub2RlU2l6ZToge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbWluOiAwLFxuICAgICAgZW51bXM6IFsnbGFiZWwnXVxuICAgIH0sXG4gICAgbnVtYmVyOiB7XG4gICAgICBudW1iZXI6IHRydWUsXG4gICAgICB1bml0bGVzczogdHJ1ZVxuICAgIH0sXG4gICAgbnVtYmVyczoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgdW5pdGxlc3M6IHRydWUsXG4gICAgICBtdWx0aXBsZTogdHJ1ZVxuICAgIH0sXG4gICAgcG9zaXRpdmVOdW1iZXI6IHtcbiAgICAgIG51bWJlcjogdHJ1ZSxcbiAgICAgIHVuaXRsZXNzOiB0cnVlLFxuICAgICAgbWluOiAwLFxuICAgICAgc3RyaWN0TWluOiB0cnVlXG4gICAgfSxcbiAgICBzaXplOiB7XG4gICAgICBudW1iZXI6IHRydWUsXG4gICAgICBtaW46IDBcbiAgICB9LFxuICAgIGJpZGlyZWN0aW9uYWxTaXplOiB7XG4gICAgICBudW1iZXI6IHRydWVcbiAgICB9LFxuICAgIC8vIGFsbG93cyBuZWdhdGl2ZVxuICAgIGJpZGlyZWN0aW9uYWxTaXplTWF5YmVQZXJjZW50OiB7XG4gICAgICBudW1iZXI6IHRydWUsXG4gICAgICBhbGxvd1BlcmNlbnQ6IHRydWVcbiAgICB9LFxuICAgIC8vIGFsbG93cyBuZWdhdGl2ZVxuICAgIGJpZGlyZWN0aW9uYWxTaXplczoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbXVsdGlwbGU6IHRydWVcbiAgICB9LFxuICAgIC8vIGFsbG93cyBuZWdhdGl2ZVxuICAgIHNpemVNYXliZVBlcmNlbnQ6IHtcbiAgICAgIG51bWJlcjogdHJ1ZSxcbiAgICAgIG1pbjogMCxcbiAgICAgIGFsbG93UGVyY2VudDogdHJ1ZVxuICAgIH0sXG4gICAgYXhpc0RpcmVjdGlvbjoge1xuICAgICAgZW51bXM6IFsnaG9yaXpvbnRhbCcsICdsZWZ0d2FyZCcsICdyaWdodHdhcmQnLCAndmVydGljYWwnLCAndXB3YXJkJywgJ2Rvd253YXJkJywgJ2F1dG8nXVxuICAgIH0sXG4gICAgcGFkZGluZ1JlbGF0aXZlVG86IHtcbiAgICAgIGVudW1zOiBbJ3dpZHRoJywgJ2hlaWdodCcsICdhdmVyYWdlJywgJ21pbicsICdtYXgnXVxuICAgIH0sXG4gICAgYmdXSDoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgbWluOiAwLFxuICAgICAgYWxsb3dQZXJjZW50OiB0cnVlLFxuICAgICAgZW51bXM6IFsnYXV0byddLFxuICAgICAgbXVsdGlwbGU6IHRydWVcbiAgICB9LFxuICAgIGJnUG9zOiB7XG4gICAgICBudW1iZXI6IHRydWUsXG4gICAgICBhbGxvd1BlcmNlbnQ6IHRydWUsXG4gICAgICBtdWx0aXBsZTogdHJ1ZVxuICAgIH0sXG4gICAgYmdSZWxhdGl2ZVRvOiB7XG4gICAgICBlbnVtczogWydpbm5lcicsICdpbmNsdWRlLXBhZGRpbmcnXSxcbiAgICAgIG11bHRpcGxlOiB0cnVlXG4gICAgfSxcbiAgICBiZ1JlcGVhdDoge1xuICAgICAgZW51bXM6IFsncmVwZWF0JywgJ3JlcGVhdC14JywgJ3JlcGVhdC15JywgJ25vLXJlcGVhdCddLFxuICAgICAgbXVsdGlwbGU6IHRydWVcbiAgICB9LFxuICAgIGJnRml0OiB7XG4gICAgICBlbnVtczogWydub25lJywgJ2NvbnRhaW4nLCAnY292ZXInXSxcbiAgICAgIG11bHRpcGxlOiB0cnVlXG4gICAgfSxcbiAgICBiZ0Nyb3NzT3JpZ2luOiB7XG4gICAgICBlbnVtczogWydhbm9ueW1vdXMnLCAndXNlLWNyZWRlbnRpYWxzJ10sXG4gICAgICBtdWx0aXBsZTogdHJ1ZVxuICAgIH0sXG4gICAgYmdDbGlwOiB7XG4gICAgICBlbnVtczogWydub25lJywgJ25vZGUnXSxcbiAgICAgIG11bHRpcGxlOiB0cnVlXG4gICAgfSxcbiAgICBjb2xvcjoge1xuICAgICAgY29sb3I6IHRydWVcbiAgICB9LFxuICAgIGNvbG9yczoge1xuICAgICAgY29sb3I6IHRydWUsXG4gICAgICBtdWx0aXBsZTogdHJ1ZVxuICAgIH0sXG4gICAgZmlsbDoge1xuICAgICAgZW51bXM6IFsnc29saWQnLCAnbGluZWFyLWdyYWRpZW50JywgJ3JhZGlhbC1ncmFkaWVudCddXG4gICAgfSxcbiAgICBib29sOiB7XG4gICAgICBlbnVtczogWyd5ZXMnLCAnbm8nXVxuICAgIH0sXG4gICAgbGluZVN0eWxlOiB7XG4gICAgICBlbnVtczogWydzb2xpZCcsICdkb3R0ZWQnLCAnZGFzaGVkJ11cbiAgICB9LFxuICAgIGxpbmVDYXA6IHtcbiAgICAgIGVudW1zOiBbJ2J1dHQnLCAncm91bmQnLCAnc3F1YXJlJ11cbiAgICB9LFxuICAgIGJvcmRlclN0eWxlOiB7XG4gICAgICBlbnVtczogWydzb2xpZCcsICdkb3R0ZWQnLCAnZGFzaGVkJywgJ2RvdWJsZSddXG4gICAgfSxcbiAgICBjdXJ2ZVN0eWxlOiB7XG4gICAgICBlbnVtczogWydiZXppZXInLCAndW5idW5kbGVkLWJlemllcicsICdoYXlzdGFjaycsICdzZWdtZW50cycsICdzdHJhaWdodCcsICd0YXhpJ11cbiAgICB9LFxuICAgIGZvbnRGYW1pbHk6IHtcbiAgICAgIHJlZ2V4OiAnXihbXFxcXHctIFxcXFxcIl0rKD86XFxcXHMqLFxcXFxzKltcXFxcdy0gXFxcXFwiXSspKikkJ1xuICAgIH0sXG4gICAgZm9udFN0eWxlOiB7XG4gICAgICBlbnVtczogWydpdGFsaWMnLCAnbm9ybWFsJywgJ29ibGlxdWUnXVxuICAgIH0sXG4gICAgZm9udFdlaWdodDoge1xuICAgICAgZW51bXM6IFsnbm9ybWFsJywgJ2JvbGQnLCAnYm9sZGVyJywgJ2xpZ2h0ZXInLCAnMTAwJywgJzIwMCcsICczMDAnLCAnNDAwJywgJzUwMCcsICc2MDAnLCAnODAwJywgJzkwMCcsIDEwMCwgMjAwLCAzMDAsIDQwMCwgNTAwLCA2MDAsIDcwMCwgODAwLCA5MDBdXG4gICAgfSxcbiAgICB0ZXh0RGVjb3JhdGlvbjoge1xuICAgICAgZW51bXM6IFsnbm9uZScsICd1bmRlcmxpbmUnLCAnb3ZlcmxpbmUnLCAnbGluZS10aHJvdWdoJ11cbiAgICB9LFxuICAgIHRleHRUcmFuc2Zvcm06IHtcbiAgICAgIGVudW1zOiBbJ25vbmUnLCAndXBwZXJjYXNlJywgJ2xvd2VyY2FzZSddXG4gICAgfSxcbiAgICB0ZXh0V3JhcDoge1xuICAgICAgZW51bXM6IFsnbm9uZScsICd3cmFwJywgJ2VsbGlwc2lzJ11cbiAgICB9LFxuICAgIHRleHRPdmVyZmxvd1dyYXA6IHtcbiAgICAgIGVudW1zOiBbJ3doaXRlc3BhY2UnLCAnYW55d2hlcmUnXVxuICAgIH0sXG4gICAgdGV4dEJhY2tncm91bmRTaGFwZToge1xuICAgICAgZW51bXM6IFsncmVjdGFuZ2xlJywgJ3JvdW5kcmVjdGFuZ2xlJywgJ3JvdW5kLXJlY3RhbmdsZSddXG4gICAgfSxcbiAgICBub2RlU2hhcGU6IHtcbiAgICAgIGVudW1zOiBbJ3JlY3RhbmdsZScsICdyb3VuZHJlY3RhbmdsZScsICdyb3VuZC1yZWN0YW5nbGUnLCAnY3V0cmVjdGFuZ2xlJywgJ2N1dC1yZWN0YW5nbGUnLCAnYm90dG9tcm91bmRyZWN0YW5nbGUnLCAnYm90dG9tLXJvdW5kLXJlY3RhbmdsZScsICdiYXJyZWwnLCAnZWxsaXBzZScsICd0cmlhbmdsZScsICdyb3VuZC10cmlhbmdsZScsICdzcXVhcmUnLCAncGVudGFnb24nLCAncm91bmQtcGVudGFnb24nLCAnaGV4YWdvbicsICdyb3VuZC1oZXhhZ29uJywgJ2NvbmNhdmVoZXhhZ29uJywgJ2NvbmNhdmUtaGV4YWdvbicsICdoZXB0YWdvbicsICdyb3VuZC1oZXB0YWdvbicsICdvY3RhZ29uJywgJ3JvdW5kLW9jdGFnb24nLCAndGFnJywgJ3JvdW5kLXRhZycsICdzdGFyJywgJ2RpYW1vbmQnLCAncm91bmQtZGlhbW9uZCcsICd2ZWUnLCAncmhvbWJvaWQnLCAncG9seWdvbiddXG4gICAgfSxcbiAgICBjb21wb3VuZEluY2x1ZGVMYWJlbHM6IHtcbiAgICAgIGVudW1zOiBbJ2luY2x1ZGUnLCAnZXhjbHVkZSddXG4gICAgfSxcbiAgICBhcnJvd1NoYXBlOiB7XG4gICAgICBlbnVtczogWyd0ZWUnLCAndHJpYW5nbGUnLCAndHJpYW5nbGUtdGVlJywgJ2NpcmNsZS10cmlhbmdsZScsICd0cmlhbmdsZS1jcm9zcycsICd0cmlhbmdsZS1iYWNrY3VydmUnLCAndmVlJywgJ3NxdWFyZScsICdjaXJjbGUnLCAnZGlhbW9uZCcsICdjaGV2cm9uJywgJ25vbmUnXVxuICAgIH0sXG4gICAgYXJyb3dGaWxsOiB7XG4gICAgICBlbnVtczogWydmaWxsZWQnLCAnaG9sbG93J11cbiAgICB9LFxuICAgIGRpc3BsYXk6IHtcbiAgICAgIGVudW1zOiBbJ2VsZW1lbnQnLCAnbm9uZSddXG4gICAgfSxcbiAgICB2aXNpYmlsaXR5OiB7XG4gICAgICBlbnVtczogWydoaWRkZW4nLCAndmlzaWJsZSddXG4gICAgfSxcbiAgICB6Q29tcG91bmREZXB0aDoge1xuICAgICAgZW51bXM6IFsnYm90dG9tJywgJ29ycGhhbicsICdhdXRvJywgJ3RvcCddXG4gICAgfSxcbiAgICB6SW5kZXhDb21wYXJlOiB7XG4gICAgICBlbnVtczogWydhdXRvJywgJ21hbnVhbCddXG4gICAgfSxcbiAgICB2YWxpZ246IHtcbiAgICAgIGVudW1zOiBbJ3RvcCcsICdjZW50ZXInLCAnYm90dG9tJ11cbiAgICB9LFxuICAgIGhhbGlnbjoge1xuICAgICAgZW51bXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXVxuICAgIH0sXG4gICAganVzdGlmaWNhdGlvbjoge1xuICAgICAgZW51bXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnLCAnYXV0byddXG4gICAgfSxcbiAgICB0ZXh0OiB7XG4gICAgICBzdHJpbmc6IHRydWVcbiAgICB9LFxuICAgIGRhdGE6IHtcbiAgICAgIG1hcHBpbmc6IHRydWUsXG4gICAgICByZWdleDogZGF0YSgnZGF0YScpXG4gICAgfSxcbiAgICBsYXlvdXREYXRhOiB7XG4gICAgICBtYXBwaW5nOiB0cnVlLFxuICAgICAgcmVnZXg6IGRhdGEoJ2xheW91dERhdGEnKVxuICAgIH0sXG4gICAgc2NyYXRjaDoge1xuICAgICAgbWFwcGluZzogdHJ1ZSxcbiAgICAgIHJlZ2V4OiBkYXRhKCdzY3JhdGNoJylcbiAgICB9LFxuICAgIG1hcERhdGE6IHtcbiAgICAgIG1hcHBpbmc6IHRydWUsXG4gICAgICByZWdleDogbWFwRGF0YSgnbWFwRGF0YScpXG4gICAgfSxcbiAgICBtYXBMYXlvdXREYXRhOiB7XG4gICAgICBtYXBwaW5nOiB0cnVlLFxuICAgICAgcmVnZXg6IG1hcERhdGEoJ21hcExheW91dERhdGEnKVxuICAgIH0sXG4gICAgbWFwU2NyYXRjaDoge1xuICAgICAgbWFwcGluZzogdHJ1ZSxcbiAgICAgIHJlZ2V4OiBtYXBEYXRhKCdtYXBTY3JhdGNoJylcbiAgICB9LFxuICAgIGZuOiB7XG4gICAgICBtYXBwaW5nOiB0cnVlLFxuICAgICAgZm46IHRydWVcbiAgICB9LFxuICAgIHVybDoge1xuICAgICAgcmVnZXhlczogdXJsUmVnZXhlcyxcbiAgICAgIHNpbmdsZVJlZ2V4TWF0Y2hWYWx1ZTogdHJ1ZVxuICAgIH0sXG4gICAgdXJsczoge1xuICAgICAgcmVnZXhlczogdXJsUmVnZXhlcyxcbiAgICAgIHNpbmdsZVJlZ2V4TWF0Y2hWYWx1ZTogdHJ1ZSxcbiAgICAgIG11bHRpcGxlOiB0cnVlXG4gICAgfSxcbiAgICBwcm9wTGlzdDoge1xuICAgICAgcHJvcExpc3Q6IHRydWVcbiAgICB9LFxuICAgIGFuZ2xlOiB7XG4gICAgICBudW1iZXI6IHRydWUsXG4gICAgICB1bml0czogJ2RlZ3xyYWQnLFxuICAgICAgaW1wbGljaXRVbml0czogJ3JhZCdcbiAgICB9LFxuICAgIHRleHRSb3RhdGlvbjoge1xuICAgICAgbnVtYmVyOiB0cnVlLFxuICAgICAgdW5pdHM6ICdkZWd8cmFkJyxcbiAgICAgIGltcGxpY2l0VW5pdHM6ICdyYWQnLFxuICAgICAgZW51bXM6IFsnbm9uZScsICdhdXRvcm90YXRlJ11cbiAgICB9LFxuICAgIHBvbHlnb25Qb2ludExpc3Q6IHtcbiAgICAgIG51bWJlcjogdHJ1ZSxcbiAgICAgIG11bHRpcGxlOiB0cnVlLFxuICAgICAgZXZlbk11bHRpcGxlOiB0cnVlLFxuICAgICAgbWluOiAtMSxcbiAgICAgIG1heDogMSxcbiAgICAgIHVuaXRsZXNzOiB0cnVlXG4gICAgfSxcbiAgICBlZGdlRGlzdGFuY2VzOiB7XG4gICAgICBlbnVtczogWydpbnRlcnNlY3Rpb24nLCAnbm9kZS1wb3NpdGlvbiddXG4gICAgfSxcbiAgICBlZGdlRW5kcG9pbnQ6IHtcbiAgICAgIG51bWJlcjogdHJ1ZSxcbiAgICAgIG11bHRpcGxlOiB0cnVlLFxuICAgICAgdW5pdHM6ICclfHB4fGVtfGRlZ3xyYWQnLFxuICAgICAgaW1wbGljaXRVbml0czogJ3B4JyxcbiAgICAgIGVudW1zOiBbJ2luc2lkZS10by1ub2RlJywgJ291dHNpZGUtdG8tbm9kZScsICdvdXRzaWRlLXRvLW5vZGUtb3ItbGFiZWwnLCAnb3V0c2lkZS10by1saW5lJywgJ291dHNpZGUtdG8tbGluZS1vci1sYWJlbCddLFxuICAgICAgc2luZ2xlRW51bTogdHJ1ZSxcbiAgICAgIHZhbGlkYXRlOiBmdW5jdGlvbiB2YWxpZGF0ZSh2YWxBcnIsIHVuaXRzQXJyKSB7XG4gICAgICAgIHN3aXRjaCAodmFsQXJyLmxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIC8vIGNhbiBiZSAlIG9yIHB4IG9ubHlcbiAgICAgICAgICAgIHJldHVybiB1bml0c0FyclswXSAhPT0gJ2RlZycgJiYgdW5pdHNBcnJbMF0gIT09ICdyYWQnICYmIHVuaXRzQXJyWzFdICE9PSAnZGVnJyAmJiB1bml0c0FyclsxXSAhPT0gJ3JhZCc7XG5cbiAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAvLyBjYW4gYmUgZW51bSwgZGVnLCBvciByYWQgb25seVxuICAgICAgICAgICAgcmV0dXJuIHN0cmluZyh2YWxBcnJbMF0pIHx8IHVuaXRzQXJyWzBdID09PSAnZGVnJyB8fCB1bml0c0FyclswXSA9PT0gJ3JhZCc7XG5cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBlYXNpbmc6IHtcbiAgICAgIHJlZ2V4ZXM6IFsnXihzcHJpbmcpXFxcXHMqXFxcXChcXFxccyooJyArIG51bWJlciArICcpXFxcXHMqLFxcXFxzKignICsgbnVtYmVyICsgJylcXFxccypcXFxcKSQnLCAnXihjdWJpYy1iZXppZXIpXFxcXHMqXFxcXChcXFxccyooJyArIG51bWJlciArICcpXFxcXHMqLFxcXFxzKignICsgbnVtYmVyICsgJylcXFxccyosXFxcXHMqKCcgKyBudW1iZXIgKyAnKVxcXFxzKixcXFxccyooJyArIG51bWJlciArICcpXFxcXHMqXFxcXCkkJ10sXG4gICAgICBlbnVtczogWydsaW5lYXInLCAnZWFzZScsICdlYXNlLWluJywgJ2Vhc2Utb3V0JywgJ2Vhc2UtaW4tb3V0JywgJ2Vhc2UtaW4tc2luZScsICdlYXNlLW91dC1zaW5lJywgJ2Vhc2UtaW4tb3V0LXNpbmUnLCAnZWFzZS1pbi1xdWFkJywgJ2Vhc2Utb3V0LXF1YWQnLCAnZWFzZS1pbi1vdXQtcXVhZCcsICdlYXNlLWluLWN1YmljJywgJ2Vhc2Utb3V0LWN1YmljJywgJ2Vhc2UtaW4tb3V0LWN1YmljJywgJ2Vhc2UtaW4tcXVhcnQnLCAnZWFzZS1vdXQtcXVhcnQnLCAnZWFzZS1pbi1vdXQtcXVhcnQnLCAnZWFzZS1pbi1xdWludCcsICdlYXNlLW91dC1xdWludCcsICdlYXNlLWluLW91dC1xdWludCcsICdlYXNlLWluLWV4cG8nLCAnZWFzZS1vdXQtZXhwbycsICdlYXNlLWluLW91dC1leHBvJywgJ2Vhc2UtaW4tY2lyYycsICdlYXNlLW91dC1jaXJjJywgJ2Vhc2UtaW4tb3V0LWNpcmMnXVxuICAgIH0sXG4gICAgZ3JhZGllbnREaXJlY3Rpb246IHtcbiAgICAgIGVudW1zOiBbJ3RvLWJvdHRvbScsICd0by10b3AnLCAndG8tbGVmdCcsICd0by1yaWdodCcsICd0by1ib3R0b20tcmlnaHQnLCAndG8tYm90dG9tLWxlZnQnLCAndG8tdG9wLXJpZ2h0JywgJ3RvLXRvcC1sZWZ0JywgJ3RvLXJpZ2h0LWJvdHRvbScsICd0by1sZWZ0LWJvdHRvbScsICd0by1yaWdodC10b3AnLCAndG8tbGVmdC10b3AnXVxuICAgIH0sXG4gICAgYm91bmRzRXhwYW5zaW9uOiB7XG4gICAgICBudW1iZXI6IHRydWUsXG4gICAgICBtdWx0aXBsZTogdHJ1ZSxcbiAgICAgIG1pbjogMCxcbiAgICAgIHZhbGlkYXRlOiBmdW5jdGlvbiB2YWxpZGF0ZSh2YWxBcnIpIHtcbiAgICAgICAgdmFyIGxlbmd0aCA9IHZhbEFyci5sZW5ndGg7XG4gICAgICAgIHJldHVybiBsZW5ndGggPT09IDEgfHwgbGVuZ3RoID09PSAyIHx8IGxlbmd0aCA9PT0gNDtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIHZhciBkaWZmID0ge1xuICAgIHplcm9Ob25aZXJvOiBmdW5jdGlvbiB6ZXJvTm9uWmVybyh2YWwxLCB2YWwyKSB7XG4gICAgICBpZiAoKHZhbDEgPT0gbnVsbCB8fCB2YWwyID09IG51bGwpICYmIHZhbDEgIT09IHZhbDIpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7IC8vIG51bGwgY2FzZXMgY291bGQgcmVwcmVzZW50IGFueSB2YWx1ZVxuICAgICAgfVxuXG4gICAgICBpZiAodmFsMSA9PSAwICYmIHZhbDIgIT0gMCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAodmFsMSAhPSAwICYmIHZhbDIgPT0gMCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGFueTogZnVuY3Rpb24gYW55KHZhbDEsIHZhbDIpIHtcbiAgICAgIHJldHVybiB2YWwxICE9IHZhbDI7XG4gICAgfSxcbiAgICBlbXB0eU5vbkVtcHR5OiBmdW5jdGlvbiBlbXB0eU5vbkVtcHR5KHN0cjEsIHN0cjIpIHtcbiAgICAgIHZhciBlbXB0eTEgPSBlbXB0eVN0cmluZyhzdHIxKTtcbiAgICAgIHZhciBlbXB0eTIgPSBlbXB0eVN0cmluZyhzdHIyKTtcbiAgICAgIHJldHVybiBlbXB0eTEgJiYgIWVtcHR5MiB8fCAhZW1wdHkxICYmIGVtcHR5MjtcbiAgICB9XG4gIH07IC8vIGRlZmluZSB2aXN1YWwgc3R5bGUgcHJvcGVydGllc1xuICAvL1xuICAvLyAtIG4uYi4gYWRkaW5nIGEgbmV3IGdyb3VwIG9mIHByb3BzIG1heSByZXF1aXJlIHVwZGF0ZXMgdG8gdXBkYXRlU3R5bGVIaW50cygpXG4gIC8vIC0gYWRkaW5nIG5ldyBwcm9wcyB0byBhbiBleGlzdGluZyBncm91cCBnZXRzIGhhbmRsZWQgYXV0b21hdGljYWxseVxuXG4gIHZhciB0ID0gc3R5Zm4kNi50eXBlcztcbiAgdmFyIG1haW5MYWJlbCA9IFt7XG4gICAgbmFtZTogJ2xhYmVsJyxcbiAgICB0eXBlOiB0LnRleHQsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55LFxuICAgIHRyaWdnZXJzWk9yZGVyOiBkaWZmLmVtcHR5Tm9uRW1wdHlcbiAgfSwge1xuICAgIG5hbWU6ICd0ZXh0LXJvdGF0aW9uJyxcbiAgICB0eXBlOiB0LnRleHRSb3RhdGlvbixcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd0ZXh0LW1hcmdpbi14JyxcbiAgICB0eXBlOiB0LmJpZGlyZWN0aW9uYWxTaXplLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtbWFyZ2luLXknLFxuICAgIHR5cGU6IHQuYmlkaXJlY3Rpb25hbFNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH1dO1xuICB2YXIgc291cmNlTGFiZWwgPSBbe1xuICAgIG5hbWU6ICdzb3VyY2UtbGFiZWwnLFxuICAgIHR5cGU6IHQudGV4dCxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdzb3VyY2UtdGV4dC1yb3RhdGlvbicsXG4gICAgdHlwZTogdC50ZXh0Um90YXRpb24sXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnc291cmNlLXRleHQtbWFyZ2luLXgnLFxuICAgIHR5cGU6IHQuYmlkaXJlY3Rpb25hbFNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnc291cmNlLXRleHQtbWFyZ2luLXknLFxuICAgIHR5cGU6IHQuYmlkaXJlY3Rpb25hbFNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnc291cmNlLXRleHQtb2Zmc2V0JyxcbiAgICB0eXBlOiB0LnNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH1dO1xuICB2YXIgdGFyZ2V0TGFiZWwgPSBbe1xuICAgIG5hbWU6ICd0YXJnZXQtbGFiZWwnLFxuICAgIHR5cGU6IHQudGV4dCxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd0YXJnZXQtdGV4dC1yb3RhdGlvbicsXG4gICAgdHlwZTogdC50ZXh0Um90YXRpb24sXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGFyZ2V0LXRleHQtbWFyZ2luLXgnLFxuICAgIHR5cGU6IHQuYmlkaXJlY3Rpb25hbFNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGFyZ2V0LXRleHQtbWFyZ2luLXknLFxuICAgIHR5cGU6IHQuYmlkaXJlY3Rpb25hbFNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGFyZ2V0LXRleHQtb2Zmc2V0JyxcbiAgICB0eXBlOiB0LnNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH1dO1xuICB2YXIgbGFiZWxEaW1lbnNpb25zID0gW3tcbiAgICBuYW1lOiAnZm9udC1mYW1pbHknLFxuICAgIHR5cGU6IHQuZm9udEZhbWlseSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdmb250LXN0eWxlJyxcbiAgICB0eXBlOiB0LmZvbnRTdHlsZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdmb250LXdlaWdodCcsXG4gICAgdHlwZTogdC5mb250V2VpZ2h0LFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ2ZvbnQtc2l6ZScsXG4gICAgdHlwZTogdC5zaXplLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtdHJhbnNmb3JtJyxcbiAgICB0eXBlOiB0LnRleHRUcmFuc2Zvcm0sXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGV4dC13cmFwJyxcbiAgICB0eXBlOiB0LnRleHRXcmFwLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtb3ZlcmZsb3ctd3JhcCcsXG4gICAgdHlwZTogdC50ZXh0T3ZlcmZsb3dXcmFwLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtbWF4LXdpZHRoJyxcbiAgICB0eXBlOiB0LnNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGV4dC1vdXRsaW5lLXdpZHRoJyxcbiAgICB0eXBlOiB0LnNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnbGluZS1oZWlnaHQnLFxuICAgIHR5cGU6IHQucG9zaXRpdmVOdW1iZXIsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH1dO1xuICB2YXIgY29tbW9uTGFiZWwgPSBbe1xuICAgIG5hbWU6ICd0ZXh0LXZhbGlnbicsXG4gICAgdHlwZTogdC52YWxpZ24sXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGV4dC1oYWxpZ24nLFxuICAgIHR5cGU6IHQuaGFsaWduLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ2NvbG9yJyxcbiAgICB0eXBlOiB0LmNvbG9yXG4gIH0sIHtcbiAgICBuYW1lOiAndGV4dC1vdXRsaW5lLWNvbG9yJyxcbiAgICB0eXBlOiB0LmNvbG9yXG4gIH0sIHtcbiAgICBuYW1lOiAndGV4dC1vdXRsaW5lLW9wYWNpdHknLFxuICAgIHR5cGU6IHQuemVyb09uZU51bWJlclxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtYmFja2dyb3VuZC1jb2xvcicsXG4gICAgdHlwZTogdC5jb2xvclxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtYmFja2dyb3VuZC1vcGFjaXR5JyxcbiAgICB0eXBlOiB0Lnplcm9PbmVOdW1iZXJcbiAgfSwge1xuICAgIG5hbWU6ICd0ZXh0LWJhY2tncm91bmQtcGFkZGluZycsXG4gICAgdHlwZTogdC5zaXplLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtYm9yZGVyLW9wYWNpdHknLFxuICAgIHR5cGU6IHQuemVyb09uZU51bWJlclxuICB9LCB7XG4gICAgbmFtZTogJ3RleHQtYm9yZGVyLWNvbG9yJyxcbiAgICB0eXBlOiB0LmNvbG9yXG4gIH0sIHtcbiAgICBuYW1lOiAndGV4dC1ib3JkZXItd2lkdGgnLFxuICAgIHR5cGU6IHQuc2l6ZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd0ZXh0LWJvcmRlci1zdHlsZScsXG4gICAgdHlwZTogdC5ib3JkZXJTdHlsZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd0ZXh0LWJhY2tncm91bmQtc2hhcGUnLFxuICAgIHR5cGU6IHQudGV4dEJhY2tncm91bmRTaGFwZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd0ZXh0LWp1c3RpZmljYXRpb24nLFxuICAgIHR5cGU6IHQuanVzdGlmaWNhdGlvblxuICB9XTtcbiAgdmFyIGJlaGF2aW9yID0gW3tcbiAgICBuYW1lOiAnZXZlbnRzJyxcbiAgICB0eXBlOiB0LmJvb2xcbiAgfSwge1xuICAgIG5hbWU6ICd0ZXh0LWV2ZW50cycsXG4gICAgdHlwZTogdC5ib29sXG4gIH1dO1xuICB2YXIgdmlzaWJpbGl0eSA9IFt7XG4gICAgbmFtZTogJ2Rpc3BsYXknLFxuICAgIHR5cGU6IHQuZGlzcGxheSxcbiAgICB0cmlnZ2Vyc1pPcmRlcjogZGlmZi5hbnksXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55LFxuICAgIHRyaWdnZXJzQm91bmRzT2ZQYXJhbGxlbEJlemllcnM6IHRydWVcbiAgfSwge1xuICAgIG5hbWU6ICd2aXNpYmlsaXR5JyxcbiAgICB0eXBlOiB0LnZpc2liaWxpdHksXG4gICAgdHJpZ2dlcnNaT3JkZXI6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnb3BhY2l0eScsXG4gICAgdHlwZTogdC56ZXJvT25lTnVtYmVyLFxuICAgIHRyaWdnZXJzWk9yZGVyOiBkaWZmLnplcm9Ob25aZXJvXG4gIH0sIHtcbiAgICBuYW1lOiAndGV4dC1vcGFjaXR5JyxcbiAgICB0eXBlOiB0Lnplcm9PbmVOdW1iZXJcbiAgfSwge1xuICAgIG5hbWU6ICdtaW4tem9vbWVkLWZvbnQtc2l6ZScsXG4gICAgdHlwZTogdC5zaXplXG4gIH0sIHtcbiAgICBuYW1lOiAnei1jb21wb3VuZC1kZXB0aCcsXG4gICAgdHlwZTogdC56Q29tcG91bmREZXB0aCxcbiAgICB0cmlnZ2Vyc1pPcmRlcjogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd6LWluZGV4LWNvbXBhcmUnLFxuICAgIHR5cGU6IHQuekluZGV4Q29tcGFyZSxcbiAgICB0cmlnZ2Vyc1pPcmRlcjogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd6LWluZGV4JyxcbiAgICB0eXBlOiB0Lm5vbk5lZ2F0aXZlSW50LFxuICAgIHRyaWdnZXJzWk9yZGVyOiBkaWZmLmFueVxuICB9XTtcbiAgdmFyIG92ZXJsYXkgPSBbe1xuICAgIG5hbWU6ICdvdmVybGF5LXBhZGRpbmcnLFxuICAgIHR5cGU6IHQuc2l6ZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdvdmVybGF5LWNvbG9yJyxcbiAgICB0eXBlOiB0LmNvbG9yXG4gIH0sIHtcbiAgICBuYW1lOiAnb3ZlcmxheS1vcGFjaXR5JyxcbiAgICB0eXBlOiB0Lnplcm9PbmVOdW1iZXIsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuemVyb05vblplcm9cbiAgfV07XG4gIHZhciB0cmFuc2l0aW9uID0gW3tcbiAgICBuYW1lOiAndHJhbnNpdGlvbi1wcm9wZXJ0eScsXG4gICAgdHlwZTogdC5wcm9wTGlzdFxuICB9LCB7XG4gICAgbmFtZTogJ3RyYW5zaXRpb24tZHVyYXRpb24nLFxuICAgIHR5cGU6IHQudGltZVxuICB9LCB7XG4gICAgbmFtZTogJ3RyYW5zaXRpb24tZGVsYXknLFxuICAgIHR5cGU6IHQudGltZVxuICB9LCB7XG4gICAgbmFtZTogJ3RyYW5zaXRpb24tdGltaW5nLWZ1bmN0aW9uJyxcbiAgICB0eXBlOiB0LmVhc2luZ1xuICB9XTtcblxuICB2YXIgbm9kZVNpemVIYXNoT3ZlcnJpZGUgPSBmdW5jdGlvbiBub2RlU2l6ZUhhc2hPdmVycmlkZShlbGUsIHBhcnNlZFByb3ApIHtcbiAgICBpZiAocGFyc2VkUHJvcC52YWx1ZSA9PT0gJ2xhYmVsJykge1xuICAgICAgcmV0dXJuIC1lbGUucG9vbEluZGV4KCk7IC8vIG5vIGhhc2gga2V5IGhpdHMgaXMgdXNpbmcgbGFiZWwgc2l6ZSAoaGl0cmF0ZSBmb3IgcGVyZiBwcm9iYWJseSBsb3cgYW55d2F5KVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcGFyc2VkUHJvcC5wZlZhbHVlO1xuICAgIH1cbiAgfTtcblxuICB2YXIgbm9kZUJvZHkgPSBbe1xuICAgIG5hbWU6ICdoZWlnaHQnLFxuICAgIHR5cGU6IHQubm9kZVNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55LFxuICAgIGhhc2hPdmVycmlkZTogbm9kZVNpemVIYXNoT3ZlcnJpZGVcbiAgfSwge1xuICAgIG5hbWU6ICd3aWR0aCcsXG4gICAgdHlwZTogdC5ub2RlU2l6ZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnksXG4gICAgaGFzaE92ZXJyaWRlOiBub2RlU2l6ZUhhc2hPdmVycmlkZVxuICB9LCB7XG4gICAgbmFtZTogJ3NoYXBlJyxcbiAgICB0eXBlOiB0Lm5vZGVTaGFwZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdzaGFwZS1wb2x5Z29uLXBvaW50cycsXG4gICAgdHlwZTogdC5wb2x5Z29uUG9pbnRMaXN0LFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ2JhY2tncm91bmQtY29sb3InLFxuICAgIHR5cGU6IHQuY29sb3JcbiAgfSwge1xuICAgIG5hbWU6ICdiYWNrZ3JvdW5kLWZpbGwnLFxuICAgIHR5cGU6IHQuZmlsbFxuICB9LCB7XG4gICAgbmFtZTogJ2JhY2tncm91bmQtb3BhY2l0eScsXG4gICAgdHlwZTogdC56ZXJvT25lTnVtYmVyXG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1ibGFja2VuJyxcbiAgICB0eXBlOiB0Lm5PbmVPbmVOdW1iZXJcbiAgfSwge1xuICAgIG5hbWU6ICdiYWNrZ3JvdW5kLWdyYWRpZW50LXN0b3AtY29sb3JzJyxcbiAgICB0eXBlOiB0LmNvbG9yc1xuICB9LCB7XG4gICAgbmFtZTogJ2JhY2tncm91bmQtZ3JhZGllbnQtc3RvcC1wb3NpdGlvbnMnLFxuICAgIHR5cGU6IHQucGVyY2VudGFnZXNcbiAgfSwge1xuICAgIG5hbWU6ICdiYWNrZ3JvdW5kLWdyYWRpZW50LWRpcmVjdGlvbicsXG4gICAgdHlwZTogdC5ncmFkaWVudERpcmVjdGlvblxuICB9LCB7XG4gICAgbmFtZTogJ3BhZGRpbmcnLFxuICAgIHR5cGU6IHQuc2l6ZU1heWJlUGVyY2VudCxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdwYWRkaW5nLXJlbGF0aXZlLXRvJyxcbiAgICB0eXBlOiB0LnBhZGRpbmdSZWxhdGl2ZVRvLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ2JvdW5kcy1leHBhbnNpb24nLFxuICAgIHR5cGU6IHQuYm91bmRzRXhwYW5zaW9uLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9XTtcbiAgdmFyIG5vZGVCb3JkZXIgPSBbe1xuICAgIG5hbWU6ICdib3JkZXItY29sb3InLFxuICAgIHR5cGU6IHQuY29sb3JcbiAgfSwge1xuICAgIG5hbWU6ICdib3JkZXItb3BhY2l0eScsXG4gICAgdHlwZTogdC56ZXJvT25lTnVtYmVyXG4gIH0sIHtcbiAgICBuYW1lOiAnYm9yZGVyLXdpZHRoJyxcbiAgICB0eXBlOiB0LnNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnYm9yZGVyLXN0eWxlJyxcbiAgICB0eXBlOiB0LmJvcmRlclN0eWxlXG4gIH1dO1xuICB2YXIgYmFja2dyb3VuZEltYWdlID0gW3tcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1pbWFnZScsXG4gICAgdHlwZTogdC51cmxzXG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1pbWFnZS1jcm9zc29yaWdpbicsXG4gICAgdHlwZTogdC5iZ0Nyb3NzT3JpZ2luXG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1pbWFnZS1vcGFjaXR5JyxcbiAgICB0eXBlOiB0Lnplcm9PbmVOdW1iZXJzXG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1wb3NpdGlvbi14JyxcbiAgICB0eXBlOiB0LmJnUG9zXG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1wb3NpdGlvbi15JyxcbiAgICB0eXBlOiB0LmJnUG9zXG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC13aWR0aC1yZWxhdGl2ZS10bycsXG4gICAgdHlwZTogdC5iZ1JlbGF0aXZlVG9cbiAgfSwge1xuICAgIG5hbWU6ICdiYWNrZ3JvdW5kLWhlaWdodC1yZWxhdGl2ZS10bycsXG4gICAgdHlwZTogdC5iZ1JlbGF0aXZlVG9cbiAgfSwge1xuICAgIG5hbWU6ICdiYWNrZ3JvdW5kLXJlcGVhdCcsXG4gICAgdHlwZTogdC5iZ1JlcGVhdFxuICB9LCB7XG4gICAgbmFtZTogJ2JhY2tncm91bmQtZml0JyxcbiAgICB0eXBlOiB0LmJnRml0XG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1jbGlwJyxcbiAgICB0eXBlOiB0LmJnQ2xpcFxuICB9LCB7XG4gICAgbmFtZTogJ2JhY2tncm91bmQtd2lkdGgnLFxuICAgIHR5cGU6IHQuYmdXSFxuICB9LCB7XG4gICAgbmFtZTogJ2JhY2tncm91bmQtaGVpZ2h0JyxcbiAgICB0eXBlOiB0LmJnV0hcbiAgfSwge1xuICAgIG5hbWU6ICdiYWNrZ3JvdW5kLW9mZnNldC14JyxcbiAgICB0eXBlOiB0LmJnUG9zXG4gIH0sIHtcbiAgICBuYW1lOiAnYmFja2dyb3VuZC1vZmZzZXQteScsXG4gICAgdHlwZTogdC5iZ1Bvc1xuICB9XTtcbiAgdmFyIGNvbXBvdW5kID0gW3tcbiAgICBuYW1lOiAncG9zaXRpb24nLFxuICAgIHR5cGU6IHQucG9zaXRpb24sXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnY29tcG91bmQtc2l6aW5nLXdydC1sYWJlbHMnLFxuICAgIHR5cGU6IHQuY29tcG91bmRJbmNsdWRlTGFiZWxzLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ21pbi13aWR0aCcsXG4gICAgdHlwZTogdC5zaXplLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ21pbi13aWR0aC1iaWFzLWxlZnQnLFxuICAgIHR5cGU6IHQuc2l6ZU1heWJlUGVyY2VudCxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdtaW4td2lkdGgtYmlhcy1yaWdodCcsXG4gICAgdHlwZTogdC5zaXplTWF5YmVQZXJjZW50LFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ21pbi1oZWlnaHQnLFxuICAgIHR5cGU6IHQuc2l6ZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdtaW4taGVpZ2h0LWJpYXMtdG9wJyxcbiAgICB0eXBlOiB0LnNpemVNYXliZVBlcmNlbnQsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnbWluLWhlaWdodC1iaWFzLWJvdHRvbScsXG4gICAgdHlwZTogdC5zaXplTWF5YmVQZXJjZW50LFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9XTtcbiAgdmFyIGVkZ2VMaW5lID0gW3tcbiAgICBuYW1lOiAnbGluZS1zdHlsZScsXG4gICAgdHlwZTogdC5saW5lU3R5bGVcbiAgfSwge1xuICAgIG5hbWU6ICdsaW5lLWNvbG9yJyxcbiAgICB0eXBlOiB0LmNvbG9yXG4gIH0sIHtcbiAgICBuYW1lOiAnbGluZS1maWxsJyxcbiAgICB0eXBlOiB0LmZpbGxcbiAgfSwge1xuICAgIG5hbWU6ICdsaW5lLWNhcCcsXG4gICAgdHlwZTogdC5saW5lQ2FwXG4gIH0sIHtcbiAgICBuYW1lOiAnbGluZS1kYXNoLXBhdHRlcm4nLFxuICAgIHR5cGU6IHQubnVtYmVyc1xuICB9LCB7XG4gICAgbmFtZTogJ2xpbmUtZGFzaC1vZmZzZXQnLFxuICAgIHR5cGU6IHQubnVtYmVyXG4gIH0sIHtcbiAgICBuYW1lOiAnbGluZS1ncmFkaWVudC1zdG9wLWNvbG9ycycsXG4gICAgdHlwZTogdC5jb2xvcnNcbiAgfSwge1xuICAgIG5hbWU6ICdsaW5lLWdyYWRpZW50LXN0b3AtcG9zaXRpb25zJyxcbiAgICB0eXBlOiB0LnBlcmNlbnRhZ2VzXG4gIH0sIHtcbiAgICBuYW1lOiAnY3VydmUtc3R5bGUnLFxuICAgIHR5cGU6IHQuY3VydmVTdHlsZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnksXG4gICAgdHJpZ2dlcnNCb3VuZHNPZlBhcmFsbGVsQmV6aWVyczogdHJ1ZVxuICB9LCB7XG4gICAgbmFtZTogJ2hheXN0YWNrLXJhZGl1cycsXG4gICAgdHlwZTogdC56ZXJvT25lTnVtYmVyLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ3NvdXJjZS1lbmRwb2ludCcsXG4gICAgdHlwZTogdC5lZGdlRW5kcG9pbnQsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGFyZ2V0LWVuZHBvaW50JyxcbiAgICB0eXBlOiB0LmVkZ2VFbmRwb2ludCxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdjb250cm9sLXBvaW50LXN0ZXAtc2l6ZScsXG4gICAgdHlwZTogdC5zaXplLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ2NvbnRyb2wtcG9pbnQtZGlzdGFuY2VzJyxcbiAgICB0eXBlOiB0LmJpZGlyZWN0aW9uYWxTaXplcyxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdjb250cm9sLXBvaW50LXdlaWdodHMnLFxuICAgIHR5cGU6IHQubnVtYmVycyxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdzZWdtZW50LWRpc3RhbmNlcycsXG4gICAgdHlwZTogdC5iaWRpcmVjdGlvbmFsU2l6ZXMsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnc2VnbWVudC13ZWlnaHRzJyxcbiAgICB0eXBlOiB0Lm51bWJlcnMsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGF4aS10dXJuJyxcbiAgICB0eXBlOiB0LmJpZGlyZWN0aW9uYWxTaXplTWF5YmVQZXJjZW50LFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ3RheGktdHVybi1taW4tZGlzdGFuY2UnLFxuICAgIHR5cGU6IHQuc2l6ZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICd0YXhpLWRpcmVjdGlvbicsXG4gICAgdHlwZTogdC5heGlzRGlyZWN0aW9uLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ2VkZ2UtZGlzdGFuY2VzJyxcbiAgICB0eXBlOiB0LmVkZ2VEaXN0YW5jZXMsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnYXJyb3ctc2NhbGUnLFxuICAgIHR5cGU6IHQucG9zaXRpdmVOdW1iZXIsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnbG9vcC1kaXJlY3Rpb24nLFxuICAgIHR5cGU6IHQuYW5nbGUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAnbG9vcC1zd2VlcCcsXG4gICAgdHlwZTogdC5hbmdsZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdzb3VyY2UtZGlzdGFuY2UtZnJvbS1ub2RlJyxcbiAgICB0eXBlOiB0LnNpemUsXG4gICAgdHJpZ2dlcnNCb3VuZHM6IGRpZmYuYW55XG4gIH0sIHtcbiAgICBuYW1lOiAndGFyZ2V0LWRpc3RhbmNlLWZyb20tbm9kZScsXG4gICAgdHlwZTogdC5zaXplLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9XTtcbiAgdmFyIGdob3N0ID0gW3tcbiAgICBuYW1lOiAnZ2hvc3QnLFxuICAgIHR5cGU6IHQuYm9vbCxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdnaG9zdC1vZmZzZXQteCcsXG4gICAgdHlwZTogdC5iaWRpcmVjdGlvbmFsU2l6ZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdnaG9zdC1vZmZzZXQteScsXG4gICAgdHlwZTogdC5iaWRpcmVjdGlvbmFsU2l6ZSxcbiAgICB0cmlnZ2Vyc0JvdW5kczogZGlmZi5hbnlcbiAgfSwge1xuICAgIG5hbWU6ICdnaG9zdC1vcGFjaXR5JyxcbiAgICB0eXBlOiB0Lnplcm9PbmVOdW1iZXJcbiAgfV07XG4gIHZhciBjb3JlID0gW3tcbiAgICBuYW1lOiAnc2VsZWN0aW9uLWJveC1jb2xvcicsXG4gICAgdHlwZTogdC5jb2xvclxuICB9LCB7XG4gICAgbmFtZTogJ3NlbGVjdGlvbi1ib3gtb3BhY2l0eScsXG4gICAgdHlwZTogdC56ZXJvT25lTnVtYmVyXG4gIH0sIHtcbiAgICBuYW1lOiAnc2VsZWN0aW9uLWJveC1ib3JkZXItY29sb3InLFxuICAgIHR5cGU6IHQuY29sb3JcbiAgfSwge1xuICAgIG5hbWU6ICdzZWxlY3Rpb24tYm94LWJvcmRlci13aWR0aCcsXG4gICAgdHlwZTogdC5zaXplXG4gIH0sIHtcbiAgICBuYW1lOiAnYWN0aXZlLWJnLWNvbG9yJyxcbiAgICB0eXBlOiB0LmNvbG9yXG4gIH0sIHtcbiAgICBuYW1lOiAnYWN0aXZlLWJnLW9wYWNpdHknLFxuICAgIHR5cGU6IHQuemVyb09uZU51bWJlclxuICB9LCB7XG4gICAgbmFtZTogJ2FjdGl2ZS1iZy1zaXplJyxcbiAgICB0eXBlOiB0LnNpemVcbiAgfSwge1xuICAgIG5hbWU6ICdvdXRzaWRlLXRleHR1cmUtYmctY29sb3InLFxuICAgIHR5cGU6IHQuY29sb3JcbiAgfSwge1xuICAgIG5hbWU6ICdvdXRzaWRlLXRleHR1cmUtYmctb3BhY2l0eScsXG4gICAgdHlwZTogdC56ZXJvT25lTnVtYmVyXG4gIH1dOyAvLyBwaWUgYmFja2dyb3VuZHMgZm9yIG5vZGVzXG5cbiAgdmFyIHBpZSA9IFtdO1xuICBzdHlmbiQ2LnBpZUJhY2tncm91bmROID0gMTY7IC8vIGJlY2F1c2UgdGhlIHBpZSBwcm9wZXJ0aWVzIGFyZSBudW1iZXJlZCwgZ2l2ZSBhY2Nlc3MgdG8gYSBjb25zdGFudCBOIChmb3IgcmVuZGVyZXIgdXNlKVxuXG4gIHBpZS5wdXNoKHtcbiAgICBuYW1lOiAncGllLXNpemUnLFxuICAgIHR5cGU6IHQuc2l6ZU1heWJlUGVyY2VudFxuICB9KTtcblxuICBmb3IgKHZhciBpID0gMTsgaSA8PSBzdHlmbiQ2LnBpZUJhY2tncm91bmROOyBpKyspIHtcbiAgICBwaWUucHVzaCh7XG4gICAgICBuYW1lOiAncGllLScgKyBpICsgJy1iYWNrZ3JvdW5kLWNvbG9yJyxcbiAgICAgIHR5cGU6IHQuY29sb3JcbiAgICB9KTtcbiAgICBwaWUucHVzaCh7XG4gICAgICBuYW1lOiAncGllLScgKyBpICsgJy1iYWNrZ3JvdW5kLXNpemUnLFxuICAgICAgdHlwZTogdC5wZXJjZW50XG4gICAgfSk7XG4gICAgcGllLnB1c2goe1xuICAgICAgbmFtZTogJ3BpZS0nICsgaSArICctYmFja2dyb3VuZC1vcGFjaXR5JyxcbiAgICAgIHR5cGU6IHQuemVyb09uZU51bWJlclxuICAgIH0pO1xuICB9IC8vIGVkZ2UgYXJyb3dzXG5cblxuICB2YXIgZWRnZUFycm93ID0gW107XG4gIHZhciBhcnJvd1ByZWZpeGVzID0gc3R5Zm4kNi5hcnJvd1ByZWZpeGVzID0gWydzb3VyY2UnLCAnbWlkLXNvdXJjZScsICd0YXJnZXQnLCAnbWlkLXRhcmdldCddO1xuICBbe1xuICAgIG5hbWU6ICdhcnJvdy1zaGFwZScsXG4gICAgdHlwZTogdC5hcnJvd1NoYXBlLFxuICAgIHRyaWdnZXJzQm91bmRzOiBkaWZmLmFueVxuICB9LCB7XG4gICAgbmFtZTogJ2Fycm93LWNvbG9yJyxcbiAgICB0eXBlOiB0LmNvbG9yXG4gIH0sIHtcbiAgICBuYW1lOiAnYXJyb3ctZmlsbCcsXG4gICAgdHlwZTogdC5hcnJvd0ZpbGxcbiAgfV0uZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgIGFycm93UHJlZml4ZXMuZm9yRWFjaChmdW5jdGlvbiAocHJlZml4KSB7XG4gICAgICB2YXIgbmFtZSA9IHByZWZpeCArICctJyArIHByb3AubmFtZTtcbiAgICAgIHZhciB0eXBlID0gcHJvcC50eXBlLFxuICAgICAgICAgIHRyaWdnZXJzQm91bmRzID0gcHJvcC50cmlnZ2Vyc0JvdW5kcztcbiAgICAgIGVkZ2VBcnJvdy5wdXNoKHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgdHJpZ2dlcnNCb3VuZHM6IHRyaWdnZXJzQm91bmRzXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSwge30pO1xuICB2YXIgcHJvcHMgPSBzdHlmbiQ2LnByb3BlcnRpZXMgPSBbXS5jb25jYXQoYmVoYXZpb3IsIHRyYW5zaXRpb24sIHZpc2liaWxpdHksIG92ZXJsYXksIGdob3N0LCBjb21tb25MYWJlbCwgbGFiZWxEaW1lbnNpb25zLCBtYWluTGFiZWwsIHNvdXJjZUxhYmVsLCB0YXJnZXRMYWJlbCwgbm9kZUJvZHksIG5vZGVCb3JkZXIsIGJhY2tncm91bmRJbWFnZSwgcGllLCBjb21wb3VuZCwgZWRnZUxpbmUsIGVkZ2VBcnJvdywgY29yZSk7XG4gIHZhciBwcm9wR3JvdXBzID0gc3R5Zm4kNi5wcm9wZXJ0eUdyb3VwcyA9IHtcbiAgICAvLyBjb21tb24gdG8gYWxsIGVsZXNcbiAgICBiZWhhdmlvcjogYmVoYXZpb3IsXG4gICAgdHJhbnNpdGlvbjogdHJhbnNpdGlvbixcbiAgICB2aXNpYmlsaXR5OiB2aXNpYmlsaXR5LFxuICAgIG92ZXJsYXk6IG92ZXJsYXksXG4gICAgZ2hvc3Q6IGdob3N0LFxuICAgIC8vIGxhYmVsc1xuICAgIGNvbW1vbkxhYmVsOiBjb21tb25MYWJlbCxcbiAgICBsYWJlbERpbWVuc2lvbnM6IGxhYmVsRGltZW5zaW9ucyxcbiAgICBtYWluTGFiZWw6IG1haW5MYWJlbCxcbiAgICBzb3VyY2VMYWJlbDogc291cmNlTGFiZWwsXG4gICAgdGFyZ2V0TGFiZWw6IHRhcmdldExhYmVsLFxuICAgIC8vIG5vZGUgcHJvcHNcbiAgICBub2RlQm9keTogbm9kZUJvZHksXG4gICAgbm9kZUJvcmRlcjogbm9kZUJvcmRlcixcbiAgICBiYWNrZ3JvdW5kSW1hZ2U6IGJhY2tncm91bmRJbWFnZSxcbiAgICBwaWU6IHBpZSxcbiAgICBjb21wb3VuZDogY29tcG91bmQsXG4gICAgLy8gZWRnZSBwcm9wc1xuICAgIGVkZ2VMaW5lOiBlZGdlTGluZSxcbiAgICBlZGdlQXJyb3c6IGVkZ2VBcnJvdyxcbiAgICBjb3JlOiBjb3JlXG4gIH07XG4gIHZhciBwcm9wR3JvdXBOYW1lcyA9IHN0eWZuJDYucHJvcGVydHlHcm91cE5hbWVzID0ge307XG4gIHZhciBwcm9wR3JvdXBLZXlzID0gc3R5Zm4kNi5wcm9wZXJ0eUdyb3VwS2V5cyA9IE9iamVjdC5rZXlzKHByb3BHcm91cHMpO1xuICBwcm9wR3JvdXBLZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIHByb3BHcm91cE5hbWVzW2tleV0gPSBwcm9wR3JvdXBzW2tleV0ubWFwKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICByZXR1cm4gcHJvcC5uYW1lO1xuICAgIH0pO1xuICAgIHByb3BHcm91cHNba2V5XS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICByZXR1cm4gcHJvcC5ncm91cEtleSA9IGtleTtcbiAgICB9KTtcbiAgfSk7IC8vIGRlZmluZSBhbGlhc2VzXG5cbiAgdmFyIGFsaWFzZXMgPSBzdHlmbiQ2LmFsaWFzZXMgPSBbe1xuICAgIG5hbWU6ICdjb250ZW50JyxcbiAgICBwb2ludHNUbzogJ2xhYmVsJ1xuICB9LCB7XG4gICAgbmFtZTogJ2NvbnRyb2wtcG9pbnQtZGlzdGFuY2UnLFxuICAgIHBvaW50c1RvOiAnY29udHJvbC1wb2ludC1kaXN0YW5jZXMnXG4gIH0sIHtcbiAgICBuYW1lOiAnY29udHJvbC1wb2ludC13ZWlnaHQnLFxuICAgIHBvaW50c1RvOiAnY29udHJvbC1wb2ludC13ZWlnaHRzJ1xuICB9LCB7XG4gICAgbmFtZTogJ2VkZ2UtdGV4dC1yb3RhdGlvbicsXG4gICAgcG9pbnRzVG86ICd0ZXh0LXJvdGF0aW9uJ1xuICB9LCB7XG4gICAgbmFtZTogJ3BhZGRpbmctbGVmdCcsXG4gICAgcG9pbnRzVG86ICdwYWRkaW5nJ1xuICB9LCB7XG4gICAgbmFtZTogJ3BhZGRpbmctcmlnaHQnLFxuICAgIHBvaW50c1RvOiAncGFkZGluZydcbiAgfSwge1xuICAgIG5hbWU6ICdwYWRkaW5nLXRvcCcsXG4gICAgcG9pbnRzVG86ICdwYWRkaW5nJ1xuICB9LCB7XG4gICAgbmFtZTogJ3BhZGRpbmctYm90dG9tJyxcbiAgICBwb2ludHNUbzogJ3BhZGRpbmcnXG4gIH1dOyAvLyBsaXN0IG9mIHByb3BlcnR5IG5hbWVzXG5cbiAgc3R5Zm4kNi5wcm9wZXJ0eU5hbWVzID0gcHJvcHMubWFwKGZ1bmN0aW9uIChwKSB7XG4gICAgcmV0dXJuIHAubmFtZTtcbiAgfSk7IC8vIGFsbG93IGFjY2VzcyBvZiBwcm9wZXJ0aWVzIGJ5IG5hbWUgKCBlLmcuIHN0eWxlLnByb3BlcnRpZXMuaGVpZ2h0IClcblxuICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgcHJvcHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgdmFyIHByb3AgPSBwcm9wc1tfaV07XG4gICAgcHJvcHNbcHJvcC5uYW1lXSA9IHByb3A7IC8vIGFsbG93IGxvb2t1cCBieSBuYW1lXG4gIH0gLy8gbWFwIGFsaWFzZXNcblxuXG4gIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IGFsaWFzZXMubGVuZ3RoOyBfaTIrKykge1xuICAgIHZhciBhbGlhcyA9IGFsaWFzZXNbX2kyXTtcbiAgICB2YXIgcG9pbnRzVG9Qcm9wID0gcHJvcHNbYWxpYXMucG9pbnRzVG9dO1xuICAgIHZhciBhbGlhc1Byb3AgPSB7XG4gICAgICBuYW1lOiBhbGlhcy5uYW1lLFxuICAgICAgYWxpYXM6IHRydWUsXG4gICAgICBwb2ludHNUbzogcG9pbnRzVG9Qcm9wXG4gICAgfTsgLy8gYWRkIGFsaWFzIHByb3AgZm9yIHBhcnNpbmdcblxuICAgIHByb3BzLnB1c2goYWxpYXNQcm9wKTtcbiAgICBwcm9wc1thbGlhcy5uYW1lXSA9IGFsaWFzUHJvcDsgLy8gYWxsb3cgbG9va3VwIGJ5IG5hbWVcbiAgfVxufSkoKTtcblxuc3R5Zm4kNi5nZXREZWZhdWx0UHJvcGVydHkgPSBmdW5jdGlvbiAobmFtZSkge1xuICByZXR1cm4gdGhpcy5nZXREZWZhdWx0UHJvcGVydGllcygpW25hbWVdO1xufTtcblxuc3R5Zm4kNi5nZXREZWZhdWx0UHJvcGVydGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9wID0gdGhpcy5fcHJpdmF0ZTtcblxuICBpZiAoX3AuZGVmYXVsdFByb3BlcnRpZXMgIT0gbnVsbCkge1xuICAgIHJldHVybiBfcC5kZWZhdWx0UHJvcGVydGllcztcbiAgfVxuXG4gIHZhciByYXdQcm9wcyA9IGV4dGVuZCh7XG4gICAgLy8gY29yZSBwcm9wc1xuICAgICdzZWxlY3Rpb24tYm94LWNvbG9yJzogJyNkZGQnLFxuICAgICdzZWxlY3Rpb24tYm94LW9wYWNpdHknOiAwLjY1LFxuICAgICdzZWxlY3Rpb24tYm94LWJvcmRlci1jb2xvcic6ICcjYWFhJyxcbiAgICAnc2VsZWN0aW9uLWJveC1ib3JkZXItd2lkdGgnOiAxLFxuICAgICdhY3RpdmUtYmctY29sb3InOiAnYmxhY2snLFxuICAgICdhY3RpdmUtYmctb3BhY2l0eSc6IDAuMTUsXG4gICAgJ2FjdGl2ZS1iZy1zaXplJzogMzAsXG4gICAgJ291dHNpZGUtdGV4dHVyZS1iZy1jb2xvcic6ICcjMDAwJyxcbiAgICAnb3V0c2lkZS10ZXh0dXJlLWJnLW9wYWNpdHknOiAwLjEyNSxcbiAgICAvLyBjb21tb24gbm9kZS9lZGdlIHByb3BzXG4gICAgJ2V2ZW50cyc6ICd5ZXMnLFxuICAgICd0ZXh0LWV2ZW50cyc6ICdubycsXG4gICAgJ3RleHQtdmFsaWduJzogJ3RvcCcsXG4gICAgJ3RleHQtaGFsaWduJzogJ2NlbnRlcicsXG4gICAgJ3RleHQtanVzdGlmaWNhdGlvbic6ICdhdXRvJyxcbiAgICAnbGluZS1oZWlnaHQnOiAxLFxuICAgICdjb2xvcic6ICcjMDAwJyxcbiAgICAndGV4dC1vdXRsaW5lLWNvbG9yJzogJyMwMDAnLFxuICAgICd0ZXh0LW91dGxpbmUtd2lkdGgnOiAwLFxuICAgICd0ZXh0LW91dGxpbmUtb3BhY2l0eSc6IDEsXG4gICAgJ3RleHQtb3BhY2l0eSc6IDEsXG4gICAgJ3RleHQtZGVjb3JhdGlvbic6ICdub25lJyxcbiAgICAndGV4dC10cmFuc2Zvcm0nOiAnbm9uZScsXG4gICAgJ3RleHQtd3JhcCc6ICdub25lJyxcbiAgICAndGV4dC1vdmVyZmxvdy13cmFwJzogJ3doaXRlc3BhY2UnLFxuICAgICd0ZXh0LW1heC13aWR0aCc6IDk5OTksXG4gICAgJ3RleHQtYmFja2dyb3VuZC1jb2xvcic6ICcjMDAwJyxcbiAgICAndGV4dC1iYWNrZ3JvdW5kLW9wYWNpdHknOiAwLFxuICAgICd0ZXh0LWJhY2tncm91bmQtc2hhcGUnOiAncmVjdGFuZ2xlJyxcbiAgICAndGV4dC1iYWNrZ3JvdW5kLXBhZGRpbmcnOiAwLFxuICAgICd0ZXh0LWJvcmRlci1vcGFjaXR5JzogMCxcbiAgICAndGV4dC1ib3JkZXItd2lkdGgnOiAwLFxuICAgICd0ZXh0LWJvcmRlci1zdHlsZSc6ICdzb2xpZCcsXG4gICAgJ3RleHQtYm9yZGVyLWNvbG9yJzogJyMwMDAnLFxuICAgICdmb250LWZhbWlseSc6ICdIZWx2ZXRpY2EgTmV1ZSwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmJyxcbiAgICAnZm9udC1zdHlsZSc6ICdub3JtYWwnLFxuICAgICdmb250LXdlaWdodCc6ICdub3JtYWwnLFxuICAgICdmb250LXNpemUnOiAxNixcbiAgICAnbWluLXpvb21lZC1mb250LXNpemUnOiAwLFxuICAgICd0ZXh0LXJvdGF0aW9uJzogJ25vbmUnLFxuICAgICdzb3VyY2UtdGV4dC1yb3RhdGlvbic6ICdub25lJyxcbiAgICAndGFyZ2V0LXRleHQtcm90YXRpb24nOiAnbm9uZScsXG4gICAgJ3Zpc2liaWxpdHknOiAndmlzaWJsZScsXG4gICAgJ2Rpc3BsYXknOiAnZWxlbWVudCcsXG4gICAgJ29wYWNpdHknOiAxLFxuICAgICd6LWNvbXBvdW5kLWRlcHRoJzogJ2F1dG8nLFxuICAgICd6LWluZGV4LWNvbXBhcmUnOiAnYXV0bycsXG4gICAgJ3otaW5kZXgnOiAwLFxuICAgICdsYWJlbCc6ICcnLFxuICAgICd0ZXh0LW1hcmdpbi14JzogMCxcbiAgICAndGV4dC1tYXJnaW4teSc6IDAsXG4gICAgJ3NvdXJjZS1sYWJlbCc6ICcnLFxuICAgICdzb3VyY2UtdGV4dC1vZmZzZXQnOiAwLFxuICAgICdzb3VyY2UtdGV4dC1tYXJnaW4teCc6IDAsXG4gICAgJ3NvdXJjZS10ZXh0LW1hcmdpbi15JzogMCxcbiAgICAndGFyZ2V0LWxhYmVsJzogJycsXG4gICAgJ3RhcmdldC10ZXh0LW9mZnNldCc6IDAsXG4gICAgJ3RhcmdldC10ZXh0LW1hcmdpbi14JzogMCxcbiAgICAndGFyZ2V0LXRleHQtbWFyZ2luLXknOiAwLFxuICAgICdvdmVybGF5LW9wYWNpdHknOiAwLFxuICAgICdvdmVybGF5LWNvbG9yJzogJyMwMDAnLFxuICAgICdvdmVybGF5LXBhZGRpbmcnOiAxMCxcbiAgICAndHJhbnNpdGlvbi1wcm9wZXJ0eSc6ICdub25lJyxcbiAgICAndHJhbnNpdGlvbi1kdXJhdGlvbic6IDAsXG4gICAgJ3RyYW5zaXRpb24tZGVsYXknOiAwLFxuICAgICd0cmFuc2l0aW9uLXRpbWluZy1mdW5jdGlvbic6ICdsaW5lYXInLFxuICAgIC8vIG5vZGUgcHJvcHNcbiAgICAnYmFja2dyb3VuZC1ibGFja2VuJzogMCxcbiAgICAnYmFja2dyb3VuZC1jb2xvcic6ICcjOTk5JyxcbiAgICAnYmFja2dyb3VuZC1maWxsJzogJ3NvbGlkJyxcbiAgICAnYmFja2dyb3VuZC1vcGFjaXR5JzogMSxcbiAgICAnYmFja2dyb3VuZC1pbWFnZSc6ICdub25lJyxcbiAgICAnYmFja2dyb3VuZC1pbWFnZS1jcm9zc29yaWdpbic6ICdhbm9ueW1vdXMnLFxuICAgICdiYWNrZ3JvdW5kLWltYWdlLW9wYWNpdHknOiAxLFxuICAgICdiYWNrZ3JvdW5kLXBvc2l0aW9uLXgnOiAnNTAlJyxcbiAgICAnYmFja2dyb3VuZC1wb3NpdGlvbi15JzogJzUwJScsXG4gICAgJ2JhY2tncm91bmQtb2Zmc2V0LXgnOiAwLFxuICAgICdiYWNrZ3JvdW5kLW9mZnNldC15JzogMCxcbiAgICAnYmFja2dyb3VuZC13aWR0aC1yZWxhdGl2ZS10byc6ICdpbmNsdWRlLXBhZGRpbmcnLFxuICAgICdiYWNrZ3JvdW5kLWhlaWdodC1yZWxhdGl2ZS10byc6ICdpbmNsdWRlLXBhZGRpbmcnLFxuICAgICdiYWNrZ3JvdW5kLXJlcGVhdCc6ICduby1yZXBlYXQnLFxuICAgICdiYWNrZ3JvdW5kLWZpdCc6ICdub25lJyxcbiAgICAnYmFja2dyb3VuZC1jbGlwJzogJ25vZGUnLFxuICAgICdiYWNrZ3JvdW5kLXdpZHRoJzogJ2F1dG8nLFxuICAgICdiYWNrZ3JvdW5kLWhlaWdodCc6ICdhdXRvJyxcbiAgICAnYm9yZGVyLWNvbG9yJzogJyMwMDAnLFxuICAgICdib3JkZXItb3BhY2l0eSc6IDEsXG4gICAgJ2JvcmRlci13aWR0aCc6IDAsXG4gICAgJ2JvcmRlci1zdHlsZSc6ICdzb2xpZCcsXG4gICAgJ2hlaWdodCc6IDMwLFxuICAgICd3aWR0aCc6IDMwLFxuICAgICdzaGFwZSc6ICdlbGxpcHNlJyxcbiAgICAnc2hhcGUtcG9seWdvbi1wb2ludHMnOiAnLTEsIC0xLCAgIDEsIC0xLCAgIDEsIDEsICAgLTEsIDEnLFxuICAgICdib3VuZHMtZXhwYW5zaW9uJzogMCxcbiAgICAvLyBub2RlIGdyYWRpZW50XG4gICAgJ2JhY2tncm91bmQtZ3JhZGllbnQtZGlyZWN0aW9uJzogJ3RvLWJvdHRvbScsXG4gICAgJ2JhY2tncm91bmQtZ3JhZGllbnQtc3RvcC1jb2xvcnMnOiAnIzk5OScsXG4gICAgJ2JhY2tncm91bmQtZ3JhZGllbnQtc3RvcC1wb3NpdGlvbnMnOiAnMCUnLFxuICAgIC8vIGdob3N0IHByb3BzXG4gICAgJ2dob3N0JzogJ25vJyxcbiAgICAnZ2hvc3Qtb2Zmc2V0LXknOiAwLFxuICAgICdnaG9zdC1vZmZzZXQteCc6IDAsXG4gICAgJ2dob3N0LW9wYWNpdHknOiAwLFxuICAgIC8vIGNvbXBvdW5kIHByb3BzXG4gICAgJ3BhZGRpbmcnOiAwLFxuICAgICdwYWRkaW5nLXJlbGF0aXZlLXRvJzogJ3dpZHRoJyxcbiAgICAncG9zaXRpb24nOiAnb3JpZ2luJyxcbiAgICAnY29tcG91bmQtc2l6aW5nLXdydC1sYWJlbHMnOiAnaW5jbHVkZScsXG4gICAgJ21pbi13aWR0aCc6IDAsXG4gICAgJ21pbi13aWR0aC1iaWFzLWxlZnQnOiAwLFxuICAgICdtaW4td2lkdGgtYmlhcy1yaWdodCc6IDAsXG4gICAgJ21pbi1oZWlnaHQnOiAwLFxuICAgICdtaW4taGVpZ2h0LWJpYXMtdG9wJzogMCxcbiAgICAnbWluLWhlaWdodC1iaWFzLWJvdHRvbSc6IDBcbiAgfSwge1xuICAgIC8vIG5vZGUgcGllIGJnXG4gICAgJ3BpZS1zaXplJzogJzEwMCUnXG4gIH0sIFt7XG4gICAgbmFtZTogJ3BpZS17e2l9fS1iYWNrZ3JvdW5kLWNvbG9yJyxcbiAgICB2YWx1ZTogJ2JsYWNrJ1xuICB9LCB7XG4gICAgbmFtZTogJ3BpZS17e2l9fS1iYWNrZ3JvdW5kLXNpemUnLFxuICAgIHZhbHVlOiAnMCUnXG4gIH0sIHtcbiAgICBuYW1lOiAncGllLXt7aX19LWJhY2tncm91bmQtb3BhY2l0eScsXG4gICAgdmFsdWU6IDFcbiAgfV0ucmVkdWNlKGZ1bmN0aW9uIChjc3MsIHByb3ApIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8PSBzdHlmbiQ2LnBpZUJhY2tncm91bmROOyBpKyspIHtcbiAgICAgIHZhciBuYW1lID0gcHJvcC5uYW1lLnJlcGxhY2UoJ3t7aX19JywgaSk7XG4gICAgICB2YXIgdmFsID0gcHJvcC52YWx1ZTtcbiAgICAgIGNzc1tuYW1lXSA9IHZhbDtcbiAgICB9XG5cbiAgICByZXR1cm4gY3NzO1xuICB9LCB7fSksIHtcbiAgICAvLyBlZGdlIHByb3BzXG4gICAgJ2xpbmUtc3R5bGUnOiAnc29saWQnLFxuICAgICdsaW5lLWNvbG9yJzogJyM5OTknLFxuICAgICdsaW5lLWZpbGwnOiAnc29saWQnLFxuICAgICdsaW5lLWNhcCc6ICdidXR0JyxcbiAgICAnbGluZS1ncmFkaWVudC1zdG9wLWNvbG9ycyc6ICcjOTk5JyxcbiAgICAnbGluZS1ncmFkaWVudC1zdG9wLXBvc2l0aW9ucyc6ICcwJScsXG4gICAgJ2NvbnRyb2wtcG9pbnQtc3RlcC1zaXplJzogNDAsXG4gICAgJ2NvbnRyb2wtcG9pbnQtd2VpZ2h0cyc6IDAuNSxcbiAgICAnc2VnbWVudC13ZWlnaHRzJzogMC41LFxuICAgICdzZWdtZW50LWRpc3RhbmNlcyc6IDIwLFxuICAgICd0YXhpLXR1cm4nOiAnNTAlJyxcbiAgICAndGF4aS10dXJuLW1pbi1kaXN0YW5jZSc6IDEwLFxuICAgICd0YXhpLWRpcmVjdGlvbic6ICdhdXRvJyxcbiAgICAnZWRnZS1kaXN0YW5jZXMnOiAnaW50ZXJzZWN0aW9uJyxcbiAgICAnY3VydmUtc3R5bGUnOiAnaGF5c3RhY2snLFxuICAgICdoYXlzdGFjay1yYWRpdXMnOiAwLFxuICAgICdhcnJvdy1zY2FsZSc6IDEsXG4gICAgJ2xvb3AtZGlyZWN0aW9uJzogJy00NWRlZycsXG4gICAgJ2xvb3Atc3dlZXAnOiAnLTkwZGVnJyxcbiAgICAnc291cmNlLWRpc3RhbmNlLWZyb20tbm9kZSc6IDAsXG4gICAgJ3RhcmdldC1kaXN0YW5jZS1mcm9tLW5vZGUnOiAwLFxuICAgICdzb3VyY2UtZW5kcG9pbnQnOiAnb3V0c2lkZS10by1ub2RlJyxcbiAgICAndGFyZ2V0LWVuZHBvaW50JzogJ291dHNpZGUtdG8tbm9kZScsXG4gICAgJ2xpbmUtZGFzaC1wYXR0ZXJuJzogWzYsIDNdLFxuICAgICdsaW5lLWRhc2gtb2Zmc2V0JzogMFxuICB9LCBbe1xuICAgIG5hbWU6ICdhcnJvdy1zaGFwZScsXG4gICAgdmFsdWU6ICdub25lJ1xuICB9LCB7XG4gICAgbmFtZTogJ2Fycm93LWNvbG9yJyxcbiAgICB2YWx1ZTogJyM5OTknXG4gIH0sIHtcbiAgICBuYW1lOiAnYXJyb3ctZmlsbCcsXG4gICAgdmFsdWU6ICdmaWxsZWQnXG4gIH1dLnJlZHVjZShmdW5jdGlvbiAoY3NzLCBwcm9wKSB7XG4gICAgc3R5Zm4kNi5hcnJvd1ByZWZpeGVzLmZvckVhY2goZnVuY3Rpb24gKHByZWZpeCkge1xuICAgICAgdmFyIG5hbWUgPSBwcmVmaXggKyAnLScgKyBwcm9wLm5hbWU7XG4gICAgICB2YXIgdmFsID0gcHJvcC52YWx1ZTtcbiAgICAgIGNzc1tuYW1lXSA9IHZhbDtcbiAgICB9KTtcbiAgICByZXR1cm4gY3NzO1xuICB9LCB7fSkpO1xuICB2YXIgcGFyc2VkUHJvcHMgPSB7fTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucHJvcGVydGllcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwcm9wID0gdGhpcy5wcm9wZXJ0aWVzW2ldO1xuXG4gICAgaWYgKHByb3AucG9pbnRzVG8pIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBuYW1lID0gcHJvcC5uYW1lO1xuICAgIHZhciB2YWwgPSByYXdQcm9wc1tuYW1lXTtcbiAgICB2YXIgcGFyc2VkUHJvcCA9IHRoaXMucGFyc2UobmFtZSwgdmFsKTtcbiAgICBwYXJzZWRQcm9wc1tuYW1lXSA9IHBhcnNlZFByb3A7XG4gIH1cblxuICBfcC5kZWZhdWx0UHJvcGVydGllcyA9IHBhcnNlZFByb3BzO1xuICByZXR1cm4gX3AuZGVmYXVsdFByb3BlcnRpZXM7XG59O1xuXG5zdHlmbiQ2LmFkZERlZmF1bHRTdHlsZXNoZWV0ID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLnNlbGVjdG9yKCc6cGFyZW50JykuY3NzKHtcbiAgICAnc2hhcGUnOiAncmVjdGFuZ2xlJyxcbiAgICAncGFkZGluZyc6IDEwLFxuICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogJyNlZWUnLFxuICAgICdib3JkZXItY29sb3InOiAnI2NjYycsXG4gICAgJ2JvcmRlci13aWR0aCc6IDFcbiAgfSkuc2VsZWN0b3IoJ2VkZ2UnKS5jc3Moe1xuICAgICd3aWR0aCc6IDNcbiAgfSkuc2VsZWN0b3IoJzpsb29wJykuY3NzKHtcbiAgICAnY3VydmUtc3R5bGUnOiAnYmV6aWVyJ1xuICB9KS5zZWxlY3RvcignZWRnZTpjb21wb3VuZCcpLmNzcyh7XG4gICAgJ2N1cnZlLXN0eWxlJzogJ2JlemllcicsXG4gICAgJ3NvdXJjZS1lbmRwb2ludCc6ICdvdXRzaWRlLXRvLWxpbmUnLFxuICAgICd0YXJnZXQtZW5kcG9pbnQnOiAnb3V0c2lkZS10by1saW5lJ1xuICB9KS5zZWxlY3RvcignOnNlbGVjdGVkJykuY3NzKHtcbiAgICAnYmFja2dyb3VuZC1jb2xvcic6ICcjMDE2OUQ5JyxcbiAgICAnbGluZS1jb2xvcic6ICcjMDE2OUQ5JyxcbiAgICAnc291cmNlLWFycm93LWNvbG9yJzogJyMwMTY5RDknLFxuICAgICd0YXJnZXQtYXJyb3ctY29sb3InOiAnIzAxNjlEOScsXG4gICAgJ21pZC1zb3VyY2UtYXJyb3ctY29sb3InOiAnIzAxNjlEOScsXG4gICAgJ21pZC10YXJnZXQtYXJyb3ctY29sb3InOiAnIzAxNjlEOSdcbiAgfSkuc2VsZWN0b3IoJzpwYXJlbnQ6c2VsZWN0ZWQnKS5jc3Moe1xuICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogJyNDQ0UxRjknLFxuICAgICdib3JkZXItY29sb3InOiAnI2FlYzhlNSdcbiAgfSkuc2VsZWN0b3IoJzphY3RpdmUnKS5jc3Moe1xuICAgICdvdmVybGF5LWNvbG9yJzogJ2JsYWNrJyxcbiAgICAnb3ZlcmxheS1wYWRkaW5nJzogMTAsXG4gICAgJ292ZXJsYXktb3BhY2l0eSc6IDAuMjVcbiAgfSk7XG4gIHRoaXMuZGVmYXVsdExlbmd0aCA9IHRoaXMubGVuZ3RoO1xufTtcblxudmFyIHN0eWZuJDcgPSB7fTsgLy8gYSBjYWNoaW5nIGxheWVyIGZvciBwcm9wZXJ0eSBwYXJzaW5nXG5cbnN0eWZuJDcucGFyc2UgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUsIHByb3BJc0J5cGFzcywgcHJvcElzRmxhdCkge1xuICB2YXIgc2VsZiA9IHRoaXM7IC8vIGZ1bmN0aW9uIHZhbHVlcyBjYW4ndCBiZSBjYWNoZWQgaW4gYWxsIGNhc2VzLCBhbmQgdGhlcmUgaXNuJ3QgbXVjaCBiZW5lZml0IG9mIGNhY2hpbmcgdGhlbSBhbnl3YXlcblxuICBpZiAoZm4odmFsdWUpKSB7XG4gICAgcmV0dXJuIHNlbGYucGFyc2VJbXBsV2FybihuYW1lLCB2YWx1ZSwgcHJvcElzQnlwYXNzLCBwcm9wSXNGbGF0KTtcbiAgfVxuXG4gIHZhciBmbGF0S2V5ID0gcHJvcElzRmxhdCA9PT0gJ21hcHBpbmcnIHx8IHByb3BJc0ZsYXQgPT09IHRydWUgfHwgcHJvcElzRmxhdCA9PT0gZmFsc2UgfHwgcHJvcElzRmxhdCA9PSBudWxsID8gJ2RvbnRjYXJlJyA6IHByb3BJc0ZsYXQ7XG4gIHZhciBieXBhc3NLZXkgPSBwcm9wSXNCeXBhc3MgPyAndCcgOiAnZic7XG4gIHZhciB2YWx1ZUtleSA9ICcnICsgdmFsdWU7XG4gIHZhciBhcmdIYXNoID0gaGFzaFN0cmluZ3MobmFtZSwgdmFsdWVLZXksIGJ5cGFzc0tleSwgZmxhdEtleSk7XG4gIHZhciBwcm9wQ2FjaGUgPSBzZWxmLnByb3BDYWNoZSA9IHNlbGYucHJvcENhY2hlIHx8IFtdO1xuICB2YXIgcmV0O1xuXG4gIGlmICghKHJldCA9IHByb3BDYWNoZVthcmdIYXNoXSkpIHtcbiAgICByZXQgPSBwcm9wQ2FjaGVbYXJnSGFzaF0gPSBzZWxmLnBhcnNlSW1wbFdhcm4obmFtZSwgdmFsdWUsIHByb3BJc0J5cGFzcywgcHJvcElzRmxhdCk7XG4gIH0gLy8gLSBieXBhc3NlcyBjYW4ndCBiZSBzaGFyZWQgYi9jIHRoZSB2YWx1ZSBjYW4gYmUgY2hhbmdlZCBieSBhbmltYXRpb25zIG9yIG90aGVyd2lzZSBvdmVycmlkZGVuXG4gIC8vIC0gbWFwcGluZ3MgY2FuJ3QgYmUgc2hhcmVkIGIvYyBtYXBwaW5ncyBhcmUgcGVyLWVsZW1lbnRcblxuXG4gIGlmIChwcm9wSXNCeXBhc3MgfHwgcHJvcElzRmxhdCA9PT0gJ21hcHBpbmcnKSB7XG4gICAgLy8gbmVlZCBhIGNvcHkgc2luY2UgcHJvcHMgYXJlIG11dGF0ZWQgbGF0ZXIgaW4gdGhlaXIgbGlmZWN5Y2xlc1xuICAgIHJldCA9IGNvcHkocmV0KTtcblxuICAgIGlmIChyZXQpIHtcbiAgICAgIHJldC52YWx1ZSA9IGNvcHkocmV0LnZhbHVlKTsgLy8gYmVjYXVzZSBpdCBjb3VsZCBiZSBhbiBhcnJheSwgZS5nLiBjb2xvdXJcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0O1xufTtcblxuc3R5Zm4kNy5wYXJzZUltcGxXYXJuID0gZnVuY3Rpb24gKG5hbWUsIHZhbHVlLCBwcm9wSXNCeXBhc3MsIHByb3BJc0ZsYXQpIHtcbiAgdmFyIHByb3AgPSB0aGlzLnBhcnNlSW1wbChuYW1lLCB2YWx1ZSwgcHJvcElzQnlwYXNzLCBwcm9wSXNGbGF0KTtcblxuICBpZiAoIXByb3AgJiYgdmFsdWUgIT0gbnVsbCkge1xuICAgIHdhcm4oXCJUaGUgc3R5bGUgcHJvcGVydHkgYFwiLmNvbmNhdChuYW1lLCBcIjogXCIpLmNvbmNhdCh2YWx1ZSwgXCJgIGlzIGludmFsaWRcIikpO1xuICB9XG5cbiAgcmV0dXJuIHByb3A7XG59OyAvLyBwYXJzZSBhIHByb3BlcnR5OyByZXR1cm4gbnVsbCBvbiBpbnZhbGlkOyByZXR1cm4gcGFyc2VkIHByb3BlcnR5IG90aGVyd2lzZVxuLy8gZmllbGRzIDpcbi8vIC0gbmFtZSA6IHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eVxuLy8gLSB2YWx1ZSA6IHRoZSBwYXJzZWQsIG5hdGl2ZS10eXBlZCB2YWx1ZSBvZiB0aGUgcHJvcGVydHlcbi8vIC0gc3RyVmFsdWUgOiBhIHN0cmluZyB2YWx1ZSB0aGF0IHJlcHJlc2VudHMgdGhlIHByb3BlcnR5IHZhbHVlIGluIHZhbGlkIGNzc1xuLy8gLSBieXBhc3MgOiB0cnVlIGlmZiB0aGUgcHJvcGVydHkgaXMgYSBieXBhc3MgcHJvcGVydHlcblxuXG5zdHlmbiQ3LnBhcnNlSW1wbCA9IGZ1bmN0aW9uIChuYW1lLCB2YWx1ZSwgcHJvcElzQnlwYXNzLCBwcm9wSXNGbGF0KSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgbmFtZSA9IGNhbWVsMmRhc2gobmFtZSk7IC8vIG1ha2Ugc3VyZSB0aGUgcHJvcGVydHkgbmFtZSBpcyBpbiBkYXNoIGZvcm0gKGUuZy4gJ3Byb3BlcnR5LW5hbWUnIG5vdCAncHJvcGVydHlOYW1lJylcblxuICB2YXIgcHJvcGVydHkgPSBzZWxmLnByb3BlcnRpZXNbbmFtZV07XG4gIHZhciBwYXNzZWRWYWx1ZSA9IHZhbHVlO1xuICB2YXIgdHlwZXMgPSBzZWxmLnR5cGVzO1xuXG4gIGlmICghcHJvcGVydHkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSAvLyByZXR1cm4gbnVsbCBvbiBwcm9wZXJ0eSBvZiB1bmtub3duIG5hbWVcblxuXG4gIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH0gLy8gY2FuJ3QgYXNzaWduIHVuZGVmaW5lZFxuICAvLyB0aGUgcHJvcGVydHkgbWF5IGJlIGFuIGFsaWFzXG5cblxuICBpZiAocHJvcGVydHkuYWxpYXMpIHtcbiAgICBwcm9wZXJ0eSA9IHByb3BlcnR5LnBvaW50c1RvO1xuICAgIG5hbWUgPSBwcm9wZXJ0eS5uYW1lO1xuICB9XG5cbiAgdmFyIHZhbHVlSXNTdHJpbmcgPSBzdHJpbmcodmFsdWUpO1xuXG4gIGlmICh2YWx1ZUlzU3RyaW5nKSB7XG4gICAgLy8gdHJpbSB0aGUgdmFsdWUgdG8gbWFrZSBwYXJzaW5nIGVhc2llclxuICAgIHZhbHVlID0gdmFsdWUudHJpbSgpO1xuICB9XG5cbiAgdmFyIHR5cGUgPSBwcm9wZXJ0eS50eXBlO1xuXG4gIGlmICghdHlwZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9IC8vIG5vIHR5cGUsIG5vIGx1Y2tcbiAgLy8gY2hlY2sgaWYgYnlwYXNzIGlzIG51bGwgb3IgZW1wdHkgc3RyaW5nIChpLmUuIGluZGljYXRpb24gdG8gZGVsZXRlIGJ5cGFzcyBwcm9wZXJ0eSlcblxuXG4gIGlmIChwcm9wSXNCeXBhc3MgJiYgKHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gbnVsbCkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogbmFtZSxcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIGJ5cGFzczogdHJ1ZSxcbiAgICAgIGRlbGV0ZUJ5cGFzczogdHJ1ZVxuICAgIH07XG4gIH0gLy8gY2hlY2sgaWYgdmFsdWUgaXMgYSBmdW5jdGlvbiB1c2VkIGFzIGEgbWFwcGVyXG5cblxuICBpZiAoZm4odmFsdWUpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IG5hbWUsXG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICBzdHJWYWx1ZTogJ2ZuJyxcbiAgICAgIG1hcHBlZDogdHlwZXMuZm4sXG4gICAgICBieXBhc3M6IHByb3BJc0J5cGFzc1xuICAgIH07XG4gIH0gLy8gY2hlY2sgaWYgdmFsdWUgaXMgbWFwcGVkXG5cblxuICB2YXIgZGF0YSwgbWFwRGF0YTtcblxuICBpZiAoIXZhbHVlSXNTdHJpbmcgfHwgcHJvcElzRmxhdCB8fCB2YWx1ZS5sZW5ndGggPCA3IHx8IHZhbHVlWzFdICE9PSAnYScpIDsgZWxzZSBpZiAodmFsdWUubGVuZ3RoID49IDcgJiYgdmFsdWVbMF0gPT09ICdkJyAmJiAoZGF0YSA9IG5ldyBSZWdFeHAodHlwZXMuZGF0YS5yZWdleCkuZXhlYyh2YWx1ZSkpKSB7XG4gICAgaWYgKHByb3BJc0J5cGFzcykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gLy8gbWFwcGVycyBub3QgYWxsb3dlZCBpbiBieXBhc3NcblxuXG4gICAgdmFyIG1hcHBlZCA9IHR5cGVzLmRhdGE7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IG5hbWUsXG4gICAgICB2YWx1ZTogZGF0YSxcbiAgICAgIHN0clZhbHVlOiAnJyArIHZhbHVlLFxuICAgICAgbWFwcGVkOiBtYXBwZWQsXG4gICAgICBmaWVsZDogZGF0YVsxXSxcbiAgICAgIGJ5cGFzczogcHJvcElzQnlwYXNzXG4gICAgfTtcbiAgfSBlbHNlIGlmICh2YWx1ZS5sZW5ndGggPj0gMTAgJiYgdmFsdWVbMF0gPT09ICdtJyAmJiAobWFwRGF0YSA9IG5ldyBSZWdFeHAodHlwZXMubWFwRGF0YS5yZWdleCkuZXhlYyh2YWx1ZSkpKSB7XG4gICAgaWYgKHByb3BJc0J5cGFzcykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gLy8gbWFwcGVycyBub3QgYWxsb3dlZCBpbiBieXBhc3NcblxuXG4gICAgaWYgKHR5cGUubXVsdGlwbGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IC8vIGltcG9zc2libGUgdG8gbWFwIHRvIG51bVxuXG5cbiAgICB2YXIgX21hcHBlZCA9IHR5cGVzLm1hcERhdGE7IC8vIHdlIGNhbiBtYXAgb25seSBpZiB0aGUgdHlwZSBpcyBhIGNvbG91ciBvciBhIG51bWJlclxuXG4gICAgaWYgKCEodHlwZS5jb2xvciB8fCB0eXBlLm51bWJlcikpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgdmFsdWVNaW4gPSB0aGlzLnBhcnNlKG5hbWUsIG1hcERhdGFbNF0pOyAvLyBwYXJzZSB0byB2YWxpZGF0ZVxuXG4gICAgaWYgKCF2YWx1ZU1pbiB8fCB2YWx1ZU1pbi5tYXBwZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IC8vIGNhbid0IGJlIGludmFsaWQgb3IgbWFwcGVkXG5cblxuICAgIHZhciB2YWx1ZU1heCA9IHRoaXMucGFyc2UobmFtZSwgbWFwRGF0YVs1XSk7IC8vIHBhcnNlIHRvIHZhbGlkYXRlXG5cbiAgICBpZiAoIXZhbHVlTWF4IHx8IHZhbHVlTWF4Lm1hcHBlZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gLy8gY2FuJ3QgYmUgaW52YWxpZCBvciBtYXBwZWRcbiAgICAvLyBjaGVjayBpZiB2YWx1ZU1pbiBhbmQgdmFsdWVNYXggYXJlIHRoZSBzYW1lXG5cblxuICAgIGlmICh2YWx1ZU1pbi5wZlZhbHVlID09PSB2YWx1ZU1heC5wZlZhbHVlIHx8IHZhbHVlTWluLnN0clZhbHVlID09PSB2YWx1ZU1heC5zdHJWYWx1ZSkge1xuICAgICAgd2FybignYCcgKyBuYW1lICsgJzogJyArIHZhbHVlICsgJ2AgaXMgbm90IGEgdmFsaWQgbWFwcGVyIGJlY2F1c2UgdGhlIG91dHB1dCByYW5nZSBpcyB6ZXJvOyBjb252ZXJ0aW5nIHRvIGAnICsgbmFtZSArICc6ICcgKyB2YWx1ZU1pbi5zdHJWYWx1ZSArICdgJyk7XG4gICAgICByZXR1cm4gdGhpcy5wYXJzZShuYW1lLCB2YWx1ZU1pbi5zdHJWYWx1ZSk7IC8vIGNhbid0IG1ha2UgbXVjaCBvZiBhIG1hcHBlciB3aXRob3V0IGEgcmFuZ2VcbiAgICB9IGVsc2UgaWYgKHR5cGUuY29sb3IpIHtcbiAgICAgIHZhciBjMSA9IHZhbHVlTWluLnZhbHVlO1xuICAgICAgdmFyIGMyID0gdmFsdWVNYXgudmFsdWU7XG4gICAgICB2YXIgc2FtZSA9IGMxWzBdID09PSBjMlswXSAvLyByZWRcbiAgICAgICYmIGMxWzFdID09PSBjMlsxXSAvLyBncmVlblxuICAgICAgJiYgYzFbMl0gPT09IGMyWzJdIC8vIGJsdWVcbiAgICAgICYmICggLy8gb3B0aW9uYWwgYWxwaGFcbiAgICAgIGMxWzNdID09PSBjMlszXSAvLyBzYW1lIGFscGhhIG91dHJpZ2h0XG4gICAgICB8fCAoYzFbM10gPT0gbnVsbCB8fCBjMVszXSA9PT0gMSkgJiYgKCAvLyBmdWxsIG9wYWNpdHkgZm9yIGNvbG91ciAxP1xuICAgICAgYzJbM10gPT0gbnVsbCB8fCBjMlszXSA9PT0gMSkgLy8gZnVsbCBvcGFjaXR5IGZvciBjb2xvdXIgMj9cbiAgICAgICk7XG5cbiAgICAgIGlmIChzYW1lKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0gLy8gY2FuJ3QgbWFrZSBhIG1hcHBlciB3aXRob3V0IGEgcmFuZ2VcblxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgdmFsdWU6IG1hcERhdGEsXG4gICAgICBzdHJWYWx1ZTogJycgKyB2YWx1ZSxcbiAgICAgIG1hcHBlZDogX21hcHBlZCxcbiAgICAgIGZpZWxkOiBtYXBEYXRhWzFdLFxuICAgICAgZmllbGRNaW46IHBhcnNlRmxvYXQobWFwRGF0YVsyXSksXG4gICAgICAvLyBtaW4gJiBtYXggYXJlIG51bWVyaWNcbiAgICAgIGZpZWxkTWF4OiBwYXJzZUZsb2F0KG1hcERhdGFbM10pLFxuICAgICAgdmFsdWVNaW46IHZhbHVlTWluLnZhbHVlLFxuICAgICAgdmFsdWVNYXg6IHZhbHVlTWF4LnZhbHVlLFxuICAgICAgYnlwYXNzOiBwcm9wSXNCeXBhc3NcbiAgICB9O1xuICB9XG5cbiAgaWYgKHR5cGUubXVsdGlwbGUgJiYgcHJvcElzRmxhdCAhPT0gJ211bHRpcGxlJykge1xuICAgIHZhciB2YWxzO1xuXG4gICAgaWYgKHZhbHVlSXNTdHJpbmcpIHtcbiAgICAgIHZhbHMgPSB2YWx1ZS5zcGxpdCgvXFxzKy8pO1xuICAgIH0gZWxzZSBpZiAoYXJyYXkodmFsdWUpKSB7XG4gICAgICB2YWxzID0gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHMgPSBbdmFsdWVdO1xuICAgIH1cblxuICAgIGlmICh0eXBlLmV2ZW5NdWx0aXBsZSAmJiB2YWxzLmxlbmd0aCAlIDIgIT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciB2YWxBcnIgPSBbXTtcbiAgICB2YXIgdW5pdHNBcnIgPSBbXTtcbiAgICB2YXIgcGZWYWxBcnIgPSBbXTtcbiAgICB2YXIgc3RyVmFsID0gJyc7XG4gICAgdmFyIGhhc0VudW0gPSBmYWxzZTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHAgPSBzZWxmLnBhcnNlKG5hbWUsIHZhbHNbaV0sIHByb3BJc0J5cGFzcywgJ211bHRpcGxlJyk7XG4gICAgICBoYXNFbnVtID0gaGFzRW51bSB8fCBzdHJpbmcocC52YWx1ZSk7XG4gICAgICB2YWxBcnIucHVzaChwLnZhbHVlKTtcbiAgICAgIHBmVmFsQXJyLnB1c2gocC5wZlZhbHVlICE9IG51bGwgPyBwLnBmVmFsdWUgOiBwLnZhbHVlKTtcbiAgICAgIHVuaXRzQXJyLnB1c2gocC51bml0cyk7XG4gICAgICBzdHJWYWwgKz0gKGkgPiAwID8gJyAnIDogJycpICsgcC5zdHJWYWx1ZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZS52YWxpZGF0ZSAmJiAhdHlwZS52YWxpZGF0ZSh2YWxBcnIsIHVuaXRzQXJyKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHR5cGUuc2luZ2xlRW51bSAmJiBoYXNFbnVtKSB7XG4gICAgICBpZiAodmFsQXJyLmxlbmd0aCA9PT0gMSAmJiBzdHJpbmcodmFsQXJyWzBdKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgdmFsdWU6IHZhbEFyclswXSxcbiAgICAgICAgICBzdHJWYWx1ZTogdmFsQXJyWzBdLFxuICAgICAgICAgIGJ5cGFzczogcHJvcElzQnlwYXNzXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogbmFtZSxcbiAgICAgIHZhbHVlOiB2YWxBcnIsXG4gICAgICBwZlZhbHVlOiBwZlZhbEFycixcbiAgICAgIHN0clZhbHVlOiBzdHJWYWwsXG4gICAgICBieXBhc3M6IHByb3BJc0J5cGFzcyxcbiAgICAgIHVuaXRzOiB1bml0c0FyclxuICAgIH07XG4gIH0gLy8gc2V2ZXJhbCB0eXBlcyBhbHNvIGFsbG93IGVudW1zXG5cblxuICB2YXIgY2hlY2tFbnVtcyA9IGZ1bmN0aW9uIGNoZWNrRW51bXMoKSB7XG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IHR5cGUuZW51bXMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICB2YXIgZW4gPSB0eXBlLmVudW1zW19pXTtcblxuICAgICAgaWYgKGVuID09PSB2YWx1ZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICAgIHN0clZhbHVlOiAnJyArIHZhbHVlLFxuICAgICAgICAgIGJ5cGFzczogcHJvcElzQnlwYXNzXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH07IC8vIGNoZWNrIHRoZSB0eXBlIGFuZCByZXR1cm4gdGhlIGFwcHJvcHJpYXRlIG9iamVjdFxuXG5cbiAgaWYgKHR5cGUubnVtYmVyKSB7XG4gICAgdmFyIHVuaXRzO1xuICAgIHZhciBpbXBsaWNpdFVuaXRzID0gJ3B4JzsgLy8gbm90IHNldCA9PiBweFxuXG4gICAgaWYgKHR5cGUudW5pdHMpIHtcbiAgICAgIC8vIHVzZSBzcGVjaWZpZWQgdW5pdHMgaWYgc2V0XG4gICAgICB1bml0cyA9IHR5cGUudW5pdHM7XG4gICAgfVxuXG4gICAgaWYgKHR5cGUuaW1wbGljaXRVbml0cykge1xuICAgICAgaW1wbGljaXRVbml0cyA9IHR5cGUuaW1wbGljaXRVbml0cztcbiAgICB9XG5cbiAgICBpZiAoIXR5cGUudW5pdGxlc3MpIHtcbiAgICAgIGlmICh2YWx1ZUlzU3RyaW5nKSB7XG4gICAgICAgIHZhciB1bml0c1JlZ2V4ID0gJ3B4fGVtJyArICh0eXBlLmFsbG93UGVyY2VudCA/ICd8XFxcXCUnIDogJycpO1xuXG4gICAgICAgIGlmICh1bml0cykge1xuICAgICAgICAgIHVuaXRzUmVnZXggPSB1bml0cztcbiAgICAgICAgfSAvLyBvbmx5IGFsbG93IGV4cGxpY2l0IHVuaXRzIGlmIHNvIHNldFxuXG5cbiAgICAgICAgdmFyIG1hdGNoID0gdmFsdWUubWF0Y2goJ14oJyArIG51bWJlciQxICsgJykoJyArIHVuaXRzUmVnZXggKyAnKT8nICsgJyQnKTtcblxuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICB2YWx1ZSA9IG1hdGNoWzFdO1xuICAgICAgICAgIHVuaXRzID0gbWF0Y2hbMl0gfHwgaW1wbGljaXRVbml0cztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICghdW5pdHMgfHwgdHlwZS5pbXBsaWNpdFVuaXRzKSB7XG4gICAgICAgIHVuaXRzID0gaW1wbGljaXRVbml0czsgLy8gaW1wbGljaXRseSBweCBpZiB1bnNwZWNpZmllZFxuICAgICAgfVxuICAgIH1cblxuICAgIHZhbHVlID0gcGFyc2VGbG9hdCh2YWx1ZSk7IC8vIGlmIG5vdCBhIG51bWJlciBhbmQgZW51bXMgbm90IGFsbG93ZWQsIHRoZW4gdGhlIHZhbHVlIGlzIGludmFsaWRcblxuICAgIGlmIChpc05hTih2YWx1ZSkgJiYgdHlwZS5lbnVtcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9IC8vIGNoZWNrIGlmIHRoaXMgbnVtYmVyIHR5cGUgYWxzbyBhY2NlcHRzIHNwZWNpYWwga2V5d29yZHMgaW4gcGxhY2Ugb2YgbnVtYmVyc1xuICAgIC8vIChpLmUuIGBsZWZ0YCwgYGF1dG9gLCBldGMpXG5cblxuICAgIGlmIChpc05hTih2YWx1ZSkgJiYgdHlwZS5lbnVtcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YWx1ZSA9IHBhc3NlZFZhbHVlO1xuICAgICAgcmV0dXJuIGNoZWNrRW51bXMoKTtcbiAgICB9IC8vIGNoZWNrIGlmIHZhbHVlIG11c3QgYmUgYW4gaW50ZWdlclxuXG5cbiAgICBpZiAodHlwZS5pbnRlZ2VyICYmICFpbnRlZ2VyKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSAvLyBjaGVjayB2YWx1ZSBpcyB3aXRoaW4gcmFuZ2VcblxuXG4gICAgaWYgKHR5cGUubWluICE9PSB1bmRlZmluZWQgJiYgKHZhbHVlIDwgdHlwZS5taW4gfHwgdHlwZS5zdHJpY3RNaW4gJiYgdmFsdWUgPT09IHR5cGUubWluKSB8fCB0eXBlLm1heCAhPT0gdW5kZWZpbmVkICYmICh2YWx1ZSA+IHR5cGUubWF4IHx8IHR5cGUuc3RyaWN0TWF4ICYmIHZhbHVlID09PSB0eXBlLm1heCkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciByZXQgPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgc3RyVmFsdWU6ICcnICsgdmFsdWUgKyAodW5pdHMgPyB1bml0cyA6ICcnKSxcbiAgICAgIHVuaXRzOiB1bml0cyxcbiAgICAgIGJ5cGFzczogcHJvcElzQnlwYXNzXG4gICAgfTsgLy8gbm9ybWFsaXNlIHZhbHVlIGluIHBpeGVsc1xuXG4gICAgaWYgKHR5cGUudW5pdGxlc3MgfHwgdW5pdHMgIT09ICdweCcgJiYgdW5pdHMgIT09ICdlbScpIHtcbiAgICAgIHJldC5wZlZhbHVlID0gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldC5wZlZhbHVlID0gdW5pdHMgPT09ICdweCcgfHwgIXVuaXRzID8gdmFsdWUgOiB0aGlzLmdldEVtU2l6ZUluUGl4ZWxzKCkgKiB2YWx1ZTtcbiAgICB9IC8vIG5vcm1hbGlzZSB2YWx1ZSBpbiBtc1xuXG5cbiAgICBpZiAodW5pdHMgPT09ICdtcycgfHwgdW5pdHMgPT09ICdzJykge1xuICAgICAgcmV0LnBmVmFsdWUgPSB1bml0cyA9PT0gJ21zJyA/IHZhbHVlIDogMTAwMCAqIHZhbHVlO1xuICAgIH0gLy8gbm9ybWFsaXNlIHZhbHVlIGluIHJhZFxuXG5cbiAgICBpZiAodW5pdHMgPT09ICdkZWcnIHx8IHVuaXRzID09PSAncmFkJykge1xuICAgICAgcmV0LnBmVmFsdWUgPSB1bml0cyA9PT0gJ3JhZCcgPyB2YWx1ZSA6IGRlZzJyYWQodmFsdWUpO1xuICAgIH0gLy8gbm9ybWFsaXplIHZhbHVlIGluICVcblxuXG4gICAgaWYgKHVuaXRzID09PSAnJScpIHtcbiAgICAgIHJldC5wZlZhbHVlID0gdmFsdWUgLyAxMDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfSBlbHNlIGlmICh0eXBlLnByb3BMaXN0KSB7XG4gICAgdmFyIHByb3BzID0gW107XG4gICAgdmFyIHByb3BzU3RyID0gJycgKyB2YWx1ZTtcblxuICAgIGlmIChwcm9wc1N0ciA9PT0gJ25vbmUnKSA7IGVsc2Uge1xuICAgICAgLy8gZ28gb3ZlciBlYWNoIHByb3BcbiAgICAgIHZhciBwcm9wc1NwbGl0ID0gcHJvcHNTdHIuc3BsaXQoL1xccyosXFxzKnxcXHMrLyk7XG5cbiAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IHByb3BzU3BsaXQubGVuZ3RoOyBfaTIrKykge1xuICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wc1NwbGl0W19pMl0udHJpbSgpO1xuXG4gICAgICAgIGlmIChzZWxmLnByb3BlcnRpZXNbcHJvcE5hbWVdKSB7XG4gICAgICAgICAgcHJvcHMucHVzaChwcm9wTmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgd2FybignYCcgKyBwcm9wTmFtZSArICdgIGlzIG5vdCBhIHZhbGlkIHByb3BlcnR5IG5hbWUnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAocHJvcHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgdmFsdWU6IHByb3BzLFxuICAgICAgc3RyVmFsdWU6IHByb3BzLmxlbmd0aCA9PT0gMCA/ICdub25lJyA6IHByb3BzLmpvaW4oJyAnKSxcbiAgICAgIGJ5cGFzczogcHJvcElzQnlwYXNzXG4gICAgfTtcbiAgfSBlbHNlIGlmICh0eXBlLmNvbG9yKSB7XG4gICAgdmFyIHR1cGxlID0gY29sb3IydHVwbGUodmFsdWUpO1xuXG4gICAgaWYgKCF0dXBsZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IG5hbWUsXG4gICAgICB2YWx1ZTogdHVwbGUsXG4gICAgICBwZlZhbHVlOiB0dXBsZSxcbiAgICAgIHN0clZhbHVlOiAncmdiKCcgKyB0dXBsZVswXSArICcsJyArIHR1cGxlWzFdICsgJywnICsgdHVwbGVbMl0gKyAnKScsXG4gICAgICAvLyBuLmIuIG5vIHNwYWNlcyBiL2Mgb2YgbXVsdGlwbGUgc3VwcG9ydFxuICAgICAgYnlwYXNzOiBwcm9wSXNCeXBhc3NcbiAgICB9O1xuICB9IGVsc2UgaWYgKHR5cGUucmVnZXggfHwgdHlwZS5yZWdleGVzKSB7XG4gICAgLy8gZmlyc3QgY2hlY2sgZW51bXNcbiAgICBpZiAodHlwZS5lbnVtcykge1xuICAgICAgdmFyIGVudW1Qcm9wID0gY2hlY2tFbnVtcygpO1xuXG4gICAgICBpZiAoZW51bVByb3ApIHtcbiAgICAgICAgcmV0dXJuIGVudW1Qcm9wO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciByZWdleGVzID0gdHlwZS5yZWdleGVzID8gdHlwZS5yZWdleGVzIDogW3R5cGUucmVnZXhdO1xuXG4gICAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgcmVnZXhlcy5sZW5ndGg7IF9pMysrKSB7XG4gICAgICB2YXIgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4ZXNbX2kzXSk7IC8vIG1ha2UgYSByZWdleCBmcm9tIHRoZSB0eXBlIHN0cmluZ1xuXG4gICAgICB2YXIgbSA9IHJlZ2V4LmV4ZWModmFsdWUpO1xuXG4gICAgICBpZiAobSkge1xuICAgICAgICAvLyByZWdleCBtYXRjaGVzXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICB2YWx1ZTogdHlwZS5zaW5nbGVSZWdleE1hdGNoVmFsdWUgPyBtWzFdIDogbSxcbiAgICAgICAgICBzdHJWYWx1ZTogJycgKyB2YWx1ZSxcbiAgICAgICAgICBieXBhc3M6IHByb3BJc0J5cGFzc1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsOyAvLyBkaWRuJ3QgbWF0Y2ggYW55XG4gIH0gZWxzZSBpZiAodHlwZS5zdHJpbmcpIHtcbiAgICAvLyBqdXN0IHJldHVyblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgdmFsdWU6ICcnICsgdmFsdWUsXG4gICAgICBzdHJWYWx1ZTogJycgKyB2YWx1ZSxcbiAgICAgIGJ5cGFzczogcHJvcElzQnlwYXNzXG4gICAgfTtcbiAgfSBlbHNlIGlmICh0eXBlLmVudW1zKSB7XG4gICAgLy8gY2hlY2sgZW51bXMgbGFzdCBiZWNhdXNlIGl0J3MgYSBjb21ibyB0eXBlIGluIG90aGVyc1xuICAgIHJldHVybiBjaGVja0VudW1zKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG51bGw7IC8vIG5vdCBhIHR5cGUgd2UgY2FuIGhhbmRsZVxuICB9XG59O1xuXG52YXIgU3R5bGUgPSBmdW5jdGlvbiBTdHlsZShjeSkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU3R5bGUpKSB7XG4gICAgcmV0dXJuIG5ldyBTdHlsZShjeSk7XG4gIH1cblxuICBpZiAoIWNvcmUoY3kpKSB7XG4gICAgZXJyb3IoJ0Egc3R5bGUgbXVzdCBoYXZlIGEgY29yZSByZWZlcmVuY2UnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICB0aGlzLl9wcml2YXRlID0ge1xuICAgIGN5OiBjeSxcbiAgICBjb3JlU3R5bGU6IHt9XG4gIH07XG4gIHRoaXMubGVuZ3RoID0gMDtcbiAgdGhpcy5yZXNldFRvRGVmYXVsdCgpO1xufTtcblxudmFyIHN0eWZuJDggPSBTdHlsZS5wcm90b3R5cGU7XG5cbnN0eWZuJDguaW5zdGFuY2VTdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiAnc3R5bGUnO1xufTsgLy8gcmVtb3ZlIGFsbCBjb250ZXh0c1xuXG5cbnN0eWZuJDguY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgIHRoaXNbaV0gPSB1bmRlZmluZWQ7XG4gIH1cblxuICB0aGlzLmxlbmd0aCA9IDA7XG4gIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG4gIF9wLm5ld1N0eWxlID0gdHJ1ZTtcbiAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG59O1xuXG5zdHlmbiQ4LnJlc2V0VG9EZWZhdWx0ID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmNsZWFyKCk7XG4gIHRoaXMuYWRkRGVmYXVsdFN0eWxlc2hlZXQoKTtcbiAgcmV0dXJuIHRoaXM7XG59OyAvLyBidWlsZHMgYSBzdHlsZSBvYmplY3QgZm9yIHRoZSAnY29yZScgc2VsZWN0b3JcblxuXG5zdHlmbiQ4LmNvcmUgPSBmdW5jdGlvbiAocHJvcE5hbWUpIHtcbiAgcmV0dXJuIHRoaXMuX3ByaXZhdGUuY29yZVN0eWxlW3Byb3BOYW1lXSB8fCB0aGlzLmdldERlZmF1bHRQcm9wZXJ0eShwcm9wTmFtZSk7XG59OyAvLyBjcmVhdGUgYSBuZXcgY29udGV4dCBmcm9tIHRoZSBzcGVjaWZpZWQgc2VsZWN0b3Igc3RyaW5nIGFuZCBzd2l0Y2ggdG8gdGhhdCBjb250ZXh0XG5cblxuc3R5Zm4kOC5zZWxlY3RvciA9IGZ1bmN0aW9uIChzZWxlY3RvclN0cikge1xuICAvLyAnY29yZScgaXMgYSBzcGVjaWFsIGNhc2UgYW5kIGRvZXMgbm90IG5lZWQgYSBzZWxlY3RvclxuICB2YXIgc2VsZWN0b3IgPSBzZWxlY3RvclN0ciA9PT0gJ2NvcmUnID8gbnVsbCA6IG5ldyBTZWxlY3RvcihzZWxlY3RvclN0cik7XG4gIHZhciBpID0gdGhpcy5sZW5ndGgrKzsgLy8gbmV3IGNvbnRleHQgbWVhbnMgbmV3IGluZGV4XG5cbiAgdGhpc1tpXSA9IHtcbiAgICBzZWxlY3Rvcjogc2VsZWN0b3IsXG4gICAgcHJvcGVydGllczogW10sXG4gICAgbWFwcGVkUHJvcGVydGllczogW10sXG4gICAgaW5kZXg6IGlcbiAgfTtcbiAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG59OyAvLyBhZGQgb25lIG9yIG1hbnkgY3NzIHJ1bGVzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcblxuXG5zdHlmbiQ4LmNzcyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcblxuICBpZiAoYXJncy5sZW5ndGggPT09IDEpIHtcbiAgICB2YXIgbWFwID0gYXJnc1swXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5wcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcHJvcCA9IHNlbGYucHJvcGVydGllc1tpXTtcbiAgICAgIHZhciBtYXBWYWwgPSBtYXBbcHJvcC5uYW1lXTtcblxuICAgICAgaWYgKG1hcFZhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG1hcFZhbCA9IG1hcFtkYXNoMmNhbWVsKHByb3AubmFtZSldO1xuICAgICAgfVxuXG4gICAgICBpZiAobWFwVmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5jc3NSdWxlKHByb3AubmFtZSwgbWFwVmFsKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICB0aGlzLmNzc1J1bGUoYXJnc1swXSwgYXJnc1sxXSk7XG4gIH0gLy8gZG8gbm90aGluZyBpZiBhcmdzIGFyZSBpbnZhbGlkXG5cblxuICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbn07XG5cbnN0eWZuJDguc3R5bGUgPSBzdHlmbiQ4LmNzczsgLy8gYWRkIGEgc2luZ2xlIGNzcyBydWxlIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcblxuc3R5Zm4kOC5jc3NSdWxlID0gZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG4gIC8vIG5hbWUtdmFsdWUgcGFpclxuICB2YXIgcHJvcGVydHkgPSB0aGlzLnBhcnNlKG5hbWUsIHZhbHVlKTsgLy8gYWRkIHByb3BlcnR5IHRvIGN1cnJlbnQgY29udGV4dCBpZiB2YWxpZFxuXG4gIGlmIChwcm9wZXJ0eSkge1xuICAgIHZhciBpID0gdGhpcy5sZW5ndGggLSAxO1xuICAgIHRoaXNbaV0ucHJvcGVydGllcy5wdXNoKHByb3BlcnR5KTtcbiAgICB0aGlzW2ldLnByb3BlcnRpZXNbcHJvcGVydHkubmFtZV0gPSBwcm9wZXJ0eTsgLy8gYWxsb3cgYWNjZXNzIGJ5IG5hbWUgYXMgd2VsbFxuXG4gICAgaWYgKHByb3BlcnR5Lm5hbWUubWF0Y2goL3BpZS0oXFxkKyktYmFja2dyb3VuZC1zaXplLykgJiYgcHJvcGVydHkudmFsdWUpIHtcbiAgICAgIHRoaXMuX3ByaXZhdGUuaGFzUGllID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAocHJvcGVydHkubWFwcGVkKSB7XG4gICAgICB0aGlzW2ldLm1hcHBlZFByb3BlcnRpZXMucHVzaChwcm9wZXJ0eSk7XG4gICAgfSAvLyBhZGQgdG8gY29yZSBzdHlsZSBpZiBuZWNlc3NhcnlcblxuXG4gICAgdmFyIGN1cnJlbnRTZWxlY3RvcklzQ29yZSA9ICF0aGlzW2ldLnNlbGVjdG9yO1xuXG4gICAgaWYgKGN1cnJlbnRTZWxlY3RvcklzQ29yZSkge1xuICAgICAgdGhpcy5fcHJpdmF0ZS5jb3JlU3R5bGVbcHJvcGVydHkubmFtZV0gPSBwcm9wZXJ0eTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbn07XG5cbnN0eWZuJDguYXBwZW5kID0gZnVuY3Rpb24gKHN0eWxlKSB7XG4gIGlmIChzdHlsZXNoZWV0KHN0eWxlKSkge1xuICAgIHN0eWxlLmFwcGVuZFRvU3R5bGUodGhpcyk7XG4gIH0gZWxzZSBpZiAoYXJyYXkoc3R5bGUpKSB7XG4gICAgdGhpcy5hcHBlbmRGcm9tSnNvbihzdHlsZSk7XG4gIH0gZWxzZSBpZiAoc3RyaW5nKHN0eWxlKSkge1xuICAgIHRoaXMuYXBwZW5kRnJvbVN0cmluZyhzdHlsZSk7XG4gIH0gLy8geW91IHByb2JhYmx5IHdvdWxkbid0IHdhbnQgdG8gYXBwZW5kIGEgU3R5bGUsIHNpbmNlIHlvdSdkIGR1cGxpY2F0ZSB0aGUgZGVmYXVsdCBwYXJ0c1xuXG5cbiAgcmV0dXJuIHRoaXM7XG59OyAvLyBzdGF0aWMgZnVuY3Rpb25cblxuXG5TdHlsZS5mcm9tSnNvbiA9IGZ1bmN0aW9uIChjeSwganNvbikge1xuICB2YXIgc3R5bGUgPSBuZXcgU3R5bGUoY3kpO1xuICBzdHlsZS5mcm9tSnNvbihqc29uKTtcbiAgcmV0dXJuIHN0eWxlO1xufTtcblxuU3R5bGUuZnJvbVN0cmluZyA9IGZ1bmN0aW9uIChjeSwgc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgU3R5bGUoY3kpLmZyb21TdHJpbmcoc3RyaW5nKTtcbn07XG5cbltzdHlmbiwgc3R5Zm4kMSwgc3R5Zm4kMiwgc3R5Zm4kMywgc3R5Zm4kNCwgc3R5Zm4kNSwgc3R5Zm4kNiwgc3R5Zm4kN10uZm9yRWFjaChmdW5jdGlvbiAocHJvcHMpIHtcbiAgZXh0ZW5kKHN0eWZuJDgsIHByb3BzKTtcbn0pO1xuU3R5bGUudHlwZXMgPSBzdHlmbiQ4LnR5cGVzO1xuU3R5bGUucHJvcGVydGllcyA9IHN0eWZuJDgucHJvcGVydGllcztcblN0eWxlLnByb3BlcnR5R3JvdXBzID0gc3R5Zm4kOC5wcm9wZXJ0eUdyb3VwcztcblN0eWxlLnByb3BlcnR5R3JvdXBOYW1lcyA9IHN0eWZuJDgucHJvcGVydHlHcm91cE5hbWVzO1xuU3R5bGUucHJvcGVydHlHcm91cEtleXMgPSBzdHlmbiQ4LnByb3BlcnR5R3JvdXBLZXlzO1xuXG52YXIgY29yZWZuJDcgPSB7XG4gIHN0eWxlOiBmdW5jdGlvbiBzdHlsZShuZXdTdHlsZSkge1xuICAgIGlmIChuZXdTdHlsZSkge1xuICAgICAgdmFyIHMgPSB0aGlzLnNldFN0eWxlKG5ld1N0eWxlKTtcbiAgICAgIHMudXBkYXRlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUuc3R5bGU7XG4gIH0sXG4gIHNldFN0eWxlOiBmdW5jdGlvbiBzZXRTdHlsZShzdHlsZSkge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG5cbiAgICBpZiAoc3R5bGVzaGVldChzdHlsZSkpIHtcbiAgICAgIF9wLnN0eWxlID0gc3R5bGUuZ2VuZXJhdGVTdHlsZSh0aGlzKTtcbiAgICB9IGVsc2UgaWYgKGFycmF5KHN0eWxlKSkge1xuICAgICAgX3Auc3R5bGUgPSBTdHlsZS5mcm9tSnNvbih0aGlzLCBzdHlsZSk7XG4gICAgfSBlbHNlIGlmIChzdHJpbmcoc3R5bGUpKSB7XG4gICAgICBfcC5zdHlsZSA9IFN0eWxlLmZyb21TdHJpbmcodGhpcywgc3R5bGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBfcC5zdHlsZSA9IFN0eWxlKHRoaXMpO1xuICAgIH1cblxuICAgIHJldHVybiBfcC5zdHlsZTtcbiAgfVxufTtcblxudmFyIGRlZmF1bHRTZWxlY3Rpb25UeXBlID0gJ3NpbmdsZSc7XG52YXIgY29yZWZuJDggPSB7XG4gIGF1dG9sb2NrOiBmdW5jdGlvbiBhdXRvbG9jayhib29sKSB7XG4gICAgaWYgKGJvb2wgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fcHJpdmF0ZS5hdXRvbG9jayA9IGJvb2wgPyB0cnVlIDogZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLl9wcml2YXRlLmF1dG9sb2NrO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICBhdXRvdW5ncmFiaWZ5OiBmdW5jdGlvbiBhdXRvdW5ncmFiaWZ5KGJvb2wpIHtcbiAgICBpZiAoYm9vbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9wcml2YXRlLmF1dG91bmdyYWJpZnkgPSBib29sID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5hdXRvdW5ncmFiaWZ5O1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICBhdXRvdW5zZWxlY3RpZnk6IGZ1bmN0aW9uIGF1dG91bnNlbGVjdGlmeShib29sKSB7XG4gICAgaWYgKGJvb2wgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fcHJpdmF0ZS5hdXRvdW5zZWxlY3RpZnkgPSBib29sID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5hdXRvdW5zZWxlY3RpZnk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gIH0sXG4gIHNlbGVjdGlvblR5cGU6IGZ1bmN0aW9uIHNlbGVjdGlvblR5cGUoc2VsVHlwZSkge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG5cbiAgICBpZiAoX3Auc2VsZWN0aW9uVHlwZSA9PSBudWxsKSB7XG4gICAgICBfcC5zZWxlY3Rpb25UeXBlID0gZGVmYXVsdFNlbGVjdGlvblR5cGU7XG4gICAgfVxuXG4gICAgaWYgKHNlbFR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHNlbFR5cGUgPT09ICdhZGRpdGl2ZScgfHwgc2VsVHlwZSA9PT0gJ3NpbmdsZScpIHtcbiAgICAgICAgX3Auc2VsZWN0aW9uVHlwZSA9IHNlbFR5cGU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBfcC5zZWxlY3Rpb25UeXBlO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBwYW5uaW5nRW5hYmxlZDogZnVuY3Rpb24gcGFubmluZ0VuYWJsZWQoYm9vbCkge1xuICAgIGlmIChib29sICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX3ByaXZhdGUucGFubmluZ0VuYWJsZWQgPSBib29sID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5wYW5uaW5nRW5hYmxlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgdXNlclBhbm5pbmdFbmFibGVkOiBmdW5jdGlvbiB1c2VyUGFubmluZ0VuYWJsZWQoYm9vbCkge1xuICAgIGlmIChib29sICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX3ByaXZhdGUudXNlclBhbm5pbmdFbmFibGVkID0gYm9vbCA/IHRydWUgOiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUudXNlclBhbm5pbmdFbmFibGVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICB6b29taW5nRW5hYmxlZDogZnVuY3Rpb24gem9vbWluZ0VuYWJsZWQoYm9vbCkge1xuICAgIGlmIChib29sICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX3ByaXZhdGUuem9vbWluZ0VuYWJsZWQgPSBib29sID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS56b29taW5nRW5hYmxlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgdXNlclpvb21pbmdFbmFibGVkOiBmdW5jdGlvbiB1c2VyWm9vbWluZ0VuYWJsZWQoYm9vbCkge1xuICAgIGlmIChib29sICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX3ByaXZhdGUudXNlclpvb21pbmdFbmFibGVkID0gYm9vbCA/IHRydWUgOiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUudXNlclpvb21pbmdFbmFibGVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICBib3hTZWxlY3Rpb25FbmFibGVkOiBmdW5jdGlvbiBib3hTZWxlY3Rpb25FbmFibGVkKGJvb2wpIHtcbiAgICBpZiAoYm9vbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9wcml2YXRlLmJveFNlbGVjdGlvbkVuYWJsZWQgPSBib29sID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5ib3hTZWxlY3Rpb25FbmFibGVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICBwYW46IGZ1bmN0aW9uIHBhbigpIHtcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICB2YXIgcGFuID0gdGhpcy5fcHJpdmF0ZS5wYW47XG4gICAgdmFyIGRpbSwgdmFsLCBkaW1zLCB4LCB5O1xuXG4gICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICAvLyAucGFuKClcbiAgICAgICAgcmV0dXJuIHBhbjtcblxuICAgICAgY2FzZSAxOlxuICAgICAgICBpZiAoc3RyaW5nKGFyZ3NbMF0pKSB7XG4gICAgICAgICAgLy8gLnBhbigneCcpXG4gICAgICAgICAgZGltID0gYXJnc1swXTtcbiAgICAgICAgICByZXR1cm4gcGFuW2RpbV07XG4gICAgICAgIH0gZWxzZSBpZiAocGxhaW5PYmplY3QoYXJnc1swXSkpIHtcbiAgICAgICAgICAvLyAucGFuKHsgeDogMCwgeTogMTAwIH0pXG4gICAgICAgICAgaWYgKCF0aGlzLl9wcml2YXRlLnBhbm5pbmdFbmFibGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkaW1zID0gYXJnc1swXTtcbiAgICAgICAgICB4ID0gZGltcy54O1xuICAgICAgICAgIHkgPSBkaW1zLnk7XG5cbiAgICAgICAgICBpZiAobnVtYmVyKHgpKSB7XG4gICAgICAgICAgICBwYW4ueCA9IHg7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG51bWJlcih5KSkge1xuICAgICAgICAgICAgcGFuLnkgPSB5O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuZW1pdCgncGFuIHZpZXdwb3J0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAyOlxuICAgICAgICAvLyAucGFuKCd4JywgMTAwKVxuICAgICAgICBpZiAoIXRoaXMuX3ByaXZhdGUucGFubmluZ0VuYWJsZWQpIHtcbiAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGRpbSA9IGFyZ3NbMF07XG4gICAgICAgIHZhbCA9IGFyZ3NbMV07XG5cbiAgICAgICAgaWYgKChkaW0gPT09ICd4JyB8fCBkaW0gPT09ICd5JykgJiYgbnVtYmVyKHZhbCkpIHtcbiAgICAgICAgICBwYW5bZGltXSA9IHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZW1pdCgncGFuIHZpZXdwb3J0Jyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gaW52YWxpZFxuICAgIH1cblxuICAgIHRoaXMubm90aWZ5KCd2aWV3cG9ydCcpO1xuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICBwYW5CeTogZnVuY3Rpb24gcGFuQnkoYXJnMCwgYXJnMSkge1xuICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgIHZhciBwYW4gPSB0aGlzLl9wcml2YXRlLnBhbjtcbiAgICB2YXIgZGltLCB2YWwsIGRpbXMsIHgsIHk7XG5cbiAgICBpZiAoIXRoaXMuX3ByaXZhdGUucGFubmluZ0VuYWJsZWQpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgaWYgKHBsYWluT2JqZWN0KGFyZzApKSB7XG4gICAgICAgICAgLy8gLnBhbkJ5KHsgeDogMCwgeTogMTAwIH0pXG4gICAgICAgICAgZGltcyA9IGFyZ3NbMF07XG4gICAgICAgICAgeCA9IGRpbXMueDtcbiAgICAgICAgICB5ID0gZGltcy55O1xuXG4gICAgICAgICAgaWYgKG51bWJlcih4KSkge1xuICAgICAgICAgICAgcGFuLnggKz0geDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobnVtYmVyKHkpKSB7XG4gICAgICAgICAgICBwYW4ueSArPSB5O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuZW1pdCgncGFuIHZpZXdwb3J0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAyOlxuICAgICAgICAvLyAucGFuQnkoJ3gnLCAxMDApXG4gICAgICAgIGRpbSA9IGFyZzA7XG4gICAgICAgIHZhbCA9IGFyZzE7XG5cbiAgICAgICAgaWYgKChkaW0gPT09ICd4JyB8fCBkaW0gPT09ICd5JykgJiYgbnVtYmVyKHZhbCkpIHtcbiAgICAgICAgICBwYW5bZGltXSArPSB2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVtaXQoJ3BhbiB2aWV3cG9ydCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIGludmFsaWRcbiAgICB9XG5cbiAgICB0aGlzLm5vdGlmeSgndmlld3BvcnQnKTtcbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgZml0OiBmdW5jdGlvbiBmaXQoZWxlbWVudHMsIHBhZGRpbmcpIHtcbiAgICB2YXIgdmlld3BvcnRTdGF0ZSA9IHRoaXMuZ2V0Rml0Vmlld3BvcnQoZWxlbWVudHMsIHBhZGRpbmcpO1xuXG4gICAgaWYgKHZpZXdwb3J0U3RhdGUpIHtcbiAgICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG4gICAgICBfcC56b29tID0gdmlld3BvcnRTdGF0ZS56b29tO1xuICAgICAgX3AucGFuID0gdmlld3BvcnRTdGF0ZS5wYW47XG4gICAgICB0aGlzLmVtaXQoJ3BhbiB6b29tIHZpZXdwb3J0Jyk7XG4gICAgICB0aGlzLm5vdGlmeSgndmlld3BvcnQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgZ2V0Rml0Vmlld3BvcnQ6IGZ1bmN0aW9uIGdldEZpdFZpZXdwb3J0KGVsZW1lbnRzLCBwYWRkaW5nKSB7XG4gICAgaWYgKG51bWJlcihlbGVtZW50cykgJiYgcGFkZGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBlbGVtZW50cyBpcyBvcHRpb25hbFxuICAgICAgcGFkZGluZyA9IGVsZW1lbnRzO1xuICAgICAgZWxlbWVudHMgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl9wcml2YXRlLnBhbm5pbmdFbmFibGVkIHx8ICF0aGlzLl9wcml2YXRlLnpvb21pbmdFbmFibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGJiO1xuXG4gICAgaWYgKHN0cmluZyhlbGVtZW50cykpIHtcbiAgICAgIHZhciBzZWwgPSBlbGVtZW50cztcbiAgICAgIGVsZW1lbnRzID0gdGhpcy4kKHNlbCk7XG4gICAgfSBlbHNlIGlmIChib3VuZGluZ0JveChlbGVtZW50cykpIHtcbiAgICAgIC8vIGFzc3VtZSBiYlxuICAgICAgdmFyIGJiZSA9IGVsZW1lbnRzO1xuICAgICAgYmIgPSB7XG4gICAgICAgIHgxOiBiYmUueDEsXG4gICAgICAgIHkxOiBiYmUueTEsXG4gICAgICAgIHgyOiBiYmUueDIsXG4gICAgICAgIHkyOiBiYmUueTJcbiAgICAgIH07XG4gICAgICBiYi53ID0gYmIueDIgLSBiYi54MTtcbiAgICAgIGJiLmggPSBiYi55MiAtIGJiLnkxO1xuICAgIH0gZWxzZSBpZiAoIWVsZW1lbnRPckNvbGxlY3Rpb24oZWxlbWVudHMpKSB7XG4gICAgICBlbGVtZW50cyA9IHRoaXMubXV0YWJsZUVsZW1lbnRzKCk7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnRPckNvbGxlY3Rpb24oZWxlbWVudHMpICYmIGVsZW1lbnRzLmVtcHR5KCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9IC8vIGNhbid0IGZpdCB0byBub3RoaW5nXG5cblxuICAgIGJiID0gYmIgfHwgZWxlbWVudHMuYm91bmRpbmdCb3goKTtcbiAgICB2YXIgdyA9IHRoaXMud2lkdGgoKTtcbiAgICB2YXIgaCA9IHRoaXMuaGVpZ2h0KCk7XG4gICAgdmFyIHpvb207XG4gICAgcGFkZGluZyA9IG51bWJlcihwYWRkaW5nKSA/IHBhZGRpbmcgOiAwO1xuXG4gICAgaWYgKCFpc05hTih3KSAmJiAhaXNOYU4oaCkgJiYgdyA+IDAgJiYgaCA+IDAgJiYgIWlzTmFOKGJiLncpICYmICFpc05hTihiYi5oKSAmJiBiYi53ID4gMCAmJiBiYi5oID4gMCkge1xuICAgICAgem9vbSA9IE1hdGgubWluKCh3IC0gMiAqIHBhZGRpbmcpIC8gYmIudywgKGggLSAyICogcGFkZGluZykgLyBiYi5oKTsgLy8gY3JvcCB6b29tXG5cbiAgICAgIHpvb20gPSB6b29tID4gdGhpcy5fcHJpdmF0ZS5tYXhab29tID8gdGhpcy5fcHJpdmF0ZS5tYXhab29tIDogem9vbTtcbiAgICAgIHpvb20gPSB6b29tIDwgdGhpcy5fcHJpdmF0ZS5taW5ab29tID8gdGhpcy5fcHJpdmF0ZS5taW5ab29tIDogem9vbTtcbiAgICAgIHZhciBwYW4gPSB7XG4gICAgICAgIC8vIG5vdyBwYW4gdG8gbWlkZGxlXG4gICAgICAgIHg6ICh3IC0gem9vbSAqIChiYi54MSArIGJiLngyKSkgLyAyLFxuICAgICAgICB5OiAoaCAtIHpvb20gKiAoYmIueTEgKyBiYi55MikpIC8gMlxuICAgICAgfTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHpvb206IHpvb20sXG4gICAgICAgIHBhbjogcGFuXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfSxcbiAgem9vbVJhbmdlOiBmdW5jdGlvbiB6b29tUmFuZ2UobWluLCBtYXgpIHtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuXG4gICAgaWYgKG1heCA9PSBudWxsKSB7XG4gICAgICB2YXIgb3B0cyA9IG1pbjtcbiAgICAgIG1pbiA9IG9wdHMubWluO1xuICAgICAgbWF4ID0gb3B0cy5tYXg7XG4gICAgfVxuXG4gICAgaWYgKG51bWJlcihtaW4pICYmIG51bWJlcihtYXgpICYmIG1pbiA8PSBtYXgpIHtcbiAgICAgIF9wLm1pblpvb20gPSBtaW47XG4gICAgICBfcC5tYXhab29tID0gbWF4O1xuICAgIH0gZWxzZSBpZiAobnVtYmVyKG1pbikgJiYgbWF4ID09PSB1bmRlZmluZWQgJiYgbWluIDw9IF9wLm1heFpvb20pIHtcbiAgICAgIF9wLm1pblpvb20gPSBtaW47XG4gICAgfSBlbHNlIGlmIChudW1iZXIobWF4KSAmJiBtaW4gPT09IHVuZGVmaW5lZCAmJiBtYXggPj0gX3AubWluWm9vbSkge1xuICAgICAgX3AubWF4Wm9vbSA9IG1heDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgbWluWm9vbTogZnVuY3Rpb24gbWluWm9vbSh6b29tKSB7XG4gICAgaWYgKHpvb20gPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUubWluWm9vbTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuem9vbVJhbmdlKHtcbiAgICAgICAgbWluOiB6b29tXG4gICAgICB9KTtcbiAgICB9XG4gIH0sXG4gIG1heFpvb206IGZ1bmN0aW9uIG1heFpvb20oem9vbSkge1xuICAgIGlmICh6b29tID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9wcml2YXRlLm1heFpvb207XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLnpvb21SYW5nZSh7XG4gICAgICAgIG1heDogem9vbVxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuICBnZXRab29tZWRWaWV3cG9ydDogZnVuY3Rpb24gZ2V0Wm9vbWVkVmlld3BvcnQocGFyYW1zKSB7XG4gICAgdmFyIF9wID0gdGhpcy5fcHJpdmF0ZTtcbiAgICB2YXIgY3VycmVudFBhbiA9IF9wLnBhbjtcbiAgICB2YXIgY3VycmVudFpvb20gPSBfcC56b29tO1xuICAgIHZhciBwb3M7IC8vIGluIHJlbmRlcmVkIHB4XG5cbiAgICB2YXIgem9vbTtcbiAgICB2YXIgYmFpbCA9IGZhbHNlO1xuXG4gICAgaWYgKCFfcC56b29taW5nRW5hYmxlZCkge1xuICAgICAgLy8gem9vbWluZyBkaXNhYmxlZFxuICAgICAgYmFpbCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG51bWJlcihwYXJhbXMpKSB7XG4gICAgICAvLyB0aGVuIHNldCB0aGUgem9vbVxuICAgICAgem9vbSA9IHBhcmFtcztcbiAgICB9IGVsc2UgaWYgKHBsYWluT2JqZWN0KHBhcmFtcykpIHtcbiAgICAgIC8vIHRoZW4gem9vbSBhYm91dCBhIHBvaW50XG4gICAgICB6b29tID0gcGFyYW1zLmxldmVsO1xuXG4gICAgICBpZiAocGFyYW1zLnBvc2l0aW9uICE9IG51bGwpIHtcbiAgICAgICAgcG9zID0gbW9kZWxUb1JlbmRlcmVkUG9zaXRpb24ocGFyYW1zLnBvc2l0aW9uLCBjdXJyZW50Wm9vbSwgY3VycmVudFBhbik7XG4gICAgICB9IGVsc2UgaWYgKHBhcmFtcy5yZW5kZXJlZFBvc2l0aW9uICE9IG51bGwpIHtcbiAgICAgICAgcG9zID0gcGFyYW1zLnJlbmRlcmVkUG9zaXRpb247XG4gICAgICB9XG5cbiAgICAgIGlmIChwb3MgIT0gbnVsbCAmJiAhX3AucGFubmluZ0VuYWJsZWQpIHtcbiAgICAgICAgLy8gcGFubmluZyBkaXNhYmxlZFxuICAgICAgICBiYWlsID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9IC8vIGNyb3Agem9vbVxuXG5cbiAgICB6b29tID0gem9vbSA+IF9wLm1heFpvb20gPyBfcC5tYXhab29tIDogem9vbTtcbiAgICB6b29tID0gem9vbSA8IF9wLm1pblpvb20gPyBfcC5taW5ab29tIDogem9vbTsgLy8gY2FuJ3Qgem9vbSB3aXRoIGludmFsaWQgcGFyYW1zXG5cbiAgICBpZiAoYmFpbCB8fCAhbnVtYmVyKHpvb20pIHx8IHpvb20gPT09IGN1cnJlbnRab29tIHx8IHBvcyAhPSBudWxsICYmICghbnVtYmVyKHBvcy54KSB8fCAhbnVtYmVyKHBvcy55KSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmIChwb3MgIT0gbnVsbCkge1xuICAgICAgLy8gc2V0IHpvb20gYWJvdXQgcG9zaXRpb25cbiAgICAgIHZhciBwYW4xID0gY3VycmVudFBhbjtcbiAgICAgIHZhciB6b29tMSA9IGN1cnJlbnRab29tO1xuICAgICAgdmFyIHpvb20yID0gem9vbTtcbiAgICAgIHZhciBwYW4yID0ge1xuICAgICAgICB4OiAtem9vbTIgLyB6b29tMSAqIChwb3MueCAtIHBhbjEueCkgKyBwb3MueCxcbiAgICAgICAgeTogLXpvb20yIC8gem9vbTEgKiAocG9zLnkgLSBwYW4xLnkpICsgcG9zLnlcbiAgICAgIH07XG4gICAgICByZXR1cm4ge1xuICAgICAgICB6b29tZWQ6IHRydWUsXG4gICAgICAgIHBhbm5lZDogdHJ1ZSxcbiAgICAgICAgem9vbTogem9vbTIsXG4gICAgICAgIHBhbjogcGFuMlxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8ganVzdCBzZXQgdGhlIHpvb21cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHpvb21lZDogdHJ1ZSxcbiAgICAgICAgcGFubmVkOiBmYWxzZSxcbiAgICAgICAgem9vbTogem9vbSxcbiAgICAgICAgcGFuOiBjdXJyZW50UGFuXG4gICAgICB9O1xuICAgIH1cbiAgfSxcbiAgem9vbTogZnVuY3Rpb24gem9vbShwYXJhbXMpIHtcbiAgICBpZiAocGFyYW1zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIGdldFxuICAgICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUuem9vbTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gc2V0XG4gICAgICB2YXIgdnAgPSB0aGlzLmdldFpvb21lZFZpZXdwb3J0KHBhcmFtcyk7XG4gICAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuXG4gICAgICBpZiAodnAgPT0gbnVsbCB8fCAhdnAuem9vbWVkKSB7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICBfcC56b29tID0gdnAuem9vbTtcblxuICAgICAgaWYgKHZwLnBhbm5lZCkge1xuICAgICAgICBfcC5wYW4ueCA9IHZwLnBhbi54O1xuICAgICAgICBfcC5wYW4ueSA9IHZwLnBhbi55O1xuICAgICAgfVxuXG4gICAgICB0aGlzLmVtaXQoJ3pvb20nICsgKHZwLnBhbm5lZCA/ICcgcGFuJyA6ICcnKSArICcgdmlld3BvcnQnKTtcbiAgICAgIHRoaXMubm90aWZ5KCd2aWV3cG9ydCcpO1xuICAgICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gICAgfVxuICB9LFxuICB2aWV3cG9ydDogZnVuY3Rpb24gdmlld3BvcnQob3B0cykge1xuICAgIHZhciBfcCA9IHRoaXMuX3ByaXZhdGU7XG4gICAgdmFyIHpvb21EZWZkID0gdHJ1ZTtcbiAgICB2YXIgcGFuRGVmZCA9IHRydWU7XG4gICAgdmFyIGV2ZW50cyA9IFtdOyAvLyB0byB0cmlnZ2VyXG5cbiAgICB2YXIgem9vbUZhaWxlZCA9IGZhbHNlO1xuICAgIHZhciBwYW5GYWlsZWQgPSBmYWxzZTtcblxuICAgIGlmICghb3B0cykge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgaWYgKCFudW1iZXIob3B0cy56b29tKSkge1xuICAgICAgem9vbURlZmQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXBsYWluT2JqZWN0KG9wdHMucGFuKSkge1xuICAgICAgcGFuRGVmZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghem9vbURlZmQgJiYgIXBhbkRlZmQpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGlmICh6b29tRGVmZCkge1xuICAgICAgdmFyIHogPSBvcHRzLnpvb207XG5cbiAgICAgIGlmICh6IDwgX3AubWluWm9vbSB8fCB6ID4gX3AubWF4Wm9vbSB8fCAhX3Auem9vbWluZ0VuYWJsZWQpIHtcbiAgICAgICAgem9vbUZhaWxlZCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfcC56b29tID0gejtcbiAgICAgICAgZXZlbnRzLnB1c2goJ3pvb20nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocGFuRGVmZCAmJiAoIXpvb21GYWlsZWQgfHwgIW9wdHMuY2FuY2VsT25GYWlsZWRab29tKSAmJiBfcC5wYW5uaW5nRW5hYmxlZCkge1xuICAgICAgdmFyIHAgPSBvcHRzLnBhbjtcblxuICAgICAgaWYgKG51bWJlcihwLngpKSB7XG4gICAgICAgIF9wLnBhbi54ID0gcC54O1xuICAgICAgICBwYW5GYWlsZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKG51bWJlcihwLnkpKSB7XG4gICAgICAgIF9wLnBhbi55ID0gcC55O1xuICAgICAgICBwYW5GYWlsZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFwYW5GYWlsZWQpIHtcbiAgICAgICAgZXZlbnRzLnB1c2goJ3BhbicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChldmVudHMubGVuZ3RoID4gMCkge1xuICAgICAgZXZlbnRzLnB1c2goJ3ZpZXdwb3J0Jyk7XG4gICAgICB0aGlzLmVtaXQoZXZlbnRzLmpvaW4oJyAnKSk7XG4gICAgICB0aGlzLm5vdGlmeSgndmlld3BvcnQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgY2VudGVyOiBmdW5jdGlvbiBjZW50ZXIoZWxlbWVudHMpIHtcbiAgICB2YXIgcGFuID0gdGhpcy5nZXRDZW50ZXJQYW4oZWxlbWVudHMpO1xuXG4gICAgaWYgKHBhbikge1xuICAgICAgdGhpcy5fcHJpdmF0ZS5wYW4gPSBwYW47XG4gICAgICB0aGlzLmVtaXQoJ3BhbiB2aWV3cG9ydCcpO1xuICAgICAgdGhpcy5ub3RpZnkoJ3ZpZXdwb3J0Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG4gIH0sXG4gIGdldENlbnRlclBhbjogZnVuY3Rpb24gZ2V0Q2VudGVyUGFuKGVsZW1lbnRzLCB6b29tKSB7XG4gICAgaWYgKCF0aGlzLl9wcml2YXRlLnBhbm5pbmdFbmFibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHN0cmluZyhlbGVtZW50cykpIHtcbiAgICAgIHZhciBzZWxlY3RvciA9IGVsZW1lbnRzO1xuICAgICAgZWxlbWVudHMgPSB0aGlzLm11dGFibGVFbGVtZW50cygpLmZpbHRlcihzZWxlY3Rvcik7XG4gICAgfSBlbHNlIGlmICghZWxlbWVudE9yQ29sbGVjdGlvbihlbGVtZW50cykpIHtcbiAgICAgIGVsZW1lbnRzID0gdGhpcy5tdXRhYmxlRWxlbWVudHMoKTtcbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyBjYW4ndCBjZW50cmUgcGFuIHRvIG5vdGhpbmdcblxuXG4gICAgdmFyIGJiID0gZWxlbWVudHMuYm91bmRpbmdCb3goKTtcbiAgICB2YXIgdyA9IHRoaXMud2lkdGgoKTtcbiAgICB2YXIgaCA9IHRoaXMuaGVpZ2h0KCk7XG4gICAgem9vbSA9IHpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3ByaXZhdGUuem9vbSA6IHpvb207XG4gICAgdmFyIHBhbiA9IHtcbiAgICAgIC8vIG1pZGRsZVxuICAgICAgeDogKHcgLSB6b29tICogKGJiLngxICsgYmIueDIpKSAvIDIsXG4gICAgICB5OiAoaCAtIHpvb20gKiAoYmIueTEgKyBiYi55MikpIC8gMlxuICAgIH07XG4gICAgcmV0dXJuIHBhbjtcbiAgfSxcbiAgcmVzZXQ6IGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgIGlmICghdGhpcy5fcHJpdmF0ZS5wYW5uaW5nRW5hYmxlZCB8fCAhdGhpcy5fcHJpdmF0ZS56b29taW5nRW5hYmxlZCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdGhpcy52aWV3cG9ydCh7XG4gICAgICBwYW46IHtcbiAgICAgICAgeDogMCxcbiAgICAgICAgeTogMFxuICAgICAgfSxcbiAgICAgIHpvb206IDFcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgfSxcbiAgaW52YWxpZGF0ZVNpemU6IGZ1bmN0aW9uIGludmFsaWRhdGVTaXplKCkge1xuICAgIHRoaXMuX3ByaXZhdGUuc2l6ZUNhY2hlID0gbnVsbDtcbiAgfSxcbiAgc2l6ZTogZnVuY3Rpb24gc2l6ZSgpIHtcbiAgICB2YXIgX3AgPSB0aGlzLl9wcml2YXRlO1xuICAgIHZhciBjb250YWluZXIgPSBfcC5jb250YWluZXI7XG4gICAgcmV0dXJuIF9wLnNpemVDYWNoZSA9IF9wLnNpemVDYWNoZSB8fCAoY29udGFpbmVyID8gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHN0eWxlID0gd2luZG93JDEuZ2V0Q29tcHV0ZWRTdHlsZShjb250YWluZXIpO1xuXG4gICAgICB2YXIgdmFsID0gZnVuY3Rpb24gdmFsKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlRmxvYXQoc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZShuYW1lKSk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICB3aWR0aDogY29udGFpbmVyLmNsaWVudFdpZHRoIC0gdmFsKCdwYWRkaW5nLWxlZnQnKSAtIHZhbCgncGFkZGluZy1yaWdodCcpLFxuICAgICAgICBoZWlnaHQ6IGNvbnRhaW5lci5jbGllbnRIZWlnaHQgLSB2YWwoJ3BhZGRpbmctdG9wJykgLSB2YWwoJ3BhZGRpbmctYm90dG9tJylcbiAgICAgIH07XG4gICAgfSgpIDoge1xuICAgICAgLy8gZmFsbGJhY2sgaWYgbm8gY29udGFpbmVyIChub3QgMCBiL2MgY2FuIGJlIHVzZWQgZm9yIGRpdmlkaW5nIGV0YylcbiAgICAgIHdpZHRoOiAxLFxuICAgICAgaGVpZ2h0OiAxXG4gICAgfSk7XG4gIH0sXG4gIHdpZHRoOiBmdW5jdGlvbiB3aWR0aCgpIHtcbiAgICByZXR1cm4gdGhpcy5zaXplKCkud2lkdGg7XG4gIH0sXG4gIGhlaWdodDogZnVuY3Rpb24gaGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzLnNpemUoKS5oZWlnaHQ7XG4gIH0sXG4gIGV4dGVudDogZnVuY3Rpb24gZXh0ZW50KCkge1xuICAgIHZhciBwYW4gPSB0aGlzLl9wcml2YXRlLnBhbjtcbiAgICB2YXIgem9vbSA9IHRoaXMuX3ByaXZhdGUuem9vbTtcbiAgICB2YXIgcmIgPSB0aGlzLnJlbmRlcmVkRXh0ZW50KCk7XG4gICAgdmFyIGIgPSB7XG4gICAgICB4MTogKHJiLngxIC0gcGFuLngpIC8gem9vbSxcbiAgICAgIHgyOiAocmIueDIgLSBwYW4ueCkgLyB6b29tLFxuICAgICAgeTE6IChyYi55MSAtIHBhbi55KSAvIHpvb20sXG4gICAgICB5MjogKHJiLnkyIC0gcGFuLnkpIC8gem9vbVxuICAgIH07XG4gICAgYi53ID0gYi54MiAtIGIueDE7XG4gICAgYi5oID0gYi55MiAtIGIueTE7XG4gICAgcmV0dXJuIGI7XG4gIH0sXG4gIHJlbmRlcmVkRXh0ZW50OiBmdW5jdGlvbiByZW5kZXJlZEV4dGVudCgpIHtcbiAgICB2YXIgd2lkdGggPSB0aGlzLndpZHRoKCk7XG4gICAgdmFyIGhlaWdodCA9IHRoaXMuaGVpZ2h0KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHgxOiAwLFxuICAgICAgeTE6IDAsXG4gICAgICB4Mjogd2lkdGgsXG4gICAgICB5MjogaGVpZ2h0LFxuICAgICAgdzogd2lkdGgsXG4gICAgICBoOiBoZWlnaHRcbiAgICB9O1xuICB9XG59OyAvLyBhbGlhc2VzXG5cbmNvcmVmbiQ4LmNlbnRyZSA9IGNvcmVmbiQ4LmNlbnRlcjsgLy8gYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcblxuY29yZWZuJDguYXV0b2xvY2tOb2RlcyA9IGNvcmVmbiQ4LmF1dG9sb2NrO1xuY29yZWZuJDguYXV0b3VuZ3JhYmlmeU5vZGVzID0gY29yZWZuJDguYXV0b3VuZ3JhYmlmeTtcblxudmFyIGZuJDYgPSB7XG4gIGRhdGE6IGRlZmluZSQzLmRhdGEoe1xuICAgIGZpZWxkOiAnZGF0YScsXG4gICAgYmluZGluZ0V2ZW50OiAnZGF0YScsXG4gICAgYWxsb3dCaW5kaW5nOiB0cnVlLFxuICAgIGFsbG93U2V0dGluZzogdHJ1ZSxcbiAgICBzZXR0aW5nRXZlbnQ6ICdkYXRhJyxcbiAgICBzZXR0aW5nVHJpZ2dlcnNFdmVudDogdHJ1ZSxcbiAgICB0cmlnZ2VyRm5OYW1lOiAndHJpZ2dlcicsXG4gICAgYWxsb3dHZXR0aW5nOiB0cnVlXG4gIH0pLFxuICByZW1vdmVEYXRhOiBkZWZpbmUkMy5yZW1vdmVEYXRhKHtcbiAgICBmaWVsZDogJ2RhdGEnLFxuICAgIGV2ZW50OiAnZGF0YScsXG4gICAgdHJpZ2dlckZuTmFtZTogJ3RyaWdnZXInLFxuICAgIHRyaWdnZXJFdmVudDogdHJ1ZVxuICB9KSxcbiAgc2NyYXRjaDogZGVmaW5lJDMuZGF0YSh7XG4gICAgZmllbGQ6ICdzY3JhdGNoJyxcbiAgICBiaW5kaW5nRXZlbnQ6ICdzY3JhdGNoJyxcbiAgICBhbGxvd0JpbmRpbmc6IHRydWUsXG4gICAgYWxsb3dTZXR0aW5nOiB0cnVlLFxuICAgIHNldHRpbmdFdmVudDogJ3NjcmF0Y2gnLFxuICAgIHNldHRpbmdUcmlnZ2Vyc0V2ZW50OiB0cnVlLFxuICAgIHRyaWdnZXJGbk5hbWU6ICd0cmlnZ2VyJyxcbiAgICBhbGxvd0dldHRpbmc6IHRydWVcbiAgfSksXG4gIHJlbW92ZVNjcmF0Y2g6IGRlZmluZSQzLnJlbW92ZURhdGEoe1xuICAgIGZpZWxkOiAnc2NyYXRjaCcsXG4gICAgZXZlbnQ6ICdzY3JhdGNoJyxcbiAgICB0cmlnZ2VyRm5OYW1lOiAndHJpZ2dlcicsXG4gICAgdHJpZ2dlckV2ZW50OiB0cnVlXG4gIH0pXG59OyAvLyBhbGlhc2VzXG5cbmZuJDYuYXR0ciA9IGZuJDYuZGF0YTtcbmZuJDYucmVtb3ZlQXR0ciA9IGZuJDYucmVtb3ZlRGF0YTtcblxudmFyIENvcmUgPSBmdW5jdGlvbiBDb3JlKG9wdHMpIHtcbiAgdmFyIGN5ID0gdGhpcztcbiAgb3B0cyA9IGV4dGVuZCh7fSwgb3B0cyk7XG4gIHZhciBjb250YWluZXIgPSBvcHRzLmNvbnRhaW5lcjsgLy8gYWxsb3cgZm9yIHBhc3NpbmcgYSB3cmFwcGVkIGpxdWVyeSBvYmplY3RcbiAgLy8gZS5nLiBjeXRvc2NhcGUoeyBjb250YWluZXI6ICQoJyNjeScpIH0pXG5cbiAgaWYgKGNvbnRhaW5lciAmJiAhaHRtbEVsZW1lbnQoY29udGFpbmVyKSAmJiBodG1sRWxlbWVudChjb250YWluZXJbMF0pKSB7XG4gICAgY29udGFpbmVyID0gY29udGFpbmVyWzBdO1xuICB9XG5cbiAgdmFyIHJlZyA9IGNvbnRhaW5lciA/IGNvbnRhaW5lci5fY3lyZWcgOiBudWxsOyAvLyBlLmcuIGFscmVhZHkgcmVnaXN0ZXJlZCBzb21lIGluZm8gKGUuZy4gcmVhZGllcykgdmlhIGpxdWVyeVxuXG4gIHJlZyA9IHJlZyB8fCB7fTtcblxuICBpZiAocmVnICYmIHJlZy5jeSkge1xuICAgIHJlZy5jeS5kZXN0cm95KCk7XG4gICAgcmVnID0ge307IC8vIG9sZCBpbnN0YW5jZSA9PiByZXBsYWNlIHJlZyBjb21wbGV0ZWx5XG4gIH1cblxuICB2YXIgcmVhZGllcyA9IHJlZy5yZWFkaWVzID0gcmVnLnJlYWRpZXMgfHwgW107XG5cbiAgaWYgKGNvbnRhaW5lcikge1xuICAgIGNvbnRhaW5lci5fY3lyZWcgPSByZWc7XG4gIH0gLy8gbWFrZSBzdXJlIGNvbnRhaW5lciBhc3NvYydkIHJlZyBwb2ludHMgdG8gdGhpcyBjeVxuXG5cbiAgcmVnLmN5ID0gY3k7XG4gIHZhciBoZWFkID0gd2luZG93JDEgIT09IHVuZGVmaW5lZCAmJiBjb250YWluZXIgIT09IHVuZGVmaW5lZCAmJiAhb3B0cy5oZWFkbGVzcztcbiAgdmFyIG9wdGlvbnMgPSBvcHRzO1xuICBvcHRpb25zLmxheW91dCA9IGV4dGVuZCh7XG4gICAgbmFtZTogaGVhZCA/ICdncmlkJyA6ICdudWxsJ1xuICB9LCBvcHRpb25zLmxheW91dCk7XG4gIG9wdGlvbnMucmVuZGVyZXIgPSBleHRlbmQoe1xuICAgIG5hbWU6IGhlYWQgPyAnY2FudmFzJyA6ICdudWxsJ1xuICB9LCBvcHRpb25zLnJlbmRlcmVyKTtcblxuICB2YXIgZGVmVmFsID0gZnVuY3Rpb24gZGVmVmFsKGRlZiwgdmFsLCBhbHRWYWwpIHtcbiAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB2YWw7XG4gICAgfSBlbHNlIGlmIChhbHRWYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGFsdFZhbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRlZjtcbiAgICB9XG4gIH07XG5cbiAgdmFyIF9wID0gdGhpcy5fcHJpdmF0ZSA9IHtcbiAgICBjb250YWluZXI6IGNvbnRhaW5lcixcbiAgICAvLyBodG1sIGRvbSBlbGUgY29udGFpbmVyXG4gICAgcmVhZHk6IGZhbHNlLFxuICAgIC8vIHdoZXRoZXIgcmVhZHkgaGFzIGJlZW4gdHJpZ2dlcmVkXG4gICAgb3B0aW9uczogb3B0aW9ucyxcbiAgICAvLyBjYWNoZWQgb3B0aW9uc1xuICAgIGVsZW1lbnRzOiBuZXcgQ29sbGVjdGlvbih0aGlzKSxcbiAgICAvLyBlbGVtZW50cyBpbiB0aGUgZ3JhcGhcbiAgICBsaXN0ZW5lcnM6IFtdLFxuICAgIC8vIGxpc3Qgb2YgbGlzdGVuZXJzXG4gICAgYW5pRWxlczogbmV3IENvbGxlY3Rpb24odGhpcyksXG4gICAgLy8gZWxlbWVudHMgYmVpbmcgYW5pbWF0ZWRcbiAgICBkYXRhOiB7fSxcbiAgICAvLyBkYXRhIGZvciB0aGUgY29yZVxuICAgIHNjcmF0Y2g6IHt9LFxuICAgIC8vIHNjcmF0Y2ggb2JqZWN0IGZvciBjb3JlXG4gICAgbGF5b3V0OiBudWxsLFxuICAgIHJlbmRlcmVyOiBudWxsLFxuICAgIGRlc3Ryb3llZDogZmFsc2UsXG4gICAgLy8gd2hldGhlciBkZXN0cm95IHdhcyBjYWxsZWRcbiAgICBub3RpZmljYXRpb25zRW5hYmxlZDogdHJ1ZSxcbiAgICAvLyB3aGV0aGVyIG5vdGlmaWNhdGlvbnMgYXJlIHNlbnQgdG8gdGhlIHJlbmRlcmVyXG4gICAgbWluWm9vbTogMWUtNTAsXG4gICAgbWF4Wm9vbTogMWU1MCxcbiAgICB6b29taW5nRW5hYmxlZDogZGVmVmFsKHRydWUsIG9wdGlvbnMuem9vbWluZ0VuYWJsZWQpLFxuICAgIHVzZXJab29taW5nRW5hYmxlZDogZGVmVmFsKHRydWUsIG9wdGlvbnMudXNlclpvb21pbmdFbmFibGVkKSxcbiAgICBwYW5uaW5nRW5hYmxlZDogZGVmVmFsKHRydWUsIG9wdGlvbnMucGFubmluZ0VuYWJsZWQpLFxuICAgIHVzZXJQYW5uaW5nRW5hYmxlZDogZGVmVmFsKHRydWUsIG9wdGlvbnMudXNlclBhbm5pbmdFbmFibGVkKSxcbiAgICBib3hTZWxlY3Rpb25FbmFibGVkOiBkZWZWYWwodHJ1ZSwgb3B0aW9ucy5ib3hTZWxlY3Rpb25FbmFibGVkKSxcbiAgICBhdXRvbG9jazogZGVmVmFsKGZhbHNlLCBvcHRpb25zLmF1dG9sb2NrLCBvcHRpb25zLmF1dG9sb2NrTm9kZXMpLFxuICAgIGF1dG91bmdyYWJpZnk6IGRlZlZhbChmYWxzZSwgb3B0aW9ucy5hdXRvdW5ncmFiaWZ5LCBvcHRpb25zLmF1dG91bmdyYWJpZnlOb2RlcyksXG4gICAgYXV0b3Vuc2VsZWN0aWZ5OiBkZWZWYWwoZmFsc2UsIG9wdGlvbnMuYXV0b3Vuc2VsZWN0aWZ5KSxcbiAgICBzdHlsZUVuYWJsZWQ6IG9wdGlvbnMuc3R5bGVFbmFibGVkID09PSB1bmRlZmluZWQgPyBoZWFkIDogb3B0aW9ucy5zdHlsZUVuYWJsZWQsXG4gICAgem9vbTogbnVtYmVyKG9wdGlvbnMuem9vbSkgPyBvcHRpb25zLnpvb20gOiAxLFxuICAgIHBhbjoge1xuICAgICAgeDogcGxhaW5PYmplY3Qob3B0aW9ucy5wYW4pICYmIG51bWJlcihvcHRpb25zLnBhbi54KSA/IG9wdGlvbnMucGFuLnggOiAwLFxuICAgICAgeTogcGxhaW5PYmplY3Qob3B0aW9ucy5wYW4pICYmIG51bWJlcihvcHRpb25zLnBhbi55KSA/IG9wdGlvbnMucGFuLnkgOiAwXG4gICAgfSxcbiAgICBhbmltYXRpb246IHtcbiAgICAgIC8vIG9iamVjdCBmb3IgY3VycmVudGx5LXJ1bm5pbmcgYW5pbWF0aW9uc1xuICAgICAgY3VycmVudDogW10sXG4gICAgICBxdWV1ZTogW11cbiAgICB9LFxuICAgIGhhc0NvbXBvdW5kTm9kZXM6IGZhbHNlXG4gIH07XG5cbiAgdGhpcy5jcmVhdGVFbWl0dGVyKCk7IC8vIHNldCBzZWxlY3Rpb24gdHlwZVxuXG4gIHRoaXMuc2VsZWN0aW9uVHlwZShvcHRpb25zLnNlbGVjdGlvblR5cGUpOyAvLyBpbml0IHpvb20gYm91bmRzXG5cbiAgdGhpcy56b29tUmFuZ2Uoe1xuICAgIG1pbjogb3B0aW9ucy5taW5ab29tLFxuICAgIG1heDogb3B0aW9ucy5tYXhab29tXG4gIH0pO1xuXG4gIHZhciBsb2FkRXh0RGF0YSA9IGZ1bmN0aW9uIGxvYWRFeHREYXRhKGV4dERhdGEsIG5leHQpIHtcbiAgICB2YXIgYW55SXNQcm9taXNlID0gZXh0RGF0YS5zb21lKHByb21pc2UpO1xuXG4gICAgaWYgKGFueUlzUHJvbWlzZSkge1xuICAgICAgcmV0dXJuIFByb21pc2UkMS5hbGwoZXh0RGF0YSkudGhlbihuZXh0KTsgLy8gbG9hZCBhbGwgZGF0YSBhc3luY2hyb25vdXNseSwgdGhlbiBleGVjIHJlc3Qgb2YgaW5pdFxuICAgIH0gZWxzZSB7XG4gICAgICBuZXh0KGV4dERhdGEpOyAvLyBleGVjIHN5bmNocm9ub3VzbHkgZm9yIGNvbnZlbmllbmNlXG4gICAgfVxuICB9OyAvLyBzdGFydCB3aXRoIHRoZSBkZWZhdWx0IHN0eWxlc2hlZXQgc28gd2UgaGF2ZSBzb21ldGhpbmcgYmVmb3JlIGxvYWRpbmcgYW4gZXh0ZXJuYWwgc3R5bGVzaGVldFxuXG5cbiAgaWYgKF9wLnN0eWxlRW5hYmxlZCkge1xuICAgIGN5LnNldFN0eWxlKFtdKTtcbiAgfSAvLyBjcmVhdGUgdGhlIHJlbmRlcmVyXG5cblxuICB2YXIgcmVuZGVyZXJPcHRpb25zID0gZXh0ZW5kKHt9LCBvcHRpb25zLCBvcHRpb25zLnJlbmRlcmVyKTsgLy8gYWxsb3cgcmVuZGVyaW5nIGhpbnRzIGluIHRvcCBsZXZlbCBvcHRpb25zXG5cbiAgY3kuaW5pdFJlbmRlcmVyKHJlbmRlcmVyT3B0aW9ucyk7XG5cbiAgdmFyIHNldEVsZXNBbmRMYXlvdXQgPSBmdW5jdGlvbiBzZXRFbGVzQW5kTGF5b3V0KGVsZW1lbnRzLCBvbmxvYWQsIG9uZG9uZSkge1xuICAgIGN5Lm5vdGlmaWNhdGlvbnMoZmFsc2UpOyAvLyByZW1vdmUgb2xkIGVsZW1lbnRzXG5cbiAgICB2YXIgb2xkRWxlcyA9IGN5Lm11dGFibGVFbGVtZW50cygpO1xuXG4gICAgaWYgKG9sZEVsZXMubGVuZ3RoID4gMCkge1xuICAgICAgb2xkRWxlcy5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudHMgIT0gbnVsbCkge1xuICAgICAgaWYgKHBsYWluT2JqZWN0KGVsZW1lbnRzKSB8fCBhcnJheShlbGVtZW50cykpIHtcbiAgICAgICAgY3kuYWRkKGVsZW1lbnRzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjeS5vbmUoJ2xheW91dHJlYWR5JywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGN5Lm5vdGlmaWNhdGlvbnModHJ1ZSk7XG4gICAgICBjeS5lbWl0KGUpOyAvLyB3ZSBtaXNzZWQgdGhpcyBldmVudCBieSB0dXJuaW5nIG5vdGlmaWNhdGlvbnMgb2ZmLCBzbyBwYXNzIGl0IG9uXG5cbiAgICAgIGN5Lm9uZSgnbG9hZCcsIG9ubG9hZCk7XG4gICAgICBjeS5lbWl0QW5kTm90aWZ5KCdsb2FkJyk7XG4gICAgfSkub25lKCdsYXlvdXRzdG9wJywgZnVuY3Rpb24gKCkge1xuICAgICAgY3kub25lKCdkb25lJywgb25kb25lKTtcbiAgICAgIGN5LmVtaXQoJ2RvbmUnKTtcbiAgICB9KTtcbiAgICB2YXIgbGF5b3V0T3B0cyA9IGV4dGVuZCh7fSwgY3kuX3ByaXZhdGUub3B0aW9ucy5sYXlvdXQpO1xuICAgIGxheW91dE9wdHMuZWxlcyA9IGN5LmVsZW1lbnRzKCk7XG4gICAgY3kubGF5b3V0KGxheW91dE9wdHMpLnJ1bigpO1xuICB9O1xuXG4gIGxvYWRFeHREYXRhKFtvcHRpb25zLnN0eWxlLCBvcHRpb25zLmVsZW1lbnRzXSwgZnVuY3Rpb24gKHRoZW5zKSB7XG4gICAgdmFyIGluaXRTdHlsZSA9IHRoZW5zWzBdO1xuICAgIHZhciBpbml0RWxlcyA9IHRoZW5zWzFdOyAvLyBpbml0IHN0eWxlXG5cbiAgICBpZiAoX3Auc3R5bGVFbmFibGVkKSB7XG4gICAgICBjeS5zdHlsZSgpLmFwcGVuZChpbml0U3R5bGUpO1xuICAgIH0gLy8gaW5pdGlhbCBsb2FkXG5cblxuICAgIHNldEVsZXNBbmRMYXlvdXQoaW5pdEVsZXMsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIG9ucmVhZHlcbiAgICAgIGN5LnN0YXJ0QW5pbWF0aW9uTG9vcCgpO1xuICAgICAgX3AucmVhZHkgPSB0cnVlOyAvLyBpZiBhIHJlYWR5IGNhbGxiYWNrIGlzIHNwZWNpZmllZCBhcyBhbiBvcHRpb24sIHRoZSBiaW5kIGl0XG5cbiAgICAgIGlmIChmbihvcHRpb25zLnJlYWR5KSkge1xuICAgICAgICBjeS5vbigncmVhZHknLCBvcHRpb25zLnJlYWR5KTtcbiAgICAgIH0gLy8gYmluZCBhbGwgdGhlIHJlYWR5IGhhbmRsZXJzIHJlZ2lzdGVyZWQgYmVmb3JlIGNyZWF0aW5nIHRoaXMgaW5zdGFuY2VcblxuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlYWRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZuJDEgPSByZWFkaWVzW2ldO1xuICAgICAgICBjeS5vbigncmVhZHknLCBmbiQxKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlZykge1xuICAgICAgICByZWcucmVhZGllcyA9IFtdO1xuICAgICAgfSAvLyBjbGVhciBiL2Mgd2UndmUgYm91bmQgdGhlbSBhbGwgYW5kIGRvbid0IHdhbnQgdG8ga2VlcCBpdCBhcm91bmQgaW4gY2FzZSBhIG5ldyBjb3JlIHVzZXMgdGhlIHNhbWUgZGl2IGV0Y1xuXG5cbiAgICAgIGN5LmVtaXQoJ3JlYWR5Jyk7XG4gICAgfSwgb3B0aW9ucy5kb25lKTtcbiAgfSk7XG59O1xuXG52YXIgY29yZWZuJDkgPSBDb3JlLnByb3RvdHlwZTsgLy8gc2hvcnQgYWxpYXNcblxuZXh0ZW5kKGNvcmVmbiQ5LCB7XG4gIGluc3RhbmNlU3RyaW5nOiBmdW5jdGlvbiBpbnN0YW5jZVN0cmluZygpIHtcbiAgICByZXR1cm4gJ2NvcmUnO1xuICB9LFxuICBpc1JlYWR5OiBmdW5jdGlvbiBpc1JlYWR5KCkge1xuICAgIHJldHVybiB0aGlzLl9wcml2YXRlLnJlYWR5O1xuICB9LFxuICBkZXN0cm95ZWQ6IGZ1bmN0aW9uIGRlc3Ryb3llZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5kZXN0cm95ZWQ7XG4gIH0sXG4gIHJlYWR5OiBmdW5jdGlvbiByZWFkeShmbikge1xuICAgIGlmICh0aGlzLmlzUmVhZHkoKSkge1xuICAgICAgdGhpcy5lbWl0dGVyKCkuZW1pdCgncmVhZHknLCBbXSwgZm4pOyAvLyBqdXN0IGNhbGxzIGZuIGFzIHRob3VnaCB0cmlnZ2VyZWQgdmlhIHJlYWR5IGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub24oJ3JlYWR5JywgZm4pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBkZXN0cm95OiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgIHZhciBjeSA9IHRoaXM7XG4gICAgaWYgKGN5LmRlc3Ryb3llZCgpKSByZXR1cm47XG4gICAgY3kuc3RvcEFuaW1hdGlvbkxvb3AoKTtcbiAgICBjeS5kZXN0cm95UmVuZGVyZXIoKTtcbiAgICB0aGlzLmVtaXQoJ2Rlc3Ryb3knKTtcbiAgICBjeS5fcHJpdmF0ZS5kZXN0cm95ZWQgPSB0cnVlO1xuICAgIHJldHVybiBjeTtcbiAgfSxcbiAgaGFzRWxlbWVudFdpdGhJZDogZnVuY3Rpb24gaGFzRWxlbWVudFdpdGhJZChpZCkge1xuICAgIHJldHVybiB0aGlzLl9wcml2YXRlLmVsZW1lbnRzLmhhc0VsZW1lbnRXaXRoSWQoaWQpO1xuICB9LFxuICBnZXRFbGVtZW50QnlJZDogZnVuY3Rpb24gZ2V0RWxlbWVudEJ5SWQoaWQpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5lbGVtZW50cy5nZXRFbGVtZW50QnlJZChpZCk7XG4gIH0sXG4gIGhhc0NvbXBvdW5kTm9kZXM6IGZ1bmN0aW9uIGhhc0NvbXBvdW5kTm9kZXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUuaGFzQ29tcG91bmROb2RlcztcbiAgfSxcbiAgaGVhZGxlc3M6IGZ1bmN0aW9uIGhlYWRsZXNzKCkge1xuICAgIHJldHVybiB0aGlzLl9wcml2YXRlLnJlbmRlcmVyLmlzSGVhZGxlc3MoKTtcbiAgfSxcbiAgc3R5bGVFbmFibGVkOiBmdW5jdGlvbiBzdHlsZUVuYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUuc3R5bGVFbmFibGVkO1xuICB9LFxuICBhZGRUb1Bvb2w6IGZ1bmN0aW9uIGFkZFRvUG9vbChlbGVzKSB7XG4gICAgdGhpcy5fcHJpdmF0ZS5lbGVtZW50cy5tZXJnZShlbGVzKTtcblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9LFxuICByZW1vdmVGcm9tUG9vbDogZnVuY3Rpb24gcmVtb3ZlRnJvbVBvb2woZWxlcykge1xuICAgIHRoaXMuX3ByaXZhdGUuZWxlbWVudHMudW5tZXJnZShlbGVzKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBjb250YWluZXI6IGZ1bmN0aW9uIGNvbnRhaW5lcigpIHtcbiAgICByZXR1cm4gdGhpcy5fcHJpdmF0ZS5jb250YWluZXIgfHwgbnVsbDtcbiAgfSxcbiAgbW91bnQ6IGZ1bmN0aW9uIG1vdW50KGNvbnRhaW5lcikge1xuICAgIGlmIChjb250YWluZXIgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBjeSA9IHRoaXM7XG4gICAgdmFyIF9wID0gY3kuX3ByaXZhdGU7XG4gICAgdmFyIG9wdGlvbnMgPSBfcC5vcHRpb25zO1xuXG4gICAgaWYgKCFodG1sRWxlbWVudChjb250YWluZXIpICYmIGh0bWxFbGVtZW50KGNvbnRhaW5lclswXSkpIHtcbiAgICAgIGNvbnRhaW5lciA9IGNvbnRhaW5lclswXTtcbiAgICB9XG5cbiAgICBjeS5zdG9wQW5pbWF0aW9uTG9vcCgpO1xuICAgIGN5LmRlc3Ryb3lSZW5kZXJlcigpO1xuICAgIF9wLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICBfcC5zdHlsZUVuYWJsZWQgPSB0cnVlO1xuICAgIGN5LmludmFsaWRhdGVTaXplKCk7XG4gICAgY3kuaW5pdFJlbmRlcmVyKGV4dGVuZCh7fSwgb3B0aW9ucywgb3B0aW9ucy5yZW5kZXJlciwge1xuICAgICAgLy8gYWxsb3cgY3VzdG9tIHJlbmRlcmVyIG5hbWUgdG8gYmUgcmUtdXNlZCwgb3RoZXJ3aXNlIHVzZSBjYW52YXNcbiAgICAgIG5hbWU6IG9wdGlvbnMucmVuZGVyZXIubmFtZSA9PT0gJ251bGwnID8gJ2NhbnZhcycgOiBvcHRpb25zLnJlbmRlcmVyLm5hbWVcbiAgICB9KSk7XG4gICAgY3kuc3RhcnRBbmltYXRpb25Mb29wKCk7XG4gICAgY3kuc3R5bGUob3B0aW9ucy5zdHlsZSk7XG4gICAgY3kuZW1pdCgnbW91bnQnKTtcbiAgICByZXR1cm4gY3k7XG4gIH0sXG4gIHVubW91bnQ6IGZ1bmN0aW9uIHVubW91bnQoKSB7XG4gICAgdmFyIGN5ID0gdGhpcztcbiAgICBjeS5zdG9wQW5pbWF0aW9uTG9vcCgpO1xuICAgIGN5LmRlc3Ryb3lSZW5kZXJlcigpO1xuICAgIGN5LmluaXRSZW5kZXJlcih7XG4gICAgICBuYW1lOiAnbnVsbCdcbiAgICB9KTtcbiAgICBjeS5lbWl0KCd1bm1vdW50Jyk7XG4gICAgcmV0dXJuIGN5O1xuICB9LFxuICBvcHRpb25zOiBmdW5jdGlvbiBvcHRpb25zKCkge1xuICAgIHJldHVybiBjb3B5KHRoaXMuX3ByaXZhdGUub3B0aW9ucyk7XG4gIH0sXG4gIGpzb246IGZ1bmN0aW9uIGpzb24ob2JqKSB7XG4gICAgdmFyIGN5ID0gdGhpcztcbiAgICB2YXIgX3AgPSBjeS5fcHJpdmF0ZTtcbiAgICB2YXIgZWxlcyA9IGN5Lm11dGFibGVFbGVtZW50cygpO1xuXG4gICAgdmFyIGdldEZyZXNoUmVmID0gZnVuY3Rpb24gZ2V0RnJlc2hSZWYoZWxlKSB7XG4gICAgICByZXR1cm4gY3kuZ2V0RWxlbWVudEJ5SWQoZWxlLmlkKCkpO1xuICAgIH07XG5cbiAgICBpZiAocGxhaW5PYmplY3Qob2JqKSkge1xuICAgICAgLy8gc2V0XG4gICAgICBjeS5zdGFydEJhdGNoKCk7XG5cbiAgICAgIGlmIChvYmouZWxlbWVudHMpIHtcbiAgICAgICAgdmFyIGlkSW5Kc29uID0ge307XG5cbiAgICAgICAgdmFyIHVwZGF0ZUVsZXMgPSBmdW5jdGlvbiB1cGRhdGVFbGVzKGpzb25zLCBncikge1xuICAgICAgICAgIHZhciB0b0FkZCA9IFtdO1xuICAgICAgICAgIHZhciB0b01vZCA9IFtdO1xuXG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBqc29ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGpzb24gPSBqc29uc1tpXTtcbiAgICAgICAgICAgIHZhciBpZCA9ICcnICsganNvbi5kYXRhLmlkOyAvLyBpZCBtdXN0IGJlIHN0cmluZ1xuXG4gICAgICAgICAgICB2YXIgZWxlID0gY3kuZ2V0RWxlbWVudEJ5SWQoaWQpO1xuICAgICAgICAgICAgaWRJbkpzb25baWRdID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKGVsZS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgLy8gZXhpc3RpbmcgZWxlbWVudCBzaG91bGQgYmUgdXBkYXRlZFxuICAgICAgICAgICAgICB0b01vZC5wdXNoKHtcbiAgICAgICAgICAgICAgICBlbGU6IGVsZSxcbiAgICAgICAgICAgICAgICBqc29uOiBqc29uXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIHNob3VsZCBiZSBhZGRlZFxuICAgICAgICAgICAgICBpZiAoZ3IpIHtcbiAgICAgICAgICAgICAgICBqc29uLmdyb3VwID0gZ3I7XG4gICAgICAgICAgICAgICAgdG9BZGQucHVzaChqc29uKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0b0FkZC5wdXNoKGpzb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY3kuYWRkKHRvQWRkKTtcblxuICAgICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCB0b01vZC5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBfdG9Nb2QkX2kgPSB0b01vZFtfaV0sXG4gICAgICAgICAgICAgICAgX2VsZSA9IF90b01vZCRfaS5lbGUsXG4gICAgICAgICAgICAgICAgX2pzb24gPSBfdG9Nb2QkX2kuanNvbjtcblxuICAgICAgICAgICAgX2VsZS5qc29uKF9qc29uKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGFycmF5KG9iai5lbGVtZW50cykpIHtcbiAgICAgICAgICAvLyBlbGVtZW50czogW11cbiAgICAgICAgICB1cGRhdGVFbGVzKG9iai5lbGVtZW50cyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gZWxlbWVudHM6IHsgbm9kZXM6IFtdLCBlZGdlczogW10gfVxuICAgICAgICAgIHZhciBncnMgPSBbJ25vZGVzJywgJ2VkZ2VzJ107XG5cbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGdyID0gZ3JzW2ldO1xuICAgICAgICAgICAgdmFyIGVsZW1lbnRzID0gb2JqLmVsZW1lbnRzW2dyXTtcblxuICAgICAgICAgICAgaWYgKGFycmF5KGVsZW1lbnRzKSkge1xuICAgICAgICAgICAgICB1cGRhdGVFbGVzKGVsZW1lbnRzLCBncik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHBhcmVudHNUb1JlbW92ZSA9IGN5LmNvbGxlY3Rpb24oKTtcbiAgICAgICAgZWxlcy5maWx0ZXIoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgICAgIHJldHVybiAhaWRJbkpzb25bZWxlLmlkKCldO1xuICAgICAgICB9KS5mb3JFYWNoKGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgICAgICBpZiAoZWxlLmlzUGFyZW50KCkpIHtcbiAgICAgICAgICAgIHBhcmVudHNUb1JlbW92ZS5tZXJnZShlbGUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGUucmVtb3ZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTsgLy8gc28gdGhhdCBjaGlsZHJlbiBhcmUgbm90IHJlbW92ZWQgdy9wYXJlbnRcblxuICAgICAgICBwYXJlbnRzVG9SZW1vdmUuZm9yRWFjaChmdW5jdGlvbiAoZWxlKSB7XG4gICAgICAgICAgcmV0dXJuIGVsZS5jaGlsZHJlbigpLm1vdmUoe1xuICAgICAgICAgICAgcGFyZW50OiBudWxsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pOyAvLyBpbnRlcm1lZGlhdGUgcGFyZW50cyBtYXkgYmUgbW92ZWQgYnkgcHJpb3IgbGluZSwgc28gbWFrZSBzdXJlIHdlIHJlbW92ZSBieSBmcmVzaCByZWZzXG5cbiAgICAgICAgcGFyZW50c1RvUmVtb3ZlLmZvckVhY2goZnVuY3Rpb24gKGVsZSkge1xuICAgICAgICAgIHJldHVybiBnZXRGcmVzaFJlZihlbGUpLnJlbW92ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9iai5zdHlsZSkge1xuICAgICAgICBjeS5zdHlsZShvYmouc3R5bGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAob2JqLnpvb20gIT0gbnVsbCAmJiBvYmouem9vbSAhPT0gX3Auem9vbSkge1xuICAgICAgICBjeS56b29tKG9iai56b29tKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9iai5wYW4pIHtcbiAgICAgICAgaWYgKG9iai5wYW4ueCAhPT0gX3AucGFuLnggfHwgb2JqLnBhbi55ICE9PSBfcC5wYW4ueSkge1xuICAgICAgICAgIGN5LnBhbihvYmoucGFuKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAob2JqLmRhdGEpIHtcbiAgICAgICAgY3kuZGF0YShvYmouZGF0YSk7XG4gICAgICB9XG5cbiAgICAgIHZhciBmaWVsZHMgPSBbJ21pblpvb20nLCAnbWF4Wm9vbScsICd6b29taW5nRW5hYmxlZCcsICd1c2VyWm9vbWluZ0VuYWJsZWQnLCAncGFubmluZ0VuYWJsZWQnLCAndXNlclBhbm5pbmdFbmFibGVkJywgJ2JveFNlbGVjdGlvbkVuYWJsZWQnLCAnYXV0b2xvY2snLCAnYXV0b3VuZ3JhYmlmeScsICdhdXRvdW5zZWxlY3RpZnknXTtcblxuICAgICAgZm9yICh2YXIgX2kyID0gMDsgX2kyIDwgZmllbGRzLmxlbmd0aDsgX2kyKyspIHtcbiAgICAgICAgdmFyIGYgPSBmaWVsZHNbX2kyXTtcblxuICAgICAgICBpZiAob2JqW2ZdICE9IG51bGwpIHtcbiAgICAgICAgICBjeVtmXShvYmpbZl0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGN5LmVuZEJhdGNoKCk7XG4gICAgICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZ2V0XG4gICAgICB2YXIgZmxhdCA9ICEhb2JqO1xuICAgICAgdmFyIGpzb24gPSB7fTtcblxuICAgICAgaWYgKGZsYXQpIHtcbiAgICAgICAganNvbi5lbGVtZW50cyA9IHRoaXMuZWxlbWVudHMoKS5tYXAoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgICAgIHJldHVybiBlbGUuanNvbigpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGpzb24uZWxlbWVudHMgPSB7fTtcbiAgICAgICAgZWxlcy5mb3JFYWNoKGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgICAgICB2YXIgZ3JvdXAgPSBlbGUuZ3JvdXAoKTtcblxuICAgICAgICAgIGlmICghanNvbi5lbGVtZW50c1tncm91cF0pIHtcbiAgICAgICAgICAgIGpzb24uZWxlbWVudHNbZ3JvdXBdID0gW107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAganNvbi5lbGVtZW50c1tncm91cF0ucHVzaChlbGUuanNvbigpKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9wcml2YXRlLnN0eWxlRW5hYmxlZCkge1xuICAgICAgICBqc29uLnN0eWxlID0gY3kuc3R5bGUoKS5qc29uKCk7XG4gICAgICB9XG5cbiAgICAgIGpzb24uZGF0YSA9IGNvcHkoY3kuZGF0YSgpKTtcbiAgICAgIHZhciBvcHRpb25zID0gX3Aub3B0aW9ucztcbiAgICAgIGpzb24uem9vbWluZ0VuYWJsZWQgPSBfcC56b29taW5nRW5hYmxlZDtcbiAgICAgIGpzb24udXNlclpvb21pbmdFbmFibGVkID0gX3AudXNlclpvb21pbmdFbmFibGVkO1xuICAgICAganNvbi56b29tID0gX3Auem9vbTtcbiAgICAgIGpzb24ubWluWm9vbSA9IF9wLm1pblpvb207XG4gICAgICBqc29uLm1heFpvb20gPSBfcC5tYXhab29tO1xuICAgICAganNvbi5wYW5uaW5nRW5hYmxlZCA9IF9wLnBhbm5pbmdFbmFibGVkO1xuICAgICAganNvbi51c2VyUGFubmluZ0VuYWJsZWQgPSBfcC51c2VyUGFubmluZ0VuYWJsZWQ7XG4gICAgICBqc29uLnBhbiA9IGNvcHkoX3AucGFuKTtcbiAgICAgIGpzb24uYm94U2VsZWN0aW9uRW5hYmxlZCA9IF9wLmJveFNlbGVjdGlvbkVuYWJsZWQ7XG4gICAgICBqc29uLnJlbmRlcmVyID0gY29weShvcHRpb25zLnJlbmRlcmVyKTtcbiAgICAgIGpzb24uaGlkZUVkZ2VzT25WaWV3cG9ydCA9IG9wdGlvbnMuaGlkZUVkZ2VzT25WaWV3cG9ydDtcbiAgICAgIGpzb24udGV4dHVyZU9uVmlld3BvcnQgPSBvcHRpb25zLnRleHR1cmVPblZpZXdwb3J0O1xuICAgICAganNvbi53aGVlbFNlbnNpdGl2aXR5ID0gb3B0aW9ucy53aGVlbFNlbnNpdGl2aXR5O1xuICAgICAganNvbi5tb3Rpb25CbHVyID0gb3B0aW9ucy5tb3Rpb25CbHVyO1xuICAgICAgcmV0dXJuIGpzb247XG4gICAgfVxuICB9XG59KTtcbmNvcmVmbiQ5LiRpZCA9IGNvcmVmbiQ5LmdldEVsZW1lbnRCeUlkO1xuW2NvcmVmbiwgY29yZWZuJDEsIGVsZXNmbiR2LCBjb3JlZm4kMiwgY29yZWZuJDMsIGNvcmVmbiQ0LCBjb3JlZm4kNSwgY29yZWZuJDYsIGNvcmVmbiQ3LCBjb3JlZm4kOCwgZm4kNl0uZm9yRWFjaChmdW5jdGlvbiAocHJvcHMpIHtcbiAgZXh0ZW5kKGNvcmVmbiQ5LCBwcm9wcyk7XG59KTtcblxuLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cblxudmFyIGRlZmF1bHRzJDkgPSB7XG4gIGZpdDogdHJ1ZSxcbiAgLy8gd2hldGhlciB0byBmaXQgdGhlIHZpZXdwb3J0IHRvIHRoZSBncmFwaFxuICBkaXJlY3RlZDogZmFsc2UsXG4gIC8vIHdoZXRoZXIgdGhlIHRyZWUgaXMgZGlyZWN0ZWQgZG93bndhcmRzIChvciBlZGdlcyBjYW4gcG9pbnQgaW4gYW55IGRpcmVjdGlvbiBpZiBmYWxzZSlcbiAgcGFkZGluZzogMzAsXG4gIC8vIHBhZGRpbmcgb24gZml0XG4gIGNpcmNsZTogZmFsc2UsXG4gIC8vIHB1dCBkZXB0aHMgaW4gY29uY2VudHJpYyBjaXJjbGVzIGlmIHRydWUsIHB1dCBkZXB0aHMgdG9wIGRvd24gaWYgZmFsc2VcbiAgZ3JpZDogZmFsc2UsXG4gIC8vIHdoZXRoZXIgdG8gY3JlYXRlIGFuIGV2ZW4gZ3JpZCBpbnRvIHdoaWNoIHRoZSBEQUcgaXMgcGxhY2VkIChjaXJjbGU6ZmFsc2Ugb25seSlcbiAgc3BhY2luZ0ZhY3RvcjogMS43NSxcbiAgLy8gcG9zaXRpdmUgc3BhY2luZyBmYWN0b3IsIGxhcmdlciA9PiBtb3JlIHNwYWNlIGJldHdlZW4gbm9kZXMgKE4uQi4gbi9hIGlmIGNhdXNlcyBvdmVybGFwKVxuICBib3VuZGluZ0JveDogdW5kZWZpbmVkLFxuICAvLyBjb25zdHJhaW4gbGF5b3V0IGJvdW5kczsgeyB4MSwgeTEsIHgyLCB5MiB9IG9yIHsgeDEsIHkxLCB3LCBoIH1cbiAgYXZvaWRPdmVybGFwOiB0cnVlLFxuICAvLyBwcmV2ZW50cyBub2RlIG92ZXJsYXAsIG1heSBvdmVyZmxvdyBib3VuZGluZ0JveCBpZiBub3QgZW5vdWdoIHNwYWNlXG4gIG5vZGVEaW1lbnNpb25zSW5jbHVkZUxhYmVsczogZmFsc2UsXG4gIC8vIEV4Y2x1ZGVzIHRoZSBsYWJlbCB3aGVuIGNhbGN1bGF0aW5nIG5vZGUgYm91bmRpbmcgYm94ZXMgZm9yIHRoZSBsYXlvdXQgYWxnb3JpdGhtXG4gIHJvb3RzOiB1bmRlZmluZWQsXG4gIC8vIHRoZSByb290cyBvZiB0aGUgdHJlZXNcbiAgbWF4aW1hbDogZmFsc2UsXG4gIC8vIHdoZXRoZXIgdG8gc2hpZnQgbm9kZXMgZG93biB0aGVpciBuYXR1cmFsIEJGUyBkZXB0aHMgaW4gb3JkZXIgdG8gYXZvaWQgdXB3YXJkcyBlZGdlcyAoREFHUyBvbmx5KVxuICBhbmltYXRlOiBmYWxzZSxcbiAgLy8gd2hldGhlciB0byB0cmFuc2l0aW9uIHRoZSBub2RlIHBvc2l0aW9uc1xuICBhbmltYXRpb25EdXJhdGlvbjogNTAwLFxuICAvLyBkdXJhdGlvbiBvZiBhbmltYXRpb24gaW4gbXMgaWYgZW5hYmxlZFxuICBhbmltYXRpb25FYXNpbmc6IHVuZGVmaW5lZCxcbiAgLy8gZWFzaW5nIG9mIGFuaW1hdGlvbiBpZiBlbmFibGVkLFxuICBhbmltYXRlRmlsdGVyOiBmdW5jdGlvbiBhbmltYXRlRmlsdGVyKG5vZGUsIGkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgLy8gYSBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgd2hldGhlciB0aGUgbm9kZSBzaG91bGQgYmUgYW5pbWF0ZWQuICBBbGwgbm9kZXMgYW5pbWF0ZWQgYnkgZGVmYXVsdCBvbiBhbmltYXRlIGVuYWJsZWQuICBOb24tYW5pbWF0ZWQgbm9kZXMgYXJlIHBvc2l0aW9uZWQgaW1tZWRpYXRlbHkgd2hlbiB0aGUgbGF5b3V0IHN0YXJ0c1xuICByZWFkeTogdW5kZWZpbmVkLFxuICAvLyBjYWxsYmFjayBvbiBsYXlvdXRyZWFkeVxuICBzdG9wOiB1bmRlZmluZWQsXG4gIC8vIGNhbGxiYWNrIG9uIGxheW91dHN0b3BcbiAgdHJhbnNmb3JtOiBmdW5jdGlvbiB0cmFuc2Zvcm0obm9kZSwgcG9zaXRpb24pIHtcbiAgICByZXR1cm4gcG9zaXRpb247XG4gIH0gLy8gdHJhbnNmb3JtIGEgZ2l2ZW4gbm9kZSBwb3NpdGlvbi4gVXNlZnVsIGZvciBjaGFuZ2luZyBmbG93IGRpcmVjdGlvbiBpbiBkaXNjcmV0ZSBsYXlvdXRzXG5cbn07XG4vKiBlc2xpbnQtZW5hYmxlICovXG5cbnZhciBnZXRJbmZvID0gZnVuY3Rpb24gZ2V0SW5mbyhlbGUpIHtcbiAgcmV0dXJuIGVsZS5zY3JhdGNoKCdicmVhZHRoZmlyc3QnKTtcbn07XG5cbnZhciBzZXRJbmZvID0gZnVuY3Rpb24gc2V0SW5mbyhlbGUsIG9iaikge1xuICByZXR1cm4gZWxlLnNjcmF0Y2goJ2JyZWFkdGhmaXJzdCcsIG9iaik7XG59O1xuXG5mdW5jdGlvbiBCcmVhZHRoRmlyc3RMYXlvdXQob3B0aW9ucykge1xuICB0aGlzLm9wdGlvbnMgPSBleHRlbmQoe30sIGRlZmF1bHRzJDksIG9wdGlvbnMpO1xufVxuXG5CcmVhZHRoRmlyc3RMYXlvdXQucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHBhcmFtcyA9IHRoaXMub3B0aW9ucztcbiAgdmFyIG9wdGlvbnMgPSBwYXJhbXM7XG4gIHZhciBjeSA9IHBhcmFtcy5jeTtcbiAgdmFyIGVsZXMgPSBvcHRpb25zLmVsZXM7XG4gIHZhciBub2RlcyA9IGVsZXMubm9kZXMoKS5maWx0ZXIoZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gIW4uaXNQYXJlbnQoKTtcbiAgfSk7XG4gIHZhciBncmFwaCA9IGVsZXM7XG4gIHZhciBkaXJlY3RlZCA9IG9wdGlvbnMuZGlyZWN0ZWQ7XG4gIHZhciBtYXhpbWFsID0gb3B0aW9ucy5tYXhpbWFsIHx8IG9wdGlvbnMubWF4aW1hbEFkanVzdG1lbnRzID4gMDsgLy8gbWF4aW1hbEFkanVzdG1lbnRzIGZvciBjb21wYXQuIHcvIG9sZCBjb2RlXG5cbiAgdmFyIGJiID0gbWFrZUJvdW5kaW5nQm94KG9wdGlvbnMuYm91bmRpbmdCb3ggPyBvcHRpb25zLmJvdW5kaW5nQm94IDoge1xuICAgIHgxOiAwLFxuICAgIHkxOiAwLFxuICAgIHc6IGN5LndpZHRoKCksXG4gICAgaDogY3kuaGVpZ2h0KClcbiAgfSk7XG4gIHZhciByb290cztcblxuICBpZiAoZWxlbWVudE9yQ29sbGVjdGlvbihvcHRpb25zLnJvb3RzKSkge1xuICAgIHJvb3RzID0gb3B0aW9ucy5yb290cztcbiAgfSBlbHNlIGlmIChhcnJheShvcHRpb25zLnJvb3RzKSkge1xuICAgIHZhciByb290c0FycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9wdGlvbnMucm9vdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBpZCA9IG9wdGlvbnMucm9vdHNbaV07XG4gICAgICB2YXIgZWxlID0gY3kuZ2V0RWxlbWVudEJ5SWQoaWQpO1xuICAgICAgcm9vdHNBcnJheS5wdXNoKGVsZSk7XG4gICAgfVxuXG4gICAgcm9vdHMgPSBjeS5jb2xsZWN0aW9uKHJvb3RzQXJyYXkpO1xuICB9IGVsc2UgaWYgKHN0cmluZyhvcHRpb25zLnJvb3RzKSkge1xuICAgIHJvb3RzID0gY3kuJChvcHRpb25zLnJvb3RzKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoZGlyZWN0ZWQpIHtcbiAgICAgIHJvb3RzID0gbm9kZXMucm9vdHMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGNvbXBvbmVudHMgPSBlbGVzLmNvbXBvbmVudHMoKTtcbiAgICAgIHJvb3RzID0gY3kuY29sbGVjdGlvbigpO1xuXG4gICAgICB2YXIgX2xvb3AgPSBmdW5jdGlvbiBfbG9vcChfaSkge1xuICAgICAgICB2YXIgY29tcCA9IGNvbXBvbmVudHNbX2ldO1xuICAgICAgICB2YXIgbWF4RGVncmVlID0gY29tcC5tYXhEZWdyZWUoZmFsc2UpO1xuICAgICAgICB2YXIgY29tcFJvb3RzID0gY29tcC5maWx0ZXIoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgICAgIHJldHVybiBlbGUuZGVncmVlKGZhbHNlKSA9PT0gbWF4RGVncmVlO1xuICAgICAgICB9KTtcbiAgICAgICAgcm9vdHMgPSByb290cy5hZGQoY29tcFJvb3RzKTtcbiAgICAgIH07XG5cbiAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBjb21wb25lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICBfbG9vcChfaSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIGRlcHRocyA9IFtdO1xuICB2YXIgZm91bmRCeUJmcyA9IHt9O1xuXG4gIHZhciBhZGRUb0RlcHRoID0gZnVuY3Rpb24gYWRkVG9EZXB0aChlbGUsIGQpIHtcbiAgICBpZiAoZGVwdGhzW2RdID09IG51bGwpIHtcbiAgICAgIGRlcHRoc1tkXSA9IFtdO1xuICAgIH1cblxuICAgIHZhciBpID0gZGVwdGhzW2RdLmxlbmd0aDtcbiAgICBkZXB0aHNbZF0ucHVzaChlbGUpO1xuICAgIHNldEluZm8oZWxlLCB7XG4gICAgICBpbmRleDogaSxcbiAgICAgIGRlcHRoOiBkXG4gICAgfSk7XG4gIH07XG5cbiAgdmFyIGNoYW5nZURlcHRoID0gZnVuY3Rpb24gY2hhbmdlRGVwdGgoZWxlLCBuZXdEZXB0aCkge1xuICAgIHZhciBfZ2V0SW5mbyA9IGdldEluZm8oZWxlKSxcbiAgICAgICAgZGVwdGggPSBfZ2V0SW5mby5kZXB0aCxcbiAgICAgICAgaW5kZXggPSBfZ2V0SW5mby5pbmRleDtcblxuICAgIGRlcHRoc1tkZXB0aF1baW5kZXhdID0gbnVsbDtcbiAgICBhZGRUb0RlcHRoKGVsZSwgbmV3RGVwdGgpO1xuICB9OyAvLyBmaW5kIHRoZSBkZXB0aHMgb2YgdGhlIG5vZGVzXG5cblxuICBncmFwaC5iZnMoe1xuICAgIHJvb3RzOiByb290cyxcbiAgICBkaXJlY3RlZDogb3B0aW9ucy5kaXJlY3RlZCxcbiAgICB2aXNpdDogZnVuY3Rpb24gdmlzaXQobm9kZSwgZWRnZSwgcE5vZGUsIGksIGRlcHRoKSB7XG4gICAgICB2YXIgZWxlID0gbm9kZVswXTtcbiAgICAgIHZhciBpZCA9IGVsZS5pZCgpO1xuICAgICAgYWRkVG9EZXB0aChlbGUsIGRlcHRoKTtcbiAgICAgIGZvdW5kQnlCZnNbaWRdID0gdHJ1ZTtcbiAgICB9XG4gIH0pOyAvLyBjaGVjayBmb3Igbm9kZXMgbm90IGZvdW5kIGJ5IGJmc1xuXG4gIHZhciBvcnBoYW5Ob2RlcyA9IFtdO1xuXG4gIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IG5vZGVzLmxlbmd0aDsgX2kyKyspIHtcbiAgICB2YXIgX2VsZSA9IG5vZGVzW19pMl07XG5cbiAgICBpZiAoZm91bmRCeUJmc1tfZWxlLmlkKCldKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3JwaGFuTm9kZXMucHVzaChfZWxlKTtcbiAgICB9XG4gIH0gLy8gYXNzaWduIHRoZSBub2RlcyBhIGRlcHRoIGFuZCBpbmRleFxuXG5cbiAgdmFyIGFzc2lnbkRlcHRoc0F0ID0gZnVuY3Rpb24gYXNzaWduRGVwdGhzQXQoaSkge1xuICAgIHZhciBlbGVzID0gZGVwdGhzW2ldO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBlbGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICB2YXIgX2VsZTIgPSBlbGVzW2pdO1xuXG4gICAgICBpZiAoX2VsZTIgPT0gbnVsbCkge1xuICAgICAgICBlbGVzLnNwbGljZShqLCAxKTtcbiAgICAgICAgai0tO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgc2V0SW5mbyhfZWxlMiwge1xuICAgICAgICBkZXB0aDogaSxcbiAgICAgICAgaW5kZXg6IGpcbiAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICB2YXIgYXNzaWduRGVwdGhzID0gZnVuY3Rpb24gYXNzaWduRGVwdGhzKCkge1xuICAgIGZvciAodmFyIF9pMyA9IDA7IF9pMyA8IGRlcHRocy5sZW5ndGg7IF9pMysrKSB7XG4gICAgICBhc3NpZ25EZXB0aHNBdChfaTMpO1xuICAgIH1cbiAgfTtcblxuICB2YXIgYWRqdXN0TWF4aW1hbGx5ID0gZnVuY3Rpb24gYWRqdXN0TWF4aW1hbGx5KGVsZSwgc2hpZnRlZCkge1xuICAgIHZhciBlSW5mbyA9IGdldEluZm8oZWxlKTtcbiAgICB2YXIgaW5jb21lcnMgPSBlbGUuaW5jb21lcnMoKS5maWx0ZXIoZnVuY3Rpb24gKGVsKSB7XG4gICAgICByZXR1cm4gZWwuaXNOb2RlKCkgJiYgZWxlcy5oYXMoZWwpO1xuICAgIH0pO1xuICAgIHZhciBtYXhEZXB0aCA9IC0xO1xuICAgIHZhciBpZCA9IGVsZS5pZCgpO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBpbmNvbWVycy5sZW5ndGg7IGsrKykge1xuICAgICAgdmFyIGluY21yID0gaW5jb21lcnNba107XG4gICAgICB2YXIgaUluZm8gPSBnZXRJbmZvKGluY21yKTtcbiAgICAgIG1heERlcHRoID0gTWF0aC5tYXgobWF4RGVwdGgsIGlJbmZvLmRlcHRoKTtcbiAgICB9XG5cbiAgICBpZiAoZUluZm8uZGVwdGggPD0gbWF4RGVwdGgpIHtcbiAgICAgIGlmIChzaGlmdGVkW2lkXSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY2hhbmdlRGVwdGgoZWxlLCBtYXhEZXB0aCArIDEpO1xuICAgICAgc2hpZnRlZFtpZF0gPSB0cnVlO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9OyAvLyBmb3IgdGhlIGRpcmVjdGVkIGNhc2UsIHRyeSB0byBtYWtlIHRoZSBlZGdlcyBhbGwgZ28gZG93biAoaS5lLiBkZXB0aCBpID0+IGRlcHRoIGkgKyAxKVxuXG5cbiAgaWYgKGRpcmVjdGVkICYmIG1heGltYWwpIHtcbiAgICB2YXIgUSA9IFtdO1xuICAgIHZhciBzaGlmdGVkID0ge307XG5cbiAgICB2YXIgZW5xdWV1ZSA9IGZ1bmN0aW9uIGVucXVldWUobikge1xuICAgICAgcmV0dXJuIFEucHVzaChuKTtcbiAgICB9O1xuXG4gICAgdmFyIGRlcXVldWUgPSBmdW5jdGlvbiBkZXF1ZXVlKCkge1xuICAgICAgcmV0dXJuIFEuc2hpZnQoKTtcbiAgICB9O1xuXG4gICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobikge1xuICAgICAgcmV0dXJuIFEucHVzaChuKTtcbiAgICB9KTtcblxuICAgIHdoaWxlIChRLmxlbmd0aCA+IDApIHtcbiAgICAgIHZhciBfZWxlMyA9IGRlcXVldWUoKTtcblxuICAgICAgdmFyIGRpZFNoaWZ0ID0gYWRqdXN0TWF4aW1hbGx5KF9lbGUzLCBzaGlmdGVkKTtcblxuICAgICAgaWYgKGRpZFNoaWZ0KSB7XG4gICAgICAgIF9lbGUzLm91dGdvZXJzKCkuZmlsdGVyKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIHJldHVybiBlbC5pc05vZGUoKSAmJiBlbGVzLmhhcyhlbCk7XG4gICAgICAgIH0pLmZvckVhY2goZW5xdWV1ZSk7XG4gICAgICB9IGVsc2UgaWYgKGRpZFNoaWZ0ID09PSBudWxsKSB7XG4gICAgICAgIHdhcm4oJ0RldGVjdGVkIGRvdWJsZSBtYXhpbWFsIHNoaWZ0IGZvciBub2RlIGAnICsgX2VsZTMuaWQoKSArICdgLiAgQmFpbGluZyBtYXhpbWFsIGFkanVzdG1lbnQgZHVlIHRvIGN5Y2xlLiAgVXNlIGBvcHRpb25zLm1heGltYWw6IHRydWVgIG9ubHkgb24gREFHcy4nKTtcbiAgICAgICAgYnJlYWs7IC8vIGV4aXQgb24gZmFpbHVyZVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFzc2lnbkRlcHRocygpOyAvLyBjbGVhciBob2xlc1xuICAvLyBmaW5kIG1pbiBkaXN0YW5jZSB3ZSBuZWVkIHRvIGxlYXZlIGJldHdlZW4gbm9kZXNcblxuICB2YXIgbWluRGlzdGFuY2UgPSAwO1xuXG4gIGlmIChvcHRpb25zLmF2b2lkT3ZlcmxhcCkge1xuICAgIGZvciAodmFyIF9pNCA9IDA7IF9pNCA8IG5vZGVzLmxlbmd0aDsgX2k0KyspIHtcbiAgICAgIHZhciBuID0gbm9kZXNbX2k0XTtcbiAgICAgIHZhciBuYmIgPSBuLmxheW91dERpbWVuc2lvbnMob3B0aW9ucyk7XG4gICAgICB2YXIgdyA9IG5iYi53O1xuICAgICAgdmFyIGggPSBuYmIuaDtcbiAgICAgIG1pbkRpc3RhbmNlID0gTWF0aC5tYXgobWluRGlzdGFuY2UsIHcsIGgpO1xuICAgIH1cbiAgfSAvLyBnZXQgdGhlIHdlaWdodGVkIHBlcmNlbnQgZm9yIGFuIGVsZW1lbnQgYmFzZWQgb24gaXRzIGNvbm5lY3Rpdml0eSB0byBvdGhlciBsZXZlbHNcblxuXG4gIHZhciBjYWNoZWRXZWlnaHRlZFBlcmNlbnQgPSB7fTtcblxuICB2YXIgZ2V0V2VpZ2h0ZWRQZXJjZW50ID0gZnVuY3Rpb24gZ2V0V2VpZ2h0ZWRQZXJjZW50KGVsZSkge1xuICAgIGlmIChjYWNoZWRXZWlnaHRlZFBlcmNlbnRbZWxlLmlkKCldKSB7XG4gICAgICByZXR1cm4gY2FjaGVkV2VpZ2h0ZWRQZXJjZW50W2VsZS5pZCgpXTtcbiAgICB9XG5cbiAgICB2YXIgZWxlRGVwdGggPSBnZXRJbmZvKGVsZSkuZGVwdGg7XG4gICAgdmFyIG5laWdoYm9ycyA9IGVsZS5uZWlnaGJvcmhvb2QoKTtcbiAgICB2YXIgcGVyY2VudCA9IDA7XG4gICAgdmFyIHNhbXBsZXMgPSAwO1xuXG4gICAgZm9yICh2YXIgX2k1ID0gMDsgX2k1IDwgbmVpZ2hib3JzLmxlbmd0aDsgX2k1KyspIHtcbiAgICAgIHZhciBuZWlnaGJvciA9IG5laWdoYm9yc1tfaTVdO1xuXG4gICAgICBpZiAobmVpZ2hib3IuaXNFZGdlKCkgfHwgbmVpZ2hib3IuaXNQYXJlbnQoKSB8fCAhbm9kZXMuaGFzKG5laWdoYm9yKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIGJmID0gZ2V0SW5mbyhuZWlnaGJvcik7XG4gICAgICB2YXIgaW5kZXggPSBiZi5pbmRleDtcbiAgICAgIHZhciBkZXB0aCA9IGJmLmRlcHRoOyAvLyB1bmFzc2lnbmVkIG5laWdoYm91cnMgc2hvdWxkbid0IGFmZmVjdCB0aGUgb3JkZXJpbmdcblxuICAgICAgaWYgKGluZGV4ID09IG51bGwgfHwgZGVwdGggPT0gbnVsbCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIG5EZXB0aCA9IGRlcHRoc1tkZXB0aF0ubGVuZ3RoO1xuXG4gICAgICBpZiAoZGVwdGggPCBlbGVEZXB0aCkge1xuICAgICAgICAvLyBvbmx5IGdldCBpbmZsdWVuY2VkIGJ5IGVsZW1lbnRzIGFib3ZlXG4gICAgICAgIHBlcmNlbnQgKz0gaW5kZXggLyBuRGVwdGg7XG4gICAgICAgIHNhbXBsZXMrKztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzYW1wbGVzID0gTWF0aC5tYXgoMSwgc2FtcGxlcyk7XG4gICAgcGVyY2VudCA9IHBlcmNlbnQgLyBzYW1wbGVzO1xuXG4gICAgaWYgKHNhbXBsZXMgPT09IDApIHtcbiAgICAgIC8vIHB1dCBsb25lIG5vZGVzIGF0IHRoZSBzdGFydFxuICAgICAgcGVyY2VudCA9IDA7XG4gICAgfVxuXG4gICAgY2FjaGVkV2VpZ2h0ZWRQZXJjZW50W2VsZS5pZCgpXSA9IHBlcmNlbnQ7XG4gICAgcmV0dXJuIHBlcmNlbnQ7XG4gIH07IC8vIHJlYXJyYW5nZSB0aGUgaW5kaWNlcyBpbiBlYWNoIGRlcHRoIGxldmVsIGJhc2VkIG9uIGNvbm5lY3Rpdml0eVxuXG5cbiAgdmFyIHNvcnRGbiA9IGZ1bmN0aW9uIHNvcnRGbihhLCBiKSB7XG4gICAgdmFyIGFwY3QgPSBnZXRXZWlnaHRlZFBlcmNlbnQoYSk7XG4gICAgdmFyIGJwY3QgPSBnZXRXZWlnaHRlZFBlcmNlbnQoYik7XG4gICAgdmFyIGRpZmYgPSBhcGN0IC0gYnBjdDtcblxuICAgIGlmIChkaWZmID09PSAwKSB7XG4gICAgICByZXR1cm4gYXNjZW5kaW5nKGEuaWQoKSwgYi5pZCgpKTsgLy8gbWFrZSBzdXJlIHNvcnQgZG9lc24ndCBoYXZlIGRvbid0LWNhcmUgY29tcGFyaXNvbnNcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRpZmY7XG4gICAgfVxuICB9OyAvLyBzb3J0IGVhY2ggbGV2ZWwgdG8gbWFrZSBjb25uZWN0ZWQgbm9kZXMgY2xvc2VyXG5cblxuICBmb3IgKHZhciBfaTYgPSAwOyBfaTYgPCBkZXB0aHMubGVuZ3RoOyBfaTYrKykge1xuICAgIGRlcHRoc1tfaTZdLnNvcnQoc29ydEZuKTtcblxuICAgIGFzc2lnbkRlcHRoc0F0KF9pNik7XG4gIH0gLy8gYXNzaWduIG9ycGhhbiBub2RlcyB0byBhIG5ldyB0b3AtbGV2ZWwgZGVwdGhcblxuXG4gIHZhciBvcnBoYW5EZXB0aCA9IFtdO1xuXG4gIGZvciAodmFyIF9pNyA9IDA7IF9pNyA8IG9ycGhhbk5vZGVzLmxlbmd0aDsgX2k3KyspIHtcbiAgICBvcnBoYW5EZXB0aC5wdXNoKG9ycGhhbk5vZGVzW19pN10pO1xuICB9XG5cbiAgZGVwdGhzLnVuc2hpZnQob3JwaGFuRGVwdGgpO1xuICBhc3NpZ25EZXB0aHMoKTtcbiAgdmFyIGJpZ2dlc3REZXB0aFNpemUgPSAwO1xuXG4gIGZvciAodmFyIF9pOCA9IDA7IF9pOCA8IGRlcHRocy5sZW5ndGg7IF9pOCsrKSB7XG4gICAgYmlnZ2VzdERlcHRoU2l6ZSA9IE1hdGgubWF4KGRlcHRoc1tfaThdLmxlbmd0aCwgYmlnZ2VzdERlcHRoU2l6ZSk7XG4gIH1cblxuICB2YXIgY2VudGVyID0ge1xuICAgIHg6IGJiLngxICsgYmIudyAvIDIsXG4gICAgeTogYmIueDEgKyBiYi5oIC8gMlxuICB9O1xuICB2YXIgbWF4RGVwdGhTaXplID0gZGVwdGhzLnJlZHVjZShmdW5jdGlvbiAobWF4LCBlbGVzKSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KG1heCwgZWxlcy5sZW5ndGgpO1xuICB9LCAwKTtcblxuICB2YXIgZ2V0UG9zaXRpb24gPSBmdW5jdGlvbiBnZXRQb3NpdGlvbihlbGUpIHtcbiAgICB2YXIgX2dldEluZm8yID0gZ2V0SW5mbyhlbGUpLFxuICAgICAgICBkZXB0aCA9IF9nZXRJbmZvMi5kZXB0aCxcbiAgICAgICAgaW5kZXggPSBfZ2V0SW5mbzIuaW5kZXg7XG5cbiAgICB2YXIgZGVwdGhTaXplID0gZGVwdGhzW2RlcHRoXS5sZW5ndGg7XG4gICAgdmFyIGRpc3RhbmNlWCA9IE1hdGgubWF4KGJiLncgLyAoKG9wdGlvbnMuZ3JpZCA/IG1heERlcHRoU2l6ZSA6IGRlcHRoU2l6ZSkgKyAxKSwgbWluRGlzdGFuY2UpO1xuICAgIHZhciBkaXN0YW5jZVkgPSBNYXRoLm1heChiYi5oIC8gKGRlcHRocy5sZW5ndGggKyAxKSwgbWluRGlzdGFuY2UpO1xuICAgIHZhciByYWRpdXNTdGVwU2l6ZSA9IE1hdGgubWluKGJiLncgLyAyIC8gZGVwdGhzLmxlbmd0aCwgYmIuaCAvIDIgLyBkZXB0aHMubGVuZ3RoKTtcbiAgICByYWRpdXNTdGVwU2l6ZSA9IE1hdGgubWF4KHJhZGl1c1N0ZXBTaXplLCBtaW5EaXN0YW5jZSk7XG5cbiAgICBpZiAoIW9wdGlvbnMuY2lyY2xlKSB7XG4gICAgICB2YXIgZXBvcyA9IHtcbiAgICAgICAgeDogY2VudGVyLnggKyAoaW5kZXggKyAxIC0gKGRlcHRoU2l6ZSArIDEpIC8gMikgKiBkaXN0YW5jZVgsXG4gICAgICAgIHk6IChkZXB0aCArIDEpICogZGlzdGFuY2VZXG4gICAgICB9O1xuICAgICAgcmV0dXJuIGVwb3M7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciByYWRpdXMgPSByYWRpdXNTdGVwU2l6ZSAqIGRlcHRoICsgcmFkaXVzU3RlcFNpemUgLSAoZGVwdGhzLmxlbmd0aCA+IDAgJiYgZGVwdGhzWzBdLmxlbmd0aCA8PSAzID8gcmFkaXVzU3RlcFNpemUgLyAyIDogMCk7XG4gICAgICB2YXIgdGhldGEgPSAyICogTWF0aC5QSSAvIGRlcHRoc1tkZXB0aF0ubGVuZ3RoICogaW5kZXg7XG5cbiAgICAgIGlmIChkZXB0aCA9PT0gMCAmJiBkZXB0aHNbMF0ubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJhZGl1cyA9IDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHg6IGNlbnRlci54ICsgcmFkaXVzICogTWF0aC5jb3ModGhldGEpLFxuICAgICAgICB5OiBjZW50ZXIueSArIHJhZGl1cyAqIE1hdGguc2luKHRoZXRhKVxuICAgICAgfTtcbiAgICB9XG4gIH07XG5cbiAgbm9kZXMubGF5b3V0UG9zaXRpb25zKHRoaXMsIG9wdGlvbnMsIGdldFBvc2l0aW9uKTtcbiAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG59O1xuXG52YXIgZGVmYXVsdHMkYSA9IHtcbiAgZml0OiB0cnVlLFxuICAvLyB3aGV0aGVyIHRvIGZpdCB0aGUgdmlld3BvcnQgdG8gdGhlIGdyYXBoXG4gIHBhZGRpbmc6IDMwLFxuICAvLyB0aGUgcGFkZGluZyBvbiBmaXRcbiAgYm91bmRpbmdCb3g6IHVuZGVmaW5lZCxcbiAgLy8gY29uc3RyYWluIGxheW91dCBib3VuZHM7IHsgeDEsIHkxLCB4MiwgeTIgfSBvciB7IHgxLCB5MSwgdywgaCB9XG4gIGF2b2lkT3ZlcmxhcDogdHJ1ZSxcbiAgLy8gcHJldmVudHMgbm9kZSBvdmVybGFwLCBtYXkgb3ZlcmZsb3cgYm91bmRpbmdCb3ggYW5kIHJhZGl1cyBpZiBub3QgZW5vdWdoIHNwYWNlXG4gIG5vZGVEaW1lbnNpb25zSW5jbHVkZUxhYmVsczogZmFsc2UsXG4gIC8vIEV4Y2x1ZGVzIHRoZSBsYWJlbCB3aGVuIGNhbGN1bGF0aW5nIG5vZGUgYm91bmRpbmcgYm94ZXMgZm9yIHRoZSBsYXlvdXQgYWxnb3JpdGhtXG4gIHNwYWNpbmdGYWN0b3I6IHVuZGVmaW5lZCxcbiAgLy8gQXBwbGllcyBhIG11bHRpcGxpY2F0aXZlIGZhY3RvciAoPjApIHRvIGV4cGFuZCBvciBjb21wcmVzcyB0aGUgb3ZlcmFsbCBhcmVhIHRoYXQgdGhlIG5vZGVzIHRha2UgdXBcbiAgcmFkaXVzOiB1bmRlZmluZWQsXG4gIC8vIHRoZSByYWRpdXMgb2YgdGhlIGNpcmNsZVxuICBzdGFydEFuZ2xlOiAzIC8gMiAqIE1hdGguUEksXG4gIC8vIHdoZXJlIG5vZGVzIHN0YXJ0IGluIHJhZGlhbnNcbiAgc3dlZXA6IHVuZGVmaW5lZCxcbiAgLy8gaG93IG1hbnkgcmFkaWFucyBzaG91bGQgYmUgYmV0d2VlbiB0aGUgZmlyc3QgYW5kIGxhc3Qgbm9kZSAoZGVmYXVsdHMgdG8gZnVsbCBjaXJjbGUpXG4gIGNsb2Nrd2lzZTogdHJ1ZSxcbiAgLy8gd2hldGhlciB0aGUgbGF5b3V0IHNob3VsZCBnbyBjbG9ja3dpc2UgKHRydWUpIG9yIGNvdW50ZXJjbG9ja3dpc2UvYW50aWNsb2Nrd2lzZSAoZmFsc2UpXG4gIHNvcnQ6IHVuZGVmaW5lZCxcbiAgLy8gYSBzb3J0aW5nIGZ1bmN0aW9uIHRvIG9yZGVyIHRoZSBub2RlczsgZS5nLiBmdW5jdGlvbihhLCBiKXsgcmV0dXJuIGEuZGF0YSgnd2VpZ2h0JykgLSBiLmRhdGEoJ3dlaWdodCcpIH1cbiAgYW5pbWF0ZTogZmFsc2UsXG4gIC8vIHdoZXRoZXIgdG8gdHJhbnNpdGlvbiB0aGUgbm9kZSBwb3NpdGlvbnNcbiAgYW5pbWF0aW9uRHVyYXRpb246IDUwMCxcbiAgLy8gZHVyYXRpb24gb2YgYW5pbWF0aW9uIGluIG1zIGlmIGVuYWJsZWRcbiAgYW5pbWF0aW9uRWFzaW5nOiB1bmRlZmluZWQsXG4gIC8vIGVhc2luZyBvZiBhbmltYXRpb24gaWYgZW5hYmxlZFxuICBhbmltYXRlRmlsdGVyOiBmdW5jdGlvbiBhbmltYXRlRmlsdGVyKG5vZGUsIGkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgLy8gYSBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgd2hldGhlciB0aGUgbm9kZSBzaG91bGQgYmUgYW5pbWF0ZWQuICBBbGwgbm9kZXMgYW5pbWF0ZWQgYnkgZGVmYXVsdCBvbiBhbmltYXRlIGVuYWJsZWQuICBOb24tYW5pbWF0ZWQgbm9kZXMgYXJlIHBvc2l0aW9uZWQgaW1tZWRpYXRlbHkgd2hlbiB0aGUgbGF5b3V0IHN0YXJ0c1xuICByZWFkeTogdW5kZWZpbmVkLFxuICAvLyBjYWxsYmFjayBvbiBsYXlvdXRyZWFkeVxuICBzdG9wOiB1bmRlZmluZWQsXG4gIC8vIGNhbGxiYWNrIG9uIGxheW91dHN0b3BcbiAgdHJhbnNmb3JtOiBmdW5jdGlvbiB0cmFuc2Zvcm0obm9kZSwgcG9zaXRpb24pIHtcbiAgICByZXR1cm4gcG9zaXRpb247XG4gIH0gLy8gdHJhbnNmb3JtIGEgZ2l2ZW4gbm9kZSBwb3NpdGlvbi4gVXNlZnVsIGZvciBjaGFuZ2luZyBmbG93IGRpcmVjdGlvbiBpbiBkaXNjcmV0ZSBsYXlvdXRzIFxuXG59O1xuXG5mdW5jdGlvbiBDaXJjbGVMYXlvdXQob3B0aW9ucykge1xuICB0aGlzLm9wdGlvbnMgPSBleHRlbmQoe30sIGRlZmF1bHRzJGEsIG9wdGlvbnMpO1xufVxuXG5DaXJjbGVMYXlvdXQucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHBhcmFtcyA9IHRoaXMub3B0aW9ucztcbiAgdmFyIG9wdGlvbnMgPSBwYXJhbXM7XG4gIHZhciBjeSA9IHBhcmFtcy5jeTtcbiAgdmFyIGVsZXMgPSBvcHRpb25zLmVsZXM7XG4gIHZhciBjbG9ja3dpc2UgPSBvcHRpb25zLmNvdW50ZXJjbG9ja3dpc2UgIT09IHVuZGVmaW5lZCA/ICFvcHRpb25zLmNvdW50ZXJjbG9ja3dpc2UgOiBvcHRpb25zLmNsb2Nrd2lzZTtcbiAgdmFyIG5vZGVzID0gZWxlcy5ub2RlcygpLm5vdCgnOnBhcmVudCcpO1xuXG4gIGlmIChvcHRpb25zLnNvcnQpIHtcbiAgICBub2RlcyA9IG5vZGVzLnNvcnQob3B0aW9ucy5zb3J0KTtcbiAgfVxuXG4gIHZhciBiYiA9IG1ha2VCb3VuZGluZ0JveChvcHRpb25zLmJvdW5kaW5nQm94ID8gb3B0aW9ucy5ib3VuZGluZ0JveCA6IHtcbiAgICB4MTogMCxcbiAgICB5MTogMCxcbiAgICB3OiBjeS53aWR0aCgpLFxuICAgIGg6IGN5LmhlaWdodCgpXG4gIH0pO1xuICB2YXIgY2VudGVyID0ge1xuICAgIHg6IGJiLngxICsgYmIudyAvIDIsXG4gICAgeTogYmIueTEgKyBiYi5oIC8gMlxuICB9O1xuICB2YXIgc3dlZXAgPSBvcHRpb25zLnN3ZWVwID09PSB1bmRlZmluZWQgPyAyICogTWF0aC5QSSAtIDIgKiBNYXRoLlBJIC8gbm9kZXMubGVuZ3RoIDogb3B0aW9ucy5zd2VlcDtcbiAgdmFyIGRUaGV0YSA9IHN3ZWVwIC8gTWF0aC5tYXgoMSwgbm9kZXMubGVuZ3RoIC0gMSk7XG4gIHZhciByO1xuICB2YXIgbWluRGlzdGFuY2UgPSAwO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgbiA9IG5vZGVzW2ldO1xuICAgIHZhciBuYmIgPSBuLmxheW91dERpbWVuc2lvbnMob3B0aW9ucyk7XG4gICAgdmFyIHcgPSBuYmIudztcbiAgICB2YXIgaCA9IG5iYi5oO1xuICAgIG1pbkRpc3RhbmNlID0gTWF0aC5tYXgobWluRGlzdGFuY2UsIHcsIGgpO1xuICB9XG5cbiAgaWYgKG51bWJlcihvcHRpb25zLnJhZGl1cykpIHtcbiAgICByID0gb3B0aW9ucy5yYWRpdXM7XG4gIH0gZWxzZSBpZiAobm9kZXMubGVuZ3RoIDw9IDEpIHtcbiAgICByID0gMDtcbiAgfSBlbHNlIHtcbiAgICByID0gTWF0aC5taW4oYmIuaCwgYmIudykgLyAyIC0gbWluRGlzdGFuY2U7XG4gIH0gLy8gY2FsY3VsYXRlIHRoZSByYWRpdXNcblxuXG4gIGlmIChub2Rlcy5sZW5ndGggPiAxICYmIG9wdGlvbnMuYXZvaWRPdmVybGFwKSB7XG4gICAgLy8gYnV0IG9ubHkgaWYgbW9yZSB0aGFuIG9uZSBub2RlIChjYW4ndCBvdmVybGFwKVxuICAgIG1pbkRpc3RhbmNlICo9IDEuNzU7IC8vIGp1c3QgdG8gaGF2ZSBzb21lIG5pY2Ugc3BhY2luZ1xuXG4gICAgdmFyIGRjb3MgPSBNYXRoLmNvcyhkVGhldGEpIC0gTWF0aC5jb3MoMCk7XG4gICAgdmFyIGRzaW4gPSBNYXRoLnNpbihkVGhldGEpIC0gTWF0aC5zaW4oMCk7XG4gICAgdmFyIHJNaW4gPSBNYXRoLnNxcnQobWluRGlzdGFuY2UgKiBtaW5EaXN0YW5jZSAvIChkY29zICogZGNvcyArIGRzaW4gKiBkc2luKSk7IC8vIHMudC4gbm8gbm9kZXMgb3ZlcmxhcHBpbmdcblxuICAgIHIgPSBNYXRoLm1heChyTWluLCByKTtcbiAgfVxuXG4gIHZhciBnZXRQb3MgPSBmdW5jdGlvbiBnZXRQb3MoZWxlLCBpKSB7XG4gICAgdmFyIHRoZXRhID0gb3B0aW9ucy5zdGFydEFuZ2xlICsgaSAqIGRUaGV0YSAqIChjbG9ja3dpc2UgPyAxIDogLTEpO1xuICAgIHZhciByeCA9IHIgKiBNYXRoLmNvcyh0aGV0YSk7XG4gICAgdmFyIHJ5ID0gciAqIE1hdGguc2luKHRoZXRhKTtcbiAgICB2YXIgcG9zID0ge1xuICAgICAgeDogY2VudGVyLnggKyByeCxcbiAgICAgIHk6IGNlbnRlci55ICsgcnlcbiAgICB9O1xuICAgIHJldHVybiBwb3M7XG4gIH07XG5cbiAgbm9kZXMubGF5b3V0UG9zaXRpb25zKHRoaXMsIG9wdGlvbnMsIGdldFBvcyk7XG4gIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xufTtcblxudmFyIGRlZmF1bHRzJGIgPSB7XG4gIGZpdDogdHJ1ZSxcbiAgLy8gd2hldGhlciB0byBmaXQgdGhlIHZpZXdwb3J0IHRvIHRoZSBncmFwaFxuICBwYWRkaW5nOiAzMCxcbiAgLy8gdGhlIHBhZGRpbmcgb24gZml0XG4gIHN0YXJ0QW5nbGU6IDMgLyAyICogTWF0aC5QSSxcbiAgLy8gd2hlcmUgbm9kZXMgc3RhcnQgaW4gcmFkaWFuc1xuICBzd2VlcDogdW5kZWZpbmVkLFxuICAvLyBob3cgbWFueSByYWRpYW5zIHNob3VsZCBiZSBiZXR3ZWVuIHRoZSBmaXJzdCBhbmQgbGFzdCBub2RlIChkZWZhdWx0cyB0byBmdWxsIGNpcmNsZSlcbiAgY2xvY2t3aXNlOiB0cnVlLFxuICAvLyB3aGV0aGVyIHRoZSBsYXlvdXQgc2hvdWxkIGdvIGNsb2Nrd2lzZSAodHJ1ZSkgb3IgY291bnRlcmNsb2Nrd2lzZS9hbnRpY2xvY2t3aXNlIChmYWxzZSlcbiAgZXF1aWRpc3RhbnQ6IGZhbHNlLFxuICAvLyB3aGV0aGVyIGxldmVscyBoYXZlIGFuIGVxdWFsIHJhZGlhbCBkaXN0YW5jZSBiZXR3ZW4gdGhlbSwgbWF5IGNhdXNlIGJvdW5kaW5nIGJveCBvdmVyZmxvd1xuICBtaW5Ob2RlU3BhY2luZzogMTAsXG4gIC8vIG1pbiBzcGFjaW5nIGJldHdlZW4gb3V0c2lkZSBvZiBub2RlcyAodXNlZCBmb3IgcmFkaXVzIGFkanVzdG1lbnQpXG4gIGJvdW5kaW5nQm94OiB1bmRlZmluZWQsXG4gIC8vIGNvbnN0cmFpbiBsYXlvdXQgYm91bmRzOyB7IHgxLCB5MSwgeDIsIHkyIH0gb3IgeyB4MSwgeTEsIHcsIGggfVxuICBhdm9pZE92ZXJsYXA6IHRydWUsXG4gIC8vIHByZXZlbnRzIG5vZGUgb3ZlcmxhcCwgbWF5IG92ZXJmbG93IGJvdW5kaW5nQm94IGlmIG5vdCBlbm91Z2ggc3BhY2VcbiAgbm9kZURpbWVuc2lvbnNJbmNsdWRlTGFiZWxzOiBmYWxzZSxcbiAgLy8gRXhjbHVkZXMgdGhlIGxhYmVsIHdoZW4gY2FsY3VsYXRpbmcgbm9kZSBib3VuZGluZyBib3hlcyBmb3IgdGhlIGxheW91dCBhbGdvcml0aG1cbiAgaGVpZ2h0OiB1bmRlZmluZWQsXG4gIC8vIGhlaWdodCBvZiBsYXlvdXQgYXJlYSAob3ZlcnJpZGVzIGNvbnRhaW5lciBoZWlnaHQpXG4gIHdpZHRoOiB1bmRlZmluZWQsXG4gIC8vIHdpZHRoIG9mIGxheW91dCBhcmVhIChvdmVycmlkZXMgY29udGFpbmVyIHdpZHRoKVxuICBzcGFjaW5nRmFjdG9yOiB1bmRlZmluZWQsXG4gIC8vIEFwcGxpZXMgYSBtdWx0aXBsaWNhdGl2ZSBmYWN0b3IgKD4wKSB0byBleHBhbmQgb3IgY29tcHJlc3MgdGhlIG92ZXJhbGwgYXJlYSB0aGF0IHRoZSBub2RlcyB0YWtlIHVwXG4gIGNvbmNlbnRyaWM6IGZ1bmN0aW9uIGNvbmNlbnRyaWMobm9kZSkge1xuICAgIC8vIHJldHVybnMgbnVtZXJpYyB2YWx1ZSBmb3IgZWFjaCBub2RlLCBwbGFjaW5nIGhpZ2hlciBub2RlcyBpbiBsZXZlbHMgdG93YXJkcyB0aGUgY2VudHJlXG4gICAgcmV0dXJuIG5vZGUuZGVncmVlKCk7XG4gIH0sXG4gIGxldmVsV2lkdGg6IGZ1bmN0aW9uIGxldmVsV2lkdGgobm9kZXMpIHtcbiAgICAvLyB0aGUgbGV0aWF0aW9uIG9mIGNvbmNlbnRyaWMgdmFsdWVzIGluIGVhY2ggbGV2ZWxcbiAgICByZXR1cm4gbm9kZXMubWF4RGVncmVlKCkgLyA0O1xuICB9LFxuICBhbmltYXRlOiBmYWxzZSxcbiAgLy8gd2hldGhlciB0byB0cmFuc2l0aW9uIHRoZSBub2RlIHBvc2l0aW9uc1xuICBhbmltYXRpb25EdXJhdGlvbjogNTAwLFxuICAvLyBkdXJhdGlvbiBvZiBhbmltYXRpb24gaW4gbXMgaWYgZW5hYmxlZFxuICBhbmltYXRpb25FYXNpbmc6IHVuZGVmaW5lZCxcbiAgLy8gZWFzaW5nIG9mIGFuaW1hdGlvbiBpZiBlbmFibGVkXG4gIGFuaW1hdGVGaWx0ZXI6IGZ1bmN0aW9uIGFuaW1hdGVGaWx0ZXIobm9kZSwgaSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICAvLyBhIGZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBub2RlIHNob3VsZCBiZSBhbmltYXRlZC4gIEFsbCBub2RlcyBhbmltYXRlZCBieSBkZWZhdWx0IG9uIGFuaW1hdGUgZW5hYmxlZC4gIE5vbi1hbmltYXRlZCBub2RlcyBhcmUgcG9zaXRpb25lZCBpbW1lZGlhdGVseSB3aGVuIHRoZSBsYXlvdXQgc3RhcnRzXG4gIHJlYWR5OiB1bmRlZmluZWQsXG4gIC8vIGNhbGxiYWNrIG9uIGxheW91dHJlYWR5XG4gIHN0b3A6IHVuZGVmaW5lZCxcbiAgLy8gY2FsbGJhY2sgb24gbGF5b3V0c3RvcFxuICB0cmFuc2Zvcm06IGZ1bmN0aW9uIHRyYW5zZm9ybShub2RlLCBwb3NpdGlvbikge1xuICAgIHJldHVybiBwb3NpdGlvbjtcbiAgfSAvLyB0cmFuc2Zvcm0gYSBnaXZlbiBub2RlIHBvc2l0aW9uLiBVc2VmdWwgZm9yIGNoYW5naW5nIGZsb3cgZGlyZWN0aW9uIGluIGRpc2NyZXRlIGxheW91dHNcblxufTtcblxuZnVuY3Rpb24gQ29uY2VudHJpY0xheW91dChvcHRpb25zKSB7XG4gIHRoaXMub3B0aW9ucyA9IGV4dGVuZCh7fSwgZGVmYXVsdHMkYiwgb3B0aW9ucyk7XG59XG5cbkNvbmNlbnRyaWNMYXlvdXQucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHBhcmFtcyA9IHRoaXMub3B0aW9ucztcbiAgdmFyIG9wdGlvbnMgPSBwYXJhbXM7XG4gIHZhciBjbG9ja3dpc2UgPSBvcHRpb25zLmNvdW50ZXJjbG9ja3dpc2UgIT09IHVuZGVmaW5lZCA/ICFvcHRpb25zLmNvdW50ZXJjbG9ja3dpc2UgOiBvcHRpb25zLmNsb2Nrd2lzZTtcbiAgdmFyIGN5ID0gcGFyYW1zLmN5O1xuICB2YXIgZWxlcyA9IG9wdGlvbnMuZWxlcztcbiAgdmFyIG5vZGVzID0gZWxlcy5ub2RlcygpLm5vdCgnOnBhcmVudCcpO1xuICB2YXIgYmIgPSBtYWtlQm91bmRpbmdCb3gob3B0aW9ucy5ib3VuZGluZ0JveCA/IG9wdGlvbnMuYm91bmRpbmdCb3ggOiB7XG4gICAgeDE6IDAsXG4gICAgeTE6IDAsXG4gICAgdzogY3kud2lkdGgoKSxcbiAgICBoOiBjeS5oZWlnaHQoKVxuICB9KTtcbiAgdmFyIGNlbnRlciA9IHtcbiAgICB4OiBiYi54MSArIGJiLncgLyAyLFxuICAgIHk6IGJiLnkxICsgYmIuaCAvIDJcbiAgfTtcbiAgdmFyIG5vZGVWYWx1ZXMgPSBbXTsgLy8geyBub2RlLCB2YWx1ZSB9XG5cbiAgdmFyIG1heE5vZGVTaXplID0gMDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIG5vZGUgPSBub2Rlc1tpXTtcbiAgICB2YXIgdmFsdWUgPSB2b2lkIDA7IC8vIGNhbGN1bGF0ZSB0aGUgbm9kZSB2YWx1ZVxuXG4gICAgdmFsdWUgPSBvcHRpb25zLmNvbmNlbnRyaWMobm9kZSk7XG4gICAgbm9kZVZhbHVlcy5wdXNoKHtcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIG5vZGU6IG5vZGVcbiAgICB9KTsgLy8gZm9yIHN0eWxlIG1hcHBpbmdcblxuICAgIG5vZGUuX3ByaXZhdGUuc2NyYXRjaC5jb25jZW50cmljID0gdmFsdWU7XG4gIH0gLy8gaW4gY2FzZSB3ZSB1c2VkIHRoZSBgY29uY2VudHJpY2AgaW4gc3R5bGVcblxuXG4gIG5vZGVzLnVwZGF0ZVN0eWxlKCk7IC8vIGNhbGN1bGF0ZSBtYXggc2l6ZSBub3cgYmFzZWQgb24gcG90ZW50aWFsbHkgdXBkYXRlZCBtYXBwZXJzXG5cbiAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IG5vZGVzLmxlbmd0aDsgX2krKykge1xuICAgIHZhciBfbm9kZSA9IG5vZGVzW19pXTtcblxuICAgIHZhciBuYmIgPSBfbm9kZS5sYXlvdXREaW1lbnNpb25zKG9wdGlvbnMpO1xuXG4gICAgbWF4Tm9kZVNpemUgPSBNYXRoLm1heChtYXhOb2RlU2l6ZSwgbmJiLncsIG5iYi5oKTtcbiAgfSAvLyBzb3J0IG5vZGUgdmFsdWVzIGluIGRlc2NyZWFzaW5nIG9yZGVyXG5cblxuICBub2RlVmFsdWVzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYi52YWx1ZSAtIGEudmFsdWU7XG4gIH0pO1xuICB2YXIgbGV2ZWxXaWR0aCA9IG9wdGlvbnMubGV2ZWxXaWR0aChub2Rlcyk7IC8vIHB1dCB0aGUgdmFsdWVzIGludG8gbGV2ZWxzXG5cbiAgdmFyIGxldmVscyA9IFtbXV07XG4gIHZhciBjdXJyZW50TGV2ZWwgPSBsZXZlbHNbMF07XG5cbiAgZm9yICh2YXIgX2kyID0gMDsgX2kyIDwgbm9kZVZhbHVlcy5sZW5ndGg7IF9pMisrKSB7XG4gICAgdmFyIHZhbCA9IG5vZGVWYWx1ZXNbX2kyXTtcblxuICAgIGlmIChjdXJyZW50TGV2ZWwubGVuZ3RoID4gMCkge1xuICAgICAgdmFyIGRpZmYgPSBNYXRoLmFicyhjdXJyZW50TGV2ZWxbMF0udmFsdWUgLSB2YWwudmFsdWUpO1xuXG4gICAgICBpZiAoZGlmZiA+PSBsZXZlbFdpZHRoKSB7XG4gICAgICAgIGN1cnJlbnRMZXZlbCA9IFtdO1xuICAgICAgICBsZXZlbHMucHVzaChjdXJyZW50TGV2ZWwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGN1cnJlbnRMZXZlbC5wdXNoKHZhbCk7XG4gIH0gLy8gY3JlYXRlIHBvc2l0aW9ucyBmcm9tIGxldmVsc1xuXG5cbiAgdmFyIG1pbkRpc3QgPSBtYXhOb2RlU2l6ZSArIG9wdGlvbnMubWluTm9kZVNwYWNpbmc7IC8vIG1pbiBkaXN0IGJldHdlZW4gbm9kZXNcblxuICBpZiAoIW9wdGlvbnMuYXZvaWRPdmVybGFwKSB7XG4gICAgLy8gdGhlbiBzdHJpY3RseSBjb25zdHJhaW4gdG8gYmJcbiAgICB2YXIgZmlyc3RMdmxIYXNNdWx0aSA9IGxldmVscy5sZW5ndGggPiAwICYmIGxldmVsc1swXS5sZW5ndGggPiAxO1xuICAgIHZhciBtYXhSID0gTWF0aC5taW4oYmIudywgYmIuaCkgLyAyIC0gbWluRGlzdDtcbiAgICB2YXIgclN0ZXAgPSBtYXhSIC8gKGxldmVscy5sZW5ndGggKyBmaXJzdEx2bEhhc011bHRpID8gMSA6IDApO1xuICAgIG1pbkRpc3QgPSBNYXRoLm1pbihtaW5EaXN0LCByU3RlcCk7XG4gIH0gLy8gZmluZCB0aGUgbWV0cmljcyBmb3IgZWFjaCBsZXZlbFxuXG5cbiAgdmFyIHIgPSAwO1xuXG4gIGZvciAodmFyIF9pMyA9IDA7IF9pMyA8IGxldmVscy5sZW5ndGg7IF9pMysrKSB7XG4gICAgdmFyIGxldmVsID0gbGV2ZWxzW19pM107XG4gICAgdmFyIHN3ZWVwID0gb3B0aW9ucy5zd2VlcCA9PT0gdW5kZWZpbmVkID8gMiAqIE1hdGguUEkgLSAyICogTWF0aC5QSSAvIGxldmVsLmxlbmd0aCA6IG9wdGlvbnMuc3dlZXA7XG4gICAgdmFyIGRUaGV0YSA9IGxldmVsLmRUaGV0YSA9IHN3ZWVwIC8gTWF0aC5tYXgoMSwgbGV2ZWwubGVuZ3RoIC0gMSk7IC8vIGNhbGN1bGF0ZSB0aGUgcmFkaXVzXG5cbiAgICBpZiAobGV2ZWwubGVuZ3RoID4gMSAmJiBvcHRpb25zLmF2b2lkT3ZlcmxhcCkge1xuICAgICAgLy8gYnV0IG9ubHkgaWYgbW9yZSB0aGFuIG9uZSBub2RlIChjYW4ndCBvdmVybGFwKVxuICAgICAgdmFyIGRjb3MgPSBNYXRoLmNvcyhkVGhldGEpIC0gTWF0aC5jb3MoMCk7XG4gICAgICB2YXIgZHNpbiA9IE1hdGguc2luKGRUaGV0YSkgLSBNYXRoLnNpbigwKTtcbiAgICAgIHZhciByTWluID0gTWF0aC5zcXJ0KG1pbkRpc3QgKiBtaW5EaXN0IC8gKGRjb3MgKiBkY29zICsgZHNpbiAqIGRzaW4pKTsgLy8gcy50LiBubyBub2RlcyBvdmVybGFwcGluZ1xuXG4gICAgICByID0gTWF0aC5tYXgock1pbiwgcik7XG4gICAgfVxuXG4gICAgbGV2ZWwuciA9IHI7XG4gICAgciArPSBtaW5EaXN0O1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuZXF1aWRpc3RhbnQpIHtcbiAgICB2YXIgckRlbHRhTWF4ID0gMDtcbiAgICB2YXIgX3IgPSAwO1xuXG4gICAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgbGV2ZWxzLmxlbmd0aDsgX2k0KyspIHtcbiAgICAgIHZhciBfbGV2ZWwgPSBsZXZlbHNbX2k0XTtcbiAgICAgIHZhciByRGVsdGEgPSBfbGV2ZWwuciAtIF9yO1xuICAgICAgckRlbHRhTWF4ID0gTWF0aC5tYXgockRlbHRhTWF4LCByRGVsdGEpO1xuICAgIH1cblxuICAgIF9yID0gMDtcblxuICAgIGZvciAodmFyIF9pNSA9IDA7IF9pNSA8IGxldmVscy5sZW5ndGg7IF9pNSsrKSB7XG4gICAgICB2YXIgX2xldmVsMiA9IGxldmVsc1tfaTVdO1xuXG4gICAgICBpZiAoX2k1ID09PSAwKSB7XG4gICAgICAgIF9yID0gX2xldmVsMi5yO1xuICAgICAgfVxuXG4gICAgICBfbGV2ZWwyLnIgPSBfcjtcbiAgICAgIF9yICs9IHJEZWx0YU1heDtcbiAgICB9XG4gIH0gLy8gY2FsY3VsYXRlIHRoZSBub2RlIHBvc2l0aW9uc1xuXG5cbiAgdmFyIHBvcyA9IHt9OyAvLyBpZCA9PiBwb3NpdGlvblxuXG4gIGZvciAodmFyIF9pNiA9IDA7IF9pNiA8IGxldmVscy5sZW5ndGg7IF9pNisrKSB7XG4gICAgdmFyIF9sZXZlbDMgPSBsZXZlbHNbX2k2XTtcbiAgICB2YXIgX2RUaGV0YSA9IF9sZXZlbDMuZFRoZXRhO1xuICAgIHZhciBfcjIgPSBfbGV2ZWwzLnI7XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IF9sZXZlbDMubGVuZ3RoOyBqKyspIHtcbiAgICAgIHZhciBfdmFsID0gX2xldmVsM1tqXTtcbiAgICAgIHZhciB0aGV0YSA9IG9wdGlvbnMuc3RhcnRBbmdsZSArIChjbG9ja3dpc2UgPyAxIDogLTEpICogX2RUaGV0YSAqIGo7XG4gICAgICB2YXIgcCA9IHtcbiAgICAgICAgeDogY2VudGVyLnggKyBfcjIgKiBNYXRoLmNvcyh0aGV0YSksXG4gICAgICAgIHk6IGNlbnRlci55ICsgX3IyICogTWF0aC5zaW4odGhldGEpXG4gICAgICB9O1xuICAgICAgcG9zW192YWwubm9kZS5pZCgpXSA9IHA7XG4gICAgfVxuICB9IC8vIHBvc2l0aW9uIHRoZSBub2Rlc1xuXG5cbiAgbm9kZXMubGF5b3V0UG9zaXRpb25zKHRoaXMsIG9wdGlvbnMsIGZ1bmN0aW9uIChlbGUpIHtcbiAgICB2YXIgaWQgPSBlbGUuaWQoKTtcbiAgICByZXR1cm4gcG9zW2lkXTtcbiAgfSk7XG4gIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xufTtcblxuLypcblRoZSBDb1NFIGxheW91dCB3YXMgd3JpdHRlbiBieSBHZXJhcmRvIEh1Y2suXG5odHRwczovL3d3dy5saW5rZWRpbi5jb20vaW4vZ2VyYXJkb2h1Y2svXG5cbkJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgYXJ0aWNsZTpcbmh0dHA6Ly9kbC5hY20ub3JnL2NpdGF0aW9uLmNmbT9pZD0xNDk4MDQ3XG5cbk1vZGlmaWNhdGlvbnMgdHJhY2tlZCBvbiBHaXRodWIuXG4qL1xudmFyIERFQlVHO1xuLyoqXG4gKiBAYnJpZWYgOiAgZGVmYXVsdCBsYXlvdXQgb3B0aW9uc1xuICovXG5cbnZhciBkZWZhdWx0cyRjID0ge1xuICAvLyBDYWxsZWQgb24gYGxheW91dHJlYWR5YFxuICByZWFkeTogZnVuY3Rpb24gcmVhZHkoKSB7fSxcbiAgLy8gQ2FsbGVkIG9uIGBsYXlvdXRzdG9wYFxuICBzdG9wOiBmdW5jdGlvbiBzdG9wKCkge30sXG4gIC8vIFdoZXRoZXIgdG8gYW5pbWF0ZSB3aGlsZSBydW5uaW5nIHRoZSBsYXlvdXRcbiAgLy8gdHJ1ZSA6IEFuaW1hdGUgY29udGludW91c2x5IGFzIHRoZSBsYXlvdXQgaXMgcnVubmluZ1xuICAvLyBmYWxzZSA6IEp1c3Qgc2hvdyB0aGUgZW5kIHJlc3VsdFxuICAvLyAnZW5kJyA6IEFuaW1hdGUgd2l0aCB0aGUgZW5kIHJlc3VsdCwgZnJvbSB0aGUgaW5pdGlhbCBwb3NpdGlvbnMgdG8gdGhlIGVuZCBwb3NpdGlvbnNcbiAgYW5pbWF0ZTogdHJ1ZSxcbiAgLy8gRWFzaW5nIG9mIHRoZSBhbmltYXRpb24gZm9yIGFuaW1hdGU6J2VuZCdcbiAgYW5pbWF0aW9uRWFzaW5nOiB1bmRlZmluZWQsXG4gIC8vIFRoZSBkdXJhdGlvbiBvZiB0aGUgYW5pbWF0aW9uIGZvciBhbmltYXRlOidlbmQnXG4gIGFuaW1hdGlvbkR1cmF0aW9uOiB1bmRlZmluZWQsXG4gIC8vIEEgZnVuY3Rpb24gdGhhdCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIG5vZGUgc2hvdWxkIGJlIGFuaW1hdGVkXG4gIC8vIEFsbCBub2RlcyBhbmltYXRlZCBieSBkZWZhdWx0IG9uIGFuaW1hdGUgZW5hYmxlZFxuICAvLyBOb24tYW5pbWF0ZWQgbm9kZXMgYXJlIHBvc2l0aW9uZWQgaW1tZWRpYXRlbHkgd2hlbiB0aGUgbGF5b3V0IHN0YXJ0c1xuICBhbmltYXRlRmlsdGVyOiBmdW5jdGlvbiBhbmltYXRlRmlsdGVyKG5vZGUsIGkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgLy8gVGhlIGxheW91dCBhbmltYXRlcyBvbmx5IGFmdGVyIHRoaXMgbWFueSBtaWxsaXNlY29uZHMgZm9yIGFuaW1hdGU6dHJ1ZVxuICAvLyAocHJldmVudHMgZmxhc2hpbmcgb24gZmFzdCBydW5zKVxuICBhbmltYXRpb25UaHJlc2hvbGQ6IDI1MCxcbiAgLy8gTnVtYmVyIG9mIGl0ZXJhdGlvbnMgYmV0d2VlbiBjb25zZWN1dGl2ZSBzY3JlZW4gcG9zaXRpb25zIHVwZGF0ZVxuICByZWZyZXNoOiAyMCxcbiAgLy8gV2hldGhlciB0byBmaXQgdGhlIG5ldHdvcmsgdmlldyBhZnRlciB3aGVuIGRvbmVcbiAgZml0OiB0cnVlLFxuICAvLyBQYWRkaW5nIG9uIGZpdFxuICBwYWRkaW5nOiAzMCxcbiAgLy8gQ29uc3RyYWluIGxheW91dCBib3VuZHM7IHsgeDEsIHkxLCB4MiwgeTIgfSBvciB7IHgxLCB5MSwgdywgaCB9XG4gIGJvdW5kaW5nQm94OiB1bmRlZmluZWQsXG4gIC8vIEV4Y2x1ZGVzIHRoZSBsYWJlbCB3aGVuIGNhbGN1bGF0aW5nIG5vZGUgYm91bmRpbmcgYm94ZXMgZm9yIHRoZSBsYXlvdXQgYWxnb3JpdGhtXG4gIG5vZGVEaW1lbnNpb25zSW5jbHVkZUxhYmVsczogZmFsc2UsXG4gIC8vIFJhbmRvbWl6ZSB0aGUgaW5pdGlhbCBwb3NpdGlvbnMgb2YgdGhlIG5vZGVzICh0cnVlKSBvciB1c2UgZXhpc3RpbmcgcG9zaXRpb25zIChmYWxzZSlcbiAgcmFuZG9taXplOiBmYWxzZSxcbiAgLy8gRXh0cmEgc3BhY2luZyBiZXR3ZWVuIGNvbXBvbmVudHMgaW4gbm9uLWNvbXBvdW5kIGdyYXBoc1xuICBjb21wb25lbnRTcGFjaW5nOiA0MCxcbiAgLy8gTm9kZSByZXB1bHNpb24gKG5vbiBvdmVybGFwcGluZykgbXVsdGlwbGllclxuICBub2RlUmVwdWxzaW9uOiBmdW5jdGlvbiBub2RlUmVwdWxzaW9uKG5vZGUpIHtcbiAgICByZXR1cm4gMjA0ODtcbiAgfSxcbiAgLy8gTm9kZSByZXB1bHNpb24gKG92ZXJsYXBwaW5nKSBtdWx0aXBsaWVyXG4gIG5vZGVPdmVybGFwOiA0LFxuICAvLyBJZGVhbCBlZGdlIChub24gbmVzdGVkKSBsZW5ndGhcbiAgaWRlYWxFZGdlTGVuZ3RoOiBmdW5jdGlvbiBpZGVhbEVkZ2VMZW5ndGgoZWRnZSkge1xuICAgIHJldHVybiAzMjtcbiAgfSxcbiAgLy8gRGl2aXNvciB0byBjb21wdXRlIGVkZ2UgZm9yY2VzXG4gIGVkZ2VFbGFzdGljaXR5OiBmdW5jdGlvbiBlZGdlRWxhc3RpY2l0eShlZGdlKSB7XG4gICAgcmV0dXJuIDMyO1xuICB9LFxuICAvLyBOZXN0aW5nIGZhY3RvciAobXVsdGlwbGllcikgdG8gY29tcHV0ZSBpZGVhbCBlZGdlIGxlbmd0aCBmb3IgbmVzdGVkIGVkZ2VzXG4gIG5lc3RpbmdGYWN0b3I6IDEuMixcbiAgLy8gR3Jhdml0eSBmb3JjZSAoY29uc3RhbnQpXG4gIGdyYXZpdHk6IDEsXG4gIC8vIE1heGltdW0gbnVtYmVyIG9mIGl0ZXJhdGlvbnMgdG8gcGVyZm9ybVxuICBudW1JdGVyOiAxMDAwLFxuICAvLyBJbml0aWFsIHRlbXBlcmF0dXJlIChtYXhpbXVtIG5vZGUgZGlzcGxhY2VtZW50KVxuICBpbml0aWFsVGVtcDogMTAwMCxcbiAgLy8gQ29vbGluZyBmYWN0b3IgKGhvdyB0aGUgdGVtcGVyYXR1cmUgaXMgcmVkdWNlZCBiZXR3ZWVuIGNvbnNlY3V0aXZlIGl0ZXJhdGlvbnNcbiAgY29vbGluZ0ZhY3RvcjogMC45OSxcbiAgLy8gTG93ZXIgdGVtcGVyYXR1cmUgdGhyZXNob2xkIChiZWxvdyB0aGlzIHBvaW50IHRoZSBsYXlvdXQgd2lsbCBlbmQpXG4gIG1pblRlbXA6IDEuMFxufTtcbi8qKlxuICogQGJyaWVmICAgICAgIDogY29uc3RydWN0b3JcbiAqIEBhcmcgb3B0aW9ucyA6IG9iamVjdCBjb250YWluaW5nIGxheW91dCBvcHRpb25zXG4gKi9cblxuZnVuY3Rpb24gQ29zZUxheW91dChvcHRpb25zKSB7XG4gIHRoaXMub3B0aW9ucyA9IGV4dGVuZCh7fSwgZGVmYXVsdHMkYywgb3B0aW9ucyk7XG4gIHRoaXMub3B0aW9ucy5sYXlvdXQgPSB0aGlzO1xufVxuLyoqXG4gKiBAYnJpZWYgOiBydW5zIHRoZSBsYXlvdXRcbiAqL1xuXG5cbkNvc2VMYXlvdXQucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gIHZhciBjeSA9IG9wdGlvbnMuY3k7XG4gIHZhciBsYXlvdXQgPSB0aGlzO1xuICBsYXlvdXQuc3RvcHBlZCA9IGZhbHNlO1xuXG4gIGlmIChvcHRpb25zLmFuaW1hdGUgPT09IHRydWUgfHwgb3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSkge1xuICAgIGxheW91dC5lbWl0KHtcbiAgICAgIHR5cGU6ICdsYXlvdXRzdGFydCcsXG4gICAgICBsYXlvdXQ6IGxheW91dFxuICAgIH0pO1xuICB9IC8vIFNldCBERUJVRyAtIEdsb2JhbCB2YXJpYWJsZVxuXG5cbiAgaWYgKHRydWUgPT09IG9wdGlvbnMuZGVidWcpIHtcbiAgICBERUJVRyA9IHRydWU7XG4gIH0gZWxzZSB7XG4gICAgREVCVUcgPSBmYWxzZTtcbiAgfSAvLyBJbml0aWFsaXplIGxheW91dCBpbmZvXG5cblxuICB2YXIgbGF5b3V0SW5mbyA9IGNyZWF0ZUxheW91dEluZm8oY3ksIGxheW91dCwgb3B0aW9ucyk7IC8vIFNob3cgTGF5b3V0SW5mbyBjb250ZW50cyBpZiBkZWJ1Z2dpbmdcblxuICBpZiAoREVCVUcpIHtcbiAgICBwcmludExheW91dEluZm8obGF5b3V0SW5mbyk7XG4gIH0gLy8gSWYgcmVxdWlyZWQsIHJhbmRvbWl6ZSBub2RlIHBvc2l0aW9uc1xuXG5cbiAgaWYgKG9wdGlvbnMucmFuZG9taXplKSB7XG4gICAgcmFuZG9taXplUG9zaXRpb25zKGxheW91dEluZm8pO1xuICB9XG5cbiAgdmFyIHN0YXJ0VGltZSA9IHBlcmZvcm1hbmNlTm93KCk7XG5cbiAgdmFyIHJlZnJlc2ggPSBmdW5jdGlvbiByZWZyZXNoKCkge1xuICAgIHJlZnJlc2hQb3NpdGlvbnMobGF5b3V0SW5mbywgY3ksIG9wdGlvbnMpOyAvLyBGaXQgdGhlIGdyYXBoIGlmIG5lY2Vzc2FyeVxuXG4gICAgaWYgKHRydWUgPT09IG9wdGlvbnMuZml0KSB7XG4gICAgICBjeS5maXQob3B0aW9ucy5wYWRkaW5nKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIG1haW5Mb29wID0gZnVuY3Rpb24gbWFpbkxvb3AoaSkge1xuICAgIGlmIChsYXlvdXQuc3RvcHBlZCB8fCBpID49IG9wdGlvbnMubnVtSXRlcikge1xuICAgICAgLy8gbG9nRGVidWcoXCJMYXlvdXQgbWFudWFsbHkgc3RvcHBlZC4gU3RvcHBpbmcgY29tcHV0YXRpb24gaW4gc3RlcCBcIiArIGkpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gLy8gRG8gb25lIHN0ZXAgaW4gdGhlIHBoaXNpY2FsIHNpbXVsYXRpb25cblxuXG4gICAgc3RlcCQxKGxheW91dEluZm8sIG9wdGlvbnMpOyAvLyBVcGRhdGUgdGVtcGVyYXR1cmVcblxuICAgIGxheW91dEluZm8udGVtcGVyYXR1cmUgPSBsYXlvdXRJbmZvLnRlbXBlcmF0dXJlICogb3B0aW9ucy5jb29saW5nRmFjdG9yOyAvLyBsb2dEZWJ1ZyhcIk5ldyB0ZW1wZXJhdHVyZTogXCIgKyBsYXlvdXRJbmZvLnRlbXBlcmF0dXJlKTtcblxuICAgIGlmIChsYXlvdXRJbmZvLnRlbXBlcmF0dXJlIDwgb3B0aW9ucy5taW5UZW1wKSB7XG4gICAgICAvLyBsb2dEZWJ1ZyhcIlRlbXBlcmF0dXJlIGRyb3AgYmVsb3cgbWluaW11bSB0aHJlc2hvbGQuIFN0b3BwaW5nIGNvbXB1dGF0aW9uIGluIHN0ZXAgXCIgKyBpKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICB2YXIgZG9uZSA9IGZ1bmN0aW9uIGRvbmUoKSB7XG4gICAgaWYgKG9wdGlvbnMuYW5pbWF0ZSA9PT0gdHJ1ZSB8fCBvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlKSB7XG4gICAgICByZWZyZXNoKCk7IC8vIExheW91dCBoYXMgZmluaXNoZWRcblxuICAgICAgbGF5b3V0Lm9uZSgnbGF5b3V0c3RvcCcsIG9wdGlvbnMuc3RvcCk7XG4gICAgICBsYXlvdXQuZW1pdCh7XG4gICAgICAgIHR5cGU6ICdsYXlvdXRzdG9wJyxcbiAgICAgICAgbGF5b3V0OiBsYXlvdXRcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgbm9kZXMgPSBvcHRpb25zLmVsZXMubm9kZXMoKTtcbiAgICAgIHZhciBnZXRTY2FsZWRQb3MgPSBnZXRTY2FsZUluQm91bmRzRm4obGF5b3V0SW5mbywgb3B0aW9ucywgbm9kZXMpO1xuICAgICAgbm9kZXMubGF5b3V0UG9zaXRpb25zKGxheW91dCwgb3B0aW9ucywgZ2V0U2NhbGVkUG9zKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGkgPSAwO1xuICB2YXIgbG9vcFJldCA9IHRydWU7XG5cbiAgaWYgKG9wdGlvbnMuYW5pbWF0ZSA9PT0gdHJ1ZSkge1xuICAgIHZhciBmcmFtZSA9IGZ1bmN0aW9uIGZyYW1lKCkge1xuICAgICAgdmFyIGYgPSAwO1xuXG4gICAgICB3aGlsZSAobG9vcFJldCAmJiBmIDwgb3B0aW9ucy5yZWZyZXNoKSB7XG4gICAgICAgIGxvb3BSZXQgPSBtYWluTG9vcChpKTtcbiAgICAgICAgaSsrO1xuICAgICAgICBmKys7XG4gICAgICB9XG5cbiAgICAgIGlmICghbG9vcFJldCkge1xuICAgICAgICAvLyBpdCdzIGRvbmVcbiAgICAgICAgc2VwYXJhdGVDb21wb25lbnRzKGxheW91dEluZm8sIG9wdGlvbnMpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbm93ID0gcGVyZm9ybWFuY2VOb3coKTtcblxuICAgICAgICBpZiAobm93IC0gc3RhcnRUaW1lID49IG9wdGlvbnMuYW5pbWF0aW9uVGhyZXNob2xkKSB7XG4gICAgICAgICAgcmVmcmVzaCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZyYW1lKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZnJhbWUoKTtcbiAgfSBlbHNlIHtcbiAgICB3aGlsZSAobG9vcFJldCkge1xuICAgICAgbG9vcFJldCA9IG1haW5Mb29wKGkpO1xuICAgICAgaSsrO1xuICAgIH1cblxuICAgIHNlcGFyYXRlQ29tcG9uZW50cyhsYXlvdXRJbmZvLCBvcHRpb25zKTtcbiAgICBkb25lKCk7XG4gIH1cblxuICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbn07XG4vKipcbiAqIEBicmllZiA6IGNhbGxlZCBvbiBjb250aW51b3VzIGxheW91dHMgdG8gc3RvcCB0aGVtIGJlZm9yZSB0aGV5IGZpbmlzaFxuICovXG5cblxuQ29zZUxheW91dC5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5zdG9wcGVkID0gdHJ1ZTtcblxuICBpZiAodGhpcy50aHJlYWQpIHtcbiAgICB0aGlzLnRocmVhZC5zdG9wKCk7XG4gIH1cblxuICB0aGlzLmVtaXQoJ2xheW91dHN0b3AnKTtcbiAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG59O1xuXG5Db3NlTGF5b3V0LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICBpZiAodGhpcy50aHJlYWQpIHtcbiAgICB0aGlzLnRocmVhZC5zdG9wKCk7XG4gIH1cblxuICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbn07XG4vKipcbiAqIEBicmllZiAgICAgOiBDcmVhdGVzIGFuIG9iamVjdCB3aGljaCBpcyBjb250YWlucyBhbGwgdGhlIGRhdGFcbiAqICAgICAgICAgICAgICB1c2VkIGluIHRoZSBsYXlvdXQgcHJvY2Vzc1xuICogQGFyZyBjeSAgICA6IGN5dG9zY2FwZS5qcyBvYmplY3RcbiAqIEByZXR1cm4gICAgOiBsYXlvdXRJbmZvIG9iamVjdCBpbml0aWFsaXplZFxuICovXG5cblxudmFyIGNyZWF0ZUxheW91dEluZm8gPSBmdW5jdGlvbiBjcmVhdGVMYXlvdXRJbmZvKGN5LCBsYXlvdXQsIG9wdGlvbnMpIHtcbiAgLy8gU2hvcnRjdXRcbiAgdmFyIGVkZ2VzID0gb3B0aW9ucy5lbGVzLmVkZ2VzKCk7XG4gIHZhciBub2RlcyA9IG9wdGlvbnMuZWxlcy5ub2RlcygpO1xuICB2YXIgbGF5b3V0SW5mbyA9IHtcbiAgICBpc0NvbXBvdW5kOiBjeS5oYXNDb21wb3VuZE5vZGVzKCksXG4gICAgbGF5b3V0Tm9kZXM6IFtdLFxuICAgIGlkVG9JbmRleDoge30sXG4gICAgbm9kZVNpemU6IG5vZGVzLnNpemUoKSxcbiAgICBncmFwaFNldDogW10sXG4gICAgaW5kZXhUb0dyYXBoOiBbXSxcbiAgICBsYXlvdXRFZGdlczogW10sXG4gICAgZWRnZVNpemU6IGVkZ2VzLnNpemUoKSxcbiAgICB0ZW1wZXJhdHVyZTogb3B0aW9ucy5pbml0aWFsVGVtcCxcbiAgICBjbGllbnRXaWR0aDogY3kud2lkdGgoKSxcbiAgICBjbGllbnRIZWlnaHQ6IGN5LndpZHRoKCksXG4gICAgYm91bmRpbmdCb3g6IG1ha2VCb3VuZGluZ0JveChvcHRpb25zLmJvdW5kaW5nQm94ID8gb3B0aW9ucy5ib3VuZGluZ0JveCA6IHtcbiAgICAgIHgxOiAwLFxuICAgICAgeTE6IDAsXG4gICAgICB3OiBjeS53aWR0aCgpLFxuICAgICAgaDogY3kuaGVpZ2h0KClcbiAgICB9KVxuICB9O1xuICB2YXIgY29tcG9uZW50cyA9IG9wdGlvbnMuZWxlcy5jb21wb25lbnRzKCk7XG4gIHZhciBpZDJjbXB0SWQgPSB7fTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbXBvbmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgY29tcG9uZW50ID0gY29tcG9uZW50c1tpXTtcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgY29tcG9uZW50Lmxlbmd0aDsgaisrKSB7XG4gICAgICB2YXIgbm9kZSA9IGNvbXBvbmVudFtqXTtcbiAgICAgIGlkMmNtcHRJZFtub2RlLmlkKCldID0gaTtcbiAgICB9XG4gIH0gLy8gSXRlcmF0ZSBvdmVyIGFsbCBub2RlcywgY3JlYXRpbmcgbGF5b3V0IG5vZGVzXG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxheW91dEluZm8ubm9kZVNpemU7IGkrKykge1xuICAgIHZhciBuID0gbm9kZXNbaV07XG4gICAgdmFyIG5iYiA9IG4ubGF5b3V0RGltZW5zaW9ucyhvcHRpb25zKTtcbiAgICB2YXIgdGVtcE5vZGUgPSB7fTtcbiAgICB0ZW1wTm9kZS5pc0xvY2tlZCA9IG4ubG9ja2VkKCk7XG4gICAgdGVtcE5vZGUuaWQgPSBuLmRhdGEoJ2lkJyk7XG4gICAgdGVtcE5vZGUucGFyZW50SWQgPSBuLmRhdGEoJ3BhcmVudCcpO1xuICAgIHRlbXBOb2RlLmNtcHRJZCA9IGlkMmNtcHRJZFtuLmlkKCldO1xuICAgIHRlbXBOb2RlLmNoaWxkcmVuID0gW107XG4gICAgdGVtcE5vZGUucG9zaXRpb25YID0gbi5wb3NpdGlvbigneCcpO1xuICAgIHRlbXBOb2RlLnBvc2l0aW9uWSA9IG4ucG9zaXRpb24oJ3knKTtcbiAgICB0ZW1wTm9kZS5vZmZzZXRYID0gMDtcbiAgICB0ZW1wTm9kZS5vZmZzZXRZID0gMDtcbiAgICB0ZW1wTm9kZS5oZWlnaHQgPSBuYmIudztcbiAgICB0ZW1wTm9kZS53aWR0aCA9IG5iYi5oO1xuICAgIHRlbXBOb2RlLm1heFggPSB0ZW1wTm9kZS5wb3NpdGlvblggKyB0ZW1wTm9kZS53aWR0aCAvIDI7XG4gICAgdGVtcE5vZGUubWluWCA9IHRlbXBOb2RlLnBvc2l0aW9uWCAtIHRlbXBOb2RlLndpZHRoIC8gMjtcbiAgICB0ZW1wTm9kZS5tYXhZID0gdGVtcE5vZGUucG9zaXRpb25ZICsgdGVtcE5vZGUuaGVpZ2h0IC8gMjtcbiAgICB0ZW1wTm9kZS5taW5ZID0gdGVtcE5vZGUucG9zaXRpb25ZIC0gdGVtcE5vZGUuaGVpZ2h0IC8gMjtcbiAgICB0ZW1wTm9kZS5wYWRMZWZ0ID0gcGFyc2VGbG9hdChuLnN0eWxlKCdwYWRkaW5nJykpO1xuICAgIHRlbXBOb2RlLnBhZFJpZ2h0ID0gcGFyc2VGbG9hdChuLnN0eWxlKCdwYWRkaW5nJykpO1xuICAgIHRlbXBOb2RlLnBhZFRvcCA9IHBhcnNlRmxvYXQobi5zdHlsZSgncGFkZGluZycpKTtcbiAgICB0ZW1wTm9kZS5wYWRCb3R0b20gPSBwYXJzZUZsb2F0KG4uc3R5bGUoJ3BhZGRpbmcnKSk7IC8vIGZvcmNlc1xuXG4gICAgdGVtcE5vZGUubm9kZVJlcHVsc2lvbiA9IGZuKG9wdGlvbnMubm9kZVJlcHVsc2lvbikgPyBvcHRpb25zLm5vZGVSZXB1bHNpb24obikgOiBvcHRpb25zLm5vZGVSZXB1bHNpb247IC8vIEFkZCBuZXcgbm9kZVxuXG4gICAgbGF5b3V0SW5mby5sYXlvdXROb2Rlcy5wdXNoKHRlbXBOb2RlKTsgLy8gQWRkIGVudHJ5IHRvIGlkLWluZGV4IG1hcFxuXG4gICAgbGF5b3V0SW5mby5pZFRvSW5kZXhbdGVtcE5vZGUuaWRdID0gaTtcbiAgfSAvLyBJbmxpbmUgaW1wbGVtZW50YXRpb24gb2YgYSBxdWV1ZSwgdXNlZCBmb3IgdHJhdmVyc2luZyB0aGUgZ3JhcGggaW4gQkZTIG9yZGVyXG5cblxuICB2YXIgcXVldWUgPSBbXTtcbiAgdmFyIHN0YXJ0ID0gMDsgLy8gUG9pbnRzIHRvIHRoZSBzdGFydCB0aGUgcXVldWVcblxuICB2YXIgZW5kID0gLTE7IC8vIFBvaW50cyB0byB0aGUgZW5kIG9mIHRoZSBxdWV1ZVxuXG4gIHZhciB0ZW1wR3JhcGggPSBbXTsgLy8gU2Vjb25kIHBhc3MgdG8gYWRkIGNoaWxkIGluZm9ybWF0aW9uIGFuZFxuICAvLyBpbml0aWFsaXplIHF1ZXVlIGZvciBoaWVyYXJjaGljYWwgdHJhdmVyc2FsXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXlvdXRJbmZvLm5vZGVTaXplOyBpKyspIHtcbiAgICB2YXIgbiA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXNbaV07XG4gICAgdmFyIHBfaWQgPSBuLnBhcmVudElkOyAvLyBDaGVjayBpZiBub2RlIG4gaGFzIGEgcGFyZW50IG5vZGVcblxuICAgIGlmIChudWxsICE9IHBfaWQpIHtcbiAgICAgIC8vIEFkZCBub2RlIElkIHRvIHBhcmVudCdzIGxpc3Qgb2YgY2hpbGRyZW5cbiAgICAgIGxheW91dEluZm8ubGF5b3V0Tm9kZXNbbGF5b3V0SW5mby5pZFRvSW5kZXhbcF9pZF1dLmNoaWxkcmVuLnB1c2gobi5pZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIGEgbm9kZSBkb2Vzbid0IGhhdmUgYSBwYXJlbnQsIHRoZW4gaXQncyBpbiB0aGUgcm9vdCBncmFwaFxuICAgICAgcXVldWVbKytlbmRdID0gbi5pZDtcbiAgICAgIHRlbXBHcmFwaC5wdXNoKG4uaWQpO1xuICAgIH1cbiAgfSAvLyBBZGQgcm9vdCBncmFwaCB0byBncmFwaFNldFxuXG5cbiAgbGF5b3V0SW5mby5ncmFwaFNldC5wdXNoKHRlbXBHcmFwaCk7IC8vIFRyYXZlcnNlIHRoZSBncmFwaCwgbGV2ZWwgYnkgbGV2ZWwsXG5cbiAgd2hpbGUgKHN0YXJ0IDw9IGVuZCkge1xuICAgIC8vIEdldCB0aGUgbm9kZSB0byB2aXNpdCBhbmQgcmVtb3ZlIGl0IGZyb20gcXVldWVcbiAgICB2YXIgbm9kZV9pZCA9IHF1ZXVlW3N0YXJ0KytdO1xuICAgIHZhciBub2RlX2l4ID0gbGF5b3V0SW5mby5pZFRvSW5kZXhbbm9kZV9pZF07XG4gICAgdmFyIG5vZGUgPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW25vZGVfaXhdO1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW47XG5cbiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgLy8gQWRkIGNoaWxkcmVuIG5vZGVzIGFzIGEgbmV3IGdyYXBoIHRvIGdyYXBoIHNldFxuICAgICAgbGF5b3V0SW5mby5ncmFwaFNldC5wdXNoKGNoaWxkcmVuKTsgLy8gQWRkIGNoaWxkcmVuIHRvIHF1ZSBxdWV1ZSB0byBiZSB2aXNpdGVkXG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcXVldWVbKytlbmRdID0gY2hpbGRyZW5baV07XG4gICAgICB9XG4gICAgfVxuICB9IC8vIENyZWF0ZSBpbmRleFRvR3JhcGggbWFwXG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxheW91dEluZm8uZ3JhcGhTZXQubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZ3JhcGggPSBsYXlvdXRJbmZvLmdyYXBoU2V0W2ldO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBncmFwaC5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIGluZGV4ID0gbGF5b3V0SW5mby5pZFRvSW5kZXhbZ3JhcGhbal1dO1xuICAgICAgbGF5b3V0SW5mby5pbmRleFRvR3JhcGhbaW5kZXhdID0gaTtcbiAgICB9XG4gIH0gLy8gSXRlcmF0ZSBvdmVyIGFsbCBlZGdlcywgY3JlYXRpbmcgTGF5b3V0IEVkZ2VzXG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxheW91dEluZm8uZWRnZVNpemU7IGkrKykge1xuICAgIHZhciBlID0gZWRnZXNbaV07XG4gICAgdmFyIHRlbXBFZGdlID0ge307XG4gICAgdGVtcEVkZ2UuaWQgPSBlLmRhdGEoJ2lkJyk7XG4gICAgdGVtcEVkZ2Uuc291cmNlSWQgPSBlLmRhdGEoJ3NvdXJjZScpO1xuICAgIHRlbXBFZGdlLnRhcmdldElkID0gZS5kYXRhKCd0YXJnZXQnKTsgLy8gQ29tcHV0ZSBpZGVhbCBsZW5ndGhcblxuICAgIHZhciBpZGVhbExlbmd0aCA9IGZuKG9wdGlvbnMuaWRlYWxFZGdlTGVuZ3RoKSA/IG9wdGlvbnMuaWRlYWxFZGdlTGVuZ3RoKGUpIDogb3B0aW9ucy5pZGVhbEVkZ2VMZW5ndGg7XG4gICAgdmFyIGVsYXN0aWNpdHkgPSBmbihvcHRpb25zLmVkZ2VFbGFzdGljaXR5KSA/IG9wdGlvbnMuZWRnZUVsYXN0aWNpdHkoZSkgOiBvcHRpb25zLmVkZ2VFbGFzdGljaXR5OyAvLyBDaGVjayBpZiBpdCdzIGFuIGludGVyIGdyYXBoIGVkZ2VcblxuICAgIHZhciBzb3VyY2VJeCA9IGxheW91dEluZm8uaWRUb0luZGV4W3RlbXBFZGdlLnNvdXJjZUlkXTtcbiAgICB2YXIgdGFyZ2V0SXggPSBsYXlvdXRJbmZvLmlkVG9JbmRleFt0ZW1wRWRnZS50YXJnZXRJZF07XG4gICAgdmFyIHNvdXJjZUdyYXBoID0gbGF5b3V0SW5mby5pbmRleFRvR3JhcGhbc291cmNlSXhdO1xuICAgIHZhciB0YXJnZXRHcmFwaCA9IGxheW91dEluZm8uaW5kZXhUb0dyYXBoW3RhcmdldEl4XTtcblxuICAgIGlmIChzb3VyY2VHcmFwaCAhPSB0YXJnZXRHcmFwaCkge1xuICAgICAgLy8gRmluZCBsb3dlc3QgY29tbW9uIGdyYXBoIGFuY2VzdG9yXG4gICAgICB2YXIgbGNhID0gZmluZExDQSh0ZW1wRWRnZS5zb3VyY2VJZCwgdGVtcEVkZ2UudGFyZ2V0SWQsIGxheW91dEluZm8pOyAvLyBDb21wdXRlIHN1bSBvZiBub2RlIGRlcHRocywgcmVsYXRpdmUgdG8gbGNhIGdyYXBoXG5cbiAgICAgIHZhciBsY2FHcmFwaCA9IGxheW91dEluZm8uZ3JhcGhTZXRbbGNhXTtcbiAgICAgIHZhciBkZXB0aCA9IDA7IC8vIFNvdXJjZSBkZXB0aFxuXG4gICAgICB2YXIgdGVtcE5vZGUgPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW3NvdXJjZUl4XTtcblxuICAgICAgd2hpbGUgKC0xID09PSBsY2FHcmFwaC5pbmRleE9mKHRlbXBOb2RlLmlkKSkge1xuICAgICAgICB0ZW1wTm9kZSA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXNbbGF5b3V0SW5mby5pZFRvSW5kZXhbdGVtcE5vZGUucGFyZW50SWRdXTtcbiAgICAgICAgZGVwdGgrKztcbiAgICAgIH0gLy8gVGFyZ2V0IGRlcHRoXG5cblxuICAgICAgdGVtcE5vZGUgPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW3RhcmdldEl4XTtcblxuICAgICAgd2hpbGUgKC0xID09PSBsY2FHcmFwaC5pbmRleE9mKHRlbXBOb2RlLmlkKSkge1xuICAgICAgICB0ZW1wTm9kZSA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXNbbGF5b3V0SW5mby5pZFRvSW5kZXhbdGVtcE5vZGUucGFyZW50SWRdXTtcbiAgICAgICAgZGVwdGgrKztcbiAgICAgIH0gLy8gbG9nRGVidWcoJ0xDQSBvZiBub2RlcyAnICsgdGVtcEVkZ2Uuc291cmNlSWQgKyAnIGFuZCAnICsgdGVtcEVkZ2UudGFyZ2V0SWQgK1xuICAgICAgLy8gIFwiLiBJbmRleDogXCIgKyBsY2EgKyBcIiBDb250ZW50czogXCIgKyBsY2FHcmFwaC50b1N0cmluZygpICtcbiAgICAgIC8vICBcIi4gRGVwdGg6IFwiICsgZGVwdGgpO1xuICAgICAgLy8gVXBkYXRlIGlkZWFsTGVuZ3RoXG5cblxuICAgICAgaWRlYWxMZW5ndGggKj0gZGVwdGggKiBvcHRpb25zLm5lc3RpbmdGYWN0b3I7XG4gICAgfVxuXG4gICAgdGVtcEVkZ2UuaWRlYWxMZW5ndGggPSBpZGVhbExlbmd0aDtcbiAgICB0ZW1wRWRnZS5lbGFzdGljaXR5ID0gZWxhc3RpY2l0eTtcbiAgICBsYXlvdXRJbmZvLmxheW91dEVkZ2VzLnB1c2godGVtcEVkZ2UpO1xuICB9IC8vIEZpbmFsbHksIHJldHVybiBsYXlvdXRJbmZvIG9iamVjdFxuXG5cbiAgcmV0dXJuIGxheW91dEluZm87XG59O1xuLyoqXG4gKiBAYnJpZWYgOiBUaGlzIGZ1bmN0aW9uIGZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbG93ZXN0IGNvbW1vblxuICogICAgICAgICAgZ3JhcGggYW5jZXN0b3IgYmV0d2VlbiAyIG5vZGVzIGluIHRoZSBzdWJ0cmVlXG4gKiAgICAgICAgICAoZnJvbSB0aGUgZ3JhcGggaGllcmFyY2h5IGluZHVjZWQgdHJlZSkgd2hvc2VcbiAqICAgICAgICAgIHJvb3QgaXMgZ3JhcGhJeFxuICpcbiAqIEBhcmcgbm9kZTE6IG5vZGUxJ3MgSURcbiAqIEBhcmcgbm9kZTI6IG5vZGUyJ3MgSURcbiAqIEBhcmcgbGF5b3V0SW5mbzogbGF5b3V0SW5mbyBvYmplY3RcbiAqXG4gKi9cblxuXG52YXIgZmluZExDQSA9IGZ1bmN0aW9uIGZpbmRMQ0Eobm9kZTEsIG5vZGUyLCBsYXlvdXRJbmZvKSB7XG4gIC8vIEZpbmQgdGhlaXIgY29tbW9uIGFuY2VzdGVyLCBzdGFydGluZyBmcm9tIHRoZSByb290IGdyYXBoXG4gIHZhciByZXMgPSBmaW5kTENBX2F1eChub2RlMSwgbm9kZTIsIDAsIGxheW91dEluZm8pO1xuXG4gIGlmICgyID4gcmVzLmNvdW50KSB7XG4gICAgLy8gSWYgYXV4IGZ1bmN0aW9uIGNvdWxkbid0IGZpbmQgdGhlIGNvbW1vbiBhbmNlc3RlcixcbiAgICAvLyB0aGVuIGl0IGlzIHRoZSByb290IGdyYXBoXG4gICAgcmV0dXJuIDA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlcy5ncmFwaDtcbiAgfVxufTtcbi8qKlxuICogQGJyaWVmICAgICAgICAgIDogQXV4aWxpYXJ5IGZ1bmN0aW9uIHVzZWQgZm9yIExDQSBjb21wdXRhdGlvblxuICpcbiAqIEBhcmcgbm9kZTEgICAgICA6IG5vZGUxJ3MgSURcbiAqIEBhcmcgbm9kZTIgICAgICA6IG5vZGUyJ3MgSURcbiAqIEBhcmcgZ3JhcGhJeCAgICA6IHN1YmdyYXBoIGluZGV4XG4gKiBAYXJnIGxheW91dEluZm8gOiBsYXlvdXRJbmZvIG9iamVjdFxuICpcbiAqIEByZXR1cm4gICAgICAgICA6IG9iamVjdCBvZiB0aGUgZm9ybSB7Y291bnQ6IFgsIGdyYXBoOiBZfSwgd2hlcmU6XG4gKiAgICAgICAgICAgICAgICAgICBYIGlzIHRoZSBudW1iZXIgb2YgYW5jZXN0ZXJzIChtYXg6IDIpIGZvdW5kIGluXG4gKiAgICAgICAgICAgICAgICAgICBncmFwaEl4IChhbmQgaXQncyBzdWJncmFwaHMpLFxuICogICAgICAgICAgICAgICAgICAgWSBpcyB0aGUgZ3JhcGggaW5kZXggb2YgdGhlIGxvd2VzdCBncmFwaCBjb250YWluaW5nXG4gKiAgICAgICAgICAgICAgICAgICBhbGwgWCBub2Rlc1xuICovXG5cblxudmFyIGZpbmRMQ0FfYXV4ID0gZnVuY3Rpb24gZmluZExDQV9hdXgobm9kZTEsIG5vZGUyLCBncmFwaEl4LCBsYXlvdXRJbmZvKSB7XG4gIHZhciBncmFwaCA9IGxheW91dEluZm8uZ3JhcGhTZXRbZ3JhcGhJeF07IC8vIElmIGJvdGggbm9kZXMgYmVsb25ncyB0byBncmFwaEl4XG5cbiAgaWYgKC0xIDwgZ3JhcGguaW5kZXhPZihub2RlMSkgJiYgLTEgPCBncmFwaC5pbmRleE9mKG5vZGUyKSkge1xuICAgIHJldHVybiB7XG4gICAgICBjb3VudDogMixcbiAgICAgIGdyYXBoOiBncmFwaEl4XG4gICAgfTtcbiAgfSAvLyBNYWtlIHJlY3Vyc2l2ZSBjYWxscyBmb3IgYWxsIHN1YmdyYXBoc1xuXG5cbiAgdmFyIGMgPSAwO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZ3JhcGgubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgbm9kZUlkID0gZ3JhcGhbaV07XG4gICAgdmFyIG5vZGVJeCA9IGxheW91dEluZm8uaWRUb0luZGV4W25vZGVJZF07XG4gICAgdmFyIGNoaWxkcmVuID0gbGF5b3V0SW5mby5sYXlvdXROb2Rlc1tub2RlSXhdLmNoaWxkcmVuOyAvLyBJZiB0aGUgbm9kZSBoYXMgbm8gY2hpbGQsIHNraXAgaXRcblxuICAgIGlmICgwID09PSBjaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBjaGlsZEdyYXBoSXggPSBsYXlvdXRJbmZvLmluZGV4VG9HcmFwaFtsYXlvdXRJbmZvLmlkVG9JbmRleFtjaGlsZHJlblswXV1dO1xuICAgIHZhciByZXN1bHQgPSBmaW5kTENBX2F1eChub2RlMSwgbm9kZTIsIGNoaWxkR3JhcGhJeCwgbGF5b3V0SW5mbyk7XG5cbiAgICBpZiAoMCA9PT0gcmVzdWx0LmNvdW50KSB7XG4gICAgICAvLyBOZWl0aGVyIG5vZGUxIG5vciBub2RlMiBhcmUgcHJlc2VudCBpbiB0aGlzIHN1YmdyYXBoXG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2UgaWYgKDEgPT09IHJlc3VsdC5jb3VudCkge1xuICAgICAgLy8gT25lIG9mIChub2RlMSwgbm9kZTIpIGlzIHByZXNlbnQgaW4gdGhpcyBzdWJncmFwaFxuICAgICAgYysrO1xuXG4gICAgICBpZiAoMiA9PT0gYykge1xuICAgICAgICAvLyBXZSd2ZSBhbHJlYWR5IGZvdW5kIGJvdGggbm9kZXMsIG5vIG5lZWQgdG8ga2VlcCBzZWFyY2hpbmdcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEJvdGggbm9kZXMgYXJlIHByZXNlbnQgaW4gdGhpcyBzdWJncmFwaFxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGNvdW50OiBjLFxuICAgIGdyYXBoOiBncmFwaEl4XG4gIH07XG59O1xuLyoqXG4gKiBAYnJpZWY6IHByaW50c0xheW91dEluZm8gaW50byBqcyBjb25zb2xlXG4gKiAgICAgICAgIE9ubHkgdXNlZCBmb3IgZGViYnVnaW5nXG4gKi9cblxuXG5pZiAoZmFsc2UpIHtcbiAgdmFyIHByaW50TGF5b3V0SW5mbztcbn1cbi8qKlxuICogQGJyaWVmIDogUmFuZG9taXplcyB0aGUgcG9zaXRpb24gb2YgYWxsIG5vZGVzXG4gKi9cblxuXG52YXIgcmFuZG9taXplUG9zaXRpb25zID0gZnVuY3Rpb24gcmFuZG9taXplUG9zaXRpb25zKGxheW91dEluZm8sIGN5KSB7XG4gIHZhciB3aWR0aCA9IGxheW91dEluZm8uY2xpZW50V2lkdGg7XG4gIHZhciBoZWlnaHQgPSBsYXlvdXRJbmZvLmNsaWVudEhlaWdodDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxheW91dEluZm8ubm9kZVNpemU7IGkrKykge1xuICAgIHZhciBuID0gbGF5b3V0SW5mby5sYXlvdXROb2Rlc1tpXTsgLy8gTm8gbmVlZCB0byByYW5kb21pemUgY29tcG91bmQgbm9kZXMgb3IgbG9ja2VkIG5vZGVzXG5cbiAgICBpZiAoMCA9PT0gbi5jaGlsZHJlbi5sZW5ndGggJiYgIW4uaXNMb2NrZWQpIHtcbiAgICAgIG4ucG9zaXRpb25YID0gTWF0aC5yYW5kb20oKSAqIHdpZHRoO1xuICAgICAgbi5wb3NpdGlvblkgPSBNYXRoLnJhbmRvbSgpICogaGVpZ2h0O1xuICAgIH1cbiAgfVxufTtcblxudmFyIGdldFNjYWxlSW5Cb3VuZHNGbiA9IGZ1bmN0aW9uIGdldFNjYWxlSW5Cb3VuZHNGbihsYXlvdXRJbmZvLCBvcHRpb25zLCBub2Rlcykge1xuICB2YXIgYmIgPSBsYXlvdXRJbmZvLmJvdW5kaW5nQm94O1xuICB2YXIgY29zZUJCID0ge1xuICAgIHgxOiBJbmZpbml0eSxcbiAgICB4MjogLUluZmluaXR5LFxuICAgIHkxOiBJbmZpbml0eSxcbiAgICB5MjogLUluZmluaXR5XG4gIH07XG5cbiAgaWYgKG9wdGlvbnMuYm91bmRpbmdCb3gpIHtcbiAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICB2YXIgbG5vZGUgPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW2xheW91dEluZm8uaWRUb0luZGV4W25vZGUuZGF0YSgnaWQnKV1dO1xuICAgICAgY29zZUJCLngxID0gTWF0aC5taW4oY29zZUJCLngxLCBsbm9kZS5wb3NpdGlvblgpO1xuICAgICAgY29zZUJCLngyID0gTWF0aC5tYXgoY29zZUJCLngyLCBsbm9kZS5wb3NpdGlvblgpO1xuICAgICAgY29zZUJCLnkxID0gTWF0aC5taW4oY29zZUJCLnkxLCBsbm9kZS5wb3NpdGlvblkpO1xuICAgICAgY29zZUJCLnkyID0gTWF0aC5tYXgoY29zZUJCLnkyLCBsbm9kZS5wb3NpdGlvblkpO1xuICAgIH0pO1xuICAgIGNvc2VCQi53ID0gY29zZUJCLngyIC0gY29zZUJCLngxO1xuICAgIGNvc2VCQi5oID0gY29zZUJCLnkyIC0gY29zZUJCLnkxO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChlbGUsIGkpIHtcbiAgICB2YXIgbG5vZGUgPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW2xheW91dEluZm8uaWRUb0luZGV4W2VsZS5kYXRhKCdpZCcpXV07XG5cbiAgICBpZiAob3B0aW9ucy5ib3VuZGluZ0JveCkge1xuICAgICAgLy8gdGhlbiBhZGQgZXh0cmEgYm91bmRpbmcgYm94IGNvbnN0cmFpbnRcbiAgICAgIHZhciBwY3RYID0gKGxub2RlLnBvc2l0aW9uWCAtIGNvc2VCQi54MSkgLyBjb3NlQkIudztcbiAgICAgIHZhciBwY3RZID0gKGxub2RlLnBvc2l0aW9uWSAtIGNvc2VCQi55MSkgLyBjb3NlQkIuaDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHg6IGJiLngxICsgcGN0WCAqIGJiLncsXG4gICAgICAgIHk6IGJiLnkxICsgcGN0WSAqIGJiLmhcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHg6IGxub2RlLnBvc2l0aW9uWCxcbiAgICAgICAgeTogbG5vZGUucG9zaXRpb25ZXG4gICAgICB9O1xuICAgIH1cbiAgfTtcbn07XG4vKipcbiAqIEBicmllZiAgICAgICAgICA6IFVwZGF0ZXMgdGhlIHBvc2l0aW9ucyBvZiBub2RlcyBpbiB0aGUgbmV0d29ya1xuICogQGFyZyBsYXlvdXRJbmZvIDogTGF5b3V0SW5mbyBvYmplY3RcbiAqIEBhcmcgY3kgICAgICAgICA6IEN5dG9zY2FwZSBvYmplY3RcbiAqIEBhcmcgb3B0aW9ucyAgICA6IExheW91dCBvcHRpb25zXG4gKi9cblxuXG52YXIgcmVmcmVzaFBvc2l0aW9ucyA9IGZ1bmN0aW9uIHJlZnJlc2hQb3NpdGlvbnMobGF5b3V0SW5mbywgY3ksIG9wdGlvbnMpIHtcbiAgLy8gdmFyIHMgPSAnUmVmcmVzaGluZyBwb3NpdGlvbnMnO1xuICAvLyBsb2dEZWJ1ZyhzKTtcbiAgdmFyIGxheW91dCA9IG9wdGlvbnMubGF5b3V0O1xuICB2YXIgbm9kZXMgPSBvcHRpb25zLmVsZXMubm9kZXMoKTtcbiAgdmFyIGdldFNjYWxlZFBvcyA9IGdldFNjYWxlSW5Cb3VuZHNGbihsYXlvdXRJbmZvLCBvcHRpb25zLCBub2Rlcyk7XG4gIG5vZGVzLnBvc2l0aW9ucyhnZXRTY2FsZWRQb3MpOyAvLyBUcmlnZ2VyIGxheW91dFJlYWR5IG9ubHkgb24gZmlyc3QgY2FsbFxuXG4gIGlmICh0cnVlICE9PSBsYXlvdXRJbmZvLnJlYWR5KSB7XG4gICAgLy8gcyA9ICdUcmlnZ2VyaW5nIGxheW91dHJlYWR5JztcbiAgICAvLyBsb2dEZWJ1ZyhzKTtcbiAgICBsYXlvdXRJbmZvLnJlYWR5ID0gdHJ1ZTtcbiAgICBsYXlvdXQub25lKCdsYXlvdXRyZWFkeScsIG9wdGlvbnMucmVhZHkpO1xuICAgIGxheW91dC5lbWl0KHtcbiAgICAgIHR5cGU6ICdsYXlvdXRyZWFkeScsXG4gICAgICBsYXlvdXQ6IHRoaXNcbiAgICB9KTtcbiAgfVxufTtcbi8qKlxuICogQGJyaWVmIDogTG9ncyBhIGRlYnVnIG1lc3NhZ2UgaW4gSlMgY29uc29sZSwgaWYgREVCVUcgaXMgT05cbiAqL1xuLy8gdmFyIGxvZ0RlYnVnID0gZnVuY3Rpb24odGV4dCkge1xuLy8gICBpZiAoREVCVUcpIHtcbi8vICAgICBjb25zb2xlLmRlYnVnKHRleHQpO1xuLy8gICB9XG4vLyB9O1xuXG4vKipcbiAqIEBicmllZiAgICAgICAgICA6IFBlcmZvcm1zIG9uZSBpdGVyYXRpb24gb2YgdGhlIHBoeXNpY2FsIHNpbXVsYXRpb25cbiAqIEBhcmcgbGF5b3V0SW5mbyA6IExheW91dEluZm8gb2JqZWN0IGFscmVhZHkgaW5pdGlhbGl6ZWRcbiAqIEBhcmcgY3kgICAgICAgICA6IEN5dG9zY2FwZSBvYmplY3RcbiAqIEBhcmcgb3B0aW9ucyAgICA6IExheW91dCBvcHRpb25zXG4gKi9cblxuXG52YXIgc3RlcCQxID0gZnVuY3Rpb24gc3RlcChsYXlvdXRJbmZvLCBvcHRpb25zLCBfc3RlcCkge1xuICAvLyB2YXIgcyA9IFwiXFxuXFxuIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1wiO1xuICAvLyBzICs9IFwiXFxuU1RFUDogXCIgKyBzdGVwO1xuICAvLyBzICs9IFwiXFxuIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xcblwiO1xuICAvLyBsb2dEZWJ1ZyhzKTtcbiAgLy8gQ2FsY3VsYXRlIG5vZGUgcmVwdWxzaW9uc1xuICBjYWxjdWxhdGVOb2RlRm9yY2VzKGxheW91dEluZm8sIG9wdGlvbnMpOyAvLyBDYWxjdWxhdGUgZWRnZSBmb3JjZXNcblxuICBjYWxjdWxhdGVFZGdlRm9yY2VzKGxheW91dEluZm8pOyAvLyBDYWxjdWxhdGUgZ3Jhdml0eSBmb3JjZXNcblxuICBjYWxjdWxhdGVHcmF2aXR5Rm9yY2VzKGxheW91dEluZm8sIG9wdGlvbnMpOyAvLyBQcm9wYWdhdGUgZm9yY2VzIGZyb20gcGFyZW50IHRvIGNoaWxkXG5cbiAgcHJvcGFnYXRlRm9yY2VzKGxheW91dEluZm8pOyAvLyBVcGRhdGUgcG9zaXRpb25zIGJhc2VkIG9uIGNhbGN1bGF0ZWQgZm9yY2VzXG5cbiAgdXBkYXRlUG9zaXRpb25zKGxheW91dEluZm8pO1xufTtcbi8qKlxuICogQGJyaWVmIDogQ29tcHV0ZXMgdGhlIG5vZGUgcmVwdWxzaW9uIGZvcmNlc1xuICovXG5cblxudmFyIGNhbGN1bGF0ZU5vZGVGb3JjZXMgPSBmdW5jdGlvbiBjYWxjdWxhdGVOb2RlRm9yY2VzKGxheW91dEluZm8sIG9wdGlvbnMpIHtcbiAgLy8gR28gdGhyb3VnaCBlYWNoIG9mIHRoZSBncmFwaHMgaW4gZ3JhcGhTZXRcbiAgLy8gTm9kZXMgb25seSByZXBlbCBlYWNoIG90aGVyIGlmIHRoZXkgYmVsb25nIHRvIHRoZSBzYW1lIGdyYXBoXG4gIC8vIHZhciBzID0gJ2NhbGN1bGF0ZU5vZGVGb3JjZXMnO1xuICAvLyBsb2dEZWJ1ZyhzKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXlvdXRJbmZvLmdyYXBoU2V0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGdyYXBoID0gbGF5b3V0SW5mby5ncmFwaFNldFtpXTtcbiAgICB2YXIgbnVtTm9kZXMgPSBncmFwaC5sZW5ndGg7IC8vIHMgPSBcIlNldDogXCIgKyBncmFwaC50b1N0cmluZygpO1xuICAgIC8vIGxvZ0RlYnVnKHMpO1xuICAgIC8vIE5vdyBnZXQgYWxsIHRoZSBwYWlycyBvZiBub2Rlc1xuICAgIC8vIE9ubHkgZ2V0IGVhY2ggcGFpciBvbmNlLCAoQSwgQikgPSAoQiwgQSlcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbnVtTm9kZXM7IGorKykge1xuICAgICAgdmFyIG5vZGUxID0gbGF5b3V0SW5mby5sYXlvdXROb2Rlc1tsYXlvdXRJbmZvLmlkVG9JbmRleFtncmFwaFtqXV1dO1xuXG4gICAgICBmb3IgKHZhciBrID0gaiArIDE7IGsgPCBudW1Ob2RlczsgaysrKSB7XG4gICAgICAgIHZhciBub2RlMiA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXNbbGF5b3V0SW5mby5pZFRvSW5kZXhbZ3JhcGhba11dXTtcbiAgICAgICAgbm9kZVJlcHVsc2lvbihub2RlMSwgbm9kZTIsIGxheW91dEluZm8sIG9wdGlvbnMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxudmFyIHJhbmRvbURpc3RhbmNlID0gZnVuY3Rpb24gcmFuZG9tRGlzdGFuY2UobWF4KSB7XG4gIHJldHVybiAtbWF4ICsgMiAqIG1heCAqIE1hdGgucmFuZG9tKCk7XG59O1xuLyoqXG4gKiBAYnJpZWYgOiBDb21wdXRlIHRoZSBub2RlIHJlcHVsc2lvbiBmb3JjZXMgYmV0d2VlbiBhIHBhaXIgb2Ygbm9kZXNcbiAqL1xuXG5cbnZhciBub2RlUmVwdWxzaW9uID0gZnVuY3Rpb24gbm9kZVJlcHVsc2lvbihub2RlMSwgbm9kZTIsIGxheW91dEluZm8sIG9wdGlvbnMpIHtcbiAgLy8gdmFyIHMgPSBcIk5vZGUgcmVwdWxzaW9uLiBOb2RlMTogXCIgKyBub2RlMS5pZCArIFwiIE5vZGUyOiBcIiArIG5vZGUyLmlkO1xuICB2YXIgY21wdElkMSA9IG5vZGUxLmNtcHRJZDtcbiAgdmFyIGNtcHRJZDIgPSBub2RlMi5jbXB0SWQ7XG5cbiAgaWYgKGNtcHRJZDEgIT09IGNtcHRJZDIgJiYgIWxheW91dEluZm8uaXNDb21wb3VuZCkge1xuICAgIHJldHVybjtcbiAgfSAvLyBHZXQgZGlyZWN0aW9uIG9mIGxpbmUgY29ubmVjdGluZyBib3RoIG5vZGUgY2VudGVyc1xuXG5cbiAgdmFyIGRpcmVjdGlvblggPSBub2RlMi5wb3NpdGlvblggLSBub2RlMS5wb3NpdGlvblg7XG4gIHZhciBkaXJlY3Rpb25ZID0gbm9kZTIucG9zaXRpb25ZIC0gbm9kZTEucG9zaXRpb25ZO1xuICB2YXIgbWF4UmFuZERpc3QgPSAxOyAvLyBzICs9IFwiXFxuZGlyZWN0aW9uWDogXCIgKyBkaXJlY3Rpb25YICsgXCIsIGRpcmVjdGlvblk6IFwiICsgZGlyZWN0aW9uWTtcbiAgLy8gSWYgYm90aCBjZW50ZXJzIGFyZSB0aGUgc2FtZSwgYXBwbHkgYSByYW5kb20gZm9yY2VcblxuICBpZiAoMCA9PT0gZGlyZWN0aW9uWCAmJiAwID09PSBkaXJlY3Rpb25ZKSB7XG4gICAgZGlyZWN0aW9uWCA9IHJhbmRvbURpc3RhbmNlKG1heFJhbmREaXN0KTtcbiAgICBkaXJlY3Rpb25ZID0gcmFuZG9tRGlzdGFuY2UobWF4UmFuZERpc3QpO1xuICB9XG5cbiAgdmFyIG92ZXJsYXAgPSBub2Rlc092ZXJsYXAobm9kZTEsIG5vZGUyLCBkaXJlY3Rpb25YLCBkaXJlY3Rpb25ZKTtcblxuICBpZiAob3ZlcmxhcCA+IDApIHtcbiAgICAvLyBzICs9IFwiXFxuTm9kZXMgRE8gb3ZlcmxhcC5cIjtcbiAgICAvLyBzICs9IFwiXFxuT3ZlcmxhcDogXCIgKyBvdmVybGFwO1xuICAgIC8vIElmIG5vZGVzIG92ZXJsYXAsIHJlcHVsc2lvbiBmb3JjZSBpcyBwcm9wb3J0aW9uYWxcbiAgICAvLyB0byB0aGUgb3ZlcmxhcFxuICAgIHZhciBmb3JjZSA9IG9wdGlvbnMubm9kZU92ZXJsYXAgKiBvdmVybGFwOyAvLyBDb21wdXRlIHRoZSBtb2R1bGUgYW5kIGNvbXBvbmVudHMgb2YgdGhlIGZvcmNlIHZlY3RvclxuXG4gICAgdmFyIGRpc3RhbmNlID0gTWF0aC5zcXJ0KGRpcmVjdGlvblggKiBkaXJlY3Rpb25YICsgZGlyZWN0aW9uWSAqIGRpcmVjdGlvblkpOyAvLyBzICs9IFwiXFxuRGlzdGFuY2U6IFwiICsgZGlzdGFuY2U7XG5cbiAgICB2YXIgZm9yY2VYID0gZm9yY2UgKiBkaXJlY3Rpb25YIC8gZGlzdGFuY2U7XG4gICAgdmFyIGZvcmNlWSA9IGZvcmNlICogZGlyZWN0aW9uWSAvIGRpc3RhbmNlO1xuICB9IGVsc2Uge1xuICAgIC8vIHMgKz0gXCJcXG5Ob2RlcyBkbyBOT1Qgb3ZlcmxhcC5cIjtcbiAgICAvLyBJZiB0aGVyZSdzIG5vIG92ZXJsYXAsIGZvcmNlIGlzIGludmVyc2VseSBwcm9wb3J0aW9uYWxcbiAgICAvLyB0byBzcXVhcmVkIGRpc3RhbmNlXG4gICAgLy8gR2V0IGNsaXBwaW5nIHBvaW50cyBmb3IgYm90aCBub2Rlc1xuICAgIHZhciBwb2ludDEgPSBmaW5kQ2xpcHBpbmdQb2ludChub2RlMSwgZGlyZWN0aW9uWCwgZGlyZWN0aW9uWSk7XG4gICAgdmFyIHBvaW50MiA9IGZpbmRDbGlwcGluZ1BvaW50KG5vZGUyLCAtMSAqIGRpcmVjdGlvblgsIC0xICogZGlyZWN0aW9uWSk7IC8vIFVzZSBjbGlwcGluZyBwb2ludHMgdG8gY29tcHV0ZSBkaXN0YW5jZVxuXG4gICAgdmFyIGRpc3RhbmNlWCA9IHBvaW50Mi54IC0gcG9pbnQxLng7XG4gICAgdmFyIGRpc3RhbmNlWSA9IHBvaW50Mi55IC0gcG9pbnQxLnk7XG4gICAgdmFyIGRpc3RhbmNlU3FyID0gZGlzdGFuY2VYICogZGlzdGFuY2VYICsgZGlzdGFuY2VZICogZGlzdGFuY2VZO1xuICAgIHZhciBkaXN0YW5jZSA9IE1hdGguc3FydChkaXN0YW5jZVNxcik7IC8vIHMgKz0gXCJcXG5EaXN0YW5jZTogXCIgKyBkaXN0YW5jZTtcbiAgICAvLyBDb21wdXRlIHRoZSBtb2R1bGUgYW5kIGNvbXBvbmVudHMgb2YgdGhlIGZvcmNlIHZlY3RvclxuXG4gICAgdmFyIGZvcmNlID0gKG5vZGUxLm5vZGVSZXB1bHNpb24gKyBub2RlMi5ub2RlUmVwdWxzaW9uKSAvIGRpc3RhbmNlU3FyO1xuICAgIHZhciBmb3JjZVggPSBmb3JjZSAqIGRpc3RhbmNlWCAvIGRpc3RhbmNlO1xuICAgIHZhciBmb3JjZVkgPSBmb3JjZSAqIGRpc3RhbmNlWSAvIGRpc3RhbmNlO1xuICB9IC8vIEFwcGx5IGZvcmNlXG5cblxuICBpZiAoIW5vZGUxLmlzTG9ja2VkKSB7XG4gICAgbm9kZTEub2Zmc2V0WCAtPSBmb3JjZVg7XG4gICAgbm9kZTEub2Zmc2V0WSAtPSBmb3JjZVk7XG4gIH1cblxuICBpZiAoIW5vZGUyLmlzTG9ja2VkKSB7XG4gICAgbm9kZTIub2Zmc2V0WCArPSBmb3JjZVg7XG4gICAgbm9kZTIub2Zmc2V0WSArPSBmb3JjZVk7XG4gIH0gLy8gcyArPSBcIlxcbkZvcmNlWDogXCIgKyBmb3JjZVggKyBcIiBGb3JjZVk6IFwiICsgZm9yY2VZO1xuICAvLyBsb2dEZWJ1ZyhzKTtcblxuXG4gIHJldHVybjtcbn07XG4vKipcbiAqIEBicmllZiAgOiBEZXRlcm1pbmVzIHdoZXRoZXIgdHdvIG5vZGVzIG92ZXJsYXAgb3Igbm90XG4gKiBAcmV0dXJuIDogQW1vdW50IG9mIG92ZXJsYXBwaW5nICgwID0+IG5vIG92ZXJsYXApXG4gKi9cblxuXG52YXIgbm9kZXNPdmVybGFwID0gZnVuY3Rpb24gbm9kZXNPdmVybGFwKG5vZGUxLCBub2RlMiwgZFgsIGRZKSB7XG4gIGlmIChkWCA+IDApIHtcbiAgICB2YXIgb3ZlcmxhcFggPSBub2RlMS5tYXhYIC0gbm9kZTIubWluWDtcbiAgfSBlbHNlIHtcbiAgICB2YXIgb3ZlcmxhcFggPSBub2RlMi5tYXhYIC0gbm9kZTEubWluWDtcbiAgfVxuXG4gIGlmIChkWSA+IDApIHtcbiAgICB2YXIgb3ZlcmxhcFkgPSBub2RlMS5tYXhZIC0gbm9kZTIubWluWTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgb3ZlcmxhcFkgPSBub2RlMi5tYXhZIC0gbm9kZTEubWluWTtcbiAgfVxuXG4gIGlmIChvdmVybGFwWCA+PSAwICYmIG92ZXJsYXBZID49IDApIHtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KG92ZXJsYXBYICogb3ZlcmxhcFggKyBvdmVybGFwWSAqIG92ZXJsYXBZKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gMDtcbiAgfVxufTtcbi8qKlxuICogQGJyaWVmIDogRmluZHMgdGhlIHBvaW50IGluIHdoaWNoIGFuIGVkZ2UgKGRpcmVjdGlvbiBkWCwgZFkpIGludGVyc2VjdHNcbiAqICAgICAgICAgIHRoZSByZWN0YW5ndWxhciBib3VuZGluZyBib3ggb2YgaXQncyBzb3VyY2UvdGFyZ2V0IG5vZGVcbiAqL1xuXG5cbnZhciBmaW5kQ2xpcHBpbmdQb2ludCA9IGZ1bmN0aW9uIGZpbmRDbGlwcGluZ1BvaW50KG5vZGUsIGRYLCBkWSkge1xuICAvLyBTaG9yY3V0c1xuICB2YXIgWCA9IG5vZGUucG9zaXRpb25YO1xuICB2YXIgWSA9IG5vZGUucG9zaXRpb25ZO1xuICB2YXIgSCA9IG5vZGUuaGVpZ2h0IHx8IDE7XG4gIHZhciBXID0gbm9kZS53aWR0aCB8fCAxO1xuICB2YXIgZGlyU2xvcGUgPSBkWSAvIGRYO1xuICB2YXIgbm9kZVNsb3BlID0gSCAvIFc7IC8vIHZhciBzID0gJ0NvbXB1dGluZyBjbGlwcGluZyBwb2ludCBvZiBub2RlICcgKyBub2RlLmlkICtcbiAgLy8gICBcIiAuIEhlaWdodDogIFwiICsgSCArIFwiLCBXaWR0aDogXCIgKyBXICtcbiAgLy8gICBcIlxcbkRpcmVjdGlvbiBcIiArIGRYICsgXCIsIFwiICsgZFk7XG4gIC8vXG4gIC8vIENvbXB1dGUgaW50ZXJzZWN0aW9uXG5cbiAgdmFyIHJlcyA9IHt9OyAvLyBDYXNlOiBWZXJ0aWNhbCBkaXJlY3Rpb24gKHVwKVxuXG4gIGlmICgwID09PSBkWCAmJiAwIDwgZFkpIHtcbiAgICByZXMueCA9IFg7IC8vIHMgKz0gXCJcXG5VcCBkaXJlY3Rpb25cIjtcblxuICAgIHJlcy55ID0gWSArIEggLyAyO1xuICAgIHJldHVybiByZXM7XG4gIH0gLy8gQ2FzZTogVmVydGljYWwgZGlyZWN0aW9uIChkb3duKVxuXG5cbiAgaWYgKDAgPT09IGRYICYmIDAgPiBkWSkge1xuICAgIHJlcy54ID0gWDtcbiAgICByZXMueSA9IFkgKyBIIC8gMjsgLy8gcyArPSBcIlxcbkRvd24gZGlyZWN0aW9uXCI7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9IC8vIENhc2U6IEludGVyc2VjdHMgdGhlIHJpZ2h0IGJvcmRlclxuXG5cbiAgaWYgKDAgPCBkWCAmJiAtMSAqIG5vZGVTbG9wZSA8PSBkaXJTbG9wZSAmJiBkaXJTbG9wZSA8PSBub2RlU2xvcGUpIHtcbiAgICByZXMueCA9IFggKyBXIC8gMjtcbiAgICByZXMueSA9IFkgKyBXICogZFkgLyAyIC8gZFg7IC8vIHMgKz0gXCJcXG5SaWdodGJvcmRlclwiO1xuXG4gICAgcmV0dXJuIHJlcztcbiAgfSAvLyBDYXNlOiBJbnRlcnNlY3RzIHRoZSBsZWZ0IGJvcmRlclxuXG5cbiAgaWYgKDAgPiBkWCAmJiAtMSAqIG5vZGVTbG9wZSA8PSBkaXJTbG9wZSAmJiBkaXJTbG9wZSA8PSBub2RlU2xvcGUpIHtcbiAgICByZXMueCA9IFggLSBXIC8gMjtcbiAgICByZXMueSA9IFkgLSBXICogZFkgLyAyIC8gZFg7IC8vIHMgKz0gXCJcXG5MZWZ0Ym9yZGVyXCI7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9IC8vIENhc2U6IEludGVyc2VjdHMgdGhlIHRvcCBib3JkZXJcblxuXG4gIGlmICgwIDwgZFkgJiYgKGRpclNsb3BlIDw9IC0xICogbm9kZVNsb3BlIHx8IGRpclNsb3BlID49IG5vZGVTbG9wZSkpIHtcbiAgICByZXMueCA9IFggKyBIICogZFggLyAyIC8gZFk7XG4gICAgcmVzLnkgPSBZICsgSCAvIDI7IC8vIHMgKz0gXCJcXG5Ub3AgYm9yZGVyXCI7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9IC8vIENhc2U6IEludGVyc2VjdHMgdGhlIGJvdHRvbSBib3JkZXJcblxuXG4gIGlmICgwID4gZFkgJiYgKGRpclNsb3BlIDw9IC0xICogbm9kZVNsb3BlIHx8IGRpclNsb3BlID49IG5vZGVTbG9wZSkpIHtcbiAgICByZXMueCA9IFggLSBIICogZFggLyAyIC8gZFk7XG4gICAgcmVzLnkgPSBZIC0gSCAvIDI7IC8vIHMgKz0gXCJcXG5Cb3R0b20gYm9yZGVyXCI7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9IC8vIHMgKz0gXCJcXG5DbGlwcGluZyBwb2ludCBmb3VuZCBhdCBcIiArIHJlcy54ICsgXCIsIFwiICsgcmVzLnk7XG4gIC8vIGxvZ0RlYnVnKHMpO1xuXG5cbiAgcmV0dXJuIHJlcztcbn07XG4vKipcbiAqIEBicmllZiA6IENhbGN1bGF0ZXMgYWxsIGVkZ2UgZm9yY2VzXG4gKi9cblxuXG52YXIgY2FsY3VsYXRlRWRnZUZvcmNlcyA9IGZ1bmN0aW9uIGNhbGN1bGF0ZUVkZ2VGb3JjZXMobGF5b3V0SW5mbywgb3B0aW9ucykge1xuICAvLyBJdGVyYXRlIG92ZXIgYWxsIGVkZ2VzXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5b3V0SW5mby5lZGdlU2l6ZTsgaSsrKSB7XG4gICAgLy8gR2V0IGVkZ2UsIHNvdXJjZSAmIHRhcmdldCBub2Rlc1xuICAgIHZhciBlZGdlID0gbGF5b3V0SW5mby5sYXlvdXRFZGdlc1tpXTtcbiAgICB2YXIgc291cmNlSXggPSBsYXlvdXRJbmZvLmlkVG9JbmRleFtlZGdlLnNvdXJjZUlkXTtcbiAgICB2YXIgc291cmNlID0gbGF5b3V0SW5mby5sYXlvdXROb2Rlc1tzb3VyY2VJeF07XG4gICAgdmFyIHRhcmdldEl4ID0gbGF5b3V0SW5mby5pZFRvSW5kZXhbZWRnZS50YXJnZXRJZF07XG4gICAgdmFyIHRhcmdldCA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXNbdGFyZ2V0SXhdOyAvLyBHZXQgZGlyZWN0aW9uIG9mIGxpbmUgY29ubmVjdGluZyBib3RoIG5vZGUgY2VudGVyc1xuXG4gICAgdmFyIGRpcmVjdGlvblggPSB0YXJnZXQucG9zaXRpb25YIC0gc291cmNlLnBvc2l0aW9uWDtcbiAgICB2YXIgZGlyZWN0aW9uWSA9IHRhcmdldC5wb3NpdGlvblkgLSBzb3VyY2UucG9zaXRpb25ZOyAvLyBJZiBib3RoIGNlbnRlcnMgYXJlIHRoZSBzYW1lLCBkbyBub3RoaW5nLlxuICAgIC8vIEEgcmFuZG9tIGZvcmNlIGhhcyBhbHJlYWR5IGJlZW4gYXBwbGllZCBhcyBub2RlIHJlcHVsc2lvblxuXG4gICAgaWYgKDAgPT09IGRpcmVjdGlvblggJiYgMCA9PT0gZGlyZWN0aW9uWSkge1xuICAgICAgY29udGludWU7XG4gICAgfSAvLyBHZXQgY2xpcHBpbmcgcG9pbnRzIGZvciBib3RoIG5vZGVzXG5cblxuICAgIHZhciBwb2ludDEgPSBmaW5kQ2xpcHBpbmdQb2ludChzb3VyY2UsIGRpcmVjdGlvblgsIGRpcmVjdGlvblkpO1xuICAgIHZhciBwb2ludDIgPSBmaW5kQ2xpcHBpbmdQb2ludCh0YXJnZXQsIC0xICogZGlyZWN0aW9uWCwgLTEgKiBkaXJlY3Rpb25ZKTtcbiAgICB2YXIgbHggPSBwb2ludDIueCAtIHBvaW50MS54O1xuICAgIHZhciBseSA9IHBvaW50Mi55IC0gcG9pbnQxLnk7XG4gICAgdmFyIGwgPSBNYXRoLnNxcnQobHggKiBseCArIGx5ICogbHkpO1xuICAgIHZhciBmb3JjZSA9IE1hdGgucG93KGVkZ2UuaWRlYWxMZW5ndGggLSBsLCAyKSAvIGVkZ2UuZWxhc3RpY2l0eTtcblxuICAgIGlmICgwICE9PSBsKSB7XG4gICAgICB2YXIgZm9yY2VYID0gZm9yY2UgKiBseCAvIGw7XG4gICAgICB2YXIgZm9yY2VZID0gZm9yY2UgKiBseSAvIGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBmb3JjZVggPSAwO1xuICAgICAgdmFyIGZvcmNlWSA9IDA7XG4gICAgfSAvLyBBZGQgdGhpcyBmb3JjZSB0byB0YXJnZXQgYW5kIHNvdXJjZSBub2Rlc1xuXG5cbiAgICBpZiAoIXNvdXJjZS5pc0xvY2tlZCkge1xuICAgICAgc291cmNlLm9mZnNldFggKz0gZm9yY2VYO1xuICAgICAgc291cmNlLm9mZnNldFkgKz0gZm9yY2VZO1xuICAgIH1cblxuICAgIGlmICghdGFyZ2V0LmlzTG9ja2VkKSB7XG4gICAgICB0YXJnZXQub2Zmc2V0WCAtPSBmb3JjZVg7XG4gICAgICB0YXJnZXQub2Zmc2V0WSAtPSBmb3JjZVk7XG4gICAgfSAvLyB2YXIgcyA9ICdFZGdlIGZvcmNlIGJldHdlZW4gbm9kZXMgJyArIHNvdXJjZS5pZCArICcgYW5kICcgKyB0YXJnZXQuaWQ7XG4gICAgLy8gcyArPSBcIlxcbkRpc3RhbmNlOiBcIiArIGwgKyBcIiBGb3JjZTogKFwiICsgZm9yY2VYICsgXCIsIFwiICsgZm9yY2VZICsgXCIpXCI7XG4gICAgLy8gbG9nRGVidWcocyk7XG5cbiAgfVxufTtcbi8qKlxuICogQGJyaWVmIDogQ29tcHV0ZXMgZ3Jhdml0eSBmb3JjZXMgZm9yIGFsbCBub2Rlc1xuICovXG5cblxudmFyIGNhbGN1bGF0ZUdyYXZpdHlGb3JjZXMgPSBmdW5jdGlvbiBjYWxjdWxhdGVHcmF2aXR5Rm9yY2VzKGxheW91dEluZm8sIG9wdGlvbnMpIHtcbiAgdmFyIGRpc3RUaHJlc2hvbGQgPSAxOyAvLyB2YXIgcyA9ICdjYWxjdWxhdGVHcmF2aXR5Rm9yY2VzJztcbiAgLy8gbG9nRGVidWcocyk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXlvdXRJbmZvLmdyYXBoU2V0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGdyYXBoID0gbGF5b3V0SW5mby5ncmFwaFNldFtpXTtcbiAgICB2YXIgbnVtTm9kZXMgPSBncmFwaC5sZW5ndGg7IC8vIHMgPSBcIlNldDogXCIgKyBncmFwaC50b1N0cmluZygpO1xuICAgIC8vIGxvZ0RlYnVnKHMpO1xuICAgIC8vIENvbXB1dGUgZ3JhcGggY2VudGVyXG5cbiAgICBpZiAoMCA9PT0gaSkge1xuICAgICAgdmFyIGNlbnRlclggPSBsYXlvdXRJbmZvLmNsaWVudEhlaWdodCAvIDI7XG4gICAgICB2YXIgY2VudGVyWSA9IGxheW91dEluZm8uY2xpZW50V2lkdGggLyAyO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBHZXQgUGFyZW50IG5vZGUgZm9yIHRoaXMgZ3JhcGgsIGFuZCB1c2UgaXRzIHBvc2l0aW9uIGFzIGNlbnRlclxuICAgICAgdmFyIHRlbXAgPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW2xheW91dEluZm8uaWRUb0luZGV4W2dyYXBoWzBdXV07XG4gICAgICB2YXIgcGFyZW50ID0gbGF5b3V0SW5mby5sYXlvdXROb2Rlc1tsYXlvdXRJbmZvLmlkVG9JbmRleFt0ZW1wLnBhcmVudElkXV07XG4gICAgICB2YXIgY2VudGVyWCA9IHBhcmVudC5wb3NpdGlvblg7XG4gICAgICB2YXIgY2VudGVyWSA9IHBhcmVudC5wb3NpdGlvblk7XG4gICAgfSAvLyBzID0gXCJDZW50ZXIgZm91bmQgYXQ6IFwiICsgY2VudGVyWCArIFwiLCBcIiArIGNlbnRlclk7XG4gICAgLy8gbG9nRGVidWcocyk7XG4gICAgLy8gQXBwbHkgZm9yY2UgdG8gYWxsIG5vZGVzIGluIGdyYXBoXG5cblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbnVtTm9kZXM7IGorKykge1xuICAgICAgdmFyIG5vZGUgPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW2xheW91dEluZm8uaWRUb0luZGV4W2dyYXBoW2pdXV07IC8vIHMgPSBcIk5vZGU6IFwiICsgbm9kZS5pZDtcblxuICAgICAgaWYgKG5vZGUuaXNMb2NrZWQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBkeCA9IGNlbnRlclggLSBub2RlLnBvc2l0aW9uWDtcbiAgICAgIHZhciBkeSA9IGNlbnRlclkgLSBub2RlLnBvc2l0aW9uWTtcbiAgICAgIHZhciBkID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgICAgaWYgKGQgPiBkaXN0VGhyZXNob2xkKSB7XG4gICAgICAgIHZhciBmeCA9IG9wdGlvbnMuZ3Jhdml0eSAqIGR4IC8gZDtcbiAgICAgICAgdmFyIGZ5ID0gb3B0aW9ucy5ncmF2aXR5ICogZHkgLyBkO1xuICAgICAgICBub2RlLm9mZnNldFggKz0gZng7XG4gICAgICAgIG5vZGUub2Zmc2V0WSArPSBmeTsgLy8gcyArPSBcIjogQXBwbGllZCBmb3JjZTogXCIgKyBmeCArIFwiLCBcIiArIGZ5O1xuICAgICAgfSAvLyBzICs9IFwiOiBza3lwcGVkIHNpbmNlIGl0J3MgdG9vIGNsb3NlIHRvIGNlbnRlclwiO1xuICAgICAgICAvLyBsb2dEZWJ1ZyhzKTtcblxuICAgIH1cbiAgfVxufTtcbi8qKlxuICogQGJyaWVmICAgICAgICAgIDogVGhpcyBmdW5jdGlvbiBwcm9wYWdhdGVzIHRoZSBleGlzdGluZyBvZmZzZXRzIGZyb21cbiAqICAgICAgICAgICAgICAgICAgIHBhcmVudCBub2RlcyB0byBpdHMgZGVzY2VuZGVudHMuXG4gKiBAYXJnIGxheW91dEluZm8gOiBsYXlvdXRJbmZvIE9iamVjdFxuICogQGFyZyBjeSAgICAgICAgIDogY3l0b3NjYXBlIE9iamVjdFxuICogQGFyZyBvcHRpb25zICAgIDogTGF5b3V0IG9wdGlvbnNcbiAqL1xuXG5cbnZhciBwcm9wYWdhdGVGb3JjZXMgPSBmdW5jdGlvbiBwcm9wYWdhdGVGb3JjZXMobGF5b3V0SW5mbywgb3B0aW9ucykge1xuICAvLyBJbmxpbmUgaW1wbGVtZW50YXRpb24gb2YgYSBxdWV1ZSwgdXNlZCBmb3IgdHJhdmVyc2luZyB0aGUgZ3JhcGggaW4gQkZTIG9yZGVyXG4gIHZhciBxdWV1ZSA9IFtdO1xuICB2YXIgc3RhcnQgPSAwOyAvLyBQb2ludHMgdG8gdGhlIHN0YXJ0IHRoZSBxdWV1ZVxuXG4gIHZhciBlbmQgPSAtMTsgLy8gUG9pbnRzIHRvIHRoZSBlbmQgb2YgdGhlIHF1ZXVlXG4gIC8vIGxvZ0RlYnVnKCdwcm9wYWdhdGVGb3JjZXMnKTtcbiAgLy8gU3RhcnQgYnkgdmlzaXRpbmcgdGhlIG5vZGVzIGluIHRoZSByb290IGdyYXBoXG5cbiAgcXVldWUucHVzaC5hcHBseShxdWV1ZSwgbGF5b3V0SW5mby5ncmFwaFNldFswXSk7XG4gIGVuZCArPSBsYXlvdXRJbmZvLmdyYXBoU2V0WzBdLmxlbmd0aDsgLy8gVHJhdmVyc2UgdGhlIGdyYXBoLCBsZXZlbCBieSBsZXZlbCxcblxuICB3aGlsZSAoc3RhcnQgPD0gZW5kKSB7XG4gICAgLy8gR2V0IHRoZSBub2RlIHRvIHZpc2l0IGFuZCByZW1vdmUgaXQgZnJvbSBxdWV1ZVxuICAgIHZhciBub2RlSWQgPSBxdWV1ZVtzdGFydCsrXTtcbiAgICB2YXIgbm9kZUluZGV4ID0gbGF5b3V0SW5mby5pZFRvSW5kZXhbbm9kZUlkXTtcbiAgICB2YXIgbm9kZSA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXNbbm9kZUluZGV4XTtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuOyAvLyBXZSBvbmx5IG5lZWQgdG8gcHJvY2VzcyB0aGUgbm9kZSBpZiBpdCdzIGNvbXBvdW5kXG5cbiAgICBpZiAoMCA8IGNoaWxkcmVuLmxlbmd0aCAmJiAhbm9kZS5pc0xvY2tlZCkge1xuICAgICAgdmFyIG9mZlggPSBub2RlLm9mZnNldFg7XG4gICAgICB2YXIgb2ZmWSA9IG5vZGUub2Zmc2V0WTsgLy8gdmFyIHMgPSBcIlByb3BhZ2F0aW5nIG9mZnNldCBmcm9tIHBhcmVudCBub2RlIDogXCIgKyBub2RlLmlkICtcbiAgICAgIC8vICAgXCIuIE9mZnNldFg6IFwiICsgb2ZmWCArIFwiLiBPZmZzZXRZOiBcIiArIG9mZlk7XG4gICAgICAvLyBzICs9IFwiXFxuIENoaWxkcmVuOiBcIiArIGNoaWxkcmVuLnRvU3RyaW5nKCk7XG4gICAgICAvLyBsb2dEZWJ1ZyhzKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2hpbGROb2RlID0gbGF5b3V0SW5mby5sYXlvdXROb2Rlc1tsYXlvdXRJbmZvLmlkVG9JbmRleFtjaGlsZHJlbltpXV1dOyAvLyBQcm9wYWdhdGUgb2Zmc2V0XG5cbiAgICAgICAgY2hpbGROb2RlLm9mZnNldFggKz0gb2ZmWDtcbiAgICAgICAgY2hpbGROb2RlLm9mZnNldFkgKz0gb2ZmWTsgLy8gQWRkIGNoaWxkcmVuIHRvIHF1ZXVlIHRvIGJlIHZpc2l0ZWRcblxuICAgICAgICBxdWV1ZVsrK2VuZF0gPSBjaGlsZHJlbltpXTtcbiAgICAgIH0gLy8gUmVzZXQgcGFyZW50IG9mZnNldHNcblxuXG4gICAgICBub2RlLm9mZnNldFggPSAwO1xuICAgICAgbm9kZS5vZmZzZXRZID0gMDtcbiAgICB9XG4gIH1cbn07XG4vKipcbiAqIEBicmllZiA6IFVwZGF0ZXMgdGhlIGxheW91dCBtb2RlbCBwb3NpdGlvbnMsIGJhc2VkIG9uXG4gKiAgICAgICAgICB0aGUgYWNjdW11bGF0ZWQgZm9yY2VzXG4gKi9cblxuXG52YXIgdXBkYXRlUG9zaXRpb25zID0gZnVuY3Rpb24gdXBkYXRlUG9zaXRpb25zKGxheW91dEluZm8sIG9wdGlvbnMpIHtcbiAgLy8gdmFyIHMgPSAnVXBkYXRpbmcgcG9zaXRpb25zJztcbiAgLy8gbG9nRGVidWcocyk7XG4gIC8vIFJlc2V0IGJvdW5kYXJpZXMgZm9yIGNvbXBvdW5kIG5vZGVzXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5b3V0SW5mby5ub2RlU2l6ZTsgaSsrKSB7XG4gICAgdmFyIG4gPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW2ldO1xuXG4gICAgaWYgKDAgPCBuLmNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgLy8gbG9nRGVidWcoXCJSZXNldHRpbmcgYm91bmRhcmllcyBvZiBjb21wb3VuZCBub2RlOiBcIiArIG4uaWQpO1xuICAgICAgbi5tYXhYID0gdW5kZWZpbmVkO1xuICAgICAgbi5taW5YID0gdW5kZWZpbmVkO1xuICAgICAgbi5tYXhZID0gdW5kZWZpbmVkO1xuICAgICAgbi5taW5ZID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5b3V0SW5mby5ub2RlU2l6ZTsgaSsrKSB7XG4gICAgdmFyIG4gPSBsYXlvdXRJbmZvLmxheW91dE5vZGVzW2ldO1xuXG4gICAgaWYgKDAgPCBuLmNoaWxkcmVuLmxlbmd0aCB8fCBuLmlzTG9ja2VkKSB7XG4gICAgICAvLyBObyBuZWVkIHRvIHNldCBjb21wb3VuZCBvciBsb2NrZWQgbm9kZSBwb3NpdGlvblxuICAgICAgLy8gbG9nRGVidWcoXCJTa2lwcGluZyBwb3NpdGlvbiB1cGRhdGUgb2Ygbm9kZTogXCIgKyBuLmlkKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH0gLy8gcyA9IFwiTm9kZTogXCIgKyBuLmlkICsgXCIgUHJldmlvdXMgcG9zaXRpb246IChcIiArXG4gICAgLy8gbi5wb3NpdGlvblggKyBcIiwgXCIgKyBuLnBvc2l0aW9uWSArIFwiKS5cIjtcbiAgICAvLyBMaW1pdCBkaXNwbGFjZW1lbnQgaW4gb3JkZXIgdG8gaW1wcm92ZSBzdGFiaWxpdHlcblxuXG4gICAgdmFyIHRlbXBGb3JjZSA9IGxpbWl0Rm9yY2Uobi5vZmZzZXRYLCBuLm9mZnNldFksIGxheW91dEluZm8udGVtcGVyYXR1cmUpO1xuICAgIG4ucG9zaXRpb25YICs9IHRlbXBGb3JjZS54O1xuICAgIG4ucG9zaXRpb25ZICs9IHRlbXBGb3JjZS55O1xuICAgIG4ub2Zmc2V0WCA9IDA7XG4gICAgbi5vZmZzZXRZID0gMDtcbiAgICBuLm1pblggPSBuLnBvc2l0aW9uWCAtIG4ud2lkdGg7XG4gICAgbi5tYXhYID0gbi5wb3NpdGlvblggKyBuLndpZHRoO1xuICAgIG4ubWluWSA9IG4ucG9zaXRpb25ZIC0gbi5oZWlnaHQ7XG4gICAgbi5tYXhZID0gbi5wb3NpdGlvblkgKyBuLmhlaWdodDsgLy8gcyArPSBcIiBOZXcgUG9zaXRpb246IChcIiArIG4ucG9zaXRpb25YICsgXCIsIFwiICsgbi5wb3NpdGlvblkgKyBcIikuXCI7XG4gICAgLy8gbG9nRGVidWcocyk7XG4gICAgLy8gVXBkYXRlIGFuY2VzdHJ5IGJvdWRhcmllc1xuXG4gICAgdXBkYXRlQW5jZXN0cnlCb3VuZGFyaWVzKG4sIGxheW91dEluZm8pO1xuICB9IC8vIFVwZGF0ZSBzaXplLCBwb3NpdGlvbiBvZiBjb21wdW5kIG5vZGVzXG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxheW91dEluZm8ubm9kZVNpemU7IGkrKykge1xuICAgIHZhciBuID0gbGF5b3V0SW5mby5sYXlvdXROb2Rlc1tpXTtcblxuICAgIGlmICgwIDwgbi5jaGlsZHJlbi5sZW5ndGggJiYgIW4uaXNMb2NrZWQpIHtcbiAgICAgIG4ucG9zaXRpb25YID0gKG4ubWF4WCArIG4ubWluWCkgLyAyO1xuICAgICAgbi5wb3NpdGlvblkgPSAobi5tYXhZICsgbi5taW5ZKSAvIDI7XG4gICAgICBuLndpZHRoID0gbi5tYXhYIC0gbi5taW5YO1xuICAgICAgbi5oZWlnaHQgPSBuLm1heFkgLSBuLm1pblk7IC8vIHMgPSBcIlVwZGF0aW5nIHBvc2l0aW9uLCBzaXplIG9mIGNvbXBvdW5kIG5vZGUgXCIgKyBuLmlkO1xuICAgICAgLy8gcyArPSBcIlxcblBvc2l0aW9uWDogXCIgKyBuLnBvc2l0aW9uWCArIFwiLCBQb3NpdGlvblk6IFwiICsgbi5wb3NpdGlvblk7XG4gICAgICAvLyBzICs9IFwiXFxuV2lkdGg6IFwiICsgbi53aWR0aCArIFwiLCBIZWlnaHQ6IFwiICsgbi5oZWlnaHQ7XG4gICAgICAvLyBsb2dEZWJ1ZyhzKTtcbiAgICB9XG4gIH1cbn07XG4vKipcbiAqIEBicmllZiA6IExpbWl0cyBhIGZvcmNlIChmb3JjZVgsIGZvcmNlWSkgdG8gYmUgbm90XG4gKiAgICAgICAgICBncmVhdGVyIChpbiBtb2R1bG8pIHRoYW4gbWF4LlxuIDggICAgICAgICAgUHJlc2VydmVzIGZvcmNlIGRpcmVjdGlvbi5cbiAgKi9cblxuXG52YXIgbGltaXRGb3JjZSA9IGZ1bmN0aW9uIGxpbWl0Rm9yY2UoZm9yY2VYLCBmb3JjZVksIG1heCkge1xuICAvLyB2YXIgcyA9IFwiTGltaXRpbmcgZm9yY2U6IChcIiArIGZvcmNlWCArIFwiLCBcIiArIGZvcmNlWSArIFwiKS4gTWF4OiBcIiArIG1heDtcbiAgdmFyIGZvcmNlID0gTWF0aC5zcXJ0KGZvcmNlWCAqIGZvcmNlWCArIGZvcmNlWSAqIGZvcmNlWSk7XG5cbiAgaWYgKGZvcmNlID4gbWF4KSB7XG4gICAgdmFyIHJlcyA9IHtcbiAgICAgIHg6IG1heCAqIGZvcmNlWCAvIGZvcmNlLFxuICAgICAgeTogbWF4ICogZm9yY2VZIC8gZm9yY2VcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHZhciByZXMgPSB7XG4gICAgICB4OiBmb3JjZVgsXG4gICAgICB5OiBmb3JjZVlcbiAgICB9O1xuICB9IC8vIHMgKz0gXCIuXFxuUmVzdWx0OiAoXCIgKyByZXMueCArIFwiLCBcIiArIHJlcy55ICsgXCIpXCI7XG4gIC8vIGxvZ0RlYnVnKHMpO1xuXG5cbiAgcmV0dXJuIHJlcztcbn07XG4vKipcbiAqIEBicmllZiA6IEZ1bmN0aW9uIHVzZWQgZm9yIGtlZXBpbmcgdHJhY2sgb2YgY29tcG91bmQgbm9kZVxuICogICAgICAgICAgc2l6ZXMsIHNpbmNlIHRoZXkgc2hvdWxkIGJvdW5kIGFsbCB0aGVpciBzdWJub2Rlcy5cbiAqL1xuXG5cbnZhciB1cGRhdGVBbmNlc3RyeUJvdW5kYXJpZXMgPSBmdW5jdGlvbiB1cGRhdGVBbmNlc3RyeUJvdW5kYXJpZXMobm9kZSwgbGF5b3V0SW5mbykge1xuICAvLyB2YXIgcyA9IFwiUHJvcGFnYXRpbmcgbmV3IHBvc2l0aW9uL3NpemUgb2Ygbm9kZSBcIiArIG5vZGUuaWQ7XG4gIHZhciBwYXJlbnRJZCA9IG5vZGUucGFyZW50SWQ7XG5cbiAgaWYgKG51bGwgPT0gcGFyZW50SWQpIHtcbiAgICAvLyBJZiB0aGVyZSdzIG5vIHBhcmVudCwgd2UgYXJlIGRvbmVcbiAgICAvLyBzICs9IFwiLiBObyBwYXJlbnQgbm9kZS5cIjtcbiAgICAvLyBsb2dEZWJ1ZyhzKTtcbiAgICByZXR1cm47XG4gIH0gLy8gR2V0IFBhcmVudCBOb2RlXG5cblxuICB2YXIgcCA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXNbbGF5b3V0SW5mby5pZFRvSW5kZXhbcGFyZW50SWRdXTtcbiAgdmFyIGZsYWcgPSBmYWxzZTsgLy8gTWF4WFxuXG4gIGlmIChudWxsID09IHAubWF4WCB8fCBub2RlLm1heFggKyBwLnBhZFJpZ2h0ID4gcC5tYXhYKSB7XG4gICAgcC5tYXhYID0gbm9kZS5tYXhYICsgcC5wYWRSaWdodDtcbiAgICBmbGFnID0gdHJ1ZTsgLy8gcyArPSBcIlxcbk5ldyBtYXhYIGZvciBwYXJlbnQgbm9kZSBcIiArIHAuaWQgKyBcIjogXCIgKyBwLm1heFg7XG4gIH0gLy8gTWluWFxuXG5cbiAgaWYgKG51bGwgPT0gcC5taW5YIHx8IG5vZGUubWluWCAtIHAucGFkTGVmdCA8IHAubWluWCkge1xuICAgIHAubWluWCA9IG5vZGUubWluWCAtIHAucGFkTGVmdDtcbiAgICBmbGFnID0gdHJ1ZTsgLy8gcyArPSBcIlxcbk5ldyBtaW5YIGZvciBwYXJlbnQgbm9kZSBcIiArIHAuaWQgKyBcIjogXCIgKyBwLm1pblg7XG4gIH0gLy8gTWF4WVxuXG5cbiAgaWYgKG51bGwgPT0gcC5tYXhZIHx8IG5vZGUubWF4WSArIHAucGFkQm90dG9tID4gcC5tYXhZKSB7XG4gICAgcC5tYXhZID0gbm9kZS5tYXhZICsgcC5wYWRCb3R0b207XG4gICAgZmxhZyA9IHRydWU7IC8vIHMgKz0gXCJcXG5OZXcgbWF4WSBmb3IgcGFyZW50IG5vZGUgXCIgKyBwLmlkICsgXCI6IFwiICsgcC5tYXhZO1xuICB9IC8vIE1pbllcblxuXG4gIGlmIChudWxsID09IHAubWluWSB8fCBub2RlLm1pblkgLSBwLnBhZFRvcCA8IHAubWluWSkge1xuICAgIHAubWluWSA9IG5vZGUubWluWSAtIHAucGFkVG9wO1xuICAgIGZsYWcgPSB0cnVlOyAvLyBzICs9IFwiXFxuTmV3IG1pblkgZm9yIHBhcmVudCBub2RlIFwiICsgcC5pZCArIFwiOiBcIiArIHAubWluWTtcbiAgfSAvLyBJZiB1cGRhdGVkIGJvdW5kYXJpZXMsIHByb3BhZ2F0ZSBjaGFuZ2VzIHVwd2FyZFxuXG5cbiAgaWYgKGZsYWcpIHtcbiAgICAvLyBsb2dEZWJ1ZyhzKTtcbiAgICByZXR1cm4gdXBkYXRlQW5jZXN0cnlCb3VuZGFyaWVzKHAsIGxheW91dEluZm8pO1xuICB9IC8vIHMgKz0gXCIuIE5vIGNoYW5nZXMgaW4gYm91bmRhcmllcy9wb3NpdGlvbiBvZiBwYXJlbnQgbm9kZSBcIiArIHAuaWQ7XG4gIC8vIGxvZ0RlYnVnKHMpO1xuXG5cbiAgcmV0dXJuO1xufTtcblxudmFyIHNlcGFyYXRlQ29tcG9uZW50cyA9IGZ1bmN0aW9uIHNlcGFyYXRlQ29tcG9uZW50cyhsYXlvdXRJbmZvLCBvcHRpb25zKSB7XG4gIHZhciBub2RlcyA9IGxheW91dEluZm8ubGF5b3V0Tm9kZXM7XG4gIHZhciBjb21wb25lbnRzID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBub2RlID0gbm9kZXNbaV07XG4gICAgdmFyIGNpZCA9IG5vZGUuY21wdElkO1xuICAgIHZhciBjb21wb25lbnQgPSBjb21wb25lbnRzW2NpZF0gPSBjb21wb25lbnRzW2NpZF0gfHwgW107XG4gICAgY29tcG9uZW50LnB1c2gobm9kZSk7XG4gIH1cblxuICB2YXIgdG90YWxBID0gMDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbXBvbmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgYyA9IGNvbXBvbmVudHNbaV07XG5cbiAgICBpZiAoIWMpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGMueDEgPSBJbmZpbml0eTtcbiAgICBjLngyID0gLUluZmluaXR5O1xuICAgIGMueTEgPSBJbmZpbml0eTtcbiAgICBjLnkyID0gLUluZmluaXR5O1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBjLmxlbmd0aDsgaisrKSB7XG4gICAgICB2YXIgbiA9IGNbal07XG4gICAgICBjLngxID0gTWF0aC5taW4oYy54MSwgbi5wb3NpdGlvblggLSBuLndpZHRoIC8gMik7XG4gICAgICBjLngyID0gTWF0aC5tYXgoYy54Miwgbi5wb3NpdGlvblggKyBuLndpZHRoIC8gMik7XG4gICAgICBjLnkxID0gTWF0aC5taW4oYy55MSwgbi5wb3NpdGlvblkgLSBuLmhlaWdodCAvIDIpO1xuICAgICAgYy55MiA9IE1hdGgubWF4KGMueTIsIG4ucG9zaXRpb25ZICsgbi5oZWlnaHQgLyAyKTtcbiAgICB9XG5cbiAgICBjLncgPSBjLngyIC0gYy54MTtcbiAgICBjLmggPSBjLnkyIC0gYy55MTtcbiAgICB0b3RhbEEgKz0gYy53ICogYy5oO1xuICB9XG5cbiAgY29tcG9uZW50cy5zb3J0KGZ1bmN0aW9uIChjMSwgYzIpIHtcbiAgICByZXR1cm4gYzIudyAqIGMyLmggLSBjMS53ICogYzEuaDtcbiAgfSk7XG4gIHZhciB4ID0gMDtcbiAgdmFyIHkgPSAwO1xuICB2YXIgdXNlZFcgPSAwO1xuICB2YXIgcm93SCA9IDA7XG4gIHZhciBtYXhSb3dXID0gTWF0aC5zcXJ0KHRvdGFsQSkgKiBsYXlvdXRJbmZvLmNsaWVudFdpZHRoIC8gbGF5b3V0SW5mby5jbGllbnRIZWlnaHQ7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb21wb25lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGMgPSBjb21wb25lbnRzW2ldO1xuXG4gICAgaWYgKCFjKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IGMubGVuZ3RoOyBqKyspIHtcbiAgICAgIHZhciBuID0gY1tqXTtcblxuICAgICAgaWYgKCFuLmlzTG9ja2VkKSB7XG4gICAgICAgIG4ucG9zaXRpb25YICs9IHggLSBjLngxO1xuICAgICAgICBuLnBvc2l0aW9uWSArPSB5IC0gYy55MTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB4ICs9IGMudyArIG9wdGlvbnMuY29tcG9uZW50U3BhY2luZztcbiAgICB1c2VkVyArPSBjLncgKyBvcHRpb25zLmNvbXBvbmVudFNwYWNpbmc7XG4gICAgcm93SCA9IE1hdGgubWF4KHJvd0gsIGMuaCk7XG5cbiAgICBpZiAodXNlZFcgPiBtYXhSb3dXKSB7XG4gICAgICB5ICs9IHJvd0ggKyBvcHRpb25zLmNvbXBvbmVudFNwYWNpbmc7XG4gICAgICB4ID0gMDtcbiAgICAgIHVzZWRXID0gMDtcbiAgICAgIHJvd0ggPSAwO1xuICAgIH1cbiAgfVxufTtcblxudmFyIGRlZmF1bHRzJGQgPSB7XG4gIGZpdDogdHJ1ZSxcbiAgLy8gd2hldGhlciB0byBmaXQgdGhlIHZpZXdwb3J0IHRvIHRoZSBncmFwaFxuICBwYWRkaW5nOiAzMCxcbiAgLy8gcGFkZGluZyB1c2VkIG9uIGZpdFxuICBib3VuZGluZ0JveDogdW5kZWZpbmVkLFxuICAvLyBjb25zdHJhaW4gbGF5b3V0IGJvdW5kczsgeyB4MSwgeTEsIHgyLCB5MiB9IG9yIHsgeDEsIHkxLCB3LCBoIH1cbiAgYXZvaWRPdmVybGFwOiB0cnVlLFxuICAvLyBwcmV2ZW50cyBub2RlIG92ZXJsYXAsIG1heSBvdmVyZmxvdyBib3VuZGluZ0JveCBpZiBub3QgZW5vdWdoIHNwYWNlXG4gIGF2b2lkT3ZlcmxhcFBhZGRpbmc6IDEwLFxuICAvLyBleHRyYSBzcGFjaW5nIGFyb3VuZCBub2RlcyB3aGVuIGF2b2lkT3ZlcmxhcDogdHJ1ZVxuICBub2RlRGltZW5zaW9uc0luY2x1ZGVMYWJlbHM6IGZhbHNlLFxuICAvLyBFeGNsdWRlcyB0aGUgbGFiZWwgd2hlbiBjYWxjdWxhdGluZyBub2RlIGJvdW5kaW5nIGJveGVzIGZvciB0aGUgbGF5b3V0IGFsZ29yaXRobVxuICBzcGFjaW5nRmFjdG9yOiB1bmRlZmluZWQsXG4gIC8vIEFwcGxpZXMgYSBtdWx0aXBsaWNhdGl2ZSBmYWN0b3IgKD4wKSB0byBleHBhbmQgb3IgY29tcHJlc3MgdGhlIG92ZXJhbGwgYXJlYSB0aGF0IHRoZSBub2RlcyB0YWtlIHVwXG4gIGNvbmRlbnNlOiBmYWxzZSxcbiAgLy8gdXNlcyBhbGwgYXZhaWxhYmxlIHNwYWNlIG9uIGZhbHNlLCB1c2VzIG1pbmltYWwgc3BhY2Ugb24gdHJ1ZVxuICByb3dzOiB1bmRlZmluZWQsXG4gIC8vIGZvcmNlIG51bSBvZiByb3dzIGluIHRoZSBncmlkXG4gIGNvbHM6IHVuZGVmaW5lZCxcbiAgLy8gZm9yY2UgbnVtIG9mIGNvbHVtbnMgaW4gdGhlIGdyaWRcbiAgcG9zaXRpb246IGZ1bmN0aW9uIHBvc2l0aW9uKG5vZGUpIHt9LFxuICAvLyByZXR1cm5zIHsgcm93LCBjb2wgfSBmb3IgZWxlbWVudFxuICBzb3J0OiB1bmRlZmluZWQsXG4gIC8vIGEgc29ydGluZyBmdW5jdGlvbiB0byBvcmRlciB0aGUgbm9kZXM7IGUuZy4gZnVuY3Rpb24oYSwgYil7IHJldHVybiBhLmRhdGEoJ3dlaWdodCcpIC0gYi5kYXRhKCd3ZWlnaHQnKSB9XG4gIGFuaW1hdGU6IGZhbHNlLFxuICAvLyB3aGV0aGVyIHRvIHRyYW5zaXRpb24gdGhlIG5vZGUgcG9zaXRpb25zXG4gIGFuaW1hdGlvbkR1cmF0aW9uOiA1MDAsXG4gIC8vIGR1cmF0aW9uIG9mIGFuaW1hdGlvbiBpbiBtcyBpZiBlbmFibGVkXG4gIGFuaW1hdGlvbkVhc2luZzogdW5kZWZpbmVkLFxuICAvLyBlYXNpbmcgb2YgYW5pbWF0aW9uIGlmIGVuYWJsZWRcbiAgYW5pbWF0ZUZpbHRlcjogZnVuY3Rpb24gYW5pbWF0ZUZpbHRlcihub2RlLCBpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIC8vIGEgZnVuY3Rpb24gdGhhdCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIG5vZGUgc2hvdWxkIGJlIGFuaW1hdGVkLiAgQWxsIG5vZGVzIGFuaW1hdGVkIGJ5IGRlZmF1bHQgb24gYW5pbWF0ZSBlbmFibGVkLiAgTm9uLWFuaW1hdGVkIG5vZGVzIGFyZSBwb3NpdGlvbmVkIGltbWVkaWF0ZWx5IHdoZW4gdGhlIGxheW91dCBzdGFydHNcbiAgcmVhZHk6IHVuZGVmaW5lZCxcbiAgLy8gY2FsbGJhY2sgb24gbGF5b3V0cmVhZHlcbiAgc3RvcDogdW5kZWZpbmVkLFxuICAvLyBjYWxsYmFjayBvbiBsYXlvdXRzdG9wXG4gIHRyYW5zZm9ybTogZnVuY3Rpb24gdHJhbnNmb3JtKG5vZGUsIHBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIHBvc2l0aW9uO1xuICB9IC8vIHRyYW5zZm9ybSBhIGdpdmVuIG5vZGUgcG9zaXRpb24uIFVzZWZ1bCBmb3IgY2hhbmdpbmcgZmxvdyBkaXJlY3Rpb24gaW4gZGlzY3JldGUgbGF5b3V0cyBcblxufTtcblxuZnVuY3Rpb24gR3JpZExheW91dChvcHRpb25zKSB7XG4gIHRoaXMub3B0aW9ucyA9IGV4dGVuZCh7fSwgZGVmYXVsdHMkZCwgb3B0aW9ucyk7XG59XG5cbkdyaWRMYXlvdXQucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHBhcmFtcyA9IHRoaXMub3B0aW9ucztcbiAgdmFyIG9wdGlvbnMgPSBwYXJhbXM7XG4gIHZhciBjeSA9IHBhcmFtcy5jeTtcbiAgdmFyIGVsZXMgPSBvcHRpb25zLmVsZXM7XG4gIHZhciBub2RlcyA9IGVsZXMubm9kZXMoKS5ub3QoJzpwYXJlbnQnKTtcblxuICBpZiAob3B0aW9ucy5zb3J0KSB7XG4gICAgbm9kZXMgPSBub2Rlcy5zb3J0KG9wdGlvbnMuc29ydCk7XG4gIH1cblxuICB2YXIgYmIgPSBtYWtlQm91bmRpbmdCb3gob3B0aW9ucy5ib3VuZGluZ0JveCA/IG9wdGlvbnMuYm91bmRpbmdCb3ggOiB7XG4gICAgeDE6IDAsXG4gICAgeTE6IDAsXG4gICAgdzogY3kud2lkdGgoKSxcbiAgICBoOiBjeS5oZWlnaHQoKVxuICB9KTtcblxuICBpZiAoYmIuaCA9PT0gMCB8fCBiYi53ID09PSAwKSB7XG4gICAgbm9kZXMubGF5b3V0UG9zaXRpb25zKHRoaXMsIG9wdGlvbnMsIGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHg6IGJiLngxLFxuICAgICAgICB5OiBiYi55MVxuICAgICAgfTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICAvLyB3aWR0aC9oZWlnaHQgKiBzcGxpdHNeMiA9IGNlbGxzIHdoZXJlIHNwbGl0cyBpcyBudW1iZXIgb2YgdGltZXMgdG8gc3BsaXQgd2lkdGhcbiAgICB2YXIgY2VsbHMgPSBub2Rlcy5zaXplKCk7XG4gICAgdmFyIHNwbGl0cyA9IE1hdGguc3FydChjZWxscyAqIGJiLmggLyBiYi53KTtcbiAgICB2YXIgcm93cyA9IE1hdGgucm91bmQoc3BsaXRzKTtcbiAgICB2YXIgY29scyA9IE1hdGgucm91bmQoYmIudyAvIGJiLmggKiBzcGxpdHMpO1xuXG4gICAgdmFyIHNtYWxsID0gZnVuY3Rpb24gc21hbGwodmFsKSB7XG4gICAgICBpZiAodmFsID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWluKHJvd3MsIGNvbHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG1pbiA9IE1hdGgubWluKHJvd3MsIGNvbHMpO1xuXG4gICAgICAgIGlmIChtaW4gPT0gcm93cykge1xuICAgICAgICAgIHJvd3MgPSB2YWw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29scyA9IHZhbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgbGFyZ2UgPSBmdW5jdGlvbiBsYXJnZSh2YWwpIHtcbiAgICAgIGlmICh2YWwgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgocm93cywgY29scyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbWF4ID0gTWF0aC5tYXgocm93cywgY29scyk7XG5cbiAgICAgICAgaWYgKG1heCA9PSByb3dzKSB7XG4gICAgICAgICAgcm93cyA9IHZhbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb2xzID0gdmFsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHZhciBvUm93cyA9IG9wdGlvbnMucm93cztcbiAgICB2YXIgb0NvbHMgPSBvcHRpb25zLmNvbHMgIT0gbnVsbCA/IG9wdGlvbnMuY29scyA6IG9wdGlvbnMuY29sdW1uczsgLy8gaWYgcm93cyBvciBjb2x1bW5zIHdlcmUgc2V0IGluIG9wdGlvbnMsIHVzZSB0aG9zZSB2YWx1ZXNcblxuICAgIGlmIChvUm93cyAhPSBudWxsICYmIG9Db2xzICE9IG51bGwpIHtcbiAgICAgIHJvd3MgPSBvUm93cztcbiAgICAgIGNvbHMgPSBvQ29scztcbiAgICB9IGVsc2UgaWYgKG9Sb3dzICE9IG51bGwgJiYgb0NvbHMgPT0gbnVsbCkge1xuICAgICAgcm93cyA9IG9Sb3dzO1xuICAgICAgY29scyA9IE1hdGguY2VpbChjZWxscyAvIHJvd3MpO1xuICAgIH0gZWxzZSBpZiAob1Jvd3MgPT0gbnVsbCAmJiBvQ29scyAhPSBudWxsKSB7XG4gICAgICBjb2xzID0gb0NvbHM7XG4gICAgICByb3dzID0gTWF0aC5jZWlsKGNlbGxzIC8gY29scyk7XG4gICAgfSAvLyBvdGhlcndpc2UgdXNlIHRoZSBhdXRvbWF0aWMgdmFsdWVzIGFuZCBhZGp1c3QgYWNjb3JkaW5nbHlcbiAgICAvLyBpZiByb3VuZGluZyB3YXMgdXAsIHNlZSBpZiB3ZSBjYW4gcmVkdWNlIHJvd3Mgb3IgY29sdW1uc1xuICAgIGVsc2UgaWYgKGNvbHMgKiByb3dzID4gY2VsbHMpIHtcbiAgICAgICAgdmFyIHNtID0gc21hbGwoKTtcbiAgICAgICAgdmFyIGxnID0gbGFyZ2UoKTsgLy8gcmVkdWNpbmcgdGhlIHNtYWxsIHNpZGUgdGFrZXMgYXdheSB0aGUgbW9zdCBjZWxscywgc28gdHJ5IGl0IGZpcnN0XG5cbiAgICAgICAgaWYgKChzbSAtIDEpICogbGcgPj0gY2VsbHMpIHtcbiAgICAgICAgICBzbWFsbChzbSAtIDEpO1xuICAgICAgICB9IGVsc2UgaWYgKChsZyAtIDEpICogc20gPj0gY2VsbHMpIHtcbiAgICAgICAgICBsYXJnZShsZyAtIDEpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBpZiByb3VuZGluZyB3YXMgdG9vIGxvdywgYWRkIHJvd3Mgb3IgY29sdW1uc1xuICAgICAgICB3aGlsZSAoY29scyAqIHJvd3MgPCBjZWxscykge1xuICAgICAgICAgIHZhciBfc20gPSBzbWFsbCgpO1xuXG4gICAgICAgICAgdmFyIF9sZyA9IGxhcmdlKCk7IC8vIHRyeSB0byBhZGQgdG8gbGFyZ2VyIHNpZGUgZmlyc3QgKGFkZHMgbGVzcyBpbiBtdWx0aXBsaWNhdGlvbilcblxuXG4gICAgICAgICAgaWYgKChfbGcgKyAxKSAqIF9zbSA+PSBjZWxscykge1xuICAgICAgICAgICAgbGFyZ2UoX2xnICsgMSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNtYWxsKF9zbSArIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgdmFyIGNlbGxXaWR0aCA9IGJiLncgLyBjb2xzO1xuICAgIHZhciBjZWxsSGVpZ2h0ID0gYmIuaCAvIHJvd3M7XG5cbiAgICBpZiAob3B0aW9ucy5jb25kZW5zZSkge1xuICAgICAgY2VsbFdpZHRoID0gMDtcbiAgICAgIGNlbGxIZWlnaHQgPSAwO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmF2b2lkT3ZlcmxhcCkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICB2YXIgcG9zID0gbm9kZS5fcHJpdmF0ZS5wb3NpdGlvbjtcblxuICAgICAgICBpZiAocG9zLnggPT0gbnVsbCB8fCBwb3MueSA9PSBudWxsKSB7XG4gICAgICAgICAgLy8gZm9yIGJiXG4gICAgICAgICAgcG9zLnggPSAwO1xuICAgICAgICAgIHBvcy55ID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBuYmIgPSBub2RlLmxheW91dERpbWVuc2lvbnMob3B0aW9ucyk7XG4gICAgICAgIHZhciBwID0gb3B0aW9ucy5hdm9pZE92ZXJsYXBQYWRkaW5nO1xuICAgICAgICB2YXIgdyA9IG5iYi53ICsgcDtcbiAgICAgICAgdmFyIGggPSBuYmIuaCArIHA7XG4gICAgICAgIGNlbGxXaWR0aCA9IE1hdGgubWF4KGNlbGxXaWR0aCwgdyk7XG4gICAgICAgIGNlbGxIZWlnaHQgPSBNYXRoLm1heChjZWxsSGVpZ2h0LCBoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY2VsbFVzZWQgPSB7fTsgLy8gZS5nLiAnYy0wLTInID0+IHRydWVcblxuICAgIHZhciB1c2VkID0gZnVuY3Rpb24gdXNlZChyb3csIGNvbCkge1xuICAgICAgcmV0dXJuIGNlbGxVc2VkWydjLScgKyByb3cgKyAnLScgKyBjb2xdID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH07XG5cbiAgICB2YXIgdXNlID0gZnVuY3Rpb24gdXNlKHJvdywgY29sKSB7XG4gICAgICBjZWxsVXNlZFsnYy0nICsgcm93ICsgJy0nICsgY29sXSA9IHRydWU7XG4gICAgfTsgLy8gdG8ga2VlcCB0cmFjayBvZiBjdXJyZW50IGNlbGwgcG9zaXRpb25cblxuXG4gICAgdmFyIHJvdyA9IDA7XG4gICAgdmFyIGNvbCA9IDA7XG5cbiAgICB2YXIgbW92ZVRvTmV4dENlbGwgPSBmdW5jdGlvbiBtb3ZlVG9OZXh0Q2VsbCgpIHtcbiAgICAgIGNvbCsrO1xuXG4gICAgICBpZiAoY29sID49IGNvbHMpIHtcbiAgICAgICAgY29sID0gMDtcbiAgICAgICAgcm93Kys7XG4gICAgICB9XG4gICAgfTsgLy8gZ2V0IGEgY2FjaGUgb2YgYWxsIHRoZSBtYW51YWwgcG9zaXRpb25zXG5cblxuICAgIHZhciBpZDJtYW5Qb3MgPSB7fTtcblxuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBub2Rlcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgIHZhciBfbm9kZSA9IG5vZGVzW19pXTtcbiAgICAgIHZhciByY1BvcyA9IG9wdGlvbnMucG9zaXRpb24oX25vZGUpO1xuXG4gICAgICBpZiAocmNQb3MgJiYgKHJjUG9zLnJvdyAhPT0gdW5kZWZpbmVkIHx8IHJjUG9zLmNvbCAhPT0gdW5kZWZpbmVkKSkge1xuICAgICAgICAvLyBtdXN0IGhhdmUgYXQgbGVhc3Qgcm93IG9yIGNvbCBkZWYnZFxuICAgICAgICB2YXIgX3BvcyA9IHtcbiAgICAgICAgICByb3c6IHJjUG9zLnJvdyxcbiAgICAgICAgICBjb2w6IHJjUG9zLmNvbFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChfcG9zLmNvbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgLy8gZmluZCB1bnVzZWQgY29sXG4gICAgICAgICAgX3Bvcy5jb2wgPSAwO1xuXG4gICAgICAgICAgd2hpbGUgKHVzZWQoX3Bvcy5yb3csIF9wb3MuY29sKSkge1xuICAgICAgICAgICAgX3Bvcy5jb2wrKztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoX3Bvcy5yb3cgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIC8vIGZpbmQgdW51c2VkIHJvd1xuICAgICAgICAgIF9wb3Mucm93ID0gMDtcblxuICAgICAgICAgIHdoaWxlICh1c2VkKF9wb3Mucm93LCBfcG9zLmNvbCkpIHtcbiAgICAgICAgICAgIF9wb3Mucm93Kys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWQybWFuUG9zW19ub2RlLmlkKCldID0gX3BvcztcbiAgICAgICAgdXNlKF9wb3Mucm93LCBfcG9zLmNvbCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGdldFBvcyA9IGZ1bmN0aW9uIGdldFBvcyhlbGVtZW50LCBpKSB7XG4gICAgICB2YXIgeCwgeTtcblxuICAgICAgaWYgKGVsZW1lbnQubG9ja2VkKCkgfHwgZWxlbWVudC5pc1BhcmVudCgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0gLy8gc2VlIGlmIHdlIGhhdmUgYSBtYW51YWwgcG9zaXRpb24gc2V0XG5cblxuICAgICAgdmFyIHJjUG9zID0gaWQybWFuUG9zW2VsZW1lbnQuaWQoKV07XG5cbiAgICAgIGlmIChyY1Bvcykge1xuICAgICAgICB4ID0gcmNQb3MuY29sICogY2VsbFdpZHRoICsgY2VsbFdpZHRoIC8gMiArIGJiLngxO1xuICAgICAgICB5ID0gcmNQb3Mucm93ICogY2VsbEhlaWdodCArIGNlbGxIZWlnaHQgLyAyICsgYmIueTE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBvdGhlcndpc2Ugc2V0IGF1dG9tYXRpY2FsbHlcbiAgICAgICAgd2hpbGUgKHVzZWQocm93LCBjb2wpKSB7XG4gICAgICAgICAgbW92ZVRvTmV4dENlbGwoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHggPSBjb2wgKiBjZWxsV2lkdGggKyBjZWxsV2lkdGggLyAyICsgYmIueDE7XG4gICAgICAgIHkgPSByb3cgKiBjZWxsSGVpZ2h0ICsgY2VsbEhlaWdodCAvIDIgKyBiYi55MTtcbiAgICAgICAgdXNlKHJvdywgY29sKTtcbiAgICAgICAgbW92ZVRvTmV4dENlbGwoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgeDogeCxcbiAgICAgICAgeTogeVxuICAgICAgfTtcbiAgICB9O1xuXG4gICAgbm9kZXMubGF5b3V0UG9zaXRpb25zKHRoaXMsIG9wdGlvbnMsIGdldFBvcyk7XG4gIH1cblxuICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbn07XG5cbnZhciBkZWZhdWx0cyRlID0ge1xuICByZWFkeTogZnVuY3Rpb24gcmVhZHkoKSB7fSxcbiAgLy8gb24gbGF5b3V0cmVhZHlcbiAgc3RvcDogZnVuY3Rpb24gc3RvcCgpIHt9IC8vIG9uIGxheW91dHN0b3BcblxufTsgLy8gY29uc3RydWN0b3Jcbi8vIG9wdGlvbnMgOiBvYmplY3QgY29udGFpbmluZyBsYXlvdXQgb3B0aW9uc1xuXG5mdW5jdGlvbiBOdWxsTGF5b3V0KG9wdGlvbnMpIHtcbiAgdGhpcy5vcHRpb25zID0gZXh0ZW5kKHt9LCBkZWZhdWx0cyRlLCBvcHRpb25zKTtcbn0gLy8gcnVucyB0aGUgbGF5b3V0XG5cblxuTnVsbExheW91dC5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgdmFyIGVsZXMgPSBvcHRpb25zLmVsZXM7IC8vIGVsZW1lbnRzIHRvIGNvbnNpZGVyIGluIHRoZSBsYXlvdXRcblxuICB2YXIgbGF5b3V0ID0gdGhpczsgLy8gY3kgaXMgYXV0b21hdGljYWxseSBwb3B1bGF0ZWQgZm9yIHVzIGluIHRoZSBjb25zdHJ1Y3RvclxuICAvLyAoZGlzYWJsZSBlc2xpbnQgZm9yIG5leHQgbGluZSBhcyB0aGlzIHNlcnZlcyBhcyBleGFtcGxlIGxheW91dCBjb2RlIHRvIGV4dGVybmFsIGRldmVsb3BlcnMpXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuXG4gIHZhciBjeSA9IG9wdGlvbnMuY3k7XG4gIGxheW91dC5lbWl0KCdsYXlvdXRzdGFydCcpOyAvLyBwdXRzIGFsbCBub2RlcyBhdCAoMCwgMClcbiAgLy8gbi5iLiBtb3N0IGxheW91dHMgd291bGQgdXNlIGxheW91dFBvc2l0aW9ucygpLCBpbnN0ZWFkIG9mIHBvc2l0aW9ucygpIGFuZCBtYW51YWwgZXZlbnRzXG5cbiAgZWxlcy5ub2RlcygpLnBvc2l0aW9ucyhmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IDAsXG4gICAgICB5OiAwXG4gICAgfTtcbiAgfSk7IC8vIHRyaWdnZXIgbGF5b3V0cmVhZHkgd2hlbiBlYWNoIG5vZGUgaGFzIGhhZCBpdHMgcG9zaXRpb24gc2V0IGF0IGxlYXN0IG9uY2VcblxuICBsYXlvdXQub25lKCdsYXlvdXRyZWFkeScsIG9wdGlvbnMucmVhZHkpO1xuICBsYXlvdXQuZW1pdCgnbGF5b3V0cmVhZHknKTsgLy8gdHJpZ2dlciBsYXlvdXRzdG9wIHdoZW4gdGhlIGxheW91dCBzdG9wcyAoZS5nLiBmaW5pc2hlcylcblxuICBsYXlvdXQub25lKCdsYXlvdXRzdG9wJywgb3B0aW9ucy5zdG9wKTtcbiAgbGF5b3V0LmVtaXQoJ2xheW91dHN0b3AnKTtcbiAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG59OyAvLyBjYWxsZWQgb24gY29udGludW91cyBsYXlvdXRzIHRvIHN0b3AgdGhlbSBiZWZvcmUgdGhleSBmaW5pc2hcblxuXG5OdWxsTGF5b3V0LnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpczsgLy8gY2hhaW5pbmdcbn07XG5cbnZhciBkZWZhdWx0cyRmID0ge1xuICBwb3NpdGlvbnM6IHVuZGVmaW5lZCxcbiAgLy8gbWFwIG9mIChub2RlIGlkKSA9PiAocG9zaXRpb24gb2JqKTsgb3IgZnVuY3Rpb24obm9kZSl7IHJldHVybiBzb21Qb3M7IH1cbiAgem9vbTogdW5kZWZpbmVkLFxuICAvLyB0aGUgem9vbSBsZXZlbCB0byBzZXQgKHByb2Igd2FudCBmaXQgPSBmYWxzZSBpZiBzZXQpXG4gIHBhbjogdW5kZWZpbmVkLFxuICAvLyB0aGUgcGFuIGxldmVsIHRvIHNldCAocHJvYiB3YW50IGZpdCA9IGZhbHNlIGlmIHNldClcbiAgZml0OiB0cnVlLFxuICAvLyB3aGV0aGVyIHRvIGZpdCB0byB2aWV3cG9ydFxuICBwYWRkaW5nOiAzMCxcbiAgLy8gcGFkZGluZyBvbiBmaXRcbiAgYW5pbWF0ZTogZmFsc2UsXG4gIC8vIHdoZXRoZXIgdG8gdHJhbnNpdGlvbiB0aGUgbm9kZSBwb3NpdGlvbnNcbiAgYW5pbWF0aW9uRHVyYXRpb246IDUwMCxcbiAgLy8gZHVyYXRpb24gb2YgYW5pbWF0aW9uIGluIG1zIGlmIGVuYWJsZWRcbiAgYW5pbWF0aW9uRWFzaW5nOiB1bmRlZmluZWQsXG4gIC8vIGVhc2luZyBvZiBhbmltYXRpb24gaWYgZW5hYmxlZFxuICBhbmltYXRlRmlsdGVyOiBmdW5jdGlvbiBhbmltYXRlRmlsdGVyKG5vZGUsIGkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgLy8gYSBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgd2hldGhlciB0aGUgbm9kZSBzaG91bGQgYmUgYW5pbWF0ZWQuICBBbGwgbm9kZXMgYW5pbWF0ZWQgYnkgZGVmYXVsdCBvbiBhbmltYXRlIGVuYWJsZWQuICBOb24tYW5pbWF0ZWQgbm9kZXMgYXJlIHBvc2l0aW9uZWQgaW1tZWRpYXRlbHkgd2hlbiB0aGUgbGF5b3V0IHN0YXJ0c1xuICByZWFkeTogdW5kZWZpbmVkLFxuICAvLyBjYWxsYmFjayBvbiBsYXlvdXRyZWFkeVxuICBzdG9wOiB1bmRlZmluZWQsXG4gIC8vIGNhbGxiYWNrIG9uIGxheW91dHN0b3BcbiAgdHJhbnNmb3JtOiBmdW5jdGlvbiB0cmFuc2Zvcm0obm9kZSwgcG9zaXRpb24pIHtcbiAgICByZXR1cm4gcG9zaXRpb247XG4gIH0gLy8gdHJhbnNmb3JtIGEgZ2l2ZW4gbm9kZSBwb3NpdGlvbi4gVXNlZnVsIGZvciBjaGFuZ2luZyBmbG93IGRpcmVjdGlvbiBpbiBkaXNjcmV0ZSBsYXlvdXRzXG5cbn07XG5cbmZ1bmN0aW9uIFByZXNldExheW91dChvcHRpb25zKSB7XG4gIHRoaXMub3B0aW9ucyA9IGV4dGVuZCh7fSwgZGVmYXVsdHMkZiwgb3B0aW9ucyk7XG59XG5cblByZXNldExheW91dC5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgdmFyIGVsZXMgPSBvcHRpb25zLmVsZXM7XG4gIHZhciBub2RlcyA9IGVsZXMubm9kZXMoKTtcbiAgdmFyIHBvc0lzRm4gPSBmbihvcHRpb25zLnBvc2l0aW9ucyk7XG5cbiAgZnVuY3Rpb24gZ2V0UG9zaXRpb24obm9kZSkge1xuICAgIGlmIChvcHRpb25zLnBvc2l0aW9ucyA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29weVBvc2l0aW9uKG5vZGUucG9zaXRpb24oKSk7XG4gICAgfVxuXG4gICAgaWYgKHBvc0lzRm4pIHtcbiAgICAgIHJldHVybiBvcHRpb25zLnBvc2l0aW9ucyhub2RlKTtcbiAgICB9XG5cbiAgICB2YXIgcG9zID0gb3B0aW9ucy5wb3NpdGlvbnNbbm9kZS5fcHJpdmF0ZS5kYXRhLmlkXTtcblxuICAgIGlmIChwb3MgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvcztcbiAgfVxuXG4gIG5vZGVzLmxheW91dFBvc2l0aW9ucyh0aGlzLCBvcHRpb25zLCBmdW5jdGlvbiAobm9kZSwgaSkge1xuICAgIHZhciBwb3NpdGlvbiA9IGdldFBvc2l0aW9uKG5vZGUpO1xuXG4gICAgaWYgKG5vZGUubG9ja2VkKCkgfHwgcG9zaXRpb24gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiBwb3NpdGlvbjtcbiAgfSk7XG4gIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xufTtcblxudmFyIGRlZmF1bHRzJGcgPSB7XG4gIGZpdDogdHJ1ZSxcbiAgLy8gd2hldGhlciB0byBmaXQgdG8gdmlld3BvcnRcbiAgcGFkZGluZzogMzAsXG4gIC8vIGZpdCBwYWRkaW5nXG4gIGJvdW5kaW5nQm94OiB1bmRlZmluZWQsXG4gIC8vIGNvbnN0cmFpbiBsYXlvdXQgYm91bmRzOyB7IHgxLCB5MSwgeDIsIHkyIH0gb3IgeyB4MSwgeTEsIHcsIGggfVxuICBhbmltYXRlOiBmYWxzZSxcbiAgLy8gd2hldGhlciB0byB0cmFuc2l0aW9uIHRoZSBub2RlIHBvc2l0aW9uc1xuICBhbmltYXRpb25EdXJhdGlvbjogNTAwLFxuICAvLyBkdXJhdGlvbiBvZiBhbmltYXRpb24gaW4gbXMgaWYgZW5hYmxlZFxuICBhbmltYXRpb25FYXNpbmc6IHVuZGVmaW5lZCxcbiAgLy8gZWFzaW5nIG9mIGFuaW1hdGlvbiBpZiBlbmFibGVkXG4gIGFuaW1hdGVGaWx0ZXI6IGZ1bmN0aW9uIGFuaW1hdGVGaWx0ZXIobm9kZSwgaSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICAvLyBhIGZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBub2RlIHNob3VsZCBiZSBhbmltYXRlZC4gIEFsbCBub2RlcyBhbmltYXRlZCBieSBkZWZhdWx0IG9uIGFuaW1hdGUgZW5hYmxlZC4gIE5vbi1hbmltYXRlZCBub2RlcyBhcmUgcG9zaXRpb25lZCBpbW1lZGlhdGVseSB3aGVuIHRoZSBsYXlvdXQgc3RhcnRzXG4gIHJlYWR5OiB1bmRlZmluZWQsXG4gIC8vIGNhbGxiYWNrIG9uIGxheW91dHJlYWR5XG4gIHN0b3A6IHVuZGVmaW5lZCxcbiAgLy8gY2FsbGJhY2sgb24gbGF5b3V0c3RvcFxuICB0cmFuc2Zvcm06IGZ1bmN0aW9uIHRyYW5zZm9ybShub2RlLCBwb3NpdGlvbikge1xuICAgIHJldHVybiBwb3NpdGlvbjtcbiAgfSAvLyB0cmFuc2Zvcm0gYSBnaXZlbiBub2RlIHBvc2l0aW9uLiBVc2VmdWwgZm9yIGNoYW5naW5nIGZsb3cgZGlyZWN0aW9uIGluIGRpc2NyZXRlIGxheW91dHMgXG5cbn07XG5cbmZ1bmN0aW9uIFJhbmRvbUxheW91dChvcHRpb25zKSB7XG4gIHRoaXMub3B0aW9ucyA9IGV4dGVuZCh7fSwgZGVmYXVsdHMkZywgb3B0aW9ucyk7XG59XG5cblJhbmRvbUxheW91dC5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgdmFyIGN5ID0gb3B0aW9ucy5jeTtcbiAgdmFyIGVsZXMgPSBvcHRpb25zLmVsZXM7XG4gIHZhciBub2RlcyA9IGVsZXMubm9kZXMoKS5ub3QoJzpwYXJlbnQnKTtcbiAgdmFyIGJiID0gbWFrZUJvdW5kaW5nQm94KG9wdGlvbnMuYm91bmRpbmdCb3ggPyBvcHRpb25zLmJvdW5kaW5nQm94IDoge1xuICAgIHgxOiAwLFxuICAgIHkxOiAwLFxuICAgIHc6IGN5LndpZHRoKCksXG4gICAgaDogY3kuaGVpZ2h0KClcbiAgfSk7XG5cbiAgdmFyIGdldFBvcyA9IGZ1bmN0aW9uIGdldFBvcyhub2RlLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IGJiLngxICsgTWF0aC5yb3VuZChNYXRoLnJhbmRvbSgpICogYmIudyksXG4gICAgICB5OiBiYi55MSArIE1hdGgucm91bmQoTWF0aC5yYW5kb20oKSAqIGJiLmgpXG4gICAgfTtcbiAgfTtcblxuICBub2Rlcy5sYXlvdXRQb3NpdGlvbnModGhpcywgb3B0aW9ucywgZ2V0UG9zKTtcbiAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG59O1xuXG52YXIgbGF5b3V0ID0gW3tcbiAgbmFtZTogJ2JyZWFkdGhmaXJzdCcsXG4gIGltcGw6IEJyZWFkdGhGaXJzdExheW91dFxufSwge1xuICBuYW1lOiAnY2lyY2xlJyxcbiAgaW1wbDogQ2lyY2xlTGF5b3V0XG59LCB7XG4gIG5hbWU6ICdjb25jZW50cmljJyxcbiAgaW1wbDogQ29uY2VudHJpY0xheW91dFxufSwge1xuICBuYW1lOiAnY29zZScsXG4gIGltcGw6IENvc2VMYXlvdXRcbn0sIHtcbiAgbmFtZTogJ2dyaWQnLFxuICBpbXBsOiBHcmlkTGF5b3V0XG59LCB7XG4gIG5hbWU6ICdudWxsJyxcbiAgaW1wbDogTnVsbExheW91dFxufSwge1xuICBuYW1lOiAncHJlc2V0JyxcbiAgaW1wbDogUHJlc2V0TGF5b3V0XG59LCB7XG4gIG5hbWU6ICdyYW5kb20nLFxuICBpbXBsOiBSYW5kb21MYXlvdXRcbn1dO1xuXG5mdW5jdGlvbiBOdWxsUmVuZGVyZXIob3B0aW9ucykge1xuICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICB0aGlzLm5vdGlmaWNhdGlvbnMgPSAwOyAvLyBmb3IgdGVzdGluZ1xufVxuXG52YXIgbm9vcCQxID0gZnVuY3Rpb24gbm9vcCgpIHt9O1xuXG52YXIgdGhyb3dJbWdFcnIgPSBmdW5jdGlvbiB0aHJvd0ltZ0VycigpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdBIGhlYWRsZXNzIGluc3RhbmNlIGNhbiBub3QgcmVuZGVyIGltYWdlcycpO1xufTtcblxuTnVsbFJlbmRlcmVyLnByb3RvdHlwZSA9IHtcbiAgcmVjYWxjdWxhdGVSZW5kZXJlZFN0eWxlOiBub29wJDEsXG4gIG5vdGlmeTogZnVuY3Rpb24gbm90aWZ5KCkge1xuICAgIHRoaXMubm90aWZpY2F0aW9ucysrO1xuICB9LFxuICBpbml0OiBub29wJDEsXG4gIGlzSGVhZGxlc3M6IGZ1bmN0aW9uIGlzSGVhZGxlc3MoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIHBuZzogdGhyb3dJbWdFcnIsXG4gIGpwZzogdGhyb3dJbWdFcnJcbn07XG5cbnZhciBCUnAgPSB7fTtcbkJScC5hcnJvd1NoYXBlV2lkdGggPSAwLjM7XG5cbkJScC5yZWdpc3RlckFycm93U2hhcGVzID0gZnVuY3Rpb24gKCkge1xuICB2YXIgYXJyb3dTaGFwZXMgPSB0aGlzLmFycm93U2hhcGVzID0ge307XG4gIHZhciByZW5kZXJlciA9IHRoaXM7IC8vIENvbnRyYWN0IGZvciBhcnJvdyBzaGFwZXM6XG4gIC8vIDAsIDAgaXMgYXJyb3cgdGlwXG4gIC8vICgwLCAxKSBpcyBkaXJlY3Rpb24gdG93YXJkcyBub2RlXG4gIC8vICgxLCAwKSBpcyByaWdodFxuICAvL1xuICAvLyBmdW5jdGlvbmFsIGFwaTpcbiAgLy8gY29sbGlkZTogY2hlY2sgeCwgeSBpbiBzaGFwZVxuICAvLyByb3VnaENvbGxpZGU6IGNhbGxlZCBiZWZvcmUgY29sbGlkZSwgbm8gZmFsc2UgbmVnYXRpdmVzXG4gIC8vIGRyYXc6IGRyYXdcbiAgLy8gc3BhY2luZzogZGlzdChhcnJvd1RpcCwgbm9kZUJvdW5kYXJ5KVxuICAvLyBnYXA6IGRpc3QoZWRnZVRpcCwgbm9kZUJvdW5kYXJ5KSwgZWRnZVRpcCBtYXkgIT0gYXJyb3dUaXBcblxuICB2YXIgYmJDb2xsaWRlID0gZnVuY3Rpb24gYmJDb2xsaWRlKHgsIHksIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbiwgZWRnZVdpZHRoLCBwYWRkaW5nKSB7XG4gICAgdmFyIHgxID0gdHJhbnNsYXRpb24ueCAtIHNpemUgLyAyIC0gcGFkZGluZztcbiAgICB2YXIgeDIgPSB0cmFuc2xhdGlvbi54ICsgc2l6ZSAvIDIgKyBwYWRkaW5nO1xuICAgIHZhciB5MSA9IHRyYW5zbGF0aW9uLnkgLSBzaXplIC8gMiAtIHBhZGRpbmc7XG4gICAgdmFyIHkyID0gdHJhbnNsYXRpb24ueSArIHNpemUgLyAyICsgcGFkZGluZztcbiAgICB2YXIgaW5zaWRlID0geDEgPD0geCAmJiB4IDw9IHgyICYmIHkxIDw9IHkgJiYgeSA8PSB5MjtcbiAgICByZXR1cm4gaW5zaWRlO1xuICB9O1xuXG4gIHZhciB0cmFuc2Zvcm0gPSBmdW5jdGlvbiB0cmFuc2Zvcm0oeCwgeSwgc2l6ZSwgYW5nbGUsIHRyYW5zbGF0aW9uKSB7XG4gICAgdmFyIHhSb3RhdGVkID0geCAqIE1hdGguY29zKGFuZ2xlKSAtIHkgKiBNYXRoLnNpbihhbmdsZSk7XG4gICAgdmFyIHlSb3RhdGVkID0geCAqIE1hdGguc2luKGFuZ2xlKSArIHkgKiBNYXRoLmNvcyhhbmdsZSk7XG4gICAgdmFyIHhTY2FsZWQgPSB4Um90YXRlZCAqIHNpemU7XG4gICAgdmFyIHlTY2FsZWQgPSB5Um90YXRlZCAqIHNpemU7XG4gICAgdmFyIHhUcmFuc2xhdGVkID0geFNjYWxlZCArIHRyYW5zbGF0aW9uLng7XG4gICAgdmFyIHlUcmFuc2xhdGVkID0geVNjYWxlZCArIHRyYW5zbGF0aW9uLnk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHhUcmFuc2xhdGVkLFxuICAgICAgeTogeVRyYW5zbGF0ZWRcbiAgICB9O1xuICB9O1xuXG4gIHZhciB0cmFuc2Zvcm1Qb2ludHMgPSBmdW5jdGlvbiB0cmFuc2Zvcm1Qb2ludHMocHRzLCBzaXplLCBhbmdsZSwgdHJhbnNsYXRpb24pIHtcbiAgICB2YXIgcmV0UHRzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHB0cy5sZW5ndGg7IGkgKz0gMikge1xuICAgICAgdmFyIHggPSBwdHNbaV07XG4gICAgICB2YXIgeSA9IHB0c1tpICsgMV07XG4gICAgICByZXRQdHMucHVzaCh0cmFuc2Zvcm0oeCwgeSwgc2l6ZSwgYW5nbGUsIHRyYW5zbGF0aW9uKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldFB0cztcbiAgfTtcblxuICB2YXIgcG9pbnRzVG9BcnIgPSBmdW5jdGlvbiBwb2ludHNUb0FycihwdHMpIHtcbiAgICB2YXIgcmV0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHAgPSBwdHNbaV07XG4gICAgICByZXQucHVzaChwLngsIHAueSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfTtcblxuICB2YXIgc3RhbmRhcmRHYXAgPSBmdW5jdGlvbiBzdGFuZGFyZEdhcChlZGdlKSB7XG4gICAgcmV0dXJuIGVkZ2UucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWUgKiBlZGdlLnBzdHlsZSgnYXJyb3ctc2NhbGUnKS5wZlZhbHVlICogMjtcbiAgfTtcblxuICB2YXIgZGVmaW5lQXJyb3dTaGFwZSA9IGZ1bmN0aW9uIGRlZmluZUFycm93U2hhcGUobmFtZSwgZGVmbikge1xuICAgIGlmIChzdHJpbmcoZGVmbikpIHtcbiAgICAgIGRlZm4gPSBhcnJvd1NoYXBlc1tkZWZuXTtcbiAgICB9XG5cbiAgICBhcnJvd1NoYXBlc1tuYW1lXSA9IGV4dGVuZCh7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgcG9pbnRzOiBbLTAuMTUsIC0wLjMsIDAuMTUsIC0wLjMsIDAuMTUsIDAuMywgLTAuMTUsIDAuM10sXG4gICAgICBjb2xsaWRlOiBmdW5jdGlvbiBjb2xsaWRlKHgsIHksIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbiwgcGFkZGluZykge1xuICAgICAgICB2YXIgcG9pbnRzID0gcG9pbnRzVG9BcnIodHJhbnNmb3JtUG9pbnRzKHRoaXMucG9pbnRzLCBzaXplICsgMiAqIHBhZGRpbmcsIGFuZ2xlLCB0cmFuc2xhdGlvbikpO1xuICAgICAgICB2YXIgaW5zaWRlID0gcG9pbnRJbnNpZGVQb2x5Z29uUG9pbnRzKHgsIHksIHBvaW50cyk7XG4gICAgICAgIHJldHVybiBpbnNpZGU7XG4gICAgICB9LFxuICAgICAgcm91Z2hDb2xsaWRlOiBiYkNvbGxpZGUsXG4gICAgICBkcmF3OiBmdW5jdGlvbiBkcmF3KGNvbnRleHQsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbikge1xuICAgICAgICB2YXIgcG9pbnRzID0gdHJhbnNmb3JtUG9pbnRzKHRoaXMucG9pbnRzLCBzaXplLCBhbmdsZSwgdHJhbnNsYXRpb24pO1xuICAgICAgICByZW5kZXJlci5hcnJvd1NoYXBlSW1wbCgncG9seWdvbicpKGNvbnRleHQsIHBvaW50cyk7XG4gICAgICB9LFxuICAgICAgc3BhY2luZzogZnVuY3Rpb24gc3BhY2luZyhlZGdlKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSxcbiAgICAgIGdhcDogc3RhbmRhcmRHYXBcbiAgICB9LCBkZWZuKTtcbiAgfTtcblxuICBkZWZpbmVBcnJvd1NoYXBlKCdub25lJywge1xuICAgIGNvbGxpZGU6IGZhbHNpZnksXG4gICAgcm91Z2hDb2xsaWRlOiBmYWxzaWZ5LFxuICAgIGRyYXc6IG5vb3AsXG4gICAgc3BhY2luZzogemVyb2lmeSxcbiAgICBnYXA6IHplcm9pZnlcbiAgfSk7XG4gIGRlZmluZUFycm93U2hhcGUoJ3RyaWFuZ2xlJywge1xuICAgIHBvaW50czogWy0wLjE1LCAtMC4zLCAwLCAwLCAwLjE1LCAtMC4zXVxuICB9KTtcbiAgZGVmaW5lQXJyb3dTaGFwZSgnYXJyb3cnLCAndHJpYW5nbGUnKTtcbiAgZGVmaW5lQXJyb3dTaGFwZSgndHJpYW5nbGUtYmFja2N1cnZlJywge1xuICAgIHBvaW50czogYXJyb3dTaGFwZXNbJ3RyaWFuZ2xlJ10ucG9pbnRzLFxuICAgIGNvbnRyb2xQb2ludDogWzAsIC0wLjE1XSxcbiAgICByb3VnaENvbGxpZGU6IGJiQ29sbGlkZSxcbiAgICBkcmF3OiBmdW5jdGlvbiBkcmF3KGNvbnRleHQsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbiwgZWRnZVdpZHRoKSB7XG4gICAgICB2YXIgcHRzVHJhbnMgPSB0cmFuc2Zvcm1Qb2ludHModGhpcy5wb2ludHMsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbik7XG4gICAgICB2YXIgY3RybFB0ID0gdGhpcy5jb250cm9sUG9pbnQ7XG4gICAgICB2YXIgY3RybFB0VHJhbnMgPSB0cmFuc2Zvcm0oY3RybFB0WzBdLCBjdHJsUHRbMV0sIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbik7XG4gICAgICByZW5kZXJlci5hcnJvd1NoYXBlSW1wbCh0aGlzLm5hbWUpKGNvbnRleHQsIHB0c1RyYW5zLCBjdHJsUHRUcmFucyk7XG4gICAgfSxcbiAgICBnYXA6IGZ1bmN0aW9uIGdhcChlZGdlKSB7XG4gICAgICByZXR1cm4gc3RhbmRhcmRHYXAoZWRnZSkgKiAwLjg7XG4gICAgfVxuICB9KTtcbiAgZGVmaW5lQXJyb3dTaGFwZSgndHJpYW5nbGUtdGVlJywge1xuICAgIHBvaW50czogWzAsIDAsIDAuMTUsIC0wLjMsIC0wLjE1LCAtMC4zLCAwLCAwXSxcbiAgICBwb2ludHNUZWU6IFstMC4xNSwgLTAuNCwgLTAuMTUsIC0wLjUsIDAuMTUsIC0wLjUsIDAuMTUsIC0wLjRdLFxuICAgIGNvbGxpZGU6IGZ1bmN0aW9uIGNvbGxpZGUoeCwgeSwgc2l6ZSwgYW5nbGUsIHRyYW5zbGF0aW9uLCBlZGdlV2lkdGgsIHBhZGRpbmcpIHtcbiAgICAgIHZhciB0cmlQdHMgPSBwb2ludHNUb0Fycih0cmFuc2Zvcm1Qb2ludHModGhpcy5wb2ludHMsIHNpemUgKyAyICogcGFkZGluZywgYW5nbGUsIHRyYW5zbGF0aW9uKSk7XG4gICAgICB2YXIgdGVlUHRzID0gcG9pbnRzVG9BcnIodHJhbnNmb3JtUG9pbnRzKHRoaXMucG9pbnRzVGVlLCBzaXplICsgMiAqIHBhZGRpbmcsIGFuZ2xlLCB0cmFuc2xhdGlvbikpO1xuICAgICAgdmFyIGluc2lkZSA9IHBvaW50SW5zaWRlUG9seWdvblBvaW50cyh4LCB5LCB0cmlQdHMpIHx8IHBvaW50SW5zaWRlUG9seWdvblBvaW50cyh4LCB5LCB0ZWVQdHMpO1xuICAgICAgcmV0dXJuIGluc2lkZTtcbiAgICB9LFxuICAgIGRyYXc6IGZ1bmN0aW9uIGRyYXcoY29udGV4dCwgc2l6ZSwgYW5nbGUsIHRyYW5zbGF0aW9uLCBlZGdlV2lkdGgpIHtcbiAgICAgIHZhciB0cmlQdHMgPSB0cmFuc2Zvcm1Qb2ludHModGhpcy5wb2ludHMsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbik7XG4gICAgICB2YXIgdGVlUHRzID0gdHJhbnNmb3JtUG9pbnRzKHRoaXMucG9pbnRzVGVlLCBzaXplLCBhbmdsZSwgdHJhbnNsYXRpb24pO1xuICAgICAgcmVuZGVyZXIuYXJyb3dTaGFwZUltcGwodGhpcy5uYW1lKShjb250ZXh0LCB0cmlQdHMsIHRlZVB0cyk7XG4gICAgfVxuICB9KTtcbiAgZGVmaW5lQXJyb3dTaGFwZSgnY2lyY2xlLXRyaWFuZ2xlJywge1xuICAgIHJhZGl1czogMC4xNSxcbiAgICBwb2ludHNUcjogWzAsIC0wLjE1LCAwLjE1LCAtMC40NSwgLTAuMTUsIC0wLjQ1LCAwLCAtMC4xNV0sXG4gICAgY29sbGlkZTogZnVuY3Rpb24gY29sbGlkZSh4LCB5LCBzaXplLCBhbmdsZSwgdHJhbnNsYXRpb24sIGVkZ2VXaWR0aCwgcGFkZGluZykge1xuICAgICAgdmFyIHQgPSB0cmFuc2xhdGlvbjtcbiAgICAgIHZhciBjaXJjbGVJbnNpZGUgPSBNYXRoLnBvdyh0LnggLSB4LCAyKSArIE1hdGgucG93KHQueSAtIHksIDIpIDw9IE1hdGgucG93KChzaXplICsgMiAqIHBhZGRpbmcpICogdGhpcy5yYWRpdXMsIDIpO1xuICAgICAgdmFyIHRyaVB0cyA9IHBvaW50c1RvQXJyKHRyYW5zZm9ybVBvaW50cyh0aGlzLnBvaW50cywgc2l6ZSArIDIgKiBwYWRkaW5nLCBhbmdsZSwgdHJhbnNsYXRpb24pKTtcbiAgICAgIHJldHVybiBwb2ludEluc2lkZVBvbHlnb25Qb2ludHMoeCwgeSwgdHJpUHRzKSB8fCBjaXJjbGVJbnNpZGU7XG4gICAgfSxcbiAgICBkcmF3OiBmdW5jdGlvbiBkcmF3KGNvbnRleHQsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbiwgZWRnZVdpZHRoKSB7XG4gICAgICB2YXIgdHJpUHRzID0gdHJhbnNmb3JtUG9pbnRzKHRoaXMucG9pbnRzVHIsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbik7XG4gICAgICByZW5kZXJlci5hcnJvd1NoYXBlSW1wbCh0aGlzLm5hbWUpKGNvbnRleHQsIHRyaVB0cywgdHJhbnNsYXRpb24ueCwgdHJhbnNsYXRpb24ueSwgdGhpcy5yYWRpdXMgKiBzaXplKTtcbiAgICB9LFxuICAgIHNwYWNpbmc6IGZ1bmN0aW9uIHNwYWNpbmcoZWRnZSkge1xuICAgICAgcmV0dXJuIHJlbmRlcmVyLmdldEFycm93V2lkdGgoZWRnZS5wc3R5bGUoJ3dpZHRoJykucGZWYWx1ZSwgZWRnZS5wc3R5bGUoJ2Fycm93LXNjYWxlJykudmFsdWUpICogdGhpcy5yYWRpdXM7XG4gICAgfVxuICB9KTtcbiAgZGVmaW5lQXJyb3dTaGFwZSgndHJpYW5nbGUtY3Jvc3MnLCB7XG4gICAgcG9pbnRzOiBbMCwgMCwgMC4xNSwgLTAuMywgLTAuMTUsIC0wLjMsIDAsIDBdLFxuICAgIGJhc2VDcm9zc0xpbmVQdHM6IFstMC4xNSwgLTAuNCwgLy8gZmlyc3QgaGFsZiBvZiB0aGUgcmVjdGFuZ2xlXG4gICAgLTAuMTUsIC0wLjQsIDAuMTUsIC0wLjQsIC8vIHNlY29uZCBoYWxmIG9mIHRoZSByZWN0YW5nbGVcbiAgICAwLjE1LCAtMC40XSxcbiAgICBjcm9zc0xpbmVQdHM6IGZ1bmN0aW9uIGNyb3NzTGluZVB0cyhzaXplLCBlZGdlV2lkdGgpIHtcbiAgICAgIC8vIHNoaWZ0IHBvaW50cyBzbyB0aGF0IHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBjcm9zcyBwb2ludHMgbWF0Y2hlcyBlZGdlIHdpZHRoXG4gICAgICB2YXIgcCA9IHRoaXMuYmFzZUNyb3NzTGluZVB0cy5zbGljZSgpO1xuICAgICAgdmFyIHNoaWZ0RmFjdG9yID0gZWRnZVdpZHRoIC8gc2l6ZTtcbiAgICAgIHZhciB5MCA9IDM7XG4gICAgICB2YXIgeTEgPSA1O1xuICAgICAgcFt5MF0gPSBwW3kwXSAtIHNoaWZ0RmFjdG9yO1xuICAgICAgcFt5MV0gPSBwW3kxXSAtIHNoaWZ0RmFjdG9yO1xuICAgICAgcmV0dXJuIHA7XG4gICAgfSxcbiAgICBjb2xsaWRlOiBmdW5jdGlvbiBjb2xsaWRlKHgsIHksIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbiwgZWRnZVdpZHRoLCBwYWRkaW5nKSB7XG4gICAgICB2YXIgdHJpUHRzID0gcG9pbnRzVG9BcnIodHJhbnNmb3JtUG9pbnRzKHRoaXMucG9pbnRzLCBzaXplICsgMiAqIHBhZGRpbmcsIGFuZ2xlLCB0cmFuc2xhdGlvbikpO1xuICAgICAgdmFyIHRlZVB0cyA9IHBvaW50c1RvQXJyKHRyYW5zZm9ybVBvaW50cyh0aGlzLmNyb3NzTGluZVB0cyhzaXplLCBlZGdlV2lkdGgpLCBzaXplICsgMiAqIHBhZGRpbmcsIGFuZ2xlLCB0cmFuc2xhdGlvbikpO1xuICAgICAgdmFyIGluc2lkZSA9IHBvaW50SW5zaWRlUG9seWdvblBvaW50cyh4LCB5LCB0cmlQdHMpIHx8IHBvaW50SW5zaWRlUG9seWdvblBvaW50cyh4LCB5LCB0ZWVQdHMpO1xuICAgICAgcmV0dXJuIGluc2lkZTtcbiAgICB9LFxuICAgIGRyYXc6IGZ1bmN0aW9uIGRyYXcoY29udGV4dCwgc2l6ZSwgYW5nbGUsIHRyYW5zbGF0aW9uLCBlZGdlV2lkdGgpIHtcbiAgICAgIHZhciB0cmlQdHMgPSB0cmFuc2Zvcm1Qb2ludHModGhpcy5wb2ludHMsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbik7XG4gICAgICB2YXIgY3Jvc3NMaW5lUHRzID0gdHJhbnNmb3JtUG9pbnRzKHRoaXMuY3Jvc3NMaW5lUHRzKHNpemUsIGVkZ2VXaWR0aCksIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbik7XG4gICAgICByZW5kZXJlci5hcnJvd1NoYXBlSW1wbCh0aGlzLm5hbWUpKGNvbnRleHQsIHRyaVB0cywgY3Jvc3NMaW5lUHRzKTtcbiAgICB9XG4gIH0pO1xuICBkZWZpbmVBcnJvd1NoYXBlKCd2ZWUnLCB7XG4gICAgcG9pbnRzOiBbLTAuMTUsIC0wLjMsIDAsIDAsIDAuMTUsIC0wLjMsIDAsIC0wLjE1XSxcbiAgICBnYXA6IGZ1bmN0aW9uIGdhcChlZGdlKSB7XG4gICAgICByZXR1cm4gc3RhbmRhcmRHYXAoZWRnZSkgKiAwLjUyNTtcbiAgICB9XG4gIH0pO1xuICBkZWZpbmVBcnJvd1NoYXBlKCdjaXJjbGUnLCB7XG4gICAgcmFkaXVzOiAwLjE1LFxuICAgIGNvbGxpZGU6IGZ1bmN0aW9uIGNvbGxpZGUoeCwgeSwgc2l6ZSwgYW5nbGUsIHRyYW5zbGF0aW9uLCBlZGdlV2lkdGgsIHBhZGRpbmcpIHtcbiAgICAgIHZhciB0ID0gdHJhbnNsYXRpb247XG4gICAgICB2YXIgaW5zaWRlID0gTWF0aC5wb3codC54IC0geCwgMikgKyBNYXRoLnBvdyh0LnkgLSB5LCAyKSA8PSBNYXRoLnBvdygoc2l6ZSArIDIgKiBwYWRkaW5nKSAqIHRoaXMucmFkaXVzLCAyKTtcbiAgICAgIHJldHVybiBpbnNpZGU7XG4gICAgfSxcbiAgICBkcmF3OiBmdW5jdGlvbiBkcmF3KGNvbnRleHQsIHNpemUsIGFuZ2xlLCB0cmFuc2xhdGlvbiwgZWRnZVdpZHRoKSB7XG4gICAgICByZW5kZXJlci5hcnJvd1NoYXBlSW1wbCh0aGlzLm5hbWUpKGNvbnRleHQsIHRyYW5zbGF0aW9uLngsIHRyYW5zbGF0aW9uLnksIHRoaXMucmFkaXVzICogc2l6ZSk7XG4gICAgfSxcbiAgICBzcGFjaW5nOiBmdW5jdGlvbiBzcGFjaW5nKGVkZ2UpIHtcbiAgICAgIHJldHVybiByZW5kZXJlci5nZXRBcnJvd1dpZHRoKGVkZ2UucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWUsIGVkZ2UucHN0eWxlKCdhcnJvdy1zY2FsZScpLnZhbHVlKSAqIHRoaXMucmFkaXVzO1xuICAgIH1cbiAgfSk7XG4gIGRlZmluZUFycm93U2hhcGUoJ3RlZScsIHtcbiAgICBwb2ludHM6IFstMC4xNSwgMCwgLTAuMTUsIC0wLjEsIDAuMTUsIC0wLjEsIDAuMTUsIDBdLFxuICAgIHNwYWNpbmc6IGZ1bmN0aW9uIHNwYWNpbmcoZWRnZSkge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfSxcbiAgICBnYXA6IGZ1bmN0aW9uIGdhcChlZGdlKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH0pO1xuICBkZWZpbmVBcnJvd1NoYXBlKCdzcXVhcmUnLCB7XG4gICAgcG9pbnRzOiBbLTAuMTUsIDAuMDAsIDAuMTUsIDAuMDAsIDAuMTUsIC0wLjMsIC0wLjE1LCAtMC4zXVxuICB9KTtcbiAgZGVmaW5lQXJyb3dTaGFwZSgnZGlhbW9uZCcsIHtcbiAgICBwb2ludHM6IFstMC4xNSwgLTAuMTUsIDAsIC0wLjMsIDAuMTUsIC0wLjE1LCAwLCAwXSxcbiAgICBnYXA6IGZ1bmN0aW9uIGdhcChlZGdlKSB7XG4gICAgICByZXR1cm4gZWRnZS5wc3R5bGUoJ3dpZHRoJykucGZWYWx1ZSAqIGVkZ2UucHN0eWxlKCdhcnJvdy1zY2FsZScpLnZhbHVlO1xuICAgIH1cbiAgfSk7XG4gIGRlZmluZUFycm93U2hhcGUoJ2NoZXZyb24nLCB7XG4gICAgcG9pbnRzOiBbMCwgMCwgLTAuMTUsIC0wLjE1LCAtMC4xLCAtMC4yLCAwLCAtMC4xLCAwLjEsIC0wLjIsIDAuMTUsIC0wLjE1XSxcbiAgICBnYXA6IGZ1bmN0aW9uIGdhcChlZGdlKSB7XG4gICAgICByZXR1cm4gMC45NSAqIGVkZ2UucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWUgKiBlZGdlLnBzdHlsZSgnYXJyb3ctc2NhbGUnKS52YWx1ZTtcbiAgICB9XG4gIH0pO1xufTtcblxudmFyIEJScCQxID0ge307IC8vIFByb2plY3QgbW91c2VcblxuQlJwJDEucHJvamVjdEludG9WaWV3cG9ydCA9IGZ1bmN0aW9uIChjbGllbnRYLCBjbGllbnRZKSB7XG4gIHZhciBjeSA9IHRoaXMuY3k7XG4gIHZhciBvZmZzZXRzID0gdGhpcy5maW5kQ29udGFpbmVyQ2xpZW50Q29vcmRzKCk7XG4gIHZhciBvZmZzZXRMZWZ0ID0gb2Zmc2V0c1swXTtcbiAgdmFyIG9mZnNldFRvcCA9IG9mZnNldHNbMV07XG4gIHZhciBzY2FsZSA9IG9mZnNldHNbNF07XG4gIHZhciBwYW4gPSBjeS5wYW4oKTtcbiAgdmFyIHpvb20gPSBjeS56b29tKCk7XG4gIHZhciB4ID0gKChjbGllbnRYIC0gb2Zmc2V0TGVmdCkgLyBzY2FsZSAtIHBhbi54KSAvIHpvb207XG4gIHZhciB5ID0gKChjbGllbnRZIC0gb2Zmc2V0VG9wKSAvIHNjYWxlIC0gcGFuLnkpIC8gem9vbTtcbiAgcmV0dXJuIFt4LCB5XTtcbn07XG5cbkJScCQxLmZpbmRDb250YWluZXJDbGllbnRDb29yZHMgPSBmdW5jdGlvbiAoKSB7XG4gIGlmICh0aGlzLmNvbnRhaW5lckJCKSB7XG4gICAgcmV0dXJuIHRoaXMuY29udGFpbmVyQkI7XG4gIH1cblxuICB2YXIgY29udGFpbmVyID0gdGhpcy5jb250YWluZXI7XG4gIHZhciByZWN0ID0gY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICB2YXIgc3R5bGUgPSB3aW5kb3ckMS5nZXRDb21wdXRlZFN0eWxlKGNvbnRhaW5lcik7XG5cbiAgdmFyIHN0eWxlVmFsdWUgPSBmdW5jdGlvbiBzdHlsZVZhbHVlKG5hbWUpIHtcbiAgICByZXR1cm4gcGFyc2VGbG9hdChzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKG5hbWUpKTtcbiAgfTtcblxuICB2YXIgcGFkZGluZyA9IHtcbiAgICBsZWZ0OiBzdHlsZVZhbHVlKCdwYWRkaW5nLWxlZnQnKSxcbiAgICByaWdodDogc3R5bGVWYWx1ZSgncGFkZGluZy1yaWdodCcpLFxuICAgIHRvcDogc3R5bGVWYWx1ZSgncGFkZGluZy10b3AnKSxcbiAgICBib3R0b206IHN0eWxlVmFsdWUoJ3BhZGRpbmctYm90dG9tJylcbiAgfTtcbiAgdmFyIGJvcmRlciA9IHtcbiAgICBsZWZ0OiBzdHlsZVZhbHVlKCdib3JkZXItbGVmdC13aWR0aCcpLFxuICAgIHJpZ2h0OiBzdHlsZVZhbHVlKCdib3JkZXItcmlnaHQtd2lkdGgnKSxcbiAgICB0b3A6IHN0eWxlVmFsdWUoJ2JvcmRlci10b3Atd2lkdGgnKSxcbiAgICBib3R0b206IHN0eWxlVmFsdWUoJ2JvcmRlci1ib3R0b20td2lkdGgnKVxuICB9O1xuICB2YXIgY2xpZW50V2lkdGggPSBjb250YWluZXIuY2xpZW50V2lkdGg7XG4gIHZhciBjbGllbnRIZWlnaHQgPSBjb250YWluZXIuY2xpZW50SGVpZ2h0O1xuICB2YXIgcGFkZGluZ0hvciA9IHBhZGRpbmcubGVmdCArIHBhZGRpbmcucmlnaHQ7XG4gIHZhciBwYWRkaW5nVmVyID0gcGFkZGluZy50b3AgKyBwYWRkaW5nLmJvdHRvbTtcbiAgdmFyIGJvcmRlckhvciA9IGJvcmRlci5sZWZ0ICsgYm9yZGVyLnJpZ2h0O1xuICB2YXIgc2NhbGUgPSByZWN0LndpZHRoIC8gKGNsaWVudFdpZHRoICsgYm9yZGVySG9yKTtcbiAgdmFyIHVuc2NhbGVkVyA9IGNsaWVudFdpZHRoIC0gcGFkZGluZ0hvcjtcbiAgdmFyIHVuc2NhbGVkSCA9IGNsaWVudEhlaWdodCAtIHBhZGRpbmdWZXI7XG4gIHZhciBsZWZ0ID0gcmVjdC5sZWZ0ICsgcGFkZGluZy5sZWZ0ICsgYm9yZGVyLmxlZnQ7XG4gIHZhciB0b3AgPSByZWN0LnRvcCArIHBhZGRpbmcudG9wICsgYm9yZGVyLnRvcDtcbiAgcmV0dXJuIHRoaXMuY29udGFpbmVyQkIgPSBbbGVmdCwgdG9wLCB1bnNjYWxlZFcsIHVuc2NhbGVkSCwgc2NhbGVdO1xufTtcblxuQlJwJDEuaW52YWxpZGF0ZUNvbnRhaW5lckNsaWVudENvb3Jkc0NhY2hlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmNvbnRhaW5lckJCID0gbnVsbDtcbn07XG5cbkJScCQxLmZpbmROZWFyZXN0RWxlbWVudCA9IGZ1bmN0aW9uICh4LCB5LCBpbnRlcmFjdGl2ZUVsZW1lbnRzT25seSwgaXNUb3VjaCkge1xuICByZXR1cm4gdGhpcy5maW5kTmVhcmVzdEVsZW1lbnRzKHgsIHksIGludGVyYWN0aXZlRWxlbWVudHNPbmx5LCBpc1RvdWNoKVswXTtcbn07XG5cbkJScCQxLmZpbmROZWFyZXN0RWxlbWVudHMgPSBmdW5jdGlvbiAoeCwgeSwgaW50ZXJhY3RpdmVFbGVtZW50c09ubHksIGlzVG91Y2gpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBlbGVzID0gci5nZXRDYWNoZWRaU29ydGVkRWxlcygpO1xuICB2YXIgbmVhciA9IFtdOyAvLyAxIG5vZGUgbWF4LCAxIGVkZ2UgbWF4XG5cbiAgdmFyIHpvb20gPSByLmN5Lnpvb20oKTtcbiAgdmFyIGhhc0NvbXBvdW5kcyA9IHIuY3kuaGFzQ29tcG91bmROb2RlcygpO1xuICB2YXIgZWRnZVRocmVzaG9sZCA9IChpc1RvdWNoID8gMjQgOiA4KSAvIHpvb207XG4gIHZhciBub2RlVGhyZXNob2xkID0gKGlzVG91Y2ggPyA4IDogMikgLyB6b29tO1xuICB2YXIgbGFiZWxUaHJlc2hvbGQgPSAoaXNUb3VjaCA/IDggOiAyKSAvIHpvb207XG4gIHZhciBtaW5TcURpc3QgPSBJbmZpbml0eTtcbiAgdmFyIG5lYXJFZGdlO1xuICB2YXIgbmVhck5vZGU7XG5cbiAgaWYgKGludGVyYWN0aXZlRWxlbWVudHNPbmx5KSB7XG4gICAgZWxlcyA9IGVsZXMuaW50ZXJhY3RpdmU7XG4gIH1cblxuICBmdW5jdGlvbiBhZGRFbGUoZWxlLCBzcURpc3QpIHtcbiAgICBpZiAoZWxlLmlzTm9kZSgpKSB7XG4gICAgICBpZiAobmVhck5vZGUpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBjYW4ndCByZXBsYWNlIG5vZGVcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5lYXJOb2RlID0gZWxlO1xuICAgICAgICBuZWFyLnB1c2goZWxlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxlLmlzRWRnZSgpICYmIChzcURpc3QgPT0gbnVsbCB8fCBzcURpc3QgPCBtaW5TcURpc3QpKSB7XG4gICAgICBpZiAobmVhckVkZ2UpIHtcbiAgICAgICAgLy8gdGhlbiByZXBsYWNlIGV4aXN0aW5nIGVkZ2VcbiAgICAgICAgLy8gY2FuIHJlcGxhY2Ugb25seSBpZiBzYW1lIHotaW5kZXhcbiAgICAgICAgaWYgKG5lYXJFZGdlLnBzdHlsZSgnei1jb21wb3VuZC1kZXB0aCcpLnZhbHVlID09PSBlbGUucHN0eWxlKCd6LWNvbXBvdW5kLWRlcHRoJykudmFsdWUgJiYgbmVhckVkZ2UucHN0eWxlKCd6LWNvbXBvdW5kLWRlcHRoJykudmFsdWUgPT09IGVsZS5wc3R5bGUoJ3otY29tcG91bmQtZGVwdGgnKS52YWx1ZSkge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmVhci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKG5lYXJbaV0uaXNFZGdlKCkpIHtcbiAgICAgICAgICAgICAgbmVhcltpXSA9IGVsZTtcbiAgICAgICAgICAgICAgbmVhckVkZ2UgPSBlbGU7XG4gICAgICAgICAgICAgIG1pblNxRGlzdCA9IHNxRGlzdCAhPSBudWxsID8gc3FEaXN0IDogbWluU3FEaXN0O1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5lYXIucHVzaChlbGUpO1xuICAgICAgICBuZWFyRWRnZSA9IGVsZTtcbiAgICAgICAgbWluU3FEaXN0ID0gc3FEaXN0ICE9IG51bGwgPyBzcURpc3QgOiBtaW5TcURpc3Q7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tOb2RlKG5vZGUpIHtcbiAgICB2YXIgd2lkdGggPSBub2RlLm91dGVyV2lkdGgoKSArIDIgKiBub2RlVGhyZXNob2xkO1xuICAgIHZhciBoZWlnaHQgPSBub2RlLm91dGVySGVpZ2h0KCkgKyAyICogbm9kZVRocmVzaG9sZDtcbiAgICB2YXIgaHcgPSB3aWR0aCAvIDI7XG4gICAgdmFyIGhoID0gaGVpZ2h0IC8gMjtcbiAgICB2YXIgcG9zID0gbm9kZS5wb3NpdGlvbigpO1xuXG4gICAgaWYgKHBvcy54IC0gaHcgPD0geCAmJiB4IDw9IHBvcy54ICsgaHcgLy8gYmIgY2hlY2sgeFxuICAgICYmIHBvcy55IC0gaGggPD0geSAmJiB5IDw9IHBvcy55ICsgaGggLy8gYmIgY2hlY2sgeVxuICAgICkge1xuICAgICAgICB2YXIgc2hhcGUgPSByLm5vZGVTaGFwZXNbc2VsZi5nZXROb2RlU2hhcGUobm9kZSldO1xuXG4gICAgICAgIGlmIChzaGFwZS5jaGVja1BvaW50KHgsIHksIDAsIHdpZHRoLCBoZWlnaHQsIHBvcy54LCBwb3MueSkpIHtcbiAgICAgICAgICBhZGRFbGUobm9kZSwgMCk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrRWRnZShlZGdlKSB7XG4gICAgdmFyIF9wID0gZWRnZS5fcHJpdmF0ZTtcbiAgICB2YXIgcnMgPSBfcC5yc2NyYXRjaDtcbiAgICB2YXIgc3R5bGVXaWR0aCA9IGVkZ2UucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWU7XG4gICAgdmFyIHNjYWxlID0gZWRnZS5wc3R5bGUoJ2Fycm93LXNjYWxlJykudmFsdWU7XG4gICAgdmFyIHdpZHRoID0gc3R5bGVXaWR0aCAvIDIgKyBlZGdlVGhyZXNob2xkOyAvLyBtb3JlIGxpa2UgYSBkaXN0YW5jZSByYWRpdXMgZnJvbSBjZW50cmVcblxuICAgIHZhciB3aWR0aFNxID0gd2lkdGggKiB3aWR0aDtcbiAgICB2YXIgd2lkdGgyID0gd2lkdGggKiAyO1xuICAgIHZhciBzcmMgPSBfcC5zb3VyY2U7XG4gICAgdmFyIHRndCA9IF9wLnRhcmdldDtcbiAgICB2YXIgc3FEaXN0O1xuXG4gICAgaWYgKHJzLmVkZ2VUeXBlID09PSAnc2VnbWVudHMnIHx8IHJzLmVkZ2VUeXBlID09PSAnc3RyYWlnaHQnIHx8IHJzLmVkZ2VUeXBlID09PSAnaGF5c3RhY2snKSB7XG4gICAgICB2YXIgcHRzID0gcnMuYWxscHRzO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSArIDMgPCBwdHMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgICAgaWYgKGluTGluZVZpY2luaXR5KHgsIHksIHB0c1tpXSwgcHRzW2kgKyAxXSwgcHRzW2kgKyAyXSwgcHRzW2kgKyAzXSwgd2lkdGgyKSAmJiB3aWR0aFNxID4gKHNxRGlzdCA9IHNxZGlzdFRvRmluaXRlTGluZSh4LCB5LCBwdHNbaV0sIHB0c1tpICsgMV0sIHB0c1tpICsgMl0sIHB0c1tpICsgM10pKSkge1xuICAgICAgICAgIGFkZEVsZShlZGdlLCBzcURpc3QpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChycy5lZGdlVHlwZSA9PT0gJ2JlemllcicgfHwgcnMuZWRnZVR5cGUgPT09ICdtdWx0aWJlemllcicgfHwgcnMuZWRnZVR5cGUgPT09ICdzZWxmJyB8fCBycy5lZGdlVHlwZSA9PT0gJ2NvbXBvdW5kJykge1xuICAgICAgdmFyIHB0cyA9IHJzLmFsbHB0cztcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgKyA1IDwgcnMuYWxscHRzLmxlbmd0aDsgaSArPSA0KSB7XG4gICAgICAgIGlmIChpbkJlemllclZpY2luaXR5KHgsIHksIHB0c1tpXSwgcHRzW2kgKyAxXSwgcHRzW2kgKyAyXSwgcHRzW2kgKyAzXSwgcHRzW2kgKyA0XSwgcHRzW2kgKyA1XSwgd2lkdGgyKSAmJiB3aWR0aFNxID4gKHNxRGlzdCA9IHNxZGlzdFRvUXVhZHJhdGljQmV6aWVyKHgsIHksIHB0c1tpXSwgcHRzW2kgKyAxXSwgcHRzW2kgKyAyXSwgcHRzW2kgKyAzXSwgcHRzW2kgKyA0XSwgcHRzW2kgKyA1XSkpKSB7XG4gICAgICAgICAgYWRkRWxlKGVkZ2UsIHNxRGlzdCk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IC8vIGlmIHdlJ3JlIGNsb3NlIHRvIHRoZSBlZGdlIGJ1dCBkaWRuJ3QgaGl0IGl0LCBtYXliZSB3ZSBoaXQgaXRzIGFycm93c1xuXG5cbiAgICB2YXIgc3JjID0gc3JjIHx8IF9wLnNvdXJjZTtcbiAgICB2YXIgdGd0ID0gdGd0IHx8IF9wLnRhcmdldDtcbiAgICB2YXIgYXJTaXplID0gc2VsZi5nZXRBcnJvd1dpZHRoKHN0eWxlV2lkdGgsIHNjYWxlKTtcbiAgICB2YXIgYXJyb3dzID0gW3tcbiAgICAgIG5hbWU6ICdzb3VyY2UnLFxuICAgICAgeDogcnMuYXJyb3dTdGFydFgsXG4gICAgICB5OiBycy5hcnJvd1N0YXJ0WSxcbiAgICAgIGFuZ2xlOiBycy5zcmNBcnJvd0FuZ2xlXG4gICAgfSwge1xuICAgICAgbmFtZTogJ3RhcmdldCcsXG4gICAgICB4OiBycy5hcnJvd0VuZFgsXG4gICAgICB5OiBycy5hcnJvd0VuZFksXG4gICAgICBhbmdsZTogcnMudGd0QXJyb3dBbmdsZVxuICAgIH0sIHtcbiAgICAgIG5hbWU6ICdtaWQtc291cmNlJyxcbiAgICAgIHg6IHJzLm1pZFgsXG4gICAgICB5OiBycy5taWRZLFxuICAgICAgYW5nbGU6IHJzLm1pZHNyY0Fycm93QW5nbGVcbiAgICB9LCB7XG4gICAgICBuYW1lOiAnbWlkLXRhcmdldCcsXG4gICAgICB4OiBycy5taWRYLFxuICAgICAgeTogcnMubWlkWSxcbiAgICAgIGFuZ2xlOiBycy5taWR0Z3RBcnJvd0FuZ2xlXG4gICAgfV07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycm93cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGFyID0gYXJyb3dzW2ldO1xuICAgICAgdmFyIHNoYXBlID0gci5hcnJvd1NoYXBlc1tlZGdlLnBzdHlsZShhci5uYW1lICsgJy1hcnJvdy1zaGFwZScpLnZhbHVlXTtcbiAgICAgIHZhciBlZGdlV2lkdGggPSBlZGdlLnBzdHlsZSgnd2lkdGgnKS5wZlZhbHVlO1xuXG4gICAgICBpZiAoc2hhcGUucm91Z2hDb2xsaWRlKHgsIHksIGFyU2l6ZSwgYXIuYW5nbGUsIHtcbiAgICAgICAgeDogYXIueCxcbiAgICAgICAgeTogYXIueVxuICAgICAgfSwgZWRnZVdpZHRoLCBlZGdlVGhyZXNob2xkKSAmJiBzaGFwZS5jb2xsaWRlKHgsIHksIGFyU2l6ZSwgYXIuYW5nbGUsIHtcbiAgICAgICAgeDogYXIueCxcbiAgICAgICAgeTogYXIueVxuICAgICAgfSwgZWRnZVdpZHRoLCBlZGdlVGhyZXNob2xkKSkge1xuICAgICAgICBhZGRFbGUoZWRnZSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH0gLy8gZm9yIGNvbXBvdW5kIGdyYXBocywgaGl0dGluZyBlZGdlIG1heSBhY3R1YWxseSB3YW50IGEgY29ubmVjdGVkIG5vZGUgaW5zdGVhZCAoYi9jIGVkZ2UgbWF5IGhhdmUgZ3JlYXRlciB6LWluZGV4IHByZWNlZGVuY2UpXG5cblxuICAgIGlmIChoYXNDb21wb3VuZHMgJiYgbmVhci5sZW5ndGggPiAwKSB7XG4gICAgICBjaGVja05vZGUoc3JjKTtcbiAgICAgIGNoZWNrTm9kZSh0Z3QpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHByZXByb3Aob2JqLCBuYW1lLCBwcmUpIHtcbiAgICByZXR1cm4gZ2V0UHJlZml4ZWRQcm9wZXJ0eShvYmosIG5hbWUsIHByZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVja0xhYmVsKGVsZSwgcHJlZml4KSB7XG4gICAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICAgIHZhciB0aCA9IGxhYmVsVGhyZXNob2xkO1xuICAgIHZhciBwcmVmaXhEYXNoO1xuXG4gICAgaWYgKHByZWZpeCkge1xuICAgICAgcHJlZml4RGFzaCA9IHByZWZpeCArICctJztcbiAgICB9IGVsc2Uge1xuICAgICAgcHJlZml4RGFzaCA9ICcnO1xuICAgIH1cblxuICAgIGVsZS5ib3VuZGluZ0JveCgpO1xuICAgIHZhciBiYiA9IF9wLmxhYmVsQm91bmRzW3ByZWZpeCB8fCAnbWFpbiddO1xuICAgIHZhciB0ZXh0ID0gZWxlLnBzdHlsZShwcmVmaXhEYXNoICsgJ2xhYmVsJykudmFsdWU7XG4gICAgdmFyIGV2ZW50c0VuYWJsZWQgPSBlbGUucHN0eWxlKCd0ZXh0LWV2ZW50cycpLnN0clZhbHVlID09PSAneWVzJztcblxuICAgIGlmICghZXZlbnRzRW5hYmxlZCB8fCAhdGV4dCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciByc3R5bGUgPSBfcC5yc3R5bGU7XG4gICAgdmFyIGx4ID0gcHJlcHJvcChyc3R5bGUsICdsYWJlbFgnLCBwcmVmaXgpO1xuICAgIHZhciBseSA9IHByZXByb3AocnN0eWxlLCAnbGFiZWxZJywgcHJlZml4KTtcbiAgICB2YXIgdGhldGEgPSBwcmVwcm9wKF9wLnJzY3JhdGNoLCAnbGFiZWxBbmdsZScsIHByZWZpeCk7XG4gICAgdmFyIGx4MSA9IGJiLngxIC0gdGg7XG4gICAgdmFyIGx4MiA9IGJiLngyICsgdGg7XG4gICAgdmFyIGx5MSA9IGJiLnkxIC0gdGg7XG4gICAgdmFyIGx5MiA9IGJiLnkyICsgdGg7XG5cbiAgICBpZiAodGhldGEpIHtcbiAgICAgIHZhciBjb3MgPSBNYXRoLmNvcyh0aGV0YSk7XG4gICAgICB2YXIgc2luID0gTWF0aC5zaW4odGhldGEpO1xuXG4gICAgICB2YXIgcm90YXRlID0gZnVuY3Rpb24gcm90YXRlKHgsIHkpIHtcbiAgICAgICAgeCA9IHggLSBseDtcbiAgICAgICAgeSA9IHkgLSBseTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB4OiB4ICogY29zIC0geSAqIHNpbiArIGx4LFxuICAgICAgICAgIHk6IHggKiBzaW4gKyB5ICogY29zICsgbHlcbiAgICAgICAgfTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBweDF5MSA9IHJvdGF0ZShseDEsIGx5MSk7XG4gICAgICB2YXIgcHgxeTIgPSByb3RhdGUobHgxLCBseTIpO1xuICAgICAgdmFyIHB4MnkxID0gcm90YXRlKGx4MiwgbHkxKTtcbiAgICAgIHZhciBweDJ5MiA9IHJvdGF0ZShseDIsIGx5Mik7XG4gICAgICB2YXIgcG9pbnRzID0gW3B4MXkxLngsIHB4MXkxLnksIHB4MnkxLngsIHB4MnkxLnksIHB4MnkyLngsIHB4MnkyLnksIHB4MXkyLngsIHB4MXkyLnldO1xuXG4gICAgICBpZiAocG9pbnRJbnNpZGVQb2x5Z29uUG9pbnRzKHgsIHksIHBvaW50cykpIHtcbiAgICAgICAgYWRkRWxlKGVsZSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBkbyBhIGNoZWFwZXIgYmIgY2hlY2tcbiAgICAgIGlmIChpbkJvdW5kaW5nQm94KGJiLCB4LCB5KSkge1xuICAgICAgICBhZGRFbGUoZWxlKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgaSA9IGVsZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAvLyByZXZlcnNlIG9yZGVyIGZvciBwcmVjZWRlbmNlXG4gICAgdmFyIGVsZSA9IGVsZXNbaV07XG5cbiAgICBpZiAoZWxlLmlzTm9kZSgpKSB7XG4gICAgICBjaGVja05vZGUoZWxlKSB8fCBjaGVja0xhYmVsKGVsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHRoZW4gZWRnZVxuICAgICAgY2hlY2tFZGdlKGVsZSkgfHwgY2hlY2tMYWJlbChlbGUpIHx8IGNoZWNrTGFiZWwoZWxlLCAnc291cmNlJykgfHwgY2hlY2tMYWJlbChlbGUsICd0YXJnZXQnKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmVhcjtcbn07IC8vICdHaXZlIG1lIGV2ZXJ5dGhpbmcgZnJvbSB0aGlzIGJveCdcblxuXG5CUnAkMS5nZXRBbGxJbkJveCA9IGZ1bmN0aW9uICh4MSwgeTEsIHgyLCB5Mikge1xuICB2YXIgZWxlcyA9IHRoaXMuZ2V0Q2FjaGVkWlNvcnRlZEVsZXMoKS5pbnRlcmFjdGl2ZTtcbiAgdmFyIGJveCA9IFtdO1xuICB2YXIgeDFjID0gTWF0aC5taW4oeDEsIHgyKTtcbiAgdmFyIHgyYyA9IE1hdGgubWF4KHgxLCB4Mik7XG4gIHZhciB5MWMgPSBNYXRoLm1pbih5MSwgeTIpO1xuICB2YXIgeTJjID0gTWF0aC5tYXgoeTEsIHkyKTtcbiAgeDEgPSB4MWM7XG4gIHgyID0geDJjO1xuICB5MSA9IHkxYztcbiAgeTIgPSB5MmM7XG4gIHZhciBib3hCYiA9IG1ha2VCb3VuZGluZ0JveCh7XG4gICAgeDE6IHgxLFxuICAgIHkxOiB5MSxcbiAgICB4MjogeDIsXG4gICAgeTI6IHkyXG4gIH0pO1xuXG4gIGZvciAodmFyIGUgPSAwOyBlIDwgZWxlcy5sZW5ndGg7IGUrKykge1xuICAgIHZhciBlbGUgPSBlbGVzW2VdO1xuXG4gICAgaWYgKGVsZS5pc05vZGUoKSkge1xuICAgICAgdmFyIG5vZGUgPSBlbGU7XG4gICAgICB2YXIgbm9kZUJiID0gbm9kZS5ib3VuZGluZ0JveCh7XG4gICAgICAgIGluY2x1ZGVOb2RlczogdHJ1ZSxcbiAgICAgICAgaW5jbHVkZUVkZ2VzOiBmYWxzZSxcbiAgICAgICAgaW5jbHVkZUxhYmVsczogZmFsc2VcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoYm91bmRpbmdCb3hlc0ludGVyc2VjdChib3hCYiwgbm9kZUJiKSAmJiAhYm91bmRpbmdCb3hJbkJvdW5kaW5nQm94KG5vZGVCYiwgYm94QmIpKSB7XG4gICAgICAgIGJveC5wdXNoKG5vZGUpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgZWRnZSA9IGVsZTtcbiAgICAgIHZhciBfcCA9IGVkZ2UuX3ByaXZhdGU7XG4gICAgICB2YXIgcnMgPSBfcC5yc2NyYXRjaDtcblxuICAgICAgaWYgKHJzLnN0YXJ0WCAhPSBudWxsICYmIHJzLnN0YXJ0WSAhPSBudWxsICYmICFpbkJvdW5kaW5nQm94KGJveEJiLCBycy5zdGFydFgsIHJzLnN0YXJ0WSkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChycy5lbmRYICE9IG51bGwgJiYgcnMuZW5kWSAhPSBudWxsICYmICFpbkJvdW5kaW5nQm94KGJveEJiLCBycy5lbmRYLCBycy5lbmRZKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJzLmVkZ2VUeXBlID09PSAnYmV6aWVyJyB8fCBycy5lZGdlVHlwZSA9PT0gJ211bHRpYmV6aWVyJyB8fCBycy5lZGdlVHlwZSA9PT0gJ3NlbGYnIHx8IHJzLmVkZ2VUeXBlID09PSAnY29tcG91bmQnIHx8IHJzLmVkZ2VUeXBlID09PSAnc2VnbWVudHMnIHx8IHJzLmVkZ2VUeXBlID09PSAnaGF5c3RhY2snKSB7XG4gICAgICAgIHZhciBwdHMgPSBfcC5yc3R5bGUuYmV6aWVyUHRzIHx8IF9wLnJzdHlsZS5saW5lUHRzIHx8IF9wLnJzdHlsZS5oYXlzdGFja1B0cztcbiAgICAgICAgdmFyIGFsbEluc2lkZSA9IHRydWU7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAoIXBvaW50SW5Cb3VuZGluZ0JveChib3hCYiwgcHRzW2ldKSkge1xuICAgICAgICAgICAgYWxsSW5zaWRlID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWxsSW5zaWRlKSB7XG4gICAgICAgICAgYm94LnB1c2goZWRnZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAocnMuZWRnZVR5cGUgPT09ICdoYXlzdGFjaycgfHwgcnMuZWRnZVR5cGUgPT09ICdzdHJhaWdodCcpIHtcbiAgICAgICAgYm94LnB1c2goZWRnZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJveDtcbn07XG5cbnZhciBCUnAkMiA9IHt9O1xuXG5CUnAkMi5jYWxjdWxhdGVBcnJvd0FuZ2xlcyA9IGZ1bmN0aW9uIChlZGdlKSB7XG4gIHZhciBycyA9IGVkZ2UuX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHZhciBpc0hheXN0YWNrID0gcnMuZWRnZVR5cGUgPT09ICdoYXlzdGFjayc7XG4gIHZhciBpc0JlemllciA9IHJzLmVkZ2VUeXBlID09PSAnYmV6aWVyJztcbiAgdmFyIGlzTXVsdGliZXppZXIgPSBycy5lZGdlVHlwZSA9PT0gJ211bHRpYmV6aWVyJztcbiAgdmFyIGlzU2VnbWVudHMgPSBycy5lZGdlVHlwZSA9PT0gJ3NlZ21lbnRzJztcbiAgdmFyIGlzQ29tcG91bmQgPSBycy5lZGdlVHlwZSA9PT0gJ2NvbXBvdW5kJztcbiAgdmFyIGlzU2VsZiA9IHJzLmVkZ2VUeXBlID09PSAnc2VsZic7IC8vIERpc3BsYWNlbWVudCBnaXZlcyBkaXJlY3Rpb24gZm9yIGFycm93aGVhZCBvcmllbnRhdGlvblxuXG4gIHZhciBkaXNwWCwgZGlzcFk7XG4gIHZhciBzdGFydFgsIHN0YXJ0WSwgZW5kWCwgZW5kWSwgbWlkWCwgbWlkWTtcblxuICBpZiAoaXNIYXlzdGFjaykge1xuICAgIHN0YXJ0WCA9IHJzLmhheXN0YWNrUHRzWzBdO1xuICAgIHN0YXJ0WSA9IHJzLmhheXN0YWNrUHRzWzFdO1xuICAgIGVuZFggPSBycy5oYXlzdGFja1B0c1syXTtcbiAgICBlbmRZID0gcnMuaGF5c3RhY2tQdHNbM107XG4gIH0gZWxzZSB7XG4gICAgc3RhcnRYID0gcnMuYXJyb3dTdGFydFg7XG4gICAgc3RhcnRZID0gcnMuYXJyb3dTdGFydFk7XG4gICAgZW5kWCA9IHJzLmFycm93RW5kWDtcbiAgICBlbmRZID0gcnMuYXJyb3dFbmRZO1xuICB9XG5cbiAgbWlkWCA9IHJzLm1pZFg7XG4gIG1pZFkgPSBycy5taWRZOyAvLyBzb3VyY2VcbiAgLy9cblxuICBpZiAoaXNTZWdtZW50cykge1xuICAgIGRpc3BYID0gc3RhcnRYIC0gcnMuc2VncHRzWzBdO1xuICAgIGRpc3BZID0gc3RhcnRZIC0gcnMuc2VncHRzWzFdO1xuICB9IGVsc2UgaWYgKGlzTXVsdGliZXppZXIgfHwgaXNDb21wb3VuZCB8fCBpc1NlbGYgfHwgaXNCZXppZXIpIHtcbiAgICB2YXIgcHRzID0gcnMuYWxscHRzO1xuICAgIHZhciBiWCA9IHFiZXppZXJBdChwdHNbMF0sIHB0c1syXSwgcHRzWzRdLCAwLjEpO1xuICAgIHZhciBiWSA9IHFiZXppZXJBdChwdHNbMV0sIHB0c1szXSwgcHRzWzVdLCAwLjEpO1xuICAgIGRpc3BYID0gc3RhcnRYIC0gYlg7XG4gICAgZGlzcFkgPSBzdGFydFkgLSBiWTtcbiAgfSBlbHNlIHtcbiAgICBkaXNwWCA9IHN0YXJ0WCAtIG1pZFg7XG4gICAgZGlzcFkgPSBzdGFydFkgLSBtaWRZO1xuICB9XG5cbiAgcnMuc3JjQXJyb3dBbmdsZSA9IGdldEFuZ2xlRnJvbURpc3AoZGlzcFgsIGRpc3BZKTsgLy8gbWlkIHRhcmdldFxuICAvL1xuXG4gIHZhciBtaWRYID0gcnMubWlkWDtcbiAgdmFyIG1pZFkgPSBycy5taWRZO1xuXG4gIGlmIChpc0hheXN0YWNrKSB7XG4gICAgbWlkWCA9IChzdGFydFggKyBlbmRYKSAvIDI7XG4gICAgbWlkWSA9IChzdGFydFkgKyBlbmRZKSAvIDI7XG4gIH1cblxuICBkaXNwWCA9IGVuZFggLSBzdGFydFg7XG4gIGRpc3BZID0gZW5kWSAtIHN0YXJ0WTtcblxuICBpZiAoaXNTZWdtZW50cykge1xuICAgIHZhciBwdHMgPSBycy5hbGxwdHM7XG5cbiAgICBpZiAocHRzLmxlbmd0aCAvIDIgJSAyID09PSAwKSB7XG4gICAgICB2YXIgaTIgPSBwdHMubGVuZ3RoIC8gMjtcbiAgICAgIHZhciBpMSA9IGkyIC0gMjtcbiAgICAgIGRpc3BYID0gcHRzW2kyXSAtIHB0c1tpMV07XG4gICAgICBkaXNwWSA9IHB0c1tpMiArIDFdIC0gcHRzW2kxICsgMV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBpMiA9IHB0cy5sZW5ndGggLyAyIC0gMTtcbiAgICAgIHZhciBpMSA9IGkyIC0gMjtcbiAgICAgIHZhciBpMyA9IGkyICsgMjtcbiAgICAgIGRpc3BYID0gcHRzW2kyXSAtIHB0c1tpMV07XG4gICAgICBkaXNwWSA9IHB0c1tpMiArIDFdIC0gcHRzW2kxICsgMV07XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzTXVsdGliZXppZXIgfHwgaXNDb21wb3VuZCB8fCBpc1NlbGYpIHtcbiAgICB2YXIgcHRzID0gcnMuYWxscHRzO1xuICAgIHZhciBjcHRzID0gcnMuY3RybHB0cztcbiAgICB2YXIgYnAweCwgYnAweTtcbiAgICB2YXIgYnAxeCwgYnAxeTtcblxuICAgIGlmIChjcHRzLmxlbmd0aCAvIDIgJSAyID09PSAwKSB7XG4gICAgICB2YXIgcDAgPSBwdHMubGVuZ3RoIC8gMiAtIDE7IC8vIHN0YXJ0cHRcblxuICAgICAgdmFyIGljID0gcDAgKyAyO1xuICAgICAgdmFyIHAxID0gaWMgKyAyO1xuICAgICAgYnAweCA9IHFiZXppZXJBdChwdHNbcDBdLCBwdHNbaWNdLCBwdHNbcDFdLCAwLjApO1xuICAgICAgYnAweSA9IHFiZXppZXJBdChwdHNbcDAgKyAxXSwgcHRzW2ljICsgMV0sIHB0c1twMSArIDFdLCAwLjApO1xuICAgICAgYnAxeCA9IHFiZXppZXJBdChwdHNbcDBdLCBwdHNbaWNdLCBwdHNbcDFdLCAwLjAwMDEpO1xuICAgICAgYnAxeSA9IHFiZXppZXJBdChwdHNbcDAgKyAxXSwgcHRzW2ljICsgMV0sIHB0c1twMSArIDFdLCAwLjAwMDEpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgaWMgPSBwdHMubGVuZ3RoIC8gMiAtIDE7IC8vIGN0cnB0XG5cbiAgICAgIHZhciBwMCA9IGljIC0gMjsgLy8gc3RhcnRwdFxuXG4gICAgICB2YXIgcDEgPSBpYyArIDI7IC8vIGVuZHB0XG5cbiAgICAgIGJwMHggPSBxYmV6aWVyQXQocHRzW3AwXSwgcHRzW2ljXSwgcHRzW3AxXSwgMC40OTk5KTtcbiAgICAgIGJwMHkgPSBxYmV6aWVyQXQocHRzW3AwICsgMV0sIHB0c1tpYyArIDFdLCBwdHNbcDEgKyAxXSwgMC40OTk5KTtcbiAgICAgIGJwMXggPSBxYmV6aWVyQXQocHRzW3AwXSwgcHRzW2ljXSwgcHRzW3AxXSwgMC41KTtcbiAgICAgIGJwMXkgPSBxYmV6aWVyQXQocHRzW3AwICsgMV0sIHB0c1tpYyArIDFdLCBwdHNbcDEgKyAxXSwgMC41KTtcbiAgICB9XG5cbiAgICBkaXNwWCA9IGJwMXggLSBicDB4O1xuICAgIGRpc3BZID0gYnAxeSAtIGJwMHk7XG4gIH1cblxuICBycy5taWR0Z3RBcnJvd0FuZ2xlID0gZ2V0QW5nbGVGcm9tRGlzcChkaXNwWCwgZGlzcFkpO1xuICBycy5taWREaXNwWCA9IGRpc3BYO1xuICBycy5taWREaXNwWSA9IGRpc3BZOyAvLyBtaWQgc291cmNlXG4gIC8vXG5cbiAgZGlzcFggKj0gLTE7XG4gIGRpc3BZICo9IC0xO1xuXG4gIGlmIChpc1NlZ21lbnRzKSB7XG4gICAgdmFyIHB0cyA9IHJzLmFsbHB0cztcblxuICAgIGlmIChwdHMubGVuZ3RoIC8gMiAlIDIgPT09IDApIDsgZWxzZSB7XG4gICAgICB2YXIgaTIgPSBwdHMubGVuZ3RoIC8gMiAtIDE7XG4gICAgICB2YXIgaTMgPSBpMiArIDI7XG4gICAgICBkaXNwWCA9IC0ocHRzW2kzXSAtIHB0c1tpMl0pO1xuICAgICAgZGlzcFkgPSAtKHB0c1tpMyArIDFdIC0gcHRzW2kyICsgMV0pO1xuICAgIH1cbiAgfVxuXG4gIHJzLm1pZHNyY0Fycm93QW5nbGUgPSBnZXRBbmdsZUZyb21EaXNwKGRpc3BYLCBkaXNwWSk7IC8vIHRhcmdldFxuICAvL1xuXG4gIGlmIChpc1NlZ21lbnRzKSB7XG4gICAgZGlzcFggPSBlbmRYIC0gcnMuc2VncHRzW3JzLnNlZ3B0cy5sZW5ndGggLSAyXTtcbiAgICBkaXNwWSA9IGVuZFkgLSBycy5zZWdwdHNbcnMuc2VncHRzLmxlbmd0aCAtIDFdO1xuICB9IGVsc2UgaWYgKGlzTXVsdGliZXppZXIgfHwgaXNDb21wb3VuZCB8fCBpc1NlbGYgfHwgaXNCZXppZXIpIHtcbiAgICB2YXIgcHRzID0gcnMuYWxscHRzO1xuICAgIHZhciBsID0gcHRzLmxlbmd0aDtcbiAgICB2YXIgYlggPSBxYmV6aWVyQXQocHRzW2wgLSA2XSwgcHRzW2wgLSA0XSwgcHRzW2wgLSAyXSwgMC45KTtcbiAgICB2YXIgYlkgPSBxYmV6aWVyQXQocHRzW2wgLSA1XSwgcHRzW2wgLSAzXSwgcHRzW2wgLSAxXSwgMC45KTtcbiAgICBkaXNwWCA9IGVuZFggLSBiWDtcbiAgICBkaXNwWSA9IGVuZFkgLSBiWTtcbiAgfSBlbHNlIHtcbiAgICBkaXNwWCA9IGVuZFggLSBtaWRYO1xuICAgIGRpc3BZID0gZW5kWSAtIG1pZFk7XG4gIH1cblxuICBycy50Z3RBcnJvd0FuZ2xlID0gZ2V0QW5nbGVGcm9tRGlzcChkaXNwWCwgZGlzcFkpO1xufTtcblxuQlJwJDIuZ2V0QXJyb3dXaWR0aCA9IEJScCQyLmdldEFycm93SGVpZ2h0ID0gZnVuY3Rpb24gKGVkZ2VXaWR0aCwgc2NhbGUpIHtcbiAgdmFyIGNhY2hlID0gdGhpcy5hcnJvd1dpZHRoQ2FjaGUgPSB0aGlzLmFycm93V2lkdGhDYWNoZSB8fCB7fTtcbiAgdmFyIGNhY2hlZFZhbCA9IGNhY2hlW2VkZ2VXaWR0aCArICcsICcgKyBzY2FsZV07XG5cbiAgaWYgKGNhY2hlZFZhbCkge1xuICAgIHJldHVybiBjYWNoZWRWYWw7XG4gIH1cblxuICBjYWNoZWRWYWwgPSBNYXRoLm1heChNYXRoLnBvdyhlZGdlV2lkdGggKiAxMy4zNywgMC45KSwgMjkpICogc2NhbGU7XG4gIGNhY2hlW2VkZ2VXaWR0aCArICcsICcgKyBzY2FsZV0gPSBjYWNoZWRWYWw7XG4gIHJldHVybiBjYWNoZWRWYWw7XG59O1xuXG52YXIgQlJwJDMgPSB7fTtcblxuQlJwJDMuZmluZEhheXN0YWNrUG9pbnRzID0gZnVuY3Rpb24gKGVkZ2VzKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZWRnZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWRnZSA9IGVkZ2VzW2ldO1xuICAgIHZhciBfcCA9IGVkZ2UuX3ByaXZhdGU7XG4gICAgdmFyIHJzID0gX3AucnNjcmF0Y2g7XG5cbiAgICBpZiAoIXJzLmhheXN0YWNrKSB7XG4gICAgICB2YXIgYW5nbGUgPSBNYXRoLnJhbmRvbSgpICogMiAqIE1hdGguUEk7XG4gICAgICBycy5zb3VyY2UgPSB7XG4gICAgICAgIHg6IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgeTogTWF0aC5zaW4oYW5nbGUpXG4gICAgICB9O1xuICAgICAgYW5nbGUgPSBNYXRoLnJhbmRvbSgpICogMiAqIE1hdGguUEk7XG4gICAgICBycy50YXJnZXQgPSB7XG4gICAgICAgIHg6IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgeTogTWF0aC5zaW4oYW5nbGUpXG4gICAgICB9O1xuICAgIH1cblxuICAgIHZhciBzcmMgPSBfcC5zb3VyY2U7XG4gICAgdmFyIHRndCA9IF9wLnRhcmdldDtcbiAgICB2YXIgc3JjUG9zID0gc3JjLnBvc2l0aW9uKCk7XG4gICAgdmFyIHRndFBvcyA9IHRndC5wb3NpdGlvbigpO1xuICAgIHZhciBzcmNXID0gc3JjLndpZHRoKCk7XG4gICAgdmFyIHRndFcgPSB0Z3Qud2lkdGgoKTtcbiAgICB2YXIgc3JjSCA9IHNyYy5oZWlnaHQoKTtcbiAgICB2YXIgdGd0SCA9IHRndC5oZWlnaHQoKTtcbiAgICB2YXIgcmFkaXVzID0gZWRnZS5wc3R5bGUoJ2hheXN0YWNrLXJhZGl1cycpLnZhbHVlO1xuICAgIHZhciBoYWxmUmFkaXVzID0gcmFkaXVzIC8gMjsgLy8gYi9jIGhhdmUgdG8gaGFsZiB3aWR0aC9oZWlnaHRcblxuICAgIHJzLmhheXN0YWNrUHRzID0gcnMuYWxscHRzID0gW3JzLnNvdXJjZS54ICogc3JjVyAqIGhhbGZSYWRpdXMgKyBzcmNQb3MueCwgcnMuc291cmNlLnkgKiBzcmNIICogaGFsZlJhZGl1cyArIHNyY1Bvcy55LCBycy50YXJnZXQueCAqIHRndFcgKiBoYWxmUmFkaXVzICsgdGd0UG9zLngsIHJzLnRhcmdldC55ICogdGd0SCAqIGhhbGZSYWRpdXMgKyB0Z3RQb3MueV07XG4gICAgcnMubWlkWCA9IChycy5hbGxwdHNbMF0gKyBycy5hbGxwdHNbMl0pIC8gMjtcbiAgICBycy5taWRZID0gKHJzLmFsbHB0c1sxXSArIHJzLmFsbHB0c1szXSkgLyAyOyAvLyBhbHdheXMgb3ZlcnJpZGUgYXMgaGF5c3RhY2sgaW4gY2FzZSBzZXQgdG8gZGlmZmVyZW50IHR5cGUgcHJldmlvdXNseVxuXG4gICAgcnMuZWRnZVR5cGUgPSAnaGF5c3RhY2snO1xuICAgIHJzLmhheXN0YWNrID0gdHJ1ZTtcbiAgICB0aGlzLnN0b3JlRWRnZVByb2plY3Rpb25zKGVkZ2UpO1xuICAgIHRoaXMuY2FsY3VsYXRlQXJyb3dBbmdsZXMoZWRnZSk7XG4gICAgdGhpcy5yZWNhbGN1bGF0ZUVkZ2VMYWJlbFByb2plY3Rpb25zKGVkZ2UpO1xuICAgIHRoaXMuY2FsY3VsYXRlTGFiZWxBbmdsZXMoZWRnZSk7XG4gIH1cbn07XG5cbkJScCQzLmZpbmRTZWdtZW50c1BvaW50cyA9IGZ1bmN0aW9uIChlZGdlLCBwYWlySW5mbykge1xuICAvLyBTZWdtZW50cyAobXVsdGlwbGUgc3RyYWlnaHQgbGluZXMpXG4gIHZhciBycyA9IGVkZ2UuX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHZhciBwb3NQdHMgPSBwYWlySW5mby5wb3NQdHMsXG4gICAgICBpbnRlcnNlY3Rpb25QdHMgPSBwYWlySW5mby5pbnRlcnNlY3Rpb25QdHMsXG4gICAgICB2ZWN0b3JOb3JtSW52ZXJzZSA9IHBhaXJJbmZvLnZlY3Rvck5vcm1JbnZlcnNlO1xuICB2YXIgZWRnZURpc3RhbmNlcyA9IGVkZ2UucHN0eWxlKCdlZGdlLWRpc3RhbmNlcycpLnZhbHVlO1xuICB2YXIgc2VnbWVudFdzID0gZWRnZS5wc3R5bGUoJ3NlZ21lbnQtd2VpZ2h0cycpO1xuICB2YXIgc2VnbWVudERzID0gZWRnZS5wc3R5bGUoJ3NlZ21lbnQtZGlzdGFuY2VzJyk7XG4gIHZhciBzZWdtZW50c04gPSBNYXRoLm1pbihzZWdtZW50V3MucGZWYWx1ZS5sZW5ndGgsIHNlZ21lbnREcy5wZlZhbHVlLmxlbmd0aCk7XG4gIHJzLmVkZ2VUeXBlID0gJ3NlZ21lbnRzJztcbiAgcnMuc2VncHRzID0gW107XG5cbiAgZm9yICh2YXIgcyA9IDA7IHMgPCBzZWdtZW50c047IHMrKykge1xuICAgIHZhciB3ID0gc2VnbWVudFdzLnBmVmFsdWVbc107XG4gICAgdmFyIGQgPSBzZWdtZW50RHMucGZWYWx1ZVtzXTtcbiAgICB2YXIgdzEgPSAxIC0gdztcbiAgICB2YXIgdzIgPSB3O1xuICAgIHZhciBtaWRwdFB0cyA9IGVkZ2VEaXN0YW5jZXMgPT09ICdub2RlLXBvc2l0aW9uJyA/IHBvc1B0cyA6IGludGVyc2VjdGlvblB0cztcbiAgICB2YXIgYWRqdXN0ZWRNaWRwdCA9IHtcbiAgICAgIHg6IG1pZHB0UHRzLngxICogdzEgKyBtaWRwdFB0cy54MiAqIHcyLFxuICAgICAgeTogbWlkcHRQdHMueTEgKiB3MSArIG1pZHB0UHRzLnkyICogdzJcbiAgICB9O1xuICAgIHJzLnNlZ3B0cy5wdXNoKGFkanVzdGVkTWlkcHQueCArIHZlY3Rvck5vcm1JbnZlcnNlLnggKiBkLCBhZGp1c3RlZE1pZHB0LnkgKyB2ZWN0b3JOb3JtSW52ZXJzZS55ICogZCk7XG4gIH1cbn07XG5cbkJScCQzLmZpbmRMb29wUG9pbnRzID0gZnVuY3Rpb24gKGVkZ2UsIHBhaXJJbmZvLCBpLCBlZGdlSXNVbmJ1bmRsZWQpIHtcbiAgLy8gU2VsZi1lZGdlXG4gIHZhciBycyA9IGVkZ2UuX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHZhciBkaXJDb3VudHMgPSBwYWlySW5mby5kaXJDb3VudHMsXG4gICAgICBzcmNQb3MgPSBwYWlySW5mby5zcmNQb3M7XG4gIHZhciBjdHJscHREaXN0cyA9IGVkZ2UucHN0eWxlKCdjb250cm9sLXBvaW50LWRpc3RhbmNlcycpO1xuICB2YXIgY3RybHB0RGlzdCA9IGN0cmxwdERpc3RzID8gY3RybHB0RGlzdHMucGZWYWx1ZVswXSA6IHVuZGVmaW5lZDtcbiAgdmFyIGxvb3BEaXIgPSBlZGdlLnBzdHlsZSgnbG9vcC1kaXJlY3Rpb24nKS5wZlZhbHVlO1xuICB2YXIgbG9vcFN3cCA9IGVkZ2UucHN0eWxlKCdsb29wLXN3ZWVwJykucGZWYWx1ZTtcbiAgdmFyIHN0ZXBTaXplID0gZWRnZS5wc3R5bGUoJ2NvbnRyb2wtcG9pbnQtc3RlcC1zaXplJykucGZWYWx1ZTtcbiAgcnMuZWRnZVR5cGUgPSAnc2VsZic7XG4gIHZhciBqID0gaTtcbiAgdmFyIGxvb3BEaXN0ID0gc3RlcFNpemU7XG5cbiAgaWYgKGVkZ2VJc1VuYnVuZGxlZCkge1xuICAgIGogPSAwO1xuICAgIGxvb3BEaXN0ID0gY3RybHB0RGlzdDtcbiAgfVxuXG4gIHZhciBsb29wQW5nbGUgPSBsb29wRGlyIC0gTWF0aC5QSSAvIDI7XG4gIHZhciBvdXRBbmdsZSA9IGxvb3BBbmdsZSAtIGxvb3BTd3AgLyAyO1xuICB2YXIgaW5BbmdsZSA9IGxvb3BBbmdsZSArIGxvb3BTd3AgLyAyOyAvLyBpbmNyZWFzZSBieSBzdGVwIHNpemUgZm9yIG92ZXJsYXBwaW5nIGxvb3BzLCBrZXllZCBvbiBkaXJlY3Rpb24gYW5kIHN3ZWVwIHZhbHVlc1xuXG4gIHZhciBkYyA9IFN0cmluZyhsb29wRGlyICsgJ18nICsgbG9vcFN3cCk7XG4gIGogPSBkaXJDb3VudHNbZGNdID09PSB1bmRlZmluZWQgPyBkaXJDb3VudHNbZGNdID0gMCA6ICsrZGlyQ291bnRzW2RjXTtcbiAgcnMuY3RybHB0cyA9IFtzcmNQb3MueCArIE1hdGguY29zKG91dEFuZ2xlKSAqIDEuNCAqIGxvb3BEaXN0ICogKGogLyAzICsgMSksIHNyY1Bvcy55ICsgTWF0aC5zaW4ob3V0QW5nbGUpICogMS40ICogbG9vcERpc3QgKiAoaiAvIDMgKyAxKSwgc3JjUG9zLnggKyBNYXRoLmNvcyhpbkFuZ2xlKSAqIDEuNCAqIGxvb3BEaXN0ICogKGogLyAzICsgMSksIHNyY1Bvcy55ICsgTWF0aC5zaW4oaW5BbmdsZSkgKiAxLjQgKiBsb29wRGlzdCAqIChqIC8gMyArIDEpXTtcbn07XG5cbkJScCQzLmZpbmRDb21wb3VuZExvb3BQb2ludHMgPSBmdW5jdGlvbiAoZWRnZSwgcGFpckluZm8sIGksIGVkZ2VJc1VuYnVuZGxlZCkge1xuICAvLyBDb21wb3VuZCBlZGdlXG4gIHZhciBycyA9IGVkZ2UuX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHJzLmVkZ2VUeXBlID0gJ2NvbXBvdW5kJztcbiAgdmFyIHNyY1BvcyA9IHBhaXJJbmZvLnNyY1BvcyxcbiAgICAgIHRndFBvcyA9IHBhaXJJbmZvLnRndFBvcyxcbiAgICAgIHNyY1cgPSBwYWlySW5mby5zcmNXLFxuICAgICAgc3JjSCA9IHBhaXJJbmZvLnNyY0gsXG4gICAgICB0Z3RXID0gcGFpckluZm8udGd0VyxcbiAgICAgIHRndEggPSBwYWlySW5mby50Z3RIO1xuICB2YXIgc3RlcFNpemUgPSBlZGdlLnBzdHlsZSgnY29udHJvbC1wb2ludC1zdGVwLXNpemUnKS5wZlZhbHVlO1xuICB2YXIgY3RybHB0RGlzdHMgPSBlZGdlLnBzdHlsZSgnY29udHJvbC1wb2ludC1kaXN0YW5jZXMnKTtcbiAgdmFyIGN0cmxwdERpc3QgPSBjdHJscHREaXN0cyA/IGN0cmxwdERpc3RzLnBmVmFsdWVbMF0gOiB1bmRlZmluZWQ7XG4gIHZhciBqID0gaTtcbiAgdmFyIGxvb3BEaXN0ID0gc3RlcFNpemU7XG5cbiAgaWYgKGVkZ2VJc1VuYnVuZGxlZCkge1xuICAgIGogPSAwO1xuICAgIGxvb3BEaXN0ID0gY3RybHB0RGlzdDtcbiAgfVxuXG4gIHZhciBsb29wVyA9IDUwO1xuICB2YXIgbG9vcGFQb3MgPSB7XG4gICAgeDogc3JjUG9zLnggLSBzcmNXIC8gMixcbiAgICB5OiBzcmNQb3MueSAtIHNyY0ggLyAyXG4gIH07XG4gIHZhciBsb29wYlBvcyA9IHtcbiAgICB4OiB0Z3RQb3MueCAtIHRndFcgLyAyLFxuICAgIHk6IHRndFBvcy55IC0gdGd0SCAvIDJcbiAgfTtcbiAgdmFyIGxvb3BQb3MgPSB7XG4gICAgeDogTWF0aC5taW4obG9vcGFQb3MueCwgbG9vcGJQb3MueCksXG4gICAgeTogTWF0aC5taW4obG9vcGFQb3MueSwgbG9vcGJQb3MueSlcbiAgfTsgLy8gYXZvaWRzIGNhc2VzIHdpdGggaW1wb3NzaWJsZSBiZXppZXJzXG5cbiAgdmFyIG1pbkNvbXBvdW5kU3RyZXRjaCA9IDAuNTtcbiAgdmFyIGNvbXBvdW5kU3RyZXRjaEEgPSBNYXRoLm1heChtaW5Db21wb3VuZFN0cmV0Y2gsIE1hdGgubG9nKHNyY1cgKiAwLjAxKSk7XG4gIHZhciBjb21wb3VuZFN0cmV0Y2hCID0gTWF0aC5tYXgobWluQ29tcG91bmRTdHJldGNoLCBNYXRoLmxvZyh0Z3RXICogMC4wMSkpO1xuICBycy5jdHJscHRzID0gW2xvb3BQb3MueCwgbG9vcFBvcy55IC0gKDEgKyBNYXRoLnBvdyhsb29wVywgMS4xMikgLyAxMDApICogbG9vcERpc3QgKiAoaiAvIDMgKyAxKSAqIGNvbXBvdW5kU3RyZXRjaEEsIGxvb3BQb3MueCAtICgxICsgTWF0aC5wb3cobG9vcFcsIDEuMTIpIC8gMTAwKSAqIGxvb3BEaXN0ICogKGogLyAzICsgMSkgKiBjb21wb3VuZFN0cmV0Y2hCLCBsb29wUG9zLnldO1xufTtcblxuQlJwJDMuZmluZFN0cmFpZ2h0RWRnZVBvaW50cyA9IGZ1bmN0aW9uIChlZGdlKSB7XG4gIC8vIFN0cmFpZ2h0IGVkZ2Ugd2l0aGluIGJ1bmRsZVxuICBlZGdlLl9wcml2YXRlLnJzY3JhdGNoLmVkZ2VUeXBlID0gJ3N0cmFpZ2h0Jztcbn07XG5cbkJScCQzLmZpbmRCZXppZXJQb2ludHMgPSBmdW5jdGlvbiAoZWRnZSwgcGFpckluZm8sIGksIGVkZ2VJc1VuYnVuZGxlZCwgZWRnZUlzU3dhcHBlZCkge1xuICB2YXIgcnMgPSBlZGdlLl9wcml2YXRlLnJzY3JhdGNoO1xuICB2YXIgdmVjdG9yTm9ybUludmVyc2UgPSBwYWlySW5mby52ZWN0b3JOb3JtSW52ZXJzZSxcbiAgICAgIHBvc1B0cyA9IHBhaXJJbmZvLnBvc1B0cyxcbiAgICAgIGludGVyc2VjdGlvblB0cyA9IHBhaXJJbmZvLmludGVyc2VjdGlvblB0cztcbiAgdmFyIGVkZ2VEaXN0YW5jZXMgPSBlZGdlLnBzdHlsZSgnZWRnZS1kaXN0YW5jZXMnKS52YWx1ZTtcbiAgdmFyIHN0ZXBTaXplID0gZWRnZS5wc3R5bGUoJ2NvbnRyb2wtcG9pbnQtc3RlcC1zaXplJykucGZWYWx1ZTtcbiAgdmFyIGN0cmxwdERpc3RzID0gZWRnZS5wc3R5bGUoJ2NvbnRyb2wtcG9pbnQtZGlzdGFuY2VzJyk7XG4gIHZhciBjdHJscHRXcyA9IGVkZ2UucHN0eWxlKCdjb250cm9sLXBvaW50LXdlaWdodHMnKTtcbiAgdmFyIGJlemllck4gPSBjdHJscHREaXN0cyAmJiBjdHJscHRXcyA/IE1hdGgubWluKGN0cmxwdERpc3RzLnZhbHVlLmxlbmd0aCwgY3RybHB0V3MudmFsdWUubGVuZ3RoKSA6IDE7XG4gIHZhciBjdHJscHREaXN0ID0gY3RybHB0RGlzdHMgPyBjdHJscHREaXN0cy5wZlZhbHVlWzBdIDogdW5kZWZpbmVkO1xuICB2YXIgY3RybHB0V2VpZ2h0ID0gY3RybHB0V3MudmFsdWVbMF07IC8vIChNdWx0aSliZXppZXJcblxuICB2YXIgbXVsdGkgPSBlZGdlSXNVbmJ1bmRsZWQ7XG4gIHJzLmVkZ2VUeXBlID0gbXVsdGkgPyAnbXVsdGliZXppZXInIDogJ2Jlemllcic7XG4gIHJzLmN0cmxwdHMgPSBbXTtcblxuICBmb3IgKHZhciBiID0gMDsgYiA8IGJlemllck47IGIrKykge1xuICAgIHZhciBub3JtY3RybHB0RGlzdCA9ICgwLjUgLSBwYWlySW5mby5lbGVzLmxlbmd0aCAvIDIgKyBpKSAqIHN0ZXBTaXplICogKGVkZ2VJc1N3YXBwZWQgPyAtMSA6IDEpO1xuICAgIHZhciBtYW5jdHJscHREaXN0ID0gdm9pZCAwO1xuICAgIHZhciBzaWduID0gc2lnbnVtKG5vcm1jdHJscHREaXN0KTtcblxuICAgIGlmIChtdWx0aSkge1xuICAgICAgY3RybHB0RGlzdCA9IGN0cmxwdERpc3RzID8gY3RybHB0RGlzdHMucGZWYWx1ZVtiXSA6IHN0ZXBTaXplOyAvLyBmYWxsIGJhY2sgb24gc3RlcCBzaXplXG5cbiAgICAgIGN0cmxwdFdlaWdodCA9IGN0cmxwdFdzLnZhbHVlW2JdO1xuICAgIH1cblxuICAgIGlmIChlZGdlSXNVbmJ1bmRsZWQpIHtcbiAgICAgIC8vIG11bHRpIG9yIHNpbmdsZSB1bmJ1bmRsZWRcbiAgICAgIG1hbmN0cmxwdERpc3QgPSBjdHJscHREaXN0O1xuICAgIH0gZWxzZSB7XG4gICAgICBtYW5jdHJscHREaXN0ID0gY3RybHB0RGlzdCAhPT0gdW5kZWZpbmVkID8gc2lnbiAqIGN0cmxwdERpc3QgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgdmFyIGRpc3RhbmNlRnJvbU1pZHBvaW50ID0gbWFuY3RybHB0RGlzdCAhPT0gdW5kZWZpbmVkID8gbWFuY3RybHB0RGlzdCA6IG5vcm1jdHJscHREaXN0O1xuICAgIHZhciB3MSA9IDEgLSBjdHJscHRXZWlnaHQ7XG4gICAgdmFyIHcyID0gY3RybHB0V2VpZ2h0O1xuICAgIHZhciBtaWRwdFB0cyA9IGVkZ2VEaXN0YW5jZXMgPT09ICdub2RlLXBvc2l0aW9uJyA/IHBvc1B0cyA6IGludGVyc2VjdGlvblB0cztcbiAgICB2YXIgYWRqdXN0ZWRNaWRwdCA9IHtcbiAgICAgIHg6IG1pZHB0UHRzLngxICogdzEgKyBtaWRwdFB0cy54MiAqIHcyLFxuICAgICAgeTogbWlkcHRQdHMueTEgKiB3MSArIG1pZHB0UHRzLnkyICogdzJcbiAgICB9O1xuICAgIHJzLmN0cmxwdHMucHVzaChhZGp1c3RlZE1pZHB0LnggKyB2ZWN0b3JOb3JtSW52ZXJzZS54ICogZGlzdGFuY2VGcm9tTWlkcG9pbnQsIGFkanVzdGVkTWlkcHQueSArIHZlY3Rvck5vcm1JbnZlcnNlLnkgKiBkaXN0YW5jZUZyb21NaWRwb2ludCk7XG4gIH1cbn07XG5cbkJScCQzLmZpbmRUYXhpUG9pbnRzID0gZnVuY3Rpb24gKGVkZ2UsIHBhaXJJbmZvKSB7XG4gIC8vIFRheGljYWIgZ2VvbWV0cnkgd2l0aCB0d28gdHVybnMgbWF4aW11bVxuICB2YXIgcnMgPSBlZGdlLl9wcml2YXRlLnJzY3JhdGNoO1xuICBycy5lZGdlVHlwZSA9ICdzZWdtZW50cyc7XG4gIHZhciBWRVJUSUNBTCA9ICd2ZXJ0aWNhbCc7XG4gIHZhciBIT1JJWk9OVEFMID0gJ2hvcml6b250YWwnO1xuICB2YXIgTEVGVFdBUkQgPSAnbGVmdHdhcmQnO1xuICB2YXIgUklHSFRXQVJEID0gJ3JpZ2h0d2FyZCc7XG4gIHZhciBET1dOV0FSRCA9ICdkb3dud2FyZCc7XG4gIHZhciBVUFdBUkQgPSAndXB3YXJkJztcbiAgdmFyIEFVVE8gPSAnYXV0byc7XG4gIHZhciBwb3NQdHMgPSBwYWlySW5mby5wb3NQdHMsXG4gICAgICBzcmNXID0gcGFpckluZm8uc3JjVyxcbiAgICAgIHNyY0ggPSBwYWlySW5mby5zcmNILFxuICAgICAgdGd0VyA9IHBhaXJJbmZvLnRndFcsXG4gICAgICB0Z3RIID0gcGFpckluZm8udGd0SDtcbiAgdmFyIGVkZ2VEaXN0YW5jZXMgPSBlZGdlLnBzdHlsZSgnZWRnZS1kaXN0YW5jZXMnKS52YWx1ZTtcbiAgdmFyIGRJbmNsdWRlc05vZGVCb2R5ID0gZWRnZURpc3RhbmNlcyAhPT0gJ25vZGUtcG9zaXRpb24nO1xuICB2YXIgdGF4aURpciA9IGVkZ2UucHN0eWxlKCd0YXhpLWRpcmVjdGlvbicpLnZhbHVlO1xuICB2YXIgcmF3VGF4aURpciA9IHRheGlEaXI7IC8vIHVucHJvY2Vzc2VkIHZhbHVlXG5cbiAgdmFyIHRheGlUdXJuID0gZWRnZS5wc3R5bGUoJ3RheGktdHVybicpO1xuICB2YXIgdHVybklzUGVyY2VudCA9IHRheGlUdXJuLnVuaXRzID09PSAnJSc7XG4gIHZhciB0YXhpVHVyblBmVmFsID0gdGF4aVR1cm4ucGZWYWx1ZTtcbiAgdmFyIHR1cm5Jc05lZ2F0aXZlID0gdGF4aVR1cm5QZlZhbCA8IDA7IC8vIGkuZS4gZnJvbSB0YXJnZXQgc2lkZVxuXG4gIHZhciBtaW5EID0gZWRnZS5wc3R5bGUoJ3RheGktdHVybi1taW4tZGlzdGFuY2UnKS5wZlZhbHVlO1xuICB2YXIgZHcgPSBkSW5jbHVkZXNOb2RlQm9keSA/IChzcmNXICsgdGd0VykgLyAyIDogMDtcbiAgdmFyIGRoID0gZEluY2x1ZGVzTm9kZUJvZHkgPyAoc3JjSCArIHRndEgpIC8gMiA6IDA7XG4gIHZhciBwZHggPSBwb3NQdHMueDIgLSBwb3NQdHMueDE7XG4gIHZhciBwZHkgPSBwb3NQdHMueTIgLSBwb3NQdHMueTE7IC8vIHRha2UgYXdheSB0aGUgZWZmZWN0aXZlIHcvaCBmcm9tIHRoZSBtYWduaXR1ZGUgb2YgdGhlIGRlbHRhIHZhbHVlXG5cbiAgdmFyIHN1YkRXSCA9IGZ1bmN0aW9uIHN1YkRXSChkeHksIGR3aCkge1xuICAgIGlmIChkeHkgPiAwKSB7XG4gICAgICByZXR1cm4gTWF0aC5tYXgoZHh5IC0gZHdoLCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIE1hdGgubWluKGR4eSArIGR3aCwgMCk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBkeCA9IHN1YkRXSChwZHgsIGR3KTtcbiAgdmFyIGR5ID0gc3ViRFdIKHBkeSwgZGgpO1xuICB2YXIgaXNFeHBsaWNpdERpciA9IGZhbHNlO1xuXG4gIGlmIChyYXdUYXhpRGlyID09PSBBVVRPKSB7XG4gICAgdGF4aURpciA9IE1hdGguYWJzKGR4KSA+IE1hdGguYWJzKGR5KSA/IEhPUklaT05UQUwgOiBWRVJUSUNBTDtcbiAgfSBlbHNlIGlmIChyYXdUYXhpRGlyID09PSBVUFdBUkQgfHwgcmF3VGF4aURpciA9PT0gRE9XTldBUkQpIHtcbiAgICB0YXhpRGlyID0gVkVSVElDQUw7XG4gICAgaXNFeHBsaWNpdERpciA9IHRydWU7XG4gIH0gZWxzZSBpZiAocmF3VGF4aURpciA9PT0gTEVGVFdBUkQgfHwgcmF3VGF4aURpciA9PT0gUklHSFRXQVJEKSB7XG4gICAgdGF4aURpciA9IEhPUklaT05UQUw7XG4gICAgaXNFeHBsaWNpdERpciA9IHRydWU7XG4gIH1cblxuICB2YXIgaXNWZXJ0ID0gdGF4aURpciA9PT0gVkVSVElDQUw7XG4gIHZhciBsID0gaXNWZXJ0ID8gZHkgOiBkeDtcbiAgdmFyIHBsID0gaXNWZXJ0ID8gcGR5IDogcGR4O1xuICB2YXIgc2duTCA9IHNpZ251bShwbCk7XG4gIHZhciBmb3JjZWREaXIgPSBmYWxzZTtcblxuICBpZiAoIShpc0V4cGxpY2l0RGlyICYmICh0dXJuSXNQZXJjZW50IHx8IHR1cm5Jc05lZ2F0aXZlKSkgLy8gZm9yY2luZyBpbiB0aGlzIGNhc2Ugd291bGQgY2F1c2Ugd2VpcmQgZ3Jvd2luZyBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uXG4gICYmIChyYXdUYXhpRGlyID09PSBET1dOV0FSRCAmJiBwbCA8IDAgfHwgcmF3VGF4aURpciA9PT0gVVBXQVJEICYmIHBsID4gMCB8fCByYXdUYXhpRGlyID09PSBMRUZUV0FSRCAmJiBwbCA+IDAgfHwgcmF3VGF4aURpciA9PT0gUklHSFRXQVJEICYmIHBsIDwgMCkpIHtcbiAgICBzZ25MICo9IC0xO1xuICAgIGwgPSBzZ25MICogTWF0aC5hYnMobCk7XG4gICAgZm9yY2VkRGlyID0gdHJ1ZTtcbiAgfVxuXG4gIHZhciBkO1xuXG4gIGlmICh0dXJuSXNQZXJjZW50KSB7XG4gICAgdmFyIHAgPSB0YXhpVHVyblBmVmFsIDwgMCA/IDEgKyB0YXhpVHVyblBmVmFsIDogdGF4aVR1cm5QZlZhbDtcbiAgICBkID0gcCAqIGw7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGsgPSB0YXhpVHVyblBmVmFsIDwgMCA/IGwgOiAwO1xuICAgIGQgPSBrICsgdGF4aVR1cm5QZlZhbCAqIHNnbkw7XG4gIH1cblxuICB2YXIgZ2V0SXNUb29DbG9zZSA9IGZ1bmN0aW9uIGdldElzVG9vQ2xvc2UoZCkge1xuICAgIHJldHVybiBNYXRoLmFicyhkKSA8IG1pbkQgfHwgTWF0aC5hYnMoZCkgPj0gTWF0aC5hYnMobCk7XG4gIH07XG5cbiAgdmFyIGlzVG9vQ2xvc2VTcmMgPSBnZXRJc1Rvb0Nsb3NlKGQpO1xuICB2YXIgaXNUb29DbG9zZVRndCA9IGdldElzVG9vQ2xvc2UoTWF0aC5hYnMobCkgLSBNYXRoLmFicyhkKSk7XG4gIHZhciBpc1Rvb0Nsb3NlID0gaXNUb29DbG9zZVNyYyB8fCBpc1Rvb0Nsb3NlVGd0O1xuXG4gIGlmIChpc1Rvb0Nsb3NlICYmICFmb3JjZWREaXIpIHtcbiAgICAvLyBub24taWRlYWwgcm91dGluZ1xuICAgIGlmIChpc1ZlcnQpIHtcbiAgICAgIC8vIHZlcnRpY2FsIGZhbGxiYWNrc1xuICAgICAgdmFyIGxTaGFwZUluc2lkZVNyYyA9IE1hdGguYWJzKHBsKSA8PSBzcmNIIC8gMjtcbiAgICAgIHZhciBsU2hhcGVJbnNpZGVUZ3QgPSBNYXRoLmFicyhwZHgpIDw9IHRndFcgLyAyO1xuXG4gICAgICBpZiAobFNoYXBlSW5zaWRlU3JjKSB7XG4gICAgICAgIC8vIGhvcml6b250YWwgWi1zaGFwZSAoZGlyZWN0aW9uIG5vdCByZXNwZWN0ZWQpXG4gICAgICAgIHZhciB4ID0gKHBvc1B0cy54MSArIHBvc1B0cy54MikgLyAyO1xuICAgICAgICB2YXIgeTEgPSBwb3NQdHMueTEsXG4gICAgICAgICAgICB5MiA9IHBvc1B0cy55MjtcbiAgICAgICAgcnMuc2VncHRzID0gW3gsIHkxLCB4LCB5Ml07XG4gICAgICB9IGVsc2UgaWYgKGxTaGFwZUluc2lkZVRndCkge1xuICAgICAgICAvLyB2ZXJ0aWNhbCBaLXNoYXBlIChkaXN0YW5jZSBub3QgcmVzcGVjdGVkKVxuICAgICAgICB2YXIgeSA9IChwb3NQdHMueTEgKyBwb3NQdHMueTIpIC8gMjtcbiAgICAgICAgdmFyIHgxID0gcG9zUHRzLngxLFxuICAgICAgICAgICAgeDIgPSBwb3NQdHMueDI7XG4gICAgICAgIHJzLnNlZ3B0cyA9IFt4MSwgeSwgeDIsIHldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gTC1zaGFwZSBmYWxsYmFjayAodHVybiBkaXN0YW5jZSBub3QgcmVzcGVjdGVkLCBidXQgd29ya3Mgd2VsbCB3aXRoIHRyZWUgc2libGluZ3MpXG4gICAgICAgIHJzLnNlZ3B0cyA9IFtwb3NQdHMueDEsIHBvc1B0cy55Ml07XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGhvcml6b250YWwgZmFsbGJhY2tzXG4gICAgICB2YXIgX2xTaGFwZUluc2lkZVNyYyA9IE1hdGguYWJzKHBsKSA8PSBzcmNXIC8gMjtcblxuICAgICAgdmFyIF9sU2hhcGVJbnNpZGVUZ3QgPSBNYXRoLmFicyhwZHkpIDw9IHRndEggLyAyO1xuXG4gICAgICBpZiAoX2xTaGFwZUluc2lkZVNyYykge1xuICAgICAgICAvLyB2ZXJ0aWNhbCBaLXNoYXBlIChkaXJlY3Rpb24gbm90IHJlc3BlY3RlZClcbiAgICAgICAgdmFyIF95ID0gKHBvc1B0cy55MSArIHBvc1B0cy55MikgLyAyO1xuXG4gICAgICAgIHZhciBfeCA9IHBvc1B0cy54MSxcbiAgICAgICAgICAgIF94MiA9IHBvc1B0cy54MjtcbiAgICAgICAgcnMuc2VncHRzID0gW194LCBfeSwgX3gyLCBfeV07XG4gICAgICB9IGVsc2UgaWYgKF9sU2hhcGVJbnNpZGVUZ3QpIHtcbiAgICAgICAgLy8gaG9yaXpvbnRhbCBaLXNoYXBlICh0dXJuIGRpc3RhbmNlIG5vdCByZXNwZWN0ZWQpXG4gICAgICAgIHZhciBfeDMgPSAocG9zUHRzLngxICsgcG9zUHRzLngyKSAvIDI7XG5cbiAgICAgICAgdmFyIF95MiA9IHBvc1B0cy55MSxcbiAgICAgICAgICAgIF95MyA9IHBvc1B0cy55MjtcbiAgICAgICAgcnMuc2VncHRzID0gW194MywgX3kyLCBfeDMsIF95M107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBMLXNoYXBlICh0dXJuIGRpc3RhbmNlIG5vdCByZXNwZWN0ZWQsIGJ1dCB3b3JrcyB3ZWxsIGZvciB0cmVlIHNpYmxpbmdzKVxuICAgICAgICBycy5zZWdwdHMgPSBbcG9zUHRzLngyLCBwb3NQdHMueTFdO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBpZGVhbCByb3V0aW5nXG4gICAgaWYgKGlzVmVydCkge1xuICAgICAgdmFyIF95NCA9IHBvc1B0cy55MSArIGQgKyAoZEluY2x1ZGVzTm9kZUJvZHkgPyBzcmNIIC8gMiAqIHNnbkwgOiAwKTtcblxuICAgICAgdmFyIF94NCA9IHBvc1B0cy54MSxcbiAgICAgICAgICBfeDUgPSBwb3NQdHMueDI7XG4gICAgICBycy5zZWdwdHMgPSBbX3g0LCBfeTQsIF94NSwgX3k0XTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaG9yaXpvbnRhbFxuICAgICAgdmFyIF94NiA9IHBvc1B0cy54MSArIGQgKyAoZEluY2x1ZGVzTm9kZUJvZHkgPyBzcmNXIC8gMiAqIHNnbkwgOiAwKTtcblxuICAgICAgdmFyIF95NSA9IHBvc1B0cy55MSxcbiAgICAgICAgICBfeTYgPSBwb3NQdHMueTI7XG4gICAgICBycy5zZWdwdHMgPSBbX3g2LCBfeTUsIF94NiwgX3k2XTtcbiAgICB9XG4gIH1cbn07XG5cbkJScCQzLnRyeVRvQ29ycmVjdEludmFsaWRQb2ludHMgPSBmdW5jdGlvbiAoZWRnZSwgcGFpckluZm8pIHtcbiAgdmFyIHJzID0gZWRnZS5fcHJpdmF0ZS5yc2NyYXRjaDsgLy8gY2FuIG9ubHkgY29ycmVjdCBiZXppZXJzIGZvciBub3cuLi5cblxuICBpZiAocnMuZWRnZVR5cGUgPT09ICdiZXppZXInKSB7XG4gICAgdmFyIHNyY1BvcyA9IHBhaXJJbmZvLnNyY1BvcyxcbiAgICAgICAgdGd0UG9zID0gcGFpckluZm8udGd0UG9zLFxuICAgICAgICBzcmNXID0gcGFpckluZm8uc3JjVyxcbiAgICAgICAgc3JjSCA9IHBhaXJJbmZvLnNyY0gsXG4gICAgICAgIHRndFcgPSBwYWlySW5mby50Z3RXLFxuICAgICAgICB0Z3RIID0gcGFpckluZm8udGd0SCxcbiAgICAgICAgc3JjU2hhcGUgPSBwYWlySW5mby5zcmNTaGFwZSxcbiAgICAgICAgdGd0U2hhcGUgPSBwYWlySW5mby50Z3RTaGFwZTtcbiAgICB2YXIgYmFkU3RhcnQgPSAhbnVtYmVyKHJzLnN0YXJ0WCkgfHwgIW51bWJlcihycy5zdGFydFkpO1xuICAgIHZhciBiYWRBU3RhcnQgPSAhbnVtYmVyKHJzLmFycm93U3RhcnRYKSB8fCAhbnVtYmVyKHJzLmFycm93U3RhcnRZKTtcbiAgICB2YXIgYmFkRW5kID0gIW51bWJlcihycy5lbmRYKSB8fCAhbnVtYmVyKHJzLmVuZFkpO1xuICAgIHZhciBiYWRBRW5kID0gIW51bWJlcihycy5hcnJvd0VuZFgpIHx8ICFudW1iZXIocnMuYXJyb3dFbmRZKTtcbiAgICB2YXIgbWluQ3BBRGlzdEZhY3RvciA9IDM7XG4gICAgdmFyIGFycm93VyA9IHRoaXMuZ2V0QXJyb3dXaWR0aChlZGdlLnBzdHlsZSgnd2lkdGgnKS5wZlZhbHVlLCBlZGdlLnBzdHlsZSgnYXJyb3ctc2NhbGUnKS52YWx1ZSkgKiB0aGlzLmFycm93U2hhcGVXaWR0aDtcbiAgICB2YXIgbWluQ3BBRGlzdCA9IG1pbkNwQURpc3RGYWN0b3IgKiBhcnJvd1c7XG4gICAgdmFyIHN0YXJ0QUNwRGlzdCA9IGRpc3Qoe1xuICAgICAgeDogcnMuY3RybHB0c1swXSxcbiAgICAgIHk6IHJzLmN0cmxwdHNbMV1cbiAgICB9LCB7XG4gICAgICB4OiBycy5zdGFydFgsXG4gICAgICB5OiBycy5zdGFydFlcbiAgICB9KTtcbiAgICB2YXIgY2xvc2VTdGFydEFDcCA9IHN0YXJ0QUNwRGlzdCA8IG1pbkNwQURpc3Q7XG4gICAgdmFyIGVuZEFDcERpc3QgPSBkaXN0KHtcbiAgICAgIHg6IHJzLmN0cmxwdHNbMF0sXG4gICAgICB5OiBycy5jdHJscHRzWzFdXG4gICAgfSwge1xuICAgICAgeDogcnMuZW5kWCxcbiAgICAgIHk6IHJzLmVuZFlcbiAgICB9KTtcbiAgICB2YXIgY2xvc2VFbmRBQ3AgPSBlbmRBQ3BEaXN0IDwgbWluQ3BBRGlzdDtcbiAgICB2YXIgb3ZlcmxhcHBpbmcgPSBmYWxzZTtcblxuICAgIGlmIChiYWRTdGFydCB8fCBiYWRBU3RhcnQgfHwgY2xvc2VTdGFydEFDcCkge1xuICAgICAgb3ZlcmxhcHBpbmcgPSB0cnVlOyAvLyBwcm9qZWN0IGNvbnRyb2wgcG9pbnQgYWxvbmcgbGluZSBmcm9tIHNyYyBjZW50cmUgdG8gb3V0c2lkZSB0aGUgc3JjIHNoYXBlXG4gICAgICAvLyAob3RoZXJ3aXNlIGludGVyc2VjdGlvbiB3aWxsIHlpZWxkIG5vdGhpbmcpXG5cbiAgICAgIHZhciBjcEQgPSB7XG4gICAgICAgIC8vIGRlbHRhXG4gICAgICAgIHg6IHJzLmN0cmxwdHNbMF0gLSBzcmNQb3MueCxcbiAgICAgICAgeTogcnMuY3RybHB0c1sxXSAtIHNyY1Bvcy55XG4gICAgICB9O1xuICAgICAgdmFyIGNwTCA9IE1hdGguc3FydChjcEQueCAqIGNwRC54ICsgY3BELnkgKiBjcEQueSk7IC8vIGxlbmd0aCBvZiBsaW5lXG5cbiAgICAgIHZhciBjcE0gPSB7XG4gICAgICAgIC8vIG5vcm1hbGlzZWQgZGVsdGFcbiAgICAgICAgeDogY3BELnggLyBjcEwsXG4gICAgICAgIHk6IGNwRC55IC8gY3BMXG4gICAgICB9O1xuICAgICAgdmFyIHJhZGl1cyA9IE1hdGgubWF4KHNyY1csIHNyY0gpO1xuICAgICAgdmFyIGNwUHJvaiA9IHtcbiAgICAgICAgLy8gKjIgcmFkaXVzIGd1YXJhbnRlZXMgb3V0c2lkZSBzaGFwZVxuICAgICAgICB4OiBycy5jdHJscHRzWzBdICsgY3BNLnggKiAyICogcmFkaXVzLFxuICAgICAgICB5OiBycy5jdHJscHRzWzFdICsgY3BNLnkgKiAyICogcmFkaXVzXG4gICAgICB9O1xuICAgICAgdmFyIHNyY0N0cmxQdEludG4gPSBzcmNTaGFwZS5pbnRlcnNlY3RMaW5lKHNyY1Bvcy54LCBzcmNQb3MueSwgc3JjVywgc3JjSCwgY3BQcm9qLngsIGNwUHJvai55LCAwKTtcblxuICAgICAgaWYgKGNsb3NlU3RhcnRBQ3ApIHtcbiAgICAgICAgcnMuY3RybHB0c1swXSA9IHJzLmN0cmxwdHNbMF0gKyBjcE0ueCAqIChtaW5DcEFEaXN0IC0gc3RhcnRBQ3BEaXN0KTtcbiAgICAgICAgcnMuY3RybHB0c1sxXSA9IHJzLmN0cmxwdHNbMV0gKyBjcE0ueSAqIChtaW5DcEFEaXN0IC0gc3RhcnRBQ3BEaXN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJzLmN0cmxwdHNbMF0gPSBzcmNDdHJsUHRJbnRuWzBdICsgY3BNLnggKiBtaW5DcEFEaXN0O1xuICAgICAgICBycy5jdHJscHRzWzFdID0gc3JjQ3RybFB0SW50blsxXSArIGNwTS55ICogbWluQ3BBRGlzdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoYmFkRW5kIHx8IGJhZEFFbmQgfHwgY2xvc2VFbmRBQ3ApIHtcbiAgICAgIG92ZXJsYXBwaW5nID0gdHJ1ZTsgLy8gcHJvamVjdCBjb250cm9sIHBvaW50IGFsb25nIGxpbmUgZnJvbSB0Z3QgY2VudHJlIHRvIG91dHNpZGUgdGhlIHRndCBzaGFwZVxuICAgICAgLy8gKG90aGVyd2lzZSBpbnRlcnNlY3Rpb24gd2lsbCB5aWVsZCBub3RoaW5nKVxuXG4gICAgICB2YXIgX2NwRCA9IHtcbiAgICAgICAgLy8gZGVsdGFcbiAgICAgICAgeDogcnMuY3RybHB0c1swXSAtIHRndFBvcy54LFxuICAgICAgICB5OiBycy5jdHJscHRzWzFdIC0gdGd0UG9zLnlcbiAgICAgIH07XG5cbiAgICAgIHZhciBfY3BMID0gTWF0aC5zcXJ0KF9jcEQueCAqIF9jcEQueCArIF9jcEQueSAqIF9jcEQueSk7IC8vIGxlbmd0aCBvZiBsaW5lXG5cblxuICAgICAgdmFyIF9jcE0gPSB7XG4gICAgICAgIC8vIG5vcm1hbGlzZWQgZGVsdGFcbiAgICAgICAgeDogX2NwRC54IC8gX2NwTCxcbiAgICAgICAgeTogX2NwRC55IC8gX2NwTFxuICAgICAgfTtcblxuICAgICAgdmFyIF9yYWRpdXMgPSBNYXRoLm1heChzcmNXLCBzcmNIKTtcblxuICAgICAgdmFyIF9jcFByb2ogPSB7XG4gICAgICAgIC8vICoyIHJhZGl1cyBndWFyYW50ZWVzIG91dHNpZGUgc2hhcGVcbiAgICAgICAgeDogcnMuY3RybHB0c1swXSArIF9jcE0ueCAqIDIgKiBfcmFkaXVzLFxuICAgICAgICB5OiBycy5jdHJscHRzWzFdICsgX2NwTS55ICogMiAqIF9yYWRpdXNcbiAgICAgIH07XG4gICAgICB2YXIgdGd0Q3RybFB0SW50biA9IHRndFNoYXBlLmludGVyc2VjdExpbmUodGd0UG9zLngsIHRndFBvcy55LCB0Z3RXLCB0Z3RILCBfY3BQcm9qLngsIF9jcFByb2oueSwgMCk7XG5cbiAgICAgIGlmIChjbG9zZUVuZEFDcCkge1xuICAgICAgICBycy5jdHJscHRzWzBdID0gcnMuY3RybHB0c1swXSArIF9jcE0ueCAqIChtaW5DcEFEaXN0IC0gZW5kQUNwRGlzdCk7XG4gICAgICAgIHJzLmN0cmxwdHNbMV0gPSBycy5jdHJscHRzWzFdICsgX2NwTS55ICogKG1pbkNwQURpc3QgLSBlbmRBQ3BEaXN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJzLmN0cmxwdHNbMF0gPSB0Z3RDdHJsUHRJbnRuWzBdICsgX2NwTS54ICogbWluQ3BBRGlzdDtcbiAgICAgICAgcnMuY3RybHB0c1sxXSA9IHRndEN0cmxQdEludG5bMV0gKyBfY3BNLnkgKiBtaW5DcEFEaXN0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChvdmVybGFwcGluZykge1xuICAgICAgLy8gcmVjYWxjIGVuZHB0c1xuICAgICAgdGhpcy5maW5kRW5kcG9pbnRzKGVkZ2UpO1xuICAgIH1cbiAgfVxufTtcblxuQlJwJDMuc3RvcmVBbGxwdHMgPSBmdW5jdGlvbiAoZWRnZSkge1xuICB2YXIgcnMgPSBlZGdlLl9wcml2YXRlLnJzY3JhdGNoO1xuXG4gIGlmIChycy5lZGdlVHlwZSA9PT0gJ211bHRpYmV6aWVyJyB8fCBycy5lZGdlVHlwZSA9PT0gJ2JlemllcicgfHwgcnMuZWRnZVR5cGUgPT09ICdzZWxmJyB8fCBycy5lZGdlVHlwZSA9PT0gJ2NvbXBvdW5kJykge1xuICAgIHJzLmFsbHB0cyA9IFtdO1xuICAgIHJzLmFsbHB0cy5wdXNoKHJzLnN0YXJ0WCwgcnMuc3RhcnRZKTtcblxuICAgIGZvciAodmFyIGIgPSAwOyBiICsgMSA8IHJzLmN0cmxwdHMubGVuZ3RoOyBiICs9IDIpIHtcbiAgICAgIC8vIGN0cmwgcHQgaXRzZWxmXG4gICAgICBycy5hbGxwdHMucHVzaChycy5jdHJscHRzW2JdLCBycy5jdHJscHRzW2IgKyAxXSk7IC8vIHRoZSBtaWRwdCBiZXR3ZWVuIGN0cmxwdHMgYXMgaW50ZXJtZWRpYXRlIGRlc3RpbmF0aW9uIHB0c1xuXG4gICAgICBpZiAoYiArIDMgPCBycy5jdHJscHRzLmxlbmd0aCkge1xuICAgICAgICBycy5hbGxwdHMucHVzaCgocnMuY3RybHB0c1tiXSArIHJzLmN0cmxwdHNbYiArIDJdKSAvIDIsIChycy5jdHJscHRzW2IgKyAxXSArIHJzLmN0cmxwdHNbYiArIDNdKSAvIDIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJzLmFsbHB0cy5wdXNoKHJzLmVuZFgsIHJzLmVuZFkpO1xuICAgIHZhciBtLCBtdDtcblxuICAgIGlmIChycy5jdHJscHRzLmxlbmd0aCAvIDIgJSAyID09PSAwKSB7XG4gICAgICBtID0gcnMuYWxscHRzLmxlbmd0aCAvIDIgLSAxO1xuICAgICAgcnMubWlkWCA9IHJzLmFsbHB0c1ttXTtcbiAgICAgIHJzLm1pZFkgPSBycy5hbGxwdHNbbSArIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gcnMuYWxscHRzLmxlbmd0aCAvIDIgLSAzO1xuICAgICAgbXQgPSAwLjU7XG4gICAgICBycy5taWRYID0gcWJlemllckF0KHJzLmFsbHB0c1ttXSwgcnMuYWxscHRzW20gKyAyXSwgcnMuYWxscHRzW20gKyA0XSwgbXQpO1xuICAgICAgcnMubWlkWSA9IHFiZXppZXJBdChycy5hbGxwdHNbbSArIDFdLCBycy5hbGxwdHNbbSArIDNdLCBycy5hbGxwdHNbbSArIDVdLCBtdCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKHJzLmVkZ2VUeXBlID09PSAnc3RyYWlnaHQnKSB7XG4gICAgLy8gbmVlZCB0byBjYWxjIHRoZXNlIGFmdGVyIGVuZHB0c1xuICAgIHJzLmFsbHB0cyA9IFtycy5zdGFydFgsIHJzLnN0YXJ0WSwgcnMuZW5kWCwgcnMuZW5kWV07IC8vIGRlZmF1bHQgbWlkcHQgZm9yIGxhYmVscyBldGNcblxuICAgIHJzLm1pZFggPSAocnMuc3RhcnRYICsgcnMuZW5kWCArIHJzLmFycm93U3RhcnRYICsgcnMuYXJyb3dFbmRYKSAvIDQ7XG4gICAgcnMubWlkWSA9IChycy5zdGFydFkgKyBycy5lbmRZICsgcnMuYXJyb3dTdGFydFkgKyBycy5hcnJvd0VuZFkpIC8gNDtcbiAgfSBlbHNlIGlmIChycy5lZGdlVHlwZSA9PT0gJ3NlZ21lbnRzJykge1xuICAgIHJzLmFsbHB0cyA9IFtdO1xuICAgIHJzLmFsbHB0cy5wdXNoKHJzLnN0YXJ0WCwgcnMuc3RhcnRZKTtcbiAgICBycy5hbGxwdHMucHVzaC5hcHBseShycy5hbGxwdHMsIHJzLnNlZ3B0cyk7XG4gICAgcnMuYWxscHRzLnB1c2gocnMuZW5kWCwgcnMuZW5kWSk7XG5cbiAgICBpZiAocnMuc2VncHRzLmxlbmd0aCAlIDQgPT09IDApIHtcbiAgICAgIHZhciBpMiA9IHJzLnNlZ3B0cy5sZW5ndGggLyAyO1xuICAgICAgdmFyIGkxID0gaTIgLSAyO1xuICAgICAgcnMubWlkWCA9IChycy5zZWdwdHNbaTFdICsgcnMuc2VncHRzW2kyXSkgLyAyO1xuICAgICAgcnMubWlkWSA9IChycy5zZWdwdHNbaTEgKyAxXSArIHJzLnNlZ3B0c1tpMiArIDFdKSAvIDI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBfaSA9IHJzLnNlZ3B0cy5sZW5ndGggLyAyIC0gMTtcblxuICAgICAgcnMubWlkWCA9IHJzLnNlZ3B0c1tfaV07XG4gICAgICBycy5taWRZID0gcnMuc2VncHRzW19pICsgMV07XG4gICAgfVxuICB9XG59O1xuXG5CUnAkMy5jaGVja0ZvckludmFsaWRFZGdlV2FybmluZyA9IGZ1bmN0aW9uIChlZGdlKSB7XG4gIHZhciBycyA9IGVkZ2VbMF0uX3ByaXZhdGUucnNjcmF0Y2g7XG5cbiAgaWYgKHJzLm5vZGVzT3ZlcmxhcCB8fCBudW1iZXIocnMuc3RhcnRYKSAmJiBudW1iZXIocnMuc3RhcnRZKSAmJiBudW1iZXIocnMuZW5kWCkgJiYgbnVtYmVyKHJzLmVuZFkpKSB7XG4gICAgcnMubG9nZ2VkRXJyID0gZmFsc2U7XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFycy5sb2dnZWRFcnIpIHtcbiAgICAgIHJzLmxvZ2dlZEVyciA9IHRydWU7XG4gICAgICB3YXJuKCdFZGdlIGAnICsgZWRnZS5pZCgpICsgJ2AgaGFzIGludmFsaWQgZW5kcG9pbnRzIGFuZCBzbyBpdCBpcyBpbXBvc3NpYmxlIHRvIGRyYXcuICBBZGp1c3QgeW91ciBlZGdlIHN0eWxlIChlLmcuIGNvbnRyb2wgcG9pbnRzKSBhY2NvcmRpbmdseSBvciB1c2UgYW4gYWx0ZXJuYXRpdmUgZWRnZSB0eXBlLiAgVGhpcyBpcyBleHBlY3RlZCBiZWhhdmlvdXIgd2hlbiB0aGUgc291cmNlIG5vZGUgYW5kIHRoZSB0YXJnZXQgbm9kZSBvdmVybGFwLicpO1xuICAgIH1cbiAgfVxufTtcblxuQlJwJDMuZmluZEVkZ2VDb250cm9sUG9pbnRzID0gZnVuY3Rpb24gKGVkZ2VzKSB7XG4gIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgaWYgKCFlZGdlcyB8fCBlZGdlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgciA9IHRoaXM7XG4gIHZhciBjeSA9IHIuY3k7XG4gIHZhciBoYXNDb21wb3VuZHMgPSBjeS5oYXNDb21wb3VuZE5vZGVzKCk7XG4gIHZhciBoYXNoVGFibGUgPSB7XG4gICAgbWFwOiBuZXcgTWFwJDEoKSxcbiAgICBnZXQ6IGZ1bmN0aW9uIGdldChwYWlySWQpIHtcbiAgICAgIHZhciBtYXAyID0gdGhpcy5tYXAuZ2V0KHBhaXJJZFswXSk7XG5cbiAgICAgIGlmIChtYXAyICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG1hcDIuZ2V0KHBhaXJJZFsxXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24gc2V0KHBhaXJJZCwgdmFsKSB7XG4gICAgICB2YXIgbWFwMiA9IHRoaXMubWFwLmdldChwYWlySWRbMF0pO1xuXG4gICAgICBpZiAobWFwMiA9PSBudWxsKSB7XG4gICAgICAgIG1hcDIgPSBuZXcgTWFwJDEoKTtcbiAgICAgICAgdGhpcy5tYXAuc2V0KHBhaXJJZFswXSwgbWFwMik7XG4gICAgICB9XG5cbiAgICAgIG1hcDIuc2V0KHBhaXJJZFsxXSwgdmFsKTtcbiAgICB9XG4gIH07XG4gIHZhciBwYWlySWRzID0gW107XG4gIHZhciBoYXlzdGFja0VkZ2VzID0gW107IC8vIGNyZWF0ZSBhIHRhYmxlIG9mIGVkZ2UgKHNyYywgdGd0KSA9PiBsaXN0IG9mIGVkZ2VzIGJldHdlZW4gdGhlbVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZWRnZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWRnZSA9IGVkZ2VzW2ldO1xuICAgIHZhciBfcCA9IGVkZ2UuX3ByaXZhdGU7XG4gICAgdmFyIGN1cnZlU3R5bGUgPSBlZGdlLnBzdHlsZSgnY3VydmUtc3R5bGUnKS52YWx1ZTsgLy8gaWdub3JlIGVkZ2VzIHdobyBhcmUgbm90IHRvIGJlIGRpc3BsYXllZFxuICAgIC8vIHRoZXkgc2hvdWxkbid0IHRha2UgdXAgc3BhY2VcblxuICAgIGlmIChlZGdlLnJlbW92ZWQoKSB8fCAhZWRnZS50YWtlc1VwU3BhY2UoKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKGN1cnZlU3R5bGUgPT09ICdoYXlzdGFjaycpIHtcbiAgICAgIGhheXN0YWNrRWRnZXMucHVzaChlZGdlKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBlZGdlSXNVbmJ1bmRsZWQgPSBjdXJ2ZVN0eWxlID09PSAndW5idW5kbGVkLWJlemllcicgfHwgY3VydmVTdHlsZSA9PT0gJ3NlZ21lbnRzJyB8fCBjdXJ2ZVN0eWxlID09PSAnc3RyYWlnaHQnIHx8IGN1cnZlU3R5bGUgPT09ICd0YXhpJztcbiAgICB2YXIgZWRnZUlzQmV6aWVyID0gY3VydmVTdHlsZSA9PT0gJ3VuYnVuZGxlZC1iZXppZXInIHx8IGN1cnZlU3R5bGUgPT09ICdiZXppZXInO1xuICAgIHZhciBzcmMgPSBfcC5zb3VyY2U7XG4gICAgdmFyIHRndCA9IF9wLnRhcmdldDtcbiAgICB2YXIgc3JjSW5kZXggPSBzcmMucG9vbEluZGV4KCk7XG4gICAgdmFyIHRndEluZGV4ID0gdGd0LnBvb2xJbmRleCgpO1xuICAgIHZhciBwYWlySWQgPSBbc3JjSW5kZXgsIHRndEluZGV4XS5zb3J0KCk7XG4gICAgdmFyIHRhYmxlRW50cnkgPSBoYXNoVGFibGUuZ2V0KHBhaXJJZCk7XG5cbiAgICBpZiAodGFibGVFbnRyeSA9PSBudWxsKSB7XG4gICAgICB0YWJsZUVudHJ5ID0ge1xuICAgICAgICBlbGVzOiBbXVxuICAgICAgfTtcbiAgICAgIGhhc2hUYWJsZS5zZXQocGFpcklkLCB0YWJsZUVudHJ5KTtcbiAgICAgIHBhaXJJZHMucHVzaChwYWlySWQpO1xuICAgIH1cblxuICAgIHRhYmxlRW50cnkuZWxlcy5wdXNoKGVkZ2UpO1xuXG4gICAgaWYgKGVkZ2VJc1VuYnVuZGxlZCkge1xuICAgICAgdGFibGVFbnRyeS5oYXNVbmJ1bmRsZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChlZGdlSXNCZXppZXIpIHtcbiAgICAgIHRhYmxlRW50cnkuaGFzQmV6aWVyID0gdHJ1ZTtcbiAgICB9XG4gIH0gLy8gZm9yIGVhY2ggcGFpciAoc3JjLCB0Z3QpLCBjcmVhdGUgdGhlIGN0cmwgcHRzXG4gIC8vIE5lc3RlZCBmb3IgbG9vcCBpcyBPSzsgdG90YWwgbnVtYmVyIG9mIGl0ZXJhdGlvbnMgZm9yIGJvdGggbG9vcHMgPSBlZGdlQ291bnRcblxuXG4gIHZhciBfbG9vcCA9IGZ1bmN0aW9uIF9sb29wKHApIHtcbiAgICB2YXIgcGFpcklkID0gcGFpcklkc1twXTtcbiAgICB2YXIgcGFpckluZm8gPSBoYXNoVGFibGUuZ2V0KHBhaXJJZCk7XG4gICAgdmFyIHN3YXBwZWRwYWlySW5mbyA9IHZvaWQgMDtcblxuICAgIGlmICghcGFpckluZm8uaGFzVW5idW5kbGVkKSB7XG4gICAgICB2YXIgcGxsRWRnZXMgPSBwYWlySW5mby5lbGVzWzBdLnBhcmFsbGVsRWRnZXMoKS5maWx0ZXIoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgcmV0dXJuIGUuaXNCdW5kbGVkQmV6aWVyKCk7XG4gICAgICB9KTtcbiAgICAgIGNsZWFyQXJyYXkocGFpckluZm8uZWxlcyk7XG4gICAgICBwbGxFZGdlcy5mb3JFYWNoKGZ1bmN0aW9uIChlZGdlKSB7XG4gICAgICAgIHJldHVybiBwYWlySW5mby5lbGVzLnB1c2goZWRnZSk7XG4gICAgICB9KTsgLy8gZm9yIGVhY2ggcGFpciBpZCwgdGhlIGVkZ2VzIHNob3VsZCBiZSBzb3J0ZWQgYnkgaW5kZXhcblxuICAgICAgcGFpckluZm8uZWxlcy5zb3J0KGZ1bmN0aW9uIChlZGdlMSwgZWRnZTIpIHtcbiAgICAgICAgcmV0dXJuIGVkZ2UxLnBvb2xJbmRleCgpIC0gZWRnZTIucG9vbEluZGV4KCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgZmlyc3RFZGdlID0gcGFpckluZm8uZWxlc1swXTtcbiAgICB2YXIgc3JjID0gZmlyc3RFZGdlLnNvdXJjZSgpO1xuICAgIHZhciB0Z3QgPSBmaXJzdEVkZ2UudGFyZ2V0KCk7IC8vIG1ha2Ugc3VyZSBzcmMvdGd0IGRpc3RpbmN0aW9uIGlzIGNvbnNpc3RlbnQgdy5yLnQuIHBhaXJJZFxuXG4gICAgaWYgKHNyYy5wb29sSW5kZXgoKSA+IHRndC5wb29sSW5kZXgoKSkge1xuICAgICAgdmFyIHRlbXAgPSBzcmM7XG4gICAgICBzcmMgPSB0Z3Q7XG4gICAgICB0Z3QgPSB0ZW1wO1xuICAgIH1cblxuICAgIHZhciBzcmNQb3MgPSBwYWlySW5mby5zcmNQb3MgPSBzcmMucG9zaXRpb24oKTtcbiAgICB2YXIgdGd0UG9zID0gcGFpckluZm8udGd0UG9zID0gdGd0LnBvc2l0aW9uKCk7XG4gICAgdmFyIHNyY1cgPSBwYWlySW5mby5zcmNXID0gc3JjLm91dGVyV2lkdGgoKTtcbiAgICB2YXIgc3JjSCA9IHBhaXJJbmZvLnNyY0ggPSBzcmMub3V0ZXJIZWlnaHQoKTtcbiAgICB2YXIgdGd0VyA9IHBhaXJJbmZvLnRndFcgPSB0Z3Qub3V0ZXJXaWR0aCgpO1xuICAgIHZhciB0Z3RIID0gcGFpckluZm8udGd0SCA9IHRndC5vdXRlckhlaWdodCgpO1xuXG4gICAgdmFyIHNyY1NoYXBlID0gcGFpckluZm8uc3JjU2hhcGUgPSByLm5vZGVTaGFwZXNbX3RoaXMuZ2V0Tm9kZVNoYXBlKHNyYyldO1xuXG4gICAgdmFyIHRndFNoYXBlID0gcGFpckluZm8udGd0U2hhcGUgPSByLm5vZGVTaGFwZXNbX3RoaXMuZ2V0Tm9kZVNoYXBlKHRndCldO1xuXG4gICAgcGFpckluZm8uZGlyQ291bnRzID0ge1xuICAgICAgJ25vcnRoJzogMCxcbiAgICAgICd3ZXN0JzogMCxcbiAgICAgICdzb3V0aCc6IDAsXG4gICAgICAnZWFzdCc6IDAsXG4gICAgICAnbm9ydGh3ZXN0JzogMCxcbiAgICAgICdzb3V0aHdlc3QnOiAwLFxuICAgICAgJ25vcnRoZWFzdCc6IDAsXG4gICAgICAnc291dGhlYXN0JzogMFxuICAgIH07XG5cbiAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBwYWlySW5mby5lbGVzLmxlbmd0aDsgX2kyKyspIHtcbiAgICAgIHZhciBfZWRnZSA9IHBhaXJJbmZvLmVsZXNbX2kyXTtcbiAgICAgIHZhciBycyA9IF9lZGdlWzBdLl9wcml2YXRlLnJzY3JhdGNoO1xuXG4gICAgICB2YXIgX2N1cnZlU3R5bGUgPSBfZWRnZS5wc3R5bGUoJ2N1cnZlLXN0eWxlJykudmFsdWU7XG5cbiAgICAgIHZhciBfZWRnZUlzVW5idW5kbGVkID0gX2N1cnZlU3R5bGUgPT09ICd1bmJ1bmRsZWQtYmV6aWVyJyB8fCBfY3VydmVTdHlsZSA9PT0gJ3NlZ21lbnRzJyB8fCBfY3VydmVTdHlsZSA9PT0gJ3RheGknOyAvLyB3aGV0aGVyIHRoZSBub3JtYWxpc2VkIHBhaXIgb3JkZXIgaXMgdGhlIHJldmVyc2Ugb2YgdGhlIGVkZ2UncyBzcmMtdGd0IG9yZGVyXG5cblxuICAgICAgdmFyIGVkZ2VJc1N3YXBwZWQgPSAhc3JjLnNhbWUoX2VkZ2Uuc291cmNlKCkpO1xuXG4gICAgICBpZiAoIXBhaXJJbmZvLmNhbGN1bGF0ZWRJbnRlcnNlY3Rpb24gJiYgc3JjICE9PSB0Z3QgJiYgKHBhaXJJbmZvLmhhc0JlemllciB8fCBwYWlySW5mby5oYXNVbmJ1bmRsZWQpKSB7XG4gICAgICAgIHBhaXJJbmZvLmNhbGN1bGF0ZWRJbnRlcnNlY3Rpb24gPSB0cnVlOyAvLyBwdCBvdXRzaWRlIHNyYyBzaGFwZSB0byBjYWxjIGRpc3RhbmNlL2Rpc3BsYWNlbWVudCBmcm9tIHNyYyB0byB0Z3RcblxuICAgICAgICB2YXIgc3JjT3V0c2lkZSA9IHNyY1NoYXBlLmludGVyc2VjdExpbmUoc3JjUG9zLngsIHNyY1Bvcy55LCBzcmNXLCBzcmNILCB0Z3RQb3MueCwgdGd0UG9zLnksIDApO1xuICAgICAgICB2YXIgc3JjSW50biA9IHBhaXJJbmZvLnNyY0ludG4gPSBzcmNPdXRzaWRlOyAvLyBwdCBvdXRzaWRlIHRndCBzaGFwZSB0byBjYWxjIGRpc3RhbmNlL2Rpc3BsYWNlbWVudCBmcm9tIHNyYyB0byB0Z3RcblxuICAgICAgICB2YXIgdGd0T3V0c2lkZSA9IHRndFNoYXBlLmludGVyc2VjdExpbmUodGd0UG9zLngsIHRndFBvcy55LCB0Z3RXLCB0Z3RILCBzcmNQb3MueCwgc3JjUG9zLnksIDApO1xuICAgICAgICB2YXIgdGd0SW50biA9IHBhaXJJbmZvLnRndEludG4gPSB0Z3RPdXRzaWRlO1xuICAgICAgICB2YXIgaW50ZXJzZWN0aW9uUHRzID0gcGFpckluZm8uaW50ZXJzZWN0aW9uUHRzID0ge1xuICAgICAgICAgIHgxOiBzcmNPdXRzaWRlWzBdLFxuICAgICAgICAgIHgyOiB0Z3RPdXRzaWRlWzBdLFxuICAgICAgICAgIHkxOiBzcmNPdXRzaWRlWzFdLFxuICAgICAgICAgIHkyOiB0Z3RPdXRzaWRlWzFdXG4gICAgICAgIH07XG4gICAgICAgIHZhciBwb3NQdHMgPSBwYWlySW5mby5wb3NQdHMgPSB7XG4gICAgICAgICAgeDE6IHNyY1Bvcy54LFxuICAgICAgICAgIHgyOiB0Z3RQb3MueCxcbiAgICAgICAgICB5MTogc3JjUG9zLnksXG4gICAgICAgICAgeTI6IHRndFBvcy55XG4gICAgICAgIH07XG4gICAgICAgIHZhciBkeSA9IHRndE91dHNpZGVbMV0gLSBzcmNPdXRzaWRlWzFdO1xuICAgICAgICB2YXIgZHggPSB0Z3RPdXRzaWRlWzBdIC0gc3JjT3V0c2lkZVswXTtcbiAgICAgICAgdmFyIGwgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgICAgICB2YXIgdmVjdG9yID0gcGFpckluZm8udmVjdG9yID0ge1xuICAgICAgICAgIHg6IGR4LFxuICAgICAgICAgIHk6IGR5XG4gICAgICAgIH07XG4gICAgICAgIHZhciB2ZWN0b3JOb3JtID0gcGFpckluZm8udmVjdG9yTm9ybSA9IHtcbiAgICAgICAgICB4OiB2ZWN0b3IueCAvIGwsXG4gICAgICAgICAgeTogdmVjdG9yLnkgLyBsXG4gICAgICAgIH07XG4gICAgICAgIHZhciB2ZWN0b3JOb3JtSW52ZXJzZSA9IHtcbiAgICAgICAgICB4OiAtdmVjdG9yTm9ybS55LFxuICAgICAgICAgIHk6IHZlY3Rvck5vcm0ueFxuICAgICAgICB9OyAvLyBpZiBub2RlIHNoYXBlcyBvdmVybGFwLCB0aGVuIG5vIGN0cmwgcHRzIHRvIGRyYXdcblxuICAgICAgICBwYWlySW5mby5ub2Rlc092ZXJsYXAgPSAhbnVtYmVyKGwpIHx8IHRndFNoYXBlLmNoZWNrUG9pbnQoc3JjT3V0c2lkZVswXSwgc3JjT3V0c2lkZVsxXSwgMCwgdGd0VywgdGd0SCwgdGd0UG9zLngsIHRndFBvcy55KSB8fCBzcmNTaGFwZS5jaGVja1BvaW50KHRndE91dHNpZGVbMF0sIHRndE91dHNpZGVbMV0sIDAsIHNyY1csIHNyY0gsIHNyY1Bvcy54LCBzcmNQb3MueSk7XG4gICAgICAgIHBhaXJJbmZvLnZlY3Rvck5vcm1JbnZlcnNlID0gdmVjdG9yTm9ybUludmVyc2U7XG4gICAgICAgIHN3YXBwZWRwYWlySW5mbyA9IHtcbiAgICAgICAgICBub2Rlc092ZXJsYXA6IHBhaXJJbmZvLm5vZGVzT3ZlcmxhcCxcbiAgICAgICAgICBkaXJDb3VudHM6IHBhaXJJbmZvLmRpckNvdW50cyxcbiAgICAgICAgICBjYWxjdWxhdGVkSW50ZXJzZWN0aW9uOiB0cnVlLFxuICAgICAgICAgIGhhc0JlemllcjogcGFpckluZm8uaGFzQmV6aWVyLFxuICAgICAgICAgIGhhc1VuYnVuZGxlZDogcGFpckluZm8uaGFzVW5idW5kbGVkLFxuICAgICAgICAgIGVsZXM6IHBhaXJJbmZvLmVsZXMsXG4gICAgICAgICAgc3JjUG9zOiB0Z3RQb3MsXG4gICAgICAgICAgdGd0UG9zOiBzcmNQb3MsXG4gICAgICAgICAgc3JjVzogdGd0VyxcbiAgICAgICAgICBzcmNIOiB0Z3RILFxuICAgICAgICAgIHRndFc6IHNyY1csXG4gICAgICAgICAgdGd0SDogc3JjSCxcbiAgICAgICAgICBzcmNJbnRuOiB0Z3RJbnRuLFxuICAgICAgICAgIHRndEludG46IHNyY0ludG4sXG4gICAgICAgICAgc3JjU2hhcGU6IHRndFNoYXBlLFxuICAgICAgICAgIHRndFNoYXBlOiBzcmNTaGFwZSxcbiAgICAgICAgICBwb3NQdHM6IHtcbiAgICAgICAgICAgIHgxOiBwb3NQdHMueDIsXG4gICAgICAgICAgICB5MTogcG9zUHRzLnkyLFxuICAgICAgICAgICAgeDI6IHBvc1B0cy54MSxcbiAgICAgICAgICAgIHkyOiBwb3NQdHMueTFcbiAgICAgICAgICB9LFxuICAgICAgICAgIGludGVyc2VjdGlvblB0czoge1xuICAgICAgICAgICAgeDE6IGludGVyc2VjdGlvblB0cy54MixcbiAgICAgICAgICAgIHkxOiBpbnRlcnNlY3Rpb25QdHMueTIsXG4gICAgICAgICAgICB4MjogaW50ZXJzZWN0aW9uUHRzLngxLFxuICAgICAgICAgICAgeTI6IGludGVyc2VjdGlvblB0cy55MVxuICAgICAgICAgIH0sXG4gICAgICAgICAgdmVjdG9yOiB7XG4gICAgICAgICAgICB4OiAtdmVjdG9yLngsXG4gICAgICAgICAgICB5OiAtdmVjdG9yLnlcbiAgICAgICAgICB9LFxuICAgICAgICAgIHZlY3Rvck5vcm06IHtcbiAgICAgICAgICAgIHg6IC12ZWN0b3JOb3JtLngsXG4gICAgICAgICAgICB5OiAtdmVjdG9yTm9ybS55XG4gICAgICAgICAgfSxcbiAgICAgICAgICB2ZWN0b3JOb3JtSW52ZXJzZToge1xuICAgICAgICAgICAgeDogLXZlY3Rvck5vcm1JbnZlcnNlLngsXG4gICAgICAgICAgICB5OiAtdmVjdG9yTm9ybUludmVyc2UueVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgdmFyIHBhc3NlZFBhaXJJbmZvID0gZWRnZUlzU3dhcHBlZCA/IHN3YXBwZWRwYWlySW5mbyA6IHBhaXJJbmZvO1xuICAgICAgcnMubm9kZXNPdmVybGFwID0gcGFzc2VkUGFpckluZm8ubm9kZXNPdmVybGFwO1xuICAgICAgcnMuc3JjSW50biA9IHBhc3NlZFBhaXJJbmZvLnNyY0ludG47XG4gICAgICBycy50Z3RJbnRuID0gcGFzc2VkUGFpckluZm8udGd0SW50bjtcblxuICAgICAgaWYgKGhhc0NvbXBvdW5kcyAmJiAoc3JjLmlzUGFyZW50KCkgfHwgc3JjLmlzQ2hpbGQoKSB8fCB0Z3QuaXNQYXJlbnQoKSB8fCB0Z3QuaXNDaGlsZCgpKSAmJiAoc3JjLnBhcmVudHMoKS5hbnlTYW1lKHRndCkgfHwgdGd0LnBhcmVudHMoKS5hbnlTYW1lKHNyYykgfHwgc3JjLnNhbWUodGd0KSAmJiBzcmMuaXNQYXJlbnQoKSkpIHtcbiAgICAgICAgX3RoaXMuZmluZENvbXBvdW5kTG9vcFBvaW50cyhfZWRnZSwgcGFzc2VkUGFpckluZm8sIF9pMiwgX2VkZ2VJc1VuYnVuZGxlZCk7XG4gICAgICB9IGVsc2UgaWYgKHNyYyA9PT0gdGd0KSB7XG4gICAgICAgIF90aGlzLmZpbmRMb29wUG9pbnRzKF9lZGdlLCBwYXNzZWRQYWlySW5mbywgX2kyLCBfZWRnZUlzVW5idW5kbGVkKTtcbiAgICAgIH0gZWxzZSBpZiAoX2N1cnZlU3R5bGUgPT09ICdzZWdtZW50cycpIHtcbiAgICAgICAgX3RoaXMuZmluZFNlZ21lbnRzUG9pbnRzKF9lZGdlLCBwYXNzZWRQYWlySW5mbyk7XG4gICAgICB9IGVsc2UgaWYgKF9jdXJ2ZVN0eWxlID09PSAndGF4aScpIHtcbiAgICAgICAgX3RoaXMuZmluZFRheGlQb2ludHMoX2VkZ2UsIHBhc3NlZFBhaXJJbmZvKTtcbiAgICAgIH0gZWxzZSBpZiAoX2N1cnZlU3R5bGUgPT09ICdzdHJhaWdodCcgfHwgIV9lZGdlSXNVbmJ1bmRsZWQgJiYgcGFpckluZm8uZWxlcy5sZW5ndGggJSAyID09PSAxICYmIF9pMiA9PT0gTWF0aC5mbG9vcihwYWlySW5mby5lbGVzLmxlbmd0aCAvIDIpKSB7XG4gICAgICAgIF90aGlzLmZpbmRTdHJhaWdodEVkZ2VQb2ludHMoX2VkZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgX3RoaXMuZmluZEJlemllclBvaW50cyhfZWRnZSwgcGFzc2VkUGFpckluZm8sIF9pMiwgX2VkZ2VJc1VuYnVuZGxlZCwgZWRnZUlzU3dhcHBlZCk7XG4gICAgICB9XG5cbiAgICAgIF90aGlzLmZpbmRFbmRwb2ludHMoX2VkZ2UpO1xuXG4gICAgICBfdGhpcy50cnlUb0NvcnJlY3RJbnZhbGlkUG9pbnRzKF9lZGdlLCBwYXNzZWRQYWlySW5mbyk7XG5cbiAgICAgIF90aGlzLmNoZWNrRm9ySW52YWxpZEVkZ2VXYXJuaW5nKF9lZGdlKTtcblxuICAgICAgX3RoaXMuc3RvcmVBbGxwdHMoX2VkZ2UpO1xuXG4gICAgICBfdGhpcy5zdG9yZUVkZ2VQcm9qZWN0aW9ucyhfZWRnZSk7XG5cbiAgICAgIF90aGlzLmNhbGN1bGF0ZUFycm93QW5nbGVzKF9lZGdlKTtcblxuICAgICAgX3RoaXMucmVjYWxjdWxhdGVFZGdlTGFiZWxQcm9qZWN0aW9ucyhfZWRnZSk7XG5cbiAgICAgIF90aGlzLmNhbGN1bGF0ZUxhYmVsQW5nbGVzKF9lZGdlKTtcbiAgICB9IC8vIGZvciBwYWlyIGVkZ2VzXG5cbiAgfTtcblxuICBmb3IgKHZhciBwID0gMDsgcCA8IHBhaXJJZHMubGVuZ3RoOyBwKyspIHtcbiAgICBfbG9vcChwKTtcbiAgfSAvLyBmb3IgcGFpciBpZHNcbiAgLy8gaGF5c3RhY2tzIGF2b2lkIHRoZSBleHBlbnNlIG9mIHBhaXJJbmZvIHN0dWZmIChpbnRlcnNlY3Rpb25zIGV0Yy4pXG5cblxuICB0aGlzLmZpbmRIYXlzdGFja1BvaW50cyhoYXlzdGFja0VkZ2VzKTtcbn07XG5cbmZ1bmN0aW9uIGdldFB0cyhwdHMpIHtcbiAgdmFyIHJldFB0cyA9IFtdO1xuXG4gIGlmIChwdHMgPT0gbnVsbCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcHRzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgdmFyIHggPSBwdHNbaV07XG4gICAgdmFyIHkgPSBwdHNbaSArIDFdO1xuICAgIHJldFB0cy5wdXNoKHtcbiAgICAgIHg6IHgsXG4gICAgICB5OiB5XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcmV0UHRzO1xufVxuXG5CUnAkMy5nZXRTZWdtZW50UG9pbnRzID0gZnVuY3Rpb24gKGVkZ2UpIHtcbiAgdmFyIHJzID0gZWRnZVswXS5fcHJpdmF0ZS5yc2NyYXRjaDtcbiAgdmFyIHR5cGUgPSBycy5lZGdlVHlwZTtcblxuICBpZiAodHlwZSA9PT0gJ3NlZ21lbnRzJykge1xuICAgIHRoaXMucmVjYWxjdWxhdGVSZW5kZXJlZFN0eWxlKGVkZ2UpO1xuICAgIHJldHVybiBnZXRQdHMocnMuc2VncHRzKTtcbiAgfVxufTtcblxuQlJwJDMuZ2V0Q29udHJvbFBvaW50cyA9IGZ1bmN0aW9uIChlZGdlKSB7XG4gIHZhciBycyA9IGVkZ2VbMF0uX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHZhciB0eXBlID0gcnMuZWRnZVR5cGU7XG5cbiAgaWYgKHR5cGUgPT09ICdiZXppZXInIHx8IHR5cGUgPT09ICdtdWx0aWJlemllcicgfHwgdHlwZSA9PT0gJ3NlbGYnIHx8IHR5cGUgPT09ICdjb21wb3VuZCcpIHtcbiAgICB0aGlzLnJlY2FsY3VsYXRlUmVuZGVyZWRTdHlsZShlZGdlKTtcbiAgICByZXR1cm4gZ2V0UHRzKHJzLmN0cmxwdHMpO1xuICB9XG59O1xuXG5CUnAkMy5nZXRFZGdlTWlkcG9pbnQgPSBmdW5jdGlvbiAoZWRnZSkge1xuICB2YXIgcnMgPSBlZGdlWzBdLl9wcml2YXRlLnJzY3JhdGNoO1xuICB0aGlzLnJlY2FsY3VsYXRlUmVuZGVyZWRTdHlsZShlZGdlKTtcbiAgcmV0dXJuIHtcbiAgICB4OiBycy5taWRYLFxuICAgIHk6IHJzLm1pZFlcbiAgfTtcbn07XG5cbnZhciBCUnAkNCA9IHt9O1xuXG5CUnAkNC5tYW51YWxFbmRwdFRvUHggPSBmdW5jdGlvbiAobm9kZSwgcHJvcCkge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBucG9zID0gbm9kZS5wb3NpdGlvbigpO1xuICB2YXIgdyA9IG5vZGUub3V0ZXJXaWR0aCgpO1xuICB2YXIgaCA9IG5vZGUub3V0ZXJIZWlnaHQoKTtcblxuICBpZiAocHJvcC52YWx1ZS5sZW5ndGggPT09IDIpIHtcbiAgICB2YXIgcCA9IFtwcm9wLnBmVmFsdWVbMF0sIHByb3AucGZWYWx1ZVsxXV07XG5cbiAgICBpZiAocHJvcC51bml0c1swXSA9PT0gJyUnKSB7XG4gICAgICBwWzBdID0gcFswXSAqIHc7XG4gICAgfVxuXG4gICAgaWYgKHByb3AudW5pdHNbMV0gPT09ICclJykge1xuICAgICAgcFsxXSA9IHBbMV0gKiBoO1xuICAgIH1cblxuICAgIHBbMF0gKz0gbnBvcy54O1xuICAgIHBbMV0gKz0gbnBvcy55O1xuICAgIHJldHVybiBwO1xuICB9IGVsc2Uge1xuICAgIHZhciBhbmdsZSA9IHByb3AucGZWYWx1ZVswXTtcbiAgICBhbmdsZSA9IC1NYXRoLlBJIC8gMiArIGFuZ2xlOyAvLyBzdGFydCBhdCAxMiBvJ2Nsb2NrXG5cbiAgICB2YXIgbCA9IDIgKiBNYXRoLm1heCh3LCBoKTtcbiAgICB2YXIgX3AgPSBbbnBvcy54ICsgTWF0aC5jb3MoYW5nbGUpICogbCwgbnBvcy55ICsgTWF0aC5zaW4oYW5nbGUpICogbF07XG4gICAgcmV0dXJuIHIubm9kZVNoYXBlc1t0aGlzLmdldE5vZGVTaGFwZShub2RlKV0uaW50ZXJzZWN0TGluZShucG9zLngsIG5wb3MueSwgdywgaCwgX3BbMF0sIF9wWzFdLCAwKTtcbiAgfVxufTtcblxuQlJwJDQuZmluZEVuZHBvaW50cyA9IGZ1bmN0aW9uIChlZGdlKSB7XG4gIHZhciByID0gdGhpcztcbiAgdmFyIGludGVyc2VjdDtcbiAgdmFyIHNvdXJjZSA9IGVkZ2Uuc291cmNlKClbMF07XG4gIHZhciB0YXJnZXQgPSBlZGdlLnRhcmdldCgpWzBdO1xuICB2YXIgc3JjUG9zID0gc291cmNlLnBvc2l0aW9uKCk7XG4gIHZhciB0Z3RQb3MgPSB0YXJnZXQucG9zaXRpb24oKTtcbiAgdmFyIHRndEFyU2hhcGUgPSBlZGdlLnBzdHlsZSgndGFyZ2V0LWFycm93LXNoYXBlJykudmFsdWU7XG4gIHZhciBzcmNBclNoYXBlID0gZWRnZS5wc3R5bGUoJ3NvdXJjZS1hcnJvdy1zaGFwZScpLnZhbHVlO1xuICB2YXIgdGd0RGlzdCA9IGVkZ2UucHN0eWxlKCd0YXJnZXQtZGlzdGFuY2UtZnJvbS1ub2RlJykucGZWYWx1ZTtcbiAgdmFyIHNyY0Rpc3QgPSBlZGdlLnBzdHlsZSgnc291cmNlLWRpc3RhbmNlLWZyb20tbm9kZScpLnBmVmFsdWU7XG4gIHZhciBjdXJ2ZVN0eWxlID0gZWRnZS5wc3R5bGUoJ2N1cnZlLXN0eWxlJykudmFsdWU7XG4gIHZhciBycyA9IGVkZ2UuX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHZhciBldCA9IHJzLmVkZ2VUeXBlO1xuICB2YXIgdGF4aSA9IGN1cnZlU3R5bGUgPT09ICd0YXhpJztcbiAgdmFyIHNlbGYgPSBldCA9PT0gJ3NlbGYnIHx8IGV0ID09PSAnY29tcG91bmQnO1xuICB2YXIgYmV6aWVyID0gZXQgPT09ICdiZXppZXInIHx8IGV0ID09PSAnbXVsdGliZXppZXInIHx8IHNlbGY7XG4gIHZhciBtdWx0aSA9IGV0ICE9PSAnYmV6aWVyJztcbiAgdmFyIGxpbmVzID0gZXQgPT09ICdzdHJhaWdodCcgfHwgZXQgPT09ICdzZWdtZW50cyc7XG4gIHZhciBzZWdtZW50cyA9IGV0ID09PSAnc2VnbWVudHMnO1xuICB2YXIgaGFzRW5kcHRzID0gYmV6aWVyIHx8IG11bHRpIHx8IGxpbmVzO1xuICB2YXIgb3ZlcnJpZGVFbmRwdHMgPSBzZWxmIHx8IHRheGk7XG4gIHZhciBzcmNNYW5FbmRwdCA9IGVkZ2UucHN0eWxlKCdzb3VyY2UtZW5kcG9pbnQnKTtcbiAgdmFyIHNyY01hbkVuZHB0VmFsID0gb3ZlcnJpZGVFbmRwdHMgPyAnb3V0c2lkZS10by1ub2RlJyA6IHNyY01hbkVuZHB0LnZhbHVlO1xuICB2YXIgdGd0TWFuRW5kcHQgPSBlZGdlLnBzdHlsZSgndGFyZ2V0LWVuZHBvaW50Jyk7XG4gIHZhciB0Z3RNYW5FbmRwdFZhbCA9IG92ZXJyaWRlRW5kcHRzID8gJ291dHNpZGUtdG8tbm9kZScgOiB0Z3RNYW5FbmRwdC52YWx1ZTtcbiAgcnMuc3JjTWFuRW5kcHQgPSBzcmNNYW5FbmRwdDtcbiAgcnMudGd0TWFuRW5kcHQgPSB0Z3RNYW5FbmRwdDtcbiAgdmFyIHAxOyAvLyBsYXN0IGtub3duIHBvaW50IG9mIGVkZ2Ugb24gdGFyZ2V0IHNpZGVcblxuICB2YXIgcDI7IC8vIGxhc3Qga25vd24gcG9pbnQgb2YgZWRnZSBvbiBzb3VyY2Ugc2lkZVxuXG4gIHZhciBwMV9pOyAvLyBwb2ludCB0byBpbnRlcnNlY3Qgd2l0aCB0YXJnZXQgc2hhcGVcblxuICB2YXIgcDJfaTsgLy8gcG9pbnQgdG8gaW50ZXJzZWN0IHdpdGggc291cmNlIHNoYXBlXG5cbiAgaWYgKGJlemllcikge1xuICAgIHZhciBjcFN0YXJ0ID0gW3JzLmN0cmxwdHNbMF0sIHJzLmN0cmxwdHNbMV1dO1xuICAgIHZhciBjcEVuZCA9IG11bHRpID8gW3JzLmN0cmxwdHNbcnMuY3RybHB0cy5sZW5ndGggLSAyXSwgcnMuY3RybHB0c1tycy5jdHJscHRzLmxlbmd0aCAtIDFdXSA6IGNwU3RhcnQ7XG4gICAgcDEgPSBjcEVuZDtcbiAgICBwMiA9IGNwU3RhcnQ7XG4gIH0gZWxzZSBpZiAobGluZXMpIHtcbiAgICB2YXIgc3JjQXJyb3dGcm9tUHQgPSAhc2VnbWVudHMgPyBbdGd0UG9zLngsIHRndFBvcy55XSA6IHJzLnNlZ3B0cy5zbGljZSgwLCAyKTtcbiAgICB2YXIgdGd0QXJyb3dGcm9tUHQgPSAhc2VnbWVudHMgPyBbc3JjUG9zLngsIHNyY1Bvcy55XSA6IHJzLnNlZ3B0cy5zbGljZShycy5zZWdwdHMubGVuZ3RoIC0gMik7XG4gICAgcDEgPSB0Z3RBcnJvd0Zyb21QdDtcbiAgICBwMiA9IHNyY0Fycm93RnJvbVB0O1xuICB9XG5cbiAgaWYgKHRndE1hbkVuZHB0VmFsID09PSAnaW5zaWRlLXRvLW5vZGUnKSB7XG4gICAgaW50ZXJzZWN0ID0gW3RndFBvcy54LCB0Z3RQb3MueV07XG4gIH0gZWxzZSBpZiAodGd0TWFuRW5kcHQudW5pdHMpIHtcbiAgICBpbnRlcnNlY3QgPSB0aGlzLm1hbnVhbEVuZHB0VG9QeCh0YXJnZXQsIHRndE1hbkVuZHB0KTtcbiAgfSBlbHNlIGlmICh0Z3RNYW5FbmRwdFZhbCA9PT0gJ291dHNpZGUtdG8tbGluZScpIHtcbiAgICBpbnRlcnNlY3QgPSBycy50Z3RJbnRuOyAvLyB1c2UgY2FjaGVkIHZhbHVlIGZyb20gY3RybHB0IGNhbGNcbiAgfSBlbHNlIHtcbiAgICBpZiAodGd0TWFuRW5kcHRWYWwgPT09ICdvdXRzaWRlLXRvLW5vZGUnIHx8IHRndE1hbkVuZHB0VmFsID09PSAnb3V0c2lkZS10by1ub2RlLW9yLWxhYmVsJykge1xuICAgICAgcDFfaSA9IHAxO1xuICAgIH0gZWxzZSBpZiAodGd0TWFuRW5kcHRWYWwgPT09ICdvdXRzaWRlLXRvLWxpbmUnIHx8IHRndE1hbkVuZHB0VmFsID09PSAnb3V0c2lkZS10by1saW5lLW9yLWxhYmVsJykge1xuICAgICAgcDFfaSA9IFtzcmNQb3MueCwgc3JjUG9zLnldO1xuICAgIH1cblxuICAgIGludGVyc2VjdCA9IHIubm9kZVNoYXBlc1t0aGlzLmdldE5vZGVTaGFwZSh0YXJnZXQpXS5pbnRlcnNlY3RMaW5lKHRndFBvcy54LCB0Z3RQb3MueSwgdGFyZ2V0Lm91dGVyV2lkdGgoKSwgdGFyZ2V0Lm91dGVySGVpZ2h0KCksIHAxX2lbMF0sIHAxX2lbMV0sIDApO1xuXG4gICAgaWYgKHRndE1hbkVuZHB0VmFsID09PSAnb3V0c2lkZS10by1ub2RlLW9yLWxhYmVsJyB8fCB0Z3RNYW5FbmRwdFZhbCA9PT0gJ291dHNpZGUtdG8tbGluZS1vci1sYWJlbCcpIHtcbiAgICAgIHZhciB0cnMgPSB0YXJnZXQuX3ByaXZhdGUucnNjcmF0Y2g7XG4gICAgICB2YXIgbHcgPSB0cnMubGFiZWxXaWR0aDtcbiAgICAgIHZhciBsaCA9IHRycy5sYWJlbEhlaWdodDtcbiAgICAgIHZhciBseCA9IHRycy5sYWJlbFg7XG4gICAgICB2YXIgbHkgPSB0cnMubGFiZWxZO1xuICAgICAgdmFyIGx3MiA9IGx3IC8gMjtcbiAgICAgIHZhciBsaDIgPSBsaCAvIDI7XG4gICAgICB2YXIgdmEgPSB0YXJnZXQucHN0eWxlKCd0ZXh0LXZhbGlnbicpLnZhbHVlO1xuXG4gICAgICBpZiAodmEgPT09ICd0b3AnKSB7XG4gICAgICAgIGx5IC09IGxoMjtcbiAgICAgIH0gZWxzZSBpZiAodmEgPT09ICdib3R0b20nKSB7XG4gICAgICAgIGx5ICs9IGxoMjtcbiAgICAgIH1cblxuICAgICAgdmFyIGhhID0gdGFyZ2V0LnBzdHlsZSgndGV4dC1oYWxpZ24nKS52YWx1ZTtcblxuICAgICAgaWYgKGhhID09PSAnbGVmdCcpIHtcbiAgICAgICAgbHggLT0gbHcyO1xuICAgICAgfSBlbHNlIGlmIChoYSA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICBseCArPSBsdzI7XG4gICAgICB9XG5cbiAgICAgIHZhciBsYWJlbEludGVyc2VjdCA9IHBvbHlnb25JbnRlcnNlY3RMaW5lKHAxX2lbMF0sIHAxX2lbMV0sIFtseCAtIGx3MiwgbHkgLSBsaDIsIGx4ICsgbHcyLCBseSAtIGxoMiwgbHggKyBsdzIsIGx5ICsgbGgyLCBseCAtIGx3MiwgbHkgKyBsaDJdLCB0Z3RQb3MueCwgdGd0UG9zLnkpO1xuXG4gICAgICBpZiAobGFiZWxJbnRlcnNlY3QubGVuZ3RoID4gMCkge1xuICAgICAgICB2YXIgcmVmUHQgPSBzcmNQb3M7XG4gICAgICAgIHZhciBpbnRTcWRpc3QgPSBzcWRpc3QocmVmUHQsIGFycmF5MnBvaW50KGludGVyc2VjdCkpO1xuICAgICAgICB2YXIgbGFiSW50U3FkaXN0ID0gc3FkaXN0KHJlZlB0LCBhcnJheTJwb2ludChsYWJlbEludGVyc2VjdCkpO1xuICAgICAgICB2YXIgbWluU3FEaXN0ID0gaW50U3FkaXN0O1xuXG4gICAgICAgIGlmIChsYWJJbnRTcWRpc3QgPCBpbnRTcWRpc3QpIHtcbiAgICAgICAgICBpbnRlcnNlY3QgPSBsYWJlbEludGVyc2VjdDtcbiAgICAgICAgICBtaW5TcURpc3QgPSBsYWJJbnRTcWRpc3Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGFiZWxJbnRlcnNlY3QubGVuZ3RoID4gMikge1xuICAgICAgICAgIHZhciBsYWJJbnQyU3FEaXN0ID0gc3FkaXN0KHJlZlB0LCB7XG4gICAgICAgICAgICB4OiBsYWJlbEludGVyc2VjdFsyXSxcbiAgICAgICAgICAgIHk6IGxhYmVsSW50ZXJzZWN0WzNdXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAobGFiSW50MlNxRGlzdCA8IG1pblNxRGlzdCkge1xuICAgICAgICAgICAgaW50ZXJzZWN0ID0gW2xhYmVsSW50ZXJzZWN0WzJdLCBsYWJlbEludGVyc2VjdFszXV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIGFycm93RW5kID0gc2hvcnRlbkludGVyc2VjdGlvbihpbnRlcnNlY3QsIHAxLCByLmFycm93U2hhcGVzW3RndEFyU2hhcGVdLnNwYWNpbmcoZWRnZSkgKyB0Z3REaXN0KTtcbiAgdmFyIGVkZ2VFbmQgPSBzaG9ydGVuSW50ZXJzZWN0aW9uKGludGVyc2VjdCwgcDEsIHIuYXJyb3dTaGFwZXNbdGd0QXJTaGFwZV0uZ2FwKGVkZ2UpICsgdGd0RGlzdCk7XG4gIHJzLmVuZFggPSBlZGdlRW5kWzBdO1xuICBycy5lbmRZID0gZWRnZUVuZFsxXTtcbiAgcnMuYXJyb3dFbmRYID0gYXJyb3dFbmRbMF07XG4gIHJzLmFycm93RW5kWSA9IGFycm93RW5kWzFdO1xuXG4gIGlmIChzcmNNYW5FbmRwdFZhbCA9PT0gJ2luc2lkZS10by1ub2RlJykge1xuICAgIGludGVyc2VjdCA9IFtzcmNQb3MueCwgc3JjUG9zLnldO1xuICB9IGVsc2UgaWYgKHNyY01hbkVuZHB0LnVuaXRzKSB7XG4gICAgaW50ZXJzZWN0ID0gdGhpcy5tYW51YWxFbmRwdFRvUHgoc291cmNlLCBzcmNNYW5FbmRwdCk7XG4gIH0gZWxzZSBpZiAoc3JjTWFuRW5kcHRWYWwgPT09ICdvdXRzaWRlLXRvLWxpbmUnKSB7XG4gICAgaW50ZXJzZWN0ID0gcnMuc3JjSW50bjsgLy8gdXNlIGNhY2hlZCB2YWx1ZSBmcm9tIGN0cmxwdCBjYWxjXG4gIH0gZWxzZSB7XG4gICAgaWYgKHNyY01hbkVuZHB0VmFsID09PSAnb3V0c2lkZS10by1ub2RlJyB8fCBzcmNNYW5FbmRwdFZhbCA9PT0gJ291dHNpZGUtdG8tbm9kZS1vci1sYWJlbCcpIHtcbiAgICAgIHAyX2kgPSBwMjtcbiAgICB9IGVsc2UgaWYgKHNyY01hbkVuZHB0VmFsID09PSAnb3V0c2lkZS10by1saW5lJyB8fCBzcmNNYW5FbmRwdFZhbCA9PT0gJ291dHNpZGUtdG8tbGluZS1vci1sYWJlbCcpIHtcbiAgICAgIHAyX2kgPSBbdGd0UG9zLngsIHRndFBvcy55XTtcbiAgICB9XG5cbiAgICBpbnRlcnNlY3QgPSByLm5vZGVTaGFwZXNbdGhpcy5nZXROb2RlU2hhcGUoc291cmNlKV0uaW50ZXJzZWN0TGluZShzcmNQb3MueCwgc3JjUG9zLnksIHNvdXJjZS5vdXRlcldpZHRoKCksIHNvdXJjZS5vdXRlckhlaWdodCgpLCBwMl9pWzBdLCBwMl9pWzFdLCAwKTtcblxuICAgIGlmIChzcmNNYW5FbmRwdFZhbCA9PT0gJ291dHNpZGUtdG8tbm9kZS1vci1sYWJlbCcgfHwgc3JjTWFuRW5kcHRWYWwgPT09ICdvdXRzaWRlLXRvLWxpbmUtb3ItbGFiZWwnKSB7XG4gICAgICB2YXIgc3JzID0gc291cmNlLl9wcml2YXRlLnJzY3JhdGNoO1xuICAgICAgdmFyIF9sdyA9IHNycy5sYWJlbFdpZHRoO1xuICAgICAgdmFyIF9saCA9IHNycy5sYWJlbEhlaWdodDtcbiAgICAgIHZhciBfbHggPSBzcnMubGFiZWxYO1xuICAgICAgdmFyIF9seSA9IHNycy5sYWJlbFk7XG5cbiAgICAgIHZhciBfbHcyID0gX2x3IC8gMjtcblxuICAgICAgdmFyIF9saDIgPSBfbGggLyAyO1xuXG4gICAgICB2YXIgX3ZhID0gc291cmNlLnBzdHlsZSgndGV4dC12YWxpZ24nKS52YWx1ZTtcblxuICAgICAgaWYgKF92YSA9PT0gJ3RvcCcpIHtcbiAgICAgICAgX2x5IC09IF9saDI7XG4gICAgICB9IGVsc2UgaWYgKF92YSA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgX2x5ICs9IF9saDI7XG4gICAgICB9XG5cbiAgICAgIHZhciBfaGEgPSBzb3VyY2UucHN0eWxlKCd0ZXh0LWhhbGlnbicpLnZhbHVlO1xuXG4gICAgICBpZiAoX2hhID09PSAnbGVmdCcpIHtcbiAgICAgICAgX2x4IC09IF9sdzI7XG4gICAgICB9IGVsc2UgaWYgKF9oYSA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICBfbHggKz0gX2x3MjtcbiAgICAgIH1cblxuICAgICAgdmFyIF9sYWJlbEludGVyc2VjdCA9IHBvbHlnb25JbnRlcnNlY3RMaW5lKHAyX2lbMF0sIHAyX2lbMV0sIFtfbHggLSBfbHcyLCBfbHkgLSBfbGgyLCBfbHggKyBfbHcyLCBfbHkgLSBfbGgyLCBfbHggKyBfbHcyLCBfbHkgKyBfbGgyLCBfbHggLSBfbHcyLCBfbHkgKyBfbGgyXSwgc3JjUG9zLngsIHNyY1Bvcy55KTtcblxuICAgICAgaWYgKF9sYWJlbEludGVyc2VjdC5sZW5ndGggPiAwKSB7XG4gICAgICAgIHZhciBfcmVmUHQgPSB0Z3RQb3M7XG5cbiAgICAgICAgdmFyIF9pbnRTcWRpc3QgPSBzcWRpc3QoX3JlZlB0LCBhcnJheTJwb2ludChpbnRlcnNlY3QpKTtcblxuICAgICAgICB2YXIgX2xhYkludFNxZGlzdCA9IHNxZGlzdChfcmVmUHQsIGFycmF5MnBvaW50KF9sYWJlbEludGVyc2VjdCkpO1xuXG4gICAgICAgIHZhciBfbWluU3FEaXN0ID0gX2ludFNxZGlzdDtcblxuICAgICAgICBpZiAoX2xhYkludFNxZGlzdCA8IF9pbnRTcWRpc3QpIHtcbiAgICAgICAgICBpbnRlcnNlY3QgPSBbX2xhYmVsSW50ZXJzZWN0WzBdLCBfbGFiZWxJbnRlcnNlY3RbMV1dO1xuICAgICAgICAgIF9taW5TcURpc3QgPSBfbGFiSW50U3FkaXN0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKF9sYWJlbEludGVyc2VjdC5sZW5ndGggPiAyKSB7XG4gICAgICAgICAgdmFyIF9sYWJJbnQyU3FEaXN0ID0gc3FkaXN0KF9yZWZQdCwge1xuICAgICAgICAgICAgeDogX2xhYmVsSW50ZXJzZWN0WzJdLFxuICAgICAgICAgICAgeTogX2xhYmVsSW50ZXJzZWN0WzNdXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAoX2xhYkludDJTcURpc3QgPCBfbWluU3FEaXN0KSB7XG4gICAgICAgICAgICBpbnRlcnNlY3QgPSBbX2xhYmVsSW50ZXJzZWN0WzJdLCBfbGFiZWxJbnRlcnNlY3RbM11dO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZhciBhcnJvd1N0YXJ0ID0gc2hvcnRlbkludGVyc2VjdGlvbihpbnRlcnNlY3QsIHAyLCByLmFycm93U2hhcGVzW3NyY0FyU2hhcGVdLnNwYWNpbmcoZWRnZSkgKyBzcmNEaXN0KTtcbiAgdmFyIGVkZ2VTdGFydCA9IHNob3J0ZW5JbnRlcnNlY3Rpb24oaW50ZXJzZWN0LCBwMiwgci5hcnJvd1NoYXBlc1tzcmNBclNoYXBlXS5nYXAoZWRnZSkgKyBzcmNEaXN0KTtcbiAgcnMuc3RhcnRYID0gZWRnZVN0YXJ0WzBdO1xuICBycy5zdGFydFkgPSBlZGdlU3RhcnRbMV07XG4gIHJzLmFycm93U3RhcnRYID0gYXJyb3dTdGFydFswXTtcbiAgcnMuYXJyb3dTdGFydFkgPSBhcnJvd1N0YXJ0WzFdO1xuXG4gIGlmIChoYXNFbmRwdHMpIHtcbiAgICBpZiAoIW51bWJlcihycy5zdGFydFgpIHx8ICFudW1iZXIocnMuc3RhcnRZKSB8fCAhbnVtYmVyKHJzLmVuZFgpIHx8ICFudW1iZXIocnMuZW5kWSkpIHtcbiAgICAgIHJzLmJhZExpbmUgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBycy5iYWRMaW5lID0gZmFsc2U7XG4gICAgfVxuICB9XG59O1xuXG5CUnAkNC5nZXRTb3VyY2VFbmRwb2ludCA9IGZ1bmN0aW9uIChlZGdlKSB7XG4gIHZhciBycyA9IGVkZ2VbMF0uX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHRoaXMucmVjYWxjdWxhdGVSZW5kZXJlZFN0eWxlKGVkZ2UpO1xuXG4gIHN3aXRjaCAocnMuZWRnZVR5cGUpIHtcbiAgICBjYXNlICdoYXlzdGFjayc6XG4gICAgICByZXR1cm4ge1xuICAgICAgICB4OiBycy5oYXlzdGFja1B0c1swXSxcbiAgICAgICAgeTogcnMuaGF5c3RhY2tQdHNbMV1cbiAgICAgIH07XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgeDogcnMuYXJyb3dTdGFydFgsXG4gICAgICAgIHk6IHJzLmFycm93U3RhcnRZXG4gICAgICB9O1xuICB9XG59O1xuXG5CUnAkNC5nZXRUYXJnZXRFbmRwb2ludCA9IGZ1bmN0aW9uIChlZGdlKSB7XG4gIHZhciBycyA9IGVkZ2VbMF0uX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHRoaXMucmVjYWxjdWxhdGVSZW5kZXJlZFN0eWxlKGVkZ2UpO1xuXG4gIHN3aXRjaCAocnMuZWRnZVR5cGUpIHtcbiAgICBjYXNlICdoYXlzdGFjayc6XG4gICAgICByZXR1cm4ge1xuICAgICAgICB4OiBycy5oYXlzdGFja1B0c1syXSxcbiAgICAgICAgeTogcnMuaGF5c3RhY2tQdHNbM11cbiAgICAgIH07XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgeDogcnMuYXJyb3dFbmRYLFxuICAgICAgICB5OiBycy5hcnJvd0VuZFlcbiAgICAgIH07XG4gIH1cbn07XG5cbnZhciBCUnAkNSA9IHt9O1xuXG5mdW5jdGlvbiBwdXNoQmV6aWVyUHRzKHIsIGVkZ2UsIHB0cykge1xuICB2YXIgcWJlemllckF0JDEgPSBmdW5jdGlvbiBxYmV6aWVyQXQkMShwMSwgcDIsIHAzLCB0KSB7XG4gICAgcmV0dXJuIHFiZXppZXJBdChwMSwgcDIsIHAzLCB0KTtcbiAgfTtcblxuICB2YXIgX3AgPSBlZGdlLl9wcml2YXRlO1xuICB2YXIgYnB0cyA9IF9wLnJzdHlsZS5iZXppZXJQdHM7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByLmJlemllclByb2pQY3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHAgPSByLmJlemllclByb2pQY3RzW2ldO1xuICAgIGJwdHMucHVzaCh7XG4gICAgICB4OiBxYmV6aWVyQXQkMShwdHNbMF0sIHB0c1syXSwgcHRzWzRdLCBwKSxcbiAgICAgIHk6IHFiZXppZXJBdCQxKHB0c1sxXSwgcHRzWzNdLCBwdHNbNV0sIHApXG4gICAgfSk7XG4gIH1cbn1cblxuQlJwJDUuc3RvcmVFZGdlUHJvamVjdGlvbnMgPSBmdW5jdGlvbiAoZWRnZSkge1xuICB2YXIgX3AgPSBlZGdlLl9wcml2YXRlO1xuICB2YXIgcnMgPSBfcC5yc2NyYXRjaDtcbiAgdmFyIGV0ID0gcnMuZWRnZVR5cGU7IC8vIGNsZWFyIHRoZSBjYWNoZWQgcG9pbnRzIHN0YXRlXG5cbiAgX3AucnN0eWxlLmJlemllclB0cyA9IG51bGw7XG4gIF9wLnJzdHlsZS5saW5lUHRzID0gbnVsbDtcbiAgX3AucnN0eWxlLmhheXN0YWNrUHRzID0gbnVsbDtcblxuICBpZiAoZXQgPT09ICdtdWx0aWJlemllcicgfHwgZXQgPT09ICdiZXppZXInIHx8IGV0ID09PSAnc2VsZicgfHwgZXQgPT09ICdjb21wb3VuZCcpIHtcbiAgICBfcC5yc3R5bGUuYmV6aWVyUHRzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSArIDUgPCBycy5hbGxwdHMubGVuZ3RoOyBpICs9IDQpIHtcbiAgICAgIHB1c2hCZXppZXJQdHModGhpcywgZWRnZSwgcnMuYWxscHRzLnNsaWNlKGksIGkgKyA2KSk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGV0ID09PSAnc2VnbWVudHMnKSB7XG4gICAgdmFyIGxwdHMgPSBfcC5yc3R5bGUubGluZVB0cyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgKyAxIDwgcnMuYWxscHRzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICBscHRzLnB1c2goe1xuICAgICAgICB4OiBycy5hbGxwdHNbaV0sXG4gICAgICAgIHk6IHJzLmFsbHB0c1tpICsgMV1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSBlbHNlIGlmIChldCA9PT0gJ2hheXN0YWNrJykge1xuICAgIHZhciBocHRzID0gcnMuaGF5c3RhY2tQdHM7XG4gICAgX3AucnN0eWxlLmhheXN0YWNrUHRzID0gW3tcbiAgICAgIHg6IGhwdHNbMF0sXG4gICAgICB5OiBocHRzWzFdXG4gICAgfSwge1xuICAgICAgeDogaHB0c1syXSxcbiAgICAgIHk6IGhwdHNbM11cbiAgICB9XTtcbiAgfVxuXG4gIF9wLnJzdHlsZS5hcnJvd1dpZHRoID0gdGhpcy5nZXRBcnJvd1dpZHRoKGVkZ2UucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWUsIGVkZ2UucHN0eWxlKCdhcnJvdy1zY2FsZScpLnZhbHVlKSAqIHRoaXMuYXJyb3dTaGFwZVdpZHRoO1xufTtcblxuQlJwJDUucmVjYWxjdWxhdGVFZGdlUHJvamVjdGlvbnMgPSBmdW5jdGlvbiAoZWRnZXMpIHtcbiAgdGhpcy5maW5kRWRnZUNvbnRyb2xQb2ludHMoZWRnZXMpO1xufTtcblxudmFyIEJScCQ2ID0ge307XG5cbkJScCQ2LnJlY2FsY3VsYXRlTm9kZUxhYmVsUHJvamVjdGlvbiA9IGZ1bmN0aW9uIChub2RlKSB7XG4gIHZhciBjb250ZW50ID0gbm9kZS5wc3R5bGUoJ2xhYmVsJykuc3RyVmFsdWU7XG5cbiAgaWYgKGVtcHR5U3RyaW5nKGNvbnRlbnQpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHRleHRYLCB0ZXh0WTtcbiAgdmFyIF9wID0gbm9kZS5fcHJpdmF0ZTtcbiAgdmFyIG5vZGVXaWR0aCA9IG5vZGUud2lkdGgoKTtcbiAgdmFyIG5vZGVIZWlnaHQgPSBub2RlLmhlaWdodCgpO1xuICB2YXIgcGFkZGluZyA9IG5vZGUucGFkZGluZygpO1xuICB2YXIgbm9kZVBvcyA9IG5vZGUucG9zaXRpb24oKTtcbiAgdmFyIHRleHRIYWxpZ24gPSBub2RlLnBzdHlsZSgndGV4dC1oYWxpZ24nKS5zdHJWYWx1ZTtcbiAgdmFyIHRleHRWYWxpZ24gPSBub2RlLnBzdHlsZSgndGV4dC12YWxpZ24nKS5zdHJWYWx1ZTtcbiAgdmFyIHJzID0gX3AucnNjcmF0Y2g7XG4gIHZhciByc3R5bGUgPSBfcC5yc3R5bGU7XG5cbiAgc3dpdGNoICh0ZXh0SGFsaWduKSB7XG4gICAgY2FzZSAnbGVmdCc6XG4gICAgICB0ZXh0WCA9IG5vZGVQb3MueCAtIG5vZGVXaWR0aCAvIDIgLSBwYWRkaW5nO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdyaWdodCc6XG4gICAgICB0ZXh0WCA9IG5vZGVQb3MueCArIG5vZGVXaWR0aCAvIDIgKyBwYWRkaW5nO1xuICAgICAgYnJlYWs7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgLy8gZS5nLiBjZW50ZXJcbiAgICAgIHRleHRYID0gbm9kZVBvcy54O1xuICB9XG5cbiAgc3dpdGNoICh0ZXh0VmFsaWduKSB7XG4gICAgY2FzZSAndG9wJzpcbiAgICAgIHRleHRZID0gbm9kZVBvcy55IC0gbm9kZUhlaWdodCAvIDIgLSBwYWRkaW5nO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdib3R0b20nOlxuICAgICAgdGV4dFkgPSBub2RlUG9zLnkgKyBub2RlSGVpZ2h0IC8gMiArIHBhZGRpbmc7XG4gICAgICBicmVhaztcblxuICAgIGRlZmF1bHQ6XG4gICAgICAvLyBlLmcuIG1pZGRsZVxuICAgICAgdGV4dFkgPSBub2RlUG9zLnk7XG4gIH1cblxuICBycy5sYWJlbFggPSB0ZXh0WDtcbiAgcnMubGFiZWxZID0gdGV4dFk7XG4gIHJzdHlsZS5sYWJlbFggPSB0ZXh0WDtcbiAgcnN0eWxlLmxhYmVsWSA9IHRleHRZO1xuICB0aGlzLmFwcGx5TGFiZWxEaW1lbnNpb25zKG5vZGUpO1xufTtcblxudmFyIGxpbmVBbmdsZUZyb21EZWx0YSA9IGZ1bmN0aW9uIGxpbmVBbmdsZUZyb21EZWx0YShkeCwgZHkpIHtcbiAgdmFyIGFuZ2xlID0gTWF0aC5hdGFuKGR5IC8gZHgpO1xuXG4gIGlmIChkeCA9PT0gMCAmJiBhbmdsZSA8IDApIHtcbiAgICBhbmdsZSA9IGFuZ2xlICogLTE7XG4gIH1cblxuICByZXR1cm4gYW5nbGU7XG59O1xuXG52YXIgbGluZUFuZ2xlID0gZnVuY3Rpb24gbGluZUFuZ2xlKHAwLCBwMSkge1xuICB2YXIgZHggPSBwMS54IC0gcDAueDtcbiAgdmFyIGR5ID0gcDEueSAtIHAwLnk7XG4gIHJldHVybiBsaW5lQW5nbGVGcm9tRGVsdGEoZHgsIGR5KTtcbn07XG5cbnZhciBiZXppZXJBbmdsZSA9IGZ1bmN0aW9uIGJlemllckFuZ2xlKHAwLCBwMSwgcDIsIHQpIHtcbiAgdmFyIHQwID0gYm91bmQoMCwgdCAtIDAuMDAxLCAxKTtcbiAgdmFyIHQxID0gYm91bmQoMCwgdCArIDAuMDAxLCAxKTtcbiAgdmFyIGxwMCA9IHFiZXppZXJQdEF0KHAwLCBwMSwgcDIsIHQwKTtcbiAgdmFyIGxwMSA9IHFiZXppZXJQdEF0KHAwLCBwMSwgcDIsIHQxKTtcbiAgcmV0dXJuIGxpbmVBbmdsZShscDAsIGxwMSk7XG59O1xuXG5CUnAkNi5yZWNhbGN1bGF0ZUVkZ2VMYWJlbFByb2plY3Rpb25zID0gZnVuY3Rpb24gKGVkZ2UpIHtcbiAgdmFyIHA7XG4gIHZhciBfcCA9IGVkZ2UuX3ByaXZhdGU7XG4gIHZhciBycyA9IF9wLnJzY3JhdGNoO1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBjb250ZW50ID0ge1xuICAgIG1pZDogZWRnZS5wc3R5bGUoJ2xhYmVsJykuc3RyVmFsdWUsXG4gICAgc291cmNlOiBlZGdlLnBzdHlsZSgnc291cmNlLWxhYmVsJykuc3RyVmFsdWUsXG4gICAgdGFyZ2V0OiBlZGdlLnBzdHlsZSgndGFyZ2V0LWxhYmVsJykuc3RyVmFsdWVcbiAgfTtcblxuICBpZiAoY29udGVudC5taWQgfHwgY29udGVudC5zb3VyY2UgfHwgY29udGVudC50YXJnZXQpIDsgZWxzZSB7XG4gICAgICByZXR1cm47IC8vIG5vIGxhYmVscyA9PiBubyBjYWxjc1xuICAgIH0gLy8gYWRkIGNlbnRlciBwb2ludCB0byBzdHlsZSBzbyBib3VuZGluZyBib3ggY2FsY3VsYXRpb25zIGNhbiB1c2UgaXRcbiAgLy9cblxuXG4gIHAgPSB7XG4gICAgeDogcnMubWlkWCxcbiAgICB5OiBycy5taWRZXG4gIH07XG5cbiAgdmFyIHNldFJzID0gZnVuY3Rpb24gc2V0UnMocHJvcE5hbWUsIHByZWZpeCwgdmFsdWUpIHtcbiAgICBzZXRQcmVmaXhlZFByb3BlcnR5KF9wLnJzY3JhdGNoLCBwcm9wTmFtZSwgcHJlZml4LCB2YWx1ZSk7XG4gICAgc2V0UHJlZml4ZWRQcm9wZXJ0eShfcC5yc3R5bGUsIHByb3BOYW1lLCBwcmVmaXgsIHZhbHVlKTtcbiAgfTtcblxuICBzZXRScygnbGFiZWxYJywgbnVsbCwgcC54KTtcbiAgc2V0UnMoJ2xhYmVsWScsIG51bGwsIHAueSk7XG4gIHZhciBtaWRBbmdsZSA9IGxpbmVBbmdsZUZyb21EZWx0YShycy5taWREaXNwWCwgcnMubWlkRGlzcFkpO1xuICBzZXRScygnbGFiZWxBdXRvQW5nbGUnLCBudWxsLCBtaWRBbmdsZSk7XG5cbiAgdmFyIGNyZWF0ZUNvbnRyb2xQb2ludEluZm8gPSBmdW5jdGlvbiBjcmVhdGVDb250cm9sUG9pbnRJbmZvKCkge1xuICAgIGlmIChjcmVhdGVDb250cm9sUG9pbnRJbmZvLmNhY2hlKSB7XG4gICAgICByZXR1cm4gY3JlYXRlQ29udHJvbFBvaW50SW5mby5jYWNoZTtcbiAgICB9IC8vIHVzZSBjYWNoZSBzbyBvbmx5IDF4IHBlciBlZGdlXG5cblxuICAgIHZhciBjdHJscHRzID0gW107IC8vIHN0b3JlIGVhY2ggY3RybHB0IGluZm8gaW5pdFxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgKyA1IDwgcnMuYWxscHRzLmxlbmd0aDsgaSArPSA0KSB7XG4gICAgICB2YXIgcDAgPSB7XG4gICAgICAgIHg6IHJzLmFsbHB0c1tpXSxcbiAgICAgICAgeTogcnMuYWxscHRzW2kgKyAxXVxuICAgICAgfTtcbiAgICAgIHZhciBwMSA9IHtcbiAgICAgICAgeDogcnMuYWxscHRzW2kgKyAyXSxcbiAgICAgICAgeTogcnMuYWxscHRzW2kgKyAzXVxuICAgICAgfTsgLy8gY3RybHB0XG5cbiAgICAgIHZhciBwMiA9IHtcbiAgICAgICAgeDogcnMuYWxscHRzW2kgKyA0XSxcbiAgICAgICAgeTogcnMuYWxscHRzW2kgKyA1XVxuICAgICAgfTtcbiAgICAgIGN0cmxwdHMucHVzaCh7XG4gICAgICAgIHAwOiBwMCxcbiAgICAgICAgcDE6IHAxLFxuICAgICAgICBwMjogcDIsXG4gICAgICAgIHN0YXJ0RGlzdDogMCxcbiAgICAgICAgbGVuZ3RoOiAwLFxuICAgICAgICBzZWdtZW50czogW11cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBicHRzID0gX3AucnN0eWxlLmJlemllclB0cztcbiAgICB2YXIgblByb2pzID0gci5iZXppZXJQcm9qUGN0cy5sZW5ndGg7XG5cbiAgICBmdW5jdGlvbiBhZGRTZWdtZW50KGNwLCBwMCwgcDEsIHQwLCB0MSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGRpc3QocDAsIHAxKTtcbiAgICAgIHZhciBwcmV2U2VnbWVudCA9IGNwLnNlZ21lbnRzW2NwLnNlZ21lbnRzLmxlbmd0aCAtIDFdO1xuICAgICAgdmFyIHNlZ21lbnQgPSB7XG4gICAgICAgIHAwOiBwMCxcbiAgICAgICAgcDE6IHAxLFxuICAgICAgICB0MDogdDAsXG4gICAgICAgIHQxOiB0MSxcbiAgICAgICAgc3RhcnREaXN0OiBwcmV2U2VnbWVudCA/IHByZXZTZWdtZW50LnN0YXJ0RGlzdCArIHByZXZTZWdtZW50Lmxlbmd0aCA6IDAsXG4gICAgICAgIGxlbmd0aDogbGVuZ3RoXG4gICAgICB9O1xuICAgICAgY3Auc2VnbWVudHMucHVzaChzZWdtZW50KTtcbiAgICAgIGNwLmxlbmd0aCArPSBsZW5ndGg7XG4gICAgfSAvLyB1cGRhdGUgZWFjaCBjdHJscHQgd2l0aCBzZWdtZW50IGluZm9cblxuXG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGN0cmxwdHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICB2YXIgY3AgPSBjdHJscHRzW19pXTtcbiAgICAgIHZhciBwcmV2Q3AgPSBjdHJscHRzW19pIC0gMV07XG5cbiAgICAgIGlmIChwcmV2Q3ApIHtcbiAgICAgICAgY3Auc3RhcnREaXN0ID0gcHJldkNwLnN0YXJ0RGlzdCArIHByZXZDcC5sZW5ndGg7XG4gICAgICB9XG5cbiAgICAgIGFkZFNlZ21lbnQoY3AsIGNwLnAwLCBicHRzW19pICogblByb2pzXSwgMCwgci5iZXppZXJQcm9qUGN0c1swXSk7IC8vIGZpcnN0XG5cbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgblByb2pzIC0gMTsgaisrKSB7XG4gICAgICAgIGFkZFNlZ21lbnQoY3AsIGJwdHNbX2kgKiBuUHJvanMgKyBqXSwgYnB0c1tfaSAqIG5Qcm9qcyArIGogKyAxXSwgci5iZXppZXJQcm9qUGN0c1tqXSwgci5iZXppZXJQcm9qUGN0c1tqICsgMV0pO1xuICAgICAgfVxuXG4gICAgICBhZGRTZWdtZW50KGNwLCBicHRzW19pICogblByb2pzICsgblByb2pzIC0gMV0sIGNwLnAyLCByLmJlemllclByb2pQY3RzW25Qcm9qcyAtIDFdLCAxKTsgLy8gbGFzdFxuICAgIH1cblxuICAgIHJldHVybiBjcmVhdGVDb250cm9sUG9pbnRJbmZvLmNhY2hlID0gY3RybHB0cztcbiAgfTtcblxuICB2YXIgY2FsY3VsYXRlRW5kUHJvamVjdGlvbiA9IGZ1bmN0aW9uIGNhbGN1bGF0ZUVuZFByb2plY3Rpb24ocHJlZml4KSB7XG4gICAgdmFyIGFuZ2xlO1xuICAgIHZhciBpc1NyYyA9IHByZWZpeCA9PT0gJ3NvdXJjZSc7XG5cbiAgICBpZiAoIWNvbnRlbnRbcHJlZml4XSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBvZmZzZXQgPSBlZGdlLnBzdHlsZShwcmVmaXggKyAnLXRleHQtb2Zmc2V0JykucGZWYWx1ZTtcblxuICAgIHN3aXRjaCAocnMuZWRnZVR5cGUpIHtcbiAgICAgIGNhc2UgJ3NlbGYnOlxuICAgICAgY2FzZSAnY29tcG91bmQnOlxuICAgICAgY2FzZSAnYmV6aWVyJzpcbiAgICAgIGNhc2UgJ211bHRpYmV6aWVyJzpcbiAgICAgICAge1xuICAgICAgICAgIHZhciBjcHMgPSBjcmVhdGVDb250cm9sUG9pbnRJbmZvKCk7XG4gICAgICAgICAgdmFyIHNlbGVjdGVkO1xuICAgICAgICAgIHZhciBzdGFydERpc3QgPSAwO1xuICAgICAgICAgIHZhciB0b3RhbERpc3QgPSAwOyAvLyBmaW5kIHRoZSBzZWdtZW50IHdlJ3JlIG9uXG5cbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIF9jcCA9IGNwc1tpc1NyYyA/IGkgOiBjcHMubGVuZ3RoIC0gMSAtIGldO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IF9jcC5zZWdtZW50cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICB2YXIgX3NlZyA9IF9jcC5zZWdtZW50c1tpc1NyYyA/IGogOiBfY3Auc2VnbWVudHMubGVuZ3RoIC0gMSAtIGpdO1xuICAgICAgICAgICAgICB2YXIgbGFzdFNlZyA9IGkgPT09IGNwcy5sZW5ndGggLSAxICYmIGogPT09IF9jcC5zZWdtZW50cy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICBzdGFydERpc3QgPSB0b3RhbERpc3Q7XG4gICAgICAgICAgICAgIHRvdGFsRGlzdCArPSBfc2VnLmxlbmd0aDtcblxuICAgICAgICAgICAgICBpZiAodG90YWxEaXN0ID49IG9mZnNldCB8fCBsYXN0U2VnKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWQgPSB7XG4gICAgICAgICAgICAgICAgICBjcDogX2NwLFxuICAgICAgICAgICAgICAgICAgc2VnbWVudDogX3NlZ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBjcCA9IHNlbGVjdGVkLmNwO1xuICAgICAgICAgIHZhciBzZWcgPSBzZWxlY3RlZC5zZWdtZW50O1xuICAgICAgICAgIHZhciB0U2VnbWVudCA9IChvZmZzZXQgLSBzdGFydERpc3QpIC8gc2VnLmxlbmd0aDtcbiAgICAgICAgICB2YXIgc2VnRHQgPSBzZWcudDEgLSBzZWcudDA7XG4gICAgICAgICAgdmFyIHQgPSBpc1NyYyA/IHNlZy50MCArIHNlZ0R0ICogdFNlZ21lbnQgOiBzZWcudDEgLSBzZWdEdCAqIHRTZWdtZW50O1xuICAgICAgICAgIHQgPSBib3VuZCgwLCB0LCAxKTtcbiAgICAgICAgICBwID0gcWJlemllclB0QXQoY3AucDAsIGNwLnAxLCBjcC5wMiwgdCk7XG4gICAgICAgICAgYW5nbGUgPSBiZXppZXJBbmdsZShjcC5wMCwgY3AucDEsIGNwLnAyLCB0KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICBjYXNlICdzdHJhaWdodCc6XG4gICAgICBjYXNlICdzZWdtZW50cyc6XG4gICAgICBjYXNlICdoYXlzdGFjayc6XG4gICAgICAgIHtcbiAgICAgICAgICB2YXIgZCA9IDAsXG4gICAgICAgICAgICAgIGRpLFxuICAgICAgICAgICAgICBkMDtcbiAgICAgICAgICB2YXIgcDAsIHAxO1xuICAgICAgICAgIHZhciBsID0gcnMuYWxscHRzLmxlbmd0aDtcblxuICAgICAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiArIDMgPCBsOyBfaTIgKz0gMikge1xuICAgICAgICAgICAgaWYgKGlzU3JjKSB7XG4gICAgICAgICAgICAgIHAwID0ge1xuICAgICAgICAgICAgICAgIHg6IHJzLmFsbHB0c1tfaTJdLFxuICAgICAgICAgICAgICAgIHk6IHJzLmFsbHB0c1tfaTIgKyAxXVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBwMSA9IHtcbiAgICAgICAgICAgICAgICB4OiBycy5hbGxwdHNbX2kyICsgMl0sXG4gICAgICAgICAgICAgICAgeTogcnMuYWxscHRzW19pMiArIDNdXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwMCA9IHtcbiAgICAgICAgICAgICAgICB4OiBycy5hbGxwdHNbbCAtIDIgLSBfaTJdLFxuICAgICAgICAgICAgICAgIHk6IHJzLmFsbHB0c1tsIC0gMSAtIF9pMl1cbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgcDEgPSB7XG4gICAgICAgICAgICAgICAgeDogcnMuYWxscHRzW2wgLSA0IC0gX2kyXSxcbiAgICAgICAgICAgICAgICB5OiBycy5hbGxwdHNbbCAtIDMgLSBfaTJdXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRpID0gZGlzdChwMCwgcDEpO1xuICAgICAgICAgICAgZDAgPSBkO1xuICAgICAgICAgICAgZCArPSBkaTtcblxuICAgICAgICAgICAgaWYgKGQgPj0gb2Zmc2V0KSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBwRCA9IG9mZnNldCAtIGQwO1xuXG4gICAgICAgICAgdmFyIF90ID0gcEQgLyBkaTtcblxuICAgICAgICAgIF90ID0gYm91bmQoMCwgX3QsIDEpO1xuICAgICAgICAgIHAgPSBsaW5lQXQocDAsIHAxLCBfdCk7XG4gICAgICAgICAgYW5nbGUgPSBsaW5lQW5nbGUocDAsIHAxKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFJzKCdsYWJlbFgnLCBwcmVmaXgsIHAueCk7XG4gICAgc2V0UnMoJ2xhYmVsWScsIHByZWZpeCwgcC55KTtcbiAgICBzZXRScygnbGFiZWxBdXRvQW5nbGUnLCBwcmVmaXgsIGFuZ2xlKTtcbiAgfTtcblxuICBjYWxjdWxhdGVFbmRQcm9qZWN0aW9uKCdzb3VyY2UnKTtcbiAgY2FsY3VsYXRlRW5kUHJvamVjdGlvbigndGFyZ2V0Jyk7XG4gIHRoaXMuYXBwbHlMYWJlbERpbWVuc2lvbnMoZWRnZSk7XG59O1xuXG5CUnAkNi5hcHBseUxhYmVsRGltZW5zaW9ucyA9IGZ1bmN0aW9uIChlbGUpIHtcbiAgdGhpcy5hcHBseVByZWZpeGVkTGFiZWxEaW1lbnNpb25zKGVsZSk7XG5cbiAgaWYgKGVsZS5pc0VkZ2UoKSkge1xuICAgIHRoaXMuYXBwbHlQcmVmaXhlZExhYmVsRGltZW5zaW9ucyhlbGUsICdzb3VyY2UnKTtcbiAgICB0aGlzLmFwcGx5UHJlZml4ZWRMYWJlbERpbWVuc2lvbnMoZWxlLCAndGFyZ2V0Jyk7XG4gIH1cbn07XG5cbkJScCQ2LmFwcGx5UHJlZml4ZWRMYWJlbERpbWVuc2lvbnMgPSBmdW5jdGlvbiAoZWxlLCBwcmVmaXgpIHtcbiAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICB2YXIgdGV4dCA9IHRoaXMuZ2V0TGFiZWxUZXh0KGVsZSwgcHJlZml4KTtcbiAgdmFyIGxhYmVsRGltcyA9IHRoaXMuY2FsY3VsYXRlTGFiZWxEaW1lbnNpb25zKGVsZSwgdGV4dCk7XG4gIHZhciBsaW5lSGVpZ2h0ID0gZWxlLnBzdHlsZSgnbGluZS1oZWlnaHQnKS5wZlZhbHVlO1xuICB2YXIgdGV4dFdyYXAgPSBlbGUucHN0eWxlKCd0ZXh0LXdyYXAnKS5zdHJWYWx1ZTtcbiAgdmFyIGxpbmVzID0gZ2V0UHJlZml4ZWRQcm9wZXJ0eShfcC5yc2NyYXRjaCwgJ2xhYmVsV3JhcENhY2hlZExpbmVzJywgcHJlZml4KSB8fCBbXTtcbiAgdmFyIG51bUxpbmVzID0gdGV4dFdyYXAgIT09ICd3cmFwJyA/IDEgOiBNYXRoLm1heChsaW5lcy5sZW5ndGgsIDEpO1xuICB2YXIgbm9ybVBlckxpbmVIZWlnaHQgPSBsYWJlbERpbXMuaGVpZ2h0IC8gbnVtTGluZXM7XG4gIHZhciBsYWJlbExpbmVIZWlnaHQgPSBub3JtUGVyTGluZUhlaWdodCAqIGxpbmVIZWlnaHQ7XG4gIHZhciB3aWR0aCA9IGxhYmVsRGltcy53aWR0aDtcbiAgdmFyIGhlaWdodCA9IGxhYmVsRGltcy5oZWlnaHQgKyAobnVtTGluZXMgLSAxKSAqIChsaW5lSGVpZ2h0IC0gMSkgKiBub3JtUGVyTGluZUhlaWdodDtcbiAgc2V0UHJlZml4ZWRQcm9wZXJ0eShfcC5yc3R5bGUsICdsYWJlbFdpZHRoJywgcHJlZml4LCB3aWR0aCk7XG4gIHNldFByZWZpeGVkUHJvcGVydHkoX3AucnNjcmF0Y2gsICdsYWJlbFdpZHRoJywgcHJlZml4LCB3aWR0aCk7XG4gIHNldFByZWZpeGVkUHJvcGVydHkoX3AucnN0eWxlLCAnbGFiZWxIZWlnaHQnLCBwcmVmaXgsIGhlaWdodCk7XG4gIHNldFByZWZpeGVkUHJvcGVydHkoX3AucnNjcmF0Y2gsICdsYWJlbEhlaWdodCcsIHByZWZpeCwgaGVpZ2h0KTtcbiAgc2V0UHJlZml4ZWRQcm9wZXJ0eShfcC5yc2NyYXRjaCwgJ2xhYmVsTGluZUhlaWdodCcsIHByZWZpeCwgbGFiZWxMaW5lSGVpZ2h0KTtcbn07XG5cbkJScCQ2LmdldExhYmVsVGV4dCA9IGZ1bmN0aW9uIChlbGUsIHByZWZpeCkge1xuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciBwZmQgPSBwcmVmaXggPyBwcmVmaXggKyAnLScgOiAnJztcbiAgdmFyIHRleHQgPSBlbGUucHN0eWxlKHBmZCArICdsYWJlbCcpLnN0clZhbHVlO1xuICB2YXIgdGV4dFRyYW5zZm9ybSA9IGVsZS5wc3R5bGUoJ3RleHQtdHJhbnNmb3JtJykudmFsdWU7XG5cbiAgdmFyIHJzY3JhdGNoID0gZnVuY3Rpb24gcnNjcmF0Y2gocHJvcE5hbWUsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICBzZXRQcmVmaXhlZFByb3BlcnR5KF9wLnJzY3JhdGNoLCBwcm9wTmFtZSwgcHJlZml4LCB2YWx1ZSk7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBnZXRQcmVmaXhlZFByb3BlcnR5KF9wLnJzY3JhdGNoLCBwcm9wTmFtZSwgcHJlZml4KTtcbiAgICB9XG4gIH07IC8vIGZvciBlbXB0eSB0ZXh0LCBza2lwIGFsbCBwcm9jZXNzaW5nXG5cblxuICBpZiAoIXRleHQpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICBpZiAodGV4dFRyYW5zZm9ybSA9PSAnbm9uZScpIDsgZWxzZSBpZiAodGV4dFRyYW5zZm9ybSA9PSAndXBwZXJjYXNlJykge1xuICAgIHRleHQgPSB0ZXh0LnRvVXBwZXJDYXNlKCk7XG4gIH0gZWxzZSBpZiAodGV4dFRyYW5zZm9ybSA9PSAnbG93ZXJjYXNlJykge1xuICAgIHRleHQgPSB0ZXh0LnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICB2YXIgd3JhcFN0eWxlID0gZWxlLnBzdHlsZSgndGV4dC13cmFwJykudmFsdWU7XG5cbiAgaWYgKHdyYXBTdHlsZSA9PT0gJ3dyYXAnKSB7XG4gICAgdmFyIGxhYmVsS2V5ID0gcnNjcmF0Y2goJ2xhYmVsS2V5Jyk7IC8vIHNhdmUgcmVjYWxjIGlmIHRoZSBsYWJlbCBpcyB0aGUgc2FtZSBhcyBiZWZvcmVcblxuICAgIGlmIChsYWJlbEtleSAhPSBudWxsICYmIHJzY3JhdGNoKCdsYWJlbFdyYXBLZXknKSA9PT0gbGFiZWxLZXkpIHtcbiAgICAgIHJldHVybiByc2NyYXRjaCgnbGFiZWxXcmFwQ2FjaGVkVGV4dCcpO1xuICAgIH1cblxuICAgIHZhciB6d3NwID0gXCJcXHUyMDBCXCI7XG4gICAgdmFyIGxpbmVzID0gdGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgdmFyIG1heFcgPSBlbGUucHN0eWxlKCd0ZXh0LW1heC13aWR0aCcpLnBmVmFsdWU7XG4gICAgdmFyIG92ZXJmbG93ID0gZWxlLnBzdHlsZSgndGV4dC1vdmVyZmxvdy13cmFwJykudmFsdWU7XG4gICAgdmFyIG92ZXJmbG93QW55ID0gb3ZlcmZsb3cgPT09ICdhbnl3aGVyZSc7XG4gICAgdmFyIHdyYXBwZWRMaW5lcyA9IFtdO1xuICAgIHZhciB3b3Jkc1JlZ2V4ID0gL1tcXHNcXHUyMDBiXSsvO1xuICAgIHZhciB3b3JkU2VwYXJhdG9yID0gb3ZlcmZsb3dBbnkgPyAnJyA6ICcgJztcblxuICAgIGZvciAodmFyIGwgPSAwOyBsIDwgbGluZXMubGVuZ3RoOyBsKyspIHtcbiAgICAgIHZhciBsaW5lID0gbGluZXNbbF07XG4gICAgICB2YXIgbGluZURpbXMgPSB0aGlzLmNhbGN1bGF0ZUxhYmVsRGltZW5zaW9ucyhlbGUsIGxpbmUpO1xuICAgICAgdmFyIGxpbmVXID0gbGluZURpbXMud2lkdGg7XG5cbiAgICAgIGlmIChvdmVyZmxvd0FueSkge1xuICAgICAgICB2YXIgcHJvY2Vzc2VkTGluZSA9IGxpbmUuc3BsaXQoJycpLmpvaW4oendzcCk7XG4gICAgICAgIGxpbmUgPSBwcm9jZXNzZWRMaW5lO1xuICAgICAgfVxuXG4gICAgICBpZiAobGluZVcgPiBtYXhXKSB7XG4gICAgICAgIC8vIGxpbmUgaXMgdG9vIGxvbmdcbiAgICAgICAgdmFyIHdvcmRzID0gbGluZS5zcGxpdCh3b3Jkc1JlZ2V4KTtcbiAgICAgICAgdmFyIHN1YmxpbmUgPSAnJztcblxuICAgICAgICBmb3IgKHZhciB3ID0gMDsgdyA8IHdvcmRzLmxlbmd0aDsgdysrKSB7XG4gICAgICAgICAgdmFyIHdvcmQgPSB3b3Jkc1t3XTtcbiAgICAgICAgICB2YXIgdGVzdExpbmUgPSBzdWJsaW5lLmxlbmd0aCA9PT0gMCA/IHdvcmQgOiBzdWJsaW5lICsgd29yZFNlcGFyYXRvciArIHdvcmQ7XG4gICAgICAgICAgdmFyIHRlc3REaW1zID0gdGhpcy5jYWxjdWxhdGVMYWJlbERpbWVuc2lvbnMoZWxlLCB0ZXN0TGluZSk7XG4gICAgICAgICAgdmFyIHRlc3RXID0gdGVzdERpbXMud2lkdGg7XG5cbiAgICAgICAgICBpZiAodGVzdFcgPD0gbWF4Vykge1xuICAgICAgICAgICAgLy8gd29yZCBmaXRzIG9uIGN1cnJlbnQgbGluZVxuICAgICAgICAgICAgc3VibGluZSArPSB3b3JkICsgd29yZFNlcGFyYXRvcjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gd29yZCBzdGFydHMgbmV3IGxpbmVcbiAgICAgICAgICAgIGlmIChzdWJsaW5lKSB7XG4gICAgICAgICAgICAgIHdyYXBwZWRMaW5lcy5wdXNoKHN1YmxpbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzdWJsaW5lID0gd29yZCArIHdvcmRTZXBhcmF0b3I7XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIGlmIHRoZXJlJ3MgcmVtYWluaW5nIHRleHQsIHB1dCBpdCBpbiBhIHdyYXBwZWQgbGluZVxuXG5cbiAgICAgICAgaWYgKCFzdWJsaW5lLm1hdGNoKC9eW1xcc1xcdTIwMGJdKyQvKSkge1xuICAgICAgICAgIHdyYXBwZWRMaW5lcy5wdXNoKHN1YmxpbmUpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBsaW5lIGlzIGFscmVhZHkgc2hvcnQgZW5vdWdoXG4gICAgICAgIHdyYXBwZWRMaW5lcy5wdXNoKGxpbmUpO1xuICAgICAgfVxuICAgIH0gLy8gZm9yXG5cblxuICAgIHJzY3JhdGNoKCdsYWJlbFdyYXBDYWNoZWRMaW5lcycsIHdyYXBwZWRMaW5lcyk7XG4gICAgdGV4dCA9IHJzY3JhdGNoKCdsYWJlbFdyYXBDYWNoZWRUZXh0Jywgd3JhcHBlZExpbmVzLmpvaW4oJ1xcbicpKTtcbiAgICByc2NyYXRjaCgnbGFiZWxXcmFwS2V5JywgbGFiZWxLZXkpO1xuICB9IGVsc2UgaWYgKHdyYXBTdHlsZSA9PT0gJ2VsbGlwc2lzJykge1xuICAgIHZhciBfbWF4VyA9IGVsZS5wc3R5bGUoJ3RleHQtbWF4LXdpZHRoJykucGZWYWx1ZTtcbiAgICB2YXIgZWxsaXBzaXplZCA9ICcnO1xuICAgIHZhciBlbGxpcHNpcyA9IFwiXFx1MjAyNlwiO1xuICAgIHZhciBpbmNMYXN0Q2ggPSBmYWxzZTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHdpZHRoV2l0aE5leHRDaCA9IHRoaXMuY2FsY3VsYXRlTGFiZWxEaW1lbnNpb25zKGVsZSwgZWxsaXBzaXplZCArIHRleHRbaV0gKyBlbGxpcHNpcykud2lkdGg7XG5cbiAgICAgIGlmICh3aWR0aFdpdGhOZXh0Q2ggPiBfbWF4Vykge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgZWxsaXBzaXplZCArPSB0ZXh0W2ldO1xuXG4gICAgICBpZiAoaSA9PT0gdGV4dC5sZW5ndGggLSAxKSB7XG4gICAgICAgIGluY0xhc3RDaCA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFpbmNMYXN0Q2gpIHtcbiAgICAgIGVsbGlwc2l6ZWQgKz0gZWxsaXBzaXM7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsbGlwc2l6ZWQ7XG4gIH0gLy8gaWYgZWxsaXBzaXplXG5cblxuICByZXR1cm4gdGV4dDtcbn07XG5cbkJScCQ2LmdldExhYmVsSnVzdGlmaWNhdGlvbiA9IGZ1bmN0aW9uIChlbGUpIHtcbiAgdmFyIGp1c3RpZmljYXRpb24gPSBlbGUucHN0eWxlKCd0ZXh0LWp1c3RpZmljYXRpb24nKS5zdHJWYWx1ZTtcbiAgdmFyIHRleHRIYWxpZ24gPSBlbGUucHN0eWxlKCd0ZXh0LWhhbGlnbicpLnN0clZhbHVlO1xuXG4gIGlmIChqdXN0aWZpY2F0aW9uID09PSAnYXV0bycpIHtcbiAgICBpZiAoZWxlLmlzTm9kZSgpKSB7XG4gICAgICBzd2l0Y2ggKHRleHRIYWxpZ24pIHtcbiAgICAgICAgY2FzZSAnbGVmdCc6XG4gICAgICAgICAgcmV0dXJuICdyaWdodCc7XG5cbiAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICAgIHJldHVybiAnbGVmdCc7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gJ2NlbnRlcic7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnY2VudGVyJztcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGp1c3RpZmljYXRpb247XG4gIH1cbn07XG5cbkJScCQ2LmNhbGN1bGF0ZUxhYmVsRGltZW5zaW9ucyA9IGZ1bmN0aW9uIChlbGUsIHRleHQpIHtcbiAgdmFyIHIgPSB0aGlzO1xuICB2YXIgY2FjaGVLZXkgPSBoYXNoU3RyaW5nKHRleHQsIGVsZS5fcHJpdmF0ZS5sYWJlbERpbXNLZXkpO1xuICB2YXIgY2FjaGUgPSByLmxhYmVsRGltQ2FjaGUgfHwgKHIubGFiZWxEaW1DYWNoZSA9IFtdKTtcbiAgdmFyIGV4aXN0aW5nVmFsID0gY2FjaGVbY2FjaGVLZXldO1xuXG4gIGlmIChleGlzdGluZ1ZhbCAhPSBudWxsKSB7XG4gICAgcmV0dXJuIGV4aXN0aW5nVmFsO1xuICB9XG5cbiAgdmFyIHNpemVNdWx0ID0gMTsgLy8gaW5jcmVhc2UgdGhlIHNjYWxlIHRvIGluY3JlYXNlIGFjY3VyYWN5IHcuci50LiB6b29tZWQgdGV4dFxuXG4gIHZhciBmU3R5bGUgPSBlbGUucHN0eWxlKCdmb250LXN0eWxlJykuc3RyVmFsdWU7XG4gIHZhciBzaXplID0gc2l6ZU11bHQgKiBlbGUucHN0eWxlKCdmb250LXNpemUnKS5wZlZhbHVlICsgJ3B4JztcbiAgdmFyIGZhbWlseSA9IGVsZS5wc3R5bGUoJ2ZvbnQtZmFtaWx5Jykuc3RyVmFsdWU7XG4gIHZhciB3ZWlnaHQgPSBlbGUucHN0eWxlKCdmb250LXdlaWdodCcpLnN0clZhbHVlO1xuICB2YXIgZGl2ID0gdGhpcy5sYWJlbENhbGNEaXY7XG5cbiAgaWYgKCFkaXYpIHtcbiAgICBkaXYgPSB0aGlzLmxhYmVsQ2FsY0RpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbiAgfVxuXG4gIHZhciBkcyA9IGRpdi5zdHlsZTsgLy8gZnJvbSBlbGUgc3R5bGVcblxuICBkcy5mb250RmFtaWx5ID0gZmFtaWx5O1xuICBkcy5mb250U3R5bGUgPSBmU3R5bGU7XG4gIGRzLmZvbnRTaXplID0gc2l6ZTtcbiAgZHMuZm9udFdlaWdodCA9IHdlaWdodDsgLy8gZm9yY2VkIHN0eWxlXG5cbiAgZHMucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICBkcy5sZWZ0ID0gJy05OTk5cHgnO1xuICBkcy50b3AgPSAnLTk5OTlweCc7XG4gIGRzLnpJbmRleCA9ICctMSc7XG4gIGRzLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgZHMucG9pbnRlckV2ZW50cyA9ICdub25lJztcbiAgZHMucGFkZGluZyA9ICcwJztcbiAgZHMubGluZUhlaWdodCA9ICcxJzsgLy8gLSBuZXdsaW5lcyBtdXN0IGJlIHRha2VuIGludG8gYWNjb3VudCBmb3IgdGV4dC13cmFwOndyYXBcbiAgLy8gLSBzaW5jZSBzcGFjZXMgYXJlIG5vdCBjb2xsYXBzZWQsIGVhY2ggc3BhY2UgbXVzdCBiZSB0YWtlbiBpbnRvIGFjY291bnRcblxuICBkcy53aGl0ZVNwYWNlID0gJ3ByZSc7IC8vIHB1dCBsYWJlbCBjb250ZW50IGluIGRpdlxuXG4gIGRpdi50ZXh0Q29udGVudCA9IHRleHQ7XG4gIHJldHVybiBjYWNoZVtjYWNoZUtleV0gPSB7XG4gICAgd2lkdGg6IE1hdGguY2VpbChkaXYuY2xpZW50V2lkdGggLyBzaXplTXVsdCksXG4gICAgaGVpZ2h0OiBNYXRoLmNlaWwoZGl2LmNsaWVudEhlaWdodCAvIHNpemVNdWx0KVxuICB9O1xufTtcblxuQlJwJDYuY2FsY3VsYXRlTGFiZWxBbmdsZSA9IGZ1bmN0aW9uIChlbGUsIHByZWZpeCkge1xuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciBycyA9IF9wLnJzY3JhdGNoO1xuICB2YXIgaXNFZGdlID0gZWxlLmlzRWRnZSgpO1xuICB2YXIgcHJlZml4RGFzaCA9IHByZWZpeCA/IHByZWZpeCArICctJyA6ICcnO1xuICB2YXIgcm90ID0gZWxlLnBzdHlsZShwcmVmaXhEYXNoICsgJ3RleHQtcm90YXRpb24nKTtcbiAgdmFyIHJvdFN0ciA9IHJvdC5zdHJWYWx1ZTtcblxuICBpZiAocm90U3RyID09PSAnbm9uZScpIHtcbiAgICByZXR1cm4gMDtcbiAgfSBlbHNlIGlmIChpc0VkZ2UgJiYgcm90U3RyID09PSAnYXV0b3JvdGF0ZScpIHtcbiAgICByZXR1cm4gcnMubGFiZWxBdXRvQW5nbGU7XG4gIH0gZWxzZSBpZiAocm90U3RyID09PSAnYXV0b3JvdGF0ZScpIHtcbiAgICByZXR1cm4gMDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcm90LnBmVmFsdWU7XG4gIH1cbn07XG5cbkJScCQ2LmNhbGN1bGF0ZUxhYmVsQW5nbGVzID0gZnVuY3Rpb24gKGVsZSkge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBpc0VkZ2UgPSBlbGUuaXNFZGdlKCk7XG4gIHZhciBfcCA9IGVsZS5fcHJpdmF0ZTtcbiAgdmFyIHJzID0gX3AucnNjcmF0Y2g7XG4gIHJzLmxhYmVsQW5nbGUgPSByLmNhbGN1bGF0ZUxhYmVsQW5nbGUoZWxlKTtcblxuICBpZiAoaXNFZGdlKSB7XG4gICAgcnMuc291cmNlTGFiZWxBbmdsZSA9IHIuY2FsY3VsYXRlTGFiZWxBbmdsZShlbGUsICdzb3VyY2UnKTtcbiAgICBycy50YXJnZXRMYWJlbEFuZ2xlID0gci5jYWxjdWxhdGVMYWJlbEFuZ2xlKGVsZSwgJ3RhcmdldCcpO1xuICB9XG59O1xuXG52YXIgQlJwJDcgPSB7fTtcbnZhciBUT09fU01BTExfQ1VUX1JFQ1QgPSAyODtcbnZhciB3YXJuZWRDdXRSZWN0ID0gZmFsc2U7XG5cbkJScCQ3LmdldE5vZGVTaGFwZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gIHZhciByID0gdGhpcztcbiAgdmFyIHNoYXBlID0gbm9kZS5wc3R5bGUoJ3NoYXBlJykudmFsdWU7XG5cbiAgaWYgKHNoYXBlID09PSAnY3V0cmVjdGFuZ2xlJyAmJiAobm9kZS53aWR0aCgpIDwgVE9PX1NNQUxMX0NVVF9SRUNUIHx8IG5vZGUuaGVpZ2h0KCkgPCBUT09fU01BTExfQ1VUX1JFQ1QpKSB7XG4gICAgaWYgKCF3YXJuZWRDdXRSZWN0KSB7XG4gICAgICB3YXJuKCdUaGUgYGN1dHJlY3RhbmdsZWAgbm9kZSBzaGFwZSBjYW4gbm90IGJlIHVzZWQgYXQgc21hbGwgc2l6ZXMgc28gYHJlY3RhbmdsZWAgaXMgdXNlZCBpbnN0ZWFkJyk7XG4gICAgICB3YXJuZWRDdXRSZWN0ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gJ3JlY3RhbmdsZSc7XG4gIH1cblxuICBpZiAobm9kZS5pc1BhcmVudCgpKSB7XG4gICAgaWYgKHNoYXBlID09PSAncmVjdGFuZ2xlJyB8fCBzaGFwZSA9PT0gJ3JvdW5kcmVjdGFuZ2xlJyB8fCBzaGFwZSA9PT0gJ3JvdW5kLXJlY3RhbmdsZScgfHwgc2hhcGUgPT09ICdjdXRyZWN0YW5nbGUnIHx8IHNoYXBlID09PSAnY3V0LXJlY3RhbmdsZScgfHwgc2hhcGUgPT09ICdiYXJyZWwnKSB7XG4gICAgICByZXR1cm4gc2hhcGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAncmVjdGFuZ2xlJztcbiAgICB9XG4gIH1cblxuICBpZiAoc2hhcGUgPT09ICdwb2x5Z29uJykge1xuICAgIHZhciBwb2ludHMgPSBub2RlLnBzdHlsZSgnc2hhcGUtcG9seWdvbi1wb2ludHMnKS52YWx1ZTtcbiAgICByZXR1cm4gci5ub2RlU2hhcGVzLm1ha2VQb2x5Z29uKHBvaW50cykubmFtZTtcbiAgfVxuXG4gIHJldHVybiBzaGFwZTtcbn07XG5cbnZhciBCUnAkOCA9IHt9O1xuXG5CUnAkOC5yZWdpc3RlckNhbGN1bGF0aW9uTGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICB2YXIgY3kgPSB0aGlzLmN5O1xuICB2YXIgZWxlc1RvVXBkYXRlID0gY3kuY29sbGVjdGlvbigpO1xuICB2YXIgciA9IHRoaXM7XG5cbiAgdmFyIGVucXVldWUgPSBmdW5jdGlvbiBlbnF1ZXVlKGVsZXMpIHtcbiAgICB2YXIgZGlydHlTdHlsZUNhY2hlcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogdHJ1ZTtcbiAgICBlbGVzVG9VcGRhdGUubWVyZ2UoZWxlcyk7XG5cbiAgICBpZiAoZGlydHlTdHlsZUNhY2hlcykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSBlbGVzW2ldO1xuICAgICAgICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gICAgICAgIHZhciByc3R5bGUgPSBfcC5yc3R5bGU7XG4gICAgICAgIHJzdHlsZS5jbGVhbiA9IGZhbHNlO1xuICAgICAgICByc3R5bGUuY2xlYW5Db25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgci5iaW5kZXIoY3kpLm9uKCdib3VuZHMuKiBkaXJ0eS4qJywgZnVuY3Rpb24gb25EaXJ0eUJvdW5kcyhlKSB7XG4gICAgdmFyIGVsZSA9IGUudGFyZ2V0O1xuICAgIGVucXVldWUoZWxlKTtcbiAgfSkub24oJ3N0eWxlLiogYmFja2dyb3VuZC4qJywgZnVuY3Rpb24gb25EaXJ0eVN0eWxlKGUpIHtcbiAgICB2YXIgZWxlID0gZS50YXJnZXQ7XG4gICAgZW5xdWV1ZShlbGUsIGZhbHNlKTtcbiAgfSk7XG5cbiAgdmFyIHVwZGF0ZUVsZUNhbGNzID0gZnVuY3Rpb24gdXBkYXRlRWxlQ2FsY3Mod2lsbERyYXcpIHtcbiAgICBpZiAod2lsbERyYXcpIHtcbiAgICAgIHZhciBmbnMgPSByLm9uVXBkYXRlRWxlQ2FsY3NGbnM7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlc1RvVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlbGUgPSBlbGVzVG9VcGRhdGVbaV07XG4gICAgICAgIHZhciByc3R5bGUgPSBlbGUuX3ByaXZhdGUucnN0eWxlO1xuXG4gICAgICAgIGlmIChlbGUuaXNOb2RlKCkgJiYgIXJzdHlsZS5jbGVhbkNvbm5lY3RlZCkge1xuICAgICAgICAgIGVucXVldWUoZWxlLmNvbm5lY3RlZEVkZ2VzKCkpO1xuICAgICAgICAgIHJzdHlsZS5jbGVhbkNvbm5lY3RlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGZucykge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgZm5zLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgIHZhciBmbiA9IGZuc1tfaV07XG4gICAgICAgICAgZm4od2lsbERyYXcsIGVsZXNUb1VwZGF0ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgci5yZWNhbGN1bGF0ZVJlbmRlcmVkU3R5bGUoZWxlc1RvVXBkYXRlKTtcbiAgICAgIGVsZXNUb1VwZGF0ZSA9IGN5LmNvbGxlY3Rpb24oKTtcbiAgICB9XG4gIH07XG5cbiAgci5mbHVzaFJlbmRlcmVkU3R5bGVRdWV1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB1cGRhdGVFbGVDYWxjcyh0cnVlKTtcbiAgfTtcblxuICByLmJlZm9yZVJlbmRlcih1cGRhdGVFbGVDYWxjcywgci5iZWZvcmVSZW5kZXJQcmlvcml0aWVzLmVsZUNhbGNzKTtcbn07XG5cbkJScCQ4Lm9uVXBkYXRlRWxlQ2FsY3MgPSBmdW5jdGlvbiAoZm4pIHtcbiAgdmFyIGZucyA9IHRoaXMub25VcGRhdGVFbGVDYWxjc0ZucyA9IHRoaXMub25VcGRhdGVFbGVDYWxjc0ZucyB8fCBbXTtcbiAgZm5zLnB1c2goZm4pO1xufTtcblxuQlJwJDgucmVjYWxjdWxhdGVSZW5kZXJlZFN0eWxlID0gZnVuY3Rpb24gKGVsZXMsIHVzZUNhY2hlKSB7XG4gIHZhciBpc0NsZWFuQ29ubmVjdGVkID0gZnVuY3Rpb24gaXNDbGVhbkNvbm5lY3RlZChlbGUpIHtcbiAgICByZXR1cm4gZWxlLl9wcml2YXRlLnJzdHlsZS5jbGVhbkNvbm5lY3RlZDtcbiAgfTtcblxuICB2YXIgZWRnZXMgPSBbXTtcbiAgdmFyIG5vZGVzID0gW107IC8vIHRoZSByZW5kZXJlciBjYW4ndCBiZSB1c2VkIGZvciBjYWxjcyB3aGVuIGRlc3Ryb3llZCwgZS5nLiBlbGUuYm91bmRpbmdCb3goKVxuXG4gIGlmICh0aGlzLmRlc3Ryb3llZCkge1xuICAgIHJldHVybjtcbiAgfSAvLyB1c2UgY2FjaGUgYnkgZGVmYXVsdCBmb3IgcGVyZlxuXG5cbiAgaWYgKHVzZUNhY2hlID09PSB1bmRlZmluZWQpIHtcbiAgICB1c2VDYWNoZSA9IHRydWU7XG4gIH1cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gICAgdmFyIHJzdHlsZSA9IF9wLnJzdHlsZTsgLy8gYW4gZWRnZSBtYXkgYmUgaW1wbGljaXRseSBkaXJ0eSBiL2Mgb2Ygb25lIG9mIGl0cyBjb25uZWN0ZWQgbm9kZXNcbiAgICAvLyAoYW5kIGEgcmVxdWVzdCBmb3IgcmVjYWxjIG1heSBjb21lIGluIGJldHdlZW4gZnJhbWVzKVxuXG4gICAgaWYgKGVsZS5pc0VkZ2UoKSAmJiAoIWlzQ2xlYW5Db25uZWN0ZWQoZWxlLnNvdXJjZSgpKSB8fCAhaXNDbGVhbkNvbm5lY3RlZChlbGUudGFyZ2V0KCkpKSkge1xuICAgICAgcnN0eWxlLmNsZWFuID0gZmFsc2U7XG4gICAgfSAvLyBvbmx5IHVwZGF0ZSBpZiBkaXJ0eSBhbmQgaW4gZ3JhcGhcblxuXG4gICAgaWYgKHVzZUNhY2hlICYmIHJzdHlsZS5jbGVhbiB8fCBlbGUucmVtb3ZlZCgpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9IC8vIG9ubHkgdXBkYXRlIGlmIG5vdCBkaXNwbGF5OiBub25lXG5cblxuICAgIGlmIChlbGUucHN0eWxlKCdkaXNwbGF5JykudmFsdWUgPT09ICdub25lJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKF9wLmdyb3VwID09PSAnbm9kZXMnKSB7XG4gICAgICBub2Rlcy5wdXNoKGVsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGVkZ2VzXG4gICAgICBlZGdlcy5wdXNoKGVsZSk7XG4gICAgfVxuXG4gICAgcnN0eWxlLmNsZWFuID0gdHJ1ZTtcbiAgfSAvLyB1cGRhdGUgbm9kZSBkYXRhIGZyb20gcHJvamVjdGlvbnNcblxuXG4gIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IG5vZGVzLmxlbmd0aDsgX2kyKyspIHtcbiAgICB2YXIgX2VsZSA9IG5vZGVzW19pMl07XG4gICAgdmFyIF9wMiA9IF9lbGUuX3ByaXZhdGU7XG4gICAgdmFyIF9yc3R5bGUgPSBfcDIucnN0eWxlO1xuXG4gICAgdmFyIHBvcyA9IF9lbGUucG9zaXRpb24oKTtcblxuICAgIHRoaXMucmVjYWxjdWxhdGVOb2RlTGFiZWxQcm9qZWN0aW9uKF9lbGUpO1xuICAgIF9yc3R5bGUubm9kZVggPSBwb3MueDtcbiAgICBfcnN0eWxlLm5vZGVZID0gcG9zLnk7XG4gICAgX3JzdHlsZS5ub2RlVyA9IF9lbGUucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWU7XG4gICAgX3JzdHlsZS5ub2RlSCA9IF9lbGUucHN0eWxlKCdoZWlnaHQnKS5wZlZhbHVlO1xuICB9XG5cbiAgdGhpcy5yZWNhbGN1bGF0ZUVkZ2VQcm9qZWN0aW9ucyhlZGdlcyk7IC8vIHVwZGF0ZSBlZGdlIGRhdGEgZnJvbSBwcm9qZWN0aW9uc1xuXG4gIGZvciAodmFyIF9pMyA9IDA7IF9pMyA8IGVkZ2VzLmxlbmd0aDsgX2kzKyspIHtcbiAgICB2YXIgX2VsZTIgPSBlZGdlc1tfaTNdO1xuICAgIHZhciBfcDMgPSBfZWxlMi5fcHJpdmF0ZTtcbiAgICB2YXIgX3JzdHlsZTIgPSBfcDMucnN0eWxlO1xuICAgIHZhciBycyA9IF9wMy5yc2NyYXRjaDsgLy8gdXBkYXRlIHJzdHlsZSBwb3NpdGlvbnNcblxuICAgIF9yc3R5bGUyLnNyY1ggPSBycy5hcnJvd1N0YXJ0WDtcbiAgICBfcnN0eWxlMi5zcmNZID0gcnMuYXJyb3dTdGFydFk7XG4gICAgX3JzdHlsZTIudGd0WCA9IHJzLmFycm93RW5kWDtcbiAgICBfcnN0eWxlMi50Z3RZID0gcnMuYXJyb3dFbmRZO1xuICAgIF9yc3R5bGUyLm1pZFggPSBycy5taWRYO1xuICAgIF9yc3R5bGUyLm1pZFkgPSBycy5taWRZO1xuICAgIF9yc3R5bGUyLmxhYmVsQW5nbGUgPSBycy5sYWJlbEFuZ2xlO1xuICAgIF9yc3R5bGUyLnNvdXJjZUxhYmVsQW5nbGUgPSBycy5zb3VyY2VMYWJlbEFuZ2xlO1xuICAgIF9yc3R5bGUyLnRhcmdldExhYmVsQW5nbGUgPSBycy50YXJnZXRMYWJlbEFuZ2xlO1xuICB9XG59O1xuXG52YXIgQlJwJDkgPSB7fTtcblxuQlJwJDkudXBkYXRlQ2FjaGVkR3JhYmJlZEVsZXMgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBlbGVzID0gdGhpcy5jYWNoZWRaU29ydGVkRWxlcztcblxuICBpZiAoIWVsZXMpIHtcbiAgICAvLyBqdXN0IGxldCB0aGlzIGJlIHJlY2FsY3VsYXRlZCBvbiB0aGUgbmV4dCB6IHNvcnQgdGlja1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGVsZXMuZHJhZyA9IFtdO1xuICBlbGVzLm5vbmRyYWcgPSBbXTtcbiAgdmFyIGdyYWJUYXJnZXRzID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IGVsZXNbaV07XG4gICAgdmFyIHJzID0gZWxlLl9wcml2YXRlLnJzY3JhdGNoO1xuXG4gICAgaWYgKGVsZS5ncmFiYmVkKCkgJiYgIWVsZS5pc1BhcmVudCgpKSB7XG4gICAgICBncmFiVGFyZ2V0cy5wdXNoKGVsZSk7XG4gICAgfSBlbHNlIGlmIChycy5pbkRyYWdMYXllcikge1xuICAgICAgZWxlcy5kcmFnLnB1c2goZWxlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZWxlcy5ub25kcmFnLnB1c2goZWxlKTtcbiAgICB9XG4gIH0gLy8gcHV0IHRoZSBncmFiIHRhcmdldCBub2RlcyBsYXN0IHNvIGl0J3Mgb24gdG9wIG9mIGl0cyBuZWlnaGJvdXJob29kXG5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGdyYWJUYXJnZXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IGdyYWJUYXJnZXRzW2ldO1xuICAgIGVsZXMuZHJhZy5wdXNoKGVsZSk7XG4gIH1cbn07XG5cbkJScCQ5LmludmFsaWRhdGVDYWNoZWRaU29ydGVkRWxlcyA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5jYWNoZWRaU29ydGVkRWxlcyA9IG51bGw7XG59O1xuXG5CUnAkOS5nZXRDYWNoZWRaU29ydGVkRWxlcyA9IGZ1bmN0aW9uIChmb3JjZVJlY2FsYykge1xuICBpZiAoZm9yY2VSZWNhbGMgfHwgIXRoaXMuY2FjaGVkWlNvcnRlZEVsZXMpIHtcbiAgICB2YXIgZWxlcyA9IHRoaXMuY3kubXV0YWJsZUVsZW1lbnRzKCkudG9BcnJheSgpO1xuICAgIGVsZXMuc29ydCh6SW5kZXhTb3J0KTtcbiAgICBlbGVzLmludGVyYWN0aXZlID0gZWxlcy5maWx0ZXIoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgcmV0dXJuIGVsZS5pbnRlcmFjdGl2ZSgpO1xuICAgIH0pO1xuICAgIHRoaXMuY2FjaGVkWlNvcnRlZEVsZXMgPSBlbGVzO1xuICAgIHRoaXMudXBkYXRlQ2FjaGVkR3JhYmJlZEVsZXMoKTtcbiAgfSBlbHNlIHtcbiAgICBlbGVzID0gdGhpcy5jYWNoZWRaU29ydGVkRWxlcztcbiAgfVxuXG4gIHJldHVybiBlbGVzO1xufTtcblxudmFyIEJScCRhID0ge307XG5bQlJwJDEsIEJScCQyLCBCUnAkMywgQlJwJDQsIEJScCQ1LCBCUnAkNiwgQlJwJDcsIEJScCQ4LCBCUnAkOV0uZm9yRWFjaChmdW5jdGlvbiAocHJvcHMpIHtcbiAgZXh0ZW5kKEJScCRhLCBwcm9wcyk7XG59KTtcblxudmFyIEJScCRiID0ge307XG5cbkJScCRiLmdldENhY2hlZEltYWdlID0gZnVuY3Rpb24gKHVybCwgY3Jvc3NPcmlnaW4sIG9uTG9hZCkge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBpbWFnZUNhY2hlID0gci5pbWFnZUNhY2hlID0gci5pbWFnZUNhY2hlIHx8IHt9O1xuICB2YXIgY2FjaGUgPSBpbWFnZUNhY2hlW3VybF07XG5cbiAgaWYgKGNhY2hlKSB7XG4gICAgaWYgKCFjYWNoZS5pbWFnZS5jb21wbGV0ZSkge1xuICAgICAgY2FjaGUuaW1hZ2UuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIG9uTG9hZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNhY2hlLmltYWdlO1xuICB9IGVsc2Uge1xuICAgIGNhY2hlID0gaW1hZ2VDYWNoZVt1cmxdID0gaW1hZ2VDYWNoZVt1cmxdIHx8IHt9O1xuICAgIHZhciBpbWFnZSA9IGNhY2hlLmltYWdlID0gbmV3IEltYWdlKCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICAgIGltYWdlLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBvbkxvYWQpO1xuICAgIGltYWdlLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgZnVuY3Rpb24gKCkge1xuICAgICAgaW1hZ2UuZXJyb3IgPSB0cnVlO1xuICAgIH0pOyAvLyAjMTU4MiBzYWZhcmkgZG9lc24ndCBsb2FkIGRhdGEgdXJpcyB3aXRoIGNyb3NzT3JpZ2luIHByb3Blcmx5XG4gICAgLy8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTEyMzk3OFxuXG4gICAgdmFyIGRhdGFVcmlQcmVmaXggPSAnZGF0YTonO1xuICAgIHZhciBpc0RhdGFVcmkgPSB1cmwuc3Vic3RyaW5nKDAsIGRhdGFVcmlQcmVmaXgubGVuZ3RoKS50b0xvd2VyQ2FzZSgpID09PSBkYXRhVXJpUHJlZml4O1xuXG4gICAgaWYgKCFpc0RhdGFVcmkpIHtcbiAgICAgIGltYWdlLmNyb3NzT3JpZ2luID0gY3Jvc3NPcmlnaW47IC8vIHByZXZlbnQgdGFpbnRlZCBjYW52YXNcbiAgICB9XG5cbiAgICBpbWFnZS5zcmMgPSB1cmw7XG4gICAgcmV0dXJuIGltYWdlO1xuICB9XG59O1xuXG52YXIgQlJwJGMgPSB7fTtcbi8qIGdsb2JhbCBkb2N1bWVudCwgd2luZG93LCBSZXNpemVPYnNlcnZlciwgTXV0YXRpb25PYnNlcnZlciAqL1xuXG5CUnAkYy5yZWdpc3RlckJpbmRpbmcgPSBmdW5jdGlvbiAodGFyZ2V0LCBldmVudCwgaGFuZGxlciwgdXNlQ2FwdHVyZSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFyZ3VtZW50cywgWzFdKTsgLy8gY29weVxuXG4gIHZhciBiID0gdGhpcy5iaW5kZXIodGFyZ2V0KTtcbiAgcmV0dXJuIGIub24uYXBwbHkoYiwgYXJncyk7XG59O1xuXG5CUnAkYy5iaW5kZXIgPSBmdW5jdGlvbiAodGd0KSB7XG4gIHZhciByID0gdGhpcztcbiAgdmFyIHRndElzRG9tID0gdGd0ID09PSB3aW5kb3cgfHwgdGd0ID09PSBkb2N1bWVudCB8fCB0Z3QgPT09IGRvY3VtZW50LmJvZHkgfHwgZG9tRWxlbWVudCh0Z3QpO1xuXG4gIGlmIChyLnN1cHBvcnRzUGFzc2l2ZUV2ZW50cyA9PSBudWxsKSB7XG4gICAgLy8gZnJvbSBodHRwczovL2dpdGh1Yi5jb20vV0lDRy9FdmVudExpc3RlbmVyT3B0aW9ucy9ibG9iL2doLXBhZ2VzL2V4cGxhaW5lci5tZCNmZWF0dXJlLWRldGVjdGlvblxuICAgIHZhciBzdXBwb3J0c1Bhc3NpdmUgPSBmYWxzZTtcblxuICAgIHRyeSB7XG4gICAgICB2YXIgb3B0cyA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ3Bhc3NpdmUnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHN1cHBvcnRzUGFzc2l2ZSA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCBudWxsLCBvcHRzKTtcbiAgICB9IGNhdGNoIChlcnIpIHsvLyBub3Qgc3VwcG9ydGVkXG4gICAgfVxuXG4gICAgci5zdXBwb3J0c1Bhc3NpdmVFdmVudHMgPSBzdXBwb3J0c1Bhc3NpdmU7XG4gIH1cblxuICB2YXIgb24gPSBmdW5jdGlvbiBvbihldmVudCwgaGFuZGxlciwgdXNlQ2FwdHVyZSkge1xuICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblxuICAgIGlmICh0Z3RJc0RvbSAmJiByLnN1cHBvcnRzUGFzc2l2ZUV2ZW50cykge1xuICAgICAgLy8gcmVwbGFjZSB1c2VDYXB0dXJlIHcvIG9wdHMgb2JqXG4gICAgICBhcmdzWzJdID0ge1xuICAgICAgICBjYXB0dXJlOiB1c2VDYXB0dXJlICE9IG51bGwgPyB1c2VDYXB0dXJlIDogZmFsc2UsXG4gICAgICAgIHBhc3NpdmU6IGZhbHNlLFxuICAgICAgICBvbmNlOiBmYWxzZVxuICAgICAgfTtcbiAgICB9XG5cbiAgICByLmJpbmRpbmdzLnB1c2goe1xuICAgICAgdGFyZ2V0OiB0Z3QsXG4gICAgICBhcmdzOiBhcmdzXG4gICAgfSk7XG4gICAgKHRndC5hZGRFdmVudExpc3RlbmVyIHx8IHRndC5vbikuYXBwbHkodGd0LCBhcmdzKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG9uOiBvbixcbiAgICBhZGRFdmVudExpc3RlbmVyOiBvbixcbiAgICBhZGRMaXN0ZW5lcjogb24sXG4gICAgYmluZDogb25cbiAgfTtcbn07XG5cbkJScCRjLm5vZGVJc0RyYWdnYWJsZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gIHJldHVybiBub2RlICYmIG5vZGUuaXNOb2RlKCkgJiYgIW5vZGUubG9ja2VkKCkgJiYgbm9kZS5ncmFiYmFibGUoKTtcbn07XG5cbkJScCRjLm5vZGVJc0dyYWJiYWJsZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gIHJldHVybiB0aGlzLm5vZGVJc0RyYWdnYWJsZShub2RlKSAmJiBub2RlLmludGVyYWN0aXZlKCk7XG59O1xuXG5CUnAkYy5sb2FkID0gZnVuY3Rpb24gKCkge1xuICB2YXIgciA9IHRoaXM7XG5cbiAgdmFyIGlzU2VsZWN0ZWQgPSBmdW5jdGlvbiBpc1NlbGVjdGVkKGVsZSkge1xuICAgIHJldHVybiBlbGUuc2VsZWN0ZWQoKTtcbiAgfTtcblxuICB2YXIgdHJpZ2dlckV2ZW50cyA9IGZ1bmN0aW9uIHRyaWdnZXJFdmVudHModGFyZ2V0LCBuYW1lcywgZSwgcG9zaXRpb24pIHtcbiAgICBpZiAodGFyZ2V0ID09IG51bGwpIHtcbiAgICAgIHRhcmdldCA9IHIuY3k7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG5hbWUgPSBuYW1lc1tpXTtcbiAgICAgIHRhcmdldC5lbWl0KHtcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgdHlwZTogbmFtZSxcbiAgICAgICAgcG9zaXRpb246IHBvc2l0aW9uXG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGlzTXVsdFNlbEtleURvd24gPSBmdW5jdGlvbiBpc011bHRTZWxLZXlEb3duKGUpIHtcbiAgICByZXR1cm4gZS5zaGlmdEtleSB8fCBlLm1ldGFLZXkgfHwgZS5jdHJsS2V5OyAvLyBtYXliZSBlLmFsdEtleVxuICB9O1xuXG4gIHZhciBhbGxvd1Bhbm5pbmdQYXNzdGhyb3VnaCA9IGZ1bmN0aW9uIGFsbG93UGFubmluZ1Bhc3N0aHJvdWdoKGRvd24sIGRvd25zKSB7XG4gICAgdmFyIGFsbG93UGFzc3Rocm91Z2ggPSB0cnVlO1xuXG4gICAgaWYgKHIuY3kuaGFzQ29tcG91bmROb2RlcygpICYmIGRvd24gJiYgZG93bi5wYW5uYWJsZSgpKSB7XG4gICAgICAvLyBhIGdyYWJiYWJsZSBjb21wb3VuZCBub2RlIGJlbG93IHRoZSBlbGUgPT4gbm8gcGFzc3Rocm91Z2ggcGFubmluZ1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGRvd25zICYmIGkgPCBkb3ducy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZG93biA9IGRvd25zW2ldO1xuXG4gICAgICAgIGlmIChkb3duLmlzTm9kZSgpICYmIGRvd24uaXNQYXJlbnQoKSkge1xuICAgICAgICAgIGFsbG93UGFzc3Rocm91Z2ggPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBhbGxvd1Bhc3N0aHJvdWdoID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gYWxsb3dQYXNzdGhyb3VnaDtcbiAgfTtcblxuICB2YXIgc2V0R3JhYmJlZCA9IGZ1bmN0aW9uIHNldEdyYWJiZWQoZWxlKSB7XG4gICAgZWxlWzBdLl9wcml2YXRlLmdyYWJiZWQgPSB0cnVlO1xuICB9O1xuXG4gIHZhciBzZXRGcmVlZCA9IGZ1bmN0aW9uIHNldEZyZWVkKGVsZSkge1xuICAgIGVsZVswXS5fcHJpdmF0ZS5ncmFiYmVkID0gZmFsc2U7XG4gIH07XG5cbiAgdmFyIHNldEluRHJhZ0xheWVyID0gZnVuY3Rpb24gc2V0SW5EcmFnTGF5ZXIoZWxlKSB7XG4gICAgZWxlWzBdLl9wcml2YXRlLnJzY3JhdGNoLmluRHJhZ0xheWVyID0gdHJ1ZTtcbiAgfTtcblxuICB2YXIgc2V0T3V0RHJhZ0xheWVyID0gZnVuY3Rpb24gc2V0T3V0RHJhZ0xheWVyKGVsZSkge1xuICAgIGVsZVswXS5fcHJpdmF0ZS5yc2NyYXRjaC5pbkRyYWdMYXllciA9IGZhbHNlO1xuICB9O1xuXG4gIHZhciBzZXRHcmFiVGFyZ2V0ID0gZnVuY3Rpb24gc2V0R3JhYlRhcmdldChlbGUpIHtcbiAgICBlbGVbMF0uX3ByaXZhdGUucnNjcmF0Y2guaXNHcmFiVGFyZ2V0ID0gdHJ1ZTtcbiAgfTtcblxuICB2YXIgcmVtb3ZlR3JhYlRhcmdldCA9IGZ1bmN0aW9uIHJlbW92ZUdyYWJUYXJnZXQoZWxlKSB7XG4gICAgZWxlWzBdLl9wcml2YXRlLnJzY3JhdGNoLmlzR3JhYlRhcmdldCA9IGZhbHNlO1xuICB9O1xuXG4gIHZhciBhZGRUb0RyYWdMaXN0ID0gZnVuY3Rpb24gYWRkVG9EcmFnTGlzdChlbGUsIG9wdHMpIHtcbiAgICB2YXIgbGlzdCA9IG9wdHMuYWRkVG9MaXN0O1xuICAgIHZhciBsaXN0SGFzRWxlID0gbGlzdC5oYXMoZWxlKTtcblxuICAgIGlmICghbGlzdEhhc0VsZSkge1xuICAgICAgbGlzdC5tZXJnZShlbGUpO1xuICAgICAgc2V0R3JhYmJlZChlbGUpO1xuICAgIH1cbiAgfTsgLy8gaGVscGVyIGZ1bmN0aW9uIHRvIGRldGVybWluZSB3aGljaCBjaGlsZCBub2RlcyBhbmQgaW5uZXIgZWRnZXNcbiAgLy8gb2YgYSBjb21wb3VuZCBub2RlIHRvIGJlIGRyYWdnZWQgYXMgd2VsbCBhcyB0aGUgZ3JhYmJlZCBhbmQgc2VsZWN0ZWQgbm9kZXNcblxuXG4gIHZhciBhZGREZXNjZW5kYW50c1RvRHJhZyA9IGZ1bmN0aW9uIGFkZERlc2NlbmRhbnRzVG9EcmFnKG5vZGUsIG9wdHMpIHtcbiAgICBpZiAoIW5vZGUuY3koKS5oYXNDb21wb3VuZE5vZGVzKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5pbkRyYWdMYXllciA9PSBudWxsICYmIG9wdHMuYWRkVG9MaXN0ID09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9IC8vIG5vdGhpbmcgdG8gZG9cblxuXG4gICAgdmFyIGlubmVyTm9kZXMgPSBub2RlLmRlc2NlbmRhbnRzKCk7XG5cbiAgICBpZiAob3B0cy5pbkRyYWdMYXllcikge1xuICAgICAgaW5uZXJOb2Rlcy5mb3JFYWNoKHNldEluRHJhZ0xheWVyKTtcbiAgICAgIGlubmVyTm9kZXMuY29ubmVjdGVkRWRnZXMoKS5mb3JFYWNoKHNldEluRHJhZ0xheWVyKTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5hZGRUb0xpc3QpIHtcbiAgICAgIG9wdHMuYWRkVG9MaXN0LnVubWVyZ2UoaW5uZXJOb2Rlcyk7XG4gICAgfVxuICB9OyAvLyBhZGRzIHRoZSBnaXZlbiBub2RlcyBhbmQgaXRzIG5laWdoYm91cmhvb2QgdG8gdGhlIGRyYWcgbGF5ZXJcblxuXG4gIHZhciBhZGROb2Rlc1RvRHJhZyA9IGZ1bmN0aW9uIGFkZE5vZGVzVG9EcmFnKG5vZGVzLCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG4gICAgdmFyIGhhc0NvbXBvdW5kTm9kZXMgPSBub2Rlcy5jeSgpLmhhc0NvbXBvdW5kTm9kZXMoKTtcblxuICAgIGlmIChvcHRzLmluRHJhZ0xheWVyKSB7XG4gICAgICBub2Rlcy5mb3JFYWNoKHNldEluRHJhZ0xheWVyKTtcbiAgICAgIG5vZGVzLm5laWdoYm9yaG9vZCgpLnN0ZEZpbHRlcihmdW5jdGlvbiAoZWxlKSB7XG4gICAgICAgIHJldHVybiAhaGFzQ29tcG91bmROb2RlcyB8fCBlbGUuaXNFZGdlKCk7XG4gICAgICB9KS5mb3JFYWNoKHNldEluRHJhZ0xheWVyKTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5hZGRUb0xpc3QpIHtcbiAgICAgIG5vZGVzLmZvckVhY2goZnVuY3Rpb24gKGVsZSkge1xuICAgICAgICBhZGRUb0RyYWdMaXN0KGVsZSwgb3B0cyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBhZGREZXNjZW5kYW50c1RvRHJhZyhub2Rlcywgb3B0cyk7IC8vIGFsd2F5cyBhZGQgdG8gZHJhZ1xuICAgIC8vIGFsc28gYWRkIG5vZGVzIGFuZCBlZGdlcyByZWxhdGVkIHRvIHRoZSB0b3Btb3N0IGFuY2VzdG9yXG5cbiAgICB1cGRhdGVBbmNlc3RvcnNJbkRyYWdMYXllcihub2Rlcywge1xuICAgICAgaW5EcmFnTGF5ZXI6IG9wdHMuaW5EcmFnTGF5ZXJcbiAgICB9KTtcbiAgICByLnVwZGF0ZUNhY2hlZEdyYWJiZWRFbGVzKCk7XG4gIH07XG5cbiAgdmFyIGFkZE5vZGVUb0RyYWcgPSBhZGROb2Rlc1RvRHJhZztcblxuICB2YXIgZnJlZURyYWdnZWRFbGVtZW50cyA9IGZ1bmN0aW9uIGZyZWVEcmFnZ2VkRWxlbWVudHMoZ3JhYmJlZEVsZXMpIHtcbiAgICBpZiAoIWdyYWJiZWRFbGVzKSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyBqdXN0IGdvIG92ZXIgYWxsIGVsZW1lbnRzIHJhdGhlciB0aGFuIGRvaW5nIGEgYnVuY2ggb2YgKHBvc3NpYmx5IGV4cGVuc2l2ZSkgdHJhdmVyc2Fsc1xuXG5cbiAgICByLmdldENhY2hlZFpTb3J0ZWRFbGVzKCkuZm9yRWFjaChmdW5jdGlvbiAoZWxlKSB7XG4gICAgICBzZXRGcmVlZChlbGUpO1xuICAgICAgc2V0T3V0RHJhZ0xheWVyKGVsZSk7XG4gICAgICByZW1vdmVHcmFiVGFyZ2V0KGVsZSk7XG4gICAgfSk7XG4gICAgci51cGRhdGVDYWNoZWRHcmFiYmVkRWxlcygpO1xuICB9OyAvLyBoZWxwZXIgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIHdoaWNoIGFuY2VzdG9yIG5vZGVzIGFuZCBlZGdlcyBzaG91bGQgZ29cbiAgLy8gdG8gdGhlIGRyYWcgbGF5ZXIgKG9yIHNob3VsZCBiZSByZW1vdmVkIGZyb20gZHJhZyBsYXllcikuXG5cblxuICB2YXIgdXBkYXRlQW5jZXN0b3JzSW5EcmFnTGF5ZXIgPSBmdW5jdGlvbiB1cGRhdGVBbmNlc3RvcnNJbkRyYWdMYXllcihub2RlLCBvcHRzKSB7XG4gICAgaWYgKG9wdHMuaW5EcmFnTGF5ZXIgPT0gbnVsbCAmJiBvcHRzLmFkZFRvTGlzdCA9PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyBub3RoaW5nIHRvIGRvXG5cblxuICAgIGlmICghbm9kZS5jeSgpLmhhc0NvbXBvdW5kTm9kZXMoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gZmluZCB0b3AtbGV2ZWwgcGFyZW50XG5cblxuICAgIHZhciBwYXJlbnQgPSBub2RlLmFuY2VzdG9ycygpLm9ycGhhbnMoKTsgLy8gbm8gcGFyZW50IG5vZGU6IG5vIG5vZGVzIHRvIGFkZCB0byB0aGUgZHJhZyBsYXllclxuXG4gICAgaWYgKHBhcmVudC5zYW1lKG5vZGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG5vZGVzID0gcGFyZW50LmRlc2NlbmRhbnRzKCkuc3Bhd25TZWxmKCkubWVyZ2UocGFyZW50KS51bm1lcmdlKG5vZGUpLnVubWVyZ2Uobm9kZS5kZXNjZW5kYW50cygpKTtcbiAgICB2YXIgZWRnZXMgPSBub2Rlcy5jb25uZWN0ZWRFZGdlcygpO1xuXG4gICAgaWYgKG9wdHMuaW5EcmFnTGF5ZXIpIHtcbiAgICAgIGVkZ2VzLmZvckVhY2goc2V0SW5EcmFnTGF5ZXIpO1xuICAgICAgbm9kZXMuZm9yRWFjaChzZXRJbkRyYWdMYXllcik7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuYWRkVG9MaXN0KSB7XG4gICAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgICAgYWRkVG9EcmFnTGlzdChlbGUsIG9wdHMpO1xuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBibHVyQWN0aXZlRG9tRWxlbWVudCA9IGZ1bmN0aW9uIGJsdXJBY3RpdmVEb21FbGVtZW50KCkge1xuICAgIGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9IG51bGwgJiYgZG9jdW1lbnQuYWN0aXZlRWxlbWVudC5ibHVyICE9IG51bGwpIHtcbiAgICAgIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQuYmx1cigpO1xuICAgIH1cbiAgfTtcblxuICB2YXIgaGF2ZU11dGF0aW9uc0FwaSA9IHR5cGVvZiBNdXRhdGlvbk9ic2VydmVyICE9PSAndW5kZWZpbmVkJztcbiAgdmFyIGhhdmVSZXNpemVPYnNlcnZlckFwaSA9IHR5cGVvZiBSZXNpemVPYnNlcnZlciAhPT0gJ3VuZGVmaW5lZCc7IC8vIHdhdGNoIGZvciB3aGVuIHRoZSBjeSBjb250YWluZXIgaXMgcmVtb3ZlZCBmcm9tIHRoZSBkb21cblxuICBpZiAoaGF2ZU11dGF0aW9uc0FwaSkge1xuICAgIHIucmVtb3ZlT2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcihmdW5jdGlvbiAobXV0bnMpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbXV0bnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG11dG4gPSBtdXRuc1tpXTtcbiAgICAgICAgdmFyIHJOb2RlcyA9IG11dG4ucmVtb3ZlZE5vZGVzO1xuXG4gICAgICAgIGlmIChyTm9kZXMpIHtcbiAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJOb2Rlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIHJOb2RlID0gck5vZGVzW2pdO1xuXG4gICAgICAgICAgICBpZiAock5vZGUgPT09IHIuY29udGFpbmVyKSB7XG4gICAgICAgICAgICAgIHIuZGVzdHJveSgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChyLmNvbnRhaW5lci5wYXJlbnROb2RlKSB7XG4gICAgICByLnJlbW92ZU9ic2VydmVyLm9ic2VydmUoci5jb250YWluZXIucGFyZW50Tm9kZSwge1xuICAgICAgICBjaGlsZExpc3Q6IHRydWVcbiAgICAgIH0pO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByLnJlZ2lzdGVyQmluZGluZyhyLmNvbnRhaW5lciwgJ0RPTU5vZGVSZW1vdmVkJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgICAgIHIuZGVzdHJveSgpO1xuICAgIH0pO1xuICB9XG5cbiAgdmFyIG9uUmVzaXplID0gdXRpbChmdW5jdGlvbiAoKSB7XG4gICAgci5jeS5yZXNpemUoKTtcbiAgfSwgMTAwKTtcblxuICBpZiAoaGF2ZU11dGF0aW9uc0FwaSkge1xuICAgIHIuc3R5bGVPYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKG9uUmVzaXplKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gICAgci5zdHlsZU9ic2VydmVyLm9ic2VydmUoci5jb250YWluZXIsIHtcbiAgICAgIGF0dHJpYnV0ZXM6IHRydWVcbiAgICB9KTtcbiAgfSAvLyBhdXRvIHJlc2l6ZVxuXG5cbiAgci5yZWdpc3RlckJpbmRpbmcod2luZG93LCAncmVzaXplJywgb25SZXNpemUpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgaWYgKGhhdmVSZXNpemVPYnNlcnZlckFwaSkge1xuICAgIHIucmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIob25SZXNpemUpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgICByLnJlc2l6ZU9ic2VydmVyLm9ic2VydmUoci5jb250YWluZXIpO1xuICB9XG5cbiAgdmFyIGZvckVhY2hVcCA9IGZ1bmN0aW9uIGZvckVhY2hVcChkb21FbGUsIGZuKSB7XG4gICAgd2hpbGUgKGRvbUVsZSAhPSBudWxsKSB7XG4gICAgICBmbihkb21FbGUpO1xuICAgICAgZG9tRWxlID0gZG9tRWxlLnBhcmVudE5vZGU7XG4gICAgfVxuICB9O1xuXG4gIHZhciBpbnZhbGlkYXRlQ29vcmRzID0gZnVuY3Rpb24gaW52YWxpZGF0ZUNvb3JkcygpIHtcbiAgICByLmludmFsaWRhdGVDb250YWluZXJDbGllbnRDb29yZHNDYWNoZSgpO1xuICB9O1xuXG4gIGZvckVhY2hVcChyLmNvbnRhaW5lciwgZnVuY3Rpb24gKGRvbUVsZSkge1xuICAgIHIucmVnaXN0ZXJCaW5kaW5nKGRvbUVsZSwgJ3RyYW5zaXRpb25lbmQnLCBpbnZhbGlkYXRlQ29vcmRzKTtcbiAgICByLnJlZ2lzdGVyQmluZGluZyhkb21FbGUsICdhbmltYXRpb25lbmQnLCBpbnZhbGlkYXRlQ29vcmRzKTtcbiAgICByLnJlZ2lzdGVyQmluZGluZyhkb21FbGUsICdzY3JvbGwnLCBpbnZhbGlkYXRlQ29vcmRzKTtcbiAgfSk7IC8vIHN0b3AgcmlnaHQgY2xpY2sgbWVudSBmcm9tIGFwcGVhcmluZyBvbiBjeVxuXG4gIHIucmVnaXN0ZXJCaW5kaW5nKHIuY29udGFpbmVyLCAnY29udGV4dG1lbnUnLCBmdW5jdGlvbiAoZSkge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgfSk7XG5cbiAgdmFyIGluQm94U2VsZWN0aW9uID0gZnVuY3Rpb24gaW5Cb3hTZWxlY3Rpb24oKSB7XG4gICAgcmV0dXJuIHIuc2VsZWN0aW9uWzRdICE9PSAwO1xuICB9O1xuXG4gIHZhciBldmVudEluQ29udGFpbmVyID0gZnVuY3Rpb24gZXZlbnRJbkNvbnRhaW5lcihlKSB7XG4gICAgLy8gc2F2ZSBjeWNsZXMgaWYgbW91c2UgZXZlbnRzIGFyZW4ndCB0byBiZSBjYXB0dXJlZFxuICAgIHZhciBjb250YWluZXJQYWdlQ29vcmRzID0gci5maW5kQ29udGFpbmVyQ2xpZW50Q29vcmRzKCk7XG4gICAgdmFyIHggPSBjb250YWluZXJQYWdlQ29vcmRzWzBdO1xuICAgIHZhciB5ID0gY29udGFpbmVyUGFnZUNvb3Jkc1sxXTtcbiAgICB2YXIgd2lkdGggPSBjb250YWluZXJQYWdlQ29vcmRzWzJdO1xuICAgIHZhciBoZWlnaHQgPSBjb250YWluZXJQYWdlQ29vcmRzWzNdO1xuICAgIHZhciBwb3NpdGlvbnMgPSBlLnRvdWNoZXMgPyBlLnRvdWNoZXMgOiBbZV07XG4gICAgdmFyIGF0TGVhc3RPbmVQb3NJbnNpZGUgPSBmYWxzZTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcCA9IHBvc2l0aW9uc1tpXTtcblxuICAgICAgaWYgKHggPD0gcC5jbGllbnRYICYmIHAuY2xpZW50WCA8PSB4ICsgd2lkdGggJiYgeSA8PSBwLmNsaWVudFkgJiYgcC5jbGllbnRZIDw9IHkgKyBoZWlnaHQpIHtcbiAgICAgICAgYXRMZWFzdE9uZVBvc0luc2lkZSA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghYXRMZWFzdE9uZVBvc0luc2lkZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBjb250YWluZXIgPSByLmNvbnRhaW5lcjtcbiAgICB2YXIgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgdmFyIHRQYXJlbnQgPSB0YXJnZXQucGFyZW50Tm9kZTtcbiAgICB2YXIgY29udGFpbmVySXNUYXJnZXQgPSBmYWxzZTtcblxuICAgIHdoaWxlICh0UGFyZW50KSB7XG4gICAgICBpZiAodFBhcmVudCA9PT0gY29udGFpbmVyKSB7XG4gICAgICAgIGNvbnRhaW5lcklzVGFyZ2V0ID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIHRQYXJlbnQgPSB0UGFyZW50LnBhcmVudE5vZGU7XG4gICAgfVxuXG4gICAgaWYgKCFjb250YWluZXJJc1RhcmdldCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gLy8gaWYgdGFyZ2V0IGlzIG91dGlzZGUgY3kgY29udGFpbmVyLCB0aGVuIHRoaXMgZXZlbnQgaXMgbm90IGZvciB1c1xuXG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTsgLy8gUHJpbWFyeSBrZXlcblxuXG4gIHIucmVnaXN0ZXJCaW5kaW5nKHIuY29udGFpbmVyLCAnbW91c2Vkb3duJywgZnVuY3Rpb24gbW91c2Vkb3duSGFuZGxlcihlKSB7XG4gICAgaWYgKCFldmVudEluQ29udGFpbmVyKGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGJsdXJBY3RpdmVEb21FbGVtZW50KCk7XG4gICAgci5ob3ZlckRhdGEuY2FwdHVyZSA9IHRydWU7XG4gICAgci5ob3ZlckRhdGEud2hpY2ggPSBlLndoaWNoO1xuICAgIHZhciBjeSA9IHIuY3k7XG4gICAgdmFyIGdwb3MgPSBbZS5jbGllbnRYLCBlLmNsaWVudFldO1xuICAgIHZhciBwb3MgPSByLnByb2plY3RJbnRvVmlld3BvcnQoZ3Bvc1swXSwgZ3Bvc1sxXSk7XG4gICAgdmFyIHNlbGVjdCA9IHIuc2VsZWN0aW9uO1xuICAgIHZhciBuZWFycyA9IHIuZmluZE5lYXJlc3RFbGVtZW50cyhwb3NbMF0sIHBvc1sxXSwgdHJ1ZSwgZmFsc2UpO1xuICAgIHZhciBuZWFyID0gbmVhcnNbMF07XG4gICAgdmFyIGRyYWdnZWRFbGVtZW50cyA9IHIuZHJhZ0RhdGEucG9zc2libGVEcmFnRWxlbWVudHM7XG4gICAgci5ob3ZlckRhdGEubWRvd25Qb3MgPSBwb3M7XG4gICAgci5ob3ZlckRhdGEubWRvd25HUG9zID0gZ3BvcztcblxuICAgIHZhciBjaGVja0ZvclRhcGhvbGQgPSBmdW5jdGlvbiBjaGVja0ZvclRhcGhvbGQoKSB7XG4gICAgICByLmhvdmVyRGF0YS50YXBob2xkQ2FuY2VsbGVkID0gZmFsc2U7XG4gICAgICBjbGVhclRpbWVvdXQoci5ob3ZlckRhdGEudGFwaG9sZFRpbWVvdXQpO1xuICAgICAgci5ob3ZlckRhdGEudGFwaG9sZFRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHIuaG92ZXJEYXRhLnRhcGhvbGRDYW5jZWxsZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIGVsZSA9IHIuaG92ZXJEYXRhLmRvd247XG5cbiAgICAgICAgICBpZiAoZWxlKSB7XG4gICAgICAgICAgICBlbGUuZW1pdCh7XG4gICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGUsXG4gICAgICAgICAgICAgIHR5cGU6ICd0YXBob2xkJyxcbiAgICAgICAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgICAgICAgICAgeTogcG9zWzFdXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjeS5lbWl0KHtcbiAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICAgICAgdHlwZTogJ3RhcGhvbGQnLFxuICAgICAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgIHg6IHBvc1swXSxcbiAgICAgICAgICAgICAgICB5OiBwb3NbMV1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LCByLnRhcGhvbGREdXJhdGlvbik7XG4gICAgfTsgLy8gUmlnaHQgY2xpY2sgYnV0dG9uXG5cblxuICAgIGlmIChlLndoaWNoID09IDMpIHtcbiAgICAgIHIuaG92ZXJEYXRhLmN4dFN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgdmFyIGN4dEV2dCA9IHtcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgdHlwZTogJ2N4dHRhcHN0YXJ0JyxcbiAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgICAgeTogcG9zWzFdXG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmIChuZWFyKSB7XG4gICAgICAgIG5lYXIuYWN0aXZhdGUoKTtcbiAgICAgICAgbmVhci5lbWl0KGN4dEV2dCk7XG4gICAgICAgIHIuaG92ZXJEYXRhLmRvd24gPSBuZWFyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3kuZW1pdChjeHRFdnQpO1xuICAgICAgfVxuXG4gICAgICByLmhvdmVyRGF0YS5kb3duVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgci5ob3ZlckRhdGEuY3h0RHJhZ2dlZCA9IGZhbHNlOyAvLyBQcmltYXJ5IGJ1dHRvblxuICAgIH0gZWxzZSBpZiAoZS53aGljaCA9PSAxKSB7XG4gICAgICBpZiAobmVhcikge1xuICAgICAgICBuZWFyLmFjdGl2YXRlKCk7XG4gICAgICB9IC8vIEVsZW1lbnQgZHJhZ2dpbmdcblxuXG4gICAgICB7XG4gICAgICAgIC8vIElmIHNvbWV0aGluZyBpcyB1bmRlciB0aGUgY3Vyc29yIGFuZCBpdCBpcyBkcmFnZ2FibGUsIHByZXBhcmUgdG8gZ3JhYiBpdFxuICAgICAgICBpZiAobmVhciAhPSBudWxsKSB7XG4gICAgICAgICAgaWYgKHIubm9kZUlzR3JhYmJhYmxlKG5lYXIpKSB7XG4gICAgICAgICAgICB2YXIgbWFrZUV2ZW50ID0gZnVuY3Rpb24gbWFrZUV2ZW50KHR5cGUpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgICAgICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgICAgICAgIHg6IHBvc1swXSxcbiAgICAgICAgICAgICAgICAgIHk6IHBvc1sxXVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHZhciB0cmlnZ2VyR3JhYiA9IGZ1bmN0aW9uIHRyaWdnZXJHcmFiKGVsZSkge1xuICAgICAgICAgICAgICBlbGUuZW1pdChtYWtlRXZlbnQoJ2dyYWInKSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBzZXRHcmFiVGFyZ2V0KG5lYXIpO1xuXG4gICAgICAgICAgICBpZiAoIW5lYXIuc2VsZWN0ZWQoKSkge1xuICAgICAgICAgICAgICBkcmFnZ2VkRWxlbWVudHMgPSByLmRyYWdEYXRhLnBvc3NpYmxlRHJhZ0VsZW1lbnRzID0gY3kuY29sbGVjdGlvbigpO1xuICAgICAgICAgICAgICBhZGROb2RlVG9EcmFnKG5lYXIsIHtcbiAgICAgICAgICAgICAgICBhZGRUb0xpc3Q6IGRyYWdnZWRFbGVtZW50c1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgbmVhci5lbWl0KG1ha2VFdmVudCgnZ3JhYm9uJykpLmVtaXQobWFrZUV2ZW50KCdncmFiJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZHJhZ2dlZEVsZW1lbnRzID0gci5kcmFnRGF0YS5wb3NzaWJsZURyYWdFbGVtZW50cyA9IGN5LmNvbGxlY3Rpb24oKTtcbiAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkTm9kZXMgPSBjeS4kKGZ1bmN0aW9uIChlbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZWxlLmlzTm9kZSgpICYmIGVsZS5zZWxlY3RlZCgpICYmIHIubm9kZUlzR3JhYmJhYmxlKGVsZSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBhZGROb2Rlc1RvRHJhZyhzZWxlY3RlZE5vZGVzLCB7XG4gICAgICAgICAgICAgICAgYWRkVG9MaXN0OiBkcmFnZ2VkRWxlbWVudHNcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIG5lYXIuZW1pdChtYWtlRXZlbnQoJ2dyYWJvbicpKTtcbiAgICAgICAgICAgICAgc2VsZWN0ZWROb2Rlcy5mb3JFYWNoKHRyaWdnZXJHcmFiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgci5yZWRyYXdIaW50KCdlbGVzJywgdHJ1ZSk7XG4gICAgICAgICAgICByLnJlZHJhd0hpbnQoJ2RyYWcnLCB0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByLmhvdmVyRGF0YS5kb3duID0gbmVhcjtcbiAgICAgICAgci5ob3ZlckRhdGEuZG93bnMgPSBuZWFycztcbiAgICAgICAgci5ob3ZlckRhdGEuZG93blRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgIH1cbiAgICAgIHRyaWdnZXJFdmVudHMobmVhciwgWydtb3VzZWRvd24nLCAndGFwc3RhcnQnLCAndm1vdXNlZG93biddLCBlLCB7XG4gICAgICAgIHg6IHBvc1swXSxcbiAgICAgICAgeTogcG9zWzFdXG4gICAgICB9KTtcblxuICAgICAgaWYgKG5lYXIgPT0gbnVsbCkge1xuICAgICAgICBzZWxlY3RbNF0gPSAxO1xuICAgICAgICByLmRhdGEuYmdBY3RpdmVQb3Npc3Rpb24gPSB7XG4gICAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICAgIHk6IHBvc1sxXVxuICAgICAgICB9O1xuICAgICAgICByLnJlZHJhd0hpbnQoJ3NlbGVjdCcsIHRydWUpO1xuICAgICAgICByLnJlZHJhdygpO1xuICAgICAgfSBlbHNlIGlmIChuZWFyLnBhbm5hYmxlKCkpIHtcbiAgICAgICAgc2VsZWN0WzRdID0gMTsgLy8gZm9yIGZ1dHVyZSBwYW5cbiAgICAgIH1cblxuICAgICAgY2hlY2tGb3JUYXBob2xkKCk7XG4gICAgfSAvLyBJbml0aWFsaXplIHNlbGVjdGlvbiBib3ggY29vcmRpbmF0ZXNcblxuXG4gICAgc2VsZWN0WzBdID0gc2VsZWN0WzJdID0gcG9zWzBdO1xuICAgIHNlbGVjdFsxXSA9IHNlbGVjdFszXSA9IHBvc1sxXTtcbiAgfSwgZmFsc2UpO1xuICByLnJlZ2lzdGVyQmluZGluZyh3aW5kb3csICdtb3VzZW1vdmUnLCBmdW5jdGlvbiBtb3VzZW1vdmVIYW5kbGVyKGUpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4gICAgdmFyIGNhcHR1cmUgPSByLmhvdmVyRGF0YS5jYXB0dXJlO1xuXG4gICAgaWYgKCFjYXB0dXJlICYmICFldmVudEluQ29udGFpbmVyKGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHByZXZlbnREZWZhdWx0ID0gZmFsc2U7XG4gICAgdmFyIGN5ID0gci5jeTtcbiAgICB2YXIgem9vbSA9IGN5Lnpvb20oKTtcbiAgICB2YXIgZ3BvcyA9IFtlLmNsaWVudFgsIGUuY2xpZW50WV07XG4gICAgdmFyIHBvcyA9IHIucHJvamVjdEludG9WaWV3cG9ydChncG9zWzBdLCBncG9zWzFdKTtcbiAgICB2YXIgbWRvd25Qb3MgPSByLmhvdmVyRGF0YS5tZG93blBvcztcbiAgICB2YXIgbWRvd25HUG9zID0gci5ob3ZlckRhdGEubWRvd25HUG9zO1xuICAgIHZhciBzZWxlY3QgPSByLnNlbGVjdGlvbjtcbiAgICB2YXIgbmVhciA9IG51bGw7XG5cbiAgICBpZiAoIXIuaG92ZXJEYXRhLmRyYWdnaW5nRWxlcyAmJiAhci5ob3ZlckRhdGEuZHJhZ2dpbmcgJiYgIXIuaG92ZXJEYXRhLnNlbGVjdGluZykge1xuICAgICAgbmVhciA9IHIuZmluZE5lYXJlc3RFbGVtZW50KHBvc1swXSwgcG9zWzFdLCB0cnVlLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgdmFyIGxhc3QgPSByLmhvdmVyRGF0YS5sYXN0O1xuICAgIHZhciBkb3duID0gci5ob3ZlckRhdGEuZG93bjtcbiAgICB2YXIgZGlzcCA9IFtwb3NbMF0gLSBzZWxlY3RbMl0sIHBvc1sxXSAtIHNlbGVjdFszXV07XG4gICAgdmFyIGRyYWdnZWRFbGVtZW50cyA9IHIuZHJhZ0RhdGEucG9zc2libGVEcmFnRWxlbWVudHM7XG4gICAgdmFyIGlzT3ZlclRocmVzaG9sZERyYWc7XG5cbiAgICBpZiAobWRvd25HUG9zKSB7XG4gICAgICB2YXIgZHggPSBncG9zWzBdIC0gbWRvd25HUG9zWzBdO1xuICAgICAgdmFyIGR4MiA9IGR4ICogZHg7XG4gICAgICB2YXIgZHkgPSBncG9zWzFdIC0gbWRvd25HUG9zWzFdO1xuICAgICAgdmFyIGR5MiA9IGR5ICogZHk7XG4gICAgICB2YXIgZGlzdDIgPSBkeDIgKyBkeTI7XG4gICAgICByLmhvdmVyRGF0YS5pc092ZXJUaHJlc2hvbGREcmFnID0gaXNPdmVyVGhyZXNob2xkRHJhZyA9IGRpc3QyID49IHIuZGVza3RvcFRhcFRocmVzaG9sZDI7XG4gICAgfVxuXG4gICAgdmFyIG11bHRTZWxLZXlEb3duID0gaXNNdWx0U2VsS2V5RG93bihlKTtcblxuICAgIGlmIChpc092ZXJUaHJlc2hvbGREcmFnKSB7XG4gICAgICByLmhvdmVyRGF0YS50YXBob2xkQ2FuY2VsbGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgdXBkYXRlRHJhZ0RlbHRhID0gZnVuY3Rpb24gdXBkYXRlRHJhZ0RlbHRhKCkge1xuICAgICAgdmFyIGRyYWdEZWx0YSA9IHIuaG92ZXJEYXRhLmRyYWdEZWx0YSA9IHIuaG92ZXJEYXRhLmRyYWdEZWx0YSB8fCBbXTtcblxuICAgICAgaWYgKGRyYWdEZWx0YS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZHJhZ0RlbHRhLnB1c2goZGlzcFswXSk7XG4gICAgICAgIGRyYWdEZWx0YS5wdXNoKGRpc3BbMV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZHJhZ0RlbHRhWzBdICs9IGRpc3BbMF07XG4gICAgICAgIGRyYWdEZWx0YVsxXSArPSBkaXNwWzFdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBwcmV2ZW50RGVmYXVsdCA9IHRydWU7XG4gICAgdHJpZ2dlckV2ZW50cyhuZWFyLCBbJ21vdXNlbW92ZScsICd2bW91c2Vtb3ZlJywgJ3RhcGRyYWcnXSwgZSwge1xuICAgICAgeDogcG9zWzBdLFxuICAgICAgeTogcG9zWzFdXG4gICAgfSk7XG5cbiAgICB2YXIgZ29JbnRvQm94TW9kZSA9IGZ1bmN0aW9uIGdvSW50b0JveE1vZGUoKSB7XG4gICAgICByLmRhdGEuYmdBY3RpdmVQb3Npc3Rpb24gPSB1bmRlZmluZWQ7XG5cbiAgICAgIGlmICghci5ob3ZlckRhdGEuc2VsZWN0aW5nKSB7XG4gICAgICAgIGN5LmVtaXQoe1xuICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGUsXG4gICAgICAgICAgdHlwZTogJ2JveHN0YXJ0JyxcbiAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICAgICAgeTogcG9zWzFdXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgc2VsZWN0WzRdID0gMTtcbiAgICAgIHIuaG92ZXJEYXRhLnNlbGVjdGluZyA9IHRydWU7XG4gICAgICByLnJlZHJhd0hpbnQoJ3NlbGVjdCcsIHRydWUpO1xuICAgICAgci5yZWRyYXcoKTtcbiAgICB9OyAvLyB0cmlnZ2VyIGNvbnRleHQgZHJhZyBpZiBybW91c2UgZG93blxuXG5cbiAgICBpZiAoci5ob3ZlckRhdGEud2hpY2ggPT09IDMpIHtcbiAgICAgIC8vIGJ1dCBvbmx5IGlmIG92ZXIgdGhyZXNob2xkXG4gICAgICBpZiAoaXNPdmVyVGhyZXNob2xkRHJhZykge1xuICAgICAgICB2YXIgY3h0RXZ0ID0ge1xuICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGUsXG4gICAgICAgICAgdHlwZTogJ2N4dGRyYWcnLFxuICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgICAgICB5OiBwb3NbMV1cbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGRvd24pIHtcbiAgICAgICAgICBkb3duLmVtaXQoY3h0RXZ0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjeS5lbWl0KGN4dEV2dCk7XG4gICAgICAgIH1cblxuICAgICAgICByLmhvdmVyRGF0YS5jeHREcmFnZ2VkID0gdHJ1ZTtcblxuICAgICAgICBpZiAoIXIuaG92ZXJEYXRhLmN4dE92ZXIgfHwgbmVhciAhPT0gci5ob3ZlckRhdGEuY3h0T3Zlcikge1xuICAgICAgICAgIGlmIChyLmhvdmVyRGF0YS5jeHRPdmVyKSB7XG4gICAgICAgICAgICByLmhvdmVyRGF0YS5jeHRPdmVyLmVtaXQoe1xuICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgICAgICAgICB0eXBlOiAnY3h0ZHJhZ291dCcsXG4gICAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICAgICAgICAgIHk6IHBvc1sxXVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByLmhvdmVyRGF0YS5jeHRPdmVyID0gbmVhcjtcblxuICAgICAgICAgIGlmIChuZWFyKSB7XG4gICAgICAgICAgICBuZWFyLmVtaXQoe1xuICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgICAgICAgICB0eXBlOiAnY3h0ZHJhZ292ZXInLFxuICAgICAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgIHg6IHBvc1swXSxcbiAgICAgICAgICAgICAgICB5OiBwb3NbMV1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IC8vIENoZWNrIGlmIHdlIGFyZSBkcmFnIHBhbm5pbmcgdGhlIGVudGlyZSBncmFwaFxuXG4gICAgfSBlbHNlIGlmIChyLmhvdmVyRGF0YS5kcmFnZ2luZykge1xuICAgICAgcHJldmVudERlZmF1bHQgPSB0cnVlO1xuXG4gICAgICBpZiAoY3kucGFubmluZ0VuYWJsZWQoKSAmJiBjeS51c2VyUGFubmluZ0VuYWJsZWQoKSkge1xuICAgICAgICB2YXIgZGVsdGFQO1xuXG4gICAgICAgIGlmIChyLmhvdmVyRGF0YS5qdXN0U3RhcnRlZFBhbikge1xuICAgICAgICAgIHZhciBtZFBvcyA9IHIuaG92ZXJEYXRhLm1kb3duUG9zO1xuICAgICAgICAgIGRlbHRhUCA9IHtcbiAgICAgICAgICAgIHg6IChwb3NbMF0gLSBtZFBvc1swXSkgKiB6b29tLFxuICAgICAgICAgICAgeTogKHBvc1sxXSAtIG1kUG9zWzFdKSAqIHpvb21cbiAgICAgICAgICB9O1xuICAgICAgICAgIHIuaG92ZXJEYXRhLmp1c3RTdGFydGVkUGFuID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGVsdGFQID0ge1xuICAgICAgICAgICAgeDogZGlzcFswXSAqIHpvb20sXG4gICAgICAgICAgICB5OiBkaXNwWzFdICogem9vbVxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBjeS5wYW5CeShkZWx0YVApO1xuICAgICAgICByLmhvdmVyRGF0YS5kcmFnZ2VkID0gdHJ1ZTtcbiAgICAgIH0gLy8gTmVlZHMgcmVwcm9qZWN0IGR1ZSB0byBwYW4gY2hhbmdpbmcgdmlld3BvcnRcblxuXG4gICAgICBwb3MgPSByLnByb2plY3RJbnRvVmlld3BvcnQoZS5jbGllbnRYLCBlLmNsaWVudFkpOyAvLyBDaGVja3MgcHJpbWFyeSBidXR0b24gZG93biAmIG91dCBvZiB0aW1lICYgbW91c2Ugbm90IG1vdmVkIG11Y2hcbiAgICB9IGVsc2UgaWYgKHNlbGVjdFs0XSA9PSAxICYmIChkb3duID09IG51bGwgfHwgZG93bi5wYW5uYWJsZSgpKSkge1xuICAgICAgaWYgKGlzT3ZlclRocmVzaG9sZERyYWcpIHtcbiAgICAgICAgaWYgKCFyLmhvdmVyRGF0YS5kcmFnZ2luZyAmJiBjeS5ib3hTZWxlY3Rpb25FbmFibGVkKCkgJiYgKG11bHRTZWxLZXlEb3duIHx8ICFjeS5wYW5uaW5nRW5hYmxlZCgpIHx8ICFjeS51c2VyUGFubmluZ0VuYWJsZWQoKSkpIHtcbiAgICAgICAgICBnb0ludG9Cb3hNb2RlKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXIuaG92ZXJEYXRhLnNlbGVjdGluZyAmJiBjeS5wYW5uaW5nRW5hYmxlZCgpICYmIGN5LnVzZXJQYW5uaW5nRW5hYmxlZCgpKSB7XG4gICAgICAgICAgdmFyIGFsbG93UGFzc3Rocm91Z2ggPSBhbGxvd1Bhbm5pbmdQYXNzdGhyb3VnaChkb3duLCByLmhvdmVyRGF0YS5kb3ducyk7XG5cbiAgICAgICAgICBpZiAoYWxsb3dQYXNzdGhyb3VnaCkge1xuICAgICAgICAgICAgci5ob3ZlckRhdGEuZHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICAgICAgci5ob3ZlckRhdGEuanVzdFN0YXJ0ZWRQYW4gPSB0cnVlO1xuICAgICAgICAgICAgc2VsZWN0WzRdID0gMDtcbiAgICAgICAgICAgIHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbiA9IGFycmF5MnBvaW50KG1kb3duUG9zKTtcbiAgICAgICAgICAgIHIucmVkcmF3SGludCgnc2VsZWN0JywgdHJ1ZSk7XG4gICAgICAgICAgICByLnJlZHJhdygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkb3duICYmIGRvd24ucGFubmFibGUoKSAmJiBkb3duLmFjdGl2ZSgpKSB7XG4gICAgICAgICAgZG93bi51bmFjdGl2YXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRvd24gJiYgZG93bi5wYW5uYWJsZSgpICYmIGRvd24uYWN0aXZlKCkpIHtcbiAgICAgICAgZG93bi51bmFjdGl2YXRlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICgoIWRvd24gfHwgIWRvd24uZ3JhYmJlZCgpKSAmJiBuZWFyICE9IGxhc3QpIHtcbiAgICAgICAgaWYgKGxhc3QpIHtcbiAgICAgICAgICB0cmlnZ2VyRXZlbnRzKGxhc3QsIFsnbW91c2VvdXQnLCAndGFwZHJhZ291dCddLCBlLCB7XG4gICAgICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgICAgICB5OiBwb3NbMV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZWFyKSB7XG4gICAgICAgICAgdHJpZ2dlckV2ZW50cyhuZWFyLCBbJ21vdXNlb3ZlcicsICd0YXBkcmFnb3ZlciddLCBlLCB7XG4gICAgICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgICAgICB5OiBwb3NbMV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHIuaG92ZXJEYXRhLmxhc3QgPSBuZWFyO1xuICAgICAgfVxuXG4gICAgICBpZiAoZG93bikge1xuICAgICAgICBpZiAoaXNPdmVyVGhyZXNob2xkRHJhZykge1xuICAgICAgICAgIC8vIHRoZW4gd2UgY2FuIHRha2UgYWN0aW9uXG4gICAgICAgICAgaWYgKGN5LmJveFNlbGVjdGlvbkVuYWJsZWQoKSAmJiBtdWx0U2VsS2V5RG93bikge1xuICAgICAgICAgICAgLy8gdGhlbiBzZWxlY3Rpb24gb3ZlcnJpZGVzXG4gICAgICAgICAgICBpZiAoZG93biAmJiBkb3duLmdyYWJiZWQoKSkge1xuICAgICAgICAgICAgICBmcmVlRHJhZ2dlZEVsZW1lbnRzKGRyYWdnZWRFbGVtZW50cyk7XG4gICAgICAgICAgICAgIGRvd24uZW1pdCgnZnJlZW9uJyk7XG4gICAgICAgICAgICAgIGRyYWdnZWRFbGVtZW50cy5lbWl0KCdmcmVlJyk7XG5cbiAgICAgICAgICAgICAgaWYgKHIuZHJhZ0RhdGEuZGlkRHJhZykge1xuICAgICAgICAgICAgICAgIGRvd24uZW1pdCgnZHJhZ2ZyZWVvbicpO1xuICAgICAgICAgICAgICAgIGRyYWdnZWRFbGVtZW50cy5lbWl0KCdkcmFnZnJlZScpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdvSW50b0JveE1vZGUoKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGRvd24gJiYgZG93bi5ncmFiYmVkKCkgJiYgci5ub2RlSXNEcmFnZ2FibGUoZG93bikpIHtcbiAgICAgICAgICAgIC8vIGRyYWcgbm9kZVxuICAgICAgICAgICAgdmFyIGp1c3RTdGFydGVkRHJhZyA9ICFyLmRyYWdEYXRhLmRpZERyYWc7XG5cbiAgICAgICAgICAgIGlmIChqdXN0U3RhcnRlZERyYWcpIHtcbiAgICAgICAgICAgICAgci5yZWRyYXdIaW50KCdlbGVzJywgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHIuZHJhZ0RhdGEuZGlkRHJhZyA9IHRydWU7IC8vIGluZGljYXRlIHRoYXQgd2UgYWN0dWFsbHkgZGlkIGRyYWcgdGhlIG5vZGVcblxuICAgICAgICAgICAgdmFyIHRvVHJpZ2dlciA9IGN5LmNvbGxlY3Rpb24oKTsgLy8gbm93LCBhZGQgdGhlIGVsZW1lbnRzIHRvIHRoZSBkcmFnIGxheWVyIGlmIG5vdCBkb25lIGFscmVhZHlcblxuICAgICAgICAgICAgaWYgKCFyLmhvdmVyRGF0YS5kcmFnZ2luZ0VsZXMpIHtcbiAgICAgICAgICAgICAgYWRkTm9kZXNUb0RyYWcoZHJhZ2dlZEVsZW1lbnRzLCB7XG4gICAgICAgICAgICAgICAgaW5EcmFnTGF5ZXI6IHRydWVcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB0b3RhbFNoaWZ0ID0ge1xuICAgICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgICB5OiAwXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAobnVtYmVyKGRpc3BbMF0pICYmIG51bWJlcihkaXNwWzFdKSkge1xuICAgICAgICAgICAgICB0b3RhbFNoaWZ0LnggKz0gZGlzcFswXTtcbiAgICAgICAgICAgICAgdG90YWxTaGlmdC55ICs9IGRpc3BbMV07XG5cbiAgICAgICAgICAgICAgaWYgKGp1c3RTdGFydGVkRHJhZykge1xuICAgICAgICAgICAgICAgIHZhciBkcmFnRGVsdGEgPSByLmhvdmVyRGF0YS5kcmFnRGVsdGE7XG5cbiAgICAgICAgICAgICAgICBpZiAoZHJhZ0RlbHRhICYmIG51bWJlcihkcmFnRGVsdGFbMF0pICYmIG51bWJlcihkcmFnRGVsdGFbMV0pKSB7XG4gICAgICAgICAgICAgICAgICB0b3RhbFNoaWZ0LnggKz0gZHJhZ0RlbHRhWzBdO1xuICAgICAgICAgICAgICAgICAgdG90YWxTaGlmdC55ICs9IGRyYWdEZWx0YVsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkcmFnZ2VkRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgdmFyIGRFbGUgPSBkcmFnZ2VkRWxlbWVudHNbaV07XG5cbiAgICAgICAgICAgICAgaWYgKHIubm9kZUlzRHJhZ2dhYmxlKGRFbGUpICYmIGRFbGUuZ3JhYmJlZCgpKSB7XG4gICAgICAgICAgICAgICAgdG9UcmlnZ2VyLm1lcmdlKGRFbGUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHIuaG92ZXJEYXRhLmRyYWdnaW5nRWxlcyA9IHRydWU7XG4gICAgICAgICAgICB0b1RyaWdnZXIuc2lsZW50U2hpZnQodG90YWxTaGlmdCkuZW1pdCgncG9zaXRpb24gZHJhZycpO1xuICAgICAgICAgICAgci5yZWRyYXdIaW50KCdkcmFnJywgdHJ1ZSk7XG4gICAgICAgICAgICByLnJlZHJhdygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBvdGhlcndpc2Ugc2F2ZSBkcmFnIGRlbHRhIGZvciB3aGVuIHdlIGFjdHVhbGx5IHN0YXJ0IGRyYWdnaW5nIHNvIHRoZSByZWxhdGl2ZSBncmFiIHBvcyBpcyBjb25zdGFudFxuICAgICAgICAgIHVwZGF0ZURyYWdEZWx0YSgpO1xuICAgICAgICB9XG4gICAgICB9IC8vIHByZXZlbnQgdGhlIGRyYWdnaW5nIGZyb20gdHJpZ2dlcmluZyB0ZXh0IHNlbGVjdGlvbiBvbiB0aGUgcGFnZVxuXG5cbiAgICAgIHByZXZlbnREZWZhdWx0ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBzZWxlY3RbMl0gPSBwb3NbMF07XG4gICAgc2VsZWN0WzNdID0gcG9zWzFdO1xuXG4gICAgaWYgKHByZXZlbnREZWZhdWx0KSB7XG4gICAgICBpZiAoZS5zdG9wUHJvcGFnYXRpb24pIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICBpZiAoZS5wcmV2ZW50RGVmYXVsdCkgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfSwgZmFsc2UpO1xuICByLnJlZ2lzdGVyQmluZGluZyh3aW5kb3csICdtb3VzZXVwJywgZnVuY3Rpb24gbW91c2V1cEhhbmRsZXIoZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbiAgICB2YXIgY2FwdHVyZSA9IHIuaG92ZXJEYXRhLmNhcHR1cmU7XG5cbiAgICBpZiAoIWNhcHR1cmUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICByLmhvdmVyRGF0YS5jYXB0dXJlID0gZmFsc2U7XG4gICAgdmFyIGN5ID0gci5jeTtcbiAgICB2YXIgcG9zID0gci5wcm9qZWN0SW50b1ZpZXdwb3J0KGUuY2xpZW50WCwgZS5jbGllbnRZKTtcbiAgICB2YXIgc2VsZWN0ID0gci5zZWxlY3Rpb247XG4gICAgdmFyIG5lYXIgPSByLmZpbmROZWFyZXN0RWxlbWVudChwb3NbMF0sIHBvc1sxXSwgdHJ1ZSwgZmFsc2UpO1xuICAgIHZhciBkcmFnZ2VkRWxlbWVudHMgPSByLmRyYWdEYXRhLnBvc3NpYmxlRHJhZ0VsZW1lbnRzO1xuICAgIHZhciBkb3duID0gci5ob3ZlckRhdGEuZG93bjtcbiAgICB2YXIgbXVsdFNlbEtleURvd24gPSBpc011bHRTZWxLZXlEb3duKGUpO1xuXG4gICAgaWYgKHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbikge1xuICAgICAgci5yZWRyYXdIaW50KCdzZWxlY3QnLCB0cnVlKTtcbiAgICAgIHIucmVkcmF3KCk7XG4gICAgfVxuXG4gICAgci5ob3ZlckRhdGEudGFwaG9sZENhbmNlbGxlZCA9IHRydWU7XG4gICAgci5kYXRhLmJnQWN0aXZlUG9zaXN0aW9uID0gdW5kZWZpbmVkOyAvLyBub3QgYWN0aXZlIGJnIG5vd1xuXG4gICAgaWYgKGRvd24pIHtcbiAgICAgIGRvd24udW5hY3RpdmF0ZSgpO1xuICAgIH1cblxuICAgIGlmIChyLmhvdmVyRGF0YS53aGljaCA9PT0gMykge1xuICAgICAgdmFyIGN4dEV2dCA9IHtcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgdHlwZTogJ2N4dHRhcGVuZCcsXG4gICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICAgIHk6IHBvc1sxXVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoZG93bikge1xuICAgICAgICBkb3duLmVtaXQoY3h0RXZ0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGN5LmVtaXQoY3h0RXZ0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFyLmhvdmVyRGF0YS5jeHREcmFnZ2VkKSB7XG4gICAgICAgIHZhciBjeHRUYXAgPSB7XG4gICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICB0eXBlOiAnY3h0dGFwJyxcbiAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICAgICAgeTogcG9zWzFdXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChkb3duKSB7XG4gICAgICAgICAgZG93bi5lbWl0KGN4dFRhcCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3kuZW1pdChjeHRUYXApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHIuaG92ZXJEYXRhLmN4dERyYWdnZWQgPSBmYWxzZTtcbiAgICAgIHIuaG92ZXJEYXRhLndoaWNoID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKHIuaG92ZXJEYXRhLndoaWNoID09PSAxKSB7XG4gICAgICB0cmlnZ2VyRXZlbnRzKG5lYXIsIFsnbW91c2V1cCcsICd0YXBlbmQnLCAndm1vdXNldXAnXSwgZSwge1xuICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgIHk6IHBvc1sxXVxuICAgICAgfSk7XG5cbiAgICAgIGlmICghci5kcmFnRGF0YS5kaWREcmFnIC8vIGRpZG4ndCBtb3ZlIGEgbm9kZSBhcm91bmRcbiAgICAgICYmICFyLmhvdmVyRGF0YS5kcmFnZ2VkIC8vIGRpZG4ndCBwYW5cbiAgICAgICYmICFyLmhvdmVyRGF0YS5zZWxlY3RpbmcgLy8gbm90IGJveCBzZWxlY3Rpb25cbiAgICAgICYmICFyLmhvdmVyRGF0YS5pc092ZXJUaHJlc2hvbGREcmFnIC8vIGRpZG4ndCBtb3ZlIHRvbyBtdWNoXG4gICAgICApIHtcbiAgICAgICAgICB0cmlnZ2VyRXZlbnRzKGRvd24sIFsnY2xpY2snLCAndGFwJywgJ3ZjbGljayddLCBlLCB7XG4gICAgICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgICAgICB5OiBwb3NbMV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSAvLyBEZXNlbGVjdCBhbGwgZWxlbWVudHMgaWYgbm90aGluZyBpcyBjdXJyZW50bHkgdW5kZXIgdGhlIG1vdXNlIGN1cnNvciBhbmQgd2UgYXJlbid0IGRyYWdnaW5nIHNvbWV0aGluZ1xuXG5cbiAgICAgIGlmIChkb3duID09IG51bGwgJiYgLy8gbm90IG1vdXNlZG93biBvbiBub2RlXG4gICAgICAhci5kcmFnRGF0YS5kaWREcmFnIC8vIGRpZG4ndCBtb3ZlIHRoZSBub2RlIGFyb3VuZFxuICAgICAgJiYgIXIuaG92ZXJEYXRhLnNlbGVjdGluZyAvLyBub3QgYm94IHNlbGVjdGlvblxuICAgICAgJiYgIXIuaG92ZXJEYXRhLmRyYWdnZWQgLy8gZGlkbid0IHBhblxuICAgICAgJiYgIWlzTXVsdFNlbEtleURvd24oZSkpIHtcbiAgICAgICAgY3kuJChpc1NlbGVjdGVkKS51bnNlbGVjdChbJ3RhcHVuc2VsZWN0J10pO1xuXG4gICAgICAgIGlmIChkcmFnZ2VkRWxlbWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHIucmVkcmF3SGludCgnZWxlcycsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgci5kcmFnRGF0YS5wb3NzaWJsZURyYWdFbGVtZW50cyA9IGRyYWdnZWRFbGVtZW50cyA9IGN5LmNvbGxlY3Rpb24oKTtcbiAgICAgIH0gLy8gU2luZ2xlIHNlbGVjdGlvblxuXG5cbiAgICAgIGlmIChuZWFyID09IGRvd24gJiYgIXIuZHJhZ0RhdGEuZGlkRHJhZyAmJiAhci5ob3ZlckRhdGEuc2VsZWN0aW5nKSB7XG4gICAgICAgIGlmIChuZWFyICE9IG51bGwgJiYgbmVhci5fcHJpdmF0ZS5zZWxlY3RhYmxlKSB7XG4gICAgICAgICAgaWYgKHIuaG92ZXJEYXRhLmRyYWdnaW5nKSA7IGVsc2UgaWYgKGN5LnNlbGVjdGlvblR5cGUoKSA9PT0gJ2FkZGl0aXZlJyB8fCBtdWx0U2VsS2V5RG93bikge1xuICAgICAgICAgICAgaWYgKG5lYXIuc2VsZWN0ZWQoKSkge1xuICAgICAgICAgICAgICBuZWFyLnVuc2VsZWN0KFsndGFwdW5zZWxlY3QnXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBuZWFyLnNlbGVjdChbJ3RhcHNlbGVjdCddKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFtdWx0U2VsS2V5RG93bikge1xuICAgICAgICAgICAgICBjeS4kKGlzU2VsZWN0ZWQpLnVubWVyZ2UobmVhcikudW5zZWxlY3QoWyd0YXB1bnNlbGVjdCddKTtcbiAgICAgICAgICAgICAgbmVhci5zZWxlY3QoWyd0YXBzZWxlY3QnXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgci5yZWRyYXdIaW50KCdlbGVzJywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHIuaG92ZXJEYXRhLnNlbGVjdGluZykge1xuICAgICAgICB2YXIgYm94ID0gY3kuY29sbGVjdGlvbihyLmdldEFsbEluQm94KHNlbGVjdFswXSwgc2VsZWN0WzFdLCBzZWxlY3RbMl0sIHNlbGVjdFszXSkpO1xuICAgICAgICByLnJlZHJhd0hpbnQoJ3NlbGVjdCcsIHRydWUpO1xuXG4gICAgICAgIGlmIChib3gubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHIucmVkcmF3SGludCgnZWxlcycsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgY3kuZW1pdCh7XG4gICAgICAgICAgdHlwZTogJ2JveGVuZCcsXG4gICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICAgICAgeTogcG9zWzFdXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgZWxlV291bGRCZVNlbGVjdGVkID0gZnVuY3Rpb24gZWxlV291bGRCZVNlbGVjdGVkKGVsZSkge1xuICAgICAgICAgIHJldHVybiBlbGUuc2VsZWN0YWJsZSgpICYmICFlbGUuc2VsZWN0ZWQoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoY3kuc2VsZWN0aW9uVHlwZSgpID09PSAnYWRkaXRpdmUnKSB7XG4gICAgICAgICAgYm94LmVtaXQoJ2JveCcpLnN0ZEZpbHRlcihlbGVXb3VsZEJlU2VsZWN0ZWQpLnNlbGVjdCgpLmVtaXQoJ2JveHNlbGVjdCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghbXVsdFNlbEtleURvd24pIHtcbiAgICAgICAgICAgIGN5LiQoaXNTZWxlY3RlZCkudW5tZXJnZShib3gpLnVuc2VsZWN0KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYm94LmVtaXQoJ2JveCcpLnN0ZEZpbHRlcihlbGVXb3VsZEJlU2VsZWN0ZWQpLnNlbGVjdCgpLmVtaXQoJ2JveHNlbGVjdCcpO1xuICAgICAgICB9IC8vIGFsd2F5cyBuZWVkIHJlZHJhdyBpbiBjYXNlIGVsZXMgdW5zZWxlY3RhYmxlXG5cblxuICAgICAgICByLnJlZHJhdygpO1xuICAgICAgfSAvLyBDYW5jZWwgZHJhZyBwYW5cblxuXG4gICAgICBpZiAoci5ob3ZlckRhdGEuZHJhZ2dpbmcpIHtcbiAgICAgICAgci5ob3ZlckRhdGEuZHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgci5yZWRyYXdIaW50KCdzZWxlY3QnLCB0cnVlKTtcbiAgICAgICAgci5yZWRyYXdIaW50KCdlbGVzJywgdHJ1ZSk7XG4gICAgICAgIHIucmVkcmF3KCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghc2VsZWN0WzRdKSB7XG4gICAgICAgIHIucmVkcmF3SGludCgnZHJhZycsIHRydWUpO1xuICAgICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgICAgICAgdmFyIGRvd25XYXNHcmFiYmVkID0gZG93biAmJiBkb3duLmdyYWJiZWQoKTtcbiAgICAgICAgZnJlZURyYWdnZWRFbGVtZW50cyhkcmFnZ2VkRWxlbWVudHMpO1xuXG4gICAgICAgIGlmIChkb3duV2FzR3JhYmJlZCkge1xuICAgICAgICAgIGRvd24uZW1pdCgnZnJlZW9uJyk7XG4gICAgICAgICAgZHJhZ2dlZEVsZW1lbnRzLmVtaXQoJ2ZyZWUnKTtcblxuICAgICAgICAgIGlmIChyLmRyYWdEYXRhLmRpZERyYWcpIHtcbiAgICAgICAgICAgIGRvd24uZW1pdCgnZHJhZ2ZyZWVvbicpO1xuICAgICAgICAgICAgZHJhZ2dlZEVsZW1lbnRzLmVtaXQoJ2RyYWdmcmVlJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSAvLyBlbHNlIG5vdCByaWdodCBtb3VzZVxuXG5cbiAgICBzZWxlY3RbNF0gPSAwO1xuICAgIHIuaG92ZXJEYXRhLmRvd24gPSBudWxsO1xuICAgIHIuaG92ZXJEYXRhLmN4dFN0YXJ0ZWQgPSBmYWxzZTtcbiAgICByLmhvdmVyRGF0YS5kcmFnZ2luZ0VsZXMgPSBmYWxzZTtcbiAgICByLmhvdmVyRGF0YS5zZWxlY3RpbmcgPSBmYWxzZTtcbiAgICByLmhvdmVyRGF0YS5pc092ZXJUaHJlc2hvbGREcmFnID0gZmFsc2U7XG4gICAgci5kcmFnRGF0YS5kaWREcmFnID0gZmFsc2U7XG4gICAgci5ob3ZlckRhdGEuZHJhZ2dlZCA9IGZhbHNlO1xuICAgIHIuaG92ZXJEYXRhLmRyYWdEZWx0YSA9IFtdO1xuICAgIHIuaG92ZXJEYXRhLm1kb3duUG9zID0gbnVsbDtcbiAgICByLmhvdmVyRGF0YS5tZG93bkdQb3MgPSBudWxsO1xuICB9LCBmYWxzZSk7XG5cbiAgdmFyIHdoZWVsSGFuZGxlciA9IGZ1bmN0aW9uIHdoZWVsSGFuZGxlcihlKSB7XG4gICAgaWYgKHIuc2Nyb2xsaW5nUGFnZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gd2hpbGUgc2Nyb2xsaW5nLCBpZ25vcmUgd2hlZWwtdG8tem9vbVxuXG5cbiAgICB2YXIgY3kgPSByLmN5O1xuICAgIHZhciB6b29tID0gY3kuem9vbSgpO1xuICAgIHZhciBwYW4gPSBjeS5wYW4oKTtcbiAgICB2YXIgcG9zID0gci5wcm9qZWN0SW50b1ZpZXdwb3J0KGUuY2xpZW50WCwgZS5jbGllbnRZKTtcbiAgICB2YXIgcnBvcyA9IFtwb3NbMF0gKiB6b29tICsgcGFuLngsIHBvc1sxXSAqIHpvb20gKyBwYW4ueV07XG5cbiAgICBpZiAoci5ob3ZlckRhdGEuZHJhZ2dpbmdFbGVzIHx8IHIuaG92ZXJEYXRhLmRyYWdnaW5nIHx8IHIuaG92ZXJEYXRhLmN4dFN0YXJ0ZWQgfHwgaW5Cb3hTZWxlY3Rpb24oKSkge1xuICAgICAgLy8gaWYgcGFuIGRyYWdnaW5nIG9yIGN4dCBkcmFnZ2luZywgd2hlZWwgbW92ZW1lbnRzIG1ha2Ugbm8gem9vbVxuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjeS5wYW5uaW5nRW5hYmxlZCgpICYmIGN5LnVzZXJQYW5uaW5nRW5hYmxlZCgpICYmIGN5Lnpvb21pbmdFbmFibGVkKCkgJiYgY3kudXNlclpvb21pbmdFbmFibGVkKCkpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHIuZGF0YS53aGVlbFpvb21pbmcgPSB0cnVlO1xuICAgICAgY2xlYXJUaW1lb3V0KHIuZGF0YS53aGVlbFRpbWVvdXQpO1xuICAgICAgci5kYXRhLndoZWVsVGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICByLmRhdGEud2hlZWxab29taW5nID0gZmFsc2U7XG4gICAgICAgIHIucmVkcmF3SGludCgnZWxlcycsIHRydWUpO1xuICAgICAgICByLnJlZHJhdygpO1xuICAgICAgfSwgMTUwKTtcbiAgICAgIHZhciBkaWZmO1xuXG4gICAgICBpZiAoZS5kZWx0YVkgIT0gbnVsbCkge1xuICAgICAgICBkaWZmID0gZS5kZWx0YVkgLyAtMjUwO1xuICAgICAgfSBlbHNlIGlmIChlLndoZWVsRGVsdGFZICE9IG51bGwpIHtcbiAgICAgICAgZGlmZiA9IGUud2hlZWxEZWx0YVkgLyAxMDAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGlmZiA9IGUud2hlZWxEZWx0YSAvIDEwMDA7XG4gICAgICB9XG5cbiAgICAgIGRpZmYgPSBkaWZmICogci53aGVlbFNlbnNpdGl2aXR5O1xuICAgICAgdmFyIG5lZWRzV2hlZWxGaXggPSBlLmRlbHRhTW9kZSA9PT0gMTtcblxuICAgICAgaWYgKG5lZWRzV2hlZWxGaXgpIHtcbiAgICAgICAgLy8gZml4ZXMgc2xvdyB3aGVlbCBldmVudHMgb24gZmYvbGludXggYW5kIGZmL3dpbmRvd3NcbiAgICAgICAgZGlmZiAqPSAzMztcbiAgICAgIH1cblxuICAgICAgdmFyIG5ld1pvb20gPSBjeS56b29tKCkgKiBNYXRoLnBvdygxMCwgZGlmZik7XG5cbiAgICAgIGlmIChlLnR5cGUgPT09ICdnZXN0dXJlY2hhbmdlJykge1xuICAgICAgICBuZXdab29tID0gci5nZXN0dXJlU3RhcnRab29tICogZS5zY2FsZTtcbiAgICAgIH1cblxuICAgICAgY3kuem9vbSh7XG4gICAgICAgIGxldmVsOiBuZXdab29tLFxuICAgICAgICByZW5kZXJlZFBvc2l0aW9uOiB7XG4gICAgICAgICAgeDogcnBvc1swXSxcbiAgICAgICAgICB5OiBycG9zWzFdXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfTsgLy8gRnVuY3Rpb25zIHRvIGhlbHAgd2l0aCB3aGV0aGVyIG1vdXNlIHdoZWVsIHNob3VsZCB0cmlnZ2VyIHpvb21pbmdcbiAgLy8gLS1cblxuXG4gIHIucmVnaXN0ZXJCaW5kaW5nKHIuY29udGFpbmVyLCAnd2hlZWwnLCB3aGVlbEhhbmRsZXIsIHRydWUpOyAvLyBkaXNhYmxlIG5vbnN0YW5kYXJkIHdoZWVsIGV2ZW50c1xuICAvLyByLnJlZ2lzdGVyQmluZGluZyhyLmNvbnRhaW5lciwgJ21vdXNld2hlZWwnLCB3aGVlbEhhbmRsZXIsIHRydWUpO1xuICAvLyByLnJlZ2lzdGVyQmluZGluZyhyLmNvbnRhaW5lciwgJ0RPTU1vdXNlU2Nyb2xsJywgd2hlZWxIYW5kbGVyLCB0cnVlKTtcbiAgLy8gci5yZWdpc3RlckJpbmRpbmcoci5jb250YWluZXIsICdNb3pNb3VzZVBpeGVsU2Nyb2xsJywgd2hlZWxIYW5kbGVyLCB0cnVlKTsgLy8gb2xkZXIgZmlyZWZveFxuXG4gIHIucmVnaXN0ZXJCaW5kaW5nKHdpbmRvdywgJ3Njcm9sbCcsIGZ1bmN0aW9uIHNjcm9sbEhhbmRsZXIoZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgICByLnNjcm9sbGluZ1BhZ2UgPSB0cnVlO1xuICAgIGNsZWFyVGltZW91dChyLnNjcm9sbGluZ1BhZ2VUaW1lb3V0KTtcbiAgICByLnNjcm9sbGluZ1BhZ2VUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICByLnNjcm9sbGluZ1BhZ2UgPSBmYWxzZTtcbiAgICB9LCAyNTApO1xuICB9LCB0cnVlKTsgLy8gZGVza3RvcCBzYWZhcmkgcGluY2ggdG8gem9vbSBzdGFydFxuXG4gIHIucmVnaXN0ZXJCaW5kaW5nKHIuY29udGFpbmVyLCAnZ2VzdHVyZXN0YXJ0JywgZnVuY3Rpb24gZ2VzdHVyZVN0YXJ0SGFuZGxlcihlKSB7XG4gICAgci5nZXN0dXJlU3RhcnRab29tID0gci5jeS56b29tKCk7XG5cbiAgICBpZiAoIXIuaGFzVG91Y2hTdGFydGVkKSB7XG4gICAgICAvLyBkb24ndCBhZmZlY3QgdG91Y2ggZGV2aWNlcyBsaWtlIGlwaG9uZVxuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfSwgdHJ1ZSk7XG4gIHIucmVnaXN0ZXJCaW5kaW5nKHIuY29udGFpbmVyLCAnZ2VzdHVyZWNoYW5nZScsIGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKCFyLmhhc1RvdWNoU3RhcnRlZCkge1xuICAgICAgLy8gZG9uJ3QgYWZmZWN0IHRvdWNoIGRldmljZXMgbGlrZSBpcGhvbmVcbiAgICAgIHdoZWVsSGFuZGxlcihlKTtcbiAgICB9XG4gIH0sIHRydWUpOyAvLyBGdW5jdGlvbnMgdG8gaGVscCB3aXRoIGhhbmRsaW5nIG1vdXNlb3V0L21vdXNlb3ZlciBvbiB0aGUgQ3l0b3NjYXBlIGNvbnRhaW5lclxuICAvLyBIYW5kbGUgbW91c2VvdXQgb24gQ3l0b3NjYXBlIGNvbnRhaW5lclxuXG4gIHIucmVnaXN0ZXJCaW5kaW5nKHIuY29udGFpbmVyLCAnbW91c2VvdXQnLCBmdW5jdGlvbiBtb3VzZU91dEhhbmRsZXIoZSkge1xuICAgIHZhciBwb3MgPSByLnByb2plY3RJbnRvVmlld3BvcnQoZS5jbGllbnRYLCBlLmNsaWVudFkpO1xuICAgIHIuY3kuZW1pdCh7XG4gICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgdHlwZTogJ21vdXNlb3V0JyxcbiAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgIHg6IHBvc1swXSxcbiAgICAgICAgeTogcG9zWzFdXG4gICAgICB9XG4gICAgfSk7XG4gIH0sIGZhbHNlKTtcbiAgci5yZWdpc3RlckJpbmRpbmcoci5jb250YWluZXIsICdtb3VzZW92ZXInLCBmdW5jdGlvbiBtb3VzZU92ZXJIYW5kbGVyKGUpIHtcbiAgICB2YXIgcG9zID0gci5wcm9qZWN0SW50b1ZpZXdwb3J0KGUuY2xpZW50WCwgZS5jbGllbnRZKTtcbiAgICByLmN5LmVtaXQoe1xuICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgIHR5cGU6ICdtb3VzZW92ZXInLFxuICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICB5OiBwb3NbMV1cbiAgICAgIH1cbiAgICB9KTtcbiAgfSwgZmFsc2UpO1xuICB2YXIgZjF4MSwgZjF5MSwgZjJ4MSwgZjJ5MTsgLy8gc3RhcnRpbmcgcG9pbnRzIGZvciBwaW5jaC10by16b29tXG5cbiAgdmFyIGRpc3RhbmNlMSwgZGlzdGFuY2UxU3E7IC8vIGluaXRpYWwgZGlzdGFuY2UgYmV0d2VlbiBmaW5nZXIgMSBhbmQgZmluZ2VyIDIgZm9yIHBpbmNoLXRvLXpvb21cblxuICB2YXIgY2VudGVyMSwgbW9kZWxDZW50ZXIxOyAvLyBjZW50ZXIgcG9pbnQgb24gc3RhcnQgcGluY2ggdG8gem9vbVxuXG4gIHZhciBvZmZzZXRMZWZ0LCBvZmZzZXRUb3A7XG4gIHZhciBjb250YWluZXJXaWR0aCwgY29udGFpbmVySGVpZ2h0O1xuICB2YXIgdHdvRmluZ2Vyc1N0YXJ0SW5zaWRlO1xuXG4gIHZhciBkaXN0YW5jZSA9IGZ1bmN0aW9uIGRpc3RhbmNlKHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgcmV0dXJuIE1hdGguc3FydCgoeDIgLSB4MSkgKiAoeDIgLSB4MSkgKyAoeTIgLSB5MSkgKiAoeTIgLSB5MSkpO1xuICB9O1xuXG4gIHZhciBkaXN0YW5jZVNxID0gZnVuY3Rpb24gZGlzdGFuY2VTcSh4MSwgeTEsIHgyLCB5Mikge1xuICAgIHJldHVybiAoeDIgLSB4MSkgKiAoeDIgLSB4MSkgKyAoeTIgLSB5MSkgKiAoeTIgLSB5MSk7XG4gIH07XG5cbiAgdmFyIHRvdWNoc3RhcnRIYW5kbGVyO1xuICByLnJlZ2lzdGVyQmluZGluZyhyLmNvbnRhaW5lciwgJ3RvdWNoc3RhcnQnLCB0b3VjaHN0YXJ0SGFuZGxlciA9IGZ1bmN0aW9uIHRvdWNoc3RhcnRIYW5kbGVyKGUpIHtcbiAgICByLmhhc1RvdWNoU3RhcnRlZCA9IHRydWU7XG5cbiAgICBpZiAoIWV2ZW50SW5Db250YWluZXIoZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBibHVyQWN0aXZlRG9tRWxlbWVudCgpO1xuICAgIHIudG91Y2hEYXRhLmNhcHR1cmUgPSB0cnVlO1xuICAgIHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB2YXIgY3kgPSByLmN5O1xuICAgIHZhciBub3cgPSByLnRvdWNoRGF0YS5ub3c7XG4gICAgdmFyIGVhcmxpZXIgPSByLnRvdWNoRGF0YS5lYXJsaWVyO1xuXG4gICAgaWYgKGUudG91Y2hlc1swXSkge1xuICAgICAgdmFyIHBvcyA9IHIucHJvamVjdEludG9WaWV3cG9ydChlLnRvdWNoZXNbMF0uY2xpZW50WCwgZS50b3VjaGVzWzBdLmNsaWVudFkpO1xuICAgICAgbm93WzBdID0gcG9zWzBdO1xuICAgICAgbm93WzFdID0gcG9zWzFdO1xuICAgIH1cblxuICAgIGlmIChlLnRvdWNoZXNbMV0pIHtcbiAgICAgIHZhciBwb3MgPSByLnByb2plY3RJbnRvVmlld3BvcnQoZS50b3VjaGVzWzFdLmNsaWVudFgsIGUudG91Y2hlc1sxXS5jbGllbnRZKTtcbiAgICAgIG5vd1syXSA9IHBvc1swXTtcbiAgICAgIG5vd1szXSA9IHBvc1sxXTtcbiAgICB9XG5cbiAgICBpZiAoZS50b3VjaGVzWzJdKSB7XG4gICAgICB2YXIgcG9zID0gci5wcm9qZWN0SW50b1ZpZXdwb3J0KGUudG91Y2hlc1syXS5jbGllbnRYLCBlLnRvdWNoZXNbMl0uY2xpZW50WSk7XG4gICAgICBub3dbNF0gPSBwb3NbMF07XG4gICAgICBub3dbNV0gPSBwb3NbMV07XG4gICAgfSAvLyByZWNvcmQgc3RhcnRpbmcgcG9pbnRzIGZvciBwaW5jaC10by16b29tXG5cblxuICAgIGlmIChlLnRvdWNoZXNbMV0pIHtcbiAgICAgIHIudG91Y2hEYXRhLnNpbmdsZVRvdWNoTW92ZWQgPSB0cnVlO1xuICAgICAgZnJlZURyYWdnZWRFbGVtZW50cyhyLmRyYWdEYXRhLnRvdWNoRHJhZ0VsZXMpO1xuICAgICAgdmFyIG9mZnNldHMgPSByLmZpbmRDb250YWluZXJDbGllbnRDb29yZHMoKTtcbiAgICAgIG9mZnNldExlZnQgPSBvZmZzZXRzWzBdO1xuICAgICAgb2Zmc2V0VG9wID0gb2Zmc2V0c1sxXTtcbiAgICAgIGNvbnRhaW5lcldpZHRoID0gb2Zmc2V0c1syXTtcbiAgICAgIGNvbnRhaW5lckhlaWdodCA9IG9mZnNldHNbM107XG4gICAgICBmMXgxID0gZS50b3VjaGVzWzBdLmNsaWVudFggLSBvZmZzZXRMZWZ0O1xuICAgICAgZjF5MSA9IGUudG91Y2hlc1swXS5jbGllbnRZIC0gb2Zmc2V0VG9wO1xuICAgICAgZjJ4MSA9IGUudG91Y2hlc1sxXS5jbGllbnRYIC0gb2Zmc2V0TGVmdDtcbiAgICAgIGYyeTEgPSBlLnRvdWNoZXNbMV0uY2xpZW50WSAtIG9mZnNldFRvcDtcbiAgICAgIHR3b0ZpbmdlcnNTdGFydEluc2lkZSA9IDAgPD0gZjF4MSAmJiBmMXgxIDw9IGNvbnRhaW5lcldpZHRoICYmIDAgPD0gZjJ4MSAmJiBmMngxIDw9IGNvbnRhaW5lcldpZHRoICYmIDAgPD0gZjF5MSAmJiBmMXkxIDw9IGNvbnRhaW5lckhlaWdodCAmJiAwIDw9IGYyeTEgJiYgZjJ5MSA8PSBjb250YWluZXJIZWlnaHQ7XG4gICAgICB2YXIgcGFuID0gY3kucGFuKCk7XG4gICAgICB2YXIgem9vbSA9IGN5Lnpvb20oKTtcbiAgICAgIGRpc3RhbmNlMSA9IGRpc3RhbmNlKGYxeDEsIGYxeTEsIGYyeDEsIGYyeTEpO1xuICAgICAgZGlzdGFuY2UxU3EgPSBkaXN0YW5jZVNxKGYxeDEsIGYxeTEsIGYyeDEsIGYyeTEpO1xuICAgICAgY2VudGVyMSA9IFsoZjF4MSArIGYyeDEpIC8gMiwgKGYxeTEgKyBmMnkxKSAvIDJdO1xuICAgICAgbW9kZWxDZW50ZXIxID0gWyhjZW50ZXIxWzBdIC0gcGFuLngpIC8gem9vbSwgKGNlbnRlcjFbMV0gLSBwYW4ueSkgLyB6b29tXTsgLy8gY29uc2lkZXIgY29udGV4dCB0YXBcblxuICAgICAgdmFyIGN4dERpc3RUaHJlc2hvbGQgPSAyMDA7XG4gICAgICB2YXIgY3h0RGlzdFRocmVzaG9sZFNxID0gY3h0RGlzdFRocmVzaG9sZCAqIGN4dERpc3RUaHJlc2hvbGQ7XG5cbiAgICAgIGlmIChkaXN0YW5jZTFTcSA8IGN4dERpc3RUaHJlc2hvbGRTcSAmJiAhZS50b3VjaGVzWzJdKSB7XG4gICAgICAgIHZhciBuZWFyMSA9IHIuZmluZE5lYXJlc3RFbGVtZW50KG5vd1swXSwgbm93WzFdLCB0cnVlLCB0cnVlKTtcbiAgICAgICAgdmFyIG5lYXIyID0gci5maW5kTmVhcmVzdEVsZW1lbnQobm93WzJdLCBub3dbM10sIHRydWUsIHRydWUpO1xuXG4gICAgICAgIGlmIChuZWFyMSAmJiBuZWFyMS5pc05vZGUoKSkge1xuICAgICAgICAgIG5lYXIxLmFjdGl2YXRlKCkuZW1pdCh7XG4gICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgICAgICAgdHlwZTogJ2N4dHRhcHN0YXJ0JyxcbiAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICAgICAgeTogbm93WzFdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgci50b3VjaERhdGEuc3RhcnQgPSBuZWFyMTtcbiAgICAgICAgfSBlbHNlIGlmIChuZWFyMiAmJiBuZWFyMi5pc05vZGUoKSkge1xuICAgICAgICAgIG5lYXIyLmFjdGl2YXRlKCkuZW1pdCh7XG4gICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgICAgICAgdHlwZTogJ2N4dHRhcHN0YXJ0JyxcbiAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICAgICAgeTogbm93WzFdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgci50b3VjaERhdGEuc3RhcnQgPSBuZWFyMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjeS5lbWl0KHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGUsXG4gICAgICAgICAgICB0eXBlOiAnY3h0dGFwc3RhcnQnLFxuICAgICAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgICAgeDogbm93WzBdLFxuICAgICAgICAgICAgICB5OiBub3dbMV1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyLnRvdWNoRGF0YS5zdGFydCkge1xuICAgICAgICAgIHIudG91Y2hEYXRhLnN0YXJ0Ll9wcml2YXRlLmdyYWJiZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHIudG91Y2hEYXRhLmN4dCA9IHRydWU7XG4gICAgICAgIHIudG91Y2hEYXRhLmN4dERyYWdnZWQgPSBmYWxzZTtcbiAgICAgICAgci5kYXRhLmJnQWN0aXZlUG9zaXN0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICByLnJlZHJhdygpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGUudG91Y2hlc1syXSkge1xuICAgICAgLy8gaWdub3JlXG4gICAgICAvLyBzYWZhcmkgb24gaW9zIHBhbnMgdGhlIHBhZ2Ugb3RoZXJ3aXNlIChub3JtYWxseSB5b3Ugc2hvdWxkIGJlIGFibGUgdG8gcHJldmVudGRlZmF1bHQgb24gdG91Y2htb3ZlLi4uKVxuICAgICAgaWYgKGN5LmJveFNlbGVjdGlvbkVuYWJsZWQoKSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChlLnRvdWNoZXNbMV0pIDsgZWxzZSBpZiAoZS50b3VjaGVzWzBdKSB7XG4gICAgICB2YXIgbmVhcnMgPSByLmZpbmROZWFyZXN0RWxlbWVudHMobm93WzBdLCBub3dbMV0sIHRydWUsIHRydWUpO1xuICAgICAgdmFyIG5lYXIgPSBuZWFyc1swXTtcblxuICAgICAgaWYgKG5lYXIgIT0gbnVsbCkge1xuICAgICAgICBuZWFyLmFjdGl2YXRlKCk7XG4gICAgICAgIHIudG91Y2hEYXRhLnN0YXJ0ID0gbmVhcjtcbiAgICAgICAgci50b3VjaERhdGEuc3RhcnRzID0gbmVhcnM7XG5cbiAgICAgICAgaWYgKHIubm9kZUlzR3JhYmJhYmxlKG5lYXIpKSB7XG4gICAgICAgICAgdmFyIGRyYWdnZWRFbGVzID0gci5kcmFnRGF0YS50b3VjaERyYWdFbGVzID0gY3kuY29sbGVjdGlvbigpO1xuICAgICAgICAgIHZhciBzZWxlY3RlZE5vZGVzID0gbnVsbDtcbiAgICAgICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgICAgICAgICByLnJlZHJhd0hpbnQoJ2RyYWcnLCB0cnVlKTtcblxuICAgICAgICAgIGlmIChuZWFyLnNlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgIC8vIHJlc2V0IGRyYWcgZWxlbWVudHMsIHNpbmNlIG5lYXIgd2lsbCBiZSBhZGRlZCBhZ2FpblxuICAgICAgICAgICAgc2VsZWN0ZWROb2RlcyA9IGN5LiQoZnVuY3Rpb24gKGVsZSkge1xuICAgICAgICAgICAgICByZXR1cm4gZWxlLnNlbGVjdGVkKCkgJiYgci5ub2RlSXNHcmFiYmFibGUoZWxlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYWRkTm9kZXNUb0RyYWcoc2VsZWN0ZWROb2Rlcywge1xuICAgICAgICAgICAgICBhZGRUb0xpc3Q6IGRyYWdnZWRFbGVzXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWRkTm9kZVRvRHJhZyhuZWFyLCB7XG4gICAgICAgICAgICAgIGFkZFRvTGlzdDogZHJhZ2dlZEVsZXNcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHNldEdyYWJUYXJnZXQobmVhcik7XG5cbiAgICAgICAgICB2YXIgbWFrZUV2ZW50ID0gZnVuY3Rpb24gbWFrZUV2ZW50KHR5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGUsXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgeDogbm93WzBdLFxuICAgICAgICAgICAgICAgIHk6IG5vd1sxXVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBuZWFyLmVtaXQobWFrZUV2ZW50KCdncmFib24nKSk7XG5cbiAgICAgICAgICBpZiAoc2VsZWN0ZWROb2Rlcykge1xuICAgICAgICAgICAgc2VsZWN0ZWROb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICAgIG4uZW1pdChtYWtlRXZlbnQoJ2dyYWInKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmVhci5lbWl0KG1ha2VFdmVudCgnZ3JhYicpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdHJpZ2dlckV2ZW50cyhuZWFyLCBbJ3RvdWNoc3RhcnQnLCAndGFwc3RhcnQnLCAndm1vdXNlZG93biddLCBlLCB7XG4gICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgeTogbm93WzFdXG4gICAgICB9KTtcblxuICAgICAgaWYgKG5lYXIgPT0gbnVsbCkge1xuICAgICAgICByLmRhdGEuYmdBY3RpdmVQb3Npc3Rpb24gPSB7XG4gICAgICAgICAgeDogcG9zWzBdLFxuICAgICAgICAgIHk6IHBvc1sxXVxuICAgICAgICB9O1xuICAgICAgICByLnJlZHJhd0hpbnQoJ3NlbGVjdCcsIHRydWUpO1xuICAgICAgICByLnJlZHJhdygpO1xuICAgICAgfSAvLyBUYXAsIHRhcGhvbGRcbiAgICAgIC8vIC0tLS0tXG5cblxuICAgICAgci50b3VjaERhdGEuc2luZ2xlVG91Y2hNb3ZlZCA9IGZhbHNlO1xuICAgICAgci50b3VjaERhdGEuc2luZ2xlVG91Y2hTdGFydFRpbWUgPSArbmV3IERhdGUoKTtcbiAgICAgIGNsZWFyVGltZW91dChyLnRvdWNoRGF0YS50YXBob2xkVGltZW91dCk7XG4gICAgICByLnRvdWNoRGF0YS50YXBob2xkVGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoci50b3VjaERhdGEuc2luZ2xlVG91Y2hNb3ZlZCA9PT0gZmFsc2UgJiYgIXIucGluY2hpbmcgLy8gaWYgcGluY2hpbmcsIHRoZW4gdGFwaG9sZCB1bnNlbGVjdCBzaG91bGRuJ3QgdGFrZSBlZmZlY3RcbiAgICAgICAgJiYgIXIudG91Y2hEYXRhLnNlbGVjdGluZyAvLyBib3ggc2VsZWN0aW9uIHNob3VsZG4ndCBhbGxvdyB0YXBob2xkIHRocm91Z2hcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0cmlnZ2VyRXZlbnRzKHIudG91Y2hEYXRhLnN0YXJ0LCBbJ3RhcGhvbGQnXSwgZSwge1xuICAgICAgICAgICAgICB4OiBub3dbMF0sXG4gICAgICAgICAgICAgIHk6IG5vd1sxXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgfSwgci50YXBob2xkRHVyYXRpb24pO1xuICAgIH1cblxuICAgIGlmIChlLnRvdWNoZXMubGVuZ3RoID49IDEpIHtcbiAgICAgIHZhciBzUG9zID0gci50b3VjaERhdGEuc3RhcnRQb3NpdGlvbiA9IFtdO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vdy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzUG9zW2ldID0gZWFybGllcltpXSA9IG5vd1tpXTtcbiAgICAgIH1cblxuICAgICAgdmFyIHRvdWNoMCA9IGUudG91Y2hlc1swXTtcbiAgICAgIHIudG91Y2hEYXRhLnN0YXJ0R1Bvc2l0aW9uID0gW3RvdWNoMC5jbGllbnRYLCB0b3VjaDAuY2xpZW50WV07XG4gICAgfVxuICB9LCBmYWxzZSk7XG4gIHZhciB0b3VjaG1vdmVIYW5kbGVyO1xuICByLnJlZ2lzdGVyQmluZGluZyh3aW5kb3csICd0b3VjaG1vdmUnLCB0b3VjaG1vdmVIYW5kbGVyID0gZnVuY3Rpb24gdG91Y2htb3ZlSGFuZGxlcihlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuICAgIHZhciBjYXB0dXJlID0gci50b3VjaERhdGEuY2FwdHVyZTtcblxuICAgIGlmICghY2FwdHVyZSAmJiAhZXZlbnRJbkNvbnRhaW5lcihlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBzZWxlY3QgPSByLnNlbGVjdGlvbjtcbiAgICB2YXIgY3kgPSByLmN5O1xuICAgIHZhciBub3cgPSByLnRvdWNoRGF0YS5ub3c7XG4gICAgdmFyIGVhcmxpZXIgPSByLnRvdWNoRGF0YS5lYXJsaWVyO1xuICAgIHZhciB6b29tID0gY3kuem9vbSgpO1xuXG4gICAgaWYgKGUudG91Y2hlc1swXSkge1xuICAgICAgdmFyIHBvcyA9IHIucHJvamVjdEludG9WaWV3cG9ydChlLnRvdWNoZXNbMF0uY2xpZW50WCwgZS50b3VjaGVzWzBdLmNsaWVudFkpO1xuICAgICAgbm93WzBdID0gcG9zWzBdO1xuICAgICAgbm93WzFdID0gcG9zWzFdO1xuICAgIH1cblxuICAgIGlmIChlLnRvdWNoZXNbMV0pIHtcbiAgICAgIHZhciBwb3MgPSByLnByb2plY3RJbnRvVmlld3BvcnQoZS50b3VjaGVzWzFdLmNsaWVudFgsIGUudG91Y2hlc1sxXS5jbGllbnRZKTtcbiAgICAgIG5vd1syXSA9IHBvc1swXTtcbiAgICAgIG5vd1szXSA9IHBvc1sxXTtcbiAgICB9XG5cbiAgICBpZiAoZS50b3VjaGVzWzJdKSB7XG4gICAgICB2YXIgcG9zID0gci5wcm9qZWN0SW50b1ZpZXdwb3J0KGUudG91Y2hlc1syXS5jbGllbnRYLCBlLnRvdWNoZXNbMl0uY2xpZW50WSk7XG4gICAgICBub3dbNF0gPSBwb3NbMF07XG4gICAgICBub3dbNV0gPSBwb3NbMV07XG4gICAgfVxuXG4gICAgdmFyIHN0YXJ0R1BvcyA9IHIudG91Y2hEYXRhLnN0YXJ0R1Bvc2l0aW9uO1xuICAgIHZhciBpc092ZXJUaHJlc2hvbGREcmFnO1xuXG4gICAgaWYgKGNhcHR1cmUgJiYgZS50b3VjaGVzWzBdICYmIHN0YXJ0R1Bvcykge1xuICAgICAgdmFyIGRpc3AgPSBbXTtcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBub3cubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgZGlzcFtqXSA9IG5vd1tqXSAtIGVhcmxpZXJbal07XG4gICAgICB9XG5cbiAgICAgIHZhciBkeCA9IGUudG91Y2hlc1swXS5jbGllbnRYIC0gc3RhcnRHUG9zWzBdO1xuICAgICAgdmFyIGR4MiA9IGR4ICogZHg7XG4gICAgICB2YXIgZHkgPSBlLnRvdWNoZXNbMF0uY2xpZW50WSAtIHN0YXJ0R1Bvc1sxXTtcbiAgICAgIHZhciBkeTIgPSBkeSAqIGR5O1xuICAgICAgdmFyIGRpc3QyID0gZHgyICsgZHkyO1xuICAgICAgaXNPdmVyVGhyZXNob2xkRHJhZyA9IGRpc3QyID49IHIudG91Y2hUYXBUaHJlc2hvbGQyO1xuICAgIH0gLy8gY29udGV4dCBzd2lwZSBjYW5jZWxsaW5nXG5cblxuICAgIGlmIChjYXB0dXJlICYmIHIudG91Y2hEYXRhLmN4dCkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgdmFyIGYxeDIgPSBlLnRvdWNoZXNbMF0uY2xpZW50WCAtIG9mZnNldExlZnQsXG4gICAgICAgICAgZjF5MiA9IGUudG91Y2hlc1swXS5jbGllbnRZIC0gb2Zmc2V0VG9wO1xuICAgICAgdmFyIGYyeDIgPSBlLnRvdWNoZXNbMV0uY2xpZW50WCAtIG9mZnNldExlZnQsXG4gICAgICAgICAgZjJ5MiA9IGUudG91Y2hlc1sxXS5jbGllbnRZIC0gb2Zmc2V0VG9wOyAvLyB2YXIgZGlzdGFuY2UyID0gZGlzdGFuY2UoIGYxeDIsIGYxeTIsIGYyeDIsIGYyeTIgKTtcblxuICAgICAgdmFyIGRpc3RhbmNlMlNxID0gZGlzdGFuY2VTcShmMXgyLCBmMXkyLCBmMngyLCBmMnkyKTtcbiAgICAgIHZhciBmYWN0b3JTcSA9IGRpc3RhbmNlMlNxIC8gZGlzdGFuY2UxU3E7XG4gICAgICB2YXIgZGlzdFRocmVzaG9sZCA9IDE1MDtcbiAgICAgIHZhciBkaXN0VGhyZXNob2xkU3EgPSBkaXN0VGhyZXNob2xkICogZGlzdFRocmVzaG9sZDtcbiAgICAgIHZhciBmYWN0b3JUaHJlc2hvbGQgPSAxLjU7XG4gICAgICB2YXIgZmFjdG9yVGhyZXNob2xkU3EgPSBmYWN0b3JUaHJlc2hvbGQgKiBmYWN0b3JUaHJlc2hvbGQ7IC8vIGNhbmNlbCBjdHggZ2VzdHVyZXMgaWYgdGhlIGRpc3RhbmNlIGIvdCB0aGUgZmluZ2VycyBpbmNyZWFzZXNcblxuICAgICAgaWYgKGZhY3RvclNxID49IGZhY3RvclRocmVzaG9sZFNxIHx8IGRpc3RhbmNlMlNxID49IGRpc3RUaHJlc2hvbGRTcSkge1xuICAgICAgICByLnRvdWNoRGF0YS5jeHQgPSBmYWxzZTtcbiAgICAgICAgci5kYXRhLmJnQWN0aXZlUG9zaXN0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICByLnJlZHJhd0hpbnQoJ3NlbGVjdCcsIHRydWUpO1xuICAgICAgICB2YXIgY3h0RXZ0ID0ge1xuICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGUsXG4gICAgICAgICAgdHlwZTogJ2N4dHRhcGVuZCcsXG4gICAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICAgIHk6IG5vd1sxXVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoci50b3VjaERhdGEuc3RhcnQpIHtcbiAgICAgICAgICByLnRvdWNoRGF0YS5zdGFydC51bmFjdGl2YXRlKCkuZW1pdChjeHRFdnQpO1xuICAgICAgICAgIHIudG91Y2hEYXRhLnN0YXJ0ID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjeS5lbWl0KGN4dEV2dCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IC8vIGNvbnRleHQgc3dpcGVcblxuXG4gICAgaWYgKGNhcHR1cmUgJiYgci50b3VjaERhdGEuY3h0KSB7XG4gICAgICB2YXIgY3h0RXZ0ID0ge1xuICAgICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgICB0eXBlOiAnY3h0ZHJhZycsXG4gICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgeDogbm93WzBdLFxuICAgICAgICAgIHk6IG5vd1sxXVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgci5kYXRhLmJnQWN0aXZlUG9zaXN0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgci5yZWRyYXdIaW50KCdzZWxlY3QnLCB0cnVlKTtcblxuICAgICAgaWYgKHIudG91Y2hEYXRhLnN0YXJ0KSB7XG4gICAgICAgIHIudG91Y2hEYXRhLnN0YXJ0LmVtaXQoY3h0RXZ0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGN5LmVtaXQoY3h0RXZ0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHIudG91Y2hEYXRhLnN0YXJ0KSB7XG4gICAgICAgIHIudG91Y2hEYXRhLnN0YXJ0Ll9wcml2YXRlLmdyYWJiZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgci50b3VjaERhdGEuY3h0RHJhZ2dlZCA9IHRydWU7XG4gICAgICB2YXIgbmVhciA9IHIuZmluZE5lYXJlc3RFbGVtZW50KG5vd1swXSwgbm93WzFdLCB0cnVlLCB0cnVlKTtcblxuICAgICAgaWYgKCFyLnRvdWNoRGF0YS5jeHRPdmVyIHx8IG5lYXIgIT09IHIudG91Y2hEYXRhLmN4dE92ZXIpIHtcbiAgICAgICAgaWYgKHIudG91Y2hEYXRhLmN4dE92ZXIpIHtcbiAgICAgICAgICByLnRvdWNoRGF0YS5jeHRPdmVyLmVtaXQoe1xuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICAgIHR5cGU6ICdjeHRkcmFnb3V0JyxcbiAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICAgICAgeTogbm93WzFdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByLnRvdWNoRGF0YS5jeHRPdmVyID0gbmVhcjtcblxuICAgICAgICBpZiAobmVhcikge1xuICAgICAgICAgIG5lYXIuZW1pdCh7XG4gICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBlLFxuICAgICAgICAgICAgdHlwZTogJ2N4dGRyYWdvdmVyJyxcbiAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICAgICAgeTogbm93WzFdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gYm94IHNlbGVjdGlvblxuXG4gICAgfSBlbHNlIGlmIChjYXB0dXJlICYmIGUudG91Y2hlc1syXSAmJiBjeS5ib3hTZWxlY3Rpb25FbmFibGVkKCkpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMubGFzdFRocmVlVG91Y2ggPSArbmV3IERhdGUoKTtcblxuICAgICAgaWYgKCFyLnRvdWNoRGF0YS5zZWxlY3RpbmcpIHtcbiAgICAgICAgY3kuZW1pdCh7XG4gICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICB0eXBlOiAnYm94c3RhcnQnLFxuICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICB4OiBub3dbMF0sXG4gICAgICAgICAgICB5OiBub3dbMV1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICByLnRvdWNoRGF0YS5zZWxlY3RpbmcgPSB0cnVlO1xuICAgICAgci50b3VjaERhdGEuZGlkU2VsZWN0ID0gdHJ1ZTtcbiAgICAgIHNlbGVjdFs0XSA9IDE7XG5cbiAgICAgIGlmICghc2VsZWN0IHx8IHNlbGVjdC5sZW5ndGggPT09IDAgfHwgc2VsZWN0WzBdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgc2VsZWN0WzBdID0gKG5vd1swXSArIG5vd1syXSArIG5vd1s0XSkgLyAzO1xuICAgICAgICBzZWxlY3RbMV0gPSAobm93WzFdICsgbm93WzNdICsgbm93WzVdKSAvIDM7XG4gICAgICAgIHNlbGVjdFsyXSA9IChub3dbMF0gKyBub3dbMl0gKyBub3dbNF0pIC8gMyArIDE7XG4gICAgICAgIHNlbGVjdFszXSA9IChub3dbMV0gKyBub3dbM10gKyBub3dbNV0pIC8gMyArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWxlY3RbMl0gPSAobm93WzBdICsgbm93WzJdICsgbm93WzRdKSAvIDM7XG4gICAgICAgIHNlbGVjdFszXSA9IChub3dbMV0gKyBub3dbM10gKyBub3dbNV0pIC8gMztcbiAgICAgIH1cblxuICAgICAgci5yZWRyYXdIaW50KCdzZWxlY3QnLCB0cnVlKTtcbiAgICAgIHIucmVkcmF3KCk7IC8vIHBpbmNoIHRvIHpvb21cbiAgICB9IGVsc2UgaWYgKGNhcHR1cmUgJiYgZS50b3VjaGVzWzFdICYmICFyLnRvdWNoRGF0YS5kaWRTZWxlY3QgLy8gZG9uJ3QgYWxsb3cgYm94IHNlbGVjdGlvbiB0byBkZWdyYWRlIHRvIHBpbmNoLXRvLXpvb21cbiAgICAmJiBjeS56b29taW5nRW5hYmxlZCgpICYmIGN5LnBhbm5pbmdFbmFibGVkKCkgJiYgY3kudXNlclpvb21pbmdFbmFibGVkKCkgJiYgY3kudXNlclBhbm5pbmdFbmFibGVkKCkpIHtcbiAgICAgIC8vIHR3byBmaW5nZXJzID0+IHBpbmNoIHRvIHpvb21cbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgIHIucmVkcmF3SGludCgnc2VsZWN0JywgdHJ1ZSk7XG4gICAgICB2YXIgZHJhZ2dlZEVsZXMgPSByLmRyYWdEYXRhLnRvdWNoRHJhZ0VsZXM7XG5cbiAgICAgIGlmIChkcmFnZ2VkRWxlcykge1xuICAgICAgICByLnJlZHJhd0hpbnQoJ2RyYWcnLCB0cnVlKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRyYWdnZWRFbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGRlX3AgPSBkcmFnZ2VkRWxlc1tpXS5fcHJpdmF0ZTtcbiAgICAgICAgICBkZV9wLmdyYWJiZWQgPSBmYWxzZTtcbiAgICAgICAgICBkZV9wLnJzY3JhdGNoLmluRHJhZ0xheWVyID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIF9zdGFydCA9IHIudG91Y2hEYXRhLnN0YXJ0OyAvLyAoeDIsIHkyKSBmb3IgZmluZ2VycyAxIGFuZCAyXG5cbiAgICAgIHZhciBmMXgyID0gZS50b3VjaGVzWzBdLmNsaWVudFggLSBvZmZzZXRMZWZ0LFxuICAgICAgICAgIGYxeTIgPSBlLnRvdWNoZXNbMF0uY2xpZW50WSAtIG9mZnNldFRvcDtcbiAgICAgIHZhciBmMngyID0gZS50b3VjaGVzWzFdLmNsaWVudFggLSBvZmZzZXRMZWZ0LFxuICAgICAgICAgIGYyeTIgPSBlLnRvdWNoZXNbMV0uY2xpZW50WSAtIG9mZnNldFRvcDtcbiAgICAgIHZhciBkaXN0YW5jZTIgPSBkaXN0YW5jZShmMXgyLCBmMXkyLCBmMngyLCBmMnkyKTsgLy8gdmFyIGRpc3RhbmNlMlNxID0gZGlzdGFuY2VTcSggZjF4MiwgZjF5MiwgZjJ4MiwgZjJ5MiApO1xuICAgICAgLy8gdmFyIGZhY3RvciA9IE1hdGguc3FydCggZGlzdGFuY2UyU3EgKSAvIE1hdGguc3FydCggZGlzdGFuY2UxU3EgKTtcblxuICAgICAgdmFyIGZhY3RvciA9IGRpc3RhbmNlMiAvIGRpc3RhbmNlMTtcblxuICAgICAgaWYgKHR3b0ZpbmdlcnNTdGFydEluc2lkZSkge1xuICAgICAgICAvLyBkZWx0YSBmaW5nZXIxXG4gICAgICAgIHZhciBkZjF4ID0gZjF4MiAtIGYxeDE7XG4gICAgICAgIHZhciBkZjF5ID0gZjF5MiAtIGYxeTE7IC8vIGRlbHRhIGZpbmdlciAyXG5cbiAgICAgICAgdmFyIGRmMnggPSBmMngyIC0gZjJ4MTtcbiAgICAgICAgdmFyIGRmMnkgPSBmMnkyIC0gZjJ5MTsgLy8gdHJhbnNsYXRpb24gaXMgdGhlIG5vcm1hbGlzZWQgdmVjdG9yIG9mIHRoZSB0d28gZmluZ2VycyBtb3ZlbWVudFxuICAgICAgICAvLyBpLmUuIHNvIHBpbmNoaW5nIGNhbmNlbHMgb3V0IGFuZCBtb3ZpbmcgdG9nZXRoZXIgcGFuc1xuXG4gICAgICAgIHZhciB0eCA9IChkZjF4ICsgZGYyeCkgLyAyO1xuICAgICAgICB2YXIgdHkgPSAoZGYxeSArIGRmMnkpIC8gMjsgLy8gbm93IGNhbGN1bGF0ZSB0aGUgem9vbVxuXG4gICAgICAgIHZhciB6b29tMSA9IGN5Lnpvb20oKTtcbiAgICAgICAgdmFyIHpvb20yID0gem9vbTEgKiBmYWN0b3I7XG4gICAgICAgIHZhciBwYW4xID0gY3kucGFuKCk7IC8vIHRoZSBtb2RlbCBjZW50ZXIgcG9pbnQgY29udmVydGVkIHRvIHRoZSBjdXJyZW50IHJlbmRlcmVkIHBvc1xuXG4gICAgICAgIHZhciBjdHJ4ID0gbW9kZWxDZW50ZXIxWzBdICogem9vbTEgKyBwYW4xLng7XG4gICAgICAgIHZhciBjdHJ5ID0gbW9kZWxDZW50ZXIxWzFdICogem9vbTEgKyBwYW4xLnk7XG4gICAgICAgIHZhciBwYW4yID0ge1xuICAgICAgICAgIHg6IC16b29tMiAvIHpvb20xICogKGN0cnggLSBwYW4xLnggLSB0eCkgKyBjdHJ4LFxuICAgICAgICAgIHk6IC16b29tMiAvIHpvb20xICogKGN0cnkgLSBwYW4xLnkgLSB0eSkgKyBjdHJ5XG4gICAgICAgIH07IC8vIHJlbW92ZSBkcmFnZ2VkIGVsZXNcblxuICAgICAgICBpZiAoX3N0YXJ0ICYmIF9zdGFydC5hY3RpdmUoKSkge1xuICAgICAgICAgIHZhciBkcmFnZ2VkRWxlcyA9IHIuZHJhZ0RhdGEudG91Y2hEcmFnRWxlcztcbiAgICAgICAgICBmcmVlRHJhZ2dlZEVsZW1lbnRzKGRyYWdnZWRFbGVzKTtcbiAgICAgICAgICByLnJlZHJhd0hpbnQoJ2RyYWcnLCB0cnVlKTtcbiAgICAgICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcblxuICAgICAgICAgIF9zdGFydC51bmFjdGl2YXRlKCkuZW1pdCgnZnJlZW9uJyk7XG5cbiAgICAgICAgICBkcmFnZ2VkRWxlcy5lbWl0KCdmcmVlJyk7XG5cbiAgICAgICAgICBpZiAoci5kcmFnRGF0YS5kaWREcmFnKSB7XG4gICAgICAgICAgICBfc3RhcnQuZW1pdCgnZHJhZ2ZyZWVvbicpO1xuXG4gICAgICAgICAgICBkcmFnZ2VkRWxlcy5lbWl0KCdkcmFnZnJlZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGN5LnZpZXdwb3J0KHtcbiAgICAgICAgICB6b29tOiB6b29tMixcbiAgICAgICAgICBwYW46IHBhbjIsXG4gICAgICAgICAgY2FuY2VsT25GYWlsZWRab29tOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBkaXN0YW5jZTEgPSBkaXN0YW5jZTI7XG4gICAgICAgIGYxeDEgPSBmMXgyO1xuICAgICAgICBmMXkxID0gZjF5MjtcbiAgICAgICAgZjJ4MSA9IGYyeDI7XG4gICAgICAgIGYyeTEgPSBmMnkyO1xuICAgICAgICByLnBpbmNoaW5nID0gdHJ1ZTtcbiAgICAgIH0gLy8gUmUtcHJvamVjdFxuXG5cbiAgICAgIGlmIChlLnRvdWNoZXNbMF0pIHtcbiAgICAgICAgdmFyIHBvcyA9IHIucHJvamVjdEludG9WaWV3cG9ydChlLnRvdWNoZXNbMF0uY2xpZW50WCwgZS50b3VjaGVzWzBdLmNsaWVudFkpO1xuICAgICAgICBub3dbMF0gPSBwb3NbMF07XG4gICAgICAgIG5vd1sxXSA9IHBvc1sxXTtcbiAgICAgIH1cblxuICAgICAgaWYgKGUudG91Y2hlc1sxXSkge1xuICAgICAgICB2YXIgcG9zID0gci5wcm9qZWN0SW50b1ZpZXdwb3J0KGUudG91Y2hlc1sxXS5jbGllbnRYLCBlLnRvdWNoZXNbMV0uY2xpZW50WSk7XG4gICAgICAgIG5vd1syXSA9IHBvc1swXTtcbiAgICAgICAgbm93WzNdID0gcG9zWzFdO1xuICAgICAgfVxuXG4gICAgICBpZiAoZS50b3VjaGVzWzJdKSB7XG4gICAgICAgIHZhciBwb3MgPSByLnByb2plY3RJbnRvVmlld3BvcnQoZS50b3VjaGVzWzJdLmNsaWVudFgsIGUudG91Y2hlc1syXS5jbGllbnRZKTtcbiAgICAgICAgbm93WzRdID0gcG9zWzBdO1xuICAgICAgICBub3dbNV0gPSBwb3NbMV07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChlLnRvdWNoZXNbMF0gJiYgIXIudG91Y2hEYXRhLmRpZFNlbGVjdCAvLyBkb24ndCBhbGxvdyBib3ggc2VsZWN0aW9uIHRvIGRlZ3JhZGUgdG8gc2luZ2xlIGZpbmdlciBldmVudHMgbGlrZSBwYW5uaW5nXG4gICAgKSB7XG4gICAgICAgIHZhciBzdGFydCA9IHIudG91Y2hEYXRhLnN0YXJ0O1xuICAgICAgICB2YXIgbGFzdCA9IHIudG91Y2hEYXRhLmxhc3Q7XG4gICAgICAgIHZhciBuZWFyO1xuXG4gICAgICAgIGlmICghci5ob3ZlckRhdGEuZHJhZ2dpbmdFbGVzICYmICFyLnN3aXBlUGFubmluZykge1xuICAgICAgICAgIG5lYXIgPSByLmZpbmROZWFyZXN0RWxlbWVudChub3dbMF0sIG5vd1sxXSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2FwdHVyZSAmJiBzdGFydCAhPSBudWxsKSB7XG4gICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9IC8vIGRyYWdnaW5nIG5vZGVzXG5cblxuICAgICAgICBpZiAoY2FwdHVyZSAmJiBzdGFydCAhPSBudWxsICYmIHIubm9kZUlzRHJhZ2dhYmxlKHN0YXJ0KSkge1xuICAgICAgICAgIGlmIChpc092ZXJUaHJlc2hvbGREcmFnKSB7XG4gICAgICAgICAgICAvLyB0aGVuIGRyYWdnaW5nIGNhbiBoYXBwZW5cbiAgICAgICAgICAgIHZhciBkcmFnZ2VkRWxlcyA9IHIuZHJhZ0RhdGEudG91Y2hEcmFnRWxlcztcbiAgICAgICAgICAgIHZhciBqdXN0U3RhcnRlZERyYWcgPSAhci5kcmFnRGF0YS5kaWREcmFnO1xuXG4gICAgICAgICAgICBpZiAoanVzdFN0YXJ0ZWREcmFnKSB7XG4gICAgICAgICAgICAgIGFkZE5vZGVzVG9EcmFnKGRyYWdnZWRFbGVzLCB7XG4gICAgICAgICAgICAgICAgaW5EcmFnTGF5ZXI6IHRydWVcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHIuZHJhZ0RhdGEuZGlkRHJhZyA9IHRydWU7XG4gICAgICAgICAgICB2YXIgdG90YWxTaGlmdCA9IHtcbiAgICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgICAgeTogMFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKG51bWJlcihkaXNwWzBdKSAmJiBudW1iZXIoZGlzcFsxXSkpIHtcbiAgICAgICAgICAgICAgdG90YWxTaGlmdC54ICs9IGRpc3BbMF07XG4gICAgICAgICAgICAgIHRvdGFsU2hpZnQueSArPSBkaXNwWzFdO1xuXG4gICAgICAgICAgICAgIGlmIChqdXN0U3RhcnRlZERyYWcpIHtcbiAgICAgICAgICAgICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB2YXIgZHJhZ0RlbHRhID0gci50b3VjaERhdGEuZHJhZ0RlbHRhO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRyYWdEZWx0YSAmJiBudW1iZXIoZHJhZ0RlbHRhWzBdKSAmJiBudW1iZXIoZHJhZ0RlbHRhWzFdKSkge1xuICAgICAgICAgICAgICAgICAgdG90YWxTaGlmdC54ICs9IGRyYWdEZWx0YVswXTtcbiAgICAgICAgICAgICAgICAgIHRvdGFsU2hpZnQueSArPSBkcmFnRGVsdGFbMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHIuaG92ZXJEYXRhLmRyYWdnaW5nRWxlcyA9IHRydWU7XG4gICAgICAgICAgICBkcmFnZ2VkRWxlcy5zaWxlbnRTaGlmdCh0b3RhbFNoaWZ0KS5lbWl0KCdwb3NpdGlvbiBkcmFnJyk7XG4gICAgICAgICAgICByLnJlZHJhd0hpbnQoJ2RyYWcnLCB0cnVlKTtcblxuICAgICAgICAgICAgaWYgKHIudG91Y2hEYXRhLnN0YXJ0UG9zaXRpb25bMF0gPT0gZWFybGllclswXSAmJiByLnRvdWNoRGF0YS5zdGFydFBvc2l0aW9uWzFdID09IGVhcmxpZXJbMV0pIHtcbiAgICAgICAgICAgICAgci5yZWRyYXdIaW50KCdlbGVzJywgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHIucmVkcmF3KCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG90aGVyaXNlIGtlZXAgdHJhY2sgb2YgZHJhZyBkZWx0YSBmb3IgbGF0ZXJcbiAgICAgICAgICAgIHZhciBkcmFnRGVsdGEgPSByLnRvdWNoRGF0YS5kcmFnRGVsdGEgPSByLnRvdWNoRGF0YS5kcmFnRGVsdGEgfHwgW107XG5cbiAgICAgICAgICAgIGlmIChkcmFnRGVsdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIGRyYWdEZWx0YS5wdXNoKGRpc3BbMF0pO1xuICAgICAgICAgICAgICBkcmFnRGVsdGEucHVzaChkaXNwWzFdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGRyYWdEZWx0YVswXSArPSBkaXNwWzBdO1xuICAgICAgICAgICAgICBkcmFnRGVsdGFbMV0gKz0gZGlzcFsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gdG91Y2htb3ZlXG5cblxuICAgICAgICB7XG4gICAgICAgICAgdHJpZ2dlckV2ZW50cyhzdGFydCB8fCBuZWFyLCBbJ3RvdWNobW92ZScsICd0YXBkcmFnJywgJ3Ztb3VzZW1vdmUnXSwgZSwge1xuICAgICAgICAgICAgeDogbm93WzBdLFxuICAgICAgICAgICAgeTogbm93WzFdXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAoKCFzdGFydCB8fCAhc3RhcnQuZ3JhYmJlZCgpKSAmJiBuZWFyICE9IGxhc3QpIHtcbiAgICAgICAgICAgIGlmIChsYXN0KSB7XG4gICAgICAgICAgICAgIGxhc3QuZW1pdCh7XG4gICAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICAgICAgICB0eXBlOiAndGFwZHJhZ291dCcsXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICAgICAgICAgIHk6IG5vd1sxXVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChuZWFyKSB7XG4gICAgICAgICAgICAgIG5lYXIuZW1pdCh7XG4gICAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICAgICAgICB0eXBlOiAndGFwZHJhZ292ZXInLFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgICB4OiBub3dbMF0sXG4gICAgICAgICAgICAgICAgICB5OiBub3dbMV1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHIudG91Y2hEYXRhLmxhc3QgPSBuZWFyO1xuICAgICAgICB9IC8vIGNoZWNrIHRvIGNhbmNlbCB0YXBob2xkXG5cbiAgICAgICAgaWYgKGNhcHR1cmUpIHtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vdy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKG5vd1tpXSAmJiByLnRvdWNoRGF0YS5zdGFydFBvc2l0aW9uW2ldICYmIGlzT3ZlclRocmVzaG9sZERyYWcpIHtcbiAgICAgICAgICAgICAgci50b3VjaERhdGEuc2luZ2xlVG91Y2hNb3ZlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIHBhbm5pbmdcblxuXG4gICAgICAgIGlmIChjYXB0dXJlICYmIChzdGFydCA9PSBudWxsIHx8IHN0YXJ0LnBhbm5hYmxlKCkpICYmIGN5LnBhbm5pbmdFbmFibGVkKCkgJiYgY3kudXNlclBhbm5pbmdFbmFibGVkKCkpIHtcbiAgICAgICAgICB2YXIgYWxsb3dQYXNzdGhyb3VnaCA9IGFsbG93UGFubmluZ1Bhc3N0aHJvdWdoKHN0YXJ0LCByLnRvdWNoRGF0YS5zdGFydHMpO1xuXG4gICAgICAgICAgaWYgKGFsbG93UGFzc3Rocm91Z2gpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgaWYgKCFyLmRhdGEuYmdBY3RpdmVQb3Npc3Rpb24pIHtcbiAgICAgICAgICAgICAgci5kYXRhLmJnQWN0aXZlUG9zaXN0aW9uID0gYXJyYXkycG9pbnQoci50b3VjaERhdGEuc3RhcnRQb3NpdGlvbik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyLnN3aXBlUGFubmluZykge1xuICAgICAgICAgICAgICBjeS5wYW5CeSh7XG4gICAgICAgICAgICAgICAgeDogZGlzcFswXSAqIHpvb20sXG4gICAgICAgICAgICAgICAgeTogZGlzcFsxXSAqIHpvb21cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT3ZlclRocmVzaG9sZERyYWcpIHtcbiAgICAgICAgICAgICAgci5zd2lwZVBhbm5pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICBjeS5wYW5CeSh7XG4gICAgICAgICAgICAgICAgeDogZHggKiB6b29tLFxuICAgICAgICAgICAgICAgIHk6IGR5ICogem9vbVxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBpZiAoc3RhcnQpIHtcbiAgICAgICAgICAgICAgICBzdGFydC51bmFjdGl2YXRlKCk7XG4gICAgICAgICAgICAgICAgci5yZWRyYXdIaW50KCdzZWxlY3QnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICByLnRvdWNoRGF0YS5zdGFydCA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IC8vIFJlLXByb2plY3RcblxuXG4gICAgICAgICAgdmFyIHBvcyA9IHIucHJvamVjdEludG9WaWV3cG9ydChlLnRvdWNoZXNbMF0uY2xpZW50WCwgZS50b3VjaGVzWzBdLmNsaWVudFkpO1xuICAgICAgICAgIG5vd1swXSA9IHBvc1swXTtcbiAgICAgICAgICBub3dbMV0gPSBwb3NbMV07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbm93Lmxlbmd0aDsgaisrKSB7XG4gICAgICBlYXJsaWVyW2pdID0gbm93W2pdO1xuICAgIH0gLy8gdGhlIGFjdGl2ZSBiZyBpbmRpY2F0b3Igc2hvdWxkIGJlIHJlbW92ZWQgd2hlbiBtYWtpbmcgYSBzd2lwZSB0aGF0IGlzIG5laXRoZXIgZm9yIGRyYWdnaW5nIG5vZGVzIG9yIHBhbm5pbmdcblxuXG4gICAgaWYgKGNhcHR1cmUgJiYgZS50b3VjaGVzLmxlbmd0aCA+IDAgJiYgIXIuaG92ZXJEYXRhLmRyYWdnaW5nRWxlcyAmJiAhci5zd2lwZVBhbm5pbmcgJiYgci5kYXRhLmJnQWN0aXZlUG9zaXN0aW9uICE9IG51bGwpIHtcbiAgICAgIHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgIHIucmVkcmF3SGludCgnc2VsZWN0JywgdHJ1ZSk7XG4gICAgICByLnJlZHJhdygpO1xuICAgIH1cbiAgfSwgZmFsc2UpO1xuICB2YXIgdG91Y2hjYW5jZWxIYW5kbGVyO1xuICByLnJlZ2lzdGVyQmluZGluZyh3aW5kb3csICd0b3VjaGNhbmNlbCcsIHRvdWNoY2FuY2VsSGFuZGxlciA9IGZ1bmN0aW9uIHRvdWNoY2FuY2VsSGFuZGxlcihlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgIHZhciBzdGFydCA9IHIudG91Y2hEYXRhLnN0YXJ0O1xuICAgIHIudG91Y2hEYXRhLmNhcHR1cmUgPSBmYWxzZTtcblxuICAgIGlmIChzdGFydCkge1xuICAgICAgc3RhcnQudW5hY3RpdmF0ZSgpO1xuICAgIH1cbiAgfSk7XG4gIHZhciB0b3VjaGVuZEhhbmRsZXI7XG4gIHIucmVnaXN0ZXJCaW5kaW5nKHdpbmRvdywgJ3RvdWNoZW5kJywgdG91Y2hlbmRIYW5kbGVyID0gZnVuY3Rpb24gdG91Y2hlbmRIYW5kbGVyKGUpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgdmFyIHN0YXJ0ID0gci50b3VjaERhdGEuc3RhcnQ7XG4gICAgdmFyIGNhcHR1cmUgPSByLnRvdWNoRGF0YS5jYXB0dXJlO1xuXG4gICAgaWYgKGNhcHR1cmUpIHtcbiAgICAgIGlmIChlLnRvdWNoZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHIudG91Y2hEYXRhLmNhcHR1cmUgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHNlbGVjdCA9IHIuc2VsZWN0aW9uO1xuICAgIHIuc3dpcGVQYW5uaW5nID0gZmFsc2U7XG4gICAgci5ob3ZlckRhdGEuZHJhZ2dpbmdFbGVzID0gZmFsc2U7XG4gICAgdmFyIGN5ID0gci5jeTtcbiAgICB2YXIgem9vbSA9IGN5Lnpvb20oKTtcbiAgICB2YXIgbm93ID0gci50b3VjaERhdGEubm93O1xuICAgIHZhciBlYXJsaWVyID0gci50b3VjaERhdGEuZWFybGllcjtcblxuICAgIGlmIChlLnRvdWNoZXNbMF0pIHtcbiAgICAgIHZhciBwb3MgPSByLnByb2plY3RJbnRvVmlld3BvcnQoZS50b3VjaGVzWzBdLmNsaWVudFgsIGUudG91Y2hlc1swXS5jbGllbnRZKTtcbiAgICAgIG5vd1swXSA9IHBvc1swXTtcbiAgICAgIG5vd1sxXSA9IHBvc1sxXTtcbiAgICB9XG5cbiAgICBpZiAoZS50b3VjaGVzWzFdKSB7XG4gICAgICB2YXIgcG9zID0gci5wcm9qZWN0SW50b1ZpZXdwb3J0KGUudG91Y2hlc1sxXS5jbGllbnRYLCBlLnRvdWNoZXNbMV0uY2xpZW50WSk7XG4gICAgICBub3dbMl0gPSBwb3NbMF07XG4gICAgICBub3dbM10gPSBwb3NbMV07XG4gICAgfVxuXG4gICAgaWYgKGUudG91Y2hlc1syXSkge1xuICAgICAgdmFyIHBvcyA9IHIucHJvamVjdEludG9WaWV3cG9ydChlLnRvdWNoZXNbMl0uY2xpZW50WCwgZS50b3VjaGVzWzJdLmNsaWVudFkpO1xuICAgICAgbm93WzRdID0gcG9zWzBdO1xuICAgICAgbm93WzVdID0gcG9zWzFdO1xuICAgIH1cblxuICAgIGlmIChzdGFydCkge1xuICAgICAgc3RhcnQudW5hY3RpdmF0ZSgpO1xuICAgIH1cblxuICAgIHZhciBjdHhUYXBlbmQ7XG5cbiAgICBpZiAoci50b3VjaERhdGEuY3h0KSB7XG4gICAgICBjdHhUYXBlbmQgPSB7XG4gICAgICAgIG9yaWdpbmFsRXZlbnQ6IGUsXG4gICAgICAgIHR5cGU6ICdjeHR0YXBlbmQnLFxuICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICB5OiBub3dbMV1cbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgaWYgKHN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0LmVtaXQoY3R4VGFwZW5kKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGN5LmVtaXQoY3R4VGFwZW5kKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFyLnRvdWNoRGF0YS5jeHREcmFnZ2VkKSB7XG4gICAgICAgIHZhciBjdHhUYXAgPSB7XG4gICAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgICB0eXBlOiAnY3h0dGFwJyxcbiAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgeDogbm93WzBdLFxuICAgICAgICAgICAgeTogbm93WzFdXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChzdGFydCkge1xuICAgICAgICAgIHN0YXJ0LmVtaXQoY3R4VGFwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjeS5lbWl0KGN0eFRhcCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHIudG91Y2hEYXRhLnN0YXJ0KSB7XG4gICAgICAgIHIudG91Y2hEYXRhLnN0YXJ0Ll9wcml2YXRlLmdyYWJiZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgci50b3VjaERhdGEuY3h0ID0gZmFsc2U7XG4gICAgICByLnRvdWNoRGF0YS5zdGFydCA9IG51bGw7XG4gICAgICByLnJlZHJhdygpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gbm8gbW9yZSBib3ggc2VsZWN0aW9uIGlmIHdlIGRvbid0IGhhdmUgdGhyZWUgZmluZ2Vyc1xuXG5cbiAgICBpZiAoIWUudG91Y2hlc1syXSAmJiBjeS5ib3hTZWxlY3Rpb25FbmFibGVkKCkgJiYgci50b3VjaERhdGEuc2VsZWN0aW5nKSB7XG4gICAgICByLnRvdWNoRGF0YS5zZWxlY3RpbmcgPSBmYWxzZTtcbiAgICAgIHZhciBib3ggPSBjeS5jb2xsZWN0aW9uKHIuZ2V0QWxsSW5Cb3goc2VsZWN0WzBdLCBzZWxlY3RbMV0sIHNlbGVjdFsyXSwgc2VsZWN0WzNdKSk7XG4gICAgICBzZWxlY3RbMF0gPSB1bmRlZmluZWQ7XG4gICAgICBzZWxlY3RbMV0gPSB1bmRlZmluZWQ7XG4gICAgICBzZWxlY3RbMl0gPSB1bmRlZmluZWQ7XG4gICAgICBzZWxlY3RbM10gPSB1bmRlZmluZWQ7XG4gICAgICBzZWxlY3RbNF0gPSAwO1xuICAgICAgci5yZWRyYXdIaW50KCdzZWxlY3QnLCB0cnVlKTtcbiAgICAgIGN5LmVtaXQoe1xuICAgICAgICB0eXBlOiAnYm94ZW5kJyxcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZSxcbiAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICB4OiBub3dbMF0sXG4gICAgICAgICAgeTogbm93WzFdXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB2YXIgZWxlV291bGRCZVNlbGVjdGVkID0gZnVuY3Rpb24gZWxlV291bGRCZVNlbGVjdGVkKGVsZSkge1xuICAgICAgICByZXR1cm4gZWxlLnNlbGVjdGFibGUoKSAmJiAhZWxlLnNlbGVjdGVkKCk7XG4gICAgICB9O1xuXG4gICAgICBib3guZW1pdCgnYm94Jykuc3RkRmlsdGVyKGVsZVdvdWxkQmVTZWxlY3RlZCkuc2VsZWN0KCkuZW1pdCgnYm94c2VsZWN0Jyk7XG5cbiAgICAgIGlmIChib3gubm9uZW1wdHkoKSkge1xuICAgICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgci5yZWRyYXcoKTtcbiAgICB9XG5cbiAgICBpZiAoc3RhcnQgIT0gbnVsbCkge1xuICAgICAgc3RhcnQudW5hY3RpdmF0ZSgpO1xuICAgIH1cblxuICAgIGlmIChlLnRvdWNoZXNbMl0pIHtcbiAgICAgIHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgIHIucmVkcmF3SGludCgnc2VsZWN0JywgdHJ1ZSk7XG4gICAgfSBlbHNlIGlmIChlLnRvdWNoZXNbMV0pIDsgZWxzZSBpZiAoZS50b3VjaGVzWzBdKSA7IGVsc2UgaWYgKCFlLnRvdWNoZXNbMF0pIHtcbiAgICAgIHIuZGF0YS5iZ0FjdGl2ZVBvc2lzdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgIHIucmVkcmF3SGludCgnc2VsZWN0JywgdHJ1ZSk7XG4gICAgICB2YXIgZHJhZ2dlZEVsZXMgPSByLmRyYWdEYXRhLnRvdWNoRHJhZ0VsZXM7XG5cbiAgICAgIGlmIChzdGFydCAhPSBudWxsKSB7XG4gICAgICAgIHZhciBzdGFydFdhc0dyYWJiZWQgPSBzdGFydC5fcHJpdmF0ZS5ncmFiYmVkO1xuICAgICAgICBmcmVlRHJhZ2dlZEVsZW1lbnRzKGRyYWdnZWRFbGVzKTtcbiAgICAgICAgci5yZWRyYXdIaW50KCdkcmFnJywgdHJ1ZSk7XG4gICAgICAgIHIucmVkcmF3SGludCgnZWxlcycsIHRydWUpO1xuXG4gICAgICAgIGlmIChzdGFydFdhc0dyYWJiZWQpIHtcbiAgICAgICAgICBzdGFydC5lbWl0KCdmcmVlb24nKTtcbiAgICAgICAgICBkcmFnZ2VkRWxlcy5lbWl0KCdmcmVlJyk7XG5cbiAgICAgICAgICBpZiAoci5kcmFnRGF0YS5kaWREcmFnKSB7XG4gICAgICAgICAgICBzdGFydC5lbWl0KCdkcmFnZnJlZW9uJyk7XG4gICAgICAgICAgICBkcmFnZ2VkRWxlcy5lbWl0KCdkcmFnZnJlZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRyaWdnZXJFdmVudHMoc3RhcnQsIFsndG91Y2hlbmQnLCAndGFwZW5kJywgJ3Ztb3VzZXVwJywgJ3RhcGRyYWdvdXQnXSwgZSwge1xuICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICB5OiBub3dbMV1cbiAgICAgICAgfSk7XG4gICAgICAgIHN0YXJ0LnVuYWN0aXZhdGUoKTtcbiAgICAgICAgci50b3VjaERhdGEuc3RhcnQgPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG5lYXIgPSByLmZpbmROZWFyZXN0RWxlbWVudChub3dbMF0sIG5vd1sxXSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgIHRyaWdnZXJFdmVudHMobmVhciwgWyd0b3VjaGVuZCcsICd0YXBlbmQnLCAndm1vdXNldXAnLCAndGFwZHJhZ291dCddLCBlLCB7XG4gICAgICAgICAgeDogbm93WzBdLFxuICAgICAgICAgIHk6IG5vd1sxXVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgdmFyIGR4ID0gci50b3VjaERhdGEuc3RhcnRQb3NpdGlvblswXSAtIG5vd1swXTtcbiAgICAgIHZhciBkeDIgPSBkeCAqIGR4O1xuICAgICAgdmFyIGR5ID0gci50b3VjaERhdGEuc3RhcnRQb3NpdGlvblsxXSAtIG5vd1sxXTtcbiAgICAgIHZhciBkeTIgPSBkeSAqIGR5O1xuICAgICAgdmFyIGRpc3QyID0gZHgyICsgZHkyO1xuICAgICAgdmFyIHJkaXN0MiA9IGRpc3QyICogem9vbSAqIHpvb207IC8vIFRhcCBldmVudCwgcm91Z2hseSBzYW1lIGFzIG1vdXNlIGNsaWNrIGV2ZW50IGZvciB0b3VjaFxuXG4gICAgICBpZiAoIXIudG91Y2hEYXRhLnNpbmdsZVRvdWNoTW92ZWQpIHtcbiAgICAgICAgaWYgKCFzdGFydCkge1xuICAgICAgICAgIGN5LiQoJzpzZWxlY3RlZCcpLnVuc2VsZWN0KFsndGFwdW5zZWxlY3QnXSk7XG4gICAgICAgIH1cblxuICAgICAgICB0cmlnZ2VyRXZlbnRzKHN0YXJ0LCBbJ3RhcCcsICd2Y2xpY2snXSwgZSwge1xuICAgICAgICAgIHg6IG5vd1swXSxcbiAgICAgICAgICB5OiBub3dbMV1cbiAgICAgICAgfSk7XG4gICAgICB9IC8vIFByZXBhcmUgdG8gc2VsZWN0IHRoZSBjdXJyZW50bHkgdG91Y2hlZCBub2RlLCBvbmx5IGlmIGl0IGhhc24ndCBiZWVuIGRyYWdnZWQgcGFzdCBhIGNlcnRhaW4gZGlzdGFuY2VcblxuXG4gICAgICBpZiAoc3RhcnQgIT0gbnVsbCAmJiAhci5kcmFnRGF0YS5kaWREcmFnIC8vIGRpZG4ndCBkcmFnIG5vZGVzIGFyb3VuZFxuICAgICAgJiYgc3RhcnQuX3ByaXZhdGUuc2VsZWN0YWJsZSAmJiByZGlzdDIgPCByLnRvdWNoVGFwVGhyZXNob2xkMiAmJiAhci5waW5jaGluZyAvLyBwaW5jaCB0byB6b29tIHNob3VsZCBub3QgYWZmZWN0IHNlbGVjdGlvblxuICAgICAgKSB7XG4gICAgICAgICAgaWYgKGN5LnNlbGVjdGlvblR5cGUoKSA9PT0gJ3NpbmdsZScpIHtcbiAgICAgICAgICAgIGN5LiQoaXNTZWxlY3RlZCkudW5tZXJnZShzdGFydCkudW5zZWxlY3QoWyd0YXB1bnNlbGVjdCddKTtcbiAgICAgICAgICAgIHN0YXJ0LnNlbGVjdChbJ3RhcHNlbGVjdCddKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHN0YXJ0LnNlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgc3RhcnQudW5zZWxlY3QoWyd0YXB1bnNlbGVjdCddKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHN0YXJ0LnNlbGVjdChbJ3RhcHNlbGVjdCddKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICByLnRvdWNoRGF0YS5zaW5nbGVUb3VjaE1vdmVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG5vdy5sZW5ndGg7IGorKykge1xuICAgICAgZWFybGllcltqXSA9IG5vd1tqXTtcbiAgICB9XG5cbiAgICByLmRyYWdEYXRhLmRpZERyYWcgPSBmYWxzZTsgLy8gcmVzZXQgZm9yIG5leHQgdG91Y2hzdGFydFxuXG4gICAgaWYgKGUudG91Y2hlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHIudG91Y2hEYXRhLmRyYWdEZWx0YSA9IFtdO1xuICAgICAgci50b3VjaERhdGEuc3RhcnRQb3NpdGlvbiA9IG51bGw7XG4gICAgICByLnRvdWNoRGF0YS5zdGFydEdQb3NpdGlvbiA9IG51bGw7XG4gICAgICByLnRvdWNoRGF0YS5kaWRTZWxlY3QgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZS50b3VjaGVzLmxlbmd0aCA8IDIpIHtcbiAgICAgIGlmIChlLnRvdWNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIC8vIHRoZSBvbGQgc3RhcnQgZ2xvYmFsIHBvcyduIG1heSBub3QgYmUgdGhlIHNhbWUgZmluZ2VyIHRoYXQgcmVtYWluc1xuICAgICAgICByLnRvdWNoRGF0YS5zdGFydEdQb3NpdGlvbiA9IFtlLnRvdWNoZXNbMF0uY2xpZW50WCwgZS50b3VjaGVzWzBdLmNsaWVudFldO1xuICAgICAgfVxuXG4gICAgICByLnBpbmNoaW5nID0gZmFsc2U7XG4gICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgICAgIHIucmVkcmF3KCk7XG4gICAgfSAvL3IucmVkcmF3KCk7XG5cbiAgfSwgZmFsc2UpOyAvLyBmYWxsYmFjayBjb21wYXRpYmlsaXR5IGxheWVyIGZvciBtcyBwb2ludGVyIGV2ZW50c1xuXG4gIGlmICh0eXBlb2YgVG91Y2hFdmVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB2YXIgcG9pbnRlcnMgPSBbXTtcblxuICAgIHZhciBtYWtlVG91Y2ggPSBmdW5jdGlvbiBtYWtlVG91Y2goZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2xpZW50WDogZS5jbGllbnRYLFxuICAgICAgICBjbGllbnRZOiBlLmNsaWVudFksXG4gICAgICAgIGZvcmNlOiAxLFxuICAgICAgICBpZGVudGlmaWVyOiBlLnBvaW50ZXJJZCxcbiAgICAgICAgcGFnZVg6IGUucGFnZVgsXG4gICAgICAgIHBhZ2VZOiBlLnBhZ2VZLFxuICAgICAgICByYWRpdXNYOiBlLndpZHRoIC8gMixcbiAgICAgICAgcmFkaXVzWTogZS5oZWlnaHQgLyAyLFxuICAgICAgICBzY3JlZW5YOiBlLnNjcmVlblgsXG4gICAgICAgIHNjcmVlblk6IGUuc2NyZWVuWSxcbiAgICAgICAgdGFyZ2V0OiBlLnRhcmdldFxuICAgICAgfTtcbiAgICB9O1xuXG4gICAgdmFyIG1ha2VQb2ludGVyID0gZnVuY3Rpb24gbWFrZVBvaW50ZXIoZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZXZlbnQ6IGUsXG4gICAgICAgIHRvdWNoOiBtYWtlVG91Y2goZSlcbiAgICAgIH07XG4gICAgfTtcblxuICAgIHZhciBhZGRQb2ludGVyID0gZnVuY3Rpb24gYWRkUG9pbnRlcihlKSB7XG4gICAgICBwb2ludGVycy5wdXNoKG1ha2VQb2ludGVyKGUpKTtcbiAgICB9O1xuXG4gICAgdmFyIHJlbW92ZVBvaW50ZXIgPSBmdW5jdGlvbiByZW1vdmVQb2ludGVyKGUpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHAgPSBwb2ludGVyc1tpXTtcblxuICAgICAgICBpZiAocC5ldmVudC5wb2ludGVySWQgPT09IGUucG9pbnRlcklkKSB7XG4gICAgICAgICAgcG9pbnRlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgdXBkYXRlUG9pbnRlciA9IGZ1bmN0aW9uIHVwZGF0ZVBvaW50ZXIoZSkge1xuICAgICAgdmFyIHAgPSBwb2ludGVycy5maWx0ZXIoZnVuY3Rpb24gKHApIHtcbiAgICAgICAgcmV0dXJuIHAuZXZlbnQucG9pbnRlcklkID09PSBlLnBvaW50ZXJJZDtcbiAgICAgIH0pWzBdO1xuICAgICAgcC5ldmVudCA9IGU7XG4gICAgICBwLnRvdWNoID0gbWFrZVRvdWNoKGUpO1xuICAgIH07XG5cbiAgICB2YXIgYWRkVG91Y2hlc1RvRXZlbnQgPSBmdW5jdGlvbiBhZGRUb3VjaGVzVG9FdmVudChlKSB7XG4gICAgICBlLnRvdWNoZXMgPSBwb2ludGVycy5tYXAoZnVuY3Rpb24gKHApIHtcbiAgICAgICAgcmV0dXJuIHAudG91Y2g7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdmFyIHBvaW50ZXJJc01vdXNlID0gZnVuY3Rpb24gcG9pbnRlcklzTW91c2UoZSkge1xuICAgICAgcmV0dXJuIGUucG9pbnRlclR5cGUgPT09ICdtb3VzZScgfHwgZS5wb2ludGVyVHlwZSA9PT0gNDtcbiAgICB9O1xuXG4gICAgci5yZWdpc3RlckJpbmRpbmcoci5jb250YWluZXIsICdwb2ludGVyZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpZiAocG9pbnRlcklzTW91c2UoZSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBtb3VzZSBhbHJlYWR5IGhhbmRsZWRcblxuXG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBhZGRQb2ludGVyKGUpO1xuICAgICAgYWRkVG91Y2hlc1RvRXZlbnQoZSk7XG4gICAgICB0b3VjaHN0YXJ0SGFuZGxlcihlKTtcbiAgICB9KTtcbiAgICByLnJlZ2lzdGVyQmluZGluZyhyLmNvbnRhaW5lciwgJ3BvaW50ZXJ1cCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpZiAocG9pbnRlcklzTW91c2UoZSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBtb3VzZSBhbHJlYWR5IGhhbmRsZWRcblxuXG4gICAgICByZW1vdmVQb2ludGVyKGUpO1xuICAgICAgYWRkVG91Y2hlc1RvRXZlbnQoZSk7XG4gICAgICB0b3VjaGVuZEhhbmRsZXIoZSk7XG4gICAgfSk7XG4gICAgci5yZWdpc3RlckJpbmRpbmcoci5jb250YWluZXIsICdwb2ludGVyY2FuY2VsJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmIChwb2ludGVySXNNb3VzZShlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIG1vdXNlIGFscmVhZHkgaGFuZGxlZFxuXG5cbiAgICAgIHJlbW92ZVBvaW50ZXIoZSk7XG4gICAgICBhZGRUb3VjaGVzVG9FdmVudChlKTtcbiAgICAgIHRvdWNoY2FuY2VsSGFuZGxlcihlKTtcbiAgICB9KTtcbiAgICByLnJlZ2lzdGVyQmluZGluZyhyLmNvbnRhaW5lciwgJ3BvaW50ZXJtb3ZlJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmIChwb2ludGVySXNNb3VzZShlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIG1vdXNlIGFscmVhZHkgaGFuZGxlZFxuXG5cbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHVwZGF0ZVBvaW50ZXIoZSk7XG4gICAgICBhZGRUb3VjaGVzVG9FdmVudChlKTtcbiAgICAgIHRvdWNobW92ZUhhbmRsZXIoZSk7XG4gICAgfSk7XG4gIH1cbn07XG5cbnZhciBCUnAkZCA9IHt9O1xuXG5CUnAkZC5nZW5lcmF0ZVBvbHlnb24gPSBmdW5jdGlvbiAobmFtZSwgcG9pbnRzKSB7XG4gIHJldHVybiB0aGlzLm5vZGVTaGFwZXNbbmFtZV0gPSB7XG4gICAgcmVuZGVyZXI6IHRoaXMsXG4gICAgbmFtZTogbmFtZSxcbiAgICBwb2ludHM6IHBvaW50cyxcbiAgICBkcmF3OiBmdW5jdGlvbiBkcmF3KGNvbnRleHQsIGNlbnRlclgsIGNlbnRlclksIHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgIHRoaXMucmVuZGVyZXIubm9kZVNoYXBlSW1wbCgncG9seWdvbicsIGNvbnRleHQsIGNlbnRlclgsIGNlbnRlclksIHdpZHRoLCBoZWlnaHQsIHRoaXMucG9pbnRzKTtcbiAgICB9LFxuICAgIGludGVyc2VjdExpbmU6IGZ1bmN0aW9uIGludGVyc2VjdExpbmUobm9kZVgsIG5vZGVZLCB3aWR0aCwgaGVpZ2h0LCB4LCB5LCBwYWRkaW5nKSB7XG4gICAgICByZXR1cm4gcG9seWdvbkludGVyc2VjdExpbmUoeCwgeSwgdGhpcy5wb2ludHMsIG5vZGVYLCBub2RlWSwgd2lkdGggLyAyLCBoZWlnaHQgLyAyLCBwYWRkaW5nKTtcbiAgICB9LFxuICAgIGNoZWNrUG9pbnQ6IGZ1bmN0aW9uIGNoZWNrUG9pbnQoeCwgeSwgcGFkZGluZywgd2lkdGgsIGhlaWdodCwgY2VudGVyWCwgY2VudGVyWSkge1xuICAgICAgcmV0dXJuIHBvaW50SW5zaWRlUG9seWdvbih4LCB5LCB0aGlzLnBvaW50cywgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCwgWzAsIC0xXSwgcGFkZGluZyk7XG4gICAgfVxuICB9O1xufTtcblxuQlJwJGQuZ2VuZXJhdGVFbGxpcHNlID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5ub2RlU2hhcGVzWydlbGxpcHNlJ10gPSB7XG4gICAgcmVuZGVyZXI6IHRoaXMsXG4gICAgbmFtZTogJ2VsbGlwc2UnLFxuICAgIGRyYXc6IGZ1bmN0aW9uIGRyYXcoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCkge1xuICAgICAgdGhpcy5yZW5kZXJlci5ub2RlU2hhcGVJbXBsKHRoaXMubmFtZSwgY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCk7XG4gICAgfSxcbiAgICBpbnRlcnNlY3RMaW5lOiBmdW5jdGlvbiBpbnRlcnNlY3RMaW5lKG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCwgeCwgeSwgcGFkZGluZykge1xuICAgICAgcmV0dXJuIGludGVyc2VjdExpbmVFbGxpcHNlKHgsIHksIG5vZGVYLCBub2RlWSwgd2lkdGggLyAyICsgcGFkZGluZywgaGVpZ2h0IC8gMiArIHBhZGRpbmcpO1xuICAgIH0sXG4gICAgY2hlY2tQb2ludDogZnVuY3Rpb24gY2hlY2tQb2ludCh4LCB5LCBwYWRkaW5nLCB3aWR0aCwgaGVpZ2h0LCBjZW50ZXJYLCBjZW50ZXJZKSB7XG4gICAgICByZXR1cm4gY2hlY2tJbkVsbGlwc2UoeCwgeSwgd2lkdGgsIGhlaWdodCwgY2VudGVyWCwgY2VudGVyWSwgcGFkZGluZyk7XG4gICAgfVxuICB9O1xufTtcblxuQlJwJGQuZ2VuZXJhdGVSb3VuZFBvbHlnb24gPSBmdW5jdGlvbiAobmFtZSwgcG9pbnRzKSB7XG4gIC8vIFByZS1jb21wdXRlIGNvbnRyb2wgcG9pbnRzXG4gIC8vIFNpbmNlIHRoZXNlIHBvaW50cyBkZXBlbmQgb24gdGhlIHJhZGl1cyBsZW5ndGggKHdoaWNoIGluIHR1cm5zIGRlcGVuZCBvbiB0aGUgd2lkdGgvaGVpZ2h0IG9mIHRoZSBub2RlKSB3ZSB3aWxsIG9ubHkgcHJlLWNvbXB1dGVcbiAgLy8gdGhlIHVuaXQgdmVjdG9ycy5cbiAgLy8gRm9yIHNpbXBsaWNpdHkgdGhlIGxheW91dCB3aWxsIGJlOlxuICAvLyBbIHAwLCBVbml0VmVjdG9yUDBQMSwgcDEsIFVuaVZlY3RvclAxUDIsIC4uLiwgcG4sIFVuaXRWZWN0b3JQblAwIF1cbiAgdmFyIGFsbFBvaW50cyA9IG5ldyBBcnJheShwb2ludHMubGVuZ3RoICogMik7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoIC8gMjsgaSsrKSB7XG4gICAgdmFyIHNvdXJjZUluZGV4ID0gaSAqIDI7XG4gICAgdmFyIGRlc3RJbmRleCA9IHZvaWQgMDtcblxuICAgIGlmIChpIDwgcG9pbnRzLmxlbmd0aCAvIDIgLSAxKSB7XG4gICAgICBkZXN0SW5kZXggPSAoaSArIDEpICogMjtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVzdEluZGV4ID0gMDtcbiAgICB9XG5cbiAgICBhbGxQb2ludHNbaSAqIDRdID0gcG9pbnRzW3NvdXJjZUluZGV4XTtcbiAgICBhbGxQb2ludHNbaSAqIDQgKyAxXSA9IHBvaW50c1tzb3VyY2VJbmRleCArIDFdO1xuICAgIHZhciB4RGVzdCA9IHBvaW50c1tkZXN0SW5kZXhdIC0gcG9pbnRzW3NvdXJjZUluZGV4XTtcbiAgICB2YXIgeURlc3QgPSBwb2ludHNbZGVzdEluZGV4ICsgMV0gLSBwb2ludHNbc291cmNlSW5kZXggKyAxXTtcbiAgICB2YXIgbm9ybSA9IE1hdGguc3FydCh4RGVzdCAqIHhEZXN0ICsgeURlc3QgKiB5RGVzdCk7XG4gICAgYWxsUG9pbnRzW2kgKiA0ICsgMl0gPSB4RGVzdCAvIG5vcm07XG4gICAgYWxsUG9pbnRzW2kgKiA0ICsgM10gPSB5RGVzdCAvIG5vcm07XG4gIH1cblxuICByZXR1cm4gdGhpcy5ub2RlU2hhcGVzW25hbWVdID0ge1xuICAgIHJlbmRlcmVyOiB0aGlzLFxuICAgIG5hbWU6IG5hbWUsXG4gICAgcG9pbnRzOiBhbGxQb2ludHMsXG4gICAgZHJhdzogZnVuY3Rpb24gZHJhdyhjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLm5vZGVTaGFwZUltcGwoJ3JvdW5kLXBvbHlnb24nLCBjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0LCB0aGlzLnBvaW50cyk7XG4gICAgfSxcbiAgICBpbnRlcnNlY3RMaW5lOiBmdW5jdGlvbiBpbnRlcnNlY3RMaW5lKG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCwgeCwgeSwgcGFkZGluZykge1xuICAgICAgcmV0dXJuIHJvdW5kUG9seWdvbkludGVyc2VjdExpbmUoeCwgeSwgdGhpcy5wb2ludHMsIG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCk7XG4gICAgfSxcbiAgICBjaGVja1BvaW50OiBmdW5jdGlvbiBjaGVja1BvaW50KHgsIHksIHBhZGRpbmcsIHdpZHRoLCBoZWlnaHQsIGNlbnRlclgsIGNlbnRlclkpIHtcbiAgICAgIHJldHVybiBwb2ludEluc2lkZVJvdW5kUG9seWdvbih4LCB5LCB0aGlzLnBvaW50cywgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCk7XG4gICAgfVxuICB9O1xufTtcblxuQlJwJGQuZ2VuZXJhdGVSb3VuZFJlY3RhbmdsZSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMubm9kZVNoYXBlc1sncm91bmQtcmVjdGFuZ2xlJ10gPSB0aGlzLm5vZGVTaGFwZXNbJ3JvdW5kcmVjdGFuZ2xlJ10gPSB7XG4gICAgcmVuZGVyZXI6IHRoaXMsXG4gICAgbmFtZTogJ3JvdW5kLXJlY3RhbmdsZScsXG4gICAgcG9pbnRzOiBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzRml0VG9TcXVhcmUoNCwgMCksXG4gICAgZHJhdzogZnVuY3Rpb24gZHJhdyhjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLm5vZGVTaGFwZUltcGwodGhpcy5uYW1lLCBjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICB9LFxuICAgIGludGVyc2VjdExpbmU6IGZ1bmN0aW9uIGludGVyc2VjdExpbmUobm9kZVgsIG5vZGVZLCB3aWR0aCwgaGVpZ2h0LCB4LCB5LCBwYWRkaW5nKSB7XG4gICAgICByZXR1cm4gcm91bmRSZWN0YW5nbGVJbnRlcnNlY3RMaW5lKHgsIHksIG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCwgcGFkZGluZyk7XG4gICAgfSxcbiAgICBjaGVja1BvaW50OiBmdW5jdGlvbiBjaGVja1BvaW50KHgsIHksIHBhZGRpbmcsIHdpZHRoLCBoZWlnaHQsIGNlbnRlclgsIGNlbnRlclkpIHtcbiAgICAgIHZhciBjb3JuZXJSYWRpdXMgPSBnZXRSb3VuZFJlY3RhbmdsZVJhZGl1cyh3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIHZhciBkaWFtID0gY29ybmVyUmFkaXVzICogMjsgLy8gQ2hlY2sgaEJveFxuXG4gICAgICBpZiAocG9pbnRJbnNpZGVQb2x5Z29uKHgsIHksIHRoaXMucG9pbnRzLCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0IC0gZGlhbSwgWzAsIC0xXSwgcGFkZGluZykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IC8vIENoZWNrIHZCb3hcblxuXG4gICAgICBpZiAocG9pbnRJbnNpZGVQb2x5Z29uKHgsIHksIHRoaXMucG9pbnRzLCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCAtIGRpYW0sIGhlaWdodCwgWzAsIC0xXSwgcGFkZGluZykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IC8vIENoZWNrIHRvcCBsZWZ0IHF1YXJ0ZXIgY2lyY2xlXG5cblxuICAgICAgaWYgKGNoZWNrSW5FbGxpcHNlKHgsIHksIGRpYW0sIGRpYW0sIGNlbnRlclggLSB3aWR0aCAvIDIgKyBjb3JuZXJSYWRpdXMsIGNlbnRlclkgLSBoZWlnaHQgLyAyICsgY29ybmVyUmFkaXVzLCBwYWRkaW5nKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gLy8gQ2hlY2sgdG9wIHJpZ2h0IHF1YXJ0ZXIgY2lyY2xlXG5cblxuICAgICAgaWYgKGNoZWNrSW5FbGxpcHNlKHgsIHksIGRpYW0sIGRpYW0sIGNlbnRlclggKyB3aWR0aCAvIDIgLSBjb3JuZXJSYWRpdXMsIGNlbnRlclkgLSBoZWlnaHQgLyAyICsgY29ybmVyUmFkaXVzLCBwYWRkaW5nKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gLy8gQ2hlY2sgYm90dG9tIHJpZ2h0IHF1YXJ0ZXIgY2lyY2xlXG5cblxuICAgICAgaWYgKGNoZWNrSW5FbGxpcHNlKHgsIHksIGRpYW0sIGRpYW0sIGNlbnRlclggKyB3aWR0aCAvIDIgLSBjb3JuZXJSYWRpdXMsIGNlbnRlclkgKyBoZWlnaHQgLyAyIC0gY29ybmVyUmFkaXVzLCBwYWRkaW5nKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gLy8gQ2hlY2sgYm90dG9tIGxlZnQgcXVhcnRlciBjaXJjbGVcblxuXG4gICAgICBpZiAoY2hlY2tJbkVsbGlwc2UoeCwgeSwgZGlhbSwgZGlhbSwgY2VudGVyWCAtIHdpZHRoIC8gMiArIGNvcm5lclJhZGl1cywgY2VudGVyWSArIGhlaWdodCAvIDIgLSBjb3JuZXJSYWRpdXMsIHBhZGRpbmcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9O1xufTtcblxuQlJwJGQuZ2VuZXJhdGVDdXRSZWN0YW5nbGUgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLm5vZGVTaGFwZXNbJ2N1dC1yZWN0YW5nbGUnXSA9IHRoaXMubm9kZVNoYXBlc1snY3V0cmVjdGFuZ2xlJ10gPSB7XG4gICAgcmVuZGVyZXI6IHRoaXMsXG4gICAgbmFtZTogJ2N1dC1yZWN0YW5nbGUnLFxuICAgIGNvcm5lckxlbmd0aDogZ2V0Q3V0UmVjdGFuZ2xlQ29ybmVyTGVuZ3RoKCksXG4gICAgcG9pbnRzOiBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzRml0VG9TcXVhcmUoNCwgMCksXG4gICAgZHJhdzogZnVuY3Rpb24gZHJhdyhjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLm5vZGVTaGFwZUltcGwodGhpcy5uYW1lLCBjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICB9LFxuICAgIGdlbmVyYXRlQ3V0VHJpYW5nbGVQdHM6IGZ1bmN0aW9uIGdlbmVyYXRlQ3V0VHJpYW5nbGVQdHMod2lkdGgsIGhlaWdodCwgY2VudGVyWCwgY2VudGVyWSkge1xuICAgICAgdmFyIGNsID0gdGhpcy5jb3JuZXJMZW5ndGg7XG4gICAgICB2YXIgaGggPSBoZWlnaHQgLyAyO1xuICAgICAgdmFyIGh3ID0gd2lkdGggLyAyO1xuICAgICAgdmFyIHhCZWdpbiA9IGNlbnRlclggLSBodztcbiAgICAgIHZhciB4RW5kID0gY2VudGVyWCArIGh3O1xuICAgICAgdmFyIHlCZWdpbiA9IGNlbnRlclkgLSBoaDtcbiAgICAgIHZhciB5RW5kID0gY2VudGVyWSArIGhoOyAvLyBwb2ludHMgYXJlIGluIGNsb2Nrd2lzZSBvcmRlciwgaW5uZXIgKGltYWdpbmFyeSkgdHJpYW5nbGUgcHQgb24gWzQsIDVdXG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRvcExlZnQ6IFt4QmVnaW4sIHlCZWdpbiArIGNsLCB4QmVnaW4gKyBjbCwgeUJlZ2luLCB4QmVnaW4gKyBjbCwgeUJlZ2luICsgY2xdLFxuICAgICAgICB0b3BSaWdodDogW3hFbmQgLSBjbCwgeUJlZ2luLCB4RW5kLCB5QmVnaW4gKyBjbCwgeEVuZCAtIGNsLCB5QmVnaW4gKyBjbF0sXG4gICAgICAgIGJvdHRvbVJpZ2h0OiBbeEVuZCwgeUVuZCAtIGNsLCB4RW5kIC0gY2wsIHlFbmQsIHhFbmQgLSBjbCwgeUVuZCAtIGNsXSxcbiAgICAgICAgYm90dG9tTGVmdDogW3hCZWdpbiArIGNsLCB5RW5kLCB4QmVnaW4sIHlFbmQgLSBjbCwgeEJlZ2luICsgY2wsIHlFbmQgLSBjbF1cbiAgICAgIH07XG4gICAgfSxcbiAgICBpbnRlcnNlY3RMaW5lOiBmdW5jdGlvbiBpbnRlcnNlY3RMaW5lKG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCwgeCwgeSwgcGFkZGluZykge1xuICAgICAgdmFyIGNQdHMgPSB0aGlzLmdlbmVyYXRlQ3V0VHJpYW5nbGVQdHMod2lkdGggKyAyICogcGFkZGluZywgaGVpZ2h0ICsgMiAqIHBhZGRpbmcsIG5vZGVYLCBub2RlWSk7XG4gICAgICB2YXIgcHRzID0gW10uY29uY2F0LmFwcGx5KFtdLCBbY1B0cy50b3BMZWZ0LnNwbGljZSgwLCA0KSwgY1B0cy50b3BSaWdodC5zcGxpY2UoMCwgNCksIGNQdHMuYm90dG9tUmlnaHQuc3BsaWNlKDAsIDQpLCBjUHRzLmJvdHRvbUxlZnQuc3BsaWNlKDAsIDQpXSk7XG4gICAgICByZXR1cm4gcG9seWdvbkludGVyc2VjdExpbmUoeCwgeSwgcHRzLCBub2RlWCwgbm9kZVkpO1xuICAgIH0sXG4gICAgY2hlY2tQb2ludDogZnVuY3Rpb24gY2hlY2tQb2ludCh4LCB5LCBwYWRkaW5nLCB3aWR0aCwgaGVpZ2h0LCBjZW50ZXJYLCBjZW50ZXJZKSB7XG4gICAgICAvLyBDaGVjayBoQm94XG4gICAgICBpZiAocG9pbnRJbnNpZGVQb2x5Z29uKHgsIHksIHRoaXMucG9pbnRzLCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0IC0gMiAqIHRoaXMuY29ybmVyTGVuZ3RoLCBbMCwgLTFdLCBwYWRkaW5nKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gLy8gQ2hlY2sgdkJveFxuXG5cbiAgICAgIGlmIChwb2ludEluc2lkZVBvbHlnb24oeCwgeSwgdGhpcy5wb2ludHMsIGNlbnRlclgsIGNlbnRlclksIHdpZHRoIC0gMiAqIHRoaXMuY29ybmVyTGVuZ3RoLCBoZWlnaHQsIFswLCAtMV0sIHBhZGRpbmcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3V0VHJpYW5nbGVQdHMgPSB0aGlzLmdlbmVyYXRlQ3V0VHJpYW5nbGVQdHMod2lkdGgsIGhlaWdodCwgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICByZXR1cm4gcG9pbnRJbnNpZGVQb2x5Z29uUG9pbnRzKHgsIHksIGN1dFRyaWFuZ2xlUHRzLnRvcExlZnQpIHx8IHBvaW50SW5zaWRlUG9seWdvblBvaW50cyh4LCB5LCBjdXRUcmlhbmdsZVB0cy50b3BSaWdodCkgfHwgcG9pbnRJbnNpZGVQb2x5Z29uUG9pbnRzKHgsIHksIGN1dFRyaWFuZ2xlUHRzLmJvdHRvbVJpZ2h0KSB8fCBwb2ludEluc2lkZVBvbHlnb25Qb2ludHMoeCwgeSwgY3V0VHJpYW5nbGVQdHMuYm90dG9tTGVmdCk7XG4gICAgfVxuICB9O1xufTtcblxuQlJwJGQuZ2VuZXJhdGVCYXJyZWwgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLm5vZGVTaGFwZXNbJ2JhcnJlbCddID0ge1xuICAgIHJlbmRlcmVyOiB0aGlzLFxuICAgIG5hbWU6ICdiYXJyZWwnLFxuICAgIHBvaW50czogZ2VuZXJhdGVVbml0TmdvblBvaW50c0ZpdFRvU3F1YXJlKDQsIDApLFxuICAgIGRyYXc6IGZ1bmN0aW9uIGRyYXcoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCkge1xuICAgICAgdGhpcy5yZW5kZXJlci5ub2RlU2hhcGVJbXBsKHRoaXMubmFtZSwgY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCk7XG4gICAgfSxcbiAgICBpbnRlcnNlY3RMaW5lOiBmdW5jdGlvbiBpbnRlcnNlY3RMaW5lKG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCwgeCwgeSwgcGFkZGluZykge1xuICAgICAgLy8gdXNlIHR3byBmaXhlZCB0IHZhbHVlcyBmb3IgdGhlIGJlemllciBjdXJ2ZSBhcHByb3hpbWF0aW9uXG4gICAgICB2YXIgdDAgPSAwLjE1O1xuICAgICAgdmFyIHQxID0gMC41O1xuICAgICAgdmFyIHQyID0gMC44NTtcbiAgICAgIHZhciBiUHRzID0gdGhpcy5nZW5lcmF0ZUJhcnJlbEJlemllclB0cyh3aWR0aCArIDIgKiBwYWRkaW5nLCBoZWlnaHQgKyAyICogcGFkZGluZywgbm9kZVgsIG5vZGVZKTtcblxuICAgICAgdmFyIGFwcHJveGltYXRlQmFycmVsQ3VydmVQdHMgPSBmdW5jdGlvbiBhcHByb3hpbWF0ZUJhcnJlbEN1cnZlUHRzKHB0cykge1xuICAgICAgICAvLyBhcHByb3hpbWF0ZSBjdXJ2ZSBwdHMgYmFzZWQgb24gdGhlIHR3byB0IHZhbHVlc1xuICAgICAgICB2YXIgbTAgPSBxYmV6aWVyUHRBdCh7XG4gICAgICAgICAgeDogcHRzWzBdLFxuICAgICAgICAgIHk6IHB0c1sxXVxuICAgICAgICB9LCB7XG4gICAgICAgICAgeDogcHRzWzJdLFxuICAgICAgICAgIHk6IHB0c1szXVxuICAgICAgICB9LCB7XG4gICAgICAgICAgeDogcHRzWzRdLFxuICAgICAgICAgIHk6IHB0c1s1XVxuICAgICAgICB9LCB0MCk7XG4gICAgICAgIHZhciBtMSA9IHFiZXppZXJQdEF0KHtcbiAgICAgICAgICB4OiBwdHNbMF0sXG4gICAgICAgICAgeTogcHRzWzFdXG4gICAgICAgIH0sIHtcbiAgICAgICAgICB4OiBwdHNbMl0sXG4gICAgICAgICAgeTogcHRzWzNdXG4gICAgICAgIH0sIHtcbiAgICAgICAgICB4OiBwdHNbNF0sXG4gICAgICAgICAgeTogcHRzWzVdXG4gICAgICAgIH0sIHQxKTtcbiAgICAgICAgdmFyIG0yID0gcWJlemllclB0QXQoe1xuICAgICAgICAgIHg6IHB0c1swXSxcbiAgICAgICAgICB5OiBwdHNbMV1cbiAgICAgICAgfSwge1xuICAgICAgICAgIHg6IHB0c1syXSxcbiAgICAgICAgICB5OiBwdHNbM11cbiAgICAgICAgfSwge1xuICAgICAgICAgIHg6IHB0c1s0XSxcbiAgICAgICAgICB5OiBwdHNbNV1cbiAgICAgICAgfSwgdDIpO1xuICAgICAgICByZXR1cm4gW3B0c1swXSwgcHRzWzFdLCBtMC54LCBtMC55LCBtMS54LCBtMS55LCBtMi54LCBtMi55LCBwdHNbNF0sIHB0c1s1XV07XG4gICAgICB9O1xuXG4gICAgICB2YXIgcHRzID0gW10uY29uY2F0KGFwcHJveGltYXRlQmFycmVsQ3VydmVQdHMoYlB0cy50b3BMZWZ0KSwgYXBwcm94aW1hdGVCYXJyZWxDdXJ2ZVB0cyhiUHRzLnRvcFJpZ2h0KSwgYXBwcm94aW1hdGVCYXJyZWxDdXJ2ZVB0cyhiUHRzLmJvdHRvbVJpZ2h0KSwgYXBwcm94aW1hdGVCYXJyZWxDdXJ2ZVB0cyhiUHRzLmJvdHRvbUxlZnQpKTtcbiAgICAgIHJldHVybiBwb2x5Z29uSW50ZXJzZWN0TGluZSh4LCB5LCBwdHMsIG5vZGVYLCBub2RlWSk7XG4gICAgfSxcbiAgICBnZW5lcmF0ZUJhcnJlbEJlemllclB0czogZnVuY3Rpb24gZ2VuZXJhdGVCYXJyZWxCZXppZXJQdHMod2lkdGgsIGhlaWdodCwgY2VudGVyWCwgY2VudGVyWSkge1xuICAgICAgdmFyIGhoID0gaGVpZ2h0IC8gMjtcbiAgICAgIHZhciBodyA9IHdpZHRoIC8gMjtcbiAgICAgIHZhciB4QmVnaW4gPSBjZW50ZXJYIC0gaHc7XG4gICAgICB2YXIgeEVuZCA9IGNlbnRlclggKyBodztcbiAgICAgIHZhciB5QmVnaW4gPSBjZW50ZXJZIC0gaGg7XG4gICAgICB2YXIgeUVuZCA9IGNlbnRlclkgKyBoaDtcbiAgICAgIHZhciBjdXJ2ZUNvbnN0YW50cyA9IGdldEJhcnJlbEN1cnZlQ29uc3RhbnRzKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgdmFyIGhPZmZzZXQgPSBjdXJ2ZUNvbnN0YW50cy5oZWlnaHRPZmZzZXQ7XG4gICAgICB2YXIgd09mZnNldCA9IGN1cnZlQ29uc3RhbnRzLndpZHRoT2Zmc2V0O1xuICAgICAgdmFyIGN0cmxQdFhPZmZzZXQgPSBjdXJ2ZUNvbnN0YW50cy5jdHJsUHRPZmZzZXRQY3QgKiB3aWR0aDsgLy8gcG9pbnRzIGFyZSBpbiBjbG9ja3dpc2Ugb3JkZXIsIGlubmVyIChpbWFnaW5hcnkpIGNvbnRyb2wgcHQgb24gWzQsIDVdXG5cbiAgICAgIHZhciBwdHMgPSB7XG4gICAgICAgIHRvcExlZnQ6IFt4QmVnaW4sIHlCZWdpbiArIGhPZmZzZXQsIHhCZWdpbiArIGN0cmxQdFhPZmZzZXQsIHlCZWdpbiwgeEJlZ2luICsgd09mZnNldCwgeUJlZ2luXSxcbiAgICAgICAgdG9wUmlnaHQ6IFt4RW5kIC0gd09mZnNldCwgeUJlZ2luLCB4RW5kIC0gY3RybFB0WE9mZnNldCwgeUJlZ2luLCB4RW5kLCB5QmVnaW4gKyBoT2Zmc2V0XSxcbiAgICAgICAgYm90dG9tUmlnaHQ6IFt4RW5kLCB5RW5kIC0gaE9mZnNldCwgeEVuZCAtIGN0cmxQdFhPZmZzZXQsIHlFbmQsIHhFbmQgLSB3T2Zmc2V0LCB5RW5kXSxcbiAgICAgICAgYm90dG9tTGVmdDogW3hCZWdpbiArIHdPZmZzZXQsIHlFbmQsIHhCZWdpbiArIGN0cmxQdFhPZmZzZXQsIHlFbmQsIHhCZWdpbiwgeUVuZCAtIGhPZmZzZXRdXG4gICAgICB9O1xuICAgICAgcHRzLnRvcExlZnQuaXNUb3AgPSB0cnVlO1xuICAgICAgcHRzLnRvcFJpZ2h0LmlzVG9wID0gdHJ1ZTtcbiAgICAgIHB0cy5ib3R0b21MZWZ0LmlzQm90dG9tID0gdHJ1ZTtcbiAgICAgIHB0cy5ib3R0b21SaWdodC5pc0JvdHRvbSA9IHRydWU7XG4gICAgICByZXR1cm4gcHRzO1xuICAgIH0sXG4gICAgY2hlY2tQb2ludDogZnVuY3Rpb24gY2hlY2tQb2ludCh4LCB5LCBwYWRkaW5nLCB3aWR0aCwgaGVpZ2h0LCBjZW50ZXJYLCBjZW50ZXJZKSB7XG4gICAgICB2YXIgY3VydmVDb25zdGFudHMgPSBnZXRCYXJyZWxDdXJ2ZUNvbnN0YW50cyh3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIHZhciBoT2Zmc2V0ID0gY3VydmVDb25zdGFudHMuaGVpZ2h0T2Zmc2V0O1xuICAgICAgdmFyIHdPZmZzZXQgPSBjdXJ2ZUNvbnN0YW50cy53aWR0aE9mZnNldDsgLy8gQ2hlY2sgaEJveFxuXG4gICAgICBpZiAocG9pbnRJbnNpZGVQb2x5Z29uKHgsIHksIHRoaXMucG9pbnRzLCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0IC0gMiAqIGhPZmZzZXQsIFswLCAtMV0sIHBhZGRpbmcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSAvLyBDaGVjayB2Qm94XG5cblxuICAgICAgaWYgKHBvaW50SW5zaWRlUG9seWdvbih4LCB5LCB0aGlzLnBvaW50cywgY2VudGVyWCwgY2VudGVyWSwgd2lkdGggLSAyICogd09mZnNldCwgaGVpZ2h0LCBbMCwgLTFdLCBwYWRkaW5nKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIGJhcnJlbEN1cnZlUHRzID0gdGhpcy5nZW5lcmF0ZUJhcnJlbEJlemllclB0cyh3aWR0aCwgaGVpZ2h0LCBjZW50ZXJYLCBjZW50ZXJZKTtcblxuICAgICAgdmFyIGdldEN1cnZlVCA9IGZ1bmN0aW9uIGdldEN1cnZlVCh4LCB5LCBjdXJ2ZVB0cykge1xuICAgICAgICB2YXIgeDAgPSBjdXJ2ZVB0c1s0XTtcbiAgICAgICAgdmFyIHgxID0gY3VydmVQdHNbMl07XG4gICAgICAgIHZhciB4MiA9IGN1cnZlUHRzWzBdO1xuICAgICAgICB2YXIgeTAgPSBjdXJ2ZVB0c1s1XTsgLy8gdmFyIHkxID0gY3VydmVQdHNbIDMgXTtcblxuICAgICAgICB2YXIgeTIgPSBjdXJ2ZVB0c1sxXTtcbiAgICAgICAgdmFyIHhNaW4gPSBNYXRoLm1pbih4MCwgeDIpO1xuICAgICAgICB2YXIgeE1heCA9IE1hdGgubWF4KHgwLCB4Mik7XG4gICAgICAgIHZhciB5TWluID0gTWF0aC5taW4oeTAsIHkyKTtcbiAgICAgICAgdmFyIHlNYXggPSBNYXRoLm1heCh5MCwgeTIpO1xuXG4gICAgICAgIGlmICh4TWluIDw9IHggJiYgeCA8PSB4TWF4ICYmIHlNaW4gPD0geSAmJiB5IDw9IHlNYXgpIHtcbiAgICAgICAgICB2YXIgY29lZmYgPSBiZXppZXJQdHNUb1F1YWRDb2VmZih4MCwgeDEsIHgyKTtcbiAgICAgICAgICB2YXIgcm9vdHMgPSBzb2x2ZVF1YWRyYXRpYyhjb2VmZlswXSwgY29lZmZbMV0sIGNvZWZmWzJdLCB4KTtcbiAgICAgICAgICB2YXIgdmFsaWRSb290cyA9IHJvb3RzLmZpbHRlcihmdW5jdGlvbiAocikge1xuICAgICAgICAgICAgcmV0dXJuIDAgPD0gciAmJiByIDw9IDE7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAodmFsaWRSb290cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWRSb290c1swXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH07XG5cbiAgICAgIHZhciBjdXJ2ZVJlZ2lvbnMgPSBPYmplY3Qua2V5cyhiYXJyZWxDdXJ2ZVB0cyk7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY3VydmVSZWdpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjb3JuZXIgPSBjdXJ2ZVJlZ2lvbnNbaV07XG4gICAgICAgIHZhciBjb3JuZXJQdHMgPSBiYXJyZWxDdXJ2ZVB0c1tjb3JuZXJdO1xuICAgICAgICB2YXIgdCA9IGdldEN1cnZlVCh4LCB5LCBjb3JuZXJQdHMpO1xuXG4gICAgICAgIGlmICh0ID09IG51bGwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB5MCA9IGNvcm5lclB0c1s1XTtcbiAgICAgICAgdmFyIHkxID0gY29ybmVyUHRzWzNdO1xuICAgICAgICB2YXIgeTIgPSBjb3JuZXJQdHNbMV07XG4gICAgICAgIHZhciBiZXpZID0gcWJlemllckF0KHkwLCB5MSwgeTIsIHQpO1xuXG4gICAgICAgIGlmIChjb3JuZXJQdHMuaXNUb3AgJiYgYmV6WSA8PSB5KSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29ybmVyUHRzLmlzQm90dG9tICYmIHkgPD0gYmV6WSkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG59O1xuXG5CUnAkZC5nZW5lcmF0ZUJvdHRvbVJvdW5kcmVjdGFuZ2xlID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5ub2RlU2hhcGVzWydib3R0b20tcm91bmQtcmVjdGFuZ2xlJ10gPSB0aGlzLm5vZGVTaGFwZXNbJ2JvdHRvbXJvdW5kcmVjdGFuZ2xlJ10gPSB7XG4gICAgcmVuZGVyZXI6IHRoaXMsXG4gICAgbmFtZTogJ2JvdHRvbS1yb3VuZC1yZWN0YW5nbGUnLFxuICAgIHBvaW50czogZ2VuZXJhdGVVbml0TmdvblBvaW50c0ZpdFRvU3F1YXJlKDQsIDApLFxuICAgIGRyYXc6IGZ1bmN0aW9uIGRyYXcoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCkge1xuICAgICAgdGhpcy5yZW5kZXJlci5ub2RlU2hhcGVJbXBsKHRoaXMubmFtZSwgY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCk7XG4gICAgfSxcbiAgICBpbnRlcnNlY3RMaW5lOiBmdW5jdGlvbiBpbnRlcnNlY3RMaW5lKG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCwgeCwgeSwgcGFkZGluZykge1xuICAgICAgdmFyIHRvcFN0YXJ0WCA9IG5vZGVYIC0gKHdpZHRoIC8gMiArIHBhZGRpbmcpO1xuICAgICAgdmFyIHRvcFN0YXJ0WSA9IG5vZGVZIC0gKGhlaWdodCAvIDIgKyBwYWRkaW5nKTtcbiAgICAgIHZhciB0b3BFbmRZID0gdG9wU3RhcnRZO1xuICAgICAgdmFyIHRvcEVuZFggPSBub2RlWCArICh3aWR0aCAvIDIgKyBwYWRkaW5nKTtcbiAgICAgIHZhciB0b3BJbnRlcnNlY3Rpb25zID0gZmluaXRlTGluZXNJbnRlcnNlY3QoeCwgeSwgbm9kZVgsIG5vZGVZLCB0b3BTdGFydFgsIHRvcFN0YXJ0WSwgdG9wRW5kWCwgdG9wRW5kWSwgZmFsc2UpO1xuXG4gICAgICBpZiAodG9wSW50ZXJzZWN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiB0b3BJbnRlcnNlY3Rpb25zO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcm91bmRSZWN0YW5nbGVJbnRlcnNlY3RMaW5lKHgsIHksIG5vZGVYLCBub2RlWSwgd2lkdGgsIGhlaWdodCwgcGFkZGluZyk7XG4gICAgfSxcbiAgICBjaGVja1BvaW50OiBmdW5jdGlvbiBjaGVja1BvaW50KHgsIHksIHBhZGRpbmcsIHdpZHRoLCBoZWlnaHQsIGNlbnRlclgsIGNlbnRlclkpIHtcbiAgICAgIHZhciBjb3JuZXJSYWRpdXMgPSBnZXRSb3VuZFJlY3RhbmdsZVJhZGl1cyh3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIHZhciBkaWFtID0gMiAqIGNvcm5lclJhZGl1czsgLy8gQ2hlY2sgaEJveFxuXG4gICAgICBpZiAocG9pbnRJbnNpZGVQb2x5Z29uKHgsIHksIHRoaXMucG9pbnRzLCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0IC0gZGlhbSwgWzAsIC0xXSwgcGFkZGluZykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IC8vIENoZWNrIHZCb3hcblxuXG4gICAgICBpZiAocG9pbnRJbnNpZGVQb2x5Z29uKHgsIHksIHRoaXMucG9pbnRzLCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCAtIGRpYW0sIGhlaWdodCwgWzAsIC0xXSwgcGFkZGluZykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IC8vIGNoZWNrIG5vbi1yb3VuZGVkIHRvcCBzaWRlXG5cblxuICAgICAgdmFyIG91dGVyV2lkdGggPSB3aWR0aCAvIDIgKyAyICogcGFkZGluZztcbiAgICAgIHZhciBvdXRlckhlaWdodCA9IGhlaWdodCAvIDIgKyAyICogcGFkZGluZztcbiAgICAgIHZhciBwb2ludHMgPSBbY2VudGVyWCAtIG91dGVyV2lkdGgsIGNlbnRlclkgLSBvdXRlckhlaWdodCwgY2VudGVyWCAtIG91dGVyV2lkdGgsIGNlbnRlclksIGNlbnRlclggKyBvdXRlcldpZHRoLCBjZW50ZXJZLCBjZW50ZXJYICsgb3V0ZXJXaWR0aCwgY2VudGVyWSAtIG91dGVySGVpZ2h0XTtcblxuICAgICAgaWYgKHBvaW50SW5zaWRlUG9seWdvblBvaW50cyh4LCB5LCBwb2ludHMpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSAvLyBDaGVjayBib3R0b20gcmlnaHQgcXVhcnRlciBjaXJjbGVcblxuXG4gICAgICBpZiAoY2hlY2tJbkVsbGlwc2UoeCwgeSwgZGlhbSwgZGlhbSwgY2VudGVyWCArIHdpZHRoIC8gMiAtIGNvcm5lclJhZGl1cywgY2VudGVyWSArIGhlaWdodCAvIDIgLSBjb3JuZXJSYWRpdXMsIHBhZGRpbmcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSAvLyBDaGVjayBib3R0b20gbGVmdCBxdWFydGVyIGNpcmNsZVxuXG5cbiAgICAgIGlmIChjaGVja0luRWxsaXBzZSh4LCB5LCBkaWFtLCBkaWFtLCBjZW50ZXJYIC0gd2lkdGggLyAyICsgY29ybmVyUmFkaXVzLCBjZW50ZXJZICsgaGVpZ2h0IC8gMiAtIGNvcm5lclJhZGl1cywgcGFkZGluZykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG59O1xuXG5CUnAkZC5yZWdpc3Rlck5vZGVTaGFwZXMgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBub2RlU2hhcGVzID0gdGhpcy5ub2RlU2hhcGVzID0ge307XG4gIHZhciByZW5kZXJlciA9IHRoaXM7XG4gIHRoaXMuZ2VuZXJhdGVFbGxpcHNlKCk7XG4gIHRoaXMuZ2VuZXJhdGVQb2x5Z29uKCd0cmlhbmdsZScsIGdlbmVyYXRlVW5pdE5nb25Qb2ludHNGaXRUb1NxdWFyZSgzLCAwKSk7XG4gIHRoaXMuZ2VuZXJhdGVSb3VuZFBvbHlnb24oJ3JvdW5kLXRyaWFuZ2xlJywgZ2VuZXJhdGVVbml0TmdvblBvaW50c0ZpdFRvU3F1YXJlKDMsIDApKTtcbiAgdGhpcy5nZW5lcmF0ZVBvbHlnb24oJ3JlY3RhbmdsZScsIGdlbmVyYXRlVW5pdE5nb25Qb2ludHNGaXRUb1NxdWFyZSg0LCAwKSk7XG4gIG5vZGVTaGFwZXNbJ3NxdWFyZSddID0gbm9kZVNoYXBlc1sncmVjdGFuZ2xlJ107XG4gIHRoaXMuZ2VuZXJhdGVSb3VuZFJlY3RhbmdsZSgpO1xuICB0aGlzLmdlbmVyYXRlQ3V0UmVjdGFuZ2xlKCk7XG4gIHRoaXMuZ2VuZXJhdGVCYXJyZWwoKTtcbiAgdGhpcy5nZW5lcmF0ZUJvdHRvbVJvdW5kcmVjdGFuZ2xlKCk7XG4gIHtcbiAgICB2YXIgZGlhbW9uZFBvaW50cyA9IFswLCAxLCAxLCAwLCAwLCAtMSwgLTEsIDBdO1xuICAgIHRoaXMuZ2VuZXJhdGVQb2x5Z29uKCdkaWFtb25kJywgZGlhbW9uZFBvaW50cyk7XG4gICAgdGhpcy5nZW5lcmF0ZVJvdW5kUG9seWdvbigncm91bmQtZGlhbW9uZCcsIGRpYW1vbmRQb2ludHMpO1xuICB9XG4gIHRoaXMuZ2VuZXJhdGVQb2x5Z29uKCdwZW50YWdvbicsIGdlbmVyYXRlVW5pdE5nb25Qb2ludHNGaXRUb1NxdWFyZSg1LCAwKSk7XG4gIHRoaXMuZ2VuZXJhdGVSb3VuZFBvbHlnb24oJ3JvdW5kLXBlbnRhZ29uJywgZ2VuZXJhdGVVbml0TmdvblBvaW50c0ZpdFRvU3F1YXJlKDUsIDApKTtcbiAgdGhpcy5nZW5lcmF0ZVBvbHlnb24oJ2hleGFnb24nLCBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzRml0VG9TcXVhcmUoNiwgMCkpO1xuICB0aGlzLmdlbmVyYXRlUm91bmRQb2x5Z29uKCdyb3VuZC1oZXhhZ29uJywgZ2VuZXJhdGVVbml0TmdvblBvaW50c0ZpdFRvU3F1YXJlKDYsIDApKTtcbiAgdGhpcy5nZW5lcmF0ZVBvbHlnb24oJ2hlcHRhZ29uJywgZ2VuZXJhdGVVbml0TmdvblBvaW50c0ZpdFRvU3F1YXJlKDcsIDApKTtcbiAgdGhpcy5nZW5lcmF0ZVJvdW5kUG9seWdvbigncm91bmQtaGVwdGFnb24nLCBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzRml0VG9TcXVhcmUoNywgMCkpO1xuICB0aGlzLmdlbmVyYXRlUG9seWdvbignb2N0YWdvbicsIGdlbmVyYXRlVW5pdE5nb25Qb2ludHNGaXRUb1NxdWFyZSg4LCAwKSk7XG4gIHRoaXMuZ2VuZXJhdGVSb3VuZFBvbHlnb24oJ3JvdW5kLW9jdGFnb24nLCBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzRml0VG9TcXVhcmUoOCwgMCkpO1xuICB2YXIgc3RhcjVQb2ludHMgPSBuZXcgQXJyYXkoMjApO1xuICB7XG4gICAgdmFyIG91dGVyUG9pbnRzID0gZ2VuZXJhdGVVbml0TmdvblBvaW50cyg1LCAwKTtcbiAgICB2YXIgaW5uZXJQb2ludHMgPSBnZW5lcmF0ZVVuaXROZ29uUG9pbnRzKDUsIE1hdGguUEkgLyA1KTsgLy8gT3V0ZXIgcmFkaXVzIGlzIDE7IGlubmVyIHJhZGl1cyBvZiBzdGFyIGlzIHNtYWxsZXJcblxuICAgIHZhciBpbm5lclJhZGl1cyA9IDAuNSAqICgzIC0gTWF0aC5zcXJ0KDUpKTtcbiAgICBpbm5lclJhZGl1cyAqPSAxLjU3O1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbm5lclBvaW50cy5sZW5ndGggLyAyOyBpKyspIHtcbiAgICAgIGlubmVyUG9pbnRzW2kgKiAyXSAqPSBpbm5lclJhZGl1cztcbiAgICAgIGlubmVyUG9pbnRzW2kgKiAyICsgMV0gKj0gaW5uZXJSYWRpdXM7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAyMCAvIDQ7IGkrKykge1xuICAgICAgc3RhcjVQb2ludHNbaSAqIDRdID0gb3V0ZXJQb2ludHNbaSAqIDJdO1xuICAgICAgc3RhcjVQb2ludHNbaSAqIDQgKyAxXSA9IG91dGVyUG9pbnRzW2kgKiAyICsgMV07XG4gICAgICBzdGFyNVBvaW50c1tpICogNCArIDJdID0gaW5uZXJQb2ludHNbaSAqIDJdO1xuICAgICAgc3RhcjVQb2ludHNbaSAqIDQgKyAzXSA9IGlubmVyUG9pbnRzW2kgKiAyICsgMV07XG4gICAgfVxuICB9XG4gIHN0YXI1UG9pbnRzID0gZml0UG9seWdvblRvU3F1YXJlKHN0YXI1UG9pbnRzKTtcbiAgdGhpcy5nZW5lcmF0ZVBvbHlnb24oJ3N0YXInLCBzdGFyNVBvaW50cyk7XG4gIHRoaXMuZ2VuZXJhdGVQb2x5Z29uKCd2ZWUnLCBbLTEsIC0xLCAwLCAtMC4zMzMsIDEsIC0xLCAwLCAxXSk7XG4gIHRoaXMuZ2VuZXJhdGVQb2x5Z29uKCdyaG9tYm9pZCcsIFstMSwgLTEsIDAuMzMzLCAtMSwgMSwgMSwgLTAuMzMzLCAxXSk7XG4gIHRoaXMubm9kZVNoYXBlc1snY29uY2F2ZWhleGFnb24nXSA9IHRoaXMuZ2VuZXJhdGVQb2x5Z29uKCdjb25jYXZlLWhleGFnb24nLCBbLTEsIC0wLjk1LCAtMC43NSwgMCwgLTEsIDAuOTUsIDEsIDAuOTUsIDAuNzUsIDAsIDEsIC0wLjk1XSk7XG4gIHtcbiAgICB2YXIgdGFnUG9pbnRzID0gWy0xLCAtMSwgMC4yNSwgLTEsIDEsIDAsIDAuMjUsIDEsIC0xLCAxXTtcbiAgICB0aGlzLmdlbmVyYXRlUG9seWdvbigndGFnJywgdGFnUG9pbnRzKTtcbiAgICB0aGlzLmdlbmVyYXRlUm91bmRQb2x5Z29uKCdyb3VuZC10YWcnLCB0YWdQb2ludHMpO1xuICB9XG5cbiAgbm9kZVNoYXBlcy5tYWtlUG9seWdvbiA9IGZ1bmN0aW9uIChwb2ludHMpIHtcbiAgICAvLyB1c2UgY2FjaGluZyBvbiB1c2VyLXNwZWNpZmllZCBwb2x5Z29ucyBzbyB0aGV5IGFyZSBhcyBmYXN0IGFzIG5hdGl2ZSBzaGFwZXNcbiAgICB2YXIga2V5ID0gcG9pbnRzLmpvaW4oJyQnKTtcbiAgICB2YXIgbmFtZSA9ICdwb2x5Z29uLScgKyBrZXk7XG4gICAgdmFyIHNoYXBlO1xuXG4gICAgaWYgKHNoYXBlID0gdGhpc1tuYW1lXSkge1xuICAgICAgLy8gZ290IGNhY2hlZCBzaGFwZVxuICAgICAgcmV0dXJuIHNoYXBlO1xuICAgIH0gLy8gY3JlYXRlIGFuZCBjYWNoZSBuZXcgc2hhcGVcblxuXG4gICAgcmV0dXJuIHJlbmRlcmVyLmdlbmVyYXRlUG9seWdvbihuYW1lLCBwb2ludHMpO1xuICB9O1xufTtcblxudmFyIEJScCRlID0ge307XG5cbkJScCRlLnRpbWVUb1JlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMucmVkcmF3VG90YWxUaW1lIC8gdGhpcy5yZWRyYXdDb3VudDtcbn07XG5cbkJScCRlLnJlZHJhdyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHN0YXRpY0VtcHR5T2JqZWN0KCk7XG4gIHZhciByID0gdGhpcztcblxuICBpZiAoci5hdmVyYWdlUmVkcmF3VGltZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgci5hdmVyYWdlUmVkcmF3VGltZSA9IDA7XG4gIH1cblxuICBpZiAoci5sYXN0UmVkcmF3VGltZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgci5sYXN0UmVkcmF3VGltZSA9IDA7XG4gIH1cblxuICBpZiAoci5sYXN0RHJhd1RpbWUgPT09IHVuZGVmaW5lZCkge1xuICAgIHIubGFzdERyYXdUaW1lID0gMDtcbiAgfVxuXG4gIHIucmVxdWVzdGVkRnJhbWUgPSB0cnVlO1xuICByLnJlbmRlck9wdGlvbnMgPSBvcHRpb25zO1xufTtcblxuQlJwJGUuYmVmb3JlUmVuZGVyID0gZnVuY3Rpb24gKGZuLCBwcmlvcml0eSkge1xuICAvLyB0aGUgcmVuZGVyZXIgY2FuJ3QgYWRkIHRpY2sgY2FsbGJhY2tzIHdoZW4gZGVzdHJveWVkXG4gIGlmICh0aGlzLmRlc3Ryb3llZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChwcmlvcml0eSA9PSBudWxsKSB7XG4gICAgZXJyb3IoJ1ByaW9yaXR5IGlzIG5vdCBvcHRpb25hbCBmb3IgYmVmb3JlUmVuZGVyJyk7XG4gIH1cblxuICB2YXIgY2JzID0gdGhpcy5iZWZvcmVSZW5kZXJDYWxsYmFja3M7XG4gIGNicy5wdXNoKHtcbiAgICBmbjogZm4sXG4gICAgcHJpb3JpdHk6IHByaW9yaXR5XG4gIH0pOyAvLyBoaWdoZXIgcHJpb3JpdHkgY2FsbGJhY2tzIGV4ZWN1dGVkIGZpcnN0XG5cbiAgY2JzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYi5wcmlvcml0eSAtIGEucHJpb3JpdHk7XG4gIH0pO1xufTtcblxudmFyIGJlZm9yZVJlbmRlckNhbGxiYWNrcyA9IGZ1bmN0aW9uIGJlZm9yZVJlbmRlckNhbGxiYWNrcyhyLCB3aWxsRHJhdywgc3RhcnRUaW1lKSB7XG4gIHZhciBjYnMgPSByLmJlZm9yZVJlbmRlckNhbGxiYWNrcztcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNicy5sZW5ndGg7IGkrKykge1xuICAgIGNic1tpXS5mbih3aWxsRHJhdywgc3RhcnRUaW1lKTtcbiAgfVxufTtcblxuQlJwJGUuc3RhcnRSZW5kZXJMb29wID0gZnVuY3Rpb24gKCkge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBjeSA9IHIuY3k7XG5cbiAgaWYgKHIucmVuZGVyTG9vcFN0YXJ0ZWQpIHtcbiAgICByZXR1cm47XG4gIH0gZWxzZSB7XG4gICAgci5yZW5kZXJMb29wU3RhcnRlZCA9IHRydWU7XG4gIH1cblxuICB2YXIgcmVuZGVyRm4gPSBmdW5jdGlvbiByZW5kZXJGbihyZXF1ZXN0VGltZSkge1xuICAgIGlmIChyLmRlc3Ryb3llZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjeS5iYXRjaGluZygpKSA7IGVsc2UgaWYgKHIucmVxdWVzdGVkRnJhbWUgJiYgIXIuc2tpcEZyYW1lKSB7XG4gICAgICBiZWZvcmVSZW5kZXJDYWxsYmFja3MociwgdHJ1ZSwgcmVxdWVzdFRpbWUpO1xuICAgICAgdmFyIHN0YXJ0VGltZSA9IHBlcmZvcm1hbmNlTm93KCk7XG4gICAgICByLnJlbmRlcihyLnJlbmRlck9wdGlvbnMpO1xuICAgICAgdmFyIGVuZFRpbWUgPSByLmxhc3REcmF3VGltZSA9IHBlcmZvcm1hbmNlTm93KCk7XG5cbiAgICAgIGlmIChyLmF2ZXJhZ2VSZWRyYXdUaW1lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgci5hdmVyYWdlUmVkcmF3VGltZSA9IGVuZFRpbWUgLSBzdGFydFRpbWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChyLnJlZHJhd0NvdW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgci5yZWRyYXdDb3VudCA9IDA7XG4gICAgICB9XG5cbiAgICAgIHIucmVkcmF3Q291bnQrKztcblxuICAgICAgaWYgKHIucmVkcmF3VG90YWxUaW1lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgci5yZWRyYXdUb3RhbFRpbWUgPSAwO1xuICAgICAgfVxuXG4gICAgICB2YXIgZHVyYXRpb24gPSBlbmRUaW1lIC0gc3RhcnRUaW1lO1xuICAgICAgci5yZWRyYXdUb3RhbFRpbWUgKz0gZHVyYXRpb247XG4gICAgICByLmxhc3RSZWRyYXdUaW1lID0gZHVyYXRpb247IC8vIHVzZSBhIHdlaWdodGVkIGF2ZXJhZ2Ugd2l0aCBhIGJpYXMgZnJvbSB0aGUgcHJldmlvdXMgYXZlcmFnZSBzbyB3ZSBkb24ndCBzcGlrZSBzbyBlYXNpbHlcblxuICAgICAgci5hdmVyYWdlUmVkcmF3VGltZSA9IHIuYXZlcmFnZVJlZHJhd1RpbWUgLyAyICsgZHVyYXRpb24gLyAyO1xuICAgICAgci5yZXF1ZXN0ZWRGcmFtZSA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBiZWZvcmVSZW5kZXJDYWxsYmFja3MociwgZmFsc2UsIHJlcXVlc3RUaW1lKTtcbiAgICB9XG5cbiAgICByLnNraXBGcmFtZSA9IGZhbHNlO1xuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShyZW5kZXJGbik7XG4gIH07XG5cbiAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHJlbmRlckZuKTtcbn07XG5cbnZhciBCYXNlUmVuZGVyZXIgPSBmdW5jdGlvbiBCYXNlUmVuZGVyZXIob3B0aW9ucykge1xuICB0aGlzLmluaXQob3B0aW9ucyk7XG59O1xuXG52YXIgQlIgPSBCYXNlUmVuZGVyZXI7XG52YXIgQlJwJGYgPSBCUi5wcm90b3R5cGU7XG5CUnAkZi5jbGllbnRGdW5jdGlvbnMgPSBbJ3JlZHJhd0hpbnQnLCAncmVuZGVyJywgJ3JlbmRlclRvJywgJ21hdGNoQ2FudmFzU2l6ZScsICdub2RlU2hhcGVJbXBsJywgJ2Fycm93U2hhcGVJbXBsJ107XG5cbkJScCRmLmluaXQgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICB2YXIgciA9IHRoaXM7XG4gIHIub3B0aW9ucyA9IG9wdGlvbnM7XG4gIHIuY3kgPSBvcHRpb25zLmN5O1xuICB2YXIgY3RyID0gci5jb250YWluZXIgPSBvcHRpb25zLmN5LmNvbnRhaW5lcigpOyAvLyBwcmVwZW5kIGEgc3R5bGVzaGVldCBpbiB0aGUgaGVhZCBzdWNoIHRoYXRcblxuICBpZiAod2luZG93JDEpIHtcbiAgICB2YXIgZG9jdW1lbnQgPSB3aW5kb3ckMS5kb2N1bWVudDtcbiAgICB2YXIgaGVhZCA9IGRvY3VtZW50LmhlYWQ7XG4gICAgdmFyIHN0eWxlc2hlZXRJZCA9ICdfX19fX19fX19fY3l0b3NjYXBlX3N0eWxlc2hlZXQnO1xuICAgIHZhciBjbGFzc05hbWUgPSAnX19fX19fX19fX2N5dG9zY2FwZV9jb250YWluZXInO1xuICAgIHZhciBzdHlsZXNoZWV0QWxyZWFkeUV4aXN0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHN0eWxlc2hlZXRJZCkgIT0gbnVsbDtcblxuICAgIGlmIChjdHIuY2xhc3NOYW1lLmluZGV4T2YoY2xhc3NOYW1lKSA8IDApIHtcbiAgICAgIGN0ci5jbGFzc05hbWUgPSAoY3RyLmNsYXNzTmFtZSB8fCAnJykgKyAnICcgKyBjbGFzc05hbWU7XG4gICAgfVxuXG4gICAgaWYgKCFzdHlsZXNoZWV0QWxyZWFkeUV4aXN0cykge1xuICAgICAgdmFyIHN0eWxlc2hlZXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuICAgICAgc3R5bGVzaGVldC5pZCA9IHN0eWxlc2hlZXRJZDtcbiAgICAgIHN0eWxlc2hlZXQuaW5uZXJIVE1MID0gJy4nICsgY2xhc3NOYW1lICsgJyB7IHBvc2l0aW9uOiByZWxhdGl2ZTsgfSc7XG4gICAgICBoZWFkLmluc2VydEJlZm9yZShzdHlsZXNoZWV0LCBoZWFkLmNoaWxkcmVuWzBdKTsgLy8gZmlyc3Qgc28gbG93ZXN0IHByaW9yaXR5XG4gICAgfVxuXG4gICAgdmFyIGNvbXB1dGVkU3R5bGUgPSB3aW5kb3ckMS5nZXRDb21wdXRlZFN0eWxlKGN0cik7XG4gICAgdmFyIHBvc2l0aW9uID0gY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCdwb3NpdGlvbicpO1xuXG4gICAgaWYgKHBvc2l0aW9uID09PSAnc3RhdGljJykge1xuICAgICAgd2FybignQSBDeXRvc2NhcGUgY29udGFpbmVyIGhhcyBzdHlsZSBwb3NpdGlvbjpzdGF0aWMgYW5kIHNvIGNhbiBub3QgdXNlIFVJIGV4dGVuc2lvbnMgcHJvcGVybHknKTtcbiAgICB9XG4gIH1cblxuICByLnNlbGVjdGlvbiA9IFt1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIDBdOyAvLyBDb29yZGluYXRlcyBmb3Igc2VsZWN0aW9uIGJveCwgcGx1cyBlbmFibGVkIGZsYWdcblxuICByLmJlemllclByb2pQY3RzID0gWzAuMDUsIDAuMjI1LCAwLjQsIDAuNSwgMC42LCAwLjc3NSwgMC45NV07IC8vLS1Qb2ludGVyLXJlbGF0ZWQgZGF0YVxuXG4gIHIuaG92ZXJEYXRhID0ge1xuICAgIGRvd246IG51bGwsXG4gICAgbGFzdDogbnVsbCxcbiAgICBkb3duVGltZTogbnVsbCxcbiAgICB0cmlnZ2VyTW9kZTogbnVsbCxcbiAgICBkcmFnZ2luZzogZmFsc2UsXG4gICAgaW5pdGlhbFBhbjogW251bGwsIG51bGxdLFxuICAgIGNhcHR1cmU6IGZhbHNlXG4gIH07XG4gIHIuZHJhZ0RhdGEgPSB7XG4gICAgcG9zc2libGVEcmFnRWxlbWVudHM6IFtdXG4gIH07XG4gIHIudG91Y2hEYXRhID0ge1xuICAgIHN0YXJ0OiBudWxsLFxuICAgIGNhcHR1cmU6IGZhbHNlLFxuICAgIC8vIFRoZXNlIDMgZmllbGRzIHJlbGF0ZWQgdG8gdGFwLCB0YXBob2xkIGV2ZW50c1xuICAgIHN0YXJ0UG9zaXRpb246IFtudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsXSxcbiAgICBzaW5nbGVUb3VjaFN0YXJ0VGltZTogbnVsbCxcbiAgICBzaW5nbGVUb3VjaE1vdmVkOiB0cnVlLFxuICAgIG5vdzogW251bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGxdLFxuICAgIGVhcmxpZXI6IFtudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsXVxuICB9O1xuICByLnJlZHJhd3MgPSAwO1xuICByLnNob3dGcHMgPSBvcHRpb25zLnNob3dGcHM7XG4gIHIuZGVidWcgPSBvcHRpb25zLmRlYnVnO1xuICByLmhpZGVFZGdlc09uVmlld3BvcnQgPSBvcHRpb25zLmhpZGVFZGdlc09uVmlld3BvcnQ7XG4gIHIudGV4dHVyZU9uVmlld3BvcnQgPSBvcHRpb25zLnRleHR1cmVPblZpZXdwb3J0O1xuICByLndoZWVsU2Vuc2l0aXZpdHkgPSBvcHRpb25zLndoZWVsU2Vuc2l0aXZpdHk7XG4gIHIubW90aW9uQmx1ckVuYWJsZWQgPSBvcHRpb25zLm1vdGlvbkJsdXI7IC8vIG9uIGJ5IGRlZmF1bHRcblxuICByLmZvcmNlZFBpeGVsUmF0aW8gPSBudW1iZXIob3B0aW9ucy5waXhlbFJhdGlvKSA/IG9wdGlvbnMucGl4ZWxSYXRpbyA6IG51bGw7XG4gIHIubW90aW9uQmx1ciA9IG9wdGlvbnMubW90aW9uQmx1cjsgLy8gZm9yIGluaXRpYWwga2ljayBvZmZcblxuICByLm1vdGlvbkJsdXJPcGFjaXR5ID0gb3B0aW9ucy5tb3Rpb25CbHVyT3BhY2l0eTtcbiAgci5tb3Rpb25CbHVyVHJhbnNwYXJlbmN5ID0gMSAtIHIubW90aW9uQmx1ck9wYWNpdHk7XG4gIHIubW90aW9uQmx1clB4UmF0aW8gPSAxO1xuICByLm1iUHhSQmx1cnJ5ID0gMTsgLy8wLjg7XG5cbiAgci5taW5NYkxvd1F1YWxGcmFtZXMgPSA0O1xuICByLmZ1bGxRdWFsaXR5TWIgPSBmYWxzZTtcbiAgci5jbGVhcmVkRm9yTW90aW9uQmx1ciA9IFtdO1xuICByLmRlc2t0b3BUYXBUaHJlc2hvbGQgPSBvcHRpb25zLmRlc2t0b3BUYXBUaHJlc2hvbGQ7XG4gIHIuZGVza3RvcFRhcFRocmVzaG9sZDIgPSBvcHRpb25zLmRlc2t0b3BUYXBUaHJlc2hvbGQgKiBvcHRpb25zLmRlc2t0b3BUYXBUaHJlc2hvbGQ7XG4gIHIudG91Y2hUYXBUaHJlc2hvbGQgPSBvcHRpb25zLnRvdWNoVGFwVGhyZXNob2xkO1xuICByLnRvdWNoVGFwVGhyZXNob2xkMiA9IG9wdGlvbnMudG91Y2hUYXBUaHJlc2hvbGQgKiBvcHRpb25zLnRvdWNoVGFwVGhyZXNob2xkO1xuICByLnRhcGhvbGREdXJhdGlvbiA9IDUwMDtcbiAgci5iaW5kaW5ncyA9IFtdO1xuICByLmJlZm9yZVJlbmRlckNhbGxiYWNrcyA9IFtdO1xuICByLmJlZm9yZVJlbmRlclByaW9yaXRpZXMgPSB7XG4gICAgLy8gaGlnaGVyIHByaW9yaXR5IGV4ZWNzIGJlZm9yZSBsb3dlciBvbmVcbiAgICBhbmltYXRpb25zOiA0MDAsXG4gICAgZWxlQ2FsY3M6IDMwMCxcbiAgICBlbGVUeHJEZXE6IDIwMCxcbiAgICBseXJUeHJEZXE6IDE1MCxcbiAgICBseXJUeHJTa2lwOiAxMDBcbiAgfTtcbiAgci5yZWdpc3Rlck5vZGVTaGFwZXMoKTtcbiAgci5yZWdpc3RlckFycm93U2hhcGVzKCk7XG4gIHIucmVnaXN0ZXJDYWxjdWxhdGlvbkxpc3RlbmVycygpO1xufTtcblxuQlJwJGYubm90aWZ5ID0gZnVuY3Rpb24gKGV2ZW50TmFtZSwgZWxlcykge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBjeSA9IHIuY3k7IC8vIHRoZSByZW5kZXJlciBjYW4ndCBiZSBub3RpZmllZCBhZnRlciBpdCdzIGRlc3Ryb3llZFxuXG4gIGlmICh0aGlzLmRlc3Ryb3llZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChldmVudE5hbWUgPT09ICdpbml0Jykge1xuICAgIHIubG9hZCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChldmVudE5hbWUgPT09ICdkZXN0cm95Jykge1xuICAgIHIuZGVzdHJveSgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChldmVudE5hbWUgPT09ICdhZGQnIHx8IGV2ZW50TmFtZSA9PT0gJ3JlbW92ZScgfHwgZXZlbnROYW1lID09PSAnbW92ZScgJiYgY3kuaGFzQ29tcG91bmROb2RlcygpIHx8IGV2ZW50TmFtZSA9PT0gJ2xvYWQnIHx8IGV2ZW50TmFtZSA9PT0gJ3pvcmRlcicgfHwgZXZlbnROYW1lID09PSAnbW91bnQnKSB7XG4gICAgci5pbnZhbGlkYXRlQ2FjaGVkWlNvcnRlZEVsZXMoKTtcbiAgfVxuXG4gIGlmIChldmVudE5hbWUgPT09ICd2aWV3cG9ydCcpIHtcbiAgICByLnJlZHJhd0hpbnQoJ3NlbGVjdCcsIHRydWUpO1xuICB9XG5cbiAgaWYgKGV2ZW50TmFtZSA9PT0gJ2xvYWQnIHx8IGV2ZW50TmFtZSA9PT0gJ3Jlc2l6ZScgfHwgZXZlbnROYW1lID09PSAnbW91bnQnKSB7XG4gICAgci5pbnZhbGlkYXRlQ29udGFpbmVyQ2xpZW50Q29vcmRzQ2FjaGUoKTtcbiAgICByLm1hdGNoQ2FudmFzU2l6ZShyLmNvbnRhaW5lcik7XG4gIH1cblxuICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgci5yZWRyYXdIaW50KCdkcmFnJywgdHJ1ZSk7XG4gIHRoaXMuc3RhcnRSZW5kZXJMb29wKCk7XG4gIHRoaXMucmVkcmF3KCk7XG59O1xuXG5CUnAkZi5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgciA9IHRoaXM7XG4gIHIuZGVzdHJveWVkID0gdHJ1ZTtcbiAgci5jeS5zdG9wQW5pbWF0aW9uTG9vcCgpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgci5iaW5kaW5ncy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBiaW5kaW5nID0gci5iaW5kaW5nc1tpXTtcbiAgICB2YXIgYiA9IGJpbmRpbmc7XG4gICAgdmFyIHRndCA9IGIudGFyZ2V0O1xuICAgICh0Z3Qub2ZmIHx8IHRndC5yZW1vdmVFdmVudExpc3RlbmVyKS5hcHBseSh0Z3QsIGIuYXJncyk7XG4gIH1cblxuICByLmJpbmRpbmdzID0gW107XG4gIHIuYmVmb3JlUmVuZGVyQ2FsbGJhY2tzID0gW107XG4gIHIub25VcGRhdGVFbGVDYWxjc0ZucyA9IFtdO1xuXG4gIGlmIChyLnJlbW92ZU9ic2VydmVyKSB7XG4gICAgci5yZW1vdmVPYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gIH1cblxuICBpZiAoci5zdHlsZU9ic2VydmVyKSB7XG4gICAgci5zdHlsZU9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgfVxuXG4gIGlmIChyLnJlc2l6ZU9ic2VydmVyKSB7XG4gICAgci5yZXNpemVPYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gIH1cblxuICBpZiAoci5sYWJlbENhbGNEaXYpIHtcbiAgICB0cnkge1xuICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChyLmxhYmVsQ2FsY0Rpdik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbiAgICB9IGNhdGNoIChlKSB7Ly8gaWUxMCBpc3N1ZSAjMTAxNFxuICAgIH1cbiAgfVxufTtcblxuQlJwJGYuaXNIZWFkbGVzcyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuW0JScCwgQlJwJGEsIEJScCRiLCBCUnAkYywgQlJwJGQsIEJScCRlXS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wcykge1xuICBleHRlbmQoQlJwJGYsIHByb3BzKTtcbn0pO1xuXG52YXIgZnVsbEZwc1RpbWUgPSAxMDAwIC8gNjA7IC8vIGFzc3VtZSA2MCBmcmFtZXMgcGVyIHNlY29uZFxuXG52YXIgZGVmcyA9IHtcbiAgc2V0dXBEZXF1ZXVlaW5nOiBmdW5jdGlvbiBzZXR1cERlcXVldWVpbmcob3B0cykge1xuICAgIHJldHVybiBmdW5jdGlvbiBzZXR1cERlcXVldWVpbmdJbXBsKCkge1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgdmFyIHIgPSB0aGlzLnJlbmRlcmVyO1xuXG4gICAgICBpZiAoc2VsZi5kZXF1ZXVlaW5nU2V0dXApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VsZi5kZXF1ZXVlaW5nU2V0dXAgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgcXVldWVSZWRyYXcgPSB1dGlsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgci5yZWRyYXdIaW50KCdlbGVzJywgdHJ1ZSk7XG4gICAgICAgIHIucmVkcmF3SGludCgnZHJhZycsIHRydWUpO1xuICAgICAgICByLnJlZHJhdygpO1xuICAgICAgfSwgb3B0cy5kZXFSZWRyYXdUaHJlc2hvbGQpO1xuXG4gICAgICB2YXIgZGVxdWV1ZSA9IGZ1bmN0aW9uIGRlcXVldWUod2lsbERyYXcsIGZyYW1lU3RhcnRUaW1lKSB7XG4gICAgICAgIHZhciBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZU5vdygpO1xuICAgICAgICB2YXIgYXZnUmVuZGVyVGltZSA9IHIuYXZlcmFnZVJlZHJhd1RpbWU7XG4gICAgICAgIHZhciByZW5kZXJUaW1lID0gci5sYXN0UmVkcmF3VGltZTtcbiAgICAgICAgdmFyIGRlcWQgPSBbXTtcbiAgICAgICAgdmFyIGV4dGVudCA9IHIuY3kuZXh0ZW50KCk7XG4gICAgICAgIHZhciBwaXhlbFJhdGlvID0gci5nZXRQaXhlbFJhdGlvKCk7IC8vIGlmIHdlIGFyZW4ndCBpbiBhIHRpY2sgdGhhdCBjYXVzZXMgYSBkcmF3LCB0aGVuIHRoZSByZW5kZXJlZCBzdHlsZVxuICAgICAgICAvLyBxdWV1ZSB3b24ndCBhdXRvbWF0aWNhbGx5IGJlIGZsdXNoZWQgYmVmb3JlIGRlcXVldWVpbmcgc3RhcnRzXG5cbiAgICAgICAgaWYgKCF3aWxsRHJhdykge1xuICAgICAgICAgIHIuZmx1c2hSZW5kZXJlZFN0eWxlUXVldWUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zdGFudC1jb25kaXRpb25cbiAgICAgICAgICB2YXIgbm93ID0gcGVyZm9ybWFuY2VOb3coKTtcbiAgICAgICAgICB2YXIgZHVyYXRpb24gPSBub3cgLSBzdGFydFRpbWU7XG4gICAgICAgICAgdmFyIGZyYW1lRHVyYXRpb24gPSBub3cgLSBmcmFtZVN0YXJ0VGltZTtcblxuICAgICAgICAgIGlmIChyZW5kZXJUaW1lIDwgZnVsbEZwc1RpbWUpIHtcbiAgICAgICAgICAgIC8vIGlmIHdlJ3JlIHJlbmRlcmluZyBmYXN0ZXIgdGhhbiB0aGUgaWRlYWwgZnBzLCB0aGVuIGRvIGRlcXVldWVpbmdcbiAgICAgICAgICAgIC8vIGR1cmluZyBhbGwgb2YgdGhlIHJlbWFpbmluZyBmcmFtZSB0aW1lXG4gICAgICAgICAgICB2YXIgdGltZUF2YWlsYWJsZSA9IGZ1bGxGcHNUaW1lIC0gKHdpbGxEcmF3ID8gYXZnUmVuZGVyVGltZSA6IDApO1xuXG4gICAgICAgICAgICBpZiAoZnJhbWVEdXJhdGlvbiA+PSBvcHRzLmRlcUZhc3RDb3N0ICogdGltZUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHdpbGxEcmF3KSB7XG4gICAgICAgICAgICAgIGlmIChkdXJhdGlvbiA+PSBvcHRzLmRlcUNvc3QgKiByZW5kZXJUaW1lIHx8IGR1cmF0aW9uID49IG9wdHMuZGVxQXZnQ29zdCAqIGF2Z1JlbmRlclRpbWUpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChmcmFtZUR1cmF0aW9uID49IG9wdHMuZGVxTm9EcmF3Q29zdCAqIGZ1bGxGcHNUaW1lKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciB0aGlzRGVxZCA9IG9wdHMuZGVxKHNlbGYsIHBpeGVsUmF0aW8sIGV4dGVudCk7XG5cbiAgICAgICAgICBpZiAodGhpc0RlcWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzRGVxZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICBkZXFkLnB1c2godGhpc0RlcWRbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gY2FsbGJhY2tzIG9uIGRlcXVldWVcblxuXG4gICAgICAgIGlmIChkZXFkLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBvcHRzLm9uRGVxZChzZWxmLCBkZXFkKTtcblxuICAgICAgICAgIGlmICghd2lsbERyYXcgJiYgb3B0cy5zaG91bGRSZWRyYXcoc2VsZiwgZGVxZCwgcGl4ZWxSYXRpbywgZXh0ZW50KSkge1xuICAgICAgICAgICAgcXVldWVSZWRyYXcoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIHZhciBwcmlvcml0eSA9IG9wdHMucHJpb3JpdHkgfHwgbm9vcDtcbiAgICAgIHIuYmVmb3JlUmVuZGVyKGRlcXVldWUsIHByaW9yaXR5KHNlbGYpKTtcbiAgICB9O1xuICB9XG59O1xuXG4vLyBVc2VzIGtleXMgc28gZWxlbWVudHMgbWF5IHNoYXJlIHRoZSBzYW1lIGNhY2hlLlxuXG52YXIgRWxlbWVudFRleHR1cmVDYWNoZUxvb2t1cCA9XG4vKiNfX1BVUkVfXyovXG5mdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEVsZW1lbnRUZXh0dXJlQ2FjaGVMb29rdXAoZ2V0S2V5KSB7XG4gICAgdmFyIGRvZXNFbGVJbnZhbGlkYXRlS2V5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzaWZ5O1xuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEVsZW1lbnRUZXh0dXJlQ2FjaGVMb29rdXApO1xuXG4gICAgdGhpcy5pZHNCeUtleSA9IG5ldyBNYXAkMSgpO1xuICAgIHRoaXMua2V5Rm9ySWQgPSBuZXcgTWFwJDEoKTtcbiAgICB0aGlzLmNhY2hlc0J5THZsID0gbmV3IE1hcCQxKCk7XG4gICAgdGhpcy5sdmxzID0gW107XG4gICAgdGhpcy5nZXRLZXkgPSBnZXRLZXk7XG4gICAgdGhpcy5kb2VzRWxlSW52YWxpZGF0ZUtleSA9IGRvZXNFbGVJbnZhbGlkYXRlS2V5O1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKEVsZW1lbnRUZXh0dXJlQ2FjaGVMb29rdXAsIFt7XG4gICAga2V5OiBcImdldElkc0ZvclwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRJZHNGb3Ioa2V5KSB7XG4gICAgICBpZiAoa2V5ID09IG51bGwpIHtcbiAgICAgICAgZXJyb3IoXCJDYW4gbm90IGdldCBpZCBsaXN0IGZvciBudWxsIGtleVwiKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGlkc0J5S2V5ID0gdGhpcy5pZHNCeUtleTtcbiAgICAgIHZhciBpZHMgPSB0aGlzLmlkc0J5S2V5LmdldChrZXkpO1xuXG4gICAgICBpZiAoIWlkcykge1xuICAgICAgICBpZHMgPSBuZXcgU2V0JDEoKTtcbiAgICAgICAgaWRzQnlLZXkuc2V0KGtleSwgaWRzKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGlkcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiYWRkSWRGb3JLZXlcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gYWRkSWRGb3JLZXkoa2V5LCBpZCkge1xuICAgICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICAgIHRoaXMuZ2V0SWRzRm9yKGtleSkuYWRkKGlkKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiZGVsZXRlSWRGb3JLZXlcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gZGVsZXRlSWRGb3JLZXkoa2V5LCBpZCkge1xuICAgICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICAgIHRoaXMuZ2V0SWRzRm9yKGtleSlbXCJkZWxldGVcIl0oaWQpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJnZXROdW1iZXJPZklkc0ZvcktleVwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXROdW1iZXJPZklkc0ZvcktleShrZXkpIHtcbiAgICAgIGlmIChrZXkgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldElkc0ZvcihrZXkpLnNpemU7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcInVwZGF0ZUtleU1hcHBpbmdGb3JcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlS2V5TWFwcGluZ0ZvcihlbGUpIHtcbiAgICAgIHZhciBpZCA9IGVsZS5pZCgpO1xuICAgICAgdmFyIHByZXZLZXkgPSB0aGlzLmtleUZvcklkLmdldChpZCk7XG4gICAgICB2YXIgY3VycktleSA9IHRoaXMuZ2V0S2V5KGVsZSk7XG4gICAgICB0aGlzLmRlbGV0ZUlkRm9yS2V5KHByZXZLZXksIGlkKTtcbiAgICAgIHRoaXMuYWRkSWRGb3JLZXkoY3VycktleSwgaWQpO1xuICAgICAgdGhpcy5rZXlGb3JJZC5zZXQoaWQsIGN1cnJLZXkpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJkZWxldGVLZXlNYXBwaW5nRm9yXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGRlbGV0ZUtleU1hcHBpbmdGb3IoZWxlKSB7XG4gICAgICB2YXIgaWQgPSBlbGUuaWQoKTtcbiAgICAgIHZhciBwcmV2S2V5ID0gdGhpcy5rZXlGb3JJZC5nZXQoaWQpO1xuICAgICAgdGhpcy5kZWxldGVJZEZvcktleShwcmV2S2V5LCBpZCk7XG4gICAgICB0aGlzLmtleUZvcklkW1wiZGVsZXRlXCJdKGlkKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwia2V5SGFzQ2hhbmdlZEZvclwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBrZXlIYXNDaGFuZ2VkRm9yKGVsZSkge1xuICAgICAgdmFyIGlkID0gZWxlLmlkKCk7XG4gICAgICB2YXIgcHJldktleSA9IHRoaXMua2V5Rm9ySWQuZ2V0KGlkKTtcbiAgICAgIHZhciBuZXdLZXkgPSB0aGlzLmdldEtleShlbGUpO1xuICAgICAgcmV0dXJuIHByZXZLZXkgIT09IG5ld0tleTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiaXNJbnZhbGlkXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGlzSW52YWxpZChlbGUpIHtcbiAgICAgIHJldHVybiB0aGlzLmtleUhhc0NoYW5nZWRGb3IoZWxlKSB8fCB0aGlzLmRvZXNFbGVJbnZhbGlkYXRlS2V5KGVsZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcImdldENhY2hlc0F0XCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldENhY2hlc0F0KGx2bCkge1xuICAgICAgdmFyIGNhY2hlc0J5THZsID0gdGhpcy5jYWNoZXNCeUx2bCxcbiAgICAgICAgICBsdmxzID0gdGhpcy5sdmxzO1xuICAgICAgdmFyIGNhY2hlcyA9IGNhY2hlc0J5THZsLmdldChsdmwpO1xuXG4gICAgICBpZiAoIWNhY2hlcykge1xuICAgICAgICBjYWNoZXMgPSBuZXcgTWFwJDEoKTtcbiAgICAgICAgY2FjaGVzQnlMdmwuc2V0KGx2bCwgY2FjaGVzKTtcbiAgICAgICAgbHZscy5wdXNoKGx2bCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjYWNoZXM7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcImdldENhY2hlXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldENhY2hlKGtleSwgbHZsKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRDYWNoZXNBdChsdmwpLmdldChrZXkpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJnZXRcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0KGVsZSwgbHZsKSB7XG4gICAgICB2YXIga2V5ID0gdGhpcy5nZXRLZXkoZWxlKTtcbiAgICAgIHZhciBjYWNoZSA9IHRoaXMuZ2V0Q2FjaGUoa2V5LCBsdmwpOyAvLyBnZXR0aW5nIGZvciBhbiBlbGVtZW50IG1heSBuZWVkIHRvIGFkZCB0byB0aGUgaWQgbGlzdCBiL2MgZWxlcyBjYW4gc2hhcmUga2V5c1xuXG4gICAgICBpZiAoY2FjaGUgIT0gbnVsbCkge1xuICAgICAgICB0aGlzLnVwZGF0ZUtleU1hcHBpbmdGb3IoZWxlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNhY2hlO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJnZXRGb3JDYWNoZWRLZXlcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0Rm9yQ2FjaGVkS2V5KGVsZSwgbHZsKSB7XG4gICAgICB2YXIga2V5ID0gdGhpcy5rZXlGb3JJZC5nZXQoZWxlLmlkKCkpOyAvLyBuLmIuIHVzZSBjYWNoZWQga2V5LCBub3QgbmV3bHkgY29tcHV0ZWQga2V5XG5cbiAgICAgIHZhciBjYWNoZSA9IHRoaXMuZ2V0Q2FjaGUoa2V5LCBsdmwpO1xuICAgICAgcmV0dXJuIGNhY2hlO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogXCJoYXNDYWNoZVwiLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBoYXNDYWNoZShrZXksIGx2bCkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FjaGVzQXQobHZsKS5oYXMoa2V5KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiaGFzXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGhhcyhlbGUsIGx2bCkge1xuICAgICAgdmFyIGtleSA9IHRoaXMuZ2V0S2V5KGVsZSk7XG4gICAgICByZXR1cm4gdGhpcy5oYXNDYWNoZShrZXksIGx2bCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcInNldENhY2hlXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNldENhY2hlKGtleSwgbHZsLCBjYWNoZSkge1xuICAgICAgY2FjaGUua2V5ID0ga2V5O1xuICAgICAgdGhpcy5nZXRDYWNoZXNBdChsdmwpLnNldChrZXksIGNhY2hlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwic2V0XCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNldChlbGUsIGx2bCwgY2FjaGUpIHtcbiAgICAgIHZhciBrZXkgPSB0aGlzLmdldEtleShlbGUpO1xuICAgICAgdGhpcy5zZXRDYWNoZShrZXksIGx2bCwgY2FjaGUpO1xuICAgICAgdGhpcy51cGRhdGVLZXlNYXBwaW5nRm9yKGVsZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcImRlbGV0ZUNhY2hlXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGRlbGV0ZUNhY2hlKGtleSwgbHZsKSB7XG4gICAgICB0aGlzLmdldENhY2hlc0F0KGx2bClbXCJkZWxldGVcIl0oa2V5KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwiZGVsZXRlXCIsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9kZWxldGUoZWxlLCBsdmwpIHtcbiAgICAgIHZhciBrZXkgPSB0aGlzLmdldEtleShlbGUpO1xuICAgICAgdGhpcy5kZWxldGVDYWNoZShrZXksIGx2bCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiBcImludmFsaWRhdGVLZXlcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gaW52YWxpZGF0ZUtleShrZXkpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHRoaXMubHZscy5mb3JFYWNoKGZ1bmN0aW9uIChsdmwpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzLmRlbGV0ZUNhY2hlKGtleSwgbHZsKTtcbiAgICAgIH0pO1xuICAgIH0gLy8gcmV0dXJucyB0cnVlIGlmIG5vIG90aGVyIGVsZXMgcmVmZXJlbmNlIHRoZSBpbnZhbGlkYXRlZCBjYWNoZSAobi5iLiBvdGhlciBlbGVzIG1heSBuZWVkIHRoZSBjYWNoZSB3aXRoIHRoZSBzYW1lIGtleSlcblxuICB9LCB7XG4gICAga2V5OiBcImludmFsaWRhdGVcIixcbiAgICB2YWx1ZTogZnVuY3Rpb24gaW52YWxpZGF0ZShlbGUpIHtcbiAgICAgIHZhciBpZCA9IGVsZS5pZCgpO1xuICAgICAgdmFyIGtleSA9IHRoaXMua2V5Rm9ySWQuZ2V0KGlkKTsgLy8gbi5iLiB1c2Ugc3RvcmVkIGtleSByYXRoZXIgdGhhbiBjdXJyZW50IChwb3RlbnRpYWwga2V5KVxuXG4gICAgICB0aGlzLmRlbGV0ZUtleU1hcHBpbmdGb3IoZWxlKTtcbiAgICAgIHZhciBlbnRpcmVLZXlJbnZhbGlkYXRlZCA9IHRoaXMuZG9lc0VsZUludmFsaWRhdGVLZXkoZWxlKTtcblxuICAgICAgaWYgKGVudGlyZUtleUludmFsaWRhdGVkKSB7XG4gICAgICAgIC8vIGNsZWFyIG1hcHBpbmcgZm9yIGN1cnJlbnQga2V5XG4gICAgICAgIHRoaXMuaW52YWxpZGF0ZUtleShrZXkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZW50aXJlS2V5SW52YWxpZGF0ZWQgfHwgdGhpcy5nZXROdW1iZXJPZklkc0ZvcktleShrZXkpID09PSAwO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBFbGVtZW50VGV4dHVyZUNhY2hlTG9va3VwO1xufSgpO1xuXG52YXIgbWluVHhySCA9IDI1OyAvLyB0aGUgc2l6ZSBvZiB0aGUgdGV4dHVyZSBjYWNoZSBmb3Igc21hbGwgaGVpZ2h0IGVsZXMgKHNwZWNpYWwgY2FzZSlcblxudmFyIHR4clN0ZXBIID0gNTA7IC8vIHRoZSBtaW4gc2l6ZSBvZiB0aGUgcmVndWxhciBjYWNoZSwgYW5kIHRoZSBzaXplIGl0IGluY3JlYXNlcyB3aXRoIGVhY2ggc3RlcCB1cFxuXG52YXIgbWluTHZsID0gLTQ7IC8vIHdoZW4gc2NhbGluZyBzbWFsbGVyIHRoYW4gdGhhdCB3ZSBkb24ndCBuZWVkIHRvIHJlLXJlbmRlclxuXG52YXIgbWF4THZsID0gMzsgLy8gd2hlbiBsYXJnZXIgdGhhbiB0aGlzIHNjYWxlIGp1c3QgcmVuZGVyIGRpcmVjdGx5IChjYWNoaW5nIGlzIG5vdCBoZWxwZnVsKVxuXG52YXIgbWF4Wm9vbSA9IDcuOTk7IC8vIGJleW9uZCB0aGlzIHpvb20gbGV2ZWwsIGxheWVyZWQgdGV4dHVyZXMgYXJlIG5vdCB1c2VkXG5cbnZhciBlbGVUeHJTcGFjaW5nID0gODsgLy8gc3BhY2luZyBiZXR3ZWVuIGVsZW1lbnRzIG9uIHRleHR1cmVzIHRvIGF2b2lkIGJsaXR0aW5nIG92ZXJsYXBzXG5cbnZhciBkZWZUeHJXaWR0aCA9IDEwMjQ7IC8vIGRlZmF1bHQvbWluaW11bSB0ZXh0dXJlIHdpZHRoXG5cbnZhciBtYXhUeHJXID0gMTAyNDsgLy8gdGhlIG1heGltdW0gd2lkdGggb2YgYSB0ZXh0dXJlXG5cbnZhciBtYXhUeHJIID0gMTAyNDsgLy8gdGhlIG1heGltdW0gaGVpZ2h0IG9mIGEgdGV4dHVyZVxuXG52YXIgbWluVXRpbGl0eSA9IDAuMjsgLy8gaWYgdXNhZ2Ugb2YgdGV4dHVyZSBpcyBsZXNzIHRoYW4gdGhpcywgaXQgaXMgcmV0aXJlZFxuXG52YXIgbWF4RnVsbG5lc3MgPSAwLjg7IC8vIGZ1bGxuZXNzIG9mIHRleHR1cmUgYWZ0ZXIgd2hpY2ggcXVldWUgcmVtb3ZhbCBpcyBjaGVja2VkXG5cbnZhciBtYXhGdWxsbmVzc0NoZWNrcyA9IDEwOyAvLyBkZXF1ZXVlZCBhZnRlciB0aGlzIG1hbnkgY2hlY2tzXG5cbnZhciBkZXFDb3N0ID0gMC4xNTsgLy8gJSBvZiBhZGQnbCByZW5kZXJpbmcgY29zdCBhbGxvd2VkIGZvciBkZXF1ZXVpbmcgZWxlIGNhY2hlcyBlYWNoIGZyYW1lXG5cbnZhciBkZXFBdmdDb3N0ID0gMC4xOyAvLyAlIG9mIGFkZCdsIHJlbmRlcmluZyBjb3N0IGNvbXBhcmVkIHRvIGF2ZXJhZ2Ugb3ZlcmFsbCByZWRyYXcgdGltZVxuXG52YXIgZGVxTm9EcmF3Q29zdCA9IDAuOTsgLy8gJSBvZiBhdmcgZnJhbWUgdGltZSB0aGF0IGNhbiBiZSB1c2VkIGZvciBkZXF1ZXVlaW5nIHdoZW4gbm90IGRyYXdpbmdcblxudmFyIGRlcUZhc3RDb3N0ID0gMC45OyAvLyAlIG9mIGZyYW1lIHRpbWUgdG8gYmUgdXNlZCB3aGVuID42MGZwc1xuXG52YXIgZGVxUmVkcmF3VGhyZXNob2xkID0gMTAwOyAvLyB0aW1lIHRvIGJhdGNoIHJlZHJhd3MgdG9nZXRoZXIgZnJvbSBkZXF1ZXVlaW5nIHRvIGFsbG93IG1vcmUgZGVxdWV1ZWluZyBjYWxjcyB0byBoYXBwZW4gaW4gdGhlIG1lYW53aGlsZVxuXG52YXIgbWF4RGVxU2l6ZSA9IDE7IC8vIG51bWJlciBvZiBlbGVzIHRvIGRlcXVldWUgYW5kIHJlbmRlciBhdCBoaWdoZXIgdGV4dHVyZSBpbiBlYWNoIGJhdGNoXG5cbnZhciBnZXRUeHJSZWFzb25zID0ge1xuICBkZXF1ZXVlOiAnZGVxdWV1ZScsXG4gIGRvd25zY2FsZTogJ2Rvd25zY2FsZScsXG4gIGhpZ2hRdWFsaXR5OiAnaGlnaFF1YWxpdHknXG59O1xudmFyIGluaXREZWZhdWx0cyA9IGRlZmF1bHRzKHtcbiAgZ2V0S2V5OiBudWxsLFxuICBkb2VzRWxlSW52YWxpZGF0ZUtleTogZmFsc2lmeSxcbiAgZHJhd0VsZW1lbnQ6IG51bGwsXG4gIGdldEJvdW5kaW5nQm94OiBudWxsLFxuICBnZXRSb3RhdGlvblBvaW50OiBudWxsLFxuICBnZXRSb3RhdGlvbk9mZnNldDogbnVsbCxcbiAgaXNWaXNpYmxlOiB0cnVlaWZ5LFxuICBhbGxvd0VkZ2VUeHJDYWNoaW5nOiB0cnVlLFxuICBhbGxvd1BhcmVudFR4ckNhY2hpbmc6IHRydWVcbn0pO1xuXG52YXIgRWxlbWVudFRleHR1cmVDYWNoZSA9IGZ1bmN0aW9uIEVsZW1lbnRUZXh0dXJlQ2FjaGUocmVuZGVyZXIsIGluaXRPcHRpb25zKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgc2VsZi5yZW5kZXJlciA9IHJlbmRlcmVyO1xuICBzZWxmLm9uRGVxdWV1ZXMgPSBbXTtcbiAgdmFyIG9wdHMgPSBpbml0RGVmYXVsdHMoaW5pdE9wdGlvbnMpO1xuICBleHRlbmQoc2VsZiwgb3B0cyk7XG4gIHNlbGYubG9va3VwID0gbmV3IEVsZW1lbnRUZXh0dXJlQ2FjaGVMb29rdXAob3B0cy5nZXRLZXksIG9wdHMuZG9lc0VsZUludmFsaWRhdGVLZXkpO1xuICBzZWxmLnNldHVwRGVxdWV1ZWluZygpO1xufTtcblxudmFyIEVUQ3AgPSBFbGVtZW50VGV4dHVyZUNhY2hlLnByb3RvdHlwZTtcbkVUQ3AucmVhc29ucyA9IGdldFR4clJlYXNvbnM7IC8vIHRoZSBsaXN0IG9mIHRleHR1cmVzIGluIHdoaWNoIG5ldyBzdWJ0ZXh0dXJlcyBmb3IgZWxlbWVudHMgY2FuIGJlIHBsYWNlZFxuXG5FVENwLmdldFRleHR1cmVRdWV1ZSA9IGZ1bmN0aW9uICh0eHJIKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgc2VsZi5lbGVJbWdDYWNoZXMgPSBzZWxmLmVsZUltZ0NhY2hlcyB8fCB7fTtcbiAgcmV0dXJuIHNlbGYuZWxlSW1nQ2FjaGVzW3R4ckhdID0gc2VsZi5lbGVJbWdDYWNoZXNbdHhySF0gfHwgW107XG59OyAvLyB0aGUgbGlzdCBvZiB1c3VzZWQgdGV4dHVyZXMgd2hpY2ggY2FuIGJlIHJlY3ljbGVkIChpbiB1c2UgaW4gdGV4dHVyZSBxdWV1ZSlcblxuXG5FVENwLmdldFJldGlyZWRUZXh0dXJlUXVldWUgPSBmdW5jdGlvbiAodHhySCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBydHh0clFzID0gc2VsZi5lbGVJbWdDYWNoZXMucmV0aXJlZCA9IHNlbGYuZWxlSW1nQ2FjaGVzLnJldGlyZWQgfHwge307XG4gIHZhciBydHh0clEgPSBydHh0clFzW3R4ckhdID0gcnR4dHJRc1t0eHJIXSB8fCBbXTtcbiAgcmV0dXJuIHJ0eHRyUTtcbn07IC8vIHF1ZXVlIG9mIGVsZW1lbnQgZHJhdyByZXF1ZXN0cyBhdCBkaWZmZXJlbnQgc2NhbGUgbGV2ZWxzXG5cblxuRVRDcC5nZXRFbGVtZW50UXVldWUgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHEgPSBzZWxmLmVsZUNhY2hlUXVldWUgPSBzZWxmLmVsZUNhY2hlUXVldWUgfHwgbmV3IEhlYXAoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYi5yZXFzIC0gYS5yZXFzO1xuICB9KTtcbiAgcmV0dXJuIHE7XG59OyAvLyBxdWV1ZSBvZiBlbGVtZW50IGRyYXcgcmVxdWVzdHMgYXQgZGlmZmVyZW50IHNjYWxlIGxldmVscyAoZWxlbWVudCBpZCBsb29rdXApXG5cblxuRVRDcC5nZXRFbGVtZW50S2V5VG9RdWV1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgazJxID0gc2VsZi5lbGVLZXlUb0NhY2hlUXVldWUgPSBzZWxmLmVsZUtleVRvQ2FjaGVRdWV1ZSB8fCB7fTtcbiAgcmV0dXJuIGsycTtcbn07XG5cbkVUQ3AuZ2V0RWxlbWVudCA9IGZ1bmN0aW9uIChlbGUsIGJiLCBweFJhdGlvLCBsdmwsIHJlYXNvbikge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciByID0gdGhpcy5yZW5kZXJlcjtcbiAgdmFyIHpvb20gPSByLmN5Lnpvb20oKTtcbiAgdmFyIGxvb2t1cCA9IHRoaXMubG9va3VwO1xuXG4gIGlmIChiYi53ID09PSAwIHx8IGJiLmggPT09IDAgfHwgaXNOYU4oYmIudykgfHwgaXNOYU4oYmIuaCkgfHwgIWVsZS52aXNpYmxlKCkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmICghc2VsZi5hbGxvd0VkZ2VUeHJDYWNoaW5nICYmIGVsZS5pc0VkZ2UoKSB8fCAhc2VsZi5hbGxvd1BhcmVudFR4ckNhY2hpbmcgJiYgZWxlLmlzUGFyZW50KCkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmIChsdmwgPT0gbnVsbCkge1xuICAgIGx2bCA9IE1hdGguY2VpbChsb2cyKHpvb20gKiBweFJhdGlvKSk7XG4gIH1cblxuICBpZiAobHZsIDwgbWluTHZsKSB7XG4gICAgbHZsID0gbWluTHZsO1xuICB9IGVsc2UgaWYgKHpvb20gPj0gbWF4Wm9vbSB8fCBsdmwgPiBtYXhMdmwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHZhciBzY2FsZSA9IE1hdGgucG93KDIsIGx2bCk7XG4gIHZhciBlbGVTY2FsZWRIID0gYmIuaCAqIHNjYWxlO1xuICB2YXIgZWxlU2NhbGVkVyA9IGJiLncgKiBzY2FsZTtcbiAgdmFyIHNjYWxlZExhYmVsU2hvd24gPSByLmVsZVRleHRCaWdnZXJUaGFuTWluKGVsZSwgc2NhbGUpO1xuXG4gIGlmICghdGhpcy5pc1Zpc2libGUoZWxlLCBzY2FsZWRMYWJlbFNob3duKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIGVsZUNhY2hlID0gbG9va3VwLmdldChlbGUsIGx2bCk7IC8vIGlmIHRoaXMgZ2V0IHdhcyBvbiBhbiB1bnVzZWQvaW52YWxpZGF0ZWQgY2FjaGUsIHRoZW4gcmVzdG9yZSB0aGUgdGV4dHVyZSB1c2FnZSBtZXRyaWNcblxuICBpZiAoZWxlQ2FjaGUgJiYgZWxlQ2FjaGUuaW52YWxpZGF0ZWQpIHtcbiAgICBlbGVDYWNoZS5pbnZhbGlkYXRlZCA9IGZhbHNlO1xuICAgIGVsZUNhY2hlLnRleHR1cmUuaW52YWxpZGF0ZWRXaWR0aCAtPSBlbGVDYWNoZS53aWR0aDtcbiAgfVxuXG4gIGlmIChlbGVDYWNoZSkge1xuICAgIHJldHVybiBlbGVDYWNoZTtcbiAgfVxuXG4gIHZhciB0eHJIOyAvLyB3aGljaCB0ZXh0dXJlIGhlaWdodCB0aGlzIGVsZSBiZWxvbmdzIHRvXG5cbiAgaWYgKGVsZVNjYWxlZEggPD0gbWluVHhySCkge1xuICAgIHR4ckggPSBtaW5UeHJIO1xuICB9IGVsc2UgaWYgKGVsZVNjYWxlZEggPD0gdHhyU3RlcEgpIHtcbiAgICB0eHJIID0gdHhyU3RlcEg7XG4gIH0gZWxzZSB7XG4gICAgdHhySCA9IE1hdGguY2VpbChlbGVTY2FsZWRIIC8gdHhyU3RlcEgpICogdHhyU3RlcEg7XG4gIH1cblxuICBpZiAoZWxlU2NhbGVkSCA+IG1heFR4ckggfHwgZWxlU2NhbGVkVyA+IG1heFR4clcpIHtcbiAgICByZXR1cm4gbnVsbDsgLy8gY2FjaGluZyBsYXJnZSBlbGVtZW50cyBpcyBub3QgZWZmaWNpZW50XG4gIH1cblxuICB2YXIgdHhyUSA9IHNlbGYuZ2V0VGV4dHVyZVF1ZXVlKHR4ckgpOyAvLyBmaXJzdCB0cnkgdGhlIHNlY29uZCBsYXN0IG9uZSBpbiBjYXNlIGl0IGhhcyBzcGFjZSBhdCB0aGUgZW5kXG5cbiAgdmFyIHR4ciA9IHR4clFbdHhyUS5sZW5ndGggLSAyXTtcblxuICB2YXIgYWRkTmV3VHhyID0gZnVuY3Rpb24gYWRkTmV3VHhyKCkge1xuICAgIHJldHVybiBzZWxmLnJlY3ljbGVUZXh0dXJlKHR4ckgsIGVsZVNjYWxlZFcpIHx8IHNlbGYuYWRkVGV4dHVyZSh0eHJILCBlbGVTY2FsZWRXKTtcbiAgfTsgLy8gdHJ5IHRoZSBsYXN0IG9uZSBpZiB0aGVyZSBpcyBubyBzZWNvbmQgbGFzdCBvbmVcblxuXG4gIGlmICghdHhyKSB7XG4gICAgdHhyID0gdHhyUVt0eHJRLmxlbmd0aCAtIDFdO1xuICB9IC8vIGlmIHRoZSBsYXN0IG9uZSBkb2Vzbid0IGV4aXN0LCB3ZSBuZWVkIGEgZmlyc3Qgb25lXG5cblxuICBpZiAoIXR4cikge1xuICAgIHR4ciA9IGFkZE5ld1R4cigpO1xuICB9IC8vIGlmIHRoZXJlJ3Mgbm8gcm9vbSBpbiB0aGUgY3VycmVudCB0ZXh0dXJlLCB3ZSBuZWVkIGEgbmV3IG9uZVxuXG5cbiAgaWYgKHR4ci53aWR0aCAtIHR4ci51c2VkV2lkdGggPCBlbGVTY2FsZWRXKSB7XG4gICAgdHhyID0gYWRkTmV3VHhyKCk7XG4gIH1cblxuICB2YXIgc2NhbGFibGVGcm9tID0gZnVuY3Rpb24gc2NhbGFibGVGcm9tKG90aGVyQ2FjaGUpIHtcbiAgICByZXR1cm4gb3RoZXJDYWNoZSAmJiBvdGhlckNhY2hlLnNjYWxlZExhYmVsU2hvd24gPT09IHNjYWxlZExhYmVsU2hvd247XG4gIH07XG5cbiAgdmFyIGRlcWluZyA9IHJlYXNvbiAmJiByZWFzb24gPT09IGdldFR4clJlYXNvbnMuZGVxdWV1ZTtcbiAgdmFyIGhpZ2hRdWFsaXR5UmVxID0gcmVhc29uICYmIHJlYXNvbiA9PT0gZ2V0VHhyUmVhc29ucy5oaWdoUXVhbGl0eTtcbiAgdmFyIGRvd25zY2FsZVJlcSA9IHJlYXNvbiAmJiByZWFzb24gPT09IGdldFR4clJlYXNvbnMuZG93bnNjYWxlO1xuICB2YXIgaGlnaGVyQ2FjaGU7IC8vIHRoZSBuZWFyZXN0IGNhY2hlIHdpdGggYSBoaWdoZXIgbGV2ZWxcblxuICBmb3IgKHZhciBsID0gbHZsICsgMTsgbCA8PSBtYXhMdmw7IGwrKykge1xuICAgIHZhciBjID0gbG9va3VwLmdldChlbGUsIGwpO1xuXG4gICAgaWYgKGMpIHtcbiAgICAgIGhpZ2hlckNhY2hlID0gYztcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHZhciBvbmVVcENhY2hlID0gaGlnaGVyQ2FjaGUgJiYgaGlnaGVyQ2FjaGUubGV2ZWwgPT09IGx2bCArIDEgPyBoaWdoZXJDYWNoZSA6IG51bGw7XG5cbiAgdmFyIGRvd25zY2FsZSA9IGZ1bmN0aW9uIGRvd25zY2FsZSgpIHtcbiAgICB0eHIuY29udGV4dC5kcmF3SW1hZ2Uob25lVXBDYWNoZS50ZXh0dXJlLmNhbnZhcywgb25lVXBDYWNoZS54LCAwLCBvbmVVcENhY2hlLndpZHRoLCBvbmVVcENhY2hlLmhlaWdodCwgdHhyLnVzZWRXaWR0aCwgMCwgZWxlU2NhbGVkVywgZWxlU2NhbGVkSCk7XG4gIH07IC8vIHJlc2V0IGVsZSBhcmVhIGluIHRleHR1cmVcblxuXG4gIHR4ci5jb250ZXh0LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcbiAgdHhyLmNvbnRleHQuY2xlYXJSZWN0KHR4ci51c2VkV2lkdGgsIDAsIGVsZVNjYWxlZFcsIHR4ckgpO1xuXG4gIGlmIChzY2FsYWJsZUZyb20ob25lVXBDYWNoZSkpIHtcbiAgICAvLyB0aGVuIHdlIGNhbiByZWxhdGl2ZWx5IGNoZWFwbHkgcmVzY2FsZSB0aGUgZXhpc3RpbmcgaW1hZ2Ugdy9vIHJlcmVuZGVyaW5nXG4gICAgZG93bnNjYWxlKCk7XG4gIH0gZWxzZSBpZiAoc2NhbGFibGVGcm9tKGhpZ2hlckNhY2hlKSkge1xuICAgIC8vIHRoZW4gdXNlIHRoZSBoaWdoZXIgY2FjaGUgZm9yIG5vdyBhbmQgcXVldWUgdGhlIG5leHQgbGV2ZWwgZG93blxuICAgIC8vIHRvIGNoZWFwbHkgc2NhbGUgdG93YXJkcyB0aGUgc21hbGxlciBsZXZlbFxuICAgIGlmIChoaWdoUXVhbGl0eVJlcSkge1xuICAgICAgZm9yICh2YXIgX2wgPSBoaWdoZXJDYWNoZS5sZXZlbDsgX2wgPiBsdmw7IF9sLS0pIHtcbiAgICAgICAgb25lVXBDYWNoZSA9IHNlbGYuZ2V0RWxlbWVudChlbGUsIGJiLCBweFJhdGlvLCBfbCwgZ2V0VHhyUmVhc29ucy5kb3duc2NhbGUpO1xuICAgICAgfVxuXG4gICAgICBkb3duc2NhbGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZi5xdWV1ZUVsZW1lbnQoZWxlLCBoaWdoZXJDYWNoZS5sZXZlbCAtIDEpO1xuICAgICAgcmV0dXJuIGhpZ2hlckNhY2hlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgbG93ZXJDYWNoZTsgLy8gdGhlIG5lYXJlc3QgY2FjaGUgd2l0aCBhIGxvd2VyIGxldmVsXG5cbiAgICBpZiAoIWRlcWluZyAmJiAhaGlnaFF1YWxpdHlSZXEgJiYgIWRvd25zY2FsZVJlcSkge1xuICAgICAgZm9yICh2YXIgX2wyID0gbHZsIC0gMTsgX2wyID49IG1pbkx2bDsgX2wyLS0pIHtcbiAgICAgICAgdmFyIF9jID0gbG9va3VwLmdldChlbGUsIF9sMik7XG5cbiAgICAgICAgaWYgKF9jKSB7XG4gICAgICAgICAgbG93ZXJDYWNoZSA9IF9jO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNjYWxhYmxlRnJvbShsb3dlckNhY2hlKSkge1xuICAgICAgLy8gdGhlbiB1c2UgdGhlIGxvd2VyIHF1YWxpdHkgY2FjaGUgZm9yIG5vdyBhbmQgcXVldWUgdGhlIGJldHRlciBvbmUgZm9yIGxhdGVyXG4gICAgICBzZWxmLnF1ZXVlRWxlbWVudChlbGUsIGx2bCk7XG4gICAgICByZXR1cm4gbG93ZXJDYWNoZTtcbiAgICB9XG5cbiAgICB0eHIuY29udGV4dC50cmFuc2xhdGUodHhyLnVzZWRXaWR0aCwgMCk7XG4gICAgdHhyLmNvbnRleHQuc2NhbGUoc2NhbGUsIHNjYWxlKTtcbiAgICB0aGlzLmRyYXdFbGVtZW50KHR4ci5jb250ZXh0LCBlbGUsIGJiLCBzY2FsZWRMYWJlbFNob3duLCBmYWxzZSk7XG4gICAgdHhyLmNvbnRleHQuc2NhbGUoMSAvIHNjYWxlLCAxIC8gc2NhbGUpO1xuICAgIHR4ci5jb250ZXh0LnRyYW5zbGF0ZSgtdHhyLnVzZWRXaWR0aCwgMCk7XG4gIH1cblxuICBlbGVDYWNoZSA9IHtcbiAgICB4OiB0eHIudXNlZFdpZHRoLFxuICAgIHRleHR1cmU6IHR4cixcbiAgICBsZXZlbDogbHZsLFxuICAgIHNjYWxlOiBzY2FsZSxcbiAgICB3aWR0aDogZWxlU2NhbGVkVyxcbiAgICBoZWlnaHQ6IGVsZVNjYWxlZEgsXG4gICAgc2NhbGVkTGFiZWxTaG93bjogc2NhbGVkTGFiZWxTaG93blxuICB9O1xuICB0eHIudXNlZFdpZHRoICs9IE1hdGguY2VpbChlbGVTY2FsZWRXICsgZWxlVHhyU3BhY2luZyk7XG4gIHR4ci5lbGVDYWNoZXMucHVzaChlbGVDYWNoZSk7XG4gIGxvb2t1cC5zZXQoZWxlLCBsdmwsIGVsZUNhY2hlKTtcbiAgc2VsZi5jaGVja1RleHR1cmVGdWxsbmVzcyh0eHIpO1xuICByZXR1cm4gZWxlQ2FjaGU7XG59O1xuXG5FVENwLmludmFsaWRhdGVFbGVtZW50cyA9IGZ1bmN0aW9uIChlbGVzKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgIHRoaXMuaW52YWxpZGF0ZUVsZW1lbnQoZWxlc1tpXSk7XG4gIH1cbn07XG5cbkVUQ3AuaW52YWxpZGF0ZUVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGxvb2t1cCA9IHNlbGYubG9va3VwO1xuICB2YXIgY2FjaGVzID0gW107XG4gIHZhciBpbnZhbGlkID0gbG9va3VwLmlzSW52YWxpZChlbGUpO1xuXG4gIGlmICghaW52YWxpZCkge1xuICAgIHJldHVybjsgLy8gb3ZlcnJpZGUgdGhlIGludmFsaWRhdGlvbiByZXF1ZXN0IGlmIHRoZSBlbGVtZW50IGtleSBoYXMgbm90IGNoYW5nZWRcbiAgfVxuXG4gIGZvciAodmFyIGx2bCA9IG1pbkx2bDsgbHZsIDw9IG1heEx2bDsgbHZsKyspIHtcbiAgICB2YXIgY2FjaGUgPSBsb29rdXAuZ2V0Rm9yQ2FjaGVkS2V5KGVsZSwgbHZsKTtcblxuICAgIGlmIChjYWNoZSkge1xuICAgICAgY2FjaGVzLnB1c2goY2FjaGUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBub090aGVyRWxlc1VzZUNhY2hlID0gbG9va3VwLmludmFsaWRhdGUoZWxlKTtcblxuICBpZiAobm9PdGhlckVsZXNVc2VDYWNoZSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2FjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgX2NhY2hlID0gY2FjaGVzW2ldO1xuICAgICAgdmFyIHR4ciA9IF9jYWNoZS50ZXh0dXJlOyAvLyByZW1vdmUgc3BhY2UgZnJvbSB0aGUgdGV4dHVyZSBpdCBiZWxvbmdzIHRvXG5cbiAgICAgIHR4ci5pbnZhbGlkYXRlZFdpZHRoICs9IF9jYWNoZS53aWR0aDsgLy8gbWFyayB0aGUgY2FjaGUgYXMgaW52YWxpZGF0ZWRcblxuICAgICAgX2NhY2hlLmludmFsaWRhdGVkID0gdHJ1ZTsgLy8gcmV0aXJlIHRoZSB0ZXh0dXJlIGlmIGl0cyB1dGlsaXR5IGlzIGxvd1xuXG4gICAgICBzZWxmLmNoZWNrVGV4dHVyZVV0aWxpdHkodHhyKTtcbiAgICB9XG4gIH0gLy8gcmVtb3ZlIGZyb20gcXVldWUgc2luY2UgdGhlIG9sZCByZXEgd2FzIGZvciB0aGUgb2xkIHN0YXRlXG5cblxuICBzZWxmLnJlbW92ZUZyb21RdWV1ZShlbGUpO1xufTtcblxuRVRDcC5jaGVja1RleHR1cmVVdGlsaXR5ID0gZnVuY3Rpb24gKHR4cikge1xuICAvLyBpbnZhbGlkYXRlIGFsbCBlbnRyaWVzIGluIHRoZSBjYWNoZSBpZiB0aGUgY2FjaGUgc2l6ZSBpcyBzbWFsbFxuICBpZiAodHhyLmludmFsaWRhdGVkV2lkdGggPj0gbWluVXRpbGl0eSAqIHR4ci53aWR0aCkge1xuICAgIHRoaXMucmV0aXJlVGV4dHVyZSh0eHIpO1xuICB9XG59O1xuXG5FVENwLmNoZWNrVGV4dHVyZUZ1bGxuZXNzID0gZnVuY3Rpb24gKHR4cikge1xuICAvLyBpZiB0ZXh0dXJlIGhhcyBiZWVuIG1vc3RseSBmaWxsZWQgYW5kIHBhc3NlZCBvdmVyIHNldmVyYWwgdGltZXMsIHJlbW92ZVxuICAvLyBpdCBmcm9tIHRoZSBxdWV1ZSBzbyB3ZSBkb24ndCBuZWVkIHRvIHdhc3RlIHRpbWUgbG9va2luZyBhdCBpdCB0byBwdXQgbmV3IHRoaW5nc1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciB0eHJRID0gc2VsZi5nZXRUZXh0dXJlUXVldWUodHhyLmhlaWdodCk7XG5cbiAgaWYgKHR4ci51c2VkV2lkdGggLyB0eHIud2lkdGggPiBtYXhGdWxsbmVzcyAmJiB0eHIuZnVsbG5lc3NDaGVja3MgPj0gbWF4RnVsbG5lc3NDaGVja3MpIHtcbiAgICByZW1vdmVGcm9tQXJyYXkodHhyUSwgdHhyKTtcbiAgfSBlbHNlIHtcbiAgICB0eHIuZnVsbG5lc3NDaGVja3MrKztcbiAgfVxufTtcblxuRVRDcC5yZXRpcmVUZXh0dXJlID0gZnVuY3Rpb24gKHR4cikge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciB0eHJIID0gdHhyLmhlaWdodDtcbiAgdmFyIHR4clEgPSBzZWxmLmdldFRleHR1cmVRdWV1ZSh0eHJIKTtcbiAgdmFyIGxvb2t1cCA9IHRoaXMubG9va3VwOyAvLyByZXRpcmUgdGhlIHRleHR1cmUgZnJvbSB0aGUgYWN0aXZlIC8gc2VhcmNoYWJsZSBxdWV1ZTpcblxuICByZW1vdmVGcm9tQXJyYXkodHhyUSwgdHhyKTtcbiAgdHhyLnJldGlyZWQgPSB0cnVlOyAvLyByZW1vdmUgdGhlIHJlZnMgZnJvbSB0aGUgZWxlcyB0byB0aGUgY2FjaGVzOlxuXG4gIHZhciBlbGVDYWNoZXMgPSB0eHIuZWxlQ2FjaGVzO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlQ2FjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZUNhY2hlID0gZWxlQ2FjaGVzW2ldO1xuICAgIGxvb2t1cC5kZWxldGVDYWNoZShlbGVDYWNoZS5rZXksIGVsZUNhY2hlLmxldmVsKTtcbiAgfVxuXG4gIGNsZWFyQXJyYXkoZWxlQ2FjaGVzKTsgLy8gYWRkIHRoZSB0ZXh0dXJlIHRvIGEgcmV0aXJlZCBxdWV1ZSBzbyBpdCBjYW4gYmUgcmVjeWNsZWQgaW4gZnV0dXJlOlxuXG4gIHZhciBydHh0clEgPSBzZWxmLmdldFJldGlyZWRUZXh0dXJlUXVldWUodHhySCk7XG4gIHJ0eHRyUS5wdXNoKHR4cik7XG59O1xuXG5FVENwLmFkZFRleHR1cmUgPSBmdW5jdGlvbiAodHhySCwgbWluVykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciB0eHJRID0gc2VsZi5nZXRUZXh0dXJlUXVldWUodHhySCk7XG4gIHZhciB0eHIgPSB7fTtcbiAgdHhyUS5wdXNoKHR4cik7XG4gIHR4ci5lbGVDYWNoZXMgPSBbXTtcbiAgdHhyLmhlaWdodCA9IHR4ckg7XG4gIHR4ci53aWR0aCA9IE1hdGgubWF4KGRlZlR4cldpZHRoLCBtaW5XKTtcbiAgdHhyLnVzZWRXaWR0aCA9IDA7XG4gIHR4ci5pbnZhbGlkYXRlZFdpZHRoID0gMDtcbiAgdHhyLmZ1bGxuZXNzQ2hlY2tzID0gMDtcbiAgdHhyLmNhbnZhcyA9IHNlbGYucmVuZGVyZXIubWFrZU9mZnNjcmVlbkNhbnZhcyh0eHIud2lkdGgsIHR4ci5oZWlnaHQpO1xuICB0eHIuY29udGV4dCA9IHR4ci5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgcmV0dXJuIHR4cjtcbn07XG5cbkVUQ3AucmVjeWNsZVRleHR1cmUgPSBmdW5jdGlvbiAodHhySCwgbWluVykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciB0eHJRID0gc2VsZi5nZXRUZXh0dXJlUXVldWUodHhySCk7XG4gIHZhciBydHh0clEgPSBzZWxmLmdldFJldGlyZWRUZXh0dXJlUXVldWUodHhySCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBydHh0clEubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgdHhyID0gcnR4dHJRW2ldO1xuXG4gICAgaWYgKHR4ci53aWR0aCA+PSBtaW5XKSB7XG4gICAgICB0eHIucmV0aXJlZCA9IGZhbHNlO1xuICAgICAgdHhyLnVzZWRXaWR0aCA9IDA7XG4gICAgICB0eHIuaW52YWxpZGF0ZWRXaWR0aCA9IDA7XG4gICAgICB0eHIuZnVsbG5lc3NDaGVja3MgPSAwO1xuICAgICAgY2xlYXJBcnJheSh0eHIuZWxlQ2FjaGVzKTtcbiAgICAgIHR4ci5jb250ZXh0LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcbiAgICAgIHR4ci5jb250ZXh0LmNsZWFyUmVjdCgwLCAwLCB0eHIud2lkdGgsIHR4ci5oZWlnaHQpO1xuICAgICAgcmVtb3ZlRnJvbUFycmF5KHJ0eHRyUSwgdHhyKTtcbiAgICAgIHR4clEucHVzaCh0eHIpO1xuICAgICAgcmV0dXJuIHR4cjtcbiAgICB9XG4gIH1cbn07XG5cbkVUQ3AucXVldWVFbGVtZW50ID0gZnVuY3Rpb24gKGVsZSwgbHZsKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHEgPSBzZWxmLmdldEVsZW1lbnRRdWV1ZSgpO1xuICB2YXIgazJxID0gc2VsZi5nZXRFbGVtZW50S2V5VG9RdWV1ZSgpO1xuICB2YXIga2V5ID0gdGhpcy5nZXRLZXkoZWxlKTtcbiAgdmFyIGV4aXN0aW5nUmVxID0gazJxW2tleV07XG5cbiAgaWYgKGV4aXN0aW5nUmVxKSB7XG4gICAgLy8gdXNlIHRoZSBtYXggbHZsIGIvYyBpbiBiZXR3ZWVuIGx2bHMgYXJlIGNoZWFwIHRvIG1ha2VcbiAgICBleGlzdGluZ1JlcS5sZXZlbCA9IE1hdGgubWF4KGV4aXN0aW5nUmVxLmxldmVsLCBsdmwpO1xuICAgIGV4aXN0aW5nUmVxLmVsZXMubWVyZ2UoZWxlKTtcbiAgICBleGlzdGluZ1JlcS5yZXFzKys7XG4gICAgcS51cGRhdGVJdGVtKGV4aXN0aW5nUmVxKTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgcmVxID0ge1xuICAgICAgZWxlczogZWxlLnNwYXduKCkubWVyZ2UoZWxlKSxcbiAgICAgIGxldmVsOiBsdmwsXG4gICAgICByZXFzOiAxLFxuICAgICAga2V5OiBrZXlcbiAgICB9O1xuICAgIHEucHVzaChyZXEpO1xuICAgIGsycVtrZXldID0gcmVxO1xuICB9XG59O1xuXG5FVENwLmRlcXVldWUgPSBmdW5jdGlvbiAocHhSYXRpb1xuLyosIGV4dGVudCovXG4pIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgcSA9IHNlbGYuZ2V0RWxlbWVudFF1ZXVlKCk7XG4gIHZhciBrMnEgPSBzZWxmLmdldEVsZW1lbnRLZXlUb1F1ZXVlKCk7XG4gIHZhciBkZXF1ZXVlZCA9IFtdO1xuICB2YXIgbG9va3VwID0gc2VsZi5sb29rdXA7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXhEZXFTaXplOyBpKyspIHtcbiAgICBpZiAocS5zaXplKCkgPiAwKSB7XG4gICAgICB2YXIgcmVxID0gcS5wb3AoKTtcbiAgICAgIHZhciBrZXkgPSByZXEua2V5O1xuICAgICAgdmFyIGVsZSA9IHJlcS5lbGVzWzBdOyAvLyBhbGwgZWxlcyBoYXZlIHRoZSBzYW1lIGtleVxuXG4gICAgICB2YXIgY2FjaGVFeGlzdHMgPSBsb29rdXAuaGFzQ2FjaGUoZWxlLCByZXEubGV2ZWwpOyAvLyBjbGVhciBvdXQgdGhlIGtleSB0byByZXEgbG9va3VwXG5cbiAgICAgIGsycVtrZXldID0gbnVsbDsgLy8gZGVxdWV1ZWluZyBpc24ndCBuZWNlc3Nhcnkgd2l0aCBhbiBleGlzdGluZyBjYWNoZVxuXG4gICAgICBpZiAoY2FjaGVFeGlzdHMpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGRlcXVldWVkLnB1c2gocmVxKTtcbiAgICAgIHZhciBiYiA9IHNlbGYuZ2V0Qm91bmRpbmdCb3goZWxlKTtcbiAgICAgIHNlbGYuZ2V0RWxlbWVudChlbGUsIGJiLCBweFJhdGlvLCByZXEubGV2ZWwsIGdldFR4clJlYXNvbnMuZGVxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkZXF1ZXVlZDtcbn07XG5cbkVUQ3AucmVtb3ZlRnJvbVF1ZXVlID0gZnVuY3Rpb24gKGVsZSkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBxID0gc2VsZi5nZXRFbGVtZW50UXVldWUoKTtcbiAgdmFyIGsycSA9IHNlbGYuZ2V0RWxlbWVudEtleVRvUXVldWUoKTtcbiAgdmFyIGtleSA9IHRoaXMuZ2V0S2V5KGVsZSk7XG4gIHZhciByZXEgPSBrMnFba2V5XTtcblxuICBpZiAocmVxICE9IG51bGwpIHtcbiAgICBpZiAocmVxLmVsZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAvLyByZW1vdmUgaWYgbGFzdCBlbGUgaW4gdGhlIHJlcVxuICAgICAgLy8gYnJpbmcgdG8gZnJvbnQgb2YgcXVldWVcbiAgICAgIHJlcS5yZXFzID0gTUFYX0lOVDtcbiAgICAgIHEudXBkYXRlSXRlbShyZXEpO1xuICAgICAgcS5wb3AoKTsgLy8gcmVtb3ZlIGZyb20gcXVldWVcblxuICAgICAgazJxW2tleV0gPSBudWxsOyAvLyByZW1vdmUgZnJvbSBsb29rdXAgbWFwXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIG90aGVyd2lzZSBqdXN0IHJlbW92ZSBlbGUgZnJvbSByZXFcbiAgICAgIHJlcS5lbGVzLnVubWVyZ2UoZWxlKTtcbiAgICB9XG4gIH1cbn07XG5cbkVUQ3Aub25EZXF1ZXVlID0gZnVuY3Rpb24gKGZuKSB7XG4gIHRoaXMub25EZXF1ZXVlcy5wdXNoKGZuKTtcbn07XG5cbkVUQ3Aub2ZmRGVxdWV1ZSA9IGZ1bmN0aW9uIChmbikge1xuICByZW1vdmVGcm9tQXJyYXkodGhpcy5vbkRlcXVldWVzLCBmbik7XG59O1xuXG5FVENwLnNldHVwRGVxdWV1ZWluZyA9IGRlZnMuc2V0dXBEZXF1ZXVlaW5nKHtcbiAgZGVxUmVkcmF3VGhyZXNob2xkOiBkZXFSZWRyYXdUaHJlc2hvbGQsXG4gIGRlcUNvc3Q6IGRlcUNvc3QsXG4gIGRlcUF2Z0Nvc3Q6IGRlcUF2Z0Nvc3QsXG4gIGRlcU5vRHJhd0Nvc3Q6IGRlcU5vRHJhd0Nvc3QsXG4gIGRlcUZhc3RDb3N0OiBkZXFGYXN0Q29zdCxcbiAgZGVxOiBmdW5jdGlvbiBkZXEoc2VsZiwgcHhSYXRpbywgZXh0ZW50KSB7XG4gICAgcmV0dXJuIHNlbGYuZGVxdWV1ZShweFJhdGlvLCBleHRlbnQpO1xuICB9LFxuICBvbkRlcWQ6IGZ1bmN0aW9uIG9uRGVxZChzZWxmLCBkZXFkKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWxmLm9uRGVxdWV1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBmbiA9IHNlbGYub25EZXF1ZXVlc1tpXTtcbiAgICAgIGZuKGRlcWQpO1xuICAgIH1cbiAgfSxcbiAgc2hvdWxkUmVkcmF3OiBmdW5jdGlvbiBzaG91bGRSZWRyYXcoc2VsZiwgZGVxZCwgcHhSYXRpbywgZXh0ZW50KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZXFkLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZWxlcyA9IGRlcWRbaV0uZWxlcztcblxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBlbGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBiYiA9IGVsZXNbal0uYm91bmRpbmdCb3goKTtcblxuICAgICAgICBpZiAoYm91bmRpbmdCb3hlc0ludGVyc2VjdChiYiwgZXh0ZW50KSkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuICBwcmlvcml0eTogZnVuY3Rpb24gcHJpb3JpdHkoc2VsZikge1xuICAgIHJldHVybiBzZWxmLnJlbmRlcmVyLmJlZm9yZVJlbmRlclByaW9yaXRpZXMuZWxlVHhyRGVxO1xuICB9XG59KTtcblxudmFyIGRlZk51bUxheWVycyA9IDE7IC8vIGRlZmF1bHQgbnVtYmVyIG9mIGxheWVycyB0byB1c2VcblxudmFyIG1pbkx2bCQxID0gLTQ7IC8vIHdoZW4gc2NhbGluZyBzbWFsbGVyIHRoYW4gdGhhdCB3ZSBkb24ndCBuZWVkIHRvIHJlLXJlbmRlclxuXG52YXIgbWF4THZsJDEgPSAyOyAvLyB3aGVuIGxhcmdlciB0aGFuIHRoaXMgc2NhbGUganVzdCByZW5kZXIgZGlyZWN0bHkgKGNhY2hpbmcgaXMgbm90IGhlbHBmdWwpXG5cbnZhciBtYXhab29tJDEgPSAzLjk5OyAvLyBiZXlvbmQgdGhpcyB6b29tIGxldmVsLCBsYXllcmVkIHRleHR1cmVzIGFyZSBub3QgdXNlZFxuXG52YXIgZGVxUmVkcmF3VGhyZXNob2xkJDEgPSA1MDsgLy8gdGltZSB0byBiYXRjaCByZWRyYXdzIHRvZ2V0aGVyIGZyb20gZGVxdWV1ZWluZyB0byBhbGxvdyBtb3JlIGRlcXVldWVpbmcgY2FsY3MgdG8gaGFwcGVuIGluIHRoZSBtZWFud2hpbGVcblxudmFyIHJlZmluZUVsZURlYm91bmNlVGltZSA9IDUwOyAvLyB0aW1lIHRvIGRlYm91bmNlIHNoYXJwZXIgZWxlIHRleHR1cmUgdXBkYXRlc1xuXG52YXIgZGVxQ29zdCQxID0gMC4xNTsgLy8gJSBvZiBhZGQnbCByZW5kZXJpbmcgY29zdCBhbGxvd2VkIGZvciBkZXF1ZXVpbmcgZWxlIGNhY2hlcyBlYWNoIGZyYW1lXG5cbnZhciBkZXFBdmdDb3N0JDEgPSAwLjE7IC8vICUgb2YgYWRkJ2wgcmVuZGVyaW5nIGNvc3QgY29tcGFyZWQgdG8gYXZlcmFnZSBvdmVyYWxsIHJlZHJhdyB0aW1lXG5cbnZhciBkZXFOb0RyYXdDb3N0JDEgPSAwLjk7IC8vICUgb2YgYXZnIGZyYW1lIHRpbWUgdGhhdCBjYW4gYmUgdXNlZCBmb3IgZGVxdWV1ZWluZyB3aGVuIG5vdCBkcmF3aW5nXG5cbnZhciBkZXFGYXN0Q29zdCQxID0gMC45OyAvLyAlIG9mIGZyYW1lIHRpbWUgdG8gYmUgdXNlZCB3aGVuID42MGZwc1xuXG52YXIgbWF4RGVxU2l6ZSQxID0gMTsgLy8gbnVtYmVyIG9mIGVsZXMgdG8gZGVxdWV1ZSBhbmQgcmVuZGVyIGF0IGhpZ2hlciB0ZXh0dXJlIGluIGVhY2ggYmF0Y2hcblxudmFyIGludmFsaWRUaHJlc2hvbGQgPSAyNTA7IC8vIHRpbWUgdGhyZXNob2xkIGZvciBkaXNhYmxpbmcgYi9jIG9mIGludmFsaWRhdGlvbnNcblxudmFyIG1heExheWVyQXJlYSA9IDQwMDAgKiA0MDAwOyAvLyBsYXllcnMgY2FuJ3QgYmUgYmlnZ2VyIHRoYW4gdGhpc1xuXG52YXIgdXNlSGlnaFF1YWxpdHlFbGVUeHJSZXFzID0gdHJ1ZTsgLy8gd2hldGhlciB0byB1c2UgaGlnaCBxdWFsaXR5IGVsZSB0eHIgcmVxdWVzdHMgKGdlbmVyYWxseSBmYXN0ZXIgYW5kIGNoZWFwZXIgaW4gdGhlIGxvbmd0ZXJtKVxuLy8gdmFyIGxvZyA9IGZ1bmN0aW9uKCl7IGNvbnNvbGUubG9nLmFwcGx5KCBjb25zb2xlLCBhcmd1bWVudHMgKTsgfTtcblxudmFyIExheWVyZWRUZXh0dXJlQ2FjaGUgPSBmdW5jdGlvbiBMYXllcmVkVGV4dHVyZUNhY2hlKHJlbmRlcmVyKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHIgPSBzZWxmLnJlbmRlcmVyID0gcmVuZGVyZXI7XG4gIHZhciBjeSA9IHIuY3k7XG4gIHNlbGYubGF5ZXJzQnlMZXZlbCA9IHt9OyAvLyBlLmcuIDIgPT4gWyBsYXllcjEsIGxheWVyMiwgLi4uLCBsYXllck4gXVxuXG4gIHNlbGYuZmlyc3RHZXQgPSB0cnVlO1xuICBzZWxmLmxhc3RJbnZhbGlkYXRpb25UaW1lID0gcGVyZm9ybWFuY2VOb3coKSAtIDIgKiBpbnZhbGlkVGhyZXNob2xkO1xuICBzZWxmLnNraXBwaW5nID0gZmFsc2U7XG4gIHNlbGYuZWxlVHhyRGVxcyA9IGN5LmNvbGxlY3Rpb24oKTtcbiAgc2VsZi5zY2hlZHVsZUVsZW1lbnRSZWZpbmVtZW50ID0gdXRpbChmdW5jdGlvbiAoKSB7XG4gICAgc2VsZi5yZWZpbmVFbGVtZW50VGV4dHVyZXMoc2VsZi5lbGVUeHJEZXFzKTtcbiAgICBzZWxmLmVsZVR4ckRlcXMudW5tZXJnZShzZWxmLmVsZVR4ckRlcXMpO1xuICB9LCByZWZpbmVFbGVEZWJvdW5jZVRpbWUpO1xuICByLmJlZm9yZVJlbmRlcihmdW5jdGlvbiAod2lsbERyYXcsIG5vdykge1xuICAgIGlmIChub3cgLSBzZWxmLmxhc3RJbnZhbGlkYXRpb25UaW1lIDw9IGludmFsaWRUaHJlc2hvbGQpIHtcbiAgICAgIHNlbGYuc2tpcHBpbmcgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZWxmLnNraXBwaW5nID0gZmFsc2U7XG4gICAgfVxuICB9LCByLmJlZm9yZVJlbmRlclByaW9yaXRpZXMubHlyVHhyU2tpcCk7XG5cbiAgdmFyIHFTb3J0ID0gZnVuY3Rpb24gcVNvcnQoYSwgYikge1xuICAgIHJldHVybiBiLnJlcXMgLSBhLnJlcXM7XG4gIH07XG5cbiAgc2VsZi5sYXllcnNRdWV1ZSA9IG5ldyBIZWFwKHFTb3J0KTtcbiAgc2VsZi5zZXR1cERlcXVldWVpbmcoKTtcbn07XG5cbnZhciBMVENwID0gTGF5ZXJlZFRleHR1cmVDYWNoZS5wcm90b3R5cGU7XG52YXIgbGF5ZXJJZFBvb2wgPSAwO1xudmFyIE1BWF9JTlQkMSA9IE1hdGgucG93KDIsIDUzKSAtIDE7XG5cbkxUQ3AubWFrZUxheWVyID0gZnVuY3Rpb24gKGJiLCBsdmwpIHtcbiAgdmFyIHNjYWxlID0gTWF0aC5wb3coMiwgbHZsKTtcbiAgdmFyIHcgPSBNYXRoLmNlaWwoYmIudyAqIHNjYWxlKTtcbiAgdmFyIGggPSBNYXRoLmNlaWwoYmIuaCAqIHNjYWxlKTtcbiAgdmFyIGNhbnZhcyA9IHRoaXMucmVuZGVyZXIubWFrZU9mZnNjcmVlbkNhbnZhcyh3LCBoKTtcbiAgdmFyIGxheWVyID0ge1xuICAgIGlkOiBsYXllcklkUG9vbCA9ICsrbGF5ZXJJZFBvb2wgJSBNQVhfSU5UJDEsXG4gICAgYmI6IGJiLFxuICAgIGxldmVsOiBsdmwsXG4gICAgd2lkdGg6IHcsXG4gICAgaGVpZ2h0OiBoLFxuICAgIGNhbnZhczogY2FudmFzLFxuICAgIGNvbnRleHQ6IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpLFxuICAgIGVsZXM6IFtdLFxuICAgIGVsZXNRdWV1ZTogW10sXG4gICAgcmVxczogMFxuICB9OyAvLyBsb2coJ21ha2UgbGF5ZXIgJXMgd2l0aCB3ICVzIGFuZCBoICVzIGFuZCBsdmwgJXMnLCBsYXllci5pZCwgbGF5ZXIud2lkdGgsIGxheWVyLmhlaWdodCwgbGF5ZXIubGV2ZWwpO1xuXG4gIHZhciBjeHQgPSBsYXllci5jb250ZXh0O1xuICB2YXIgZHggPSAtbGF5ZXIuYmIueDE7XG4gIHZhciBkeSA9IC1sYXllci5iYi55MTsgLy8gZG8gdGhlIHRyYW5zZm9ybSBvbiBjcmVhdGlvbiB0byBzYXZlIGN5Y2xlcyAoaXQncyB0aGUgc2FtZSBmb3IgYWxsIGVsZXMpXG5cbiAgY3h0LnNjYWxlKHNjYWxlLCBzY2FsZSk7XG4gIGN4dC50cmFuc2xhdGUoZHgsIGR5KTtcbiAgcmV0dXJuIGxheWVyO1xufTtcblxuTFRDcC5nZXRMYXllcnMgPSBmdW5jdGlvbiAoZWxlcywgcHhSYXRpbywgbHZsKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHIgPSBzZWxmLnJlbmRlcmVyO1xuICB2YXIgY3kgPSByLmN5O1xuICB2YXIgem9vbSA9IGN5Lnpvb20oKTtcbiAgdmFyIGZpcnN0R2V0ID0gc2VsZi5maXJzdEdldDtcbiAgc2VsZi5maXJzdEdldCA9IGZhbHNlOyAvLyBsb2coJy0tXFxuZ2V0IGxheWVycyB3aXRoICVzIGVsZXMnLCBlbGVzLmxlbmd0aCk7XG4gIC8vbG9nIGVsZXMubWFwKGZ1bmN0aW9uKGVsZSl7IHJldHVybiBlbGUuaWQoKSB9KSApO1xuXG4gIGlmIChsdmwgPT0gbnVsbCkge1xuICAgIGx2bCA9IE1hdGguY2VpbChsb2cyKHpvb20gKiBweFJhdGlvKSk7XG5cbiAgICBpZiAobHZsIDwgbWluTHZsJDEpIHtcbiAgICAgIGx2bCA9IG1pbkx2bCQxO1xuICAgIH0gZWxzZSBpZiAoem9vbSA+PSBtYXhab29tJDEgfHwgbHZsID4gbWF4THZsJDEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHNlbGYudmFsaWRhdGVMYXllcnNFbGVzT3JkZXJpbmcobHZsLCBlbGVzKTtcbiAgdmFyIGxheWVyc0J5THZsID0gc2VsZi5sYXllcnNCeUxldmVsO1xuICB2YXIgc2NhbGUgPSBNYXRoLnBvdygyLCBsdmwpO1xuICB2YXIgbGF5ZXJzID0gbGF5ZXJzQnlMdmxbbHZsXSA9IGxheWVyc0J5THZsW2x2bF0gfHwgW107XG4gIHZhciBiYjtcbiAgdmFyIGx2bENvbXBsZXRlID0gc2VsZi5sZXZlbElzQ29tcGxldGUobHZsLCBlbGVzKTtcbiAgdmFyIHRtcExheWVycztcblxuICB2YXIgY2hlY2tUZW1wTGV2ZWxzID0gZnVuY3Rpb24gY2hlY2tUZW1wTGV2ZWxzKCkge1xuICAgIHZhciBjYW5Vc2VBc1RtcEx2bCA9IGZ1bmN0aW9uIGNhblVzZUFzVG1wTHZsKGwpIHtcbiAgICAgIHNlbGYudmFsaWRhdGVMYXllcnNFbGVzT3JkZXJpbmcobCwgZWxlcyk7XG5cbiAgICAgIGlmIChzZWxmLmxldmVsSXNDb21wbGV0ZShsLCBlbGVzKSkge1xuICAgICAgICB0bXBMYXllcnMgPSBsYXllcnNCeUx2bFtsXTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHZhciBjaGVja0x2bHMgPSBmdW5jdGlvbiBjaGVja0x2bHMoZGlyKSB7XG4gICAgICBpZiAodG1wTGF5ZXJzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgZm9yICh2YXIgbCA9IGx2bCArIGRpcjsgbWluTHZsJDEgPD0gbCAmJiBsIDw9IG1heEx2bCQxOyBsICs9IGRpcikge1xuICAgICAgICBpZiAoY2FuVXNlQXNUbXBMdmwobCkpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBjaGVja0x2bHMoKzEpO1xuICAgIGNoZWNrTHZscygtMSk7IC8vIHJlbW92ZSB0aGUgaW52YWxpZCBsYXllcnM7IHRoZXkgd2lsbCBiZSByZXBsYWNlZCBhcyBuZWVkZWQgbGF0ZXIgaW4gdGhpcyBmdW5jdGlvblxuXG4gICAgZm9yICh2YXIgaSA9IGxheWVycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICBpZiAobGF5ZXIuaW52YWxpZCkge1xuICAgICAgICByZW1vdmVGcm9tQXJyYXkobGF5ZXJzLCBsYXllcik7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGlmICghbHZsQ29tcGxldGUpIHtcbiAgICAvLyBpZiB0aGUgY3VycmVudCBsZXZlbCBpcyBpbmNvbXBsZXRlLCB0aGVuIHVzZSB0aGUgY2xvc2VzdCwgYmVzdCBxdWFsaXR5IGxheWVyc2V0IHRlbXBvcmFyaWx5XG4gICAgLy8gYW5kIGxhdGVyIHF1ZXVlIHRoZSBjdXJyZW50IGxheWVyc2V0IHNvIHdlIGNhbiBnZXQgdGhlIHByb3BlciBxdWFsaXR5IGxldmVsIHNvb25cbiAgICBjaGVja1RlbXBMZXZlbHMoKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBsb2coJ2xldmVsIGNvbXBsZXRlLCB1c2luZyBleGlzdGluZyBsYXllcnNcXG4tLScpO1xuICAgIHJldHVybiBsYXllcnM7XG4gIH1cblxuICB2YXIgZ2V0QmIgPSBmdW5jdGlvbiBnZXRCYigpIHtcbiAgICBpZiAoIWJiKSB7XG4gICAgICBiYiA9IG1ha2VCb3VuZGluZ0JveCgpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdXBkYXRlQm91bmRpbmdCb3goYmIsIGVsZXNbaV0uYm91bmRpbmdCb3goKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGJiO1xuICB9O1xuXG4gIHZhciBtYWtlTGF5ZXIgPSBmdW5jdGlvbiBtYWtlTGF5ZXIob3B0cykge1xuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAgIHZhciBhZnRlciA9IG9wdHMuYWZ0ZXI7XG4gICAgZ2V0QmIoKTtcbiAgICB2YXIgYXJlYSA9IGJiLncgKiBzY2FsZSAqIChiYi5oICogc2NhbGUpO1xuXG4gICAgaWYgKGFyZWEgPiBtYXhMYXllckFyZWEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBsYXllciA9IHNlbGYubWFrZUxheWVyKGJiLCBsdmwpO1xuXG4gICAgaWYgKGFmdGVyICE9IG51bGwpIHtcbiAgICAgIHZhciBpbmRleCA9IGxheWVycy5pbmRleE9mKGFmdGVyKSArIDE7XG4gICAgICBsYXllcnMuc3BsaWNlKGluZGV4LCAwLCBsYXllcik7XG4gICAgfSBlbHNlIGlmIChvcHRzLmluc2VydCA9PT0gdW5kZWZpbmVkIHx8IG9wdHMuaW5zZXJ0KSB7XG4gICAgICAvLyBubyBhZnRlciBzcGVjaWZpZWQgPT4gZmlyc3QgbGF5ZXIgbWFkZSBzbyBwdXQgYXQgc3RhcnRcbiAgICAgIGxheWVycy51bnNoaWZ0KGxheWVyKTtcbiAgICB9IC8vIGlmKCB0bXBMYXllcnMgKXtcbiAgICAvL3NlbGYucXVldWVMYXllciggbGF5ZXIgKTtcbiAgICAvLyB9XG5cblxuICAgIHJldHVybiBsYXllcjtcbiAgfTtcblxuICBpZiAoc2VsZi5za2lwcGluZyAmJiAhZmlyc3RHZXQpIHtcbiAgICAvLyBsb2coJ3NraXAgbGF5ZXJzJyk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH0gLy8gbG9nKCdkbyBsYXllcnMnKTtcblxuXG4gIHZhciBsYXllciA9IG51bGw7XG4gIHZhciBtYXhFbGVzUGVyTGF5ZXIgPSBlbGVzLmxlbmd0aCAvIGRlZk51bUxheWVycztcbiAgdmFyIGFsbG93TGF6eVF1ZXVlaW5nID0gICFmaXJzdEdldDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICB2YXIgcnMgPSBlbGUuX3ByaXZhdGUucnNjcmF0Y2g7XG4gICAgdmFyIGNhY2hlcyA9IHJzLmltZ0xheWVyQ2FjaGVzID0gcnMuaW1nTGF5ZXJDYWNoZXMgfHwge307IC8vIGxvZygnbG9vayBhdCBlbGUnLCBlbGUuaWQoKSk7XG5cbiAgICB2YXIgZXhpc3RpbmdMYXllciA9IGNhY2hlc1tsdmxdO1xuXG4gICAgaWYgKGV4aXN0aW5nTGF5ZXIpIHtcbiAgICAgIC8vIHJldXNlIGxheWVyIGZvciBsYXRlciBlbGVzXG4gICAgICAvLyBsb2coJ3JldXNlIGxheWVyIGZvcicsIGVsZS5pZCgpKTtcbiAgICAgIGxheWVyID0gZXhpc3RpbmdMYXllcjtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICghbGF5ZXIgfHwgbGF5ZXIuZWxlcy5sZW5ndGggPj0gbWF4RWxlc1BlckxheWVyIHx8ICFib3VuZGluZ0JveEluQm91bmRpbmdCb3gobGF5ZXIuYmIsIGVsZS5ib3VuZGluZ0JveCgpKSkge1xuICAgICAgLy8gbG9nKCdtYWtlIG5ldyBsYXllciBmb3IgZWxlICVzJywgZWxlLmlkKCkpO1xuICAgICAgbGF5ZXIgPSBtYWtlTGF5ZXIoe1xuICAgICAgICBpbnNlcnQ6IHRydWUsXG4gICAgICAgIGFmdGVyOiBsYXllclxuICAgICAgfSk7IC8vIGlmIG5vdyBsYXllciBjYW4gYmUgYnVpbHQgdGhlbiB3ZSBjYW4ndCB1c2UgbGF5ZXJzIGF0IHRoaXMgbGV2ZWxcblxuICAgICAgaWYgKCFsYXllcikge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0gLy8gbG9nKCduZXcgbGF5ZXIgd2l0aCBpZCAlcycsIGxheWVyLmlkKTtcblxuICAgIH1cblxuICAgIGlmICh0bXBMYXllcnMgfHwgYWxsb3dMYXp5UXVldWVpbmcpIHtcbiAgICAgIC8vIGxvZygncXVldWUgZWxlICVzIGluIGxheWVyICVzJywgZWxlLmlkKCksIGxheWVyLmlkKTtcbiAgICAgIHNlbGYucXVldWVMYXllcihsYXllciwgZWxlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gbG9nKCdkcmF3IGVsZSAlcyBpbiBsYXllciAlcycsIGVsZS5pZCgpLCBsYXllci5pZCk7XG4gICAgICBzZWxmLmRyYXdFbGVJbkxheWVyKGxheWVyLCBlbGUsIGx2bCwgcHhSYXRpbyk7XG4gICAgfVxuXG4gICAgbGF5ZXIuZWxlcy5wdXNoKGVsZSk7XG4gICAgY2FjaGVzW2x2bF0gPSBsYXllcjtcbiAgfSAvLyBsb2coJy0tJyk7XG5cblxuICBpZiAodG1wTGF5ZXJzKSB7XG4gICAgLy8gdGhlbiB3ZSBvbmx5IHF1ZXVlZCB0aGUgY3VycmVudCBsYXllcnNldCBhbmQgY2FuJ3QgZHJhdyBpdCB5ZXRcbiAgICByZXR1cm4gdG1wTGF5ZXJzO1xuICB9XG5cbiAgaWYgKGFsbG93TGF6eVF1ZXVlaW5nKSB7XG4gICAgLy8gbG9nKCdsYXp5IHF1ZXVlIGxldmVsJywgbHZsKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBsYXllcnM7XG59OyAvLyBhIGxheWVyIG1heSB3YW50IHRvIHVzZSBhbiBlbGUgY2FjaGUgb2YgYSBoaWdoZXIgbGV2ZWwgdG8gYXZvaWQgYmx1cnJpbmVzc1xuLy8gc28gdGhlIGxheWVyIGxldmVsIG1pZ2h0IG5vdCBlcXVhbCB0aGUgZWxlIGxldmVsXG5cblxuTFRDcC5nZXRFbGVMZXZlbEZvckxheWVyTGV2ZWwgPSBmdW5jdGlvbiAobHZsLCBweFJhdGlvKSB7XG4gIHJldHVybiBsdmw7XG59O1xuXG5MVENwLmRyYXdFbGVJbkxheWVyID0gZnVuY3Rpb24gKGxheWVyLCBlbGUsIGx2bCwgcHhSYXRpbykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciByID0gdGhpcy5yZW5kZXJlcjtcbiAgdmFyIGNvbnRleHQgPSBsYXllci5jb250ZXh0O1xuICB2YXIgYmIgPSBlbGUuYm91bmRpbmdCb3goKTtcblxuICBpZiAoYmIudyA9PT0gMCB8fCBiYi5oID09PSAwIHx8ICFlbGUudmlzaWJsZSgpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbHZsID0gc2VsZi5nZXRFbGVMZXZlbEZvckxheWVyTGV2ZWwobHZsLCBweFJhdGlvKTtcblxuICB7XG4gICAgci5zZXRJbWdTbW9vdGhpbmcoY29udGV4dCwgZmFsc2UpO1xuICB9XG5cbiAge1xuICAgIHIuZHJhd0NhY2hlZEVsZW1lbnQoY29udGV4dCwgZWxlLCBudWxsLCBudWxsLCBsdmwsIHVzZUhpZ2hRdWFsaXR5RWxlVHhyUmVxcyk7XG4gIH1cblxuICB7XG4gICAgci5zZXRJbWdTbW9vdGhpbmcoY29udGV4dCwgdHJ1ZSk7XG4gIH1cbn07XG5cbkxUQ3AubGV2ZWxJc0NvbXBsZXRlID0gZnVuY3Rpb24gKGx2bCwgZWxlcykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBsYXllcnMgPSBzZWxmLmxheWVyc0J5TGV2ZWxbbHZsXTtcblxuICBpZiAoIWxheWVycyB8fCBsYXllcnMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdmFyIG51bUVsZXNJbkxheWVycyA9IDA7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXllcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgbGF5ZXIgPSBsYXllcnNbaV07IC8vIGlmIHRoZXJlIGFyZSBhbnkgZWxlcyBuZWVkZWQgdG8gYmUgZHJhd24geWV0LCB0aGUgbGV2ZWwgaXMgbm90IGNvbXBsZXRlXG5cbiAgICBpZiAobGF5ZXIucmVxcyA+IDApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IC8vIGlmIHRoZSBsYXllciBpcyBpbnZhbGlkLCB0aGUgbGV2ZWwgaXMgbm90IGNvbXBsZXRlXG5cblxuICAgIGlmIChsYXllci5pbnZhbGlkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbnVtRWxlc0luTGF5ZXJzICs9IGxheWVyLmVsZXMubGVuZ3RoO1xuICB9IC8vIHdlIHNob3VsZCBoYXZlIGV4YWN0bHkgdGhlIG51bWJlciBvZiBlbGVzIHBhc3NlZCBpbiB0byBiZSBjb21wbGV0ZVxuXG5cbiAgaWYgKG51bUVsZXNJbkxheWVycyAhPT0gZWxlcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbkxUQ3AudmFsaWRhdGVMYXllcnNFbGVzT3JkZXJpbmcgPSBmdW5jdGlvbiAobHZsLCBlbGVzKSB7XG4gIHZhciBsYXllcnMgPSB0aGlzLmxheWVyc0J5TGV2ZWxbbHZsXTtcblxuICBpZiAoIWxheWVycykge1xuICAgIHJldHVybjtcbiAgfSAvLyBpZiBpbiBhIGxheWVyIHRoZSBlbGVzIGFyZSBub3QgaW4gdGhlIHNhbWUgb3JkZXIsIHRoZW4gdGhlIGxheWVyIGlzIGludmFsaWRcbiAgLy8gKGkuZS4gdGhlcmUgaXMgYW4gZWxlIGluIGJldHdlZW4gdGhlIGVsZXMgaW4gdGhlIGxheWVyKVxuXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXllcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgbGF5ZXIgPSBsYXllcnNbaV07XG4gICAgdmFyIG9mZnNldCA9IC0xOyAvLyBmaW5kIHRoZSBvZmZzZXRcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgZWxlcy5sZW5ndGg7IGorKykge1xuICAgICAgaWYgKGxheWVyLmVsZXNbMF0gPT09IGVsZXNbal0pIHtcbiAgICAgICAgb2Zmc2V0ID0gajtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9mZnNldCA8IDApIHtcbiAgICAgIC8vIHRoZW4gdGhlIGxheWVyIGhhcyBub25leGlzdGFudCBlbGVtZW50cyBhbmQgaXMgaW52YWxpZFxuICAgICAgdGhpcy5pbnZhbGlkYXRlTGF5ZXIobGF5ZXIpO1xuICAgICAgY29udGludWU7XG4gICAgfSAvLyB0aGUgZWxlcyBpbiB0aGUgbGF5ZXIgbXVzdCBiZSBpbiB0aGUgc2FtZSBjb250aW51b3VzIG9yZGVyLCBlbHNlIHRoZSBsYXllciBpcyBpbnZhbGlkXG5cblxuICAgIHZhciBvID0gb2Zmc2V0O1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBsYXllci5lbGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICBpZiAobGF5ZXIuZWxlc1tqXSAhPT0gZWxlc1tvICsgal0pIHtcbiAgICAgICAgLy8gbG9nKCdpbnZhbGlkYXRlIGJhc2VkIG9uIG9yZGVyaW5nJywgbGF5ZXIuaWQpO1xuICAgICAgICB0aGlzLmludmFsaWRhdGVMYXllcihsYXllcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuTFRDcC51cGRhdGVFbGVtZW50c0luTGF5ZXJzID0gZnVuY3Rpb24gKGVsZXMsIHVwZGF0ZSkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBpc0VsZXMgPSBlbGVtZW50KGVsZXNbMF0pOyAvLyBjb2xsZWN0IHVkcGF0ZWQgZWxlbWVudHMgKGNhc2NhZGVkIGZyb20gdGhlIGxheWVycykgYW5kIHVwZGF0ZSBlYWNoXG4gIC8vIGxheWVyIGl0c2VsZiBhbG9uZyB0aGUgd2F5XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHJlcSA9IGlzRWxlcyA/IG51bGwgOiBlbGVzW2ldO1xuICAgIHZhciBlbGUgPSBpc0VsZXMgPyBlbGVzW2ldIDogZWxlc1tpXS5lbGU7XG4gICAgdmFyIHJzID0gZWxlLl9wcml2YXRlLnJzY3JhdGNoO1xuICAgIHZhciBjYWNoZXMgPSBycy5pbWdMYXllckNhY2hlcyA9IHJzLmltZ0xheWVyQ2FjaGVzIHx8IHt9O1xuXG4gICAgZm9yICh2YXIgbCA9IG1pbkx2bCQxOyBsIDw9IG1heEx2bCQxOyBsKyspIHtcbiAgICAgIHZhciBsYXllciA9IGNhY2hlc1tsXTtcblxuICAgICAgaWYgKCFsYXllcikge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH0gLy8gaWYgdXBkYXRlIGlzIGEgcmVxdWVzdCBmcm9tIHRoZSBlbGUgY2FjaGUsIHRoZW4gaXQgYWZmZWN0cyBvbmx5XG4gICAgICAvLyB0aGUgbWF0Y2hpbmcgbGV2ZWxcblxuXG4gICAgICBpZiAocmVxICYmIHNlbGYuZ2V0RWxlTGV2ZWxGb3JMYXllckxldmVsKGxheWVyLmxldmVsKSAhPT0gcmVxLmxldmVsKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB1cGRhdGUobGF5ZXIsIGVsZSwgcmVxKTtcbiAgICB9XG4gIH1cbn07XG5cbkxUQ3AuaGF2ZUxheWVycyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgaGF2ZUxheWVycyA9IGZhbHNlO1xuXG4gIGZvciAodmFyIGwgPSBtaW5MdmwkMTsgbCA8PSBtYXhMdmwkMTsgbCsrKSB7XG4gICAgdmFyIGxheWVycyA9IHNlbGYubGF5ZXJzQnlMZXZlbFtsXTtcblxuICAgIGlmIChsYXllcnMgJiYgbGF5ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGhhdmVMYXllcnMgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGhhdmVMYXllcnM7XG59O1xuXG5MVENwLmludmFsaWRhdGVFbGVtZW50cyA9IGZ1bmN0aW9uIChlbGVzKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICBpZiAoZWxlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBzZWxmLmxhc3RJbnZhbGlkYXRpb25UaW1lID0gcGVyZm9ybWFuY2VOb3coKTsgLy8gbG9nKCd1cGRhdGUgaW52YWxpZGF0ZSBsYXllciB0aW1lIGZyb20gZWxlcycpO1xuXG4gIGlmIChlbGVzLmxlbmd0aCA9PT0gMCB8fCAhc2VsZi5oYXZlTGF5ZXJzKCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBzZWxmLnVwZGF0ZUVsZW1lbnRzSW5MYXllcnMoZWxlcywgZnVuY3Rpb24gaW52YWxBc3NvY0xheWVycyhsYXllciwgZWxlLCByZXEpIHtcbiAgICBzZWxmLmludmFsaWRhdGVMYXllcihsYXllcik7XG4gIH0pO1xufTtcblxuTFRDcC5pbnZhbGlkYXRlTGF5ZXIgPSBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgLy8gbG9nKCd1cGRhdGUgaW52YWxpZGF0ZSBsYXllciB0aW1lJyk7XG4gIHRoaXMubGFzdEludmFsaWRhdGlvblRpbWUgPSBwZXJmb3JtYW5jZU5vdygpO1xuXG4gIGlmIChsYXllci5pbnZhbGlkKSB7XG4gICAgcmV0dXJuO1xuICB9IC8vIHNhdmUgY3ljbGVzXG5cblxuICB2YXIgbHZsID0gbGF5ZXIubGV2ZWw7XG4gIHZhciBlbGVzID0gbGF5ZXIuZWxlcztcbiAgdmFyIGxheWVycyA9IHRoaXMubGF5ZXJzQnlMZXZlbFtsdmxdOyAvLyBsb2coJ2ludmFsaWRhdGUgbGF5ZXInLCBsYXllci5pZCApO1xuXG4gIHJlbW92ZUZyb21BcnJheShsYXllcnMsIGxheWVyKTsgLy8gbGF5ZXIuZWxlcyA9IFtdO1xuXG4gIGxheWVyLmVsZXNRdWV1ZSA9IFtdO1xuICBsYXllci5pbnZhbGlkID0gdHJ1ZTtcblxuICBpZiAobGF5ZXIucmVwbGFjZW1lbnQpIHtcbiAgICBsYXllci5yZXBsYWNlbWVudC5pbnZhbGlkID0gdHJ1ZTtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBjYWNoZXMgPSBlbGVzW2ldLl9wcml2YXRlLnJzY3JhdGNoLmltZ0xheWVyQ2FjaGVzO1xuXG4gICAgaWYgKGNhY2hlcykge1xuICAgICAgY2FjaGVzW2x2bF0gPSBudWxsO1xuICAgIH1cbiAgfVxufTtcblxuTFRDcC5yZWZpbmVFbGVtZW50VGV4dHVyZXMgPSBmdW5jdGlvbiAoZWxlcykge1xuICB2YXIgc2VsZiA9IHRoaXM7IC8vIGxvZygncmVmaW5lJywgZWxlcy5sZW5ndGgpO1xuXG4gIHNlbGYudXBkYXRlRWxlbWVudHNJbkxheWVycyhlbGVzLCBmdW5jdGlvbiByZWZpbmVFYWNoRWxlKGxheWVyLCBlbGUsIHJlcSkge1xuICAgIHZhciByTHlyID0gbGF5ZXIucmVwbGFjZW1lbnQ7XG5cbiAgICBpZiAoIXJMeXIpIHtcbiAgICAgIHJMeXIgPSBsYXllci5yZXBsYWNlbWVudCA9IHNlbGYubWFrZUxheWVyKGxheWVyLmJiLCBsYXllci5sZXZlbCk7XG4gICAgICByTHlyLnJlcGxhY2VzID0gbGF5ZXI7XG4gICAgICByTHlyLmVsZXMgPSBsYXllci5lbGVzOyAvLyBsb2coJ21ha2UgcmVwbGFjZW1lbnQgbGF5ZXIgJXMgZm9yICVzIHdpdGggbGV2ZWwgJXMnLCByTHlyLmlkLCBsYXllci5pZCwgckx5ci5sZXZlbCk7XG4gICAgfVxuXG4gICAgaWYgKCFyTHlyLnJlcXMpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgckx5ci5lbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNlbGYucXVldWVMYXllcihyTHlyLCByTHlyLmVsZXNbaV0pO1xuICAgICAgfSAvLyBsb2coJ3F1ZXVlIHJlcGxhY2VtZW50IGxheWVyIHJlZmluZW1lbnQnLCByTHlyLmlkKTtcblxuICAgIH1cbiAgfSk7XG59O1xuXG5MVENwLmVucXVldWVFbGVtZW50UmVmaW5lbWVudCA9IGZ1bmN0aW9uIChlbGUpIHtcblxuICB0aGlzLmVsZVR4ckRlcXMubWVyZ2UoZWxlKTtcbiAgdGhpcy5zY2hlZHVsZUVsZW1lbnRSZWZpbmVtZW50KCk7XG59O1xuXG5MVENwLnF1ZXVlTGF5ZXIgPSBmdW5jdGlvbiAobGF5ZXIsIGVsZSkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBxID0gc2VsZi5sYXllcnNRdWV1ZTtcbiAgdmFyIGVsZXNRID0gbGF5ZXIuZWxlc1F1ZXVlO1xuICB2YXIgaGFzSWQgPSBlbGVzUS5oYXNJZCA9IGVsZXNRLmhhc0lkIHx8IHt9OyAvLyBpZiBhIGxheWVyIGlzIGdvaW5nIHRvIGJlIHJlcGxhY2VkLCBxdWV1aW5nIGlzIGEgd2FzdGUgb2YgdGltZVxuXG4gIGlmIChsYXllci5yZXBsYWNlbWVudCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChlbGUpIHtcbiAgICBpZiAoaGFzSWRbZWxlLmlkKCldKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZWxlc1EucHVzaChlbGUpO1xuICAgIGhhc0lkW2VsZS5pZCgpXSA9IHRydWU7XG4gIH1cblxuICBpZiAobGF5ZXIucmVxcykge1xuICAgIGxheWVyLnJlcXMrKztcbiAgICBxLnVwZGF0ZUl0ZW0obGF5ZXIpO1xuICB9IGVsc2Uge1xuICAgIGxheWVyLnJlcXMgPSAxO1xuICAgIHEucHVzaChsYXllcik7XG4gIH1cbn07XG5cbkxUQ3AuZGVxdWV1ZSA9IGZ1bmN0aW9uIChweFJhdGlvKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHEgPSBzZWxmLmxheWVyc1F1ZXVlO1xuICB2YXIgZGVxZCA9IFtdO1xuICB2YXIgZWxlRGVxcyA9IDA7XG5cbiAgd2hpbGUgKGVsZURlcXMgPCBtYXhEZXFTaXplJDEpIHtcbiAgICBpZiAocS5zaXplKCkgPT09IDApIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHZhciBsYXllciA9IHEucGVlaygpOyAvLyBpZiBhIGxheWVyIGhhcyBiZWVuIG9yIHdpbGwgYmUgcmVwbGFjZWQsIHRoZW4gZG9uJ3Qgd2FzdGUgdGltZSB3aXRoIGl0XG5cbiAgICBpZiAobGF5ZXIucmVwbGFjZW1lbnQpIHtcbiAgICAgIC8vIGxvZygnbGF5ZXIgJXMgaW4gcXVldWUgc2tpcHBlZCBiL2MgaXQgYWxyZWFkeSBoYXMgYSByZXBsYWNlbWVudCcsIGxheWVyLmlkKTtcbiAgICAgIHEucG9wKCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9IC8vIGlmIHRoaXMgaXMgYSByZXBsYWNlbWVudCBsYXllciB0aGF0IGhhcyBiZWVuIHN1cGVyY2VkZWQsIHRoZW4gZm9yZ2V0IGl0XG5cblxuICAgIGlmIChsYXllci5yZXBsYWNlcyAmJiBsYXllciAhPT0gbGF5ZXIucmVwbGFjZXMucmVwbGFjZW1lbnQpIHtcbiAgICAgIC8vIGxvZygnbGF5ZXIgaXMgbm8gbG9uZ2VyIHRoZSBtb3N0IHVwdG9kYXRlIHJlcGxhY2VtZW50OyBkZXF1ZXVlZCcsIGxheWVyLmlkKVxuICAgICAgcS5wb3AoKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChsYXllci5pbnZhbGlkKSB7XG4gICAgICAvLyBsb2coJ3JlcGxhY2VtZW50IGxheWVyICVzIGlzIGludmFsaWQ7IGRlcXVldWVkJywgbGF5ZXIuaWQpO1xuICAgICAgcS5wb3AoKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBlbGUgPSBsYXllci5lbGVzUXVldWUuc2hpZnQoKTtcblxuICAgIGlmIChlbGUpIHtcbiAgICAgIC8vIGxvZygnZGVxdWV1ZSBsYXllciAlcycsIGxheWVyLmlkKTtcbiAgICAgIHNlbGYuZHJhd0VsZUluTGF5ZXIobGF5ZXIsIGVsZSwgbGF5ZXIubGV2ZWwsIHB4UmF0aW8pO1xuICAgICAgZWxlRGVxcysrO1xuICAgIH1cblxuICAgIGlmIChkZXFkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgLy8gd2UgbmVlZCBvbmx5IG9uZSBlbnRyeSBpbiBkZXFkIHRvIHF1ZXVlIHJlZHJhd2luZyBldGNcbiAgICAgIGRlcWQucHVzaCh0cnVlKTtcbiAgICB9IC8vIGlmIHRoZSBsYXllciBoYXMgYWxsIGl0cyBlbGVzIGRvbmUsIHRoZW4gcmVtb3ZlIGZyb20gdGhlIHF1ZXVlXG5cblxuICAgIGlmIChsYXllci5lbGVzUXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICBxLnBvcCgpO1xuICAgICAgbGF5ZXIucmVxcyA9IDA7IC8vIGxvZygnZGVxdWV1ZSBvZiBsYXllciAlcyBjb21wbGV0ZScsIGxheWVyLmlkKTtcbiAgICAgIC8vIHdoZW4gYSByZXBsYWNlbWVudCBsYXllciBpcyBkZXF1ZXVlZCwgaXQgcmVwbGFjZXMgdGhlIG9sZCBsYXllciBpbiB0aGUgbGV2ZWxcblxuICAgICAgaWYgKGxheWVyLnJlcGxhY2VzKSB7XG4gICAgICAgIHNlbGYuYXBwbHlMYXllclJlcGxhY2VtZW50KGxheWVyKTtcbiAgICAgIH1cblxuICAgICAgc2VsZi5yZXF1ZXN0UmVkcmF3KCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRlcWQ7XG59O1xuXG5MVENwLmFwcGx5TGF5ZXJSZXBsYWNlbWVudCA9IGZ1bmN0aW9uIChsYXllcikge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBsYXllcnNJbkxldmVsID0gc2VsZi5sYXllcnNCeUxldmVsW2xheWVyLmxldmVsXTtcbiAgdmFyIHJlcGxhY2VkID0gbGF5ZXIucmVwbGFjZXM7XG4gIHZhciBpbmRleCA9IGxheWVyc0luTGV2ZWwuaW5kZXhPZihyZXBsYWNlZCk7IC8vIGlmIHRoZSByZXBsYWNlZCBsYXllciBpcyBub3QgaW4gdGhlIGFjdGl2ZSBsaXN0IGZvciB0aGUgbGV2ZWwsIHRoZW4gcmVwbGFjaW5nXG4gIC8vIHJlZnMgd291bGQgYmUgYSBtaXN0YWtlIChpLmUuIG92ZXJ3cml0aW5nIHRoZSB0cnVlIGFjdGl2ZSBsYXllcilcblxuICBpZiAoaW5kZXggPCAwIHx8IHJlcGxhY2VkLmludmFsaWQpIHtcbiAgICAvLyBsb2coJ3JlcGxhY2VtZW50IGxheWVyIHdvdWxkIGhhdmUgbm8gZWZmZWN0JywgbGF5ZXIuaWQpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxheWVyc0luTGV2ZWxbaW5kZXhdID0gbGF5ZXI7IC8vIHJlcGxhY2UgbGV2ZWwgcmVmXG4gIC8vIHJlcGxhY2UgcmVmcyBpbiBlbGVzXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXllci5lbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIF9wID0gbGF5ZXIuZWxlc1tpXS5fcHJpdmF0ZTtcbiAgICB2YXIgY2FjaGUgPSBfcC5pbWdMYXllckNhY2hlcyA9IF9wLmltZ0xheWVyQ2FjaGVzIHx8IHt9O1xuXG4gICAgaWYgKGNhY2hlKSB7XG4gICAgICBjYWNoZVtsYXllci5sZXZlbF0gPSBsYXllcjtcbiAgICB9XG4gIH0gLy8gbG9nKCdhcHBseSByZXBsYWNlbWVudCBsYXllciAlcyBvdmVyICVzJywgbGF5ZXIuaWQsIHJlcGxhY2VkLmlkKTtcblxuXG4gIHNlbGYucmVxdWVzdFJlZHJhdygpO1xufTtcblxuTFRDcC5yZXF1ZXN0UmVkcmF3ID0gdXRpbChmdW5jdGlvbiAoKSB7XG4gIHZhciByID0gdGhpcy5yZW5kZXJlcjtcbiAgci5yZWRyYXdIaW50KCdlbGVzJywgdHJ1ZSk7XG4gIHIucmVkcmF3SGludCgnZHJhZycsIHRydWUpO1xuICByLnJlZHJhdygpO1xufSwgMTAwKTtcbkxUQ3Auc2V0dXBEZXF1ZXVlaW5nID0gZGVmcy5zZXR1cERlcXVldWVpbmcoe1xuICBkZXFSZWRyYXdUaHJlc2hvbGQ6IGRlcVJlZHJhd1RocmVzaG9sZCQxLFxuICBkZXFDb3N0OiBkZXFDb3N0JDEsXG4gIGRlcUF2Z0Nvc3Q6IGRlcUF2Z0Nvc3QkMSxcbiAgZGVxTm9EcmF3Q29zdDogZGVxTm9EcmF3Q29zdCQxLFxuICBkZXFGYXN0Q29zdDogZGVxRmFzdENvc3QkMSxcbiAgZGVxOiBmdW5jdGlvbiBkZXEoc2VsZiwgcHhSYXRpbykge1xuICAgIHJldHVybiBzZWxmLmRlcXVldWUocHhSYXRpbyk7XG4gIH0sXG4gIG9uRGVxZDogbm9vcCxcbiAgc2hvdWxkUmVkcmF3OiB0cnVlaWZ5LFxuICBwcmlvcml0eTogZnVuY3Rpb24gcHJpb3JpdHkoc2VsZikge1xuICAgIHJldHVybiBzZWxmLnJlbmRlcmVyLmJlZm9yZVJlbmRlclByaW9yaXRpZXMubHlyVHhyRGVxO1xuICB9XG59KTtcblxudmFyIENScCA9IHt9O1xudmFyIGltcGw7XG5cbmZ1bmN0aW9uIHBvbHlnb24oY29udGV4dCwgcG9pbnRzKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHB0ID0gcG9pbnRzW2ldO1xuICAgIGNvbnRleHQubGluZVRvKHB0LngsIHB0LnkpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRyaWFuZ2xlQmFja2N1cnZlKGNvbnRleHQsIHBvaW50cywgY29udHJvbFBvaW50KSB7XG4gIHZhciBmaXJzdFB0O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHB0ID0gcG9pbnRzW2ldO1xuXG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIGZpcnN0UHQgPSBwdDtcbiAgICB9XG5cbiAgICBjb250ZXh0LmxpbmVUbyhwdC54LCBwdC55KTtcbiAgfVxuXG4gIGNvbnRleHQucXVhZHJhdGljQ3VydmVUbyhjb250cm9sUG9pbnQueCwgY29udHJvbFBvaW50LnksIGZpcnN0UHQueCwgZmlyc3RQdC55KTtcbn1cblxuZnVuY3Rpb24gdHJpYW5nbGVUZWUoY29udGV4dCwgdHJpYW5nbGVQb2ludHMsIHRlZVBvaW50cykge1xuICBpZiAoY29udGV4dC5iZWdpblBhdGgpIHtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICB9XG5cbiAgdmFyIHRyaVB0cyA9IHRyaWFuZ2xlUG9pbnRzO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHJpUHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHB0ID0gdHJpUHRzW2ldO1xuICAgIGNvbnRleHQubGluZVRvKHB0LngsIHB0LnkpO1xuICB9XG5cbiAgdmFyIHRlZVB0cyA9IHRlZVBvaW50cztcbiAgdmFyIGZpcnN0VGVlUHQgPSB0ZWVQb2ludHNbMF07XG4gIGNvbnRleHQubW92ZVRvKGZpcnN0VGVlUHQueCwgZmlyc3RUZWVQdC55KTtcblxuICBmb3IgKHZhciBpID0gMTsgaSA8IHRlZVB0cy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwdCA9IHRlZVB0c1tpXTtcbiAgICBjb250ZXh0LmxpbmVUbyhwdC54LCBwdC55KTtcbiAgfVxuXG4gIGlmIChjb250ZXh0LmNsb3NlUGF0aCkge1xuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2lyY2xlVHJpYW5nbGUoY29udGV4dCwgdHJpYW5nbGVQb2ludHMsIHJ4LCByeSwgcikge1xuICBpZiAoY29udGV4dC5iZWdpblBhdGgpIHtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICB9XG5cbiAgY29udGV4dC5hcmMocngsIHJ5LCByLCAwLCBNYXRoLlBJICogMiwgZmFsc2UpO1xuICB2YXIgdHJpUHRzID0gdHJpYW5nbGVQb2ludHM7XG4gIHZhciBmaXJzdFRyUHQgPSB0cmlQdHNbMF07XG4gIGNvbnRleHQubW92ZVRvKGZpcnN0VHJQdC54LCBmaXJzdFRyUHQueSk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmlQdHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcHQgPSB0cmlQdHNbaV07XG4gICAgY29udGV4dC5saW5lVG8ocHQueCwgcHQueSk7XG4gIH1cblxuICBpZiAoY29udGV4dC5jbG9zZVBhdGgpIHtcbiAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNpcmNsZShjb250ZXh0LCByeCwgcnksIHIpIHtcbiAgY29udGV4dC5hcmMocngsIHJ5LCByLCAwLCBNYXRoLlBJICogMiwgZmFsc2UpO1xufVxuXG5DUnAuYXJyb3dTaGFwZUltcGwgPSBmdW5jdGlvbiAobmFtZSkge1xuICByZXR1cm4gKGltcGwgfHwgKGltcGwgPSB7XG4gICAgJ3BvbHlnb24nOiBwb2x5Z29uLFxuICAgICd0cmlhbmdsZS1iYWNrY3VydmUnOiB0cmlhbmdsZUJhY2tjdXJ2ZSxcbiAgICAndHJpYW5nbGUtdGVlJzogdHJpYW5nbGVUZWUsXG4gICAgJ2NpcmNsZS10cmlhbmdsZSc6IGNpcmNsZVRyaWFuZ2xlLFxuICAgICd0cmlhbmdsZS1jcm9zcyc6IHRyaWFuZ2xlVGVlLFxuICAgICdjaXJjbGUnOiBjaXJjbGVcbiAgfSkpW25hbWVdO1xufTtcblxudmFyIENScCQxID0ge307XG5cbkNScCQxLmRyYXdFbGVtZW50ID0gZnVuY3Rpb24gKGNvbnRleHQsIGVsZSwgc2hpZnRUb09yaWdpbldpdGhCYiwgc2hvd0xhYmVsLCBzaG93T3ZlcmxheSwgc2hvd09wYWNpdHkpIHtcbiAgdmFyIHIgPSB0aGlzO1xuXG4gIGlmIChlbGUuaXNOb2RlKCkpIHtcbiAgICByLmRyYXdOb2RlKGNvbnRleHQsIGVsZSwgc2hpZnRUb09yaWdpbldpdGhCYiwgc2hvd0xhYmVsLCBzaG93T3ZlcmxheSwgc2hvd09wYWNpdHkpO1xuICB9IGVsc2Uge1xuICAgIHIuZHJhd0VkZ2UoY29udGV4dCwgZWxlLCBzaGlmdFRvT3JpZ2luV2l0aEJiLCBzaG93TGFiZWwsIHNob3dPdmVybGF5LCBzaG93T3BhY2l0eSk7XG4gIH1cbn07XG5cbkNScCQxLmRyYXdFbGVtZW50T3ZlcmxheSA9IGZ1bmN0aW9uIChjb250ZXh0LCBlbGUpIHtcbiAgdmFyIHIgPSB0aGlzO1xuXG4gIGlmIChlbGUuaXNOb2RlKCkpIHtcbiAgICByLmRyYXdOb2RlT3ZlcmxheShjb250ZXh0LCBlbGUpO1xuICB9IGVsc2Uge1xuICAgIHIuZHJhd0VkZ2VPdmVybGF5KGNvbnRleHQsIGVsZSk7XG4gIH1cbn07XG5cbkNScCQxLmRyYXdDYWNoZWRFbGVtZW50UG9ydGlvbiA9IGZ1bmN0aW9uIChjb250ZXh0LCBlbGUsIGVsZVR4ckNhY2hlLCBweFJhdGlvLCBsdmwsIHJlYXNvbiwgZ2V0Um90YXRpb24sIGdldE9wYWNpdHkpIHtcbiAgdmFyIHIgPSB0aGlzO1xuICB2YXIgYmIgPSBlbGVUeHJDYWNoZS5nZXRCb3VuZGluZ0JveChlbGUpO1xuXG4gIGlmIChiYi53ID09PSAwIHx8IGJiLmggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH0gLy8gaWdub3JlIHplcm8gc2l6ZSBjYXNlXG5cblxuICB2YXIgZWxlQ2FjaGUgPSBlbGVUeHJDYWNoZS5nZXRFbGVtZW50KGVsZSwgYmIsIHB4UmF0aW8sIGx2bCwgcmVhc29uKTtcblxuICBpZiAoZWxlQ2FjaGUgIT0gbnVsbCkge1xuICAgIHZhciBvcGFjaXR5ID0gZ2V0T3BhY2l0eShyLCBlbGUpO1xuXG4gICAgaWYgKG9wYWNpdHkgPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgdGhldGEgPSBnZXRSb3RhdGlvbihyLCBlbGUpO1xuICAgIHZhciB4MSA9IGJiLngxLFxuICAgICAgICB5MSA9IGJiLnkxLFxuICAgICAgICB3ID0gYmIudyxcbiAgICAgICAgaCA9IGJiLmg7XG4gICAgdmFyIHgsIHksIHN4LCBzeSwgc21vb3RoO1xuXG4gICAgaWYgKHRoZXRhICE9PSAwKSB7XG4gICAgICB2YXIgcm90UHQgPSBlbGVUeHJDYWNoZS5nZXRSb3RhdGlvblBvaW50KGVsZSk7XG4gICAgICBzeCA9IHJvdFB0Lng7XG4gICAgICBzeSA9IHJvdFB0Lnk7XG4gICAgICBjb250ZXh0LnRyYW5zbGF0ZShzeCwgc3kpO1xuICAgICAgY29udGV4dC5yb3RhdGUodGhldGEpO1xuICAgICAgc21vb3RoID0gci5nZXRJbWdTbW9vdGhpbmcoY29udGV4dCk7XG5cbiAgICAgIGlmICghc21vb3RoKSB7XG4gICAgICAgIHIuc2V0SW1nU21vb3RoaW5nKGNvbnRleHQsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICB2YXIgb2ZmID0gZWxlVHhyQ2FjaGUuZ2V0Um90YXRpb25PZmZzZXQoZWxlKTtcbiAgICAgIHggPSBvZmYueDtcbiAgICAgIHkgPSBvZmYueTtcbiAgICB9IGVsc2Uge1xuICAgICAgeCA9IHgxO1xuICAgICAgeSA9IHkxO1xuICAgIH1cblxuICAgIHZhciBvbGRHbG9iYWxBbHBoYTtcblxuICAgIGlmIChvcGFjaXR5ICE9PSAxKSB7XG4gICAgICBvbGRHbG9iYWxBbHBoYSA9IGNvbnRleHQuZ2xvYmFsQWxwaGE7XG4gICAgICBjb250ZXh0Lmdsb2JhbEFscGhhID0gb2xkR2xvYmFsQWxwaGEgKiBvcGFjaXR5O1xuICAgIH1cblxuICAgIGNvbnRleHQuZHJhd0ltYWdlKGVsZUNhY2hlLnRleHR1cmUuY2FudmFzLCBlbGVDYWNoZS54LCAwLCBlbGVDYWNoZS53aWR0aCwgZWxlQ2FjaGUuaGVpZ2h0LCB4LCB5LCB3LCBoKTtcblxuICAgIGlmIChvcGFjaXR5ICE9PSAxKSB7XG4gICAgICBjb250ZXh0Lmdsb2JhbEFscGhhID0gb2xkR2xvYmFsQWxwaGE7XG4gICAgfVxuXG4gICAgaWYgKHRoZXRhICE9PSAwKSB7XG4gICAgICBjb250ZXh0LnJvdGF0ZSgtdGhldGEpO1xuICAgICAgY29udGV4dC50cmFuc2xhdGUoLXN4LCAtc3kpO1xuXG4gICAgICBpZiAoIXNtb290aCkge1xuICAgICAgICByLnNldEltZ1Ntb290aGluZyhjb250ZXh0LCBmYWxzZSk7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGVsZVR4ckNhY2hlLmRyYXdFbGVtZW50KGNvbnRleHQsIGVsZSk7IC8vIGRpcmVjdCBkcmF3IGZhbGxiYWNrXG4gIH1cbn07XG5cbnZhciBnZXRaZXJvUm90YXRpb24gPSBmdW5jdGlvbiBnZXRaZXJvUm90YXRpb24oKSB7XG4gIHJldHVybiAwO1xufTtcblxudmFyIGdldExhYmVsUm90YXRpb24gPSBmdW5jdGlvbiBnZXRMYWJlbFJvdGF0aW9uKHIsIGVsZSkge1xuICByZXR1cm4gci5nZXRUZXh0QW5nbGUoZWxlLCBudWxsKTtcbn07XG5cbnZhciBnZXRTb3VyY2VMYWJlbFJvdGF0aW9uID0gZnVuY3Rpb24gZ2V0U291cmNlTGFiZWxSb3RhdGlvbihyLCBlbGUpIHtcbiAgcmV0dXJuIHIuZ2V0VGV4dEFuZ2xlKGVsZSwgJ3NvdXJjZScpO1xufTtcblxudmFyIGdldFRhcmdldExhYmVsUm90YXRpb24gPSBmdW5jdGlvbiBnZXRUYXJnZXRMYWJlbFJvdGF0aW9uKHIsIGVsZSkge1xuICByZXR1cm4gci5nZXRUZXh0QW5nbGUoZWxlLCAndGFyZ2V0Jyk7XG59O1xuXG52YXIgZ2V0T3BhY2l0eSA9IGZ1bmN0aW9uIGdldE9wYWNpdHkociwgZWxlKSB7XG4gIHJldHVybiBlbGUuZWZmZWN0aXZlT3BhY2l0eSgpO1xufTtcblxudmFyIGdldFRleHRPcGFjaXR5ID0gZnVuY3Rpb24gZ2V0VGV4dE9wYWNpdHkoZSwgZWxlKSB7XG4gIHJldHVybiBlbGUucHN0eWxlKCd0ZXh0LW9wYWNpdHknKS5wZlZhbHVlICogZWxlLmVmZmVjdGl2ZU9wYWNpdHkoKTtcbn07XG5cbkNScCQxLmRyYXdDYWNoZWRFbGVtZW50ID0gZnVuY3Rpb24gKGNvbnRleHQsIGVsZSwgcHhSYXRpbywgZXh0ZW50LCBsdmwsIHJlcXVlc3RIaWdoUXVhbGl0eSkge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBfciRkYXRhID0gci5kYXRhLFxuICAgICAgZWxlVHhyQ2FjaGUgPSBfciRkYXRhLmVsZVR4ckNhY2hlLFxuICAgICAgbGJsVHhyQ2FjaGUgPSBfciRkYXRhLmxibFR4ckNhY2hlLFxuICAgICAgc2xiVHhyQ2FjaGUgPSBfciRkYXRhLnNsYlR4ckNhY2hlLFxuICAgICAgdGxiVHhyQ2FjaGUgPSBfciRkYXRhLnRsYlR4ckNhY2hlO1xuICB2YXIgYmIgPSBlbGUuYm91bmRpbmdCb3goKTtcbiAgdmFyIHJlYXNvbiA9IHJlcXVlc3RIaWdoUXVhbGl0eSA9PT0gdHJ1ZSA/IGVsZVR4ckNhY2hlLnJlYXNvbnMuaGlnaFF1YWxpdHkgOiBudWxsO1xuXG4gIGlmIChiYi53ID09PSAwIHx8IGJiLmggPT09IDAgfHwgIWVsZS52aXNpYmxlKCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIWV4dGVudCB8fCBib3VuZGluZ0JveGVzSW50ZXJzZWN0KGJiLCBleHRlbnQpKSB7XG4gICAgdmFyIGlzRWRnZSA9IGVsZS5pc0VkZ2UoKTtcblxuICAgIHZhciBiYWRMaW5lID0gZWxlLmVsZW1lbnQoKS5fcHJpdmF0ZS5yc2NyYXRjaC5iYWRMaW5lO1xuXG4gICAgci5kcmF3Q2FjaGVkRWxlbWVudFBvcnRpb24oY29udGV4dCwgZWxlLCBlbGVUeHJDYWNoZSwgcHhSYXRpbywgbHZsLCByZWFzb24sIGdldFplcm9Sb3RhdGlvbiwgZ2V0T3BhY2l0eSk7XG5cbiAgICBpZiAoIWlzRWRnZSB8fCAhYmFkTGluZSkge1xuICAgICAgci5kcmF3Q2FjaGVkRWxlbWVudFBvcnRpb24oY29udGV4dCwgZWxlLCBsYmxUeHJDYWNoZSwgcHhSYXRpbywgbHZsLCByZWFzb24sIGdldExhYmVsUm90YXRpb24sIGdldFRleHRPcGFjaXR5KTtcbiAgICB9XG5cbiAgICBpZiAoaXNFZGdlICYmICFiYWRMaW5lKSB7XG4gICAgICByLmRyYXdDYWNoZWRFbGVtZW50UG9ydGlvbihjb250ZXh0LCBlbGUsIHNsYlR4ckNhY2hlLCBweFJhdGlvLCBsdmwsIHJlYXNvbiwgZ2V0U291cmNlTGFiZWxSb3RhdGlvbiwgZ2V0VGV4dE9wYWNpdHkpO1xuICAgICAgci5kcmF3Q2FjaGVkRWxlbWVudFBvcnRpb24oY29udGV4dCwgZWxlLCB0bGJUeHJDYWNoZSwgcHhSYXRpbywgbHZsLCByZWFzb24sIGdldFRhcmdldExhYmVsUm90YXRpb24sIGdldFRleHRPcGFjaXR5KTtcbiAgICB9XG5cbiAgICByLmRyYXdFbGVtZW50T3ZlcmxheShjb250ZXh0LCBlbGUpO1xuICB9XG59O1xuXG5DUnAkMS5kcmF3RWxlbWVudHMgPSBmdW5jdGlvbiAoY29udGV4dCwgZWxlcykge1xuICB2YXIgciA9IHRoaXM7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IGVsZXNbaV07XG4gICAgci5kcmF3RWxlbWVudChjb250ZXh0LCBlbGUpO1xuICB9XG59O1xuXG5DUnAkMS5kcmF3Q2FjaGVkRWxlbWVudHMgPSBmdW5jdGlvbiAoY29udGV4dCwgZWxlcywgcHhSYXRpbywgZXh0ZW50KSB7XG4gIHZhciByID0gdGhpcztcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZWxlID0gZWxlc1tpXTtcbiAgICByLmRyYXdDYWNoZWRFbGVtZW50KGNvbnRleHQsIGVsZSwgcHhSYXRpbywgZXh0ZW50KTtcbiAgfVxufTtcblxuQ1JwJDEuZHJhd0NhY2hlZE5vZGVzID0gZnVuY3Rpb24gKGNvbnRleHQsIGVsZXMsIHB4UmF0aW8sIGV4dGVudCkge1xuICB2YXIgciA9IHRoaXM7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVsZSA9IGVsZXNbaV07XG5cbiAgICBpZiAoIWVsZS5pc05vZGUoKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgci5kcmF3Q2FjaGVkRWxlbWVudChjb250ZXh0LCBlbGUsIHB4UmF0aW8sIGV4dGVudCk7XG4gIH1cbn07XG5cbkNScCQxLmRyYXdMYXllcmVkRWxlbWVudHMgPSBmdW5jdGlvbiAoY29udGV4dCwgZWxlcywgcHhSYXRpbywgZXh0ZW50KSB7XG4gIHZhciByID0gdGhpcztcbiAgdmFyIGxheWVycyA9IHIuZGF0YS5seXJUeHJDYWNoZS5nZXRMYXllcnMoZWxlcywgcHhSYXRpbyk7XG5cbiAgaWYgKGxheWVycykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbGF5ZXIgPSBsYXllcnNbaV07XG4gICAgICB2YXIgYmIgPSBsYXllci5iYjtcblxuICAgICAgaWYgKGJiLncgPT09IDAgfHwgYmIuaCA9PT0gMCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29udGV4dC5kcmF3SW1hZ2UobGF5ZXIuY2FudmFzLCBiYi54MSwgYmIueTEsIGJiLncsIGJiLmgpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBmYWxsIGJhY2sgb24gcGxhaW4gY2FjaGluZyBpZiBubyBsYXllcnNcbiAgICByLmRyYXdDYWNoZWRFbGVtZW50cyhjb250ZXh0LCBlbGVzLCBweFJhdGlvLCBleHRlbnQpO1xuICB9XG59O1xuXG4vKiBnbG9iYWwgUGF0aDJEICovXG52YXIgQ1JwJDIgPSB7fTtcblxuQ1JwJDIuZHJhd0VkZ2UgPSBmdW5jdGlvbiAoY29udGV4dCwgZWRnZSwgc2hpZnRUb09yaWdpbldpdGhCYikge1xuICB2YXIgZHJhd0xhYmVsID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiB0cnVlO1xuICB2YXIgc2hvdWxkRHJhd092ZXJsYXkgPSBhcmd1bWVudHMubGVuZ3RoID4gNCAmJiBhcmd1bWVudHNbNF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s0XSA6IHRydWU7XG4gIHZhciBzaG91bGREcmF3T3BhY2l0eSA9IGFyZ3VtZW50cy5sZW5ndGggPiA1ICYmIGFyZ3VtZW50c1s1XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzVdIDogdHJ1ZTtcbiAgdmFyIHIgPSB0aGlzO1xuICB2YXIgcnMgPSBlZGdlLl9wcml2YXRlLnJzY3JhdGNoO1xuXG4gIGlmIChzaG91bGREcmF3T3BhY2l0eSAmJiAhZWRnZS52aXNpYmxlKCkpIHtcbiAgICByZXR1cm47XG4gIH0gLy8gaWYgYmV6aWVyIGN0cmwgcHRzIGNhbiBub3QgYmUgY2FsY3VsYXRlZCwgdGhlbiBkaWVcblxuXG4gIGlmIChycy5iYWRMaW5lIHx8IHJzLmFsbHB0cyA9PSBudWxsIHx8IGlzTmFOKHJzLmFsbHB0c1swXSkpIHtcbiAgICAvLyBpc05hTiBpbiBjYXNlIGVkZ2UgaXMgaW1wb3NzaWJsZSBhbmQgYnJvd3NlciBidWdzIChlLmcuIHNhZmFyaSlcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgYmI7XG5cbiAgaWYgKHNoaWZ0VG9PcmlnaW5XaXRoQmIpIHtcbiAgICBiYiA9IHNoaWZ0VG9PcmlnaW5XaXRoQmI7XG4gICAgY29udGV4dC50cmFuc2xhdGUoLWJiLngxLCAtYmIueTEpO1xuICB9XG5cbiAgdmFyIG9wYWNpdHkgPSBzaG91bGREcmF3T3BhY2l0eSA/IGVkZ2UucHN0eWxlKCdvcGFjaXR5JykudmFsdWUgOiAxO1xuICB2YXIgbGluZVN0eWxlID0gZWRnZS5wc3R5bGUoJ2xpbmUtc3R5bGUnKS52YWx1ZTtcbiAgdmFyIGVkZ2VXaWR0aCA9IGVkZ2UucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWU7XG4gIHZhciBsaW5lQ2FwID0gZWRnZS5wc3R5bGUoJ2xpbmUtY2FwJykudmFsdWU7XG5cbiAgdmFyIGRyYXdMaW5lID0gZnVuY3Rpb24gZHJhd0xpbmUoKSB7XG4gICAgdmFyIHN0cm9rZU9wYWNpdHkgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IG9wYWNpdHk7XG4gICAgY29udGV4dC5saW5lV2lkdGggPSBlZGdlV2lkdGg7XG4gICAgY29udGV4dC5saW5lQ2FwID0gbGluZUNhcDtcbiAgICByLmVsZVN0cm9rZVN0eWxlKGNvbnRleHQsIGVkZ2UsIHN0cm9rZU9wYWNpdHkpO1xuICAgIHIuZHJhd0VkZ2VQYXRoKGVkZ2UsIGNvbnRleHQsIHJzLmFsbHB0cywgbGluZVN0eWxlKTtcbiAgICBjb250ZXh0LmxpbmVDYXAgPSAnYnV0dCc7IC8vIHJlc2V0IGZvciBvdGhlciBkcmF3aW5nIGZ1bmN0aW9uc1xuICB9O1xuXG4gIHZhciBkcmF3T3ZlcmxheSA9IGZ1bmN0aW9uIGRyYXdPdmVybGF5KCkge1xuICAgIGlmICghc2hvdWxkRHJhd092ZXJsYXkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICByLmRyYXdFZGdlT3ZlcmxheShjb250ZXh0LCBlZGdlKTtcbiAgfTtcblxuICB2YXIgZHJhd0Fycm93cyA9IGZ1bmN0aW9uIGRyYXdBcnJvd3MoKSB7XG4gICAgdmFyIGFycm93T3BhY2l0eSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogb3BhY2l0eTtcbiAgICByLmRyYXdBcnJvd2hlYWRzKGNvbnRleHQsIGVkZ2UsIGFycm93T3BhY2l0eSk7XG4gIH07XG5cbiAgdmFyIGRyYXdUZXh0ID0gZnVuY3Rpb24gZHJhd1RleHQoKSB7XG4gICAgci5kcmF3RWxlbWVudFRleHQoY29udGV4dCwgZWRnZSwgbnVsbCwgZHJhd0xhYmVsKTtcbiAgfTtcblxuICBjb250ZXh0LmxpbmVKb2luID0gJ3JvdW5kJztcbiAgdmFyIGdob3N0ID0gZWRnZS5wc3R5bGUoJ2dob3N0JykudmFsdWUgPT09ICd5ZXMnO1xuXG4gIGlmIChnaG9zdCkge1xuICAgIHZhciBneCA9IGVkZ2UucHN0eWxlKCdnaG9zdC1vZmZzZXQteCcpLnBmVmFsdWU7XG4gICAgdmFyIGd5ID0gZWRnZS5wc3R5bGUoJ2dob3N0LW9mZnNldC15JykucGZWYWx1ZTtcbiAgICB2YXIgZ2hvc3RPcGFjaXR5ID0gZWRnZS5wc3R5bGUoJ2dob3N0LW9wYWNpdHknKS52YWx1ZTtcbiAgICB2YXIgZWZmZWN0aXZlR2hvc3RPcGFjaXR5ID0gb3BhY2l0eSAqIGdob3N0T3BhY2l0eTtcbiAgICBjb250ZXh0LnRyYW5zbGF0ZShneCwgZ3kpO1xuICAgIGRyYXdMaW5lKGVmZmVjdGl2ZUdob3N0T3BhY2l0eSk7XG4gICAgZHJhd0Fycm93cyhlZmZlY3RpdmVHaG9zdE9wYWNpdHkpO1xuICAgIGNvbnRleHQudHJhbnNsYXRlKC1neCwgLWd5KTtcbiAgfVxuXG4gIGRyYXdMaW5lKCk7XG4gIGRyYXdBcnJvd3MoKTtcbiAgZHJhd092ZXJsYXkoKTtcbiAgZHJhd1RleHQoKTtcblxuICBpZiAoc2hpZnRUb09yaWdpbldpdGhCYikge1xuICAgIGNvbnRleHQudHJhbnNsYXRlKGJiLngxLCBiYi55MSk7XG4gIH1cbn07XG5cbkNScCQyLmRyYXdFZGdlT3ZlcmxheSA9IGZ1bmN0aW9uIChjb250ZXh0LCBlZGdlKSB7XG4gIGlmICghZWRnZS52aXNpYmxlKCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgb3ZlcmxheU9wYWNpdHkgPSBlZGdlLnBzdHlsZSgnb3ZlcmxheS1vcGFjaXR5JykudmFsdWU7XG5cbiAgaWYgKG92ZXJsYXlPcGFjaXR5ID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHIgPSB0aGlzO1xuICB2YXIgdXNlUGF0aHMgPSByLnVzZVBhdGhzKCk7XG4gIHZhciBycyA9IGVkZ2UuX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHZhciBvdmVybGF5UGFkZGluZyA9IGVkZ2UucHN0eWxlKCdvdmVybGF5LXBhZGRpbmcnKS5wZlZhbHVlO1xuICB2YXIgb3ZlcmxheVdpZHRoID0gMiAqIG92ZXJsYXlQYWRkaW5nO1xuICB2YXIgb3ZlcmxheUNvbG9yID0gZWRnZS5wc3R5bGUoJ292ZXJsYXktY29sb3InKS52YWx1ZTtcbiAgY29udGV4dC5saW5lV2lkdGggPSBvdmVybGF5V2lkdGg7XG5cbiAgaWYgKHJzLmVkZ2VUeXBlID09PSAnc2VsZicgJiYgIXVzZVBhdGhzKSB7XG4gICAgY29udGV4dC5saW5lQ2FwID0gJ2J1dHQnO1xuICB9IGVsc2Uge1xuICAgIGNvbnRleHQubGluZUNhcCA9ICdyb3VuZCc7XG4gIH1cblxuICByLmNvbG9yU3Ryb2tlU3R5bGUoY29udGV4dCwgb3ZlcmxheUNvbG9yWzBdLCBvdmVybGF5Q29sb3JbMV0sIG92ZXJsYXlDb2xvclsyXSwgb3ZlcmxheU9wYWNpdHkpO1xuICByLmRyYXdFZGdlUGF0aChlZGdlLCBjb250ZXh0LCBycy5hbGxwdHMsICdzb2xpZCcpO1xufTtcblxuQ1JwJDIuZHJhd0VkZ2VQYXRoID0gZnVuY3Rpb24gKGVkZ2UsIGNvbnRleHQsIHB0cywgdHlwZSkge1xuICB2YXIgcnMgPSBlZGdlLl9wcml2YXRlLnJzY3JhdGNoO1xuICB2YXIgY2FudmFzQ3h0ID0gY29udGV4dDtcbiAgdmFyIHBhdGg7XG4gIHZhciBwYXRoQ2FjaGVIaXQgPSBmYWxzZTtcbiAgdmFyIHVzZVBhdGhzID0gdGhpcy51c2VQYXRocygpO1xuICB2YXIgbGluZURhc2hQYXR0ZXJuID0gZWRnZS5wc3R5bGUoJ2xpbmUtZGFzaC1wYXR0ZXJuJykucGZWYWx1ZTtcbiAgdmFyIGxpbmVEYXNoT2Zmc2V0ID0gZWRnZS5wc3R5bGUoJ2xpbmUtZGFzaC1vZmZzZXQnKS5wZlZhbHVlO1xuXG4gIGlmICh1c2VQYXRocykge1xuICAgIHZhciBwYXRoQ2FjaGVLZXkgPSBwdHMuam9pbignJCcpO1xuICAgIHZhciBrZXlNYXRjaGVzID0gcnMucGF0aENhY2hlS2V5ICYmIHJzLnBhdGhDYWNoZUtleSA9PT0gcGF0aENhY2hlS2V5O1xuXG4gICAgaWYgKGtleU1hdGNoZXMpIHtcbiAgICAgIHBhdGggPSBjb250ZXh0ID0gcnMucGF0aENhY2hlO1xuICAgICAgcGF0aENhY2hlSGl0ID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0aCA9IGNvbnRleHQgPSBuZXcgUGF0aDJEKCk7XG4gICAgICBycy5wYXRoQ2FjaGVLZXkgPSBwYXRoQ2FjaGVLZXk7XG4gICAgICBycy5wYXRoQ2FjaGUgPSBwYXRoO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjYW52YXNDeHQuc2V0TGluZURhc2gpIHtcbiAgICAvLyBmb3IgdmVyeSBvdXRvZmRhdGUgYnJvd3NlcnNcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2RvdHRlZCc6XG4gICAgICAgIGNhbnZhc0N4dC5zZXRMaW5lRGFzaChbMSwgMV0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnZGFzaGVkJzpcbiAgICAgICAgY2FudmFzQ3h0LnNldExpbmVEYXNoKGxpbmVEYXNoUGF0dGVybik7XG4gICAgICAgIGNhbnZhc0N4dC5saW5lRGFzaE9mZnNldCA9IGxpbmVEYXNoT2Zmc2V0O1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnc29saWQnOlxuICAgICAgICBjYW52YXNDeHQuc2V0TGluZURhc2goW10pO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBpZiAoIXBhdGhDYWNoZUhpdCAmJiAhcnMuYmFkTGluZSkge1xuICAgIGlmIChjb250ZXh0LmJlZ2luUGF0aCkge1xuICAgICAgY29udGV4dC5iZWdpblBhdGgoKTtcbiAgICB9XG5cbiAgICBjb250ZXh0Lm1vdmVUbyhwdHNbMF0sIHB0c1sxXSk7XG5cbiAgICBzd2l0Y2ggKHJzLmVkZ2VUeXBlKSB7XG4gICAgICBjYXNlICdiZXppZXInOlxuICAgICAgY2FzZSAnc2VsZic6XG4gICAgICBjYXNlICdjb21wb3VuZCc6XG4gICAgICBjYXNlICdtdWx0aWJlemllcic6XG4gICAgICAgIGZvciAodmFyIGkgPSAyOyBpICsgMyA8IHB0cy5sZW5ndGg7IGkgKz0gNCkge1xuICAgICAgICAgIGNvbnRleHQucXVhZHJhdGljQ3VydmVUbyhwdHNbaV0sIHB0c1tpICsgMV0sIHB0c1tpICsgMl0sIHB0c1tpICsgM10pO1xuICAgICAgICB9XG5cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3N0cmFpZ2h0JzpcbiAgICAgIGNhc2UgJ3NlZ21lbnRzJzpcbiAgICAgIGNhc2UgJ2hheXN0YWNrJzpcbiAgICAgICAgZm9yICh2YXIgX2kgPSAyOyBfaSArIDEgPCBwdHMubGVuZ3RoOyBfaSArPSAyKSB7XG4gICAgICAgICAgY29udGV4dC5saW5lVG8ocHRzW19pXSwgcHRzW19pICsgMV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY29udGV4dCA9IGNhbnZhc0N4dDtcblxuICBpZiAodXNlUGF0aHMpIHtcbiAgICBjb250ZXh0LnN0cm9rZShwYXRoKTtcbiAgfSBlbHNlIHtcbiAgICBjb250ZXh0LnN0cm9rZSgpO1xuICB9IC8vIHJlc2V0IGFueSBsaW5lIGRhc2hlc1xuXG5cbiAgaWYgKGNvbnRleHQuc2V0TGluZURhc2gpIHtcbiAgICAvLyBmb3IgdmVyeSBvdXRvZmRhdGUgYnJvd3NlcnNcbiAgICBjb250ZXh0LnNldExpbmVEYXNoKFtdKTtcbiAgfVxufTtcblxuQ1JwJDIuZHJhd0Fycm93aGVhZHMgPSBmdW5jdGlvbiAoY29udGV4dCwgZWRnZSwgb3BhY2l0eSkge1xuICB2YXIgcnMgPSBlZGdlLl9wcml2YXRlLnJzY3JhdGNoO1xuICB2YXIgaXNIYXlzdGFjayA9IHJzLmVkZ2VUeXBlID09PSAnaGF5c3RhY2snO1xuXG4gIGlmICghaXNIYXlzdGFjaykge1xuICAgIHRoaXMuZHJhd0Fycm93aGVhZChjb250ZXh0LCBlZGdlLCAnc291cmNlJywgcnMuYXJyb3dTdGFydFgsIHJzLmFycm93U3RhcnRZLCBycy5zcmNBcnJvd0FuZ2xlLCBvcGFjaXR5KTtcbiAgfVxuXG4gIHRoaXMuZHJhd0Fycm93aGVhZChjb250ZXh0LCBlZGdlLCAnbWlkLXRhcmdldCcsIHJzLm1pZFgsIHJzLm1pZFksIHJzLm1pZHRndEFycm93QW5nbGUsIG9wYWNpdHkpO1xuICB0aGlzLmRyYXdBcnJvd2hlYWQoY29udGV4dCwgZWRnZSwgJ21pZC1zb3VyY2UnLCBycy5taWRYLCBycy5taWRZLCBycy5taWRzcmNBcnJvd0FuZ2xlLCBvcGFjaXR5KTtcblxuICBpZiAoIWlzSGF5c3RhY2spIHtcbiAgICB0aGlzLmRyYXdBcnJvd2hlYWQoY29udGV4dCwgZWRnZSwgJ3RhcmdldCcsIHJzLmFycm93RW5kWCwgcnMuYXJyb3dFbmRZLCBycy50Z3RBcnJvd0FuZ2xlLCBvcGFjaXR5KTtcbiAgfVxufTtcblxuQ1JwJDIuZHJhd0Fycm93aGVhZCA9IGZ1bmN0aW9uIChjb250ZXh0LCBlZGdlLCBwcmVmaXgsIHgsIHksIGFuZ2xlLCBvcGFjaXR5KSB7XG4gIGlmIChpc05hTih4KSB8fCB4ID09IG51bGwgfHwgaXNOYU4oeSkgfHwgeSA9PSBudWxsIHx8IGlzTmFOKGFuZ2xlKSB8fCBhbmdsZSA9PSBudWxsKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgYXJyb3dTaGFwZSA9IGVkZ2UucHN0eWxlKHByZWZpeCArICctYXJyb3ctc2hhcGUnKS52YWx1ZTtcblxuICBpZiAoYXJyb3dTaGFwZSA9PT0gJ25vbmUnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGFycm93Q2xlYXJGaWxsID0gZWRnZS5wc3R5bGUocHJlZml4ICsgJy1hcnJvdy1maWxsJykudmFsdWUgPT09ICdob2xsb3cnID8gJ2JvdGgnIDogJ2ZpbGxlZCc7XG4gIHZhciBhcnJvd0ZpbGwgPSBlZGdlLnBzdHlsZShwcmVmaXggKyAnLWFycm93LWZpbGwnKS52YWx1ZTtcbiAgdmFyIGVkZ2VXaWR0aCA9IGVkZ2UucHN0eWxlKCd3aWR0aCcpLnBmVmFsdWU7XG4gIHZhciBlZGdlT3BhY2l0eSA9IGVkZ2UucHN0eWxlKCdvcGFjaXR5JykudmFsdWU7XG5cbiAgaWYgKG9wYWNpdHkgPT09IHVuZGVmaW5lZCkge1xuICAgIG9wYWNpdHkgPSBlZGdlT3BhY2l0eTtcbiAgfVxuXG4gIHZhciBnY28gPSBjb250ZXh0Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbjtcblxuICBpZiAob3BhY2l0eSAhPT0gMSB8fCBhcnJvd0ZpbGwgPT09ICdob2xsb3cnKSB7XG4gICAgLy8gdGhlbiBleHRyYSBjbGVhciBpcyBuZWVkZWRcbiAgICBjb250ZXh0Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9ICdkZXN0aW5hdGlvbi1vdXQnO1xuICAgIHNlbGYuY29sb3JGaWxsU3R5bGUoY29udGV4dCwgMjU1LCAyNTUsIDI1NSwgMSk7XG4gICAgc2VsZi5jb2xvclN0cm9rZVN0eWxlKGNvbnRleHQsIDI1NSwgMjU1LCAyNTUsIDEpO1xuICAgIHNlbGYuZHJhd0Fycm93U2hhcGUoZWRnZSwgY29udGV4dCwgYXJyb3dDbGVhckZpbGwsIGVkZ2VXaWR0aCwgYXJyb3dTaGFwZSwgeCwgeSwgYW5nbGUpO1xuICAgIGNvbnRleHQuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gZ2NvO1xuICB9IC8vIG90aGVyd2lzZSwgdGhlIG9wYXF1ZSBhcnJvdyBjbGVhcnMgaXQgZm9yIGZyZWUgOilcblxuXG4gIHZhciBjb2xvciA9IGVkZ2UucHN0eWxlKHByZWZpeCArICctYXJyb3ctY29sb3InKS52YWx1ZTtcbiAgc2VsZi5jb2xvckZpbGxTdHlsZShjb250ZXh0LCBjb2xvclswXSwgY29sb3JbMV0sIGNvbG9yWzJdLCBvcGFjaXR5KTtcbiAgc2VsZi5jb2xvclN0cm9rZVN0eWxlKGNvbnRleHQsIGNvbG9yWzBdLCBjb2xvclsxXSwgY29sb3JbMl0sIG9wYWNpdHkpO1xuICBzZWxmLmRyYXdBcnJvd1NoYXBlKGVkZ2UsIGNvbnRleHQsIGFycm93RmlsbCwgZWRnZVdpZHRoLCBhcnJvd1NoYXBlLCB4LCB5LCBhbmdsZSk7XG59O1xuXG5DUnAkMi5kcmF3QXJyb3dTaGFwZSA9IGZ1bmN0aW9uIChlZGdlLCBjb250ZXh0LCBmaWxsLCBlZGdlV2lkdGgsIHNoYXBlLCB4LCB5LCBhbmdsZSkge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciB1c2VQYXRocyA9IHRoaXMudXNlUGF0aHMoKSAmJiBzaGFwZSAhPT0gJ3RyaWFuZ2xlLWNyb3NzJztcbiAgdmFyIHBhdGhDYWNoZUhpdCA9IGZhbHNlO1xuICB2YXIgcGF0aDtcbiAgdmFyIGNhbnZhc0NvbnRleHQgPSBjb250ZXh0O1xuICB2YXIgdHJhbnNsYXRpb24gPSB7XG4gICAgeDogeCxcbiAgICB5OiB5XG4gIH07XG4gIHZhciBzY2FsZSA9IGVkZ2UucHN0eWxlKCdhcnJvdy1zY2FsZScpLnZhbHVlO1xuICB2YXIgc2l6ZSA9IHRoaXMuZ2V0QXJyb3dXaWR0aChlZGdlV2lkdGgsIHNjYWxlKTtcbiAgdmFyIHNoYXBlSW1wbCA9IHIuYXJyb3dTaGFwZXNbc2hhcGVdO1xuXG4gIGlmICh1c2VQYXRocykge1xuICAgIHZhciBjYWNoZSA9IHIuYXJyb3dQYXRoQ2FjaGUgPSByLmFycm93UGF0aENhY2hlIHx8IFtdO1xuICAgIHZhciBrZXkgPSBoYXNoU3RyaW5nKHNoYXBlKTtcbiAgICB2YXIgY2FjaGVkUGF0aCA9IGNhY2hlW2tleV07XG5cbiAgICBpZiAoY2FjaGVkUGF0aCAhPSBudWxsKSB7XG4gICAgICBwYXRoID0gY29udGV4dCA9IGNhY2hlZFBhdGg7XG4gICAgICBwYXRoQ2FjaGVIaXQgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBwYXRoID0gY29udGV4dCA9IG5ldyBQYXRoMkQoKTtcbiAgICAgIGNhY2hlW2tleV0gPSBwYXRoO1xuICAgIH1cbiAgfVxuXG4gIGlmICghcGF0aENhY2hlSGl0KSB7XG4gICAgaWYgKGNvbnRleHQuYmVnaW5QYXRoKSB7XG4gICAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgIH1cblxuICAgIGlmICh1c2VQYXRocykge1xuICAgICAgLy8gc3RvcmUgaW4gdGhlIHBhdGggY2FjaGUgd2l0aCB2YWx1ZXMgZWFzaWx5IG1hbmlwdWxhdGVkIGxhdGVyXG4gICAgICBzaGFwZUltcGwuZHJhdyhjb250ZXh0LCAxLCAwLCB7XG4gICAgICAgIHg6IDAsXG4gICAgICAgIHk6IDBcbiAgICAgIH0sIDEpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzaGFwZUltcGwuZHJhdyhjb250ZXh0LCBzaXplLCBhbmdsZSwgdHJhbnNsYXRpb24sIGVkZ2VXaWR0aCk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQuY2xvc2VQYXRoKSB7XG4gICAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnRleHQgPSBjYW52YXNDb250ZXh0O1xuXG4gIGlmICh1c2VQYXRocykge1xuICAgIC8vIHNldCB0cmFuc2Zvcm0gdG8gYXJyb3cgcG9zaXRpb24vb3JpZW50YXRpb25cbiAgICBjb250ZXh0LnRyYW5zbGF0ZSh4LCB5KTtcbiAgICBjb250ZXh0LnJvdGF0ZShhbmdsZSk7XG4gICAgY29udGV4dC5zY2FsZShzaXplLCBzaXplKTtcbiAgfVxuXG4gIGlmIChmaWxsID09PSAnZmlsbGVkJyB8fCBmaWxsID09PSAnYm90aCcpIHtcbiAgICBpZiAodXNlUGF0aHMpIHtcbiAgICAgIGNvbnRleHQuZmlsbChwYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGV4dC5maWxsKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGZpbGwgPT09ICdob2xsb3cnIHx8IGZpbGwgPT09ICdib3RoJykge1xuICAgIGNvbnRleHQubGluZVdpZHRoID0gKHNoYXBlSW1wbC5tYXRjaEVkZ2VXaWR0aCA/IGVkZ2VXaWR0aCA6IDEpIC8gKHVzZVBhdGhzID8gc2l6ZSA6IDEpO1xuICAgIGNvbnRleHQubGluZUpvaW4gPSAnbWl0ZXInO1xuXG4gICAgaWYgKHVzZVBhdGhzKSB7XG4gICAgICBjb250ZXh0LnN0cm9rZShwYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICB9XG4gIH1cblxuICBpZiAodXNlUGF0aHMpIHtcbiAgICAvLyByZXNldCB0cmFuc2Zvcm0gYnkgYXBwbHlpbmcgaW52ZXJzZVxuICAgIGNvbnRleHQuc2NhbGUoMSAvIHNpemUsIDEgLyBzaXplKTtcbiAgICBjb250ZXh0LnJvdGF0ZSgtYW5nbGUpO1xuICAgIGNvbnRleHQudHJhbnNsYXRlKC14LCAteSk7XG4gIH1cbn07XG5cbnZhciBDUnAkMyA9IHt9O1xuXG5DUnAkMy5zYWZlRHJhd0ltYWdlID0gZnVuY3Rpb24gKGNvbnRleHQsIGltZywgaXgsIGl5LCBpdywgaWgsIHgsIHksIHcsIGgpIHtcbiAgLy8gZGV0ZWN0IHByb2JsZW1hdGljIGNhc2VzIGZvciBvbGQgYnJvd3NlcnMgd2l0aCBiYWQgaW1hZ2VzIChjaGVhcGVyIHRoYW4gdHJ5LWNhdGNoKVxuICBpZiAoaXcgPD0gMCB8fCBpaCA8PSAwIHx8IHcgPD0gMCB8fCBoIDw9IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb250ZXh0LmRyYXdJbWFnZShpbWcsIGl4LCBpeSwgaXcsIGloLCB4LCB5LCB3LCBoKTtcbn07XG5cbkNScCQzLmRyYXdJbnNjcmliZWRJbWFnZSA9IGZ1bmN0aW9uIChjb250ZXh0LCBpbWcsIG5vZGUsIGluZGV4LCBub2RlT3BhY2l0eSkge1xuICB2YXIgciA9IHRoaXM7XG4gIHZhciBwb3MgPSBub2RlLnBvc2l0aW9uKCk7XG4gIHZhciBub2RlWCA9IHBvcy54O1xuICB2YXIgbm9kZVkgPSBwb3MueTtcbiAgdmFyIHN0eWxlT2JqID0gbm9kZS5jeSgpLnN0eWxlKCk7XG4gIHZhciBnZXRJbmRleGVkU3R5bGUgPSBzdHlsZU9iai5nZXRJbmRleGVkU3R5bGUuYmluZChzdHlsZU9iaik7XG4gIHZhciBmaXQgPSBnZXRJbmRleGVkU3R5bGUobm9kZSwgJ2JhY2tncm91bmQtZml0JywgJ3ZhbHVlJywgaW5kZXgpO1xuICB2YXIgcmVwZWF0ID0gZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLXJlcGVhdCcsICd2YWx1ZScsIGluZGV4KTtcbiAgdmFyIG5vZGVXID0gbm9kZS53aWR0aCgpO1xuICB2YXIgbm9kZUggPSBub2RlLmhlaWdodCgpO1xuICB2YXIgcGFkZGluZ1gyID0gbm9kZS5wYWRkaW5nKCkgKiAyO1xuICB2YXIgbm9kZVRXID0gbm9kZVcgKyAoZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLXdpZHRoLXJlbGF0aXZlLXRvJywgJ3ZhbHVlJywgaW5kZXgpID09PSAnaW5uZXInID8gMCA6IHBhZGRpbmdYMik7XG4gIHZhciBub2RlVEggPSBub2RlSCArIChnZXRJbmRleGVkU3R5bGUobm9kZSwgJ2JhY2tncm91bmQtaGVpZ2h0LXJlbGF0aXZlLXRvJywgJ3ZhbHVlJywgaW5kZXgpID09PSAnaW5uZXInID8gMCA6IHBhZGRpbmdYMik7XG4gIHZhciBycyA9IG5vZGUuX3ByaXZhdGUucnNjcmF0Y2g7XG4gIHZhciBjbGlwID0gZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLWNsaXAnLCAndmFsdWUnLCBpbmRleCk7XG4gIHZhciBzaG91bGRDbGlwID0gY2xpcCA9PT0gJ25vZGUnO1xuICB2YXIgaW1nT3BhY2l0eSA9IGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC1pbWFnZS1vcGFjaXR5JywgJ3ZhbHVlJywgaW5kZXgpICogbm9kZU9wYWNpdHk7XG4gIHZhciBpbWdXID0gaW1nLndpZHRoIHx8IGltZy5jYWNoZWRXO1xuICB2YXIgaW1nSCA9IGltZy5oZWlnaHQgfHwgaW1nLmNhY2hlZEg7IC8vIHdvcmthcm91bmQgZm9yIGJyb2tlbiBicm93c2VycyBsaWtlIGllXG5cbiAgaWYgKG51bGwgPT0gaW1nVyB8fCBudWxsID09IGltZ0gpIHtcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGltZyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICAgIGltZ1cgPSBpbWcuY2FjaGVkVyA9IGltZy53aWR0aCB8fCBpbWcub2Zmc2V0V2lkdGg7XG4gICAgaW1nSCA9IGltZy5jYWNoZWRIID0gaW1nLmhlaWdodCB8fCBpbWcub2Zmc2V0SGVpZ2h0O1xuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoaW1nKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuICB9XG5cbiAgdmFyIHcgPSBpbWdXO1xuICB2YXIgaCA9IGltZ0g7XG5cbiAgaWYgKGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC13aWR0aCcsICd2YWx1ZScsIGluZGV4KSAhPT0gJ2F1dG8nKSB7XG4gICAgaWYgKGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC13aWR0aCcsICd1bml0cycsIGluZGV4KSA9PT0gJyUnKSB7XG4gICAgICB3ID0gZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLXdpZHRoJywgJ3BmVmFsdWUnLCBpbmRleCkgKiBub2RlVFc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHcgPSBnZXRJbmRleGVkU3R5bGUobm9kZSwgJ2JhY2tncm91bmQtd2lkdGgnLCAncGZWYWx1ZScsIGluZGV4KTtcbiAgICB9XG4gIH1cblxuICBpZiAoZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLWhlaWdodCcsICd2YWx1ZScsIGluZGV4KSAhPT0gJ2F1dG8nKSB7XG4gICAgaWYgKGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC1oZWlnaHQnLCAndW5pdHMnLCBpbmRleCkgPT09ICclJykge1xuICAgICAgaCA9IGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC1oZWlnaHQnLCAncGZWYWx1ZScsIGluZGV4KSAqIG5vZGVUSDtcbiAgICB9IGVsc2Uge1xuICAgICAgaCA9IGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC1oZWlnaHQnLCAncGZWYWx1ZScsIGluZGV4KTtcbiAgICB9XG4gIH1cblxuICBpZiAodyA9PT0gMCB8fCBoID09PSAwKSB7XG4gICAgcmV0dXJuOyAvLyBubyBwb2ludCBpbiBkcmF3aW5nIGVtcHR5IGltYWdlIChhbmQgY2hyb21lIGlzIGJyb2tlbiBpbiB0aGlzIGNhc2UpXG4gIH1cblxuICBpZiAoZml0ID09PSAnY29udGFpbicpIHtcbiAgICB2YXIgc2NhbGUgPSBNYXRoLm1pbihub2RlVFcgLyB3LCBub2RlVEggLyBoKTtcbiAgICB3ICo9IHNjYWxlO1xuICAgIGggKj0gc2NhbGU7XG4gIH0gZWxzZSBpZiAoZml0ID09PSAnY292ZXInKSB7XG4gICAgdmFyIHNjYWxlID0gTWF0aC5tYXgobm9kZVRXIC8gdywgbm9kZVRIIC8gaCk7XG4gICAgdyAqPSBzY2FsZTtcbiAgICBoICo9IHNjYWxlO1xuICB9XG5cbiAgdmFyIHggPSBub2RlWCAtIG5vZGVUVyAvIDI7IC8vIGxlZnRcblxuICB2YXIgcG9zWFVuaXRzID0gZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLXBvc2l0aW9uLXgnLCAndW5pdHMnLCBpbmRleCk7XG4gIHZhciBwb3NYUGZWYWwgPSBnZXRJbmRleGVkU3R5bGUobm9kZSwgJ2JhY2tncm91bmQtcG9zaXRpb24teCcsICdwZlZhbHVlJywgaW5kZXgpO1xuXG4gIGlmIChwb3NYVW5pdHMgPT09ICclJykge1xuICAgIHggKz0gKG5vZGVUVyAtIHcpICogcG9zWFBmVmFsO1xuICB9IGVsc2Uge1xuICAgIHggKz0gcG9zWFBmVmFsO1xuICB9XG5cbiAgdmFyIG9mZlhVbml0cyA9IGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC1vZmZzZXQteCcsICd1bml0cycsIGluZGV4KTtcbiAgdmFyIG9mZlhQZlZhbCA9IGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC1vZmZzZXQteCcsICdwZlZhbHVlJywgaW5kZXgpO1xuXG4gIGlmIChvZmZYVW5pdHMgPT09ICclJykge1xuICAgIHggKz0gKG5vZGVUVyAtIHcpICogb2ZmWFBmVmFsO1xuICB9IGVsc2Uge1xuICAgIHggKz0gb2ZmWFBmVmFsO1xuICB9XG5cbiAgdmFyIHkgPSBub2RlWSAtIG5vZGVUSCAvIDI7IC8vIHRvcFxuXG4gIHZhciBwb3NZVW5pdHMgPSBnZXRJbmRleGVkU3R5bGUobm9kZSwgJ2JhY2tncm91bmQtcG9zaXRpb24teScsICd1bml0cycsIGluZGV4KTtcbiAgdmFyIHBvc1lQZlZhbCA9IGdldEluZGV4ZWRTdHlsZShub2RlLCAnYmFja2dyb3VuZC1wb3NpdGlvbi15JywgJ3BmVmFsdWUnLCBpbmRleCk7XG5cbiAgaWYgKHBvc1lVbml0cyA9PT0gJyUnKSB7XG4gICAgeSArPSAobm9kZVRIIC0gaCkgKiBwb3NZUGZWYWw7XG4gIH0gZWxzZSB7XG4gICAgeSArPSBwb3NZUGZWYWw7XG4gIH1cblxuICB2YXIgb2ZmWVVuaXRzID0gZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLW9mZnNldC15JywgJ3VuaXRzJywgaW5kZXgpO1xuICB2YXIgb2ZmWVBmVmFsID0gZ2V0SW5kZXhlZFN0eWxlKG5vZGUsICdiYWNrZ3JvdW5kLW9mZnNldC15JywgJ3BmVmFsdWUnLCBpbmRleCk7XG5cbiAgaWYgKG9mZllVbml0cyA9PT0gJyUnKSB7XG4gICAgeSArPSAobm9kZVRIIC0gaCkgKiBvZmZZUGZWYWw7XG4gIH0gZWxzZSB7XG4gICAgeSArPSBvZmZZUGZWYWw7XG4gIH1cblxuICBpZiAocnMucGF0aENhY2hlKSB7XG4gICAgeCAtPSBub2RlWDtcbiAgICB5IC09IG5vZGVZO1xuICAgIG5vZGVYID0gMDtcbiAgICBub2RlWSA9IDA7XG4gIH1cblxuICB2YXIgZ0FscGhhID0gY29udGV4dC5nbG9iYWxBbHBoYTtcbiAgY29udGV4dC5nbG9iYWxBbHBoYSA9IGltZ09wYWNpdHk7XG5cbiAgaWYgKHJlcGVhdCA9PT0gJ25vLXJlcGVhdCcpIHtcbiAgICBpZiAoc2hvdWxkQ2xpcCkge1xuICAgICAgY29udGV4dC5zYXZlKCk7XG5cbiAgICAgIGlmIChycy5wYXRoQ2FjaGUpIHtcbiAgICAgICAgY29udGV4dC5jbGlwKHJzLnBhdGhDYWNoZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByLm5vZGVTaGFwZXNbci5nZXROb2RlU2hhcGUobm9kZSldLmRyYXcoY29udGV4dCwgbm9kZVgsIG5vZGVZLCBub2RlVFcsIG5vZGVUSCk7XG4gICAgICAgIGNvbnRleHQuY2xpcCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHIuc2FmZURyYXdJbWFnZShjb250ZXh0LCBpbWcsIDAsIDAsIGltZ1csIGltZ0gsIHgsIHksIHcsIGgpO1xuXG4gICAgaWYgKHNob3VsZENsaXApIHtcbiAgICAgIGNvbnRleHQucmVzdG9yZSgpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgcGF0dGVybiA9IGNvbnRleHQuY3JlYXRlUGF0dGVybihpbWcsIHJlcGVhdCk7XG4gICAgY29udGV4dC5maWxsU3R5bGUgPSBwYXR0ZXJuO1xuICAgIHIubm9kZVNoYXBlc1tyLmdldE5vZGVTaGFwZShub2RlKV0uZHJhdyhjb250ZXh0LCBub2RlWCwgbm9kZVksIG5vZGVUVywgbm9kZVRIKTtcbiAgICBjb250ZXh0LnRyYW5zbGF0ZSh4LCB5KTtcbiAgICBjb250ZXh0LmZpbGwoKTtcbiAgICBjb250ZXh0LnRyYW5zbGF0ZSgteCwgLXkpO1xuICB9XG5cbiAgY29udGV4dC5nbG9iYWxBbHBoYSA9IGdBbHBoYTtcbn07XG5cbnZhciBDUnAkNCA9IHt9O1xuXG5DUnAkNC5lbGVUZXh0QmlnZ2VyVGhhbk1pbiA9IGZ1bmN0aW9uIChlbGUsIHNjYWxlKSB7XG4gIGlmICghc2NhbGUpIHtcbiAgICB2YXIgem9vbSA9IGVsZS5jeSgpLnpvb20oKTtcbiAgICB2YXIgcHhSYXRpbyA9IHRoaXMuZ2V0UGl4ZWxSYXRpbygpO1xuICAgIHZhciBsdmwgPSBNYXRoLmNlaWwobG9nMih6b29tICogcHhSYXRpbykpOyAvLyB0aGUgZWZmZWN0aXZlIHRleHR1cmUgbGV2ZWxcblxuICAgIHNjYWxlID0gTWF0aC5wb3coMiwgbHZsKTtcbiAgfVxuXG4gIHZhciBjb21wdXRlZFNpemUgPSBlbGUucHN0eWxlKCdmb250LXNpemUnKS5wZlZhbHVlICogc2NhbGU7XG4gIHZhciBtaW5TaXplID0gZWxlLnBzdHlsZSgnbWluLXpvb21lZC1mb250LXNpemUnKS5wZlZhbHVlO1xuXG4gIGlmIChjb21wdXRlZFNpemUgPCBtaW5TaXplKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5DUnAkNC5kcmF3RWxlbWVudFRleHQgPSBmdW5jdGlvbiAoY29udGV4dCwgZWxlLCBzaGlmdFRvT3JpZ2luV2l0aEJiLCBmb3JjZSwgcHJlZml4KSB7XG4gIHZhciB1c2VFbGVPcGFjaXR5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDUgJiYgYXJndW1lbnRzWzVdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNV0gOiB0cnVlO1xuICB2YXIgciA9IHRoaXM7XG5cbiAgaWYgKGZvcmNlID09IG51bGwpIHtcbiAgICBpZiAodXNlRWxlT3BhY2l0eSAmJiAhci5lbGVUZXh0QmlnZ2VyVGhhbk1pbihlbGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9IGVsc2UgaWYgKGZvcmNlID09PSBmYWxzZSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChlbGUuaXNOb2RlKCkpIHtcbiAgICB2YXIgbGFiZWwgPSBlbGUucHN0eWxlKCdsYWJlbCcpO1xuXG4gICAgaWYgKCFsYWJlbCB8fCAhbGFiZWwudmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIganVzdGlmaWNhdGlvbiA9IHIuZ2V0TGFiZWxKdXN0aWZpY2F0aW9uKGVsZSk7XG4gICAgY29udGV4dC50ZXh0QWxpZ24gPSBqdXN0aWZpY2F0aW9uO1xuICAgIGNvbnRleHQudGV4dEJhc2VsaW5lID0gJ2JvdHRvbSc7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGJhZExpbmUgPSBlbGUuZWxlbWVudCgpLl9wcml2YXRlLnJzY3JhdGNoLmJhZExpbmU7XG5cbiAgICB2YXIgX2xhYmVsID0gZWxlLnBzdHlsZSgnbGFiZWwnKTtcblxuICAgIHZhciBzcmNMYWJlbCA9IGVsZS5wc3R5bGUoJ3NvdXJjZS1sYWJlbCcpO1xuICAgIHZhciB0Z3RMYWJlbCA9IGVsZS5wc3R5bGUoJ3RhcmdldC1sYWJlbCcpO1xuXG4gICAgaWYgKGJhZExpbmUgfHwgKCFfbGFiZWwgfHwgIV9sYWJlbC52YWx1ZSkgJiYgKCFzcmNMYWJlbCB8fCAhc3JjTGFiZWwudmFsdWUpICYmICghdGd0TGFiZWwgfHwgIXRndExhYmVsLnZhbHVlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnRleHQudGV4dEFsaWduID0gJ2NlbnRlcic7XG4gICAgY29udGV4dC50ZXh0QmFzZWxpbmUgPSAnYm90dG9tJztcbiAgfVxuXG4gIHZhciBhcHBseVJvdGF0aW9uID0gIXNoaWZ0VG9PcmlnaW5XaXRoQmI7XG4gIHZhciBiYjtcblxuICBpZiAoc2hpZnRUb09yaWdpbldpdGhCYikge1xuICAgIGJiID0gc2hpZnRUb09yaWdpbldpdGhCYjtcbiAgICBjb250ZXh0LnRyYW5zbGF0ZSgtYmIueDEsIC1iYi55MSk7XG4gIH1cblxuICBpZiAocHJlZml4ID09IG51bGwpIHtcbiAgICByLmRyYXdUZXh0KGNvbnRleHQsIGVsZSwgbnVsbCwgYXBwbHlSb3RhdGlvbiwgdXNlRWxlT3BhY2l0eSk7XG5cbiAgICBpZiAoZWxlLmlzRWRnZSgpKSB7XG4gICAgICByLmRyYXdUZXh0KGNvbnRleHQsIGVsZSwgJ3NvdXJjZScsIGFwcGx5Um90YXRpb24sIHVzZUVsZU9wYWNpdHkpO1xuICAgICAgci5kcmF3VGV4dChjb250ZXh0LCBlbGUsICd0YXJnZXQnLCBhcHBseVJvdGF0aW9uLCB1c2VFbGVPcGFjaXR5KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgci5kcmF3VGV4dChjb250ZXh0LCBlbGUsIHByZWZpeCwgYXBwbHlSb3RhdGlvbiwgdXNlRWxlT3BhY2l0eSk7XG4gIH1cblxuICBpZiAoc2hpZnRUb09yaWdpbldpdGhCYikge1xuICAgIGNvbnRleHQudHJhbnNsYXRlKGJiLngxLCBiYi55MSk7XG4gIH1cbn07XG5cbkNScCQ0LmdldEZvbnRDYWNoZSA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gIHZhciBjYWNoZTtcbiAgdGhpcy5mb250Q2FjaGVzID0gdGhpcy5mb250Q2FjaGVzIHx8IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5mb250Q2FjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgY2FjaGUgPSB0aGlzLmZvbnRDYWNoZXNbaV07XG5cbiAgICBpZiAoY2FjaGUuY29udGV4dCA9PT0gY29udGV4dCkge1xuICAgICAgcmV0dXJuIGNhY2hlO1xuICAgIH1cbiAgfVxuXG4gIGNhY2hlID0ge1xuICAgIGNvbnRleHQ6IGNvbnRleHRcbiAgfTtcbiAgdGhpcy5mb250Q2FjaGVzLnB1c2goY2FjaGUpO1xuICByZXR1cm4gY2FjaGU7XG59OyAvLyBzZXQgdXAgY2FudmFzIGNvbnRleHQgd2l0aCBmb250XG4vLyByZXR1cm5zIHRyYW5zZm9ybWVkIHRleHQgc3RyaW5nXG5cblxuQ1JwJDQuc2V0dXBUZXh0U3R5bGUgPSBmdW5jdGlvbiAoY29udGV4dCwgZWxlKSB7XG4gIHZhciB1c2VFbGVPcGFjaXR5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiB0cnVlO1xuICAvLyBGb250IHN0eWxlXG4gIHZhciBsYWJlbFN0eWxlID0gZWxlLnBzdHlsZSgnZm9udC1zdHlsZScpLnN0clZhbHVlO1xuICB2YXIgbGFiZWxTaXplID0gZWxlLnBzdHlsZSgnZm9udC1zaXplJykucGZWYWx1ZSArICdweCc7XG4gIHZhciBsYWJlbEZhbWlseSA9IGVsZS5wc3R5bGUoJ2ZvbnQtZmFtaWx5Jykuc3RyVmFsdWU7XG4gIHZhciBsYWJlbFdlaWdodCA9IGVsZS5wc3R5bGUoJ2ZvbnQtd2VpZ2h0Jykuc3RyVmFsdWU7XG4gIHZhciBvcGFjaXR5ID0gdXNlRWxlT3BhY2l0eSA/IGVsZS5lZmZlY3RpdmVPcGFjaXR5KCkgKiBlbGUucHN0eWxlKCd0ZXh0LW9wYWNpdHknKS52YWx1ZSA6IDE7XG4gIHZhciBvdXRsaW5lT3BhY2l0eSA9IGVsZS5wc3R5bGUoJ3RleHQtb3V0bGluZS1vcGFjaXR5JykudmFsdWUgKiBvcGFjaXR5O1xuICB2YXIgY29sb3IgPSBlbGUucHN0eWxlKCdjb2xvcicpLnZhbHVlO1xuICB2YXIgb3V0bGluZUNvbG9yID0gZWxlLnBzdHlsZSgndGV4dC1vdXRsaW5lLWNvbG9yJykudmFsdWU7XG4gIGNvbnRleHQuZm9udCA9IGxhYmVsU3R5bGUgKyAnICcgKyBsYWJlbFdlaWdodCArICcgJyArIGxhYmVsU2l6ZSArICcgJyArIGxhYmVsRmFtaWx5O1xuICBjb250ZXh0LmxpbmVKb2luID0gJ3JvdW5kJzsgLy8gc28gdGV4dCBvdXRsaW5lcyBhcmVuJ3QgamFnZ2VkXG5cbiAgdGhpcy5jb2xvckZpbGxTdHlsZShjb250ZXh0LCBjb2xvclswXSwgY29sb3JbMV0sIGNvbG9yWzJdLCBvcGFjaXR5KTtcbiAgdGhpcy5jb2xvclN0cm9rZVN0eWxlKGNvbnRleHQsIG91dGxpbmVDb2xvclswXSwgb3V0bGluZUNvbG9yWzFdLCBvdXRsaW5lQ29sb3JbMl0sIG91dGxpbmVPcGFjaXR5KTtcbn07IC8vIFRPRE8gZW5zdXJlIHJlLXVzZWRcblxuXG5mdW5jdGlvbiByb3VuZFJlY3QoY3R4LCB4LCB5LCB3aWR0aCwgaGVpZ2h0KSB7XG4gIHZhciByYWRpdXMgPSBhcmd1bWVudHMubGVuZ3RoID4gNSAmJiBhcmd1bWVudHNbNV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s1XSA6IDU7XG4gIGN0eC5iZWdpblBhdGgoKTtcbiAgY3R4Lm1vdmVUbyh4ICsgcmFkaXVzLCB5KTtcbiAgY3R4LmxpbmVUbyh4ICsgd2lkdGggLSByYWRpdXMsIHkpO1xuICBjdHgucXVhZHJhdGljQ3VydmVUbyh4ICsgd2lkdGgsIHksIHggKyB3aWR0aCwgeSArIHJhZGl1cyk7XG4gIGN0eC5saW5lVG8oeCArIHdpZHRoLCB5ICsgaGVpZ2h0IC0gcmFkaXVzKTtcbiAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCArIHdpZHRoLCB5ICsgaGVpZ2h0LCB4ICsgd2lkdGggLSByYWRpdXMsIHkgKyBoZWlnaHQpO1xuICBjdHgubGluZVRvKHggKyByYWRpdXMsIHkgKyBoZWlnaHQpO1xuICBjdHgucXVhZHJhdGljQ3VydmVUbyh4LCB5ICsgaGVpZ2h0LCB4LCB5ICsgaGVpZ2h0IC0gcmFkaXVzKTtcbiAgY3R4LmxpbmVUbyh4LCB5ICsgcmFkaXVzKTtcbiAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCwgeSwgeCArIHJhZGl1cywgeSk7XG4gIGN0eC5jbG9zZVBhdGgoKTtcbiAgY3R4LmZpbGwoKTtcbn1cblxuQ1JwJDQuZ2V0VGV4dEFuZ2xlID0gZnVuY3Rpb24gKGVsZSwgcHJlZml4KSB7XG4gIHZhciB0aGV0YTtcbiAgdmFyIF9wID0gZWxlLl9wcml2YXRlO1xuICB2YXIgcnNjcmF0Y2ggPSBfcC5yc2NyYXRjaDtcbiAgdmFyIHBkYXNoID0gcHJlZml4ID8gcHJlZml4ICsgJy0nIDogJyc7XG4gIHZhciByb3RhdGlvbiA9IGVsZS5wc3R5bGUocGRhc2ggKyAndGV4dC1yb3RhdGlvbicpO1xuICB2YXIgdGV4dEFuZ2xlID0gZ2V0UHJlZml4ZWRQcm9wZXJ0eShyc2NyYXRjaCwgJ2xhYmVsQW5nbGUnLCBwcmVmaXgpO1xuXG4gIGlmIChyb3RhdGlvbi5zdHJWYWx1ZSA9PT0gJ2F1dG9yb3RhdGUnKSB7XG4gICAgdGhldGEgPSBlbGUuaXNFZGdlKCkgPyB0ZXh0QW5nbGUgOiAwO1xuICB9IGVsc2UgaWYgKHJvdGF0aW9uLnN0clZhbHVlID09PSAnbm9uZScpIHtcbiAgICB0aGV0YSA9IDA7XG4gIH0gZWxzZSB7XG4gICAgdGhldGEgPSByb3RhdGlvbi5wZlZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIHRoZXRhO1xufTtcblxuQ1JwJDQuZHJhd1RleHQgPSBmdW5jdGlvbiAoY29udGV4dCwgZWxlLCBwcmVmaXgpIHtcbiAgdmFyIGFwcGx5Um90YXRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IHRydWU7XG4gIHZhciB1c2VFbGVPcGFjaXR5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDQgJiYgYXJndW1lbnRzWzRdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNF0gOiB0cnVlO1xuICB2YXIgX3AgPSBlbGUuX3ByaXZhdGU7XG4gIHZhciByc2NyYXRjaCA9IF9wLnJzY3JhdGNoO1xuICB2YXIgcGFyZW50T3BhY2l0eSA9IHVzZUVsZU9wYWNpdHkgPyBlbGUuZWZmZWN0aXZlT3BhY2l0eSgpIDogMTtcblxuICBpZiAodXNlRWxlT3BhY2l0eSAmJiAocGFyZW50T3BhY2l0eSA9PT0gMCB8fCBlbGUucHN0eWxlKCd0ZXh0LW9wYWNpdHknKS52YWx1ZSA9PT0gMCkpIHtcbiAgICByZXR1cm47XG4gIH0gLy8gdXNlICdtYWluJyBhcyBhbiBhbGlhcyBmb3IgdGhlIG1haW4gbGFiZWwgKGkuZS4gbnVsbCBwcmVmaXgpXG5cblxuICBpZiAocHJlZml4ID09PSAnbWFpbicpIHtcbiAgICBwcmVmaXggPSBudWxsO1xuICB9XG5cbiAgdmFyIHRleHRYID0gZ2V0UHJlZml4ZWRQcm9wZXJ0eShyc2NyYXRjaCwgJ2xhYmVsWCcsIHByZWZpeCk7XG4gIHZhciB0ZXh0WSA9IGdldFByZWZpeGVkUHJvcGVydHkocnNjcmF0Y2gsICdsYWJlbFknLCBwcmVmaXgpO1xuICB2YXIgb3JnVGV4dFgsIG9yZ1RleHRZOyAvLyB1c2VkIGZvciByb3RhdGlvblxuXG4gIHZhciB0ZXh0ID0gdGhpcy5nZXRMYWJlbFRleHQoZWxlLCBwcmVmaXgpO1xuXG4gIGlmICh0ZXh0ICE9IG51bGwgJiYgdGV4dCAhPT0gJycgJiYgIWlzTmFOKHRleHRYKSAmJiAhaXNOYU4odGV4dFkpKSB7XG4gICAgdGhpcy5zZXR1cFRleHRTdHlsZShjb250ZXh0LCBlbGUsIHVzZUVsZU9wYWNpdHkpO1xuICAgIHZhciBwZGFzaCA9IHByZWZpeCA/IHByZWZpeCArICctJyA6ICcnO1xuICAgIHZhciB0ZXh0VyA9IGdldFByZWZpeGVkUHJvcGVydHkocnNjcmF0Y2gsICdsYWJlbFdpZHRoJywgcHJlZml4KTtcbiAgICB2YXIgdGV4dEggPSBnZXRQcmVmaXhlZFByb3BlcnR5KHJzY3JhdGNoLCAnbGFiZWxIZWlnaHQnLCBwcmVmaXgpO1xuICAgIHZhciBtYXJnaW5YID0gZWxlLnBzdHlsZShwZGFzaCArICd0ZXh0LW1hcmdpbi14JykucGZWYWx1ZTtcbiAgICB2YXIgbWFyZ2luWSA9IGVsZS5wc3R5bGUocGRhc2ggKyAndGV4dC1tYXJnaW4teScpLnBmVmFsdWU7XG4gICAgdmFyIGlzRWRnZSA9IGVsZS5pc0VkZ2UoKTtcbiAgICB2YXIgaGFsaWduID0gZWxlLnBzdHlsZSgndGV4dC1oYWxpZ24nKS52YWx1ZTtcbiAgICB2YXIgdmFsaWduID0gZWxlLnBzdHlsZSgndGV4dC12YWxpZ24nKS52YWx1ZTtcblxuICAgIGlmIChpc0VkZ2UpIHtcbiAgICAgIGhhbGlnbiA9ICdjZW50ZXInO1xuICAgICAgdmFsaWduID0gJ2NlbnRlcic7XG4gICAgfVxuXG4gICAgdGV4dFggKz0gbWFyZ2luWDtcbiAgICB0ZXh0WSArPSBtYXJnaW5ZO1xuICAgIHZhciB0aGV0YTtcblxuICAgIGlmICghYXBwbHlSb3RhdGlvbikge1xuICAgICAgdGhldGEgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGV0YSA9IHRoaXMuZ2V0VGV4dEFuZ2xlKGVsZSwgcHJlZml4KTtcbiAgICB9XG5cbiAgICBpZiAodGhldGEgIT09IDApIHtcbiAgICAgIG9yZ1RleHRYID0gdGV4dFg7XG4gICAgICBvcmdUZXh0WSA9IHRleHRZO1xuICAgICAgY29udGV4dC50cmFuc2xhdGUob3JnVGV4dFgsIG9yZ1RleHRZKTtcbiAgICAgIGNvbnRleHQucm90YXRlKHRoZXRhKTtcbiAgICAgIHRleHRYID0gMDtcbiAgICAgIHRleHRZID0gMDtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKHZhbGlnbikge1xuICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICAgIHRleHRZICs9IHRleHRIIC8gMjtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgIHRleHRZICs9IHRleHRIO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICB2YXIgYmFja2dyb3VuZE9wYWNpdHkgPSBlbGUucHN0eWxlKCd0ZXh0LWJhY2tncm91bmQtb3BhY2l0eScpLnZhbHVlO1xuICAgIHZhciBib3JkZXJPcGFjaXR5ID0gZWxlLnBzdHlsZSgndGV4dC1ib3JkZXItb3BhY2l0eScpLnZhbHVlO1xuICAgIHZhciB0ZXh0Qm9yZGVyV2lkdGggPSBlbGUucHN0eWxlKCd0ZXh0LWJvcmRlci13aWR0aCcpLnBmVmFsdWU7XG4gICAgdmFyIGJhY2tncm91bmRQYWRkaW5nID0gZWxlLnBzdHlsZSgndGV4dC1iYWNrZ3JvdW5kLXBhZGRpbmcnKS5wZlZhbHVlO1xuXG4gICAgaWYgKGJhY2tncm91bmRPcGFjaXR5ID4gMCB8fCB0ZXh0Qm9yZGVyV2lkdGggPiAwICYmIGJvcmRlck9wYWNpdHkgPiAwKSB7XG4gICAgICB2YXIgYmdYID0gdGV4dFggLSBiYWNrZ3JvdW5kUGFkZGluZztcblxuICAgICAgc3dpdGNoIChoYWxpZ24pIHtcbiAgICAgICAgY2FzZSAnbGVmdCc6XG4gICAgICAgICAgYmdYIC09IHRleHRXO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICAgICAgYmdYIC09IHRleHRXIC8gMjtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgdmFyIGJnWSA9IHRleHRZIC0gdGV4dEggLSBiYWNrZ3JvdW5kUGFkZGluZztcbiAgICAgIHZhciBiZ1cgPSB0ZXh0VyArIDIgKiBiYWNrZ3JvdW5kUGFkZGluZztcbiAgICAgIHZhciBiZ0ggPSB0ZXh0SCArIDIgKiBiYWNrZ3JvdW5kUGFkZGluZztcblxuICAgICAgaWYgKGJhY2tncm91bmRPcGFjaXR5ID4gMCkge1xuICAgICAgICB2YXIgdGV4dEZpbGwgPSBjb250ZXh0LmZpbGxTdHlsZTtcbiAgICAgICAgdmFyIHRleHRCYWNrZ3JvdW5kQ29sb3IgPSBlbGUucHN0eWxlKCd0ZXh0LWJhY2tncm91bmQtY29sb3InKS52YWx1ZTtcbiAgICAgICAgY29udGV4dC5maWxsU3R5bGUgPSAncmdiYSgnICsgdGV4dEJhY2tncm91bmRDb2xvclswXSArICcsJyArIHRleHRCYWNrZ3JvdW5kQ29sb3JbMV0gKyAnLCcgKyB0ZXh0QmFja2dyb3VuZENvbG9yWzJdICsgJywnICsgYmFja2dyb3VuZE9wYWNpdHkgKiBwYXJlbnRPcGFjaXR5ICsgJyknO1xuICAgICAgICB2YXIgc3R5bGVTaGFwZSA9IGVsZS5wc3R5bGUoJ3RleHQtYmFja2dyb3VuZC1zaGFwZScpLnN0clZhbHVlO1xuXG4gICAgICAgIGlmIChzdHlsZVNoYXBlLmluZGV4T2YoJ3JvdW5kJykgPT09IDApIHtcbiAgICAgICAgICByb3VuZFJlY3QoY29udGV4dCwgYmdYLCBiZ1ksIGJnVywgYmdILCAyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb250ZXh0LmZpbGxSZWN0KGJnWCwgYmdZLCBiZ1csIGJnSCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0LmZpbGxTdHlsZSA9IHRleHRGaWxsO1xuICAgICAgfVxuXG4gICAgICBpZiAodGV4dEJvcmRlcldpZHRoID4gMCAmJiBib3JkZXJPcGFjaXR5ID4gMCkge1xuICAgICAgICB2YXIgdGV4dFN0cm9rZSA9IGNvbnRleHQuc3Ryb2tlU3R5bGU7XG4gICAgICAgIHZhciB0ZXh0TGluZVdpZHRoID0gY29udGV4dC5saW5lV2lkdGg7XG4gICAgICAgIHZhciB0ZXh0Qm9yZGVyQ29sb3IgPSBlbGUucHN0eWxlKCd0ZXh0LWJvcmRlci1jb2xvcicpLnZhbHVlO1xuICAgICAgICB2YXIgdGV4dEJvcmRlclN0eWxlID0gZWxlLnBzdHlsZSgndGV4dC1ib3JkZXItc3R5bGUnKS52YWx1ZTtcbiAgICAgICAgY29udGV4dC5zdHJva2VTdHlsZSA9ICdyZ2JhKCcgKyB0ZXh0Qm9yZGVyQ29sb3JbMF0gKyAnLCcgKyB0ZXh0Qm9yZGVyQ29sb3JbMV0gKyAnLCcgKyB0ZXh0Qm9yZGVyQ29sb3JbMl0gKyAnLCcgKyBib3JkZXJPcGFjaXR5ICogcGFyZW50T3BhY2l0eSArICcpJztcbiAgICAgICAgY29udGV4dC5saW5lV2lkdGggPSB0ZXh0Qm9yZGVyV2lkdGg7XG5cbiAgICAgICAgaWYgKGNvbnRleHQuc2V0TGluZURhc2gpIHtcbiAgICAgICAgICAvLyBmb3IgdmVyeSBvdXRvZmRhdGUgYnJvd3NlcnNcbiAgICAgICAgICBzd2l0Y2ggKHRleHRCb3JkZXJTdHlsZSkge1xuICAgICAgICAgICAgY2FzZSAnZG90dGVkJzpcbiAgICAgICAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChbMSwgMV0pO1xuICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSAnZGFzaGVkJzpcbiAgICAgICAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChbNCwgMl0pO1xuICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSAnZG91YmxlJzpcbiAgICAgICAgICAgICAgY29udGV4dC5saW5lV2lkdGggPSB0ZXh0Qm9yZGVyV2lkdGggLyA0OyAvLyA1MCUgcmVzZXJ2ZWQgZm9yIHdoaXRlIGJldHdlZW4gdGhlIHR3byBib3JkZXJzXG5cbiAgICAgICAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChbXSk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlICdzb2xpZCc6XG4gICAgICAgICAgICAgIGNvbnRleHQuc2V0TGluZURhc2goW10pO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0LnN0cm9rZVJlY3QoYmdYLCBiZ1ksIGJnVywgYmdIKTtcblxuICAgICAgICBpZiAodGV4dEJvcmRlclN0eWxlID09PSAnZG91YmxlJykge1xuICAgICAgICAgIHZhciB3aGl0ZVdpZHRoID0gdGV4dEJvcmRlcldpZHRoIC8gMjtcbiAgICAgICAgICBjb250ZXh0LnN0cm9rZVJlY3QoYmdYICsgd2hpdGVXaWR0aCwgYmdZICsgd2hpdGVXaWR0aCwgYmdXIC0gd2hpdGVXaWR0aCAqIDIsIGJnSCAtIHdoaXRlV2lkdGggKiAyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb250ZXh0LnNldExpbmVEYXNoKSB7XG4gICAgICAgICAgLy8gZm9yIHZlcnkgb3V0b2ZkYXRlIGJyb3dzZXJzXG4gICAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChbXSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0LmxpbmVXaWR0aCA9IHRleHRMaW5lV2lkdGg7XG4gICAgICAgIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSB0ZXh0U3Ryb2tlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsaW5lV2lkdGggPSAyICogZWxlLnBzdHlsZSgndGV4dC1vdXRsaW5lLXdpZHRoJykucGZWYWx1ZTsgLy8gKjIgYi9jIHRoZSBzdHJva2UgaXMgZHJhd24gY2VudHJlZCBvbiB0aGUgbWlkZGxlXG5cbiAgICBpZiAobGluZVdpZHRoID4gMCkge1xuICAgICAgY29udGV4dC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgfVxuXG4gICAgaWYgKGVsZS5wc3R5bGUoJ3RleHQtd3JhcCcpLnZhbHVlID09PSAnd3JhcCcpIHtcbiAgICAgIHZhciBsaW5lcyA9IGdldFByZWZpeGVkUHJvcGVydHkocnNjcmF0Y2gsICdsYWJlbFdyYXBDYWNoZWRMaW5lcycsIHByZWZpeCk7XG4gICAgICB2YXIgbGluZUhlaWdodCA9IGdldFByZWZpeGVkUHJvcGVydHkocnNjcmF0Y2gsICdsYWJlbExpbmVIZWlnaHQnLCBwcmVmaXgpO1xuICAgICAgdmFyIGhhbGZUZXh0VyA9IHRleHRXIC8gMjtcbiAgICAgIHZhciBqdXN0aWZpY2F0aW9uID0gdGhpcy5nZXRMYWJlbEp1c3RpZmljYXRpb24oZWxlKTtcblxuICAgICAgaWYgKGp1c3RpZmljYXRpb24gPT09ICdhdXRvJykgOyBlbHNlIGlmIChoYWxpZ24gPT09ICdsZWZ0Jykge1xuICAgICAgICAvLyBhdXRvIGp1c3RpZmljYXRpb24gOiByaWdodFxuICAgICAgICBpZiAoanVzdGlmaWNhdGlvbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgdGV4dFggKz0gLXRleHRXO1xuICAgICAgICB9IGVsc2UgaWYgKGp1c3RpZmljYXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgdGV4dFggKz0gLWhhbGZUZXh0VztcbiAgICAgICAgfSAvLyBlbHNlIHNhbWUgYXMgYXV0b1xuXG4gICAgICB9IGVsc2UgaWYgKGhhbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgLy8gYXV0byBqdXN0ZmljYXRpb24gOiBjZW50ZXJcbiAgICAgICAgaWYgKGp1c3RpZmljYXRpb24gPT09ICdsZWZ0Jykge1xuICAgICAgICAgIHRleHRYICs9IC1oYWxmVGV4dFc7XG4gICAgICAgIH0gZWxzZSBpZiAoanVzdGlmaWNhdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgIHRleHRYICs9IGhhbGZUZXh0VztcbiAgICAgICAgfSAvLyBlbHNlIHNhbWUgYXMgYXV0b1xuXG4gICAgICB9IGVsc2UgaWYgKGhhbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAvLyBhdXRvIGp1c3RpZmljYXRpb24gOiBsZWZ0XG4gICAgICAgIGlmIChqdXN0aWZpY2F0aW9uID09PSAnY2VudGVyJykge1xuICAgICAgICAgIHRleHRYICs9IGhhbGZUZXh0VztcbiAgICAgICAgfSBlbHNlIGlmIChqdXN0aWZpY2F0aW9uID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgdGV4dFggKz0gdGV4dFc7XG4gICAgICAgIH0gLy8gZWxzZSBzYW1lIGFzIGF1dG9cblxuICAgICAgfVxuXG4gICAgICBzd2l0Y2ggKHZhbGlnbikge1xuICAgICAgICBjYXNlICd0b3AnOlxuICAgICAgICAgIHRleHRZIC09IChsaW5lcy5sZW5ndGggLSAxKSAqIGxpbmVIZWlnaHQ7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnY2VudGVyJzpcbiAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgICB0ZXh0WSAtPSAobGluZXMubGVuZ3RoIC0gMSkgKiBsaW5lSGVpZ2h0O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBsID0gMDsgbCA8IGxpbmVzLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgIGlmIChsaW5lV2lkdGggPiAwKSB7XG4gICAgICAgICAgY29udGV4dC5zdHJva2VUZXh0KGxpbmVzW2xdLCB0ZXh0WCwgdGV4dFkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGV4dC5maWxsVGV4dChsaW5lc1tsXSwgdGV4dFgsIHRleHRZKTtcbiAgICAgICAgdGV4dFkgKz0gbGluZUhlaWdodDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGxpbmVXaWR0aCA+IDApIHtcbiAgICAgICAgY29udGV4dC5zdHJva2VUZXh0KHRleHQsIHRleHRYLCB0ZXh0WSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnRleHQuZmlsbFRleHQodGV4dCwgdGV4dFgsIHRleHRZKTtcbiAgICB9XG5cbiAgICBpZiAodGhldGEgIT09IDApIHtcbiAgICAgIGNvbnRleHQucm90YXRlKC10aGV0YSk7XG4gICAgICBjb250ZXh0LnRyYW5zbGF0ZSgtb3JnVGV4dFgsIC1vcmdUZXh0WSk7XG4gICAgfVxuICB9XG59O1xuXG4vKiBnbG9iYWwgUGF0aDJEICovXG52YXIgQ1JwJDUgPSB7fTtcblxuQ1JwJDUuZHJhd05vZGUgPSBmdW5jdGlvbiAoY29udGV4dCwgbm9kZSwgc2hpZnRUb09yaWdpbldpdGhCYikge1xuICB2YXIgZHJhd0xhYmVsID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiB0cnVlO1xuICB2YXIgc2hvdWxkRHJhd092ZXJsYXkgPSBhcmd1bWVudHMubGVuZ3RoID4gNCAmJiBhcmd1bWVudHNbNF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s0XSA6IHRydWU7XG4gIHZhciBzaG91bGREcmF3T3BhY2l0eSA9IGFyZ3VtZW50cy5sZW5ndGggPiA1ICYmIGFyZ3VtZW50c1s1XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzVdIDogdHJ1ZTtcbiAgdmFyIHIgPSB0aGlzO1xuICB2YXIgbm9kZVdpZHRoLCBub2RlSGVpZ2h0O1xuICB2YXIgX3AgPSBub2RlLl9wcml2YXRlO1xuICB2YXIgcnMgPSBfcC5yc2NyYXRjaDtcbiAgdmFyIHBvcyA9IG5vZGUucG9zaXRpb24oKTtcblxuICBpZiAoIW51bWJlcihwb3MueCkgfHwgIW51bWJlcihwb3MueSkpIHtcbiAgICByZXR1cm47IC8vIGNhbid0IGRyYXcgbm9kZSB3aXRoIHVuZGVmaW5lZCBwb3NpdGlvblxuICB9XG5cbiAgaWYgKHNob3VsZERyYXdPcGFjaXR5ICYmICFub2RlLnZpc2libGUoKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBlbGVPcGFjaXR5ID0gc2hvdWxkRHJhd09wYWNpdHkgPyBub2RlLmVmZmVjdGl2ZU9wYWNpdHkoKSA6IDE7XG4gIHZhciB1c2VQYXRocyA9IHIudXNlUGF0aHMoKTtcbiAgdmFyIHBhdGg7XG4gIHZhciBwYXRoQ2FjaGVIaXQgPSBmYWxzZTtcbiAgdmFyIHBhZGRpbmcgPSBub2RlLnBhZGRpbmcoKTtcbiAgbm9kZVdpZHRoID0gbm9kZS53aWR0aCgpICsgMiAqIHBhZGRpbmc7XG4gIG5vZGVIZWlnaHQgPSBub2RlLmhlaWdodCgpICsgMiAqIHBhZGRpbmc7IC8vXG4gIC8vIHNldHVwIHNoaWZ0XG5cbiAgdmFyIGJiO1xuXG4gIGlmIChzaGlmdFRvT3JpZ2luV2l0aEJiKSB7XG4gICAgYmIgPSBzaGlmdFRvT3JpZ2luV2l0aEJiO1xuICAgIGNvbnRleHQudHJhbnNsYXRlKC1iYi54MSwgLWJiLnkxKTtcbiAgfSAvL1xuICAvLyBsb2FkIGJnIGltYWdlXG5cblxuICB2YXIgYmdJbWdQcm9wID0gbm9kZS5wc3R5bGUoJ2JhY2tncm91bmQtaW1hZ2UnKTtcbiAgdmFyIHVybHMgPSBiZ0ltZ1Byb3AudmFsdWU7XG4gIHZhciB1cmxEZWZpbmVkID0gbmV3IEFycmF5KHVybHMubGVuZ3RoKTtcbiAgdmFyIGltYWdlID0gbmV3IEFycmF5KHVybHMubGVuZ3RoKTtcbiAgdmFyIG51bUltYWdlcyA9IDA7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB1cmxzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHVybCA9IHVybHNbaV07XG4gICAgdmFyIGRlZmQgPSB1cmxEZWZpbmVkW2ldID0gdXJsICE9IG51bGwgJiYgdXJsICE9PSAnbm9uZSc7XG5cbiAgICBpZiAoZGVmZCkge1xuICAgICAgdmFyIGJnSW1nQ3Jvc3NPcmlnaW4gPSBub2RlLmN5KCkuc3R5bGUoKS5nZXRJbmRleGVkU3R5bGUobm9kZSwgJ2JhY2tncm91bmQtaW1hZ2UtY3Jvc3NvcmlnaW4nLCAndmFsdWUnLCBpKTtcbiAgICAgIG51bUltYWdlcysrOyAvLyBnZXQgaW1hZ2UsIGFuZCBpZiBub3QgbG9hZGVkIHRoZW4gYXNrIHRvIHJlZHJhdyB3aGVuIGxhdGVyIGxvYWRlZFxuXG4gICAgICBpbWFnZVtpXSA9IHIuZ2V0Q2FjaGVkSW1hZ2UodXJsLCBiZ0ltZ0Nyb3NzT3JpZ2luLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9wLmJhY2tncm91bmRUaW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICBub2RlLmVtaXRBbmROb3RpZnkoJ2JhY2tncm91bmQnKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSAvL1xuICAvLyBzZXR1cCBzdHlsZXNcblxuXG4gIHZhciBkYXJrbmVzcyA9IG5vZGUucHN0eWxlKCdiYWNrZ3JvdW5kLWJsYWNrZW4nKS52YWx1ZTtcbiAgdmFyIGJvcmRlcldpZHRoID0gbm9kZS5wc3R5bGUoJ2JvcmRlci13aWR0aCcpLnBmVmFsdWU7XG4gIHZhciBiZ09wYWNpdHkgPSBub2RlLnBzdHlsZSgnYmFja2dyb3VuZC1vcGFjaXR5JykudmFsdWUgKiBlbGVPcGFjaXR5O1xuICB2YXIgYm9yZGVyQ29sb3IgPSBub2RlLnBzdHlsZSgnYm9yZGVyLWNvbG9yJykudmFsdWU7XG4gIHZhciBib3JkZXJTdHlsZSA9IG5vZGUucHN0eWxlKCdib3JkZXItc3R5bGUnKS52YWx1ZTtcbiAgdmFyIGJvcmRlck9wYWNpdHkgPSBub2RlLnBzdHlsZSgnYm9yZGVyLW9wYWNpdHknKS52YWx1ZSAqIGVsZU9wYWNpdHk7XG4gIGNvbnRleHQubGluZUpvaW4gPSAnbWl0ZXInOyAvLyBzbyBib3JkZXJzIGFyZSBzcXVhcmUgd2l0aCB0aGUgbm9kZSBzaGFwZVxuXG4gIHZhciBzZXR1cFNoYXBlQ29sb3IgPSBmdW5jdGlvbiBzZXR1cFNoYXBlQ29sb3IoKSB7XG4gICAgdmFyIGJnT3B5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBiZ09wYWNpdHk7XG4gICAgci5lbGVGaWxsU3R5bGUoY29udGV4dCwgbm9kZSwgYmdPcHkpO1xuICB9O1xuXG4gIHZhciBzZXR1cEJvcmRlckNvbG9yID0gZnVuY3Rpb24gc2V0dXBCb3JkZXJDb2xvcigpIHtcbiAgICB2YXIgYmRyT3B5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBib3JkZXJPcGFjaXR5O1xuICAgIHIuY29sb3JTdHJva2VTdHlsZShjb250ZXh0LCBib3JkZXJDb2xvclswXSwgYm9yZGVyQ29sb3JbMV0sIGJvcmRlckNvbG9yWzJdLCBiZHJPcHkpO1xuICB9OyAvL1xuICAvLyBzZXR1cCBzaGFwZVxuXG5cbiAgdmFyIHN0eWxlU2hhcGUgPSBub2RlLnBzdHlsZSgnc2hhcGUnKS5zdHJWYWx1ZTtcbiAgdmFyIHNoYXBlUHRzID0gbm9kZS5wc3R5bGUoJ3NoYXBlLXBvbHlnb24tcG9pbnRzJykucGZWYWx1ZTtcblxuICBpZiAodXNlUGF0aHMpIHtcbiAgICBjb250ZXh0LnRyYW5zbGF0ZShwb3MueCwgcG9zLnkpO1xuICAgIHZhciBwYXRoQ2FjaGUgPSByLm5vZGVQYXRoQ2FjaGUgPSByLm5vZGVQYXRoQ2FjaGUgfHwgW107XG4gICAgdmFyIGtleSA9IGhhc2hTdHJpbmdzKHN0eWxlU2hhcGUgPT09ICdwb2x5Z29uJyA/IHN0eWxlU2hhcGUgKyAnLCcgKyBzaGFwZVB0cy5qb2luKCcsJykgOiBzdHlsZVNoYXBlLCAnJyArIG5vZGVIZWlnaHQsICcnICsgbm9kZVdpZHRoKTtcbiAgICB2YXIgY2FjaGVkUGF0aCA9IHBhdGhDYWNoZVtrZXldO1xuXG4gICAgaWYgKGNhY2hlZFBhdGggIT0gbnVsbCkge1xuICAgICAgcGF0aCA9IGNhY2hlZFBhdGg7XG4gICAgICBwYXRoQ2FjaGVIaXQgPSB0cnVlO1xuICAgICAgcnMucGF0aENhY2hlID0gcGF0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0aCA9IG5ldyBQYXRoMkQoKTtcbiAgICAgIHBhdGhDYWNoZVtrZXldID0gcnMucGF0aENhY2hlID0gcGF0aDtcbiAgICB9XG4gIH1cblxuICB2YXIgZHJhd1NoYXBlID0gZnVuY3Rpb24gZHJhd1NoYXBlKCkge1xuICAgIGlmICghcGF0aENhY2hlSGl0KSB7XG4gICAgICB2YXIgbnBvcyA9IHBvcztcblxuICAgICAgaWYgKHVzZVBhdGhzKSB7XG4gICAgICAgIG5wb3MgPSB7XG4gICAgICAgICAgeDogMCxcbiAgICAgICAgICB5OiAwXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHIubm9kZVNoYXBlc1tyLmdldE5vZGVTaGFwZShub2RlKV0uZHJhdyhwYXRoIHx8IGNvbnRleHQsIG5wb3MueCwgbnBvcy55LCBub2RlV2lkdGgsIG5vZGVIZWlnaHQpO1xuICAgIH1cblxuICAgIGlmICh1c2VQYXRocykge1xuICAgICAgY29udGV4dC5maWxsKHBhdGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0LmZpbGwoKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGRyYXdJbWFnZXMgPSBmdW5jdGlvbiBkcmF3SW1hZ2VzKCkge1xuICAgIHZhciBub2RlT3BhY2l0eSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZWxlT3BhY2l0eTtcbiAgICB2YXIgcHJldkJnaW5nID0gX3AuYmFja2dyb3VuZGluZztcbiAgICB2YXIgdG90YWxDb21wbGV0ZWQgPSAwO1xuXG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGltYWdlLmxlbmd0aDsgX2krKykge1xuICAgICAgaWYgKHVybERlZmluZWRbX2ldICYmIGltYWdlW19pXS5jb21wbGV0ZSAmJiAhaW1hZ2VbX2ldLmVycm9yKSB7XG4gICAgICAgIHRvdGFsQ29tcGxldGVkKys7XG4gICAgICAgIHIuZHJhd0luc2NyaWJlZEltYWdlKGNvbnRleHQsIGltYWdlW19pXSwgbm9kZSwgX2ksIG5vZGVPcGFjaXR5KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfcC5iYWNrZ3JvdW5kaW5nID0gISh0b3RhbENvbXBsZXRlZCA9PT0gbnVtSW1hZ2VzKTtcblxuICAgIGlmIChwcmV2QmdpbmcgIT09IF9wLmJhY2tncm91bmRpbmcpIHtcbiAgICAgIC8vIHVwZGF0ZSBzdHlsZSBiL2MgOmJhY2tncm91bmRpbmcgc3RhdGUgY2hhbmdlZFxuICAgICAgbm9kZS51cGRhdGVTdHlsZShmYWxzZSk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBkcmF3UGllID0gZnVuY3Rpb24gZHJhd1BpZSgpIHtcbiAgICB2YXIgcmVkcmF3U2hhcGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlO1xuICAgIHZhciBwaWVPcGFjaXR5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBlbGVPcGFjaXR5O1xuXG4gICAgaWYgKHIuaGFzUGllKG5vZGUpKSB7XG4gICAgICByLmRyYXdQaWUoY29udGV4dCwgbm9kZSwgcGllT3BhY2l0eSk7IC8vIHJlZHJhdy9yZXN0b3JlIHBhdGggaWYgc3RlcHMgYWZ0ZXIgcGllIG5lZWQgaXRcblxuICAgICAgaWYgKHJlZHJhd1NoYXBlKSB7XG4gICAgICAgIGlmICghdXNlUGF0aHMpIHtcbiAgICAgICAgICByLm5vZGVTaGFwZXNbci5nZXROb2RlU2hhcGUobm9kZSldLmRyYXcoY29udGV4dCwgcG9zLngsIHBvcy55LCBub2RlV2lkdGgsIG5vZGVIZWlnaHQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHZhciBkYXJrZW4gPSBmdW5jdGlvbiBkYXJrZW4oKSB7XG4gICAgdmFyIGRhcmtlbk9wYWNpdHkgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGVsZU9wYWNpdHk7XG4gICAgdmFyIG9wYWNpdHkgPSAoZGFya25lc3MgPiAwID8gZGFya25lc3MgOiAtZGFya25lc3MpICogZGFya2VuT3BhY2l0eTtcbiAgICB2YXIgYyA9IGRhcmtuZXNzID4gMCA/IDAgOiAyNTU7XG5cbiAgICBpZiAoZGFya25lc3MgIT09IDApIHtcbiAgICAgIHIuY29sb3JGaWxsU3R5bGUoY29udGV4dCwgYywgYywgYywgb3BhY2l0eSk7XG5cbiAgICAgIGlmICh1c2VQYXRocykge1xuICAgICAgICBjb250ZXh0LmZpbGwocGF0aCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZXh0LmZpbGwoKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgdmFyIGRyYXdCb3JkZXIgPSBmdW5jdGlvbiBkcmF3Qm9yZGVyKCkge1xuICAgIGlmIChib3JkZXJXaWR0aCA+IDApIHtcbiAgICAgIGNvbnRleHQubGluZVdpZHRoID0gYm9yZGVyV2lkdGg7XG4gICAgICBjb250ZXh0LmxpbmVDYXAgPSAnYnV0dCc7XG5cbiAgICAgIGlmIChjb250ZXh0LnNldExpbmVEYXNoKSB7XG4gICAgICAgIC8vIGZvciB2ZXJ5IG91dG9mZGF0ZSBicm93c2Vyc1xuICAgICAgICBzd2l0Y2ggKGJvcmRlclN0eWxlKSB7XG4gICAgICAgICAgY2FzZSAnZG90dGVkJzpcbiAgICAgICAgICAgIGNvbnRleHQuc2V0TGluZURhc2goWzEsIDFdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnZGFzaGVkJzpcbiAgICAgICAgICAgIGNvbnRleHQuc2V0TGluZURhc2goWzQsIDJdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnc29saWQnOlxuICAgICAgICAgIGNhc2UgJ2RvdWJsZSc6XG4gICAgICAgICAgICBjb250ZXh0LnNldExpbmVEYXNoKFtdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh1c2VQYXRocykge1xuICAgICAgICBjb250ZXh0LnN0cm9rZShwYXRoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChib3JkZXJTdHlsZSA9PT0gJ2RvdWJsZScpIHtcbiAgICAgICAgY29udGV4dC5saW5lV2lkdGggPSBib3JkZXJXaWR0aCAvIDM7XG4gICAgICAgIHZhciBnY28gPSBjb250ZXh0Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbjtcbiAgICAgICAgY29udGV4dC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSAnZGVzdGluYXRpb24tb3V0JztcblxuICAgICAgICBpZiAodXNlUGF0aHMpIHtcbiAgICAgICAgICBjb250ZXh0LnN0cm9rZShwYXRoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb250ZXh0LnN0cm9rZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGV4dC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSBnY287XG4gICAgICB9IC8vIHJlc2V0IGluIGNhc2Ugd2UgY2hhbmdlZCB0aGUgYm9yZGVyIHN0eWxlXG5cblxuICAgICAgaWYgKGNvbnRleHQuc2V0TGluZURhc2gpIHtcbiAgICAgICAgLy8gZm9yIHZlcnkgb3V0b2ZkYXRlIGJyb3dzZXJzXG4gICAgICAgIGNvbnRleHQuc2V0TGluZURhc2goW10pO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB2YXIgZHJhd092ZXJsYXkgPSBmdW5jdGlvbiBkcmF3T3ZlcmxheSgpIHtcbiAgICBpZiAoc2hvdWxkRHJhd092ZXJsYXkpIHtcbiAgICAgIHIuZHJhd05vZGVPdmVybGF5KGNvbnRleHQsIG5vZGUsIHBvcywgbm9kZVdpZHRoLCBub2RlSGVpZ2h0KTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGRyYXdUZXh0ID0gZnVuY3Rpb24gZHJhd1RleHQoKSB7XG4gICAgci5kcmF3RWxlbWVudFRleHQoY29udGV4dCwgbm9kZSwgbnVsbCwgZHJhd0xhYmVsKTtcbiAgfTtcblxuICB2YXIgZ2hvc3QgPSBub2RlLnBzdHlsZSgnZ2hvc3QnKS52YWx1ZSA9PT0gJ3llcyc7XG5cbiAgaWYgKGdob3N0KSB7XG4gICAgdmFyIGd4ID0gbm9kZS5wc3R5bGUoJ2dob3N0LW9mZnNldC14JykucGZWYWx1ZTtcbiAgICB2YXIgZ3kgPSBub2RlLnBzdHlsZSgnZ2hvc3Qtb2Zmc2V0LXknKS5wZlZhbHVlO1xuICAgIHZhciBnaG9zdE9wYWNpdHkgPSBub2RlLnBzdHlsZSgnZ2hvc3Qtb3BhY2l0eScpLnZhbHVlO1xuICAgIHZhciBlZmZHaG9zdE9wYWNpdHkgPSBnaG9zdE9wYWNpdHkgKiBlbGVPcGFjaXR5O1xuICAgIGNvbnRleHQudHJhbnNsYXRlKGd4LCBneSk7XG4gICAgc2V0dXBTaGFwZUNvbG9yKGdob3N0T3BhY2l0eSAqIGJnT3BhY2l0eSk7XG4gICAgZHJhd1NoYXBlKCk7XG4gICAgZHJhd0ltYWdlcyhlZmZHaG9zdE9wYWNpdHkpO1xuICAgIGRyYXdQaWUoZGFya25lc3MgIT09IDAgfHwgYm9yZGVyV2lkdGggIT09IDApO1xuICAgIGRhcmtlbihlZmZHaG9zdE9wYWNpdHkpO1xuICAgIHNldHVwQm9yZGVyQ29sb3IoZ2hvc3RPcGFjaXR5ICogYm9yZGVyT3BhY2l0eSk7XG4gICAgZHJhd0JvcmRlcigpO1xuICAgIGNvbnRleHQudHJhbnNsYXRlKC1neCwgLWd5KTtcbiAgfVxuXG4gIHNldHVwU2hhcGVDb2xvcigpO1xuICBkcmF3U2hhcGUoKTtcbiAgZHJhd0ltYWdlcygpO1xuICBkcmF3UGllKGRhcmtuZXNzICE9PSAwIHx8IGJvcmRlcldpZHRoICE9PSAwKTtcbiAgZGFya2VuKCk7XG4gIHNldHVwQm9yZGVyQ29sb3IoKTtcbiAgZHJhd0JvcmRlcigpO1xuXG4gIGlmICh1c2VQYXRocykge1xuICAgIGNvbnRleHQudHJhbnNsYXRlKC1wb3MueCwgLXBvcy55KTtcbiAgfVxuXG4gIGRyYXdUZXh0KCk7XG4gIGRyYXdPdmVybGF5KCk7IC8vXG4gIC8vIGNsZWFuIHVwIHNoaWZ0XG5cbiAgaWYgKHNoaWZ0VG9PcmlnaW5XaXRoQmIpIHtcbiAgICBjb250ZXh0LnRyYW5zbGF0ZShiYi54MSwgYmIueTEpO1xuICB9XG59O1xuXG5DUnAkNS5kcmF3Tm9kZU92ZXJsYXkgPSBmdW5jdGlvbiAoY29udGV4dCwgbm9kZSwgcG9zLCBub2RlV2lkdGgsIG5vZGVIZWlnaHQpIHtcbiAgdmFyIHIgPSB0aGlzO1xuXG4gIGlmICghbm9kZS52aXNpYmxlKCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgb3ZlcmxheVBhZGRpbmcgPSBub2RlLnBzdHlsZSgnb3ZlcmxheS1wYWRkaW5nJykucGZWYWx1ZTtcbiAgdmFyIG92ZXJsYXlPcGFjaXR5ID0gbm9kZS5wc3R5bGUoJ292ZXJsYXktb3BhY2l0eScpLnZhbHVlO1xuICB2YXIgb3ZlcmxheUNvbG9yID0gbm9kZS5wc3R5bGUoJ292ZXJsYXktY29sb3InKS52YWx1ZTtcblxuICBpZiAob3ZlcmxheU9wYWNpdHkgPiAwKSB7XG4gICAgcG9zID0gcG9zIHx8IG5vZGUucG9zaXRpb24oKTtcblxuICAgIGlmIChub2RlV2lkdGggPT0gbnVsbCB8fCBub2RlSGVpZ2h0ID09IG51bGwpIHtcbiAgICAgIHZhciBwYWRkaW5nID0gbm9kZS5wYWRkaW5nKCk7XG4gICAgICBub2RlV2lkdGggPSBub2RlLndpZHRoKCkgKyAyICogcGFkZGluZztcbiAgICAgIG5vZGVIZWlnaHQgPSBub2RlLmhlaWdodCgpICsgMiAqIHBhZGRpbmc7XG4gICAgfVxuXG4gICAgci5jb2xvckZpbGxTdHlsZShjb250ZXh0LCBvdmVybGF5Q29sb3JbMF0sIG92ZXJsYXlDb2xvclsxXSwgb3ZlcmxheUNvbG9yWzJdLCBvdmVybGF5T3BhY2l0eSk7XG4gICAgci5ub2RlU2hhcGVzWydyb3VuZHJlY3RhbmdsZSddLmRyYXcoY29udGV4dCwgcG9zLngsIHBvcy55LCBub2RlV2lkdGggKyBvdmVybGF5UGFkZGluZyAqIDIsIG5vZGVIZWlnaHQgKyBvdmVybGF5UGFkZGluZyAqIDIpO1xuICAgIGNvbnRleHQuZmlsbCgpO1xuICB9XG59OyAvLyBkb2VzIHRoZSBub2RlIGhhdmUgYXQgbGVhc3Qgb25lIHBpZSBwaWVjZT9cblxuXG5DUnAkNS5oYXNQaWUgPSBmdW5jdGlvbiAobm9kZSkge1xuICBub2RlID0gbm9kZVswXTsgLy8gZW5zdXJlIGVsZSByZWZcblxuICByZXR1cm4gbm9kZS5fcHJpdmF0ZS5oYXNQaWU7XG59O1xuXG5DUnAkNS5kcmF3UGllID0gZnVuY3Rpb24gKGNvbnRleHQsIG5vZGUsIG5vZGVPcGFjaXR5LCBwb3MpIHtcbiAgbm9kZSA9IG5vZGVbMF07IC8vIGVuc3VyZSBlbGUgcmVmXG5cbiAgcG9zID0gcG9zIHx8IG5vZGUucG9zaXRpb24oKTtcbiAgdmFyIGN5U3R5bGUgPSBub2RlLmN5KCkuc3R5bGUoKTtcbiAgdmFyIHBpZVNpemUgPSBub2RlLnBzdHlsZSgncGllLXNpemUnKTtcbiAgdmFyIHggPSBwb3MueDtcbiAgdmFyIHkgPSBwb3MueTtcbiAgdmFyIG5vZGVXID0gbm9kZS53aWR0aCgpO1xuICB2YXIgbm9kZUggPSBub2RlLmhlaWdodCgpO1xuICB2YXIgcmFkaXVzID0gTWF0aC5taW4obm9kZVcsIG5vZGVIKSAvIDI7IC8vIG11c3QgZml0IGluIG5vZGVcblxuICB2YXIgbGFzdFBlcmNlbnQgPSAwOyAvLyB3aGF0ICUgdG8gY29udGludWUgZHJhd2luZyBwaWUgc2xpY2VzIGZyb20gb24gWzAsIDFdXG5cbiAgdmFyIHVzZVBhdGhzID0gdGhpcy51c2VQYXRocygpO1xuXG4gIGlmICh1c2VQYXRocykge1xuICAgIHggPSAwO1xuICAgIHkgPSAwO1xuICB9XG5cbiAgaWYgKHBpZVNpemUudW5pdHMgPT09ICclJykge1xuICAgIHJhZGl1cyA9IHJhZGl1cyAqIHBpZVNpemUucGZWYWx1ZTtcbiAgfSBlbHNlIGlmIChwaWVTaXplLnBmVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgIHJhZGl1cyA9IHBpZVNpemUucGZWYWx1ZSAvIDI7XG4gIH1cblxuICBmb3IgKHZhciBpID0gMTsgaSA8PSBjeVN0eWxlLnBpZUJhY2tncm91bmROOyBpKyspIHtcbiAgICAvLyAxLi5OXG4gICAgdmFyIHNpemUgPSBub2RlLnBzdHlsZSgncGllLScgKyBpICsgJy1iYWNrZ3JvdW5kLXNpemUnKS52YWx1ZTtcbiAgICB2YXIgY29sb3IgPSBub2RlLnBzdHlsZSgncGllLScgKyBpICsgJy1iYWNrZ3JvdW5kLWNvbG9yJykudmFsdWU7XG4gICAgdmFyIG9wYWNpdHkgPSBub2RlLnBzdHlsZSgncGllLScgKyBpICsgJy1iYWNrZ3JvdW5kLW9wYWNpdHknKS52YWx1ZSAqIG5vZGVPcGFjaXR5O1xuICAgIHZhciBwZXJjZW50ID0gc2l6ZSAvIDEwMDsgLy8gbWFwIGludGVnZXIgcmFuZ2UgWzAsIDEwMF0gdG8gWzAsIDFdXG4gICAgLy8gcGVyY2VudCBjYW4ndCBwdXNoIGJleW9uZCAxXG5cbiAgICBpZiAocGVyY2VudCArIGxhc3RQZXJjZW50ID4gMSkge1xuICAgICAgcGVyY2VudCA9IDEgLSBsYXN0UGVyY2VudDtcbiAgICB9XG5cbiAgICB2YXIgYW5nbGVTdGFydCA9IDEuNSAqIE1hdGguUEkgKyAyICogTWF0aC5QSSAqIGxhc3RQZXJjZW50OyAvLyBzdGFydCBhdCAxMiBvJ2Nsb2NrIGFuZCBnbyBjbG9ja3dpc2VcblxuICAgIHZhciBhbmdsZURlbHRhID0gMiAqIE1hdGguUEkgKiBwZXJjZW50O1xuICAgIHZhciBhbmdsZUVuZCA9IGFuZ2xlU3RhcnQgKyBhbmdsZURlbHRhOyAvLyBpZ25vcmUgaWZcbiAgICAvLyAtIHplcm8gc2l6ZVxuICAgIC8vIC0gd2UncmUgYWxyZWFkeSBiZXlvbmQgdGhlIGZ1bGwgY2lyY2xlXG4gICAgLy8gLSBhZGRpbmcgdGhlIGN1cnJlbnQgc2xpY2Ugd291bGQgZ28gYmV5b25kIHRoZSBmdWxsIGNpcmNsZVxuXG4gICAgaWYgKHNpemUgPT09IDAgfHwgbGFzdFBlcmNlbnQgPj0gMSB8fCBsYXN0UGVyY2VudCArIHBlcmNlbnQgPiAxKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgIGNvbnRleHQubW92ZVRvKHgsIHkpO1xuICAgIGNvbnRleHQuYXJjKHgsIHksIHJhZGl1cywgYW5nbGVTdGFydCwgYW5nbGVFbmQpO1xuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgdGhpcy5jb2xvckZpbGxTdHlsZShjb250ZXh0LCBjb2xvclswXSwgY29sb3JbMV0sIGNvbG9yWzJdLCBvcGFjaXR5KTtcbiAgICBjb250ZXh0LmZpbGwoKTtcbiAgICBsYXN0UGVyY2VudCArPSBwZXJjZW50O1xuICB9XG59O1xuXG52YXIgQ1JwJDYgPSB7fTtcbnZhciBtb3Rpb25CbHVyRGVsYXkgPSAxMDA7IC8vIHZhciBpc0ZpcmVmb3ggPSB0eXBlb2YgSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xuXG5DUnAkNi5nZXRQaXhlbFJhdGlvID0gZnVuY3Rpb24gKCkge1xuICB2YXIgY29udGV4dCA9IHRoaXMuZGF0YS5jb250ZXh0c1swXTtcblxuICBpZiAodGhpcy5mb3JjZWRQaXhlbFJhdGlvICE9IG51bGwpIHtcbiAgICByZXR1cm4gdGhpcy5mb3JjZWRQaXhlbFJhdGlvO1xuICB9XG5cbiAgdmFyIGJhY2tpbmdTdG9yZSA9IGNvbnRleHQuYmFja2luZ1N0b3JlUGl4ZWxSYXRpbyB8fCBjb250ZXh0LndlYmtpdEJhY2tpbmdTdG9yZVBpeGVsUmF0aW8gfHwgY29udGV4dC5tb3pCYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8IGNvbnRleHQubXNCYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8IGNvbnRleHQub0JhY2tpbmdTdG9yZVBpeGVsUmF0aW8gfHwgY29udGV4dC5iYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8IDE7XG4gIHJldHVybiAod2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgMSkgLyBiYWNraW5nU3RvcmU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbn07XG5cbkNScCQ2LnBhaW50Q2FjaGUgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICB2YXIgY2FjaGVzID0gdGhpcy5wYWludENhY2hlcyA9IHRoaXMucGFpbnRDYWNoZXMgfHwgW107XG4gIHZhciBuZWVkVG9DcmVhdGVDYWNoZSA9IHRydWU7XG4gIHZhciBjYWNoZTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNhY2hlcy5sZW5ndGg7IGkrKykge1xuICAgIGNhY2hlID0gY2FjaGVzW2ldO1xuXG4gICAgaWYgKGNhY2hlLmNvbnRleHQgPT09IGNvbnRleHQpIHtcbiAgICAgIG5lZWRUb0NyZWF0ZUNhY2hlID0gZmFsc2U7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBpZiAobmVlZFRvQ3JlYXRlQ2FjaGUpIHtcbiAgICBjYWNoZSA9IHtcbiAgICAgIGNvbnRleHQ6IGNvbnRleHRcbiAgICB9O1xuICAgIGNhY2hlcy5wdXNoKGNhY2hlKTtcbiAgfVxuXG4gIHJldHVybiBjYWNoZTtcbn07XG5cbkNScCQ2LmNyZWF0ZUdyYWRpZW50U3R5bGVGb3IgPSBmdW5jdGlvbiAoY29udGV4dCwgc2hhcGVTdHlsZU5hbWUsIGVsZSwgZmlsbCwgb3BhY2l0eSkge1xuICB2YXIgZ3JhZGllbnRTdHlsZTtcbiAgdmFyIHVzZVBhdGhzID0gdGhpcy51c2VQYXRocygpO1xuICB2YXIgY29sb3JzID0gZWxlLnBzdHlsZShzaGFwZVN0eWxlTmFtZSArICctZ3JhZGllbnQtc3RvcC1jb2xvcnMnKS52YWx1ZSxcbiAgICAgIHBvc2l0aW9ucyA9IGVsZS5wc3R5bGUoc2hhcGVTdHlsZU5hbWUgKyAnLWdyYWRpZW50LXN0b3AtcG9zaXRpb25zJykucGZWYWx1ZTtcblxuICBpZiAoZmlsbCA9PT0gJ3JhZGlhbC1ncmFkaWVudCcpIHtcbiAgICBpZiAoZWxlLmlzRWRnZSgpKSB7XG4gICAgICB2YXIgc3RhcnQgPSBlbGUuc291cmNlRW5kcG9pbnQoKSxcbiAgICAgICAgICBlbmQgPSBlbGUudGFyZ2V0RW5kcG9pbnQoKSxcbiAgICAgICAgICBtaWQgPSBlbGUubWlkcG9pbnQoKTtcbiAgICAgIHZhciBkMSA9IGRpc3Qoc3RhcnQsIG1pZCk7XG4gICAgICB2YXIgZDIgPSBkaXN0KGVuZCwgbWlkKTtcbiAgICAgIGdyYWRpZW50U3R5bGUgPSBjb250ZXh0LmNyZWF0ZVJhZGlhbEdyYWRpZW50KG1pZC54LCBtaWQueSwgMCwgbWlkLngsIG1pZC55LCBNYXRoLm1heChkMSwgZDIpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHBvcyA9IHVzZVBhdGhzID8ge1xuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwXG4gICAgICB9IDogZWxlLnBvc2l0aW9uKCksXG4gICAgICAgICAgd2lkdGggPSBlbGUucGFkZGVkV2lkdGgoKSxcbiAgICAgICAgICBoZWlnaHQgPSBlbGUucGFkZGVkSGVpZ2h0KCk7XG4gICAgICBncmFkaWVudFN0eWxlID0gY29udGV4dC5jcmVhdGVSYWRpYWxHcmFkaWVudChwb3MueCwgcG9zLnksIDAsIHBvcy54LCBwb3MueSwgTWF0aC5tYXgod2lkdGgsIGhlaWdodCkpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoZWxlLmlzRWRnZSgpKSB7XG4gICAgICB2YXIgX3N0YXJ0ID0gZWxlLnNvdXJjZUVuZHBvaW50KCksXG4gICAgICAgICAgX2VuZCA9IGVsZS50YXJnZXRFbmRwb2ludCgpO1xuXG4gICAgICBncmFkaWVudFN0eWxlID0gY29udGV4dC5jcmVhdGVMaW5lYXJHcmFkaWVudChfc3RhcnQueCwgX3N0YXJ0LnksIF9lbmQueCwgX2VuZC55KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIF9wb3MgPSB1c2VQYXRocyA/IHtcbiAgICAgICAgeDogMCxcbiAgICAgICAgeTogMFxuICAgICAgfSA6IGVsZS5wb3NpdGlvbigpLFxuICAgICAgICAgIF93aWR0aCA9IGVsZS5wYWRkZWRXaWR0aCgpLFxuICAgICAgICAgIF9oZWlnaHQgPSBlbGUucGFkZGVkSGVpZ2h0KCksXG4gICAgICAgICAgaGFsZldpZHRoID0gX3dpZHRoIC8gMixcbiAgICAgICAgICBoYWxmSGVpZ2h0ID0gX2hlaWdodCAvIDI7XG5cbiAgICAgIHZhciBkaXJlY3Rpb24gPSBlbGUucHN0eWxlKCdiYWNrZ3JvdW5kLWdyYWRpZW50LWRpcmVjdGlvbicpLnZhbHVlO1xuXG4gICAgICBzd2l0Y2ggKGRpcmVjdGlvbikge1xuICAgICAgICBjYXNlICd0by1ib3R0b20nOlxuICAgICAgICAgIGdyYWRpZW50U3R5bGUgPSBjb250ZXh0LmNyZWF0ZUxpbmVhckdyYWRpZW50KF9wb3MueCwgX3Bvcy55IC0gaGFsZkhlaWdodCwgX3Bvcy54LCBfcG9zLnkgKyBoYWxmSGVpZ2h0KTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICd0by10b3AnOlxuICAgICAgICAgIGdyYWRpZW50U3R5bGUgPSBjb250ZXh0LmNyZWF0ZUxpbmVhckdyYWRpZW50KF9wb3MueCwgX3Bvcy55ICsgaGFsZkhlaWdodCwgX3Bvcy54LCBfcG9zLnkgLSBoYWxmSGVpZ2h0KTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICd0by1sZWZ0JzpcbiAgICAgICAgICBncmFkaWVudFN0eWxlID0gY29udGV4dC5jcmVhdGVMaW5lYXJHcmFkaWVudChfcG9zLnggKyBoYWxmV2lkdGgsIF9wb3MueSwgX3Bvcy54IC0gaGFsZldpZHRoLCBfcG9zLnkpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3RvLXJpZ2h0JzpcbiAgICAgICAgICBncmFkaWVudFN0eWxlID0gY29udGV4dC5jcmVhdGVMaW5lYXJHcmFkaWVudChfcG9zLnggLSBoYWxmV2lkdGgsIF9wb3MueSwgX3Bvcy54ICsgaGFsZldpZHRoLCBfcG9zLnkpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3RvLWJvdHRvbS1yaWdodCc6XG4gICAgICAgIGNhc2UgJ3RvLXJpZ2h0LWJvdHRvbSc6XG4gICAgICAgICAgZ3JhZGllbnRTdHlsZSA9IGNvbnRleHQuY3JlYXRlTGluZWFyR3JhZGllbnQoX3Bvcy54IC0gaGFsZldpZHRoLCBfcG9zLnkgLSBoYWxmSGVpZ2h0LCBfcG9zLnggKyBoYWxmV2lkdGgsIF9wb3MueSArIGhhbGZIZWlnaHQpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3RvLXRvcC1yaWdodCc6XG4gICAgICAgIGNhc2UgJ3RvLXJpZ2h0LXRvcCc6XG4gICAgICAgICAgZ3JhZGllbnRTdHlsZSA9IGNvbnRleHQuY3JlYXRlTGluZWFyR3JhZGllbnQoX3Bvcy54IC0gaGFsZldpZHRoLCBfcG9zLnkgKyBoYWxmSGVpZ2h0LCBfcG9zLnggKyBoYWxmV2lkdGgsIF9wb3MueSAtIGhhbGZIZWlnaHQpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3RvLWJvdHRvbS1sZWZ0JzpcbiAgICAgICAgY2FzZSAndG8tbGVmdC1ib3R0b20nOlxuICAgICAgICAgIGdyYWRpZW50U3R5bGUgPSBjb250ZXh0LmNyZWF0ZUxpbmVhckdyYWRpZW50KF9wb3MueCArIGhhbGZXaWR0aCwgX3Bvcy55IC0gaGFsZkhlaWdodCwgX3Bvcy54IC0gaGFsZldpZHRoLCBfcG9zLnkgKyBoYWxmSGVpZ2h0KTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICd0by10b3AtbGVmdCc6XG4gICAgICAgIGNhc2UgJ3RvLWxlZnQtdG9wJzpcbiAgICAgICAgICBncmFkaWVudFN0eWxlID0gY29udGV4dC5jcmVhdGVMaW5lYXJHcmFkaWVudChfcG9zLnggKyBoYWxmV2lkdGgsIF9wb3MueSArIGhhbGZIZWlnaHQsIF9wb3MueCAtIGhhbGZXaWR0aCwgX3Bvcy55IC0gaGFsZkhlaWdodCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKCFncmFkaWVudFN0eWxlKSByZXR1cm4gbnVsbDsgLy8gaW52YWxpZCBncmFkaWVudCBzdHlsZVxuXG4gIHZhciBoYXNQb3NpdGlvbnMgPSBwb3NpdGlvbnMubGVuZ3RoID09PSBjb2xvcnMubGVuZ3RoO1xuICB2YXIgbGVuZ3RoID0gY29sb3JzLmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgZ3JhZGllbnRTdHlsZS5hZGRDb2xvclN0b3AoaGFzUG9zaXRpb25zID8gcG9zaXRpb25zW2ldIDogaSAvIChsZW5ndGggLSAxKSwgJ3JnYmEoJyArIGNvbG9yc1tpXVswXSArICcsJyArIGNvbG9yc1tpXVsxXSArICcsJyArIGNvbG9yc1tpXVsyXSArICcsJyArIG9wYWNpdHkgKyAnKScpO1xuICB9XG5cbiAgcmV0dXJuIGdyYWRpZW50U3R5bGU7XG59O1xuXG5DUnAkNi5ncmFkaWVudEZpbGxTdHlsZSA9IGZ1bmN0aW9uIChjb250ZXh0LCBlbGUsIGZpbGwsIG9wYWNpdHkpIHtcbiAgdmFyIGdyYWRpZW50U3R5bGUgPSB0aGlzLmNyZWF0ZUdyYWRpZW50U3R5bGVGb3IoY29udGV4dCwgJ2JhY2tncm91bmQnLCBlbGUsIGZpbGwsIG9wYWNpdHkpO1xuICBpZiAoIWdyYWRpZW50U3R5bGUpIHJldHVybiBudWxsOyAvLyBlcnJvclxuXG4gIGNvbnRleHQuZmlsbFN0eWxlID0gZ3JhZGllbnRTdHlsZTtcbn07XG5cbkNScCQ2LmNvbG9yRmlsbFN0eWxlID0gZnVuY3Rpb24gKGNvbnRleHQsIHIsIGcsIGIsIGEpIHtcbiAgY29udGV4dC5maWxsU3R5bGUgPSAncmdiYSgnICsgciArICcsJyArIGcgKyAnLCcgKyBiICsgJywnICsgYSArICcpJzsgLy8gdHVybiBvZmYgZm9yIG5vdywgc2VlbXMgY29udGV4dCBkb2VzIGl0cyBvd24gY2FjaGluZ1xuICAvLyB2YXIgY2FjaGUgPSB0aGlzLnBhaW50Q2FjaGUoY29udGV4dCk7XG4gIC8vIHZhciBmaWxsU3R5bGUgPSAncmdiYSgnICsgciArICcsJyArIGcgKyAnLCcgKyBiICsgJywnICsgYSArICcpJztcbiAgLy8gaWYoIGNhY2hlLmZpbGxTdHlsZSAhPT0gZmlsbFN0eWxlICl7XG4gIC8vICAgY29udGV4dC5maWxsU3R5bGUgPSBjYWNoZS5maWxsU3R5bGUgPSBmaWxsU3R5bGU7XG4gIC8vIH1cbn07XG5cbkNScCQ2LmVsZUZpbGxTdHlsZSA9IGZ1bmN0aW9uIChjb250ZXh0LCBlbGUsIG9wYWNpdHkpIHtcbiAgdmFyIGJhY2tncm91bmRGaWxsID0gZWxlLnBzdHlsZSgnYmFja2dyb3VuZC1maWxsJykudmFsdWU7XG5cbiAgaWYgKGJhY2tncm91bmRGaWxsID09PSAnbGluZWFyLWdyYWRpZW50JyB8fCBiYWNrZ3JvdW5kRmlsbCA9PT0gJ3JhZGlhbC1ncmFkaWVudCcpIHtcbiAgICB0aGlzLmdyYWRpZW50RmlsbFN0eWxlKGNvbnRleHQsIGVsZSwgYmFja2dyb3VuZEZpbGwsIG9wYWNpdHkpO1xuICB9IGVsc2Uge1xuICAgIHZhciBiYWNrZ3JvdW5kQ29sb3IgPSBlbGUucHN0eWxlKCdiYWNrZ3JvdW5kLWNvbG9yJykudmFsdWU7XG4gICAgdGhpcy5jb2xvckZpbGxTdHlsZShjb250ZXh0LCBiYWNrZ3JvdW5kQ29sb3JbMF0sIGJhY2tncm91bmRDb2xvclsxXSwgYmFja2dyb3VuZENvbG9yWzJdLCBvcGFjaXR5KTtcbiAgfVxufTtcblxuQ1JwJDYuZ3JhZGllbnRTdHJva2VTdHlsZSA9IGZ1bmN0aW9uIChjb250ZXh0LCBlbGUsIGZpbGwsIG9wYWNpdHkpIHtcbiAgdmFyIGdyYWRpZW50U3R5bGUgPSB0aGlzLmNyZWF0ZUdyYWRpZW50U3R5bGVGb3IoY29udGV4dCwgJ2xpbmUnLCBlbGUsIGZpbGwsIG9wYWNpdHkpO1xuICBpZiAoIWdyYWRpZW50U3R5bGUpIHJldHVybiBudWxsOyAvLyBlcnJvclxuXG4gIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSBncmFkaWVudFN0eWxlO1xufTtcblxuQ1JwJDYuY29sb3JTdHJva2VTdHlsZSA9IGZ1bmN0aW9uIChjb250ZXh0LCByLCBnLCBiLCBhKSB7XG4gIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSAncmdiYSgnICsgciArICcsJyArIGcgKyAnLCcgKyBiICsgJywnICsgYSArICcpJzsgLy8gdHVybiBvZmYgZm9yIG5vdywgc2VlbXMgY29udGV4dCBkb2VzIGl0cyBvd24gY2FjaGluZ1xuICAvLyB2YXIgY2FjaGUgPSB0aGlzLnBhaW50Q2FjaGUoY29udGV4dCk7XG4gIC8vIHZhciBzdHJva2VTdHlsZSA9ICdyZ2JhKCcgKyByICsgJywnICsgZyArICcsJyArIGIgKyAnLCcgKyBhICsgJyknO1xuICAvLyBpZiggY2FjaGUuc3Ryb2tlU3R5bGUgIT09IHN0cm9rZVN0eWxlICl7XG4gIC8vICAgY29udGV4dC5zdHJva2VTdHlsZSA9IGNhY2hlLnN0cm9rZVN0eWxlID0gc3Ryb2tlU3R5bGU7XG4gIC8vIH1cbn07XG5cbkNScCQ2LmVsZVN0cm9rZVN0eWxlID0gZnVuY3Rpb24gKGNvbnRleHQsIGVsZSwgb3BhY2l0eSkge1xuICB2YXIgbGluZUZpbGwgPSBlbGUucHN0eWxlKCdsaW5lLWZpbGwnKS52YWx1ZTtcblxuICBpZiAobGluZUZpbGwgPT09ICdsaW5lYXItZ3JhZGllbnQnIHx8IGxpbmVGaWxsID09PSAncmFkaWFsLWdyYWRpZW50Jykge1xuICAgIHRoaXMuZ3JhZGllbnRTdHJva2VTdHlsZShjb250ZXh0LCBlbGUsIGxpbmVGaWxsLCBvcGFjaXR5KTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgbGluZUNvbG9yID0gZWxlLnBzdHlsZSgnbGluZS1jb2xvcicpLnZhbHVlO1xuICAgIHRoaXMuY29sb3JTdHJva2VTdHlsZShjb250ZXh0LCBsaW5lQ29sb3JbMF0sIGxpbmVDb2xvclsxXSwgbGluZUNvbG9yWzJdLCBvcGFjaXR5KTtcbiAgfVxufTsgLy8gUmVzaXplIGNhbnZhc1xuXG5cbkNScCQ2Lm1hdGNoQ2FudmFzU2l6ZSA9IGZ1bmN0aW9uIChjb250YWluZXIpIHtcbiAgdmFyIHIgPSB0aGlzO1xuICB2YXIgZGF0YSA9IHIuZGF0YTtcbiAgdmFyIGJiID0gci5maW5kQ29udGFpbmVyQ2xpZW50Q29vcmRzKCk7XG4gIHZhciB3aWR0aCA9IGJiWzJdO1xuICB2YXIgaGVpZ2h0ID0gYmJbM107XG4gIHZhciBwaXhlbFJhdGlvID0gci5nZXRQaXhlbFJhdGlvKCk7XG4gIHZhciBtYlB4UmF0aW8gPSByLm1vdGlvbkJsdXJQeFJhdGlvO1xuXG4gIGlmIChjb250YWluZXIgPT09IHIuZGF0YS5idWZmZXJDYW52YXNlc1tyLk1PVElPTkJMVVJfQlVGRkVSX05PREVdIHx8IGNvbnRhaW5lciA9PT0gci5kYXRhLmJ1ZmZlckNhbnZhc2VzW3IuTU9USU9OQkxVUl9CVUZGRVJfRFJBR10pIHtcbiAgICBwaXhlbFJhdGlvID0gbWJQeFJhdGlvO1xuICB9XG5cbiAgdmFyIGNhbnZhc1dpZHRoID0gd2lkdGggKiBwaXhlbFJhdGlvO1xuICB2YXIgY2FudmFzSGVpZ2h0ID0gaGVpZ2h0ICogcGl4ZWxSYXRpbztcbiAgdmFyIGNhbnZhcztcblxuICBpZiAoY2FudmFzV2lkdGggPT09IHIuY2FudmFzV2lkdGggJiYgY2FudmFzSGVpZ2h0ID09PSByLmNhbnZhc0hlaWdodCkge1xuICAgIHJldHVybjsgLy8gc2F2ZSBjeWNsZXMgaWYgc2FtZVxuICB9XG5cbiAgci5mb250Q2FjaGVzID0gbnVsbDsgLy8gcmVzaXppbmcgcmVzZXRzIHRoZSBzdHlsZVxuXG4gIHZhciBjYW52YXNDb250YWluZXIgPSBkYXRhLmNhbnZhc0NvbnRhaW5lcjtcbiAgY2FudmFzQ29udGFpbmVyLnN0eWxlLndpZHRoID0gd2lkdGggKyAncHgnO1xuICBjYW52YXNDb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgJ3B4JztcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHIuQ0FOVkFTX0xBWUVSUzsgaSsrKSB7XG4gICAgY2FudmFzID0gZGF0YS5jYW52YXNlc1tpXTtcbiAgICBjYW52YXMud2lkdGggPSBjYW52YXNXaWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gY2FudmFzSGVpZ2h0O1xuICAgIGNhbnZhcy5zdHlsZS53aWR0aCA9IHdpZHRoICsgJ3B4JztcbiAgICBjYW52YXMuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgJ3B4JztcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgci5CVUZGRVJfQ09VTlQ7IGkrKykge1xuICAgIGNhbnZhcyA9IGRhdGEuYnVmZmVyQ2FudmFzZXNbaV07XG4gICAgY2FudmFzLndpZHRoID0gY2FudmFzV2lkdGg7XG4gICAgY2FudmFzLmhlaWdodCA9IGNhbnZhc0hlaWdodDtcbiAgICBjYW52YXMuc3R5bGUud2lkdGggPSB3aWR0aCArICdweCc7XG4gICAgY2FudmFzLnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG4gIH1cblxuICByLnRleHR1cmVNdWx0ID0gMTtcblxuICBpZiAocGl4ZWxSYXRpbyA8PSAxKSB7XG4gICAgY2FudmFzID0gZGF0YS5idWZmZXJDYW52YXNlc1tyLlRFWFRVUkVfQlVGRkVSXTtcbiAgICByLnRleHR1cmVNdWx0ID0gMjtcbiAgICBjYW52YXMud2lkdGggPSBjYW52YXNXaWR0aCAqIHIudGV4dHVyZU11bHQ7XG4gICAgY2FudmFzLmhlaWdodCA9IGNhbnZhc0hlaWdodCAqIHIudGV4dHVyZU11bHQ7XG4gIH1cblxuICByLmNhbnZhc1dpZHRoID0gY2FudmFzV2lkdGg7XG4gIHIuY2FudmFzSGVpZ2h0ID0gY2FudmFzSGVpZ2h0O1xufTtcblxuQ1JwJDYucmVuZGVyVG8gPSBmdW5jdGlvbiAoY3h0LCB6b29tLCBwYW4sIHB4UmF0aW8pIHtcbiAgdGhpcy5yZW5kZXIoe1xuICAgIGZvcmNlZENvbnRleHQ6IGN4dCxcbiAgICBmb3JjZWRab29tOiB6b29tLFxuICAgIGZvcmNlZFBhbjogcGFuLFxuICAgIGRyYXdBbGxMYXllcnM6IHRydWUsXG4gICAgZm9yY2VkUHhSYXRpbzogcHhSYXRpb1xuICB9KTtcbn07XG5cbkNScCQ2LnJlbmRlciA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHN0YXRpY0VtcHR5T2JqZWN0KCk7XG4gIHZhciBmb3JjZWRDb250ZXh0ID0gb3B0aW9ucy5mb3JjZWRDb250ZXh0O1xuICB2YXIgZHJhd0FsbExheWVycyA9IG9wdGlvbnMuZHJhd0FsbExheWVycztcbiAgdmFyIGRyYXdPbmx5Tm9kZUxheWVyID0gb3B0aW9ucy5kcmF3T25seU5vZGVMYXllcjtcbiAgdmFyIGZvcmNlZFpvb20gPSBvcHRpb25zLmZvcmNlZFpvb207XG4gIHZhciBmb3JjZWRQYW4gPSBvcHRpb25zLmZvcmNlZFBhbjtcbiAgdmFyIHIgPSB0aGlzO1xuICB2YXIgcGl4ZWxSYXRpbyA9IG9wdGlvbnMuZm9yY2VkUHhSYXRpbyA9PT0gdW5kZWZpbmVkID8gdGhpcy5nZXRQaXhlbFJhdGlvKCkgOiBvcHRpb25zLmZvcmNlZFB4UmF0aW87XG4gIHZhciBjeSA9IHIuY3k7XG4gIHZhciBkYXRhID0gci5kYXRhO1xuICB2YXIgbmVlZERyYXcgPSBkYXRhLmNhbnZhc05lZWRzUmVkcmF3O1xuICB2YXIgdGV4dHVyZURyYXcgPSByLnRleHR1cmVPblZpZXdwb3J0ICYmICFmb3JjZWRDb250ZXh0ICYmIChyLnBpbmNoaW5nIHx8IHIuaG92ZXJEYXRhLmRyYWdnaW5nIHx8IHIuc3dpcGVQYW5uaW5nIHx8IHIuZGF0YS53aGVlbFpvb21pbmcpO1xuICB2YXIgbW90aW9uQmx1ciA9IG9wdGlvbnMubW90aW9uQmx1ciAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5tb3Rpb25CbHVyIDogci5tb3Rpb25CbHVyO1xuICB2YXIgbWJQeFJhdGlvID0gci5tb3Rpb25CbHVyUHhSYXRpbztcbiAgdmFyIGhhc0NvbXBvdW5kTm9kZXMgPSBjeS5oYXNDb21wb3VuZE5vZGVzKCk7XG4gIHZhciBpbk5vZGVEcmFnR2VzdHVyZSA9IHIuaG92ZXJEYXRhLmRyYWdnaW5nRWxlcztcbiAgdmFyIGluQm94U2VsZWN0aW9uID0gci5ob3ZlckRhdGEuc2VsZWN0aW5nIHx8IHIudG91Y2hEYXRhLnNlbGVjdGluZyA/IHRydWUgOiBmYWxzZTtcbiAgbW90aW9uQmx1ciA9IG1vdGlvbkJsdXIgJiYgIWZvcmNlZENvbnRleHQgJiYgci5tb3Rpb25CbHVyRW5hYmxlZCAmJiAhaW5Cb3hTZWxlY3Rpb247XG4gIHZhciBtb3Rpb25CbHVyRmFkZUVmZmVjdCA9IG1vdGlvbkJsdXI7XG5cbiAgaWYgKCFmb3JjZWRDb250ZXh0KSB7XG4gICAgaWYgKHIucHJldlB4UmF0aW8gIT09IHBpeGVsUmF0aW8pIHtcbiAgICAgIHIuaW52YWxpZGF0ZUNvbnRhaW5lckNsaWVudENvb3Jkc0NhY2hlKCk7XG4gICAgICByLm1hdGNoQ2FudmFzU2l6ZShyLmNvbnRhaW5lcik7XG4gICAgICByLnJlZHJhd0hpbnQoJ2VsZXMnLCB0cnVlKTtcbiAgICAgIHIucmVkcmF3SGludCgnZHJhZycsIHRydWUpO1xuICAgIH1cblxuICAgIHIucHJldlB4UmF0aW8gPSBwaXhlbFJhdGlvO1xuICB9XG5cbiAgaWYgKCFmb3JjZWRDb250ZXh0ICYmIHIubW90aW9uQmx1clRpbWVvdXQpIHtcbiAgICBjbGVhclRpbWVvdXQoci5tb3Rpb25CbHVyVGltZW91dCk7XG4gIH1cblxuICBpZiAobW90aW9uQmx1cikge1xuICAgIGlmIChyLm1iRnJhbWVzID09IG51bGwpIHtcbiAgICAgIHIubWJGcmFtZXMgPSAwO1xuICAgIH1cblxuICAgIHIubWJGcmFtZXMrKztcblxuICAgIGlmIChyLm1iRnJhbWVzIDwgMykge1xuICAgICAgLy8gbmVlZCBzZXZlcmFsIGZyYW1lcyBiZWZvcmUgZXZlbiBoaWdoIHF1YWxpdHkgbW90aW9uYmx1clxuICAgICAgbW90aW9uQmx1ckZhZGVFZmZlY3QgPSBmYWxzZTtcbiAgICB9IC8vIGdvIHRvIGxvd2VyIHF1YWxpdHkgYmx1cnJ5IGZyYW1lcyB3aGVuIHNldmVyYWwgbS9iIGZyYW1lcyBoYXZlIGJlZW4gcmVuZGVyZWQgKGF2b2lkcyBmbGFzaGluZylcblxuXG4gICAgaWYgKHIubWJGcmFtZXMgPiByLm1pbk1iTG93UXVhbEZyYW1lcykge1xuICAgICAgLy9yLmZ1bGxRdWFsaXR5TWIgPSBmYWxzZTtcbiAgICAgIHIubW90aW9uQmx1clB4UmF0aW8gPSByLm1iUHhSQmx1cnJ5O1xuICAgIH1cbiAgfVxuXG4gIGlmIChyLmNsZWFyaW5nTW90aW9uQmx1cikge1xuICAgIHIubW90aW9uQmx1clB4UmF0aW8gPSAxO1xuICB9IC8vIGIvYyBkcmF3VG9Db250ZXh0KCkgbWF5IGJlIGFzeW5jIHcuci50LiByZWRyYXcoKSwga2VlcCB0cmFjayBvZiBsYXN0IHRleHR1cmUgZnJhbWVcbiAgLy8gYmVjYXVzZSBhIHJvZ3VlIGFzeW5jIHRleHR1cmUgZnJhbWUgd291bGQgY2xlYXIgbmVlZERyYXdcblxuXG4gIGlmIChyLnRleHR1cmVEcmF3TGFzdEZyYW1lICYmICF0ZXh0dXJlRHJhdykge1xuICAgIG5lZWREcmF3W3IuTk9ERV0gPSB0cnVlO1xuICAgIG5lZWREcmF3W3IuU0VMRUNUX0JPWF0gPSB0cnVlO1xuICB9XG5cbiAgdmFyIHN0eWxlID0gY3kuc3R5bGUoKTtcbiAgdmFyIHpvb20gPSBjeS56b29tKCk7XG4gIHZhciBlZmZlY3RpdmVab29tID0gZm9yY2VkWm9vbSAhPT0gdW5kZWZpbmVkID8gZm9yY2VkWm9vbSA6IHpvb207XG4gIHZhciBwYW4gPSBjeS5wYW4oKTtcbiAgdmFyIGVmZmVjdGl2ZVBhbiA9IHtcbiAgICB4OiBwYW4ueCxcbiAgICB5OiBwYW4ueVxuICB9O1xuICB2YXIgdnAgPSB7XG4gICAgem9vbTogem9vbSxcbiAgICBwYW46IHtcbiAgICAgIHg6IHBhbi54LFxuICAgICAgeTogcGFuLnlcbiAgICB9XG4gIH07XG4gIHZhciBwcmV2VnAgPSByLnByZXZWaWV3cG9ydDtcbiAgdmFyIHZpZXdwb3J0SXNEaWZmID0gcHJldlZwID09PSB1bmRlZmluZWQgfHwgdnAuem9vbSAhPT0gcHJldlZwLnpvb20gfHwgdnAucGFuLnggIT09IHByZXZWcC5wYW4ueCB8fCB2cC5wYW4ueSAhPT0gcHJldlZwLnBhbi55OyAvLyB3ZSB3YW50IHRoZSBsb3cgcXVhbGl0eSBtb3Rpb25ibHVyIG9ubHkgd2hlbiB0aGUgdmlld3BvcnQgaXMgYmVpbmcgbWFuaXB1bGF0ZWQgZXRjICh3aGVyZSBpdCdzIG5vdCBub3RpY2VkKVxuXG4gIGlmICghdmlld3BvcnRJc0RpZmYgJiYgIShpbk5vZGVEcmFnR2VzdHVyZSAmJiAhaGFzQ29tcG91bmROb2RlcykpIHtcbiAgICByLm1vdGlvbkJsdXJQeFJhdGlvID0gMTtcbiAgfVxuXG4gIGlmIChmb3JjZWRQYW4pIHtcbiAgICBlZmZlY3RpdmVQYW4gPSBmb3JjZWRQYW47XG4gIH0gLy8gYXBwbHkgcGl4ZWwgcmF0aW9cblxuXG4gIGVmZmVjdGl2ZVpvb20gKj0gcGl4ZWxSYXRpbztcbiAgZWZmZWN0aXZlUGFuLnggKj0gcGl4ZWxSYXRpbztcbiAgZWZmZWN0aXZlUGFuLnkgKj0gcGl4ZWxSYXRpbztcbiAgdmFyIGVsZXMgPSByLmdldENhY2hlZFpTb3J0ZWRFbGVzKCk7XG5cbiAgZnVuY3Rpb24gbWJjbGVhcihjb250ZXh0LCB4LCB5LCB3LCBoKSB7XG4gICAgdmFyIGdjbyA9IGNvbnRleHQuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uO1xuICAgIGNvbnRleHQuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gJ2Rlc3RpbmF0aW9uLW91dCc7XG4gICAgci5jb2xvckZpbGxTdHlsZShjb250ZXh0LCAyNTUsIDI1NSwgMjU1LCByLm1vdGlvbkJsdXJUcmFuc3BhcmVuY3kpO1xuICAgIGNvbnRleHQuZmlsbFJlY3QoeCwgeSwgdywgaCk7XG4gICAgY29udGV4dC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSBnY287XG4gIH1cblxuICBmdW5jdGlvbiBzZXRDb250ZXh0VHJhbnNmb3JtKGNvbnRleHQsIGNsZWFyKSB7XG4gICAgdmFyIGVQYW4sIGVab29tLCB3LCBoO1xuXG4gICAgaWYgKCFyLmNsZWFyaW5nTW90aW9uQmx1ciAmJiAoY29udGV4dCA9PT0gZGF0YS5idWZmZXJDb250ZXh0c1tyLk1PVElPTkJMVVJfQlVGRkVSX05PREVdIHx8IGNvbnRleHQgPT09IGRhdGEuYnVmZmVyQ29udGV4dHNbci5NT1RJT05CTFVSX0JVRkZFUl9EUkFHXSkpIHtcbiAgICAgIGVQYW4gPSB7XG4gICAgICAgIHg6IHBhbi54ICogbWJQeFJhdGlvLFxuICAgICAgICB5OiBwYW4ueSAqIG1iUHhSYXRpb1xuICAgICAgfTtcbiAgICAgIGVab29tID0gem9vbSAqIG1iUHhSYXRpbztcbiAgICAgIHcgPSByLmNhbnZhc1dpZHRoICogbWJQeFJhdGlvO1xuICAgICAgaCA9IHIuY2FudmFzSGVpZ2h0ICogbWJQeFJhdGlvO1xuICAgIH0gZWxzZSB7XG4gICAgICBlUGFuID0gZWZmZWN0aXZlUGFuO1xuICAgICAgZVpvb20gPSBlZmZlY3RpdmVab29tO1xuICAgICAgdyA9IHIuY2FudmFzV2lkdGg7XG4gICAgICBoID0gci5jYW52YXNIZWlnaHQ7XG4gICAgfVxuXG4gICAgY29udGV4dC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG5cbiAgICBpZiAoY2xlYXIgPT09ICdtb3Rpb25CbHVyJykge1xuICAgICAgbWJjbGVhcihjb250ZXh0LCAwLCAwLCB3LCBoKTtcbiAgICB9IGVsc2UgaWYgKCFmb3JjZWRDb250ZXh0ICYmIChjbGVhciA9PT0gdW5kZWZpbmVkIHx8IGNsZWFyKSkge1xuICAgICAgY29udGV4dC5jbGVhclJlY3QoMCwgMCwgdywgaCk7XG4gICAgfVxuXG4gICAgaWYgKCFkcmF3QWxsTGF5ZXJzKSB7XG4gICAgICBjb250ZXh0LnRyYW5zbGF0ZShlUGFuLngsIGVQYW4ueSk7XG4gICAgICBjb250ZXh0LnNjYWxlKGVab29tLCBlWm9vbSk7XG4gICAgfVxuXG4gICAgaWYgKGZvcmNlZFBhbikge1xuICAgICAgY29udGV4dC50cmFuc2xhdGUoZm9yY2VkUGFuLngsIGZvcmNlZFBhbi55KTtcbiAgICB9XG5cbiAgICBpZiAoZm9yY2VkWm9vbSkge1xuICAgICAgY29udGV4dC5zY2FsZShmb3JjZWRab29tLCBmb3JjZWRab29tKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXRleHR1cmVEcmF3KSB7XG4gICAgci50ZXh0dXJlRHJhd0xhc3RGcmFtZSA9IGZhbHNlO1xuICB9XG5cbiAgaWYgKHRleHR1cmVEcmF3KSB7XG4gICAgci50ZXh0dXJlRHJhd0xhc3RGcmFtZSA9IHRydWU7XG5cbiAgICBpZiAoIXIudGV4dHVyZUNhY2hlKSB7XG4gICAgICByLnRleHR1cmVDYWNoZSA9IHt9O1xuICAgICAgci50ZXh0dXJlQ2FjaGUuYmIgPSBjeS5tdXRhYmxlRWxlbWVudHMoKS5ib3VuZGluZ0JveCgpO1xuICAgICAgci50ZXh0dXJlQ2FjaGUudGV4dHVyZSA9IHIuZGF0YS5idWZmZXJDYW52YXNlc1tyLlRFWFRVUkVfQlVGRkVSXTtcbiAgICAgIHZhciBjeHQgPSByLmRhdGEuYnVmZmVyQ29udGV4dHNbci5URVhUVVJFX0JVRkZFUl07XG4gICAgICBjeHQuc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApO1xuICAgICAgY3h0LmNsZWFyUmVjdCgwLCAwLCByLmNhbnZhc1dpZHRoICogci50ZXh0dXJlTXVsdCwgci5jYW52YXNIZWlnaHQgKiByLnRleHR1cmVNdWx0KTtcbiAgICAgIHIucmVuZGVyKHtcbiAgICAgICAgZm9yY2VkQ29udGV4dDogY3h0LFxuICAgICAgICBkcmF3T25seU5vZGVMYXllcjogdHJ1ZSxcbiAgICAgICAgZm9yY2VkUHhSYXRpbzogcGl4ZWxSYXRpbyAqIHIudGV4dHVyZU11bHRcbiAgICAgIH0pO1xuICAgICAgdmFyIHZwID0gci50ZXh0dXJlQ2FjaGUudmlld3BvcnQgPSB7XG4gICAgICAgIHpvb206IGN5Lnpvb20oKSxcbiAgICAgICAgcGFuOiBjeS5wYW4oKSxcbiAgICAgICAgd2lkdGg6IHIuY2FudmFzV2lkdGgsXG4gICAgICAgIGhlaWdodDogci5jYW52YXNIZWlnaHRcbiAgICAgIH07XG4gICAgICB2cC5tcGFuID0ge1xuICAgICAgICB4OiAoMCAtIHZwLnBhbi54KSAvIHZwLnpvb20sXG4gICAgICAgIHk6ICgwIC0gdnAucGFuLnkpIC8gdnAuem9vbVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBuZWVkRHJhd1tyLkRSQUddID0gZmFsc2U7XG4gICAgbmVlZERyYXdbci5OT0RFXSA9IGZhbHNlO1xuICAgIHZhciBjb250ZXh0ID0gZGF0YS5jb250ZXh0c1tyLk5PREVdO1xuICAgIHZhciB0ZXh0dXJlID0gci50ZXh0dXJlQ2FjaGUudGV4dHVyZTtcbiAgICB2YXIgdnAgPSByLnRleHR1cmVDYWNoZS52aWV3cG9ydDtcbiAgICBjb250ZXh0LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcblxuICAgIGlmIChtb3Rpb25CbHVyKSB7XG4gICAgICBtYmNsZWFyKGNvbnRleHQsIDAsIDAsIHZwLndpZHRoLCB2cC5oZWlnaHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0LmNsZWFyUmVjdCgwLCAwLCB2cC53aWR0aCwgdnAuaGVpZ2h0KTtcbiAgICB9XG5cbiAgICB2YXIgb3V0c2lkZUJnQ29sb3IgPSBzdHlsZS5jb3JlKCdvdXRzaWRlLXRleHR1cmUtYmctY29sb3InKS52YWx1ZTtcbiAgICB2YXIgb3V0c2lkZUJnT3BhY2l0eSA9IHN0eWxlLmNvcmUoJ291dHNpZGUtdGV4dHVyZS1iZy1vcGFjaXR5JykudmFsdWU7XG4gICAgci5jb2xvckZpbGxTdHlsZShjb250ZXh0LCBvdXRzaWRlQmdDb2xvclswXSwgb3V0c2lkZUJnQ29sb3JbMV0sIG91dHNpZGVCZ0NvbG9yWzJdLCBvdXRzaWRlQmdPcGFjaXR5KTtcbiAgICBjb250ZXh0LmZpbGxSZWN0KDAsIDAsIHZwLndpZHRoLCB2cC5oZWlnaHQpO1xuICAgIHZhciB6b29tID0gY3kuem9vbSgpO1xuICAgIHNldENvbnRleHRUcmFuc2Zvcm0oY29udGV4dCwgZmFsc2UpO1xuICAgIGNvbnRleHQuY2xlYXJSZWN0KHZwLm1wYW4ueCwgdnAubXBhbi55LCB2cC53aWR0aCAvIHZwLnpvb20gLyBwaXhlbFJhdGlvLCB2cC5oZWlnaHQgLyB2cC56b29tIC8gcGl4ZWxSYXRpbyk7XG4gICAgY29udGV4dC5kcmF3SW1hZ2UodGV4dHVyZSwgdnAubXBhbi54LCB2cC5tcGFuLnksIHZwLndpZHRoIC8gdnAuem9vbSAvIHBpeGVsUmF0aW8sIHZwLmhlaWdodCAvIHZwLnpvb20gLyBwaXhlbFJhdGlvKTtcbiAgfSBlbHNlIGlmIChyLnRleHR1cmVPblZpZXdwb3J0ICYmICFmb3JjZWRDb250ZXh0KSB7XG4gICAgLy8gY2xlYXIgdGhlIGNhY2hlIHNpbmNlIHdlIGRvbid0IG5lZWQgaXRcbiAgICByLnRleHR1cmVDYWNoZSA9IG51bGw7XG4gIH1cblxuICB2YXIgZXh0ZW50ID0gY3kuZXh0ZW50KCk7XG4gIHZhciB2cE1hbmlwID0gci5waW5jaGluZyB8fCByLmhvdmVyRGF0YS5kcmFnZ2luZyB8fCByLnN3aXBlUGFubmluZyB8fCByLmRhdGEud2hlZWxab29taW5nIHx8IHIuaG92ZXJEYXRhLmRyYWdnaW5nRWxlcyB8fCByLmN5LmFuaW1hdGVkKCk7XG4gIHZhciBoaWRlRWRnZXMgPSByLmhpZGVFZGdlc09uVmlld3BvcnQgJiYgdnBNYW5pcDtcbiAgdmFyIG5lZWRNYkNsZWFyID0gW107XG4gIG5lZWRNYkNsZWFyW3IuTk9ERV0gPSAhbmVlZERyYXdbci5OT0RFXSAmJiBtb3Rpb25CbHVyICYmICFyLmNsZWFyZWRGb3JNb3Rpb25CbHVyW3IuTk9ERV0gfHwgci5jbGVhcmluZ01vdGlvbkJsdXI7XG5cbiAgaWYgKG5lZWRNYkNsZWFyW3IuTk9ERV0pIHtcbiAgICByLmNsZWFyZWRGb3JNb3Rpb25CbHVyW3IuTk9ERV0gPSB0cnVlO1xuICB9XG5cbiAgbmVlZE1iQ2xlYXJbci5EUkFHXSA9ICFuZWVkRHJhd1tyLkRSQUddICYmIG1vdGlvbkJsdXIgJiYgIXIuY2xlYXJlZEZvck1vdGlvbkJsdXJbci5EUkFHXSB8fCByLmNsZWFyaW5nTW90aW9uQmx1cjtcblxuICBpZiAobmVlZE1iQ2xlYXJbci5EUkFHXSkge1xuICAgIHIuY2xlYXJlZEZvck1vdGlvbkJsdXJbci5EUkFHXSA9IHRydWU7XG4gIH1cblxuICBpZiAobmVlZERyYXdbci5OT0RFXSB8fCBkcmF3QWxsTGF5ZXJzIHx8IGRyYXdPbmx5Tm9kZUxheWVyIHx8IG5lZWRNYkNsZWFyW3IuTk9ERV0pIHtcbiAgICB2YXIgdXNlQnVmZmVyID0gbW90aW9uQmx1ciAmJiAhbmVlZE1iQ2xlYXJbci5OT0RFXSAmJiBtYlB4UmF0aW8gIT09IDE7XG4gICAgdmFyIGNvbnRleHQgPSBmb3JjZWRDb250ZXh0IHx8ICh1c2VCdWZmZXIgPyByLmRhdGEuYnVmZmVyQ29udGV4dHNbci5NT1RJT05CTFVSX0JVRkZFUl9OT0RFXSA6IGRhdGEuY29udGV4dHNbci5OT0RFXSk7XG4gICAgdmFyIGNsZWFyID0gbW90aW9uQmx1ciAmJiAhdXNlQnVmZmVyID8gJ21vdGlvbkJsdXInIDogdW5kZWZpbmVkO1xuICAgIHNldENvbnRleHRUcmFuc2Zvcm0oY29udGV4dCwgY2xlYXIpO1xuXG4gICAgaWYgKGhpZGVFZGdlcykge1xuICAgICAgci5kcmF3Q2FjaGVkTm9kZXMoY29udGV4dCwgZWxlcy5ub25kcmFnLCBwaXhlbFJhdGlvLCBleHRlbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByLmRyYXdMYXllcmVkRWxlbWVudHMoY29udGV4dCwgZWxlcy5ub25kcmFnLCBwaXhlbFJhdGlvLCBleHRlbnQpO1xuICAgIH1cblxuICAgIGlmIChyLmRlYnVnKSB7XG4gICAgICByLmRyYXdEZWJ1Z1BvaW50cyhjb250ZXh0LCBlbGVzLm5vbmRyYWcpO1xuICAgIH1cblxuICAgIGlmICghZHJhd0FsbExheWVycyAmJiAhbW90aW9uQmx1cikge1xuICAgICAgbmVlZERyYXdbci5OT0RFXSA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGlmICghZHJhd09ubHlOb2RlTGF5ZXIgJiYgKG5lZWREcmF3W3IuRFJBR10gfHwgZHJhd0FsbExheWVycyB8fCBuZWVkTWJDbGVhcltyLkRSQUddKSkge1xuICAgIHZhciB1c2VCdWZmZXIgPSBtb3Rpb25CbHVyICYmICFuZWVkTWJDbGVhcltyLkRSQUddICYmIG1iUHhSYXRpbyAhPT0gMTtcbiAgICB2YXIgY29udGV4dCA9IGZvcmNlZENvbnRleHQgfHwgKHVzZUJ1ZmZlciA/IHIuZGF0YS5idWZmZXJDb250ZXh0c1tyLk1PVElPTkJMVVJfQlVGRkVSX0RSQUddIDogZGF0YS5jb250ZXh0c1tyLkRSQUddKTtcbiAgICBzZXRDb250ZXh0VHJhbnNmb3JtKGNvbnRleHQsIG1vdGlvbkJsdXIgJiYgIXVzZUJ1ZmZlciA/ICdtb3Rpb25CbHVyJyA6IHVuZGVmaW5lZCk7XG5cbiAgICBpZiAoaGlkZUVkZ2VzKSB7XG4gICAgICByLmRyYXdDYWNoZWROb2Rlcyhjb250ZXh0LCBlbGVzLmRyYWcsIHBpeGVsUmF0aW8sIGV4dGVudCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHIuZHJhd0NhY2hlZEVsZW1lbnRzKGNvbnRleHQsIGVsZXMuZHJhZywgcGl4ZWxSYXRpbywgZXh0ZW50KTtcbiAgICB9XG5cbiAgICBpZiAoci5kZWJ1Zykge1xuICAgICAgci5kcmF3RGVidWdQb2ludHMoY29udGV4dCwgZWxlcy5kcmFnKTtcbiAgICB9XG5cbiAgICBpZiAoIWRyYXdBbGxMYXllcnMgJiYgIW1vdGlvbkJsdXIpIHtcbiAgICAgIG5lZWREcmF3W3IuRFJBR10gPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBpZiAoci5zaG93RnBzIHx8ICFkcmF3T25seU5vZGVMYXllciAmJiBuZWVkRHJhd1tyLlNFTEVDVF9CT1hdICYmICFkcmF3QWxsTGF5ZXJzKSB7XG4gICAgdmFyIGNvbnRleHQgPSBmb3JjZWRDb250ZXh0IHx8IGRhdGEuY29udGV4dHNbci5TRUxFQ1RfQk9YXTtcbiAgICBzZXRDb250ZXh0VHJhbnNmb3JtKGNvbnRleHQpO1xuXG4gICAgaWYgKHIuc2VsZWN0aW9uWzRdID09IDEgJiYgKHIuaG92ZXJEYXRhLnNlbGVjdGluZyB8fCByLnRvdWNoRGF0YS5zZWxlY3RpbmcpKSB7XG4gICAgICB2YXIgem9vbSA9IHIuY3kuem9vbSgpO1xuICAgICAgdmFyIGJvcmRlcldpZHRoID0gc3R5bGUuY29yZSgnc2VsZWN0aW9uLWJveC1ib3JkZXItd2lkdGgnKS52YWx1ZSAvIHpvb207XG4gICAgICBjb250ZXh0LmxpbmVXaWR0aCA9IGJvcmRlcldpZHRoO1xuICAgICAgY29udGV4dC5maWxsU3R5bGUgPSAncmdiYSgnICsgc3R5bGUuY29yZSgnc2VsZWN0aW9uLWJveC1jb2xvcicpLnZhbHVlWzBdICsgJywnICsgc3R5bGUuY29yZSgnc2VsZWN0aW9uLWJveC1jb2xvcicpLnZhbHVlWzFdICsgJywnICsgc3R5bGUuY29yZSgnc2VsZWN0aW9uLWJveC1jb2xvcicpLnZhbHVlWzJdICsgJywnICsgc3R5bGUuY29yZSgnc2VsZWN0aW9uLWJveC1vcGFjaXR5JykudmFsdWUgKyAnKSc7XG4gICAgICBjb250ZXh0LmZpbGxSZWN0KHIuc2VsZWN0aW9uWzBdLCByLnNlbGVjdGlvblsxXSwgci5zZWxlY3Rpb25bMl0gLSByLnNlbGVjdGlvblswXSwgci5zZWxlY3Rpb25bM10gLSByLnNlbGVjdGlvblsxXSk7XG5cbiAgICAgIGlmIChib3JkZXJXaWR0aCA+IDApIHtcbiAgICAgICAgY29udGV4dC5zdHJva2VTdHlsZSA9ICdyZ2JhKCcgKyBzdHlsZS5jb3JlKCdzZWxlY3Rpb24tYm94LWJvcmRlci1jb2xvcicpLnZhbHVlWzBdICsgJywnICsgc3R5bGUuY29yZSgnc2VsZWN0aW9uLWJveC1ib3JkZXItY29sb3InKS52YWx1ZVsxXSArICcsJyArIHN0eWxlLmNvcmUoJ3NlbGVjdGlvbi1ib3gtYm9yZGVyLWNvbG9yJykudmFsdWVbMl0gKyAnLCcgKyBzdHlsZS5jb3JlKCdzZWxlY3Rpb24tYm94LW9wYWNpdHknKS52YWx1ZSArICcpJztcbiAgICAgICAgY29udGV4dC5zdHJva2VSZWN0KHIuc2VsZWN0aW9uWzBdLCByLnNlbGVjdGlvblsxXSwgci5zZWxlY3Rpb25bMl0gLSByLnNlbGVjdGlvblswXSwgci5zZWxlY3Rpb25bM10gLSByLnNlbGVjdGlvblsxXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGRhdGEuYmdBY3RpdmVQb3Npc3Rpb24gJiYgIXIuaG92ZXJEYXRhLnNlbGVjdGluZykge1xuICAgICAgdmFyIHpvb20gPSByLmN5Lnpvb20oKTtcbiAgICAgIHZhciBwb3MgPSBkYXRhLmJnQWN0aXZlUG9zaXN0aW9uO1xuICAgICAgY29udGV4dC5maWxsU3R5bGUgPSAncmdiYSgnICsgc3R5bGUuY29yZSgnYWN0aXZlLWJnLWNvbG9yJykudmFsdWVbMF0gKyAnLCcgKyBzdHlsZS5jb3JlKCdhY3RpdmUtYmctY29sb3InKS52YWx1ZVsxXSArICcsJyArIHN0eWxlLmNvcmUoJ2FjdGl2ZS1iZy1jb2xvcicpLnZhbHVlWzJdICsgJywnICsgc3R5bGUuY29yZSgnYWN0aXZlLWJnLW9wYWNpdHknKS52YWx1ZSArICcpJztcbiAgICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gICAgICBjb250ZXh0LmFyYyhwb3MueCwgcG9zLnksIHN0eWxlLmNvcmUoJ2FjdGl2ZS1iZy1zaXplJykucGZWYWx1ZSAvIHpvb20sIDAsIDIgKiBNYXRoLlBJKTtcbiAgICAgIGNvbnRleHQuZmlsbCgpO1xuICAgIH1cblxuICAgIHZhciB0aW1lVG9SZW5kZXIgPSByLmxhc3RSZWRyYXdUaW1lO1xuXG4gICAgaWYgKHIuc2hvd0ZwcyAmJiB0aW1lVG9SZW5kZXIpIHtcbiAgICAgIHRpbWVUb1JlbmRlciA9IE1hdGgucm91bmQodGltZVRvUmVuZGVyKTtcbiAgICAgIHZhciBmcHMgPSBNYXRoLnJvdW5kKDEwMDAgLyB0aW1lVG9SZW5kZXIpO1xuICAgICAgY29udGV4dC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG4gICAgICBjb250ZXh0LmZpbGxTdHlsZSA9ICdyZ2JhKDI1NSwgMCwgMCwgMC43NSknO1xuICAgICAgY29udGV4dC5zdHJva2VTdHlsZSA9ICdyZ2JhKDI1NSwgMCwgMCwgMC43NSknO1xuICAgICAgY29udGV4dC5saW5lV2lkdGggPSAxO1xuICAgICAgY29udGV4dC5maWxsVGV4dCgnMSBmcmFtZSA9ICcgKyB0aW1lVG9SZW5kZXIgKyAnIG1zID0gJyArIGZwcyArICcgZnBzJywgMCwgMjApO1xuICAgICAgdmFyIG1heEZwcyA9IDYwO1xuICAgICAgY29udGV4dC5zdHJva2VSZWN0KDAsIDMwLCAyNTAsIDIwKTtcbiAgICAgIGNvbnRleHQuZmlsbFJlY3QoMCwgMzAsIDI1MCAqIE1hdGgubWluKGZwcyAvIG1heEZwcywgMSksIDIwKTtcbiAgICB9XG5cbiAgICBpZiAoIWRyYXdBbGxMYXllcnMpIHtcbiAgICAgIG5lZWREcmF3W3IuU0VMRUNUX0JPWF0gPSBmYWxzZTtcbiAgICB9XG4gIH0gLy8gbW90aW9uYmx1cjogYmxpdCByZW5kZXJlZCBibHVycnkgZnJhbWVzXG5cblxuICBpZiAobW90aW9uQmx1ciAmJiBtYlB4UmF0aW8gIT09IDEpIHtcbiAgICB2YXIgY3h0Tm9kZSA9IGRhdGEuY29udGV4dHNbci5OT0RFXTtcbiAgICB2YXIgdHh0Tm9kZSA9IHIuZGF0YS5idWZmZXJDYW52YXNlc1tyLk1PVElPTkJMVVJfQlVGRkVSX05PREVdO1xuICAgIHZhciBjeHREcmFnID0gZGF0YS5jb250ZXh0c1tyLkRSQUddO1xuICAgIHZhciB0eHREcmFnID0gci5kYXRhLmJ1ZmZlckNhbnZhc2VzW3IuTU9USU9OQkxVUl9CVUZGRVJfRFJBR107XG5cbiAgICB2YXIgZHJhd01vdGlvbkJsdXIgPSBmdW5jdGlvbiBkcmF3TW90aW9uQmx1cihjeHQsIHR4dCwgbmVlZENsZWFyKSB7XG4gICAgICBjeHQuc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApO1xuXG4gICAgICBpZiAobmVlZENsZWFyIHx8ICFtb3Rpb25CbHVyRmFkZUVmZmVjdCkge1xuICAgICAgICBjeHQuY2xlYXJSZWN0KDAsIDAsIHIuY2FudmFzV2lkdGgsIHIuY2FudmFzSGVpZ2h0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1iY2xlYXIoY3h0LCAwLCAwLCByLmNhbnZhc1dpZHRoLCByLmNhbnZhc0hlaWdodCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBweHIgPSBtYlB4UmF0aW87XG4gICAgICBjeHQuZHJhd0ltYWdlKHR4dCwgLy8gaW1nXG4gICAgICAwLCAwLCAvLyBzeCwgc3lcbiAgICAgIHIuY2FudmFzV2lkdGggKiBweHIsIHIuY2FudmFzSGVpZ2h0ICogcHhyLCAvLyBzdywgc2hcbiAgICAgIDAsIDAsIC8vIHgsIHlcbiAgICAgIHIuY2FudmFzV2lkdGgsIHIuY2FudmFzSGVpZ2h0IC8vIHcsIGhcbiAgICAgICk7XG4gICAgfTtcblxuICAgIGlmIChuZWVkRHJhd1tyLk5PREVdIHx8IG5lZWRNYkNsZWFyW3IuTk9ERV0pIHtcbiAgICAgIGRyYXdNb3Rpb25CbHVyKGN4dE5vZGUsIHR4dE5vZGUsIG5lZWRNYkNsZWFyW3IuTk9ERV0pO1xuICAgICAgbmVlZERyYXdbci5OT0RFXSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChuZWVkRHJhd1tyLkRSQUddIHx8IG5lZWRNYkNsZWFyW3IuRFJBR10pIHtcbiAgICAgIGRyYXdNb3Rpb25CbHVyKGN4dERyYWcsIHR4dERyYWcsIG5lZWRNYkNsZWFyW3IuRFJBR10pO1xuICAgICAgbmVlZERyYXdbci5EUkFHXSA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHIucHJldlZpZXdwb3J0ID0gdnA7XG5cbiAgaWYgKHIuY2xlYXJpbmdNb3Rpb25CbHVyKSB7XG4gICAgci5jbGVhcmluZ01vdGlvbkJsdXIgPSBmYWxzZTtcbiAgICByLm1vdGlvbkJsdXJDbGVhcmVkID0gdHJ1ZTtcbiAgICByLm1vdGlvbkJsdXIgPSB0cnVlO1xuICB9XG5cbiAgaWYgKG1vdGlvbkJsdXIpIHtcbiAgICByLm1vdGlvbkJsdXJUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICByLm1vdGlvbkJsdXJUaW1lb3V0ID0gbnVsbDtcbiAgICAgIHIuY2xlYXJlZEZvck1vdGlvbkJsdXJbci5OT0RFXSA9IGZhbHNlO1xuICAgICAgci5jbGVhcmVkRm9yTW90aW9uQmx1cltyLkRSQUddID0gZmFsc2U7XG4gICAgICByLm1vdGlvbkJsdXIgPSBmYWxzZTtcbiAgICAgIHIuY2xlYXJpbmdNb3Rpb25CbHVyID0gIXRleHR1cmVEcmF3O1xuICAgICAgci5tYkZyYW1lcyA9IDA7XG4gICAgICBuZWVkRHJhd1tyLk5PREVdID0gdHJ1ZTtcbiAgICAgIG5lZWREcmF3W3IuRFJBR10gPSB0cnVlO1xuICAgICAgci5yZWRyYXcoKTtcbiAgICB9LCBtb3Rpb25CbHVyRGVsYXkpO1xuICB9XG5cbiAgaWYgKCFmb3JjZWRDb250ZXh0KSB7XG4gICAgY3kuZW1pdCgncmVuZGVyJyk7XG4gIH1cbn07XG5cbnZhciBDUnAkNyA9IHt9OyAvLyBATyBQb2x5Z29uIGRyYXdpbmdcblxuQ1JwJDcuZHJhd1BvbHlnb25QYXRoID0gZnVuY3Rpb24gKGNvbnRleHQsIHgsIHksIHdpZHRoLCBoZWlnaHQsIHBvaW50cykge1xuICB2YXIgaGFsZlcgPSB3aWR0aCAvIDI7XG4gIHZhciBoYWxmSCA9IGhlaWdodCAvIDI7XG5cbiAgaWYgKGNvbnRleHQuYmVnaW5QYXRoKSB7XG4gICAgY29udGV4dC5iZWdpblBhdGgoKTtcbiAgfVxuXG4gIGNvbnRleHQubW92ZVRvKHggKyBoYWxmVyAqIHBvaW50c1swXSwgeSArIGhhbGZIICogcG9pbnRzWzFdKTtcblxuICBmb3IgKHZhciBpID0gMTsgaSA8IHBvaW50cy5sZW5ndGggLyAyOyBpKyspIHtcbiAgICBjb250ZXh0LmxpbmVUbyh4ICsgaGFsZlcgKiBwb2ludHNbaSAqIDJdLCB5ICsgaGFsZkggKiBwb2ludHNbaSAqIDIgKyAxXSk7XG4gIH1cblxuICBjb250ZXh0LmNsb3NlUGF0aCgpO1xufTtcblxuQ1JwJDcuZHJhd1JvdW5kUG9seWdvblBhdGggPSBmdW5jdGlvbiAoY29udGV4dCwgeCwgeSwgd2lkdGgsIGhlaWdodCwgcG9pbnRzKSB7XG4gIHZhciBoYWxmVyA9IHdpZHRoIC8gMjtcbiAgdmFyIGhhbGZIID0gaGVpZ2h0IC8gMjtcbiAgdmFyIGNvcm5lclJhZGl1cyA9IGdldFJvdW5kUG9seWdvblJhZGl1cyh3aWR0aCwgaGVpZ2h0KTtcblxuICBpZiAoY29udGV4dC5iZWdpblBhdGgpIHtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICB9XG5cbiAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IHBvaW50cy5sZW5ndGggLyA0OyBfaSsrKSB7XG4gICAgdmFyIHNvdXJjZVV2ID0gdm9pZCAwLFxuICAgICAgICBkZXN0VXYgPSB2b2lkIDA7XG5cbiAgICBpZiAoX2kgPT09IDApIHtcbiAgICAgIHNvdXJjZVV2ID0gcG9pbnRzLmxlbmd0aCAtIDI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNvdXJjZVV2ID0gX2kgKiA0IC0gMjtcbiAgICB9XG5cbiAgICBkZXN0VXYgPSBfaSAqIDQgKyAyO1xuICAgIHZhciBweCA9IHggKyBoYWxmVyAqIHBvaW50c1tfaSAqIDRdO1xuICAgIHZhciBweSA9IHkgKyBoYWxmSCAqIHBvaW50c1tfaSAqIDQgKyAxXTtcbiAgICB2YXIgY29zVGhldGEgPSAtcG9pbnRzW3NvdXJjZVV2XSAqIHBvaW50c1tkZXN0VXZdIC0gcG9pbnRzW3NvdXJjZVV2ICsgMV0gKiBwb2ludHNbZGVzdFV2ICsgMV07XG4gICAgdmFyIG9mZnNldCA9IGNvcm5lclJhZGl1cyAvIE1hdGgudGFuKE1hdGguYWNvcyhjb3NUaGV0YSkgLyAyKTtcbiAgICB2YXIgY3AweCA9IHB4IC0gb2Zmc2V0ICogcG9pbnRzW3NvdXJjZVV2XTtcbiAgICB2YXIgY3AweSA9IHB5IC0gb2Zmc2V0ICogcG9pbnRzW3NvdXJjZVV2ICsgMV07XG4gICAgdmFyIGNwMXggPSBweCArIG9mZnNldCAqIHBvaW50c1tkZXN0VXZdO1xuICAgIHZhciBjcDF5ID0gcHkgKyBvZmZzZXQgKiBwb2ludHNbZGVzdFV2ICsgMV07XG5cbiAgICBpZiAoX2kgPT09IDApIHtcbiAgICAgIGNvbnRleHQubW92ZVRvKGNwMHgsIGNwMHkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0LmxpbmVUbyhjcDB4LCBjcDB5KTtcbiAgICB9XG5cbiAgICBjb250ZXh0LmFyY1RvKHB4LCBweSwgY3AxeCwgY3AxeSwgY29ybmVyUmFkaXVzKTtcbiAgfVxuXG4gIGNvbnRleHQuY2xvc2VQYXRoKCk7XG59OyAvLyBSb3VuZCByZWN0YW5nbGUgZHJhd2luZ1xuXG5cbkNScCQ3LmRyYXdSb3VuZFJlY3RhbmdsZVBhdGggPSBmdW5jdGlvbiAoY29udGV4dCwgeCwgeSwgd2lkdGgsIGhlaWdodCkge1xuICB2YXIgaGFsZldpZHRoID0gd2lkdGggLyAyO1xuICB2YXIgaGFsZkhlaWdodCA9IGhlaWdodCAvIDI7XG4gIHZhciBjb3JuZXJSYWRpdXMgPSBnZXRSb3VuZFJlY3RhbmdsZVJhZGl1cyh3aWR0aCwgaGVpZ2h0KTtcblxuICBpZiAoY29udGV4dC5iZWdpblBhdGgpIHtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICB9IC8vIFN0YXJ0IGF0IHRvcCBtaWRkbGVcblxuXG4gIGNvbnRleHQubW92ZVRvKHgsIHkgLSBoYWxmSGVpZ2h0KTsgLy8gQXJjIGZyb20gbWlkZGxlIHRvcCB0byByaWdodCBzaWRlXG5cbiAgY29udGV4dC5hcmNUbyh4ICsgaGFsZldpZHRoLCB5IC0gaGFsZkhlaWdodCwgeCArIGhhbGZXaWR0aCwgeSwgY29ybmVyUmFkaXVzKTsgLy8gQXJjIGZyb20gcmlnaHQgc2lkZSB0byBib3R0b21cblxuICBjb250ZXh0LmFyY1RvKHggKyBoYWxmV2lkdGgsIHkgKyBoYWxmSGVpZ2h0LCB4LCB5ICsgaGFsZkhlaWdodCwgY29ybmVyUmFkaXVzKTsgLy8gQXJjIGZyb20gYm90dG9tIHRvIGxlZnQgc2lkZVxuXG4gIGNvbnRleHQuYXJjVG8oeCAtIGhhbGZXaWR0aCwgeSArIGhhbGZIZWlnaHQsIHggLSBoYWxmV2lkdGgsIHksIGNvcm5lclJhZGl1cyk7IC8vIEFyYyBmcm9tIGxlZnQgc2lkZSB0byB0b3BCb3JkZXJcblxuICBjb250ZXh0LmFyY1RvKHggLSBoYWxmV2lkdGgsIHkgLSBoYWxmSGVpZ2h0LCB4LCB5IC0gaGFsZkhlaWdodCwgY29ybmVyUmFkaXVzKTsgLy8gSm9pbiBsaW5lXG5cbiAgY29udGV4dC5saW5lVG8oeCwgeSAtIGhhbGZIZWlnaHQpO1xuICBjb250ZXh0LmNsb3NlUGF0aCgpO1xufTtcblxuQ1JwJDcuZHJhd0JvdHRvbVJvdW5kUmVjdGFuZ2xlUGF0aCA9IGZ1bmN0aW9uIChjb250ZXh0LCB4LCB5LCB3aWR0aCwgaGVpZ2h0KSB7XG4gIHZhciBoYWxmV2lkdGggPSB3aWR0aCAvIDI7XG4gIHZhciBoYWxmSGVpZ2h0ID0gaGVpZ2h0IC8gMjtcbiAgdmFyIGNvcm5lclJhZGl1cyA9IGdldFJvdW5kUmVjdGFuZ2xlUmFkaXVzKHdpZHRoLCBoZWlnaHQpO1xuXG4gIGlmIChjb250ZXh0LmJlZ2luUGF0aCkge1xuICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gIH0gLy8gU3RhcnQgYXQgdG9wIG1pZGRsZVxuXG5cbiAgY29udGV4dC5tb3ZlVG8oeCwgeSAtIGhhbGZIZWlnaHQpO1xuICBjb250ZXh0LmxpbmVUbyh4ICsgaGFsZldpZHRoLCB5IC0gaGFsZkhlaWdodCk7XG4gIGNvbnRleHQubGluZVRvKHggKyBoYWxmV2lkdGgsIHkpO1xuICBjb250ZXh0LmFyY1RvKHggKyBoYWxmV2lkdGgsIHkgKyBoYWxmSGVpZ2h0LCB4LCB5ICsgaGFsZkhlaWdodCwgY29ybmVyUmFkaXVzKTtcbiAgY29udGV4dC5hcmNUbyh4IC0gaGFsZldpZHRoLCB5ICsgaGFsZkhlaWdodCwgeCAtIGhhbGZXaWR0aCwgeSwgY29ybmVyUmFkaXVzKTtcbiAgY29udGV4dC5saW5lVG8oeCAtIGhhbGZXaWR0aCwgeSAtIGhhbGZIZWlnaHQpO1xuICBjb250ZXh0LmxpbmVUbyh4LCB5IC0gaGFsZkhlaWdodCk7XG4gIGNvbnRleHQuY2xvc2VQYXRoKCk7XG59O1xuXG5DUnAkNy5kcmF3Q3V0UmVjdGFuZ2xlUGF0aCA9IGZ1bmN0aW9uIChjb250ZXh0LCB4LCB5LCB3aWR0aCwgaGVpZ2h0KSB7XG4gIHZhciBoYWxmV2lkdGggPSB3aWR0aCAvIDI7XG4gIHZhciBoYWxmSGVpZ2h0ID0gaGVpZ2h0IC8gMjtcbiAgdmFyIGNvcm5lckxlbmd0aCA9IGdldEN1dFJlY3RhbmdsZUNvcm5lckxlbmd0aCgpO1xuXG4gIGlmIChjb250ZXh0LmJlZ2luUGF0aCkge1xuICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gIH1cblxuICBjb250ZXh0Lm1vdmVUbyh4IC0gaGFsZldpZHRoICsgY29ybmVyTGVuZ3RoLCB5IC0gaGFsZkhlaWdodCk7XG4gIGNvbnRleHQubGluZVRvKHggKyBoYWxmV2lkdGggLSBjb3JuZXJMZW5ndGgsIHkgLSBoYWxmSGVpZ2h0KTtcbiAgY29udGV4dC5saW5lVG8oeCArIGhhbGZXaWR0aCwgeSAtIGhhbGZIZWlnaHQgKyBjb3JuZXJMZW5ndGgpO1xuICBjb250ZXh0LmxpbmVUbyh4ICsgaGFsZldpZHRoLCB5ICsgaGFsZkhlaWdodCAtIGNvcm5lckxlbmd0aCk7XG4gIGNvbnRleHQubGluZVRvKHggKyBoYWxmV2lkdGggLSBjb3JuZXJMZW5ndGgsIHkgKyBoYWxmSGVpZ2h0KTtcbiAgY29udGV4dC5saW5lVG8oeCAtIGhhbGZXaWR0aCArIGNvcm5lckxlbmd0aCwgeSArIGhhbGZIZWlnaHQpO1xuICBjb250ZXh0LmxpbmVUbyh4IC0gaGFsZldpZHRoLCB5ICsgaGFsZkhlaWdodCAtIGNvcm5lckxlbmd0aCk7XG4gIGNvbnRleHQubGluZVRvKHggLSBoYWxmV2lkdGgsIHkgLSBoYWxmSGVpZ2h0ICsgY29ybmVyTGVuZ3RoKTtcbiAgY29udGV4dC5jbG9zZVBhdGgoKTtcbn07XG5cbkNScCQ3LmRyYXdCYXJyZWxQYXRoID0gZnVuY3Rpb24gKGNvbnRleHQsIHgsIHksIHdpZHRoLCBoZWlnaHQpIHtcbiAgdmFyIGhhbGZXaWR0aCA9IHdpZHRoIC8gMjtcbiAgdmFyIGhhbGZIZWlnaHQgPSBoZWlnaHQgLyAyO1xuICB2YXIgeEJlZ2luID0geCAtIGhhbGZXaWR0aDtcbiAgdmFyIHhFbmQgPSB4ICsgaGFsZldpZHRoO1xuICB2YXIgeUJlZ2luID0geSAtIGhhbGZIZWlnaHQ7XG4gIHZhciB5RW5kID0geSArIGhhbGZIZWlnaHQ7XG4gIHZhciBiYXJyZWxDdXJ2ZUNvbnN0YW50cyA9IGdldEJhcnJlbEN1cnZlQ29uc3RhbnRzKHdpZHRoLCBoZWlnaHQpO1xuICB2YXIgd09mZnNldCA9IGJhcnJlbEN1cnZlQ29uc3RhbnRzLndpZHRoT2Zmc2V0O1xuICB2YXIgaE9mZnNldCA9IGJhcnJlbEN1cnZlQ29uc3RhbnRzLmhlaWdodE9mZnNldDtcbiAgdmFyIGN0cmxQdFhPZmZzZXQgPSBiYXJyZWxDdXJ2ZUNvbnN0YW50cy5jdHJsUHRPZmZzZXRQY3QgKiB3T2Zmc2V0O1xuXG4gIGlmIChjb250ZXh0LmJlZ2luUGF0aCkge1xuICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gIH1cblxuICBjb250ZXh0Lm1vdmVUbyh4QmVnaW4sIHlCZWdpbiArIGhPZmZzZXQpO1xuICBjb250ZXh0LmxpbmVUbyh4QmVnaW4sIHlFbmQgLSBoT2Zmc2V0KTtcbiAgY29udGV4dC5xdWFkcmF0aWNDdXJ2ZVRvKHhCZWdpbiArIGN0cmxQdFhPZmZzZXQsIHlFbmQsIHhCZWdpbiArIHdPZmZzZXQsIHlFbmQpO1xuICBjb250ZXh0LmxpbmVUbyh4RW5kIC0gd09mZnNldCwgeUVuZCk7XG4gIGNvbnRleHQucXVhZHJhdGljQ3VydmVUbyh4RW5kIC0gY3RybFB0WE9mZnNldCwgeUVuZCwgeEVuZCwgeUVuZCAtIGhPZmZzZXQpO1xuICBjb250ZXh0LmxpbmVUbyh4RW5kLCB5QmVnaW4gKyBoT2Zmc2V0KTtcbiAgY29udGV4dC5xdWFkcmF0aWNDdXJ2ZVRvKHhFbmQgLSBjdHJsUHRYT2Zmc2V0LCB5QmVnaW4sIHhFbmQgLSB3T2Zmc2V0LCB5QmVnaW4pO1xuICBjb250ZXh0LmxpbmVUbyh4QmVnaW4gKyB3T2Zmc2V0LCB5QmVnaW4pO1xuICBjb250ZXh0LnF1YWRyYXRpY0N1cnZlVG8oeEJlZ2luICsgY3RybFB0WE9mZnNldCwgeUJlZ2luLCB4QmVnaW4sIHlCZWdpbiArIGhPZmZzZXQpO1xuICBjb250ZXh0LmNsb3NlUGF0aCgpO1xufTtcblxudmFyIHNpbjAgPSBNYXRoLnNpbigwKTtcbnZhciBjb3MwID0gTWF0aC5jb3MoMCk7XG52YXIgc2luID0ge307XG52YXIgY29zID0ge307XG52YXIgZWxsaXBzZVN0ZXBTaXplID0gTWF0aC5QSSAvIDQwO1xuXG5mb3IgKHZhciBpID0gMCAqIE1hdGguUEk7IGkgPCAyICogTWF0aC5QSTsgaSArPSBlbGxpcHNlU3RlcFNpemUpIHtcbiAgc2luW2ldID0gTWF0aC5zaW4oaSk7XG4gIGNvc1tpXSA9IE1hdGguY29zKGkpO1xufVxuXG5DUnAkNy5kcmF3RWxsaXBzZVBhdGggPSBmdW5jdGlvbiAoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCkge1xuICBpZiAoY29udGV4dC5iZWdpblBhdGgpIHtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICB9XG5cbiAgaWYgKGNvbnRleHQuZWxsaXBzZSkge1xuICAgIGNvbnRleHQuZWxsaXBzZShjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCAvIDIsIGhlaWdodCAvIDIsIDAsIDAsIDIgKiBNYXRoLlBJKTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgeFBvcywgeVBvcztcbiAgICB2YXIgcncgPSB3aWR0aCAvIDI7XG4gICAgdmFyIHJoID0gaGVpZ2h0IC8gMjtcblxuICAgIGZvciAodmFyIGkgPSAwICogTWF0aC5QSTsgaSA8IDIgKiBNYXRoLlBJOyBpICs9IGVsbGlwc2VTdGVwU2l6ZSkge1xuICAgICAgeFBvcyA9IGNlbnRlclggLSBydyAqIHNpbltpXSAqIHNpbjAgKyBydyAqIGNvc1tpXSAqIGNvczA7XG4gICAgICB5UG9zID0gY2VudGVyWSArIHJoICogY29zW2ldICogc2luMCArIHJoICogc2luW2ldICogY29zMDtcblxuICAgICAgaWYgKGkgPT09IDApIHtcbiAgICAgICAgY29udGV4dC5tb3ZlVG8oeFBvcywgeVBvcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZXh0LmxpbmVUbyh4UG9zLCB5UG9zKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb250ZXh0LmNsb3NlUGF0aCgpO1xufTtcblxuLyogZ2xvYmFsIGF0b2IsIEFycmF5QnVmZmVyLCBVaW50OEFycmF5LCBCbG9iICovXG52YXIgQ1JwJDggPSB7fTtcblxuQ1JwJDguY3JlYXRlQnVmZmVyID0gZnVuY3Rpb24gKHcsIGgpIHtcbiAgdmFyIGJ1ZmZlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgYnVmZmVyLndpZHRoID0gdztcbiAgYnVmZmVyLmhlaWdodCA9IGg7XG4gIHJldHVybiBbYnVmZmVyLCBidWZmZXIuZ2V0Q29udGV4dCgnMmQnKV07XG59O1xuXG5DUnAkOC5idWZmZXJDYW52YXNJbWFnZSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIHZhciBjeSA9IHRoaXMuY3k7XG4gIHZhciBlbGVzID0gY3kubXV0YWJsZUVsZW1lbnRzKCk7XG4gIHZhciBiYiA9IGVsZXMuYm91bmRpbmdCb3goKTtcbiAgdmFyIGN0clJlY3QgPSB0aGlzLmZpbmRDb250YWluZXJDbGllbnRDb29yZHMoKTtcbiAgdmFyIHdpZHRoID0gb3B0aW9ucy5mdWxsID8gTWF0aC5jZWlsKGJiLncpIDogY3RyUmVjdFsyXTtcbiAgdmFyIGhlaWdodCA9IG9wdGlvbnMuZnVsbCA/IE1hdGguY2VpbChiYi5oKSA6IGN0clJlY3RbM107XG4gIHZhciBzcGVjZE1heERpbXMgPSBudW1iZXIob3B0aW9ucy5tYXhXaWR0aCkgfHwgbnVtYmVyKG9wdGlvbnMubWF4SGVpZ2h0KTtcbiAgdmFyIHB4UmF0aW8gPSB0aGlzLmdldFBpeGVsUmF0aW8oKTtcbiAgdmFyIHNjYWxlID0gMTtcblxuICBpZiAob3B0aW9ucy5zY2FsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgd2lkdGggKj0gb3B0aW9ucy5zY2FsZTtcbiAgICBoZWlnaHQgKj0gb3B0aW9ucy5zY2FsZTtcbiAgICBzY2FsZSA9IG9wdGlvbnMuc2NhbGU7XG4gIH0gZWxzZSBpZiAoc3BlY2RNYXhEaW1zKSB7XG4gICAgdmFyIG1heFNjYWxlVyA9IEluZmluaXR5O1xuICAgIHZhciBtYXhTY2FsZUggPSBJbmZpbml0eTtcblxuICAgIGlmIChudW1iZXIob3B0aW9ucy5tYXhXaWR0aCkpIHtcbiAgICAgIG1heFNjYWxlVyA9IHNjYWxlICogb3B0aW9ucy5tYXhXaWR0aCAvIHdpZHRoO1xuICAgIH1cblxuICAgIGlmIChudW1iZXIob3B0aW9ucy5tYXhIZWlnaHQpKSB7XG4gICAgICBtYXhTY2FsZUggPSBzY2FsZSAqIG9wdGlvbnMubWF4SGVpZ2h0IC8gaGVpZ2h0O1xuICAgIH1cblxuICAgIHNjYWxlID0gTWF0aC5taW4obWF4U2NhbGVXLCBtYXhTY2FsZUgpO1xuICAgIHdpZHRoICo9IHNjYWxlO1xuICAgIGhlaWdodCAqPSBzY2FsZTtcbiAgfVxuXG4gIGlmICghc3BlY2RNYXhEaW1zKSB7XG4gICAgd2lkdGggKj0gcHhSYXRpbztcbiAgICBoZWlnaHQgKj0gcHhSYXRpbztcbiAgICBzY2FsZSAqPSBweFJhdGlvO1xuICB9XG5cbiAgdmFyIGJ1ZmZDYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gIGJ1ZmZDYW52YXMud2lkdGggPSB3aWR0aDtcbiAgYnVmZkNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG4gIGJ1ZmZDYW52YXMuc3R5bGUud2lkdGggPSB3aWR0aCArICdweCc7XG4gIGJ1ZmZDYW52YXMuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgJ3B4JztcbiAgdmFyIGJ1ZmZDeHQgPSBidWZmQ2FudmFzLmdldENvbnRleHQoJzJkJyk7IC8vIFJhc3Rlcml6ZSB0aGUgbGF5ZXJzLCBidXQgb25seSBpZiBjb250YWluZXIgaGFzIG5vbnplcm8gc2l6ZVxuXG4gIGlmICh3aWR0aCA+IDAgJiYgaGVpZ2h0ID4gMCkge1xuICAgIGJ1ZmZDeHQuY2xlYXJSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgIGJ1ZmZDeHQuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gJ3NvdXJjZS1vdmVyJztcbiAgICB2YXIgenNvcnRlZEVsZXMgPSB0aGlzLmdldENhY2hlZFpTb3J0ZWRFbGVzKCk7XG5cbiAgICBpZiAob3B0aW9ucy5mdWxsKSB7XG4gICAgICAvLyBkcmF3IHRoZSBmdWxsIGJvdW5kcyBvZiB0aGUgZ3JhcGhcbiAgICAgIGJ1ZmZDeHQudHJhbnNsYXRlKC1iYi54MSAqIHNjYWxlLCAtYmIueTEgKiBzY2FsZSk7XG4gICAgICBidWZmQ3h0LnNjYWxlKHNjYWxlLCBzY2FsZSk7XG4gICAgICB0aGlzLmRyYXdFbGVtZW50cyhidWZmQ3h0LCB6c29ydGVkRWxlcyk7XG4gICAgICBidWZmQ3h0LnNjYWxlKDEgLyBzY2FsZSwgMSAvIHNjYWxlKTtcbiAgICAgIGJ1ZmZDeHQudHJhbnNsYXRlKGJiLngxICogc2NhbGUsIGJiLnkxICogc2NhbGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBkcmF3IHRoZSBjdXJyZW50IHZpZXdcbiAgICAgIHZhciBwYW4gPSBjeS5wYW4oKTtcbiAgICAgIHZhciB0cmFuc2xhdGlvbiA9IHtcbiAgICAgICAgeDogcGFuLnggKiBzY2FsZSxcbiAgICAgICAgeTogcGFuLnkgKiBzY2FsZVxuICAgICAgfTtcbiAgICAgIHNjYWxlICo9IGN5Lnpvb20oKTtcbiAgICAgIGJ1ZmZDeHQudHJhbnNsYXRlKHRyYW5zbGF0aW9uLngsIHRyYW5zbGF0aW9uLnkpO1xuICAgICAgYnVmZkN4dC5zY2FsZShzY2FsZSwgc2NhbGUpO1xuICAgICAgdGhpcy5kcmF3RWxlbWVudHMoYnVmZkN4dCwgenNvcnRlZEVsZXMpO1xuICAgICAgYnVmZkN4dC5zY2FsZSgxIC8gc2NhbGUsIDEgLyBzY2FsZSk7XG4gICAgICBidWZmQ3h0LnRyYW5zbGF0ZSgtdHJhbnNsYXRpb24ueCwgLXRyYW5zbGF0aW9uLnkpO1xuICAgIH0gLy8gbmVlZCB0byBmaWxsIGJnIGF0IGVuZCBsaWtlIHRoaXMgaW4gb3JkZXIgdG8gZmlsbCBjbGVhcmVkIHRyYW5zcGFyZW50IHBpeGVscyBpbiBqcGdzXG5cblxuICAgIGlmIChvcHRpb25zLmJnKSB7XG4gICAgICBidWZmQ3h0Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9ICdkZXN0aW5hdGlvbi1vdmVyJztcbiAgICAgIGJ1ZmZDeHQuZmlsbFN0eWxlID0gb3B0aW9ucy5iZztcbiAgICAgIGJ1ZmZDeHQucmVjdCgwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIGJ1ZmZDeHQuZmlsbCgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWZmQ2FudmFzO1xufTtcblxuZnVuY3Rpb24gYjY0VG9CbG9iKGI2NCwgbWltZVR5cGUpIHtcbiAgdmFyIGJ5dGVzID0gYXRvYihiNjQpO1xuICB2YXIgYnVmZiA9IG5ldyBBcnJheUJ1ZmZlcihieXRlcy5sZW5ndGgpO1xuICB2YXIgYnVmZlVpbnQ4ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZik7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgIGJ1ZmZVaW50OFtpXSA9IGJ5dGVzLmNoYXJDb2RlQXQoaSk7XG4gIH1cblxuICByZXR1cm4gbmV3IEJsb2IoW2J1ZmZdLCB7XG4gICAgdHlwZTogbWltZVR5cGVcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGI2NFVyaVRvQjY0KGI2NHVyaSkge1xuICB2YXIgaSA9IGI2NHVyaS5pbmRleE9mKCcsJyk7XG4gIHJldHVybiBiNjR1cmkuc3Vic3RyKGkgKyAxKTtcbn1cblxuZnVuY3Rpb24gb3V0cHV0KG9wdGlvbnMsIGNhbnZhcywgbWltZVR5cGUpIHtcbiAgdmFyIGdldEI2NFVyaSA9IGZ1bmN0aW9uIGdldEI2NFVyaSgpIHtcbiAgICByZXR1cm4gY2FudmFzLnRvRGF0YVVSTChtaW1lVHlwZSwgb3B0aW9ucy5xdWFsaXR5KTtcbiAgfTtcblxuICBzd2l0Y2ggKG9wdGlvbnMub3V0cHV0KSB7XG4gICAgY2FzZSAnYmxvYi1wcm9taXNlJzpcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZSQxKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjYW52YXMudG9CbG9iKGZ1bmN0aW9uIChibG9iKSB7XG4gICAgICAgICAgICBpZiAoYmxvYiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgIHJlc29sdmUoYmxvYik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdgY2FudmFzLnRvQmxvYigpYCBzZW50IGEgbnVsbCB2YWx1ZSBpbiBpdHMgY2FsbGJhY2snKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSwgbWltZVR5cGUsIG9wdGlvbnMucXVhbGl0eSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIGNhc2UgJ2Jsb2InOlxuICAgICAgcmV0dXJuIGI2NFRvQmxvYihiNjRVcmlUb0I2NChnZXRCNjRVcmkoKSksIG1pbWVUeXBlKTtcblxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICByZXR1cm4gYjY0VXJpVG9CNjQoZ2V0QjY0VXJpKCkpO1xuXG4gICAgY2FzZSAnYmFzZTY0dXJpJzpcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGdldEI2NFVyaSgpO1xuICB9XG59XG5cbkNScCQ4LnBuZyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIHJldHVybiBvdXRwdXQob3B0aW9ucywgdGhpcy5idWZmZXJDYW52YXNJbWFnZShvcHRpb25zKSwgJ2ltYWdlL3BuZycpO1xufTtcblxuQ1JwJDguanBnID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgcmV0dXJuIG91dHB1dChvcHRpb25zLCB0aGlzLmJ1ZmZlckNhbnZhc0ltYWdlKG9wdGlvbnMpLCAnaW1hZ2UvanBlZycpO1xufTtcblxudmFyIENScCQ5ID0ge307XG5cbkNScCQ5Lm5vZGVTaGFwZUltcGwgPSBmdW5jdGlvbiAobmFtZSwgY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCwgcG9pbnRzKSB7XG4gIHN3aXRjaCAobmFtZSkge1xuICAgIGNhc2UgJ2VsbGlwc2UnOlxuICAgICAgcmV0dXJuIHRoaXMuZHJhd0VsbGlwc2VQYXRoKGNvbnRleHQsIGNlbnRlclgsIGNlbnRlclksIHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgY2FzZSAncG9seWdvbic6XG4gICAgICByZXR1cm4gdGhpcy5kcmF3UG9seWdvblBhdGgoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCwgcG9pbnRzKTtcblxuICAgIGNhc2UgJ3JvdW5kLXBvbHlnb24nOlxuICAgICAgcmV0dXJuIHRoaXMuZHJhd1JvdW5kUG9seWdvblBhdGgoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCwgcG9pbnRzKTtcblxuICAgIGNhc2UgJ3JvdW5kcmVjdGFuZ2xlJzpcbiAgICBjYXNlICdyb3VuZC1yZWN0YW5nbGUnOlxuICAgICAgcmV0dXJuIHRoaXMuZHJhd1JvdW5kUmVjdGFuZ2xlUGF0aChjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0KTtcblxuICAgIGNhc2UgJ2N1dHJlY3RhbmdsZSc6XG4gICAgY2FzZSAnY3V0LXJlY3RhbmdsZSc6XG4gICAgICByZXR1cm4gdGhpcy5kcmF3Q3V0UmVjdGFuZ2xlUGF0aChjb250ZXh0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0KTtcblxuICAgIGNhc2UgJ2JvdHRvbXJvdW5kcmVjdGFuZ2xlJzpcbiAgICBjYXNlICdib3R0b20tcm91bmQtcmVjdGFuZ2xlJzpcbiAgICAgIHJldHVybiB0aGlzLmRyYXdCb3R0b21Sb3VuZFJlY3RhbmdsZVBhdGgoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCk7XG5cbiAgICBjYXNlICdiYXJyZWwnOlxuICAgICAgcmV0dXJuIHRoaXMuZHJhd0JhcnJlbFBhdGgoY29udGV4dCwgY2VudGVyWCwgY2VudGVyWSwgd2lkdGgsIGhlaWdodCk7XG4gIH1cbn07XG5cbnZhciBDUiA9IENhbnZhc1JlbmRlcmVyO1xudmFyIENScCRhID0gQ2FudmFzUmVuZGVyZXIucHJvdG90eXBlO1xuQ1JwJGEuQ0FOVkFTX0xBWUVSUyA9IDM7IC8vXG5cbkNScCRhLlNFTEVDVF9CT1ggPSAwO1xuQ1JwJGEuRFJBRyA9IDE7XG5DUnAkYS5OT0RFID0gMjtcbkNScCRhLkJVRkZFUl9DT1VOVCA9IDM7IC8vXG5cbkNScCRhLlRFWFRVUkVfQlVGRkVSID0gMDtcbkNScCRhLk1PVElPTkJMVVJfQlVGRkVSX05PREUgPSAxO1xuQ1JwJGEuTU9USU9OQkxVUl9CVUZGRVJfRFJBRyA9IDI7XG5cbmZ1bmN0aW9uIENhbnZhc1JlbmRlcmVyKG9wdGlvbnMpIHtcbiAgdmFyIHIgPSB0aGlzO1xuICByLmRhdGEgPSB7XG4gICAgY2FudmFzZXM6IG5ldyBBcnJheShDUnAkYS5DQU5WQVNfTEFZRVJTKSxcbiAgICBjb250ZXh0czogbmV3IEFycmF5KENScCRhLkNBTlZBU19MQVlFUlMpLFxuICAgIGNhbnZhc05lZWRzUmVkcmF3OiBuZXcgQXJyYXkoQ1JwJGEuQ0FOVkFTX0xBWUVSUyksXG4gICAgYnVmZmVyQ2FudmFzZXM6IG5ldyBBcnJheShDUnAkYS5CVUZGRVJfQ09VTlQpLFxuICAgIGJ1ZmZlckNvbnRleHRzOiBuZXcgQXJyYXkoQ1JwJGEuQ0FOVkFTX0xBWUVSUylcbiAgfTtcbiAgdmFyIHRhcEhsT2ZmQXR0ciA9ICctd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3InO1xuICB2YXIgdGFwSGxPZmZTdHlsZSA9ICdyZ2JhKDAsMCwwLDApJztcbiAgci5kYXRhLmNhbnZhc0NvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgdmFyIGNvbnRhaW5lclN0eWxlID0gci5kYXRhLmNhbnZhc0NvbnRhaW5lci5zdHlsZTtcbiAgci5kYXRhLmNhbnZhc0NvbnRhaW5lci5zdHlsZVt0YXBIbE9mZkF0dHJdID0gdGFwSGxPZmZTdHlsZTtcbiAgY29udGFpbmVyU3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICBjb250YWluZXJTdHlsZS56SW5kZXggPSAnMCc7XG4gIGNvbnRhaW5lclN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG4gIHZhciBjb250YWluZXIgPSBvcHRpb25zLmN5LmNvbnRhaW5lcigpO1xuICBjb250YWluZXIuYXBwZW5kQ2hpbGQoci5kYXRhLmNhbnZhc0NvbnRhaW5lcik7XG4gIGNvbnRhaW5lci5zdHlsZVt0YXBIbE9mZkF0dHJdID0gdGFwSGxPZmZTdHlsZTtcbiAgdmFyIHN0eWxlTWFwID0ge1xuICAgICctd2Via2l0LXVzZXItc2VsZWN0JzogJ25vbmUnLFxuICAgICctbW96LXVzZXItc2VsZWN0JzogJy1tb3otbm9uZScsXG4gICAgJ3VzZXItc2VsZWN0JzogJ25vbmUnLFxuICAgICctd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3InOiAncmdiYSgwLDAsMCwwKScsXG4gICAgJ291dGxpbmUtc3R5bGUnOiAnbm9uZSdcbiAgfTtcblxuICBpZiAobXMoKSkge1xuICAgIHN0eWxlTWFwWyctbXMtdG91Y2gtYWN0aW9uJ10gPSAnbm9uZSc7XG4gICAgc3R5bGVNYXBbJ3RvdWNoLWFjdGlvbiddID0gJ25vbmUnO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBDUnAkYS5DQU5WQVNfTEFZRVJTOyBpKyspIHtcbiAgICB2YXIgY2FudmFzID0gci5kYXRhLmNhbnZhc2VzW2ldID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICAgIHIuZGF0YS5jb250ZXh0c1tpXSA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIE9iamVjdC5rZXlzKHN0eWxlTWFwKS5mb3JFYWNoKGZ1bmN0aW9uIChrKSB7XG4gICAgICBjYW52YXMuc3R5bGVba10gPSBzdHlsZU1hcFtrXTtcbiAgICB9KTtcbiAgICBjYW52YXMuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIGNhbnZhcy5zZXRBdHRyaWJ1dGUoJ2RhdGEtaWQnLCAnbGF5ZXInICsgaSk7XG4gICAgY2FudmFzLnN0eWxlLnpJbmRleCA9IFN0cmluZyhDUnAkYS5DQU5WQVNfTEFZRVJTIC0gaSk7XG4gICAgci5kYXRhLmNhbnZhc0NvbnRhaW5lci5hcHBlbmRDaGlsZChjYW52YXMpO1xuICAgIHIuZGF0YS5jYW52YXNOZWVkc1JlZHJhd1tpXSA9IGZhbHNlO1xuICB9XG5cbiAgci5kYXRhLnRvcENhbnZhcyA9IHIuZGF0YS5jYW52YXNlc1swXTtcbiAgci5kYXRhLmNhbnZhc2VzW0NScCRhLk5PREVdLnNldEF0dHJpYnV0ZSgnZGF0YS1pZCcsICdsYXllcicgKyBDUnAkYS5OT0RFICsgJy1ub2RlJyk7XG4gIHIuZGF0YS5jYW52YXNlc1tDUnAkYS5TRUxFQ1RfQk9YXS5zZXRBdHRyaWJ1dGUoJ2RhdGEtaWQnLCAnbGF5ZXInICsgQ1JwJGEuU0VMRUNUX0JPWCArICctc2VsZWN0Ym94Jyk7XG4gIHIuZGF0YS5jYW52YXNlc1tDUnAkYS5EUkFHXS5zZXRBdHRyaWJ1dGUoJ2RhdGEtaWQnLCAnbGF5ZXInICsgQ1JwJGEuRFJBRyArICctZHJhZycpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgQ1JwJGEuQlVGRkVSX0NPVU5UOyBpKyspIHtcbiAgICByLmRhdGEuYnVmZmVyQ2FudmFzZXNbaV0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gICAgci5kYXRhLmJ1ZmZlckNvbnRleHRzW2ldID0gci5kYXRhLmJ1ZmZlckNhbnZhc2VzW2ldLmdldENvbnRleHQoJzJkJyk7XG4gICAgci5kYXRhLmJ1ZmZlckNhbnZhc2VzW2ldLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICByLmRhdGEuYnVmZmVyQ2FudmFzZXNbaV0uc2V0QXR0cmlidXRlKCdkYXRhLWlkJywgJ2J1ZmZlcicgKyBpKTtcbiAgICByLmRhdGEuYnVmZmVyQ2FudmFzZXNbaV0uc3R5bGUuekluZGV4ID0gU3RyaW5nKC1pIC0gMSk7XG4gICAgci5kYXRhLmJ1ZmZlckNhbnZhc2VzW2ldLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJzsgLy9yLmRhdGEuY2FudmFzQ29udGFpbmVyLmFwcGVuZENoaWxkKHIuZGF0YS5idWZmZXJDYW52YXNlc1tpXSk7XG4gIH1cblxuICByLnBhdGhzRW5hYmxlZCA9IHRydWU7XG4gIHZhciBlbXB0eUJiID0gbWFrZUJvdW5kaW5nQm94KCk7XG5cbiAgdmFyIGdldEJveENlbnRlciA9IGZ1bmN0aW9uIGdldEJveENlbnRlcihiYikge1xuICAgIHJldHVybiB7XG4gICAgICB4OiAoYmIueDEgKyBiYi54MikgLyAyLFxuICAgICAgeTogKGJiLnkxICsgYmIueTIpIC8gMlxuICAgIH07XG4gIH07XG5cbiAgdmFyIGdldENlbnRlck9mZnNldCA9IGZ1bmN0aW9uIGdldENlbnRlck9mZnNldChiYikge1xuICAgIHJldHVybiB7XG4gICAgICB4OiAtYmIudyAvIDIsXG4gICAgICB5OiAtYmIuaCAvIDJcbiAgICB9O1xuICB9O1xuXG4gIHZhciBiYWNrZ3JvdW5kVGltZXN0YW1wSGFzQ2hhbmdlZCA9IGZ1bmN0aW9uIGJhY2tncm91bmRUaW1lc3RhbXBIYXNDaGFuZ2VkKGVsZSkge1xuICAgIHZhciBfcCA9IGVsZVswXS5fcHJpdmF0ZTtcbiAgICB2YXIgc2FtZSA9IF9wLm9sZEJhY2tncm91bmRUaW1lc3RhbXAgPT09IF9wLmJhY2tncm91bmRUaW1lc3RhbXA7XG4gICAgcmV0dXJuICFzYW1lO1xuICB9O1xuXG4gIHZhciBnZXRTdHlsZUtleSA9IGZ1bmN0aW9uIGdldFN0eWxlS2V5KGVsZSkge1xuICAgIHJldHVybiBlbGVbMF0uX3ByaXZhdGUubm9kZUtleTtcbiAgfTtcblxuICB2YXIgZ2V0TGFiZWxLZXkgPSBmdW5jdGlvbiBnZXRMYWJlbEtleShlbGUpIHtcbiAgICByZXR1cm4gZWxlWzBdLl9wcml2YXRlLmxhYmVsU3R5bGVLZXk7XG4gIH07XG5cbiAgdmFyIGdldFNvdXJjZUxhYmVsS2V5ID0gZnVuY3Rpb24gZ2V0U291cmNlTGFiZWxLZXkoZWxlKSB7XG4gICAgcmV0dXJuIGVsZVswXS5fcHJpdmF0ZS5zb3VyY2VMYWJlbFN0eWxlS2V5O1xuICB9O1xuXG4gIHZhciBnZXRUYXJnZXRMYWJlbEtleSA9IGZ1bmN0aW9uIGdldFRhcmdldExhYmVsS2V5KGVsZSkge1xuICAgIHJldHVybiBlbGVbMF0uX3ByaXZhdGUudGFyZ2V0TGFiZWxTdHlsZUtleTtcbiAgfTtcblxuICB2YXIgZHJhd0VsZW1lbnQgPSBmdW5jdGlvbiBkcmF3RWxlbWVudChjb250ZXh0LCBlbGUsIGJiLCBzY2FsZWRMYWJlbFNob3duLCB1c2VFbGVPcGFjaXR5KSB7XG4gICAgcmV0dXJuIHIuZHJhd0VsZW1lbnQoY29udGV4dCwgZWxlLCBiYiwgZmFsc2UsIGZhbHNlLCB1c2VFbGVPcGFjaXR5KTtcbiAgfTtcblxuICB2YXIgZHJhd0xhYmVsID0gZnVuY3Rpb24gZHJhd0xhYmVsKGNvbnRleHQsIGVsZSwgYmIsIHNjYWxlZExhYmVsU2hvd24sIHVzZUVsZU9wYWNpdHkpIHtcbiAgICByZXR1cm4gci5kcmF3RWxlbWVudFRleHQoY29udGV4dCwgZWxlLCBiYiwgc2NhbGVkTGFiZWxTaG93biwgJ21haW4nLCB1c2VFbGVPcGFjaXR5KTtcbiAgfTtcblxuICB2YXIgZHJhd1NvdXJjZUxhYmVsID0gZnVuY3Rpb24gZHJhd1NvdXJjZUxhYmVsKGNvbnRleHQsIGVsZSwgYmIsIHNjYWxlZExhYmVsU2hvd24sIHVzZUVsZU9wYWNpdHkpIHtcbiAgICByZXR1cm4gci5kcmF3RWxlbWVudFRleHQoY29udGV4dCwgZWxlLCBiYiwgc2NhbGVkTGFiZWxTaG93biwgJ3NvdXJjZScsIHVzZUVsZU9wYWNpdHkpO1xuICB9O1xuXG4gIHZhciBkcmF3VGFyZ2V0TGFiZWwgPSBmdW5jdGlvbiBkcmF3VGFyZ2V0TGFiZWwoY29udGV4dCwgZWxlLCBiYiwgc2NhbGVkTGFiZWxTaG93biwgdXNlRWxlT3BhY2l0eSkge1xuICAgIHJldHVybiByLmRyYXdFbGVtZW50VGV4dChjb250ZXh0LCBlbGUsIGJiLCBzY2FsZWRMYWJlbFNob3duLCAndGFyZ2V0JywgdXNlRWxlT3BhY2l0eSk7XG4gIH07XG5cbiAgdmFyIGdldEVsZW1lbnRCb3ggPSBmdW5jdGlvbiBnZXRFbGVtZW50Qm94KGVsZSkge1xuICAgIGVsZS5ib3VuZGluZ0JveCgpO1xuICAgIHJldHVybiBlbGVbMF0uX3ByaXZhdGUuYm9keUJvdW5kcztcbiAgfTtcblxuICB2YXIgZ2V0TGFiZWxCb3ggPSBmdW5jdGlvbiBnZXRMYWJlbEJveChlbGUpIHtcbiAgICBlbGUuYm91bmRpbmdCb3goKTtcbiAgICByZXR1cm4gZWxlWzBdLl9wcml2YXRlLmxhYmVsQm91bmRzLm1haW4gfHwgZW1wdHlCYjtcbiAgfTtcblxuICB2YXIgZ2V0U291cmNlTGFiZWxCb3ggPSBmdW5jdGlvbiBnZXRTb3VyY2VMYWJlbEJveChlbGUpIHtcbiAgICBlbGUuYm91bmRpbmdCb3goKTtcbiAgICByZXR1cm4gZWxlWzBdLl9wcml2YXRlLmxhYmVsQm91bmRzLnNvdXJjZSB8fCBlbXB0eUJiO1xuICB9O1xuXG4gIHZhciBnZXRUYXJnZXRMYWJlbEJveCA9IGZ1bmN0aW9uIGdldFRhcmdldExhYmVsQm94KGVsZSkge1xuICAgIGVsZS5ib3VuZGluZ0JveCgpO1xuICAgIHJldHVybiBlbGVbMF0uX3ByaXZhdGUubGFiZWxCb3VuZHMudGFyZ2V0IHx8IGVtcHR5QmI7XG4gIH07XG5cbiAgdmFyIGlzTGFiZWxWaXNpYmxlQXRTY2FsZSA9IGZ1bmN0aW9uIGlzTGFiZWxWaXNpYmxlQXRTY2FsZShlbGUsIHNjYWxlZExhYmVsU2hvd24pIHtcbiAgICByZXR1cm4gc2NhbGVkTGFiZWxTaG93bjtcbiAgfTtcblxuICB2YXIgZ2V0RWxlbWVudFJvdGF0aW9uUG9pbnQgPSBmdW5jdGlvbiBnZXRFbGVtZW50Um90YXRpb25Qb2ludChlbGUpIHtcbiAgICByZXR1cm4gZ2V0Qm94Q2VudGVyKGdldEVsZW1lbnRCb3goZWxlKSk7XG4gIH07XG5cbiAgdmFyIGFkZFRleHRNYXJnaW4gPSBmdW5jdGlvbiBhZGRUZXh0TWFyZ2luKHByZWZpeCwgcHQsIGVsZSkge1xuICAgIHZhciBwcmUgPSBwcmVmaXggPyBwcmVmaXggKyAnLScgOiAnJztcbiAgICByZXR1cm4ge1xuICAgICAgeDogcHQueCArIGVsZS5wc3R5bGUocHJlICsgJ3RleHQtbWFyZ2luLXgnKS5wZlZhbHVlLFxuICAgICAgeTogcHQueSArIGVsZS5wc3R5bGUocHJlICsgJ3RleHQtbWFyZ2luLXknKS5wZlZhbHVlXG4gICAgfTtcbiAgfTtcblxuICB2YXIgZ2V0UnNQdCA9IGZ1bmN0aW9uIGdldFJzUHQoZWxlLCB4LCB5KSB7XG4gICAgdmFyIHJzID0gZWxlWzBdLl9wcml2YXRlLnJzY3JhdGNoO1xuICAgIHJldHVybiB7XG4gICAgICB4OiByc1t4XSxcbiAgICAgIHk6IHJzW3ldXG4gICAgfTtcbiAgfTtcblxuICB2YXIgZ2V0TGFiZWxSb3RhdGlvblBvaW50ID0gZnVuY3Rpb24gZ2V0TGFiZWxSb3RhdGlvblBvaW50KGVsZSkge1xuICAgIHJldHVybiBhZGRUZXh0TWFyZ2luKCcnLCBnZXRSc1B0KGVsZSwgJ2xhYmVsWCcsICdsYWJlbFknKSwgZWxlKTtcbiAgfTtcblxuICB2YXIgZ2V0U291cmNlTGFiZWxSb3RhdGlvblBvaW50ID0gZnVuY3Rpb24gZ2V0U291cmNlTGFiZWxSb3RhdGlvblBvaW50KGVsZSkge1xuICAgIHJldHVybiBhZGRUZXh0TWFyZ2luKCdzb3VyY2UnLCBnZXRSc1B0KGVsZSwgJ3NvdXJjZUxhYmVsWCcsICdzb3VyY2VMYWJlbFknKSwgZWxlKTtcbiAgfTtcblxuICB2YXIgZ2V0VGFyZ2V0TGFiZWxSb3RhdGlvblBvaW50ID0gZnVuY3Rpb24gZ2V0VGFyZ2V0TGFiZWxSb3RhdGlvblBvaW50KGVsZSkge1xuICAgIHJldHVybiBhZGRUZXh0TWFyZ2luKCd0YXJnZXQnLCBnZXRSc1B0KGVsZSwgJ3RhcmdldExhYmVsWCcsICd0YXJnZXRMYWJlbFknKSwgZWxlKTtcbiAgfTtcblxuICB2YXIgZ2V0RWxlbWVudFJvdGF0aW9uT2Zmc2V0ID0gZnVuY3Rpb24gZ2V0RWxlbWVudFJvdGF0aW9uT2Zmc2V0KGVsZSkge1xuICAgIHJldHVybiBnZXRDZW50ZXJPZmZzZXQoZ2V0RWxlbWVudEJveChlbGUpKTtcbiAgfTtcblxuICB2YXIgZ2V0U291cmNlTGFiZWxSb3RhdGlvbk9mZnNldCA9IGZ1bmN0aW9uIGdldFNvdXJjZUxhYmVsUm90YXRpb25PZmZzZXQoZWxlKSB7XG4gICAgcmV0dXJuIGdldENlbnRlck9mZnNldChnZXRTb3VyY2VMYWJlbEJveChlbGUpKTtcbiAgfTtcblxuICB2YXIgZ2V0VGFyZ2V0TGFiZWxSb3RhdGlvbk9mZnNldCA9IGZ1bmN0aW9uIGdldFRhcmdldExhYmVsUm90YXRpb25PZmZzZXQoZWxlKSB7XG4gICAgcmV0dXJuIGdldENlbnRlck9mZnNldChnZXRUYXJnZXRMYWJlbEJveChlbGUpKTtcbiAgfTtcblxuICB2YXIgZ2V0TGFiZWxSb3RhdGlvbk9mZnNldCA9IGZ1bmN0aW9uIGdldExhYmVsUm90YXRpb25PZmZzZXQoZWxlKSB7XG4gICAgdmFyIGJiID0gZ2V0TGFiZWxCb3goZWxlKTtcbiAgICB2YXIgcCA9IGdldENlbnRlck9mZnNldChnZXRMYWJlbEJveChlbGUpKTtcblxuICAgIGlmIChlbGUuaXNOb2RlKCkpIHtcbiAgICAgIHN3aXRjaCAoZWxlLnBzdHlsZSgndGV4dC1oYWxpZ24nKS52YWx1ZSkge1xuICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgICBwLnggPSAtYmIudztcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgICAgcC54ID0gMDtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgc3dpdGNoIChlbGUucHN0eWxlKCd0ZXh0LXZhbGlnbicpLnZhbHVlKSB7XG4gICAgICAgIGNhc2UgJ3RvcCc6XG4gICAgICAgICAgcC55ID0gLWJiLmg7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgICBwLnkgPSAwO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwO1xuICB9O1xuXG4gIHZhciBlbGVUeHJDYWNoZSA9IHIuZGF0YS5lbGVUeHJDYWNoZSA9IG5ldyBFbGVtZW50VGV4dHVyZUNhY2hlKHIsIHtcbiAgICBnZXRLZXk6IGdldFN0eWxlS2V5LFxuICAgIGRvZXNFbGVJbnZhbGlkYXRlS2V5OiBiYWNrZ3JvdW5kVGltZXN0YW1wSGFzQ2hhbmdlZCxcbiAgICBkcmF3RWxlbWVudDogZHJhd0VsZW1lbnQsXG4gICAgZ2V0Qm91bmRpbmdCb3g6IGdldEVsZW1lbnRCb3gsXG4gICAgZ2V0Um90YXRpb25Qb2ludDogZ2V0RWxlbWVudFJvdGF0aW9uUG9pbnQsXG4gICAgZ2V0Um90YXRpb25PZmZzZXQ6IGdldEVsZW1lbnRSb3RhdGlvbk9mZnNldCxcbiAgICBhbGxvd0VkZ2VUeHJDYWNoaW5nOiBmYWxzZSxcbiAgICBhbGxvd1BhcmVudFR4ckNhY2hpbmc6IGZhbHNlXG4gIH0pO1xuICB2YXIgbGJsVHhyQ2FjaGUgPSByLmRhdGEubGJsVHhyQ2FjaGUgPSBuZXcgRWxlbWVudFRleHR1cmVDYWNoZShyLCB7XG4gICAgZ2V0S2V5OiBnZXRMYWJlbEtleSxcbiAgICBkcmF3RWxlbWVudDogZHJhd0xhYmVsLFxuICAgIGdldEJvdW5kaW5nQm94OiBnZXRMYWJlbEJveCxcbiAgICBnZXRSb3RhdGlvblBvaW50OiBnZXRMYWJlbFJvdGF0aW9uUG9pbnQsXG4gICAgZ2V0Um90YXRpb25PZmZzZXQ6IGdldExhYmVsUm90YXRpb25PZmZzZXQsXG4gICAgaXNWaXNpYmxlOiBpc0xhYmVsVmlzaWJsZUF0U2NhbGVcbiAgfSk7XG4gIHZhciBzbGJUeHJDYWNoZSA9IHIuZGF0YS5zbGJUeHJDYWNoZSA9IG5ldyBFbGVtZW50VGV4dHVyZUNhY2hlKHIsIHtcbiAgICBnZXRLZXk6IGdldFNvdXJjZUxhYmVsS2V5LFxuICAgIGRyYXdFbGVtZW50OiBkcmF3U291cmNlTGFiZWwsXG4gICAgZ2V0Qm91bmRpbmdCb3g6IGdldFNvdXJjZUxhYmVsQm94LFxuICAgIGdldFJvdGF0aW9uUG9pbnQ6IGdldFNvdXJjZUxhYmVsUm90YXRpb25Qb2ludCxcbiAgICBnZXRSb3RhdGlvbk9mZnNldDogZ2V0U291cmNlTGFiZWxSb3RhdGlvbk9mZnNldCxcbiAgICBpc1Zpc2libGU6IGlzTGFiZWxWaXNpYmxlQXRTY2FsZVxuICB9KTtcbiAgdmFyIHRsYlR4ckNhY2hlID0gci5kYXRhLnRsYlR4ckNhY2hlID0gbmV3IEVsZW1lbnRUZXh0dXJlQ2FjaGUociwge1xuICAgIGdldEtleTogZ2V0VGFyZ2V0TGFiZWxLZXksXG4gICAgZHJhd0VsZW1lbnQ6IGRyYXdUYXJnZXRMYWJlbCxcbiAgICBnZXRCb3VuZGluZ0JveDogZ2V0VGFyZ2V0TGFiZWxCb3gsXG4gICAgZ2V0Um90YXRpb25Qb2ludDogZ2V0VGFyZ2V0TGFiZWxSb3RhdGlvblBvaW50LFxuICAgIGdldFJvdGF0aW9uT2Zmc2V0OiBnZXRUYXJnZXRMYWJlbFJvdGF0aW9uT2Zmc2V0LFxuICAgIGlzVmlzaWJsZTogaXNMYWJlbFZpc2libGVBdFNjYWxlXG4gIH0pO1xuICB2YXIgbHlyVHhyQ2FjaGUgPSByLmRhdGEubHlyVHhyQ2FjaGUgPSBuZXcgTGF5ZXJlZFRleHR1cmVDYWNoZShyKTtcbiAgci5vblVwZGF0ZUVsZUNhbGNzKGZ1bmN0aW9uIGludmFsaWRhdGVUZXh0dXJlQ2FjaGVzKHdpbGxEcmF3LCBlbGVzKSB7XG4gICAgLy8gZWFjaCBjYWNoZSBzaG91bGQgY2hlY2sgZm9yIHN1Yi1rZXkgZGlmZiB0byBzZWUgdGhhdCB0aGUgdXBkYXRlIGFmZmVjdHMgdGhhdCBjYWNoZSBwYXJ0aWN1bGFybHlcbiAgICBlbGVUeHJDYWNoZS5pbnZhbGlkYXRlRWxlbWVudHMoZWxlcyk7XG4gICAgbGJsVHhyQ2FjaGUuaW52YWxpZGF0ZUVsZW1lbnRzKGVsZXMpO1xuICAgIHNsYlR4ckNhY2hlLmludmFsaWRhdGVFbGVtZW50cyhlbGVzKTtcbiAgICB0bGJUeHJDYWNoZS5pbnZhbGlkYXRlRWxlbWVudHMoZWxlcyk7IC8vIGFueSBjaGFuZ2UgaW52YWxpZGF0ZXMgdGhlIGxheWVyc1xuXG4gICAgbHlyVHhyQ2FjaGUuaW52YWxpZGF0ZUVsZW1lbnRzKGVsZXMpOyAvLyB1cGRhdGUgdGhlIG9sZCBiZyB0aW1lc3RhbXAgc28gZGlmZnMgY2FuIGJlIGRvbmUgaW4gdGhlIGVsZSB0eHIgY2FjaGVzXG5cbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgZWxlcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgIHZhciBfcCA9IGVsZXNbX2ldLl9wcml2YXRlO1xuICAgICAgX3Aub2xkQmFja2dyb3VuZFRpbWVzdGFtcCA9IF9wLmJhY2tncm91bmRUaW1lc3RhbXA7XG4gICAgfVxuICB9KTtcblxuICB2YXIgcmVmaW5lSW5MYXllcnMgPSBmdW5jdGlvbiByZWZpbmVJbkxheWVycyhyZXFzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXFzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBseXJUeHJDYWNoZS5lbnF1ZXVlRWxlbWVudFJlZmluZW1lbnQocmVxc1tpXS5lbGUpO1xuICAgIH1cbiAgfTtcblxuICBlbGVUeHJDYWNoZS5vbkRlcXVldWUocmVmaW5lSW5MYXllcnMpO1xuICBsYmxUeHJDYWNoZS5vbkRlcXVldWUocmVmaW5lSW5MYXllcnMpO1xuICBzbGJUeHJDYWNoZS5vbkRlcXVldWUocmVmaW5lSW5MYXllcnMpO1xuICB0bGJUeHJDYWNoZS5vbkRlcXVldWUocmVmaW5lSW5MYXllcnMpO1xufVxuXG5DUnAkYS5yZWRyYXdIaW50ID0gZnVuY3Rpb24gKGdyb3VwLCBib29sKSB7XG4gIHZhciByID0gdGhpcztcblxuICBzd2l0Y2ggKGdyb3VwKSB7XG4gICAgY2FzZSAnZWxlcyc6XG4gICAgICByLmRhdGEuY2FudmFzTmVlZHNSZWRyYXdbQ1JwJGEuTk9ERV0gPSBib29sO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdkcmFnJzpcbiAgICAgIHIuZGF0YS5jYW52YXNOZWVkc1JlZHJhd1tDUnAkYS5EUkFHXSA9IGJvb2w7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3NlbGVjdCc6XG4gICAgICByLmRhdGEuY2FudmFzTmVlZHNSZWRyYXdbQ1JwJGEuU0VMRUNUX0JPWF0gPSBib29sO1xuICAgICAgYnJlYWs7XG4gIH1cbn07IC8vIHdoZXRoZXIgdG8gdXNlIFBhdGgyRCBjYWNoaW5nIGZvciBkcmF3aW5nXG5cblxudmFyIHBhdGhzSW1wbGQgPSB0eXBlb2YgUGF0aDJEICE9PSAndW5kZWZpbmVkJztcblxuQ1JwJGEucGF0aDJkRW5hYmxlZCA9IGZ1bmN0aW9uIChvbikge1xuICBpZiAob24gPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB0aGlzLnBhdGhzRW5hYmxlZDtcbiAgfVxuXG4gIHRoaXMucGF0aHNFbmFibGVkID0gb24gPyB0cnVlIDogZmFsc2U7XG59O1xuXG5DUnAkYS51c2VQYXRocyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHBhdGhzSW1wbGQgJiYgdGhpcy5wYXRoc0VuYWJsZWQ7XG59O1xuXG5DUnAkYS5zZXRJbWdTbW9vdGhpbmcgPSBmdW5jdGlvbiAoY29udGV4dCwgYm9vbCkge1xuICBpZiAoY29udGV4dC5pbWFnZVNtb290aGluZ0VuYWJsZWQgIT0gbnVsbCkge1xuICAgIGNvbnRleHQuaW1hZ2VTbW9vdGhpbmdFbmFibGVkID0gYm9vbDtcbiAgfSBlbHNlIHtcbiAgICBjb250ZXh0LndlYmtpdEltYWdlU21vb3RoaW5nRW5hYmxlZCA9IGJvb2w7XG4gICAgY29udGV4dC5tb3pJbWFnZVNtb290aGluZ0VuYWJsZWQgPSBib29sO1xuICAgIGNvbnRleHQubXNJbWFnZVNtb290aGluZ0VuYWJsZWQgPSBib29sO1xuICB9XG59O1xuXG5DUnAkYS5nZXRJbWdTbW9vdGhpbmcgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICBpZiAoY29udGV4dC5pbWFnZVNtb290aGluZ0VuYWJsZWQgIT0gbnVsbCkge1xuICAgIHJldHVybiBjb250ZXh0LmltYWdlU21vb3RoaW5nRW5hYmxlZDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29udGV4dC53ZWJraXRJbWFnZVNtb290aGluZ0VuYWJsZWQgfHwgY29udGV4dC5tb3pJbWFnZVNtb290aGluZ0VuYWJsZWQgfHwgY29udGV4dC5tc0ltYWdlU21vb3RoaW5nRW5hYmxlZDtcbiAgfVxufTtcblxuQ1JwJGEubWFrZU9mZnNjcmVlbkNhbnZhcyA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0KSB7XG4gIHZhciBjYW52YXM7XG5cbiAgaWYgKCh0eXBlb2YgT2Zmc2NyZWVuQ2FudmFzID09PSBcInVuZGVmaW5lZFwiID8gXCJ1bmRlZmluZWRcIiA6IF90eXBlb2YoT2Zmc2NyZWVuQ2FudmFzKSkgIT09ICggXCJ1bmRlZmluZWRcIiApKSB7XG4gICAgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTtcbiAgfSBlbHNlIHtcbiAgICBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4gICAgY2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgfVxuXG4gIHJldHVybiBjYW52YXM7XG59O1xuXG5bQ1JwLCBDUnAkMSwgQ1JwJDIsIENScCQzLCBDUnAkNCwgQ1JwJDUsIENScCQ2LCBDUnAkNywgQ1JwJDgsIENScCQ5XS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wcykge1xuICBleHRlbmQoQ1JwJGEsIHByb3BzKTtcbn0pO1xuXG52YXIgcmVuZGVyZXIgPSBbe1xuICBuYW1lOiAnbnVsbCcsXG4gIGltcGw6IE51bGxSZW5kZXJlclxufSwge1xuICBuYW1lOiAnYmFzZScsXG4gIGltcGw6IEJSXG59LCB7XG4gIG5hbWU6ICdjYW52YXMnLFxuICBpbXBsOiBDUlxufV07XG5cbnZhciBpbmNFeHRzID0gW3tcbiAgdHlwZTogJ2xheW91dCcsXG4gIGV4dGVuc2lvbnM6IGxheW91dFxufSwge1xuICB0eXBlOiAncmVuZGVyZXInLFxuICBleHRlbnNpb25zOiByZW5kZXJlclxufV07XG5cbnZhciBleHRlbnNpb25zID0ge307IC8vIHJlZ2lzdGVyZWQgbW9kdWxlcyBmb3IgZXh0ZW5zaW9ucywgaW5kZXhlZCBieSBuYW1lXG5cbnZhciBtb2R1bGVzID0ge307XG5cbmZ1bmN0aW9uIHNldEV4dGVuc2lvbih0eXBlLCBuYW1lLCByZWdpc3RyYW50KSB7XG4gIHZhciBleHQgPSByZWdpc3RyYW50O1xuXG4gIHZhciBvdmVycmlkZUVyciA9IGZ1bmN0aW9uIG92ZXJyaWRlRXJyKGZpZWxkKSB7XG4gICAgZXJyb3IoJ0NhbiBub3QgcmVnaXN0ZXIgYCcgKyBuYW1lICsgJ2AgZm9yIGAnICsgdHlwZSArICdgIHNpbmNlIGAnICsgZmllbGQgKyAnYCBhbHJlYWR5IGV4aXN0cyBpbiB0aGUgcHJvdG90eXBlIGFuZCBjYW4gbm90IGJlIG92ZXJyaWRkZW4nKTtcbiAgfTtcblxuICBpZiAodHlwZSA9PT0gJ2NvcmUnKSB7XG4gICAgaWYgKENvcmUucHJvdG90eXBlW25hbWVdKSB7XG4gICAgICByZXR1cm4gb3ZlcnJpZGVFcnIobmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIENvcmUucHJvdG90eXBlW25hbWVdID0gcmVnaXN0cmFudDtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2NvbGxlY3Rpb24nKSB7XG4gICAgaWYgKENvbGxlY3Rpb24ucHJvdG90eXBlW25hbWVdKSB7XG4gICAgICByZXR1cm4gb3ZlcnJpZGVFcnIobmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIENvbGxlY3Rpb24ucHJvdG90eXBlW25hbWVdID0gcmVnaXN0cmFudDtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2xheW91dCcpIHtcbiAgICAvLyBmaWxsIGluIG1pc3NpbmcgbGF5b3V0IGZ1bmN0aW9ucyBpbiB0aGUgcHJvdG90eXBlXG4gICAgdmFyIExheW91dCA9IGZ1bmN0aW9uIExheW91dChvcHRpb25zKSB7XG4gICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgcmVnaXN0cmFudC5jYWxsKHRoaXMsIG9wdGlvbnMpOyAvLyBtYWtlIHN1cmUgbGF5b3V0IGhhcyBfcHJpdmF0ZSBmb3IgdXNlIHcvIHN0ZCBhcGlzIGxpa2UgLm9uKClcblxuICAgICAgaWYgKCFwbGFpbk9iamVjdCh0aGlzLl9wcml2YXRlKSkge1xuICAgICAgICB0aGlzLl9wcml2YXRlID0ge307XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3ByaXZhdGUuY3kgPSBvcHRpb25zLmN5O1xuICAgICAgdGhpcy5fcHJpdmF0ZS5saXN0ZW5lcnMgPSBbXTtcbiAgICAgIHRoaXMuY3JlYXRlRW1pdHRlcigpO1xuICAgIH07XG5cbiAgICB2YXIgbGF5b3V0UHJvdG8gPSBMYXlvdXQucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShyZWdpc3RyYW50LnByb3RvdHlwZSk7XG4gICAgdmFyIG9wdExheW91dEZucyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvcHRMYXlvdXRGbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBmbk5hbWUgPSBvcHRMYXlvdXRGbnNbaV07XG5cbiAgICAgIGxheW91dFByb3RvW2ZuTmFtZV0gPSBsYXlvdXRQcm90b1tmbk5hbWVdIHx8IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9O1xuICAgIH0gLy8gZWl0aGVyIC5zdGFydCgpIG9yIC5ydW4oKSBpcyBkZWZpbmVkLCBzbyBhdXRvZ2VuIHRoZSBvdGhlclxuXG5cbiAgICBpZiAobGF5b3V0UHJvdG8uc3RhcnQgJiYgIWxheW91dFByb3RvLnJ1bikge1xuICAgICAgbGF5b3V0UHJvdG8ucnVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKCFsYXlvdXRQcm90by5zdGFydCAmJiBsYXlvdXRQcm90by5ydW4pIHtcbiAgICAgIGxheW91dFByb3RvLnN0YXJ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJ1bigpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIHJlZ1N0b3AgPSByZWdpc3RyYW50LnByb3RvdHlwZS5zdG9wO1xuXG4gICAgbGF5b3V0UHJvdG8uc3RvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBvcHRzID0gdGhpcy5vcHRpb25zO1xuXG4gICAgICBpZiAob3B0cyAmJiBvcHRzLmFuaW1hdGUpIHtcbiAgICAgICAgdmFyIGFuaXMgPSB0aGlzLmFuaW1hdGlvbnM7XG5cbiAgICAgICAgaWYgKGFuaXMpIHtcbiAgICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYW5pcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGFuaXNbX2ldLnN0b3AoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHJlZ1N0b3ApIHtcbiAgICAgICAgcmVnU3RvcC5jYWxsKHRoaXMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5lbWl0KCdsYXlvdXRzdG9wJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICBpZiAoIWxheW91dFByb3RvLmRlc3Ryb3kpIHtcbiAgICAgIGxheW91dFByb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBsYXlvdXRQcm90by5jeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9wcml2YXRlLmN5O1xuICAgIH07XG5cbiAgICB2YXIgZ2V0Q3kgPSBmdW5jdGlvbiBnZXRDeShsYXlvdXQpIHtcbiAgICAgIHJldHVybiBsYXlvdXQuX3ByaXZhdGUuY3k7XG4gICAgfTtcblxuICAgIHZhciBlbWl0dGVyT3B0cyA9IHtcbiAgICAgIGFkZEV2ZW50RmllbGRzOiBmdW5jdGlvbiBhZGRFdmVudEZpZWxkcyhsYXlvdXQsIGV2dCkge1xuICAgICAgICBldnQubGF5b3V0ID0gbGF5b3V0O1xuICAgICAgICBldnQuY3kgPSBnZXRDeShsYXlvdXQpO1xuICAgICAgICBldnQudGFyZ2V0ID0gbGF5b3V0O1xuICAgICAgfSxcbiAgICAgIGJ1YmJsZTogZnVuY3Rpb24gYnViYmxlKCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgICBwYXJlbnQ6IGZ1bmN0aW9uIHBhcmVudChsYXlvdXQpIHtcbiAgICAgICAgcmV0dXJuIGdldEN5KGxheW91dCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBleHRlbmQobGF5b3V0UHJvdG8sIHtcbiAgICAgIGNyZWF0ZUVtaXR0ZXI6IGZ1bmN0aW9uIGNyZWF0ZUVtaXR0ZXIoKSB7XG4gICAgICAgIHRoaXMuX3ByaXZhdGUuZW1pdHRlciA9IG5ldyBFbWl0dGVyKGVtaXR0ZXJPcHRzLCB0aGlzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9LFxuICAgICAgZW1pdHRlcjogZnVuY3Rpb24gZW1pdHRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ByaXZhdGUuZW1pdHRlcjtcbiAgICAgIH0sXG4gICAgICBvbjogZnVuY3Rpb24gb24oZXZ0LCBjYikge1xuICAgICAgICB0aGlzLmVtaXR0ZXIoKS5vbihldnQsIGNiKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9LFxuICAgICAgb25lOiBmdW5jdGlvbiBvbmUoZXZ0LCBjYikge1xuICAgICAgICB0aGlzLmVtaXR0ZXIoKS5vbmUoZXZ0LCBjYik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSxcbiAgICAgIG9uY2U6IGZ1bmN0aW9uIG9uY2UoZXZ0LCBjYikge1xuICAgICAgICB0aGlzLmVtaXR0ZXIoKS5vbmUoZXZ0LCBjYik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSxcbiAgICAgIHJlbW92ZUxpc3RlbmVyOiBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldnQsIGNiKSB7XG4gICAgICAgIHRoaXMuZW1pdHRlcigpLnJlbW92ZUxpc3RlbmVyKGV2dCwgY2IpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH0sXG4gICAgICByZW1vdmVBbGxMaXN0ZW5lcnM6IGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycygpIHtcbiAgICAgICAgdGhpcy5lbWl0dGVyKCkucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSxcbiAgICAgIGVtaXQ6IGZ1bmN0aW9uIGVtaXQoZXZ0LCBwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5lbWl0dGVyKCkuZW1pdChldnQsIHBhcmFtcyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGRlZmluZSQzLmV2ZW50QWxpYXNlc09uKGxheW91dFByb3RvKTtcbiAgICBleHQgPSBMYXlvdXQ7IC8vIHJlcGxhY2Ugd2l0aCBvdXIgd3JhcHBlZCBsYXlvdXRcbiAgfSBlbHNlIGlmICh0eXBlID09PSAncmVuZGVyZXInICYmIG5hbWUgIT09ICdudWxsJyAmJiBuYW1lICE9PSAnYmFzZScpIHtcbiAgICAvLyB1c2VyIHJlZ2lzdGVyZWQgcmVuZGVyZXJzIGluaGVyaXQgZnJvbSBiYXNlXG4gICAgdmFyIEJhc2VSZW5kZXJlciA9IGdldEV4dGVuc2lvbigncmVuZGVyZXInLCAnYmFzZScpO1xuICAgIHZhciBiUHJvdG8gPSBCYXNlUmVuZGVyZXIucHJvdG90eXBlO1xuICAgIHZhciBSZWdpc3RyYW50UmVuZGVyZXIgPSByZWdpc3RyYW50O1xuICAgIHZhciByUHJvdG8gPSByZWdpc3RyYW50LnByb3RvdHlwZTtcblxuICAgIHZhciBSZW5kZXJlciA9IGZ1bmN0aW9uIFJlbmRlcmVyKCkge1xuICAgICAgQmFzZVJlbmRlcmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBSZWdpc3RyYW50UmVuZGVyZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuXG4gICAgdmFyIHByb3RvID0gUmVuZGVyZXIucHJvdG90eXBlO1xuXG4gICAgZm9yICh2YXIgcE5hbWUgaW4gYlByb3RvKSB7XG4gICAgICB2YXIgcFZhbCA9IGJQcm90b1twTmFtZV07XG4gICAgICB2YXIgZXhpc3RzSW5SID0gclByb3RvW3BOYW1lXSAhPSBudWxsO1xuXG4gICAgICBpZiAoZXhpc3RzSW5SKSB7XG4gICAgICAgIHJldHVybiBvdmVycmlkZUVycihwTmFtZSk7XG4gICAgICB9XG5cbiAgICAgIHByb3RvW3BOYW1lXSA9IHBWYWw7IC8vIHRha2UgaW1wbCBmcm9tIGJhc2VcbiAgICB9XG5cbiAgICBmb3IgKHZhciBfcE5hbWUgaW4gclByb3RvKSB7XG4gICAgICBwcm90b1tfcE5hbWVdID0gclByb3RvW19wTmFtZV07IC8vIHRha2UgaW1wbCBmcm9tIHJlZ2lzdHJhbnRcbiAgICB9XG5cbiAgICBiUHJvdG8uY2xpZW50RnVuY3Rpb25zLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgIHByb3RvW25hbWVdID0gcHJvdG9bbmFtZV0gfHwgZnVuY3Rpb24gKCkge1xuICAgICAgICBlcnJvcignUmVuZGVyZXIgZG9lcyBub3QgaW1wbGVtZW50IGByZW5kZXJlci4nICsgbmFtZSArICcoKWAgb24gaXRzIHByb3RvdHlwZScpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgICBleHQgPSBSZW5kZXJlcjtcbiAgfVxuXG4gIHJldHVybiBzZXRNYXAoe1xuICAgIG1hcDogZXh0ZW5zaW9ucyxcbiAgICBrZXlzOiBbdHlwZSwgbmFtZV0sXG4gICAgdmFsdWU6IGV4dFxuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0RXh0ZW5zaW9uKHR5cGUsIG5hbWUpIHtcbiAgcmV0dXJuIGdldE1hcCh7XG4gICAgbWFwOiBleHRlbnNpb25zLFxuICAgIGtleXM6IFt0eXBlLCBuYW1lXVxuICB9KTtcbn1cblxuZnVuY3Rpb24gc2V0TW9kdWxlKHR5cGUsIG5hbWUsIG1vZHVsZVR5cGUsIG1vZHVsZU5hbWUsIHJlZ2lzdHJhbnQpIHtcbiAgcmV0dXJuIHNldE1hcCh7XG4gICAgbWFwOiBtb2R1bGVzLFxuICAgIGtleXM6IFt0eXBlLCBuYW1lLCBtb2R1bGVUeXBlLCBtb2R1bGVOYW1lXSxcbiAgICB2YWx1ZTogcmVnaXN0cmFudFxuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0TW9kdWxlKHR5cGUsIG5hbWUsIG1vZHVsZVR5cGUsIG1vZHVsZU5hbWUpIHtcbiAgcmV0dXJuIGdldE1hcCh7XG4gICAgbWFwOiBtb2R1bGVzLFxuICAgIGtleXM6IFt0eXBlLCBuYW1lLCBtb2R1bGVUeXBlLCBtb2R1bGVOYW1lXVxuICB9KTtcbn1cblxudmFyIGV4dGVuc2lvbiA9IGZ1bmN0aW9uIGV4dGVuc2lvbigpIHtcbiAgLy8gZS5nLiBleHRlbnNpb24oJ3JlbmRlcmVyJywgJ3N2ZycpXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7XG4gICAgcmV0dXJuIGdldEV4dGVuc2lvbi5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICB9IC8vIGUuZy4gZXh0ZW5zaW9uKCdyZW5kZXJlcicsICdzdmcnLCB7IC4uLiB9KVxuICBlbHNlIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAzKSB7XG4gICAgICByZXR1cm4gc2V0RXh0ZW5zaW9uLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgfSAvLyBlLmcuIGV4dGVuc2lvbigncmVuZGVyZXInLCAnc3ZnJywgJ25vZGVTaGFwZScsICdlbGxpcHNlJylcbiAgICBlbHNlIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSA0KSB7XG4gICAgICAgIHJldHVybiBnZXRNb2R1bGUuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgIH0gLy8gZS5nLiBleHRlbnNpb24oJ3JlbmRlcmVyJywgJ3N2ZycsICdub2RlU2hhcGUnLCAnZWxsaXBzZScsIHsgLi4uIH0pXG4gICAgICBlbHNlIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSA1KSB7XG4gICAgICAgICAgcmV0dXJuIHNldE1vZHVsZS5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVycm9yKCdJbnZhbGlkIGV4dGVuc2lvbiBhY2Nlc3Mgc3ludGF4Jyk7XG4gICAgICAgIH1cbn07IC8vIGFsbG93cyBhIGNvcmUgaW5zdGFuY2UgdG8gYWNjZXNzIGV4dGVuc2lvbnMgaW50ZXJuYWxseVxuXG5cbkNvcmUucHJvdG90eXBlLmV4dGVuc2lvbiA9IGV4dGVuc2lvbjsgLy8gaW5jbHVkZWQgZXh0ZW5zaW9uc1xuXG5pbmNFeHRzLmZvckVhY2goZnVuY3Rpb24gKGdyb3VwKSB7XG4gIGdyb3VwLmV4dGVuc2lvbnMuZm9yRWFjaChmdW5jdGlvbiAoZXh0KSB7XG4gICAgc2V0RXh0ZW5zaW9uKGdyb3VwLnR5cGUsIGV4dC5uYW1lLCBleHQuaW1wbCk7XG4gIH0pO1xufSk7XG5cbi8vICh1c2VmdWwgZm9yIGluaXQpXG5cbnZhciBTdHlsZXNoZWV0ID0gZnVuY3Rpb24gU3R5bGVzaGVldCgpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFN0eWxlc2hlZXQpKSB7XG4gICAgcmV0dXJuIG5ldyBTdHlsZXNoZWV0KCk7XG4gIH1cblxuICB0aGlzLmxlbmd0aCA9IDA7XG59O1xuXG52YXIgc2hlZXRmbiA9IFN0eWxlc2hlZXQucHJvdG90eXBlO1xuXG5zaGVldGZuLmluc3RhbmNlU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gJ3N0eWxlc2hlZXQnO1xufTsgLy8ganVzdCBzdG9yZSB0aGUgc2VsZWN0b3IgdG8gYmUgcGFyc2VkIGxhdGVyXG5cblxuc2hlZXRmbi5zZWxlY3RvciA9IGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICB2YXIgaSA9IHRoaXMubGVuZ3RoKys7XG4gIHRoaXNbaV0gPSB7XG4gICAgc2VsZWN0b3I6IHNlbGVjdG9yLFxuICAgIHByb3BlcnRpZXM6IFtdXG4gIH07XG4gIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xufTsgLy8ganVzdCBzdG9yZSB0aGUgcHJvcGVydHkgdG8gYmUgcGFyc2VkIGxhdGVyXG5cblxuc2hlZXRmbi5jc3MgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgdmFyIGkgPSB0aGlzLmxlbmd0aCAtIDE7XG5cbiAgaWYgKHN0cmluZyhuYW1lKSkge1xuICAgIHRoaXNbaV0ucHJvcGVydGllcy5wdXNoKHtcbiAgICAgIG5hbWU6IG5hbWUsXG4gICAgICB2YWx1ZTogdmFsdWVcbiAgICB9KTtcbiAgfSBlbHNlIGlmIChwbGFpbk9iamVjdChuYW1lKSkge1xuICAgIHZhciBtYXAgPSBuYW1lO1xuICAgIHZhciBwcm9wTmFtZXMgPSBPYmplY3Qua2V5cyhtYXApO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwcm9wTmFtZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgIHZhciBrZXkgPSBwcm9wTmFtZXNbal07XG4gICAgICB2YXIgbWFwVmFsID0gbWFwW2tleV07XG5cbiAgICAgIGlmIChtYXBWYWwgPT0gbnVsbCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIHByb3AgPSBTdHlsZS5wcm9wZXJ0aWVzW2tleV0gfHwgU3R5bGUucHJvcGVydGllc1tkYXNoMmNhbWVsKGtleSldO1xuXG4gICAgICBpZiAocHJvcCA9PSBudWxsKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgX25hbWUgPSBwcm9wLm5hbWU7XG4gICAgICB2YXIgX3ZhbHVlID0gbWFwVmFsO1xuICAgICAgdGhpc1tpXS5wcm9wZXJ0aWVzLnB1c2goe1xuICAgICAgICBuYW1lOiBfbmFtZSxcbiAgICAgICAgdmFsdWU6IF92YWx1ZVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXM7IC8vIGNoYWluaW5nXG59O1xuXG5zaGVldGZuLnN0eWxlID0gc2hlZXRmbi5jc3M7IC8vIGdlbmVyYXRlIGEgcmVhbCBzdHlsZSBvYmplY3QgZnJvbSB0aGUgZHVtbXkgc3R5bGVzaGVldFxuXG5zaGVldGZuLmdlbmVyYXRlU3R5bGUgPSBmdW5jdGlvbiAoY3kpIHtcbiAgdmFyIHN0eWxlID0gbmV3IFN0eWxlKGN5KTtcbiAgcmV0dXJuIHRoaXMuYXBwZW5kVG9TdHlsZShzdHlsZSk7XG59OyAvLyBhcHBlbmQgYSBkdW1teSBzdHlsZXNoZWV0IG9iamVjdCBvbiBhIHJlYWwgc3R5bGUgb2JqZWN0XG5cblxuc2hlZXRmbi5hcHBlbmRUb1N0eWxlID0gZnVuY3Rpb24gKHN0eWxlKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBjb250ZXh0ID0gdGhpc1tpXTtcbiAgICB2YXIgc2VsZWN0b3IgPSBjb250ZXh0LnNlbGVjdG9yO1xuICAgIHZhciBwcm9wcyA9IGNvbnRleHQucHJvcGVydGllcztcbiAgICBzdHlsZS5zZWxlY3RvcihzZWxlY3Rvcik7IC8vIGFwcGx5IHNlbGVjdG9yXG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IHByb3BzLmxlbmd0aDsgaisrKSB7XG4gICAgICB2YXIgcHJvcCA9IHByb3BzW2pdO1xuICAgICAgc3R5bGUuY3NzKHByb3AubmFtZSwgcHJvcC52YWx1ZSk7IC8vIGFwcGx5IHByb3BlcnR5XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN0eWxlO1xufTtcblxudmFyIHZlcnNpb24gPSBcIjMuMTUuMVwiO1xuXG52YXIgY3l0b3NjYXBlID0gZnVuY3Rpb24gY3l0b3NjYXBlKG9wdGlvbnMpIHtcbiAgLy8gaWYgbm8gb3B0aW9ucyBzcGVjaWZpZWQsIHVzZSBkZWZhdWx0XG4gIGlmIChvcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICBvcHRpb25zID0ge307XG4gIH0gLy8gY3JlYXRlIGluc3RhbmNlXG5cblxuICBpZiAocGxhaW5PYmplY3Qob3B0aW9ucykpIHtcbiAgICByZXR1cm4gbmV3IENvcmUob3B0aW9ucyk7XG4gIH0gLy8gYWxsb3cgZm9yIHJlZ2lzdHJhdGlvbiBvZiBleHRlbnNpb25zXG4gIGVsc2UgaWYgKHN0cmluZyhvcHRpb25zKSkge1xuICAgICAgcmV0dXJuIGV4dGVuc2lvbi5hcHBseShleHRlbnNpb24sIGFyZ3VtZW50cyk7XG4gICAgfVxufTsgLy8gZS5nLiBjeXRvc2NhcGUudXNlKCByZXF1aXJlKCdjeXRvc2NhcGUtZm9vJyksIGJhciApXG5cblxuY3l0b3NjYXBlLnVzZSA9IGZ1bmN0aW9uIChleHQpIHtcbiAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpOyAvLyBhcmdzIHRvIHBhc3MgdG8gZXh0XG5cbiAgYXJncy51bnNoaWZ0KGN5dG9zY2FwZSk7IC8vIGN5dG9zY2FwZSBpcyBmaXJzdCBhcmcgdG8gZXh0XG5cbiAgZXh0LmFwcGx5KG51bGwsIGFyZ3MpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmN5dG9zY2FwZS53YXJuaW5ncyA9IGZ1bmN0aW9uIChib29sKSB7XG4gIHJldHVybiB3YXJuaW5ncyhib29sKTtcbn07IC8vIHJlcGxhY2VkIGJ5IGJ1aWxkIHN5c3RlbVxuXG5cbmN5dG9zY2FwZS52ZXJzaW9uID0gdmVyc2lvbjsgLy8gZXhwb3NlIHB1YmxpYyBhcGlzIChtb3N0bHkgZm9yIGV4dGVuc2lvbnMpXG5cbmN5dG9zY2FwZS5zdHlsZXNoZWV0ID0gY3l0b3NjYXBlLlN0eWxlc2hlZXQgPSBTdHlsZXNoZWV0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGN5dG9zY2FwZTtcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/cytoscape/dist/cytoscape.cjs.js\n");
/***/ }),
/***/ "./node_modules/heap/index.js":
/*!************************************!*\
!*** ./node_modules/heap/index.js ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("module.exports = __webpack_require__(/*! ./lib/heap */ \"./node_modules/heap/lib/heap.js\");\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9oZWFwL2luZGV4LmpzPzE3NWEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsaUJBQWlCLG1CQUFPLENBQUMsbURBQVkiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaGVhcC9pbmRleC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9saWIvaGVhcCcpO1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/heap/index.js\n");
/***/ }),
/***/ "./node_modules/heap/lib/heap.js":
/*!***************************************!*\
!*** ./node_modules/heap/lib/heap.js ***!
\***************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Generated by CoffeeScript 1.8.0\n(function() {\n var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;\n\n floor = Math.floor, min = Math.min;\n\n\n /*\n Default comparison function to be used\n */\n\n defaultCmp = function(x, y) {\n if (x < y) {\n return -1;\n }\n if (x > y) {\n return 1;\n }\n return 0;\n };\n\n\n /*\n Insert item x in list a, and keep it sorted assuming a is sorted.\n \n If x is already in a, insert it to the right of the rightmost x.\n \n Optional args lo (default 0) and hi (default a.length) bound the slice\n of a to be searched.\n */\n\n insort = function(a, x, lo, hi, cmp) {\n var mid;\n if (lo == null) {\n lo = 0;\n }\n if (cmp == null) {\n cmp = defaultCmp;\n }\n if (lo < 0) {\n throw new Error('lo must be non-negative');\n }\n if (hi == null) {\n hi = a.length;\n }\n while (lo < hi) {\n mid = floor((lo + hi) / 2);\n if (cmp(x, a[mid]) < 0) {\n hi = mid;\n } else {\n lo = mid + 1;\n }\n }\n return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);\n };\n\n\n /*\n Push item onto heap, maintaining the heap invariant.\n */\n\n heappush = function(array, item, cmp) {\n if (cmp == null) {\n cmp = defaultCmp;\n }\n array.push(item);\n return _siftdown(array, 0, array.length - 1, cmp);\n };\n\n\n /*\n Pop the smallest item off the heap, maintaining the heap invariant.\n */\n\n heappop = function(array, cmp) {\n var lastelt, returnitem;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n lastelt = array.pop();\n if (array.length) {\n returnitem = array[0];\n array[0] = lastelt;\n _siftup(array, 0, cmp);\n } else {\n returnitem = lastelt;\n }\n return returnitem;\n };\n\n\n /*\n Pop and return the current smallest value, and add the new item.\n \n This is more efficient than heappop() followed by heappush(), and can be\n more appropriate when using a fixed size heap. Note that the value\n returned may be larger than item! That constrains reasonable use of\n this routine unless written as part of a conditional replacement:\n if item > array[0]\n item = heapreplace(array, item)\n */\n\n heapreplace = function(array, item, cmp) {\n var returnitem;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n returnitem = array[0];\n array[0] = item;\n _siftup(array, 0, cmp);\n return returnitem;\n };\n\n\n /*\n Fast version of a heappush followed by a heappop.\n */\n\n heappushpop = function(array, item, cmp) {\n var _ref;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n if (array.length && cmp(array[0], item) < 0) {\n _ref = [array[0], item], item = _ref[0], array[0] = _ref[1];\n _siftup(array, 0, cmp);\n }\n return item;\n };\n\n\n /*\n Transform list into a heap, in-place, in O(array.length) time.\n */\n\n heapify = function(array, cmp) {\n var i, _i, _j, _len, _ref, _ref1, _results, _results1;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n _ref1 = (function() {\n _results1 = [];\n for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }\n return _results1;\n }).apply(this).reverse();\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n i = _ref1[_i];\n _results.push(_siftup(array, i, cmp));\n }\n return _results;\n };\n\n\n /*\n Update the position of the given item in the heap.\n This function should be called every time the item is being modified.\n */\n\n updateItem = function(array, item, cmp) {\n var pos;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n pos = array.indexOf(item);\n if (pos === -1) {\n return;\n }\n _siftdown(array, 0, pos, cmp);\n return _siftup(array, pos, cmp);\n };\n\n\n /*\n Find the n largest elements in a dataset.\n */\n\n nlargest = function(array, n, cmp) {\n var elem, result, _i, _len, _ref;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n result = array.slice(0, n);\n if (!result.length) {\n return result;\n }\n heapify(result, cmp);\n _ref = array.slice(n);\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n elem = _ref[_i];\n heappushpop(result, elem, cmp);\n }\n return result.sort(cmp).reverse();\n };\n\n\n /*\n Find the n smallest elements in a dataset.\n */\n\n nsmallest = function(array, n, cmp) {\n var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n if (n * 10 <= array.length) {\n result = array.slice(0, n).sort(cmp);\n if (!result.length) {\n return result;\n }\n los = result[result.length - 1];\n _ref = array.slice(n);\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n elem = _ref[_i];\n if (cmp(elem, los) < 0) {\n insort(result, elem, 0, null, cmp);\n result.pop();\n los = result[result.length - 1];\n }\n }\n return result;\n }\n heapify(array, cmp);\n _results = [];\n for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {\n _results.push(heappop(array, cmp));\n }\n return _results;\n };\n\n _siftdown = function(array, startpos, pos, cmp) {\n var newitem, parent, parentpos;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n newitem = array[pos];\n while (pos > startpos) {\n parentpos = (pos - 1) >> 1;\n parent = array[parentpos];\n if (cmp(newitem, parent) < 0) {\n array[pos] = parent;\n pos = parentpos;\n continue;\n }\n break;\n }\n return array[pos] = newitem;\n };\n\n _siftup = function(array, pos, cmp) {\n var childpos, endpos, newitem, rightpos, startpos;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n endpos = array.length;\n startpos = pos;\n newitem = array[pos];\n childpos = 2 * pos + 1;\n while (childpos < endpos) {\n rightpos = childpos + 1;\n if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {\n childpos = rightpos;\n }\n array[pos] = array[childpos];\n pos = childpos;\n childpos = 2 * pos + 1;\n }\n array[pos] = newitem;\n return _siftdown(array, startpos, pos, cmp);\n };\n\n Heap = (function() {\n Heap.push = heappush;\n\n Heap.pop = heappop;\n\n Heap.replace = heapreplace;\n\n Heap.pushpop = heappushpop;\n\n Heap.heapify = heapify;\n\n Heap.updateItem = updateItem;\n\n Heap.nlargest = nlargest;\n\n Heap.nsmallest = nsmallest;\n\n function Heap(cmp) {\n this.cmp = cmp != null ? cmp : defaultCmp;\n this.nodes = [];\n }\n\n Heap.prototype.push = function(x) {\n return heappush(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.pop = function() {\n return heappop(this.nodes, this.cmp);\n };\n\n Heap.prototype.peek = function() {\n return this.nodes[0];\n };\n\n Heap.prototype.contains = function(x) {\n return this.nodes.indexOf(x) !== -1;\n };\n\n Heap.prototype.replace = function(x) {\n return heapreplace(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.pushpop = function(x) {\n return heappushpop(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.heapify = function() {\n return heapify(this.nodes, this.cmp);\n };\n\n Heap.prototype.updateItem = function(x) {\n return updateItem(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.clear = function() {\n return this.nodes = [];\n };\n\n Heap.prototype.empty = function() {\n return this.nodes.length === 0;\n };\n\n Heap.prototype.size = function() {\n return this.nodes.length;\n };\n\n Heap.prototype.clone = function() {\n var heap;\n heap = new Heap();\n heap.nodes = this.nodes.slice(0);\n return heap;\n };\n\n Heap.prototype.toArray = function() {\n return this.nodes.slice(0);\n };\n\n Heap.prototype.insert = Heap.prototype.push;\n\n Heap.prototype.top = Heap.prototype.peek;\n\n Heap.prototype.front = Heap.prototype.peek;\n\n Heap.prototype.has = Heap.prototype.contains;\n\n Heap.prototype.copy = Heap.prototype.clone;\n\n return Heap;\n\n })();\n\n (function(root, factory) {\n if (true) {\n return !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n } else {}\n })(this, function() {\n return Heap;\n });\n\n}).call(this);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9oZWFwL2xpYi9oZWFwLmpzPzEyNDgiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0QsbUNBQW1DLDBCQUEwQixvQkFBb0I7QUFDdkk7QUFDQSxLQUFLO0FBQ0w7QUFDQSxxQ0FBcUMsV0FBVztBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DLFdBQVc7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxXQUFXO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Qsc0NBQXNDO0FBQ3hGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBLFFBQVEsSUFBMEM7QUFDbEQsYUFBYSxpQ0FBTyxFQUFFLG9DQUFFLE9BQU87QUFBQTtBQUFBO0FBQUEsb0dBQUM7QUFDaEMsS0FBSyxNQUFNLEVBSU47QUFDTCxHQUFHO0FBQ0g7QUFDQSxHQUFHOztBQUVILENBQUMiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaGVhcC9saWIvaGVhcC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdlbmVyYXRlZCBieSBDb2ZmZWVTY3JpcHQgMS44LjBcbihmdW5jdGlvbigpIHtcbiAgdmFyIEhlYXAsIGRlZmF1bHRDbXAsIGZsb29yLCBoZWFwaWZ5LCBoZWFwcG9wLCBoZWFwcHVzaCwgaGVhcHB1c2hwb3AsIGhlYXByZXBsYWNlLCBpbnNvcnQsIG1pbiwgbmxhcmdlc3QsIG5zbWFsbGVzdCwgdXBkYXRlSXRlbSwgX3NpZnRkb3duLCBfc2lmdHVwO1xuXG4gIGZsb29yID0gTWF0aC5mbG9vciwgbWluID0gTWF0aC5taW47XG5cblxuICAvKlxuICBEZWZhdWx0IGNvbXBhcmlzb24gZnVuY3Rpb24gdG8gYmUgdXNlZFxuICAgKi9cblxuICBkZWZhdWx0Q21wID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIGlmICh4IDwgeSkge1xuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbiAgICBpZiAoeCA+IHkpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICByZXR1cm4gMDtcbiAgfTtcblxuXG4gIC8qXG4gIEluc2VydCBpdGVtIHggaW4gbGlzdCBhLCBhbmQga2VlcCBpdCBzb3J0ZWQgYXNzdW1pbmcgYSBpcyBzb3J0ZWQuXG4gIFxuICBJZiB4IGlzIGFscmVhZHkgaW4gYSwgaW5zZXJ0IGl0IHRvIHRoZSByaWdodCBvZiB0aGUgcmlnaHRtb3N0IHguXG4gIFxuICBPcHRpb25hbCBhcmdzIGxvIChkZWZhdWx0IDApIGFuZCBoaSAoZGVmYXVsdCBhLmxlbmd0aCkgYm91bmQgdGhlIHNsaWNlXG4gIG9mIGEgdG8gYmUgc2VhcmNoZWQuXG4gICAqL1xuXG4gIGluc29ydCA9IGZ1bmN0aW9uKGEsIHgsIGxvLCBoaSwgY21wKSB7XG4gICAgdmFyIG1pZDtcbiAgICBpZiAobG8gPT0gbnVsbCkge1xuICAgICAgbG8gPSAwO1xuICAgIH1cbiAgICBpZiAoY21wID09IG51bGwpIHtcbiAgICAgIGNtcCA9IGRlZmF1bHRDbXA7XG4gICAgfVxuICAgIGlmIChsbyA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbG8gbXVzdCBiZSBub24tbmVnYXRpdmUnKTtcbiAgICB9XG4gICAgaWYgKGhpID09IG51bGwpIHtcbiAgICAgIGhpID0gYS5sZW5ndGg7XG4gICAgfVxuICAgIHdoaWxlIChsbyA8IGhpKSB7XG4gICAgICBtaWQgPSBmbG9vcigobG8gKyBoaSkgLyAyKTtcbiAgICAgIGlmIChjbXAoeCwgYVttaWRdKSA8IDApIHtcbiAgICAgICAgaGkgPSBtaWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsbyA9IG1pZCArIDE7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAoW10uc3BsaWNlLmFwcGx5KGEsIFtsbywgbG8gLSBsb10uY29uY2F0KHgpKSwgeCk7XG4gIH07XG5cblxuICAvKlxuICBQdXNoIGl0ZW0gb250byBoZWFwLCBtYWludGFpbmluZyB0aGUgaGVhcCBpbnZhcmlhbnQuXG4gICAqL1xuXG4gIGhlYXBwdXNoID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGNtcCkge1xuICAgIGlmIChjbXAgPT0gbnVsbCkge1xuICAgICAgY21wID0gZGVmYXVsdENtcDtcbiAgICB9XG4gICAgYXJyYXkucHVzaChpdGVtKTtcbiAgICByZXR1cm4gX3NpZnRkb3duKGFycmF5LCAwLCBhcnJheS5sZW5ndGggLSAxLCBjbXApO1xuICB9O1xuXG5cbiAgLypcbiAgUG9wIHRoZSBzbWFsbGVzdCBpdGVtIG9mZiB0aGUgaGVhcCwgbWFpbnRhaW5pbmcgdGhlIGhlYXAgaW52YXJpYW50LlxuICAgKi9cblxuICBoZWFwcG9wID0gZnVuY3Rpb24oYXJyYXksIGNtcCkge1xuICAgIHZhciBsYXN0ZWx0LCByZXR1cm5pdGVtO1xuICAgIGlmIChjbXAgPT0gbnVsbCkge1xuICAgICAgY21wID0gZGVmYXVsdENtcDtcbiAgICB9XG4gICAgbGFzdGVsdCA9IGFycmF5LnBvcCgpO1xuICAgIGlmIChhcnJheS5sZW5ndGgpIHtcbiAgICAgIHJldHVybml0ZW0gPSBhcnJheVswXTtcbiAgICAgIGFycmF5WzBdID0gbGFzdGVsdDtcbiAgICAgIF9zaWZ0dXAoYXJyYXksIDAsIGNtcCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybml0ZW0gPSBsYXN0ZWx0O1xuICAgIH1cbiAgICByZXR1cm4gcmV0dXJuaXRlbTtcbiAgfTtcblxuXG4gIC8qXG4gIFBvcCBhbmQgcmV0dXJuIHRoZSBjdXJyZW50IHNtYWxsZXN0IHZhbHVlLCBhbmQgYWRkIHRoZSBuZXcgaXRlbS5cbiAgXG4gIFRoaXMgaXMgbW9yZSBlZmZpY2llbnQgdGhhbiBoZWFwcG9wKCkgZm9sbG93ZWQgYnkgaGVhcHB1c2goKSwgYW5kIGNhbiBiZVxuICBtb3JlIGFwcHJvcHJpYXRlIHdoZW4gdXNpbmcgYSBmaXhlZCBzaXplIGhlYXAuIE5vdGUgdGhhdCB0aGUgdmFsdWVcbiAgcmV0dXJuZWQgbWF5IGJlIGxhcmdlciB0aGFuIGl0ZW0hIFRoYXQgY29uc3RyYWlucyByZWFzb25hYmxlIHVzZSBvZlxuICB0aGlzIHJvdXRpbmUgdW5sZXNzIHdyaXR0ZW4gYXMgcGFydCBvZiBhIGNvbmRpdGlvbmFsIHJlcGxhY2VtZW50OlxuICAgICAgaWYgaXRlbSA+IGFycmF5WzBdXG4gICAgICAgIGl0ZW0gPSBoZWFwcmVwbGFjZShhcnJheSwgaXRlbSlcbiAgICovXG5cbiAgaGVhcHJlcGxhY2UgPSBmdW5jdGlvbihhcnJheSwgaXRlbSwgY21wKSB7XG4gICAgdmFyIHJldHVybml0ZW07XG4gICAgaWYgKGNtcCA9PSBudWxsKSB7XG4gICAgICBjbXAgPSBkZWZhdWx0Q21wO1xuICAgIH1cbiAgICByZXR1cm5pdGVtID0gYXJyYXlbMF07XG4gICAgYXJyYXlbMF0gPSBpdGVtO1xuICAgIF9zaWZ0dXAoYXJyYXksIDAsIGNtcCk7XG4gICAgcmV0dXJuIHJldHVybml0ZW07XG4gIH07XG5cblxuICAvKlxuICBGYXN0IHZlcnNpb24gb2YgYSBoZWFwcHVzaCBmb2xsb3dlZCBieSBhIGhlYXBwb3AuXG4gICAqL1xuXG4gIGhlYXBwdXNocG9wID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGNtcCkge1xuICAgIHZhciBfcmVmO1xuICAgIGlmIChjbXAgPT0gbnVsbCkge1xuICAgICAgY21wID0gZGVmYXVsdENtcDtcbiAgICB9XG4gICAgaWYgKGFycmF5Lmxlbmd0aCAmJiBjbXAoYXJyYXlbMF0sIGl0ZW0pIDwgMCkge1xuICAgICAgX3JlZiA9IFthcnJheVswXSwgaXRlbV0sIGl0ZW0gPSBfcmVmWzBdLCBhcnJheVswXSA9IF9yZWZbMV07XG4gICAgICBfc2lmdHVwKGFycmF5LCAwLCBjbXApO1xuICAgIH1cbiAgICByZXR1cm4gaXRlbTtcbiAgfTtcblxuXG4gIC8qXG4gIFRyYW5zZm9ybSBsaXN0IGludG8gYSBoZWFwLCBpbi1wbGFjZSwgaW4gTyhhcnJheS5sZW5ndGgpIHRpbWUuXG4gICAqL1xuXG4gIGhlYXBpZnkgPSBmdW5jdGlvbihhcnJheSwgY21wKSB7XG4gICAgdmFyIGksIF9pLCBfaiwgX2xlbiwgX3JlZiwgX3JlZjEsIF9yZXN1bHRzLCBfcmVzdWx0czE7XG4gICAgaWYgKGNtcCA9PSBudWxsKSB7XG4gICAgICBjbXAgPSBkZWZhdWx0Q21wO1xuICAgIH1cbiAgICBfcmVmMSA9IChmdW5jdGlvbigpIHtcbiAgICAgIF9yZXN1bHRzMSA9IFtdO1xuICAgICAgZm9yICh2YXIgX2ogPSAwLCBfcmVmID0gZmxvb3IoYXJyYXkubGVuZ3RoIC8gMik7IDAgPD0gX3JlZiA/IF9qIDwgX3JlZiA6IF9qID4gX3JlZjsgMCA8PSBfcmVmID8gX2orKyA6IF9qLS0peyBfcmVzdWx0czEucHVzaChfaik7IH1cbiAgICAgIHJldHVybiBfcmVzdWx0czE7XG4gICAgfSkuYXBwbHkodGhpcykucmV2ZXJzZSgpO1xuICAgIF9yZXN1bHRzID0gW107XG4gICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgaSA9IF9yZWYxW19pXTtcbiAgICAgIF9yZXN1bHRzLnB1c2goX3NpZnR1cChhcnJheSwgaSwgY21wKSk7XG4gICAgfVxuICAgIHJldHVybiBfcmVzdWx0cztcbiAgfTtcblxuXG4gIC8qXG4gIFVwZGF0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIGdpdmVuIGl0ZW0gaW4gdGhlIGhlYXAuXG4gIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGNhbGxlZCBldmVyeSB0aW1lIHRoZSBpdGVtIGlzIGJlaW5nIG1vZGlmaWVkLlxuICAgKi9cblxuICB1cGRhdGVJdGVtID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGNtcCkge1xuICAgIHZhciBwb3M7XG4gICAgaWYgKGNtcCA9PSBudWxsKSB7XG4gICAgICBjbXAgPSBkZWZhdWx0Q21wO1xuICAgIH1cbiAgICBwb3MgPSBhcnJheS5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChwb3MgPT09IC0xKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIF9zaWZ0ZG93bihhcnJheSwgMCwgcG9zLCBjbXApO1xuICAgIHJldHVybiBfc2lmdHVwKGFycmF5LCBwb3MsIGNtcCk7XG4gIH07XG5cblxuICAvKlxuICBGaW5kIHRoZSBuIGxhcmdlc3QgZWxlbWVudHMgaW4gYSBkYXRhc2V0LlxuICAgKi9cblxuICBubGFyZ2VzdCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBjbXApIHtcbiAgICB2YXIgZWxlbSwgcmVzdWx0LCBfaSwgX2xlbiwgX3JlZjtcbiAgICBpZiAoY21wID09IG51bGwpIHtcbiAgICAgIGNtcCA9IGRlZmF1bHRDbXA7XG4gICAgfVxuICAgIHJlc3VsdCA9IGFycmF5LnNsaWNlKDAsIG4pO1xuICAgIGlmICghcmVzdWx0Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgaGVhcGlmeShyZXN1bHQsIGNtcCk7XG4gICAgX3JlZiA9IGFycmF5LnNsaWNlKG4pO1xuICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZi5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgZWxlbSA9IF9yZWZbX2ldO1xuICAgICAgaGVhcHB1c2hwb3AocmVzdWx0LCBlbGVtLCBjbXApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0LnNvcnQoY21wKS5yZXZlcnNlKCk7XG4gIH07XG5cblxuICAvKlxuICBGaW5kIHRoZSBuIHNtYWxsZXN0IGVsZW1lbnRzIGluIGEgZGF0YXNldC5cbiAgICovXG5cbiAgbnNtYWxsZXN0ID0gZnVuY3Rpb24oYXJyYXksIG4sIGNtcCkge1xuICAgIHZhciBlbGVtLCBpLCBsb3MsIHJlc3VsdCwgX2ksIF9qLCBfbGVuLCBfcmVmLCBfcmVmMSwgX3Jlc3VsdHM7XG4gICAgaWYgKGNtcCA9PSBudWxsKSB7XG4gICAgICBjbXAgPSBkZWZhdWx0Q21wO1xuICAgIH1cbiAgICBpZiAobiAqIDEwIDw9IGFycmF5Lmxlbmd0aCkge1xuICAgICAgcmVzdWx0ID0gYXJyYXkuc2xpY2UoMCwgbikuc29ydChjbXApO1xuICAgICAgaWYgKCFyZXN1bHQubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBsb3MgPSByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdO1xuICAgICAgX3JlZiA9IGFycmF5LnNsaWNlKG4pO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGVsZW0gPSBfcmVmW19pXTtcbiAgICAgICAgaWYgKGNtcChlbGVtLCBsb3MpIDwgMCkge1xuICAgICAgICAgIGluc29ydChyZXN1bHQsIGVsZW0sIDAsIG51bGwsIGNtcCk7XG4gICAgICAgICAgcmVzdWx0LnBvcCgpO1xuICAgICAgICAgIGxvcyA9IHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIGhlYXBpZnkoYXJyYXksIGNtcCk7XG4gICAgX3Jlc3VsdHMgPSBbXTtcbiAgICBmb3IgKGkgPSBfaiA9IDAsIF9yZWYxID0gbWluKG4sIGFycmF5Lmxlbmd0aCk7IDAgPD0gX3JlZjEgPyBfaiA8IF9yZWYxIDogX2ogPiBfcmVmMTsgaSA9IDAgPD0gX3JlZjEgPyArK19qIDogLS1faikge1xuICAgICAgX3Jlc3VsdHMucHVzaChoZWFwcG9wKGFycmF5LCBjbXApKTtcbiAgICB9XG4gICAgcmV0dXJuIF9yZXN1bHRzO1xuICB9O1xuXG4gIF9zaWZ0ZG93biA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydHBvcywgcG9zLCBjbXApIHtcbiAgICB2YXIgbmV3aXRlbSwgcGFyZW50LCBwYXJlbnRwb3M7XG4gICAgaWYgKGNtcCA9PSBudWxsKSB7XG4gICAgICBjbXAgPSBkZWZhdWx0Q21wO1xuICAgIH1cbiAgICBuZXdpdGVtID0gYXJyYXlbcG9zXTtcbiAgICB3aGlsZSAocG9zID4gc3RhcnRwb3MpIHtcbiAgICAgIHBhcmVudHBvcyA9IChwb3MgLSAxKSA+PiAxO1xuICAgICAgcGFyZW50ID0gYXJyYXlbcGFyZW50cG9zXTtcbiAgICAgIGlmIChjbXAobmV3aXRlbSwgcGFyZW50KSA8IDApIHtcbiAgICAgICAgYXJyYXlbcG9zXSA9IHBhcmVudDtcbiAgICAgICAgcG9zID0gcGFyZW50cG9zO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXlbcG9zXSA9IG5ld2l0ZW07XG4gIH07XG5cbiAgX3NpZnR1cCA9IGZ1bmN0aW9uKGFycmF5LCBwb3MsIGNtcCkge1xuICAgIHZhciBjaGlsZHBvcywgZW5kcG9zLCBuZXdpdGVtLCByaWdodHBvcywgc3RhcnRwb3M7XG4gICAgaWYgKGNtcCA9PSBudWxsKSB7XG4gICAgICBjbXAgPSBkZWZhdWx0Q21wO1xuICAgIH1cbiAgICBlbmRwb3MgPSBhcnJheS5sZW5ndGg7XG4gICAgc3RhcnRwb3MgPSBwb3M7XG4gICAgbmV3aXRlbSA9IGFycmF5W3Bvc107XG4gICAgY2hpbGRwb3MgPSAyICogcG9zICsgMTtcbiAgICB3aGlsZSAoY2hpbGRwb3MgPCBlbmRwb3MpIHtcbiAgICAgIHJpZ2h0cG9zID0gY2hpbGRwb3MgKyAxO1xuICAgICAgaWYgKHJpZ2h0cG9zIDwgZW5kcG9zICYmICEoY21wKGFycmF5W2NoaWxkcG9zXSwgYXJyYXlbcmlnaHRwb3NdKSA8IDApKSB7XG4gICAgICAgIGNoaWxkcG9zID0gcmlnaHRwb3M7XG4gICAgICB9XG4gICAgICBhcnJheVtwb3NdID0gYXJyYXlbY2hpbGRwb3NdO1xuICAgICAgcG9zID0gY2hpbGRwb3M7XG4gICAgICBjaGlsZHBvcyA9IDIgKiBwb3MgKyAxO1xuICAgIH1cbiAgICBhcnJheVtwb3NdID0gbmV3aXRlbTtcbiAgICByZXR1cm4gX3NpZnRkb3duKGFycmF5LCBzdGFydHBvcywgcG9zLCBjbXApO1xuICB9O1xuXG4gIEhlYXAgPSAoZnVuY3Rpb24oKSB7XG4gICAgSGVhcC5wdXNoID0gaGVhcHB1c2g7XG5cbiAgICBIZWFwLnBvcCA9IGhlYXBwb3A7XG5cbiAgICBIZWFwLnJlcGxhY2UgPSBoZWFwcmVwbGFjZTtcblxuICAgIEhlYXAucHVzaHBvcCA9IGhlYXBwdXNocG9wO1xuXG4gICAgSGVhcC5oZWFwaWZ5ID0gaGVhcGlmeTtcblxuICAgIEhlYXAudXBkYXRlSXRlbSA9IHVwZGF0ZUl0ZW07XG5cbiAgICBIZWFwLm5sYXJnZXN0ID0gbmxhcmdlc3Q7XG5cbiAgICBIZWFwLm5zbWFsbGVzdCA9IG5zbWFsbGVzdDtcblxuICAgIGZ1bmN0aW9uIEhlYXAoY21wKSB7XG4gICAgICB0aGlzLmNtcCA9IGNtcCAhPSBudWxsID8gY21wIDogZGVmYXVsdENtcDtcbiAgICAgIHRoaXMubm9kZXMgPSBbXTtcbiAgICB9XG5cbiAgICBIZWFwLnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIGhlYXBwdXNoKHRoaXMubm9kZXMsIHgsIHRoaXMuY21wKTtcbiAgICB9O1xuXG4gICAgSGVhcC5wcm90b3R5cGUucG9wID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gaGVhcHBvcCh0aGlzLm5vZGVzLCB0aGlzLmNtcCk7XG4gICAgfTtcblxuICAgIEhlYXAucHJvdG90eXBlLnBlZWsgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLm5vZGVzWzBdO1xuICAgIH07XG5cbiAgICBIZWFwLnByb3RvdHlwZS5jb250YWlucyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB0aGlzLm5vZGVzLmluZGV4T2YoeCkgIT09IC0xO1xuICAgIH07XG5cbiAgICBIZWFwLnByb3RvdHlwZS5yZXBsYWNlID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIGhlYXByZXBsYWNlKHRoaXMubm9kZXMsIHgsIHRoaXMuY21wKTtcbiAgICB9O1xuXG4gICAgSGVhcC5wcm90b3R5cGUucHVzaHBvcCA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiBoZWFwcHVzaHBvcCh0aGlzLm5vZGVzLCB4LCB0aGlzLmNtcCk7XG4gICAgfTtcblxuICAgIEhlYXAucHJvdG90eXBlLmhlYXBpZnkgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBoZWFwaWZ5KHRoaXMubm9kZXMsIHRoaXMuY21wKTtcbiAgICB9O1xuXG4gICAgSGVhcC5wcm90b3R5cGUudXBkYXRlSXRlbSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB1cGRhdGVJdGVtKHRoaXMubm9kZXMsIHgsIHRoaXMuY21wKTtcbiAgICB9O1xuXG4gICAgSGVhcC5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLm5vZGVzID0gW107XG4gICAgfTtcblxuICAgIEhlYXAucHJvdG90eXBlLmVtcHR5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5ub2Rlcy5sZW5ndGggPT09IDA7XG4gICAgfTtcblxuICAgIEhlYXAucHJvdG90eXBlLnNpemUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLm5vZGVzLmxlbmd0aDtcbiAgICB9O1xuXG4gICAgSGVhcC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBoZWFwO1xuICAgICAgaGVhcCA9IG5ldyBIZWFwKCk7XG4gICAgICBoZWFwLm5vZGVzID0gdGhpcy5ub2Rlcy5zbGljZSgwKTtcbiAgICAgIHJldHVybiBoZWFwO1xuICAgIH07XG5cbiAgICBIZWFwLnByb3RvdHlwZS50b0FycmF5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5ub2Rlcy5zbGljZSgwKTtcbiAgICB9O1xuXG4gICAgSGVhcC5wcm90b3R5cGUuaW5zZXJ0ID0gSGVhcC5wcm90b3R5cGUucHVzaDtcblxuICAgIEhlYXAucHJvdG90eXBlLnRvcCA9IEhlYXAucHJvdG90eXBlLnBlZWs7XG5cbiAgICBIZWFwLnByb3RvdHlwZS5mcm9udCA9IEhlYXAucHJvdG90eXBlLnBlZWs7XG5cbiAgICBIZWFwLnByb3RvdHlwZS5oYXMgPSBIZWFwLnByb3RvdHlwZS5jb250YWlucztcblxuICAgIEhlYXAucHJvdG90eXBlLmNvcHkgPSBIZWFwLnByb3RvdHlwZS5jbG9uZTtcblxuICAgIHJldHVybiBIZWFwO1xuXG4gIH0pKCk7XG5cbiAgKGZ1bmN0aW9uKHJvb3QsIGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICByZXR1cm4gZGVmaW5lKFtdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcm9vdC5IZWFwID0gZmFjdG9yeSgpO1xuICAgIH1cbiAgfSkodGhpcywgZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIEhlYXA7XG4gIH0pO1xuXG59KS5jYWxsKHRoaXMpO1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/heap/lib/heap.js\n");
/***/ }),
/***/ "./node_modules/lodash.debounce/index.js":
/*!***********************************************!*\
!*** ./node_modules/lodash.debounce/index.js ***!
\***********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("/* WEBPACK VAR INJECTION */(function(global) {/**\n * lodash (Custom Build) <https://lodash.com/>\n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors <https://jquery.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/** Used to match leading and trailing whitespace. */\nvar reTrim = /^\\s+|\\s+$/g;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n result = wait - timeSinceLastCall;\n\n return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && objectToString.call(value) == symbolTag);\n}\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = debounce;\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\")))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9sb2Rhc2guZGVib3VuY2UvaW5kZXguanM/ZjdmZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU8sWUFBWTtBQUM5QixXQUFXLFFBQVE7QUFDbkI7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQSxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSw4Q0FBOEMsa0JBQWtCO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9sb2Rhc2guZGVib3VuY2UvaW5kZXguanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGxvZGFzaCAoQ3VzdG9tIEJ1aWxkKSA8aHR0cHM6Ly9sb2Rhc2guY29tLz5cbiAqIEJ1aWxkOiBgbG9kYXNoIG1vZHVsYXJpemUgZXhwb3J0cz1cIm5wbVwiIC1vIC4vYFxuICogQ29weXJpZ2h0IGpRdWVyeSBGb3VuZGF0aW9uIGFuZCBvdGhlciBjb250cmlidXRvcnMgPGh0dHBzOi8vanF1ZXJ5Lm9yZy8+XG4gKiBSZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9sb2Rhc2guY29tL2xpY2Vuc2U+XG4gKiBCYXNlZCBvbiBVbmRlcnNjb3JlLmpzIDEuOC4zIDxodHRwOi8vdW5kZXJzY29yZWpzLm9yZy9MSUNFTlNFPlxuICogQ29weXJpZ2h0IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4gKi9cblxuLyoqIFVzZWQgYXMgdGhlIGBUeXBlRXJyb3JgIG1lc3NhZ2UgZm9yIFwiRnVuY3Rpb25zXCIgbWV0aG9kcy4gKi9cbnZhciBGVU5DX0VSUk9SX1RFWFQgPSAnRXhwZWN0ZWQgYSBmdW5jdGlvbic7XG5cbi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHZhcmlvdXMgYE51bWJlcmAgY29uc3RhbnRzLiAqL1xudmFyIE5BTiA9IDAgLyAwO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgc3ltYm9sVGFnID0gJ1tvYmplY3QgU3ltYm9sXSc7XG5cbi8qKiBVc2VkIHRvIG1hdGNoIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UuICovXG52YXIgcmVUcmltID0gL15cXHMrfFxccyskL2c7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiYWQgc2lnbmVkIGhleGFkZWNpbWFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JhZEhleCA9IC9eWy0rXTB4WzAtOWEtZl0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgYmluYXJ5IHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JpbmFyeSA9IC9eMGJbMDFdKyQvaTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IG9jdGFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc09jdGFsID0gL14wb1swLTddKyQvaTtcblxuLyoqIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHdpdGhvdXQgYSBkZXBlbmRlbmN5IG9uIGByb290YC4gKi9cbnZhciBmcmVlUGFyc2VJbnQgPSBwYXJzZUludDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcy4gKi9cbnZhciBmcmVlR2xvYmFsID0gdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCA9PT0gT2JqZWN0ICYmIGdsb2JhbDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBzZWxmYC4gKi9cbnZhciBmcmVlU2VsZiA9IHR5cGVvZiBzZWxmID09ICdvYmplY3QnICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgPT09IE9iamVjdCAmJiBzZWxmO1xuXG4vKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbnZhciByb290ID0gZnJlZUdsb2JhbCB8fCBmcmVlU2VsZiB8fCBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGVcbiAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU1heCA9IE1hdGgubWF4LFxuICAgIG5hdGl2ZU1pbiA9IE1hdGgubWluO1xuXG4vKipcbiAqIEdldHMgdGhlIHRpbWVzdGFtcCBvZiB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0aGF0IGhhdmUgZWxhcHNlZCBzaW5jZVxuICogdGhlIFVuaXggZXBvY2ggKDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAyLjQuMFxuICogQGNhdGVnb3J5IERhdGVcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVzdGFtcC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5kZWZlcihmdW5jdGlvbihzdGFtcCkge1xuICogICBjb25zb2xlLmxvZyhfLm5vdygpIC0gc3RhbXApO1xuICogfSwgXy5ub3coKSk7XG4gKiAvLyA9PiBMb2dzIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGl0IHRvb2sgZm9yIHRoZSBkZWZlcnJlZCBpbnZvY2F0aW9uLlxuICovXG52YXIgbm93ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiByb290LkRhdGUubm93KCk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gdGhhdCBkZWxheXMgaW52b2tpbmcgYGZ1bmNgIHVudGlsIGFmdGVyIGB3YWl0YFxuICogbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gd2FzXG4gKiBpbnZva2VkLiBUaGUgZGVib3VuY2VkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYCBtZXRob2QgdG8gY2FuY2VsXG4gKiBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0byBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS5cbiAqIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZVxuICogbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZFxuICogd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbi4gU3Vic2VxdWVudFxuICogY2FsbHMgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2BcbiAqIGludm9jYXRpb24uXG4gKlxuICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb25cbiAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAqXG4gKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAqXG4gKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8uZGVib3VuY2VgIGFuZCBgXy50aHJvdHRsZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWJvdW5jZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPWZhbHNlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tYXhXYWl0XVxuICogIFRoZSBtYXhpbXVtIHRpbWUgYGZ1bmNgIGlzIGFsbG93ZWQgdG8gYmUgZGVsYXllZCBiZWZvcmUgaXQncyBpbnZva2VkLlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBkZWJvdW5jZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIC8vIEF2b2lkIGNvc3RseSBjYWxjdWxhdGlvbnMgd2hpbGUgdGhlIHdpbmRvdyBzaXplIGlzIGluIGZsdXguXG4gKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgXy5kZWJvdW5jZShjYWxjdWxhdGVMYXlvdXQsIDE1MCkpO1xuICpcbiAqIC8vIEludm9rZSBgc2VuZE1haWxgIHdoZW4gY2xpY2tlZCwgZGVib3VuY2luZyBzdWJzZXF1ZW50IGNhbGxzLlxuICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIF8uZGVib3VuY2Uoc2VuZE1haWwsIDMwMCwge1xuICogICAnbGVhZGluZyc6IHRydWUsXG4gKiAgICd0cmFpbGluZyc6IGZhbHNlXG4gKiB9KSk7XG4gKlxuICogLy8gRW5zdXJlIGBiYXRjaExvZ2AgaXMgaW52b2tlZCBvbmNlIGFmdGVyIDEgc2Vjb25kIG9mIGRlYm91bmNlZCBjYWxscy5cbiAqIHZhciBkZWJvdW5jZWQgPSBfLmRlYm91bmNlKGJhdGNoTG9nLCAyNTAsIHsgJ21heFdhaXQnOiAxMDAwIH0pO1xuICogdmFyIHNvdXJjZSA9IG5ldyBFdmVudFNvdXJjZSgnL3N0cmVhbScpO1xuICogalF1ZXJ5KHNvdXJjZSkub24oJ21lc3NhZ2UnLCBkZWJvdW5jZWQpO1xuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgZGVib3VuY2VkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCBkZWJvdW5jZWQuY2FuY2VsKTtcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICB2YXIgbGFzdEFyZ3MsXG4gICAgICBsYXN0VGhpcyxcbiAgICAgIG1heFdhaXQsXG4gICAgICByZXN1bHQsXG4gICAgICB0aW1lcklkLFxuICAgICAgbGFzdENhbGxUaW1lLFxuICAgICAgbGFzdEludm9rZVRpbWUgPSAwLFxuICAgICAgbGVhZGluZyA9IGZhbHNlLFxuICAgICAgbWF4aW5nID0gZmFsc2UsXG4gICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gIH1cbiAgd2FpdCA9IHRvTnVtYmVyKHdhaXQpIHx8IDA7XG4gIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgIGxlYWRpbmcgPSAhIW9wdGlvbnMubGVhZGluZztcbiAgICBtYXhpbmcgPSAnbWF4V2FpdCcgaW4gb3B0aW9ucztcbiAgICBtYXhXYWl0ID0gbWF4aW5nID8gbmF0aXZlTWF4KHRvTnVtYmVyKG9wdGlvbnMubWF4V2FpdCkgfHwgMCwgd2FpdCkgOiBtYXhXYWl0O1xuICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gIH1cblxuICBmdW5jdGlvbiBpbnZva2VGdW5jKHRpbWUpIHtcbiAgICB2YXIgYXJncyA9IGxhc3RBcmdzLFxuICAgICAgICB0aGlzQXJnID0gbGFzdFRoaXM7XG5cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBsZWFkaW5nRWRnZSh0aW1lKSB7XG4gICAgLy8gUmVzZXQgYW55IGBtYXhXYWl0YCB0aW1lci5cbiAgICBsYXN0SW52b2tlVGltZSA9IHRpbWU7XG4gICAgLy8gU3RhcnQgdGhlIHRpbWVyIGZvciB0aGUgdHJhaWxpbmcgZWRnZS5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIC8vIEludm9rZSB0aGUgbGVhZGluZyBlZGdlLlxuICAgIHJldHVybiBsZWFkaW5nID8gaW52b2tlRnVuYyh0aW1lKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbWFpbmluZ1dhaXQodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWUsXG4gICAgICAgIHJlc3VsdCA9IHdhaXQgLSB0aW1lU2luY2VMYXN0Q2FsbDtcblxuICAgIHJldHVybiBtYXhpbmcgPyBuYXRpdmVNaW4ocmVzdWx0LCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSkgOiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBzaG91bGRJbnZva2UodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWU7XG5cbiAgICAvLyBFaXRoZXIgdGhpcyBpcyB0aGUgZmlyc3QgY2FsbCwgYWN0aXZpdHkgaGFzIHN0b3BwZWQgYW5kIHdlJ3JlIGF0IHRoZVxuICAgIC8vIHRyYWlsaW5nIGVkZ2UsIHRoZSBzeXN0ZW0gdGltZSBoYXMgZ29uZSBiYWNrd2FyZHMgYW5kIHdlJ3JlIHRyZWF0aW5nXG4gICAgLy8gaXQgYXMgdGhlIHRyYWlsaW5nIGVkZ2UsIG9yIHdlJ3ZlIGhpdCB0aGUgYG1heFdhaXRgIGxpbWl0LlxuICAgIHJldHVybiAobGFzdENhbGxUaW1lID09PSB1bmRlZmluZWQgfHwgKHRpbWVTaW5jZUxhc3RDYWxsID49IHdhaXQpIHx8XG4gICAgICAodGltZVNpbmNlTGFzdENhbGwgPCAwKSB8fCAobWF4aW5nICYmIHRpbWVTaW5jZUxhc3RJbnZva2UgPj0gbWF4V2FpdCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdGltZXJFeHBpcmVkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCk7XG4gICAgaWYgKHNob3VsZEludm9rZSh0aW1lKSkge1xuICAgICAgcmV0dXJuIHRyYWlsaW5nRWRnZSh0aW1lKTtcbiAgICB9XG4gICAgLy8gUmVzdGFydCB0aGUgdGltZXIuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCByZW1haW5pbmdXYWl0KHRpbWUpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRyYWlsaW5nRWRnZSh0aW1lKSB7XG4gICAgdGltZXJJZCA9IHVuZGVmaW5lZDtcblxuICAgIC8vIE9ubHkgaW52b2tlIGlmIHdlIGhhdmUgYGxhc3RBcmdzYCB3aGljaCBtZWFucyBgZnVuY2AgaGFzIGJlZW5cbiAgICAvLyBkZWJvdW5jZWQgYXQgbGVhc3Qgb25jZS5cbiAgICBpZiAodHJhaWxpbmcgJiYgbGFzdEFyZ3MpIHtcbiAgICAgIHJldHVybiBpbnZva2VGdW5jKHRpbWUpO1xuICAgIH1cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBjYW5jZWwoKSB7XG4gICAgaWYgKHRpbWVySWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVySWQpO1xuICAgIH1cbiAgICBsYXN0SW52b2tlVGltZSA9IDA7XG4gICAgbGFzdEFyZ3MgPSBsYXN0Q2FsbFRpbWUgPSBsYXN0VGhpcyA9IHRpbWVySWQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBmdW5jdGlvbiBmbHVzaCgpIHtcbiAgICByZXR1cm4gdGltZXJJZCA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogdHJhaWxpbmdFZGdlKG5vdygpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcbiAgICB2YXIgdGltZSA9IG5vdygpLFxuICAgICAgICBpc0ludm9raW5nID0gc2hvdWxkSW52b2tlKHRpbWUpO1xuXG4gICAgbGFzdEFyZ3MgPSBhcmd1bWVudHM7XG4gICAgbGFzdFRoaXMgPSB0aGlzO1xuICAgIGxhc3RDYWxsVGltZSA9IHRpbWU7XG5cbiAgICBpZiAoaXNJbnZva2luZykge1xuICAgICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gbGVhZGluZ0VkZ2UobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICAgIGlmIChtYXhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIGludm9jYXRpb25zIGluIGEgdGlnaHQgbG9vcC5cbiAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgcmV0dXJuIGludm9rZUZ1bmMobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBkZWJvdW5jZWQuY2FuY2VsID0gY2FuY2VsO1xuICBkZWJvdW5jZWQuZmx1c2ggPSBmbHVzaDtcbiAgcmV0dXJuIGRlYm91bmNlZDtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGVcbiAqIFtsYW5ndWFnZSB0eXBlXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtZWNtYXNjcmlwdC1sYW5ndWFnZS10eXBlcylcbiAqIG9mIGBPYmplY3RgLiAoZS5nLiBhcnJheXMsIGZ1bmN0aW9ucywgb2JqZWN0cywgcmVnZXhlcywgYG5ldyBOdW1iZXIoMClgLCBhbmQgYG5ldyBTdHJpbmcoJycpYClcbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdCh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoXy5ub29wKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIHJldHVybiAhIXZhbHVlICYmICh0eXBlID09ICdvYmplY3QnIHx8IHR5cGUgPT0gJ2Z1bmN0aW9uJyk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UuIEEgdmFsdWUgaXMgb2JqZWN0LWxpa2UgaWYgaXQncyBub3QgYG51bGxgXG4gKiBhbmQgaGFzIGEgYHR5cGVvZmAgcmVzdWx0IG9mIFwib2JqZWN0XCIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdExpa2Uoe30pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc09iamVjdExpa2UobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdExpa2UodmFsdWUpIHtcbiAgcmV0dXJuICEhdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3ltYm9sYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc3ltYm9sLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNTeW1ib2woU3ltYm9sLml0ZXJhdG9yKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzU3ltYm9sKCdhYmMnKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzU3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N5bWJvbCcgfHxcbiAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBzeW1ib2xUYWcpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBudW1iZXIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBudW1iZXIuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8udG9OdW1iZXIoMy4yKTtcbiAqIC8vID0+IDMuMlxuICpcbiAqIF8udG9OdW1iZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gKiAvLyA9PiA1ZS0zMjRcbiAqXG4gKiBfLnRvTnVtYmVyKEluZmluaXR5KTtcbiAqIC8vID0+IEluZmluaXR5XG4gKlxuICogXy50b051bWJlcignMy4yJyk7XG4gKiAvLyA9PiAzLjJcbiAqL1xuZnVuY3Rpb24gdG9OdW1iZXIodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJykge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgcmV0dXJuIE5BTjtcbiAgfVxuICBpZiAoaXNPYmplY3QodmFsdWUpKSB7XG4gICAgdmFyIG90aGVyID0gdHlwZW9mIHZhbHVlLnZhbHVlT2YgPT0gJ2Z1bmN0aW9uJyA/IHZhbHVlLnZhbHVlT2YoKSA6IHZhbHVlO1xuICAgIHZhbHVlID0gaXNPYmplY3Qob3RoZXIpID8gKG90aGVyICsgJycpIDogb3RoZXI7XG4gIH1cbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykge1xuICAgIHJldHVybiB2YWx1ZSA9PT0gMCA/IHZhbHVlIDogK3ZhbHVlO1xuICB9XG4gIHZhbHVlID0gdmFsdWUucmVwbGFjZShyZVRyaW0sICcnKTtcbiAgdmFyIGlzQmluYXJ5ID0gcmVJc0JpbmFyeS50ZXN0KHZhbHVlKTtcbiAgcmV0dXJuIChpc0JpbmFyeSB8fCByZUlzT2N0YWwudGVzdCh2YWx1ZSkpXG4gICAgPyBmcmVlUGFyc2VJbnQodmFsdWUuc2xpY2UoMiksIGlzQmluYXJ5ID8gMiA6IDgpXG4gICAgOiAocmVJc0JhZEhleC50ZXN0KHZhbHVlKSA/IE5BTiA6ICt2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZGVib3VuY2U7XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/lodash.debounce/index.js\n");
/***/ }),
/***/ "./node_modules/lodash/lodash.js":
/*!***************************************!*\
!*** ./node_modules/lodash/lodash.js ***!
\***************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("/* WEBPACK VAR INJECTION */(function(global, module) {var __WEBPACK_AMD_DEFINE_RESULT__;/**\n * @license\n * Lodash <https://lodash.com/>\n * Copyright OpenJS Foundation and other contributors <https://openjsf.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n;(function() {\n\n /** Used as a safe reference for `undefined` in pre-ES5 environments. */\n var undefined;\n\n /** Used as the semantic version number. */\n var VERSION = '4.17.19';\n\n /** Used as the size to enable large array optimizations. */\n var LARGE_ARRAY_SIZE = 200;\n\n /** Error message constants. */\n var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',\n FUNC_ERROR_TEXT = 'Expected a function';\n\n /** Used to stand-in for `undefined` hash values. */\n var HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n /** Used as the maximum memoize cache size. */\n var MAX_MEMOIZE_SIZE = 500;\n\n /** Used as the internal argument placeholder. */\n var PLACEHOLDER = '__lodash_placeholder__';\n\n /** Used to compose bitmasks for cloning. */\n var CLONE_DEEP_FLAG = 1,\n CLONE_FLAT_FLAG = 2,\n CLONE_SYMBOLS_FLAG = 4;\n\n /** Used to compose bitmasks for value comparisons. */\n var COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n /** Used to compose bitmasks for function metadata. */\n var WRAP_BIND_FLAG = 1,\n WRAP_BIND_KEY_FLAG = 2,\n WRAP_CURRY_BOUND_FLAG = 4,\n WRAP_CURRY_FLAG = 8,\n WRAP_CURRY_RIGHT_FLAG = 16,\n WRAP_PARTIAL_FLAG = 32,\n WRAP_PARTIAL_RIGHT_FLAG = 64,\n WRAP_ARY_FLAG = 128,\n WRAP_REARG_FLAG = 256,\n WRAP_FLIP_FLAG = 512;\n\n /** Used as default options for `_.truncate`. */\n var DEFAULT_TRUNC_LENGTH = 30,\n DEFAULT_TRUNC_OMISSION = '...';\n\n /** Used to detect hot functions by number of calls within a span of milliseconds. */\n var HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n /** Used to indicate the type of lazy iteratees. */\n var LAZY_FILTER_FLAG = 1,\n LAZY_MAP_FLAG = 2,\n LAZY_WHILE_FLAG = 3;\n\n /** Used as references for various `Number` constants. */\n var INFINITY = 1 / 0,\n MAX_SAFE_INTEGER = 9007199254740991,\n MAX_INTEGER = 1.7976931348623157e+308,\n NAN = 0 / 0;\n\n /** Used as references for the maximum length and index of an array. */\n var MAX_ARRAY_LENGTH = 4294967295,\n MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,\n HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;\n\n /** Used to associate wrap methods with their bit flags. */\n var wrapFlags = [\n ['ary', WRAP_ARY_FLAG],\n ['bind', WRAP_BIND_FLAG],\n ['bindKey', WRAP_BIND_KEY_FLAG],\n ['curry', WRAP_CURRY_FLAG],\n ['curryRight', WRAP_CURRY_RIGHT_FLAG],\n ['flip', WRAP_FLIP_FLAG],\n ['partial', WRAP_PARTIAL_FLAG],\n ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],\n ['rearg', WRAP_REARG_FLAG]\n ];\n\n /** `Object#toString` result references. */\n var argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n asyncTag = '[object AsyncFunction]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n domExcTag = '[object DOMException]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n nullTag = '[object Null]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n proxyTag = '[object Proxy]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]',\n undefinedTag = '[object Undefined]',\n weakMapTag = '[object WeakMap]',\n weakSetTag = '[object WeakSet]';\n\n var arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n /** Used to match empty string literals in compiled template source. */\n var reEmptyStringLeading = /\\b__p \\+= '';/g,\n reEmptyStringMiddle = /\\b(__p \\+=) '' \\+/g,\n reEmptyStringTrailing = /(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g;\n\n /** Used to match HTML entities and HTML characters. */\n var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,\n reUnescapedHtml = /[&<>\"']/g,\n reHasEscapedHtml = RegExp(reEscapedHtml.source),\n reHasUnescapedHtml = RegExp(reUnescapedHtml.source);\n\n /** Used to match template delimiters. */\n var reEscape = /<%-([\\s\\S]+?)%>/g,\n reEvaluate = /<%([\\s\\S]+?)%>/g,\n reInterpolate = /<%=([\\s\\S]+?)%>/g;\n\n /** Used to match property names within property paths. */\n var reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/,\n rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n /**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\n var reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g,\n reHasRegExpChar = RegExp(reRegExpChar.source);\n\n /** Used to match leading and trailing whitespace. */\n var reTrim = /^\\s+|\\s+$/g,\n reTrimStart = /^\\s+/,\n reTrimEnd = /\\s+$/;\n\n /** Used to match wrap detail comments. */\n var reWrapComment = /\\{(?:\\n\\/\\* \\[wrapped with .+\\] \\*\\/)?\\n?/,\n reWrapDetails = /\\{\\n\\/\\* \\[wrapped with (.+)\\] \\*/,\n reSplitDetails = /,? & /;\n\n /** Used to match words composed of alphanumeric characters. */\n var reAsciiWord = /[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g;\n\n /** Used to match backslashes in property paths. */\n var reEscapeChar = /\\\\(\\\\)?/g;\n\n /**\n * Used to match\n * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).\n */\n var reEsTemplate = /\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g;\n\n /** Used to match `RegExp` flags from their coerced string values. */\n var reFlags = /\\w*$/;\n\n /** Used to detect bad signed hexadecimal string values. */\n var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n /** Used to detect binary string values. */\n var reIsBinary = /^0b[01]+$/i;\n\n /** Used to detect host constructors (Safari). */\n var reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n /** Used to detect octal string values. */\n var reIsOctal = /^0o[0-7]+$/i;\n\n /** Used to detect unsigned integer values. */\n var reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n /** Used to match Latin Unicode letters (excluding mathematical operators). */\n var reLatin = /[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g;\n\n /** Used to ensure capturing order of template delimiters. */\n var reNoMatch = /($^)/;\n\n /** Used to match unescaped characters in compiled string literals. */\n var reUnescapedString = /['\\n\\r\\u2028\\u2029\\\\]/g;\n\n /** Used to compose unicode character classes. */\n var rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsDingbatRange = '\\\\u2700-\\\\u27bf',\n rsLowerRange = 'a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff',\n rsMathOpRange = '\\\\xac\\\\xb1\\\\xd7\\\\xf7',\n rsNonCharRange = '\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf',\n rsPunctuationRange = '\\\\u2000-\\\\u206f',\n rsSpaceRange = ' \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000',\n rsUpperRange = 'A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde',\n rsVarRange = '\\\\ufe0e\\\\ufe0f',\n rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;\n\n /** Used to compose unicode capture groups. */\n var rsApos = \"['\\u2019]\",\n rsAstral = '[' + rsAstralRange + ']',\n rsBreak = '[' + rsBreakRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsDigits = '\\\\d+',\n rsDingbat = '[' + rsDingbatRange + ']',\n rsLower = '[' + rsLowerRange + ']',\n rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsUpper = '[' + rsUpperRange + ']',\n rsZWJ = '\\\\u200d';\n\n /** Used to compose unicode regexes. */\n var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',\n rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',\n rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',\n rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',\n reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsOrdLower = '\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])',\n rsOrdUpper = '\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n /** Used to match apostrophes. */\n var reApos = RegExp(rsApos, 'g');\n\n /**\n * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and\n * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).\n */\n var reComboMark = RegExp(rsCombo, 'g');\n\n /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\n var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n /** Used to match complex or compound words. */\n var reUnicodeWord = RegExp([\n rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',\n rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',\n rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,\n rsUpper + '+' + rsOptContrUpper,\n rsOrdUpper,\n rsOrdLower,\n rsDigits,\n rsEmoji\n ].join('|'), 'g');\n\n /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\n var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n /** Used to detect strings that need a more robust regexp to match words. */\n var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;\n\n /** Used to assign default `context` object properties. */\n var contextProps = [\n 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',\n 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',\n 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',\n 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',\n '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'\n ];\n\n /** Used to make template sourceURLs easier to identify. */\n var templateCounter = -1;\n\n /** Used to identify `toStringTag` values of typed arrays. */\n var typedArrayTags = {};\n typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\n typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\n typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\n typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\n typedArrayTags[uint32Tag] = true;\n typedArrayTags[argsTag] = typedArrayTags[arrayTag] =\n typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\n typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\n typedArrayTags[errorTag] = typedArrayTags[funcTag] =\n typedArrayTags[mapTag] = typedArrayTags[numberTag] =\n typedArrayTags[objectTag] = typedArrayTags[regexpTag] =\n typedArrayTags[setTag] = typedArrayTags[stringTag] =\n typedArrayTags[weakMapTag] = false;\n\n /** Used to identify `toStringTag` values supported by `_.clone`. */\n var cloneableTags = {};\n cloneableTags[argsTag] = cloneableTags[arrayTag] =\n cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =\n cloneableTags[boolTag] = cloneableTags[dateTag] =\n cloneableTags[float32Tag] = cloneableTags[float64Tag] =\n cloneableTags[int8Tag] = cloneableTags[int16Tag] =\n cloneableTags[int32Tag] = cloneableTags[mapTag] =\n cloneableTags[numberTag] = cloneableTags[objectTag] =\n cloneableTags[regexpTag] = cloneableTags[setTag] =\n cloneableTags[stringTag] = cloneableTags[symbolTag] =\n cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\n cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\n cloneableTags[errorTag] = cloneableTags[funcTag] =\n cloneableTags[weakMapTag] = false;\n\n /** Used to map Latin Unicode letters to basic Latin letters. */\n var deburredLetters = {\n // Latin-1 Supplement block.\n '\\xc0': 'A', '\\xc1': 'A', '\\xc2': 'A', '\\xc3': 'A', '\\xc4': 'A', '\\xc5': 'A',\n '\\xe0': 'a', '\\xe1': 'a', '\\xe2': 'a', '\\xe3': 'a', '\\xe4': 'a', '\\xe5': 'a',\n '\\xc7': 'C', '\\xe7': 'c',\n '\\xd0': 'D', '\\xf0': 'd',\n '\\xc8': 'E', '\\xc9': 'E', '\\xca': 'E', '\\xcb': 'E',\n '\\xe8': 'e', '\\xe9': 'e', '\\xea': 'e', '\\xeb': 'e',\n '\\xcc': 'I', '\\xcd': 'I', '\\xce': 'I', '\\xcf': 'I',\n '\\xec': 'i', '\\xed': 'i', '\\xee': 'i', '\\xef': 'i',\n '\\xd1': 'N', '\\xf1': 'n',\n '\\xd2': 'O', '\\xd3': 'O', '\\xd4': 'O', '\\xd5': 'O', '\\xd6': 'O', '\\xd8': 'O',\n '\\xf2': 'o', '\\xf3': 'o', '\\xf4': 'o', '\\xf5': 'o', '\\xf6': 'o', '\\xf8': 'o',\n '\\xd9': 'U', '\\xda': 'U', '\\xdb': 'U', '\\xdc': 'U',\n '\\xf9': 'u', '\\xfa': 'u', '\\xfb': 'u', '\\xfc': 'u',\n '\\xdd': 'Y', '\\xfd': 'y', '\\xff': 'y',\n '\\xc6': 'Ae', '\\xe6': 'ae',\n '\\xde': 'Th', '\\xfe': 'th',\n '\\xdf': 'ss',\n // Latin Extended-A block.\n '\\u0100': 'A', '\\u0102': 'A', '\\u0104': 'A',\n '\\u0101': 'a', '\\u0103': 'a', '\\u0105': 'a',\n '\\u0106': 'C', '\\u0108': 'C', '\\u010a': 'C', '\\u010c': 'C',\n '\\u0107': 'c', '\\u0109': 'c', '\\u010b': 'c', '\\u010d': 'c',\n '\\u010e': 'D', '\\u0110': 'D', '\\u010f': 'd', '\\u0111': 'd',\n '\\u0112': 'E', '\\u0114': 'E', '\\u0116': 'E', '\\u0118': 'E', '\\u011a': 'E',\n '\\u0113': 'e', '\\u0115': 'e', '\\u0117': 'e', '\\u0119': 'e', '\\u011b': 'e',\n '\\u011c': 'G', '\\u011e': 'G', '\\u0120': 'G', '\\u0122': 'G',\n '\\u011d': 'g', '\\u011f': 'g', '\\u0121': 'g', '\\u0123': 'g',\n '\\u0124': 'H', '\\u0126': 'H', '\\u0125': 'h', '\\u0127': 'h',\n '\\u0128': 'I', '\\u012a': 'I', '\\u012c': 'I', '\\u012e': 'I', '\\u0130': 'I',\n '\\u0129': 'i', '\\u012b': 'i', '\\u012d': 'i', '\\u012f': 'i', '\\u0131': 'i',\n '\\u0134': 'J', '\\u0135': 'j',\n '\\u0136': 'K', '\\u0137': 'k', '\\u0138': 'k',\n '\\u0139': 'L', '\\u013b': 'L', '\\u013d': 'L', '\\u013f': 'L', '\\u0141': 'L',\n '\\u013a': 'l', '\\u013c': 'l', '\\u013e': 'l', '\\u0140': 'l', '\\u0142': 'l',\n '\\u0143': 'N', '\\u0145': 'N', '\\u0147': 'N', '\\u014a': 'N',\n '\\u0144': 'n', '\\u0146': 'n', '\\u0148': 'n', '\\u014b': 'n',\n '\\u014c': 'O', '\\u014e': 'O', '\\u0150': 'O',\n '\\u014d': 'o', '\\u014f': 'o', '\\u0151': 'o',\n '\\u0154': 'R', '\\u0156': 'R', '\\u0158': 'R',\n '\\u0155': 'r', '\\u0157': 'r', '\\u0159': 'r',\n '\\u015a': 'S', '\\u015c': 'S', '\\u015e': 'S', '\\u0160': 'S',\n '\\u015b': 's', '\\u015d': 's', '\\u015f': 's', '\\u0161': 's',\n '\\u0162': 'T', '\\u0164': 'T', '\\u0166': 'T',\n '\\u0163': 't', '\\u0165': 't', '\\u0167': 't',\n '\\u0168': 'U', '\\u016a': 'U', '\\u016c': 'U', '\\u016e': 'U', '\\u0170': 'U', '\\u0172': 'U',\n '\\u0169': 'u', '\\u016b': 'u', '\\u016d': 'u', '\\u016f': 'u', '\\u0171': 'u', '\\u0173': 'u',\n '\\u0174': 'W', '\\u0175': 'w',\n '\\u0176': 'Y', '\\u0177': 'y', '\\u0178': 'Y',\n '\\u0179': 'Z', '\\u017b': 'Z', '\\u017d': 'Z',\n '\\u017a': 'z', '\\u017c': 'z', '\\u017e': 'z',\n '\\u0132': 'IJ', '\\u0133': 'ij',\n '\\u0152': 'Oe', '\\u0153': 'oe',\n '\\u0149': \"'n\", '\\u017f': 's'\n };\n\n /** Used to map characters to HTML entities. */\n var htmlEscapes = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;'\n };\n\n /** Used to map HTML entities to characters. */\n var htmlUnescapes = {\n '&amp;': '&',\n '&lt;': '<',\n '&gt;': '>',\n '&quot;': '\"',\n '&#39;': \"'\"\n };\n\n /** Used to escape characters for inclusion in compiled string literals. */\n var stringEscapes = {\n '\\\\': '\\\\',\n \"'\": \"'\",\n '\\n': 'n',\n '\\r': 'r',\n '\\u2028': 'u2028',\n '\\u2029': 'u2029'\n };\n\n /** Built-in method references without a dependency on `root`. */\n var freeParseFloat = parseFloat,\n freeParseInt = parseInt;\n\n /** Detect free variable `global` from Node.js. */\n var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n /** Detect free variable `self`. */\n var freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n /** Used as a reference to the global object. */\n var root = freeGlobal || freeSelf || Function('return this')();\n\n /** Detect free variable `exports`. */\n var freeExports = true && exports && !exports.nodeType && exports;\n\n /** Detect free variable `module`. */\n var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n /** Detect the popular CommonJS extension `module.exports`. */\n var moduleExports = freeModule && freeModule.exports === freeExports;\n\n /** Detect free variable `process` from Node.js. */\n var freeProcess = moduleExports && freeGlobal.process;\n\n /** Used to access faster Node.js helpers. */\n var nodeUtil = (function() {\n try {\n // Use `util.types` for Node.js 10+.\n var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n if (types) {\n return types;\n }\n\n // Legacy `process.binding('util')` for Node.js < 10.\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n }());\n\n /* Node.js helper references. */\n var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,\n nodeIsDate = nodeUtil && nodeUtil.isDate,\n nodeIsMap = nodeUtil && nodeUtil.isMap,\n nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,\n nodeIsSet = nodeUtil && nodeUtil.isSet,\n nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\n function apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n }\n\n /**\n * A specialized version of `baseAggregator` for arrays.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} setter The function to set `accumulator` values.\n * @param {Function} iteratee The iteratee to transform keys.\n * @param {Object} accumulator The initial aggregated object.\n * @returns {Function} Returns `accumulator`.\n */\n function arrayAggregator(array, setter, iteratee, accumulator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n var value = array[index];\n setter(accumulator, value, iteratee(value), array);\n }\n return accumulator;\n }\n\n /**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\n function arrayEach(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n }\n\n /**\n * A specialized version of `_.forEachRight` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\n function arrayEachRight(array, iteratee) {\n var length = array == null ? 0 : array.length;\n\n while (length--) {\n if (iteratee(array[length], length, array) === false) {\n break;\n }\n }\n return array;\n }\n\n /**\n * A specialized version of `_.every` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if all elements pass the predicate check,\n * else `false`.\n */\n function arrayEvery(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (!predicate(array[index], index, array)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\n function arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n }\n\n /**\n * A specialized version of `_.includes` for arrays without support for\n * specifying an index to search from.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\n function arrayIncludes(array, value) {\n var length = array == null ? 0 : array.length;\n return !!length && baseIndexOf(array, value, 0) > -1;\n }\n\n /**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\n function arrayIncludesWith(array, value, comparator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (comparator(value, array[index])) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\n function arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n }\n\n /**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\n function arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n }\n\n /**\n * A specialized version of `_.reduce` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the first element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\n function arrayReduce(array, iteratee, accumulator, initAccum) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n if (initAccum && length) {\n accumulator = array[++index];\n }\n while (++index < length) {\n accumulator = iteratee(accumulator, array[index], index, array);\n }\n return accumulator;\n }\n\n /**\n * A specialized version of `_.reduceRight` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the last element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\n function arrayReduceRight(array, iteratee, accumulator, initAccum) {\n var length = array == null ? 0 : array.length;\n if (initAccum && length) {\n accumulator = array[--length];\n }\n while (length--) {\n accumulator = iteratee(accumulator, array[length], length, array);\n }\n return accumulator;\n }\n\n /**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\n function arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Gets the size of an ASCII `string`.\n *\n * @private\n * @param {string} string The string inspect.\n * @returns {number} Returns the string size.\n */\n var asciiSize = baseProperty('length');\n\n /**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\n function asciiToArray(string) {\n return string.split('');\n }\n\n /**\n * Splits an ASCII `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\n function asciiWords(string) {\n return string.match(reAsciiWord) || [];\n }\n\n /**\n * The base implementation of methods like `_.findKey` and `_.findLastKey`,\n * without support for iteratee shorthands, which iterates over `collection`\n * using `eachFunc`.\n *\n * @private\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {Function} eachFunc The function to iterate over `collection`.\n * @returns {*} Returns the found element or its key, else `undefined`.\n */\n function baseFindKey(collection, predicate, eachFunc) {\n var result;\n eachFunc(collection, function(value, key, collection) {\n if (predicate(value, key, collection)) {\n result = key;\n return false;\n }\n });\n return result;\n }\n\n /**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * The base implementation of `_.indexOf` without `fromIndex` bounds checks.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function baseIndexOf(array, value, fromIndex) {\n return value === value\n ? strictIndexOf(array, value, fromIndex)\n : baseFindIndex(array, baseIsNaN, fromIndex);\n }\n\n /**\n * This function is like `baseIndexOf` except that it accepts a comparator.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function baseIndexOfWith(array, value, fromIndex, comparator) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (comparator(array[index], value)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\n function baseIsNaN(value) {\n return value !== value;\n }\n\n /**\n * The base implementation of `_.mean` and `_.meanBy` without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {number} Returns the mean.\n */\n function baseMean(array, iteratee) {\n var length = array == null ? 0 : array.length;\n return length ? (baseSum(array, iteratee) / length) : NAN;\n }\n\n /**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\n function baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n }\n\n /**\n * The base implementation of `_.propertyOf` without support for deep paths.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n */\n function basePropertyOf(object) {\n return function(key) {\n return object == null ? undefined : object[key];\n };\n }\n\n /**\n * The base implementation of `_.reduce` and `_.reduceRight`, without support\n * for iteratee shorthands, which iterates over `collection` using `eachFunc`.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} accumulator The initial value.\n * @param {boolean} initAccum Specify using the first or last element of\n * `collection` as the initial value.\n * @param {Function} eachFunc The function to iterate over `collection`.\n * @returns {*} Returns the accumulated value.\n */\n function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {\n eachFunc(collection, function(value, index, collection) {\n accumulator = initAccum\n ? (initAccum = false, value)\n : iteratee(accumulator, value, index, collection);\n });\n return accumulator;\n }\n\n /**\n * The base implementation of `_.sortBy` which uses `comparer` to define the\n * sort order of `array` and replaces criteria objects with their corresponding\n * values.\n *\n * @private\n * @param {Array} array The array to sort.\n * @param {Function} comparer The function to define sort order.\n * @returns {Array} Returns `array`.\n */\n function baseSortBy(array, comparer) {\n var length = array.length;\n\n array.sort(comparer);\n while (length--) {\n array[length] = array[length].value;\n }\n return array;\n }\n\n /**\n * The base implementation of `_.sum` and `_.sumBy` without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {number} Returns the sum.\n */\n function baseSum(array, iteratee) {\n var result,\n index = -1,\n length = array.length;\n\n while (++index < length) {\n var current = iteratee(array[index]);\n if (current !== undefined) {\n result = result === undefined ? current : (result + current);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\n function baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n }\n\n /**\n * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array\n * of key-value pairs for `object` corresponding to the property names of `props`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} props The property names to get values for.\n * @returns {Object} Returns the key-value pairs.\n */\n function baseToPairs(object, props) {\n return arrayMap(props, function(key) {\n return [key, object[key]];\n });\n }\n\n /**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\n function baseUnary(func) {\n return function(value) {\n return func(value);\n };\n }\n\n /**\n * The base implementation of `_.values` and `_.valuesIn` which creates an\n * array of `object` property values corresponding to the property names\n * of `props`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} props The property names to get values for.\n * @returns {Object} Returns the array of property values.\n */\n function baseValues(object, props) {\n return arrayMap(props, function(key) {\n return object[key];\n });\n }\n\n /**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function cacheHas(cache, key) {\n return cache.has(key);\n }\n\n /**\n * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol\n * that is not found in the character symbols.\n *\n * @private\n * @param {Array} strSymbols The string symbols to inspect.\n * @param {Array} chrSymbols The character symbols to find.\n * @returns {number} Returns the index of the first unmatched string symbol.\n */\n function charsStartIndex(strSymbols, chrSymbols) {\n var index = -1,\n length = strSymbols.length;\n\n while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}\n return index;\n }\n\n /**\n * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol\n * that is not found in the character symbols.\n *\n * @private\n * @param {Array} strSymbols The string symbols to inspect.\n * @param {Array} chrSymbols The character symbols to find.\n * @returns {number} Returns the index of the last unmatched string symbol.\n */\n function charsEndIndex(strSymbols, chrSymbols) {\n var index = strSymbols.length;\n\n while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}\n return index;\n }\n\n /**\n * Gets the number of `placeholder` occurrences in `array`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} placeholder The placeholder to search for.\n * @returns {number} Returns the placeholder count.\n */\n function countHolders(array, placeholder) {\n var length = array.length,\n result = 0;\n\n while (length--) {\n if (array[length] === placeholder) {\n ++result;\n }\n }\n return result;\n }\n\n /**\n * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A\n * letters to basic Latin letters.\n *\n * @private\n * @param {string} letter The matched letter to deburr.\n * @returns {string} Returns the deburred letter.\n */\n var deburrLetter = basePropertyOf(deburredLetters);\n\n /**\n * Used by `_.escape` to convert characters to HTML entities.\n *\n * @private\n * @param {string} chr The matched character to escape.\n * @returns {string} Returns the escaped character.\n */\n var escapeHtmlChar = basePropertyOf(htmlEscapes);\n\n /**\n * Used by `_.template` to escape characters for inclusion in compiled string literals.\n *\n * @private\n * @param {string} chr The matched character to escape.\n * @returns {string} Returns the escaped character.\n */\n function escapeStringChar(chr) {\n return '\\\\' + stringEscapes[chr];\n }\n\n /**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\n function getValue(object, key) {\n return object == null ? undefined : object[key];\n }\n\n /**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\n function hasUnicode(string) {\n return reHasUnicode.test(string);\n }\n\n /**\n * Checks if `string` contains a word composed of Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a word is found, else `false`.\n */\n function hasUnicodeWord(string) {\n return reHasUnicodeWord.test(string);\n }\n\n /**\n * Converts `iterator` to an array.\n *\n * @private\n * @param {Object} iterator The iterator to convert.\n * @returns {Array} Returns the converted array.\n */\n function iteratorToArray(iterator) {\n var data,\n result = [];\n\n while (!(data = iterator.next()).done) {\n result.push(data.value);\n }\n return result;\n }\n\n /**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\n function mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n }\n\n /**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\n function overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n }\n\n /**\n * Replaces all `placeholder` elements in `array` with an internal placeholder\n * and returns an array of their indexes.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {*} placeholder The placeholder to replace.\n * @returns {Array} Returns the new array of placeholder indexes.\n */\n function replaceHolders(array, placeholder) {\n var index = -1,\n length = array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (value === placeholder || value === PLACEHOLDER) {\n array[index] = PLACEHOLDER;\n result[resIndex++] = index;\n }\n }\n return result;\n }\n\n /**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\n function setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n }\n\n /**\n * Converts `set` to its value-value pairs.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the value-value pairs.\n */\n function setToPairs(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = [value, value];\n });\n return result;\n }\n\n /**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * A specialized version of `_.lastIndexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function strictLastIndexOf(array, value, fromIndex) {\n var index = fromIndex + 1;\n while (index--) {\n if (array[index] === value) {\n return index;\n }\n }\n return index;\n }\n\n /**\n * Gets the number of symbols in `string`.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {number} Returns the string size.\n */\n function stringSize(string) {\n return hasUnicode(string)\n ? unicodeSize(string)\n : asciiSize(string);\n }\n\n /**\n * Converts `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\n function stringToArray(string) {\n return hasUnicode(string)\n ? unicodeToArray(string)\n : asciiToArray(string);\n }\n\n /**\n * Used by `_.unescape` to convert HTML entities to characters.\n *\n * @private\n * @param {string} chr The matched character to unescape.\n * @returns {string} Returns the unescaped character.\n */\n var unescapeHtmlChar = basePropertyOf(htmlUnescapes);\n\n /**\n * Gets the size of a Unicode `string`.\n *\n * @private\n * @param {string} string The string inspect.\n * @returns {number} Returns the string size.\n */\n function unicodeSize(string) {\n var result = reUnicode.lastIndex = 0;\n while (reUnicode.test(string)) {\n ++result;\n }\n return result;\n }\n\n /**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\n function unicodeToArray(string) {\n return string.match(reUnicode) || [];\n }\n\n /**\n * Splits a Unicode `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\n function unicodeWords(string) {\n return string.match(reUnicodeWord) || [];\n }\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * Create a new pristine `lodash` function using the `context` object.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category Util\n * @param {Object} [context=root] The context object.\n * @returns {Function} Returns a new `lodash` function.\n * @example\n *\n * _.mixin({ 'foo': _.constant('foo') });\n *\n * var lodash = _.runInContext();\n * lodash.mixin({ 'bar': lodash.constant('bar') });\n *\n * _.isFunction(_.foo);\n * // => true\n * _.isFunction(_.bar);\n * // => false\n *\n * lodash.isFunction(lodash.foo);\n * // => false\n * lodash.isFunction(lodash.bar);\n * // => true\n *\n * // Create a suped-up `defer` in Node.js.\n * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;\n */\n var runInContext = (function runInContext(context) {\n context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));\n\n /** Built-in constructor references. */\n var Array = context.Array,\n Date = context.Date,\n Error = context.Error,\n Function = context.Function,\n Math = context.Math,\n Object = context.Object,\n RegExp = context.RegExp,\n String = context.String,\n TypeError = context.TypeError;\n\n /** Used for built-in method references. */\n var arrayProto = Array.prototype,\n funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n /** Used to detect overreaching core-js shims. */\n var coreJsData = context['__core-js_shared__'];\n\n /** Used to resolve the decompiled source of functions. */\n var funcToString = funcProto.toString;\n\n /** Used to check objects for own properties. */\n var hasOwnProperty = objectProto.hasOwnProperty;\n\n /** Used to generate unique IDs. */\n var idCounter = 0;\n\n /** Used to detect methods masquerading as native. */\n var maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n }());\n\n /**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\n var nativeObjectToString = objectProto.toString;\n\n /** Used to infer the `Object` constructor. */\n var objectCtorString = funcToString.call(Object);\n\n /** Used to restore the original `_` reference in `_.noConflict`. */\n var oldDash = root._;\n\n /** Used to detect if a method is native. */\n var reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n );\n\n /** Built-in value references. */\n var Buffer = moduleExports ? context.Buffer : undefined,\n Symbol = context.Symbol,\n Uint8Array = context.Uint8Array,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,\n getPrototype = overArg(Object.getPrototypeOf, Object),\n objectCreate = Object.create,\n propertyIsEnumerable = objectProto.propertyIsEnumerable,\n splice = arrayProto.splice,\n spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,\n symIterator = Symbol ? Symbol.iterator : undefined,\n symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n var defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n }());\n\n /** Mocked built-ins. */\n var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,\n ctxNow = Date && Date.now !== root.Date.now && Date.now,\n ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;\n\n /* Built-in method references for those with the same name as other `lodash` methods. */\n var nativeCeil = Math.ceil,\n nativeFloor = Math.floor,\n nativeGetSymbols = Object.getOwnPropertySymbols,\n nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,\n nativeIsFinite = context.isFinite,\n nativeJoin = arrayProto.join,\n nativeKeys = overArg(Object.keys, Object),\n nativeMax = Math.max,\n nativeMin = Math.min,\n nativeNow = Date.now,\n nativeParseInt = context.parseInt,\n nativeRandom = Math.random,\n nativeReverse = arrayProto.reverse;\n\n /* Built-in method references that are verified to be native. */\n var DataView = getNative(context, 'DataView'),\n Map = getNative(context, 'Map'),\n Promise = getNative(context, 'Promise'),\n Set = getNative(context, 'Set'),\n WeakMap = getNative(context, 'WeakMap'),\n nativeCreate = getNative(Object, 'create');\n\n /** Used to store function metadata. */\n var metaMap = WeakMap && new WeakMap;\n\n /** Used to lookup unminified function names. */\n var realNames = {};\n\n /** Used to detect maps, sets, and weakmaps. */\n var dataViewCtorString = toSource(DataView),\n mapCtorString = toSource(Map),\n promiseCtorString = toSource(Promise),\n setCtorString = toSource(Set),\n weakMapCtorString = toSource(WeakMap);\n\n /** Used to convert symbols to primitives and strings. */\n var symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,\n symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a `lodash` object which wraps `value` to enable implicit method\n * chain sequences. Methods that operate on and return arrays, collections,\n * and functions can be chained together. Methods that retrieve a single value\n * or may return a primitive value will automatically end the chain sequence\n * and return the unwrapped value. Otherwise, the value must be unwrapped\n * with `_#value`.\n *\n * Explicit chain sequences, which must be unwrapped with `_#value`, may be\n * enabled using `_.chain`.\n *\n * The execution of chained methods is lazy, that is, it's deferred until\n * `_#value` is implicitly or explicitly called.\n *\n * Lazy evaluation allows several methods to support shortcut fusion.\n * Shortcut fusion is an optimization to merge iteratee calls; this avoids\n * the creation of intermediate arrays and can greatly reduce the number of\n * iteratee executions. Sections of a chain sequence qualify for shortcut\n * fusion if the section is applied to an array and iteratees accept only\n * one argument. The heuristic for whether a section qualifies for shortcut\n * fusion is subject to change.\n *\n * Chaining is supported in custom builds as long as the `_#value` method is\n * directly or indirectly included in the build.\n *\n * In addition to lodash methods, wrappers have `Array` and `String` methods.\n *\n * The wrapper `Array` methods are:\n * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`\n *\n * The wrapper `String` methods are:\n * `replace` and `split`\n *\n * The wrapper methods that support shortcut fusion are:\n * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,\n * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,\n * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`\n *\n * The chainable wrapper methods are:\n * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,\n * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,\n * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,\n * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,\n * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,\n * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,\n * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,\n * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,\n * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,\n * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,\n * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,\n * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,\n * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,\n * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,\n * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,\n * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,\n * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,\n * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,\n * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,\n * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,\n * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,\n * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,\n * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,\n * `zipObject`, `zipObjectDeep`, and `zipWith`\n *\n * The wrapper methods that are **not** chainable by default are:\n * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,\n * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,\n * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,\n * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,\n * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,\n * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,\n * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,\n * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,\n * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,\n * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,\n * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,\n * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,\n * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,\n * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,\n * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,\n * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,\n * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,\n * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,\n * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,\n * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,\n * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,\n * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,\n * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,\n * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,\n * `upperFirst`, `value`, and `words`\n *\n * @name _\n * @constructor\n * @category Seq\n * @param {*} value The value to wrap in a `lodash` instance.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var wrapped = _([1, 2, 3]);\n *\n * // Returns an unwrapped value.\n * wrapped.reduce(_.add);\n * // => 6\n *\n * // Returns a wrapped value.\n * var squares = wrapped.map(square);\n *\n * _.isArray(squares);\n * // => false\n *\n * _.isArray(squares.value());\n * // => true\n */\n function lodash(value) {\n if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {\n if (value instanceof LodashWrapper) {\n return value;\n }\n if (hasOwnProperty.call(value, '__wrapped__')) {\n return wrapperClone(value);\n }\n }\n return new LodashWrapper(value);\n }\n\n /**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\n var baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n }());\n\n /**\n * The function whose prototype chain sequence wrappers inherit from.\n *\n * @private\n */\n function baseLodash() {\n // No operation performed.\n }\n\n /**\n * The base constructor for creating `lodash` wrapper objects.\n *\n * @private\n * @param {*} value The value to wrap.\n * @param {boolean} [chainAll] Enable explicit method chain sequences.\n */\n function LodashWrapper(value, chainAll) {\n this.__wrapped__ = value;\n this.__actions__ = [];\n this.__chain__ = !!chainAll;\n this.__index__ = 0;\n this.__values__ = undefined;\n }\n\n /**\n * By default, the template delimiters used by lodash are like those in\n * embedded Ruby (ERB) as well as ES2015 template strings. Change the\n * following template settings to use alternative delimiters.\n *\n * @static\n * @memberOf _\n * @type {Object}\n */\n lodash.templateSettings = {\n\n /**\n * Used to detect `data` property values to be HTML-escaped.\n *\n * @memberOf _.templateSettings\n * @type {RegExp}\n */\n 'escape': reEscape,\n\n /**\n * Used to detect code to be evaluated.\n *\n * @memberOf _.templateSettings\n * @type {RegExp}\n */\n 'evaluate': reEvaluate,\n\n /**\n * Used to detect `data` property values to inject.\n *\n * @memberOf _.templateSettings\n * @type {RegExp}\n */\n 'interpolate': reInterpolate,\n\n /**\n * Used to reference the data object in the template text.\n *\n * @memberOf _.templateSettings\n * @type {string}\n */\n 'variable': '',\n\n /**\n * Used to import variables into the compiled template.\n *\n * @memberOf _.templateSettings\n * @type {Object}\n */\n 'imports': {\n\n /**\n * A reference to the `lodash` function.\n *\n * @memberOf _.templateSettings.imports\n * @type {Function}\n */\n '_': lodash\n }\n };\n\n // Ensure wrappers are instances of `baseLodash`.\n lodash.prototype = baseLodash.prototype;\n lodash.prototype.constructor = lodash;\n\n LodashWrapper.prototype = baseCreate(baseLodash.prototype);\n LodashWrapper.prototype.constructor = LodashWrapper;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.\n *\n * @private\n * @constructor\n * @param {*} value The value to wrap.\n */\n function LazyWrapper(value) {\n this.__wrapped__ = value;\n this.__actions__ = [];\n this.__dir__ = 1;\n this.__filtered__ = false;\n this.__iteratees__ = [];\n this.__takeCount__ = MAX_ARRAY_LENGTH;\n this.__views__ = [];\n }\n\n /**\n * Creates a clone of the lazy wrapper object.\n *\n * @private\n * @name clone\n * @memberOf LazyWrapper\n * @returns {Object} Returns the cloned `LazyWrapper` object.\n */\n function lazyClone() {\n var result = new LazyWrapper(this.__wrapped__);\n result.__actions__ = copyArray(this.__actions__);\n result.__dir__ = this.__dir__;\n result.__filtered__ = this.__filtered__;\n result.__iteratees__ = copyArray(this.__iteratees__);\n result.__takeCount__ = this.__takeCount__;\n result.__views__ = copyArray(this.__views__);\n return result;\n }\n\n /**\n * Reverses the direction of lazy iteration.\n *\n * @private\n * @name reverse\n * @memberOf LazyWrapper\n * @returns {Object} Returns the new reversed `LazyWrapper` object.\n */\n function lazyReverse() {\n if (this.__filtered__) {\n var result = new LazyWrapper(this);\n result.__dir__ = -1;\n result.__filtered__ = true;\n } else {\n result = this.clone();\n result.__dir__ *= -1;\n }\n return result;\n }\n\n /**\n * Extracts the unwrapped value from its lazy wrapper.\n *\n * @private\n * @name value\n * @memberOf LazyWrapper\n * @returns {*} Returns the unwrapped value.\n */\n function lazyValue() {\n var array = this.__wrapped__.value(),\n dir = this.__dir__,\n isArr = isArray(array),\n isRight = dir < 0,\n arrLength = isArr ? array.length : 0,\n view = getView(0, arrLength, this.__views__),\n start = view.start,\n end = view.end,\n length = end - start,\n index = isRight ? end : (start - 1),\n iteratees = this.__iteratees__,\n iterLength = iteratees.length,\n resIndex = 0,\n takeCount = nativeMin(length, this.__takeCount__);\n\n if (!isArr || (!isRight && arrLength == length && takeCount == length)) {\n return baseWrapperValue(array, this.__actions__);\n }\n var result = [];\n\n outer:\n while (length-- && resIndex < takeCount) {\n index += dir;\n\n var iterIndex = -1,\n value = array[index];\n\n while (++iterIndex < iterLength) {\n var data = iteratees[iterIndex],\n iteratee = data.iteratee,\n type = data.type,\n computed = iteratee(value);\n\n if (type == LAZY_MAP_FLAG) {\n value = computed;\n } else if (!computed) {\n if (type == LAZY_FILTER_FLAG) {\n continue outer;\n } else {\n break outer;\n }\n }\n }\n result[resIndex++] = value;\n }\n return result;\n }\n\n // Ensure `LazyWrapper` is an instance of `baseLodash`.\n LazyWrapper.prototype = baseCreate(baseLodash.prototype);\n LazyWrapper.prototype.constructor = LazyWrapper;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n }\n\n /**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\n function hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n }\n\n /**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n }\n\n /**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n }\n\n /**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n }\n\n /**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\n function hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n }\n\n // Add methods to `Hash`.\n Hash.prototype.clear = hashClear;\n Hash.prototype['delete'] = hashDelete;\n Hash.prototype.get = hashGet;\n Hash.prototype.has = hashHas;\n Hash.prototype.set = hashSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n }\n\n /**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\n function listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n }\n\n /**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n }\n\n /**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n }\n\n /**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n }\n\n /**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\n function listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n }\n\n // Add methods to `ListCache`.\n ListCache.prototype.clear = listCacheClear;\n ListCache.prototype['delete'] = listCacheDelete;\n ListCache.prototype.get = listCacheGet;\n ListCache.prototype.has = listCacheHas;\n ListCache.prototype.set = listCacheSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n }\n\n /**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\n function mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n }\n\n /**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n }\n\n /**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function mapCacheGet(key) {\n return getMapData(this, key).get(key);\n }\n\n /**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function mapCacheHas(key) {\n return getMapData(this, key).has(key);\n }\n\n /**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\n function mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n }\n\n // Add methods to `MapCache`.\n MapCache.prototype.clear = mapCacheClear;\n MapCache.prototype['delete'] = mapCacheDelete;\n MapCache.prototype.get = mapCacheGet;\n MapCache.prototype.has = mapCacheHas;\n MapCache.prototype.set = mapCacheSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\n function SetCache(values) {\n var index = -1,\n length = values == null ? 0 : values.length;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n }\n\n /**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\n function setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n }\n\n /**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\n function setCacheHas(value) {\n return this.__data__.has(value);\n }\n\n // Add methods to `SetCache`.\n SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\n SetCache.prototype.has = setCacheHas;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n }\n\n /**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\n function stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n }\n\n /**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n }\n\n /**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function stackGet(key) {\n return this.__data__.get(key);\n }\n\n /**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function stackHas(key) {\n return this.__data__.has(key);\n }\n\n /**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\n function stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n }\n\n // Add methods to `Stack`.\n Stack.prototype.clear = stackClear;\n Stack.prototype['delete'] = stackDelete;\n Stack.prototype.get = stackGet;\n Stack.prototype.has = stackHas;\n Stack.prototype.set = stackSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\n function arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * A specialized version of `_.sample` for arrays.\n *\n * @private\n * @param {Array} array The array to sample.\n * @returns {*} Returns the random element.\n */\n function arraySample(array) {\n var length = array.length;\n return length ? array[baseRandom(0, length - 1)] : undefined;\n }\n\n /**\n * A specialized version of `_.sampleSize` for arrays.\n *\n * @private\n * @param {Array} array The array to sample.\n * @param {number} n The number of elements to sample.\n * @returns {Array} Returns the random elements.\n */\n function arraySampleSize(array, n) {\n return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));\n }\n\n /**\n * A specialized version of `_.shuffle` for arrays.\n *\n * @private\n * @param {Array} array The array to shuffle.\n * @returns {Array} Returns the new shuffled array.\n */\n function arrayShuffle(array) {\n return shuffleSelf(copyArray(array));\n }\n\n /**\n * This function is like `assignValue` except that it doesn't assign\n * `undefined` values.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\n function assignMergeValue(object, key, value) {\n if ((value !== undefined && !eq(object[key], value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n }\n\n /**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\n function assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n }\n\n /**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n }\n\n /**\n * Aggregates elements of `collection` on `accumulator` with keys transformed\n * by `iteratee` and values set by `setter`.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} setter The function to set `accumulator` values.\n * @param {Function} iteratee The iteratee to transform keys.\n * @param {Object} accumulator The initial aggregated object.\n * @returns {Function} Returns `accumulator`.\n */\n function baseAggregator(collection, setter, iteratee, accumulator) {\n baseEach(collection, function(value, key, collection) {\n setter(accumulator, value, iteratee(value), collection);\n });\n return accumulator;\n }\n\n /**\n * The base implementation of `_.assign` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\n function baseAssign(object, source) {\n return object && copyObject(source, keys(source), object);\n }\n\n /**\n * The base implementation of `_.assignIn` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\n function baseAssignIn(object, source) {\n return object && copyObject(source, keysIn(source), object);\n }\n\n /**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\n function baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n }\n\n /**\n * The base implementation of `_.at` without support for individual paths.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {string[]} paths The property paths to pick.\n * @returns {Array} Returns the picked elements.\n */\n function baseAt(object, paths) {\n var index = -1,\n length = paths.length,\n result = Array(length),\n skip = object == null;\n\n while (++index < length) {\n result[index] = skip ? undefined : get(object, paths[index]);\n }\n return result;\n }\n\n /**\n * The base implementation of `_.clamp` which doesn't coerce arguments.\n *\n * @private\n * @param {number} number The number to clamp.\n * @param {number} [lower] The lower bound.\n * @param {number} upper The upper bound.\n * @returns {number} Returns the clamped number.\n */\n function baseClamp(number, lower, upper) {\n if (number === number) {\n if (upper !== undefined) {\n number = number <= upper ? number : upper;\n }\n if (lower !== undefined) {\n number = number >= lower ? number : lower;\n }\n }\n return number;\n }\n\n /**\n * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n * traversed objects.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Deep clone\n * 2 - Flatten inherited properties\n * 4 - Clone symbols\n * @param {Function} [customizer] The function to customize cloning.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The parent object of `value`.\n * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n * @returns {*} Returns the cloned value.\n */\n function baseClone(value, bitmask, customizer, key, object, stack) {\n var result,\n isDeep = bitmask & CLONE_DEEP_FLAG,\n isFlat = bitmask & CLONE_FLAT_FLAG,\n isFull = bitmask & CLONE_SYMBOLS_FLAG;\n\n if (customizer) {\n result = object ? customizer(value, key, object, stack) : customizer(value);\n }\n if (result !== undefined) {\n return result;\n }\n if (!isObject(value)) {\n return value;\n }\n var isArr = isArray(value);\n if (isArr) {\n result = initCloneArray(value);\n if (!isDeep) {\n return copyArray(value, result);\n }\n } else {\n var tag = getTag(value),\n isFunc = tag == funcTag || tag == genTag;\n\n if (isBuffer(value)) {\n return cloneBuffer(value, isDeep);\n }\n if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n result = (isFlat || isFunc) ? {} : initCloneObject(value);\n if (!isDeep) {\n return isFlat\n ? copySymbolsIn(value, baseAssignIn(result, value))\n : copySymbols(value, baseAssign(result, value));\n }\n } else {\n if (!cloneableTags[tag]) {\n return object ? value : {};\n }\n result = initCloneByTag(value, tag, isDeep);\n }\n }\n // Check for circular references and return its corresponding clone.\n stack || (stack = new Stack);\n var stacked = stack.get(value);\n if (stacked) {\n return stacked;\n }\n stack.set(value, result);\n\n if (isSet(value)) {\n value.forEach(function(subValue) {\n result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));\n });\n } else if (isMap(value)) {\n value.forEach(function(subValue, key) {\n result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));\n });\n }\n\n var keysFunc = isFull\n ? (isFlat ? getAllKeysIn : getAllKeys)\n : (isFlat ? keysIn : keys);\n\n var props = isArr ? undefined : keysFunc(value);\n arrayEach(props || value, function(subValue, key) {\n if (props) {\n key = subValue;\n subValue = value[key];\n }\n // Recursively populate clone (susceptible to call stack limits).\n assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));\n });\n return result;\n }\n\n /**\n * The base implementation of `_.conforms` which doesn't clone `source`.\n *\n * @private\n * @param {Object} source The object of property predicates to conform to.\n * @returns {Function} Returns the new spec function.\n */\n function baseConforms(source) {\n var props = keys(source);\n return function(object) {\n return baseConformsTo(object, source, props);\n };\n }\n\n /**\n * The base implementation of `_.conformsTo` which accepts `props` to check.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property predicates to conform to.\n * @returns {boolean} Returns `true` if `object` conforms, else `false`.\n */\n function baseConformsTo(object, source, props) {\n var length = props.length;\n if (object == null) {\n return !length;\n }\n object = Object(object);\n while (length--) {\n var key = props[length],\n predicate = source[key],\n value = object[key];\n\n if ((value === undefined && !(key in object)) || !predicate(value)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * The base implementation of `_.delay` and `_.defer` which accepts `args`\n * to provide to `func`.\n *\n * @private\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {Array} args The arguments to provide to `func`.\n * @returns {number|Object} Returns the timer id or timeout object.\n */\n function baseDelay(func, wait, args) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return setTimeout(function() { func.apply(undefined, args); }, wait);\n }\n\n /**\n * The base implementation of methods like `_.difference` without support\n * for excluding multiple arrays or iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Array} values The values to exclude.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n */\n function baseDifference(array, values, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n isCommon = true,\n length = array.length,\n result = [],\n valuesLength = values.length;\n\n if (!length) {\n return result;\n }\n if (iteratee) {\n values = arrayMap(values, baseUnary(iteratee));\n }\n if (comparator) {\n includes = arrayIncludesWith;\n isCommon = false;\n }\n else if (values.length >= LARGE_ARRAY_SIZE) {\n includes = cacheHas;\n isCommon = false;\n values = new SetCache(values);\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee == null ? value : iteratee(value);\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var valuesIndex = valuesLength;\n while (valuesIndex--) {\n if (values[valuesIndex] === computed) {\n continue outer;\n }\n }\n result.push(value);\n }\n else if (!includes(values, computed, comparator)) {\n result.push(value);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.forEach` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n */\n var baseEach = createBaseEach(baseForOwn);\n\n /**\n * The base implementation of `_.forEachRight` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n */\n var baseEachRight = createBaseEach(baseForOwnRight, true);\n\n /**\n * The base implementation of `_.every` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if all elements pass the predicate check,\n * else `false`\n */\n function baseEvery(collection, predicate) {\n var result = true;\n baseEach(collection, function(value, index, collection) {\n result = !!predicate(value, index, collection);\n return result;\n });\n return result;\n }\n\n /**\n * The base implementation of methods like `_.max` and `_.min` which accepts a\n * `comparator` to determine the extremum value.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The iteratee invoked per iteration.\n * @param {Function} comparator The comparator used to compare values.\n * @returns {*} Returns the extremum value.\n */\n function baseExtremum(array, iteratee, comparator) {\n var index = -1,\n length = array.length;\n\n while (++index < length) {\n var value = array[index],\n current = iteratee(value);\n\n if (current != null && (computed === undefined\n ? (current === current && !isSymbol(current))\n : comparator(current, computed)\n )) {\n var computed = current,\n result = value;\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.fill` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to fill.\n * @param {*} value The value to fill `array` with.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns `array`.\n */\n function baseFill(array, value, start, end) {\n var length = array.length;\n\n start = toInteger(start);\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = (end === undefined || end > length) ? length : toInteger(end);\n if (end < 0) {\n end += length;\n }\n end = start > end ? 0 : toLength(end);\n while (start < end) {\n array[start++] = value;\n }\n return array;\n }\n\n /**\n * The base implementation of `_.filter` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\n function baseFilter(collection, predicate) {\n var result = [];\n baseEach(collection, function(value, index, collection) {\n if (predicate(value, index, collection)) {\n result.push(value);\n }\n });\n return result;\n }\n\n /**\n * The base implementation of `_.flatten` with support for restricting flattening.\n *\n * @private\n * @param {Array} array The array to flatten.\n * @param {number} depth The maximum recursion depth.\n * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n * @param {Array} [result=[]] The initial result value.\n * @returns {Array} Returns the new flattened array.\n */\n function baseFlatten(array, depth, predicate, isStrict, result) {\n var index = -1,\n length = array.length;\n\n predicate || (predicate = isFlattenable);\n result || (result = []);\n\n while (++index < length) {\n var value = array[index];\n if (depth > 0 && predicate(value)) {\n if (depth > 1) {\n // Recursively flatten arrays (susceptible to call stack limits).\n baseFlatten(value, depth - 1, predicate, isStrict, result);\n } else {\n arrayPush(result, value);\n }\n } else if (!isStrict) {\n result[result.length] = value;\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `baseForOwn` which iterates over `object`\n * properties returned by `keysFunc` and invokes `iteratee` for each property.\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\n var baseFor = createBaseFor();\n\n /**\n * This function is like `baseFor` except that it iterates over properties\n * in the opposite order.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\n var baseForRight = createBaseFor(true);\n\n /**\n * The base implementation of `_.forOwn` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\n function baseForOwn(object, iteratee) {\n return object && baseFor(object, iteratee, keys);\n }\n\n /**\n * The base implementation of `_.forOwnRight` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\n function baseForOwnRight(object, iteratee) {\n return object && baseForRight(object, iteratee, keys);\n }\n\n /**\n * The base implementation of `_.functions` which creates an array of\n * `object` function property names filtered from `props`.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Array} props The property names to filter.\n * @returns {Array} Returns the function names.\n */\n function baseFunctions(object, props) {\n return arrayFilter(props, function(key) {\n return isFunction(object[key]);\n });\n }\n\n /**\n * The base implementation of `_.get` without support for default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @returns {*} Returns the resolved value.\n */\n function baseGet(object, path) {\n path = castPath(path, object);\n\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[toKey(path[index++])];\n }\n return (index && index == length) ? object : undefined;\n }\n\n /**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\n function baseGetAllKeys(object, keysFunc, symbolsFunc) {\n var result = keysFunc(object);\n return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n }\n\n /**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\n function baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n }\n\n /**\n * The base implementation of `_.gt` which doesn't coerce arguments.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than `other`,\n * else `false`.\n */\n function baseGt(value, other) {\n return value > other;\n }\n\n /**\n * The base implementation of `_.has` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\n function baseHas(object, key) {\n return object != null && hasOwnProperty.call(object, key);\n }\n\n /**\n * The base implementation of `_.hasIn` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\n function baseHasIn(object, key) {\n return object != null && key in Object(object);\n }\n\n /**\n * The base implementation of `_.inRange` which doesn't coerce arguments.\n *\n * @private\n * @param {number} number The number to check.\n * @param {number} start The start of the range.\n * @param {number} end The end of the range.\n * @returns {boolean} Returns `true` if `number` is in the range, else `false`.\n */\n function baseInRange(number, start, end) {\n return number >= nativeMin(start, end) && number < nativeMax(start, end);\n }\n\n /**\n * The base implementation of methods like `_.intersection`, without support\n * for iteratee shorthands, that accepts an array of arrays to inspect.\n *\n * @private\n * @param {Array} arrays The arrays to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of shared values.\n */\n function baseIntersection(arrays, iteratee, comparator) {\n var includes = comparator ? arrayIncludesWith : arrayIncludes,\n length = arrays[0].length,\n othLength = arrays.length,\n othIndex = othLength,\n caches = Array(othLength),\n maxLength = Infinity,\n result = [];\n\n while (othIndex--) {\n var array = arrays[othIndex];\n if (othIndex && iteratee) {\n array = arrayMap(array, baseUnary(iteratee));\n }\n maxLength = nativeMin(array.length, maxLength);\n caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))\n ? new SetCache(othIndex && array)\n : undefined;\n }\n array = arrays[0];\n\n var index = -1,\n seen = caches[0];\n\n outer:\n while (++index < length && result.length < maxLength) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (!(seen\n ? cacheHas(seen, computed)\n : includes(result, computed, comparator)\n )) {\n othIndex = othLength;\n while (--othIndex) {\n var cache = caches[othIndex];\n if (!(cache\n ? cacheHas(cache, computed)\n : includes(arrays[othIndex], computed, comparator))\n ) {\n continue outer;\n }\n }\n if (seen) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.invert` and `_.invertBy` which inverts\n * `object` with values transformed by `iteratee` and set by `setter`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} setter The function to set `accumulator` values.\n * @param {Function} iteratee The iteratee to transform values.\n * @param {Object} accumulator The initial inverted object.\n * @returns {Function} Returns `accumulator`.\n */\n function baseInverter(object, setter, iteratee, accumulator) {\n baseForOwn(object, function(value, key, object) {\n setter(accumulator, iteratee(value), key, object);\n });\n return accumulator;\n }\n\n /**\n * The base implementation of `_.invoke` without support for individual\n * method arguments.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the method to invoke.\n * @param {Array} args The arguments to invoke the method with.\n * @returns {*} Returns the result of the invoked method.\n */\n function baseInvoke(object, path, args) {\n path = castPath(path, object);\n object = parent(object, path);\n var func = object == null ? object : object[toKey(last(path))];\n return func == null ? undefined : apply(func, object, args);\n }\n\n /**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\n function baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n }\n\n /**\n * The base implementation of `_.isArrayBuffer` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.\n */\n function baseIsArrayBuffer(value) {\n return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;\n }\n\n /**\n * The base implementation of `_.isDate` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a date object, else `false`.\n */\n function baseIsDate(value) {\n return isObjectLike(value) && baseGetTag(value) == dateTag;\n }\n\n /**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Unordered comparison\n * 2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\n function baseIsEqual(value, other, bitmask, customizer, stack) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n }\n\n /**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\n function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = objIsArr ? arrayTag : getTag(object),\n othTag = othIsArr ? arrayTag : getTag(other);\n\n objTag = objTag == argsTag ? objectTag : objTag;\n othTag = othTag == argsTag ? objectTag : othTag;\n\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && isBuffer(object)) {\n if (!isBuffer(other)) {\n return false;\n }\n objIsArr = true;\n objIsObj = false;\n }\n if (isSameTag && !objIsObj) {\n stack || (stack = new Stack);\n return (objIsArr || isTypedArray(object))\n ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n }\n if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n var objUnwrapped = objIsWrapped ? object.value() : object,\n othUnwrapped = othIsWrapped ? other.value() : other;\n\n stack || (stack = new Stack);\n return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n }\n }\n if (!isSameTag) {\n return false;\n }\n stack || (stack = new Stack);\n return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n }\n\n /**\n * The base implementation of `_.isMap` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n */\n function baseIsMap(value) {\n return isObjectLike(value) && getTag(value) == mapTag;\n }\n\n /**\n * The base implementation of `_.isMatch` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @param {Array} matchData The property names, values, and compare flags to match.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n */\n function baseIsMatch(object, source, matchData, customizer) {\n var index = matchData.length,\n length = index,\n noCustomizer = !customizer;\n\n if (object == null) {\n return !length;\n }\n object = Object(object);\n while (index--) {\n var data = matchData[index];\n if ((noCustomizer && data[2])\n ? data[1] !== object[data[0]]\n : !(data[0] in object)\n ) {\n return false;\n }\n }\n while (++index < length) {\n data = matchData[index];\n var key = data[0],\n objValue = object[key],\n srcValue = data[1];\n\n if (noCustomizer && data[2]) {\n if (objValue === undefined && !(key in object)) {\n return false;\n }\n } else {\n var stack = new Stack;\n if (customizer) {\n var result = customizer(objValue, srcValue, key, object, source, stack);\n }\n if (!(result === undefined\n ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)\n : result\n )) {\n return false;\n }\n }\n }\n return true;\n }\n\n /**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\n function baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n }\n\n /**\n * The base implementation of `_.isRegExp` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.\n */\n function baseIsRegExp(value) {\n return isObjectLike(value) && baseGetTag(value) == regexpTag;\n }\n\n /**\n * The base implementation of `_.isSet` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n */\n function baseIsSet(value) {\n return isObjectLike(value) && getTag(value) == setTag;\n }\n\n /**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\n function baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n }\n\n /**\n * The base implementation of `_.iteratee`.\n *\n * @private\n * @param {*} [value=_.identity] The value to convert to an iteratee.\n * @returns {Function} Returns the iteratee.\n */\n function baseIteratee(value) {\n // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.\n // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.\n if (typeof value == 'function') {\n return value;\n }\n if (value == null) {\n return identity;\n }\n if (typeof value == 'object') {\n return isArray(value)\n ? baseMatchesProperty(value[0], value[1])\n : baseMatches(value);\n }\n return property(value);\n }\n\n /**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\n function baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\n function baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.lt` which doesn't coerce arguments.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than `other`,\n * else `false`.\n */\n function baseLt(value, other) {\n return value < other;\n }\n\n /**\n * The base implementation of `_.map` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\n function baseMap(collection, iteratee) {\n var index = -1,\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value, key, collection) {\n result[++index] = iteratee(value, key, collection);\n });\n return result;\n }\n\n /**\n * The base implementation of `_.matches` which doesn't clone `source`.\n *\n * @private\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new spec function.\n */\n function baseMatches(source) {\n var matchData = getMatchData(source);\n if (matchData.length == 1 && matchData[0][2]) {\n return matchesStrictComparable(matchData[0][0], matchData[0][1]);\n }\n return function(object) {\n return object === source || baseIsMatch(object, source, matchData);\n };\n }\n\n /**\n * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.\n *\n * @private\n * @param {string} path The path of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\n function baseMatchesProperty(path, srcValue) {\n if (isKey(path) && isStrictComparable(srcValue)) {\n return matchesStrictComparable(toKey(path), srcValue);\n }\n return function(object) {\n var objValue = get(object, path);\n return (objValue === undefined && objValue === srcValue)\n ? hasIn(object, path)\n : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);\n };\n }\n\n /**\n * The base implementation of `_.merge` without support for multiple sources.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} [customizer] The function to customize merged values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\n function baseMerge(object, source, srcIndex, customizer, stack) {\n if (object === source) {\n return;\n }\n baseFor(source, function(srcValue, key) {\n stack || (stack = new Stack);\n if (isObject(srcValue)) {\n baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n }\n else {\n var newValue = customizer\n ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)\n : undefined;\n\n if (newValue === undefined) {\n newValue = srcValue;\n }\n assignMergeValue(object, key, newValue);\n }\n }, keysIn);\n }\n\n /**\n * A specialized version of `baseMerge` for arrays and objects which performs\n * deep merges and tracks traversed objects enabling objects with circular\n * references to be merged.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {string} key The key of the value to merge.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} mergeFunc The function to merge values.\n * @param {Function} [customizer] The function to customize assigned values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\n function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n var objValue = safeGet(object, key),\n srcValue = safeGet(source, key),\n stacked = stack.get(srcValue);\n\n if (stacked) {\n assignMergeValue(object, key, stacked);\n return;\n }\n var newValue = customizer\n ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n : undefined;\n\n var isCommon = newValue === undefined;\n\n if (isCommon) {\n var isArr = isArray(srcValue),\n isBuff = !isArr && isBuffer(srcValue),\n isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n newValue = srcValue;\n if (isArr || isBuff || isTyped) {\n if (isArray(objValue)) {\n newValue = objValue;\n }\n else if (isArrayLikeObject(objValue)) {\n newValue = copyArray(objValue);\n }\n else if (isBuff) {\n isCommon = false;\n newValue = cloneBuffer(srcValue, true);\n }\n else if (isTyped) {\n isCommon = false;\n newValue = cloneTypedArray(srcValue, true);\n }\n else {\n newValue = [];\n }\n }\n else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n newValue = objValue;\n if (isArguments(objValue)) {\n newValue = toPlainObject(objValue);\n }\n else if (!isObject(objValue) || isFunction(objValue)) {\n newValue = initCloneObject(srcValue);\n }\n }\n else {\n isCommon = false;\n }\n }\n if (isCommon) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, newValue);\n mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n stack['delete'](srcValue);\n }\n assignMergeValue(object, key, newValue);\n }\n\n /**\n * The base implementation of `_.nth` which doesn't coerce arguments.\n *\n * @private\n * @param {Array} array The array to query.\n * @param {number} n The index of the element to return.\n * @returns {*} Returns the nth element of `array`.\n */\n function baseNth(array, n) {\n var length = array.length;\n if (!length) {\n return;\n }\n n += n < 0 ? length : 0;\n return isIndex(n, length) ? array[n] : undefined;\n }\n\n /**\n * The base implementation of `_.orderBy` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n * @param {string[]} orders The sort orders of `iteratees`.\n * @returns {Array} Returns the new sorted array.\n */\n function baseOrderBy(collection, iteratees, orders) {\n if (iteratees.length) {\n iteratees = arrayMap(iteratees, function(iteratee) {\n if (isArray(iteratee)) {\n return function(value) {\n return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);\n }\n }\n return iteratee;\n });\n } else {\n iteratees = [identity];\n }\n\n var index = -1;\n iteratees = arrayMap(iteratees, baseUnary(getIteratee()));\n\n var result = baseMap(collection, function(value, key, collection) {\n var criteria = arrayMap(iteratees, function(iteratee) {\n return iteratee(value);\n });\n return { 'criteria': criteria, 'index': ++index, 'value': value };\n });\n\n return baseSortBy(result, function(object, other) {\n return compareMultiple(object, other, orders);\n });\n }\n\n /**\n * The base implementation of `_.pick` without support for individual\n * property identifiers.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @returns {Object} Returns the new object.\n */\n function basePick(object, paths) {\n return basePickBy(object, paths, function(value, path) {\n return hasIn(object, path);\n });\n }\n\n /**\n * The base implementation of `_.pickBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @param {Function} predicate The function invoked per property.\n * @returns {Object} Returns the new object.\n */\n function basePickBy(object, paths, predicate) {\n var index = -1,\n length = paths.length,\n result = {};\n\n while (++index < length) {\n var path = paths[index],\n value = baseGet(object, path);\n\n if (predicate(value, path)) {\n baseSet(result, castPath(path, object), value);\n }\n }\n return result;\n }\n\n /**\n * A specialized version of `baseProperty` which supports deep paths.\n *\n * @private\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\n function basePropertyDeep(path) {\n return function(object) {\n return baseGet(object, path);\n };\n }\n\n /**\n * The base implementation of `_.pullAllBy` without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns `array`.\n */\n function basePullAll(array, values, iteratee, comparator) {\n var indexOf = comparator ? baseIndexOfWith : baseIndexOf,\n index = -1,\n length = values.length,\n seen = array;\n\n if (array === values) {\n values = copyArray(values);\n }\n if (iteratee) {\n seen = arrayMap(array, baseUnary(iteratee));\n }\n while (++index < length) {\n var fromIndex = 0,\n value = values[index],\n computed = iteratee ? iteratee(value) : value;\n\n while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {\n if (seen !== array) {\n splice.call(seen, fromIndex, 1);\n }\n splice.call(array, fromIndex, 1);\n }\n }\n return array;\n }\n\n /**\n * The base implementation of `_.pullAt` without support for individual\n * indexes or capturing the removed elements.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {number[]} indexes The indexes of elements to remove.\n * @returns {Array} Returns `array`.\n */\n function basePullAt(array, indexes) {\n var length = array ? indexes.length : 0,\n lastIndex = length - 1;\n\n while (length--) {\n var index = indexes[length];\n if (length == lastIndex || index !== previous) {\n var previous = index;\n if (isIndex(index)) {\n splice.call(array, index, 1);\n } else {\n baseUnset(array, index);\n }\n }\n }\n return array;\n }\n\n /**\n * The base implementation of `_.random` without support for returning\n * floating-point numbers.\n *\n * @private\n * @param {number} lower The lower bound.\n * @param {number} upper The upper bound.\n * @returns {number} Returns the random number.\n */\n function baseRandom(lower, upper) {\n return lower + nativeFloor(nativeRandom() * (upper - lower + 1));\n }\n\n /**\n * The base implementation of `_.range` and `_.rangeRight` which doesn't\n * coerce arguments.\n *\n * @private\n * @param {number} start The start of the range.\n * @param {number} end The end of the range.\n * @param {number} step The value to increment or decrement by.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Array} Returns the range of numbers.\n */\n function baseRange(start, end, step, fromRight) {\n var index = -1,\n length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),\n result = Array(length);\n\n while (length--) {\n result[fromRight ? length : ++index] = start;\n start += step;\n }\n return result;\n }\n\n /**\n * The base implementation of `_.repeat` which doesn't coerce arguments.\n *\n * @private\n * @param {string} string The string to repeat.\n * @param {number} n The number of times to repeat the string.\n * @returns {string} Returns the repeated string.\n */\n function baseRepeat(string, n) {\n var result = '';\n if (!string || n < 1 || n > MAX_SAFE_INTEGER) {\n return result;\n }\n // Leverage the exponentiation by squaring algorithm for a faster repeat.\n // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.\n do {\n if (n % 2) {\n result += string;\n }\n n = nativeFloor(n / 2);\n if (n) {\n string += string;\n }\n } while (n);\n\n return result;\n }\n\n /**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\n function baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n }\n\n /**\n * The base implementation of `_.sample`.\n *\n * @private\n * @param {Array|Object} collection The collection to sample.\n * @returns {*} Returns the random element.\n */\n function baseSample(collection) {\n return arraySample(values(collection));\n }\n\n /**\n * The base implementation of `_.sampleSize` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to sample.\n * @param {number} n The number of elements to sample.\n * @returns {Array} Returns the random elements.\n */\n function baseSampleSize(collection, n) {\n var array = values(collection);\n return shuffleSelf(array, baseClamp(n, 0, array.length));\n }\n\n /**\n * The base implementation of `_.set`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @param {Function} [customizer] The function to customize path creation.\n * @returns {Object} Returns `object`.\n */\n function baseSet(object, path, value, customizer) {\n if (!isObject(object)) {\n return object;\n }\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n lastIndex = length - 1,\n nested = object;\n\n while (nested != null && ++index < length) {\n var key = toKey(path[index]),\n newValue = value;\n\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n return object;\n }\n\n if (index != lastIndex) {\n var objValue = nested[key];\n newValue = customizer ? customizer(objValue, key, nested) : undefined;\n if (newValue === undefined) {\n newValue = isObject(objValue)\n ? objValue\n : (isIndex(path[index + 1]) ? [] : {});\n }\n }\n assignValue(nested, key, newValue);\n nested = nested[key];\n }\n return object;\n }\n\n /**\n * The base implementation of `setData` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to associate metadata with.\n * @param {*} data The metadata.\n * @returns {Function} Returns `func`.\n */\n var baseSetData = !metaMap ? identity : function(func, data) {\n metaMap.set(func, data);\n return func;\n };\n\n /**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\n var baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n };\n\n /**\n * The base implementation of `_.shuffle`.\n *\n * @private\n * @param {Array|Object} collection The collection to shuffle.\n * @returns {Array} Returns the new shuffled array.\n */\n function baseShuffle(collection) {\n return shuffleSelf(values(collection));\n }\n\n /**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\n function baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n }\n\n /**\n * The base implementation of `_.some` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\n function baseSome(collection, predicate) {\n var result;\n\n baseEach(collection, function(value, index, collection) {\n result = predicate(value, index, collection);\n return !result;\n });\n return !!result;\n }\n\n /**\n * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which\n * performs a binary search of `array` to determine the index at which `value`\n * should be inserted into `array` in order to maintain its sort order.\n *\n * @private\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {boolean} [retHighest] Specify returning the highest qualified index.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n */\n function baseSortedIndex(array, value, retHighest) {\n var low = 0,\n high = array == null ? low : array.length;\n\n if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {\n while (low < high) {\n var mid = (low + high) >>> 1,\n computed = array[mid];\n\n if (computed !== null && !isSymbol(computed) &&\n (retHighest ? (computed <= value) : (computed < value))) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return high;\n }\n return baseSortedIndexBy(array, value, identity, retHighest);\n }\n\n /**\n * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`\n * which invokes `iteratee` for `value` and each element of `array` to compute\n * their sort ranking. The iteratee is invoked with one argument; (value).\n *\n * @private\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {Function} iteratee The iteratee invoked per element.\n * @param {boolean} [retHighest] Specify returning the highest qualified index.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n */\n function baseSortedIndexBy(array, value, iteratee, retHighest) {\n var low = 0,\n high = array == null ? 0 : array.length;\n if (high === 0) {\n return 0;\n }\n\n value = iteratee(value);\n var valIsNaN = value !== value,\n valIsNull = value === null,\n valIsSymbol = isSymbol(value),\n valIsUndefined = value === undefined;\n\n while (low < high) {\n var mid = nativeFloor((low + high) / 2),\n computed = iteratee(array[mid]),\n othIsDefined = computed !== undefined,\n othIsNull = computed === null,\n othIsReflexive = computed === computed,\n othIsSymbol = isSymbol(computed);\n\n if (valIsNaN) {\n var setLow = retHighest || othIsReflexive;\n } else if (valIsUndefined) {\n setLow = othIsReflexive && (retHighest || othIsDefined);\n } else if (valIsNull) {\n setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);\n } else if (valIsSymbol) {\n setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);\n } else if (othIsNull || othIsSymbol) {\n setLow = false;\n } else {\n setLow = retHighest ? (computed <= value) : (computed < value);\n }\n if (setLow) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return nativeMin(high, MAX_ARRAY_INDEX);\n }\n\n /**\n * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\n function baseSortedUniq(array, iteratee) {\n var index = -1,\n length = array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n if (!index || !eq(computed, seen)) {\n var seen = computed;\n result[resIndex++] = value === 0 ? 0 : value;\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.toNumber` which doesn't ensure correct\n * conversions of binary, hexadecimal, or octal string values.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n */\n function baseToNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n return +value;\n }\n\n /**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\n function baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value;\n }\n if (isArray(value)) {\n // Recursively convert values (susceptible to call stack limits).\n return arrayMap(value, baseToString) + '';\n }\n if (isSymbol(value)) {\n return symbolToString ? symbolToString.call(value) : '';\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n }\n\n /**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\n function baseUniq(array, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n length = array.length,\n isCommon = true,\n result = [],\n seen = result;\n\n if (comparator) {\n isCommon = false;\n includes = arrayIncludesWith;\n }\n else if (length >= LARGE_ARRAY_SIZE) {\n var set = iteratee ? null : createSet(array);\n if (set) {\n return setToArray(set);\n }\n isCommon = false;\n includes = cacheHas;\n seen = new SetCache;\n }\n else {\n seen = iteratee ? [] : result;\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var seenIndex = seen.length;\n while (seenIndex--) {\n if (seen[seenIndex] === computed) {\n continue outer;\n }\n }\n if (iteratee) {\n seen.push(computed);\n }\n result.push(value);\n }\n else if (!includes(seen, computed, comparator)) {\n if (seen !== result) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.unset`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The property path to unset.\n * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n */\n function baseUnset(object, path) {\n path = castPath(path, object);\n object = parent(object, path);\n return object == null || delete object[toKey(last(path))];\n }\n\n /**\n * The base implementation of `_.update`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to update.\n * @param {Function} updater The function to produce the updated value.\n * @param {Function} [customizer] The function to customize path creation.\n * @returns {Object} Returns `object`.\n */\n function baseUpdate(object, path, updater, customizer) {\n return baseSet(object, path, updater(baseGet(object, path)), customizer);\n }\n\n /**\n * The base implementation of methods like `_.dropWhile` and `_.takeWhile`\n * without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to query.\n * @param {Function} predicate The function invoked per iteration.\n * @param {boolean} [isDrop] Specify dropping elements instead of taking them.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Array} Returns the slice of `array`.\n */\n function baseWhile(array, predicate, isDrop, fromRight) {\n var length = array.length,\n index = fromRight ? length : -1;\n\n while ((fromRight ? index-- : ++index < length) &&\n predicate(array[index], index, array)) {}\n\n return isDrop\n ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))\n : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));\n }\n\n /**\n * The base implementation of `wrapperValue` which returns the result of\n * performing a sequence of actions on the unwrapped `value`, where each\n * successive action is supplied the return value of the previous.\n *\n * @private\n * @param {*} value The unwrapped value.\n * @param {Array} actions Actions to perform to resolve the unwrapped value.\n * @returns {*} Returns the resolved value.\n */\n function baseWrapperValue(value, actions) {\n var result = value;\n if (result instanceof LazyWrapper) {\n result = result.value();\n }\n return arrayReduce(actions, function(result, action) {\n return action.func.apply(action.thisArg, arrayPush([result], action.args));\n }, result);\n }\n\n /**\n * The base implementation of methods like `_.xor`, without support for\n * iteratee shorthands, that accepts an array of arrays to inspect.\n *\n * @private\n * @param {Array} arrays The arrays to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of values.\n */\n function baseXor(arrays, iteratee, comparator) {\n var length = arrays.length;\n if (length < 2) {\n return length ? baseUniq(arrays[0]) : [];\n }\n var index = -1,\n result = Array(length);\n\n while (++index < length) {\n var array = arrays[index],\n othIndex = -1;\n\n while (++othIndex < length) {\n if (othIndex != index) {\n result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);\n }\n }\n }\n return baseUniq(baseFlatten(result, 1), iteratee, comparator);\n }\n\n /**\n * This base implementation of `_.zipObject` which assigns values using `assignFunc`.\n *\n * @private\n * @param {Array} props The property identifiers.\n * @param {Array} values The property values.\n * @param {Function} assignFunc The function to assign values.\n * @returns {Object} Returns the new object.\n */\n function baseZipObject(props, values, assignFunc) {\n var index = -1,\n length = props.length,\n valsLength = values.length,\n result = {};\n\n while (++index < length) {\n var value = index < valsLength ? values[index] : undefined;\n assignFunc(result, props[index], value);\n }\n return result;\n }\n\n /**\n * Casts `value` to an empty array if it's not an array like object.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Array|Object} Returns the cast array-like object.\n */\n function castArrayLikeObject(value) {\n return isArrayLikeObject(value) ? value : [];\n }\n\n /**\n * Casts `value` to `identity` if it's not a function.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Function} Returns cast function.\n */\n function castFunction(value) {\n return typeof value == 'function' ? value : identity;\n }\n\n /**\n * Casts `value` to a path array if it's not one.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {Object} [object] The object to query keys on.\n * @returns {Array} Returns the cast property path array.\n */\n function castPath(value, object) {\n if (isArray(value)) {\n return value;\n }\n return isKey(value, object) ? [value] : stringToPath(toString(value));\n }\n\n /**\n * A `baseRest` alias which can be replaced with `identity` by module\n * replacement plugins.\n *\n * @private\n * @type {Function}\n * @param {Function} func The function to apply a rest parameter to.\n * @returns {Function} Returns the new function.\n */\n var castRest = baseRest;\n\n /**\n * Casts `array` to a slice if it's needed.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {number} start The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the cast slice.\n */\n function castSlice(array, start, end) {\n var length = array.length;\n end = end === undefined ? length : end;\n return (!start && end >= length) ? array : baseSlice(array, start, end);\n }\n\n /**\n * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).\n *\n * @private\n * @param {number|Object} id The timer id or timeout object of the timer to clear.\n */\n var clearTimeout = ctxClearTimeout || function(id) {\n return root.clearTimeout(id);\n };\n\n /**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\n function cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n }\n\n /**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\n function cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n }\n\n /**\n * Creates a clone of `dataView`.\n *\n * @private\n * @param {Object} dataView The data view to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned data view.\n */\n function cloneDataView(dataView, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n }\n\n /**\n * Creates a clone of `regexp`.\n *\n * @private\n * @param {Object} regexp The regexp to clone.\n * @returns {Object} Returns the cloned regexp.\n */\n function cloneRegExp(regexp) {\n var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n result.lastIndex = regexp.lastIndex;\n return result;\n }\n\n /**\n * Creates a clone of the `symbol` object.\n *\n * @private\n * @param {Object} symbol The symbol object to clone.\n * @returns {Object} Returns the cloned symbol object.\n */\n function cloneSymbol(symbol) {\n return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n }\n\n /**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\n function cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n }\n\n /**\n * Compares values to sort them in ascending order.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {number} Returns the sort order indicator for `value`.\n */\n function compareAscending(value, other) {\n if (value !== other) {\n var valIsDefined = value !== undefined,\n valIsNull = value === null,\n valIsReflexive = value === value,\n valIsSymbol = isSymbol(value);\n\n var othIsDefined = other !== undefined,\n othIsNull = other === null,\n othIsReflexive = other === other,\n othIsSymbol = isSymbol(other);\n\n if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n (valIsNull && othIsDefined && othIsReflexive) ||\n (!valIsDefined && othIsReflexive) ||\n !valIsReflexive) {\n return 1;\n }\n if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n (othIsNull && valIsDefined && valIsReflexive) ||\n (!othIsDefined && valIsReflexive) ||\n !othIsReflexive) {\n return -1;\n }\n }\n return 0;\n }\n\n /**\n * Used by `_.orderBy` to compare multiple properties of a value to another\n * and stable sort them.\n *\n * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,\n * specify an order of \"desc\" for descending or \"asc\" for ascending sort order\n * of corresponding values.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {boolean[]|string[]} orders The order to sort by for each property.\n * @returns {number} Returns the sort order indicator for `object`.\n */\n function compareMultiple(object, other, orders) {\n var index = -1,\n objCriteria = object.criteria,\n othCriteria = other.criteria,\n length = objCriteria.length,\n ordersLength = orders.length;\n\n while (++index < length) {\n var result = compareAscending(objCriteria[index], othCriteria[index]);\n if (result) {\n if (index >= ordersLength) {\n return result;\n }\n var order = orders[index];\n return result * (order == 'desc' ? -1 : 1);\n }\n }\n // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications\n // that causes it, under certain circumstances, to provide the same value for\n // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247\n // for more details.\n //\n // This also ensures a stable sort in V8 and other engines.\n // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n return object.index - other.index;\n }\n\n /**\n * Creates an array that is the composition of partially applied arguments,\n * placeholders, and provided arguments into a single array of arguments.\n *\n * @private\n * @param {Array} args The provided arguments.\n * @param {Array} partials The arguments to prepend to those provided.\n * @param {Array} holders The `partials` placeholder indexes.\n * @params {boolean} [isCurried] Specify composing for a curried function.\n * @returns {Array} Returns the new array of composed arguments.\n */\n function composeArgs(args, partials, holders, isCurried) {\n var argsIndex = -1,\n argsLength = args.length,\n holdersLength = holders.length,\n leftIndex = -1,\n leftLength = partials.length,\n rangeLength = nativeMax(argsLength - holdersLength, 0),\n result = Array(leftLength + rangeLength),\n isUncurried = !isCurried;\n\n while (++leftIndex < leftLength) {\n result[leftIndex] = partials[leftIndex];\n }\n while (++argsIndex < holdersLength) {\n if (isUncurried || argsIndex < argsLength) {\n result[holders[argsIndex]] = args[argsIndex];\n }\n }\n while (rangeLength--) {\n result[leftIndex++] = args[argsIndex++];\n }\n return result;\n }\n\n /**\n * This function is like `composeArgs` except that the arguments composition\n * is tailored for `_.partialRight`.\n *\n * @private\n * @param {Array} args The provided arguments.\n * @param {Array} partials The arguments to append to those provided.\n * @param {Array} holders The `partials` placeholder indexes.\n * @params {boolean} [isCurried] Specify composing for a curried function.\n * @returns {Array} Returns the new array of composed arguments.\n */\n function composeArgsRight(args, partials, holders, isCurried) {\n var argsIndex = -1,\n argsLength = args.length,\n holdersIndex = -1,\n holdersLength = holders.length,\n rightIndex = -1,\n rightLength = partials.length,\n rangeLength = nativeMax(argsLength - holdersLength, 0),\n result = Array(rangeLength + rightLength),\n isUncurried = !isCurried;\n\n while (++argsIndex < rangeLength) {\n result[argsIndex] = args[argsIndex];\n }\n var offset = argsIndex;\n while (++rightIndex < rightLength) {\n result[offset + rightIndex] = partials[rightIndex];\n }\n while (++holdersIndex < holdersLength) {\n if (isUncurried || argsIndex < argsLength) {\n result[offset + holders[holdersIndex]] = args[argsIndex++];\n }\n }\n return result;\n }\n\n /**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\n function copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n }\n\n /**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\n function copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n }\n\n /**\n * Copies own symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\n function copySymbols(source, object) {\n return copyObject(source, getSymbols(source), object);\n }\n\n /**\n * Copies own and inherited symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\n function copySymbolsIn(source, object) {\n return copyObject(source, getSymbolsIn(source), object);\n }\n\n /**\n * Creates a function like `_.groupBy`.\n *\n * @private\n * @param {Function} setter The function to set accumulator values.\n * @param {Function} [initializer] The accumulator object initializer.\n * @returns {Function} Returns the new aggregator function.\n */\n function createAggregator(setter, initializer) {\n return function(collection, iteratee) {\n var func = isArray(collection) ? arrayAggregator : baseAggregator,\n accumulator = initializer ? initializer() : {};\n\n return func(collection, setter, getIteratee(iteratee, 2), accumulator);\n };\n }\n\n /**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\n function createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n }\n\n /**\n * Creates a `baseEach` or `baseEachRight` function.\n *\n * @private\n * @param {Function} eachFunc The function to iterate over a collection.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\n function createBaseEach(eachFunc, fromRight) {\n return function(collection, iteratee) {\n if (collection == null) {\n return collection;\n }\n if (!isArrayLike(collection)) {\n return eachFunc(collection, iteratee);\n }\n var length = collection.length,\n index = fromRight ? length : -1,\n iterable = Object(collection);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (iteratee(iterable[index], index, iterable) === false) {\n break;\n }\n }\n return collection;\n };\n }\n\n /**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\n function createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n }\n\n /**\n * Creates a function that wraps `func` to invoke it with the optional `this`\n * binding of `thisArg`.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createBind(func, bitmask, thisArg) {\n var isBind = bitmask & WRAP_BIND_FLAG,\n Ctor = createCtor(func);\n\n function wrapper() {\n var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n return fn.apply(isBind ? thisArg : this, arguments);\n }\n return wrapper;\n }\n\n /**\n * Creates a function like `_.lowerFirst`.\n *\n * @private\n * @param {string} methodName The name of the `String` case method to use.\n * @returns {Function} Returns the new case function.\n */\n function createCaseFirst(methodName) {\n return function(string) {\n string = toString(string);\n\n var strSymbols = hasUnicode(string)\n ? stringToArray(string)\n : undefined;\n\n var chr = strSymbols\n ? strSymbols[0]\n : string.charAt(0);\n\n var trailing = strSymbols\n ? castSlice(strSymbols, 1).join('')\n : string.slice(1);\n\n return chr[methodName]() + trailing;\n };\n }\n\n /**\n * Creates a function like `_.camelCase`.\n *\n * @private\n * @param {Function} callback The function to combine each word.\n * @returns {Function} Returns the new compounder function.\n */\n function createCompounder(callback) {\n return function(string) {\n return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');\n };\n }\n\n /**\n * Creates a function that produces an instance of `Ctor` regardless of\n * whether it was invoked as part of a `new` expression or by `call` or `apply`.\n *\n * @private\n * @param {Function} Ctor The constructor to wrap.\n * @returns {Function} Returns the new wrapped function.\n */\n function createCtor(Ctor) {\n return function() {\n // Use a `switch` statement to work with class constructors. See\n // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist\n // for more details.\n var args = arguments;\n switch (args.length) {\n case 0: return new Ctor;\n case 1: return new Ctor(args[0]);\n case 2: return new Ctor(args[0], args[1]);\n case 3: return new Ctor(args[0], args[1], args[2]);\n case 4: return new Ctor(args[0], args[1], args[2], args[3]);\n case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);\n case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);\n case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n }\n var thisBinding = baseCreate(Ctor.prototype),\n result = Ctor.apply(thisBinding, args);\n\n // Mimic the constructor's `return` behavior.\n // See https://es5.github.io/#x13.2.2 for more details.\n return isObject(result) ? result : thisBinding;\n };\n }\n\n /**\n * Creates a function that wraps `func` to enable currying.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {number} arity The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createCurry(func, bitmask, arity) {\n var Ctor = createCtor(func);\n\n function wrapper() {\n var length = arguments.length,\n args = Array(length),\n index = length,\n placeholder = getHolder(wrapper);\n\n while (index--) {\n args[index] = arguments[index];\n }\n var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)\n ? []\n : replaceHolders(args, placeholder);\n\n length -= holders.length;\n if (length < arity) {\n return createRecurry(\n func, bitmask, createHybrid, wrapper.placeholder, undefined,\n args, holders, undefined, undefined, arity - length);\n }\n var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n return apply(fn, this, args);\n }\n return wrapper;\n }\n\n /**\n * Creates a `_.find` or `_.findLast` function.\n *\n * @private\n * @param {Function} findIndexFunc The function to find the collection index.\n * @returns {Function} Returns the new find function.\n */\n function createFind(findIndexFunc) {\n return function(collection, predicate, fromIndex) {\n var iterable = Object(collection);\n if (!isArrayLike(collection)) {\n var iteratee = getIteratee(predicate, 3);\n collection = keys(collection);\n predicate = function(key) { return iteratee(iterable[key], key, iterable); };\n }\n var index = findIndexFunc(collection, predicate, fromIndex);\n return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;\n };\n }\n\n /**\n * Creates a `_.flow` or `_.flowRight` function.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new flow function.\n */\n function createFlow(fromRight) {\n return flatRest(function(funcs) {\n var length = funcs.length,\n index = length,\n prereq = LodashWrapper.prototype.thru;\n\n if (fromRight) {\n funcs.reverse();\n }\n while (index--) {\n var func = funcs[index];\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n if (prereq && !wrapper && getFuncName(func) == 'wrapper') {\n var wrapper = new LodashWrapper([], true);\n }\n }\n index = wrapper ? index : length;\n while (++index < length) {\n func = funcs[index];\n\n var funcName = getFuncName(func),\n data = funcName == 'wrapper' ? getData(func) : undefined;\n\n if (data && isLaziable(data[0]) &&\n data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&\n !data[4].length && data[9] == 1\n ) {\n wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);\n } else {\n wrapper = (func.length == 1 && isLaziable(func))\n ? wrapper[funcName]()\n : wrapper.thru(func);\n }\n }\n return function() {\n var args = arguments,\n value = args[0];\n\n if (wrapper && args.length == 1 && isArray(value)) {\n return wrapper.plant(value).value();\n }\n var index = 0,\n result = length ? funcs[index].apply(this, args) : value;\n\n while (++index < length) {\n result = funcs[index].call(this, result);\n }\n return result;\n };\n });\n }\n\n /**\n * Creates a function that wraps `func` to invoke it with optional `this`\n * binding of `thisArg`, partial application, and currying.\n *\n * @private\n * @param {Function|string} func The function or method name to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to prepend to those provided to\n * the new function.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [partialsRight] The arguments to append to those provided\n * to the new function.\n * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {\n var isAry = bitmask & WRAP_ARY_FLAG,\n isBind = bitmask & WRAP_BIND_FLAG,\n isBindKey = bitmask & WRAP_BIND_KEY_FLAG,\n isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),\n isFlip = bitmask & WRAP_FLIP_FLAG,\n Ctor = isBindKey ? undefined : createCtor(func);\n\n function wrapper() {\n var length = arguments.length,\n args = Array(length),\n index = length;\n\n while (index--) {\n args[index] = arguments[index];\n }\n if (isCurried) {\n var placeholder = getHolder(wrapper),\n holdersCount = countHolders(args, placeholder);\n }\n if (partials) {\n args = composeArgs(args, partials, holders, isCurried);\n }\n if (partialsRight) {\n args = composeArgsRight(args, partialsRight, holdersRight, isCurried);\n }\n length -= holdersCount;\n if (isCurried && length < arity) {\n var newHolders = replaceHolders(args, placeholder);\n return createRecurry(\n func, bitmask, createHybrid, wrapper.placeholder, thisArg,\n args, newHolders, argPos, ary, arity - length\n );\n }\n var thisBinding = isBind ? thisArg : this,\n fn = isBindKey ? thisBinding[func] : func;\n\n length = args.length;\n if (argPos) {\n args = reorder(args, argPos);\n } else if (isFlip && length > 1) {\n args.reverse();\n }\n if (isAry && ary < length) {\n args.length = ary;\n }\n if (this && this !== root && this instanceof wrapper) {\n fn = Ctor || createCtor(fn);\n }\n return fn.apply(thisBinding, args);\n }\n return wrapper;\n }\n\n /**\n * Creates a function like `_.invertBy`.\n *\n * @private\n * @param {Function} setter The function to set accumulator values.\n * @param {Function} toIteratee The function to resolve iteratees.\n * @returns {Function} Returns the new inverter function.\n */\n function createInverter(setter, toIteratee) {\n return function(object, iteratee) {\n return baseInverter(object, setter, toIteratee(iteratee), {});\n };\n }\n\n /**\n * Creates a function that performs a mathematical operation on two values.\n *\n * @private\n * @param {Function} operator The function to perform the operation.\n * @param {number} [defaultValue] The value used for `undefined` arguments.\n * @returns {Function} Returns the new mathematical operation function.\n */\n function createMathOperation(operator, defaultValue) {\n return function(value, other) {\n var result;\n if (value === undefined && other === undefined) {\n return defaultValue;\n }\n if (value !== undefined) {\n result = value;\n }\n if (other !== undefined) {\n if (result === undefined) {\n return other;\n }\n if (typeof value == 'string' || typeof other == 'string') {\n value = baseToString(value);\n other = baseToString(other);\n } else {\n value = baseToNumber(value);\n other = baseToNumber(other);\n }\n result = operator(value, other);\n }\n return result;\n };\n }\n\n /**\n * Creates a function like `_.over`.\n *\n * @private\n * @param {Function} arrayFunc The function to iterate over iteratees.\n * @returns {Function} Returns the new over function.\n */\n function createOver(arrayFunc) {\n return flatRest(function(iteratees) {\n iteratees = arrayMap(iteratees, baseUnary(getIteratee()));\n return baseRest(function(args) {\n var thisArg = this;\n return arrayFunc(iteratees, function(iteratee) {\n return apply(iteratee, thisArg, args);\n });\n });\n });\n }\n\n /**\n * Creates the padding for `string` based on `length`. The `chars` string\n * is truncated if the number of characters exceeds `length`.\n *\n * @private\n * @param {number} length The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padding for `string`.\n */\n function createPadding(length, chars) {\n chars = chars === undefined ? ' ' : baseToString(chars);\n\n var charsLength = chars.length;\n if (charsLength < 2) {\n return charsLength ? baseRepeat(chars, length) : chars;\n }\n var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));\n return hasUnicode(chars)\n ? castSlice(stringToArray(result), 0, length).join('')\n : result.slice(0, length);\n }\n\n /**\n * Creates a function that wraps `func` to invoke it with the `this` binding\n * of `thisArg` and `partials` prepended to the arguments it receives.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} partials The arguments to prepend to those provided to\n * the new function.\n * @returns {Function} Returns the new wrapped function.\n */\n function createPartial(func, bitmask, thisArg, partials) {\n var isBind = bitmask & WRAP_BIND_FLAG,\n Ctor = createCtor(func);\n\n function wrapper() {\n var argsIndex = -1,\n argsLength = arguments.length,\n leftIndex = -1,\n leftLength = partials.length,\n args = Array(leftLength + argsLength),\n fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n\n while (++leftIndex < leftLength) {\n args[leftIndex] = partials[leftIndex];\n }\n while (argsLength--) {\n args[leftIndex++] = arguments[++argsIndex];\n }\n return apply(fn, isBind ? thisArg : this, args);\n }\n return wrapper;\n }\n\n /**\n * Creates a `_.range` or `_.rangeRight` function.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new range function.\n */\n function createRange(fromRight) {\n return function(start, end, step) {\n if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {\n end = step = undefined;\n }\n // Ensure the sign of `-0` is preserved.\n start = toFinite(start);\n if (end === undefined) {\n end = start;\n start = 0;\n } else {\n end = toFinite(end);\n }\n step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);\n return baseRange(start, end, step, fromRight);\n };\n }\n\n /**\n * Creates a function that performs a relational operation on two values.\n *\n * @private\n * @param {Function} operator The function to perform the operation.\n * @returns {Function} Returns the new relational operation function.\n */\n function createRelationalOperation(operator) {\n return function(value, other) {\n if (!(typeof value == 'string' && typeof other == 'string')) {\n value = toNumber(value);\n other = toNumber(other);\n }\n return operator(value, other);\n };\n }\n\n /**\n * Creates a function that wraps `func` to continue currying.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {Function} wrapFunc The function to create the `func` wrapper.\n * @param {*} placeholder The placeholder value.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to prepend to those provided to\n * the new function.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {\n var isCurry = bitmask & WRAP_CURRY_FLAG,\n newHolders = isCurry ? holders : undefined,\n newHoldersRight = isCurry ? undefined : holders,\n newPartials = isCurry ? partials : undefined,\n newPartialsRight = isCurry ? undefined : partials;\n\n bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);\n bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);\n\n if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {\n bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);\n }\n var newData = [\n func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,\n newHoldersRight, argPos, ary, arity\n ];\n\n var result = wrapFunc.apply(undefined, newData);\n if (isLaziable(func)) {\n setData(result, newData);\n }\n result.placeholder = placeholder;\n return setWrapToString(result, func, bitmask);\n }\n\n /**\n * Creates a function like `_.round`.\n *\n * @private\n * @param {string} methodName The name of the `Math` method to use when rounding.\n * @returns {Function} Returns the new round function.\n */\n function createRound(methodName) {\n var func = Math[methodName];\n return function(number, precision) {\n number = toNumber(number);\n precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);\n if (precision && nativeIsFinite(number)) {\n // Shift with exponential notation to avoid floating-point issues.\n // See [MDN](https://mdn.io/round#Examples) for more details.\n var pair = (toString(number) + 'e').split('e'),\n value = func(pair[0] + 'e' + (+pair[1] + precision));\n\n pair = (toString(value) + 'e').split('e');\n return +(pair[0] + 'e' + (+pair[1] - precision));\n }\n return func(number);\n };\n }\n\n /**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\n var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n return new Set(values);\n };\n\n /**\n * Creates a `_.toPairs` or `_.toPairsIn` function.\n *\n * @private\n * @param {Function} keysFunc The function to get the keys of a given object.\n * @returns {Function} Returns the new pairs function.\n */\n function createToPairs(keysFunc) {\n return function(object) {\n var tag = getTag(object);\n if (tag == mapTag) {\n return mapToArray(object);\n }\n if (tag == setTag) {\n return setToPairs(object);\n }\n return baseToPairs(object, keysFunc(object));\n };\n }\n\n /**\n * Creates a function that either curries or invokes `func` with optional\n * `this` binding and partially applied arguments.\n *\n * @private\n * @param {Function|string} func The function or method name to wrap.\n * @param {number} bitmask The bitmask flags.\n * 1 - `_.bind`\n * 2 - `_.bindKey`\n * 4 - `_.curry` or `_.curryRight` of a bound function\n * 8 - `_.curry`\n * 16 - `_.curryRight`\n * 32 - `_.partial`\n * 64 - `_.partialRight`\n * 128 - `_.rearg`\n * 256 - `_.ary`\n * 512 - `_.flip`\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to be partially applied.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {\n var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;\n if (!isBindKey && typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var length = partials ? partials.length : 0;\n if (!length) {\n bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);\n partials = holders = undefined;\n }\n ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);\n arity = arity === undefined ? arity : toInteger(arity);\n length -= holders ? holders.length : 0;\n\n if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {\n var partialsRight = partials,\n holdersRight = holders;\n\n partials = holders = undefined;\n }\n var data = isBindKey ? undefined : getData(func);\n\n var newData = [\n func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,\n argPos, ary, arity\n ];\n\n if (data) {\n mergeData(newData, data);\n }\n func = newData[0];\n bitmask = newData[1];\n thisArg = newData[2];\n partials = newData[3];\n holders = newData[4];\n arity = newData[9] = newData[9] === undefined\n ? (isBindKey ? 0 : func.length)\n : nativeMax(newData[9] - length, 0);\n\n if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {\n bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);\n }\n if (!bitmask || bitmask == WRAP_BIND_FLAG) {\n var result = createBind(func, bitmask, thisArg);\n } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {\n result = createCurry(func, bitmask, arity);\n } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {\n result = createPartial(func, bitmask, thisArg, partials);\n } else {\n result = createHybrid.apply(undefined, newData);\n }\n var setter = data ? baseSetData : setData;\n return setWrapToString(setter(result, newData), func, bitmask);\n }\n\n /**\n * Used by `_.defaults` to customize its `_.assignIn` use to assign properties\n * of source objects to the destination object for all destination properties\n * that resolve to `undefined`.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to assign.\n * @param {Object} object The parent object of `objValue`.\n * @returns {*} Returns the value to assign.\n */\n function customDefaultsAssignIn(objValue, srcValue, key, object) {\n if (objValue === undefined ||\n (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n return srcValue;\n }\n return objValue;\n }\n\n /**\n * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source\n * objects into destination objects that are passed thru.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to merge.\n * @param {Object} object The parent object of `objValue`.\n * @param {Object} source The parent object of `srcValue`.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n * @returns {*} Returns the value to assign.\n */\n function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {\n if (isObject(objValue) && isObject(srcValue)) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, objValue);\n baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);\n stack['delete'](srcValue);\n }\n return objValue;\n }\n\n /**\n * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain\n * objects.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {string} key The key of the property to inspect.\n * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.\n */\n function customOmitClone(value) {\n return isPlainObject(value) ? undefined : value;\n }\n\n /**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\n function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n return false;\n }\n // Check that cyclic values are equal.\n var arrStacked = stack.get(array);\n var othStacked = stack.get(other);\n if (arrStacked && othStacked) {\n return arrStacked == other && othStacked == array;\n }\n var index = -1,\n result = true,\n seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n stack.set(array, other);\n stack.set(other, array);\n\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, arrValue, index, other, array, stack)\n : customizer(arrValue, othValue, index, array, other, stack);\n }\n if (compared !== undefined) {\n if (compared) {\n continue;\n }\n result = false;\n break;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (seen) {\n if (!arraySome(other, function(othValue, othIndex) {\n if (!cacheHas(seen, othIndex) &&\n (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n return seen.push(othIndex);\n }\n })) {\n result = false;\n break;\n }\n } else if (!(\n arrValue === othValue ||\n equalFunc(arrValue, othValue, bitmask, customizer, stack)\n )) {\n result = false;\n break;\n }\n }\n stack['delete'](array);\n stack['delete'](other);\n return result;\n }\n\n /**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\n function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n switch (tag) {\n case dataViewTag:\n if ((object.byteLength != other.byteLength) ||\n (object.byteOffset != other.byteOffset)) {\n return false;\n }\n object = object.buffer;\n other = other.buffer;\n\n case arrayBufferTag:\n if ((object.byteLength != other.byteLength) ||\n !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n return false;\n }\n return true;\n\n case boolTag:\n case dateTag:\n case numberTag:\n // Coerce booleans to `1` or `0` and dates to milliseconds.\n // Invalid dates are coerced to `NaN`.\n return eq(+object, +other);\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings, primitives and objects,\n // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n // for more details.\n return object == (other + '');\n\n case mapTag:\n var convert = mapToArray;\n\n case setTag:\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n convert || (convert = setToArray);\n\n if (object.size != other.size && !isPartial) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked) {\n return stacked == other;\n }\n bitmask |= COMPARE_UNORDERED_FLAG;\n\n // Recursively compare objects (susceptible to call stack limits).\n stack.set(object, other);\n var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n stack['delete'](object);\n return result;\n\n case symbolTag:\n if (symbolValueOf) {\n return symbolValueOf.call(object) == symbolValueOf.call(other);\n }\n }\n return false;\n }\n\n /**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\n function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n objProps = getAllKeys(object),\n objLength = objProps.length,\n othProps = getAllKeys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isPartial) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n // Check that cyclic values are equal.\n var objStacked = stack.get(object);\n var othStacked = stack.get(other);\n if (objStacked && othStacked) {\n return objStacked == other && othStacked == object;\n }\n var result = true;\n stack.set(object, other);\n stack.set(other, object);\n\n var skipCtor = isPartial;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, objValue, key, other, object, stack)\n : customizer(objValue, othValue, key, object, other, stack);\n }\n // Recursively compare objects (susceptible to call stack limits).\n if (!(compared === undefined\n ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n : compared\n )) {\n result = false;\n break;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (result && !skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n result = false;\n }\n }\n stack['delete'](object);\n stack['delete'](other);\n return result;\n }\n\n /**\n * A specialized version of `baseRest` which flattens the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @returns {Function} Returns the new function.\n */\n function flatRest(func) {\n return setToString(overRest(func, undefined, flatten), func + '');\n }\n\n /**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\n function getAllKeys(object) {\n return baseGetAllKeys(object, keys, getSymbols);\n }\n\n /**\n * Creates an array of own and inherited enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\n function getAllKeysIn(object) {\n return baseGetAllKeys(object, keysIn, getSymbolsIn);\n }\n\n /**\n * Gets metadata for `func`.\n *\n * @private\n * @param {Function} func The function to query.\n * @returns {*} Returns the metadata for `func`.\n */\n var getData = !metaMap ? noop : function(func) {\n return metaMap.get(func);\n };\n\n /**\n * Gets the name of `func`.\n *\n * @private\n * @param {Function} func The function to query.\n * @returns {string} Returns the function name.\n */\n function getFuncName(func) {\n var result = (func.name + ''),\n array = realNames[result],\n length = hasOwnProperty.call(realNames, result) ? array.length : 0;\n\n while (length--) {\n var data = array[length],\n otherFunc = data.func;\n if (otherFunc == null || otherFunc == func) {\n return data.name;\n }\n }\n return result;\n }\n\n /**\n * Gets the argument placeholder value for `func`.\n *\n * @private\n * @param {Function} func The function to inspect.\n * @returns {*} Returns the placeholder value.\n */\n function getHolder(func) {\n var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;\n return object.placeholder;\n }\n\n /**\n * Gets the appropriate \"iteratee\" function. If `_.iteratee` is customized,\n * this function returns the custom method, otherwise it returns `baseIteratee`.\n * If arguments are provided, the chosen function is invoked with them and\n * its result is returned.\n *\n * @private\n * @param {*} [value] The value to convert to an iteratee.\n * @param {number} [arity] The arity of the created iteratee.\n * @returns {Function} Returns the chosen function or its result.\n */\n function getIteratee() {\n var result = lodash.iteratee || iteratee;\n result = result === iteratee ? baseIteratee : result;\n return arguments.length ? result(arguments[0], arguments[1]) : result;\n }\n\n /**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\n function getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n }\n\n /**\n * Gets the property names, values, and compare flags of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the match data of `object`.\n */\n function getMatchData(object) {\n var result = keys(object),\n length = result.length;\n\n while (length--) {\n var key = result[length],\n value = object[key];\n\n result[length] = [key, value, isStrictComparable(value)];\n }\n return result;\n }\n\n /**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\n function getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n }\n\n /**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\n function getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n }\n\n /**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\n var getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n if (object == null) {\n return [];\n }\n object = Object(object);\n return arrayFilter(nativeGetSymbols(object), function(symbol) {\n return propertyIsEnumerable.call(object, symbol);\n });\n };\n\n /**\n * Creates an array of the own and inherited enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\n var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {\n var result = [];\n while (object) {\n arrayPush(result, getSymbols(object));\n object = getPrototype(object);\n }\n return result;\n };\n\n /**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\n var getTag = baseGetTag;\n\n // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\n if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n (Map && getTag(new Map) != mapTag) ||\n (Promise && getTag(Promise.resolve()) != promiseTag) ||\n (Set && getTag(new Set) != setTag) ||\n (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n getTag = function(value) {\n var result = baseGetTag(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : '';\n\n if (ctorString) {\n switch (ctorString) {\n case dataViewCtorString: return dataViewTag;\n case mapCtorString: return mapTag;\n case promiseCtorString: return promiseTag;\n case setCtorString: return setTag;\n case weakMapCtorString: return weakMapTag;\n }\n }\n return result;\n };\n }\n\n /**\n * Gets the view, applying any `transforms` to the `start` and `end` positions.\n *\n * @private\n * @param {number} start The start of the view.\n * @param {number} end The end of the view.\n * @param {Array} transforms The transformations to apply to the view.\n * @returns {Object} Returns an object containing the `start` and `end`\n * positions of the view.\n */\n function getView(start, end, transforms) {\n var index = -1,\n length = transforms.length;\n\n while (++index < length) {\n var data = transforms[index],\n size = data.size;\n\n switch (data.type) {\n case 'drop': start += size; break;\n case 'dropRight': end -= size; break;\n case 'take': end = nativeMin(end, start + size); break;\n case 'takeRight': start = nativeMax(start, end - size); break;\n }\n }\n return { 'start': start, 'end': end };\n }\n\n /**\n * Extracts wrapper details from the `source` body comment.\n *\n * @private\n * @param {string} source The source to inspect.\n * @returns {Array} Returns the wrapper details.\n */\n function getWrapDetails(source) {\n var match = source.match(reWrapDetails);\n return match ? match[1].split(reSplitDetails) : [];\n }\n\n /**\n * Checks if `path` exists on `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @param {Function} hasFunc The function to check properties.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n */\n function hasPath(object, path, hasFunc) {\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n result = false;\n\n while (++index < length) {\n var key = toKey(path[index]);\n if (!(result = object != null && hasFunc(object, key))) {\n break;\n }\n object = object[key];\n }\n if (result || ++index != length) {\n return result;\n }\n length = object == null ? 0 : object.length;\n return !!length && isLength(length) && isIndex(key, length) &&\n (isArray(object) || isArguments(object));\n }\n\n /**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\n function initCloneArray(array) {\n var length = array.length,\n result = new array.constructor(length);\n\n // Add properties assigned by `RegExp#exec`.\n if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n result.index = array.index;\n result.input = array.input;\n }\n return result;\n }\n\n /**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\n function initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n }\n\n /**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\n function initCloneByTag(object, tag, isDeep) {\n var Ctor = object.constructor;\n switch (tag) {\n case arrayBufferTag:\n return cloneArrayBuffer(object);\n\n case boolTag:\n case dateTag:\n return new Ctor(+object);\n\n case dataViewTag:\n return cloneDataView(object, isDeep);\n\n case float32Tag: case float64Tag:\n case int8Tag: case int16Tag: case int32Tag:\n case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n return cloneTypedArray(object, isDeep);\n\n case mapTag:\n return new Ctor;\n\n case numberTag:\n case stringTag:\n return new Ctor(object);\n\n case regexpTag:\n return cloneRegExp(object);\n\n case setTag:\n return new Ctor;\n\n case symbolTag:\n return cloneSymbol(object);\n }\n }\n\n /**\n * Inserts wrapper `details` in a comment at the top of the `source` body.\n *\n * @private\n * @param {string} source The source to modify.\n * @returns {Array} details The details to insert.\n * @returns {string} Returns the modified source.\n */\n function insertWrapDetails(source, details) {\n var length = details.length;\n if (!length) {\n return source;\n }\n var lastIndex = length - 1;\n details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];\n details = details.join(length > 2 ? ', ' : ' ');\n return source.replace(reWrapComment, '{\\n/* [wrapped with ' + details + '] */\\n');\n }\n\n /**\n * Checks if `value` is a flattenable `arguments` object or array.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n */\n function isFlattenable(value) {\n return isArray(value) || isArguments(value) ||\n !!(spreadableSymbol && value && value[spreadableSymbol]);\n }\n\n /**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\n function isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n }\n\n /**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\n function isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n }\n\n /**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\n function isKey(value, object) {\n if (isArray(value)) {\n return false;\n }\n var type = typeof value;\n if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n value == null || isSymbol(value)) {\n return true;\n }\n return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n (object != null && value in Object(object));\n }\n\n /**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\n function isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n }\n\n /**\n * Checks if `func` has a lazy counterpart.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` has a lazy counterpart,\n * else `false`.\n */\n function isLaziable(func) {\n var funcName = getFuncName(func),\n other = lodash[funcName];\n\n if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {\n return false;\n }\n if (func === other) {\n return true;\n }\n var data = getData(other);\n return !!data && func === data[0];\n }\n\n /**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\n function isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n }\n\n /**\n * Checks if `func` is capable of being masked.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `func` is maskable, else `false`.\n */\n var isMaskable = coreJsData ? isFunction : stubFalse;\n\n /**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\n function isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n }\n\n /**\n * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` if suitable for strict\n * equality comparisons, else `false`.\n */\n function isStrictComparable(value) {\n return value === value && !isObject(value);\n }\n\n /**\n * A specialized version of `matchesProperty` for source values suitable\n * for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\n function matchesStrictComparable(key, srcValue) {\n return function(object) {\n if (object == null) {\n return false;\n }\n return object[key] === srcValue &&\n (srcValue !== undefined || (key in Object(object)));\n };\n }\n\n /**\n * A specialized version of `_.memoize` which clears the memoized function's\n * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n *\n * @private\n * @param {Function} func The function to have its output memoized.\n * @returns {Function} Returns the new memoized function.\n */\n function memoizeCapped(func) {\n var result = memoize(func, function(key) {\n if (cache.size === MAX_MEMOIZE_SIZE) {\n cache.clear();\n }\n return key;\n });\n\n var cache = result.cache;\n return result;\n }\n\n /**\n * Merges the function metadata of `source` into `data`.\n *\n * Merging metadata reduces the number of wrappers used to invoke a function.\n * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`\n * may be applied regardless of execution order. Methods like `_.ary` and\n * `_.rearg` modify function arguments, making the order in which they are\n * executed important, preventing the merging of metadata. However, we make\n * an exception for a safe combined case where curried functions have `_.ary`\n * and or `_.rearg` applied.\n *\n * @private\n * @param {Array} data The destination metadata.\n * @param {Array} source The source metadata.\n * @returns {Array} Returns `data`.\n */\n function mergeData(data, source) {\n var bitmask = data[1],\n srcBitmask = source[1],\n newBitmask = bitmask | srcBitmask,\n isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);\n\n var isCombo =\n ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||\n ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||\n ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));\n\n // Exit early if metadata can't be merged.\n if (!(isCommon || isCombo)) {\n return data;\n }\n // Use source `thisArg` if available.\n if (srcBitmask & WRAP_BIND_FLAG) {\n data[2] = source[2];\n // Set when currying a bound function.\n newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;\n }\n // Compose partial arguments.\n var value = source[3];\n if (value) {\n var partials = data[3];\n data[3] = partials ? composeArgs(partials, value, source[4]) : value;\n data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];\n }\n // Compose partial right arguments.\n value = source[5];\n if (value) {\n partials = data[5];\n data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;\n data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];\n }\n // Use source `argPos` if available.\n value = source[7];\n if (value) {\n data[7] = value;\n }\n // Use source `ary` if it's smaller.\n if (srcBitmask & WRAP_ARY_FLAG) {\n data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);\n }\n // Use source `arity` if one is not provided.\n if (data[9] == null) {\n data[9] = source[9];\n }\n // Use source `func` and merge bitmasks.\n data[0] = source[0];\n data[1] = newBitmask;\n\n return data;\n }\n\n /**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\n function nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\n function objectToString(value) {\n return nativeObjectToString.call(value);\n }\n\n /**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\n function overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n }\n\n /**\n * Gets the parent value at `path` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} path The path to get the parent value of.\n * @returns {*} Returns the parent value.\n */\n function parent(object, path) {\n return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));\n }\n\n /**\n * Reorder `array` according to the specified indexes where the element at\n * the first index is assigned as the first element, the element at\n * the second index is assigned as the second element, and so on.\n *\n * @private\n * @param {Array} array The array to reorder.\n * @param {Array} indexes The arranged array indexes.\n * @returns {Array} Returns `array`.\n */\n function reorder(array, indexes) {\n var arrLength = array.length,\n length = nativeMin(indexes.length, arrLength),\n oldArray = copyArray(array);\n\n while (length--) {\n var index = indexes[length];\n array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;\n }\n return array;\n }\n\n /**\n * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\n function safeGet(object, key) {\n if (key === 'constructor' && typeof object[key] === 'function') {\n return;\n }\n\n if (key == '__proto__') {\n return;\n }\n\n return object[key];\n }\n\n /**\n * Sets metadata for `func`.\n *\n * **Note:** If this function becomes hot, i.e. is invoked a lot in a short\n * period of time, it will trip its breaker and transition to an identity\n * function to avoid garbage collection pauses in V8. See\n * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)\n * for more details.\n *\n * @private\n * @param {Function} func The function to associate metadata with.\n * @param {*} data The metadata.\n * @returns {Function} Returns `func`.\n */\n var setData = shortOut(baseSetData);\n\n /**\n * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).\n *\n * @private\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @returns {number|Object} Returns the timer id or timeout object.\n */\n var setTimeout = ctxSetTimeout || function(func, wait) {\n return root.setTimeout(func, wait);\n };\n\n /**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\n var setToString = shortOut(baseSetToString);\n\n /**\n * Sets the `toString` method of `wrapper` to mimic the source of `reference`\n * with wrapper details in a comment at the top of the source body.\n *\n * @private\n * @param {Function} wrapper The function to modify.\n * @param {Function} reference The reference function.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @returns {Function} Returns `wrapper`.\n */\n function setWrapToString(wrapper, reference, bitmask) {\n var source = (reference + '');\n return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));\n }\n\n /**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\n function shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n }\n\n /**\n * A specialized version of `_.shuffle` which mutates and sets the size of `array`.\n *\n * @private\n * @param {Array} array The array to shuffle.\n * @param {number} [size=array.length] The size of `array`.\n * @returns {Array} Returns `array`.\n */\n function shuffleSelf(array, size) {\n var index = -1,\n length = array.length,\n lastIndex = length - 1;\n\n size = size === undefined ? length : size;\n while (++index < size) {\n var rand = baseRandom(index, lastIndex),\n value = array[rand];\n\n array[rand] = array[index];\n array[index] = value;\n }\n array.length = size;\n return array;\n }\n\n /**\n * Converts `string` to a property path array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the property path array.\n */\n var stringToPath = memoizeCapped(function(string) {\n var result = [];\n if (string.charCodeAt(0) === 46 /* . */) {\n result.push('');\n }\n string.replace(rePropName, function(match, number, quote, subString) {\n result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n });\n\n /**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\n function toKey(value) {\n if (typeof value == 'string' || isSymbol(value)) {\n return value;\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n }\n\n /**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\n function toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n }\n\n /**\n * Updates wrapper `details` based on `bitmask` flags.\n *\n * @private\n * @returns {Array} details The details to modify.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @returns {Array} Returns `details`.\n */\n function updateWrapDetails(details, bitmask) {\n arrayEach(wrapFlags, function(pair) {\n var value = '_.' + pair[0];\n if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {\n details.push(value);\n }\n });\n return details.sort();\n }\n\n /**\n * Creates a clone of `wrapper`.\n *\n * @private\n * @param {Object} wrapper The wrapper to clone.\n * @returns {Object} Returns the cloned wrapper.\n */\n function wrapperClone(wrapper) {\n if (wrapper instanceof LazyWrapper) {\n return wrapper.clone();\n }\n var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);\n result.__actions__ = copyArray(wrapper.__actions__);\n result.__index__ = wrapper.__index__;\n result.__values__ = wrapper.__values__;\n return result;\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an array of elements split into groups the length of `size`.\n * If `array` can't be split evenly, the final chunk will be the remaining\n * elements.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to process.\n * @param {number} [size=1] The length of each chunk\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the new array of chunks.\n * @example\n *\n * _.chunk(['a', 'b', 'c', 'd'], 2);\n * // => [['a', 'b'], ['c', 'd']]\n *\n * _.chunk(['a', 'b', 'c', 'd'], 3);\n * // => [['a', 'b', 'c'], ['d']]\n */\n function chunk(array, size, guard) {\n if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {\n size = 1;\n } else {\n size = nativeMax(toInteger(size), 0);\n }\n var length = array == null ? 0 : array.length;\n if (!length || size < 1) {\n return [];\n }\n var index = 0,\n resIndex = 0,\n result = Array(nativeCeil(length / size));\n\n while (index < length) {\n result[resIndex++] = baseSlice(array, index, (index += size));\n }\n return result;\n }\n\n /**\n * Creates an array with all falsey values removed. The values `false`, `null`,\n * `0`, `\"\"`, `undefined`, and `NaN` are falsey.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to compact.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.compact([0, 1, false, 2, '', 3]);\n * // => [1, 2, 3]\n */\n function compact(array) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (value) {\n result[resIndex++] = value;\n }\n }\n return result;\n }\n\n /**\n * Creates a new array concatenating `array` with any additional arrays\n * and/or values.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to concatenate.\n * @param {...*} [values] The values to concatenate.\n * @returns {Array} Returns the new concatenated array.\n * @example\n *\n * var array = [1];\n * var other = _.concat(array, 2, [3], [[4]]);\n *\n * console.log(other);\n * // => [1, 2, 3, [4]]\n *\n * console.log(array);\n * // => [1]\n */\n function concat() {\n var length = arguments.length;\n if (!length) {\n return [];\n }\n var args = Array(length - 1),\n array = arguments[0],\n index = length;\n\n while (index--) {\n args[index - 1] = arguments[index];\n }\n return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));\n }\n\n /**\n * Creates an array of `array` values not included in the other given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * **Note:** Unlike `_.pullAll`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.without, _.xor\n * @example\n *\n * _.difference([2, 1], [2, 3]);\n * // => [1]\n */\n var difference = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))\n : [];\n });\n\n /**\n * This method is like `_.difference` except that it accepts `iteratee` which\n * is invoked for each element of `array` and `values` to generate the criterion\n * by which they're compared. The order and references of result values are\n * determined by the first array. The iteratee is invoked with one argument:\n * (value).\n *\n * **Note:** Unlike `_.pullAllBy`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n * // => [1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');\n * // => [{ 'x': 2 }]\n */\n var differenceBy = baseRest(function(array, values) {\n var iteratee = last(values);\n if (isArrayLikeObject(iteratee)) {\n iteratee = undefined;\n }\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))\n : [];\n });\n\n /**\n * This method is like `_.difference` except that it accepts `comparator`\n * which is invoked to compare elements of `array` to `values`. The order and\n * references of result values are determined by the first array. The comparator\n * is invoked with two arguments: (arrVal, othVal).\n *\n * **Note:** Unlike `_.pullAllWith`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n *\n * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);\n * // => [{ 'x': 2, 'y': 1 }]\n */\n var differenceWith = baseRest(function(array, values) {\n var comparator = last(values);\n if (isArrayLikeObject(comparator)) {\n comparator = undefined;\n }\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)\n : [];\n });\n\n /**\n * Creates a slice of `array` with `n` elements dropped from the beginning.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to drop.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.drop([1, 2, 3]);\n * // => [2, 3]\n *\n * _.drop([1, 2, 3], 2);\n * // => [3]\n *\n * _.drop([1, 2, 3], 5);\n * // => []\n *\n * _.drop([1, 2, 3], 0);\n * // => [1, 2, 3]\n */\n function drop(array, n, guard) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n return baseSlice(array, n < 0 ? 0 : n, length);\n }\n\n /**\n * Creates a slice of `array` with `n` elements dropped from the end.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to drop.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.dropRight([1, 2, 3]);\n * // => [1, 2]\n *\n * _.dropRight([1, 2, 3], 2);\n * // => [1]\n *\n * _.dropRight([1, 2, 3], 5);\n * // => []\n *\n * _.dropRight([1, 2, 3], 0);\n * // => [1, 2, 3]\n */\n function dropRight(array, n, guard) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n n = length - n;\n return baseSlice(array, 0, n < 0 ? 0 : n);\n }\n\n /**\n * Creates a slice of `array` excluding elements dropped from the end.\n * Elements are dropped until `predicate` returns falsey. The predicate is\n * invoked with three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': false }\n * ];\n *\n * _.dropRightWhile(users, function(o) { return !o.active; });\n * // => objects for ['barney']\n *\n * // The `_.matches` iteratee shorthand.\n * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });\n * // => objects for ['barney', 'fred']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.dropRightWhile(users, ['active', false]);\n * // => objects for ['barney']\n *\n * // The `_.property` iteratee shorthand.\n * _.dropRightWhile(users, 'active');\n * // => objects for ['barney', 'fred', 'pebbles']\n */\n function dropRightWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3), true, true)\n : [];\n }\n\n /**\n * Creates a slice of `array` excluding elements dropped from the beginning.\n * Elements are dropped until `predicate` returns falsey. The predicate is\n * invoked with three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': false },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': true }\n * ];\n *\n * _.dropWhile(users, function(o) { return !o.active; });\n * // => objects for ['pebbles']\n *\n * // The `_.matches` iteratee shorthand.\n * _.dropWhile(users, { 'user': 'barney', 'active': false });\n * // => objects for ['fred', 'pebbles']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.dropWhile(users, ['active', false]);\n * // => objects for ['pebbles']\n *\n * // The `_.property` iteratee shorthand.\n * _.dropWhile(users, 'active');\n * // => objects for ['barney', 'fred', 'pebbles']\n */\n function dropWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3), true)\n : [];\n }\n\n /**\n * Fills elements of `array` with `value` from `start` up to, but not\n * including, `end`.\n *\n * **Note:** This method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 3.2.0\n * @category Array\n * @param {Array} array The array to fill.\n * @param {*} value The value to fill `array` with.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [1, 2, 3];\n *\n * _.fill(array, 'a');\n * console.log(array);\n * // => ['a', 'a', 'a']\n *\n * _.fill(Array(3), 2);\n * // => [2, 2, 2]\n *\n * _.fill([4, 6, 8, 10], '*', 1, 3);\n * // => [4, '*', '*', 10]\n */\n function fill(array, value, start, end) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {\n start = 0;\n end = length;\n }\n return baseFill(array, value, start, end);\n }\n\n /**\n * This method is like `_.find` except that it returns the index of the first\n * element `predicate` returns truthy for instead of the element itself.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=0] The index to search from.\n * @returns {number} Returns the index of the found element, else `-1`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': false },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': true }\n * ];\n *\n * _.findIndex(users, function(o) { return o.user == 'barney'; });\n * // => 0\n *\n * // The `_.matches` iteratee shorthand.\n * _.findIndex(users, { 'user': 'fred', 'active': false });\n * // => 1\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findIndex(users, ['active', false]);\n * // => 0\n *\n * // The `_.property` iteratee shorthand.\n * _.findIndex(users, 'active');\n * // => 2\n */\n function findIndex(array, predicate, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = fromIndex == null ? 0 : toInteger(fromIndex);\n if (index < 0) {\n index = nativeMax(length + index, 0);\n }\n return baseFindIndex(array, getIteratee(predicate, 3), index);\n }\n\n /**\n * This method is like `_.findIndex` except that it iterates over elements\n * of `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=array.length-1] The index to search from.\n * @returns {number} Returns the index of the found element, else `-1`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': false }\n * ];\n *\n * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });\n * // => 2\n *\n * // The `_.matches` iteratee shorthand.\n * _.findLastIndex(users, { 'user': 'barney', 'active': true });\n * // => 0\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findLastIndex(users, ['active', false]);\n * // => 2\n *\n * // The `_.property` iteratee shorthand.\n * _.findLastIndex(users, 'active');\n * // => 0\n */\n function findLastIndex(array, predicate, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = length - 1;\n if (fromIndex !== undefined) {\n index = toInteger(fromIndex);\n index = fromIndex < 0\n ? nativeMax(length + index, 0)\n : nativeMin(index, length - 1);\n }\n return baseFindIndex(array, getIteratee(predicate, 3), index, true);\n }\n\n /**\n * Flattens `array` a single level deep.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flatten([1, [2, [3, [4]], 5]]);\n * // => [1, 2, [3, [4]], 5]\n */\n function flatten(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, 1) : [];\n }\n\n /**\n * Recursively flattens `array`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flattenDeep([1, [2, [3, [4]], 5]]);\n * // => [1, 2, 3, 4, 5]\n */\n function flattenDeep(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, INFINITY) : [];\n }\n\n /**\n * Recursively flatten `array` up to `depth` times.\n *\n * @static\n * @memberOf _\n * @since 4.4.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @param {number} [depth=1] The maximum recursion depth.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * var array = [1, [2, [3, [4]], 5]];\n *\n * _.flattenDepth(array, 1);\n * // => [1, 2, [3, [4]], 5]\n *\n * _.flattenDepth(array, 2);\n * // => [1, 2, 3, [4], 5]\n */\n function flattenDepth(array, depth) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n depth = depth === undefined ? 1 : toInteger(depth);\n return baseFlatten(array, depth);\n }\n\n /**\n * The inverse of `_.toPairs`; this method returns an object composed\n * from key-value `pairs`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} pairs The key-value pairs.\n * @returns {Object} Returns the new object.\n * @example\n *\n * _.fromPairs([['a', 1], ['b', 2]]);\n * // => { 'a': 1, 'b': 2 }\n */\n function fromPairs(pairs) {\n var index = -1,\n length = pairs == null ? 0 : pairs.length,\n result = {};\n\n while (++index < length) {\n var pair = pairs[index];\n result[pair[0]] = pair[1];\n }\n return result;\n }\n\n /**\n * Gets the first element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @alias first\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the first element of `array`.\n * @example\n *\n * _.head([1, 2, 3]);\n * // => 1\n *\n * _.head([]);\n * // => undefined\n */\n function head(array) {\n return (array && array.length) ? array[0] : undefined;\n }\n\n /**\n * Gets the index at which the first occurrence of `value` is found in `array`\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. If `fromIndex` is negative, it's used as the\n * offset from the end of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} [fromIndex=0] The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.indexOf([1, 2, 1, 2], 2);\n * // => 1\n *\n * // Search from the `fromIndex`.\n * _.indexOf([1, 2, 1, 2], 2, 2);\n * // => 3\n */\n function indexOf(array, value, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = fromIndex == null ? 0 : toInteger(fromIndex);\n if (index < 0) {\n index = nativeMax(length + index, 0);\n }\n return baseIndexOf(array, value, index);\n }\n\n /**\n * Gets all but the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.initial([1, 2, 3]);\n * // => [1, 2]\n */\n function initial(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseSlice(array, 0, -1) : [];\n }\n\n /**\n * Creates an array of unique values that are included in all given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * _.intersection([2, 1], [2, 3]);\n * // => [2]\n */\n var intersection = baseRest(function(arrays) {\n var mapped = arrayMap(arrays, castArrayLikeObject);\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped)\n : [];\n });\n\n /**\n * This method is like `_.intersection` except that it accepts `iteratee`\n * which is invoked for each element of each `arrays` to generate the criterion\n * by which they're compared. The order and references of result values are\n * determined by the first array. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n * // => [2.1]\n *\n * // The `_.property` iteratee shorthand.\n * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }]\n */\n var intersectionBy = baseRest(function(arrays) {\n var iteratee = last(arrays),\n mapped = arrayMap(arrays, castArrayLikeObject);\n\n if (iteratee === last(mapped)) {\n iteratee = undefined;\n } else {\n mapped.pop();\n }\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped, getIteratee(iteratee, 2))\n : [];\n });\n\n /**\n * This method is like `_.intersection` except that it accepts `comparator`\n * which is invoked to compare elements of `arrays`. The order and references\n * of result values are determined by the first array. The comparator is\n * invoked with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.intersectionWith(objects, others, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }]\n */\n var intersectionWith = baseRest(function(arrays) {\n var comparator = last(arrays),\n mapped = arrayMap(arrays, castArrayLikeObject);\n\n comparator = typeof comparator == 'function' ? comparator : undefined;\n if (comparator) {\n mapped.pop();\n }\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped, undefined, comparator)\n : [];\n });\n\n /**\n * Converts all elements in `array` into a string separated by `separator`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to convert.\n * @param {string} [separator=','] The element separator.\n * @returns {string} Returns the joined string.\n * @example\n *\n * _.join(['a', 'b', 'c'], '~');\n * // => 'a~b~c'\n */\n function join(array, separator) {\n return array == null ? '' : nativeJoin.call(array, separator);\n }\n\n /**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\n function last(array) {\n var length = array == null ? 0 : array.length;\n return length ? array[length - 1] : undefined;\n }\n\n /**\n * This method is like `_.indexOf` except that it iterates over elements of\n * `array` from right to left.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} [fromIndex=array.length-1] The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.lastIndexOf([1, 2, 1, 2], 2);\n * // => 3\n *\n * // Search from the `fromIndex`.\n * _.lastIndexOf([1, 2, 1, 2], 2, 2);\n * // => 1\n */\n function lastIndexOf(array, value, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = length;\n if (fromIndex !== undefined) {\n index = toInteger(fromIndex);\n index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);\n }\n return value === value\n ? strictLastIndexOf(array, value, index)\n : baseFindIndex(array, baseIsNaN, index, true);\n }\n\n /**\n * Gets the element at index `n` of `array`. If `n` is negative, the nth\n * element from the end is returned.\n *\n * @static\n * @memberOf _\n * @since 4.11.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=0] The index of the element to return.\n * @returns {*} Returns the nth element of `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'd'];\n *\n * _.nth(array, 1);\n * // => 'b'\n *\n * _.nth(array, -2);\n * // => 'c';\n */\n function nth(array, n) {\n return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;\n }\n\n /**\n * Removes all given values from `array` using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`\n * to remove elements from an array by predicate.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {...*} [values] The values to remove.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'a', 'b', 'c'];\n *\n * _.pull(array, 'a', 'c');\n * console.log(array);\n * // => ['b', 'b']\n */\n var pull = baseRest(pullAll);\n\n /**\n * This method is like `_.pull` except that it accepts an array of values to remove.\n *\n * **Note:** Unlike `_.difference`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'a', 'b', 'c'];\n *\n * _.pullAll(array, ['a', 'c']);\n * console.log(array);\n * // => ['b', 'b']\n */\n function pullAll(array, values) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values)\n : array;\n }\n\n /**\n * This method is like `_.pullAll` except that it accepts `iteratee` which is\n * invoked for each element of `array` and `values` to generate the criterion\n * by which they're compared. The iteratee is invoked with one argument: (value).\n *\n * **Note:** Unlike `_.differenceBy`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];\n *\n * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');\n * console.log(array);\n * // => [{ 'x': 2 }]\n */\n function pullAllBy(array, values, iteratee) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values, getIteratee(iteratee, 2))\n : array;\n }\n\n /**\n * This method is like `_.pullAll` except that it accepts `comparator` which\n * is invoked to compare elements of `array` to `values`. The comparator is\n * invoked with two arguments: (arrVal, othVal).\n *\n * **Note:** Unlike `_.differenceWith`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];\n *\n * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);\n * console.log(array);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]\n */\n function pullAllWith(array, values, comparator) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values, undefined, comparator)\n : array;\n }\n\n /**\n * Removes elements from `array` corresponding to `indexes` and returns an\n * array of removed elements.\n *\n * **Note:** Unlike `_.at`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {...(number|number[])} [indexes] The indexes of elements to remove.\n * @returns {Array} Returns the new array of removed elements.\n * @example\n *\n * var array = ['a', 'b', 'c', 'd'];\n * var pulled = _.pullAt(array, [1, 3]);\n *\n * console.log(array);\n * // => ['a', 'c']\n *\n * console.log(pulled);\n * // => ['b', 'd']\n */\n var pullAt = flatRest(function(array, indexes) {\n var length = array == null ? 0 : array.length,\n result = baseAt(array, indexes);\n\n basePullAt(array, arrayMap(indexes, function(index) {\n return isIndex(index, length) ? +index : index;\n }).sort(compareAscending));\n\n return result;\n });\n\n /**\n * Removes all elements from `array` that `predicate` returns truthy for\n * and returns an array of the removed elements. The predicate is invoked\n * with three arguments: (value, index, array).\n *\n * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`\n * to pull elements from an array by value.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new array of removed elements.\n * @example\n *\n * var array = [1, 2, 3, 4];\n * var evens = _.remove(array, function(n) {\n * return n % 2 == 0;\n * });\n *\n * console.log(array);\n * // => [1, 3]\n *\n * console.log(evens);\n * // => [2, 4]\n */\n function remove(array, predicate) {\n var result = [];\n if (!(array && array.length)) {\n return result;\n }\n var index = -1,\n indexes = [],\n length = array.length;\n\n predicate = getIteratee(predicate, 3);\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result.push(value);\n indexes.push(index);\n }\n }\n basePullAt(array, indexes);\n return result;\n }\n\n /**\n * Reverses `array` so that the first element becomes the last, the second\n * element becomes the second to last, and so on.\n *\n * **Note:** This method mutates `array` and is based on\n * [`Array#reverse`](https://mdn.io/Array/reverse).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [1, 2, 3];\n *\n * _.reverse(array);\n * // => [3, 2, 1]\n *\n * console.log(array);\n * // => [3, 2, 1]\n */\n function reverse(array) {\n return array == null ? array : nativeReverse.call(array);\n }\n\n /**\n * Creates a slice of `array` from `start` up to, but not including, `end`.\n *\n * **Note:** This method is used instead of\n * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are\n * returned.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\n function slice(array, start, end) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {\n start = 0;\n end = length;\n }\n else {\n start = start == null ? 0 : toInteger(start);\n end = end === undefined ? length : toInteger(end);\n }\n return baseSlice(array, start, end);\n }\n\n /**\n * Uses a binary search to determine the lowest index at which `value`\n * should be inserted into `array` in order to maintain its sort order.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * _.sortedIndex([30, 50], 40);\n * // => 1\n */\n function sortedIndex(array, value) {\n return baseSortedIndex(array, value);\n }\n\n /**\n * This method is like `_.sortedIndex` except that it accepts `iteratee`\n * which is invoked for `value` and each element of `array` to compute their\n * sort ranking. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * var objects = [{ 'x': 4 }, { 'x': 5 }];\n *\n * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });\n * // => 0\n *\n * // The `_.property` iteratee shorthand.\n * _.sortedIndexBy(objects, { 'x': 4 }, 'x');\n * // => 0\n */\n function sortedIndexBy(array, value, iteratee) {\n return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));\n }\n\n /**\n * This method is like `_.indexOf` except that it performs a binary\n * search on a sorted `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.sortedIndexOf([4, 5, 5, 5, 6], 5);\n * // => 1\n */\n function sortedIndexOf(array, value) {\n var length = array == null ? 0 : array.length;\n if (length) {\n var index = baseSortedIndex(array, value);\n if (index < length && eq(array[index], value)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * This method is like `_.sortedIndex` except that it returns the highest\n * index at which `value` should be inserted into `array` in order to\n * maintain its sort order.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * _.sortedLastIndex([4, 5, 5, 5, 6], 5);\n * // => 4\n */\n function sortedLastIndex(array, value) {\n return baseSortedIndex(array, value, true);\n }\n\n /**\n * This method is like `_.sortedLastIndex` except that it accepts `iteratee`\n * which is invoked for `value` and each element of `array` to compute their\n * sort ranking. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * var objects = [{ 'x': 4 }, { 'x': 5 }];\n *\n * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });\n * // => 1\n *\n * // The `_.property` iteratee shorthand.\n * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');\n * // => 1\n */\n function sortedLastIndexBy(array, value, iteratee) {\n return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);\n }\n\n /**\n * This method is like `_.lastIndexOf` except that it performs a binary\n * search on a sorted `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);\n * // => 3\n */\n function sortedLastIndexOf(array, value) {\n var length = array == null ? 0 : array.length;\n if (length) {\n var index = baseSortedIndex(array, value, true) - 1;\n if (eq(array[index], value)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * This method is like `_.uniq` except that it's designed and optimized\n * for sorted arrays.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.sortedUniq([1, 1, 2]);\n * // => [1, 2]\n */\n function sortedUniq(array) {\n return (array && array.length)\n ? baseSortedUniq(array)\n : [];\n }\n\n /**\n * This method is like `_.uniqBy` except that it's designed and optimized\n * for sorted arrays.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);\n * // => [1.1, 2.3]\n */\n function sortedUniqBy(array, iteratee) {\n return (array && array.length)\n ? baseSortedUniq(array, getIteratee(iteratee, 2))\n : [];\n }\n\n /**\n * Gets all but the first element of `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.tail([1, 2, 3]);\n * // => [2, 3]\n */\n function tail(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseSlice(array, 1, length) : [];\n }\n\n /**\n * Creates a slice of `array` with `n` elements taken from the beginning.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to take.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.take([1, 2, 3]);\n * // => [1]\n *\n * _.take([1, 2, 3], 2);\n * // => [1, 2]\n *\n * _.take([1, 2, 3], 5);\n * // => [1, 2, 3]\n *\n * _.take([1, 2, 3], 0);\n * // => []\n */\n function take(array, n, guard) {\n if (!(array && array.length)) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n return baseSlice(array, 0, n < 0 ? 0 : n);\n }\n\n /**\n * Creates a slice of `array` with `n` elements taken from the end.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to take.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.takeRight([1, 2, 3]);\n * // => [3]\n *\n * _.takeRight([1, 2, 3], 2);\n * // => [2, 3]\n *\n * _.takeRight([1, 2, 3], 5);\n * // => [1, 2, 3]\n *\n * _.takeRight([1, 2, 3], 0);\n * // => []\n */\n function takeRight(array, n, guard) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n n = length - n;\n return baseSlice(array, n < 0 ? 0 : n, length);\n }\n\n /**\n * Creates a slice of `array` with elements taken from the end. Elements are\n * taken until `predicate` returns falsey. The predicate is invoked with\n * three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': false }\n * ];\n *\n * _.takeRightWhile(users, function(o) { return !o.active; });\n * // => objects for ['fred', 'pebbles']\n *\n * // The `_.matches` iteratee shorthand.\n * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });\n * // => objects for ['pebbles']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.takeRightWhile(users, ['active', false]);\n * // => objects for ['fred', 'pebbles']\n *\n * // The `_.property` iteratee shorthand.\n * _.takeRightWhile(users, 'active');\n * // => []\n */\n function takeRightWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3), false, true)\n : [];\n }\n\n /**\n * Creates a slice of `array` with elements taken from the beginning. Elements\n * are taken until `predicate` returns falsey. The predicate is invoked with\n * three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': false },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': true }\n * ];\n *\n * _.takeWhile(users, function(o) { return !o.active; });\n * // => objects for ['barney', 'fred']\n *\n * // The `_.matches` iteratee shorthand.\n * _.takeWhile(users, { 'user': 'barney', 'active': false });\n * // => objects for ['barney']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.takeWhile(users, ['active', false]);\n * // => objects for ['barney', 'fred']\n *\n * // The `_.property` iteratee shorthand.\n * _.takeWhile(users, 'active');\n * // => []\n */\n function takeWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3))\n : [];\n }\n\n /**\n * Creates an array of unique values, in order, from all given arrays using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of combined values.\n * @example\n *\n * _.union([2], [1, 2]);\n * // => [2, 1]\n */\n var union = baseRest(function(arrays) {\n return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));\n });\n\n /**\n * This method is like `_.union` except that it accepts `iteratee` which is\n * invoked for each element of each `arrays` to generate the criterion by\n * which uniqueness is computed. Result values are chosen from the first\n * array in which the value occurs. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of combined values.\n * @example\n *\n * _.unionBy([2.1], [1.2, 2.3], Math.floor);\n * // => [2.1, 1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }, { 'x': 2 }]\n */\n var unionBy = baseRest(function(arrays) {\n var iteratee = last(arrays);\n if (isArrayLikeObject(iteratee)) {\n iteratee = undefined;\n }\n return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));\n });\n\n /**\n * This method is like `_.union` except that it accepts `comparator` which\n * is invoked to compare elements of `arrays`. Result values are chosen from\n * the first array in which the value occurs. The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of combined values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.unionWith(objects, others, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]\n */\n var unionWith = baseRest(function(arrays) {\n var comparator = last(arrays);\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);\n });\n\n /**\n * Creates a duplicate-free version of an array, using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons, in which only the first occurrence of each element\n * is kept. The order of result values is determined by the order they occur\n * in the array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniq([2, 1, 2]);\n * // => [2, 1]\n */\n function uniq(array) {\n return (array && array.length) ? baseUniq(array) : [];\n }\n\n /**\n * This method is like `_.uniq` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * uniqueness is computed. The order of result values is determined by the\n * order they occur in the array. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniqBy([2.1, 1.2, 2.3], Math.floor);\n * // => [2.1, 1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }, { 'x': 2 }]\n */\n function uniqBy(array, iteratee) {\n return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];\n }\n\n /**\n * This method is like `_.uniq` except that it accepts `comparator` which\n * is invoked to compare elements of `array`. The order of result values is\n * determined by the order they occur in the array.The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.uniqWith(objects, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]\n */\n function uniqWith(array, comparator) {\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return (array && array.length) ? baseUniq(array, undefined, comparator) : [];\n }\n\n /**\n * This method is like `_.zip` except that it accepts an array of grouped\n * elements and creates an array regrouping the elements to their pre-zip\n * configuration.\n *\n * @static\n * @memberOf _\n * @since 1.2.0\n * @category Array\n * @param {Array} array The array of grouped elements to process.\n * @returns {Array} Returns the new array of regrouped elements.\n * @example\n *\n * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);\n * // => [['a', 1, true], ['b', 2, false]]\n *\n * _.unzip(zipped);\n * // => [['a', 'b'], [1, 2], [true, false]]\n */\n function unzip(array) {\n if (!(array && array.length)) {\n return [];\n }\n var length = 0;\n array = arrayFilter(array, function(group) {\n if (isArrayLikeObject(group)) {\n length = nativeMax(group.length, length);\n return true;\n }\n });\n return baseTimes(length, function(index) {\n return arrayMap(array, baseProperty(index));\n });\n }\n\n /**\n * This method is like `_.unzip` except that it accepts `iteratee` to specify\n * how regrouped values should be combined. The iteratee is invoked with the\n * elements of each group: (...group).\n *\n * @static\n * @memberOf _\n * @since 3.8.0\n * @category Array\n * @param {Array} array The array of grouped elements to process.\n * @param {Function} [iteratee=_.identity] The function to combine\n * regrouped values.\n * @returns {Array} Returns the new array of regrouped elements.\n * @example\n *\n * var zipped = _.zip([1, 2], [10, 20], [100, 200]);\n * // => [[1, 10, 100], [2, 20, 200]]\n *\n * _.unzipWith(zipped, _.add);\n * // => [3, 30, 300]\n */\n function unzipWith(array, iteratee) {\n if (!(array && array.length)) {\n return [];\n }\n var result = unzip(array);\n if (iteratee == null) {\n return result;\n }\n return arrayMap(result, function(group) {\n return apply(iteratee, undefined, group);\n });\n }\n\n /**\n * Creates an array excluding all given values using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * **Note:** Unlike `_.pull`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...*} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.difference, _.xor\n * @example\n *\n * _.without([2, 1, 2, 3], 1, 2);\n * // => [3]\n */\n var without = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, values)\n : [];\n });\n\n /**\n * Creates an array of unique values that is the\n * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)\n * of the given arrays. The order of result values is determined by the order\n * they occur in the arrays.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.difference, _.without\n * @example\n *\n * _.xor([2, 1], [2, 3]);\n * // => [1, 3]\n */\n var xor = baseRest(function(arrays) {\n return baseXor(arrayFilter(arrays, isArrayLikeObject));\n });\n\n /**\n * This method is like `_.xor` except that it accepts `iteratee` which is\n * invoked for each element of each `arrays` to generate the criterion by\n * which by which they're compared. The order of result values is determined\n * by the order they occur in the arrays. The iteratee is invoked with one\n * argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n * // => [1.2, 3.4]\n *\n * // The `_.property` iteratee shorthand.\n * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 2 }]\n */\n var xorBy = baseRest(function(arrays) {\n var iteratee = last(arrays);\n if (isArrayLikeObject(iteratee)) {\n iteratee = undefined;\n }\n return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));\n });\n\n /**\n * This method is like `_.xor` except that it accepts `comparator` which is\n * invoked to compare elements of `arrays`. The order of result values is\n * determined by the order they occur in the arrays. The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.xorWith(objects, others, _.isEqual);\n * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]\n */\n var xorWith = baseRest(function(arrays) {\n var comparator = last(arrays);\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);\n });\n\n /**\n * Creates an array of grouped elements, the first of which contains the\n * first elements of the given arrays, the second of which contains the\n * second elements of the given arrays, and so on.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to process.\n * @returns {Array} Returns the new array of grouped elements.\n * @example\n *\n * _.zip(['a', 'b'], [1, 2], [true, false]);\n * // => [['a', 1, true], ['b', 2, false]]\n */\n var zip = baseRest(unzip);\n\n /**\n * This method is like `_.fromPairs` except that it accepts two arrays,\n * one of property identifiers and one of corresponding values.\n *\n * @static\n * @memberOf _\n * @since 0.4.0\n * @category Array\n * @param {Array} [props=[]] The property identifiers.\n * @param {Array} [values=[]] The property values.\n * @returns {Object} Returns the new object.\n * @example\n *\n * _.zipObject(['a', 'b'], [1, 2]);\n * // => { 'a': 1, 'b': 2 }\n */\n function zipObject(props, values) {\n return baseZipObject(props || [], values || [], assignValue);\n }\n\n /**\n * This method is like `_.zipObject` except that it supports property paths.\n *\n * @static\n * @memberOf _\n * @since 4.1.0\n * @category Array\n * @param {Array} [props=[]] The property identifiers.\n * @param {Array} [values=[]] The property values.\n * @returns {Object} Returns the new object.\n * @example\n *\n * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);\n * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }\n */\n function zipObjectDeep(props, values) {\n return baseZipObject(props || [], values || [], baseSet);\n }\n\n /**\n * This method is like `_.zip` except that it accepts `iteratee` to specify\n * how grouped values should be combined. The iteratee is invoked with the\n * elements of each group: (...group).\n *\n * @static\n * @memberOf _\n * @since 3.8.0\n * @category Array\n * @param {...Array} [arrays] The arrays to process.\n * @param {Function} [iteratee=_.identity] The function to combine\n * grouped values.\n * @returns {Array} Returns the new array of grouped elements.\n * @example\n *\n * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {\n * return a + b + c;\n * });\n * // => [111, 222]\n */\n var zipWith = baseRest(function(arrays) {\n var length = arrays.length,\n iteratee = length > 1 ? arrays[length - 1] : undefined;\n\n iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;\n return unzipWith(arrays, iteratee);\n });\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a `lodash` wrapper instance that wraps `value` with explicit method\n * chain sequences enabled. The result of such sequences must be unwrapped\n * with `_#value`.\n *\n * @static\n * @memberOf _\n * @since 1.3.0\n * @category Seq\n * @param {*} value The value to wrap.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 40 },\n * { 'user': 'pebbles', 'age': 1 }\n * ];\n *\n * var youngest = _\n * .chain(users)\n * .sortBy('age')\n * .map(function(o) {\n * return o.user + ' is ' + o.age;\n * })\n * .head()\n * .value();\n * // => 'pebbles is 1'\n */\n function chain(value) {\n var result = lodash(value);\n result.__chain__ = true;\n return result;\n }\n\n /**\n * This method invokes `interceptor` and returns `value`. The interceptor\n * is invoked with one argument; (value). The purpose of this method is to\n * \"tap into\" a method chain sequence in order to modify intermediate results.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Seq\n * @param {*} value The value to provide to `interceptor`.\n * @param {Function} interceptor The function to invoke.\n * @returns {*} Returns `value`.\n * @example\n *\n * _([1, 2, 3])\n * .tap(function(array) {\n * // Mutate input array.\n * array.pop();\n * })\n * .reverse()\n * .value();\n * // => [2, 1]\n */\n function tap(value, interceptor) {\n interceptor(value);\n return value;\n }\n\n /**\n * This method is like `_.tap` except that it returns the result of `interceptor`.\n * The purpose of this method is to \"pass thru\" values replacing intermediate\n * results in a method chain sequence.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Seq\n * @param {*} value The value to provide to `interceptor`.\n * @param {Function} interceptor The function to invoke.\n * @returns {*} Returns the result of `interceptor`.\n * @example\n *\n * _(' abc ')\n * .chain()\n * .trim()\n * .thru(function(value) {\n * return [value];\n * })\n * .value();\n * // => ['abc']\n */\n function thru(value, interceptor) {\n return interceptor(value);\n }\n\n /**\n * This method is the wrapper version of `_.at`.\n *\n * @name at\n * @memberOf _\n * @since 1.0.0\n * @category Seq\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };\n *\n * _(object).at(['a[0].b.c', 'a[1]']).value();\n * // => [3, 4]\n */\n var wrapperAt = flatRest(function(paths) {\n var length = paths.length,\n start = length ? paths[0] : 0,\n value = this.__wrapped__,\n interceptor = function(object) { return baseAt(object, paths); };\n\n if (length > 1 || this.__actions__.length ||\n !(value instanceof LazyWrapper) || !isIndex(start)) {\n return this.thru(interceptor);\n }\n value = value.slice(start, +start + (length ? 1 : 0));\n value.__actions__.push({\n 'func': thru,\n 'args': [interceptor],\n 'thisArg': undefined\n });\n return new LodashWrapper(value, this.__chain__).thru(function(array) {\n if (length && !array.length) {\n array.push(undefined);\n }\n return array;\n });\n });\n\n /**\n * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.\n *\n * @name chain\n * @memberOf _\n * @since 0.1.0\n * @category Seq\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 40 }\n * ];\n *\n * // A sequence without explicit chaining.\n * _(users).head();\n * // => { 'user': 'barney', 'age': 36 }\n *\n * // A sequence with explicit chaining.\n * _(users)\n * .chain()\n * .head()\n * .pick('user')\n * .value();\n * // => { 'user': 'barney' }\n */\n function wrapperChain() {\n return chain(this);\n }\n\n /**\n * Executes the chain sequence and returns the wrapped result.\n *\n * @name commit\n * @memberOf _\n * @since 3.2.0\n * @category Seq\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var array = [1, 2];\n * var wrapped = _(array).push(3);\n *\n * console.log(array);\n * // => [1, 2]\n *\n * wrapped = wrapped.commit();\n * console.log(array);\n * // => [1, 2, 3]\n *\n * wrapped.last();\n * // => 3\n *\n * console.log(array);\n * // => [1, 2, 3]\n */\n function wrapperCommit() {\n return new LodashWrapper(this.value(), this.__chain__);\n }\n\n /**\n * Gets the next value on a wrapped object following the\n * [iterator protocol](https://mdn.io/iteration_protocols#iterator).\n *\n * @name next\n * @memberOf _\n * @since 4.0.0\n * @category Seq\n * @returns {Object} Returns the next iterator value.\n * @example\n *\n * var wrapped = _([1, 2]);\n *\n * wrapped.next();\n * // => { 'done': false, 'value': 1 }\n *\n * wrapped.next();\n * // => { 'done': false, 'value': 2 }\n *\n * wrapped.next();\n * // => { 'done': true, 'value': undefined }\n */\n function wrapperNext() {\n if (this.__values__ === undefined) {\n this.__values__ = toArray(this.value());\n }\n var done = this.__index__ >= this.__values__.length,\n value = done ? undefined : this.__values__[this.__index__++];\n\n return { 'done': done, 'value': value };\n }\n\n /**\n * Enables the wrapper to be iterable.\n *\n * @name Symbol.iterator\n * @memberOf _\n * @since 4.0.0\n * @category Seq\n * @returns {Object} Returns the wrapper object.\n * @example\n *\n * var wrapped = _([1, 2]);\n *\n * wrapped[Symbol.iterator]() === wrapped;\n * // => true\n *\n * Array.from(wrapped);\n * // => [1, 2]\n */\n function wrapperToIterator() {\n return this;\n }\n\n /**\n * Creates a clone of the chain sequence planting `value` as the wrapped value.\n *\n * @name plant\n * @memberOf _\n * @since 3.2.0\n * @category Seq\n * @param {*} value The value to plant.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var wrapped = _([1, 2]).map(square);\n * var other = wrapped.plant([3, 4]);\n *\n * other.value();\n * // => [9, 16]\n *\n * wrapped.value();\n * // => [1, 4]\n */\n function wrapperPlant(value) {\n var result,\n parent = this;\n\n while (parent instanceof baseLodash) {\n var clone = wrapperClone(parent);\n clone.__index__ = 0;\n clone.__values__ = undefined;\n if (result) {\n previous.__wrapped__ = clone;\n } else {\n result = clone;\n }\n var previous = clone;\n parent = parent.__wrapped__;\n }\n previous.__wrapped__ = value;\n return result;\n }\n\n /**\n * This method is the wrapper version of `_.reverse`.\n *\n * **Note:** This method mutates the wrapped array.\n *\n * @name reverse\n * @memberOf _\n * @since 0.1.0\n * @category Seq\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var array = [1, 2, 3];\n *\n * _(array).reverse().value()\n * // => [3, 2, 1]\n *\n * console.log(array);\n * // => [3, 2, 1]\n */\n function wrapperReverse() {\n var value = this.__wrapped__;\n if (value instanceof LazyWrapper) {\n var wrapped = value;\n if (this.__actions__.length) {\n wrapped = new LazyWrapper(this);\n }\n wrapped = wrapped.reverse();\n wrapped.__actions__.push({\n 'func': thru,\n 'args': [reverse],\n 'thisArg': undefined\n });\n return new LodashWrapper(wrapped, this.__chain__);\n }\n return this.thru(reverse);\n }\n\n /**\n * Executes the chain sequence to resolve the unwrapped value.\n *\n * @name value\n * @memberOf _\n * @since 0.1.0\n * @alias toJSON, valueOf\n * @category Seq\n * @returns {*} Returns the resolved unwrapped value.\n * @example\n *\n * _([1, 2, 3]).value();\n * // => [1, 2, 3]\n */\n function wrapperValue() {\n return baseWrapperValue(this.__wrapped__, this.__actions__);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The corresponding value of\n * each key is the number of times the key was returned by `iteratee`. The\n * iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * _.countBy([6.1, 4.2, 6.3], Math.floor);\n * // => { '4': 1, '6': 2 }\n *\n * // The `_.property` iteratee shorthand.\n * _.countBy(['one', 'two', 'three'], 'length');\n * // => { '3': 2, '5': 1 }\n */\n var countBy = createAggregator(function(result, value, key) {\n if (hasOwnProperty.call(result, key)) {\n ++result[key];\n } else {\n baseAssignValue(result, key, 1);\n }\n });\n\n /**\n * Checks if `predicate` returns truthy for **all** elements of `collection`.\n * Iteration is stopped once `predicate` returns falsey. The predicate is\n * invoked with three arguments: (value, index|key, collection).\n *\n * **Note:** This method returns `true` for\n * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because\n * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of\n * elements of empty collections.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {boolean} Returns `true` if all elements pass the predicate check,\n * else `false`.\n * @example\n *\n * _.every([true, 1, null, 'yes'], Boolean);\n * // => false\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': false },\n * { 'user': 'fred', 'age': 40, 'active': false }\n * ];\n *\n * // The `_.matches` iteratee shorthand.\n * _.every(users, { 'user': 'barney', 'active': false });\n * // => false\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.every(users, ['active', false]);\n * // => true\n *\n * // The `_.property` iteratee shorthand.\n * _.every(users, 'active');\n * // => false\n */\n function every(collection, predicate, guard) {\n var func = isArray(collection) ? arrayEvery : baseEvery;\n if (guard && isIterateeCall(collection, predicate, guard)) {\n predicate = undefined;\n }\n return func(collection, getIteratee(predicate, 3));\n }\n\n /**\n * Iterates over elements of `collection`, returning an array of all elements\n * `predicate` returns truthy for. The predicate is invoked with three\n * arguments: (value, index|key, collection).\n *\n * **Note:** Unlike `_.remove`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n * @see _.reject\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': true },\n * { 'user': 'fred', 'age': 40, 'active': false }\n * ];\n *\n * _.filter(users, function(o) { return !o.active; });\n * // => objects for ['fred']\n *\n * // The `_.matches` iteratee shorthand.\n * _.filter(users, { 'age': 36, 'active': true });\n * // => objects for ['barney']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.filter(users, ['active', false]);\n * // => objects for ['fred']\n *\n * // The `_.property` iteratee shorthand.\n * _.filter(users, 'active');\n * // => objects for ['barney']\n *\n * // Combining several predicates using `_.overEvery` or `_.overSome`.\n * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));\n * // => objects for ['fred', 'barney']\n */\n function filter(collection, predicate) {\n var func = isArray(collection) ? arrayFilter : baseFilter;\n return func(collection, getIteratee(predicate, 3));\n }\n\n /**\n * Iterates over elements of `collection`, returning the first element\n * `predicate` returns truthy for. The predicate is invoked with three\n * arguments: (value, index|key, collection).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=0] The index to search from.\n * @returns {*} Returns the matched element, else `undefined`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': true },\n * { 'user': 'fred', 'age': 40, 'active': false },\n * { 'user': 'pebbles', 'age': 1, 'active': true }\n * ];\n *\n * _.find(users, function(o) { return o.age < 40; });\n * // => object for 'barney'\n *\n * // The `_.matches` iteratee shorthand.\n * _.find(users, { 'age': 1, 'active': true });\n * // => object for 'pebbles'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.find(users, ['active', false]);\n * // => object for 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.find(users, 'active');\n * // => object for 'barney'\n */\n var find = createFind(findIndex);\n\n /**\n * This method is like `_.find` except that it iterates over elements of\n * `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=collection.length-1] The index to search from.\n * @returns {*} Returns the matched element, else `undefined`.\n * @example\n *\n * _.findLast([1, 2, 3, 4], function(n) {\n * return n % 2 == 1;\n * });\n * // => 3\n */\n var findLast = createFind(findLastIndex);\n\n /**\n * Creates a flattened array of values by running each element in `collection`\n * thru `iteratee` and flattening the mapped results. The iteratee is invoked\n * with three arguments: (value, index|key, collection).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * function duplicate(n) {\n * return [n, n];\n * }\n *\n * _.flatMap([1, 2], duplicate);\n * // => [1, 1, 2, 2]\n */\n function flatMap(collection, iteratee) {\n return baseFlatten(map(collection, iteratee), 1);\n }\n\n /**\n * This method is like `_.flatMap` except that it recursively flattens the\n * mapped results.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * function duplicate(n) {\n * return [[[n, n]]];\n * }\n *\n * _.flatMapDeep([1, 2], duplicate);\n * // => [1, 1, 2, 2]\n */\n function flatMapDeep(collection, iteratee) {\n return baseFlatten(map(collection, iteratee), INFINITY);\n }\n\n /**\n * This method is like `_.flatMap` except that it recursively flattens the\n * mapped results up to `depth` times.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {number} [depth=1] The maximum recursion depth.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * function duplicate(n) {\n * return [[[n, n]]];\n * }\n *\n * _.flatMapDepth([1, 2], duplicate, 2);\n * // => [[1, 1], [2, 2]]\n */\n function flatMapDepth(collection, iteratee, depth) {\n depth = depth === undefined ? 1 : toInteger(depth);\n return baseFlatten(map(collection, iteratee), depth);\n }\n\n /**\n * Iterates over elements of `collection` and invokes `iteratee` for each element.\n * The iteratee is invoked with three arguments: (value, index|key, collection).\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * **Note:** As with other \"Collections\" methods, objects with a \"length\"\n * property are iterated like arrays. To avoid this behavior use `_.forIn`\n * or `_.forOwn` for object iteration.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @alias each\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n * @see _.forEachRight\n * @example\n *\n * _.forEach([1, 2], function(value) {\n * console.log(value);\n * });\n * // => Logs `1` then `2`.\n *\n * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n */\n function forEach(collection, iteratee) {\n var func = isArray(collection) ? arrayEach : baseEach;\n return func(collection, getIteratee(iteratee, 3));\n }\n\n /**\n * This method is like `_.forEach` except that it iterates over elements of\n * `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @alias eachRight\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n * @see _.forEach\n * @example\n *\n * _.forEachRight([1, 2], function(value) {\n * console.log(value);\n * });\n * // => Logs `2` then `1`.\n */\n function forEachRight(collection, iteratee) {\n var func = isArray(collection) ? arrayEachRight : baseEachRight;\n return func(collection, getIteratee(iteratee, 3));\n }\n\n /**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The order of grouped values\n * is determined by the order they occur in `collection`. The corresponding\n * value of each key is an array of elements responsible for generating the\n * key. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * _.groupBy([6.1, 4.2, 6.3], Math.floor);\n * // => { '4': [4.2], '6': [6.1, 6.3] }\n *\n * // The `_.property` iteratee shorthand.\n * _.groupBy(['one', 'two', 'three'], 'length');\n * // => { '3': ['one', 'two'], '5': ['three'] }\n */\n var groupBy = createAggregator(function(result, value, key) {\n if (hasOwnProperty.call(result, key)) {\n result[key].push(value);\n } else {\n baseAssignValue(result, key, [value]);\n }\n });\n\n /**\n * Checks if `value` is in `collection`. If `collection` is a string, it's\n * checked for a substring of `value`, otherwise\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * is used for equality comparisons. If `fromIndex` is negative, it's used as\n * the offset from the end of `collection`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object|string} collection The collection to inspect.\n * @param {*} value The value to search for.\n * @param {number} [fromIndex=0] The index to search from.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.\n * @returns {boolean} Returns `true` if `value` is found, else `false`.\n * @example\n *\n * _.includes([1, 2, 3], 1);\n * // => true\n *\n * _.includes([1, 2, 3], 1, 2);\n * // => false\n *\n * _.includes({ 'a': 1, 'b': 2 }, 1);\n * // => true\n *\n * _.includes('abcd', 'bc');\n * // => true\n */\n function includes(collection, value, fromIndex, guard) {\n collection = isArrayLike(collection) ? collection : values(collection);\n fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;\n\n var length = collection.length;\n if (fromIndex < 0) {\n fromIndex = nativeMax(length + fromIndex, 0);\n }\n return isString(collection)\n ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)\n : (!!length && baseIndexOf(collection, value, fromIndex) > -1);\n }\n\n /**\n * Invokes the method at `path` of each element in `collection`, returning\n * an array of the results of each invoked method. Any additional arguments\n * are provided to each invoked method. If `path` is a function, it's invoked\n * for, and `this` bound to, each element in `collection`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Array|Function|string} path The path of the method to invoke or\n * the function invoked per iteration.\n * @param {...*} [args] The arguments to invoke each method with.\n * @returns {Array} Returns the array of results.\n * @example\n *\n * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');\n * // => [[1, 5, 7], [1, 2, 3]]\n *\n * _.invokeMap([123, 456], String.prototype.split, '');\n * // => [['1', '2', '3'], ['4', '5', '6']]\n */\n var invokeMap = baseRest(function(collection, path, args) {\n var index = -1,\n isFunc = typeof path == 'function',\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value) {\n result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);\n });\n return result;\n });\n\n /**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The corresponding value of\n * each key is the last element responsible for generating the key. The\n * iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * var array = [\n * { 'dir': 'left', 'code': 97 },\n * { 'dir': 'right', 'code': 100 }\n * ];\n *\n * _.keyBy(array, function(o) {\n * return String.fromCharCode(o.code);\n * });\n * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }\n *\n * _.keyBy(array, 'dir');\n * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }\n */\n var keyBy = createAggregator(function(result, value, key) {\n baseAssignValue(result, key, value);\n });\n\n /**\n * Creates an array of values by running each element in `collection` thru\n * `iteratee`. The iteratee is invoked with three arguments:\n * (value, index|key, collection).\n *\n * Many lodash methods are guarded to work as iteratees for methods like\n * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.\n *\n * The guarded methods are:\n * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,\n * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,\n * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,\n * `template`, `trim`, `trimEnd`, `trimStart`, and `words`\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * _.map([4, 8], square);\n * // => [16, 64]\n *\n * _.map({ 'a': 4, 'b': 8 }, square);\n * // => [16, 64] (iteration order is not guaranteed)\n *\n * var users = [\n * { 'user': 'barney' },\n * { 'user': 'fred' }\n * ];\n *\n * // The `_.property` iteratee shorthand.\n * _.map(users, 'user');\n * // => ['barney', 'fred']\n */\n function map(collection, iteratee) {\n var func = isArray(collection) ? arrayMap : baseMap;\n return func(collection, getIteratee(iteratee, 3));\n }\n\n /**\n * This method is like `_.sortBy` except that it allows specifying the sort\n * orders of the iteratees to sort by. If `orders` is unspecified, all values\n * are sorted in ascending order. Otherwise, specify an order of \"desc\" for\n * descending or \"asc\" for ascending sort order of corresponding values.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @param {string[]} [orders] The sort orders of `iteratees`.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 34 },\n * { 'user': 'fred', 'age': 40 },\n * { 'user': 'barney', 'age': 36 }\n * ];\n *\n * // Sort by `user` in ascending order and by `age` in descending order.\n * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]\n */\n function orderBy(collection, iteratees, orders, guard) {\n if (collection == null) {\n return [];\n }\n if (!isArray(iteratees)) {\n iteratees = iteratees == null ? [] : [iteratees];\n }\n orders = guard ? undefined : orders;\n if (!isArray(orders)) {\n orders = orders == null ? [] : [orders];\n }\n return baseOrderBy(collection, iteratees, orders);\n }\n\n /**\n * Creates an array of elements split into two groups, the first of which\n * contains elements `predicate` returns truthy for, the second of which\n * contains elements `predicate` returns falsey for. The predicate is\n * invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the array of grouped elements.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': false },\n * { 'user': 'fred', 'age': 40, 'active': true },\n * { 'user': 'pebbles', 'age': 1, 'active': false }\n * ];\n *\n * _.partition(users, function(o) { return o.active; });\n * // => objects for [['fred'], ['barney', 'pebbles']]\n *\n * // The `_.matches` iteratee shorthand.\n * _.partition(users, { 'age': 1, 'active': false });\n * // => objects for [['pebbles'], ['barney', 'fred']]\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.partition(users, ['active', false]);\n * // => objects for [['barney', 'pebbles'], ['fred']]\n *\n * // The `_.property` iteratee shorthand.\n * _.partition(users, 'active');\n * // => objects for [['fred'], ['barney', 'pebbles']]\n */\n var partition = createAggregator(function(result, value, key) {\n result[key ? 0 : 1].push(value);\n }, function() { return [[], []]; });\n\n /**\n * Reduces `collection` to a value which is the accumulated result of running\n * each element in `collection` thru `iteratee`, where each successive\n * invocation is supplied the return value of the previous. If `accumulator`\n * is not given, the first element of `collection` is used as the initial\n * value. The iteratee is invoked with four arguments:\n * (accumulator, value, index|key, collection).\n *\n * Many lodash methods are guarded to work as iteratees for methods like\n * `_.reduce`, `_.reduceRight`, and `_.transform`.\n *\n * The guarded methods are:\n * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,\n * and `sortBy`\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @returns {*} Returns the accumulated value.\n * @see _.reduceRight\n * @example\n *\n * _.reduce([1, 2], function(sum, n) {\n * return sum + n;\n * }, 0);\n * // => 3\n *\n * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {\n * (result[value] || (result[value] = [])).push(key);\n * return result;\n * }, {});\n * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)\n */\n function reduce(collection, iteratee, accumulator) {\n var func = isArray(collection) ? arrayReduce : baseReduce,\n initAccum = arguments.length < 3;\n\n return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);\n }\n\n /**\n * This method is like `_.reduce` except that it iterates over elements of\n * `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @returns {*} Returns the accumulated value.\n * @see _.reduce\n * @example\n *\n * var array = [[0, 1], [2, 3], [4, 5]];\n *\n * _.reduceRight(array, function(flattened, other) {\n * return flattened.concat(other);\n * }, []);\n * // => [4, 5, 2, 3, 0, 1]\n */\n function reduceRight(collection, iteratee, accumulator) {\n var func = isArray(collection) ? arrayReduceRight : baseReduce,\n initAccum = arguments.length < 3;\n\n return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);\n }\n\n /**\n * The opposite of `_.filter`; this method returns the elements of `collection`\n * that `predicate` does **not** return truthy for.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n * @see _.filter\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': false },\n * { 'user': 'fred', 'age': 40, 'active': true }\n * ];\n *\n * _.reject(users, function(o) { return !o.active; });\n * // => objects for ['fred']\n *\n * // The `_.matches` iteratee shorthand.\n * _.reject(users, { 'age': 40, 'active': true });\n * // => objects for ['barney']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.reject(users, ['active', false]);\n * // => objects for ['fred']\n *\n * // The `_.property` iteratee shorthand.\n * _.reject(users, 'active');\n * // => objects for ['barney']\n */\n function reject(collection, predicate) {\n var func = isArray(collection) ? arrayFilter : baseFilter;\n return func(collection, negate(getIteratee(predicate, 3)));\n }\n\n /**\n * Gets a random element from `collection`.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to sample.\n * @returns {*} Returns the random element.\n * @example\n *\n * _.sample([1, 2, 3, 4]);\n * // => 2\n */\n function sample(collection) {\n var func = isArray(collection) ? arraySample : baseSample;\n return func(collection);\n }\n\n /**\n * Gets `n` random elements at unique keys from `collection` up to the\n * size of `collection`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to sample.\n * @param {number} [n=1] The number of elements to sample.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the random elements.\n * @example\n *\n * _.sampleSize([1, 2, 3], 2);\n * // => [3, 1]\n *\n * _.sampleSize([1, 2, 3], 4);\n * // => [2, 3, 1]\n */\n function sampleSize(collection, n, guard) {\n if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {\n n = 1;\n } else {\n n = toInteger(n);\n }\n var func = isArray(collection) ? arraySampleSize : baseSampleSize;\n return func(collection, n);\n }\n\n /**\n * Creates an array of shuffled values, using a version of the\n * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to shuffle.\n * @returns {Array} Returns the new shuffled array.\n * @example\n *\n * _.shuffle([1, 2, 3, 4]);\n * // => [4, 1, 3, 2]\n */\n function shuffle(collection) {\n var func = isArray(collection) ? arrayShuffle : baseShuffle;\n return func(collection);\n }\n\n /**\n * Gets the size of `collection` by returning its length for array-like\n * values or the number of own enumerable string keyed properties for objects.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object|string} collection The collection to inspect.\n * @returns {number} Returns the collection size.\n * @example\n *\n * _.size([1, 2, 3]);\n * // => 3\n *\n * _.size({ 'a': 1, 'b': 2 });\n * // => 2\n *\n * _.size('pebbles');\n * // => 7\n */\n function size(collection) {\n if (collection == null) {\n return 0;\n }\n if (isArrayLike(collection)) {\n return isString(collection) ? stringSize(collection) : collection.length;\n }\n var tag = getTag(collection);\n if (tag == mapTag || tag == setTag) {\n return collection.size;\n }\n return baseKeys(collection).length;\n }\n\n /**\n * Checks if `predicate` returns truthy for **any** element of `collection`.\n * Iteration is stopped once `predicate` returns truthy. The predicate is\n * invoked with three arguments: (value, index|key, collection).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n * @example\n *\n * _.some([null, 0, 'yes', false], Boolean);\n * // => true\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false }\n * ];\n *\n * // The `_.matches` iteratee shorthand.\n * _.some(users, { 'user': 'barney', 'active': false });\n * // => false\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.some(users, ['active', false]);\n * // => true\n *\n * // The `_.property` iteratee shorthand.\n * _.some(users, 'active');\n * // => true\n */\n function some(collection, predicate, guard) {\n var func = isArray(collection) ? arraySome : baseSome;\n if (guard && isIterateeCall(collection, predicate, guard)) {\n predicate = undefined;\n }\n return func(collection, getIteratee(predicate, 3));\n }\n\n /**\n * Creates an array of elements, sorted in ascending order by the results of\n * running each element in a collection thru each iteratee. This method\n * performs a stable sort, that is, it preserves the original sort order of\n * equal elements. The iteratees are invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 30 },\n * { 'user': 'barney', 'age': 34 }\n * ];\n *\n * _.sortBy(users, [function(o) { return o.user; }]);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]\n *\n * _.sortBy(users, ['user', 'age']);\n * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]\n */\n var sortBy = baseRest(function(collection, iteratees) {\n if (collection == null) {\n return [];\n }\n var length = iteratees.length;\n if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n iteratees = [];\n } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n iteratees = [iteratees[0]];\n }\n return baseOrderBy(collection, baseFlatten(iteratees, 1), []);\n });\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\n var now = ctxNow || function() {\n return root.Date.now();\n };\n\n /*------------------------------------------------------------------------*/\n\n /**\n * The opposite of `_.before`; this method creates a function that invokes\n * `func` once it's called `n` or more times.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {number} n The number of calls before `func` is invoked.\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new restricted function.\n * @example\n *\n * var saves = ['profile', 'settings'];\n *\n * var done = _.after(saves.length, function() {\n * console.log('done saving!');\n * });\n *\n * _.forEach(saves, function(type) {\n * asyncSave({ 'type': type, 'complete': done });\n * });\n * // => Logs 'done saving!' after the two async saves have completed.\n */\n function after(n, func) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n n = toInteger(n);\n return function() {\n if (--n < 1) {\n return func.apply(this, arguments);\n }\n };\n }\n\n /**\n * Creates a function that invokes `func`, with up to `n` arguments,\n * ignoring any additional arguments.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} func The function to cap arguments for.\n * @param {number} [n=func.length] The arity cap.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the new capped function.\n * @example\n *\n * _.map(['6', '8', '10'], _.ary(parseInt, 1));\n * // => [6, 8, 10]\n */\n function ary(func, n, guard) {\n n = guard ? undefined : n;\n n = (func && n == null) ? func.length : n;\n return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);\n }\n\n /**\n * Creates a function that invokes `func`, with the `this` binding and arguments\n * of the created function, while it's called less than `n` times. Subsequent\n * calls to the created function return the result of the last `func` invocation.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {number} n The number of calls at which `func` is no longer invoked.\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new restricted function.\n * @example\n *\n * jQuery(element).on('click', _.before(5, addContactToList));\n * // => Allows adding up to 4 contacts to the list.\n */\n function before(n, func) {\n var result;\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n n = toInteger(n);\n return function() {\n if (--n > 0) {\n result = func.apply(this, arguments);\n }\n if (n <= 1) {\n func = undefined;\n }\n return result;\n };\n }\n\n /**\n * Creates a function that invokes `func` with the `this` binding of `thisArg`\n * and `partials` prepended to the arguments it receives.\n *\n * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,\n * may be used as a placeholder for partially applied arguments.\n *\n * **Note:** Unlike native `Function#bind`, this method doesn't set the \"length\"\n * property of bound functions.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to bind.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new bound function.\n * @example\n *\n * function greet(greeting, punctuation) {\n * return greeting + ' ' + this.user + punctuation;\n * }\n *\n * var object = { 'user': 'fred' };\n *\n * var bound = _.bind(greet, object, 'hi');\n * bound('!');\n * // => 'hi fred!'\n *\n * // Bound with placeholders.\n * var bound = _.bind(greet, object, _, '!');\n * bound('hi');\n * // => 'hi fred!'\n */\n var bind = baseRest(function(func, thisArg, partials) {\n var bitmask = WRAP_BIND_FLAG;\n if (partials.length) {\n var holders = replaceHolders(partials, getHolder(bind));\n bitmask |= WRAP_PARTIAL_FLAG;\n }\n return createWrap(func, bitmask, thisArg, partials, holders);\n });\n\n /**\n * Creates a function that invokes the method at `object[key]` with `partials`\n * prepended to the arguments it receives.\n *\n * This method differs from `_.bind` by allowing bound functions to reference\n * methods that may be redefined or don't yet exist. See\n * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)\n * for more details.\n *\n * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for partially applied arguments.\n *\n * @static\n * @memberOf _\n * @since 0.10.0\n * @category Function\n * @param {Object} object The object to invoke the method on.\n * @param {string} key The key of the method.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new bound function.\n * @example\n *\n * var object = {\n * 'user': 'fred',\n * 'greet': function(greeting, punctuation) {\n * return greeting + ' ' + this.user + punctuation;\n * }\n * };\n *\n * var bound = _.bindKey(object, 'greet', 'hi');\n * bound('!');\n * // => 'hi fred!'\n *\n * object.greet = function(greeting, punctuation) {\n * return greeting + 'ya ' + this.user + punctuation;\n * };\n *\n * bound('!');\n * // => 'hiya fred!'\n *\n * // Bound with placeholders.\n * var bound = _.bindKey(object, 'greet', _, '!');\n * bound('hi');\n * // => 'hiya fred!'\n */\n var bindKey = baseRest(function(object, key, partials) {\n var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;\n if (partials.length) {\n var holders = replaceHolders(partials, getHolder(bindKey));\n bitmask |= WRAP_PARTIAL_FLAG;\n }\n return createWrap(key, bitmask, object, partials, holders);\n });\n\n /**\n * Creates a function that accepts arguments of `func` and either invokes\n * `func` returning its result, if at least `arity` number of arguments have\n * been provided, or returns a function that accepts the remaining `func`\n * arguments, and so on. The arity of `func` may be specified if `func.length`\n * is not sufficient.\n *\n * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,\n * may be used as a placeholder for provided arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of curried functions.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Function\n * @param {Function} func The function to curry.\n * @param {number} [arity=func.length] The arity of `func`.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the new curried function.\n * @example\n *\n * var abc = function(a, b, c) {\n * return [a, b, c];\n * };\n *\n * var curried = _.curry(abc);\n *\n * curried(1)(2)(3);\n * // => [1, 2, 3]\n *\n * curried(1, 2)(3);\n * // => [1, 2, 3]\n *\n * curried(1, 2, 3);\n * // => [1, 2, 3]\n *\n * // Curried with placeholders.\n * curried(1)(_, 3)(2);\n * // => [1, 2, 3]\n */\n function curry(func, arity, guard) {\n arity = guard ? undefined : arity;\n var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);\n result.placeholder = curry.placeholder;\n return result;\n }\n\n /**\n * This method is like `_.curry` except that arguments are applied to `func`\n * in the manner of `_.partialRight` instead of `_.partial`.\n *\n * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for provided arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of curried functions.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} func The function to curry.\n * @param {number} [arity=func.length] The arity of `func`.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the new curried function.\n * @example\n *\n * var abc = function(a, b, c) {\n * return [a, b, c];\n * };\n *\n * var curried = _.curryRight(abc);\n *\n * curried(3)(2)(1);\n * // => [1, 2, 3]\n *\n * curried(2, 3)(1);\n * // => [1, 2, 3]\n *\n * curried(1, 2, 3);\n * // => [1, 2, 3]\n *\n * // Curried with placeholders.\n * curried(3)(1, _)(2);\n * // => [1, 2, 3]\n */\n function curryRight(func, arity, guard) {\n arity = guard ? undefined : arity;\n var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);\n result.placeholder = curryRight.placeholder;\n return result;\n }\n\n /**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\n function debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n timeWaiting = wait - timeSinceLastCall;\n\n return maxing\n ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n clearTimeout(timerId);\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n }\n\n /**\n * Defers invoking the `func` until the current call stack has cleared. Any\n * additional arguments are provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to defer.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {number} Returns the timer id.\n * @example\n *\n * _.defer(function(text) {\n * console.log(text);\n * }, 'deferred');\n * // => Logs 'deferred' after one millisecond.\n */\n var defer = baseRest(function(func, args) {\n return baseDelay(func, 1, args);\n });\n\n /**\n * Invokes `func` after `wait` milliseconds. Any additional arguments are\n * provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {number} Returns the timer id.\n * @example\n *\n * _.delay(function(text) {\n * console.log(text);\n * }, 1000, 'later');\n * // => Logs 'later' after one second.\n */\n var delay = baseRest(function(func, wait, args) {\n return baseDelay(func, toNumber(wait) || 0, args);\n });\n\n /**\n * Creates a function that invokes `func` with arguments reversed.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Function\n * @param {Function} func The function to flip arguments for.\n * @returns {Function} Returns the new flipped function.\n * @example\n *\n * var flipped = _.flip(function() {\n * return _.toArray(arguments);\n * });\n *\n * flipped('a', 'b', 'c', 'd');\n * // => ['d', 'c', 'b', 'a']\n */\n function flip(func) {\n return createWrap(func, WRAP_FLIP_FLAG);\n }\n\n /**\n * Creates a function that memoizes the result of `func`. If `resolver` is\n * provided, it determines the cache key for storing the result based on the\n * arguments provided to the memoized function. By default, the first argument\n * provided to the memoized function is used as the map cache key. The `func`\n * is invoked with the `this` binding of the memoized function.\n *\n * **Note:** The cache is exposed as the `cache` property on the memoized\n * function. Its creation may be customized by replacing the `_.memoize.Cache`\n * constructor with one whose instances implement the\n * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to have its output memoized.\n * @param {Function} [resolver] The function to resolve the cache key.\n * @returns {Function} Returns the new memoized function.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n * var other = { 'c': 3, 'd': 4 };\n *\n * var values = _.memoize(_.values);\n * values(object);\n * // => [1, 2]\n *\n * values(other);\n * // => [3, 4]\n *\n * object.a = 2;\n * values(object);\n * // => [1, 2]\n *\n * // Modify the result cache.\n * values.cache.set(object, ['a', 'b']);\n * values(object);\n * // => ['a', 'b']\n *\n * // Replace `_.memoize.Cache`.\n * _.memoize.Cache = WeakMap;\n */\n function memoize(func, resolver) {\n if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var memoized = function() {\n var args = arguments,\n key = resolver ? resolver.apply(this, args) : args[0],\n cache = memoized.cache;\n\n if (cache.has(key)) {\n return cache.get(key);\n }\n var result = func.apply(this, args);\n memoized.cache = cache.set(key, result) || cache;\n return result;\n };\n memoized.cache = new (memoize.Cache || MapCache);\n return memoized;\n }\n\n // Expose `MapCache`.\n memoize.Cache = MapCache;\n\n /**\n * Creates a function that negates the result of the predicate `func`. The\n * `func` predicate is invoked with the `this` binding and arguments of the\n * created function.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} predicate The predicate to negate.\n * @returns {Function} Returns the new negated function.\n * @example\n *\n * function isEven(n) {\n * return n % 2 == 0;\n * }\n *\n * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));\n * // => [1, 3, 5]\n */\n function negate(predicate) {\n if (typeof predicate != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return function() {\n var args = arguments;\n switch (args.length) {\n case 0: return !predicate.call(this);\n case 1: return !predicate.call(this, args[0]);\n case 2: return !predicate.call(this, args[0], args[1]);\n case 3: return !predicate.call(this, args[0], args[1], args[2]);\n }\n return !predicate.apply(this, args);\n };\n }\n\n /**\n * Creates a function that is restricted to invoking `func` once. Repeat calls\n * to the function return the value of the first invocation. The `func` is\n * invoked with the `this` binding and arguments of the created function.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new restricted function.\n * @example\n *\n * var initialize = _.once(createApplication);\n * initialize();\n * initialize();\n * // => `createApplication` is invoked once\n */\n function once(func) {\n return before(2, func);\n }\n\n /**\n * Creates a function that invokes `func` with its arguments transformed.\n *\n * @static\n * @since 4.0.0\n * @memberOf _\n * @category Function\n * @param {Function} func The function to wrap.\n * @param {...(Function|Function[])} [transforms=[_.identity]]\n * The argument transforms.\n * @returns {Function} Returns the new function.\n * @example\n *\n * function doubled(n) {\n * return n * 2;\n * }\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var func = _.overArgs(function(x, y) {\n * return [x, y];\n * }, [square, doubled]);\n *\n * func(9, 3);\n * // => [81, 6]\n *\n * func(10, 5);\n * // => [100, 10]\n */\n var overArgs = castRest(function(func, transforms) {\n transforms = (transforms.length == 1 && isArray(transforms[0]))\n ? arrayMap(transforms[0], baseUnary(getIteratee()))\n : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));\n\n var funcsLength = transforms.length;\n return baseRest(function(args) {\n var index = -1,\n length = nativeMin(args.length, funcsLength);\n\n while (++index < length) {\n args[index] = transforms[index].call(this, args[index]);\n }\n return apply(func, this, args);\n });\n });\n\n /**\n * Creates a function that invokes `func` with `partials` prepended to the\n * arguments it receives. This method is like `_.bind` except it does **not**\n * alter the `this` binding.\n *\n * The `_.partial.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for partially applied arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of partially\n * applied functions.\n *\n * @static\n * @memberOf _\n * @since 0.2.0\n * @category Function\n * @param {Function} func The function to partially apply arguments to.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new partially applied function.\n * @example\n *\n * function greet(greeting, name) {\n * return greeting + ' ' + name;\n * }\n *\n * var sayHelloTo = _.partial(greet, 'hello');\n * sayHelloTo('fred');\n * // => 'hello fred'\n *\n * // Partially applied with placeholders.\n * var greetFred = _.partial(greet, _, 'fred');\n * greetFred('hi');\n * // => 'hi fred'\n */\n var partial = baseRest(function(func, partials) {\n var holders = replaceHolders(partials, getHolder(partial));\n return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);\n });\n\n /**\n * This method is like `_.partial` except that partially applied arguments\n * are appended to the arguments it receives.\n *\n * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for partially applied arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of partially\n * applied functions.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Function\n * @param {Function} func The function to partially apply arguments to.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new partially applied function.\n * @example\n *\n * function greet(greeting, name) {\n * return greeting + ' ' + name;\n * }\n *\n * var greetFred = _.partialRight(greet, 'fred');\n * greetFred('hi');\n * // => 'hi fred'\n *\n * // Partially applied with placeholders.\n * var sayHelloTo = _.partialRight(greet, 'hello', _);\n * sayHelloTo('fred');\n * // => 'hello fred'\n */\n var partialRight = baseRest(function(func, partials) {\n var holders = replaceHolders(partials, getHolder(partialRight));\n return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);\n });\n\n /**\n * Creates a function that invokes `func` with arguments arranged according\n * to the specified `indexes` where the argument value at the first index is\n * provided as the first argument, the argument value at the second index is\n * provided as the second argument, and so on.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} func The function to rearrange arguments for.\n * @param {...(number|number[])} indexes The arranged argument indexes.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var rearged = _.rearg(function(a, b, c) {\n * return [a, b, c];\n * }, [2, 0, 1]);\n *\n * rearged('b', 'c', 'a')\n * // => ['a', 'b', 'c']\n */\n var rearg = flatRest(function(func, indexes) {\n return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);\n });\n\n /**\n * Creates a function that invokes `func` with the `this` binding of the\n * created function and arguments from `start` and beyond provided as\n * an array.\n *\n * **Note:** This method is based on the\n * [rest parameter](https://mdn.io/rest_parameters).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Function\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var say = _.rest(function(what, names) {\n * return what + ' ' + _.initial(names).join(', ') +\n * (_.size(names) > 1 ? ', & ' : '') + _.last(names);\n * });\n *\n * say('hello', 'fred', 'barney', 'pebbles');\n * // => 'hello fred, barney, & pebbles'\n */\n function rest(func, start) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n start = start === undefined ? start : toInteger(start);\n return baseRest(func, start);\n }\n\n /**\n * Creates a function that invokes `func` with the `this` binding of the\n * create function and an array of arguments much like\n * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).\n *\n * **Note:** This method is based on the\n * [spread operator](https://mdn.io/spread_operator).\n *\n * @static\n * @memberOf _\n * @since 3.2.0\n * @category Function\n * @param {Function} func The function to spread arguments over.\n * @param {number} [start=0] The start position of the spread.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var say = _.spread(function(who, what) {\n * return who + ' says ' + what;\n * });\n *\n * say(['fred', 'hello']);\n * // => 'fred says hello'\n *\n * var numbers = Promise.all([\n * Promise.resolve(40),\n * Promise.resolve(36)\n * ]);\n *\n * numbers.then(_.spread(function(x, y) {\n * return x + y;\n * }));\n * // => a Promise of 76\n */\n function spread(func, start) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n start = start == null ? 0 : nativeMax(toInteger(start), 0);\n return baseRest(function(args) {\n var array = args[start],\n otherArgs = castSlice(args, 0, start);\n\n if (array) {\n arrayPush(otherArgs, array);\n }\n return apply(func, this, otherArgs);\n });\n }\n\n /**\n * Creates a throttled function that only invokes `func` at most once per\n * every `wait` milliseconds. The throttled function comes with a `cancel`\n * method to cancel delayed `func` invocations and a `flush` method to\n * immediately invoke them. Provide `options` to indicate whether `func`\n * should be invoked on the leading and/or trailing edge of the `wait`\n * timeout. The `func` is invoked with the last arguments provided to the\n * throttled function. Subsequent calls to the throttled function return the\n * result of the last `func` invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the throttled function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.throttle` and `_.debounce`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to throttle.\n * @param {number} [wait=0] The number of milliseconds to throttle invocations to.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=true]\n * Specify invoking on the leading edge of the timeout.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new throttled function.\n * @example\n *\n * // Avoid excessively updating the position while scrolling.\n * jQuery(window).on('scroll', _.throttle(updatePosition, 100));\n *\n * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.\n * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });\n * jQuery(element).on('click', throttled);\n *\n * // Cancel the trailing throttled invocation.\n * jQuery(window).on('popstate', throttled.cancel);\n */\n function throttle(func, wait, options) {\n var leading = true,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n if (isObject(options)) {\n leading = 'leading' in options ? !!options.leading : leading;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n return debounce(func, wait, {\n 'leading': leading,\n 'maxWait': wait,\n 'trailing': trailing\n });\n }\n\n /**\n * Creates a function that accepts up to one argument, ignoring any\n * additional arguments.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Function\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n * @example\n *\n * _.map(['6', '8', '10'], _.unary(parseInt));\n * // => [6, 8, 10]\n */\n function unary(func) {\n return ary(func, 1);\n }\n\n /**\n * Creates a function that provides `value` to `wrapper` as its first\n * argument. Any additional arguments provided to the function are appended\n * to those provided to the `wrapper`. The wrapper is invoked with the `this`\n * binding of the created function.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {*} value The value to wrap.\n * @param {Function} [wrapper=identity] The wrapper function.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var p = _.wrap(_.escape, function(func, text) {\n * return '<p>' + func(text) + '</p>';\n * });\n *\n * p('fred, barney, & pebbles');\n * // => '<p>fred, barney, &amp; pebbles</p>'\n */\n function wrap(value, wrapper) {\n return partial(castFunction(wrapper), value);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Casts `value` as an array if it's not one.\n *\n * @static\n * @memberOf _\n * @since 4.4.0\n * @category Lang\n * @param {*} value The value to inspect.\n * @returns {Array} Returns the cast array.\n * @example\n *\n * _.castArray(1);\n * // => [1]\n *\n * _.castArray({ 'a': 1 });\n * // => [{ 'a': 1 }]\n *\n * _.castArray('abc');\n * // => ['abc']\n *\n * _.castArray(null);\n * // => [null]\n *\n * _.castArray(undefined);\n * // => [undefined]\n *\n * _.castArray();\n * // => []\n *\n * var array = [1, 2, 3];\n * console.log(_.castArray(array) === array);\n * // => true\n */\n function castArray() {\n if (!arguments.length) {\n return [];\n }\n var value = arguments[0];\n return isArray(value) ? value : [value];\n }\n\n /**\n * Creates a shallow clone of `value`.\n *\n * **Note:** This method is loosely based on the\n * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)\n * and supports cloning arrays, array buffers, booleans, date objects, maps,\n * numbers, `Object` objects, regexes, sets, strings, symbols, and typed\n * arrays. The own enumerable properties of `arguments` objects are cloned\n * as plain objects. An empty object is returned for uncloneable values such\n * as error objects, functions, DOM nodes, and WeakMaps.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to clone.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeep\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var shallow = _.clone(objects);\n * console.log(shallow[0] === objects[0]);\n * // => true\n */\n function clone(value) {\n return baseClone(value, CLONE_SYMBOLS_FLAG);\n }\n\n /**\n * This method is like `_.clone` except that it accepts `customizer` which\n * is invoked to produce the cloned value. If `customizer` returns `undefined`,\n * cloning is handled by the method instead. The `customizer` is invoked with\n * up to four arguments; (value [, index|key, object, stack]).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to clone.\n * @param {Function} [customizer] The function to customize cloning.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeepWith\n * @example\n *\n * function customizer(value) {\n * if (_.isElement(value)) {\n * return value.cloneNode(false);\n * }\n * }\n *\n * var el = _.cloneWith(document.body, customizer);\n *\n * console.log(el === document.body);\n * // => false\n * console.log(el.nodeName);\n * // => 'BODY'\n * console.log(el.childNodes.length);\n * // => 0\n */\n function cloneWith(value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);\n }\n\n /**\n * This method is like `_.clone` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @returns {*} Returns the deep cloned value.\n * @see _.clone\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var deep = _.cloneDeep(objects);\n * console.log(deep[0] === objects[0]);\n * // => false\n */\n function cloneDeep(value) {\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n }\n\n /**\n * This method is like `_.cloneWith` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @param {Function} [customizer] The function to customize cloning.\n * @returns {*} Returns the deep cloned value.\n * @see _.cloneWith\n * @example\n *\n * function customizer(value) {\n * if (_.isElement(value)) {\n * return value.cloneNode(true);\n * }\n * }\n *\n * var el = _.cloneDeepWith(document.body, customizer);\n *\n * console.log(el === document.body);\n * // => false\n * console.log(el.nodeName);\n * // => 'BODY'\n * console.log(el.childNodes.length);\n * // => 20\n */\n function cloneDeepWith(value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);\n }\n\n /**\n * Checks if `object` conforms to `source` by invoking the predicate\n * properties of `source` with the corresponding property values of `object`.\n *\n * **Note:** This method is equivalent to `_.conforms` when `source` is\n * partially applied.\n *\n * @static\n * @memberOf _\n * @since 4.14.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property predicates to conform to.\n * @returns {boolean} Returns `true` if `object` conforms, else `false`.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n *\n * _.conformsTo(object, { 'b': function(n) { return n > 1; } });\n * // => true\n *\n * _.conformsTo(object, { 'b': function(n) { return n > 2; } });\n * // => false\n */\n function conformsTo(object, source) {\n return source == null || baseConformsTo(object, source, keys(source));\n }\n\n /**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\n function eq(value, other) {\n return value === other || (value !== value && other !== other);\n }\n\n /**\n * Checks if `value` is greater than `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than `other`,\n * else `false`.\n * @see _.lt\n * @example\n *\n * _.gt(3, 1);\n * // => true\n *\n * _.gt(3, 3);\n * // => false\n *\n * _.gt(1, 3);\n * // => false\n */\n var gt = createRelationalOperation(baseGt);\n\n /**\n * Checks if `value` is greater than or equal to `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than or equal to\n * `other`, else `false`.\n * @see _.lte\n * @example\n *\n * _.gte(3, 1);\n * // => true\n *\n * _.gte(3, 3);\n * // => true\n *\n * _.gte(1, 3);\n * // => false\n */\n var gte = createRelationalOperation(function(value, other) {\n return value >= other;\n });\n\n /**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\n var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n };\n\n /**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\n var isArray = Array.isArray;\n\n /**\n * Checks if `value` is classified as an `ArrayBuffer` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.\n * @example\n *\n * _.isArrayBuffer(new ArrayBuffer(2));\n * // => true\n *\n * _.isArrayBuffer(new Array(2));\n * // => false\n */\n var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;\n\n /**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\n function isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n }\n\n /**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\n function isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n }\n\n /**\n * Checks if `value` is classified as a boolean primitive or object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.\n * @example\n *\n * _.isBoolean(false);\n * // => true\n *\n * _.isBoolean(null);\n * // => false\n */\n function isBoolean(value) {\n return value === true || value === false ||\n (isObjectLike(value) && baseGetTag(value) == boolTag);\n }\n\n /**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\n var isBuffer = nativeIsBuffer || stubFalse;\n\n /**\n * Checks if `value` is classified as a `Date` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a date object, else `false`.\n * @example\n *\n * _.isDate(new Date);\n * // => true\n *\n * _.isDate('Mon April 23 2012');\n * // => false\n */\n var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;\n\n /**\n * Checks if `value` is likely a DOM element.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.\n * @example\n *\n * _.isElement(document.body);\n * // => true\n *\n * _.isElement('<body>');\n * // => false\n */\n function isElement(value) {\n return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);\n }\n\n /**\n * Checks if `value` is an empty object, collection, map, or set.\n *\n * Objects are considered empty if they have no own enumerable string keyed\n * properties.\n *\n * Array-like values such as `arguments` objects, arrays, buffers, strings, or\n * jQuery-like collections are considered empty if they have a `length` of `0`.\n * Similarly, maps and sets are considered empty if they have a `size` of `0`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is empty, else `false`.\n * @example\n *\n * _.isEmpty(null);\n * // => true\n *\n * _.isEmpty(true);\n * // => true\n *\n * _.isEmpty(1);\n * // => true\n *\n * _.isEmpty([1, 2, 3]);\n * // => false\n *\n * _.isEmpty({ 'a': 1 });\n * // => false\n */\n function isEmpty(value) {\n if (value == null) {\n return true;\n }\n if (isArrayLike(value) &&\n (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||\n isBuffer(value) || isTypedArray(value) || isArguments(value))) {\n return !value.length;\n }\n var tag = getTag(value);\n if (tag == mapTag || tag == setTag) {\n return !value.size;\n }\n if (isPrototype(value)) {\n return !baseKeys(value).length;\n }\n for (var key in value) {\n if (hasOwnProperty.call(value, key)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\n function isEqual(value, other) {\n return baseIsEqual(value, other);\n }\n\n /**\n * This method is like `_.isEqual` except that it accepts `customizer` which\n * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n * are handled by the method instead. The `customizer` is invoked with up to\n * six arguments: (objValue, othValue [, index|key, object, other, stack]).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * function isGreeting(value) {\n * return /^h(?:i|ello)$/.test(value);\n * }\n *\n * function customizer(objValue, othValue) {\n * if (isGreeting(objValue) && isGreeting(othValue)) {\n * return true;\n * }\n * }\n *\n * var array = ['hello', 'goodbye'];\n * var other = ['hi', 'goodbye'];\n *\n * _.isEqualWith(array, other, customizer);\n * // => true\n */\n function isEqualWith(value, other, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n var result = customizer ? customizer(value, other) : undefined;\n return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;\n }\n\n /**\n * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,\n * `SyntaxError`, `TypeError`, or `URIError` object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an error object, else `false`.\n * @example\n *\n * _.isError(new Error);\n * // => true\n *\n * _.isError(Error);\n * // => false\n */\n function isError(value) {\n if (!isObjectLike(value)) {\n return false;\n }\n var tag = baseGetTag(value);\n return tag == errorTag || tag == domExcTag ||\n (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));\n }\n\n /**\n * Checks if `value` is a finite primitive number.\n *\n * **Note:** This method is based on\n * [`Number.isFinite`](https://mdn.io/Number/isFinite).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.\n * @example\n *\n * _.isFinite(3);\n * // => true\n *\n * _.isFinite(Number.MIN_VALUE);\n * // => true\n *\n * _.isFinite(Infinity);\n * // => false\n *\n * _.isFinite('3');\n * // => false\n */\n function isFinite(value) {\n return typeof value == 'number' && nativeIsFinite(value);\n }\n\n /**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\n function isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n }\n\n /**\n * Checks if `value` is an integer.\n *\n * **Note:** This method is based on\n * [`Number.isInteger`](https://mdn.io/Number/isInteger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an integer, else `false`.\n * @example\n *\n * _.isInteger(3);\n * // => true\n *\n * _.isInteger(Number.MIN_VALUE);\n * // => false\n *\n * _.isInteger(Infinity);\n * // => false\n *\n * _.isInteger('3');\n * // => false\n */\n function isInteger(value) {\n return typeof value == 'number' && value == toInteger(value);\n }\n\n /**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\n function isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n }\n\n /**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\n function isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n }\n\n /**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\n function isObjectLike(value) {\n return value != null && typeof value == 'object';\n }\n\n /**\n * Checks if `value` is classified as a `Map` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n * @example\n *\n * _.isMap(new Map);\n * // => true\n *\n * _.isMap(new WeakMap);\n * // => false\n */\n var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\n /**\n * Performs a partial deep comparison between `object` and `source` to\n * determine if `object` contains equivalent property values.\n *\n * **Note:** This method is equivalent to `_.matches` when `source` is\n * partially applied.\n *\n * Partial comparisons will match empty array and empty object `source`\n * values against any array or object value, respectively. See `_.isEqual`\n * for a list of supported value comparisons.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n *\n * _.isMatch(object, { 'b': 2 });\n * // => true\n *\n * _.isMatch(object, { 'b': 1 });\n * // => false\n */\n function isMatch(object, source) {\n return object === source || baseIsMatch(object, source, getMatchData(source));\n }\n\n /**\n * This method is like `_.isMatch` except that it accepts `customizer` which\n * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n * are handled by the method instead. The `customizer` is invoked with five\n * arguments: (objValue, srcValue, index|key, object, source).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n * @example\n *\n * function isGreeting(value) {\n * return /^h(?:i|ello)$/.test(value);\n * }\n *\n * function customizer(objValue, srcValue) {\n * if (isGreeting(objValue) && isGreeting(srcValue)) {\n * return true;\n * }\n * }\n *\n * var object = { 'greeting': 'hello' };\n * var source = { 'greeting': 'hi' };\n *\n * _.isMatchWith(object, source, customizer);\n * // => true\n */\n function isMatchWith(object, source, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseIsMatch(object, source, getMatchData(source), customizer);\n }\n\n /**\n * Checks if `value` is `NaN`.\n *\n * **Note:** This method is based on\n * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as\n * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for\n * `undefined` and other non-number values.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n * @example\n *\n * _.isNaN(NaN);\n * // => true\n *\n * _.isNaN(new Number(NaN));\n * // => true\n *\n * isNaN(undefined);\n * // => true\n *\n * _.isNaN(undefined);\n * // => false\n */\n function isNaN(value) {\n // An `NaN` primitive is the only value that is not equal to itself.\n // Perform the `toStringTag` check first to avoid errors with some\n // ActiveX objects in IE.\n return isNumber(value) && value != +value;\n }\n\n /**\n * Checks if `value` is a pristine native function.\n *\n * **Note:** This method can't reliably detect native functions in the presence\n * of the core-js package because core-js circumvents this kind of detection.\n * Despite multiple requests, the core-js maintainer has made it clear: any\n * attempt to fix the detection will be obstructed. As a result, we're left\n * with little choice but to throw an error. Unfortunately, this also affects\n * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),\n * which rely on core-js.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n * @example\n *\n * _.isNative(Array.prototype.push);\n * // => true\n *\n * _.isNative(_);\n * // => false\n */\n function isNative(value) {\n if (isMaskable(value)) {\n throw new Error(CORE_ERROR_TEXT);\n }\n return baseIsNative(value);\n }\n\n /**\n * Checks if `value` is `null`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `null`, else `false`.\n * @example\n *\n * _.isNull(null);\n * // => true\n *\n * _.isNull(void 0);\n * // => false\n */\n function isNull(value) {\n return value === null;\n }\n\n /**\n * Checks if `value` is `null` or `undefined`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is nullish, else `false`.\n * @example\n *\n * _.isNil(null);\n * // => true\n *\n * _.isNil(void 0);\n * // => true\n *\n * _.isNil(NaN);\n * // => false\n */\n function isNil(value) {\n return value == null;\n }\n\n /**\n * Checks if `value` is classified as a `Number` primitive or object.\n *\n * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are\n * classified as numbers, use the `_.isFinite` method.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a number, else `false`.\n * @example\n *\n * _.isNumber(3);\n * // => true\n *\n * _.isNumber(Number.MIN_VALUE);\n * // => true\n *\n * _.isNumber(Infinity);\n * // => true\n *\n * _.isNumber('3');\n * // => false\n */\n function isNumber(value) {\n return typeof value == 'number' ||\n (isObjectLike(value) && baseGetTag(value) == numberTag);\n }\n\n /**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\n function isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n }\n\n /**\n * Checks if `value` is classified as a `RegExp` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.\n * @example\n *\n * _.isRegExp(/abc/);\n * // => true\n *\n * _.isRegExp('/abc/');\n * // => false\n */\n var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;\n\n /**\n * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754\n * double precision number which isn't the result of a rounded unsafe integer.\n *\n * **Note:** This method is based on\n * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.\n * @example\n *\n * _.isSafeInteger(3);\n * // => true\n *\n * _.isSafeInteger(Number.MIN_VALUE);\n * // => false\n *\n * _.isSafeInteger(Infinity);\n * // => false\n *\n * _.isSafeInteger('3');\n * // => false\n */\n function isSafeInteger(value) {\n return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;\n }\n\n /**\n * Checks if `value` is classified as a `Set` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n * @example\n *\n * _.isSet(new Set);\n * // => true\n *\n * _.isSet(new WeakSet);\n * // => false\n */\n var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\n /**\n * Checks if `value` is classified as a `String` primitive or object.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a string, else `false`.\n * @example\n *\n * _.isString('abc');\n * // => true\n *\n * _.isString(1);\n * // => false\n */\n function isString(value) {\n return typeof value == 'string' ||\n (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);\n }\n\n /**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\n function isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n }\n\n /**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\n var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\n /**\n * Checks if `value` is `undefined`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.\n * @example\n *\n * _.isUndefined(void 0);\n * // => true\n *\n * _.isUndefined(null);\n * // => false\n */\n function isUndefined(value) {\n return value === undefined;\n }\n\n /**\n * Checks if `value` is classified as a `WeakMap` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.\n * @example\n *\n * _.isWeakMap(new WeakMap);\n * // => true\n *\n * _.isWeakMap(new Map);\n * // => false\n */\n function isWeakMap(value) {\n return isObjectLike(value) && getTag(value) == weakMapTag;\n }\n\n /**\n * Checks if `value` is classified as a `WeakSet` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.\n * @example\n *\n * _.isWeakSet(new WeakSet);\n * // => true\n *\n * _.isWeakSet(new Set);\n * // => false\n */\n function isWeakSet(value) {\n return isObjectLike(value) && baseGetTag(value) == weakSetTag;\n }\n\n /**\n * Checks if `value` is less than `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than `other`,\n * else `false`.\n * @see _.gt\n * @example\n *\n * _.lt(1, 3);\n * // => true\n *\n * _.lt(3, 3);\n * // => false\n *\n * _.lt(3, 1);\n * // => false\n */\n var lt = createRelationalOperation(baseLt);\n\n /**\n * Checks if `value` is less than or equal to `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than or equal to\n * `other`, else `false`.\n * @see _.gte\n * @example\n *\n * _.lte(1, 3);\n * // => true\n *\n * _.lte(3, 3);\n * // => true\n *\n * _.lte(3, 1);\n * // => false\n */\n var lte = createRelationalOperation(function(value, other) {\n return value <= other;\n });\n\n /**\n * Converts `value` to an array.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Array} Returns the converted array.\n * @example\n *\n * _.toArray({ 'a': 1, 'b': 2 });\n * // => [1, 2]\n *\n * _.toArray('abc');\n * // => ['a', 'b', 'c']\n *\n * _.toArray(1);\n * // => []\n *\n * _.toArray(null);\n * // => []\n */\n function toArray(value) {\n if (!value) {\n return [];\n }\n if (isArrayLike(value)) {\n return isString(value) ? stringToArray(value) : copyArray(value);\n }\n if (symIterator && value[symIterator]) {\n return iteratorToArray(value[symIterator]());\n }\n var tag = getTag(value),\n func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);\n\n return func(value);\n }\n\n /**\n * Converts `value` to a finite number.\n *\n * @static\n * @memberOf _\n * @since 4.12.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted number.\n * @example\n *\n * _.toFinite(3.2);\n * // => 3.2\n *\n * _.toFinite(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toFinite(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toFinite('3.2');\n * // => 3.2\n */\n function toFinite(value) {\n if (!value) {\n return value === 0 ? value : 0;\n }\n value = toNumber(value);\n if (value === INFINITY || value === -INFINITY) {\n var sign = (value < 0 ? -1 : 1);\n return sign * MAX_INTEGER;\n }\n return value === value ? value : 0;\n }\n\n /**\n * Converts `value` to an integer.\n *\n * **Note:** This method is loosely based on\n * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toInteger(3.2);\n * // => 3\n *\n * _.toInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toInteger(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toInteger('3.2');\n * // => 3\n */\n function toInteger(value) {\n var result = toFinite(value),\n remainder = result % 1;\n\n return result === result ? (remainder ? result - remainder : result) : 0;\n }\n\n /**\n * Converts `value` to an integer suitable for use as the length of an\n * array-like object.\n *\n * **Note:** This method is based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toLength(3.2);\n * // => 3\n *\n * _.toLength(Number.MIN_VALUE);\n * // => 0\n *\n * _.toLength(Infinity);\n * // => 4294967295\n *\n * _.toLength('3.2');\n * // => 3\n */\n function toLength(value) {\n return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;\n }\n\n /**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\n function toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n }\n\n /**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\n function toPlainObject(value) {\n return copyObject(value, keysIn(value));\n }\n\n /**\n * Converts `value` to a safe integer. A safe integer can be compared and\n * represented correctly.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toSafeInteger(3.2);\n * // => 3\n *\n * _.toSafeInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toSafeInteger(Infinity);\n * // => 9007199254740991\n *\n * _.toSafeInteger('3.2');\n * // => 3\n */\n function toSafeInteger(value) {\n return value\n ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)\n : (value === 0 ? value : 0);\n }\n\n /**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\n function toString(value) {\n return value == null ? '' : baseToString(value);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Assigns own enumerable string keyed properties of source objects to the\n * destination object. Source objects are applied from left to right.\n * Subsequent sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object` and is loosely based on\n * [`Object.assign`](https://mdn.io/Object/assign).\n *\n * @static\n * @memberOf _\n * @since 0.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assignIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assign({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'c': 3 }\n */\n var assign = createAssigner(function(object, source) {\n if (isPrototype(source) || isArrayLike(source)) {\n copyObject(source, keys(source), object);\n return;\n }\n for (var key in source) {\n if (hasOwnProperty.call(source, key)) {\n assignValue(object, key, source[key]);\n }\n }\n });\n\n /**\n * This method is like `_.assign` except that it iterates over own and\n * inherited source properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extend\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assign\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assignIn({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }\n */\n var assignIn = createAssigner(function(object, source) {\n copyObject(source, keysIn(source), object);\n });\n\n /**\n * This method is like `_.assignIn` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extendWith\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignInWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keysIn(source), object, customizer);\n });\n\n /**\n * This method is like `_.assign` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignInWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var assignWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keys(source), object, customizer);\n });\n\n /**\n * Creates an array of values corresponding to `paths` of `object`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Array} Returns the picked values.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };\n *\n * _.at(object, ['a[0].b.c', 'a[1]']);\n * // => [3, 4]\n */\n var at = flatRest(baseAt);\n\n /**\n * Creates an object that inherits from the `prototype` object. If a\n * `properties` object is given, its own enumerable string keyed properties\n * are assigned to the created object.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Object\n * @param {Object} prototype The object to inherit from.\n * @param {Object} [properties] The properties to assign to the object.\n * @returns {Object} Returns the new object.\n * @example\n *\n * function Shape() {\n * this.x = 0;\n * this.y = 0;\n * }\n *\n * function Circle() {\n * Shape.call(this);\n * }\n *\n * Circle.prototype = _.create(Shape.prototype, {\n * 'constructor': Circle\n * });\n *\n * var circle = new Circle;\n * circle instanceof Circle;\n * // => true\n *\n * circle instanceof Shape;\n * // => true\n */\n function create(prototype, properties) {\n var result = baseCreate(prototype);\n return properties == null ? result : baseAssign(result, properties);\n }\n\n /**\n * Assigns own and inherited enumerable string keyed properties of source\n * objects to the destination object for all destination properties that\n * resolve to `undefined`. Source objects are applied from left to right.\n * Once a property is set, additional values of the same property are ignored.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaultsDeep\n * @example\n *\n * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var defaults = baseRest(function(object, sources) {\n object = Object(object);\n\n var index = -1;\n var length = sources.length;\n var guard = length > 2 ? sources[2] : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n length = 1;\n }\n\n while (++index < length) {\n var source = sources[index];\n var props = keysIn(source);\n var propsIndex = -1;\n var propsLength = props.length;\n\n while (++propsIndex < propsLength) {\n var key = props[propsIndex];\n var value = object[key];\n\n if (value === undefined ||\n (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n object[key] = source[key];\n }\n }\n }\n\n return object;\n });\n\n /**\n * This method is like `_.defaults` except that it recursively assigns\n * default properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaults\n * @example\n *\n * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });\n * // => { 'a': { 'b': 2, 'c': 3 } }\n */\n var defaultsDeep = baseRest(function(args) {\n args.push(undefined, customDefaultsMerge);\n return apply(mergeWith, undefined, args);\n });\n\n /**\n * This method is like `_.find` except that it returns the key of the first\n * element `predicate` returns truthy for instead of the element itself.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {string|undefined} Returns the key of the matched element,\n * else `undefined`.\n * @example\n *\n * var users = {\n * 'barney': { 'age': 36, 'active': true },\n * 'fred': { 'age': 40, 'active': false },\n * 'pebbles': { 'age': 1, 'active': true }\n * };\n *\n * _.findKey(users, function(o) { return o.age < 40; });\n * // => 'barney' (iteration order is not guaranteed)\n *\n * // The `_.matches` iteratee shorthand.\n * _.findKey(users, { 'age': 1, 'active': true });\n * // => 'pebbles'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findKey(users, ['active', false]);\n * // => 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.findKey(users, 'active');\n * // => 'barney'\n */\n function findKey(object, predicate) {\n return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);\n }\n\n /**\n * This method is like `_.findKey` except that it iterates over elements of\n * a collection in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {string|undefined} Returns the key of the matched element,\n * else `undefined`.\n * @example\n *\n * var users = {\n * 'barney': { 'age': 36, 'active': true },\n * 'fred': { 'age': 40, 'active': false },\n * 'pebbles': { 'age': 1, 'active': true }\n * };\n *\n * _.findLastKey(users, function(o) { return o.age < 40; });\n * // => returns 'pebbles' assuming `_.findKey` returns 'barney'\n *\n * // The `_.matches` iteratee shorthand.\n * _.findLastKey(users, { 'age': 36, 'active': true });\n * // => 'barney'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findLastKey(users, ['active', false]);\n * // => 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.findLastKey(users, 'active');\n * // => 'pebbles'\n */\n function findLastKey(object, predicate) {\n return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);\n }\n\n /**\n * Iterates over own and inherited enumerable string keyed properties of an\n * object and invokes `iteratee` for each property. The iteratee is invoked\n * with three arguments: (value, key, object). Iteratee functions may exit\n * iteration early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 0.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forInRight\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forIn(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).\n */\n function forIn(object, iteratee) {\n return object == null\n ? object\n : baseFor(object, getIteratee(iteratee, 3), keysIn);\n }\n\n /**\n * This method is like `_.forIn` except that it iterates over properties of\n * `object` in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forInRight(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.\n */\n function forInRight(object, iteratee) {\n return object == null\n ? object\n : baseForRight(object, getIteratee(iteratee, 3), keysIn);\n }\n\n /**\n * Iterates over own enumerable string keyed properties of an object and\n * invokes `iteratee` for each property. The iteratee is invoked with three\n * arguments: (value, key, object). Iteratee functions may exit iteration\n * early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 0.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forOwnRight\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forOwn(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n */\n function forOwn(object, iteratee) {\n return object && baseForOwn(object, getIteratee(iteratee, 3));\n }\n\n /**\n * This method is like `_.forOwn` except that it iterates over properties of\n * `object` in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forOwn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forOwnRight(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.\n */\n function forOwnRight(object, iteratee) {\n return object && baseForOwnRight(object, getIteratee(iteratee, 3));\n }\n\n /**\n * Creates an array of function property names from own enumerable properties\n * of `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to inspect.\n * @returns {Array} Returns the function names.\n * @see _.functionsIn\n * @example\n *\n * function Foo() {\n * this.a = _.constant('a');\n * this.b = _.constant('b');\n * }\n *\n * Foo.prototype.c = _.constant('c');\n *\n * _.functions(new Foo);\n * // => ['a', 'b']\n */\n function functions(object) {\n return object == null ? [] : baseFunctions(object, keys(object));\n }\n\n /**\n * Creates an array of function property names from own and inherited\n * enumerable properties of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @returns {Array} Returns the function names.\n * @see _.functions\n * @example\n *\n * function Foo() {\n * this.a = _.constant('a');\n * this.b = _.constant('b');\n * }\n *\n * Foo.prototype.c = _.constant('c');\n *\n * _.functionsIn(new Foo);\n * // => ['a', 'b', 'c']\n */\n function functionsIn(object) {\n return object == null ? [] : baseFunctions(object, keysIn(object));\n }\n\n /**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\n function get(object, path, defaultValue) {\n var result = object == null ? undefined : baseGet(object, path);\n return result === undefined ? defaultValue : result;\n }\n\n /**\n * Checks if `path` is a direct property of `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = { 'a': { 'b': 2 } };\n * var other = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.has(object, 'a');\n * // => true\n *\n * _.has(object, 'a.b');\n * // => true\n *\n * _.has(object, ['a', 'b']);\n * // => true\n *\n * _.has(other, 'a');\n * // => false\n */\n function has(object, path) {\n return object != null && hasPath(object, path, baseHas);\n }\n\n /**\n * Checks if `path` is a direct or inherited property of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.hasIn(object, 'a');\n * // => true\n *\n * _.hasIn(object, 'a.b');\n * // => true\n *\n * _.hasIn(object, ['a', 'b']);\n * // => true\n *\n * _.hasIn(object, 'b');\n * // => false\n */\n function hasIn(object, path) {\n return object != null && hasPath(object, path, baseHasIn);\n }\n\n /**\n * Creates an object composed of the inverted keys and values of `object`.\n * If `object` contains duplicate values, subsequent values overwrite\n * property assignments of previous values.\n *\n * @static\n * @memberOf _\n * @since 0.7.0\n * @category Object\n * @param {Object} object The object to invert.\n * @returns {Object} Returns the new inverted object.\n * @example\n *\n * var object = { 'a': 1, 'b': 2, 'c': 1 };\n *\n * _.invert(object);\n * // => { '1': 'c', '2': 'b' }\n */\n var invert = createInverter(function(result, value, key) {\n if (value != null &&\n typeof value.toString != 'function') {\n value = nativeObjectToString.call(value);\n }\n\n result[value] = key;\n }, constant(identity));\n\n /**\n * This method is like `_.invert` except that the inverted object is generated\n * from the results of running each element of `object` thru `iteratee`. The\n * corresponding inverted value of each inverted key is an array of keys\n * responsible for generating the inverted value. The iteratee is invoked\n * with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.1.0\n * @category Object\n * @param {Object} object The object to invert.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Object} Returns the new inverted object.\n * @example\n *\n * var object = { 'a': 1, 'b': 2, 'c': 1 };\n *\n * _.invertBy(object);\n * // => { '1': ['a', 'c'], '2': ['b'] }\n *\n * _.invertBy(object, function(value) {\n * return 'group' + value;\n * });\n * // => { 'group1': ['a', 'c'], 'group2': ['b'] }\n */\n var invertBy = createInverter(function(result, value, key) {\n if (value != null &&\n typeof value.toString != 'function') {\n value = nativeObjectToString.call(value);\n }\n\n if (hasOwnProperty.call(result, value)) {\n result[value].push(key);\n } else {\n result[value] = [key];\n }\n }, getIteratee);\n\n /**\n * Invokes the method at `path` of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the method to invoke.\n * @param {...*} [args] The arguments to invoke the method with.\n * @returns {*} Returns the result of the invoked method.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };\n *\n * _.invoke(object, 'a[0].b.c.slice', 1, 3);\n * // => [2, 3]\n */\n var invoke = baseRest(baseInvoke);\n\n /**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\n function keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n }\n\n /**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\n function keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n }\n\n /**\n * The opposite of `_.mapValues`; this method creates an object with the\n * same values as `object` and keys generated by running each own enumerable\n * string keyed property of `object` thru `iteratee`. The iteratee is invoked\n * with three arguments: (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 3.8.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapValues\n * @example\n *\n * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {\n * return key + value;\n * });\n * // => { 'a1': 1, 'b2': 2 }\n */\n function mapKeys(object, iteratee) {\n var result = {};\n iteratee = getIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, iteratee(value, key, object), value);\n });\n return result;\n }\n\n /**\n * Creates an object with the same keys as `object` and values generated\n * by running each own enumerable string keyed property of `object` thru\n * `iteratee`. The iteratee is invoked with three arguments:\n * (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapKeys\n * @example\n *\n * var users = {\n * 'fred': { 'user': 'fred', 'age': 40 },\n * 'pebbles': { 'user': 'pebbles', 'age': 1 }\n * };\n *\n * _.mapValues(users, function(o) { return o.age; });\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n *\n * // The `_.property` iteratee shorthand.\n * _.mapValues(users, 'age');\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n */\n function mapValues(object, iteratee) {\n var result = {};\n iteratee = getIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, key, iteratee(value, key, object));\n });\n return result;\n }\n\n /**\n * This method is like `_.assign` except that it recursively merges own and\n * inherited enumerable string keyed properties of source objects into the\n * destination object. Source properties that resolve to `undefined` are\n * skipped if a destination value exists. Array and plain object properties\n * are merged recursively. Other objects and value types are overridden by\n * assignment. Source objects are applied from left to right. Subsequent\n * sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {\n * 'a': [{ 'b': 2 }, { 'd': 4 }]\n * };\n *\n * var other = {\n * 'a': [{ 'c': 3 }, { 'e': 5 }]\n * };\n *\n * _.merge(object, other);\n * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }\n */\n var merge = createAssigner(function(object, source, srcIndex) {\n baseMerge(object, source, srcIndex);\n });\n\n /**\n * This method is like `_.merge` except that it accepts `customizer` which\n * is invoked to produce the merged values of the destination and source\n * properties. If `customizer` returns `undefined`, merging is handled by the\n * method instead. The `customizer` is invoked with six arguments:\n * (objValue, srcValue, key, object, source, stack).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} customizer The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * function customizer(objValue, srcValue) {\n * if (_.isArray(objValue)) {\n * return objValue.concat(srcValue);\n * }\n * }\n *\n * var object = { 'a': [1], 'b': [2] };\n * var other = { 'a': [3], 'b': [4] };\n *\n * _.mergeWith(object, other, customizer);\n * // => { 'a': [1, 3], 'b': [2, 4] }\n */\n var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {\n baseMerge(object, source, srcIndex, customizer);\n });\n\n /**\n * The opposite of `_.pick`; this method creates an object composed of the\n * own and inherited enumerable property paths of `object` that are not omitted.\n *\n * **Note:** This method is considerably slower than `_.pick`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to omit.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.omit(object, ['a', 'c']);\n * // => { 'b': '2' }\n */\n var omit = flatRest(function(object, paths) {\n var result = {};\n if (object == null) {\n return result;\n }\n var isDeep = false;\n paths = arrayMap(paths, function(path) {\n path = castPath(path, object);\n isDeep || (isDeep = path.length > 1);\n return path;\n });\n copyObject(object, getAllKeysIn(object), result);\n if (isDeep) {\n result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);\n }\n var length = paths.length;\n while (length--) {\n baseUnset(result, paths[length]);\n }\n return result;\n });\n\n /**\n * The opposite of `_.pickBy`; this method creates an object composed of\n * the own and inherited enumerable string keyed properties of `object` that\n * `predicate` doesn't return truthy for. The predicate is invoked with two\n * arguments: (value, key).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The source object.\n * @param {Function} [predicate=_.identity] The function invoked per property.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.omitBy(object, _.isNumber);\n * // => { 'b': '2' }\n */\n function omitBy(object, predicate) {\n return pickBy(object, negate(getIteratee(predicate)));\n }\n\n /**\n * Creates an object composed of the picked `object` properties.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pick(object, ['a', 'c']);\n * // => { 'a': 1, 'c': 3 }\n */\n var pick = flatRest(function(object, paths) {\n return object == null ? {} : basePick(object, paths);\n });\n\n /**\n * Creates an object composed of the `object` properties `predicate` returns\n * truthy for. The predicate is invoked with two arguments: (value, key).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The source object.\n * @param {Function} [predicate=_.identity] The function invoked per property.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pickBy(object, _.isNumber);\n * // => { 'a': 1, 'c': 3 }\n */\n function pickBy(object, predicate) {\n if (object == null) {\n return {};\n }\n var props = arrayMap(getAllKeysIn(object), function(prop) {\n return [prop];\n });\n predicate = getIteratee(predicate);\n return basePickBy(object, props, function(value, path) {\n return predicate(value, path[0]);\n });\n }\n\n /**\n * This method is like `_.get` except that if the resolved value is a\n * function it's invoked with the `this` binding of its parent object and\n * its result is returned.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to resolve.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };\n *\n * _.result(object, 'a[0].b.c1');\n * // => 3\n *\n * _.result(object, 'a[0].b.c2');\n * // => 4\n *\n * _.result(object, 'a[0].b.c3', 'default');\n * // => 'default'\n *\n * _.result(object, 'a[0].b.c3', _.constant('default'));\n * // => 'default'\n */\n function result(object, path, defaultValue) {\n path = castPath(path, object);\n\n var index = -1,\n length = path.length;\n\n // Ensure the loop is entered when path is empty.\n if (!length) {\n length = 1;\n object = undefined;\n }\n while (++index < length) {\n var value = object == null ? undefined : object[toKey(path[index])];\n if (value === undefined) {\n index = length;\n value = defaultValue;\n }\n object = isFunction(value) ? value.call(object) : value;\n }\n return object;\n }\n\n /**\n * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,\n * it's created. Arrays are created for missing index properties while objects\n * are created for all other missing properties. Use `_.setWith` to customize\n * `path` creation.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.set(object, 'a[0].b.c', 4);\n * console.log(object.a[0].b.c);\n * // => 4\n *\n * _.set(object, ['x', '0', 'y', 'z'], 5);\n * console.log(object.x[0].y.z);\n * // => 5\n */\n function set(object, path, value) {\n return object == null ? object : baseSet(object, path, value);\n }\n\n /**\n * This method is like `_.set` except that it accepts `customizer` which is\n * invoked to produce the objects of `path`. If `customizer` returns `undefined`\n * path creation is handled by the method instead. The `customizer` is invoked\n * with three arguments: (nsValue, key, nsObject).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {};\n *\n * _.setWith(object, '[0][1]', 'a', Object);\n * // => { '0': { '1': 'a' } }\n */\n function setWith(object, path, value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return object == null ? object : baseSet(object, path, value, customizer);\n }\n\n /**\n * Creates an array of own enumerable string keyed-value pairs for `object`\n * which can be consumed by `_.fromPairs`. If `object` is a map or set, its\n * entries are returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias entries\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the key-value pairs.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.toPairs(new Foo);\n * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)\n */\n var toPairs = createToPairs(keys);\n\n /**\n * Creates an array of own and inherited enumerable string keyed-value pairs\n * for `object` which can be consumed by `_.fromPairs`. If `object` is a map\n * or set, its entries are returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias entriesIn\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the key-value pairs.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.toPairsIn(new Foo);\n * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)\n */\n var toPairsIn = createToPairs(keysIn);\n\n /**\n * An alternative to `_.reduce`; this method transforms `object` to a new\n * `accumulator` object which is the result of running each of its own\n * enumerable string keyed properties thru `iteratee`, with each invocation\n * potentially mutating the `accumulator` object. If `accumulator` is not\n * provided, a new object with the same `[[Prototype]]` will be used. The\n * iteratee is invoked with four arguments: (accumulator, value, key, object).\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 1.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [accumulator] The custom accumulator value.\n * @returns {*} Returns the accumulated value.\n * @example\n *\n * _.transform([2, 3, 4], function(result, n) {\n * result.push(n *= n);\n * return n % 2 == 0;\n * }, []);\n * // => [4, 9]\n *\n * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {\n * (result[value] || (result[value] = [])).push(key);\n * }, {});\n * // => { '1': ['a', 'c'], '2': ['b'] }\n */\n function transform(object, iteratee, accumulator) {\n var isArr = isArray(object),\n isArrLike = isArr || isBuffer(object) || isTypedArray(object);\n\n iteratee = getIteratee(iteratee, 4);\n if (accumulator == null) {\n var Ctor = object && object.constructor;\n if (isArrLike) {\n accumulator = isArr ? new Ctor : [];\n }\n else if (isObject(object)) {\n accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};\n }\n else {\n accumulator = {};\n }\n }\n (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {\n return iteratee(accumulator, value, index, object);\n });\n return accumulator;\n }\n\n /**\n * Removes the property at `path` of `object`.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to unset.\n * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 7 } }] };\n * _.unset(object, 'a[0].b.c');\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n *\n * _.unset(object, ['a', '0', 'b', 'c']);\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n */\n function unset(object, path) {\n return object == null ? true : baseUnset(object, path);\n }\n\n /**\n * This method is like `_.set` except that accepts `updater` to produce the\n * value to set. Use `_.updateWith` to customize `path` creation. The `updater`\n * is invoked with one argument: (value).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {Function} updater The function to produce the updated value.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.update(object, 'a[0].b.c', function(n) { return n * n; });\n * console.log(object.a[0].b.c);\n * // => 9\n *\n * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });\n * console.log(object.x[0].y.z);\n * // => 0\n */\n function update(object, path, updater) {\n return object == null ? object : baseUpdate(object, path, castFunction(updater));\n }\n\n /**\n * This method is like `_.update` except that it accepts `customizer` which is\n * invoked to produce the objects of `path`. If `customizer` returns `undefined`\n * path creation is handled by the method instead. The `customizer` is invoked\n * with three arguments: (nsValue, key, nsObject).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {Function} updater The function to produce the updated value.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {};\n *\n * _.updateWith(object, '[0][1]', _.constant('a'), Object);\n * // => { '0': { '1': 'a' } }\n */\n function updateWith(object, path, updater, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);\n }\n\n /**\n * Creates an array of the own enumerable string keyed property values of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property values.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.values(new Foo);\n * // => [1, 2] (iteration order is not guaranteed)\n *\n * _.values('hi');\n * // => ['h', 'i']\n */\n function values(object) {\n return object == null ? [] : baseValues(object, keys(object));\n }\n\n /**\n * Creates an array of the own and inherited enumerable string keyed property\n * values of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property values.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.valuesIn(new Foo);\n * // => [1, 2, 3] (iteration order is not guaranteed)\n */\n function valuesIn(object) {\n return object == null ? [] : baseValues(object, keysIn(object));\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Clamps `number` within the inclusive `lower` and `upper` bounds.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Number\n * @param {number} number The number to clamp.\n * @param {number} [lower] The lower bound.\n * @param {number} upper The upper bound.\n * @returns {number} Returns the clamped number.\n * @example\n *\n * _.clamp(-10, -5, 5);\n * // => -5\n *\n * _.clamp(10, -5, 5);\n * // => 5\n */\n function clamp(number, lower, upper) {\n if (upper === undefined) {\n upper = lower;\n lower = undefined;\n }\n if (upper !== undefined) {\n upper = toNumber(upper);\n upper = upper === upper ? upper : 0;\n }\n if (lower !== undefined) {\n lower = toNumber(lower);\n lower = lower === lower ? lower : 0;\n }\n return baseClamp(toNumber(number), lower, upper);\n }\n\n /**\n * Checks if `n` is between `start` and up to, but not including, `end`. If\n * `end` is not specified, it's set to `start` with `start` then set to `0`.\n * If `start` is greater than `end` the params are swapped to support\n * negative ranges.\n *\n * @static\n * @memberOf _\n * @since 3.3.0\n * @category Number\n * @param {number} number The number to check.\n * @param {number} [start=0] The start of the range.\n * @param {number} end The end of the range.\n * @returns {boolean} Returns `true` if `number` is in the range, else `false`.\n * @see _.range, _.rangeRight\n * @example\n *\n * _.inRange(3, 2, 4);\n * // => true\n *\n * _.inRange(4, 8);\n * // => true\n *\n * _.inRange(4, 2);\n * // => false\n *\n * _.inRange(2, 2);\n * // => false\n *\n * _.inRange(1.2, 2);\n * // => true\n *\n * _.inRange(5.2, 4);\n * // => false\n *\n * _.inRange(-3, -2, -6);\n * // => true\n */\n function inRange(number, start, end) {\n start = toFinite(start);\n if (end === undefined) {\n end = start;\n start = 0;\n } else {\n end = toFinite(end);\n }\n number = toNumber(number);\n return baseInRange(number, start, end);\n }\n\n /**\n * Produces a random number between the inclusive `lower` and `upper` bounds.\n * If only one argument is provided a number between `0` and the given number\n * is returned. If `floating` is `true`, or either `lower` or `upper` are\n * floats, a floating-point number is returned instead of an integer.\n *\n * **Note:** JavaScript follows the IEEE-754 standard for resolving\n * floating-point values which can produce unexpected results.\n *\n * @static\n * @memberOf _\n * @since 0.7.0\n * @category Number\n * @param {number} [lower=0] The lower bound.\n * @param {number} [upper=1] The upper bound.\n * @param {boolean} [floating] Specify returning a floating-point number.\n * @returns {number} Returns the random number.\n * @example\n *\n * _.random(0, 5);\n * // => an integer between 0 and 5\n *\n * _.random(5);\n * // => also an integer between 0 and 5\n *\n * _.random(5, true);\n * // => a floating-point number between 0 and 5\n *\n * _.random(1.2, 5.2);\n * // => a floating-point number between 1.2 and 5.2\n */\n function random(lower, upper, floating) {\n if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {\n upper = floating = undefined;\n }\n if (floating === undefined) {\n if (typeof upper == 'boolean') {\n floating = upper;\n upper = undefined;\n }\n else if (typeof lower == 'boolean') {\n floating = lower;\n lower = undefined;\n }\n }\n if (lower === undefined && upper === undefined) {\n lower = 0;\n upper = 1;\n }\n else {\n lower = toFinite(lower);\n if (upper === undefined) {\n upper = lower;\n lower = 0;\n } else {\n upper = toFinite(upper);\n }\n }\n if (lower > upper) {\n var temp = lower;\n lower = upper;\n upper = temp;\n }\n if (floating || lower % 1 || upper % 1) {\n var rand = nativeRandom();\n return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);\n }\n return baseRandom(lower, upper);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the camel cased string.\n * @example\n *\n * _.camelCase('Foo Bar');\n * // => 'fooBar'\n *\n * _.camelCase('--foo-bar--');\n * // => 'fooBar'\n *\n * _.camelCase('__FOO_BAR__');\n * // => 'fooBar'\n */\n var camelCase = createCompounder(function(result, word, index) {\n word = word.toLowerCase();\n return result + (index ? capitalize(word) : word);\n });\n\n /**\n * Converts the first character of `string` to upper case and the remaining\n * to lower case.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to capitalize.\n * @returns {string} Returns the capitalized string.\n * @example\n *\n * _.capitalize('FRED');\n * // => 'Fred'\n */\n function capitalize(string) {\n return upperFirst(toString(string).toLowerCase());\n }\n\n /**\n * Deburrs `string` by converting\n * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)\n * letters to basic Latin letters and removing\n * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to deburr.\n * @returns {string} Returns the deburred string.\n * @example\n *\n * _.deburr('déjà vu');\n * // => 'deja vu'\n */\n function deburr(string) {\n string = toString(string);\n return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');\n }\n\n /**\n * Checks if `string` ends with the given target string.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {string} [target] The string to search for.\n * @param {number} [position=string.length] The position to search up to.\n * @returns {boolean} Returns `true` if `string` ends with `target`,\n * else `false`.\n * @example\n *\n * _.endsWith('abc', 'c');\n * // => true\n *\n * _.endsWith('abc', 'b');\n * // => false\n *\n * _.endsWith('abc', 'b', 2);\n * // => true\n */\n function endsWith(string, target, position) {\n string = toString(string);\n target = baseToString(target);\n\n var length = string.length;\n position = position === undefined\n ? length\n : baseClamp(toInteger(position), 0, length);\n\n var end = position;\n position -= target.length;\n return position >= 0 && string.slice(position, end) == target;\n }\n\n /**\n * Converts the characters \"&\", \"<\", \">\", '\"', and \"'\" in `string` to their\n * corresponding HTML entities.\n *\n * **Note:** No other characters are escaped. To escape additional\n * characters use a third-party library like [_he_](https://mths.be/he).\n *\n * Though the \">\" character is escaped for symmetry, characters like\n * \">\" and \"/\" don't need escaping in HTML and have no special meaning\n * unless they're part of a tag or unquoted attribute value. See\n * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)\n * (under \"semi-related fun fact\") for more details.\n *\n * When working with HTML you should always\n * [quote attribute values](http://wonko.com/post/html-escaping) to reduce\n * XSS vectors.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category String\n * @param {string} [string=''] The string to escape.\n * @returns {string} Returns the escaped string.\n * @example\n *\n * _.escape('fred, barney, & pebbles');\n * // => 'fred, barney, &amp; pebbles'\n */\n function escape(string) {\n string = toString(string);\n return (string && reHasUnescapedHtml.test(string))\n ? string.replace(reUnescapedHtml, escapeHtmlChar)\n : string;\n }\n\n /**\n * Escapes the `RegExp` special characters \"^\", \"$\", \"\\\", \".\", \"*\", \"+\",\n * \"?\", \"(\", \")\", \"[\", \"]\", \"{\", \"}\", and \"|\" in `string`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to escape.\n * @returns {string} Returns the escaped string.\n * @example\n *\n * _.escapeRegExp('[lodash](https://lodash.com/)');\n * // => '\\[lodash\\]\\(https://lodash\\.com/\\)'\n */\n function escapeRegExp(string) {\n string = toString(string);\n return (string && reHasRegExpChar.test(string))\n ? string.replace(reRegExpChar, '\\\\$&')\n : string;\n }\n\n /**\n * Converts `string` to\n * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the kebab cased string.\n * @example\n *\n * _.kebabCase('Foo Bar');\n * // => 'foo-bar'\n *\n * _.kebabCase('fooBar');\n * // => 'foo-bar'\n *\n * _.kebabCase('__FOO_BAR__');\n * // => 'foo-bar'\n */\n var kebabCase = createCompounder(function(result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase();\n });\n\n /**\n * Converts `string`, as space separated words, to lower case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the lower cased string.\n * @example\n *\n * _.lowerCase('--Foo-Bar--');\n * // => 'foo bar'\n *\n * _.lowerCase('fooBar');\n * // => 'foo bar'\n *\n * _.lowerCase('__FOO_BAR__');\n * // => 'foo bar'\n */\n var lowerCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + word.toLowerCase();\n });\n\n /**\n * Converts the first character of `string` to lower case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.lowerFirst('Fred');\n * // => 'fred'\n *\n * _.lowerFirst('FRED');\n * // => 'fRED'\n */\n var lowerFirst = createCaseFirst('toLowerCase');\n\n /**\n * Pads `string` on the left and right sides if it's shorter than `length`.\n * Padding characters are truncated if they can't be evenly divided by `length`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.pad('abc', 8);\n * // => ' abc '\n *\n * _.pad('abc', 8, '_-');\n * // => '_-abc_-_'\n *\n * _.pad('abc', 3);\n * // => 'abc'\n */\n function pad(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n if (!length || strLength >= length) {\n return string;\n }\n var mid = (length - strLength) / 2;\n return (\n createPadding(nativeFloor(mid), chars) +\n string +\n createPadding(nativeCeil(mid), chars)\n );\n }\n\n /**\n * Pads `string` on the right side if it's shorter than `length`. Padding\n * characters are truncated if they exceed `length`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.padEnd('abc', 6);\n * // => 'abc '\n *\n * _.padEnd('abc', 6, '_-');\n * // => 'abc_-_'\n *\n * _.padEnd('abc', 3);\n * // => 'abc'\n */\n function padEnd(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n return (length && strLength < length)\n ? (string + createPadding(length - strLength, chars))\n : string;\n }\n\n /**\n * Pads `string` on the left side if it's shorter than `length`. Padding\n * characters are truncated if they exceed `length`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.padStart('abc', 6);\n * // => ' abc'\n *\n * _.padStart('abc', 6, '_-');\n * // => '_-_abc'\n *\n * _.padStart('abc', 3);\n * // => 'abc'\n */\n function padStart(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n return (length && strLength < length)\n ? (createPadding(length - strLength, chars) + string)\n : string;\n }\n\n /**\n * Converts `string` to an integer of the specified radix. If `radix` is\n * `undefined` or `0`, a `radix` of `10` is used unless `value` is a\n * hexadecimal, in which case a `radix` of `16` is used.\n *\n * **Note:** This method aligns with the\n * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category String\n * @param {string} string The string to convert.\n * @param {number} [radix=10] The radix to interpret `value` by.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.parseInt('08');\n * // => 8\n *\n * _.map(['6', '08', '10'], _.parseInt);\n * // => [6, 8, 10]\n */\n function parseInt(string, radix, guard) {\n if (guard || radix == null) {\n radix = 0;\n } else if (radix) {\n radix = +radix;\n }\n return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);\n }\n\n /**\n * Repeats the given string `n` times.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to repeat.\n * @param {number} [n=1] The number of times to repeat the string.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the repeated string.\n * @example\n *\n * _.repeat('*', 3);\n * // => '***'\n *\n * _.repeat('abc', 2);\n * // => 'abcabc'\n *\n * _.repeat('abc', 0);\n * // => ''\n */\n function repeat(string, n, guard) {\n if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {\n n = 1;\n } else {\n n = toInteger(n);\n }\n return baseRepeat(toString(string), n);\n }\n\n /**\n * Replaces matches for `pattern` in `string` with `replacement`.\n *\n * **Note:** This method is based on\n * [`String#replace`](https://mdn.io/String/replace).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to modify.\n * @param {RegExp|string} pattern The pattern to replace.\n * @param {Function|string} replacement The match replacement.\n * @returns {string} Returns the modified string.\n * @example\n *\n * _.replace('Hi Fred', 'Fred', 'Barney');\n * // => 'Hi Barney'\n */\n function replace() {\n var args = arguments,\n string = toString(args[0]);\n\n return args.length < 3 ? string : string.replace(args[1], args[2]);\n }\n\n /**\n * Converts `string` to\n * [snake case](https://en.wikipedia.org/wiki/Snake_case).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the snake cased string.\n * @example\n *\n * _.snakeCase('Foo Bar');\n * // => 'foo_bar'\n *\n * _.snakeCase('fooBar');\n * // => 'foo_bar'\n *\n * _.snakeCase('--FOO-BAR--');\n * // => 'foo_bar'\n */\n var snakeCase = createCompounder(function(result, word, index) {\n return result + (index ? '_' : '') + word.toLowerCase();\n });\n\n /**\n * Splits `string` by `separator`.\n *\n * **Note:** This method is based on\n * [`String#split`](https://mdn.io/String/split).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to split.\n * @param {RegExp|string} separator The separator pattern to split by.\n * @param {number} [limit] The length to truncate results to.\n * @returns {Array} Returns the string segments.\n * @example\n *\n * _.split('a-b-c', '-', 2);\n * // => ['a', 'b']\n */\n function split(string, separator, limit) {\n if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {\n separator = limit = undefined;\n }\n limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;\n if (!limit) {\n return [];\n }\n string = toString(string);\n if (string && (\n typeof separator == 'string' ||\n (separator != null && !isRegExp(separator))\n )) {\n separator = baseToString(separator);\n if (!separator && hasUnicode(string)) {\n return castSlice(stringToArray(string), 0, limit);\n }\n }\n return string.split(separator, limit);\n }\n\n /**\n * Converts `string` to\n * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n *\n * @static\n * @memberOf _\n * @since 3.1.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the start cased string.\n * @example\n *\n * _.startCase('--foo-bar--');\n * // => 'Foo Bar'\n *\n * _.startCase('fooBar');\n * // => 'Foo Bar'\n *\n * _.startCase('__FOO_BAR__');\n * // => 'FOO BAR'\n */\n var startCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + upperFirst(word);\n });\n\n /**\n * Checks if `string` starts with the given target string.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {string} [target] The string to search for.\n * @param {number} [position=0] The position to search from.\n * @returns {boolean} Returns `true` if `string` starts with `target`,\n * else `false`.\n * @example\n *\n * _.startsWith('abc', 'a');\n * // => true\n *\n * _.startsWith('abc', 'b');\n * // => false\n *\n * _.startsWith('abc', 'b', 1);\n * // => true\n */\n function startsWith(string, target, position) {\n string = toString(string);\n position = position == null\n ? 0\n : baseClamp(toInteger(position), 0, string.length);\n\n target = baseToString(target);\n return string.slice(position, position + target.length) == target;\n }\n\n /**\n * Creates a compiled template function that can interpolate data properties\n * in \"interpolate\" delimiters, HTML-escape interpolated data properties in\n * \"escape\" delimiters, and execute JavaScript in \"evaluate\" delimiters. Data\n * properties may be accessed as free variables in the template. If a setting\n * object is given, it takes precedence over `_.templateSettings` values.\n *\n * **Note:** In the development build `_.template` utilizes\n * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)\n * for easier debugging.\n *\n * For more information on precompiling templates see\n * [lodash's custom builds documentation](https://lodash.com/custom-builds).\n *\n * For more information on Chrome extension sandboxes see\n * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category String\n * @param {string} [string=''] The template string.\n * @param {Object} [options={}] The options object.\n * @param {RegExp} [options.escape=_.templateSettings.escape]\n * The HTML \"escape\" delimiter.\n * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]\n * The \"evaluate\" delimiter.\n * @param {Object} [options.imports=_.templateSettings.imports]\n * An object to import into the template as free variables.\n * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]\n * The \"interpolate\" delimiter.\n * @param {string} [options.sourceURL='lodash.templateSources[n]']\n * The sourceURL of the compiled template.\n * @param {string} [options.variable='obj']\n * The data object variable name.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the compiled template function.\n * @example\n *\n * // Use the \"interpolate\" delimiter to create a compiled template.\n * var compiled = _.template('hello <%= user %>!');\n * compiled({ 'user': 'fred' });\n * // => 'hello fred!'\n *\n * // Use the HTML \"escape\" delimiter to escape data property values.\n * var compiled = _.template('<b><%- value %></b>');\n * compiled({ 'value': '<script>' });\n * // => '<b>&lt;script&gt;</b>'\n *\n * // Use the \"evaluate\" delimiter to execute JavaScript and generate HTML.\n * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');\n * compiled({ 'users': ['fred', 'barney'] });\n * // => '<li>fred</li><li>barney</li>'\n *\n * // Use the internal `print` function in \"evaluate\" delimiters.\n * var compiled = _.template('<% print(\"hello \" + user); %>!');\n * compiled({ 'user': 'barney' });\n * // => 'hello barney!'\n *\n * // Use the ES template literal delimiter as an \"interpolate\" delimiter.\n * // Disable support by replacing the \"interpolate\" delimiter.\n * var compiled = _.template('hello ${ user }!');\n * compiled({ 'user': 'pebbles' });\n * // => 'hello pebbles!'\n *\n * // Use backslashes to treat delimiters as plain text.\n * var compiled = _.template('<%= \"\\\\<%- value %\\\\>\" %>');\n * compiled({ 'value': 'ignored' });\n * // => '<%- value %>'\n *\n * // Use the `imports` option to import `jQuery` as `jq`.\n * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';\n * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });\n * compiled({ 'users': ['fred', 'barney'] });\n * // => '<li>fred</li><li>barney</li>'\n *\n * // Use the `sourceURL` option to specify a custom sourceURL for the template.\n * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });\n * compiled(data);\n * // => Find the source of \"greeting.jst\" under the Sources tab or Resources panel of the web inspector.\n *\n * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.\n * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });\n * compiled.source;\n * // => function(data) {\n * // var __t, __p = '';\n * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';\n * // return __p;\n * // }\n *\n * // Use custom template delimiters.\n * _.templateSettings.interpolate = /{{([\\s\\S]+?)}}/g;\n * var compiled = _.template('hello {{ user }}!');\n * compiled({ 'user': 'mustache' });\n * // => 'hello mustache!'\n *\n * // Use the `source` property to inline compiled templates for meaningful\n * // line numbers in error messages and stack traces.\n * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\\\n * var JST = {\\\n * \"main\": ' + _.template(mainText).source + '\\\n * };\\\n * ');\n */\n function template(string, options, guard) {\n // Based on John Resig's `tmpl` implementation\n // (http://ejohn.org/blog/javascript-micro-templating/)\n // and Laura Doktorova's doT.js (https://github.com/olado/doT).\n var settings = lodash.templateSettings;\n\n if (guard && isIterateeCall(string, options, guard)) {\n options = undefined;\n }\n string = toString(string);\n options = assignInWith({}, options, settings, customDefaultsAssignIn);\n\n var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),\n importsKeys = keys(imports),\n importsValues = baseValues(imports, importsKeys);\n\n var isEscaping,\n isEvaluating,\n index = 0,\n interpolate = options.interpolate || reNoMatch,\n source = \"__p += '\";\n\n // Compile the regexp to match each delimiter.\n var reDelimiters = RegExp(\n (options.escape || reNoMatch).source + '|' +\n interpolate.source + '|' +\n (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +\n (options.evaluate || reNoMatch).source + '|$'\n , 'g');\n\n // Use a sourceURL for easier debugging.\n // The sourceURL gets injected into the source that's eval-ed, so be careful\n // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in\n // and escape the comment, thus injecting code that gets evaled.\n var sourceURL = '//# sourceURL=' +\n (hasOwnProperty.call(options, 'sourceURL')\n ? (options.sourceURL + '').replace(/\\s/g, ' ')\n : ('lodash.templateSources[' + (++templateCounter) + ']')\n ) + '\\n';\n\n string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {\n interpolateValue || (interpolateValue = esTemplateValue);\n\n // Escape characters that can't be included in string literals.\n source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);\n\n // Replace delimiters with snippets.\n if (escapeValue) {\n isEscaping = true;\n source += \"' +\\n__e(\" + escapeValue + \") +\\n'\";\n }\n if (evaluateValue) {\n isEvaluating = true;\n source += \"';\\n\" + evaluateValue + \";\\n__p += '\";\n }\n if (interpolateValue) {\n source += \"' +\\n((__t = (\" + interpolateValue + \")) == null ? '' : __t) +\\n'\";\n }\n index = offset + match.length;\n\n // The JS engine embedded in Adobe products needs `match` returned in\n // order to produce the correct `offset` value.\n return match;\n });\n\n source += \"';\\n\";\n\n // If `variable` is not specified wrap a with-statement around the generated\n // code to add the data object to the top of the scope chain.\n var variable = hasOwnProperty.call(options, 'variable') && options.variable;\n if (!variable) {\n source = 'with (obj) {\\n' + source + '\\n}\\n';\n }\n // Cleanup code by stripping empty strings.\n source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)\n .replace(reEmptyStringMiddle, '$1')\n .replace(reEmptyStringTrailing, '$1;');\n\n // Frame code as the function body.\n source = 'function(' + (variable || 'obj') + ') {\\n' +\n (variable\n ? ''\n : 'obj || (obj = {});\\n'\n ) +\n \"var __t, __p = ''\" +\n (isEscaping\n ? ', __e = _.escape'\n : ''\n ) +\n (isEvaluating\n ? ', __j = Array.prototype.join;\\n' +\n \"function print() { __p += __j.call(arguments, '') }\\n\"\n : ';\\n'\n ) +\n source +\n 'return __p\\n}';\n\n var result = attempt(function() {\n return Function(importsKeys, sourceURL + 'return ' + source)\n .apply(undefined, importsValues);\n });\n\n // Provide the compiled function's source by its `toString` method or\n // the `source` property as a convenience for inlining compiled templates.\n result.source = source;\n if (isError(result)) {\n throw result;\n }\n return result;\n }\n\n /**\n * Converts `string`, as a whole, to lower case just like\n * [String#toLowerCase](https://mdn.io/toLowerCase).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the lower cased string.\n * @example\n *\n * _.toLower('--Foo-Bar--');\n * // => '--foo-bar--'\n *\n * _.toLower('fooBar');\n * // => 'foobar'\n *\n * _.toLower('__FOO_BAR__');\n * // => '__foo_bar__'\n */\n function toLower(value) {\n return toString(value).toLowerCase();\n }\n\n /**\n * Converts `string`, as a whole, to upper case just like\n * [String#toUpperCase](https://mdn.io/toUpperCase).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the upper cased string.\n * @example\n *\n * _.toUpper('--foo-bar--');\n * // => '--FOO-BAR--'\n *\n * _.toUpper('fooBar');\n * // => 'FOOBAR'\n *\n * _.toUpper('__foo_bar__');\n * // => '__FOO_BAR__'\n */\n function toUpper(value) {\n return toString(value).toUpperCase();\n }\n\n /**\n * Removes leading and trailing whitespace or specified characters from `string`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to trim.\n * @param {string} [chars=whitespace] The characters to trim.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the trimmed string.\n * @example\n *\n * _.trim(' abc ');\n * // => 'abc'\n *\n * _.trim('-_-abc-_-', '_-');\n * // => 'abc'\n *\n * _.map([' foo ', ' bar '], _.trim);\n * // => ['foo', 'bar']\n */\n function trim(string, chars, guard) {\n string = toString(string);\n if (string && (guard || chars === undefined)) {\n return string.replace(reTrim, '');\n }\n if (!string || !(chars = baseToString(chars))) {\n return string;\n }\n var strSymbols = stringToArray(string),\n chrSymbols = stringToArray(chars),\n start = charsStartIndex(strSymbols, chrSymbols),\n end = charsEndIndex(strSymbols, chrSymbols) + 1;\n\n return castSlice(strSymbols, start, end).join('');\n }\n\n /**\n * Removes trailing whitespace or specified characters from `string`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to trim.\n * @param {string} [chars=whitespace] The characters to trim.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the trimmed string.\n * @example\n *\n * _.trimEnd(' abc ');\n * // => ' abc'\n *\n * _.trimEnd('-_-abc-_-', '_-');\n * // => '-_-abc'\n */\n function trimEnd(string, chars, guard) {\n string = toString(string);\n if (string && (guard || chars === undefined)) {\n return string.replace(reTrimEnd, '');\n }\n if (!string || !(chars = baseToString(chars))) {\n return string;\n }\n var strSymbols = stringToArray(string),\n end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;\n\n return castSlice(strSymbols, 0, end).join('');\n }\n\n /**\n * Removes leading whitespace or specified characters from `string`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to trim.\n * @param {string} [chars=whitespace] The characters to trim.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the trimmed string.\n * @example\n *\n * _.trimStart(' abc ');\n * // => 'abc '\n *\n * _.trimStart('-_-abc-_-', '_-');\n * // => 'abc-_-'\n */\n function trimStart(string, chars, guard) {\n string = toString(string);\n if (string && (guard || chars === undefined)) {\n return string.replace(reTrimStart, '');\n }\n if (!string || !(chars = baseToString(chars))) {\n return string;\n }\n var strSymbols = stringToArray(string),\n start = charsStartIndex(strSymbols, stringToArray(chars));\n\n return castSlice(strSymbols, start).join('');\n }\n\n /**\n * Truncates `string` if it's longer than the given maximum string length.\n * The last characters of the truncated string are replaced with the omission\n * string which defaults to \"...\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to truncate.\n * @param {Object} [options={}] The options object.\n * @param {number} [options.length=30] The maximum string length.\n * @param {string} [options.omission='...'] The string to indicate text is omitted.\n * @param {RegExp|string} [options.separator] The separator pattern to truncate to.\n * @returns {string} Returns the truncated string.\n * @example\n *\n * _.truncate('hi-diddly-ho there, neighborino');\n * // => 'hi-diddly-ho there, neighbo...'\n *\n * _.truncate('hi-diddly-ho there, neighborino', {\n * 'length': 24,\n * 'separator': ' '\n * });\n * // => 'hi-diddly-ho there,...'\n *\n * _.truncate('hi-diddly-ho there, neighborino', {\n * 'length': 24,\n * 'separator': /,? +/\n * });\n * // => 'hi-diddly-ho there...'\n *\n * _.truncate('hi-diddly-ho there, neighborino', {\n * 'omission': ' [...]'\n * });\n * // => 'hi-diddly-ho there, neig [...]'\n */\n function truncate(string, options) {\n var length = DEFAULT_TRUNC_LENGTH,\n omission = DEFAULT_TRUNC_OMISSION;\n\n if (isObject(options)) {\n var separator = 'separator' in options ? options.separator : separator;\n length = 'length' in options ? toInteger(options.length) : length;\n omission = 'omission' in options ? baseToString(options.omission) : omission;\n }\n string = toString(string);\n\n var strLength = string.length;\n if (hasUnicode(string)) {\n var strSymbols = stringToArray(string);\n strLength = strSymbols.length;\n }\n if (length >= strLength) {\n return string;\n }\n var end = length - stringSize(omission);\n if (end < 1) {\n return omission;\n }\n var result = strSymbols\n ? castSlice(strSymbols, 0, end).join('')\n : string.slice(0, end);\n\n if (separator === undefined) {\n return result + omission;\n }\n if (strSymbols) {\n end += (result.length - end);\n }\n if (isRegExp(separator)) {\n if (string.slice(end).search(separator)) {\n var match,\n substring = result;\n\n if (!separator.global) {\n separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');\n }\n separator.lastIndex = 0;\n while ((match = separator.exec(substring))) {\n var newEnd = match.index;\n }\n result = result.slice(0, newEnd === undefined ? end : newEnd);\n }\n } else if (string.indexOf(baseToString(separator), end) != end) {\n var index = result.lastIndexOf(separator);\n if (index > -1) {\n result = result.slice(0, index);\n }\n }\n return result + omission;\n }\n\n /**\n * The inverse of `_.escape`; this method converts the HTML entities\n * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to\n * their corresponding characters.\n *\n * **Note:** No other HTML entities are unescaped. To unescape additional\n * HTML entities use a third-party library like [_he_](https://mths.be/he).\n *\n * @static\n * @memberOf _\n * @since 0.6.0\n * @category String\n * @param {string} [string=''] The string to unescape.\n * @returns {string} Returns the unescaped string.\n * @example\n *\n * _.unescape('fred, barney, &amp; pebbles');\n * // => 'fred, barney, & pebbles'\n */\n function unescape(string) {\n string = toString(string);\n return (string && reHasEscapedHtml.test(string))\n ? string.replace(reEscapedHtml, unescapeHtmlChar)\n : string;\n }\n\n /**\n * Converts `string`, as space separated words, to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the upper cased string.\n * @example\n *\n * _.upperCase('--foo-bar');\n * // => 'FOO BAR'\n *\n * _.upperCase('fooBar');\n * // => 'FOO BAR'\n *\n * _.upperCase('__foo_bar__');\n * // => 'FOO BAR'\n */\n var upperCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + word.toUpperCase();\n });\n\n /**\n * Converts the first character of `string` to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.upperFirst('fred');\n * // => 'Fred'\n *\n * _.upperFirst('FRED');\n * // => 'FRED'\n */\n var upperFirst = createCaseFirst('toUpperCase');\n\n /**\n * Splits `string` into an array of its words.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {RegExp|string} [pattern] The pattern to match words.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the words of `string`.\n * @example\n *\n * _.words('fred, barney, & pebbles');\n * // => ['fred', 'barney', 'pebbles']\n *\n * _.words('fred, barney, & pebbles', /[^, ]+/g);\n * // => ['fred', 'barney', '&', 'pebbles']\n */\n function words(string, pattern, guard) {\n string = toString(string);\n pattern = guard ? undefined : pattern;\n\n if (pattern === undefined) {\n return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);\n }\n return string.match(pattern) || [];\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Attempts to invoke `func`, returning either the result or the caught error\n * object. Any additional arguments are provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {Function} func The function to attempt.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {*} Returns the `func` result or error object.\n * @example\n *\n * // Avoid throwing errors for invalid selectors.\n * var elements = _.attempt(function(selector) {\n * return document.querySelectorAll(selector);\n * }, '>_>');\n *\n * if (_.isError(elements)) {\n * elements = [];\n * }\n */\n var attempt = baseRest(function(func, args) {\n try {\n return apply(func, undefined, args);\n } catch (e) {\n return isError(e) ? e : new Error(e);\n }\n });\n\n /**\n * Binds methods of an object to the object itself, overwriting the existing\n * method.\n *\n * **Note:** This method doesn't set the \"length\" property of bound functions.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {Object} object The object to bind and assign the bound methods to.\n * @param {...(string|string[])} methodNames The object method names to bind.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var view = {\n * 'label': 'docs',\n * 'click': function() {\n * console.log('clicked ' + this.label);\n * }\n * };\n *\n * _.bindAll(view, ['click']);\n * jQuery(element).on('click', view.click);\n * // => Logs 'clicked docs' when clicked.\n */\n var bindAll = flatRest(function(object, methodNames) {\n arrayEach(methodNames, function(key) {\n key = toKey(key);\n baseAssignValue(object, key, bind(object[key], object));\n });\n return object;\n });\n\n /**\n * Creates a function that iterates over `pairs` and invokes the corresponding\n * function of the first predicate to return truthy. The predicate-function\n * pairs are invoked with the `this` binding and arguments of the created\n * function.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {Array} pairs The predicate-function pairs.\n * @returns {Function} Returns the new composite function.\n * @example\n *\n * var func = _.cond([\n * [_.matches({ 'a': 1 }), _.constant('matches A')],\n * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],\n * [_.stubTrue, _.constant('no match')]\n * ]);\n *\n * func({ 'a': 1, 'b': 2 });\n * // => 'matches A'\n *\n * func({ 'a': 0, 'b': 1 });\n * // => 'matches B'\n *\n * func({ 'a': '1', 'b': '2' });\n * // => 'no match'\n */\n function cond(pairs) {\n var length = pairs == null ? 0 : pairs.length,\n toIteratee = getIteratee();\n\n pairs = !length ? [] : arrayMap(pairs, function(pair) {\n if (typeof pair[1] != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return [toIteratee(pair[0]), pair[1]];\n });\n\n return baseRest(function(args) {\n var index = -1;\n while (++index < length) {\n var pair = pairs[index];\n if (apply(pair[0], this, args)) {\n return apply(pair[1], this, args);\n }\n }\n });\n }\n\n /**\n * Creates a function that invokes the predicate properties of `source` with\n * the corresponding property values of a given object, returning `true` if\n * all predicates return truthy, else `false`.\n *\n * **Note:** The created function is equivalent to `_.conformsTo` with\n * `source` partially applied.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {Object} source The object of property predicates to conform to.\n * @returns {Function} Returns the new spec function.\n * @example\n *\n * var objects = [\n * { 'a': 2, 'b': 1 },\n * { 'a': 1, 'b': 2 }\n * ];\n *\n * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));\n * // => [{ 'a': 1, 'b': 2 }]\n */\n function conforms(source) {\n return baseConforms(baseClone(source, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\n function constant(value) {\n return function() {\n return value;\n };\n }\n\n /**\n * Checks `value` to determine whether a default value should be returned in\n * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,\n * or `undefined`.\n *\n * @static\n * @memberOf _\n * @since 4.14.0\n * @category Util\n * @param {*} value The value to check.\n * @param {*} defaultValue The default value.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * _.defaultTo(1, 10);\n * // => 1\n *\n * _.defaultTo(undefined, 10);\n * // => 10\n */\n function defaultTo(value, defaultValue) {\n return (value == null || value !== value) ? defaultValue : value;\n }\n\n /**\n * Creates a function that returns the result of invoking the given functions\n * with the `this` binding of the created function, where each successive\n * invocation is supplied the return value of the previous.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {...(Function|Function[])} [funcs] The functions to invoke.\n * @returns {Function} Returns the new composite function.\n * @see _.flowRight\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var addSquare = _.flow([_.add, square]);\n * addSquare(1, 2);\n * // => 9\n */\n var flow = createFlow();\n\n /**\n * This method is like `_.flow` except that it creates a function that\n * invokes the given functions from right to left.\n *\n * @static\n * @since 3.0.0\n * @memberOf _\n * @category Util\n * @param {...(Function|Function[])} [funcs] The functions to invoke.\n * @returns {Function} Returns the new composite function.\n * @see _.flow\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var addSquare = _.flowRight([square, _.add]);\n * addSquare(1, 2);\n * // => 9\n */\n var flowRight = createFlow(true);\n\n /**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\n function identity(value) {\n return value;\n }\n\n /**\n * Creates a function that invokes `func` with the arguments of the created\n * function. If `func` is a property name, the created function returns the\n * property value for a given element. If `func` is an array or object, the\n * created function returns `true` for elements that contain the equivalent\n * source properties, otherwise it returns `false`.\n *\n * @static\n * @since 4.0.0\n * @memberOf _\n * @category Util\n * @param {*} [func=_.identity] The value to convert to a callback.\n * @returns {Function} Returns the callback.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': true },\n * { 'user': 'fred', 'age': 40, 'active': false }\n * ];\n *\n * // The `_.matches` iteratee shorthand.\n * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));\n * // => [{ 'user': 'barney', 'age': 36, 'active': true }]\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.filter(users, _.iteratee(['user', 'fred']));\n * // => [{ 'user': 'fred', 'age': 40 }]\n *\n * // The `_.property` iteratee shorthand.\n * _.map(users, _.iteratee('user'));\n * // => ['barney', 'fred']\n *\n * // Create custom iteratee shorthands.\n * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {\n * return !_.isRegExp(func) ? iteratee(func) : function(string) {\n * return func.test(string);\n * };\n * });\n *\n * _.filter(['abc', 'def'], /ef/);\n * // => ['def']\n */\n function iteratee(func) {\n return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that performs a partial deep comparison between a given\n * object and `source`, returning `true` if the given object has equivalent\n * property values, else `false`.\n *\n * **Note:** The created function is equivalent to `_.isMatch` with `source`\n * partially applied.\n *\n * Partial comparisons will match empty array and empty object `source`\n * values against any array or object value, respectively. See `_.isEqual`\n * for a list of supported value comparisons.\n *\n * **Note:** Multiple values can be checked by combining several matchers\n * using `_.overSome`\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new spec function.\n * @example\n *\n * var objects = [\n * { 'a': 1, 'b': 2, 'c': 3 },\n * { 'a': 4, 'b': 5, 'c': 6 }\n * ];\n *\n * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));\n * // => [{ 'a': 4, 'b': 5, 'c': 6 }]\n *\n * // Checking for several possible values\n * _.filter(users, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));\n * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]\n */\n function matches(source) {\n return baseMatches(baseClone(source, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that performs a partial deep comparison between the\n * value at `path` of a given object to `srcValue`, returning `true` if the\n * object value is equivalent, else `false`.\n *\n * **Note:** Partial comparisons will match empty array and empty object\n * `srcValue` values against any array or object value, respectively. See\n * `_.isEqual` for a list of supported value comparisons.\n *\n * **Note:** Multiple values can be checked by combining several matchers\n * using `_.overSome`\n *\n * @static\n * @memberOf _\n * @since 3.2.0\n * @category Util\n * @param {Array|string} path The path of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n * @example\n *\n * var objects = [\n * { 'a': 1, 'b': 2, 'c': 3 },\n * { 'a': 4, 'b': 5, 'c': 6 }\n * ];\n *\n * _.find(objects, _.matchesProperty('a', 4));\n * // => { 'a': 4, 'b': 5, 'c': 6 }\n *\n * // Checking for several possible values\n * _.filter(users, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));\n * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]\n */\n function matchesProperty(path, srcValue) {\n return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that invokes the method at `path` of a given object.\n * Any additional arguments are provided to the invoked method.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Util\n * @param {Array|string} path The path of the method to invoke.\n * @param {...*} [args] The arguments to invoke the method with.\n * @returns {Function} Returns the new invoker function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': _.constant(2) } },\n * { 'a': { 'b': _.constant(1) } }\n * ];\n *\n * _.map(objects, _.method('a.b'));\n * // => [2, 1]\n *\n * _.map(objects, _.method(['a', 'b']));\n * // => [2, 1]\n */\n var method = baseRest(function(path, args) {\n return function(object) {\n return baseInvoke(object, path, args);\n };\n });\n\n /**\n * The opposite of `_.method`; this method creates a function that invokes\n * the method at a given path of `object`. Any additional arguments are\n * provided to the invoked method.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Util\n * @param {Object} object The object to query.\n * @param {...*} [args] The arguments to invoke the method with.\n * @returns {Function} Returns the new invoker function.\n * @example\n *\n * var array = _.times(3, _.constant),\n * object = { 'a': array, 'b': array, 'c': array };\n *\n * _.map(['a[2]', 'c[0]'], _.methodOf(object));\n * // => [2, 0]\n *\n * _.map([['a', '2'], ['c', '0']], _.methodOf(object));\n * // => [2, 0]\n */\n var methodOf = baseRest(function(object, args) {\n return function(path) {\n return baseInvoke(object, path, args);\n };\n });\n\n /**\n * Adds all own enumerable string keyed function properties of a source\n * object to the destination object. If `object` is a function, then methods\n * are added to its prototype as well.\n *\n * **Note:** Use `_.runInContext` to create a pristine `lodash` function to\n * avoid conflicts caused by modifying the original.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {Function|Object} [object=lodash] The destination object.\n * @param {Object} source The object of functions to add.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.chain=true] Specify whether mixins are chainable.\n * @returns {Function|Object} Returns `object`.\n * @example\n *\n * function vowels(string) {\n * return _.filter(string, function(v) {\n * return /[aeiou]/i.test(v);\n * });\n * }\n *\n * _.mixin({ 'vowels': vowels });\n * _.vowels('fred');\n * // => ['e']\n *\n * _('fred').vowels().value();\n * // => ['e']\n *\n * _.mixin({ 'vowels': vowels }, { 'chain': false });\n * _('fred').vowels();\n * // => ['e']\n */\n function mixin(object, source, options) {\n var props = keys(source),\n methodNames = baseFunctions(source, props);\n\n if (options == null &&\n !(isObject(source) && (methodNames.length || !props.length))) {\n options = source;\n source = object;\n object = this;\n methodNames = baseFunctions(source, keys(source));\n }\n var chain = !(isObject(options) && 'chain' in options) || !!options.chain,\n isFunc = isFunction(object);\n\n arrayEach(methodNames, function(methodName) {\n var func = source[methodName];\n object[methodName] = func;\n if (isFunc) {\n object.prototype[methodName] = function() {\n var chainAll = this.__chain__;\n if (chain || chainAll) {\n var result = object(this.__wrapped__),\n actions = result.__actions__ = copyArray(this.__actions__);\n\n actions.push({ 'func': func, 'args': arguments, 'thisArg': object });\n result.__chain__ = chainAll;\n return result;\n }\n return func.apply(object, arrayPush([this.value()], arguments));\n };\n }\n });\n\n return object;\n }\n\n /**\n * Reverts the `_` variable to its previous value and returns a reference to\n * the `lodash` function.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @returns {Function} Returns the `lodash` function.\n * @example\n *\n * var lodash = _.noConflict();\n */\n function noConflict() {\n if (root._ === this) {\n root._ = oldDash;\n }\n return this;\n }\n\n /**\n * This method returns `undefined`.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Util\n * @example\n *\n * _.times(2, _.noop);\n * // => [undefined, undefined]\n */\n function noop() {\n // No operation performed.\n }\n\n /**\n * Creates a function that gets the argument at index `n`. If `n` is negative,\n * the nth argument from the end is returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {number} [n=0] The index of the argument to return.\n * @returns {Function} Returns the new pass-thru function.\n * @example\n *\n * var func = _.nthArg(1);\n * func('a', 'b', 'c', 'd');\n * // => 'b'\n *\n * var func = _.nthArg(-2);\n * func('a', 'b', 'c', 'd');\n * // => 'c'\n */\n function nthArg(n) {\n n = toInteger(n);\n return baseRest(function(args) {\n return baseNth(args, n);\n });\n }\n\n /**\n * Creates a function that invokes `iteratees` with the arguments it receives\n * and returns their results.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to invoke.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var func = _.over([Math.max, Math.min]);\n *\n * func(1, 2, 3, 4);\n * // => [4, 1]\n */\n var over = createOver(arrayMap);\n\n /**\n * Creates a function that checks if **all** of the `predicates` return\n * truthy when invoked with the arguments it receives.\n *\n * Following shorthands are possible for providing predicates.\n * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.\n * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {...(Function|Function[])} [predicates=[_.identity]]\n * The predicates to check.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var func = _.overEvery([Boolean, isFinite]);\n *\n * func('1');\n * // => true\n *\n * func(null);\n * // => false\n *\n * func(NaN);\n * // => false\n */\n var overEvery = createOver(arrayEvery);\n\n /**\n * Creates a function that checks if **any** of the `predicates` return\n * truthy when invoked with the arguments it receives.\n *\n * Following shorthands are possible for providing predicates.\n * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.\n * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {...(Function|Function[])} [predicates=[_.identity]]\n * The predicates to check.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var func = _.overSome([Boolean, isFinite]);\n *\n * func('1');\n * // => true\n *\n * func(null);\n * // => true\n *\n * func(NaN);\n * // => false\n *\n * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])\n * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])\n */\n var overSome = createOver(arraySome);\n\n /**\n * Creates a function that returns the value at `path` of a given object.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': 2 } },\n * { 'a': { 'b': 1 } }\n * ];\n *\n * _.map(objects, _.property('a.b'));\n * // => [2, 1]\n *\n * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');\n * // => [1, 2]\n */\n function property(path) {\n return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);\n }\n\n /**\n * The opposite of `_.property`; this method creates a function that returns\n * the value at a given path of `object`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n * @example\n *\n * var array = [0, 1, 2],\n * object = { 'a': array, 'b': array, 'c': array };\n *\n * _.map(['a[2]', 'c[0]'], _.propertyOf(object));\n * // => [2, 0]\n *\n * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));\n * // => [2, 0]\n */\n function propertyOf(object) {\n return function(path) {\n return object == null ? undefined : baseGet(object, path);\n };\n }\n\n /**\n * Creates an array of numbers (positive and/or negative) progressing from\n * `start` up to, but not including, `end`. A step of `-1` is used if a negative\n * `start` is specified without an `end` or `step`. If `end` is not specified,\n * it's set to `start` with `start` then set to `0`.\n *\n * **Note:** JavaScript follows the IEEE-754 standard for resolving\n * floating-point values which can produce unexpected results.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {number} [start=0] The start of the range.\n * @param {number} end The end of the range.\n * @param {number} [step=1] The value to increment or decrement by.\n * @returns {Array} Returns the range of numbers.\n * @see _.inRange, _.rangeRight\n * @example\n *\n * _.range(4);\n * // => [0, 1, 2, 3]\n *\n * _.range(-4);\n * // => [0, -1, -2, -3]\n *\n * _.range(1, 5);\n * // => [1, 2, 3, 4]\n *\n * _.range(0, 20, 5);\n * // => [0, 5, 10, 15]\n *\n * _.range(0, -4, -1);\n * // => [0, -1, -2, -3]\n *\n * _.range(1, 4, 0);\n * // => [1, 1, 1]\n *\n * _.range(0);\n * // => []\n */\n var range = createRange();\n\n /**\n * This method is like `_.range` except that it populates values in\n * descending order.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {number} [start=0] The start of the range.\n * @param {number} end The end of the range.\n * @param {number} [step=1] The value to increment or decrement by.\n * @returns {Array} Returns the range of numbers.\n * @see _.inRange, _.range\n * @example\n *\n * _.rangeRight(4);\n * // => [3, 2, 1, 0]\n *\n * _.rangeRight(-4);\n * // => [-3, -2, -1, 0]\n *\n * _.rangeRight(1, 5);\n * // => [4, 3, 2, 1]\n *\n * _.rangeRight(0, 20, 5);\n * // => [15, 10, 5, 0]\n *\n * _.rangeRight(0, -4, -1);\n * // => [-3, -2, -1, 0]\n *\n * _.rangeRight(1, 4, 0);\n * // => [1, 1, 1]\n *\n * _.rangeRight(0);\n * // => []\n */\n var rangeRight = createRange(true);\n\n /**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\n function stubArray() {\n return [];\n }\n\n /**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\n function stubFalse() {\n return false;\n }\n\n /**\n * This method returns a new empty object.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Object} Returns the new empty object.\n * @example\n *\n * var objects = _.times(2, _.stubObject);\n *\n * console.log(objects);\n * // => [{}, {}]\n *\n * console.log(objects[0] === objects[1]);\n * // => false\n */\n function stubObject() {\n return {};\n }\n\n /**\n * This method returns an empty string.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {string} Returns the empty string.\n * @example\n *\n * _.times(2, _.stubString);\n * // => ['', '']\n */\n function stubString() {\n return '';\n }\n\n /**\n * This method returns `true`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `true`.\n * @example\n *\n * _.times(2, _.stubTrue);\n * // => [true, true]\n */\n function stubTrue() {\n return true;\n }\n\n /**\n * Invokes the iteratee `n` times, returning an array of the results of\n * each invocation. The iteratee is invoked with one argument; (index).\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n * @example\n *\n * _.times(3, String);\n * // => ['0', '1', '2']\n *\n * _.times(4, _.constant(0));\n * // => [0, 0, 0, 0]\n */\n function times(n, iteratee) {\n n = toInteger(n);\n if (n < 1 || n > MAX_SAFE_INTEGER) {\n return [];\n }\n var index = MAX_ARRAY_LENGTH,\n length = nativeMin(n, MAX_ARRAY_LENGTH);\n\n iteratee = getIteratee(iteratee);\n n -= MAX_ARRAY_LENGTH;\n\n var result = baseTimes(length, iteratee);\n while (++index < n) {\n iteratee(index);\n }\n return result;\n }\n\n /**\n * Converts `value` to a property path array.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {*} value The value to convert.\n * @returns {Array} Returns the new property path array.\n * @example\n *\n * _.toPath('a.b.c');\n * // => ['a', 'b', 'c']\n *\n * _.toPath('a[0].b.c');\n * // => ['a', '0', 'b', 'c']\n */\n function toPath(value) {\n if (isArray(value)) {\n return arrayMap(value, toKey);\n }\n return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));\n }\n\n /**\n * Generates a unique ID. If `prefix` is given, the ID is appended to it.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {string} [prefix=''] The value to prefix the ID with.\n * @returns {string} Returns the unique ID.\n * @example\n *\n * _.uniqueId('contact_');\n * // => 'contact_104'\n *\n * _.uniqueId();\n * // => '105'\n */\n function uniqueId(prefix) {\n var id = ++idCounter;\n return toString(prefix) + id;\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Adds two numbers.\n *\n * @static\n * @memberOf _\n * @since 3.4.0\n * @category Math\n * @param {number} augend The first number in an addition.\n * @param {number} addend The second number in an addition.\n * @returns {number} Returns the total.\n * @example\n *\n * _.add(6, 4);\n * // => 10\n */\n var add = createMathOperation(function(augend, addend) {\n return augend + addend;\n }, 0);\n\n /**\n * Computes `number` rounded up to `precision`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Math\n * @param {number} number The number to round up.\n * @param {number} [precision=0] The precision to round up to.\n * @returns {number} Returns the rounded up number.\n * @example\n *\n * _.ceil(4.006);\n * // => 5\n *\n * _.ceil(6.004, 2);\n * // => 6.01\n *\n * _.ceil(6040, -2);\n * // => 6100\n */\n var ceil = createRound('ceil');\n\n /**\n * Divide two numbers.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Math\n * @param {number} dividend The first number in a division.\n * @param {number} divisor The second number in a division.\n * @returns {number} Returns the quotient.\n * @example\n *\n * _.divide(6, 4);\n * // => 1.5\n */\n var divide = createMathOperation(function(dividend, divisor) {\n return dividend / divisor;\n }, 1);\n\n /**\n * Computes `number` rounded down to `precision`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Math\n * @param {number} number The number to round down.\n * @param {number} [precision=0] The precision to round down to.\n * @returns {number} Returns the rounded down number.\n * @example\n *\n * _.floor(4.006);\n * // => 4\n *\n * _.floor(0.046, 2);\n * // => 0.04\n *\n * _.floor(4060, -2);\n * // => 4000\n */\n var floor = createRound('floor');\n\n /**\n * Computes the maximum value of `array`. If `array` is empty or falsey,\n * `undefined` is returned.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {*} Returns the maximum value.\n * @example\n *\n * _.max([4, 2, 8, 6]);\n * // => 8\n *\n * _.max([]);\n * // => undefined\n */\n function max(array) {\n return (array && array.length)\n ? baseExtremum(array, identity, baseGt)\n : undefined;\n }\n\n /**\n * This method is like `_.max` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * the value is ranked. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {*} Returns the maximum value.\n * @example\n *\n * var objects = [{ 'n': 1 }, { 'n': 2 }];\n *\n * _.maxBy(objects, function(o) { return o.n; });\n * // => { 'n': 2 }\n *\n * // The `_.property` iteratee shorthand.\n * _.maxBy(objects, 'n');\n * // => { 'n': 2 }\n */\n function maxBy(array, iteratee) {\n return (array && array.length)\n ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)\n : undefined;\n }\n\n /**\n * Computes the mean of the values in `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {number} Returns the mean.\n * @example\n *\n * _.mean([4, 2, 8, 6]);\n * // => 5\n */\n function mean(array) {\n return baseMean(array, identity);\n }\n\n /**\n * This method is like `_.mean` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the value to be averaged.\n * The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the mean.\n * @example\n *\n * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];\n *\n * _.meanBy(objects, function(o) { return o.n; });\n * // => 5\n *\n * // The `_.property` iteratee shorthand.\n * _.meanBy(objects, 'n');\n * // => 5\n */\n function meanBy(array, iteratee) {\n return baseMean(array, getIteratee(iteratee, 2));\n }\n\n /**\n * Computes the minimum value of `array`. If `array` is empty or falsey,\n * `undefined` is returned.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {*} Returns the minimum value.\n * @example\n *\n * _.min([4, 2, 8, 6]);\n * // => 2\n *\n * _.min([]);\n * // => undefined\n */\n function min(array) {\n return (array && array.length)\n ? baseExtremum(array, identity, baseLt)\n : undefined;\n }\n\n /**\n * This method is like `_.min` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * the value is ranked. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {*} Returns the minimum value.\n * @example\n *\n * var objects = [{ 'n': 1 }, { 'n': 2 }];\n *\n * _.minBy(objects, function(o) { return o.n; });\n * // => { 'n': 1 }\n *\n * // The `_.property` iteratee shorthand.\n * _.minBy(objects, 'n');\n * // => { 'n': 1 }\n */\n function minBy(array, iteratee) {\n return (array && array.length)\n ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)\n : undefined;\n }\n\n /**\n * Multiply two numbers.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Math\n * @param {number} multiplier The first number in a multiplication.\n * @param {number} multiplicand The second number in a multiplication.\n * @returns {number} Returns the product.\n * @example\n *\n * _.multiply(6, 4);\n * // => 24\n */\n var multiply = createMathOperation(function(multiplier, multiplicand) {\n return multiplier * multiplicand;\n }, 1);\n\n /**\n * Computes `number` rounded to `precision`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Math\n * @param {number} number The number to round.\n * @param {number} [precision=0] The precision to round to.\n * @returns {number} Returns the rounded number.\n * @example\n *\n * _.round(4.006);\n * // => 4\n *\n * _.round(4.006, 2);\n * // => 4.01\n *\n * _.round(4060, -2);\n * // => 4100\n */\n var round = createRound('round');\n\n /**\n * Subtract two numbers.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {number} minuend The first number in a subtraction.\n * @param {number} subtrahend The second number in a subtraction.\n * @returns {number} Returns the difference.\n * @example\n *\n * _.subtract(6, 4);\n * // => 2\n */\n var subtract = createMathOperation(function(minuend, subtrahend) {\n return minuend - subtrahend;\n }, 0);\n\n /**\n * Computes the sum of the values in `array`.\n *\n * @static\n * @memberOf _\n * @since 3.4.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {number} Returns the sum.\n * @example\n *\n * _.sum([4, 2, 8, 6]);\n * // => 20\n */\n function sum(array) {\n return (array && array.length)\n ? baseSum(array, identity)\n : 0;\n }\n\n /**\n * This method is like `_.sum` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the value to be summed.\n * The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the sum.\n * @example\n *\n * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];\n *\n * _.sumBy(objects, function(o) { return o.n; });\n * // => 20\n *\n * // The `_.property` iteratee shorthand.\n * _.sumBy(objects, 'n');\n * // => 20\n */\n function sumBy(array, iteratee) {\n return (array && array.length)\n ? baseSum(array, getIteratee(iteratee, 2))\n : 0;\n }\n\n /*------------------------------------------------------------------------*/\n\n // Add methods that return wrapped values in chain sequences.\n lodash.after = after;\n lodash.ary = ary;\n lodash.assign = assign;\n lodash.assignIn = assignIn;\n lodash.assignInWith = assignInWith;\n lodash.assignWith = assignWith;\n lodash.at = at;\n lodash.before = before;\n lodash.bind = bind;\n lodash.bindAll = bindAll;\n lodash.bindKey = bindKey;\n lodash.castArray = castArray;\n lodash.chain = chain;\n lodash.chunk = chunk;\n lodash.compact = compact;\n lodash.concat = concat;\n lodash.cond = cond;\n lodash.conforms = conforms;\n lodash.constant = constant;\n lodash.countBy = countBy;\n lodash.create = create;\n lodash.curry = curry;\n lodash.curryRight = curryRight;\n lodash.debounce = debounce;\n lodash.defaults = defaults;\n lodash.defaultsDeep = defaultsDeep;\n lodash.defer = defer;\n lodash.delay = delay;\n lodash.difference = difference;\n lodash.differenceBy = differenceBy;\n lodash.differenceWith = differenceWith;\n lodash.drop = drop;\n lodash.dropRight = dropRight;\n lodash.dropRightWhile = dropRightWhile;\n lodash.dropWhile = dropWhile;\n lodash.fill = fill;\n lodash.filter = filter;\n lodash.flatMap = flatMap;\n lodash.flatMapDeep = flatMapDeep;\n lodash.flatMapDepth = flatMapDepth;\n lodash.flatten = flatten;\n lodash.flattenDeep = flattenDeep;\n lodash.flattenDepth = flattenDepth;\n lodash.flip = flip;\n lodash.flow = flow;\n lodash.flowRight = flowRight;\n lodash.fromPairs = fromPairs;\n lodash.functions = functions;\n lodash.functionsIn = functionsIn;\n lodash.groupBy = groupBy;\n lodash.initial = initial;\n lodash.intersection = intersection;\n lodash.intersectionBy = intersectionBy;\n lodash.intersectionWith = intersectionWith;\n lodash.invert = invert;\n lodash.invertBy = invertBy;\n lodash.invokeMap = invokeMap;\n lodash.iteratee = iteratee;\n lodash.keyBy = keyBy;\n lodash.keys = keys;\n lodash.keysIn = keysIn;\n lodash.map = map;\n lodash.mapKeys = mapKeys;\n lodash.mapValues = mapValues;\n lodash.matches = matches;\n lodash.matchesProperty = matchesProperty;\n lodash.memoize = memoize;\n lodash.merge = merge;\n lodash.mergeWith = mergeWith;\n lodash.method = method;\n lodash.methodOf = methodOf;\n lodash.mixin = mixin;\n lodash.negate = negate;\n lodash.nthArg = nthArg;\n lodash.omit = omit;\n lodash.omitBy = omitBy;\n lodash.once = once;\n lodash.orderBy = orderBy;\n lodash.over = over;\n lodash.overArgs = overArgs;\n lodash.overEvery = overEvery;\n lodash.overSome = overSome;\n lodash.partial = partial;\n lodash.partialRight = partialRight;\n lodash.partition = partition;\n lodash.pick = pick;\n lodash.pickBy = pickBy;\n lodash.property = property;\n lodash.propertyOf = propertyOf;\n lodash.pull = pull;\n lodash.pullAll = pullAll;\n lodash.pullAllBy = pullAllBy;\n lodash.pullAllWith = pullAllWith;\n lodash.pullAt = pullAt;\n lodash.range = range;\n lodash.rangeRight = rangeRight;\n lodash.rearg = rearg;\n lodash.reject = reject;\n lodash.remove = remove;\n lodash.rest = rest;\n lodash.reverse = reverse;\n lodash.sampleSize = sampleSize;\n lodash.set = set;\n lodash.setWith = setWith;\n lodash.shuffle = shuffle;\n lodash.slice = slice;\n lodash.sortBy = sortBy;\n lodash.sortedUniq = sortedUniq;\n lodash.sortedUniqBy = sortedUniqBy;\n lodash.split = split;\n lodash.spread = spread;\n lodash.tail = tail;\n lodash.take = take;\n lodash.takeRight = takeRight;\n lodash.takeRightWhile = takeRightWhile;\n lodash.takeWhile = takeWhile;\n lodash.tap = tap;\n lodash.throttle = throttle;\n lodash.thru = thru;\n lodash.toArray = toArray;\n lodash.toPairs = toPairs;\n lodash.toPairsIn = toPairsIn;\n lodash.toPath = toPath;\n lodash.toPlainObject = toPlainObject;\n lodash.transform = transform;\n lodash.unary = unary;\n lodash.union = union;\n lodash.unionBy = unionBy;\n lodash.unionWith = unionWith;\n lodash.uniq = uniq;\n lodash.uniqBy = uniqBy;\n lodash.uniqWith = uniqWith;\n lodash.unset = unset;\n lodash.unzip = unzip;\n lodash.unzipWith = unzipWith;\n lodash.update = update;\n lodash.updateWith = updateWith;\n lodash.values = values;\n lodash.valuesIn = valuesIn;\n lodash.without = without;\n lodash.words = words;\n lodash.wrap = wrap;\n lodash.xor = xor;\n lodash.xorBy = xorBy;\n lodash.xorWith = xorWith;\n lodash.zip = zip;\n lodash.zipObject = zipObject;\n lodash.zipObjectDeep = zipObjectDeep;\n lodash.zipWith = zipWith;\n\n // Add aliases.\n lodash.entries = toPairs;\n lodash.entriesIn = toPairsIn;\n lodash.extend = assignIn;\n lodash.extendWith = assignInWith;\n\n // Add methods to `lodash.prototype`.\n mixin(lodash, lodash);\n\n /*------------------------------------------------------------------------*/\n\n // Add methods that return unwrapped values in chain sequences.\n lodash.add = add;\n lodash.attempt = attempt;\n lodash.camelCase = camelCase;\n lodash.capitalize = capitalize;\n lodash.ceil = ceil;\n lodash.clamp = clamp;\n lodash.clone = clone;\n lodash.cloneDeep = cloneDeep;\n lodash.cloneDeepWith = cloneDeepWith;\n lodash.cloneWith = cloneWith;\n lodash.conformsTo = conformsTo;\n lodash.deburr = deburr;\n lodash.defaultTo = defaultTo;\n lodash.divide = divide;\n lodash.endsWith = endsWith;\n lodash.eq = eq;\n lodash.escape = escape;\n lodash.escapeRegExp = escapeRegExp;\n lodash.every = every;\n lodash.find = find;\n lodash.findIndex = findIndex;\n lodash.findKey = findKey;\n lodash.findLast = findLast;\n lodash.findLastIndex = findLastIndex;\n lodash.findLastKey = findLastKey;\n lodash.floor = floor;\n lodash.forEach = forEach;\n lodash.forEachRight = forEachRight;\n lodash.forIn = forIn;\n lodash.forInRight = forInRight;\n lodash.forOwn = forOwn;\n lodash.forOwnRight = forOwnRight;\n lodash.get = get;\n lodash.gt = gt;\n lodash.gte = gte;\n lodash.has = has;\n lodash.hasIn = hasIn;\n lodash.head = head;\n lodash.identity = identity;\n lodash.includes = includes;\n lodash.indexOf = indexOf;\n lodash.inRange = inRange;\n lodash.invoke = invoke;\n lodash.isArguments = isArguments;\n lodash.isArray = isArray;\n lodash.isArrayBuffer = isArrayBuffer;\n lodash.isArrayLike = isArrayLike;\n lodash.isArrayLikeObject = isArrayLikeObject;\n lodash.isBoolean = isBoolean;\n lodash.isBuffer = isBuffer;\n lodash.isDate = isDate;\n lodash.isElement = isElement;\n lodash.isEmpty = isEmpty;\n lodash.isEqual = isEqual;\n lodash.isEqualWith = isEqualWith;\n lodash.isError = isError;\n lodash.isFinite = isFinite;\n lodash.isFunction = isFunction;\n lodash.isInteger = isInteger;\n lodash.isLength = isLength;\n lodash.isMap = isMap;\n lodash.isMatch = isMatch;\n lodash.isMatchWith = isMatchWith;\n lodash.isNaN = isNaN;\n lodash.isNative = isNative;\n lodash.isNil = isNil;\n lodash.isNull = isNull;\n lodash.isNumber = isNumber;\n lodash.isObject = isObject;\n lodash.isObjectLike = isObjectLike;\n lodash.isPlainObject = isPlainObject;\n lodash.isRegExp = isRegExp;\n lodash.isSafeInteger = isSafeInteger;\n lodash.isSet = isSet;\n lodash.isString = isString;\n lodash.isSymbol = isSymbol;\n lodash.isTypedArray = isTypedArray;\n lodash.isUndefined = isUndefined;\n lodash.isWeakMap = isWeakMap;\n lodash.isWeakSet = isWeakSet;\n lodash.join = join;\n lodash.kebabCase = kebabCase;\n lodash.last = last;\n lodash.lastIndexOf = lastIndexOf;\n lodash.lowerCase = lowerCase;\n lodash.lowerFirst = lowerFirst;\n lodash.lt = lt;\n lodash.lte = lte;\n lodash.max = max;\n lodash.maxBy = maxBy;\n lodash.mean = mean;\n lodash.meanBy = meanBy;\n lodash.min = min;\n lodash.minBy = minBy;\n lodash.stubArray = stubArray;\n lodash.stubFalse = stubFalse;\n lodash.stubObject = stubObject;\n lodash.stubString = stubString;\n lodash.stubTrue = stubTrue;\n lodash.multiply = multiply;\n lodash.nth = nth;\n lodash.noConflict = noConflict;\n lodash.noop = noop;\n lodash.now = now;\n lodash.pad = pad;\n lodash.padEnd = padEnd;\n lodash.padStart = padStart;\n lodash.parseInt = parseInt;\n lodash.random = random;\n lodash.reduce = reduce;\n lodash.reduceRight = reduceRight;\n lodash.repeat = repeat;\n lodash.replace = replace;\n lodash.result = result;\n lodash.round = round;\n lodash.runInContext = runInContext;\n lodash.sample = sample;\n lodash.size = size;\n lodash.snakeCase = snakeCase;\n lodash.some = some;\n lodash.sortedIndex = sortedIndex;\n lodash.sortedIndexBy = sortedIndexBy;\n lodash.sortedIndexOf = sortedIndexOf;\n lodash.sortedLastIndex = sortedLastIndex;\n lodash.sortedLastIndexBy = sortedLastIndexBy;\n lodash.sortedLastIndexOf = sortedLastIndexOf;\n lodash.startCase = startCase;\n lodash.startsWith = startsWith;\n lodash.subtract = subtract;\n lodash.sum = sum;\n lodash.sumBy = sumBy;\n lodash.template = template;\n lodash.times = times;\n lodash.toFinite = toFinite;\n lodash.toInteger = toInteger;\n lodash.toLength = toLength;\n lodash.toLower = toLower;\n lodash.toNumber = toNumber;\n lodash.toSafeInteger = toSafeInteger;\n lodash.toString = toString;\n lodash.toUpper = toUpper;\n lodash.trim = trim;\n lodash.trimEnd = trimEnd;\n lodash.trimStart = trimStart;\n lodash.truncate = truncate;\n lodash.unescape = unescape;\n lodash.uniqueId = uniqueId;\n lodash.upperCase = upperCase;\n lodash.upperFirst = upperFirst;\n\n // Add aliases.\n lodash.each = forEach;\n lodash.eachRight = forEachRight;\n lodash.first = head;\n\n mixin(lodash, (function() {\n var source = {};\n baseForOwn(lodash, function(func, methodName) {\n if (!hasOwnProperty.call(lodash.prototype, methodName)) {\n source[methodName] = func;\n }\n });\n return source;\n }()), { 'chain': false });\n\n /*------------------------------------------------------------------------*/\n\n /**\n * The semantic version number.\n *\n * @static\n * @memberOf _\n * @type {string}\n */\n lodash.VERSION = VERSION;\n\n // Assign default placeholders.\n arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {\n lodash[methodName].placeholder = lodash;\n });\n\n // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.\n arrayEach(['drop', 'take'], function(methodName, index) {\n LazyWrapper.prototype[methodName] = function(n) {\n n = n === undefined ? 1 : nativeMax(toInteger(n), 0);\n\n var result = (this.__filtered__ && !index)\n ? new LazyWrapper(this)\n : this.clone();\n\n if (result.__filtered__) {\n result.__takeCount__ = nativeMin(n, result.__takeCount__);\n } else {\n result.__views__.push({\n 'size': nativeMin(n, MAX_ARRAY_LENGTH),\n 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')\n });\n }\n return result;\n };\n\n LazyWrapper.prototype[methodName + 'Right'] = function(n) {\n return this.reverse()[methodName](n).reverse();\n };\n });\n\n // Add `LazyWrapper` methods that accept an `iteratee` value.\n arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {\n var type = index + 1,\n isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;\n\n LazyWrapper.prototype[methodName] = function(iteratee) {\n var result = this.clone();\n result.__iteratees__.push({\n 'iteratee': getIteratee(iteratee, 3),\n 'type': type\n });\n result.__filtered__ = result.__filtered__ || isFilter;\n return result;\n };\n });\n\n // Add `LazyWrapper` methods for `_.head` and `_.last`.\n arrayEach(['head', 'last'], function(methodName, index) {\n var takeName = 'take' + (index ? 'Right' : '');\n\n LazyWrapper.prototype[methodName] = function() {\n return this[takeName](1).value()[0];\n };\n });\n\n // Add `LazyWrapper` methods for `_.initial` and `_.tail`.\n arrayEach(['initial', 'tail'], function(methodName, index) {\n var dropName = 'drop' + (index ? '' : 'Right');\n\n LazyWrapper.prototype[methodName] = function() {\n return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);\n };\n });\n\n LazyWrapper.prototype.compact = function() {\n return this.filter(identity);\n };\n\n LazyWrapper.prototype.find = function(predicate) {\n return this.filter(predicate).head();\n };\n\n LazyWrapper.prototype.findLast = function(predicate) {\n return this.reverse().find(predicate);\n };\n\n LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {\n if (typeof path == 'function') {\n return new LazyWrapper(this);\n }\n return this.map(function(value) {\n return baseInvoke(value, path, args);\n });\n });\n\n LazyWrapper.prototype.reject = function(predicate) {\n return this.filter(negate(getIteratee(predicate)));\n };\n\n LazyWrapper.prototype.slice = function(start, end) {\n start = toInteger(start);\n\n var result = this;\n if (result.__filtered__ && (start > 0 || end < 0)) {\n return new LazyWrapper(result);\n }\n if (start < 0) {\n result = result.takeRight(-start);\n } else if (start) {\n result = result.drop(start);\n }\n if (end !== undefined) {\n end = toInteger(end);\n result = end < 0 ? result.dropRight(-end) : result.take(end - start);\n }\n return result;\n };\n\n LazyWrapper.prototype.takeRightWhile = function(predicate) {\n return this.reverse().takeWhile(predicate).reverse();\n };\n\n LazyWrapper.prototype.toArray = function() {\n return this.take(MAX_ARRAY_LENGTH);\n };\n\n // Add `LazyWrapper` methods to `lodash.prototype`.\n baseForOwn(LazyWrapper.prototype, function(func, methodName) {\n var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),\n isTaker = /^(?:head|last)$/.test(methodName),\n lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],\n retUnwrapped = isTaker || /^find/.test(methodName);\n\n if (!lodashFunc) {\n return;\n }\n lodash.prototype[methodName] = function() {\n var value = this.__wrapped__,\n args = isTaker ? [1] : arguments,\n isLazy = value instanceof LazyWrapper,\n iteratee = args[0],\n useLazy = isLazy || isArray(value);\n\n var interceptor = function(value) {\n var result = lodashFunc.apply(lodash, arrayPush([value], args));\n return (isTaker && chainAll) ? result[0] : result;\n };\n\n if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {\n // Avoid lazy use if the iteratee has a \"length\" value other than `1`.\n isLazy = useLazy = false;\n }\n var chainAll = this.__chain__,\n isHybrid = !!this.__actions__.length,\n isUnwrapped = retUnwrapped && !chainAll,\n onlyLazy = isLazy && !isHybrid;\n\n if (!retUnwrapped && useLazy) {\n value = onlyLazy ? value : new LazyWrapper(this);\n var result = func.apply(value, args);\n result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });\n return new LodashWrapper(result, chainAll);\n }\n if (isUnwrapped && onlyLazy) {\n return func.apply(this, args);\n }\n result = this.thru(interceptor);\n return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;\n };\n });\n\n // Add `Array` methods to `lodash.prototype`.\n arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {\n var func = arrayProto[methodName],\n chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',\n retUnwrapped = /^(?:pop|shift)$/.test(methodName);\n\n lodash.prototype[methodName] = function() {\n var args = arguments;\n if (retUnwrapped && !this.__chain__) {\n var value = this.value();\n return func.apply(isArray(value) ? value : [], args);\n }\n return this[chainName](function(value) {\n return func.apply(isArray(value) ? value : [], args);\n });\n };\n });\n\n // Map minified method names to their real names.\n baseForOwn(LazyWrapper.prototype, function(func, methodName) {\n var lodashFunc = lodash[methodName];\n if (lodashFunc) {\n var key = lodashFunc.name + '';\n if (!hasOwnProperty.call(realNames, key)) {\n realNames[key] = [];\n }\n realNames[key].push({ 'name': methodName, 'func': lodashFunc });\n }\n });\n\n realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{\n 'name': 'wrapper',\n 'func': undefined\n }];\n\n // Add methods to `LazyWrapper`.\n LazyWrapper.prototype.clone = lazyClone;\n LazyWrapper.prototype.reverse = lazyReverse;\n LazyWrapper.prototype.value = lazyValue;\n\n // Add chain sequence methods to the `lodash` wrapper.\n lodash.prototype.at = wrapperAt;\n lodash.prototype.chain = wrapperChain;\n lodash.prototype.commit = wrapperCommit;\n lodash.prototype.next = wrapperNext;\n lodash.prototype.plant = wrapperPlant;\n lodash.prototype.reverse = wrapperReverse;\n lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;\n\n // Add lazy aliases.\n lodash.prototype.first = lodash.prototype.head;\n\n if (symIterator) {\n lodash.prototype[symIterator] = wrapperToIterator;\n }\n return lodash;\n });\n\n /*--------------------------------------------------------------------------*/\n\n // Export lodash.\n var _ = runInContext();\n\n // Some AMD build optimizers, like r.js, check for condition patterns like:\n if (true) {\n // Expose Lodash on the global object to prevent errors when Lodash is\n // loaded by a script tag in the presence of an AMD loader.\n // See http://requirejs.org/docs/errors.html#mismatch for more details.\n // Use `_.noConflict` to remove Lodash from the global object.\n root._ = _;\n\n // Define as an anonymous module so, through path mapping, it can be\n // referenced as the \"underscore\" module.\n !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {\n return _;\n }).call(exports, __webpack_require__, exports, module),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n }\n // Check for `exports` after `define` in case a build optimizer adds it.\n else {}\n}.call(this));\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\"), __webpack_require__(/*! ./../webpack/buildin/module.js */ \"./node_modules/webpack/buildin/module.js\")(module)))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9sb2Rhc2gvbG9kYXNoLmpzPzJlZjAiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkNBQTJDO0FBQzNDO0FBQ0EsMkRBQTJEOztBQUUzRDtBQUNBLCtDQUErQztBQUMvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx5QkFBeUI7QUFDekIseUJBQXlCO0FBQ3pCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixNQUFNLGFBQWEsT0FBTzs7QUFFcEQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRCxFQUFFO0FBQ25EO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwyQ0FBMkMsRUFBRTs7QUFFN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrRUFBa0U7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixPQUFPO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixpQkFBaUIsT0FBTztBQUN4QjtBQUNBO0FB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QUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEIsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEIsZUFBZSxTQUFTO0FBQ3hCLGVBQWUsU0FBUztBQUN4QixlQUFlLE9BQU87QUFDdEIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEIsZUFBZSxTQUFTO0FBQ3hCLGVBQWUsU0FBUztBQUN4QixlQUFlLE9BQU87QUFDdEIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsZUFBZSxPQUFPO0FBQ3RCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsZUFBZSxFQUFFO0FBQ2pCLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsZUFBZSxPQUFPO0FBQ3RCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxTQUFTO0FBQ3hCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxTQUFTO0FBQ3hCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFp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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDLGtCQUFrQixFQUFFO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Qsa0JBQWtCLEVBQUU7QUFDdEU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsU0FBUztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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Q0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsaUJBQWlCO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixpQkFBaUIsUUFBUTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakIsZUFBZSxFQUFFO0FBQ2pCLGlCQUFpQixRQUFRO0FB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEIsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEIsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsT0FBTztBQUN0QixpQkFBaUIsT0FBTztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEIsZUFBZSxPQUFPO0FBQ3RCLGlCQUFpQixPQUFPO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEIsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEIsZ0JBQWdCLE9BQU87QUFDdkIsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixpQkFBaUIsT0FBTztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEIsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEIsZ0JBQWdCLE9BQU87QUFDdkIsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsT0FBTztBQUN0QixnQkFBZ0IsT0FBTztBQUN2QixpQkFBaUIsT0FBTztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEIsZ0JBQWdCLE9BQU87QUFDdkIsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLEtBQUssTUFBTSxpQkFBaUI7O0FBRTVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLDREQUE0RDtBQUMvRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIseUNBQXlDO0FBQ3RFO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLE1BQU0sSUFBMEU7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSSxtQ0FBTztBQUNYO0FBQ0EsS0FBSztBQUFBLG9HQUFDO0FBQ047QUFDQTtBQUNBLE9BQU8sRUFTSjtBQUNILENBQUMiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvbG9kYXNoL2xvZGFzaC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIExvZGFzaCA8aHR0cHM6Ly9sb2Rhc2guY29tLz5cbiAqIENvcHlyaWdodCBPcGVuSlMgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzIDxodHRwczovL29wZW5qc2Yub3JnLz5cbiAqIFJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL2xvZGFzaC5jb20vbGljZW5zZT5cbiAqIEJhc2VkIG9uIFVuZGVyc2NvcmUuanMgMS44LjMgPGh0dHA6Ly91bmRlcnNjb3JlanMub3JnL0xJQ0VOU0U+XG4gKiBDb3B5cmlnaHQgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnNcbiAqL1xuOyhmdW5jdGlvbigpIHtcblxuICAvKiogVXNlZCBhcyBhIHNhZmUgcmVmZXJlbmNlIGZvciBgdW5kZWZpbmVkYCBpbiBwcmUtRVM1IGVudmlyb25tZW50cy4gKi9cbiAgdmFyIHVuZGVmaW5lZDtcblxuICAvKiogVXNlZCBhcyB0aGUgc2VtYW50aWMgdmVyc2lvbiBudW1iZXIuICovXG4gIHZhciBWRVJTSU9OID0gJzQuMTcuMTknO1xuXG4gIC8qKiBVc2VkIGFzIHRoZSBzaXplIHRvIGVuYWJsZSBsYXJnZSBhcnJheSBvcHRpbWl6YXRpb25zLiAqL1xuICB2YXIgTEFSR0VfQVJSQVlfU0laRSA9IDIwMDtcblxuICAvKiogRXJyb3IgbWVzc2FnZSBjb25zdGFudHMuICovXG4gIHZhciBDT1JFX0VSUk9SX1RFWFQgPSAnVW5zdXBwb3J0ZWQgY29yZS1qcyB1c2UuIFRyeSBodHRwczovL25wbXMuaW8vc2VhcmNoP3E9cG9ueWZpbGwuJyxcbiAgICAgIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuICAvKiogVXNlZCB0byBzdGFuZC1pbiBmb3IgYHVuZGVmaW5lZGAgaGFzaCB2YWx1ZXMuICovXG4gIHZhciBIQVNIX1VOREVGSU5FRCA9ICdfX2xvZGFzaF9oYXNoX3VuZGVmaW5lZF9fJztcblxuICAvKiogVXNlZCBhcyB0aGUgbWF4aW11bSBtZW1vaXplIGNhY2hlIHNpemUuICovXG4gIHZhciBNQVhfTUVNT0laRV9TSVpFID0gNTAwO1xuXG4gIC8qKiBVc2VkIGFzIHRoZSBpbnRlcm5hbCBhcmd1bWVudCBwbGFjZWhvbGRlci4gKi9cbiAgdmFyIFBMQUNFSE9MREVSID0gJ19fbG9kYXNoX3BsYWNlaG9sZGVyX18nO1xuXG4gIC8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIGNsb25pbmcuICovXG4gIHZhciBDTE9ORV9ERUVQX0ZMQUcgPSAxLFxuICAgICAgQ0xPTkVfRkxBVF9GTEFHID0gMixcbiAgICAgIENMT05FX1NZTUJPTFNfRkxBRyA9IDQ7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgdmFsdWUgY29tcGFyaXNvbnMuICovXG4gIHZhciBDT01QQVJFX1BBUlRJQUxfRkxBRyA9IDEsXG4gICAgICBDT01QQVJFX1VOT1JERVJFRF9GTEFHID0gMjtcblxuICAvKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciBmdW5jdGlvbiBtZXRhZGF0YS4gKi9cbiAgdmFyIFdSQVBfQklORF9GTEFHID0gMSxcbiAgICAgIFdSQVBfQklORF9LRVlfRkxBRyA9IDIsXG4gICAgICBXUkFQX0NVUlJZX0JPVU5EX0ZMQUcgPSA0LFxuICAgICAgV1JBUF9DVVJSWV9GTEFHID0gOCxcbiAgICAgIFdSQVBfQ1VSUllfUklHSFRfRkxBRyA9IDE2LFxuICAgICAgV1JBUF9QQVJUSUFMX0ZMQUcgPSAzMixcbiAgICAgIFdSQVBfUEFSVElBTF9SSUdIVF9GTEFHID0gNjQsXG4gICAgICBXUkFQX0FSWV9GTEFHID0gMTI4LFxuICAgICAgV1JBUF9SRUFSR19GTEFHID0gMjU2LFxuICAgICAgV1JBUF9GTElQX0ZMQUcgPSA1MTI7XG5cbiAgLyoqIFVzZWQgYXMgZGVmYXVsdCBvcHRpb25zIGZvciBgXy50cnVuY2F0ZWAuICovXG4gIHZhciBERUZBVUxUX1RSVU5DX0xFTkdUSCA9IDMwLFxuICAgICAgREVGQVVMVF9UUlVOQ19PTUlTU0lPTiA9ICcuLi4nO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBob3QgZnVuY3Rpb25zIGJ5IG51bWJlciBvZiBjYWxscyB3aXRoaW4gYSBzcGFuIG9mIG1pbGxpc2Vjb25kcy4gKi9cbiAgdmFyIEhPVF9DT1VOVCA9IDgwMCxcbiAgICAgIEhPVF9TUEFOID0gMTY7XG5cbiAgLyoqIFVzZWQgdG8gaW5kaWNhdGUgdGhlIHR5cGUgb2YgbGF6eSBpdGVyYXRlZXMuICovXG4gIHZhciBMQVpZX0ZJTFRFUl9GTEFHID0gMSxcbiAgICAgIExBWllfTUFQX0ZMQUcgPSAyLFxuICAgICAgTEFaWV9XSElMRV9GTEFHID0gMztcblxuICAvKiogVXNlZCBhcyByZWZlcmVuY2VzIGZvciB2YXJpb3VzIGBOdW1iZXJgIGNvbnN0YW50cy4gKi9cbiAgdmFyIElORklOSVRZID0gMSAvIDAsXG4gICAgICBNQVhfU0FGRV9JTlRFR0VSID0gOTAwNzE5OTI1NDc0MDk5MSxcbiAgICAgIE1BWF9JTlRFR0VSID0gMS43OTc2OTMxMzQ4NjIzMTU3ZSszMDgsXG4gICAgICBOQU4gPSAwIC8gMDtcblxuICAvKiogVXNlZCBhcyByZWZlcmVuY2VzIGZvciB0aGUgbWF4aW11bSBsZW5ndGggYW5kIGluZGV4IG9mIGFuIGFycmF5LiAqL1xuICB2YXIgTUFYX0FSUkFZX0xFTkdUSCA9IDQyOTQ5NjcyOTUsXG4gICAgICBNQVhfQVJSQVlfSU5ERVggPSBNQVhfQVJSQVlfTEVOR1RIIC0gMSxcbiAgICAgIEhBTEZfTUFYX0FSUkFZX0xFTkdUSCA9IE1BWF9BUlJBWV9MRU5HVEggPj4+IDE7XG5cbiAgLyoqIFVzZWQgdG8gYXNzb2NpYXRlIHdyYXAgbWV0aG9kcyB3aXRoIHRoZWlyIGJpdCBmbGFncy4gKi9cbiAgdmFyIHdyYXBGbGFncyA9IFtcbiAgICBbJ2FyeScsIFdSQVBfQVJZX0ZMQUddLFxuICAgIFsnYmluZCcsIFdSQVBfQklORF9GTEFHXSxcbiAgICBbJ2JpbmRLZXknLCBXUkFQX0JJTkRfS0VZX0ZMQUddLFxuICAgIFsnY3VycnknLCBXUkFQX0NVUlJZX0ZMQUddLFxuICAgIFsnY3VycnlSaWdodCcsIFdSQVBfQ1VSUllfUklHSFRfRkxBR10sXG4gICAgWydmbGlwJywgV1JBUF9GTElQX0ZMQUddLFxuICAgIFsncGFydGlhbCcsIFdSQVBfUEFSVElBTF9GTEFHXSxcbiAgICBbJ3BhcnRpYWxSaWdodCcsIFdSQVBfUEFSVElBTF9SSUdIVF9GTEFHXSxcbiAgICBbJ3JlYXJnJywgV1JBUF9SRUFSR19GTEFHXVxuICBdO1xuXG4gIC8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIGFyZ3NUYWcgPSAnW29iamVjdCBBcmd1bWVudHNdJyxcbiAgICAgIGFycmF5VGFnID0gJ1tvYmplY3QgQXJyYXldJyxcbiAgICAgIGFzeW5jVGFnID0gJ1tvYmplY3QgQXN5bmNGdW5jdGlvbl0nLFxuICAgICAgYm9vbFRhZyA9ICdbb2JqZWN0IEJvb2xlYW5dJyxcbiAgICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgICBkb21FeGNUYWcgPSAnW29iamVjdCBET01FeGNlcHRpb25dJyxcbiAgICAgIGVycm9yVGFnID0gJ1tvYmplY3QgRXJyb3JdJyxcbiAgICAgIGZ1bmNUYWcgPSAnW29iamVjdCBGdW5jdGlvbl0nLFxuICAgICAgZ2VuVGFnID0gJ1tvYmplY3QgR2VuZXJhdG9yRnVuY3Rpb25dJyxcbiAgICAgIG1hcFRhZyA9ICdbb2JqZWN0IE1hcF0nLFxuICAgICAgbnVtYmVyVGFnID0gJ1tvYmplY3QgTnVtYmVyXScsXG4gICAgICBudWxsVGFnID0gJ1tvYmplY3QgTnVsbF0nLFxuICAgICAgb2JqZWN0VGFnID0gJ1tvYmplY3QgT2JqZWN0XScsXG4gICAgICBwcm9taXNlVGFnID0gJ1tvYmplY3QgUHJvbWlzZV0nLFxuICAgICAgcHJveHlUYWcgPSAnW29iamVjdCBQcm94eV0nLFxuICAgICAgcmVnZXhwVGFnID0gJ1tvYmplY3QgUmVnRXhwXScsXG4gICAgICBzZXRUYWcgPSAnW29iamVjdCBTZXRdJyxcbiAgICAgIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nLFxuICAgICAgc3ltYm9sVGFnID0gJ1tvYmplY3QgU3ltYm9sXScsXG4gICAgICB1bmRlZmluZWRUYWcgPSAnW29iamVjdCBVbmRlZmluZWRdJyxcbiAgICAgIHdlYWtNYXBUYWcgPSAnW29iamVjdCBXZWFrTWFwXScsXG4gICAgICB3ZWFrU2V0VGFnID0gJ1tvYmplY3QgV2Vha1NldF0nO1xuXG4gIHZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgICBkYXRhVmlld1RhZyA9ICdbb2JqZWN0IERhdGFWaWV3XScsXG4gICAgICBmbG9hdDMyVGFnID0gJ1tvYmplY3QgRmxvYXQzMkFycmF5XScsXG4gICAgICBmbG9hdDY0VGFnID0gJ1tvYmplY3QgRmxvYXQ2NEFycmF5XScsXG4gICAgICBpbnQ4VGFnID0gJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgICBpbnQxNlRhZyA9ICdbb2JqZWN0IEludDE2QXJyYXldJyxcbiAgICAgIGludDMyVGFnID0gJ1tvYmplY3QgSW50MzJBcnJheV0nLFxuICAgICAgdWludDhUYWcgPSAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgICB1aW50OENsYW1wZWRUYWcgPSAnW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0nLFxuICAgICAgdWludDE2VGFnID0gJ1tvYmplY3QgVWludDE2QXJyYXldJyxcbiAgICAgIHVpbnQzMlRhZyA9ICdbb2JqZWN0IFVpbnQzMkFycmF5XSc7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggZW1wdHkgc3RyaW5nIGxpdGVyYWxzIGluIGNvbXBpbGVkIHRlbXBsYXRlIHNvdXJjZS4gKi9cbiAgdmFyIHJlRW1wdHlTdHJpbmdMZWFkaW5nID0gL1xcYl9fcCBcXCs9ICcnOy9nLFxuICAgICAgcmVFbXB0eVN0cmluZ01pZGRsZSA9IC9cXGIoX19wIFxcKz0pICcnIFxcKy9nLFxuICAgICAgcmVFbXB0eVN0cmluZ1RyYWlsaW5nID0gLyhfX2VcXCguKj9cXCl8XFxiX190XFwpKSBcXCtcXG4nJzsvZztcblxuICAvKiogVXNlZCB0byBtYXRjaCBIVE1MIGVudGl0aWVzIGFuZCBIVE1MIGNoYXJhY3RlcnMuICovXG4gIHZhciByZUVzY2FwZWRIdG1sID0gLyYoPzphbXB8bHR8Z3R8cXVvdHwjMzkpOy9nLFxuICAgICAgcmVVbmVzY2FwZWRIdG1sID0gL1smPD5cIiddL2csXG4gICAgICByZUhhc0VzY2FwZWRIdG1sID0gUmVnRXhwKHJlRXNjYXBlZEh0bWwuc291cmNlKSxcbiAgICAgIHJlSGFzVW5lc2NhcGVkSHRtbCA9IFJlZ0V4cChyZVVuZXNjYXBlZEh0bWwuc291cmNlKTtcblxuICAvKiogVXNlZCB0byBtYXRjaCB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLiAqL1xuICB2YXIgcmVFc2NhcGUgPSAvPCUtKFtcXHNcXFNdKz8pJT4vZyxcbiAgICAgIHJlRXZhbHVhdGUgPSAvPCUoW1xcc1xcU10rPyklPi9nLFxuICAgICAgcmVJbnRlcnBvbGF0ZSA9IC88JT0oW1xcc1xcU10rPyklPi9nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIHByb3BlcnR5IG5hbWVzIHdpdGhpbiBwcm9wZXJ0eSBwYXRocy4gKi9cbiAgdmFyIHJlSXNEZWVwUHJvcCA9IC9cXC58XFxbKD86W15bXFxdXSp8KFtcIiddKSg/Oig/IVxcMSlbXlxcXFxdfFxcXFwuKSo/XFwxKVxcXS8sXG4gICAgICByZUlzUGxhaW5Qcm9wID0gL15cXHcqJC8sXG4gICAgICByZVByb3BOYW1lID0gL1teLltcXF1dK3xcXFsoPzooLT9cXGQrKD86XFwuXFxkKyk/KXwoW1wiJ10pKCg/Oig/IVxcMilbXlxcXFxdfFxcXFwuKSo/KVxcMilcXF18KD89KD86XFwufFxcW1xcXSkoPzpcXC58XFxbXFxdfCQpKS9nO1xuXG4gIC8qKlxuICAgKiBVc2VkIHRvIG1hdGNoIGBSZWdFeHBgXG4gICAqIFtzeW50YXggY2hhcmFjdGVyc10oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtcGF0dGVybnMpLlxuICAgKi9cbiAgdmFyIHJlUmVnRXhwQ2hhciA9IC9bXFxcXF4kLiorPygpW1xcXXt9fF0vZyxcbiAgICAgIHJlSGFzUmVnRXhwQ2hhciA9IFJlZ0V4cChyZVJlZ0V4cENoYXIuc291cmNlKTtcblxuICAvKiogVXNlZCB0byBtYXRjaCBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlLiAqL1xuICB2YXIgcmVUcmltID0gL15cXHMrfFxccyskL2csXG4gICAgICByZVRyaW1TdGFydCA9IC9eXFxzKy8sXG4gICAgICByZVRyaW1FbmQgPSAvXFxzKyQvO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIHdyYXAgZGV0YWlsIGNvbW1lbnRzLiAqL1xuICB2YXIgcmVXcmFwQ29tbWVudCA9IC9cXHsoPzpcXG5cXC9cXCogXFxbd3JhcHBlZCB3aXRoIC4rXFxdIFxcKlxcLyk/XFxuPy8sXG4gICAgICByZVdyYXBEZXRhaWxzID0gL1xce1xcblxcL1xcKiBcXFt3cmFwcGVkIHdpdGggKC4rKVxcXSBcXCovLFxuICAgICAgcmVTcGxpdERldGFpbHMgPSAvLD8gJiAvO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIHdvcmRzIGNvbXBvc2VkIG9mIGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzLiAqL1xuICB2YXIgcmVBc2NpaVdvcmQgPSAvW15cXHgwMC1cXHgyZlxceDNhLVxceDQwXFx4NWItXFx4NjBcXHg3Yi1cXHg3Zl0rL2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggYmFja3NsYXNoZXMgaW4gcHJvcGVydHkgcGF0aHMuICovXG4gIHZhciByZUVzY2FwZUNoYXIgPSAvXFxcXChcXFxcKT8vZztcblxuICAvKipcbiAgICogVXNlZCB0byBtYXRjaFxuICAgKiBbRVMgdGVtcGxhdGUgZGVsaW1pdGVyc10oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtdGVtcGxhdGUtbGl0ZXJhbC1sZXhpY2FsLWNvbXBvbmVudHMpLlxuICAgKi9cbiAgdmFyIHJlRXNUZW1wbGF0ZSA9IC9cXCRcXHsoW15cXFxcfV0qKD86XFxcXC5bXlxcXFx9XSopKilcXH0vZztcblxuICAvKiogVXNlZCB0byBtYXRjaCBgUmVnRXhwYCBmbGFncyBmcm9tIHRoZWlyIGNvZXJjZWQgc3RyaW5nIHZhbHVlcy4gKi9cbiAgdmFyIHJlRmxhZ3MgPSAvXFx3KiQvO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBiYWQgc2lnbmVkIGhleGFkZWNpbWFsIHN0cmluZyB2YWx1ZXMuICovXG4gIHZhciByZUlzQmFkSGV4ID0gL15bLStdMHhbMC05YS1mXSskL2k7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IGJpbmFyeSBzdHJpbmcgdmFsdWVzLiAqL1xuICB2YXIgcmVJc0JpbmFyeSA9IC9eMGJbMDFdKyQvaTtcblxuICAvKiogVXNlZCB0byBkZXRlY3QgaG9zdCBjb25zdHJ1Y3RvcnMgKFNhZmFyaSkuICovXG4gIHZhciByZUlzSG9zdEN0b3IgPSAvXlxcW29iamVjdCAuKz9Db25zdHJ1Y3RvclxcXSQvO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBvY3RhbCBzdHJpbmcgdmFsdWVzLiAqL1xuICB2YXIgcmVJc09jdGFsID0gL14wb1swLTddKyQvaTtcblxuICAvKiogVXNlZCB0byBkZXRlY3QgdW5zaWduZWQgaW50ZWdlciB2YWx1ZXMuICovXG4gIHZhciByZUlzVWludCA9IC9eKD86MHxbMS05XVxcZCopJC87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggTGF0aW4gVW5pY29kZSBsZXR0ZXJzIChleGNsdWRpbmcgbWF0aGVtYXRpY2FsIG9wZXJhdG9ycykuICovXG4gIHZhciByZUxhdGluID0gL1tcXHhjMC1cXHhkNlxceGQ4LVxceGY2XFx4ZjgtXFx4ZmZcXHUwMTAwLVxcdTAxN2ZdL2c7XG5cbiAgLyoqIFVzZWQgdG8gZW5zdXJlIGNhcHR1cmluZyBvcmRlciBvZiB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLiAqL1xuICB2YXIgcmVOb01hdGNoID0gLygkXikvO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIHVuZXNjYXBlZCBjaGFyYWN0ZXJzIGluIGNvbXBpbGVkIHN0cmluZyBsaXRlcmFscy4gKi9cbiAgdmFyIHJlVW5lc2NhcGVkU3RyaW5nID0gL1snXFxuXFxyXFx1MjAyOFxcdTIwMjlcXFxcXS9nO1xuXG4gIC8qKiBVc2VkIHRvIGNvbXBvc2UgdW5pY29kZSBjaGFyYWN0ZXIgY2xhc3Nlcy4gKi9cbiAgdmFyIHJzQXN0cmFsUmFuZ2UgPSAnXFxcXHVkODAwLVxcXFx1ZGZmZicsXG4gICAgICByc0NvbWJvTWFya3NSYW5nZSA9ICdcXFxcdTAzMDAtXFxcXHUwMzZmJyxcbiAgICAgIHJlQ29tYm9IYWxmTWFya3NSYW5nZSA9ICdcXFxcdWZlMjAtXFxcXHVmZTJmJyxcbiAgICAgIHJzQ29tYm9TeW1ib2xzUmFuZ2UgPSAnXFxcXHUyMGQwLVxcXFx1MjBmZicsXG4gICAgICByc0NvbWJvUmFuZ2UgPSByc0NvbWJvTWFya3NSYW5nZSArIHJlQ29tYm9IYWxmTWFya3NSYW5nZSArIHJzQ29tYm9TeW1ib2xzUmFuZ2UsXG4gICAgICByc0RpbmdiYXRSYW5nZSA9ICdcXFxcdTI3MDAtXFxcXHUyN2JmJyxcbiAgICAgIHJzTG93ZXJSYW5nZSA9ICdhLXpcXFxceGRmLVxcXFx4ZjZcXFxceGY4LVxcXFx4ZmYnLFxuICAgICAgcnNNYXRoT3BSYW5nZSA9ICdcXFxceGFjXFxcXHhiMVxcXFx4ZDdcXFxceGY3JyxcbiAgICAgIHJzTm9uQ2hhclJhbmdlID0gJ1xcXFx4MDAtXFxcXHgyZlxcXFx4M2EtXFxcXHg0MFxcXFx4NWItXFxcXHg2MFxcXFx4N2ItXFxcXHhiZicsXG4gICAgICByc1B1bmN0dWF0aW9uUmFuZ2UgPSAnXFxcXHUyMDAwLVxcXFx1MjA2ZicsXG4gICAgICByc1NwYWNlUmFuZ2UgPSAnIFxcXFx0XFxcXHgwYlxcXFxmXFxcXHhhMFxcXFx1ZmVmZlxcXFxuXFxcXHJcXFxcdTIwMjhcXFxcdTIwMjlcXFxcdTE2ODBcXFxcdTE4MGVcXFxcdTIwMDBcXFxcdTIwMDFcXFxcdTIwMDJcXFxcdTIwMDNcXFxcdTIwMDRcXFxcdTIwMDVcXFxcdTIwMDZcXFxcdTIwMDdcXFxcdTIwMDhcXFxcdTIwMDlcXFxcdTIwMGFcXFxcdTIwMmZcXFxcdTIwNWZcXFxcdTMwMDAnLFxuICAgICAgcnNVcHBlclJhbmdlID0gJ0EtWlxcXFx4YzAtXFxcXHhkNlxcXFx4ZDgtXFxcXHhkZScsXG4gICAgICByc1ZhclJhbmdlID0gJ1xcXFx1ZmUwZVxcXFx1ZmUwZicsXG4gICAgICByc0JyZWFrUmFuZ2UgPSByc01hdGhPcFJhbmdlICsgcnNOb25DaGFyUmFuZ2UgKyByc1B1bmN0dWF0aW9uUmFuZ2UgKyByc1NwYWNlUmFuZ2U7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSB1bmljb2RlIGNhcHR1cmUgZ3JvdXBzLiAqL1xuICB2YXIgcnNBcG9zID0gXCJbJ1xcdTIwMTldXCIsXG4gICAgICByc0FzdHJhbCA9ICdbJyArIHJzQXN0cmFsUmFuZ2UgKyAnXScsXG4gICAgICByc0JyZWFrID0gJ1snICsgcnNCcmVha1JhbmdlICsgJ10nLFxuICAgICAgcnNDb21ibyA9ICdbJyArIHJzQ29tYm9SYW5nZSArICddJyxcbiAgICAgIHJzRGlnaXRzID0gJ1xcXFxkKycsXG4gICAgICByc0RpbmdiYXQgPSAnWycgKyByc0RpbmdiYXRSYW5nZSArICddJyxcbiAgICAgIHJzTG93ZXIgPSAnWycgKyByc0xvd2VyUmFuZ2UgKyAnXScsXG4gICAgICByc01pc2MgPSAnW14nICsgcnNBc3RyYWxSYW5nZSArIHJzQnJlYWtSYW5nZSArIHJzRGlnaXRzICsgcnNEaW5nYmF0UmFuZ2UgKyByc0xvd2VyUmFuZ2UgKyByc1VwcGVyUmFuZ2UgKyAnXScsXG4gICAgICByc0ZpdHogPSAnXFxcXHVkODNjW1xcXFx1ZGZmYi1cXFxcdWRmZmZdJyxcbiAgICAgIHJzTW9kaWZpZXIgPSAnKD86JyArIHJzQ29tYm8gKyAnfCcgKyByc0ZpdHogKyAnKScsXG4gICAgICByc05vbkFzdHJhbCA9ICdbXicgKyByc0FzdHJhbFJhbmdlICsgJ10nLFxuICAgICAgcnNSZWdpb25hbCA9ICcoPzpcXFxcdWQ4M2NbXFxcXHVkZGU2LVxcXFx1ZGRmZl0pezJ9JyxcbiAgICAgIHJzU3VyclBhaXIgPSAnW1xcXFx1ZDgwMC1cXFxcdWRiZmZdW1xcXFx1ZGMwMC1cXFxcdWRmZmZdJyxcbiAgICAgIHJzVXBwZXIgPSAnWycgKyByc1VwcGVyUmFuZ2UgKyAnXScsXG4gICAgICByc1pXSiA9ICdcXFxcdTIwMGQnO1xuXG4gIC8qKiBVc2VkIHRvIGNvbXBvc2UgdW5pY29kZSByZWdleGVzLiAqL1xuICB2YXIgcnNNaXNjTG93ZXIgPSAnKD86JyArIHJzTG93ZXIgKyAnfCcgKyByc01pc2MgKyAnKScsXG4gICAgICByc01pc2NVcHBlciA9ICcoPzonICsgcnNVcHBlciArICd8JyArIHJzTWlzYyArICcpJyxcbiAgICAgIHJzT3B0Q29udHJMb3dlciA9ICcoPzonICsgcnNBcG9zICsgJyg/OmR8bGx8bXxyZXxzfHR8dmUpKT8nLFxuICAgICAgcnNPcHRDb250clVwcGVyID0gJyg/OicgKyByc0Fwb3MgKyAnKD86RHxMTHxNfFJFfFN8VHxWRSkpPycsXG4gICAgICByZU9wdE1vZCA9IHJzTW9kaWZpZXIgKyAnPycsXG4gICAgICByc09wdFZhciA9ICdbJyArIHJzVmFyUmFuZ2UgKyAnXT8nLFxuICAgICAgcnNPcHRKb2luID0gJyg/OicgKyByc1pXSiArICcoPzonICsgW3JzTm9uQXN0cmFsLCByc1JlZ2lvbmFsLCByc1N1cnJQYWlyXS5qb2luKCd8JykgKyAnKScgKyByc09wdFZhciArIHJlT3B0TW9kICsgJykqJyxcbiAgICAgIHJzT3JkTG93ZXIgPSAnXFxcXGQqKD86MXN0fDJuZHwzcmR8KD8hWzEyM10pXFxcXGR0aCkoPz1cXFxcYnxbQS1aX10pJyxcbiAgICAgIHJzT3JkVXBwZXIgPSAnXFxcXGQqKD86MVNUfDJORHwzUkR8KD8hWzEyM10pXFxcXGRUSCkoPz1cXFxcYnxbYS16X10pJyxcbiAgICAgIHJzU2VxID0gcnNPcHRWYXIgKyByZU9wdE1vZCArIHJzT3B0Sm9pbixcbiAgICAgIHJzRW1vamkgPSAnKD86JyArIFtyc0RpbmdiYXQsIHJzUmVnaW9uYWwsIHJzU3VyclBhaXJdLmpvaW4oJ3wnKSArICcpJyArIHJzU2VxLFxuICAgICAgcnNTeW1ib2wgPSAnKD86JyArIFtyc05vbkFzdHJhbCArIHJzQ29tYm8gKyAnPycsIHJzQ29tYm8sIHJzUmVnaW9uYWwsIHJzU3VyclBhaXIsIHJzQXN0cmFsXS5qb2luKCd8JykgKyAnKSc7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggYXBvc3Ryb3BoZXMuICovXG4gIHZhciByZUFwb3MgPSBSZWdFeHAocnNBcG9zLCAnZycpO1xuXG4gIC8qKlxuICAgKiBVc2VkIHRvIG1hdGNoIFtjb21iaW5pbmcgZGlhY3JpdGljYWwgbWFya3NdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbWJpbmluZ19EaWFjcml0aWNhbF9NYXJrcykgYW5kXG4gICAqIFtjb21iaW5pbmcgZGlhY3JpdGljYWwgbWFya3MgZm9yIHN5bWJvbHNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbWJpbmluZ19EaWFjcml0aWNhbF9NYXJrc19mb3JfU3ltYm9scykuXG4gICAqL1xuICB2YXIgcmVDb21ib01hcmsgPSBSZWdFeHAocnNDb21ibywgJ2cnKTtcblxuICAvKiogVXNlZCB0byBtYXRjaCBbc3RyaW5nIHN5bWJvbHNdKGh0dHBzOi8vbWF0aGlhc2J5bmVucy5iZS9ub3Rlcy9qYXZhc2NyaXB0LXVuaWNvZGUpLiAqL1xuICB2YXIgcmVVbmljb2RlID0gUmVnRXhwKHJzRml0eiArICcoPz0nICsgcnNGaXR6ICsgJyl8JyArIHJzU3ltYm9sICsgcnNTZXEsICdnJyk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggY29tcGxleCBvciBjb21wb3VuZCB3b3Jkcy4gKi9cbiAgdmFyIHJlVW5pY29kZVdvcmQgPSBSZWdFeHAoW1xuICAgIHJzVXBwZXIgKyAnPycgKyByc0xvd2VyICsgJysnICsgcnNPcHRDb250ckxvd2VyICsgJyg/PScgKyBbcnNCcmVhaywgcnNVcHBlciwgJyQnXS5qb2luKCd8JykgKyAnKScsXG4gICAgcnNNaXNjVXBwZXIgKyAnKycgKyByc09wdENvbnRyVXBwZXIgKyAnKD89JyArIFtyc0JyZWFrLCByc1VwcGVyICsgcnNNaXNjTG93ZXIsICckJ10uam9pbignfCcpICsgJyknLFxuICAgIHJzVXBwZXIgKyAnPycgKyByc01pc2NMb3dlciArICcrJyArIHJzT3B0Q29udHJMb3dlcixcbiAgICByc1VwcGVyICsgJysnICsgcnNPcHRDb250clVwcGVyLFxuICAgIHJzT3JkVXBwZXIsXG4gICAgcnNPcmRMb3dlcixcbiAgICByc0RpZ2l0cyxcbiAgICByc0Vtb2ppXG4gIF0uam9pbignfCcpLCAnZycpO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBzdHJpbmdzIHdpdGggW3plcm8td2lkdGggam9pbmVycyBvciBjb2RlIHBvaW50cyBmcm9tIHRoZSBhc3RyYWwgcGxhbmVzXShodHRwOi8vZWV2LmVlL2Jsb2cvMjAxNS8wOS8xMi9kYXJrLWNvcm5lcnMtb2YtdW5pY29kZS8pLiAqL1xuICB2YXIgcmVIYXNVbmljb2RlID0gUmVnRXhwKCdbJyArIHJzWldKICsgcnNBc3RyYWxSYW5nZSAgKyByc0NvbWJvUmFuZ2UgKyByc1ZhclJhbmdlICsgJ10nKTtcblxuICAvKiogVXNlZCB0byBkZXRlY3Qgc3RyaW5ncyB0aGF0IG5lZWQgYSBtb3JlIHJvYnVzdCByZWdleHAgdG8gbWF0Y2ggd29yZHMuICovXG4gIHZhciByZUhhc1VuaWNvZGVXb3JkID0gL1thLXpdW0EtWl18W0EtWl17Mn1bYS16XXxbMC05XVthLXpBLVpdfFthLXpBLVpdWzAtOV18W15hLXpBLVowLTkgXS87XG5cbiAgLyoqIFVzZWQgdG8gYXNzaWduIGRlZmF1bHQgYGNvbnRleHRgIG9iamVjdCBwcm9wZXJ0aWVzLiAqL1xuICB2YXIgY29udGV4dFByb3BzID0gW1xuICAgICdBcnJheScsICdCdWZmZXInLCAnRGF0YVZpZXcnLCAnRGF0ZScsICdFcnJvcicsICdGbG9hdDMyQXJyYXknLCAnRmxvYXQ2NEFycmF5JyxcbiAgICAnRnVuY3Rpb24nLCAnSW50OEFycmF5JywgJ0ludDE2QXJyYXknLCAnSW50MzJBcnJheScsICdNYXAnLCAnTWF0aCcsICdPYmplY3QnLFxuICAgICdQcm9taXNlJywgJ1JlZ0V4cCcsICdTZXQnLCAnU3RyaW5nJywgJ1N5bWJvbCcsICdUeXBlRXJyb3InLCAnVWludDhBcnJheScsXG4gICAgJ1VpbnQ4Q2xhbXBlZEFycmF5JywgJ1VpbnQxNkFycmF5JywgJ1VpbnQzMkFycmF5JywgJ1dlYWtNYXAnLFxuICAgICdfJywgJ2NsZWFyVGltZW91dCcsICdpc0Zpbml0ZScsICdwYXJzZUludCcsICdzZXRUaW1lb3V0J1xuICBdO1xuXG4gIC8qKiBVc2VkIHRvIG1ha2UgdGVtcGxhdGUgc291cmNlVVJMcyBlYXNpZXIgdG8gaWRlbnRpZnkuICovXG4gIHZhciB0ZW1wbGF0ZUNvdW50ZXIgPSAtMTtcblxuICAvKiogVXNlZCB0byBpZGVudGlmeSBgdG9TdHJpbmdUYWdgIHZhbHVlcyBvZiB0eXBlZCBhcnJheXMuICovXG4gIHZhciB0eXBlZEFycmF5VGFncyA9IHt9O1xuICB0eXBlZEFycmF5VGFnc1tmbG9hdDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Zsb2F0NjRUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbaW50OFRhZ10gPSB0eXBlZEFycmF5VGFnc1tpbnQxNlRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tpbnQzMlRhZ10gPSB0eXBlZEFycmF5VGFnc1t1aW50OFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1t1aW50OENsYW1wZWRUYWddID0gdHlwZWRBcnJheVRhZ3NbdWludDE2VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3VpbnQzMlRhZ10gPSB0cnVlO1xuICB0eXBlZEFycmF5VGFnc1thcmdzVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2FycmF5VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW2FycmF5QnVmZmVyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Jvb2xUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbZGF0YVZpZXdUYWddID0gdHlwZWRBcnJheVRhZ3NbZGF0ZVRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tlcnJvclRhZ10gPSB0eXBlZEFycmF5VGFnc1tmdW5jVGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW21hcFRhZ10gPSB0eXBlZEFycmF5VGFnc1tudW1iZXJUYWddID1cbiAgdHlwZWRBcnJheVRhZ3Nbb2JqZWN0VGFnXSA9IHR5cGVkQXJyYXlUYWdzW3JlZ2V4cFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tzZXRUYWddID0gdHlwZWRBcnJheVRhZ3Nbc3RyaW5nVGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3dlYWtNYXBUYWddID0gZmFsc2U7XG5cbiAgLyoqIFVzZWQgdG8gaWRlbnRpZnkgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgc3VwcG9ydGVkIGJ5IGBfLmNsb25lYC4gKi9cbiAgdmFyIGNsb25lYWJsZVRhZ3MgPSB7fTtcbiAgY2xvbmVhYmxlVGFnc1thcmdzVGFnXSA9IGNsb25lYWJsZVRhZ3NbYXJyYXlUYWddID1cbiAgY2xvbmVhYmxlVGFnc1thcnJheUJ1ZmZlclRhZ10gPSBjbG9uZWFibGVUYWdzW2RhdGFWaWV3VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbYm9vbFRhZ10gPSBjbG9uZWFibGVUYWdzW2RhdGVUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tmbG9hdDMyVGFnXSA9IGNsb25lYWJsZVRhZ3NbZmxvYXQ2NFRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2ludDhUYWddID0gY2xvbmVhYmxlVGFnc1tpbnQxNlRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2ludDMyVGFnXSA9IGNsb25lYWJsZVRhZ3NbbWFwVGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbbnVtYmVyVGFnXSA9IGNsb25lYWJsZVRhZ3Nbb2JqZWN0VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbcmVnZXhwVGFnXSA9IGNsb25lYWJsZVRhZ3Nbc2V0VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3Nbc3RyaW5nVGFnXSA9IGNsb25lYWJsZVRhZ3Nbc3ltYm9sVGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbdWludDhUYWddID0gY2xvbmVhYmxlVGFnc1t1aW50OENsYW1wZWRUYWddID1cbiAgY2xvbmVhYmxlVGFnc1t1aW50MTZUYWddID0gY2xvbmVhYmxlVGFnc1t1aW50MzJUYWddID0gdHJ1ZTtcbiAgY2xvbmVhYmxlVGFnc1tlcnJvclRhZ10gPSBjbG9uZWFibGVUYWdzW2Z1bmNUYWddID1cbiAgY2xvbmVhYmxlVGFnc1t3ZWFrTWFwVGFnXSA9IGZhbHNlO1xuXG4gIC8qKiBVc2VkIHRvIG1hcCBMYXRpbiBVbmljb2RlIGxldHRlcnMgdG8gYmFzaWMgTGF0aW4gbGV0dGVycy4gKi9cbiAgdmFyIGRlYnVycmVkTGV0dGVycyA9IHtcbiAgICAvLyBMYXRpbi0xIFN1cHBsZW1lbnQgYmxvY2suXG4gICAgJ1xceGMwJzogJ0EnLCAgJ1xceGMxJzogJ0EnLCAnXFx4YzInOiAnQScsICdcXHhjMyc6ICdBJywgJ1xceGM0JzogJ0EnLCAnXFx4YzUnOiAnQScsXG4gICAgJ1xceGUwJzogJ2EnLCAgJ1xceGUxJzogJ2EnLCAnXFx4ZTInOiAnYScsICdcXHhlMyc6ICdhJywgJ1xceGU0JzogJ2EnLCAnXFx4ZTUnOiAnYScsXG4gICAgJ1xceGM3JzogJ0MnLCAgJ1xceGU3JzogJ2MnLFxuICAgICdcXHhkMCc6ICdEJywgICdcXHhmMCc6ICdkJyxcbiAgICAnXFx4YzgnOiAnRScsICAnXFx4YzknOiAnRScsICdcXHhjYSc6ICdFJywgJ1xceGNiJzogJ0UnLFxuICAgICdcXHhlOCc6ICdlJywgICdcXHhlOSc6ICdlJywgJ1xceGVhJzogJ2UnLCAnXFx4ZWInOiAnZScsXG4gICAgJ1xceGNjJzogJ0knLCAgJ1xceGNkJzogJ0knLCAnXFx4Y2UnOiAnSScsICdcXHhjZic6ICdJJyxcbiAgICAnXFx4ZWMnOiAnaScsICAnXFx4ZWQnOiAnaScsICdcXHhlZSc6ICdpJywgJ1xceGVmJzogJ2knLFxuICAgICdcXHhkMSc6ICdOJywgICdcXHhmMSc6ICduJyxcbiAgICAnXFx4ZDInOiAnTycsICAnXFx4ZDMnOiAnTycsICdcXHhkNCc6ICdPJywgJ1xceGQ1JzogJ08nLCAnXFx4ZDYnOiAnTycsICdcXHhkOCc6ICdPJyxcbiAgICAnXFx4ZjInOiAnbycsICAnXFx4ZjMnOiAnbycsICdcXHhmNCc6ICdvJywgJ1xceGY1JzogJ28nLCAnXFx4ZjYnOiAnbycsICdcXHhmOCc6ICdvJyxcbiAgICAnXFx4ZDknOiAnVScsICAnXFx4ZGEnOiAnVScsICdcXHhkYic6ICdVJywgJ1xceGRjJzogJ1UnLFxuICAgICdcXHhmOSc6ICd1JywgICdcXHhmYSc6ICd1JywgJ1xceGZiJzogJ3UnLCAnXFx4ZmMnOiAndScsXG4gICAgJ1xceGRkJzogJ1knLCAgJ1xceGZkJzogJ3knLCAnXFx4ZmYnOiAneScsXG4gICAgJ1xceGM2JzogJ0FlJywgJ1xceGU2JzogJ2FlJyxcbiAgICAnXFx4ZGUnOiAnVGgnLCAnXFx4ZmUnOiAndGgnLFxuICAgICdcXHhkZic6ICdzcycsXG4gICAgLy8gTGF0aW4gRXh0ZW5kZWQtQSBibG9jay5cbiAgICAnXFx1MDEwMCc6ICdBJywgICdcXHUwMTAyJzogJ0EnLCAnXFx1MDEwNCc6ICdBJyxcbiAgICAnXFx1MDEwMSc6ICdhJywgICdcXHUwMTAzJzogJ2EnLCAnXFx1MDEwNSc6ICdhJyxcbiAgICAnXFx1MDEwNic6ICdDJywgICdcXHUwMTA4JzogJ0MnLCAnXFx1MDEwYSc6ICdDJywgJ1xcdTAxMGMnOiAnQycsXG4gICAgJ1xcdTAxMDcnOiAnYycsICAnXFx1MDEwOSc6ICdjJywgJ1xcdTAxMGInOiAnYycsICdcXHUwMTBkJzogJ2MnLFxuICAgICdcXHUwMTBlJzogJ0QnLCAgJ1xcdTAxMTAnOiAnRCcsICdcXHUwMTBmJzogJ2QnLCAnXFx1MDExMSc6ICdkJyxcbiAgICAnXFx1MDExMic6ICdFJywgICdcXHUwMTE0JzogJ0UnLCAnXFx1MDExNic6ICdFJywgJ1xcdTAxMTgnOiAnRScsICdcXHUwMTFhJzogJ0UnLFxuICAgICdcXHUwMTEzJzogJ2UnLCAgJ1xcdTAxMTUnOiAnZScsICdcXHUwMTE3JzogJ2UnLCAnXFx1MDExOSc6ICdlJywgJ1xcdTAxMWInOiAnZScsXG4gICAgJ1xcdTAxMWMnOiAnRycsICAnXFx1MDExZSc6ICdHJywgJ1xcdTAxMjAnOiAnRycsICdcXHUwMTIyJzogJ0cnLFxuICAgICdcXHUwMTFkJzogJ2cnLCAgJ1xcdTAxMWYnOiAnZycsICdcXHUwMTIxJzogJ2cnLCAnXFx1MDEyMyc6ICdnJyxcbiAgICAnXFx1MDEyNCc6ICdIJywgICdcXHUwMTI2JzogJ0gnLCAnXFx1MDEyNSc6ICdoJywgJ1xcdTAxMjcnOiAnaCcsXG4gICAgJ1xcdTAxMjgnOiAnSScsICAnXFx1MDEyYSc6ICdJJywgJ1xcdTAxMmMnOiAnSScsICdcXHUwMTJlJzogJ0knLCAnXFx1MDEzMCc6ICdJJyxcbiAgICAnXFx1MDEyOSc6ICdpJywgICdcXHUwMTJiJzogJ2knLCAnXFx1MDEyZCc6ICdpJywgJ1xcdTAxMmYnOiAnaScsICdcXHUwMTMxJzogJ2knLFxuICAgICdcXHUwMTM0JzogJ0onLCAgJ1xcdTAxMzUnOiAnaicsXG4gICAgJ1xcdTAxMzYnOiAnSycsICAnXFx1MDEzNyc6ICdrJywgJ1xcdTAxMzgnOiAnaycsXG4gICAgJ1xcdTAxMzknOiAnTCcsICAnXFx1MDEzYic6ICdMJywgJ1xcdTAxM2QnOiAnTCcsICdcXHUwMTNmJzogJ0wnLCAnXFx1MDE0MSc6ICdMJyxcbiAgICAnXFx1MDEzYSc6ICdsJywgICdcXHUwMTNjJzogJ2wnLCAnXFx1MDEzZSc6ICdsJywgJ1xcdTAxNDAnOiAnbCcsICdcXHUwMTQyJzogJ2wnLFxuICAgICdcXHUwMTQzJzogJ04nLCAgJ1xcdTAxNDUnOiAnTicsICdcXHUwMTQ3JzogJ04nLCAnXFx1MDE0YSc6ICdOJyxcbiAgICAnXFx1MDE0NCc6ICduJywgICdcXHUwMTQ2JzogJ24nLCAnXFx1MDE0OCc6ICduJywgJ1xcdTAxNGInOiAnbicsXG4gICAgJ1xcdTAxNGMnOiAnTycsICAnXFx1MDE0ZSc6ICdPJywgJ1xcdTAxNTAnOiAnTycsXG4gICAgJ1xcdTAxNGQnOiAnbycsICAnXFx1MDE0Zic6ICdvJywgJ1xcdTAxNTEnOiAnbycsXG4gICAgJ1xcdTAxNTQnOiAnUicsICAnXFx1MDE1Nic6ICdSJywgJ1xcdTAxNTgnOiAnUicsXG4gICAgJ1xcdTAxNTUnOiAncicsICAnXFx1MDE1Nyc6ICdyJywgJ1xcdTAxNTknOiAncicsXG4gICAgJ1xcdTAxNWEnOiAnUycsICAnXFx1MDE1Yyc6ICdTJywgJ1xcdTAxNWUnOiAnUycsICdcXHUwMTYwJzogJ1MnLFxuICAgICdcXHUwMTViJzogJ3MnLCAgJ1xcdTAxNWQnOiAncycsICdcXHUwMTVmJzogJ3MnLCAnXFx1MDE2MSc6ICdzJyxcbiAgICAnXFx1MDE2Mic6ICdUJywgICdcXHUwMTY0JzogJ1QnLCAnXFx1MDE2Nic6ICdUJyxcbiAgICAnXFx1MDE2Myc6ICd0JywgICdcXHUwMTY1JzogJ3QnLCAnXFx1MDE2Nyc6ICd0JyxcbiAgICAnXFx1MDE2OCc6ICdVJywgICdcXHUwMTZhJzogJ1UnLCAnXFx1MDE2Yyc6ICdVJywgJ1xcdTAxNmUnOiAnVScsICdcXHUwMTcwJzogJ1UnLCAnXFx1MDE3Mic6ICdVJyxcbiAgICAnXFx1MDE2OSc6ICd1JywgICdcXHUwMTZiJzogJ3UnLCAnXFx1MDE2ZCc6ICd1JywgJ1xcdTAxNmYnOiAndScsICdcXHUwMTcxJzogJ3UnLCAnXFx1MDE3Myc6ICd1JyxcbiAgICAnXFx1MDE3NCc6ICdXJywgICdcXHUwMTc1JzogJ3cnLFxuICAgICdcXHUwMTc2JzogJ1knLCAgJ1xcdTAxNzcnOiAneScsICdcXHUwMTc4JzogJ1knLFxuICAgICdcXHUwMTc5JzogJ1onLCAgJ1xcdTAxN2InOiAnWicsICdcXHUwMTdkJzogJ1onLFxuICAgICdcXHUwMTdhJzogJ3onLCAgJ1xcdTAxN2MnOiAneicsICdcXHUwMTdlJzogJ3onLFxuICAgICdcXHUwMTMyJzogJ0lKJywgJ1xcdTAxMzMnOiAnaWonLFxuICAgICdcXHUwMTUyJzogJ09lJywgJ1xcdTAxNTMnOiAnb2UnLFxuICAgICdcXHUwMTQ5JzogXCInblwiLCAnXFx1MDE3Zic6ICdzJ1xuICB9O1xuXG4gIC8qKiBVc2VkIHRvIG1hcCBjaGFyYWN0ZXJzIHRvIEhUTUwgZW50aXRpZXMuICovXG4gIHZhciBodG1sRXNjYXBlcyA9IHtcbiAgICAnJic6ICcmYW1wOycsXG4gICAgJzwnOiAnJmx0OycsXG4gICAgJz4nOiAnJmd0OycsXG4gICAgJ1wiJzogJyZxdW90OycsXG4gICAgXCInXCI6ICcmIzM5OydcbiAgfTtcblxuICAvKiogVXNlZCB0byBtYXAgSFRNTCBlbnRpdGllcyB0byBjaGFyYWN0ZXJzLiAqL1xuICB2YXIgaHRtbFVuZXNjYXBlcyA9IHtcbiAgICAnJmFtcDsnOiAnJicsXG4gICAgJyZsdDsnOiAnPCcsXG4gICAgJyZndDsnOiAnPicsXG4gICAgJyZxdW90Oyc6ICdcIicsXG4gICAgJyYjMzk7JzogXCInXCJcbiAgfTtcblxuICAvKiogVXNlZCB0byBlc2NhcGUgY2hhcmFjdGVycyBmb3IgaW5jbHVzaW9uIGluIGNvbXBpbGVkIHN0cmluZyBsaXRlcmFscy4gKi9cbiAgdmFyIHN0cmluZ0VzY2FwZXMgPSB7XG4gICAgJ1xcXFwnOiAnXFxcXCcsXG4gICAgXCInXCI6IFwiJ1wiLFxuICAgICdcXG4nOiAnbicsXG4gICAgJ1xccic6ICdyJyxcbiAgICAnXFx1MjAyOCc6ICd1MjAyOCcsXG4gICAgJ1xcdTIwMjknOiAndTIwMjknXG4gIH07XG5cbiAgLyoqIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHdpdGhvdXQgYSBkZXBlbmRlbmN5IG9uIGByb290YC4gKi9cbiAgdmFyIGZyZWVQYXJzZUZsb2F0ID0gcGFyc2VGbG9hdCxcbiAgICAgIGZyZWVQYXJzZUludCA9IHBhcnNlSW50O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMuICovXG4gIHZhciBmcmVlR2xvYmFsID0gdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCA9PT0gT2JqZWN0ICYmIGdsb2JhbDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHNlbGZgLiAqL1xuICB2YXIgZnJlZVNlbGYgPSB0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmICYmIHNlbGYuT2JqZWN0ID09PSBPYmplY3QgJiYgc2VsZjtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSBmcmVlR2xvYmFsIHx8IGZyZWVTZWxmIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gdHlwZW9mIGV4cG9ydHMgPT0gJ29iamVjdCcgJiYgZXhwb3J0cyAmJiAhZXhwb3J0cy5ub2RlVHlwZSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBmcmVlRXhwb3J0cyAmJiB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IHRoZSBwb3B1bGFyIENvbW1vbkpTIGV4dGVuc2lvbiBgbW9kdWxlLmV4cG9ydHNgLiAqL1xuICB2YXIgbW9kdWxlRXhwb3J0cyA9IGZyZWVNb2R1bGUgJiYgZnJlZU1vZHVsZS5leHBvcnRzID09PSBmcmVlRXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHByb2Nlc3NgIGZyb20gTm9kZS5qcy4gKi9cbiAgdmFyIGZyZWVQcm9jZXNzID0gbW9kdWxlRXhwb3J0cyAmJiBmcmVlR2xvYmFsLnByb2Nlc3M7XG5cbiAgLyoqIFVzZWQgdG8gYWNjZXNzIGZhc3RlciBOb2RlLmpzIGhlbHBlcnMuICovXG4gIHZhciBub2RlVXRpbCA9IChmdW5jdGlvbigpIHtcbiAgICB0cnkge1xuICAgICAgLy8gVXNlIGB1dGlsLnR5cGVzYCBmb3IgTm9kZS5qcyAxMCsuXG4gICAgICB2YXIgdHlwZXMgPSBmcmVlTW9kdWxlICYmIGZyZWVNb2R1bGUucmVxdWlyZSAmJiBmcmVlTW9kdWxlLnJlcXVpcmUoJ3V0aWwnKS50eXBlcztcblxuICAgICAgaWYgKHR5cGVzKSB7XG4gICAgICAgIHJldHVybiB0eXBlcztcbiAgICAgIH1cblxuICAgICAgLy8gTGVnYWN5IGBwcm9jZXNzLmJpbmRpbmcoJ3V0aWwnKWAgZm9yIE5vZGUuanMgPCAxMC5cbiAgICAgIHJldHVybiBmcmVlUHJvY2VzcyAmJiBmcmVlUHJvY2Vzcy5iaW5kaW5nICYmIGZyZWVQcm9jZXNzLmJpbmRpbmcoJ3V0aWwnKTtcbiAgICB9IGNhdGNoIChlKSB7fVxuICB9KCkpO1xuXG4gIC8qIE5vZGUuanMgaGVscGVyIHJlZmVyZW5jZXMuICovXG4gIHZhciBub2RlSXNBcnJheUJ1ZmZlciA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzQXJyYXlCdWZmZXIsXG4gICAgICBub2RlSXNEYXRlID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNEYXRlLFxuICAgICAgbm9kZUlzTWFwID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNNYXAsXG4gICAgICBub2RlSXNSZWdFeHAgPSBub2RlVXRpbCAmJiBub2RlVXRpbC5pc1JlZ0V4cCxcbiAgICAgIG5vZGVJc1NldCA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzU2V0LFxuICAgICAgbm9kZUlzVHlwZWRBcnJheSA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzVHlwZWRBcnJheTtcblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQSBmYXN0ZXIgYWx0ZXJuYXRpdmUgdG8gYEZ1bmN0aW9uI2FwcGx5YCwgdGhpcyBmdW5jdGlvbiBpbnZva2VzIGBmdW5jYFxuICAgKiB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiBgdGhpc0FyZ2AgYW5kIHRoZSBhcmd1bWVudHMgb2YgYGFyZ3NgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBpbnZva2UuXG4gICAqIEBwYXJhbSB7Kn0gdGhpc0FyZyBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgKiBAcGFyYW0ge0FycmF5fSBhcmdzIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIGBmdW5jYCB3aXRoLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzdWx0IG9mIGBmdW5jYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFwcGx5KGZ1bmMsIHRoaXNBcmcsIGFyZ3MpIHtcbiAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZyk7XG4gICAgICBjYXNlIDE6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZywgYXJnc1swXSk7XG4gICAgICBjYXNlIDI6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZywgYXJnc1swXSwgYXJnc1sxXSk7XG4gICAgICBjYXNlIDM6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZywgYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgfVxuICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUFnZ3JlZ2F0b3JgIGZvciBhcnJheXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gc2V0dGVyIFRoZSBmdW5jdGlvbiB0byBzZXQgYGFjY3VtdWxhdG9yYCB2YWx1ZXMuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICogQHBhcmFtIHtPYmplY3R9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIGFnZ3JlZ2F0ZWQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGFjY3VtdWxhdG9yYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5QWdncmVnYXRvcihhcnJheSwgc2V0dGVyLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgc2V0dGVyKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaXRlcmF0ZWUodmFsdWUpLCBhcnJheSk7XG4gICAgfVxuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZm9yRWFjaGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUVhY2goYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmIChpdGVyYXRlZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkgPT09IGZhbHNlKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZvckVhY2hSaWdodGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUVhY2hSaWdodChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGlmIChpdGVyYXRlZShhcnJheVtsZW5ndGhdLCBsZW5ndGgsIGFycmF5KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZXZlcnlgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYWxsIGVsZW1lbnRzIHBhc3MgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICogIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RXZlcnkoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoIXByZWRpY2F0ZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZmlsdGVyYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmlsdGVyZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUZpbHRlcihhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoLFxuICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmluY2x1ZGVzYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogc3BlY2lmeWluZyBhbiBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHsqfSB0YXJnZXQgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdGFyZ2V0YCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlJbmNsdWRlcyhhcnJheSwgdmFsdWUpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgcmV0dXJuICEhbGVuZ3RoICYmIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgMCkgPiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGFycmF5SW5jbHVkZXNgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYSBjb21wYXJhdG9yLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHRhcmdldCBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyYXRvciBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHRhcmdldGAgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5SW5jbHVkZXNXaXRoKGFycmF5LCB2YWx1ZSwgY29tcGFyYXRvcikge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoY29tcGFyYXRvcih2YWx1ZSwgYXJyYXlbaW5kZXhdKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5tYXBgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZVxuICAgKiBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5TWFwKGFycmF5LCBpdGVyYXRlZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gaXRlcmF0ZWUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZHMgdGhlIGVsZW1lbnRzIG9mIGB2YWx1ZXNgIHRvIGBhcnJheWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIGFwcGVuZC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVB1c2goYXJyYXksIHZhbHVlcykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgICBvZmZzZXQgPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgYXJyYXlbb2Zmc2V0ICsgaW5kZXhdID0gdmFsdWVzW2luZGV4XTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5yZWR1Y2VgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7Kn0gW2FjY3VtdWxhdG9yXSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHBhcmFtIHtib29sZWFufSBbaW5pdEFjY3VtXSBTcGVjaWZ5IHVzaW5nIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAgYXNcbiAgICogIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVJlZHVjZShhcnJheSwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0pIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgICBpZiAoaW5pdEFjY3VtICYmIGxlbmd0aCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBhcnJheVsrK2luZGV4XTtcbiAgICB9XG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaXRlcmF0ZWUoYWNjdW11bGF0b3IsIGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KTtcbiAgICB9XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5yZWR1Y2VSaWdodGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpbml0QWNjdW1dIFNwZWNpZnkgdXNpbmcgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgIGFzXG4gICAqICB0aGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlSZWR1Y2VSaWdodChhcnJheSwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0pIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgaWYgKGluaXRBY2N1bSAmJiBsZW5ndGgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gYXJyYXlbLS1sZW5ndGhdO1xuICAgIH1cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaXRlcmF0ZWUoYWNjdW11bGF0b3IsIGFycmF5W2xlbmd0aF0sIGxlbmd0aCwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNvbWVgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZVxuICAgKiBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW55IGVsZW1lbnQgcGFzc2VzIHRoZSBwcmVkaWNhdGUgY2hlY2ssXG4gICAqICBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVNvbWUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHNpemUgb2YgYW4gQVNDSUkgYHN0cmluZ2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgc2l6ZS5cbiAgICovXG4gIHZhciBhc2NpaVNpemUgPSBiYXNlUHJvcGVydHkoJ2xlbmd0aCcpO1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhbiBBU0NJSSBgc3RyaW5nYCB0byBhbiBhcnJheS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY29udmVydGVkIGFycmF5LlxuICAgKi9cbiAgZnVuY3Rpb24gYXNjaWlUb0FycmF5KHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcuc3BsaXQoJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0cyBhbiBBU0NJSSBgc3RyaW5nYCBpbnRvIGFuIGFycmF5IG9mIGl0cyB3b3Jkcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB3b3JkcyBvZiBgc3RyaW5nYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFzY2lpV29yZHMoc3RyaW5nKSB7XG4gICAgcmV0dXJuIHN0cmluZy5tYXRjaChyZUFzY2lpV29yZCkgfHwgW107XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLmZpbmRLZXlgIGFuZCBgXy5maW5kTGFzdEtleWAsXG4gICAqIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcywgd2hpY2ggaXRlcmF0ZXMgb3ZlciBgY29sbGVjdGlvbmBcbiAgICogdXNpbmcgYGVhY2hGdW5jYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGVhY2hGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYGNvbGxlY3Rpb25gLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZm91bmQgZWxlbWVudCBvciBpdHMga2V5LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUZpbmRLZXkoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBlYWNoRnVuYykge1xuICAgIHZhciByZXN1bHQ7XG4gICAgZWFjaEZ1bmMoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSkge1xuICAgICAgICByZXN1bHQgPSBrZXk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZpbmRJbmRleGAgYW5kIGBfLmZpbmRMYXN0SW5kZXhgIHdpdGhvdXRcbiAgICogc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlRmluZEluZGV4KGFycmF5LCBwcmVkaWNhdGUsIGZyb21JbmRleCwgZnJvbVJpZ2h0KSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgaW5kZXggPSBmcm9tSW5kZXggKyAoZnJvbVJpZ2h0ID8gMSA6IC0xKTtcblxuICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpKSB7XG4gICAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pbmRleE9mYCB3aXRob3V0IGBmcm9tSW5kZXhgIGJvdW5kcyBjaGVja3MuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZVxuICAgICAgPyBzdHJpY3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KVxuICAgICAgOiBiYXNlRmluZEluZGV4KGFycmF5LCBiYXNlSXNOYU4sIGZyb21JbmRleCk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlIGBiYXNlSW5kZXhPZmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhIGNvbXBhcmF0b3IuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyYXRvciBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUluZGV4T2ZXaXRoKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4LCBjb21wYXJhdG9yKSB7XG4gICAgdmFyIGluZGV4ID0gZnJvbUluZGV4IC0gMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmIChjb21wYXJhdG9yKGFycmF5W2luZGV4XSwgdmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTmFOYCB3aXRob3V0IHN1cHBvcnQgZm9yIG51bWJlciBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYE5hTmAsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJc05hTih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSAhPT0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWVhbmAgYW5kIGBfLm1lYW5CeWAgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBtZWFuLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZU1lYW4oYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgIHJldHVybiBsZW5ndGggPyAoYmFzZVN1bShhcnJheSwgaXRlcmF0ZWUpIC8gbGVuZ3RoKSA6IE5BTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wcm9wZXJ0eWAgd2l0aG91dCBzdXBwb3J0IGZvciBkZWVwIHBhdGhzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWNjZXNzb3IgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlUHJvcGVydHkoa2V5KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wcm9wZXJ0eU9mYCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWNjZXNzb3IgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlUHJvcGVydHlPZihvYmplY3QpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3Rba2V5XTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJlZHVjZWAgYW5kIGBfLnJlZHVjZVJpZ2h0YCwgd2l0aG91dCBzdXBwb3J0XG4gICAqIGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLCB3aGljaCBpdGVyYXRlcyBvdmVyIGBjb2xsZWN0aW9uYCB1c2luZyBgZWFjaEZ1bmNgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7Kn0gYWNjdW11bGF0b3IgVGhlIGluaXRpYWwgdmFsdWUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaW5pdEFjY3VtIFNwZWNpZnkgdXNpbmcgdGhlIGZpcnN0IG9yIGxhc3QgZWxlbWVudCBvZlxuICAgKiAgYGNvbGxlY3Rpb25gIGFzIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGBjb2xsZWN0aW9uYC5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVJlZHVjZShjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRBY2N1bSwgZWFjaEZ1bmMpIHtcbiAgICBlYWNoRnVuYyhjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaW5pdEFjY3VtXG4gICAgICAgID8gKGluaXRBY2N1bSA9IGZhbHNlLCB2YWx1ZSlcbiAgICAgICAgOiBpdGVyYXRlZShhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydEJ5YCB3aGljaCB1c2VzIGBjb21wYXJlcmAgdG8gZGVmaW5lIHRoZVxuICAgKiBzb3J0IG9yZGVyIG9mIGBhcnJheWAgYW5kIHJlcGxhY2VzIGNyaXRlcmlhIG9iamVjdHMgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nXG4gICAqIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNvcnQuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNvbXBhcmVyIFRoZSBmdW5jdGlvbiB0byBkZWZpbmUgc29ydCBvcmRlci5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlU29ydEJ5KGFycmF5LCBjb21wYXJlcikge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICBhcnJheS5zb3J0KGNvbXBhcmVyKTtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGFycmF5W2xlbmd0aF0gPSBhcnJheVtsZW5ndGhdLnZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc3VtYCBhbmQgYF8uc3VtQnlgIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3VtLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVN1bShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICB2YXIgcmVzdWx0LFxuICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIGN1cnJlbnQgPSBpdGVyYXRlZShhcnJheVtpbmRleF0pO1xuICAgICAgaWYgKGN1cnJlbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQgPT09IHVuZGVmaW5lZCA/IGN1cnJlbnQgOiAocmVzdWx0ICsgY3VycmVudCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udGltZXNgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kc1xuICAgKiBvciBtYXggYXJyYXkgbGVuZ3RoIGNoZWNrcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciBvZiB0aW1lcyB0byBpbnZva2UgYGl0ZXJhdGVlYC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiByZXN1bHRzLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVRpbWVzKG4sIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIHJlc3VsdCA9IEFycmF5KG4pO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBuKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gaXRlcmF0ZWUoaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnRvUGFpcnNgIGFuZCBgXy50b1BhaXJzSW5gIHdoaWNoIGNyZWF0ZXMgYW4gYXJyYXlcbiAgICogb2Yga2V5LXZhbHVlIHBhaXJzIGZvciBgb2JqZWN0YCBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm9wZXJ0eSBuYW1lcyBvZiBgcHJvcHNgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBnZXQgdmFsdWVzIGZvci5cbiAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVRvUGFpcnMob2JqZWN0LCBwcm9wcykge1xuICAgIHJldHVybiBhcnJheU1hcChwcm9wcywgZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gW2tleSwgb2JqZWN0W2tleV1dO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnVuYXJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIHN0b3JpbmcgbWV0YWRhdGEuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhcCBhcmd1bWVudHMgZm9yLlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjYXBwZWQgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVW5hcnkoZnVuYykge1xuICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmModmFsdWUpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udmFsdWVzYCBhbmQgYF8udmFsdWVzSW5gIHdoaWNoIGNyZWF0ZXMgYW5cbiAgICogYXJyYXkgb2YgYG9iamVjdGAgcHJvcGVydHkgdmFsdWVzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3BlcnR5IG5hbWVzXG4gICAqIG9mIGBwcm9wc2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGdldCB2YWx1ZXMgZm9yLlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVmFsdWVzKG9iamVjdCwgcHJvcHMpIHtcbiAgICByZXR1cm4gYXJyYXlNYXAocHJvcHMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIG9iamVjdFtrZXldO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhIGBjYWNoZWAgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IGNhY2hlIFRoZSBjYWNoZSB0byBxdWVyeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGNhY2hlSGFzKGNhY2hlLCBrZXkpIHtcbiAgICByZXR1cm4gY2FjaGUuaGFzKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy50cmltYCBhbmQgYF8udHJpbVN0YXJ0YCB0byBnZXQgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBzdHJpbmcgc3ltYm9sXG4gICAqIHRoYXQgaXMgbm90IGZvdW5kIGluIHRoZSBjaGFyYWN0ZXIgc3ltYm9scy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gc3RyU3ltYm9scyBUaGUgc3RyaW5nIHN5bWJvbHMgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtBcnJheX0gY2hyU3ltYm9scyBUaGUgY2hhcmFjdGVyIHN5bWJvbHMgdG8gZmluZC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IHVubWF0Y2hlZCBzdHJpbmcgc3ltYm9sLlxuICAgKi9cbiAgZnVuY3Rpb24gY2hhcnNTdGFydEluZGV4KHN0clN5bWJvbHMsIGNoclN5bWJvbHMpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gc3RyU3ltYm9scy5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCAmJiBiYXNlSW5kZXhPZihjaHJTeW1ib2xzLCBzdHJTeW1ib2xzW2luZGV4XSwgMCkgPiAtMSkge31cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy50cmltYCBhbmQgYF8udHJpbUVuZGAgdG8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgbGFzdCBzdHJpbmcgc3ltYm9sXG4gICAqIHRoYXQgaXMgbm90IGZvdW5kIGluIHRoZSBjaGFyYWN0ZXIgc3ltYm9scy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gc3RyU3ltYm9scyBUaGUgc3RyaW5nIHN5bWJvbHMgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtBcnJheX0gY2hyU3ltYm9scyBUaGUgY2hhcmFjdGVyIHN5bWJvbHMgdG8gZmluZC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGxhc3QgdW5tYXRjaGVkIHN0cmluZyBzeW1ib2wuXG4gICAqL1xuICBmdW5jdGlvbiBjaGFyc0VuZEluZGV4KHN0clN5bWJvbHMsIGNoclN5bWJvbHMpIHtcbiAgICB2YXIgaW5kZXggPSBzdHJTeW1ib2xzLmxlbmd0aDtcblxuICAgIHdoaWxlIChpbmRleC0tICYmIGJhc2VJbmRleE9mKGNoclN5bWJvbHMsIHN0clN5bWJvbHNbaW5kZXhdLCAwKSA+IC0xKSB7fVxuICAgIHJldHVybiBpbmRleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBudW1iZXIgb2YgYHBsYWNlaG9sZGVyYCBvY2N1cnJlbmNlcyBpbiBgYXJyYXlgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHsqfSBwbGFjZWhvbGRlciBUaGUgcGxhY2Vob2xkZXIgdG8gc2VhcmNoIGZvci5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcGxhY2Vob2xkZXIgY291bnQuXG4gICAqL1xuICBmdW5jdGlvbiBjb3VudEhvbGRlcnMoYXJyYXksIHBsYWNlaG9sZGVyKSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgcmVzdWx0ID0gMDtcblxuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgaWYgKGFycmF5W2xlbmd0aF0gPT09IHBsYWNlaG9sZGVyKSB7XG4gICAgICAgICsrcmVzdWx0O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8uZGVidXJyYCB0byBjb252ZXJ0IExhdGluLTEgU3VwcGxlbWVudCBhbmQgTGF0aW4gRXh0ZW5kZWQtQVxuICAgKiBsZXR0ZXJzIHRvIGJhc2ljIExhdGluIGxldHRlcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsZXR0ZXIgVGhlIG1hdGNoZWQgbGV0dGVyIHRvIGRlYnVyci5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZGVidXJyZWQgbGV0dGVyLlxuICAgKi9cbiAgdmFyIGRlYnVyckxldHRlciA9IGJhc2VQcm9wZXJ0eU9mKGRlYnVycmVkTGV0dGVycyk7XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8uZXNjYXBlYCB0byBjb252ZXJ0IGNoYXJhY3RlcnMgdG8gSFRNTCBlbnRpdGllcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNociBUaGUgbWF0Y2hlZCBjaGFyYWN0ZXIgdG8gZXNjYXBlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlc2NhcGVkIGNoYXJhY3Rlci5cbiAgICovXG4gIHZhciBlc2NhcGVIdG1sQ2hhciA9IGJhc2VQcm9wZXJ0eU9mKGh0bWxFc2NhcGVzKTtcblxuICAvKipcbiAgICogVXNlZCBieSBgXy50ZW1wbGF0ZWAgdG8gZXNjYXBlIGNoYXJhY3RlcnMgZm9yIGluY2x1c2lvbiBpbiBjb21waWxlZCBzdHJpbmcgbGl0ZXJhbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaHIgVGhlIG1hdGNoZWQgY2hhcmFjdGVyIHRvIGVzY2FwZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAqL1xuICBmdW5jdGlvbiBlc2NhcGVTdHJpbmdDaGFyKGNocikge1xuICAgIHJldHVybiAnXFxcXCcgKyBzdHJpbmdFc2NhcGVzW2Nocl07XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgdmFsdWUgYXQgYGtleWAgb2YgYG9iamVjdGAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0VmFsdWUob2JqZWN0LCBrZXkpIHtcbiAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3Rba2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYHN0cmluZ2AgY29udGFpbnMgVW5pY29kZSBzeW1ib2xzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGEgc3ltYm9sIGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBoYXNVbmljb2RlKHN0cmluZykge1xuICAgIHJldHVybiByZUhhc1VuaWNvZGUudGVzdChzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBgc3RyaW5nYCBjb250YWlucyBhIHdvcmQgY29tcG9zZWQgb2YgVW5pY29kZSBzeW1ib2xzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGEgd29yZCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gaGFzVW5pY29kZVdvcmQoc3RyaW5nKSB7XG4gICAgcmV0dXJuIHJlSGFzVW5pY29kZVdvcmQudGVzdChzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBpdGVyYXRvcmAgdG8gYW4gYXJyYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBpdGVyYXRvciBUaGUgaXRlcmF0b3IgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBpdGVyYXRvclRvQXJyYXkoaXRlcmF0b3IpIHtcbiAgICB2YXIgZGF0YSxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoIShkYXRhID0gaXRlcmF0b3IubmV4dCgpKS5kb25lKSB7XG4gICAgICByZXN1bHQucHVzaChkYXRhLnZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBgbWFwYCB0byBpdHMga2V5LXZhbHVlIHBhaXJzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbWFwIFRoZSBtYXAgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBrZXktdmFsdWUgcGFpcnMuXG4gICAqL1xuICBmdW5jdGlvbiBtYXBUb0FycmF5KG1hcCkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBBcnJheShtYXAuc2l6ZSk7XG5cbiAgICBtYXAuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICByZXN1bHRbKytpbmRleF0gPSBba2V5LCB2YWx1ZV07XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgdW5hcnkgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGl0cyBhcmd1bWVudCB0cmFuc2Zvcm1lZC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gdHJhbnNmb3JtIFRoZSBhcmd1bWVudCB0cmFuc2Zvcm0uXG4gICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gb3ZlckFyZyhmdW5jLCB0cmFuc2Zvcm0pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oYXJnKSB7XG4gICAgICByZXR1cm4gZnVuYyh0cmFuc2Zvcm0oYXJnKSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyBhbGwgYHBsYWNlaG9sZGVyYCBlbGVtZW50cyBpbiBgYXJyYXlgIHdpdGggYW4gaW50ZXJuYWwgcGxhY2Vob2xkZXJcbiAgICogYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgdGhlaXIgaW5kZXhlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICogQHBhcmFtIHsqfSBwbGFjZWhvbGRlciBUaGUgcGxhY2Vob2xkZXIgdG8gcmVwbGFjZS5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICovXG4gIGZ1bmN0aW9uIHJlcGxhY2VIb2xkZXJzKGFycmF5LCBwbGFjZWhvbGRlcikge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgaWYgKHZhbHVlID09PSBwbGFjZWhvbGRlciB8fCB2YWx1ZSA9PT0gUExBQ0VIT0xERVIpIHtcbiAgICAgICAgYXJyYXlbaW5kZXhdID0gUExBQ0VIT0xERVI7XG4gICAgICAgIHJlc3VsdFtyZXNJbmRleCsrXSA9IGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBzZXRgIHRvIGFuIGFycmF5IG9mIGl0cyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHZhbHVlcy5cbiAgICovXG4gIGZ1bmN0aW9uIHNldFRvQXJyYXkoc2V0KSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIHJlc3VsdCA9IEFycmF5KHNldC5zaXplKTtcblxuICAgIHNldC5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXN1bHRbKytpbmRleF0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBzZXRgIHRvIGl0cyB2YWx1ZS12YWx1ZSBwYWlycy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IHNldCBUaGUgc2V0IHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgdmFsdWUtdmFsdWUgcGFpcnMuXG4gICAqL1xuICBmdW5jdGlvbiBzZXRUb1BhaXJzKHNldCkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBBcnJheShzZXQuc2l6ZSk7XG5cbiAgICBzZXQuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmVzdWx0WysraW5kZXhdID0gW3ZhbHVlLCB2YWx1ZV07XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uaW5kZXhPZmAgd2hpY2ggcGVyZm9ybXMgc3RyaWN0IGVxdWFsaXR5XG4gICAqIGNvbXBhcmlzb25zIG9mIHZhbHVlcywgaS5lLiBgPT09YC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tSW5kZXggVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gc3RyaWN0SW5kZXhPZihhcnJheSwgdmFsdWUsIGZyb21JbmRleCkge1xuICAgIHZhciBpbmRleCA9IGZyb21JbmRleCAtIDEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoYXJyYXlbaW5kZXhdID09PSB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8ubGFzdEluZGV4T2ZgIHdoaWNoIHBlcmZvcm1zIHN0cmljdCBlcXVhbGl0eVxuICAgKiBjb21wYXJpc29ucyBvZiB2YWx1ZXMsIGkuZS4gYD09PWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIHN0cmljdExhc3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgdmFyIGluZGV4ID0gZnJvbUluZGV4ICsgMTtcbiAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgaWYgKGFycmF5W2luZGV4XSA9PT0gdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbnVtYmVyIG9mIHN5bWJvbHMgaW4gYHN0cmluZ2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgc2l6ZS5cbiAgICovXG4gIGZ1bmN0aW9uIHN0cmluZ1NpemUoc3RyaW5nKSB7XG4gICAgcmV0dXJuIGhhc1VuaWNvZGUoc3RyaW5nKVxuICAgICAgPyB1bmljb2RlU2l6ZShzdHJpbmcpXG4gICAgICA6IGFzY2lpU2l6ZShzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIGFuIGFycmF5LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBzdHJpbmdUb0FycmF5KHN0cmluZykge1xuICAgIHJldHVybiBoYXNVbmljb2RlKHN0cmluZylcbiAgICAgID8gdW5pY29kZVRvQXJyYXkoc3RyaW5nKVxuICAgICAgOiBhc2NpaVRvQXJyYXkoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLnVuZXNjYXBlYCB0byBjb252ZXJ0IEhUTUwgZW50aXRpZXMgdG8gY2hhcmFjdGVycy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNociBUaGUgbWF0Y2hlZCBjaGFyYWN0ZXIgdG8gdW5lc2NhcGUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHVuZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAqL1xuICB2YXIgdW5lc2NhcGVIdG1sQ2hhciA9IGJhc2VQcm9wZXJ0eU9mKGh0bWxVbmVzY2FwZXMpO1xuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBzaXplIG9mIGEgVW5pY29kZSBgc3RyaW5nYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN0cmluZyBzaXplLlxuICAgKi9cbiAgZnVuY3Rpb24gdW5pY29kZVNpemUoc3RyaW5nKSB7XG4gICAgdmFyIHJlc3VsdCA9IHJlVW5pY29kZS5sYXN0SW5kZXggPSAwO1xuICAgIHdoaWxlIChyZVVuaWNvZGUudGVzdChzdHJpbmcpKSB7XG4gICAgICArK3Jlc3VsdDtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIFVuaWNvZGUgYHN0cmluZ2AgdG8gYW4gYXJyYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIHVuaWNvZGVUb0FycmF5KHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcubWF0Y2gocmVVbmljb2RlKSB8fCBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdHMgYSBVbmljb2RlIGBzdHJpbmdgIGludG8gYW4gYXJyYXkgb2YgaXRzIHdvcmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHdvcmRzIG9mIGBzdHJpbmdgLlxuICAgKi9cbiAgZnVuY3Rpb24gdW5pY29kZVdvcmRzKHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcubWF0Y2gocmVVbmljb2RlV29yZCkgfHwgW107XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IHByaXN0aW5lIGBsb2Rhc2hgIGZ1bmN0aW9uIHVzaW5nIHRoZSBgY29udGV4dGAgb2JqZWN0LlxuICAgKlxuICAgKiBAc3RhdGljXG4gICAqIEBtZW1iZXJPZiBfXG4gICAqIEBzaW5jZSAxLjEuMFxuICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgKiBAcGFyYW0ge09iamVjdH0gW2NvbnRleHQ9cm9vdF0gVGhlIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYSBuZXcgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIF8ubWl4aW4oeyAnZm9vJzogXy5jb25zdGFudCgnZm9vJykgfSk7XG4gICAqXG4gICAqIHZhciBsb2Rhc2ggPSBfLnJ1bkluQ29udGV4dCgpO1xuICAgKiBsb2Rhc2gubWl4aW4oeyAnYmFyJzogbG9kYXNoLmNvbnN0YW50KCdiYXInKSB9KTtcbiAgICpcbiAgICogXy5pc0Z1bmN0aW9uKF8uZm9vKTtcbiAgICogLy8gPT4gdHJ1ZVxuICAgKiBfLmlzRnVuY3Rpb24oXy5iYXIpO1xuICAgKiAvLyA9PiBmYWxzZVxuICAgKlxuICAgKiBsb2Rhc2guaXNGdW5jdGlvbihsb2Rhc2guZm9vKTtcbiAgICogLy8gPT4gZmFsc2VcbiAgICogbG9kYXNoLmlzRnVuY3Rpb24obG9kYXNoLmJhcik7XG4gICAqIC8vID0+IHRydWVcbiAgICpcbiAgICogLy8gQ3JlYXRlIGEgc3VwZWQtdXAgYGRlZmVyYCBpbiBOb2RlLmpzLlxuICAgKiB2YXIgZGVmZXIgPSBfLnJ1bkluQ29udGV4dCh7ICdzZXRUaW1lb3V0Jzogc2V0SW1tZWRpYXRlIH0pLmRlZmVyO1xuICAgKi9cbiAgdmFyIHJ1bkluQ29udGV4dCA9IChmdW5jdGlvbiBydW5JbkNvbnRleHQoY29udGV4dCkge1xuICAgIGNvbnRleHQgPSBjb250ZXh0ID09IG51bGwgPyByb290IDogXy5kZWZhdWx0cyhyb290Lk9iamVjdCgpLCBjb250ZXh0LCBfLnBpY2socm9vdCwgY29udGV4dFByb3BzKSk7XG5cbiAgICAvKiogQnVpbHQtaW4gY29uc3RydWN0b3IgcmVmZXJlbmNlcy4gKi9cbiAgICB2YXIgQXJyYXkgPSBjb250ZXh0LkFycmF5LFxuICAgICAgICBEYXRlID0gY29udGV4dC5EYXRlLFxuICAgICAgICBFcnJvciA9IGNvbnRleHQuRXJyb3IsXG4gICAgICAgIEZ1bmN0aW9uID0gY29udGV4dC5GdW5jdGlvbixcbiAgICAgICAgTWF0aCA9IGNvbnRleHQuTWF0aCxcbiAgICAgICAgT2JqZWN0ID0gY29udGV4dC5PYmplY3QsXG4gICAgICAgIFJlZ0V4cCA9IGNvbnRleHQuUmVnRXhwLFxuICAgICAgICBTdHJpbmcgPSBjb250ZXh0LlN0cmluZyxcbiAgICAgICAgVHlwZUVycm9yID0gY29udGV4dC5UeXBlRXJyb3I7XG5cbiAgICAvKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG4gICAgdmFyIGFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGUsXG4gICAgICAgIGZ1bmNQcm90byA9IEZ1bmN0aW9uLnByb3RvdHlwZSxcbiAgICAgICAgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IG92ZXJyZWFjaGluZyBjb3JlLWpzIHNoaW1zLiAqL1xuICAgIHZhciBjb3JlSnNEYXRhID0gY29udGV4dFsnX19jb3JlLWpzX3NoYXJlZF9fJ107XG5cbiAgICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBkZWNvbXBpbGVkIHNvdXJjZSBvZiBmdW5jdGlvbnMuICovXG4gICAgdmFyIGZ1bmNUb1N0cmluZyA9IGZ1bmNQcm90by50b1N0cmluZztcblxuICAgIC8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xuICAgIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gICAgLyoqIFVzZWQgdG8gZ2VuZXJhdGUgdW5pcXVlIElEcy4gKi9cbiAgICB2YXIgaWRDb3VudGVyID0gMDtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBtZXRob2RzIG1hc3F1ZXJhZGluZyBhcyBuYXRpdmUuICovXG4gICAgdmFyIG1hc2tTcmNLZXkgPSAoZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdWlkID0gL1teLl0rJC8uZXhlYyhjb3JlSnNEYXRhICYmIGNvcmVKc0RhdGEua2V5cyAmJiBjb3JlSnNEYXRhLmtleXMuSUVfUFJPVE8gfHwgJycpO1xuICAgICAgcmV0dXJuIHVpZCA/ICgnU3ltYm9sKHNyYylfMS4nICsgdWlkKSA6ICcnO1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIHRvIHJlc29sdmUgdGhlXG4gICAgICogW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gICAgICogb2YgdmFsdWVzLlxuICAgICAqL1xuICAgIHZhciBuYXRpdmVPYmplY3RUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gICAgLyoqIFVzZWQgdG8gaW5mZXIgdGhlIGBPYmplY3RgIGNvbnN0cnVjdG9yLiAqL1xuICAgIHZhciBvYmplY3RDdG9yU3RyaW5nID0gZnVuY1RvU3RyaW5nLmNhbGwoT2JqZWN0KTtcblxuICAgIC8qKiBVc2VkIHRvIHJlc3RvcmUgdGhlIG9yaWdpbmFsIGBfYCByZWZlcmVuY2UgaW4gYF8ubm9Db25mbGljdGAuICovXG4gICAgdmFyIG9sZERhc2ggPSByb290Ll87XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYSBtZXRob2QgaXMgbmF0aXZlLiAqL1xuICAgIHZhciByZUlzTmF0aXZlID0gUmVnRXhwKCdeJyArXG4gICAgICBmdW5jVG9TdHJpbmcuY2FsbChoYXNPd25Qcm9wZXJ0eSkucmVwbGFjZShyZVJlZ0V4cENoYXIsICdcXFxcJCYnKVxuICAgICAgLnJlcGxhY2UoL2hhc093blByb3BlcnR5fChmdW5jdGlvbikuKj8oPz1cXFxcXFwoKXwgZm9yIC4rPyg/PVxcXFxcXF0pL2csICckMS4qPycpICsgJyQnXG4gICAgKTtcblxuICAgIC8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xuICAgIHZhciBCdWZmZXIgPSBtb2R1bGVFeHBvcnRzID8gY29udGV4dC5CdWZmZXIgOiB1bmRlZmluZWQsXG4gICAgICAgIFN5bWJvbCA9IGNvbnRleHQuU3ltYm9sLFxuICAgICAgICBVaW50OEFycmF5ID0gY29udGV4dC5VaW50OEFycmF5LFxuICAgICAgICBhbGxvY1Vuc2FmZSA9IEJ1ZmZlciA/IEJ1ZmZlci5hbGxvY1Vuc2FmZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZ2V0UHJvdG90eXBlID0gb3ZlckFyZyhPYmplY3QuZ2V0UHJvdG90eXBlT2YsIE9iamVjdCksXG4gICAgICAgIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUsXG4gICAgICAgIHByb3BlcnR5SXNFbnVtZXJhYmxlID0gb2JqZWN0UHJvdG8ucHJvcGVydHlJc0VudW1lcmFibGUsXG4gICAgICAgIHNwbGljZSA9IGFycmF5UHJvdG8uc3BsaWNlLFxuICAgICAgICBzcHJlYWRhYmxlU3ltYm9sID0gU3ltYm9sID8gU3ltYm9sLmlzQ29uY2F0U3ByZWFkYWJsZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgc3ltSXRlcmF0b3IgPSBTeW1ib2wgPyBTeW1ib2wuaXRlcmF0b3IgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bVRvU3RyaW5nVGFnID0gU3ltYm9sID8gU3ltYm9sLnRvU3RyaW5nVGFnIDogdW5kZWZpbmVkO1xuXG4gICAgdmFyIGRlZmluZVByb3BlcnR5ID0gKGZ1bmN0aW9uKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIGZ1bmMgPSBnZXROYXRpdmUoT2JqZWN0LCAnZGVmaW5lUHJvcGVydHknKTtcbiAgICAgICAgZnVuYyh7fSwgJycsIHt9KTtcbiAgICAgICAgcmV0dXJuIGZ1bmM7XG4gICAgICB9IGNhdGNoIChlKSB7fVxuICAgIH0oKSk7XG5cbiAgICAvKiogTW9ja2VkIGJ1aWx0LWlucy4gKi9cbiAgICB2YXIgY3R4Q2xlYXJUaW1lb3V0ID0gY29udGV4dC5jbGVhclRpbWVvdXQgIT09IHJvb3QuY2xlYXJUaW1lb3V0ICYmIGNvbnRleHQuY2xlYXJUaW1lb3V0LFxuICAgICAgICBjdHhOb3cgPSBEYXRlICYmIERhdGUubm93ICE9PSByb290LkRhdGUubm93ICYmIERhdGUubm93LFxuICAgICAgICBjdHhTZXRUaW1lb3V0ID0gY29udGV4dC5zZXRUaW1lb3V0ICE9PSByb290LnNldFRpbWVvdXQgJiYgY29udGV4dC5zZXRUaW1lb3V0O1xuXG4gICAgLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xuICAgIHZhciBuYXRpdmVDZWlsID0gTWF0aC5jZWlsLFxuICAgICAgICBuYXRpdmVGbG9vciA9IE1hdGguZmxvb3IsXG4gICAgICAgIG5hdGl2ZUdldFN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzLFxuICAgICAgICBuYXRpdmVJc0J1ZmZlciA9IEJ1ZmZlciA/IEJ1ZmZlci5pc0J1ZmZlciA6IHVuZGVmaW5lZCxcbiAgICAgICAgbmF0aXZlSXNGaW5pdGUgPSBjb250ZXh0LmlzRmluaXRlLFxuICAgICAgICBuYXRpdmVKb2luID0gYXJyYXlQcm90by5qb2luLFxuICAgICAgICBuYXRpdmVLZXlzID0gb3ZlckFyZyhPYmplY3Qua2V5cywgT2JqZWN0KSxcbiAgICAgICAgbmF0aXZlTWF4ID0gTWF0aC5tYXgsXG4gICAgICAgIG5hdGl2ZU1pbiA9IE1hdGgubWluLFxuICAgICAgICBuYXRpdmVOb3cgPSBEYXRlLm5vdyxcbiAgICAgICAgbmF0aXZlUGFyc2VJbnQgPSBjb250ZXh0LnBhcnNlSW50LFxuICAgICAgICBuYXRpdmVSYW5kb20gPSBNYXRoLnJhbmRvbSxcbiAgICAgICAgbmF0aXZlUmV2ZXJzZSA9IGFycmF5UHJvdG8ucmV2ZXJzZTtcblxuICAgIC8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHRoYXQgYXJlIHZlcmlmaWVkIHRvIGJlIG5hdGl2ZS4gKi9cbiAgICB2YXIgRGF0YVZpZXcgPSBnZXROYXRpdmUoY29udGV4dCwgJ0RhdGFWaWV3JyksXG4gICAgICAgIE1hcCA9IGdldE5hdGl2ZShjb250ZXh0LCAnTWFwJyksXG4gICAgICAgIFByb21pc2UgPSBnZXROYXRpdmUoY29udGV4dCwgJ1Byb21pc2UnKSxcbiAgICAgICAgU2V0ID0gZ2V0TmF0aXZlKGNvbnRleHQsICdTZXQnKSxcbiAgICAgICAgV2Vha01hcCA9IGdldE5hdGl2ZShjb250ZXh0LCAnV2Vha01hcCcpLFxuICAgICAgICBuYXRpdmVDcmVhdGUgPSBnZXROYXRpdmUoT2JqZWN0LCAnY3JlYXRlJyk7XG5cbiAgICAvKiogVXNlZCB0byBzdG9yZSBmdW5jdGlvbiBtZXRhZGF0YS4gKi9cbiAgICB2YXIgbWV0YU1hcCA9IFdlYWtNYXAgJiYgbmV3IFdlYWtNYXA7XG5cbiAgICAvKiogVXNlZCB0byBsb29rdXAgdW5taW5pZmllZCBmdW5jdGlvbiBuYW1lcy4gKi9cbiAgICB2YXIgcmVhbE5hbWVzID0ge307XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgbWFwcywgc2V0cywgYW5kIHdlYWttYXBzLiAqL1xuICAgIHZhciBkYXRhVmlld0N0b3JTdHJpbmcgPSB0b1NvdXJjZShEYXRhVmlldyksXG4gICAgICAgIG1hcEN0b3JTdHJpbmcgPSB0b1NvdXJjZShNYXApLFxuICAgICAgICBwcm9taXNlQ3RvclN0cmluZyA9IHRvU291cmNlKFByb21pc2UpLFxuICAgICAgICBzZXRDdG9yU3RyaW5nID0gdG9Tb3VyY2UoU2V0KSxcbiAgICAgICAgd2Vha01hcEN0b3JTdHJpbmcgPSB0b1NvdXJjZShXZWFrTWFwKTtcblxuICAgIC8qKiBVc2VkIHRvIGNvbnZlcnQgc3ltYm9scyB0byBwcmltaXRpdmVzIGFuZCBzdHJpbmdzLiAqL1xuICAgIHZhciBzeW1ib2xQcm90byA9IFN5bWJvbCA/IFN5bWJvbC5wcm90b3R5cGUgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bWJvbFZhbHVlT2YgPSBzeW1ib2xQcm90byA/IHN5bWJvbFByb3RvLnZhbHVlT2YgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bWJvbFRvU3RyaW5nID0gc3ltYm9sUHJvdG8gPyBzeW1ib2xQcm90by50b1N0cmluZyA6IHVuZGVmaW5lZDtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgbG9kYXNoYCBvYmplY3Qgd2hpY2ggd3JhcHMgYHZhbHVlYCB0byBlbmFibGUgaW1wbGljaXQgbWV0aG9kXG4gICAgICogY2hhaW4gc2VxdWVuY2VzLiBNZXRob2RzIHRoYXQgb3BlcmF0ZSBvbiBhbmQgcmV0dXJuIGFycmF5cywgY29sbGVjdGlvbnMsXG4gICAgICogYW5kIGZ1bmN0aW9ucyBjYW4gYmUgY2hhaW5lZCB0b2dldGhlci4gTWV0aG9kcyB0aGF0IHJldHJpZXZlIGEgc2luZ2xlIHZhbHVlXG4gICAgICogb3IgbWF5IHJldHVybiBhIHByaW1pdGl2ZSB2YWx1ZSB3aWxsIGF1dG9tYXRpY2FsbHkgZW5kIHRoZSBjaGFpbiBzZXF1ZW5jZVxuICAgICAqIGFuZCByZXR1cm4gdGhlIHVud3JhcHBlZCB2YWx1ZS4gT3RoZXJ3aXNlLCB0aGUgdmFsdWUgbXVzdCBiZSB1bndyYXBwZWRcbiAgICAgKiB3aXRoIGBfI3ZhbHVlYC5cbiAgICAgKlxuICAgICAqIEV4cGxpY2l0IGNoYWluIHNlcXVlbmNlcywgd2hpY2ggbXVzdCBiZSB1bndyYXBwZWQgd2l0aCBgXyN2YWx1ZWAsIG1heSBiZVxuICAgICAqIGVuYWJsZWQgdXNpbmcgYF8uY2hhaW5gLlxuICAgICAqXG4gICAgICogVGhlIGV4ZWN1dGlvbiBvZiBjaGFpbmVkIG1ldGhvZHMgaXMgbGF6eSwgdGhhdCBpcywgaXQncyBkZWZlcnJlZCB1bnRpbFxuICAgICAqIGBfI3ZhbHVlYCBpcyBpbXBsaWNpdGx5IG9yIGV4cGxpY2l0bHkgY2FsbGVkLlxuICAgICAqXG4gICAgICogTGF6eSBldmFsdWF0aW9uIGFsbG93cyBzZXZlcmFsIG1ldGhvZHMgdG8gc3VwcG9ydCBzaG9ydGN1dCBmdXNpb24uXG4gICAgICogU2hvcnRjdXQgZnVzaW9uIGlzIGFuIG9wdGltaXphdGlvbiB0byBtZXJnZSBpdGVyYXRlZSBjYWxsczsgdGhpcyBhdm9pZHNcbiAgICAgKiB0aGUgY3JlYXRpb24gb2YgaW50ZXJtZWRpYXRlIGFycmF5cyBhbmQgY2FuIGdyZWF0bHkgcmVkdWNlIHRoZSBudW1iZXIgb2ZcbiAgICAgKiBpdGVyYXRlZSBleGVjdXRpb25zLiBTZWN0aW9ucyBvZiBhIGNoYWluIHNlcXVlbmNlIHF1YWxpZnkgZm9yIHNob3J0Y3V0XG4gICAgICogZnVzaW9uIGlmIHRoZSBzZWN0aW9uIGlzIGFwcGxpZWQgdG8gYW4gYXJyYXkgYW5kIGl0ZXJhdGVlcyBhY2NlcHQgb25seVxuICAgICAqIG9uZSBhcmd1bWVudC4gVGhlIGhldXJpc3RpYyBmb3Igd2hldGhlciBhIHNlY3Rpb24gcXVhbGlmaWVzIGZvciBzaG9ydGN1dFxuICAgICAqIGZ1c2lvbiBpcyBzdWJqZWN0IHRvIGNoYW5nZS5cbiAgICAgKlxuICAgICAqIENoYWluaW5nIGlzIHN1cHBvcnRlZCBpbiBjdXN0b20gYnVpbGRzIGFzIGxvbmcgYXMgdGhlIGBfI3ZhbHVlYCBtZXRob2QgaXNcbiAgICAgKiBkaXJlY3RseSBvciBpbmRpcmVjdGx5IGluY2x1ZGVkIGluIHRoZSBidWlsZC5cbiAgICAgKlxuICAgICAqIEluIGFkZGl0aW9uIHRvIGxvZGFzaCBtZXRob2RzLCB3cmFwcGVycyBoYXZlIGBBcnJheWAgYW5kIGBTdHJpbmdgIG1ldGhvZHMuXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBgQXJyYXlgIG1ldGhvZHMgYXJlOlxuICAgICAqIGBjb25jYXRgLCBgam9pbmAsIGBwb3BgLCBgcHVzaGAsIGBzaGlmdGAsIGBzb3J0YCwgYHNwbGljZWAsIGFuZCBgdW5zaGlmdGBcbiAgICAgKlxuICAgICAqIFRoZSB3cmFwcGVyIGBTdHJpbmdgIG1ldGhvZHMgYXJlOlxuICAgICAqIGByZXBsYWNlYCBhbmQgYHNwbGl0YFxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgbWV0aG9kcyB0aGF0IHN1cHBvcnQgc2hvcnRjdXQgZnVzaW9uIGFyZTpcbiAgICAgKiBgYXRgLCBgY29tcGFjdGAsIGBkcm9wYCwgYGRyb3BSaWdodGAsIGBkcm9wV2hpbGVgLCBgZmlsdGVyYCwgYGZpbmRgLFxuICAgICAqIGBmaW5kTGFzdGAsIGBoZWFkYCwgYGluaXRpYWxgLCBgbGFzdGAsIGBtYXBgLCBgcmVqZWN0YCwgYHJldmVyc2VgLCBgc2xpY2VgLFxuICAgICAqIGB0YWlsYCwgYHRha2VgLCBgdGFrZVJpZ2h0YCwgYHRha2VSaWdodFdoaWxlYCwgYHRha2VXaGlsZWAsIGFuZCBgdG9BcnJheWBcbiAgICAgKlxuICAgICAqIFRoZSBjaGFpbmFibGUgd3JhcHBlciBtZXRob2RzIGFyZTpcbiAgICAgKiBgYWZ0ZXJgLCBgYXJ5YCwgYGFzc2lnbmAsIGBhc3NpZ25JbmAsIGBhc3NpZ25JbldpdGhgLCBgYXNzaWduV2l0aGAsIGBhdGAsXG4gICAgICogYGJlZm9yZWAsIGBiaW5kYCwgYGJpbmRBbGxgLCBgYmluZEtleWAsIGBjYXN0QXJyYXlgLCBgY2hhaW5gLCBgY2h1bmtgLFxuICAgICAqIGBjb21taXRgLCBgY29tcGFjdGAsIGBjb25jYXRgLCBgY29uZm9ybXNgLCBgY29uc3RhbnRgLCBgY291bnRCeWAsIGBjcmVhdGVgLFxuICAgICAqIGBjdXJyeWAsIGBkZWJvdW5jZWAsIGBkZWZhdWx0c2AsIGBkZWZhdWx0c0RlZXBgLCBgZGVmZXJgLCBgZGVsYXlgLFxuICAgICAqIGBkaWZmZXJlbmNlYCwgYGRpZmZlcmVuY2VCeWAsIGBkaWZmZXJlbmNlV2l0aGAsIGBkcm9wYCwgYGRyb3BSaWdodGAsXG4gICAgICogYGRyb3BSaWdodFdoaWxlYCwgYGRyb3BXaGlsZWAsIGBleHRlbmRgLCBgZXh0ZW5kV2l0aGAsIGBmaWxsYCwgYGZpbHRlcmAsXG4gICAgICogYGZsYXRNYXBgLCBgZmxhdE1hcERlZXBgLCBgZmxhdE1hcERlcHRoYCwgYGZsYXR0ZW5gLCBgZmxhdHRlbkRlZXBgLFxuICAgICAqIGBmbGF0dGVuRGVwdGhgLCBgZmxpcGAsIGBmbG93YCwgYGZsb3dSaWdodGAsIGBmcm9tUGFpcnNgLCBgZnVuY3Rpb25zYCxcbiAgICAgKiBgZnVuY3Rpb25zSW5gLCBgZ3JvdXBCeWAsIGBpbml0aWFsYCwgYGludGVyc2VjdGlvbmAsIGBpbnRlcnNlY3Rpb25CeWAsXG4gICAgICogYGludGVyc2VjdGlvbldpdGhgLCBgaW52ZXJ0YCwgYGludmVydEJ5YCwgYGludm9rZU1hcGAsIGBpdGVyYXRlZWAsIGBrZXlCeWAsXG4gICAgICogYGtleXNgLCBga2V5c0luYCwgYG1hcGAsIGBtYXBLZXlzYCwgYG1hcFZhbHVlc2AsIGBtYXRjaGVzYCwgYG1hdGNoZXNQcm9wZXJ0eWAsXG4gICAgICogYG1lbW9pemVgLCBgbWVyZ2VgLCBgbWVyZ2VXaXRoYCwgYG1ldGhvZGAsIGBtZXRob2RPZmAsIGBtaXhpbmAsIGBuZWdhdGVgLFxuICAgICAqIGBudGhBcmdgLCBgb21pdGAsIGBvbWl0QnlgLCBgb25jZWAsIGBvcmRlckJ5YCwgYG92ZXJgLCBgb3ZlckFyZ3NgLFxuICAgICAqIGBvdmVyRXZlcnlgLCBgb3ZlclNvbWVgLCBgcGFydGlhbGAsIGBwYXJ0aWFsUmlnaHRgLCBgcGFydGl0aW9uYCwgYHBpY2tgLFxuICAgICAqIGBwaWNrQnlgLCBgcGxhbnRgLCBgcHJvcGVydHlgLCBgcHJvcGVydHlPZmAsIGBwdWxsYCwgYHB1bGxBbGxgLCBgcHVsbEFsbEJ5YCxcbiAgICAgKiBgcHVsbEFsbFdpdGhgLCBgcHVsbEF0YCwgYHB1c2hgLCBgcmFuZ2VgLCBgcmFuZ2VSaWdodGAsIGByZWFyZ2AsIGByZWplY3RgLFxuICAgICAqIGByZW1vdmVgLCBgcmVzdGAsIGByZXZlcnNlYCwgYHNhbXBsZVNpemVgLCBgc2V0YCwgYHNldFdpdGhgLCBgc2h1ZmZsZWAsXG4gICAgICogYHNsaWNlYCwgYHNvcnRgLCBgc29ydEJ5YCwgYHNwbGljZWAsIGBzcHJlYWRgLCBgdGFpbGAsIGB0YWtlYCwgYHRha2VSaWdodGAsXG4gICAgICogYHRha2VSaWdodFdoaWxlYCwgYHRha2VXaGlsZWAsIGB0YXBgLCBgdGhyb3R0bGVgLCBgdGhydWAsIGB0b0FycmF5YCxcbiAgICAgKiBgdG9QYWlyc2AsIGB0b1BhaXJzSW5gLCBgdG9QYXRoYCwgYHRvUGxhaW5PYmplY3RgLCBgdHJhbnNmb3JtYCwgYHVuYXJ5YCxcbiAgICAgKiBgdW5pb25gLCBgdW5pb25CeWAsIGB1bmlvbldpdGhgLCBgdW5pcWAsIGB1bmlxQnlgLCBgdW5pcVdpdGhgLCBgdW5zZXRgLFxuICAgICAqIGB1bnNoaWZ0YCwgYHVuemlwYCwgYHVuemlwV2l0aGAsIGB1cGRhdGVgLCBgdXBkYXRlV2l0aGAsIGB2YWx1ZXNgLFxuICAgICAqIGB2YWx1ZXNJbmAsIGB3aXRob3V0YCwgYHdyYXBgLCBgeG9yYCwgYHhvckJ5YCwgYHhvcldpdGhgLCBgemlwYCxcbiAgICAgKiBgemlwT2JqZWN0YCwgYHppcE9iamVjdERlZXBgLCBhbmQgYHppcFdpdGhgXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBtZXRob2RzIHRoYXQgYXJlICoqbm90KiogY2hhaW5hYmxlIGJ5IGRlZmF1bHQgYXJlOlxuICAgICAqIGBhZGRgLCBgYXR0ZW1wdGAsIGBjYW1lbENhc2VgLCBgY2FwaXRhbGl6ZWAsIGBjZWlsYCwgYGNsYW1wYCwgYGNsb25lYCxcbiAgICAgKiBgY2xvbmVEZWVwYCwgYGNsb25lRGVlcFdpdGhgLCBgY2xvbmVXaXRoYCwgYGNvbmZvcm1zVG9gLCBgZGVidXJyYCxcbiAgICAgKiBgZGVmYXVsdFRvYCwgYGRpdmlkZWAsIGBlYWNoYCwgYGVhY2hSaWdodGAsIGBlbmRzV2l0aGAsIGBlcWAsIGBlc2NhcGVgLFxuICAgICAqIGBlc2NhcGVSZWdFeHBgLCBgZXZlcnlgLCBgZmluZGAsIGBmaW5kSW5kZXhgLCBgZmluZEtleWAsIGBmaW5kTGFzdGAsXG4gICAgICogYGZpbmRMYXN0SW5kZXhgLCBgZmluZExhc3RLZXlgLCBgZmlyc3RgLCBgZmxvb3JgLCBgZm9yRWFjaGAsIGBmb3JFYWNoUmlnaHRgLFxuICAgICAqIGBmb3JJbmAsIGBmb3JJblJpZ2h0YCwgYGZvck93bmAsIGBmb3JPd25SaWdodGAsIGBnZXRgLCBgZ3RgLCBgZ3RlYCwgYGhhc2AsXG4gICAgICogYGhhc0luYCwgYGhlYWRgLCBgaWRlbnRpdHlgLCBgaW5jbHVkZXNgLCBgaW5kZXhPZmAsIGBpblJhbmdlYCwgYGludm9rZWAsXG4gICAgICogYGlzQXJndW1lbnRzYCwgYGlzQXJyYXlgLCBgaXNBcnJheUJ1ZmZlcmAsIGBpc0FycmF5TGlrZWAsIGBpc0FycmF5TGlrZU9iamVjdGAsXG4gICAgICogYGlzQm9vbGVhbmAsIGBpc0J1ZmZlcmAsIGBpc0RhdGVgLCBgaXNFbGVtZW50YCwgYGlzRW1wdHlgLCBgaXNFcXVhbGAsXG4gICAgICogYGlzRXF1YWxXaXRoYCwgYGlzRXJyb3JgLCBgaXNGaW5pdGVgLCBgaXNGdW5jdGlvbmAsIGBpc0ludGVnZXJgLCBgaXNMZW5ndGhgLFxuICAgICAqIGBpc01hcGAsIGBpc01hdGNoYCwgYGlzTWF0Y2hXaXRoYCwgYGlzTmFOYCwgYGlzTmF0aXZlYCwgYGlzTmlsYCwgYGlzTnVsbGAsXG4gICAgICogYGlzTnVtYmVyYCwgYGlzT2JqZWN0YCwgYGlzT2JqZWN0TGlrZWAsIGBpc1BsYWluT2JqZWN0YCwgYGlzUmVnRXhwYCxcbiAgICAgKiBgaXNTYWZlSW50ZWdlcmAsIGBpc1NldGAsIGBpc1N0cmluZ2AsIGBpc1VuZGVmaW5lZGAsIGBpc1R5cGVkQXJyYXlgLFxuICAgICAqIGBpc1dlYWtNYXBgLCBgaXNXZWFrU2V0YCwgYGpvaW5gLCBga2ViYWJDYXNlYCwgYGxhc3RgLCBgbGFzdEluZGV4T2ZgLFxuICAgICAqIGBsb3dlckNhc2VgLCBgbG93ZXJGaXJzdGAsIGBsdGAsIGBsdGVgLCBgbWF4YCwgYG1heEJ5YCwgYG1lYW5gLCBgbWVhbkJ5YCxcbiAgICAgKiBgbWluYCwgYG1pbkJ5YCwgYG11bHRpcGx5YCwgYG5vQ29uZmxpY3RgLCBgbm9vcGAsIGBub3dgLCBgbnRoYCwgYHBhZGAsXG4gICAgICogYHBhZEVuZGAsIGBwYWRTdGFydGAsIGBwYXJzZUludGAsIGBwb3BgLCBgcmFuZG9tYCwgYHJlZHVjZWAsIGByZWR1Y2VSaWdodGAsXG4gICAgICogYHJlcGVhdGAsIGByZXN1bHRgLCBgcm91bmRgLCBgcnVuSW5Db250ZXh0YCwgYHNhbXBsZWAsIGBzaGlmdGAsIGBzaXplYCxcbiAgICAgKiBgc25ha2VDYXNlYCwgYHNvbWVgLCBgc29ydGVkSW5kZXhgLCBgc29ydGVkSW5kZXhCeWAsIGBzb3J0ZWRMYXN0SW5kZXhgLFxuICAgICAqIGBzb3J0ZWRMYXN0SW5kZXhCeWAsIGBzdGFydENhc2VgLCBgc3RhcnRzV2l0aGAsIGBzdHViQXJyYXlgLCBgc3R1YkZhbHNlYCxcbiAgICAgKiBgc3R1Yk9iamVjdGAsIGBzdHViU3RyaW5nYCwgYHN0dWJUcnVlYCwgYHN1YnRyYWN0YCwgYHN1bWAsIGBzdW1CeWAsXG4gICAgICogYHRlbXBsYXRlYCwgYHRpbWVzYCwgYHRvRmluaXRlYCwgYHRvSW50ZWdlcmAsIGB0b0pTT05gLCBgdG9MZW5ndGhgLFxuICAgICAqIGB0b0xvd2VyYCwgYHRvTnVtYmVyYCwgYHRvU2FmZUludGVnZXJgLCBgdG9TdHJpbmdgLCBgdG9VcHBlcmAsIGB0cmltYCxcbiAgICAgKiBgdHJpbUVuZGAsIGB0cmltU3RhcnRgLCBgdHJ1bmNhdGVgLCBgdW5lc2NhcGVgLCBgdW5pcXVlSWRgLCBgdXBwZXJDYXNlYCxcbiAgICAgKiBgdXBwZXJGaXJzdGAsIGB2YWx1ZWAsIGFuZCBgd29yZHNgXG4gICAgICpcbiAgICAgKiBAbmFtZSBfXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAgaW4gYSBgbG9kYXNoYCBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oWzEsIDIsIDNdKTtcbiAgICAgKlxuICAgICAqIC8vIFJldHVybnMgYW4gdW53cmFwcGVkIHZhbHVlLlxuICAgICAqIHdyYXBwZWQucmVkdWNlKF8uYWRkKTtcbiAgICAgKiAvLyA9PiA2XG4gICAgICpcbiAgICAgKiAvLyBSZXR1cm5zIGEgd3JhcHBlZCB2YWx1ZS5cbiAgICAgKiB2YXIgc3F1YXJlcyA9IHdyYXBwZWQubWFwKHNxdWFyZSk7XG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoc3F1YXJlcyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheShzcXVhcmVzLnZhbHVlKCkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsb2Rhc2godmFsdWUpIHtcbiAgICAgIGlmIChpc09iamVjdExpa2UodmFsdWUpICYmICFpc0FycmF5KHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpKSB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIExvZGFzaFdyYXBwZXIpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdfX3dyYXBwZWRfXycpKSB7XG4gICAgICAgICAgcmV0dXJuIHdyYXBwZXJDbG9uZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY3JlYXRlYCB3aXRob3V0IHN1cHBvcnQgZm9yIGFzc2lnbmluZ1xuICAgICAqIHByb3BlcnRpZXMgdG8gdGhlIGNyZWF0ZWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcHJvdG8gVGhlIG9iamVjdCB0byBpbmhlcml0IGZyb20uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUNyZWF0ZSA9IChmdW5jdGlvbigpIHtcbiAgICAgIGZ1bmN0aW9uIG9iamVjdCgpIHt9XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocHJvdG8pIHtcbiAgICAgICAgaWYgKCFpc09iamVjdChwcm90bykpIHtcbiAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9iamVjdENyZWF0ZSkge1xuICAgICAgICAgIHJldHVybiBvYmplY3RDcmVhdGUocHJvdG8pO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdC5wcm90b3R5cGUgPSBwcm90bztcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBvYmplY3Q7XG4gICAgICAgIG9iamVjdC5wcm90b3R5cGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnVuY3Rpb24gd2hvc2UgcHJvdG90eXBlIGNoYWluIHNlcXVlbmNlIHdyYXBwZXJzIGluaGVyaXQgZnJvbS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUxvZGFzaCgpIHtcbiAgICAgIC8vIE5vIG9wZXJhdGlvbiBwZXJmb3JtZWQuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgY29uc3RydWN0b3IgZm9yIGNyZWF0aW5nIGBsb2Rhc2hgIHdyYXBwZXIgb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtjaGFpbkFsbF0gRW5hYmxlIGV4cGxpY2l0IG1ldGhvZCBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTG9kYXNoV3JhcHBlcih2YWx1ZSwgY2hhaW5BbGwpIHtcbiAgICAgIHRoaXMuX193cmFwcGVkX18gPSB2YWx1ZTtcbiAgICAgIHRoaXMuX19hY3Rpb25zX18gPSBbXTtcbiAgICAgIHRoaXMuX19jaGFpbl9fID0gISFjaGFpbkFsbDtcbiAgICAgIHRoaXMuX19pbmRleF9fID0gMDtcbiAgICAgIHRoaXMuX192YWx1ZXNfXyA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCeSBkZWZhdWx0LCB0aGUgdGVtcGxhdGUgZGVsaW1pdGVycyB1c2VkIGJ5IGxvZGFzaCBhcmUgbGlrZSB0aG9zZSBpblxuICAgICAqIGVtYmVkZGVkIFJ1YnkgKEVSQikgYXMgd2VsbCBhcyBFUzIwMTUgdGVtcGxhdGUgc3RyaW5ncy4gQ2hhbmdlIHRoZVxuICAgICAqIGZvbGxvd2luZyB0ZW1wbGF0ZSBzZXR0aW5ncyB0byB1c2UgYWx0ZXJuYXRpdmUgZGVsaW1pdGVycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICovXG4gICAgbG9kYXNoLnRlbXBsYXRlU2V0dGluZ3MgPSB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBkZXRlY3QgYGRhdGFgIHByb3BlcnR5IHZhbHVlcyB0byBiZSBIVE1MLWVzY2FwZWQuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUge1JlZ0V4cH1cbiAgICAgICAqL1xuICAgICAgJ2VzY2FwZSc6IHJlRXNjYXBlLFxuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gZGV0ZWN0IGNvZGUgdG8gYmUgZXZhbHVhdGVkLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtSZWdFeHB9XG4gICAgICAgKi9cbiAgICAgICdldmFsdWF0ZSc6IHJlRXZhbHVhdGUsXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBkZXRlY3QgYGRhdGFgIHByb3BlcnR5IHZhbHVlcyB0byBpbmplY3QuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUge1JlZ0V4cH1cbiAgICAgICAqL1xuICAgICAgJ2ludGVycG9sYXRlJzogcmVJbnRlcnBvbGF0ZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIHJlZmVyZW5jZSB0aGUgZGF0YSBvYmplY3QgaW4gdGhlIHRlbXBsYXRlIHRleHQuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgICAqL1xuICAgICAgJ3ZhcmlhYmxlJzogJycsXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBpbXBvcnQgdmFyaWFibGVzIGludG8gdGhlIGNvbXBpbGVkIHRlbXBsYXRlLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICAgKi9cbiAgICAgICdpbXBvcnRzJzoge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBIHJlZmVyZW5jZSB0byB0aGUgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3MuaW1wb3J0c1xuICAgICAgICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAgICAgICAqL1xuICAgICAgICAnXyc6IGxvZGFzaFxuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBFbnN1cmUgd3JhcHBlcnMgYXJlIGluc3RhbmNlcyBvZiBgYmFzZUxvZGFzaGAuXG4gICAgbG9kYXNoLnByb3RvdHlwZSA9IGJhc2VMb2Rhc2gucHJvdG90eXBlO1xuICAgIGxvZGFzaC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBsb2Rhc2g7XG5cbiAgICBMb2Rhc2hXcmFwcGVyLnByb3RvdHlwZSA9IGJhc2VDcmVhdGUoYmFzZUxvZGFzaC5wcm90b3R5cGUpO1xuICAgIExvZGFzaFdyYXBwZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTG9kYXNoV3JhcHBlcjtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBsYXp5IHdyYXBwZXIgb2JqZWN0IHdoaWNoIHdyYXBzIGB2YWx1ZWAgdG8gZW5hYmxlIGxhenkgZXZhbHVhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBMYXp5V3JhcHBlcih2YWx1ZSkge1xuICAgICAgdGhpcy5fX3dyYXBwZWRfXyA9IHZhbHVlO1xuICAgICAgdGhpcy5fX2FjdGlvbnNfXyA9IFtdO1xuICAgICAgdGhpcy5fX2Rpcl9fID0gMTtcbiAgICAgIHRoaXMuX19maWx0ZXJlZF9fID0gZmFsc2U7XG4gICAgICB0aGlzLl9faXRlcmF0ZWVzX18gPSBbXTtcbiAgICAgIHRoaXMuX190YWtlQ291bnRfXyA9IE1BWF9BUlJBWV9MRU5HVEg7XG4gICAgICB0aGlzLl9fdmlld3NfXyA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiB0aGUgbGF6eSB3cmFwcGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgY2xvbmVcbiAgICAgKiBAbWVtYmVyT2YgTGF6eVdyYXBwZXJcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgYExhenlXcmFwcGVyYCBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGF6eUNsb25lKCkge1xuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXp5V3JhcHBlcih0aGlzLl9fd3JhcHBlZF9fKTtcbiAgICAgIHJlc3VsdC5fX2FjdGlvbnNfXyA9IGNvcHlBcnJheSh0aGlzLl9fYWN0aW9uc19fKTtcbiAgICAgIHJlc3VsdC5fX2Rpcl9fID0gdGhpcy5fX2Rpcl9fO1xuICAgICAgcmVzdWx0Ll9fZmlsdGVyZWRfXyA9IHRoaXMuX19maWx0ZXJlZF9fO1xuICAgICAgcmVzdWx0Ll9faXRlcmF0ZWVzX18gPSBjb3B5QXJyYXkodGhpcy5fX2l0ZXJhdGVlc19fKTtcbiAgICAgIHJlc3VsdC5fX3Rha2VDb3VudF9fID0gdGhpcy5fX3Rha2VDb3VudF9fO1xuICAgICAgcmVzdWx0Ll9fdmlld3NfXyA9IGNvcHlBcnJheSh0aGlzLl9fdmlld3NfXyk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldmVyc2VzIHRoZSBkaXJlY3Rpb24gb2YgbGF6eSBpdGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIHJldmVyc2VcbiAgICAgKiBAbWVtYmVyT2YgTGF6eVdyYXBwZXJcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgcmV2ZXJzZWQgYExhenlXcmFwcGVyYCBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGF6eVJldmVyc2UoKSB7XG4gICAgICBpZiAodGhpcy5fX2ZpbHRlcmVkX18pIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXp5V3JhcHBlcih0aGlzKTtcbiAgICAgICAgcmVzdWx0Ll9fZGlyX18gPSAtMTtcbiAgICAgICAgcmVzdWx0Ll9fZmlsdGVyZWRfXyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQgPSB0aGlzLmNsb25lKCk7XG4gICAgICAgIHJlc3VsdC5fX2Rpcl9fICo9IC0xO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0cyB0aGUgdW53cmFwcGVkIHZhbHVlIGZyb20gaXRzIGxhenkgd3JhcHBlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgdmFsdWVcbiAgICAgKiBAbWVtYmVyT2YgTGF6eVdyYXBwZXJcbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdW53cmFwcGVkIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhenlWYWx1ZSgpIHtcbiAgICAgIHZhciBhcnJheSA9IHRoaXMuX193cmFwcGVkX18udmFsdWUoKSxcbiAgICAgICAgICBkaXIgPSB0aGlzLl9fZGlyX18sXG4gICAgICAgICAgaXNBcnIgPSBpc0FycmF5KGFycmF5KSxcbiAgICAgICAgICBpc1JpZ2h0ID0gZGlyIDwgMCxcbiAgICAgICAgICBhcnJMZW5ndGggPSBpc0FyciA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICAgICAgdmlldyA9IGdldFZpZXcoMCwgYXJyTGVuZ3RoLCB0aGlzLl9fdmlld3NfXyksXG4gICAgICAgICAgc3RhcnQgPSB2aWV3LnN0YXJ0LFxuICAgICAgICAgIGVuZCA9IHZpZXcuZW5kLFxuICAgICAgICAgIGxlbmd0aCA9IGVuZCAtIHN0YXJ0LFxuICAgICAgICAgIGluZGV4ID0gaXNSaWdodCA/IGVuZCA6IChzdGFydCAtIDEpLFxuICAgICAgICAgIGl0ZXJhdGVlcyA9IHRoaXMuX19pdGVyYXRlZXNfXyxcbiAgICAgICAgICBpdGVyTGVuZ3RoID0gaXRlcmF0ZWVzLmxlbmd0aCxcbiAgICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgICAgdGFrZUNvdW50ID0gbmF0aXZlTWluKGxlbmd0aCwgdGhpcy5fX3Rha2VDb3VudF9fKTtcblxuICAgICAgaWYgKCFpc0FyciB8fCAoIWlzUmlnaHQgJiYgYXJyTGVuZ3RoID09IGxlbmd0aCAmJiB0YWtlQ291bnQgPT0gbGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gYmFzZVdyYXBwZXJWYWx1ZShhcnJheSwgdGhpcy5fX2FjdGlvbnNfXyk7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG5cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKGxlbmd0aC0tICYmIHJlc0luZGV4IDwgdGFrZUNvdW50KSB7XG4gICAgICAgIGluZGV4ICs9IGRpcjtcblxuICAgICAgICB2YXIgaXRlckluZGV4ID0gLTEsXG4gICAgICAgICAgICB2YWx1ZSA9IGFycmF5W2luZGV4XTtcblxuICAgICAgICB3aGlsZSAoKytpdGVySW5kZXggPCBpdGVyTGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSBpdGVyYXRlZXNbaXRlckluZGV4XSxcbiAgICAgICAgICAgICAgaXRlcmF0ZWUgPSBkYXRhLml0ZXJhdGVlLFxuICAgICAgICAgICAgICB0eXBlID0gZGF0YS50eXBlLFxuICAgICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlKHZhbHVlKTtcblxuICAgICAgICAgIGlmICh0eXBlID09IExBWllfTUFQX0ZMQUcpIHtcbiAgICAgICAgICAgIHZhbHVlID0gY29tcHV0ZWQ7XG4gICAgICAgICAgfSBlbHNlIGlmICghY29tcHV0ZWQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlID09IExBWllfRklMVEVSX0ZMQUcpIHtcbiAgICAgICAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBicmVhayBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8vIEVuc3VyZSBgTGF6eVdyYXBwZXJgIGlzIGFuIGluc3RhbmNlIG9mIGBiYXNlTG9kYXNoYC5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBMYXp5V3JhcHBlcjtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBoYXNoIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2VudHJpZXNdIFRoZSBrZXktdmFsdWUgcGFpcnMgdG8gY2FjaGUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gSGFzaChlbnRyaWVzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBlbnRyaWVzID09IG51bGwgPyAwIDogZW50cmllcy5sZW5ndGg7XG5cbiAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaW5kZXhdO1xuICAgICAgICB0aGlzLnNldChlbnRyeVswXSwgZW50cnlbMV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIGhhc2guXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGNsZWFyXG4gICAgICogQG1lbWJlck9mIEhhc2hcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoQ2xlYXIoKSB7XG4gICAgICB0aGlzLl9fZGF0YV9fID0gbmF0aXZlQ3JlYXRlID8gbmF0aXZlQ3JlYXRlKG51bGwpIDoge307XG4gICAgICB0aGlzLnNpemUgPSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBoYXNoLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBkZWxldGVcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBoYXNoIFRoZSBoYXNoIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzaERlbGV0ZShrZXkpIHtcbiAgICAgIHZhciByZXN1bHQgPSB0aGlzLmhhcyhrZXkpICYmIGRlbGV0ZSB0aGlzLl9fZGF0YV9fW2tleV07XG4gICAgICB0aGlzLnNpemUgLT0gcmVzdWx0ID8gMSA6IDA7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGhhc2ggdmFsdWUgZm9yIGBrZXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBnZXRcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoR2V0KGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgaWYgKG5hdGl2ZUNyZWF0ZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZGF0YVtrZXldO1xuICAgICAgICByZXR1cm4gcmVzdWx0ID09PSBIQVNIX1VOREVGSU5FRCA/IHVuZGVmaW5lZCA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGRhdGEsIGtleSkgPyBkYXRhW2tleV0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgaGFzaCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoSGFzKGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgcmV0dXJuIG5hdGl2ZUNyZWF0ZSA/IChkYXRhW2tleV0gIT09IHVuZGVmaW5lZCkgOiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGRhdGEsIGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgaGFzaCBga2V5YCB0byBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBzZXRcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBoYXNoIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhhc2hTZXQoa2V5LCB2YWx1ZSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgdGhpcy5zaXplICs9IHRoaXMuaGFzKGtleSkgPyAwIDogMTtcbiAgICAgIGRhdGFba2V5XSA9IChuYXRpdmVDcmVhdGUgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCkgPyBIQVNIX1VOREVGSU5FRCA6IHZhbHVlO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLy8gQWRkIG1ldGhvZHMgdG8gYEhhc2hgLlxuICAgIEhhc2gucHJvdG90eXBlLmNsZWFyID0gaGFzaENsZWFyO1xuICAgIEhhc2gucHJvdG90eXBlWydkZWxldGUnXSA9IGhhc2hEZWxldGU7XG4gICAgSGFzaC5wcm90b3R5cGUuZ2V0ID0gaGFzaEdldDtcbiAgICBIYXNoLnByb3RvdHlwZS5oYXMgPSBoYXNoSGFzO1xuICAgIEhhc2gucHJvdG90eXBlLnNldCA9IGhhc2hTZXQ7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGxpc3QgY2FjaGUgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBMaXN0Q2FjaGUoZW50cmllcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gZW50cmllcyA9PSBudWxsID8gMCA6IGVudHJpZXMubGVuZ3RoO1xuXG4gICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICAgICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBsaXN0IGNhY2hlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbGVhclxuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsaXN0Q2FjaGVDbGVhcigpIHtcbiAgICAgIHRoaXMuX19kYXRhX18gPSBbXTtcbiAgICAgIHRoaXMuc2l6ZSA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIGxpc3QgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGRlbGV0ZVxuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlRGVsZXRlKGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgICAgIGluZGV4ID0gYXNzb2NJbmRleE9mKGRhdGEsIGtleSk7XG5cbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIGxhc3RJbmRleCA9IGRhdGEubGVuZ3RoIC0gMTtcbiAgICAgIGlmIChpbmRleCA9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgZGF0YS5wb3AoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNwbGljZS5jYWxsKGRhdGEsIGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICAgIC0tdGhpcy5zaXplO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbGlzdCBjYWNoZSB2YWx1ZSBmb3IgYGtleWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGdldFxuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlR2V0KGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgICAgIGluZGV4ID0gYXNzb2NJbmRleE9mKGRhdGEsIGtleSk7XG5cbiAgICAgIHJldHVybiBpbmRleCA8IDAgPyB1bmRlZmluZWQgOiBkYXRhW2luZGV4XVsxXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYSBsaXN0IGNhY2hlIHZhbHVlIGZvciBga2V5YCBleGlzdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGhhc1xuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlSGFzKGtleSkge1xuICAgICAgcmV0dXJuIGFzc29jSW5kZXhPZih0aGlzLl9fZGF0YV9fLCBrZXkpID4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbGlzdCBjYWNoZSBga2V5YCB0byBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBzZXRcbiAgICAgKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGxpc3QgY2FjaGUgaW5zdGFuY2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlU2V0KGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgICAgICBpbmRleCA9IGFzc29jSW5kZXhPZihkYXRhLCBrZXkpO1xuXG4gICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICsrdGhpcy5zaXplO1xuICAgICAgICBkYXRhLnB1c2goW2tleSwgdmFsdWVdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRhdGFbaW5kZXhdWzFdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgTGlzdENhY2hlYC5cbiAgICBMaXN0Q2FjaGUucHJvdG90eXBlLmNsZWFyID0gbGlzdENhY2hlQ2xlYXI7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBsaXN0Q2FjaGVEZWxldGU7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZS5nZXQgPSBsaXN0Q2FjaGVHZXQ7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZS5oYXMgPSBsaXN0Q2FjaGVIYXM7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZS5zZXQgPSBsaXN0Q2FjaGVTZXQ7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbWFwIGNhY2hlIG9iamVjdCB0byBzdG9yZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIE1hcENhY2hlKGVudHJpZXMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGVudHJpZXMgPT0gbnVsbCA/IDAgOiBlbnRyaWVzLmxlbmd0aDtcblxuICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgICAgIHRoaXMuc2V0KGVudHJ5WzBdLCBlbnRyeVsxXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgbWFwLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbGVhclxuICAgICAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcENhY2hlQ2xlYXIoKSB7XG4gICAgICB0aGlzLnNpemUgPSAwO1xuICAgICAgdGhpcy5fX2RhdGFfXyA9IHtcbiAgICAgICAgJ2hhc2gnOiBuZXcgSGFzaCxcbiAgICAgICAgJ21hcCc6IG5ldyAoTWFwIHx8IExpc3RDYWNoZSksXG4gICAgICAgICdzdHJpbmcnOiBuZXcgSGFzaFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgbWFwLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBkZWxldGVcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwQ2FjaGVEZWxldGUoa2V5KSB7XG4gICAgICB2YXIgcmVzdWx0ID0gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpWydkZWxldGUnXShrZXkpO1xuICAgICAgdGhpcy5zaXplIC09IHJlc3VsdCA/IDEgOiAwO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBtYXAgdmFsdWUgZm9yIGBrZXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBnZXRcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwQ2FjaGVHZXQoa2V5KSB7XG4gICAgICByZXR1cm4gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLmdldChrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIG1hcCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwQ2FjaGVIYXMoa2V5KSB7XG4gICAgICByZXR1cm4gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLmhhcyhrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1hcCBga2V5YCB0byBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBzZXRcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbWFwIGNhY2hlIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcENhY2hlU2V0KGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBkYXRhID0gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLFxuICAgICAgICAgIHNpemUgPSBkYXRhLnNpemU7XG5cbiAgICAgIGRhdGEuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgdGhpcy5zaXplICs9IGRhdGEuc2l6ZSA9PSBzaXplID8gMCA6IDE7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgTWFwQ2FjaGVgLlxuICAgIE1hcENhY2hlLnByb3RvdHlwZS5jbGVhciA9IG1hcENhY2hlQ2xlYXI7XG4gICAgTWFwQ2FjaGUucHJvdG90eXBlWydkZWxldGUnXSA9IG1hcENhY2hlRGVsZXRlO1xuICAgIE1hcENhY2hlLnByb3RvdHlwZS5nZXQgPSBtYXBDYWNoZUdldDtcbiAgICBNYXBDYWNoZS5wcm90b3R5cGUuaGFzID0gbWFwQ2FjaGVIYXM7XG4gICAgTWFwQ2FjaGUucHJvdG90eXBlLnNldCA9IG1hcENhY2hlU2V0O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IGNhY2hlIG9iamVjdCB0byBzdG9yZSB1bmlxdWUgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIFNldENhY2hlKHZhbHVlcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gdmFsdWVzID09IG51bGwgPyAwIDogdmFsdWVzLmxlbmd0aDtcblxuICAgICAgdGhpcy5fX2RhdGFfXyA9IG5ldyBNYXBDYWNoZTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuYWRkKHZhbHVlc1tpbmRleF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYHZhbHVlYCB0byB0aGUgYXJyYXkgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGFkZFxuICAgICAqIEBtZW1iZXJPZiBTZXRDYWNoZVxuICAgICAqIEBhbGlhcyBwdXNoXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2FjaGUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2FjaGUgaW5zdGFuY2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0Q2FjaGVBZGQodmFsdWUpIHtcbiAgICAgIHRoaXMuX19kYXRhX18uc2V0KHZhbHVlLCBIQVNIX1VOREVGSU5FRCk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBpbiB0aGUgYXJyYXkgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGhhc1xuICAgICAqIEBtZW1iZXJPZiBTZXRDYWNoZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldENhY2hlSGFzKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fX2RhdGFfXy5oYXModmFsdWUpO1xuICAgIH1cblxuICAgIC8vIEFkZCBtZXRob2RzIHRvIGBTZXRDYWNoZWAuXG4gICAgU2V0Q2FjaGUucHJvdG90eXBlLmFkZCA9IFNldENhY2hlLnByb3RvdHlwZS5wdXNoID0gc2V0Q2FjaGVBZGQ7XG4gICAgU2V0Q2FjaGUucHJvdG90eXBlLmhhcyA9IHNldENhY2hlSGFzO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHN0YWNrIGNhY2hlIG9iamVjdCB0byBzdG9yZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIFN0YWNrKGVudHJpZXMpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyA9IG5ldyBMaXN0Q2FjaGUoZW50cmllcyk7XG4gICAgICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgc3RhY2suXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGNsZWFyXG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhY2tDbGVhcigpIHtcbiAgICAgIHRoaXMuX19kYXRhX18gPSBuZXcgTGlzdENhY2hlO1xuICAgICAgdGhpcy5zaXplID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgc3RhY2suXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGRlbGV0ZVxuICAgICAqIEBtZW1iZXJPZiBTdGFja1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZW50cnkgd2FzIHJlbW92ZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFja0RlbGV0ZShrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgICAgICByZXN1bHQgPSBkYXRhWydkZWxldGUnXShrZXkpO1xuXG4gICAgICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHN0YWNrIHZhbHVlIGZvciBga2V5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZ2V0XG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGVudHJ5IHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrR2V0KGtleSkge1xuICAgICAgcmV0dXJuIHRoaXMuX19kYXRhX18uZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgc3RhY2sgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgaGFzXG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrSGFzKGtleSkge1xuICAgICAgcmV0dXJuIHRoaXMuX19kYXRhX18uaGFzKGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc3RhY2sgYGtleWAgdG8gYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgc2V0XG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIHN0YWNrIGNhY2hlIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrU2V0KGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgICAgIGlmIChkYXRhIGluc3RhbmNlb2YgTGlzdENhY2hlKSB7XG4gICAgICAgIHZhciBwYWlycyA9IGRhdGEuX19kYXRhX187XG4gICAgICAgIGlmICghTWFwIHx8IChwYWlycy5sZW5ndGggPCBMQVJHRV9BUlJBWV9TSVpFIC0gMSkpIHtcbiAgICAgICAgICBwYWlycy5wdXNoKFtrZXksIHZhbHVlXSk7XG4gICAgICAgICAgdGhpcy5zaXplID0gKytkYXRhLnNpemU7XG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YSA9IHRoaXMuX19kYXRhX18gPSBuZXcgTWFwQ2FjaGUocGFpcnMpO1xuICAgICAgfVxuICAgICAgZGF0YS5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgU3RhY2tgLlxuICAgIFN0YWNrLnByb3RvdHlwZS5jbGVhciA9IHN0YWNrQ2xlYXI7XG4gICAgU3RhY2sucHJvdG90eXBlWydkZWxldGUnXSA9IHN0YWNrRGVsZXRlO1xuICAgIFN0YWNrLnByb3RvdHlwZS5nZXQgPSBzdGFja0dldDtcbiAgICBTdGFjay5wcm90b3R5cGUuaGFzID0gc3RhY2tIYXM7XG4gICAgU3RhY2sucHJvdG90eXBlLnNldCA9IHN0YWNrU2V0O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBvZiB0aGUgYXJyYXktbGlrZSBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGluaGVyaXRlZCBTcGVjaWZ5IHJldHVybmluZyBpbmhlcml0ZWQgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheUxpa2VLZXlzKHZhbHVlLCBpbmhlcml0ZWQpIHtcbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkodmFsdWUpLFxuICAgICAgICAgIGlzQXJnID0gIWlzQXJyICYmIGlzQXJndW1lbnRzKHZhbHVlKSxcbiAgICAgICAgICBpc0J1ZmYgPSAhaXNBcnIgJiYgIWlzQXJnICYmIGlzQnVmZmVyKHZhbHVlKSxcbiAgICAgICAgICBpc1R5cGUgPSAhaXNBcnIgJiYgIWlzQXJnICYmICFpc0J1ZmYgJiYgaXNUeXBlZEFycmF5KHZhbHVlKSxcbiAgICAgICAgICBza2lwSW5kZXhlcyA9IGlzQXJyIHx8IGlzQXJnIHx8IGlzQnVmZiB8fCBpc1R5cGUsXG4gICAgICAgICAgcmVzdWx0ID0gc2tpcEluZGV4ZXMgPyBiYXNlVGltZXModmFsdWUubGVuZ3RoLCBTdHJpbmcpIDogW10sXG4gICAgICAgICAgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDtcblxuICAgICAgZm9yICh2YXIga2V5IGluIHZhbHVlKSB7XG4gICAgICAgIGlmICgoaW5oZXJpdGVkIHx8IGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIGtleSkpICYmXG4gICAgICAgICAgICAhKHNraXBJbmRleGVzICYmIChcbiAgICAgICAgICAgICAgIC8vIFNhZmFyaSA5IGhhcyBlbnVtZXJhYmxlIGBhcmd1bWVudHMubGVuZ3RoYCBpbiBzdHJpY3QgbW9kZS5cbiAgICAgICAgICAgICAgIGtleSA9PSAnbGVuZ3RoJyB8fFxuICAgICAgICAgICAgICAgLy8gTm9kZS5qcyAwLjEwIGhhcyBlbnVtZXJhYmxlIG5vbi1pbmRleCBwcm9wZXJ0aWVzIG9uIGJ1ZmZlcnMuXG4gICAgICAgICAgICAgICAoaXNCdWZmICYmIChrZXkgPT0gJ29mZnNldCcgfHwga2V5ID09ICdwYXJlbnQnKSkgfHxcbiAgICAgICAgICAgICAgIC8vIFBoYW50b21KUyAyIGhhcyBlbnVtZXJhYmxlIG5vbi1pbmRleCBwcm9wZXJ0aWVzIG9uIHR5cGVkIGFycmF5cy5cbiAgICAgICAgICAgICAgIChpc1R5cGUgJiYgKGtleSA9PSAnYnVmZmVyJyB8fCBrZXkgPT0gJ2J5dGVMZW5ndGgnIHx8IGtleSA9PSAnYnl0ZU9mZnNldCcpKSB8fFxuICAgICAgICAgICAgICAgLy8gU2tpcCBpbmRleCBwcm9wZXJ0aWVzLlxuICAgICAgICAgICAgICAgaXNJbmRleChrZXksIGxlbmd0aClcbiAgICAgICAgICAgICkpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc2FtcGxlYCBmb3IgYXJyYXlzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2FtcGxlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByYW5kb20gZWxlbWVudC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheVNhbXBsZShhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBhcnJheVtiYXNlUmFuZG9tKDAsIGxlbmd0aCAtIDEpXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc2FtcGxlU2l6ZWAgZm9yIGFycmF5cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNhbXBsZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheVNhbXBsZVNpemUoYXJyYXksIG4pIHtcbiAgICAgIHJldHVybiBzaHVmZmxlU2VsZihjb3B5QXJyYXkoYXJyYXkpLCBiYXNlQ2xhbXAobiwgMCwgYXJyYXkubGVuZ3RoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNodWZmbGVgIGZvciBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzaHVmZmxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNodWZmbGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFycmF5U2h1ZmZsZShhcnJheSkge1xuICAgICAgcmV0dXJuIHNodWZmbGVTZWxmKGNvcHlBcnJheShhcnJheSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgYXNzaWduVmFsdWVgIGV4Y2VwdCB0aGF0IGl0IGRvZXNuJ3QgYXNzaWduXG4gICAgICogYHVuZGVmaW5lZGAgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGFzc2lnbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhc3NpZ25NZXJnZVZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgICAgaWYgKCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFlcShvYmplY3Rba2V5XSwgdmFsdWUpKSB8fFxuICAgICAgICAgICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmICEoa2V5IGluIG9iamVjdCkpKSB7XG4gICAgICAgIGJhc2VBc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgYHZhbHVlYCB0byBga2V5YCBvZiBgb2JqZWN0YCBpZiB0aGUgZXhpc3RpbmcgdmFsdWUgaXMgbm90IGVxdWl2YWxlbnRcbiAgICAgKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGFzc2lnbi5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXNzaWduVmFsdWUob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gICAgICB2YXIgb2JqVmFsdWUgPSBvYmplY3Rba2V5XTtcbiAgICAgIGlmICghKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpICYmIGVxKG9ialZhbHVlLCB2YWx1ZSkpIHx8XG4gICAgICAgICAgKHZhbHVlID09PSB1bmRlZmluZWQgJiYgIShrZXkgaW4gb2JqZWN0KSkpIHtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaW5kZXggYXQgd2hpY2ggdGhlIGBrZXlgIGlzIGZvdW5kIGluIGBhcnJheWAgb2Yga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IGtleSBUaGUga2V5IHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhc3NvY0luZGV4T2YoYXJyYXksIGtleSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBpZiAoZXEoYXJyYXlbbGVuZ3RoXVswXSwga2V5KSkge1xuICAgICAgICAgIHJldHVybiBsZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZ2dyZWdhdGVzIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCBvbiBgYWNjdW11bGF0b3JgIHdpdGgga2V5cyB0cmFuc2Zvcm1lZFxuICAgICAqIGJ5IGBpdGVyYXRlZWAgYW5kIHZhbHVlcyBzZXQgYnkgYHNldHRlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIGZ1bmN0aW9uIHRvIHNldCBgYWNjdW11bGF0b3JgIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgaXRlcmF0ZWUgdG8gdHJhbnNmb3JtIGtleXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIGFnZ3JlZ2F0ZWQgb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgYWNjdW11bGF0b3JgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VBZ2dyZWdhdG9yKGNvbGxlY3Rpb24sIHNldHRlciwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yKSB7XG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHNldHRlcihhY2N1bXVsYXRvciwgdmFsdWUsIGl0ZXJhdGVlKHZhbHVlKSwgY29sbGVjdGlvbik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5hc3NpZ25gIHdpdGhvdXQgc3VwcG9ydCBmb3IgbXVsdGlwbGUgc291cmNlc1xuICAgICAqIG9yIGBjdXN0b21pemVyYCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUFzc2lnbihvYmplY3QsIHNvdXJjZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBjb3B5T2JqZWN0KHNvdXJjZSwga2V5cyhzb3VyY2UpLCBvYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmFzc2lnbkluYCB3aXRob3V0IHN1cHBvcnQgZm9yIG11bHRpcGxlIHNvdXJjZXNcbiAgICAgKiBvciBgY3VzdG9taXplcmAgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VBc3NpZ25JbihvYmplY3QsIHNvdXJjZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBjb3B5T2JqZWN0KHNvdXJjZSwga2V5c0luKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGFzc2lnblZhbHVlYCBhbmQgYGFzc2lnbk1lcmdlVmFsdWVgIHdpdGhvdXRcbiAgICAgKiB2YWx1ZSBjaGVja3MuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBhc3NpZ24uXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gYXNzaWduLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VBc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICAgIGlmIChrZXkgPT0gJ19fcHJvdG9fXycgJiYgZGVmaW5lUHJvcGVydHkpIHtcbiAgICAgICAgZGVmaW5lUHJvcGVydHkob2JqZWN0LCBrZXksIHtcbiAgICAgICAgICAnY29uZmlndXJhYmxlJzogdHJ1ZSxcbiAgICAgICAgICAnZW51bWVyYWJsZSc6IHRydWUsXG4gICAgICAgICAgJ3ZhbHVlJzogdmFsdWUsXG4gICAgICAgICAgJ3dyaXRhYmxlJzogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9iamVjdFtrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uYXRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRocyBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHBpY2tlZCBlbGVtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQXQob2JqZWN0LCBwYXRocykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCksXG4gICAgICAgICAgc2tpcCA9IG9iamVjdCA9PSBudWxsO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gc2tpcCA/IHVuZGVmaW5lZCA6IGdldChvYmplY3QsIHBhdGhzW2luZGV4XSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNsYW1wYCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXIgVGhlIG51bWJlciB0byBjbGFtcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xvd2VyXSBUaGUgbG93ZXIgYm91bmQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHVwcGVyIFRoZSB1cHBlciBib3VuZC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBjbGFtcGVkIG51bWJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ2xhbXAobnVtYmVyLCBsb3dlciwgdXBwZXIpIHtcbiAgICAgIGlmIChudW1iZXIgPT09IG51bWJlcikge1xuICAgICAgICBpZiAodXBwZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG51bWJlciA9IG51bWJlciA8PSB1cHBlciA/IG51bWJlciA6IHVwcGVyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsb3dlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbnVtYmVyID0gbnVtYmVyID49IGxvd2VyID8gbnVtYmVyIDogbG93ZXI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBudW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY2xvbmVgIGFuZCBgXy5jbG9uZURlZXBgIHdoaWNoIHRyYWNrc1xuICAgICAqIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuXG4gICAgICogIDEgLSBEZWVwIGNsb25lXG4gICAgICogIDIgLSBGbGF0dGVuIGluaGVyaXRlZCBwcm9wZXJ0aWVzXG4gICAgICogIDQgLSBDbG9uZSBzeW1ib2xzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY2xvbmluZy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2tleV0gVGhlIGtleSBvZiBgdmFsdWVgLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgcGFyZW50IG9iamVjdCBvZiBgdmFsdWVgLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBhbmQgdGhlaXIgY2xvbmUgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNsb25lKHZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBrZXksIG9iamVjdCwgc3RhY2spIHtcbiAgICAgIHZhciByZXN1bHQsXG4gICAgICAgICAgaXNEZWVwID0gYml0bWFzayAmIENMT05FX0RFRVBfRkxBRyxcbiAgICAgICAgICBpc0ZsYXQgPSBiaXRtYXNrICYgQ0xPTkVfRkxBVF9GTEFHLFxuICAgICAgICAgIGlzRnVsbCA9IGJpdG1hc2sgJiBDTE9ORV9TWU1CT0xTX0ZMQUc7XG5cbiAgICAgIGlmIChjdXN0b21pemVyKSB7XG4gICAgICAgIHJlc3VsdCA9IG9iamVjdCA/IGN1c3RvbWl6ZXIodmFsdWUsIGtleSwgb2JqZWN0LCBzdGFjaykgOiBjdXN0b21pemVyKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXN1bHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgaWYgKCFpc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgdmFyIGlzQXJyID0gaXNBcnJheSh2YWx1ZSk7XG4gICAgICBpZiAoaXNBcnIpIHtcbiAgICAgICAgcmVzdWx0ID0gaW5pdENsb25lQXJyYXkodmFsdWUpO1xuICAgICAgICBpZiAoIWlzRGVlcCkge1xuICAgICAgICAgIHJldHVybiBjb3B5QXJyYXkodmFsdWUsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB0YWcgPSBnZXRUYWcodmFsdWUpLFxuICAgICAgICAgICAgaXNGdW5jID0gdGFnID09IGZ1bmNUYWcgfHwgdGFnID09IGdlblRhZztcblxuICAgICAgICBpZiAoaXNCdWZmZXIodmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIGNsb25lQnVmZmVyKHZhbHVlLCBpc0RlZXApO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0YWcgPT0gb2JqZWN0VGFnIHx8IHRhZyA9PSBhcmdzVGFnIHx8IChpc0Z1bmMgJiYgIW9iamVjdCkpIHtcbiAgICAgICAgICByZXN1bHQgPSAoaXNGbGF0IHx8IGlzRnVuYykgPyB7fSA6IGluaXRDbG9uZU9iamVjdCh2YWx1ZSk7XG4gICAgICAgICAgaWYgKCFpc0RlZXApIHtcbiAgICAgICAgICAgIHJldHVybiBpc0ZsYXRcbiAgICAgICAgICAgICAgPyBjb3B5U3ltYm9sc0luKHZhbHVlLCBiYXNlQXNzaWduSW4ocmVzdWx0LCB2YWx1ZSkpXG4gICAgICAgICAgICAgIDogY29weVN5bWJvbHModmFsdWUsIGJhc2VBc3NpZ24ocmVzdWx0LCB2YWx1ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIWNsb25lYWJsZVRhZ3NbdGFnXSkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdCA/IHZhbHVlIDoge307XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdCA9IGluaXRDbG9uZUJ5VGFnKHZhbHVlLCB0YWcsIGlzRGVlcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIENoZWNrIGZvciBjaXJjdWxhciByZWZlcmVuY2VzIGFuZCByZXR1cm4gaXRzIGNvcnJlc3BvbmRpbmcgY2xvbmUuXG4gICAgICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICAgICAgdmFyIHN0YWNrZWQgPSBzdGFjay5nZXQodmFsdWUpO1xuICAgICAgaWYgKHN0YWNrZWQpIHtcbiAgICAgICAgcmV0dXJuIHN0YWNrZWQ7XG4gICAgICB9XG4gICAgICBzdGFjay5zZXQodmFsdWUsIHJlc3VsdCk7XG5cbiAgICAgIGlmIChpc1NldCh2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbihzdWJWYWx1ZSkge1xuICAgICAgICAgIHJlc3VsdC5hZGQoYmFzZUNsb25lKHN1YlZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdWJWYWx1ZSwgdmFsdWUsIHN0YWNrKSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChpc01hcCh2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbihzdWJWYWx1ZSwga2V5KSB7XG4gICAgICAgICAgcmVzdWx0LnNldChrZXksIGJhc2VDbG9uZShzdWJWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwga2V5LCB2YWx1ZSwgc3RhY2spKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHZhciBrZXlzRnVuYyA9IGlzRnVsbFxuICAgICAgICA/IChpc0ZsYXQgPyBnZXRBbGxLZXlzSW4gOiBnZXRBbGxLZXlzKVxuICAgICAgICA6IChpc0ZsYXQgPyBrZXlzSW4gOiBrZXlzKTtcblxuICAgICAgdmFyIHByb3BzID0gaXNBcnIgPyB1bmRlZmluZWQgOiBrZXlzRnVuYyh2YWx1ZSk7XG4gICAgICBhcnJheUVhY2gocHJvcHMgfHwgdmFsdWUsIGZ1bmN0aW9uKHN1YlZhbHVlLCBrZXkpIHtcbiAgICAgICAgaWYgKHByb3BzKSB7XG4gICAgICAgICAga2V5ID0gc3ViVmFsdWU7XG4gICAgICAgICAgc3ViVmFsdWUgPSB2YWx1ZVtrZXldO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IHBvcHVsYXRlIGNsb25lIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgIGFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCBiYXNlQ2xvbmUoc3ViVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGtleSwgdmFsdWUsIHN0YWNrKSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY29uZm9ybXNgIHdoaWNoIGRvZXNuJ3QgY2xvbmUgYHNvdXJjZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSBwcmVkaWNhdGVzIHRvIGNvbmZvcm0gdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc3BlYyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ29uZm9ybXMoc291cmNlKSB7XG4gICAgICB2YXIgcHJvcHMgPSBrZXlzKHNvdXJjZSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBiYXNlQ29uZm9ybXNUbyhvYmplY3QsIHNvdXJjZSwgcHJvcHMpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jb25mb3Jtc1RvYCB3aGljaCBhY2NlcHRzIGBwcm9wc2AgdG8gY2hlY2suXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSBwcmVkaWNhdGVzIHRvIGNvbmZvcm0gdG8uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBvYmplY3RgIGNvbmZvcm1zLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNvbmZvcm1zVG8ob2JqZWN0LCBzb3VyY2UsIHByb3BzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAhbGVuZ3RoO1xuICAgICAgfVxuICAgICAgb2JqZWN0ID0gT2JqZWN0KG9iamVjdCk7XG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgdmFyIGtleSA9IHByb3BzW2xlbmd0aF0sXG4gICAgICAgICAgICBwcmVkaWNhdGUgPSBzb3VyY2Vba2V5XSxcbiAgICAgICAgICAgIHZhbHVlID0gb2JqZWN0W2tleV07XG5cbiAgICAgICAgaWYgKCh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmICEoa2V5IGluIG9iamVjdCkpIHx8ICFwcmVkaWNhdGUodmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5kZWxheWAgYW5kIGBfLmRlZmVyYCB3aGljaCBhY2NlcHRzIGBhcmdzYFxuICAgICAqIHRvIHByb3ZpZGUgdG8gYGZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWxheS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gd2FpdCBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheSBpbnZvY2F0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgVGhlIGFyZ3VtZW50cyB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfE9iamVjdH0gUmV0dXJucyB0aGUgdGltZXIgaWQgb3IgdGltZW91dCBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZURlbGF5KGZ1bmMsIHdhaXQsIGFyZ3MpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyBmdW5jLmFwcGx5KHVuZGVmaW5lZCwgYXJncyk7IH0sIHdhaXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIG1ldGhvZHMgbGlrZSBgXy5kaWZmZXJlbmNlYCB3aXRob3V0IHN1cHBvcnRcbiAgICAgKiBmb3IgZXhjbHVkaW5nIG11bHRpcGxlIGFycmF5cyBvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byBleGNsdWRlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VEaWZmZXJlbmNlKGFycmF5LCB2YWx1ZXMsIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpbmNsdWRlcyA9IGFycmF5SW5jbHVkZXMsXG4gICAgICAgICAgaXNDb21tb24gPSB0cnVlLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBbXSxcbiAgICAgICAgICB2YWx1ZXNMZW5ndGggPSB2YWx1ZXMubGVuZ3RoO1xuXG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgaWYgKGl0ZXJhdGVlKSB7XG4gICAgICAgIHZhbHVlcyA9IGFycmF5TWFwKHZhbHVlcywgYmFzZVVuYXJ5KGl0ZXJhdGVlKSk7XG4gICAgICB9XG4gICAgICBpZiAoY29tcGFyYXRvcikge1xuICAgICAgICBpbmNsdWRlcyA9IGFycmF5SW5jbHVkZXNXaXRoO1xuICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAodmFsdWVzLmxlbmd0aCA+PSBMQVJHRV9BUlJBWV9TSVpFKSB7XG4gICAgICAgIGluY2x1ZGVzID0gY2FjaGVIYXM7XG4gICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIHZhbHVlcyA9IG5ldyBTZXRDYWNoZSh2YWx1ZXMpO1xuICAgICAgfVxuICAgICAgb3V0ZXI6XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlID09IG51bGwgPyB2YWx1ZSA6IGl0ZXJhdGVlKHZhbHVlKTtcblxuICAgICAgICB2YWx1ZSA9IChjb21wYXJhdG9yIHx8IHZhbHVlICE9PSAwKSA/IHZhbHVlIDogMDtcbiAgICAgICAgaWYgKGlzQ29tbW9uICYmIGNvbXB1dGVkID09PSBjb21wdXRlZCkge1xuICAgICAgICAgIHZhciB2YWx1ZXNJbmRleCA9IHZhbHVlc0xlbmd0aDtcbiAgICAgICAgICB3aGlsZSAodmFsdWVzSW5kZXgtLSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlc1t2YWx1ZXNJbmRleF0gPT09IGNvbXB1dGVkKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIG91dGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIWluY2x1ZGVzKHZhbHVlcywgY29tcHV0ZWQsIGNvbXBhcmF0b3IpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZvckVhY2hgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICovXG4gICAgdmFyIGJhc2VFYWNoID0gY3JlYXRlQmFzZUVhY2goYmFzZUZvck93bik7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JFYWNoUmlnaHRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICovXG4gICAgdmFyIGJhc2VFYWNoUmlnaHQgPSBjcmVhdGVCYXNlRWFjaChiYXNlRm9yT3duUmlnaHQsIHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZXZlcnlgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbGwgZWxlbWVudHMgcGFzcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRXZlcnkoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICByZXN1bHQgPSAhIXByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIG1ldGhvZHMgbGlrZSBgXy5tYXhgIGFuZCBgXy5taW5gIHdoaWNoIGFjY2VwdHMgYVxuICAgICAqIGBjb21wYXJhdG9yYCB0byBkZXRlcm1pbmUgdGhlIGV4dHJlbXVtIHZhbHVlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyYXRvciBUaGUgY29tcGFyYXRvciB1c2VkIHRvIGNvbXBhcmUgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBleHRyZW11bSB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRXh0cmVtdW0oYXJyYXksIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGN1cnJlbnQgPSBpdGVyYXRlZSh2YWx1ZSk7XG5cbiAgICAgICAgaWYgKGN1cnJlbnQgIT0gbnVsbCAmJiAoY29tcHV0ZWQgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICA/IChjdXJyZW50ID09PSBjdXJyZW50ICYmICFpc1N5bWJvbChjdXJyZW50KSlcbiAgICAgICAgICAgICAgOiBjb21wYXJhdG9yKGN1cnJlbnQsIGNvbXB1dGVkKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIHZhciBjb21wdXRlZCA9IGN1cnJlbnQsXG4gICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZpbGxgIHdpdGhvdXQgYW4gaXRlcmF0ZWUgY2FsbCBndWFyZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZpbGwuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZmlsbCBgYXJyYXlgIHdpdGguXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtlbmQ9YXJyYXkubGVuZ3RoXSBUaGUgZW5kIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGaWxsKGFycmF5LCB2YWx1ZSwgc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgc3RhcnQgPSB0b0ludGVnZXIoc3RhcnQpO1xuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICBzdGFydCA9IC1zdGFydCA+IGxlbmd0aCA/IDAgOiAobGVuZ3RoICsgc3RhcnQpO1xuICAgICAgfVxuICAgICAgZW5kID0gKGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA+IGxlbmd0aCkgPyBsZW5ndGggOiB0b0ludGVnZXIoZW5kKTtcbiAgICAgIGlmIChlbmQgPCAwKSB7XG4gICAgICAgIGVuZCArPSBsZW5ndGg7XG4gICAgICB9XG4gICAgICBlbmQgPSBzdGFydCA+IGVuZCA/IDAgOiB0b0xlbmd0aChlbmQpO1xuICAgICAgd2hpbGUgKHN0YXJ0IDwgZW5kKSB7XG4gICAgICAgIGFycmF5W3N0YXJ0KytdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmlsdGVyYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRmlsdGVyKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZsYXR0ZW5gIHdpdGggc3VwcG9ydCBmb3IgcmVzdHJpY3RpbmcgZmxhdHRlbmluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGRlcHRoIFRoZSBtYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtwcmVkaWNhdGU9aXNGbGF0dGVuYWJsZV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N0cmljdF0gUmVzdHJpY3QgdG8gdmFsdWVzIHRoYXQgcGFzcyBgcHJlZGljYXRlYCBjaGVja3MuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3Jlc3VsdD1bXV0gVGhlIGluaXRpYWwgcmVzdWx0IHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZsYXR0ZW5lZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRmxhdHRlbihhcnJheSwgZGVwdGgsIHByZWRpY2F0ZSwgaXNTdHJpY3QsIHJlc3VsdCkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICBwcmVkaWNhdGUgfHwgKHByZWRpY2F0ZSA9IGlzRmxhdHRlbmFibGUpO1xuICAgICAgcmVzdWx0IHx8IChyZXN1bHQgPSBbXSk7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgICAgaWYgKGRlcHRoID4gMCAmJiBwcmVkaWNhdGUodmFsdWUpKSB7XG4gICAgICAgICAgaWYgKGRlcHRoID4gMSkge1xuICAgICAgICAgICAgLy8gUmVjdXJzaXZlbHkgZmxhdHRlbiBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgICAgIGJhc2VGbGF0dGVuKHZhbHVlLCBkZXB0aCAtIDEsIHByZWRpY2F0ZSwgaXNTdHJpY3QsIHJlc3VsdCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFycmF5UHVzaChyZXN1bHQsIHZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIWlzU3RyaWN0KSB7XG4gICAgICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGhdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGJhc2VGb3JPd25gIHdoaWNoIGl0ZXJhdGVzIG92ZXIgYG9iamVjdGBcbiAgICAgKiBwcm9wZXJ0aWVzIHJldHVybmVkIGJ5IGBrZXlzRnVuY2AgYW5kIGludm9rZXMgYGl0ZXJhdGVlYCBmb3IgZWFjaCBwcm9wZXJ0eS5cbiAgICAgKiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBrZXlzRnVuYyBUaGUgZnVuY3Rpb24gdG8gZ2V0IHRoZSBrZXlzIG9mIGBvYmplY3RgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgdmFyIGJhc2VGb3IgPSBjcmVhdGVCYXNlRm9yKCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGJhc2VGb3JgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgcHJvcGVydGllc1xuICAgICAqIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGtleXNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIGtleXMgb2YgYG9iamVjdGAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUZvclJpZ2h0ID0gY3JlYXRlQmFzZUZvcih0cnVlKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZvck93bmAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRm9yT3duKG9iamVjdCwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBvYmplY3QgJiYgYmFzZUZvcihvYmplY3QsIGl0ZXJhdGVlLCBrZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JPd25SaWdodGAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRm9yT3duUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBiYXNlRm9yUmlnaHQob2JqZWN0LCBpdGVyYXRlZSwga2V5cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZnVuY3Rpb25zYCB3aGljaCBjcmVhdGVzIGFuIGFycmF5IG9mXG4gICAgICogYG9iamVjdGAgZnVuY3Rpb24gcHJvcGVydHkgbmFtZXMgZmlsdGVyZWQgZnJvbSBgcHJvcHNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgbmFtZXMgdG8gZmlsdGVyLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgZnVuY3Rpb24gbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZ1bmN0aW9ucyhvYmplY3QsIHByb3BzKSB7XG4gICAgICByZXR1cm4gYXJyYXlGaWx0ZXIocHJvcHMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICByZXR1cm4gaXNGdW5jdGlvbihvYmplY3Rba2V5XSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5nZXRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgZGVmYXVsdCB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlR2V0KG9iamVjdCwgcGF0aCkge1xuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG5cbiAgICAgIHZhciBpbmRleCA9IDAsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aC5sZW5ndGg7XG5cbiAgICAgIHdoaWxlIChvYmplY3QgIT0gbnVsbCAmJiBpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBvYmplY3QgPSBvYmplY3RbdG9LZXkocGF0aFtpbmRleCsrXSldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChpbmRleCAmJiBpbmRleCA9PSBsZW5ndGgpID8gb2JqZWN0IDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBnZXRBbGxLZXlzYCBhbmQgYGdldEFsbEtleXNJbmAgd2hpY2ggdXNlc1xuICAgICAqIGBrZXlzRnVuY2AgYW5kIGBzeW1ib2xzRnVuY2AgdG8gZ2V0IHRoZSBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIGFuZFxuICAgICAqIHN5bWJvbHMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBrZXlzRnVuYyBUaGUgZnVuY3Rpb24gdG8gZ2V0IHRoZSBrZXlzIG9mIGBvYmplY3RgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHN5bWJvbHNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIHN5bWJvbHMgb2YgYG9iamVjdGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlR2V0QWxsS2V5cyhvYmplY3QsIGtleXNGdW5jLCBzeW1ib2xzRnVuYykge1xuICAgICAgdmFyIHJlc3VsdCA9IGtleXNGdW5jKG9iamVjdCk7XG4gICAgICByZXR1cm4gaXNBcnJheShvYmplY3QpID8gcmVzdWx0IDogYXJyYXlQdXNoKHJlc3VsdCwgc3ltYm9sc0Z1bmMob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGdldFRhZ2Agd2l0aG91dCBmYWxsYmFja3MgZm9yIGJ1Z2d5IGVudmlyb25tZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgYHRvU3RyaW5nVGFnYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlR2V0VGFnKHZhbHVlKSB7XG4gICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZFRhZyA6IG51bGxUYWc7XG4gICAgICB9XG4gICAgICByZXR1cm4gKHN5bVRvU3RyaW5nVGFnICYmIHN5bVRvU3RyaW5nVGFnIGluIE9iamVjdCh2YWx1ZSkpXG4gICAgICAgID8gZ2V0UmF3VGFnKHZhbHVlKVxuICAgICAgICA6IG9iamVjdFRvU3RyaW5nKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5ndGAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZ3JlYXRlciB0aGFuIGBvdGhlcmAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlR3QodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPiBvdGhlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5oYXNgIHdpdGhvdXQgc3VwcG9ydCBmb3IgZGVlcCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IGtleSBUaGUga2V5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSGFzKG9iamVjdCwga2V5KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICE9IG51bGwgJiYgaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaGFzSW5gIHdpdGhvdXQgc3VwcG9ydCBmb3IgZGVlcCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IGtleSBUaGUga2V5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSGFzSW4ob2JqZWN0LCBrZXkpIHtcbiAgICAgIHJldHVybiBvYmplY3QgIT0gbnVsbCAmJiBrZXkgaW4gT2JqZWN0KG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW5SYW5nZWAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG51bWJlcmAgaXMgaW4gdGhlIHJhbmdlLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUluUmFuZ2UobnVtYmVyLCBzdGFydCwgZW5kKSB7XG4gICAgICByZXR1cm4gbnVtYmVyID49IG5hdGl2ZU1pbihzdGFydCwgZW5kKSAmJiBudW1iZXIgPCBuYXRpdmVNYXgoc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLmludGVyc2VjdGlvbmAsIHdpdGhvdXQgc3VwcG9ydFxuICAgICAqIGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLCB0aGF0IGFjY2VwdHMgYW4gYXJyYXkgb2YgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5cyBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBzaGFyZWQgdmFsdWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJbnRlcnNlY3Rpb24oYXJyYXlzLCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGluY2x1ZGVzID0gY29tcGFyYXRvciA/IGFycmF5SW5jbHVkZXNXaXRoIDogYXJyYXlJbmNsdWRlcyxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheXNbMF0ubGVuZ3RoLFxuICAgICAgICAgIG90aExlbmd0aCA9IGFycmF5cy5sZW5ndGgsXG4gICAgICAgICAgb3RoSW5kZXggPSBvdGhMZW5ndGgsXG4gICAgICAgICAgY2FjaGVzID0gQXJyYXkob3RoTGVuZ3RoKSxcbiAgICAgICAgICBtYXhMZW5ndGggPSBJbmZpbml0eSxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgd2hpbGUgKG90aEluZGV4LS0pIHtcbiAgICAgICAgdmFyIGFycmF5ID0gYXJyYXlzW290aEluZGV4XTtcbiAgICAgICAgaWYgKG90aEluZGV4ICYmIGl0ZXJhdGVlKSB7XG4gICAgICAgICAgYXJyYXkgPSBhcnJheU1hcChhcnJheSwgYmFzZVVuYXJ5KGl0ZXJhdGVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgbWF4TGVuZ3RoID0gbmF0aXZlTWluKGFycmF5Lmxlbmd0aCwgbWF4TGVuZ3RoKTtcbiAgICAgICAgY2FjaGVzW290aEluZGV4XSA9ICFjb21wYXJhdG9yICYmIChpdGVyYXRlZSB8fCAobGVuZ3RoID49IDEyMCAmJiBhcnJheS5sZW5ndGggPj0gMTIwKSlcbiAgICAgICAgICA/IG5ldyBTZXRDYWNoZShvdGhJbmRleCAmJiBhcnJheSlcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGFycmF5ID0gYXJyYXlzWzBdO1xuXG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBzZWVuID0gY2FjaGVzWzBdO1xuXG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoICYmIHJlc3VsdC5sZW5ndGggPCBtYXhMZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlO1xuXG4gICAgICAgIHZhbHVlID0gKGNvbXBhcmF0b3IgfHwgdmFsdWUgIT09IDApID8gdmFsdWUgOiAwO1xuICAgICAgICBpZiAoIShzZWVuXG4gICAgICAgICAgICAgID8gY2FjaGVIYXMoc2VlbiwgY29tcHV0ZWQpXG4gICAgICAgICAgICAgIDogaW5jbHVkZXMocmVzdWx0LCBjb21wdXRlZCwgY29tcGFyYXRvcilcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICBvdGhJbmRleCA9IG90aExlbmd0aDtcbiAgICAgICAgICB3aGlsZSAoLS1vdGhJbmRleCkge1xuICAgICAgICAgICAgdmFyIGNhY2hlID0gY2FjaGVzW290aEluZGV4XTtcbiAgICAgICAgICAgIGlmICghKGNhY2hlXG4gICAgICAgICAgICAgICAgICA/IGNhY2hlSGFzKGNhY2hlLCBjb21wdXRlZClcbiAgICAgICAgICAgICAgICAgIDogaW5jbHVkZXMoYXJyYXlzW290aEluZGV4XSwgY29tcHV0ZWQsIGNvbXBhcmF0b3IpKVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHNlZW4pIHtcbiAgICAgICAgICAgIHNlZW4ucHVzaChjb21wdXRlZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pbnZlcnRgIGFuZCBgXy5pbnZlcnRCeWAgd2hpY2ggaW52ZXJ0c1xuICAgICAqIGBvYmplY3RgIHdpdGggdmFsdWVzIHRyYW5zZm9ybWVkIGJ5IGBpdGVyYXRlZWAgYW5kIHNldCBieSBgc2V0dGVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIGZ1bmN0aW9uIHRvIHNldCBgYWNjdW11bGF0b3JgIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgaXRlcmF0ZWUgdG8gdHJhbnNmb3JtIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gYWNjdW11bGF0b3IgVGhlIGluaXRpYWwgaW52ZXJ0ZWQgb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgYWNjdW11bGF0b3JgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJbnZlcnRlcihvYmplY3QsIHNldHRlciwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yKSB7XG4gICAgICBiYXNlRm9yT3duKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGtleSwgb2JqZWN0KSB7XG4gICAgICAgIHNldHRlcihhY2N1bXVsYXRvciwgaXRlcmF0ZWUodmFsdWUpLCBrZXksIG9iamVjdCk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pbnZva2VgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbFxuICAgICAqIG1ldGhvZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcmdzIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIHRoZSBtZXRob2Qgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSBpbnZva2VkIG1ldGhvZC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSW52b2tlKG9iamVjdCwgcGF0aCwgYXJncykge1xuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG4gICAgICBvYmplY3QgPSBwYXJlbnQob2JqZWN0LCBwYXRoKTtcbiAgICAgIHZhciBmdW5jID0gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBvYmplY3RbdG9LZXkobGFzdChwYXRoKSldO1xuICAgICAgcmV0dXJuIGZ1bmMgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IGFwcGx5KGZ1bmMsIG9iamVjdCwgYXJncyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNBcmd1bWVudHNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBgYXJndW1lbnRzYCBvYmplY3QsXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzQXJndW1lbnRzKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSBhcmdzVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzQXJyYXlCdWZmZXJgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBhcnJheSBidWZmZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNBcnJheUJ1ZmZlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gYXJyYXlCdWZmZXJUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNEYXRlYCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBkYXRlIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc0RhdGUodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IGRhdGVUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNFcXVhbGAgd2hpY2ggc3VwcG9ydHMgcGFydGlhbCBjb21wYXJpc29uc1xuICAgICAqIGFuZCB0cmFja3MgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuXG4gICAgICogIDEgLSBVbm9yZGVyZWQgY29tcGFyaXNvblxuICAgICAqICAyIC0gUGFydGlhbCBjb21wYXJpc29uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBgdmFsdWVgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNFcXVhbCh2YWx1ZSwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKSB7XG4gICAgICBpZiAodmFsdWUgPT09IG90aGVyKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlID09IG51bGwgfHwgb3RoZXIgPT0gbnVsbCB8fCAoIWlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgIWlzT2JqZWN0TGlrZShvdGhlcikpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSAhPT0gdmFsdWUgJiYgb3RoZXIgIT09IG90aGVyO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VJc0VxdWFsRGVlcCh2YWx1ZSwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGJhc2VJc0VxdWFsLCBzdGFjayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbGAgZm9yIGFycmF5cyBhbmQgb2JqZWN0cyB3aGljaCBwZXJmb3Jtc1xuICAgICAqIGRlZXAgY29tcGFyaXNvbnMgYW5kIHRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBlbmFibGluZyBvYmplY3RzIHdpdGggY2lyY3VsYXJcbiAgICAgKiByZWZlcmVuY2VzIHRvIGJlIGNvbXBhcmVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBgb2JqZWN0YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc0VxdWFsRGVlcChvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKSB7XG4gICAgICB2YXIgb2JqSXNBcnIgPSBpc0FycmF5KG9iamVjdCksXG4gICAgICAgICAgb3RoSXNBcnIgPSBpc0FycmF5KG90aGVyKSxcbiAgICAgICAgICBvYmpUYWcgPSBvYmpJc0FyciA/IGFycmF5VGFnIDogZ2V0VGFnKG9iamVjdCksXG4gICAgICAgICAgb3RoVGFnID0gb3RoSXNBcnIgPyBhcnJheVRhZyA6IGdldFRhZyhvdGhlcik7XG5cbiAgICAgIG9ialRhZyA9IG9ialRhZyA9PSBhcmdzVGFnID8gb2JqZWN0VGFnIDogb2JqVGFnO1xuICAgICAgb3RoVGFnID0gb3RoVGFnID09IGFyZ3NUYWcgPyBvYmplY3RUYWcgOiBvdGhUYWc7XG5cbiAgICAgIHZhciBvYmpJc09iaiA9IG9ialRhZyA9PSBvYmplY3RUYWcsXG4gICAgICAgICAgb3RoSXNPYmogPSBvdGhUYWcgPT0gb2JqZWN0VGFnLFxuICAgICAgICAgIGlzU2FtZVRhZyA9IG9ialRhZyA9PSBvdGhUYWc7XG5cbiAgICAgIGlmIChpc1NhbWVUYWcgJiYgaXNCdWZmZXIob2JqZWN0KSkge1xuICAgICAgICBpZiAoIWlzQnVmZmVyKG90aGVyKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBvYmpJc0FyciA9IHRydWU7XG4gICAgICAgIG9iaklzT2JqID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoaXNTYW1lVGFnICYmICFvYmpJc09iaikge1xuICAgICAgICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICAgICAgICByZXR1cm4gKG9iaklzQXJyIHx8IGlzVHlwZWRBcnJheShvYmplY3QpKVxuICAgICAgICAgID8gZXF1YWxBcnJheXMob2JqZWN0LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaylcbiAgICAgICAgICA6IGVxdWFsQnlUYWcob2JqZWN0LCBvdGhlciwgb2JqVGFnLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKTtcbiAgICAgIH1cbiAgICAgIGlmICghKGJpdG1hc2sgJiBDT01QQVJFX1BBUlRJQUxfRkxBRykpIHtcbiAgICAgICAgdmFyIG9iaklzV3JhcHBlZCA9IG9iaklzT2JqICYmIGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCAnX193cmFwcGVkX18nKSxcbiAgICAgICAgICAgIG90aElzV3JhcHBlZCA9IG90aElzT2JqICYmIGhhc093blByb3BlcnR5LmNhbGwob3RoZXIsICdfX3dyYXBwZWRfXycpO1xuXG4gICAgICAgIGlmIChvYmpJc1dyYXBwZWQgfHwgb3RoSXNXcmFwcGVkKSB7XG4gICAgICAgICAgdmFyIG9ialVud3JhcHBlZCA9IG9iaklzV3JhcHBlZCA/IG9iamVjdC52YWx1ZSgpIDogb2JqZWN0LFxuICAgICAgICAgICAgICBvdGhVbndyYXBwZWQgPSBvdGhJc1dyYXBwZWQgPyBvdGhlci52YWx1ZSgpIDogb3RoZXI7XG5cbiAgICAgICAgICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICAgICAgICAgIHJldHVybiBlcXVhbEZ1bmMob2JqVW53cmFwcGVkLCBvdGhVbndyYXBwZWQsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFpc1NhbWVUYWcpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgICAgIHJldHVybiBlcXVhbE9iamVjdHMob2JqZWN0LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNNYXBgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG1hcCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc01hcCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgZ2V0VGFnKHZhbHVlKSA9PSBtYXBUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNNYXRjaGAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IG1hdGNoRGF0YSBUaGUgcHJvcGVydHkgbmFtZXMsIHZhbHVlcywgYW5kIGNvbXBhcmUgZmxhZ3MgdG8gbWF0Y2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBvYmplY3RgIGlzIGEgbWF0Y2gsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNNYXRjaChvYmplY3QsIHNvdXJjZSwgbWF0Y2hEYXRhLCBjdXN0b21pemVyKSB7XG4gICAgICB2YXIgaW5kZXggPSBtYXRjaERhdGEubGVuZ3RoLFxuICAgICAgICAgIGxlbmd0aCA9IGluZGV4LFxuICAgICAgICAgIG5vQ3VzdG9taXplciA9ICFjdXN0b21pemVyO1xuXG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuICFsZW5ndGg7XG4gICAgICB9XG4gICAgICBvYmplY3QgPSBPYmplY3Qob2JqZWN0KTtcbiAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgIHZhciBkYXRhID0gbWF0Y2hEYXRhW2luZGV4XTtcbiAgICAgICAgaWYgKChub0N1c3RvbWl6ZXIgJiYgZGF0YVsyXSlcbiAgICAgICAgICAgICAgPyBkYXRhWzFdICE9PSBvYmplY3RbZGF0YVswXV1cbiAgICAgICAgICAgICAgOiAhKGRhdGFbMF0gaW4gb2JqZWN0KVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBkYXRhID0gbWF0Y2hEYXRhW2luZGV4XTtcbiAgICAgICAgdmFyIGtleSA9IGRhdGFbMF0sXG4gICAgICAgICAgICBvYmpWYWx1ZSA9IG9iamVjdFtrZXldLFxuICAgICAgICAgICAgc3JjVmFsdWUgPSBkYXRhWzFdO1xuXG4gICAgICAgIGlmIChub0N1c3RvbWl6ZXIgJiYgZGF0YVsyXSkge1xuICAgICAgICAgIGlmIChvYmpWYWx1ZSA9PT0gdW5kZWZpbmVkICYmICEoa2V5IGluIG9iamVjdCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHN0YWNrID0gbmV3IFN0YWNrO1xuICAgICAgICAgIGlmIChjdXN0b21pemVyKSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCEocmVzdWx0ID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICA/IGJhc2VJc0VxdWFsKHNyY1ZhbHVlLCBvYmpWYWx1ZSwgQ09NUEFSRV9QQVJUSUFMX0ZMQUcgfCBDT01QQVJFX1VOT1JERVJFRF9GTEFHLCBjdXN0b21pemVyLCBzdGFjaylcbiAgICAgICAgICAgICAgICA6IHJlc3VsdFxuICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc05hdGl2ZWAgd2l0aG91dCBiYWQgc2hpbSBjaGVja3MuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbmF0aXZlIGZ1bmN0aW9uLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzTmF0aXZlKHZhbHVlKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KHZhbHVlKSB8fCBpc01hc2tlZCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIHBhdHRlcm4gPSBpc0Z1bmN0aW9uKHZhbHVlKSA/IHJlSXNOYXRpdmUgOiByZUlzSG9zdEN0b3I7XG4gICAgICByZXR1cm4gcGF0dGVybi50ZXN0KHRvU291cmNlKHZhbHVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNSZWdFeHBgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHJlZ2V4cCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc1JlZ0V4cCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gcmVnZXhwVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzU2V0YCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzZXQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNTZXQodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGdldFRhZyh2YWx1ZSkgPT0gc2V0VGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzVHlwZWRBcnJheWAgd2l0aG91dCBOb2RlLmpzIG9wdGltaXphdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdHlwZWQgYXJyYXksIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNUeXBlZEFycmF5KHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJlxuICAgICAgICBpc0xlbmd0aCh2YWx1ZS5sZW5ndGgpICYmICEhdHlwZWRBcnJheVRhZ3NbYmFzZUdldFRhZyh2YWx1ZSldO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLml0ZXJhdGVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSBbdmFsdWU9Xy5pZGVudGl0eV0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgdG8gYW4gaXRlcmF0ZWUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBpdGVyYXRlZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXRlcmF0ZWUodmFsdWUpIHtcbiAgICAgIC8vIERvbid0IHN0b3JlIHRoZSBgdHlwZW9mYCByZXN1bHQgaW4gYSB2YXJpYWJsZSB0byBhdm9pZCBhIEpJVCBidWcgaW4gU2FmYXJpIDkuXG4gICAgICAvLyBTZWUgaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTE1NjAzNCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBpZGVudGl0eTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodmFsdWUpXG4gICAgICAgICAgPyBiYXNlTWF0Y2hlc1Byb3BlcnR5KHZhbHVlWzBdLCB2YWx1ZVsxXSlcbiAgICAgICAgICA6IGJhc2VNYXRjaGVzKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwcm9wZXJ0eSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ua2V5c2Agd2hpY2ggZG9lc24ndCB0cmVhdCBzcGFyc2UgYXJyYXlzIGFzIGRlbnNlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlS2V5cyhvYmplY3QpIHtcbiAgICAgIGlmICghaXNQcm90b3R5cGUob2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gbmF0aXZlS2V5cyhvYmplY3QpO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgZm9yICh2YXIga2V5IGluIE9iamVjdChvYmplY3QpKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSAmJiBrZXkgIT0gJ2NvbnN0cnVjdG9yJykge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ua2V5c0luYCB3aGljaCBkb2Vzbid0IHRyZWF0IHNwYXJzZSBhcnJheXMgYXMgZGVuc2UuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VLZXlzSW4ob2JqZWN0KSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZUtleXNJbihvYmplY3QpO1xuICAgICAgfVxuICAgICAgdmFyIGlzUHJvdG8gPSBpc1Byb3RvdHlwZShvYmplY3QpLFxuICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICAgIGlmICghKGtleSA9PSAnY29uc3RydWN0b3InICYmIChpc1Byb3RvIHx8ICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5sdGAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIGBvdGhlcmAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTHQodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPCBvdGhlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tYXBgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pID8gQXJyYXkoY29sbGVjdGlvbi5sZW5ndGgpIDogW107XG5cbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmVzdWx0WysraW5kZXhdID0gaXRlcmF0ZWUodmFsdWUsIGtleSwgY29sbGVjdGlvbik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWF0Y2hlc2Agd2hpY2ggZG9lc24ndCBjbG9uZSBgc291cmNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHZhbHVlcyB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBzcGVjIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNYXRjaGVzKHNvdXJjZSkge1xuICAgICAgdmFyIG1hdGNoRGF0YSA9IGdldE1hdGNoRGF0YShzb3VyY2UpO1xuICAgICAgaWYgKG1hdGNoRGF0YS5sZW5ndGggPT0gMSAmJiBtYXRjaERhdGFbMF1bMl0pIHtcbiAgICAgICAgcmV0dXJuIG1hdGNoZXNTdHJpY3RDb21wYXJhYmxlKG1hdGNoRGF0YVswXVswXSwgbWF0Y2hEYXRhWzBdWzFdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA9PT0gc291cmNlIHx8IGJhc2VJc01hdGNoKG9iamVjdCwgc291cmNlLCBtYXRjaERhdGEpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tYXRjaGVzUHJvcGVydHlgIHdoaWNoIGRvZXNuJ3QgY2xvbmUgYHNyY1ZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IHNyY1ZhbHVlIFRoZSB2YWx1ZSB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBzcGVjIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNYXRjaGVzUHJvcGVydHkocGF0aCwgc3JjVmFsdWUpIHtcbiAgICAgIGlmIChpc0tleShwYXRoKSAmJiBpc1N0cmljdENvbXBhcmFibGUoc3JjVmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBtYXRjaGVzU3RyaWN0Q29tcGFyYWJsZSh0b0tleShwYXRoKSwgc3JjVmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICB2YXIgb2JqVmFsdWUgPSBnZXQob2JqZWN0LCBwYXRoKTtcbiAgICAgICAgcmV0dXJuIChvYmpWYWx1ZSA9PT0gdW5kZWZpbmVkICYmIG9ialZhbHVlID09PSBzcmNWYWx1ZSlcbiAgICAgICAgICA/IGhhc0luKG9iamVjdCwgcGF0aClcbiAgICAgICAgICA6IGJhc2VJc0VxdWFsKHNyY1ZhbHVlLCBvYmpWYWx1ZSwgQ09NUEFSRV9QQVJUSUFMX0ZMQUcgfCBDT01QQVJFX1VOT1JERVJFRF9GTEFHKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWVyZ2VgIHdpdGhvdXQgc3VwcG9ydCBmb3IgbXVsdGlwbGUgc291cmNlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNyY0luZGV4IFRoZSBpbmRleCBvZiBgc291cmNlYC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBtZXJnZWQgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIHZhbHVlcyBhbmQgdGhlaXIgbWVyZ2VkXG4gICAgICogIGNvdW50ZXJwYXJ0cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWVyZ2Uob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyLCBzdGFjaykge1xuICAgICAgaWYgKG9iamVjdCA9PT0gc291cmNlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGJhc2VGb3Ioc291cmNlLCBmdW5jdGlvbihzcmNWYWx1ZSwga2V5KSB7XG4gICAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICAgIGlmIChpc09iamVjdChzcmNWYWx1ZSkpIHtcbiAgICAgICAgICBiYXNlTWVyZ2VEZWVwKG9iamVjdCwgc291cmNlLCBrZXksIHNyY0luZGV4LCBiYXNlTWVyZ2UsIGN1c3RvbWl6ZXIsIHN0YWNrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICB2YXIgbmV3VmFsdWUgPSBjdXN0b21pemVyXG4gICAgICAgICAgICA/IGN1c3RvbWl6ZXIoc2FmZUdldChvYmplY3QsIGtleSksIHNyY1ZhbHVlLCAoa2V5ICsgJycpLCBvYmplY3QsIHNvdXJjZSwgc3RhY2spXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IHNyY1ZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhc3NpZ25NZXJnZVZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0sIGtleXNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlTWVyZ2VgIGZvciBhcnJheXMgYW5kIG9iamVjdHMgd2hpY2ggcGVyZm9ybXNcbiAgICAgKiBkZWVwIG1lcmdlcyBhbmQgdHJhY2tzIHRyYXZlcnNlZCBvYmplY3RzIGVuYWJsaW5nIG9iamVjdHMgd2l0aCBjaXJjdWxhclxuICAgICAqIHJlZmVyZW5jZXMgdG8gYmUgbWVyZ2VkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIG1lcmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzcmNJbmRleCBUaGUgaW5kZXggb2YgYHNvdXJjZWAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbWVyZ2VGdW5jIFRoZSBmdW5jdGlvbiB0byBtZXJnZSB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIHZhbHVlcyBhbmQgdGhlaXIgbWVyZ2VkXG4gICAgICogIGNvdW50ZXJwYXJ0cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWVyZ2VEZWVwKG9iamVjdCwgc291cmNlLCBrZXksIHNyY0luZGV4LCBtZXJnZUZ1bmMsIGN1c3RvbWl6ZXIsIHN0YWNrKSB7XG4gICAgICB2YXIgb2JqVmFsdWUgPSBzYWZlR2V0KG9iamVjdCwga2V5KSxcbiAgICAgICAgICBzcmNWYWx1ZSA9IHNhZmVHZXQoc291cmNlLCBrZXkpLFxuICAgICAgICAgIHN0YWNrZWQgPSBzdGFjay5nZXQoc3JjVmFsdWUpO1xuXG4gICAgICBpZiAoc3RhY2tlZCkge1xuICAgICAgICBhc3NpZ25NZXJnZVZhbHVlKG9iamVjdCwga2V5LCBzdGFja2VkKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdmFyIG5ld1ZhbHVlID0gY3VzdG9taXplclxuICAgICAgICA/IGN1c3RvbWl6ZXIob2JqVmFsdWUsIHNyY1ZhbHVlLCAoa2V5ICsgJycpLCBvYmplY3QsIHNvdXJjZSwgc3RhY2spXG4gICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgICB2YXIgaXNDb21tb24gPSBuZXdWYWx1ZSA9PT0gdW5kZWZpbmVkO1xuXG4gICAgICBpZiAoaXNDb21tb24pIHtcbiAgICAgICAgdmFyIGlzQXJyID0gaXNBcnJheShzcmNWYWx1ZSksXG4gICAgICAgICAgICBpc0J1ZmYgPSAhaXNBcnIgJiYgaXNCdWZmZXIoc3JjVmFsdWUpLFxuICAgICAgICAgICAgaXNUeXBlZCA9ICFpc0FyciAmJiAhaXNCdWZmICYmIGlzVHlwZWRBcnJheShzcmNWYWx1ZSk7XG5cbiAgICAgICAgbmV3VmFsdWUgPSBzcmNWYWx1ZTtcbiAgICAgICAgaWYgKGlzQXJyIHx8IGlzQnVmZiB8fCBpc1R5cGVkKSB7XG4gICAgICAgICAgaWYgKGlzQXJyYXkob2JqVmFsdWUpKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IG9ialZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChpc0FycmF5TGlrZU9iamVjdChvYmpWYWx1ZSkpIHtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gY29weUFycmF5KG9ialZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoaXNCdWZmKSB7XG4gICAgICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBjbG9uZUJ1ZmZlcihzcmNWYWx1ZSwgdHJ1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKGlzVHlwZWQpIHtcbiAgICAgICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGNsb25lVHlwZWRBcnJheShzcmNWYWx1ZSwgdHJ1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBbXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNQbGFpbk9iamVjdChzcmNWYWx1ZSkgfHwgaXNBcmd1bWVudHMoc3JjVmFsdWUpKSB7XG4gICAgICAgICAgbmV3VmFsdWUgPSBvYmpWYWx1ZTtcbiAgICAgICAgICBpZiAoaXNBcmd1bWVudHMob2JqVmFsdWUpKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IHRvUGxhaW5PYmplY3Qob2JqVmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmICghaXNPYmplY3Qob2JqVmFsdWUpIHx8IGlzRnVuY3Rpb24ob2JqVmFsdWUpKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGluaXRDbG9uZU9iamVjdChzcmNWYWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChpc0NvbW1vbikge1xuICAgICAgICAvLyBSZWN1cnNpdmVseSBtZXJnZSBvYmplY3RzIGFuZCBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgc3RhY2suc2V0KHNyY1ZhbHVlLCBuZXdWYWx1ZSk7XG4gICAgICAgIG1lcmdlRnVuYyhuZXdWYWx1ZSwgc3JjVmFsdWUsIHNyY0luZGV4LCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgICAgIHN0YWNrWydkZWxldGUnXShzcmNWYWx1ZSk7XG4gICAgICB9XG4gICAgICBhc3NpZ25NZXJnZVZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubnRoYCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBudGggZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VOdGgoYXJyYXksIG4pIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBuICs9IG4gPCAwID8gbGVuZ3RoIDogMDtcbiAgICAgIHJldHVybiBpc0luZGV4KG4sIGxlbmd0aCkgPyBhcnJheVtuXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5vcmRlckJ5YCB3aXRob3V0IHBhcmFtIGd1YXJkcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXXxPYmplY3RbXXxzdHJpbmdbXX0gaXRlcmF0ZWVzIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBvcmRlcnMgVGhlIHNvcnQgb3JkZXJzIG9mIGBpdGVyYXRlZXNgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNvcnRlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlT3JkZXJCeShjb2xsZWN0aW9uLCBpdGVyYXRlZXMsIG9yZGVycykge1xuICAgICAgaWYgKGl0ZXJhdGVlcy5sZW5ndGgpIHtcbiAgICAgICAgaXRlcmF0ZWVzID0gYXJyYXlNYXAoaXRlcmF0ZWVzLCBmdW5jdGlvbihpdGVyYXRlZSkge1xuICAgICAgICAgIGlmIChpc0FycmF5KGl0ZXJhdGVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICAgIHJldHVybiBiYXNlR2V0KHZhbHVlLCBpdGVyYXRlZS5sZW5ndGggPT09IDEgPyBpdGVyYXRlZVswXSA6IGl0ZXJhdGVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGl0ZXJhdGVlO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGl0ZXJhdGVlcyA9IFtpZGVudGl0eV07XG4gICAgICB9XG5cbiAgICAgIHZhciBpbmRleCA9IC0xO1xuICAgICAgaXRlcmF0ZWVzID0gYXJyYXlNYXAoaXRlcmF0ZWVzLCBiYXNlVW5hcnkoZ2V0SXRlcmF0ZWUoKSkpO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gYmFzZU1hcChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHZhciBjcml0ZXJpYSA9IGFycmF5TWFwKGl0ZXJhdGVlcywgZnVuY3Rpb24oaXRlcmF0ZWUpIHtcbiAgICAgICAgICByZXR1cm4gaXRlcmF0ZWUodmFsdWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgJ2NyaXRlcmlhJzogY3JpdGVyaWEsICdpbmRleCc6ICsraW5kZXgsICd2YWx1ZSc6IHZhbHVlIH07XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGJhc2VTb3J0QnkocmVzdWx0LCBmdW5jdGlvbihvYmplY3QsIG90aGVyKSB7XG4gICAgICAgIHJldHVybiBjb21wYXJlTXVsdGlwbGUob2JqZWN0LCBvdGhlciwgb3JkZXJzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnBpY2tgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbFxuICAgICAqIHByb3BlcnR5IGlkZW50aWZpZXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGhzIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBwaWNrLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVBpY2sob2JqZWN0LCBwYXRocykge1xuICAgICAgcmV0dXJuIGJhc2VQaWNrQnkob2JqZWN0LCBwYXRocywgZnVuY3Rpb24odmFsdWUsIHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIGhhc0luKG9iamVjdCwgcGF0aCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiAgYF8ucGlja0J5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aHMgVGhlIHByb3BlcnR5IHBhdGhzIHRvIHBpY2suXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQaWNrQnkob2JqZWN0LCBwYXRocywgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBwYXRocy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBwYXRoID0gcGF0aHNbaW5kZXhdLFxuICAgICAgICAgICAgdmFsdWUgPSBiYXNlR2V0KG9iamVjdCwgcGF0aCk7XG5cbiAgICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgcGF0aCkpIHtcbiAgICAgICAgICBiYXNlU2V0KHJlc3VsdCwgY2FzdFBhdGgocGF0aCwgb2JqZWN0KSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZVByb3BlcnR5YCB3aGljaCBzdXBwb3J0cyBkZWVwIHBhdGhzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFjY2Vzc29yIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQcm9wZXJ0eURlZXAocGF0aCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICByZXR1cm4gYmFzZUdldChvYmplY3QsIHBhdGgpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wdWxsQWxsQnlgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWVcbiAgICAgKiBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIHJlbW92ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQdWxsQWxsKGFycmF5LCB2YWx1ZXMsIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgaW5kZXhPZiA9IGNvbXBhcmF0b3IgPyBiYXNlSW5kZXhPZldpdGggOiBiYXNlSW5kZXhPZixcbiAgICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgc2VlbiA9IGFycmF5O1xuXG4gICAgICBpZiAoYXJyYXkgPT09IHZhbHVlcykge1xuICAgICAgICB2YWx1ZXMgPSBjb3B5QXJyYXkodmFsdWVzKTtcbiAgICAgIH1cbiAgICAgIGlmIChpdGVyYXRlZSkge1xuICAgICAgICBzZWVuID0gYXJyYXlNYXAoYXJyYXksIGJhc2VVbmFyeShpdGVyYXRlZSkpO1xuICAgICAgfVxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGZyb21JbmRleCA9IDAsXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlc1tpbmRleF0sXG4gICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlID8gaXRlcmF0ZWUodmFsdWUpIDogdmFsdWU7XG5cbiAgICAgICAgd2hpbGUgKChmcm9tSW5kZXggPSBpbmRleE9mKHNlZW4sIGNvbXB1dGVkLCBmcm9tSW5kZXgsIGNvbXBhcmF0b3IpKSA+IC0xKSB7XG4gICAgICAgICAgaWYgKHNlZW4gIT09IGFycmF5KSB7XG4gICAgICAgICAgICBzcGxpY2UuY2FsbChzZWVuLCBmcm9tSW5kZXgsIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzcGxpY2UuY2FsbChhcnJheSwgZnJvbUluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnB1bGxBdGAgd2l0aG91dCBzdXBwb3J0IGZvciBpbmRpdmlkdWFsXG4gICAgICogaW5kZXhlcyBvciBjYXB0dXJpbmcgdGhlIHJlbW92ZWQgZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJbXX0gaW5kZXhlcyBUaGUgaW5kZXhlcyBvZiBlbGVtZW50cyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVB1bGxBdChhcnJheSwgaW5kZXhlcykge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gaW5kZXhlcy5sZW5ndGggOiAwLFxuICAgICAgICAgIGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIgaW5kZXggPSBpbmRleGVzW2xlbmd0aF07XG4gICAgICAgIGlmIChsZW5ndGggPT0gbGFzdEluZGV4IHx8IGluZGV4ICE9PSBwcmV2aW91cykge1xuICAgICAgICAgIHZhciBwcmV2aW91cyA9IGluZGV4O1xuICAgICAgICAgIGlmIChpc0luZGV4KGluZGV4KSkge1xuICAgICAgICAgICAgc3BsaWNlLmNhbGwoYXJyYXksIGluZGV4LCAxKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYmFzZVVuc2V0KGFycmF5LCBpbmRleCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucmFuZG9tYCB3aXRob3V0IHN1cHBvcnQgZm9yIHJldHVybmluZ1xuICAgICAqIGZsb2F0aW5nLXBvaW50IG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBsb3dlciBUaGUgbG93ZXIgYm91bmQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHVwcGVyIFRoZSB1cHBlciBib3VuZC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByYW5kb20gbnVtYmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSYW5kb20obG93ZXIsIHVwcGVyKSB7XG4gICAgICByZXR1cm4gbG93ZXIgKyBuYXRpdmVGbG9vcihuYXRpdmVSYW5kb20oKSAqICh1cHBlciAtIGxvd2VyICsgMSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJhbmdlYCBhbmQgYF8ucmFuZ2VSaWdodGAgd2hpY2ggZG9lc24ndFxuICAgICAqIGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN0ZXAgVGhlIHZhbHVlIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgYnkuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSByYW5nZSBvZiBudW1iZXJzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSYW5nZShzdGFydCwgZW5kLCBzdGVwLCBmcm9tUmlnaHQpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChuYXRpdmVDZWlsKChlbmQgLSBzdGFydCkgLyAoc3RlcCB8fCAxKSksIDApLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICByZXN1bHRbZnJvbVJpZ2h0ID8gbGVuZ3RoIDogKytpbmRleF0gPSBzdGFydDtcbiAgICAgICAgc3RhcnQgKz0gc3RlcDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucmVwZWF0YCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byByZXBlYXQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciBvZiB0aW1lcyB0byByZXBlYXQgdGhlIHN0cmluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSByZXBlYXRlZCBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVJlcGVhdChzdHJpbmcsIG4pIHtcbiAgICAgIHZhciByZXN1bHQgPSAnJztcbiAgICAgIGlmICghc3RyaW5nIHx8IG4gPCAxIHx8IG4gPiBNQVhfU0FGRV9JTlRFR0VSKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICAvLyBMZXZlcmFnZSB0aGUgZXhwb25lbnRpYXRpb24gYnkgc3F1YXJpbmcgYWxnb3JpdGhtIGZvciBhIGZhc3RlciByZXBlYXQuXG4gICAgICAvLyBTZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRXhwb25lbnRpYXRpb25fYnlfc3F1YXJpbmcgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgIGRvIHtcbiAgICAgICAgaWYgKG4gJSAyKSB7XG4gICAgICAgICAgcmVzdWx0ICs9IHN0cmluZztcbiAgICAgICAgfVxuICAgICAgICBuID0gbmF0aXZlRmxvb3IobiAvIDIpO1xuICAgICAgICBpZiAobikge1xuICAgICAgICAgIHN0cmluZyArPSBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgIH0gd2hpbGUgKG4pO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJlc3RgIHdoaWNoIGRvZXNuJ3QgdmFsaWRhdGUgb3IgY29lcmNlIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXBwbHkgYSByZXN0IHBhcmFtZXRlciB0by5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PWZ1bmMubGVuZ3RoLTFdIFRoZSBzdGFydCBwb3NpdGlvbiBvZiB0aGUgcmVzdCBwYXJhbWV0ZXIuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVJlc3QoZnVuYywgc3RhcnQpIHtcbiAgICAgIHJldHVybiBzZXRUb1N0cmluZyhvdmVyUmVzdChmdW5jLCBzdGFydCwgaWRlbnRpdHkpLCBmdW5jICsgJycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNhbXBsZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmFuZG9tIGVsZW1lbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNhbXBsZShjb2xsZWN0aW9uKSB7XG4gICAgICByZXR1cm4gYXJyYXlTYW1wbGUodmFsdWVzKGNvbGxlY3Rpb24pKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zYW1wbGVTaXplYCB3aXRob3V0IHBhcmFtIGd1YXJkcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2FtcGxlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gc2FtcGxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZG9tIGVsZW1lbnRzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTYW1wbGVTaXplKGNvbGxlY3Rpb24sIG4pIHtcbiAgICAgIHZhciBhcnJheSA9IHZhbHVlcyhjb2xsZWN0aW9uKTtcbiAgICAgIHJldHVybiBzaHVmZmxlU2VsZihhcnJheSwgYmFzZUNsYW1wKG4sIDAsIGFycmF5Lmxlbmd0aCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNldGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgcGF0aCBjcmVhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTZXQob2JqZWN0LCBwYXRoLCB2YWx1ZSwgY3VzdG9taXplcikge1xuICAgICAgaWYgKCFpc09iamVjdChvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICB9XG4gICAgICBwYXRoID0gY2FzdFBhdGgocGF0aCwgb2JqZWN0KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aC5sZW5ndGgsXG4gICAgICAgICAgbGFzdEluZGV4ID0gbGVuZ3RoIC0gMSxcbiAgICAgICAgICBuZXN0ZWQgPSBvYmplY3Q7XG5cbiAgICAgIHdoaWxlIChuZXN0ZWQgIT0gbnVsbCAmJiArK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSB0b0tleShwYXRoW2luZGV4XSksXG4gICAgICAgICAgICBuZXdWYWx1ZSA9IHZhbHVlO1xuXG4gICAgICAgIGlmIChrZXkgPT09ICdfX3Byb3RvX18nIHx8IGtleSA9PT0gJ2NvbnN0cnVjdG9yJyB8fCBrZXkgPT09ICdwcm90b3R5cGUnKSB7XG4gICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbmRleCAhPSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICB2YXIgb2JqVmFsdWUgPSBuZXN0ZWRba2V5XTtcbiAgICAgICAgICBuZXdWYWx1ZSA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKG9ialZhbHVlLCBrZXksIG5lc3RlZCkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgaWYgKG5ld1ZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gaXNPYmplY3Qob2JqVmFsdWUpXG4gICAgICAgICAgICAgID8gb2JqVmFsdWVcbiAgICAgICAgICAgICAgOiAoaXNJbmRleChwYXRoW2luZGV4ICsgMV0pID8gW10gOiB7fSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFzc2lnblZhbHVlKG5lc3RlZCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgICAgIG5lc3RlZCA9IG5lc3RlZFtrZXldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgc2V0RGF0YWAgd2l0aG91dCBzdXBwb3J0IGZvciBob3QgbG9vcCBzaG9ydGluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXNzb2NpYXRlIG1ldGFkYXRhIHdpdGguXG4gICAgICogQHBhcmFtIHsqfSBkYXRhIFRoZSBtZXRhZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBiYXNlU2V0RGF0YSA9ICFtZXRhTWFwID8gaWRlbnRpdHkgOiBmdW5jdGlvbihmdW5jLCBkYXRhKSB7XG4gICAgICBtZXRhTWFwLnNldChmdW5jLCBkYXRhKTtcbiAgICAgIHJldHVybiBmdW5jO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgc2V0VG9TdHJpbmdgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaG90IGxvb3Agc2hvcnRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzdHJpbmcgVGhlIGB0b1N0cmluZ2AgcmVzdWx0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgZnVuY2AuXG4gICAgICovXG4gICAgdmFyIGJhc2VTZXRUb1N0cmluZyA9ICFkZWZpbmVQcm9wZXJ0eSA/IGlkZW50aXR5IDogZnVuY3Rpb24oZnVuYywgc3RyaW5nKSB7XG4gICAgICByZXR1cm4gZGVmaW5lUHJvcGVydHkoZnVuYywgJ3RvU3RyaW5nJywge1xuICAgICAgICAnY29uZmlndXJhYmxlJzogdHJ1ZSxcbiAgICAgICAgJ2VudW1lcmFibGUnOiBmYWxzZSxcbiAgICAgICAgJ3ZhbHVlJzogY29uc3RhbnQoc3RyaW5nKSxcbiAgICAgICAgJ3dyaXRhYmxlJzogdHJ1ZVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNodWZmbGVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzaHVmZmxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNodWZmbGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTaHVmZmxlKGNvbGxlY3Rpb24pIHtcbiAgICAgIHJldHVybiBzaHVmZmxlU2VsZih2YWx1ZXMoY29sbGVjdGlvbikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNsaWNlYCB3aXRob3V0IGFuIGl0ZXJhdGVlIGNhbGwgZ3VhcmQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzbGljZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTbGljZShhcnJheSwgc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgIHN0YXJ0ID0gLXN0YXJ0ID4gbGVuZ3RoID8gMCA6IChsZW5ndGggKyBzdGFydCk7XG4gICAgICB9XG4gICAgICBlbmQgPSBlbmQgPiBsZW5ndGggPyBsZW5ndGggOiBlbmQ7XG4gICAgICBpZiAoZW5kIDwgMCkge1xuICAgICAgICBlbmQgKz0gbGVuZ3RoO1xuICAgICAgfVxuICAgICAgbGVuZ3RoID0gc3RhcnQgPiBlbmQgPyAwIDogKChlbmQgLSBzdGFydCkgPj4+IDApO1xuICAgICAgc3RhcnQgPj4+PSAwO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtpbmRleF0gPSBhcnJheVtpbmRleCArIHN0YXJ0XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29tZWAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNvbWUoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuXG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmVzdWx0ID0gcHJlZGljYXRlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICAgIHJldHVybiAhcmVzdWx0O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gISFyZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydGVkSW5kZXhgIGFuZCBgXy5zb3J0ZWRMYXN0SW5kZXhgIHdoaWNoXG4gICAgICogcGVyZm9ybXMgYSBiaW5hcnkgc2VhcmNoIG9mIGBhcnJheWAgdG8gZGV0ZXJtaW5lIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgXG4gICAgICogc2hvdWxkIGJlIGluc2VydGVkIGludG8gYGFycmF5YCBpbiBvcmRlciB0byBtYWludGFpbiBpdHMgc29ydCBvcmRlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3JldEhpZ2hlc3RdIFNwZWNpZnkgcmV0dXJuaW5nIHRoZSBoaWdoZXN0IHF1YWxpZmllZCBpbmRleC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZFxuICAgICAqICBpbnRvIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSwgcmV0SGlnaGVzdCkge1xuICAgICAgdmFyIGxvdyA9IDAsXG4gICAgICAgICAgaGlnaCA9IGFycmF5ID09IG51bGwgPyBsb3cgOiBhcnJheS5sZW5ndGg7XG5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgJiYgdmFsdWUgPT09IHZhbHVlICYmIGhpZ2ggPD0gSEFMRl9NQVhfQVJSQVlfTEVOR1RIKSB7XG4gICAgICAgIHdoaWxlIChsb3cgPCBoaWdoKSB7XG4gICAgICAgICAgdmFyIG1pZCA9IChsb3cgKyBoaWdoKSA+Pj4gMSxcbiAgICAgICAgICAgICAgY29tcHV0ZWQgPSBhcnJheVttaWRdO1xuXG4gICAgICAgICAgaWYgKGNvbXB1dGVkICE9PSBudWxsICYmICFpc1N5bWJvbChjb21wdXRlZCkgJiZcbiAgICAgICAgICAgICAgKHJldEhpZ2hlc3QgPyAoY29tcHV0ZWQgPD0gdmFsdWUpIDogKGNvbXB1dGVkIDwgdmFsdWUpKSkge1xuICAgICAgICAgICAgbG93ID0gbWlkICsgMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGlnaCA9IG1pZDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGhpZ2g7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4QnkoYXJyYXksIHZhbHVlLCBpZGVudGl0eSwgcmV0SGlnaGVzdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydGVkSW5kZXhCeWAgYW5kIGBfLnNvcnRlZExhc3RJbmRleEJ5YFxuICAgICAqIHdoaWNoIGludm9rZXMgYGl0ZXJhdGVlYCBmb3IgYHZhbHVlYCBhbmQgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgdG8gY29tcHV0ZVxuICAgICAqIHRoZWlyIHNvcnQgcmFua2luZy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ7ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRIaWdoZXN0XSBTcGVjaWZ5IHJldHVybmluZyB0aGUgaGlnaGVzdCBxdWFsaWZpZWQgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgaXRlcmF0ZWUsIHJldEhpZ2hlc3QpIHtcbiAgICAgIHZhciBsb3cgPSAwLFxuICAgICAgICAgIGhpZ2ggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmIChoaWdoID09PSAwKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuXG4gICAgICB2YWx1ZSA9IGl0ZXJhdGVlKHZhbHVlKTtcbiAgICAgIHZhciB2YWxJc05hTiA9IHZhbHVlICE9PSB2YWx1ZSxcbiAgICAgICAgICB2YWxJc051bGwgPSB2YWx1ZSA9PT0gbnVsbCxcbiAgICAgICAgICB2YWxJc1N5bWJvbCA9IGlzU3ltYm9sKHZhbHVlKSxcbiAgICAgICAgICB2YWxJc1VuZGVmaW5lZCA9IHZhbHVlID09PSB1bmRlZmluZWQ7XG5cbiAgICAgIHdoaWxlIChsb3cgPCBoaWdoKSB7XG4gICAgICAgIHZhciBtaWQgPSBuYXRpdmVGbG9vcigobG93ICsgaGlnaCkgLyAyKSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUoYXJyYXlbbWlkXSksXG4gICAgICAgICAgICBvdGhJc0RlZmluZWQgPSBjb21wdXRlZCAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgb3RoSXNOdWxsID0gY29tcHV0ZWQgPT09IG51bGwsXG4gICAgICAgICAgICBvdGhJc1JlZmxleGl2ZSA9IGNvbXB1dGVkID09PSBjb21wdXRlZCxcbiAgICAgICAgICAgIG90aElzU3ltYm9sID0gaXNTeW1ib2woY29tcHV0ZWQpO1xuXG4gICAgICAgIGlmICh2YWxJc05hTikge1xuICAgICAgICAgIHZhciBzZXRMb3cgPSByZXRIaWdoZXN0IHx8IG90aElzUmVmbGV4aXZlO1xuICAgICAgICB9IGVsc2UgaWYgKHZhbElzVW5kZWZpbmVkKSB7XG4gICAgICAgICAgc2V0TG93ID0gb3RoSXNSZWZsZXhpdmUgJiYgKHJldEhpZ2hlc3QgfHwgb3RoSXNEZWZpbmVkKTtcbiAgICAgICAgfSBlbHNlIGlmICh2YWxJc051bGwpIHtcbiAgICAgICAgICBzZXRMb3cgPSBvdGhJc1JlZmxleGl2ZSAmJiBvdGhJc0RlZmluZWQgJiYgKHJldEhpZ2hlc3QgfHwgIW90aElzTnVsbCk7XG4gICAgICAgIH0gZWxzZSBpZiAodmFsSXNTeW1ib2wpIHtcbiAgICAgICAgICBzZXRMb3cgPSBvdGhJc1JlZmxleGl2ZSAmJiBvdGhJc0RlZmluZWQgJiYgIW90aElzTnVsbCAmJiAocmV0SGlnaGVzdCB8fCAhb3RoSXNTeW1ib2wpO1xuICAgICAgICB9IGVsc2UgaWYgKG90aElzTnVsbCB8fCBvdGhJc1N5bWJvbCkge1xuICAgICAgICAgIHNldExvdyA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNldExvdyA9IHJldEhpZ2hlc3QgPyAoY29tcHV0ZWQgPD0gdmFsdWUpIDogKGNvbXB1dGVkIDwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZXRMb3cpIHtcbiAgICAgICAgICBsb3cgPSBtaWQgKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGhpZ2ggPSBtaWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVNaW4oaGlnaCwgTUFYX0FSUkFZX0lOREVYKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zb3J0ZWRVbmlxYCBhbmQgYF8uc29ydGVkVW5pcUJ5YCB3aXRob3V0XG4gICAgICogc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU29ydGVkVW5pcShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSkgOiB2YWx1ZTtcblxuICAgICAgICBpZiAoIWluZGV4IHx8ICFlcShjb21wdXRlZCwgc2VlbikpIHtcbiAgICAgICAgICB2YXIgc2VlbiA9IGNvbXB1dGVkO1xuICAgICAgICAgIHJlc3VsdFtyZXNJbmRleCsrXSA9IHZhbHVlID09PSAwID8gMCA6IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnRvTnVtYmVyYCB3aGljaCBkb2Vzbid0IGVuc3VyZSBjb3JyZWN0XG4gICAgICogY29udmVyc2lvbnMgb2YgYmluYXJ5LCBoZXhhZGVjaW1hbCwgb3Igb2N0YWwgc3RyaW5nIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBudW1iZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVRvTnVtYmVyKHZhbHVlKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIE5BTjtcbiAgICAgIH1cbiAgICAgIHJldHVybiArdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udG9TdHJpbmdgIHdoaWNoIGRvZXNuJ3QgY29udmVydCBudWxsaXNoXG4gICAgICogdmFsdWVzIHRvIGVtcHR5IHN0cmluZ3MuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VUb1N0cmluZyh2YWx1ZSkge1xuICAgICAgLy8gRXhpdCBlYXJseSBmb3Igc3RyaW5ncyB0byBhdm9pZCBhIHBlcmZvcm1hbmNlIGhpdCBpbiBzb21lIGVudmlyb25tZW50cy5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbnZlcnQgdmFsdWVzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgIHJldHVybiBhcnJheU1hcCh2YWx1ZSwgYmFzZVRvU3RyaW5nKSArICcnO1xuICAgICAgfVxuICAgICAgaWYgKGlzU3ltYm9sKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gc3ltYm9sVG9TdHJpbmcgPyBzeW1ib2xUb1N0cmluZy5jYWxsKHZhbHVlKSA6ICcnO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9ICh2YWx1ZSArICcnKTtcbiAgICAgIHJldHVybiAocmVzdWx0ID09ICcwJyAmJiAoMSAvIHZhbHVlKSA9PSAtSU5GSU5JVFkpID8gJy0wJyA6IHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51bmlxQnlgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlVW5pcShhcnJheSwgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGluY2x1ZGVzID0gYXJyYXlJbmNsdWRlcyxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgaXNDb21tb24gPSB0cnVlLFxuICAgICAgICAgIHJlc3VsdCA9IFtdLFxuICAgICAgICAgIHNlZW4gPSByZXN1bHQ7XG5cbiAgICAgIGlmIChjb21wYXJhdG9yKSB7XG4gICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIGluY2x1ZGVzID0gYXJyYXlJbmNsdWRlc1dpdGg7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChsZW5ndGggPj0gTEFSR0VfQVJSQVlfU0laRSkge1xuICAgICAgICB2YXIgc2V0ID0gaXRlcmF0ZWUgPyBudWxsIDogY3JlYXRlU2V0KGFycmF5KTtcbiAgICAgICAgaWYgKHNldCkge1xuICAgICAgICAgIHJldHVybiBzZXRUb0FycmF5KHNldCk7XG4gICAgICAgIH1cbiAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgaW5jbHVkZXMgPSBjYWNoZUhhcztcbiAgICAgICAgc2VlbiA9IG5ldyBTZXRDYWNoZTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBzZWVuID0gaXRlcmF0ZWUgPyBbXSA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlO1xuXG4gICAgICAgIHZhbHVlID0gKGNvbXBhcmF0b3IgfHwgdmFsdWUgIT09IDApID8gdmFsdWUgOiAwO1xuICAgICAgICBpZiAoaXNDb21tb24gJiYgY29tcHV0ZWQgPT09IGNvbXB1dGVkKSB7XG4gICAgICAgICAgdmFyIHNlZW5JbmRleCA9IHNlZW4ubGVuZ3RoO1xuICAgICAgICAgIHdoaWxlIChzZWVuSW5kZXgtLSkge1xuICAgICAgICAgICAgaWYgKHNlZW5bc2VlbkluZGV4XSA9PT0gY29tcHV0ZWQpIHtcbiAgICAgICAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChpdGVyYXRlZSkge1xuICAgICAgICAgICAgc2Vlbi5wdXNoKGNvbXB1dGVkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCFpbmNsdWRlcyhzZWVuLCBjb21wdXRlZCwgY29tcGFyYXRvcikpIHtcbiAgICAgICAgICBpZiAoc2VlbiAhPT0gcmVzdWx0KSB7XG4gICAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udW5zZXRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwcm9wZXJ0eSBwYXRoIHRvIHVuc2V0LlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgaXMgZGVsZXRlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VVbnNldChvYmplY3QsIHBhdGgpIHtcbiAgICAgIHBhdGggPSBjYXN0UGF0aChwYXRoLCBvYmplY3QpO1xuICAgICAgb2JqZWN0ID0gcGFyZW50KG9iamVjdCwgcGF0aCk7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgfHwgZGVsZXRlIG9iamVjdFt0b0tleShsYXN0KHBhdGgpKV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udXBkYXRlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gdXBkYXRlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHVwZGF0ZXIgVGhlIGZ1bmN0aW9uIHRvIHByb2R1Y2UgdGhlIHVwZGF0ZWQgdmFsdWUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgcGF0aCBjcmVhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VVcGRhdGUob2JqZWN0LCBwYXRoLCB1cGRhdGVyLCBjdXN0b21pemVyKSB7XG4gICAgICByZXR1cm4gYmFzZVNldChvYmplY3QsIHBhdGgsIHVwZGF0ZXIoYmFzZUdldChvYmplY3QsIHBhdGgpKSwgY3VzdG9taXplcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLmRyb3BXaGlsZWAgYW5kIGBfLnRha2VXaGlsZWBcbiAgICAgKiB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0Ryb3BdIFNwZWNpZnkgZHJvcHBpbmcgZWxlbWVudHMgaW5zdGVhZCBvZiB0YWtpbmcgdGhlbS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVdoaWxlKGFycmF5LCBwcmVkaWNhdGUsIGlzRHJvcCwgZnJvbVJpZ2h0KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIGluZGV4ID0gZnJvbVJpZ2h0ID8gbGVuZ3RoIDogLTE7XG5cbiAgICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpICYmXG4gICAgICAgIHByZWRpY2F0ZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHt9XG5cbiAgICAgIHJldHVybiBpc0Ryb3BcbiAgICAgICAgPyBiYXNlU2xpY2UoYXJyYXksIChmcm9tUmlnaHQgPyAwIDogaW5kZXgpLCAoZnJvbVJpZ2h0ID8gaW5kZXggKyAxIDogbGVuZ3RoKSlcbiAgICAgICAgOiBiYXNlU2xpY2UoYXJyYXksIChmcm9tUmlnaHQgPyBpbmRleCArIDEgOiAwKSwgKGZyb21SaWdodCA/IGxlbmd0aCA6IGluZGV4KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYHdyYXBwZXJWYWx1ZWAgd2hpY2ggcmV0dXJucyB0aGUgcmVzdWx0IG9mXG4gICAgICogcGVyZm9ybWluZyBhIHNlcXVlbmNlIG9mIGFjdGlvbnMgb24gdGhlIHVud3JhcHBlZCBgdmFsdWVgLCB3aGVyZSBlYWNoXG4gICAgICogc3VjY2Vzc2l2ZSBhY3Rpb24gaXMgc3VwcGxpZWQgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgcHJldmlvdXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhY3Rpb25zIEFjdGlvbnMgdG8gcGVyZm9ybSB0byByZXNvbHZlIHRoZSB1bndyYXBwZWQgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VXcmFwcGVyVmFsdWUodmFsdWUsIGFjdGlvbnMpIHtcbiAgICAgIHZhciByZXN1bHQgPSB2YWx1ZTtcbiAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcikge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQudmFsdWUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheVJlZHVjZShhY3Rpb25zLCBmdW5jdGlvbihyZXN1bHQsIGFjdGlvbikge1xuICAgICAgICByZXR1cm4gYWN0aW9uLmZ1bmMuYXBwbHkoYWN0aW9uLnRoaXNBcmcsIGFycmF5UHVzaChbcmVzdWx0XSwgYWN0aW9uLmFyZ3MpKTtcbiAgICAgIH0sIHJlc3VsdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLnhvcmAsIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLCB0aGF0IGFjY2VwdHMgYW4gYXJyYXkgb2YgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5cyBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiB2YWx1ZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVhvcihhcnJheXMsIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXlzLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggPCAyKSB7XG4gICAgICAgIHJldHVybiBsZW5ndGggPyBiYXNlVW5pcShhcnJheXNbMF0pIDogW107XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgYXJyYXkgPSBhcnJheXNbaW5kZXhdLFxuICAgICAgICAgICAgb3RoSW5kZXggPSAtMTtcblxuICAgICAgICB3aGlsZSAoKytvdGhJbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIGlmIChvdGhJbmRleCAhPSBpbmRleCkge1xuICAgICAgICAgICAgcmVzdWx0W2luZGV4XSA9IGJhc2VEaWZmZXJlbmNlKHJlc3VsdFtpbmRleF0gfHwgYXJyYXksIGFycmF5c1tvdGhJbmRleF0sIGl0ZXJhdGVlLCBjb21wYXJhdG9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlVW5pcShiYXNlRmxhdHRlbihyZXN1bHQsIDEpLCBpdGVyYXRlZSwgY29tcGFyYXRvcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnppcE9iamVjdGAgd2hpY2ggYXNzaWducyB2YWx1ZXMgdXNpbmcgYGFzc2lnbkZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgaWRlbnRpZmllcnMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYXNzaWduRnVuYyBUaGUgZnVuY3Rpb24gdG8gYXNzaWduIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VaaXBPYmplY3QocHJvcHMsIHZhbHVlcywgYXNzaWduRnVuYykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgICAgIHZhbHNMZW5ndGggPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IHt9O1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBpbmRleCA8IHZhbHNMZW5ndGggPyB2YWx1ZXNbaW5kZXhdIDogdW5kZWZpbmVkO1xuICAgICAgICBhc3NpZ25GdW5jKHJlc3VsdCwgcHJvcHNbaW5kZXhdLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhc3RzIGB2YWx1ZWAgdG8gYW4gZW1wdHkgYXJyYXkgaWYgaXQncyBub3QgYW4gYXJyYXkgbGlrZSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyB0aGUgY2FzdCBhcnJheS1saWtlIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYXN0QXJyYXlMaWtlT2JqZWN0KHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QodmFsdWUpID8gdmFsdWUgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYXN0cyBgdmFsdWVgIHRvIGBpZGVudGl0eWAgaWYgaXQncyBub3QgYSBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgY2FzdCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYXN0RnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ2Z1bmN0aW9uJyA/IHZhbHVlIDogaWRlbnRpdHk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FzdHMgYHZhbHVlYCB0byBhIHBhdGggYXJyYXkgaWYgaXQncyBub3Qgb25lLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgb2JqZWN0IHRvIHF1ZXJ5IGtleXMgb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjYXN0IHByb3BlcnR5IHBhdGggYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FzdFBhdGgodmFsdWUsIG9iamVjdCkge1xuICAgICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0tleSh2YWx1ZSwgb2JqZWN0KSA/IFt2YWx1ZV0gOiBzdHJpbmdUb1BhdGgodG9TdHJpbmcodmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIGBiYXNlUmVzdGAgYWxpYXMgd2hpY2ggY2FuIGJlIHJlcGxhY2VkIHdpdGggYGlkZW50aXR5YCBieSBtb2R1bGVcbiAgICAgKiByZXBsYWNlbWVudCBwbHVnaW5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXBwbHkgYSByZXN0IHBhcmFtZXRlciB0by5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICB2YXIgY2FzdFJlc3QgPSBiYXNlUmVzdDtcblxuICAgIC8qKlxuICAgICAqIENhc3RzIGBhcnJheWAgdG8gYSBzbGljZSBpZiBpdCdzIG5lZWRlZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjYXN0IHNsaWNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhc3RTbGljZShhcnJheSwgc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICAgIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuZ3RoIDogZW5kO1xuICAgICAgcmV0dXJuICghc3RhcnQgJiYgZW5kID49IGxlbmd0aCkgPyBhcnJheSA6IGJhc2VTbGljZShhcnJheSwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzaW1wbGUgd3JhcHBlciBhcm91bmQgdGhlIGdsb2JhbCBbYGNsZWFyVGltZW91dGBdKGh0dHBzOi8vbWRuLmlvL2NsZWFyVGltZW91dCkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfE9iamVjdH0gaWQgVGhlIHRpbWVyIGlkIG9yIHRpbWVvdXQgb2JqZWN0IG9mIHRoZSB0aW1lciB0byBjbGVhci5cbiAgICAgKi9cbiAgICB2YXIgY2xlYXJUaW1lb3V0ID0gY3R4Q2xlYXJUaW1lb3V0IHx8IGZ1bmN0aW9uKGlkKSB7XG4gICAgICByZXR1cm4gcm9vdC5jbGVhclRpbWVvdXQoaWQpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgIGBidWZmZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0J1ZmZlcn0gYnVmZmVyIFRoZSBidWZmZXIgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7QnVmZmVyfSBSZXR1cm5zIHRoZSBjbG9uZWQgYnVmZmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lQnVmZmVyKGJ1ZmZlciwgaXNEZWVwKSB7XG4gICAgICBpZiAoaXNEZWVwKSB7XG4gICAgICAgIHJldHVybiBidWZmZXIuc2xpY2UoKTtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSBidWZmZXIubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IGFsbG9jVW5zYWZlID8gYWxsb2NVbnNhZmUobGVuZ3RoKSA6IG5ldyBidWZmZXIuY29uc3RydWN0b3IobGVuZ3RoKTtcblxuICAgICAgYnVmZmVyLmNvcHkocmVzdWx0KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGBhcnJheUJ1ZmZlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGFycmF5QnVmZmVyIFRoZSBhcnJheSBidWZmZXIgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge0FycmF5QnVmZmVyfSBSZXR1cm5zIHRoZSBjbG9uZWQgYXJyYXkgYnVmZmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lQXJyYXlCdWZmZXIoYXJyYXlCdWZmZXIpIHtcbiAgICAgIHZhciByZXN1bHQgPSBuZXcgYXJyYXlCdWZmZXIuY29uc3RydWN0b3IoYXJyYXlCdWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICBuZXcgVWludDhBcnJheShyZXN1bHQpLnNldChuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcikpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYGRhdGFWaWV3YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFWaWV3IFRoZSBkYXRhIHZpZXcgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgZGF0YSB2aWV3LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lRGF0YVZpZXcoZGF0YVZpZXcsIGlzRGVlcCkge1xuICAgICAgdmFyIGJ1ZmZlciA9IGlzRGVlcCA/IGNsb25lQXJyYXlCdWZmZXIoZGF0YVZpZXcuYnVmZmVyKSA6IGRhdGFWaWV3LmJ1ZmZlcjtcbiAgICAgIHJldHVybiBuZXcgZGF0YVZpZXcuY29uc3RydWN0b3IoYnVmZmVyLCBkYXRhVmlldy5ieXRlT2Zmc2V0LCBkYXRhVmlldy5ieXRlTGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHJlZ2V4cGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSByZWdleHAgVGhlIHJlZ2V4cCB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgcmVnZXhwLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lUmVnRXhwKHJlZ2V4cCkge1xuICAgICAgdmFyIHJlc3VsdCA9IG5ldyByZWdleHAuY29uc3RydWN0b3IocmVnZXhwLnNvdXJjZSwgcmVGbGFncy5leGVjKHJlZ2V4cCkpO1xuICAgICAgcmVzdWx0Lmxhc3RJbmRleCA9IHJlZ2V4cC5sYXN0SW5kZXg7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiB0aGUgYHN5bWJvbGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3ltYm9sIFRoZSBzeW1ib2wgb2JqZWN0IHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCBzeW1ib2wgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lU3ltYm9sKHN5bWJvbCkge1xuICAgICAgcmV0dXJuIHN5bWJvbFZhbHVlT2YgPyBPYmplY3Qoc3ltYm9sVmFsdWVPZi5jYWxsKHN5bWJvbCkpIDoge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGB0eXBlZEFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHR5cGVkQXJyYXkgVGhlIHR5cGVkIGFycmF5IHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHR5cGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lVHlwZWRBcnJheSh0eXBlZEFycmF5LCBpc0RlZXApIHtcbiAgICAgIHZhciBidWZmZXIgPSBpc0RlZXAgPyBjbG9uZUFycmF5QnVmZmVyKHR5cGVkQXJyYXkuYnVmZmVyKSA6IHR5cGVkQXJyYXkuYnVmZmVyO1xuICAgICAgcmV0dXJuIG5ldyB0eXBlZEFycmF5LmNvbnN0cnVjdG9yKGJ1ZmZlciwgdHlwZWRBcnJheS5ieXRlT2Zmc2V0LCB0eXBlZEFycmF5Lmxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcGFyZXMgdmFsdWVzIHRvIHNvcnQgdGhlbSBpbiBhc2NlbmRpbmcgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzb3J0IG9yZGVyIGluZGljYXRvciBmb3IgYHZhbHVlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wYXJlQXNjZW5kaW5nKHZhbHVlLCBvdGhlcikge1xuICAgICAgaWYgKHZhbHVlICE9PSBvdGhlcikge1xuICAgICAgICB2YXIgdmFsSXNEZWZpbmVkID0gdmFsdWUgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHZhbElzTnVsbCA9IHZhbHVlID09PSBudWxsLFxuICAgICAgICAgICAgdmFsSXNSZWZsZXhpdmUgPSB2YWx1ZSA9PT0gdmFsdWUsXG4gICAgICAgICAgICB2YWxJc1N5bWJvbCA9IGlzU3ltYm9sKHZhbHVlKTtcblxuICAgICAgICB2YXIgb3RoSXNEZWZpbmVkID0gb3RoZXIgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIG90aElzTnVsbCA9IG90aGVyID09PSBudWxsLFxuICAgICAgICAgICAgb3RoSXNSZWZsZXhpdmUgPSBvdGhlciA9PT0gb3RoZXIsXG4gICAgICAgICAgICBvdGhJc1N5bWJvbCA9IGlzU3ltYm9sKG90aGVyKTtcblxuICAgICAgICBpZiAoKCFvdGhJc051bGwgJiYgIW90aElzU3ltYm9sICYmICF2YWxJc1N5bWJvbCAmJiB2YWx1ZSA+IG90aGVyKSB8fFxuICAgICAgICAgICAgKHZhbElzU3ltYm9sICYmIG90aElzRGVmaW5lZCAmJiBvdGhJc1JlZmxleGl2ZSAmJiAhb3RoSXNOdWxsICYmICFvdGhJc1N5bWJvbCkgfHxcbiAgICAgICAgICAgICh2YWxJc051bGwgJiYgb3RoSXNEZWZpbmVkICYmIG90aElzUmVmbGV4aXZlKSB8fFxuICAgICAgICAgICAgKCF2YWxJc0RlZmluZWQgJiYgb3RoSXNSZWZsZXhpdmUpIHx8XG4gICAgICAgICAgICAhdmFsSXNSZWZsZXhpdmUpIHtcbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKCF2YWxJc051bGwgJiYgIXZhbElzU3ltYm9sICYmICFvdGhJc1N5bWJvbCAmJiB2YWx1ZSA8IG90aGVyKSB8fFxuICAgICAgICAgICAgKG90aElzU3ltYm9sICYmIHZhbElzRGVmaW5lZCAmJiB2YWxJc1JlZmxleGl2ZSAmJiAhdmFsSXNOdWxsICYmICF2YWxJc1N5bWJvbCkgfHxcbiAgICAgICAgICAgIChvdGhJc051bGwgJiYgdmFsSXNEZWZpbmVkICYmIHZhbElzUmVmbGV4aXZlKSB8fFxuICAgICAgICAgICAgKCFvdGhJc0RlZmluZWQgJiYgdmFsSXNSZWZsZXhpdmUpIHx8XG4gICAgICAgICAgICAhb3RoSXNSZWZsZXhpdmUpIHtcbiAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8ub3JkZXJCeWAgdG8gY29tcGFyZSBtdWx0aXBsZSBwcm9wZXJ0aWVzIG9mIGEgdmFsdWUgdG8gYW5vdGhlclxuICAgICAqIGFuZCBzdGFibGUgc29ydCB0aGVtLlxuICAgICAqXG4gICAgICogSWYgYG9yZGVyc2AgaXMgdW5zcGVjaWZpZWQsIGFsbCB2YWx1ZXMgYXJlIHNvcnRlZCBpbiBhc2NlbmRpbmcgb3JkZXIuIE90aGVyd2lzZSxcbiAgICAgKiBzcGVjaWZ5IGFuIG9yZGVyIG9mIFwiZGVzY1wiIGZvciBkZXNjZW5kaW5nIG9yIFwiYXNjXCIgZm9yIGFzY2VuZGluZyBzb3J0IG9yZGVyXG4gICAgICogb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtib29sZWFuW118c3RyaW5nW119IG9yZGVycyBUaGUgb3JkZXIgdG8gc29ydCBieSBmb3IgZWFjaCBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzb3J0IG9yZGVyIGluZGljYXRvciBmb3IgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcGFyZU11bHRpcGxlKG9iamVjdCwgb3RoZXIsIG9yZGVycykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgb2JqQ3JpdGVyaWEgPSBvYmplY3QuY3JpdGVyaWEsXG4gICAgICAgICAgb3RoQ3JpdGVyaWEgPSBvdGhlci5jcml0ZXJpYSxcbiAgICAgICAgICBsZW5ndGggPSBvYmpDcml0ZXJpYS5sZW5ndGgsXG4gICAgICAgICAgb3JkZXJzTGVuZ3RoID0gb3JkZXJzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGNvbXBhcmVBc2NlbmRpbmcob2JqQ3JpdGVyaWFbaW5kZXhdLCBvdGhDcml0ZXJpYVtpbmRleF0pO1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgaWYgKGluZGV4ID49IG9yZGVyc0xlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIG9yZGVyID0gb3JkZXJzW2luZGV4XTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0ICogKG9yZGVyID09ICdkZXNjJyA/IC0xIDogMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEZpeGVzIGFuIGBBcnJheSNzb3J0YCBidWcgaW4gdGhlIEpTIGVuZ2luZSBlbWJlZGRlZCBpbiBBZG9iZSBhcHBsaWNhdGlvbnNcbiAgICAgIC8vIHRoYXQgY2F1c2VzIGl0LCB1bmRlciBjZXJ0YWluIGNpcmN1bXN0YW5jZXMsIHRvIHByb3ZpZGUgdGhlIHNhbWUgdmFsdWUgZm9yXG4gICAgICAvLyBgb2JqZWN0YCBhbmQgYG90aGVyYC4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9qYXNoa2VuYXMvdW5kZXJzY29yZS9wdWxsLzEyNDdcbiAgICAgIC8vIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAvL1xuICAgICAgLy8gVGhpcyBhbHNvIGVuc3VyZXMgYSBzdGFibGUgc29ydCBpbiBWOCBhbmQgb3RoZXIgZW5naW5lcy5cbiAgICAgIC8vIFNlZSBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD05MCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgcmV0dXJuIG9iamVjdC5pbmRleCAtIG90aGVyLmluZGV4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLFxuICAgICAqIHBsYWNlaG9sZGVycywgYW5kIHByb3ZpZGVkIGFyZ3VtZW50cyBpbnRvIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBob2xkZXJzIFRoZSBgcGFydGlhbHNgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAgICogQHBhcmFtcyB7Ym9vbGVhbn0gW2lzQ3VycmllZF0gU3BlY2lmeSBjb21wb3NpbmcgZm9yIGEgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21wb3NlZCBhcmd1bWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcG9zZUFyZ3MoYXJncywgcGFydGlhbHMsIGhvbGRlcnMsIGlzQ3VycmllZCkge1xuICAgICAgdmFyIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgICAgIGFyZ3NMZW5ndGggPSBhcmdzLmxlbmd0aCxcbiAgICAgICAgICBob2xkZXJzTGVuZ3RoID0gaG9sZGVycy5sZW5ndGgsXG4gICAgICAgICAgbGVmdEluZGV4ID0gLTEsXG4gICAgICAgICAgbGVmdExlbmd0aCA9IHBhcnRpYWxzLmxlbmd0aCxcbiAgICAgICAgICByYW5nZUxlbmd0aCA9IG5hdGl2ZU1heChhcmdzTGVuZ3RoIC0gaG9sZGVyc0xlbmd0aCwgMCksXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVmdExlbmd0aCArIHJhbmdlTGVuZ3RoKSxcbiAgICAgICAgICBpc1VuY3VycmllZCA9ICFpc0N1cnJpZWQ7XG5cbiAgICAgIHdoaWxlICgrK2xlZnRJbmRleCA8IGxlZnRMZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2xlZnRJbmRleF0gPSBwYXJ0aWFsc1tsZWZ0SW5kZXhdO1xuICAgICAgfVxuICAgICAgd2hpbGUgKCsrYXJnc0luZGV4IDwgaG9sZGVyc0xlbmd0aCkge1xuICAgICAgICBpZiAoaXNVbmN1cnJpZWQgfHwgYXJnc0luZGV4IDwgYXJnc0xlbmd0aCkge1xuICAgICAgICAgIHJlc3VsdFtob2xkZXJzW2FyZ3NJbmRleF1dID0gYXJnc1thcmdzSW5kZXhdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aGlsZSAocmFuZ2VMZW5ndGgtLSkge1xuICAgICAgICByZXN1bHRbbGVmdEluZGV4KytdID0gYXJnc1thcmdzSW5kZXgrK107XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgY29tcG9zZUFyZ3NgIGV4Y2VwdCB0aGF0IHRoZSBhcmd1bWVudHMgY29tcG9zaXRpb25cbiAgICAgKiBpcyB0YWlsb3JlZCBmb3IgYF8ucGFydGlhbFJpZ2h0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gYXBwZW5kIHRvIHRob3NlIHByb3ZpZGVkLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGhvbGRlcnMgVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW1zIHtib29sZWFufSBbaXNDdXJyaWVkXSBTcGVjaWZ5IGNvbXBvc2luZyBmb3IgYSBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbXBvc2VkIGFyZ3VtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wb3NlQXJnc1JpZ2h0KGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzLCBpc0N1cnJpZWQpIHtcbiAgICAgIHZhciBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgICBhcmdzTGVuZ3RoID0gYXJncy5sZW5ndGgsXG4gICAgICAgICAgaG9sZGVyc0luZGV4ID0gLTEsXG4gICAgICAgICAgaG9sZGVyc0xlbmd0aCA9IGhvbGRlcnMubGVuZ3RoLFxuICAgICAgICAgIHJpZ2h0SW5kZXggPSAtMSxcbiAgICAgICAgICByaWdodExlbmd0aCA9IHBhcnRpYWxzLmxlbmd0aCxcbiAgICAgICAgICByYW5nZUxlbmd0aCA9IG5hdGl2ZU1heChhcmdzTGVuZ3RoIC0gaG9sZGVyc0xlbmd0aCwgMCksXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkocmFuZ2VMZW5ndGggKyByaWdodExlbmd0aCksXG4gICAgICAgICAgaXNVbmN1cnJpZWQgPSAhaXNDdXJyaWVkO1xuXG4gICAgICB3aGlsZSAoKythcmdzSW5kZXggPCByYW5nZUxlbmd0aCkge1xuICAgICAgICByZXN1bHRbYXJnc0luZGV4XSA9IGFyZ3NbYXJnc0luZGV4XTtcbiAgICAgIH1cbiAgICAgIHZhciBvZmZzZXQgPSBhcmdzSW5kZXg7XG4gICAgICB3aGlsZSAoKytyaWdodEluZGV4IDwgcmlnaHRMZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W29mZnNldCArIHJpZ2h0SW5kZXhdID0gcGFydGlhbHNbcmlnaHRJbmRleF07XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytob2xkZXJzSW5kZXggPCBob2xkZXJzTGVuZ3RoKSB7XG4gICAgICAgIGlmIChpc1VuY3VycmllZCB8fCBhcmdzSW5kZXggPCBhcmdzTGVuZ3RoKSB7XG4gICAgICAgICAgcmVzdWx0W29mZnNldCArIGhvbGRlcnNbaG9sZGVyc0luZGV4XV0gPSBhcmdzW2FyZ3NJbmRleCsrXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgdGhlIHZhbHVlcyBvZiBgc291cmNlYCB0byBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBzb3VyY2UgVGhlIGFycmF5IHRvIGNvcHkgdmFsdWVzIGZyb20uXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5PVtdXSBUaGUgYXJyYXkgdG8gY29weSB2YWx1ZXMgdG8uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29weUFycmF5KHNvdXJjZSwgYXJyYXkpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHNvdXJjZS5sZW5ndGg7XG5cbiAgICAgIGFycmF5IHx8IChhcnJheSA9IEFycmF5KGxlbmd0aCkpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgYXJyYXlbaW5kZXhdID0gc291cmNlW2luZGV4XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgcHJvcGVydGllcyBvZiBgc291cmNlYCB0byBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IHRvIGNvcHkgcHJvcGVydGllcyBmcm9tLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBpZGVudGlmaWVycyB0byBjb3B5LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgcHJvcGVydGllcyB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb3BpZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29weU9iamVjdChzb3VyY2UsIHByb3BzLCBvYmplY3QsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHZhciBpc05ldyA9ICFvYmplY3Q7XG4gICAgICBvYmplY3QgfHwgKG9iamVjdCA9IHt9KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuXG4gICAgICAgIHZhciBuZXdWYWx1ZSA9IGN1c3RvbWl6ZXJcbiAgICAgICAgICA/IGN1c3RvbWl6ZXIob2JqZWN0W2tleV0sIHNvdXJjZVtrZXldLCBrZXksIG9iamVjdCwgc291cmNlKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbmV3VmFsdWUgPSBzb3VyY2Vba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNOZXcpIHtcbiAgICAgICAgICBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIG5ld1ZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgbmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvcGllcyBvd24gc3ltYm9scyBvZiBgc291cmNlYCB0byBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyBmcm9tLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyB0by5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvcHlTeW1ib2xzKHNvdXJjZSwgb2JqZWN0KSB7XG4gICAgICByZXR1cm4gY29weU9iamVjdChzb3VyY2UsIGdldFN5bWJvbHMoc291cmNlKSwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgb3duIGFuZCBpbmhlcml0ZWQgc3ltYm9scyBvZiBgc291cmNlYCB0byBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyBmcm9tLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyB0by5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvcHlTeW1ib2xzSW4oc291cmNlLCBvYmplY3QpIHtcbiAgICAgIHJldHVybiBjb3B5T2JqZWN0KHNvdXJjZSwgZ2V0U3ltYm9sc0luKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uZ3JvdXBCeWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHNldHRlciBUaGUgZnVuY3Rpb24gdG8gc2V0IGFjY3VtdWxhdG9yIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaW5pdGlhbGl6ZXJdIFRoZSBhY2N1bXVsYXRvciBvYmplY3QgaW5pdGlhbGl6ZXIuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWdncmVnYXRvciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVBZ2dyZWdhdG9yKHNldHRlciwgaW5pdGlhbGl6ZXIpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUFnZ3JlZ2F0b3IgOiBiYXNlQWdncmVnYXRvcixcbiAgICAgICAgICAgIGFjY3VtdWxhdG9yID0gaW5pdGlhbGl6ZXIgPyBpbml0aWFsaXplcigpIDoge307XG5cbiAgICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgc2V0dGVyLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMiksIGFjY3VtdWxhdG9yKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uYXNzaWduYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYXNzaWduZXIgVGhlIGZ1bmN0aW9uIHRvIGFzc2lnbiB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYXNzaWduZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQXNzaWduZXIoYXNzaWduZXIpIHtcbiAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jdGlvbihvYmplY3QsIHNvdXJjZXMpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBsZW5ndGggPSBzb3VyY2VzLmxlbmd0aCxcbiAgICAgICAgICAgIGN1c3RvbWl6ZXIgPSBsZW5ndGggPiAxID8gc291cmNlc1tsZW5ndGggLSAxXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGd1YXJkID0gbGVuZ3RoID4gMiA/IHNvdXJjZXNbMl0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgY3VzdG9taXplciA9IChhc3NpZ25lci5sZW5ndGggPiAzICYmIHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicpXG4gICAgICAgICAgPyAobGVuZ3RoLS0sIGN1c3RvbWl6ZXIpXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKHNvdXJjZXNbMF0sIHNvdXJjZXNbMV0sIGd1YXJkKSkge1xuICAgICAgICAgIGN1c3RvbWl6ZXIgPSBsZW5ndGggPCAzID8gdW5kZWZpbmVkIDogY3VzdG9taXplcjtcbiAgICAgICAgICBsZW5ndGggPSAxO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW2luZGV4XTtcbiAgICAgICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgICAgICBhc3NpZ25lcihvYmplY3QsIHNvdXJjZSwgaW5kZXgsIGN1c3RvbWl6ZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBiYXNlRWFjaGAgb3IgYGJhc2VFYWNoUmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGEgY29sbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBiYXNlIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJhc2VFYWNoKGVhY2hGdW5jLCBmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0FycmF5TGlrZShjb2xsZWN0aW9uKSkge1xuICAgICAgICAgIHJldHVybiBlYWNoRnVuYyhjb2xsZWN0aW9uLCBpdGVyYXRlZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxlbmd0aCA9IGNvbGxlY3Rpb24ubGVuZ3RoLFxuICAgICAgICAgICAgaW5kZXggPSBmcm9tUmlnaHQgPyBsZW5ndGggOiAtMSxcbiAgICAgICAgICAgIGl0ZXJhYmxlID0gT2JqZWN0KGNvbGxlY3Rpb24pO1xuXG4gICAgICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpKSB7XG4gICAgICAgICAgaWYgKGl0ZXJhdGVlKGl0ZXJhYmxlW2luZGV4XSwgaW5kZXgsIGl0ZXJhYmxlKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGJhc2UgZnVuY3Rpb24gZm9yIG1ldGhvZHMgbGlrZSBgXy5mb3JJbmAgYW5kIGBfLmZvck93bmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJhc2UgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQmFzZUZvcihmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QsIGl0ZXJhdGVlLCBrZXlzRnVuYykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGl0ZXJhYmxlID0gT2JqZWN0KG9iamVjdCksXG4gICAgICAgICAgICBwcm9wcyA9IGtleXNGdW5jKG9iamVjdCksXG4gICAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGg7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgICAgdmFyIGtleSA9IHByb3BzW2Zyb21SaWdodCA/IGxlbmd0aCA6ICsraW5kZXhdO1xuICAgICAgICAgIGlmIChpdGVyYXRlZShpdGVyYWJsZVtrZXldLCBrZXksIGl0ZXJhYmxlKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB3cmFwcyBgZnVuY2AgdG8gaW52b2tlIGl0IHdpdGggdGhlIG9wdGlvbmFsIGB0aGlzYFxuICAgICAqIGJpbmRpbmcgb2YgYHRoaXNBcmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJpbmQoZnVuYywgYml0bWFzaywgdGhpc0FyZykge1xuICAgICAgdmFyIGlzQmluZCA9IGJpdG1hc2sgJiBXUkFQX0JJTkRfRkxBRyxcbiAgICAgICAgICBDdG9yID0gY3JlYXRlQ3RvcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGZuID0gKHRoaXMgJiYgdGhpcyAhPT0gcm9vdCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KGlzQmluZCA/IHRoaXNBcmcgOiB0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8ubG93ZXJGaXJzdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIFRoZSBuYW1lIG9mIHRoZSBgU3RyaW5nYCBjYXNlIG1ldGhvZCB0byB1c2UuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY2FzZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDYXNlRmlyc3QobWV0aG9kTmFtZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuXG4gICAgICAgIHZhciBzdHJTeW1ib2xzID0gaGFzVW5pY29kZShzdHJpbmcpXG4gICAgICAgICAgPyBzdHJpbmdUb0FycmF5KHN0cmluZylcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICB2YXIgY2hyID0gc3RyU3ltYm9sc1xuICAgICAgICAgID8gc3RyU3ltYm9sc1swXVxuICAgICAgICAgIDogc3RyaW5nLmNoYXJBdCgwKTtcblxuICAgICAgICB2YXIgdHJhaWxpbmcgPSBzdHJTeW1ib2xzXG4gICAgICAgICAgPyBjYXN0U2xpY2Uoc3RyU3ltYm9scywgMSkuam9pbignJylcbiAgICAgICAgICA6IHN0cmluZy5zbGljZSgxKTtcblxuICAgICAgICByZXR1cm4gY2hyW21ldGhvZE5hbWVdKCkgKyB0cmFpbGluZztcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uY2FtZWxDYXNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNvbWJpbmUgZWFjaCB3b3JkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvdW5kZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQ29tcG91bmRlcihjYWxsYmFjaykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgICByZXR1cm4gYXJyYXlSZWR1Y2Uod29yZHMoZGVidXJyKHN0cmluZykucmVwbGFjZShyZUFwb3MsICcnKSksIGNhbGxiYWNrLCAnJyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGFuIGluc3RhbmNlIG9mIGBDdG9yYCByZWdhcmRsZXNzIG9mXG4gICAgICogd2hldGhlciBpdCB3YXMgaW52b2tlZCBhcyBwYXJ0IG9mIGEgYG5ld2AgZXhwcmVzc2lvbiBvciBieSBgY2FsbGAgb3IgYGFwcGx5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gQ3RvciBUaGUgY29uc3RydWN0b3IgdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUN0b3IoQ3Rvcikge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBVc2UgYSBgc3dpdGNoYCBzdGF0ZW1lbnQgdG8gd29yayB3aXRoIGNsYXNzIGNvbnN0cnVjdG9ycy4gU2VlXG4gICAgICAgIC8vIGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLWVjbWFzY3JpcHQtZnVuY3Rpb24tb2JqZWN0cy1jYWxsLXRoaXNhcmd1bWVudC1hcmd1bWVudHNsaXN0XG4gICAgICAgIC8vIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgY2FzZSAwOiByZXR1cm4gbmV3IEN0b3I7XG4gICAgICAgICAgY2FzZSAxOiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSk7XG4gICAgICAgICAgY2FzZSAyOiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSk7XG4gICAgICAgICAgY2FzZSAzOiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgICAgICAgY2FzZSA0OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSk7XG4gICAgICAgICAgY2FzZSA1OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSk7XG4gICAgICAgICAgY2FzZSA2OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSk7XG4gICAgICAgICAgY2FzZSA3OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSwgYXJnc1s2XSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRoaXNCaW5kaW5nID0gYmFzZUNyZWF0ZShDdG9yLnByb3RvdHlwZSksXG4gICAgICAgICAgICByZXN1bHQgPSBDdG9yLmFwcGx5KHRoaXNCaW5kaW5nLCBhcmdzKTtcblxuICAgICAgICAvLyBNaW1pYyB0aGUgY29uc3RydWN0b3IncyBgcmV0dXJuYCBiZWhhdmlvci5cbiAgICAgICAgLy8gU2VlIGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDEzLjIuMiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgICByZXR1cm4gaXNPYmplY3QocmVzdWx0KSA/IHJlc3VsdCA6IHRoaXNCaW5kaW5nO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB3cmFwcyBgZnVuY2AgdG8gZW5hYmxlIGN1cnJ5aW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGFyaXR5IFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDdXJyeShmdW5jLCBiaXRtYXNrLCBhcml0eSkge1xuICAgICAgdmFyIEN0b3IgPSBjcmVhdGVDdG9yKGZ1bmMpO1xuXG4gICAgICBmdW5jdGlvbiB3cmFwcGVyKCkge1xuICAgICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCxcbiAgICAgICAgICAgIGFyZ3MgPSBBcnJheShsZW5ndGgpLFxuICAgICAgICAgICAgaW5kZXggPSBsZW5ndGgsXG4gICAgICAgICAgICBwbGFjZWhvbGRlciA9IGdldEhvbGRlcih3cmFwcGVyKTtcblxuICAgICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICAgIGFyZ3NbaW5kZXhdID0gYXJndW1lbnRzW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaG9sZGVycyA9IChsZW5ndGggPCAzICYmIGFyZ3NbMF0gIT09IHBsYWNlaG9sZGVyICYmIGFyZ3NbbGVuZ3RoIC0gMV0gIT09IHBsYWNlaG9sZGVyKVxuICAgICAgICAgID8gW11cbiAgICAgICAgICA6IHJlcGxhY2VIb2xkZXJzKGFyZ3MsIHBsYWNlaG9sZGVyKTtcblxuICAgICAgICBsZW5ndGggLT0gaG9sZGVycy5sZW5ndGg7XG4gICAgICAgIGlmIChsZW5ndGggPCBhcml0eSkge1xuICAgICAgICAgIHJldHVybiBjcmVhdGVSZWN1cnJ5KFxuICAgICAgICAgICAgZnVuYywgYml0bWFzaywgY3JlYXRlSHlicmlkLCB3cmFwcGVyLnBsYWNlaG9sZGVyLCB1bmRlZmluZWQsXG4gICAgICAgICAgICBhcmdzLCBob2xkZXJzLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkgLSBsZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IHJvb3QgJiYgdGhpcyBpbnN0YW5jZW9mIHdyYXBwZXIpID8gQ3RvciA6IGZ1bmM7XG4gICAgICAgIHJldHVybiBhcHBseShmbiwgdGhpcywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uZmluZGAgb3IgYF8uZmluZExhc3RgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmaW5kSW5kZXhGdW5jIFRoZSBmdW5jdGlvbiB0byBmaW5kIHRoZSBjb2xsZWN0aW9uIGluZGV4LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZpbmQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRmluZChmaW5kSW5kZXhGdW5jKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY29sbGVjdGlvbiwgcHJlZGljYXRlLCBmcm9tSW5kZXgpIHtcbiAgICAgICAgdmFyIGl0ZXJhYmxlID0gT2JqZWN0KGNvbGxlY3Rpb24pO1xuICAgICAgICBpZiAoIWlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pKSB7XG4gICAgICAgICAgdmFyIGl0ZXJhdGVlID0gZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKTtcbiAgICAgICAgICBjb2xsZWN0aW9uID0ga2V5cyhjb2xsZWN0aW9uKTtcbiAgICAgICAgICBwcmVkaWNhdGUgPSBmdW5jdGlvbihrZXkpIHsgcmV0dXJuIGl0ZXJhdGVlKGl0ZXJhYmxlW2tleV0sIGtleSwgaXRlcmFibGUpOyB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbmRleCA9IGZpbmRJbmRleEZ1bmMoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBmcm9tSW5kZXgpO1xuICAgICAgICByZXR1cm4gaW5kZXggPiAtMSA/IGl0ZXJhYmxlW2l0ZXJhdGVlID8gY29sbGVjdGlvbltpbmRleF0gOiBpbmRleF0gOiB1bmRlZmluZWQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgXy5mbG93YCBvciBgXy5mbG93UmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmbG93IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUZsb3coZnJvbVJpZ2h0KSB7XG4gICAgICByZXR1cm4gZmxhdFJlc3QoZnVuY3Rpb24oZnVuY3MpIHtcbiAgICAgICAgdmFyIGxlbmd0aCA9IGZ1bmNzLmxlbmd0aCxcbiAgICAgICAgICAgIGluZGV4ID0gbGVuZ3RoLFxuICAgICAgICAgICAgcHJlcmVxID0gTG9kYXNoV3JhcHBlci5wcm90b3R5cGUudGhydTtcblxuICAgICAgICBpZiAoZnJvbVJpZ2h0KSB7XG4gICAgICAgICAgZnVuY3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgICAgdmFyIGZ1bmMgPSBmdW5jc1tpbmRleF07XG4gICAgICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHByZXJlcSAmJiAhd3JhcHBlciAmJiBnZXRGdW5jTmFtZShmdW5jKSA9PSAnd3JhcHBlcicpIHtcbiAgICAgICAgICAgIHZhciB3cmFwcGVyID0gbmV3IExvZGFzaFdyYXBwZXIoW10sIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpbmRleCA9IHdyYXBwZXIgPyBpbmRleCA6IGxlbmd0aDtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBmdW5jID0gZnVuY3NbaW5kZXhdO1xuXG4gICAgICAgICAgdmFyIGZ1bmNOYW1lID0gZ2V0RnVuY05hbWUoZnVuYyksXG4gICAgICAgICAgICAgIGRhdGEgPSBmdW5jTmFtZSA9PSAnd3JhcHBlcicgPyBnZXREYXRhKGZ1bmMpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgaWYgKGRhdGEgJiYgaXNMYXppYWJsZShkYXRhWzBdKSAmJlxuICAgICAgICAgICAgICAgIGRhdGFbMV0gPT0gKFdSQVBfQVJZX0ZMQUcgfCBXUkFQX0NVUlJZX0ZMQUcgfCBXUkFQX1BBUlRJQUxfRkxBRyB8IFdSQVBfUkVBUkdfRkxBRykgJiZcbiAgICAgICAgICAgICAgICAhZGF0YVs0XS5sZW5ndGggJiYgZGF0YVs5XSA9PSAxXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgd3JhcHBlciA9IHdyYXBwZXJbZ2V0RnVuY05hbWUoZGF0YVswXSldLmFwcGx5KHdyYXBwZXIsIGRhdGFbM10pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3cmFwcGVyID0gKGZ1bmMubGVuZ3RoID09IDEgJiYgaXNMYXppYWJsZShmdW5jKSlcbiAgICAgICAgICAgICAgPyB3cmFwcGVyW2Z1bmNOYW1lXSgpXG4gICAgICAgICAgICAgIDogd3JhcHBlci50aHJ1KGZ1bmMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICAgIHZhbHVlID0gYXJnc1swXTtcblxuICAgICAgICAgIGlmICh3cmFwcGVyICYmIGFyZ3MubGVuZ3RoID09IDEgJiYgaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB3cmFwcGVyLnBsYW50KHZhbHVlKS52YWx1ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgaW5kZXggPSAwLFxuICAgICAgICAgICAgICByZXN1bHQgPSBsZW5ndGggPyBmdW5jc1tpbmRleF0uYXBwbHkodGhpcywgYXJncykgOiB2YWx1ZTtcblxuICAgICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBmdW5jc1tpbmRleF0uY2FsbCh0aGlzLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGludm9rZSBpdCB3aXRoIG9wdGlvbmFsIGB0aGlzYFxuICAgICAqIGJpbmRpbmcgb2YgYHRoaXNBcmdgLCBwYXJ0aWFsIGFwcGxpY2F0aW9uLCBhbmQgY3VycnlpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258c3RyaW5nfSBmdW5jIFRoZSBmdW5jdGlvbiBvciBtZXRob2QgbmFtZSB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0b1xuICAgICAqICB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzXSBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc1JpZ2h0XSBUaGUgYXJndW1lbnRzIHRvIGFwcGVuZCB0byB0aG9zZSBwcm92aWRlZFxuICAgICAqICB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzUmlnaHRdIFRoZSBgcGFydGlhbHNSaWdodGAgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVIeWJyaWQoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMsIHBhcnRpYWxzUmlnaHQsIGhvbGRlcnNSaWdodCwgYXJnUG9zLCBhcnksIGFyaXR5KSB7XG4gICAgICB2YXIgaXNBcnkgPSBiaXRtYXNrICYgV1JBUF9BUllfRkxBRyxcbiAgICAgICAgICBpc0JpbmQgPSBiaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcsXG4gICAgICAgICAgaXNCaW5kS2V5ID0gYml0bWFzayAmIFdSQVBfQklORF9LRVlfRkxBRyxcbiAgICAgICAgICBpc0N1cnJpZWQgPSBiaXRtYXNrICYgKFdSQVBfQ1VSUllfRkxBRyB8IFdSQVBfQ1VSUllfUklHSFRfRkxBRyksXG4gICAgICAgICAgaXNGbGlwID0gYml0bWFzayAmIFdSQVBfRkxJUF9GTEFHLFxuICAgICAgICAgIEN0b3IgPSBpc0JpbmRLZXkgPyB1bmRlZmluZWQgOiBjcmVhdGVDdG9yKGZ1bmMpO1xuXG4gICAgICBmdW5jdGlvbiB3cmFwcGVyKCkge1xuICAgICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCxcbiAgICAgICAgICAgIGFyZ3MgPSBBcnJheShsZW5ndGgpLFxuICAgICAgICAgICAgaW5kZXggPSBsZW5ndGg7XG5cbiAgICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgICBhcmdzW2luZGV4XSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzQ3VycmllZCkge1xuICAgICAgICAgIHZhciBwbGFjZWhvbGRlciA9IGdldEhvbGRlcih3cmFwcGVyKSxcbiAgICAgICAgICAgICAgaG9sZGVyc0NvdW50ID0gY291bnRIb2xkZXJzKGFyZ3MsIHBsYWNlaG9sZGVyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFydGlhbHMpIHtcbiAgICAgICAgICBhcmdzID0gY29tcG9zZUFyZ3MoYXJncywgcGFydGlhbHMsIGhvbGRlcnMsIGlzQ3VycmllZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnRpYWxzUmlnaHQpIHtcbiAgICAgICAgICBhcmdzID0gY29tcG9zZUFyZ3NSaWdodChhcmdzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsIGlzQ3VycmllZCk7XG4gICAgICAgIH1cbiAgICAgICAgbGVuZ3RoIC09IGhvbGRlcnNDb3VudDtcbiAgICAgICAgaWYgKGlzQ3VycmllZCAmJiBsZW5ndGggPCBhcml0eSkge1xuICAgICAgICAgIHZhciBuZXdIb2xkZXJzID0gcmVwbGFjZUhvbGRlcnMoYXJncywgcGxhY2Vob2xkZXIpO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVSZWN1cnJ5KFxuICAgICAgICAgICAgZnVuYywgYml0bWFzaywgY3JlYXRlSHlicmlkLCB3cmFwcGVyLnBsYWNlaG9sZGVyLCB0aGlzQXJnLFxuICAgICAgICAgICAgYXJncywgbmV3SG9sZGVycywgYXJnUG9zLCBhcnksIGFyaXR5IC0gbGVuZ3RoXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdGhpc0JpbmRpbmcgPSBpc0JpbmQgPyB0aGlzQXJnIDogdGhpcyxcbiAgICAgICAgICAgIGZuID0gaXNCaW5kS2V5ID8gdGhpc0JpbmRpbmdbZnVuY10gOiBmdW5jO1xuXG4gICAgICAgIGxlbmd0aCA9IGFyZ3MubGVuZ3RoO1xuICAgICAgICBpZiAoYXJnUG9zKSB7XG4gICAgICAgICAgYXJncyA9IHJlb3JkZXIoYXJncywgYXJnUG9zKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0ZsaXAgJiYgbGVuZ3RoID4gMSkge1xuICAgICAgICAgIGFyZ3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0FyeSAmJiBhcnkgPCBsZW5ndGgpIHtcbiAgICAgICAgICBhcmdzLmxlbmd0aCA9IGFyeTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcyAmJiB0aGlzICE9PSByb290ICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSB7XG4gICAgICAgICAgZm4gPSBDdG9yIHx8IGNyZWF0ZUN0b3IoZm4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gbGlrZSBgXy5pbnZlcnRCeWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHNldHRlciBUaGUgZnVuY3Rpb24gdG8gc2V0IGFjY3VtdWxhdG9yIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB0b0l0ZXJhdGVlIFRoZSBmdW5jdGlvbiB0byByZXNvbHZlIGl0ZXJhdGVlcy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBpbnZlcnRlciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVJbnZlcnRlcihzZXR0ZXIsIHRvSXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICAgIHJldHVybiBiYXNlSW52ZXJ0ZXIob2JqZWN0LCBzZXR0ZXIsIHRvSXRlcmF0ZWUoaXRlcmF0ZWUpLCB7fSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHBlcmZvcm1zIGEgbWF0aGVtYXRpY2FsIG9wZXJhdGlvbiBvbiB0d28gdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcGVyYXRvciBUaGUgZnVuY3Rpb24gdG8gcGVyZm9ybSB0aGUgb3BlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZGVmYXVsdFZhbHVlXSBUaGUgdmFsdWUgdXNlZCBmb3IgYHVuZGVmaW5lZGAgYXJndW1lbnRzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IG1hdGhlbWF0aWNhbCBvcGVyYXRpb24gZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlTWF0aE9wZXJhdGlvbihvcGVyYXRvciwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIG90aGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG90aGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBvdGhlcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyB8fCB0eXBlb2Ygb3RoZXIgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYmFzZVRvU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgIG90aGVyID0gYmFzZVRvU3RyaW5nKG90aGVyKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWUgPSBiYXNlVG9OdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgb3RoZXIgPSBiYXNlVG9OdW1iZXIob3RoZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSBvcGVyYXRvcih2YWx1ZSwgb3RoZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBsaWtlIGBfLm92ZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBhcnJheUZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBpdGVyYXRlZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgb3ZlciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVPdmVyKGFycmF5RnVuYykge1xuICAgICAgcmV0dXJuIGZsYXRSZXN0KGZ1bmN0aW9uKGl0ZXJhdGVlcykge1xuICAgICAgICBpdGVyYXRlZXMgPSBhcnJheU1hcChpdGVyYXRlZXMsIGJhc2VVbmFyeShnZXRJdGVyYXRlZSgpKSk7XG4gICAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICAgICAgdmFyIHRoaXNBcmcgPSB0aGlzO1xuICAgICAgICAgIHJldHVybiBhcnJheUZ1bmMoaXRlcmF0ZWVzLCBmdW5jdGlvbihpdGVyYXRlZSkge1xuICAgICAgICAgICAgcmV0dXJuIGFwcGx5KGl0ZXJhdGVlLCB0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIHRoZSBwYWRkaW5nIGZvciBgc3RyaW5nYCBiYXNlZCBvbiBgbGVuZ3RoYC4gVGhlIGBjaGFyc2Agc3RyaW5nXG4gICAgICogaXMgdHJ1bmNhdGVkIGlmIHRoZSBudW1iZXIgb2YgY2hhcmFjdGVycyBleGNlZWRzIGBsZW5ndGhgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGVuZ3RoIFRoZSBwYWRkaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPScgJ10gVGhlIHN0cmluZyB1c2VkIGFzIHBhZGRpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcGFkZGluZyBmb3IgYHN0cmluZ2AuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUGFkZGluZyhsZW5ndGgsIGNoYXJzKSB7XG4gICAgICBjaGFycyA9IGNoYXJzID09PSB1bmRlZmluZWQgPyAnICcgOiBiYXNlVG9TdHJpbmcoY2hhcnMpO1xuXG4gICAgICB2YXIgY2hhcnNMZW5ndGggPSBjaGFycy5sZW5ndGg7XG4gICAgICBpZiAoY2hhcnNMZW5ndGggPCAyKSB7XG4gICAgICAgIHJldHVybiBjaGFyc0xlbmd0aCA/IGJhc2VSZXBlYXQoY2hhcnMsIGxlbmd0aCkgOiBjaGFycztcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSBiYXNlUmVwZWF0KGNoYXJzLCBuYXRpdmVDZWlsKGxlbmd0aCAvIHN0cmluZ1NpemUoY2hhcnMpKSk7XG4gICAgICByZXR1cm4gaGFzVW5pY29kZShjaGFycylcbiAgICAgICAgPyBjYXN0U2xpY2Uoc3RyaW5nVG9BcnJheShyZXN1bHQpLCAwLCBsZW5ndGgpLmpvaW4oJycpXG4gICAgICAgIDogcmVzdWx0LnNsaWNlKDAsIGxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGludm9rZSBpdCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZ1xuICAgICAqIG9mIGB0aGlzQXJnYCBhbmQgYHBhcnRpYWxzYCBwcmVwZW5kZWQgdG8gdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7Kn0gdGhpc0FyZyBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0b1xuICAgICAqICB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUGFydGlhbChmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscykge1xuICAgICAgdmFyIGlzQmluZCA9IGJpdG1hc2sgJiBXUkFQX0JJTkRfRkxBRyxcbiAgICAgICAgICBDdG9yID0gY3JlYXRlQ3RvcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgICAgICAgYXJnc0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgICAgICBsZWZ0SW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgICAgICBhcmdzID0gQXJyYXkobGVmdExlbmd0aCArIGFyZ3NMZW5ndGgpLFxuICAgICAgICAgICAgZm4gPSAodGhpcyAmJiB0aGlzICE9PSByb290ICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSA/IEN0b3IgOiBmdW5jO1xuXG4gICAgICAgIHdoaWxlICgrK2xlZnRJbmRleCA8IGxlZnRMZW5ndGgpIHtcbiAgICAgICAgICBhcmdzW2xlZnRJbmRleF0gPSBwYXJ0aWFsc1tsZWZ0SW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChhcmdzTGVuZ3RoLS0pIHtcbiAgICAgICAgICBhcmdzW2xlZnRJbmRleCsrXSA9IGFyZ3VtZW50c1srK2FyZ3NJbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFwcGx5KGZuLCBpc0JpbmQgPyB0aGlzQXJnIDogdGhpcywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8ucmFuZ2VgIG9yIGBfLnJhbmdlUmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByYW5nZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSYW5nZShmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihzdGFydCwgZW5kLCBzdGVwKSB7XG4gICAgICAgIGlmIChzdGVwICYmIHR5cGVvZiBzdGVwICE9ICdudW1iZXInICYmIGlzSXRlcmF0ZWVDYWxsKHN0YXJ0LCBlbmQsIHN0ZXApKSB7XG4gICAgICAgICAgZW5kID0gc3RlcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBFbnN1cmUgdGhlIHNpZ24gb2YgYC0wYCBpcyBwcmVzZXJ2ZWQuXG4gICAgICAgIHN0YXJ0ID0gdG9GaW5pdGUoc3RhcnQpO1xuICAgICAgICBpZiAoZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW5kID0gdG9GaW5pdGUoZW5kKTtcbiAgICAgICAgfVxuICAgICAgICBzdGVwID0gc3RlcCA9PT0gdW5kZWZpbmVkID8gKHN0YXJ0IDwgZW5kID8gMSA6IC0xKSA6IHRvRmluaXRlKHN0ZXApO1xuICAgICAgICByZXR1cm4gYmFzZVJhbmdlKHN0YXJ0LCBlbmQsIHN0ZXAsIGZyb21SaWdodCk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHBlcmZvcm1zIGEgcmVsYXRpb25hbCBvcGVyYXRpb24gb24gdHdvIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3BlcmF0b3IgVGhlIGZ1bmN0aW9uIHRvIHBlcmZvcm0gdGhlIG9wZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZWxhdGlvbmFsIG9wZXJhdGlvbiBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSZWxhdGlvbmFsT3BlcmF0aW9uKG9wZXJhdG9yKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICAgIGlmICghKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyAmJiB0eXBlb2Ygb3RoZXIgPT0gJ3N0cmluZycpKSB7XG4gICAgICAgICAgdmFsdWUgPSB0b051bWJlcih2YWx1ZSk7XG4gICAgICAgICAgb3RoZXIgPSB0b051bWJlcihvdGhlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9wZXJhdG9yKHZhbHVlLCBvdGhlcik7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdyYXBzIGBmdW5jYCB0byBjb250aW51ZSBjdXJyeWluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdyYXBGdW5jIFRoZSBmdW5jdGlvbiB0byBjcmVhdGUgdGhlIGBmdW5jYCB3cmFwcGVyLlxuICAgICAqIEBwYXJhbSB7Kn0gcGxhY2Vob2xkZXIgVGhlIHBsYWNlaG9sZGVyIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2UgcHJvdmlkZWQgdG9cbiAgICAgKiAgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSZWN1cnJ5KGZ1bmMsIGJpdG1hc2ssIHdyYXBGdW5jLCBwbGFjZWhvbGRlciwgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMsIGFyZ1BvcywgYXJ5LCBhcml0eSkge1xuICAgICAgdmFyIGlzQ3VycnkgPSBiaXRtYXNrICYgV1JBUF9DVVJSWV9GTEFHLFxuICAgICAgICAgIG5ld0hvbGRlcnMgPSBpc0N1cnJ5ID8gaG9sZGVycyA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBuZXdIb2xkZXJzUmlnaHQgPSBpc0N1cnJ5ID8gdW5kZWZpbmVkIDogaG9sZGVycyxcbiAgICAgICAgICBuZXdQYXJ0aWFscyA9IGlzQ3VycnkgPyBwYXJ0aWFscyA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBuZXdQYXJ0aWFsc1JpZ2h0ID0gaXNDdXJyeSA/IHVuZGVmaW5lZCA6IHBhcnRpYWxzO1xuXG4gICAgICBiaXRtYXNrIHw9IChpc0N1cnJ5ID8gV1JBUF9QQVJUSUFMX0ZMQUcgOiBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRyk7XG4gICAgICBiaXRtYXNrICY9IH4oaXNDdXJyeSA/IFdSQVBfUEFSVElBTF9SSUdIVF9GTEFHIDogV1JBUF9QQVJUSUFMX0ZMQUcpO1xuXG4gICAgICBpZiAoIShiaXRtYXNrICYgV1JBUF9DVVJSWV9CT1VORF9GTEFHKSkge1xuICAgICAgICBiaXRtYXNrICY9IH4oV1JBUF9CSU5EX0ZMQUcgfCBXUkFQX0JJTkRfS0VZX0ZMQUcpO1xuICAgICAgfVxuICAgICAgdmFyIG5ld0RhdGEgPSBbXG4gICAgICAgIGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIG5ld1BhcnRpYWxzLCBuZXdIb2xkZXJzLCBuZXdQYXJ0aWFsc1JpZ2h0LFxuICAgICAgICBuZXdIb2xkZXJzUmlnaHQsIGFyZ1BvcywgYXJ5LCBhcml0eVxuICAgICAgXTtcblxuICAgICAgdmFyIHJlc3VsdCA9IHdyYXBGdW5jLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG4gICAgICBpZiAoaXNMYXppYWJsZShmdW5jKSkge1xuICAgICAgICBzZXREYXRhKHJlc3VsdCwgbmV3RGF0YSk7XG4gICAgICB9XG4gICAgICByZXN1bHQucGxhY2Vob2xkZXIgPSBwbGFjZWhvbGRlcjtcbiAgICAgIHJldHVybiBzZXRXcmFwVG9TdHJpbmcocmVzdWx0LCBmdW5jLCBiaXRtYXNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gbGlrZSBgXy5yb3VuZGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIFRoZSBuYW1lIG9mIHRoZSBgTWF0aGAgbWV0aG9kIHRvIHVzZSB3aGVuIHJvdW5kaW5nLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJvdW5kIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVJvdW5kKG1ldGhvZE5hbWUpIHtcbiAgICAgIHZhciBmdW5jID0gTWF0aFttZXRob2ROYW1lXTtcbiAgICAgIHJldHVybiBmdW5jdGlvbihudW1iZXIsIHByZWNpc2lvbikge1xuICAgICAgICBudW1iZXIgPSB0b051bWJlcihudW1iZXIpO1xuICAgICAgICBwcmVjaXNpb24gPSBwcmVjaXNpb24gPT0gbnVsbCA/IDAgOiBuYXRpdmVNaW4odG9JbnRlZ2VyKHByZWNpc2lvbiksIDI5Mik7XG4gICAgICAgIGlmIChwcmVjaXNpb24gJiYgbmF0aXZlSXNGaW5pdGUobnVtYmVyKSkge1xuICAgICAgICAgIC8vIFNoaWZ0IHdpdGggZXhwb25lbnRpYWwgbm90YXRpb24gdG8gYXZvaWQgZmxvYXRpbmctcG9pbnQgaXNzdWVzLlxuICAgICAgICAgIC8vIFNlZSBbTUROXShodHRwczovL21kbi5pby9yb3VuZCNFeGFtcGxlcykgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgICB2YXIgcGFpciA9ICh0b1N0cmluZyhudW1iZXIpICsgJ2UnKS5zcGxpdCgnZScpLFxuICAgICAgICAgICAgICB2YWx1ZSA9IGZ1bmMocGFpclswXSArICdlJyArICgrcGFpclsxXSArIHByZWNpc2lvbikpO1xuXG4gICAgICAgICAgcGFpciA9ICh0b1N0cmluZyh2YWx1ZSkgKyAnZScpLnNwbGl0KCdlJyk7XG4gICAgICAgICAgcmV0dXJuICsocGFpclswXSArICdlJyArICgrcGFpclsxXSAtIHByZWNpc2lvbikpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jKG51bWJlcik7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzZXQgb2JqZWN0IG9mIGB2YWx1ZXNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byBhZGQgdG8gdGhlIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgc2V0LlxuICAgICAqL1xuICAgIHZhciBjcmVhdGVTZXQgPSAhKFNldCAmJiAoMSAvIHNldFRvQXJyYXkobmV3IFNldChbLC0wXSkpWzFdKSA9PSBJTkZJTklUWSkgPyBub29wIDogZnVuY3Rpb24odmFsdWVzKSB7XG4gICAgICByZXR1cm4gbmV3IFNldCh2YWx1ZXMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8udG9QYWlyc2Agb3IgYF8udG9QYWlyc0luYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0ga2V5c0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5cyBvZiBhIGdpdmVuIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBwYWlycyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVUb1BhaXJzKGtleXNGdW5jKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHZhciB0YWcgPSBnZXRUYWcob2JqZWN0KTtcbiAgICAgICAgaWYgKHRhZyA9PSBtYXBUYWcpIHtcbiAgICAgICAgICByZXR1cm4gbWFwVG9BcnJheShvYmplY3QpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0YWcgPT0gc2V0VGFnKSB7XG4gICAgICAgICAgcmV0dXJuIHNldFRvUGFpcnMob2JqZWN0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmFzZVRvUGFpcnMob2JqZWN0LCBrZXlzRnVuYyhvYmplY3QpKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgZWl0aGVyIGN1cnJpZXMgb3IgaW52b2tlcyBgZnVuY2Agd2l0aCBvcHRpb25hbFxuICAgICAqIGB0aGlzYCBiaW5kaW5nIGFuZCBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258c3RyaW5nfSBmdW5jIFRoZSBmdW5jdGlvbiBvciBtZXRob2QgbmFtZSB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLlxuICAgICAqICAgIDEgLSBgXy5iaW5kYFxuICAgICAqICAgIDIgLSBgXy5iaW5kS2V5YFxuICAgICAqICAgIDQgLSBgXy5jdXJyeWAgb3IgYF8uY3VycnlSaWdodGAgb2YgYSBib3VuZCBmdW5jdGlvblxuICAgICAqICAgIDggLSBgXy5jdXJyeWBcbiAgICAgKiAgIDE2IC0gYF8uY3VycnlSaWdodGBcbiAgICAgKiAgIDMyIC0gYF8ucGFydGlhbGBcbiAgICAgKiAgIDY0IC0gYF8ucGFydGlhbFJpZ2h0YFxuICAgICAqICAxMjggLSBgXy5yZWFyZ2BcbiAgICAgKiAgMjU2IC0gYF8uYXJ5YFxuICAgICAqICA1MTIgLSBgXy5mbGlwYFxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzXSBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcmdQb3NdIFRoZSBhcmd1bWVudCBwb3NpdGlvbnMgb2YgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyeV0gVGhlIGFyaXR5IGNhcCBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eV0gVGhlIGFyaXR5IG9mIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVdyYXAoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMsIGFyZ1BvcywgYXJ5LCBhcml0eSkge1xuICAgICAgdmFyIGlzQmluZEtleSA9IGJpdG1hc2sgJiBXUkFQX0JJTkRfS0VZX0ZMQUc7XG4gICAgICBpZiAoIWlzQmluZEtleSAmJiB0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSBwYXJ0aWFscyA/IHBhcnRpYWxzLmxlbmd0aCA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICBiaXRtYXNrICY9IH4oV1JBUF9QQVJUSUFMX0ZMQUcgfCBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRyk7XG4gICAgICAgIHBhcnRpYWxzID0gaG9sZGVycyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGFyeSA9IGFyeSA9PT0gdW5kZWZpbmVkID8gYXJ5IDogbmF0aXZlTWF4KHRvSW50ZWdlcihhcnkpLCAwKTtcbiAgICAgIGFyaXR5ID0gYXJpdHkgPT09IHVuZGVmaW5lZCA/IGFyaXR5IDogdG9JbnRlZ2VyKGFyaXR5KTtcbiAgICAgIGxlbmd0aCAtPSBob2xkZXJzID8gaG9sZGVycy5sZW5ndGggOiAwO1xuXG4gICAgICBpZiAoYml0bWFzayAmIFdSQVBfUEFSVElBTF9SSUdIVF9GTEFHKSB7XG4gICAgICAgIHZhciBwYXJ0aWFsc1JpZ2h0ID0gcGFydGlhbHMsXG4gICAgICAgICAgICBob2xkZXJzUmlnaHQgPSBob2xkZXJzO1xuXG4gICAgICAgIHBhcnRpYWxzID0gaG9sZGVycyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHZhciBkYXRhID0gaXNCaW5kS2V5ID8gdW5kZWZpbmVkIDogZ2V0RGF0YShmdW5jKTtcblxuICAgICAgdmFyIG5ld0RhdGEgPSBbXG4gICAgICAgIGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsXG4gICAgICAgIGFyZ1BvcywgYXJ5LCBhcml0eVxuICAgICAgXTtcblxuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgbWVyZ2VEYXRhKG5ld0RhdGEsIGRhdGEpO1xuICAgICAgfVxuICAgICAgZnVuYyA9IG5ld0RhdGFbMF07XG4gICAgICBiaXRtYXNrID0gbmV3RGF0YVsxXTtcbiAgICAgIHRoaXNBcmcgPSBuZXdEYXRhWzJdO1xuICAgICAgcGFydGlhbHMgPSBuZXdEYXRhWzNdO1xuICAgICAgaG9sZGVycyA9IG5ld0RhdGFbNF07XG4gICAgICBhcml0eSA9IG5ld0RhdGFbOV0gPSBuZXdEYXRhWzldID09PSB1bmRlZmluZWRcbiAgICAgICAgPyAoaXNCaW5kS2V5ID8gMCA6IGZ1bmMubGVuZ3RoKVxuICAgICAgICA6IG5hdGl2ZU1heChuZXdEYXRhWzldIC0gbGVuZ3RoLCAwKTtcblxuICAgICAgaWYgKCFhcml0eSAmJiBiaXRtYXNrICYgKFdSQVBfQ1VSUllfRkxBRyB8IFdSQVBfQ1VSUllfUklHSFRfRkxBRykpIHtcbiAgICAgICAgYml0bWFzayAmPSB+KFdSQVBfQ1VSUllfRkxBRyB8IFdSQVBfQ1VSUllfUklHSFRfRkxBRyk7XG4gICAgICB9XG4gICAgICBpZiAoIWJpdG1hc2sgfHwgYml0bWFzayA9PSBXUkFQX0JJTkRfRkxBRykge1xuICAgICAgICB2YXIgcmVzdWx0ID0gY3JlYXRlQmluZChmdW5jLCBiaXRtYXNrLCB0aGlzQXJnKTtcbiAgICAgIH0gZWxzZSBpZiAoYml0bWFzayA9PSBXUkFQX0NVUlJZX0ZMQUcgfHwgYml0bWFzayA9PSBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcpIHtcbiAgICAgICAgcmVzdWx0ID0gY3JlYXRlQ3VycnkoZnVuYywgYml0bWFzaywgYXJpdHkpO1xuICAgICAgfSBlbHNlIGlmICgoYml0bWFzayA9PSBXUkFQX1BBUlRJQUxfRkxBRyB8fCBiaXRtYXNrID09IChXUkFQX0JJTkRfRkxBRyB8IFdSQVBfUEFSVElBTF9GTEFHKSkgJiYgIWhvbGRlcnMubGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZVBhcnRpYWwoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0ID0gY3JlYXRlSHlicmlkLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG4gICAgICB9XG4gICAgICB2YXIgc2V0dGVyID0gZGF0YSA/IGJhc2VTZXREYXRhIDogc2V0RGF0YTtcbiAgICAgIHJldHVybiBzZXRXcmFwVG9TdHJpbmcoc2V0dGVyKHJlc3VsdCwgbmV3RGF0YSksIGZ1bmMsIGJpdG1hc2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8uZGVmYXVsdHNgIHRvIGN1c3RvbWl6ZSBpdHMgYF8uYXNzaWduSW5gIHVzZSB0byBhc3NpZ24gcHJvcGVydGllc1xuICAgICAqIG9mIHNvdXJjZSBvYmplY3RzIHRvIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QgZm9yIGFsbCBkZXN0aW5hdGlvbiBwcm9wZXJ0aWVzXG4gICAgICogdGhhdCByZXNvbHZlIHRvIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IG9ialZhbHVlIFRoZSBkZXN0aW5hdGlvbiB2YWx1ZS5cbiAgICAgKiBAcGFyYW0geyp9IHNyY1ZhbHVlIFRoZSBzb3VyY2UgdmFsdWUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBhc3NpZ24uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgcGFyZW50IG9iamVjdCBvZiBgb2JqVmFsdWVgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3VzdG9tRGVmYXVsdHNBc3NpZ25JbihvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0KSB7XG4gICAgICBpZiAob2JqVmFsdWUgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgIChlcShvYmpWYWx1ZSwgb2JqZWN0UHJvdG9ba2V5XSkgJiYgIWhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSkge1xuICAgICAgICByZXR1cm4gc3JjVmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCBieSBgXy5kZWZhdWx0c0RlZXBgIHRvIGN1c3RvbWl6ZSBpdHMgYF8ubWVyZ2VgIHVzZSB0byBtZXJnZSBzb3VyY2VcbiAgICAgKiBvYmplY3RzIGludG8gZGVzdGluYXRpb24gb2JqZWN0cyB0aGF0IGFyZSBwYXNzZWQgdGhydS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSBvYmpWYWx1ZSBUaGUgZGVzdGluYXRpb24gdmFsdWUuXG4gICAgICogQHBhcmFtIHsqfSBzcmNWYWx1ZSBUaGUgc291cmNlIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gbWVyZ2UuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgcGFyZW50IG9iamVjdCBvZiBgb2JqVmFsdWVgLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHBhcmVudCBvYmplY3Qgb2YgYHNyY1ZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIHNvdXJjZSB2YWx1ZXMgYW5kIHRoZWlyIG1lcmdlZFxuICAgICAqICBjb3VudGVycGFydHMuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHZhbHVlIHRvIGFzc2lnbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjdXN0b21EZWZhdWx0c01lcmdlKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSwgc3RhY2spIHtcbiAgICAgIGlmIChpc09iamVjdChvYmpWYWx1ZSkgJiYgaXNPYmplY3Qoc3JjVmFsdWUpKSB7XG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IG1lcmdlIG9iamVjdHMgYW5kIGFycmF5cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICBzdGFjay5zZXQoc3JjVmFsdWUsIG9ialZhbHVlKTtcbiAgICAgICAgYmFzZU1lcmdlKG9ialZhbHVlLCBzcmNWYWx1ZSwgdW5kZWZpbmVkLCBjdXN0b21EZWZhdWx0c01lcmdlLCBzdGFjayk7XG4gICAgICAgIHN0YWNrWydkZWxldGUnXShzcmNWYWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCBieSBgXy5vbWl0YCB0byBjdXN0b21pemUgaXRzIGBfLmNsb25lRGVlcGAgdXNlIHRvIG9ubHkgY2xvbmUgcGxhaW5cbiAgICAgKiBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdW5jbG9uZWQgdmFsdWUgb3IgYHVuZGVmaW5lZGAgdG8gZGVmZXIgY2xvbmluZyB0byBgXy5jbG9uZURlZXBgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGN1c3RvbU9taXRDbG9uZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzUGxhaW5PYmplY3QodmFsdWUpID8gdW5kZWZpbmVkIDogdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbERlZXBgIGZvciBhcnJheXMgd2l0aCBzdXBwb3J0IGZvclxuICAgICAqIHBhcnRpYWwgZGVlcCBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtBcnJheX0gb3RoZXIgVGhlIG90aGVyIGFycmF5IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3RhY2sgVHJhY2tzIHRyYXZlcnNlZCBgYXJyYXlgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBhcnJheXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcXVhbEFycmF5cyhhcnJheSwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spIHtcbiAgICAgIHZhciBpc1BhcnRpYWwgPSBiaXRtYXNrICYgQ09NUEFSRV9QQVJUSUFMX0ZMQUcsXG4gICAgICAgICAgYXJyTGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIG90aExlbmd0aCA9IG90aGVyLmxlbmd0aDtcblxuICAgICAgaWYgKGFyckxlbmd0aCAhPSBvdGhMZW5ndGggJiYgIShpc1BhcnRpYWwgJiYgb3RoTGVuZ3RoID4gYXJyTGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICAvLyBDaGVjayB0aGF0IGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICAgICAgdmFyIGFyclN0YWNrZWQgPSBzdGFjay5nZXQoYXJyYXkpO1xuICAgICAgdmFyIG90aFN0YWNrZWQgPSBzdGFjay5nZXQob3RoZXIpO1xuICAgICAgaWYgKGFyclN0YWNrZWQgJiYgb3RoU3RhY2tlZCkge1xuICAgICAgICByZXR1cm4gYXJyU3RhY2tlZCA9PSBvdGhlciAmJiBvdGhTdGFja2VkID09IGFycmF5O1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gdHJ1ZSxcbiAgICAgICAgICBzZWVuID0gKGJpdG1hc2sgJiBDT01QQVJFX1VOT1JERVJFRF9GTEFHKSA/IG5ldyBTZXRDYWNoZSA6IHVuZGVmaW5lZDtcblxuICAgICAgc3RhY2suc2V0KGFycmF5LCBvdGhlcik7XG4gICAgICBzdGFjay5zZXQob3RoZXIsIGFycmF5KTtcblxuICAgICAgLy8gSWdub3JlIG5vbi1pbmRleCBwcm9wZXJ0aWVzLlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBhcnJMZW5ndGgpIHtcbiAgICAgICAgdmFyIGFyclZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgb3RoVmFsdWUgPSBvdGhlcltpbmRleF07XG5cbiAgICAgICAgaWYgKGN1c3RvbWl6ZXIpIHtcbiAgICAgICAgICB2YXIgY29tcGFyZWQgPSBpc1BhcnRpYWxcbiAgICAgICAgICAgID8gY3VzdG9taXplcihvdGhWYWx1ZSwgYXJyVmFsdWUsIGluZGV4LCBvdGhlciwgYXJyYXksIHN0YWNrKVxuICAgICAgICAgICAgOiBjdXN0b21pemVyKGFyclZhbHVlLCBvdGhWYWx1ZSwgaW5kZXgsIGFycmF5LCBvdGhlciwgc3RhY2spO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb21wYXJlZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKGNvbXBhcmVkKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgaWYgKHNlZW4pIHtcbiAgICAgICAgICBpZiAoIWFycmF5U29tZShvdGhlciwgZnVuY3Rpb24ob3RoVmFsdWUsIG90aEluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFjYWNoZUhhcyhzZWVuLCBvdGhJbmRleCkgJiZcbiAgICAgICAgICAgICAgICAgICAgKGFyclZhbHVlID09PSBvdGhWYWx1ZSB8fCBlcXVhbEZ1bmMoYXJyVmFsdWUsIG90aFZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaykpKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gc2Vlbi5wdXNoKG90aEluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICghKFxuICAgICAgICAgICAgICBhcnJWYWx1ZSA9PT0gb3RoVmFsdWUgfHxcbiAgICAgICAgICAgICAgICBlcXVhbEZ1bmMoYXJyVmFsdWUsIG90aFZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaylcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgc3RhY2tbJ2RlbGV0ZSddKGFycmF5KTtcbiAgICAgIHN0YWNrWydkZWxldGUnXShvdGhlcik7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3IgY29tcGFyaW5nIG9iamVjdHMgb2ZcbiAgICAgKiB0aGUgc2FtZSBgdG9TdHJpbmdUYWdgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gb25seSBzdXBwb3J0cyBjb21wYXJpbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICAgICAqIGBCb29sZWFuYCwgYERhdGVgLCBgRXJyb3JgLCBgTnVtYmVyYCwgYFJlZ0V4cGAsIG9yIGBTdHJpbmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdHMgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjdXN0b21pemVyIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzdGFjayBUcmFja3MgdHJhdmVyc2VkIGBvYmplY3RgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBvYmplY3RzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXF1YWxCeVRhZyhvYmplY3QsIG90aGVyLCB0YWcsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spIHtcbiAgICAgIHN3aXRjaCAodGFnKSB7XG4gICAgICAgIGNhc2UgZGF0YVZpZXdUYWc6XG4gICAgICAgICAgaWYgKChvYmplY3QuYnl0ZUxlbmd0aCAhPSBvdGhlci5ieXRlTGVuZ3RoKSB8fFxuICAgICAgICAgICAgICAob2JqZWN0LmJ5dGVPZmZzZXQgIT0gb3RoZXIuYnl0ZU9mZnNldCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgb2JqZWN0ID0gb2JqZWN0LmJ1ZmZlcjtcbiAgICAgICAgICBvdGhlciA9IG90aGVyLmJ1ZmZlcjtcblxuICAgICAgICBjYXNlIGFycmF5QnVmZmVyVGFnOlxuICAgICAgICAgIGlmICgob2JqZWN0LmJ5dGVMZW5ndGggIT0gb3RoZXIuYnl0ZUxlbmd0aCkgfHxcbiAgICAgICAgICAgICAgIWVxdWFsRnVuYyhuZXcgVWludDhBcnJheShvYmplY3QpLCBuZXcgVWludDhBcnJheShvdGhlcikpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0cnVlO1xuXG4gICAgICAgIGNhc2UgYm9vbFRhZzpcbiAgICAgICAgY2FzZSBkYXRlVGFnOlxuICAgICAgICBjYXNlIG51bWJlclRhZzpcbiAgICAgICAgICAvLyBDb2VyY2UgYm9vbGVhbnMgdG8gYDFgIG9yIGAwYCBhbmQgZGF0ZXMgdG8gbWlsbGlzZWNvbmRzLlxuICAgICAgICAgIC8vIEludmFsaWQgZGF0ZXMgYXJlIGNvZXJjZWQgdG8gYE5hTmAuXG4gICAgICAgICAgcmV0dXJuIGVxKCtvYmplY3QsICtvdGhlcik7XG5cbiAgICAgICAgY2FzZSBlcnJvclRhZzpcbiAgICAgICAgICByZXR1cm4gb2JqZWN0Lm5hbWUgPT0gb3RoZXIubmFtZSAmJiBvYmplY3QubWVzc2FnZSA9PSBvdGhlci5tZXNzYWdlO1xuXG4gICAgICAgIGNhc2UgcmVnZXhwVGFnOlxuICAgICAgICBjYXNlIHN0cmluZ1RhZzpcbiAgICAgICAgICAvLyBDb2VyY2UgcmVnZXhlcyB0byBzdHJpbmdzIGFuZCB0cmVhdCBzdHJpbmdzLCBwcmltaXRpdmVzIGFuZCBvYmplY3RzLFxuICAgICAgICAgIC8vIGFzIGVxdWFsLiBTZWUgaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXJlZ2V4cC5wcm90b3R5cGUudG9zdHJpbmdcbiAgICAgICAgICAvLyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgICAgIHJldHVybiBvYmplY3QgPT0gKG90aGVyICsgJycpO1xuXG4gICAgICAgIGNhc2UgbWFwVGFnOlxuICAgICAgICAgIHZhciBjb252ZXJ0ID0gbWFwVG9BcnJheTtcblxuICAgICAgICBjYXNlIHNldFRhZzpcbiAgICAgICAgICB2YXIgaXNQYXJ0aWFsID0gYml0bWFzayAmIENPTVBBUkVfUEFSVElBTF9GTEFHO1xuICAgICAgICAgIGNvbnZlcnQgfHwgKGNvbnZlcnQgPSBzZXRUb0FycmF5KTtcblxuICAgICAgICAgIGlmIChvYmplY3Quc2l6ZSAhPSBvdGhlci5zaXplICYmICFpc1BhcnRpYWwpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQXNzdW1lIGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICAgICAgICAgIHZhciBzdGFja2VkID0gc3RhY2suZ2V0KG9iamVjdCk7XG4gICAgICAgICAgaWYgKHN0YWNrZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGFja2VkID09IG90aGVyO1xuICAgICAgICAgIH1cbiAgICAgICAgICBiaXRtYXNrIHw9IENPTVBBUkVfVU5PUkRFUkVEX0ZMQUc7XG5cbiAgICAgICAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgICBzdGFjay5zZXQob2JqZWN0LCBvdGhlcik7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGVxdWFsQXJyYXlzKGNvbnZlcnQob2JqZWN0KSwgY29udmVydChvdGhlciksIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spO1xuICAgICAgICAgIHN0YWNrWydkZWxldGUnXShvYmplY3QpO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG5cbiAgICAgICAgY2FzZSBzeW1ib2xUYWc6XG4gICAgICAgICAgaWYgKHN5bWJvbFZhbHVlT2YpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xWYWx1ZU9mLmNhbGwob2JqZWN0KSA9PSBzeW1ib2xWYWx1ZU9mLmNhbGwob3RoZXIpO1xuICAgICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIG9iamVjdHMgd2l0aCBzdXBwb3J0IGZvclxuICAgICAqIHBhcnRpYWwgZGVlcCBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjdXN0b21pemVyIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzdGFjayBUcmFja3MgdHJhdmVyc2VkIGBvYmplY3RgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBvYmplY3RzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXF1YWxPYmplY3RzKG9iamVjdCwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spIHtcbiAgICAgIHZhciBpc1BhcnRpYWwgPSBiaXRtYXNrICYgQ09NUEFSRV9QQVJUSUFMX0ZMQUcsXG4gICAgICAgICAgb2JqUHJvcHMgPSBnZXRBbGxLZXlzKG9iamVjdCksXG4gICAgICAgICAgb2JqTGVuZ3RoID0gb2JqUHJvcHMubGVuZ3RoLFxuICAgICAgICAgIG90aFByb3BzID0gZ2V0QWxsS2V5cyhvdGhlciksXG4gICAgICAgICAgb3RoTGVuZ3RoID0gb3RoUHJvcHMubGVuZ3RoO1xuXG4gICAgICBpZiAob2JqTGVuZ3RoICE9IG90aExlbmd0aCAmJiAhaXNQYXJ0aWFsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IG9iakxlbmd0aDtcbiAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgIHZhciBrZXkgPSBvYmpQcm9wc1tpbmRleF07XG4gICAgICAgIGlmICghKGlzUGFydGlhbCA/IGtleSBpbiBvdGhlciA6IGhhc093blByb3BlcnR5LmNhbGwob3RoZXIsIGtleSkpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBDaGVjayB0aGF0IGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICAgICAgdmFyIG9ialN0YWNrZWQgPSBzdGFjay5nZXQob2JqZWN0KTtcbiAgICAgIHZhciBvdGhTdGFja2VkID0gc3RhY2suZ2V0KG90aGVyKTtcbiAgICAgIGlmIChvYmpTdGFja2VkICYmIG90aFN0YWNrZWQpIHtcbiAgICAgICAgcmV0dXJuIG9ialN0YWNrZWQgPT0gb3RoZXIgJiYgb3RoU3RhY2tlZCA9PSBvYmplY3Q7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgIHN0YWNrLnNldChvYmplY3QsIG90aGVyKTtcbiAgICAgIHN0YWNrLnNldChvdGhlciwgb2JqZWN0KTtcblxuICAgICAgdmFyIHNraXBDdG9yID0gaXNQYXJ0aWFsO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBvYmpMZW5ndGgpIHtcbiAgICAgICAga2V5ID0gb2JqUHJvcHNbaW5kZXhdO1xuICAgICAgICB2YXIgb2JqVmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgICAgIG90aFZhbHVlID0gb3RoZXJba2V5XTtcblxuICAgICAgICBpZiAoY3VzdG9taXplcikge1xuICAgICAgICAgIHZhciBjb21wYXJlZCA9IGlzUGFydGlhbFxuICAgICAgICAgICAgPyBjdXN0b21pemVyKG90aFZhbHVlLCBvYmpWYWx1ZSwga2V5LCBvdGhlciwgb2JqZWN0LCBzdGFjaylcbiAgICAgICAgICAgIDogY3VzdG9taXplcihvYmpWYWx1ZSwgb3RoVmFsdWUsIGtleSwgb2JqZWN0LCBvdGhlciwgc3RhY2spO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICBpZiAoIShjb21wYXJlZCA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgID8gKG9ialZhbHVlID09PSBvdGhWYWx1ZSB8fCBlcXVhbEZ1bmMob2JqVmFsdWUsIG90aFZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaykpXG4gICAgICAgICAgICAgIDogY29tcGFyZWRcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBza2lwQ3RvciB8fCAoc2tpcEN0b3IgPSBrZXkgPT0gJ2NvbnN0cnVjdG9yJyk7XG4gICAgICB9XG4gICAgICBpZiAocmVzdWx0ICYmICFza2lwQ3Rvcikge1xuICAgICAgICB2YXIgb2JqQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcixcbiAgICAgICAgICAgIG90aEN0b3IgPSBvdGhlci5jb25zdHJ1Y3RvcjtcblxuICAgICAgICAvLyBOb24gYE9iamVjdGAgb2JqZWN0IGluc3RhbmNlcyB3aXRoIGRpZmZlcmVudCBjb25zdHJ1Y3RvcnMgYXJlIG5vdCBlcXVhbC5cbiAgICAgICAgaWYgKG9iakN0b3IgIT0gb3RoQ3RvciAmJlxuICAgICAgICAgICAgKCdjb25zdHJ1Y3RvcicgaW4gb2JqZWN0ICYmICdjb25zdHJ1Y3RvcicgaW4gb3RoZXIpICYmXG4gICAgICAgICAgICAhKHR5cGVvZiBvYmpDdG9yID09ICdmdW5jdGlvbicgJiYgb2JqQ3RvciBpbnN0YW5jZW9mIG9iakN0b3IgJiZcbiAgICAgICAgICAgICAgdHlwZW9mIG90aEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBvdGhDdG9yIGluc3RhbmNlb2Ygb3RoQ3RvcikpIHtcbiAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgc3RhY2tbJ2RlbGV0ZSddKG9iamVjdCk7XG4gICAgICBzdGFja1snZGVsZXRlJ10ob3RoZXIpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VSZXN0YCB3aGljaCBmbGF0dGVucyB0aGUgcmVzdCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXBwbHkgYSByZXN0IHBhcmFtZXRlciB0by5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGF0UmVzdChmdW5jKSB7XG4gICAgICByZXR1cm4gc2V0VG9TdHJpbmcob3ZlclJlc3QoZnVuYywgdW5kZWZpbmVkLCBmbGF0dGVuKSwgZnVuYyArICcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIGFuZCBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRBbGxLZXlzKG9iamVjdCkge1xuICAgICAgcmV0dXJuIGJhc2VHZXRBbGxLZXlzKG9iamVjdCwga2V5cywgZ2V0U3ltYm9scyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIGFuZFxuICAgICAqIHN5bWJvbHMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIGFuZCBzeW1ib2xzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldEFsbEtleXNJbihvYmplY3QpIHtcbiAgICAgIHJldHVybiBiYXNlR2V0QWxsS2V5cyhvYmplY3QsIGtleXNJbiwgZ2V0U3ltYm9sc0luKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIG1ldGFkYXRhIGZvciBgZnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBnZXREYXRhID0gIW1ldGFNYXAgPyBub29wIDogZnVuY3Rpb24oZnVuYykge1xuICAgICAgcmV0dXJuIG1ldGFNYXAuZ2V0KGZ1bmMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBuYW1lIG9mIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZnVuY3Rpb24gbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRGdW5jTmFtZShmdW5jKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gKGZ1bmMubmFtZSArICcnKSxcbiAgICAgICAgICBhcnJheSA9IHJlYWxOYW1lc1tyZXN1bHRdLFxuICAgICAgICAgIGxlbmd0aCA9IGhhc093blByb3BlcnR5LmNhbGwocmVhbE5hbWVzLCByZXN1bHQpID8gYXJyYXkubGVuZ3RoIDogMDtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBkYXRhID0gYXJyYXlbbGVuZ3RoXSxcbiAgICAgICAgICAgIG90aGVyRnVuYyA9IGRhdGEuZnVuYztcbiAgICAgICAgaWYgKG90aGVyRnVuYyA9PSBudWxsIHx8IG90aGVyRnVuYyA9PSBmdW5jKSB7XG4gICAgICAgICAgcmV0dXJuIGRhdGEubmFtZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBhcmd1bWVudCBwbGFjZWhvbGRlciB2YWx1ZSBmb3IgYGZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBwbGFjZWhvbGRlciB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRIb2xkZXIoZnVuYykge1xuICAgICAgdmFyIG9iamVjdCA9IGhhc093blByb3BlcnR5LmNhbGwobG9kYXNoLCAncGxhY2Vob2xkZXInKSA/IGxvZGFzaCA6IGZ1bmM7XG4gICAgICByZXR1cm4gb2JqZWN0LnBsYWNlaG9sZGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGFwcHJvcHJpYXRlIFwiaXRlcmF0ZWVcIiBmdW5jdGlvbi4gSWYgYF8uaXRlcmF0ZWVgIGlzIGN1c3RvbWl6ZWQsXG4gICAgICogdGhpcyBmdW5jdGlvbiByZXR1cm5zIHRoZSBjdXN0b20gbWV0aG9kLCBvdGhlcndpc2UgaXQgcmV0dXJucyBgYmFzZUl0ZXJhdGVlYC5cbiAgICAgKiBJZiBhcmd1bWVudHMgYXJlIHByb3ZpZGVkLCB0aGUgY2hvc2VuIGZ1bmN0aW9uIGlzIGludm9rZWQgd2l0aCB0aGVtIGFuZFxuICAgICAqIGl0cyByZXN1bHQgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gW3ZhbHVlXSBUaGUgdmFsdWUgdG8gY29udmVydCB0byBhbiBpdGVyYXRlZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5XSBUaGUgYXJpdHkgb2YgdGhlIGNyZWF0ZWQgaXRlcmF0ZWUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBjaG9zZW4gZnVuY3Rpb24gb3IgaXRzIHJlc3VsdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRJdGVyYXRlZSgpIHtcbiAgICAgIHZhciByZXN1bHQgPSBsb2Rhc2guaXRlcmF0ZWUgfHwgaXRlcmF0ZWU7XG4gICAgICByZXN1bHQgPSByZXN1bHQgPT09IGl0ZXJhdGVlID8gYmFzZUl0ZXJhdGVlIDogcmVzdWx0O1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyByZXN1bHQoYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0pIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGRhdGEgZm9yIGBtYXBgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbWFwIFRoZSBtYXAgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgcmVmZXJlbmNlIGtleS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWFwIGRhdGEuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWFwRGF0YShtYXAsIGtleSkge1xuICAgICAgdmFyIGRhdGEgPSBtYXAuX19kYXRhX187XG4gICAgICByZXR1cm4gaXNLZXlhYmxlKGtleSlcbiAgICAgICAgPyBkYXRhW3R5cGVvZiBrZXkgPT0gJ3N0cmluZycgPyAnc3RyaW5nJyA6ICdoYXNoJ11cbiAgICAgICAgOiBkYXRhLm1hcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwcm9wZXJ0eSBuYW1lcywgdmFsdWVzLCBhbmQgY29tcGFyZSBmbGFncyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbWF0Y2ggZGF0YSBvZiBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRNYXRjaERhdGEob2JqZWN0KSB7XG4gICAgICB2YXIgcmVzdWx0ID0ga2V5cyhvYmplY3QpLFxuICAgICAgICAgIGxlbmd0aCA9IHJlc3VsdC5sZW5ndGg7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIga2V5ID0gcmVzdWx0W2xlbmd0aF0sXG4gICAgICAgICAgICB2YWx1ZSA9IG9iamVjdFtrZXldO1xuXG4gICAgICAgIHJlc3VsdFtsZW5ndGhdID0gW2tleSwgdmFsdWUsIGlzU3RyaWN0Q29tcGFyYWJsZSh2YWx1ZSldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBuYXRpdmUgZnVuY3Rpb24gYXQgYGtleWAgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIG1ldGhvZCB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZ1bmN0aW9uIGlmIGl0J3MgbmF0aXZlLCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hdGl2ZShvYmplY3QsIGtleSkge1xuICAgICAgdmFyIHZhbHVlID0gZ2V0VmFsdWUob2JqZWN0LCBrZXkpO1xuICAgICAgcmV0dXJuIGJhc2VJc05hdGl2ZSh2YWx1ZSkgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VHZXRUYWdgIHdoaWNoIGlnbm9yZXMgYFN5bWJvbC50b1N0cmluZ1RhZ2AgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSByYXcgYHRvU3RyaW5nVGFnYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRSYXdUYWcodmFsdWUpIHtcbiAgICAgIHZhciBpc093biA9IGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIHN5bVRvU3RyaW5nVGFnKSxcbiAgICAgICAgICB0YWcgPSB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ107XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHZhbHVlW3N5bVRvU3RyaW5nVGFnXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdmFyIHVubWFza2VkID0gdHJ1ZTtcbiAgICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgIHZhciByZXN1bHQgPSBuYXRpdmVPYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgICAgIGlmICh1bm1hc2tlZCkge1xuICAgICAgICBpZiAoaXNPd24pIHtcbiAgICAgICAgICB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ10gPSB0YWc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGVsZXRlIHZhbHVlW3N5bVRvU3RyaW5nVGFnXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHRoZSBvd24gZW51bWVyYWJsZSBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBzeW1ib2xzLlxuICAgICAqL1xuICAgIHZhciBnZXRTeW1ib2xzID0gIW5hdGl2ZUdldFN5bWJvbHMgPyBzdHViQXJyYXkgOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBvYmplY3QgPSBPYmplY3Qob2JqZWN0KTtcbiAgICAgIHJldHVybiBhcnJheUZpbHRlcihuYXRpdmVHZXRTeW1ib2xzKG9iamVjdCksIGZ1bmN0aW9uKHN5bWJvbCkge1xuICAgICAgICByZXR1cm4gcHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmplY3QsIHN5bWJvbCk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBzeW1ib2xzLlxuICAgICAqL1xuICAgIHZhciBnZXRTeW1ib2xzSW4gPSAhbmF0aXZlR2V0U3ltYm9scyA/IHN0dWJBcnJheSA6IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgd2hpbGUgKG9iamVjdCkge1xuICAgICAgICBhcnJheVB1c2gocmVzdWx0LCBnZXRTeW1ib2xzKG9iamVjdCkpO1xuICAgICAgICBvYmplY3QgPSBnZXRQcm90b3R5cGUob2JqZWN0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGB0b1N0cmluZ1RhZ2Agb2YgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgYHRvU3RyaW5nVGFnYC5cbiAgICAgKi9cbiAgICB2YXIgZ2V0VGFnID0gYmFzZUdldFRhZztcblxuICAgIC8vIEZhbGxiYWNrIGZvciBkYXRhIHZpZXdzLCBtYXBzLCBzZXRzLCBhbmQgd2VhayBtYXBzIGluIElFIDExIGFuZCBwcm9taXNlcyBpbiBOb2RlLmpzIDwgNi5cbiAgICBpZiAoKERhdGFWaWV3ICYmIGdldFRhZyhuZXcgRGF0YVZpZXcobmV3IEFycmF5QnVmZmVyKDEpKSkgIT0gZGF0YVZpZXdUYWcpIHx8XG4gICAgICAgIChNYXAgJiYgZ2V0VGFnKG5ldyBNYXApICE9IG1hcFRhZykgfHxcbiAgICAgICAgKFByb21pc2UgJiYgZ2V0VGFnKFByb21pc2UucmVzb2x2ZSgpKSAhPSBwcm9taXNlVGFnKSB8fFxuICAgICAgICAoU2V0ICYmIGdldFRhZyhuZXcgU2V0KSAhPSBzZXRUYWcpIHx8XG4gICAgICAgIChXZWFrTWFwICYmIGdldFRhZyhuZXcgV2Vha01hcCkgIT0gd2Vha01hcFRhZykpIHtcbiAgICAgIGdldFRhZyA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBiYXNlR2V0VGFnKHZhbHVlKSxcbiAgICAgICAgICAgIEN0b3IgPSByZXN1bHQgPT0gb2JqZWN0VGFnID8gdmFsdWUuY29uc3RydWN0b3IgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBjdG9yU3RyaW5nID0gQ3RvciA/IHRvU291cmNlKEN0b3IpIDogJyc7XG5cbiAgICAgICAgaWYgKGN0b3JTdHJpbmcpIHtcbiAgICAgICAgICBzd2l0Y2ggKGN0b3JTdHJpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgZGF0YVZpZXdDdG9yU3RyaW5nOiByZXR1cm4gZGF0YVZpZXdUYWc7XG4gICAgICAgICAgICBjYXNlIG1hcEN0b3JTdHJpbmc6IHJldHVybiBtYXBUYWc7XG4gICAgICAgICAgICBjYXNlIHByb21pc2VDdG9yU3RyaW5nOiByZXR1cm4gcHJvbWlzZVRhZztcbiAgICAgICAgICAgIGNhc2Ugc2V0Q3RvclN0cmluZzogcmV0dXJuIHNldFRhZztcbiAgICAgICAgICAgIGNhc2Ugd2Vha01hcEN0b3JTdHJpbmc6IHJldHVybiB3ZWFrTWFwVGFnO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB2aWV3LCBhcHBseWluZyBhbnkgYHRyYW5zZm9ybXNgIHRvIHRoZSBgc3RhcnRgIGFuZCBgZW5kYCBwb3NpdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCBUaGUgc3RhcnQgb2YgdGhlIHZpZXcuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSB2aWV3LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHRyYW5zZm9ybXMgVGhlIHRyYW5zZm9ybWF0aW9ucyB0byBhcHBseSB0byB0aGUgdmlldy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBgc3RhcnRgIGFuZCBgZW5kYFxuICAgICAqICBwb3NpdGlvbnMgb2YgdGhlIHZpZXcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0VmlldyhzdGFydCwgZW5kLCB0cmFuc2Zvcm1zKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSB0cmFuc2Zvcm1zLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGRhdGEgPSB0cmFuc2Zvcm1zW2luZGV4XSxcbiAgICAgICAgICAgIHNpemUgPSBkYXRhLnNpemU7XG5cbiAgICAgICAgc3dpdGNoIChkYXRhLnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdkcm9wJzogICAgICBzdGFydCArPSBzaXplOyBicmVhaztcbiAgICAgICAgICBjYXNlICdkcm9wUmlnaHQnOiBlbmQgLT0gc2l6ZTsgYnJlYWs7XG4gICAgICAgICAgY2FzZSAndGFrZSc6ICAgICAgZW5kID0gbmF0aXZlTWluKGVuZCwgc3RhcnQgKyBzaXplKTsgYnJlYWs7XG4gICAgICAgICAgY2FzZSAndGFrZVJpZ2h0Jzogc3RhcnQgPSBuYXRpdmVNYXgoc3RhcnQsIGVuZCAtIHNpemUpOyBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHsgJ3N0YXJ0Jzogc3RhcnQsICdlbmQnOiBlbmQgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0cyB3cmFwcGVyIGRldGFpbHMgZnJvbSB0aGUgYHNvdXJjZWAgYm9keSBjb21tZW50LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIFRoZSBzb3VyY2UgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHdyYXBwZXIgZGV0YWlscy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRXcmFwRGV0YWlscyhzb3VyY2UpIHtcbiAgICAgIHZhciBtYXRjaCA9IHNvdXJjZS5tYXRjaChyZVdyYXBEZXRhaWxzKTtcbiAgICAgIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdLnNwbGl0KHJlU3BsaXREZXRhaWxzKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcGF0aGAgZXhpc3RzIG9uIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaGFzRnVuYyBUaGUgZnVuY3Rpb24gdG8gY2hlY2sgcHJvcGVydGllcy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHBhdGhgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhhc1BhdGgob2JqZWN0LCBwYXRoLCBoYXNGdW5jKSB7XG4gICAgICBwYXRoID0gY2FzdFBhdGgocGF0aCwgb2JqZWN0KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aC5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSB0b0tleShwYXRoW2luZGV4XSk7XG4gICAgICAgIGlmICghKHJlc3VsdCA9IG9iamVjdCAhPSBudWxsICYmIGhhc0Z1bmMob2JqZWN0LCBrZXkpKSkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdCA9IG9iamVjdFtrZXldO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdCB8fCArK2luZGV4ICE9IGxlbmd0aCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgbGVuZ3RoID0gb2JqZWN0ID09IG51bGwgPyAwIDogb2JqZWN0Lmxlbmd0aDtcbiAgICAgIHJldHVybiAhIWxlbmd0aCAmJiBpc0xlbmd0aChsZW5ndGgpICYmIGlzSW5kZXgoa2V5LCBsZW5ndGgpICYmXG4gICAgICAgIChpc0FycmF5KG9iamVjdCkgfHwgaXNBcmd1bWVudHMob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgYW4gYXJyYXkgY2xvbmUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGluaXRpYWxpemVkIGNsb25lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluaXRDbG9uZUFycmF5KGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IG5ldyBhcnJheS5jb25zdHJ1Y3RvcihsZW5ndGgpO1xuXG4gICAgICAvLyBBZGQgcHJvcGVydGllcyBhc3NpZ25lZCBieSBgUmVnRXhwI2V4ZWNgLlxuICAgICAgaWYgKGxlbmd0aCAmJiB0eXBlb2YgYXJyYXlbMF0gPT0gJ3N0cmluZycgJiYgaGFzT3duUHJvcGVydHkuY2FsbChhcnJheSwgJ2luZGV4JykpIHtcbiAgICAgICAgcmVzdWx0LmluZGV4ID0gYXJyYXkuaW5kZXg7XG4gICAgICAgIHJlc3VsdC5pbnB1dCA9IGFycmF5LmlucHV0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhbiBvYmplY3QgY2xvbmUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVPYmplY3Qob2JqZWN0KSB7XG4gICAgICByZXR1cm4gKHR5cGVvZiBvYmplY3QuY29uc3RydWN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNQcm90b3R5cGUob2JqZWN0KSlcbiAgICAgICAgPyBiYXNlQ3JlYXRlKGdldFByb3RvdHlwZShvYmplY3QpKVxuICAgICAgICA6IHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIGFuIG9iamVjdCBjbG9uZSBiYXNlZCBvbiBpdHMgYHRvU3RyaW5nVGFnYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIG9ubHkgc3VwcG9ydHMgY2xvbmluZyB2YWx1ZXMgd2l0aCB0YWdzIG9mXG4gICAgICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBNYXBgLCBgTnVtYmVyYCwgYFJlZ0V4cGAsIGBTZXRgLCBvciBgU3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGluaXRpYWxpemVkIGNsb25lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluaXRDbG9uZUJ5VGFnKG9iamVjdCwgdGFnLCBpc0RlZXApIHtcbiAgICAgIHZhciBDdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yO1xuICAgICAgc3dpdGNoICh0YWcpIHtcbiAgICAgICAgY2FzZSBhcnJheUJ1ZmZlclRhZzpcbiAgICAgICAgICByZXR1cm4gY2xvbmVBcnJheUJ1ZmZlcihvYmplY3QpO1xuXG4gICAgICAgIGNhc2UgYm9vbFRhZzpcbiAgICAgICAgY2FzZSBkYXRlVGFnOlxuICAgICAgICAgIHJldHVybiBuZXcgQ3Rvcigrb2JqZWN0KTtcblxuICAgICAgICBjYXNlIGRhdGFWaWV3VGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZURhdGFWaWV3KG9iamVjdCwgaXNEZWVwKTtcblxuICAgICAgICBjYXNlIGZsb2F0MzJUYWc6IGNhc2UgZmxvYXQ2NFRhZzpcbiAgICAgICAgY2FzZSBpbnQ4VGFnOiBjYXNlIGludDE2VGFnOiBjYXNlIGludDMyVGFnOlxuICAgICAgICBjYXNlIHVpbnQ4VGFnOiBjYXNlIHVpbnQ4Q2xhbXBlZFRhZzogY2FzZSB1aW50MTZUYWc6IGNhc2UgdWludDMyVGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZVR5cGVkQXJyYXkob2JqZWN0LCBpc0RlZXApO1xuXG4gICAgICAgIGNhc2UgbWFwVGFnOlxuICAgICAgICAgIHJldHVybiBuZXcgQ3RvcjtcblxuICAgICAgICBjYXNlIG51bWJlclRhZzpcbiAgICAgICAgY2FzZSBzdHJpbmdUYWc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBDdG9yKG9iamVjdCk7XG5cbiAgICAgICAgY2FzZSByZWdleHBUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lUmVnRXhwKG9iamVjdCk7XG5cbiAgICAgICAgY2FzZSBzZXRUYWc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBDdG9yO1xuXG4gICAgICAgIGNhc2Ugc3ltYm9sVGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZVN5bWJvbChvYmplY3QpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc2VydHMgd3JhcHBlciBgZGV0YWlsc2AgaW4gYSBjb21tZW50IGF0IHRoZSB0b3Agb2YgdGhlIGBzb3VyY2VgIGJvZHkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgVGhlIHNvdXJjZSB0byBtb2RpZnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBkZXRhaWxzIFRoZSBkZXRhaWxzIHRvIGluc2VydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBtb2RpZmllZCBzb3VyY2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5zZXJ0V3JhcERldGFpbHMoc291cmNlLCBkZXRhaWxzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gZGV0YWlscy5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gc291cmNlO1xuICAgICAgfVxuICAgICAgdmFyIGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG4gICAgICBkZXRhaWxzW2xhc3RJbmRleF0gPSAobGVuZ3RoID4gMSA/ICcmICcgOiAnJykgKyBkZXRhaWxzW2xhc3RJbmRleF07XG4gICAgICBkZXRhaWxzID0gZGV0YWlscy5qb2luKGxlbmd0aCA+IDIgPyAnLCAnIDogJyAnKTtcbiAgICAgIHJldHVybiBzb3VyY2UucmVwbGFjZShyZVdyYXBDb21tZW50LCAne1xcbi8qIFt3cmFwcGVkIHdpdGggJyArIGRldGFpbHMgKyAnXSAqL1xcbicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgZmxhdHRlbmFibGUgYGFyZ3VtZW50c2Agb2JqZWN0IG9yIGFycmF5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBmbGF0dGVuYWJsZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRmxhdHRlbmFibGUodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc0FycmF5KHZhbHVlKSB8fCBpc0FyZ3VtZW50cyh2YWx1ZSkgfHxcbiAgICAgICAgISEoc3ByZWFkYWJsZVN5bWJvbCAmJiB2YWx1ZSAmJiB2YWx1ZVtzcHJlYWRhYmxlU3ltYm9sXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBhcnJheS1saWtlIGluZGV4LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD1NQVhfU0FGRV9JTlRFR0VSXSBUaGUgdXBwZXIgYm91bmRzIG9mIGEgdmFsaWQgaW5kZXguXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBpbmRleCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzSW5kZXgodmFsdWUsIGxlbmd0aCkge1xuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gICAgICBsZW5ndGggPSBsZW5ndGggPT0gbnVsbCA/IE1BWF9TQUZFX0lOVEVHRVIgOiBsZW5ndGg7XG5cbiAgICAgIHJldHVybiAhIWxlbmd0aCAmJlxuICAgICAgICAodHlwZSA9PSAnbnVtYmVyJyB8fFxuICAgICAgICAgICh0eXBlICE9ICdzeW1ib2wnICYmIHJlSXNVaW50LnRlc3QodmFsdWUpKSkgJiZcbiAgICAgICAgICAgICh2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDwgbGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGFyZ3VtZW50cyBhcmUgZnJvbSBhbiBpdGVyYXRlZSBjYWxsLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBwb3RlbnRpYWwgaXRlcmF0ZWUgdmFsdWUgYXJndW1lbnQuXG4gICAgICogQHBhcmFtIHsqfSBpbmRleCBUaGUgcG90ZW50aWFsIGl0ZXJhdGVlIGluZGV4IG9yIGtleSBhcmd1bWVudC5cbiAgICAgKiBAcGFyYW0geyp9IG9iamVjdCBUaGUgcG90ZW50aWFsIGl0ZXJhdGVlIG9iamVjdCBhcmd1bWVudC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGFyZ3VtZW50cyBhcmUgZnJvbSBhbiBpdGVyYXRlZSBjYWxsLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNJdGVyYXRlZUNhbGwodmFsdWUsIGluZGV4LCBvYmplY3QpIHtcbiAgICAgIGlmICghaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiBpbmRleDtcbiAgICAgIGlmICh0eXBlID09ICdudW1iZXInXG4gICAgICAgICAgICA/IChpc0FycmF5TGlrZShvYmplY3QpICYmIGlzSW5kZXgoaW5kZXgsIG9iamVjdC5sZW5ndGgpKVxuICAgICAgICAgICAgOiAodHlwZSA9PSAnc3RyaW5nJyAmJiBpbmRleCBpbiBvYmplY3QpXG4gICAgICAgICAgKSB7XG4gICAgICAgIHJldHVybiBlcShvYmplY3RbaW5kZXhdLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBwcm9wZXJ0eSBuYW1lIGFuZCBub3QgYSBwcm9wZXJ0eSBwYXRoLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeSBrZXlzIG9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcHJvcGVydHkgbmFtZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzS2V5KHZhbHVlLCBvYmplY3QpIHtcbiAgICAgIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgICAgIGlmICh0eXBlID09ICdudW1iZXInIHx8IHR5cGUgPT0gJ3N5bWJvbCcgfHwgdHlwZSA9PSAnYm9vbGVhbicgfHxcbiAgICAgICAgICB2YWx1ZSA9PSBudWxsIHx8IGlzU3ltYm9sKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZUlzUGxhaW5Qcm9wLnRlc3QodmFsdWUpIHx8ICFyZUlzRGVlcFByb3AudGVzdCh2YWx1ZSkgfHxcbiAgICAgICAgKG9iamVjdCAhPSBudWxsICYmIHZhbHVlIGluIE9iamVjdChvYmplY3QpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBzdWl0YWJsZSBmb3IgdXNlIGFzIHVuaXF1ZSBvYmplY3Qga2V5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBzdWl0YWJsZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzS2V5YWJsZSh2YWx1ZSkge1xuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gICAgICByZXR1cm4gKHR5cGUgPT0gJ3N0cmluZycgfHwgdHlwZSA9PSAnbnVtYmVyJyB8fCB0eXBlID09ICdzeW1ib2wnIHx8IHR5cGUgPT0gJ2Jvb2xlYW4nKVxuICAgICAgICA/ICh2YWx1ZSAhPT0gJ19fcHJvdG9fXycpXG4gICAgICAgIDogKHZhbHVlID09PSBudWxsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYGZ1bmNgIGhhcyBhIGxhenkgY291bnRlcnBhcnQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgZnVuY2AgaGFzIGEgbGF6eSBjb3VudGVycGFydCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTGF6aWFibGUoZnVuYykge1xuICAgICAgdmFyIGZ1bmNOYW1lID0gZ2V0RnVuY05hbWUoZnVuYyksXG4gICAgICAgICAgb3RoZXIgPSBsb2Rhc2hbZnVuY05hbWVdO1xuXG4gICAgICBpZiAodHlwZW9mIG90aGVyICE9ICdmdW5jdGlvbicgfHwgIShmdW5jTmFtZSBpbiBMYXp5V3JhcHBlci5wcm90b3R5cGUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChmdW5jID09PSBvdGhlcikge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBkYXRhID0gZ2V0RGF0YShvdGhlcik7XG4gICAgICByZXR1cm4gISFkYXRhICYmIGZ1bmMgPT09IGRhdGFbMF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBmdW5jYCBoYXMgaXRzIHNvdXJjZSBtYXNrZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgZnVuY2AgaXMgbWFza2VkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNNYXNrZWQoZnVuYykge1xuICAgICAgcmV0dXJuICEhbWFza1NyY0tleSAmJiAobWFza1NyY0tleSBpbiBmdW5jKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYGZ1bmNgIGlzIGNhcGFibGUgb2YgYmVpbmcgbWFza2VkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGZ1bmNgIGlzIG1hc2thYmxlLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgdmFyIGlzTWFza2FibGUgPSBjb3JlSnNEYXRhID8gaXNGdW5jdGlvbiA6IHN0dWJGYWxzZTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxpa2VseSBhIHByb3RvdHlwZSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcHJvdG90eXBlLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgIHZhciBDdG9yID0gdmFsdWUgJiYgdmFsdWUuY29uc3RydWN0b3IsXG4gICAgICAgICAgcHJvdG8gPSAodHlwZW9mIEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBDdG9yLnByb3RvdHlwZSkgfHwgb2JqZWN0UHJvdG87XG5cbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gcHJvdG87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUgZm9yIHN0cmljdCBlcXVhbGl0eSBjb21wYXJpc29ucywgaS5lLiBgPT09YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaWYgc3VpdGFibGUgZm9yIHN0cmljdFxuICAgICAqICBlcXVhbGl0eSBjb21wYXJpc29ucywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU3RyaWN0Q29tcGFyYWJsZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSAmJiAhaXNPYmplY3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgbWF0Y2hlc1Byb3BlcnR5YCBmb3Igc291cmNlIHZhbHVlcyBzdWl0YWJsZVxuICAgICAqIGZvciBzdHJpY3QgZXF1YWxpdHkgY29tcGFyaXNvbnMsIGkuZS4gYD09PWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHZhbHVlIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWF0Y2hlc1N0cmljdENvbXBhcmFibGUoa2V5LCBzcmNWYWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdFtrZXldID09PSBzcmNWYWx1ZSAmJlxuICAgICAgICAgIChzcmNWYWx1ZSAhPT0gdW5kZWZpbmVkIHx8IChrZXkgaW4gT2JqZWN0KG9iamVjdCkpKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLm1lbW9pemVgIHdoaWNoIGNsZWFycyB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24nc1xuICAgICAqIGNhY2hlIHdoZW4gaXQgZXhjZWVkcyBgTUFYX01FTU9JWkVfU0laRWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGhhdmUgaXRzIG91dHB1dCBtZW1vaXplZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBtZW1vaXplZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtZW1vaXplQ2FwcGVkKGZ1bmMpIHtcbiAgICAgIHZhciByZXN1bHQgPSBtZW1vaXplKGZ1bmMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBpZiAoY2FjaGUuc2l6ZSA9PT0gTUFYX01FTU9JWkVfU0laRSkge1xuICAgICAgICAgIGNhY2hlLmNsZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtleTtcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgY2FjaGUgPSByZXN1bHQuY2FjaGU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlcyB0aGUgZnVuY3Rpb24gbWV0YWRhdGEgb2YgYHNvdXJjZWAgaW50byBgZGF0YWAuXG4gICAgICpcbiAgICAgKiBNZXJnaW5nIG1ldGFkYXRhIHJlZHVjZXMgdGhlIG51bWJlciBvZiB3cmFwcGVycyB1c2VkIHRvIGludm9rZSBhIGZ1bmN0aW9uLlxuICAgICAqIFRoaXMgaXMgcG9zc2libGUgYmVjYXVzZSBtZXRob2RzIGxpa2UgYF8uYmluZGAsIGBfLmN1cnJ5YCwgYW5kIGBfLnBhcnRpYWxgXG4gICAgICogbWF5IGJlIGFwcGxpZWQgcmVnYXJkbGVzcyBvZiBleGVjdXRpb24gb3JkZXIuIE1ldGhvZHMgbGlrZSBgXy5hcnlgIGFuZFxuICAgICAqIGBfLnJlYXJnYCBtb2RpZnkgZnVuY3Rpb24gYXJndW1lbnRzLCBtYWtpbmcgdGhlIG9yZGVyIGluIHdoaWNoIHRoZXkgYXJlXG4gICAgICogZXhlY3V0ZWQgaW1wb3J0YW50LCBwcmV2ZW50aW5nIHRoZSBtZXJnaW5nIG9mIG1ldGFkYXRhLiBIb3dldmVyLCB3ZSBtYWtlXG4gICAgICogYW4gZXhjZXB0aW9uIGZvciBhIHNhZmUgY29tYmluZWQgY2FzZSB3aGVyZSBjdXJyaWVkIGZ1bmN0aW9ucyBoYXZlIGBfLmFyeWBcbiAgICAgKiBhbmQgb3IgYF8ucmVhcmdgIGFwcGxpZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGRhdGEgVGhlIGRlc3RpbmF0aW9uIG1ldGFkYXRhLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHNvdXJjZSBUaGUgc291cmNlIG1ldGFkYXRhLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgZGF0YWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVyZ2VEYXRhKGRhdGEsIHNvdXJjZSkge1xuICAgICAgdmFyIGJpdG1hc2sgPSBkYXRhWzFdLFxuICAgICAgICAgIHNyY0JpdG1hc2sgPSBzb3VyY2VbMV0sXG4gICAgICAgICAgbmV3Qml0bWFzayA9IGJpdG1hc2sgfCBzcmNCaXRtYXNrLFxuICAgICAgICAgIGlzQ29tbW9uID0gbmV3Qml0bWFzayA8IChXUkFQX0JJTkRfRkxBRyB8IFdSQVBfQklORF9LRVlfRkxBRyB8IFdSQVBfQVJZX0ZMQUcpO1xuXG4gICAgICB2YXIgaXNDb21ibyA9XG4gICAgICAgICgoc3JjQml0bWFzayA9PSBXUkFQX0FSWV9GTEFHKSAmJiAoYml0bWFzayA9PSBXUkFQX0NVUlJZX0ZMQUcpKSB8fFxuICAgICAgICAoKHNyY0JpdG1hc2sgPT0gV1JBUF9BUllfRkxBRykgJiYgKGJpdG1hc2sgPT0gV1JBUF9SRUFSR19GTEFHKSAmJiAoZGF0YVs3XS5sZW5ndGggPD0gc291cmNlWzhdKSkgfHxcbiAgICAgICAgKChzcmNCaXRtYXNrID09IChXUkFQX0FSWV9GTEFHIHwgV1JBUF9SRUFSR19GTEFHKSkgJiYgKHNvdXJjZVs3XS5sZW5ndGggPD0gc291cmNlWzhdKSAmJiAoYml0bWFzayA9PSBXUkFQX0NVUlJZX0ZMQUcpKTtcblxuICAgICAgLy8gRXhpdCBlYXJseSBpZiBtZXRhZGF0YSBjYW4ndCBiZSBtZXJnZWQuXG4gICAgICBpZiAoIShpc0NvbW1vbiB8fCBpc0NvbWJvKSkge1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBzb3VyY2UgYHRoaXNBcmdgIGlmIGF2YWlsYWJsZS5cbiAgICAgIGlmIChzcmNCaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcpIHtcbiAgICAgICAgZGF0YVsyXSA9IHNvdXJjZVsyXTtcbiAgICAgICAgLy8gU2V0IHdoZW4gY3VycnlpbmcgYSBib3VuZCBmdW5jdGlvbi5cbiAgICAgICAgbmV3Qml0bWFzayB8PSBiaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcgPyAwIDogV1JBUF9DVVJSWV9CT1VORF9GTEFHO1xuICAgICAgfVxuICAgICAgLy8gQ29tcG9zZSBwYXJ0aWFsIGFyZ3VtZW50cy5cbiAgICAgIHZhciB2YWx1ZSA9IHNvdXJjZVszXTtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICB2YXIgcGFydGlhbHMgPSBkYXRhWzNdO1xuICAgICAgICBkYXRhWzNdID0gcGFydGlhbHMgPyBjb21wb3NlQXJncyhwYXJ0aWFscywgdmFsdWUsIHNvdXJjZVs0XSkgOiB2YWx1ZTtcbiAgICAgICAgZGF0YVs0XSA9IHBhcnRpYWxzID8gcmVwbGFjZUhvbGRlcnMoZGF0YVszXSwgUExBQ0VIT0xERVIpIDogc291cmNlWzRdO1xuICAgICAgfVxuICAgICAgLy8gQ29tcG9zZSBwYXJ0aWFsIHJpZ2h0IGFyZ3VtZW50cy5cbiAgICAgIHZhbHVlID0gc291cmNlWzVdO1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHBhcnRpYWxzID0gZGF0YVs1XTtcbiAgICAgICAgZGF0YVs1XSA9IHBhcnRpYWxzID8gY29tcG9zZUFyZ3NSaWdodChwYXJ0aWFscywgdmFsdWUsIHNvdXJjZVs2XSkgOiB2YWx1ZTtcbiAgICAgICAgZGF0YVs2XSA9IHBhcnRpYWxzID8gcmVwbGFjZUhvbGRlcnMoZGF0YVs1XSwgUExBQ0VIT0xERVIpIDogc291cmNlWzZdO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgYXJnUG9zYCBpZiBhdmFpbGFibGUuXG4gICAgICB2YWx1ZSA9IHNvdXJjZVs3XTtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICBkYXRhWzddID0gdmFsdWU7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBhcnlgIGlmIGl0J3Mgc21hbGxlci5cbiAgICAgIGlmIChzcmNCaXRtYXNrICYgV1JBUF9BUllfRkxBRykge1xuICAgICAgICBkYXRhWzhdID0gZGF0YVs4XSA9PSBudWxsID8gc291cmNlWzhdIDogbmF0aXZlTWluKGRhdGFbOF0sIHNvdXJjZVs4XSk7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBhcml0eWAgaWYgb25lIGlzIG5vdCBwcm92aWRlZC5cbiAgICAgIGlmIChkYXRhWzldID09IG51bGwpIHtcbiAgICAgICAgZGF0YVs5XSA9IHNvdXJjZVs5XTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBzb3VyY2UgYGZ1bmNgIGFuZCBtZXJnZSBiaXRtYXNrcy5cbiAgICAgIGRhdGFbMF0gPSBzb3VyY2VbMF07XG4gICAgICBkYXRhWzFdID0gbmV3Qml0bWFzaztcblxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlXG4gICAgICogW2BPYmplY3Qua2V5c2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5rZXlzKVxuICAgICAqIGV4Y2VwdCB0aGF0IGl0IGluY2x1ZGVzIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5hdGl2ZUtleXNJbihvYmplY3QpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChvYmplY3QgIT0gbnVsbCkge1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBzdHJpbmcgdXNpbmcgYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gb2JqZWN0VG9TdHJpbmcodmFsdWUpIHtcbiAgICAgIHJldHVybiBuYXRpdmVPYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VSZXN0YCB3aGljaCB0cmFuc2Zvcm1zIHRoZSByZXN0IGFycmF5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhcHBseSBhIHJlc3QgcGFyYW1ldGVyIHRvLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9ZnVuYy5sZW5ndGgtMV0gVGhlIHN0YXJ0IHBvc2l0aW9uIG9mIHRoZSByZXN0IHBhcmFtZXRlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB0cmFuc2Zvcm0gVGhlIHJlc3QgYXJyYXkgdHJhbnNmb3JtLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG92ZXJSZXN0KGZ1bmMsIHN0YXJ0LCB0cmFuc2Zvcm0pIHtcbiAgICAgIHN0YXJ0ID0gbmF0aXZlTWF4KHN0YXJ0ID09PSB1bmRlZmluZWQgPyAoZnVuYy5sZW5ndGggLSAxKSA6IHN0YXJ0LCAwKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICAgICAgbGVuZ3RoID0gbmF0aXZlTWF4KGFyZ3MubGVuZ3RoIC0gc3RhcnQsIDApLFxuICAgICAgICAgICAgYXJyYXkgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgYXJyYXlbaW5kZXhdID0gYXJnc1tzdGFydCArIGluZGV4XTtcbiAgICAgICAgfVxuICAgICAgICBpbmRleCA9IC0xO1xuICAgICAgICB2YXIgb3RoZXJBcmdzID0gQXJyYXkoc3RhcnQgKyAxKTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBzdGFydCkge1xuICAgICAgICAgIG90aGVyQXJnc1tpbmRleF0gPSBhcmdzW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICBvdGhlckFyZ3Nbc3RhcnRdID0gdHJhbnNmb3JtKGFycmF5KTtcbiAgICAgICAgcmV0dXJuIGFwcGx5KGZ1bmMsIHRoaXMsIG90aGVyQXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHBhcmVudCB2YWx1ZSBhdCBgcGF0aGAgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXRoIFRoZSBwYXRoIHRvIGdldCB0aGUgcGFyZW50IHZhbHVlIG9mLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBwYXJlbnQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFyZW50KG9iamVjdCwgcGF0aCkge1xuICAgICAgcmV0dXJuIHBhdGgubGVuZ3RoIDwgMiA/IG9iamVjdCA6IGJhc2VHZXQob2JqZWN0LCBiYXNlU2xpY2UocGF0aCwgMCwgLTEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW9yZGVyIGBhcnJheWAgYWNjb3JkaW5nIHRvIHRoZSBzcGVjaWZpZWQgaW5kZXhlcyB3aGVyZSB0aGUgZWxlbWVudCBhdFxuICAgICAqIHRoZSBmaXJzdCBpbmRleCBpcyBhc3NpZ25lZCBhcyB0aGUgZmlyc3QgZWxlbWVudCwgdGhlIGVsZW1lbnQgYXRcbiAgICAgKiB0aGUgc2Vjb25kIGluZGV4IGlzIGFzc2lnbmVkIGFzIHRoZSBzZWNvbmQgZWxlbWVudCwgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcmVvcmRlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBpbmRleGVzIFRoZSBhcnJhbmdlZCBhcnJheSBpbmRleGVzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlb3JkZXIoYXJyYXksIGluZGV4ZXMpIHtcbiAgICAgIHZhciBhcnJMZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgbGVuZ3RoID0gbmF0aXZlTWluKGluZGV4ZXMubGVuZ3RoLCBhcnJMZW5ndGgpLFxuICAgICAgICAgIG9sZEFycmF5ID0gY29weUFycmF5KGFycmF5KTtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGluZGV4ZXNbbGVuZ3RoXTtcbiAgICAgICAgYXJyYXlbbGVuZ3RoXSA9IGlzSW5kZXgoaW5kZXgsIGFyckxlbmd0aCkgPyBvbGRBcnJheVtpbmRleF0gOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmFsdWUgYXQgYGtleWAsIHVubGVzcyBga2V5YCBpcyBcIl9fcHJvdG9fX1wiIG9yIFwiY29uc3RydWN0b3JcIi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYWZlR2V0KG9iamVjdCwga2V5KSB7XG4gICAgICBpZiAoa2V5ID09PSAnY29uc3RydWN0b3InICYmIHR5cGVvZiBvYmplY3Rba2V5XSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChrZXkgPT0gJ19fcHJvdG9fXycpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gb2JqZWN0W2tleV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIElmIHRoaXMgZnVuY3Rpb24gYmVjb21lcyBob3QsIGkuZS4gaXMgaW52b2tlZCBhIGxvdCBpbiBhIHNob3J0XG4gICAgICogcGVyaW9kIG9mIHRpbWUsIGl0IHdpbGwgdHJpcCBpdHMgYnJlYWtlciBhbmQgdHJhbnNpdGlvbiB0byBhbiBpZGVudGl0eVxuICAgICAqIGZ1bmN0aW9uIHRvIGF2b2lkIGdhcmJhZ2UgY29sbGVjdGlvbiBwYXVzZXMgaW4gVjguIFNlZVxuICAgICAqIFtWOCBpc3N1ZSAyMDcwXShodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0yMDcwKVxuICAgICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFzc29jaWF0ZSBtZXRhZGF0YSB3aXRoLlxuICAgICAqIEBwYXJhbSB7Kn0gZGF0YSBUaGUgbWV0YWRhdGEuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgc2V0RGF0YSA9IHNob3J0T3V0KGJhc2VTZXREYXRhKTtcblxuICAgIC8qKlxuICAgICAqIEEgc2ltcGxlIHdyYXBwZXIgYXJvdW5kIHRoZSBnbG9iYWwgW2BzZXRUaW1lb3V0YF0oaHR0cHM6Ly9tZG4uaW8vc2V0VGltZW91dCkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlbGF5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3YWl0IFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5IGludm9jYXRpb24uXG4gICAgICogQHJldHVybnMge251bWJlcnxPYmplY3R9IFJldHVybnMgdGhlIHRpbWVyIGlkIG9yIHRpbWVvdXQgb2JqZWN0LlxuICAgICAqL1xuICAgIHZhciBzZXRUaW1lb3V0ID0gY3R4U2V0VGltZW91dCB8fCBmdW5jdGlvbihmdW5jLCB3YWl0KSB7XG4gICAgICByZXR1cm4gcm9vdC5zZXRUaW1lb3V0KGZ1bmMsIHdhaXQpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBgdG9TdHJpbmdgIG1ldGhvZCBvZiBgZnVuY2AgdG8gcmV0dXJuIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc3RyaW5nIFRoZSBgdG9TdHJpbmdgIHJlc3VsdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBzZXRUb1N0cmluZyA9IHNob3J0T3V0KGJhc2VTZXRUb1N0cmluZyk7XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBgdG9TdHJpbmdgIG1ldGhvZCBvZiBgd3JhcHBlcmAgdG8gbWltaWMgdGhlIHNvdXJjZSBvZiBgcmVmZXJlbmNlYFxuICAgICAqIHdpdGggd3JhcHBlciBkZXRhaWxzIGluIGEgY29tbWVudCBhdCB0aGUgdG9wIG9mIHRoZSBzb3VyY2UgYm9keS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gd3JhcHBlciBUaGUgZnVuY3Rpb24gdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHJlZmVyZW5jZSBUaGUgcmVmZXJlbmNlIGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGB3cmFwcGVyYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZXRXcmFwVG9TdHJpbmcod3JhcHBlciwgcmVmZXJlbmNlLCBiaXRtYXNrKSB7XG4gICAgICB2YXIgc291cmNlID0gKHJlZmVyZW5jZSArICcnKTtcbiAgICAgIHJldHVybiBzZXRUb1N0cmluZyh3cmFwcGVyLCBpbnNlcnRXcmFwRGV0YWlscyhzb3VyY2UsIHVwZGF0ZVdyYXBEZXRhaWxzKGdldFdyYXBEZXRhaWxzKHNvdXJjZSksIGJpdG1hc2spKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQnbGwgc2hvcnQgb3V0IGFuZCBpbnZva2UgYGlkZW50aXR5YCBpbnN0ZWFkXG4gICAgICogb2YgYGZ1bmNgIHdoZW4gaXQncyBjYWxsZWQgYEhPVF9DT1VOVGAgb3IgbW9yZSB0aW1lcyBpbiBgSE9UX1NQQU5gXG4gICAgICogbWlsbGlzZWNvbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBzaG9ydGFibGUgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2hvcnRPdXQoZnVuYykge1xuICAgICAgdmFyIGNvdW50ID0gMCxcbiAgICAgICAgICBsYXN0Q2FsbGVkID0gMDtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgc3RhbXAgPSBuYXRpdmVOb3coKSxcbiAgICAgICAgICAgIHJlbWFpbmluZyA9IEhPVF9TUEFOIC0gKHN0YW1wIC0gbGFzdENhbGxlZCk7XG5cbiAgICAgICAgbGFzdENhbGxlZCA9IHN0YW1wO1xuICAgICAgICBpZiAocmVtYWluaW5nID4gMCkge1xuICAgICAgICAgIGlmICgrK2NvdW50ID49IEhPVF9DT1VOVCkge1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3VtZW50c1swXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY291bnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHVuZGVmaW5lZCwgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNodWZmbGVgIHdoaWNoIG11dGF0ZXMgYW5kIHNldHMgdGhlIHNpemUgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNodWZmbGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzaXplPWFycmF5Lmxlbmd0aF0gVGhlIHNpemUgb2YgYGFycmF5YC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaHVmZmxlU2VsZihhcnJheSwgc2l6ZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG5cbiAgICAgIHNpemUgPSBzaXplID09PSB1bmRlZmluZWQgPyBsZW5ndGggOiBzaXplO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBzaXplKSB7XG4gICAgICAgIHZhciByYW5kID0gYmFzZVJhbmRvbShpbmRleCwgbGFzdEluZGV4KSxcbiAgICAgICAgICAgIHZhbHVlID0gYXJyYXlbcmFuZF07XG5cbiAgICAgICAgYXJyYXlbcmFuZF0gPSBhcnJheVtpbmRleF07XG4gICAgICAgIGFycmF5W2luZGV4XSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgYXJyYXkubGVuZ3RoID0gc2l6ZTtcbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBhIHByb3BlcnR5IHBhdGggYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKi9cbiAgICB2YXIgc3RyaW5nVG9QYXRoID0gbWVtb2l6ZUNhcHBlZChmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChzdHJpbmcuY2hhckNvZGVBdCgwKSA9PT0gNDYgLyogLiAqLykge1xuICAgICAgICByZXN1bHQucHVzaCgnJyk7XG4gICAgICB9XG4gICAgICBzdHJpbmcucmVwbGFjZShyZVByb3BOYW1lLCBmdW5jdGlvbihtYXRjaCwgbnVtYmVyLCBxdW90ZSwgc3ViU3RyaW5nKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHF1b3RlID8gc3ViU3RyaW5nLnJlcGxhY2UocmVFc2NhcGVDaGFyLCAnJDEnKSA6IChudW1iZXIgfHwgbWF0Y2gpKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBzdHJpbmcga2V5IGlmIGl0J3Mgbm90IGEgc3RyaW5nIG9yIHN5bWJvbC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfHN5bWJvbH0gUmV0dXJucyB0aGUga2V5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvS2V5KHZhbHVlKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdzdHJpbmcnIHx8IGlzU3ltYm9sKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gKHZhbHVlICsgJycpO1xuICAgICAgcmV0dXJuIChyZXN1bHQgPT0gJzAnICYmICgxIC8gdmFsdWUpID09IC1JTkZJTklUWSkgPyAnLTAnIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBmdW5jYCB0byBpdHMgc291cmNlIGNvZGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc291cmNlIGNvZGUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9Tb3VyY2UoZnVuYykge1xuICAgICAgaWYgKGZ1bmMgIT0gbnVsbCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBmdW5jVG9TdHJpbmcuY2FsbChmdW5jKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gKGZ1bmMgKyAnJyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICB9XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB3cmFwcGVyIGBkZXRhaWxzYCBiYXNlZCBvbiBgYml0bWFza2AgZmxhZ3MuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gZGV0YWlscyBUaGUgZGV0YWlscyB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgY3JlYXRlV3JhcGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGRldGFpbHNgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVwZGF0ZVdyYXBEZXRhaWxzKGRldGFpbHMsIGJpdG1hc2spIHtcbiAgICAgIGFycmF5RWFjaCh3cmFwRmxhZ3MsIGZ1bmN0aW9uKHBhaXIpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gJ18uJyArIHBhaXJbMF07XG4gICAgICAgIGlmICgoYml0bWFzayAmIHBhaXJbMV0pICYmICFhcnJheUluY2x1ZGVzKGRldGFpbHMsIHZhbHVlKSkge1xuICAgICAgICAgIGRldGFpbHMucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGRldGFpbHMuc29ydCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiBgd3JhcHBlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB3cmFwcGVyIFRoZSB3cmFwcGVyIHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCB3cmFwcGVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJDbG9uZSh3cmFwcGVyKSB7XG4gICAgICBpZiAod3JhcHBlciBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSB7XG4gICAgICAgIHJldHVybiB3cmFwcGVyLmNsb25lKCk7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gbmV3IExvZGFzaFdyYXBwZXIod3JhcHBlci5fX3dyYXBwZWRfXywgd3JhcHBlci5fX2NoYWluX18pO1xuICAgICAgcmVzdWx0Ll9fYWN0aW9uc19fID0gY29weUFycmF5KHdyYXBwZXIuX19hY3Rpb25zX18pO1xuICAgICAgcmVzdWx0Ll9faW5kZXhfXyAgPSB3cmFwcGVyLl9faW5kZXhfXztcbiAgICAgIHJlc3VsdC5fX3ZhbHVlc19fID0gd3JhcHBlci5fX3ZhbHVlc19fO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGVsZW1lbnRzIHNwbGl0IGludG8gZ3JvdXBzIHRoZSBsZW5ndGggb2YgYHNpemVgLlxuICAgICAqIElmIGBhcnJheWAgY2FuJ3QgYmUgc3BsaXQgZXZlbmx5LCB0aGUgZmluYWwgY2h1bmsgd2lsbCBiZSB0aGUgcmVtYWluaW5nXG4gICAgICogZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3NpemU9MV0gVGhlIGxlbmd0aCBvZiBlYWNoIGNodW5rXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjaHVua3MuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2h1bmsoWydhJywgJ2InLCAnYycsICdkJ10sIDIpO1xuICAgICAqIC8vID0+IFtbJ2EnLCAnYiddLCBbJ2MnLCAnZCddXVxuICAgICAqXG4gICAgICogXy5jaHVuayhbJ2EnLCAnYicsICdjJywgJ2QnXSwgMyk7XG4gICAgICogLy8gPT4gW1snYScsICdiJywgJ2MnXSwgWydkJ11dXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2h1bmsoYXJyYXksIHNpemUsIGd1YXJkKSB7XG4gICAgICBpZiAoKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwoYXJyYXksIHNpemUsIGd1YXJkKSA6IHNpemUgPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgc2l6ZSA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaXplID0gbmF0aXZlTWF4KHRvSW50ZWdlcihzaXplKSwgMCk7XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCB8fCBzaXplIDwgMSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAwLFxuICAgICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShuYXRpdmVDZWlsKGxlbmd0aCAvIHNpemUpKTtcblxuICAgICAgd2hpbGUgKGluZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtyZXNJbmRleCsrXSA9IGJhc2VTbGljZShhcnJheSwgaW5kZXgsIChpbmRleCArPSBzaXplKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgd2l0aCBhbGwgZmFsc2V5IHZhbHVlcyByZW1vdmVkLiBUaGUgdmFsdWVzIGBmYWxzZWAsIGBudWxsYCxcbiAgICAgKiBgMGAsIGBcIlwiYCwgYHVuZGVmaW5lZGAsIGFuZCBgTmFOYCBhcmUgZmFsc2V5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbXBhY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNvbXBhY3QoWzAsIDEsIGZhbHNlLCAyLCAnJywgM10pO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbXBhY3QoYXJyYXkpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICByZXN1bHRbcmVzSW5kZXgrK10gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGFycmF5IGNvbmNhdGVuYXRpbmcgYGFycmF5YCB3aXRoIGFueSBhZGRpdGlvbmFsIGFycmF5c1xuICAgICAqIGFuZC9vciB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29uY2F0ZW5hdGUuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGNvbmNhdGVuYXRlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGNvbmNhdGVuYXRlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzFdO1xuICAgICAqIHZhciBvdGhlciA9IF8uY29uY2F0KGFycmF5LCAyLCBbM10sIFtbNF1dKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKG90aGVyKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgMywgWzRdXVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbmNhdCgpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGFyZ3MgPSBBcnJheShsZW5ndGggLSAxKSxcbiAgICAgICAgICBhcnJheSA9IGFyZ3VtZW50c1swXSxcbiAgICAgICAgICBpbmRleCA9IGxlbmd0aDtcblxuICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgYXJnc1tpbmRleCAtIDFdID0gYXJndW1lbnRzW2luZGV4XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheVB1c2goaXNBcnJheShhcnJheSkgPyBjb3B5QXJyYXkoYXJyYXkpIDogW2FycmF5XSwgYmFzZUZsYXR0ZW4oYXJncywgMSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgYGFycmF5YCB2YWx1ZXMgbm90IGluY2x1ZGVkIGluIHRoZSBvdGhlciBnaXZlbiBhcnJheXNcbiAgICAgKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy4gVGhlIG9yZGVyIGFuZCByZWZlcmVuY2VzIG9mIHJlc3VsdCB2YWx1ZXMgYXJlXG4gICAgICogZGV0ZXJtaW5lZCBieSB0aGUgZmlyc3QgYXJyYXkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLnB1bGxBbGxgLCB0aGlzIG1ldGhvZCByZXR1cm5zIGEgbmV3IGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBleGNsdWRlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAc2VlIF8ud2l0aG91dCwgXy54b3JcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kaWZmZXJlbmNlKFsyLCAxXSwgWzIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKi9cbiAgICB2YXIgZGlmZmVyZW5jZSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHJldHVybiBpc0FycmF5TGlrZU9iamVjdChhcnJheSlcbiAgICAgICAgPyBiYXNlRGlmZmVyZW5jZShhcnJheSwgYmFzZUZsYXR0ZW4odmFsdWVzLCAxLCBpc0FycmF5TGlrZU9iamVjdCwgdHJ1ZSkpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmRpZmZlcmVuY2VgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIGFuZCBgdmFsdWVzYCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uXG4gICAgICogYnkgd2hpY2ggdGhleSdyZSBjb21wYXJlZC4gVGhlIG9yZGVyIGFuZCByZWZlcmVuY2VzIG9mIHJlc3VsdCB2YWx1ZXMgYXJlXG4gICAgICogZGV0ZXJtaW5lZCBieSB0aGUgZmlyc3QgYXJyYXkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OlxuICAgICAqICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLnB1bGxBbGxCeWAsIHRoaXMgbWV0aG9kIHJldHVybnMgYSBuZXcgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kaWZmZXJlbmNlQnkoWzIuMSwgMS4yXSwgWzIuMywgMy40XSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzEuMl1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZGlmZmVyZW5jZUJ5KFt7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgW3sgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIHZhciBkaWZmZXJlbmNlQnkgPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheSwgdmFsdWVzKSB7XG4gICAgICB2YXIgaXRlcmF0ZWUgPSBsYXN0KHZhbHVlcyk7XG4gICAgICBpZiAoaXNBcnJheUxpa2VPYmplY3QoaXRlcmF0ZWUpKSB7XG4gICAgICAgIGl0ZXJhdGVlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlT2JqZWN0KGFycmF5KVxuICAgICAgICA/IGJhc2VEaWZmZXJlbmNlKGFycmF5LCBiYXNlRmxhdHRlbih2YWx1ZXMsIDEsIGlzQXJyYXlMaWtlT2JqZWN0LCB0cnVlKSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5kaWZmZXJlbmNlYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjb21wYXJhdG9yYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgdG8gY29tcGFyZSBlbGVtZW50cyBvZiBgYXJyYXlgIHRvIGB2YWx1ZXNgLiBUaGUgb3JkZXIgYW5kXG4gICAgICogcmVmZXJlbmNlcyBvZiByZXN1bHQgdmFsdWVzIGFyZSBkZXRlcm1pbmVkIGJ5IHRoZSBmaXJzdCBhcnJheS4gVGhlIGNvbXBhcmF0b3JcbiAgICAgKiBpcyBpbnZva2VkIHdpdGggdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ucHVsbEFsbFdpdGhgLCB0aGlzIG1ldGhvZCByZXR1cm5zIGEgbmV3IGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBleGNsdWRlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dO1xuICAgICAqXG4gICAgICogXy5kaWZmZXJlbmNlV2l0aChvYmplY3RzLCBbeyAneCc6IDEsICd5JzogMiB9XSwgXy5pc0VxdWFsKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDIsICd5JzogMSB9XVxuICAgICAqL1xuICAgIHZhciBkaWZmZXJlbmNlV2l0aCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHZhciBjb21wYXJhdG9yID0gbGFzdCh2YWx1ZXMpO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGNvbXBhcmF0b3IpKSB7XG4gICAgICAgIGNvbXBhcmF0b3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKHZhbHVlcywgMSwgaXNBcnJheUxpa2VPYmplY3QsIHRydWUpLCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGBuYCBlbGVtZW50cyBkcm9wcGVkIGZyb20gdGhlIGJlZ2lubmluZy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjUuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MV0gVGhlIG51bWJlciBvZiBlbGVtZW50cyB0byBkcm9wLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRyb3AoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKlxuICAgICAqIF8uZHJvcChbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFszXVxuICAgICAqXG4gICAgICogXy5kcm9wKFsxLCAyLCAzXSwgNSk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKlxuICAgICAqIF8uZHJvcChbMSwgMiwgM10sIDApO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRyb3AoYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBuID0gKGd1YXJkIHx8IG4gPT09IHVuZGVmaW5lZCkgPyAxIDogdG9JbnRlZ2VyKG4pO1xuICAgICAgcmV0dXJuIGJhc2VTbGljZShhcnJheSwgbiA8IDAgPyAwIDogbiwgbGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGBuYCBlbGVtZW50cyBkcm9wcGVkIGZyb20gdGhlIGVuZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MV0gVGhlIG51bWJlciBvZiBlbGVtZW50cyB0byBkcm9wLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHQoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKlxuICAgICAqIF8uZHJvcFJpZ2h0KFsxLCAyLCAzXSwgNSk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKlxuICAgICAqIF8uZHJvcFJpZ2h0KFsxLCAyLCAzXSwgMCk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHJvcFJpZ2h0KGFycmF5LCBuLCBndWFyZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgbiA9IChndWFyZCB8fCBuID09PSB1bmRlZmluZWQpID8gMSA6IHRvSW50ZWdlcihuKTtcbiAgICAgIG4gPSBsZW5ndGggLSBuO1xuICAgICAgcmV0dXJuIGJhc2VTbGljZShhcnJheSwgMCwgbiA8IDAgPyAwIDogbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgZXhjbHVkaW5nIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgZW5kLlxuICAgICAqIEVsZW1lbnRzIGFyZSBkcm9wcGVkIHVudGlsIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZHJvcFJpZ2h0V2hpbGUodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuICFvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wUmlnaHRXaGlsZSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZHJvcFJpZ2h0V2hpbGUodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leScsICdmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRyb3BSaWdodFdoaWxlKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VXaGlsZShhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgdHJ1ZSwgdHJ1ZSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCBleGNsdWRpbmcgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBiZWdpbm5pbmcuXG4gICAgICogRWxlbWVudHMgYXJlIGRyb3BwZWQgdW50aWwgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkuIFRoZSBwcmVkaWNhdGUgaXNcbiAgICAgKiBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5kcm9wV2hpbGUodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuICFvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wV2hpbGUodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BXaGlsZSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BXaGlsZSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5JywgJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHJvcFdoaWxlKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VXaGlsZShhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgdHJ1ZSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaWxscyBlbGVtZW50cyBvZiBgYXJyYXlgIHdpdGggYHZhbHVlYCBmcm9tIGBzdGFydGAgdXAgdG8sIGJ1dCBub3RcbiAgICAgKiBpbmNsdWRpbmcsIGBlbmRgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjIuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmaWxsLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGZpbGwgYGFycmF5YCB3aXRoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDNdO1xuICAgICAqXG4gICAgICogXy5maWxsKGFycmF5LCAnYScpO1xuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYScsICdhJ11cbiAgICAgKlxuICAgICAqIF8uZmlsbChBcnJheSgzKSwgMik7XG4gICAgICogLy8gPT4gWzIsIDIsIDJdXG4gICAgICpcbiAgICAgKiBfLmZpbGwoWzQsIDYsIDgsIDEwXSwgJyonLCAxLCAzKTtcbiAgICAgKiAvLyA9PiBbNCwgJyonLCAnKicsIDEwXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbGwoYXJyYXksIHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoc3RhcnQgJiYgdHlwZW9mIHN0YXJ0ICE9ICdudW1iZXInICYmIGlzSXRlcmF0ZWVDYWxsKGFycmF5LCB2YWx1ZSwgc3RhcnQpKSB7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgZW5kID0gbGVuZ3RoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VGaWxsKGFycmF5LCB2YWx1ZSwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5maW5kYCBleGNlcHQgdGhhdCBpdCByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZmlyc3RcbiAgICAgKiBlbGVtZW50IGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciBpbnN0ZWFkIG9mIHRoZSBlbGVtZW50IGl0c2VsZi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD0wXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZvdW5kIGVsZW1lbnQsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maW5kSW5kZXgodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8udXNlciA9PSAnYmFybmV5JzsgfSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRJbmRleCh1c2VycywgeyAndXNlcic6ICdmcmVkJywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRJbmRleCh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZEluZGV4KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IGZyb21JbmRleCA9PSBudWxsID8gMCA6IHRvSW50ZWdlcihmcm9tSW5kZXgpO1xuICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICBpbmRleCA9IG5hdGl2ZU1heChsZW5ndGggKyBpbmRleCwgMCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUZpbmRJbmRleChhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgaW5kZXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZEluZGV4YCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzXG4gICAgICogb2YgYGNvbGxlY3Rpb25gIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD1hcnJheS5sZW5ndGgtMV0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby51c2VyID09ICdwZWJibGVzJzsgfSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IHRydWUgfSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IDBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kTGFzdEluZGV4KGFycmF5LCBwcmVkaWNhdGUsIGZyb21JbmRleCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gbGVuZ3RoIC0gMTtcbiAgICAgIGlmIChmcm9tSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpbmRleCA9IHRvSW50ZWdlcihmcm9tSW5kZXgpO1xuICAgICAgICBpbmRleCA9IGZyb21JbmRleCA8IDBcbiAgICAgICAgICA/IG5hdGl2ZU1heChsZW5ndGggKyBpbmRleCwgMClcbiAgICAgICAgICA6IG5hdGl2ZU1pbihpbmRleCwgbGVuZ3RoIC0gMSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUZpbmRJbmRleChhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgaW5kZXgsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZsYXR0ZW5zIGBhcnJheWAgYSBzaW5nbGUgbGV2ZWwgZGVlcC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmbGF0dGVuLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZsYXR0ZW5lZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mbGF0dGVuKFsxLCBbMiwgWzMsIFs0XV0sIDVdXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIFszLCBbNF1dLCA1XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXR0ZW4oYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBiYXNlRmxhdHRlbihhcnJheSwgMSkgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWN1cnNpdmVseSBmbGF0dGVucyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW5EZWVwKFsxLCBbMiwgWzMsIFs0XV0sIDVdXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIDQsIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdHRlbkRlZXAoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBiYXNlRmxhdHRlbihhcnJheSwgSU5GSU5JVFkpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgZmxhdHRlbiBgYXJyYXlgIHVwIHRvIGBkZXB0aGAgdGltZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC40LjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmxhdHRlbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2RlcHRoPTFdIFRoZSBtYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCBbMiwgWzMsIFs0XV0sIDVdXTtcbiAgICAgKlxuICAgICAqIF8uZmxhdHRlbkRlcHRoKGFycmF5LCAxKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgWzMsIFs0XV0sIDVdXG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW5EZXB0aChhcnJheSwgMik7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIFs0XSwgNV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGF0dGVuRGVwdGgoYXJyYXksIGRlcHRoKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBkZXB0aCA9IGRlcHRoID09PSB1bmRlZmluZWQgPyAxIDogdG9JbnRlZ2VyKGRlcHRoKTtcbiAgICAgIHJldHVybiBiYXNlRmxhdHRlbihhcnJheSwgZGVwdGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBpbnZlcnNlIG9mIGBfLnRvUGFpcnNgOyB0aGlzIG1ldGhvZCByZXR1cm5zIGFuIG9iamVjdCBjb21wb3NlZFxuICAgICAqIGZyb20ga2V5LXZhbHVlIGBwYWlyc2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYWlycyBUaGUga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZnJvbVBhaXJzKFtbJ2EnLCAxXSwgWydiJywgMl1dKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmcm9tUGFpcnMocGFpcnMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhaXJzID09IG51bGwgPyAwIDogcGFpcnMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IHt9O1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgcGFpciA9IHBhaXJzW2luZGV4XTtcbiAgICAgICAgcmVzdWx0W3BhaXJbMF1dID0gcGFpclsxXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZmlyc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGFsaWFzIGZpcnN0XG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaGVhZChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIF8uaGVhZChbXSk7XG4gICAgICogLy8gPT4gdW5kZWZpbmVkXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGVhZChhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpID8gYXJyYXlbMF0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaW5kZXggYXQgd2hpY2ggdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYHZhbHVlYCBpcyBmb3VuZCBpbiBgYXJyYXlgXG4gICAgICogdXNpbmcgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuIElmIGBmcm9tSW5kZXhgIGlzIG5lZ2F0aXZlLCBpdCdzIHVzZWQgYXMgdGhlXG4gICAgICogb2Zmc2V0IGZyb20gdGhlIGVuZCBvZiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD0wXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbmRleE9mKFsxLCAyLCAxLCAyXSwgMik7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogLy8gU2VhcmNoIGZyb20gdGhlIGBmcm9tSW5kZXhgLlxuICAgICAqIF8uaW5kZXhPZihbMSwgMiwgMSwgMl0sIDIsIDIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBmcm9tSW5kZXggPT0gbnVsbCA/IDAgOiB0b0ludGVnZXIoZnJvbUluZGV4KTtcbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgaW5kZXggPSBuYXRpdmVNYXgobGVuZ3RoICsgaW5kZXgsIDApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgaW5kZXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYWxsIGJ1dCB0aGUgbGFzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluaXRpYWwoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0aWFsKGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYmFzZVNsaWNlKGFycmF5LCAwLCAtMSkgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHVuaXF1ZSB2YWx1ZXMgdGhhdCBhcmUgaW5jbHVkZWQgaW4gYWxsIGdpdmVuIGFycmF5c1xuICAgICAqIHVzaW5nIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLiBUaGUgb3JkZXIgYW5kIHJlZmVyZW5jZXMgb2YgcmVzdWx0IHZhbHVlcyBhcmVcbiAgICAgKiBkZXRlcm1pbmVkIGJ5IHRoZSBmaXJzdCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBpbnRlcnNlY3RpbmcgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmludGVyc2VjdGlvbihbMiwgMV0sIFsyLCAzXSk7XG4gICAgICogLy8gPT4gWzJdXG4gICAgICovXG4gICAgdmFyIGludGVyc2VjdGlvbiA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIG1hcHBlZCA9IGFycmF5TWFwKGFycmF5cywgY2FzdEFycmF5TGlrZU9iamVjdCk7XG4gICAgICByZXR1cm4gKG1hcHBlZC5sZW5ndGggJiYgbWFwcGVkWzBdID09PSBhcnJheXNbMF0pXG4gICAgICAgID8gYmFzZUludGVyc2VjdGlvbihtYXBwZWQpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmludGVyc2VjdGlvbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgXG4gICAgICogd2hpY2ggaXMgaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IG9mIGVhY2ggYGFycmF5c2AgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvblxuICAgICAqIGJ5IHdoaWNoIHRoZXkncmUgY29tcGFyZWQuIFRoZSBvcmRlciBhbmQgcmVmZXJlbmNlcyBvZiByZXN1bHQgdmFsdWVzIGFyZVxuICAgICAqIGRldGVybWluZWQgYnkgdGhlIGZpcnN0IGFycmF5LiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDpcbiAgICAgKiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBpbnRlcnNlY3RpbmcgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmludGVyc2VjdGlvbkJ5KFsyLjEsIDEuMl0sIFsyLjMsIDMuNF0sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsyLjFdXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmludGVyc2VjdGlvbkJ5KFt7ICd4JzogMSB9XSwgW3sgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSB9XVxuICAgICAqL1xuICAgIHZhciBpbnRlcnNlY3Rpb25CeSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGl0ZXJhdGVlID0gbGFzdChhcnJheXMpLFxuICAgICAgICAgIG1hcHBlZCA9IGFycmF5TWFwKGFycmF5cywgY2FzdEFycmF5TGlrZU9iamVjdCk7XG5cbiAgICAgIGlmIChpdGVyYXRlZSA9PT0gbGFzdChtYXBwZWQpKSB7XG4gICAgICAgIGl0ZXJhdGVlID0gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWFwcGVkLnBvcCgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChtYXBwZWQubGVuZ3RoICYmIG1hcHBlZFswXSA9PT0gYXJyYXlzWzBdKVxuICAgICAgICA/IGJhc2VJbnRlcnNlY3Rpb24obWFwcGVkLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmludGVyc2VjdGlvbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5c2AuIFRoZSBvcmRlciBhbmQgcmVmZXJlbmNlc1xuICAgICAqIG9mIHJlc3VsdCB2YWx1ZXMgYXJlIGRldGVybWluZWQgYnkgdGhlIGZpcnN0IGFycmF5LiBUaGUgY29tcGFyYXRvciBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGludGVyc2VjdGluZyB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9XTtcbiAgICAgKiB2YXIgb3RoZXJzID0gW3sgJ3gnOiAxLCAneSc6IDEgfSwgeyAneCc6IDEsICd5JzogMiB9XTtcbiAgICAgKlxuICAgICAqIF8uaW50ZXJzZWN0aW9uV2l0aChvYmplY3RzLCBvdGhlcnMsIF8uaXNFcXVhbCk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxLCAneSc6IDIgfV1cbiAgICAgKi9cbiAgICB2YXIgaW50ZXJzZWN0aW9uV2l0aCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGNvbXBhcmF0b3IgPSBsYXN0KGFycmF5cyksXG4gICAgICAgICAgbWFwcGVkID0gYXJyYXlNYXAoYXJyYXlzLCBjYXN0QXJyYXlMaWtlT2JqZWN0KTtcblxuICAgICAgY29tcGFyYXRvciA9IHR5cGVvZiBjb21wYXJhdG9yID09ICdmdW5jdGlvbicgPyBjb21wYXJhdG9yIDogdW5kZWZpbmVkO1xuICAgICAgaWYgKGNvbXBhcmF0b3IpIHtcbiAgICAgICAgbWFwcGVkLnBvcCgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChtYXBwZWQubGVuZ3RoICYmIG1hcHBlZFswXSA9PT0gYXJyYXlzWzBdKVxuICAgICAgICA/IGJhc2VJbnRlcnNlY3Rpb24obWFwcGVkLCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBhbGwgZWxlbWVudHMgaW4gYGFycmF5YCBpbnRvIGEgc3RyaW5nIHNlcGFyYXRlZCBieSBgc2VwYXJhdG9yYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjb252ZXJ0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc2VwYXJhdG9yPScsJ10gVGhlIGVsZW1lbnQgc2VwYXJhdG9yLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGpvaW5lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uam9pbihbJ2EnLCAnYicsICdjJ10sICd+Jyk7XG4gICAgICogLy8gPT4gJ2F+Yn5jJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGpvaW4oYXJyYXksIHNlcGFyYXRvcikge1xuICAgICAgcmV0dXJuIGFycmF5ID09IG51bGwgPyAnJyA6IG5hdGl2ZUpvaW4uY2FsbChhcnJheSwgc2VwYXJhdG9yKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBsYXN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbGFzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubGFzdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXN0KGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYXJyYXlbbGVuZ3RoIC0gMV0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pbmRleE9mYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYGFycmF5YCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PWFycmF5Lmxlbmd0aC0xXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sYXN0SW5kZXhPZihbMSwgMiwgMSwgMl0sIDIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIC8vIFNlYXJjaCBmcm9tIHRoZSBgZnJvbUluZGV4YC5cbiAgICAgKiBfLmxhc3RJbmRleE9mKFsxLCAyLCAxLCAyXSwgMiwgMik7XG4gICAgICogLy8gPT4gMVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhc3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBsZW5ndGg7XG4gICAgICBpZiAoZnJvbUluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaW5kZXggPSB0b0ludGVnZXIoZnJvbUluZGV4KTtcbiAgICAgICAgaW5kZXggPSBpbmRleCA8IDAgPyBuYXRpdmVNYXgobGVuZ3RoICsgaW5kZXgsIDApIDogbmF0aXZlTWluKGluZGV4LCBsZW5ndGggLSAxKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdmFsdWVcbiAgICAgICAgPyBzdHJpY3RMYXN0SW5kZXhPZihhcnJheSwgdmFsdWUsIGluZGV4KVxuICAgICAgICA6IGJhc2VGaW5kSW5kZXgoYXJyYXksIGJhc2VJc05hTiwgaW5kZXgsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGVsZW1lbnQgYXQgaW5kZXggYG5gIG9mIGBhcnJheWAuIElmIGBuYCBpcyBuZWdhdGl2ZSwgdGhlIG50aFxuICAgICAqIGVsZW1lbnQgZnJvbSB0aGUgZW5kIGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MF0gVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbnRoIGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWydhJywgJ2InLCAnYycsICdkJ107XG4gICAgICpcbiAgICAgKiBfLm50aChhcnJheSwgMSk7XG4gICAgICogLy8gPT4gJ2InXG4gICAgICpcbiAgICAgKiBfLm50aChhcnJheSwgLTIpO1xuICAgICAqIC8vID0+ICdjJztcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBudGgoYXJyYXksIG4pIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSA/IGJhc2VOdGgoYXJyYXksIHRvSW50ZWdlcihuKSkgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgZ2l2ZW4gdmFsdWVzIGZyb20gYGFycmF5YCB1c2luZ1xuICAgICAqIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy53aXRob3V0YCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLiBVc2UgYF8ucmVtb3ZlYFxuICAgICAqIHRvIHJlbW92ZSBlbGVtZW50cyBmcm9tIGFuIGFycmF5IGJ5IHByZWRpY2F0ZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWydhJywgJ2InLCAnYycsICdhJywgJ2InLCAnYyddO1xuICAgICAqXG4gICAgICogXy5wdWxsKGFycmF5LCAnYScsICdjJyk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsnYicsICdiJ11cbiAgICAgKi9cbiAgICB2YXIgcHVsbCA9IGJhc2VSZXN0KHB1bGxBbGwpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5wdWxsYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGFuIGFycmF5IG9mIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLmRpZmZlcmVuY2VgLCB0aGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWydhJywgJ2InLCAnYycsICdhJywgJ2InLCAnYyddO1xuICAgICAqXG4gICAgICogXy5wdWxsQWxsKGFycmF5LCBbJ2EnLCAnYyddKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWydiJywgJ2InXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHB1bGxBbGwoYXJyYXksIHZhbHVlcykge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGggJiYgdmFsdWVzICYmIHZhbHVlcy5sZW5ndGgpXG4gICAgICAgID8gYmFzZVB1bGxBbGwoYXJyYXksIHZhbHVlcylcbiAgICAgICAgOiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnB1bGxBbGxgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIGFuZCBgdmFsdWVzYCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uXG4gICAgICogYnkgd2hpY2ggdGhleSdyZSBjb21wYXJlZC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLmRpZmZlcmVuY2VCeWAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gcmVtb3ZlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gW3sgJ3gnOiAxIH0sIHsgJ3gnOiAyIH0sIHsgJ3gnOiAzIH0sIHsgJ3gnOiAxIH1dO1xuICAgICAqXG4gICAgICogXy5wdWxsQWxsQnkoYXJyYXksIFt7ICd4JzogMSB9LCB7ICd4JzogMyB9XSwgJ3gnKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAyIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHVsbEFsbEJ5KGFycmF5LCB2YWx1ZXMsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCAmJiB2YWx1ZXMgJiYgdmFsdWVzLmxlbmd0aClcbiAgICAgICAgPyBiYXNlUHVsbEFsbChhcnJheSwgdmFsdWVzLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpXG4gICAgICAgIDogYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5wdWxsQWxsYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjb21wYXJhdG9yYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgdG8gY29tcGFyZSBlbGVtZW50cyBvZiBgYXJyYXlgIHRvIGB2YWx1ZXNgLiBUaGUgY29tcGFyYXRvciBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5kaWZmZXJlbmNlV2l0aGAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjYuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gcmVtb3ZlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMywgJ3knOiA0IH0sIHsgJ3gnOiA1LCAneSc6IDYgfV07XG4gICAgICpcbiAgICAgKiBfLnB1bGxBbGxXaXRoKGFycmF5LCBbeyAneCc6IDMsICd5JzogNCB9XSwgXy5pc0VxdWFsKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDUsICd5JzogNiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHB1bGxBbGxXaXRoKGFycmF5LCB2YWx1ZXMsIGNvbXBhcmF0b3IpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoICYmIHZhbHVlcyAmJiB2YWx1ZXMubGVuZ3RoKVxuICAgICAgICA/IGJhc2VQdWxsQWxsKGFycmF5LCB2YWx1ZXMsIHVuZGVmaW5lZCwgY29tcGFyYXRvcilcbiAgICAgICAgOiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGVsZW1lbnRzIGZyb20gYGFycmF5YCBjb3JyZXNwb25kaW5nIHRvIGBpbmRleGVzYCBhbmQgcmV0dXJucyBhblxuICAgICAqIGFycmF5IG9mIHJlbW92ZWQgZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLmF0YCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0gey4uLihudW1iZXJ8bnVtYmVyW10pfSBbaW5kZXhlc10gVGhlIGluZGV4ZXMgb2YgZWxlbWVudHMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHJlbW92ZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsnYScsICdiJywgJ2MnLCAnZCddO1xuICAgICAqIHZhciBwdWxsZWQgPSBfLnB1bGxBdChhcnJheSwgWzEsIDNdKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYyddXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhwdWxsZWQpO1xuICAgICAqIC8vID0+IFsnYicsICdkJ11cbiAgICAgKi9cbiAgICB2YXIgcHVsbEF0ID0gZmxhdFJlc3QoZnVuY3Rpb24oYXJyYXksIGluZGV4ZXMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBiYXNlQXQoYXJyYXksIGluZGV4ZXMpO1xuXG4gICAgICBiYXNlUHVsbEF0KGFycmF5LCBhcnJheU1hcChpbmRleGVzLCBmdW5jdGlvbihpbmRleCkge1xuICAgICAgICByZXR1cm4gaXNJbmRleChpbmRleCwgbGVuZ3RoKSA/ICtpbmRleCA6IGluZGV4O1xuICAgICAgfSkuc29ydChjb21wYXJlQXNjZW5kaW5nKSk7XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBlbGVtZW50cyBmcm9tIGBhcnJheWAgdGhhdCBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3JcbiAgICAgKiBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiB0aGUgcmVtb3ZlZCBlbGVtZW50cy4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8uZmlsdGVyYCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLiBVc2UgYF8ucHVsbGBcbiAgICAgKiB0byBwdWxsIGVsZW1lbnRzIGZyb20gYW4gYXJyYXkgYnkgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiByZW1vdmVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgMywgNF07XG4gICAgICogdmFyIGV2ZW5zID0gXy5yZW1vdmUoYXJyYXksIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICUgMiA9PSAwO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAzXVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2coZXZlbnMpO1xuICAgICAqIC8vID0+IFsyLCA0XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlbW92ZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICAgIGluZGV4ZXMucHVzaChpbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJhc2VQdWxsQXQoYXJyYXksIGluZGV4ZXMpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnNlcyBgYXJyYXlgIHNvIHRoYXQgdGhlIGZpcnN0IGVsZW1lbnQgYmVjb21lcyB0aGUgbGFzdCwgdGhlIHNlY29uZFxuICAgICAqIGVsZW1lbnQgYmVjb21lcyB0aGUgc2Vjb25kIHRvIGxhc3QsIGFuZCBzbyBvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAgYW5kIGlzIGJhc2VkIG9uXG4gICAgICogW2BBcnJheSNyZXZlcnNlYF0oaHR0cHM6Ly9tZG4uaW8vQXJyYXkvcmV2ZXJzZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgM107XG4gICAgICpcbiAgICAgKiBfLnJldmVyc2UoYXJyYXkpO1xuICAgICAqIC8vID0+IFszLCAyLCAxXVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFszLCAyLCAxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJldmVyc2UoYXJyYXkpIHtcbiAgICAgIHJldHVybiBhcnJheSA9PSBudWxsID8gYXJyYXkgOiBuYXRpdmVSZXZlcnNlLmNhbGwoYXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIGZyb20gYHN0YXJ0YCB1cCB0bywgYnV0IG5vdCBpbmNsdWRpbmcsIGBlbmRgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIHVzZWQgaW5zdGVhZCBvZlxuICAgICAqIFtgQXJyYXkjc2xpY2VgXShodHRwczovL21kbi5pby9BcnJheS9zbGljZSkgdG8gZW5zdXJlIGRlbnNlIGFycmF5cyBhcmVcbiAgICAgKiByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzbGljZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNsaWNlKGFycmF5LCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoZW5kICYmIHR5cGVvZiBlbmQgIT0gJ251bWJlcicgJiYgaXNJdGVyYXRlZUNhbGwoYXJyYXksIHN0YXJ0LCBlbmQpKSB7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgZW5kID0gbGVuZ3RoO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHN0YXJ0ID0gc3RhcnQgPT0gbnVsbCA/IDAgOiB0b0ludGVnZXIoc3RhcnQpO1xuICAgICAgICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbmd0aCA6IHRvSW50ZWdlcihlbmQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VTbGljZShhcnJheSwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlcyBhIGJpbmFyeSBzZWFyY2ggdG8gZGV0ZXJtaW5lIHRoZSBsb3dlc3QgaW5kZXggYXQgd2hpY2ggYHZhbHVlYFxuICAgICAqIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG8gbWFpbnRhaW4gaXRzIHNvcnQgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZEluZGV4KFszMCwgNTBdLCA0MCk7XG4gICAgICogLy8gPT4gMVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc29ydGVkSW5kZXhgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgZm9yIGB2YWx1ZWAgYW5kIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIHRvIGNvbXB1dGUgdGhlaXJcbiAgICAgKiBzb3J0IHJhbmtpbmcuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZFxuICAgICAqICBpbnRvIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiA0IH0sIHsgJ3gnOiA1IH1dO1xuICAgICAqXG4gICAgICogXy5zb3J0ZWRJbmRleEJ5KG9iamVjdHMsIHsgJ3gnOiA0IH0sIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ueDsgfSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zb3J0ZWRJbmRleEJ5KG9iamVjdHMsIHsgJ3gnOiA0IH0sICd4Jyk7XG4gICAgICogLy8gPT4gMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZEluZGV4QnkoYXJyYXksIHZhbHVlLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmluZGV4T2ZgIGV4Y2VwdCB0aGF0IGl0IHBlcmZvcm1zIGEgYmluYXJ5XG4gICAgICogc2VhcmNoIG9uIGEgc29ydGVkIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydGVkSW5kZXhPZihbNCwgNSwgNSwgNSwgNl0sIDUpO1xuICAgICAqIC8vID0+IDFcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRJbmRleE9mKGFycmF5LCB2YWx1ZSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKGxlbmd0aCkge1xuICAgICAgICB2YXIgaW5kZXggPSBiYXNlU29ydGVkSW5kZXgoYXJyYXksIHZhbHVlKTtcbiAgICAgICAgaWYgKGluZGV4IDwgbGVuZ3RoICYmIGVxKGFycmF5W2luZGV4XSwgdmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0ZWRJbmRleGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgaGlnaGVzdFxuICAgICAqIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkIGludG8gYGFycmF5YCBpbiBvcmRlciB0b1xuICAgICAqIG1haW50YWluIGl0cyBzb3J0IG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICogIGludG8gYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRMYXN0SW5kZXgoWzQsIDUsIDUsIDUsIDZdLCA1KTtcbiAgICAgKiAvLyA9PiA0XG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkTGFzdEluZGV4KGFycmF5LCB2YWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc29ydGVkTGFzdEluZGV4YCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIGZvciBgdmFsdWVgIGFuZCBlYWNoIGVsZW1lbnQgb2YgYGFycmF5YCB0byBjb21wdXRlIHRoZWlyXG4gICAgICogc29ydCByYW5raW5nLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogNCB9LCB7ICd4JzogNSB9XTtcbiAgICAgKlxuICAgICAqIF8uc29ydGVkTGFzdEluZGV4Qnkob2JqZWN0cywgeyAneCc6IDQgfSwgZnVuY3Rpb24obykgeyByZXR1cm4gby54OyB9KTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnNvcnRlZExhc3RJbmRleEJ5KG9iamVjdHMsIHsgJ3gnOiA0IH0sICd4Jyk7XG4gICAgICogLy8gPT4gMVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZExhc3RJbmRleEJ5KGFycmF5LCB2YWx1ZSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBiYXNlU29ydGVkSW5kZXhCeShhcnJheSwgdmFsdWUsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5sYXN0SW5kZXhPZmAgZXhjZXB0IHRoYXQgaXQgcGVyZm9ybXMgYSBiaW5hcnlcbiAgICAgKiBzZWFyY2ggb24gYSBzb3J0ZWQgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRMYXN0SW5kZXhPZihbNCwgNSwgNSwgNSwgNl0sIDUpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRMYXN0SW5kZXhPZihhcnJheSwgdmFsdWUpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGgpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gYmFzZVNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSwgdHJ1ZSkgLSAxO1xuICAgICAgICBpZiAoZXEoYXJyYXlbaW5kZXhdLCB2YWx1ZSkpIHtcbiAgICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaXFgIGV4Y2VwdCB0aGF0IGl0J3MgZGVzaWduZWQgYW5kIG9wdGltaXplZFxuICAgICAqIGZvciBzb3J0ZWQgYXJyYXlzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydGVkVW5pcShbMSwgMSwgMl0pO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZFVuaXEoYXJyYXkpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VTb3J0ZWRVbmlxKGFycmF5KVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pcUJ5YCBleGNlcHQgdGhhdCBpdCdzIGRlc2lnbmVkIGFuZCBvcHRpbWl6ZWRcbiAgICAgKiBmb3Igc29ydGVkIGFycmF5cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydGVkVW5pcUJ5KFsxLjEsIDEuMiwgMi4zLCAyLjRdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiBbMS4xLCAyLjNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkVW5pcUJ5KGFycmF5LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVNvcnRlZFVuaXEoYXJyYXksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBidXQgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGFpbChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRhaWwoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBiYXNlU2xpY2UoYXJyYXksIDEsIGxlbmd0aCkgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGBuYCBlbGVtZW50cyB0YWtlbiBmcm9tIHRoZSBiZWdpbm5pbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gdGFrZS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50YWtlKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzFdXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIF8udGFrZShbMSwgMiwgM10sIDUpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogXy50YWtlKFsxLCAyLCAzXSwgMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlKGFycmF5LCBuLCBndWFyZCkge1xuICAgICAgaWYgKCEoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBuID0gKGd1YXJkIHx8IG4gPT09IHVuZGVmaW5lZCkgPyAxIDogdG9JbnRlZ2VyKG4pO1xuICAgICAgcmV0dXJuIGJhc2VTbGljZShhcnJheSwgMCwgbiA8IDAgPyAwIDogbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBgbmAgZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgZW5kLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHRha2UuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGFrZVJpZ2h0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzNdXG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodChbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHQoWzEsIDIsIDNdLCA1KTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8udGFrZVJpZ2h0KFsxLCAyLCAzXSwgMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlUmlnaHQoYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBuID0gKGd1YXJkIHx8IG4gPT09IHVuZGVmaW5lZCkgPyAxIDogdG9JbnRlZ2VyKG4pO1xuICAgICAgbiA9IGxlbmd0aCAtIG47XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCBuIDwgMCA/IDAgOiBuLCBsZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgZW5kLiBFbGVtZW50cyBhcmVcbiAgICAgKiB0YWtlbiB1bnRpbCBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGhcbiAgICAgKiB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodFdoaWxlKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy50YWtlUmlnaHRXaGlsZSh1c2VycywgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy50YWtlUmlnaHRXaGlsZSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVJpZ2h0V2hpbGUodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRha2VSaWdodFdoaWxlKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VXaGlsZShhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgZmFsc2UsIHRydWUpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBlbGVtZW50cyB0YWtlbiBmcm9tIHRoZSBiZWdpbm5pbmcuIEVsZW1lbnRzXG4gICAgICogYXJlIHRha2VuIHVudGlsIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aFxuICAgICAqIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8udGFrZVdoaWxlKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnRha2VXaGlsZSh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVdoaWxlKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnRha2VXaGlsZSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGFrZVdoaWxlKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VXaGlsZShhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHVuaXF1ZSB2YWx1ZXMsIGluIG9yZGVyLCBmcm9tIGFsbCBnaXZlbiBhcnJheXMgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21iaW5lZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pb24oWzJdLCBbMSwgMl0pO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqL1xuICAgIHZhciB1bmlvbiA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgcmV0dXJuIGJhc2VVbmlxKGJhc2VGbGF0dGVuKGFycmF5cywgMSwgaXNBcnJheUxpa2VPYmplY3QsIHRydWUpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pb25gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBlYWNoIGBhcnJheXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnlcbiAgICAgKiB3aGljaCB1bmlxdWVuZXNzIGlzIGNvbXB1dGVkLiBSZXN1bHQgdmFsdWVzIGFyZSBjaG9zZW4gZnJvbSB0aGUgZmlyc3RcbiAgICAgKiBhcnJheSBpbiB3aGljaCB0aGUgdmFsdWUgb2NjdXJzLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDpcbiAgICAgKiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21iaW5lZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pb25CeShbMi4xXSwgWzEuMiwgMi4zXSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzIuMSwgMS4yXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy51bmlvbkJ5KFt7ICd4JzogMSB9XSwgW3sgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSB9LCB7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIHZhciB1bmlvbkJ5ID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgaXRlcmF0ZWUgPSBsYXN0KGFycmF5cyk7XG4gICAgICBpZiAoaXNBcnJheUxpa2VPYmplY3QoaXRlcmF0ZWUpKSB7XG4gICAgICAgIGl0ZXJhdGVlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VVbmlxKGJhc2VGbGF0dGVuKGFycmF5cywgMSwgaXNBcnJheUxpa2VPYmplY3QsIHRydWUpLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlvbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5c2AuIFJlc3VsdCB2YWx1ZXMgYXJlIGNob3NlbiBmcm9tXG4gICAgICogdGhlIGZpcnN0IGFycmF5IGluIHdoaWNoIHRoZSB2YWx1ZSBvY2N1cnMuIFRoZSBjb21wYXJhdG9yIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHR3byBhcmd1bWVudHM6IChhcnJWYWwsIG90aFZhbCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tYmluZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfV07XG4gICAgICogdmFyIG90aGVycyA9IFt7ICd4JzogMSwgJ3knOiAxIH0sIHsgJ3gnOiAxLCAneSc6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLnVuaW9uV2l0aChvYmplY3RzLCBvdGhlcnMsIF8uaXNFcXVhbCk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAxIH1dXG4gICAgICovXG4gICAgdmFyIHVuaW9uV2l0aCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGNvbXBhcmF0b3IgPSBsYXN0KGFycmF5cyk7XG4gICAgICBjb21wYXJhdG9yID0gdHlwZW9mIGNvbXBhcmF0b3IgPT0gJ2Z1bmN0aW9uJyA/IGNvbXBhcmF0b3IgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gYmFzZVVuaXEoYmFzZUZsYXR0ZW4oYXJyYXlzLCAxLCBpc0FycmF5TGlrZU9iamVjdCwgdHJ1ZSksIHVuZGVmaW5lZCwgY29tcGFyYXRvcik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZHVwbGljYXRlLWZyZWUgdmVyc2lvbiBvZiBhbiBhcnJheSwgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucywgaW4gd2hpY2ggb25seSB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBlYWNoIGVsZW1lbnRcbiAgICAgKiBpcyBrZXB0LiBUaGUgb3JkZXIgb2YgcmVzdWx0IHZhbHVlcyBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBvcmRlciB0aGV5IG9jY3VyXG4gICAgICogaW4gdGhlIGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pcShbMiwgMSwgMl0pO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaXEoYXJyYXkpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSA/IGJhc2VVbmlxKGFycmF5KSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pcWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHVuaXF1ZW5lc3MgaXMgY29tcHV0ZWQuIFRoZSBvcmRlciBvZiByZXN1bHQgdmFsdWVzIGlzIGRldGVybWluZWQgYnkgdGhlXG4gICAgICogb3JkZXIgdGhleSBvY2N1ciBpbiB0aGUgYXJyYXkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OlxuICAgICAqICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pcUJ5KFsyLjEsIDEuMiwgMi4zXSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzIuMSwgMS4yXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy51bmlxQnkoW3sgJ3gnOiAxIH0sIHsgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSB9LCB7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaXFCeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSA/IGJhc2VVbmlxKGFycmF5LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlxYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjb21wYXJhdG9yYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgdG8gY29tcGFyZSBlbGVtZW50cyBvZiBgYXJyYXlgLiBUaGUgb3JkZXIgb2YgcmVzdWx0IHZhbHVlcyBpc1xuICAgICAqIGRldGVybWluZWQgYnkgdGhlIG9yZGVyIHRoZXkgb2NjdXIgaW4gdGhlIGFycmF5LlRoZSBjb21wYXJhdG9yIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHR3byBhcmd1bWVudHM6IChhcnJWYWwsIG90aFZhbCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH0sIHsgJ3gnOiAxLCAneSc6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLnVuaXFXaXRoKG9iamVjdHMsIF8uaXNFcXVhbCk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaXFXaXRoKGFycmF5LCBjb21wYXJhdG9yKSB7XG4gICAgICBjb21wYXJhdG9yID0gdHlwZW9mIGNvbXBhcmF0b3IgPT0gJ2Z1bmN0aW9uJyA/IGNvbXBhcmF0b3IgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkgPyBiYXNlVW5pcShhcnJheSwgdW5kZWZpbmVkLCBjb21wYXJhdG9yKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uemlwYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGFuIGFycmF5IG9mIGdyb3VwZWRcbiAgICAgKiBlbGVtZW50cyBhbmQgY3JlYXRlcyBhbiBhcnJheSByZWdyb3VwaW5nIHRoZSBlbGVtZW50cyB0byB0aGVpciBwcmUtemlwXG4gICAgICogY29uZmlndXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjIuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgemlwcGVkID0gXy56aXAoWydhJywgJ2InXSwgWzEsIDJdLCBbdHJ1ZSwgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBbWydhJywgMSwgdHJ1ZV0sIFsnYicsIDIsIGZhbHNlXV1cbiAgICAgKlxuICAgICAqIF8udW56aXAoemlwcGVkKTtcbiAgICAgKiAvLyA9PiBbWydhJywgJ2InXSwgWzEsIDJdLCBbdHJ1ZSwgZmFsc2VdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuemlwKGFycmF5KSB7XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSAwO1xuICAgICAgYXJyYXkgPSBhcnJheUZpbHRlcihhcnJheSwgZnVuY3Rpb24oZ3JvdXApIHtcbiAgICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGdyb3VwKSkge1xuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChncm91cC5sZW5ndGgsIGxlbmd0aCk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGJhc2VUaW1lcyhsZW5ndGgsIGZ1bmN0aW9uKGluZGV4KSB7XG4gICAgICAgIHJldHVybiBhcnJheU1hcChhcnJheSwgYmFzZVByb3BlcnR5KGluZGV4KSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuemlwYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgdG8gc3BlY2lmeVxuICAgICAqIGhvdyByZWdyb3VwZWQgdmFsdWVzIHNob3VsZCBiZSBjb21iaW5lZC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aGVcbiAgICAgKiBlbGVtZW50cyBvZiBlYWNoIGdyb3VwOiAoLi4uZ3JvdXApLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuOC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIHRvIGNvbWJpbmVcbiAgICAgKiAgcmVncm91cGVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiByZWdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB6aXBwZWQgPSBfLnppcChbMSwgMl0sIFsxMCwgMjBdLCBbMTAwLCAyMDBdKTtcbiAgICAgKiAvLyA9PiBbWzEsIDEwLCAxMDBdLCBbMiwgMjAsIDIwMF1dXG4gICAgICpcbiAgICAgKiBfLnVuemlwV2l0aCh6aXBwZWQsIF8uYWRkKTtcbiAgICAgKiAvLyA9PiBbMywgMzAsIDMwMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bnppcFdpdGgoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSB1bnppcChhcnJheSk7XG4gICAgICBpZiAoaXRlcmF0ZWUgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5TWFwKHJlc3VsdCwgZnVuY3Rpb24oZ3JvdXApIHtcbiAgICAgICAgcmV0dXJuIGFwcGx5KGl0ZXJhdGVlLCB1bmRlZmluZWQsIGdyb3VwKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgZXhjbHVkaW5nIGFsbCBnaXZlbiB2YWx1ZXMgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ucHVsbGAsIHRoaXMgbWV0aG9kIHJldHVybnMgYSBuZXcgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0gey4uLip9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQHNlZSBfLmRpZmZlcmVuY2UsIF8ueG9yXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ud2l0aG91dChbMiwgMSwgMiwgM10sIDEsIDIpO1xuICAgICAqIC8vID0+IFszXVxuICAgICAqL1xuICAgIHZhciB3aXRob3V0ID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXksIHZhbHVlcykge1xuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlT2JqZWN0KGFycmF5KVxuICAgICAgICA/IGJhc2VEaWZmZXJlbmNlKGFycmF5LCB2YWx1ZXMpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHVuaXF1ZSB2YWx1ZXMgdGhhdCBpcyB0aGVcbiAgICAgKiBbc3ltbWV0cmljIGRpZmZlcmVuY2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1N5bW1ldHJpY19kaWZmZXJlbmNlKVxuICAgICAqIG9mIHRoZSBnaXZlbiBhcnJheXMuIFRoZSBvcmRlciBvZiByZXN1bHQgdmFsdWVzIGlzIGRldGVybWluZWQgYnkgdGhlIG9yZGVyXG4gICAgICogdGhleSBvY2N1ciBpbiB0aGUgYXJyYXlzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuNC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAc2VlIF8uZGlmZmVyZW5jZSwgXy53aXRob3V0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ueG9yKFsyLCAxXSwgWzIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgM11cbiAgICAgKi9cbiAgICB2YXIgeG9yID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICByZXR1cm4gYmFzZVhvcihhcnJheUZpbHRlcihhcnJheXMsIGlzQXJyYXlMaWtlT2JqZWN0KSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnhvcmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IG9mIGVhY2ggYGFycmF5c2AgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieVxuICAgICAqIHdoaWNoIGJ5IHdoaWNoIHRoZXkncmUgY29tcGFyZWQuIFRoZSBvcmRlciBvZiByZXN1bHQgdmFsdWVzIGlzIGRldGVybWluZWRcbiAgICAgKiBieSB0aGUgb3JkZXIgdGhleSBvY2N1ciBpbiB0aGUgYXJyYXlzLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZVxuICAgICAqIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ueG9yQnkoWzIuMSwgMS4yXSwgWzIuMywgMy40XSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzEuMiwgMy40XVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy54b3JCeShbeyAneCc6IDEgfV0sIFt7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgJ3gnKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDIgfV1cbiAgICAgKi9cbiAgICB2YXIgeG9yQnkgPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBpdGVyYXRlZSA9IGxhc3QoYXJyYXlzKTtcbiAgICAgIGlmIChpc0FycmF5TGlrZU9iamVjdChpdGVyYXRlZSkpIHtcbiAgICAgICAgaXRlcmF0ZWUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVhvcihhcnJheUZpbHRlcihhcnJheXMsIGlzQXJyYXlMaWtlT2JqZWN0KSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ueG9yYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjb21wYXJhdG9yYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgdG8gY29tcGFyZSBlbGVtZW50cyBvZiBgYXJyYXlzYC4gVGhlIG9yZGVyIG9mIHJlc3VsdCB2YWx1ZXMgaXNcbiAgICAgKiBkZXRlcm1pbmVkIGJ5IHRoZSBvcmRlciB0aGV5IG9jY3VyIGluIHRoZSBhcnJheXMuIFRoZSBjb21wYXJhdG9yIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHR3byBhcmd1bWVudHM6IChhcnJWYWwsIG90aFZhbCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfV07XG4gICAgICogdmFyIG90aGVycyA9IFt7ICd4JzogMSwgJ3knOiAxIH0sIHsgJ3gnOiAxLCAneSc6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLnhvcldpdGgob2JqZWN0cywgb3RoZXJzLCBfLmlzRXF1YWwpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMiwgJ3knOiAxIH0sIHsgJ3gnOiAxLCAneSc6IDEgfV1cbiAgICAgKi9cbiAgICB2YXIgeG9yV2l0aCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGNvbXBhcmF0b3IgPSBsYXN0KGFycmF5cyk7XG4gICAgICBjb21wYXJhdG9yID0gdHlwZW9mIGNvbXBhcmF0b3IgPT0gJ2Z1bmN0aW9uJyA/IGNvbXBhcmF0b3IgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gYmFzZVhvcihhcnJheUZpbHRlcihhcnJheXMsIGlzQXJyYXlMaWtlT2JqZWN0KSwgdW5kZWZpbmVkLCBjb21wYXJhdG9yKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZ3JvdXBlZCBlbGVtZW50cywgdGhlIGZpcnN0IG9mIHdoaWNoIGNvbnRhaW5zIHRoZVxuICAgICAqIGZpcnN0IGVsZW1lbnRzIG9mIHRoZSBnaXZlbiBhcnJheXMsIHRoZSBzZWNvbmQgb2Ygd2hpY2ggY29udGFpbnMgdGhlXG4gICAgICogc2Vjb25kIGVsZW1lbnRzIG9mIHRoZSBnaXZlbiBhcnJheXMsIGFuZCBzbyBvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcChbJ2EnLCAnYiddLCBbMSwgMl0sIFt0cnVlLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IFtbJ2EnLCAxLCB0cnVlXSwgWydiJywgMiwgZmFsc2VdXVxuICAgICAqL1xuICAgIHZhciB6aXAgPSBiYXNlUmVzdCh1bnppcCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZyb21QYWlyc2AgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyB0d28gYXJyYXlzLFxuICAgICAqIG9uZSBvZiBwcm9wZXJ0eSBpZGVudGlmaWVycyBhbmQgb25lIG9mIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuNC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gW3Byb3BzPVtdXSBUaGUgcHJvcGVydHkgaWRlbnRpZmllcnMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlcz1bXV0gVGhlIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcE9iamVjdChbJ2EnLCAnYiddLCBbMSwgMl0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHppcE9iamVjdChwcm9wcywgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gYmFzZVppcE9iamVjdChwcm9wcyB8fCBbXSwgdmFsdWVzIHx8IFtdLCBhc3NpZ25WYWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy56aXBPYmplY3RgIGV4Y2VwdCB0aGF0IGl0IHN1cHBvcnRzIHByb3BlcnR5IHBhdGhzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gW3Byb3BzPVtdXSBUaGUgcHJvcGVydHkgaWRlbnRpZmllcnMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlcz1bXV0gVGhlIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcE9iamVjdERlZXAoWydhLmJbMF0uYycsICdhLmJbMV0uZCddLCBbMSwgMl0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiB7ICdiJzogW3sgJ2MnOiAxIH0sIHsgJ2QnOiAyIH1dIH0gfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHppcE9iamVjdERlZXAocHJvcHMsIHZhbHVlcykge1xuICAgICAgcmV0dXJuIGJhc2VaaXBPYmplY3QocHJvcHMgfHwgW10sIHZhbHVlcyB8fCBbXSwgYmFzZVNldCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy56aXBgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB0byBzcGVjaWZ5XG4gICAgICogaG93IGdyb3VwZWQgdmFsdWVzIHNob3VsZCBiZSBjb21iaW5lZC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aGVcbiAgICAgKiBlbGVtZW50cyBvZiBlYWNoIGdyb3VwOiAoLi4uZ3JvdXApLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuOC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBwcm9jZXNzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gdG8gY29tYmluZVxuICAgICAqICBncm91cGVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcFdpdGgoWzEsIDJdLCBbMTAsIDIwXSwgWzEwMCwgMjAwXSwgZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIGEgKyBiICsgYztcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbMTExLCAyMjJdXG4gICAgICovXG4gICAgdmFyIHppcFdpdGggPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheXMubGVuZ3RoLFxuICAgICAgICAgIGl0ZXJhdGVlID0gbGVuZ3RoID4gMSA/IGFycmF5c1tsZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcblxuICAgICAgaXRlcmF0ZWUgPSB0eXBlb2YgaXRlcmF0ZWUgPT0gJ2Z1bmN0aW9uJyA/IChhcnJheXMucG9wKCksIGl0ZXJhdGVlKSA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiB1bnppcFdpdGgoYXJyYXlzLCBpdGVyYXRlZSk7XG4gICAgfSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZSB0aGF0IHdyYXBzIGB2YWx1ZWAgd2l0aCBleHBsaWNpdCBtZXRob2RcbiAgICAgKiBjaGFpbiBzZXF1ZW5jZXMgZW5hYmxlZC4gVGhlIHJlc3VsdCBvZiBzdWNoIHNlcXVlbmNlcyBtdXN0IGJlIHVud3JhcHBlZFxuICAgICAqIHdpdGggYF8jdmFsdWVgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMy4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FnZSc6IDQwIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWdlJzogMSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIHZhciB5b3VuZ2VzdCA9IF9cbiAgICAgKiAgIC5jaGFpbih1c2VycylcbiAgICAgKiAgIC5zb3J0QnkoJ2FnZScpXG4gICAgICogICAubWFwKGZ1bmN0aW9uKG8pIHtcbiAgICAgKiAgICAgcmV0dXJuIG8udXNlciArICcgaXMgJyArIG8uYWdlO1xuICAgICAqICAgfSlcbiAgICAgKiAgIC5oZWFkKClcbiAgICAgKiAgIC52YWx1ZSgpO1xuICAgICAqIC8vID0+ICdwZWJibGVzIGlzIDEnXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2hhaW4odmFsdWUpIHtcbiAgICAgIHZhciByZXN1bHQgPSBsb2Rhc2godmFsdWUpO1xuICAgICAgcmVzdWx0Ll9fY2hhaW5fXyA9IHRydWU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGludm9rZXMgYGludGVyY2VwdG9yYCBhbmQgcmV0dXJucyBgdmFsdWVgLiBUaGUgaW50ZXJjZXB0b3JcbiAgICAgKiBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAodmFsdWUpLiBUaGUgcHVycG9zZSBvZiB0aGlzIG1ldGhvZCBpcyB0b1xuICAgICAqIFwidGFwIGludG9cIiBhIG1ldGhvZCBjaGFpbiBzZXF1ZW5jZSBpbiBvcmRlciB0byBtb2RpZnkgaW50ZXJtZWRpYXRlIHJlc3VsdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvdmlkZSB0byBgaW50ZXJjZXB0b3JgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGludGVyY2VwdG9yIFRoZSBmdW5jdGlvbiB0byBpbnZva2UuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgYHZhbHVlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMiwgM10pXG4gICAgICogIC50YXAoZnVuY3Rpb24oYXJyYXkpIHtcbiAgICAgKiAgICAvLyBNdXRhdGUgaW5wdXQgYXJyYXkuXG4gICAgICogICAgYXJyYXkucG9wKCk7XG4gICAgICogIH0pXG4gICAgICogIC5yZXZlcnNlKClcbiAgICAgKiAgLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzIsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGFwKHZhbHVlLCBpbnRlcmNlcHRvcikge1xuICAgICAgaW50ZXJjZXB0b3IodmFsdWUpO1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udGFwYCBleGNlcHQgdGhhdCBpdCByZXR1cm5zIHRoZSByZXN1bHQgb2YgYGludGVyY2VwdG9yYC5cbiAgICAgKiBUaGUgcHVycG9zZSBvZiB0aGlzIG1ldGhvZCBpcyB0byBcInBhc3MgdGhydVwiIHZhbHVlcyByZXBsYWNpbmcgaW50ZXJtZWRpYXRlXG4gICAgICogcmVzdWx0cyBpbiBhIG1ldGhvZCBjaGFpbiBzZXF1ZW5jZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm92aWRlIHRvIGBpbnRlcmNlcHRvcmAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaW50ZXJjZXB0b3IgVGhlIGZ1bmN0aW9uIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzdWx0IG9mIGBpbnRlcmNlcHRvcmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oJyAgYWJjICAnKVxuICAgICAqICAuY2hhaW4oKVxuICAgICAqICAudHJpbSgpXG4gICAgICogIC50aHJ1KGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICogICAgcmV0dXJuIFt2YWx1ZV07XG4gICAgICogIH0pXG4gICAgICogIC52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsnYWJjJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aHJ1KHZhbHVlLCBpbnRlcmNlcHRvcikge1xuICAgICAgcmV0dXJuIGludGVyY2VwdG9yKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyB0aGUgd3JhcHBlciB2ZXJzaW9uIG9mIGBfLmF0YC5cbiAgICAgKlxuICAgICAqIEBuYW1lIGF0XG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHBhcmFtIHsuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3BhdGhzXSBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfSwgNF0gfTtcbiAgICAgKlxuICAgICAqIF8ob2JqZWN0KS5hdChbJ2FbMF0uYi5jJywgJ2FbMV0nXSkudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbMywgNF1cbiAgICAgKi9cbiAgICB2YXIgd3JhcHBlckF0ID0gZmxhdFJlc3QoZnVuY3Rpb24ocGF0aHMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBwYXRocy5sZW5ndGgsXG4gICAgICAgICAgc3RhcnQgPSBsZW5ndGggPyBwYXRoc1swXSA6IDAsXG4gICAgICAgICAgdmFsdWUgPSB0aGlzLl9fd3JhcHBlZF9fLFxuICAgICAgICAgIGludGVyY2VwdG9yID0gZnVuY3Rpb24ob2JqZWN0KSB7IHJldHVybiBiYXNlQXQob2JqZWN0LCBwYXRocyk7IH07XG5cbiAgICAgIGlmIChsZW5ndGggPiAxIHx8IHRoaXMuX19hY3Rpb25zX18ubGVuZ3RoIHx8XG4gICAgICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSB8fCAhaXNJbmRleChzdGFydCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGhydShpbnRlcmNlcHRvcik7XG4gICAgICB9XG4gICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKHN0YXJ0LCArc3RhcnQgKyAobGVuZ3RoID8gMSA6IDApKTtcbiAgICAgIHZhbHVlLl9fYWN0aW9uc19fLnB1c2goe1xuICAgICAgICAnZnVuYyc6IHRocnUsXG4gICAgICAgICdhcmdzJzogW2ludGVyY2VwdG9yXSxcbiAgICAgICAgJ3RoaXNBcmcnOiB1bmRlZmluZWRcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBMb2Rhc2hXcmFwcGVyKHZhbHVlLCB0aGlzLl9fY2hhaW5fXykudGhydShmdW5jdGlvbihhcnJheSkge1xuICAgICAgICBpZiAobGVuZ3RoICYmICFhcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICBhcnJheS5wdXNoKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFycmF5O1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZSB3aXRoIGV4cGxpY2l0IG1ldGhvZCBjaGFpbiBzZXF1ZW5jZXMgZW5hYmxlZC5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNoYWluXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIEEgc2VxdWVuY2Ugd2l0aG91dCBleHBsaWNpdCBjaGFpbmluZy5cbiAgICAgKiBfKHVzZXJzKS5oZWFkKCk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfVxuICAgICAqXG4gICAgICogLy8gQSBzZXF1ZW5jZSB3aXRoIGV4cGxpY2l0IGNoYWluaW5nLlxuICAgICAqIF8odXNlcnMpXG4gICAgICogICAuY2hhaW4oKVxuICAgICAqICAgLmhlYWQoKVxuICAgICAqICAgLnBpY2soJ3VzZXInKVxuICAgICAqICAgLnZhbHVlKCk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdiYXJuZXknIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyQ2hhaW4oKSB7XG4gICAgICByZXR1cm4gY2hhaW4odGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZXMgdGhlIGNoYWluIHNlcXVlbmNlIGFuZCByZXR1cm5zIHRoZSB3cmFwcGVkIHJlc3VsdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNvbW1pdFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMi4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMl07XG4gICAgICogdmFyIHdyYXBwZWQgPSBfKGFycmF5KS5wdXNoKDMpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogd3JhcHBlZCA9IHdyYXBwZWQuY29tbWl0KCk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogd3JhcHBlZC5sYXN0KCk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJDb21taXQoKSB7XG4gICAgICByZXR1cm4gbmV3IExvZGFzaFdyYXBwZXIodGhpcy52YWx1ZSgpLCB0aGlzLl9fY2hhaW5fXyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmV4dCB2YWx1ZSBvbiBhIHdyYXBwZWQgb2JqZWN0IGZvbGxvd2luZyB0aGVcbiAgICAgKiBbaXRlcmF0b3IgcHJvdG9jb2xdKGh0dHBzOi8vbWRuLmlvL2l0ZXJhdGlvbl9wcm90b2NvbHMjaXRlcmF0b3IpLlxuICAgICAqXG4gICAgICogQG5hbWUgbmV4dFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5leHQgaXRlcmF0b3IgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB3cmFwcGVkID0gXyhbMSwgMl0pO1xuICAgICAqXG4gICAgICogd3JhcHBlZC5uZXh0KCk7XG4gICAgICogLy8gPT4geyAnZG9uZSc6IGZhbHNlLCAndmFsdWUnOiAxIH1cbiAgICAgKlxuICAgICAqIHdyYXBwZWQubmV4dCgpO1xuICAgICAqIC8vID0+IHsgJ2RvbmUnOiBmYWxzZSwgJ3ZhbHVlJzogMiB9XG4gICAgICpcbiAgICAgKiB3cmFwcGVkLm5leHQoKTtcbiAgICAgKiAvLyA9PiB7ICdkb25lJzogdHJ1ZSwgJ3ZhbHVlJzogdW5kZWZpbmVkIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyTmV4dCgpIHtcbiAgICAgIGlmICh0aGlzLl9fdmFsdWVzX18gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLl9fdmFsdWVzX18gPSB0b0FycmF5KHRoaXMudmFsdWUoKSk7XG4gICAgICB9XG4gICAgICB2YXIgZG9uZSA9IHRoaXMuX19pbmRleF9fID49IHRoaXMuX192YWx1ZXNfXy5sZW5ndGgsXG4gICAgICAgICAgdmFsdWUgPSBkb25lID8gdW5kZWZpbmVkIDogdGhpcy5fX3ZhbHVlc19fW3RoaXMuX19pbmRleF9fKytdO1xuXG4gICAgICByZXR1cm4geyAnZG9uZSc6IGRvbmUsICd2YWx1ZSc6IHZhbHVlIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyB0aGUgd3JhcHBlciB0byBiZSBpdGVyYWJsZS5cbiAgICAgKlxuICAgICAqIEBuYW1lIFN5bWJvbC5pdGVyYXRvclxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIHdyYXBwZXIgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oWzEsIDJdKTtcbiAgICAgKlxuICAgICAqIHdyYXBwZWRbU3ltYm9sLml0ZXJhdG9yXSgpID09PSB3cmFwcGVkO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIEFycmF5LmZyb20od3JhcHBlZCk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlclRvSXRlcmF0b3IoKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgdGhlIGNoYWluIHNlcXVlbmNlIHBsYW50aW5nIGB2YWx1ZWAgYXMgdGhlIHdyYXBwZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAbmFtZSBwbGFudFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMi4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHBsYW50LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciB3cmFwcGVkID0gXyhbMSwgMl0pLm1hcChzcXVhcmUpO1xuICAgICAqIHZhciBvdGhlciA9IHdyYXBwZWQucGxhbnQoWzMsIDRdKTtcbiAgICAgKlxuICAgICAqIG90aGVyLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzksIDE2XVxuICAgICAqXG4gICAgICogd3JhcHBlZC52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsxLCA0XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJQbGFudCh2YWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCxcbiAgICAgICAgICBwYXJlbnQgPSB0aGlzO1xuXG4gICAgICB3aGlsZSAocGFyZW50IGluc3RhbmNlb2YgYmFzZUxvZGFzaCkge1xuICAgICAgICB2YXIgY2xvbmUgPSB3cmFwcGVyQ2xvbmUocGFyZW50KTtcbiAgICAgICAgY2xvbmUuX19pbmRleF9fID0gMDtcbiAgICAgICAgY2xvbmUuX192YWx1ZXNfXyA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHByZXZpb3VzLl9fd3JhcHBlZF9fID0gY2xvbmU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xvbmU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByZXZpb3VzID0gY2xvbmU7XG4gICAgICAgIHBhcmVudCA9IHBhcmVudC5fX3dyYXBwZWRfXztcbiAgICAgIH1cbiAgICAgIHByZXZpb3VzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIHRoZSB3cmFwcGVyIHZlcnNpb24gb2YgYF8ucmV2ZXJzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyB0aGUgd3JhcHBlZCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBuYW1lIHJldmVyc2VcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDNdO1xuICAgICAqXG4gICAgICogXyhhcnJheSkucmV2ZXJzZSgpLnZhbHVlKClcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyUmV2ZXJzZSgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IHRoaXMuX193cmFwcGVkX187XG4gICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcikge1xuICAgICAgICB2YXIgd3JhcHBlZCA9IHZhbHVlO1xuICAgICAgICBpZiAodGhpcy5fX2FjdGlvbnNfXy5sZW5ndGgpIHtcbiAgICAgICAgICB3cmFwcGVkID0gbmV3IExhenlXcmFwcGVyKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHdyYXBwZWQgPSB3cmFwcGVkLnJldmVyc2UoKTtcbiAgICAgICAgd3JhcHBlZC5fX2FjdGlvbnNfXy5wdXNoKHtcbiAgICAgICAgICAnZnVuYyc6IHRocnUsXG4gICAgICAgICAgJ2FyZ3MnOiBbcmV2ZXJzZV0sXG4gICAgICAgICAgJ3RoaXNBcmcnOiB1bmRlZmluZWRcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih3cmFwcGVkLCB0aGlzLl9fY2hhaW5fXyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy50aHJ1KHJldmVyc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGVzIHRoZSBjaGFpbiBzZXF1ZW5jZSB0byByZXNvbHZlIHRoZSB1bndyYXBwZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAbmFtZSB2YWx1ZVxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGFsaWFzIHRvSlNPTiwgdmFsdWVPZlxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdW53cmFwcGVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfKFsxLCAyLCAzXSkudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyVmFsdWUoKSB7XG4gICAgICByZXR1cm4gYmFzZVdyYXBwZXJWYWx1ZSh0aGlzLl9fd3JhcHBlZF9fLCB0aGlzLl9fYWN0aW9uc19fKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiBrZXlzIGdlbmVyYXRlZCBmcm9tIHRoZSByZXN1bHRzIG9mIHJ1bm5pbmdcbiAgICAgKiBlYWNoIGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIHRocnUgYGl0ZXJhdGVlYC4gVGhlIGNvcnJlc3BvbmRpbmcgdmFsdWUgb2ZcbiAgICAgKiBlYWNoIGtleSBpcyB0aGUgbnVtYmVyIG9mIHRpbWVzIHRoZSBrZXkgd2FzIHJldHVybmVkIGJ5IGBpdGVyYXRlZWAuIFRoZVxuICAgICAqIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC41LjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIHRvIHRyYW5zZm9ybSBrZXlzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbXBvc2VkIGFnZ3JlZ2F0ZSBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY291bnRCeShbNi4xLCA0LjIsIDYuM10sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IHsgJzQnOiAxLCAnNic6IDIgfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5jb3VudEJ5KFsnb25lJywgJ3R3bycsICd0aHJlZSddLCAnbGVuZ3RoJyk7XG4gICAgICogLy8gPT4geyAnMyc6IDIsICc1JzogMSB9XG4gICAgICovXG4gICAgdmFyIGNvdW50QnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwocmVzdWx0LCBrZXkpKSB7XG4gICAgICAgICsrcmVzdWx0W2tleV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUocmVzdWx0LCBrZXksIDEpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciAqKmFsbCoqIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBJdGVyYXRpb24gaXMgc3RvcHBlZCBvbmNlIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIHJldHVybnMgYHRydWVgIGZvclxuICAgICAqIFtlbXB0eSBjb2xsZWN0aW9uc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRW1wdHlfc2V0KSBiZWNhdXNlXG4gICAgICogW2V2ZXJ5dGhpbmcgaXMgdHJ1ZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVmFjdW91c190cnV0aCkgb2ZcbiAgICAgKiBlbGVtZW50cyBvZiBlbXB0eSBjb2xsZWN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbGwgZWxlbWVudHMgcGFzcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZXZlcnkoW3RydWUsIDEsIG51bGwsICd5ZXMnXSwgQm9vbGVhbik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZXZlcnkodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5ldmVyeSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZXZlcnkodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGV2ZXJ5KGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZ3VhcmQpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5RXZlcnkgOiBiYXNlRXZlcnk7XG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBndWFyZCkpIHtcbiAgICAgICAgcHJlZGljYXRlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmAsIHJldHVybmluZyBhbiBhcnJheSBvZiBhbGwgZWxlbWVudHNcbiAgICAgKiBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHRocmVlXG4gICAgICogYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLnJlbW92ZWAsIHRoaXMgbWV0aG9kIHJldHVybnMgYSBuZXcgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmlsdGVyZWQgYXJyYXkuXG4gICAgICogQHNlZSBfLnJlamVjdFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbHRlcih1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIENvbWJpbmluZyBzZXZlcmFsIHByZWRpY2F0ZXMgdXNpbmcgYF8ub3ZlckV2ZXJ5YCBvciBgXy5vdmVyU29tZWAuXG4gICAgICogXy5maWx0ZXIodXNlcnMsIF8ub3ZlclNvbWUoW3sgJ2FnZSc6IDM2IH0sIFsnYWdlJywgNDBdXSkpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCcsICdiYXJuZXknXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbHRlcihjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5RmlsdGVyIDogYmFzZUZpbHRlcjtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gLCByZXR1cm5pbmcgdGhlIGZpcnN0IGVsZW1lbnRcbiAgICAgKiBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHRocmVlXG4gICAgICogYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWF0Y2hlZCBlbGVtZW50LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEsICAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZCh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hZ2UgPCA0MDsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0IGZvciAnYmFybmV5J1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmQodXNlcnMsIHsgJ2FnZSc6IDEsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ3BlYmJsZXMnXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0IGZvciAnZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ2Jhcm5leSdcbiAgICAgKi9cbiAgICB2YXIgZmluZCA9IGNyZWF0ZUZpbmQoZmluZEluZGV4KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PWNvbGxlY3Rpb24ubGVuZ3RoLTFdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWF0Y2hlZCBlbGVtZW50LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZpbmRMYXN0KFsxLCAyLCAzLCA0XSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIG4gJSAyID09IDE7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIHZhciBmaW5kTGFzdCA9IGNyZWF0ZUZpbmQoZmluZExhc3RJbmRleCk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZmxhdHRlbmVkIGFycmF5IG9mIHZhbHVlcyBieSBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmBcbiAgICAgKiB0aHJ1IGBpdGVyYXRlZWAgYW5kIGZsYXR0ZW5pbmcgdGhlIG1hcHBlZCByZXN1bHRzLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGR1cGxpY2F0ZShuKSB7XG4gICAgICogICByZXR1cm4gW24sIG5dO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8uZmxhdE1hcChbMSwgMl0sIGR1cGxpY2F0ZSk7XG4gICAgICogLy8gPT4gWzEsIDEsIDIsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdE1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKG1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSksIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmxhdE1hcGAgZXhjZXB0IHRoYXQgaXQgcmVjdXJzaXZlbHkgZmxhdHRlbnMgdGhlXG4gICAgICogbWFwcGVkIHJlc3VsdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGR1cGxpY2F0ZShuKSB7XG4gICAgICogICByZXR1cm4gW1tbbiwgbl1dXTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZsYXRNYXBEZWVwKFsxLCAyXSwgZHVwbGljYXRlKTtcbiAgICAgKiAvLyA9PiBbMSwgMSwgMiwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGF0TWFwRGVlcChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKG1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSksIElORklOSVRZKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZsYXRNYXBgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGZsYXR0ZW5zIHRoZVxuICAgICAqIG1hcHBlZCByZXN1bHRzIHVwIHRvIGBkZXB0aGAgdGltZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2RlcHRoPTFdIFRoZSBtYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGR1cGxpY2F0ZShuKSB7XG4gICAgICogICByZXR1cm4gW1tbbiwgbl1dXTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZsYXRNYXBEZXB0aChbMSwgMl0sIGR1cGxpY2F0ZSwgMik7XG4gICAgICogLy8gPT4gW1sxLCAxXSwgWzIsIDJdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXRNYXBEZXB0aChjb2xsZWN0aW9uLCBpdGVyYXRlZSwgZGVwdGgpIHtcbiAgICAgIGRlcHRoID0gZGVwdGggPT09IHVuZGVmaW5lZCA/IDEgOiB0b0ludGVnZXIoZGVwdGgpO1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKG1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSksIGRlcHRoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCBhbmQgaW52b2tlcyBgaXRlcmF0ZWVgIGZvciBlYWNoIGVsZW1lbnQuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogQXMgd2l0aCBvdGhlciBcIkNvbGxlY3Rpb25zXCIgbWV0aG9kcywgb2JqZWN0cyB3aXRoIGEgXCJsZW5ndGhcIlxuICAgICAqIHByb3BlcnR5IGFyZSBpdGVyYXRlZCBsaWtlIGFycmF5cy4gVG8gYXZvaWQgdGhpcyBiZWhhdmlvciB1c2UgYF8uZm9ySW5gXG4gICAgICogb3IgYF8uZm9yT3duYCBmb3Igb2JqZWN0IGl0ZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBhbGlhcyBlYWNoXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICogQHNlZSBfLmZvckVhY2hSaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZvckVhY2goWzEsIDJdLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgY29uc29sZS5sb2codmFsdWUpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IExvZ3MgYDFgIHRoZW4gYDJgLlxuICAgICAqXG4gICAgICogXy5mb3JFYWNoKHsgJ2EnOiAxLCAnYic6IDIgfSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBMb2dzICdhJyB0aGVuICdiJyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JFYWNoKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUVhY2ggOiBiYXNlRWFjaDtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mb3JFYWNoYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYGNvbGxlY3Rpb25gIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBhbGlhcyBlYWNoUmlnaHRcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fSBSZXR1cm5zIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBAc2VlIF8uZm9yRWFjaFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZvckVhY2hSaWdodChbMSwgMl0sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICogICBjb25zb2xlLmxvZyh2YWx1ZSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyBgMmAgdGhlbiBgMWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yRWFjaFJpZ2h0KGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUVhY2hSaWdodCA6IGJhc2VFYWNoUmlnaHQ7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIGtleXMgZ2VuZXJhdGVkIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBvZiBgY29sbGVjdGlvbmAgdGhydSBgaXRlcmF0ZWVgLiBUaGUgb3JkZXIgb2YgZ3JvdXBlZCB2YWx1ZXNcbiAgICAgKiBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBvcmRlciB0aGV5IG9jY3VyIGluIGBjb2xsZWN0aW9uYC4gVGhlIGNvcnJlc3BvbmRpbmdcbiAgICAgKiB2YWx1ZSBvZiBlYWNoIGtleSBpcyBhbiBhcnJheSBvZiBlbGVtZW50cyByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGVcbiAgICAgKiBrZXkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmdyb3VwQnkoWzYuMSwgNC4yLCA2LjNdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiB7ICc0JzogWzQuMl0sICc2JzogWzYuMSwgNi4zXSB9XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmdyb3VwQnkoWydvbmUnLCAndHdvJywgJ3RocmVlJ10sICdsZW5ndGgnKTtcbiAgICAgKiAvLyA9PiB7ICczJzogWydvbmUnLCAndHdvJ10sICc1JzogWyd0aHJlZSddIH1cbiAgICAgKi9cbiAgICB2YXIgZ3JvdXBCeSA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsIGtleSkpIHtcbiAgICAgICAgcmVzdWx0W2tleV0ucHVzaCh2YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUocmVzdWx0LCBrZXksIFt2YWx1ZV0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgaW4gYGNvbGxlY3Rpb25gLiBJZiBgY29sbGVjdGlvbmAgaXMgYSBzdHJpbmcsIGl0J3NcbiAgICAgKiBjaGVja2VkIGZvciBhIHN1YnN0cmluZyBvZiBgdmFsdWVgLCBvdGhlcndpc2VcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGlzIHVzZWQgZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLiBJZiBgZnJvbUluZGV4YCBpcyBuZWdhdGl2ZSwgaXQncyB1c2VkIGFzXG4gICAgICogdGhlIG9mZnNldCBmcm9tIHRoZSBlbmQgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5yZWR1Y2VgLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5jbHVkZXMoWzEsIDIsIDNdLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKFsxLCAyLCAzXSwgMSwgMik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaW5jbHVkZXMoeyAnYSc6IDEsICdiJzogMiB9LCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKCdhYmNkJywgJ2JjJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluY2x1ZGVzKGNvbGxlY3Rpb24sIHZhbHVlLCBmcm9tSW5kZXgsIGd1YXJkKSB7XG4gICAgICBjb2xsZWN0aW9uID0gaXNBcnJheUxpa2UoY29sbGVjdGlvbikgPyBjb2xsZWN0aW9uIDogdmFsdWVzKGNvbGxlY3Rpb24pO1xuICAgICAgZnJvbUluZGV4ID0gKGZyb21JbmRleCAmJiAhZ3VhcmQpID8gdG9JbnRlZ2VyKGZyb21JbmRleCkgOiAwO1xuXG4gICAgICB2YXIgbGVuZ3RoID0gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgICBpZiAoZnJvbUluZGV4IDwgMCkge1xuICAgICAgICBmcm9tSW5kZXggPSBuYXRpdmVNYXgobGVuZ3RoICsgZnJvbUluZGV4LCAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc1N0cmluZyhjb2xsZWN0aW9uKVxuICAgICAgICA/IChmcm9tSW5kZXggPD0gbGVuZ3RoICYmIGNvbGxlY3Rpb24uaW5kZXhPZih2YWx1ZSwgZnJvbUluZGV4KSA+IC0xKVxuICAgICAgICA6ICghIWxlbmd0aCAmJiBiYXNlSW5kZXhPZihjb2xsZWN0aW9uLCB2YWx1ZSwgZnJvbUluZGV4KSA+IC0xKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9mIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAsIHJldHVybmluZ1xuICAgICAqIGFuIGFycmF5IG9mIHRoZSByZXN1bHRzIG9mIGVhY2ggaW52b2tlZCBtZXRob2QuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgICAqIGFyZSBwcm92aWRlZCB0byBlYWNoIGludm9rZWQgbWV0aG9kLiBJZiBgcGF0aGAgaXMgYSBmdW5jdGlvbiwgaXQncyBpbnZva2VkXG4gICAgICogZm9yLCBhbmQgYHRoaXNgIGJvdW5kIHRvLCBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtBcnJheXxGdW5jdGlvbnxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2Ugb3JcbiAgICAgKiAgdGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSBlYWNoIG1ldGhvZCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcmVzdWx0cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbnZva2VNYXAoW1s1LCAxLCA3XSwgWzMsIDIsIDFdXSwgJ3NvcnQnKTtcbiAgICAgKiAvLyA9PiBbWzEsIDUsIDddLCBbMSwgMiwgM11dXG4gICAgICpcbiAgICAgKiBfLmludm9rZU1hcChbMTIzLCA0NTZdLCBTdHJpbmcucHJvdG90eXBlLnNwbGl0LCAnJyk7XG4gICAgICogLy8gPT4gW1snMScsICcyJywgJzMnXSwgWyc0JywgJzUnLCAnNiddXVxuICAgICAqL1xuICAgIHZhciBpbnZva2VNYXAgPSBiYXNlUmVzdChmdW5jdGlvbihjb2xsZWN0aW9uLCBwYXRoLCBhcmdzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpc0Z1bmMgPSB0eXBlb2YgcGF0aCA9PSAnZnVuY3Rpb24nLFxuICAgICAgICAgIHJlc3VsdCA9IGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pID8gQXJyYXkoY29sbGVjdGlvbi5sZW5ndGgpIDogW107XG5cbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJlc3VsdFsrK2luZGV4XSA9IGlzRnVuYyA/IGFwcGx5KHBhdGgsIHZhbHVlLCBhcmdzKSA6IGJhc2VJbnZva2UodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCB0aHJ1IGBpdGVyYXRlZWAuIFRoZSBjb3JyZXNwb25kaW5nIHZhbHVlIG9mXG4gICAgICogZWFjaCBrZXkgaXMgdGhlIGxhc3QgZWxlbWVudCByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGUga2V5LiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbXG4gICAgICogICB7ICdkaXInOiAnbGVmdCcsICdjb2RlJzogOTcgfSxcbiAgICAgKiAgIHsgJ2Rpcic6ICdyaWdodCcsICdjb2RlJzogMTAwIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5rZXlCeShhcnJheSwgZnVuY3Rpb24obykge1xuICAgICAqICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoby5jb2RlKTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogeyAnZGlyJzogJ2xlZnQnLCAnY29kZSc6IDk3IH0sICdkJzogeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfSB9XG4gICAgICpcbiAgICAgKiBfLmtleUJ5KGFycmF5LCAnZGlyJyk7XG4gICAgICogLy8gPT4geyAnbGVmdCc6IHsgJ2Rpcic6ICdsZWZ0JywgJ2NvZGUnOiA5NyB9LCAncmlnaHQnOiB7ICdkaXInOiAncmlnaHQnLCAnY29kZSc6IDEwMCB9IH1cbiAgICAgKi9cbiAgICB2YXIga2V5QnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgYmFzZUFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCB2YWx1ZSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHZhbHVlcyBieSBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAgdGhydVxuICAgICAqIGBpdGVyYXRlZWAuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIE1hbnkgbG9kYXNoIG1ldGhvZHMgYXJlIGd1YXJkZWQgdG8gd29yayBhcyBpdGVyYXRlZXMgZm9yIG1ldGhvZHMgbGlrZVxuICAgICAqIGBfLmV2ZXJ5YCwgYF8uZmlsdGVyYCwgYF8ubWFwYCwgYF8ubWFwVmFsdWVzYCwgYF8ucmVqZWN0YCwgYW5kIGBfLnNvbWVgLlxuICAgICAqXG4gICAgICogVGhlIGd1YXJkZWQgbWV0aG9kcyBhcmU6XG4gICAgICogYGFyeWAsIGBjaHVua2AsIGBjdXJyeWAsIGBjdXJyeVJpZ2h0YCwgYGRyb3BgLCBgZHJvcFJpZ2h0YCwgYGV2ZXJ5YCxcbiAgICAgKiBgZmlsbGAsIGBpbnZlcnRgLCBgcGFyc2VJbnRgLCBgcmFuZG9tYCwgYHJhbmdlYCwgYHJhbmdlUmlnaHRgLCBgcmVwZWF0YCxcbiAgICAgKiBgc2FtcGxlU2l6ZWAsIGBzbGljZWAsIGBzb21lYCwgYHNvcnRCeWAsIGBzcGxpdGAsIGB0YWtlYCwgYHRha2VSaWdodGAsXG4gICAgICogYHRlbXBsYXRlYCwgYHRyaW1gLCBgdHJpbUVuZGAsIGB0cmltU3RhcnRgLCBhbmQgYHdvcmRzYFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8ubWFwKFs0LCA4XSwgc3F1YXJlKTtcbiAgICAgKiAvLyA9PiBbMTYsIDY0XVxuICAgICAqXG4gICAgICogXy5tYXAoeyAnYSc6IDQsICdiJzogOCB9LCBzcXVhcmUpO1xuICAgICAqIC8vID0+IFsxNiwgNjRdIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1hcCh1c2VycywgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5TWFwIDogYmFzZU1hcDtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0QnlgIGV4Y2VwdCB0aGF0IGl0IGFsbG93cyBzcGVjaWZ5aW5nIHRoZSBzb3J0XG4gICAgICogb3JkZXJzIG9mIHRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS4gSWYgYG9yZGVyc2AgaXMgdW5zcGVjaWZpZWQsIGFsbCB2YWx1ZXNcbiAgICAgKiBhcmUgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlci4gT3RoZXJ3aXNlLCBzcGVjaWZ5IGFuIG9yZGVyIG9mIFwiZGVzY1wiIGZvclxuICAgICAqIGRlc2NlbmRpbmcgb3IgXCJhc2NcIiBmb3IgYXNjZW5kaW5nIHNvcnQgb3JkZXIgb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5W118RnVuY3Rpb25bXXxPYmplY3RbXXxzdHJpbmdbXX0gW2l0ZXJhdGVlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbb3JkZXJzXSBUaGUgc29ydCBvcmRlcnMgb2YgYGl0ZXJhdGVlc2AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ucmVkdWNlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQ4IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNCB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gU29ydCBieSBgdXNlcmAgaW4gYXNjZW5kaW5nIG9yZGVyIGFuZCBieSBgYWdlYCBpbiBkZXNjZW5kaW5nIG9yZGVyLlxuICAgICAqIF8ub3JkZXJCeSh1c2VycywgWyd1c2VyJywgJ2FnZSddLCBbJ2FzYycsICdkZXNjJ10pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsIDM2XSwgWydiYXJuZXknLCAzNF0sIFsnZnJlZCcsIDQ4XSwgWydmcmVkJywgNDBdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9yZGVyQnkoY29sbGVjdGlvbiwgaXRlcmF0ZWVzLCBvcmRlcnMsIGd1YXJkKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmICghaXNBcnJheShpdGVyYXRlZXMpKSB7XG4gICAgICAgIGl0ZXJhdGVlcyA9IGl0ZXJhdGVlcyA9PSBudWxsID8gW10gOiBbaXRlcmF0ZWVzXTtcbiAgICAgIH1cbiAgICAgIG9yZGVycyA9IGd1YXJkID8gdW5kZWZpbmVkIDogb3JkZXJzO1xuICAgICAgaWYgKCFpc0FycmF5KG9yZGVycykpIHtcbiAgICAgICAgb3JkZXJzID0gb3JkZXJzID09IG51bGwgPyBbXSA6IFtvcmRlcnNdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VPcmRlckJ5KGNvbGxlY3Rpb24sIGl0ZXJhdGVlcywgb3JkZXJzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGVsZW1lbnRzIHNwbGl0IGludG8gdHdvIGdyb3VwcywgdGhlIGZpcnN0IG9mIHdoaWNoXG4gICAgICogY29udGFpbnMgZWxlbWVudHMgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yLCB0aGUgc2Vjb25kIG9mIHdoaWNoXG4gICAgICogY29udGFpbnMgZWxlbWVudHMgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkgZm9yLiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWdlJzogMSwgICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ucGFydGl0aW9uKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snZnJlZCddLCBbJ2Jhcm5leScsICdwZWJibGVzJ11dXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucGFydGl0aW9uKHVzZXJzLCB7ICdhZ2UnOiAxLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1sncGViYmxlcyddLCBbJ2Jhcm5leScsICdmcmVkJ11dXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5wYXJ0aXRpb24odXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydiYXJuZXknLCAncGViYmxlcyddLCBbJ2ZyZWQnXV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucGFydGl0aW9uKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snZnJlZCddLCBbJ2Jhcm5leScsICdwZWJibGVzJ11dXG4gICAgICovXG4gICAgdmFyIHBhcnRpdGlvbiA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICByZXN1bHRba2V5ID8gMCA6IDFdLnB1c2godmFsdWUpO1xuICAgIH0sIGZ1bmN0aW9uKCkgeyByZXR1cm4gW1tdLCBbXV07IH0pO1xuXG4gICAgLyoqXG4gICAgICogUmVkdWNlcyBgY29sbGVjdGlvbmAgdG8gYSB2YWx1ZSB3aGljaCBpcyB0aGUgYWNjdW11bGF0ZWQgcmVzdWx0IG9mIHJ1bm5pbmdcbiAgICAgKiBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gIHRocnUgYGl0ZXJhdGVlYCwgd2hlcmUgZWFjaCBzdWNjZXNzaXZlXG4gICAgICogaW52b2NhdGlvbiBpcyBzdXBwbGllZCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBwcmV2aW91cy4gSWYgYGFjY3VtdWxhdG9yYFxuICAgICAqIGlzIG5vdCBnaXZlbiwgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIGlzIHVzZWQgYXMgdGhlIGluaXRpYWxcbiAgICAgKiB2YWx1ZS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBmb3VyIGFyZ3VtZW50czpcbiAgICAgKiAoYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogTWFueSBsb2Rhc2ggbWV0aG9kcyBhcmUgZ3VhcmRlZCB0byB3b3JrIGFzIGl0ZXJhdGVlcyBmb3IgbWV0aG9kcyBsaWtlXG4gICAgICogYF8ucmVkdWNlYCwgYF8ucmVkdWNlUmlnaHRgLCBhbmQgYF8udHJhbnNmb3JtYC5cbiAgICAgKlxuICAgICAqIFRoZSBndWFyZGVkIG1ldGhvZHMgYXJlOlxuICAgICAqIGBhc3NpZ25gLCBgZGVmYXVsdHNgLCBgZGVmYXVsdHNEZWVwYCwgYGluY2x1ZGVzYCwgYG1lcmdlYCwgYG9yZGVyQnlgLFxuICAgICAqIGFuZCBgc29ydEJ5YFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAc2VlIF8ucmVkdWNlUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yZWR1Y2UoWzEsIDJdLCBmdW5jdGlvbihzdW0sIG4pIHtcbiAgICAgKiAgIHJldHVybiBzdW0gKyBuO1xuICAgICAqIH0sIDApO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8ucmVkdWNlKHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMSB9LCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIChyZXN1bHRbdmFsdWVdIHx8IChyZXN1bHRbdmFsdWVdID0gW10pKS5wdXNoKGtleSk7XG4gICAgICogICByZXR1cm4gcmVzdWx0O1xuICAgICAqIH0sIHt9KTtcbiAgICAgKiAvLyA9PiB7ICcxJzogWydhJywgJ2MnXSwgJzInOiBbJ2InXSB9IChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVkdWNlKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlSZWR1Y2UgOiBiYXNlUmVkdWNlLFxuICAgICAgICAgIGluaXRBY2N1bSA9IGFyZ3VtZW50cy5sZW5ndGggPCAzO1xuXG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgNCksIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0sIGJhc2VFYWNoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnJlZHVjZWAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFthY2N1bXVsYXRvcl0gVGhlIGluaXRpYWwgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgICAqIEBzZWUgXy5yZWR1Y2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gW1swLCAxXSwgWzIsIDNdLCBbNCwgNV1dO1xuICAgICAqXG4gICAgICogXy5yZWR1Y2VSaWdodChhcnJheSwgZnVuY3Rpb24oZmxhdHRlbmVkLCBvdGhlcikge1xuICAgICAqICAgcmV0dXJuIGZsYXR0ZW5lZC5jb25jYXQob3RoZXIpO1xuICAgICAqIH0sIFtdKTtcbiAgICAgKiAvLyA9PiBbNCwgNSwgMiwgMywgMCwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZWR1Y2VSaWdodChjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5UmVkdWNlUmlnaHQgOiBiYXNlUmVkdWNlLFxuICAgICAgICAgIGluaXRBY2N1bSA9IGFyZ3VtZW50cy5sZW5ndGggPCAzO1xuXG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgNCksIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0sIGJhc2VFYWNoUmlnaHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5maWx0ZXJgOyB0aGlzIG1ldGhvZCByZXR1cm5zIHRoZSBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmBcbiAgICAgKiB0aGF0IGBwcmVkaWNhdGVgIGRvZXMgKipub3QqKiByZXR1cm4gdHJ1dGh5IGZvci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICAgKiBAc2VlIF8uZmlsdGVyXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IHRydWUgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlamVjdChjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5RmlsdGVyIDogYmFzZUZpbHRlcjtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIG5lZ2F0ZShnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIHJhbmRvbSBlbGVtZW50IGZyb20gYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzYW1wbGUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNhbXBsZShbMSwgMiwgMywgNF0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYW1wbGUoY29sbGVjdGlvbikge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlTYW1wbGUgOiBiYXNlU2FtcGxlO1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBgbmAgcmFuZG9tIGVsZW1lbnRzIGF0IHVuaXF1ZSBrZXlzIGZyb20gYGNvbGxlY3Rpb25gIHVwIHRvIHRoZVxuICAgICAqIHNpemUgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzYW1wbGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gc2FtcGxlLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSByYW5kb20gZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc2FtcGxlU2l6ZShbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFszLCAxXVxuICAgICAqXG4gICAgICogXy5zYW1wbGVTaXplKFsxLCAyLCAzXSwgNCk7XG4gICAgICogLy8gPT4gWzIsIDMsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2FtcGxlU2l6ZShjb2xsZWN0aW9uLCBuLCBndWFyZCkge1xuICAgICAgaWYgKChndWFyZCA/IGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIG4sIGd1YXJkKSA6IG4gPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgbiA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuID0gdG9JbnRlZ2VyKG4pO1xuICAgICAgfVxuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlTYW1wbGVTaXplIDogYmFzZVNhbXBsZVNpemU7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHNodWZmbGVkIHZhbHVlcywgdXNpbmcgYSB2ZXJzaW9uIG9mIHRoZVxuICAgICAqIFtGaXNoZXItWWF0ZXMgc2h1ZmZsZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRmlzaGVyLVlhdGVzX3NodWZmbGUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzaHVmZmxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNodWZmbGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNodWZmbGUoWzEsIDIsIDMsIDRdKTtcbiAgICAgKiAvLyA9PiBbNCwgMSwgMywgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaHVmZmxlKGNvbGxlY3Rpb24pIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5U2h1ZmZsZSA6IGJhc2VTaHVmZmxlO1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgc2l6ZSBvZiBgY29sbGVjdGlvbmAgYnkgcmV0dXJuaW5nIGl0cyBsZW5ndGggZm9yIGFycmF5LWxpa2VcbiAgICAgKiB2YWx1ZXMgb3IgdGhlIG51bWJlciBvZiBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBmb3Igb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29sbGVjdGlvbiBzaXplLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNpemUoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnNpemUoeyAnYSc6IDEsICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICpcbiAgICAgKiBfLnNpemUoJ3BlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiA3XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2l6ZShjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgICAgaWYgKGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pKSB7XG4gICAgICAgIHJldHVybiBpc1N0cmluZyhjb2xsZWN0aW9uKSA/IHN0cmluZ1NpemUoY29sbGVjdGlvbikgOiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICAgIH1cbiAgICAgIHZhciB0YWcgPSBnZXRUYWcoY29sbGVjdGlvbik7XG4gICAgICBpZiAodGFnID09IG1hcFRhZyB8fCB0YWcgPT0gc2V0VGFnKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uLnNpemU7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUtleXMoY29sbGVjdGlvbikubGVuZ3RoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IgKiphbnkqKiBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBJdGVyYXRpb24gaXMgc3RvcHBlZCBvbmNlIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29tZShbbnVsbCwgMCwgJ3llcycsIGZhbHNlXSwgQm9vbGVhbik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29tZSh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnNvbWUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnNvbWUodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29tZShjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGd1YXJkKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheVNvbWUgOiBiYXNlU29tZTtcbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGd1YXJkKSkge1xuICAgICAgICBwcmVkaWNhdGUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGVsZW1lbnRzLCBzb3J0ZWQgaW4gYXNjZW5kaW5nIG9yZGVyIGJ5IHRoZSByZXN1bHRzIG9mXG4gICAgICogcnVubmluZyBlYWNoIGVsZW1lbnQgaW4gYSBjb2xsZWN0aW9uIHRocnUgZWFjaCBpdGVyYXRlZS4gVGhpcyBtZXRob2RcbiAgICAgKiBwZXJmb3JtcyBhIHN0YWJsZSBzb3J0LCB0aGF0IGlzLCBpdCBwcmVzZXJ2ZXMgdGhlIG9yaWdpbmFsIHNvcnQgb3JkZXIgb2ZcbiAgICAgKiBlcXVhbCBlbGVtZW50cy4gVGhlIGl0ZXJhdGVlcyBhcmUgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbaXRlcmF0ZWVzPVtfLmlkZW50aXR5XV1cbiAgICAgKiAgVGhlIGl0ZXJhdGVlcyB0byBzb3J0IGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNvcnRlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDggfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiAzMCB9LFxuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzQgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnNvcnRCeSh1c2VycywgW2Z1bmN0aW9uKG8pIHsgcmV0dXJuIG8udXNlcjsgfV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsIDM2XSwgWydiYXJuZXknLCAzNF0sIFsnZnJlZCcsIDQ4XSwgWydmcmVkJywgMzBdXVxuICAgICAqXG4gICAgICogXy5zb3J0QnkodXNlcnMsIFsndXNlcicsICdhZ2UnXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snYmFybmV5JywgMzRdLCBbJ2Jhcm5leScsIDM2XSwgWydmcmVkJywgMzBdLCBbJ2ZyZWQnLCA0OF1dXG4gICAgICovXG4gICAgdmFyIHNvcnRCeSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGl0ZXJhdGVlcykge1xuICAgICAgaWYgKGNvbGxlY3Rpb24gPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gaXRlcmF0ZWVzLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggPiAxICYmIGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIGl0ZXJhdGVlc1swXSwgaXRlcmF0ZWVzWzFdKSkge1xuICAgICAgICBpdGVyYXRlZXMgPSBbXTtcbiAgICAgIH0gZWxzZSBpZiAobGVuZ3RoID4gMiAmJiBpc0l0ZXJhdGVlQ2FsbChpdGVyYXRlZXNbMF0sIGl0ZXJhdGVlc1sxXSwgaXRlcmF0ZWVzWzJdKSkge1xuICAgICAgICBpdGVyYXRlZXMgPSBbaXRlcmF0ZWVzWzBdXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlT3JkZXJCeShjb2xsZWN0aW9uLCBiYXNlRmxhdHRlbihpdGVyYXRlZXMsIDEpLCBbXSk7XG4gICAgfSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB0aW1lc3RhbXAgb2YgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdGhhdCBoYXZlIGVsYXBzZWQgc2luY2VcbiAgICAgKiB0aGUgVW5peCBlcG9jaCAoMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjQuMFxuICAgICAqIEBjYXRlZ29yeSBEYXRlXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXN0YW1wLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmVyKGZ1bmN0aW9uKHN0YW1wKSB7XG4gICAgICogICBjb25zb2xlLmxvZyhfLm5vdygpIC0gc3RhbXApO1xuICAgICAqIH0sIF8ubm93KCkpO1xuICAgICAqIC8vID0+IExvZ3MgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgaXQgdG9vayBmb3IgdGhlIGRlZmVycmVkIGludm9jYXRpb24uXG4gICAgICovXG4gICAgdmFyIG5vdyA9IGN0eE5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiByb290LkRhdGUubm93KCk7XG4gICAgfTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5iZWZvcmVgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzXG4gICAgICogYGZ1bmNgIG9uY2UgaXQncyBjYWxsZWQgYG5gIG9yIG1vcmUgdGltZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGNhbGxzIGJlZm9yZSBgZnVuY2AgaXMgaW52b2tlZC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZXN0cmljdGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc2F2ZXMgPSBbJ3Byb2ZpbGUnLCAnc2V0dGluZ3MnXTtcbiAgICAgKlxuICAgICAqIHZhciBkb25lID0gXy5hZnRlcihzYXZlcy5sZW5ndGgsIGZ1bmN0aW9uKCkge1xuICAgICAqICAgY29uc29sZS5sb2coJ2RvbmUgc2F2aW5nIScpO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogXy5mb3JFYWNoKHNhdmVzLCBmdW5jdGlvbih0eXBlKSB7XG4gICAgICogICBhc3luY1NhdmUoeyAndHlwZSc6IHR5cGUsICdjb21wbGV0ZSc6IGRvbmUgfSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnZG9uZSBzYXZpbmchJyBhZnRlciB0aGUgdHdvIGFzeW5jIHNhdmVzIGhhdmUgY29tcGxldGVkLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFmdGVyKG4sIGZ1bmMpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIG4gPSB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICgtLW4gPCAxKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCwgd2l0aCB1cCB0byBgbmAgYXJndW1lbnRzLFxuICAgICAqIGlnbm9yaW5nIGFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhcCBhcmd1bWVudHMgZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj1mdW5jLmxlbmd0aF0gVGhlIGFyaXR5IGNhcC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNhcHBlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzgnLCAnMTAnXSwgXy5hcnkocGFyc2VJbnQsIDEpKTtcbiAgICAgKiAvLyA9PiBbNiwgOCwgMTBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJ5KGZ1bmMsIG4sIGd1YXJkKSB7XG4gICAgICBuID0gZ3VhcmQgPyB1bmRlZmluZWQgOiBuO1xuICAgICAgbiA9IChmdW5jICYmIG4gPT0gbnVsbCkgPyBmdW5jLmxlbmd0aCA6IG47XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBXUkFQX0FSWV9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgLCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBhbmQgYXJndW1lbnRzXG4gICAgICogb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24sIHdoaWxlIGl0J3MgY2FsbGVkIGxlc3MgdGhhbiBgbmAgdGltZXMuIFN1YnNlcXVlbnRcbiAgICAgKiBjYWxscyB0byB0aGUgY3JlYXRlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgY2FsbHMgYXQgd2hpY2ggYGZ1bmNgIGlzIG5vIGxvbmdlciBpbnZva2VkLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlc3RyaWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJlc3RyaWN0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCBfLmJlZm9yZSg1LCBhZGRDb250YWN0VG9MaXN0KSk7XG4gICAgICogLy8gPT4gQWxsb3dzIGFkZGluZyB1cCB0byA0IGNvbnRhY3RzIHRvIHRoZSBsaXN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJlZm9yZShuLCBmdW5jKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKC0tbiA+IDApIHtcbiAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4gPD0gMSkge1xuICAgICAgICAgIGZ1bmMgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgYHRoaXNBcmdgXG4gICAgICogYW5kIGBwYXJ0aWFsc2AgcHJlcGVuZGVkIHRvIHRoZSBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uYmluZC5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljIGJ1aWxkcyxcbiAgICAgKiBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIG5hdGl2ZSBgRnVuY3Rpb24jYmluZGAsIHRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiXG4gICAgICogcHJvcGVydHkgb2YgYm91bmQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYmluZC5cbiAgICAgKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0gey4uLip9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBib3VuZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gZ3JlZXQoZ3JlZXRpbmcsIHB1bmN0dWF0aW9uKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyB0aGlzLnVzZXIgKyBwdW5jdHVhdGlvbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAndXNlcic6ICdmcmVkJyB9O1xuICAgICAqXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kKGdyZWV0LCBvYmplY3QsICdoaScpO1xuICAgICAqIGJvdW5kKCchJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQhJ1xuICAgICAqXG4gICAgICogLy8gQm91bmQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kKGdyZWV0LCBvYmplY3QsIF8sICchJyk7XG4gICAgICogYm91bmQoJ2hpJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQhJ1xuICAgICAqL1xuICAgIHZhciBiaW5kID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gV1JBUF9CSU5EX0ZMQUc7XG4gICAgICBpZiAocGFydGlhbHMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBob2xkZXJzID0gcmVwbGFjZUhvbGRlcnMocGFydGlhbHMsIGdldEhvbGRlcihiaW5kKSk7XG4gICAgICAgIGJpdG1hc2sgfD0gV1JBUF9QQVJUSUFMX0ZMQUc7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBtZXRob2QgYXQgYG9iamVjdFtrZXldYCB3aXRoIGBwYXJ0aWFsc2BcbiAgICAgKiBwcmVwZW5kZWQgdG8gdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGRpZmZlcnMgZnJvbSBgXy5iaW5kYCBieSBhbGxvd2luZyBib3VuZCBmdW5jdGlvbnMgdG8gcmVmZXJlbmNlXG4gICAgICogbWV0aG9kcyB0aGF0IG1heSBiZSByZWRlZmluZWQgb3IgZG9uJ3QgeWV0IGV4aXN0LiBTZWVcbiAgICAgKiBbUGV0ZXIgTWljaGF1eCdzIGFydGljbGVdKGh0dHA6Ly9wZXRlci5taWNoYXV4LmNhL2FydGljbGVzL2xhenktZnVuY3Rpb24tZGVmaW5pdGlvbi1wYXR0ZXJuKVxuICAgICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uYmluZEtleS5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludm9rZSB0aGUgbWV0aG9kIG9uLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgbWV0aG9kLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJvdW5kIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0ge1xuICAgICAqICAgJ3VzZXInOiAnZnJlZCcsXG4gICAgICogICAnZ3JlZXQnOiBmdW5jdGlvbihncmVldGluZywgcHVuY3R1YXRpb24pIHtcbiAgICAgKiAgICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgdGhpcy51c2VyICsgcHVuY3R1YXRpb247XG4gICAgICogICB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZEtleShvYmplY3QsICdncmVldCcsICdoaScpO1xuICAgICAqIGJvdW5kKCchJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQhJ1xuICAgICAqXG4gICAgICogb2JqZWN0LmdyZWV0ID0gZnVuY3Rpb24oZ3JlZXRpbmcsIHB1bmN0dWF0aW9uKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAneWEgJyArIHRoaXMudXNlciArIHB1bmN0dWF0aW9uO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBib3VuZCgnIScpO1xuICAgICAqIC8vID0+ICdoaXlhIGZyZWQhJ1xuICAgICAqXG4gICAgICogLy8gQm91bmQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kS2V5KG9iamVjdCwgJ2dyZWV0JywgXywgJyEnKTtcbiAgICAgKiBib3VuZCgnaGknKTtcbiAgICAgKiAvLyA9PiAnaGl5YSBmcmVkISdcbiAgICAgKi9cbiAgICB2YXIgYmluZEtleSA9IGJhc2VSZXN0KGZ1bmN0aW9uKG9iamVjdCwga2V5LCBwYXJ0aWFscykge1xuICAgICAgdmFyIGJpdG1hc2sgPSBXUkFQX0JJTkRfRkxBRyB8IFdSQVBfQklORF9LRVlfRkxBRztcbiAgICAgIGlmIChwYXJ0aWFscy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgZ2V0SG9sZGVyKGJpbmRLZXkpKTtcbiAgICAgICAgYml0bWFzayB8PSBXUkFQX1BBUlRJQUxfRkxBRztcbiAgICAgIH1cbiAgICAgIHJldHVybiBjcmVhdGVXcmFwKGtleSwgYml0bWFzaywgb2JqZWN0LCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIGFyZ3VtZW50cyBvZiBgZnVuY2AgYW5kIGVpdGhlciBpbnZva2VzXG4gICAgICogYGZ1bmNgIHJldHVybmluZyBpdHMgcmVzdWx0LCBpZiBhdCBsZWFzdCBgYXJpdHlgIG51bWJlciBvZiBhcmd1bWVudHMgaGF2ZVxuICAgICAqIGJlZW4gcHJvdmlkZWQsIG9yIHJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgdGhlIHJlbWFpbmluZyBgZnVuY2BcbiAgICAgKiBhcmd1bWVudHMsIGFuZCBzbyBvbi4gVGhlIGFyaXR5IG9mIGBmdW5jYCBtYXkgYmUgc3BlY2lmaWVkIGlmIGBmdW5jLmxlbmd0aGBcbiAgICAgKiBpcyBub3Qgc3VmZmljaWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5jdXJyeS5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljIGJ1aWxkcyxcbiAgICAgKiBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgY3VycmllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5PWZ1bmMubGVuZ3RoXSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFiYyA9IGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICAgKiAgIHJldHVybiBbYSwgYiwgY107XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIHZhciBjdXJyaWVkID0gXy5jdXJyeShhYmMpO1xuICAgICAqXG4gICAgICogY3VycmllZCgxKSgyKSgzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMSwgMikoMyk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDEsIDIsIDMpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogLy8gQ3VycmllZCB3aXRoIHBsYWNlaG9sZGVycy5cbiAgICAgKiBjdXJyaWVkKDEpKF8sIDMpKDIpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGN1cnJ5KGZ1bmMsIGFyaXR5LCBndWFyZCkge1xuICAgICAgYXJpdHkgPSBndWFyZCA/IHVuZGVmaW5lZCA6IGFyaXR5O1xuICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9DVVJSWV9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkpO1xuICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gY3VycnkucGxhY2Vob2xkZXI7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uY3VycnlgIGV4Y2VwdCB0aGF0IGFyZ3VtZW50cyBhcmUgYXBwbGllZCB0byBgZnVuY2BcbiAgICAgKiBpbiB0aGUgbWFubmVyIG9mIGBfLnBhcnRpYWxSaWdodGAgaW5zdGVhZCBvZiBgXy5wYXJ0aWFsYC5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5jdXJyeVJpZ2h0LnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWNcbiAgICAgKiBidWlsZHMsIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2Vzbid0IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBjdXJyaWVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGN1cnJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHk9ZnVuYy5sZW5ndGhdIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYWJjID0gZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIFthLCBiLCBjXTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGN1cnJpZWQgPSBfLmN1cnJ5UmlnaHQoYWJjKTtcbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMykoMikoMSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDIsIDMpKDEpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogY3VycmllZCgxLCAyLCAzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIC8vIEN1cnJpZWQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogY3VycmllZCgzKSgxLCBfKSgyKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjdXJyeVJpZ2h0KGZ1bmMsIGFyaXR5LCBndWFyZCkge1xuICAgICAgYXJpdHkgPSBndWFyZCA/IHVuZGVmaW5lZCA6IGFyaXR5O1xuICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9DVVJSWV9SSUdIVF9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkpO1xuICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gY3VycnlSaWdodC5wbGFjZWhvbGRlcjtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gICAgICogbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gd2FzXG4gICAgICogaW52b2tlZC4gVGhlIGRlYm91bmNlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGAgbWV0aG9kIHRvIGNhbmNlbFxuICAgICAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICAgICAqIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZVxuICAgICAqIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YCB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50XG4gICAgICogY2FsbHMgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2BcbiAgICAgKiBpbnZvY2F0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICAgICAqIGludm9rZWQgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uXG4gICAgICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICAgICAqXG4gICAgICogSWYgYHdhaXRgIGlzIGAwYCBhbmQgYGxlYWRpbmdgIGlzIGBmYWxzZWAsIGBmdW5jYCBpbnZvY2F0aW9uIGlzIGRlZmVycmVkXG4gICAgICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICAgICAqXG4gICAgICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vZGVib3VuY2luZy10aHJvdHRsaW5nLWV4cGxhaW5lZC1leGFtcGxlcy8pXG4gICAgICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy5kZWJvdW5jZWAgYW5kIGBfLnRocm90dGxlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlYm91bmNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9ZmFsc2VdXG4gICAgICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMubWF4V2FpdF1cbiAgICAgKiAgVGhlIG1heGltdW0gdGltZSBgZnVuY2AgaXMgYWxsb3dlZCB0byBiZSBkZWxheWVkIGJlZm9yZSBpdCdzIGludm9rZWQuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICAgICAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGRlYm91bmNlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogLy8gQXZvaWQgY29zdGx5IGNhbGN1bGF0aW9ucyB3aGlsZSB0aGUgd2luZG93IHNpemUgaXMgaW4gZmx1eC5cbiAgICAgKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgXy5kZWJvdW5jZShjYWxjdWxhdGVMYXlvdXQsIDE1MCkpO1xuICAgICAqXG4gICAgICogLy8gSW52b2tlIGBzZW5kTWFpbGAgd2hlbiBjbGlja2VkLCBkZWJvdW5jaW5nIHN1YnNlcXVlbnQgY2FsbHMuXG4gICAgICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIF8uZGVib3VuY2Uoc2VuZE1haWwsIDMwMCwge1xuICAgICAqICAgJ2xlYWRpbmcnOiB0cnVlLFxuICAgICAqICAgJ3RyYWlsaW5nJzogZmFsc2VcbiAgICAgKiB9KSk7XG4gICAgICpcbiAgICAgKiAvLyBFbnN1cmUgYGJhdGNoTG9nYCBpcyBpbnZva2VkIG9uY2UgYWZ0ZXIgMSBzZWNvbmQgb2YgZGVib3VuY2VkIGNhbGxzLlxuICAgICAqIHZhciBkZWJvdW5jZWQgPSBfLmRlYm91bmNlKGJhdGNoTG9nLCAyNTAsIHsgJ21heFdhaXQnOiAxMDAwIH0pO1xuICAgICAqIHZhciBzb3VyY2UgPSBuZXcgRXZlbnRTb3VyY2UoJy9zdHJlYW0nKTtcbiAgICAgKiBqUXVlcnkoc291cmNlKS5vbignbWVzc2FnZScsIGRlYm91bmNlZCk7XG4gICAgICpcbiAgICAgKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIGRlYm91bmNlZCBpbnZvY2F0aW9uLlxuICAgICAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIGRlYm91bmNlZC5jYW5jZWwpO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlYm91bmNlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBsYXN0QXJncyxcbiAgICAgICAgICBsYXN0VGhpcyxcbiAgICAgICAgICBtYXhXYWl0LFxuICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICB0aW1lcklkLFxuICAgICAgICAgIGxhc3RDYWxsVGltZSxcbiAgICAgICAgICBsYXN0SW52b2tlVGltZSA9IDAsXG4gICAgICAgICAgbGVhZGluZyA9IGZhbHNlLFxuICAgICAgICAgIG1heGluZyA9IGZhbHNlLFxuICAgICAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgd2FpdCA9IHRvTnVtYmVyKHdhaXQpIHx8IDA7XG4gICAgICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgICAgbGVhZGluZyA9ICEhb3B0aW9ucy5sZWFkaW5nO1xuICAgICAgICBtYXhpbmcgPSAnbWF4V2FpdCcgaW4gb3B0aW9ucztcbiAgICAgICAgbWF4V2FpdCA9IG1heGluZyA/IG5hdGl2ZU1heCh0b051bWJlcihvcHRpb25zLm1heFdhaXQpIHx8IDAsIHdhaXQpIDogbWF4V2FpdDtcbiAgICAgICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gaW52b2tlRnVuYyh0aW1lKSB7XG4gICAgICAgIHZhciBhcmdzID0gbGFzdEFyZ3MsXG4gICAgICAgICAgICB0aGlzQXJnID0gbGFzdFRoaXM7XG5cbiAgICAgICAgbGFzdEFyZ3MgPSBsYXN0VGhpcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBsZWFkaW5nRWRnZSh0aW1lKSB7XG4gICAgICAgIC8vIFJlc2V0IGFueSBgbWF4V2FpdGAgdGltZXIuXG4gICAgICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICAgICAgLy8gU3RhcnQgdGhlIHRpbWVyIGZvciB0aGUgdHJhaWxpbmcgZWRnZS5cbiAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgLy8gSW52b2tlIHRoZSBsZWFkaW5nIGVkZ2UuXG4gICAgICAgIHJldHVybiBsZWFkaW5nID8gaW52b2tlRnVuYyh0aW1lKSA6IHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gcmVtYWluaW5nV2FpdCh0aW1lKSB7XG4gICAgICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgICAgICB0aW1lU2luY2VMYXN0SW52b2tlID0gdGltZSAtIGxhc3RJbnZva2VUaW1lLFxuICAgICAgICAgICAgdGltZVdhaXRpbmcgPSB3YWl0IC0gdGltZVNpbmNlTGFzdENhbGw7XG5cbiAgICAgICAgcmV0dXJuIG1heGluZ1xuICAgICAgICAgID8gbmF0aXZlTWluKHRpbWVXYWl0aW5nLCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSlcbiAgICAgICAgICA6IHRpbWVXYWl0aW5nO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBzaG91bGRJbnZva2UodGltZSkge1xuICAgICAgICB2YXIgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lLFxuICAgICAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZTtcblxuICAgICAgICAvLyBFaXRoZXIgdGhpcyBpcyB0aGUgZmlyc3QgY2FsbCwgYWN0aXZpdHkgaGFzIHN0b3BwZWQgYW5kIHdlJ3JlIGF0IHRoZVxuICAgICAgICAvLyB0cmFpbGluZyBlZGdlLCB0aGUgc3lzdGVtIHRpbWUgaGFzIGdvbmUgYmFja3dhcmRzIGFuZCB3ZSdyZSB0cmVhdGluZ1xuICAgICAgICAvLyBpdCBhcyB0aGUgdHJhaWxpbmcgZWRnZSwgb3Igd2UndmUgaGl0IHRoZSBgbWF4V2FpdGAgbGltaXQuXG4gICAgICAgIHJldHVybiAobGFzdENhbGxUaW1lID09PSB1bmRlZmluZWQgfHwgKHRpbWVTaW5jZUxhc3RDYWxsID49IHdhaXQpIHx8XG4gICAgICAgICAgKHRpbWVTaW5jZUxhc3RDYWxsIDwgMCkgfHwgKG1heGluZyAmJiB0aW1lU2luY2VMYXN0SW52b2tlID49IG1heFdhaXQpKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdGltZXJFeHBpcmVkKCkge1xuICAgICAgICB2YXIgdGltZSA9IG5vdygpO1xuICAgICAgICBpZiAoc2hvdWxkSW52b2tlKHRpbWUpKSB7XG4gICAgICAgICAgcmV0dXJuIHRyYWlsaW5nRWRnZSh0aW1lKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZXN0YXJ0IHRoZSB0aW1lci5cbiAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCByZW1haW5pbmdXYWl0KHRpbWUpKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdHJhaWxpbmdFZGdlKHRpbWUpIHtcbiAgICAgICAgdGltZXJJZCA9IHVuZGVmaW5lZDtcblxuICAgICAgICAvLyBPbmx5IGludm9rZSBpZiB3ZSBoYXZlIGBsYXN0QXJnc2Agd2hpY2ggbWVhbnMgYGZ1bmNgIGhhcyBiZWVuXG4gICAgICAgIC8vIGRlYm91bmNlZCBhdCBsZWFzdCBvbmNlLlxuICAgICAgICBpZiAodHJhaWxpbmcgJiYgbGFzdEFyZ3MpIHtcbiAgICAgICAgICByZXR1cm4gaW52b2tlRnVuYyh0aW1lKTtcbiAgICAgICAgfVxuICAgICAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBjYW5jZWwoKSB7XG4gICAgICAgIGlmICh0aW1lcklkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgICAgIH1cbiAgICAgICAgbGFzdEludm9rZVRpbWUgPSAwO1xuICAgICAgICBsYXN0QXJncyA9IGxhc3RDYWxsVGltZSA9IGxhc3RUaGlzID0gdGltZXJJZCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZmx1c2goKSB7XG4gICAgICAgIHJldHVybiB0aW1lcklkID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiB0cmFpbGluZ0VkZ2Uobm93KCkpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkZWJvdW5jZWQoKSB7XG4gICAgICAgIHZhciB0aW1lID0gbm93KCksXG4gICAgICAgICAgICBpc0ludm9raW5nID0gc2hvdWxkSW52b2tlKHRpbWUpO1xuXG4gICAgICAgIGxhc3RBcmdzID0gYXJndW1lbnRzO1xuICAgICAgICBsYXN0VGhpcyA9IHRoaXM7XG4gICAgICAgIGxhc3RDYWxsVGltZSA9IHRpbWU7XG5cbiAgICAgICAgaWYgKGlzSW52b2tpbmcpIHtcbiAgICAgICAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gbGVhZGluZ0VkZ2UobGFzdENhbGxUaW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKG1heGluZykge1xuICAgICAgICAgICAgLy8gSGFuZGxlIGludm9jYXRpb25zIGluIGEgdGlnaHQgbG9vcC5cbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcklkKTtcbiAgICAgICAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgICAgICAgICByZXR1cm4gaW52b2tlRnVuYyhsYXN0Q2FsbFRpbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgZGVib3VuY2VkLmNhbmNlbCA9IGNhbmNlbDtcbiAgICAgIGRlYm91bmNlZC5mbHVzaCA9IGZsdXNoO1xuICAgICAgcmV0dXJuIGRlYm91bmNlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWZlcnMgaW52b2tpbmcgdGhlIGBmdW5jYCB1bnRpbCB0aGUgY3VycmVudCBjYWxsIHN0YWNrIGhhcyBjbGVhcmVkLiBBbnlcbiAgICAgKiBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmUgcHJvdmlkZWQgdG8gYGZ1bmNgIHdoZW4gaXQncyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVmZXIuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgYGZ1bmNgIHdpdGguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXIgaWQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVmZXIoZnVuY3Rpb24odGV4dCkge1xuICAgICAqICAgY29uc29sZS5sb2codGV4dCk7XG4gICAgICogfSwgJ2RlZmVycmVkJyk7XG4gICAgICogLy8gPT4gTG9ncyAnZGVmZXJyZWQnIGFmdGVyIG9uZSBtaWxsaXNlY29uZC5cbiAgICAgKi9cbiAgICB2YXIgZGVmZXIgPSBiYXNlUmVzdChmdW5jdGlvbihmdW5jLCBhcmdzKSB7XG4gICAgICByZXR1cm4gYmFzZURlbGF5KGZ1bmMsIDEsIGFyZ3MpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSW52b2tlcyBgZnVuY2AgYWZ0ZXIgYHdhaXRgIG1pbGxpc2Vjb25kcy4gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZVxuICAgICAqIHByb3ZpZGVkIHRvIGBmdW5jYCB3aGVuIGl0J3MgaW52b2tlZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlbGF5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3YWl0IFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5IGludm9jYXRpb24uXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgYGZ1bmNgIHdpdGguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXIgaWQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVsYXkoZnVuY3Rpb24odGV4dCkge1xuICAgICAqICAgY29uc29sZS5sb2codGV4dCk7XG4gICAgICogfSwgMTAwMCwgJ2xhdGVyJyk7XG4gICAgICogLy8gPT4gTG9ncyAnbGF0ZXInIGFmdGVyIG9uZSBzZWNvbmQuXG4gICAgICovXG4gICAgdmFyIGRlbGF5ID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgd2FpdCwgYXJncykge1xuICAgICAgcmV0dXJuIGJhc2VEZWxheShmdW5jLCB0b051bWJlcih3YWl0KSB8fCAwLCBhcmdzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggYXJndW1lbnRzIHJldmVyc2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZmxpcCBhcmd1bWVudHMgZm9yLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZsaXBwZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBmbGlwcGVkID0gXy5mbGlwKGZ1bmN0aW9uKCkge1xuICAgICAqICAgcmV0dXJuIF8udG9BcnJheShhcmd1bWVudHMpO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogZmxpcHBlZCgnYScsICdiJywgJ2MnLCAnZCcpO1xuICAgICAqIC8vID0+IFsnZCcsICdjJywgJ2InLCAnYSddXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxpcChmdW5jKSB7XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBXUkFQX0ZMSVBfRkxBRyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgbWVtb2l6ZXMgdGhlIHJlc3VsdCBvZiBgZnVuY2AuIElmIGByZXNvbHZlcmAgaXNcbiAgICAgKiBwcm92aWRlZCwgaXQgZGV0ZXJtaW5lcyB0aGUgY2FjaGUga2V5IGZvciBzdG9yaW5nIHRoZSByZXN1bHQgYmFzZWQgb24gdGhlXG4gICAgICogYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBtZW1vaXplZCBmdW5jdGlvbi4gQnkgZGVmYXVsdCwgdGhlIGZpcnN0IGFyZ3VtZW50XG4gICAgICogcHJvdmlkZWQgdG8gdGhlIG1lbW9pemVkIGZ1bmN0aW9uIGlzIHVzZWQgYXMgdGhlIG1hcCBjYWNoZSBrZXkuIFRoZSBgZnVuY2BcbiAgICAgKiBpcyBpbnZva2VkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZSBtZW1vaXplZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGUgY2FjaGUgaXMgZXhwb3NlZCBhcyB0aGUgYGNhY2hlYCBwcm9wZXJ0eSBvbiB0aGUgbWVtb2l6ZWRcbiAgICAgKiBmdW5jdGlvbi4gSXRzIGNyZWF0aW9uIG1heSBiZSBjdXN0b21pemVkIGJ5IHJlcGxhY2luZyB0aGUgYF8ubWVtb2l6ZS5DYWNoZWBcbiAgICAgKiBjb25zdHJ1Y3RvciB3aXRoIG9uZSB3aG9zZSBpbnN0YW5jZXMgaW1wbGVtZW50IHRoZVxuICAgICAqIFtgTWFwYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtcHJvcGVydGllcy1vZi10aGUtbWFwLXByb3RvdHlwZS1vYmplY3QpXG4gICAgICogbWV0aG9kIGludGVyZmFjZSBvZiBgY2xlYXJgLCBgZGVsZXRlYCwgYGdldGAsIGBoYXNgLCBhbmQgYHNldGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBoYXZlIGl0cyBvdXRwdXQgbWVtb2l6ZWQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3Jlc29sdmVyXSBUaGUgZnVuY3Rpb24gdG8gcmVzb2x2ZSB0aGUgY2FjaGUga2V5LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IG1lbW9pemVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogMiB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ2MnOiAzLCAnZCc6IDQgfTtcbiAgICAgKlxuICAgICAqIHZhciB2YWx1ZXMgPSBfLm1lbW9pemUoXy52YWx1ZXMpO1xuICAgICAqIHZhbHVlcyhvYmplY3QpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogdmFsdWVzKG90aGVyKTtcbiAgICAgKiAvLyA9PiBbMywgNF1cbiAgICAgKlxuICAgICAqIG9iamVjdC5hID0gMjtcbiAgICAgKiB2YWx1ZXMob2JqZWN0KTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIC8vIE1vZGlmeSB0aGUgcmVzdWx0IGNhY2hlLlxuICAgICAqIHZhbHVlcy5jYWNoZS5zZXQob2JqZWN0LCBbJ2EnLCAnYiddKTtcbiAgICAgKiB2YWx1ZXMob2JqZWN0KTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYiddXG4gICAgICpcbiAgICAgKiAvLyBSZXBsYWNlIGBfLm1lbW9pemUuQ2FjaGVgLlxuICAgICAqIF8ubWVtb2l6ZS5DYWNoZSA9IFdlYWtNYXA7XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVtb2l6ZShmdW5jLCByZXNvbHZlcikge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicgfHwgKHJlc29sdmVyICE9IG51bGwgJiYgdHlwZW9mIHJlc29sdmVyICE9ICdmdW5jdGlvbicpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHZhciBtZW1vaXplZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAgICAgIGtleSA9IHJlc29sdmVyID8gcmVzb2x2ZXIuYXBwbHkodGhpcywgYXJncykgOiBhcmdzWzBdLFxuICAgICAgICAgICAgY2FjaGUgPSBtZW1vaXplZC5jYWNoZTtcblxuICAgICAgICBpZiAoY2FjaGUuaGFzKGtleSkpIHtcbiAgICAgICAgICByZXR1cm4gY2FjaGUuZ2V0KGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgIG1lbW9pemVkLmNhY2hlID0gY2FjaGUuc2V0KGtleSwgcmVzdWx0KSB8fCBjYWNoZTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgICBtZW1vaXplZC5jYWNoZSA9IG5ldyAobWVtb2l6ZS5DYWNoZSB8fCBNYXBDYWNoZSk7XG4gICAgICByZXR1cm4gbWVtb2l6ZWQ7XG4gICAgfVxuXG4gICAgLy8gRXhwb3NlIGBNYXBDYWNoZWAuXG4gICAgbWVtb2l6ZS5DYWNoZSA9IE1hcENhY2hlO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgbmVnYXRlcyB0aGUgcmVzdWx0IG9mIHRoZSBwcmVkaWNhdGUgYGZ1bmNgLiBUaGVcbiAgICAgKiBgZnVuY2AgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgYW5kIGFyZ3VtZW50cyBvZiB0aGVcbiAgICAgKiBjcmVhdGVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBwcmVkaWNhdGUgdG8gbmVnYXRlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IG5lZ2F0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGlzRXZlbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMDtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZpbHRlcihbMSwgMiwgMywgNCwgNSwgNl0sIF8ubmVnYXRlKGlzRXZlbikpO1xuICAgICAqIC8vID0+IFsxLCAzLCA1XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5lZ2F0ZShwcmVkaWNhdGUpIHtcbiAgICAgIGlmICh0eXBlb2YgcHJlZGljYXRlICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDogcmV0dXJuICFwcmVkaWNhdGUuY2FsbCh0aGlzKTtcbiAgICAgICAgICBjYXNlIDE6IHJldHVybiAhcHJlZGljYXRlLmNhbGwodGhpcywgYXJnc1swXSk7XG4gICAgICAgICAgY2FzZSAyOiByZXR1cm4gIXByZWRpY2F0ZS5jYWxsKHRoaXMsIGFyZ3NbMF0sIGFyZ3NbMV0pO1xuICAgICAgICAgIGNhc2UgMzogcmV0dXJuICFwcmVkaWNhdGUuY2FsbCh0aGlzLCBhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gIXByZWRpY2F0ZS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaXMgcmVzdHJpY3RlZCB0byBpbnZva2luZyBgZnVuY2Agb25jZS4gUmVwZWF0IGNhbGxzXG4gICAgICogdG8gdGhlIGZ1bmN0aW9uIHJldHVybiB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGludm9jYXRpb24uIFRoZSBgZnVuY2AgaXNcbiAgICAgKiBpbnZva2VkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIGFuZCBhcmd1bWVudHMgb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZXN0cmljdGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgaW5pdGlhbGl6ZSA9IF8ub25jZShjcmVhdGVBcHBsaWNhdGlvbik7XG4gICAgICogaW5pdGlhbGl6ZSgpO1xuICAgICAqIGluaXRpYWxpemUoKTtcbiAgICAgKiAvLyA9PiBgY3JlYXRlQXBwbGljYXRpb25gIGlzIGludm9rZWQgb25jZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9uY2UoZnVuYykge1xuICAgICAgcmV0dXJuIGJlZm9yZSgyLCBmdW5jKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGl0cyBhcmd1bWVudHMgdHJhbnNmb3JtZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbdHJhbnNmb3Jtcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBhcmd1bWVudCB0cmFuc2Zvcm1zLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBkb3VibGVkKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBmdW5jID0gXy5vdmVyQXJncyhmdW5jdGlvbih4LCB5KSB7XG4gICAgICogICByZXR1cm4gW3gsIHldO1xuICAgICAqIH0sIFtzcXVhcmUsIGRvdWJsZWRdKTtcbiAgICAgKlxuICAgICAqIGZ1bmMoOSwgMyk7XG4gICAgICogLy8gPT4gWzgxLCA2XVxuICAgICAqXG4gICAgICogZnVuYygxMCwgNSk7XG4gICAgICogLy8gPT4gWzEwMCwgMTBdXG4gICAgICovXG4gICAgdmFyIG92ZXJBcmdzID0gY2FzdFJlc3QoZnVuY3Rpb24oZnVuYywgdHJhbnNmb3Jtcykge1xuICAgICAgdHJhbnNmb3JtcyA9ICh0cmFuc2Zvcm1zLmxlbmd0aCA9PSAxICYmIGlzQXJyYXkodHJhbnNmb3Jtc1swXSkpXG4gICAgICAgID8gYXJyYXlNYXAodHJhbnNmb3Jtc1swXSwgYmFzZVVuYXJ5KGdldEl0ZXJhdGVlKCkpKVxuICAgICAgICA6IGFycmF5TWFwKGJhc2VGbGF0dGVuKHRyYW5zZm9ybXMsIDEpLCBiYXNlVW5hcnkoZ2V0SXRlcmF0ZWUoKSkpO1xuXG4gICAgICB2YXIgZnVuY3NMZW5ndGggPSB0cmFuc2Zvcm1zLmxlbmd0aDtcbiAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgICAgbGVuZ3RoID0gbmF0aXZlTWluKGFyZ3MubGVuZ3RoLCBmdW5jc0xlbmd0aCk7XG5cbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBhcmdzW2luZGV4XSA9IHRyYW5zZm9ybXNbaW5kZXhdLmNhbGwodGhpcywgYXJnc1tpbmRleF0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcHBseShmdW5jLCB0aGlzLCBhcmdzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCBgcGFydGlhbHNgIHByZXBlbmRlZCB0byB0aGVcbiAgICAgKiBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYmluZGAgZXhjZXB0IGl0IGRvZXMgKipub3QqKlxuICAgICAqIGFsdGVyIHRoZSBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5wYXJ0aWFsLnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWNcbiAgICAgKiBidWlsZHMsIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2Vzbid0IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBwYXJ0aWFsbHlcbiAgICAgKiBhcHBsaWVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjIuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHBhcnRpYWxseSBhcHBseSBhcmd1bWVudHMgdG8uXG4gICAgICogQHBhcmFtIHsuLi4qfSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcGFydGlhbGx5IGFwcGxpZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGdyZWV0KGdyZWV0aW5nLCBuYW1lKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyBuYW1lO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBzYXlIZWxsb1RvID0gXy5wYXJ0aWFsKGdyZWV0LCAnaGVsbG8nKTtcbiAgICAgKiBzYXlIZWxsb1RvKCdmcmVkJyk7XG4gICAgICogLy8gPT4gJ2hlbGxvIGZyZWQnXG4gICAgICpcbiAgICAgKiAvLyBQYXJ0aWFsbHkgYXBwbGllZCB3aXRoIHBsYWNlaG9sZGVycy5cbiAgICAgKiB2YXIgZ3JlZXRGcmVkID0gXy5wYXJ0aWFsKGdyZWV0LCBfLCAnZnJlZCcpO1xuICAgICAqIGdyZWV0RnJlZCgnaGknKTtcbiAgICAgKiAvLyA9PiAnaGkgZnJlZCdcbiAgICAgKi9cbiAgICB2YXIgcGFydGlhbCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGZ1bmMsIHBhcnRpYWxzKSB7XG4gICAgICB2YXIgaG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKHBhcnRpYWxzLCBnZXRIb2xkZXIocGFydGlhbCkpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9QQVJUSUFMX0ZMQUcsIHVuZGVmaW5lZCwgcGFydGlhbHMsIGhvbGRlcnMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5wYXJ0aWFsYCBleGNlcHQgdGhhdCBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHNcbiAgICAgKiBhcmUgYXBwZW5kZWQgdG8gdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5wYXJ0aWFsUmlnaHQucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpY1xuICAgICAqIGJ1aWxkcywgbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IG9mIHBhcnRpYWxseVxuICAgICAqIGFwcGxpZWQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5IGFyZ3VtZW50cyB0by5cbiAgICAgKiBAcGFyYW0gey4uLip9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBwYXJ0aWFsbHkgYXBwbGllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gZ3JlZXQoZ3JlZXRpbmcsIG5hbWUpIHtcbiAgICAgKiAgIHJldHVybiBncmVldGluZyArICcgJyArIG5hbWU7XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIGdyZWV0RnJlZCA9IF8ucGFydGlhbFJpZ2h0KGdyZWV0LCAnZnJlZCcpO1xuICAgICAqIGdyZWV0RnJlZCgnaGknKTtcbiAgICAgKiAvLyA9PiAnaGkgZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIFBhcnRpYWxseSBhcHBsaWVkIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIHZhciBzYXlIZWxsb1RvID0gXy5wYXJ0aWFsUmlnaHQoZ3JlZXQsICdoZWxsbycsIF8pO1xuICAgICAqIHNheUhlbGxvVG8oJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCdcbiAgICAgKi9cbiAgICB2YXIgcGFydGlhbFJpZ2h0ID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBob2xkZXJzID0gcmVwbGFjZUhvbGRlcnMocGFydGlhbHMsIGdldEhvbGRlcihwYXJ0aWFsUmlnaHQpKTtcbiAgICAgIHJldHVybiBjcmVhdGVXcmFwKGZ1bmMsIFdSQVBfUEFSVElBTF9SSUdIVF9GTEFHLCB1bmRlZmluZWQsIHBhcnRpYWxzLCBob2xkZXJzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggYXJndW1lbnRzIGFycmFuZ2VkIGFjY29yZGluZ1xuICAgICAqIHRvIHRoZSBzcGVjaWZpZWQgYGluZGV4ZXNgIHdoZXJlIHRoZSBhcmd1bWVudCB2YWx1ZSBhdCB0aGUgZmlyc3QgaW5kZXggaXNcbiAgICAgKiBwcm92aWRlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQsIHRoZSBhcmd1bWVudCB2YWx1ZSBhdCB0aGUgc2Vjb25kIGluZGV4IGlzXG4gICAgICogcHJvdmlkZWQgYXMgdGhlIHNlY29uZCBhcmd1bWVudCwgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcmVhcnJhbmdlIGFyZ3VtZW50cyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4obnVtYmVyfG51bWJlcltdKX0gaW5kZXhlcyBUaGUgYXJyYW5nZWQgYXJndW1lbnQgaW5kZXhlcy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHJlYXJnZWQgPSBfLnJlYXJnKGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICAgKiAgIHJldHVybiBbYSwgYiwgY107XG4gICAgICogfSwgWzIsIDAsIDFdKTtcbiAgICAgKlxuICAgICAqIHJlYXJnZWQoJ2InLCAnYycsICdhJylcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKi9cbiAgICB2YXIgcmVhcmcgPSBmbGF0UmVzdChmdW5jdGlvbihmdW5jLCBpbmRleGVzKSB7XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBXUkFQX1JFQVJHX0ZMQUcsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGluZGV4ZXMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgdGhlXG4gICAgICogY3JlYXRlZCBmdW5jdGlvbiBhbmQgYXJndW1lbnRzIGZyb20gYHN0YXJ0YCBhbmQgYmV5b25kIHByb3ZpZGVkIGFzXG4gICAgICogYW4gYXJyYXkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb24gdGhlXG4gICAgICogW3Jlc3QgcGFyYW1ldGVyXShodHRwczovL21kbi5pby9yZXN0X3BhcmFtZXRlcnMpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXBwbHkgYSByZXN0IHBhcmFtZXRlciB0by5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PWZ1bmMubGVuZ3RoLTFdIFRoZSBzdGFydCBwb3NpdGlvbiBvZiB0aGUgcmVzdCBwYXJhbWV0ZXIuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBzYXkgPSBfLnJlc3QoZnVuY3Rpb24od2hhdCwgbmFtZXMpIHtcbiAgICAgKiAgIHJldHVybiB3aGF0ICsgJyAnICsgXy5pbml0aWFsKG5hbWVzKS5qb2luKCcsICcpICtcbiAgICAgKiAgICAgKF8uc2l6ZShuYW1lcykgPiAxID8gJywgJiAnIDogJycpICsgXy5sYXN0KG5hbWVzKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHNheSgnaGVsbG8nLCAnZnJlZCcsICdiYXJuZXknLCAncGViYmxlcycpO1xuICAgICAqIC8vID0+ICdoZWxsbyBmcmVkLCBiYXJuZXksICYgcGViYmxlcydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXN0KGZ1bmMsIHN0YXJ0KSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICBzdGFydCA9IHN0YXJ0ID09PSB1bmRlZmluZWQgPyBzdGFydCA6IHRvSW50ZWdlcihzdGFydCk7XG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuYywgc3RhcnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZVxuICAgICAqIGNyZWF0ZSBmdW5jdGlvbiBhbmQgYW4gYXJyYXkgb2YgYXJndW1lbnRzIG11Y2ggbGlrZVxuICAgICAqIFtgRnVuY3Rpb24jYXBwbHlgXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtZnVuY3Rpb24ucHJvdG90eXBlLmFwcGx5KS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvbiB0aGVcbiAgICAgKiBbc3ByZWFkIG9wZXJhdG9yXShodHRwczovL21kbi5pby9zcHJlYWRfb3BlcmF0b3IpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMi4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gc3ByZWFkIGFyZ3VtZW50cyBvdmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uIG9mIHRoZSBzcHJlYWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBzYXkgPSBfLnNwcmVhZChmdW5jdGlvbih3aG8sIHdoYXQpIHtcbiAgICAgKiAgIHJldHVybiB3aG8gKyAnIHNheXMgJyArIHdoYXQ7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBzYXkoWydmcmVkJywgJ2hlbGxvJ10pO1xuICAgICAqIC8vID0+ICdmcmVkIHNheXMgaGVsbG8nXG4gICAgICpcbiAgICAgKiB2YXIgbnVtYmVycyA9IFByb21pc2UuYWxsKFtcbiAgICAgKiAgIFByb21pc2UucmVzb2x2ZSg0MCksXG4gICAgICogICBQcm9taXNlLnJlc29sdmUoMzYpXG4gICAgICogXSk7XG4gICAgICpcbiAgICAgKiBudW1iZXJzLnRoZW4oXy5zcHJlYWQoZnVuY3Rpb24oeCwgeSkge1xuICAgICAqICAgcmV0dXJuIHggKyB5O1xuICAgICAqIH0pKTtcbiAgICAgKiAvLyA9PiBhIFByb21pc2Ugb2YgNzZcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzcHJlYWQoZnVuYywgc3RhcnQpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHN0YXJ0ID0gc3RhcnQgPT0gbnVsbCA/IDAgOiBuYXRpdmVNYXgodG9JbnRlZ2VyKHN0YXJ0KSwgMCk7XG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgYXJyYXkgPSBhcmdzW3N0YXJ0XSxcbiAgICAgICAgICAgIG90aGVyQXJncyA9IGNhc3RTbGljZShhcmdzLCAwLCBzdGFydCk7XG5cbiAgICAgICAgaWYgKGFycmF5KSB7XG4gICAgICAgICAgYXJyYXlQdXNoKG90aGVyQXJncywgYXJyYXkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcHBseShmdW5jLCB0aGlzLCBvdGhlckFyZ3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHRocm90dGxlZCBmdW5jdGlvbiB0aGF0IG9ubHkgaW52b2tlcyBgZnVuY2AgYXQgbW9zdCBvbmNlIHBlclxuICAgICAqIGV2ZXJ5IGB3YWl0YCBtaWxsaXNlY29uZHMuIFRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgXG4gICAgICogbWV0aG9kIHRvIGNhbmNlbCBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0b1xuICAgICAqIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLiBQcm92aWRlIGBvcHRpb25zYCB0byBpbmRpY2F0ZSB3aGV0aGVyIGBmdW5jYFxuICAgICAqIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZSBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGBcbiAgICAgKiB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWQgd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlXG4gICAgICogdGhyb3R0bGVkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50IGNhbGxzIHRvIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gcmV0dXJuIHRoZVxuICAgICAqIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXNcbiAgICAgKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIHRocm90dGxlZCBmdW5jdGlvblxuICAgICAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAgICAgKlxuICAgICAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICAgICAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAgICAgKlxuICAgICAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICAgICAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8udGhyb3R0bGVgIGFuZCBgXy5kZWJvdW5jZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3dhaXQ9MF0gVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gdGhyb3R0bGUgaW52b2NhdGlvbnMgdG8uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPXRydWVdXG4gICAgICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gICAgICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgdGhyb3R0bGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBBdm9pZCBleGNlc3NpdmVseSB1cGRhdGluZyB0aGUgcG9zaXRpb24gd2hpbGUgc2Nyb2xsaW5nLlxuICAgICAqIGpRdWVyeSh3aW5kb3cpLm9uKCdzY3JvbGwnLCBfLnRocm90dGxlKHVwZGF0ZVBvc2l0aW9uLCAxMDApKTtcbiAgICAgKlxuICAgICAqIC8vIEludm9rZSBgcmVuZXdUb2tlbmAgd2hlbiB0aGUgY2xpY2sgZXZlbnQgaXMgZmlyZWQsIGJ1dCBub3QgbW9yZSB0aGFuIG9uY2UgZXZlcnkgNSBtaW51dGVzLlxuICAgICAqIHZhciB0aHJvdHRsZWQgPSBfLnRocm90dGxlKHJlbmV3VG9rZW4sIDMwMDAwMCwgeyAndHJhaWxpbmcnOiBmYWxzZSB9KTtcbiAgICAgKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgdGhyb3R0bGVkKTtcbiAgICAgKlxuICAgICAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgdGhyb3R0bGVkIGludm9jYXRpb24uXG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgdGhyb3R0bGVkLmNhbmNlbCk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gdGhyb3R0bGUoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICAgICAgdmFyIGxlYWRpbmcgPSB0cnVlLFxuICAgICAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICAgIGxlYWRpbmcgPSAnbGVhZGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy5sZWFkaW5nIDogbGVhZGluZztcbiAgICAgICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgICAgIH1cbiAgICAgIHJldHVybiBkZWJvdW5jZShmdW5jLCB3YWl0LCB7XG4gICAgICAgICdsZWFkaW5nJzogbGVhZGluZyxcbiAgICAgICAgJ21heFdhaXQnOiB3YWl0LFxuICAgICAgICAndHJhaWxpbmcnOiB0cmFpbGluZ1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgYWNjZXB0cyB1cCB0byBvbmUgYXJndW1lbnQsIGlnbm9yaW5nIGFueVxuICAgICAqIGFkZGl0aW9uYWwgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY2FwIGFyZ3VtZW50cyBmb3IuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY2FwcGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1hcChbJzYnLCAnOCcsICcxMCddLCBfLnVuYXJ5KHBhcnNlSW50KSk7XG4gICAgICogLy8gPT4gWzYsIDgsIDEwXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuYXJ5KGZ1bmMpIHtcbiAgICAgIHJldHVybiBhcnkoZnVuYywgMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcHJvdmlkZXMgYHZhbHVlYCB0byBgd3JhcHBlcmAgYXMgaXRzIGZpcnN0XG4gICAgICogYXJndW1lbnQuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZnVuY3Rpb24gYXJlIGFwcGVuZGVkXG4gICAgICogdG8gdGhvc2UgcHJvdmlkZWQgdG8gdGhlIGB3cmFwcGVyYC4gVGhlIHdyYXBwZXIgaXMgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2BcbiAgICAgKiBiaW5kaW5nIG9mIHRoZSBjcmVhdGVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbd3JhcHBlcj1pZGVudGl0eV0gVGhlIHdyYXBwZXIgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBwID0gXy53cmFwKF8uZXNjYXBlLCBmdW5jdGlvbihmdW5jLCB0ZXh0KSB7XG4gICAgICogICByZXR1cm4gJzxwPicgKyBmdW5jKHRleHQpICsgJzwvcD4nO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogcCgnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnPHA+ZnJlZCwgYmFybmV5LCAmYW1wOyBwZWJibGVzPC9wPidcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwKHZhbHVlLCB3cmFwcGVyKSB7XG4gICAgICByZXR1cm4gcGFydGlhbChjYXN0RnVuY3Rpb24od3JhcHBlciksIHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDYXN0cyBgdmFsdWVgIGFzIGFuIGFycmF5IGlmIGl0J3Mgbm90IG9uZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjQuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNhc3QgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2FzdEFycmF5KDEpO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkoeyAnYSc6IDEgfSk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiAxIH1dXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSgnYWJjJyk7XG4gICAgICogLy8gPT4gWydhYmMnXVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkobnVsbCk7XG4gICAgICogLy8gPT4gW251bGxdXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSh1bmRlZmluZWQpO1xuICAgICAqIC8vID0+IFt1bmRlZmluZWRdXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSgpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgM107XG4gICAgICogY29uc29sZS5sb2coXy5jYXN0QXJyYXkoYXJyYXkpID09PSBhcnJheSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhc3RBcnJheSgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgdmFsdWUgPSBhcmd1bWVudHNbMF07XG4gICAgICByZXR1cm4gaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFt2YWx1ZV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNoYWxsb3cgY2xvbmUgb2YgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBsb29zZWx5IGJhc2VkIG9uIHRoZVxuICAgICAqIFtzdHJ1Y3R1cmVkIGNsb25lIGFsZ29yaXRobV0oaHR0cHM6Ly9tZG4uaW8vU3RydWN0dXJlZF9jbG9uZV9hbGdvcml0aG0pXG4gICAgICogYW5kIHN1cHBvcnRzIGNsb25pbmcgYXJyYXlzLCBhcnJheSBidWZmZXJzLCBib29sZWFucywgZGF0ZSBvYmplY3RzLCBtYXBzLFxuICAgICAqIG51bWJlcnMsIGBPYmplY3RgIG9iamVjdHMsIHJlZ2V4ZXMsIHNldHMsIHN0cmluZ3MsIHN5bWJvbHMsIGFuZCB0eXBlZFxuICAgICAqIGFycmF5cy4gVGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYGFyZ3VtZW50c2Agb2JqZWN0cyBhcmUgY2xvbmVkXG4gICAgICogYXMgcGxhaW4gb2JqZWN0cy4gQW4gZW1wdHkgb2JqZWN0IGlzIHJldHVybmVkIGZvciB1bmNsb25lYWJsZSB2YWx1ZXMgc3VjaFxuICAgICAqIGFzIGVycm9yIG9iamVjdHMsIGZ1bmN0aW9ucywgRE9NIG5vZGVzLCBhbmQgV2Vha01hcHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICogQHNlZSBfLmNsb25lRGVlcFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICdhJzogMSB9LCB7ICdiJzogMiB9XTtcbiAgICAgKlxuICAgICAqIHZhciBzaGFsbG93ID0gXy5jbG9uZShvYmplY3RzKTtcbiAgICAgKiBjb25zb2xlLmxvZyhzaGFsbG93WzBdID09PSBvYmplY3RzWzBdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmUodmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlQ2xvbmUodmFsdWUsIENMT05FX1NZTUJPTFNfRkxBRyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5jbG9uZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIGNsb25lZCB2YWx1ZS4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGAsXG4gICAgICogY2xvbmluZyBpcyBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkIHdpdGhcbiAgICAgKiB1cCB0byBmb3VyIGFyZ3VtZW50czsgKHZhbHVlIFssIGluZGV4fGtleSwgb2JqZWN0LCBzdGFja10pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjbG9uaW5nLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICogQHNlZSBfLmNsb25lRGVlcFdpdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcih2YWx1ZSkge1xuICAgICAqICAgaWYgKF8uaXNFbGVtZW50KHZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdmFsdWUuY2xvbmVOb2RlKGZhbHNlKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZWwgPSBfLmNsb25lV2l0aChkb2N1bWVudC5ib2R5LCBjdXN0b21pemVyKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGVsID09PSBkb2N1bWVudC5ib2R5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqIGNvbnNvbGUubG9nKGVsLm5vZGVOYW1lKTtcbiAgICAgKiAvLyA9PiAnQk9EWSdcbiAgICAgKiBjb25zb2xlLmxvZyhlbC5jaGlsZE5vZGVzLmxlbmd0aCk7XG4gICAgICogLy8gPT4gMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lV2l0aCh2YWx1ZSwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIGJhc2VDbG9uZSh2YWx1ZSwgQ0xPTkVfU1lNQk9MU19GTEFHLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmNsb25lYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBjbG9uZXMgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcmVjdXJzaXZlbHkgY2xvbmUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGRlZXAgY2xvbmVkIHZhbHVlLlxuICAgICAqIEBzZWUgXy5jbG9uZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICdhJzogMSB9LCB7ICdiJzogMiB9XTtcbiAgICAgKlxuICAgICAqIHZhciBkZWVwID0gXy5jbG9uZURlZXAob2JqZWN0cyk7XG4gICAgICogY29uc29sZS5sb2coZGVlcFswXSA9PT0gb2JqZWN0c1swXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZURlZXAodmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlQ2xvbmUodmFsdWUsIENMT05FX0RFRVBfRkxBRyB8IENMT05FX1NZTUJPTFNfRkxBRyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5jbG9uZVdpdGhgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGNsb25lcyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byByZWN1cnNpdmVseSBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjbG9uaW5nLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBkZWVwIGNsb25lZCB2YWx1ZS5cbiAgICAgKiBAc2VlIF8uY2xvbmVXaXRoXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGN1c3RvbWl6ZXIodmFsdWUpIHtcbiAgICAgKiAgIGlmIChfLmlzRWxlbWVudCh2YWx1ZSkpIHtcbiAgICAgKiAgICAgcmV0dXJuIHZhbHVlLmNsb25lTm9kZSh0cnVlKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZWwgPSBfLmNsb25lRGVlcFdpdGgoZG9jdW1lbnQuYm9keSwgY3VzdG9taXplcik7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhlbCA9PT0gZG9jdW1lbnQuYm9keSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKiBjb25zb2xlLmxvZyhlbC5ub2RlTmFtZSk7XG4gICAgICogLy8gPT4gJ0JPRFknXG4gICAgICogY29uc29sZS5sb2coZWwuY2hpbGROb2Rlcy5sZW5ndGgpO1xuICAgICAqIC8vID0+IDIwXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVEZWVwV2l0aCh2YWx1ZSwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIGJhc2VDbG9uZSh2YWx1ZSwgQ0xPTkVfREVFUF9GTEFHIHwgQ0xPTkVfU1lNQk9MU19GTEFHLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYG9iamVjdGAgY29uZm9ybXMgdG8gYHNvdXJjZWAgYnkgaW52b2tpbmcgdGhlIHByZWRpY2F0ZVxuICAgICAqIHByb3BlcnRpZXMgb2YgYHNvdXJjZWAgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBwcm9wZXJ0eSB2YWx1ZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgZXF1aXZhbGVudCB0byBgXy5jb25mb3Jtc2Agd2hlbiBgc291cmNlYCBpc1xuICAgICAqIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTQuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHByZWRpY2F0ZXMgdG8gY29uZm9ybSB0by5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgY29uZm9ybXMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6IDIgfTtcbiAgICAgKlxuICAgICAqIF8uY29uZm9ybXNUbyhvYmplY3QsIHsgJ2InOiBmdW5jdGlvbihuKSB7IHJldHVybiBuID4gMTsgfSB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmNvbmZvcm1zVG8ob2JqZWN0LCB7ICdiJzogZnVuY3Rpb24obikgeyByZXR1cm4gbiA+IDI7IH0gfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25mb3Jtc1RvKG9iamVjdCwgc291cmNlKSB7XG4gICAgICByZXR1cm4gc291cmNlID09IG51bGwgfHwgYmFzZUNvbmZvcm1zVG8ob2JqZWN0LCBzb3VyY2UsIGtleXMoc291cmNlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgYVxuICAgICAqIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlIGVxdWl2YWxlbnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEgfTtcbiAgICAgKiB2YXIgb3RoZXIgPSB7ICdhJzogMSB9O1xuICAgICAqXG4gICAgICogXy5lcShvYmplY3QsIG9iamVjdCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5lcShvYmplY3QsIG90aGVyKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5lcSgnYScsICdhJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5lcSgnYScsIE9iamVjdCgnYScpKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5lcShOYU4sIE5hTik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVxKHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSBvdGhlciB8fCAodmFsdWUgIT09IHZhbHVlICYmIG90aGVyICE9PSBvdGhlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgZ3JlYXRlciB0aGFuIGBvdGhlcmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy45LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBncmVhdGVyIHRoYW4gYG90aGVyYCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBzZWUgXy5sdFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmd0KDMsIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZ3QoMywgMyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uZ3QoMSwgMyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgZ3QgPSBjcmVhdGVSZWxhdGlvbmFsT3BlcmF0aW9uKGJhc2VHdCk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYG90aGVyYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjkuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0b1xuICAgICAqICBgb3RoZXJgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQHNlZSBfLmx0ZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmd0ZSgzLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmd0ZSgzLCAzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmd0ZSgxLCAzKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBndGUgPSBjcmVhdGVSZWxhdGlvbmFsT3BlcmF0aW9uKGZ1bmN0aW9uKHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlID49IG90aGVyO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgbGlrZWx5IGFuIGBhcmd1bWVudHNgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYGFyZ3VtZW50c2Agb2JqZWN0LFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcmd1bWVudHMoZnVuY3Rpb24oKSB7IHJldHVybiBhcmd1bWVudHM7IH0oKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FyZ3VtZW50cyhbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzQXJndW1lbnRzID0gYmFzZUlzQXJndW1lbnRzKGZ1bmN0aW9uKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpID8gYmFzZUlzQXJndW1lbnRzIDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdjYWxsZWUnKSAmJlxuICAgICAgICAhcHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCh2YWx1ZSwgJ2NhbGxlZScpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGFuIGBBcnJheWAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBhcnJheSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoZG9jdW1lbnQuYm9keS5jaGlsZHJlbik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheSgnYWJjJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheShfLm5vb3ApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhbiBgQXJyYXlCdWZmZXJgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjMuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYXJyYXkgYnVmZmVyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUJ1ZmZlcihuZXcgQXJyYXlCdWZmZXIoMikpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUJ1ZmZlcihuZXcgQXJyYXkoMikpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzQXJyYXlCdWZmZXIgPSBub2RlSXNBcnJheUJ1ZmZlciA/IGJhc2VVbmFyeShub2RlSXNBcnJheUJ1ZmZlcikgOiBiYXNlSXNBcnJheUJ1ZmZlcjtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFycmF5LWxpa2UuIEEgdmFsdWUgaXMgY29uc2lkZXJlZCBhcnJheS1saWtlIGlmIGl0J3NcbiAgICAgKiBub3QgYSBmdW5jdGlvbiBhbmQgaGFzIGEgYHZhbHVlLmxlbmd0aGAgdGhhdCdzIGFuIGludGVnZXIgZ3JlYXRlciB0aGFuIG9yXG4gICAgICogZXF1YWwgdG8gYDBgIGFuZCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gYE51bWJlci5NQVhfU0FGRV9JTlRFR0VSYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYXJyYXktbGlrZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZShkb2N1bWVudC5ib2R5LmNoaWxkcmVuKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlKCdhYmMnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlKF8ubm9vcCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0FycmF5TGlrZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgaXNMZW5ndGgodmFsdWUubGVuZ3RoKSAmJiAhaXNGdW5jdGlvbih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pc0FycmF5TGlrZWAgZXhjZXB0IHRoYXQgaXQgYWxzbyBjaGVja3MgaWYgYHZhbHVlYFxuICAgICAqIGlzIGFuIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYXJyYXktbGlrZSBvYmplY3QsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZU9iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2VPYmplY3QoZG9jdW1lbnQuYm9keS5jaGlsZHJlbik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZU9iamVjdCgnYWJjJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2VPYmplY3QoXy5ub29wKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQXJyYXlMaWtlT2JqZWN0KHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBpc0FycmF5TGlrZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGJvb2xlYW4gcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBib29sZWFuLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNCb29sZWFuKGZhbHNlKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQm9vbGVhbihudWxsKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQm9vbGVhbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB0cnVlIHx8IHZhbHVlID09PSBmYWxzZSB8fFxuICAgICAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSBib29sVGFnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIGJ1ZmZlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjMuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBidWZmZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0J1ZmZlcihuZXcgQnVmZmVyKDIpKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQnVmZmVyKG5ldyBVaW50OEFycmF5KDIpKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc0J1ZmZlciA9IG5hdGl2ZUlzQnVmZmVyIHx8IHN0dWJGYWxzZTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgRGF0ZWAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGRhdGUgb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNEYXRlKG5ldyBEYXRlKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRGF0ZSgnTW9uIEFwcmlsIDIzIDIwMTInKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc0RhdGUgPSBub2RlSXNEYXRlID8gYmFzZVVuYXJ5KG5vZGVJc0RhdGUpIDogYmFzZUlzRGF0ZTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxpa2VseSBhIERPTSBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIERPTSBlbGVtZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNFbGVtZW50KGRvY3VtZW50LmJvZHkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbGVtZW50KCc8Ym9keT4nKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRWxlbWVudCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgdmFsdWUubm9kZVR5cGUgPT09IDEgJiYgIWlzUGxhaW5PYmplY3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIGVtcHR5IG9iamVjdCwgY29sbGVjdGlvbiwgbWFwLCBvciBzZXQuXG4gICAgICpcbiAgICAgKiBPYmplY3RzIGFyZSBjb25zaWRlcmVkIGVtcHR5IGlmIHRoZXkgaGF2ZSBubyBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWRcbiAgICAgKiBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogQXJyYXktbGlrZSB2YWx1ZXMgc3VjaCBhcyBgYXJndW1lbnRzYCBvYmplY3RzLCBhcnJheXMsIGJ1ZmZlcnMsIHN0cmluZ3MsIG9yXG4gICAgICogalF1ZXJ5LWxpa2UgY29sbGVjdGlvbnMgYXJlIGNvbnNpZGVyZWQgZW1wdHkgaWYgdGhleSBoYXZlIGEgYGxlbmd0aGAgb2YgYDBgLlxuICAgICAqIFNpbWlsYXJseSwgbWFwcyBhbmQgc2V0cyBhcmUgY29uc2lkZXJlZCBlbXB0eSBpZiB0aGV5IGhhdmUgYSBgc2l6ZWAgb2YgYDBgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBlbXB0eSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkobnVsbCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KHRydWUpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eSgxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KHsgJ2EnOiAxIH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBpZiAoaXNBcnJheUxpa2UodmFsdWUpICYmXG4gICAgICAgICAgKGlzQXJyYXkodmFsdWUpIHx8IHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUuc3BsaWNlID09ICdmdW5jdGlvbicgfHxcbiAgICAgICAgICAgIGlzQnVmZmVyKHZhbHVlKSB8fCBpc1R5cGVkQXJyYXkodmFsdWUpIHx8IGlzQXJndW1lbnRzKHZhbHVlKSkpIHtcbiAgICAgICAgcmV0dXJuICF2YWx1ZS5sZW5ndGg7XG4gICAgICB9XG4gICAgICB2YXIgdGFnID0gZ2V0VGFnKHZhbHVlKTtcbiAgICAgIGlmICh0YWcgPT0gbWFwVGFnIHx8IHRhZyA9PSBzZXRUYWcpIHtcbiAgICAgICAgcmV0dXJuICF2YWx1ZS5zaXplO1xuICAgICAgfVxuICAgICAgaWYgKGlzUHJvdG90eXBlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gIWJhc2VLZXlzKHZhbHVlKS5sZW5ndGg7XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBrZXkgaW4gdmFsdWUpIHtcbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIGtleSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIGEgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gdHdvIHZhbHVlcyB0byBkZXRlcm1pbmUgaWYgdGhleSBhcmVcbiAgICAgKiBlcXVpdmFsZW50LlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIHN1cHBvcnRzIGNvbXBhcmluZyBhcnJheXMsIGFycmF5IGJ1ZmZlcnMsIGJvb2xlYW5zLFxuICAgICAqIGRhdGUgb2JqZWN0cywgZXJyb3Igb2JqZWN0cywgbWFwcywgbnVtYmVycywgYE9iamVjdGAgb2JqZWN0cywgcmVnZXhlcyxcbiAgICAgKiBzZXRzLCBzdHJpbmdzLCBzeW1ib2xzLCBhbmQgdHlwZWQgYXJyYXlzLiBgT2JqZWN0YCBvYmplY3RzIGFyZSBjb21wYXJlZFxuICAgICAqIGJ5IHRoZWlyIG93biwgbm90IGluaGVyaXRlZCwgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLiBGdW5jdGlvbnMgYW5kIERPTVxuICAgICAqIG5vZGVzIGFyZSBjb21wYXJlZCBieSBzdHJpY3QgZXF1YWxpdHksIGkuZS4gYD09PWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEgfTtcbiAgICAgKiB2YXIgb3RoZXIgPSB7ICdhJzogMSB9O1xuICAgICAqXG4gICAgICogXy5pc0VxdWFsKG9iamVjdCwgb3RoZXIpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIG9iamVjdCA9PT0gb3RoZXI7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VxdWFsKHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIGJhc2VJc0VxdWFsKHZhbHVlLCBvdGhlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pc0VxdWFsYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgdG8gY29tcGFyZSB2YWx1ZXMuIElmIGBjdXN0b21pemVyYCByZXR1cm5zIGB1bmRlZmluZWRgLCBjb21wYXJpc29uc1xuICAgICAqIGFyZSBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkIHdpdGggdXAgdG9cbiAgICAgKiBzaXggYXJndW1lbnRzOiAob2JqVmFsdWUsIG90aFZhbHVlIFssIGluZGV4fGtleSwgb2JqZWN0LCBvdGhlciwgc3RhY2tdKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGlzR3JlZXRpbmcodmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiAvXmgoPzppfGVsbG8pJC8udGVzdCh2YWx1ZSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcihvYmpWYWx1ZSwgb3RoVmFsdWUpIHtcbiAgICAgKiAgIGlmIChpc0dyZWV0aW5nKG9ialZhbHVlKSAmJiBpc0dyZWV0aW5nKG90aFZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbJ2hlbGxvJywgJ2dvb2RieWUnXTtcbiAgICAgKiB2YXIgb3RoZXIgPSBbJ2hpJywgJ2dvb2RieWUnXTtcbiAgICAgKlxuICAgICAqIF8uaXNFcXVhbFdpdGgoYXJyYXksIG90aGVyLCBjdXN0b21pemVyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFcXVhbFdpdGgodmFsdWUsIG90aGVyLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICB2YXIgcmVzdWx0ID0gY3VzdG9taXplciA/IGN1c3RvbWl6ZXIodmFsdWUsIG90aGVyKSA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IGJhc2VJc0VxdWFsKHZhbHVlLCBvdGhlciwgdW5kZWZpbmVkLCBjdXN0b21pemVyKSA6ICEhcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIGBFcnJvcmAsIGBFdmFsRXJyb3JgLCBgUmFuZ2VFcnJvcmAsIGBSZWZlcmVuY2VFcnJvcmAsXG4gICAgICogYFN5bnRheEVycm9yYCwgYFR5cGVFcnJvcmAsIG9yIGBVUklFcnJvcmAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBlcnJvciBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0Vycm9yKG5ldyBFcnJvcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Vycm9yKEVycm9yKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRXJyb3IodmFsdWUpIHtcbiAgICAgIGlmICghaXNPYmplY3RMaWtlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgdGFnID0gYmFzZUdldFRhZyh2YWx1ZSk7XG4gICAgICByZXR1cm4gdGFnID09IGVycm9yVGFnIHx8IHRhZyA9PSBkb21FeGNUYWcgfHxcbiAgICAgICAgKHR5cGVvZiB2YWx1ZS5tZXNzYWdlID09ICdzdHJpbmcnICYmIHR5cGVvZiB2YWx1ZS5uYW1lID09ICdzdHJpbmcnICYmICFpc1BsYWluT2JqZWN0KHZhbHVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBmaW5pdGUgcHJpbWl0aXZlIG51bWJlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgTnVtYmVyLmlzRmluaXRlYF0oaHR0cHM6Ly9tZG4uaW8vTnVtYmVyL2lzRmluaXRlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBmaW5pdGUgbnVtYmVyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZShOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRmluaXRlKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZSgnMycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNGaW5pdGUodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgJiYgbmF0aXZlSXNGaW5pdGUodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgRnVuY3Rpb25gIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBmdW5jdGlvbiwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRnVuY3Rpb24oXyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Z1bmN0aW9uKC9hYmMvKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmICghaXNPYmplY3QodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIFRoZSB1c2Ugb2YgYE9iamVjdCN0b1N0cmluZ2AgYXZvaWRzIGlzc3VlcyB3aXRoIHRoZSBgdHlwZW9mYCBvcGVyYXRvclxuICAgICAgLy8gaW4gU2FmYXJpIDkgd2hpY2ggcmV0dXJucyAnb2JqZWN0JyBmb3IgdHlwZWQgYXJyYXlzIGFuZCBvdGhlciBjb25zdHJ1Y3RvcnMuXG4gICAgICB2YXIgdGFnID0gYmFzZUdldFRhZyh2YWx1ZSk7XG4gICAgICByZXR1cm4gdGFnID09IGZ1bmNUYWcgfHwgdGFnID09IGdlblRhZyB8fCB0YWcgPT0gYXN5bmNUYWcgfHwgdGFnID09IHByb3h5VGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIGludGVnZXIuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb25cbiAgICAgKiBbYE51bWJlci5pc0ludGVnZXJgXShodHRwczovL21kbi5pby9OdW1iZXIvaXNJbnRlZ2VyKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gaW50ZWdlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzSW50ZWdlcigzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzSW50ZWdlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0ludGVnZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzSW50ZWdlcignMycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNJbnRlZ2VyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdudW1iZXInICYmIHZhbHVlID09IHRvSW50ZWdlcih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBhcnJheS1saWtlIGxlbmd0aC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBsb29zZWx5IGJhc2VkIG9uXG4gICAgICogW2BUb0xlbmd0aGBdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXRvbGVuZ3RoKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBsZW5ndGgsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0xlbmd0aCgzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTGVuZ3RoKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzTGVuZ3RoKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0xlbmd0aCgnMycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNMZW5ndGgodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgJiZcbiAgICAgICAgdmFsdWUgPiAtMSAmJiB2YWx1ZSAlIDEgPT0gMCAmJiB2YWx1ZSA8PSBNQVhfU0FGRV9JTlRFR0VSO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHRoZVxuICAgICAqIFtsYW5ndWFnZSB0eXBlXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtZWNtYXNjcmlwdC1sYW5ndWFnZS10eXBlcylcbiAgICAgKiBvZiBgT2JqZWN0YC4gKGUuZy4gYXJyYXlzLCBmdW5jdGlvbnMsIG9iamVjdHMsIHJlZ2V4ZXMsIGBuZXcgTnVtYmVyKDApYCwgYW5kIGBuZXcgU3RyaW5nKCcnKWApXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0KHt9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdChfLm5vb3ApO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3QobnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCAmJiAodHlwZSA9PSAnb2JqZWN0JyB8fCB0eXBlID09ICdmdW5jdGlvbicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLiBBIHZhbHVlIGlzIG9iamVjdC1saWtlIGlmIGl0J3Mgbm90IGBudWxsYFxuICAgICAqIGFuZCBoYXMgYSBgdHlwZW9mYCByZXN1bHQgb2YgXCJvYmplY3RcIi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdExpa2Uoe30pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3RMaWtlKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdExpa2UoXy5ub29wKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdExpa2UobnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc09iamVjdExpa2UodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSAhPSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYE1hcGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMy4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG1hcCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTWFwKG5ldyBNYXApO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNNYXAobmV3IFdlYWtNYXApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzTWFwID0gbm9kZUlzTWFwID8gYmFzZVVuYXJ5KG5vZGVJc01hcCkgOiBiYXNlSXNNYXA7XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIHBhcnRpYWwgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gYG9iamVjdGAgYW5kIGBzb3VyY2VgIHRvXG4gICAgICogZGV0ZXJtaW5lIGlmIGBvYmplY3RgIGNvbnRhaW5zIGVxdWl2YWxlbnQgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGVxdWl2YWxlbnQgdG8gYF8ubWF0Y2hlc2Agd2hlbiBgc291cmNlYCBpc1xuICAgICAqIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogUGFydGlhbCBjb21wYXJpc29ucyB3aWxsIG1hdGNoIGVtcHR5IGFycmF5IGFuZCBlbXB0eSBvYmplY3QgYHNvdXJjZWBcbiAgICAgKiB2YWx1ZXMgYWdhaW5zdCBhbnkgYXJyYXkgb3Igb2JqZWN0IHZhbHVlLCByZXNwZWN0aXZlbHkuIFNlZSBgXy5pc0VxdWFsYFxuICAgICAqIGZvciBhIGxpc3Qgb2Ygc3VwcG9ydGVkIHZhbHVlIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgb2JqZWN0YCBpcyBhIG1hdGNoLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAyIH07XG4gICAgICpcbiAgICAgKiBfLmlzTWF0Y2gob2JqZWN0LCB7ICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTWF0Y2gob2JqZWN0LCB7ICdiJzogMSB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTWF0Y2gob2JqZWN0LCBzb3VyY2UpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT09IHNvdXJjZSB8fCBiYXNlSXNNYXRjaChvYmplY3QsIHNvdXJjZSwgZ2V0TWF0Y2hEYXRhKHNvdXJjZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaXNNYXRjaGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIGNvbXBhcmUgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCwgY29tcGFyaXNvbnNcbiAgICAgKiBhcmUgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZCB3aXRoIGZpdmVcbiAgICAgKiBhcmd1bWVudHM6IChvYmpWYWx1ZSwgc3JjVmFsdWUsIGluZGV4fGtleSwgb2JqZWN0LCBzb3VyY2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgb2JqZWN0YCBpcyBhIG1hdGNoLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGlzR3JlZXRpbmcodmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiAvXmgoPzppfGVsbG8pJC8udGVzdCh2YWx1ZSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUpIHtcbiAgICAgKiAgIGlmIChpc0dyZWV0aW5nKG9ialZhbHVlKSAmJiBpc0dyZWV0aW5nKHNyY1ZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnZ3JlZXRpbmcnOiAnaGVsbG8nIH07XG4gICAgICogdmFyIHNvdXJjZSA9IHsgJ2dyZWV0aW5nJzogJ2hpJyB9O1xuICAgICAqXG4gICAgICogXy5pc01hdGNoV2l0aChvYmplY3QsIHNvdXJjZSwgY3VzdG9taXplcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTWF0Y2hXaXRoKG9iamVjdCwgc291cmNlLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gYmFzZUlzTWF0Y2gob2JqZWN0LCBzb3VyY2UsIGdldE1hdGNoRGF0YShzb3VyY2UpLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgTmFOYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgTnVtYmVyLmlzTmFOYF0oaHR0cHM6Ly9tZG4uaW8vTnVtYmVyL2lzTmFOKSBhbmQgaXMgbm90IHRoZSBzYW1lIGFzXG4gICAgICogZ2xvYmFsIFtgaXNOYU5gXShodHRwczovL21kbi5pby9pc05hTikgd2hpY2ggcmV0dXJucyBgdHJ1ZWAgZm9yXG4gICAgICogYHVuZGVmaW5lZGAgYW5kIG90aGVyIG5vbi1udW1iZXIgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgTmFOYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTmFOKE5hTik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc05hTihuZXcgTnVtYmVyKE5hTikpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGlzTmFOKHVuZGVmaW5lZCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc05hTih1bmRlZmluZWQpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOYU4odmFsdWUpIHtcbiAgICAgIC8vIEFuIGBOYU5gIHByaW1pdGl2ZSBpcyB0aGUgb25seSB2YWx1ZSB0aGF0IGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuXG4gICAgICAvLyBQZXJmb3JtIHRoZSBgdG9TdHJpbmdUYWdgIGNoZWNrIGZpcnN0IHRvIGF2b2lkIGVycm9ycyB3aXRoIHNvbWVcbiAgICAgIC8vIEFjdGl2ZVggb2JqZWN0cyBpbiBJRS5cbiAgICAgIHJldHVybiBpc051bWJlcih2YWx1ZSkgJiYgdmFsdWUgIT0gK3ZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgcHJpc3RpbmUgbmF0aXZlIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGNhbid0IHJlbGlhYmx5IGRldGVjdCBuYXRpdmUgZnVuY3Rpb25zIGluIHRoZSBwcmVzZW5jZVxuICAgICAqIG9mIHRoZSBjb3JlLWpzIHBhY2thZ2UgYmVjYXVzZSBjb3JlLWpzIGNpcmN1bXZlbnRzIHRoaXMga2luZCBvZiBkZXRlY3Rpb24uXG4gICAgICogRGVzcGl0ZSBtdWx0aXBsZSByZXF1ZXN0cywgdGhlIGNvcmUtanMgbWFpbnRhaW5lciBoYXMgbWFkZSBpdCBjbGVhcjogYW55XG4gICAgICogYXR0ZW1wdCB0byBmaXggdGhlIGRldGVjdGlvbiB3aWxsIGJlIG9ic3RydWN0ZWQuIEFzIGEgcmVzdWx0LCB3ZSdyZSBsZWZ0XG4gICAgICogd2l0aCBsaXR0bGUgY2hvaWNlIGJ1dCB0byB0aHJvdyBhbiBlcnJvci4gVW5mb3J0dW5hdGVseSwgdGhpcyBhbHNvIGFmZmVjdHNcbiAgICAgKiBwYWNrYWdlcywgbGlrZSBbYmFiZWwtcG9seWZpbGxdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL2JhYmVsLXBvbHlmaWxsKSxcbiAgICAgKiB3aGljaCByZWx5IG9uIGNvcmUtanMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbmF0aXZlIGZ1bmN0aW9uLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNOYXRpdmUoQXJyYXkucHJvdG90eXBlLnB1c2gpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYXRpdmUoXyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc05hdGl2ZSh2YWx1ZSkge1xuICAgICAgaWYgKGlzTWFza2FibGUodmFsdWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihDT1JFX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VJc05hdGl2ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYG51bGxgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgbnVsbGAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc051bGwobnVsbCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc051bGwodm9pZCAwKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTnVsbCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGBudWxsYCBvciBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgbnVsbGlzaCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTmlsKG51bGwpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOaWwodm9pZCAwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTmlsKE5hTik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc05pbCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBOdW1iZXJgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVG8gZXhjbHVkZSBgSW5maW5pdHlgLCBgLUluZmluaXR5YCwgYW5kIGBOYU5gLCB3aGljaCBhcmVcbiAgICAgKiBjbGFzc2lmaWVkIGFzIG51bWJlcnMsIHVzZSB0aGUgYF8uaXNGaW5pdGVgIG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBudW1iZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc051bWJlcigzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTnVtYmVyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdW1iZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdW1iZXIoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTnVtYmVyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdudW1iZXInIHx8XG4gICAgICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IG51bWJlclRhZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBwbGFpbiBvYmplY3QsIHRoYXQgaXMsIGFuIG9iamVjdCBjcmVhdGVkIGJ5IHRoZVxuICAgICAqIGBPYmplY3RgIGNvbnN0cnVjdG9yIG9yIG9uZSB3aXRoIGEgYFtbUHJvdG90eXBlXV1gIG9mIGBudWxsYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjguMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwbGFpbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QobmV3IEZvbyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNQbGFpbk9iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QoeyAneCc6IDAsICd5JzogMCB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QoT2JqZWN0LmNyZWF0ZShudWxsKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgICAgIGlmICghaXNPYmplY3RMaWtlKHZhbHVlKSB8fCBiYXNlR2V0VGFnKHZhbHVlKSAhPSBvYmplY3RUYWcpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIHByb3RvID0gZ2V0UHJvdG90eXBlKHZhbHVlKTtcbiAgICAgIGlmIChwcm90byA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBDdG9yID0gaGFzT3duUHJvcGVydHkuY2FsbChwcm90bywgJ2NvbnN0cnVjdG9yJykgJiYgcHJvdG8uY29uc3RydWN0b3I7XG4gICAgICByZXR1cm4gdHlwZW9mIEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBDdG9yIGluc3RhbmNlb2YgQ3RvciAmJlxuICAgICAgICBmdW5jVG9TdHJpbmcuY2FsbChDdG9yKSA9PSBvYmplY3RDdG9yU3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgUmVnRXhwYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcmVnZXhwLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNSZWdFeHAoL2FiYy8pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNSZWdFeHAoJy9hYmMvJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNSZWdFeHAgPSBub2RlSXNSZWdFeHAgPyBiYXNlVW5hcnkobm9kZUlzUmVnRXhwKSA6IGJhc2VJc1JlZ0V4cDtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgc2FmZSBpbnRlZ2VyLiBBbiBpbnRlZ2VyIGlzIHNhZmUgaWYgaXQncyBhbiBJRUVFLTc1NFxuICAgICAqIGRvdWJsZSBwcmVjaXNpb24gbnVtYmVyIHdoaWNoIGlzbid0IHRoZSByZXN1bHQgb2YgYSByb3VuZGVkIHVuc2FmZSBpbnRlZ2VyLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uXG4gICAgICogW2BOdW1iZXIuaXNTYWZlSW50ZWdlcmBdKGh0dHBzOi8vbWRuLmlvL051bWJlci9pc1NhZmVJbnRlZ2VyKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzYWZlIGludGVnZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1NhZmVJbnRlZ2VyKDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNTYWZlSW50ZWdlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc1NhZmVJbnRlZ2VyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc1NhZmVJbnRlZ2VyKCczJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1NhZmVJbnRlZ2VyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNJbnRlZ2VyKHZhbHVlKSAmJiB2YWx1ZSA+PSAtTUFYX1NBRkVfSU5URUdFUiAmJiB2YWx1ZSA8PSBNQVhfU0FGRV9JTlRFR0VSO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU2V0YCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc2V0LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNTZXQobmV3IFNldCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1NldChuZXcgV2Vha1NldCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNTZXQgPSBub2RlSXNTZXQgPyBiYXNlVW5hcnkobm9kZUlzU2V0KSA6IGJhc2VJc1NldDtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3RyaW5nYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHN0cmluZywgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzU3RyaW5nKCdhYmMnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzU3RyaW5nKDEpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNTdHJpbmcodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycgfHxcbiAgICAgICAgKCFpc0FycmF5KHZhbHVlKSAmJiBpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IHN0cmluZ1RhZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTeW1ib2xgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc3ltYm9sLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNTeW1ib2woU3ltYm9sLml0ZXJhdG9yKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzU3ltYm9sKCdhYmMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU3ltYm9sKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdzeW1ib2wnIHx8XG4gICAgICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IHN5bWJvbFRhZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIHR5cGVkIGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHR5cGVkIGFycmF5LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNUeXBlZEFycmF5KG5ldyBVaW50OEFycmF5KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzVHlwZWRBcnJheShbXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNUeXBlZEFycmF5ID0gbm9kZUlzVHlwZWRBcnJheSA/IGJhc2VVbmFyeShub2RlSXNUeXBlZEFycmF5KSA6IGJhc2VJc1R5cGVkQXJyYXk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1VuZGVmaW5lZCh2b2lkIDApO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNVbmRlZmluZWQobnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1VuZGVmaW5lZCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBXZWFrTWFwYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgd2VhayBtYXAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1dlYWtNYXAobmV3IFdlYWtNYXApO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNXZWFrTWFwKG5ldyBNYXApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNXZWFrTWFwKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBnZXRUYWcodmFsdWUpID09IHdlYWtNYXBUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBXZWFrU2V0YCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgd2VhayBzZXQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1dlYWtTZXQobmV3IFdlYWtTZXQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNXZWFrU2V0KG5ldyBTZXQpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNXZWFrU2V0KHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSB3ZWFrU2V0VGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuOS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIGBvdGhlcmAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAc2VlIF8uZ3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sdCgxLCAzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmx0KDMsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmx0KDMsIDEpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGx0ID0gY3JlYXRlUmVsYXRpb25hbE9wZXJhdGlvbihiYXNlTHQpO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGBvdGhlcmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy45LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG9cbiAgICAgKiAgYG90aGVyYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBzZWUgXy5ndGVcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sdGUoMSwgMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5sdGUoMywgMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5sdGUoMywgMSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgbHRlID0gY3JlYXRlUmVsYXRpb25hbE9wZXJhdGlvbihmdW5jdGlvbih2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA8PSBvdGhlcjtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYW4gYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9BcnJheSh7ICdhJzogMSwgJ2InOiAyIH0pO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogXy50b0FycmF5KCdhYmMnKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKlxuICAgICAqIF8udG9BcnJheSgxKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqXG4gICAgICogXy50b0FycmF5KG51bGwpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9BcnJheSh2YWx1ZSkge1xuICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoaXNBcnJheUxpa2UodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBpc1N0cmluZyh2YWx1ZSkgPyBzdHJpbmdUb0FycmF5KHZhbHVlKSA6IGNvcHlBcnJheSh2YWx1ZSk7XG4gICAgICB9XG4gICAgICBpZiAoc3ltSXRlcmF0b3IgJiYgdmFsdWVbc3ltSXRlcmF0b3JdKSB7XG4gICAgICAgIHJldHVybiBpdGVyYXRvclRvQXJyYXkodmFsdWVbc3ltSXRlcmF0b3JdKCkpO1xuICAgICAgfVxuICAgICAgdmFyIHRhZyA9IGdldFRhZyh2YWx1ZSksXG4gICAgICAgICAgZnVuYyA9IHRhZyA9PSBtYXBUYWcgPyBtYXBUb0FycmF5IDogKHRhZyA9PSBzZXRUYWcgPyBzZXRUb0FycmF5IDogdmFsdWVzKTtcblxuICAgICAgcmV0dXJuIGZ1bmModmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBmaW5pdGUgbnVtYmVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTIuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvRmluaXRlKDMuMik7XG4gICAgICogLy8gPT4gMy4yXG4gICAgICpcbiAgICAgKiBfLnRvRmluaXRlKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IDVlLTMyNFxuICAgICAqXG4gICAgICogXy50b0Zpbml0ZShJbmZpbml0eSk7XG4gICAgICogLy8gPT4gMS43OTc2OTMxMzQ4NjIzMTU3ZSszMDhcbiAgICAgKlxuICAgICAqIF8udG9GaW5pdGUoJzMuMicpO1xuICAgICAqIC8vID0+IDMuMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvRmluaXRlKHZhbHVlKSB7XG4gICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gMCA/IHZhbHVlIDogMDtcbiAgICAgIH1cbiAgICAgIHZhbHVlID0gdG9OdW1iZXIodmFsdWUpO1xuICAgICAgaWYgKHZhbHVlID09PSBJTkZJTklUWSB8fCB2YWx1ZSA9PT0gLUlORklOSVRZKSB7XG4gICAgICAgIHZhciBzaWduID0gKHZhbHVlIDwgMCA/IC0xIDogMSk7XG4gICAgICAgIHJldHVybiBzaWduICogTUFYX0lOVEVHRVI7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWUgPT09IHZhbHVlID8gdmFsdWUgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYW4gaW50ZWdlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBsb29zZWx5IGJhc2VkIG9uXG4gICAgICogW2BUb0ludGVnZXJgXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtdG9pbnRlZ2VyKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgaW50ZWdlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b0ludGVnZXIoMy4yKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnRvSW50ZWdlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiBfLnRvSW50ZWdlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gMS43OTc2OTMxMzQ4NjIzMTU3ZSszMDhcbiAgICAgKlxuICAgICAqIF8udG9JbnRlZ2VyKCczLjInKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9JbnRlZ2VyKHZhbHVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gdG9GaW5pdGUodmFsdWUpLFxuICAgICAgICAgIHJlbWFpbmRlciA9IHJlc3VsdCAlIDE7XG5cbiAgICAgIHJldHVybiByZXN1bHQgPT09IHJlc3VsdCA/IChyZW1haW5kZXIgPyByZXN1bHQgLSByZW1haW5kZXIgOiByZXN1bHQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGFuIGludGVnZXIgc3VpdGFibGUgZm9yIHVzZSBhcyB0aGUgbGVuZ3RoIG9mIGFuXG4gICAgICogYXJyYXktbGlrZSBvYmplY3QuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb25cbiAgICAgKiBbYFRvTGVuZ3RoYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtdG9sZW5ndGgpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvTGVuZ3RoKDMuMik7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy50b0xlbmd0aChOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiBfLnRvTGVuZ3RoKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiA0Mjk0OTY3Mjk1XG4gICAgICpcbiAgICAgKiBfLnRvTGVuZ3RoKCczLjInKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9MZW5ndGgodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA/IGJhc2VDbGFtcCh0b0ludGVnZXIodmFsdWUpLCAwLCBNQVhfQVJSQVlfTEVOR1RIKSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhIG51bWJlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9OdW1iZXIoMy4yKTtcbiAgICAgKiAvLyA9PiAzLjJcbiAgICAgKlxuICAgICAqIF8udG9OdW1iZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gNWUtMzI0XG4gICAgICpcbiAgICAgKiBfLnRvTnVtYmVyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiBJbmZpbml0eVxuICAgICAqXG4gICAgICogXy50b051bWJlcignMy4yJyk7XG4gICAgICogLy8gPT4gMy4yXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9OdW1iZXIodmFsdWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgaWYgKGlzU3ltYm9sKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gTkFOO1xuICAgICAgfVxuICAgICAgaWYgKGlzT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICB2YXIgb3RoZXIgPSB0eXBlb2YgdmFsdWUudmFsdWVPZiA9PSAnZnVuY3Rpb24nID8gdmFsdWUudmFsdWVPZigpIDogdmFsdWU7XG4gICAgICAgIHZhbHVlID0gaXNPYmplY3Qob3RoZXIpID8gKG90aGVyICsgJycpIDogb3RoZXI7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gMCA/IHZhbHVlIDogK3ZhbHVlO1xuICAgICAgfVxuICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHJlVHJpbSwgJycpO1xuICAgICAgdmFyIGlzQmluYXJ5ID0gcmVJc0JpbmFyeS50ZXN0KHZhbHVlKTtcbiAgICAgIHJldHVybiAoaXNCaW5hcnkgfHwgcmVJc09jdGFsLnRlc3QodmFsdWUpKVxuICAgICAgICA/IGZyZWVQYXJzZUludCh2YWx1ZS5zbGljZSgyKSwgaXNCaW5hcnkgPyAyIDogOClcbiAgICAgICAgOiAocmVJc0JhZEhleC50ZXN0KHZhbHVlKSA/IE5BTiA6ICt2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhIHBsYWluIG9iamVjdCBmbGF0dGVuaW5nIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZ1xuICAgICAqIGtleWVkIHByb3BlcnRpZXMgb2YgYHZhbHVlYCB0byBvd24gcHJvcGVydGllcyBvZiB0aGUgcGxhaW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBwbGFpbiBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uYXNzaWduKHsgJ2EnOiAxIH0sIG5ldyBGb28pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqXG4gICAgICogXy5hc3NpZ24oeyAnYSc6IDEgfSwgXy50b1BsYWluT2JqZWN0KG5ldyBGb28pKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDMgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBjb3B5T2JqZWN0KHZhbHVlLCBrZXlzSW4odmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc2FmZSBpbnRlZ2VyLiBBIHNhZmUgaW50ZWdlciBjYW4gYmUgY29tcGFyZWQgYW5kXG4gICAgICogcmVwcmVzZW50ZWQgY29ycmVjdGx5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoMy4yKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogXy50b1NhZmVJbnRlZ2VyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiA5MDA3MTk5MjU0NzQwOTkxXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoJzMuMicpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1NhZmVJbnRlZ2VyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgPyBiYXNlQ2xhbXAodG9JbnRlZ2VyKHZhbHVlKSwgLU1BWF9TQUZFX0lOVEVHRVIsIE1BWF9TQUZFX0lOVEVHRVIpXG4gICAgICAgIDogKHZhbHVlID09PSAwID8gdmFsdWUgOiAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc3RyaW5nLiBBbiBlbXB0eSBzdHJpbmcgaXMgcmV0dXJuZWQgZm9yIGBudWxsYFxuICAgICAqIGFuZCBgdW5kZWZpbmVkYCB2YWx1ZXMuIFRoZSBzaWduIG9mIGAtMGAgaXMgcHJlc2VydmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9TdHJpbmcobnVsbCk7XG4gICAgICogLy8gPT4gJydcbiAgICAgKlxuICAgICAqIF8udG9TdHJpbmcoLTApO1xuICAgICAqIC8vID0+ICctMCdcbiAgICAgKlxuICAgICAqIF8udG9TdHJpbmcoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiAnMSwyLDMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9TdHJpbmcodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PSBudWxsID8gJycgOiBiYXNlVG9TdHJpbmcodmFsdWUpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgb2Ygc291cmNlIG9iamVjdHMgdG8gdGhlXG4gICAgICogZGVzdGluYXRpb24gb2JqZWN0LiBTb3VyY2Ugb2JqZWN0cyBhcmUgYXBwbGllZCBmcm9tIGxlZnQgdG8gcmlnaHQuXG4gICAgICogU3Vic2VxdWVudCBzb3VyY2VzIG92ZXJ3cml0ZSBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91cyBzb3VyY2VzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAgYW5kIGlzIGxvb3NlbHkgYmFzZWQgb25cbiAgICAgKiBbYE9iamVjdC5hc3NpZ25gXShodHRwczovL21kbi5pby9PYmplY3QvYXNzaWduKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEwLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmFzc2lnbkluXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gQmFyKCkge1xuICAgICAqICAgdGhpcy5jID0gMztcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmIgPSAyO1xuICAgICAqIEJhci5wcm90b3R5cGUuZCA9IDQ7XG4gICAgICpcbiAgICAgKiBfLmFzc2lnbih7ICdhJzogMCB9LCBuZXcgRm9vLCBuZXcgQmFyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2MnOiAzIH1cbiAgICAgKi9cbiAgICB2YXIgYXNzaWduID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UpIHtcbiAgICAgIGlmIChpc1Byb3RvdHlwZShzb3VyY2UpIHx8IGlzQXJyYXlMaWtlKHNvdXJjZSkpIHtcbiAgICAgICAgY29weU9iamVjdChzb3VyY2UsIGtleXMoc291cmNlKSwgb2JqZWN0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHtcbiAgICAgICAgICBhc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgc291cmNlW2tleV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBvd24gYW5kXG4gICAgICogaW5oZXJpdGVkIHNvdXJjZSBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAYWxpYXMgZXh0ZW5kXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5hc3NpZ25cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBCYXIoKSB7XG4gICAgICogICB0aGlzLmMgPSAzO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYiA9IDI7XG4gICAgICogQmFyLnByb3RvdHlwZS5kID0gNDtcbiAgICAgKlxuICAgICAqIF8uYXNzaWduSW4oeyAnYSc6IDAgfSwgbmV3IEZvbywgbmV3IEJhcik7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdiJzogMiwgJ2MnOiAzLCAnZCc6IDQgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ25JbiA9IGNyZWF0ZUFzc2lnbmVyKGZ1bmN0aW9uKG9iamVjdCwgc291cmNlKSB7XG4gICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5c0luKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbkluYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgYXNzaWduZWQgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJuc1xuICAgICAqIGB1bmRlZmluZWRgLCBhc3NpZ25tZW50IGlzIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgXG4gICAgICogaXMgaW52b2tlZCB3aXRoIGZpdmUgYXJndW1lbnRzOiAob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCwgc291cmNlKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGFsaWFzIGV4dGVuZFdpdGhcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBzb3VyY2VzIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAc2VlIF8uYXNzaWduV2l0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgcmV0dXJuIF8uaXNVbmRlZmluZWQob2JqVmFsdWUpID8gc3JjVmFsdWUgOiBvYmpWYWx1ZTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZGVmYXVsdHMgPSBfLnBhcnRpYWxSaWdodChfLmFzc2lnbkluV2l0aCwgY3VzdG9taXplcik7XG4gICAgICpcbiAgICAgKiBkZWZhdWx0cyh7ICdhJzogMSB9LCB7ICdiJzogMiB9LCB7ICdhJzogMyB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKi9cbiAgICB2YXIgYXNzaWduSW5XaXRoID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKSB7XG4gICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5c0luKHNvdXJjZSksIG9iamVjdCwgY3VzdG9taXplcik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIGFzc2lnbmVkIHZhbHVlcy4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnNcbiAgICAgKiBgdW5kZWZpbmVkYCwgYXNzaWdubWVudCBpcyBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYFxuICAgICAqIGlzIGludm9rZWQgd2l0aCBmaXZlIGFyZ3VtZW50czogKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IHNvdXJjZXMgVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5hc3NpZ25JbldpdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiBfLmlzVW5kZWZpbmVkKG9ialZhbHVlKSA/IHNyY1ZhbHVlIDogb2JqVmFsdWU7XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIGRlZmF1bHRzID0gXy5wYXJ0aWFsUmlnaHQoXy5hc3NpZ25XaXRoLCBjdXN0b21pemVyKTtcbiAgICAgKlxuICAgICAqIGRlZmF1bHRzKHsgJ2EnOiAxIH0sIHsgJ2InOiAyIH0sIHsgJ2EnOiAzIH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ25XaXRoID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKSB7XG4gICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5cyhzb3VyY2UpLCBvYmplY3QsIGN1c3RvbWl6ZXIpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB2YWx1ZXMgY29ycmVzcG9uZGluZyB0byBgcGF0aHNgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHsuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3BhdGhzXSBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHBpY2tlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogMyB9IH0sIDRdIH07XG4gICAgICpcbiAgICAgKiBfLmF0KG9iamVjdCwgWydhWzBdLmIuYycsICdhWzFdJ10pO1xuICAgICAqIC8vID0+IFszLCA0XVxuICAgICAqL1xuICAgIHZhciBhdCA9IGZsYXRSZXN0KGJhc2VBdCk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCB0aGF0IGluaGVyaXRzIGZyb20gdGhlIGBwcm90b3R5cGVgIG9iamVjdC4gSWYgYVxuICAgICAqIGBwcm9wZXJ0aWVzYCBvYmplY3QgaXMgZ2l2ZW4sIGl0cyBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllc1xuICAgICAqIGFyZSBhc3NpZ25lZCB0byB0aGUgY3JlYXRlZCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IHByb3RvdHlwZSBUaGUgb2JqZWN0IHRvIGluaGVyaXQgZnJvbS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3Byb3BlcnRpZXNdIFRoZSBwcm9wZXJ0aWVzIHRvIGFzc2lnbiB0byB0aGUgb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIFNoYXBlKCkge1xuICAgICAqICAgdGhpcy54ID0gMDtcbiAgICAgKiAgIHRoaXMueSA9IDA7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gQ2lyY2xlKCkge1xuICAgICAqICAgU2hhcGUuY2FsbCh0aGlzKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBDaXJjbGUucHJvdG90eXBlID0gXy5jcmVhdGUoU2hhcGUucHJvdG90eXBlLCB7XG4gICAgICogICAnY29uc3RydWN0b3InOiBDaXJjbGVcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHZhciBjaXJjbGUgPSBuZXcgQ2lyY2xlO1xuICAgICAqIGNpcmNsZSBpbnN0YW5jZW9mIENpcmNsZTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBjaXJjbGUgaW5zdGFuY2VvZiBTaGFwZTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlKHByb3RvdHlwZSwgcHJvcGVydGllcykge1xuICAgICAgdmFyIHJlc3VsdCA9IGJhc2VDcmVhdGUocHJvdG90eXBlKTtcbiAgICAgIHJldHVybiBwcm9wZXJ0aWVzID09IG51bGwgPyByZXN1bHQgOiBiYXNlQXNzaWduKHJlc3VsdCwgcHJvcGVydGllcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXNzaWducyBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBwcm9wZXJ0aWVzIG9mIHNvdXJjZVxuICAgICAqIG9iamVjdHMgdG8gdGhlIGRlc3RpbmF0aW9uIG9iamVjdCBmb3IgYWxsIGRlc3RpbmF0aW9uIHByb3BlcnRpZXMgdGhhdFxuICAgICAqIHJlc29sdmUgdG8gYHVuZGVmaW5lZGAuIFNvdXJjZSBvYmplY3RzIGFyZSBhcHBsaWVkIGZyb20gbGVmdCB0byByaWdodC5cbiAgICAgKiBPbmNlIGEgcHJvcGVydHkgaXMgc2V0LCBhZGRpdGlvbmFsIHZhbHVlcyBvZiB0aGUgc2FtZSBwcm9wZXJ0eSBhcmUgaWdub3JlZC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5kZWZhdWx0c0RlZXBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWZhdWx0cyh7ICdhJzogMSB9LCB7ICdiJzogMiB9LCB7ICdhJzogMyB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKi9cbiAgICB2YXIgZGVmYXVsdHMgPSBiYXNlUmVzdChmdW5jdGlvbihvYmplY3QsIHNvdXJjZXMpIHtcbiAgICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuXG4gICAgICB2YXIgaW5kZXggPSAtMTtcbiAgICAgIHZhciBsZW5ndGggPSBzb3VyY2VzLmxlbmd0aDtcbiAgICAgIHZhciBndWFyZCA9IGxlbmd0aCA+IDIgPyBzb3VyY2VzWzJdIDogdW5kZWZpbmVkO1xuXG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoc291cmNlc1swXSwgc291cmNlc1sxXSwgZ3VhcmQpKSB7XG4gICAgICAgIGxlbmd0aCA9IDE7XG4gICAgICB9XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW2luZGV4XTtcbiAgICAgICAgdmFyIHByb3BzID0ga2V5c0luKHNvdXJjZSk7XG4gICAgICAgIHZhciBwcm9wc0luZGV4ID0gLTE7XG4gICAgICAgIHZhciBwcm9wc0xlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICAgICAgICB3aGlsZSAoKytwcm9wc0luZGV4IDwgcHJvcHNMZW5ndGgpIHtcbiAgICAgICAgICB2YXIga2V5ID0gcHJvcHNbcHJvcHNJbmRleF07XG4gICAgICAgICAgdmFyIHZhbHVlID0gb2JqZWN0W2tleV07XG5cbiAgICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgICAoZXEodmFsdWUsIG9iamVjdFByb3RvW2tleV0pICYmICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkpIHtcbiAgICAgICAgICAgIG9iamVjdFtrZXldID0gc291cmNlW2tleV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmRlZmF1bHRzYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBhc3NpZ25zXG4gICAgICogZGVmYXVsdCBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4xMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5kZWZhdWx0c1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmF1bHRzRGVlcCh7ICdhJzogeyAnYic6IDIgfSB9LCB7ICdhJzogeyAnYic6IDEsICdjJzogMyB9IH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiB7ICdiJzogMiwgJ2MnOiAzIH0gfVxuICAgICAqL1xuICAgIHZhciBkZWZhdWx0c0RlZXAgPSBiYXNlUmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICBhcmdzLnB1c2godW5kZWZpbmVkLCBjdXN0b21EZWZhdWx0c01lcmdlKTtcbiAgICAgIHJldHVybiBhcHBseShtZXJnZVdpdGgsIHVuZGVmaW5lZCwgYXJncyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRgIGV4Y2VwdCB0aGF0IGl0IHJldHVybnMgdGhlIGtleSBvZiB0aGUgZmlyc3RcbiAgICAgKiBlbGVtZW50IGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciBpbnN0ZWFkIG9mIHRoZSBlbGVtZW50IGl0c2VsZi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjEuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IFJldHVybnMgdGhlIGtleSBvZiB0aGUgbWF0Y2hlZCBlbGVtZW50LFxuICAgICAqICBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSB7XG4gICAgICogICAnYmFybmV5JzogIHsgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgJ2ZyZWQnOiAgICB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ2FnZSc6IDEsICAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uZmluZEtleSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hZ2UgPCA0MDsgfSk7XG4gICAgICogLy8gPT4gJ2Jhcm5leScgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kS2V5KHVzZXJzLCB7ICdhZ2UnOiAxLCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiAncGViYmxlcydcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRLZXkodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiAnZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZEtleSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+ICdiYXJuZXknXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZEtleShvYmplY3QsIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIGJhc2VGaW5kS2V5KG9iamVjdCwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgYmFzZUZvck93bik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5maW5kS2V5YCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYSBjb2xsZWN0aW9uIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IFJldHVybnMgdGhlIGtleSBvZiB0aGUgbWF0Y2hlZCBlbGVtZW50LFxuICAgICAqICBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSB7XG4gICAgICogICAnYmFybmV5JzogIHsgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgJ2ZyZWQnOiAgICB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ2FnZSc6IDEsICAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3RLZXkodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWdlIDwgNDA7IH0pO1xuICAgICAqIC8vID0+IHJldHVybnMgJ3BlYmJsZXMnIGFzc3VtaW5nIGBfLmZpbmRLZXlgIHJldHVybnMgJ2Jhcm5leSdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+ICdiYXJuZXknXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+ICdmcmVkJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+ICdwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRMYXN0S2V5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gYmFzZUZpbmRLZXkob2JqZWN0LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBiYXNlRm9yT3duUmlnaHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBvZiBhblxuICAgICAqIG9iamVjdCBhbmQgaW52b2tlcyBgaXRlcmF0ZWVgIGZvciBlYWNoIHByb3BlcnR5LiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGtleSwgb2JqZWN0KS4gSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0XG4gICAgICogaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5mb3JJblJpZ2h0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmZvckluKG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYScsICdiJywgdGhlbiAnYycgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZCkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9ySW4ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsXG4gICAgICAgID8gb2JqZWN0XG4gICAgICAgIDogYmFzZUZvcihvYmplY3QsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSwga2V5c0luKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZvckluYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIHByb3BlcnRpZXMgb2ZcbiAgICAgKiBgb2JqZWN0YCBpbiB0aGUgb3Bwb3NpdGUgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5mb3JJblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5mb3JJblJpZ2h0KG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYycsICdiJywgdGhlbiAnYScgYXNzdW1pbmcgYF8uZm9ySW5gIGxvZ3MgJ2EnLCAnYicsIHRoZW4gJ2MnLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZvckluUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsXG4gICAgICAgID8gb2JqZWN0XG4gICAgICAgIDogYmFzZUZvclJpZ2h0KG9iamVjdCwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDMpLCBrZXlzSW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0IGFuZFxuICAgICAqIGludm9rZXMgYGl0ZXJhdGVlYCBmb3IgZWFjaCBwcm9wZXJ0eS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBrZXksIG9iamVjdCkuIEl0ZXJhdGVlIGZ1bmN0aW9ucyBtYXkgZXhpdCBpdGVyYXRpb25cbiAgICAgKiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMy4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAc2VlIF8uZm9yT3duUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uZm9yT3duKG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYScgdGhlbiAnYicgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZCkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBvYmplY3QgJiYgYmFzZUZvck93bihvYmplY3QsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mb3JPd25gIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgcHJvcGVydGllcyBvZlxuICAgICAqIGBvYmplY3RgIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmZvck93blxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5mb3JPd25SaWdodChuZXcgRm9vLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICBjb25zb2xlLmxvZyhrZXkpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IExvZ3MgJ2InIHRoZW4gJ2EnIGFzc3VtaW5nIGBfLmZvck93bmAgbG9ncyAnYScgdGhlbiAnYicuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yT3duUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBiYXNlRm9yT3duUmlnaHQob2JqZWN0LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZnVuY3Rpb24gcHJvcGVydHkgbmFtZXMgZnJvbSBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzXG4gICAgICogb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBuYW1lcy5cbiAgICAgKiBAc2VlIF8uZnVuY3Rpb25zSW5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gXy5jb25zdGFudCgnYScpO1xuICAgICAqICAgdGhpcy5iID0gXy5jb25zdGFudCgnYicpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IF8uY29uc3RhbnQoJ2MnKTtcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsnYScsICdiJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmdW5jdGlvbnMob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBbXSA6IGJhc2VGdW5jdGlvbnMob2JqZWN0LCBrZXlzKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZnVuY3Rpb24gcHJvcGVydHkgbmFtZXMgZnJvbSBvd24gYW5kIGluaGVyaXRlZFxuICAgICAqIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGZ1bmN0aW9uIG5hbWVzLlxuICAgICAqIEBzZWUgXy5mdW5jdGlvbnNcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gXy5jb25zdGFudCgnYScpO1xuICAgICAqICAgdGhpcy5iID0gXy5jb25zdGFudCgnYicpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IF8uY29uc3RhbnQoJ2MnKTtcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gZnVuY3Rpb25zSW4ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBbXSA6IGJhc2VGdW5jdGlvbnMob2JqZWN0LCBrZXlzSW4ob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmFsdWUgYXQgYHBhdGhgIG9mIGBvYmplY3RgLiBJZiB0aGUgcmVzb2x2ZWQgdmFsdWUgaXNcbiAgICAgKiBgdW5kZWZpbmVkYCwgdGhlIGBkZWZhdWx0VmFsdWVgIGlzIHJldHVybmVkIGluIGl0cyBwbGFjZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjcuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IFtkZWZhdWx0VmFsdWVdIFRoZSB2YWx1ZSByZXR1cm5lZCBmb3IgYHVuZGVmaW5lZGAgcmVzb2x2ZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8uZ2V0KG9iamVjdCwgJ2FbMF0uYi5jJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCBbJ2EnLCAnMCcsICdiJywgJ2MnXSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCAnYS5iLmMnLCAnZGVmYXVsdCcpO1xuICAgICAqIC8vID0+ICdkZWZhdWx0J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldChvYmplY3QsIHBhdGgsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogYmFzZUdldChvYmplY3QsIHBhdGgpO1xuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gZGVmYXVsdFZhbHVlIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcGF0aGAgaXMgYSBkaXJlY3QgcHJvcGVydHkgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgcGF0aGAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogeyAnYic6IDIgfSB9O1xuICAgICAqIHZhciBvdGhlciA9IF8uY3JlYXRlKHsgJ2EnOiBfLmNyZWF0ZSh7ICdiJzogMiB9KSB9KTtcbiAgICAgKlxuICAgICAqIF8uaGFzKG9iamVjdCwgJ2EnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsICdhLmInKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsIFsnYScsICdiJ10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzKG90aGVyLCAnYScpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzKG9iamVjdCwgcGF0aCkge1xuICAgICAgcmV0dXJuIG9iamVjdCAhPSBudWxsICYmIGhhc1BhdGgob2JqZWN0LCBwYXRoLCBiYXNlSGFzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHBhdGhgIGlzIGEgZGlyZWN0IG9yIGluaGVyaXRlZCBwcm9wZXJ0eSBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBwYXRoYCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IF8uY3JlYXRlKHsgJ2EnOiBfLmNyZWF0ZSh7ICdiJzogMiB9KSB9KTtcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYS5iJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXNJbihvYmplY3QsIFsnYScsICdiJ10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYicpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzSW4ob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICE9IG51bGwgJiYgaGFzUGF0aChvYmplY3QsIHBhdGgsIGJhc2VIYXNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlIGludmVydGVkIGtleXMgYW5kIHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAgICAgKiBJZiBgb2JqZWN0YCBjb250YWlucyBkdXBsaWNhdGUgdmFsdWVzLCBzdWJzZXF1ZW50IHZhbHVlcyBvdmVyd3JpdGVcbiAgICAgKiBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91cyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludmVydC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgaW52ZXJ0ZWQgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogMiwgJ2MnOiAxIH07XG4gICAgICpcbiAgICAgKiBfLmludmVydChvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJzEnOiAnYycsICcyJzogJ2InIH1cbiAgICAgKi9cbiAgICB2YXIgaW52ZXJ0ID0gY3JlYXRlSW52ZXJ0ZXIoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICBpZiAodmFsdWUgIT0gbnVsbCAmJlxuICAgICAgICAgIHR5cGVvZiB2YWx1ZS50b1N0cmluZyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHZhbHVlID0gbmF0aXZlT2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHJlc3VsdFt2YWx1ZV0gPSBrZXk7XG4gICAgfSwgY29uc3RhbnQoaWRlbnRpdHkpKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW52ZXJ0YCBleGNlcHQgdGhhdCB0aGUgaW52ZXJ0ZWQgb2JqZWN0IGlzIGdlbmVyYXRlZFxuICAgICAqIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZyBlYWNoIGVsZW1lbnQgb2YgYG9iamVjdGAgdGhydSBgaXRlcmF0ZWVgLiBUaGVcbiAgICAgKiBjb3JyZXNwb25kaW5nIGludmVydGVkIHZhbHVlIG9mIGVhY2ggaW52ZXJ0ZWQga2V5IGlzIGFuIGFycmF5IG9mIGtleXNcbiAgICAgKiByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGUgaW52ZXJ0ZWQgdmFsdWUuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkXG4gICAgICogd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludmVydC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGludmVydGVkIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMSB9O1xuICAgICAqXG4gICAgICogXy5pbnZlcnRCeShvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJzEnOiBbJ2EnLCAnYyddLCAnMic6IFsnYiddIH1cbiAgICAgKlxuICAgICAqIF8uaW52ZXJ0Qnkob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgcmV0dXJuICdncm91cCcgKyB2YWx1ZTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdncm91cDEnOiBbJ2EnLCAnYyddLCAnZ3JvdXAyJzogWydiJ10gfVxuICAgICAqL1xuICAgIHZhciBpbnZlcnRCeSA9IGNyZWF0ZUludmVydGVyKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgaWYgKHZhbHVlICE9IG51bGwgJiZcbiAgICAgICAgICB0eXBlb2YgdmFsdWUudG9TdHJpbmcgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB2YWx1ZSA9IG5hdGl2ZU9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsIHZhbHVlKSkge1xuICAgICAgICByZXN1bHRbdmFsdWVdLnB1c2goa2V5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFt2YWx1ZV0gPSBba2V5XTtcbiAgICAgIH1cbiAgICB9LCBnZXRJdGVyYXRlZSk7XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogWzEsIDIsIDMsIDRdIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8uaW52b2tlKG9iamVjdCwgJ2FbMF0uYi5jLnNsaWNlJywgMSwgMyk7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICovXG4gICAgdmFyIGludm9rZSA9IGJhc2VSZXN0KGJhc2VJbnZva2UpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy4gU2VlIHRoZVxuICAgICAqIFtFUyBzcGVjXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3Qua2V5cylcbiAgICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5rZXlzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsnYScsICdiJ10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIF8ua2V5cygnaGknKTtcbiAgICAgKiAvLyA9PiBbJzAnLCAnMSddXG4gICAgICovXG4gICAgZnVuY3Rpb24ga2V5cyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBpc0FycmF5TGlrZShvYmplY3QpID8gYXJyYXlMaWtlS2V5cyhvYmplY3QpIDogYmFzZUtleXMob2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHRoZSBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmtleXNJbihuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBrZXlzSW4ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2Uob2JqZWN0KSA/IGFycmF5TGlrZUtleXMob2JqZWN0LCB0cnVlKSA6IGJhc2VLZXlzSW4ob2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ubWFwVmFsdWVzYDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhbiBvYmplY3Qgd2l0aCB0aGVcbiAgICAgKiBzYW1lIHZhbHVlcyBhcyBgb2JqZWN0YCBhbmQga2V5cyBnZW5lcmF0ZWQgYnkgcnVubmluZyBlYWNoIG93biBlbnVtZXJhYmxlXG4gICAgICogc3RyaW5nIGtleWVkIHByb3BlcnR5IG9mIGBvYmplY3RgIHRocnUgYGl0ZXJhdGVlYC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBrZXksIG9iamVjdCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy44LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIG9iamVjdC5cbiAgICAgKiBAc2VlIF8ubWFwVmFsdWVzXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWFwS2V5cyh7ICdhJzogMSwgJ2InOiAyIH0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIHJldHVybiBrZXkgKyB2YWx1ZTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdhMSc6IDEsICdiMic6IDIgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcEtleXMob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaXRlcmF0ZWUgPSBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMyk7XG5cbiAgICAgIGJhc2VGb3JPd24ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKHJlc3VsdCwgaXRlcmF0ZWUodmFsdWUsIGtleSwgb2JqZWN0KSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlIHNhbWUga2V5cyBhcyBgb2JqZWN0YCBhbmQgdmFsdWVzIGdlbmVyYXRlZFxuICAgICAqIGJ5IHJ1bm5pbmcgZWFjaCBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydHkgb2YgYG9iamVjdGAgdGhydVxuICAgICAqIGBpdGVyYXRlZWAuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwga2V5LCBvYmplY3QpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuNC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBvYmplY3QuXG4gICAgICogQHNlZSBfLm1hcEtleXNcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0ge1xuICAgICAqICAgJ2ZyZWQnOiAgICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgICdwZWJibGVzJzogeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLm1hcFZhbHVlcyh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hZ2U7IH0pO1xuICAgICAqIC8vID0+IHsgJ2ZyZWQnOiA0MCwgJ3BlYmJsZXMnOiAxIH0gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ubWFwVmFsdWVzKHVzZXJzLCAnYWdlJyk7XG4gICAgICogLy8gPT4geyAnZnJlZCc6IDQwLCAncGViYmxlcyc6IDEgfSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcFZhbHVlcyhvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpdGVyYXRlZSA9IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKTtcblxuICAgICAgYmFzZUZvck93bihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUocmVzdWx0LCBrZXksIGl0ZXJhdGVlKHZhbHVlLCBrZXksIG9iamVjdCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYXNzaWduYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBtZXJnZXMgb3duIGFuZFxuICAgICAqIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBwcm9wZXJ0aWVzIG9mIHNvdXJjZSBvYmplY3RzIGludG8gdGhlXG4gICAgICogZGVzdGluYXRpb24gb2JqZWN0LiBTb3VyY2UgcHJvcGVydGllcyB0aGF0IHJlc29sdmUgdG8gYHVuZGVmaW5lZGAgYXJlXG4gICAgICogc2tpcHBlZCBpZiBhIGRlc3RpbmF0aW9uIHZhbHVlIGV4aXN0cy4gQXJyYXkgYW5kIHBsYWluIG9iamVjdCBwcm9wZXJ0aWVzXG4gICAgICogYXJlIG1lcmdlZCByZWN1cnNpdmVseS4gT3RoZXIgb2JqZWN0cyBhbmQgdmFsdWUgdHlwZXMgYXJlIG92ZXJyaWRkZW4gYnlcbiAgICAgKiBhc3NpZ25tZW50LiBTb3VyY2Ugb2JqZWN0cyBhcmUgYXBwbGllZCBmcm9tIGxlZnQgdG8gcmlnaHQuIFN1YnNlcXVlbnRcbiAgICAgKiBzb3VyY2VzIG92ZXJ3cml0ZSBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91cyBzb3VyY2VzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC41LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7XG4gICAgICogICAnYSc6IFt7ICdiJzogMiB9LCB7ICdkJzogNCB9XVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgb3RoZXIgPSB7XG4gICAgICogICAnYSc6IFt7ICdjJzogMyB9LCB7ICdlJzogNSB9XVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLm1lcmdlKG9iamVjdCwgb3RoZXIpO1xuICAgICAqIC8vID0+IHsgJ2EnOiBbeyAnYic6IDIsICdjJzogMyB9LCB7ICdkJzogNCwgJ2UnOiA1IH1dIH1cbiAgICAgKi9cbiAgICB2YXIgbWVyZ2UgPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgpIHtcbiAgICAgIGJhc2VNZXJnZShvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5tZXJnZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIG1lcmdlZCB2YWx1ZXMgb2YgdGhlIGRlc3RpbmF0aW9uIGFuZCBzb3VyY2VcbiAgICAgKiBwcm9wZXJ0aWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCwgbWVyZ2luZyBpcyBoYW5kbGVkIGJ5IHRoZVxuICAgICAqIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWQgd2l0aCBzaXggYXJndW1lbnRzOlxuICAgICAqIChvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gc291cmNlcyBUaGUgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgaWYgKF8uaXNBcnJheShvYmpWYWx1ZSkpIHtcbiAgICAgKiAgICAgcmV0dXJuIG9ialZhbHVlLmNvbmNhdChzcmNWYWx1ZSk7XG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbMV0sICdiJzogWzJdIH07XG4gICAgICogdmFyIG90aGVyID0geyAnYSc6IFszXSwgJ2InOiBbNF0gfTtcbiAgICAgKlxuICAgICAqIF8ubWVyZ2VXaXRoKG9iamVjdCwgb3RoZXIsIGN1c3RvbWl6ZXIpO1xuICAgICAqIC8vID0+IHsgJ2EnOiBbMSwgM10sICdiJzogWzIsIDRdIH1cbiAgICAgKi9cbiAgICB2YXIgbWVyZ2VXaXRoID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKSB7XG4gICAgICBiYXNlTWVyZ2Uob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5waWNrYDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlXG4gICAgICogb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBwYXRocyBvZiBgb2JqZWN0YCB0aGF0IGFyZSBub3Qgb21pdHRlZC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBjb25zaWRlcmFibHkgc2xvd2VyIHRoYW4gYF8ucGlja2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBbcGF0aHNdIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBvbWl0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAnMicsICdjJzogMyB9O1xuICAgICAqXG4gICAgICogXy5vbWl0KG9iamVjdCwgWydhJywgJ2MnXSk7XG4gICAgICogLy8gPT4geyAnYic6ICcyJyB9XG4gICAgICovXG4gICAgdmFyIG9taXQgPSBmbGF0UmVzdChmdW5jdGlvbihvYmplY3QsIHBhdGhzKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHZhciBpc0RlZXAgPSBmYWxzZTtcbiAgICAgIHBhdGhzID0gYXJyYXlNYXAocGF0aHMsIGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG4gICAgICAgIGlzRGVlcCB8fCAoaXNEZWVwID0gcGF0aC5sZW5ndGggPiAxKTtcbiAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgICB9KTtcbiAgICAgIGNvcHlPYmplY3Qob2JqZWN0LCBnZXRBbGxLZXlzSW4ob2JqZWN0KSwgcmVzdWx0KTtcbiAgICAgIGlmIChpc0RlZXApIHtcbiAgICAgICAgcmVzdWx0ID0gYmFzZUNsb25lKHJlc3VsdCwgQ0xPTkVfREVFUF9GTEFHIHwgQ0xPTkVfRkxBVF9GTEFHIHwgQ0xPTkVfU1lNQk9MU19GTEFHLCBjdXN0b21PbWl0Q2xvbmUpO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IHBhdGhzLmxlbmd0aDtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBiYXNlVW5zZXQocmVzdWx0LCBwYXRoc1tsZW5ndGhdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ucGlja0J5YDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2ZcbiAgICAgKiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBvZiBgb2JqZWN0YCB0aGF0XG4gICAgICogYHByZWRpY2F0ZWAgZG9lc24ndCByZXR1cm4gdHJ1dGh5IGZvci4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGggdHdvXG4gICAgICogYXJndW1lbnRzOiAodmFsdWUsIGtleSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ub21pdEJ5KG9iamVjdCwgXy5pc051bWJlcik7XG4gICAgICogLy8gPT4geyAnYic6ICcyJyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gb21pdEJ5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gcGlja0J5KG9iamVjdCwgbmVnYXRlKGdldEl0ZXJhdGVlKHByZWRpY2F0ZSkpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiB0aGUgcGlja2VkIGBvYmplY3RgIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBbcGF0aHNdIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBwaWNrLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAnMicsICdjJzogMyB9O1xuICAgICAqXG4gICAgICogXy5waWNrKG9iamVjdCwgWydhJywgJ2MnXSk7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdjJzogMyB9XG4gICAgICovXG4gICAgdmFyIHBpY2sgPSBmbGF0UmVzdChmdW5jdGlvbihvYmplY3QsIHBhdGhzKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB7fSA6IGJhc2VQaWNrKG9iamVjdCwgcGF0aHMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlIGBvYmplY3RgIHByb3BlcnRpZXMgYHByZWRpY2F0ZWAgcmV0dXJuc1xuICAgICAqIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHR3byBhcmd1bWVudHM6ICh2YWx1ZSwga2V5KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIHByb3BlcnR5LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAnMicsICdjJzogMyB9O1xuICAgICAqXG4gICAgICogXy5waWNrQnkob2JqZWN0LCBfLmlzTnVtYmVyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2MnOiAzIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwaWNrQnkob2JqZWN0LCBwcmVkaWNhdGUpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4ge307XG4gICAgICB9XG4gICAgICB2YXIgcHJvcHMgPSBhcnJheU1hcChnZXRBbGxLZXlzSW4ob2JqZWN0KSwgZnVuY3Rpb24ocHJvcCkge1xuICAgICAgICByZXR1cm4gW3Byb3BdO1xuICAgICAgfSk7XG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUpO1xuICAgICAgcmV0dXJuIGJhc2VQaWNrQnkob2JqZWN0LCBwcm9wcywgZnVuY3Rpb24odmFsdWUsIHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIHByZWRpY2F0ZSh2YWx1ZSwgcGF0aFswXSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmdldGAgZXhjZXB0IHRoYXQgaWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzIGFcbiAgICAgKiBmdW5jdGlvbiBpdCdzIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgaXRzIHBhcmVudCBvYmplY3QgYW5kXG4gICAgICogaXRzIHJlc3VsdCBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHJlc29sdmUuXG4gICAgICogQHBhcmFtIHsqfSBbZGVmYXVsdFZhbHVlXSBUaGUgdmFsdWUgcmV0dXJuZWQgZm9yIGB1bmRlZmluZWRgIHJlc29sdmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjMSc6IDMsICdjMic6IF8uY29uc3RhbnQoNCkgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMxJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMyJyk7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMzJywgJ2RlZmF1bHQnKTtcbiAgICAgKiAvLyA9PiAnZGVmYXVsdCdcbiAgICAgKlxuICAgICAqIF8ucmVzdWx0KG9iamVjdCwgJ2FbMF0uYi5jMycsIF8uY29uc3RhbnQoJ2RlZmF1bHQnKSk7XG4gICAgICogLy8gPT4gJ2RlZmF1bHQnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVzdWx0KG9iamVjdCwgcGF0aCwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICBwYXRoID0gY2FzdFBhdGgocGF0aCwgb2JqZWN0KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aC5sZW5ndGg7XG5cbiAgICAgIC8vIEVuc3VyZSB0aGUgbG9vcCBpcyBlbnRlcmVkIHdoZW4gcGF0aCBpcyBlbXB0eS5cbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIGxlbmd0aCA9IDE7XG4gICAgICAgIG9iamVjdCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W3RvS2V5KHBhdGhbaW5kZXhdKV07XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaW5kZXggPSBsZW5ndGg7XG4gICAgICAgICAgdmFsdWUgPSBkZWZhdWx0VmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0ID0gaXNGdW5jdGlvbih2YWx1ZSkgPyB2YWx1ZS5jYWxsKG9iamVjdCkgOiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdmFsdWUgYXQgYHBhdGhgIG9mIGBvYmplY3RgLiBJZiBhIHBvcnRpb24gb2YgYHBhdGhgIGRvZXNuJ3QgZXhpc3QsXG4gICAgICogaXQncyBjcmVhdGVkLiBBcnJheXMgYXJlIGNyZWF0ZWQgZm9yIG1pc3NpbmcgaW5kZXggcHJvcGVydGllcyB3aGlsZSBvYmplY3RzXG4gICAgICogYXJlIGNyZWF0ZWQgZm9yIGFsbCBvdGhlciBtaXNzaW5nIHByb3BlcnRpZXMuIFVzZSBgXy5zZXRXaXRoYCB0byBjdXN0b21pemVcbiAgICAgKiBgcGF0aGAgY3JlYXRpb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjcuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogMyB9IH1dIH07XG4gICAgICpcbiAgICAgKiBfLnNldChvYmplY3QsICdhWzBdLmIuYycsIDQpO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC5hWzBdLmIuYyk7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5zZXQob2JqZWN0LCBbJ3gnLCAnMCcsICd5JywgJ3onXSwgNSk7XG4gICAgICogY29uc29sZS5sb2cob2JqZWN0LnhbMF0ueS56KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0KG9iamVjdCwgcGF0aCwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IG9iamVjdCA6IGJhc2VTZXQob2JqZWN0LCBwYXRoLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zZXRgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCB0byBwcm9kdWNlIHRoZSBvYmplY3RzIG9mIGBwYXRoYC4gIElmIGBjdXN0b21pemVyYCByZXR1cm5zIGB1bmRlZmluZWRgXG4gICAgICogcGF0aCBjcmVhdGlvbiBpcyBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aHJlZSBhcmd1bWVudHM6IChuc1ZhbHVlLCBrZXksIG5zT2JqZWN0KS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7fTtcbiAgICAgKlxuICAgICAqIF8uc2V0V2l0aChvYmplY3QsICdbMF1bMV0nLCAnYScsIE9iamVjdCk7XG4gICAgICogLy8gPT4geyAnMCc6IHsgJzEnOiAnYScgfSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0V2l0aChvYmplY3QsIHBhdGgsIHZhbHVlLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdmFsdWUsIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2Ygb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkLXZhbHVlIHBhaXJzIGZvciBgb2JqZWN0YFxuICAgICAqIHdoaWNoIGNhbiBiZSBjb25zdW1lZCBieSBgXy5mcm9tUGFpcnNgLiBJZiBgb2JqZWN0YCBpcyBhIG1hcCBvciBzZXQsIGl0c1xuICAgICAqIGVudHJpZXMgYXJlIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGFsaWFzIGVudHJpZXNcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy50b1BhaXJzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFtbJ2EnLCAxXSwgWydiJywgMl1dIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgdmFyIHRvUGFpcnMgPSBjcmVhdGVUb1BhaXJzKGtleXMpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXllZC12YWx1ZSBwYWlyc1xuICAgICAqIGZvciBgb2JqZWN0YCB3aGljaCBjYW4gYmUgY29uc3VtZWQgYnkgYF8uZnJvbVBhaXJzYC4gSWYgYG9iamVjdGAgaXMgYSBtYXBcbiAgICAgKiBvciBzZXQsIGl0cyBlbnRyaWVzIGFyZSByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBhbGlhcyBlbnRyaWVzSW5cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy50b1BhaXJzSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gW1snYScsIDFdLCBbJ2InLCAyXSwgWydjJywgM11dIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgdmFyIHRvUGFpcnNJbiA9IGNyZWF0ZVRvUGFpcnMoa2V5c0luKTtcblxuICAgIC8qKlxuICAgICAqIEFuIGFsdGVybmF0aXZlIHRvIGBfLnJlZHVjZWA7IHRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYG9iamVjdGAgdG8gYSBuZXdcbiAgICAgKiBgYWNjdW11bGF0b3JgIG9iamVjdCB3aGljaCBpcyB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcgZWFjaCBvZiBpdHMgb3duXG4gICAgICogZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyB0aHJ1IGBpdGVyYXRlZWAsIHdpdGggZWFjaCBpbnZvY2F0aW9uXG4gICAgICogcG90ZW50aWFsbHkgbXV0YXRpbmcgdGhlIGBhY2N1bXVsYXRvcmAgb2JqZWN0LiBJZiBgYWNjdW11bGF0b3JgIGlzIG5vdFxuICAgICAqIHByb3ZpZGVkLCBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgc2FtZSBgW1tQcm90b3R5cGVdXWAgd2lsbCBiZSB1c2VkLiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggZm91ciBhcmd1bWVudHM6IChhY2N1bXVsYXRvciwgdmFsdWUsIGtleSwgb2JqZWN0KS5cbiAgICAgKiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFthY2N1bXVsYXRvcl0gVGhlIGN1c3RvbSBhY2N1bXVsYXRvciB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJhbnNmb3JtKFsyLCAzLCA0XSwgZnVuY3Rpb24ocmVzdWx0LCBuKSB7XG4gICAgICogICByZXN1bHQucHVzaChuICo9IG4pO1xuICAgICAqICAgcmV0dXJuIG4gJSAyID09IDA7XG4gICAgICogfSwgW10pO1xuICAgICAqIC8vID0+IFs0LCA5XVxuICAgICAqXG4gICAgICogXy50cmFuc2Zvcm0oeyAnYSc6IDEsICdiJzogMiwgJ2MnOiAxIH0sIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAqICAgKHJlc3VsdFt2YWx1ZV0gfHwgKHJlc3VsdFt2YWx1ZV0gPSBbXSkpLnB1c2goa2V5KTtcbiAgICAgKiB9LCB7fSk7XG4gICAgICogLy8gPT4geyAnMSc6IFsnYScsICdjJ10sICcyJzogWydiJ10gfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybShvYmplY3QsIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgICAgdmFyIGlzQXJyID0gaXNBcnJheShvYmplY3QpLFxuICAgICAgICAgIGlzQXJyTGlrZSA9IGlzQXJyIHx8IGlzQnVmZmVyKG9iamVjdCkgfHwgaXNUeXBlZEFycmF5KG9iamVjdCk7XG5cbiAgICAgIGl0ZXJhdGVlID0gZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDQpO1xuICAgICAgaWYgKGFjY3VtdWxhdG9yID09IG51bGwpIHtcbiAgICAgICAgdmFyIEN0b3IgPSBvYmplY3QgJiYgb2JqZWN0LmNvbnN0cnVjdG9yO1xuICAgICAgICBpZiAoaXNBcnJMaWtlKSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgPSBpc0FyciA/IG5ldyBDdG9yIDogW107XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICAgIGFjY3VtdWxhdG9yID0gaXNGdW5jdGlvbihDdG9yKSA/IGJhc2VDcmVhdGUoZ2V0UHJvdG90eXBlKG9iamVjdCkpIDoge307XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgPSB7fTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgKGlzQXJyTGlrZSA/IGFycmF5RWFjaCA6IGJhc2VGb3JPd24pKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdGVlKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBwcm9wZXJ0eSBhdCBgcGF0aGAgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byB1bnNldC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHByb3BlcnR5IGlzIGRlbGV0ZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiA3IH0gfV0gfTtcbiAgICAgKiBfLnVuc2V0KG9iamVjdCwgJ2FbMF0uYi5jJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2cob2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogW3sgJ2InOiB7fSB9XSB9O1xuICAgICAqXG4gICAgICogXy51bnNldChvYmplY3QsIFsnYScsICcwJywgJ2InLCAnYyddKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJ2EnOiBbeyAnYic6IHt9IH1dIH07XG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5zZXQob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB0cnVlIDogYmFzZVVuc2V0KG9iamVjdCwgcGF0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zZXRgIGV4Y2VwdCB0aGF0IGFjY2VwdHMgYHVwZGF0ZXJgIHRvIHByb2R1Y2UgdGhlXG4gICAgICogdmFsdWUgdG8gc2V0LiBVc2UgYF8udXBkYXRlV2l0aGAgdG8gY3VzdG9taXplIGBwYXRoYCBjcmVhdGlvbi4gVGhlIGB1cGRhdGVyYFxuICAgICAqIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjYuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdXBkYXRlciBUaGUgZnVuY3Rpb24gdG8gcHJvZHVjZSB0aGUgdXBkYXRlZCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy51cGRhdGUob2JqZWN0LCAnYVswXS5iLmMnLCBmdW5jdGlvbihuKSB7IHJldHVybiBuICogbjsgfSk7XG4gICAgICogY29uc29sZS5sb2cob2JqZWN0LmFbMF0uYi5jKTtcbiAgICAgKiAvLyA9PiA5XG4gICAgICpcbiAgICAgKiBfLnVwZGF0ZShvYmplY3QsICd4WzBdLnkueicsIGZ1bmN0aW9uKG4pIHsgcmV0dXJuIG4gPyBuICsgMSA6IDA7IH0pO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC54WzBdLnkueik7XG4gICAgICogLy8gPT4gMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVwZGF0ZShvYmplY3QsIHBhdGgsIHVwZGF0ZXIpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IG9iamVjdCA6IGJhc2VVcGRhdGUob2JqZWN0LCBwYXRoLCBjYXN0RnVuY3Rpb24odXBkYXRlcikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udXBkYXRlYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgb2JqZWN0cyBvZiBgcGF0aGAuICBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYFxuICAgICAqIHBhdGggY3JlYXRpb24gaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAobnNWYWx1ZSwga2V5LCBuc09iamVjdCkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjYuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdXBkYXRlciBUaGUgZnVuY3Rpb24gdG8gcHJvZHVjZSB0aGUgdXBkYXRlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHt9O1xuICAgICAqXG4gICAgICogXy51cGRhdGVXaXRoKG9iamVjdCwgJ1swXVsxXScsIF8uY29uc3RhbnQoJ2EnKSwgT2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICcwJzogeyAnMSc6ICdhJyB9IH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1cGRhdGVXaXRoKG9iamVjdCwgcGF0aCwgdXBkYXRlciwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gb2JqZWN0IDogYmFzZVVwZGF0ZShvYmplY3QsIHBhdGgsIGNhc3RGdW5jdGlvbih1cGRhdGVyKSwgY3VzdG9taXplcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnR5IHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBOb24tb2JqZWN0IHZhbHVlcyBhcmUgY29lcmNlZCB0byBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8udmFsdWVzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsxLCAyXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogXy52YWx1ZXMoJ2hpJyk7XG4gICAgICogLy8gPT4gWydoJywgJ2knXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbHVlcyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IFtdIDogYmFzZVZhbHVlcyhvYmplY3QsIGtleXMob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydHlcbiAgICAgKiB2YWx1ZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLnZhbHVlc0luKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbHVlc0luKG9iamVjdCkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gW10gOiBiYXNlVmFsdWVzKG9iamVjdCwga2V5c0luKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENsYW1wcyBgbnVtYmVyYCB3aXRoaW4gdGhlIGluY2x1c2l2ZSBgbG93ZXJgIGFuZCBgdXBwZXJgIGJvdW5kcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gY2xhbXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsb3dlcl0gVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB1cHBlciBUaGUgdXBwZXIgYm91bmQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY2xhbXBlZCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2xhbXAoLTEwLCAtNSwgNSk7XG4gICAgICogLy8gPT4gLTVcbiAgICAgKlxuICAgICAqIF8uY2xhbXAoMTAsIC01LCA1KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xhbXAobnVtYmVyLCBsb3dlciwgdXBwZXIpIHtcbiAgICAgIGlmICh1cHBlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHVwcGVyID0gbG93ZXI7XG4gICAgICAgIGxvd2VyID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKHVwcGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdXBwZXIgPSB0b051bWJlcih1cHBlcik7XG4gICAgICAgIHVwcGVyID0gdXBwZXIgPT09IHVwcGVyID8gdXBwZXIgOiAwO1xuICAgICAgfVxuICAgICAgaWYgKGxvd2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbG93ZXIgPSB0b051bWJlcihsb3dlcik7XG4gICAgICAgIGxvd2VyID0gbG93ZXIgPT09IGxvd2VyID8gbG93ZXIgOiAwO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VDbGFtcCh0b051bWJlcihudW1iZXIpLCBsb3dlciwgdXBwZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgbmAgaXMgYmV0d2VlbiBgc3RhcnRgIGFuZCB1cCB0bywgYnV0IG5vdCBpbmNsdWRpbmcsIGBlbmRgLiBJZlxuICAgICAqIGBlbmRgIGlzIG5vdCBzcGVjaWZpZWQsIGl0J3Mgc2V0IHRvIGBzdGFydGAgd2l0aCBgc3RhcnRgIHRoZW4gc2V0IHRvIGAwYC5cbiAgICAgKiBJZiBgc3RhcnRgIGlzIGdyZWF0ZXIgdGhhbiBgZW5kYCB0aGUgcGFyYW1zIGFyZSBzd2FwcGVkIHRvIHN1cHBvcnRcbiAgICAgKiBuZWdhdGl2ZSByYW5nZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTnVtYmVyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIGNoZWNrLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIFRoZSBlbmQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgbnVtYmVyYCBpcyBpbiB0aGUgcmFuZ2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAc2VlIF8ucmFuZ2UsIF8ucmFuZ2VSaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoMywgMiwgNCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDQsIDgpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSg0LCAyKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDIsIDIpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoMS4yLCAyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoNS4yLCA0KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKC0zLCAtMiwgLTYpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpblJhbmdlKG51bWJlciwgc3RhcnQsIGVuZCkge1xuICAgICAgc3RhcnQgPSB0b0Zpbml0ZShzdGFydCk7XG4gICAgICBpZiAoZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVuZCA9IHRvRmluaXRlKGVuZCk7XG4gICAgICB9XG4gICAgICBudW1iZXIgPSB0b051bWJlcihudW1iZXIpO1xuICAgICAgcmV0dXJuIGJhc2VJblJhbmdlKG51bWJlciwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvZHVjZXMgYSByYW5kb20gbnVtYmVyIGJldHdlZW4gdGhlIGluY2x1c2l2ZSBgbG93ZXJgIGFuZCBgdXBwZXJgIGJvdW5kcy5cbiAgICAgKiBJZiBvbmx5IG9uZSBhcmd1bWVudCBpcyBwcm92aWRlZCBhIG51bWJlciBiZXR3ZWVuIGAwYCBhbmQgdGhlIGdpdmVuIG51bWJlclxuICAgICAqIGlzIHJldHVybmVkLiBJZiBgZmxvYXRpbmdgIGlzIGB0cnVlYCwgb3IgZWl0aGVyIGBsb3dlcmAgb3IgYHVwcGVyYCBhcmVcbiAgICAgKiBmbG9hdHMsIGEgZmxvYXRpbmctcG9pbnQgbnVtYmVyIGlzIHJldHVybmVkIGluc3RlYWQgb2YgYW4gaW50ZWdlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBKYXZhU2NyaXB0IGZvbGxvd3MgdGhlIElFRUUtNzU0IHN0YW5kYXJkIGZvciByZXNvbHZpbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCB2YWx1ZXMgd2hpY2ggY2FuIHByb2R1Y2UgdW5leHBlY3RlZCByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuNy4wXG4gICAgICogQGNhdGVnb3J5IE51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbG93ZXI9MF0gVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbdXBwZXI9MV0gVGhlIHVwcGVyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zsb2F0aW5nXSBTcGVjaWZ5IHJldHVybmluZyBhIGZsb2F0aW5nLXBvaW50IG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByYW5kb20gbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgwLCA1KTtcbiAgICAgKiAvLyA9PiBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSk7XG4gICAgICogLy8gPT4gYWxzbyBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSwgdHJ1ZSk7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAwIGFuZCA1XG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgxLjIsIDUuMik7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAxLjIgYW5kIDUuMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJhbmRvbShsb3dlciwgdXBwZXIsIGZsb2F0aW5nKSB7XG4gICAgICBpZiAoZmxvYXRpbmcgJiYgdHlwZW9mIGZsb2F0aW5nICE9ICdib29sZWFuJyAmJiBpc0l0ZXJhdGVlQ2FsbChsb3dlciwgdXBwZXIsIGZsb2F0aW5nKSkge1xuICAgICAgICB1cHBlciA9IGZsb2F0aW5nID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKGZsb2F0aW5nID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB1cHBlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICBmbG9hdGluZyA9IHVwcGVyO1xuICAgICAgICAgIHVwcGVyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBsb3dlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICBmbG9hdGluZyA9IGxvd2VyO1xuICAgICAgICAgIGxvd2VyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobG93ZXIgPT09IHVuZGVmaW5lZCAmJiB1cHBlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxvd2VyID0gMDtcbiAgICAgICAgdXBwZXIgPSAxO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGxvd2VyID0gdG9GaW5pdGUobG93ZXIpO1xuICAgICAgICBpZiAodXBwZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHVwcGVyID0gbG93ZXI7XG4gICAgICAgICAgbG93ZXIgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVwcGVyID0gdG9GaW5pdGUodXBwZXIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobG93ZXIgPiB1cHBlcikge1xuICAgICAgICB2YXIgdGVtcCA9IGxvd2VyO1xuICAgICAgICBsb3dlciA9IHVwcGVyO1xuICAgICAgICB1cHBlciA9IHRlbXA7XG4gICAgICB9XG4gICAgICBpZiAoZmxvYXRpbmcgfHwgbG93ZXIgJSAxIHx8IHVwcGVyICUgMSkge1xuICAgICAgICB2YXIgcmFuZCA9IG5hdGl2ZVJhbmRvbSgpO1xuICAgICAgICByZXR1cm4gbmF0aXZlTWluKGxvd2VyICsgKHJhbmQgKiAodXBwZXIgLSBsb3dlciArIGZyZWVQYXJzZUZsb2F0KCcxZS0nICsgKChyYW5kICsgJycpLmxlbmd0aCAtIDEpKSkpLCB1cHBlcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVJhbmRvbShsb3dlciwgdXBwZXIpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIFtjYW1lbCBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DYW1lbENhc2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgY2FtZWwgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNhbWVsQ2FzZSgnRm9vIEJhcicpO1xuICAgICAqIC8vID0+ICdmb29CYXInXG4gICAgICpcbiAgICAgKiBfLmNhbWVsQ2FzZSgnLS1mb28tYmFyLS0nKTtcbiAgICAgKiAvLyA9PiAnZm9vQmFyJ1xuICAgICAqXG4gICAgICogXy5jYW1lbENhc2UoJ19fRk9PX0JBUl9fJyk7XG4gICAgICogLy8gPT4gJ2Zvb0JhcidcbiAgICAgKi9cbiAgICB2YXIgY2FtZWxDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICB3b3JkID0gd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/IGNhcGl0YWxpemUod29yZCkgOiB3b3JkKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgYHN0cmluZ2AgdG8gdXBwZXIgY2FzZSBhbmQgdGhlIHJlbWFpbmluZ1xuICAgICAqIHRvIGxvd2VyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2FwaXRhbGl6ZSgnRlJFRCcpO1xuICAgICAqIC8vID0+ICdGcmVkJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgICByZXR1cm4gdXBwZXJGaXJzdCh0b1N0cmluZyhzdHJpbmcpLnRvTG93ZXJDYXNlKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlYnVycnMgYHN0cmluZ2AgYnkgY29udmVydGluZ1xuICAgICAqIFtMYXRpbi0xIFN1cHBsZW1lbnRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xhdGluLTFfU3VwcGxlbWVudF8oVW5pY29kZV9ibG9jaykjQ2hhcmFjdGVyX3RhYmxlKVxuICAgICAqIGFuZCBbTGF0aW4gRXh0ZW5kZWQtQV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGF0aW5fRXh0ZW5kZWQtQSlcbiAgICAgKiBsZXR0ZXJzIHRvIGJhc2ljIExhdGluIGxldHRlcnMgYW5kIHJlbW92aW5nXG4gICAgICogW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBkZWJ1cnIuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZGVidXJyZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlYnVycignZMOpasOgIHZ1Jyk7XG4gICAgICogLy8gPT4gJ2RlamEgdnUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVidXJyKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiBzdHJpbmcgJiYgc3RyaW5nLnJlcGxhY2UocmVMYXRpbiwgZGVidXJyTGV0dGVyKS5yZXBsYWNlKHJlQ29tYm9NYXJrLCAnJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBzdHJpbmdgIGVuZHMgd2l0aCB0aGUgZ2l2ZW4gdGFyZ2V0IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdGFyZ2V0XSBUaGUgc3RyaW5nIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwb3NpdGlvbj1zdHJpbmcubGVuZ3RoXSBUaGUgcG9zaXRpb24gdG8gc2VhcmNoIHVwIHRvLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgc3RyaW5nYCBlbmRzIHdpdGggYHRhcmdldGAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5lbmRzV2l0aCgnYWJjJywgJ2MnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmVuZHNXaXRoKCdhYmMnLCAnYicpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmVuZHNXaXRoKCdhYmMnLCAnYicsIDIpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlbmRzV2l0aChzdHJpbmcsIHRhcmdldCwgcG9zaXRpb24pIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICB0YXJnZXQgPSBiYXNlVG9TdHJpbmcodGFyZ2V0KTtcblxuICAgICAgdmFyIGxlbmd0aCA9IHN0cmluZy5sZW5ndGg7XG4gICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uID09PSB1bmRlZmluZWRcbiAgICAgICAgPyBsZW5ndGhcbiAgICAgICAgOiBiYXNlQ2xhbXAodG9JbnRlZ2VyKHBvc2l0aW9uKSwgMCwgbGVuZ3RoKTtcblxuICAgICAgdmFyIGVuZCA9IHBvc2l0aW9uO1xuICAgICAgcG9zaXRpb24gLT0gdGFyZ2V0Lmxlbmd0aDtcbiAgICAgIHJldHVybiBwb3NpdGlvbiA+PSAwICYmIHN0cmluZy5zbGljZShwb3NpdGlvbiwgZW5kKSA9PSB0YXJnZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIGNoYXJhY3RlcnMgXCImXCIsIFwiPFwiLCBcIj5cIiwgJ1wiJywgYW5kIFwiJ1wiIGluIGBzdHJpbmdgIHRvIHRoZWlyXG4gICAgICogY29ycmVzcG9uZGluZyBIVE1MIGVudGl0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vIG90aGVyIGNoYXJhY3RlcnMgYXJlIGVzY2FwZWQuIFRvIGVzY2FwZSBhZGRpdGlvbmFsXG4gICAgICogY2hhcmFjdGVycyB1c2UgYSB0aGlyZC1wYXJ0eSBsaWJyYXJ5IGxpa2UgW19oZV9dKGh0dHBzOi8vbXRocy5iZS9oZSkuXG4gICAgICpcbiAgICAgKiBUaG91Z2ggdGhlIFwiPlwiIGNoYXJhY3RlciBpcyBlc2NhcGVkIGZvciBzeW1tZXRyeSwgY2hhcmFjdGVycyBsaWtlXG4gICAgICogXCI+XCIgYW5kIFwiL1wiIGRvbid0IG5lZWQgZXNjYXBpbmcgaW4gSFRNTCBhbmQgaGF2ZSBubyBzcGVjaWFsIG1lYW5pbmdcbiAgICAgKiB1bmxlc3MgdGhleSdyZSBwYXJ0IG9mIGEgdGFnIG9yIHVucXVvdGVkIGF0dHJpYnV0ZSB2YWx1ZS4gU2VlXG4gICAgICogW01hdGhpYXMgQnluZW5zJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2FtYmlndW91cy1hbXBlcnNhbmRzKVxuICAgICAqICh1bmRlciBcInNlbWktcmVsYXRlZCBmdW4gZmFjdFwiKSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogV2hlbiB3b3JraW5nIHdpdGggSFRNTCB5b3Ugc2hvdWxkIGFsd2F5c1xuICAgICAqIFtxdW90ZSBhdHRyaWJ1dGUgdmFsdWVzXShodHRwOi8vd29ua28uY29tL3Bvc3QvaHRtbC1lc2NhcGluZykgdG8gcmVkdWNlXG4gICAgICogWFNTIHZlY3RvcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gZXNjYXBlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmVzY2FwZSgnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnZnJlZCwgYmFybmV5LCAmYW1wOyBwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVzY2FwZShzdHJpbmcpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gKHN0cmluZyAmJiByZUhhc1VuZXNjYXBlZEh0bWwudGVzdChzdHJpbmcpKVxuICAgICAgICA/IHN0cmluZy5yZXBsYWNlKHJlVW5lc2NhcGVkSHRtbCwgZXNjYXBlSHRtbENoYXIpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVzY2FwZXMgdGhlIGBSZWdFeHBgIHNwZWNpYWwgY2hhcmFjdGVycyBcIl5cIiwgXCIkXCIsIFwiXFxcIiwgXCIuXCIsIFwiKlwiLCBcIitcIixcbiAgICAgKiBcIj9cIiwgXCIoXCIsIFwiKVwiLCBcIltcIiwgXCJdXCIsIFwie1wiLCBcIn1cIiwgYW5kIFwifFwiIGluIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGVzY2FwZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlc2NhcGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5lc2NhcGVSZWdFeHAoJ1tsb2Rhc2hdKGh0dHBzOi8vbG9kYXNoLmNvbS8pJyk7XG4gICAgICogLy8gPT4gJ1xcW2xvZGFzaFxcXVxcKGh0dHBzOi8vbG9kYXNoXFwuY29tL1xcKSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlc2NhcGVSZWdFeHAoc3RyaW5nKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgcmV0dXJuIChzdHJpbmcgJiYgcmVIYXNSZWdFeHBDaGFyLnRlc3Qoc3RyaW5nKSlcbiAgICAgICAgPyBzdHJpbmcucmVwbGFjZShyZVJlZ0V4cENoYXIsICdcXFxcJCYnKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0b1xuICAgICAqIFtrZWJhYiBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MZXR0ZXJfY2FzZSNTcGVjaWFsX2Nhc2Vfc3R5bGVzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGtlYmFiIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5rZWJhYkNhc2UoJ0ZvbyBCYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdmb28tYmFyJ1xuICAgICAqL1xuICAgIHZhciBrZWJhYkNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnLScgOiAnJykgKyB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCwgYXMgc3BhY2Ugc2VwYXJhdGVkIHdvcmRzLCB0byBsb3dlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgbG93ZXIgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxvd2VyQ2FzZSgnLS1Gb28tQmFyLS0nKTtcbiAgICAgKiAvLyA9PiAnZm9vIGJhcidcbiAgICAgKlxuICAgICAqIF8ubG93ZXJDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vIGJhcidcbiAgICAgKlxuICAgICAqIF8ubG93ZXJDYXNlKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdmb28gYmFyJ1xuICAgICAqL1xuICAgIHZhciBsb3dlckNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnICcgOiAnJykgKyB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGBzdHJpbmdgIHRvIGxvd2VyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxvd2VyRmlyc3QoJ0ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnZnJlZCdcbiAgICAgKlxuICAgICAqIF8ubG93ZXJGaXJzdCgnRlJFRCcpO1xuICAgICAqIC8vID0+ICdmUkVEJ1xuICAgICAqL1xuICAgIHZhciBsb3dlckZpcnN0ID0gY3JlYXRlQ2FzZUZpcnN0KCd0b0xvd2VyQ2FzZScpO1xuXG4gICAgLyoqXG4gICAgICogUGFkcyBgc3RyaW5nYCBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgc2lkZXMgaWYgaXQncyBzaG9ydGVyIHRoYW4gYGxlbmd0aGAuXG4gICAgICogUGFkZGluZyBjaGFyYWN0ZXJzIGFyZSB0cnVuY2F0ZWQgaWYgdGhleSBjYW4ndCBiZSBldmVubHkgZGl2aWRlZCBieSBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBwYWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWRkZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhZCgnYWJjJywgOCk7XG4gICAgICogLy8gPT4gJyAgYWJjICAgJ1xuICAgICAqXG4gICAgICogXy5wYWQoJ2FiYycsIDgsICdfLScpO1xuICAgICAqIC8vID0+ICdfLWFiY18tXydcbiAgICAgKlxuICAgICAqIF8ucGFkKCdhYmMnLCAzKTtcbiAgICAgKiAvLyA9PiAnYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhZChzdHJpbmcsIGxlbmd0aCwgY2hhcnMpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBsZW5ndGggPSB0b0ludGVnZXIobGVuZ3RoKTtcblxuICAgICAgdmFyIHN0ckxlbmd0aCA9IGxlbmd0aCA/IHN0cmluZ1NpemUoc3RyaW5nKSA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCB8fCBzdHJMZW5ndGggPj0gbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICB2YXIgbWlkID0gKGxlbmd0aCAtIHN0ckxlbmd0aCkgLyAyO1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgY3JlYXRlUGFkZGluZyhuYXRpdmVGbG9vcihtaWQpLCBjaGFycykgK1xuICAgICAgICBzdHJpbmcgK1xuICAgICAgICBjcmVhdGVQYWRkaW5nKG5hdGl2ZUNlaWwobWlkKSwgY2hhcnMpXG4gICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhZHMgYHN0cmluZ2Agb24gdGhlIHJpZ2h0IHNpZGUgaWYgaXQncyBzaG9ydGVyIHRoYW4gYGxlbmd0aGAuIFBhZGRpbmdcbiAgICAgKiBjaGFyYWN0ZXJzIGFyZSB0cnVuY2F0ZWQgaWYgdGhleSBleGNlZWQgYGxlbmd0aGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gcGFkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoPTBdIFRoZSBwYWRkaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPScgJ10gVGhlIHN0cmluZyB1c2VkIGFzIHBhZGRpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcGFkZGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5wYWRFbmQoJ2FiYycsIDYpO1xuICAgICAqIC8vID0+ICdhYmMgICAnXG4gICAgICpcbiAgICAgKiBfLnBhZEVuZCgnYWJjJywgNiwgJ18tJyk7XG4gICAgICogLy8gPT4gJ2FiY18tXydcbiAgICAgKlxuICAgICAqIF8ucGFkRW5kKCdhYmMnLCAzKTtcbiAgICAgKiAvLyA9PiAnYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhZEVuZChzdHJpbmcsIGxlbmd0aCwgY2hhcnMpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBsZW5ndGggPSB0b0ludGVnZXIobGVuZ3RoKTtcblxuICAgICAgdmFyIHN0ckxlbmd0aCA9IGxlbmd0aCA/IHN0cmluZ1NpemUoc3RyaW5nKSA6IDA7XG4gICAgICByZXR1cm4gKGxlbmd0aCAmJiBzdHJMZW5ndGggPCBsZW5ndGgpXG4gICAgICAgID8gKHN0cmluZyArIGNyZWF0ZVBhZGRpbmcobGVuZ3RoIC0gc3RyTGVuZ3RoLCBjaGFycykpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhZHMgYHN0cmluZ2Agb24gdGhlIGxlZnQgc2lkZSBpZiBpdCdzIHNob3J0ZXIgdGhhbiBgbGVuZ3RoYC4gUGFkZGluZ1xuICAgICAqIGNoYXJhY3RlcnMgYXJlIHRydW5jYXRlZCBpZiB0aGV5IGV4Y2VlZCBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBwYWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWRkZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhZFN0YXJ0KCdhYmMnLCA2KTtcbiAgICAgKiAvLyA9PiAnICAgYWJjJ1xuICAgICAqXG4gICAgICogXy5wYWRTdGFydCgnYWJjJywgNiwgJ18tJyk7XG4gICAgICogLy8gPT4gJ18tX2FiYydcbiAgICAgKlxuICAgICAqIF8ucGFkU3RhcnQoJ2FiYycsIDMpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFkU3RhcnQoc3RyaW5nLCBsZW5ndGgsIGNoYXJzKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgbGVuZ3RoID0gdG9JbnRlZ2VyKGxlbmd0aCk7XG5cbiAgICAgIHZhciBzdHJMZW5ndGggPSBsZW5ndGggPyBzdHJpbmdTaXplKHN0cmluZykgOiAwO1xuICAgICAgcmV0dXJuIChsZW5ndGggJiYgc3RyTGVuZ3RoIDwgbGVuZ3RoKVxuICAgICAgICA/IChjcmVhdGVQYWRkaW5nKGxlbmd0aCAtIHN0ckxlbmd0aCwgY2hhcnMpICsgc3RyaW5nKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBhbiBpbnRlZ2VyIG9mIHRoZSBzcGVjaWZpZWQgcmFkaXguIElmIGByYWRpeGAgaXNcbiAgICAgKiBgdW5kZWZpbmVkYCBvciBgMGAsIGEgYHJhZGl4YCBvZiBgMTBgIGlzIHVzZWQgdW5sZXNzIGB2YWx1ZWAgaXMgYVxuICAgICAqIGhleGFkZWNpbWFsLCBpbiB3aGljaCBjYXNlIGEgYHJhZGl4YCBvZiBgMTZgIGlzIHVzZWQuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgYWxpZ25zIHdpdGggdGhlXG4gICAgICogW0VTNSBpbXBsZW1lbnRhdGlvbl0oaHR0cHM6Ly9lczUuZ2l0aHViLmlvLyN4MTUuMS4yLjIpIG9mIGBwYXJzZUludGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtyYWRpeD0xMF0gVGhlIHJhZGl4IHRvIGludGVycHJldCBgdmFsdWVgIGJ5LlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29udmVydGVkIGludGVnZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFyc2VJbnQoJzA4Jyk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzA4JywgJzEwJ10sIF8ucGFyc2VJbnQpO1xuICAgICAqIC8vID0+IFs2LCA4LCAxMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYXJzZUludChzdHJpbmcsIHJhZGl4LCBndWFyZCkge1xuICAgICAgaWYgKGd1YXJkIHx8IHJhZGl4ID09IG51bGwpIHtcbiAgICAgICAgcmFkaXggPSAwO1xuICAgICAgfSBlbHNlIGlmIChyYWRpeCkge1xuICAgICAgICByYWRpeCA9ICtyYWRpeDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVQYXJzZUludCh0b1N0cmluZyhzdHJpbmcpLnJlcGxhY2UocmVUcmltU3RhcnQsICcnKSwgcmFkaXggfHwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVwZWF0cyB0aGUgZ2l2ZW4gc3RyaW5nIGBuYCB0aW1lcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byByZXBlYXQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmVwZWF0IHRoZSBzdHJpbmcuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSByZXBlYXRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCcqJywgMyk7XG4gICAgICogLy8gPT4gJyoqKidcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCdhYmMnLCAyKTtcbiAgICAgKiAvLyA9PiAnYWJjYWJjJ1xuICAgICAqXG4gICAgICogXy5yZXBlYXQoJ2FiYycsIDApO1xuICAgICAqIC8vID0+ICcnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVwZWF0KHN0cmluZywgbiwgZ3VhcmQpIHtcbiAgICAgIGlmICgoZ3VhcmQgPyBpc0l0ZXJhdGVlQ2FsbChzdHJpbmcsIG4sIGd1YXJkKSA6IG4gPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgbiA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuID0gdG9JbnRlZ2VyKG4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VSZXBlYXQodG9TdHJpbmcoc3RyaW5nKSwgbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZXMgbWF0Y2hlcyBmb3IgYHBhdHRlcm5gIGluIGBzdHJpbmdgIHdpdGggYHJlcGxhY2VtZW50YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgU3RyaW5nI3JlcGxhY2VgXShodHRwczovL21kbi5pby9TdHJpbmcvcmVwbGFjZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gcGF0dGVybiBUaGUgcGF0dGVybiB0byByZXBsYWNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258c3RyaW5nfSByZXBsYWNlbWVudCBUaGUgbWF0Y2ggcmVwbGFjZW1lbnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgbW9kaWZpZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJlcGxhY2UoJ0hpIEZyZWQnLCAnRnJlZCcsICdCYXJuZXknKTtcbiAgICAgKiAvLyA9PiAnSGkgQmFybmV5J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlcGxhY2UoKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAgICBzdHJpbmcgPSB0b1N0cmluZyhhcmdzWzBdKTtcblxuICAgICAgcmV0dXJuIGFyZ3MubGVuZ3RoIDwgMyA/IHN0cmluZyA6IHN0cmluZy5yZXBsYWNlKGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvXG4gICAgICogW3NuYWtlIGNhc2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NuYWtlX2Nhc2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc25ha2UgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNuYWtlQ2FzZSgnRm9vIEJhcicpO1xuICAgICAqIC8vID0+ICdmb29fYmFyJ1xuICAgICAqXG4gICAgICogXy5zbmFrZUNhc2UoJ2Zvb0JhcicpO1xuICAgICAqIC8vID0+ICdmb29fYmFyJ1xuICAgICAqXG4gICAgICogXy5zbmFrZUNhc2UoJy0tRk9PLUJBUi0tJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICovXG4gICAgdmFyIHNuYWtlQ2FzZSA9IGNyZWF0ZUNvbXBvdW5kZXIoZnVuY3Rpb24ocmVzdWx0LCB3b3JkLCBpbmRleCkge1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/ICdfJyA6ICcnKSArIHdvcmQudG9Mb3dlckNhc2UoKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBgc3RyaW5nYCBieSBgc2VwYXJhdG9yYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgU3RyaW5nI3NwbGl0YF0oaHR0cHM6Ly9tZG4uaW8vU3RyaW5nL3NwbGl0KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBzcGxpdC5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cHxzdHJpbmd9IHNlcGFyYXRvciBUaGUgc2VwYXJhdG9yIHBhdHRlcm4gdG8gc3BsaXQgYnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsaW1pdF0gVGhlIGxlbmd0aCB0byB0cnVuY2F0ZSByZXN1bHRzIHRvLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc3RyaW5nIHNlZ21lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNwbGl0KCdhLWItYycsICctJywgMik7XG4gICAgICogLy8gPT4gWydhJywgJ2InXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNwbGl0KHN0cmluZywgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgaWYgKGxpbWl0ICYmIHR5cGVvZiBsaW1pdCAhPSAnbnVtYmVyJyAmJiBpc0l0ZXJhdGVlQ2FsbChzdHJpbmcsIHNlcGFyYXRvciwgbGltaXQpKSB7XG4gICAgICAgIHNlcGFyYXRvciA9IGxpbWl0ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWZpbmVkID8gTUFYX0FSUkFZX0xFTkdUSCA6IGxpbWl0ID4+PiAwO1xuICAgICAgaWYgKCFsaW1pdCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKHN0cmluZyAmJiAoXG4gICAgICAgICAgICB0eXBlb2Ygc2VwYXJhdG9yID09ICdzdHJpbmcnIHx8XG4gICAgICAgICAgICAoc2VwYXJhdG9yICE9IG51bGwgJiYgIWlzUmVnRXhwKHNlcGFyYXRvcikpXG4gICAgICAgICAgKSkge1xuICAgICAgICBzZXBhcmF0b3IgPSBiYXNlVG9TdHJpbmcoc2VwYXJhdG9yKTtcbiAgICAgICAgaWYgKCFzZXBhcmF0b3IgJiYgaGFzVW5pY29kZShzdHJpbmcpKSB7XG4gICAgICAgICAgcmV0dXJuIGNhc3RTbGljZShzdHJpbmdUb0FycmF5KHN0cmluZyksIDAsIGxpbWl0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cmluZy5zcGxpdChzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0b1xuICAgICAqIFtzdGFydCBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MZXR0ZXJfY2FzZSNTdHlsaXN0aWNfb3Jfc3BlY2lhbGlzZWRfdXNhZ2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMS4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RhcnQgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0Q2FzZSgnLS1mb28tYmFyLS0nKTtcbiAgICAgKiAvLyA9PiAnRm9vIEJhcidcbiAgICAgKlxuICAgICAqIF8uc3RhcnRDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnRm9vIEJhcidcbiAgICAgKlxuICAgICAqIF8uc3RhcnRDYXNlKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdGT08gQkFSJ1xuICAgICAqL1xuICAgIHZhciBzdGFydENhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnICcgOiAnJykgKyB1cHBlckZpcnN0KHdvcmQpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBzdHJpbmdgIHN0YXJ0cyB3aXRoIHRoZSBnaXZlbiB0YXJnZXQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFt0YXJnZXRdIFRoZSBzdHJpbmcgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3Bvc2l0aW9uPTBdIFRoZSBwb3NpdGlvbiB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHN0cmluZ2Agc3RhcnRzIHdpdGggYHRhcmdldGAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdGFydHNXaXRoKCdhYmMnLCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uc3RhcnRzV2l0aCgnYWJjJywgJ2InKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5zdGFydHNXaXRoKCdhYmMnLCAnYicsIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFydHNXaXRoKHN0cmluZywgdGFyZ2V0LCBwb3NpdGlvbikge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb24gPT0gbnVsbFxuICAgICAgICA/IDBcbiAgICAgICAgOiBiYXNlQ2xhbXAodG9JbnRlZ2VyKHBvc2l0aW9uKSwgMCwgc3RyaW5nLmxlbmd0aCk7XG5cbiAgICAgIHRhcmdldCA9IGJhc2VUb1N0cmluZyh0YXJnZXQpO1xuICAgICAgcmV0dXJuIHN0cmluZy5zbGljZShwb3NpdGlvbiwgcG9zaXRpb24gKyB0YXJnZXQubGVuZ3RoKSA9PSB0YXJnZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNvbXBpbGVkIHRlbXBsYXRlIGZ1bmN0aW9uIHRoYXQgY2FuIGludGVycG9sYXRlIGRhdGEgcHJvcGVydGllc1xuICAgICAqIGluIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXJzLCBIVE1MLWVzY2FwZSBpbnRlcnBvbGF0ZWQgZGF0YSBwcm9wZXJ0aWVzIGluXG4gICAgICogXCJlc2NhcGVcIiBkZWxpbWl0ZXJzLCBhbmQgZXhlY3V0ZSBKYXZhU2NyaXB0IGluIFwiZXZhbHVhdGVcIiBkZWxpbWl0ZXJzLiBEYXRhXG4gICAgICogcHJvcGVydGllcyBtYXkgYmUgYWNjZXNzZWQgYXMgZnJlZSB2YXJpYWJsZXMgaW4gdGhlIHRlbXBsYXRlLiBJZiBhIHNldHRpbmdcbiAgICAgKiBvYmplY3QgaXMgZ2l2ZW4sIGl0IHRha2VzIHByZWNlZGVuY2Ugb3ZlciBgXy50ZW1wbGF0ZVNldHRpbmdzYCB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogSW4gdGhlIGRldmVsb3BtZW50IGJ1aWxkIGBfLnRlbXBsYXRlYCB1dGlsaXplc1xuICAgICAqIFtzb3VyY2VVUkxzXShodHRwOi8vd3d3Lmh0bWw1cm9ja3MuY29tL2VuL3R1dG9yaWFscy9kZXZlbG9wZXJ0b29scy9zb3VyY2VtYXBzLyN0b2Mtc291cmNldXJsKVxuICAgICAqIGZvciBlYXNpZXIgZGVidWdnaW5nLlxuICAgICAqXG4gICAgICogRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gcHJlY29tcGlsaW5nIHRlbXBsYXRlcyBzZWVcbiAgICAgKiBbbG9kYXNoJ3MgY3VzdG9tIGJ1aWxkcyBkb2N1bWVudGF0aW9uXShodHRwczovL2xvZGFzaC5jb20vY3VzdG9tLWJ1aWxkcykuXG4gICAgICpcbiAgICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBDaHJvbWUgZXh0ZW5zaW9uIHNhbmRib3hlcyBzZWVcbiAgICAgKiBbQ2hyb21lJ3MgZXh0ZW5zaW9ucyBkb2N1bWVudGF0aW9uXShodHRwczovL2RldmVsb3Blci5jaHJvbWUuY29tL2V4dGVuc2lvbnMvc2FuZGJveGluZ0V2YWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgdGVtcGxhdGUgc3RyaW5nLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfSBbb3B0aW9ucy5lc2NhcGU9Xy50ZW1wbGF0ZVNldHRpbmdzLmVzY2FwZV1cbiAgICAgKiAgVGhlIEhUTUwgXCJlc2NhcGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmV2YWx1YXRlPV8udGVtcGxhdGVTZXR0aW5ncy5ldmFsdWF0ZV1cbiAgICAgKiAgVGhlIFwiZXZhbHVhdGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmltcG9ydHM9Xy50ZW1wbGF0ZVNldHRpbmdzLmltcG9ydHNdXG4gICAgICogIEFuIG9iamVjdCB0byBpbXBvcnQgaW50byB0aGUgdGVtcGxhdGUgYXMgZnJlZSB2YXJpYWJsZXMuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmludGVycG9sYXRlPV8udGVtcGxhdGVTZXR0aW5ncy5pbnRlcnBvbGF0ZV1cbiAgICAgKiAgVGhlIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLnNvdXJjZVVSTD0nbG9kYXNoLnRlbXBsYXRlU291cmNlc1tuXSddXG4gICAgICogIFRoZSBzb3VyY2VVUkwgb2YgdGhlIGNvbXBpbGVkIHRlbXBsYXRlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy52YXJpYWJsZT0nb2JqJ11cbiAgICAgKiAgVGhlIGRhdGEgb2JqZWN0IHZhcmlhYmxlIG5hbWUuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNvbXBpbGVkIHRlbXBsYXRlIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXIgdG8gY3JlYXRlIGEgY29tcGlsZWQgdGVtcGxhdGUuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGVsbG8gPCU9IHVzZXIgJT4hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdmcmVkJyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCEnXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIEhUTUwgXCJlc2NhcGVcIiBkZWxpbWl0ZXIgdG8gZXNjYXBlIGRhdGEgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJzxiPjwlLSB2YWx1ZSAlPjwvYj4nKTtcbiAgICAgKiBjb21waWxlZCh7ICd2YWx1ZSc6ICc8c2NyaXB0PicgfSk7XG4gICAgICogLy8gPT4gJzxiPiZsdDtzY3JpcHQmZ3Q7PC9iPidcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgXCJldmFsdWF0ZVwiIGRlbGltaXRlciB0byBleGVjdXRlIEphdmFTY3JpcHQgYW5kIGdlbmVyYXRlIEhUTUwuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnPCUgXy5mb3JFYWNoKHVzZXJzLCBmdW5jdGlvbih1c2VyKSB7ICU+PGxpPjwlLSB1c2VyICU+PC9saT48JSB9KTsgJT4nKTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2Vycyc6IFsnZnJlZCcsICdiYXJuZXknXSB9KTtcbiAgICAgKiAvLyA9PiAnPGxpPmZyZWQ8L2xpPjxsaT5iYXJuZXk8L2xpPidcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgaW50ZXJuYWwgYHByaW50YCBmdW5jdGlvbiBpbiBcImV2YWx1YXRlXCIgZGVsaW1pdGVycy5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8JSBwcmludChcImhlbGxvIFwiICsgdXNlcik7ICU+IScpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXInOiAnYmFybmV5JyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gYmFybmV5ISdcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgRVMgdGVtcGxhdGUgbGl0ZXJhbCBkZWxpbWl0ZXIgYXMgYW4gXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlci5cbiAgICAgKiAvLyBEaXNhYmxlIHN1cHBvcnQgYnkgcmVwbGFjaW5nIHRoZSBcImludGVycG9sYXRlXCIgZGVsaW1pdGVyLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hlbGxvICR7IHVzZXIgfSEnKTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2VyJzogJ3BlYmJsZXMnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBwZWJibGVzISdcbiAgICAgKlxuICAgICAqIC8vIFVzZSBiYWNrc2xhc2hlcyB0byB0cmVhdCBkZWxpbWl0ZXJzIGFzIHBsYWluIHRleHQuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnPCU9IFwiXFxcXDwlLSB2YWx1ZSAlXFxcXD5cIiAlPicpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3ZhbHVlJzogJ2lnbm9yZWQnIH0pO1xuICAgICAqIC8vID0+ICc8JS0gdmFsdWUgJT4nXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIGBpbXBvcnRzYCBvcHRpb24gdG8gaW1wb3J0IGBqUXVlcnlgIGFzIGBqcWAuXG4gICAgICogdmFyIHRleHQgPSAnPCUganEuZWFjaCh1c2VycywgZnVuY3Rpb24odXNlcikgeyAlPjxsaT48JS0gdXNlciAlPjwvbGk+PCUgfSk7ICU+JztcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKHRleHQsIHsgJ2ltcG9ydHMnOiB7ICdqcSc6IGpRdWVyeSB9IH0pO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXJzJzogWydmcmVkJywgJ2Jhcm5leSddIH0pO1xuICAgICAqIC8vID0+ICc8bGk+ZnJlZDwvbGk+PGxpPmJhcm5leTwvbGk+J1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBgc291cmNlVVJMYCBvcHRpb24gdG8gc3BlY2lmeSBhIGN1c3RvbSBzb3VyY2VVUkwgZm9yIHRoZSB0ZW1wbGF0ZS5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyA8JT0gdXNlciAlPiEnLCB7ICdzb3VyY2VVUkwnOiAnL2Jhc2ljL2dyZWV0aW5nLmpzdCcgfSk7XG4gICAgICogY29tcGlsZWQoZGF0YSk7XG4gICAgICogLy8gPT4gRmluZCB0aGUgc291cmNlIG9mIFwiZ3JlZXRpbmcuanN0XCIgdW5kZXIgdGhlIFNvdXJjZXMgdGFiIG9yIFJlc291cmNlcyBwYW5lbCBvZiB0aGUgd2ViIGluc3BlY3Rvci5cbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHZhcmlhYmxlYCBvcHRpb24gdG8gZW5zdXJlIGEgd2l0aC1zdGF0ZW1lbnQgaXNuJ3QgdXNlZCBpbiB0aGUgY29tcGlsZWQgdGVtcGxhdGUuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGkgPCU9IGRhdGEudXNlciAlPiEnLCB7ICd2YXJpYWJsZSc6ICdkYXRhJyB9KTtcbiAgICAgKiBjb21waWxlZC5zb3VyY2U7XG4gICAgICogLy8gPT4gZnVuY3Rpb24oZGF0YSkge1xuICAgICAqIC8vICAgdmFyIF9fdCwgX19wID0gJyc7XG4gICAgICogLy8gICBfX3AgKz0gJ2hpICcgKyAoKF9fdCA9ICggZGF0YS51c2VyICkpID09IG51bGwgPyAnJyA6IF9fdCkgKyAnISc7XG4gICAgICogLy8gICByZXR1cm4gX19wO1xuICAgICAqIC8vIH1cbiAgICAgKlxuICAgICAqIC8vIFVzZSBjdXN0b20gdGVtcGxhdGUgZGVsaW1pdGVycy5cbiAgICAgKiBfLnRlbXBsYXRlU2V0dGluZ3MuaW50ZXJwb2xhdGUgPSAve3soW1xcc1xcU10rPyl9fS9nO1xuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hlbGxvIHt7IHVzZXIgfX0hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdtdXN0YWNoZScgfSk7XG4gICAgICogLy8gPT4gJ2hlbGxvIG11c3RhY2hlISdcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHNvdXJjZWAgcHJvcGVydHkgdG8gaW5saW5lIGNvbXBpbGVkIHRlbXBsYXRlcyBmb3IgbWVhbmluZ2Z1bFxuICAgICAqIC8vIGxpbmUgbnVtYmVycyBpbiBlcnJvciBtZXNzYWdlcyBhbmQgc3RhY2sgdHJhY2VzLlxuICAgICAqIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksICdqc3QuanMnKSwgJ1xcXG4gICAgICogICB2YXIgSlNUID0ge1xcXG4gICAgICogICAgIFwibWFpblwiOiAnICsgXy50ZW1wbGF0ZShtYWluVGV4dCkuc291cmNlICsgJ1xcXG4gICAgICogICB9O1xcXG4gICAgICogJyk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gdGVtcGxhdGUoc3RyaW5nLCBvcHRpb25zLCBndWFyZCkge1xuICAgICAgLy8gQmFzZWQgb24gSm9obiBSZXNpZydzIGB0bXBsYCBpbXBsZW1lbnRhdGlvblxuICAgICAgLy8gKGh0dHA6Ly9lam9obi5vcmcvYmxvZy9qYXZhc2NyaXB0LW1pY3JvLXRlbXBsYXRpbmcvKVxuICAgICAgLy8gYW5kIExhdXJhIERva3Rvcm92YSdzIGRvVC5qcyAoaHR0cHM6Ly9naXRodWIuY29tL29sYWRvL2RvVCkuXG4gICAgICB2YXIgc2V0dGluZ3MgPSBsb2Rhc2gudGVtcGxhdGVTZXR0aW5ncztcblxuICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKHN0cmluZywgb3B0aW9ucywgZ3VhcmQpKSB7XG4gICAgICAgIG9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgb3B0aW9ucyA9IGFzc2lnbkluV2l0aCh7fSwgb3B0aW9ucywgc2V0dGluZ3MsIGN1c3RvbURlZmF1bHRzQXNzaWduSW4pO1xuXG4gICAgICB2YXIgaW1wb3J0cyA9IGFzc2lnbkluV2l0aCh7fSwgb3B0aW9ucy5pbXBvcnRzLCBzZXR0aW5ncy5pbXBvcnRzLCBjdXN0b21EZWZhdWx0c0Fzc2lnbkluKSxcbiAgICAgICAgICBpbXBvcnRzS2V5cyA9IGtleXMoaW1wb3J0cyksXG4gICAgICAgICAgaW1wb3J0c1ZhbHVlcyA9IGJhc2VWYWx1ZXMoaW1wb3J0cywgaW1wb3J0c0tleXMpO1xuXG4gICAgICB2YXIgaXNFc2NhcGluZyxcbiAgICAgICAgICBpc0V2YWx1YXRpbmcsXG4gICAgICAgICAgaW5kZXggPSAwLFxuICAgICAgICAgIGludGVycG9sYXRlID0gb3B0aW9ucy5pbnRlcnBvbGF0ZSB8fCByZU5vTWF0Y2gsXG4gICAgICAgICAgc291cmNlID0gXCJfX3AgKz0gJ1wiO1xuXG4gICAgICAvLyBDb21waWxlIHRoZSByZWdleHAgdG8gbWF0Y2ggZWFjaCBkZWxpbWl0ZXIuXG4gICAgICB2YXIgcmVEZWxpbWl0ZXJzID0gUmVnRXhwKFxuICAgICAgICAob3B0aW9ucy5lc2NhcGUgfHwgcmVOb01hdGNoKS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICBpbnRlcnBvbGF0ZS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICAoaW50ZXJwb2xhdGUgPT09IHJlSW50ZXJwb2xhdGUgPyByZUVzVGVtcGxhdGUgOiByZU5vTWF0Y2gpLnNvdXJjZSArICd8JyArXG4gICAgICAgIChvcHRpb25zLmV2YWx1YXRlIHx8IHJlTm9NYXRjaCkuc291cmNlICsgJ3wkJ1xuICAgICAgLCAnZycpO1xuXG4gICAgICAvLyBVc2UgYSBzb3VyY2VVUkwgZm9yIGVhc2llciBkZWJ1Z2dpbmcuXG4gICAgICAvLyBUaGUgc291cmNlVVJMIGdldHMgaW5qZWN0ZWQgaW50byB0aGUgc291cmNlIHRoYXQncyBldmFsLWVkLCBzbyBiZSBjYXJlZnVsXG4gICAgICAvLyB0byBub3JtYWxpemUgYWxsIGtpbmRzIG9mIHdoaXRlc3BhY2UsIHNvIGUuZy4gbmV3bGluZXMgKGFuZCB1bmljb2RlIHZlcnNpb25zIG9mIGl0KSBjYW4ndCBzbmVhayBpblxuICAgICAgLy8gYW5kIGVzY2FwZSB0aGUgY29tbWVudCwgdGh1cyBpbmplY3RpbmcgY29kZSB0aGF0IGdldHMgZXZhbGVkLlxuICAgICAgdmFyIHNvdXJjZVVSTCA9ICcvLyMgc291cmNlVVJMPScgK1xuICAgICAgICAoaGFzT3duUHJvcGVydHkuY2FsbChvcHRpb25zLCAnc291cmNlVVJMJylcbiAgICAgICAgICA/IChvcHRpb25zLnNvdXJjZVVSTCArICcnKS5yZXBsYWNlKC9cXHMvZywgJyAnKVxuICAgICAgICAgIDogKCdsb2Rhc2gudGVtcGxhdGVTb3VyY2VzWycgKyAoKyt0ZW1wbGF0ZUNvdW50ZXIpICsgJ10nKVxuICAgICAgICApICsgJ1xcbic7XG5cbiAgICAgIHN0cmluZy5yZXBsYWNlKHJlRGVsaW1pdGVycywgZnVuY3Rpb24obWF0Y2gsIGVzY2FwZVZhbHVlLCBpbnRlcnBvbGF0ZVZhbHVlLCBlc1RlbXBsYXRlVmFsdWUsIGV2YWx1YXRlVmFsdWUsIG9mZnNldCkge1xuICAgICAgICBpbnRlcnBvbGF0ZVZhbHVlIHx8IChpbnRlcnBvbGF0ZVZhbHVlID0gZXNUZW1wbGF0ZVZhbHVlKTtcblxuICAgICAgICAvLyBFc2NhcGUgY2hhcmFjdGVycyB0aGF0IGNhbid0IGJlIGluY2x1ZGVkIGluIHN0cmluZyBsaXRlcmFscy5cbiAgICAgICAgc291cmNlICs9IHN0cmluZy5zbGljZShpbmRleCwgb2Zmc2V0KS5yZXBsYWNlKHJlVW5lc2NhcGVkU3RyaW5nLCBlc2NhcGVTdHJpbmdDaGFyKTtcblxuICAgICAgICAvLyBSZXBsYWNlIGRlbGltaXRlcnMgd2l0aCBzbmlwcGV0cy5cbiAgICAgICAgaWYgKGVzY2FwZVZhbHVlKSB7XG4gICAgICAgICAgaXNFc2NhcGluZyA9IHRydWU7XG4gICAgICAgICAgc291cmNlICs9IFwiJyArXFxuX19lKFwiICsgZXNjYXBlVmFsdWUgKyBcIikgK1xcbidcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXZhbHVhdGVWYWx1ZSkge1xuICAgICAgICAgIGlzRXZhbHVhdGluZyA9IHRydWU7XG4gICAgICAgICAgc291cmNlICs9IFwiJztcXG5cIiArIGV2YWx1YXRlVmFsdWUgKyBcIjtcXG5fX3AgKz0gJ1wiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpbnRlcnBvbGF0ZVZhbHVlKSB7XG4gICAgICAgICAgc291cmNlICs9IFwiJyArXFxuKChfX3QgPSAoXCIgKyBpbnRlcnBvbGF0ZVZhbHVlICsgXCIpKSA9PSBudWxsID8gJycgOiBfX3QpICtcXG4nXCI7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSBvZmZzZXQgKyBtYXRjaC5sZW5ndGg7XG5cbiAgICAgICAgLy8gVGhlIEpTIGVuZ2luZSBlbWJlZGRlZCBpbiBBZG9iZSBwcm9kdWN0cyBuZWVkcyBgbWF0Y2hgIHJldHVybmVkIGluXG4gICAgICAgIC8vIG9yZGVyIHRvIHByb2R1Y2UgdGhlIGNvcnJlY3QgYG9mZnNldGAgdmFsdWUuXG4gICAgICAgIHJldHVybiBtYXRjaDtcbiAgICAgIH0pO1xuXG4gICAgICBzb3VyY2UgKz0gXCInO1xcblwiO1xuXG4gICAgICAvLyBJZiBgdmFyaWFibGVgIGlzIG5vdCBzcGVjaWZpZWQgd3JhcCBhIHdpdGgtc3RhdGVtZW50IGFyb3VuZCB0aGUgZ2VuZXJhdGVkXG4gICAgICAvLyBjb2RlIHRvIGFkZCB0aGUgZGF0YSBvYmplY3QgdG8gdGhlIHRvcCBvZiB0aGUgc2NvcGUgY2hhaW4uXG4gICAgICB2YXIgdmFyaWFibGUgPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9wdGlvbnMsICd2YXJpYWJsZScpICYmIG9wdGlvbnMudmFyaWFibGU7XG4gICAgICBpZiAoIXZhcmlhYmxlKSB7XG4gICAgICAgIHNvdXJjZSA9ICd3aXRoIChvYmopIHtcXG4nICsgc291cmNlICsgJ1xcbn1cXG4nO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYW51cCBjb2RlIGJ5IHN0cmlwcGluZyBlbXB0eSBzdHJpbmdzLlxuICAgICAgc291cmNlID0gKGlzRXZhbHVhdGluZyA/IHNvdXJjZS5yZXBsYWNlKHJlRW1wdHlTdHJpbmdMZWFkaW5nLCAnJykgOiBzb3VyY2UpXG4gICAgICAgIC5yZXBsYWNlKHJlRW1wdHlTdHJpbmdNaWRkbGUsICckMScpXG4gICAgICAgIC5yZXBsYWNlKHJlRW1wdHlTdHJpbmdUcmFpbGluZywgJyQxOycpO1xuXG4gICAgICAvLyBGcmFtZSBjb2RlIGFzIHRoZSBmdW5jdGlvbiBib2R5LlxuICAgICAgc291cmNlID0gJ2Z1bmN0aW9uKCcgKyAodmFyaWFibGUgfHwgJ29iaicpICsgJykge1xcbicgK1xuICAgICAgICAodmFyaWFibGVcbiAgICAgICAgICA/ICcnXG4gICAgICAgICAgOiAnb2JqIHx8IChvYmogPSB7fSk7XFxuJ1xuICAgICAgICApICtcbiAgICAgICAgXCJ2YXIgX190LCBfX3AgPSAnJ1wiICtcbiAgICAgICAgKGlzRXNjYXBpbmdcbiAgICAgICAgICAgPyAnLCBfX2UgPSBfLmVzY2FwZSdcbiAgICAgICAgICAgOiAnJ1xuICAgICAgICApICtcbiAgICAgICAgKGlzRXZhbHVhdGluZ1xuICAgICAgICAgID8gJywgX19qID0gQXJyYXkucHJvdG90eXBlLmpvaW47XFxuJyArXG4gICAgICAgICAgICBcImZ1bmN0aW9uIHByaW50KCkgeyBfX3AgKz0gX19qLmNhbGwoYXJndW1lbnRzLCAnJykgfVxcblwiXG4gICAgICAgICAgOiAnO1xcbidcbiAgICAgICAgKSArXG4gICAgICAgIHNvdXJjZSArXG4gICAgICAgICdyZXR1cm4gX19wXFxufSc7XG5cbiAgICAgIHZhciByZXN1bHQgPSBhdHRlbXB0KGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gRnVuY3Rpb24oaW1wb3J0c0tleXMsIHNvdXJjZVVSTCArICdyZXR1cm4gJyArIHNvdXJjZSlcbiAgICAgICAgICAuYXBwbHkodW5kZWZpbmVkLCBpbXBvcnRzVmFsdWVzKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBQcm92aWRlIHRoZSBjb21waWxlZCBmdW5jdGlvbidzIHNvdXJjZSBieSBpdHMgYHRvU3RyaW5nYCBtZXRob2Qgb3JcbiAgICAgIC8vIHRoZSBgc291cmNlYCBwcm9wZXJ0eSBhcyBhIGNvbnZlbmllbmNlIGZvciBpbmxpbmluZyBjb21waWxlZCB0ZW1wbGF0ZXMuXG4gICAgICByZXN1bHQuc291cmNlID0gc291cmNlO1xuICAgICAgaWYgKGlzRXJyb3IocmVzdWx0KSkge1xuICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgLCBhcyBhIHdob2xlLCB0byBsb3dlciBjYXNlIGp1c3QgbGlrZVxuICAgICAqIFtTdHJpbmcjdG9Mb3dlckNhc2VdKGh0dHBzOi8vbWRuLmlvL3RvTG93ZXJDYXNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGxvd2VyIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b0xvd2VyKCctLUZvby1CYXItLScpO1xuICAgICAqIC8vID0+ICctLWZvby1iYXItLSdcbiAgICAgKlxuICAgICAqIF8udG9Mb3dlcignZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb2JhcidcbiAgICAgKlxuICAgICAqIF8udG9Mb3dlcignX19GT09fQkFSX18nKTtcbiAgICAgKiAvLyA9PiAnX19mb29fYmFyX18nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9Mb3dlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nKHZhbHVlKS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgLCBhcyBhIHdob2xlLCB0byB1cHBlciBjYXNlIGp1c3QgbGlrZVxuICAgICAqIFtTdHJpbmcjdG9VcHBlckNhc2VdKGh0dHBzOi8vbWRuLmlvL3RvVXBwZXJDYXNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHVwcGVyIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b1VwcGVyKCctLWZvby1iYXItLScpO1xuICAgICAqIC8vID0+ICctLUZPTy1CQVItLSdcbiAgICAgKlxuICAgICAqIF8udG9VcHBlcignZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ0ZPT0JBUidcbiAgICAgKlxuICAgICAqIF8udG9VcHBlcignX19mb29fYmFyX18nKTtcbiAgICAgKiAvLyA9PiAnX19GT09fQkFSX18nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9VcHBlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nKHZhbHVlKS50b1VwcGVyQ2FzZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBvciBzcGVjaWZpZWQgY2hhcmFjdGVycyBmcm9tIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz13aGl0ZXNwYWNlXSBUaGUgY2hhcmFjdGVycyB0byB0cmltLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbSgnICBhYmMgICcpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLnRyaW0oJy1fLWFiYy1fLScsICdfLScpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLm1hcChbJyAgZm9vICAnLCAnICBiYXIgICddLCBfLnRyaW0pO1xuICAgICAqIC8vID0+IFsnZm9vJywgJ2JhciddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJpbShzdHJpbmcsIGNoYXJzLCBndWFyZCkge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIGlmIChzdHJpbmcgJiYgKGd1YXJkIHx8IGNoYXJzID09PSB1bmRlZmluZWQpKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZShyZVRyaW0sICcnKTtcbiAgICAgIH1cbiAgICAgIGlmICghc3RyaW5nIHx8ICEoY2hhcnMgPSBiYXNlVG9TdHJpbmcoY2hhcnMpKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIHN0clN5bWJvbHMgPSBzdHJpbmdUb0FycmF5KHN0cmluZyksXG4gICAgICAgICAgY2hyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoY2hhcnMpLFxuICAgICAgICAgIHN0YXJ0ID0gY2hhcnNTdGFydEluZGV4KHN0clN5bWJvbHMsIGNoclN5bWJvbHMpLFxuICAgICAgICAgIGVuZCA9IGNoYXJzRW5kSW5kZXgoc3RyU3ltYm9scywgY2hyU3ltYm9scykgKyAxO1xuXG4gICAgICByZXR1cm4gY2FzdFNsaWNlKHN0clN5bWJvbHMsIHN0YXJ0LCBlbmQpLmpvaW4oJycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdHJhaWxpbmcgd2hpdGVzcGFjZSBvciBzcGVjaWZpZWQgY2hhcmFjdGVycyBmcm9tIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz13aGl0ZXNwYWNlXSBUaGUgY2hhcmFjdGVycyB0byB0cmltLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbUVuZCgnICBhYmMgICcpO1xuICAgICAqIC8vID0+ICcgIGFiYydcbiAgICAgKlxuICAgICAqIF8udHJpbUVuZCgnLV8tYWJjLV8tJywgJ18tJyk7XG4gICAgICogLy8gPT4gJy1fLWFiYydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmltRW5kKHN0cmluZywgY2hhcnMsIGd1YXJkKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKHN0cmluZyAmJiAoZ3VhcmQgfHwgY2hhcnMgPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKHJlVHJpbUVuZCwgJycpO1xuICAgICAgfVxuICAgICAgaWYgKCFzdHJpbmcgfHwgIShjaGFycyA9IGJhc2VUb1N0cmluZyhjaGFycykpKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICB2YXIgc3RyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoc3RyaW5nKSxcbiAgICAgICAgICBlbmQgPSBjaGFyc0VuZEluZGV4KHN0clN5bWJvbHMsIHN0cmluZ1RvQXJyYXkoY2hhcnMpKSArIDE7XG5cbiAgICAgIHJldHVybiBjYXN0U2xpY2Uoc3RyU3ltYm9scywgMCwgZW5kKS5qb2luKCcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGxlYWRpbmcgd2hpdGVzcGFjZSBvciBzcGVjaWZpZWQgY2hhcmFjdGVycyBmcm9tIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz13aGl0ZXNwYWNlXSBUaGUgY2hhcmFjdGVycyB0byB0cmltLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbVN0YXJ0KCcgIGFiYyAgJyk7XG4gICAgICogLy8gPT4gJ2FiYyAgJ1xuICAgICAqXG4gICAgICogXy50cmltU3RhcnQoJy1fLWFiYy1fLScsICdfLScpO1xuICAgICAqIC8vID0+ICdhYmMtXy0nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJpbVN0YXJ0KHN0cmluZywgY2hhcnMsIGd1YXJkKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKHN0cmluZyAmJiAoZ3VhcmQgfHwgY2hhcnMgPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKHJlVHJpbVN0YXJ0LCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoIXN0cmluZyB8fCAhKGNoYXJzID0gYmFzZVRvU3RyaW5nKGNoYXJzKSkpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZztcbiAgICAgIH1cbiAgICAgIHZhciBzdHJTeW1ib2xzID0gc3RyaW5nVG9BcnJheShzdHJpbmcpLFxuICAgICAgICAgIHN0YXJ0ID0gY2hhcnNTdGFydEluZGV4KHN0clN5bWJvbHMsIHN0cmluZ1RvQXJyYXkoY2hhcnMpKTtcblxuICAgICAgcmV0dXJuIGNhc3RTbGljZShzdHJTeW1ib2xzLCBzdGFydCkuam9pbignJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ1bmNhdGVzIGBzdHJpbmdgIGlmIGl0J3MgbG9uZ2VyIHRoYW4gdGhlIGdpdmVuIG1heGltdW0gc3RyaW5nIGxlbmd0aC5cbiAgICAgKiBUaGUgbGFzdCBjaGFyYWN0ZXJzIG9mIHRoZSB0cnVuY2F0ZWQgc3RyaW5nIGFyZSByZXBsYWNlZCB3aXRoIHRoZSBvbWlzc2lvblxuICAgICAqIHN0cmluZyB3aGljaCBkZWZhdWx0cyB0byBcIi4uLlwiLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRydW5jYXRlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5sZW5ndGg9MzBdIFRoZSBtYXhpbXVtIHN0cmluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLm9taXNzaW9uPScuLi4nXSBUaGUgc3RyaW5nIHRvIGluZGljYXRlIHRleHQgaXMgb21pdHRlZC5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cHxzdHJpbmd9IFtvcHRpb25zLnNlcGFyYXRvcl0gVGhlIHNlcGFyYXRvciBwYXR0ZXJuIHRvIHRydW5jYXRlIHRvLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHRydW5jYXRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJ1bmNhdGUoJ2hpLWRpZGRseS1obyB0aGVyZSwgbmVpZ2hib3Jpbm8nKTtcbiAgICAgKiAvLyA9PiAnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdsZW5ndGgnOiAyNCxcbiAgICAgKiAgICdzZXBhcmF0b3InOiAnICdcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAnaGktZGlkZGx5LWhvIHRoZXJlLC4uLidcbiAgICAgKlxuICAgICAqIF8udHJ1bmNhdGUoJ2hpLWRpZGRseS1obyB0aGVyZSwgbmVpZ2hib3Jpbm8nLCB7XG4gICAgICogICAnbGVuZ3RoJzogMjQsXG4gICAgICogICAnc2VwYXJhdG9yJzogLyw/ICsvXG4gICAgICogfSk7XG4gICAgICogLy8gPT4gJ2hpLWRpZGRseS1obyB0aGVyZS4uLidcbiAgICAgKlxuICAgICAqIF8udHJ1bmNhdGUoJ2hpLWRpZGRseS1obyB0aGVyZSwgbmVpZ2hib3Jpbm8nLCB7XG4gICAgICogICAnb21pc3Npb24nOiAnIFsuLi5dJ1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWcgWy4uLl0nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJ1bmNhdGUoc3RyaW5nLCBvcHRpb25zKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gREVGQVVMVF9UUlVOQ19MRU5HVEgsXG4gICAgICAgICAgb21pc3Npb24gPSBERUZBVUxUX1RSVU5DX09NSVNTSU9OO1xuXG4gICAgICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgICAgdmFyIHNlcGFyYXRvciA9ICdzZXBhcmF0b3InIGluIG9wdGlvbnMgPyBvcHRpb25zLnNlcGFyYXRvciA6IHNlcGFyYXRvcjtcbiAgICAgICAgbGVuZ3RoID0gJ2xlbmd0aCcgaW4gb3B0aW9ucyA/IHRvSW50ZWdlcihvcHRpb25zLmxlbmd0aCkgOiBsZW5ndGg7XG4gICAgICAgIG9taXNzaW9uID0gJ29taXNzaW9uJyBpbiBvcHRpb25zID8gYmFzZVRvU3RyaW5nKG9wdGlvbnMub21pc3Npb24pIDogb21pc3Npb247XG4gICAgICB9XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuXG4gICAgICB2YXIgc3RyTGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcbiAgICAgIGlmIChoYXNVbmljb2RlKHN0cmluZykpIHtcbiAgICAgICAgdmFyIHN0clN5bWJvbHMgPSBzdHJpbmdUb0FycmF5KHN0cmluZyk7XG4gICAgICAgIHN0ckxlbmd0aCA9IHN0clN5bWJvbHMubGVuZ3RoO1xuICAgICAgfVxuICAgICAgaWYgKGxlbmd0aCA+PSBzdHJMZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZztcbiAgICAgIH1cbiAgICAgIHZhciBlbmQgPSBsZW5ndGggLSBzdHJpbmdTaXplKG9taXNzaW9uKTtcbiAgICAgIGlmIChlbmQgPCAxKSB7XG4gICAgICAgIHJldHVybiBvbWlzc2lvbjtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSBzdHJTeW1ib2xzXG4gICAgICAgID8gY2FzdFNsaWNlKHN0clN5bWJvbHMsIDAsIGVuZCkuam9pbignJylcbiAgICAgICAgOiBzdHJpbmcuc2xpY2UoMCwgZW5kKTtcblxuICAgICAgaWYgKHNlcGFyYXRvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgKyBvbWlzc2lvbjtcbiAgICAgIH1cbiAgICAgIGlmIChzdHJTeW1ib2xzKSB7XG4gICAgICAgIGVuZCArPSAocmVzdWx0Lmxlbmd0aCAtIGVuZCk7XG4gICAgICB9XG4gICAgICBpZiAoaXNSZWdFeHAoc2VwYXJhdG9yKSkge1xuICAgICAgICBpZiAoc3RyaW5nLnNsaWNlKGVuZCkuc2VhcmNoKHNlcGFyYXRvcikpIHtcbiAgICAgICAgICB2YXIgbWF0Y2gsXG4gICAgICAgICAgICAgIHN1YnN0cmluZyA9IHJlc3VsdDtcblxuICAgICAgICAgIGlmICghc2VwYXJhdG9yLmdsb2JhbCkge1xuICAgICAgICAgICAgc2VwYXJhdG9yID0gUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIHRvU3RyaW5nKHJlRmxhZ3MuZXhlYyhzZXBhcmF0b3IpKSArICdnJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXggPSAwO1xuICAgICAgICAgIHdoaWxlICgobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdWJzdHJpbmcpKSkge1xuICAgICAgICAgICAgdmFyIG5ld0VuZCA9IG1hdGNoLmluZGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSByZXN1bHQuc2xpY2UoMCwgbmV3RW5kID09PSB1bmRlZmluZWQgPyBlbmQgOiBuZXdFbmQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0cmluZy5pbmRleE9mKGJhc2VUb1N0cmluZyhzZXBhcmF0b3IpLCBlbmQpICE9IGVuZCkge1xuICAgICAgICB2YXIgaW5kZXggPSByZXN1bHQubGFzdEluZGV4T2Yoc2VwYXJhdG9yKTtcbiAgICAgICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgICAgICByZXN1bHQgPSByZXN1bHQuc2xpY2UoMCwgaW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0ICsgb21pc3Npb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGludmVyc2Ugb2YgYF8uZXNjYXBlYDsgdGhpcyBtZXRob2QgY29udmVydHMgdGhlIEhUTUwgZW50aXRpZXNcbiAgICAgKiBgJmFtcDtgLCBgJmx0O2AsIGAmZ3Q7YCwgYCZxdW90O2AsIGFuZCBgJiMzOTtgIGluIGBzdHJpbmdgIHRvXG4gICAgICogdGhlaXIgY29ycmVzcG9uZGluZyBjaGFyYWN0ZXJzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vIG90aGVyIEhUTUwgZW50aXRpZXMgYXJlIHVuZXNjYXBlZC4gVG8gdW5lc2NhcGUgYWRkaXRpb25hbFxuICAgICAqIEhUTUwgZW50aXRpZXMgdXNlIGEgdGhpcmQtcGFydHkgbGlicmFyeSBsaWtlIFtfaGVfXShodHRwczovL210aHMuYmUvaGUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuNi4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHVuZXNjYXBlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHVuZXNjYXBlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5lc2NhcGUoJ2ZyZWQsIGJhcm5leSwgJmFtcDsgcGViYmxlcycpO1xuICAgICAqIC8vID0+ICdmcmVkLCBiYXJuZXksICYgcGViYmxlcydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmVzY2FwZShzdHJpbmcpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gKHN0cmluZyAmJiByZUhhc0VzY2FwZWRIdG1sLnRlc3Qoc3RyaW5nKSlcbiAgICAgICAgPyBzdHJpbmcucmVwbGFjZShyZUVzY2FwZWRIdG1sLCB1bmVzY2FwZUh0bWxDaGFyKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCwgYXMgc3BhY2Ugc2VwYXJhdGVkIHdvcmRzLCB0byB1cHBlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdXBwZXIgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVwcGVyQ2FzZSgnLS1mb28tYmFyJyk7XG4gICAgICogLy8gPT4gJ0ZPTyBCQVInXG4gICAgICpcbiAgICAgKiBfLnVwcGVyQ2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ0ZPTyBCQVInXG4gICAgICpcbiAgICAgKiBfLnVwcGVyQ2FzZSgnX19mb29fYmFyX18nKTtcbiAgICAgKiAvLyA9PiAnRk9PIEJBUidcbiAgICAgKi9cbiAgICB2YXIgdXBwZXJDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gJyAnIDogJycpICsgd29yZC50b1VwcGVyQ2FzZSgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiBgc3RyaW5nYCB0byB1cHBlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgY29udmVydGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51cHBlckZpcnN0KCdmcmVkJyk7XG4gICAgICogLy8gPT4gJ0ZyZWQnXG4gICAgICpcbiAgICAgKiBfLnVwcGVyRmlyc3QoJ0ZSRUQnKTtcbiAgICAgKiAvLyA9PiAnRlJFRCdcbiAgICAgKi9cbiAgICB2YXIgdXBwZXJGaXJzdCA9IGNyZWF0ZUNhc2VGaXJzdCgndG9VcHBlckNhc2UnKTtcblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBgc3RyaW5nYCBpbnRvIGFuIGFycmF5IG9mIGl0cyB3b3Jkcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gW3BhdHRlcm5dIFRoZSBwYXR0ZXJuIHRvIG1hdGNoIHdvcmRzLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB3b3JkcyBvZiBgc3RyaW5nYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy53b3JkcygnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiBbJ2ZyZWQnLCAnYmFybmV5JywgJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogXy53b3JkcygnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnLCAvW14sIF0rL2cpO1xuICAgICAqIC8vID0+IFsnZnJlZCcsICdiYXJuZXknLCAnJicsICdwZWJibGVzJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3b3JkcyhzdHJpbmcsIHBhdHRlcm4sIGd1YXJkKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgcGF0dGVybiA9IGd1YXJkID8gdW5kZWZpbmVkIDogcGF0dGVybjtcblxuICAgICAgaWYgKHBhdHRlcm4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gaGFzVW5pY29kZVdvcmQoc3RyaW5nKSA/IHVuaWNvZGVXb3JkcyhzdHJpbmcpIDogYXNjaWlXb3JkcyhzdHJpbmcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cmluZy5tYXRjaChwYXR0ZXJuKSB8fCBbXTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBBdHRlbXB0cyB0byBpbnZva2UgYGZ1bmNgLCByZXR1cm5pbmcgZWl0aGVyIHRoZSByZXN1bHQgb3IgdGhlIGNhdWdodCBlcnJvclxuICAgICAqIG9iamVjdC4gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZSBwcm92aWRlZCB0byBgZnVuY2Agd2hlbiBpdCdzIGludm9rZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGF0dGVtcHQuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgYGZ1bmNgIHdpdGguXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGBmdW5jYCByZXN1bHQgb3IgZXJyb3Igb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBBdm9pZCB0aHJvd2luZyBlcnJvcnMgZm9yIGludmFsaWQgc2VsZWN0b3JzLlxuICAgICAqIHZhciBlbGVtZW50cyA9IF8uYXR0ZW1wdChmdW5jdGlvbihzZWxlY3Rvcikge1xuICAgICAqICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuICAgICAqIH0sICc+Xz4nKTtcbiAgICAgKlxuICAgICAqIGlmIChfLmlzRXJyb3IoZWxlbWVudHMpKSB7XG4gICAgICogICBlbGVtZW50cyA9IFtdO1xuICAgICAqIH1cbiAgICAgKi9cbiAgICB2YXIgYXR0ZW1wdCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGZ1bmMsIGFyZ3MpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhcHBseShmdW5jLCB1bmRlZmluZWQsIGFyZ3MpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gaXNFcnJvcihlKSA/IGUgOiBuZXcgRXJyb3IoZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBCaW5kcyBtZXRob2RzIG9mIGFuIG9iamVjdCB0byB0aGUgb2JqZWN0IGl0c2VsZiwgb3ZlcndyaXRpbmcgdGhlIGV4aXN0aW5nXG4gICAgICogbWV0aG9kLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IG9mIGJvdW5kIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGJpbmQgYW5kIGFzc2lnbiB0aGUgYm91bmQgbWV0aG9kcyB0by5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBtZXRob2ROYW1lcyBUaGUgb2JqZWN0IG1ldGhvZCBuYW1lcyB0byBiaW5kLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB2aWV3ID0ge1xuICAgICAqICAgJ2xhYmVsJzogJ2RvY3MnLFxuICAgICAqICAgJ2NsaWNrJzogZnVuY3Rpb24oKSB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdjbGlja2VkICcgKyB0aGlzLmxhYmVsKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5iaW5kQWxsKHZpZXcsIFsnY2xpY2snXSk7XG4gICAgICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIHZpZXcuY2xpY2spO1xuICAgICAqIC8vID0+IExvZ3MgJ2NsaWNrZWQgZG9jcycgd2hlbiBjbGlja2VkLlxuICAgICAqL1xuICAgIHZhciBiaW5kQWxsID0gZmxhdFJlc3QoZnVuY3Rpb24ob2JqZWN0LCBtZXRob2ROYW1lcykge1xuICAgICAgYXJyYXlFYWNoKG1ldGhvZE5hbWVzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAga2V5ID0gdG9LZXkoa2V5KTtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKG9iamVjdCwga2V5LCBiaW5kKG9iamVjdFtrZXldLCBvYmplY3QpKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGl0ZXJhdGVzIG92ZXIgYHBhaXJzYCBhbmQgaW52b2tlcyB0aGUgY29ycmVzcG9uZGluZ1xuICAgICAqIGZ1bmN0aW9uIG9mIHRoZSBmaXJzdCBwcmVkaWNhdGUgdG8gcmV0dXJuIHRydXRoeS4gVGhlIHByZWRpY2F0ZS1mdW5jdGlvblxuICAgICAqIHBhaXJzIGFyZSBpbnZva2VkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIGFuZCBhcmd1bWVudHMgb2YgdGhlIGNyZWF0ZWRcbiAgICAgKiBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGFpcnMgVGhlIHByZWRpY2F0ZS1mdW5jdGlvbiBwYWlycy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjb21wb3NpdGUgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBmdW5jID0gXy5jb25kKFtcbiAgICAgKiAgIFtfLm1hdGNoZXMoeyAnYSc6IDEgfSksICAgICAgICAgICBfLmNvbnN0YW50KCdtYXRjaGVzIEEnKV0sXG4gICAgICogICBbXy5jb25mb3Jtcyh7ICdiJzogXy5pc051bWJlciB9KSwgXy5jb25zdGFudCgnbWF0Y2hlcyBCJyldLFxuICAgICAqICAgW18uc3R1YlRydWUsICAgICAgICAgICAgICAgICAgICAgIF8uY29uc3RhbnQoJ25vIG1hdGNoJyldXG4gICAgICogXSk7XG4gICAgICpcbiAgICAgKiBmdW5jKHsgJ2EnOiAxLCAnYic6IDIgfSk7XG4gICAgICogLy8gPT4gJ21hdGNoZXMgQSdcbiAgICAgKlxuICAgICAqIGZ1bmMoeyAnYSc6IDAsICdiJzogMSB9KTtcbiAgICAgKiAvLyA9PiAnbWF0Y2hlcyBCJ1xuICAgICAqXG4gICAgICogZnVuYyh7ICdhJzogJzEnLCAnYic6ICcyJyB9KTtcbiAgICAgKiAvLyA9PiAnbm8gbWF0Y2gnXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uZChwYWlycykge1xuICAgICAgdmFyIGxlbmd0aCA9IHBhaXJzID09IG51bGwgPyAwIDogcGFpcnMubGVuZ3RoLFxuICAgICAgICAgIHRvSXRlcmF0ZWUgPSBnZXRJdGVyYXRlZSgpO1xuXG4gICAgICBwYWlycyA9ICFsZW5ndGggPyBbXSA6IGFycmF5TWFwKHBhaXJzLCBmdW5jdGlvbihwYWlyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcGFpclsxXSAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbdG9JdGVyYXRlZShwYWlyWzBdKSwgcGFpclsxXV07XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGJhc2VSZXN0KGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTE7XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIHBhaXIgPSBwYWlyc1tpbmRleF07XG4gICAgICAgICAgaWYgKGFwcGx5KHBhaXJbMF0sIHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgICByZXR1cm4gYXBwbHkocGFpclsxXSwgdGhpcywgYXJncyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBwcmVkaWNhdGUgcHJvcGVydGllcyBvZiBgc291cmNlYCB3aXRoXG4gICAgICogdGhlIGNvcnJlc3BvbmRpbmcgcHJvcGVydHkgdmFsdWVzIG9mIGEgZ2l2ZW4gb2JqZWN0LCByZXR1cm5pbmcgYHRydWVgIGlmXG4gICAgICogYWxsIHByZWRpY2F0ZXMgcmV0dXJuIHRydXRoeSwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoZSBjcmVhdGVkIGZ1bmN0aW9uIGlzIGVxdWl2YWxlbnQgdG8gYF8uY29uZm9ybXNUb2Agd2l0aFxuICAgICAqIGBzb3VyY2VgIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgcHJlZGljYXRlcyB0byBjb25mb3JtIHRvLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IDIsICdiJzogMSB9LFxuICAgICAqICAgeyAnYSc6IDEsICdiJzogMiB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKG9iamVjdHMsIF8uY29uZm9ybXMoeyAnYic6IGZ1bmN0aW9uKG4pIHsgcmV0dXJuIG4gPiAxOyB9IH0pKTtcbiAgICAgKiAvLyA9PiBbeyAnYSc6IDEsICdiJzogMiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbmZvcm1zKHNvdXJjZSkge1xuICAgICAgcmV0dXJuIGJhc2VDb25mb3JtcyhiYXNlQ2xvbmUoc291cmNlLCBDTE9ORV9ERUVQX0ZMQUcpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi40LjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHJldHVybiBmcm9tIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY29uc3RhbnQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gXy50aW1lcygyLCBfLmNvbnN0YW50KHsgJ2EnOiAxIH0pKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdHMpO1xuICAgICAqIC8vID0+IFt7ICdhJzogMSB9LCB7ICdhJzogMSB9XVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2cob2JqZWN0c1swXSA9PT0gb2JqZWN0c1sxXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbnN0YW50KHZhbHVlKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGB2YWx1ZWAgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYSBkZWZhdWx0IHZhbHVlIHNob3VsZCBiZSByZXR1cm5lZCBpblxuICAgICAqIGl0cyBwbGFjZS4gVGhlIGBkZWZhdWx0VmFsdWVgIGlzIHJldHVybmVkIGlmIGB2YWx1ZWAgaXMgYE5hTmAsIGBudWxsYCxcbiAgICAgKiBvciBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjE0LjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEBwYXJhbSB7Kn0gZGVmYXVsdFZhbHVlIFRoZSBkZWZhdWx0IHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWZhdWx0VG8oMSwgMTApO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIF8uZGVmYXVsdFRvKHVuZGVmaW5lZCwgMTApO1xuICAgICAqIC8vID0+IDEwXG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVmYXVsdFRvKHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgIHJldHVybiAodmFsdWUgPT0gbnVsbCB8fCB2YWx1ZSAhPT0gdmFsdWUpID8gZGVmYXVsdFZhbHVlIDogdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgcmVzdWx0IG9mIGludm9raW5nIHRoZSBnaXZlbiBmdW5jdGlvbnNcbiAgICAgKiB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgY3JlYXRlZCBmdW5jdGlvbiwgd2hlcmUgZWFjaCBzdWNjZXNzaXZlXG4gICAgICogaW52b2NhdGlvbiBpcyBzdXBwbGllZCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBwcmV2aW91cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXSl9IFtmdW5jc10gVGhlIGZ1bmN0aW9ucyB0byBpbnZva2UuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY29tcG9zaXRlIGZ1bmN0aW9uLlxuICAgICAqIEBzZWUgXy5mbG93UmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgYWRkU3F1YXJlID0gXy5mbG93KFtfLmFkZCwgc3F1YXJlXSk7XG4gICAgICogYWRkU3F1YXJlKDEsIDIpO1xuICAgICAqIC8vID0+IDlcbiAgICAgKi9cbiAgICB2YXIgZmxvdyA9IGNyZWF0ZUZsb3coKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmxvd2AgZXhjZXB0IHRoYXQgaXQgY3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXRcbiAgICAgKiBpbnZva2VzIHRoZSBnaXZlbiBmdW5jdGlvbnMgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW2Z1bmNzXSBUaGUgZnVuY3Rpb25zIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjb21wb3NpdGUgZnVuY3Rpb24uXG4gICAgICogQHNlZSBfLmZsb3dcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgYWRkU3F1YXJlID0gXy5mbG93UmlnaHQoW3NxdWFyZSwgXy5hZGRdKTtcbiAgICAgKiBhZGRTcXVhcmUoMSwgMik7XG4gICAgICogLy8gPT4gOVxuICAgICAqL1xuICAgIHZhciBmbG93UmlnaHQgPSBjcmVhdGVGbG93KHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyB0aGUgZmlyc3QgYXJndW1lbnQgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgQW55IHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIGB2YWx1ZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSB9O1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coXy5pZGVudGl0eShvYmplY3QpID09PSBvYmplY3QpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpZGVudGl0eSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggdGhlIGFyZ3VtZW50cyBvZiB0aGUgY3JlYXRlZFxuICAgICAqIGZ1bmN0aW9uLiBJZiBgZnVuY2AgaXMgYSBwcm9wZXJ0eSBuYW1lLCB0aGUgY3JlYXRlZCBmdW5jdGlvbiByZXR1cm5zIHRoZVxuICAgICAqIHByb3BlcnR5IHZhbHVlIGZvciBhIGdpdmVuIGVsZW1lbnQuIElmIGBmdW5jYCBpcyBhbiBhcnJheSBvciBvYmplY3QsIHRoZVxuICAgICAqIGNyZWF0ZWQgZnVuY3Rpb24gcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgY29udGFpbiB0aGUgZXF1aXZhbGVudFxuICAgICAqIHNvdXJjZSBwcm9wZXJ0aWVzLCBvdGhlcndpc2UgaXQgcmV0dXJucyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0geyp9IFtmdW5jPV8uaWRlbnRpdHldIFRoZSB2YWx1ZSB0byBjb252ZXJ0IHRvIGEgY2FsbGJhY2suXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBjYWxsYmFjay5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgXy5pdGVyYXRlZSh7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiB0cnVlIH0pKTtcbiAgICAgKiAvLyA9PiBbeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH1dXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maWx0ZXIodXNlcnMsIF8uaXRlcmF0ZWUoWyd1c2VyJywgJ2ZyZWQnXSkpO1xuICAgICAqIC8vID0+IFt7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ubWFwKHVzZXJzLCBfLml0ZXJhdGVlKCd1c2VyJykpO1xuICAgICAqIC8vID0+IFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gQ3JlYXRlIGN1c3RvbSBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqIF8uaXRlcmF0ZWUgPSBfLndyYXAoXy5pdGVyYXRlZSwgZnVuY3Rpb24oaXRlcmF0ZWUsIGZ1bmMpIHtcbiAgICAgKiAgIHJldHVybiAhXy5pc1JlZ0V4cChmdW5jKSA/IGl0ZXJhdGVlKGZ1bmMpIDogZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICogICAgIHJldHVybiBmdW5jLnRlc3Qoc3RyaW5nKTtcbiAgICAgKiAgIH07XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBfLmZpbHRlcihbJ2FiYycsICdkZWYnXSwgL2VmLyk7XG4gICAgICogLy8gPT4gWydkZWYnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGl0ZXJhdGVlKGZ1bmMpIHtcbiAgICAgIHJldHVybiBiYXNlSXRlcmF0ZWUodHlwZW9mIGZ1bmMgPT0gJ2Z1bmN0aW9uJyA/IGZ1bmMgOiBiYXNlQ2xvbmUoZnVuYywgQ0xPTkVfREVFUF9GTEFHKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcGVyZm9ybXMgYSBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIGEgZ2l2ZW5cbiAgICAgKiBvYmplY3QgYW5kIGBzb3VyY2VgLCByZXR1cm5pbmcgYHRydWVgIGlmIHRoZSBnaXZlbiBvYmplY3QgaGFzIGVxdWl2YWxlbnRcbiAgICAgKiBwcm9wZXJ0eSB2YWx1ZXMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGUgY3JlYXRlZCBmdW5jdGlvbiBpcyBlcXVpdmFsZW50IHRvIGBfLmlzTWF0Y2hgIHdpdGggYHNvdXJjZWBcbiAgICAgKiBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKlxuICAgICAqIFBhcnRpYWwgY29tcGFyaXNvbnMgd2lsbCBtYXRjaCBlbXB0eSBhcnJheSBhbmQgZW1wdHkgb2JqZWN0IGBzb3VyY2VgXG4gICAgICogdmFsdWVzIGFnYWluc3QgYW55IGFycmF5IG9yIG9iamVjdCB2YWx1ZSwgcmVzcGVjdGl2ZWx5LiBTZWUgYF8uaXNFcXVhbGBcbiAgICAgKiBmb3IgYSBsaXN0IG9mIHN1cHBvcnRlZCB2YWx1ZSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBNdWx0aXBsZSB2YWx1ZXMgY2FuIGJlIGNoZWNrZWQgYnkgY29tYmluaW5nIHNldmVyYWwgbWF0Y2hlcnNcbiAgICAgKiB1c2luZyBgXy5vdmVyU29tZWBcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHZhbHVlcyB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBzcGVjIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFtcbiAgICAgKiAgIHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMyB9LFxuICAgICAqICAgeyAnYSc6IDQsICdiJzogNSwgJ2MnOiA2IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maWx0ZXIob2JqZWN0cywgXy5tYXRjaGVzKHsgJ2EnOiA0LCAnYyc6IDYgfSkpO1xuICAgICAqIC8vID0+IFt7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfV1cbiAgICAgKlxuICAgICAqIC8vIENoZWNraW5nIGZvciBzZXZlcmFsIHBvc3NpYmxlIHZhbHVlc1xuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBfLm92ZXJTb21lKFtfLm1hdGNoZXMoeyAnYSc6IDEgfSksIF8ubWF0Y2hlcyh7ICdhJzogNCB9KV0pKTtcbiAgICAgKiAvLyA9PiBbeyAnYSc6IDEsICdiJzogMiwgJ2MnOiAzIH0sIHsgJ2EnOiA0LCAnYic6IDUsICdjJzogNiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hdGNoZXMoc291cmNlKSB7XG4gICAgICByZXR1cm4gYmFzZU1hdGNoZXMoYmFzZUNsb25lKHNvdXJjZSwgQ0xPTkVfREVFUF9GTEFHKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcGVyZm9ybXMgYSBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHRoZVxuICAgICAqIHZhbHVlIGF0IGBwYXRoYCBvZiBhIGdpdmVuIG9iamVjdCB0byBgc3JjVmFsdWVgLCByZXR1cm5pbmcgYHRydWVgIGlmIHRoZVxuICAgICAqIG9iamVjdCB2YWx1ZSBpcyBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogUGFydGlhbCBjb21wYXJpc29ucyB3aWxsIG1hdGNoIGVtcHR5IGFycmF5IGFuZCBlbXB0eSBvYmplY3RcbiAgICAgKiBgc3JjVmFsdWVgIHZhbHVlcyBhZ2FpbnN0IGFueSBhcnJheSBvciBvYmplY3QgdmFsdWUsIHJlc3BlY3RpdmVseS4gU2VlXG4gICAgICogYF8uaXNFcXVhbGAgZm9yIGEgbGlzdCBvZiBzdXBwb3J0ZWQgdmFsdWUgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTXVsdGlwbGUgdmFsdWVzIGNhbiBiZSBjaGVja2VkIGJ5IGNvbWJpbmluZyBzZXZlcmFsIG1hdGNoZXJzXG4gICAgICogdXNpbmcgYF8ub3ZlclNvbWVgXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHBhcmFtIHsqfSBzcmNWYWx1ZSBUaGUgdmFsdWUgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc3BlYyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbXG4gICAgICogICB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDMgfSxcbiAgICAgKiAgIHsgJ2EnOiA0LCAnYic6IDUsICdjJzogNiB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZChvYmplY3RzLCBfLm1hdGNoZXNQcm9wZXJ0eSgnYScsIDQpKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfVxuICAgICAqXG4gICAgICogLy8gQ2hlY2tpbmcgZm9yIHNldmVyYWwgcG9zc2libGUgdmFsdWVzXG4gICAgICogXy5maWx0ZXIodXNlcnMsIF8ub3ZlclNvbWUoW18ubWF0Y2hlc1Byb3BlcnR5KCdhJywgMSksIF8ubWF0Y2hlc1Byb3BlcnR5KCdhJywgNCldKSk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiAxLCAnYic6IDIsICdjJzogMyB9LCB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXRjaGVzUHJvcGVydHkocGF0aCwgc3JjVmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlTWF0Y2hlc1Byb3BlcnR5KHBhdGgsIGJhc2VDbG9uZShzcmNWYWx1ZSwgQ0xPTkVfREVFUF9GTEFHKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyB0aGUgbWV0aG9kIGF0IGBwYXRoYCBvZiBhIGdpdmVuIG9iamVjdC5cbiAgICAgKiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRvIHRoZSBpbnZva2VkIG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjcuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgdGhlIG1ldGhvZCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGludm9rZXIgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiBfLmNvbnN0YW50KDIpIH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogXy5jb25zdGFudCgxKSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5tZXRob2QoJ2EuYicpKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKlxuICAgICAqIF8ubWFwKG9iamVjdHMsIF8ubWV0aG9kKFsnYScsICdiJ10pKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKi9cbiAgICB2YXIgbWV0aG9kID0gYmFzZVJlc3QoZnVuY3Rpb24ocGF0aCwgYXJncykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICByZXR1cm4gYmFzZUludm9rZShvYmplY3QsIHBhdGgsIGFyZ3MpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5tZXRob2RgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzXG4gICAgICogdGhlIG1ldGhvZCBhdCBhIGdpdmVuIHBhdGggb2YgYG9iamVjdGAuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmVcbiAgICAgKiBwcm92aWRlZCB0byB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy43LjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgaW52b2tlciBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gXy50aW1lcygzLCBfLmNvbnN0YW50KSxcbiAgICAgKiAgICAgb2JqZWN0ID0geyAnYSc6IGFycmF5LCAnYic6IGFycmF5LCAnYyc6IGFycmF5IH07XG4gICAgICpcbiAgICAgKiBfLm1hcChbJ2FbMl0nLCAnY1swXSddLCBfLm1ldGhvZE9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqXG4gICAgICogXy5tYXAoW1snYScsICcyJ10sIFsnYycsICcwJ11dLCBfLm1ldGhvZE9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqL1xuICAgIHZhciBtZXRob2RPZiA9IGJhc2VSZXN0KGZ1bmN0aW9uKG9iamVjdCwgYXJncykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VJbnZva2Uob2JqZWN0LCBwYXRoLCBhcmdzKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGFsbCBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgZnVuY3Rpb24gcHJvcGVydGllcyBvZiBhIHNvdXJjZVxuICAgICAqIG9iamVjdCB0byB0aGUgZGVzdGluYXRpb24gb2JqZWN0LiBJZiBgb2JqZWN0YCBpcyBhIGZ1bmN0aW9uLCB0aGVuIG1ldGhvZHNcbiAgICAgKiBhcmUgYWRkZWQgdG8gaXRzIHByb3RvdHlwZSBhcyB3ZWxsLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVzZSBgXy5ydW5JbkNvbnRleHRgIHRvIGNyZWF0ZSBhIHByaXN0aW5lIGBsb2Rhc2hgIGZ1bmN0aW9uIHRvXG4gICAgICogYXZvaWQgY29uZmxpY3RzIGNhdXNlZCBieSBtb2RpZnlpbmcgdGhlIG9yaWdpbmFsLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdH0gW29iamVjdD1sb2Rhc2hdIFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5jaGFpbj10cnVlXSBTcGVjaWZ5IHdoZXRoZXIgbWl4aW5zIGFyZSBjaGFpbmFibGUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufE9iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gdm93ZWxzKHN0cmluZykge1xuICAgICAqICAgcmV0dXJuIF8uZmlsdGVyKHN0cmluZywgZnVuY3Rpb24odikge1xuICAgICAqICAgICByZXR1cm4gL1thZWlvdV0vaS50ZXN0KHYpO1xuICAgICAqICAgfSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5taXhpbih7ICd2b3dlbHMnOiB2b3dlbHMgfSk7XG4gICAgICogXy52b3dlbHMoJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiBbJ2UnXVxuICAgICAqXG4gICAgICogXygnZnJlZCcpLnZvd2VscygpLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWydlJ11cbiAgICAgKlxuICAgICAqIF8ubWl4aW4oeyAndm93ZWxzJzogdm93ZWxzIH0sIHsgJ2NoYWluJzogZmFsc2UgfSk7XG4gICAgICogXygnZnJlZCcpLnZvd2VscygpO1xuICAgICAqIC8vID0+IFsnZSddXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWl4aW4ob2JqZWN0LCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBwcm9wcyA9IGtleXMoc291cmNlKSxcbiAgICAgICAgICBtZXRob2ROYW1lcyA9IGJhc2VGdW5jdGlvbnMoc291cmNlLCBwcm9wcyk7XG5cbiAgICAgIGlmIChvcHRpb25zID09IG51bGwgJiZcbiAgICAgICAgICAhKGlzT2JqZWN0KHNvdXJjZSkgJiYgKG1ldGhvZE5hbWVzLmxlbmd0aCB8fCAhcHJvcHMubGVuZ3RoKSkpIHtcbiAgICAgICAgb3B0aW9ucyA9IHNvdXJjZTtcbiAgICAgICAgc291cmNlID0gb2JqZWN0O1xuICAgICAgICBvYmplY3QgPSB0aGlzO1xuICAgICAgICBtZXRob2ROYW1lcyA9IGJhc2VGdW5jdGlvbnMoc291cmNlLCBrZXlzKHNvdXJjZSkpO1xuICAgICAgfVxuICAgICAgdmFyIGNoYWluID0gIShpc09iamVjdChvcHRpb25zKSAmJiAnY2hhaW4nIGluIG9wdGlvbnMpIHx8ICEhb3B0aW9ucy5jaGFpbixcbiAgICAgICAgICBpc0Z1bmMgPSBpc0Z1bmN0aW9uKG9iamVjdCk7XG5cbiAgICAgIGFycmF5RWFjaChtZXRob2ROYW1lcywgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgICB2YXIgZnVuYyA9IHNvdXJjZVttZXRob2ROYW1lXTtcbiAgICAgICAgb2JqZWN0W21ldGhvZE5hbWVdID0gZnVuYztcbiAgICAgICAgaWYgKGlzRnVuYykge1xuICAgICAgICAgIG9iamVjdC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBjaGFpbkFsbCA9IHRoaXMuX19jaGFpbl9fO1xuICAgICAgICAgICAgaWYgKGNoYWluIHx8IGNoYWluQWxsKSB7XG4gICAgICAgICAgICAgIHZhciByZXN1bHQgPSBvYmplY3QodGhpcy5fX3dyYXBwZWRfXyksXG4gICAgICAgICAgICAgICAgICBhY3Rpb25zID0gcmVzdWx0Ll9fYWN0aW9uc19fID0gY29weUFycmF5KHRoaXMuX19hY3Rpb25zX18pO1xuXG4gICAgICAgICAgICAgIGFjdGlvbnMucHVzaCh7ICdmdW5jJzogZnVuYywgJ2FyZ3MnOiBhcmd1bWVudHMsICd0aGlzQXJnJzogb2JqZWN0IH0pO1xuICAgICAgICAgICAgICByZXN1bHQuX19jaGFpbl9fID0gY2hhaW5BbGw7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseShvYmplY3QsIGFycmF5UHVzaChbdGhpcy52YWx1ZSgpXSwgYXJndW1lbnRzKSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgYF9gIHZhcmlhYmxlIHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0b1xuICAgICAqIHRoZSBgbG9kYXNoYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBgbG9kYXNoYCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGxvZGFzaCA9IF8ubm9Db25mbGljdCgpO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICBpZiAocm9vdC5fID09PSB0aGlzKSB7XG4gICAgICAgIHJvb3QuXyA9IG9sZERhc2g7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50aW1lcygyLCBfLm5vb3ApO1xuICAgICAqIC8vID0+IFt1bmRlZmluZWQsIHVuZGVmaW5lZF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBub29wKCkge1xuICAgICAgLy8gTm8gb3BlcmF0aW9uIHBlcmZvcm1lZC5cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBnZXRzIHRoZSBhcmd1bWVudCBhdCBpbmRleCBgbmAuIElmIGBuYCBpcyBuZWdhdGl2ZSxcbiAgICAgKiB0aGUgbnRoIGFyZ3VtZW50IGZyb20gdGhlIGVuZCBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTBdIFRoZSBpbmRleCBvZiB0aGUgYXJndW1lbnQgdG8gcmV0dXJuLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHBhc3MtdGhydSBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLm50aEFyZygxKTtcbiAgICAgKiBmdW5jKCdhJywgJ2InLCAnYycsICdkJyk7XG4gICAgICogLy8gPT4gJ2InXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ubnRoQXJnKC0yKTtcbiAgICAgKiBmdW5jKCdhJywgJ2InLCAnYycsICdkJyk7XG4gICAgICogLy8gPT4gJ2MnXG4gICAgICovXG4gICAgZnVuY3Rpb24gbnRoQXJnKG4pIHtcbiAgICAgIG4gPSB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICByZXR1cm4gYmFzZU50aChhcmdzLCBuKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGl0ZXJhdGVlc2Agd2l0aCB0aGUgYXJndW1lbnRzIGl0IHJlY2VpdmVzXG4gICAgICogYW5kIHJldHVybnMgdGhlaXIgcmVzdWx0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXSl9IFtpdGVyYXRlZXM9W18uaWRlbnRpdHldXVxuICAgICAqICBUaGUgaXRlcmF0ZWVzIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLm92ZXIoW01hdGgubWF4LCBNYXRoLm1pbl0pO1xuICAgICAqXG4gICAgICogZnVuYygxLCAyLCAzLCA0KTtcbiAgICAgKiAvLyA9PiBbNCwgMV1cbiAgICAgKi9cbiAgICB2YXIgb3ZlciA9IGNyZWF0ZU92ZXIoYXJyYXlNYXApO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGlmICoqYWxsKiogb2YgdGhlIGBwcmVkaWNhdGVzYCByZXR1cm5cbiAgICAgKiB0cnV0aHkgd2hlbiBpbnZva2VkIHdpdGggdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEZvbGxvd2luZyBzaG9ydGhhbmRzIGFyZSBwb3NzaWJsZSBmb3IgcHJvdmlkaW5nIHByZWRpY2F0ZXMuXG4gICAgICogUGFzcyBhbiBgT2JqZWN0YCBhbmQgaXQgd2lsbCBiZSB1c2VkIGFzIGFuIHBhcmFtZXRlciBmb3IgYF8ubWF0Y2hlc2AgdG8gY3JlYXRlIHRoZSBwcmVkaWNhdGUuXG4gICAgICogUGFzcyBhbiBgQXJyYXlgIG9mIHBhcmFtZXRlcnMgZm9yIGBfLm1hdGNoZXNQcm9wZXJ0eWAgYW5kIHRoZSBwcmVkaWNhdGUgd2lsbCBiZSBjcmVhdGVkIHVzaW5nIHRoZW0uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbcHJlZGljYXRlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBwcmVkaWNhdGVzIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlckV2ZXJ5KFtCb29sZWFuLCBpc0Zpbml0ZV0pO1xuICAgICAqXG4gICAgICogZnVuYygnMScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGZ1bmMobnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIGZ1bmMoTmFOKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBvdmVyRXZlcnkgPSBjcmVhdGVPdmVyKGFycmF5RXZlcnkpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGlmICoqYW55Kiogb2YgdGhlIGBwcmVkaWNhdGVzYCByZXR1cm5cbiAgICAgKiB0cnV0aHkgd2hlbiBpbnZva2VkIHdpdGggdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEZvbGxvd2luZyBzaG9ydGhhbmRzIGFyZSBwb3NzaWJsZSBmb3IgcHJvdmlkaW5nIHByZWRpY2F0ZXMuXG4gICAgICogUGFzcyBhbiBgT2JqZWN0YCBhbmQgaXQgd2lsbCBiZSB1c2VkIGFzIGFuIHBhcmFtZXRlciBmb3IgYF8ubWF0Y2hlc2AgdG8gY3JlYXRlIHRoZSBwcmVkaWNhdGUuXG4gICAgICogUGFzcyBhbiBgQXJyYXlgIG9mIHBhcmFtZXRlcnMgZm9yIGBfLm1hdGNoZXNQcm9wZXJ0eWAgYW5kIHRoZSBwcmVkaWNhdGUgd2lsbCBiZSBjcmVhdGVkIHVzaW5nIHRoZW0uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbcHJlZGljYXRlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBwcmVkaWNhdGVzIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlclNvbWUoW0Jvb2xlYW4sIGlzRmluaXRlXSk7XG4gICAgICpcbiAgICAgKiBmdW5jKCcxJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogZnVuYyhudWxsKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBmdW5jKE5hTik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIHZhciBtYXRjaGVzRnVuYyA9IF8ub3ZlclNvbWUoW3sgJ2EnOiAxIH0sIHsgJ2EnOiAyIH1dKVxuICAgICAqIHZhciBtYXRjaGVzUHJvcGVydHlGdW5jID0gXy5vdmVyU29tZShbWydhJywgMV0sIFsnYScsIDJdXSlcbiAgICAgKi9cbiAgICB2YXIgb3ZlclNvbWUgPSBjcmVhdGVPdmVyKGFycmF5U29tZSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSB2YWx1ZSBhdCBgcGF0aGAgb2YgYSBnaXZlbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi40LjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWNjZXNzb3IgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiAyIH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogMSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5wcm9wZXJ0eSgnYS5iJykpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqXG4gICAgICogXy5tYXAoXy5zb3J0Qnkob2JqZWN0cywgXy5wcm9wZXJ0eShbJ2EnLCAnYiddKSksICdhLmInKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwcm9wZXJ0eShwYXRoKSB7XG4gICAgICByZXR1cm4gaXNLZXkocGF0aCkgPyBiYXNlUHJvcGVydHkodG9LZXkocGF0aCkpIDogYmFzZVByb3BlcnR5RGVlcChwYXRoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ucHJvcGVydHlgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zXG4gICAgICogdGhlIHZhbHVlIGF0IGEgZ2l2ZW4gcGF0aCBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFjY2Vzc29yIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMCwgMSwgMl0sXG4gICAgICogICAgIG9iamVjdCA9IHsgJ2EnOiBhcnJheSwgJ2InOiBhcnJheSwgJ2MnOiBhcnJheSB9O1xuICAgICAqXG4gICAgICogXy5tYXAoWydhWzJdJywgJ2NbMF0nXSwgXy5wcm9wZXJ0eU9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqXG4gICAgICogXy5tYXAoW1snYScsICcyJ10sIFsnYycsICcwJ11dLCBfLnByb3BlcnR5T2Yob2JqZWN0KSk7XG4gICAgICogLy8gPT4gWzIsIDBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHJvcGVydHlPZihvYmplY3QpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihwYXRoKSB7XG4gICAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IGJhc2VHZXQob2JqZWN0LCBwYXRoKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBudW1iZXJzIChwb3NpdGl2ZSBhbmQvb3IgbmVnYXRpdmUpIHByb2dyZXNzaW5nIGZyb21cbiAgICAgKiBgc3RhcnRgIHVwIHRvLCBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuIEEgc3RlcCBvZiBgLTFgIGlzIHVzZWQgaWYgYSBuZWdhdGl2ZVxuICAgICAqIGBzdGFydGAgaXMgc3BlY2lmaWVkIHdpdGhvdXQgYW4gYGVuZGAgb3IgYHN0ZXBgLiBJZiBgZW5kYCBpcyBub3Qgc3BlY2lmaWVkLFxuICAgICAqIGl0J3Mgc2V0IHRvIGBzdGFydGAgd2l0aCBgc3RhcnRgIHRoZW4gc2V0IHRvIGAwYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBKYXZhU2NyaXB0IGZvbGxvd3MgdGhlIElFRUUtNzU0IHN0YW5kYXJkIGZvciByZXNvbHZpbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCB2YWx1ZXMgd2hpY2ggY2FuIHByb2R1Y2UgdW5leHBlY3RlZCByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0ZXA9MV0gVGhlIHZhbHVlIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgYnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSByYW5nZSBvZiBudW1iZXJzLlxuICAgICAqIEBzZWUgXy5pblJhbmdlLCBfLnJhbmdlUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yYW5nZSg0KTtcbiAgICAgKiAvLyA9PiBbMCwgMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoLTQpO1xuICAgICAqIC8vID0+IFswLCAtMSwgLTIsIC0zXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgxLCA1KTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgMywgNF1cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMCwgMjAsIDUpO1xuICAgICAqIC8vID0+IFswLCA1LCAxMCwgMTVdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDAsIC00LCAtMSk7XG4gICAgICogLy8gPT4gWzAsIC0xLCAtMiwgLTNdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDEsIDQsIDApO1xuICAgICAqIC8vID0+IFsxLCAxLCAxXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIHZhciByYW5nZSA9IGNyZWF0ZVJhbmdlKCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnJhbmdlYCBleGNlcHQgdGhhdCBpdCBwb3B1bGF0ZXMgdmFsdWVzIGluXG4gICAgICogZGVzY2VuZGluZyBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGVwPTFdIFRoZSB2YWx1ZSB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZ2Ugb2YgbnVtYmVycy5cbiAgICAgKiBAc2VlIF8uaW5SYW5nZSwgXy5yYW5nZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoNCk7XG4gICAgICogLy8gPT4gWzMsIDIsIDEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoLTQpO1xuICAgICAqIC8vID0+IFstMywgLTIsIC0xLCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDEsIDUpO1xuICAgICAqIC8vID0+IFs0LCAzLCAyLCAxXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIDIwLCA1KTtcbiAgICAgKiAvLyA9PiBbMTUsIDEwLCA1LCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIC00LCAtMSk7XG4gICAgICogLy8gPT4gWy0zLCAtMiwgLTEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMSwgNCwgMCk7XG4gICAgICogLy8gPT4gWzEsIDEsIDFdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICB2YXIgcmFuZ2VSaWdodCA9IGNyZWF0ZVJhbmdlKHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBlbXB0eSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjEzLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGVtcHR5IGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXlzID0gXy50aW1lcygyLCBfLnN0dWJBcnJheSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheXMpO1xuICAgICAqIC8vID0+IFtbXSwgW11dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheXNbMF0gPT09IGFycmF5c1sxXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdHViQXJyYXkoKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTMuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50aW1lcygyLCBfLnN0dWJGYWxzZSk7XG4gICAgICogLy8gPT4gW2ZhbHNlLCBmYWxzZV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdHViRmFsc2UoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBlbXB0eSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgZW1wdHkgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IF8udGltZXMoMiwgXy5zdHViT2JqZWN0KTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdHMpO1xuICAgICAqIC8vID0+IFt7fSwge31dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3RzWzBdID09PSBvYmplY3RzWzFdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0dWJPYmplY3QoKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlbXB0eSBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGltZXMoMiwgXy5zdHViU3RyaW5nKTtcbiAgICAgKiAvLyA9PiBbJycsICcnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0dWJTdHJpbmcoKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGltZXMoMiwgXy5zdHViVHJ1ZSk7XG4gICAgICogLy8gPT4gW3RydWUsIHRydWVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3R1YlRydWUoKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBpdGVyYXRlZSBgbmAgdGltZXMsIHJldHVybmluZyBhbiBhcnJheSBvZiB0aGUgcmVzdWx0cyBvZlxuICAgICAqIGVhY2ggaW52b2NhdGlvbi4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ7IChpbmRleCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gaW52b2tlIGBpdGVyYXRlZWAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiByZXN1bHRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRpbWVzKDMsIFN0cmluZyk7XG4gICAgICogLy8gPT4gWycwJywgJzEnLCAnMiddXG4gICAgICpcbiAgICAgKiAgXy50aW1lcyg0LCBfLmNvbnN0YW50KDApKTtcbiAgICAgKiAvLyA9PiBbMCwgMCwgMCwgMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aW1lcyhuLCBpdGVyYXRlZSkge1xuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIGlmIChuIDwgMSB8fCBuID4gTUFYX1NBRkVfSU5URUdFUikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBNQVhfQVJSQVlfTEVOR1RILFxuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1pbihuLCBNQVhfQVJSQVlfTEVOR1RIKTtcblxuICAgICAgaXRlcmF0ZWUgPSBnZXRJdGVyYXRlZShpdGVyYXRlZSk7XG4gICAgICBuIC09IE1BWF9BUlJBWV9MRU5HVEg7XG5cbiAgICAgIHZhciByZXN1bHQgPSBiYXNlVGltZXMobGVuZ3RoLCBpdGVyYXRlZSk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICAgICAgaXRlcmF0ZWUoaW5kZXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvUGF0aCgnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKlxuICAgICAqIF8udG9QYXRoKCdhWzBdLmIuYycpO1xuICAgICAqIC8vID0+IFsnYScsICcwJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9QYXRoKHZhbHVlKSB7XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5TWFwKHZhbHVlLCB0b0tleSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNTeW1ib2wodmFsdWUpID8gW3ZhbHVlXSA6IGNvcHlBcnJheShzdHJpbmdUb1BhdGgodG9TdHJpbmcodmFsdWUpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGVzIGEgdW5pcXVlIElELiBJZiBgcHJlZml4YCBpcyBnaXZlbiwgdGhlIElEIGlzIGFwcGVuZGVkIHRvIGl0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ByZWZpeD0nJ10gVGhlIHZhbHVlIHRvIHByZWZpeCB0aGUgSUQgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmlxdWUgSUQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pcXVlSWQoJ2NvbnRhY3RfJyk7XG4gICAgICogLy8gPT4gJ2NvbnRhY3RfMTA0J1xuICAgICAqXG4gICAgICogXy51bmlxdWVJZCgpO1xuICAgICAqIC8vID0+ICcxMDUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcXVlSWQocHJlZml4KSB7XG4gICAgICB2YXIgaWQgPSArK2lkQ291bnRlcjtcbiAgICAgIHJldHVybiB0b1N0cmluZyhwcmVmaXgpICsgaWQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyB0d28gbnVtYmVycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjQuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGF1Z2VuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGFuIGFkZGl0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhZGRlbmQgVGhlIHNlY29uZCBudW1iZXIgaW4gYW4gYWRkaXRpb24uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdG90YWwuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uYWRkKDYsIDQpO1xuICAgICAqIC8vID0+IDEwXG4gICAgICovXG4gICAgdmFyIGFkZCA9IGNyZWF0ZU1hdGhPcGVyYXRpb24oZnVuY3Rpb24oYXVnZW5kLCBhZGRlbmQpIHtcbiAgICAgIHJldHVybiBhdWdlbmQgKyBhZGRlbmQ7XG4gICAgfSwgMCk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHVwIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIHJvdW5kIHVwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFRoZSBwcmVjaXNpb24gdG8gcm91bmQgdXAgdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCB1cCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2VpbCg0LjAwNik7XG4gICAgICogLy8gPT4gNVxuICAgICAqXG4gICAgICogXy5jZWlsKDYuMDA0LCAyKTtcbiAgICAgKiAvLyA9PiA2LjAxXG4gICAgICpcbiAgICAgKiBfLmNlaWwoNjA0MCwgLTIpO1xuICAgICAqIC8vID0+IDYxMDBcbiAgICAgKi9cbiAgICB2YXIgY2VpbCA9IGNyZWF0ZVJvdW5kKCdjZWlsJyk7XG5cbiAgICAvKipcbiAgICAgKiBEaXZpZGUgdHdvIG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkaXZpZGVuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGEgZGl2aXNpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGRpdmlzb3IgVGhlIHNlY29uZCBudW1iZXIgaW4gYSBkaXZpc2lvbi5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBxdW90aWVudC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kaXZpZGUoNiwgNCk7XG4gICAgICogLy8gPT4gMS41XG4gICAgICovXG4gICAgdmFyIGRpdmlkZSA9IGNyZWF0ZU1hdGhPcGVyYXRpb24oZnVuY3Rpb24oZGl2aWRlbmQsIGRpdmlzb3IpIHtcbiAgICAgIHJldHVybiBkaXZpZGVuZCAvIGRpdmlzb3I7XG4gICAgfSwgMSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIGRvd24gdG8gYHByZWNpc2lvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4xMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gcm91bmQgZG93bi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3ByZWNpc2lvbj0wXSBUaGUgcHJlY2lzaW9uIHRvIHJvdW5kIGRvd24gdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCBkb3duIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mbG9vcig0LjAwNik7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5mbG9vcigwLjA0NiwgMik7XG4gICAgICogLy8gPT4gMC4wNFxuICAgICAqXG4gICAgICogXy5mbG9vcig0MDYwLCAtMik7XG4gICAgICogLy8gPT4gNDAwMFxuICAgICAqL1xuICAgIHZhciBmbG9vciA9IGNyZWF0ZVJvdW5kKCdmbG9vcicpO1xuXG4gICAgLyoqXG4gICAgICogQ29tcHV0ZXMgdGhlIG1heGltdW0gdmFsdWUgb2YgYGFycmF5YC4gSWYgYGFycmF5YCBpcyBlbXB0eSBvciBmYWxzZXksXG4gICAgICogYHVuZGVmaW5lZGAgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1heGltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWF4KFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXgoW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1heChhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBpZGVudGl0eSwgYmFzZUd0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLm1heGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHRoZSB2YWx1ZSBpcyByYW5rZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWF4aW11bSB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnbic6IDEgfSwgeyAnbic6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLm1heEJ5KG9iamVjdHMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ubjsgfSk7XG4gICAgICogLy8gPT4geyAnbic6IDIgfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5tYXhCeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IHsgJ24nOiAyIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXhCeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VFeHRyZW11bShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCBiYXNlR3QpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBtZWFuIG9mIHRoZSB2YWx1ZXMgaW4gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBtZWFuLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1lYW4oWzQsIDIsIDgsIDZdKTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVhbihhcnJheSkge1xuICAgICAgcmV0dXJuIGJhc2VNZWFuKGFycmF5LCBpZGVudGl0eSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5tZWFuYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgaW4gYGFycmF5YCB0byBnZW5lcmF0ZSB0aGUgdmFsdWUgdG8gYmUgYXZlcmFnZWQuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG1lYW4uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ24nOiA0IH0sIHsgJ24nOiAyIH0sIHsgJ24nOiA4IH0sIHsgJ24nOiA2IH1dO1xuICAgICAqXG4gICAgICogXy5tZWFuQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1lYW5CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IDVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtZWFuQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gYmFzZU1lYW4oYXJyYXksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcHV0ZXMgdGhlIG1pbmltdW0gdmFsdWUgb2YgYGFycmF5YC4gSWYgYGFycmF5YCBpcyBlbXB0eSBvciBmYWxzZXksXG4gICAgICogYHVuZGVmaW5lZGAgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1pbmltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWluKFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5taW4oW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1pbihhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBpZGVudGl0eSwgYmFzZUx0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLm1pbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHRoZSB2YWx1ZSBpcyByYW5rZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWluaW11bSB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnbic6IDEgfSwgeyAnbic6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLm1pbkJ5KG9iamVjdHMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ubjsgfSk7XG4gICAgICogLy8gPT4geyAnbic6IDEgfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5taW5CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IHsgJ24nOiAxIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtaW5CeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VFeHRyZW11bShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCBiYXNlTHQpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE11bHRpcGx5IHR3byBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNy4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbXVsdGlwbGllciBUaGUgZmlyc3QgbnVtYmVyIGluIGEgbXVsdGlwbGljYXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG11bHRpcGxpY2FuZCBUaGUgc2Vjb25kIG51bWJlciBpbiBhIG11bHRpcGxpY2F0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHByb2R1Y3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubXVsdGlwbHkoNiwgNCk7XG4gICAgICogLy8gPT4gMjRcbiAgICAgKi9cbiAgICB2YXIgbXVsdGlwbHkgPSBjcmVhdGVNYXRoT3BlcmF0aW9uKGZ1bmN0aW9uKG11bHRpcGxpZXIsIG11bHRpcGxpY2FuZCkge1xuICAgICAgcmV0dXJuIG11bHRpcGxpZXIgKiBtdWx0aXBsaWNhbmQ7XG4gICAgfSwgMSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIHJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFRoZSBwcmVjaXNpb24gdG8gcm91bmQgdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNC4wMDYpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNC4wMDYsIDIpO1xuICAgICAqIC8vID0+IDQuMDFcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNDA2MCwgLTIpO1xuICAgICAqIC8vID0+IDQxMDBcbiAgICAgKi9cbiAgICB2YXIgcm91bmQgPSBjcmVhdGVSb3VuZCgncm91bmQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRyYWN0IHR3byBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWludWVuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGEgc3VidHJhY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN1YnRyYWhlbmQgVGhlIHNlY29uZCBudW1iZXIgaW4gYSBzdWJ0cmFjdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBkaWZmZXJlbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnN1YnRyYWN0KDYsIDQpO1xuICAgICAqIC8vID0+IDJcbiAgICAgKi9cbiAgICB2YXIgc3VidHJhY3QgPSBjcmVhdGVNYXRoT3BlcmF0aW9uKGZ1bmN0aW9uKG1pbnVlbmQsIHN1YnRyYWhlbmQpIHtcbiAgICAgIHJldHVybiBtaW51ZW5kIC0gc3VidHJhaGVuZDtcbiAgICB9LCAwKTtcblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBzdW0gb2YgdGhlIHZhbHVlcyBpbiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuNC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN1bS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdW0oWzQsIDIsIDgsIDZdKTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN1bShhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVN1bShhcnJheSwgaWRlbnRpdHkpXG4gICAgICAgIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnN1bWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIHZhbHVlIHRvIGJlIHN1bW1lZC5cbiAgICAgKiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3VtLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICduJzogNCB9LCB7ICduJzogMiB9LCB7ICduJzogOCB9LCB7ICduJzogNiB9XTtcbiAgICAgKlxuICAgICAqIF8uc3VtQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zdW1CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IDIwXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3VtQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlU3VtKGFycmF5LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpXG4gICAgICAgIDogMDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0aGF0IHJldHVybiB3cmFwcGVkIHZhbHVlcyBpbiBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgbG9kYXNoLmFmdGVyID0gYWZ0ZXI7XG4gICAgbG9kYXNoLmFyeSA9IGFyeTtcbiAgICBsb2Rhc2guYXNzaWduID0gYXNzaWduO1xuICAgIGxvZGFzaC5hc3NpZ25JbiA9IGFzc2lnbkluO1xuICAgIGxvZGFzaC5hc3NpZ25JbldpdGggPSBhc3NpZ25JbldpdGg7XG4gICAgbG9kYXNoLmFzc2lnbldpdGggPSBhc3NpZ25XaXRoO1xuICAgIGxvZGFzaC5hdCA9IGF0O1xuICAgIGxvZGFzaC5iZWZvcmUgPSBiZWZvcmU7XG4gICAgbG9kYXNoLmJpbmQgPSBiaW5kO1xuICAgIGxvZGFzaC5iaW5kQWxsID0gYmluZEFsbDtcbiAgICBsb2Rhc2guYmluZEtleSA9IGJpbmRLZXk7XG4gICAgbG9kYXNoLmNhc3RBcnJheSA9IGNhc3RBcnJheTtcbiAgICBsb2Rhc2guY2hhaW4gPSBjaGFpbjtcbiAgICBsb2Rhc2guY2h1bmsgPSBjaHVuaztcbiAgICBsb2Rhc2guY29tcGFjdCA9IGNvbXBhY3Q7XG4gICAgbG9kYXNoLmNvbmNhdCA9IGNvbmNhdDtcbiAgICBsb2Rhc2guY29uZCA9IGNvbmQ7XG4gICAgbG9kYXNoLmNvbmZvcm1zID0gY29uZm9ybXM7XG4gICAgbG9kYXNoLmNvbnN0YW50ID0gY29uc3RhbnQ7XG4gICAgbG9kYXNoLmNvdW50QnkgPSBjb3VudEJ5O1xuICAgIGxvZGFzaC5jcmVhdGUgPSBjcmVhdGU7XG4gICAgbG9kYXNoLmN1cnJ5ID0gY3Vycnk7XG4gICAgbG9kYXNoLmN1cnJ5UmlnaHQgPSBjdXJyeVJpZ2h0O1xuICAgIGxvZGFzaC5kZWJvdW5jZSA9IGRlYm91bmNlO1xuICAgIGxvZGFzaC5kZWZhdWx0cyA9IGRlZmF1bHRzO1xuICAgIGxvZGFzaC5kZWZhdWx0c0RlZXAgPSBkZWZhdWx0c0RlZXA7XG4gICAgbG9kYXNoLmRlZmVyID0gZGVmZXI7XG4gICAgbG9kYXNoLmRlbGF5ID0gZGVsYXk7XG4gICAgbG9kYXNoLmRpZmZlcmVuY2UgPSBkaWZmZXJlbmNlO1xuICAgIGxvZGFzaC5kaWZmZXJlbmNlQnkgPSBkaWZmZXJlbmNlQnk7XG4gICAgbG9kYXNoLmRpZmZlcmVuY2VXaXRoID0gZGlmZmVyZW5jZVdpdGg7XG4gICAgbG9kYXNoLmRyb3AgPSBkcm9wO1xuICAgIGxvZGFzaC5kcm9wUmlnaHQgPSBkcm9wUmlnaHQ7XG4gICAgbG9kYXNoLmRyb3BSaWdodFdoaWxlID0gZHJvcFJpZ2h0V2hpbGU7XG4gICAgbG9kYXNoLmRyb3BXaGlsZSA9IGRyb3BXaGlsZTtcbiAgICBsb2Rhc2guZmlsbCA9IGZpbGw7XG4gICAgbG9kYXNoLmZpbHRlciA9IGZpbHRlcjtcbiAgICBsb2Rhc2guZmxhdE1hcCA9IGZsYXRNYXA7XG4gICAgbG9kYXNoLmZsYXRNYXBEZWVwID0gZmxhdE1hcERlZXA7XG4gICAgbG9kYXNoLmZsYXRNYXBEZXB0aCA9IGZsYXRNYXBEZXB0aDtcbiAgICBsb2Rhc2guZmxhdHRlbiA9IGZsYXR0ZW47XG4gICAgbG9kYXNoLmZsYXR0ZW5EZWVwID0gZmxhdHRlbkRlZXA7XG4gICAgbG9kYXNoLmZsYXR0ZW5EZXB0aCA9IGZsYXR0ZW5EZXB0aDtcbiAgICBsb2Rhc2guZmxpcCA9IGZsaXA7XG4gICAgbG9kYXNoLmZsb3cgPSBmbG93O1xuICAgIGxvZGFzaC5mbG93UmlnaHQgPSBmbG93UmlnaHQ7XG4gICAgbG9kYXNoLmZyb21QYWlycyA9IGZyb21QYWlycztcbiAgICBsb2Rhc2guZnVuY3Rpb25zID0gZnVuY3Rpb25zO1xuICAgIGxvZGFzaC5mdW5jdGlvbnNJbiA9IGZ1bmN0aW9uc0luO1xuICAgIGxvZGFzaC5ncm91cEJ5ID0gZ3JvdXBCeTtcbiAgICBsb2Rhc2guaW5pdGlhbCA9IGluaXRpYWw7XG4gICAgbG9kYXNoLmludGVyc2VjdGlvbiA9IGludGVyc2VjdGlvbjtcbiAgICBsb2Rhc2guaW50ZXJzZWN0aW9uQnkgPSBpbnRlcnNlY3Rpb25CeTtcbiAgICBsb2Rhc2guaW50ZXJzZWN0aW9uV2l0aCA9IGludGVyc2VjdGlvbldpdGg7XG4gICAgbG9kYXNoLmludmVydCA9IGludmVydDtcbiAgICBsb2Rhc2guaW52ZXJ0QnkgPSBpbnZlcnRCeTtcbiAgICBsb2Rhc2guaW52b2tlTWFwID0gaW52b2tlTWFwO1xuICAgIGxvZGFzaC5pdGVyYXRlZSA9IGl0ZXJhdGVlO1xuICAgIGxvZGFzaC5rZXlCeSA9IGtleUJ5O1xuICAgIGxvZGFzaC5rZXlzID0ga2V5cztcbiAgICBsb2Rhc2gua2V5c0luID0ga2V5c0luO1xuICAgIGxvZGFzaC5tYXAgPSBtYXA7XG4gICAgbG9kYXNoLm1hcEtleXMgPSBtYXBLZXlzO1xuICAgIGxvZGFzaC5tYXBWYWx1ZXMgPSBtYXBWYWx1ZXM7XG4gICAgbG9kYXNoLm1hdGNoZXMgPSBtYXRjaGVzO1xuICAgIGxvZGFzaC5tYXRjaGVzUHJvcGVydHkgPSBtYXRjaGVzUHJvcGVydHk7XG4gICAgbG9kYXNoLm1lbW9pemUgPSBtZW1vaXplO1xuICAgIGxvZGFzaC5tZXJnZSA9IG1lcmdlO1xuICAgIGxvZGFzaC5tZXJnZVdpdGggPSBtZXJnZVdpdGg7XG4gICAgbG9kYXNoLm1ldGhvZCA9IG1ldGhvZDtcbiAgICBsb2Rhc2gubWV0aG9kT2YgPSBtZXRob2RPZjtcbiAgICBsb2Rhc2gubWl4aW4gPSBtaXhpbjtcbiAgICBsb2Rhc2gubmVnYXRlID0gbmVnYXRlO1xuICAgIGxvZGFzaC5udGhBcmcgPSBudGhBcmc7XG4gICAgbG9kYXNoLm9taXQgPSBvbWl0O1xuICAgIGxvZGFzaC5vbWl0QnkgPSBvbWl0Qnk7XG4gICAgbG9kYXNoLm9uY2UgPSBvbmNlO1xuICAgIGxvZGFzaC5vcmRlckJ5ID0gb3JkZXJCeTtcbiAgICBsb2Rhc2gub3ZlciA9IG92ZXI7XG4gICAgbG9kYXNoLm92ZXJBcmdzID0gb3ZlckFyZ3M7XG4gICAgbG9kYXNoLm92ZXJFdmVyeSA9IG92ZXJFdmVyeTtcbiAgICBsb2Rhc2gub3ZlclNvbWUgPSBvdmVyU29tZTtcbiAgICBsb2Rhc2gucGFydGlhbCA9IHBhcnRpYWw7XG4gICAgbG9kYXNoLnBhcnRpYWxSaWdodCA9IHBhcnRpYWxSaWdodDtcbiAgICBsb2Rhc2gucGFydGl0aW9uID0gcGFydGl0aW9uO1xuICAgIGxvZGFzaC5waWNrID0gcGljaztcbiAgICBsb2Rhc2gucGlja0J5ID0gcGlja0J5O1xuICAgIGxvZGFzaC5wcm9wZXJ0eSA9IHByb3BlcnR5O1xuICAgIGxvZGFzaC5wcm9wZXJ0eU9mID0gcHJvcGVydHlPZjtcbiAgICBsb2Rhc2gucHVsbCA9IHB1bGw7XG4gICAgbG9kYXNoLnB1bGxBbGwgPSBwdWxsQWxsO1xuICAgIGxvZGFzaC5wdWxsQWxsQnkgPSBwdWxsQWxsQnk7XG4gICAgbG9kYXNoLnB1bGxBbGxXaXRoID0gcHVsbEFsbFdpdGg7XG4gICAgbG9kYXNoLnB1bGxBdCA9IHB1bGxBdDtcbiAgICBsb2Rhc2gucmFuZ2UgPSByYW5nZTtcbiAgICBsb2Rhc2gucmFuZ2VSaWdodCA9IHJhbmdlUmlnaHQ7XG4gICAgbG9kYXNoLnJlYXJnID0gcmVhcmc7XG4gICAgbG9kYXNoLnJlamVjdCA9IHJlamVjdDtcbiAgICBsb2Rhc2gucmVtb3ZlID0gcmVtb3ZlO1xuICAgIGxvZGFzaC5yZXN0ID0gcmVzdDtcbiAgICBsb2Rhc2gucmV2ZXJzZSA9IHJldmVyc2U7XG4gICAgbG9kYXNoLnNhbXBsZVNpemUgPSBzYW1wbGVTaXplO1xuICAgIGxvZGFzaC5zZXQgPSBzZXQ7XG4gICAgbG9kYXNoLnNldFdpdGggPSBzZXRXaXRoO1xuICAgIGxvZGFzaC5zaHVmZmxlID0gc2h1ZmZsZTtcbiAgICBsb2Rhc2guc2xpY2UgPSBzbGljZTtcbiAgICBsb2Rhc2guc29ydEJ5ID0gc29ydEJ5O1xuICAgIGxvZGFzaC5zb3J0ZWRVbmlxID0gc29ydGVkVW5pcTtcbiAgICBsb2Rhc2guc29ydGVkVW5pcUJ5ID0gc29ydGVkVW5pcUJ5O1xuICAgIGxvZGFzaC5zcGxpdCA9IHNwbGl0O1xuICAgIGxvZGFzaC5zcHJlYWQgPSBzcHJlYWQ7XG4gICAgbG9kYXNoLnRhaWwgPSB0YWlsO1xuICAgIGxvZGFzaC50YWtlID0gdGFrZTtcbiAgICBsb2Rhc2gudGFrZVJpZ2h0ID0gdGFrZVJpZ2h0O1xuICAgIGxvZGFzaC50YWtlUmlnaHRXaGlsZSA9IHRha2VSaWdodFdoaWxlO1xuICAgIGxvZGFzaC50YWtlV2hpbGUgPSB0YWtlV2hpbGU7XG4gICAgbG9kYXNoLnRhcCA9IHRhcDtcbiAgICBsb2Rhc2gudGhyb3R0bGUgPSB0aHJvdHRsZTtcbiAgICBsb2Rhc2gudGhydSA9IHRocnU7XG4gICAgbG9kYXNoLnRvQXJyYXkgPSB0b0FycmF5O1xuICAgIGxvZGFzaC50b1BhaXJzID0gdG9QYWlycztcbiAgICBsb2Rhc2gudG9QYWlyc0luID0gdG9QYWlyc0luO1xuICAgIGxvZGFzaC50b1BhdGggPSB0b1BhdGg7XG4gICAgbG9kYXNoLnRvUGxhaW5PYmplY3QgPSB0b1BsYWluT2JqZWN0O1xuICAgIGxvZGFzaC50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG4gICAgbG9kYXNoLnVuYXJ5ID0gdW5hcnk7XG4gICAgbG9kYXNoLnVuaW9uID0gdW5pb247XG4gICAgbG9kYXNoLnVuaW9uQnkgPSB1bmlvbkJ5O1xuICAgIGxvZGFzaC51bmlvbldpdGggPSB1bmlvbldpdGg7XG4gICAgbG9kYXNoLnVuaXEgPSB1bmlxO1xuICAgIGxvZGFzaC51bmlxQnkgPSB1bmlxQnk7XG4gICAgbG9kYXNoLnVuaXFXaXRoID0gdW5pcVdpdGg7XG4gICAgbG9kYXNoLnVuc2V0ID0gdW5zZXQ7XG4gICAgbG9kYXNoLnVuemlwID0gdW56aXA7XG4gICAgbG9kYXNoLnVuemlwV2l0aCA9IHVuemlwV2l0aDtcbiAgICBsb2Rhc2gudXBkYXRlID0gdXBkYXRlO1xuICAgIGxvZGFzaC51cGRhdGVXaXRoID0gdXBkYXRlV2l0aDtcbiAgICBsb2Rhc2gudmFsdWVzID0gdmFsdWVzO1xuICAgIGxvZGFzaC52YWx1ZXNJbiA9IHZhbHVlc0luO1xuICAgIGxvZGFzaC53aXRob3V0ID0gd2l0aG91dDtcbiAgICBsb2Rhc2gud29yZHMgPSB3b3JkcztcbiAgICBsb2Rhc2gud3JhcCA9IHdyYXA7XG4gICAgbG9kYXNoLnhvciA9IHhvcjtcbiAgICBsb2Rhc2gueG9yQnkgPSB4b3JCeTtcbiAgICBsb2Rhc2gueG9yV2l0aCA9IHhvcldpdGg7XG4gICAgbG9kYXNoLnppcCA9IHppcDtcbiAgICBsb2Rhc2guemlwT2JqZWN0ID0gemlwT2JqZWN0O1xuICAgIGxvZGFzaC56aXBPYmplY3REZWVwID0gemlwT2JqZWN0RGVlcDtcbiAgICBsb2Rhc2guemlwV2l0aCA9IHppcFdpdGg7XG5cbiAgICAvLyBBZGQgYWxpYXNlcy5cbiAgICBsb2Rhc2guZW50cmllcyA9IHRvUGFpcnM7XG4gICAgbG9kYXNoLmVudHJpZXNJbiA9IHRvUGFpcnNJbjtcbiAgICBsb2Rhc2guZXh0ZW5kID0gYXNzaWduSW47XG4gICAgbG9kYXNoLmV4dGVuZFdpdGggPSBhc3NpZ25JbldpdGg7XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgbG9kYXNoLnByb3RvdHlwZWAuXG4gICAgbWl4aW4obG9kYXNoLCBsb2Rhc2gpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQWRkIG1ldGhvZHMgdGhhdCByZXR1cm4gdW53cmFwcGVkIHZhbHVlcyBpbiBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgbG9kYXNoLmFkZCA9IGFkZDtcbiAgICBsb2Rhc2guYXR0ZW1wdCA9IGF0dGVtcHQ7XG4gICAgbG9kYXNoLmNhbWVsQ2FzZSA9IGNhbWVsQ2FzZTtcbiAgICBsb2Rhc2guY2FwaXRhbGl6ZSA9IGNhcGl0YWxpemU7XG4gICAgbG9kYXNoLmNlaWwgPSBjZWlsO1xuICAgIGxvZGFzaC5jbGFtcCA9IGNsYW1wO1xuICAgIGxvZGFzaC5jbG9uZSA9IGNsb25lO1xuICAgIGxvZGFzaC5jbG9uZURlZXAgPSBjbG9uZURlZXA7XG4gICAgbG9kYXNoLmNsb25lRGVlcFdpdGggPSBjbG9uZURlZXBXaXRoO1xuICAgIGxvZGFzaC5jbG9uZVdpdGggPSBjbG9uZVdpdGg7XG4gICAgbG9kYXNoLmNvbmZvcm1zVG8gPSBjb25mb3Jtc1RvO1xuICAgIGxvZGFzaC5kZWJ1cnIgPSBkZWJ1cnI7XG4gICAgbG9kYXNoLmRlZmF1bHRUbyA9IGRlZmF1bHRUbztcbiAgICBsb2Rhc2guZGl2aWRlID0gZGl2aWRlO1xuICAgIGxvZGFzaC5lbmRzV2l0aCA9IGVuZHNXaXRoO1xuICAgIGxvZGFzaC5lcSA9IGVxO1xuICAgIGxvZGFzaC5lc2NhcGUgPSBlc2NhcGU7XG4gICAgbG9kYXNoLmVzY2FwZVJlZ0V4cCA9IGVzY2FwZVJlZ0V4cDtcbiAgICBsb2Rhc2guZXZlcnkgPSBldmVyeTtcbiAgICBsb2Rhc2guZmluZCA9IGZpbmQ7XG4gICAgbG9kYXNoLmZpbmRJbmRleCA9IGZpbmRJbmRleDtcbiAgICBsb2Rhc2guZmluZEtleSA9IGZpbmRLZXk7XG4gICAgbG9kYXNoLmZpbmRMYXN0ID0gZmluZExhc3Q7XG4gICAgbG9kYXNoLmZpbmRMYXN0SW5kZXggPSBmaW5kTGFzdEluZGV4O1xuICAgIGxvZGFzaC5maW5kTGFzdEtleSA9IGZpbmRMYXN0S2V5O1xuICAgIGxvZGFzaC5mbG9vciA9IGZsb29yO1xuICAgIGxvZGFzaC5mb3JFYWNoID0gZm9yRWFjaDtcbiAgICBsb2Rhc2guZm9yRWFjaFJpZ2h0ID0gZm9yRWFjaFJpZ2h0O1xuICAgIGxvZGFzaC5mb3JJbiA9IGZvckluO1xuICAgIGxvZGFzaC5mb3JJblJpZ2h0ID0gZm9ySW5SaWdodDtcbiAgICBsb2Rhc2guZm9yT3duID0gZm9yT3duO1xuICAgIGxvZGFzaC5mb3JPd25SaWdodCA9IGZvck93blJpZ2h0O1xuICAgIGxvZGFzaC5nZXQgPSBnZXQ7XG4gICAgbG9kYXNoLmd0ID0gZ3Q7XG4gICAgbG9kYXNoLmd0ZSA9IGd0ZTtcbiAgICBsb2Rhc2guaGFzID0gaGFzO1xuICAgIGxvZGFzaC5oYXNJbiA9IGhhc0luO1xuICAgIGxvZGFzaC5oZWFkID0gaGVhZDtcbiAgICBsb2Rhc2guaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICBsb2Rhc2guaW5jbHVkZXMgPSBpbmNsdWRlcztcbiAgICBsb2Rhc2guaW5kZXhPZiA9IGluZGV4T2Y7XG4gICAgbG9kYXNoLmluUmFuZ2UgPSBpblJhbmdlO1xuICAgIGxvZGFzaC5pbnZva2UgPSBpbnZva2U7XG4gICAgbG9kYXNoLmlzQXJndW1lbnRzID0gaXNBcmd1bWVudHM7XG4gICAgbG9kYXNoLmlzQXJyYXkgPSBpc0FycmF5O1xuICAgIGxvZGFzaC5pc0FycmF5QnVmZmVyID0gaXNBcnJheUJ1ZmZlcjtcbiAgICBsb2Rhc2guaXNBcnJheUxpa2UgPSBpc0FycmF5TGlrZTtcbiAgICBsb2Rhc2guaXNBcnJheUxpa2VPYmplY3QgPSBpc0FycmF5TGlrZU9iamVjdDtcbiAgICBsb2Rhc2guaXNCb29sZWFuID0gaXNCb29sZWFuO1xuICAgIGxvZGFzaC5pc0J1ZmZlciA9IGlzQnVmZmVyO1xuICAgIGxvZGFzaC5pc0RhdGUgPSBpc0RhdGU7XG4gICAgbG9kYXNoLmlzRWxlbWVudCA9IGlzRWxlbWVudDtcbiAgICBsb2Rhc2guaXNFbXB0eSA9IGlzRW1wdHk7XG4gICAgbG9kYXNoLmlzRXF1YWwgPSBpc0VxdWFsO1xuICAgIGxvZGFzaC5pc0VxdWFsV2l0aCA9IGlzRXF1YWxXaXRoO1xuICAgIGxvZGFzaC5pc0Vycm9yID0gaXNFcnJvcjtcbiAgICBsb2Rhc2guaXNGaW5pdGUgPSBpc0Zpbml0ZTtcbiAgICBsb2Rhc2guaXNGdW5jdGlvbiA9IGlzRnVuY3Rpb247XG4gICAgbG9kYXNoLmlzSW50ZWdlciA9IGlzSW50ZWdlcjtcbiAgICBsb2Rhc2guaXNMZW5ndGggPSBpc0xlbmd0aDtcbiAgICBsb2Rhc2guaXNNYXAgPSBpc01hcDtcbiAgICBsb2Rhc2guaXNNYXRjaCA9IGlzTWF0Y2g7XG4gICAgbG9kYXNoLmlzTWF0Y2hXaXRoID0gaXNNYXRjaFdpdGg7XG4gICAgbG9kYXNoLmlzTmFOID0gaXNOYU47XG4gICAgbG9kYXNoLmlzTmF0aXZlID0gaXNOYXRpdmU7XG4gICAgbG9kYXNoLmlzTmlsID0gaXNOaWw7XG4gICAgbG9kYXNoLmlzTnVsbCA9IGlzTnVsbDtcbiAgICBsb2Rhc2guaXNOdW1iZXIgPSBpc051bWJlcjtcbiAgICBsb2Rhc2guaXNPYmplY3QgPSBpc09iamVjdDtcbiAgICBsb2Rhc2guaXNPYmplY3RMaWtlID0gaXNPYmplY3RMaWtlO1xuICAgIGxvZGFzaC5pc1BsYWluT2JqZWN0ID0gaXNQbGFpbk9iamVjdDtcbiAgICBsb2Rhc2guaXNSZWdFeHAgPSBpc1JlZ0V4cDtcbiAgICBsb2Rhc2guaXNTYWZlSW50ZWdlciA9IGlzU2FmZUludGVnZXI7XG4gICAgbG9kYXNoLmlzU2V0ID0gaXNTZXQ7XG4gICAgbG9kYXNoLmlzU3RyaW5nID0gaXNTdHJpbmc7XG4gICAgbG9kYXNoLmlzU3ltYm9sID0gaXNTeW1ib2w7XG4gICAgbG9kYXNoLmlzVHlwZWRBcnJheSA9IGlzVHlwZWRBcnJheTtcbiAgICBsb2Rhc2guaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcbiAgICBsb2Rhc2guaXNXZWFrTWFwID0gaXNXZWFrTWFwO1xuICAgIGxvZGFzaC5pc1dlYWtTZXQgPSBpc1dlYWtTZXQ7XG4gICAgbG9kYXNoLmpvaW4gPSBqb2luO1xuICAgIGxvZGFzaC5rZWJhYkNhc2UgPSBrZWJhYkNhc2U7XG4gICAgbG9kYXNoLmxhc3QgPSBsYXN0O1xuICAgIGxvZGFzaC5sYXN0SW5kZXhPZiA9IGxhc3RJbmRleE9mO1xuICAgIGxvZGFzaC5sb3dlckNhc2UgPSBsb3dlckNhc2U7XG4gICAgbG9kYXNoLmxvd2VyRmlyc3QgPSBsb3dlckZpcnN0O1xuICAgIGxvZGFzaC5sdCA9IGx0O1xuICAgIGxvZGFzaC5sdGUgPSBsdGU7XG4gICAgbG9kYXNoLm1heCA9IG1heDtcbiAgICBsb2Rhc2gubWF4QnkgPSBtYXhCeTtcbiAgICBsb2Rhc2gubWVhbiA9IG1lYW47XG4gICAgbG9kYXNoLm1lYW5CeSA9IG1lYW5CeTtcbiAgICBsb2Rhc2gubWluID0gbWluO1xuICAgIGxvZGFzaC5taW5CeSA9IG1pbkJ5O1xuICAgIGxvZGFzaC5zdHViQXJyYXkgPSBzdHViQXJyYXk7XG4gICAgbG9kYXNoLnN0dWJGYWxzZSA9IHN0dWJGYWxzZTtcbiAgICBsb2Rhc2guc3R1Yk9iamVjdCA9IHN0dWJPYmplY3Q7XG4gICAgbG9kYXNoLnN0dWJTdHJpbmcgPSBzdHViU3RyaW5nO1xuICAgIGxvZGFzaC5zdHViVHJ1ZSA9IHN0dWJUcnVlO1xuICAgIGxvZGFzaC5tdWx0aXBseSA9IG11bHRpcGx5O1xuICAgIGxvZGFzaC5udGggPSBudGg7XG4gICAgbG9kYXNoLm5vQ29uZmxpY3QgPSBub0NvbmZsaWN0O1xuICAgIGxvZGFzaC5ub29wID0gbm9vcDtcbiAgICBsb2Rhc2gubm93ID0gbm93O1xuICAgIGxvZGFzaC5wYWQgPSBwYWQ7XG4gICAgbG9kYXNoLnBhZEVuZCA9IHBhZEVuZDtcbiAgICBsb2Rhc2gucGFkU3RhcnQgPSBwYWRTdGFydDtcbiAgICBsb2Rhc2gucGFyc2VJbnQgPSBwYXJzZUludDtcbiAgICBsb2Rhc2gucmFuZG9tID0gcmFuZG9tO1xuICAgIGxvZGFzaC5yZWR1Y2UgPSByZWR1Y2U7XG4gICAgbG9kYXNoLnJlZHVjZVJpZ2h0ID0gcmVkdWNlUmlnaHQ7XG4gICAgbG9kYXNoLnJlcGVhdCA9IHJlcGVhdDtcbiAgICBsb2Rhc2gucmVwbGFjZSA9IHJlcGxhY2U7XG4gICAgbG9kYXNoLnJlc3VsdCA9IHJlc3VsdDtcbiAgICBsb2Rhc2gucm91bmQgPSByb3VuZDtcbiAgICBsb2Rhc2gucnVuSW5Db250ZXh0ID0gcnVuSW5Db250ZXh0O1xuICAgIGxvZGFzaC5zYW1wbGUgPSBzYW1wbGU7XG4gICAgbG9kYXNoLnNpemUgPSBzaXplO1xuICAgIGxvZGFzaC5zbmFrZUNhc2UgPSBzbmFrZUNhc2U7XG4gICAgbG9kYXNoLnNvbWUgPSBzb21lO1xuICAgIGxvZGFzaC5zb3J0ZWRJbmRleCA9IHNvcnRlZEluZGV4O1xuICAgIGxvZGFzaC5zb3J0ZWRJbmRleEJ5ID0gc29ydGVkSW5kZXhCeTtcbiAgICBsb2Rhc2guc29ydGVkSW5kZXhPZiA9IHNvcnRlZEluZGV4T2Y7XG4gICAgbG9kYXNoLnNvcnRlZExhc3RJbmRleCA9IHNvcnRlZExhc3RJbmRleDtcbiAgICBsb2Rhc2guc29ydGVkTGFzdEluZGV4QnkgPSBzb3J0ZWRMYXN0SW5kZXhCeTtcbiAgICBsb2Rhc2guc29ydGVkTGFzdEluZGV4T2YgPSBzb3J0ZWRMYXN0SW5kZXhPZjtcbiAgICBsb2Rhc2guc3RhcnRDYXNlID0gc3RhcnRDYXNlO1xuICAgIGxvZGFzaC5zdGFydHNXaXRoID0gc3RhcnRzV2l0aDtcbiAgICBsb2Rhc2guc3VidHJhY3QgPSBzdWJ0cmFjdDtcbiAgICBsb2Rhc2guc3VtID0gc3VtO1xuICAgIGxvZGFzaC5zdW1CeSA9IHN1bUJ5O1xuICAgIGxvZGFzaC50ZW1wbGF0ZSA9IHRlbXBsYXRlO1xuICAgIGxvZGFzaC50aW1lcyA9IHRpbWVzO1xuICAgIGxvZGFzaC50b0Zpbml0ZSA9IHRvRmluaXRlO1xuICAgIGxvZGFzaC50b0ludGVnZXIgPSB0b0ludGVnZXI7XG4gICAgbG9kYXNoLnRvTGVuZ3RoID0gdG9MZW5ndGg7XG4gICAgbG9kYXNoLnRvTG93ZXIgPSB0b0xvd2VyO1xuICAgIGxvZGFzaC50b051bWJlciA9IHRvTnVtYmVyO1xuICAgIGxvZGFzaC50b1NhZmVJbnRlZ2VyID0gdG9TYWZlSW50ZWdlcjtcbiAgICBsb2Rhc2gudG9TdHJpbmcgPSB0b1N0cmluZztcbiAgICBsb2Rhc2gudG9VcHBlciA9IHRvVXBwZXI7XG4gICAgbG9kYXNoLnRyaW0gPSB0cmltO1xuICAgIGxvZGFzaC50cmltRW5kID0gdHJpbUVuZDtcbiAgICBsb2Rhc2gudHJpbVN0YXJ0ID0gdHJpbVN0YXJ0O1xuICAgIGxvZGFzaC50cnVuY2F0ZSA9IHRydW5jYXRlO1xuICAgIGxvZGFzaC51bmVzY2FwZSA9IHVuZXNjYXBlO1xuICAgIGxvZGFzaC51bmlxdWVJZCA9IHVuaXF1ZUlkO1xuICAgIGxvZGFzaC51cHBlckNhc2UgPSB1cHBlckNhc2U7XG4gICAgbG9kYXNoLnVwcGVyRmlyc3QgPSB1cHBlckZpcnN0O1xuXG4gICAgLy8gQWRkIGFsaWFzZXMuXG4gICAgbG9kYXNoLmVhY2ggPSBmb3JFYWNoO1xuICAgIGxvZGFzaC5lYWNoUmlnaHQgPSBmb3JFYWNoUmlnaHQ7XG4gICAgbG9kYXNoLmZpcnN0ID0gaGVhZDtcblxuICAgIG1peGluKGxvZGFzaCwgKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHNvdXJjZSA9IHt9O1xuICAgICAgYmFzZUZvck93bihsb2Rhc2gsIGZ1bmN0aW9uKGZ1bmMsIG1ldGhvZE5hbWUpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKGxvZGFzaC5wcm90b3R5cGUsIG1ldGhvZE5hbWUpKSB7XG4gICAgICAgICAgc291cmNlW21ldGhvZE5hbWVdID0gZnVuYztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gc291cmNlO1xuICAgIH0oKSksIHsgJ2NoYWluJzogZmFsc2UgfSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgc2VtYW50aWMgdmVyc2lvbiBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIGxvZGFzaC5WRVJTSU9OID0gVkVSU0lPTjtcblxuICAgIC8vIEFzc2lnbiBkZWZhdWx0IHBsYWNlaG9sZGVycy5cbiAgICBhcnJheUVhY2goWydiaW5kJywgJ2JpbmRLZXknLCAnY3VycnknLCAnY3VycnlSaWdodCcsICdwYXJ0aWFsJywgJ3BhcnRpYWxSaWdodCddLCBmdW5jdGlvbihtZXRob2ROYW1lKSB7XG4gICAgICBsb2Rhc2hbbWV0aG9kTmFtZV0ucGxhY2Vob2xkZXIgPSBsb2Rhc2g7XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5kcm9wYCBhbmQgYF8udGFrZWAgdmFyaWFudHMuXG4gICAgYXJyYXlFYWNoKFsnZHJvcCcsICd0YWtlJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbihuKSB7XG4gICAgICAgIG4gPSBuID09PSB1bmRlZmluZWQgPyAxIDogbmF0aXZlTWF4KHRvSW50ZWdlcihuKSwgMCk7XG5cbiAgICAgICAgdmFyIHJlc3VsdCA9ICh0aGlzLl9fZmlsdGVyZWRfXyAmJiAhaW5kZXgpXG4gICAgICAgICAgPyBuZXcgTGF6eVdyYXBwZXIodGhpcylcbiAgICAgICAgICA6IHRoaXMuY2xvbmUoKTtcblxuICAgICAgICBpZiAocmVzdWx0Ll9fZmlsdGVyZWRfXykge1xuICAgICAgICAgIHJlc3VsdC5fX3Rha2VDb3VudF9fID0gbmF0aXZlTWluKG4sIHJlc3VsdC5fX3Rha2VDb3VudF9fKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHQuX192aWV3c19fLnB1c2goe1xuICAgICAgICAgICAgJ3NpemUnOiBuYXRpdmVNaW4obiwgTUFYX0FSUkFZX0xFTkdUSCksXG4gICAgICAgICAgICAndHlwZSc6IG1ldGhvZE5hbWUgKyAocmVzdWx0Ll9fZGlyX18gPCAwID8gJ1JpZ2h0JyA6ICcnKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZSArICdSaWdodCddID0gZnVuY3Rpb24obikge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXZlcnNlKClbbWV0aG9kTmFtZV0obikucmV2ZXJzZSgpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgdGhhdCBhY2NlcHQgYW4gYGl0ZXJhdGVlYCB2YWx1ZS5cbiAgICBhcnJheUVhY2goWydmaWx0ZXInLCAnbWFwJywgJ3Rha2VXaGlsZSddLCBmdW5jdGlvbihtZXRob2ROYW1lLCBpbmRleCkge1xuICAgICAgdmFyIHR5cGUgPSBpbmRleCArIDEsXG4gICAgICAgICAgaXNGaWx0ZXIgPSB0eXBlID09IExBWllfRklMVEVSX0ZMQUcgfHwgdHlwZSA9PSBMQVpZX1dISUxFX0ZMQUc7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKGl0ZXJhdGVlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLmNsb25lKCk7XG4gICAgICAgIHJlc3VsdC5fX2l0ZXJhdGVlc19fLnB1c2goe1xuICAgICAgICAgICdpdGVyYXRlZSc6IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSxcbiAgICAgICAgICAndHlwZSc6IHR5cGVcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5fX2ZpbHRlcmVkX18gPSByZXN1bHQuX19maWx0ZXJlZF9fIHx8IGlzRmlsdGVyO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgZm9yIGBfLmhlYWRgIGFuZCBgXy5sYXN0YC5cbiAgICBhcnJheUVhY2goWydoZWFkJywgJ2xhc3QnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSwgaW5kZXgpIHtcbiAgICAgIHZhciB0YWtlTmFtZSA9ICd0YWtlJyArIChpbmRleCA/ICdSaWdodCcgOiAnJyk7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpc1t0YWtlTmFtZV0oMSkudmFsdWUoKVswXTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5pbml0aWFsYCBhbmQgYF8udGFpbGAuXG4gICAgYXJyYXlFYWNoKFsnaW5pdGlhbCcsICd0YWlsJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICB2YXIgZHJvcE5hbWUgPSAnZHJvcCcgKyAoaW5kZXggPyAnJyA6ICdSaWdodCcpO1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX19maWx0ZXJlZF9fID8gbmV3IExhenlXcmFwcGVyKHRoaXMpIDogdGhpc1tkcm9wTmFtZV0oMSk7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNvbXBhY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLmZpbHRlcihpZGVudGl0eSk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5maW5kID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIocHJlZGljYXRlKS5oZWFkKCk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5maW5kTGFzdCA9IGZ1bmN0aW9uKHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZSgpLmZpbmQocHJlZGljYXRlKTtcbiAgICB9O1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmludm9rZU1hcCA9IGJhc2VSZXN0KGZ1bmN0aW9uKHBhdGgsIGFyZ3MpIHtcbiAgICAgIGlmICh0eXBlb2YgcGF0aCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VJbnZva2UodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUucmVqZWN0ID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIobmVnYXRlKGdldEl0ZXJhdGVlKHByZWRpY2F0ZSkpKTtcbiAgICB9O1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgICAgc3RhcnQgPSB0b0ludGVnZXIoc3RhcnQpO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gdGhpcztcbiAgICAgIGlmIChyZXN1bHQuX19maWx0ZXJlZF9fICYmIChzdGFydCA+IDAgfHwgZW5kIDwgMCkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXp5V3JhcHBlcihyZXN1bHQpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQudGFrZVJpZ2h0KC1zdGFydCk7XG4gICAgICB9IGVsc2UgaWYgKHN0YXJ0KSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC5kcm9wKHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIGlmIChlbmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbmQgPSB0b0ludGVnZXIoZW5kKTtcbiAgICAgICAgcmVzdWx0ID0gZW5kIDwgMCA/IHJlc3VsdC5kcm9wUmlnaHQoLWVuZCkgOiByZXN1bHQudGFrZShlbmQgLSBzdGFydCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUudGFrZVJpZ2h0V2hpbGUgPSBmdW5jdGlvbihwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJldmVyc2UoKS50YWtlV2hpbGUocHJlZGljYXRlKS5yZXZlcnNlKCk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS50b0FycmF5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy50YWtlKE1BWF9BUlJBWV9MRU5HVEgpO1xuICAgIH07XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIHRvIGBsb2Rhc2gucHJvdG90eXBlYC5cbiAgICBiYXNlRm9yT3duKExhenlXcmFwcGVyLnByb3RvdHlwZSwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGNoZWNrSXRlcmF0ZWUgPSAvXig/OmZpbHRlcnxmaW5kfG1hcHxyZWplY3QpfFdoaWxlJC8udGVzdChtZXRob2ROYW1lKSxcbiAgICAgICAgICBpc1Rha2VyID0gL14oPzpoZWFkfGxhc3QpJC8udGVzdChtZXRob2ROYW1lKSxcbiAgICAgICAgICBsb2Rhc2hGdW5jID0gbG9kYXNoW2lzVGFrZXIgPyAoJ3Rha2UnICsgKG1ldGhvZE5hbWUgPT0gJ2xhc3QnID8gJ1JpZ2h0JyA6ICcnKSkgOiBtZXRob2ROYW1lXSxcbiAgICAgICAgICByZXRVbndyYXBwZWQgPSBpc1Rha2VyIHx8IC9eZmluZC8udGVzdChtZXRob2ROYW1lKTtcblxuICAgICAgaWYgKCFsb2Rhc2hGdW5jKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXyxcbiAgICAgICAgICAgIGFyZ3MgPSBpc1Rha2VyID8gWzFdIDogYXJndW1lbnRzLFxuICAgICAgICAgICAgaXNMYXp5ID0gdmFsdWUgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcixcbiAgICAgICAgICAgIGl0ZXJhdGVlID0gYXJnc1swXSxcbiAgICAgICAgICAgIHVzZUxhenkgPSBpc0xhenkgfHwgaXNBcnJheSh2YWx1ZSk7XG5cbiAgICAgICAgdmFyIGludGVyY2VwdG9yID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoRnVuYy5hcHBseShsb2Rhc2gsIGFycmF5UHVzaChbdmFsdWVdLCBhcmdzKSk7XG4gICAgICAgICAgcmV0dXJuIChpc1Rha2VyICYmIGNoYWluQWxsKSA/IHJlc3VsdFswXSA6IHJlc3VsdDtcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodXNlTGF6eSAmJiBjaGVja0l0ZXJhdGVlICYmIHR5cGVvZiBpdGVyYXRlZSA9PSAnZnVuY3Rpb24nICYmIGl0ZXJhdGVlLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgICAgLy8gQXZvaWQgbGF6eSB1c2UgaWYgdGhlIGl0ZXJhdGVlIGhhcyBhIFwibGVuZ3RoXCIgdmFsdWUgb3RoZXIgdGhhbiBgMWAuXG4gICAgICAgICAgaXNMYXp5ID0gdXNlTGF6eSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjaGFpbkFsbCA9IHRoaXMuX19jaGFpbl9fLFxuICAgICAgICAgICAgaXNIeWJyaWQgPSAhIXRoaXMuX19hY3Rpb25zX18ubGVuZ3RoLFxuICAgICAgICAgICAgaXNVbndyYXBwZWQgPSByZXRVbndyYXBwZWQgJiYgIWNoYWluQWxsLFxuICAgICAgICAgICAgb25seUxhenkgPSBpc0xhenkgJiYgIWlzSHlicmlkO1xuXG4gICAgICAgIGlmICghcmV0VW53cmFwcGVkICYmIHVzZUxhenkpIHtcbiAgICAgICAgICB2YWx1ZSA9IG9ubHlMYXp5ID8gdmFsdWUgOiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGZ1bmMuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgICAgICAgIHJlc3VsdC5fX2FjdGlvbnNfXy5wdXNoKHsgJ2Z1bmMnOiB0aHJ1LCAnYXJncyc6IFtpbnRlcmNlcHRvcl0sICd0aGlzQXJnJzogdW5kZWZpbmVkIH0pO1xuICAgICAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcihyZXN1bHQsIGNoYWluQWxsKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNVbndyYXBwZWQgJiYgb25seUxhenkpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSB0aGlzLnRocnUoaW50ZXJjZXB0b3IpO1xuICAgICAgICByZXR1cm4gaXNVbndyYXBwZWQgPyAoaXNUYWtlciA/IHJlc3VsdC52YWx1ZSgpWzBdIDogcmVzdWx0LnZhbHVlKCkpIDogcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgQXJyYXlgIG1ldGhvZHMgdG8gYGxvZGFzaC5wcm90b3R5cGVgLlxuICAgIGFycmF5RWFjaChbJ3BvcCcsICdwdXNoJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBhcnJheVByb3RvW21ldGhvZE5hbWVdLFxuICAgICAgICAgIGNoYWluTmFtZSA9IC9eKD86cHVzaHxzb3J0fHVuc2hpZnQpJC8udGVzdChtZXRob2ROYW1lKSA/ICd0YXAnIDogJ3RocnUnLFxuICAgICAgICAgIHJldFVud3JhcHBlZCA9IC9eKD86cG9wfHNoaWZ0KSQvLnRlc3QobWV0aG9kTmFtZSk7XG5cbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIGlmIChyZXRVbndyYXBwZWQgJiYgIXRoaXMuX19jaGFpbl9fKSB7XG4gICAgICAgICAgdmFyIHZhbHVlID0gdGhpcy52YWx1ZSgpO1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KGlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbXSwgYXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXNbY2hhaW5OYW1lXShmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KGlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbXSwgYXJncyk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIE1hcCBtaW5pZmllZCBtZXRob2QgbmFtZXMgdG8gdGhlaXIgcmVhbCBuYW1lcy5cbiAgICBiYXNlRm9yT3duKExhenlXcmFwcGVyLnByb3RvdHlwZSwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGxvZGFzaEZ1bmMgPSBsb2Rhc2hbbWV0aG9kTmFtZV07XG4gICAgICBpZiAobG9kYXNoRnVuYykge1xuICAgICAgICB2YXIga2V5ID0gbG9kYXNoRnVuYy5uYW1lICsgJyc7XG4gICAgICAgIGlmICghaGFzT3duUHJvcGVydHkuY2FsbChyZWFsTmFtZXMsIGtleSkpIHtcbiAgICAgICAgICByZWFsTmFtZXNba2V5XSA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHJlYWxOYW1lc1trZXldLnB1c2goeyAnbmFtZSc6IG1ldGhvZE5hbWUsICdmdW5jJzogbG9kYXNoRnVuYyB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJlYWxOYW1lc1tjcmVhdGVIeWJyaWQodW5kZWZpbmVkLCBXUkFQX0JJTkRfS0VZX0ZMQUcpLm5hbWVdID0gW3tcbiAgICAgICduYW1lJzogJ3dyYXBwZXInLFxuICAgICAgJ2Z1bmMnOiB1bmRlZmluZWRcbiAgICB9XTtcblxuICAgIC8vIEFkZCBtZXRob2RzIHRvIGBMYXp5V3JhcHBlcmAuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNsb25lID0gbGF6eUNsb25lO1xuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5yZXZlcnNlID0gbGF6eVJldmVyc2U7XG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnZhbHVlID0gbGF6eVZhbHVlO1xuXG4gICAgLy8gQWRkIGNoYWluIHNlcXVlbmNlIG1ldGhvZHMgdG8gdGhlIGBsb2Rhc2hgIHdyYXBwZXIuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5hdCA9IHdyYXBwZXJBdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLmNoYWluID0gd3JhcHBlckNoYWluO1xuICAgIGxvZGFzaC5wcm90b3R5cGUuY29tbWl0ID0gd3JhcHBlckNvbW1pdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLm5leHQgPSB3cmFwcGVyTmV4dDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLnBsYW50ID0gd3JhcHBlclBsYW50O1xuICAgIGxvZGFzaC5wcm90b3R5cGUucmV2ZXJzZSA9IHdyYXBwZXJSZXZlcnNlO1xuICAgIGxvZGFzaC5wcm90b3R5cGUudG9KU09OID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZU9mID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZSA9IHdyYXBwZXJWYWx1ZTtcblxuICAgIC8vIEFkZCBsYXp5IGFsaWFzZXMuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5maXJzdCA9IGxvZGFzaC5wcm90b3R5cGUuaGVhZDtcblxuICAgIGlmIChzeW1JdGVyYXRvcikge1xuICAgICAgbG9kYXNoLnByb3RvdHlwZVtzeW1JdGVyYXRvcl0gPSB3cmFwcGVyVG9JdGVyYXRvcjtcbiAgICB9XG4gICAgcmV0dXJuIGxvZGFzaDtcbiAgfSk7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IGxvZGFzaC5cbiAgdmFyIF8gPSBydW5JbkNvbnRleHQoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZTpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIExvZGFzaCBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIExvZGFzaCBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICAvLyBVc2UgYF8ubm9Db25mbGljdGAgdG8gcmVtb3ZlIExvZGFzaCBmcm9tIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgIHJvb3QuXyA9IF87XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbywgdGhyb3VnaCBwYXRoIG1hcHBpbmcsIGl0IGNhbiBiZVxuICAgIC8vIHJlZmVyZW5jZWQgYXMgdGhlIFwidW5kZXJzY29yZVwiIG1vZHVsZS5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gXztcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBpdC5cbiAgZWxzZSBpZiAoZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgTm9kZS5qcy5cbiAgICAoZnJlZU1vZHVsZS5leHBvcnRzID0gXykuXyA9IF87XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZyZWVFeHBvcnRzLl8gPSBfO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290Ll8gPSBfO1xuICB9XG59LmNhbGwodGhpcykpO1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/lodash/lodash.js\n");
/***/ }),
/***/ "./node_modules/object-assign/index.js":
/*!*********************************************!*\
!*** ./node_modules/object-assign/index.js ***!
\*********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("/*\nobject-assign\n(c) Sindre Sorhus\n@license MIT\n*/\n\n\n/* eslint-disable no-unused-vars */\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc'); // eslint-disable-line no-new-wrappers\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (err) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (getOwnPropertySymbols) {\n\t\t\tsymbols = getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9vYmplY3QtYXNzaWduL2luZGV4LmpzPzMyMGMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLHNCQUFzQjtBQUN0Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0Isb0JBQW9CO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL29iamVjdC1hc3NpZ24vaW5kZXguanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxub2JqZWN0LWFzc2lnblxuKGMpIFNpbmRyZSBTb3JodXNcbkBsaWNlbnNlIE1JVFxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbnZhciBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzO1xudmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbnZhciBwcm9wSXNFbnVtZXJhYmxlID0gT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuZnVuY3Rpb24gdG9PYmplY3QodmFsKSB7XG5cdGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHtcblx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdPYmplY3QuYXNzaWduIGNhbm5vdCBiZSBjYWxsZWQgd2l0aCBudWxsIG9yIHVuZGVmaW5lZCcpO1xuXHR9XG5cblx0cmV0dXJuIE9iamVjdCh2YWwpO1xufVxuXG5mdW5jdGlvbiBzaG91bGRVc2VOYXRpdmUoKSB7XG5cdHRyeSB7XG5cdFx0aWYgKCFPYmplY3QuYXNzaWduKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gRGV0ZWN0IGJ1Z2d5IHByb3BlcnR5IGVudW1lcmF0aW9uIG9yZGVyIGluIG9sZGVyIFY4IHZlcnNpb25zLlxuXG5cdFx0Ly8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9NDExOFxuXHRcdHZhciB0ZXN0MSA9IG5ldyBTdHJpbmcoJ2FiYycpOyAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1uZXctd3JhcHBlcnNcblx0XHR0ZXN0MVs1XSA9ICdkZSc7XG5cdFx0aWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRlc3QxKVswXSA9PT0gJzUnKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzA1NlxuXHRcdHZhciB0ZXN0MiA9IHt9O1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgMTA7IGkrKykge1xuXHRcdFx0dGVzdDJbJ18nICsgU3RyaW5nLmZyb21DaGFyQ29kZShpKV0gPSBpO1xuXHRcdH1cblx0XHR2YXIgb3JkZXIyID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGVzdDIpLm1hcChmdW5jdGlvbiAobikge1xuXHRcdFx0cmV0dXJuIHRlc3QyW25dO1xuXHRcdH0pO1xuXHRcdGlmIChvcmRlcjIuam9pbignJykgIT09ICcwMTIzNDU2Nzg5Jykge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMwNTZcblx0XHR2YXIgdGVzdDMgPSB7fTtcblx0XHQnYWJjZGVmZ2hpamtsbW5vcHFyc3QnLnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uIChsZXR0ZXIpIHtcblx0XHRcdHRlc3QzW2xldHRlcl0gPSBsZXR0ZXI7XG5cdFx0fSk7XG5cdFx0aWYgKE9iamVjdC5rZXlzKE9iamVjdC5hc3NpZ24oe30sIHRlc3QzKSkuam9pbignJykgIT09XG5cdFx0XHRcdCdhYmNkZWZnaGlqa2xtbm9wcXJzdCcpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0Ly8gV2UgZG9uJ3QgZXhwZWN0IGFueSBvZiB0aGUgYWJvdmUgdG8gdGhyb3csIGJ1dCBiZXR0ZXIgdG8gYmUgc2FmZS5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzaG91bGRVc2VOYXRpdmUoKSA/IE9iamVjdC5hc3NpZ24gOiBmdW5jdGlvbiAodGFyZ2V0LCBzb3VyY2UpIHtcblx0dmFyIGZyb207XG5cdHZhciB0byA9IHRvT2JqZWN0KHRhcmdldCk7XG5cdHZhciBzeW1ib2xzO1xuXG5cdGZvciAodmFyIHMgPSAxOyBzIDwgYXJndW1lbnRzLmxlbmd0aDsgcysrKSB7XG5cdFx0ZnJvbSA9IE9iamVjdChhcmd1bWVudHNbc10pO1xuXG5cdFx0Zm9yICh2YXIga2V5IGluIGZyb20pIHtcblx0XHRcdGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKGZyb20sIGtleSkpIHtcblx0XHRcdFx0dG9ba2V5XSA9IGZyb21ba2V5XTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZ2V0T3duUHJvcGVydHlTeW1ib2xzKSB7XG5cdFx0XHRzeW1ib2xzID0gZ2V0T3duUHJvcGVydHlTeW1ib2xzKGZyb20pO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBzeW1ib2xzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmIChwcm9wSXNFbnVtZXJhYmxlLmNhbGwoZnJvbSwgc3ltYm9sc1tpXSkpIHtcblx0XHRcdFx0XHR0b1tzeW1ib2xzW2ldXSA9IGZyb21bc3ltYm9sc1tpXV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdG87XG59O1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/object-assign/index.js\n");
/***/ }),
/***/ "./node_modules/process/browser.js":
/*!*****************************************!*\
!*** ./node_modules/process/browser.js ***!
\*****************************************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanM/ZjI4YyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHNCQUFzQjtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDOztBQUVyQztBQUNBO0FBQ0E7O0FBRUEsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QixVQUFVIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxudmFyIHByb2Nlc3MgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vLyBjYWNoZWQgZnJvbSB3aGF0ZXZlciBnbG9iYWwgaXMgcHJlc2VudCBzbyB0aGF0IHRlc3QgcnVubmVycyB0aGF0IHN0dWIgaXRcbi8vIGRvbid0IGJyZWFrIHRoaW5ncy4gIEJ1dCB3ZSBuZWVkIHRvIHdyYXAgaXQgaW4gYSB0cnkgY2F0Y2ggaW4gY2FzZSBpdCBpc1xuLy8gd3JhcHBlZCBpbiBzdHJpY3QgbW9kZSBjb2RlIHdoaWNoIGRvZXNuJ3QgZGVmaW5lIGFueSBnbG9iYWxzLiAgSXQncyBpbnNpZGUgYVxuLy8gZnVuY3Rpb24gYmVjYXVzZSB0cnkvY2F0Y2hlcyBkZW9wdGltaXplIGluIGNlcnRhaW4gZW5naW5lcy5cblxudmFyIGNhY2hlZFNldFRpbWVvdXQ7XG52YXIgY2FjaGVkQ2xlYXJUaW1lb3V0O1xuXG5mdW5jdGlvbiBkZWZhdWx0U2V0VGltb3V0KCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc2V0VGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuZnVuY3Rpb24gZGVmYXVsdENsZWFyVGltZW91dCAoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjbGVhclRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbihmdW5jdGlvbiAoKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZXRUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKHR5cGVvZiBjbGVhclRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGRlZmF1bHRDbGVhclRpbWVvdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGRlZmF1bHRDbGVhclRpbWVvdXQ7XG4gICAgfVxufSAoKSlcbmZ1bmN0aW9uIHJ1blRpbWVvdXQoZnVuKSB7XG4gICAgaWYgKGNhY2hlZFNldFRpbWVvdXQgPT09IHNldFRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIC8vIGlmIHNldFRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRTZXRUaW1lb3V0ID09PSBkZWZhdWx0U2V0VGltb3V0IHx8ICFjYWNoZWRTZXRUaW1lb3V0KSAmJiBzZXRUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfSBjYXRjaChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCB0cnVzdCB0aGUgZ2xvYmFsIG9iamVjdCB3aGVuIGNhbGxlZCBub3JtYWxseVxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbChudWxsLCBmdW4sIDApO1xuICAgICAgICB9IGNhdGNoKGUpe1xuICAgICAgICAgICAgLy8gc2FtZSBhcyBhYm92ZSBidXQgd2hlbiBpdCdzIGEgdmVyc2lvbiBvZiBJLkUuIHRoYXQgbXVzdCBoYXZlIHRoZSBnbG9iYWwgb2JqZWN0IGZvciAndGhpcycsIGhvcGZ1bGx5IG91ciBjb250ZXh0IGNvcnJlY3Qgb3RoZXJ3aXNlIGl0IHdpbGwgdGhyb3cgYSBnbG9iYWwgZXJyb3JcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwodGhpcywgZnVuLCAwKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG59XG5mdW5jdGlvbiBydW5DbGVhclRpbWVvdXQobWFya2VyKSB7XG4gICAgaWYgKGNhY2hlZENsZWFyVGltZW91dCA9PT0gY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gY2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfVxuICAgIC8vIGlmIGNsZWFyVGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZENsZWFyVGltZW91dCA9PT0gZGVmYXVsdENsZWFyVGltZW91dCB8fCAhY2FjaGVkQ2xlYXJUaW1lb3V0KSAmJiBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICByZXR1cm4gY2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH0gY2F0Y2ggKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0ICB0cnVzdCB0aGUgZ2xvYmFsIG9iamVjdCB3aGVuIGNhbGxlZCBub3JtYWxseVxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKG51bGwsIG1hcmtlcik7XG4gICAgICAgIH0gY2F0Y2ggKGUpe1xuICAgICAgICAgICAgLy8gc2FtZSBhcyBhYm92ZSBidXQgd2hlbiBpdCdzIGEgdmVyc2lvbiBvZiBJLkUuIHRoYXQgbXVzdCBoYXZlIHRoZSBnbG9iYWwgb2JqZWN0IGZvciAndGhpcycsIGhvcGZ1bGx5IG91ciBjb250ZXh0IGNvcnJlY3Qgb3RoZXJ3aXNlIGl0IHdpbGwgdGhyb3cgYSBnbG9iYWwgZXJyb3IuXG4gICAgICAgICAgICAvLyBTb21lIHZlcnNpb25zIG9mIEkuRS4gaGF2ZSBkaWZmZXJlbnQgcnVsZXMgZm9yIGNsZWFyVGltZW91dCB2cyBzZXRUaW1lb3V0XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwodGhpcywgbWFya2VyKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG5cbn1cbnZhciBxdWV1ZSA9IFtdO1xudmFyIGRyYWluaW5nID0gZmFsc2U7XG52YXIgY3VycmVudFF1ZXVlO1xudmFyIHF1ZXVlSW5kZXggPSAtMTtcblxuZnVuY3Rpb24gY2xlYW5VcE5leHRUaWNrKCkge1xuICAgIGlmICghZHJhaW5pbmcgfHwgIWN1cnJlbnRRdWV1ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgaWYgKGN1cnJlbnRRdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgcXVldWUgPSBjdXJyZW50UXVldWUuY29uY2F0KHF1ZXVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgfVxuICAgIGlmIChxdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgZHJhaW5RdWV1ZSgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZHJhaW5RdWV1ZSgpIHtcbiAgICBpZiAoZHJhaW5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgdGltZW91dCA9IHJ1blRpbWVvdXQoY2xlYW5VcE5leHRUaWNrKTtcbiAgICBkcmFpbmluZyA9IHRydWU7XG5cbiAgICB2YXIgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIHdoaWxlKGxlbikge1xuICAgICAgICBjdXJyZW50UXVldWUgPSBxdWV1ZTtcbiAgICAgICAgcXVldWUgPSBbXTtcbiAgICAgICAgd2hpbGUgKCsrcXVldWVJbmRleCA8IGxlbikge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRRdWV1ZSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgY3VycmVudFF1ZXVlID0gbnVsbDtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIHJ1bkNsZWFyVGltZW91dCh0aW1lb3V0KTtcbn1cblxucHJvY2Vzcy5uZXh0VGljayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1biwgYXJncykpO1xuICAgIGlmIChxdWV1ZS5sZW5ndGggPT09IDEgJiYgIWRyYWluaW5nKSB7XG4gICAgICAgIHJ1blRpbWVvdXQoZHJhaW5RdWV1ZSk7XG4gICAgfVxufTtcblxuLy8gdjggbGlrZXMgcHJlZGljdGlibGUgb2JqZWN0c1xuZnVuY3Rpb24gSXRlbShmdW4sIGFycmF5KSB7XG4gICAgdGhpcy5mdW4gPSBmdW47XG4gICAgdGhpcy5hcnJheSA9IGFycmF5O1xufVxuSXRlbS5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpO1xufTtcbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xucHJvY2Vzcy52ZXJzaW9uID0gJyc7IC8vIGVtcHR5IHN0cmluZyB0byBhdm9pZCByZWdleHAgaXNzdWVzXG5wcm9jZXNzLnZlcnNpb25zID0ge307XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5wcm9jZXNzLm9uID0gbm9vcDtcbnByb2Nlc3MuYWRkTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5vbmNlID0gbm9vcDtcbnByb2Nlc3Mub2ZmID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBub29wO1xucHJvY2Vzcy5lbWl0ID0gbm9vcDtcbnByb2Nlc3MucHJlcGVuZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucHJlcGVuZE9uY2VMaXN0ZW5lciA9IG5vb3A7XG5cbnByb2Nlc3MubGlzdGVuZXJzID0gZnVuY3Rpb24gKG5hbWUpIHsgcmV0dXJuIFtdIH1cblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuXG5wcm9jZXNzLmN3ZCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuICcvJyB9O1xucHJvY2Vzcy5jaGRpciA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcbnByb2Nlc3MudW1hc2sgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/process/browser.js\n");
/***/ }),
/***/ "./node_modules/prop-types/checkPropTypes.js":
/*!***************************************************!*\
!*** ./node_modules/prop-types/checkPropTypes.js ***!
\***************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\n\nvar printWarning = function() {};\n\nif (true) {\n var ReactPropTypesSecret = __webpack_require__(/*! ./lib/ReactPropTypesSecret */ \"./node_modules/prop-types/lib/ReactPropTypesSecret.js\");\n var loggedTypeFailures = {};\n var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n printWarning = function(text) {\n var message = 'Warning: ' + text;\n if (typeof console !== 'undefined') {\n console.error(message);\n }\n try {\n // --- Welcome to debugging React ---\n // This error was thrown as a convenience so that you can use this stack\n // to find the callsite that caused this warning to fire.\n throw new Error(message);\n } catch (x) {}\n };\n}\n\n/**\n * Assert that the values match with the type specs.\n * Error messages are memorized and will only be shown once.\n *\n * @param {object} typeSpecs Map of name to a ReactPropType\n * @param {object} values Runtime values that need to be type-checked\n * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n * @param {string} componentName Name of the component for error messages.\n * @param {?Function} getStack Returns the component stack.\n * @private\n */\nfunction checkPropTypes(typeSpecs, values, location, componentName, getStack) {\n if (true) {\n for (var typeSpecName in typeSpecs) {\n if (has(typeSpecs, typeSpecName)) {\n var error;\n // Prop type validation may throw. In case they do, we don't want to\n // fail the render phase where it didn't fail before. So we log it.\n // After these have been cleaned up, we'll let them throw.\n try {\n // This is intentionally an invariant that gets caught. It's the same\n // behavior as without this statement except with a better message.\n if (typeof typeSpecs[typeSpecName] !== 'function') {\n var err = Error(\n (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +\n 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.'\n );\n err.name = 'Invariant Violation';\n throw err;\n }\n error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);\n } catch (ex) {\n error = ex;\n }\n if (error && !(error instanceof Error)) {\n printWarning(\n (componentName || 'React class') + ': type specification of ' +\n location + ' `' + typeSpecName + '` is invalid; the type checker ' +\n 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +\n 'You may have forgotten to pass an argument to the type checker ' +\n 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +\n 'shape all require an argument).'\n );\n }\n if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n // Only monitor this failure once because there tends to be a lot of the\n // same error.\n loggedTypeFailures[error.message] = true;\n\n var stack = getStack ? getStack() : '';\n\n printWarning(\n 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')\n );\n }\n }\n }\n }\n}\n\n/**\n * Resets warning cache when testing.\n *\n * @private\n */\ncheckPropTypes.resetWarningCache = function() {\n if (true) {\n loggedTypeFailures = {};\n }\n}\n\nmodule.exports = checkPropTypes;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9wcm9wLXR5cGVzL2NoZWNrUHJvcFR5cGVzLmpzP2ExNWMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVhOztBQUViOztBQUVBLElBQUksSUFBcUM7QUFDekMsNkJBQTZCLG1CQUFPLENBQUMseUZBQTRCO0FBQ2pFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixXQUFXLFVBQVU7QUFDckI7QUFDQTtBQUNBO0FBQ0EsTUFBTSxJQUFxQztBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEdBQTRHO0FBQzVHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkRBQTJEO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTSxJQUFxQztBQUMzQztBQUNBO0FBQ0E7O0FBRUEiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvcHJvcC10eXBlcy9jaGVja1Byb3BUeXBlcy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLXByZXNlbnQsIEZhY2Vib29rLCBJbmMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcHJpbnRXYXJuaW5nID0gZnVuY3Rpb24oKSB7fTtcblxuaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgdmFyIFJlYWN0UHJvcFR5cGVzU2VjcmV0ID0gcmVxdWlyZSgnLi9saWIvUmVhY3RQcm9wVHlwZXNTZWNyZXQnKTtcbiAgdmFyIGxvZ2dlZFR5cGVGYWlsdXJlcyA9IHt9O1xuICB2YXIgaGFzID0gRnVuY3Rpb24uY2FsbC5iaW5kKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkpO1xuXG4gIHByaW50V2FybmluZyA9IGZ1bmN0aW9uKHRleHQpIHtcbiAgICB2YXIgbWVzc2FnZSA9ICdXYXJuaW5nOiAnICsgdGV4dDtcbiAgICBpZiAodHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgLy8gLS0tIFdlbGNvbWUgdG8gZGVidWdnaW5nIFJlYWN0IC0tLVxuICAgICAgLy8gVGhpcyBlcnJvciB3YXMgdGhyb3duIGFzIGEgY29udmVuaWVuY2Ugc28gdGhhdCB5b3UgY2FuIHVzZSB0aGlzIHN0YWNrXG4gICAgICAvLyB0byBmaW5kIHRoZSBjYWxsc2l0ZSB0aGF0IGNhdXNlZCB0aGlzIHdhcm5pbmcgdG8gZmlyZS5cbiAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICB9IGNhdGNoICh4KSB7fVxuICB9O1xufVxuXG4vKipcbiAqIEFzc2VydCB0aGF0IHRoZSB2YWx1ZXMgbWF0Y2ggd2l0aCB0aGUgdHlwZSBzcGVjcy5cbiAqIEVycm9yIG1lc3NhZ2VzIGFyZSBtZW1vcml6ZWQgYW5kIHdpbGwgb25seSBiZSBzaG93biBvbmNlLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0eXBlU3BlY3MgTWFwIG9mIG5hbWUgdG8gYSBSZWFjdFByb3BUeXBlXG4gKiBAcGFyYW0ge29iamVjdH0gdmFsdWVzIFJ1bnRpbWUgdmFsdWVzIHRoYXQgbmVlZCB0byBiZSB0eXBlLWNoZWNrZWRcbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhdGlvbiBlLmcuIFwicHJvcFwiLCBcImNvbnRleHRcIiwgXCJjaGlsZCBjb250ZXh0XCJcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb21wb25lbnROYW1lIE5hbWUgb2YgdGhlIGNvbXBvbmVudCBmb3IgZXJyb3IgbWVzc2FnZXMuXG4gKiBAcGFyYW0gez9GdW5jdGlvbn0gZ2V0U3RhY2sgUmV0dXJucyB0aGUgY29tcG9uZW50IHN0YWNrLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gY2hlY2tQcm9wVHlwZXModHlwZVNwZWNzLCB2YWx1ZXMsIGxvY2F0aW9uLCBjb21wb25lbnROYW1lLCBnZXRTdGFjaykge1xuICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgIGZvciAodmFyIHR5cGVTcGVjTmFtZSBpbiB0eXBlU3BlY3MpIHtcbiAgICAgIGlmIChoYXModHlwZVNwZWNzLCB0eXBlU3BlY05hbWUpKSB7XG4gICAgICAgIHZhciBlcnJvcjtcbiAgICAgICAgLy8gUHJvcCB0eXBlIHZhbGlkYXRpb24gbWF5IHRocm93LiBJbiBjYXNlIHRoZXkgZG8sIHdlIGRvbid0IHdhbnQgdG9cbiAgICAgICAgLy8gZmFpbCB0aGUgcmVuZGVyIHBoYXNlIHdoZXJlIGl0IGRpZG4ndCBmYWlsIGJlZm9yZS4gU28gd2UgbG9nIGl0LlxuICAgICAgICAvLyBBZnRlciB0aGVzZSBoYXZlIGJlZW4gY2xlYW5lZCB1cCwgd2UnbGwgbGV0IHRoZW0gdGhyb3cuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gVGhpcyBpcyBpbnRlbnRpb25hbGx5IGFuIGludmFyaWFudCB0aGF0IGdldHMgY2F1Z2h0LiBJdCdzIHRoZSBzYW1lXG4gICAgICAgICAgLy8gYmVoYXZpb3IgYXMgd2l0aG91dCB0aGlzIHN0YXRlbWVudCBleGNlcHQgd2l0aCBhIGJldHRlciBtZXNzYWdlLlxuICAgICAgICAgIGlmICh0eXBlb2YgdHlwZVNwZWNzW3R5cGVTcGVjTmFtZV0gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHZhciBlcnIgPSBFcnJvcihcbiAgICAgICAgICAgICAgKGNvbXBvbmVudE5hbWUgfHwgJ1JlYWN0IGNsYXNzJykgKyAnOiAnICsgbG9jYXRpb24gKyAnIHR5cGUgYCcgKyB0eXBlU3BlY05hbWUgKyAnYCBpcyBpbnZhbGlkOyAnICtcbiAgICAgICAgICAgICAgJ2l0IG11c3QgYmUgYSBmdW5jdGlvbiwgdXN1YWxseSBmcm9tIHRoZSBgcHJvcC10eXBlc2AgcGFja2FnZSwgYnV0IHJlY2VpdmVkIGAnICsgdHlwZW9mIHR5cGVTcGVjc1t0eXBlU3BlY05hbWVdICsgJ2AuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGVyci5uYW1lID0gJ0ludmFyaWFudCBWaW9sYXRpb24nO1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlcnJvciA9IHR5cGVTcGVjc1t0eXBlU3BlY05hbWVdKHZhbHVlcywgdHlwZVNwZWNOYW1lLCBjb21wb25lbnROYW1lLCBsb2NhdGlvbiwgbnVsbCwgUmVhY3RQcm9wVHlwZXNTZWNyZXQpO1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGVycm9yID0gZXg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVycm9yICYmICEoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgICBwcmludFdhcm5pbmcoXG4gICAgICAgICAgICAoY29tcG9uZW50TmFtZSB8fCAnUmVhY3QgY2xhc3MnKSArICc6IHR5cGUgc3BlY2lmaWNhdGlvbiBvZiAnICtcbiAgICAgICAgICAgIGxvY2F0aW9uICsgJyBgJyArIHR5cGVTcGVjTmFtZSArICdgIGlzIGludmFsaWQ7IHRoZSB0eXBlIGNoZWNrZXIgJyArXG4gICAgICAgICAgICAnZnVuY3Rpb24gbXVzdCByZXR1cm4gYG51bGxgIG9yIGFuIGBFcnJvcmAgYnV0IHJldHVybmVkIGEgJyArIHR5cGVvZiBlcnJvciArICcuICcgK1xuICAgICAgICAgICAgJ1lvdSBtYXkgaGF2ZSBmb3Jnb3R0ZW4gdG8gcGFzcyBhbiBhcmd1bWVudCB0byB0aGUgdHlwZSBjaGVja2VyICcgK1xuICAgICAgICAgICAgJ2NyZWF0b3IgKGFycmF5T2YsIGluc3RhbmNlT2YsIG9iamVjdE9mLCBvbmVPZiwgb25lT2ZUeXBlLCBhbmQgJyArXG4gICAgICAgICAgICAnc2hhcGUgYWxsIHJlcXVpcmUgYW4gYXJndW1lbnQpLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yICYmICEoZXJyb3IubWVzc2FnZSBpbiBsb2dnZWRUeXBlRmFpbHVyZXMpKSB7XG4gICAgICAgICAgLy8gT25seSBtb25pdG9yIHRoaXMgZmFpbHVyZSBvbmNlIGJlY2F1c2UgdGhlcmUgdGVuZHMgdG8gYmUgYSBsb3Qgb2YgdGhlXG4gICAgICAgICAgLy8gc2FtZSBlcnJvci5cbiAgICAgICAgICBsb2dnZWRUeXBlRmFpbHVyZXNbZXJyb3IubWVzc2FnZV0gPSB0cnVlO1xuXG4gICAgICAgICAgdmFyIHN0YWNrID0gZ2V0U3RhY2sgPyBnZXRTdGFjaygpIDogJyc7XG5cbiAgICAgICAgICBwcmludFdhcm5pbmcoXG4gICAgICAgICAgICAnRmFpbGVkICcgKyBsb2NhdGlvbiArICcgdHlwZTogJyArIGVycm9yLm1lc3NhZ2UgKyAoc3RhY2sgIT0gbnVsbCA/IHN0YWNrIDogJycpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJlc2V0cyB3YXJuaW5nIGNhY2hlIHdoZW4gdGVzdGluZy5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jaGVja1Byb3BUeXBlcy5yZXNldFdhcm5pbmdDYWNoZSA9IGZ1bmN0aW9uKCkge1xuICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgIGxvZ2dlZFR5cGVGYWlsdXJlcyA9IHt9O1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2hlY2tQcm9wVHlwZXM7XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/prop-types/checkPropTypes.js\n");
/***/ }),
/***/ "./node_modules/prop-types/factoryWithTypeCheckers.js":
/*!************************************************************!*\
!*** ./node_modules/prop-types/factoryWithTypeCheckers.js ***!
\************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\n\nvar ReactIs = __webpack_require__(/*! react-is */ \"./node_modules/react-is/index.js\");\nvar assign = __webpack_require__(/*! object-assign */ \"./node_modules/object-assign/index.js\");\n\nvar ReactPropTypesSecret = __webpack_require__(/*! ./lib/ReactPropTypesSecret */ \"./node_modules/prop-types/lib/ReactPropTypesSecret.js\");\nvar checkPropTypes = __webpack_require__(/*! ./checkPropTypes */ \"./node_modules/prop-types/checkPropTypes.js\");\n\nvar has = Function.call.bind(Object.prototype.hasOwnProperty);\nvar printWarning = function() {};\n\nif (true) {\n printWarning = function(text) {\n var message = 'Warning: ' + text;\n if (typeof console !== 'undefined') {\n console.error(message);\n }\n try {\n // --- Welcome to debugging React ---\n // This error was thrown as a convenience so that you can use this stack\n // to find the callsite that caused this warning to fire.\n throw new Error(message);\n } catch (x) {}\n };\n}\n\nfunction emptyFunctionThatReturnsNull() {\n return null;\n}\n\nmodule.exports = function(isValidElement, throwOnDirectAccess) {\n /* global Symbol */\n var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\n var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.\n\n /**\n * Returns the iterator method function contained on the iterable object.\n *\n * Be sure to invoke the function with the iterable as context:\n *\n * var iteratorFn = getIteratorFn(myIterable);\n * if (iteratorFn) {\n * var iterator = iteratorFn.call(myIterable);\n * ...\n * }\n *\n * @param {?object} maybeIterable\n * @return {?function}\n */\n function getIteratorFn(maybeIterable) {\n var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);\n if (typeof iteratorFn === 'function') {\n return iteratorFn;\n }\n }\n\n /**\n * Collection of methods that allow declaration and validation of props that are\n * supplied to React components. Example usage:\n *\n * var Props = require('ReactPropTypes');\n * var MyArticle = React.createClass({\n * propTypes: {\n * // An optional string prop named \"description\".\n * description: Props.string,\n *\n * // A required enum prop named \"category\".\n * category: Props.oneOf(['News','Photos']).isRequired,\n *\n * // A prop named \"dialog\" that requires an instance of Dialog.\n * dialog: Props.instanceOf(Dialog).isRequired\n * },\n * render: function() { ... }\n * });\n *\n * A more formal specification of how these methods are used:\n *\n * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)\n * decl := ReactPropTypes.{type}(.isRequired)?\n *\n * Each and every declaration produces a function with the same signature. This\n * allows the creation of custom validation functions. For example:\n *\n * var MyLink = React.createClass({\n * propTypes: {\n * // An optional string or URI prop named \"href\".\n * href: function(props, propName, componentName) {\n * var propValue = props[propName];\n * if (propValue != null && typeof propValue !== 'string' &&\n * !(propValue instanceof URI)) {\n * return new Error(\n * 'Expected a string or an URI for ' + propName + ' in ' +\n * componentName\n * );\n * }\n * }\n * },\n * render: function() {...}\n * });\n *\n * @internal\n */\n\n var ANONYMOUS = '<<anonymous>>';\n\n // Important!\n // Keep this list in sync with production version in `./factoryWithThrowingShims.js`.\n var ReactPropTypes = {\n array: createPrimitiveTypeChecker('array'),\n bool: createPrimitiveTypeChecker('boolean'),\n func: createPrimitiveTypeChecker('function'),\n number: createPrimitiveTypeChecker('number'),\n object: createPrimitiveTypeChecker('object'),\n string: createPrimitiveTypeChecker('string'),\n symbol: createPrimitiveTypeChecker('symbol'),\n\n any: createAnyTypeChecker(),\n arrayOf: createArrayOfTypeChecker,\n element: createElementTypeChecker(),\n elementType: createElementTypeTypeChecker(),\n instanceOf: createInstanceTypeChecker,\n node: createNodeChecker(),\n objectOf: createObjectOfTypeChecker,\n oneOf: createEnumTypeChecker,\n oneOfType: createUnionTypeChecker,\n shape: createShapeTypeChecker,\n exact: createStrictShapeTypeChecker,\n };\n\n /**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n /*eslint-disable no-self-compare*/\n function is(x, y) {\n // SameValue algorithm\n if (x === y) {\n // Steps 1-5, 7-10\n // Steps 6.b-6.e: +0 != -0\n return x !== 0 || 1 / x === 1 / y;\n } else {\n // Step 6.a: NaN == NaN\n return x !== x && y !== y;\n }\n }\n /*eslint-enable no-self-compare*/\n\n /**\n * We use an Error-like object for backward compatibility as people may call\n * PropTypes directly and inspect their output. However, we don't use real\n * Errors anymore. We don't inspect their stack anyway, and creating them\n * is prohibitively expensive if they are created too often, such as what\n * happens in oneOfType() for any type before the one that matched.\n */\n function PropTypeError(message) {\n this.message = message;\n this.stack = '';\n }\n // Make `instanceof Error` still work for returned errors.\n PropTypeError.prototype = Error.prototype;\n\n function createChainableTypeChecker(validate) {\n if (true) {\n var manualPropTypeCallCache = {};\n var manualPropTypeWarningCount = 0;\n }\n function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {\n componentName = componentName || ANONYMOUS;\n propFullName = propFullName || propName;\n\n if (secret !== ReactPropTypesSecret) {\n if (throwOnDirectAccess) {\n // New behavior only for users of `prop-types` package\n var err = new Error(\n 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +\n 'Use `PropTypes.checkPropTypes()` to call them. ' +\n 'Read more at http://fb.me/use-check-prop-types'\n );\n err.name = 'Invariant Violation';\n throw err;\n } else if ( true && typeof console !== 'undefined') {\n // Old behavior for people using React.PropTypes\n var cacheKey = componentName + ':' + propName;\n if (\n !manualPropTypeCallCache[cacheKey] &&\n // Avoid spamming the console because they are often not actionable except for lib authors\n manualPropTypeWarningCount < 3\n ) {\n printWarning(\n 'You are manually calling a React.PropTypes validation ' +\n 'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' +\n 'and will throw in the standalone `prop-types` package. ' +\n 'You may be seeing this warning due to a third-party PropTypes ' +\n 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.'\n );\n manualPropTypeCallCache[cacheKey] = true;\n manualPropTypeWarningCount++;\n }\n }\n }\n if (props[propName] == null) {\n if (isRequired) {\n if (props[propName] === null) {\n return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));\n }\n return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));\n }\n return null;\n } else {\n return validate(props, propName, componentName, location, propFullName);\n }\n }\n\n var chainedCheckType = checkType.bind(null, false);\n chainedCheckType.isRequired = checkType.bind(null, true);\n\n return chainedCheckType;\n }\n\n function createPrimitiveTypeChecker(expectedType) {\n function validate(props, propName, componentName, location, propFullName, secret) {\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== expectedType) {\n // `propValue` being instance of, say, date/regexp, pass the 'object'\n // check, but we can offer a more precise error message here rather than\n // 'of type `object`'.\n var preciseType = getPreciseType(propValue);\n\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createAnyTypeChecker() {\n return createChainableTypeChecker(emptyFunctionThatReturnsNull);\n }\n\n function createArrayOfTypeChecker(typeChecker) {\n function validate(props, propName, componentName, location, propFullName) {\n if (typeof typeChecker !== 'function') {\n return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');\n }\n var propValue = props[propName];\n if (!Array.isArray(propValue)) {\n var propType = getPropType(propValue);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));\n }\n for (var i = 0; i < propValue.length; i++) {\n var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);\n if (error instanceof Error) {\n return error;\n }\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createElementTypeChecker() {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n if (!isValidElement(propValue)) {\n var propType = getPropType(propValue);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createElementTypeTypeChecker() {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n if (!ReactIs.isValidElementType(propValue)) {\n var propType = getPropType(propValue);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createInstanceTypeChecker(expectedClass) {\n function validate(props, propName, componentName, location, propFullName) {\n if (!(props[propName] instanceof expectedClass)) {\n var expectedClassName = expectedClass.name || ANONYMOUS;\n var actualClassName = getClassName(props[propName]);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createEnumTypeChecker(expectedValues) {\n if (!Array.isArray(expectedValues)) {\n if (true) {\n if (arguments.length > 1) {\n printWarning(\n 'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' +\n 'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).'\n );\n } else {\n printWarning('Invalid argument supplied to oneOf, expected an array.');\n }\n }\n return emptyFunctionThatReturnsNull;\n }\n\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n for (var i = 0; i < expectedValues.length; i++) {\n if (is(propValue, expectedValues[i])) {\n return null;\n }\n }\n\n var valuesString = JSON.stringify(expectedValues, function replacer(key, value) {\n var type = getPreciseType(value);\n if (type === 'symbol') {\n return String(value);\n }\n return value;\n });\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));\n }\n return createChainableTypeChecker(validate);\n }\n\n function createObjectOfTypeChecker(typeChecker) {\n function validate(props, propName, componentName, location, propFullName) {\n if (typeof typeChecker !== 'function') {\n return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');\n }\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== 'object') {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));\n }\n for (var key in propValue) {\n if (has(propValue, key)) {\n var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);\n if (error instanceof Error) {\n return error;\n }\n }\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createUnionTypeChecker(arrayOfTypeCheckers) {\n if (!Array.isArray(arrayOfTypeCheckers)) {\n true ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : undefined;\n return emptyFunctionThatReturnsNull;\n }\n\n for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n var checker = arrayOfTypeCheckers[i];\n if (typeof checker !== 'function') {\n printWarning(\n 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +\n 'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.'\n );\n return emptyFunctionThatReturnsNull;\n }\n }\n\n function validate(props, propName, componentName, location, propFullName) {\n for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n var checker = arrayOfTypeCheckers[i];\n if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) {\n return null;\n }\n }\n\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));\n }\n return createChainableTypeChecker(validate);\n }\n\n function createNodeChecker() {\n function validate(props, propName, componentName, location, propFullName) {\n if (!isNode(props[propName])) {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createShapeTypeChecker(shapeTypes) {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== 'object') {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n }\n for (var key in shapeTypes) {\n var checker = shapeTypes[key];\n if (!checker) {\n continue;\n }\n var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);\n if (error) {\n return error;\n }\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createStrictShapeTypeChecker(shapeTypes) {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== 'object') {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n }\n // We need to check all keys in case some are required but missing from\n // props.\n var allKeys = assign({}, props[propName], shapeTypes);\n for (var key in allKeys) {\n var checker = shapeTypes[key];\n if (!checker) {\n return new PropTypeError(\n 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +\n '\\nBad object: ' + JSON.stringify(props[propName], null, ' ') +\n '\\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ')\n );\n }\n var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);\n if (error) {\n return error;\n }\n }\n return null;\n }\n\n return createChainableTypeChecker(validate);\n }\n\n function isNode(propValue) {\n switch (typeof propValue) {\n case 'number':\n case 'string':\n case 'undefined':\n return true;\n case 'boolean':\n return !propValue;\n case 'object':\n if (Array.isArray(propValue)) {\n return propValue.every(isNode);\n }\n if (propValue === null || isValidElement(propValue)) {\n return true;\n }\n\n var iteratorFn = getIteratorFn(propValue);\n if (iteratorFn) {\n var iterator = iteratorFn.call(propValue);\n var step;\n if (iteratorFn !== propValue.entries) {\n while (!(step = iterator.next()).done) {\n if (!isNode(step.value)) {\n return false;\n }\n }\n } else {\n // Iterator will provide entry [k,v] tuples rather than values.\n while (!(step = iterator.next()).done) {\n var entry = step.value;\n if (entry) {\n if (!isNode(entry[1])) {\n return false;\n }\n }\n }\n }\n } else {\n return false;\n }\n\n return true;\n default:\n return false;\n }\n }\n\n function isSymbol(propType, propValue) {\n // Native Symbol.\n if (propType === 'symbol') {\n return true;\n }\n\n // falsy value can't be a Symbol\n if (!propValue) {\n return false;\n }\n\n // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'\n if (propValue['@@toStringTag'] === 'Symbol') {\n return true;\n }\n\n // Fallback for non-spec compliant Symbols which are polyfilled.\n if (typeof Symbol === 'function' && propValue instanceof Symbol) {\n return true;\n }\n\n return false;\n }\n\n // Equivalent of `typeof` but with special handling for array and regexp.\n function getPropType(propValue) {\n var propType = typeof propValue;\n if (Array.isArray(propValue)) {\n return 'array';\n }\n if (propValue instanceof RegExp) {\n // Old webkits (at least until Android 4.0) return 'function' rather than\n // 'object' for typeof a RegExp. We'll normalize this here so that /bla/\n // passes PropTypes.object.\n return 'object';\n }\n if (isSymbol(propType, propValue)) {\n return 'symbol';\n }\n return propType;\n }\n\n // This handles more types than `getPropType`. Only used for error messages.\n // See `createPrimitiveTypeChecker`.\n function getPreciseType(propValue) {\n if (typeof propValue === 'undefined' || propValue === null) {\n return '' + propValue;\n }\n var propType = getPropType(propValue);\n if (propType === 'object') {\n if (propValue instanceof Date) {\n return 'date';\n } else if (propValue instanceof RegExp) {\n return 'regexp';\n }\n }\n return propType;\n }\n\n // Returns a string that is postfixed to a warning about an invalid type.\n // For example, \"undefined\" or \"of type array\"\n function getPostfixForTypeWarning(value) {\n var type = getPreciseType(value);\n switch (type) {\n case 'array':\n case 'object':\n return 'an ' + type;\n case 'boolean':\n case 'date':\n case 'regexp':\n return 'a ' + type;\n default:\n return type;\n }\n }\n\n // Returns class name of the object, if any.\n function getClassName(propValue) {\n if (!propValue.constructor || !propValue.constructor.name) {\n return ANONYMOUS;\n }\n return propValue.constructor.name;\n }\n\n ReactPropTypes.checkPropTypes = checkPropTypes;\n ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache;\n ReactPropTypes.PropTypes = ReactPropTypes;\n\n return ReactPropTypes;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9wcm9wLXR5cGVzL2ZhY3RvcnlXaXRoVHlwZUNoZWNrZXJzLmpzP2IwNzIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVhOztBQUViLGNBQWMsbUJBQU8sQ0FBQyxrREFBVTtBQUNoQyxhQUFhLG1CQUFPLENBQUMsNERBQWU7O0FBRXBDLDJCQUEyQixtQkFBTyxDQUFDLHlGQUE0QjtBQUMvRCxxQkFBcUIsbUJBQU8sQ0FBQyxxRUFBa0I7O0FBRS9DO0FBQ0E7O0FBRUEsSUFBSSxJQUFxQztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckIsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDViw2QkFBNkI7QUFDN0IsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLEtBQUs7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCw0QkFBNEI7QUFDNUIsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSxJQUFxQztBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLFVBQVUsS0FBcUM7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUIsc0JBQXNCO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBVSxJQUFxQztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHFCQUFxQiwyQkFBMkI7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNLEtBQXFDLDRGQUE0RixTQUFNO0FBQzdJO0FBQ0E7O0FBRUEsbUJBQW1CLGdDQUFnQztBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUIsZ0NBQWdDO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvcHJvcC10eXBlcy9mYWN0b3J5V2l0aFR5cGVDaGVja2Vycy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLXByZXNlbnQsIEZhY2Vib29rLCBJbmMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVhY3RJcyA9IHJlcXVpcmUoJ3JlYWN0LWlzJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xuXG52YXIgUmVhY3RQcm9wVHlwZXNTZWNyZXQgPSByZXF1aXJlKCcuL2xpYi9SZWFjdFByb3BUeXBlc1NlY3JldCcpO1xudmFyIGNoZWNrUHJvcFR5cGVzID0gcmVxdWlyZSgnLi9jaGVja1Byb3BUeXBlcycpO1xuXG52YXIgaGFzID0gRnVuY3Rpb24uY2FsbC5iaW5kKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkpO1xudmFyIHByaW50V2FybmluZyA9IGZ1bmN0aW9uKCkge307XG5cbmlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gIHByaW50V2FybmluZyA9IGZ1bmN0aW9uKHRleHQpIHtcbiAgICB2YXIgbWVzc2FnZSA9ICdXYXJuaW5nOiAnICsgdGV4dDtcbiAgICBpZiAodHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgLy8gLS0tIFdlbGNvbWUgdG8gZGVidWdnaW5nIFJlYWN0IC0tLVxuICAgICAgLy8gVGhpcyBlcnJvciB3YXMgdGhyb3duIGFzIGEgY29udmVuaWVuY2Ugc28gdGhhdCB5b3UgY2FuIHVzZSB0aGlzIHN0YWNrXG4gICAgICAvLyB0byBmaW5kIHRoZSBjYWxsc2l0ZSB0aGF0IGNhdXNlZCB0aGlzIHdhcm5pbmcgdG8gZmlyZS5cbiAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICB9IGNhdGNoICh4KSB7fVxuICB9O1xufVxuXG5mdW5jdGlvbiBlbXB0eUZ1bmN0aW9uVGhhdFJldHVybnNOdWxsKCkge1xuICByZXR1cm4gbnVsbDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpc1ZhbGlkRWxlbWVudCwgdGhyb3dPbkRpcmVjdEFjY2Vzcykge1xuICAvKiBnbG9iYWwgU3ltYm9sICovXG4gIHZhciBJVEVSQVRPUl9TWU1CT0wgPSB0eXBlb2YgU3ltYm9sID09PSAnZnVuY3Rpb24nICYmIFN5bWJvbC5pdGVyYXRvcjtcbiAgdmFyIEZBVVhfSVRFUkFUT1JfU1lNQk9MID0gJ0BAaXRlcmF0b3InOyAvLyBCZWZvcmUgU3ltYm9sIHNwZWMuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGl0ZXJhdG9yIG1ldGhvZCBmdW5jdGlvbiBjb250YWluZWQgb24gdGhlIGl0ZXJhYmxlIG9iamVjdC5cbiAgICpcbiAgICogQmUgc3VyZSB0byBpbnZva2UgdGhlIGZ1bmN0aW9uIHdpdGggdGhlIGl0ZXJhYmxlIGFzIGNvbnRleHQ6XG4gICAqXG4gICAqICAgICB2YXIgaXRlcmF0b3JGbiA9IGdldEl0ZXJhdG9yRm4obXlJdGVyYWJsZSk7XG4gICAqICAgICBpZiAoaXRlcmF0b3JGbikge1xuICAgKiAgICAgICB2YXIgaXRlcmF0b3IgPSBpdGVyYXRvckZuLmNhbGwobXlJdGVyYWJsZSk7XG4gICAqICAgICAgIC4uLlxuICAgKiAgICAgfVxuICAgKlxuICAgKiBAcGFyYW0gez9vYmplY3R9IG1heWJlSXRlcmFibGVcbiAgICogQHJldHVybiB7P2Z1bmN0aW9ufVxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0SXRlcmF0b3JGbihtYXliZUl0ZXJhYmxlKSB7XG4gICAgdmFyIGl0ZXJhdG9yRm4gPSBtYXliZUl0ZXJhYmxlICYmIChJVEVSQVRPUl9TWU1CT0wgJiYgbWF5YmVJdGVyYWJsZVtJVEVSQVRPUl9TWU1CT0xdIHx8IG1heWJlSXRlcmFibGVbRkFVWF9JVEVSQVRPUl9TWU1CT0xdKTtcbiAgICBpZiAodHlwZW9mIGl0ZXJhdG9yRm4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiBpdGVyYXRvckZuO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb2xsZWN0aW9uIG9mIG1ldGhvZHMgdGhhdCBhbGxvdyBkZWNsYXJhdGlvbiBhbmQgdmFsaWRhdGlvbiBvZiBwcm9wcyB0aGF0IGFyZVxuICAgKiBzdXBwbGllZCB0byBSZWFjdCBjb21wb25lbnRzLiBFeGFtcGxlIHVzYWdlOlxuICAgKlxuICAgKiAgIHZhciBQcm9wcyA9IHJlcXVpcmUoJ1JlYWN0UHJvcFR5cGVzJyk7XG4gICAqICAgdmFyIE15QXJ0aWNsZSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcbiAgICogICAgIHByb3BUeXBlczoge1xuICAgKiAgICAgICAvLyBBbiBvcHRpb25hbCBzdHJpbmcgcHJvcCBuYW1lZCBcImRlc2NyaXB0aW9uXCIuXG4gICAqICAgICAgIGRlc2NyaXB0aW9uOiBQcm9wcy5zdHJpbmcsXG4gICAqXG4gICAqICAgICAgIC8vIEEgcmVxdWlyZWQgZW51bSBwcm9wIG5hbWVkIFwiY2F0ZWdvcnlcIi5cbiAgICogICAgICAgY2F0ZWdvcnk6IFByb3BzLm9uZU9mKFsnTmV3cycsJ1Bob3RvcyddKS5pc1JlcXVpcmVkLFxuICAgKlxuICAgKiAgICAgICAvLyBBIHByb3AgbmFtZWQgXCJkaWFsb2dcIiB0aGF0IHJlcXVpcmVzIGFuIGluc3RhbmNlIG9mIERpYWxvZy5cbiAgICogICAgICAgZGlhbG9nOiBQcm9wcy5pbnN0YW5jZU9mKERpYWxvZykuaXNSZXF1aXJlZFxuICAgKiAgICAgfSxcbiAgICogICAgIHJlbmRlcjogZnVuY3Rpb24oKSB7IC4uLiB9XG4gICAqICAgfSk7XG4gICAqXG4gICAqIEEgbW9yZSBmb3JtYWwgc3BlY2lmaWNhdGlvbiBvZiBob3cgdGhlc2UgbWV0aG9kcyBhcmUgdXNlZDpcbiAgICpcbiAgICogICB0eXBlIDo9IGFycmF5fGJvb2x8ZnVuY3xvYmplY3R8bnVtYmVyfHN0cmluZ3xvbmVPZihbLi4uXSl8aW5zdGFuY2VPZiguLi4pXG4gICAqICAgZGVjbCA6PSBSZWFjdFByb3BUeXBlcy57dHlwZX0oLmlzUmVxdWlyZWQpP1xuICAgKlxuICAgKiBFYWNoIGFuZCBldmVyeSBkZWNsYXJhdGlvbiBwcm9kdWNlcyBhIGZ1bmN0aW9uIHdpdGggdGhlIHNhbWUgc2lnbmF0dXJlLiBUaGlzXG4gICAqIGFsbG93cyB0aGUgY3JlYXRpb24gb2YgY3VzdG9tIHZhbGlkYXRpb24gZnVuY3Rpb25zLiBGb3IgZXhhbXBsZTpcbiAgICpcbiAgICogIHZhciBNeUxpbmsgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG4gICAqICAgIHByb3BUeXBlczoge1xuICAgKiAgICAgIC8vIEFuIG9wdGlvbmFsIHN0cmluZyBvciBVUkkgcHJvcCBuYW1lZCBcImhyZWZcIi5cbiAgICogICAgICBocmVmOiBmdW5jdGlvbihwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUpIHtcbiAgICogICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG4gICAqICAgICAgICBpZiAocHJvcFZhbHVlICE9IG51bGwgJiYgdHlwZW9mIHByb3BWYWx1ZSAhPT0gJ3N0cmluZycgJiZcbiAgICogICAgICAgICAgICAhKHByb3BWYWx1ZSBpbnN0YW5jZW9mIFVSSSkpIHtcbiAgICogICAgICAgICAgcmV0dXJuIG5ldyBFcnJvcihcbiAgICogICAgICAgICAgICAnRXhwZWN0ZWQgYSBzdHJpbmcgb3IgYW4gVVJJIGZvciAnICsgcHJvcE5hbWUgKyAnIGluICcgK1xuICAgKiAgICAgICAgICAgIGNvbXBvbmVudE5hbWVcbiAgICogICAgICAgICAgKTtcbiAgICogICAgICAgIH1cbiAgICogICAgICB9XG4gICAqICAgIH0sXG4gICAqICAgIHJlbmRlcjogZnVuY3Rpb24oKSB7Li4ufVxuICAgKiAgfSk7XG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cblxuICB2YXIgQU5PTllNT1VTID0gJzw8YW5vbnltb3VzPj4nO1xuXG4gIC8vIEltcG9ydGFudCFcbiAgLy8gS2VlcCB0aGlzIGxpc3QgaW4gc3luYyB3aXRoIHByb2R1Y3Rpb24gdmVyc2lvbiBpbiBgLi9mYWN0b3J5V2l0aFRocm93aW5nU2hpbXMuanNgLlxuICB2YXIgUmVhY3RQcm9wVHlwZXMgPSB7XG4gICAgYXJyYXk6IGNyZWF0ZVByaW1pdGl2ZVR5cGVDaGVja2VyKCdhcnJheScpLFxuICAgIGJvb2w6IGNyZWF0ZVByaW1pdGl2ZVR5cGVDaGVja2VyKCdib29sZWFuJyksXG4gICAgZnVuYzogY3JlYXRlUHJpbWl0aXZlVHlwZUNoZWNrZXIoJ2Z1bmN0aW9uJyksXG4gICAgbnVtYmVyOiBjcmVhdGVQcmltaXRpdmVUeXBlQ2hlY2tlcignbnVtYmVyJyksXG4gICAgb2JqZWN0OiBjcmVhdGVQcmltaXRpdmVUeXBlQ2hlY2tlcignb2JqZWN0JyksXG4gICAgc3RyaW5nOiBjcmVhdGVQcmltaXRpdmVUeXBlQ2hlY2tlcignc3RyaW5nJyksXG4gICAgc3ltYm9sOiBjcmVhdGVQcmltaXRpdmVUeXBlQ2hlY2tlcignc3ltYm9sJyksXG5cbiAgICBhbnk6IGNyZWF0ZUFueVR5cGVDaGVja2VyKCksXG4gICAgYXJyYXlPZjogY3JlYXRlQXJyYXlPZlR5cGVDaGVja2VyLFxuICAgIGVsZW1lbnQ6IGNyZWF0ZUVsZW1lbnRUeXBlQ2hlY2tlcigpLFxuICAgIGVsZW1lbnRUeXBlOiBjcmVhdGVFbGVtZW50VHlwZVR5cGVDaGVja2VyKCksXG4gICAgaW5zdGFuY2VPZjogY3JlYXRlSW5zdGFuY2VUeXBlQ2hlY2tlcixcbiAgICBub2RlOiBjcmVhdGVOb2RlQ2hlY2tlcigpLFxuICAgIG9iamVjdE9mOiBjcmVhdGVPYmplY3RPZlR5cGVDaGVja2VyLFxuICAgIG9uZU9mOiBjcmVhdGVFbnVtVHlwZUNoZWNrZXIsXG4gICAgb25lT2ZUeXBlOiBjcmVhdGVVbmlvblR5cGVDaGVja2VyLFxuICAgIHNoYXBlOiBjcmVhdGVTaGFwZVR5cGVDaGVja2VyLFxuICAgIGV4YWN0OiBjcmVhdGVTdHJpY3RTaGFwZVR5cGVDaGVja2VyLFxuICB9O1xuXG4gIC8qKlxuICAgKiBpbmxpbmVkIE9iamVjdC5pcyBwb2x5ZmlsbCB0byBhdm9pZCByZXF1aXJpbmcgY29uc3VtZXJzIHNoaXAgdGhlaXIgb3duXG4gICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9pc1xuICAgKi9cbiAgLyplc2xpbnQtZGlzYWJsZSBuby1zZWxmLWNvbXBhcmUqL1xuICBmdW5jdGlvbiBpcyh4LCB5KSB7XG4gICAgLy8gU2FtZVZhbHVlIGFsZ29yaXRobVxuICAgIGlmICh4ID09PSB5KSB7XG4gICAgICAvLyBTdGVwcyAxLTUsIDctMTBcbiAgICAgIC8vIFN0ZXBzIDYuYi02LmU6ICswICE9IC0wXG4gICAgICByZXR1cm4geCAhPT0gMCB8fCAxIC8geCA9PT0gMSAvIHk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFN0ZXAgNi5hOiBOYU4gPT0gTmFOXG4gICAgICByZXR1cm4geCAhPT0geCAmJiB5ICE9PSB5O1xuICAgIH1cbiAgfVxuICAvKmVzbGludC1lbmFibGUgbm8tc2VsZi1jb21wYXJlKi9cblxuICAvKipcbiAgICogV2UgdXNlIGFuIEVycm9yLWxpa2Ugb2JqZWN0IGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IGFzIHBlb3BsZSBtYXkgY2FsbFxuICAgKiBQcm9wVHlwZXMgZGlyZWN0bHkgYW5kIGluc3BlY3QgdGhlaXIgb3V0cHV0LiBIb3dldmVyLCB3ZSBkb24ndCB1c2UgcmVhbFxuICAgKiBFcnJvcnMgYW55bW9yZS4gV2UgZG9uJ3QgaW5zcGVjdCB0aGVpciBzdGFjayBhbnl3YXksIGFuZCBjcmVhdGluZyB0aGVtXG4gICAqIGlzIHByb2hpYml0aXZlbHkgZXhwZW5zaXZlIGlmIHRoZXkgYXJlIGNyZWF0ZWQgdG9vIG9mdGVuLCBzdWNoIGFzIHdoYXRcbiAgICogaGFwcGVucyBpbiBvbmVPZlR5cGUoKSBmb3IgYW55IHR5cGUgYmVmb3JlIHRoZSBvbmUgdGhhdCBtYXRjaGVkLlxuICAgKi9cbiAgZnVuY3Rpb24gUHJvcFR5cGVFcnJvcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICB0aGlzLnN0YWNrID0gJyc7XG4gIH1cbiAgLy8gTWFrZSBgaW5zdGFuY2VvZiBFcnJvcmAgc3RpbGwgd29yayBmb3IgcmV0dXJuZWQgZXJyb3JzLlxuICBQcm9wVHlwZUVycm9yLnByb3RvdHlwZSA9IEVycm9yLnByb3RvdHlwZTtcblxuICBmdW5jdGlvbiBjcmVhdGVDaGFpbmFibGVUeXBlQ2hlY2tlcih2YWxpZGF0ZSkge1xuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICB2YXIgbWFudWFsUHJvcFR5cGVDYWxsQ2FjaGUgPSB7fTtcbiAgICAgIHZhciBtYW51YWxQcm9wVHlwZVdhcm5pbmdDb3VudCA9IDA7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNoZWNrVHlwZShpc1JlcXVpcmVkLCBwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUsIHNlY3JldCkge1xuICAgICAgY29tcG9uZW50TmFtZSA9IGNvbXBvbmVudE5hbWUgfHwgQU5PTllNT1VTO1xuICAgICAgcHJvcEZ1bGxOYW1lID0gcHJvcEZ1bGxOYW1lIHx8IHByb3BOYW1lO1xuXG4gICAgICBpZiAoc2VjcmV0ICE9PSBSZWFjdFByb3BUeXBlc1NlY3JldCkge1xuICAgICAgICBpZiAodGhyb3dPbkRpcmVjdEFjY2Vzcykge1xuICAgICAgICAgIC8vIE5ldyBiZWhhdmlvciBvbmx5IGZvciB1c2VycyBvZiBgcHJvcC10eXBlc2AgcGFja2FnZVxuICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnQ2FsbGluZyBQcm9wVHlwZXMgdmFsaWRhdG9ycyBkaXJlY3RseSBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBgcHJvcC10eXBlc2AgcGFja2FnZS4gJyArXG4gICAgICAgICAgICAnVXNlIGBQcm9wVHlwZXMuY2hlY2tQcm9wVHlwZXMoKWAgdG8gY2FsbCB0aGVtLiAnICtcbiAgICAgICAgICAgICdSZWFkIG1vcmUgYXQgaHR0cDovL2ZiLm1lL3VzZS1jaGVjay1wcm9wLXR5cGVzJ1xuICAgICAgICAgICk7XG4gICAgICAgICAgZXJyLm5hbWUgPSAnSW52YXJpYW50IFZpb2xhdGlvbic7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9IGVsc2UgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiYgdHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgLy8gT2xkIGJlaGF2aW9yIGZvciBwZW9wbGUgdXNpbmcgUmVhY3QuUHJvcFR5cGVzXG4gICAgICAgICAgdmFyIGNhY2hlS2V5ID0gY29tcG9uZW50TmFtZSArICc6JyArIHByb3BOYW1lO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICFtYW51YWxQcm9wVHlwZUNhbGxDYWNoZVtjYWNoZUtleV0gJiZcbiAgICAgICAgICAgIC8vIEF2b2lkIHNwYW1taW5nIHRoZSBjb25zb2xlIGJlY2F1c2UgdGhleSBhcmUgb2Z0ZW4gbm90IGFjdGlvbmFibGUgZXhjZXB0IGZvciBsaWIgYXV0aG9yc1xuICAgICAgICAgICAgbWFudWFsUHJvcFR5cGVXYXJuaW5nQ291bnQgPCAzXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBwcmludFdhcm5pbmcoXG4gICAgICAgICAgICAgICdZb3UgYXJlIG1hbnVhbGx5IGNhbGxpbmcgYSBSZWFjdC5Qcm9wVHlwZXMgdmFsaWRhdGlvbiAnICtcbiAgICAgICAgICAgICAgJ2Z1bmN0aW9uIGZvciB0aGUgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBwcm9wIG9uIGAnICsgY29tcG9uZW50TmFtZSAgKyAnYC4gVGhpcyBpcyBkZXByZWNhdGVkICcgK1xuICAgICAgICAgICAgICAnYW5kIHdpbGwgdGhyb3cgaW4gdGhlIHN0YW5kYWxvbmUgYHByb3AtdHlwZXNgIHBhY2thZ2UuICcgK1xuICAgICAgICAgICAgICAnWW91IG1heSBiZSBzZWVpbmcgdGhpcyB3YXJuaW5nIGR1ZSB0byBhIHRoaXJkLXBhcnR5IFByb3BUeXBlcyAnICtcbiAgICAgICAgICAgICAgJ2xpYnJhcnkuIFNlZSBodHRwczovL2ZiLm1lL3JlYWN0LXdhcm5pbmctZG9udC1jYWxsLXByb3B0eXBlcyAnICsgJ2ZvciBkZXRhaWxzLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBtYW51YWxQcm9wVHlwZUNhbGxDYWNoZVtjYWNoZUtleV0gPSB0cnVlO1xuICAgICAgICAgICAgbWFudWFsUHJvcFR5cGVXYXJuaW5nQ291bnQrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChwcm9wc1twcm9wTmFtZV0gPT0gbnVsbCkge1xuICAgICAgICBpZiAoaXNSZXF1aXJlZCkge1xuICAgICAgICAgIGlmIChwcm9wc1twcm9wTmFtZV0gPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJvcFR5cGVFcnJvcignVGhlICcgKyBsb2NhdGlvbiArICcgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBpcyBtYXJrZWQgYXMgcmVxdWlyZWQgJyArICgnaW4gYCcgKyBjb21wb25lbnROYW1lICsgJ2AsIGJ1dCBpdHMgdmFsdWUgaXMgYG51bGxgLicpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBQcm9wVHlwZUVycm9yKCdUaGUgJyArIGxvY2F0aW9uICsgJyBgJyArIHByb3BGdWxsTmFtZSArICdgIGlzIG1hcmtlZCBhcyByZXF1aXJlZCBpbiAnICsgKCdgJyArIGNvbXBvbmVudE5hbWUgKyAnYCwgYnV0IGl0cyB2YWx1ZSBpcyBgdW5kZWZpbmVkYC4nKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdmFsaWRhdGUocHJvcHMsIHByb3BOYW1lLCBjb21wb25lbnROYW1lLCBsb2NhdGlvbiwgcHJvcEZ1bGxOYW1lKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY2hhaW5lZENoZWNrVHlwZSA9IGNoZWNrVHlwZS5iaW5kKG51bGwsIGZhbHNlKTtcbiAgICBjaGFpbmVkQ2hlY2tUeXBlLmlzUmVxdWlyZWQgPSBjaGVja1R5cGUuYmluZChudWxsLCB0cnVlKTtcblxuICAgIHJldHVybiBjaGFpbmVkQ2hlY2tUeXBlO1xuICB9XG5cbiAgZnVuY3Rpb24gY3JlYXRlUHJpbWl0aXZlVHlwZUNoZWNrZXIoZXhwZWN0ZWRUeXBlKSB7XG4gICAgZnVuY3Rpb24gdmFsaWRhdGUocHJvcHMsIHByb3BOYW1lLCBjb21wb25lbnROYW1lLCBsb2NhdGlvbiwgcHJvcEZ1bGxOYW1lLCBzZWNyZXQpIHtcbiAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG4gICAgICB2YXIgcHJvcFR5cGUgPSBnZXRQcm9wVHlwZShwcm9wVmFsdWUpO1xuICAgICAgaWYgKHByb3BUeXBlICE9PSBleHBlY3RlZFR5cGUpIHtcbiAgICAgICAgLy8gYHByb3BWYWx1ZWAgYmVpbmcgaW5zdGFuY2Ugb2YsIHNheSwgZGF0ZS9yZWdleHAsIHBhc3MgdGhlICdvYmplY3QnXG4gICAgICAgIC8vIGNoZWNrLCBidXQgd2UgY2FuIG9mZmVyIGEgbW9yZSBwcmVjaXNlIGVycm9yIG1lc3NhZ2UgaGVyZSByYXRoZXIgdGhhblxuICAgICAgICAvLyAnb2YgdHlwZSBgb2JqZWN0YCcuXG4gICAgICAgIHZhciBwcmVjaXNlVHlwZSA9IGdldFByZWNpc2VUeXBlKHByb3BWYWx1ZSk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9wVHlwZUVycm9yKCdJbnZhbGlkICcgKyBsb2NhdGlvbiArICcgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBvZiB0eXBlICcgKyAoJ2AnICsgcHJlY2lzZVR5cGUgKyAnYCBzdXBwbGllZCB0byBgJyArIGNvbXBvbmVudE5hbWUgKyAnYCwgZXhwZWN0ZWQgJykgKyAoJ2AnICsgZXhwZWN0ZWRUeXBlICsgJ2AuJykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVDaGFpbmFibGVUeXBlQ2hlY2tlcih2YWxpZGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVBbnlUeXBlQ2hlY2tlcigpIHtcbiAgICByZXR1cm4gY3JlYXRlQ2hhaW5hYmxlVHlwZUNoZWNrZXIoZW1wdHlGdW5jdGlvblRoYXRSZXR1cm5zTnVsbCk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVBcnJheU9mVHlwZUNoZWNrZXIodHlwZUNoZWNrZXIpIHtcbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdHlwZUNoZWNrZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9wVHlwZUVycm9yKCdQcm9wZXJ0eSBgJyArIHByb3BGdWxsTmFtZSArICdgIG9mIGNvbXBvbmVudCBgJyArIGNvbXBvbmVudE5hbWUgKyAnYCBoYXMgaW52YWxpZCBQcm9wVHlwZSBub3RhdGlvbiBpbnNpZGUgYXJyYXlPZi4nKTtcbiAgICAgIH1cbiAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkocHJvcFZhbHVlKSkge1xuICAgICAgICB2YXIgcHJvcFR5cGUgPSBnZXRQcm9wVHlwZShwcm9wVmFsdWUpO1xuICAgICAgICByZXR1cm4gbmV3IFByb3BUeXBlRXJyb3IoJ0ludmFsaWQgJyArIGxvY2F0aW9uICsgJyBgJyArIHByb3BGdWxsTmFtZSArICdgIG9mIHR5cGUgJyArICgnYCcgKyBwcm9wVHlwZSArICdgIHN1cHBsaWVkIHRvIGAnICsgY29tcG9uZW50TmFtZSArICdgLCBleHBlY3RlZCBhbiBhcnJheS4nKSk7XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BWYWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZXJyb3IgPSB0eXBlQ2hlY2tlcihwcm9wVmFsdWUsIGksIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUgKyAnWycgKyBpICsgJ10nLCBSZWFjdFByb3BUeXBlc1NlY3JldCk7XG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIGVycm9yO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZUNoYWluYWJsZVR5cGVDaGVja2VyKHZhbGlkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnRUeXBlQ2hlY2tlcigpIHtcbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUpIHtcbiAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG4gICAgICBpZiAoIWlzVmFsaWRFbGVtZW50KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgdmFyIHByb3BUeXBlID0gZ2V0UHJvcFR5cGUocHJvcFZhbHVlKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9wVHlwZUVycm9yKCdJbnZhbGlkICcgKyBsb2NhdGlvbiArICcgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBvZiB0eXBlICcgKyAoJ2AnICsgcHJvcFR5cGUgKyAnYCBzdXBwbGllZCB0byBgJyArIGNvbXBvbmVudE5hbWUgKyAnYCwgZXhwZWN0ZWQgYSBzaW5nbGUgUmVhY3RFbGVtZW50LicpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlQ2hhaW5hYmxlVHlwZUNoZWNrZXIodmFsaWRhdGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudFR5cGVUeXBlQ2hlY2tlcigpIHtcbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUpIHtcbiAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG4gICAgICBpZiAoIVJlYWN0SXMuaXNWYWxpZEVsZW1lbnRUeXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgdmFyIHByb3BUeXBlID0gZ2V0UHJvcFR5cGUocHJvcFZhbHVlKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9wVHlwZUVycm9yKCdJbnZhbGlkICcgKyBsb2NhdGlvbiArICcgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBvZiB0eXBlICcgKyAoJ2AnICsgcHJvcFR5cGUgKyAnYCBzdXBwbGllZCB0byBgJyArIGNvbXBvbmVudE5hbWUgKyAnYCwgZXhwZWN0ZWQgYSBzaW5nbGUgUmVhY3RFbGVtZW50IHR5cGUuJykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVDaGFpbmFibGVUeXBlQ2hlY2tlcih2YWxpZGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVJbnN0YW5jZVR5cGVDaGVja2VyKGV4cGVjdGVkQ2xhc3MpIHtcbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUpIHtcbiAgICAgIGlmICghKHByb3BzW3Byb3BOYW1lXSBpbnN0YW5jZW9mIGV4cGVjdGVkQ2xhc3MpKSB7XG4gICAgICAgIHZhciBleHBlY3RlZENsYXNzTmFtZSA9IGV4cGVjdGVkQ2xhc3MubmFtZSB8fCBBTk9OWU1PVVM7XG4gICAgICAgIHZhciBhY3R1YWxDbGFzc05hbWUgPSBnZXRDbGFzc05hbWUocHJvcHNbcHJvcE5hbWVdKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9wVHlwZUVycm9yKCdJbnZhbGlkICcgKyBsb2NhdGlvbiArICcgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBvZiB0eXBlICcgKyAoJ2AnICsgYWN0dWFsQ2xhc3NOYW1lICsgJ2Agc3VwcGxpZWQgdG8gYCcgKyBjb21wb25lbnROYW1lICsgJ2AsIGV4cGVjdGVkICcpICsgKCdpbnN0YW5jZSBvZiBgJyArIGV4cGVjdGVkQ2xhc3NOYW1lICsgJ2AuJykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVDaGFpbmFibGVUeXBlQ2hlY2tlcih2YWxpZGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVFbnVtVHlwZUNoZWNrZXIoZXhwZWN0ZWRWYWx1ZXMpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZXhwZWN0ZWRWYWx1ZXMpKSB7XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBwcmludFdhcm5pbmcoXG4gICAgICAgICAgICAnSW52YWxpZCBhcmd1bWVudHMgc3VwcGxpZWQgdG8gb25lT2YsIGV4cGVjdGVkIGFuIGFycmF5LCBnb3QgJyArIGFyZ3VtZW50cy5sZW5ndGggKyAnIGFyZ3VtZW50cy4gJyArXG4gICAgICAgICAgICAnQSBjb21tb24gbWlzdGFrZSBpcyB0byB3cml0ZSBvbmVPZih4LCB5LCB6KSBpbnN0ZWFkIG9mIG9uZU9mKFt4LCB5LCB6XSkuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcHJpbnRXYXJuaW5nKCdJbnZhbGlkIGFyZ3VtZW50IHN1cHBsaWVkIHRvIG9uZU9mLCBleHBlY3RlZCBhbiBhcnJheS4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGVtcHR5RnVuY3Rpb25UaGF0UmV0dXJuc051bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmFsaWRhdGUocHJvcHMsIHByb3BOYW1lLCBjb21wb25lbnROYW1lLCBsb2NhdGlvbiwgcHJvcEZ1bGxOYW1lKSB7XG4gICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHBlY3RlZFZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaXMocHJvcFZhbHVlLCBleHBlY3RlZFZhbHVlc1tpXSkpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgdmFsdWVzU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkoZXhwZWN0ZWRWYWx1ZXMsIGZ1bmN0aW9uIHJlcGxhY2VyKGtleSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIHR5cGUgPSBnZXRQcmVjaXNlVHlwZSh2YWx1ZSk7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBQcm9wVHlwZUVycm9yKCdJbnZhbGlkICcgKyBsb2NhdGlvbiArICcgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBvZiB2YWx1ZSBgJyArIFN0cmluZyhwcm9wVmFsdWUpICsgJ2AgJyArICgnc3VwcGxpZWQgdG8gYCcgKyBjb21wb25lbnROYW1lICsgJ2AsIGV4cGVjdGVkIG9uZSBvZiAnICsgdmFsdWVzU3RyaW5nICsgJy4nKSk7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVDaGFpbmFibGVUeXBlQ2hlY2tlcih2YWxpZGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVPYmplY3RPZlR5cGVDaGVja2VyKHR5cGVDaGVja2VyKSB7XG4gICAgZnVuY3Rpb24gdmFsaWRhdGUocHJvcHMsIHByb3BOYW1lLCBjb21wb25lbnROYW1lLCBsb2NhdGlvbiwgcHJvcEZ1bGxOYW1lKSB7XG4gICAgICBpZiAodHlwZW9mIHR5cGVDaGVja2VyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvcFR5cGVFcnJvcignUHJvcGVydHkgYCcgKyBwcm9wRnVsbE5hbWUgKyAnYCBvZiBjb21wb25lbnQgYCcgKyBjb21wb25lbnROYW1lICsgJ2AgaGFzIGludmFsaWQgUHJvcFR5cGUgbm90YXRpb24gaW5zaWRlIG9iamVjdE9mLicpO1xuICAgICAgfVxuICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcbiAgICAgIHZhciBwcm9wVHlwZSA9IGdldFByb3BUeXBlKHByb3BWYWx1ZSk7XG4gICAgICBpZiAocHJvcFR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvcFR5cGVFcnJvcignSW52YWxpZCAnICsgbG9jYXRpb24gKyAnIGAnICsgcHJvcEZ1bGxOYW1lICsgJ2Agb2YgdHlwZSAnICsgKCdgJyArIHByb3BUeXBlICsgJ2Agc3VwcGxpZWQgdG8gYCcgKyBjb21wb25lbnROYW1lICsgJ2AsIGV4cGVjdGVkIGFuIG9iamVjdC4nKSk7XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBrZXkgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgIGlmIChoYXMocHJvcFZhbHVlLCBrZXkpKSB7XG4gICAgICAgICAgdmFyIGVycm9yID0gdHlwZUNoZWNrZXIocHJvcFZhbHVlLCBrZXksIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUgKyAnLicgKyBrZXksIFJlYWN0UHJvcFR5cGVzU2VjcmV0KTtcbiAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVDaGFpbmFibGVUeXBlQ2hlY2tlcih2YWxpZGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVVbmlvblR5cGVDaGVja2VyKGFycmF5T2ZUeXBlQ2hlY2tlcnMpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyYXlPZlR5cGVDaGVja2VycykpIHtcbiAgICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgPyBwcmludFdhcm5pbmcoJ0ludmFsaWQgYXJndW1lbnQgc3VwcGxpZWQgdG8gb25lT2ZUeXBlLCBleHBlY3RlZCBhbiBpbnN0YW5jZSBvZiBhcnJheS4nKSA6IHZvaWQgMDtcbiAgICAgIHJldHVybiBlbXB0eUZ1bmN0aW9uVGhhdFJldHVybnNOdWxsO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXlPZlR5cGVDaGVja2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoZWNrZXIgPSBhcnJheU9mVHlwZUNoZWNrZXJzW2ldO1xuICAgICAgaWYgKHR5cGVvZiBjaGVja2VyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHByaW50V2FybmluZyhcbiAgICAgICAgICAnSW52YWxpZCBhcmd1bWVudCBzdXBwbGllZCB0byBvbmVPZlR5cGUuIEV4cGVjdGVkIGFuIGFycmF5IG9mIGNoZWNrIGZ1bmN0aW9ucywgYnV0ICcgK1xuICAgICAgICAgICdyZWNlaXZlZCAnICsgZ2V0UG9zdGZpeEZvclR5cGVXYXJuaW5nKGNoZWNrZXIpICsgJyBhdCBpbmRleCAnICsgaSArICcuJ1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4gZW1wdHlGdW5jdGlvblRoYXRSZXR1cm5zTnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXlPZlR5cGVDaGVja2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2hlY2tlciA9IGFycmF5T2ZUeXBlQ2hlY2tlcnNbaV07XG4gICAgICAgIGlmIChjaGVja2VyKHByb3BzLCBwcm9wTmFtZSwgY29tcG9uZW50TmFtZSwgbG9jYXRpb24sIHByb3BGdWxsTmFtZSwgUmVhY3RQcm9wVHlwZXNTZWNyZXQpID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IFByb3BUeXBlRXJyb3IoJ0ludmFsaWQgJyArIGxvY2F0aW9uICsgJyBgJyArIHByb3BGdWxsTmFtZSArICdgIHN1cHBsaWVkIHRvICcgKyAoJ2AnICsgY29tcG9uZW50TmFtZSArICdgLicpKTtcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZUNoYWluYWJsZVR5cGVDaGVja2VyKHZhbGlkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZU5vZGVDaGVja2VyKCkge1xuICAgIGZ1bmN0aW9uIHZhbGlkYXRlKHByb3BzLCBwcm9wTmFtZSwgY29tcG9uZW50TmFtZSwgbG9jYXRpb24sIHByb3BGdWxsTmFtZSkge1xuICAgICAgaWYgKCFpc05vZGUocHJvcHNbcHJvcE5hbWVdKSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb3BUeXBlRXJyb3IoJ0ludmFsaWQgJyArIGxvY2F0aW9uICsgJyBgJyArIHByb3BGdWxsTmFtZSArICdgIHN1cHBsaWVkIHRvICcgKyAoJ2AnICsgY29tcG9uZW50TmFtZSArICdgLCBleHBlY3RlZCBhIFJlYWN0Tm9kZS4nKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZUNoYWluYWJsZVR5cGVDaGVja2VyKHZhbGlkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZVNoYXBlVHlwZUNoZWNrZXIoc2hhcGVUeXBlcykge1xuICAgIGZ1bmN0aW9uIHZhbGlkYXRlKHByb3BzLCBwcm9wTmFtZSwgY29tcG9uZW50TmFtZSwgbG9jYXRpb24sIHByb3BGdWxsTmFtZSkge1xuICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcbiAgICAgIHZhciBwcm9wVHlwZSA9IGdldFByb3BUeXBlKHByb3BWYWx1ZSk7XG4gICAgICBpZiAocHJvcFR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvcFR5cGVFcnJvcignSW52YWxpZCAnICsgbG9jYXRpb24gKyAnIGAnICsgcHJvcEZ1bGxOYW1lICsgJ2Agb2YgdHlwZSBgJyArIHByb3BUeXBlICsgJ2AgJyArICgnc3VwcGxpZWQgdG8gYCcgKyBjb21wb25lbnROYW1lICsgJ2AsIGV4cGVjdGVkIGBvYmplY3RgLicpKTtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGtleSBpbiBzaGFwZVR5cGVzKSB7XG4gICAgICAgIHZhciBjaGVja2VyID0gc2hhcGVUeXBlc1trZXldO1xuICAgICAgICBpZiAoIWNoZWNrZXIpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXJyb3IgPSBjaGVja2VyKHByb3BWYWx1ZSwga2V5LCBjb21wb25lbnROYW1lLCBsb2NhdGlvbiwgcHJvcEZ1bGxOYW1lICsgJy4nICsga2V5LCBSZWFjdFByb3BUeXBlc1NlY3JldCk7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVDaGFpbmFibGVUeXBlQ2hlY2tlcih2YWxpZGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVTdHJpY3RTaGFwZVR5cGVDaGVja2VyKHNoYXBlVHlwZXMpIHtcbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShwcm9wcywgcHJvcE5hbWUsIGNvbXBvbmVudE5hbWUsIGxvY2F0aW9uLCBwcm9wRnVsbE5hbWUpIHtcbiAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG4gICAgICB2YXIgcHJvcFR5cGUgPSBnZXRQcm9wVHlwZShwcm9wVmFsdWUpO1xuICAgICAgaWYgKHByb3BUeXBlICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gbmV3IFByb3BUeXBlRXJyb3IoJ0ludmFsaWQgJyArIGxvY2F0aW9uICsgJyBgJyArIHByb3BGdWxsTmFtZSArICdgIG9mIHR5cGUgYCcgKyBwcm9wVHlwZSArICdgICcgKyAoJ3N1cHBsaWVkIHRvIGAnICsgY29tcG9uZW50TmFtZSArICdgLCBleHBlY3RlZCBgb2JqZWN0YC4nKSk7XG4gICAgICB9XG4gICAgICAvLyBXZSBuZWVkIHRvIGNoZWNrIGFsbCBrZXlzIGluIGNhc2Ugc29tZSBhcmUgcmVxdWlyZWQgYnV0IG1pc3NpbmcgZnJvbVxuICAgICAgLy8gcHJvcHMuXG4gICAgICB2YXIgYWxsS2V5cyA9IGFzc2lnbih7fSwgcHJvcHNbcHJvcE5hbWVdLCBzaGFwZVR5cGVzKTtcbiAgICAgIGZvciAodmFyIGtleSBpbiBhbGxLZXlzKSB7XG4gICAgICAgIHZhciBjaGVja2VyID0gc2hhcGVUeXBlc1trZXldO1xuICAgICAgICBpZiAoIWNoZWNrZXIpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFByb3BUeXBlRXJyb3IoXG4gICAgICAgICAgICAnSW52YWxpZCAnICsgbG9jYXRpb24gKyAnIGAnICsgcHJvcEZ1bGxOYW1lICsgJ2Aga2V5IGAnICsga2V5ICsgJ2Agc3VwcGxpZWQgdG8gYCcgKyBjb21wb25lbnROYW1lICsgJ2AuJyArXG4gICAgICAgICAgICAnXFxuQmFkIG9iamVjdDogJyArIEpTT04uc3RyaW5naWZ5KHByb3BzW3Byb3BOYW1lXSwgbnVsbCwgJyAgJykgK1xuICAgICAgICAgICAgJ1xcblZhbGlkIGtleXM6ICcgKyAgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXMoc2hhcGVUeXBlcyksIG51bGwsICcgICcpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXJyb3IgPSBjaGVja2VyKHByb3BWYWx1ZSwga2V5LCBjb21wb25lbnROYW1lLCBsb2NhdGlvbiwgcHJvcEZ1bGxOYW1lICsgJy4nICsga2V5LCBSZWFjdFByb3BUeXBlc1NlY3JldCk7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNyZWF0ZUNoYWluYWJsZVR5cGVDaGVja2VyKHZhbGlkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzTm9kZShwcm9wVmFsdWUpIHtcbiAgICBzd2l0Y2ggKHR5cGVvZiBwcm9wVmFsdWUpIHtcbiAgICAgIGNhc2UgJ251bWJlcic6XG4gICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdib29sZWFuJzpcbiAgICAgICAgcmV0dXJuICFwcm9wVmFsdWU7XG4gICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIHByb3BWYWx1ZS5ldmVyeShpc05vZGUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9wVmFsdWUgPT09IG51bGwgfHwgaXNWYWxpZEVsZW1lbnQocHJvcFZhbHVlKSkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGl0ZXJhdG9yRm4gPSBnZXRJdGVyYXRvckZuKHByb3BWYWx1ZSk7XG4gICAgICAgIGlmIChpdGVyYXRvckZuKSB7XG4gICAgICAgICAgdmFyIGl0ZXJhdG9yID0gaXRlcmF0b3JGbi5jYWxsKHByb3BWYWx1ZSk7XG4gICAgICAgICAgdmFyIHN0ZXA7XG4gICAgICAgICAgaWYgKGl0ZXJhdG9yRm4gIT09IHByb3BWYWx1ZS5lbnRyaWVzKSB7XG4gICAgICAgICAgICB3aGlsZSAoIShzdGVwID0gaXRlcmF0b3IubmV4dCgpKS5kb25lKSB7XG4gICAgICAgICAgICAgIGlmICghaXNOb2RlKHN0ZXAudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEl0ZXJhdG9yIHdpbGwgcHJvdmlkZSBlbnRyeSBbayx2XSB0dXBsZXMgcmF0aGVyIHRoYW4gdmFsdWVzLlxuICAgICAgICAgICAgd2hpbGUgKCEoc3RlcCA9IGl0ZXJhdG9yLm5leHQoKSkuZG9uZSkge1xuICAgICAgICAgICAgICB2YXIgZW50cnkgPSBzdGVwLnZhbHVlO1xuICAgICAgICAgICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWlzTm9kZShlbnRyeVsxXSkpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaXNTeW1ib2wocHJvcFR5cGUsIHByb3BWYWx1ZSkge1xuICAgIC8vIE5hdGl2ZSBTeW1ib2wuXG4gICAgaWYgKHByb3BUeXBlID09PSAnc3ltYm9sJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gZmFsc3kgdmFsdWUgY2FuJ3QgYmUgYSBTeW1ib2xcbiAgICBpZiAoIXByb3BWYWx1ZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIDE5LjQuMy41IFN5bWJvbC5wcm90b3R5cGVbQEB0b1N0cmluZ1RhZ10gPT09ICdTeW1ib2wnXG4gICAgaWYgKHByb3BWYWx1ZVsnQEB0b1N0cmluZ1RhZyddID09PSAnU3ltYm9sJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gRmFsbGJhY2sgZm9yIG5vbi1zcGVjIGNvbXBsaWFudCBTeW1ib2xzIHdoaWNoIGFyZSBwb2x5ZmlsbGVkLlxuICAgIGlmICh0eXBlb2YgU3ltYm9sID09PSAnZnVuY3Rpb24nICYmIHByb3BWYWx1ZSBpbnN0YW5jZW9mIFN5bWJvbCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gRXF1aXZhbGVudCBvZiBgdHlwZW9mYCBidXQgd2l0aCBzcGVjaWFsIGhhbmRsaW5nIGZvciBhcnJheSBhbmQgcmVnZXhwLlxuICBmdW5jdGlvbiBnZXRQcm9wVHlwZShwcm9wVmFsdWUpIHtcbiAgICB2YXIgcHJvcFR5cGUgPSB0eXBlb2YgcHJvcFZhbHVlO1xuICAgIGlmIChBcnJheS5pc0FycmF5KHByb3BWYWx1ZSkpIHtcbiAgICAgIHJldHVybiAnYXJyYXknO1xuICAgIH1cbiAgICBpZiAocHJvcFZhbHVlIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAvLyBPbGQgd2Via2l0cyAoYXQgbGVhc3QgdW50aWwgQW5kcm9pZCA0LjApIHJldHVybiAnZnVuY3Rpb24nIHJhdGhlciB0aGFuXG4gICAgICAvLyAnb2JqZWN0JyBmb3IgdHlwZW9mIGEgUmVnRXhwLiBXZSdsbCBub3JtYWxpemUgdGhpcyBoZXJlIHNvIHRoYXQgL2JsYS9cbiAgICAgIC8vIHBhc3NlcyBQcm9wVHlwZXMub2JqZWN0LlxuICAgICAgcmV0dXJuICdvYmplY3QnO1xuICAgIH1cbiAgICBpZiAoaXNTeW1ib2wocHJvcFR5cGUsIHByb3BWYWx1ZSkpIHtcbiAgICAgIHJldHVybiAnc3ltYm9sJztcbiAgICB9XG4gICAgcmV0dXJuIHByb3BUeXBlO1xuICB9XG5cbiAgLy8gVGhpcyBoYW5kbGVzIG1vcmUgdHlwZXMgdGhhbiBgZ2V0UHJvcFR5cGVgLiBPbmx5IHVzZWQgZm9yIGVycm9yIG1lc3NhZ2VzLlxuICAvLyBTZWUgYGNyZWF0ZVByaW1pdGl2ZVR5cGVDaGVja2VyYC5cbiAgZnVuY3Rpb24gZ2V0UHJlY2lzZVR5cGUocHJvcFZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiBwcm9wVmFsdWUgPT09ICd1bmRlZmluZWQnIHx8IHByb3BWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuICcnICsgcHJvcFZhbHVlO1xuICAgIH1cbiAgICB2YXIgcHJvcFR5cGUgPSBnZXRQcm9wVHlwZShwcm9wVmFsdWUpO1xuICAgIGlmIChwcm9wVHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmIChwcm9wVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgIHJldHVybiAnZGF0ZSc7XG4gICAgICB9IGVsc2UgaWYgKHByb3BWYWx1ZSBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICByZXR1cm4gJ3JlZ2V4cCc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwcm9wVHlwZTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYSBzdHJpbmcgdGhhdCBpcyBwb3N0Zml4ZWQgdG8gYSB3YXJuaW5nIGFib3V0IGFuIGludmFsaWQgdHlwZS5cbiAgLy8gRm9yIGV4YW1wbGUsIFwidW5kZWZpbmVkXCIgb3IgXCJvZiB0eXBlIGFycmF5XCJcbiAgZnVuY3Rpb24gZ2V0UG9zdGZpeEZvclR5cGVXYXJuaW5nKHZhbHVlKSB7XG4gICAgdmFyIHR5cGUgPSBnZXRQcmVjaXNlVHlwZSh2YWx1ZSk7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlICdhcnJheSc6XG4gICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICByZXR1cm4gJ2FuICcgKyB0eXBlO1xuICAgICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICBjYXNlICdkYXRlJzpcbiAgICAgIGNhc2UgJ3JlZ2V4cCc6XG4gICAgICAgIHJldHVybiAnYSAnICsgdHlwZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB0eXBlO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJldHVybnMgY2xhc3MgbmFtZSBvZiB0aGUgb2JqZWN0LCBpZiBhbnkuXG4gIGZ1bmN0aW9uIGdldENsYXNzTmFtZShwcm9wVmFsdWUpIHtcbiAgICBpZiAoIXByb3BWYWx1ZS5jb25zdHJ1Y3RvciB8fCAhcHJvcFZhbHVlLmNvbnN0cnVjdG9yLm5hbWUpIHtcbiAgICAgIHJldHVybiBBTk9OWU1PVVM7XG4gICAgfVxuICAgIHJldHVybiBwcm9wVmFsdWUuY29uc3RydWN0b3IubmFtZTtcbiAgfVxuXG4gIFJlYWN0UHJvcFR5cGVzLmNoZWNrUHJvcFR5cGVzID0gY2hlY2tQcm9wVHlwZXM7XG4gIFJlYWN0UHJvcFR5cGVzLnJlc2V0V2FybmluZ0NhY2hlID0gY2hlY2tQcm9wVHlwZXMucmVzZXRXYXJuaW5nQ2FjaGU7XG4gIFJlYWN0UHJvcFR5cGVzLlByb3BUeXBlcyA9IFJlYWN0UHJvcFR5cGVzO1xuXG4gIHJldHVybiBSZWFjdFByb3BUeXBlcztcbn07XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/prop-types/factoryWithTypeCheckers.js\n");
/***/ }),
/***/ "./node_modules/prop-types/index.js":
/*!******************************************!*\
!*** ./node_modules/prop-types/index.js ***!
\******************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nif (true) {\n var ReactIs = __webpack_require__(/*! react-is */ \"./node_modules/react-is/index.js\");\n\n // By explicitly using `prop-types` you are opting into new development behavior.\n // http://fb.me/prop-types-in-prod\n var throwOnDirectAccess = true;\n module.exports = __webpack_require__(/*! ./factoryWithTypeCheckers */ \"./node_modules/prop-types/factoryWithTypeCheckers.js\")(ReactIs.isElement, throwOnDirectAccess);\n} else {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9wcm9wLXR5cGVzL2luZGV4LmpzP2Q3YmMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLElBQUksSUFBcUM7QUFDekMsZ0JBQWdCLG1CQUFPLENBQUMsa0RBQVU7O0FBRWxDO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixtQkFBTyxDQUFDLHVGQUEyQjtBQUN0RCxDQUFDLE1BQU0sRUFJTiIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9wcm9wLXR5cGVzL2luZGV4LmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtcHJlc2VudCwgRmFjZWJvb2ssIEluYy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG5pZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICB2YXIgUmVhY3RJcyA9IHJlcXVpcmUoJ3JlYWN0LWlzJyk7XG5cbiAgLy8gQnkgZXhwbGljaXRseSB1c2luZyBgcHJvcC10eXBlc2AgeW91IGFyZSBvcHRpbmcgaW50byBuZXcgZGV2ZWxvcG1lbnQgYmVoYXZpb3IuXG4gIC8vIGh0dHA6Ly9mYi5tZS9wcm9wLXR5cGVzLWluLXByb2RcbiAgdmFyIHRocm93T25EaXJlY3RBY2Nlc3MgPSB0cnVlO1xuICBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vZmFjdG9yeVdpdGhUeXBlQ2hlY2tlcnMnKShSZWFjdElzLmlzRWxlbWVudCwgdGhyb3dPbkRpcmVjdEFjY2Vzcyk7XG59IGVsc2Uge1xuICAvLyBCeSBleHBsaWNpdGx5IHVzaW5nIGBwcm9wLXR5cGVzYCB5b3UgYXJlIG9wdGluZyBpbnRvIG5ldyBwcm9kdWN0aW9uIGJlaGF2aW9yLlxuICAvLyBodHRwOi8vZmIubWUvcHJvcC10eXBlcy1pbi1wcm9kXG4gIG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9mYWN0b3J5V2l0aFRocm93aW5nU2hpbXMnKSgpO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/prop-types/index.js\n");
/***/ }),
/***/ "./node_modules/prop-types/lib/ReactPropTypesSecret.js":
/*!*************************************************************!*\
!*** ./node_modules/prop-types/lib/ReactPropTypesSecret.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\n\nvar ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';\n\nmodule.exports = ReactPropTypesSecret;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9wcm9wLXR5cGVzL2xpYi9SZWFjdFByb3BUeXBlc1NlY3JldC5qcz81OWIwIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFYTs7QUFFYjs7QUFFQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9wcm9wLXR5cGVzL2xpYi9SZWFjdFByb3BUeXBlc1NlY3JldC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLXByZXNlbnQsIEZhY2Vib29rLCBJbmMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVhY3RQcm9wVHlwZXNTZWNyZXQgPSAnU0VDUkVUX0RPX05PVF9QQVNTX1RISVNfT1JfWU9VX1dJTExfQkVfRklSRUQnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJlYWN0UHJvcFR5cGVzU2VjcmV0O1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/prop-types/lib/ReactPropTypesSecret.js\n");
/***/ }),
/***/ "./node_modules/react-cytoscapejs/dist/react-cytoscape.js":
/*!****************************************************************!*\
!*** ./node_modules/react-cytoscapejs/dist/react-cytoscape.js ***!
\****************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("!function(e,t){ true?module.exports=t(__webpack_require__(/*! react */ \"react\"),__webpack_require__(/*! react-dom */ \"react-dom\"),__webpack_require__(/*! prop-types */ \"./node_modules/prop-types/index.js\"),__webpack_require__(/*! cytoscape */ \"./node_modules/cytoscape/dist/cytoscape.cjs.js\")):undefined}(window,function(e,t,n,o){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(e,\"__esModule\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\"object\"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,\"default\",{enumerable:!0,value:e}),2&t&&\"string\"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\"a\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\"\",n(n.s=2)}([function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e},r=o({}),u=function(e,t){return null==e||null==t};t.hashDiff=function(e,t){return u(e,t)||e.hash()!==t.hash()},t.shallowObjDiff=function(e,t){if(u(e,t)&&(null!=e||null!=t))return!0;if(e===t)return!1;if((void 0===e?\"undefined\":o(e))!==r||(void 0===t?\"undefined\":o(t))!==r)return e!==t;var n=Object.keys(e),i=Object.keys(t),l=function(n){return e[n]!==t[n]};return n.length!==i.length||!(!n.some(l)&&!i.some(l))}},function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});t.get=function(e,t){return null!=e?e[t]:null},t.toJson=function(e){return e},t.forEach=function(e,t){return e.forEach(t)}},function(e,t,n){\"use strict\";e.exports=n(3).default},function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,\"value\"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),r=s(n(4)),u=s(n(5)),i=n(6),l=n(8),a=s(n(9)),c=n(10);function s(e){return e&&e.__esModule?e:{default:e}}var f=function(e){function t(e){!function(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}(this,t);var n=function(e,t){if(!e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!t||\"object\"!=typeof t&&\"function\"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.displayName=\"CytoscapeComponent\",n}return function(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,r.default.Component),o(t,null,[{key:\"normalizeElements\",value:function(e){if(null!=e.length)return e;var t=e.nodes,n=e.edges;return null==t&&(t=[]),null==n&&(n=[]),t.concat(n)}},{key:\"propTypes\",get:function(){return i.types}},{key:\"defaultProps\",get:function(){return l.defaults}}]),o(t,[{key:\"componentDidMount\",value:function(){var e=u.default.findDOMNode(this),t=this.props,n=t.global,o=t.headless,r=t.styleEnabled,i=t.hideEdgesOnViewport,l=t.textureOnViewport,c=t.motionBlur,s=t.motionBlurOpacity,f=t.wheelSensitivity,d=t.pixelRatio,p=this._cy=new a.default({container:e,headless:o,styleEnabled:r,hideEdgesOnViewport:i,textureOnViewport:l,motionBlur:c,motionBlurOpacity:s,wheelSensitivity:f,pixelRatio:d});n&&(window[n]=p),this.updateCytoscape(null,this.props)}},{key:\"updateCytoscape\",value:function(e,t){var n=this._cy,o=t.diff,r=t.toJson,u=t.get,i=t.forEach;(0,c.patch)(n,e,t,o,r,u,i),null!=t.cy&&t.cy(n)}},{key:\"componentDidUpdate\",value:function(e){this.updateCytoscape(e,this.props)}},{key:\"componentWillUnmount\",value:function(){this._cy.destroy()}},{key:\"render\",value:function(){var e=this.props,t=e.id,n=e.className,o=e.style;return r.default.createElement(\"div\",{id:t,className:n,style:o})}}]),t}();t.default=f},function(t,n){t.exports=e},function(e,n){e.exports=t},function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.types=void 0;var o=function(e){return e&&e.__esModule?e:{default:e}}(n(7));var r=o.default.string,u=o.default.array,i=o.default.object,l=o.default.number,a=o.default.bool,c=o.default.oneOfType,s=o.default.any,f=o.default.func;t.types={id:r,className:r,style:c([r,i]),elements:c([u,s]),stylesheet:c([u,s]),layout:c([i,s]),pan:c([i,s]),zoom:l,panningEnabled:a,userPanningEnabled:a,minZoom:l,maxZoom:l,zoomingEnabled:a,userZoomingEnabled:a,boxSelectionEnabled:a,autoungrabify:a,autolock:a,autounselectify:a,get:f,toJson:f,diff:f,forEach:f,cy:f,headless:a,styleEnabled:a,hideEdgesOnViewport:a,textureOnViewport:a,motionBlur:a,motionBlurOpacity:l,wheelSensitivity:l,pixelRatio:c([r,i])}},function(e,t){e.exports=n},function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.defaults=t.pan=t.zoom=t.stylesheet=t.elements=t.identity=void 0;var o=n(0),r=n(1),u=(t.identity=function(e){return e},t.elements=[{data:{id:\"a\",label:\"Example node A\"}},{data:{id:\"b\",label:\"Example node B\"}},{data:{id:\"e\",source:\"a\",target:\"b\"}}]),i=t.stylesheet=[{selector:\"node\",style:{label:\"data(label)\"}}],l=t.zoom=1,a=t.pan={x:0,y:0};t.defaults={diff:o.shallowObjDiff,get:r.get,toJson:r.toJson,forEach:r.forEach,elements:u,stylesheet:i,zoom:l,pan:a}},function(e,t){e.exports=o},function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.patch=void 0;var o=n(1),r=n(0),u=function(e,t,n,r){return n((0,o.get)(e,r),(0,o.get)(t,r))},i=(t.patch=function(e,t,n,s,f,d,p){e.batch(function(){(s===r.shallowObjDiff||u(t,n,s,\"elements\"))&&c(e,(0,o.get)(t,\"elements\"),(0,o.get)(n,\"elements\"),f,d,p,s),u(t,n,s,\"stylesheet\")&&a(e,(0,o.get)(t,\"stylesheet\"),(0,o.get)(n,\"stylesheet\"),f),[\"zoom\",\"minZoom\",\"maxZoom\",\"zoomingEnabled\",\"userZoomingEnabled\",\"pan\",\"panningEnabled\",\"userPanningEnabled\",\"boxSelectionEnabled\",\"autoungrabify\",\"autolock\",\"autounselectify\"].forEach(function(r){u(t,n,s,r)&&i(e,r,(0,o.get)(t,r),(0,o.get)(n,r),f)})}),u(t,n,s,\"layout\")&&l(e,(0,o.get)(t,\"layout\"),(0,o.get)(n,\"layout\"),f)},function(e,t,n,o,r){e[t](r(o))}),l=function(e,t,n,o){var r=o(n);null!=r&&e.layout(r).run()},a=function(e,t,n,o){var r=e.style();null!=r&&r.fromJson(o(n)).update()},c=function(e,t,n,o,r,u,i){var l=[],a=e.collection(),c=[],f={},d={},p=function(e){return r(r(e,\"data\"),\"id\")};u(n,function(e){var t=p(e);d[t]=e}),null!=t&&u(t,function(t){var n=p(t);f[n]=t,function(e){return null!=d[e]}(n)||a.merge(e.getElementById(n))}),u(n,function(e){var t=p(e),n=function(e){return f[e]}(t);!function(e){return null!=f[e]}(t)?l.push(o(e)):c.push({ele1:n,ele2:e})}),a.length>0&&e.remove(a),l.length>0&&e.add(l),c.forEach(function(t){var n=t.ele1,u=t.ele2;return s(e,n,u,o,r,i)})},s=function(e,t,n,o,r,u){var i=r(r(n,\"data\"),\"id\"),l=e.getElementById(i),a={};[\"data\",\"position\",\"selected\",\"selectable\",\"locked\",\"grabbable\",\"classes\"].forEach(function(e){var i=r(n,e);u(i,r(t,e))&&(a[e]=o(i))});var c=r(n,\"scratch\");u(c,r(t,\"scratch\"))&&l.scratch(o(c)),Object.keys(a).length>0&&l.json(a)}}])});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9yZWFjdC1jeXRvc2NhcGVqcy9kaXN0L3JlYWN0LWN5dG9zY2FwZS5qcz84NzRkIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGVBQWUsS0FBaUQsa0JBQWtCLG1CQUFPLENBQUMsb0JBQU8sRUFBRSxtQkFBTyxDQUFDLDRCQUFXLEVBQUUsbUJBQU8sQ0FBQyxzREFBWSxFQUFFLG1CQUFPLENBQUMsaUVBQVcsR0FBRyxTQUFpUyxDQUFDLDBCQUEwQixtQkFBbUIsU0FBUyxjQUFjLDRCQUE0QixZQUFZLHFCQUFxQiwyREFBMkQsdUNBQXVDLHFDQUFxQyxvQkFBb0IsRUFBRSxpQkFBaUIsNEZBQTRGLGVBQWUsd0NBQXdDLFNBQVMsRUFBRSxtQkFBbUIsOEJBQThCLHFEQUFxRCwwQkFBMEIsNkNBQTZDLHNCQUFzQiw2REFBNkQsWUFBWSxlQUFlLFNBQVMsaUJBQWlCLGlDQUFpQyxpQkFBaUIsWUFBWSxVQUFVLHNCQUFzQixtQkFBbUIsaURBQWlELGlCQUFpQixrQkFBa0IsYUFBYSxzQ0FBc0MsU0FBUyxFQUFFLDhFQUE4RSxnQkFBZ0IsYUFBYSxvR0FBb0csT0FBTyxrQkFBa0IseUJBQXlCLHlCQUF5QixtQ0FBbUMsZ0NBQWdDLHVDQUF1QyxrQkFBa0IscUZBQXFGLG9EQUFvRCxvQkFBb0IsdURBQXVELGlCQUFpQixhQUFhLHNDQUFzQyxTQUFTLEVBQUUsb0JBQW9CLHlCQUF5QixzQkFBc0IsU0FBUyx5QkFBeUIscUJBQXFCLGlCQUFpQixhQUFhLHVCQUF1QixpQkFBaUIsYUFBYSxzQ0FBc0MsU0FBUyxFQUFFLGlCQUFpQixnQkFBZ0IsWUFBWSxXQUFXLEtBQUssV0FBVywrR0FBK0csdUJBQXVCLHdDQUF3Qyx1REFBdUQsY0FBYywwQkFBMEIsV0FBVyxrQkFBa0IsY0FBYyxlQUFlLDhFQUE4RSxTQUFTLG9CQUFvQiw0RkFBNEYsdURBQXVELDREQUE0RCw0Q0FBNEMscUJBQXFCLDJIQUEySCwwQ0FBMEMsYUFBYSxtREFBbUQsc0VBQXNFLG1DQUFtQywwQ0FBMEMsMkJBQTJCLHdCQUF3QixvREFBb0QsRUFBRSwrQkFBK0IsZ0JBQWdCLEVBQUUsa0NBQWtDLG1CQUFtQixTQUFTLHlDQUF5Qyx5T0FBeU8saUpBQWlKLEVBQUUsd0RBQXdELEVBQUUsMENBQTBDLHVEQUF1RCxnREFBZ0QsRUFBRSwyQ0FBMkMsb0NBQW9DLEVBQUUsNENBQTRDLG9CQUFvQixFQUFFLDhCQUE4QixnREFBZ0Qsc0NBQXNDLHlCQUF5QixHQUFHLEtBQUssR0FBRyxZQUFZLGVBQWUsWUFBWSxlQUFlLFlBQVksaUJBQWlCLGFBQWEsc0NBQXNDLFNBQVMsaUJBQWlCLGtCQUFrQiwwQkFBMEIsV0FBVyxPQUFPLHVKQUF1SixTQUFTLCtiQUErYixlQUFlLFlBQVksaUJBQWlCLGFBQWEsc0NBQXNDLFNBQVMsb0VBQW9FLDRDQUE0QyxTQUFTLGNBQWMsTUFBTSwrQkFBK0IsRUFBRSxNQUFNLCtCQUErQixFQUFFLE1BQU0sOEJBQThCLG9CQUFvQix1QkFBdUIscUJBQXFCLHNCQUFzQixTQUFTLFlBQVksd0dBQXdHLGVBQWUsWUFBWSxpQkFBaUIsYUFBYSxzQ0FBc0MsU0FBUyxpQkFBaUIsc0NBQXNDLHdDQUF3QyxvQ0FBb0MsbUJBQW1CLGtZQUFrWSxtREFBbUQsRUFBRSx3RUFBd0UscUJBQXFCLFdBQVcsc0JBQXNCLFdBQVcsMkJBQTJCLHFCQUFxQixnQkFBZ0IsbUNBQW1DLDJCQUEyQixtQ0FBbUMsS0FBSyxlQUFlLDRCQUE0QixnQkFBZ0IsV0FBVyxPQUFPLDJCQUEyQixXQUFXLG1CQUFtQixrQkFBa0Isa0NBQWtDLGtCQUFrQix5QkFBeUIsWUFBWSxJQUFJLGFBQWEsa0JBQWtCLHlCQUF5QixjQUFjLEVBQUUscUVBQXFFLHNCQUFzQixzQkFBc0IsRUFBRSx5QkFBeUIscURBQXFELCtGQUErRixhQUFhLHlCQUF5QixFQUFFLHFCQUFxQix5RUFBeUUsR0FBRyIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9yZWFjdC1jeXRvc2NhcGVqcy9kaXN0L3JlYWN0LWN5dG9zY2FwZS5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIiFmdW5jdGlvbihlLHQpe1wib2JqZWN0XCI9PXR5cGVvZiBleHBvcnRzJiZcIm9iamVjdFwiPT10eXBlb2YgbW9kdWxlP21vZHVsZS5leHBvcnRzPXQocmVxdWlyZShcInJlYWN0XCIpLHJlcXVpcmUoXCJyZWFjdC1kb21cIikscmVxdWlyZShcInByb3AtdHlwZXNcIikscmVxdWlyZShcImN5dG9zY2FwZVwiKSk6XCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShbXCJyZWFjdFwiLFwicmVhY3QtZG9tXCIsXCJwcm9wLXR5cGVzXCIsXCJjeXRvc2NhcGVcIl0sdCk6XCJvYmplY3RcIj09dHlwZW9mIGV4cG9ydHM/ZXhwb3J0cy5SZWFjdEN5dG9zY2FwZT10KHJlcXVpcmUoXCJyZWFjdFwiKSxyZXF1aXJlKFwicmVhY3QtZG9tXCIpLHJlcXVpcmUoXCJwcm9wLXR5cGVzXCIpLHJlcXVpcmUoXCJjeXRvc2NhcGVcIikpOmUuUmVhY3RDeXRvc2NhcGU9dChlLlJlYWN0LGUuUmVhY3RET00sZS5Qcm9wVHlwZXMsZS5jeXRvc2NhcGUpfSh3aW5kb3csZnVuY3Rpb24oZSx0LG4sbyl7cmV0dXJuIGZ1bmN0aW9uKGUpe3ZhciB0PXt9O2Z1bmN0aW9uIG4obyl7aWYodFtvXSlyZXR1cm4gdFtvXS5leHBvcnRzO3ZhciByPXRbb109e2k6byxsOiExLGV4cG9ydHM6e319O3JldHVybiBlW29dLmNhbGwoci5leHBvcnRzLHIsci5leHBvcnRzLG4pLHIubD0hMCxyLmV4cG9ydHN9cmV0dXJuIG4ubT1lLG4uYz10LG4uZD1mdW5jdGlvbihlLHQsbyl7bi5vKGUsdCl8fE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlLHQse2VudW1lcmFibGU6ITAsZ2V0Om99KX0sbi5yPWZ1bmN0aW9uKGUpe1widW5kZWZpbmVkXCIhPXR5cGVvZiBTeW1ib2wmJlN5bWJvbC50b1N0cmluZ1RhZyYmT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsU3ltYm9sLnRvU3RyaW5nVGFnLHt2YWx1ZTpcIk1vZHVsZVwifSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSl9LG4udD1mdW5jdGlvbihlLHQpe2lmKDEmdCYmKGU9bihlKSksOCZ0KXJldHVybiBlO2lmKDQmdCYmXCJvYmplY3RcIj09dHlwZW9mIGUmJmUmJmUuX19lc01vZHVsZSlyZXR1cm4gZTt2YXIgbz1PYmplY3QuY3JlYXRlKG51bGwpO2lmKG4ucihvKSxPYmplY3QuZGVmaW5lUHJvcGVydHkobyxcImRlZmF1bHRcIix7ZW51bWVyYWJsZTohMCx2YWx1ZTplfSksMiZ0JiZcInN0cmluZ1wiIT10eXBlb2YgZSlmb3IodmFyIHIgaW4gZSluLmQobyxyLGZ1bmN0aW9uKHQpe3JldHVybiBlW3RdfS5iaW5kKG51bGwscikpO3JldHVybiBvfSxuLm49ZnVuY3Rpb24oZSl7dmFyIHQ9ZSYmZS5fX2VzTW9kdWxlP2Z1bmN0aW9uKCl7cmV0dXJuIGUuZGVmYXVsdH06ZnVuY3Rpb24oKXtyZXR1cm4gZX07cmV0dXJuIG4uZCh0LFwiYVwiLHQpLHR9LG4ubz1mdW5jdGlvbihlLHQpe3JldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZSx0KX0sbi5wPVwiXCIsbihuLnM9Mil9KFtmdW5jdGlvbihlLHQsbil7XCJ1c2Ugc3RyaWN0XCI7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyIG89XCJmdW5jdGlvblwiPT10eXBlb2YgU3ltYm9sJiZcInN5bWJvbFwiPT10eXBlb2YgU3ltYm9sLml0ZXJhdG9yP2Z1bmN0aW9uKGUpe3JldHVybiB0eXBlb2YgZX06ZnVuY3Rpb24oZSl7cmV0dXJuIGUmJlwiZnVuY3Rpb25cIj09dHlwZW9mIFN5bWJvbCYmZS5jb25zdHJ1Y3Rvcj09PVN5bWJvbCYmZSE9PVN5bWJvbC5wcm90b3R5cGU/XCJzeW1ib2xcIjp0eXBlb2YgZX0scj1vKHt9KSx1PWZ1bmN0aW9uKGUsdCl7cmV0dXJuIG51bGw9PWV8fG51bGw9PXR9O3QuaGFzaERpZmY9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gdShlLHQpfHxlLmhhc2goKSE9PXQuaGFzaCgpfSx0LnNoYWxsb3dPYmpEaWZmPWZ1bmN0aW9uKGUsdCl7aWYodShlLHQpJiYobnVsbCE9ZXx8bnVsbCE9dCkpcmV0dXJuITA7aWYoZT09PXQpcmV0dXJuITE7aWYoKHZvaWQgMD09PWU/XCJ1bmRlZmluZWRcIjpvKGUpKSE9PXJ8fCh2b2lkIDA9PT10P1widW5kZWZpbmVkXCI6byh0KSkhPT1yKXJldHVybiBlIT09dDt2YXIgbj1PYmplY3Qua2V5cyhlKSxpPU9iamVjdC5rZXlzKHQpLGw9ZnVuY3Rpb24obil7cmV0dXJuIGVbbl0hPT10W25dfTtyZXR1cm4gbi5sZW5ndGghPT1pLmxlbmd0aHx8ISghbi5zb21lKGwpJiYhaS5zb21lKGwpKX19LGZ1bmN0aW9uKGUsdCxuKXtcInVzZSBzdHJpY3RcIjtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTt0LmdldD1mdW5jdGlvbihlLHQpe3JldHVybiBudWxsIT1lP2VbdF06bnVsbH0sdC50b0pzb249ZnVuY3Rpb24oZSl7cmV0dXJuIGV9LHQuZm9yRWFjaD1mdW5jdGlvbihlLHQpe3JldHVybiBlLmZvckVhY2godCl9fSxmdW5jdGlvbihlLHQsbil7XCJ1c2Ugc3RyaWN0XCI7ZS5leHBvcnRzPW4oMykuZGVmYXVsdH0sZnVuY3Rpb24oZSx0LG4pe1widXNlIHN0cmljdFwiO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciBvPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gZShlLHQpe2Zvcih2YXIgbj0wO248dC5sZW5ndGg7bisrKXt2YXIgbz10W25dO28uZW51bWVyYWJsZT1vLmVudW1lcmFibGV8fCExLG8uY29uZmlndXJhYmxlPSEwLFwidmFsdWVcImluIG8mJihvLndyaXRhYmxlPSEwKSxPYmplY3QuZGVmaW5lUHJvcGVydHkoZSxvLmtleSxvKX19cmV0dXJuIGZ1bmN0aW9uKHQsbixvKXtyZXR1cm4gbiYmZSh0LnByb3RvdHlwZSxuKSxvJiZlKHQsbyksdH19KCkscj1zKG4oNCkpLHU9cyhuKDUpKSxpPW4oNiksbD1uKDgpLGE9cyhuKDkpKSxjPW4oMTApO2Z1bmN0aW9uIHMoZSl7cmV0dXJuIGUmJmUuX19lc01vZHVsZT9lOntkZWZhdWx0OmV9fXZhciBmPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHQoZSl7IWZ1bmN0aW9uKGUsdCl7aWYoIShlIGluc3RhbmNlb2YgdCkpdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKX0odGhpcyx0KTt2YXIgbj1mdW5jdGlvbihlLHQpe2lmKCFlKXRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTtyZXR1cm4hdHx8XCJvYmplY3RcIiE9dHlwZW9mIHQmJlwiZnVuY3Rpb25cIiE9dHlwZW9mIHQ/ZTp0fSh0aGlzLCh0Ll9fcHJvdG9fX3x8T2JqZWN0LmdldFByb3RvdHlwZU9mKHQpKS5jYWxsKHRoaXMsZSkpO3JldHVybiBuLmRpc3BsYXlOYW1lPVwiQ3l0b3NjYXBlQ29tcG9uZW50XCIsbn1yZXR1cm4gZnVuY3Rpb24oZSx0KXtpZihcImZ1bmN0aW9uXCIhPXR5cGVvZiB0JiZudWxsIT09dCl0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIit0eXBlb2YgdCk7ZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSx7Y29uc3RydWN0b3I6e3ZhbHVlOmUsZW51bWVyYWJsZTohMSx3cml0YWJsZTohMCxjb25maWd1cmFibGU6ITB9fSksdCYmKE9iamVjdC5zZXRQcm90b3R5cGVPZj9PYmplY3Quc2V0UHJvdG90eXBlT2YoZSx0KTplLl9fcHJvdG9fXz10KX0odCxyLmRlZmF1bHQuQ29tcG9uZW50KSxvKHQsbnVsbCxbe2tleTpcIm5vcm1hbGl6ZUVsZW1lbnRzXCIsdmFsdWU6ZnVuY3Rpb24oZSl7aWYobnVsbCE9ZS5sZW5ndGgpcmV0dXJuIGU7dmFyIHQ9ZS5ub2RlcyxuPWUuZWRnZXM7cmV0dXJuIG51bGw9PXQmJih0PVtdKSxudWxsPT1uJiYobj1bXSksdC5jb25jYXQobil9fSx7a2V5OlwicHJvcFR5cGVzXCIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGkudHlwZXN9fSx7a2V5OlwiZGVmYXVsdFByb3BzXCIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGwuZGVmYXVsdHN9fV0pLG8odCxbe2tleTpcImNvbXBvbmVudERpZE1vdW50XCIsdmFsdWU6ZnVuY3Rpb24oKXt2YXIgZT11LmRlZmF1bHQuZmluZERPTU5vZGUodGhpcyksdD10aGlzLnByb3BzLG49dC5nbG9iYWwsbz10LmhlYWRsZXNzLHI9dC5zdHlsZUVuYWJsZWQsaT10LmhpZGVFZGdlc09uVmlld3BvcnQsbD10LnRleHR1cmVPblZpZXdwb3J0LGM9dC5tb3Rpb25CbHVyLHM9dC5tb3Rpb25CbHVyT3BhY2l0eSxmPXQud2hlZWxTZW5zaXRpdml0eSxkPXQucGl4ZWxSYXRpbyxwPXRoaXMuX2N5PW5ldyBhLmRlZmF1bHQoe2NvbnRhaW5lcjplLGhlYWRsZXNzOm8sc3R5bGVFbmFibGVkOnIsaGlkZUVkZ2VzT25WaWV3cG9ydDppLHRleHR1cmVPblZpZXdwb3J0OmwsbW90aW9uQmx1cjpjLG1vdGlvbkJsdXJPcGFjaXR5OnMsd2hlZWxTZW5zaXRpdml0eTpmLHBpeGVsUmF0aW86ZH0pO24mJih3aW5kb3dbbl09cCksdGhpcy51cGRhdGVDeXRvc2NhcGUobnVsbCx0aGlzLnByb3BzKX19LHtrZXk6XCJ1cGRhdGVDeXRvc2NhcGVcIix2YWx1ZTpmdW5jdGlvbihlLHQpe3ZhciBuPXRoaXMuX2N5LG89dC5kaWZmLHI9dC50b0pzb24sdT10LmdldCxpPXQuZm9yRWFjaDsoMCxjLnBhdGNoKShuLGUsdCxvLHIsdSxpKSxudWxsIT10LmN5JiZ0LmN5KG4pfX0se2tleTpcImNvbXBvbmVudERpZFVwZGF0ZVwiLHZhbHVlOmZ1bmN0aW9uKGUpe3RoaXMudXBkYXRlQ3l0b3NjYXBlKGUsdGhpcy5wcm9wcyl9fSx7a2V5OlwiY29tcG9uZW50V2lsbFVubW91bnRcIix2YWx1ZTpmdW5jdGlvbigpe3RoaXMuX2N5LmRlc3Ryb3koKX19LHtrZXk6XCJyZW5kZXJcIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMsdD1lLmlkLG49ZS5jbGFzc05hbWUsbz1lLnN0eWxlO3JldHVybiByLmRlZmF1bHQuY3JlYXRlRWxlbWVudChcImRpdlwiLHtpZDp0LGNsYXNzTmFtZTpuLHN0eWxlOm99KX19XSksdH0oKTt0LmRlZmF1bHQ9Zn0sZnVuY3Rpb24odCxuKXt0LmV4cG9ydHM9ZX0sZnVuY3Rpb24oZSxuKXtlLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSx0LG4pe1widXNlIHN0cmljdFwiO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pLHQudHlwZXM9dm9pZCAwO3ZhciBvPWZ1bmN0aW9uKGUpe3JldHVybiBlJiZlLl9fZXNNb2R1bGU/ZTp7ZGVmYXVsdDplfX0obig3KSk7dmFyIHI9by5kZWZhdWx0LnN0cmluZyx1PW8uZGVmYXVsdC5hcnJheSxpPW8uZGVmYXVsdC5vYmplY3QsbD1vLmRlZmF1bHQubnVtYmVyLGE9by5kZWZhdWx0LmJvb2wsYz1vLmRlZmF1bHQub25lT2ZUeXBlLHM9by5kZWZhdWx0LmFueSxmPW8uZGVmYXVsdC5mdW5jO3QudHlwZXM9e2lkOnIsY2xhc3NOYW1lOnIsc3R5bGU6YyhbcixpXSksZWxlbWVudHM6YyhbdSxzXSksc3R5bGVzaGVldDpjKFt1LHNdKSxsYXlvdXQ6YyhbaSxzXSkscGFuOmMoW2ksc10pLHpvb206bCxwYW5uaW5nRW5hYmxlZDphLHVzZXJQYW5uaW5nRW5hYmxlZDphLG1pblpvb206bCxtYXhab29tOmwsem9vbWluZ0VuYWJsZWQ6YSx1c2VyWm9vbWluZ0VuYWJsZWQ6YSxib3hTZWxlY3Rpb25FbmFibGVkOmEsYXV0b3VuZ3JhYmlmeTphLGF1dG9sb2NrOmEsYXV0b3Vuc2VsZWN0aWZ5OmEsZ2V0OmYsdG9Kc29uOmYsZGlmZjpmLGZvckVhY2g6ZixjeTpmLGhlYWRsZXNzOmEsc3R5bGVFbmFibGVkOmEsaGlkZUVkZ2VzT25WaWV3cG9ydDphLHRleHR1cmVPblZpZXdwb3J0OmEsbW90aW9uQmx1cjphLG1vdGlvbkJsdXJPcGFjaXR5Omwsd2hlZWxTZW5zaXRpdml0eTpsLHBpeGVsUmF0aW86YyhbcixpXSl9fSxmdW5jdGlvbihlLHQpe2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLHQsbil7XCJ1c2Ugc3RyaWN0XCI7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSksdC5kZWZhdWx0cz10LnBhbj10Lnpvb209dC5zdHlsZXNoZWV0PXQuZWxlbWVudHM9dC5pZGVudGl0eT12b2lkIDA7dmFyIG89bigwKSxyPW4oMSksdT0odC5pZGVudGl0eT1mdW5jdGlvbihlKXtyZXR1cm4gZX0sdC5lbGVtZW50cz1be2RhdGE6e2lkOlwiYVwiLGxhYmVsOlwiRXhhbXBsZSBub2RlIEFcIn19LHtkYXRhOntpZDpcImJcIixsYWJlbDpcIkV4YW1wbGUgbm9kZSBCXCJ9fSx7ZGF0YTp7aWQ6XCJlXCIsc291cmNlOlwiYVwiLHRhcmdldDpcImJcIn19XSksaT10LnN0eWxlc2hlZXQ9W3tzZWxlY3RvcjpcIm5vZGVcIixzdHlsZTp7bGFiZWw6XCJkYXRhKGxhYmVsKVwifX1dLGw9dC56b29tPTEsYT10LnBhbj17eDowLHk6MH07dC5kZWZhdWx0cz17ZGlmZjpvLnNoYWxsb3dPYmpEaWZmLGdldDpyLmdldCx0b0pzb246ci50b0pzb24sZm9yRWFjaDpyLmZvckVhY2gsZWxlbWVudHM6dSxzdHlsZXNoZWV0Omksem9vbTpsLHBhbjphfX0sZnVuY3Rpb24oZSx0KXtlLmV4cG9ydHM9b30sZnVuY3Rpb24oZSx0LG4pe1widXNlIHN0cmljdFwiO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pLHQucGF0Y2g9dm9pZCAwO3ZhciBvPW4oMSkscj1uKDApLHU9ZnVuY3Rpb24oZSx0LG4scil7cmV0dXJuIG4oKDAsby5nZXQpKGUsciksKDAsby5nZXQpKHQscikpfSxpPSh0LnBhdGNoPWZ1bmN0aW9uKGUsdCxuLHMsZixkLHApe2UuYmF0Y2goZnVuY3Rpb24oKXsocz09PXIuc2hhbGxvd09iakRpZmZ8fHUodCxuLHMsXCJlbGVtZW50c1wiKSkmJmMoZSwoMCxvLmdldCkodCxcImVsZW1lbnRzXCIpLCgwLG8uZ2V0KShuLFwiZWxlbWVudHNcIiksZixkLHAscyksdSh0LG4scyxcInN0eWxlc2hlZXRcIikmJmEoZSwoMCxvLmdldCkodCxcInN0eWxlc2hlZXRcIiksKDAsby5nZXQpKG4sXCJzdHlsZXNoZWV0XCIpLGYpLFtcInpvb21cIixcIm1pblpvb21cIixcIm1heFpvb21cIixcInpvb21pbmdFbmFibGVkXCIsXCJ1c2VyWm9vbWluZ0VuYWJsZWRcIixcInBhblwiLFwicGFubmluZ0VuYWJsZWRcIixcInVzZXJQYW5uaW5nRW5hYmxlZFwiLFwiYm94U2VsZWN0aW9uRW5hYmxlZFwiLFwiYXV0b3VuZ3JhYmlmeVwiLFwiYXV0b2xvY2tcIixcImF1dG91bnNlbGVjdGlmeVwiXS5mb3JFYWNoKGZ1bmN0aW9uKHIpe3UodCxuLHMscikmJmkoZSxyLCgwLG8uZ2V0KSh0LHIpLCgwLG8uZ2V0KShuLHIpLGYpfSl9KSx1KHQsbixzLFwibGF5b3V0XCIpJiZsKGUsKDAsby5nZXQpKHQsXCJsYXlvdXRcIiksKDAsby5nZXQpKG4sXCJsYXlvdXRcIiksZil9LGZ1bmN0aW9uKGUsdCxuLG8scil7ZVt0XShyKG8pKX0pLGw9ZnVuY3Rpb24oZSx0LG4sbyl7dmFyIHI9byhuKTtudWxsIT1yJiZlLmxheW91dChyKS5ydW4oKX0sYT1mdW5jdGlvbihlLHQsbixvKXt2YXIgcj1lLnN0eWxlKCk7bnVsbCE9ciYmci5mcm9tSnNvbihvKG4pKS51cGRhdGUoKX0sYz1mdW5jdGlvbihlLHQsbixvLHIsdSxpKXt2YXIgbD1bXSxhPWUuY29sbGVjdGlvbigpLGM9W10sZj17fSxkPXt9LHA9ZnVuY3Rpb24oZSl7cmV0dXJuIHIocihlLFwiZGF0YVwiKSxcImlkXCIpfTt1KG4sZnVuY3Rpb24oZSl7dmFyIHQ9cChlKTtkW3RdPWV9KSxudWxsIT10JiZ1KHQsZnVuY3Rpb24odCl7dmFyIG49cCh0KTtmW25dPXQsZnVuY3Rpb24oZSl7cmV0dXJuIG51bGwhPWRbZV19KG4pfHxhLm1lcmdlKGUuZ2V0RWxlbWVudEJ5SWQobikpfSksdShuLGZ1bmN0aW9uKGUpe3ZhciB0PXAoZSksbj1mdW5jdGlvbihlKXtyZXR1cm4gZltlXX0odCk7IWZ1bmN0aW9uKGUpe3JldHVybiBudWxsIT1mW2VdfSh0KT9sLnB1c2gobyhlKSk6Yy5wdXNoKHtlbGUxOm4sZWxlMjplfSl9KSxhLmxlbmd0aD4wJiZlLnJlbW92ZShhKSxsLmxlbmd0aD4wJiZlLmFkZChsKSxjLmZvckVhY2goZnVuY3Rpb24odCl7dmFyIG49dC5lbGUxLHU9dC5lbGUyO3JldHVybiBzKGUsbix1LG8scixpKX0pfSxzPWZ1bmN0aW9uKGUsdCxuLG8scix1KXt2YXIgaT1yKHIobixcImRhdGFcIiksXCJpZFwiKSxsPWUuZ2V0RWxlbWVudEJ5SWQoaSksYT17fTtbXCJkYXRhXCIsXCJwb3NpdGlvblwiLFwic2VsZWN0ZWRcIixcInNlbGVjdGFibGVcIixcImxvY2tlZFwiLFwiZ3JhYmJhYmxlXCIsXCJjbGFzc2VzXCJdLmZvckVhY2goZnVuY3Rpb24oZSl7dmFyIGk9cihuLGUpO3UoaSxyKHQsZSkpJiYoYVtlXT1vKGkpKX0pO3ZhciBjPXIobixcInNjcmF0Y2hcIik7dShjLHIodCxcInNjcmF0Y2hcIikpJiZsLnNjcmF0Y2gobyhjKSksT2JqZWN0LmtleXMoYSkubGVuZ3RoPjAmJmwuanNvbihhKX19XSl9KTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/react-cytoscapejs/dist/react-cytoscape.js\n");
/***/ }),
/***/ "./node_modules/react-is/cjs/react-is.development.js":
/*!***********************************************************!*\
!*** ./node_modules/react-is/cjs/react-is.development.js ***!
\***********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("/** @license React v16.13.1\n * react-is.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\n\n\n\nif (true) {\n (function() {\n'use strict';\n\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar hasSymbol = typeof Symbol === 'function' && Symbol.for;\nvar REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;\nvar REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;\nvar REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;\nvar REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;\nvar REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;\nvar REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;\nvar REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary\n// (unstable) APIs that have been removed. Can we remove the symbols?\n\nvar REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;\nvar REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;\nvar REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;\nvar REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;\nvar REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;\nvar REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;\nvar REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;\nvar REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;\nvar REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;\nvar REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;\n\nfunction isValidElementType(type) {\n return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.\n type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);\n}\n\nfunction typeOf(object) {\n if (typeof object === 'object' && object !== null) {\n var $$typeof = object.$$typeof;\n\n switch ($$typeof) {\n case REACT_ELEMENT_TYPE:\n var type = object.type;\n\n switch (type) {\n case REACT_ASYNC_MODE_TYPE:\n case REACT_CONCURRENT_MODE_TYPE:\n case REACT_FRAGMENT_TYPE:\n case REACT_PROFILER_TYPE:\n case REACT_STRICT_MODE_TYPE:\n case REACT_SUSPENSE_TYPE:\n return type;\n\n default:\n var $$typeofType = type && type.$$typeof;\n\n switch ($$typeofType) {\n case REACT_CONTEXT_TYPE:\n case REACT_FORWARD_REF_TYPE:\n case REACT_LAZY_TYPE:\n case REACT_MEMO_TYPE:\n case REACT_PROVIDER_TYPE:\n return $$typeofType;\n\n default:\n return $$typeof;\n }\n\n }\n\n case REACT_PORTAL_TYPE:\n return $$typeof;\n }\n }\n\n return undefined;\n} // AsyncMode is deprecated along with isAsyncMode\n\nvar AsyncMode = REACT_ASYNC_MODE_TYPE;\nvar ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;\nvar ContextConsumer = REACT_CONTEXT_TYPE;\nvar ContextProvider = REACT_PROVIDER_TYPE;\nvar Element = REACT_ELEMENT_TYPE;\nvar ForwardRef = REACT_FORWARD_REF_TYPE;\nvar Fragment = REACT_FRAGMENT_TYPE;\nvar Lazy = REACT_LAZY_TYPE;\nvar Memo = REACT_MEMO_TYPE;\nvar Portal = REACT_PORTAL_TYPE;\nvar Profiler = REACT_PROFILER_TYPE;\nvar StrictMode = REACT_STRICT_MODE_TYPE;\nvar Suspense = REACT_SUSPENSE_TYPE;\nvar hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated\n\nfunction isAsyncMode(object) {\n {\n if (!hasWarnedAboutDeprecatedIsAsyncMode) {\n hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint\n\n console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.');\n }\n }\n\n return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;\n}\nfunction isConcurrentMode(object) {\n return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;\n}\nfunction isContextConsumer(object) {\n return typeOf(object) === REACT_CONTEXT_TYPE;\n}\nfunction isContextProvider(object) {\n return typeOf(object) === REACT_PROVIDER_TYPE;\n}\nfunction isElement(object) {\n return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n}\nfunction isForwardRef(object) {\n return typeOf(object) === REACT_FORWARD_REF_TYPE;\n}\nfunction isFragment(object) {\n return typeOf(object) === REACT_FRAGMENT_TYPE;\n}\nfunction isLazy(object) {\n return typeOf(object) === REACT_LAZY_TYPE;\n}\nfunction isMemo(object) {\n return typeOf(object) === REACT_MEMO_TYPE;\n}\nfunction isPortal(object) {\n return typeOf(object) === REACT_PORTAL_TYPE;\n}\nfunction isProfiler(object) {\n return typeOf(object) === REACT_PROFILER_TYPE;\n}\nfunction isStrictMode(object) {\n return typeOf(object) === REACT_STRICT_MODE_TYPE;\n}\nfunction isSuspense(object) {\n return typeOf(object) === REACT_SUSPENSE_TYPE;\n}\n\nexports.AsyncMode = AsyncMode;\nexports.ConcurrentMode = ConcurrentMode;\nexports.ContextConsumer = ContextConsumer;\nexports.ContextProvider = ContextProvider;\nexports.Element = Element;\nexports.ForwardRef = ForwardRef;\nexports.Fragment = Fragment;\nexports.Lazy = Lazy;\nexports.Memo = Memo;\nexports.Portal = Portal;\nexports.Profiler = Profiler;\nexports.StrictMode = StrictMode;\nexports.Suspense = Suspense;\nexports.isAsyncMode = isAsyncMode;\nexports.isConcurrentMode = isConcurrentMode;\nexports.isContextConsumer = isContextConsumer;\nexports.isContextProvider = isContextProvider;\nexports.isElement = isElement;\nexports.isForwardRef = isForwardRef;\nexports.isFragment = isFragment;\nexports.isLazy = isLazy;\nexports.isMemo = isMemo;\nexports.isPortal = isPortal;\nexports.isProfiler = isProfiler;\nexports.isStrictMode = isStrictMode;\nexports.isSuspense = isSuspense;\nexports.isValidElementType = isValidElementType;\nexports.typeOf = typeOf;\n })();\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9yZWFjdC1pcy9janMvcmVhY3QtaXMuZGV2ZWxvcG1lbnQuanM/YThmNSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVhOzs7O0FBSWIsSUFBSSxJQUFxQztBQUN6QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBFQUEwRTtBQUMxRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7O0FBRWhEO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDs7QUFFakQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0giLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvcmVhY3QtaXMvY2pzL3JlYWN0LWlzLmRldmVsb3BtZW50LmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqIEBsaWNlbnNlIFJlYWN0IHYxNi4xMy4xXG4gKiByZWFjdC1pcy5kZXZlbG9wbWVudC5qc1xuICpcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuXG5cbmlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gXCJwcm9kdWN0aW9uXCIpIHtcbiAgKGZ1bmN0aW9uKCkge1xuJ3VzZSBzdHJpY3QnO1xuXG4vLyBUaGUgU3ltYm9sIHVzZWQgdG8gdGFnIHRoZSBSZWFjdEVsZW1lbnQtbGlrZSB0eXBlcy4gSWYgdGhlcmUgaXMgbm8gbmF0aXZlIFN5bWJvbFxuLy8gbm9yIHBvbHlmaWxsLCB0aGVuIGEgcGxhaW4gbnVtYmVyIGlzIHVzZWQgZm9yIHBlcmZvcm1hbmNlLlxudmFyIGhhc1N5bWJvbCA9IHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiYgU3ltYm9sLmZvcjtcbnZhciBSRUFDVF9FTEVNRU5UX1RZUEUgPSBoYXNTeW1ib2wgPyBTeW1ib2wuZm9yKCdyZWFjdC5lbGVtZW50JykgOiAweGVhYzc7XG52YXIgUkVBQ1RfUE9SVEFMX1RZUEUgPSBoYXNTeW1ib2wgPyBTeW1ib2wuZm9yKCdyZWFjdC5wb3J0YWwnKSA6IDB4ZWFjYTtcbnZhciBSRUFDVF9GUkFHTUVOVF9UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3QuZnJhZ21lbnQnKSA6IDB4ZWFjYjtcbnZhciBSRUFDVF9TVFJJQ1RfTU9ERV9UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3Quc3RyaWN0X21vZGUnKSA6IDB4ZWFjYztcbnZhciBSRUFDVF9QUk9GSUxFUl9UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3QucHJvZmlsZXInKSA6IDB4ZWFkMjtcbnZhciBSRUFDVF9QUk9WSURFUl9UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3QucHJvdmlkZXInKSA6IDB4ZWFjZDtcbnZhciBSRUFDVF9DT05URVhUX1RZUEUgPSBoYXNTeW1ib2wgPyBTeW1ib2wuZm9yKCdyZWFjdC5jb250ZXh0JykgOiAweGVhY2U7IC8vIFRPRE86IFdlIGRvbid0IHVzZSBBc3luY01vZGUgb3IgQ29uY3VycmVudE1vZGUgYW55bW9yZS4gVGhleSB3ZXJlIHRlbXBvcmFyeVxuLy8gKHVuc3RhYmxlKSBBUElzIHRoYXQgaGF2ZSBiZWVuIHJlbW92ZWQuIENhbiB3ZSByZW1vdmUgdGhlIHN5bWJvbHM/XG5cbnZhciBSRUFDVF9BU1lOQ19NT0RFX1RZUEUgPSBoYXNTeW1ib2wgPyBTeW1ib2wuZm9yKCdyZWFjdC5hc3luY19tb2RlJykgOiAweGVhY2Y7XG52YXIgUkVBQ1RfQ09OQ1VSUkVOVF9NT0RFX1RZUEUgPSBoYXNTeW1ib2wgPyBTeW1ib2wuZm9yKCdyZWFjdC5jb25jdXJyZW50X21vZGUnKSA6IDB4ZWFjZjtcbnZhciBSRUFDVF9GT1JXQVJEX1JFRl9UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3QuZm9yd2FyZF9yZWYnKSA6IDB4ZWFkMDtcbnZhciBSRUFDVF9TVVNQRU5TRV9UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3Quc3VzcGVuc2UnKSA6IDB4ZWFkMTtcbnZhciBSRUFDVF9TVVNQRU5TRV9MSVNUX1RZUEUgPSBoYXNTeW1ib2wgPyBTeW1ib2wuZm9yKCdyZWFjdC5zdXNwZW5zZV9saXN0JykgOiAweGVhZDg7XG52YXIgUkVBQ1RfTUVNT19UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3QubWVtbycpIDogMHhlYWQzO1xudmFyIFJFQUNUX0xBWllfVFlQRSA9IGhhc1N5bWJvbCA/IFN5bWJvbC5mb3IoJ3JlYWN0LmxhenknKSA6IDB4ZWFkNDtcbnZhciBSRUFDVF9CTE9DS19UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3QuYmxvY2snKSA6IDB4ZWFkOTtcbnZhciBSRUFDVF9GVU5EQU1FTlRBTF9UWVBFID0gaGFzU3ltYm9sID8gU3ltYm9sLmZvcigncmVhY3QuZnVuZGFtZW50YWwnKSA6IDB4ZWFkNTtcbnZhciBSRUFDVF9SRVNQT05ERVJfVFlQRSA9IGhhc1N5bWJvbCA/IFN5bWJvbC5mb3IoJ3JlYWN0LnJlc3BvbmRlcicpIDogMHhlYWQ2O1xudmFyIFJFQUNUX1NDT1BFX1RZUEUgPSBoYXNTeW1ib2wgPyBTeW1ib2wuZm9yKCdyZWFjdC5zY29wZScpIDogMHhlYWQ3O1xuXG5mdW5jdGlvbiBpc1ZhbGlkRWxlbWVudFR5cGUodHlwZSkge1xuICByZXR1cm4gdHlwZW9mIHR5cGUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB0eXBlID09PSAnZnVuY3Rpb24nIHx8IC8vIE5vdGU6IGl0cyB0eXBlb2YgbWlnaHQgYmUgb3RoZXIgdGhhbiAnc3ltYm9sJyBvciAnbnVtYmVyJyBpZiBpdCdzIGEgcG9seWZpbGwuXG4gIHR5cGUgPT09IFJFQUNUX0ZSQUdNRU5UX1RZUEUgfHwgdHlwZSA9PT0gUkVBQ1RfQ09OQ1VSUkVOVF9NT0RFX1RZUEUgfHwgdHlwZSA9PT0gUkVBQ1RfUFJPRklMRVJfVFlQRSB8fCB0eXBlID09PSBSRUFDVF9TVFJJQ1RfTU9ERV9UWVBFIHx8IHR5cGUgPT09IFJFQUNUX1NVU1BFTlNFX1RZUEUgfHwgdHlwZSA9PT0gUkVBQ1RfU1VTUEVOU0VfTElTVF9UWVBFIHx8IHR5cGVvZiB0eXBlID09PSAnb2JqZWN0JyAmJiB0eXBlICE9PSBudWxsICYmICh0eXBlLiQkdHlwZW9mID09PSBSRUFDVF9MQVpZX1RZUEUgfHwgdHlwZS4kJHR5cGVvZiA9PT0gUkVBQ1RfTUVNT19UWVBFIHx8IHR5cGUuJCR0eXBlb2YgPT09IFJFQUNUX1BST1ZJREVSX1RZUEUgfHwgdHlwZS4kJHR5cGVvZiA9PT0gUkVBQ1RfQ09OVEVYVF9UWVBFIHx8IHR5cGUuJCR0eXBlb2YgPT09IFJFQUNUX0ZPUldBUkRfUkVGX1RZUEUgfHwgdHlwZS4kJHR5cGVvZiA9PT0gUkVBQ1RfRlVOREFNRU5UQUxfVFlQRSB8fCB0eXBlLiQkdHlwZW9mID09PSBSRUFDVF9SRVNQT05ERVJfVFlQRSB8fCB0eXBlLiQkdHlwZW9mID09PSBSRUFDVF9TQ09QRV9UWVBFIHx8IHR5cGUuJCR0eXBlb2YgPT09IFJFQUNUX0JMT0NLX1RZUEUpO1xufVxuXG5mdW5jdGlvbiB0eXBlT2Yob2JqZWN0KSB7XG4gIGlmICh0eXBlb2Ygb2JqZWN0ID09PSAnb2JqZWN0JyAmJiBvYmplY3QgIT09IG51bGwpIHtcbiAgICB2YXIgJCR0eXBlb2YgPSBvYmplY3QuJCR0eXBlb2Y7XG5cbiAgICBzd2l0Y2ggKCQkdHlwZW9mKSB7XG4gICAgICBjYXNlIFJFQUNUX0VMRU1FTlRfVFlQRTpcbiAgICAgICAgdmFyIHR5cGUgPSBvYmplY3QudHlwZTtcblxuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICBjYXNlIFJFQUNUX0FTWU5DX01PREVfVFlQRTpcbiAgICAgICAgICBjYXNlIFJFQUNUX0NPTkNVUlJFTlRfTU9ERV9UWVBFOlxuICAgICAgICAgIGNhc2UgUkVBQ1RfRlJBR01FTlRfVFlQRTpcbiAgICAgICAgICBjYXNlIFJFQUNUX1BST0ZJTEVSX1RZUEU6XG4gICAgICAgICAgY2FzZSBSRUFDVF9TVFJJQ1RfTU9ERV9UWVBFOlxuICAgICAgICAgIGNhc2UgUkVBQ1RfU1VTUEVOU0VfVFlQRTpcbiAgICAgICAgICAgIHJldHVybiB0eXBlO1xuXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHZhciAkJHR5cGVvZlR5cGUgPSB0eXBlICYmIHR5cGUuJCR0eXBlb2Y7XG5cbiAgICAgICAgICAgIHN3aXRjaCAoJCR0eXBlb2ZUeXBlKSB7XG4gICAgICAgICAgICAgIGNhc2UgUkVBQ1RfQ09OVEVYVF9UWVBFOlxuICAgICAgICAgICAgICBjYXNlIFJFQUNUX0ZPUldBUkRfUkVGX1RZUEU6XG4gICAgICAgICAgICAgIGNhc2UgUkVBQ1RfTEFaWV9UWVBFOlxuICAgICAgICAgICAgICBjYXNlIFJFQUNUX01FTU9fVFlQRTpcbiAgICAgICAgICAgICAgY2FzZSBSRUFDVF9QUk9WSURFUl9UWVBFOlxuICAgICAgICAgICAgICAgIHJldHVybiAkJHR5cGVvZlR5cGU7XG5cbiAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gJCR0eXBlb2Y7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuXG4gICAgICBjYXNlIFJFQUNUX1BPUlRBTF9UWVBFOlxuICAgICAgICByZXR1cm4gJCR0eXBlb2Y7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn0gLy8gQXN5bmNNb2RlIGlzIGRlcHJlY2F0ZWQgYWxvbmcgd2l0aCBpc0FzeW5jTW9kZVxuXG52YXIgQXN5bmNNb2RlID0gUkVBQ1RfQVNZTkNfTU9ERV9UWVBFO1xudmFyIENvbmN1cnJlbnRNb2RlID0gUkVBQ1RfQ09OQ1VSUkVOVF9NT0RFX1RZUEU7XG52YXIgQ29udGV4dENvbnN1bWVyID0gUkVBQ1RfQ09OVEVYVF9UWVBFO1xudmFyIENvbnRleHRQcm92aWRlciA9IFJFQUNUX1BST1ZJREVSX1RZUEU7XG52YXIgRWxlbWVudCA9IFJFQUNUX0VMRU1FTlRfVFlQRTtcbnZhciBGb3J3YXJkUmVmID0gUkVBQ1RfRk9SV0FSRF9SRUZfVFlQRTtcbnZhciBGcmFnbWVudCA9IFJFQUNUX0ZSQUdNRU5UX1RZUEU7XG52YXIgTGF6eSA9IFJFQUNUX0xBWllfVFlQRTtcbnZhciBNZW1vID0gUkVBQ1RfTUVNT19UWVBFO1xudmFyIFBvcnRhbCA9IFJFQUNUX1BPUlRBTF9UWVBFO1xudmFyIFByb2ZpbGVyID0gUkVBQ1RfUFJPRklMRVJfVFlQRTtcbnZhciBTdHJpY3RNb2RlID0gUkVBQ1RfU1RSSUNUX01PREVfVFlQRTtcbnZhciBTdXNwZW5zZSA9IFJFQUNUX1NVU1BFTlNFX1RZUEU7XG52YXIgaGFzV2FybmVkQWJvdXREZXByZWNhdGVkSXNBc3luY01vZGUgPSBmYWxzZTsgLy8gQXN5bmNNb2RlIHNob3VsZCBiZSBkZXByZWNhdGVkXG5cbmZ1bmN0aW9uIGlzQXN5bmNNb2RlKG9iamVjdCkge1xuICB7XG4gICAgaWYgKCFoYXNXYXJuZWRBYm91dERlcHJlY2F0ZWRJc0FzeW5jTW9kZSkge1xuICAgICAgaGFzV2FybmVkQWJvdXREZXByZWNhdGVkSXNBc3luY01vZGUgPSB0cnVlOyAvLyBVc2luZyBjb25zb2xlWyd3YXJuJ10gdG8gZXZhZGUgQmFiZWwgYW5kIEVTTGludFxuXG4gICAgICBjb25zb2xlWyd3YXJuJ10oJ1RoZSBSZWFjdElzLmlzQXN5bmNNb2RlKCkgYWxpYXMgaGFzIGJlZW4gZGVwcmVjYXRlZCwgJyArICdhbmQgd2lsbCBiZSByZW1vdmVkIGluIFJlYWN0IDE3Ky4gVXBkYXRlIHlvdXIgY29kZSB0byB1c2UgJyArICdSZWFjdElzLmlzQ29uY3VycmVudE1vZGUoKSBpbnN0ZWFkLiBJdCBoYXMgdGhlIGV4YWN0IHNhbWUgQVBJLicpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBpc0NvbmN1cnJlbnRNb2RlKG9iamVjdCkgfHwgdHlwZU9mKG9iamVjdCkgPT09IFJFQUNUX0FTWU5DX01PREVfVFlQRTtcbn1cbmZ1bmN0aW9uIGlzQ29uY3VycmVudE1vZGUob2JqZWN0KSB7XG4gIHJldHVybiB0eXBlT2Yob2JqZWN0KSA9PT0gUkVBQ1RfQ09OQ1VSUkVOVF9NT0RFX1RZUEU7XG59XG5mdW5jdGlvbiBpc0NvbnRleHRDb25zdW1lcihvYmplY3QpIHtcbiAgcmV0dXJuIHR5cGVPZihvYmplY3QpID09PSBSRUFDVF9DT05URVhUX1RZUEU7XG59XG5mdW5jdGlvbiBpc0NvbnRleHRQcm92aWRlcihvYmplY3QpIHtcbiAgcmV0dXJuIHR5cGVPZihvYmplY3QpID09PSBSRUFDVF9QUk9WSURFUl9UWVBFO1xufVxuZnVuY3Rpb24gaXNFbGVtZW50KG9iamVjdCkge1xuICByZXR1cm4gdHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0ICE9PSBudWxsICYmIG9iamVjdC4kJHR5cGVvZiA9PT0gUkVBQ1RfRUxFTUVOVF9UWVBFO1xufVxuZnVuY3Rpb24gaXNGb3J3YXJkUmVmKG9iamVjdCkge1xuICByZXR1cm4gdHlwZU9mKG9iamVjdCkgPT09IFJFQUNUX0ZPUldBUkRfUkVGX1RZUEU7XG59XG5mdW5jdGlvbiBpc0ZyYWdtZW50KG9iamVjdCkge1xuICByZXR1cm4gdHlwZU9mKG9iamVjdCkgPT09IFJFQUNUX0ZSQUdNRU5UX1RZUEU7XG59XG5mdW5jdGlvbiBpc0xhenkob2JqZWN0KSB7XG4gIHJldHVybiB0eXBlT2Yob2JqZWN0KSA9PT0gUkVBQ1RfTEFaWV9UWVBFO1xufVxuZnVuY3Rpb24gaXNNZW1vKG9iamVjdCkge1xuICByZXR1cm4gdHlwZU9mKG9iamVjdCkgPT09IFJFQUNUX01FTU9fVFlQRTtcbn1cbmZ1bmN0aW9uIGlzUG9ydGFsKG9iamVjdCkge1xuICByZXR1cm4gdHlwZU9mKG9iamVjdCkgPT09IFJFQUNUX1BPUlRBTF9UWVBFO1xufVxuZnVuY3Rpb24gaXNQcm9maWxlcihvYmplY3QpIHtcbiAgcmV0dXJuIHR5cGVPZihvYmplY3QpID09PSBSRUFDVF9QUk9GSUxFUl9UWVBFO1xufVxuZnVuY3Rpb24gaXNTdHJpY3RNb2RlKG9iamVjdCkge1xuICByZXR1cm4gdHlwZU9mKG9iamVjdCkgPT09IFJFQUNUX1NUUklDVF9NT0RFX1RZUEU7XG59XG5mdW5jdGlvbiBpc1N1c3BlbnNlKG9iamVjdCkge1xuICByZXR1cm4gdHlwZU9mKG9iamVjdCkgPT09IFJFQUNUX1NVU1BFTlNFX1RZUEU7XG59XG5cbmV4cG9ydHMuQXN5bmNNb2RlID0gQXN5bmNNb2RlO1xuZXhwb3J0cy5Db25jdXJyZW50TW9kZSA9IENvbmN1cnJlbnRNb2RlO1xuZXhwb3J0cy5Db250ZXh0Q29uc3VtZXIgPSBDb250ZXh0Q29uc3VtZXI7XG5leHBvcnRzLkNvbnRleHRQcm92aWRlciA9IENvbnRleHRQcm92aWRlcjtcbmV4cG9ydHMuRWxlbWVudCA9IEVsZW1lbnQ7XG5leHBvcnRzLkZvcndhcmRSZWYgPSBGb3J3YXJkUmVmO1xuZXhwb3J0cy5GcmFnbWVudCA9IEZyYWdtZW50O1xuZXhwb3J0cy5MYXp5ID0gTGF6eTtcbmV4cG9ydHMuTWVtbyA9IE1lbW87XG5leHBvcnRzLlBvcnRhbCA9IFBvcnRhbDtcbmV4cG9ydHMuUHJvZmlsZXIgPSBQcm9maWxlcjtcbmV4cG9ydHMuU3RyaWN0TW9kZSA9IFN0cmljdE1vZGU7XG5leHBvcnRzLlN1c3BlbnNlID0gU3VzcGVuc2U7XG5leHBvcnRzLmlzQXN5bmNNb2RlID0gaXNBc3luY01vZGU7XG5leHBvcnRzLmlzQ29uY3VycmVudE1vZGUgPSBpc0NvbmN1cnJlbnRNb2RlO1xuZXhwb3J0cy5pc0NvbnRleHRDb25zdW1lciA9IGlzQ29udGV4dENvbnN1bWVyO1xuZXhwb3J0cy5pc0NvbnRleHRQcm92aWRlciA9IGlzQ29udGV4dFByb3ZpZGVyO1xuZXhwb3J0cy5pc0VsZW1lbnQgPSBpc0VsZW1lbnQ7XG5leHBvcnRzLmlzRm9yd2FyZFJlZiA9IGlzRm9yd2FyZFJlZjtcbmV4cG9ydHMuaXNGcmFnbWVudCA9IGlzRnJhZ21lbnQ7XG5leHBvcnRzLmlzTGF6eSA9IGlzTGF6eTtcbmV4cG9ydHMuaXNNZW1vID0gaXNNZW1vO1xuZXhwb3J0cy5pc1BvcnRhbCA9IGlzUG9ydGFsO1xuZXhwb3J0cy5pc1Byb2ZpbGVyID0gaXNQcm9maWxlcjtcbmV4cG9ydHMuaXNTdHJpY3RNb2RlID0gaXNTdHJpY3RNb2RlO1xuZXhwb3J0cy5pc1N1c3BlbnNlID0gaXNTdXNwZW5zZTtcbmV4cG9ydHMuaXNWYWxpZEVsZW1lbnRUeXBlID0gaXNWYWxpZEVsZW1lbnRUeXBlO1xuZXhwb3J0cy50eXBlT2YgPSB0eXBlT2Y7XG4gIH0pKCk7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/react-is/cjs/react-is.development.js\n");
/***/ }),
/***/ "./node_modules/react-is/index.js":
/*!****************************************!*\
!*** ./node_modules/react-is/index.js ***!
\****************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nif (false) {} else {\n module.exports = __webpack_require__(/*! ./cjs/react-is.development.js */ \"./node_modules/react-is/cjs/react-is.development.js\");\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9yZWFjdC1pcy9pbmRleC5qcz80Y2VjIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViLElBQUksS0FBcUMsRUFBRSxFQUUxQztBQUNELG1CQUFtQixtQkFBTyxDQUFDLDBGQUErQjtBQUMxRCIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9yZWFjdC1pcy9pbmRleC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbicpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2Nqcy9yZWFjdC1pcy5wcm9kdWN0aW9uLm1pbi5qcycpO1xufSBlbHNlIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2Nqcy9yZWFjdC1pcy5kZXZlbG9wbWVudC5qcycpO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/react-is/index.js\n");
/***/ }),
/***/ "./node_modules/setimmediate/setImmediate.js":
/*!***************************************************!*\
!*** ./node_modules/setimmediate/setImmediate.js ***!
\***************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) {\n \"use strict\";\n\n if (global.setImmediate) {\n return;\n }\n\n var nextHandle = 1; // Spec says greater than zero\n var tasksByHandle = {};\n var currentlyRunningATask = false;\n var doc = global.document;\n var registerImmediate;\n\n function setImmediate(callback) {\n // Callback can either be a function or a string\n if (typeof callback !== \"function\") {\n callback = new Function(\"\" + callback);\n }\n // Copy function arguments\n var args = new Array(arguments.length - 1);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i + 1];\n }\n // Store and register the task\n var task = { callback: callback, args: args };\n tasksByHandle[nextHandle] = task;\n registerImmediate(nextHandle);\n return nextHandle++;\n }\n\n function clearImmediate(handle) {\n delete tasksByHandle[handle];\n }\n\n function run(task) {\n var callback = task.callback;\n var args = task.args;\n switch (args.length) {\n case 0:\n callback();\n break;\n case 1:\n callback(args[0]);\n break;\n case 2:\n callback(args[0], args[1]);\n break;\n case 3:\n callback(args[0], args[1], args[2]);\n break;\n default:\n callback.apply(undefined, args);\n break;\n }\n }\n\n function runIfPresent(handle) {\n // From the spec: \"Wait until any invocations of this algorithm started before this one have completed.\"\n // So if we're currently running a task, we'll need to delay this invocation.\n if (currentlyRunningATask) {\n // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a\n // \"too much recursion\" error.\n setTimeout(runIfPresent, 0, handle);\n } else {\n var task = tasksByHandle[handle];\n if (task) {\n currentlyRunningATask = true;\n try {\n run(task);\n } finally {\n clearImmediate(handle);\n currentlyRunningATask = false;\n }\n }\n }\n }\n\n function installNextTickImplementation() {\n registerImmediate = function(handle) {\n process.nextTick(function () { runIfPresent(handle); });\n };\n }\n\n function canUsePostMessage() {\n // The test against `importScripts` prevents this implementation from being installed inside a web worker,\n // where `global.postMessage` means something completely different and can't be used for this purpose.\n if (global.postMessage && !global.importScripts) {\n var postMessageIsAsynchronous = true;\n var oldOnMessage = global.onmessage;\n global.onmessage = function() {\n postMessageIsAsynchronous = false;\n };\n global.postMessage(\"\", \"*\");\n global.onmessage = oldOnMessage;\n return postMessageIsAsynchronous;\n }\n }\n\n function installPostMessageImplementation() {\n // Installs an event handler on `global` for the `message` event: see\n // * https://developer.mozilla.org/en/DOM/window.postMessage\n // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages\n\n var messagePrefix = \"setImmediate$\" + Math.random() + \"$\";\n var onGlobalMessage = function(event) {\n if (event.source === global &&\n typeof event.data === \"string\" &&\n event.data.indexOf(messagePrefix) === 0) {\n runIfPresent(+event.data.slice(messagePrefix.length));\n }\n };\n\n if (global.addEventListener) {\n global.addEventListener(\"message\", onGlobalMessage, false);\n } else {\n global.attachEvent(\"onmessage\", onGlobalMessage);\n }\n\n registerImmediate = function(handle) {\n global.postMessage(messagePrefix + handle, \"*\");\n };\n }\n\n function installMessageChannelImplementation() {\n var channel = new MessageChannel();\n channel.port1.onmessage = function(event) {\n var handle = event.data;\n runIfPresent(handle);\n };\n\n registerImmediate = function(handle) {\n channel.port2.postMessage(handle);\n };\n }\n\n function installReadyStateChangeImplementation() {\n var html = doc.documentElement;\n registerImmediate = function(handle) {\n // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted\n // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.\n var script = doc.createElement(\"script\");\n script.onreadystatechange = function () {\n runIfPresent(handle);\n script.onreadystatechange = null;\n html.removeChild(script);\n script = null;\n };\n html.appendChild(script);\n };\n }\n\n function installSetTimeoutImplementation() {\n registerImmediate = function(handle) {\n setTimeout(runIfPresent, 0, handle);\n };\n }\n\n // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.\n var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);\n attachTo = attachTo && attachTo.setTimeout ? attachTo : global;\n\n // Don't get fooled by e.g. browserify environments.\n if ({}.toString.call(global.process) === \"[object process]\") {\n // For Node.js before 0.9\n installNextTickImplementation();\n\n } else if (canUsePostMessage()) {\n // For non-IE10 modern browsers\n installPostMessageImplementation();\n\n } else if (global.MessageChannel) {\n // For web workers, where supported\n installMessageChannelImplementation();\n\n } else if (doc && \"onreadystatechange\" in doc.createElement(\"script\")) {\n // For IE 68\n installReadyStateChangeImplementation();\n\n } else {\n // For older browsers\n installSetTimeoutImplementation();\n }\n\n attachTo.setImmediate = setImmediate;\n attachTo.clearImmediate = clearImmediate;\n}(typeof self === \"undefined\" ? typeof global === \"undefined\" ? this : global : self));\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\"), __webpack_require__(/*! ./../process/browser.js */ \"./node_modules/process/browser.js\")))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9zZXRpbW1lZGlhdGUvc2V0SW1tZWRpYXRlLmpzPzYwMTciXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQjtBQUN0QztBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMENBQTBDLHNCQUFzQixFQUFFO0FBQ2xFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL3NldGltbWVkaWF0ZS9zZXRJbW1lZGlhdGUuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gKGdsb2JhbCwgdW5kZWZpbmVkKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICBpZiAoZ2xvYmFsLnNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG5leHRIYW5kbGUgPSAxOyAvLyBTcGVjIHNheXMgZ3JlYXRlciB0aGFuIHplcm9cbiAgICB2YXIgdGFza3NCeUhhbmRsZSA9IHt9O1xuICAgIHZhciBjdXJyZW50bHlSdW5uaW5nQVRhc2sgPSBmYWxzZTtcbiAgICB2YXIgZG9jID0gZ2xvYmFsLmRvY3VtZW50O1xuICAgIHZhciByZWdpc3RlckltbWVkaWF0ZTtcblxuICAgIGZ1bmN0aW9uIHNldEltbWVkaWF0ZShjYWxsYmFjaykge1xuICAgICAgLy8gQ2FsbGJhY2sgY2FuIGVpdGhlciBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nXG4gICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBuZXcgRnVuY3Rpb24oXCJcIiArIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICAgIC8vIENvcHkgZnVuY3Rpb24gYXJndW1lbnRzXG4gICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBhcmdzW2ldID0gYXJndW1lbnRzW2kgKyAxXTtcbiAgICAgIH1cbiAgICAgIC8vIFN0b3JlIGFuZCByZWdpc3RlciB0aGUgdGFza1xuICAgICAgdmFyIHRhc2sgPSB7IGNhbGxiYWNrOiBjYWxsYmFjaywgYXJnczogYXJncyB9O1xuICAgICAgdGFza3NCeUhhbmRsZVtuZXh0SGFuZGxlXSA9IHRhc2s7XG4gICAgICByZWdpc3RlckltbWVkaWF0ZShuZXh0SGFuZGxlKTtcbiAgICAgIHJldHVybiBuZXh0SGFuZGxlKys7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xlYXJJbW1lZGlhdGUoaGFuZGxlKSB7XG4gICAgICAgIGRlbGV0ZSB0YXNrc0J5SGFuZGxlW2hhbmRsZV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcnVuKHRhc2spIHtcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gdGFzay5jYWxsYmFjaztcbiAgICAgICAgdmFyIGFyZ3MgPSB0YXNrLmFyZ3M7XG4gICAgICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICBjYWxsYmFjayhhcmdzWzBdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICBjYWxsYmFjayhhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICBjYWxsYmFjayhhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkodW5kZWZpbmVkLCBhcmdzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcnVuSWZQcmVzZW50KGhhbmRsZSkge1xuICAgICAgICAvLyBGcm9tIHRoZSBzcGVjOiBcIldhaXQgdW50aWwgYW55IGludm9jYXRpb25zIG9mIHRoaXMgYWxnb3JpdGhtIHN0YXJ0ZWQgYmVmb3JlIHRoaXMgb25lIGhhdmUgY29tcGxldGVkLlwiXG4gICAgICAgIC8vIFNvIGlmIHdlJ3JlIGN1cnJlbnRseSBydW5uaW5nIGEgdGFzaywgd2UnbGwgbmVlZCB0byBkZWxheSB0aGlzIGludm9jYXRpb24uXG4gICAgICAgIGlmIChjdXJyZW50bHlSdW5uaW5nQVRhc2spIHtcbiAgICAgICAgICAgIC8vIERlbGF5IGJ5IGRvaW5nIGEgc2V0VGltZW91dC4gc2V0SW1tZWRpYXRlIHdhcyB0cmllZCBpbnN0ZWFkLCBidXQgaW4gRmlyZWZveCA3IGl0IGdlbmVyYXRlZCBhXG4gICAgICAgICAgICAvLyBcInRvbyBtdWNoIHJlY3Vyc2lvblwiIGVycm9yLlxuICAgICAgICAgICAgc2V0VGltZW91dChydW5JZlByZXNlbnQsIDAsIGhhbmRsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgdGFzayA9IHRhc2tzQnlIYW5kbGVbaGFuZGxlXTtcbiAgICAgICAgICAgIGlmICh0YXNrKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudGx5UnVubmluZ0FUYXNrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBydW4odGFzayk7XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJJbW1lZGlhdGUoaGFuZGxlKTtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudGx5UnVubmluZ0FUYXNrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbE5leHRUaWNrSW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHJlZ2lzdGVySW1tZWRpYXRlID0gZnVuY3Rpb24oaGFuZGxlKSB7XG4gICAgICAgICAgICBwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uICgpIHsgcnVuSWZQcmVzZW50KGhhbmRsZSk7IH0pO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhblVzZVBvc3RNZXNzYWdlKCkge1xuICAgICAgICAvLyBUaGUgdGVzdCBhZ2FpbnN0IGBpbXBvcnRTY3JpcHRzYCBwcmV2ZW50cyB0aGlzIGltcGxlbWVudGF0aW9uIGZyb20gYmVpbmcgaW5zdGFsbGVkIGluc2lkZSBhIHdlYiB3b3JrZXIsXG4gICAgICAgIC8vIHdoZXJlIGBnbG9iYWwucG9zdE1lc3NhZ2VgIG1lYW5zIHNvbWV0aGluZyBjb21wbGV0ZWx5IGRpZmZlcmVudCBhbmQgY2FuJ3QgYmUgdXNlZCBmb3IgdGhpcyBwdXJwb3NlLlxuICAgICAgICBpZiAoZ2xvYmFsLnBvc3RNZXNzYWdlICYmICFnbG9iYWwuaW1wb3J0U2NyaXB0cykge1xuICAgICAgICAgICAgdmFyIHBvc3RNZXNzYWdlSXNBc3luY2hyb25vdXMgPSB0cnVlO1xuICAgICAgICAgICAgdmFyIG9sZE9uTWVzc2FnZSA9IGdsb2JhbC5vbm1lc3NhZ2U7XG4gICAgICAgICAgICBnbG9iYWwub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cyA9IGZhbHNlO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGdsb2JhbC5wb3N0TWVzc2FnZShcIlwiLCBcIipcIik7XG4gICAgICAgICAgICBnbG9iYWwub25tZXNzYWdlID0gb2xkT25NZXNzYWdlO1xuICAgICAgICAgICAgcmV0dXJuIHBvc3RNZXNzYWdlSXNBc3luY2hyb25vdXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsUG9zdE1lc3NhZ2VJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgLy8gSW5zdGFsbHMgYW4gZXZlbnQgaGFuZGxlciBvbiBgZ2xvYmFsYCBmb3IgdGhlIGBtZXNzYWdlYCBldmVudDogc2VlXG4gICAgICAgIC8vICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vRE9NL3dpbmRvdy5wb3N0TWVzc2FnZVxuICAgICAgICAvLyAqIGh0dHA6Ly93d3cud2hhdHdnLm9yZy9zcGVjcy93ZWItYXBwcy9jdXJyZW50LXdvcmsvbXVsdGlwYWdlL2NvbW1zLmh0bWwjY3Jvc3NEb2N1bWVudE1lc3NhZ2VzXG5cbiAgICAgICAgdmFyIG1lc3NhZ2VQcmVmaXggPSBcInNldEltbWVkaWF0ZSRcIiArIE1hdGgucmFuZG9tKCkgKyBcIiRcIjtcbiAgICAgICAgdmFyIG9uR2xvYmFsTWVzc2FnZSA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoZXZlbnQuc291cmNlID09PSBnbG9iYWwgJiZcbiAgICAgICAgICAgICAgICB0eXBlb2YgZXZlbnQuZGF0YSA9PT0gXCJzdHJpbmdcIiAmJlxuICAgICAgICAgICAgICAgIGV2ZW50LmRhdGEuaW5kZXhPZihtZXNzYWdlUHJlZml4KSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJ1bklmUHJlc2VudCgrZXZlbnQuZGF0YS5zbGljZShtZXNzYWdlUHJlZml4Lmxlbmd0aCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChnbG9iYWwuYWRkRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICAgICAgZ2xvYmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIG9uR2xvYmFsTWVzc2FnZSwgZmFsc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2xvYmFsLmF0dGFjaEV2ZW50KFwib25tZXNzYWdlXCIsIG9uR2xvYmFsTWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZWdpc3RlckltbWVkaWF0ZSA9IGZ1bmN0aW9uKGhhbmRsZSkge1xuICAgICAgICAgICAgZ2xvYmFsLnBvc3RNZXNzYWdlKG1lc3NhZ2VQcmVmaXggKyBoYW5kbGUsIFwiKlwiKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsTWVzc2FnZUNoYW5uZWxJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgdmFyIGNoYW5uZWwgPSBuZXcgTWVzc2FnZUNoYW5uZWwoKTtcbiAgICAgICAgY2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGV2ZW50LmRhdGE7XG4gICAgICAgICAgICBydW5JZlByZXNlbnQoaGFuZGxlKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3RlckltbWVkaWF0ZSA9IGZ1bmN0aW9uKGhhbmRsZSkge1xuICAgICAgICAgICAgY2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZShoYW5kbGUpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxSZWFkeVN0YXRlQ2hhbmdlSW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHZhciBodG1sID0gZG9jLmRvY3VtZW50RWxlbWVudDtcbiAgICAgICAgcmVnaXN0ZXJJbW1lZGlhdGUgPSBmdW5jdGlvbihoYW5kbGUpIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIDxzY3JpcHQ+IGVsZW1lbnQ7IGl0cyByZWFkeXN0YXRlY2hhbmdlIGV2ZW50IHdpbGwgYmUgZmlyZWQgYXN5bmNocm9ub3VzbHkgb25jZSBpdCBpcyBpbnNlcnRlZFxuICAgICAgICAgICAgLy8gaW50byB0aGUgZG9jdW1lbnQuIERvIHNvLCB0aHVzIHF1ZXVpbmcgdXAgdGhlIHRhc2suIFJlbWVtYmVyIHRvIGNsZWFuIHVwIG9uY2UgaXQncyBiZWVuIGNhbGxlZC5cbiAgICAgICAgICAgIHZhciBzY3JpcHQgPSBkb2MuY3JlYXRlRWxlbWVudChcInNjcmlwdFwiKTtcbiAgICAgICAgICAgIHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcnVuSWZQcmVzZW50KGhhbmRsZSk7XG4gICAgICAgICAgICAgICAgc2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaHRtbC5yZW1vdmVDaGlsZChzY3JpcHQpO1xuICAgICAgICAgICAgICAgIHNjcmlwdCA9IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHRtbC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxTZXRUaW1lb3V0SW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHJlZ2lzdGVySW1tZWRpYXRlID0gZnVuY3Rpb24oaGFuZGxlKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KHJ1bklmUHJlc2VudCwgMCwgaGFuZGxlKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBJZiBzdXBwb3J0ZWQsIHdlIHNob3VsZCBhdHRhY2ggdG8gdGhlIHByb3RvdHlwZSBvZiBnbG9iYWwsIHNpbmNlIHRoYXQgaXMgd2hlcmUgc2V0VGltZW91dCBldCBhbC4gbGl2ZS5cbiAgICB2YXIgYXR0YWNoVG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKGdsb2JhbCk7XG4gICAgYXR0YWNoVG8gPSBhdHRhY2hUbyAmJiBhdHRhY2hUby5zZXRUaW1lb3V0ID8gYXR0YWNoVG8gOiBnbG9iYWw7XG5cbiAgICAvLyBEb24ndCBnZXQgZm9vbGVkIGJ5IGUuZy4gYnJvd3NlcmlmeSBlbnZpcm9ubWVudHMuXG4gICAgaWYgKHt9LnRvU3RyaW5nLmNhbGwoZ2xvYmFsLnByb2Nlc3MpID09PSBcIltvYmplY3QgcHJvY2Vzc11cIikge1xuICAgICAgICAvLyBGb3IgTm9kZS5qcyBiZWZvcmUgMC45XG4gICAgICAgIGluc3RhbGxOZXh0VGlja0ltcGxlbWVudGF0aW9uKCk7XG5cbiAgICB9IGVsc2UgaWYgKGNhblVzZVBvc3RNZXNzYWdlKCkpIHtcbiAgICAgICAgLy8gRm9yIG5vbi1JRTEwIG1vZGVybiBicm93c2Vyc1xuICAgICAgICBpbnN0YWxsUG9zdE1lc3NhZ2VJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIGlmIChnbG9iYWwuTWVzc2FnZUNoYW5uZWwpIHtcbiAgICAgICAgLy8gRm9yIHdlYiB3b3JrZXJzLCB3aGVyZSBzdXBwb3J0ZWRcbiAgICAgICAgaW5zdGFsbE1lc3NhZ2VDaGFubmVsSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSBpZiAoZG9jICYmIFwib25yZWFkeXN0YXRlY2hhbmdlXCIgaW4gZG9jLmNyZWF0ZUVsZW1lbnQoXCJzY3JpcHRcIikpIHtcbiAgICAgICAgLy8gRm9yIElFIDbigJM4XG4gICAgICAgIGluc3RhbGxSZWFkeVN0YXRlQ2hhbmdlSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEZvciBvbGRlciBicm93c2Vyc1xuICAgICAgICBpbnN0YWxsU2V0VGltZW91dEltcGxlbWVudGF0aW9uKCk7XG4gICAgfVxuXG4gICAgYXR0YWNoVG8uc2V0SW1tZWRpYXRlID0gc2V0SW1tZWRpYXRlO1xuICAgIGF0dGFjaFRvLmNsZWFySW1tZWRpYXRlID0gY2xlYXJJbW1lZGlhdGU7XG59KHR5cGVvZiBzZWxmID09PSBcInVuZGVmaW5lZFwiID8gdHlwZW9mIGdsb2JhbCA9PT0gXCJ1bmRlZmluZWRcIiA/IHRoaXMgOiBnbG9iYWwgOiBzZWxmKSk7XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/setimmediate/setImmediate.js\n");
/***/ }),
/***/ "./node_modules/timers-browserify/main.js":
/*!************************************************!*\
!*** ./node_modules/timers-browserify/main.js ***!
\************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("/* WEBPACK VAR INJECTION */(function(global) {var scope = (typeof global !== \"undefined\" && global) ||\n (typeof self !== \"undefined\" && self) ||\n window;\nvar apply = Function.prototype.apply;\n\n// DOM APIs, for completeness\n\nexports.setTimeout = function() {\n return new Timeout(apply.call(setTimeout, scope, arguments), clearTimeout);\n};\nexports.setInterval = function() {\n return new Timeout(apply.call(setInterval, scope, arguments), clearInterval);\n};\nexports.clearTimeout =\nexports.clearInterval = function(timeout) {\n if (timeout) {\n timeout.close();\n }\n};\n\nfunction Timeout(id, clearFn) {\n this._id = id;\n this._clearFn = clearFn;\n}\nTimeout.prototype.unref = Timeout.prototype.ref = function() {};\nTimeout.prototype.close = function() {\n this._clearFn.call(scope, this._id);\n};\n\n// Does not start the time, just sets up the members needed.\nexports.enroll = function(item, msecs) {\n clearTimeout(item._idleTimeoutId);\n item._idleTimeout = msecs;\n};\n\nexports.unenroll = function(item) {\n clearTimeout(item._idleTimeoutId);\n item._idleTimeout = -1;\n};\n\nexports._unrefActive = exports.active = function(item) {\n clearTimeout(item._idleTimeoutId);\n\n var msecs = item._idleTimeout;\n if (msecs >= 0) {\n item._idleTimeoutId = setTimeout(function onTimeout() {\n if (item._onTimeout)\n item._onTimeout();\n }, msecs);\n }\n};\n\n// setimmediate attaches itself to the global object\n__webpack_require__(/*! setimmediate */ \"./node_modules/setimmediate/setImmediate.js\");\n// On some exotic environments, it's not clear which object `setimmediate` was\n// able to install onto. Search each possibility in the same order as the\n// `setimmediate` library.\nexports.setImmediate = (typeof self !== \"undefined\" && self.setImmediate) ||\n (typeof global !== \"undefined\" && global.setImmediate) ||\n (this && this.setImmediate);\nexports.clearImmediate = (typeof self !== \"undefined\" && self.clearImmediate) ||\n (typeof global !== \"undefined\" && global.clearImmediate) ||\n (this && this.clearImmediate);\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\")))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy90aW1lcnMtYnJvd3NlcmlmeS9tYWluLmpzPzUxMTgiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBLG1CQUFPLENBQUMsaUVBQWM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL3RpbWVycy1icm93c2VyaWZ5L21haW4uanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgc2NvcGUgPSAodHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBnbG9iYWwpIHx8XG4gICAgICAgICAgICAodHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgJiYgc2VsZikgfHxcbiAgICAgICAgICAgIHdpbmRvdztcbnZhciBhcHBseSA9IEZ1bmN0aW9uLnByb3RvdHlwZS5hcHBseTtcblxuLy8gRE9NIEFQSXMsIGZvciBjb21wbGV0ZW5lc3NcblxuZXhwb3J0cy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgVGltZW91dChhcHBseS5jYWxsKHNldFRpbWVvdXQsIHNjb3BlLCBhcmd1bWVudHMpLCBjbGVhclRpbWVvdXQpO1xufTtcbmV4cG9ydHMuc2V0SW50ZXJ2YWwgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIG5ldyBUaW1lb3V0KGFwcGx5LmNhbGwoc2V0SW50ZXJ2YWwsIHNjb3BlLCBhcmd1bWVudHMpLCBjbGVhckludGVydmFsKTtcbn07XG5leHBvcnRzLmNsZWFyVGltZW91dCA9XG5leHBvcnRzLmNsZWFySW50ZXJ2YWwgPSBmdW5jdGlvbih0aW1lb3V0KSB7XG4gIGlmICh0aW1lb3V0KSB7XG4gICAgdGltZW91dC5jbG9zZSgpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBUaW1lb3V0KGlkLCBjbGVhckZuKSB7XG4gIHRoaXMuX2lkID0gaWQ7XG4gIHRoaXMuX2NsZWFyRm4gPSBjbGVhckZuO1xufVxuVGltZW91dC5wcm90b3R5cGUudW5yZWYgPSBUaW1lb3V0LnByb3RvdHlwZS5yZWYgPSBmdW5jdGlvbigpIHt9O1xuVGltZW91dC5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fY2xlYXJGbi5jYWxsKHNjb3BlLCB0aGlzLl9pZCk7XG59O1xuXG4vLyBEb2VzIG5vdCBzdGFydCB0aGUgdGltZSwganVzdCBzZXRzIHVwIHRoZSBtZW1iZXJzIG5lZWRlZC5cbmV4cG9ydHMuZW5yb2xsID0gZnVuY3Rpb24oaXRlbSwgbXNlY3MpIHtcbiAgY2xlYXJUaW1lb3V0KGl0ZW0uX2lkbGVUaW1lb3V0SWQpO1xuICBpdGVtLl9pZGxlVGltZW91dCA9IG1zZWNzO1xufTtcblxuZXhwb3J0cy51bmVucm9sbCA9IGZ1bmN0aW9uKGl0ZW0pIHtcbiAgY2xlYXJUaW1lb3V0KGl0ZW0uX2lkbGVUaW1lb3V0SWQpO1xuICBpdGVtLl9pZGxlVGltZW91dCA9IC0xO1xufTtcblxuZXhwb3J0cy5fdW5yZWZBY3RpdmUgPSBleHBvcnRzLmFjdGl2ZSA9IGZ1bmN0aW9uKGl0ZW0pIHtcbiAgY2xlYXJUaW1lb3V0KGl0ZW0uX2lkbGVUaW1lb3V0SWQpO1xuXG4gIHZhciBtc2VjcyA9IGl0ZW0uX2lkbGVUaW1lb3V0O1xuICBpZiAobXNlY3MgPj0gMCkge1xuICAgIGl0ZW0uX2lkbGVUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uIG9uVGltZW91dCgpIHtcbiAgICAgIGlmIChpdGVtLl9vblRpbWVvdXQpXG4gICAgICAgIGl0ZW0uX29uVGltZW91dCgpO1xuICAgIH0sIG1zZWNzKTtcbiAgfVxufTtcblxuLy8gc2V0aW1tZWRpYXRlIGF0dGFjaGVzIGl0c2VsZiB0byB0aGUgZ2xvYmFsIG9iamVjdFxucmVxdWlyZShcInNldGltbWVkaWF0ZVwiKTtcbi8vIE9uIHNvbWUgZXhvdGljIGVudmlyb25tZW50cywgaXQncyBub3QgY2xlYXIgd2hpY2ggb2JqZWN0IGBzZXRpbW1lZGlhdGVgIHdhc1xuLy8gYWJsZSB0byBpbnN0YWxsIG9udG8uICBTZWFyY2ggZWFjaCBwb3NzaWJpbGl0eSBpbiB0aGUgc2FtZSBvcmRlciBhcyB0aGVcbi8vIGBzZXRpbW1lZGlhdGVgIGxpYnJhcnkuXG5leHBvcnRzLnNldEltbWVkaWF0ZSA9ICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiAmJiBzZWxmLnNldEltbWVkaWF0ZSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgJiYgZ2xvYmFsLnNldEltbWVkaWF0ZSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMgJiYgdGhpcy5zZXRJbW1lZGlhdGUpO1xuZXhwb3J0cy5jbGVhckltbWVkaWF0ZSA9ICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiAmJiBzZWxmLmNsZWFySW1tZWRpYXRlKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICh0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiICYmIGdsb2JhbC5jbGVhckltbWVkaWF0ZSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAodGhpcyAmJiB0aGlzLmNsZWFySW1tZWRpYXRlKTtcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/timers-browserify/main.js\n");
/***/ }),
/***/ "./node_modules/webpack/buildin/global.js":
/*!***********************************!*\
!*** (webpack)/buildin/global.js ***!
\***********************************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8od2VicGFjaykvYnVpbGRpbi9nbG9iYWwuanM/Y2QwMCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDRDQUE0Qzs7QUFFNUMiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvd2VicGFjay9idWlsZGluL2dsb2JhbC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbInZhciBnO1xuXG4vLyBUaGlzIHdvcmtzIGluIG5vbi1zdHJpY3QgbW9kZVxuZyA9IChmdW5jdGlvbigpIHtcblx0cmV0dXJuIHRoaXM7XG59KSgpO1xuXG50cnkge1xuXHQvLyBUaGlzIHdvcmtzIGlmIGV2YWwgaXMgYWxsb3dlZCAoc2VlIENTUClcblx0ZyA9IGcgfHwgbmV3IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKTtcbn0gY2F0Y2ggKGUpIHtcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcblx0aWYgKHR5cGVvZiB3aW5kb3cgPT09IFwib2JqZWN0XCIpIGcgPSB3aW5kb3c7XG59XG5cbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XG5cbm1vZHVsZS5leHBvcnRzID0gZztcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/webpack/buildin/global.js\n");
/***/ }),
/***/ "./node_modules/webpack/buildin/module.js":
/*!***********************************!*\
!*** (webpack)/buildin/module.js ***!
\***********************************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("module.exports = function(module) {\n\tif (!module.webpackPolyfill) {\n\t\tmodule.deprecate = function() {};\n\t\tmodule.paths = [];\n\t\t// module.parent = undefined by default\n\t\tif (!module.children) module.children = [];\n\t\tObject.defineProperty(module, \"loaded\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.l;\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(module, \"id\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.i;\n\t\t\t}\n\t\t});\n\t\tmodule.webpackPolyfill = 1;\n\t}\n\treturn module;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8od2VicGFjaykvYnVpbGRpbi9tb2R1bGUuanM/Y2VkMiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvd2VicGFjay9idWlsZGluL21vZHVsZS5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obW9kdWxlKSB7XG5cdGlmICghbW9kdWxlLndlYnBhY2tQb2x5ZmlsbCkge1xuXHRcdG1vZHVsZS5kZXByZWNhdGUgPSBmdW5jdGlvbigpIHt9O1xuXHRcdG1vZHVsZS5wYXRocyA9IFtdO1xuXHRcdC8vIG1vZHVsZS5wYXJlbnQgPSB1bmRlZmluZWQgYnkgZGVmYXVsdFxuXHRcdGlmICghbW9kdWxlLmNoaWxkcmVuKSBtb2R1bGUuY2hpbGRyZW4gPSBbXTtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkobW9kdWxlLCBcImxvYWRlZFwiLCB7XG5cdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0Z2V0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuIG1vZHVsZS5sO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUsIFwiaWRcIiwge1xuXHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcblx0XHRcdGdldDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiBtb2R1bGUuaTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRtb2R1bGUud2VicGFja1BvbHlmaWxsID0gMTtcblx0fVxuXHRyZXR1cm4gbW9kdWxlO1xufTtcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/webpack/buildin/module.js\n");
/***/ }),
/***/ "./src/lib/components/Cytoscape.react.js":
/*!***********************************************!*\
!*** ./src/lib/components/Cytoscape.react.js ***!
\***********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = __webpack_require__(/*! react */ \"react\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _propTypes = __webpack_require__(/*! prop-types */ \"./node_modules/prop-types/index.js\");\n\nvar _propTypes2 = _interopRequireDefault(_propTypes);\n\nvar _reactCytoscapejs = __webpack_require__(/*! react-cytoscapejs */ \"./node_modules/react-cytoscapejs/dist/react-cytoscape.js\");\n\nvar _reactCytoscapejs2 = _interopRequireDefault(_reactCytoscapejs);\n\nvar _lodash = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\n\nvar _lodash2 = _interopRequireDefault(_lodash);\n\nvar _cyResponsive = __webpack_require__(/*! ../cyResponsive.js */ \"./src/lib/cyResponsive.js\");\n\nvar _cyResponsive2 = _interopRequireDefault(_cyResponsive);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**\n * JavaScript Requirements: cytoscape, cytoscape-svg\n * React.js requirements: react-cytoscapejs\n */\n\n\n/**\nA Component Library for Dash aimed at facilitating network visualization in\nPython, wrapped around [Cytoscape.js](http://js.cytoscape.org/).\n */\nvar Cytoscape = function (_Component) {\n _inherits(Cytoscape, _Component);\n\n function Cytoscape(props) {\n _classCallCheck(this, Cytoscape);\n\n var _this = _possibleConstructorReturn(this, (Cytoscape.__proto__ || Object.getPrototypeOf(Cytoscape)).call(this, props));\n\n _this.handleCy = _this.handleCy.bind(_this);\n _this._handleCyCalled = false;\n _this.handleImageGeneration = _this.handleImageGeneration.bind(_this);\n _this.cyResponsiveClass = false;\n return _this;\n }\n\n _createClass(Cytoscape, [{\n key: 'generateNode',\n value: function generateNode(event) {\n var ele = event.target;\n\n var isParent = ele.isParent(),\n isChildless = ele.isChildless(),\n isChild = ele.isChild(),\n isOrphan = ele.isOrphan(),\n renderedPosition = ele.renderedPosition(),\n relativePosition = ele.relativePosition(),\n parent = ele.parent(),\n style = ele.style();\n\n // Trim down the element objects to only the data contained\n var edgesData = ele.connectedEdges().map(function (ele) {\n return ele.data();\n }),\n childrenData = ele.children().map(function (ele) {\n return ele.data();\n }),\n ancestorsData = ele.ancestors().map(function (ele) {\n return ele.data();\n }),\n descendantsData = ele.descendants().map(function (ele) {\n return ele.data();\n }),\n siblingsData = ele.siblings().map(function (ele) {\n return ele.data();\n });\n\n var timeStamp = event.timeStamp;\n\n var _ele$json = ele.json(),\n classes = _ele$json.classes,\n data = _ele$json.data,\n grabbable = _ele$json.grabbable,\n group = _ele$json.group,\n locked = _ele$json.locked,\n position = _ele$json.position,\n selected = _ele$json.selected,\n selectable = _ele$json.selectable;\n\n var parentData = void 0;\n if (parent) {\n parentData = parent.data();\n } else {\n parentData = null;\n }\n\n var nodeObject = {\n // Nodes attributes\n edgesData: edgesData,\n renderedPosition: renderedPosition,\n timeStamp: timeStamp,\n // From ele.json()\n classes: classes,\n data: data,\n grabbable: grabbable,\n group: group,\n locked: locked,\n position: position,\n selectable: selectable,\n selected: selected,\n // Compound Nodes additional attributes\n ancestorsData: ancestorsData,\n childrenData: childrenData,\n descendantsData: descendantsData,\n parentData: parentData,\n siblingsData: siblingsData,\n isParent: isParent,\n isChildless: isChildless,\n isChild: isChild,\n isOrphan: isOrphan,\n relativePosition: relativePosition,\n // Styling\n style: style\n };\n return nodeObject;\n }\n }, {\n key: 'generateEdge',\n value: function generateEdge(event) {\n var ele = event.target;\n\n var midpoint = ele.midpoint(),\n isLoop = ele.isLoop(),\n isSimple = ele.isSimple(),\n sourceData = ele.source().data(),\n sourceEndpoint = ele.sourceEndpoint(),\n style = ele.style(),\n targetData = ele.target().data(),\n targetEndpoint = ele.targetEndpoint();\n\n var timeStamp = event.timeStamp;\n\n var _ele$json2 = ele.json(),\n classes = _ele$json2.classes,\n data = _ele$json2.data,\n grabbable = _ele$json2.grabbable,\n group = _ele$json2.group,\n locked = _ele$json2.locked,\n selectable = _ele$json2.selectable,\n selected = _ele$json2.selected;\n\n var edgeObject = {\n // Edges attributes\n isLoop: isLoop,\n isSimple: isSimple,\n midpoint: midpoint,\n sourceData: sourceData,\n sourceEndpoint: sourceEndpoint,\n targetData: targetData,\n targetEndpoint: targetEndpoint,\n timeStamp: timeStamp,\n // From ele.json()\n classes: classes,\n data: data,\n grabbable: grabbable,\n group: group,\n locked: locked,\n selectable: selectable,\n selected: selected,\n // Styling\n style: style\n };\n\n return edgeObject;\n }\n }, {\n key: 'handleCy',\n value: function handleCy(cy) {\n var _this2 = this;\n\n // If the cy pointer has not been modified, and handleCy has already\n // been called before, than we don't run this function.\n if (cy === this._cy && this._handleCyCalled) {\n return;\n }\n this._cy = cy;\n window.cy = cy;\n this._handleCyCalled = true;\n\n // ///////////////////////////////////// CONSTANTS /////////////////////////////////////////\n var SELECT_THRESHOLD = 100;\n\n var selectedNodes = cy.collection();\n var selectedEdges = cy.collection();\n\n // ///////////////////////////////////// FUNCTIONS /////////////////////////////////////////\n var refreshLayout = _lodash2.default.debounce(function () {\n /**\n * Refresh Layout if needed\n */\n var _props = _this2.props,\n autoRefreshLayout = _props.autoRefreshLayout,\n layout = _props.layout;\n\n\n if (autoRefreshLayout) {\n cy.layout(layout).run();\n }\n }, SELECT_THRESHOLD);\n\n var sendSelectedNodesData = _lodash2.default.debounce(function () {\n /**\n This function is repetitively called every time a node is selected\n or unselected, but keeps being debounced if it is called again\n within 100 ms (given by SELECT_THRESHOLD). Effectively, it only\n runs when all the nodes have been correctly selected/unselected and\n added/removed from the selectedNodes collection, and then updates\n the selectedNodeData prop.\n */\n var nodeData = selectedNodes.map(function (el) {\n return el.data();\n });\n\n if (typeof _this2.props.setProps === 'function') {\n _this2.props.setProps({\n selectedNodeData: nodeData\n });\n }\n }, SELECT_THRESHOLD);\n\n var sendSelectedEdgesData = _lodash2.default.debounce(function () {\n var edgeData = selectedEdges.map(function (el) {\n return el.data();\n });\n\n if (typeof _this2.props.setProps === 'function') {\n _this2.props.setProps({\n selectedEdgeData: edgeData\n });\n }\n }, SELECT_THRESHOLD);\n\n // /////////////////////////////////////// EVENTS //////////////////////////////////////////\n cy.on('tap', 'node', function (event) {\n var nodeObject = _this2.generateNode(event);\n\n if (typeof _this2.props.setProps === 'function') {\n _this2.props.setProps({\n tapNode: nodeObject,\n tapNodeData: nodeObject.data\n });\n }\n });\n\n cy.on('tap', 'edge', function (event) {\n var edgeObject = _this2.generateEdge(event);\n\n if (typeof _this2.props.setProps === 'function') {\n _this2.props.setProps({\n tapEdge: edgeObject,\n tapEdgeData: edgeObject.data\n });\n }\n });\n\n cy.on('mouseover', 'node', function (event) {\n if (typeof _this2.props.setProps === 'function') {\n _this2.props.setProps({\n mouseoverNodeData: event.target.data()\n });\n }\n });\n\n cy.on('mouseover', 'edge', function (event) {\n if (typeof _this2.props.setProps === 'function') {\n _this2.props.setProps({\n mouseoverEdgeData: event.target.data()\n });\n }\n });\n\n cy.on('select', 'node', function (event) {\n var ele = event.target;\n\n selectedNodes.merge(ele);\n sendSelectedNodesData();\n });\n\n cy.on('unselect remove', 'node', function (event) {\n var ele = event.target;\n\n selectedNodes.unmerge(ele);\n sendSelectedNodesData();\n });\n\n cy.on('select', 'edge', function (event) {\n var ele = event.target;\n\n selectedEdges.merge(ele);\n sendSelectedEdgesData();\n });\n\n cy.on('unselect remove', 'edge', function (event) {\n var ele = event.target;\n\n selectedEdges.unmerge(ele);\n sendSelectedEdgesData();\n });\n\n cy.on('add remove', function () {\n refreshLayout();\n });\n\n this.cyResponsiveClass = new _cyResponsive2.default(cy);\n this.cyResponsiveClass.toggle(this.props.responsive);\n }\n }, {\n key: 'handleImageGeneration',\n value: function handleImageGeneration(imageType, imageOptions, actionsToPerform, fileName) {\n var _this3 = this;\n\n var options = {};\n if (imageOptions) {\n options = imageOptions;\n }\n\n var desiredOutput = options.output;\n options.output = 'blob';\n\n var downloadImage = void 0;\n var storeImage = void 0;\n switch (actionsToPerform) {\n case 'store':\n downloadImage = false;\n storeImage = true;\n break;\n case 'download':\n downloadImage = true;\n storeImage = false;\n break;\n case 'both':\n downloadImage = true;\n storeImage = true;\n break;\n default:\n downloadImage = false;\n storeImage = true;\n break;\n }\n\n var output = void 0;\n if (imageType === 'png') {\n output = this._cy.png(options);\n }\n if (imageType === 'jpg' || imageType === 'jpeg') {\n output = this._cy.jpg(options);\n }\n // only works when svg is imported (see lib/extra_index.js)\n if (imageType === 'svg') {\n output = this._cy.svg(options);\n }\n\n /*\n * If output is empty because of bad options or a cytoscape error,\n * skip any download or storage steps.\n */\n if (output && downloadImage) {\n /*\n * Downloading is initiated client-side because the image is generated at\n * the client. This avoids transferring a potentially large image\n * to the server and back again through a callback.\n */\n var fName = fileName;\n if (!fileName) {\n fName = 'cyto';\n }\n\n if (imageType !== 'svg') {\n this.downloadBlob(output, fName + '.' + imageType);\n } else {\n var blob = new Blob([output], {\n type: 'image/svg+xml;charset=utf-8'\n });\n this.downloadBlob(blob, fName + '.' + imageType);\n }\n }\n\n if (output && storeImage) {\n // Default output type if unspecified\n if (!desiredOutput) {\n desiredOutput = 'base64uri';\n }\n\n if (!(desiredOutput === 'base64uri' || desiredOutput === 'base64')) {\n return;\n }\n\n /*\n * Convert blob to base64uri or base64 string to store the image data.\n * Thank you, base64guru https://base64.guru/developers/javascript/examples/encode-blob\n */\n var reader = new FileReader();\n reader.onload = function () {\n /* FileReader is asynchronous, so the read function is non-blocking.\n * If this code block is placed after the read command, it\n * may result in empty output because the blob has not been loaded yet.\n */\n var callbackData = reader.result;\n if (desiredOutput === 'base64') {\n callbackData = callbackData.replace(/^data:.+;base64,/, '');\n }\n _this3.props.setProps({ imageData: callbackData });\n };\n reader.readAsDataURL(output);\n }\n }\n }, {\n key: 'downloadBlob',\n value: function downloadBlob(blob, fileName) {\n /*\n * Download blob as file by dynamically creating link.\n * Chrome does not open data URLs when JS opens a new tab directed\n * at the data URL, so this is an alternate implementation\n * that doesn't require extra packages. It may not behave in\n * exactly the same way across browsers (might display image in new tab\n * intead of downloading as a file).\n * Thank you, koldev https://jsfiddle.net/koldev/cW7W5/\n */\n var downloadLink = document.createElement('a');\n downloadLink.style = 'display: none';\n document.body.appendChild(downloadLink);\n\n var url = window.URL.createObjectURL(blob);\n downloadLink.href = url;\n downloadLink.download = fileName;\n downloadLink.click();\n window.URL.revokeObjectURL(url);\n\n document.body.removeChild(downloadLink);\n }\n }, {\n key: 'render',\n value: function render() {\n var _props2 = this.props,\n id = _props2.id,\n style = _props2.style,\n className = _props2.className,\n elements = _props2.elements,\n stylesheet = _props2.stylesheet,\n layout = _props2.layout,\n pan = _props2.pan,\n zoom = _props2.zoom,\n panningEnabled = _props2.panningEnabled,\n userPanningEnabled = _props2.userPanningEnabled,\n minZoom = _props2.minZoom,\n maxZoom = _props2.maxZoom,\n zoomingEnabled = _props2.zoomingEnabled,\n userZoomingEnabled = _props2.userZoomingEnabled,\n boxSelectionEnabled = _props2.boxSelectionEnabled,\n autoungrabify = _props2.autoungrabify,\n autolock = _props2.autolock,\n autounselectify = _props2.autounselectify,\n generateImage = _props2.generateImage,\n responsive = _props2.responsive;\n\n\n if (Object.keys(generateImage).length > 0) {\n // If no cytoscape object has been created yet, an image cannot be generated,\n // so generateImage will be ignored and cleared.\n this.props.setProps({ generateImage: {} });\n if (this._cy) {\n this.handleImageGeneration(generateImage.type, generateImage.options, generateImage.action, generateImage.filename);\n }\n }\n\n if (this.cyResponsiveClass) {\n this.cyResponsiveClass.toggle(responsive);\n }\n\n return _react2.default.createElement(_reactCytoscapejs2.default, {\n id: id,\n cy: this.handleCy,\n className: className,\n style: style,\n elements: _reactCytoscapejs2.default.normalizeElements(elements),\n stylesheet: stylesheet,\n layout: layout,\n pan: pan,\n zoom: zoom,\n panningEnabled: panningEnabled,\n userPanningEnabled: userPanningEnabled,\n minZoom: minZoom,\n maxZoom: maxZoom,\n zoomingEnabled: zoomingEnabled,\n userZoomingEnabled: userZoomingEnabled,\n boxSelectionEnabled: boxSelectionEnabled,\n autoungrabify: autoungrabify,\n autolock: autolock,\n autounselectify: autounselectify\n });\n }\n }]);\n\n return Cytoscape;\n}(_react.Component);\n\nCytoscape.propTypes = {\n // HTML attribute props\n\n /**\n * The ID used to identify this component in Dash callbacks.\n */\n id: _propTypes2.default.string,\n\n /**\n * Sets the class name of the element (the value of an element's html\n * class attribute).\n */\n className: _propTypes2.default.string,\n\n /**\n * Add inline styles to the root element.\n */\n style: _propTypes2.default.object,\n\n // Dash specific props\n\n /**\n * Dash-assigned callback that should be called whenever any of the\n * properties change.\n */\n setProps: _propTypes2.default.func,\n\n // Common props\n\n /**\n * A list of dictionaries representing the elements of the networks. Each dictionary describes an element, and\n * specifies its purpose. The [official Cytoscape.js documentation](https://js.cytoscape.org/#notation/elements-json)\n * offers an extensive overview and examples of element declaration.\n * Alternatively, a dictionary with the format { 'nodes': [], 'edges': [] } is allowed at initialization,\n * but arrays remain the recommended format.\n */\n elements: _propTypes2.default.oneOfType([_propTypes2.default.arrayOf(_propTypes2.default.shape({\n /**\n * Either 'nodes' or 'edges'. If not given, it's automatically inferred.\n */\n group: _propTypes2.default.string,\n /** Element specific data.*/\n data: _propTypes2.default.shape({\n /** Reference to the element, useful for selectors and edges. Randomly assigned if not given.*/\n id: _propTypes2.default.string,\n /**\n * Optional name for the element, useful when `data(label)` is given to a style's `content`\n * or `label`. It is only a convention. */\n label: _propTypes2.default.string,\n /** Only for nodes. Optional reference to another node. Needed to create compound nodes. */\n parent: _propTypes2.default.string,\n /** Only for edges. The id of the source node, which is where the edge starts. */\n source: _propTypes2.default.string,\n /** Only for edges. The id of the target node, where the edge ends. */\n target: _propTypes2.default.string\n }),\n /** Only for nodes. The position of the node. */\n position: _propTypes2.default.shape({\n /** The x-coordinate of the node. */\n x: _propTypes2.default.number,\n /** The y-coordinate of the node. */\n y: _propTypes2.default.number\n }),\n /** If the element is selected upon initialisation. */\n selected: _propTypes2.default.bool,\n /** If the element can be selected. */\n selectable: _propTypes2.default.bool,\n /** Only for nodes. If the position is immutable. */\n locked: _propTypes2.default.bool,\n /** Only for nodes. If the node can be grabbed and moved by the user. */\n grabbable: _propTypes2.default.bool,\n /**\n * Space separated string of class names of the element. Those classes can be selected\n * by a style selector.\n */\n classes: _propTypes2.default.string\n })), _propTypes2.default.exact({\n nodes: _propTypes2.default.array,\n edges: _propTypes2.default.array\n })]),\n\n /**\n * A list of dictionaries representing the styles of the elements.\n * Each dictionary requires the following keys: `selector` and `style`.\n *\n * Both the [selector](https://js.cytoscape.org/#selectors) and\n * the [style](https://js.cytoscape.org/#style/node-body) are\n * exhaustively documented in the Cytoscape.js docs. Although methods such\n * as `cy.elements(...)` and `cy.filter(...)` are not available, the selector\n * string syntax stays the same.\n */\n stylesheet: _propTypes2.default.arrayOf(_propTypes2.default.exact({\n /**\n * Which elements you are styling. Generally, you select a group of elements (node, edges, both),\n * a class (that you declare in the element dictionary), or an element by ID.\n */\n selector: _propTypes2.default.string.isRequired,\n /**\n * What aspects of the elements you want to modify. This could be the size or\n * color of a node, the shape of an edge arrow, or many more.\n */\n style: _propTypes2.default.object.isRequired\n })),\n\n /**\n * A dictionary specifying how to set the position of the elements in your\n * graph. The `'name'` key is required, and indicates which layout (algorithm) to\n * use. The keys accepted by `layout` vary depending on the algorithm, but these\n * keys are accepted by all layouts: `fit`, `padding`, `animate`, `animationDuration`,\n * `boundingBox`.\n *\n * The complete list of layouts and their accepted options are available on the\n * [Cytoscape.js docs](https://js.cytoscape.org/#layouts) . For the external layouts,\n * the options are listed in the \"API\" section of the README.\n * Note that certain keys are not supported in Dash since the value is a JavaScript\n * function or a callback. Please visit this\n * [issue](https://github.com/plotly/dash-cytoscape/issues/25) for more information.\n */\n layout: _propTypes2.default.shape({\n /**\n * The layouts available by default are:\n * `random`: Randomly assigns positions.\n * `preset`: Assigns position based on the `position` key in element dictionaries.\n * `circle`: Single-level circle, with optional radius.\n * `concentric`: Multi-level circle, with optional radius.\n * `grid`: Square grid, optionally with numbers of `rows` and `cols`.\n * `breadthfirst`: Tree structure built using BFS, with optional `roots`.\n * `cose`: Force-directed physics simulation.\n *\n * Some external layouts are also included. To use them, run\n * `dash_cytoscape.load_extra_layouts()` before creating your Dash app. Be careful about\n * using the extra layouts when not necessary, since they require supplementary bandwidth\n * for loading, which impacts the startup time of the app.\n * The external layouts are:\n * [cose-bilkent](https://github.com/cytoscape/cytoscape.js-cose-bilkent),\n * [cola](https://github.com/cytoscape/cytoscape.js-cola),\n * [euler](https://github.com/cytoscape/cytoscape.js-dagre),\n * [spread](https://github.com/cytoscape/cytoscape.js-spread),\n * [dagre](https://github.com/cytoscape/cytoscape.js-dagre),\n * [klay](https://github.com/cytoscape/cytoscape.js-klay),\n */\n name: _propTypes2.default.oneOf(['random', 'preset', 'circle', 'concentric', 'grid', 'breadthfirst', 'cose', 'close-bilkent', 'cola', 'euler', 'spread', 'dagre', 'klay']).isRequired,\n /** Whether to render the nodes in order to fit the canvas. */\n fit: _propTypes2.default.bool,\n /** Padding around the sides of the canvas, if fit is enabled. */\n padding: _propTypes2.default.number,\n /** Whether to animate change in position when the layout changes. */\n animate: _propTypes2.default.bool,\n /** Duration of animation in milliseconds, if enabled. */\n animationDuration: _propTypes2.default.number,\n /**\n * How to constrain the layout in a specific area. Keys accepted are either\n * `x1, y1, x2, y2` or `x1, y1, w, h`, all of which receive a pixel value.\n */\n boundingBox: _propTypes2.default.object\n }),\n\n // Viewport Manipulation\n\n /**\n * Dictionary indicating the initial panning position of the graph. The\n * following keys are accepted:\n */\n pan: _propTypes2.default.exact({\n /** The x-coordinate of the node */\n x: _propTypes2.default.number,\n /** The y-coordinate of the node */\n y: _propTypes2.default.number\n }),\n\n /**\n * The initial zoom level of the graph. You can set `minZoom` and\n * `maxZoom` to set restrictions on the zoom level.\n */\n zoom: _propTypes2.default.number,\n\n // Viewport Mutability and gesture Toggling\n /**\n * Whether panning the graph is enabled (i.e., the position of the graph is\n * mutable overall).\n */\n panningEnabled: _propTypes2.default.bool,\n\n /**\n * Whether user events (e.g. dragging the graph background) are allowed to\n * pan the graph.\n */\n userPanningEnabled: _propTypes2.default.bool,\n\n /**\n * A minimum bound on the zoom level of the graph. The viewport can not be\n * scaled smaller than this zoom level.\n */\n minZoom: _propTypes2.default.number,\n\n /**\n * A maximum bound on the zoom level of the graph. The viewport can not be\n * scaled larger than this zoom level.\n */\n maxZoom: _propTypes2.default.number,\n\n /**\n * Whether zooming the graph is enabled (i.e., the zoom level of the graph\n * is mutable overall).\n */\n zoomingEnabled: _propTypes2.default.bool,\n\n /**\n * Whether user events (e.g. dragging the graph background) are allowed\n * to pan the graph.\n */\n userZoomingEnabled: _propTypes2.default.bool,\n\n /**\n * Whether box selection (i.e. drag a box overlay around, and release it\n * to select) is enabled. If enabled, the user must taphold to pan the graph.\n */\n boxSelectionEnabled: _propTypes2.default.bool,\n\n /**\n * Whether nodes should be ungrabified (not grabbable by user) by\n * default (if true, overrides individual node state).\n */\n autoungrabify: _propTypes2.default.bool,\n\n /**\n * Whether nodes should be locked (not draggable at all) by default\n * (if true, overrides individual node state).\n */\n autolock: _propTypes2.default.bool,\n\n /**\n * Whether nodes should be unselectified (immutable selection state) by\n * default (if true, overrides individual element state).\n */\n autounselectify: _propTypes2.default.bool,\n\n /**\n * Whether the layout should be refreshed when elements are added or removed.\n */\n autoRefreshLayout: _propTypes2.default.bool,\n\n // User Events Props\n\n /**\n * The complete node dictionary returned when you tap or click it. Read-only.\n */\n tapNode: _propTypes2.default.exact({\n /** node specific item */\n edgesData: _propTypes2.default.array,\n /** node specific item */\n renderedPosition: _propTypes2.default.object,\n /** node specific item */\n timeStamp: _propTypes2.default.number,\n /** General item (for all elements) */\n classes: _propTypes2.default.string,\n /** General item (for all elements) */\n data: _propTypes2.default.object,\n /** General item (for all elements) */\n grabbable: _propTypes2.default.bool,\n /** General item (for all elements) */\n group: _propTypes2.default.string,\n /** General item (for all elements) */\n locked: _propTypes2.default.bool,\n /** General item (for all elements) */\n position: _propTypes2.default.object,\n /** General item (for all elements) */\n selectable: _propTypes2.default.bool,\n /** General item (for all elements) */\n selected: _propTypes2.default.bool,\n /** General item (for all elements) */\n style: _propTypes2.default.object,\n /** Item for compound nodes */\n ancestorsData: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.array]),\n /** Item for compound nodes */\n childrenData: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.array]),\n /** Item for compound nodes */\n descendantsData: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.array]),\n /** Item for compound nodes */\n parentData: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.array]),\n /** Item for compound nodes */\n siblingsData: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.array]),\n /** Item for compound nodes */\n isParent: _propTypes2.default.bool,\n /** Item for compound nodes */\n isChildless: _propTypes2.default.bool,\n /** Item for compound nodes */\n isChild: _propTypes2.default.bool,\n /** Item for compound nodes */\n isOrphan: _propTypes2.default.bool,\n /** Item for compound nodes */\n relativePosition: _propTypes2.default.object\n }),\n\n /**\n * The data dictionary of a node returned when you tap or click it. Read-only.\n */\n tapNodeData: _propTypes2.default.object,\n\n /**\n * The complete edge dictionary returned when you tap or click it. Read-only.\n */\n tapEdge: _propTypes2.default.exact({\n /** Edge-specific item */\n isLoop: _propTypes2.default.bool,\n /** Edge-specific item */\n isSimple: _propTypes2.default.bool,\n /** Edge-specific item */\n midpoint: _propTypes2.default.object,\n /** Edge-specific item */\n sourceData: _propTypes2.default.object,\n /** Edge-specific item */\n sourceEndpoint: _propTypes2.default.object,\n /** Edge-specific item */\n targetData: _propTypes2.default.object,\n /** Edge-specific item */\n targetEndpoint: _propTypes2.default.object,\n /** Edge-specific item */\n timeStamp: _propTypes2.default.number,\n /** General item (for all elements) */\n classes: _propTypes2.default.string,\n /** General item (for all elements) */\n data: _propTypes2.default.object,\n /** General item (for all elements) */\n grabbable: _propTypes2.default.bool,\n /** General item (for all elements) */\n group: _propTypes2.default.string,\n /** General item (for all elements) */\n locked: _propTypes2.default.bool,\n /** General item (for all elements) */\n selectable: _propTypes2.default.bool,\n /** General item (for all elements) */\n selected: _propTypes2.default.bool,\n /** General item (for all elements) */\n style: _propTypes2.default.object\n }),\n\n /**\n * The data dictionary of an edge returned when you tap or click it. Read-only.\n */\n tapEdgeData: _propTypes2.default.object,\n\n /**\n * The data dictionary of a node returned when you hover over it. Read-only.\n */\n mouseoverNodeData: _propTypes2.default.object,\n\n /**\n * The data dictionary of an edge returned when you hover over it. Read-only.\n */\n mouseoverEdgeData: _propTypes2.default.object,\n\n /**\n * The list of data dictionaries of all selected nodes (e.g. using\n * Shift+Click to select multiple nodes, or Shift+Drag to use box selection). Read-only.\n */\n selectedNodeData: _propTypes2.default.array,\n\n /**\n * The list of data dictionaries of all selected edges (e.g. using\n * Shift+Click to select multiple nodes, or Shift+Drag to use box selection). Read-only.\n */\n selectedEdgeData: _propTypes2.default.array,\n\n /**\n * Dictionary specifying options to generate an image of the current cytoscape graph.\n * Value is cleared after data is received and image is generated. This property will\n * be ignored on the initial creation of the cytoscape object and must be invoked through\n * a callback after it has been rendered.\n *\n * If the app does not need the image data server side and/or it will only be used to download\n * the image, it may be prudent to invoke `'download'` for `action` instead of\n * `'store'` to improve performance by preventing transfer of data to the server.\n */\n generateImage: _propTypes2.default.shape({\n /** File type to output */\n type: _propTypes2.default.oneOf(['svg', 'png', 'jpg', 'jpeg']),\n /** Dictionary of options to cy.png() / cy.jpg() or cy.svg() for image generation.\n * See https://js.cytoscape.org/#core/export for details. For `'output'`, only 'base64'\n * and 'base64uri' are supported. Default: `{'output': 'base64uri'}`.*/\n options: _propTypes2.default.object,\n /**\n * `'store'`: Stores the image data (only jpg and png are supported)\n * in `imageData` and invokes server-side Dash callbacks. `'download'`: Downloads the image\n * as a file with all data handling done client-side. No `imageData` callbacks are fired.\n * `'both'`: Stores image data and downloads image as file. The default is `'store'`\n */\n action: _propTypes2.default.oneOf(['store', 'download', 'both']),\n /** Name for the file to be downloaded. Default: 'cyto'.*/\n filename: _propTypes2.default.string\n }),\n\n /**\n * String representation of the image requested with generateImage. Null if no\n * image was requested yet or the previous request failed. Read-only.\n */\n imageData: _propTypes2.default.string,\n\n /**\n * Toggles intelligent responsive resize of Cytoscape graph with viewport size change\n */\n responsive: _propTypes2.default.bool\n};\n\nCytoscape.defaultProps = {\n style: { width: '600px', height: '600px' },\n layout: { name: 'grid' },\n pan: { x: 0, y: 0 },\n zoom: 1,\n minZoom: 1e-50,\n maxZoom: 1e50,\n zoomingEnabled: true,\n userZoomingEnabled: true,\n panningEnabled: true,\n userPanningEnabled: true,\n boxSelectionEnabled: false,\n autolock: false,\n autoungrabify: false,\n autounselectify: false,\n autoRefreshLayout: true,\n generateImage: {},\n imageData: null,\n responsive: false,\n elements: []\n};\n\nexports.default = Cytoscape;//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL3NyYy9saWIvY29tcG9uZW50cy9DeXRvc2NhcGUucmVhY3QuanM/NjQyYyJdLCJuYW1lcyI6WyJDeXRvc2NhcGUiLCJwcm9wcyIsImhhbmRsZUN5IiwiYmluZCIsIl9oYW5kbGVDeUNhbGxlZCIsImhhbmRsZUltYWdlR2VuZXJhdGlvbiIsImN5UmVzcG9uc2l2ZUNsYXNzIiwiZXZlbnQiLCJlbGUiLCJ0YXJnZXQiLCJpc1BhcmVudCIsImlzQ2hpbGRsZXNzIiwiaXNDaGlsZCIsImlzT3JwaGFuIiwicmVuZGVyZWRQb3NpdGlvbiIsInJlbGF0aXZlUG9zaXRpb24iLCJwYXJlbnQiLCJzdHlsZSIsImVkZ2VzRGF0YSIsImNvbm5lY3RlZEVkZ2VzIiwibWFwIiwiZGF0YSIsImNoaWxkcmVuRGF0YSIsImNoaWxkcmVuIiwiYW5jZXN0b3JzRGF0YSIsImFuY2VzdG9ycyIsImRlc2NlbmRhbnRzRGF0YSIsImRlc2NlbmRhbnRzIiwic2libGluZ3NEYXRhIiwic2libGluZ3MiLCJ0aW1lU3RhbXAiLCJqc29uIiwiY2xhc3NlcyIsImdyYWJiYWJsZSIsImdyb3VwIiwibG9ja2VkIiwicG9zaXRpb24iLCJzZWxlY3RlZCIsInNlbGVjdGFibGUiLCJwYXJlbnREYXRhIiwibm9kZU9iamVjdCIsIm1pZHBvaW50IiwiaXNMb29wIiwiaXNTaW1wbGUiLCJzb3VyY2VEYXRhIiwic291cmNlIiwic291cmNlRW5kcG9pbnQiLCJ0YXJnZXREYXRhIiwidGFyZ2V0RW5kcG9pbnQiLCJlZGdlT2JqZWN0IiwiY3kiLCJfY3kiLCJ3aW5kb3ciLCJTRUxFQ1RfVEhSRVNIT0xEIiwic2VsZWN0ZWROb2RlcyIsImNvbGxlY3Rpb24iLCJzZWxlY3RlZEVkZ2VzIiwicmVmcmVzaExheW91dCIsIl8iLCJkZWJvdW5jZSIsImF1dG9SZWZyZXNoTGF5b3V0IiwibGF5b3V0IiwicnVuIiwic2VuZFNlbGVjdGVkTm9kZXNEYXRhIiwibm9kZURhdGEiLCJlbCIsInNldFByb3BzIiwic2VsZWN0ZWROb2RlRGF0YSIsInNlbmRTZWxlY3RlZEVkZ2VzRGF0YSIsImVkZ2VEYXRhIiwic2VsZWN0ZWRFZGdlRGF0YSIsIm9uIiwiZ2VuZXJhdGVOb2RlIiwidGFwTm9kZSIsInRhcE5vZGVEYXRhIiwiZ2VuZXJhdGVFZGdlIiwidGFwRWRnZSIsInRhcEVkZ2VEYXRhIiwibW91c2VvdmVyTm9kZURhdGEiLCJtb3VzZW92ZXJFZGdlRGF0YSIsIm1lcmdlIiwidW5tZXJnZSIsIkN5UmVzcG9uc2l2ZSIsInRvZ2dsZSIsInJlc3BvbnNpdmUiLCJpbWFnZVR5cGUiLCJpbWFnZU9wdGlvbnMiLCJhY3Rpb25zVG9QZXJmb3JtIiwiZmlsZU5hbWUiLCJvcHRpb25zIiwiZGVzaXJlZE91dHB1dCIsIm91dHB1dCIsImRvd25sb2FkSW1hZ2UiLCJzdG9yZUltYWdlIiwicG5nIiwianBnIiwic3ZnIiwiZk5hbWUiLCJkb3dubG9hZEJsb2IiLCJibG9iIiwiQmxvYiIsInR5cGUiLCJyZWFkZXIiLCJGaWxlUmVhZGVyIiwib25sb2FkIiwiY2FsbGJhY2tEYXRhIiwicmVzdWx0IiwicmVwbGFjZSIsImltYWdlRGF0YSIsInJlYWRBc0RhdGFVUkwiLCJkb3dubG9hZExpbmsiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJib2R5IiwiYXBwZW5kQ2hpbGQiLCJ1cmwiLCJVUkwiLCJjcmVhdGVPYmplY3RVUkwiLCJocmVmIiwiZG93bmxvYWQiLCJjbGljayIsInJldm9rZU9iamVjdFVSTCIsInJlbW92ZUNoaWxkIiwiaWQiLCJjbGFzc05hbWUiLCJlbGVtZW50cyIsInN0eWxlc2hlZXQiLCJwYW4iLCJ6b29tIiwicGFubmluZ0VuYWJsZWQiLCJ1c2VyUGFubmluZ0VuYWJsZWQiLCJtaW5ab29tIiwibWF4Wm9vbSIsInpvb21pbmdFbmFibGVkIiwidXNlclpvb21pbmdFbmFibGVkIiwiYm94U2VsZWN0aW9uRW5hYmxlZCIsImF1dG91bmdyYWJpZnkiLCJhdXRvbG9jayIsImF1dG91bnNlbGVjdGlmeSIsImdlbmVyYXRlSW1hZ2UiLCJPYmplY3QiLCJrZXlzIiwibGVuZ3RoIiwiYWN0aW9uIiwiZmlsZW5hbWUiLCJDeXRvc2NhcGVDb21wb25lbnQiLCJub3JtYWxpemVFbGVtZW50cyIsIkNvbXBvbmVudCIsInByb3BUeXBlcyIsIlByb3BUeXBlcyIsInN0cmluZyIsIm9iamVjdCIsImZ1bmMiLCJvbmVPZlR5cGUiLCJhcnJheU9mIiwic2hhcGUiLCJsYWJlbCIsIngiLCJudW1iZXIiLCJ5IiwiYm9vbCIsImV4YWN0Iiwibm9kZXMiLCJhcnJheSIsImVkZ2VzIiwic2VsZWN0b3IiLCJpc1JlcXVpcmVkIiwibmFtZSIsIm9uZU9mIiwiZml0IiwicGFkZGluZyIsImFuaW1hdGUiLCJhbmltYXRpb25EdXJhdGlvbiIsImJvdW5kaW5nQm94IiwiZGVmYXVsdFByb3BzIiwid2lkdGgiLCJoZWlnaHQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBSUE7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFFQTs7Ozs7Ozs7OzsrZUFUQTs7Ozs7O0FBV0E7Ozs7SUFJTUEsUzs7O0FBQ0YsdUJBQVlDLEtBQVosRUFBbUI7QUFBQTs7QUFBQSwwSEFDVEEsS0FEUzs7QUFHZixjQUFLQyxRQUFMLEdBQWdCLE1BQUtBLFFBQUwsQ0FBY0MsSUFBZCxPQUFoQjtBQUNBLGNBQUtDLGVBQUwsR0FBdUIsS0FBdkI7QUFDQSxjQUFLQyxxQkFBTCxHQUE2QixNQUFLQSxxQkFBTCxDQUEyQkYsSUFBM0IsT0FBN0I7QUFDQSxjQUFLRyxpQkFBTCxHQUF5QixLQUF6QjtBQU5lO0FBT2xCOzs7O3FDQUVZQyxLLEVBQU87QUFDaEIsZ0JBQU1DLE1BQU1ELE1BQU1FLE1BQWxCOztBQUVBLGdCQUFNQyxXQUFXRixJQUFJRSxRQUFKLEVBQWpCO0FBQUEsZ0JBQ0lDLGNBQWNILElBQUlHLFdBQUosRUFEbEI7QUFBQSxnQkFFSUMsVUFBVUosSUFBSUksT0FBSixFQUZkO0FBQUEsZ0JBR0lDLFdBQVdMLElBQUlLLFFBQUosRUFI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QWUsS0FiTTtBQWNyQkUscUJBQWlCLEtBZEk7QUFlckI5RSx1QkFBbUIsSUFmRTtBQWdCckIrRSxtQkFBZSxFQWhCTTtBQWlCckIvQixlQUFXLElBakJVO0FBa0JyQnhCLGdCQUFZLEtBbEJTO0FBbUJyQnlDLGNBQVU7QUFuQlcsQ0FBekI7O2tCQXNCZTdILFMiLCJmaWxlIjoiLi9zcmMvbGliL2NvbXBvbmVudHMvQ3l0b3NjYXBlLnJlYWN0LmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBKYXZhU2NyaXB0IFJlcXVpcmVtZW50czogY3l0b3NjYXBlLCBjeXRvc2NhcGUtc3ZnXG4gKiBSZWFjdC5qcyByZXF1aXJlbWVudHM6IHJlYWN0LWN5dG9zY2FwZWpzXG4gKi9cbmltcG9ydCBSZWFjdCwge0NvbXBvbmVudH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tICdwcm9wLXR5cGVzJztcbmltcG9ydCBDeXRvc2NhcGVDb21wb25lbnQgZnJvbSAncmVhY3QtY3l0b3NjYXBlanMnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcblxuaW1wb3J0IEN5UmVzcG9uc2l2ZSBmcm9tICcuLi9jeVJlc3BvbnNpdmUuanMnO1xuXG4vKipcbkEgQ29tcG9uZW50IExpYnJhcnkgZm9yIERhc2ggYWltZWQgYXQgZmFjaWxpdGF0aW5nIG5ldHdvcmsgdmlzdWFsaXphdGlvbiBpblxuUHl0aG9uLCB3cmFwcGVkIGFyb3VuZCBbQ3l0b3NjYXBlLmpzXShodHRwOi8vanMuY3l0b3NjYXBlLm9yZy8pLlxuICovXG5jbGFzcyBDeXRvc2NhcGUgZXh0ZW5kcyBDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcblxuICAgICAgICB0aGlzLmhhbmRsZUN5ID0gdGhpcy5oYW5kbGVDeS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLl9oYW5kbGVDeUNhbGxlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmhhbmRsZUltYWdlR2VuZXJhdGlvbiA9IHRoaXMuaGFuZGxlSW1hZ2VHZW5lcmF0aW9uLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuY3lSZXNwb25zaXZlQ2xhc3MgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBnZW5lcmF0ZU5vZGUoZXZlbnQpIHtcbiAgICAgICAgY29uc3QgZWxlID0gZXZlbnQudGFyZ2V0O1xuXG4gICAgICAgIGNvbnN0IGlzUGFyZW50ID0gZWxlLmlzUGFyZW50KCksXG4gICAgICAgICAgICBpc0NoaWxkbGVzcyA9IGVsZS5pc0NoaWxkbGVzcygpLFxuICAgICAgICAgICAgaXNDaGlsZCA9IGVsZS5pc0NoaWxkKCksXG4gICAgICAgICAgICBpc09ycGhhbiA9IGVsZS5pc09ycGhhbigpLFxuICAgICAgICAgICAgcmVuZGVyZWRQb3NpdGlvbiA9IGVsZS5yZW5kZXJlZFBvc2l0aW9uKCksXG4gICAgICAgICAgICByZWxhdGl2ZVBvc2l0aW9uID0gZWxlLnJlbGF0aXZlUG9zaXRpb24oKSxcbiAgICAgICAgICAgIHBhcmVudCA9IGVsZS5wYXJlbnQoKSxcbiAgICAgICAgICAgIHN0eWxlID0gZWxlLnN0eWxlKCk7XG5cbiAgICAgICAgLy8gVHJpbSBkb3duIHRoZSBlbGVtZW50IG9iamVjdHMgdG8gb25seSB0aGUgZGF0YSBjb250YWluZWRcbiAgICAgICAgY29uc3QgZWRnZXNEYXRhID0gZWxlLmNvbm5lY3RlZEVkZ2VzKCkubWFwKGVsZSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZS5kYXRhKCk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNoaWxkcmVuRGF0YSA9IGVsZS5jaGlsZHJlbigpLm1hcChlbGUgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBlbGUuZGF0YSgpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBhbmNlc3RvcnNEYXRhID0gZWxlLmFuY2VzdG9ycygpLm1hcChlbGUgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBlbGUuZGF0YSgpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBkZXNjZW5kYW50c0RhdGEgPSBlbGUuZGVzY2VuZGFudHMoKS5tYXAoZWxlID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZWxlLmRhdGEoKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgc2libGluZ3NEYXRhID0gZWxlLnNpYmxpbmdzKCkubWFwKGVsZSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZS5kYXRhKCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB7dGltZVN0YW1wfSA9IGV2ZW50O1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBjbGFzc2VzLFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgIGdyYWJiYWJsZSxcbiAgICAgICAgICAgIGdyb3VwLFxuICAgICAgICAgICAgbG9ja2VkLFxuICAgICAgICAgICAgcG9zaXRpb24sXG4gICAgICAgICAgICBzZWxlY3RlZCxcbiAgICAgICAgICAgIHNlbGVjdGFibGVcbiAgICAgICAgfSA9IGVsZS5qc29uKCk7XG5cbiAgICAgICAgbGV0IHBhcmVudERhdGE7XG4gICAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgICAgIHBhcmVudERhdGEgPSBwYXJlbnQuZGF0YSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGFyZW50RGF0YSA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBub2RlT2JqZWN0ID0ge1xuICAgICAgICAgICAgLy8gTm9kZXMgYXR0cmlidXRlc1xuICAgICAgICAgICAgZWRnZXNEYXRhLFxuICAgICAgICAgICAgcmVuZGVyZWRQb3NpdGlvbixcbiAgICAgICAgICAgIHRpbWVTdGFtcCxcbiAgICAgICAgICAgIC8vIEZyb20gZWxlLmpzb24oKVxuICAgICAgICAgICAgY2xhc3NlcyxcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBncmFiYmFibGUsXG4gICAgICAgICAgICBncm91cCxcbiAgICAgICAgICAgIGxvY2tlZCxcbiAgICAgICAgICAgIHBvc2l0aW9uLFxuICAgICAgICAgICAgc2VsZWN0YWJsZSxcbiAgICAgICAgICAgIHNlbGVjdGVkLFxuICAgICAgICAgICAgLy8gQ29tcG91bmQgTm9kZXMgYWRkaXRpb25hbCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICBhbmNlc3RvcnNEYXRhLFxuICAgICAgICAgICAgY2hpbGRyZW5EYXRhLFxuICAgICAgICAgICAgZGVzY2VuZGFudHNEYXRhLFxuICAgICAgICAgICAgcGFyZW50RGF0YSxcbiAgICAgICAgICAgIHNpYmxpbmdzRGF0YSxcbiAgICAgICAgICAgIGlzUGFyZW50LFxuICAgICAgICAgICAgaXNDaGlsZGxlc3MsXG4gICAgICAgICAgICBpc0NoaWxkLFxuICAgICAgICAgICAgaXNPcnBoYW4sXG4gICAgICAgICAgICByZWxhdGl2ZVBvc2l0aW9uLFxuICAgICAgICAgICAgLy8gU3R5bGluZ1xuICAgICAgICAgICAgc3R5bGVcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIG5vZGVPYmplY3Q7XG4gICAgfVxuXG4gICAgZ2VuZXJhdGVFZGdlKGV2ZW50KSB7XG4gICAgICAgIGNvbnN0IGVsZSA9IGV2ZW50LnRhcmdldDtcblxuICAgICAgICBjb25zdCBtaWRwb2ludCA9IGVsZS5taWRwb2ludCgpLFxuICAgICAgICAgICAgaXNMb29wID0gZWxlLmlzTG9vcCgpLFxuICAgICAgICAgICAgaXNTaW1wbGUgPSBlbGUuaXNTaW1wbGUoKSxcbiAgICAgICAgICAgIHNvdXJjZURhdGEgPSBlbGUuc291cmNlKCkuZGF0YSgpLFxuICAgICAgICAgICAgc291cmNlRW5kcG9pbnQgPSBlbGUuc291cmNlRW5kcG9pbnQoKSxcbiAgICAgICAgICAgIHN0eWxlID0gZWxlLnN0eWxlKCksXG4gICAgICAgICAgICB0YXJnZXREYXRhID0gZWxlLnRhcmdldCgpLmRhdGEoKSxcbiAgICAgICAgICAgIHRhcmdldEVuZHBvaW50ID0gZWxlLnRhcmdldEVuZHBvaW50KCk7XG5cbiAgICAgICAgY29uc3Qge3RpbWVTdGFtcH0gPSBldmVudDtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgY2xhc3NlcyxcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBncmFiYmFibGUsXG4gICAgICAgICAgICBncm91cCxcbiAgICAgICAgICAgIGxvY2tlZCxcbiAgICAgICAgICAgIHNlbGVjdGFibGUsXG4gICAgICAgICAgICBzZWxlY3RlZFxuICAgICAgICB9ID0gZWxlLmpzb24oKTtcblxuICAgICAgICBjb25zdCBlZGdlT2JqZWN0ID0ge1xuICAgICAgICAgICAgLy8gRWRnZXMgYXR0cmlidXRlc1xuICAgICAgICAgICAgaXNMb29wLFxuICAgICAgICAgICAgaXNTaW1wbGUsXG4gICAgICAgICAgICBtaWRwb2ludCxcbiAgICAgICAgICAgIHNvdXJjZURhdGEsXG4gICAgICAgICAgICBzb3VyY2VFbmRwb2ludCxcbiAgICAgICAgICAgIHRhcmdldERhdGEsXG4gICAgICAgICAgICB0YXJnZXRFbmRwb2ludCxcbiAgICAgICAgICAgIHRpbWVTdGFtcCxcbiAgICAgICAgICAgIC8vIEZyb20gZWxlLmpzb24oKVxuICAgICAgICAgICAgY2xhc3NlcyxcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBncmFiYmFibGUsXG4gICAgICAgICAgICBncm91cCxcbiAgICAgICAgICAgIGxvY2tlZCxcbiAgICAgICAgICAgIHNlbGVjdGFibGUsXG4gICAgICAgICAgICBzZWxlY3RlZCxcbiAgICAgICAgICAgIC8vIFN0eWxpbmdcbiAgICAgICAgICAgIHN0eWxlXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIGVkZ2VPYmplY3Q7XG4gICAgfVxuXG4gICAgaGFuZGxlQ3koY3kpIHtcbiAgICAgICAgLy8gSWYgdGhlIGN5IHBvaW50ZXIgaGFzIG5vdCBiZWVuIG1vZGlmaWVkLCBhbmQgaGFuZGxlQ3kgaGFzIGFscmVhZHlcbiAgICAgICAgLy8gYmVlbiBjYWxsZWQgYmVmb3JlLCB0aGFuIHdlIGRvbid0IHJ1biB0aGlzIGZ1bmN0aW9uLlxuICAgICAgICBpZiAoY3kgPT09IHRoaXMuX2N5ICYmIHRoaXMuX2hhbmRsZUN5Q2FsbGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY3kgPSBjeTtcbiAgICAgICAgd2luZG93LmN5ID0gY3k7XG4gICAgICAgIHRoaXMuX2hhbmRsZUN5Q2FsbGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vIENPTlNUQU5UUyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICBjb25zdCBTRUxFQ1RfVEhSRVNIT0xEID0gMTAwO1xuXG4gICAgICAgIGNvbnN0IHNlbGVjdGVkTm9kZXMgPSBjeS5jb2xsZWN0aW9uKCk7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRWRnZXMgPSBjeS5jb2xsZWN0aW9uKCk7XG5cbiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLyBGVU5DVElPTlMgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgY29uc3QgcmVmcmVzaExheW91dCA9IF8uZGVib3VuY2UoKCkgPT4ge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZWZyZXNoIExheW91dCBpZiBuZWVkZWRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY29uc3Qge2F1dG9SZWZyZXNoTGF5b3V0LCBsYXlvdXR9ID0gdGhpcy5wcm9wcztcblxuICAgICAgICAgICAgaWYgKGF1dG9SZWZyZXNoTGF5b3V0KSB7XG4gICAgICAgICAgICAgICAgY3kubGF5b3V0KGxheW91dCkucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIFNFTEVDVF9USFJFU0hPTEQpO1xuXG4gICAgICAgIGNvbnN0IHNlbmRTZWxlY3RlZE5vZGVzRGF0YSA9IF8uZGVib3VuY2UoKCkgPT4ge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgVGhpcyBmdW5jdGlvbiBpcyByZXBldGl0aXZlbHkgY2FsbGVkIGV2ZXJ5IHRpbWUgYSBub2RlIGlzIHNlbGVjdGVkXG4gICAgICAgICAgICAgb3IgdW5zZWxlY3RlZCwgYnV0IGtlZXBzIGJlaW5nIGRlYm91bmNlZCBpZiBpdCBpcyBjYWxsZWQgYWdhaW5cbiAgICAgICAgICAgICB3aXRoaW4gMTAwIG1zIChnaXZlbiBieSBTRUxFQ1RfVEhSRVNIT0xEKS4gRWZmZWN0aXZlbHksIGl0IG9ubHlcbiAgICAgICAgICAgICBydW5zIHdoZW4gYWxsIHRoZSBub2RlcyBoYXZlIGJlZW4gY29ycmVjdGx5IHNlbGVjdGVkL3Vuc2VsZWN0ZWQgYW5kXG4gICAgICAgICAgICAgYWRkZWQvcmVtb3ZlZCBmcm9tIHRoZSBzZWxlY3RlZE5vZGVzIGNvbGxlY3Rpb24sIGFuZCB0aGVuIHVwZGF0ZXNcbiAgICAgICAgICAgICB0aGUgc2VsZWN0ZWROb2RlRGF0YSBwcm9wLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBjb25zdCBub2RlRGF0YSA9IHNlbGVjdGVkTm9kZXMubWFwKGVsID0+IGVsLmRhdGEoKSk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy5zZXRQcm9wcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuc2V0UHJvcHMoe1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZE5vZGVEYXRhOiBub2RlRGF0YVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBTRUxFQ1RfVEhSRVNIT0xEKTtcblxuICAgICAgICBjb25zdCBzZW5kU2VsZWN0ZWRFZGdlc0RhdGEgPSBfLmRlYm91bmNlKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVkZ2VEYXRhID0gc2VsZWN0ZWRFZGdlcy5tYXAoZWwgPT4gZWwuZGF0YSgpKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnByb3BzLnNldFByb3BzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5zZXRQcm9wcyh7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRWRnZURhdGE6IGVkZ2VEYXRhXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIFNFTEVDVF9USFJFU0hPTEQpO1xuXG4gICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLyBFVkVOVFMgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgIGN5Lm9uKCd0YXAnLCAnbm9kZScsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5vZGVPYmplY3QgPSB0aGlzLmdlbmVyYXRlTm9kZShldmVudCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy5zZXRQcm9wcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuc2V0UHJvcHMoe1xuICAgICAgICAgICAgICAgICAgICB0YXBOb2RlOiBub2RlT2JqZWN0LFxuICAgICAgICAgICAgICAgICAgICB0YXBOb2RlRGF0YTogbm9kZU9iamVjdC5kYXRhXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGN5Lm9uKCd0YXAnLCAnZWRnZScsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVkZ2VPYmplY3QgPSB0aGlzLmdlbmVyYXRlRWRnZShldmVudCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy5zZXRQcm9wcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuc2V0UHJvcHMoe1xuICAgICAgICAgICAgICAgICAgICB0YXBFZGdlOiBlZGdlT2JqZWN0LFxuICAgICAgICAgICAgICAgICAgICB0YXBFZGdlRGF0YTogZWRnZU9iamVjdC5kYXRhXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGN5Lm9uKCdtb3VzZW92ZXInLCAnbm9kZScsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy5zZXRQcm9wcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuc2V0UHJvcHMoe1xuICAgICAgICAgICAgICAgICAgICBtb3VzZW92ZXJOb2RlRGF0YTogZXZlbnQudGFyZ2V0LmRhdGEoKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBjeS5vbignbW91c2VvdmVyJywgJ2VkZ2UnLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMucHJvcHMuc2V0UHJvcHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BzLnNldFByb3BzKHtcbiAgICAgICAgICAgICAgICAgICAgbW91c2VvdmVyRWRnZURhdGE6IGV2ZW50LnRhcmdldC5kYXRhKClcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgY3kub24oJ3NlbGVjdCcsICdub2RlJywgZXZlbnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgZWxlID0gZXZlbnQudGFyZ2V0O1xuXG4gICAgICAgICAgICBzZWxlY3RlZE5vZGVzLm1lcmdlKGVsZSk7XG4gICAgICAgICAgICBzZW5kU2VsZWN0ZWROb2Rlc0RhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY3kub24oJ3Vuc2VsZWN0IHJlbW92ZScsICdub2RlJywgZXZlbnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgZWxlID0gZXZlbnQudGFyZ2V0O1xuXG4gICAgICAgICAgICBzZWxlY3RlZE5vZGVzLnVubWVyZ2UoZWxlKTtcbiAgICAgICAgICAgIHNlbmRTZWxlY3RlZE5vZGVzRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjeS5vbignc2VsZWN0JywgJ2VkZ2UnLCBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbGUgPSBldmVudC50YXJnZXQ7XG5cbiAgICAgICAgICAgIHNlbGVjdGVkRWRnZXMubWVyZ2UoZWxlKTtcbiAgICAgICAgICAgIHNlbmRTZWxlY3RlZEVkZ2VzRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjeS5vbigndW5zZWxlY3QgcmVtb3ZlJywgJ2VkZ2UnLCBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbGUgPSBldmVudC50YXJnZXQ7XG5cbiAgICAgICAgICAgIHNlbGVjdGVkRWRnZXMudW5tZXJnZShlbGUpO1xuICAgICAgICAgICAgc2VuZFNlbGVjdGVkRWRnZXNEYXRhKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGN5Lm9uKCdhZGQgcmVtb3ZlJywgKCkgPT4ge1xuICAgICAgICAgICAgcmVmcmVzaExheW91dCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmN5UmVzcG9uc2l2ZUNsYXNzID0gbmV3IEN5UmVzcG9uc2l2ZShjeSk7XG4gICAgICAgIHRoaXMuY3lSZXNwb25zaXZlQ2xhc3MudG9nZ2xlKHRoaXMucHJvcHMucmVzcG9uc2l2ZSk7XG4gICAgfVxuXG4gICAgaGFuZGxlSW1hZ2VHZW5lcmF0aW9uKGltYWdlVHlwZSwgaW1hZ2VPcHRpb25zLCBhY3Rpb25zVG9QZXJmb3JtLCBmaWxlTmFtZSkge1xuICAgICAgICBsZXQgb3B0aW9ucyA9IHt9O1xuICAgICAgICBpZiAoaW1hZ2VPcHRpb25zKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gaW1hZ2VPcHRpb25zO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGRlc2lyZWRPdXRwdXQgPSBvcHRpb25zLm91dHB1dDtcbiAgICAgICAgb3B0aW9ucy5vdXRwdXQgPSAnYmxvYic7XG5cbiAgICAgICAgbGV0IGRvd25sb2FkSW1hZ2U7XG4gICAgICAgIGxldCBzdG9yZUltYWdlO1xuICAgICAgICBzd2l0Y2ggKGFjdGlvbnNUb1BlcmZvcm0pIHtcbiAgICAgICAgICAgIGNhc2UgJ3N0b3JlJzpcbiAgICAgICAgICAgICAgICBkb3dubG9hZEltYWdlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RvcmVJbWFnZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkb3dubG9hZCc6XG4gICAgICAgICAgICAgICAgZG93bmxvYWRJbWFnZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgc3RvcmVJbWFnZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYm90aCc6XG4gICAgICAgICAgICAgICAgZG93bmxvYWRJbWFnZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgc3RvcmVJbWFnZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGRvd25sb2FkSW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBzdG9yZUltYWdlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBvdXRwdXQ7XG4gICAgICAgIGlmIChpbWFnZVR5cGUgPT09ICdwbmcnKSB7XG4gICAgICAgICAgICBvdXRwdXQgPSB0aGlzLl9jeS5wbmcob3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGltYWdlVHlwZSA9PT0gJ2pwZycgfHwgaW1hZ2VUeXBlID09PSAnanBlZycpIHtcbiAgICAgICAgICAgIG91dHB1dCA9IHRoaXMuX2N5LmpwZyhvcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvbmx5IHdvcmtzIHdoZW4gc3ZnIGlzIGltcG9ydGVkIChzZWUgbGliL2V4dHJhX2luZGV4LmpzKVxuICAgICAgICBpZiAoaW1hZ2VUeXBlID09PSAnc3ZnJykge1xuICAgICAgICAgICAgb3V0cHV0ID0gdGhpcy5fY3kuc3ZnKG9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLypcbiAgICAgICAgICogSWYgb3V0cHV0IGlzIGVtcHR5IGJlY2F1c2Ugb2YgYmFkIG9wdGlvbnMgb3IgYSBjeXRvc2NhcGUgZXJyb3IsXG4gICAgICAgICAqIHNraXAgYW55IGRvd25sb2FkIG9yIHN0b3JhZ2Ugc3RlcHMuXG4gICAgICAgICAqL1xuICAgICAgICBpZiAob3V0cHV0ICYmIGRvd25sb2FkSW1hZ2UpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBEb3dubG9hZGluZyBpcyBpbml0aWF0ZWQgY2xpZW50LXNpZGUgYmVjYXVzZSB0aGUgaW1hZ2UgaXMgZ2VuZXJhdGVkIGF0XG4gICAgICAgICAgICAgKiB0aGUgY2xpZW50LiBUaGlzIGF2b2lkcyB0cmFuc2ZlcnJpbmcgYSBwb3RlbnRpYWxseSBsYXJnZSBpbWFnZVxuICAgICAgICAgICAgICogdG8gdGhlIHNlcnZlciBhbmQgYmFjayBhZ2FpbiB0aHJvdWdoIGEgY2FsbGJhY2suXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGxldCBmTmFtZSA9IGZpbGVOYW1lO1xuICAgICAgICAgICAgaWYgKCFmaWxlTmFtZSkge1xuICAgICAgICAgICAgICAgIGZOYW1lID0gJ2N5dG8nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaW1hZ2VUeXBlICE9PSAnc3ZnJykge1xuICAgICAgICAgICAgICAgIHRoaXMuZG93bmxvYWRCbG9iKG91dHB1dCwgZk5hbWUgKyAnLicgKyBpbWFnZVR5cGUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW291dHB1dF0sIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2ltYWdlL3N2Zyt4bWw7Y2hhcnNldD11dGYtOCdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmRvd25sb2FkQmxvYihibG9iLCBmTmFtZSArICcuJyArIGltYWdlVHlwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3V0cHV0ICYmIHN0b3JlSW1hZ2UpIHtcbiAgICAgICAgICAgIC8vIERlZmF1bHQgb3V0cHV0IHR5cGUgaWYgdW5zcGVjaWZpZWRcbiAgICAgICAgICAgIGlmICghZGVzaXJlZE91dHB1dCkge1xuICAgICAgICAgICAgICAgIGRlc2lyZWRPdXRwdXQgPSAnYmFzZTY0dXJpJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICEoZGVzaXJlZE91dHB1dCA9PT0gJ2Jhc2U2NHVyaScgfHwgZGVzaXJlZE91dHB1dCA9PT0gJ2Jhc2U2NCcpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBDb252ZXJ0IGJsb2IgdG8gYmFzZTY0dXJpIG9yIGJhc2U2NCBzdHJpbmcgdG8gc3RvcmUgdGhlIGltYWdlIGRhdGEuXG4gICAgICAgICAgICAgKiBUaGFuayB5b3UsIGJhc2U2NGd1cnUgaHR0cHM6Ly9iYXNlNjQuZ3VydS9kZXZlbG9wZXJzL2phdmFzY3JpcHQvZXhhbXBsZXMvZW5jb2RlLWJsb2JcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcbiAgICAgICAgICAgIHJlYWRlci5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLyogRmlsZVJlYWRlciBpcyBhc3luY2hyb25vdXMsIHNvIHRoZSByZWFkIGZ1bmN0aW9uIGlzIG5vbi1ibG9ja2luZy5cbiAgICAgICAgICAgICAgICAgKiBJZiB0aGlzIGNvZGUgYmxvY2sgaXMgcGxhY2VkIGFmdGVyIHRoZSByZWFkIGNvbW1hbmQsIGl0XG4gICAgICAgICAgICAgICAgICogbWF5IHJlc3VsdCBpbiBlbXB0eSBvdXRwdXQgYmVjYXVzZSB0aGUgYmxvYiBoYXMgbm90IGJlZW4gbG9hZGVkIHlldC5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBsZXQgY2FsbGJhY2tEYXRhID0gcmVhZGVyLnJlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAoZGVzaXJlZE91dHB1dCA9PT0gJ2Jhc2U2NCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tEYXRhID0gY2FsbGJhY2tEYXRhLnJlcGxhY2UoL15kYXRhOi4rO2Jhc2U2NCwvLCAnJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuc2V0UHJvcHMoe2ltYWdlRGF0YTogY2FsbGJhY2tEYXRhfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwob3V0cHV0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRvd25sb2FkQmxvYihibG9iLCBmaWxlTmFtZSkge1xuICAgICAgICAvKlxuICAgICAgICAgKiBEb3dubG9hZCBibG9iIGFzIGZpbGUgYnkgZHluYW1pY2FsbHkgY3JlYXRpbmcgbGluay5cbiAgICAgICAgICogQ2hyb21lIGRvZXMgbm90IG9wZW4gZGF0YSBVUkxzIHdoZW4gSlMgb3BlbnMgYSBuZXcgdGFiIGRpcmVjdGVkXG4gICAgICAgICAqIGF0IHRoZSBkYXRhIFVSTCwgc28gdGhpcyBpcyBhbiBhbHRlcm5hdGUgaW1wbGVtZW50YXRpb25cbiAgICAgICAgICogdGhhdCBkb2Vzbid0IHJlcXVpcmUgZXh0cmEgcGFja2FnZXMuIEl0IG1heSBub3QgYmVoYXZlIGluXG4gICAgICAgICAqIGV4YWN0bHkgdGhlIHNhbWUgd2F5IGFjcm9zcyBicm93c2VycyAobWlnaHQgZGlzcGxheSBpbWFnZSBpbiBuZXcgdGFiXG4gICAgICAgICAqIGludGVhZCBvZiBkb3dubG9hZGluZyBhcyBhIGZpbGUpLlxuICAgICAgICAgKiBUaGFuayB5b3UsIGtvbGRldiBodHRwczovL2pzZmlkZGxlLm5ldC9rb2xkZXYvY1c3VzUvXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdCBkb3dubG9hZExpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgIGRvd25sb2FkTGluay5zdHlsZSA9ICdkaXNwbGF5OiBub25lJztcbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkb3dubG9hZExpbmspO1xuXG4gICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuICAgICAgICBkb3dubG9hZExpbmsuaHJlZiA9IHVybDtcbiAgICAgICAgZG93bmxvYWRMaW5rLmRvd25sb2FkID0gZmlsZU5hbWU7XG4gICAgICAgIGRvd25sb2FkTGluay5jbGljaygpO1xuICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZG93bmxvYWRMaW5rKTtcbiAgICB9XG5cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIC8vIEhUTUwgYXR0cmlidXRlIHByb3BzXG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIHN0eWxlLFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgLy8gQ29tbW9uIHByb3BzXG4gICAgICAgICAgICBlbGVtZW50cyxcbiAgICAgICAgICAgIHN0eWxlc2hlZXQsXG4gICAgICAgICAgICBsYXlvdXQsXG4gICAgICAgICAgICAvLyBWaWV3cG9ydCBNYW5pcHVsYXRpb25cbiAgICAgICAgICAgIHBhbixcbiAgICAgICAgICAgIHpvb20sXG4gICAgICAgICAgICAvLyBWaWV3cG9ydCBNdXRhYmlsaXR5IGFuZCBnZXN0dXJlIFRvZ2dsaW5nXG4gICAgICAgICAgICBwYW5uaW5nRW5hYmxlZCxcbiAgICAgICAgICAgIHVzZXJQYW5uaW5nRW5hYmxlZCxcbiAgICAgICAgICAgIG1pblpvb20sXG4gICAgICAgICAgICBtYXhab29tLFxuICAgICAgICAgICAgem9vbWluZ0VuYWJsZWQsXG4gICAgICAgICAgICB1c2VyWm9vbWluZ0VuYWJsZWQsXG4gICAgICAgICAgICBib3hTZWxlY3Rpb25FbmFibGVkLFxuICAgICAgICAgICAgYXV0b3VuZ3JhYmlmeSxcbiAgICAgICAgICAgIGF1dG9sb2NrLFxuICAgICAgICAgICAgYXV0b3Vuc2VsZWN0aWZ5LFxuICAgICAgICAgICAgLy8gSW1hZ2UgaGFuZGxpbmdcbiAgICAgICAgICAgIGdlbmVyYXRlSW1hZ2UsXG4gICAgICAgICAgICAvLyBSZXNwb25zaXZlIGdyYXBoc1xuICAgICAgICAgICAgcmVzcG9uc2l2ZVxuICAgICAgICB9ID0gdGhpcy5wcm9wcztcblxuICAgICAgICBpZiAoT2JqZWN0LmtleXMoZ2VuZXJhdGVJbWFnZSkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgLy8gSWYgbm8gY3l0b3NjYXBlIG9iamVjdCBoYXMgYmVlbiBjcmVhdGVkIHlldCwgYW4gaW1hZ2UgY2Fubm90IGJlIGdlbmVyYXRlZCxcbiAgICAgICAgICAgIC8vIHNvIGdlbmVyYXRlSW1hZ2Ugd2lsbCBiZSBpZ25vcmVkIGFuZCBjbGVhcmVkLlxuICAgICAgICAgICAgdGhpcy5wcm9wcy5zZXRQcm9wcyh7Z2VuZXJhdGVJbWFnZToge319KTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9jeSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlSW1hZ2VHZW5lcmF0aW9uKFxuICAgICAgICAgICAgICAgICAgICBnZW5lcmF0ZUltYWdlLnR5cGUsXG4gICAgICAgICAgICAgICAgICAgIGdlbmVyYXRlSW1hZ2Uub3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgZ2VuZXJhdGVJbWFnZS5hY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgIGdlbmVyYXRlSW1hZ2UuZmlsZW5hbWVcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuY3lSZXNwb25zaXZlQ2xhc3MpIHtcbiAgICAgICAgICAgIHRoaXMuY3lSZXNwb25zaXZlQ2xhc3MudG9nZ2xlKHJlc3BvbnNpdmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxDeXRvc2NhcGVDb21wb25lbnRcbiAgICAgICAgICAgICAgICBpZD17aWR9XG4gICAgICAgICAgICAgICAgY3k9e3RoaXMuaGFuZGxlQ3l9XG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lPXtjbGFzc05hbWV9XG4gICAgICAgICAgICAgICAgc3R5bGU9e3N0eWxlfVxuICAgICAgICAgICAgICAgIGVsZW1lbnRzPXtDeXRvc2NhcGVDb21wb25lbnQubm9ybWFsaXplRWxlbWVudHMoZWxlbWVudHMpfVxuICAgICAgICAgICAgICAgIHN0eWxlc2hlZXQ9e3N0eWxlc2hlZXR9XG4gICAgICAgICAgICAgICAgbGF5b3V0PXtsYXlvdXR9XG4gICAgICAgICAgICAgICAgcGFuPXtwYW59XG4gICAgICAgICAgICAgICAgem9vbT17em9vbX1cbiAgICAgICAgICAgICAgICBwYW5uaW5nRW5hYmxlZD17cGFubmluZ0VuYWJsZWR9XG4gICAgICAgICAgICAgICAgdXNlclBhbm5pbmdFbmFibGVkPXt1c2VyUGFubmluZ0VuYWJsZWR9XG4gICAgICAgICAgICAgICAgbWluWm9vbT17bWluWm9vbX1cbiAgICAgICAgICAgICAgICBtYXhab29tPXttYXhab29tfVxuICAgICAgICAgICAgICAgIHpvb21pbmdFbmFibGVkPXt6b29taW5nRW5hYmxlZH1cbiAgICAgICAgICAgICAgICB1c2VyWm9vbWluZ0VuYWJsZWQ9e3VzZXJab29taW5nRW5hYmxlZH1cbiAgICAgICAgICAgICAgICBib3hTZWxlY3Rpb25FbmFibGVkPXtib3hTZWxlY3Rpb25FbmFibGVkfVxuICAgICAgICAgICAgICAgIGF1dG91bmdyYWJpZnk9e2F1dG91bmdyYWJpZnl9XG4gICAgICAgICAgICAgICAgYXV0b2xvY2s9e2F1dG9sb2NrfVxuICAgICAgICAgICAgICAgIGF1dG91bnNlbGVjdGlmeT17YXV0b3Vuc2VsZWN0aWZ5fVxuICAgICAgICAgICAgLz5cbiAgICAgICAgKTtcbiAgICB9XG59XG5cbkN5dG9zY2FwZS5wcm9wVHlwZXMgPSB7XG4gICAgLy8gSFRNTCBhdHRyaWJ1dGUgcHJvcHNcblxuICAgIC8qKlxuICAgICAqIFRoZSBJRCB1c2VkIHRvIGlkZW50aWZ5IHRoaXMgY29tcG9uZW50IGluIERhc2ggY2FsbGJhY2tzLlxuICAgICAqL1xuICAgIGlkOiBQcm9wVHlwZXMuc3RyaW5nLFxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY2xhc3MgbmFtZSBvZiB0aGUgZWxlbWVudCAodGhlIHZhbHVlIG9mIGFuIGVsZW1lbnQncyBodG1sXG4gICAgICogY2xhc3MgYXR0cmlidXRlKS5cbiAgICAgKi9cbiAgICBjbGFzc05hbWU6IFByb3BUeXBlcy5zdHJpbmcsXG5cbiAgICAvKipcbiAgICAgKiBBZGQgaW5saW5lIHN0eWxlcyB0byB0aGUgcm9vdCBlbGVtZW50LlxuICAgICAqL1xuICAgIHN0eWxlOiBQcm9wVHlwZXMub2JqZWN0LFxuXG4gICAgLy8gRGFzaCBzcGVjaWZpYyBwcm9wc1xuXG4gICAgLyoqXG4gICAgICogRGFzaC1hc3NpZ25lZCBjYWxsYmFjayB0aGF0IHNob3VsZCBiZSBjYWxsZWQgd2hlbmV2ZXIgYW55IG9mIHRoZVxuICAgICAqIHByb3BlcnRpZXMgY2hhbmdlLlxuICAgICAqL1xuICAgIHNldFByb3BzOiBQcm9wVHlwZXMuZnVuYyxcblxuICAgIC8vIENvbW1vbiBwcm9wc1xuXG4gICAgLyoqXG4gICAgICogQSBsaXN0IG9mIGRpY3Rpb25hcmllcyByZXByZXNlbnRpbmcgdGhlIGVsZW1lbnRzIG9mIHRoZSBuZXR3b3Jrcy4gRWFjaCBkaWN0aW9uYXJ5IGRlc2NyaWJlcyBhbiBlbGVtZW50LCBhbmRcbiAgICAgKiBzcGVjaWZpZXMgaXRzIHB1cnBvc2UuIFRoZSBbb2ZmaWNpYWwgQ3l0b3NjYXBlLmpzIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vanMuY3l0b3NjYXBlLm9yZy8jbm90YXRpb24vZWxlbWVudHMtanNvbilcbiAgICAgKiBvZmZlcnMgYW4gZXh0ZW5zaXZlIG92ZXJ2aWV3IGFuZCBleGFtcGxlcyBvZiBlbGVtZW50IGRlY2xhcmF0aW9uLlxuICAgICAqIEFsdGVybmF0aXZlbHksIGEgZGljdGlvbmFyeSB3aXRoIHRoZSBmb3JtYXQgeyAnbm9kZXMnOiBbXSwgJ2VkZ2VzJzogW10gfSBpcyBhbGxvd2VkIGF0IGluaXRpYWxpemF0aW9uLFxuICAgICAqIGJ1dCBhcnJheXMgcmVtYWluIHRoZSByZWNvbW1lbmRlZCBmb3JtYXQuXG4gICAgICovXG4gICAgZWxlbWVudHM6IFByb3BUeXBlcy5vbmVPZlR5cGUoW1xuICAgICAgICBQcm9wVHlwZXMuYXJyYXlPZihcbiAgICAgICAgICAgIFByb3BUeXBlcy5zaGFwZSh7XG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogRWl0aGVyICdub2Rlcycgb3IgJ2VkZ2VzJy4gSWYgbm90IGdpdmVuLCBpdCdzIGF1dG9tYXRpY2FsbHkgaW5mZXJyZWQuXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgZ3JvdXA6IFByb3BUeXBlcy5zdHJpbmcsXG4gICAgICAgICAgICAgICAgLyoqIEVsZW1lbnQgc3BlY2lmaWMgZGF0YS4qL1xuICAgICAgICAgICAgICAgIGRhdGE6IFByb3BUeXBlcy5zaGFwZSh7XG4gICAgICAgICAgICAgICAgICAgIC8qKiAgUmVmZXJlbmNlIHRvIHRoZSBlbGVtZW50LCB1c2VmdWwgZm9yIHNlbGVjdG9ycyBhbmQgZWRnZXMuIFJhbmRvbWx5IGFzc2lnbmVkIGlmIG5vdCBnaXZlbi4qL1xuICAgICAgICAgICAgICAgICAgICBpZDogUHJvcFR5cGVzLnN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAqIE9wdGlvbmFsIG5hbWUgZm9yIHRoZSBlbGVtZW50LCB1c2VmdWwgd2hlbiBgZGF0YShsYWJlbClgIGlzIGdpdmVuIHRvIGEgc3R5bGUncyBgY29udGVudGBcbiAgICAgICAgICAgICAgICAgICAgICogb3IgYGxhYmVsYC4gSXQgaXMgb25seSBhIGNvbnZlbnRpb24uICovXG4gICAgICAgICAgICAgICAgICAgIGxhYmVsOiBQcm9wVHlwZXMuc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAvKiogT25seSBmb3Igbm9kZXMuIE9wdGlvbmFsIHJlZmVyZW5jZSB0byBhbm90aGVyIG5vZGUuIE5lZWRlZCB0byBjcmVhdGUgY29tcG91bmQgbm9kZXMuICovXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudDogUHJvcFR5cGVzLnN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgLyoqIE9ubHkgZm9yIGVkZ2VzLiBUaGUgaWQgb2YgdGhlIHNvdXJjZSBub2RlLCB3aGljaCBpcyB3aGVyZSB0aGUgZWRnZSBzdGFydHMuICovXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogUHJvcFR5cGVzLnN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgLyoqIE9ubHkgZm9yIGVkZ2VzLiBUaGUgaWQgb2YgdGhlIHRhcmdldCBub2RlLCB3aGVyZSB0aGUgZWRnZSBlbmRzLiAqL1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IFByb3BUeXBlcy5zdHJpbmdcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAvKiogT25seSBmb3Igbm9kZXMuIFRoZSBwb3NpdGlvbiBvZiB0aGUgbm9kZS4gKi9cbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogUHJvcFR5cGVzLnNoYXBlKHtcbiAgICAgICAgICAgICAgICAgICAgLyoqIFRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIG5vZGUuICovXG4gICAgICAgICAgICAgICAgICAgIHg6IFByb3BUeXBlcy5udW1iZXIsXG4gICAgICAgICAgICAgICAgICAgIC8qKiBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSBub2RlLiAqL1xuICAgICAgICAgICAgICAgICAgICB5OiBQcm9wVHlwZXMubnVtYmVyXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgLyoqIElmIHRoZSBlbGVtZW50IGlzIHNlbGVjdGVkIHVwb24gaW5pdGlhbGlzYXRpb24uICovXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWQ6IFByb3BUeXBlcy5ib29sLFxuICAgICAgICAgICAgICAgIC8qKiBJZiB0aGUgZWxlbWVudCBjYW4gYmUgc2VsZWN0ZWQuICovXG4gICAgICAgICAgICAgICAgc2VsZWN0YWJsZTogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgICAgICAgICAgLyoqIE9ubHkgZm9yIG5vZGVzLiBJZiB0aGUgcG9zaXRpb24gaXMgaW1tdXRhYmxlLiAqL1xuICAgICAgICAgICAgICAgIGxvY2tlZDogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgICAgICAgICAgLyoqIE9ubHkgZm9yIG5vZGVzLiBJZiB0aGUgbm9kZSBjYW4gYmUgZ3JhYmJlZCBhbmQgbW92ZWQgYnkgdGhlIHVzZXIuICovXG4gICAgICAgICAgICAgICAgZ3JhYmJhYmxlOiBQcm9wVHlwZXMuYm9vbCxcbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiBTcGFjZSBzZXBhcmF0ZWQgc3RyaW5nIG9mIGNsYXNzIG5hbWVzIG9mIHRoZSBlbGVtZW50LiBUaG9zZSBjbGFzc2VzIGNhbiBiZSBzZWxlY3RlZFxuICAgICAgICAgICAgICAgICAqIGJ5IGEgc3R5bGUgc2VsZWN0b3IuXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgY2xhc3NlczogUHJvcFR5cGVzLnN0cmluZ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKSxcbiAgICAgICAgUHJvcFR5cGVzLmV4YWN0KHtcbiAgICAgICAgICAgIG5vZGVzOiBQcm9wVHlwZXMuYXJyYXksXG4gICAgICAgICAgICBlZGdlczogUHJvcFR5cGVzLmFycmF5XG4gICAgICAgIH0pXG4gICAgXSksXG5cbiAgICAvKipcbiAgICAgKiBBIGxpc3Qgb2YgZGljdGlvbmFyaWVzIHJlcHJlc2VudGluZyB0aGUgc3R5bGVzIG9mIHRoZSBlbGVtZW50cy5cbiAgICAgKiBFYWNoIGRpY3Rpb25hcnkgcmVxdWlyZXMgdGhlIGZvbGxvd2luZyBrZXlzOiBgc2VsZWN0b3JgIGFuZCBgc3R5bGVgLlxuICAgICAqXG4gICAgICogQm90aCB0aGUgW3NlbGVjdG9yXShodHRwczovL2pzLmN5dG9zY2FwZS5vcmcvI3NlbGVjdG9ycykgYW5kXG4gICAgICogdGhlIFtzdHlsZV0oaHR0cHM6Ly9qcy5jeXRvc2NhcGUub3JnLyNzdHlsZS9ub2RlLWJvZHkpIGFyZVxuICAgICAqIGV4aGF1c3RpdmVseSBkb2N1bWVudGVkIGluIHRoZSBDeXRvc2NhcGUuanMgZG9jcy4gQWx0aG91Z2ggbWV0aG9kcyBzdWNoXG4gICAgICogYXMgYGN5LmVsZW1lbnRzKC4uLilgIGFuZCBgY3kuZmlsdGVyKC4uLilgIGFyZSBub3QgYXZhaWxhYmxlLCB0aGUgc2VsZWN0b3JcbiAgICAgKiBzdHJpbmcgc3ludGF4IHN0YXlzIHRoZSBzYW1lLlxuICAgICAqL1xuICAgIHN0eWxlc2hlZXQ6IFByb3BUeXBlcy5hcnJheU9mKFxuICAgICAgICBQcm9wVHlwZXMuZXhhY3Qoe1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBXaGljaCBlbGVtZW50cyB5b3UgYXJlIHN0eWxpbmcuIEdlbmVyYWxseSwgeW91IHNlbGVjdCBhIGdyb3VwIG9mIGVsZW1lbnRzIChub2RlLCBlZGdlcywgYm90aCksXG4gICAgICAgICAgICAgKiBhIGNsYXNzICh0aGF0IHlvdSBkZWNsYXJlIGluIHRoZSBlbGVtZW50IGRpY3Rpb25hcnkpLCBvciBhbiBlbGVtZW50IGJ5IElELlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZWxlY3RvcjogUHJvcFR5cGVzLnN0cmluZy5pc1JlcXVpcmVkLFxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBXaGF0IGFzcGVjdHMgb2YgdGhlIGVsZW1lbnRzIHlvdSB3YW50IHRvIG1vZGlmeS4gVGhpcyBjb3VsZCBiZSB0aGUgc2l6ZSBvclxuICAgICAgICAgICAgICogY29sb3Igb2YgYSBub2RlLCB0aGUgc2hhcGUgb2YgYW4gZWRnZSBhcnJvdywgb3IgbWFueSBtb3JlLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzdHlsZTogUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkXG4gICAgICAgIH0pXG4gICAgKSxcblxuICAgIC8qKlxuICAgICAqIEEgZGljdGlvbmFyeSBzcGVjaWZ5aW5nIGhvdyB0byBzZXQgdGhlIHBvc2l0aW9uIG9mIHRoZSBlbGVtZW50cyBpbiB5b3VyXG4gICAgICogZ3JhcGguIFRoZSBgJ25hbWUnYCBrZXkgaXMgcmVxdWlyZWQsIGFuZCBpbmRpY2F0ZXMgd2hpY2ggbGF5b3V0IChhbGdvcml0aG0pIHRvXG4gICAgICogdXNlLiBUaGUga2V5cyBhY2NlcHRlZCBieSBgbGF5b3V0YCB2YXJ5IGRlcGVuZGluZyBvbiB0aGUgYWxnb3JpdGhtLCBidXQgdGhlc2VcbiAgICAgKiBrZXlzIGFyZSBhY2NlcHRlZCBieSBhbGwgbGF5b3V0czogYGZpdGAsICBgcGFkZGluZ2AsIGBhbmltYXRlYCwgYGFuaW1hdGlvbkR1cmF0aW9uYCxcbiAgICAgKiBgYm91bmRpbmdCb3hgLlxuICAgICAqXG4gICAgICogIFRoZSBjb21wbGV0ZSBsaXN0IG9mIGxheW91dHMgYW5kIHRoZWlyIGFjY2VwdGVkIG9wdGlvbnMgYXJlIGF2YWlsYWJsZSBvbiB0aGVcbiAgICAgKiAgW0N5dG9zY2FwZS5qcyBkb2NzXShodHRwczovL2pzLmN5dG9zY2FwZS5vcmcvI2xheW91dHMpIC4gRm9yIHRoZSBleHRlcm5hbCBsYXlvdXRzLFxuICAgICAqIHRoZSBvcHRpb25zIGFyZSBsaXN0ZWQgaW4gdGhlIFwiQVBJXCIgc2VjdGlvbiBvZiB0aGUgIFJFQURNRS5cbiAgICAgKiAgTm90ZSB0aGF0IGNlcnRhaW4ga2V5cyBhcmUgbm90IHN1cHBvcnRlZCBpbiBEYXNoIHNpbmNlIHRoZSB2YWx1ZSBpcyBhIEphdmFTY3JpcHRcbiAgICAgKiAgZnVuY3Rpb24gb3IgYSBjYWxsYmFjay4gUGxlYXNlIHZpc2l0IHRoaXNcbiAgICAgKiBbaXNzdWVdKGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvZGFzaC1jeXRvc2NhcGUvaXNzdWVzLzI1KSBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cbiAgICAgKi9cbiAgICBsYXlvdXQ6IFByb3BUeXBlcy5zaGFwZSh7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgbGF5b3V0cyBhdmFpbGFibGUgYnkgZGVmYXVsdCBhcmU6XG4gICAgICAgICAqICAgYHJhbmRvbWA6IFJhbmRvbWx5IGFzc2lnbnMgcG9zaXRpb25zLlxuICAgICAgICAgKiAgIGBwcmVzZXRgOiBBc3NpZ25zIHBvc2l0aW9uIGJhc2VkIG9uIHRoZSBgcG9zaXRpb25gIGtleSBpbiBlbGVtZW50IGRpY3Rpb25hcmllcy5cbiAgICAgICAgICogICBgY2lyY2xlYDogU2luZ2xlLWxldmVsIGNpcmNsZSwgd2l0aCBvcHRpb25hbCByYWRpdXMuXG4gICAgICAgICAqICAgYGNvbmNlbnRyaWNgOiBNdWx0aS1sZXZlbCBjaXJjbGUsIHdpdGggb3B0aW9uYWwgcmFkaXVzLlxuICAgICAgICAgKiAgIGBncmlkYDogU3F1YXJlIGdyaWQsIG9wdGlvbmFsbHkgd2l0aCBudW1iZXJzIG9mIGByb3dzYCBhbmQgYGNvbHNgLlxuICAgICAgICAgKiAgIGBicmVhZHRoZmlyc3RgOiBUcmVlIHN0cnVjdHVyZSBidWlsdCB1c2luZyBCRlMsIHdpdGggb3B0aW9uYWwgYHJvb3RzYC5cbiAgICAgICAgICogICBgY29zZWA6IEZvcmNlLWRpcmVjdGVkIHBoeXNpY3Mgc2ltdWxhdGlvbi5cbiAgICAgICAgICpcbiAgICAgICAgICogU29tZSBleHRlcm5hbCBsYXlvdXRzIGFyZSBhbHNvIGluY2x1ZGVkLiBUbyB1c2UgdGhlbSwgcnVuXG4gICAgICAgICAqICAgYGRhc2hfY3l0b3NjYXBlLmxvYWRfZXh0cmFfbGF5b3V0cygpYCBiZWZvcmUgY3JlYXRpbmcgeW91ciBEYXNoIGFwcC4gQmUgY2FyZWZ1bCBhYm91dFxuICAgICAgICAgKiAgIHVzaW5nIHRoZSBleHRyYSBsYXlvdXRzIHdoZW4gbm90IG5lY2Vzc2FyeSwgc2luY2UgdGhleSByZXF1aXJlIHN1cHBsZW1lbnRhcnkgYmFuZHdpZHRoXG4gICAgICAgICAqICAgZm9yIGxvYWRpbmcsIHdoaWNoIGltcGFjdHMgdGhlIHN0YXJ0dXAgdGltZSBvZiB0aGUgYXBwLlxuICAgICAgICAgKiAgIFRoZSBleHRlcm5hbCBsYXlvdXRzIGFyZTpcbiAgICAgICAgICogICBbY29zZS1iaWxrZW50XShodHRwczovL2dpdGh1Yi5jb20vY3l0b3NjYXBlL2N5dG9zY2FwZS5qcy1jb3NlLWJpbGtlbnQpLFxuICAgICAgICAgKiAgIFtjb2xhXShodHRwczovL2dpdGh1Yi5jb20vY3l0b3NjYXBlL2N5dG9zY2FwZS5qcy1jb2xhKSxcbiAgICAgICAgICogICBbZXVsZXJdKGh0dHBzOi8vZ2l0aHViLmNvbS9jeXRvc2NhcGUvY3l0b3NjYXBlLmpzLWRhZ3JlKSxcbiAgICAgICAgICogICBbc3ByZWFkXShodHRwczovL2dpdGh1Yi5jb20vY3l0b3NjYXBlL2N5dG9zY2FwZS5qcy1zcHJlYWQpLFxuICAgICAgICAgKiAgIFtkYWdyZV0oaHR0cHM6Ly9naXRodWIuY29tL2N5dG9zY2FwZS9jeXRvc2NhcGUuanMtZGFncmUpLFxuICAgICAgICAgKiAgIFtrbGF5XShodHRwczovL2dpdGh1Yi5jb20vY3l0b3NjYXBlL2N5dG9zY2FwZS5qcy1rbGF5KSxcbiAgICAgICAgICovXG4gICAgICAgIG5hbWU6IFByb3BUeXBlcy5vbmVPZihbXG4gICAgICAgICAgICAncmFuZG9tJyxcbiAgICAgICAgICAgICdwcmVzZXQnLFxuICAgICAgICAgICAgJ2NpcmNsZScsXG4gICAgICAgICAgICAnY29uY2VudHJpYycsXG4gICAgICAgICAgICAnZ3JpZCcsXG4gICAgICAgICAgICAnYnJlYWR0aGZpcnN0JyxcbiAgICAgICAgICAgICdjb3NlJyxcbiAgICAgICAgICAgICdjbG9zZS1iaWxrZW50JyxcbiAgICAgICAgICAgICdjb2xhJyxcbiAgICAgICAgICAgICdldWxlcicsXG4gICAgICAgICAgICAnc3ByZWFkJyxcbiAgICAgICAgICAgICdkYWdyZScsXG4gICAgICAgICAgICAna2xheSdcbiAgICAgICAgXSkuaXNSZXF1aXJlZCxcbiAgICAgICAgLyoqICBXaGV0aGVyIHRvIHJlbmRlciB0aGUgbm9kZXMgaW4gb3JkZXIgdG8gZml0IHRoZSBjYW52YXMuICovXG4gICAgICAgIGZpdDogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgIC8qKiBQYWRkaW5nIGFyb3VuZCB0aGUgc2lkZXMgb2YgdGhlIGNhbnZhcywgaWYgZml0IGlzIGVuYWJsZWQuICovXG4gICAgICAgIHBhZGRpbmc6IFByb3BUeXBlcy5udW1iZXIsXG4gICAgICAgIC8qKiBXaGV0aGVyIHRvIGFuaW1hdGUgY2hhbmdlIGluIHBvc2l0aW9uIHdoZW4gdGhlIGxheW91dCBjaGFuZ2VzLiAqL1xuICAgICAgICBhbmltYXRlOiBQcm9wVHlwZXMuYm9vbCxcbiAgICAgICAgLyoqIER1cmF0aW9uIG9mIGFuaW1hdGlvbiBpbiBtaWxsaXNlY29uZHMsIGlmIGVuYWJsZWQuICovXG4gICAgICAgIGFuaW1hdGlvbkR1cmF0aW9uOiBQcm9wVHlwZXMubnVtYmVyLFxuICAgICAgICAvKipcbiAgICAgICAgICogSG93IHRvIGNvbnN0cmFpbiB0aGUgbGF5b3V0IGluIGEgc3BlY2lmaWMgYXJlYS4gS2V5cyBhY2NlcHRlZCBhcmUgZWl0aGVyXG4gICAgICAgICAqIGB4MSwgeTEsIHgyLCB5MmAgb3IgYHgxLCB5MSwgdywgaGAsIGFsbCBvZiB3aGljaCByZWNlaXZlIGEgcGl4ZWwgdmFsdWUuXG4gICAgICAgICAqL1xuICAgICAgICBib3VuZGluZ0JveDogUHJvcFR5cGVzLm9iamVjdFxuICAgIH0pLFxuXG4gICAgLy8gVmlld3BvcnQgTWFuaXB1bGF0aW9uXG5cbiAgICAvKipcbiAgICAgKiBEaWN0aW9uYXJ5IGluZGljYXRpbmcgdGhlIGluaXRpYWwgcGFubmluZyBwb3NpdGlvbiBvZiB0aGUgZ3JhcGguIFRoZVxuICAgICAqIGZvbGxvd2luZyBrZXlzIGFyZSBhY2NlcHRlZDpcbiAgICAgKi9cbiAgICBwYW46IFByb3BUeXBlcy5leGFjdCh7XG4gICAgICAgIC8qKiBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSBub2RlICovXG4gICAgICAgIHg6IFByb3BUeXBlcy5udW1iZXIsXG4gICAgICAgIC8qKiBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSBub2RlICAqL1xuICAgICAgICB5OiBQcm9wVHlwZXMubnVtYmVyXG4gICAgfSksXG5cbiAgICAvKipcbiAgICAgKiBUaGUgaW5pdGlhbCB6b29tIGxldmVsIG9mIHRoZSBncmFwaC4gWW91IGNhbiBzZXQgYG1pblpvb21gIGFuZFxuICAgICAqIGBtYXhab29tYCB0byBzZXQgcmVzdHJpY3Rpb25zIG9uIHRoZSB6b29tIGxldmVsLlxuICAgICAqL1xuICAgIHpvb206IFByb3BUeXBlcy5udW1iZXIsXG5cbiAgICAvLyBWaWV3cG9ydCBNdXRhYmlsaXR5IGFuZCBnZXN0dXJlIFRvZ2dsaW5nXG4gICAgLyoqXG4gICAgICogV2hldGhlciBwYW5uaW5nIHRoZSBncmFwaCBpcyBlbmFibGVkIChpLmUuLCB0aGUgcG9zaXRpb24gb2YgdGhlIGdyYXBoIGlzXG4gICAgICogbXV0YWJsZSBvdmVyYWxsKS5cbiAgICAgKi9cbiAgICBwYW5uaW5nRW5hYmxlZDogUHJvcFR5cGVzLmJvb2wsXG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHVzZXIgZXZlbnRzIChlLmcuIGRyYWdnaW5nIHRoZSBncmFwaCBiYWNrZ3JvdW5kKSBhcmUgYWxsb3dlZCB0b1xuICAgICAqIHBhbiB0aGUgZ3JhcGguXG4gICAgICovXG4gICAgdXNlclBhbm5pbmdFbmFibGVkOiBQcm9wVHlwZXMuYm9vbCxcblxuICAgIC8qKlxuICAgICAqIEEgbWluaW11bSBib3VuZCBvbiB0aGUgem9vbSBsZXZlbCBvZiB0aGUgZ3JhcGguIFRoZSB2aWV3cG9ydCBjYW4gbm90IGJlXG4gICAgICogc2NhbGVkIHNtYWxsZXIgdGhhbiB0aGlzIHpvb20gbGV2ZWwuXG4gICAgICovXG4gICAgbWluWm9vbTogUHJvcFR5cGVzLm51bWJlcixcblxuICAgIC8qKlxuICAgICAqIEEgbWF4aW11bSBib3VuZCBvbiB0aGUgem9vbSBsZXZlbCBvZiB0aGUgZ3JhcGguIFRoZSB2aWV3cG9ydCBjYW4gbm90IGJlXG4gICAgICogc2NhbGVkIGxhcmdlciB0aGFuIHRoaXMgem9vbSBsZXZlbC5cbiAgICAgKi9cbiAgICBtYXhab29tOiBQcm9wVHlwZXMubnVtYmVyLFxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB6b29taW5nIHRoZSBncmFwaCBpcyBlbmFibGVkIChpLmUuLCB0aGUgem9vbSBsZXZlbCBvZiB0aGUgZ3JhcGhcbiAgICAgKiBpcyBtdXRhYmxlIG92ZXJhbGwpLlxuICAgICAqL1xuICAgIHpvb21pbmdFbmFibGVkOiBQcm9wVHlwZXMuYm9vbCxcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdXNlciBldmVudHMgKGUuZy4gZHJhZ2dpbmcgdGhlIGdyYXBoIGJhY2tncm91bmQpIGFyZSBhbGxvd2VkXG4gICAgICogdG8gcGFuIHRoZSBncmFwaC5cbiAgICAgKi9cbiAgICB1c2VyWm9vbWluZ0VuYWJsZWQ6IFByb3BUeXBlcy5ib29sLFxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciBib3ggc2VsZWN0aW9uIChpLmUuIGRyYWcgYSBib3ggb3ZlcmxheSBhcm91bmQsIGFuZCByZWxlYXNlIGl0XG4gICAgICogdG8gc2VsZWN0KSBpcyBlbmFibGVkLiBJZiBlbmFibGVkLCB0aGUgdXNlciBtdXN0IHRhcGhvbGQgdG8gcGFuIHRoZSBncmFwaC5cbiAgICAgKi9cbiAgICBib3hTZWxlY3Rpb25FbmFibGVkOiBQcm9wVHlwZXMuYm9vbCxcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgbm9kZXMgc2hvdWxkIGJlIHVuZ3JhYmlmaWVkIChub3QgZ3JhYmJhYmxlIGJ5IHVzZXIpIGJ5XG4gICAgICogZGVmYXVsdCAoaWYgdHJ1ZSwgb3ZlcnJpZGVzIGluZGl2aWR1YWwgbm9kZSBzdGF0ZSkuXG4gICAgICovXG4gICAgYXV0b3VuZ3JhYmlmeTogUHJvcFR5cGVzLmJvb2wsXG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIG5vZGVzIHNob3VsZCBiZSBsb2NrZWQgKG5vdCBkcmFnZ2FibGUgYXQgYWxsKSBieSBkZWZhdWx0XG4gICAgICogKGlmIHRydWUsIG92ZXJyaWRlcyBpbmRpdmlkdWFsIG5vZGUgc3RhdGUpLlxuICAgICAqL1xuICAgIGF1dG9sb2NrOiBQcm9wVHlwZXMuYm9vbCxcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgbm9kZXMgc2hvdWxkIGJlIHVuc2VsZWN0aWZpZWQgKGltbXV0YWJsZSBzZWxlY3Rpb24gc3RhdGUpIGJ5XG4gICAgICogZGVmYXVsdCAoaWYgdHJ1ZSwgb3ZlcnJpZGVzIGluZGl2aWR1YWwgZWxlbWVudCBzdGF0ZSkuXG4gICAgICovXG4gICAgYXV0b3Vuc2VsZWN0aWZ5OiBQcm9wVHlwZXMuYm9vbCxcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGxheW91dCBzaG91bGQgYmUgcmVmcmVzaGVkIHdoZW4gZWxlbWVudHMgYXJlIGFkZGVkIG9yIHJlbW92ZWQuXG4gICAgICovXG4gICAgYXV0b1JlZnJlc2hMYXlvdXQ6IFByb3BUeXBlcy5ib29sLFxuXG4gICAgLy8gVXNlciBFdmVudHMgUHJvcHNcblxuICAgIC8qKlxuICAgICAqIFRoZSBjb21wbGV0ZSBub2RlIGRpY3Rpb25hcnkgcmV0dXJuZWQgd2hlbiB5b3UgdGFwIG9yIGNsaWNrIGl0LiBSZWFkLW9ubHkuXG4gICAgICovXG4gICAgdGFwTm9kZTogUHJvcFR5cGVzLmV4YWN0KHtcbiAgICAgICAgLyoqIG5vZGUgc3BlY2lmaWMgaXRlbSAqL1xuICAgICAgICBlZGdlc0RhdGE6IFByb3BUeXBlcy5hcnJheSxcbiAgICAgICAgLyoqIG5vZGUgc3BlY2lmaWMgaXRlbSAqL1xuICAgICAgICByZW5kZXJlZFBvc2l0aW9uOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgICAvKiogbm9kZSBzcGVjaWZpYyBpdGVtICovXG4gICAgICAgIHRpbWVTdGFtcDogUHJvcFR5cGVzLm51bWJlcixcbiAgICAgICAgLyoqIEdlbmVyYWwgaXRlbSAoZm9yIGFsbCBlbGVtZW50cykgKi9cbiAgICAgICAgY2xhc3NlczogUHJvcFR5cGVzLnN0cmluZyxcbiAgICAgICAgLyoqIEdlbmVyYWwgaXRlbSAoZm9yIGFsbCBlbGVtZW50cykgKi9cbiAgICAgICAgZGF0YTogUHJvcFR5cGVzLm9iamVjdCxcbiAgICAgICAgLyoqIEdlbmVyYWwgaXRlbSAoZm9yIGFsbCBlbGVtZW50cykgKi9cbiAgICAgICAgZ3JhYmJhYmxlOiBQcm9wVHlwZXMuYm9vbCxcbiAgICAgICAgLyoqIEdlbmVyYWwgaXRlbSAoZm9yIGFsbCBlbGVtZW50cykgKi9cbiAgICAgICAgZ3JvdXA6IFByb3BUeXBlcy5zdHJpbmcsXG4gICAgICAgIC8qKiBHZW5lcmFsIGl0ZW0gKGZvciBhbGwgZWxlbWVudHMpICovXG4gICAgICAgIGxvY2tlZDogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgIC8qKiBHZW5lcmFsIGl0ZW0gKGZvciBhbGwgZWxlbWVudHMpICovXG4gICAgICAgIHBvc2l0aW9uOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgICAvKiogR2VuZXJhbCBpdGVtIChmb3IgYWxsIGVsZW1lbnRzKSAqL1xuICAgICAgICBzZWxlY3RhYmxlOiBQcm9wVHlwZXMuYm9vbCxcbiAgICAgICAgLyoqIEdlbmVyYWwgaXRlbSAoZm9yIGFsbCBlbGVtZW50cykgKi9cbiAgICAgICAgc2VsZWN0ZWQ6IFByb3BUeXBlcy5ib29sLFxuICAgICAgICAvKiogR2VuZXJhbCBpdGVtIChmb3IgYWxsIGVsZW1lbnRzKSAqL1xuICAgICAgICBzdHlsZTogUHJvcFR5cGVzLm9iamVjdCxcbiAgICAgICAgLyoqIEl0ZW0gZm9yIGNvbXBvdW5kIG5vZGVzICovXG4gICAgICAgIGFuY2VzdG9yc0RhdGE6IFByb3BUeXBlcy5vbmVPZlR5cGUoW1Byb3BUeXBlcy5vYmplY3QsIFByb3BUeXBlcy5hcnJheV0pLFxuICAgICAgICAvKiogSXRlbSBmb3IgY29tcG91bmQgbm9kZXMgKi9cbiAgICAgICAgY2hpbGRyZW5EYXRhOiBQcm9wVHlwZXMub25lT2ZUeXBlKFtQcm9wVHlwZXMub2JqZWN0LCBQcm9wVHlwZXMuYXJyYXldKSxcbiAgICAgICAgLyoqIEl0ZW0gZm9yIGNvbXBvdW5kIG5vZGVzICovXG4gICAgICAgIGRlc2NlbmRhbnRzRGF0YTogUHJvcFR5cGVzLm9uZU9mVHlwZShbUHJvcFR5cGVzLm9iamVjdCwgUHJvcFR5cGVzLmFycmF5XSksXG4gICAgICAgIC8qKiBJdGVtIGZvciBjb21wb3VuZCBub2RlcyAqL1xuICAgICAgICBwYXJlbnREYXRhOiBQcm9wVHlwZXMub25lT2ZUeXBlKFtQcm9wVHlwZXMub2JqZWN0LCBQcm9wVHlwZXMuYXJyYXldKSxcbiAgICAgICAgLyoqIEl0ZW0gZm9yIGNvbXBvdW5kIG5vZGVzICovXG4gICAgICAgIHNpYmxpbmdzRGF0YTogUHJvcFR5cGVzLm9uZU9mVHlwZShbUHJvcFR5cGVzLm9iamVjdCwgUHJvcFR5cGVzLmFycmF5XSksXG4gICAgICAgIC8qKiBJdGVtIGZvciBjb21wb3VuZCBub2RlcyAqL1xuICAgICAgICBpc1BhcmVudDogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgIC8qKiBJdGVtIGZvciBjb21wb3VuZCBub2RlcyAqL1xuICAgICAgICBpc0NoaWxkbGVzczogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgIC8qKiBJdGVtIGZvciBjb21wb3VuZCBub2RlcyAqL1xuICAgICAgICBpc0NoaWxkOiBQcm9wVHlwZXMuYm9vbCxcbiAgICAgICAgLyoqIEl0ZW0gZm9yIGNvbXBvdW5kIG5vZGVzICovXG4gICAgICAgIGlzT3JwaGFuOiBQcm9wVHlwZXMuYm9vbCxcbiAgICAgICAgLyoqIEl0ZW0gZm9yIGNvbXBvdW5kIG5vZGVzICovXG4gICAgICAgIHJlbGF0aXZlUG9zaXRpb246IFByb3BUeXBlcy5vYmplY3RcbiAgICB9KSxcblxuICAgIC8qKlxuICAgICAqIFRoZSBkYXRhIGRpY3Rpb25hcnkgb2YgYSBub2RlIHJldHVybmVkIHdoZW4geW91IHRhcCBvciBjbGljayBpdC4gUmVhZC1vbmx5LlxuICAgICAqL1xuICAgIHRhcE5vZGVEYXRhOiBQcm9wVHlwZXMub2JqZWN0LFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNvbXBsZXRlIGVkZ2UgZGljdGlvbmFyeSByZXR1cm5lZCB3aGVuIHlvdSB0YXAgb3IgY2xpY2sgaXQuIFJlYWQtb25seS5cbiAgICAgKi9cbiAgICB0YXBFZGdlOiBQcm9wVHlwZXMuZXhhY3Qoe1xuICAgICAgICAvKiogRWRnZS1zcGVjaWZpYyBpdGVtICovXG4gICAgICAgIGlzTG9vcDogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgIC8qKiBFZGdlLXNwZWNpZmljIGl0ZW0gKi9cbiAgICAgICAgaXNTaW1wbGU6IFByb3BUeXBlcy5ib29sLFxuICAgICAgICAvKiogRWRnZS1zcGVjaWZpYyBpdGVtICovXG4gICAgICAgIG1pZHBvaW50OiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgICAvKiogRWRnZS1zcGVjaWZpYyBpdGVtICovXG4gICAgICAgIHNvdXJjZURhdGE6IFByb3BUeXBlcy5vYmplY3QsXG4gICAgICAgIC8qKiBFZGdlLXNwZWNpZmljIGl0ZW0gKi9cbiAgICAgICAgc291cmNlRW5kcG9pbnQ6IFByb3BUeXBlcy5vYmplY3QsXG4gICAgICAgIC8qKiBFZGdlLXNwZWNpZmljIGl0ZW0gKi9cbiAgICAgICAgdGFyZ2V0RGF0YTogUHJvcFR5cGVzLm9iamVjdCxcbiAgICAgICAgLyoqIEVkZ2Utc3BlY2lmaWMgaXRlbSAqL1xuICAgICAgICB0YXJnZXRFbmRwb2ludDogUHJvcFR5cGVzLm9iamVjdCxcbiAgICAgICAgLyoqIEVkZ2Utc3BlY2lmaWMgaXRlbSAqL1xuICAgICAgICB0aW1lU3RhbXA6IFByb3BUeXBlcy5udW1iZXIsXG4gICAgICAgIC8qKiBHZW5lcmFsIGl0ZW0gKGZvciBhbGwgZWxlbWVudHMpICovXG4gICAgICAgIGNsYXNzZXM6IFByb3BUeXBlcy5zdHJpbmcsXG4gICAgICAgIC8qKiBHZW5lcmFsIGl0ZW0gKGZvciBhbGwgZWxlbWVudHMpICovXG4gICAgICAgIGRhdGE6IFByb3BUeXBlcy5vYmplY3QsXG4gICAgICAgIC8qKiBHZW5lcmFsIGl0ZW0gKGZvciBhbGwgZWxlbWVudHMpICovXG4gICAgICAgIGdyYWJiYWJsZTogUHJvcFR5cGVzLmJvb2wsXG4gICAgICAgIC8qKiBHZW5lcmFsIGl0ZW0gKGZvciBhbGwgZWxlbWVudHMpICovXG4gICAgICAgIGdyb3VwOiBQcm9wVHlwZXMuc3RyaW5nLFxuICAgICAgICAvKiogR2VuZXJhbCBpdGVtIChmb3IgYWxsIGVsZW1lbnRzKSAqL1xuICAgICAgICBsb2NrZWQ6IFByb3BUeXBlcy5ib29sLFxuICAgICAgICAvKiogR2VuZXJhbCBpdGVtIChmb3IgYWxsIGVsZW1lbnRzKSAqL1xuICAgICAgICBzZWxlY3RhYmxlOiBQcm9wVHlwZXMuYm9vbCxcbiAgICAgICAgLyoqIEdlbmVyYWwgaXRlbSAoZm9yIGFsbCBlbGVtZW50cykgKi9cbiAgICAgICAgc2VsZWN0ZWQ6IFByb3BUeXBlcy5ib29sLFxuICAgICAgICAvKiogR2VuZXJhbCBpdGVtIChmb3IgYWxsIGVsZW1lbnRzKSAqL1xuICAgICAgICBzdHlsZTogUHJvcFR5cGVzLm9iamVjdFxuICAgIH0pLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGRhdGEgZGljdGlvbmFyeSBvZiBhbiBlZGdlIHJldHVybmVkIHdoZW4geW91IHRhcCBvciBjbGljayBpdC4gUmVhZC1vbmx5LlxuICAgICAqL1xuICAgIHRhcEVkZ2VEYXRhOiBQcm9wVHlwZXMub2JqZWN0LFxuXG4gICAgLyoqXG4gICAgICogVGhlIGRhdGEgZGljdGlvbmFyeSBvZiBhIG5vZGUgcmV0dXJuZWQgd2hlbiB5b3UgaG92ZXIgb3ZlciBpdC4gUmVhZC1vbmx5LlxuICAgICAqL1xuICAgIG1vdXNlb3Zlck5vZGVEYXRhOiBQcm9wVHlwZXMub2JqZWN0LFxuXG4gICAgLyoqXG4gICAgICogVGhlIGRhdGEgZGljdGlvbmFyeSBvZiBhbiBlZGdlIHJldHVybmVkIHdoZW4geW91IGhvdmVyIG92ZXIgaXQuIFJlYWQtb25seS5cbiAgICAgKi9cbiAgICBtb3VzZW92ZXJFZGdlRGF0YTogUHJvcFR5cGVzLm9iamVjdCxcblxuICAgIC8qKlxuICAgICAqIFRoZSBsaXN0IG9mIGRhdGEgZGljdGlvbmFyaWVzIG9mIGFsbCBzZWxlY3RlZCBub2RlcyAoZS5nLiB1c2luZ1xuICAgICAqIFNoaWZ0K0NsaWNrIHRvIHNlbGVjdCBtdWx0aXBsZSBub2Rlcywgb3IgU2hpZnQrRHJhZyB0byB1c2UgYm94IHNlbGVjdGlvbikuIFJlYWQtb25seS5cbiAgICAgKi9cbiAgICBzZWxlY3RlZE5vZGVEYXRhOiBQcm9wVHlwZXMuYXJyYXksXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbGlzdCBvZiBkYXRhIGRpY3Rpb25hcmllcyBvZiBhbGwgc2VsZWN0ZWQgZWRnZXMgKGUuZy4gdXNpbmdcbiAgICAgKiBTaGlmdCtDbGljayB0byBzZWxlY3QgbXVsdGlwbGUgbm9kZXMsIG9yIFNoaWZ0K0RyYWcgdG8gdXNlIGJveCBzZWxlY3Rpb24pLiBSZWFkLW9ubHkuXG4gICAgICovXG4gICAgc2VsZWN0ZWRFZGdlRGF0YTogUHJvcFR5cGVzLmFycmF5LFxuXG4gICAgLyoqXG4gICAgICogRGljdGlvbmFyeSBzcGVjaWZ5aW5nIG9wdGlvbnMgdG8gZ2VuZXJhdGUgYW4gaW1hZ2Ugb2YgdGhlIGN1cnJlbnQgY3l0b3NjYXBlIGdyYXBoLlxuICAgICAqIFZhbHVlIGlzIGNsZWFyZWQgYWZ0ZXIgZGF0YSBpcyByZWNlaXZlZCBhbmQgaW1hZ2UgaXMgZ2VuZXJhdGVkLiBUaGlzIHByb3BlcnR5IHdpbGxcbiAgICAgKiBiZSBpZ25vcmVkIG9uIHRoZSBpbml0aWFsIGNyZWF0aW9uIG9mIHRoZSBjeXRvc2NhcGUgb2JqZWN0IGFuZCBtdXN0IGJlIGludm9rZWQgdGhyb3VnaFxuICAgICAqIGEgY2FsbGJhY2sgYWZ0ZXIgaXQgaGFzIGJlZW4gcmVuZGVyZWQuXG4gICAgICpcbiAgICAgKiBJZiB0aGUgYXBwIGRvZXMgbm90IG5lZWQgdGhlIGltYWdlIGRhdGEgc2VydmVyIHNpZGUgYW5kL29yIGl0IHdpbGwgb25seSBiZSB1c2VkIHRvIGRvd25sb2FkXG4gICAgICogdGhlIGltYWdlLCBpdCBtYXkgYmUgcHJ1ZGVudCB0byBpbnZva2UgYCdkb3dubG9hZCdgIGZvciBgYWN0aW9uYCBpbnN0ZWFkIG9mXG4gICAgICogYCdzdG9yZSdgIHRvIGltcHJvdmUgcGVyZm9ybWFuY2UgYnkgcHJldmVudGluZyB0cmFuc2ZlciBvZiBkYXRhIHRvIHRoZSBzZXJ2ZXIuXG4gICAgICovXG4gICAgZ2VuZXJhdGVJbWFnZTogUHJvcFR5cGVzLnNoYXBlKHtcbiAgICAgICAgLyoqIEZpbGUgdHlwZSB0byBvdXRwdXQgICovXG4gICAgICAgIHR5cGU6IFByb3BUeXBlcy5vbmVPZihbJ3N2ZycsICdwbmcnLCAnanBnJywgJ2pwZWcnXSksXG4gICAgICAgIC8qKiBEaWN0aW9uYXJ5IG9mIG9wdGlvbnMgdG8gY3kucG5nKCkgLyBjeS5qcGcoKSBvciBjeS5zdmcoKSBmb3IgaW1hZ2UgZ2VuZXJhdGlvbi5cbiAgICAgICAgICogU2VlIGh0dHBzOi8vanMuY3l0b3NjYXBlLm9yZy8jY29yZS9leHBvcnQgZm9yIGRldGFpbHMuIEZvciBgJ291dHB1dCdgLCBvbmx5ICdiYXNlNjQnXG4gICAgICAgICAqIGFuZCAnYmFzZTY0dXJpJyBhcmUgc3VwcG9ydGVkLiBEZWZhdWx0OiBgeydvdXRwdXQnOiAnYmFzZTY0dXJpJ31gLiovXG4gICAgICAgIG9wdGlvbnM6IFByb3BUeXBlcy5vYmplY3QsXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgJ3N0b3JlJ2A6IFN0b3JlcyB0aGUgaW1hZ2UgZGF0YSAob25seSBqcGcgYW5kIHBuZyBhcmUgc3VwcG9ydGVkKVxuICAgICAgICAgKiBpbiBgaW1hZ2VEYXRhYCBhbmQgaW52b2tlcyBzZXJ2ZXItc2lkZSBEYXNoIGNhbGxiYWNrcy4gYCdkb3dubG9hZCdgOiBEb3dubG9hZHMgdGhlIGltYWdlXG4gICAgICAgICAqIGFzIGEgZmlsZSB3aXRoIGFsbCBkYXRhIGhhbmRsaW5nIGRvbmUgY2xpZW50LXNpZGUuIE5vIGBpbWFnZURhdGFgIGNhbGxiYWNrcyBhcmUgZmlyZWQuXG4gICAgICAgICAqIGAnYm90aCdgOiBTdG9yZXMgaW1hZ2UgZGF0YSBhbmQgZG93bmxvYWRzIGltYWdlIGFzIGZpbGUuIFRoZSBkZWZhdWx0IGlzIGAnc3RvcmUnYFxuICAgICAgICAgKi9cbiAgICAgICAgYWN0aW9uOiBQcm9wVHlwZXMub25lT2YoWydzdG9yZScsICdkb3dubG9hZCcsICdib3RoJ10pLFxuICAgICAgICAvKiogTmFtZSBmb3IgdGhlIGZpbGUgdG8gYmUgZG93bmxvYWRlZC4gRGVmYXVsdDogJ2N5dG8nLiovXG4gICAgICAgIGZpbGVuYW1lOiBQcm9wVHlwZXMuc3RyaW5nXG4gICAgfSksXG5cbiAgICAvKipcbiAgICAgKiBTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGltYWdlIHJlcXVlc3RlZCB3aXRoIGdlbmVyYXRlSW1hZ2UuIE51bGwgaWYgbm9cbiAgICAgKiBpbWFnZSB3YXMgcmVxdWVzdGVkIHlldCBvciB0aGUgcHJldmlvdXMgcmVxdWVzdCBmYWlsZWQuIFJlYWQtb25seS5cbiAgICAgKi9cbiAgICBpbWFnZURhdGE6IFByb3BUeXBlcy5zdHJpbmcsXG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIGludGVsbGlnZW50IHJlc3BvbnNpdmUgcmVzaXplIG9mIEN5dG9zY2FwZSBncmFwaCB3aXRoIHZpZXdwb3J0IHNpemUgY2hhbmdlXG4gICAgICovXG4gICAgcmVzcG9uc2l2ZTogUHJvcFR5cGVzLmJvb2xcbn07XG5cbkN5dG9zY2FwZS5kZWZhdWx0UHJvcHMgPSB7XG4gICAgc3R5bGU6IHt3aWR0aDogJzYwMHB4JywgaGVpZ2h0OiAnNjAwcHgnfSxcbiAgICBsYXlvdXQ6IHtuYW1lOiAnZ3JpZCd9LFxuICAgIHBhbjoge3g6IDAsIHk6IDB9LFxuICAgIHpvb206IDEsXG4gICAgbWluWm9vbTogMWUtNTAsXG4gICAgbWF4Wm9vbTogMWU1MCxcbiAgICB6b29taW5nRW5hYmxlZDogdHJ1ZSxcbiAgICB1c2VyWm9vbWluZ0VuYWJsZWQ6IHRydWUsXG4gICAgcGFubmluZ0VuYWJsZWQ6IHRydWUsXG4gICAgdXNlclBhbm5pbmdFbmFibGVkOiB0cnVlLFxuICAgIGJveFNlbGVjdGlvbkVuYWJsZWQ6IGZhbHNlLFxuICAgIGF1dG9sb2NrOiBmYWxzZSxcbiAgICBhdXRvdW5ncmFiaWZ5OiBmYWxzZSxcbiAgICBhdXRvdW5zZWxlY3RpZnk6IGZhbHNlLFxuICAgIGF1dG9SZWZyZXNoTGF5b3V0OiB0cnVlLFxuICAgIGdlbmVyYXRlSW1hZ2U6IHt9LFxuICAgIGltYWdlRGF0YTogbnVsbCxcbiAgICByZXNwb25zaXZlOiBmYWxzZSxcbiAgICBlbGVtZW50czogW11cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEN5dG9zY2FwZTtcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/lib/components/Cytoscape.react.js\n");
/***/ }),
/***/ "./src/lib/cyResponsive.js":
/*!*********************************!*\
!*** ./src/lib/cyResponsive.js ***!
\*********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar cyResponsive = function () {\n function cyResponsive(cy) {\n _classCallCheck(this, cyResponsive);\n\n this.shouldResize = false;\n\n this.cy = cy;\n this.curr = {};\n this.prev = {};\n\n this.marginPercentage = {};\n\n // constants\n this.containedZoomMargin = 0.05;\n\n this.toggle = this.toggle.bind(this);\n this.getViewport = this.getViewport.bind(this);\n this.updateViewport = this.updateViewport.bind(this);\n this._xConstrainedZoom = this._xConstrainedZoom.bind(this);\n this._xChangeMargin = this._xChangeMargin.bind(this);\n this._yConstrainedZoom = this._yConstrainedZoom.bind(this);\n this._yChangeMargin = this._yChangeMargin.bind(this);\n this.resize = this.resize.bind(this);\n }\n\n _createClass(cyResponsive, [{\n key: 'toggle',\n value: function toggle() {\n var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : !this.shouldResize;\n\n var cy = this.cy;\n\n if (state !== this.shouldResize) {\n if (state) {\n cy.on('render', this.updateViewport);\n cy.on('resize', this.resize);\n\n this.updateViewport(cy);\n } else {\n cy.removeListener('render', this.updateViewport);\n cy.removeListener('resize', this.resize);\n }\n\n this.shouldResize = state;\n }\n }\n }, {\n key: 'getViewport',\n value: function getViewport() {\n var cy = this.cy;\n return {\n position: cy.pan(),\n zoom: cy.zoom(),\n renderedBB: Object.assign({}, cy.elements().renderedBoundingBox()),\n height: cy.height(),\n width: cy.width()\n };\n }\n }, {\n key: 'updateViewport',\n value: function updateViewport() {\n var cy = this.cy;\n this.prev = this.getViewport(cy);\n }\n }, {\n key: '_xConstrainedZoom',\n value: function _xConstrainedZoom(level) {\n var curr = this.curr,\n prev = this.prev,\n marginPercentage = this.marginPercentage;\n\n // Look at constrained dimension\n // calculate the new position needed to maintain same left/right margin percentages\n // with new zoom\n\n var newRenderedBBX1 = marginPercentage.left * curr.width;\n\n curr.position.x = newRenderedBBX1 + (prev.position.x - prev.renderedBB.x1);\n\n // Look at unconstrained dimension\n // get midpoint\n var midpoint = curr.renderedBB.y1 + curr.renderedBB.h / 2;\n // get new height of graph\n var newHeight = curr.renderedBB.h / prev.zoom * level;\n // get new top margin\n var newRenderedBBY1 = midpoint - newHeight / 2;\n // compensate for any change in height between prev and curr\n newRenderedBBY1 = newRenderedBBY1 + (curr.height - prev.height) / 2;\n\n curr.position.y = newRenderedBBY1 + (prev.position.y - prev.renderedBB.y1);\n }\n }, {\n key: '_xChangeMargin',\n value: function _xChangeMargin(width) {\n var curr = this.curr,\n prev = this.prev;\n\n // get initial centroid percentage from the BB left boundary\n\n var xCentroidPos = prev.renderedBB.x1 + prev.renderedBB.w / 2;\n var xCentroidPosPer = xCentroidPos / prev.width;\n\n // calculate new x1 position using new width;\n var newXCentroidPos = xCentroidPosPer * width;\n\n // Find displacement in x required to bring to new position\n curr.position.x = curr.position.x + (newXCentroidPos - xCentroidPos);\n }\n }, {\n key: '_yConstrainedZoom',\n value: function _yConstrainedZoom(level) {\n // same as this._xConstrainedZoom except x and y switched where applicable\n var curr = this.curr,\n prev = this.prev,\n marginPercentage = this.marginPercentage;\n\n\n var newRenderedBBY1 = marginPercentage.top * curr.height;\n curr.position.y = newRenderedBBY1 + (prev.position.y - prev.renderedBB.y1);\n\n var midpoint = curr.renderedBB.x1 + curr.renderedBB.w / 2;\n var newWidth = curr.renderedBB.w / prev.zoom * level;\n var newRenderedBBX1 = midpoint - newWidth / 2;\n newRenderedBBX1 = newRenderedBBX1 + (curr.width - prev.width) / 2;\n\n curr.position.x = newRenderedBBX1 + (prev.position.x - prev.renderedBB.x1);\n }\n }, {\n key: '_yChangeMargin',\n value: function _yChangeMargin() {\n // same as _xChangeMargin except x and y switched where applicable\n var curr = this.curr,\n prev = this.prev;\n\n\n var yCentroidPos = prev.renderedBB.y1 + prev.renderedBB.h / 2;\n var yCentroidPosPer = yCentroidPos / prev.height;\n\n var newYCentroidPos = yCentroidPosPer * curr.height;\n\n curr.position.y = curr.position.y + (newYCentroidPos - yCentroidPos);\n }\n }, {\n key: 'resize',\n value: function resize() {\n var cy = this.cy;\n this.curr = this.getViewport(cy);\n\n var curr = this.curr,\n prev = this.prev;\n\n // Is the figure fully contained in the viewport?\n\n var fullyContained = prev.renderedBB.x1 >= 0 && prev.renderedBB.y1 >= 0 && prev.renderedBB.x2 <= prev.width && prev.renderedBB.y2 <= prev.height;\n\n // Calculate margin percentages based on prev vals\n this.marginPercentage = {\n left: prev.renderedBB.x1 / prev.width,\n // right: ( prev.width - prev.renderedBB.x2 ) / prev.width,\n top: prev.renderedBB.y1 / prev.height\n // bottom: ( prev.height - prev.renderedBB.y2 ) / prev.height,\n };\n\n // Find constrained dimension\n // Find which dimension has changed the most as a percentage of the currrent dimensions\n var xConstrained = Math.abs(1 - curr.width / prev.width) > Math.abs(1 - curr.height / prev.height);\n\n // define output variables\n if (xConstrained) {\n // calculate zoom so that the width remains same\n var targetZoom = prev.zoom / prev.width * curr.width;\n if (fullyContained) {\n var maxContainedZoom = Math.min((curr.renderedBB.y1 + curr.renderedBB.h / 2) * prev.zoom * 2 / curr.renderedBB.h, -(curr.renderedBB.y1 + curr.renderedBB.h / 2 - prev.height) * prev.zoom * 2 / curr.renderedBB.h) - this.containedZoomMargin;\n var maxContainedWidth = prev.width / prev.zoom * maxContainedZoom;\n\n // Setup state machine and required variables\n var currrentState = curr.zoom < maxContainedZoom ? -1 : 1;\n var targetState = targetZoom < maxContainedZoom ? -1 : 1;\n while (Math.abs(currrentState) <= 1) {\n // set an intermediate target zoom if a transition through the maxContained level is needed\n if (currrentState === -1) {\n var intermediateTargetZoom = targetState === 1 ? maxContainedZoom : targetZoom;\n this._xConstrainedZoom(intermediateTargetZoom);\n curr.zoom = intermediateTargetZoom;\n if (targetState === 1) {\n this.prev.position = this.curr.position;\n this.prev.width = maxContainedWidth;\n }\n } else {\n var intermediateTargetWidth = targetState === -1 ? maxContainedWidth : curr.width;\n this._xChangeMargin(intermediateTargetWidth);\n if (targetState === -1) {\n this.prev.position = this.curr.position;\n this.prev.width = maxContainedWidth;\n }\n }\n\n currrentState += 2 * targetState;\n }\n } else {\n curr.zoom = targetZoom;\n this._xConstrainedZoom(curr.zoom);\n }\n } else {\n // calculate zoom so that the width remains same\n var _targetZoom = prev.zoom / prev.height * curr.height;\n if (fullyContained) {\n var _maxContainedZoom = Math.min((curr.renderedBB.x1 + curr.renderedBB.w / 2) * prev.zoom * 2 / curr.renderedBB.w, -(curr.renderedBB.x1 + curr.renderedBB.w / 2 - prev.width) * prev.zoom * 2 / curr.renderedBB.w) - this.containedZoomMargin;\n var maxContainedHeight = prev.height / prev.zoom * _maxContainedZoom;\n\n // Setup state machine and required variables\n var _currrentState = curr.zoom < _maxContainedZoom ? -1 : 1;\n var _targetState = _targetZoom < _maxContainedZoom ? -1 : 1;\n while (Math.abs(_currrentState) <= 1) {\n // set an intermediate target zoom if a transition through the maxContained level is needed\n if (_currrentState === -1) {\n var _intermediateTargetZoom = _targetState === 1 ? _maxContainedZoom : _targetZoom;\n this._yConstrainedZoom(_intermediateTargetZoom);\n curr.zoom = _intermediateTargetZoom;\n if (_targetState === 1) {\n this.prev.position = this.curr.position;\n this.prev.height = maxContainedHeight;\n }\n } else {\n var intermediateTargetHeight = _targetState === -1 ? maxContainedHeight : curr.height;\n this._yChangeMargin(intermediateTargetHeight);\n if (_targetState === -1) {\n this.prev.position = this.curr.position;\n this.prev.height = maxContainedHeight;\n }\n }\n\n _currrentState += 2 * _targetState;\n }\n } else {\n curr.zoom = _targetZoom;\n this._yConstrainedZoom(curr.zoom);\n }\n }\n\n cy.zoom({ level: curr.zoom });\n cy.pan(curr.position);\n this.prev = this.curr;\n\n return curr;\n }\n }]);\n\n return cyResponsive;\n}();\n\nexports.default = cyResponsive;\n;//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL3NyYy9saWIvY3lSZXNwb25zaXZlLmpzPzE2M2UiXSwibmFtZXMiOlsiY3lSZXNwb25zaXZlIiwiY3kiLCJzaG91bGRSZXNpemUiLCJjdXJyIiwicHJldiIsIm1hcmdpblBlcmNlbnRhZ2UiLCJjb250YWluZWRab29tTWFyZ2luIiwidG9nZ2xlIiwiYmluZCIsImdldFZpZXdwb3J0IiwidXBkYXRlVmlld3BvcnQiLCJfeENvbnN0cmFpbmVkWm9vbSIsIl94Q2hhbmdlTWFyZ2luIiwiX3lDb25zdHJhaW5lZFpvb20iLCJfeUNoYW5nZU1hcmdpbiIsInJlc2l6ZSIsInN0YXRlIiwib24iLCJyZW1vdmVMaXN0ZW5lciIsInBvc2l0aW9uIiwicGFuIiwiem9vbSIsInJlbmRlcmVkQkIiLCJPYmplY3QiLCJhc3NpZ24iLCJlbGVtZW50cyIsInJlbmRlcmVkQm91bmRpbmdCb3giLCJoZWlnaHQiLCJ3aWR0aCIsImxldmVsIiwibmV3UmVuZGVyZWRCQlgxIiwibGVmdCIsIngiLCJ4MSIsIm1pZHBvaW50IiwieTEiLCJoIiwibmV3SGVpZ2h0IiwibmV3UmVuZGVyZWRCQlkxIiwieSIsInhDZW50cm9pZFBvcyIsInciLCJ4Q2VudHJvaWRQb3NQZXIiLCJuZXdYQ2VudHJvaWRQb3MiLCJ0b3AiLCJuZXdXaWR0aCIsInlDZW50cm9pZFBvcyIsInlDZW50cm9pZFBvc1BlciIsIm5ld1lDZW50cm9pZFBvcyIsImZ1bGx5Q29udGFpbmVkIiwieDIiLCJ5MiIsInhDb25zdHJhaW5lZCIsIk1hdGgiLCJhYnMiLCJ0YXJnZXRab29tIiwibWF4Q29udGFpbmVkWm9vbSIsIm1pbiIsIm1heENvbnRhaW5lZFdpZHRoIiwiY3VycnJlbnRTdGF0ZSIsInRhcmdldFN0YXRlIiwiaW50ZXJtZWRpYXRlVGFyZ2V0Wm9vbSIsImludGVybWVkaWF0ZVRhcmdldFdpZHRoIiwibWF4Q29udGFpbmVkSGVpZ2h0IiwiaW50ZXJtZWRpYXRlVGFyZ2V0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QUFMLENBQVV1QixNQUFWLEdBQW1Cb0Msa0JBQW5CO0FBQ0g7QUFDSjs7QUFFREosMENBQWlCLElBQUlDLFlBQXJCO0FBQ0g7QUFDSixpQkFwQ0QsTUFxQ0s7QUFDRHpELHlCQUFLa0IsSUFBTCxHQUFZa0MsV0FBWjtBQUNBLHlCQUFLMUMsaUJBQUwsQ0FBdUJWLEtBQUtrQixJQUE1QjtBQUNIO0FBQ0o7O0FBRURwQixlQUFHb0IsSUFBSCxDQUFRLEVBQUNRLE9BQU8xQixLQUFLa0IsSUFBYixFQUFSO0FBQ0FwQixlQUFHbUIsR0FBSCxDQUFPakIsS0FBS2dCLFFBQVo7QUFDQSxpQkFBS2YsSUFBTCxHQUFZLEtBQUtELElBQWpCOztBQUVBLG1CQUFPQSxJQUFQO0FBQ0g7Ozs7OztrQkE3UGdCSCxZO0FBOFBwQiIsImZpbGUiOiIuL3NyYy9saWIvY3lSZXNwb25zaXZlLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgY2xhc3MgY3lSZXNwb25zaXZlIHtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihjeSkge1xyXG4gICAgICAgIHRoaXMuc2hvdWxkUmVzaXplID0gZmFsc2U7XHJcblxyXG4gICAgICAgIHRoaXMuY3kgPSBjeTtcclxuICAgICAgICB0aGlzLmN1cnIgPSB7fTtcclxuICAgICAgICB0aGlzLnByZXYgPSB7fTtcclxuXHJcbiAgICAgICAgdGhpcy5tYXJnaW5QZXJjZW50YWdlID0ge307XHJcblxyXG4gICAgICAgIC8vIGNvbnN0YW50c1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVkWm9vbU1hcmdpbiA9IDAuMDU7XHJcblxyXG4gICAgICAgIHRoaXMudG9nZ2xlID0gdGhpcy50b2dnbGUuYmluZCh0aGlzKTtcclxuICAgICAgICB0aGlzLmdldFZpZXdwb3J0ID0gdGhpcy5nZXRWaWV3cG9ydC5iaW5kKHRoaXMpO1xyXG4gICAgICAgIHRoaXMudXBkYXRlVmlld3BvcnQgPSB0aGlzLnVwZGF0ZVZpZXdwb3J0LmJpbmQodGhpcyk7XHJcbiAgICAgICAgdGhpcy5feENvbnN0cmFpbmVkWm9vbSA9IHRoaXMuX3hDb25zdHJhaW5lZFpvb20uYmluZCh0aGlzKTtcclxuICAgICAgICB0aGlzLl94Q2hhbmdlTWFyZ2luID0gdGhpcy5feENoYW5nZU1hcmdpbi5iaW5kKHRoaXMpO1xyXG4gICAgICAgIHRoaXMuX3lDb25zdHJhaW5lZFpvb20gPSB0aGlzLl95Q29uc3RyYWluZWRab29tLmJpbmQodGhpcyk7XHJcbiAgICAgICAgdGhpcy5feUNoYW5nZU1hcmdpbiA9IHRoaXMuX3lDaGFuZ2VNYXJnaW4uYmluZCh0aGlzKTtcclxuICAgICAgICB0aGlzLnJlc2l6ZSA9IHRoaXMucmVzaXplLmJpbmQodGhpcyk7XHJcbiAgICB9XHJcblxyXG5cclxuXHJcbiAgICB0b2dnbGUoc3RhdGUgPSAhdGhpcy5zaG91bGRSZXNpemUpIHtcclxuICAgICAgICBjb25zdCBjeSA9IHRoaXMuY3k7XHJcblxyXG4gICAgICAgIGlmKHN0YXRlICE9PSB0aGlzLnNob3VsZFJlc2l6ZSkge1xyXG4gICAgICAgICAgICBpZihzdGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgY3kub24oJ3JlbmRlcicsIHRoaXMudXBkYXRlVmlld3BvcnQpO1xyXG4gICAgICAgICAgICAgICAgY3kub24oJ3Jlc2l6ZScsIHRoaXMucmVzaXplKTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVZpZXdwb3J0KGN5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGN5LnJlbW92ZUxpc3RlbmVyKCdyZW5kZXInLCB0aGlzLnVwZGF0ZVZpZXdwb3J0KTtcclxuICAgICAgICAgICAgICAgIGN5LnJlbW92ZUxpc3RlbmVyKCdyZXNpemUnLCB0aGlzLnJlc2l6ZSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMuc2hvdWxkUmVzaXplID0gc3RhdGU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuXHJcblxyXG4gICAgZ2V0Vmlld3BvcnQoKSB7XHJcbiAgICAgICAgY29uc3QgY3kgPSB0aGlzLmN5O1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiBjeS5wYW4oKSxcclxuICAgICAgICAgICAgem9vbTogY3kuem9vbSgpLFxyXG4gICAgICAgICAgICByZW5kZXJlZEJCOiBPYmplY3QuYXNzaWduKHt9LCBjeS5lbGVtZW50cygpLnJlbmRlcmVkQm91bmRpbmdCb3goKSksXHJcbiAgICAgICAgICAgIGhlaWdodDogY3kuaGVpZ2h0KCksXHJcbiAgICAgICAgICAgIHdpZHRoOiBjeS53aWR0aCgpLFxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgdXBkYXRlVmlld3BvcnQoKSB7XHJcbiAgICAgICAgY29uc3QgY3kgPSB0aGlzLmN5O1xyXG4gICAgICAgIHRoaXMucHJldiA9IHRoaXMuZ2V0Vmlld3BvcnQoY3kpO1xyXG4gICAgfVxyXG5cclxuXHJcblxyXG4gICAgX3hDb25zdHJhaW5lZFpvb20obGV2ZWwpIHtcclxuICAgICAgICBjb25zdCB7Y3VyciwgcHJldiwgbWFyZ2luUGVyY2VudGFnZX0gPSB0aGlzO1xyXG5cclxuICAgICAgICAvLyBMb29rIGF0IGNvbnN0cmFpbmVkIGRpbWVuc2lvblxyXG4gICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgbmV3IHBvc2l0aW9uIG5lZWRlZCB0byBtYWludGFpbiBzYW1lIGxlZnQvcmlnaHQgbWFyZ2luIHBlcmNlbnRhZ2VzXHJcbiAgICAgICAgLy8gd2l0aCBuZXcgem9vbVxyXG4gICAgICAgIGNvbnN0IG5ld1JlbmRlcmVkQkJYMSA9IG1hcmdpblBlcmNlbnRhZ2UubGVmdCAqIGN1cnIud2lkdGg7XHJcblxyXG4gICAgICAgIGN1cnIucG9zaXRpb24ueCA9IG5ld1JlbmRlcmVkQkJYMSArIChwcmV2LnBvc2l0aW9uLnggLSBwcmV2LnJlbmRlcmVkQkIueDEpO1xyXG5cclxuICAgICAgICAvLyBMb29rIGF0IHVuY29uc3RyYWluZWQgZGltZW5zaW9uXHJcbiAgICAgICAgLy8gZ2V0IG1pZHBvaW50XHJcbiAgICAgICAgY29uc3QgbWlkcG9pbnQgPSBjdXJyLnJlbmRlcmVkQkIueTEgKyBjdXJyLnJlbmRlcmVkQkIuaCAvIDI7XHJcbiAgICAgICAgLy8gZ2V0IG5ldyBoZWlnaHQgb2YgZ3JhcGhcclxuICAgICAgICBjb25zdCBuZXdIZWlnaHQgPSBjdXJyLnJlbmRlcmVkQkIuaCAvIHByZXYuem9vbSAqIGxldmVsO1xyXG4gICAgICAgIC8vIGdldCBuZXcgdG9wIG1hcmdpblxyXG4gICAgICAgIGxldCBuZXdSZW5kZXJlZEJCWTEgPSBtaWRwb2ludCAtIChuZXdIZWlnaHQgLyAyKTtcclxuICAgICAgICAvLyBjb21wZW5zYXRlIGZvciBhbnkgY2hhbmdlIGluIGhlaWdodCBiZXR3ZWVuIHByZXYgYW5kIGN1cnJcclxuICAgICAgICBuZXdSZW5kZXJlZEJCWTEgPSBuZXdSZW5kZXJlZEJCWTEgKyAoY3Vyci5oZWlnaHQgLSBwcmV2LmhlaWdodCkgLyAyO1xyXG5cclxuICAgICAgICBjdXJyLnBvc2l0aW9uLnkgPSBuZXdSZW5kZXJlZEJCWTEgKyAocHJldi5wb3NpdGlvbi55IC0gcHJldi5yZW5kZXJlZEJCLnkxKTtcclxuICAgIH1cclxuXHJcbiAgICBfeENoYW5nZU1hcmdpbih3aWR0aCkge1xyXG4gICAgICAgIGNvbnN0IHtjdXJyLCBwcmV2fSA9IHRoaXM7XHJcblxyXG4gICAgICAgIC8vIGdldCBpbml0aWFsIGNlbnRyb2lkIHBlcmNlbnRhZ2UgZnJvbSB0aGUgQkIgbGVmdCBib3VuZGFyeVxyXG4gICAgICAgIGNvbnN0IHhDZW50cm9pZFBvcyA9IHByZXYucmVuZGVyZWRCQi54MSArIHByZXYucmVuZGVyZWRCQi53IC8gMjtcclxuICAgICAgICBjb25zdCB4Q2VudHJvaWRQb3NQZXIgPSB4Q2VudHJvaWRQb3MgLyBwcmV2LndpZHRoO1xyXG5cclxuICAgICAgICAvLyBjYWxjdWxhdGUgbmV3IHgxIHBvc2l0aW9uIHVzaW5nIG5ldyB3aWR0aDtcclxuICAgICAgICBjb25zdCBuZXdYQ2VudHJvaWRQb3MgPSB4Q2VudHJvaWRQb3NQZXIgKiB3aWR0aDtcclxuXHJcbiAgICAgICAgLy8gRmluZCBkaXNwbGFjZW1lbnQgaW4geCByZXF1aXJlZCB0byBicmluZyB0byBuZXcgcG9zaXRpb25cclxuICAgICAgICBjdXJyLnBvc2l0aW9uLnggPSBjdXJyLnBvc2l0aW9uLnggKyAobmV3WENlbnRyb2lkUG9zIC0geENlbnRyb2lkUG9zKTtcclxuICAgIH1cclxuXHJcbiAgICBfeUNvbnN0cmFpbmVkWm9vbShsZXZlbCkge1xyXG4gICAgICAgIC8vIHNhbWUgYXMgdGhpcy5feENvbnN0cmFpbmVkWm9vbSBleGNlcHQgeCBhbmQgeSBzd2l0Y2hlZCB3aGVyZSBhcHBsaWNhYmxlXHJcbiAgICAgICAgY29uc3Qge2N1cnIsIHByZXYsIG1hcmdpblBlcmNlbnRhZ2V9ID0gdGhpcztcclxuXHJcbiAgICAgICAgY29uc3QgbmV3UmVuZGVyZWRCQlkxID0gbWFyZ2luUGVyY2VudGFnZS50b3AgKiBjdXJyLmhlaWdodDtcclxuICAgICAgICBjdXJyLnBvc2l0aW9uLnkgPSBuZXdSZW5kZXJlZEJCWTEgKyAocHJldi5wb3NpdGlvbi55IC0gcHJldi5yZW5kZXJlZEJCLnkxKTtcclxuXHJcbiAgICAgICAgY29uc3QgbWlkcG9pbnQgPSBjdXJyLnJlbmRlcmVkQkIueDEgKyBjdXJyLnJlbmRlcmVkQkIudyAvIDI7XHJcbiAgICAgICAgY29uc3QgbmV3V2lkdGggPSBjdXJyLnJlbmRlcmVkQkIudyAvIHByZXYuem9vbSAqIGxldmVsO1xyXG4gICAgICAgIGxldCBuZXdSZW5kZXJlZEJCWDEgPSBtaWRwb2ludCAtIChuZXdXaWR0aCAvIDIpO1xyXG4gICAgICAgIG5ld1JlbmRlcmVkQkJYMSA9IG5ld1JlbmRlcmVkQkJYMSArIChjdXJyLndpZHRoIC0gcHJldi53aWR0aCkgLyAyO1xyXG5cclxuICAgICAgICBjdXJyLnBvc2l0aW9uLnggPSBuZXdSZW5kZXJlZEJCWDEgKyAocHJldi5wb3NpdGlvbi54IC0gcHJldi5yZW5kZXJlZEJCLngxKTtcclxuICAgIH1cclxuXHJcbiAgICBfeUNoYW5nZU1hcmdpbigpIHtcclxuICAgICAgICAvLyBzYW1lIGFzIF94Q2hhbmdlTWFyZ2luIGV4Y2VwdCB4IGFuZCB5IHN3aXRjaGVkIHdoZXJlIGFwcGxpY2FibGVcclxuICAgICAgICBjb25zdCB7Y3VyciwgcHJldn0gPSB0aGlzO1xyXG5cclxuICAgICAgICBjb25zdCB5Q2VudHJvaWRQb3MgPSBwcmV2LnJlbmRlcmVkQkIueTEgKyBwcmV2LnJlbmRlcmVkQkIuaCAvIDI7XHJcbiAgICAgICAgY29uc3QgeUNlbnRyb2lkUG9zUGVyID0geUNlbnRyb2lkUG9zIC8gcHJldi5oZWlnaHQ7XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld1lDZW50cm9pZFBvcyA9IHlDZW50cm9pZFBvc1BlciAqIGN1cnIuaGVpZ2h0O1xyXG5cclxuICAgICAgICBjdXJyLnBvc2l0aW9uLnkgPSBjdXJyLnBvc2l0aW9uLnkgKyAobmV3WUNlbnRyb2lkUG9zIC0geUNlbnRyb2lkUG9zKTtcclxuICAgIH1cclxuXHJcblxyXG5cclxuICAgIHJlc2l6ZSgpIHtcclxuICAgICAgICBjb25zdCBjeSA9IHRoaXMuY3k7XHJcbiAgICAgICAgdGhpcy5jdXJyID0gdGhpcy5nZXRWaWV3cG9ydChjeSk7XHJcblxyXG4gICAgICAgIGNvbnN0IHtjdXJyLCBwcmV2fSA9IHRoaXM7XHJcblxyXG4gICAgICAgIC8vIElzIHRoZSBmaWd1cmUgZnVsbHkgY29udGFpbmVkIGluIHRoZSB2aWV3cG9ydD9cclxuICAgICAgICBjb25zdCBmdWxseUNvbnRhaW5lZCA9IChwcmV2LnJlbmRlcmVkQkIueDEgPj0gMClcclxuICAgICAgICAgICAgJiYgKHByZXYucmVuZGVyZWRCQi55MSA+PSAwKVxyXG4gICAgICAgICAgICAmJiAocHJldi5yZW5kZXJlZEJCLngyIDw9IHByZXYud2lkdGgpXHJcbiAgICAgICAgICAgICYmIChwcmV2LnJlbmRlcmVkQkIueTIgPD0gcHJldi5oZWlnaHQpO1xyXG5cclxuICAgICAgICAvLyBDYWxjdWxhdGUgbWFyZ2luIHBlcmNlbnRhZ2VzIGJhc2VkIG9uIHByZXYgdmFsc1xyXG4gICAgICAgIHRoaXMubWFyZ2luUGVyY2VudGFnZSA9IHtcclxuICAgICAgICAgICAgbGVmdDogcHJldi5yZW5kZXJlZEJCLngxIC8gcHJldi53aWR0aCxcclxuICAgICAgICAgICAgLy8gcmlnaHQ6ICggcHJldi53aWR0aCAtIHByZXYucmVuZGVyZWRCQi54MiApIC8gcHJldi53aWR0aCxcclxuICAgICAgICAgICAgdG9wOiBwcmV2LnJlbmRlcmVkQkIueTEgLyBwcmV2LmhlaWdodCxcclxuICAgICAgICAgICAgLy8gYm90dG9tOiAoIHByZXYuaGVpZ2h0IC0gcHJldi5yZW5kZXJlZEJCLnkyICkgLyBwcmV2LmhlaWdodCxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvLyBGaW5kIGNvbnN0cmFpbmVkIGRpbWVuc2lvblxyXG4gICAgICAgIC8vIEZpbmQgd2hpY2ggZGltZW5zaW9uIGhhcyBjaGFuZ2VkIHRoZSBtb3N0IGFzIGEgcGVyY2VudGFnZSBvZiB0aGUgY3VycnJlbnQgZGltZW5zaW9uc1xyXG4gICAgICAgIGNvbnN0IHhDb25zdHJhaW5lZCA9IE1hdGguYWJzKDEgLSAoY3Vyci53aWR0aCAvIHByZXYud2lkdGgpKVxyXG4gICAgICAgICAgICA+IE1hdGguYWJzKDEgLSAoY3Vyci5oZWlnaHQgLyBwcmV2LmhlaWdodCkpO1xyXG5cclxuICAgICAgICAvLyBkZWZpbmUgb3V0cHV0IHZhcmlhYmxlc1xyXG4gICAgICAgIGlmKHhDb25zdHJhaW5lZCkge1xyXG4gICAgICAgICAgICAvLyBjYWxjdWxhdGUgem9vbSBzbyB0aGF0IHRoZSB3aWR0aCByZW1haW5zIHNhbWVcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0Wm9vbSA9IHByZXYuem9vbSAvIHByZXYud2lkdGggKiBjdXJyLndpZHRoO1xyXG4gICAgICAgICAgICBpZihmdWxseUNvbnRhaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbWF4Q29udGFpbmVkWm9vbSA9IE1hdGgubWluKFxyXG4gICAgICAgICAgICAgICAgICAgIChjdXJyLnJlbmRlcmVkQkIueTEgKyAoY3Vyci5yZW5kZXJlZEJCLmggLyAyKSkgKiBwcmV2Lnpvb20gKiAyIC8gY3Vyci5yZW5kZXJlZEJCLmgsXHJcbiAgICAgICAgICAgICAgICAgICAgLSAoY3Vyci5yZW5kZXJlZEJCLnkxICsgKGN1cnIucmVuZGVyZWRCQi5oIC8gMikgLSBwcmV2LmhlaWdodCkgKiBwcmV2Lnpvb20gKiAyIC8gY3Vyci5yZW5kZXJlZEJCLmhcclxuICAgICAgICAgICAgICAgICkgLSB0aGlzLmNvbnRhaW5lZFpvb21NYXJnaW47XHJcbiAgICAgICAgICAgICAgICBjb25zdCBtYXhDb250YWluZWRXaWR0aCA9IHByZXYud2lkdGggLyBwcmV2Lnpvb20gKiBtYXhDb250YWluZWRab29tO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNldHVwIHN0YXRlIG1hY2hpbmUgYW5kIHJlcXVpcmVkIHZhcmlhYmxlc1xyXG4gICAgICAgICAgICAgICAgbGV0IGN1cnJyZW50U3RhdGUgPSBjdXJyLnpvb20gPCBtYXhDb250YWluZWRab29tID8gLTEgOiAxO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3RhdGUgPSB0YXJnZXRab29tIDwgbWF4Q29udGFpbmVkWm9vbSA/IC0xIDogMTtcclxuICAgICAgICAgICAgICAgIHdoaWxlKE1hdGguYWJzKGN1cnJyZW50U3RhdGUpIDw9IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBzZXQgYW4gaW50ZXJtZWRpYXRlIHRhcmdldCB6b29tIGlmIGEgdHJhbnNpdGlvbiB0aHJvdWdoIHRoZSBtYXhDb250YWluZWQgbGV2ZWwgaXMgbmVlZGVkXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoY3VycnJlbnRTdGF0ZSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW50ZXJtZWRpYXRlVGFyZ2V0Wm9vbSA9IHRhcmdldFN0YXRlID09PSAxXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IG1heENvbnRhaW5lZFpvb21cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdGFyZ2V0Wm9vbTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5feENvbnN0cmFpbmVkWm9vbShpbnRlcm1lZGlhdGVUYXJnZXRab29tKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY3Vyci56b29tID0gaW50ZXJtZWRpYXRlVGFyZ2V0Wm9vbTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGFyZ2V0U3RhdGUgPT09IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJldi5wb3NpdGlvbiA9IHRoaXMuY3Vyci5wb3NpdGlvbjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJldi53aWR0aCA9IG1heENvbnRhaW5lZFdpZHRoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnRlcm1lZGlhdGVUYXJnZXRXaWR0aCA9IHRhcmdldFN0YXRlID09PSAtMVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBtYXhDb250YWluZWRXaWR0aFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBjdXJyLndpZHRoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl94Q2hhbmdlTWFyZ2luKGludGVybWVkaWF0ZVRhcmdldFdpZHRoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGFyZ2V0U3RhdGUgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXYucG9zaXRpb24gPSB0aGlzLmN1cnIucG9zaXRpb247XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXYud2lkdGggPSBtYXhDb250YWluZWRXaWR0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgY3VycnJlbnRTdGF0ZSArPSAyICogdGFyZ2V0U3RhdGU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBjdXJyLnpvb20gPSB0YXJnZXRab29tO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5feENvbnN0cmFpbmVkWm9vbShjdXJyLnpvb20pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBjYWxjdWxhdGUgem9vbSBzbyB0aGF0IHRoZSB3aWR0aCByZW1haW5zIHNhbWVcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0Wm9vbSA9IHByZXYuem9vbSAvIHByZXYuaGVpZ2h0ICogY3Vyci5oZWlnaHQ7XHJcbiAgICAgICAgICAgIGlmKGZ1bGx5Q29udGFpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBtYXhDb250YWluZWRab29tID0gTWF0aC5taW4oXHJcbiAgICAgICAgICAgICAgICAgICAgKGN1cnIucmVuZGVyZWRCQi54MSArIChjdXJyLnJlbmRlcmVkQkIudyAvIDIpKSAqIHByZXYuem9vbSAqIDIgLyBjdXJyLnJlbmRlcmVkQkIudyxcclxuICAgICAgICAgICAgICAgICAgICAtIChjdXJyLnJlbmRlcmVkQkIueDEgKyAoY3Vyci5yZW5kZXJlZEJCLncgLyAyKSAtIHByZXYud2lkdGgpICogcHJldi56b29tICogMiAvIGN1cnIucmVuZGVyZWRCQi53XHJcbiAgICAgICAgICAgICAgICApIC0gdGhpcy5jb250YWluZWRab29tTWFyZ2luO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbWF4Q29udGFpbmVkSGVpZ2h0ID0gcHJldi5oZWlnaHQgLyBwcmV2Lnpvb20gKiBtYXhDb250YWluZWRab29tO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNldHVwIHN0YXRlIG1hY2hpbmUgYW5kIHJlcXVpcmVkIHZhcmlhYmxlc1xyXG4gICAgICAgICAgICAgICAgbGV0IGN1cnJyZW50U3RhdGUgPSBjdXJyLnpvb20gPCBtYXhDb250YWluZWRab29tID8gLTEgOiAxO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3RhdGUgPSB0YXJnZXRab29tIDwgbWF4Q29udGFpbmVkWm9vbSA/IC0xIDogMTtcclxuICAgICAgICAgICAgICAgIHdoaWxlKE1hdGguYWJzKGN1cnJyZW50U3RhdGUpIDw9IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBzZXQgYW4gaW50ZXJtZWRpYXRlIHRhcmdldCB6b29tIGlmIGEgdHJhbnNpdGlvbiB0aHJvdWdoIHRoZSBtYXhDb250YWluZWQgbGV2ZWwgaXMgbmVlZGVkXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoY3VycnJlbnRTdGF0ZSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW50ZXJtZWRpYXRlVGFyZ2V0Wm9vbSA9IHRhcmdldFN0YXRlID09PSAxXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IG1heENvbnRhaW5lZFpvb21cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdGFyZ2V0Wm9vbTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5feUNvbnN0cmFpbmVkWm9vbShpbnRlcm1lZGlhdGVUYXJnZXRab29tKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY3Vyci56b29tID0gaW50ZXJtZWRpYXRlVGFyZ2V0Wm9vbTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGFyZ2V0U3RhdGUgPT09IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJldi5wb3NpdGlvbiA9IHRoaXMuY3Vyci5wb3NpdGlvbjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJldi5oZWlnaHQgPSBtYXhDb250YWluZWRIZWlnaHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludGVybWVkaWF0ZVRhcmdldEhlaWdodCA9IHRhcmdldFN0YXRlID09PSAtMVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBtYXhDb250YWluZWRIZWlnaHRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogY3Vyci5oZWlnaHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3lDaGFuZ2VNYXJnaW4oaW50ZXJtZWRpYXRlVGFyZ2V0SGVpZ2h0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGFyZ2V0U3RhdGUgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXYucG9zaXRpb24gPSB0aGlzLmN1cnIucG9zaXRpb247XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXYuaGVpZ2h0ID0gbWF4Q29udGFpbmVkSGVpZ2h0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBjdXJycmVudFN0YXRlICs9IDIgKiB0YXJnZXRTdGF0ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGN1cnIuem9vbSA9IHRhcmdldFpvb207XHJcbiAgICAgICAgICAgICAgICB0aGlzLl95Q29uc3RyYWluZWRab29tKGN1cnIuem9vbSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGN5Lnpvb20oe2xldmVsOiBjdXJyLnpvb219KTtcclxuICAgICAgICBjeS5wYW4oY3Vyci5wb3NpdGlvbik7XHJcbiAgICAgICAgdGhpcy5wcmV2ID0gdGhpcy5jdXJyO1xyXG5cclxuICAgICAgICByZXR1cm4gY3VycjtcclxuICAgIH1cclxufTtcclxuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/lib/cyResponsive.js\n");
/***/ }),
/***/ "./src/lib/index.js":
/*!**************************!*\
!*** ./src/lib/index.js ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.Cytoscape = undefined;\n\nvar _Cytoscape = __webpack_require__(/*! ./components/Cytoscape.react */ \"./src/lib/components/Cytoscape.react.js\");\n\nvar _Cytoscape2 = _interopRequireDefault(_Cytoscape);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.Cytoscape = _Cytoscape2.default; /* eslint-disable import/prefer-default-export *///# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL3NyYy9saWIvaW5kZXguanM/ZDc1YSJdLCJuYW1lcyI6WyJDeXRvc2NhcGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTs7Ozs7O1FBR0lBLFMsR0FBQUEsbUIsRUFKSiIsImZpbGUiOiIuL3NyYy9saWIvaW5kZXguanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvcHJlZmVyLWRlZmF1bHQtZXhwb3J0ICovXG5pbXBvcnQgQ3l0b3NjYXBlIGZyb20gJy4vY29tcG9uZW50cy9DeXRvc2NhcGUucmVhY3QnO1xuXG5leHBvcnQge1xuICAgIEN5dG9zY2FwZVxufTtcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/lib/index.js\n");
/***/ }),
/***/ "react":
/*!************************!*\
!*** external "React" ***!
\************************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("(function() { module.exports = window[\"React\"]; }());//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS9leHRlcm5hbCBcIlJlYWN0XCI/YzQ4MSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxhQUFhLGtDQUFrQyxFQUFFIiwiZmlsZSI6InJlYWN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCkgeyBtb2R1bGUuZXhwb3J0cyA9IHdpbmRvd1tcIlJlYWN0XCJdOyB9KCkpOyJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///react\n");
/***/ }),
/***/ "react-dom":
/*!***************************!*\
!*** external "ReactDOM" ***!
\***************************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("(function() { module.exports = window[\"ReactDOM\"]; }());//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS9leHRlcm5hbCBcIlJlYWN0RE9NXCI/NGIyZCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxhQUFhLHFDQUFxQyxFQUFFIiwiZmlsZSI6InJlYWN0LWRvbS5qcyIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpIHsgbW9kdWxlLmV4cG9ydHMgPSB3aW5kb3dbXCJSZWFjdERPTVwiXTsgfSgpKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///react-dom\n");
/***/ })
/******/ });