/* * ATTENTION: An "eval-source-map" devtool has been used. * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./node_modules/@kurkle/color/dist/color.esm.js": /*!******************************************************!*\ !*** ./node_modules/@kurkle/color/dist/color.esm.js ***! \******************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Color: () => (/* binding */ Color),\n/* harmony export */ b2n: () => (/* binding */ b2n),\n/* harmony export */ b2p: () => (/* binding */ b2p),\n/* harmony export */ \"default\": () => (/* binding */ index_esm),\n/* harmony export */ hexParse: () => (/* binding */ hexParse),\n/* harmony export */ hexString: () => (/* binding */ hexString),\n/* harmony export */ hsl2rgb: () => (/* binding */ hsl2rgb),\n/* harmony export */ hslString: () => (/* binding */ hslString),\n/* harmony export */ hsv2rgb: () => (/* binding */ hsv2rgb),\n/* harmony export */ hueParse: () => (/* binding */ hueParse),\n/* harmony export */ hwb2rgb: () => (/* binding */ hwb2rgb),\n/* harmony export */ lim: () => (/* binding */ lim),\n/* harmony export */ n2b: () => (/* binding */ n2b),\n/* harmony export */ n2p: () => (/* binding */ n2p),\n/* harmony export */ nameParse: () => (/* binding */ nameParse),\n/* harmony export */ p2b: () => (/* binding */ p2b),\n/* harmony export */ rgb2hsl: () => (/* binding */ rgb2hsl),\n/* harmony export */ rgbParse: () => (/* binding */ rgbParse),\n/* harmony export */ rgbString: () => (/* binding */ rgbString),\n/* harmony export */ rotate: () => (/* binding */ rotate),\n/* harmony export */ round: () => (/* binding */ round)\n/* harmony export */ });\n/*!\n * @kurkle/color v0.3.4\n * https://github.com/kurkle/color#readme\n * (c) 2024 Jukka Kurkela\n * Released under the MIT License\n */\nfunction round(v) {\n return v + 0.5 | 0;\n}\nconst lim = (v, l, h) => Math.max(Math.min(v, h), l);\nfunction p2b(v) {\n return lim(round(v * 2.55), 0, 255);\n}\nfunction b2p(v) {\n return lim(round(v / 2.55), 0, 100);\n}\nfunction n2b(v) {\n return lim(round(v * 255), 0, 255);\n}\nfunction b2n(v) {\n return lim(round(v / 2.55) / 100, 0, 1);\n}\nfunction n2p(v) {\n return lim(round(v * 100), 0, 100);\n}\n\nconst map$1 = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15};\nconst hex = [...'0123456789ABCDEF'];\nconst h1 = b => hex[b & 0xF];\nconst h2 = b => hex[(b & 0xF0) >> 4] + hex[b & 0xF];\nconst eq = b => ((b & 0xF0) >> 4) === (b & 0xF);\nconst isShort = v => eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a);\nfunction hexParse(str) {\n var len = str.length;\n var ret;\n if (str[0] === '#') {\n if (len === 4 || len === 5) {\n ret = {\n r: 255 & map$1[str[1]] * 17,\n g: 255 & map$1[str[2]] * 17,\n b: 255 & map$1[str[3]] * 17,\n a: len === 5 ? map$1[str[4]] * 17 : 255\n };\n } else if (len === 7 || len === 9) {\n ret = {\n r: map$1[str[1]] << 4 | map$1[str[2]],\n g: map$1[str[3]] << 4 | map$1[str[4]],\n b: map$1[str[5]] << 4 | map$1[str[6]],\n a: len === 9 ? (map$1[str[7]] << 4 | map$1[str[8]]) : 255\n };\n }\n }\n return ret;\n}\nconst alpha = (a, f) => a < 255 ? f(a) : '';\nfunction hexString(v) {\n var f = isShort(v) ? h1 : h2;\n return v\n ? '#' + f(v.r) + f(v.g) + f(v.b) + alpha(v.a, f)\n : undefined;\n}\n\nconst HUE_RE = /^(hsla?|hwb|hsv)\\(\\s*([-+.e\\d]+)(?:deg)?[\\s,]+([-+.e\\d]+)%[\\s,]+([-+.e\\d]+)%(?:[\\s,]+([-+.e\\d]+)(%)?)?\\s*\\)$/;\nfunction hsl2rgbn(h, s, l) {\n const a = s * Math.min(l, 1 - l);\n const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n return [f(0), f(8), f(4)];\n}\nfunction hsv2rgbn(h, s, v) {\n const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);\n return [f(5), f(3), f(1)];\n}\nfunction hwb2rgbn(h, w, b) {\n const rgb = hsl2rgbn(h, 1, 0.5);\n let i;\n if (w + b > 1) {\n i = 1 / (w + b);\n w *= i;\n b *= i;\n }\n for (i = 0; i < 3; i++) {\n rgb[i] *= 1 - w - b;\n rgb[i] += w;\n }\n return rgb;\n}\nfunction hueValue(r, g, b, d, max) {\n if (r === max) {\n return ((g - b) / d) + (g < b ? 6 : 0);\n }\n if (g === max) {\n return (b - r) / d + 2;\n }\n return (r - g) / d + 4;\n}\nfunction rgb2hsl(v) {\n const range = 255;\n const r = v.r / range;\n const g = v.g / range;\n const b = v.b / range;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n let h, s, d;\n if (max !== min) {\n d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n h = hueValue(r, g, b, d, max);\n h = h * 60 + 0.5;\n }\n return [h | 0, s || 0, l];\n}\nfunction calln(f, a, b, c) {\n return (\n Array.isArray(a)\n ? f(a[0], a[1], a[2])\n : f(a, b, c)\n ).map(n2b);\n}\nfunction hsl2rgb(h, s, l) {\n return calln(hsl2rgbn, h, s, l);\n}\nfunction hwb2rgb(h, w, b) {\n return calln(hwb2rgbn, h, w, b);\n}\nfunction hsv2rgb(h, s, v) {\n return calln(hsv2rgbn, h, s, v);\n}\nfunction hue(h) {\n return (h % 360 + 360) % 360;\n}\nfunction hueParse(str) {\n const m = HUE_RE.exec(str);\n let a = 255;\n let v;\n if (!m) {\n return;\n }\n if (m[5] !== v) {\n a = m[6] ? p2b(+m[5]) : n2b(+m[5]);\n }\n const h = hue(+m[2]);\n const p1 = +m[3] / 100;\n const p2 = +m[4] / 100;\n if (m[1] === 'hwb') {\n v = hwb2rgb(h, p1, p2);\n } else if (m[1] === 'hsv') {\n v = hsv2rgb(h, p1, p2);\n } else {\n v = hsl2rgb(h, p1, p2);\n }\n return {\n r: v[0],\n g: v[1],\n b: v[2],\n a: a\n };\n}\nfunction rotate(v, deg) {\n var h = rgb2hsl(v);\n h[0] = hue(h[0] + deg);\n h = hsl2rgb(h);\n v.r = h[0];\n v.g = h[1];\n v.b = h[2];\n}\nfunction hslString(v) {\n if (!v) {\n return;\n }\n const a = rgb2hsl(v);\n const h = a[0];\n const s = n2p(a[1]);\n const l = n2p(a[2]);\n return v.a < 255\n ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})`\n : `hsl(${h}, ${s}%, ${l}%)`;\n}\n\nconst map = {\n\tx: 'dark',\n\tZ: 'light',\n\tY: 're',\n\tX: 'blu',\n\tW: 'gr',\n\tV: 'medium',\n\tU: 'slate',\n\tA: 'ee',\n\tT: 'ol',\n\tS: 'or',\n\tB: 'ra',\n\tC: 'lateg',\n\tD: 'ights',\n\tR: 'in',\n\tQ: 'turquois',\n\tE: 'hi',\n\tP: 'ro',\n\tO: 'al',\n\tN: 'le',\n\tM: 'de',\n\tL: 'yello',\n\tF: 'en',\n\tK: 'ch',\n\tG: 'arks',\n\tH: 'ea',\n\tI: 'ightg',\n\tJ: 'wh'\n};\nconst names$1 = {\n\tOiceXe: 'f0f8ff',\n\tantiquewEte: 'faebd7',\n\taqua: 'ffff',\n\taquamarRe: '7fffd4',\n\tazuY: 'f0ffff',\n\tbeige: 'f5f5dc',\n\tbisque: 'ffe4c4',\n\tblack: '0',\n\tblanKedOmond: 'ffebcd',\n\tXe: 'ff',\n\tXeviTet: '8a2be2',\n\tbPwn: 'a52a2a',\n\tburlywood: 'deb887',\n\tcaMtXe: '5f9ea0',\n\tKartYuse: '7fff00',\n\tKocTate: 'd2691e',\n\tcSO: 'ff7f50',\n\tcSnflowerXe: '6495ed',\n\tcSnsilk: 'fff8dc',\n\tcrimson: 'dc143c',\n\tcyan: 'ffff',\n\txXe: '8b',\n\txcyan: '8b8b',\n\txgTMnPd: 'b8860b',\n\txWay: 'a9a9a9',\n\txgYF: '6400',\n\txgYy: 'a9a9a9',\n\txkhaki: 'bdb76b',\n\txmagFta: '8b008b',\n\txTivegYF: '556b2f',\n\txSange: 'ff8c00',\n\txScEd: '9932cc',\n\txYd: '8b0000',\n\txsOmon: 'e9967a',\n\txsHgYF: '8fbc8f',\n\txUXe: '483d8b',\n\txUWay: '2f4f4f',\n\txUgYy: '2f4f4f',\n\txQe: 'ced1',\n\txviTet: '9400d3',\n\tdAppRk: 'ff1493',\n\tdApskyXe: 'bfff',\n\tdimWay: '696969',\n\tdimgYy: '696969',\n\tdodgerXe: '1e90ff',\n\tfiYbrick: 'b22222',\n\tflSOwEte: 'fffaf0',\n\tfoYstWAn: '228b22',\n\tfuKsia: 'ff00ff',\n\tgaRsbSo: 'dcdcdc',\n\tghostwEte: 'f8f8ff',\n\tgTd: 'ffd700',\n\tgTMnPd: 'daa520',\n\tWay: '808080',\n\tgYF: '8000',\n\tgYFLw: 'adff2f',\n\tgYy: '808080',\n\thoneyMw: 'f0fff0',\n\thotpRk: 'ff69b4',\n\tRdianYd: 'cd5c5c',\n\tRdigo: '4b0082',\n\tivSy: 'fffff0',\n\tkhaki: 'f0e68c',\n\tlavFMr: 'e6e6fa',\n\tlavFMrXsh: 'fff0f5',\n\tlawngYF: '7cfc00',\n\tNmoncEffon: 'fffacd',\n\tZXe: 'add8e6',\n\tZcSO: 'f08080',\n\tZcyan: 'e0ffff',\n\tZgTMnPdLw: 'fafad2',\n\tZWay: 'd3d3d3',\n\tZgYF: '90ee90',\n\tZgYy: 'd3d3d3',\n\tZpRk: 'ffb6c1',\n\tZsOmon: 'ffa07a',\n\tZsHgYF: '20b2aa',\n\tZskyXe: '87cefa',\n\tZUWay: '778899',\n\tZUgYy: '778899',\n\tZstAlXe: 'b0c4de',\n\tZLw: 'ffffe0',\n\tlime: 'ff00',\n\tlimegYF: '32cd32',\n\tlRF: 'faf0e6',\n\tmagFta: 'ff00ff',\n\tmaPon: '800000',\n\tVaquamarRe: '66cdaa',\n\tVXe: 'cd',\n\tVScEd: 'ba55d3',\n\tVpurpN: '9370db',\n\tVsHgYF: '3cb371',\n\tVUXe: '7b68ee',\n\tVsprRggYF: 'fa9a',\n\tVQe: '48d1cc',\n\tVviTetYd: 'c71585',\n\tmidnightXe: '191970',\n\tmRtcYam: 'f5fffa',\n\tmistyPse: 'ffe4e1',\n\tmoccasR: 'ffe4b5',\n\tnavajowEte: 'ffdead',\n\tnavy: '80',\n\tTdlace: 'fdf5e6',\n\tTive: '808000',\n\tTivedBb: '6b8e23',\n\tSange: 'ffa500',\n\tSangeYd: 'ff4500',\n\tScEd: 'da70d6',\n\tpOegTMnPd: 'eee8aa',\n\tpOegYF: '98fb98',\n\tpOeQe: 'afeeee',\n\tpOeviTetYd: 'db7093',\n\tpapayawEp: 'ffefd5',\n\tpHKpuff: 'ffdab9',\n\tperu: 'cd853f',\n\tpRk: 'ffc0cb',\n\tplum: 'dda0dd',\n\tpowMrXe: 'b0e0e6',\n\tpurpN: '800080',\n\tYbeccapurpN: '663399',\n\tYd: 'ff0000',\n\tPsybrown: 'bc8f8f',\n\tPyOXe: '4169e1',\n\tsaddNbPwn: '8b4513',\n\tsOmon: 'fa8072',\n\tsandybPwn: 'f4a460',\n\tsHgYF: '2e8b57',\n\tsHshell: 'fff5ee',\n\tsiFna: 'a0522d',\n\tsilver: 'c0c0c0',\n\tskyXe: '87ceeb',\n\tUXe: '6a5acd',\n\tUWay: '708090',\n\tUgYy: '708090',\n\tsnow: 'fffafa',\n\tsprRggYF: 'ff7f',\n\tstAlXe: '4682b4',\n\ttan: 'd2b48c',\n\tteO: '8080',\n\ttEstN: 'd8bfd8',\n\ttomato: 'ff6347',\n\tQe: '40e0d0',\n\tviTet: 'ee82ee',\n\tJHt: 'f5deb3',\n\twEte: 'ffffff',\n\twEtesmoke: 'f5f5f5',\n\tLw: 'ffff00',\n\tLwgYF: '9acd32'\n};\nfunction unpack() {\n const unpacked = {};\n const keys = Object.keys(names$1);\n const tkeys = Object.keys(map);\n let i, j, k, ok, nk;\n for (i = 0; i < keys.length; i++) {\n ok = nk = keys[i];\n for (j = 0; j < tkeys.length; j++) {\n k = tkeys[j];\n nk = nk.replace(k, map[k]);\n }\n k = parseInt(names$1[ok], 16);\n unpacked[nk] = [k >> 16 & 0xFF, k >> 8 & 0xFF, k & 0xFF];\n }\n return unpacked;\n}\n\nlet names;\nfunction nameParse(str) {\n if (!names) {\n names = unpack();\n names.transparent = [0, 0, 0, 0];\n }\n const a = names[str.toLowerCase()];\n return a && {\n r: a[0],\n g: a[1],\n b: a[2],\n a: a.length === 4 ? a[3] : 255\n };\n}\n\nconst RGB_RE = /^rgba?\\(\\s*([-+.\\d]+)(%)?[\\s,]+([-+.e\\d]+)(%)?[\\s,]+([-+.e\\d]+)(%)?(?:[\\s,/]+([-+.e\\d]+)(%)?)?\\s*\\)$/;\nfunction rgbParse(str) {\n const m = RGB_RE.exec(str);\n let a = 255;\n let r, g, b;\n if (!m) {\n return;\n }\n if (m[7] !== r) {\n const v = +m[7];\n a = m[8] ? p2b(v) : lim(v * 255, 0, 255);\n }\n r = +m[1];\n g = +m[3];\n b = +m[5];\n r = 255 & (m[2] ? p2b(r) : lim(r, 0, 255));\n g = 255 & (m[4] ? p2b(g) : lim(g, 0, 255));\n b = 255 & (m[6] ? p2b(b) : lim(b, 0, 255));\n return {\n r: r,\n g: g,\n b: b,\n a: a\n };\n}\nfunction rgbString(v) {\n return v && (\n v.a < 255\n ? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})`\n : `rgb(${v.r}, ${v.g}, ${v.b})`\n );\n}\n\nconst to = v => v <= 0.0031308 ? v * 12.92 : Math.pow(v, 1.0 / 2.4) * 1.055 - 0.055;\nconst from = v => v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\nfunction interpolate(rgb1, rgb2, t) {\n const r = from(b2n(rgb1.r));\n const g = from(b2n(rgb1.g));\n const b = from(b2n(rgb1.b));\n return {\n r: n2b(to(r + t * (from(b2n(rgb2.r)) - r))),\n g: n2b(to(g + t * (from(b2n(rgb2.g)) - g))),\n b: n2b(to(b + t * (from(b2n(rgb2.b)) - b))),\n a: rgb1.a + t * (rgb2.a - rgb1.a)\n };\n}\n\nfunction modHSL(v, i, ratio) {\n if (v) {\n let tmp = rgb2hsl(v);\n tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1));\n tmp = hsl2rgb(tmp);\n v.r = tmp[0];\n v.g = tmp[1];\n v.b = tmp[2];\n }\n}\nfunction clone(v, proto) {\n return v ? Object.assign(proto || {}, v) : v;\n}\nfunction fromObject(input) {\n var v = {r: 0, g: 0, b: 0, a: 255};\n if (Array.isArray(input)) {\n if (input.length >= 3) {\n v = {r: input[0], g: input[1], b: input[2], a: 255};\n if (input.length > 3) {\n v.a = n2b(input[3]);\n }\n }\n } else {\n v = clone(input, {r: 0, g: 0, b: 0, a: 1});\n v.a = n2b(v.a);\n }\n return v;\n}\nfunction functionParse(str) {\n if (str.charAt(0) === 'r') {\n return rgbParse(str);\n }\n return hueParse(str);\n}\nclass Color {\n constructor(input) {\n if (input instanceof Color) {\n return input;\n }\n const type = typeof input;\n let v;\n if (type === 'object') {\n v = fromObject(input);\n } else if (type === 'string') {\n v = hexParse(input) || nameParse(input) || functionParse(input);\n }\n this._rgb = v;\n this._valid = !!v;\n }\n get valid() {\n return this._valid;\n }\n get rgb() {\n var v = clone(this._rgb);\n if (v) {\n v.a = b2n(v.a);\n }\n return v;\n }\n set rgb(obj) {\n this._rgb = fromObject(obj);\n }\n rgbString() {\n return this._valid ? rgbString(this._rgb) : undefined;\n }\n hexString() {\n return this._valid ? hexString(this._rgb) : undefined;\n }\n hslString() {\n return this._valid ? hslString(this._rgb) : undefined;\n }\n mix(color, weight) {\n if (color) {\n const c1 = this.rgb;\n const c2 = color.rgb;\n let w2;\n const p = weight === w2 ? 0.5 : weight;\n const w = 2 * p - 1;\n const a = c1.a - c2.a;\n const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;\n w2 = 1 - w1;\n c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5;\n c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5;\n c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5;\n c1.a = p * c1.a + (1 - p) * c2.a;\n this.rgb = c1;\n }\n return this;\n }\n interpolate(color, t) {\n if (color) {\n this._rgb = interpolate(this._rgb, color._rgb, t);\n }\n return this;\n }\n clone() {\n return new Color(this.rgb);\n }\n alpha(a) {\n this._rgb.a = n2b(a);\n return this;\n }\n clearer(ratio) {\n const rgb = this._rgb;\n rgb.a *= 1 - ratio;\n return this;\n }\n greyscale() {\n const rgb = this._rgb;\n const val = round(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11);\n rgb.r = rgb.g = rgb.b = val;\n return this;\n }\n opaquer(ratio) {\n const rgb = this._rgb;\n rgb.a *= 1 + ratio;\n return this;\n }\n negate() {\n const v = this._rgb;\n v.r = 255 - v.r;\n v.g = 255 - v.g;\n v.b = 255 - v.b;\n return this;\n }\n lighten(ratio) {\n modHSL(this._rgb, 2, ratio);\n return this;\n }\n darken(ratio) {\n modHSL(this._rgb, 2, -ratio);\n return this;\n }\n saturate(ratio) {\n modHSL(this._rgb, 1, ratio);\n return this;\n }\n desaturate(ratio) {\n modHSL(this._rgb, 1, -ratio);\n return this;\n }\n rotate(deg) {\n rotate(this._rgb, deg);\n return this;\n }\n}\n\nfunction index_esm(input) {\n return new Color(input);\n}\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGt1cmtsZS9jb2xvci9kaXN0L2NvbG9yLmVzbS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxTQUFTO0FBQzNDLGFBQWEsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxpQkFBaUI7QUFDL0I7QUFDQSxnQkFBZ0Isa0JBQWtCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixJQUFJLElBQUksSUFBSSxJQUFJLElBQUksSUFBSSxTQUFTO0FBQ2pELGVBQWUsSUFBSSxJQUFJLElBQUksSUFBSSxJQUFJO0FBQ25DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQztBQUN0QztBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osc0JBQXNCLHVCQUF1QjtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVrTSIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9Aa3Vya2xlL2NvbG9yL2Rpc3QvY29sb3IuZXNtLmpzP2I2ODgiXSwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBAa3Vya2xlL2NvbG9yIHYwLjMuNFxuICogaHR0cHM6Ly9naXRodWIuY29tL2t1cmtsZS9jb2xvciNyZWFkbWVcbiAqIChjKSAyMDI0IEp1a2thIEt1cmtlbGFcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICovXG5mdW5jdGlvbiByb3VuZCh2KSB7XG4gIHJldHVybiB2ICsgMC41IHwgMDtcbn1cbmNvbnN0IGxpbSA9ICh2LCBsLCBoKSA9PiBNYXRoLm1heChNYXRoLm1pbih2LCBoKSwgbCk7XG5mdW5jdGlvbiBwMmIodikge1xuICByZXR1cm4gbGltKHJvdW5kKHYgKiAyLjU1KSwgMCwgMjU1KTtcbn1cbmZ1bmN0aW9uIGIycCh2KSB7XG4gIHJldHVybiBsaW0ocm91bmQodiAvIDIuNTUpLCAwLCAxMDApO1xufVxuZnVuY3Rpb24gbjJiKHYpIHtcbiAgcmV0dXJuIGxpbShyb3VuZCh2ICogMjU1KSwgMCwgMjU1KTtcbn1cbmZ1bmN0aW9uIGIybih2KSB7XG4gIHJldHVybiBsaW0ocm91bmQodiAvIDIuNTUpIC8gMTAwLCAwLCAxKTtcbn1cbmZ1bmN0aW9uIG4ycCh2KSB7XG4gIHJldHVybiBsaW0ocm91bmQodiAqIDEwMCksIDAsIDEwMCk7XG59XG5cbmNvbnN0IG1hcCQxID0gezA6IDAsIDE6IDEsIDI6IDIsIDM6IDMsIDQ6IDQsIDU6IDUsIDY6IDYsIDc6IDcsIDg6IDgsIDk6IDksIEE6IDEwLCBCOiAxMSwgQzogMTIsIEQ6IDEzLCBFOiAxNCwgRjogMTUsIGE6IDEwLCBiOiAxMSwgYzogMTIsIGQ6IDEzLCBlOiAxNCwgZjogMTV9O1xuY29uc3QgaGV4ID0gWy4uLicwMTIzNDU2Nzg5QUJDREVGJ107XG5jb25zdCBoMSA9IGIgPT4gaGV4W2IgJiAweEZdO1xuY29uc3QgaDIgPSBiID0+IGhleFsoYiAmIDB4RjApID4+IDRdICsgaGV4W2IgJiAweEZdO1xuY29uc3QgZXEgPSBiID0+ICgoYiAmIDB4RjApID4+IDQpID09PSAoYiAmIDB4Rik7XG5jb25zdCBpc1Nob3J0ID0gdiA9PiBlcSh2LnIpICYmIGVxKHYuZykgJiYgZXEodi5iKSAmJiBlcSh2LmEpO1xuZnVuY3Rpb24gaGV4UGFyc2Uoc3RyKSB7XG4gIHZhciBsZW4gPSBzdHIubGVuZ3RoO1xuICB2YXIgcmV0O1xuICBpZiAoc3RyWzBdID09PSAnIycpIHtcbiAgICBpZiAobGVuID09PSA0IHx8IGxlbiA9PT0gNSkge1xuICAgICAgcmV0ID0ge1xuICAgICAgICByOiAyNTUgJiBtYXAkMVtzdHJbMV1dICogMTcsXG4gICAgICAgIGc6IDI1NSAmIG1hcCQxW3N0clsyXV0gKiAxNyxcbiAgICAgICAgYjogMjU1ICYgbWFwJDFbc3RyWzNdXSAqIDE3LFxuICAgICAgICBhOiBsZW4gPT09IDUgPyBtYXAkMVtzdHJbNF1dICogMTcgOiAyNTVcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChsZW4gPT09IDcgfHwgbGVuID09PSA5KSB7XG4gICAgICByZXQgPSB7XG4gICAgICAgIHI6IG1hcCQxW3N0clsxXV0gPDwgNCB8IG1hcCQxW3N0clsyXV0sXG4gICAgICAgIGc6IG1hcCQxW3N0clszXV0gPDwgNCB8IG1hcCQxW3N0cls0XV0sXG4gICAgICAgIGI6IG1hcCQxW3N0cls1XV0gPDwgNCB8IG1hcCQxW3N0cls2XV0sXG4gICAgICAgIGE6IGxlbiA9PT0gOSA/IChtYXAkMVtzdHJbN11dIDw8IDQgfCBtYXAkMVtzdHJbOF1dKSA6IDI1NVxuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cbmNvbnN0IGFscGhhID0gKGEsIGYpID0+IGEgPCAyNTUgPyBmKGEpIDogJyc7XG5mdW5jdGlvbiBoZXhTdHJpbmcodikge1xuICB2YXIgZiA9IGlzU2hvcnQodikgPyBoMSA6IGgyO1xuICByZXR1cm4gdlxuICAgID8gJyMnICsgZih2LnIpICsgZih2LmcpICsgZih2LmIpICsgYWxwaGEodi5hLCBmKVxuICAgIDogdW5kZWZpbmVkO1xufVxuXG5jb25zdCBIVUVfUkUgPSAvXihoc2xhP3xod2J8aHN2KVxcKFxccyooWy0rLmVcXGRdKykoPzpkZWcpP1tcXHMsXSsoWy0rLmVcXGRdKyklW1xccyxdKyhbLSsuZVxcZF0rKSUoPzpbXFxzLF0rKFstKy5lXFxkXSspKCUpPyk/XFxzKlxcKSQvO1xuZnVuY3Rpb24gaHNsMnJnYm4oaCwgcywgbCkge1xuICBjb25zdCBhID0gcyAqIE1hdGgubWluKGwsIDEgLSBsKTtcbiAgY29uc3QgZiA9IChuLCBrID0gKG4gKyBoIC8gMzApICUgMTIpID0+IGwgLSBhICogTWF0aC5tYXgoTWF0aC5taW4oayAtIDMsIDkgLSBrLCAxKSwgLTEpO1xuICByZXR1cm4gW2YoMCksIGYoOCksIGYoNCldO1xufVxuZnVuY3Rpb24gaHN2MnJnYm4oaCwgcywgdikge1xuICBjb25zdCBmID0gKG4sIGsgPSAobiArIGggLyA2MCkgJSA2KSA9PiB2IC0gdiAqIHMgKiBNYXRoLm1heChNYXRoLm1pbihrLCA0IC0gaywgMSksIDApO1xuICByZXR1cm4gW2YoNSksIGYoMyksIGYoMSldO1xufVxuZnVuY3Rpb24gaHdiMnJnYm4oaCwgdywgYikge1xuICBjb25zdCByZ2IgPSBoc2wycmdibihoLCAxLCAwLjUpO1xuICBsZXQgaTtcbiAgaWYgKHcgKyBiID4gMSkge1xuICAgIGkgPSAxIC8gKHcgKyBiKTtcbiAgICB3ICo9IGk7XG4gICAgYiAqPSBpO1xuICB9XG4gIGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICByZ2JbaV0gKj0gMSAtIHcgLSBiO1xuICAgIHJnYltpXSArPSB3O1xuICB9XG4gIHJldHVybiByZ2I7XG59XG5mdW5jdGlvbiBodWVWYWx1ZShyLCBnLCBiLCBkLCBtYXgpIHtcbiAgaWYgKHIgPT09IG1heCkge1xuICAgIHJldHVybiAoKGcgLSBiKSAvIGQpICsgKGcgPCBiID8gNiA6IDApO1xuICB9XG4gIGlmIChnID09PSBtYXgpIHtcbiAgICByZXR1cm4gKGIgLSByKSAvIGQgKyAyO1xuICB9XG4gIHJldHVybiAociAtIGcpIC8gZCArIDQ7XG59XG5mdW5jdGlvbiByZ2IyaHNsKHYpIHtcbiAgY29uc3QgcmFuZ2UgPSAyNTU7XG4gIGNvbnN0IHIgPSB2LnIgLyByYW5nZTtcbiAgY29uc3QgZyA9IHYuZyAvIHJhbmdlO1xuICBjb25zdCBiID0gdi5iIC8gcmFuZ2U7XG4gIGNvbnN0IG1heCA9IE1hdGgubWF4KHIsIGcsIGIpO1xuICBjb25zdCBtaW4gPSBNYXRoLm1pbihyLCBnLCBiKTtcbiAgY29uc3QgbCA9IChtYXggKyBtaW4pIC8gMjtcbiAgbGV0IGgsIHMsIGQ7XG4gIGlmIChtYXggIT09IG1pbikge1xuICAgIGQgPSBtYXggLSBtaW47XG4gICAgcyA9IGwgPiAwLjUgPyBkIC8gKDIgLSBtYXggLSBtaW4pIDogZCAvIChtYXggKyBtaW4pO1xuICAgIGggPSBodWVWYWx1ZShyLCBnLCBiLCBkLCBtYXgpO1xuICAgIGggPSBoICogNjAgKyAwLjU7XG4gIH1cbiAgcmV0dXJuIFtoIHwgMCwgcyB8fCAwLCBsXTtcbn1cbmZ1bmN0aW9uIGNhbGxuKGYsIGEsIGIsIGMpIHtcbiAgcmV0dXJuIChcbiAgICBBcnJheS5pc0FycmF5KGEpXG4gICAgICA/IGYoYVswXSwgYVsxXSwgYVsyXSlcbiAgICAgIDogZihhLCBiLCBjKVxuICApLm1hcChuMmIpO1xufVxuZnVuY3Rpb24gaHNsMnJnYihoLCBzLCBsKSB7XG4gIHJldHVybiBjYWxsbihoc2wycmdibiwgaCwgcywgbCk7XG59XG5mdW5jdGlvbiBod2IycmdiKGgsIHcsIGIpIHtcbiAgcmV0dXJuIGNhbGxuKGh3YjJyZ2JuLCBoLCB3LCBiKTtcbn1cbmZ1bmN0aW9uIGhzdjJyZ2IoaCwgcywgdikge1xuICByZXR1cm4gY2FsbG4oaHN2MnJnYm4sIGgsIHMsIHYpO1xufVxuZnVuY3Rpb24gaHVlKGgpIHtcbiAgcmV0dXJuIChoICUgMzYwICsgMzYwKSAlIDM2MDtcbn1cbmZ1bmN0aW9uIGh1ZVBhcnNlKHN0cikge1xuICBjb25zdCBtID0gSFVFX1JFLmV4ZWMoc3RyKTtcbiAgbGV0IGEgPSAyNTU7XG4gIGxldCB2O1xuICBpZiAoIW0pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKG1bNV0gIT09IHYpIHtcbiAgICBhID0gbVs2XSA/IHAyYigrbVs1XSkgOiBuMmIoK21bNV0pO1xuICB9XG4gIGNvbnN0IGggPSBodWUoK21bMl0pO1xuICBjb25zdCBwMSA9ICttWzNdIC8gMTAwO1xuICBjb25zdCBwMiA9ICttWzRdIC8gMTAwO1xuICBpZiAobVsxXSA9PT0gJ2h3YicpIHtcbiAgICB2ID0gaHdiMnJnYihoLCBwMSwgcDIpO1xuICB9IGVsc2UgaWYgKG1bMV0gPT09ICdoc3YnKSB7XG4gICAgdiA9IGhzdjJyZ2IoaCwgcDEsIHAyKTtcbiAgfSBlbHNlIHtcbiAgICB2ID0gaHNsMnJnYihoLCBwMSwgcDIpO1xuICB9XG4gIHJldHVybiB7XG4gICAgcjogdlswXSxcbiAgICBnOiB2WzFdLFxuICAgIGI6IHZbMl0sXG4gICAgYTogYVxuICB9O1xufVxuZnVuY3Rpb24gcm90YXRlKHYsIGRlZykge1xuICB2YXIgaCA9IHJnYjJoc2wodik7XG4gIGhbMF0gPSBodWUoaFswXSArIGRlZyk7XG4gIGggPSBoc2wycmdiKGgpO1xuICB2LnIgPSBoWzBdO1xuICB2LmcgPSBoWzFdO1xuICB2LmIgPSBoWzJdO1xufVxuZnVuY3Rpb24gaHNsU3RyaW5nKHYpIHtcbiAgaWYgKCF2KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IGEgPSByZ2IyaHNsKHYpO1xuICBjb25zdCBoID0gYVswXTtcbiAgY29uc3QgcyA9IG4ycChhWzFdKTtcbiAgY29uc3QgbCA9IG4ycChhWzJdKTtcbiAgcmV0dXJuIHYuYSA8IDI1NVxuICAgID8gYGhzbGEoJHtofSwgJHtzfSUsICR7bH0lLCAke2Iybih2LmEpfSlgXG4gICAgOiBgaHNsKCR7aH0sICR7c30lLCAke2x9JSlgO1xufVxuXG5jb25zdCBtYXAgPSB7XG5cdHg6ICdkYXJrJyxcblx0WjogJ2xpZ2h0Jyxcblx0WTogJ3JlJyxcblx0WDogJ2JsdScsXG5cdFc6ICdncicsXG5cdFY6ICdtZWRpdW0nLFxuXHRVOiAnc2xhdGUnLFxuXHRBOiAnZWUnLFxuXHRUOiAnb2wnLFxuXHRTOiAnb3InLFxuXHRCOiAncmEnLFxuXHRDOiAnbGF0ZWcnLFxuXHREOiAnaWdodHMnLFxuXHRSOiAnaW4nLFxuXHRROiAndHVycXVvaXMnLFxuXHRFOiAnaGknLFxuXHRQOiAncm8nLFxuXHRPOiAnYWwnLFxuXHROOiAnbGUnLFxuXHRNOiAnZGUnLFxuXHRMOiAneWVsbG8nLFxuXHRGOiAnZW4nLFxuXHRLOiAnY2gnLFxuXHRHOiAnYXJrcycsXG5cdEg6ICdlYScsXG5cdEk6ICdpZ2h0ZycsXG5cdEo6ICd3aCdcbn07XG5jb25zdCBuYW1lcyQxID0ge1xuXHRPaWNlWGU6ICdmMGY4ZmYnLFxuXHRhbnRpcXVld0V0ZTogJ2ZhZWJkNycsXG5cdGFxdWE6ICdmZmZmJyxcblx0YXF1YW1hclJlOiAnN2ZmZmQ0Jyxcblx0YXp1WTogJ2YwZmZmZicsXG5cdGJlaWdlOiAnZjVmNWRjJyxcblx0YmlzcXVlOiAnZmZlNGM0Jyxcblx0YmxhY2s6ICcwJyxcblx0YmxhbktlZE9tb25kOiAnZmZlYmNkJyxcblx0WGU6ICdmZicsXG5cdFhldmlUZXQ6ICc4YTJiZTInLFxuXHRiUHduOiAnYTUyYTJhJyxcblx0YnVybHl3b29kOiAnZGViODg3Jyxcblx0Y2FNdFhlOiAnNWY5ZWEwJyxcblx0S2FydFl1c2U6ICc3ZmZmMDAnLFxuXHRLb2NUYXRlOiAnZDI2OTFlJyxcblx0Y1NPOiAnZmY3ZjUwJyxcblx0Y1NuZmxvd2VyWGU6ICc2NDk1ZWQnLFxuXHRjU25zaWxrOiAnZmZmOGRjJyxcblx0Y3JpbXNvbjogJ2RjMTQzYycsXG5cdGN5YW46ICdmZmZmJyxcblx0eFhlOiAnOGInLFxuXHR4Y3lhbjogJzhiOGInLFxuXHR4Z1RNblBkOiAnYjg4NjBiJyxcblx0eFdheTogJ2E5YTlhOScsXG5cdHhnWUY6ICc2NDAwJyxcblx0eGdZeTogJ2E5YTlhOScsXG5cdHhraGFraTogJ2JkYjc2YicsXG5cdHhtYWdGdGE6ICc4YjAwOGInLFxuXHR4VGl2ZWdZRjogJzU1NmIyZicsXG5cdHhTYW5nZTogJ2ZmOGMwMCcsXG5cdHhTY0VkOiAnOTkzMmNjJyxcblx0eFlkOiAnOGIwMDAwJyxcblx0eHNPbW9uOiAnZTk5NjdhJyxcblx0eHNIZ1lGOiAnOGZiYzhmJyxcblx0eFVYZTogJzQ4M2Q4YicsXG5cdHhVV2F5OiAnMmY0ZjRmJyxcblx0eFVnWXk6ICcyZjRmNGYnLFxuXHR4UWU6ICdjZWQxJyxcblx0eHZpVGV0OiAnOTQwMGQzJyxcblx0ZEFwcFJrOiAnZmYxNDkzJyxcblx0ZEFwc2t5WGU6ICdiZmZmJyxcblx0ZGltV2F5OiAnNjk2OTY5Jyxcblx0ZGltZ1l5OiAnNjk2OTY5Jyxcblx0ZG9kZ2VyWGU6ICcxZTkwZmYnLFxuXHRmaVlicmljazogJ2IyMjIyMicsXG5cdGZsU093RXRlOiAnZmZmYWYwJyxcblx0Zm9Zc3RXQW46ICcyMjhiMjInLFxuXHRmdUtzaWE6ICdmZjAwZmYnLFxuXHRnYVJzYlNvOiAnZGNkY2RjJyxcblx0Z2hvc3R3RXRlOiAnZjhmOGZmJyxcblx0Z1RkOiAnZmZkNzAwJyxcblx0Z1RNblBkOiAnZGFhNTIwJyxcblx0V2F5OiAnODA4MDgwJyxcblx0Z1lGOiAnODAwMCcsXG5cdGdZRkx3OiAnYWRmZjJmJyxcblx0Z1l5OiAnODA4MDgwJyxcblx0aG9uZXlNdzogJ2YwZmZmMCcsXG5cdGhvdHBSazogJ2ZmNjliNCcsXG5cdFJkaWFuWWQ6ICdjZDVjNWMnLFxuXHRSZGlnbzogJzRiMDA4MicsXG5cdGl2U3k6ICdmZmZmZjAnLFxuXHRraGFraTogJ2YwZTY4YycsXG5cdGxhdkZNcjogJ2U2ZTZmYScsXG5cdGxhdkZNclhzaDogJ2ZmZjBmNScsXG5cdGxhd25nWUY6ICc3Y2ZjMDAnLFxuXHRObW9uY0VmZm9uOiAnZmZmYWNkJyxcblx0WlhlOiAnYWRkOGU2Jyxcblx0WmNTTzogJ2YwODA4MCcsXG5cdFpjeWFuOiAnZTBmZmZmJyxcblx0WmdUTW5QZEx3OiAnZmFmYWQyJyxcblx0WldheTogJ2QzZDNkMycsXG5cdFpnWUY6ICc5MGVlOTAnLFxuXHRaZ1l5OiAnZDNkM2QzJyxcblx0WnBSazogJ2ZmYjZjMScsXG5cdFpzT21vbjogJ2ZmYTA3YScsXG5cdFpzSGdZRjogJzIwYjJhYScsXG5cdFpza3lYZTogJzg3Y2VmYScsXG5cdFpVV2F5OiAnNzc4ODk5Jyxcblx0WlVnWXk6ICc3Nzg4OTknLFxuXHRac3RBbFhlOiAnYjBjNGRlJyxcblx0Wkx3OiAnZmZmZmUwJyxcblx0bGltZTogJ2ZmMDAnLFxuXHRsaW1lZ1lGOiAnMzJjZDMyJyxcblx0bFJGOiAnZmFmMGU2Jyxcblx0bWFnRnRhOiAnZmYwMGZmJyxcblx0bWFQb246ICc4MDAwMDAnLFxuXHRWYXF1YW1hclJlOiAnNjZjZGFhJyxcblx0VlhlOiAnY2QnLFxuXHRWU2NFZDogJ2JhNTVkMycsXG5cdFZwdXJwTjogJzkzNzBkYicsXG5cdFZzSGdZRjogJzNjYjM3MScsXG5cdFZVWGU6ICc3YjY4ZWUnLFxuXHRWc3ByUmdnWUY6ICdmYTlhJyxcblx0VlFlOiAnNDhkMWNjJyxcblx0VnZpVGV0WWQ6ICdjNzE1ODUnLFxuXHRtaWRuaWdodFhlOiAnMTkxOTcwJyxcblx0bVJ0Y1lhbTogJ2Y1ZmZmYScsXG5cdG1pc3R5UHNlOiAnZmZlNGUxJyxcblx0bW9jY2FzUjogJ2ZmZTRiNScsXG5cdG5hdmFqb3dFdGU6ICdmZmRlYWQnLFxuXHRuYXZ5OiAnODAnLFxuXHRUZGxhY2U6ICdmZGY1ZTYnLFxuXHRUaXZlOiAnODA4MDAwJyxcblx0VGl2ZWRCYjogJzZiOGUyMycsXG5cdFNhbmdlOiAnZmZhNTAwJyxcblx0U2FuZ2VZZDogJ2ZmNDUwMCcsXG5cdFNjRWQ6ICdkYTcwZDYnLFxuXHRwT2VnVE1uUGQ6ICdlZWU4YWEnLFxuXHRwT2VnWUY6ICc5OGZiOTgnLFxuXHRwT2VRZTogJ2FmZWVlZScsXG5cdHBPZXZpVGV0WWQ6ICdkYjcwOTMnLFxuXHRwYXBheWF3RXA6ICdmZmVmZDUnLFxuXHRwSEtwdWZmOiAnZmZkYWI5Jyxcblx0cGVydTogJ2NkODUzZicsXG5cdHBSazogJ2ZmYzBjYicsXG5cdHBsdW06ICdkZGEwZGQnLFxuXHRwb3dNclhlOiAnYjBlMGU2Jyxcblx0cHVycE46ICc4MDAwODAnLFxuXHRZYmVjY2FwdXJwTjogJzY2MzM5OScsXG5cdFlkOiAnZmYwMDAwJyxcblx0UHN5YnJvd246ICdiYzhmOGYnLFxuXHRQeU9YZTogJzQxNjllMScsXG5cdHNhZGROYlB3bjogJzhiNDUxMycsXG5cdHNPbW9uOiAnZmE4MDcyJyxcblx0c2FuZHliUHduOiAnZjRhNDYwJyxcblx0c0hnWUY6ICcyZThiNTcnLFxuXHRzSHNoZWxsOiAnZmZmNWVlJyxcblx0c2lGbmE6ICdhMDUyMmQnLFxuXHRzaWx2ZXI6ICdjMGMwYzAnLFxuXHRza3lYZTogJzg3Y2VlYicsXG5cdFVYZTogJzZhNWFjZCcsXG5cdFVXYXk6ICc3MDgwOTAnLFxuXHRVZ1l5OiAnNzA4MDkwJyxcblx0c25vdzogJ2ZmZmFmYScsXG5cdHNwclJnZ1lGOiAnZmY3ZicsXG5cdHN0QWxYZTogJzQ2ODJiNCcsXG5cdHRhbjogJ2QyYjQ4YycsXG5cdHRlTzogJzgwODAnLFxuXHR0RXN0TjogJ2Q4YmZkOCcsXG5cdHRvbWF0bzogJ2ZmNjM0NycsXG5cdFFlOiAnNDBlMGQwJyxcblx0dmlUZXQ6ICdlZTgyZWUnLFxuXHRKSHQ6ICdmNWRlYjMnLFxuXHR3RXRlOiAnZmZmZmZmJyxcblx0d0V0ZXNtb2tlOiAnZjVmNWY1Jyxcblx0THc6ICdmZmZmMDAnLFxuXHRMd2dZRjogJzlhY2QzMidcbn07XG5mdW5jdGlvbiB1bnBhY2soKSB7XG4gIGNvbnN0IHVucGFja2VkID0ge307XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhuYW1lcyQxKTtcbiAgY29uc3QgdGtleXMgPSBPYmplY3Qua2V5cyhtYXApO1xuICBsZXQgaSwgaiwgaywgb2ssIG5rO1xuICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgIG9rID0gbmsgPSBrZXlzW2ldO1xuICAgIGZvciAoaiA9IDA7IGogPCB0a2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgayA9IHRrZXlzW2pdO1xuICAgICAgbmsgPSBuay5yZXBsYWNlKGssIG1hcFtrXSk7XG4gICAgfVxuICAgIGsgPSBwYXJzZUludChuYW1lcyQxW29rXSwgMTYpO1xuICAgIHVucGFja2VkW25rXSA9IFtrID4+IDE2ICYgMHhGRiwgayA+PiA4ICYgMHhGRiwgayAmIDB4RkZdO1xuICB9XG4gIHJldHVybiB1bnBhY2tlZDtcbn1cblxubGV0IG5hbWVzO1xuZnVuY3Rpb24gbmFtZVBhcnNlKHN0cikge1xuICBpZiAoIW5hbWVzKSB7XG4gICAgbmFtZXMgPSB1bnBhY2soKTtcbiAgICBuYW1lcy50cmFuc3BhcmVudCA9IFswLCAwLCAwLCAwXTtcbiAgfVxuICBjb25zdCBhID0gbmFtZXNbc3RyLnRvTG93ZXJDYXNlKCldO1xuICByZXR1cm4gYSAmJiB7XG4gICAgcjogYVswXSxcbiAgICBnOiBhWzFdLFxuICAgIGI6IGFbMl0sXG4gICAgYTogYS5sZW5ndGggPT09IDQgPyBhWzNdIDogMjU1XG4gIH07XG59XG5cbmNvbnN0IFJHQl9SRSA9IC9ecmdiYT9cXChcXHMqKFstKy5cXGRdKykoJSk/W1xccyxdKyhbLSsuZVxcZF0rKSglKT9bXFxzLF0rKFstKy5lXFxkXSspKCUpPyg/OltcXHMsL10rKFstKy5lXFxkXSspKCUpPyk/XFxzKlxcKSQvO1xuZnVuY3Rpb24gcmdiUGFyc2Uoc3RyKSB7XG4gIGNvbnN0IG0gPSBSR0JfUkUuZXhlYyhzdHIpO1xuICBsZXQgYSA9IDI1NTtcbiAgbGV0IHIsIGcsIGI7XG4gIGlmICghbSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAobVs3XSAhPT0gcikge1xuICAgIGNvbnN0IHYgPSArbVs3XTtcbiAgICBhID0gbVs4XSA/IHAyYih2KSA6IGxpbSh2ICogMjU1LCAwLCAyNTUpO1xuICB9XG4gIHIgPSArbVsxXTtcbiAgZyA9ICttWzNdO1xuICBiID0gK21bNV07XG4gIHIgPSAyNTUgJiAobVsyXSA/IHAyYihyKSA6IGxpbShyLCAwLCAyNTUpKTtcbiAgZyA9IDI1NSAmIChtWzRdID8gcDJiKGcpIDogbGltKGcsIDAsIDI1NSkpO1xuICBiID0gMjU1ICYgKG1bNl0gPyBwMmIoYikgOiBsaW0oYiwgMCwgMjU1KSk7XG4gIHJldHVybiB7XG4gICAgcjogcixcbiAgICBnOiBnLFxuICAgIGI6IGIsXG4gICAgYTogYVxuICB9O1xufVxuZnVuY3Rpb24gcmdiU3RyaW5nKHYpIHtcbiAgcmV0dXJuIHYgJiYgKFxuICAgIHYuYSA8IDI1NVxuICAgICAgPyBgcmdiYSgke3Yucn0sICR7di5nfSwgJHt2LmJ9LCAke2Iybih2LmEpfSlgXG4gICAgICA6IGByZ2IoJHt2LnJ9LCAke3YuZ30sICR7di5ifSlgXG4gICk7XG59XG5cbmNvbnN0IHRvID0gdiA9PiB2IDw9IDAuMDAzMTMwOCA/IHYgKiAxMi45MiA6IE1hdGgucG93KHYsIDEuMCAvIDIuNCkgKiAxLjA1NSAtIDAuMDU1O1xuY29uc3QgZnJvbSA9IHYgPT4gdiA8PSAwLjA0MDQ1ID8gdiAvIDEyLjkyIDogTWF0aC5wb3coKHYgKyAwLjA1NSkgLyAxLjA1NSwgMi40KTtcbmZ1bmN0aW9uIGludGVycG9sYXRlKHJnYjEsIHJnYjIsIHQpIHtcbiAgY29uc3QgciA9IGZyb20oYjJuKHJnYjEucikpO1xuICBjb25zdCBnID0gZnJvbShiMm4ocmdiMS5nKSk7XG4gIGNvbnN0IGIgPSBmcm9tKGIybihyZ2IxLmIpKTtcbiAgcmV0dXJuIHtcbiAgICByOiBuMmIodG8ociArIHQgKiAoZnJvbShiMm4ocmdiMi5yKSkgLSByKSkpLFxuICAgIGc6IG4yYih0byhnICsgdCAqIChmcm9tKGIybihyZ2IyLmcpKSAtIGcpKSksXG4gICAgYjogbjJiKHRvKGIgKyB0ICogKGZyb20oYjJuKHJnYjIuYikpIC0gYikpKSxcbiAgICBhOiByZ2IxLmEgKyB0ICogKHJnYjIuYSAtIHJnYjEuYSlcbiAgfTtcbn1cblxuZnVuY3Rpb24gbW9kSFNMKHYsIGksIHJhdGlvKSB7XG4gIGlmICh2KSB7XG4gICAgbGV0IHRtcCA9IHJnYjJoc2wodik7XG4gICAgdG1wW2ldID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odG1wW2ldICsgdG1wW2ldICogcmF0aW8sIGkgPT09IDAgPyAzNjAgOiAxKSk7XG4gICAgdG1wID0gaHNsMnJnYih0bXApO1xuICAgIHYuciA9IHRtcFswXTtcbiAgICB2LmcgPSB0bXBbMV07XG4gICAgdi5iID0gdG1wWzJdO1xuICB9XG59XG5mdW5jdGlvbiBjbG9uZSh2LCBwcm90bykge1xuICByZXR1cm4gdiA/IE9iamVjdC5hc3NpZ24ocHJvdG8gfHwge30sIHYpIDogdjtcbn1cbmZ1bmN0aW9uIGZyb21PYmplY3QoaW5wdXQpIHtcbiAgdmFyIHYgPSB7cjogMCwgZzogMCwgYjogMCwgYTogMjU1fTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgaWYgKGlucHV0Lmxlbmd0aCA+PSAzKSB7XG4gICAgICB2ID0ge3I6IGlucHV0WzBdLCBnOiBpbnB1dFsxXSwgYjogaW5wdXRbMl0sIGE6IDI1NX07XG4gICAgICBpZiAoaW5wdXQubGVuZ3RoID4gMykge1xuICAgICAgICB2LmEgPSBuMmIoaW5wdXRbM10pO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2ID0gY2xvbmUoaW5wdXQsIHtyOiAwLCBnOiAwLCBiOiAwLCBhOiAxfSk7XG4gICAgdi5hID0gbjJiKHYuYSk7XG4gIH1cbiAgcmV0dXJuIHY7XG59XG5mdW5jdGlvbiBmdW5jdGlvblBhcnNlKHN0cikge1xuICBpZiAoc3RyLmNoYXJBdCgwKSA9PT0gJ3InKSB7XG4gICAgcmV0dXJuIHJnYlBhcnNlKHN0cik7XG4gIH1cbiAgcmV0dXJuIGh1ZVBhcnNlKHN0cik7XG59XG5jbGFzcyBDb2xvciB7XG4gIGNvbnN0cnVjdG9yKGlucHV0KSB7XG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgQ29sb3IpIHtcbiAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG4gICAgY29uc3QgdHlwZSA9IHR5cGVvZiBpbnB1dDtcbiAgICBsZXQgdjtcbiAgICBpZiAodHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHYgPSBmcm9tT2JqZWN0KGlucHV0KTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICB2ID0gaGV4UGFyc2UoaW5wdXQpIHx8IG5hbWVQYXJzZShpbnB1dCkgfHwgZnVuY3Rpb25QYXJzZShpbnB1dCk7XG4gICAgfVxuICAgIHRoaXMuX3JnYiA9IHY7XG4gICAgdGhpcy5fdmFsaWQgPSAhIXY7XG4gIH1cbiAgZ2V0IHZhbGlkKCkge1xuICAgIHJldHVybiB0aGlzLl92YWxpZDtcbiAgfVxuICBnZXQgcmdiKCkge1xuICAgIHZhciB2ID0gY2xvbmUodGhpcy5fcmdiKTtcbiAgICBpZiAodikge1xuICAgICAgdi5hID0gYjJuKHYuYSk7XG4gICAgfVxuICAgIHJldHVybiB2O1xuICB9XG4gIHNldCByZ2Iob2JqKSB7XG4gICAgdGhpcy5fcmdiID0gZnJvbU9iamVjdChvYmopO1xuICB9XG4gIHJnYlN0cmluZygpIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsaWQgPyByZ2JTdHJpbmcodGhpcy5fcmdiKSA6IHVuZGVmaW5lZDtcbiAgfVxuICBoZXhTdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbGlkID8gaGV4U3RyaW5nKHRoaXMuX3JnYikgOiB1bmRlZmluZWQ7XG4gIH1cbiAgaHNsU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLl92YWxpZCA/IGhzbFN0cmluZyh0aGlzLl9yZ2IpIDogdW5kZWZpbmVkO1xuICB9XG4gIG1peChjb2xvciwgd2VpZ2h0KSB7XG4gICAgaWYgKGNvbG9yKSB7XG4gICAgICBjb25zdCBjMSA9IHRoaXMucmdiO1xuICAgICAgY29uc3QgYzIgPSBjb2xvci5yZ2I7XG4gICAgICBsZXQgdzI7XG4gICAgICBjb25zdCBwID0gd2VpZ2h0ID09PSB3MiA/IDAuNSA6IHdlaWdodDtcbiAgICAgIGNvbnN0IHcgPSAyICogcCAtIDE7XG4gICAgICBjb25zdCBhID0gYzEuYSAtIGMyLmE7XG4gICAgICBjb25zdCB3MSA9ICgodyAqIGEgPT09IC0xID8gdyA6ICh3ICsgYSkgLyAoMSArIHcgKiBhKSkgKyAxKSAvIDIuMDtcbiAgICAgIHcyID0gMSAtIHcxO1xuICAgICAgYzEuciA9IDB4RkYgJiB3MSAqIGMxLnIgKyB3MiAqIGMyLnIgKyAwLjU7XG4gICAgICBjMS5nID0gMHhGRiAmIHcxICogYzEuZyArIHcyICogYzIuZyArIDAuNTtcbiAgICAgIGMxLmIgPSAweEZGICYgdzEgKiBjMS5iICsgdzIgKiBjMi5iICsgMC41O1xuICAgICAgYzEuYSA9IHAgKiBjMS5hICsgKDEgLSBwKSAqIGMyLmE7XG4gICAgICB0aGlzLnJnYiA9IGMxO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBpbnRlcnBvbGF0ZShjb2xvciwgdCkge1xuICAgIGlmIChjb2xvcikge1xuICAgICAgdGhpcy5fcmdiID0gaW50ZXJwb2xhdGUodGhpcy5fcmdiLCBjb2xvci5fcmdiLCB0KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgY2xvbmUoKSB7XG4gICAgcmV0dXJuIG5ldyBDb2xvcih0aGlzLnJnYik7XG4gIH1cbiAgYWxwaGEoYSkge1xuICAgIHRoaXMuX3JnYi5hID0gbjJiKGEpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIGNsZWFyZXIocmF0aW8pIHtcbiAgICBjb25zdCByZ2IgPSB0aGlzLl9yZ2I7XG4gICAgcmdiLmEgKj0gMSAtIHJhdGlvO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIGdyZXlzY2FsZSgpIHtcbiAgICBjb25zdCByZ2IgPSB0aGlzLl9yZ2I7XG4gICAgY29uc3QgdmFsID0gcm91bmQocmdiLnIgKiAwLjMgKyByZ2IuZyAqIDAuNTkgKyByZ2IuYiAqIDAuMTEpO1xuICAgIHJnYi5yID0gcmdiLmcgPSByZ2IuYiA9IHZhbDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBvcGFxdWVyKHJhdGlvKSB7XG4gICAgY29uc3QgcmdiID0gdGhpcy5fcmdiO1xuICAgIHJnYi5hICo9IDEgKyByYXRpbztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBuZWdhdGUoKSB7XG4gICAgY29uc3QgdiA9IHRoaXMuX3JnYjtcbiAgICB2LnIgPSAyNTUgLSB2LnI7XG4gICAgdi5nID0gMjU1IC0gdi5nO1xuICAgIHYuYiA9IDI1NSAtIHYuYjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBsaWdodGVuKHJhdGlvKSB7XG4gICAgbW9kSFNMKHRoaXMuX3JnYiwgMiwgcmF0aW8pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIGRhcmtlbihyYXRpbykge1xuICAgIG1vZEhTTCh0aGlzLl9yZ2IsIDIsIC1yYXRpbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgc2F0dXJhdGUocmF0aW8pIHtcbiAgICBtb2RIU0wodGhpcy5fcmdiLCAxLCByYXRpbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgZGVzYXR1cmF0ZShyYXRpbykge1xuICAgIG1vZEhTTCh0aGlzLl9yZ2IsIDEsIC1yYXRpbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgcm90YXRlKGRlZykge1xuICAgIHJvdGF0ZSh0aGlzLl9yZ2IsIGRlZyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5kZXhfZXNtKGlucHV0KSB7XG4gIHJldHVybiBuZXcgQ29sb3IoaW5wdXQpO1xufVxuXG5leHBvcnQgeyBDb2xvciwgYjJuLCBiMnAsIGluZGV4X2VzbSBhcyBkZWZhdWx0LCBoZXhQYXJzZSwgaGV4U3RyaW5nLCBoc2wycmdiLCBoc2xTdHJpbmcsIGhzdjJyZ2IsIGh1ZVBhcnNlLCBod2IycmdiLCBsaW0sIG4yYiwgbjJwLCBuYW1lUGFyc2UsIHAyYiwgcmdiMmhzbCwgcmdiUGFyc2UsIHJnYlN0cmluZywgcm90YXRlLCByb3VuZCB9O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/@kurkle/color/dist/color.esm.js\n"); /***/ }), /***/ "./node_modules/chart.js/auto/auto.js": /*!********************************************!*\ !*** ./node_modules/chart.js/auto/auto.js ***! \********************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Animation: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Animation),\n/* harmony export */ Animations: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Animations),\n/* harmony export */ ArcElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.ArcElement),\n/* harmony export */ BarController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BarController),\n/* harmony export */ BarElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BarElement),\n/* harmony export */ BasePlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BasePlatform),\n/* harmony export */ BasicPlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BasicPlatform),\n/* harmony export */ BubbleController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BubbleController),\n/* harmony export */ CategoryScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.CategoryScale),\n/* harmony export */ Chart: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Chart),\n/* harmony export */ Colors: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Colors),\n/* harmony export */ DatasetController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.DatasetController),\n/* harmony export */ Decimation: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Decimation),\n/* harmony export */ DomPlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.DomPlatform),\n/* harmony export */ DoughnutController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.DoughnutController),\n/* harmony export */ Element: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Element),\n/* harmony export */ Filler: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Filler),\n/* harmony export */ Interaction: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Interaction),\n/* harmony export */ Legend: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Legend),\n/* harmony export */ LineController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LineController),\n/* harmony export */ LineElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LineElement),\n/* harmony export */ LinearScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LinearScale),\n/* harmony export */ LogarithmicScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LogarithmicScale),\n/* harmony export */ PieController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.PieController),\n/* harmony export */ PointElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.PointElement),\n/* harmony export */ PolarAreaController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.PolarAreaController),\n/* harmony export */ RadarController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.RadarController),\n/* harmony export */ RadialLinearScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.RadialLinearScale),\n/* harmony export */ Scale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Scale),\n/* harmony export */ ScatterController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.ScatterController),\n/* harmony export */ SubTitle: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.SubTitle),\n/* harmony export */ Ticks: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Ticks),\n/* harmony export */ TimeScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.TimeScale),\n/* harmony export */ TimeSeriesScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.TimeSeriesScale),\n/* harmony export */ Title: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Title),\n/* harmony export */ Tooltip: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Tooltip),\n/* harmony export */ _adapters: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__._adapters),\n/* harmony export */ _detectPlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__._detectPlatform),\n/* harmony export */ animator: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.animator),\n/* harmony export */ controllers: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.controllers),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ defaults: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.defaults),\n/* harmony export */ elements: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.elements),\n/* harmony export */ layouts: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.layouts),\n/* harmony export */ plugins: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.plugins),\n/* harmony export */ registerables: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.registerables),\n/* harmony export */ registry: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.registry),\n/* harmony export */ scales: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.scales)\n/* harmony export */ });\n/* harmony import */ var _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../dist/chart.js */ \"./node_modules/chart.js/dist/chart.js\");\n\n\n_dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Chart.register(..._dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.registerables);\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Chart);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvYXV0by9hdXRvLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBc0Q7O0FBRXRELGlEQUFLLGFBQWEseURBQWE7O0FBRUU7QUFDakMsaUVBQWUsaURBQUssRUFBQyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jaGFydC5qcy9hdXRvL2F1dG8uanM/YzgyOSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0NoYXJ0LCByZWdpc3RlcmFibGVzfSBmcm9tICcuLi9kaXN0L2NoYXJ0LmpzJztcblxuQ2hhcnQucmVnaXN0ZXIoLi4ucmVnaXN0ZXJhYmxlcyk7XG5cbmV4cG9ydCAqIGZyb20gJy4uL2Rpc3QvY2hhcnQuanMnO1xuZXhwb3J0IGRlZmF1bHQgQ2hhcnQ7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/chart.js/auto/auto.js\n"); /***/ }), /***/ "./node_modules/chart.js/dist/chart.js": /*!*********************************************!*\ !*** ./node_modules/chart.js/dist/chart.js ***! \*********************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Animation: () => (/* binding */ Animation),\n/* harmony export */ Animations: () => (/* binding */ Animations),\n/* harmony export */ ArcElement: () => (/* binding */ ArcElement),\n/* harmony export */ BarController: () => (/* binding */ BarController),\n/* harmony export */ BarElement: () => (/* binding */ BarElement),\n/* harmony export */ BasePlatform: () => (/* binding */ BasePlatform),\n/* harmony export */ BasicPlatform: () => (/* binding */ BasicPlatform),\n/* harmony export */ BubbleController: () => (/* binding */ BubbleController),\n/* harmony export */ CategoryScale: () => (/* binding */ CategoryScale),\n/* harmony export */ Chart: () => (/* binding */ Chart),\n/* harmony export */ Colors: () => (/* binding */ plugin_colors),\n/* harmony export */ DatasetController: () => (/* binding */ DatasetController),\n/* harmony export */ Decimation: () => (/* binding */ plugin_decimation),\n/* harmony export */ DomPlatform: () => (/* binding */ DomPlatform),\n/* harmony export */ DoughnutController: () => (/* binding */ DoughnutController),\n/* harmony export */ Element: () => (/* binding */ Element),\n/* harmony export */ Filler: () => (/* binding */ index),\n/* harmony export */ Interaction: () => (/* binding */ Interaction),\n/* harmony export */ Legend: () => (/* binding */ plugin_legend),\n/* harmony export */ LineController: () => (/* binding */ LineController),\n/* harmony export */ LineElement: () => (/* binding */ LineElement),\n/* harmony export */ LinearScale: () => (/* binding */ LinearScale),\n/* harmony export */ LogarithmicScale: () => (/* binding */ LogarithmicScale),\n/* harmony export */ PieController: () => (/* binding */ PieController),\n/* harmony export */ PointElement: () => (/* binding */ PointElement),\n/* harmony export */ PolarAreaController: () => (/* binding */ PolarAreaController),\n/* harmony export */ RadarController: () => (/* binding */ RadarController),\n/* harmony export */ RadialLinearScale: () => (/* binding */ RadialLinearScale),\n/* harmony export */ Scale: () => (/* binding */ Scale),\n/* harmony export */ ScatterController: () => (/* binding */ ScatterController),\n/* harmony export */ SubTitle: () => (/* binding */ plugin_subtitle),\n/* harmony export */ Ticks: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM),\n/* harmony export */ TimeScale: () => (/* binding */ TimeScale),\n/* harmony export */ TimeSeriesScale: () => (/* binding */ TimeSeriesScale),\n/* harmony export */ Title: () => (/* binding */ plugin_title),\n/* harmony export */ Tooltip: () => (/* binding */ plugin_tooltip),\n/* harmony export */ _adapters: () => (/* binding */ adapters),\n/* harmony export */ _detectPlatform: () => (/* binding */ _detectPlatform),\n/* harmony export */ animator: () => (/* binding */ animator),\n/* harmony export */ controllers: () => (/* binding */ controllers),\n/* harmony export */ defaults: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d),\n/* harmony export */ elements: () => (/* binding */ elements),\n/* harmony export */ layouts: () => (/* binding */ layouts),\n/* harmony export */ plugins: () => (/* binding */ plugins),\n/* harmony export */ registerables: () => (/* binding */ registerables),\n/* harmony export */ registry: () => (/* binding */ registry),\n/* harmony export */ scales: () => (/* binding */ scales)\n/* harmony export */ });\n/* harmony import */ var _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chunks/helpers.dataset.js */ \"./node_modules/chart.js/dist/chunks/helpers.dataset.js\");\n/*!\n * Chart.js v4.5.0\n * https://www.chartjs.org\n * (c) 2025 Chart.js Contributors\n * Released under the MIT License\n */\n\n\n\nclass Animator {\n constructor(){\n this._request = null;\n this._charts = new Map();\n this._running = false;\n this._lastDate = undefined;\n }\n _notify(chart, anims, date, type) {\n const callbacks = anims.listeners[type];\n const numSteps = anims.duration;\n callbacks.forEach((fn)=>fn({\n chart,\n initial: anims.initial,\n numSteps,\n currentStep: Math.min(date - anims.start, numSteps)\n }));\n }\n _refresh() {\n if (this._request) {\n return;\n }\n this._running = true;\n this._request = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.r.call(window, ()=>{\n this._update();\n this._request = null;\n if (this._running) {\n this._refresh();\n }\n });\n }\n _update(date = Date.now()) {\n let remaining = 0;\n this._charts.forEach((anims, chart)=>{\n if (!anims.running || !anims.items.length) {\n return;\n }\n const items = anims.items;\n let i = items.length - 1;\n let draw = false;\n let item;\n for(; i >= 0; --i){\n item = items[i];\n if (item._active) {\n if (item._total > anims.duration) {\n anims.duration = item._total;\n }\n item.tick(date);\n draw = true;\n } else {\n items[i] = items[items.length - 1];\n items.pop();\n }\n }\n if (draw) {\n chart.draw();\n this._notify(chart, anims, date, 'progress');\n }\n if (!items.length) {\n anims.running = false;\n this._notify(chart, anims, date, 'complete');\n anims.initial = false;\n }\n remaining += items.length;\n });\n this._lastDate = date;\n if (remaining === 0) {\n this._running = false;\n }\n }\n _getAnims(chart) {\n const charts = this._charts;\n let anims = charts.get(chart);\n if (!anims) {\n anims = {\n running: false,\n initial: true,\n items: [],\n listeners: {\n complete: [],\n progress: []\n }\n };\n charts.set(chart, anims);\n }\n return anims;\n }\n listen(chart, event, cb) {\n this._getAnims(chart).listeners[event].push(cb);\n }\n add(chart, items) {\n if (!items || !items.length) {\n return;\n }\n this._getAnims(chart).items.push(...items);\n }\n has(chart) {\n return this._getAnims(chart).items.length > 0;\n }\n start(chart) {\n const anims = this._charts.get(chart);\n if (!anims) {\n return;\n }\n anims.running = true;\n anims.start = Date.now();\n anims.duration = anims.items.reduce((acc, cur)=>Math.max(acc, cur._duration), 0);\n this._refresh();\n }\n running(chart) {\n if (!this._running) {\n return false;\n }\n const anims = this._charts.get(chart);\n if (!anims || !anims.running || !anims.items.length) {\n return false;\n }\n return true;\n }\n stop(chart) {\n const anims = this._charts.get(chart);\n if (!anims || !anims.items.length) {\n return;\n }\n const items = anims.items;\n let i = items.length - 1;\n for(; i >= 0; --i){\n items[i].cancel();\n }\n anims.items = [];\n this._notify(chart, anims, Date.now(), 'complete');\n }\n remove(chart) {\n return this._charts.delete(chart);\n }\n}\nvar animator = /* #__PURE__ */ new Animator();\n\nconst transparent = 'transparent';\nconst interpolators = {\n boolean (from, to, factor) {\n return factor > 0.5 ? to : from;\n },\n color (from, to, factor) {\n const c0 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.c)(from || transparent);\n const c1 = c0.valid && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.c)(to || transparent);\n return c1 && c1.valid ? c1.mix(c0, factor).hexString() : to;\n },\n number (from, to, factor) {\n return from + (to - from) * factor;\n }\n};\nclass Animation {\n constructor(cfg, target, prop, to){\n const currentValue = target[prop];\n to = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([\n cfg.to,\n to,\n currentValue,\n cfg.from\n ]);\n const from = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([\n cfg.from,\n currentValue,\n to\n ]);\n this._active = true;\n this._fn = cfg.fn || interpolators[cfg.type || typeof from];\n this._easing = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.e[cfg.easing] || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.e.linear;\n this._start = Math.floor(Date.now() + (cfg.delay || 0));\n this._duration = this._total = Math.floor(cfg.duration);\n this._loop = !!cfg.loop;\n this._target = target;\n this._prop = prop;\n this._from = from;\n this._to = to;\n this._promises = undefined;\n }\n active() {\n return this._active;\n }\n update(cfg, to, date) {\n if (this._active) {\n this._notify(false);\n const currentValue = this._target[this._prop];\n const elapsed = date - this._start;\n const remain = this._duration - elapsed;\n this._start = date;\n this._duration = Math.floor(Math.max(remain, cfg.duration));\n this._total += elapsed;\n this._loop = !!cfg.loop;\n this._to = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([\n cfg.to,\n to,\n currentValue,\n cfg.from\n ]);\n this._from = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([\n cfg.from,\n currentValue,\n to\n ]);\n }\n }\n cancel() {\n if (this._active) {\n this.tick(Date.now());\n this._active = false;\n this._notify(false);\n }\n }\n tick(date) {\n const elapsed = date - this._start;\n const duration = this._duration;\n const prop = this._prop;\n const from = this._from;\n const loop = this._loop;\n const to = this._to;\n let factor;\n this._active = from !== to && (loop || elapsed < duration);\n if (!this._active) {\n this._target[prop] = to;\n this._notify(true);\n return;\n }\n if (elapsed < 0) {\n this._target[prop] = from;\n return;\n }\n factor = elapsed / duration % 2;\n factor = loop && factor > 1 ? 2 - factor : factor;\n factor = this._easing(Math.min(1, Math.max(0, factor)));\n this._target[prop] = this._fn(from, to, factor);\n }\n wait() {\n const promises = this._promises || (this._promises = []);\n return new Promise((res, rej)=>{\n promises.push({\n res,\n rej\n });\n });\n }\n _notify(resolved) {\n const method = resolved ? 'res' : 'rej';\n const promises = this._promises || [];\n for(let i = 0; i < promises.length; i++){\n promises[i][method]();\n }\n }\n}\n\nclass Animations {\n constructor(chart, config){\n this._chart = chart;\n this._properties = new Map();\n this.configure(config);\n }\n configure(config) {\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(config)) {\n return;\n }\n const animationOptions = Object.keys(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.animation);\n const animatedProps = this._properties;\n Object.getOwnPropertyNames(config).forEach((key)=>{\n const cfg = config[key];\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(cfg)) {\n return;\n }\n const resolved = {};\n for (const option of animationOptions){\n resolved[option] = cfg[option];\n }\n ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(cfg.properties) && cfg.properties || [\n key\n ]).forEach((prop)=>{\n if (prop === key || !animatedProps.has(prop)) {\n animatedProps.set(prop, resolved);\n }\n });\n });\n }\n _animateOptions(target, values) {\n const newOptions = values.options;\n const options = resolveTargetOptions(target, newOptions);\n if (!options) {\n return [];\n }\n const animations = this._createAnimations(options, newOptions);\n if (newOptions.$shared) {\n awaitAll(target.options.$animations, newOptions).then(()=>{\n target.options = newOptions;\n }, ()=>{\n });\n }\n return animations;\n }\n _createAnimations(target, values) {\n const animatedProps = this._properties;\n const animations = [];\n const running = target.$animations || (target.$animations = {});\n const props = Object.keys(values);\n const date = Date.now();\n let i;\n for(i = props.length - 1; i >= 0; --i){\n const prop = props[i];\n if (prop.charAt(0) === '$') {\n continue;\n }\n if (prop === 'options') {\n animations.push(...this._animateOptions(target, values));\n continue;\n }\n const value = values[prop];\n let animation = running[prop];\n const cfg = animatedProps.get(prop);\n if (animation) {\n if (cfg && animation.active()) {\n animation.update(cfg, value, date);\n continue;\n } else {\n animation.cancel();\n }\n }\n if (!cfg || !cfg.duration) {\n target[prop] = value;\n continue;\n }\n running[prop] = animation = new Animation(cfg, target, prop, value);\n animations.push(animation);\n }\n return animations;\n }\n update(target, values) {\n if (this._properties.size === 0) {\n Object.assign(target, values);\n return;\n }\n const animations = this._createAnimations(target, values);\n if (animations.length) {\n animator.add(this._chart, animations);\n return true;\n }\n }\n}\nfunction awaitAll(animations, properties) {\n const running = [];\n const keys = Object.keys(properties);\n for(let i = 0; i < keys.length; i++){\n const anim = animations[keys[i]];\n if (anim && anim.active()) {\n running.push(anim.wait());\n }\n }\n return Promise.all(running);\n}\nfunction resolveTargetOptions(target, newOptions) {\n if (!newOptions) {\n return;\n }\n let options = target.options;\n if (!options) {\n target.options = newOptions;\n return;\n }\n if (options.$shared) {\n target.options = options = Object.assign({}, options, {\n $shared: false,\n $animations: {}\n });\n }\n return options;\n}\n\nfunction scaleClip(scale, allowedOverflow) {\n const opts = scale && scale.options || {};\n const reverse = opts.reverse;\n const min = opts.min === undefined ? allowedOverflow : 0;\n const max = opts.max === undefined ? allowedOverflow : 0;\n return {\n start: reverse ? max : min,\n end: reverse ? min : max\n };\n}\nfunction defaultClip(xScale, yScale, allowedOverflow) {\n if (allowedOverflow === false) {\n return false;\n }\n const x = scaleClip(xScale, allowedOverflow);\n const y = scaleClip(yScale, allowedOverflow);\n return {\n top: y.end,\n right: x.end,\n bottom: y.start,\n left: x.start\n };\n}\nfunction toClip(value) {\n let t, r, b, l;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(value)) {\n t = value.top;\n r = value.right;\n b = value.bottom;\n l = value.left;\n } else {\n t = r = b = l = value;\n }\n return {\n top: t,\n right: r,\n bottom: b,\n left: l,\n disabled: value === false\n };\n}\nfunction getSortedDatasetIndices(chart, filterVisible) {\n const keys = [];\n const metasets = chart._getSortedDatasetMetas(filterVisible);\n let i, ilen;\n for(i = 0, ilen = metasets.length; i < ilen; ++i){\n keys.push(metasets[i].index);\n }\n return keys;\n}\nfunction applyStack(stack, value, dsIndex, options = {}) {\n const keys = stack.keys;\n const singleMode = options.mode === 'single';\n let i, ilen, datasetIndex, otherValue;\n if (value === null) {\n return;\n }\n let found = false;\n for(i = 0, ilen = keys.length; i < ilen; ++i){\n datasetIndex = +keys[i];\n if (datasetIndex === dsIndex) {\n found = true;\n if (options.all) {\n continue;\n }\n break;\n }\n otherValue = stack.values[datasetIndex];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(otherValue) && (singleMode || value === 0 || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) === (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(otherValue))) {\n value += otherValue;\n }\n }\n if (!found && !options.all) {\n return 0;\n }\n return value;\n}\nfunction convertObjectDataToArray(data, meta) {\n const { iScale , vScale } = meta;\n const iAxisKey = iScale.axis === 'x' ? 'x' : 'y';\n const vAxisKey = vScale.axis === 'x' ? 'x' : 'y';\n const keys = Object.keys(data);\n const adata = new Array(keys.length);\n let i, ilen, key;\n for(i = 0, ilen = keys.length; i < ilen; ++i){\n key = keys[i];\n adata[i] = {\n [iAxisKey]: key,\n [vAxisKey]: data[key]\n };\n }\n return adata;\n}\nfunction isStacked(scale, meta) {\n const stacked = scale && scale.options.stacked;\n return stacked || stacked === undefined && meta.stack !== undefined;\n}\nfunction getStackKey(indexScale, valueScale, meta) {\n return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`;\n}\nfunction getUserBounds(scale) {\n const { min , max , minDefined , maxDefined } = scale.getUserBounds();\n return {\n min: minDefined ? min : Number.NEGATIVE_INFINITY,\n max: maxDefined ? max : Number.POSITIVE_INFINITY\n };\n}\nfunction getOrCreateStack(stacks, stackKey, indexValue) {\n const subStack = stacks[stackKey] || (stacks[stackKey] = {});\n return subStack[indexValue] || (subStack[indexValue] = {});\n}\nfunction getLastIndexInStack(stack, vScale, positive, type) {\n for (const meta of vScale.getMatchingVisibleMetas(type).reverse()){\n const value = stack[meta.index];\n if (positive && value > 0 || !positive && value < 0) {\n return meta.index;\n }\n }\n return null;\n}\nfunction updateStacks(controller, parsed) {\n const { chart , _cachedMeta: meta } = controller;\n const stacks = chart._stacks || (chart._stacks = {});\n const { iScale , vScale , index: datasetIndex } = meta;\n const iAxis = iScale.axis;\n const vAxis = vScale.axis;\n const key = getStackKey(iScale, vScale, meta);\n const ilen = parsed.length;\n let stack;\n for(let i = 0; i < ilen; ++i){\n const item = parsed[i];\n const { [iAxis]: index , [vAxis]: value } = item;\n const itemStacks = item._stacks || (item._stacks = {});\n stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);\n stack[datasetIndex] = value;\n stack._top = getLastIndexInStack(stack, vScale, true, meta.type);\n stack._bottom = getLastIndexInStack(stack, vScale, false, meta.type);\n const visualValues = stack._visualValues || (stack._visualValues = {});\n visualValues[datasetIndex] = value;\n }\n}\nfunction getFirstScaleId(chart, axis) {\n const scales = chart.scales;\n return Object.keys(scales).filter((key)=>scales[key].axis === axis).shift();\n}\nfunction createDatasetContext(parent, index) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {\n active: false,\n dataset: undefined,\n datasetIndex: index,\n index,\n mode: 'default',\n type: 'dataset'\n });\n}\nfunction createDataContext(parent, index, element) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {\n active: false,\n dataIndex: index,\n parsed: undefined,\n raw: undefined,\n element,\n index,\n mode: 'default',\n type: 'data'\n });\n}\nfunction clearStacks(meta, items) {\n const datasetIndex = meta.controller.index;\n const axis = meta.vScale && meta.vScale.axis;\n if (!axis) {\n return;\n }\n items = items || meta._parsed;\n for (const parsed of items){\n const stacks = parsed._stacks;\n if (!stacks || stacks[axis] === undefined || stacks[axis][datasetIndex] === undefined) {\n return;\n }\n delete stacks[axis][datasetIndex];\n if (stacks[axis]._visualValues !== undefined && stacks[axis]._visualValues[datasetIndex] !== undefined) {\n delete stacks[axis]._visualValues[datasetIndex];\n }\n }\n}\nconst isDirectUpdateMode = (mode)=>mode === 'reset' || mode === 'none';\nconst cloneIfNotShared = (cached, shared)=>shared ? cached : Object.assign({}, cached);\nconst createStack = (canStack, meta, chart)=>canStack && !meta.hidden && meta._stacked && {\n keys: getSortedDatasetIndices(chart, true),\n values: null\n };\nclass DatasetController {\n static defaults = {};\n static datasetElementType = null;\n static dataElementType = null;\n constructor(chart, datasetIndex){\n this.chart = chart;\n this._ctx = chart.ctx;\n this.index = datasetIndex;\n this._cachedDataOpts = {};\n this._cachedMeta = this.getMeta();\n this._type = this._cachedMeta.type;\n this.options = undefined;\n this._parsing = false;\n this._data = undefined;\n this._objectData = undefined;\n this._sharedOptions = undefined;\n this._drawStart = undefined;\n this._drawCount = undefined;\n this.enableOptionSharing = false;\n this.supportsDecimation = false;\n this.$context = undefined;\n this._syncList = [];\n this.datasetElementType = new.target.datasetElementType;\n this.dataElementType = new.target.dataElementType;\n this.initialize();\n }\n initialize() {\n const meta = this._cachedMeta;\n this.configure();\n this.linkScales();\n meta._stacked = isStacked(meta.vScale, meta);\n this.addElements();\n if (this.options.fill && !this.chart.isPluginEnabled('filler')) {\n console.warn(\"Tried to use the 'fill' option without the 'Filler' plugin enabled. Please import and register the 'Filler' plugin and make sure it is not disabled in the options\");\n }\n }\n updateIndex(datasetIndex) {\n if (this.index !== datasetIndex) {\n clearStacks(this._cachedMeta);\n }\n this.index = datasetIndex;\n }\n linkScales() {\n const chart = this.chart;\n const meta = this._cachedMeta;\n const dataset = this.getDataset();\n const chooseId = (axis, x, y, r)=>axis === 'x' ? x : axis === 'r' ? r : y;\n const xid = meta.xAxisID = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.xAxisID, getFirstScaleId(chart, 'x'));\n const yid = meta.yAxisID = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.yAxisID, getFirstScaleId(chart, 'y'));\n const rid = meta.rAxisID = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.rAxisID, getFirstScaleId(chart, 'r'));\n const indexAxis = meta.indexAxis;\n const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid);\n const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid);\n meta.xScale = this.getScaleForId(xid);\n meta.yScale = this.getScaleForId(yid);\n meta.rScale = this.getScaleForId(rid);\n meta.iScale = this.getScaleForId(iid);\n meta.vScale = this.getScaleForId(vid);\n }\n getDataset() {\n return this.chart.data.datasets[this.index];\n }\n getMeta() {\n return this.chart.getDatasetMeta(this.index);\n }\n getScaleForId(scaleID) {\n return this.chart.scales[scaleID];\n }\n _getOtherScale(scale) {\n const meta = this._cachedMeta;\n return scale === meta.iScale ? meta.vScale : meta.iScale;\n }\n reset() {\n this._update('reset');\n }\n _destroy() {\n const meta = this._cachedMeta;\n if (this._data) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.u)(this._data, this);\n }\n if (meta._stacked) {\n clearStacks(meta);\n }\n }\n _dataCheck() {\n const dataset = this.getDataset();\n const data = dataset.data || (dataset.data = []);\n const _data = this._data;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(data)) {\n const meta = this._cachedMeta;\n this._data = convertObjectDataToArray(data, meta);\n } else if (_data !== data) {\n if (_data) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.u)(_data, this);\n const meta = this._cachedMeta;\n clearStacks(meta);\n meta._parsed = [];\n }\n if (data && Object.isExtensible(data)) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.l)(data, this);\n }\n this._syncList = [];\n this._data = data;\n }\n }\n addElements() {\n const meta = this._cachedMeta;\n this._dataCheck();\n if (this.datasetElementType) {\n meta.dataset = new this.datasetElementType();\n }\n }\n buildOrUpdateElements(resetNewElements) {\n const meta = this._cachedMeta;\n const dataset = this.getDataset();\n let stackChanged = false;\n this._dataCheck();\n const oldStacked = meta._stacked;\n meta._stacked = isStacked(meta.vScale, meta);\n if (meta.stack !== dataset.stack) {\n stackChanged = true;\n clearStacks(meta);\n meta.stack = dataset.stack;\n }\n this._resyncElements(resetNewElements);\n if (stackChanged || oldStacked !== meta._stacked) {\n updateStacks(this, meta._parsed);\n meta._stacked = isStacked(meta.vScale, meta);\n }\n }\n configure() {\n const config = this.chart.config;\n const scopeKeys = config.datasetScopeKeys(this._type);\n const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true);\n this.options = config.createResolver(scopes, this.getContext());\n this._parsing = this.options.parsing;\n this._cachedDataOpts = {};\n }\n parse(start, count) {\n const { _cachedMeta: meta , _data: data } = this;\n const { iScale , _stacked } = meta;\n const iAxis = iScale.axis;\n let sorted = start === 0 && count === data.length ? true : meta._sorted;\n let prev = start > 0 && meta._parsed[start - 1];\n let i, cur, parsed;\n if (this._parsing === false) {\n meta._parsed = data;\n meta._sorted = true;\n parsed = data;\n } else {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(data[start])) {\n parsed = this.parseArrayData(meta, data, start, count);\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(data[start])) {\n parsed = this.parseObjectData(meta, data, start, count);\n } else {\n parsed = this.parsePrimitiveData(meta, data, start, count);\n }\n const isNotInOrderComparedToPrev = ()=>cur[iAxis] === null || prev && cur[iAxis] < prev[iAxis];\n for(i = 0; i < count; ++i){\n meta._parsed[i + start] = cur = parsed[i];\n if (sorted) {\n if (isNotInOrderComparedToPrev()) {\n sorted = false;\n }\n prev = cur;\n }\n }\n meta._sorted = sorted;\n }\n if (_stacked) {\n updateStacks(this, parsed);\n }\n }\n parsePrimitiveData(meta, data, start, count) {\n const { iScale , vScale } = meta;\n const iAxis = iScale.axis;\n const vAxis = vScale.axis;\n const labels = iScale.getLabels();\n const singleScale = iScale === vScale;\n const parsed = new Array(count);\n let i, ilen, index;\n for(i = 0, ilen = count; i < ilen; ++i){\n index = i + start;\n parsed[i] = {\n [iAxis]: singleScale || iScale.parse(labels[index], index),\n [vAxis]: vScale.parse(data[index], index)\n };\n }\n return parsed;\n }\n parseArrayData(meta, data, start, count) {\n const { xScale , yScale } = meta;\n const parsed = new Array(count);\n let i, ilen, index, item;\n for(i = 0, ilen = count; i < ilen; ++i){\n index = i + start;\n item = data[index];\n parsed[i] = {\n x: xScale.parse(item[0], index),\n y: yScale.parse(item[1], index)\n };\n }\n return parsed;\n }\n parseObjectData(meta, data, start, count) {\n const { xScale , yScale } = meta;\n const { xAxisKey ='x' , yAxisKey ='y' } = this._parsing;\n const parsed = new Array(count);\n let i, ilen, index, item;\n for(i = 0, ilen = count; i < ilen; ++i){\n index = i + start;\n item = data[index];\n parsed[i] = {\n x: xScale.parse((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, xAxisKey), index),\n y: yScale.parse((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, yAxisKey), index)\n };\n }\n return parsed;\n }\n getParsed(index) {\n return this._cachedMeta._parsed[index];\n }\n getDataElement(index) {\n return this._cachedMeta.data[index];\n }\n applyStack(scale, parsed, mode) {\n const chart = this.chart;\n const meta = this._cachedMeta;\n const value = parsed[scale.axis];\n const stack = {\n keys: getSortedDatasetIndices(chart, true),\n values: parsed._stacks[scale.axis]._visualValues\n };\n return applyStack(stack, value, meta.index, {\n mode\n });\n }\n updateRangeFromParsed(range, scale, parsed, stack) {\n const parsedValue = parsed[scale.axis];\n let value = parsedValue === null ? NaN : parsedValue;\n const values = stack && parsed._stacks[scale.axis];\n if (stack && values) {\n stack.values = values;\n value = applyStack(stack, parsedValue, this._cachedMeta.index);\n }\n range.min = Math.min(range.min, value);\n range.max = Math.max(range.max, value);\n }\n getMinMax(scale, canStack) {\n const meta = this._cachedMeta;\n const _parsed = meta._parsed;\n const sorted = meta._sorted && scale === meta.iScale;\n const ilen = _parsed.length;\n const otherScale = this._getOtherScale(scale);\n const stack = createStack(canStack, meta, this.chart);\n const range = {\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY\n };\n const { min: otherMin , max: otherMax } = getUserBounds(otherScale);\n let i, parsed;\n function _skip() {\n parsed = _parsed[i];\n const otherValue = parsed[otherScale.axis];\n return !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue;\n }\n for(i = 0; i < ilen; ++i){\n if (_skip()) {\n continue;\n }\n this.updateRangeFromParsed(range, scale, parsed, stack);\n if (sorted) {\n break;\n }\n }\n if (sorted) {\n for(i = ilen - 1; i >= 0; --i){\n if (_skip()) {\n continue;\n }\n this.updateRangeFromParsed(range, scale, parsed, stack);\n break;\n }\n }\n return range;\n }\n getAllParsedValues(scale) {\n const parsed = this._cachedMeta._parsed;\n const values = [];\n let i, ilen, value;\n for(i = 0, ilen = parsed.length; i < ilen; ++i){\n value = parsed[i][scale.axis];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) {\n values.push(value);\n }\n }\n return values;\n }\n getMaxOverflow() {\n return false;\n }\n getLabelAndValue(index) {\n const meta = this._cachedMeta;\n const iScale = meta.iScale;\n const vScale = meta.vScale;\n const parsed = this.getParsed(index);\n return {\n label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '',\n value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : ''\n };\n }\n _update(mode) {\n const meta = this._cachedMeta;\n this.update(mode || 'default');\n meta._clip = toClip((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow())));\n }\n update(mode) {}\n draw() {\n const ctx = this._ctx;\n const chart = this.chart;\n const meta = this._cachedMeta;\n const elements = meta.data || [];\n const area = chart.chartArea;\n const active = [];\n const start = this._drawStart || 0;\n const count = this._drawCount || elements.length - start;\n const drawActiveElementsOnTop = this.options.drawActiveElementsOnTop;\n let i;\n if (meta.dataset) {\n meta.dataset.draw(ctx, area, start, count);\n }\n for(i = start; i < start + count; ++i){\n const element = elements[i];\n if (element.hidden) {\n continue;\n }\n if (element.active && drawActiveElementsOnTop) {\n active.push(element);\n } else {\n element.draw(ctx, area);\n }\n }\n for(i = 0; i < active.length; ++i){\n active[i].draw(ctx, area);\n }\n }\n getStyle(index, active) {\n const mode = active ? 'active' : 'default';\n return index === undefined && this._cachedMeta.dataset ? this.resolveDatasetElementOptions(mode) : this.resolveDataElementOptions(index || 0, mode);\n }\n getContext(index, active, mode) {\n const dataset = this.getDataset();\n let context;\n if (index >= 0 && index < this._cachedMeta.data.length) {\n const element = this._cachedMeta.data[index];\n context = element.$context || (element.$context = createDataContext(this.getContext(), index, element));\n context.parsed = this.getParsed(index);\n context.raw = dataset.data[index];\n context.index = context.dataIndex = index;\n } else {\n context = this.$context || (this.$context = createDatasetContext(this.chart.getContext(), this.index));\n context.dataset = dataset;\n context.index = context.datasetIndex = this.index;\n }\n context.active = !!active;\n context.mode = mode;\n return context;\n }\n resolveDatasetElementOptions(mode) {\n return this._resolveElementOptions(this.datasetElementType.id, mode);\n }\n resolveDataElementOptions(index, mode) {\n return this._resolveElementOptions(this.dataElementType.id, mode, index);\n }\n _resolveElementOptions(elementType, mode = 'default', index) {\n const active = mode === 'active';\n const cache = this._cachedDataOpts;\n const cacheKey = elementType + '-' + mode;\n const cached = cache[cacheKey];\n const sharing = this.enableOptionSharing && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(index);\n if (cached) {\n return cloneIfNotShared(cached, sharing);\n }\n const config = this.chart.config;\n const scopeKeys = config.datasetElementScopeKeys(this._type, elementType);\n const prefixes = active ? [\n `${elementType}Hover`,\n 'hover',\n elementType,\n ''\n ] : [\n elementType,\n ''\n ];\n const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);\n const names = Object.keys(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.elements[elementType]);\n const context = ()=>this.getContext(index, active, mode);\n const values = config.resolveNamedOptions(scopes, names, context, prefixes);\n if (values.$shared) {\n values.$shared = sharing;\n cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing));\n }\n return values;\n }\n _resolveAnimations(index, transition, active) {\n const chart = this.chart;\n const cache = this._cachedDataOpts;\n const cacheKey = `animation-${transition}`;\n const cached = cache[cacheKey];\n if (cached) {\n return cached;\n }\n let options;\n if (chart.options.animation !== false) {\n const config = this.chart.config;\n const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition);\n const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);\n options = config.createResolver(scopes, this.getContext(index, active, transition));\n }\n const animations = new Animations(chart, options && options.animations);\n if (options && options._cacheable) {\n cache[cacheKey] = Object.freeze(animations);\n }\n return animations;\n }\n getSharedOptions(options) {\n if (!options.$shared) {\n return;\n }\n return this._sharedOptions || (this._sharedOptions = Object.assign({}, options));\n }\n includeOptions(mode, sharedOptions) {\n return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled;\n }\n _getSharedOptions(start, mode) {\n const firstOpts = this.resolveDataElementOptions(start, mode);\n const previouslySharedOptions = this._sharedOptions;\n const sharedOptions = this.getSharedOptions(firstOpts);\n const includeOptions = this.includeOptions(mode, sharedOptions) || sharedOptions !== previouslySharedOptions;\n this.updateSharedOptions(sharedOptions, mode, firstOpts);\n return {\n sharedOptions,\n includeOptions\n };\n }\n updateElement(element, index, properties, mode) {\n if (isDirectUpdateMode(mode)) {\n Object.assign(element, properties);\n } else {\n this._resolveAnimations(index, mode).update(element, properties);\n }\n }\n updateSharedOptions(sharedOptions, mode, newOptions) {\n if (sharedOptions && !isDirectUpdateMode(mode)) {\n this._resolveAnimations(undefined, mode).update(sharedOptions, newOptions);\n }\n }\n _setStyle(element, index, mode, active) {\n element.active = active;\n const options = this.getStyle(index, active);\n this._resolveAnimations(index, mode, active).update(element, {\n options: !active && this.getSharedOptions(options) || options\n });\n }\n removeHoverStyle(element, datasetIndex, index) {\n this._setStyle(element, index, 'active', false);\n }\n setHoverStyle(element, datasetIndex, index) {\n this._setStyle(element, index, 'active', true);\n }\n _removeDatasetHoverStyle() {\n const element = this._cachedMeta.dataset;\n if (element) {\n this._setStyle(element, undefined, 'active', false);\n }\n }\n _setDatasetHoverStyle() {\n const element = this._cachedMeta.dataset;\n if (element) {\n this._setStyle(element, undefined, 'active', true);\n }\n }\n _resyncElements(resetNewElements) {\n const data = this._data;\n const elements = this._cachedMeta.data;\n for (const [method, arg1, arg2] of this._syncList){\n this[method](arg1, arg2);\n }\n this._syncList = [];\n const numMeta = elements.length;\n const numData = data.length;\n const count = Math.min(numData, numMeta);\n if (count) {\n this.parse(0, count);\n }\n if (numData > numMeta) {\n this._insertElements(numMeta, numData - numMeta, resetNewElements);\n } else if (numData < numMeta) {\n this._removeElements(numData, numMeta - numData);\n }\n }\n _insertElements(start, count, resetNewElements = true) {\n const meta = this._cachedMeta;\n const data = meta.data;\n const end = start + count;\n let i;\n const move = (arr)=>{\n arr.length += count;\n for(i = arr.length - 1; i >= end; i--){\n arr[i] = arr[i - count];\n }\n };\n move(data);\n for(i = start; i < end; ++i){\n data[i] = new this.dataElementType();\n }\n if (this._parsing) {\n move(meta._parsed);\n }\n this.parse(start, count);\n if (resetNewElements) {\n this.updateElements(data, start, count, 'reset');\n }\n }\n updateElements(element, start, count, mode) {}\n _removeElements(start, count) {\n const meta = this._cachedMeta;\n if (this._parsing) {\n const removed = meta._parsed.splice(start, count);\n if (meta._stacked) {\n clearStacks(meta, removed);\n }\n }\n meta.data.splice(start, count);\n }\n _sync(args) {\n if (this._parsing) {\n this._syncList.push(args);\n } else {\n const [method, arg1, arg2] = args;\n this[method](arg1, arg2);\n }\n this.chart._dataChanges.push([\n this.index,\n ...args\n ]);\n }\n _onDataPush() {\n const count = arguments.length;\n this._sync([\n '_insertElements',\n this.getDataset().data.length - count,\n count\n ]);\n }\n _onDataPop() {\n this._sync([\n '_removeElements',\n this._cachedMeta.data.length - 1,\n 1\n ]);\n }\n _onDataShift() {\n this._sync([\n '_removeElements',\n 0,\n 1\n ]);\n }\n _onDataSplice(start, count) {\n if (count) {\n this._sync([\n '_removeElements',\n start,\n count\n ]);\n }\n const newCount = arguments.length - 2;\n if (newCount) {\n this._sync([\n '_insertElements',\n start,\n newCount\n ]);\n }\n }\n _onDataUnshift() {\n this._sync([\n '_insertElements',\n 0,\n arguments.length\n ]);\n }\n}\n\nfunction getAllScaleValues(scale, type) {\n if (!scale._cache.$bar) {\n const visibleMetas = scale.getMatchingVisibleMetas(type);\n let values = [];\n for(let i = 0, ilen = visibleMetas.length; i < ilen; i++){\n values = values.concat(visibleMetas[i].controller.getAllParsedValues(scale));\n }\n scale._cache.$bar = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort((a, b)=>a - b));\n }\n return scale._cache.$bar;\n}\n function computeMinSampleSize(meta) {\n const scale = meta.iScale;\n const values = getAllScaleValues(scale, meta.type);\n let min = scale._length;\n let i, ilen, curr, prev;\n const updateMinAndPrev = ()=>{\n if (curr === 32767 || curr === -32768) {\n return;\n }\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(prev)) {\n min = Math.min(min, Math.abs(curr - prev) || min);\n }\n prev = curr;\n };\n for(i = 0, ilen = values.length; i < ilen; ++i){\n curr = scale.getPixelForValue(values[i]);\n updateMinAndPrev();\n }\n prev = undefined;\n for(i = 0, ilen = scale.ticks.length; i < ilen; ++i){\n curr = scale.getPixelForTick(i);\n updateMinAndPrev();\n }\n return min;\n}\n function computeFitCategoryTraits(index, ruler, options, stackCount) {\n const thickness = options.barThickness;\n let size, ratio;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(thickness)) {\n size = ruler.min * options.categoryPercentage;\n ratio = options.barPercentage;\n } else {\n size = thickness * stackCount;\n ratio = 1;\n }\n return {\n chunk: size / stackCount,\n ratio,\n start: ruler.pixels[index] - size / 2\n };\n}\n function computeFlexCategoryTraits(index, ruler, options, stackCount) {\n const pixels = ruler.pixels;\n const curr = pixels[index];\n let prev = index > 0 ? pixels[index - 1] : null;\n let next = index < pixels.length - 1 ? pixels[index + 1] : null;\n const percent = options.categoryPercentage;\n if (prev === null) {\n prev = curr - (next === null ? ruler.end - ruler.start : next - curr);\n }\n if (next === null) {\n next = curr + curr - prev;\n }\n const start = curr - (curr - Math.min(prev, next)) / 2 * percent;\n const size = Math.abs(next - prev) / 2 * percent;\n return {\n chunk: size / stackCount,\n ratio: options.barPercentage,\n start\n };\n}\nfunction parseFloatBar(entry, item, vScale, i) {\n const startValue = vScale.parse(entry[0], i);\n const endValue = vScale.parse(entry[1], i);\n const min = Math.min(startValue, endValue);\n const max = Math.max(startValue, endValue);\n let barStart = min;\n let barEnd = max;\n if (Math.abs(min) > Math.abs(max)) {\n barStart = max;\n barEnd = min;\n }\n item[vScale.axis] = barEnd;\n item._custom = {\n barStart,\n barEnd,\n start: startValue,\n end: endValue,\n min,\n max\n };\n}\nfunction parseValue(entry, item, vScale, i) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(entry)) {\n parseFloatBar(entry, item, vScale, i);\n } else {\n item[vScale.axis] = vScale.parse(entry, i);\n }\n return item;\n}\nfunction parseArrayOrPrimitive(meta, data, start, count) {\n const iScale = meta.iScale;\n const vScale = meta.vScale;\n const labels = iScale.getLabels();\n const singleScale = iScale === vScale;\n const parsed = [];\n let i, ilen, item, entry;\n for(i = start, ilen = start + count; i < ilen; ++i){\n entry = data[i];\n item = {};\n item[iScale.axis] = singleScale || iScale.parse(labels[i], i);\n parsed.push(parseValue(entry, item, vScale, i));\n }\n return parsed;\n}\nfunction isFloatBar(custom) {\n return custom && custom.barStart !== undefined && custom.barEnd !== undefined;\n}\nfunction barSign(size, vScale, actualBase) {\n if (size !== 0) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(size);\n }\n return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);\n}\nfunction borderProps(properties) {\n let reverse, start, end, top, bottom;\n if (properties.horizontal) {\n reverse = properties.base > properties.x;\n start = 'left';\n end = 'right';\n } else {\n reverse = properties.base < properties.y;\n start = 'bottom';\n end = 'top';\n }\n if (reverse) {\n top = 'end';\n bottom = 'start';\n } else {\n top = 'start';\n bottom = 'end';\n }\n return {\n start,\n end,\n reverse,\n top,\n bottom\n };\n}\nfunction setBorderSkipped(properties, options, stack, index) {\n let edge = options.borderSkipped;\n const res = {};\n if (!edge) {\n properties.borderSkipped = res;\n return;\n }\n if (edge === true) {\n properties.borderSkipped = {\n top: true,\n right: true,\n bottom: true,\n left: true\n };\n return;\n }\n const { start , end , reverse , top , bottom } = borderProps(properties);\n if (edge === 'middle' && stack) {\n properties.enableBorderRadius = true;\n if ((stack._top || 0) === index) {\n edge = top;\n } else if ((stack._bottom || 0) === index) {\n edge = bottom;\n } else {\n res[parseEdge(bottom, start, end, reverse)] = true;\n edge = top;\n }\n }\n res[parseEdge(edge, start, end, reverse)] = true;\n properties.borderSkipped = res;\n}\nfunction parseEdge(edge, a, b, reverse) {\n if (reverse) {\n edge = swap(edge, a, b);\n edge = startEnd(edge, b, a);\n } else {\n edge = startEnd(edge, a, b);\n }\n return edge;\n}\nfunction swap(orig, v1, v2) {\n return orig === v1 ? v2 : orig === v2 ? v1 : orig;\n}\nfunction startEnd(v, start, end) {\n return v === 'start' ? start : v === 'end' ? end : v;\n}\nfunction setInflateAmount(properties, { inflateAmount }, ratio) {\n properties.inflateAmount = inflateAmount === 'auto' ? ratio === 1 ? 0.33 : 0 : inflateAmount;\n}\nclass BarController extends DatasetController {\n static id = 'bar';\n static defaults = {\n datasetElementType: false,\n dataElementType: 'bar',\n categoryPercentage: 0.8,\n barPercentage: 0.9,\n grouped: true,\n animations: {\n numbers: {\n type: 'number',\n properties: [\n 'x',\n 'y',\n 'base',\n 'width',\n 'height'\n ]\n }\n }\n };\n static overrides = {\n scales: {\n _index_: {\n type: 'category',\n offset: true,\n grid: {\n offset: true\n }\n },\n _value_: {\n type: 'linear',\n beginAtZero: true\n }\n }\n };\n parsePrimitiveData(meta, data, start, count) {\n return parseArrayOrPrimitive(meta, data, start, count);\n }\n parseArrayData(meta, data, start, count) {\n return parseArrayOrPrimitive(meta, data, start, count);\n }\n parseObjectData(meta, data, start, count) {\n const { iScale , vScale } = meta;\n const { xAxisKey ='x' , yAxisKey ='y' } = this._parsing;\n const iAxisKey = iScale.axis === 'x' ? xAxisKey : yAxisKey;\n const vAxisKey = vScale.axis === 'x' ? xAxisKey : yAxisKey;\n const parsed = [];\n let i, ilen, item, obj;\n for(i = start, ilen = start + count; i < ilen; ++i){\n obj = data[i];\n item = {};\n item[iScale.axis] = iScale.parse((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, iAxisKey), i);\n parsed.push(parseValue((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, vAxisKey), item, vScale, i));\n }\n return parsed;\n }\n updateRangeFromParsed(range, scale, parsed, stack) {\n super.updateRangeFromParsed(range, scale, parsed, stack);\n const custom = parsed._custom;\n if (custom && scale === this._cachedMeta.vScale) {\n range.min = Math.min(range.min, custom.min);\n range.max = Math.max(range.max, custom.max);\n }\n }\n getMaxOverflow() {\n return 0;\n }\n getLabelAndValue(index) {\n const meta = this._cachedMeta;\n const { iScale , vScale } = meta;\n const parsed = this.getParsed(index);\n const custom = parsed._custom;\n const value = isFloatBar(custom) ? '[' + custom.start + ', ' + custom.end + ']' : '' + vScale.getLabelForValue(parsed[vScale.axis]);\n return {\n label: '' + iScale.getLabelForValue(parsed[iScale.axis]),\n value\n };\n }\n initialize() {\n this.enableOptionSharing = true;\n super.initialize();\n const meta = this._cachedMeta;\n meta.stack = this.getDataset().stack;\n }\n update(mode) {\n const meta = this._cachedMeta;\n this.updateElements(meta.data, 0, meta.data.length, mode);\n }\n updateElements(bars, start, count, mode) {\n const reset = mode === 'reset';\n const { index , _cachedMeta: { vScale } } = this;\n const base = vScale.getBasePixel();\n const horizontal = vScale.isHorizontal();\n const ruler = this._getRuler();\n const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);\n for(let i = start; i < start + count; i++){\n const parsed = this.getParsed(i);\n const vpixels = reset || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vScale.axis]) ? {\n base,\n head: base\n } : this._calculateBarValuePixels(i);\n const ipixels = this._calculateBarIndexPixels(i, ruler);\n const stack = (parsed._stacks || {})[vScale.axis];\n const properties = {\n horizontal,\n base: vpixels.base,\n enableBorderRadius: !stack || isFloatBar(parsed._custom) || index === stack._top || index === stack._bottom,\n x: horizontal ? vpixels.head : ipixels.center,\n y: horizontal ? ipixels.center : vpixels.head,\n height: horizontal ? ipixels.size : Math.abs(vpixels.size),\n width: horizontal ? Math.abs(vpixels.size) : ipixels.size\n };\n if (includeOptions) {\n properties.options = sharedOptions || this.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);\n }\n const options = properties.options || bars[i].options;\n setBorderSkipped(properties, options, stack, index);\n setInflateAmount(properties, options, ruler.ratio);\n this.updateElement(bars[i], i, properties, mode);\n }\n }\n _getStacks(last, dataIndex) {\n const { iScale } = this._cachedMeta;\n const metasets = iScale.getMatchingVisibleMetas(this._type).filter((meta)=>meta.controller.options.grouped);\n const stacked = iScale.options.stacked;\n const stacks = [];\n const currentParsed = this._cachedMeta.controller.getParsed(dataIndex);\n const iScaleValue = currentParsed && currentParsed[iScale.axis];\n const skipNull = (meta)=>{\n const parsed = meta._parsed.find((item)=>item[iScale.axis] === iScaleValue);\n const val = parsed && parsed[meta.vScale.axis];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(val) || isNaN(val)) {\n return true;\n }\n };\n for (const meta of metasets){\n if (dataIndex !== undefined && skipNull(meta)) {\n continue;\n }\n if (stacked === false || stacks.indexOf(meta.stack) === -1 || stacked === undefined && meta.stack === undefined) {\n stacks.push(meta.stack);\n }\n if (meta.index === last) {\n break;\n }\n }\n if (!stacks.length) {\n stacks.push(undefined);\n }\n return stacks;\n }\n _getStackCount(index) {\n return this._getStacks(undefined, index).length;\n }\n _getAxisCount() {\n return this._getAxis().length;\n }\n getFirstScaleIdForIndexAxis() {\n const scales = this.chart.scales;\n const indexScaleId = this.chart.options.indexAxis;\n return Object.keys(scales).filter((key)=>scales[key].axis === indexScaleId).shift();\n }\n _getAxis() {\n const axis = {};\n const firstScaleAxisId = this.getFirstScaleIdForIndexAxis();\n for (const dataset of this.chart.data.datasets){\n axis[(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.chart.options.indexAxis === 'x' ? dataset.xAxisID : dataset.yAxisID, firstScaleAxisId)] = true;\n }\n return Object.keys(axis);\n }\n _getStackIndex(datasetIndex, name, dataIndex) {\n const stacks = this._getStacks(datasetIndex, dataIndex);\n const index = name !== undefined ? stacks.indexOf(name) : -1;\n return index === -1 ? stacks.length - 1 : index;\n }\n _getRuler() {\n const opts = this.options;\n const meta = this._cachedMeta;\n const iScale = meta.iScale;\n const pixels = [];\n let i, ilen;\n for(i = 0, ilen = meta.data.length; i < ilen; ++i){\n pixels.push(iScale.getPixelForValue(this.getParsed(i)[iScale.axis], i));\n }\n const barThickness = opts.barThickness;\n const min = barThickness || computeMinSampleSize(meta);\n return {\n min,\n pixels,\n start: iScale._startPixel,\n end: iScale._endPixel,\n stackCount: this._getStackCount(),\n scale: iScale,\n grouped: opts.grouped,\n ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage\n };\n }\n _calculateBarValuePixels(index) {\n const { _cachedMeta: { vScale , _stacked , index: datasetIndex } , options: { base: baseValue , minBarLength } } = this;\n const actualBase = baseValue || 0;\n const parsed = this.getParsed(index);\n const custom = parsed._custom;\n const floating = isFloatBar(custom);\n let value = parsed[vScale.axis];\n let start = 0;\n let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value;\n let head, size;\n if (length !== value) {\n start = length - value;\n length = value;\n }\n if (floating) {\n value = custom.barStart;\n length = custom.barEnd - custom.barStart;\n if (value !== 0 && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) !== (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(custom.barEnd)) {\n start = 0;\n }\n start += value;\n }\n const startValue = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(baseValue) && !floating ? baseValue : start;\n let base = vScale.getPixelForValue(startValue);\n if (this.chart.getDataVisibility(index)) {\n head = vScale.getPixelForValue(start + length);\n } else {\n head = base;\n }\n size = head - base;\n if (Math.abs(size) < minBarLength) {\n size = barSign(size, vScale, actualBase) * minBarLength;\n if (value === actualBase) {\n base -= size / 2;\n }\n const startPixel = vScale.getPixelForDecimal(0);\n const endPixel = vScale.getPixelForDecimal(1);\n const min = Math.min(startPixel, endPixel);\n const max = Math.max(startPixel, endPixel);\n base = Math.max(Math.min(base, max), min);\n head = base + size;\n if (_stacked && !floating) {\n parsed._stacks[vScale.axis]._visualValues[datasetIndex] = vScale.getValueForPixel(head) - vScale.getValueForPixel(base);\n }\n }\n if (base === vScale.getPixelForValue(actualBase)) {\n const halfGrid = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(size) * vScale.getLineWidthForValue(actualBase) / 2;\n base += halfGrid;\n size -= halfGrid;\n }\n return {\n size,\n base,\n head,\n center: head + size / 2\n };\n }\n _calculateBarIndexPixels(index, ruler) {\n const scale = ruler.scale;\n const options = this.options;\n const skipNull = options.skipNull;\n const maxBarThickness = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.maxBarThickness, Infinity);\n let center, size;\n const axisCount = this._getAxisCount();\n if (ruler.grouped) {\n const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;\n const range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options, stackCount * axisCount) : computeFitCategoryTraits(index, ruler, options, stackCount * axisCount);\n const axisID = this.chart.options.indexAxis === 'x' ? this.getDataset().xAxisID : this.getDataset().yAxisID;\n const axisNumber = this._getAxis().indexOf((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(axisID, this.getFirstScaleIdForIndexAxis()));\n const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined) + axisNumber;\n center = range.start + range.chunk * stackIndex + range.chunk / 2;\n size = Math.min(maxBarThickness, range.chunk * range.ratio);\n } else {\n center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index);\n size = Math.min(maxBarThickness, ruler.min * ruler.ratio);\n }\n return {\n base: center - size / 2,\n head: center + size / 2,\n center,\n size\n };\n }\n draw() {\n const meta = this._cachedMeta;\n const vScale = meta.vScale;\n const rects = meta.data;\n const ilen = rects.length;\n let i = 0;\n for(; i < ilen; ++i){\n if (this.getParsed(i)[vScale.axis] !== null && !rects[i].hidden) {\n rects[i].draw(this._ctx);\n }\n }\n }\n}\n\nclass BubbleController extends DatasetController {\n static id = 'bubble';\n static defaults = {\n datasetElementType: false,\n dataElementType: 'point',\n animations: {\n numbers: {\n type: 'number',\n properties: [\n 'x',\n 'y',\n 'borderWidth',\n 'radius'\n ]\n }\n }\n };\n static overrides = {\n scales: {\n x: {\n type: 'linear'\n },\n y: {\n type: 'linear'\n }\n }\n };\n initialize() {\n this.enableOptionSharing = true;\n super.initialize();\n }\n parsePrimitiveData(meta, data, start, count) {\n const parsed = super.parsePrimitiveData(meta, data, start, count);\n for(let i = 0; i < parsed.length; i++){\n parsed[i]._custom = this.resolveDataElementOptions(i + start).radius;\n }\n return parsed;\n }\n parseArrayData(meta, data, start, count) {\n const parsed = super.parseArrayData(meta, data, start, count);\n for(let i = 0; i < parsed.length; i++){\n const item = data[start + i];\n parsed[i]._custom = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(item[2], this.resolveDataElementOptions(i + start).radius);\n }\n return parsed;\n }\n parseObjectData(meta, data, start, count) {\n const parsed = super.parseObjectData(meta, data, start, count);\n for(let i = 0; i < parsed.length; i++){\n const item = data[start + i];\n parsed[i]._custom = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(item && item.r && +item.r, this.resolveDataElementOptions(i + start).radius);\n }\n return parsed;\n }\n getMaxOverflow() {\n const data = this._cachedMeta.data;\n let max = 0;\n for(let i = data.length - 1; i >= 0; --i){\n max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2);\n }\n return max > 0 && max;\n }\n getLabelAndValue(index) {\n const meta = this._cachedMeta;\n const labels = this.chart.data.labels || [];\n const { xScale , yScale } = meta;\n const parsed = this.getParsed(index);\n const x = xScale.getLabelForValue(parsed.x);\n const y = yScale.getLabelForValue(parsed.y);\n const r = parsed._custom;\n return {\n label: labels[index] || '',\n value: '(' + x + ', ' + y + (r ? ', ' + r : '') + ')'\n };\n }\n update(mode) {\n const points = this._cachedMeta.data;\n this.updateElements(points, 0, points.length, mode);\n }\n updateElements(points, start, count, mode) {\n const reset = mode === 'reset';\n const { iScale , vScale } = this._cachedMeta;\n const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);\n const iAxis = iScale.axis;\n const vAxis = vScale.axis;\n for(let i = start; i < start + count; i++){\n const point = points[i];\n const parsed = !reset && this.getParsed(i);\n const properties = {};\n const iPixel = properties[iAxis] = reset ? iScale.getPixelForDecimal(0.5) : iScale.getPixelForValue(parsed[iAxis]);\n const vPixel = properties[vAxis] = reset ? vScale.getBasePixel() : vScale.getPixelForValue(parsed[vAxis]);\n properties.skip = isNaN(iPixel) || isNaN(vPixel);\n if (includeOptions) {\n properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n if (reset) {\n properties.options.radius = 0;\n }\n }\n this.updateElement(point, i, properties, mode);\n }\n }\n resolveDataElementOptions(index, mode) {\n const parsed = this.getParsed(index);\n let values = super.resolveDataElementOptions(index, mode);\n if (values.$shared) {\n values = Object.assign({}, values, {\n $shared: false\n });\n }\n const radius = values.radius;\n if (mode !== 'active') {\n values.radius = 0;\n }\n values.radius += (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(parsed && parsed._custom, radius);\n return values;\n }\n}\n\nfunction getRatioAndOffset(rotation, circumference, cutout) {\n let ratioX = 1;\n let ratioY = 1;\n let offsetX = 0;\n let offsetY = 0;\n if (circumference < _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T) {\n const startAngle = rotation;\n const endAngle = startAngle + circumference;\n const startX = Math.cos(startAngle);\n const startY = Math.sin(startAngle);\n const endX = Math.cos(endAngle);\n const endY = Math.sin(endAngle);\n const calcMax = (angle, a, b)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle, true) ? 1 : Math.max(a, a * cutout, b, b * cutout);\n const calcMin = (angle, a, b)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle, true) ? -1 : Math.min(a, a * cutout, b, b * cutout);\n const maxX = calcMax(0, startX, endX);\n const maxY = calcMax(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY);\n const minX = calcMin(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P, startX, endX);\n const minY = calcMin(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY);\n ratioX = (maxX - minX) / 2;\n ratioY = (maxY - minY) / 2;\n offsetX = -(maxX + minX) / 2;\n offsetY = -(maxY + minY) / 2;\n }\n return {\n ratioX,\n ratioY,\n offsetX,\n offsetY\n };\n}\nclass DoughnutController extends DatasetController {\n static id = 'doughnut';\n static defaults = {\n datasetElementType: false,\n dataElementType: 'arc',\n animation: {\n animateRotate: true,\n animateScale: false\n },\n animations: {\n numbers: {\n type: 'number',\n properties: [\n 'circumference',\n 'endAngle',\n 'innerRadius',\n 'outerRadius',\n 'startAngle',\n 'x',\n 'y',\n 'offset',\n 'borderWidth',\n 'spacing'\n ]\n }\n },\n cutout: '50%',\n rotation: 0,\n circumference: 360,\n radius: '100%',\n spacing: 0,\n indexAxis: 'r'\n };\n static descriptors = {\n _scriptable: (name)=>name !== 'spacing',\n _indexable: (name)=>name !== 'spacing' && !name.startsWith('borderDash') && !name.startsWith('hoverBorderDash')\n };\n static overrides = {\n aspectRatio: 1,\n plugins: {\n legend: {\n labels: {\n generateLabels (chart) {\n const data = chart.data;\n if (data.labels.length && data.datasets.length) {\n const { labels: { pointStyle , color } } = chart.legend.options;\n return data.labels.map((label, i)=>{\n const meta = chart.getDatasetMeta(0);\n const style = meta.controller.getStyle(i);\n return {\n text: label,\n fillStyle: style.backgroundColor,\n strokeStyle: style.borderColor,\n fontColor: color,\n lineWidth: style.borderWidth,\n pointStyle: pointStyle,\n hidden: !chart.getDataVisibility(i),\n index: i\n };\n });\n }\n return [];\n }\n },\n onClick (e, legendItem, legend) {\n legend.chart.toggleDataVisibility(legendItem.index);\n legend.chart.update();\n }\n }\n }\n };\n constructor(chart, datasetIndex){\n super(chart, datasetIndex);\n this.enableOptionSharing = true;\n this.innerRadius = undefined;\n this.outerRadius = undefined;\n this.offsetX = undefined;\n this.offsetY = undefined;\n }\n linkScales() {}\n parse(start, count) {\n const data = this.getDataset().data;\n const meta = this._cachedMeta;\n if (this._parsing === false) {\n meta._parsed = data;\n } else {\n let getter = (i)=>+data[i];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(data[start])) {\n const { key ='value' } = this._parsing;\n getter = (i)=>+(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(data[i], key);\n }\n let i, ilen;\n for(i = start, ilen = start + count; i < ilen; ++i){\n meta._parsed[i] = getter(i);\n }\n }\n }\n _getRotation() {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.rotation - 90);\n }\n _getCircumference() {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.circumference);\n }\n _getRotationExtents() {\n let min = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T;\n let max = -_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T;\n for(let i = 0; i < this.chart.data.datasets.length; ++i){\n if (this.chart.isDatasetVisible(i) && this.chart.getDatasetMeta(i).type === this._type) {\n const controller = this.chart.getDatasetMeta(i).controller;\n const rotation = controller._getRotation();\n const circumference = controller._getCircumference();\n min = Math.min(min, rotation);\n max = Math.max(max, rotation + circumference);\n }\n }\n return {\n rotation: min,\n circumference: max - min\n };\n }\n update(mode) {\n const chart = this.chart;\n const { chartArea } = chart;\n const meta = this._cachedMeta;\n const arcs = meta.data;\n const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing;\n const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0);\n const cutout = Math.min((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.m)(this.options.cutout, maxSize), 1);\n const chartWeight = this._getRingWeight(this.index);\n const { circumference , rotation } = this._getRotationExtents();\n const { ratioX , ratioY , offsetX , offsetY } = getRatioAndOffset(rotation, circumference, cutout);\n const maxWidth = (chartArea.width - spacing) / ratioX;\n const maxHeight = (chartArea.height - spacing) / ratioY;\n const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);\n const outerRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.n)(this.options.radius, maxRadius);\n const innerRadius = Math.max(outerRadius * cutout, 0);\n const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal();\n this.offsetX = offsetX * outerRadius;\n this.offsetY = offsetY * outerRadius;\n meta.total = this.calculateTotal();\n this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index);\n this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0);\n this.updateElements(arcs, 0, arcs.length, mode);\n }\n _circumference(i, reset) {\n const opts = this.options;\n const meta = this._cachedMeta;\n const circumference = this._getCircumference();\n if (reset && opts.animation.animateRotate || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) {\n return 0;\n }\n return this.calculateCircumference(meta._parsed[i] * circumference / _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);\n }\n updateElements(arcs, start, count, mode) {\n const reset = mode === 'reset';\n const chart = this.chart;\n const chartArea = chart.chartArea;\n const opts = chart.options;\n const animationOpts = opts.animation;\n const centerX = (chartArea.left + chartArea.right) / 2;\n const centerY = (chartArea.top + chartArea.bottom) / 2;\n const animateScale = reset && animationOpts.animateScale;\n const innerRadius = animateScale ? 0 : this.innerRadius;\n const outerRadius = animateScale ? 0 : this.outerRadius;\n const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);\n let startAngle = this._getRotation();\n let i;\n for(i = 0; i < start; ++i){\n startAngle += this._circumference(i, reset);\n }\n for(i = start; i < start + count; ++i){\n const circumference = this._circumference(i, reset);\n const arc = arcs[i];\n const properties = {\n x: centerX + this.offsetX,\n y: centerY + this.offsetY,\n startAngle,\n endAngle: startAngle + circumference,\n circumference,\n outerRadius,\n innerRadius\n };\n if (includeOptions) {\n properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? 'active' : mode);\n }\n startAngle += circumference;\n this.updateElement(arc, i, properties, mode);\n }\n }\n calculateTotal() {\n const meta = this._cachedMeta;\n const metaData = meta.data;\n let total = 0;\n let i;\n for(i = 0; i < metaData.length; i++){\n const value = meta._parsed[i];\n if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) {\n total += Math.abs(value);\n }\n }\n return total;\n }\n calculateCircumference(value) {\n const total = this._cachedMeta.total;\n if (total > 0 && !isNaN(value)) {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T * (Math.abs(value) / total);\n }\n return 0;\n }\n getLabelAndValue(index) {\n const meta = this._cachedMeta;\n const chart = this.chart;\n const labels = chart.data.labels || [];\n const value = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(meta._parsed[index], chart.options.locale);\n return {\n label: labels[index] || '',\n value\n };\n }\n getMaxBorderWidth(arcs) {\n let max = 0;\n const chart = this.chart;\n let i, ilen, meta, controller, options;\n if (!arcs) {\n for(i = 0, ilen = chart.data.datasets.length; i < ilen; ++i){\n if (chart.isDatasetVisible(i)) {\n meta = chart.getDatasetMeta(i);\n arcs = meta.data;\n controller = meta.controller;\n break;\n }\n }\n }\n if (!arcs) {\n return 0;\n }\n for(i = 0, ilen = arcs.length; i < ilen; ++i){\n options = controller.resolveDataElementOptions(i);\n if (options.borderAlign !== 'inner') {\n max = Math.max(max, options.borderWidth || 0, options.hoverBorderWidth || 0);\n }\n }\n return max;\n }\n getMaxOffset(arcs) {\n let max = 0;\n for(let i = 0, ilen = arcs.length; i < ilen; ++i){\n const options = this.resolveDataElementOptions(i);\n max = Math.max(max, options.offset || 0, options.hoverOffset || 0);\n }\n return max;\n }\n _getRingWeightOffset(datasetIndex) {\n let ringWeightOffset = 0;\n for(let i = 0; i < datasetIndex; ++i){\n if (this.chart.isDatasetVisible(i)) {\n ringWeightOffset += this._getRingWeight(i);\n }\n }\n return ringWeightOffset;\n }\n _getRingWeight(datasetIndex) {\n return Math.max((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.chart.data.datasets[datasetIndex].weight, 1), 0);\n }\n _getVisibleDatasetWeightTotal() {\n return this._getRingWeightOffset(this.chart.data.datasets.length) || 1;\n }\n}\n\nclass LineController extends DatasetController {\n static id = 'line';\n static defaults = {\n datasetElementType: 'line',\n dataElementType: 'point',\n showLine: true,\n spanGaps: false\n };\n static overrides = {\n scales: {\n _index_: {\n type: 'category'\n },\n _value_: {\n type: 'linear'\n }\n }\n };\n initialize() {\n this.enableOptionSharing = true;\n this.supportsDecimation = true;\n super.initialize();\n }\n update(mode) {\n const meta = this._cachedMeta;\n const { dataset: line , data: points = [] , _dataset } = meta;\n const animationsDisabled = this.chart._animationsDisabled;\n let { start , count } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.q)(meta, points, animationsDisabled);\n this._drawStart = start;\n this._drawCount = count;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.w)(meta)) {\n start = 0;\n count = points.length;\n }\n line._chart = this.chart;\n line._datasetIndex = this.index;\n line._decimated = !!_dataset._decimated;\n line.points = points;\n const options = this.resolveDatasetElementOptions(mode);\n if (!this.options.showLine) {\n options.borderWidth = 0;\n }\n options.segment = this.options.segment;\n this.updateElement(line, undefined, {\n animated: !animationsDisabled,\n options\n }, mode);\n this.updateElements(points, start, count, mode);\n }\n updateElements(points, start, count, mode) {\n const reset = mode === 'reset';\n const { iScale , vScale , _stacked , _dataset } = this._cachedMeta;\n const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);\n const iAxis = iScale.axis;\n const vAxis = vScale.axis;\n const { spanGaps , segment } = this.options;\n const maxGapLength = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;\n const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';\n const end = start + count;\n const pointsCount = points.length;\n let prevParsed = start > 0 && this.getParsed(start - 1);\n for(let i = 0; i < pointsCount; ++i){\n const point = points[i];\n const properties = directUpdate ? point : {};\n if (i < start || i >= end) {\n properties.skip = true;\n continue;\n }\n const parsed = this.getParsed(i);\n const nullData = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vAxis]);\n const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);\n const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);\n properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;\n properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;\n if (segment) {\n properties.parsed = parsed;\n properties.raw = _dataset.data[i];\n }\n if (includeOptions) {\n properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n }\n if (!directUpdate) {\n this.updateElement(point, i, properties, mode);\n }\n prevParsed = parsed;\n }\n }\n getMaxOverflow() {\n const meta = this._cachedMeta;\n const dataset = meta.dataset;\n const border = dataset.options && dataset.options.borderWidth || 0;\n const data = meta.data || [];\n if (!data.length) {\n return border;\n }\n const firstPoint = data[0].size(this.resolveDataElementOptions(0));\n const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));\n return Math.max(border, firstPoint, lastPoint) / 2;\n }\n draw() {\n const meta = this._cachedMeta;\n meta.dataset.updateControlPoints(this.chart.chartArea, meta.iScale.axis);\n super.draw();\n }\n}\n\nclass PolarAreaController extends DatasetController {\n static id = 'polarArea';\n static defaults = {\n dataElementType: 'arc',\n animation: {\n animateRotate: true,\n animateScale: true\n },\n animations: {\n numbers: {\n type: 'number',\n properties: [\n 'x',\n 'y',\n 'startAngle',\n 'endAngle',\n 'innerRadius',\n 'outerRadius'\n ]\n }\n },\n indexAxis: 'r',\n startAngle: 0\n };\n static overrides = {\n aspectRatio: 1,\n plugins: {\n legend: {\n labels: {\n generateLabels (chart) {\n const data = chart.data;\n if (data.labels.length && data.datasets.length) {\n const { labels: { pointStyle , color } } = chart.legend.options;\n return data.labels.map((label, i)=>{\n const meta = chart.getDatasetMeta(0);\n const style = meta.controller.getStyle(i);\n return {\n text: label,\n fillStyle: style.backgroundColor,\n strokeStyle: style.borderColor,\n fontColor: color,\n lineWidth: style.borderWidth,\n pointStyle: pointStyle,\n hidden: !chart.getDataVisibility(i),\n index: i\n };\n });\n }\n return [];\n }\n },\n onClick (e, legendItem, legend) {\n legend.chart.toggleDataVisibility(legendItem.index);\n legend.chart.update();\n }\n }\n },\n scales: {\n r: {\n type: 'radialLinear',\n angleLines: {\n display: false\n },\n beginAtZero: true,\n grid: {\n circular: true\n },\n pointLabels: {\n display: false\n },\n startAngle: 0\n }\n }\n };\n constructor(chart, datasetIndex){\n super(chart, datasetIndex);\n this.innerRadius = undefined;\n this.outerRadius = undefined;\n }\n getLabelAndValue(index) {\n const meta = this._cachedMeta;\n const chart = this.chart;\n const labels = chart.data.labels || [];\n const value = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(meta._parsed[index].r, chart.options.locale);\n return {\n label: labels[index] || '',\n value\n };\n }\n parseObjectData(meta, data, start, count) {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.y.bind(this)(meta, data, start, count);\n }\n update(mode) {\n const arcs = this._cachedMeta.data;\n this._updateRadius();\n this.updateElements(arcs, 0, arcs.length, mode);\n }\n getMinMax() {\n const meta = this._cachedMeta;\n const range = {\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY\n };\n meta.data.forEach((element, index)=>{\n const parsed = this.getParsed(index).r;\n if (!isNaN(parsed) && this.chart.getDataVisibility(index)) {\n if (parsed < range.min) {\n range.min = parsed;\n }\n if (parsed > range.max) {\n range.max = parsed;\n }\n }\n });\n return range;\n }\n _updateRadius() {\n const chart = this.chart;\n const chartArea = chart.chartArea;\n const opts = chart.options;\n const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\n const outerRadius = Math.max(minSize / 2, 0);\n const innerRadius = Math.max(opts.cutoutPercentage ? outerRadius / 100 * opts.cutoutPercentage : 1, 0);\n const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount();\n this.outerRadius = outerRadius - radiusLength * this.index;\n this.innerRadius = this.outerRadius - radiusLength;\n }\n updateElements(arcs, start, count, mode) {\n const reset = mode === 'reset';\n const chart = this.chart;\n const opts = chart.options;\n const animationOpts = opts.animation;\n const scale = this._cachedMeta.rScale;\n const centerX = scale.xCenter;\n const centerY = scale.yCenter;\n const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P;\n let angle = datasetStartAngle;\n let i;\n const defaultAngle = 360 / this.countVisibleElements();\n for(i = 0; i < start; ++i){\n angle += this._computeAngle(i, mode, defaultAngle);\n }\n for(i = start; i < start + count; i++){\n const arc = arcs[i];\n let startAngle = angle;\n let endAngle = angle + this._computeAngle(i, mode, defaultAngle);\n let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(this.getParsed(i).r) : 0;\n angle = endAngle;\n if (reset) {\n if (animationOpts.animateScale) {\n outerRadius = 0;\n }\n if (animationOpts.animateRotate) {\n startAngle = endAngle = datasetStartAngle;\n }\n }\n const properties = {\n x: centerX,\n y: centerY,\n innerRadius: 0,\n outerRadius,\n startAngle,\n endAngle,\n options: this.resolveDataElementOptions(i, arc.active ? 'active' : mode)\n };\n this.updateElement(arc, i, properties, mode);\n }\n }\n countVisibleElements() {\n const meta = this._cachedMeta;\n let count = 0;\n meta.data.forEach((element, index)=>{\n if (!isNaN(this.getParsed(index).r) && this.chart.getDataVisibility(index)) {\n count++;\n }\n });\n return count;\n }\n _computeAngle(index, mode, defaultAngle) {\n return this.chart.getDataVisibility(index) ? (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.resolveDataElementOptions(index, mode).angle || defaultAngle) : 0;\n }\n}\n\nclass PieController extends DoughnutController {\n static id = 'pie';\n static defaults = {\n cutout: 0,\n rotation: 0,\n circumference: 360,\n radius: '100%'\n };\n}\n\nclass RadarController extends DatasetController {\n static id = 'radar';\n static defaults = {\n datasetElementType: 'line',\n dataElementType: 'point',\n indexAxis: 'r',\n showLine: true,\n elements: {\n line: {\n fill: 'start'\n }\n }\n };\n static overrides = {\n aspectRatio: 1,\n scales: {\n r: {\n type: 'radialLinear'\n }\n }\n };\n getLabelAndValue(index) {\n const vScale = this._cachedMeta.vScale;\n const parsed = this.getParsed(index);\n return {\n label: vScale.getLabels()[index],\n value: '' + vScale.getLabelForValue(parsed[vScale.axis])\n };\n }\n parseObjectData(meta, data, start, count) {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.y.bind(this)(meta, data, start, count);\n }\n update(mode) {\n const meta = this._cachedMeta;\n const line = meta.dataset;\n const points = meta.data || [];\n const labels = meta.iScale.getLabels();\n line.points = points;\n if (mode !== 'resize') {\n const options = this.resolveDatasetElementOptions(mode);\n if (!this.options.showLine) {\n options.borderWidth = 0;\n }\n const properties = {\n _loop: true,\n _fullLoop: labels.length === points.length,\n options\n };\n this.updateElement(line, undefined, properties, mode);\n }\n this.updateElements(points, 0, points.length, mode);\n }\n updateElements(points, start, count, mode) {\n const scale = this._cachedMeta.rScale;\n const reset = mode === 'reset';\n for(let i = start; i < start + count; i++){\n const point = points[i];\n const options = this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n const pointPosition = scale.getPointPositionForValue(i, this.getParsed(i).r);\n const x = reset ? scale.xCenter : pointPosition.x;\n const y = reset ? scale.yCenter : pointPosition.y;\n const properties = {\n x,\n y,\n angle: pointPosition.angle,\n skip: isNaN(x) || isNaN(y),\n options\n };\n this.updateElement(point, i, properties, mode);\n }\n }\n}\n\nclass ScatterController extends DatasetController {\n static id = 'scatter';\n static defaults = {\n datasetElementType: false,\n dataElementType: 'point',\n showLine: false,\n fill: false\n };\n static overrides = {\n interaction: {\n mode: 'point'\n },\n scales: {\n x: {\n type: 'linear'\n },\n y: {\n type: 'linear'\n }\n }\n };\n getLabelAndValue(index) {\n const meta = this._cachedMeta;\n const labels = this.chart.data.labels || [];\n const { xScale , yScale } = meta;\n const parsed = this.getParsed(index);\n const x = xScale.getLabelForValue(parsed.x);\n const y = yScale.getLabelForValue(parsed.y);\n return {\n label: labels[index] || '',\n value: '(' + x + ', ' + y + ')'\n };\n }\n update(mode) {\n const meta = this._cachedMeta;\n const { data: points = [] } = meta;\n const animationsDisabled = this.chart._animationsDisabled;\n let { start , count } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.q)(meta, points, animationsDisabled);\n this._drawStart = start;\n this._drawCount = count;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.w)(meta)) {\n start = 0;\n count = points.length;\n }\n if (this.options.showLine) {\n if (!this.datasetElementType) {\n this.addElements();\n }\n const { dataset: line , _dataset } = meta;\n line._chart = this.chart;\n line._datasetIndex = this.index;\n line._decimated = !!_dataset._decimated;\n line.points = points;\n const options = this.resolveDatasetElementOptions(mode);\n options.segment = this.options.segment;\n this.updateElement(line, undefined, {\n animated: !animationsDisabled,\n options\n }, mode);\n } else if (this.datasetElementType) {\n delete meta.dataset;\n this.datasetElementType = false;\n }\n this.updateElements(points, start, count, mode);\n }\n addElements() {\n const { showLine } = this.options;\n if (!this.datasetElementType && showLine) {\n this.datasetElementType = this.chart.registry.getElement('line');\n }\n super.addElements();\n }\n updateElements(points, start, count, mode) {\n const reset = mode === 'reset';\n const { iScale , vScale , _stacked , _dataset } = this._cachedMeta;\n const firstOpts = this.resolveDataElementOptions(start, mode);\n const sharedOptions = this.getSharedOptions(firstOpts);\n const includeOptions = this.includeOptions(mode, sharedOptions);\n const iAxis = iScale.axis;\n const vAxis = vScale.axis;\n const { spanGaps , segment } = this.options;\n const maxGapLength = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;\n const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';\n let prevParsed = start > 0 && this.getParsed(start - 1);\n for(let i = start; i < start + count; ++i){\n const point = points[i];\n const parsed = this.getParsed(i);\n const properties = directUpdate ? point : {};\n const nullData = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vAxis]);\n const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);\n const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);\n properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;\n properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;\n if (segment) {\n properties.parsed = parsed;\n properties.raw = _dataset.data[i];\n }\n if (includeOptions) {\n properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n }\n if (!directUpdate) {\n this.updateElement(point, i, properties, mode);\n }\n prevParsed = parsed;\n }\n this.updateSharedOptions(sharedOptions, mode, firstOpts);\n }\n getMaxOverflow() {\n const meta = this._cachedMeta;\n const data = meta.data || [];\n if (!this.options.showLine) {\n let max = 0;\n for(let i = data.length - 1; i >= 0; --i){\n max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2);\n }\n return max > 0 && max;\n }\n const dataset = meta.dataset;\n const border = dataset.options && dataset.options.borderWidth || 0;\n if (!data.length) {\n return border;\n }\n const firstPoint = data[0].size(this.resolveDataElementOptions(0));\n const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));\n return Math.max(border, firstPoint, lastPoint) / 2;\n }\n}\n\nvar controllers = /*#__PURE__*/Object.freeze({\n__proto__: null,\nBarController: BarController,\nBubbleController: BubbleController,\nDoughnutController: DoughnutController,\nLineController: LineController,\nPieController: PieController,\nPolarAreaController: PolarAreaController,\nRadarController: RadarController,\nScatterController: ScatterController\n});\n\n/**\n * @namespace Chart._adapters\n * @since 2.8.0\n * @private\n */ function abstract() {\n throw new Error('This method is not implemented: Check that a complete date adapter is provided.');\n}\n/**\n * Date adapter (current used by the time scale)\n * @namespace Chart._adapters._date\n * @memberof Chart._adapters\n * @private\n */ class DateAdapterBase {\n /**\n * Override default date adapter methods.\n * Accepts type parameter to define options type.\n * @example\n * Chart._adapters._date.override<{myAdapterOption: string}>({\n * init() {\n * console.log(this.options.myAdapterOption);\n * }\n * })\n */ static override(members) {\n Object.assign(DateAdapterBase.prototype, members);\n }\n options;\n constructor(options){\n this.options = options || {};\n }\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n init() {}\n formats() {\n return abstract();\n }\n parse() {\n return abstract();\n }\n format() {\n return abstract();\n }\n add() {\n return abstract();\n }\n diff() {\n return abstract();\n }\n startOf() {\n return abstract();\n }\n endOf() {\n return abstract();\n }\n}\nvar adapters = {\n _date: DateAdapterBase\n};\n\nfunction binarySearch(metaset, axis, value, intersect) {\n const { controller , data , _sorted } = metaset;\n const iScale = controller._cachedMeta.iScale;\n const spanGaps = metaset.dataset ? metaset.dataset.options ? metaset.dataset.options.spanGaps : null : null;\n if (iScale && axis === iScale.axis && axis !== 'r' && _sorted && data.length) {\n const lookupMethod = iScale._reversePixels ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.A : _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B;\n if (!intersect) {\n const result = lookupMethod(data, axis, value);\n if (spanGaps) {\n const { vScale } = controller._cachedMeta;\n const { _parsed } = metaset;\n const distanceToDefinedLo = _parsed.slice(0, result.lo + 1).reverse().findIndex((point)=>!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(point[vScale.axis]));\n result.lo -= Math.max(0, distanceToDefinedLo);\n const distanceToDefinedHi = _parsed.slice(result.hi).findIndex((point)=>!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(point[vScale.axis]));\n result.hi += Math.max(0, distanceToDefinedHi);\n }\n return result;\n } else if (controller._sharedOptions) {\n const el = data[0];\n const range = typeof el.getRange === 'function' && el.getRange(axis);\n if (range) {\n const start = lookupMethod(data, axis, value - range);\n const end = lookupMethod(data, axis, value + range);\n return {\n lo: start.lo,\n hi: end.hi\n };\n }\n }\n }\n return {\n lo: 0,\n hi: data.length - 1\n };\n}\n function evaluateInteractionItems(chart, axis, position, handler, intersect) {\n const metasets = chart.getSortedVisibleDatasetMetas();\n const value = position[axis];\n for(let i = 0, ilen = metasets.length; i < ilen; ++i){\n const { index , data } = metasets[i];\n const { lo , hi } = binarySearch(metasets[i], axis, value, intersect);\n for(let j = lo; j <= hi; ++j){\n const element = data[j];\n if (!element.skip) {\n handler(element, index, j);\n }\n }\n }\n}\n function getDistanceMetricForAxis(axis) {\n const useX = axis.indexOf('x') !== -1;\n const useY = axis.indexOf('y') !== -1;\n return function(pt1, pt2) {\n const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;\n const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;\n return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));\n };\n}\n function getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) {\n const items = [];\n if (!includeInvisible && !chart.isPointInArea(position)) {\n return items;\n }\n const evaluationFunc = function(element, datasetIndex, index) {\n if (!includeInvisible && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)(element, chart.chartArea, 0)) {\n return;\n }\n if (element.inRange(position.x, position.y, useFinalPosition)) {\n items.push({\n element,\n datasetIndex,\n index\n });\n }\n };\n evaluateInteractionItems(chart, axis, position, evaluationFunc, true);\n return items;\n}\n function getNearestRadialItems(chart, position, axis, useFinalPosition) {\n let items = [];\n function evaluationFunc(element, datasetIndex, index) {\n const { startAngle , endAngle } = element.getProps([\n 'startAngle',\n 'endAngle'\n ], useFinalPosition);\n const { angle } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.D)(element, {\n x: position.x,\n y: position.y\n });\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle)) {\n items.push({\n element,\n datasetIndex,\n index\n });\n }\n }\n evaluateInteractionItems(chart, axis, position, evaluationFunc);\n return items;\n}\n function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {\n let items = [];\n const distanceMetric = getDistanceMetricForAxis(axis);\n let minDistance = Number.POSITIVE_INFINITY;\n function evaluationFunc(element, datasetIndex, index) {\n const inRange = element.inRange(position.x, position.y, useFinalPosition);\n if (intersect && !inRange) {\n return;\n }\n const center = element.getCenterPoint(useFinalPosition);\n const pointInArea = !!includeInvisible || chart.isPointInArea(center);\n if (!pointInArea && !inRange) {\n return;\n }\n const distance = distanceMetric(position, center);\n if (distance < minDistance) {\n items = [\n {\n element,\n datasetIndex,\n index\n }\n ];\n minDistance = distance;\n } else if (distance === minDistance) {\n items.push({\n element,\n datasetIndex,\n index\n });\n }\n }\n evaluateInteractionItems(chart, axis, position, evaluationFunc);\n return items;\n}\n function getNearestItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {\n if (!includeInvisible && !chart.isPointInArea(position)) {\n return [];\n }\n return axis === 'r' && !intersect ? getNearestRadialItems(chart, position, axis, useFinalPosition) : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible);\n}\n function getAxisItems(chart, position, axis, intersect, useFinalPosition) {\n const items = [];\n const rangeMethod = axis === 'x' ? 'inXRange' : 'inYRange';\n let intersectsItem = false;\n evaluateInteractionItems(chart, axis, position, (element, datasetIndex, index)=>{\n if (element[rangeMethod] && element[rangeMethod](position[axis], useFinalPosition)) {\n items.push({\n element,\n datasetIndex,\n index\n });\n intersectsItem = intersectsItem || element.inRange(position.x, position.y, useFinalPosition);\n }\n });\n if (intersect && !intersectsItem) {\n return [];\n }\n return items;\n}\n var Interaction = {\n evaluateInteractionItems,\n modes: {\n index (chart, e, options, useFinalPosition) {\n const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);\n const axis = options.axis || 'x';\n const includeInvisible = options.includeInvisible || false;\n const items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);\n const elements = [];\n if (!items.length) {\n return [];\n }\n chart.getSortedVisibleDatasetMetas().forEach((meta)=>{\n const index = items[0].index;\n const element = meta.data[index];\n if (element && !element.skip) {\n elements.push({\n element,\n datasetIndex: meta.index,\n index\n });\n }\n });\n return elements;\n },\n dataset (chart, e, options, useFinalPosition) {\n const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);\n const axis = options.axis || 'xy';\n const includeInvisible = options.includeInvisible || false;\n let items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);\n if (items.length > 0) {\n const datasetIndex = items[0].datasetIndex;\n const data = chart.getDatasetMeta(datasetIndex).data;\n items = [];\n for(let i = 0; i < data.length; ++i){\n items.push({\n element: data[i],\n datasetIndex,\n index: i\n });\n }\n }\n return items;\n },\n point (chart, e, options, useFinalPosition) {\n const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);\n const axis = options.axis || 'xy';\n const includeInvisible = options.includeInvisible || false;\n return getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible);\n },\n nearest (chart, e, options, useFinalPosition) {\n const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);\n const axis = options.axis || 'xy';\n const includeInvisible = options.includeInvisible || false;\n return getNearestItems(chart, position, axis, options.intersect, useFinalPosition, includeInvisible);\n },\n x (chart, e, options, useFinalPosition) {\n const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);\n return getAxisItems(chart, position, 'x', options.intersect, useFinalPosition);\n },\n y (chart, e, options, useFinalPosition) {\n const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);\n return getAxisItems(chart, position, 'y', options.intersect, useFinalPosition);\n }\n }\n};\n\nconst STATIC_POSITIONS = [\n 'left',\n 'top',\n 'right',\n 'bottom'\n];\nfunction filterByPosition(array, position) {\n return array.filter((v)=>v.pos === position);\n}\nfunction filterDynamicPositionByAxis(array, axis) {\n return array.filter((v)=>STATIC_POSITIONS.indexOf(v.pos) === -1 && v.box.axis === axis);\n}\nfunction sortByWeight(array, reverse) {\n return array.sort((a, b)=>{\n const v0 = reverse ? b : a;\n const v1 = reverse ? a : b;\n return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight;\n });\n}\nfunction wrapBoxes(boxes) {\n const layoutBoxes = [];\n let i, ilen, box, pos, stack, stackWeight;\n for(i = 0, ilen = (boxes || []).length; i < ilen; ++i){\n box = boxes[i];\n ({ position: pos , options: { stack , stackWeight =1 } } = box);\n layoutBoxes.push({\n index: i,\n box,\n pos,\n horizontal: box.isHorizontal(),\n weight: box.weight,\n stack: stack && pos + stack,\n stackWeight\n });\n }\n return layoutBoxes;\n}\nfunction buildStacks(layouts) {\n const stacks = {};\n for (const wrap of layouts){\n const { stack , pos , stackWeight } = wrap;\n if (!stack || !STATIC_POSITIONS.includes(pos)) {\n continue;\n }\n const _stack = stacks[stack] || (stacks[stack] = {\n count: 0,\n placed: 0,\n weight: 0,\n size: 0\n });\n _stack.count++;\n _stack.weight += stackWeight;\n }\n return stacks;\n}\n function setLayoutDims(layouts, params) {\n const stacks = buildStacks(layouts);\n const { vBoxMaxWidth , hBoxMaxHeight } = params;\n let i, ilen, layout;\n for(i = 0, ilen = layouts.length; i < ilen; ++i){\n layout = layouts[i];\n const { fullSize } = layout.box;\n const stack = stacks[layout.stack];\n const factor = stack && layout.stackWeight / stack.weight;\n if (layout.horizontal) {\n layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth;\n layout.height = hBoxMaxHeight;\n } else {\n layout.width = vBoxMaxWidth;\n layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight;\n }\n }\n return stacks;\n}\nfunction buildLayoutBoxes(boxes) {\n const layoutBoxes = wrapBoxes(boxes);\n const fullSize = sortByWeight(layoutBoxes.filter((wrap)=>wrap.box.fullSize), true);\n const left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true);\n const right = sortByWeight(filterByPosition(layoutBoxes, 'right'));\n const top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true);\n const bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom'));\n const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, 'x');\n const centerVertical = filterDynamicPositionByAxis(layoutBoxes, 'y');\n return {\n fullSize,\n leftAndTop: left.concat(top),\n rightAndBottom: right.concat(centerVertical).concat(bottom).concat(centerHorizontal),\n chartArea: filterByPosition(layoutBoxes, 'chartArea'),\n vertical: left.concat(right).concat(centerVertical),\n horizontal: top.concat(bottom).concat(centerHorizontal)\n };\n}\nfunction getCombinedMax(maxPadding, chartArea, a, b) {\n return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]);\n}\nfunction updateMaxPadding(maxPadding, boxPadding) {\n maxPadding.top = Math.max(maxPadding.top, boxPadding.top);\n maxPadding.left = Math.max(maxPadding.left, boxPadding.left);\n maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom);\n maxPadding.right = Math.max(maxPadding.right, boxPadding.right);\n}\nfunction updateDims(chartArea, params, layout, stacks) {\n const { pos , box } = layout;\n const maxPadding = chartArea.maxPadding;\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(pos)) {\n if (layout.size) {\n chartArea[pos] -= layout.size;\n }\n const stack = stacks[layout.stack] || {\n size: 0,\n count: 1\n };\n stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width);\n layout.size = stack.size / stack.count;\n chartArea[pos] += layout.size;\n }\n if (box.getPadding) {\n updateMaxPadding(maxPadding, box.getPadding());\n }\n const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right'));\n const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom'));\n const widthChanged = newWidth !== chartArea.w;\n const heightChanged = newHeight !== chartArea.h;\n chartArea.w = newWidth;\n chartArea.h = newHeight;\n return layout.horizontal ? {\n same: widthChanged,\n other: heightChanged\n } : {\n same: heightChanged,\n other: widthChanged\n };\n}\nfunction handleMaxPadding(chartArea) {\n const maxPadding = chartArea.maxPadding;\n function updatePos(pos) {\n const change = Math.max(maxPadding[pos] - chartArea[pos], 0);\n chartArea[pos] += change;\n return change;\n }\n chartArea.y += updatePos('top');\n chartArea.x += updatePos('left');\n updatePos('right');\n updatePos('bottom');\n}\nfunction getMargins(horizontal, chartArea) {\n const maxPadding = chartArea.maxPadding;\n function marginForPositions(positions) {\n const margin = {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0\n };\n positions.forEach((pos)=>{\n margin[pos] = Math.max(chartArea[pos], maxPadding[pos]);\n });\n return margin;\n }\n return horizontal ? marginForPositions([\n 'left',\n 'right'\n ]) : marginForPositions([\n 'top',\n 'bottom'\n ]);\n}\nfunction fitBoxes(boxes, chartArea, params, stacks) {\n const refitBoxes = [];\n let i, ilen, layout, box, refit, changed;\n for(i = 0, ilen = boxes.length, refit = 0; i < ilen; ++i){\n layout = boxes[i];\n box = layout.box;\n box.update(layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea));\n const { same , other } = updateDims(chartArea, params, layout, stacks);\n refit |= same && refitBoxes.length;\n changed = changed || other;\n if (!box.fullSize) {\n refitBoxes.push(layout);\n }\n }\n return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed;\n}\nfunction setBoxDims(box, left, top, width, height) {\n box.top = top;\n box.left = left;\n box.right = left + width;\n box.bottom = top + height;\n box.width = width;\n box.height = height;\n}\nfunction placeBoxes(boxes, chartArea, params, stacks) {\n const userPadding = params.padding;\n let { x , y } = chartArea;\n for (const layout of boxes){\n const box = layout.box;\n const stack = stacks[layout.stack] || {\n count: 1,\n placed: 0,\n weight: 1\n };\n const weight = layout.stackWeight / stack.weight || 1;\n if (layout.horizontal) {\n const width = chartArea.w * weight;\n const height = stack.size || box.height;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) {\n y = stack.start;\n }\n if (box.fullSize) {\n setBoxDims(box, userPadding.left, y, params.outerWidth - userPadding.right - userPadding.left, height);\n } else {\n setBoxDims(box, chartArea.left + stack.placed, y, width, height);\n }\n stack.start = y;\n stack.placed += width;\n y = box.bottom;\n } else {\n const height = chartArea.h * weight;\n const width = stack.size || box.width;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) {\n x = stack.start;\n }\n if (box.fullSize) {\n setBoxDims(box, x, userPadding.top, width, params.outerHeight - userPadding.bottom - userPadding.top);\n } else {\n setBoxDims(box, x, chartArea.top + stack.placed, width, height);\n }\n stack.start = x;\n stack.placed += height;\n x = box.right;\n }\n }\n chartArea.x = x;\n chartArea.y = y;\n}\nvar layouts = {\n addBox (chart, item) {\n if (!chart.boxes) {\n chart.boxes = [];\n }\n item.fullSize = item.fullSize || false;\n item.position = item.position || 'top';\n item.weight = item.weight || 0;\n item._layers = item._layers || function() {\n return [\n {\n z: 0,\n draw (chartArea) {\n item.draw(chartArea);\n }\n }\n ];\n };\n chart.boxes.push(item);\n },\n removeBox (chart, layoutItem) {\n const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;\n if (index !== -1) {\n chart.boxes.splice(index, 1);\n }\n },\n configure (chart, item, options) {\n item.fullSize = options.fullSize;\n item.position = options.position;\n item.weight = options.weight;\n },\n update (chart, width, height, minPadding) {\n if (!chart) {\n return;\n }\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(chart.options.layout.padding);\n const availableWidth = Math.max(width - padding.width, 0);\n const availableHeight = Math.max(height - padding.height, 0);\n const boxes = buildLayoutBoxes(chart.boxes);\n const verticalBoxes = boxes.vertical;\n const horizontalBoxes = boxes.horizontal;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(chart.boxes, (box)=>{\n if (typeof box.beforeLayout === 'function') {\n box.beforeLayout();\n }\n });\n const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap)=>wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1;\n const params = Object.freeze({\n outerWidth: width,\n outerHeight: height,\n padding,\n availableWidth,\n availableHeight,\n vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount,\n hBoxMaxHeight: availableHeight / 2\n });\n const maxPadding = Object.assign({}, padding);\n updateMaxPadding(maxPadding, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(minPadding));\n const chartArea = Object.assign({\n maxPadding,\n w: availableWidth,\n h: availableHeight,\n x: padding.left,\n y: padding.top\n }, padding);\n const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params);\n fitBoxes(boxes.fullSize, chartArea, params, stacks);\n fitBoxes(verticalBoxes, chartArea, params, stacks);\n if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) {\n fitBoxes(verticalBoxes, chartArea, params, stacks);\n }\n handleMaxPadding(chartArea);\n placeBoxes(boxes.leftAndTop, chartArea, params, stacks);\n chartArea.x += chartArea.w;\n chartArea.y += chartArea.h;\n placeBoxes(boxes.rightAndBottom, chartArea, params, stacks);\n chart.chartArea = {\n left: chartArea.left,\n top: chartArea.top,\n right: chartArea.left + chartArea.w,\n bottom: chartArea.top + chartArea.h,\n height: chartArea.h,\n width: chartArea.w\n };\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(boxes.chartArea, (layout)=>{\n const box = layout.box;\n Object.assign(box, chart.chartArea);\n box.update(chartArea.w, chartArea.h, {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0\n });\n });\n }\n};\n\nclass BasePlatform {\n acquireContext(canvas, aspectRatio) {}\n releaseContext(context) {\n return false;\n }\n addEventListener(chart, type, listener) {}\n removeEventListener(chart, type, listener) {}\n getDevicePixelRatio() {\n return 1;\n }\n getMaximumSize(element, width, height, aspectRatio) {\n width = Math.max(0, width || element.width);\n height = height || element.height;\n return {\n width,\n height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height)\n };\n }\n isAttached(canvas) {\n return true;\n }\n updateConfig(config) {\n }\n}\n\nclass BasicPlatform extends BasePlatform {\n acquireContext(item) {\n return item && item.getContext && item.getContext('2d') || null;\n }\n updateConfig(config) {\n config.options.animation = false;\n }\n}\n\nconst EXPANDO_KEY = '$chartjs';\n const EVENT_TYPES = {\n touchstart: 'mousedown',\n touchmove: 'mousemove',\n touchend: 'mouseup',\n pointerenter: 'mouseenter',\n pointerdown: 'mousedown',\n pointermove: 'mousemove',\n pointerup: 'mouseup',\n pointerleave: 'mouseout',\n pointerout: 'mouseout'\n};\nconst isNullOrEmpty = (value)=>value === null || value === '';\n function initCanvas(canvas, aspectRatio) {\n const style = canvas.style;\n const renderHeight = canvas.getAttribute('height');\n const renderWidth = canvas.getAttribute('width');\n canvas[EXPANDO_KEY] = {\n initial: {\n height: renderHeight,\n width: renderWidth,\n style: {\n display: style.display,\n height: style.height,\n width: style.width\n }\n }\n };\n style.display = style.display || 'block';\n style.boxSizing = style.boxSizing || 'border-box';\n if (isNullOrEmpty(renderWidth)) {\n const displayWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.J)(canvas, 'width');\n if (displayWidth !== undefined) {\n canvas.width = displayWidth;\n }\n }\n if (isNullOrEmpty(renderHeight)) {\n if (canvas.style.height === '') {\n canvas.height = canvas.width / (aspectRatio || 2);\n } else {\n const displayHeight = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.J)(canvas, 'height');\n if (displayHeight !== undefined) {\n canvas.height = displayHeight;\n }\n }\n }\n return canvas;\n}\nconst eventListenerOptions = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.K ? {\n passive: true\n} : false;\nfunction addListener(node, type, listener) {\n if (node) {\n node.addEventListener(type, listener, eventListenerOptions);\n }\n}\nfunction removeListener(chart, type, listener) {\n if (chart && chart.canvas) {\n chart.canvas.removeEventListener(type, listener, eventListenerOptions);\n }\n}\nfunction fromNativeEvent(event, chart) {\n const type = EVENT_TYPES[event.type] || event.type;\n const { x , y } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(event, chart);\n return {\n type,\n chart,\n native: event,\n x: x !== undefined ? x : null,\n y: y !== undefined ? y : null\n };\n}\nfunction nodeListContains(nodeList, canvas) {\n for (const node of nodeList){\n if (node === canvas || node.contains(canvas)) {\n return true;\n }\n }\n}\nfunction createAttachObserver(chart, type, listener) {\n const canvas = chart.canvas;\n const observer = new MutationObserver((entries)=>{\n let trigger = false;\n for (const entry of entries){\n trigger = trigger || nodeListContains(entry.addedNodes, canvas);\n trigger = trigger && !nodeListContains(entry.removedNodes, canvas);\n }\n if (trigger) {\n listener();\n }\n });\n observer.observe(document, {\n childList: true,\n subtree: true\n });\n return observer;\n}\nfunction createDetachObserver(chart, type, listener) {\n const canvas = chart.canvas;\n const observer = new MutationObserver((entries)=>{\n let trigger = false;\n for (const entry of entries){\n trigger = trigger || nodeListContains(entry.removedNodes, canvas);\n trigger = trigger && !nodeListContains(entry.addedNodes, canvas);\n }\n if (trigger) {\n listener();\n }\n });\n observer.observe(document, {\n childList: true,\n subtree: true\n });\n return observer;\n}\nconst drpListeningCharts = new Map();\nlet oldDevicePixelRatio = 0;\nfunction onWindowResize() {\n const dpr = window.devicePixelRatio;\n if (dpr === oldDevicePixelRatio) {\n return;\n }\n oldDevicePixelRatio = dpr;\n drpListeningCharts.forEach((resize, chart)=>{\n if (chart.currentDevicePixelRatio !== dpr) {\n resize();\n }\n });\n}\nfunction listenDevicePixelRatioChanges(chart, resize) {\n if (!drpListeningCharts.size) {\n window.addEventListener('resize', onWindowResize);\n }\n drpListeningCharts.set(chart, resize);\n}\nfunction unlistenDevicePixelRatioChanges(chart) {\n drpListeningCharts.delete(chart);\n if (!drpListeningCharts.size) {\n window.removeEventListener('resize', onWindowResize);\n }\n}\nfunction createResizeObserver(chart, type, listener) {\n const canvas = chart.canvas;\n const container = canvas && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.I)(canvas);\n if (!container) {\n return;\n }\n const resize = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.L)((width, height)=>{\n const w = container.clientWidth;\n listener(width, height);\n if (w < container.clientWidth) {\n listener();\n }\n }, window);\n const observer = new ResizeObserver((entries)=>{\n const entry = entries[0];\n const width = entry.contentRect.width;\n const height = entry.contentRect.height;\n if (width === 0 && height === 0) {\n return;\n }\n resize(width, height);\n });\n observer.observe(container);\n listenDevicePixelRatioChanges(chart, resize);\n return observer;\n}\nfunction releaseObserver(chart, type, observer) {\n if (observer) {\n observer.disconnect();\n }\n if (type === 'resize') {\n unlistenDevicePixelRatioChanges(chart);\n }\n}\nfunction createProxyAndListen(chart, type, listener) {\n const canvas = chart.canvas;\n const proxy = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.L)((event)=>{\n if (chart.ctx !== null) {\n listener(fromNativeEvent(event, chart));\n }\n }, chart);\n addListener(canvas, type, proxy);\n return proxy;\n}\n class DomPlatform extends BasePlatform {\n acquireContext(canvas, aspectRatio) {\n const context = canvas && canvas.getContext && canvas.getContext('2d');\n if (context && context.canvas === canvas) {\n initCanvas(canvas, aspectRatio);\n return context;\n }\n return null;\n }\n releaseContext(context) {\n const canvas = context.canvas;\n if (!canvas[EXPANDO_KEY]) {\n return false;\n }\n const initial = canvas[EXPANDO_KEY].initial;\n [\n 'height',\n 'width'\n ].forEach((prop)=>{\n const value = initial[prop];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) {\n canvas.removeAttribute(prop);\n } else {\n canvas.setAttribute(prop, value);\n }\n });\n const style = initial.style || {};\n Object.keys(style).forEach((key)=>{\n canvas.style[key] = style[key];\n });\n canvas.width = canvas.width;\n delete canvas[EXPANDO_KEY];\n return true;\n }\n addEventListener(chart, type, listener) {\n this.removeEventListener(chart, type);\n const proxies = chart.$proxies || (chart.$proxies = {});\n const handlers = {\n attach: createAttachObserver,\n detach: createDetachObserver,\n resize: createResizeObserver\n };\n const handler = handlers[type] || createProxyAndListen;\n proxies[type] = handler(chart, type, listener);\n }\n removeEventListener(chart, type) {\n const proxies = chart.$proxies || (chart.$proxies = {});\n const proxy = proxies[type];\n if (!proxy) {\n return;\n }\n const handlers = {\n attach: releaseObserver,\n detach: releaseObserver,\n resize: releaseObserver\n };\n const handler = handlers[type] || removeListener;\n handler(chart, type, proxy);\n proxies[type] = undefined;\n }\n getDevicePixelRatio() {\n return window.devicePixelRatio;\n }\n getMaximumSize(canvas, width, height, aspectRatio) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.G)(canvas, width, height, aspectRatio);\n }\n isAttached(canvas) {\n const container = canvas && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.I)(canvas);\n return !!(container && container.isConnected);\n }\n}\n\nfunction _detectPlatform(canvas) {\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.M)() || typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas) {\n return BasicPlatform;\n }\n return DomPlatform;\n}\n\nclass Element {\n static defaults = {};\n static defaultRoutes = undefined;\n x;\n y;\n active = false;\n options;\n $animations;\n tooltipPosition(useFinalPosition) {\n const { x , y } = this.getProps([\n 'x',\n 'y'\n ], useFinalPosition);\n return {\n x,\n y\n };\n }\n hasValue() {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(this.x) && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(this.y);\n }\n getProps(props, final) {\n const anims = this.$animations;\n if (!final || !anims) {\n // let's not create an object, if not needed\n return this;\n }\n const ret = {};\n props.forEach((prop)=>{\n ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop];\n });\n return ret;\n }\n}\n\nfunction autoSkip(scale, ticks) {\n const tickOpts = scale.options.ticks;\n const determinedMaxTicks = determineMaxTicks(scale);\n const ticksLimit = Math.min(tickOpts.maxTicksLimit || determinedMaxTicks, determinedMaxTicks);\n const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];\n const numMajorIndices = majorIndices.length;\n const first = majorIndices[0];\n const last = majorIndices[numMajorIndices - 1];\n const newTicks = [];\n if (numMajorIndices > ticksLimit) {\n skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);\n return newTicks;\n }\n const spacing = calculateSpacing(majorIndices, ticks, ticksLimit);\n if (numMajorIndices > 0) {\n let i, ilen;\n const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null;\n skip(ticks, newTicks, spacing, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);\n for(i = 0, ilen = numMajorIndices - 1; i < ilen; i++){\n skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]);\n }\n skip(ticks, newTicks, spacing, last, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);\n return newTicks;\n }\n skip(ticks, newTicks, spacing);\n return newTicks;\n}\nfunction determineMaxTicks(scale) {\n const offset = scale.options.offset;\n const tickLength = scale._tickSize();\n const maxScale = scale._length / tickLength + (offset ? 0 : 1);\n const maxChart = scale._maxLength / tickLength;\n return Math.floor(Math.min(maxScale, maxChart));\n}\n function calculateSpacing(majorIndices, ticks, ticksLimit) {\n const evenMajorSpacing = getEvenSpacing(majorIndices);\n const spacing = ticks.length / ticksLimit;\n if (!evenMajorSpacing) {\n return Math.max(spacing, 1);\n }\n const factors = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.N)(evenMajorSpacing);\n for(let i = 0, ilen = factors.length - 1; i < ilen; i++){\n const factor = factors[i];\n if (factor > spacing) {\n return factor;\n }\n }\n return Math.max(spacing, 1);\n}\n function getMajorIndices(ticks) {\n const result = [];\n let i, ilen;\n for(i = 0, ilen = ticks.length; i < ilen; i++){\n if (ticks[i].major) {\n result.push(i);\n }\n }\n return result;\n}\n function skipMajors(ticks, newTicks, majorIndices, spacing) {\n let count = 0;\n let next = majorIndices[0];\n let i;\n spacing = Math.ceil(spacing);\n for(i = 0; i < ticks.length; i++){\n if (i === next) {\n newTicks.push(ticks[i]);\n count++;\n next = majorIndices[count * spacing];\n }\n }\n}\n function skip(ticks, newTicks, spacing, majorStart, majorEnd) {\n const start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorStart, 0);\n const end = Math.min((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorEnd, ticks.length), ticks.length);\n let count = 0;\n let length, i, next;\n spacing = Math.ceil(spacing);\n if (majorEnd) {\n length = majorEnd - majorStart;\n spacing = length / Math.floor(length / spacing);\n }\n next = start;\n while(next < 0){\n count++;\n next = Math.round(start + count * spacing);\n }\n for(i = Math.max(start, 0); i < end; i++){\n if (i === next) {\n newTicks.push(ticks[i]);\n count++;\n next = Math.round(start + count * spacing);\n }\n }\n}\n function getEvenSpacing(arr) {\n const len = arr.length;\n let i, diff;\n if (len < 2) {\n return false;\n }\n for(diff = arr[0], i = 1; i < len; ++i){\n if (arr[i] - arr[i - 1] !== diff) {\n return false;\n }\n }\n return diff;\n}\n\nconst reverseAlign = (align)=>align === 'left' ? 'right' : align === 'right' ? 'left' : align;\nconst offsetFromEdge = (scale, edge, offset)=>edge === 'top' || edge === 'left' ? scale[edge] + offset : scale[edge] - offset;\nconst getTicksLimit = (ticksLength, maxTicksLimit)=>Math.min(maxTicksLimit || ticksLength, ticksLength);\n function sample(arr, numItems) {\n const result = [];\n const increment = arr.length / numItems;\n const len = arr.length;\n let i = 0;\n for(; i < len; i += increment){\n result.push(arr[Math.floor(i)]);\n }\n return result;\n}\n function getPixelForGridLine(scale, index, offsetGridLines) {\n const length = scale.ticks.length;\n const validIndex = Math.min(index, length - 1);\n const start = scale._startPixel;\n const end = scale._endPixel;\n const epsilon = 1e-6;\n let lineValue = scale.getPixelForTick(validIndex);\n let offset;\n if (offsetGridLines) {\n if (length === 1) {\n offset = Math.max(lineValue - start, end - lineValue);\n } else if (index === 0) {\n offset = (scale.getPixelForTick(1) - lineValue) / 2;\n } else {\n offset = (lineValue - scale.getPixelForTick(validIndex - 1)) / 2;\n }\n lineValue += validIndex < index ? offset : -offset;\n if (lineValue < start - epsilon || lineValue > end + epsilon) {\n return;\n }\n }\n return lineValue;\n}\n function garbageCollect(caches, length) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(caches, (cache)=>{\n const gc = cache.gc;\n const gcLen = gc.length / 2;\n let i;\n if (gcLen > length) {\n for(i = 0; i < gcLen; ++i){\n delete cache.data[gc[i]];\n }\n gc.splice(0, gcLen);\n }\n });\n}\n function getTickMarkLength(options) {\n return options.drawTicks ? options.tickLength : 0;\n}\n function getTitleHeight(options, fallback) {\n if (!options.display) {\n return 0;\n }\n const font = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.font, fallback);\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);\n const lines = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(options.text) ? options.text.length : 1;\n return lines * font.lineHeight + padding.height;\n}\nfunction createScaleContext(parent, scale) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {\n scale,\n type: 'scale'\n });\n}\nfunction createTickContext(parent, index, tick) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {\n tick,\n index,\n type: 'tick'\n });\n}\nfunction titleAlign(align, position, reverse) {\n let ret = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a1)(align);\n if (reverse && position !== 'right' || !reverse && position === 'right') {\n ret = reverseAlign(ret);\n }\n return ret;\n}\nfunction titleArgs(scale, offset, position, align) {\n const { top , left , bottom , right , chart } = scale;\n const { chartArea , scales } = chart;\n let rotation = 0;\n let maxWidth, titleX, titleY;\n const height = bottom - top;\n const width = right - left;\n if (scale.isHorizontal()) {\n titleX = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, left, right);\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {\n const positionAxisID = Object.keys(position)[0];\n const value = position[positionAxisID];\n titleY = scales[positionAxisID].getPixelForValue(value) + height - offset;\n } else if (position === 'center') {\n titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset;\n } else {\n titleY = offsetFromEdge(scale, position, offset);\n }\n maxWidth = right - left;\n } else {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {\n const positionAxisID = Object.keys(position)[0];\n const value = position[positionAxisID];\n titleX = scales[positionAxisID].getPixelForValue(value) - width + offset;\n } else if (position === 'center') {\n titleX = (chartArea.left + chartArea.right) / 2 - width + offset;\n } else {\n titleX = offsetFromEdge(scale, position, offset);\n }\n titleY = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, bottom, top);\n rotation = position === 'left' ? -_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H : _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H;\n }\n return {\n titleX,\n titleY,\n maxWidth,\n rotation\n };\n}\nclass Scale extends Element {\n constructor(cfg){\n super();\n this.id = cfg.id;\n this.type = cfg.type;\n this.options = undefined;\n this.ctx = cfg.ctx;\n this.chart = cfg.chart;\n this.top = undefined;\n this.bottom = undefined;\n this.left = undefined;\n this.right = undefined;\n this.width = undefined;\n this.height = undefined;\n this._margins = {\n left: 0,\n right: 0,\n top: 0,\n bottom: 0\n };\n this.maxWidth = undefined;\n this.maxHeight = undefined;\n this.paddingTop = undefined;\n this.paddingBottom = undefined;\n this.paddingLeft = undefined;\n this.paddingRight = undefined;\n this.axis = undefined;\n this.labelRotation = undefined;\n this.min = undefined;\n this.max = undefined;\n this._range = undefined;\n this.ticks = [];\n this._gridLineItems = null;\n this._labelItems = null;\n this._labelSizes = null;\n this._length = 0;\n this._maxLength = 0;\n this._longestTextCache = {};\n this._startPixel = undefined;\n this._endPixel = undefined;\n this._reversePixels = false;\n this._userMax = undefined;\n this._userMin = undefined;\n this._suggestedMax = undefined;\n this._suggestedMin = undefined;\n this._ticksLength = 0;\n this._borderValue = 0;\n this._cache = {};\n this._dataLimitsCached = false;\n this.$context = undefined;\n }\n init(options) {\n this.options = options.setContext(this.getContext());\n this.axis = options.axis;\n this._userMin = this.parse(options.min);\n this._userMax = this.parse(options.max);\n this._suggestedMin = this.parse(options.suggestedMin);\n this._suggestedMax = this.parse(options.suggestedMax);\n }\n parse(raw, index) {\n return raw;\n }\n getUserBounds() {\n let { _userMin , _userMax , _suggestedMin , _suggestedMax } = this;\n _userMin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMin, Number.POSITIVE_INFINITY);\n _userMax = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMax, Number.NEGATIVE_INFINITY);\n _suggestedMin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_suggestedMin, Number.POSITIVE_INFINITY);\n _suggestedMax = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_suggestedMax, Number.NEGATIVE_INFINITY);\n return {\n min: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMin, _suggestedMin),\n max: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMax, _suggestedMax),\n minDefined: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMin),\n maxDefined: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMax)\n };\n }\n getMinMax(canStack) {\n let { min , max , minDefined , maxDefined } = this.getUserBounds();\n let range;\n if (minDefined && maxDefined) {\n return {\n min,\n max\n };\n }\n const metas = this.getMatchingVisibleMetas();\n for(let i = 0, ilen = metas.length; i < ilen; ++i){\n range = metas[i].controller.getMinMax(this, canStack);\n if (!minDefined) {\n min = Math.min(min, range.min);\n }\n if (!maxDefined) {\n max = Math.max(max, range.max);\n }\n }\n min = maxDefined && min > max ? max : min;\n max = minDefined && min > max ? min : max;\n return {\n min: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(min, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(max, min)),\n max: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(max, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(min, max))\n };\n }\n getPadding() {\n return {\n left: this.paddingLeft || 0,\n top: this.paddingTop || 0,\n right: this.paddingRight || 0,\n bottom: this.paddingBottom || 0\n };\n }\n getTicks() {\n return this.ticks;\n }\n getLabels() {\n const data = this.chart.data;\n return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || [];\n }\n getLabelItems(chartArea = this.chart.chartArea) {\n const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));\n return items;\n }\n beforeLayout() {\n this._cache = {};\n this._dataLimitsCached = false;\n }\n beforeUpdate() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeUpdate, [\n this\n ]);\n }\n update(maxWidth, maxHeight, margins) {\n const { beginAtZero , grace , ticks: tickOpts } = this.options;\n const sampleSize = tickOpts.sampleSize;\n this.beforeUpdate();\n this.maxWidth = maxWidth;\n this.maxHeight = maxHeight;\n this._margins = margins = Object.assign({\n left: 0,\n right: 0,\n top: 0,\n bottom: 0\n }, margins);\n this.ticks = null;\n this._labelSizes = null;\n this._gridLineItems = null;\n this._labelItems = null;\n this.beforeSetDimensions();\n this.setDimensions();\n this.afterSetDimensions();\n this._maxLength = this.isHorizontal() ? this.width + margins.left + margins.right : this.height + margins.top + margins.bottom;\n if (!this._dataLimitsCached) {\n this.beforeDataLimits();\n this.determineDataLimits();\n this.afterDataLimits();\n this._range = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.R)(this, grace, beginAtZero);\n this._dataLimitsCached = true;\n }\n this.beforeBuildTicks();\n this.ticks = this.buildTicks() || [];\n this.afterBuildTicks();\n const samplingEnabled = sampleSize < this.ticks.length;\n this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);\n this.configure();\n this.beforeCalculateLabelRotation();\n this.calculateLabelRotation();\n this.afterCalculateLabelRotation();\n if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) {\n this.ticks = autoSkip(this, this.ticks);\n this._labelSizes = null;\n this.afterAutoSkip();\n }\n if (samplingEnabled) {\n this._convertTicksToLabels(this.ticks);\n }\n this.beforeFit();\n this.fit();\n this.afterFit();\n this.afterUpdate();\n }\n configure() {\n let reversePixels = this.options.reverse;\n let startPixel, endPixel;\n if (this.isHorizontal()) {\n startPixel = this.left;\n endPixel = this.right;\n } else {\n startPixel = this.top;\n endPixel = this.bottom;\n reversePixels = !reversePixels;\n }\n this._startPixel = startPixel;\n this._endPixel = endPixel;\n this._reversePixels = reversePixels;\n this._length = endPixel - startPixel;\n this._alignToPixels = this.options.alignToPixels;\n }\n afterUpdate() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterUpdate, [\n this\n ]);\n }\n beforeSetDimensions() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeSetDimensions, [\n this\n ]);\n }\n setDimensions() {\n if (this.isHorizontal()) {\n this.width = this.maxWidth;\n this.left = 0;\n this.right = this.width;\n } else {\n this.height = this.maxHeight;\n this.top = 0;\n this.bottom = this.height;\n }\n this.paddingLeft = 0;\n this.paddingTop = 0;\n this.paddingRight = 0;\n this.paddingBottom = 0;\n }\n afterSetDimensions() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterSetDimensions, [\n this\n ]);\n }\n _callHooks(name) {\n this.chart.notifyPlugins(name, this.getContext());\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options[name], [\n this\n ]);\n }\n beforeDataLimits() {\n this._callHooks('beforeDataLimits');\n }\n determineDataLimits() {}\n afterDataLimits() {\n this._callHooks('afterDataLimits');\n }\n beforeBuildTicks() {\n this._callHooks('beforeBuildTicks');\n }\n buildTicks() {\n return [];\n }\n afterBuildTicks() {\n this._callHooks('afterBuildTicks');\n }\n beforeTickToLabelConversion() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeTickToLabelConversion, [\n this\n ]);\n }\n generateTickLabels(ticks) {\n const tickOpts = this.options.ticks;\n let i, ilen, tick;\n for(i = 0, ilen = ticks.length; i < ilen; i++){\n tick = ticks[i];\n tick.label = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(tickOpts.callback, [\n tick.value,\n i,\n ticks\n ], this);\n }\n }\n afterTickToLabelConversion() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterTickToLabelConversion, [\n this\n ]);\n }\n beforeCalculateLabelRotation() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeCalculateLabelRotation, [\n this\n ]);\n }\n calculateLabelRotation() {\n const options = this.options;\n const tickOpts = options.ticks;\n const numTicks = getTicksLimit(this.ticks.length, options.ticks.maxTicksLimit);\n const minRotation = tickOpts.minRotation || 0;\n const maxRotation = tickOpts.maxRotation;\n let labelRotation = minRotation;\n let tickWidth, maxHeight, maxLabelDiagonal;\n if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) {\n this.labelRotation = minRotation;\n return;\n }\n const labelSizes = this._getLabelSizes();\n const maxLabelWidth = labelSizes.widest.width;\n const maxLabelHeight = labelSizes.highest.height;\n const maxWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(this.chart.width - maxLabelWidth, 0, this.maxWidth);\n tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1);\n if (maxLabelWidth + 6 > tickWidth) {\n tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1));\n maxHeight = this.maxHeight - getTickMarkLength(options.grid) - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font);\n maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight);\n labelRotation = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.U)(Math.min(Math.asin((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)((labelSizes.highest.height + 6) / tickWidth, -1, 1)), Math.asin((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(maxLabelHeight / maxLabelDiagonal, -1, 1))));\n labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation));\n }\n this.labelRotation = labelRotation;\n }\n afterCalculateLabelRotation() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterCalculateLabelRotation, [\n this\n ]);\n }\n afterAutoSkip() {}\n beforeFit() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeFit, [\n this\n ]);\n }\n fit() {\n const minSize = {\n width: 0,\n height: 0\n };\n const { chart , options: { ticks: tickOpts , title: titleOpts , grid: gridOpts } } = this;\n const display = this._isVisible();\n const isHorizontal = this.isHorizontal();\n if (display) {\n const titleHeight = getTitleHeight(titleOpts, chart.options.font);\n if (isHorizontal) {\n minSize.width = this.maxWidth;\n minSize.height = getTickMarkLength(gridOpts) + titleHeight;\n } else {\n minSize.height = this.maxHeight;\n minSize.width = getTickMarkLength(gridOpts) + titleHeight;\n }\n if (tickOpts.display && this.ticks.length) {\n const { first , last , widest , highest } = this._getLabelSizes();\n const tickPadding = tickOpts.padding * 2;\n const angleRadians = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);\n const cos = Math.cos(angleRadians);\n const sin = Math.sin(angleRadians);\n if (isHorizontal) {\n const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height;\n minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding);\n } else {\n const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height;\n minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding);\n }\n this._calculatePadding(first, last, sin, cos);\n }\n }\n this._handleMargins();\n if (isHorizontal) {\n this.width = this._length = chart.width - this._margins.left - this._margins.right;\n this.height = minSize.height;\n } else {\n this.width = minSize.width;\n this.height = this._length = chart.height - this._margins.top - this._margins.bottom;\n }\n }\n _calculatePadding(first, last, sin, cos) {\n const { ticks: { align , padding } , position } = this.options;\n const isRotated = this.labelRotation !== 0;\n const labelsBelowTicks = position !== 'top' && this.axis === 'x';\n if (this.isHorizontal()) {\n const offsetLeft = this.getPixelForTick(0) - this.left;\n const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1);\n let paddingLeft = 0;\n let paddingRight = 0;\n if (isRotated) {\n if (labelsBelowTicks) {\n paddingLeft = cos * first.width;\n paddingRight = sin * last.height;\n } else {\n paddingLeft = sin * first.height;\n paddingRight = cos * last.width;\n }\n } else if (align === 'start') {\n paddingRight = last.width;\n } else if (align === 'end') {\n paddingLeft = first.width;\n } else if (align !== 'inner') {\n paddingLeft = first.width / 2;\n paddingRight = last.width / 2;\n }\n this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0);\n this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0);\n } else {\n let paddingTop = last.height / 2;\n let paddingBottom = first.height / 2;\n if (align === 'start') {\n paddingTop = 0;\n paddingBottom = first.height;\n } else if (align === 'end') {\n paddingTop = last.height;\n paddingBottom = 0;\n }\n this.paddingTop = paddingTop + padding;\n this.paddingBottom = paddingBottom + padding;\n }\n }\n _handleMargins() {\n if (this._margins) {\n this._margins.left = Math.max(this.paddingLeft, this._margins.left);\n this._margins.top = Math.max(this.paddingTop, this._margins.top);\n this._margins.right = Math.max(this.paddingRight, this._margins.right);\n this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom);\n }\n }\n afterFit() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterFit, [\n this\n ]);\n }\n isHorizontal() {\n const { axis , position } = this.options;\n return position === 'top' || position === 'bottom' || axis === 'x';\n }\n isFullSize() {\n return this.options.fullSize;\n }\n _convertTicksToLabels(ticks) {\n this.beforeTickToLabelConversion();\n this.generateTickLabels(ticks);\n let i, ilen;\n for(i = 0, ilen = ticks.length; i < ilen; i++){\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(ticks[i].label)) {\n ticks.splice(i, 1);\n ilen--;\n i--;\n }\n }\n this.afterTickToLabelConversion();\n }\n _getLabelSizes() {\n let labelSizes = this._labelSizes;\n if (!labelSizes) {\n const sampleSize = this.options.ticks.sampleSize;\n let ticks = this.ticks;\n if (sampleSize < ticks.length) {\n ticks = sample(ticks, sampleSize);\n }\n this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length, this.options.ticks.maxTicksLimit);\n }\n return labelSizes;\n }\n _computeLabelSizes(ticks, length, maxTicksLimit) {\n const { ctx , _longestTextCache: caches } = this;\n const widths = [];\n const heights = [];\n const increment = Math.floor(length / getTicksLimit(length, maxTicksLimit));\n let widestLabelSize = 0;\n let highestLabelSize = 0;\n let i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel;\n for(i = 0; i < length; i += increment){\n label = ticks[i].label;\n tickFont = this._resolveTickFontOptions(i);\n ctx.font = fontString = tickFont.string;\n cache = caches[fontString] = caches[fontString] || {\n data: {},\n gc: []\n };\n lineHeight = tickFont.lineHeight;\n width = height = 0;\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(label) && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) {\n width = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, cache.data, cache.gc, width, label);\n height = lineHeight;\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) {\n for(j = 0, jlen = label.length; j < jlen; ++j){\n nestedLabel = label[j];\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(nestedLabel) && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(nestedLabel)) {\n width = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, cache.data, cache.gc, width, nestedLabel);\n height += lineHeight;\n }\n }\n }\n widths.push(width);\n heights.push(height);\n widestLabelSize = Math.max(width, widestLabelSize);\n highestLabelSize = Math.max(height, highestLabelSize);\n }\n garbageCollect(caches, length);\n const widest = widths.indexOf(widestLabelSize);\n const highest = heights.indexOf(highestLabelSize);\n const valueAt = (idx)=>({\n width: widths[idx] || 0,\n height: heights[idx] || 0\n });\n return {\n first: valueAt(0),\n last: valueAt(length - 1),\n widest: valueAt(widest),\n highest: valueAt(highest),\n widths,\n heights\n };\n }\n getLabelForValue(value) {\n return value;\n }\n getPixelForValue(value, index) {\n return NaN;\n }\n getValueForPixel(pixel) {}\n getPixelForTick(index) {\n const ticks = this.ticks;\n if (index < 0 || index > ticks.length - 1) {\n return null;\n }\n return this.getPixelForValue(ticks[index].value);\n }\n getPixelForDecimal(decimal) {\n if (this._reversePixels) {\n decimal = 1 - decimal;\n }\n const pixel = this._startPixel + decimal * this._length;\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.W)(this._alignToPixels ? (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(this.chart, pixel, 0) : pixel);\n }\n getDecimalForPixel(pixel) {\n const decimal = (pixel - this._startPixel) / this._length;\n return this._reversePixels ? 1 - decimal : decimal;\n }\n getBasePixel() {\n return this.getPixelForValue(this.getBaseValue());\n }\n getBaseValue() {\n const { min , max } = this;\n return min < 0 && max < 0 ? max : min > 0 && max > 0 ? min : 0;\n }\n getContext(index) {\n const ticks = this.ticks || [];\n if (index >= 0 && index < ticks.length) {\n const tick = ticks[index];\n return tick.$context || (tick.$context = createTickContext(this.getContext(), index, tick));\n }\n return this.$context || (this.$context = createScaleContext(this.chart.getContext(), this));\n }\n _tickSize() {\n const optionTicks = this.options.ticks;\n const rot = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);\n const cos = Math.abs(Math.cos(rot));\n const sin = Math.abs(Math.sin(rot));\n const labelSizes = this._getLabelSizes();\n const padding = optionTicks.autoSkipPadding || 0;\n const w = labelSizes ? labelSizes.widest.width + padding : 0;\n const h = labelSizes ? labelSizes.highest.height + padding : 0;\n return this.isHorizontal() ? h * cos > w * sin ? w / cos : h / sin : h * sin < w * cos ? h / cos : w / sin;\n }\n _isVisible() {\n const display = this.options.display;\n if (display !== 'auto') {\n return !!display;\n }\n return this.getMatchingVisibleMetas().length > 0;\n }\n _computeGridLineItems(chartArea) {\n const axis = this.axis;\n const chart = this.chart;\n const options = this.options;\n const { grid , position , border } = options;\n const offset = grid.offset;\n const isHorizontal = this.isHorizontal();\n const ticks = this.ticks;\n const ticksLength = ticks.length + (offset ? 1 : 0);\n const tl = getTickMarkLength(grid);\n const items = [];\n const borderOpts = border.setContext(this.getContext());\n const axisWidth = borderOpts.display ? borderOpts.width : 0;\n const axisHalfWidth = axisWidth / 2;\n const alignBorderValue = function(pixel) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, pixel, axisWidth);\n };\n let borderValue, i, lineValue, alignedLineValue;\n let tx1, ty1, tx2, ty2, x1, y1, x2, y2;\n if (position === 'top') {\n borderValue = alignBorderValue(this.bottom);\n ty1 = this.bottom - tl;\n ty2 = borderValue - axisHalfWidth;\n y1 = alignBorderValue(chartArea.top) + axisHalfWidth;\n y2 = chartArea.bottom;\n } else if (position === 'bottom') {\n borderValue = alignBorderValue(this.top);\n y1 = chartArea.top;\n y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth;\n ty1 = borderValue + axisHalfWidth;\n ty2 = this.top + tl;\n } else if (position === 'left') {\n borderValue = alignBorderValue(this.right);\n tx1 = this.right - tl;\n tx2 = borderValue - axisHalfWidth;\n x1 = alignBorderValue(chartArea.left) + axisHalfWidth;\n x2 = chartArea.right;\n } else if (position === 'right') {\n borderValue = alignBorderValue(this.left);\n x1 = chartArea.left;\n x2 = alignBorderValue(chartArea.right) - axisHalfWidth;\n tx1 = borderValue + axisHalfWidth;\n tx2 = this.left + tl;\n } else if (axis === 'x') {\n if (position === 'center') {\n borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5);\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {\n const positionAxisID = Object.keys(position)[0];\n const value = position[positionAxisID];\n borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));\n }\n y1 = chartArea.top;\n y2 = chartArea.bottom;\n ty1 = borderValue + axisHalfWidth;\n ty2 = ty1 + tl;\n } else if (axis === 'y') {\n if (position === 'center') {\n borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2);\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {\n const positionAxisID = Object.keys(position)[0];\n const value = position[positionAxisID];\n borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));\n }\n tx1 = borderValue - axisHalfWidth;\n tx2 = tx1 - tl;\n x1 = chartArea.left;\n x2 = chartArea.right;\n }\n const limit = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.ticks.maxTicksLimit, ticksLength);\n const step = Math.max(1, Math.ceil(ticksLength / limit));\n for(i = 0; i < ticksLength; i += step){\n const context = this.getContext(i);\n const optsAtIndex = grid.setContext(context);\n const optsAtIndexBorder = border.setContext(context);\n const lineWidth = optsAtIndex.lineWidth;\n const lineColor = optsAtIndex.color;\n const borderDash = optsAtIndexBorder.dash || [];\n const borderDashOffset = optsAtIndexBorder.dashOffset;\n const tickWidth = optsAtIndex.tickWidth;\n const tickColor = optsAtIndex.tickColor;\n const tickBorderDash = optsAtIndex.tickBorderDash || [];\n const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset;\n lineValue = getPixelForGridLine(this, i, offset);\n if (lineValue === undefined) {\n continue;\n }\n alignedLineValue = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, lineValue, lineWidth);\n if (isHorizontal) {\n tx1 = tx2 = x1 = x2 = alignedLineValue;\n } else {\n ty1 = ty2 = y1 = y2 = alignedLineValue;\n }\n items.push({\n tx1,\n ty1,\n tx2,\n ty2,\n x1,\n y1,\n x2,\n y2,\n width: lineWidth,\n color: lineColor,\n borderDash,\n borderDashOffset,\n tickWidth,\n tickColor,\n tickBorderDash,\n tickBorderDashOffset\n });\n }\n this._ticksLength = ticksLength;\n this._borderValue = borderValue;\n return items;\n }\n _computeLabelItems(chartArea) {\n const axis = this.axis;\n const options = this.options;\n const { position , ticks: optionTicks } = options;\n const isHorizontal = this.isHorizontal();\n const ticks = this.ticks;\n const { align , crossAlign , padding , mirror } = optionTicks;\n const tl = getTickMarkLength(options.grid);\n const tickAndPadding = tl + padding;\n const hTickAndPadding = mirror ? -padding : tickAndPadding;\n const rotation = -(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);\n const items = [];\n let i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;\n let textBaseline = 'middle';\n if (position === 'top') {\n y = this.bottom - hTickAndPadding;\n textAlign = this._getXAxisLabelAlignment();\n } else if (position === 'bottom') {\n y = this.top + hTickAndPadding;\n textAlign = this._getXAxisLabelAlignment();\n } else if (position === 'left') {\n const ret = this._getYAxisLabelAlignment(tl);\n textAlign = ret.textAlign;\n x = ret.x;\n } else if (position === 'right') {\n const ret = this._getYAxisLabelAlignment(tl);\n textAlign = ret.textAlign;\n x = ret.x;\n } else if (axis === 'x') {\n if (position === 'center') {\n y = (chartArea.top + chartArea.bottom) / 2 + tickAndPadding;\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {\n const positionAxisID = Object.keys(position)[0];\n const value = position[positionAxisID];\n y = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;\n }\n textAlign = this._getXAxisLabelAlignment();\n } else if (axis === 'y') {\n if (position === 'center') {\n x = (chartArea.left + chartArea.right) / 2 - tickAndPadding;\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {\n const positionAxisID = Object.keys(position)[0];\n const value = position[positionAxisID];\n x = this.chart.scales[positionAxisID].getPixelForValue(value);\n }\n textAlign = this._getYAxisLabelAlignment(tl).textAlign;\n }\n if (axis === 'y') {\n if (align === 'start') {\n textBaseline = 'top';\n } else if (align === 'end') {\n textBaseline = 'bottom';\n }\n }\n const labelSizes = this._getLabelSizes();\n for(i = 0, ilen = ticks.length; i < ilen; ++i){\n tick = ticks[i];\n label = tick.label;\n const optsAtIndex = optionTicks.setContext(this.getContext(i));\n pixel = this.getPixelForTick(i) + optionTicks.labelOffset;\n font = this._resolveTickFontOptions(i);\n lineHeight = font.lineHeight;\n lineCount = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label.length : 1;\n const halfCount = lineCount / 2;\n const color = optsAtIndex.color;\n const strokeColor = optsAtIndex.textStrokeColor;\n const strokeWidth = optsAtIndex.textStrokeWidth;\n let tickTextAlign = textAlign;\n if (isHorizontal) {\n x = pixel;\n if (textAlign === 'inner') {\n if (i === ilen - 1) {\n tickTextAlign = !this.options.reverse ? 'right' : 'left';\n } else if (i === 0) {\n tickTextAlign = !this.options.reverse ? 'left' : 'right';\n } else {\n tickTextAlign = 'center';\n }\n }\n if (position === 'top') {\n if (crossAlign === 'near' || rotation !== 0) {\n textOffset = -lineCount * lineHeight + lineHeight / 2;\n } else if (crossAlign === 'center') {\n textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight;\n } else {\n textOffset = -labelSizes.highest.height + lineHeight / 2;\n }\n } else {\n if (crossAlign === 'near' || rotation !== 0) {\n textOffset = lineHeight / 2;\n } else if (crossAlign === 'center') {\n textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight;\n } else {\n textOffset = labelSizes.highest.height - lineCount * lineHeight;\n }\n }\n if (mirror) {\n textOffset *= -1;\n }\n if (rotation !== 0 && !optsAtIndex.showLabelBackdrop) {\n x += lineHeight / 2 * Math.sin(rotation);\n }\n } else {\n y = pixel;\n textOffset = (1 - lineCount) * lineHeight / 2;\n }\n let backdrop;\n if (optsAtIndex.showLabelBackdrop) {\n const labelPadding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(optsAtIndex.backdropPadding);\n const height = labelSizes.heights[i];\n const width = labelSizes.widths[i];\n let top = textOffset - labelPadding.top;\n let left = 0 - labelPadding.left;\n switch(textBaseline){\n case 'middle':\n top -= height / 2;\n break;\n case 'bottom':\n top -= height;\n break;\n }\n switch(textAlign){\n case 'center':\n left -= width / 2;\n break;\n case 'right':\n left -= width;\n break;\n case 'inner':\n if (i === ilen - 1) {\n left -= width;\n } else if (i > 0) {\n left -= width / 2;\n }\n break;\n }\n backdrop = {\n left,\n top,\n width: width + labelPadding.width,\n height: height + labelPadding.height,\n color: optsAtIndex.backdropColor\n };\n }\n items.push({\n label,\n font,\n textOffset,\n options: {\n rotation,\n color,\n strokeColor,\n strokeWidth,\n textAlign: tickTextAlign,\n textBaseline,\n translation: [\n x,\n y\n ],\n backdrop\n }\n });\n }\n return items;\n }\n _getXAxisLabelAlignment() {\n const { position , ticks } = this.options;\n const rotation = -(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);\n if (rotation) {\n return position === 'top' ? 'left' : 'right';\n }\n let align = 'center';\n if (ticks.align === 'start') {\n align = 'left';\n } else if (ticks.align === 'end') {\n align = 'right';\n } else if (ticks.align === 'inner') {\n align = 'inner';\n }\n return align;\n }\n _getYAxisLabelAlignment(tl) {\n const { position , ticks: { crossAlign , mirror , padding } } = this.options;\n const labelSizes = this._getLabelSizes();\n const tickAndPadding = tl + padding;\n const widest = labelSizes.widest.width;\n let textAlign;\n let x;\n if (position === 'left') {\n if (mirror) {\n x = this.right + padding;\n if (crossAlign === 'near') {\n textAlign = 'left';\n } else if (crossAlign === 'center') {\n textAlign = 'center';\n x += widest / 2;\n } else {\n textAlign = 'right';\n x += widest;\n }\n } else {\n x = this.right - tickAndPadding;\n if (crossAlign === 'near') {\n textAlign = 'right';\n } else if (crossAlign === 'center') {\n textAlign = 'center';\n x -= widest / 2;\n } else {\n textAlign = 'left';\n x = this.left;\n }\n }\n } else if (position === 'right') {\n if (mirror) {\n x = this.left + padding;\n if (crossAlign === 'near') {\n textAlign = 'right';\n } else if (crossAlign === 'center') {\n textAlign = 'center';\n x -= widest / 2;\n } else {\n textAlign = 'left';\n x -= widest;\n }\n } else {\n x = this.left + tickAndPadding;\n if (crossAlign === 'near') {\n textAlign = 'left';\n } else if (crossAlign === 'center') {\n textAlign = 'center';\n x += widest / 2;\n } else {\n textAlign = 'right';\n x = this.right;\n }\n }\n } else {\n textAlign = 'right';\n }\n return {\n textAlign,\n x\n };\n }\n _computeLabelArea() {\n if (this.options.ticks.mirror) {\n return;\n }\n const chart = this.chart;\n const position = this.options.position;\n if (position === 'left' || position === 'right') {\n return {\n top: 0,\n left: this.left,\n bottom: chart.height,\n right: this.right\n };\n }\n if (position === 'top' || position === 'bottom') {\n return {\n top: this.top,\n left: 0,\n bottom: this.bottom,\n right: chart.width\n };\n }\n }\n drawBackground() {\n const { ctx , options: { backgroundColor } , left , top , width , height } = this;\n if (backgroundColor) {\n ctx.save();\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(left, top, width, height);\n ctx.restore();\n }\n }\n getLineWidthForValue(value) {\n const grid = this.options.grid;\n if (!this._isVisible() || !grid.display) {\n return 0;\n }\n const ticks = this.ticks;\n const index = ticks.findIndex((t)=>t.value === value);\n if (index >= 0) {\n const opts = grid.setContext(this.getContext(index));\n return opts.lineWidth;\n }\n return 0;\n }\n drawGrid(chartArea) {\n const grid = this.options.grid;\n const ctx = this.ctx;\n const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea));\n let i, ilen;\n const drawLine = (p1, p2, style)=>{\n if (!style.width || !style.color) {\n return;\n }\n ctx.save();\n ctx.lineWidth = style.width;\n ctx.strokeStyle = style.color;\n ctx.setLineDash(style.borderDash || []);\n ctx.lineDashOffset = style.borderDashOffset;\n ctx.beginPath();\n ctx.moveTo(p1.x, p1.y);\n ctx.lineTo(p2.x, p2.y);\n ctx.stroke();\n ctx.restore();\n };\n if (grid.display) {\n for(i = 0, ilen = items.length; i < ilen; ++i){\n const item = items[i];\n if (grid.drawOnChartArea) {\n drawLine({\n x: item.x1,\n y: item.y1\n }, {\n x: item.x2,\n y: item.y2\n }, item);\n }\n if (grid.drawTicks) {\n drawLine({\n x: item.tx1,\n y: item.ty1\n }, {\n x: item.tx2,\n y: item.ty2\n }, {\n color: item.tickColor,\n width: item.tickWidth,\n borderDash: item.tickBorderDash,\n borderDashOffset: item.tickBorderDashOffset\n });\n }\n }\n }\n }\n drawBorder() {\n const { chart , ctx , options: { border , grid } } = this;\n const borderOpts = border.setContext(this.getContext());\n const axisWidth = border.display ? borderOpts.width : 0;\n if (!axisWidth) {\n return;\n }\n const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth;\n const borderValue = this._borderValue;\n let x1, x2, y1, y2;\n if (this.isHorizontal()) {\n x1 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.left, axisWidth) - axisWidth / 2;\n x2 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.right, lastLineWidth) + lastLineWidth / 2;\n y1 = y2 = borderValue;\n } else {\n y1 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.top, axisWidth) - axisWidth / 2;\n y2 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.bottom, lastLineWidth) + lastLineWidth / 2;\n x1 = x2 = borderValue;\n }\n ctx.save();\n ctx.lineWidth = borderOpts.width;\n ctx.strokeStyle = borderOpts.color;\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n ctx.restore();\n }\n drawLabels(chartArea) {\n const optionTicks = this.options.ticks;\n if (!optionTicks.display) {\n return;\n }\n const ctx = this.ctx;\n const area = this._computeLabelArea();\n if (area) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, area);\n }\n const items = this.getLabelItems(chartArea);\n for (const item of items){\n const renderTextOptions = item.options;\n const tickFont = item.font;\n const label = item.label;\n const y = item.textOffset;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, label, 0, y, tickFont, renderTextOptions);\n }\n if (area) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);\n }\n }\n drawTitle() {\n const { ctx , options: { position , title , reverse } } = this;\n if (!title.display) {\n return;\n }\n const font = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(title.font);\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(title.padding);\n const align = title.align;\n let offset = font.lineHeight / 2;\n if (position === 'bottom' || position === 'center' || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {\n offset += padding.bottom;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(title.text)) {\n offset += font.lineHeight * (title.text.length - 1);\n }\n } else {\n offset += padding.top;\n }\n const { titleX , titleY , maxWidth , rotation } = titleArgs(this, offset, position, align);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, title.text, 0, 0, font, {\n color: title.color,\n maxWidth,\n rotation,\n textAlign: titleAlign(align, position, reverse),\n textBaseline: 'middle',\n translation: [\n titleX,\n titleY\n ]\n });\n }\n draw(chartArea) {\n if (!this._isVisible()) {\n return;\n }\n this.drawBackground();\n this.drawGrid(chartArea);\n this.drawBorder();\n this.drawTitle();\n this.drawLabels(chartArea);\n }\n _layers() {\n const opts = this.options;\n const tz = opts.ticks && opts.ticks.z || 0;\n const gz = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(opts.grid && opts.grid.z, -1);\n const bz = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(opts.border && opts.border.z, 0);\n if (!this._isVisible() || this.draw !== Scale.prototype.draw) {\n return [\n {\n z: tz,\n draw: (chartArea)=>{\n this.draw(chartArea);\n }\n }\n ];\n }\n return [\n {\n z: gz,\n draw: (chartArea)=>{\n this.drawBackground();\n this.drawGrid(chartArea);\n this.drawTitle();\n }\n },\n {\n z: bz,\n draw: ()=>{\n this.drawBorder();\n }\n },\n {\n z: tz,\n draw: (chartArea)=>{\n this.drawLabels(chartArea);\n }\n }\n ];\n }\n getMatchingVisibleMetas(type) {\n const metas = this.chart.getSortedVisibleDatasetMetas();\n const axisID = this.axis + 'AxisID';\n const result = [];\n let i, ilen;\n for(i = 0, ilen = metas.length; i < ilen; ++i){\n const meta = metas[i];\n if (meta[axisID] === this.id && (!type || meta.type === type)) {\n result.push(meta);\n }\n }\n return result;\n }\n _resolveTickFontOptions(index) {\n const opts = this.options.ticks.setContext(this.getContext(index));\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font);\n }\n _maxDigits() {\n const fontSize = this._resolveTickFontOptions(0).lineHeight;\n return (this.isHorizontal() ? this.width : this.height) / fontSize;\n }\n}\n\nclass TypedRegistry {\n constructor(type, scope, override){\n this.type = type;\n this.scope = scope;\n this.override = override;\n this.items = Object.create(null);\n }\n isForType(type) {\n return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);\n }\n register(item) {\n const proto = Object.getPrototypeOf(item);\n let parentScope;\n if (isIChartComponent(proto)) {\n parentScope = this.register(proto);\n }\n const items = this.items;\n const id = item.id;\n const scope = this.scope + '.' + id;\n if (!id) {\n throw new Error('class does not have id: ' + item);\n }\n if (id in items) {\n return scope;\n }\n items[id] = item;\n registerDefaults(item, scope, parentScope);\n if (this.override) {\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.override(item.id, item.overrides);\n }\n return scope;\n }\n get(id) {\n return this.items[id];\n }\n unregister(item) {\n const items = this.items;\n const id = item.id;\n const scope = this.scope;\n if (id in items) {\n delete items[id];\n }\n if (scope && id in _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d[scope]) {\n delete _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d[scope][id];\n if (this.override) {\n delete _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[id];\n }\n }\n }\n}\nfunction registerDefaults(item, scope, parentScope) {\n const itemDefaults = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a4)(Object.create(null), [\n parentScope ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.get(parentScope) : {},\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.get(scope),\n item.defaults\n ]);\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.set(scope, itemDefaults);\n if (item.defaultRoutes) {\n routeDefaults(scope, item.defaultRoutes);\n }\n if (item.descriptors) {\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.describe(scope, item.descriptors);\n }\n}\nfunction routeDefaults(scope, routes) {\n Object.keys(routes).forEach((property)=>{\n const propertyParts = property.split('.');\n const sourceName = propertyParts.pop();\n const sourceScope = [\n scope\n ].concat(propertyParts).join('.');\n const parts = routes[property].split('.');\n const targetName = parts.pop();\n const targetScope = parts.join('.');\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.route(sourceScope, sourceName, targetScope, targetName);\n });\n}\nfunction isIChartComponent(proto) {\n return 'id' in proto && 'defaults' in proto;\n}\n\nclass Registry {\n constructor(){\n this.controllers = new TypedRegistry(DatasetController, 'datasets', true);\n this.elements = new TypedRegistry(Element, 'elements');\n this.plugins = new TypedRegistry(Object, 'plugins');\n this.scales = new TypedRegistry(Scale, 'scales');\n this._typedRegistries = [\n this.controllers,\n this.scales,\n this.elements\n ];\n }\n add(...args) {\n this._each('register', args);\n }\n remove(...args) {\n this._each('unregister', args);\n }\n addControllers(...args) {\n this._each('register', args, this.controllers);\n }\n addElements(...args) {\n this._each('register', args, this.elements);\n }\n addPlugins(...args) {\n this._each('register', args, this.plugins);\n }\n addScales(...args) {\n this._each('register', args, this.scales);\n }\n getController(id) {\n return this._get(id, this.controllers, 'controller');\n }\n getElement(id) {\n return this._get(id, this.elements, 'element');\n }\n getPlugin(id) {\n return this._get(id, this.plugins, 'plugin');\n }\n getScale(id) {\n return this._get(id, this.scales, 'scale');\n }\n removeControllers(...args) {\n this._each('unregister', args, this.controllers);\n }\n removeElements(...args) {\n this._each('unregister', args, this.elements);\n }\n removePlugins(...args) {\n this._each('unregister', args, this.plugins);\n }\n removeScales(...args) {\n this._each('unregister', args, this.scales);\n }\n _each(method, args, typedRegistry) {\n [\n ...args\n ].forEach((arg)=>{\n const reg = typedRegistry || this._getRegistryForType(arg);\n if (typedRegistry || reg.isForType(arg) || reg === this.plugins && arg.id) {\n this._exec(method, reg, arg);\n } else {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(arg, (item)=>{\n const itemReg = typedRegistry || this._getRegistryForType(item);\n this._exec(method, itemReg, item);\n });\n }\n });\n }\n _exec(method, registry, component) {\n const camelMethod = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a5)(method);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(component['before' + camelMethod], [], component);\n registry[method](component);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(component['after' + camelMethod], [], component);\n }\n _getRegistryForType(type) {\n for(let i = 0; i < this._typedRegistries.length; i++){\n const reg = this._typedRegistries[i];\n if (reg.isForType(type)) {\n return reg;\n }\n }\n return this.plugins;\n }\n _get(id, typedRegistry, type) {\n const item = typedRegistry.get(id);\n if (item === undefined) {\n throw new Error('\"' + id + '\" is not a registered ' + type + '.');\n }\n return item;\n }\n}\nvar registry = /* #__PURE__ */ new Registry();\n\nclass PluginService {\n constructor(){\n this._init = [];\n }\n notify(chart, hook, args, filter) {\n if (hook === 'beforeInit') {\n this._init = this._createDescriptors(chart, true);\n this._notify(this._init, chart, 'install');\n }\n const descriptors = filter ? this._descriptors(chart).filter(filter) : this._descriptors(chart);\n const result = this._notify(descriptors, chart, hook, args);\n if (hook === 'afterDestroy') {\n this._notify(descriptors, chart, 'stop');\n this._notify(this._init, chart, 'uninstall');\n }\n return result;\n }\n _notify(descriptors, chart, hook, args) {\n args = args || {};\n for (const descriptor of descriptors){\n const plugin = descriptor.plugin;\n const method = plugin[hook];\n const params = [\n chart,\n args,\n descriptor.options\n ];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(method, params, plugin) === false && args.cancelable) {\n return false;\n }\n }\n return true;\n }\n invalidate() {\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(this._cache)) {\n this._oldCache = this._cache;\n this._cache = undefined;\n }\n }\n _descriptors(chart) {\n if (this._cache) {\n return this._cache;\n }\n const descriptors = this._cache = this._createDescriptors(chart);\n this._notifyStateChanges(chart);\n return descriptors;\n }\n _createDescriptors(chart, all) {\n const config = chart && chart.config;\n const options = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(config.options && config.options.plugins, {});\n const plugins = allPlugins(config);\n return options === false && !all ? [] : createDescriptors(chart, plugins, options, all);\n }\n _notifyStateChanges(chart) {\n const previousDescriptors = this._oldCache || [];\n const descriptors = this._cache;\n const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.plugin.id === y.plugin.id));\n this._notify(diff(previousDescriptors, descriptors), chart, 'stop');\n this._notify(diff(descriptors, previousDescriptors), chart, 'start');\n }\n}\n function allPlugins(config) {\n const localIds = {};\n const plugins = [];\n const keys = Object.keys(registry.plugins.items);\n for(let i = 0; i < keys.length; i++){\n plugins.push(registry.getPlugin(keys[i]));\n }\n const local = config.plugins || [];\n for(let i = 0; i < local.length; i++){\n const plugin = local[i];\n if (plugins.indexOf(plugin) === -1) {\n plugins.push(plugin);\n localIds[plugin.id] = true;\n }\n }\n return {\n plugins,\n localIds\n };\n}\nfunction getOpts(options, all) {\n if (!all && options === false) {\n return null;\n }\n if (options === true) {\n return {};\n }\n return options;\n}\nfunction createDescriptors(chart, { plugins , localIds }, options, all) {\n const result = [];\n const context = chart.getContext();\n for (const plugin of plugins){\n const id = plugin.id;\n const opts = getOpts(options[id], all);\n if (opts === null) {\n continue;\n }\n result.push({\n plugin,\n options: pluginOpts(chart.config, {\n plugin,\n local: localIds[id]\n }, opts, context)\n });\n }\n return result;\n}\nfunction pluginOpts(config, { plugin , local }, opts, context) {\n const keys = config.pluginScopeKeys(plugin);\n const scopes = config.getOptionScopes(opts, keys);\n if (local && plugin.defaults) {\n scopes.push(plugin.defaults);\n }\n return config.createResolver(scopes, context, [\n ''\n ], {\n scriptable: false,\n indexable: false,\n allKeys: true\n });\n}\n\nfunction getIndexAxis(type, options) {\n const datasetDefaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {};\n const datasetOptions = (options.datasets || {})[type] || {};\n return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x';\n}\nfunction getAxisFromDefaultScaleID(id, indexAxis) {\n let axis = id;\n if (id === '_index_') {\n axis = indexAxis;\n } else if (id === '_value_') {\n axis = indexAxis === 'x' ? 'y' : 'x';\n }\n return axis;\n}\nfunction getDefaultScaleIDFromAxis(axis, indexAxis) {\n return axis === indexAxis ? '_index_' : '_value_';\n}\nfunction idMatchesAxis(id) {\n if (id === 'x' || id === 'y' || id === 'r') {\n return id;\n }\n}\nfunction axisFromPosition(position) {\n if (position === 'top' || position === 'bottom') {\n return 'x';\n }\n if (position === 'left' || position === 'right') {\n return 'y';\n }\n}\nfunction determineAxis(id, ...scaleOptions) {\n if (idMatchesAxis(id)) {\n return id;\n }\n for (const opts of scaleOptions){\n const axis = opts.axis || axisFromPosition(opts.position) || id.length > 1 && idMatchesAxis(id[0].toLowerCase());\n if (axis) {\n return axis;\n }\n }\n throw new Error(`Cannot determine type of '${id}' axis. Please provide 'axis' or 'position' option.`);\n}\nfunction getAxisFromDataset(id, axis, dataset) {\n if (dataset[axis + 'AxisID'] === id) {\n return {\n axis\n };\n }\n}\nfunction retrieveAxisFromDatasets(id, config) {\n if (config.data && config.data.datasets) {\n const boundDs = config.data.datasets.filter((d)=>d.xAxisID === id || d.yAxisID === id);\n if (boundDs.length) {\n return getAxisFromDataset(id, 'x', boundDs[0]) || getAxisFromDataset(id, 'y', boundDs[0]);\n }\n }\n return {};\n}\nfunction mergeScaleConfig(config, options) {\n const chartDefaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[config.type] || {\n scales: {}\n };\n const configScales = options.scales || {};\n const chartIndexAxis = getIndexAxis(config.type, options);\n const scales = Object.create(null);\n Object.keys(configScales).forEach((id)=>{\n const scaleConf = configScales[id];\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(scaleConf)) {\n return console.error(`Invalid scale configuration for scale: ${id}`);\n }\n if (scaleConf._proxy) {\n return console.warn(`Ignoring resolver passed as options for scale: ${id}`);\n }\n const axis = determineAxis(id, scaleConf, retrieveAxisFromDatasets(id, config), _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.scales[scaleConf.type]);\n const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis);\n const defaultScaleOptions = chartDefaults.scales || {};\n scales[id] = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(Object.create(null), [\n {\n axis\n },\n scaleConf,\n defaultScaleOptions[axis],\n defaultScaleOptions[defaultId]\n ]);\n });\n config.data.datasets.forEach((dataset)=>{\n const type = dataset.type || config.type;\n const indexAxis = dataset.indexAxis || getIndexAxis(type, options);\n const datasetDefaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {};\n const defaultScaleOptions = datasetDefaults.scales || {};\n Object.keys(defaultScaleOptions).forEach((defaultID)=>{\n const axis = getAxisFromDefaultScaleID(defaultID, indexAxis);\n const id = dataset[axis + 'AxisID'] || axis;\n scales[id] = scales[id] || Object.create(null);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(scales[id], [\n {\n axis\n },\n configScales[id],\n defaultScaleOptions[defaultID]\n ]);\n });\n });\n Object.keys(scales).forEach((key)=>{\n const scale = scales[key];\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(scale, [\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.scales[scale.type],\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.scale\n ]);\n });\n return scales;\n}\nfunction initOptions(config) {\n const options = config.options || (config.options = {});\n options.plugins = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.plugins, {});\n options.scales = mergeScaleConfig(config, options);\n}\nfunction initData(data) {\n data = data || {};\n data.datasets = data.datasets || [];\n data.labels = data.labels || [];\n return data;\n}\nfunction initConfig(config) {\n config = config || {};\n config.data = initData(config.data);\n initOptions(config);\n return config;\n}\nconst keyCache = new Map();\nconst keysCached = new Set();\nfunction cachedKeys(cacheKey, generate) {\n let keys = keyCache.get(cacheKey);\n if (!keys) {\n keys = generate();\n keyCache.set(cacheKey, keys);\n keysCached.add(keys);\n }\n return keys;\n}\nconst addIfFound = (set, obj, key)=>{\n const opts = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, key);\n if (opts !== undefined) {\n set.add(opts);\n }\n};\nclass Config {\n constructor(config){\n this._config = initConfig(config);\n this._scopeCache = new Map();\n this._resolverCache = new Map();\n }\n get platform() {\n return this._config.platform;\n }\n get type() {\n return this._config.type;\n }\n set type(type) {\n this._config.type = type;\n }\n get data() {\n return this._config.data;\n }\n set data(data) {\n this._config.data = initData(data);\n }\n get options() {\n return this._config.options;\n }\n set options(options) {\n this._config.options = options;\n }\n get plugins() {\n return this._config.plugins;\n }\n update() {\n const config = this._config;\n this.clearCache();\n initOptions(config);\n }\n clearCache() {\n this._scopeCache.clear();\n this._resolverCache.clear();\n }\n datasetScopeKeys(datasetType) {\n return cachedKeys(datasetType, ()=>[\n [\n `datasets.${datasetType}`,\n ''\n ]\n ]);\n }\n datasetAnimationScopeKeys(datasetType, transition) {\n return cachedKeys(`${datasetType}.transition.${transition}`, ()=>[\n [\n `datasets.${datasetType}.transitions.${transition}`,\n `transitions.${transition}`\n ],\n [\n `datasets.${datasetType}`,\n ''\n ]\n ]);\n }\n datasetElementScopeKeys(datasetType, elementType) {\n return cachedKeys(`${datasetType}-${elementType}`, ()=>[\n [\n `datasets.${datasetType}.elements.${elementType}`,\n `datasets.${datasetType}`,\n `elements.${elementType}`,\n ''\n ]\n ]);\n }\n pluginScopeKeys(plugin) {\n const id = plugin.id;\n const type = this.type;\n return cachedKeys(`${type}-plugin-${id}`, ()=>[\n [\n `plugins.${id}`,\n ...plugin.additionalOptionScopes || []\n ]\n ]);\n }\n _cachedScopes(mainScope, resetCache) {\n const _scopeCache = this._scopeCache;\n let cache = _scopeCache.get(mainScope);\n if (!cache || resetCache) {\n cache = new Map();\n _scopeCache.set(mainScope, cache);\n }\n return cache;\n }\n getOptionScopes(mainScope, keyLists, resetCache) {\n const { options , type } = this;\n const cache = this._cachedScopes(mainScope, resetCache);\n const cached = cache.get(keyLists);\n if (cached) {\n return cached;\n }\n const scopes = new Set();\n keyLists.forEach((keys)=>{\n if (mainScope) {\n scopes.add(mainScope);\n keys.forEach((key)=>addIfFound(scopes, mainScope, key));\n }\n keys.forEach((key)=>addIfFound(scopes, options, key));\n keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {}, key));\n keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d, key));\n keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a6, key));\n });\n const array = Array.from(scopes);\n if (array.length === 0) {\n array.push(Object.create(null));\n }\n if (keysCached.has(keyLists)) {\n cache.set(keyLists, array);\n }\n return array;\n }\n chartOptionScopes() {\n const { options , type } = this;\n return [\n options,\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {},\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {},\n {\n type\n },\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d,\n _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a6\n ];\n }\n resolveNamedOptions(scopes, names, context, prefixes = [\n ''\n ]) {\n const result = {\n $shared: true\n };\n const { resolver , subPrefixes } = getResolver(this._resolverCache, scopes, prefixes);\n let options = resolver;\n if (needContext(resolver, names)) {\n result.$shared = false;\n context = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(context) ? context() : context;\n const subResolver = this.createResolver(scopes, context, subPrefixes);\n options = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a8)(resolver, context, subResolver);\n }\n for (const prop of names){\n result[prop] = options[prop];\n }\n return result;\n }\n createResolver(scopes, context, prefixes = [\n ''\n ], descriptorDefaults) {\n const { resolver } = getResolver(this._resolverCache, scopes, prefixes);\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(context) ? (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a8)(resolver, context, undefined, descriptorDefaults) : resolver;\n }\n}\nfunction getResolver(resolverCache, scopes, prefixes) {\n let cache = resolverCache.get(scopes);\n if (!cache) {\n cache = new Map();\n resolverCache.set(scopes, cache);\n }\n const cacheKey = prefixes.join();\n let cached = cache.get(cacheKey);\n if (!cached) {\n const resolver = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a9)(scopes, prefixes);\n cached = {\n resolver,\n subPrefixes: prefixes.filter((p)=>!p.toLowerCase().includes('hover'))\n };\n cache.set(cacheKey, cached);\n }\n return cached;\n}\nconst hasFunction = (value)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(value) && Object.getOwnPropertyNames(value).some((key)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(value[key]));\nfunction needContext(proxy, names) {\n const { isScriptable , isIndexable } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aa)(proxy);\n for (const prop of names){\n const scriptable = isScriptable(prop);\n const indexable = isIndexable(prop);\n const value = (indexable || scriptable) && proxy[prop];\n if (scriptable && ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(value) || hasFunction(value)) || indexable && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(value)) {\n return true;\n }\n }\n return false;\n}\n\nvar version = \"4.5.0\";\n\nconst KNOWN_POSITIONS = [\n 'top',\n 'bottom',\n 'left',\n 'right',\n 'chartArea'\n];\nfunction positionIsHorizontal(position, axis) {\n return position === 'top' || position === 'bottom' || KNOWN_POSITIONS.indexOf(position) === -1 && axis === 'x';\n}\nfunction compare2Level(l1, l2) {\n return function(a, b) {\n return a[l1] === b[l1] ? a[l2] - b[l2] : a[l1] - b[l1];\n };\n}\nfunction onAnimationsComplete(context) {\n const chart = context.chart;\n const animationOptions = chart.options.animation;\n chart.notifyPlugins('afterRender');\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(animationOptions && animationOptions.onComplete, [\n context\n ], chart);\n}\nfunction onAnimationProgress(context) {\n const chart = context.chart;\n const animationOptions = chart.options.animation;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(animationOptions && animationOptions.onProgress, [\n context\n ], chart);\n}\n function getCanvas(item) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.M)() && typeof item === 'string') {\n item = document.getElementById(item);\n } else if (item && item.length) {\n item = item[0];\n }\n if (item && item.canvas) {\n item = item.canvas;\n }\n return item;\n}\nconst instances = {};\nconst getChart = (key)=>{\n const canvas = getCanvas(key);\n return Object.values(instances).filter((c)=>c.canvas === canvas).pop();\n};\nfunction moveNumericKeys(obj, start, move) {\n const keys = Object.keys(obj);\n for (const key of keys){\n const intKey = +key;\n if (intKey >= start) {\n const value = obj[key];\n delete obj[key];\n if (move > 0 || intKey > start) {\n obj[intKey + move] = value;\n }\n }\n }\n}\n function determineLastEvent(e, lastEvent, inChartArea, isClick) {\n if (!inChartArea || e.type === 'mouseout') {\n return null;\n }\n if (isClick) {\n return lastEvent;\n }\n return e;\n}\nclass Chart {\n static defaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d;\n static instances = instances;\n static overrides = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3;\n static registry = registry;\n static version = version;\n static getChart = getChart;\n static register(...items) {\n registry.add(...items);\n invalidatePlugins();\n }\n static unregister(...items) {\n registry.remove(...items);\n invalidatePlugins();\n }\n constructor(item, userConfig){\n const config = this.config = new Config(userConfig);\n const initialCanvas = getCanvas(item);\n const existingChart = getChart(initialCanvas);\n if (existingChart) {\n throw new Error('Canvas is already in use. Chart with ID \\'' + existingChart.id + '\\'' + ' must be destroyed before the canvas with ID \\'' + existingChart.canvas.id + '\\' can be reused.');\n }\n const options = config.createResolver(config.chartOptionScopes(), this.getContext());\n this.platform = new (config.platform || _detectPlatform(initialCanvas))();\n this.platform.updateConfig(config);\n const context = this.platform.acquireContext(initialCanvas, options.aspectRatio);\n const canvas = context && context.canvas;\n const height = canvas && canvas.height;\n const width = canvas && canvas.width;\n this.id = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ac)();\n this.ctx = context;\n this.canvas = canvas;\n this.width = width;\n this.height = height;\n this._options = options;\n this._aspectRatio = this.aspectRatio;\n this._layers = [];\n this._metasets = [];\n this._stacks = undefined;\n this.boxes = [];\n this.currentDevicePixelRatio = undefined;\n this.chartArea = undefined;\n this._active = [];\n this._lastEvent = undefined;\n this._listeners = {};\n this._responsiveListeners = undefined;\n this._sortedMetasets = [];\n this.scales = {};\n this._plugins = new PluginService();\n this.$proxies = {};\n this._hiddenIndices = {};\n this.attached = false;\n this._animationsDisabled = undefined;\n this.$context = undefined;\n this._doResize = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ad)((mode)=>this.update(mode), options.resizeDelay || 0);\n this._dataChanges = [];\n instances[this.id] = this;\n if (!context || !canvas) {\n console.error(\"Failed to create chart: can't acquire context from the given item\");\n return;\n }\n animator.listen(this, 'complete', onAnimationsComplete);\n animator.listen(this, 'progress', onAnimationProgress);\n this._initialize();\n if (this.attached) {\n this.update();\n }\n }\n get aspectRatio() {\n const { options: { aspectRatio , maintainAspectRatio } , width , height , _aspectRatio } = this;\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(aspectRatio)) {\n return aspectRatio;\n }\n if (maintainAspectRatio && _aspectRatio) {\n return _aspectRatio;\n }\n return height ? width / height : null;\n }\n get data() {\n return this.config.data;\n }\n set data(data) {\n this.config.data = data;\n }\n get options() {\n return this._options;\n }\n set options(options) {\n this.config.options = options;\n }\n get registry() {\n return registry;\n }\n _initialize() {\n this.notifyPlugins('beforeInit');\n if (this.options.responsive) {\n this.resize();\n } else {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ae)(this, this.options.devicePixelRatio);\n }\n this.bindEvents();\n this.notifyPlugins('afterInit');\n return this;\n }\n clear() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.af)(this.canvas, this.ctx);\n return this;\n }\n stop() {\n animator.stop(this);\n return this;\n }\n resize(width, height) {\n if (!animator.running(this)) {\n this._resize(width, height);\n } else {\n this._resizeBeforeDraw = {\n width,\n height\n };\n }\n }\n _resize(width, height) {\n const options = this.options;\n const canvas = this.canvas;\n const aspectRatio = options.maintainAspectRatio && this.aspectRatio;\n const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio);\n const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio();\n const mode = this.width ? 'resize' : 'attach';\n this.width = newSize.width;\n this.height = newSize.height;\n this._aspectRatio = this.aspectRatio;\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ae)(this, newRatio, true)) {\n return;\n }\n this.notifyPlugins('resize', {\n size: newSize\n });\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onResize, [\n this,\n newSize\n ], this);\n if (this.attached) {\n if (this._doResize(mode)) {\n this.render();\n }\n }\n }\n ensureScalesHaveIDs() {\n const options = this.options;\n const scalesOptions = options.scales || {};\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(scalesOptions, (axisOptions, axisID)=>{\n axisOptions.id = axisID;\n });\n }\n buildOrUpdateScales() {\n const options = this.options;\n const scaleOpts = options.scales;\n const scales = this.scales;\n const updated = Object.keys(scales).reduce((obj, id)=>{\n obj[id] = false;\n return obj;\n }, {});\n let items = [];\n if (scaleOpts) {\n items = items.concat(Object.keys(scaleOpts).map((id)=>{\n const scaleOptions = scaleOpts[id];\n const axis = determineAxis(id, scaleOptions);\n const isRadial = axis === 'r';\n const isHorizontal = axis === 'x';\n return {\n options: scaleOptions,\n dposition: isRadial ? 'chartArea' : isHorizontal ? 'bottom' : 'left',\n dtype: isRadial ? 'radialLinear' : isHorizontal ? 'category' : 'linear'\n };\n }));\n }\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(items, (item)=>{\n const scaleOptions = item.options;\n const id = scaleOptions.id;\n const axis = determineAxis(id, scaleOptions);\n const scaleType = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(scaleOptions.type, item.dtype);\n if (scaleOptions.position === undefined || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) {\n scaleOptions.position = item.dposition;\n }\n updated[id] = true;\n let scale = null;\n if (id in scales && scales[id].type === scaleType) {\n scale = scales[id];\n } else {\n const scaleClass = registry.getScale(scaleType);\n scale = new scaleClass({\n id,\n type: scaleType,\n ctx: this.ctx,\n chart: this\n });\n scales[scale.id] = scale;\n }\n scale.init(scaleOptions, options);\n });\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(updated, (hasUpdated, id)=>{\n if (!hasUpdated) {\n delete scales[id];\n }\n });\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(scales, (scale)=>{\n layouts.configure(this, scale, scale.options);\n layouts.addBox(this, scale);\n });\n }\n _updateMetasets() {\n const metasets = this._metasets;\n const numData = this.data.datasets.length;\n const numMeta = metasets.length;\n metasets.sort((a, b)=>a.index - b.index);\n if (numMeta > numData) {\n for(let i = numData; i < numMeta; ++i){\n this._destroyDatasetMeta(i);\n }\n metasets.splice(numData, numMeta - numData);\n }\n this._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));\n }\n _removeUnreferencedMetasets() {\n const { _metasets: metasets , data: { datasets } } = this;\n if (metasets.length > datasets.length) {\n delete this._stacks;\n }\n metasets.forEach((meta, index)=>{\n if (datasets.filter((x)=>x === meta._dataset).length === 0) {\n this._destroyDatasetMeta(index);\n }\n });\n }\n buildOrUpdateControllers() {\n const newControllers = [];\n const datasets = this.data.datasets;\n let i, ilen;\n this._removeUnreferencedMetasets();\n for(i = 0, ilen = datasets.length; i < ilen; i++){\n const dataset = datasets[i];\n let meta = this.getDatasetMeta(i);\n const type = dataset.type || this.config.type;\n if (meta.type && meta.type !== type) {\n this._destroyDatasetMeta(i);\n meta = this.getDatasetMeta(i);\n }\n meta.type = type;\n meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options);\n meta.order = dataset.order || 0;\n meta.index = i;\n meta.label = '' + dataset.label;\n meta.visible = this.isDatasetVisible(i);\n if (meta.controller) {\n meta.controller.updateIndex(i);\n meta.controller.linkScales();\n } else {\n const ControllerClass = registry.getController(type);\n const { datasetElementType , dataElementType } = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type];\n Object.assign(ControllerClass, {\n dataElementType: registry.getElement(dataElementType),\n datasetElementType: datasetElementType && registry.getElement(datasetElementType)\n });\n meta.controller = new ControllerClass(this, i);\n newControllers.push(meta.controller);\n }\n }\n this._updateMetasets();\n return newControllers;\n }\n _resetElements() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.data.datasets, (dataset, datasetIndex)=>{\n this.getDatasetMeta(datasetIndex).controller.reset();\n }, this);\n }\n reset() {\n this._resetElements();\n this.notifyPlugins('reset');\n }\n update(mode) {\n const config = this.config;\n config.update();\n const options = this._options = config.createResolver(config.chartOptionScopes(), this.getContext());\n const animsDisabled = this._animationsDisabled = !options.animation;\n this._updateScales();\n this._checkEventBindings();\n this._updateHiddenIndices();\n this._plugins.invalidate();\n if (this.notifyPlugins('beforeUpdate', {\n mode,\n cancelable: true\n }) === false) {\n return;\n }\n const newControllers = this.buildOrUpdateControllers();\n this.notifyPlugins('beforeElementsUpdate');\n let minPadding = 0;\n for(let i = 0, ilen = this.data.datasets.length; i < ilen; i++){\n const { controller } = this.getDatasetMeta(i);\n const reset = !animsDisabled && newControllers.indexOf(controller) === -1;\n controller.buildOrUpdateElements(reset);\n minPadding = Math.max(+controller.getMaxOverflow(), minPadding);\n }\n minPadding = this._minPadding = options.layout.autoPadding ? minPadding : 0;\n this._updateLayout(minPadding);\n if (!animsDisabled) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(newControllers, (controller)=>{\n controller.reset();\n });\n }\n this._updateDatasets(mode);\n this.notifyPlugins('afterUpdate', {\n mode\n });\n this._layers.sort(compare2Level('z', '_idx'));\n const { _active , _lastEvent } = this;\n if (_lastEvent) {\n this._eventHandler(_lastEvent, true);\n } else if (_active.length) {\n this._updateHoverStyles(_active, _active, true);\n }\n this.render();\n }\n _updateScales() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.scales, (scale)=>{\n layouts.removeBox(this, scale);\n });\n this.ensureScalesHaveIDs();\n this.buildOrUpdateScales();\n }\n _checkEventBindings() {\n const options = this.options;\n const existingEvents = new Set(Object.keys(this._listeners));\n const newEvents = new Set(options.events);\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ag)(existingEvents, newEvents) || !!this._responsiveListeners !== options.responsive) {\n this.unbindEvents();\n this.bindEvents();\n }\n }\n _updateHiddenIndices() {\n const { _hiddenIndices } = this;\n const changes = this._getUniformDataChanges() || [];\n for (const { method , start , count } of changes){\n const move = method === '_removeElements' ? -count : count;\n moveNumericKeys(_hiddenIndices, start, move);\n }\n }\n _getUniformDataChanges() {\n const _dataChanges = this._dataChanges;\n if (!_dataChanges || !_dataChanges.length) {\n return;\n }\n this._dataChanges = [];\n const datasetCount = this.data.datasets.length;\n const makeSet = (idx)=>new Set(_dataChanges.filter((c)=>c[0] === idx).map((c, i)=>i + ',' + c.splice(1).join(',')));\n const changeSet = makeSet(0);\n for(let i = 1; i < datasetCount; i++){\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ag)(changeSet, makeSet(i))) {\n return;\n }\n }\n return Array.from(changeSet).map((c)=>c.split(',')).map((a)=>({\n method: a[1],\n start: +a[2],\n count: +a[3]\n }));\n }\n _updateLayout(minPadding) {\n if (this.notifyPlugins('beforeLayout', {\n cancelable: true\n }) === false) {\n return;\n }\n layouts.update(this, this.width, this.height, minPadding);\n const area = this.chartArea;\n const noArea = area.width <= 0 || area.height <= 0;\n this._layers = [];\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.boxes, (box)=>{\n if (noArea && box.position === 'chartArea') {\n return;\n }\n if (box.configure) {\n box.configure();\n }\n this._layers.push(...box._layers());\n }, this);\n this._layers.forEach((item, index)=>{\n item._idx = index;\n });\n this.notifyPlugins('afterLayout');\n }\n _updateDatasets(mode) {\n if (this.notifyPlugins('beforeDatasetsUpdate', {\n mode,\n cancelable: true\n }) === false) {\n return;\n }\n for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){\n this.getDatasetMeta(i).controller.configure();\n }\n for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){\n this._updateDataset(i, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(mode) ? mode({\n datasetIndex: i\n }) : mode);\n }\n this.notifyPlugins('afterDatasetsUpdate', {\n mode\n });\n }\n _updateDataset(index, mode) {\n const meta = this.getDatasetMeta(index);\n const args = {\n meta,\n index,\n mode,\n cancelable: true\n };\n if (this.notifyPlugins('beforeDatasetUpdate', args) === false) {\n return;\n }\n meta.controller._update(mode);\n args.cancelable = false;\n this.notifyPlugins('afterDatasetUpdate', args);\n }\n render() {\n if (this.notifyPlugins('beforeRender', {\n cancelable: true\n }) === false) {\n return;\n }\n if (animator.has(this)) {\n if (this.attached && !animator.running(this)) {\n animator.start(this);\n }\n } else {\n this.draw();\n onAnimationsComplete({\n chart: this\n });\n }\n }\n draw() {\n let i;\n if (this._resizeBeforeDraw) {\n const { width , height } = this._resizeBeforeDraw;\n this._resizeBeforeDraw = null;\n this._resize(width, height);\n }\n this.clear();\n if (this.width <= 0 || this.height <= 0) {\n return;\n }\n if (this.notifyPlugins('beforeDraw', {\n cancelable: true\n }) === false) {\n return;\n }\n const layers = this._layers;\n for(i = 0; i < layers.length && layers[i].z <= 0; ++i){\n layers[i].draw(this.chartArea);\n }\n this._drawDatasets();\n for(; i < layers.length; ++i){\n layers[i].draw(this.chartArea);\n }\n this.notifyPlugins('afterDraw');\n }\n _getSortedDatasetMetas(filterVisible) {\n const metasets = this._sortedMetasets;\n const result = [];\n let i, ilen;\n for(i = 0, ilen = metasets.length; i < ilen; ++i){\n const meta = metasets[i];\n if (!filterVisible || meta.visible) {\n result.push(meta);\n }\n }\n return result;\n }\n getSortedVisibleDatasetMetas() {\n return this._getSortedDatasetMetas(true);\n }\n _drawDatasets() {\n if (this.notifyPlugins('beforeDatasetsDraw', {\n cancelable: true\n }) === false) {\n return;\n }\n const metasets = this.getSortedVisibleDatasetMetas();\n for(let i = metasets.length - 1; i >= 0; --i){\n this._drawDataset(metasets[i]);\n }\n this.notifyPlugins('afterDatasetsDraw');\n }\n _drawDataset(meta) {\n const ctx = this.ctx;\n const args = {\n meta,\n index: meta.index,\n cancelable: true\n };\n const clip = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ah)(this, meta);\n if (this.notifyPlugins('beforeDatasetDraw', args) === false) {\n return;\n }\n if (clip) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, clip);\n }\n meta.controller.draw();\n if (clip) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);\n }\n args.cancelable = false;\n this.notifyPlugins('afterDatasetDraw', args);\n }\n isPointInArea(point) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)(point, this.chartArea, this._minPadding);\n }\n getElementsAtEventForMode(e, mode, options, useFinalPosition) {\n const method = Interaction.modes[mode];\n if (typeof method === 'function') {\n return method(this, e, options, useFinalPosition);\n }\n return [];\n }\n getDatasetMeta(datasetIndex) {\n const dataset = this.data.datasets[datasetIndex];\n const metasets = this._metasets;\n let meta = metasets.filter((x)=>x && x._dataset === dataset).pop();\n if (!meta) {\n meta = {\n type: null,\n data: [],\n dataset: null,\n controller: null,\n hidden: null,\n xAxisID: null,\n yAxisID: null,\n order: dataset && dataset.order || 0,\n index: datasetIndex,\n _dataset: dataset,\n _parsed: [],\n _sorted: false\n };\n metasets.push(meta);\n }\n return meta;\n }\n getContext() {\n return this.$context || (this.$context = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(null, {\n chart: this,\n type: 'chart'\n }));\n }\n getVisibleDatasetCount() {\n return this.getSortedVisibleDatasetMetas().length;\n }\n isDatasetVisible(datasetIndex) {\n const dataset = this.data.datasets[datasetIndex];\n if (!dataset) {\n return false;\n }\n const meta = this.getDatasetMeta(datasetIndex);\n return typeof meta.hidden === 'boolean' ? !meta.hidden : !dataset.hidden;\n }\n setDatasetVisibility(datasetIndex, visible) {\n const meta = this.getDatasetMeta(datasetIndex);\n meta.hidden = !visible;\n }\n toggleDataVisibility(index) {\n this._hiddenIndices[index] = !this._hiddenIndices[index];\n }\n getDataVisibility(index) {\n return !this._hiddenIndices[index];\n }\n _updateVisibility(datasetIndex, dataIndex, visible) {\n const mode = visible ? 'show' : 'hide';\n const meta = this.getDatasetMeta(datasetIndex);\n const anims = meta.controller._resolveAnimations(undefined, mode);\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(dataIndex)) {\n meta.data[dataIndex].hidden = !visible;\n this.update();\n } else {\n this.setDatasetVisibility(datasetIndex, visible);\n anims.update(meta, {\n visible\n });\n this.update((ctx)=>ctx.datasetIndex === datasetIndex ? mode : undefined);\n }\n }\n hide(datasetIndex, dataIndex) {\n this._updateVisibility(datasetIndex, dataIndex, false);\n }\n show(datasetIndex, dataIndex) {\n this._updateVisibility(datasetIndex, dataIndex, true);\n }\n _destroyDatasetMeta(datasetIndex) {\n const meta = this._metasets[datasetIndex];\n if (meta && meta.controller) {\n meta.controller._destroy();\n }\n delete this._metasets[datasetIndex];\n }\n _stop() {\n let i, ilen;\n this.stop();\n animator.remove(this);\n for(i = 0, ilen = this.data.datasets.length; i < ilen; ++i){\n this._destroyDatasetMeta(i);\n }\n }\n destroy() {\n this.notifyPlugins('beforeDestroy');\n const { canvas , ctx } = this;\n this._stop();\n this.config.clearCache();\n if (canvas) {\n this.unbindEvents();\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.af)(canvas, ctx);\n this.platform.releaseContext(ctx);\n this.canvas = null;\n this.ctx = null;\n }\n delete instances[this.id];\n this.notifyPlugins('afterDestroy');\n }\n toBase64Image(...args) {\n return this.canvas.toDataURL(...args);\n }\n bindEvents() {\n this.bindUserEvents();\n if (this.options.responsive) {\n this.bindResponsiveEvents();\n } else {\n this.attached = true;\n }\n }\n bindUserEvents() {\n const listeners = this._listeners;\n const platform = this.platform;\n const _add = (type, listener)=>{\n platform.addEventListener(this, type, listener);\n listeners[type] = listener;\n };\n const listener = (e, x, y)=>{\n e.offsetX = x;\n e.offsetY = y;\n this._eventHandler(e);\n };\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.options.events, (type)=>_add(type, listener));\n }\n bindResponsiveEvents() {\n if (!this._responsiveListeners) {\n this._responsiveListeners = {};\n }\n const listeners = this._responsiveListeners;\n const platform = this.platform;\n const _add = (type, listener)=>{\n platform.addEventListener(this, type, listener);\n listeners[type] = listener;\n };\n const _remove = (type, listener)=>{\n if (listeners[type]) {\n platform.removeEventListener(this, type, listener);\n delete listeners[type];\n }\n };\n const listener = (width, height)=>{\n if (this.canvas) {\n this.resize(width, height);\n }\n };\n let detached;\n const attached = ()=>{\n _remove('attach', attached);\n this.attached = true;\n this.resize();\n _add('resize', listener);\n _add('detach', detached);\n };\n detached = ()=>{\n this.attached = false;\n _remove('resize', listener);\n this._stop();\n this._resize(0, 0);\n _add('attach', attached);\n };\n if (platform.isAttached(this.canvas)) {\n attached();\n } else {\n detached();\n }\n }\n unbindEvents() {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this._listeners, (listener, type)=>{\n this.platform.removeEventListener(this, type, listener);\n });\n this._listeners = {};\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this._responsiveListeners, (listener, type)=>{\n this.platform.removeEventListener(this, type, listener);\n });\n this._responsiveListeners = undefined;\n }\n updateHoverStyle(items, mode, enabled) {\n const prefix = enabled ? 'set' : 'remove';\n let meta, item, i, ilen;\n if (mode === 'dataset') {\n meta = this.getDatasetMeta(items[0].datasetIndex);\n meta.controller['_' + prefix + 'DatasetHoverStyle']();\n }\n for(i = 0, ilen = items.length; i < ilen; ++i){\n item = items[i];\n const controller = item && this.getDatasetMeta(item.datasetIndex).controller;\n if (controller) {\n controller[prefix + 'HoverStyle'](item.element, item.datasetIndex, item.index);\n }\n }\n }\n getActiveElements() {\n return this._active || [];\n }\n setActiveElements(activeElements) {\n const lastActive = this._active || [];\n const active = activeElements.map(({ datasetIndex , index })=>{\n const meta = this.getDatasetMeta(datasetIndex);\n if (!meta) {\n throw new Error('No dataset found at index ' + datasetIndex);\n }\n return {\n datasetIndex,\n element: meta.data[index],\n index\n };\n });\n const changed = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(active, lastActive);\n if (changed) {\n this._active = active;\n this._lastEvent = null;\n this._updateHoverStyles(active, lastActive);\n }\n }\n notifyPlugins(hook, args, filter) {\n return this._plugins.notify(this, hook, args, filter);\n }\n isPluginEnabled(pluginId) {\n return this._plugins._cache.filter((p)=>p.plugin.id === pluginId).length === 1;\n }\n _updateHoverStyles(active, lastActive, replay) {\n const hoverOptions = this.options.hover;\n const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.datasetIndex === y.datasetIndex && x.index === y.index));\n const deactivated = diff(lastActive, active);\n const activated = replay ? active : diff(active, lastActive);\n if (deactivated.length) {\n this.updateHoverStyle(deactivated, hoverOptions.mode, false);\n }\n if (activated.length && hoverOptions.mode) {\n this.updateHoverStyle(activated, hoverOptions.mode, true);\n }\n }\n _eventHandler(e, replay) {\n const args = {\n event: e,\n replay,\n cancelable: true,\n inChartArea: this.isPointInArea(e)\n };\n const eventFilter = (plugin)=>(plugin.options.events || this.options.events).includes(e.native.type);\n if (this.notifyPlugins('beforeEvent', args, eventFilter) === false) {\n return;\n }\n const changed = this._handleEvent(e, replay, args.inChartArea);\n args.cancelable = false;\n this.notifyPlugins('afterEvent', args, eventFilter);\n if (changed || args.changed) {\n this.render();\n }\n return this;\n }\n _handleEvent(e, replay, inChartArea) {\n const { _active: lastActive = [] , options } = this;\n const useFinalPosition = replay;\n const active = this._getActiveElements(e, lastActive, inChartArea, useFinalPosition);\n const isClick = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aj)(e);\n const lastEvent = determineLastEvent(e, this._lastEvent, inChartArea, isClick);\n if (inChartArea) {\n this._lastEvent = null;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onHover, [\n e,\n active,\n this\n ], this);\n if (isClick) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onClick, [\n e,\n active,\n this\n ], this);\n }\n }\n const changed = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(active, lastActive);\n if (changed || replay) {\n this._active = active;\n this._updateHoverStyles(active, lastActive, replay);\n }\n this._lastEvent = lastEvent;\n return changed;\n }\n _getActiveElements(e, lastActive, inChartArea, useFinalPosition) {\n if (e.type === 'mouseout') {\n return [];\n }\n if (!inChartArea) {\n return lastActive;\n }\n const hoverOptions = this.options.hover;\n return this.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition);\n }\n}\nfunction invalidatePlugins() {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(Chart.instances, (chart)=>chart._plugins.invalidate());\n}\n\nfunction clipSelf(ctx, element, endAngle) {\n const { startAngle , x , y , outerRadius , innerRadius , options } = element;\n const { borderWidth , borderJoinStyle } = options;\n const outerAngleClip = Math.min(borderWidth / outerRadius, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(startAngle - endAngle));\n ctx.beginPath();\n ctx.arc(x, y, outerRadius - borderWidth / 2, startAngle + outerAngleClip / 2, endAngle - outerAngleClip / 2);\n if (innerRadius > 0) {\n const innerAngleClip = Math.min(borderWidth / innerRadius, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(startAngle - endAngle));\n ctx.arc(x, y, innerRadius + borderWidth / 2, endAngle - innerAngleClip / 2, startAngle + innerAngleClip / 2, true);\n } else {\n const clipWidth = Math.min(borderWidth / 2, outerRadius * (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(startAngle - endAngle));\n if (borderJoinStyle === 'round') {\n ctx.arc(x, y, clipWidth, endAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2, startAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2, true);\n } else if (borderJoinStyle === 'bevel') {\n const r = 2 * clipWidth * clipWidth;\n const endX = -r * Math.cos(endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + x;\n const endY = -r * Math.sin(endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + y;\n const startX = r * Math.cos(startAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + x;\n const startY = r * Math.sin(startAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + y;\n ctx.lineTo(endX, endY);\n ctx.lineTo(startX, startY);\n }\n }\n ctx.closePath();\n ctx.moveTo(0, 0);\n ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.clip('evenodd');\n}\nfunction clipArc(ctx, element, endAngle) {\n const { startAngle , pixelMargin , x , y , outerRadius , innerRadius } = element;\n let angleMargin = pixelMargin / outerRadius;\n // Draw an inner border by clipping the arc and drawing a double-width border\n // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders\n ctx.beginPath();\n ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin);\n if (innerRadius > pixelMargin) {\n angleMargin = pixelMargin / innerRadius;\n ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true);\n } else {\n ctx.arc(x, y, pixelMargin, endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, startAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H);\n }\n ctx.closePath();\n ctx.clip();\n}\nfunction toRadiusCorners(value) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.am)(value, [\n 'outerStart',\n 'outerEnd',\n 'innerStart',\n 'innerEnd'\n ]);\n}\n/**\n * Parse border radius from the provided options\n */ function parseBorderRadius$1(arc, innerRadius, outerRadius, angleDelta) {\n const o = toRadiusCorners(arc.options.borderRadius);\n const halfThickness = (outerRadius - innerRadius) / 2;\n const innerLimit = Math.min(halfThickness, angleDelta * innerRadius / 2);\n // Outer limits are complicated. We want to compute the available angular distance at\n // a radius of outerRadius - borderRadius because for small angular distances, this term limits.\n // We compute at r = outerRadius - borderRadius because this circle defines the center of the border corners.\n //\n // If the borderRadius is large, that value can become negative.\n // This causes the outer borders to lose their radius entirely, which is rather unexpected. To solve that, if borderRadius > outerRadius\n // we know that the thickness term will dominate and compute the limits at that point\n const computeOuterLimit = (val)=>{\n const outerArcLimit = (outerRadius - Math.min(halfThickness, val)) * angleDelta / 2;\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(val, 0, Math.min(halfThickness, outerArcLimit));\n };\n return {\n outerStart: computeOuterLimit(o.outerStart),\n outerEnd: computeOuterLimit(o.outerEnd),\n innerStart: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(o.innerStart, 0, innerLimit),\n innerEnd: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(o.innerEnd, 0, innerLimit)\n };\n}\n/**\n * Convert (r, 𝜃) to (x, y)\n */ function rThetaToXY(r, theta, x, y) {\n return {\n x: x + r * Math.cos(theta),\n y: y + r * Math.sin(theta)\n };\n}\n/**\n * Path the arc, respecting border radius by separating into left and right halves.\n *\n * Start End\n *\n * 1--->a--->2 Outer\n * / \\\n * 8 3\n * | |\n * | |\n * 7 4\n * \\ /\n * 6<---b<---5 Inner\n */ function pathArc(ctx, element, offset, spacing, end, circular) {\n const { x , y , startAngle: start , pixelMargin , innerRadius: innerR } = element;\n const outerRadius = Math.max(element.outerRadius + spacing + offset - pixelMargin, 0);\n const innerRadius = innerR > 0 ? innerR + spacing + offset + pixelMargin : 0;\n let spacingOffset = 0;\n const alpha = end - start;\n if (spacing) {\n // When spacing is present, it is the same for all items\n // So we adjust the start and end angle of the arc such that\n // the distance is the same as it would be without the spacing\n const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0;\n const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0;\n const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2;\n const adjustedAngle = avNogSpacingRadius !== 0 ? alpha * avNogSpacingRadius / (avNogSpacingRadius + spacing) : alpha;\n spacingOffset = (alpha - adjustedAngle) / 2;\n }\n const beta = Math.max(0.001, alpha * outerRadius - offset / _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P) / outerRadius;\n const angleOffset = (alpha - beta) / 2;\n const startAngle = start + angleOffset + spacingOffset;\n const endAngle = end - angleOffset - spacingOffset;\n const { outerStart , outerEnd , innerStart , innerEnd } = parseBorderRadius$1(element, innerRadius, outerRadius, endAngle - startAngle);\n const outerStartAdjustedRadius = outerRadius - outerStart;\n const outerEndAdjustedRadius = outerRadius - outerEnd;\n const outerStartAdjustedAngle = startAngle + outerStart / outerStartAdjustedRadius;\n const outerEndAdjustedAngle = endAngle - outerEnd / outerEndAdjustedRadius;\n const innerStartAdjustedRadius = innerRadius + innerStart;\n const innerEndAdjustedRadius = innerRadius + innerEnd;\n const innerStartAdjustedAngle = startAngle + innerStart / innerStartAdjustedRadius;\n const innerEndAdjustedAngle = endAngle - innerEnd / innerEndAdjustedRadius;\n ctx.beginPath();\n if (circular) {\n // The first arc segments from point 1 to point a to point 2\n const outerMidAdjustedAngle = (outerStartAdjustedAngle + outerEndAdjustedAngle) / 2;\n ctx.arc(x, y, outerRadius, outerStartAdjustedAngle, outerMidAdjustedAngle);\n ctx.arc(x, y, outerRadius, outerMidAdjustedAngle, outerEndAdjustedAngle);\n // The corner segment from point 2 to point 3\n if (outerEnd > 0) {\n const pCenter = rThetaToXY(outerEndAdjustedRadius, outerEndAdjustedAngle, x, y);\n ctx.arc(pCenter.x, pCenter.y, outerEnd, outerEndAdjustedAngle, endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H);\n }\n // The line from point 3 to point 4\n const p4 = rThetaToXY(innerEndAdjustedRadius, endAngle, x, y);\n ctx.lineTo(p4.x, p4.y);\n // The corner segment from point 4 to point 5\n if (innerEnd > 0) {\n const pCenter = rThetaToXY(innerEndAdjustedRadius, innerEndAdjustedAngle, x, y);\n ctx.arc(pCenter.x, pCenter.y, innerEnd, endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, innerEndAdjustedAngle + Math.PI);\n }\n // The inner arc from point 5 to point b to point 6\n const innerMidAdjustedAngle = (endAngle - innerEnd / innerRadius + (startAngle + innerStart / innerRadius)) / 2;\n ctx.arc(x, y, innerRadius, endAngle - innerEnd / innerRadius, innerMidAdjustedAngle, true);\n ctx.arc(x, y, innerRadius, innerMidAdjustedAngle, startAngle + innerStart / innerRadius, true);\n // The corner segment from point 6 to point 7\n if (innerStart > 0) {\n const pCenter = rThetaToXY(innerStartAdjustedRadius, innerStartAdjustedAngle, x, y);\n ctx.arc(pCenter.x, pCenter.y, innerStart, innerStartAdjustedAngle + Math.PI, startAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H);\n }\n // The line from point 7 to point 8\n const p8 = rThetaToXY(outerStartAdjustedRadius, startAngle, x, y);\n ctx.lineTo(p8.x, p8.y);\n // The corner segment from point 8 to point 1\n if (outerStart > 0) {\n const pCenter = rThetaToXY(outerStartAdjustedRadius, outerStartAdjustedAngle, x, y);\n ctx.arc(pCenter.x, pCenter.y, outerStart, startAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, outerStartAdjustedAngle);\n }\n } else {\n ctx.moveTo(x, y);\n const outerStartX = Math.cos(outerStartAdjustedAngle) * outerRadius + x;\n const outerStartY = Math.sin(outerStartAdjustedAngle) * outerRadius + y;\n ctx.lineTo(outerStartX, outerStartY);\n const outerEndX = Math.cos(outerEndAdjustedAngle) * outerRadius + x;\n const outerEndY = Math.sin(outerEndAdjustedAngle) * outerRadius + y;\n ctx.lineTo(outerEndX, outerEndY);\n }\n ctx.closePath();\n}\nfunction drawArc(ctx, element, offset, spacing, circular) {\n const { fullCircles , startAngle , circumference } = element;\n let endAngle = element.endAngle;\n if (fullCircles) {\n pathArc(ctx, element, offset, spacing, endAngle, circular);\n for(let i = 0; i < fullCircles; ++i){\n ctx.fill();\n }\n if (!isNaN(circumference)) {\n endAngle = startAngle + (circumference % _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);\n }\n }\n pathArc(ctx, element, offset, spacing, endAngle, circular);\n ctx.fill();\n return endAngle;\n}\nfunction drawBorder(ctx, element, offset, spacing, circular) {\n const { fullCircles , startAngle , circumference , options } = element;\n const { borderWidth , borderJoinStyle , borderDash , borderDashOffset , borderRadius } = options;\n const inner = options.borderAlign === 'inner';\n if (!borderWidth) {\n return;\n }\n ctx.setLineDash(borderDash || []);\n ctx.lineDashOffset = borderDashOffset;\n if (inner) {\n ctx.lineWidth = borderWidth * 2;\n ctx.lineJoin = borderJoinStyle || 'round';\n } else {\n ctx.lineWidth = borderWidth;\n ctx.lineJoin = borderJoinStyle || 'bevel';\n }\n let endAngle = element.endAngle;\n if (fullCircles) {\n pathArc(ctx, element, offset, spacing, endAngle, circular);\n for(let i = 0; i < fullCircles; ++i){\n ctx.stroke();\n }\n if (!isNaN(circumference)) {\n endAngle = startAngle + (circumference % _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);\n }\n }\n if (inner) {\n clipArc(ctx, element, endAngle);\n }\n if (options.selfJoin && endAngle - startAngle >= _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P && borderRadius === 0 && borderJoinStyle !== 'miter') {\n clipSelf(ctx, element, endAngle);\n }\n if (!fullCircles) {\n pathArc(ctx, element, offset, spacing, endAngle, circular);\n ctx.stroke();\n }\n}\nclass ArcElement extends Element {\n static id = 'arc';\n static defaults = {\n borderAlign: 'center',\n borderColor: '#fff',\n borderDash: [],\n borderDashOffset: 0,\n borderJoinStyle: undefined,\n borderRadius: 0,\n borderWidth: 2,\n offset: 0,\n spacing: 0,\n angle: undefined,\n circular: true,\n selfJoin: false\n };\n static defaultRoutes = {\n backgroundColor: 'backgroundColor'\n };\n static descriptors = {\n _scriptable: true,\n _indexable: (name)=>name !== 'borderDash'\n };\n circumference;\n endAngle;\n fullCircles;\n innerRadius;\n outerRadius;\n pixelMargin;\n startAngle;\n constructor(cfg){\n super();\n this.options = undefined;\n this.circumference = undefined;\n this.startAngle = undefined;\n this.endAngle = undefined;\n this.innerRadius = undefined;\n this.outerRadius = undefined;\n this.pixelMargin = 0;\n this.fullCircles = 0;\n if (cfg) {\n Object.assign(this, cfg);\n }\n }\n inRange(chartX, chartY, useFinalPosition) {\n const point = this.getProps([\n 'x',\n 'y'\n ], useFinalPosition);\n const { angle , distance } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.D)(point, {\n x: chartX,\n y: chartY\n });\n const { startAngle , endAngle , innerRadius , outerRadius , circumference } = this.getProps([\n 'startAngle',\n 'endAngle',\n 'innerRadius',\n 'outerRadius',\n 'circumference'\n ], useFinalPosition);\n const rAdjust = (this.options.spacing + this.options.borderWidth) / 2;\n const _circumference = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(circumference, endAngle - startAngle);\n const nonZeroBetween = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle) && startAngle !== endAngle;\n const betweenAngles = _circumference >= _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T || nonZeroBetween;\n const withinRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(distance, innerRadius + rAdjust, outerRadius + rAdjust);\n return betweenAngles && withinRadius;\n }\n getCenterPoint(useFinalPosition) {\n const { x , y , startAngle , endAngle , innerRadius , outerRadius } = this.getProps([\n 'x',\n 'y',\n 'startAngle',\n 'endAngle',\n 'innerRadius',\n 'outerRadius'\n ], useFinalPosition);\n const { offset , spacing } = this.options;\n const halfAngle = (startAngle + endAngle) / 2;\n const halfRadius = (innerRadius + outerRadius + spacing + offset) / 2;\n return {\n x: x + Math.cos(halfAngle) * halfRadius,\n y: y + Math.sin(halfAngle) * halfRadius\n };\n }\n tooltipPosition(useFinalPosition) {\n return this.getCenterPoint(useFinalPosition);\n }\n draw(ctx) {\n const { options , circumference } = this;\n const offset = (options.offset || 0) / 4;\n const spacing = (options.spacing || 0) / 2;\n const circular = options.circular;\n this.pixelMargin = options.borderAlign === 'inner' ? 0.33 : 0;\n this.fullCircles = circumference > _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T ? Math.floor(circumference / _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T) : 0;\n if (circumference === 0 || this.innerRadius < 0 || this.outerRadius < 0) {\n return;\n }\n ctx.save();\n const halfAngle = (this.startAngle + this.endAngle) / 2;\n ctx.translate(Math.cos(halfAngle) * offset, Math.sin(halfAngle) * offset);\n const fix = 1 - Math.sin(Math.min(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P, circumference || 0));\n const radiusOffset = offset * fix;\n ctx.fillStyle = options.backgroundColor;\n ctx.strokeStyle = options.borderColor;\n drawArc(ctx, this, radiusOffset, spacing, circular);\n drawBorder(ctx, this, radiusOffset, spacing, circular);\n ctx.restore();\n }\n}\n\nfunction setStyle(ctx, options, style = options) {\n ctx.lineCap = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderCapStyle, options.borderCapStyle);\n ctx.setLineDash((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDash, options.borderDash));\n ctx.lineDashOffset = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDashOffset, options.borderDashOffset);\n ctx.lineJoin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderJoinStyle, options.borderJoinStyle);\n ctx.lineWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderWidth, options.borderWidth);\n ctx.strokeStyle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderColor, options.borderColor);\n}\nfunction lineTo(ctx, previous, target) {\n ctx.lineTo(target.x, target.y);\n}\n function getLineMethod(options) {\n if (options.stepped) {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.at;\n }\n if (options.tension || options.cubicInterpolationMode === 'monotone') {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.au;\n }\n return lineTo;\n}\nfunction pathVars(points, segment, params = {}) {\n const count = points.length;\n const { start: paramsStart = 0 , end: paramsEnd = count - 1 } = params;\n const { start: segmentStart , end: segmentEnd } = segment;\n const start = Math.max(paramsStart, segmentStart);\n const end = Math.min(paramsEnd, segmentEnd);\n const outside = paramsStart < segmentStart && paramsEnd < segmentStart || paramsStart > segmentEnd && paramsEnd > segmentEnd;\n return {\n count,\n start,\n loop: segment.loop,\n ilen: end < start && !outside ? count + end - start : end - start\n };\n}\n function pathSegment(ctx, line, segment, params) {\n const { points , options } = line;\n const { count , start , loop , ilen } = pathVars(points, segment, params);\n const lineMethod = getLineMethod(options);\n let { move =true , reverse } = params || {};\n let i, point, prev;\n for(i = 0; i <= ilen; ++i){\n point = points[(start + (reverse ? ilen - i : i)) % count];\n if (point.skip) {\n continue;\n } else if (move) {\n ctx.moveTo(point.x, point.y);\n move = false;\n } else {\n lineMethod(ctx, prev, point, reverse, options.stepped);\n }\n prev = point;\n }\n if (loop) {\n point = points[(start + (reverse ? ilen : 0)) % count];\n lineMethod(ctx, prev, point, reverse, options.stepped);\n }\n return !!loop;\n}\n function fastPathSegment(ctx, line, segment, params) {\n const points = line.points;\n const { count , start , ilen } = pathVars(points, segment, params);\n const { move =true , reverse } = params || {};\n let avgX = 0;\n let countX = 0;\n let i, point, prevX, minY, maxY, lastY;\n const pointIndex = (index)=>(start + (reverse ? ilen - index : index)) % count;\n const drawX = ()=>{\n if (minY !== maxY) {\n ctx.lineTo(avgX, maxY);\n ctx.lineTo(avgX, minY);\n ctx.lineTo(avgX, lastY);\n }\n };\n if (move) {\n point = points[pointIndex(0)];\n ctx.moveTo(point.x, point.y);\n }\n for(i = 0; i <= ilen; ++i){\n point = points[pointIndex(i)];\n if (point.skip) {\n continue;\n }\n const x = point.x;\n const y = point.y;\n const truncX = x | 0;\n if (truncX === prevX) {\n if (y < minY) {\n minY = y;\n } else if (y > maxY) {\n maxY = y;\n }\n avgX = (countX * avgX + x) / ++countX;\n } else {\n drawX();\n ctx.lineTo(x, y);\n prevX = truncX;\n countX = 0;\n minY = maxY = y;\n }\n lastY = y;\n }\n drawX();\n}\n function _getSegmentMethod(line) {\n const opts = line.options;\n const borderDash = opts.borderDash && opts.borderDash.length;\n const useFastPath = !line._decimated && !line._loop && !opts.tension && opts.cubicInterpolationMode !== 'monotone' && !opts.stepped && !borderDash;\n return useFastPath ? fastPathSegment : pathSegment;\n}\n function _getInterpolationMethod(options) {\n if (options.stepped) {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aq;\n }\n if (options.tension || options.cubicInterpolationMode === 'monotone') {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ar;\n }\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.as;\n}\nfunction strokePathWithCache(ctx, line, start, count) {\n let path = line._path;\n if (!path) {\n path = line._path = new Path2D();\n if (line.path(path, start, count)) {\n path.closePath();\n }\n }\n setStyle(ctx, line.options);\n ctx.stroke(path);\n}\nfunction strokePathDirect(ctx, line, start, count) {\n const { segments , options } = line;\n const segmentMethod = _getSegmentMethod(line);\n for (const segment of segments){\n setStyle(ctx, options, segment.style);\n ctx.beginPath();\n if (segmentMethod(ctx, line, segment, {\n start,\n end: start + count - 1\n })) {\n ctx.closePath();\n }\n ctx.stroke();\n }\n}\nconst usePath2D = typeof Path2D === 'function';\nfunction draw(ctx, line, start, count) {\n if (usePath2D && !line.options.segment) {\n strokePathWithCache(ctx, line, start, count);\n } else {\n strokePathDirect(ctx, line, start, count);\n }\n}\nclass LineElement extends Element {\n static id = 'line';\n static defaults = {\n borderCapStyle: 'butt',\n borderDash: [],\n borderDashOffset: 0,\n borderJoinStyle: 'miter',\n borderWidth: 3,\n capBezierPoints: true,\n cubicInterpolationMode: 'default',\n fill: false,\n spanGaps: false,\n stepped: false,\n tension: 0\n };\n static defaultRoutes = {\n backgroundColor: 'backgroundColor',\n borderColor: 'borderColor'\n };\n static descriptors = {\n _scriptable: true,\n _indexable: (name)=>name !== 'borderDash' && name !== 'fill'\n };\n constructor(cfg){\n super();\n this.animated = true;\n this.options = undefined;\n this._chart = undefined;\n this._loop = undefined;\n this._fullLoop = undefined;\n this._path = undefined;\n this._points = undefined;\n this._segments = undefined;\n this._decimated = false;\n this._pointsUpdated = false;\n this._datasetIndex = undefined;\n if (cfg) {\n Object.assign(this, cfg);\n }\n }\n updateControlPoints(chartArea, indexAxis) {\n const options = this.options;\n if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !this._pointsUpdated) {\n const loop = options.spanGaps ? this._loop : this._fullLoop;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.an)(this._points, options, chartArea, loop, indexAxis);\n this._pointsUpdated = true;\n }\n }\n set points(points) {\n this._points = points;\n delete this._segments;\n delete this._path;\n this._pointsUpdated = false;\n }\n get points() {\n return this._points;\n }\n get segments() {\n return this._segments || (this._segments = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ao)(this, this.options.segment));\n }\n first() {\n const segments = this.segments;\n const points = this.points;\n return segments.length && points[segments[0].start];\n }\n last() {\n const segments = this.segments;\n const points = this.points;\n const count = segments.length;\n return count && points[segments[count - 1].end];\n }\n interpolate(point, property) {\n const options = this.options;\n const value = point[property];\n const points = this.points;\n const segments = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ap)(this, {\n property,\n start: value,\n end: value\n });\n if (!segments.length) {\n return;\n }\n const result = [];\n const _interpolate = _getInterpolationMethod(options);\n let i, ilen;\n for(i = 0, ilen = segments.length; i < ilen; ++i){\n const { start , end } = segments[i];\n const p1 = points[start];\n const p2 = points[end];\n if (p1 === p2) {\n result.push(p1);\n continue;\n }\n const t = Math.abs((value - p1[property]) / (p2[property] - p1[property]));\n const interpolated = _interpolate(p1, p2, t, options.stepped);\n interpolated[property] = point[property];\n result.push(interpolated);\n }\n return result.length === 1 ? result[0] : result;\n }\n pathSegment(ctx, segment, params) {\n const segmentMethod = _getSegmentMethod(this);\n return segmentMethod(ctx, this, segment, params);\n }\n path(ctx, start, count) {\n const segments = this.segments;\n const segmentMethod = _getSegmentMethod(this);\n let loop = this._loop;\n start = start || 0;\n count = count || this.points.length - start;\n for (const segment of segments){\n loop &= segmentMethod(ctx, this, segment, {\n start,\n end: start + count - 1\n });\n }\n return !!loop;\n }\n draw(ctx, chartArea, start, count) {\n const options = this.options || {};\n const points = this.points || [];\n if (points.length && options.borderWidth) {\n ctx.save();\n draw(ctx, this, start, count);\n ctx.restore();\n }\n if (this.animated) {\n this._pointsUpdated = false;\n this._path = undefined;\n }\n }\n}\n\nfunction inRange$1(el, pos, axis, useFinalPosition) {\n const options = el.options;\n const { [axis]: value } = el.getProps([\n axis\n ], useFinalPosition);\n return Math.abs(pos - value) < options.radius + options.hitRadius;\n}\nclass PointElement extends Element {\n static id = 'point';\n parsed;\n skip;\n stop;\n /**\n * @type {any}\n */ static defaults = {\n borderWidth: 1,\n hitRadius: 1,\n hoverBorderWidth: 1,\n hoverRadius: 4,\n pointStyle: 'circle',\n radius: 3,\n rotation: 0\n };\n /**\n * @type {any}\n */ static defaultRoutes = {\n backgroundColor: 'backgroundColor',\n borderColor: 'borderColor'\n };\n constructor(cfg){\n super();\n this.options = undefined;\n this.parsed = undefined;\n this.skip = undefined;\n this.stop = undefined;\n if (cfg) {\n Object.assign(this, cfg);\n }\n }\n inRange(mouseX, mouseY, useFinalPosition) {\n const options = this.options;\n const { x , y } = this.getProps([\n 'x',\n 'y'\n ], useFinalPosition);\n return Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2) < Math.pow(options.hitRadius + options.radius, 2);\n }\n inXRange(mouseX, useFinalPosition) {\n return inRange$1(this, mouseX, 'x', useFinalPosition);\n }\n inYRange(mouseY, useFinalPosition) {\n return inRange$1(this, mouseY, 'y', useFinalPosition);\n }\n getCenterPoint(useFinalPosition) {\n const { x , y } = this.getProps([\n 'x',\n 'y'\n ], useFinalPosition);\n return {\n x,\n y\n };\n }\n size(options) {\n options = options || this.options || {};\n let radius = options.radius || 0;\n radius = Math.max(radius, radius && options.hoverRadius || 0);\n const borderWidth = radius && options.borderWidth || 0;\n return (radius + borderWidth) * 2;\n }\n draw(ctx, area) {\n const options = this.options;\n if (this.skip || options.radius < 0.1 || !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)(this, area, this.size(options) / 2)) {\n return;\n }\n ctx.strokeStyle = options.borderColor;\n ctx.lineWidth = options.borderWidth;\n ctx.fillStyle = options.backgroundColor;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.av)(ctx, options, this.x, this.y);\n }\n getRange() {\n const options = this.options || {};\n // @ts-expect-error Fallbacks should never be hit in practice\n return options.radius + options.hitRadius;\n }\n}\n\nfunction getBarBounds(bar, useFinalPosition) {\n const { x , y , base , width , height } = bar.getProps([\n 'x',\n 'y',\n 'base',\n 'width',\n 'height'\n ], useFinalPosition);\n let left, right, top, bottom, half;\n if (bar.horizontal) {\n half = height / 2;\n left = Math.min(x, base);\n right = Math.max(x, base);\n top = y - half;\n bottom = y + half;\n } else {\n half = width / 2;\n left = x - half;\n right = x + half;\n top = Math.min(y, base);\n bottom = Math.max(y, base);\n }\n return {\n left,\n top,\n right,\n bottom\n };\n}\nfunction skipOrLimit(skip, value, min, max) {\n return skip ? 0 : (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(value, min, max);\n}\nfunction parseBorderWidth(bar, maxW, maxH) {\n const value = bar.options.borderWidth;\n const skip = bar.borderSkipped;\n const o = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ax)(value);\n return {\n t: skipOrLimit(skip.top, o.top, 0, maxH),\n r: skipOrLimit(skip.right, o.right, 0, maxW),\n b: skipOrLimit(skip.bottom, o.bottom, 0, maxH),\n l: skipOrLimit(skip.left, o.left, 0, maxW)\n };\n}\nfunction parseBorderRadius(bar, maxW, maxH) {\n const { enableBorderRadius } = bar.getProps([\n 'enableBorderRadius'\n ]);\n const value = bar.options.borderRadius;\n const o = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(value);\n const maxR = Math.min(maxW, maxH);\n const skip = bar.borderSkipped;\n const enableBorder = enableBorderRadius || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(value);\n return {\n topLeft: skipOrLimit(!enableBorder || skip.top || skip.left, o.topLeft, 0, maxR),\n topRight: skipOrLimit(!enableBorder || skip.top || skip.right, o.topRight, 0, maxR),\n bottomLeft: skipOrLimit(!enableBorder || skip.bottom || skip.left, o.bottomLeft, 0, maxR),\n bottomRight: skipOrLimit(!enableBorder || skip.bottom || skip.right, o.bottomRight, 0, maxR)\n };\n}\nfunction boundingRects(bar) {\n const bounds = getBarBounds(bar);\n const width = bounds.right - bounds.left;\n const height = bounds.bottom - bounds.top;\n const border = parseBorderWidth(bar, width / 2, height / 2);\n const radius = parseBorderRadius(bar, width / 2, height / 2);\n return {\n outer: {\n x: bounds.left,\n y: bounds.top,\n w: width,\n h: height,\n radius\n },\n inner: {\n x: bounds.left + border.l,\n y: bounds.top + border.t,\n w: width - border.l - border.r,\n h: height - border.t - border.b,\n radius: {\n topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),\n topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),\n bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),\n bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r))\n }\n }\n };\n}\nfunction inRange(bar, x, y, useFinalPosition) {\n const skipX = x === null;\n const skipY = y === null;\n const skipBoth = skipX && skipY;\n const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition);\n return bounds && (skipX || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(x, bounds.left, bounds.right)) && (skipY || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(y, bounds.top, bounds.bottom));\n}\nfunction hasRadius(radius) {\n return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;\n}\n function addNormalRectPath(ctx, rect) {\n ctx.rect(rect.x, rect.y, rect.w, rect.h);\n}\nfunction inflateRect(rect, amount, refRect = {}) {\n const x = rect.x !== refRect.x ? -amount : 0;\n const y = rect.y !== refRect.y ? -amount : 0;\n const w = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x;\n const h = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y;\n return {\n x: rect.x + x,\n y: rect.y + y,\n w: rect.w + w,\n h: rect.h + h,\n radius: rect.radius\n };\n}\nclass BarElement extends Element {\n static id = 'bar';\n static defaults = {\n borderSkipped: 'start',\n borderWidth: 0,\n borderRadius: 0,\n inflateAmount: 'auto',\n pointStyle: undefined\n };\n static defaultRoutes = {\n backgroundColor: 'backgroundColor',\n borderColor: 'borderColor'\n };\n constructor(cfg){\n super();\n this.options = undefined;\n this.horizontal = undefined;\n this.base = undefined;\n this.width = undefined;\n this.height = undefined;\n this.inflateAmount = undefined;\n if (cfg) {\n Object.assign(this, cfg);\n }\n }\n draw(ctx) {\n const { inflateAmount , options: { borderColor , backgroundColor } } = this;\n const { inner , outer } = boundingRects(this);\n const addRectPath = hasRadius(outer.radius) ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw : addNormalRectPath;\n ctx.save();\n if (outer.w !== inner.w || outer.h !== inner.h) {\n ctx.beginPath();\n addRectPath(ctx, inflateRect(outer, inflateAmount, inner));\n ctx.clip();\n addRectPath(ctx, inflateRect(inner, -inflateAmount, outer));\n ctx.fillStyle = borderColor;\n ctx.fill('evenodd');\n }\n ctx.beginPath();\n addRectPath(ctx, inflateRect(inner, inflateAmount));\n ctx.fillStyle = backgroundColor;\n ctx.fill();\n ctx.restore();\n }\n inRange(mouseX, mouseY, useFinalPosition) {\n return inRange(this, mouseX, mouseY, useFinalPosition);\n }\n inXRange(mouseX, useFinalPosition) {\n return inRange(this, mouseX, null, useFinalPosition);\n }\n inYRange(mouseY, useFinalPosition) {\n return inRange(this, null, mouseY, useFinalPosition);\n }\n getCenterPoint(useFinalPosition) {\n const { x , y , base , horizontal } = this.getProps([\n 'x',\n 'y',\n 'base',\n 'horizontal'\n ], useFinalPosition);\n return {\n x: horizontal ? (x + base) / 2 : x,\n y: horizontal ? y : (y + base) / 2\n };\n }\n getRange(axis) {\n return axis === 'x' ? this.width / 2 : this.height / 2;\n }\n}\n\nvar elements = /*#__PURE__*/Object.freeze({\n__proto__: null,\nArcElement: ArcElement,\nBarElement: BarElement,\nLineElement: LineElement,\nPointElement: PointElement\n});\n\nconst BORDER_COLORS = [\n 'rgb(54, 162, 235)',\n 'rgb(255, 99, 132)',\n 'rgb(255, 159, 64)',\n 'rgb(255, 205, 86)',\n 'rgb(75, 192, 192)',\n 'rgb(153, 102, 255)',\n 'rgb(201, 203, 207)' // grey\n];\n// Border colors with 50% transparency\nconst BACKGROUND_COLORS = /* #__PURE__ */ BORDER_COLORS.map((color)=>color.replace('rgb(', 'rgba(').replace(')', ', 0.5)'));\nfunction getBorderColor(i) {\n return BORDER_COLORS[i % BORDER_COLORS.length];\n}\nfunction getBackgroundColor(i) {\n return BACKGROUND_COLORS[i % BACKGROUND_COLORS.length];\n}\nfunction colorizeDefaultDataset(dataset, i) {\n dataset.borderColor = getBorderColor(i);\n dataset.backgroundColor = getBackgroundColor(i);\n return ++i;\n}\nfunction colorizeDoughnutDataset(dataset, i) {\n dataset.backgroundColor = dataset.data.map(()=>getBorderColor(i++));\n return i;\n}\nfunction colorizePolarAreaDataset(dataset, i) {\n dataset.backgroundColor = dataset.data.map(()=>getBackgroundColor(i++));\n return i;\n}\nfunction getColorizer(chart) {\n let i = 0;\n return (dataset, datasetIndex)=>{\n const controller = chart.getDatasetMeta(datasetIndex).controller;\n if (controller instanceof DoughnutController) {\n i = colorizeDoughnutDataset(dataset, i);\n } else if (controller instanceof PolarAreaController) {\n i = colorizePolarAreaDataset(dataset, i);\n } else if (controller) {\n i = colorizeDefaultDataset(dataset, i);\n }\n };\n}\nfunction containsColorsDefinitions(descriptors) {\n let k;\n for(k in descriptors){\n if (descriptors[k].borderColor || descriptors[k].backgroundColor) {\n return true;\n }\n }\n return false;\n}\nfunction containsColorsDefinition(descriptor) {\n return descriptor && (descriptor.borderColor || descriptor.backgroundColor);\n}\nfunction containsDefaultColorsDefenitions() {\n return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.borderColor !== 'rgba(0,0,0,0.1)' || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.backgroundColor !== 'rgba(0,0,0,0.1)';\n}\nvar plugin_colors = {\n id: 'colors',\n defaults: {\n enabled: true,\n forceOverride: false\n },\n beforeLayout (chart, _args, options) {\n if (!options.enabled) {\n return;\n }\n const { data: { datasets } , options: chartOptions } = chart.config;\n const { elements } = chartOptions;\n const containsColorDefenition = containsColorsDefinitions(datasets) || containsColorsDefinition(chartOptions) || elements && containsColorsDefinitions(elements) || containsDefaultColorsDefenitions();\n if (!options.forceOverride && containsColorDefenition) {\n return;\n }\n const colorizer = getColorizer(chart);\n datasets.forEach(colorizer);\n }\n};\n\nfunction lttbDecimation(data, start, count, availableWidth, options) {\n const samples = options.samples || availableWidth;\n if (samples >= count) {\n return data.slice(start, start + count);\n }\n const decimated = [];\n const bucketWidth = (count - 2) / (samples - 2);\n let sampledIndex = 0;\n const endIndex = start + count - 1;\n let a = start;\n let i, maxAreaPoint, maxArea, area, nextA;\n decimated[sampledIndex++] = data[a];\n for(i = 0; i < samples - 2; i++){\n let avgX = 0;\n let avgY = 0;\n let j;\n const avgRangeStart = Math.floor((i + 1) * bucketWidth) + 1 + start;\n const avgRangeEnd = Math.min(Math.floor((i + 2) * bucketWidth) + 1, count) + start;\n const avgRangeLength = avgRangeEnd - avgRangeStart;\n for(j = avgRangeStart; j < avgRangeEnd; j++){\n avgX += data[j].x;\n avgY += data[j].y;\n }\n avgX /= avgRangeLength;\n avgY /= avgRangeLength;\n const rangeOffs = Math.floor(i * bucketWidth) + 1 + start;\n const rangeTo = Math.min(Math.floor((i + 1) * bucketWidth) + 1, count) + start;\n const { x: pointAx , y: pointAy } = data[a];\n maxArea = area = -1;\n for(j = rangeOffs; j < rangeTo; j++){\n area = 0.5 * Math.abs((pointAx - avgX) * (data[j].y - pointAy) - (pointAx - data[j].x) * (avgY - pointAy));\n if (area > maxArea) {\n maxArea = area;\n maxAreaPoint = data[j];\n nextA = j;\n }\n }\n decimated[sampledIndex++] = maxAreaPoint;\n a = nextA;\n }\n decimated[sampledIndex++] = data[endIndex];\n return decimated;\n}\nfunction minMaxDecimation(data, start, count, availableWidth) {\n let avgX = 0;\n let countX = 0;\n let i, point, x, y, prevX, minIndex, maxIndex, startIndex, minY, maxY;\n const decimated = [];\n const endIndex = start + count - 1;\n const xMin = data[start].x;\n const xMax = data[endIndex].x;\n const dx = xMax - xMin;\n for(i = start; i < start + count; ++i){\n point = data[i];\n x = (point.x - xMin) / dx * availableWidth;\n y = point.y;\n const truncX = x | 0;\n if (truncX === prevX) {\n if (y < minY) {\n minY = y;\n minIndex = i;\n } else if (y > maxY) {\n maxY = y;\n maxIndex = i;\n }\n avgX = (countX * avgX + point.x) / ++countX;\n } else {\n const lastIndex = i - 1;\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(minIndex) && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(maxIndex)) {\n const intermediateIndex1 = Math.min(minIndex, maxIndex);\n const intermediateIndex2 = Math.max(minIndex, maxIndex);\n if (intermediateIndex1 !== startIndex && intermediateIndex1 !== lastIndex) {\n decimated.push({\n ...data[intermediateIndex1],\n x: avgX\n });\n }\n if (intermediateIndex2 !== startIndex && intermediateIndex2 !== lastIndex) {\n decimated.push({\n ...data[intermediateIndex2],\n x: avgX\n });\n }\n }\n if (i > 0 && lastIndex !== startIndex) {\n decimated.push(data[lastIndex]);\n }\n decimated.push(point);\n prevX = truncX;\n countX = 0;\n minY = maxY = y;\n minIndex = maxIndex = startIndex = i;\n }\n }\n return decimated;\n}\nfunction cleanDecimatedDataset(dataset) {\n if (dataset._decimated) {\n const data = dataset._data;\n delete dataset._decimated;\n delete dataset._data;\n Object.defineProperty(dataset, 'data', {\n configurable: true,\n enumerable: true,\n writable: true,\n value: data\n });\n }\n}\nfunction cleanDecimatedData(chart) {\n chart.data.datasets.forEach((dataset)=>{\n cleanDecimatedDataset(dataset);\n });\n}\nfunction getStartAndCountOfVisiblePointsSimplified(meta, points) {\n const pointCount = points.length;\n let start = 0;\n let count;\n const { iScale } = meta;\n const { min , max , minDefined , maxDefined } = iScale.getUserBounds();\n if (minDefined) {\n start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(points, iScale.axis, min).lo, 0, pointCount - 1);\n }\n if (maxDefined) {\n count = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(points, iScale.axis, max).hi + 1, start, pointCount) - start;\n } else {\n count = pointCount - start;\n }\n return {\n start,\n count\n };\n}\nvar plugin_decimation = {\n id: 'decimation',\n defaults: {\n algorithm: 'min-max',\n enabled: false\n },\n beforeElementsUpdate: (chart, args, options)=>{\n if (!options.enabled) {\n cleanDecimatedData(chart);\n return;\n }\n const availableWidth = chart.width;\n chart.data.datasets.forEach((dataset, datasetIndex)=>{\n const { _data , indexAxis } = dataset;\n const meta = chart.getDatasetMeta(datasetIndex);\n const data = _data || dataset.data;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([\n indexAxis,\n chart.options.indexAxis\n ]) === 'y') {\n return;\n }\n if (!meta.controller.supportsDecimation) {\n return;\n }\n const xAxis = chart.scales[meta.xAxisID];\n if (xAxis.type !== 'linear' && xAxis.type !== 'time') {\n return;\n }\n if (chart.options.parsing) {\n return;\n }\n let { start , count } = getStartAndCountOfVisiblePointsSimplified(meta, data);\n const threshold = options.threshold || 4 * availableWidth;\n if (count <= threshold) {\n cleanDecimatedDataset(dataset);\n return;\n }\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(_data)) {\n dataset._data = data;\n delete dataset.data;\n Object.defineProperty(dataset, 'data', {\n configurable: true,\n enumerable: true,\n get: function() {\n return this._decimated;\n },\n set: function(d) {\n this._data = d;\n }\n });\n }\n let decimated;\n switch(options.algorithm){\n case 'lttb':\n decimated = lttbDecimation(data, start, count, availableWidth, options);\n break;\n case 'min-max':\n decimated = minMaxDecimation(data, start, count, availableWidth);\n break;\n default:\n throw new Error(`Unsupported decimation algorithm '${options.algorithm}'`);\n }\n dataset._decimated = decimated;\n });\n },\n destroy (chart) {\n cleanDecimatedData(chart);\n }\n};\n\nfunction _segments(line, target, property) {\n const segments = line.segments;\n const points = line.points;\n const tpoints = target.points;\n const parts = [];\n for (const segment of segments){\n let { start , end } = segment;\n end = _findSegmentEnd(start, end, points);\n const bounds = _getBounds(property, points[start], points[end], segment.loop);\n if (!target.segments) {\n parts.push({\n source: segment,\n target: bounds,\n start: points[start],\n end: points[end]\n });\n continue;\n }\n const targetSegments = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ap)(target, bounds);\n for (const tgt of targetSegments){\n const subBounds = _getBounds(property, tpoints[tgt.start], tpoints[tgt.end], tgt.loop);\n const fillSources = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.az)(segment, points, subBounds);\n for (const fillSource of fillSources){\n parts.push({\n source: fillSource,\n target: tgt,\n start: {\n [property]: _getEdge(bounds, subBounds, 'start', Math.max)\n },\n end: {\n [property]: _getEdge(bounds, subBounds, 'end', Math.min)\n }\n });\n }\n }\n }\n return parts;\n}\nfunction _getBounds(property, first, last, loop) {\n if (loop) {\n return;\n }\n let start = first[property];\n let end = last[property];\n if (property === 'angle') {\n start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(start);\n end = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(end);\n }\n return {\n property,\n start,\n end\n };\n}\nfunction _pointsFromSegments(boundary, line) {\n const { x =null , y =null } = boundary || {};\n const linePoints = line.points;\n const points = [];\n line.segments.forEach(({ start , end })=>{\n end = _findSegmentEnd(start, end, linePoints);\n const first = linePoints[start];\n const last = linePoints[end];\n if (y !== null) {\n points.push({\n x: first.x,\n y\n });\n points.push({\n x: last.x,\n y\n });\n } else if (x !== null) {\n points.push({\n x,\n y: first.y\n });\n points.push({\n x,\n y: last.y\n });\n }\n });\n return points;\n}\nfunction _findSegmentEnd(start, end, points) {\n for(; end > start; end--){\n const point = points[end];\n if (!isNaN(point.x) && !isNaN(point.y)) {\n break;\n }\n }\n return end;\n}\nfunction _getEdge(a, b, prop, fn) {\n if (a && b) {\n return fn(a[prop], b[prop]);\n }\n return a ? a[prop] : b ? b[prop] : 0;\n}\n\nfunction _createBoundaryLine(boundary, line) {\n let points = [];\n let _loop = false;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(boundary)) {\n _loop = true;\n points = boundary;\n } else {\n points = _pointsFromSegments(boundary, line);\n }\n return points.length ? new LineElement({\n points,\n options: {\n tension: 0\n },\n _loop,\n _fullLoop: _loop\n }) : null;\n}\nfunction _shouldApplyFill(source) {\n return source && source.fill !== false;\n}\n\nfunction _resolveTarget(sources, index, propagate) {\n const source = sources[index];\n let fill = source.fill;\n const visited = [\n index\n ];\n let target;\n if (!propagate) {\n return fill;\n }\n while(fill !== false && visited.indexOf(fill) === -1){\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) {\n return fill;\n }\n target = sources[fill];\n if (!target) {\n return false;\n }\n if (target.visible) {\n return fill;\n }\n visited.push(fill);\n fill = target.fill;\n }\n return false;\n}\n function _decodeFill(line, index, count) {\n const fill = parseFillOption(line);\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) {\n return isNaN(fill.value) ? false : fill;\n }\n let target = parseFloat(fill);\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(target) && Math.floor(target) === target) {\n return decodeTargetIndex(fill[0], index, target, count);\n }\n return [\n 'origin',\n 'start',\n 'end',\n 'stack',\n 'shape'\n ].indexOf(fill) >= 0 && fill;\n}\nfunction decodeTargetIndex(firstCh, index, target, count) {\n if (firstCh === '-' || firstCh === '+') {\n target = index + target;\n }\n if (target === index || target < 0 || target >= count) {\n return false;\n }\n return target;\n}\n function _getTargetPixel(fill, scale) {\n let pixel = null;\n if (fill === 'start') {\n pixel = scale.bottom;\n } else if (fill === 'end') {\n pixel = scale.top;\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) {\n pixel = scale.getPixelForValue(fill.value);\n } else if (scale.getBasePixel) {\n pixel = scale.getBasePixel();\n }\n return pixel;\n}\n function _getTargetValue(fill, scale, startValue) {\n let value;\n if (fill === 'start') {\n value = startValue;\n } else if (fill === 'end') {\n value = scale.options.reverse ? scale.min : scale.max;\n } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) {\n value = fill.value;\n } else {\n value = scale.getBaseValue();\n }\n return value;\n}\n function parseFillOption(line) {\n const options = line.options;\n const fillOption = options.fill;\n let fill = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(fillOption && fillOption.target, fillOption);\n if (fill === undefined) {\n fill = !!options.backgroundColor;\n }\n if (fill === false || fill === null) {\n return false;\n }\n if (fill === true) {\n return 'origin';\n }\n return fill;\n}\n\nfunction _buildStackLine(source) {\n const { scale , index , line } = source;\n const points = [];\n const segments = line.segments;\n const sourcePoints = line.points;\n const linesBelow = getLinesBelow(scale, index);\n linesBelow.push(_createBoundaryLine({\n x: null,\n y: scale.bottom\n }, line));\n for(let i = 0; i < segments.length; i++){\n const segment = segments[i];\n for(let j = segment.start; j <= segment.end; j++){\n addPointsBelow(points, sourcePoints[j], linesBelow);\n }\n }\n return new LineElement({\n points,\n options: {}\n });\n}\n function getLinesBelow(scale, index) {\n const below = [];\n const metas = scale.getMatchingVisibleMetas('line');\n for(let i = 0; i < metas.length; i++){\n const meta = metas[i];\n if (meta.index === index) {\n break;\n }\n if (!meta.hidden) {\n below.unshift(meta.dataset);\n }\n }\n return below;\n}\n function addPointsBelow(points, sourcePoint, linesBelow) {\n const postponed = [];\n for(let j = 0; j < linesBelow.length; j++){\n const line = linesBelow[j];\n const { first , last , point } = findPoint(line, sourcePoint, 'x');\n if (!point || first && last) {\n continue;\n }\n if (first) {\n postponed.unshift(point);\n } else {\n points.push(point);\n if (!last) {\n break;\n }\n }\n }\n points.push(...postponed);\n}\n function findPoint(line, sourcePoint, property) {\n const point = line.interpolate(sourcePoint, property);\n if (!point) {\n return {};\n }\n const pointValue = point[property];\n const segments = line.segments;\n const linePoints = line.points;\n let first = false;\n let last = false;\n for(let i = 0; i < segments.length; i++){\n const segment = segments[i];\n const firstValue = linePoints[segment.start][property];\n const lastValue = linePoints[segment.end][property];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(pointValue, firstValue, lastValue)) {\n first = pointValue === firstValue;\n last = pointValue === lastValue;\n break;\n }\n }\n return {\n first,\n last,\n point\n };\n}\n\nclass simpleArc {\n constructor(opts){\n this.x = opts.x;\n this.y = opts.y;\n this.radius = opts.radius;\n }\n pathSegment(ctx, bounds, opts) {\n const { x , y , radius } = this;\n bounds = bounds || {\n start: 0,\n end: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T\n };\n ctx.arc(x, y, radius, bounds.end, bounds.start, true);\n return !opts.bounds;\n }\n interpolate(point) {\n const { x , y , radius } = this;\n const angle = point.angle;\n return {\n x: x + Math.cos(angle) * radius,\n y: y + Math.sin(angle) * radius,\n angle\n };\n }\n}\n\nfunction _getTarget(source) {\n const { chart , fill , line } = source;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) {\n return getLineByIndex(chart, fill);\n }\n if (fill === 'stack') {\n return _buildStackLine(source);\n }\n if (fill === 'shape') {\n return true;\n }\n const boundary = computeBoundary(source);\n if (boundary instanceof simpleArc) {\n return boundary;\n }\n return _createBoundaryLine(boundary, line);\n}\n function getLineByIndex(chart, index) {\n const meta = chart.getDatasetMeta(index);\n const visible = meta && chart.isDatasetVisible(index);\n return visible ? meta.dataset : null;\n}\nfunction computeBoundary(source) {\n const scale = source.scale || {};\n if (scale.getPointPositionForValue) {\n return computeCircularBoundary(source);\n }\n return computeLinearBoundary(source);\n}\nfunction computeLinearBoundary(source) {\n const { scale ={} , fill } = source;\n const pixel = _getTargetPixel(fill, scale);\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(pixel)) {\n const horizontal = scale.isHorizontal();\n return {\n x: horizontal ? pixel : null,\n y: horizontal ? null : pixel\n };\n }\n return null;\n}\nfunction computeCircularBoundary(source) {\n const { scale , fill } = source;\n const options = scale.options;\n const length = scale.getLabels().length;\n const start = options.reverse ? scale.max : scale.min;\n const value = _getTargetValue(fill, scale, start);\n const target = [];\n if (options.grid.circular) {\n const center = scale.getPointPositionForValue(0, start);\n return new simpleArc({\n x: center.x,\n y: center.y,\n radius: scale.getDistanceFromCenterForValue(value)\n });\n }\n for(let i = 0; i < length; ++i){\n target.push(scale.getPointPositionForValue(i, value));\n }\n return target;\n}\n\nfunction _drawfill(ctx, source, area) {\n const target = _getTarget(source);\n const { chart , index , line , scale , axis } = source;\n const lineOpts = line.options;\n const fillOption = lineOpts.fill;\n const color = lineOpts.backgroundColor;\n const { above =color , below =color } = fillOption || {};\n const meta = chart.getDatasetMeta(index);\n const clip = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ah)(chart, meta);\n if (target && line.points.length) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, area);\n doFill(ctx, {\n line,\n target,\n above,\n below,\n area,\n scale,\n axis,\n clip\n });\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);\n }\n}\nfunction doFill(ctx, cfg) {\n const { line , target , above , below , area , scale , clip } = cfg;\n const property = line._loop ? 'angle' : cfg.axis;\n ctx.save();\n let fillColor = below;\n if (below !== above) {\n if (property === 'x') {\n clipVertical(ctx, target, area.top);\n fill(ctx, {\n line,\n target,\n color: above,\n scale,\n property,\n clip\n });\n ctx.restore();\n ctx.save();\n clipVertical(ctx, target, area.bottom);\n } else if (property === 'y') {\n clipHorizontal(ctx, target, area.left);\n fill(ctx, {\n line,\n target,\n color: below,\n scale,\n property,\n clip\n });\n ctx.restore();\n ctx.save();\n clipHorizontal(ctx, target, area.right);\n fillColor = above;\n }\n }\n fill(ctx, {\n line,\n target,\n color: fillColor,\n scale,\n property,\n clip\n });\n ctx.restore();\n}\nfunction clipVertical(ctx, target, clipY) {\n const { segments , points } = target;\n let first = true;\n let lineLoop = false;\n ctx.beginPath();\n for (const segment of segments){\n const { start , end } = segment;\n const firstPoint = points[start];\n const lastPoint = points[_findSegmentEnd(start, end, points)];\n if (first) {\n ctx.moveTo(firstPoint.x, firstPoint.y);\n first = false;\n } else {\n ctx.lineTo(firstPoint.x, clipY);\n ctx.lineTo(firstPoint.x, firstPoint.y);\n }\n lineLoop = !!target.pathSegment(ctx, segment, {\n move: lineLoop\n });\n if (lineLoop) {\n ctx.closePath();\n } else {\n ctx.lineTo(lastPoint.x, clipY);\n }\n }\n ctx.lineTo(target.first().x, clipY);\n ctx.closePath();\n ctx.clip();\n}\nfunction clipHorizontal(ctx, target, clipX) {\n const { segments , points } = target;\n let first = true;\n let lineLoop = false;\n ctx.beginPath();\n for (const segment of segments){\n const { start , end } = segment;\n const firstPoint = points[start];\n const lastPoint = points[_findSegmentEnd(start, end, points)];\n if (first) {\n ctx.moveTo(firstPoint.x, firstPoint.y);\n first = false;\n } else {\n ctx.lineTo(clipX, firstPoint.y);\n ctx.lineTo(firstPoint.x, firstPoint.y);\n }\n lineLoop = !!target.pathSegment(ctx, segment, {\n move: lineLoop\n });\n if (lineLoop) {\n ctx.closePath();\n } else {\n ctx.lineTo(clipX, lastPoint.y);\n }\n }\n ctx.lineTo(clipX, target.first().y);\n ctx.closePath();\n ctx.clip();\n}\nfunction fill(ctx, cfg) {\n const { line , target , property , color , scale , clip } = cfg;\n const segments = _segments(line, target, property);\n for (const { source: src , target: tgt , start , end } of segments){\n const { style: { backgroundColor =color } = {} } = src;\n const notShape = target !== true;\n ctx.save();\n ctx.fillStyle = backgroundColor;\n clipBounds(ctx, scale, clip, notShape && _getBounds(property, start, end));\n ctx.beginPath();\n const lineLoop = !!line.pathSegment(ctx, src);\n let loop;\n if (notShape) {\n if (lineLoop) {\n ctx.closePath();\n } else {\n interpolatedLineTo(ctx, target, end, property);\n }\n const targetLoop = !!target.pathSegment(ctx, tgt, {\n move: lineLoop,\n reverse: true\n });\n loop = lineLoop && targetLoop;\n if (!loop) {\n interpolatedLineTo(ctx, target, start, property);\n }\n }\n ctx.closePath();\n ctx.fill(loop ? 'evenodd' : 'nonzero');\n ctx.restore();\n }\n}\nfunction clipBounds(ctx, scale, clip, bounds) {\n const chartArea = scale.chart.chartArea;\n const { property , start , end } = bounds || {};\n if (property === 'x' || property === 'y') {\n let left, top, right, bottom;\n if (property === 'x') {\n left = start;\n top = chartArea.top;\n right = end;\n bottom = chartArea.bottom;\n } else {\n left = chartArea.left;\n top = start;\n right = chartArea.right;\n bottom = end;\n }\n ctx.beginPath();\n if (clip) {\n left = Math.max(left, clip.left);\n right = Math.min(right, clip.right);\n top = Math.max(top, clip.top);\n bottom = Math.min(bottom, clip.bottom);\n }\n ctx.rect(left, top, right - left, bottom - top);\n ctx.clip();\n }\n}\nfunction interpolatedLineTo(ctx, target, point, property) {\n const interpolatedPoint = target.interpolate(point, property);\n if (interpolatedPoint) {\n ctx.lineTo(interpolatedPoint.x, interpolatedPoint.y);\n }\n}\n\nvar index = {\n id: 'filler',\n afterDatasetsUpdate (chart, _args, options) {\n const count = (chart.data.datasets || []).length;\n const sources = [];\n let meta, i, line, source;\n for(i = 0; i < count; ++i){\n meta = chart.getDatasetMeta(i);\n line = meta.dataset;\n source = null;\n if (line && line.options && line instanceof LineElement) {\n source = {\n visible: chart.isDatasetVisible(i),\n index: i,\n fill: _decodeFill(line, i, count),\n chart,\n axis: meta.controller.options.indexAxis,\n scale: meta.vScale,\n line\n };\n }\n meta.$filler = source;\n sources.push(source);\n }\n for(i = 0; i < count; ++i){\n source = sources[i];\n if (!source || source.fill === false) {\n continue;\n }\n source.fill = _resolveTarget(sources, i, options.propagate);\n }\n },\n beforeDraw (chart, _args, options) {\n const draw = options.drawTime === 'beforeDraw';\n const metasets = chart.getSortedVisibleDatasetMetas();\n const area = chart.chartArea;\n for(let i = metasets.length - 1; i >= 0; --i){\n const source = metasets[i].$filler;\n if (!source) {\n continue;\n }\n source.line.updateControlPoints(area, source.axis);\n if (draw && source.fill) {\n _drawfill(chart.ctx, source, area);\n }\n }\n },\n beforeDatasetsDraw (chart, _args, options) {\n if (options.drawTime !== 'beforeDatasetsDraw') {\n return;\n }\n const metasets = chart.getSortedVisibleDatasetMetas();\n for(let i = metasets.length - 1; i >= 0; --i){\n const source = metasets[i].$filler;\n if (_shouldApplyFill(source)) {\n _drawfill(chart.ctx, source, chart.chartArea);\n }\n }\n },\n beforeDatasetDraw (chart, args, options) {\n const source = args.meta.$filler;\n if (!_shouldApplyFill(source) || options.drawTime !== 'beforeDatasetDraw') {\n return;\n }\n _drawfill(chart.ctx, source, chart.chartArea);\n },\n defaults: {\n propagate: true,\n drawTime: 'beforeDatasetDraw'\n }\n};\n\nconst getBoxSize = (labelOpts, fontSize)=>{\n let { boxHeight =fontSize , boxWidth =fontSize } = labelOpts;\n if (labelOpts.usePointStyle) {\n boxHeight = Math.min(boxHeight, fontSize);\n boxWidth = labelOpts.pointStyleWidth || Math.min(boxWidth, fontSize);\n }\n return {\n boxWidth,\n boxHeight,\n itemHeight: Math.max(fontSize, boxHeight)\n };\n};\nconst itemsEqual = (a, b)=>a !== null && b !== null && a.datasetIndex === b.datasetIndex && a.index === b.index;\nclass Legend extends Element {\n constructor(config){\n super();\n this._added = false;\n this.legendHitBoxes = [];\n this._hoveredItem = null;\n this.doughnutMode = false;\n this.chart = config.chart;\n this.options = config.options;\n this.ctx = config.ctx;\n this.legendItems = undefined;\n this.columnSizes = undefined;\n this.lineWidths = undefined;\n this.maxHeight = undefined;\n this.maxWidth = undefined;\n this.top = undefined;\n this.bottom = undefined;\n this.left = undefined;\n this.right = undefined;\n this.height = undefined;\n this.width = undefined;\n this._margins = undefined;\n this.position = undefined;\n this.weight = undefined;\n this.fullSize = undefined;\n }\n update(maxWidth, maxHeight, margins) {\n this.maxWidth = maxWidth;\n this.maxHeight = maxHeight;\n this._margins = margins;\n this.setDimensions();\n this.buildLabels();\n this.fit();\n }\n setDimensions() {\n if (this.isHorizontal()) {\n this.width = this.maxWidth;\n this.left = this._margins.left;\n this.right = this.width;\n } else {\n this.height = this.maxHeight;\n this.top = this._margins.top;\n this.bottom = this.height;\n }\n }\n buildLabels() {\n const labelOpts = this.options.labels || {};\n let legendItems = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(labelOpts.generateLabels, [\n this.chart\n ], this) || [];\n if (labelOpts.filter) {\n legendItems = legendItems.filter((item)=>labelOpts.filter(item, this.chart.data));\n }\n if (labelOpts.sort) {\n legendItems = legendItems.sort((a, b)=>labelOpts.sort(a, b, this.chart.data));\n }\n if (this.options.reverse) {\n legendItems.reverse();\n }\n this.legendItems = legendItems;\n }\n fit() {\n const { options , ctx } = this;\n if (!options.display) {\n this.width = this.height = 0;\n return;\n }\n const labelOpts = options.labels;\n const labelFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(labelOpts.font);\n const fontSize = labelFont.size;\n const titleHeight = this._computeTitleHeight();\n const { boxWidth , itemHeight } = getBoxSize(labelOpts, fontSize);\n let width, height;\n ctx.font = labelFont.string;\n if (this.isHorizontal()) {\n width = this.maxWidth;\n height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;\n } else {\n height = this.maxHeight;\n width = this._fitCols(titleHeight, labelFont, boxWidth, itemHeight) + 10;\n }\n this.width = Math.min(width, options.maxWidth || this.maxWidth);\n this.height = Math.min(height, options.maxHeight || this.maxHeight);\n }\n _fitRows(titleHeight, fontSize, boxWidth, itemHeight) {\n const { ctx , maxWidth , options: { labels: { padding } } } = this;\n const hitboxes = this.legendHitBoxes = [];\n const lineWidths = this.lineWidths = [\n 0\n ];\n const lineHeight = itemHeight + padding;\n let totalHeight = titleHeight;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n let row = -1;\n let top = -lineHeight;\n this.legendItems.forEach((legendItem, i)=>{\n const itemWidth = boxWidth + fontSize / 2 + ctx.measureText(legendItem.text).width;\n if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) {\n totalHeight += lineHeight;\n lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0;\n top += lineHeight;\n row++;\n }\n hitboxes[i] = {\n left: 0,\n top,\n row,\n width: itemWidth,\n height: itemHeight\n };\n lineWidths[lineWidths.length - 1] += itemWidth + padding;\n });\n return totalHeight;\n }\n _fitCols(titleHeight, labelFont, boxWidth, _itemHeight) {\n const { ctx , maxHeight , options: { labels: { padding } } } = this;\n const hitboxes = this.legendHitBoxes = [];\n const columnSizes = this.columnSizes = [];\n const heightLimit = maxHeight - titleHeight;\n let totalWidth = padding;\n let currentColWidth = 0;\n let currentColHeight = 0;\n let left = 0;\n let col = 0;\n this.legendItems.forEach((legendItem, i)=>{\n const { itemWidth , itemHeight } = calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight);\n if (i > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) {\n totalWidth += currentColWidth + padding;\n columnSizes.push({\n width: currentColWidth,\n height: currentColHeight\n });\n left += currentColWidth + padding;\n col++;\n currentColWidth = currentColHeight = 0;\n }\n hitboxes[i] = {\n left,\n top: currentColHeight,\n col,\n width: itemWidth,\n height: itemHeight\n };\n currentColWidth = Math.max(currentColWidth, itemWidth);\n currentColHeight += itemHeight + padding;\n });\n totalWidth += currentColWidth;\n columnSizes.push({\n width: currentColWidth,\n height: currentColHeight\n });\n return totalWidth;\n }\n adjustHitBoxes() {\n if (!this.options.display) {\n return;\n }\n const titleHeight = this._computeTitleHeight();\n const { legendHitBoxes: hitboxes , options: { align , labels: { padding } , rtl } } = this;\n const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(rtl, this.left, this.width);\n if (this.isHorizontal()) {\n let row = 0;\n let left = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - this.lineWidths[row]);\n for (const hitbox of hitboxes){\n if (row !== hitbox.row) {\n row = hitbox.row;\n left = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - this.lineWidths[row]);\n }\n hitbox.top += this.top + titleHeight + padding;\n hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width);\n left += hitbox.width + padding;\n }\n } else {\n let col = 0;\n let top = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);\n for (const hitbox of hitboxes){\n if (hitbox.col !== col) {\n col = hitbox.col;\n top = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);\n }\n hitbox.top = top;\n hitbox.left += this.left + padding;\n hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width);\n top += hitbox.height + padding;\n }\n }\n }\n isHorizontal() {\n return this.options.position === 'top' || this.options.position === 'bottom';\n }\n draw() {\n if (this.options.display) {\n const ctx = this.ctx;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, this);\n this._draw();\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);\n }\n }\n _draw() {\n const { options: opts , columnSizes , lineWidths , ctx } = this;\n const { align , labels: labelOpts } = opts;\n const defaultColor = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.color;\n const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(opts.rtl, this.left, this.width);\n const labelFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(labelOpts.font);\n const { padding } = labelOpts;\n const fontSize = labelFont.size;\n const halfFontSize = fontSize / 2;\n let cursor;\n this.drawTitle();\n ctx.textAlign = rtlHelper.textAlign('left');\n ctx.textBaseline = 'middle';\n ctx.lineWidth = 0.5;\n ctx.font = labelFont.string;\n const { boxWidth , boxHeight , itemHeight } = getBoxSize(labelOpts, fontSize);\n const drawLegendBox = function(x, y, legendItem) {\n if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) {\n return;\n }\n ctx.save();\n const lineWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineWidth, 1);\n ctx.fillStyle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.fillStyle, defaultColor);\n ctx.lineCap = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineCap, 'butt');\n ctx.lineDashOffset = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDashOffset, 0);\n ctx.lineJoin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineJoin, 'miter');\n ctx.lineWidth = lineWidth;\n ctx.strokeStyle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.strokeStyle, defaultColor);\n ctx.setLineDash((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDash, []));\n if (labelOpts.usePointStyle) {\n const drawOptions = {\n radius: boxHeight * Math.SQRT2 / 2,\n pointStyle: legendItem.pointStyle,\n rotation: legendItem.rotation,\n borderWidth: lineWidth\n };\n const centerX = rtlHelper.xPlus(x, boxWidth / 2);\n const centerY = y + halfFontSize;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aE)(ctx, drawOptions, centerX, centerY, labelOpts.pointStyleWidth && boxWidth);\n } else {\n const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0);\n const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth);\n const borderRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(legendItem.borderRadius);\n ctx.beginPath();\n if (Object.values(borderRadius).some((v)=>v !== 0)) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {\n x: xBoxLeft,\n y: yBoxTop,\n w: boxWidth,\n h: boxHeight,\n radius: borderRadius\n });\n } else {\n ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight);\n }\n ctx.fill();\n if (lineWidth !== 0) {\n ctx.stroke();\n }\n }\n ctx.restore();\n };\n const fillText = function(x, y, legendItem) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, legendItem.text, x, y + itemHeight / 2, labelFont, {\n strikethrough: legendItem.hidden,\n textAlign: rtlHelper.textAlign(legendItem.textAlign)\n });\n };\n const isHorizontal = this.isHorizontal();\n const titleHeight = this._computeTitleHeight();\n if (isHorizontal) {\n cursor = {\n x: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - lineWidths[0]),\n y: this.top + padding + titleHeight,\n line: 0\n };\n } else {\n cursor = {\n x: this.left + padding,\n y: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height),\n line: 0\n };\n }\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aB)(this.ctx, opts.textDirection);\n const lineHeight = itemHeight + padding;\n this.legendItems.forEach((legendItem, i)=>{\n ctx.strokeStyle = legendItem.fontColor;\n ctx.fillStyle = legendItem.fontColor;\n const textWidth = ctx.measureText(legendItem.text).width;\n const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign));\n const width = boxWidth + halfFontSize + textWidth;\n let x = cursor.x;\n let y = cursor.y;\n rtlHelper.setWidth(this.width);\n if (isHorizontal) {\n if (i > 0 && x + width + padding > this.right) {\n y = cursor.y += lineHeight;\n cursor.line++;\n x = cursor.x = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - lineWidths[cursor.line]);\n }\n } else if (i > 0 && y + lineHeight > this.bottom) {\n x = cursor.x = x + columnSizes[cursor.line].width + padding;\n cursor.line++;\n y = cursor.y = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height);\n }\n const realX = rtlHelper.x(x);\n drawLegendBox(realX, y, legendItem);\n x = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aC)(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : this.right, opts.rtl);\n fillText(rtlHelper.x(x), y, legendItem);\n if (isHorizontal) {\n cursor.x += width + padding;\n } else if (typeof legendItem.text !== 'string') {\n const fontLineHeight = labelFont.lineHeight;\n cursor.y += calculateLegendItemHeight(legendItem, fontLineHeight) + padding;\n } else {\n cursor.y += lineHeight;\n }\n });\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aD)(this.ctx, opts.textDirection);\n }\n drawTitle() {\n const opts = this.options;\n const titleOpts = opts.title;\n const titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(titleOpts.font);\n const titlePadding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(titleOpts.padding);\n if (!titleOpts.display) {\n return;\n }\n const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(opts.rtl, this.left, this.width);\n const ctx = this.ctx;\n const position = titleOpts.position;\n const halfFontSize = titleFont.size / 2;\n const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize;\n let y;\n let left = this.left;\n let maxWidth = this.width;\n if (this.isHorizontal()) {\n maxWidth = Math.max(...this.lineWidths);\n y = this.top + topPaddingPlusHalfFontSize;\n left = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(opts.align, left, this.right - maxWidth);\n } else {\n const maxHeight = this.columnSizes.reduce((acc, size)=>Math.max(acc, size.height), 0);\n y = topPaddingPlusHalfFontSize + (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight());\n }\n const x = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(position, left, left + maxWidth);\n ctx.textAlign = rtlHelper.textAlign((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a1)(position));\n ctx.textBaseline = 'middle';\n ctx.strokeStyle = titleOpts.color;\n ctx.fillStyle = titleOpts.color;\n ctx.font = titleFont.string;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, titleOpts.text, x, y, titleFont);\n }\n _computeTitleHeight() {\n const titleOpts = this.options.title;\n const titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(titleOpts.font);\n const titlePadding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(titleOpts.padding);\n return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0;\n }\n _getLegendItemAt(x, y) {\n let i, hitBox, lh;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(x, this.left, this.right) && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(y, this.top, this.bottom)) {\n lh = this.legendHitBoxes;\n for(i = 0; i < lh.length; ++i){\n hitBox = lh[i];\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(x, hitBox.left, hitBox.left + hitBox.width) && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(y, hitBox.top, hitBox.top + hitBox.height)) {\n return this.legendItems[i];\n }\n }\n }\n return null;\n }\n handleEvent(e) {\n const opts = this.options;\n if (!isListened(e.type, opts)) {\n return;\n }\n const hoveredItem = this._getLegendItemAt(e.x, e.y);\n if (e.type === 'mousemove' || e.type === 'mouseout') {\n const previous = this._hoveredItem;\n const sameItem = itemsEqual(previous, hoveredItem);\n if (previous && !sameItem) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onLeave, [\n e,\n previous,\n this\n ], this);\n }\n this._hoveredItem = hoveredItem;\n if (hoveredItem && !sameItem) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onHover, [\n e,\n hoveredItem,\n this\n ], this);\n }\n } else if (hoveredItem) {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onClick, [\n e,\n hoveredItem,\n this\n ], this);\n }\n }\n}\nfunction calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight) {\n const itemWidth = calculateItemWidth(legendItem, boxWidth, labelFont, ctx);\n const itemHeight = calculateItemHeight(_itemHeight, legendItem, labelFont.lineHeight);\n return {\n itemWidth,\n itemHeight\n };\n}\nfunction calculateItemWidth(legendItem, boxWidth, labelFont, ctx) {\n let legendItemText = legendItem.text;\n if (legendItemText && typeof legendItemText !== 'string') {\n legendItemText = legendItemText.reduce((a, b)=>a.length > b.length ? a : b);\n }\n return boxWidth + labelFont.size / 2 + ctx.measureText(legendItemText).width;\n}\nfunction calculateItemHeight(_itemHeight, legendItem, fontLineHeight) {\n let itemHeight = _itemHeight;\n if (typeof legendItem.text !== 'string') {\n itemHeight = calculateLegendItemHeight(legendItem, fontLineHeight);\n }\n return itemHeight;\n}\nfunction calculateLegendItemHeight(legendItem, fontLineHeight) {\n const labelHeight = legendItem.text ? legendItem.text.length : 0;\n return fontLineHeight * labelHeight;\n}\nfunction isListened(type, opts) {\n if ((type === 'mousemove' || type === 'mouseout') && (opts.onHover || opts.onLeave)) {\n return true;\n }\n if (opts.onClick && (type === 'click' || type === 'mouseup')) {\n return true;\n }\n return false;\n}\nvar plugin_legend = {\n id: 'legend',\n _element: Legend,\n start (chart, _args, options) {\n const legend = chart.legend = new Legend({\n ctx: chart.ctx,\n options,\n chart\n });\n layouts.configure(chart, legend, options);\n layouts.addBox(chart, legend);\n },\n stop (chart) {\n layouts.removeBox(chart, chart.legend);\n delete chart.legend;\n },\n beforeUpdate (chart, _args, options) {\n const legend = chart.legend;\n layouts.configure(chart, legend, options);\n legend.options = options;\n },\n afterUpdate (chart) {\n const legend = chart.legend;\n legend.buildLabels();\n legend.adjustHitBoxes();\n },\n afterEvent (chart, args) {\n if (!args.replay) {\n chart.legend.handleEvent(args.event);\n }\n },\n defaults: {\n display: true,\n position: 'top',\n align: 'center',\n fullSize: true,\n reverse: false,\n weight: 1000,\n onClick (e, legendItem, legend) {\n const index = legendItem.datasetIndex;\n const ci = legend.chart;\n if (ci.isDatasetVisible(index)) {\n ci.hide(index);\n legendItem.hidden = true;\n } else {\n ci.show(index);\n legendItem.hidden = false;\n }\n },\n onHover: null,\n onLeave: null,\n labels: {\n color: (ctx)=>ctx.chart.options.color,\n boxWidth: 40,\n padding: 10,\n generateLabels (chart) {\n const datasets = chart.data.datasets;\n const { labels: { usePointStyle , pointStyle , textAlign , color , useBorderRadius , borderRadius } } = chart.legend.options;\n return chart._getSortedDatasetMetas().map((meta)=>{\n const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);\n const borderWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(style.borderWidth);\n return {\n text: datasets[meta.index].label,\n fillStyle: style.backgroundColor,\n fontColor: color,\n hidden: !meta.visible,\n lineCap: style.borderCapStyle,\n lineDash: style.borderDash,\n lineDashOffset: style.borderDashOffset,\n lineJoin: style.borderJoinStyle,\n lineWidth: (borderWidth.width + borderWidth.height) / 4,\n strokeStyle: style.borderColor,\n pointStyle: pointStyle || style.pointStyle,\n rotation: style.rotation,\n textAlign: textAlign || style.textAlign,\n borderRadius: useBorderRadius && (borderRadius || style.borderRadius),\n datasetIndex: meta.index\n };\n }, this);\n }\n },\n title: {\n color: (ctx)=>ctx.chart.options.color,\n display: false,\n position: 'center',\n text: ''\n }\n },\n descriptors: {\n _scriptable: (name)=>!name.startsWith('on'),\n labels: {\n _scriptable: (name)=>![\n 'generateLabels',\n 'filter',\n 'sort'\n ].includes(name)\n }\n }\n};\n\nclass Title extends Element {\n constructor(config){\n super();\n this.chart = config.chart;\n this.options = config.options;\n this.ctx = config.ctx;\n this._padding = undefined;\n this.top = undefined;\n this.bottom = undefined;\n this.left = undefined;\n this.right = undefined;\n this.width = undefined;\n this.height = undefined;\n this.position = undefined;\n this.weight = undefined;\n this.fullSize = undefined;\n }\n update(maxWidth, maxHeight) {\n const opts = this.options;\n this.left = 0;\n this.top = 0;\n if (!opts.display) {\n this.width = this.height = this.right = this.bottom = 0;\n return;\n }\n this.width = this.right = maxWidth;\n this.height = this.bottom = maxHeight;\n const lineCount = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(opts.text) ? opts.text.length : 1;\n this._padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(opts.padding);\n const textSize = lineCount * (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font).lineHeight + this._padding.height;\n if (this.isHorizontal()) {\n this.height = textSize;\n } else {\n this.width = textSize;\n }\n }\n isHorizontal() {\n const pos = this.options.position;\n return pos === 'top' || pos === 'bottom';\n }\n _drawArgs(offset) {\n const { top , left , bottom , right , options } = this;\n const align = options.align;\n let rotation = 0;\n let maxWidth, titleX, titleY;\n if (this.isHorizontal()) {\n titleX = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, left, right);\n titleY = top + offset;\n maxWidth = right - left;\n } else {\n if (options.position === 'left') {\n titleX = left + offset;\n titleY = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, bottom, top);\n rotation = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P * -0.5;\n } else {\n titleX = right - offset;\n titleY = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, top, bottom);\n rotation = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P * 0.5;\n }\n maxWidth = bottom - top;\n }\n return {\n titleX,\n titleY,\n maxWidth,\n rotation\n };\n }\n draw() {\n const ctx = this.ctx;\n const opts = this.options;\n if (!opts.display) {\n return;\n }\n const fontOpts = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font);\n const lineHeight = fontOpts.lineHeight;\n const offset = lineHeight / 2 + this._padding.top;\n const { titleX , titleY , maxWidth , rotation } = this._drawArgs(offset);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, opts.text, 0, 0, fontOpts, {\n color: opts.color,\n maxWidth,\n rotation,\n textAlign: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a1)(opts.align),\n textBaseline: 'middle',\n translation: [\n titleX,\n titleY\n ]\n });\n }\n}\nfunction createTitle(chart, titleOpts) {\n const title = new Title({\n ctx: chart.ctx,\n options: titleOpts,\n chart\n });\n layouts.configure(chart, title, titleOpts);\n layouts.addBox(chart, title);\n chart.titleBlock = title;\n}\nvar plugin_title = {\n id: 'title',\n _element: Title,\n start (chart, _args, options) {\n createTitle(chart, options);\n },\n stop (chart) {\n const titleBlock = chart.titleBlock;\n layouts.removeBox(chart, titleBlock);\n delete chart.titleBlock;\n },\n beforeUpdate (chart, _args, options) {\n const title = chart.titleBlock;\n layouts.configure(chart, title, options);\n title.options = options;\n },\n defaults: {\n align: 'center',\n display: false,\n font: {\n weight: 'bold'\n },\n fullSize: true,\n padding: 10,\n position: 'top',\n text: '',\n weight: 2000\n },\n defaultRoutes: {\n color: 'color'\n },\n descriptors: {\n _scriptable: true,\n _indexable: false\n }\n};\n\nconst map = new WeakMap();\nvar plugin_subtitle = {\n id: 'subtitle',\n start (chart, _args, options) {\n const title = new Title({\n ctx: chart.ctx,\n options,\n chart\n });\n layouts.configure(chart, title, options);\n layouts.addBox(chart, title);\n map.set(chart, title);\n },\n stop (chart) {\n layouts.removeBox(chart, map.get(chart));\n map.delete(chart);\n },\n beforeUpdate (chart, _args, options) {\n const title = map.get(chart);\n layouts.configure(chart, title, options);\n title.options = options;\n },\n defaults: {\n align: 'center',\n display: false,\n font: {\n weight: 'normal'\n },\n fullSize: true,\n padding: 0,\n position: 'top',\n text: '',\n weight: 1500\n },\n defaultRoutes: {\n color: 'color'\n },\n descriptors: {\n _scriptable: true,\n _indexable: false\n }\n};\n\nconst positioners = {\n average (items) {\n if (!items.length) {\n return false;\n }\n let i, len;\n let xSet = new Set();\n let y = 0;\n let count = 0;\n for(i = 0, len = items.length; i < len; ++i){\n const el = items[i].element;\n if (el && el.hasValue()) {\n const pos = el.tooltipPosition();\n xSet.add(pos.x);\n y += pos.y;\n ++count;\n }\n }\n if (count === 0 || xSet.size === 0) {\n return false;\n }\n const xAverage = [\n ...xSet\n ].reduce((a, b)=>a + b) / xSet.size;\n return {\n x: xAverage,\n y: y / count\n };\n },\n nearest (items, eventPosition) {\n if (!items.length) {\n return false;\n }\n let x = eventPosition.x;\n let y = eventPosition.y;\n let minDistance = Number.POSITIVE_INFINITY;\n let i, len, nearestElement;\n for(i = 0, len = items.length; i < len; ++i){\n const el = items[i].element;\n if (el && el.hasValue()) {\n const center = el.getCenterPoint();\n const d = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aF)(eventPosition, center);\n if (d < minDistance) {\n minDistance = d;\n nearestElement = el;\n }\n }\n }\n if (nearestElement) {\n const tp = nearestElement.tooltipPosition();\n x = tp.x;\n y = tp.y;\n }\n return {\n x,\n y\n };\n }\n};\nfunction pushOrConcat(base, toPush) {\n if (toPush) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(toPush)) {\n Array.prototype.push.apply(base, toPush);\n } else {\n base.push(toPush);\n }\n }\n return base;\n}\n function splitNewlines(str) {\n if ((typeof str === 'string' || str instanceof String) && str.indexOf('\\n') > -1) {\n return str.split('\\n');\n }\n return str;\n}\n function createTooltipItem(chart, item) {\n const { element , datasetIndex , index } = item;\n const controller = chart.getDatasetMeta(datasetIndex).controller;\n const { label , value } = controller.getLabelAndValue(index);\n return {\n chart,\n label,\n parsed: controller.getParsed(index),\n raw: chart.data.datasets[datasetIndex].data[index],\n formattedValue: value,\n dataset: controller.getDataset(),\n dataIndex: index,\n datasetIndex,\n element\n };\n}\n function getTooltipSize(tooltip, options) {\n const ctx = tooltip.chart.ctx;\n const { body , footer , title } = tooltip;\n const { boxWidth , boxHeight } = options;\n const bodyFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont);\n const titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.titleFont);\n const footerFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.footerFont);\n const titleLineCount = title.length;\n const footerLineCount = footer.length;\n const bodyLineItemCount = body.length;\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);\n let height = padding.height;\n let width = 0;\n let combinedBodyLength = body.reduce((count, bodyItem)=>count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0);\n combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length;\n if (titleLineCount) {\n height += titleLineCount * titleFont.lineHeight + (titleLineCount - 1) * options.titleSpacing + options.titleMarginBottom;\n }\n if (combinedBodyLength) {\n const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight;\n height += bodyLineItemCount * bodyLineHeight + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight + (combinedBodyLength - 1) * options.bodySpacing;\n }\n if (footerLineCount) {\n height += options.footerMarginTop + footerLineCount * footerFont.lineHeight + (footerLineCount - 1) * options.footerSpacing;\n }\n let widthPadding = 0;\n const maxLineWidth = function(line) {\n width = Math.max(width, ctx.measureText(line).width + widthPadding);\n };\n ctx.save();\n ctx.font = titleFont.string;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.title, maxLineWidth);\n ctx.font = bodyFont.string;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth);\n widthPadding = options.displayColors ? boxWidth + 2 + options.boxPadding : 0;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(body, (bodyItem)=>{\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.before, maxLineWidth);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.lines, maxLineWidth);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.after, maxLineWidth);\n });\n widthPadding = 0;\n ctx.font = footerFont.string;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.footer, maxLineWidth);\n ctx.restore();\n width += padding.width;\n return {\n width,\n height\n };\n}\nfunction determineYAlign(chart, size) {\n const { y , height } = size;\n if (y < height / 2) {\n return 'top';\n } else if (y > chart.height - height / 2) {\n return 'bottom';\n }\n return 'center';\n}\nfunction doesNotFitWithAlign(xAlign, chart, options, size) {\n const { x , width } = size;\n const caret = options.caretSize + options.caretPadding;\n if (xAlign === 'left' && x + width + caret > chart.width) {\n return true;\n }\n if (xAlign === 'right' && x - width - caret < 0) {\n return true;\n }\n}\nfunction determineXAlign(chart, options, size, yAlign) {\n const { x , width } = size;\n const { width: chartWidth , chartArea: { left , right } } = chart;\n let xAlign = 'center';\n if (yAlign === 'center') {\n xAlign = x <= (left + right) / 2 ? 'left' : 'right';\n } else if (x <= width / 2) {\n xAlign = 'left';\n } else if (x >= chartWidth - width / 2) {\n xAlign = 'right';\n }\n if (doesNotFitWithAlign(xAlign, chart, options, size)) {\n xAlign = 'center';\n }\n return xAlign;\n}\n function determineAlignment(chart, options, size) {\n const yAlign = size.yAlign || options.yAlign || determineYAlign(chart, size);\n return {\n xAlign: size.xAlign || options.xAlign || determineXAlign(chart, options, size, yAlign),\n yAlign\n };\n}\nfunction alignX(size, xAlign) {\n let { x , width } = size;\n if (xAlign === 'right') {\n x -= width;\n } else if (xAlign === 'center') {\n x -= width / 2;\n }\n return x;\n}\nfunction alignY(size, yAlign, paddingAndSize) {\n let { y , height } = size;\n if (yAlign === 'top') {\n y += paddingAndSize;\n } else if (yAlign === 'bottom') {\n y -= height + paddingAndSize;\n } else {\n y -= height / 2;\n }\n return y;\n}\n function getBackgroundPoint(options, size, alignment, chart) {\n const { caretSize , caretPadding , cornerRadius } = options;\n const { xAlign , yAlign } = alignment;\n const paddingAndSize = caretSize + caretPadding;\n const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(cornerRadius);\n let x = alignX(size, xAlign);\n const y = alignY(size, yAlign, paddingAndSize);\n if (yAlign === 'center') {\n if (xAlign === 'left') {\n x += paddingAndSize;\n } else if (xAlign === 'right') {\n x -= paddingAndSize;\n }\n } else if (xAlign === 'left') {\n x -= Math.max(topLeft, bottomLeft) + caretSize;\n } else if (xAlign === 'right') {\n x += Math.max(topRight, bottomRight) + caretSize;\n }\n return {\n x: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(x, 0, chart.width - size.width),\n y: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(y, 0, chart.height - size.height)\n };\n}\nfunction getAlignedX(tooltip, align, options) {\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);\n return align === 'center' ? tooltip.x + tooltip.width / 2 : align === 'right' ? tooltip.x + tooltip.width - padding.right : tooltip.x + padding.left;\n}\n function getBeforeAfterBodyLines(callback) {\n return pushOrConcat([], splitNewlines(callback));\n}\nfunction createTooltipContext(parent, tooltip, tooltipItems) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {\n tooltip,\n tooltipItems,\n type: 'tooltip'\n });\n}\nfunction overrideCallbacks(callbacks, context) {\n const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks;\n return override ? callbacks.override(override) : callbacks;\n}\nconst defaultCallbacks = {\n beforeTitle: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n title (tooltipItems) {\n if (tooltipItems.length > 0) {\n const item = tooltipItems[0];\n const labels = item.chart.data.labels;\n const labelCount = labels ? labels.length : 0;\n if (this && this.options && this.options.mode === 'dataset') {\n return item.dataset.label || '';\n } else if (item.label) {\n return item.label;\n } else if (labelCount > 0 && item.dataIndex < labelCount) {\n return labels[item.dataIndex];\n }\n }\n return '';\n },\n afterTitle: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n beforeBody: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n beforeLabel: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n label (tooltipItem) {\n if (this && this.options && this.options.mode === 'dataset') {\n return tooltipItem.label + ': ' + tooltipItem.formattedValue || tooltipItem.formattedValue;\n }\n let label = tooltipItem.dataset.label || '';\n if (label) {\n label += ': ';\n }\n const value = tooltipItem.formattedValue;\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) {\n label += value;\n }\n return label;\n },\n labelColor (tooltipItem) {\n const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);\n const options = meta.controller.getStyle(tooltipItem.dataIndex);\n return {\n borderColor: options.borderColor,\n backgroundColor: options.backgroundColor,\n borderWidth: options.borderWidth,\n borderDash: options.borderDash,\n borderDashOffset: options.borderDashOffset,\n borderRadius: 0\n };\n },\n labelTextColor () {\n return this.options.bodyColor;\n },\n labelPointStyle (tooltipItem) {\n const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);\n const options = meta.controller.getStyle(tooltipItem.dataIndex);\n return {\n pointStyle: options.pointStyle,\n rotation: options.rotation\n };\n },\n afterLabel: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n afterBody: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n beforeFooter: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n footer: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,\n afterFooter: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG\n};\n function invokeCallbackWithFallback(callbacks, name, ctx, arg) {\n const result = callbacks[name].call(ctx, arg);\n if (typeof result === 'undefined') {\n return defaultCallbacks[name].call(ctx, arg);\n }\n return result;\n}\nclass Tooltip extends Element {\n static positioners = positioners;\n constructor(config){\n super();\n this.opacity = 0;\n this._active = [];\n this._eventPosition = undefined;\n this._size = undefined;\n this._cachedAnimations = undefined;\n this._tooltipItems = [];\n this.$animations = undefined;\n this.$context = undefined;\n this.chart = config.chart;\n this.options = config.options;\n this.dataPoints = undefined;\n this.title = undefined;\n this.beforeBody = undefined;\n this.body = undefined;\n this.afterBody = undefined;\n this.footer = undefined;\n this.xAlign = undefined;\n this.yAlign = undefined;\n this.x = undefined;\n this.y = undefined;\n this.height = undefined;\n this.width = undefined;\n this.caretX = undefined;\n this.caretY = undefined;\n this.labelColors = undefined;\n this.labelPointStyles = undefined;\n this.labelTextColors = undefined;\n }\n initialize(options) {\n this.options = options;\n this._cachedAnimations = undefined;\n this.$context = undefined;\n }\n _resolveAnimations() {\n const cached = this._cachedAnimations;\n if (cached) {\n return cached;\n }\n const chart = this.chart;\n const options = this.options.setContext(this.getContext());\n const opts = options.enabled && chart.options.animation && options.animations;\n const animations = new Animations(this.chart, opts);\n if (opts._cacheable) {\n this._cachedAnimations = Object.freeze(animations);\n }\n return animations;\n }\n getContext() {\n return this.$context || (this.$context = createTooltipContext(this.chart.getContext(), this, this._tooltipItems));\n }\n getTitle(context, options) {\n const { callbacks } = options;\n const beforeTitle = invokeCallbackWithFallback(callbacks, 'beforeTitle', this, context);\n const title = invokeCallbackWithFallback(callbacks, 'title', this, context);\n const afterTitle = invokeCallbackWithFallback(callbacks, 'afterTitle', this, context);\n let lines = [];\n lines = pushOrConcat(lines, splitNewlines(beforeTitle));\n lines = pushOrConcat(lines, splitNewlines(title));\n lines = pushOrConcat(lines, splitNewlines(afterTitle));\n return lines;\n }\n getBeforeBody(tooltipItems, options) {\n return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'beforeBody', this, tooltipItems));\n }\n getBody(tooltipItems, options) {\n const { callbacks } = options;\n const bodyItems = [];\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltipItems, (context)=>{\n const bodyItem = {\n before: [],\n lines: [],\n after: []\n };\n const scoped = overrideCallbacks(callbacks, context);\n pushOrConcat(bodyItem.before, splitNewlines(invokeCallbackWithFallback(scoped, 'beforeLabel', this, context)));\n pushOrConcat(bodyItem.lines, invokeCallbackWithFallback(scoped, 'label', this, context));\n pushOrConcat(bodyItem.after, splitNewlines(invokeCallbackWithFallback(scoped, 'afterLabel', this, context)));\n bodyItems.push(bodyItem);\n });\n return bodyItems;\n }\n getAfterBody(tooltipItems, options) {\n return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'afterBody', this, tooltipItems));\n }\n getFooter(tooltipItems, options) {\n const { callbacks } = options;\n const beforeFooter = invokeCallbackWithFallback(callbacks, 'beforeFooter', this, tooltipItems);\n const footer = invokeCallbackWithFallback(callbacks, 'footer', this, tooltipItems);\n const afterFooter = invokeCallbackWithFallback(callbacks, 'afterFooter', this, tooltipItems);\n let lines = [];\n lines = pushOrConcat(lines, splitNewlines(beforeFooter));\n lines = pushOrConcat(lines, splitNewlines(footer));\n lines = pushOrConcat(lines, splitNewlines(afterFooter));\n return lines;\n }\n _createItems(options) {\n const active = this._active;\n const data = this.chart.data;\n const labelColors = [];\n const labelPointStyles = [];\n const labelTextColors = [];\n let tooltipItems = [];\n let i, len;\n for(i = 0, len = active.length; i < len; ++i){\n tooltipItems.push(createTooltipItem(this.chart, active[i]));\n }\n if (options.filter) {\n tooltipItems = tooltipItems.filter((element, index, array)=>options.filter(element, index, array, data));\n }\n if (options.itemSort) {\n tooltipItems = tooltipItems.sort((a, b)=>options.itemSort(a, b, data));\n }\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltipItems, (context)=>{\n const scoped = overrideCallbacks(options.callbacks, context);\n labelColors.push(invokeCallbackWithFallback(scoped, 'labelColor', this, context));\n labelPointStyles.push(invokeCallbackWithFallback(scoped, 'labelPointStyle', this, context));\n labelTextColors.push(invokeCallbackWithFallback(scoped, 'labelTextColor', this, context));\n });\n this.labelColors = labelColors;\n this.labelPointStyles = labelPointStyles;\n this.labelTextColors = labelTextColors;\n this.dataPoints = tooltipItems;\n return tooltipItems;\n }\n update(changed, replay) {\n const options = this.options.setContext(this.getContext());\n const active = this._active;\n let properties;\n let tooltipItems = [];\n if (!active.length) {\n if (this.opacity !== 0) {\n properties = {\n opacity: 0\n };\n }\n } else {\n const position = positioners[options.position].call(this, active, this._eventPosition);\n tooltipItems = this._createItems(options);\n this.title = this.getTitle(tooltipItems, options);\n this.beforeBody = this.getBeforeBody(tooltipItems, options);\n this.body = this.getBody(tooltipItems, options);\n this.afterBody = this.getAfterBody(tooltipItems, options);\n this.footer = this.getFooter(tooltipItems, options);\n const size = this._size = getTooltipSize(this, options);\n const positionAndSize = Object.assign({}, position, size);\n const alignment = determineAlignment(this.chart, options, positionAndSize);\n const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this.chart);\n this.xAlign = alignment.xAlign;\n this.yAlign = alignment.yAlign;\n properties = {\n opacity: 1,\n x: backgroundPoint.x,\n y: backgroundPoint.y,\n width: size.width,\n height: size.height,\n caretX: position.x,\n caretY: position.y\n };\n }\n this._tooltipItems = tooltipItems;\n this.$context = undefined;\n if (properties) {\n this._resolveAnimations().update(this, properties);\n }\n if (changed && options.external) {\n options.external.call(this, {\n chart: this.chart,\n tooltip: this,\n replay\n });\n }\n }\n drawCaret(tooltipPoint, ctx, size, options) {\n const caretPosition = this.getCaretPosition(tooltipPoint, size, options);\n ctx.lineTo(caretPosition.x1, caretPosition.y1);\n ctx.lineTo(caretPosition.x2, caretPosition.y2);\n ctx.lineTo(caretPosition.x3, caretPosition.y3);\n }\n getCaretPosition(tooltipPoint, size, options) {\n const { xAlign , yAlign } = this;\n const { caretSize , cornerRadius } = options;\n const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(cornerRadius);\n const { x: ptX , y: ptY } = tooltipPoint;\n const { width , height } = size;\n let x1, x2, x3, y1, y2, y3;\n if (yAlign === 'center') {\n y2 = ptY + height / 2;\n if (xAlign === 'left') {\n x1 = ptX;\n x2 = x1 - caretSize;\n y1 = y2 + caretSize;\n y3 = y2 - caretSize;\n } else {\n x1 = ptX + width;\n x2 = x1 + caretSize;\n y1 = y2 - caretSize;\n y3 = y2 + caretSize;\n }\n x3 = x1;\n } else {\n if (xAlign === 'left') {\n x2 = ptX + Math.max(topLeft, bottomLeft) + caretSize;\n } else if (xAlign === 'right') {\n x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize;\n } else {\n x2 = this.caretX;\n }\n if (yAlign === 'top') {\n y1 = ptY;\n y2 = y1 - caretSize;\n x1 = x2 - caretSize;\n x3 = x2 + caretSize;\n } else {\n y1 = ptY + height;\n y2 = y1 + caretSize;\n x1 = x2 + caretSize;\n x3 = x2 - caretSize;\n }\n y3 = y1;\n }\n return {\n x1,\n x2,\n x3,\n y1,\n y2,\n y3\n };\n }\n drawTitle(pt, ctx, options) {\n const title = this.title;\n const length = title.length;\n let titleFont, titleSpacing, i;\n if (length) {\n const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(options.rtl, this.x, this.width);\n pt.x = getAlignedX(this, options.titleAlign, options);\n ctx.textAlign = rtlHelper.textAlign(options.titleAlign);\n ctx.textBaseline = 'middle';\n titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.titleFont);\n titleSpacing = options.titleSpacing;\n ctx.fillStyle = options.titleColor;\n ctx.font = titleFont.string;\n for(i = 0; i < length; ++i){\n ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2);\n pt.y += titleFont.lineHeight + titleSpacing;\n if (i + 1 === length) {\n pt.y += options.titleMarginBottom - titleSpacing;\n }\n }\n }\n }\n _drawColorBox(ctx, pt, i, rtlHelper, options) {\n const labelColor = this.labelColors[i];\n const labelPointStyle = this.labelPointStyles[i];\n const { boxHeight , boxWidth } = options;\n const bodyFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont);\n const colorX = getAlignedX(this, 'left', options);\n const rtlColorX = rtlHelper.x(colorX);\n const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;\n const colorY = pt.y + yOffSet;\n if (options.usePointStyle) {\n const drawOptions = {\n radius: Math.min(boxWidth, boxHeight) / 2,\n pointStyle: labelPointStyle.pointStyle,\n rotation: labelPointStyle.rotation,\n borderWidth: 1\n };\n const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2;\n const centerY = colorY + boxHeight / 2;\n ctx.strokeStyle = options.multiKeyBackground;\n ctx.fillStyle = options.multiKeyBackground;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.av)(ctx, drawOptions, centerX, centerY);\n ctx.strokeStyle = labelColor.borderColor;\n ctx.fillStyle = labelColor.backgroundColor;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.av)(ctx, drawOptions, centerX, centerY);\n } else {\n ctx.lineWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(labelColor.borderWidth) ? Math.max(...Object.values(labelColor.borderWidth)) : labelColor.borderWidth || 1;\n ctx.strokeStyle = labelColor.borderColor;\n ctx.setLineDash(labelColor.borderDash || []);\n ctx.lineDashOffset = labelColor.borderDashOffset || 0;\n const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth);\n const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2);\n const borderRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(labelColor.borderRadius);\n if (Object.values(borderRadius).some((v)=>v !== 0)) {\n ctx.beginPath();\n ctx.fillStyle = options.multiKeyBackground;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {\n x: outerX,\n y: colorY,\n w: boxWidth,\n h: boxHeight,\n radius: borderRadius\n });\n ctx.fill();\n ctx.stroke();\n ctx.fillStyle = labelColor.backgroundColor;\n ctx.beginPath();\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {\n x: innerX,\n y: colorY + 1,\n w: boxWidth - 2,\n h: boxHeight - 2,\n radius: borderRadius\n });\n ctx.fill();\n } else {\n ctx.fillStyle = options.multiKeyBackground;\n ctx.fillRect(outerX, colorY, boxWidth, boxHeight);\n ctx.strokeRect(outerX, colorY, boxWidth, boxHeight);\n ctx.fillStyle = labelColor.backgroundColor;\n ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2);\n }\n }\n ctx.fillStyle = this.labelTextColors[i];\n }\n drawBody(pt, ctx, options) {\n const { body } = this;\n const { bodySpacing , bodyAlign , displayColors , boxHeight , boxWidth , boxPadding } = options;\n const bodyFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont);\n let bodyLineHeight = bodyFont.lineHeight;\n let xLinePadding = 0;\n const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(options.rtl, this.x, this.width);\n const fillLineOfText = function(line) {\n ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2);\n pt.y += bodyLineHeight + bodySpacing;\n };\n const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign);\n let bodyItem, textColor, lines, i, j, ilen, jlen;\n ctx.textAlign = bodyAlign;\n ctx.textBaseline = 'middle';\n ctx.font = bodyFont.string;\n pt.x = getAlignedX(this, bodyAlignForCalculation, options);\n ctx.fillStyle = options.bodyColor;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.beforeBody, fillLineOfText);\n xLinePadding = displayColors && bodyAlignForCalculation !== 'right' ? bodyAlign === 'center' ? boxWidth / 2 + boxPadding : boxWidth + 2 + boxPadding : 0;\n for(i = 0, ilen = body.length; i < ilen; ++i){\n bodyItem = body[i];\n textColor = this.labelTextColors[i];\n ctx.fillStyle = textColor;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.before, fillLineOfText);\n lines = bodyItem.lines;\n if (displayColors && lines.length) {\n this._drawColorBox(ctx, pt, i, rtlHelper, options);\n bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);\n }\n for(j = 0, jlen = lines.length; j < jlen; ++j){\n fillLineOfText(lines[j]);\n bodyLineHeight = bodyFont.lineHeight;\n }\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.after, fillLineOfText);\n }\n xLinePadding = 0;\n bodyLineHeight = bodyFont.lineHeight;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.afterBody, fillLineOfText);\n pt.y -= bodySpacing;\n }\n drawFooter(pt, ctx, options) {\n const footer = this.footer;\n const length = footer.length;\n let footerFont, i;\n if (length) {\n const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(options.rtl, this.x, this.width);\n pt.x = getAlignedX(this, options.footerAlign, options);\n pt.y += options.footerMarginTop;\n ctx.textAlign = rtlHelper.textAlign(options.footerAlign);\n ctx.textBaseline = 'middle';\n footerFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.footerFont);\n ctx.fillStyle = options.footerColor;\n ctx.font = footerFont.string;\n for(i = 0; i < length; ++i){\n ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2);\n pt.y += footerFont.lineHeight + options.footerSpacing;\n }\n }\n }\n drawBackground(pt, ctx, tooltipSize, options) {\n const { xAlign , yAlign } = this;\n const { x , y } = pt;\n const { width , height } = tooltipSize;\n const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(options.cornerRadius);\n ctx.fillStyle = options.backgroundColor;\n ctx.strokeStyle = options.borderColor;\n ctx.lineWidth = options.borderWidth;\n ctx.beginPath();\n ctx.moveTo(x + topLeft, y);\n if (yAlign === 'top') {\n this.drawCaret(pt, ctx, tooltipSize, options);\n }\n ctx.lineTo(x + width - topRight, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + topRight);\n if (yAlign === 'center' && xAlign === 'right') {\n this.drawCaret(pt, ctx, tooltipSize, options);\n }\n ctx.lineTo(x + width, y + height - bottomRight);\n ctx.quadraticCurveTo(x + width, y + height, x + width - bottomRight, y + height);\n if (yAlign === 'bottom') {\n this.drawCaret(pt, ctx, tooltipSize, options);\n }\n ctx.lineTo(x + bottomLeft, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - bottomLeft);\n if (yAlign === 'center' && xAlign === 'left') {\n this.drawCaret(pt, ctx, tooltipSize, options);\n }\n ctx.lineTo(x, y + topLeft);\n ctx.quadraticCurveTo(x, y, x + topLeft, y);\n ctx.closePath();\n ctx.fill();\n if (options.borderWidth > 0) {\n ctx.stroke();\n }\n }\n _updateAnimationTarget(options) {\n const chart = this.chart;\n const anims = this.$animations;\n const animX = anims && anims.x;\n const animY = anims && anims.y;\n if (animX || animY) {\n const position = positioners[options.position].call(this, this._active, this._eventPosition);\n if (!position) {\n return;\n }\n const size = this._size = getTooltipSize(this, options);\n const positionAndSize = Object.assign({}, position, this._size);\n const alignment = determineAlignment(chart, options, positionAndSize);\n const point = getBackgroundPoint(options, positionAndSize, alignment, chart);\n if (animX._to !== point.x || animY._to !== point.y) {\n this.xAlign = alignment.xAlign;\n this.yAlign = alignment.yAlign;\n this.width = size.width;\n this.height = size.height;\n this.caretX = position.x;\n this.caretY = position.y;\n this._resolveAnimations().update(this, point);\n }\n }\n }\n _willRender() {\n return !!this.opacity;\n }\n draw(ctx) {\n const options = this.options.setContext(this.getContext());\n let opacity = this.opacity;\n if (!opacity) {\n return;\n }\n this._updateAnimationTarget(options);\n const tooltipSize = {\n width: this.width,\n height: this.height\n };\n const pt = {\n x: this.x,\n y: this.y\n };\n opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity;\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);\n const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length;\n if (options.enabled && hasTooltipContent) {\n ctx.save();\n ctx.globalAlpha = opacity;\n this.drawBackground(pt, ctx, tooltipSize, options);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aB)(ctx, options.textDirection);\n pt.y += padding.top;\n this.drawTitle(pt, ctx, options);\n this.drawBody(pt, ctx, options);\n this.drawFooter(pt, ctx, options);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aD)(ctx, options.textDirection);\n ctx.restore();\n }\n }\n getActiveElements() {\n return this._active || [];\n }\n setActiveElements(activeElements, eventPosition) {\n const lastActive = this._active;\n const active = activeElements.map(({ datasetIndex , index })=>{\n const meta = this.chart.getDatasetMeta(datasetIndex);\n if (!meta) {\n throw new Error('Cannot find a dataset at index ' + datasetIndex);\n }\n return {\n datasetIndex,\n element: meta.data[index],\n index\n };\n });\n const changed = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(lastActive, active);\n const positionChanged = this._positionChanged(active, eventPosition);\n if (changed || positionChanged) {\n this._active = active;\n this._eventPosition = eventPosition;\n this._ignoreReplayEvents = true;\n this.update(true);\n }\n }\n handleEvent(e, replay, inChartArea = true) {\n if (replay && this._ignoreReplayEvents) {\n return false;\n }\n this._ignoreReplayEvents = false;\n const options = this.options;\n const lastActive = this._active || [];\n const active = this._getActiveElements(e, lastActive, replay, inChartArea);\n const positionChanged = this._positionChanged(active, e);\n const changed = replay || !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(active, lastActive) || positionChanged;\n if (changed) {\n this._active = active;\n if (options.enabled || options.external) {\n this._eventPosition = {\n x: e.x,\n y: e.y\n };\n this.update(true, replay);\n }\n }\n return changed;\n }\n _getActiveElements(e, lastActive, replay, inChartArea) {\n const options = this.options;\n if (e.type === 'mouseout') {\n return [];\n }\n if (!inChartArea) {\n return lastActive.filter((i)=>this.chart.data.datasets[i.datasetIndex] && this.chart.getDatasetMeta(i.datasetIndex).controller.getParsed(i.index) !== undefined);\n }\n const active = this.chart.getElementsAtEventForMode(e, options.mode, options, replay);\n if (options.reverse) {\n active.reverse();\n }\n return active;\n }\n _positionChanged(active, e) {\n const { caretX , caretY , options } = this;\n const position = positioners[options.position].call(this, active, e);\n return position !== false && (caretX !== position.x || caretY !== position.y);\n }\n}\nvar plugin_tooltip = {\n id: 'tooltip',\n _element: Tooltip,\n positioners,\n afterInit (chart, _args, options) {\n if (options) {\n chart.tooltip = new Tooltip({\n chart,\n options\n });\n }\n },\n beforeUpdate (chart, _args, options) {\n if (chart.tooltip) {\n chart.tooltip.initialize(options);\n }\n },\n reset (chart, _args, options) {\n if (chart.tooltip) {\n chart.tooltip.initialize(options);\n }\n },\n afterDraw (chart) {\n const tooltip = chart.tooltip;\n if (tooltip && tooltip._willRender()) {\n const args = {\n tooltip\n };\n if (chart.notifyPlugins('beforeTooltipDraw', {\n ...args,\n cancelable: true\n }) === false) {\n return;\n }\n tooltip.draw(chart.ctx);\n chart.notifyPlugins('afterTooltipDraw', args);\n }\n },\n afterEvent (chart, args) {\n if (chart.tooltip) {\n const useFinalPosition = args.replay;\n if (chart.tooltip.handleEvent(args.event, useFinalPosition, args.inChartArea)) {\n args.changed = true;\n }\n }\n },\n defaults: {\n enabled: true,\n external: null,\n position: 'average',\n backgroundColor: 'rgba(0,0,0,0.8)',\n titleColor: '#fff',\n titleFont: {\n weight: 'bold'\n },\n titleSpacing: 2,\n titleMarginBottom: 6,\n titleAlign: 'left',\n bodyColor: '#fff',\n bodySpacing: 2,\n bodyFont: {},\n bodyAlign: 'left',\n footerColor: '#fff',\n footerSpacing: 2,\n footerMarginTop: 6,\n footerFont: {\n weight: 'bold'\n },\n footerAlign: 'left',\n padding: 6,\n caretPadding: 2,\n caretSize: 5,\n cornerRadius: 6,\n boxHeight: (ctx, opts)=>opts.bodyFont.size,\n boxWidth: (ctx, opts)=>opts.bodyFont.size,\n multiKeyBackground: '#fff',\n displayColors: true,\n boxPadding: 0,\n borderColor: 'rgba(0,0,0,0)',\n borderWidth: 0,\n animation: {\n duration: 400,\n easing: 'easeOutQuart'\n },\n animations: {\n numbers: {\n type: 'number',\n properties: [\n 'x',\n 'y',\n 'width',\n 'height',\n 'caretX',\n 'caretY'\n ]\n },\n opacity: {\n easing: 'linear',\n duration: 200\n }\n },\n callbacks: defaultCallbacks\n },\n defaultRoutes: {\n bodyFont: 'font',\n footerFont: 'font',\n titleFont: 'font'\n },\n descriptors: {\n _scriptable: (name)=>name !== 'filter' && name !== 'itemSort' && name !== 'external',\n _indexable: false,\n callbacks: {\n _scriptable: false,\n _indexable: false\n },\n animation: {\n _fallback: false\n },\n animations: {\n _fallback: 'animation'\n }\n },\n additionalOptionScopes: [\n 'interaction'\n ]\n};\n\nvar plugins = /*#__PURE__*/Object.freeze({\n__proto__: null,\nColors: plugin_colors,\nDecimation: plugin_decimation,\nFiller: index,\nLegend: plugin_legend,\nSubTitle: plugin_subtitle,\nTitle: plugin_title,\nTooltip: plugin_tooltip\n});\n\nconst addIfString = (labels, raw, index, addedLabels)=>{\n if (typeof raw === 'string') {\n index = labels.push(raw) - 1;\n addedLabels.unshift({\n index,\n label: raw\n });\n } else if (isNaN(raw)) {\n index = null;\n }\n return index;\n};\nfunction findOrAddLabel(labels, raw, index, addedLabels) {\n const first = labels.indexOf(raw);\n if (first === -1) {\n return addIfString(labels, raw, index, addedLabels);\n }\n const last = labels.lastIndexOf(raw);\n return first !== last ? index : first;\n}\nconst validIndex = (index, max)=>index === null ? null : (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(Math.round(index), 0, max);\nfunction _getLabelForValue(value) {\n const labels = this.getLabels();\n if (value >= 0 && value < labels.length) {\n return labels[value];\n }\n return value;\n}\nclass CategoryScale extends Scale {\n static id = 'category';\n static defaults = {\n ticks: {\n callback: _getLabelForValue\n }\n };\n constructor(cfg){\n super(cfg);\n this._startValue = undefined;\n this._valueRange = 0;\n this._addedLabels = [];\n }\n init(scaleOptions) {\n const added = this._addedLabels;\n if (added.length) {\n const labels = this.getLabels();\n for (const { index , label } of added){\n if (labels[index] === label) {\n labels.splice(index, 1);\n }\n }\n this._addedLabels = [];\n }\n super.init(scaleOptions);\n }\n parse(raw, index) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(raw)) {\n return null;\n }\n const labels = this.getLabels();\n index = isFinite(index) && labels[index] === raw ? index : findOrAddLabel(labels, raw, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(index, raw), this._addedLabels);\n return validIndex(index, labels.length - 1);\n }\n determineDataLimits() {\n const { minDefined , maxDefined } = this.getUserBounds();\n let { min , max } = this.getMinMax(true);\n if (this.options.bounds === 'ticks') {\n if (!minDefined) {\n min = 0;\n }\n if (!maxDefined) {\n max = this.getLabels().length - 1;\n }\n }\n this.min = min;\n this.max = max;\n }\n buildTicks() {\n const min = this.min;\n const max = this.max;\n const offset = this.options.offset;\n const ticks = [];\n let labels = this.getLabels();\n labels = min === 0 && max === labels.length - 1 ? labels : labels.slice(min, max + 1);\n this._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1);\n this._startValue = this.min - (offset ? 0.5 : 0);\n for(let value = min; value <= max; value++){\n ticks.push({\n value\n });\n }\n return ticks;\n }\n getLabelForValue(value) {\n return _getLabelForValue.call(this, value);\n }\n configure() {\n super.configure();\n if (!this.isHorizontal()) {\n this._reversePixels = !this._reversePixels;\n }\n }\n getPixelForValue(value) {\n if (typeof value !== 'number') {\n value = this.parse(value);\n }\n return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);\n }\n getPixelForTick(index) {\n const ticks = this.ticks;\n if (index < 0 || index > ticks.length - 1) {\n return null;\n }\n return this.getPixelForValue(ticks[index].value);\n }\n getValueForPixel(pixel) {\n return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange);\n }\n getBasePixel() {\n return this.bottom;\n }\n}\n\nfunction generateTicks$1(generationOptions, dataRange) {\n const ticks = [];\n const MIN_SPACING = 1e-14;\n const { bounds , step , min , max , precision , count , maxTicks , maxDigits , includeBounds } = generationOptions;\n const unit = step || 1;\n const maxSpaces = maxTicks - 1;\n const { min: rmin , max: rmax } = dataRange;\n const minDefined = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(min);\n const maxDefined = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(max);\n const countDefined = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(count);\n const minSpacing = (rmax - rmin) / (maxDigits + 1);\n let spacing = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aI)((rmax - rmin) / maxSpaces / unit) * unit;\n let factor, niceMin, niceMax, numSpaces;\n if (spacing < MIN_SPACING && !minDefined && !maxDefined) {\n return [\n {\n value: rmin\n },\n {\n value: rmax\n }\n ];\n }\n numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);\n if (numSpaces > maxSpaces) {\n spacing = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aI)(numSpaces * spacing / maxSpaces / unit) * unit;\n }\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(precision)) {\n factor = Math.pow(10, precision);\n spacing = Math.ceil(spacing * factor) / factor;\n }\n if (bounds === 'ticks') {\n niceMin = Math.floor(rmin / spacing) * spacing;\n niceMax = Math.ceil(rmax / spacing) * spacing;\n } else {\n niceMin = rmin;\n niceMax = rmax;\n }\n if (minDefined && maxDefined && step && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aJ)((max - min) / step, spacing / 1000)) {\n numSpaces = Math.round(Math.min((max - min) / spacing, maxTicks));\n spacing = (max - min) / numSpaces;\n niceMin = min;\n niceMax = max;\n } else if (countDefined) {\n niceMin = minDefined ? min : niceMin;\n niceMax = maxDefined ? max : niceMax;\n numSpaces = count - 1;\n spacing = (niceMax - niceMin) / numSpaces;\n } else {\n numSpaces = (niceMax - niceMin) / spacing;\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aK)(numSpaces, Math.round(numSpaces), spacing / 1000)) {\n numSpaces = Math.round(numSpaces);\n } else {\n numSpaces = Math.ceil(numSpaces);\n }\n }\n const decimalPlaces = Math.max((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aL)(spacing), (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aL)(niceMin));\n factor = Math.pow(10, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(precision) ? decimalPlaces : precision);\n niceMin = Math.round(niceMin * factor) / factor;\n niceMax = Math.round(niceMax * factor) / factor;\n let j = 0;\n if (minDefined) {\n if (includeBounds && niceMin !== min) {\n ticks.push({\n value: min\n });\n if (niceMin < min) {\n j++;\n }\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aK)(Math.round((niceMin + j * spacing) * factor) / factor, min, relativeLabelSize(min, minSpacing, generationOptions))) {\n j++;\n }\n } else if (niceMin < min) {\n j++;\n }\n }\n for(; j < numSpaces; ++j){\n const tickValue = Math.round((niceMin + j * spacing) * factor) / factor;\n if (maxDefined && tickValue > max) {\n break;\n }\n ticks.push({\n value: tickValue\n });\n }\n if (maxDefined && includeBounds && niceMax !== max) {\n if (ticks.length && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aK)(ticks[ticks.length - 1].value, max, relativeLabelSize(max, minSpacing, generationOptions))) {\n ticks[ticks.length - 1].value = max;\n } else {\n ticks.push({\n value: max\n });\n }\n } else if (!maxDefined || niceMax === max) {\n ticks.push({\n value: niceMax\n });\n }\n return ticks;\n}\nfunction relativeLabelSize(value, minSpacing, { horizontal , minRotation }) {\n const rad = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(minRotation);\n const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 0.001;\n const length = 0.75 * minSpacing * ('' + value).length;\n return Math.min(minSpacing / ratio, length);\n}\nclass LinearScaleBase extends Scale {\n constructor(cfg){\n super(cfg);\n this.start = undefined;\n this.end = undefined;\n this._startValue = undefined;\n this._endValue = undefined;\n this._valueRange = 0;\n }\n parse(raw, index) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(raw)) {\n return null;\n }\n if ((typeof raw === 'number' || raw instanceof Number) && !isFinite(+raw)) {\n return null;\n }\n return +raw;\n }\n handleTickRangeOptions() {\n const { beginAtZero } = this.options;\n const { minDefined , maxDefined } = this.getUserBounds();\n let { min , max } = this;\n const setMin = (v)=>min = minDefined ? min : v;\n const setMax = (v)=>max = maxDefined ? max : v;\n if (beginAtZero) {\n const minSign = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(min);\n const maxSign = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(max);\n if (minSign < 0 && maxSign < 0) {\n setMax(0);\n } else if (minSign > 0 && maxSign > 0) {\n setMin(0);\n }\n }\n if (min === max) {\n let offset = max === 0 ? 1 : Math.abs(max * 0.05);\n setMax(max + offset);\n if (!beginAtZero) {\n setMin(min - offset);\n }\n }\n this.min = min;\n this.max = max;\n }\n getTickLimit() {\n const tickOpts = this.options.ticks;\n let { maxTicksLimit , stepSize } = tickOpts;\n let maxTicks;\n if (stepSize) {\n maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1;\n if (maxTicks > 1000) {\n console.warn(`scales.${this.id}.ticks.stepSize: ${stepSize} would result generating up to ${maxTicks} ticks. Limiting to 1000.`);\n maxTicks = 1000;\n }\n } else {\n maxTicks = this.computeTickLimit();\n maxTicksLimit = maxTicksLimit || 11;\n }\n if (maxTicksLimit) {\n maxTicks = Math.min(maxTicksLimit, maxTicks);\n }\n return maxTicks;\n }\n computeTickLimit() {\n return Number.POSITIVE_INFINITY;\n }\n buildTicks() {\n const opts = this.options;\n const tickOpts = opts.ticks;\n let maxTicks = this.getTickLimit();\n maxTicks = Math.max(2, maxTicks);\n const numericGeneratorOptions = {\n maxTicks,\n bounds: opts.bounds,\n min: opts.min,\n max: opts.max,\n precision: tickOpts.precision,\n step: tickOpts.stepSize,\n count: tickOpts.count,\n maxDigits: this._maxDigits(),\n horizontal: this.isHorizontal(),\n minRotation: tickOpts.minRotation || 0,\n includeBounds: tickOpts.includeBounds !== false\n };\n const dataRange = this._range || this;\n const ticks = generateTicks$1(numericGeneratorOptions, dataRange);\n if (opts.bounds === 'ticks') {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aH)(ticks, this, 'value');\n }\n if (opts.reverse) {\n ticks.reverse();\n this.start = this.max;\n this.end = this.min;\n } else {\n this.start = this.min;\n this.end = this.max;\n }\n return ticks;\n }\n configure() {\n const ticks = this.ticks;\n let start = this.min;\n let end = this.max;\n super.configure();\n if (this.options.offset && ticks.length) {\n const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2;\n start -= offset;\n end += offset;\n }\n this._startValue = start;\n this._endValue = end;\n this._valueRange = end - start;\n }\n getLabelForValue(value) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(value, this.chart.options.locale, this.options.ticks.format);\n }\n}\n\nclass LinearScale extends LinearScaleBase {\n static id = 'linear';\n static defaults = {\n ticks: {\n callback: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM.formatters.numeric\n }\n };\n determineDataLimits() {\n const { min , max } = this.getMinMax(true);\n this.min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? min : 0;\n this.max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? max : 1;\n this.handleTickRangeOptions();\n }\n computeTickLimit() {\n const horizontal = this.isHorizontal();\n const length = horizontal ? this.width : this.height;\n const minRotation = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.ticks.minRotation);\n const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 0.001;\n const tickFont = this._resolveTickFontOptions(0);\n return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio));\n }\n getPixelForValue(value) {\n return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);\n }\n getValueForPixel(pixel) {\n return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange;\n }\n}\n\nconst log10Floor = (v)=>Math.floor((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(v));\nconst changeExponent = (v, m)=>Math.pow(10, log10Floor(v) + m);\nfunction isMajor(tickVal) {\n const remain = tickVal / Math.pow(10, log10Floor(tickVal));\n return remain === 1;\n}\nfunction steps(min, max, rangeExp) {\n const rangeStep = Math.pow(10, rangeExp);\n const start = Math.floor(min / rangeStep);\n const end = Math.ceil(max / rangeStep);\n return end - start;\n}\nfunction startExp(min, max) {\n const range = max - min;\n let rangeExp = log10Floor(range);\n while(steps(min, max, rangeExp) > 10){\n rangeExp++;\n }\n while(steps(min, max, rangeExp) < 10){\n rangeExp--;\n }\n return Math.min(rangeExp, log10Floor(min));\n}\n function generateTicks(generationOptions, { min , max }) {\n min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.min, min);\n const ticks = [];\n const minExp = log10Floor(min);\n let exp = startExp(min, max);\n let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;\n const stepSize = Math.pow(10, exp);\n const base = minExp > exp ? Math.pow(10, minExp) : 0;\n const start = Math.round((min - base) * precision) / precision;\n const offset = Math.floor((min - base) / stepSize / 10) * stepSize * 10;\n let significand = Math.floor((start - offset) / Math.pow(10, exp));\n let value = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.min, Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision);\n while(value < max){\n ticks.push({\n value,\n major: isMajor(value),\n significand\n });\n if (significand >= 10) {\n significand = significand < 15 ? 15 : 20;\n } else {\n significand++;\n }\n if (significand >= 20) {\n exp++;\n significand = 2;\n precision = exp >= 0 ? 1 : precision;\n }\n value = Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision;\n }\n const lastTick = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.max, value);\n ticks.push({\n value: lastTick,\n major: isMajor(lastTick),\n significand\n });\n return ticks;\n}\nclass LogarithmicScale extends Scale {\n static id = 'logarithmic';\n static defaults = {\n ticks: {\n callback: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM.formatters.logarithmic,\n major: {\n enabled: true\n }\n }\n };\n constructor(cfg){\n super(cfg);\n this.start = undefined;\n this.end = undefined;\n this._startValue = undefined;\n this._valueRange = 0;\n }\n parse(raw, index) {\n const value = LinearScaleBase.prototype.parse.apply(this, [\n raw,\n index\n ]);\n if (value === 0) {\n this._zero = true;\n return undefined;\n }\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(value) && value > 0 ? value : null;\n }\n determineDataLimits() {\n const { min , max } = this.getMinMax(true);\n this.min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? Math.max(0, min) : null;\n this.max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? Math.max(0, max) : null;\n if (this.options.beginAtZero) {\n this._zero = true;\n }\n if (this._zero && this.min !== this._suggestedMin && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(this._userMin)) {\n this.min = min === changeExponent(this.min, 0) ? changeExponent(this.min, -1) : changeExponent(this.min, 0);\n }\n this.handleTickRangeOptions();\n }\n handleTickRangeOptions() {\n const { minDefined , maxDefined } = this.getUserBounds();\n let min = this.min;\n let max = this.max;\n const setMin = (v)=>min = minDefined ? min : v;\n const setMax = (v)=>max = maxDefined ? max : v;\n if (min === max) {\n if (min <= 0) {\n setMin(1);\n setMax(10);\n } else {\n setMin(changeExponent(min, -1));\n setMax(changeExponent(max, +1));\n }\n }\n if (min <= 0) {\n setMin(changeExponent(max, -1));\n }\n if (max <= 0) {\n setMax(changeExponent(min, +1));\n }\n this.min = min;\n this.max = max;\n }\n buildTicks() {\n const opts = this.options;\n const generationOptions = {\n min: this._userMin,\n max: this._userMax\n };\n const ticks = generateTicks(generationOptions, this);\n if (opts.bounds === 'ticks') {\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aH)(ticks, this, 'value');\n }\n if (opts.reverse) {\n ticks.reverse();\n this.start = this.max;\n this.end = this.min;\n } else {\n this.start = this.min;\n this.end = this.max;\n }\n return ticks;\n }\n getLabelForValue(value) {\n return value === undefined ? '0' : (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(value, this.chart.options.locale, this.options.ticks.format);\n }\n configure() {\n const start = this.min;\n super.configure();\n this._startValue = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(start);\n this._valueRange = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(this.max) - (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(start);\n }\n getPixelForValue(value) {\n if (value === undefined || value === 0) {\n value = this.min;\n }\n if (value === null || isNaN(value)) {\n return NaN;\n }\n return this.getPixelForDecimal(value === this.min ? 0 : ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(value) - this._startValue) / this._valueRange);\n }\n getValueForPixel(pixel) {\n const decimal = this.getDecimalForPixel(pixel);\n return Math.pow(10, this._startValue + decimal * this._valueRange);\n }\n}\n\nfunction getTickBackdropHeight(opts) {\n const tickOpts = opts.ticks;\n if (tickOpts.display && opts.display) {\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(tickOpts.backdropPadding);\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(tickOpts.font && tickOpts.font.size, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.font.size) + padding.height;\n }\n return 0;\n}\nfunction measureLabelSize(ctx, font, label) {\n label = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label : [\n label\n ];\n return {\n w: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aO)(ctx, font.string, label),\n h: label.length * font.lineHeight\n };\n}\nfunction determineLimits(angle, pos, size, min, max) {\n if (angle === min || angle === max) {\n return {\n start: pos - size / 2,\n end: pos + size / 2\n };\n } else if (angle < min || angle > max) {\n return {\n start: pos - size,\n end: pos\n };\n }\n return {\n start: pos,\n end: pos + size\n };\n}\n function fitWithPointLabels(scale) {\n const orig = {\n l: scale.left + scale._padding.left,\n r: scale.right - scale._padding.right,\n t: scale.top + scale._padding.top,\n b: scale.bottom - scale._padding.bottom\n };\n const limits = Object.assign({}, orig);\n const labelSizes = [];\n const padding = [];\n const valueCount = scale._pointLabels.length;\n const pointLabelOpts = scale.options.pointLabels;\n const additionalAngle = pointLabelOpts.centerPointLabels ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / valueCount : 0;\n for(let i = 0; i < valueCount; i++){\n const opts = pointLabelOpts.setContext(scale.getPointLabelContext(i));\n padding[i] = opts.padding;\n const pointPosition = scale.getPointPosition(i, scale.drawingArea + padding[i], additionalAngle);\n const plFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font);\n const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i]);\n labelSizes[i] = textSize;\n const angleRadians = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(scale.getIndexAngle(i) + additionalAngle);\n const angle = Math.round((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.U)(angleRadians));\n const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);\n const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);\n updateLimits(limits, orig, angleRadians, hLimits, vLimits);\n }\n scale.setCenterPoint(orig.l - limits.l, limits.r - orig.r, orig.t - limits.t, limits.b - orig.b);\n scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding);\n}\nfunction updateLimits(limits, orig, angle, hLimits, vLimits) {\n const sin = Math.abs(Math.sin(angle));\n const cos = Math.abs(Math.cos(angle));\n let x = 0;\n let y = 0;\n if (hLimits.start < orig.l) {\n x = (orig.l - hLimits.start) / sin;\n limits.l = Math.min(limits.l, orig.l - x);\n } else if (hLimits.end > orig.r) {\n x = (hLimits.end - orig.r) / sin;\n limits.r = Math.max(limits.r, orig.r + x);\n }\n if (vLimits.start < orig.t) {\n y = (orig.t - vLimits.start) / cos;\n limits.t = Math.min(limits.t, orig.t - y);\n } else if (vLimits.end > orig.b) {\n y = (vLimits.end - orig.b) / cos;\n limits.b = Math.max(limits.b, orig.b + y);\n }\n}\nfunction createPointLabelItem(scale, index, itemOpts) {\n const outerDistance = scale.drawingArea;\n const { extra , additionalAngle , padding , size } = itemOpts;\n const pointLabelPosition = scale.getPointPosition(index, outerDistance + extra + padding, additionalAngle);\n const angle = Math.round((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.U)((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(pointLabelPosition.angle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H)));\n const y = yForAngle(pointLabelPosition.y, size.h, angle);\n const textAlign = getTextAlignForAngle(angle);\n const left = leftForTextAlign(pointLabelPosition.x, size.w, textAlign);\n return {\n visible: true,\n x: pointLabelPosition.x,\n y,\n textAlign,\n left,\n top: y,\n right: left + size.w,\n bottom: y + size.h\n };\n}\nfunction isNotOverlapped(item, area) {\n if (!area) {\n return true;\n }\n const { left , top , right , bottom } = item;\n const apexesInArea = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({\n x: left,\n y: top\n }, area) || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({\n x: left,\n y: bottom\n }, area) || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({\n x: right,\n y: top\n }, area) || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({\n x: right,\n y: bottom\n }, area);\n return !apexesInArea;\n}\nfunction buildPointLabelItems(scale, labelSizes, padding) {\n const items = [];\n const valueCount = scale._pointLabels.length;\n const opts = scale.options;\n const { centerPointLabels , display } = opts.pointLabels;\n const itemOpts = {\n extra: getTickBackdropHeight(opts) / 2,\n additionalAngle: centerPointLabels ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / valueCount : 0\n };\n let area;\n for(let i = 0; i < valueCount; i++){\n itemOpts.padding = padding[i];\n itemOpts.size = labelSizes[i];\n const item = createPointLabelItem(scale, i, itemOpts);\n items.push(item);\n if (display === 'auto') {\n item.visible = isNotOverlapped(item, area);\n if (item.visible) {\n area = item;\n }\n }\n }\n return items;\n}\nfunction getTextAlignForAngle(angle) {\n if (angle === 0 || angle === 180) {\n return 'center';\n } else if (angle < 180) {\n return 'left';\n }\n return 'right';\n}\nfunction leftForTextAlign(x, w, align) {\n if (align === 'right') {\n x -= w;\n } else if (align === 'center') {\n x -= w / 2;\n }\n return x;\n}\nfunction yForAngle(y, h, angle) {\n if (angle === 90 || angle === 270) {\n y -= h / 2;\n } else if (angle > 270 || angle < 90) {\n y -= h;\n }\n return y;\n}\nfunction drawPointLabelBox(ctx, opts, item) {\n const { left , top , right , bottom } = item;\n const { backdropColor } = opts;\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(backdropColor)) {\n const borderRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(opts.borderRadius);\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(opts.backdropPadding);\n ctx.fillStyle = backdropColor;\n const backdropLeft = left - padding.left;\n const backdropTop = top - padding.top;\n const backdropWidth = right - left + padding.width;\n const backdropHeight = bottom - top + padding.height;\n if (Object.values(borderRadius).some((v)=>v !== 0)) {\n ctx.beginPath();\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {\n x: backdropLeft,\n y: backdropTop,\n w: backdropWidth,\n h: backdropHeight,\n radius: borderRadius\n });\n ctx.fill();\n } else {\n ctx.fillRect(backdropLeft, backdropTop, backdropWidth, backdropHeight);\n }\n }\n}\nfunction drawPointLabels(scale, labelCount) {\n const { ctx , options: { pointLabels } } = scale;\n for(let i = labelCount - 1; i >= 0; i--){\n const item = scale._pointLabelItems[i];\n if (!item.visible) {\n continue;\n }\n const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i));\n drawPointLabelBox(ctx, optsAtIndex, item);\n const plFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(optsAtIndex.font);\n const { x , y , textAlign } = item;\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, scale._pointLabels[i], x, y + plFont.lineHeight / 2, plFont, {\n color: optsAtIndex.color,\n textAlign: textAlign,\n textBaseline: 'middle'\n });\n }\n}\nfunction pathRadiusLine(scale, radius, circular, labelCount) {\n const { ctx } = scale;\n if (circular) {\n ctx.arc(scale.xCenter, scale.yCenter, radius, 0, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);\n } else {\n let pointPosition = scale.getPointPosition(0, radius);\n ctx.moveTo(pointPosition.x, pointPosition.y);\n for(let i = 1; i < labelCount; i++){\n pointPosition = scale.getPointPosition(i, radius);\n ctx.lineTo(pointPosition.x, pointPosition.y);\n }\n }\n}\nfunction drawRadiusLine(scale, gridLineOpts, radius, labelCount, borderOpts) {\n const ctx = scale.ctx;\n const circular = gridLineOpts.circular;\n const { color , lineWidth } = gridLineOpts;\n if (!circular && !labelCount || !color || !lineWidth || radius < 0) {\n return;\n }\n ctx.save();\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth;\n ctx.setLineDash(borderOpts.dash || []);\n ctx.lineDashOffset = borderOpts.dashOffset;\n ctx.beginPath();\n pathRadiusLine(scale, radius, circular, labelCount);\n ctx.closePath();\n ctx.stroke();\n ctx.restore();\n}\nfunction createPointLabelContext(parent, index, label) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {\n label,\n index,\n type: 'pointLabel'\n });\n}\nclass RadialLinearScale extends LinearScaleBase {\n static id = 'radialLinear';\n static defaults = {\n display: true,\n animate: true,\n position: 'chartArea',\n angleLines: {\n display: true,\n lineWidth: 1,\n borderDash: [],\n borderDashOffset: 0.0\n },\n grid: {\n circular: false\n },\n startAngle: 0,\n ticks: {\n showLabelBackdrop: true,\n callback: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM.formatters.numeric\n },\n pointLabels: {\n backdropColor: undefined,\n backdropPadding: 2,\n display: true,\n font: {\n size: 10\n },\n callback (label) {\n return label;\n },\n padding: 5,\n centerPointLabels: false\n }\n };\n static defaultRoutes = {\n 'angleLines.color': 'borderColor',\n 'pointLabels.color': 'color',\n 'ticks.color': 'color'\n };\n static descriptors = {\n angleLines: {\n _fallback: 'grid'\n }\n };\n constructor(cfg){\n super(cfg);\n this.xCenter = undefined;\n this.yCenter = undefined;\n this.drawingArea = undefined;\n this._pointLabels = [];\n this._pointLabelItems = [];\n }\n setDimensions() {\n const padding = this._padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(getTickBackdropHeight(this.options) / 2);\n const w = this.width = this.maxWidth - padding.width;\n const h = this.height = this.maxHeight - padding.height;\n this.xCenter = Math.floor(this.left + w / 2 + padding.left);\n this.yCenter = Math.floor(this.top + h / 2 + padding.top);\n this.drawingArea = Math.floor(Math.min(w, h) / 2);\n }\n determineDataLimits() {\n const { min , max } = this.getMinMax(false);\n this.min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : 0;\n this.max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : 0;\n this.handleTickRangeOptions();\n }\n computeTickLimit() {\n return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options));\n }\n generateTickLabels(ticks) {\n LinearScaleBase.prototype.generateTickLabels.call(this, ticks);\n this._pointLabels = this.getLabels().map((value, index)=>{\n const label = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.pointLabels.callback, [\n value,\n index\n ], this);\n return label || label === 0 ? label : '';\n }).filter((v, i)=>this.chart.getDataVisibility(i));\n }\n fit() {\n const opts = this.options;\n if (opts.display && opts.pointLabels.display) {\n fitWithPointLabels(this);\n } else {\n this.setCenterPoint(0, 0, 0, 0);\n }\n }\n setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) {\n this.xCenter += Math.floor((leftMovement - rightMovement) / 2);\n this.yCenter += Math.floor((topMovement - bottomMovement) / 2);\n this.drawingArea -= Math.min(this.drawingArea / 2, Math.max(leftMovement, rightMovement, topMovement, bottomMovement));\n }\n getIndexAngle(index) {\n const angleMultiplier = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T / (this._pointLabels.length || 1);\n const startAngle = this.options.startAngle || 0;\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(index * angleMultiplier + (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(startAngle));\n }\n getDistanceFromCenterForValue(value) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) {\n return NaN;\n }\n const scalingFactor = this.drawingArea / (this.max - this.min);\n if (this.options.reverse) {\n return (this.max - value) * scalingFactor;\n }\n return (value - this.min) * scalingFactor;\n }\n getValueForDistanceFromCenter(distance) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(distance)) {\n return NaN;\n }\n const scaledDistance = distance / (this.drawingArea / (this.max - this.min));\n return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance;\n }\n getPointLabelContext(index) {\n const pointLabels = this._pointLabels || [];\n if (index >= 0 && index < pointLabels.length) {\n const pointLabel = pointLabels[index];\n return createPointLabelContext(this.getContext(), index, pointLabel);\n }\n }\n getPointPosition(index, distanceFromCenter, additionalAngle = 0) {\n const angle = this.getIndexAngle(index) - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H + additionalAngle;\n return {\n x: Math.cos(angle) * distanceFromCenter + this.xCenter,\n y: Math.sin(angle) * distanceFromCenter + this.yCenter,\n angle\n };\n }\n getPointPositionForValue(index, value) {\n return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));\n }\n getBasePosition(index) {\n return this.getPointPositionForValue(index || 0, this.getBaseValue());\n }\n getPointLabelPosition(index) {\n const { left , top , right , bottom } = this._pointLabelItems[index];\n return {\n left,\n top,\n right,\n bottom\n };\n }\n drawBackground() {\n const { backgroundColor , grid: { circular } } = this.options;\n if (backgroundColor) {\n const ctx = this.ctx;\n ctx.save();\n ctx.beginPath();\n pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this._pointLabels.length);\n ctx.closePath();\n ctx.fillStyle = backgroundColor;\n ctx.fill();\n ctx.restore();\n }\n }\n drawGrid() {\n const ctx = this.ctx;\n const opts = this.options;\n const { angleLines , grid , border } = opts;\n const labelCount = this._pointLabels.length;\n let i, offset, position;\n if (opts.pointLabels.display) {\n drawPointLabels(this, labelCount);\n }\n if (grid.display) {\n this.ticks.forEach((tick, index)=>{\n if (index !== 0 || index === 0 && this.min < 0) {\n offset = this.getDistanceFromCenterForValue(tick.value);\n const context = this.getContext(index);\n const optsAtIndex = grid.setContext(context);\n const optsAtIndexBorder = border.setContext(context);\n drawRadiusLine(this, optsAtIndex, offset, labelCount, optsAtIndexBorder);\n }\n });\n }\n if (angleLines.display) {\n ctx.save();\n for(i = labelCount - 1; i >= 0; i--){\n const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i));\n const { color , lineWidth } = optsAtIndex;\n if (!lineWidth || !color) {\n continue;\n }\n ctx.lineWidth = lineWidth;\n ctx.strokeStyle = color;\n ctx.setLineDash(optsAtIndex.borderDash);\n ctx.lineDashOffset = optsAtIndex.borderDashOffset;\n offset = this.getDistanceFromCenterForValue(opts.reverse ? this.min : this.max);\n position = this.getPointPosition(i, offset);\n ctx.beginPath();\n ctx.moveTo(this.xCenter, this.yCenter);\n ctx.lineTo(position.x, position.y);\n ctx.stroke();\n }\n ctx.restore();\n }\n }\n drawBorder() {}\n drawLabels() {\n const ctx = this.ctx;\n const opts = this.options;\n const tickOpts = opts.ticks;\n if (!tickOpts.display) {\n return;\n }\n const startAngle = this.getIndexAngle(0);\n let offset, width;\n ctx.save();\n ctx.translate(this.xCenter, this.yCenter);\n ctx.rotate(startAngle);\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n this.ticks.forEach((tick, index)=>{\n if (index === 0 && this.min >= 0 && !opts.reverse) {\n return;\n }\n const optsAtIndex = tickOpts.setContext(this.getContext(index));\n const tickFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(optsAtIndex.font);\n offset = this.getDistanceFromCenterForValue(this.ticks[index].value);\n if (optsAtIndex.showLabelBackdrop) {\n ctx.font = tickFont.string;\n width = ctx.measureText(tick.label).width;\n ctx.fillStyle = optsAtIndex.backdropColor;\n const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(optsAtIndex.backdropPadding);\n ctx.fillRect(-width / 2 - padding.left, -offset - tickFont.size / 2 - padding.top, width + padding.width, tickFont.size + padding.height);\n }\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, tick.label, 0, -offset, tickFont, {\n color: optsAtIndex.color,\n strokeColor: optsAtIndex.textStrokeColor,\n strokeWidth: optsAtIndex.textStrokeWidth\n });\n });\n ctx.restore();\n }\n drawTitle() {}\n}\n\nconst INTERVALS = {\n millisecond: {\n common: true,\n size: 1,\n steps: 1000\n },\n second: {\n common: true,\n size: 1000,\n steps: 60\n },\n minute: {\n common: true,\n size: 60000,\n steps: 60\n },\n hour: {\n common: true,\n size: 3600000,\n steps: 24\n },\n day: {\n common: true,\n size: 86400000,\n steps: 30\n },\n week: {\n common: false,\n size: 604800000,\n steps: 4\n },\n month: {\n common: true,\n size: 2.628e9,\n steps: 12\n },\n quarter: {\n common: false,\n size: 7.884e9,\n steps: 4\n },\n year: {\n common: true,\n size: 3.154e10\n }\n};\n const UNITS = /* #__PURE__ */ Object.keys(INTERVALS);\n function sorter(a, b) {\n return a - b;\n}\n function parse(scale, input) {\n if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(input)) {\n return null;\n }\n const adapter = scale._adapter;\n const { parser , round , isoWeekday } = scale._parseOpts;\n let value = input;\n if (typeof parser === 'function') {\n value = parser(value);\n }\n if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) {\n value = typeof parser === 'string' ? adapter.parse(value, parser) : adapter.parse(value);\n }\n if (value === null) {\n return null;\n }\n if (round) {\n value = round === 'week' && ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, 'isoWeek', isoWeekday) : adapter.startOf(value, round);\n }\n return +value;\n}\n function determineUnitForAutoTicks(minUnit, min, max, capacity) {\n const ilen = UNITS.length;\n for(let i = UNITS.indexOf(minUnit); i < ilen - 1; ++i){\n const interval = INTERVALS[UNITS[i]];\n const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER;\n if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) {\n return UNITS[i];\n }\n }\n return UNITS[ilen - 1];\n}\n function determineUnitForFormatting(scale, numTicks, minUnit, min, max) {\n for(let i = UNITS.length - 1; i >= UNITS.indexOf(minUnit); i--){\n const unit = UNITS[i];\n if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= numTicks - 1) {\n return unit;\n }\n }\n return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];\n}\n function determineMajorUnit(unit) {\n for(let i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i){\n if (INTERVALS[UNITS[i]].common) {\n return UNITS[i];\n }\n }\n}\n function addTick(ticks, time, timestamps) {\n if (!timestamps) {\n ticks[time] = true;\n } else if (timestamps.length) {\n const { lo , hi } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aQ)(timestamps, time);\n const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi];\n ticks[timestamp] = true;\n }\n}\n function setMajorTicks(scale, ticks, map, majorUnit) {\n const adapter = scale._adapter;\n const first = +adapter.startOf(ticks[0].value, majorUnit);\n const last = ticks[ticks.length - 1].value;\n let major, index;\n for(major = first; major <= last; major = +adapter.add(major, 1, majorUnit)){\n index = map[major];\n if (index >= 0) {\n ticks[index].major = true;\n }\n }\n return ticks;\n}\n function ticksFromTimestamps(scale, values, majorUnit) {\n const ticks = [];\n const map = {};\n const ilen = values.length;\n let i, value;\n for(i = 0; i < ilen; ++i){\n value = values[i];\n map[value] = i;\n ticks.push({\n value,\n major: false\n });\n }\n return ilen === 0 || !majorUnit ? ticks : setMajorTicks(scale, ticks, map, majorUnit);\n}\nclass TimeScale extends Scale {\n static id = 'time';\n static defaults = {\n bounds: 'data',\n adapters: {},\n time: {\n parser: false,\n unit: false,\n round: false,\n isoWeekday: false,\n minUnit: 'millisecond',\n displayFormats: {}\n },\n ticks: {\n source: 'auto',\n callback: false,\n major: {\n enabled: false\n }\n }\n };\n constructor(props){\n super(props);\n this._cache = {\n data: [],\n labels: [],\n all: []\n };\n this._unit = 'day';\n this._majorUnit = undefined;\n this._offsets = {};\n this._normalized = false;\n this._parseOpts = undefined;\n }\n init(scaleOpts, opts = {}) {\n const time = scaleOpts.time || (scaleOpts.time = {});\n const adapter = this._adapter = new adapters._date(scaleOpts.adapters.date);\n adapter.init(opts);\n (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(time.displayFormats, adapter.formats());\n this._parseOpts = {\n parser: time.parser,\n round: time.round,\n isoWeekday: time.isoWeekday\n };\n super.init(scaleOpts);\n this._normalized = opts.normalized;\n }\n parse(raw, index) {\n if (raw === undefined) {\n return null;\n }\n return parse(this, raw);\n }\n beforeLayout() {\n super.beforeLayout();\n this._cache = {\n data: [],\n labels: [],\n all: []\n };\n }\n determineDataLimits() {\n const options = this.options;\n const adapter = this._adapter;\n const unit = options.time.unit || 'day';\n let { min , max , minDefined , maxDefined } = this.getUserBounds();\n function _applyBounds(bounds) {\n if (!minDefined && !isNaN(bounds.min)) {\n min = Math.min(min, bounds.min);\n }\n if (!maxDefined && !isNaN(bounds.max)) {\n max = Math.max(max, bounds.max);\n }\n }\n if (!minDefined || !maxDefined) {\n _applyBounds(this._getLabelBounds());\n if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') {\n _applyBounds(this.getMinMax(false));\n }\n }\n min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit);\n max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1;\n this.min = Math.min(min, max - 1);\n this.max = Math.max(min + 1, max);\n }\n _getLabelBounds() {\n const arr = this.getLabelTimestamps();\n let min = Number.POSITIVE_INFINITY;\n let max = Number.NEGATIVE_INFINITY;\n if (arr.length) {\n min = arr[0];\n max = arr[arr.length - 1];\n }\n return {\n min,\n max\n };\n }\n buildTicks() {\n const options = this.options;\n const timeOpts = options.time;\n const tickOpts = options.ticks;\n const timestamps = tickOpts.source === 'labels' ? this.getLabelTimestamps() : this._generate();\n if (options.bounds === 'ticks' && timestamps.length) {\n this.min = this._userMin || timestamps[0];\n this.max = this._userMax || timestamps[timestamps.length - 1];\n }\n const min = this.min;\n const max = this.max;\n const ticks = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aP)(timestamps, min, max);\n this._unit = timeOpts.unit || (tickOpts.autoSkip ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min)) : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max));\n this._majorUnit = !tickOpts.major.enabled || this._unit === 'year' ? undefined : determineMajorUnit(this._unit);\n this.initOffsets(timestamps);\n if (options.reverse) {\n ticks.reverse();\n }\n return ticksFromTimestamps(this, ticks, this._majorUnit);\n }\n afterAutoSkip() {\n if (this.options.offsetAfterAutoskip) {\n this.initOffsets(this.ticks.map((tick)=>+tick.value));\n }\n }\n initOffsets(timestamps = []) {\n let start = 0;\n let end = 0;\n let first, last;\n if (this.options.offset && timestamps.length) {\n first = this.getDecimalForValue(timestamps[0]);\n if (timestamps.length === 1) {\n start = 1 - first;\n } else {\n start = (this.getDecimalForValue(timestamps[1]) - first) / 2;\n }\n last = this.getDecimalForValue(timestamps[timestamps.length - 1]);\n if (timestamps.length === 1) {\n end = last;\n } else {\n end = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;\n }\n }\n const limit = timestamps.length < 3 ? 0.5 : 0.25;\n start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(start, 0, limit);\n end = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(end, 0, limit);\n this._offsets = {\n start,\n end,\n factor: 1 / (start + 1 + end)\n };\n }\n _generate() {\n const adapter = this._adapter;\n const min = this.min;\n const max = this.max;\n const options = this.options;\n const timeOpts = options.time;\n const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));\n const stepSize = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.ticks.stepSize, 1);\n const weekday = minor === 'week' ? timeOpts.isoWeekday : false;\n const hasWeekday = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(weekday) || weekday === true;\n const ticks = {};\n let first = min;\n let time, count;\n if (hasWeekday) {\n first = +adapter.startOf(first, 'isoWeek', weekday);\n }\n first = +adapter.startOf(first, hasWeekday ? 'day' : minor);\n if (adapter.diff(max, min, minor) > 100000 * stepSize) {\n throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor);\n }\n const timestamps = options.ticks.source === 'data' && this.getDataTimestamps();\n for(time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++){\n addTick(ticks, time, timestamps);\n }\n if (time === max || options.bounds === 'ticks' || count === 1) {\n addTick(ticks, time, timestamps);\n }\n return Object.keys(ticks).sort(sorter).map((x)=>+x);\n }\n getLabelForValue(value) {\n const adapter = this._adapter;\n const timeOpts = this.options.time;\n if (timeOpts.tooltipFormat) {\n return adapter.format(value, timeOpts.tooltipFormat);\n }\n return adapter.format(value, timeOpts.displayFormats.datetime);\n }\n format(value, format) {\n const options = this.options;\n const formats = options.time.displayFormats;\n const unit = this._unit;\n const fmt = format || formats[unit];\n return this._adapter.format(value, fmt);\n }\n _tickFormatFunction(time, index, ticks, format) {\n const options = this.options;\n const formatter = options.ticks.callback;\n if (formatter) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(formatter, [\n time,\n index,\n ticks\n ], this);\n }\n const formats = options.time.displayFormats;\n const unit = this._unit;\n const majorUnit = this._majorUnit;\n const minorFormat = unit && formats[unit];\n const majorFormat = majorUnit && formats[majorUnit];\n const tick = ticks[index];\n const major = majorUnit && majorFormat && tick && tick.major;\n return this._adapter.format(time, format || (major ? majorFormat : minorFormat));\n }\n generateTickLabels(ticks) {\n let i, ilen, tick;\n for(i = 0, ilen = ticks.length; i < ilen; ++i){\n tick = ticks[i];\n tick.label = this._tickFormatFunction(tick.value, i, ticks);\n }\n }\n getDecimalForValue(value) {\n return value === null ? NaN : (value - this.min) / (this.max - this.min);\n }\n getPixelForValue(value) {\n const offsets = this._offsets;\n const pos = this.getDecimalForValue(value);\n return this.getPixelForDecimal((offsets.start + pos) * offsets.factor);\n }\n getValueForPixel(pixel) {\n const offsets = this._offsets;\n const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;\n return this.min + pos * (this.max - this.min);\n }\n _getLabelSize(label) {\n const ticksOpts = this.options.ticks;\n const tickLabelWidth = this.ctx.measureText(label).width;\n const angle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);\n const cosRotation = Math.cos(angle);\n const sinRotation = Math.sin(angle);\n const tickFontSize = this._resolveTickFontOptions(0).size;\n return {\n w: tickLabelWidth * cosRotation + tickFontSize * sinRotation,\n h: tickLabelWidth * sinRotation + tickFontSize * cosRotation\n };\n }\n _getLabelCapacity(exampleTime) {\n const timeOpts = this.options.time;\n const displayFormats = timeOpts.displayFormats;\n const format = displayFormats[timeOpts.unit] || displayFormats.millisecond;\n const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [\n exampleTime\n ], this._majorUnit), format);\n const size = this._getLabelSize(exampleLabel);\n const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1;\n return capacity > 0 ? capacity : 1;\n }\n getDataTimestamps() {\n let timestamps = this._cache.data || [];\n let i, ilen;\n if (timestamps.length) {\n return timestamps;\n }\n const metas = this.getMatchingVisibleMetas();\n if (this._normalized && metas.length) {\n return this._cache.data = metas[0].controller.getAllParsedValues(this);\n }\n for(i = 0, ilen = metas.length; i < ilen; ++i){\n timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(this));\n }\n return this._cache.data = this.normalize(timestamps);\n }\n getLabelTimestamps() {\n const timestamps = this._cache.labels || [];\n let i, ilen;\n if (timestamps.length) {\n return timestamps;\n }\n const labels = this.getLabels();\n for(i = 0, ilen = labels.length; i < ilen; ++i){\n timestamps.push(parse(this, labels[i]));\n }\n return this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps);\n }\n normalize(values) {\n return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort(sorter));\n }\n}\n\nfunction interpolate(table, val, reverse) {\n let lo = 0;\n let hi = table.length - 1;\n let prevSource, nextSource, prevTarget, nextTarget;\n if (reverse) {\n if (val >= table[lo].pos && val <= table[hi].pos) {\n ({ lo , hi } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(table, 'pos', val));\n }\n ({ pos: prevSource , time: prevTarget } = table[lo]);\n ({ pos: nextSource , time: nextTarget } = table[hi]);\n } else {\n if (val >= table[lo].time && val <= table[hi].time) {\n ({ lo , hi } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(table, 'time', val));\n }\n ({ time: prevSource , pos: prevTarget } = table[lo]);\n ({ time: nextSource , pos: nextTarget } = table[hi]);\n }\n const span = nextSource - prevSource;\n return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget;\n}\nclass TimeSeriesScale extends TimeScale {\n static id = 'timeseries';\n static defaults = TimeScale.defaults;\n constructor(props){\n super(props);\n this._table = [];\n this._minPos = undefined;\n this._tableRange = undefined;\n }\n initOffsets() {\n const timestamps = this._getTimestampsForTable();\n const table = this._table = this.buildLookupTable(timestamps);\n this._minPos = interpolate(table, this.min);\n this._tableRange = interpolate(table, this.max) - this._minPos;\n super.initOffsets(timestamps);\n }\n buildLookupTable(timestamps) {\n const { min , max } = this;\n const items = [];\n const table = [];\n let i, ilen, prev, curr, next;\n for(i = 0, ilen = timestamps.length; i < ilen; ++i){\n curr = timestamps[i];\n if (curr >= min && curr <= max) {\n items.push(curr);\n }\n }\n if (items.length < 2) {\n return [\n {\n time: min,\n pos: 0\n },\n {\n time: max,\n pos: 1\n }\n ];\n }\n for(i = 0, ilen = items.length; i < ilen; ++i){\n next = items[i + 1];\n prev = items[i - 1];\n curr = items[i];\n if (Math.round((next + prev) / 2) !== curr) {\n table.push({\n time: curr,\n pos: i / (ilen - 1)\n });\n }\n }\n return table;\n }\n _generate() {\n const min = this.min;\n const max = this.max;\n let timestamps = super.getDataTimestamps();\n if (!timestamps.includes(min) || !timestamps.length) {\n timestamps.splice(0, 0, min);\n }\n if (!timestamps.includes(max) || timestamps.length === 1) {\n timestamps.push(max);\n }\n return timestamps.sort((a, b)=>a - b);\n }\n _getTimestampsForTable() {\n let timestamps = this._cache.all || [];\n if (timestamps.length) {\n return timestamps;\n }\n const data = this.getDataTimestamps();\n const label = this.getLabelTimestamps();\n if (data.length && label.length) {\n timestamps = this.normalize(data.concat(label));\n } else {\n timestamps = data.length ? data : label;\n }\n timestamps = this._cache.all = timestamps;\n return timestamps;\n }\n getDecimalForValue(value) {\n return (interpolate(this._table, value) - this._minPos) / this._tableRange;\n }\n getValueForPixel(pixel) {\n const offsets = this._offsets;\n const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;\n return interpolate(this._table, decimal * this._tableRange + this._minPos, true);\n }\n}\n\nvar scales = /*#__PURE__*/Object.freeze({\n__proto__: null,\nCategoryScale: CategoryScale,\nLinearScale: LinearScale,\nLogarithmicScale: LogarithmicScale,\nRadialLinearScale: RadialLinearScale,\nTimeScale: TimeScale,\nTimeSeriesScale: TimeSeriesScale\n});\n\nconst registerables = [\n controllers,\n elements,\n plugins,\n scales\n];\n\n\n//# sourceMappingURL=chart.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvZGlzdC9jaGFydC5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDMm1FO0FBQ3BsRTs7QUFFdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qix5REFBZ0I7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFFBQVE7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0MsVUFBVTtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixTQUFTO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRCxVQUFVO0FBQzdEO0FBQ0E7QUFDQSw0QkFBNEIs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QTtBQUNBLG1CQUFtQixXQUFXO0FBQzlCO0FBQ0E7QUFDQSx1QkFBdUIsbUJBQW1CO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EscURBQXFELDZEQUFTO0FBQzlEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUseURBQTJCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixtQkFBbUI7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixtQkFBbUI7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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QUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsNkRBQVk7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Ysa0NBQWtDLDZEQUFZO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLHlEQUE0QjtBQUN6RDtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFNBQVMsRUFBRSw2REFBbUI7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFVBQVUsYUFBYTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLDZEQUFPO0FBQ2Y7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSw2REFBYztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsNkRBQVE7QUFDaEI7QUFDQTtBQUNBO0FBQ0EsUUFBUSw2REFBYztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsTUFBTSxTQUFTLDZEQUFRO0FBQ3ZCO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNLFNBQVMsNkRBQVE7QUFDdkI7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLDZEQUFjO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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O0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxTQUFTO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFNBQVM7QUFDaEQ7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLDhEQUFxQjtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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REFBSTtBQUNoQixpQkFBaUIsMERBQUk7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLGFBQWE7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsYUFBYTtBQUM3QjtBQUNBLFFBQVEsNkRBQUk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsYUFBYTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLFNBQVM7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsNkRBQUk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixtQkFBbUI7QUFDbkMsZ0JBQWdCLDRCQUE0QjtBQUM1QyxnQkFBZ0IsaURBQWlELEVBQUUsOERBQWE7QUFDaEYsZ0JBQWdCLG1CQUFtQjtBQUNuQyxnQkFBZ0Isa0JBQWtCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLDhEQUFhO0FBQzNDO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qiw4REFBTTtBQUM5QjtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsWUFBWTtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLHdCQUF3QjtBQUN4Qyx5QkFBeUIsOERBQU07QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSw4REFBUztBQUNyQjtBQUNBO0FBQ0EsWUFBWSw4REFBUztBQUNyQixVQUFVO0FBQ1YsNEJBQTRCLDZEQUFRO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsOERBQWE7QUFDOUM7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLDhEQUFrQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLDhEQUFrQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLFFBQVE7QUFDeEIsZ0JBQWdCLCtFQUErRTtBQUMvRix5QkFBeUIsOERBQU07QUFDL0I7QUFDQTtBQUNBLDBCQUEwQiw4REFBYTtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSw2REFBSTtBQUNaO0FBQ0EsdUNBQXVDLFVBQVU7QUFDakQ7QUFDQTtBQUNBO0FBQ0EsWUFBWSw2REFBSTtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLFVBQVU7QUFDdEQ7QUFDQTtBQUNBO0FBQ0EsWUFBWSw2REFBSTtBQUNoQjtBQUNBO0FBQ0E7QUFDQSxRQUFRLDZEQUFJO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsOERBQWE7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsOERBQU07QUFDL0I7QUFDQTtBQUNBLHVCQUF1QixZQUFZO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixtQkFBbUI7QUFDbkMsZ0JBQWdCLFNBQVM7QUFDekIsZ0JBQWdCLGtCQUFrQjtBQUNsQyxnQkFBZ0IsaURBQWlELEVBQUUsOERBQWE7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsNkRBQVM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksOERBQXFCO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSw4REFBb0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2Qyx1QkFBdUI7QUFDcEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULHlCQUF5Qiw4REFBYztBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLDhEQUFjO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQiw2QkFBNkI7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RCw2REFBVztBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFK3RCO0FBQy90QiIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jaGFydC5qcy9kaXN0L2NoYXJ0LmpzP2RjNWMiXSwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBDaGFydC5qcyB2NC41LjBcbiAqIGh0dHBzOi8vd3d3LmNoYXJ0anMub3JnXG4gKiAoYykgMjAyNSBDaGFydC5qcyBDb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICovXG5pbXBvcnQgeyByIGFzIHJlcXVlc3RBbmltRnJhbWUsIGEgYXMgcmVzb2x2ZSwgZSBhcyBlZmZlY3RzLCBjIGFzIGNvbG9yLCBpIGFzIGlzT2JqZWN0LCBkIGFzIGRlZmF1bHRzLCBiIGFzIGlzQXJyYXksIHYgYXMgdmFsdWVPckRlZmF1bHQsIHUgYXMgdW5saXN0ZW5BcnJheUV2ZW50cywgbCBhcyBsaXN0ZW5BcnJheUV2ZW50cywgZiBhcyByZXNvbHZlT2JqZWN0S2V5LCBnIGFzIGlzTnVtYmVyRmluaXRlLCBoIGFzIGRlZmluZWQsIHMgYXMgc2lnbiwgaiBhcyBjcmVhdGVDb250ZXh0LCBrIGFzIGlzTnVsbE9yVW5kZWYsIF8gYXMgX2FycmF5VW5pcXVlLCB0IGFzIHRvUmFkaWFucywgbSBhcyB0b1BlcmNlbnRhZ2UsIG4gYXMgdG9EaW1lbnNpb24sIFQgYXMgVEFVLCBvIGFzIGZvcm1hdE51bWJlciwgcCBhcyBfYW5nbGVCZXR3ZWVuLCBIIGFzIEhBTEZfUEksIFAgYXMgUEksIHEgYXMgX2dldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHMsIHcgYXMgX3NjYWxlUmFuZ2VzQ2hhbmdlZCwgeCBhcyBpc051bWJlciwgeSBhcyBfcGFyc2VPYmplY3REYXRhUmFkaWFsU2NhbGUsIHogYXMgZ2V0UmVsYXRpdmVQb3NpdGlvbiwgQSBhcyBfcmxvb2t1cEJ5S2V5LCBCIGFzIF9sb29rdXBCeUtleSwgQyBhcyBfaXNQb2ludEluQXJlYSwgRCBhcyBnZXRBbmdsZUZyb21Qb2ludCwgRSBhcyB0b1BhZGRpbmcsIEYgYXMgZWFjaCwgRyBhcyBnZXRNYXhpbXVtU2l6ZSwgSSBhcyBfZ2V0UGFyZW50Tm9kZSwgSiBhcyByZWFkVXNlZFNpemUsIEsgYXMgc3VwcG9ydHNFdmVudExpc3RlbmVyT3B0aW9ucywgTCBhcyB0aHJvdHRsZWQsIE0gYXMgX2lzRG9tU3VwcG9ydGVkLCBOIGFzIF9mYWN0b3JpemUsIE8gYXMgZmluaXRlT3JEZWZhdWx0LCBRIGFzIGNhbGxiYWNrLCBSIGFzIF9hZGRHcmFjZSwgUyBhcyBfbGltaXRWYWx1ZSwgVSBhcyB0b0RlZ3JlZXMsIFYgYXMgX21lYXN1cmVUZXh0LCBXIGFzIF9pbnQxNlJhbmdlLCBYIGFzIF9hbGlnblBpeGVsLCBZIGFzIGNsaXBBcmVhLCBaIGFzIHJlbmRlclRleHQsICQgYXMgdW5jbGlwQXJlYSwgYTAgYXMgdG9Gb250LCBhMSBhcyBfdG9MZWZ0UmlnaHRDZW50ZXIsIGEyIGFzIF9hbGlnblN0YXJ0RW5kLCBhMyBhcyBvdmVycmlkZXMsIGE0IGFzIG1lcmdlLCBhNSBhcyBfY2FwaXRhbGl6ZSwgYTYgYXMgZGVzY3JpcHRvcnMsIGE3IGFzIGlzRnVuY3Rpb24sIGE4IGFzIF9hdHRhY2hDb250ZXh0LCBhOSBhcyBfY3JlYXRlUmVzb2x2ZXIsIGFhIGFzIF9kZXNjcmlwdG9ycywgYWIgYXMgbWVyZ2VJZiwgYWMgYXMgdWlkLCBhZCBhcyBkZWJvdW5jZSwgYWUgYXMgcmV0aW5hU2NhbGUsIGFmIGFzIGNsZWFyQ2FudmFzLCBhZyBhcyBzZXRzRXF1YWwsIGFoIGFzIGdldERhdGFzZXRDbGlwQXJlYSwgYWkgYXMgX2VsZW1lbnRzRXF1YWwsIGFqIGFzIF9pc0NsaWNrRXZlbnQsIGFrIGFzIF9pc0JldHdlZW4sIGFsIGFzIF9ub3JtYWxpemVBbmdsZSwgYW0gYXMgX3JlYWRWYWx1ZVRvUHJvcHMsIGFuIGFzIF91cGRhdGVCZXppZXJDb250cm9sUG9pbnRzLCBhbyBhcyBfY29tcHV0ZVNlZ21lbnRzLCBhcCBhcyBfYm91bmRTZWdtZW50cywgYXEgYXMgX3N0ZXBwZWRJbnRlcnBvbGF0aW9uLCBhciBhcyBfYmV6aWVySW50ZXJwb2xhdGlvbiwgYXMgYXMgX3BvaW50SW5MaW5lLCBhdCBhcyBfc3RlcHBlZExpbmVUbywgYXUgYXMgX2JlemllckN1cnZlVG8sIGF2IGFzIGRyYXdQb2ludCwgYXcgYXMgYWRkUm91bmRlZFJlY3RQYXRoLCBheCBhcyB0b1RSQkwsIGF5IGFzIHRvVFJCTENvcm5lcnMsIGF6IGFzIF9ib3VuZFNlZ21lbnQsIGFBIGFzIGdldFJ0bEFkYXB0ZXIsIGFCIGFzIG92ZXJyaWRlVGV4dERpcmVjdGlvbiwgYUMgYXMgX3RleHRYLCBhRCBhcyByZXN0b3JlVGV4dERpcmVjdGlvbiwgYUUgYXMgZHJhd1BvaW50TGVnZW5kLCBhRiBhcyBkaXN0YW5jZUJldHdlZW5Qb2ludHMsIGFHIGFzIG5vb3AsIGFIIGFzIF9zZXRNaW5BbmRNYXhCeUtleSwgYUkgYXMgbmljZU51bSwgYUogYXMgYWxtb3N0V2hvbGUsIGFLIGFzIGFsbW9zdEVxdWFscywgYUwgYXMgX2RlY2ltYWxQbGFjZXMsIGFNIGFzIFRpY2tzLCBhTiBhcyBsb2cxMCwgYU8gYXMgX2xvbmdlc3RUZXh0LCBhUCBhcyBfZmlsdGVyQmV0d2VlbiwgYVEgYXMgX2xvb2t1cCB9IGZyb20gJy4vY2h1bmtzL2hlbHBlcnMuZGF0YXNldC5qcyc7XG5pbXBvcnQgJ0BrdXJrbGUvY29sb3InO1xuXG5jbGFzcyBBbmltYXRvciB7XG4gICAgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy5fcmVxdWVzdCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2NoYXJ0cyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fcnVubmluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9sYXN0RGF0ZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gX25vdGlmeShjaGFydCwgYW5pbXMsIGRhdGUsIHR5cGUpIHtcbiAgICAgICAgY29uc3QgY2FsbGJhY2tzID0gYW5pbXMubGlzdGVuZXJzW3R5cGVdO1xuICAgICAgICBjb25zdCBudW1TdGVwcyA9IGFuaW1zLmR1cmF0aW9uO1xuICAgICAgICBjYWxsYmFja3MuZm9yRWFjaCgoZm4pPT5mbih7XG4gICAgICAgICAgICAgICAgY2hhcnQsXG4gICAgICAgICAgICAgICAgaW5pdGlhbDogYW5pbXMuaW5pdGlhbCxcbiAgICAgICAgICAgICAgICBudW1TdGVwcyxcbiAgICAgICAgICAgICAgICBjdXJyZW50U3RlcDogTWF0aC5taW4oZGF0ZSAtIGFuaW1zLnN0YXJ0LCBudW1TdGVwcylcbiAgICAgICAgICAgIH0pKTtcbiAgICB9XG4gX3JlZnJlc2goKSB7XG4gICAgICAgIGlmICh0aGlzLl9yZXF1ZXN0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcnVubmluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuX3JlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lLmNhbGwod2luZG93LCAoKT0+e1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICB0aGlzLl9yZXF1ZXN0ID0gbnVsbDtcbiAgICAgICAgICAgIGlmICh0aGlzLl9ydW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVmcmVzaCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gX3VwZGF0ZShkYXRlID0gRGF0ZS5ub3coKSkge1xuICAgICAgICBsZXQgcmVtYWluaW5nID0gMDtcbiAgICAgICAgdGhpcy5fY2hhcnRzLmZvckVhY2goKGFuaW1zLCBjaGFydCk9PntcbiAgICAgICAgICAgIGlmICghYW5pbXMucnVubmluZyB8fCAhYW5pbXMuaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaXRlbXMgPSBhbmltcy5pdGVtcztcbiAgICAgICAgICAgIGxldCBpID0gaXRlbXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIGxldCBkcmF3ID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgaXRlbTtcbiAgICAgICAgICAgIGZvcig7IGkgPj0gMDsgLS1pKXtcbiAgICAgICAgICAgICAgICBpdGVtID0gaXRlbXNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0uX2FjdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXRlbS5fdG90YWwgPiBhbmltcy5kdXJhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbXMuZHVyYXRpb24gPSBpdGVtLl90b3RhbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpdGVtLnRpY2soZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIGRyYXcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGl0ZW1zW2ldID0gaXRlbXNbaXRlbXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgIGl0ZW1zLnBvcCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkcmF3KSB7XG4gICAgICAgICAgICAgICAgY2hhcnQuZHJhdygpO1xuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeShjaGFydCwgYW5pbXMsIGRhdGUsICdwcm9ncmVzcycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBhbmltcy5ydW5uaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5KGNoYXJ0LCBhbmltcywgZGF0ZSwgJ2NvbXBsZXRlJyk7XG4gICAgICAgICAgICAgICAgYW5pbXMuaW5pdGlhbCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVtYWluaW5nICs9IGl0ZW1zLmxlbmd0aDtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX2xhc3REYXRlID0gZGF0ZTtcbiAgICAgICAgaWYgKHJlbWFpbmluZyA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5fcnVubmluZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuIF9nZXRBbmltcyhjaGFydCkge1xuICAgICAgICBjb25zdCBjaGFydHMgPSB0aGlzLl9jaGFydHM7XG4gICAgICAgIGxldCBhbmltcyA9IGNoYXJ0cy5nZXQoY2hhcnQpO1xuICAgICAgICBpZiAoIWFuaW1zKSB7XG4gICAgICAgICAgICBhbmltcyA9IHtcbiAgICAgICAgICAgICAgICBydW5uaW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpbml0aWFsOiB0cnVlLFxuICAgICAgICAgICAgICAgIGl0ZW1zOiBbXSxcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGU6IFtdLFxuICAgICAgICAgICAgICAgICAgICBwcm9ncmVzczogW11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY2hhcnRzLnNldChjaGFydCwgYW5pbXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhbmltcztcbiAgICB9XG4gbGlzdGVuKGNoYXJ0LCBldmVudCwgY2IpIHtcbiAgICAgICAgdGhpcy5fZ2V0QW5pbXMoY2hhcnQpLmxpc3RlbmVyc1tldmVudF0ucHVzaChjYik7XG4gICAgfVxuIGFkZChjaGFydCwgaXRlbXMpIHtcbiAgICAgICAgaWYgKCFpdGVtcyB8fCAhaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fZ2V0QW5pbXMoY2hhcnQpLml0ZW1zLnB1c2goLi4uaXRlbXMpO1xuICAgIH1cbiBoYXMoY2hhcnQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldEFuaW1zKGNoYXJ0KS5pdGVtcy5sZW5ndGggPiAwO1xuICAgIH1cbiBzdGFydChjaGFydCkge1xuICAgICAgICBjb25zdCBhbmltcyA9IHRoaXMuX2NoYXJ0cy5nZXQoY2hhcnQpO1xuICAgICAgICBpZiAoIWFuaW1zKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgYW5pbXMucnVubmluZyA9IHRydWU7XG4gICAgICAgIGFuaW1zLnN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgYW5pbXMuZHVyYXRpb24gPSBhbmltcy5pdGVtcy5yZWR1Y2UoKGFjYywgY3VyKT0+TWF0aC5tYXgoYWNjLCBjdXIuX2R1cmF0aW9uKSwgMCk7XG4gICAgICAgIHRoaXMuX3JlZnJlc2goKTtcbiAgICB9XG4gICAgcnVubmluZyhjaGFydCkge1xuICAgICAgICBpZiAoIXRoaXMuX3J1bm5pbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhbmltcyA9IHRoaXMuX2NoYXJ0cy5nZXQoY2hhcnQpO1xuICAgICAgICBpZiAoIWFuaW1zIHx8ICFhbmltcy5ydW5uaW5nIHx8ICFhbmltcy5pdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gc3RvcChjaGFydCkge1xuICAgICAgICBjb25zdCBhbmltcyA9IHRoaXMuX2NoYXJ0cy5nZXQoY2hhcnQpO1xuICAgICAgICBpZiAoIWFuaW1zIHx8ICFhbmltcy5pdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpdGVtcyA9IGFuaW1zLml0ZW1zO1xuICAgICAgICBsZXQgaSA9IGl0ZW1zLmxlbmd0aCAtIDE7XG4gICAgICAgIGZvcig7IGkgPj0gMDsgLS1pKXtcbiAgICAgICAgICAgIGl0ZW1zW2ldLmNhbmNlbCgpO1xuICAgICAgICB9XG4gICAgICAgIGFuaW1zLml0ZW1zID0gW107XG4gICAgICAgIHRoaXMuX25vdGlmeShjaGFydCwgYW5pbXMsIERhdGUubm93KCksICdjb21wbGV0ZScpO1xuICAgIH1cbiByZW1vdmUoY2hhcnQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NoYXJ0cy5kZWxldGUoY2hhcnQpO1xuICAgIH1cbn1cbnZhciBhbmltYXRvciA9IC8qICNfX1BVUkVfXyAqLyBuZXcgQW5pbWF0b3IoKTtcblxuY29uc3QgdHJhbnNwYXJlbnQgPSAndHJhbnNwYXJlbnQnO1xuY29uc3QgaW50ZXJwb2xhdG9ycyA9IHtcbiAgICBib29sZWFuIChmcm9tLCB0bywgZmFjdG9yKSB7XG4gICAgICAgIHJldHVybiBmYWN0b3IgPiAwLjUgPyB0byA6IGZyb207XG4gICAgfSxcbiBjb2xvciAoZnJvbSwgdG8sIGZhY3Rvcikge1xuICAgICAgICBjb25zdCBjMCA9IGNvbG9yKGZyb20gfHwgdHJhbnNwYXJlbnQpO1xuICAgICAgICBjb25zdCBjMSA9IGMwLnZhbGlkICYmIGNvbG9yKHRvIHx8IHRyYW5zcGFyZW50KTtcbiAgICAgICAgcmV0dXJuIGMxICYmIGMxLnZhbGlkID8gYzEubWl4KGMwLCBmYWN0b3IpLmhleFN0cmluZygpIDogdG87XG4gICAgfSxcbiAgICBudW1iZXIgKGZyb20sIHRvLCBmYWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIGZyb20gKyAodG8gLSBmcm9tKSAqIGZhY3RvcjtcbiAgICB9XG59O1xuY2xhc3MgQW5pbWF0aW9uIHtcbiAgICBjb25zdHJ1Y3RvcihjZmcsIHRhcmdldCwgcHJvcCwgdG8pe1xuICAgICAgICBjb25zdCBjdXJyZW50VmFsdWUgPSB0YXJnZXRbcHJvcF07XG4gICAgICAgIHRvID0gcmVzb2x2ZShbXG4gICAgICAgICAgICBjZmcudG8sXG4gICAgICAgICAgICB0byxcbiAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSxcbiAgICAgICAgICAgIGNmZy5mcm9tXG4gICAgICAgIF0pO1xuICAgICAgICBjb25zdCBmcm9tID0gcmVzb2x2ZShbXG4gICAgICAgICAgICBjZmcuZnJvbSxcbiAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSxcbiAgICAgICAgICAgIHRvXG4gICAgICAgIF0pO1xuICAgICAgICB0aGlzLl9hY3RpdmUgPSB0cnVlO1xuICAgICAgICB0aGlzLl9mbiA9IGNmZy5mbiB8fCBpbnRlcnBvbGF0b3JzW2NmZy50eXBlIHx8IHR5cGVvZiBmcm9tXTtcbiAgICAgICAgdGhpcy5fZWFzaW5nID0gZWZmZWN0c1tjZmcuZWFzaW5nXSB8fCBlZmZlY3RzLmxpbmVhcjtcbiAgICAgICAgdGhpcy5fc3RhcnQgPSBNYXRoLmZsb29yKERhdGUubm93KCkgKyAoY2ZnLmRlbGF5IHx8IDApKTtcbiAgICAgICAgdGhpcy5fZHVyYXRpb24gPSB0aGlzLl90b3RhbCA9IE1hdGguZmxvb3IoY2ZnLmR1cmF0aW9uKTtcbiAgICAgICAgdGhpcy5fbG9vcCA9ICEhY2ZnLmxvb3A7XG4gICAgICAgIHRoaXMuX3RhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy5fcHJvcCA9IHByb3A7XG4gICAgICAgIHRoaXMuX2Zyb20gPSBmcm9tO1xuICAgICAgICB0aGlzLl90byA9IHRvO1xuICAgICAgICB0aGlzLl9wcm9taXNlcyA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgYWN0aXZlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWN0aXZlO1xuICAgIH1cbiAgICB1cGRhdGUoY2ZnLCB0bywgZGF0ZSkge1xuICAgICAgICBpZiAodGhpcy5fYWN0aXZlKSB7XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnkoZmFsc2UpO1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gdGhpcy5fdGFyZ2V0W3RoaXMuX3Byb3BdO1xuICAgICAgICAgICAgY29uc3QgZWxhcHNlZCA9IGRhdGUgLSB0aGlzLl9zdGFydDtcbiAgICAgICAgICAgIGNvbnN0IHJlbWFpbiA9IHRoaXMuX2R1cmF0aW9uIC0gZWxhcHNlZDtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0ID0gZGF0ZTtcbiAgICAgICAgICAgIHRoaXMuX2R1cmF0aW9uID0gTWF0aC5mbG9vcihNYXRoLm1heChyZW1haW4sIGNmZy5kdXJhdGlvbikpO1xuICAgICAgICAgICAgdGhpcy5fdG90YWwgKz0gZWxhcHNlZDtcbiAgICAgICAgICAgIHRoaXMuX2xvb3AgPSAhIWNmZy5sb29wO1xuICAgICAgICAgICAgdGhpcy5fdG8gPSByZXNvbHZlKFtcbiAgICAgICAgICAgICAgICBjZmcudG8sXG4gICAgICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICAgICAgY3VycmVudFZhbHVlLFxuICAgICAgICAgICAgICAgIGNmZy5mcm9tXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIHRoaXMuX2Zyb20gPSByZXNvbHZlKFtcbiAgICAgICAgICAgICAgICBjZmcuZnJvbSxcbiAgICAgICAgICAgICAgICBjdXJyZW50VmFsdWUsXG4gICAgICAgICAgICAgICAgdG9cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNhbmNlbCgpIHtcbiAgICAgICAgaWYgKHRoaXMuX2FjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy50aWNrKERhdGUubm93KCkpO1xuICAgICAgICAgICAgdGhpcy5fYWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnkoZmFsc2UpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRpY2soZGF0ZSkge1xuICAgICAgICBjb25zdCBlbGFwc2VkID0gZGF0ZSAtIHRoaXMuX3N0YXJ0O1xuICAgICAgICBjb25zdCBkdXJhdGlvbiA9IHRoaXMuX2R1cmF0aW9uO1xuICAgICAgICBjb25zdCBwcm9wID0gdGhpcy5fcHJvcDtcbiAgICAgICAgY29uc3QgZnJvbSA9IHRoaXMuX2Zyb207XG4gICAgICAgIGNvbnN0IGxvb3AgPSB0aGlzLl9sb29wO1xuICAgICAgICBjb25zdCB0byA9IHRoaXMuX3RvO1xuICAgICAgICBsZXQgZmFjdG9yO1xuICAgICAgICB0aGlzLl9hY3RpdmUgPSBmcm9tICE9PSB0byAmJiAobG9vcCB8fCBlbGFwc2VkIDwgZHVyYXRpb24pO1xuICAgICAgICBpZiAoIXRoaXMuX2FjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5fdGFyZ2V0W3Byb3BdID0gdG87XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnkodHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVsYXBzZWQgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLl90YXJnZXRbcHJvcF0gPSBmcm9tO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZhY3RvciA9IGVsYXBzZWQgLyBkdXJhdGlvbiAlIDI7XG4gICAgICAgIGZhY3RvciA9IGxvb3AgJiYgZmFjdG9yID4gMSA/IDIgLSBmYWN0b3IgOiBmYWN0b3I7XG4gICAgICAgIGZhY3RvciA9IHRoaXMuX2Vhc2luZyhNYXRoLm1pbigxLCBNYXRoLm1heCgwLCBmYWN0b3IpKSk7XG4gICAgICAgIHRoaXMuX3RhcmdldFtwcm9wXSA9IHRoaXMuX2ZuKGZyb20sIHRvLCBmYWN0b3IpO1xuICAgIH1cbiAgICB3YWl0KCkge1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IHRoaXMuX3Byb21pc2VzIHx8ICh0aGlzLl9wcm9taXNlcyA9IFtdKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXMsIHJlaik9PntcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goe1xuICAgICAgICAgICAgICAgIHJlcyxcbiAgICAgICAgICAgICAgICByZWpcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgX25vdGlmeShyZXNvbHZlZCkge1xuICAgICAgICBjb25zdCBtZXRob2QgPSByZXNvbHZlZCA/ICdyZXMnIDogJ3Jlaic7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gdGhpcy5fcHJvbWlzZXMgfHwgW107XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBwcm9taXNlcy5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICBwcm9taXNlc1tpXVttZXRob2RdKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmNsYXNzIEFuaW1hdGlvbnMge1xuICAgIGNvbnN0cnVjdG9yKGNoYXJ0LCBjb25maWcpe1xuICAgICAgICB0aGlzLl9jaGFydCA9IGNoYXJ0O1xuICAgICAgICB0aGlzLl9wcm9wZXJ0aWVzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyZShjb25maWcpO1xuICAgIH1cbiAgICBjb25maWd1cmUoY29uZmlnKSB7XG4gICAgICAgIGlmICghaXNPYmplY3QoY29uZmlnKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbk9wdGlvbnMgPSBPYmplY3Qua2V5cyhkZWZhdWx0cy5hbmltYXRpb24pO1xuICAgICAgICBjb25zdCBhbmltYXRlZFByb3BzID0gdGhpcy5fcHJvcGVydGllcztcbiAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoY29uZmlnKS5mb3JFYWNoKChrZXkpPT57XG4gICAgICAgICAgICBjb25zdCBjZmcgPSBjb25maWdba2V5XTtcbiAgICAgICAgICAgIGlmICghaXNPYmplY3QoY2ZnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkID0ge307XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBhbmltYXRpb25PcHRpb25zKXtcbiAgICAgICAgICAgICAgICByZXNvbHZlZFtvcHRpb25dID0gY2ZnW29wdGlvbl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAoaXNBcnJheShjZmcucHJvcGVydGllcykgJiYgY2ZnLnByb3BlcnRpZXMgfHwgW1xuICAgICAgICAgICAgICAgIGtleVxuICAgICAgICAgICAgXSkuZm9yRWFjaCgocHJvcCk9PntcbiAgICAgICAgICAgICAgICBpZiAocHJvcCA9PT0ga2V5IHx8ICFhbmltYXRlZFByb3BzLmhhcyhwcm9wKSkge1xuICAgICAgICAgICAgICAgICAgICBhbmltYXRlZFByb3BzLnNldChwcm9wLCByZXNvbHZlZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiBfYW5pbWF0ZU9wdGlvbnModGFyZ2V0LCB2YWx1ZXMpIHtcbiAgICAgICAgY29uc3QgbmV3T3B0aW9ucyA9IHZhbHVlcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gcmVzb2x2ZVRhcmdldE9wdGlvbnModGFyZ2V0LCBuZXdPcHRpb25zKTtcbiAgICAgICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYW5pbWF0aW9ucyA9IHRoaXMuX2NyZWF0ZUFuaW1hdGlvbnMob3B0aW9ucywgbmV3T3B0aW9ucyk7XG4gICAgICAgIGlmIChuZXdPcHRpb25zLiRzaGFyZWQpIHtcbiAgICAgICAgICAgIGF3YWl0QWxsKHRhcmdldC5vcHRpb25zLiRhbmltYXRpb25zLCBuZXdPcHRpb25zKS50aGVuKCgpPT57XG4gICAgICAgICAgICAgICAgdGFyZ2V0Lm9wdGlvbnMgPSBuZXdPcHRpb25zO1xuICAgICAgICAgICAgfSwgKCk9PntcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhbmltYXRpb25zO1xuICAgIH1cbiBfY3JlYXRlQW5pbWF0aW9ucyh0YXJnZXQsIHZhbHVlcykge1xuICAgICAgICBjb25zdCBhbmltYXRlZFByb3BzID0gdGhpcy5fcHJvcGVydGllcztcbiAgICAgICAgY29uc3QgYW5pbWF0aW9ucyA9IFtdO1xuICAgICAgICBjb25zdCBydW5uaW5nID0gdGFyZ2V0LiRhbmltYXRpb25zIHx8ICh0YXJnZXQuJGFuaW1hdGlvbnMgPSB7fSk7XG4gICAgICAgIGNvbnN0IHByb3BzID0gT2JqZWN0LmtleXModmFsdWVzKTtcbiAgICAgICAgY29uc3QgZGF0ZSA9IERhdGUubm93KCk7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBmb3IoaSA9IHByb3BzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKXtcbiAgICAgICAgICAgIGNvbnN0IHByb3AgPSBwcm9wc1tpXTtcbiAgICAgICAgICAgIGlmIChwcm9wLmNoYXJBdCgwKSA9PT0gJyQnKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHJvcCA9PT0gJ29wdGlvbnMnKSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKC4uLnRoaXMuX2FuaW1hdGVPcHRpb25zKHRhcmdldCwgdmFsdWVzKSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHZhbHVlc1twcm9wXTtcbiAgICAgICAgICAgIGxldCBhbmltYXRpb24gPSBydW5uaW5nW3Byb3BdO1xuICAgICAgICAgICAgY29uc3QgY2ZnID0gYW5pbWF0ZWRQcm9wcy5nZXQocHJvcCk7XG4gICAgICAgICAgICBpZiAoYW5pbWF0aW9uKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNmZyAmJiBhbmltYXRpb24uYWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9uLnVwZGF0ZShjZmcsIHZhbHVlLCBkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9uLmNhbmNlbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghY2ZnIHx8ICFjZmcuZHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRbcHJvcF0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJ1bm5pbmdbcHJvcF0gPSBhbmltYXRpb24gPSBuZXcgQW5pbWF0aW9uKGNmZywgdGFyZ2V0LCBwcm9wLCB2YWx1ZSk7XG4gICAgICAgICAgICBhbmltYXRpb25zLnB1c2goYW5pbWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYW5pbWF0aW9ucztcbiAgICB9XG4gdXBkYXRlKHRhcmdldCwgdmFsdWVzKSB7XG4gICAgICAgIGlmICh0aGlzLl9wcm9wZXJ0aWVzLnNpemUgPT09IDApIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGFyZ2V0LCB2YWx1ZXMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSB0aGlzLl9jcmVhdGVBbmltYXRpb25zKHRhcmdldCwgdmFsdWVzKTtcbiAgICAgICAgaWYgKGFuaW1hdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBhbmltYXRvci5hZGQodGhpcy5fY2hhcnQsIGFuaW1hdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBhd2FpdEFsbChhbmltYXRpb25zLCBwcm9wZXJ0aWVzKSB7XG4gICAgY29uc3QgcnVubmluZyA9IFtdO1xuICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGNvbnN0IGFuaW0gPSBhbmltYXRpb25zW2tleXNbaV1dO1xuICAgICAgICBpZiAoYW5pbSAmJiBhbmltLmFjdGl2ZSgpKSB7XG4gICAgICAgICAgICBydW5uaW5nLnB1c2goYW5pbS53YWl0KCkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLmFsbChydW5uaW5nKTtcbn1cbmZ1bmN0aW9uIHJlc29sdmVUYXJnZXRPcHRpb25zKHRhcmdldCwgbmV3T3B0aW9ucykge1xuICAgIGlmICghbmV3T3B0aW9ucykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBvcHRpb25zID0gdGFyZ2V0Lm9wdGlvbnM7XG4gICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICAgIHRhcmdldC5vcHRpb25zID0gbmV3T3B0aW9ucztcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy4kc2hhcmVkKSB7XG4gICAgICAgIHRhcmdldC5vcHRpb25zID0gb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIG9wdGlvbnMsIHtcbiAgICAgICAgICAgICRzaGFyZWQ6IGZhbHNlLFxuICAgICAgICAgICAgJGFuaW1hdGlvbnM6IHt9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gb3B0aW9ucztcbn1cblxuZnVuY3Rpb24gc2NhbGVDbGlwKHNjYWxlLCBhbGxvd2VkT3ZlcmZsb3cpIHtcbiAgICBjb25zdCBvcHRzID0gc2NhbGUgJiYgc2NhbGUub3B0aW9ucyB8fCB7fTtcbiAgICBjb25zdCByZXZlcnNlID0gb3B0cy5yZXZlcnNlO1xuICAgIGNvbnN0IG1pbiA9IG9wdHMubWluID09PSB1bmRlZmluZWQgPyBhbGxvd2VkT3ZlcmZsb3cgOiAwO1xuICAgIGNvbnN0IG1heCA9IG9wdHMubWF4ID09PSB1bmRlZmluZWQgPyBhbGxvd2VkT3ZlcmZsb3cgOiAwO1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiByZXZlcnNlID8gbWF4IDogbWluLFxuICAgICAgICBlbmQ6IHJldmVyc2UgPyBtaW4gOiBtYXhcbiAgICB9O1xufVxuZnVuY3Rpb24gZGVmYXVsdENsaXAoeFNjYWxlLCB5U2NhbGUsIGFsbG93ZWRPdmVyZmxvdykge1xuICAgIGlmIChhbGxvd2VkT3ZlcmZsb3cgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgeCA9IHNjYWxlQ2xpcCh4U2NhbGUsIGFsbG93ZWRPdmVyZmxvdyk7XG4gICAgY29uc3QgeSA9IHNjYWxlQ2xpcCh5U2NhbGUsIGFsbG93ZWRPdmVyZmxvdyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiB5LmVuZCxcbiAgICAgICAgcmlnaHQ6IHguZW5kLFxuICAgICAgICBib3R0b206IHkuc3RhcnQsXG4gICAgICAgIGxlZnQ6IHguc3RhcnRcbiAgICB9O1xufVxuZnVuY3Rpb24gdG9DbGlwKHZhbHVlKSB7XG4gICAgbGV0IHQsIHIsIGIsIGw7XG4gICAgaWYgKGlzT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICB0ID0gdmFsdWUudG9wO1xuICAgICAgICByID0gdmFsdWUucmlnaHQ7XG4gICAgICAgIGIgPSB2YWx1ZS5ib3R0b207XG4gICAgICAgIGwgPSB2YWx1ZS5sZWZ0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHQgPSByID0gYiA9IGwgPSB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiB0LFxuICAgICAgICByaWdodDogcixcbiAgICAgICAgYm90dG9tOiBiLFxuICAgICAgICBsZWZ0OiBsLFxuICAgICAgICBkaXNhYmxlZDogdmFsdWUgPT09IGZhbHNlXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldFNvcnRlZERhdGFzZXRJbmRpY2VzKGNoYXJ0LCBmaWx0ZXJWaXNpYmxlKSB7XG4gICAgY29uc3Qga2V5cyA9IFtdO1xuICAgIGNvbnN0IG1ldGFzZXRzID0gY2hhcnQuX2dldFNvcnRlZERhdGFzZXRNZXRhcyhmaWx0ZXJWaXNpYmxlKTtcbiAgICBsZXQgaSwgaWxlbjtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBtZXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBrZXlzLnB1c2gobWV0YXNldHNbaV0uaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4ga2V5cztcbn1cbmZ1bmN0aW9uIGFwcGx5U3RhY2soc3RhY2ssIHZhbHVlLCBkc0luZGV4LCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBrZXlzID0gc3RhY2sua2V5cztcbiAgICBjb25zdCBzaW5nbGVNb2RlID0gb3B0aW9ucy5tb2RlID09PSAnc2luZ2xlJztcbiAgICBsZXQgaSwgaWxlbiwgZGF0YXNldEluZGV4LCBvdGhlclZhbHVlO1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihpID0gMCwgaWxlbiA9IGtleXMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgZGF0YXNldEluZGV4ID0gK2tleXNbaV07XG4gICAgICAgIGlmIChkYXRhc2V0SW5kZXggPT09IGRzSW5kZXgpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFsbCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgb3RoZXJWYWx1ZSA9IHN0YWNrLnZhbHVlc1tkYXRhc2V0SW5kZXhdO1xuICAgICAgICBpZiAoaXNOdW1iZXJGaW5pdGUob3RoZXJWYWx1ZSkgJiYgKHNpbmdsZU1vZGUgfHwgdmFsdWUgPT09IDAgfHwgc2lnbih2YWx1ZSkgPT09IHNpZ24ob3RoZXJWYWx1ZSkpKSB7XG4gICAgICAgICAgICB2YWx1ZSArPSBvdGhlclZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICghZm91bmQgJiYgIW9wdGlvbnMuYWxsKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59XG5mdW5jdGlvbiBjb252ZXJ0T2JqZWN0RGF0YVRvQXJyYXkoZGF0YSwgbWV0YSkge1xuICAgIGNvbnN0IHsgaVNjYWxlICwgdlNjYWxlICB9ID0gbWV0YTtcbiAgICBjb25zdCBpQXhpc0tleSA9IGlTY2FsZS5heGlzID09PSAneCcgPyAneCcgOiAneSc7XG4gICAgY29uc3QgdkF4aXNLZXkgPSB2U2NhbGUuYXhpcyA9PT0gJ3gnID8gJ3gnIDogJ3knO1xuICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhkYXRhKTtcbiAgICBjb25zdCBhZGF0YSA9IG5ldyBBcnJheShrZXlzLmxlbmd0aCk7XG4gICAgbGV0IGksIGlsZW4sIGtleTtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgIGFkYXRhW2ldID0ge1xuICAgICAgICAgICAgW2lBeGlzS2V5XToga2V5LFxuICAgICAgICAgICAgW3ZBeGlzS2V5XTogZGF0YVtrZXldXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBhZGF0YTtcbn1cbmZ1bmN0aW9uIGlzU3RhY2tlZChzY2FsZSwgbWV0YSkge1xuICAgIGNvbnN0IHN0YWNrZWQgPSBzY2FsZSAmJiBzY2FsZS5vcHRpb25zLnN0YWNrZWQ7XG4gICAgcmV0dXJuIHN0YWNrZWQgfHwgc3RhY2tlZCA9PT0gdW5kZWZpbmVkICYmIG1ldGEuc3RhY2sgIT09IHVuZGVmaW5lZDtcbn1cbmZ1bmN0aW9uIGdldFN0YWNrS2V5KGluZGV4U2NhbGUsIHZhbHVlU2NhbGUsIG1ldGEpIHtcbiAgICByZXR1cm4gYCR7aW5kZXhTY2FsZS5pZH0uJHt2YWx1ZVNjYWxlLmlkfS4ke21ldGEuc3RhY2sgfHwgbWV0YS50eXBlfWA7XG59XG5mdW5jdGlvbiBnZXRVc2VyQm91bmRzKHNjYWxlKSB7XG4gICAgY29uc3QgeyBtaW4gLCBtYXggLCBtaW5EZWZpbmVkICwgbWF4RGVmaW5lZCAgfSA9IHNjYWxlLmdldFVzZXJCb3VuZHMoKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBtaW46IG1pbkRlZmluZWQgPyBtaW4gOiBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksXG4gICAgICAgIG1heDogbWF4RGVmaW5lZCA/IG1heCA6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWVxuICAgIH07XG59XG5mdW5jdGlvbiBnZXRPckNyZWF0ZVN0YWNrKHN0YWNrcywgc3RhY2tLZXksIGluZGV4VmFsdWUpIHtcbiAgICBjb25zdCBzdWJTdGFjayA9IHN0YWNrc1tzdGFja0tleV0gfHwgKHN0YWNrc1tzdGFja0tleV0gPSB7fSk7XG4gICAgcmV0dXJuIHN1YlN0YWNrW2luZGV4VmFsdWVdIHx8IChzdWJTdGFja1tpbmRleFZhbHVlXSA9IHt9KTtcbn1cbmZ1bmN0aW9uIGdldExhc3RJbmRleEluU3RhY2soc3RhY2ssIHZTY2FsZSwgcG9zaXRpdmUsIHR5cGUpIHtcbiAgICBmb3IgKGNvbnN0IG1ldGEgb2YgdlNjYWxlLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKHR5cGUpLnJldmVyc2UoKSl7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gc3RhY2tbbWV0YS5pbmRleF07XG4gICAgICAgIGlmIChwb3NpdGl2ZSAmJiB2YWx1ZSA+IDAgfHwgIXBvc2l0aXZlICYmIHZhbHVlIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGEuaW5kZXg7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiB1cGRhdGVTdGFja3MoY29udHJvbGxlciwgcGFyc2VkKSB7XG4gICAgY29uc3QgeyBjaGFydCAsIF9jYWNoZWRNZXRhOiBtZXRhICB9ID0gY29udHJvbGxlcjtcbiAgICBjb25zdCBzdGFja3MgPSBjaGFydC5fc3RhY2tzIHx8IChjaGFydC5fc3RhY2tzID0ge30pO1xuICAgIGNvbnN0IHsgaVNjYWxlICwgdlNjYWxlICwgaW5kZXg6IGRhdGFzZXRJbmRleCAgfSA9IG1ldGE7XG4gICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICBjb25zdCB2QXhpcyA9IHZTY2FsZS5heGlzO1xuICAgIGNvbnN0IGtleSA9IGdldFN0YWNrS2V5KGlTY2FsZSwgdlNjYWxlLCBtZXRhKTtcbiAgICBjb25zdCBpbGVuID0gcGFyc2VkLmxlbmd0aDtcbiAgICBsZXQgc3RhY2s7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSBwYXJzZWRbaV07XG4gICAgICAgIGNvbnN0IHsgW2lBeGlzXTogaW5kZXggLCBbdkF4aXNdOiB2YWx1ZSAgfSA9IGl0ZW07XG4gICAgICAgIGNvbnN0IGl0ZW1TdGFja3MgPSBpdGVtLl9zdGFja3MgfHwgKGl0ZW0uX3N0YWNrcyA9IHt9KTtcbiAgICAgICAgc3RhY2sgPSBpdGVtU3RhY2tzW3ZBeGlzXSA9IGdldE9yQ3JlYXRlU3RhY2soc3RhY2tzLCBrZXksIGluZGV4KTtcbiAgICAgICAgc3RhY2tbZGF0YXNldEluZGV4XSA9IHZhbHVlO1xuICAgICAgICBzdGFjay5fdG9wID0gZ2V0TGFzdEluZGV4SW5TdGFjayhzdGFjaywgdlNjYWxlLCB0cnVlLCBtZXRhLnR5cGUpO1xuICAgICAgICBzdGFjay5fYm90dG9tID0gZ2V0TGFzdEluZGV4SW5TdGFjayhzdGFjaywgdlNjYWxlLCBmYWxzZSwgbWV0YS50eXBlKTtcbiAgICAgICAgY29uc3QgdmlzdWFsVmFsdWVzID0gc3RhY2suX3Zpc3VhbFZhbHVlcyB8fCAoc3RhY2suX3Zpc3VhbFZhbHVlcyA9IHt9KTtcbiAgICAgICAgdmlzdWFsVmFsdWVzW2RhdGFzZXRJbmRleF0gPSB2YWx1ZTtcbiAgICB9XG59XG5mdW5jdGlvbiBnZXRGaXJzdFNjYWxlSWQoY2hhcnQsIGF4aXMpIHtcbiAgICBjb25zdCBzY2FsZXMgPSBjaGFydC5zY2FsZXM7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHNjYWxlcykuZmlsdGVyKChrZXkpPT5zY2FsZXNba2V5XS5heGlzID09PSBheGlzKS5zaGlmdCgpO1xufVxuZnVuY3Rpb24gY3JlYXRlRGF0YXNldENvbnRleHQocGFyZW50LCBpbmRleCkge1xuICAgIHJldHVybiBjcmVhdGVDb250ZXh0KHBhcmVudCwge1xuICAgICAgICBhY3RpdmU6IGZhbHNlLFxuICAgICAgICBkYXRhc2V0OiB1bmRlZmluZWQsXG4gICAgICAgIGRhdGFzZXRJbmRleDogaW5kZXgsXG4gICAgICAgIGluZGV4LFxuICAgICAgICBtb2RlOiAnZGVmYXVsdCcsXG4gICAgICAgIHR5cGU6ICdkYXRhc2V0J1xuICAgIH0pO1xufVxuZnVuY3Rpb24gY3JlYXRlRGF0YUNvbnRleHQocGFyZW50LCBpbmRleCwgZWxlbWVudCkge1xuICAgIHJldHVybiBjcmVhdGVDb250ZXh0KHBhcmVudCwge1xuICAgICAgICBhY3RpdmU6IGZhbHNlLFxuICAgICAgICBkYXRhSW5kZXg6IGluZGV4LFxuICAgICAgICBwYXJzZWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgcmF3OiB1bmRlZmluZWQsXG4gICAgICAgIGVsZW1lbnQsXG4gICAgICAgIGluZGV4LFxuICAgICAgICBtb2RlOiAnZGVmYXVsdCcsXG4gICAgICAgIHR5cGU6ICdkYXRhJ1xuICAgIH0pO1xufVxuZnVuY3Rpb24gY2xlYXJTdGFja3MobWV0YSwgaXRlbXMpIHtcbiAgICBjb25zdCBkYXRhc2V0SW5kZXggPSBtZXRhLmNvbnRyb2xsZXIuaW5kZXg7XG4gICAgY29uc3QgYXhpcyA9IG1ldGEudlNjYWxlICYmIG1ldGEudlNjYWxlLmF4aXM7XG4gICAgaWYgKCFheGlzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaXRlbXMgPSBpdGVtcyB8fCBtZXRhLl9wYXJzZWQ7XG4gICAgZm9yIChjb25zdCBwYXJzZWQgb2YgaXRlbXMpe1xuICAgICAgICBjb25zdCBzdGFja3MgPSBwYXJzZWQuX3N0YWNrcztcbiAgICAgICAgaWYgKCFzdGFja3MgfHwgc3RhY2tzW2F4aXNdID09PSB1bmRlZmluZWQgfHwgc3RhY2tzW2F4aXNdW2RhdGFzZXRJbmRleF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSBzdGFja3NbYXhpc11bZGF0YXNldEluZGV4XTtcbiAgICAgICAgaWYgKHN0YWNrc1theGlzXS5fdmlzdWFsVmFsdWVzICE9PSB1bmRlZmluZWQgJiYgc3RhY2tzW2F4aXNdLl92aXN1YWxWYWx1ZXNbZGF0YXNldEluZGV4XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkZWxldGUgc3RhY2tzW2F4aXNdLl92aXN1YWxWYWx1ZXNbZGF0YXNldEluZGV4XTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmNvbnN0IGlzRGlyZWN0VXBkYXRlTW9kZSA9IChtb2RlKT0+bW9kZSA9PT0gJ3Jlc2V0JyB8fCBtb2RlID09PSAnbm9uZSc7XG5jb25zdCBjbG9uZUlmTm90U2hhcmVkID0gKGNhY2hlZCwgc2hhcmVkKT0+c2hhcmVkID8gY2FjaGVkIDogT2JqZWN0LmFzc2lnbih7fSwgY2FjaGVkKTtcbmNvbnN0IGNyZWF0ZVN0YWNrID0gKGNhblN0YWNrLCBtZXRhLCBjaGFydCk9PmNhblN0YWNrICYmICFtZXRhLmhpZGRlbiAmJiBtZXRhLl9zdGFja2VkICYmIHtcbiAgICAgICAga2V5czogZ2V0U29ydGVkRGF0YXNldEluZGljZXMoY2hhcnQsIHRydWUpLFxuICAgICAgICB2YWx1ZXM6IG51bGxcbiAgICB9O1xuY2xhc3MgRGF0YXNldENvbnRyb2xsZXIge1xuIHN0YXRpYyBkZWZhdWx0cyA9IHt9O1xuIHN0YXRpYyBkYXRhc2V0RWxlbWVudFR5cGUgPSBudWxsO1xuIHN0YXRpYyBkYXRhRWxlbWVudFR5cGUgPSBudWxsO1xuIGNvbnN0cnVjdG9yKGNoYXJ0LCBkYXRhc2V0SW5kZXgpe1xuICAgICAgICB0aGlzLmNoYXJ0ID0gY2hhcnQ7XG4gICAgICAgIHRoaXMuX2N0eCA9IGNoYXJ0LmN0eDtcbiAgICAgICAgdGhpcy5pbmRleCA9IGRhdGFzZXRJbmRleDtcbiAgICAgICAgdGhpcy5fY2FjaGVkRGF0YU9wdHMgPSB7fTtcbiAgICAgICAgdGhpcy5fY2FjaGVkTWV0YSA9IHRoaXMuZ2V0TWV0YSgpO1xuICAgICAgICB0aGlzLl90eXBlID0gdGhpcy5fY2FjaGVkTWV0YS50eXBlO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLl9wYXJzaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2RhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX29iamVjdERhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3NoYXJlZE9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2RyYXdTdGFydCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fZHJhd0NvdW50ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zdXBwb3J0c0RlY2ltYXRpb24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fc3luY0xpc3QgPSBbXTtcbiAgICAgICAgdGhpcy5kYXRhc2V0RWxlbWVudFR5cGUgPSBuZXcudGFyZ2V0LmRhdGFzZXRFbGVtZW50VHlwZTtcbiAgICAgICAgdGhpcy5kYXRhRWxlbWVudFR5cGUgPSBuZXcudGFyZ2V0LmRhdGFFbGVtZW50VHlwZTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKCk7XG4gICAgfVxuICAgIGluaXRpYWxpemUoKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyZSgpO1xuICAgICAgICB0aGlzLmxpbmtTY2FsZXMoKTtcbiAgICAgICAgbWV0YS5fc3RhY2tlZCA9IGlzU3RhY2tlZChtZXRhLnZTY2FsZSwgbWV0YSk7XG4gICAgICAgIHRoaXMuYWRkRWxlbWVudHMoKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5maWxsICYmICF0aGlzLmNoYXJ0LmlzUGx1Z2luRW5hYmxlZCgnZmlsbGVyJykpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlRyaWVkIHRvIHVzZSB0aGUgJ2ZpbGwnIG9wdGlvbiB3aXRob3V0IHRoZSAnRmlsbGVyJyBwbHVnaW4gZW5hYmxlZC4gUGxlYXNlIGltcG9ydCBhbmQgcmVnaXN0ZXIgdGhlICdGaWxsZXInIHBsdWdpbiBhbmQgbWFrZSBzdXJlIGl0IGlzIG5vdCBkaXNhYmxlZCBpbiB0aGUgb3B0aW9uc1wiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB1cGRhdGVJbmRleChkYXRhc2V0SW5kZXgpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5kZXggIT09IGRhdGFzZXRJbmRleCkge1xuICAgICAgICAgICAgY2xlYXJTdGFja3ModGhpcy5fY2FjaGVkTWV0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbmRleCA9IGRhdGFzZXRJbmRleDtcbiAgICB9XG4gICAgbGlua1NjYWxlcygpIHtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZ2V0RGF0YXNldCgpO1xuICAgICAgICBjb25zdCBjaG9vc2VJZCA9IChheGlzLCB4LCB5LCByKT0+YXhpcyA9PT0gJ3gnID8geCA6IGF4aXMgPT09ICdyJyA/IHIgOiB5O1xuICAgICAgICBjb25zdCB4aWQgPSBtZXRhLnhBeGlzSUQgPSB2YWx1ZU9yRGVmYXVsdChkYXRhc2V0LnhBeGlzSUQsIGdldEZpcnN0U2NhbGVJZChjaGFydCwgJ3gnKSk7XG4gICAgICAgIGNvbnN0IHlpZCA9IG1ldGEueUF4aXNJRCA9IHZhbHVlT3JEZWZhdWx0KGRhdGFzZXQueUF4aXNJRCwgZ2V0Rmlyc3RTY2FsZUlkKGNoYXJ0LCAneScpKTtcbiAgICAgICAgY29uc3QgcmlkID0gbWV0YS5yQXhpc0lEID0gdmFsdWVPckRlZmF1bHQoZGF0YXNldC5yQXhpc0lELCBnZXRGaXJzdFNjYWxlSWQoY2hhcnQsICdyJykpO1xuICAgICAgICBjb25zdCBpbmRleEF4aXMgPSBtZXRhLmluZGV4QXhpcztcbiAgICAgICAgY29uc3QgaWlkID0gbWV0YS5pQXhpc0lEID0gY2hvb3NlSWQoaW5kZXhBeGlzLCB4aWQsIHlpZCwgcmlkKTtcbiAgICAgICAgY29uc3QgdmlkID0gbWV0YS52QXhpc0lEID0gY2hvb3NlSWQoaW5kZXhBeGlzLCB5aWQsIHhpZCwgcmlkKTtcbiAgICAgICAgbWV0YS54U2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQoeGlkKTtcbiAgICAgICAgbWV0YS55U2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQoeWlkKTtcbiAgICAgICAgbWV0YS5yU2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQocmlkKTtcbiAgICAgICAgbWV0YS5pU2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQoaWlkKTtcbiAgICAgICAgbWV0YS52U2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQodmlkKTtcbiAgICB9XG4gICAgZ2V0RGF0YXNldCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnQuZGF0YS5kYXRhc2V0c1t0aGlzLmluZGV4XTtcbiAgICB9XG4gICAgZ2V0TWV0YSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnQuZ2V0RGF0YXNldE1ldGEodGhpcy5pbmRleCk7XG4gICAgfVxuIGdldFNjYWxlRm9ySWQoc2NhbGVJRCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jaGFydC5zY2FsZXNbc2NhbGVJRF07XG4gICAgfVxuIF9nZXRPdGhlclNjYWxlKHNjYWxlKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICByZXR1cm4gc2NhbGUgPT09IG1ldGEuaVNjYWxlID8gbWV0YS52U2NhbGUgOiBtZXRhLmlTY2FsZTtcbiAgICB9XG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZSgncmVzZXQnKTtcbiAgICB9XG4gX2Rlc3Ryb3koKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBpZiAodGhpcy5fZGF0YSkge1xuICAgICAgICAgICAgdW5saXN0ZW5BcnJheUV2ZW50cyh0aGlzLl9kYXRhLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YS5fc3RhY2tlZCkge1xuICAgICAgICAgICAgY2xlYXJTdGFja3MobWV0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gX2RhdGFDaGVjaygpIHtcbiAgICAgICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZ2V0RGF0YXNldCgpO1xuICAgICAgICBjb25zdCBkYXRhID0gZGF0YXNldC5kYXRhIHx8IChkYXRhc2V0LmRhdGEgPSBbXSk7XG4gICAgICAgIGNvbnN0IF9kYXRhID0gdGhpcy5fZGF0YTtcbiAgICAgICAgaWYgKGlzT2JqZWN0KGRhdGEpKSB7XG4gICAgICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGEgPSBjb252ZXJ0T2JqZWN0RGF0YVRvQXJyYXkoZGF0YSwgbWV0YSk7XG4gICAgICAgIH0gZWxzZSBpZiAoX2RhdGEgIT09IGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChfZGF0YSkge1xuICAgICAgICAgICAgICAgIHVubGlzdGVuQXJyYXlFdmVudHMoX2RhdGEsIHRoaXMpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICAgICAgICAgIGNsZWFyU3RhY2tzKG1ldGEpO1xuICAgICAgICAgICAgICAgIG1ldGEuX3BhcnNlZCA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRhdGEgJiYgT2JqZWN0LmlzRXh0ZW5zaWJsZShkYXRhKSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbkFycmF5RXZlbnRzKGRhdGEsIHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fc3luY0xpc3QgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGEgPSBkYXRhO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFkZEVsZW1lbnRzKCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgdGhpcy5fZGF0YUNoZWNrKCk7XG4gICAgICAgIGlmICh0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSkge1xuICAgICAgICAgICAgbWV0YS5kYXRhc2V0ID0gbmV3IHRoaXMuZGF0YXNldEVsZW1lbnRUeXBlKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYnVpbGRPclVwZGF0ZUVsZW1lbnRzKHJlc2V0TmV3RWxlbWVudHMpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGRhdGFzZXQgPSB0aGlzLmdldERhdGFzZXQoKTtcbiAgICAgICAgbGV0IHN0YWNrQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9kYXRhQ2hlY2soKTtcbiAgICAgICAgY29uc3Qgb2xkU3RhY2tlZCA9IG1ldGEuX3N0YWNrZWQ7XG4gICAgICAgIG1ldGEuX3N0YWNrZWQgPSBpc1N0YWNrZWQobWV0YS52U2NhbGUsIG1ldGEpO1xuICAgICAgICBpZiAobWV0YS5zdGFjayAhPT0gZGF0YXNldC5zdGFjaykge1xuICAgICAgICAgICAgc3RhY2tDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNsZWFyU3RhY2tzKG1ldGEpO1xuICAgICAgICAgICAgbWV0YS5zdGFjayA9IGRhdGFzZXQuc3RhY2s7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVzeW5jRWxlbWVudHMocmVzZXROZXdFbGVtZW50cyk7XG4gICAgICAgIGlmIChzdGFja0NoYW5nZWQgfHwgb2xkU3RhY2tlZCAhPT0gbWV0YS5fc3RhY2tlZCkge1xuICAgICAgICAgICAgdXBkYXRlU3RhY2tzKHRoaXMsIG1ldGEuX3BhcnNlZCk7XG4gICAgICAgICAgICBtZXRhLl9zdGFja2VkID0gaXNTdGFja2VkKG1ldGEudlNjYWxlLCBtZXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiBjb25maWd1cmUoKSB7XG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuY2hhcnQuY29uZmlnO1xuICAgICAgICBjb25zdCBzY29wZUtleXMgPSBjb25maWcuZGF0YXNldFNjb3BlS2V5cyh0aGlzLl90eXBlKTtcbiAgICAgICAgY29uc3Qgc2NvcGVzID0gY29uZmlnLmdldE9wdGlvblNjb3Blcyh0aGlzLmdldERhdGFzZXQoKSwgc2NvcGVLZXlzLCB0cnVlKTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gY29uZmlnLmNyZWF0ZVJlc29sdmVyKHNjb3BlcywgdGhpcy5nZXRDb250ZXh0KCkpO1xuICAgICAgICB0aGlzLl9wYXJzaW5nID0gdGhpcy5vcHRpb25zLnBhcnNpbmc7XG4gICAgICAgIHRoaXMuX2NhY2hlZERhdGFPcHRzID0ge307XG4gICAgfVxuIHBhcnNlKHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCB7IF9jYWNoZWRNZXRhOiBtZXRhICwgX2RhdGE6IGRhdGEgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IGlTY2FsZSAsIF9zdGFja2VkICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICAgICAgbGV0IHNvcnRlZCA9IHN0YXJ0ID09PSAwICYmIGNvdW50ID09PSBkYXRhLmxlbmd0aCA/IHRydWUgOiBtZXRhLl9zb3J0ZWQ7XG4gICAgICAgIGxldCBwcmV2ID0gc3RhcnQgPiAwICYmIG1ldGEuX3BhcnNlZFtzdGFydCAtIDFdO1xuICAgICAgICBsZXQgaSwgY3VyLCBwYXJzZWQ7XG4gICAgICAgIGlmICh0aGlzLl9wYXJzaW5nID09PSBmYWxzZSkge1xuICAgICAgICAgICAgbWV0YS5fcGFyc2VkID0gZGF0YTtcbiAgICAgICAgICAgIG1ldGEuX3NvcnRlZCA9IHRydWU7XG4gICAgICAgICAgICBwYXJzZWQgPSBkYXRhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzQXJyYXkoZGF0YVtzdGFydF0pKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VkID0gdGhpcy5wYXJzZUFycmF5RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChkYXRhW3N0YXJ0XSkpIHtcbiAgICAgICAgICAgICAgICBwYXJzZWQgPSB0aGlzLnBhcnNlT2JqZWN0RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwYXJzZWQgPSB0aGlzLnBhcnNlUHJpbWl0aXZlRGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaXNOb3RJbk9yZGVyQ29tcGFyZWRUb1ByZXYgPSAoKT0+Y3VyW2lBeGlzXSA9PT0gbnVsbCB8fCBwcmV2ICYmIGN1cltpQXhpc10gPCBwcmV2W2lBeGlzXTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyArK2kpe1xuICAgICAgICAgICAgICAgIG1ldGEuX3BhcnNlZFtpICsgc3RhcnRdID0gY3VyID0gcGFyc2VkW2ldO1xuICAgICAgICAgICAgICAgIGlmIChzb3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzTm90SW5PcmRlckNvbXBhcmVkVG9QcmV2KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNvcnRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHByZXYgPSBjdXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWV0YS5fc29ydGVkID0gc29ydGVkO1xuICAgICAgICB9XG4gICAgICAgIGlmIChfc3RhY2tlZCkge1xuICAgICAgICAgICAgdXBkYXRlU3RhY2tzKHRoaXMsIHBhcnNlZCk7XG4gICAgICAgIH1cbiAgICB9XG4gcGFyc2VQcmltaXRpdmVEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCB7IGlTY2FsZSAsIHZTY2FsZSAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IGlBeGlzID0gaVNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHZBeGlzID0gdlNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IGxhYmVscyA9IGlTY2FsZS5nZXRMYWJlbHMoKTtcbiAgICAgICAgY29uc3Qgc2luZ2xlU2NhbGUgPSBpU2NhbGUgPT09IHZTY2FsZTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICAgICAgbGV0IGksIGlsZW4sIGluZGV4O1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBpbmRleCA9IGkgKyBzdGFydDtcbiAgICAgICAgICAgIHBhcnNlZFtpXSA9IHtcbiAgICAgICAgICAgICAgICBbaUF4aXNdOiBzaW5nbGVTY2FsZSB8fCBpU2NhbGUucGFyc2UobGFiZWxzW2luZGV4XSwgaW5kZXgpLFxuICAgICAgICAgICAgICAgIFt2QXhpc106IHZTY2FsZS5wYXJzZShkYXRhW2luZGV4XSwgaW5kZXgpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuIHBhcnNlQXJyYXlEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCB7IHhTY2FsZSAsIHlTY2FsZSAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgICAgIGxldCBpLCBpbGVuLCBpbmRleCwgaXRlbTtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gY291bnQ7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgaW5kZXggPSBpICsgc3RhcnQ7XG4gICAgICAgICAgICBpdGVtID0gZGF0YVtpbmRleF07XG4gICAgICAgICAgICBwYXJzZWRbaV0gPSB7XG4gICAgICAgICAgICAgICAgeDogeFNjYWxlLnBhcnNlKGl0ZW1bMF0sIGluZGV4KSxcbiAgICAgICAgICAgICAgICB5OiB5U2NhbGUucGFyc2UoaXRlbVsxXSwgaW5kZXgpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuIHBhcnNlT2JqZWN0RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpIHtcbiAgICAgICAgY29uc3QgeyB4U2NhbGUgLCB5U2NhbGUgIH0gPSBtZXRhO1xuICAgICAgICBjb25zdCB7IHhBeGlzS2V5ID0neCcgLCB5QXhpc0tleSA9J3knICB9ID0gdGhpcy5fcGFyc2luZztcbiAgICAgICAgY29uc3QgcGFyc2VkID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICAgICAgbGV0IGksIGlsZW4sIGluZGV4LCBpdGVtO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBpbmRleCA9IGkgKyBzdGFydDtcbiAgICAgICAgICAgIGl0ZW0gPSBkYXRhW2luZGV4XTtcbiAgICAgICAgICAgIHBhcnNlZFtpXSA9IHtcbiAgICAgICAgICAgICAgICB4OiB4U2NhbGUucGFyc2UocmVzb2x2ZU9iamVjdEtleShpdGVtLCB4QXhpc0tleSksIGluZGV4KSxcbiAgICAgICAgICAgICAgICB5OiB5U2NhbGUucGFyc2UocmVzb2x2ZU9iamVjdEtleShpdGVtLCB5QXhpc0tleSksIGluZGV4KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFyc2VkO1xuICAgIH1cbiBnZXRQYXJzZWQoaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZE1ldGEuX3BhcnNlZFtpbmRleF07XG4gICAgfVxuIGdldERhdGFFbGVtZW50KGluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWNoZWRNZXRhLmRhdGFbaW5kZXhdO1xuICAgIH1cbiBhcHBseVN0YWNrKHNjYWxlLCBwYXJzZWQsIG1vZGUpIHtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBwYXJzZWRbc2NhbGUuYXhpc107XG4gICAgICAgIGNvbnN0IHN0YWNrID0ge1xuICAgICAgICAgICAga2V5czogZ2V0U29ydGVkRGF0YXNldEluZGljZXMoY2hhcnQsIHRydWUpLFxuICAgICAgICAgICAgdmFsdWVzOiBwYXJzZWQuX3N0YWNrc1tzY2FsZS5heGlzXS5fdmlzdWFsVmFsdWVzXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBhcHBseVN0YWNrKHN0YWNrLCB2YWx1ZSwgbWV0YS5pbmRleCwge1xuICAgICAgICAgICAgbW9kZVxuICAgICAgICB9KTtcbiAgICB9XG4gdXBkYXRlUmFuZ2VGcm9tUGFyc2VkKHJhbmdlLCBzY2FsZSwgcGFyc2VkLCBzdGFjaykge1xuICAgICAgICBjb25zdCBwYXJzZWRWYWx1ZSA9IHBhcnNlZFtzY2FsZS5heGlzXTtcbiAgICAgICAgbGV0IHZhbHVlID0gcGFyc2VkVmFsdWUgPT09IG51bGwgPyBOYU4gOiBwYXJzZWRWYWx1ZTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gc3RhY2sgJiYgcGFyc2VkLl9zdGFja3Nbc2NhbGUuYXhpc107XG4gICAgICAgIGlmIChzdGFjayAmJiB2YWx1ZXMpIHtcbiAgICAgICAgICAgIHN0YWNrLnZhbHVlcyA9IHZhbHVlcztcbiAgICAgICAgICAgIHZhbHVlID0gYXBwbHlTdGFjayhzdGFjaywgcGFyc2VkVmFsdWUsIHRoaXMuX2NhY2hlZE1ldGEuaW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHJhbmdlLm1pbiA9IE1hdGgubWluKHJhbmdlLm1pbiwgdmFsdWUpO1xuICAgICAgICByYW5nZS5tYXggPSBNYXRoLm1heChyYW5nZS5tYXgsIHZhbHVlKTtcbiAgICB9XG4gZ2V0TWluTWF4KHNjYWxlLCBjYW5TdGFjaykge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgX3BhcnNlZCA9IG1ldGEuX3BhcnNlZDtcbiAgICAgICAgY29uc3Qgc29ydGVkID0gbWV0YS5fc29ydGVkICYmIHNjYWxlID09PSBtZXRhLmlTY2FsZTtcbiAgICAgICAgY29uc3QgaWxlbiA9IF9wYXJzZWQubGVuZ3RoO1xuICAgICAgICBjb25zdCBvdGhlclNjYWxlID0gdGhpcy5fZ2V0T3RoZXJTY2FsZShzY2FsZSk7XG4gICAgICAgIGNvbnN0IHN0YWNrID0gY3JlYXRlU3RhY2soY2FuU3RhY2ssIG1ldGEsIHRoaXMuY2hhcnQpO1xuICAgICAgICBjb25zdCByYW5nZSA9IHtcbiAgICAgICAgICAgIG1pbjogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLFxuICAgICAgICAgICAgbWF4OiBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFlcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgeyBtaW46IG90aGVyTWluICwgbWF4OiBvdGhlck1heCAgfSA9IGdldFVzZXJCb3VuZHMob3RoZXJTY2FsZSk7XG4gICAgICAgIGxldCBpLCBwYXJzZWQ7XG4gICAgICAgIGZ1bmN0aW9uIF9za2lwKCkge1xuICAgICAgICAgICAgcGFyc2VkID0gX3BhcnNlZFtpXTtcbiAgICAgICAgICAgIGNvbnN0IG90aGVyVmFsdWUgPSBwYXJzZWRbb3RoZXJTY2FsZS5heGlzXTtcbiAgICAgICAgICAgIHJldHVybiAhaXNOdW1iZXJGaW5pdGUocGFyc2VkW3NjYWxlLmF4aXNdKSB8fCBvdGhlck1pbiA+IG90aGVyVmFsdWUgfHwgb3RoZXJNYXggPCBvdGhlclZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBpZiAoX3NraXAoKSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy51cGRhdGVSYW5nZUZyb21QYXJzZWQocmFuZ2UsIHNjYWxlLCBwYXJzZWQsIHN0YWNrKTtcbiAgICAgICAgICAgIGlmIChzb3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoc29ydGVkKSB7XG4gICAgICAgICAgICBmb3IoaSA9IGlsZW4gLSAxOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICAgICAgaWYgKF9za2lwKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlUmFuZ2VGcm9tUGFyc2VkKHJhbmdlLCBzY2FsZSwgcGFyc2VkLCBzdGFjayk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJhbmdlO1xuICAgIH1cbiAgICBnZXRBbGxQYXJzZWRWYWx1ZXMoc2NhbGUpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gdGhpcy5fY2FjaGVkTWV0YS5fcGFyc2VkO1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBbXTtcbiAgICAgICAgbGV0IGksIGlsZW4sIHZhbHVlO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBwYXJzZWQubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHZhbHVlID0gcGFyc2VkW2ldW3NjYWxlLmF4aXNdO1xuICAgICAgICAgICAgaWYgKGlzTnVtYmVyRmluaXRlKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgIH1cbiBnZXRNYXhPdmVyZmxvdygpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiBnZXRMYWJlbEFuZFZhbHVlKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBpU2NhbGUgPSBtZXRhLmlTY2FsZTtcbiAgICAgICAgY29uc3QgdlNjYWxlID0gbWV0YS52U2NhbGU7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxhYmVsOiBpU2NhbGUgPyAnJyArIGlTY2FsZS5nZXRMYWJlbEZvclZhbHVlKHBhcnNlZFtpU2NhbGUuYXhpc10pIDogJycsXG4gICAgICAgICAgICB2YWx1ZTogdlNjYWxlID8gJycgKyB2U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWRbdlNjYWxlLmF4aXNdKSA6ICcnXG4gICAgICAgIH07XG4gICAgfVxuIF91cGRhdGUobW9kZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgdGhpcy51cGRhdGUobW9kZSB8fCAnZGVmYXVsdCcpO1xuICAgICAgICBtZXRhLl9jbGlwID0gdG9DbGlwKHZhbHVlT3JEZWZhdWx0KHRoaXMub3B0aW9ucy5jbGlwLCBkZWZhdWx0Q2xpcChtZXRhLnhTY2FsZSwgbWV0YS55U2NhbGUsIHRoaXMuZ2V0TWF4T3ZlcmZsb3coKSkpKTtcbiAgICB9XG4gdXBkYXRlKG1vZGUpIHt9XG4gICAgZHJhdygpIHtcbiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fY3R4O1xuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBlbGVtZW50cyA9IG1ldGEuZGF0YSB8fCBbXTtcbiAgICAgICAgY29uc3QgYXJlYSA9IGNoYXJ0LmNoYXJ0QXJlYTtcbiAgICAgICAgY29uc3QgYWN0aXZlID0gW107XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5fZHJhd1N0YXJ0IHx8IDA7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gdGhpcy5fZHJhd0NvdW50IHx8IGVsZW1lbnRzLmxlbmd0aCAtIHN0YXJ0O1xuICAgICAgICBjb25zdCBkcmF3QWN0aXZlRWxlbWVudHNPblRvcCA9IHRoaXMub3B0aW9ucy5kcmF3QWN0aXZlRWxlbWVudHNPblRvcDtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGlmIChtZXRhLmRhdGFzZXQpIHtcbiAgICAgICAgICAgIG1ldGEuZGF0YXNldC5kcmF3KGN0eCwgYXJlYSwgc3RhcnQsIGNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgKytpKXtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBlbGVtZW50c1tpXTtcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmhpZGRlbikge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVsZW1lbnQuYWN0aXZlICYmIGRyYXdBY3RpdmVFbGVtZW50c09uVG9wKSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuZHJhdyhjdHgsIGFyZWEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGFjdGl2ZS5sZW5ndGg7ICsraSl7XG4gICAgICAgICAgICBhY3RpdmVbaV0uZHJhdyhjdHgsIGFyZWEpO1xuICAgICAgICB9XG4gICAgfVxuIGdldFN0eWxlKGluZGV4LCBhY3RpdmUpIHtcbiAgICAgICAgY29uc3QgbW9kZSA9IGFjdGl2ZSA/ICdhY3RpdmUnIDogJ2RlZmF1bHQnO1xuICAgICAgICByZXR1cm4gaW5kZXggPT09IHVuZGVmaW5lZCAmJiB0aGlzLl9jYWNoZWRNZXRhLmRhdGFzZXQgPyB0aGlzLnJlc29sdmVEYXRhc2V0RWxlbWVudE9wdGlvbnMobW9kZSkgOiB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaW5kZXggfHwgMCwgbW9kZSk7XG4gICAgfVxuIGdldENvbnRleHQoaW5kZXgsIGFjdGl2ZSwgbW9kZSkge1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5nZXREYXRhc2V0KCk7XG4gICAgICAgIGxldCBjb250ZXh0O1xuICAgICAgICBpZiAoaW5kZXggPj0gMCAmJiBpbmRleCA8IHRoaXMuX2NhY2hlZE1ldGEuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGFbaW5kZXhdO1xuICAgICAgICAgICAgY29udGV4dCA9IGVsZW1lbnQuJGNvbnRleHQgfHwgKGVsZW1lbnQuJGNvbnRleHQgPSBjcmVhdGVEYXRhQ29udGV4dCh0aGlzLmdldENvbnRleHQoKSwgaW5kZXgsIGVsZW1lbnQpKTtcbiAgICAgICAgICAgIGNvbnRleHQucGFyc2VkID0gdGhpcy5nZXRQYXJzZWQoaW5kZXgpO1xuICAgICAgICAgICAgY29udGV4dC5yYXcgPSBkYXRhc2V0LmRhdGFbaW5kZXhdO1xuICAgICAgICAgICAgY29udGV4dC5pbmRleCA9IGNvbnRleHQuZGF0YUluZGV4ID0gaW5kZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250ZXh0ID0gdGhpcy4kY29udGV4dCB8fCAodGhpcy4kY29udGV4dCA9IGNyZWF0ZURhdGFzZXRDb250ZXh0KHRoaXMuY2hhcnQuZ2V0Q29udGV4dCgpLCB0aGlzLmluZGV4KSk7XG4gICAgICAgICAgICBjb250ZXh0LmRhdGFzZXQgPSBkYXRhc2V0O1xuICAgICAgICAgICAgY29udGV4dC5pbmRleCA9IGNvbnRleHQuZGF0YXNldEluZGV4ID0gdGhpcy5pbmRleDtcbiAgICAgICAgfVxuICAgICAgICBjb250ZXh0LmFjdGl2ZSA9ICEhYWN0aXZlO1xuICAgICAgICBjb250ZXh0Lm1vZGUgPSBtb2RlO1xuICAgICAgICByZXR1cm4gY29udGV4dDtcbiAgICB9XG4gcmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyhtb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXNvbHZlRWxlbWVudE9wdGlvbnModGhpcy5kYXRhc2V0RWxlbWVudFR5cGUuaWQsIG1vZGUpO1xuICAgIH1cbiByZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGluZGV4LCBtb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXNvbHZlRWxlbWVudE9wdGlvbnModGhpcy5kYXRhRWxlbWVudFR5cGUuaWQsIG1vZGUsIGluZGV4KTtcbiAgICB9XG4gX3Jlc29sdmVFbGVtZW50T3B0aW9ucyhlbGVtZW50VHlwZSwgbW9kZSA9ICdkZWZhdWx0JywgaW5kZXgpIHtcbiAgICAgICAgY29uc3QgYWN0aXZlID0gbW9kZSA9PT0gJ2FjdGl2ZSc7XG4gICAgICAgIGNvbnN0IGNhY2hlID0gdGhpcy5fY2FjaGVkRGF0YU9wdHM7XG4gICAgICAgIGNvbnN0IGNhY2hlS2V5ID0gZWxlbWVudFR5cGUgKyAnLScgKyBtb2RlO1xuICAgICAgICBjb25zdCBjYWNoZWQgPSBjYWNoZVtjYWNoZUtleV07XG4gICAgICAgIGNvbnN0IHNoYXJpbmcgPSB0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmcgJiYgZGVmaW5lZChpbmRleCk7XG4gICAgICAgIGlmIChjYWNoZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBjbG9uZUlmTm90U2hhcmVkKGNhY2hlZCwgc2hhcmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29uZmlnID0gdGhpcy5jaGFydC5jb25maWc7XG4gICAgICAgIGNvbnN0IHNjb3BlS2V5cyA9IGNvbmZpZy5kYXRhc2V0RWxlbWVudFNjb3BlS2V5cyh0aGlzLl90eXBlLCBlbGVtZW50VHlwZSk7XG4gICAgICAgIGNvbnN0IHByZWZpeGVzID0gYWN0aXZlID8gW1xuICAgICAgICAgICAgYCR7ZWxlbWVudFR5cGV9SG92ZXJgLFxuICAgICAgICAgICAgJ2hvdmVyJyxcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlLFxuICAgICAgICAgICAgJydcbiAgICAgICAgXSA6IFtcbiAgICAgICAgICAgIGVsZW1lbnRUeXBlLFxuICAgICAgICAgICAgJydcbiAgICAgICAgXTtcbiAgICAgICAgY29uc3Qgc2NvcGVzID0gY29uZmlnLmdldE9wdGlvblNjb3Blcyh0aGlzLmdldERhdGFzZXQoKSwgc2NvcGVLZXlzKTtcbiAgICAgICAgY29uc3QgbmFtZXMgPSBPYmplY3Qua2V5cyhkZWZhdWx0cy5lbGVtZW50c1tlbGVtZW50VHlwZV0pO1xuICAgICAgICBjb25zdCBjb250ZXh0ID0gKCk9PnRoaXMuZ2V0Q29udGV4dChpbmRleCwgYWN0aXZlLCBtb2RlKTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gY29uZmlnLnJlc29sdmVOYW1lZE9wdGlvbnMoc2NvcGVzLCBuYW1lcywgY29udGV4dCwgcHJlZml4ZXMpO1xuICAgICAgICBpZiAodmFsdWVzLiRzaGFyZWQpIHtcbiAgICAgICAgICAgIHZhbHVlcy4kc2hhcmVkID0gc2hhcmluZztcbiAgICAgICAgICAgIGNhY2hlW2NhY2hlS2V5XSA9IE9iamVjdC5mcmVlemUoY2xvbmVJZk5vdFNoYXJlZCh2YWx1ZXMsIHNoYXJpbmcpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgIH1cbiBfcmVzb2x2ZUFuaW1hdGlvbnMoaW5kZXgsIHRyYW5zaXRpb24sIGFjdGl2ZSkge1xuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGNvbnN0IGNhY2hlID0gdGhpcy5fY2FjaGVkRGF0YU9wdHM7XG4gICAgICAgIGNvbnN0IGNhY2hlS2V5ID0gYGFuaW1hdGlvbi0ke3RyYW5zaXRpb259YDtcbiAgICAgICAgY29uc3QgY2FjaGVkID0gY2FjaGVbY2FjaGVLZXldO1xuICAgICAgICBpZiAoY2FjaGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkO1xuICAgICAgICB9XG4gICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICBpZiAoY2hhcnQub3B0aW9ucy5hbmltYXRpb24gIT09IGZhbHNlKSB7XG4gICAgICAgICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNoYXJ0LmNvbmZpZztcbiAgICAgICAgICAgIGNvbnN0IHNjb3BlS2V5cyA9IGNvbmZpZy5kYXRhc2V0QW5pbWF0aW9uU2NvcGVLZXlzKHRoaXMuX3R5cGUsIHRyYW5zaXRpb24pO1xuICAgICAgICAgICAgY29uc3Qgc2NvcGVzID0gY29uZmlnLmdldE9wdGlvblNjb3Blcyh0aGlzLmdldERhdGFzZXQoKSwgc2NvcGVLZXlzKTtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBjb25maWcuY3JlYXRlUmVzb2x2ZXIoc2NvcGVzLCB0aGlzLmdldENvbnRleHQoaW5kZXgsIGFjdGl2ZSwgdHJhbnNpdGlvbikpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBuZXcgQW5pbWF0aW9ucyhjaGFydCwgb3B0aW9ucyAmJiBvcHRpb25zLmFuaW1hdGlvbnMpO1xuICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLl9jYWNoZWFibGUpIHtcbiAgICAgICAgICAgIGNhY2hlW2NhY2hlS2V5XSA9IE9iamVjdC5mcmVlemUoYW5pbWF0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFuaW1hdGlvbnM7XG4gICAgfVxuIGdldFNoYXJlZE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgICBpZiAoIW9wdGlvbnMuJHNoYXJlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zaGFyZWRPcHRpb25zIHx8ICh0aGlzLl9zaGFyZWRPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgb3B0aW9ucykpO1xuICAgIH1cbiBpbmNsdWRlT3B0aW9ucyhtb2RlLCBzaGFyZWRPcHRpb25zKSB7XG4gICAgICAgIHJldHVybiAhc2hhcmVkT3B0aW9ucyB8fCBpc0RpcmVjdFVwZGF0ZU1vZGUobW9kZSkgfHwgdGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkO1xuICAgIH1cbiBfZ2V0U2hhcmVkT3B0aW9ucyhzdGFydCwgbW9kZSkge1xuICAgICAgICBjb25zdCBmaXJzdE9wdHMgPSB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoc3RhcnQsIG1vZGUpO1xuICAgICAgICBjb25zdCBwcmV2aW91c2x5U2hhcmVkT3B0aW9ucyA9IHRoaXMuX3NoYXJlZE9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHNoYXJlZE9wdGlvbnMgPSB0aGlzLmdldFNoYXJlZE9wdGlvbnMoZmlyc3RPcHRzKTtcbiAgICAgICAgY29uc3QgaW5jbHVkZU9wdGlvbnMgPSB0aGlzLmluY2x1ZGVPcHRpb25zKG1vZGUsIHNoYXJlZE9wdGlvbnMpIHx8IHNoYXJlZE9wdGlvbnMgIT09IHByZXZpb3VzbHlTaGFyZWRPcHRpb25zO1xuICAgICAgICB0aGlzLnVwZGF0ZVNoYXJlZE9wdGlvbnMoc2hhcmVkT3B0aW9ucywgbW9kZSwgZmlyc3RPcHRzKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNoYXJlZE9wdGlvbnMsXG4gICAgICAgICAgICBpbmNsdWRlT3B0aW9uc1xuICAgICAgICB9O1xuICAgIH1cbiB1cGRhdGVFbGVtZW50KGVsZW1lbnQsIGluZGV4LCBwcm9wZXJ0aWVzLCBtb2RlKSB7XG4gICAgICAgIGlmIChpc0RpcmVjdFVwZGF0ZU1vZGUobW9kZSkpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZWxlbWVudCwgcHJvcGVydGllcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9yZXNvbHZlQW5pbWF0aW9ucyhpbmRleCwgbW9kZSkudXBkYXRlKGVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICB9XG4gICAgfVxuIHVwZGF0ZVNoYXJlZE9wdGlvbnMoc2hhcmVkT3B0aW9ucywgbW9kZSwgbmV3T3B0aW9ucykge1xuICAgICAgICBpZiAoc2hhcmVkT3B0aW9ucyAmJiAhaXNEaXJlY3RVcGRhdGVNb2RlKG1vZGUpKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXNvbHZlQW5pbWF0aW9ucyh1bmRlZmluZWQsIG1vZGUpLnVwZGF0ZShzaGFyZWRPcHRpb25zLCBuZXdPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cbiBfc2V0U3R5bGUoZWxlbWVudCwgaW5kZXgsIG1vZGUsIGFjdGl2ZSkge1xuICAgICAgICBlbGVtZW50LmFjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuZ2V0U3R5bGUoaW5kZXgsIGFjdGl2ZSk7XG4gICAgICAgIHRoaXMuX3Jlc29sdmVBbmltYXRpb25zKGluZGV4LCBtb2RlLCBhY3RpdmUpLnVwZGF0ZShlbGVtZW50LCB7XG4gICAgICAgICAgICBvcHRpb25zOiAhYWN0aXZlICYmIHRoaXMuZ2V0U2hhcmVkT3B0aW9ucyhvcHRpb25zKSB8fCBvcHRpb25zXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZW1vdmVIb3ZlclN0eWxlKGVsZW1lbnQsIGRhdGFzZXRJbmRleCwgaW5kZXgpIHtcbiAgICAgICAgdGhpcy5fc2V0U3R5bGUoZWxlbWVudCwgaW5kZXgsICdhY3RpdmUnLCBmYWxzZSk7XG4gICAgfVxuICAgIHNldEhvdmVyU3R5bGUoZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleCkge1xuICAgICAgICB0aGlzLl9zZXRTdHlsZShlbGVtZW50LCBpbmRleCwgJ2FjdGl2ZScsIHRydWUpO1xuICAgIH1cbiBfcmVtb3ZlRGF0YXNldEhvdmVyU3R5bGUoKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGFzZXQ7XG4gICAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTdHlsZShlbGVtZW50LCB1bmRlZmluZWQsICdhY3RpdmUnLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9XG4gX3NldERhdGFzZXRIb3ZlclN0eWxlKCkge1xuICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fY2FjaGVkTWV0YS5kYXRhc2V0O1xuICAgICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5fc2V0U3R5bGUoZWxlbWVudCwgdW5kZWZpbmVkLCAnYWN0aXZlJywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gX3Jlc3luY0VsZW1lbnRzKHJlc2V0TmV3RWxlbWVudHMpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5fY2FjaGVkTWV0YS5kYXRhO1xuICAgICAgICBmb3IgKGNvbnN0IFttZXRob2QsIGFyZzEsIGFyZzJdIG9mIHRoaXMuX3N5bmNMaXN0KXtcbiAgICAgICAgICAgIHRoaXNbbWV0aG9kXShhcmcxLCBhcmcyKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zeW5jTGlzdCA9IFtdO1xuICAgICAgICBjb25zdCBudW1NZXRhID0gZWxlbWVudHMubGVuZ3RoO1xuICAgICAgICBjb25zdCBudW1EYXRhID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gTWF0aC5taW4obnVtRGF0YSwgbnVtTWV0YSk7XG4gICAgICAgIGlmIChjb3VudCkge1xuICAgICAgICAgICAgdGhpcy5wYXJzZSgwLCBjb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG51bURhdGEgPiBudW1NZXRhKSB7XG4gICAgICAgICAgICB0aGlzLl9pbnNlcnRFbGVtZW50cyhudW1NZXRhLCBudW1EYXRhIC0gbnVtTWV0YSwgcmVzZXROZXdFbGVtZW50cyk7XG4gICAgICAgIH0gZWxzZSBpZiAobnVtRGF0YSA8IG51bU1ldGEpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbW92ZUVsZW1lbnRzKG51bURhdGEsIG51bU1ldGEgLSBudW1EYXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiBfaW5zZXJ0RWxlbWVudHMoc3RhcnQsIGNvdW50LCByZXNldE5ld0VsZW1lbnRzID0gdHJ1ZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgZGF0YSA9IG1ldGEuZGF0YTtcbiAgICAgICAgY29uc3QgZW5kID0gc3RhcnQgKyBjb3VudDtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGNvbnN0IG1vdmUgPSAoYXJyKT0+e1xuICAgICAgICAgICAgYXJyLmxlbmd0aCArPSBjb3VudDtcbiAgICAgICAgICAgIGZvcihpID0gYXJyLmxlbmd0aCAtIDE7IGkgPj0gZW5kOyBpLS0pe1xuICAgICAgICAgICAgICAgIGFycltpXSA9IGFycltpIC0gY291bnRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBtb3ZlKGRhdGEpO1xuICAgICAgICBmb3IoaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpe1xuICAgICAgICAgICAgZGF0YVtpXSA9IG5ldyB0aGlzLmRhdGFFbGVtZW50VHlwZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9wYXJzaW5nKSB7XG4gICAgICAgICAgICBtb3ZlKG1ldGEuX3BhcnNlZCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYXJzZShzdGFydCwgY291bnQpO1xuICAgICAgICBpZiAocmVzZXROZXdFbGVtZW50cykge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50cyhkYXRhLCBzdGFydCwgY291bnQsICdyZXNldCcpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKGVsZW1lbnQsIHN0YXJ0LCBjb3VudCwgbW9kZSkge31cbiBfcmVtb3ZlRWxlbWVudHMoc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBpZiAodGhpcy5fcGFyc2luZykge1xuICAgICAgICAgICAgY29uc3QgcmVtb3ZlZCA9IG1ldGEuX3BhcnNlZC5zcGxpY2Uoc3RhcnQsIGNvdW50KTtcbiAgICAgICAgICAgIGlmIChtZXRhLl9zdGFja2VkKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJTdGFja3MobWV0YSwgcmVtb3ZlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbWV0YS5kYXRhLnNwbGljZShzdGFydCwgY291bnQpO1xuICAgIH1cbiBfc3luYyhhcmdzKSB7XG4gICAgICAgIGlmICh0aGlzLl9wYXJzaW5nKSB7XG4gICAgICAgICAgICB0aGlzLl9zeW5jTGlzdC5wdXNoKGFyZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgW21ldGhvZCwgYXJnMSwgYXJnMl0gPSBhcmdzO1xuICAgICAgICAgICAgdGhpc1ttZXRob2RdKGFyZzEsIGFyZzIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2hhcnQuX2RhdGFDaGFuZ2VzLnB1c2goW1xuICAgICAgICAgICAgdGhpcy5pbmRleCxcbiAgICAgICAgICAgIC4uLmFyZ3NcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIF9vbkRhdGFQdXNoKCkge1xuICAgICAgICBjb25zdCBjb3VudCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICAgIHRoaXMuX3N5bmMoW1xuICAgICAgICAgICAgJ19pbnNlcnRFbGVtZW50cycsXG4gICAgICAgICAgICB0aGlzLmdldERhdGFzZXQoKS5kYXRhLmxlbmd0aCAtIGNvdW50LFxuICAgICAgICAgICAgY291bnRcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIF9vbkRhdGFQb3AoKSB7XG4gICAgICAgIHRoaXMuX3N5bmMoW1xuICAgICAgICAgICAgJ19yZW1vdmVFbGVtZW50cycsXG4gICAgICAgICAgICB0aGlzLl9jYWNoZWRNZXRhLmRhdGEubGVuZ3RoIC0gMSxcbiAgICAgICAgICAgIDFcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIF9vbkRhdGFTaGlmdCgpIHtcbiAgICAgICAgdGhpcy5fc3luYyhbXG4gICAgICAgICAgICAnX3JlbW92ZUVsZW1lbnRzJyxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAxXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBfb25EYXRhU3BsaWNlKHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBpZiAoY291bnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3N5bmMoW1xuICAgICAgICAgICAgICAgICdfcmVtb3ZlRWxlbWVudHMnLFxuICAgICAgICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgICAgICAgIGNvdW50XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuZXdDb3VudCA9IGFyZ3VtZW50cy5sZW5ndGggLSAyO1xuICAgICAgICBpZiAobmV3Q291bnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3N5bmMoW1xuICAgICAgICAgICAgICAgICdfaW5zZXJ0RWxlbWVudHMnLFxuICAgICAgICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgICAgICAgIG5ld0NvdW50XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBfb25EYXRhVW5zaGlmdCgpIHtcbiAgICAgICAgdGhpcy5fc3luYyhbXG4gICAgICAgICAgICAnX2luc2VydEVsZW1lbnRzJyxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBhcmd1bWVudHMubGVuZ3RoXG4gICAgICAgIF0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0QWxsU2NhbGVWYWx1ZXMoc2NhbGUsIHR5cGUpIHtcbiAgICBpZiAoIXNjYWxlLl9jYWNoZS4kYmFyKSB7XG4gICAgICAgIGNvbnN0IHZpc2libGVNZXRhcyA9IHNjYWxlLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKHR5cGUpO1xuICAgICAgICBsZXQgdmFsdWVzID0gW107XG4gICAgICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSB2aXNpYmxlTWV0YXMubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgICAgIHZhbHVlcyA9IHZhbHVlcy5jb25jYXQodmlzaWJsZU1ldGFzW2ldLmNvbnRyb2xsZXIuZ2V0QWxsUGFyc2VkVmFsdWVzKHNjYWxlKSk7XG4gICAgICAgIH1cbiAgICAgICAgc2NhbGUuX2NhY2hlLiRiYXIgPSBfYXJyYXlVbmlxdWUodmFsdWVzLnNvcnQoKGEsIGIpPT5hIC0gYikpO1xuICAgIH1cbiAgICByZXR1cm4gc2NhbGUuX2NhY2hlLiRiYXI7XG59XG4gZnVuY3Rpb24gY29tcHV0ZU1pblNhbXBsZVNpemUobWV0YSkge1xuICAgIGNvbnN0IHNjYWxlID0gbWV0YS5pU2NhbGU7XG4gICAgY29uc3QgdmFsdWVzID0gZ2V0QWxsU2NhbGVWYWx1ZXMoc2NhbGUsIG1ldGEudHlwZSk7XG4gICAgbGV0IG1pbiA9IHNjYWxlLl9sZW5ndGg7XG4gICAgbGV0IGksIGlsZW4sIGN1cnIsIHByZXY7XG4gICAgY29uc3QgdXBkYXRlTWluQW5kUHJldiA9ICgpPT57XG4gICAgICAgIGlmIChjdXJyID09PSAzMjc2NyB8fCBjdXJyID09PSAtMzI3NjgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGVmaW5lZChwcmV2KSkge1xuICAgICAgICAgICAgbWluID0gTWF0aC5taW4obWluLCBNYXRoLmFicyhjdXJyIC0gcHJldikgfHwgbWluKTtcbiAgICAgICAgfVxuICAgICAgICBwcmV2ID0gY3VycjtcbiAgICB9O1xuICAgIGZvcihpID0gMCwgaWxlbiA9IHZhbHVlcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBjdXJyID0gc2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZXNbaV0pO1xuICAgICAgICB1cGRhdGVNaW5BbmRQcmV2KCk7XG4gICAgfVxuICAgIHByZXYgPSB1bmRlZmluZWQ7XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gc2NhbGUudGlja3MubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgY3VyciA9IHNjYWxlLmdldFBpeGVsRm9yVGljayhpKTtcbiAgICAgICAgdXBkYXRlTWluQW5kUHJldigpO1xuICAgIH1cbiAgICByZXR1cm4gbWluO1xufVxuIGZ1bmN0aW9uIGNvbXB1dGVGaXRDYXRlZ29yeVRyYWl0cyhpbmRleCwgcnVsZXIsIG9wdGlvbnMsIHN0YWNrQ291bnQpIHtcbiAgICBjb25zdCB0aGlja25lc3MgPSBvcHRpb25zLmJhclRoaWNrbmVzcztcbiAgICBsZXQgc2l6ZSwgcmF0aW87XG4gICAgaWYgKGlzTnVsbE9yVW5kZWYodGhpY2tuZXNzKSkge1xuICAgICAgICBzaXplID0gcnVsZXIubWluICogb3B0aW9ucy5jYXRlZ29yeVBlcmNlbnRhZ2U7XG4gICAgICAgIHJhdGlvID0gb3B0aW9ucy5iYXJQZXJjZW50YWdlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNpemUgPSB0aGlja25lc3MgKiBzdGFja0NvdW50O1xuICAgICAgICByYXRpbyA9IDE7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGNodW5rOiBzaXplIC8gc3RhY2tDb3VudCxcbiAgICAgICAgcmF0aW8sXG4gICAgICAgIHN0YXJ0OiBydWxlci5waXhlbHNbaW5kZXhdIC0gc2l6ZSAvIDJcbiAgICB9O1xufVxuIGZ1bmN0aW9uIGNvbXB1dGVGbGV4Q2F0ZWdvcnlUcmFpdHMoaW5kZXgsIHJ1bGVyLCBvcHRpb25zLCBzdGFja0NvdW50KSB7XG4gICAgY29uc3QgcGl4ZWxzID0gcnVsZXIucGl4ZWxzO1xuICAgIGNvbnN0IGN1cnIgPSBwaXhlbHNbaW5kZXhdO1xuICAgIGxldCBwcmV2ID0gaW5kZXggPiAwID8gcGl4ZWxzW2luZGV4IC0gMV0gOiBudWxsO1xuICAgIGxldCBuZXh0ID0gaW5kZXggPCBwaXhlbHMubGVuZ3RoIC0gMSA/IHBpeGVsc1tpbmRleCArIDFdIDogbnVsbDtcbiAgICBjb25zdCBwZXJjZW50ID0gb3B0aW9ucy5jYXRlZ29yeVBlcmNlbnRhZ2U7XG4gICAgaWYgKHByZXYgPT09IG51bGwpIHtcbiAgICAgICAgcHJldiA9IGN1cnIgLSAobmV4dCA9PT0gbnVsbCA/IHJ1bGVyLmVuZCAtIHJ1bGVyLnN0YXJ0IDogbmV4dCAtIGN1cnIpO1xuICAgIH1cbiAgICBpZiAobmV4dCA9PT0gbnVsbCkge1xuICAgICAgICBuZXh0ID0gY3VyciArIGN1cnIgLSBwcmV2O1xuICAgIH1cbiAgICBjb25zdCBzdGFydCA9IGN1cnIgLSAoY3VyciAtIE1hdGgubWluKHByZXYsIG5leHQpKSAvIDIgKiBwZXJjZW50O1xuICAgIGNvbnN0IHNpemUgPSBNYXRoLmFicyhuZXh0IC0gcHJldikgLyAyICogcGVyY2VudDtcbiAgICByZXR1cm4ge1xuICAgICAgICBjaHVuazogc2l6ZSAvIHN0YWNrQ291bnQsXG4gICAgICAgIHJhdGlvOiBvcHRpb25zLmJhclBlcmNlbnRhZ2UsXG4gICAgICAgIHN0YXJ0XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlRmxvYXRCYXIoZW50cnksIGl0ZW0sIHZTY2FsZSwgaSkge1xuICAgIGNvbnN0IHN0YXJ0VmFsdWUgPSB2U2NhbGUucGFyc2UoZW50cnlbMF0sIGkpO1xuICAgIGNvbnN0IGVuZFZhbHVlID0gdlNjYWxlLnBhcnNlKGVudHJ5WzFdLCBpKTtcbiAgICBjb25zdCBtaW4gPSBNYXRoLm1pbihzdGFydFZhbHVlLCBlbmRWYWx1ZSk7XG4gICAgY29uc3QgbWF4ID0gTWF0aC5tYXgoc3RhcnRWYWx1ZSwgZW5kVmFsdWUpO1xuICAgIGxldCBiYXJTdGFydCA9IG1pbjtcbiAgICBsZXQgYmFyRW5kID0gbWF4O1xuICAgIGlmIChNYXRoLmFicyhtaW4pID4gTWF0aC5hYnMobWF4KSkge1xuICAgICAgICBiYXJTdGFydCA9IG1heDtcbiAgICAgICAgYmFyRW5kID0gbWluO1xuICAgIH1cbiAgICBpdGVtW3ZTY2FsZS5heGlzXSA9IGJhckVuZDtcbiAgICBpdGVtLl9jdXN0b20gPSB7XG4gICAgICAgIGJhclN0YXJ0LFxuICAgICAgICBiYXJFbmQsXG4gICAgICAgIHN0YXJ0OiBzdGFydFZhbHVlLFxuICAgICAgICBlbmQ6IGVuZFZhbHVlLFxuICAgICAgICBtaW4sXG4gICAgICAgIG1heFxuICAgIH07XG59XG5mdW5jdGlvbiBwYXJzZVZhbHVlKGVudHJ5LCBpdGVtLCB2U2NhbGUsIGkpIHtcbiAgICBpZiAoaXNBcnJheShlbnRyeSkpIHtcbiAgICAgICAgcGFyc2VGbG9hdEJhcihlbnRyeSwgaXRlbSwgdlNjYWxlLCBpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpdGVtW3ZTY2FsZS5heGlzXSA9IHZTY2FsZS5wYXJzZShlbnRyeSwgaSk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtO1xufVxuZnVuY3Rpb24gcGFyc2VBcnJheU9yUHJpbWl0aXZlKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgIGNvbnN0IGlTY2FsZSA9IG1ldGEuaVNjYWxlO1xuICAgIGNvbnN0IHZTY2FsZSA9IG1ldGEudlNjYWxlO1xuICAgIGNvbnN0IGxhYmVscyA9IGlTY2FsZS5nZXRMYWJlbHMoKTtcbiAgICBjb25zdCBzaW5nbGVTY2FsZSA9IGlTY2FsZSA9PT0gdlNjYWxlO1xuICAgIGNvbnN0IHBhcnNlZCA9IFtdO1xuICAgIGxldCBpLCBpbGVuLCBpdGVtLCBlbnRyeTtcbiAgICBmb3IoaSA9IHN0YXJ0LCBpbGVuID0gc3RhcnQgKyBjb3VudDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGVudHJ5ID0gZGF0YVtpXTtcbiAgICAgICAgaXRlbSA9IHt9O1xuICAgICAgICBpdGVtW2lTY2FsZS5heGlzXSA9IHNpbmdsZVNjYWxlIHx8IGlTY2FsZS5wYXJzZShsYWJlbHNbaV0sIGkpO1xuICAgICAgICBwYXJzZWQucHVzaChwYXJzZVZhbHVlKGVudHJ5LCBpdGVtLCB2U2NhbGUsIGkpKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlZDtcbn1cbmZ1bmN0aW9uIGlzRmxvYXRCYXIoY3VzdG9tKSB7XG4gICAgcmV0dXJuIGN1c3RvbSAmJiBjdXN0b20uYmFyU3RhcnQgIT09IHVuZGVmaW5lZCAmJiBjdXN0b20uYmFyRW5kICE9PSB1bmRlZmluZWQ7XG59XG5mdW5jdGlvbiBiYXJTaWduKHNpemUsIHZTY2FsZSwgYWN0dWFsQmFzZSkge1xuICAgIGlmIChzaXplICE9PSAwKSB7XG4gICAgICAgIHJldHVybiBzaWduKHNpemUpO1xuICAgIH1cbiAgICByZXR1cm4gKHZTY2FsZS5pc0hvcml6b250YWwoKSA/IDEgOiAtMSkgKiAodlNjYWxlLm1pbiA+PSBhY3R1YWxCYXNlID8gMSA6IC0xKTtcbn1cbmZ1bmN0aW9uIGJvcmRlclByb3BzKHByb3BlcnRpZXMpIHtcbiAgICBsZXQgcmV2ZXJzZSwgc3RhcnQsIGVuZCwgdG9wLCBib3R0b207XG4gICAgaWYgKHByb3BlcnRpZXMuaG9yaXpvbnRhbCkge1xuICAgICAgICByZXZlcnNlID0gcHJvcGVydGllcy5iYXNlID4gcHJvcGVydGllcy54O1xuICAgICAgICBzdGFydCA9ICdsZWZ0JztcbiAgICAgICAgZW5kID0gJ3JpZ2h0JztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXZlcnNlID0gcHJvcGVydGllcy5iYXNlIDwgcHJvcGVydGllcy55O1xuICAgICAgICBzdGFydCA9ICdib3R0b20nO1xuICAgICAgICBlbmQgPSAndG9wJztcbiAgICB9XG4gICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgdG9wID0gJ2VuZCc7XG4gICAgICAgIGJvdHRvbSA9ICdzdGFydCc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdG9wID0gJ3N0YXJ0JztcbiAgICAgICAgYm90dG9tID0gJ2VuZCc7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0LFxuICAgICAgICBlbmQsXG4gICAgICAgIHJldmVyc2UsXG4gICAgICAgIHRvcCxcbiAgICAgICAgYm90dG9tXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHNldEJvcmRlclNraXBwZWQocHJvcGVydGllcywgb3B0aW9ucywgc3RhY2ssIGluZGV4KSB7XG4gICAgbGV0IGVkZ2UgPSBvcHRpb25zLmJvcmRlclNraXBwZWQ7XG4gICAgY29uc3QgcmVzID0ge307XG4gICAgaWYgKCFlZGdlKSB7XG4gICAgICAgIHByb3BlcnRpZXMuYm9yZGVyU2tpcHBlZCA9IHJlcztcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZWRnZSA9PT0gdHJ1ZSkge1xuICAgICAgICBwcm9wZXJ0aWVzLmJvcmRlclNraXBwZWQgPSB7XG4gICAgICAgICAgICB0b3A6IHRydWUsXG4gICAgICAgICAgICByaWdodDogdHJ1ZSxcbiAgICAgICAgICAgIGJvdHRvbTogdHJ1ZSxcbiAgICAgICAgICAgIGxlZnQ6IHRydWVcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB7IHN0YXJ0ICwgZW5kICwgcmV2ZXJzZSAsIHRvcCAsIGJvdHRvbSAgfSA9IGJvcmRlclByb3BzKHByb3BlcnRpZXMpO1xuICAgIGlmIChlZGdlID09PSAnbWlkZGxlJyAmJiBzdGFjaykge1xuICAgICAgICBwcm9wZXJ0aWVzLmVuYWJsZUJvcmRlclJhZGl1cyA9IHRydWU7XG4gICAgICAgIGlmICgoc3RhY2suX3RvcCB8fCAwKSA9PT0gaW5kZXgpIHtcbiAgICAgICAgICAgIGVkZ2UgPSB0b3A7XG4gICAgICAgIH0gZWxzZSBpZiAoKHN0YWNrLl9ib3R0b20gfHwgMCkgPT09IGluZGV4KSB7XG4gICAgICAgICAgICBlZGdlID0gYm90dG9tO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzW3BhcnNlRWRnZShib3R0b20sIHN0YXJ0LCBlbmQsIHJldmVyc2UpXSA9IHRydWU7XG4gICAgICAgICAgICBlZGdlID0gdG9wO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlc1twYXJzZUVkZ2UoZWRnZSwgc3RhcnQsIGVuZCwgcmV2ZXJzZSldID0gdHJ1ZTtcbiAgICBwcm9wZXJ0aWVzLmJvcmRlclNraXBwZWQgPSByZXM7XG59XG5mdW5jdGlvbiBwYXJzZUVkZ2UoZWRnZSwgYSwgYiwgcmV2ZXJzZSkge1xuICAgIGlmIChyZXZlcnNlKSB7XG4gICAgICAgIGVkZ2UgPSBzd2FwKGVkZ2UsIGEsIGIpO1xuICAgICAgICBlZGdlID0gc3RhcnRFbmQoZWRnZSwgYiwgYSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZWRnZSA9IHN0YXJ0RW5kKGVkZ2UsIGEsIGIpO1xuICAgIH1cbiAgICByZXR1cm4gZWRnZTtcbn1cbmZ1bmN0aW9uIHN3YXAob3JpZywgdjEsIHYyKSB7XG4gICAgcmV0dXJuIG9yaWcgPT09IHYxID8gdjIgOiBvcmlnID09PSB2MiA/IHYxIDogb3JpZztcbn1cbmZ1bmN0aW9uIHN0YXJ0RW5kKHYsIHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gdiA9PT0gJ3N0YXJ0JyA/IHN0YXJ0IDogdiA9PT0gJ2VuZCcgPyBlbmQgOiB2O1xufVxuZnVuY3Rpb24gc2V0SW5mbGF0ZUFtb3VudChwcm9wZXJ0aWVzLCB7IGluZmxhdGVBbW91bnQgIH0sIHJhdGlvKSB7XG4gICAgcHJvcGVydGllcy5pbmZsYXRlQW1vdW50ID0gaW5mbGF0ZUFtb3VudCA9PT0gJ2F1dG8nID8gcmF0aW8gPT09IDEgPyAwLjMzIDogMCA6IGluZmxhdGVBbW91bnQ7XG59XG5jbGFzcyBCYXJDb250cm9sbGVyIGV4dGVuZHMgRGF0YXNldENvbnRyb2xsZXIge1xuICAgIHN0YXRpYyBpZCA9ICdiYXInO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgZGF0YXNldEVsZW1lbnRUeXBlOiBmYWxzZSxcbiAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiAnYmFyJyxcbiAgICAgICAgY2F0ZWdvcnlQZXJjZW50YWdlOiAwLjgsXG4gICAgICAgIGJhclBlcmNlbnRhZ2U6IDAuOSxcbiAgICAgICAgZ3JvdXBlZDogdHJ1ZSxcbiAgICAgICAgYW5pbWF0aW9uczoge1xuICAgICAgICAgICAgbnVtYmVyczoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgJ3gnLFxuICAgICAgICAgICAgICAgICAgICAneScsXG4gICAgICAgICAgICAgICAgICAgICdiYXNlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJyxcbiAgICAgICAgICAgICAgICAgICAgJ2hlaWdodCdcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuIHN0YXRpYyBvdmVycmlkZXMgPSB7XG4gICAgICAgIHNjYWxlczoge1xuICAgICAgICAgICAgX2luZGV4Xzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdjYXRlZ29yeScsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiB0cnVlLFxuICAgICAgICAgICAgICAgIGdyaWQ6IHtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0OiB0cnVlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF92YWx1ZV86IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgICAgICAgICBiZWdpbkF0WmVybzogdHJ1ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiBwYXJzZVByaW1pdGl2ZURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIHJldHVybiBwYXJzZUFycmF5T3JQcmltaXRpdmUobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgICB9XG4gcGFyc2VBcnJheURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIHJldHVybiBwYXJzZUFycmF5T3JQcmltaXRpdmUobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgICB9XG4gcGFyc2VPYmplY3REYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCB7IGlTY2FsZSAsIHZTY2FsZSAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IHsgeEF4aXNLZXkgPSd4JyAsIHlBeGlzS2V5ID0neScgIH0gPSB0aGlzLl9wYXJzaW5nO1xuICAgICAgICBjb25zdCBpQXhpc0tleSA9IGlTY2FsZS5heGlzID09PSAneCcgPyB4QXhpc0tleSA6IHlBeGlzS2V5O1xuICAgICAgICBjb25zdCB2QXhpc0tleSA9IHZTY2FsZS5heGlzID09PSAneCcgPyB4QXhpc0tleSA6IHlBeGlzS2V5O1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBbXTtcbiAgICAgICAgbGV0IGksIGlsZW4sIGl0ZW0sIG9iajtcbiAgICAgICAgZm9yKGkgPSBzdGFydCwgaWxlbiA9IHN0YXJ0ICsgY291bnQ7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgb2JqID0gZGF0YVtpXTtcbiAgICAgICAgICAgIGl0ZW0gPSB7fTtcbiAgICAgICAgICAgIGl0ZW1baVNjYWxlLmF4aXNdID0gaVNjYWxlLnBhcnNlKHJlc29sdmVPYmplY3RLZXkob2JqLCBpQXhpc0tleSksIGkpO1xuICAgICAgICAgICAgcGFyc2VkLnB1c2gocGFyc2VWYWx1ZShyZXNvbHZlT2JqZWN0S2V5KG9iaiwgdkF4aXNLZXkpLCBpdGVtLCB2U2NhbGUsIGkpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFyc2VkO1xuICAgIH1cbiB1cGRhdGVSYW5nZUZyb21QYXJzZWQocmFuZ2UsIHNjYWxlLCBwYXJzZWQsIHN0YWNrKSB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZVJhbmdlRnJvbVBhcnNlZChyYW5nZSwgc2NhbGUsIHBhcnNlZCwgc3RhY2spO1xuICAgICAgICBjb25zdCBjdXN0b20gPSBwYXJzZWQuX2N1c3RvbTtcbiAgICAgICAgaWYgKGN1c3RvbSAmJiBzY2FsZSA9PT0gdGhpcy5fY2FjaGVkTWV0YS52U2NhbGUpIHtcbiAgICAgICAgICAgIHJhbmdlLm1pbiA9IE1hdGgubWluKHJhbmdlLm1pbiwgY3VzdG9tLm1pbik7XG4gICAgICAgICAgICByYW5nZS5tYXggPSBNYXRoLm1heChyYW5nZS5tYXgsIGN1c3RvbS5tYXgpO1xuICAgICAgICB9XG4gICAgfVxuIGdldE1heE92ZXJmbG93KCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgeyBpU2NhbGUgLCB2U2NhbGUgIH0gPSBtZXRhO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpbmRleCk7XG4gICAgICAgIGNvbnN0IGN1c3RvbSA9IHBhcnNlZC5fY3VzdG9tO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGlzRmxvYXRCYXIoY3VzdG9tKSA/ICdbJyArIGN1c3RvbS5zdGFydCArICcsICcgKyBjdXN0b20uZW5kICsgJ10nIDogJycgKyB2U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWRbdlNjYWxlLmF4aXNdKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxhYmVsOiAnJyArIGlTY2FsZS5nZXRMYWJlbEZvclZhbHVlKHBhcnNlZFtpU2NhbGUuYXhpc10pLFxuICAgICAgICAgICAgdmFsdWVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaW5pdGlhbGl6ZSgpIHtcbiAgICAgICAgdGhpcy5lbmFibGVPcHRpb25TaGFyaW5nID0gdHJ1ZTtcbiAgICAgICAgc3VwZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgbWV0YS5zdGFjayA9IHRoaXMuZ2V0RGF0YXNldCgpLnN0YWNrO1xuICAgIH1cbiAgICB1cGRhdGUobW9kZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50cyhtZXRhLmRhdGEsIDAsIG1ldGEuZGF0YS5sZW5ndGgsIG1vZGUpO1xuICAgIH1cbiAgICB1cGRhdGVFbGVtZW50cyhiYXJzLCBzdGFydCwgY291bnQsIG1vZGUpIHtcbiAgICAgICAgY29uc3QgcmVzZXQgPSBtb2RlID09PSAncmVzZXQnO1xuICAgICAgICBjb25zdCB7IGluZGV4ICwgX2NhY2hlZE1ldGE6IHsgdlNjYWxlICB9ICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgYmFzZSA9IHZTY2FsZS5nZXRCYXNlUGl4ZWwoKTtcbiAgICAgICAgY29uc3QgaG9yaXpvbnRhbCA9IHZTY2FsZS5pc0hvcml6b250YWwoKTtcbiAgICAgICAgY29uc3QgcnVsZXIgPSB0aGlzLl9nZXRSdWxlcigpO1xuICAgICAgICBjb25zdCB7IHNoYXJlZE9wdGlvbnMgLCBpbmNsdWRlT3B0aW9ucyAgfSA9IHRoaXMuX2dldFNoYXJlZE9wdGlvbnMoc3RhcnQsIG1vZGUpO1xuICAgICAgICBmb3IobGV0IGkgPSBzdGFydDsgaSA8IHN0YXJ0ICsgY291bnQ7IGkrKyl7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpKTtcbiAgICAgICAgICAgIGNvbnN0IHZwaXhlbHMgPSByZXNldCB8fCBpc051bGxPclVuZGVmKHBhcnNlZFt2U2NhbGUuYXhpc10pID8ge1xuICAgICAgICAgICAgICAgIGJhc2UsXG4gICAgICAgICAgICAgICAgaGVhZDogYmFzZVxuICAgICAgICAgICAgfSA6IHRoaXMuX2NhbGN1bGF0ZUJhclZhbHVlUGl4ZWxzKGkpO1xuICAgICAgICAgICAgY29uc3QgaXBpeGVscyA9IHRoaXMuX2NhbGN1bGF0ZUJhckluZGV4UGl4ZWxzKGksIHJ1bGVyKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YWNrID0gKHBhcnNlZC5fc3RhY2tzIHx8IHt9KVt2U2NhbGUuYXhpc107XG4gICAgICAgICAgICBjb25zdCBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGhvcml6b250YWwsXG4gICAgICAgICAgICAgICAgYmFzZTogdnBpeGVscy5iYXNlLFxuICAgICAgICAgICAgICAgIGVuYWJsZUJvcmRlclJhZGl1czogIXN0YWNrIHx8IGlzRmxvYXRCYXIocGFyc2VkLl9jdXN0b20pIHx8IGluZGV4ID09PSBzdGFjay5fdG9wIHx8IGluZGV4ID09PSBzdGFjay5fYm90dG9tLFxuICAgICAgICAgICAgICAgIHg6IGhvcml6b250YWwgPyB2cGl4ZWxzLmhlYWQgOiBpcGl4ZWxzLmNlbnRlcixcbiAgICAgICAgICAgICAgICB5OiBob3Jpem9udGFsID8gaXBpeGVscy5jZW50ZXIgOiB2cGl4ZWxzLmhlYWQsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBob3Jpem9udGFsID8gaXBpeGVscy5zaXplIDogTWF0aC5hYnModnBpeGVscy5zaXplKSxcbiAgICAgICAgICAgICAgICB3aWR0aDogaG9yaXpvbnRhbCA/IE1hdGguYWJzKHZwaXhlbHMuc2l6ZSkgOiBpcGl4ZWxzLnNpemVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoaW5jbHVkZU9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLm9wdGlvbnMgPSBzaGFyZWRPcHRpb25zIHx8IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpLCBiYXJzW2ldLmFjdGl2ZSA/ICdhY3RpdmUnIDogbW9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0gcHJvcGVydGllcy5vcHRpb25zIHx8IGJhcnNbaV0ub3B0aW9ucztcbiAgICAgICAgICAgIHNldEJvcmRlclNraXBwZWQocHJvcGVydGllcywgb3B0aW9ucywgc3RhY2ssIGluZGV4KTtcbiAgICAgICAgICAgIHNldEluZmxhdGVBbW91bnQocHJvcGVydGllcywgb3B0aW9ucywgcnVsZXIucmF0aW8pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50KGJhcnNbaV0sIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgICAgICB9XG4gICAgfVxuIF9nZXRTdGFja3MobGFzdCwgZGF0YUluZGV4KSB7XG4gICAgICAgIGNvbnN0IHsgaVNjYWxlICB9ID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgbWV0YXNldHMgPSBpU2NhbGUuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXModGhpcy5fdHlwZSkuZmlsdGVyKChtZXRhKT0+bWV0YS5jb250cm9sbGVyLm9wdGlvbnMuZ3JvdXBlZCk7XG4gICAgICAgIGNvbnN0IHN0YWNrZWQgPSBpU2NhbGUub3B0aW9ucy5zdGFja2VkO1xuICAgICAgICBjb25zdCBzdGFja3MgPSBbXTtcbiAgICAgICAgY29uc3QgY3VycmVudFBhcnNlZCA9IHRoaXMuX2NhY2hlZE1ldGEuY29udHJvbGxlci5nZXRQYXJzZWQoZGF0YUluZGV4KTtcbiAgICAgICAgY29uc3QgaVNjYWxlVmFsdWUgPSBjdXJyZW50UGFyc2VkICYmIGN1cnJlbnRQYXJzZWRbaVNjYWxlLmF4aXNdO1xuICAgICAgICBjb25zdCBza2lwTnVsbCA9IChtZXRhKT0+e1xuICAgICAgICAgICAgY29uc3QgcGFyc2VkID0gbWV0YS5fcGFyc2VkLmZpbmQoKGl0ZW0pPT5pdGVtW2lTY2FsZS5heGlzXSA9PT0gaVNjYWxlVmFsdWUpO1xuICAgICAgICAgICAgY29uc3QgdmFsID0gcGFyc2VkICYmIHBhcnNlZFttZXRhLnZTY2FsZS5heGlzXTtcbiAgICAgICAgICAgIGlmIChpc051bGxPclVuZGVmKHZhbCkgfHwgaXNOYU4odmFsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBmb3IgKGNvbnN0IG1ldGEgb2YgbWV0YXNldHMpe1xuICAgICAgICAgICAgaWYgKGRhdGFJbmRleCAhPT0gdW5kZWZpbmVkICYmIHNraXBOdWxsKG1ldGEpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhY2tlZCA9PT0gZmFsc2UgfHwgc3RhY2tzLmluZGV4T2YobWV0YS5zdGFjaykgPT09IC0xIHx8IHN0YWNrZWQgPT09IHVuZGVmaW5lZCAmJiBtZXRhLnN0YWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBzdGFja3MucHVzaChtZXRhLnN0YWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXRhLmluZGV4ID09PSBsYXN0KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFzdGFja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBzdGFja3MucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdGFja3M7XG4gICAgfVxuIF9nZXRTdGFja0NvdW50KGluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRTdGFja3ModW5kZWZpbmVkLCBpbmRleCkubGVuZ3RoO1xuICAgIH1cbiAgICBfZ2V0QXhpc0NvdW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0QXhpcygpLmxlbmd0aDtcbiAgICB9XG4gICAgZ2V0Rmlyc3RTY2FsZUlkRm9ySW5kZXhBeGlzKCkge1xuICAgICAgICBjb25zdCBzY2FsZXMgPSB0aGlzLmNoYXJ0LnNjYWxlcztcbiAgICAgICAgY29uc3QgaW5kZXhTY2FsZUlkID0gdGhpcy5jaGFydC5vcHRpb25zLmluZGV4QXhpcztcbiAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHNjYWxlcykuZmlsdGVyKChrZXkpPT5zY2FsZXNba2V5XS5heGlzID09PSBpbmRleFNjYWxlSWQpLnNoaWZ0KCk7XG4gICAgfVxuICAgIF9nZXRBeGlzKCkge1xuICAgICAgICBjb25zdCBheGlzID0ge307XG4gICAgICAgIGNvbnN0IGZpcnN0U2NhbGVBeGlzSWQgPSB0aGlzLmdldEZpcnN0U2NhbGVJZEZvckluZGV4QXhpcygpO1xuICAgICAgICBmb3IgKGNvbnN0IGRhdGFzZXQgb2YgdGhpcy5jaGFydC5kYXRhLmRhdGFzZXRzKXtcbiAgICAgICAgICAgIGF4aXNbdmFsdWVPckRlZmF1bHQodGhpcy5jaGFydC5vcHRpb25zLmluZGV4QXhpcyA9PT0gJ3gnID8gZGF0YXNldC54QXhpc0lEIDogZGF0YXNldC55QXhpc0lELCBmaXJzdFNjYWxlQXhpc0lkKV0gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhheGlzKTtcbiAgICB9XG4gX2dldFN0YWNrSW5kZXgoZGF0YXNldEluZGV4LCBuYW1lLCBkYXRhSW5kZXgpIHtcbiAgICAgICAgY29uc3Qgc3RhY2tzID0gdGhpcy5fZ2V0U3RhY2tzKGRhdGFzZXRJbmRleCwgZGF0YUluZGV4KTtcbiAgICAgICAgY29uc3QgaW5kZXggPSBuYW1lICE9PSB1bmRlZmluZWQgPyBzdGFja3MuaW5kZXhPZihuYW1lKSA6IC0xO1xuICAgICAgICByZXR1cm4gaW5kZXggPT09IC0xID8gc3RhY2tzLmxlbmd0aCAtIDEgOiBpbmRleDtcbiAgICB9XG4gX2dldFJ1bGVyKCkge1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgaVNjYWxlID0gbWV0YS5pU2NhbGU7XG4gICAgICAgIGNvbnN0IHBpeGVscyA9IFtdO1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gbWV0YS5kYXRhLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBwaXhlbHMucHVzaChpU2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZSh0aGlzLmdldFBhcnNlZChpKVtpU2NhbGUuYXhpc10sIGkpKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBiYXJUaGlja25lc3MgPSBvcHRzLmJhclRoaWNrbmVzcztcbiAgICAgICAgY29uc3QgbWluID0gYmFyVGhpY2tuZXNzIHx8IGNvbXB1dGVNaW5TYW1wbGVTaXplKG1ldGEpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbWluLFxuICAgICAgICAgICAgcGl4ZWxzLFxuICAgICAgICAgICAgc3RhcnQ6IGlTY2FsZS5fc3RhcnRQaXhlbCxcbiAgICAgICAgICAgIGVuZDogaVNjYWxlLl9lbmRQaXhlbCxcbiAgICAgICAgICAgIHN0YWNrQ291bnQ6IHRoaXMuX2dldFN0YWNrQ291bnQoKSxcbiAgICAgICAgICAgIHNjYWxlOiBpU2NhbGUsXG4gICAgICAgICAgICBncm91cGVkOiBvcHRzLmdyb3VwZWQsXG4gICAgICAgICAgICByYXRpbzogYmFyVGhpY2tuZXNzID8gMSA6IG9wdHMuY2F0ZWdvcnlQZXJjZW50YWdlICogb3B0cy5iYXJQZXJjZW50YWdlXG4gICAgICAgIH07XG4gICAgfVxuIF9jYWxjdWxhdGVCYXJWYWx1ZVBpeGVscyhpbmRleCkge1xuICAgICAgICBjb25zdCB7IF9jYWNoZWRNZXRhOiB7IHZTY2FsZSAsIF9zdGFja2VkICwgaW5kZXg6IGRhdGFzZXRJbmRleCAgfSAsIG9wdGlvbnM6IHsgYmFzZTogYmFzZVZhbHVlICwgbWluQmFyTGVuZ3RoICB9ICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgYWN0dWFsQmFzZSA9IGJhc2VWYWx1ZSB8fCAwO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpbmRleCk7XG4gICAgICAgIGNvbnN0IGN1c3RvbSA9IHBhcnNlZC5fY3VzdG9tO1xuICAgICAgICBjb25zdCBmbG9hdGluZyA9IGlzRmxvYXRCYXIoY3VzdG9tKTtcbiAgICAgICAgbGV0IHZhbHVlID0gcGFyc2VkW3ZTY2FsZS5heGlzXTtcbiAgICAgICAgbGV0IHN0YXJ0ID0gMDtcbiAgICAgICAgbGV0IGxlbmd0aCA9IF9zdGFja2VkID8gdGhpcy5hcHBseVN0YWNrKHZTY2FsZSwgcGFyc2VkLCBfc3RhY2tlZCkgOiB2YWx1ZTtcbiAgICAgICAgbGV0IGhlYWQsIHNpemU7XG4gICAgICAgIGlmIChsZW5ndGggIT09IHZhbHVlKSB7XG4gICAgICAgICAgICBzdGFydCA9IGxlbmd0aCAtIHZhbHVlO1xuICAgICAgICAgICAgbGVuZ3RoID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZsb2F0aW5nKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGN1c3RvbS5iYXJTdGFydDtcbiAgICAgICAgICAgIGxlbmd0aCA9IGN1c3RvbS5iYXJFbmQgLSBjdXN0b20uYmFyU3RhcnQ7XG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IDAgJiYgc2lnbih2YWx1ZSkgIT09IHNpZ24oY3VzdG9tLmJhckVuZCkpIHtcbiAgICAgICAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdGFydCArPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdGFydFZhbHVlID0gIWlzTnVsbE9yVW5kZWYoYmFzZVZhbHVlKSAmJiAhZmxvYXRpbmcgPyBiYXNlVmFsdWUgOiBzdGFydDtcbiAgICAgICAgbGV0IGJhc2UgPSB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShzdGFydFZhbHVlKTtcbiAgICAgICAgaWYgKHRoaXMuY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaW5kZXgpKSB7XG4gICAgICAgICAgICBoZWFkID0gdlNjYWxlLmdldFBpeGVsRm9yVmFsdWUoc3RhcnQgKyBsZW5ndGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGVhZCA9IGJhc2U7XG4gICAgICAgIH1cbiAgICAgICAgc2l6ZSA9IGhlYWQgLSBiYXNlO1xuICAgICAgICBpZiAoTWF0aC5hYnMoc2l6ZSkgPCBtaW5CYXJMZW5ndGgpIHtcbiAgICAgICAgICAgIHNpemUgPSBiYXJTaWduKHNpemUsIHZTY2FsZSwgYWN0dWFsQmFzZSkgKiBtaW5CYXJMZW5ndGg7XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IGFjdHVhbEJhc2UpIHtcbiAgICAgICAgICAgICAgICBiYXNlIC09IHNpemUgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc3RhcnRQaXhlbCA9IHZTY2FsZS5nZXRQaXhlbEZvckRlY2ltYWwoMCk7XG4gICAgICAgICAgICBjb25zdCBlbmRQaXhlbCA9IHZTY2FsZS5nZXRQaXhlbEZvckRlY2ltYWwoMSk7XG4gICAgICAgICAgICBjb25zdCBtaW4gPSBNYXRoLm1pbihzdGFydFBpeGVsLCBlbmRQaXhlbCk7XG4gICAgICAgICAgICBjb25zdCBtYXggPSBNYXRoLm1heChzdGFydFBpeGVsLCBlbmRQaXhlbCk7XG4gICAgICAgICAgICBiYXNlID0gTWF0aC5tYXgoTWF0aC5taW4oYmFzZSwgbWF4KSwgbWluKTtcbiAgICAgICAgICAgIGhlYWQgPSBiYXNlICsgc2l6ZTtcbiAgICAgICAgICAgIGlmIChfc3RhY2tlZCAmJiAhZmxvYXRpbmcpIHtcbiAgICAgICAgICAgICAgICBwYXJzZWQuX3N0YWNrc1t2U2NhbGUuYXhpc10uX3Zpc3VhbFZhbHVlc1tkYXRhc2V0SW5kZXhdID0gdlNjYWxlLmdldFZhbHVlRm9yUGl4ZWwoaGVhZCkgLSB2U2NhbGUuZ2V0VmFsdWVGb3JQaXhlbChiYXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoYmFzZSA9PT0gdlNjYWxlLmdldFBpeGVsRm9yVmFsdWUoYWN0dWFsQmFzZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGhhbGZHcmlkID0gc2lnbihzaXplKSAqIHZTY2FsZS5nZXRMaW5lV2lkdGhGb3JWYWx1ZShhY3R1YWxCYXNlKSAvIDI7XG4gICAgICAgICAgICBiYXNlICs9IGhhbGZHcmlkO1xuICAgICAgICAgICAgc2l6ZSAtPSBoYWxmR3JpZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc2l6ZSxcbiAgICAgICAgICAgIGJhc2UsXG4gICAgICAgICAgICBoZWFkLFxuICAgICAgICAgICAgY2VudGVyOiBoZWFkICsgc2l6ZSAvIDJcbiAgICAgICAgfTtcbiAgICB9XG4gX2NhbGN1bGF0ZUJhckluZGV4UGl4ZWxzKGluZGV4LCBydWxlcikge1xuICAgICAgICBjb25zdCBzY2FsZSA9IHJ1bGVyLnNjYWxlO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBza2lwTnVsbCA9IG9wdGlvbnMuc2tpcE51bGw7XG4gICAgICAgIGNvbnN0IG1heEJhclRoaWNrbmVzcyA9IHZhbHVlT3JEZWZhdWx0KG9wdGlvbnMubWF4QmFyVGhpY2tuZXNzLCBJbmZpbml0eSk7XG4gICAgICAgIGxldCBjZW50ZXIsIHNpemU7XG4gICAgICAgIGNvbnN0IGF4aXNDb3VudCA9IHRoaXMuX2dldEF4aXNDb3VudCgpO1xuICAgICAgICBpZiAocnVsZXIuZ3JvdXBlZCkge1xuICAgICAgICAgICAgY29uc3Qgc3RhY2tDb3VudCA9IHNraXBOdWxsID8gdGhpcy5fZ2V0U3RhY2tDb3VudChpbmRleCkgOiBydWxlci5zdGFja0NvdW50O1xuICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBvcHRpb25zLmJhclRoaWNrbmVzcyA9PT0gJ2ZsZXgnID8gY29tcHV0ZUZsZXhDYXRlZ29yeVRyYWl0cyhpbmRleCwgcnVsZXIsIG9wdGlvbnMsIHN0YWNrQ291bnQgKiBheGlzQ291bnQpIDogY29tcHV0ZUZpdENhdGVnb3J5VHJhaXRzKGluZGV4LCBydWxlciwgb3B0aW9ucywgc3RhY2tDb3VudCAqIGF4aXNDb3VudCk7XG4gICAgICAgICAgICBjb25zdCBheGlzSUQgPSB0aGlzLmNoYXJ0Lm9wdGlvbnMuaW5kZXhBeGlzID09PSAneCcgPyB0aGlzLmdldERhdGFzZXQoKS54QXhpc0lEIDogdGhpcy5nZXREYXRhc2V0KCkueUF4aXNJRDtcbiAgICAgICAgICAgIGNvbnN0IGF4aXNOdW1iZXIgPSB0aGlzLl9nZXRBeGlzKCkuaW5kZXhPZih2YWx1ZU9yRGVmYXVsdChheGlzSUQsIHRoaXMuZ2V0Rmlyc3RTY2FsZUlkRm9ySW5kZXhBeGlzKCkpKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YWNrSW5kZXggPSB0aGlzLl9nZXRTdGFja0luZGV4KHRoaXMuaW5kZXgsIHRoaXMuX2NhY2hlZE1ldGEuc3RhY2ssIHNraXBOdWxsID8gaW5kZXggOiB1bmRlZmluZWQpICsgYXhpc051bWJlcjtcbiAgICAgICAgICAgIGNlbnRlciA9IHJhbmdlLnN0YXJ0ICsgcmFuZ2UuY2h1bmsgKiBzdGFja0luZGV4ICsgcmFuZ2UuY2h1bmsgLyAyO1xuICAgICAgICAgICAgc2l6ZSA9IE1hdGgubWluKG1heEJhclRoaWNrbmVzcywgcmFuZ2UuY2h1bmsgKiByYW5nZS5yYXRpbyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjZW50ZXIgPSBzY2FsZS5nZXRQaXhlbEZvclZhbHVlKHRoaXMuZ2V0UGFyc2VkKGluZGV4KVtzY2FsZS5heGlzXSwgaW5kZXgpO1xuICAgICAgICAgICAgc2l6ZSA9IE1hdGgubWluKG1heEJhclRoaWNrbmVzcywgcnVsZXIubWluICogcnVsZXIucmF0aW8pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBiYXNlOiBjZW50ZXIgLSBzaXplIC8gMixcbiAgICAgICAgICAgIGhlYWQ6IGNlbnRlciArIHNpemUgLyAyLFxuICAgICAgICAgICAgY2VudGVyLFxuICAgICAgICAgICAgc2l6ZVxuICAgICAgICB9O1xuICAgIH1cbiAgICBkcmF3KCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgdlNjYWxlID0gbWV0YS52U2NhbGU7XG4gICAgICAgIGNvbnN0IHJlY3RzID0gbWV0YS5kYXRhO1xuICAgICAgICBjb25zdCBpbGVuID0gcmVjdHMubGVuZ3RoO1xuICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgIGZvcig7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0UGFyc2VkKGkpW3ZTY2FsZS5heGlzXSAhPT0gbnVsbCAmJiAhcmVjdHNbaV0uaGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgcmVjdHNbaV0uZHJhdyh0aGlzLl9jdHgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5jbGFzcyBCdWJibGVDb250cm9sbGVyIGV4dGVuZHMgRGF0YXNldENvbnRyb2xsZXIge1xuICAgIHN0YXRpYyBpZCA9ICdidWJibGUnO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgZGF0YXNldEVsZW1lbnRUeXBlOiBmYWxzZSxcbiAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiAncG9pbnQnLFxuICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICBudW1iZXJzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgcHJvcGVydGllczogW1xuICAgICAgICAgICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAgICAgICAgICd5JyxcbiAgICAgICAgICAgICAgICAgICAgJ2JvcmRlcldpZHRoJyxcbiAgICAgICAgICAgICAgICAgICAgJ3JhZGl1cydcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuIHN0YXRpYyBvdmVycmlkZXMgPSB7XG4gICAgICAgIHNjYWxlczoge1xuICAgICAgICAgICAgeDoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdsaW5lYXInXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeToge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdsaW5lYXInXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGluaXRpYWxpemUoKSB7XG4gICAgICAgIHRoaXMuZW5hYmxlT3B0aW9uU2hhcmluZyA9IHRydWU7XG4gICAgICAgIHN1cGVyLmluaXRpYWxpemUoKTtcbiAgICB9XG4gcGFyc2VQcmltaXRpdmVEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBzdXBlci5wYXJzZVByaW1pdGl2ZURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHBhcnNlZC5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICBwYXJzZWRbaV0uX2N1c3RvbSA9IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpICsgc3RhcnQpLnJhZGl1cztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFyc2VkO1xuICAgIH1cbiBwYXJzZUFycmF5RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gc3VwZXIucGFyc2VBcnJheURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHBhcnNlZC5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICBjb25zdCBpdGVtID0gZGF0YVtzdGFydCArIGldO1xuICAgICAgICAgICAgcGFyc2VkW2ldLl9jdXN0b20gPSB2YWx1ZU9yRGVmYXVsdChpdGVtWzJdLCB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSArIHN0YXJ0KS5yYWRpdXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuIHBhcnNlT2JqZWN0RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gc3VwZXIucGFyc2VPYmplY3REYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCk7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBwYXJzZWQubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgY29uc3QgaXRlbSA9IGRhdGFbc3RhcnQgKyBpXTtcbiAgICAgICAgICAgIHBhcnNlZFtpXS5fY3VzdG9tID0gdmFsdWVPckRlZmF1bHQoaXRlbSAmJiBpdGVtLnIgJiYgK2l0ZW0uciwgdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGkgKyBzdGFydCkucmFkaXVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFyc2VkO1xuICAgIH1cbiBnZXRNYXhPdmVyZmxvdygpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2NhY2hlZE1ldGEuZGF0YTtcbiAgICAgICAgbGV0IG1heCA9IDA7XG4gICAgICAgIGZvcihsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpe1xuICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCBkYXRhW2ldLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGkpKSAvIDIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXggPiAwICYmIG1heDtcbiAgICB9XG4gZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgbGFiZWxzID0gdGhpcy5jaGFydC5kYXRhLmxhYmVscyB8fCBbXTtcbiAgICAgICAgY29uc3QgeyB4U2NhbGUgLCB5U2NhbGUgIH0gPSBtZXRhO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpbmRleCk7XG4gICAgICAgIGNvbnN0IHggPSB4U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWQueCk7XG4gICAgICAgIGNvbnN0IHkgPSB5U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWQueSk7XG4gICAgICAgIGNvbnN0IHIgPSBwYXJzZWQuX2N1c3RvbTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxhYmVsOiBsYWJlbHNbaW5kZXhdIHx8ICcnLFxuICAgICAgICAgICAgdmFsdWU6ICcoJyArIHggKyAnLCAnICsgeSArIChyID8gJywgJyArIHIgOiAnJykgKyAnKSdcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdXBkYXRlKG1vZGUpIHtcbiAgICAgICAgY29uc3QgcG9pbnRzID0gdGhpcy5fY2FjaGVkTWV0YS5kYXRhO1xuICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnRzKHBvaW50cywgMCwgcG9pbnRzLmxlbmd0aCwgbW9kZSk7XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKHBvaW50cywgc3RhcnQsIGNvdW50LCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IHJlc2V0ID0gbW9kZSA9PT0gJ3Jlc2V0JztcbiAgICAgICAgY29uc3QgeyBpU2NhbGUgLCB2U2NhbGUgIH0gPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCB7IHNoYXJlZE9wdGlvbnMgLCBpbmNsdWRlT3B0aW9ucyAgfSA9IHRoaXMuX2dldFNoYXJlZE9wdGlvbnMoc3RhcnQsIG1vZGUpO1xuICAgICAgICBjb25zdCBpQXhpcyA9IGlTY2FsZS5heGlzO1xuICAgICAgICBjb25zdCB2QXhpcyA9IHZTY2FsZS5heGlzO1xuICAgICAgICBmb3IobGV0IGkgPSBzdGFydDsgaSA8IHN0YXJ0ICsgY291bnQ7IGkrKyl7XG4gICAgICAgICAgICBjb25zdCBwb2ludCA9IHBvaW50c1tpXTtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9ICFyZXNldCAmJiB0aGlzLmdldFBhcnNlZChpKTtcbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIGNvbnN0IGlQaXhlbCA9IHByb3BlcnRpZXNbaUF4aXNdID0gcmVzZXQgPyBpU2NhbGUuZ2V0UGl4ZWxGb3JEZWNpbWFsKDAuNSkgOiBpU2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShwYXJzZWRbaUF4aXNdKTtcbiAgICAgICAgICAgIGNvbnN0IHZQaXhlbCA9IHByb3BlcnRpZXNbdkF4aXNdID0gcmVzZXQgPyB2U2NhbGUuZ2V0QmFzZVBpeGVsKCkgOiB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShwYXJzZWRbdkF4aXNdKTtcbiAgICAgICAgICAgIHByb3BlcnRpZXMuc2tpcCA9IGlzTmFOKGlQaXhlbCkgfHwgaXNOYU4odlBpeGVsKTtcbiAgICAgICAgICAgIGlmIChpbmNsdWRlT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHByb3BlcnRpZXMub3B0aW9ucyA9IHNoYXJlZE9wdGlvbnMgfHwgdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGksIHBvaW50LmFjdGl2ZSA/ICdhY3RpdmUnIDogbW9kZSk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXMub3B0aW9ucy5yYWRpdXMgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudXBkYXRlRWxlbWVudChwb2ludCwgaSwgcHJvcGVydGllcywgbW9kZSk7XG4gICAgICAgIH1cbiAgICB9XG4gcmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpbmRleCwgbW9kZSkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpbmRleCk7XG4gICAgICAgIGxldCB2YWx1ZXMgPSBzdXBlci5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGluZGV4LCBtb2RlKTtcbiAgICAgICAgaWYgKHZhbHVlcy4kc2hhcmVkKSB7XG4gICAgICAgICAgICB2YWx1ZXMgPSBPYmplY3QuYXNzaWduKHt9LCB2YWx1ZXMsIHtcbiAgICAgICAgICAgICAgICAkc2hhcmVkOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmFkaXVzID0gdmFsdWVzLnJhZGl1cztcbiAgICAgICAgaWYgKG1vZGUgIT09ICdhY3RpdmUnKSB7XG4gICAgICAgICAgICB2YWx1ZXMucmFkaXVzID0gMDtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZXMucmFkaXVzICs9IHZhbHVlT3JEZWZhdWx0KHBhcnNlZCAmJiBwYXJzZWQuX2N1c3RvbSwgcmFkaXVzKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlcztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldFJhdGlvQW5kT2Zmc2V0KHJvdGF0aW9uLCBjaXJjdW1mZXJlbmNlLCBjdXRvdXQpIHtcbiAgICBsZXQgcmF0aW9YID0gMTtcbiAgICBsZXQgcmF0aW9ZID0gMTtcbiAgICBsZXQgb2Zmc2V0WCA9IDA7XG4gICAgbGV0IG9mZnNldFkgPSAwO1xuICAgIGlmIChjaXJjdW1mZXJlbmNlIDwgVEFVKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0QW5nbGUgPSByb3RhdGlvbjtcbiAgICAgICAgY29uc3QgZW5kQW5nbGUgPSBzdGFydEFuZ2xlICsgY2lyY3VtZmVyZW5jZTtcbiAgICAgICAgY29uc3Qgc3RhcnRYID0gTWF0aC5jb3Moc3RhcnRBbmdsZSk7XG4gICAgICAgIGNvbnN0IHN0YXJ0WSA9IE1hdGguc2luKHN0YXJ0QW5nbGUpO1xuICAgICAgICBjb25zdCBlbmRYID0gTWF0aC5jb3MoZW5kQW5nbGUpO1xuICAgICAgICBjb25zdCBlbmRZID0gTWF0aC5zaW4oZW5kQW5nbGUpO1xuICAgICAgICBjb25zdCBjYWxjTWF4ID0gKGFuZ2xlLCBhLCBiKT0+X2FuZ2xlQmV0d2VlbihhbmdsZSwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIHRydWUpID8gMSA6IE1hdGgubWF4KGEsIGEgKiBjdXRvdXQsIGIsIGIgKiBjdXRvdXQpO1xuICAgICAgICBjb25zdCBjYWxjTWluID0gKGFuZ2xlLCBhLCBiKT0+X2FuZ2xlQmV0d2VlbihhbmdsZSwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIHRydWUpID8gLTEgOiBNYXRoLm1pbihhLCBhICogY3V0b3V0LCBiLCBiICogY3V0b3V0KTtcbiAgICAgICAgY29uc3QgbWF4WCA9IGNhbGNNYXgoMCwgc3RhcnRYLCBlbmRYKTtcbiAgICAgICAgY29uc3QgbWF4WSA9IGNhbGNNYXgoSEFMRl9QSSwgc3RhcnRZLCBlbmRZKTtcbiAgICAgICAgY29uc3QgbWluWCA9IGNhbGNNaW4oUEksIHN0YXJ0WCwgZW5kWCk7XG4gICAgICAgIGNvbnN0IG1pblkgPSBjYWxjTWluKFBJICsgSEFMRl9QSSwgc3RhcnRZLCBlbmRZKTtcbiAgICAgICAgcmF0aW9YID0gKG1heFggLSBtaW5YKSAvIDI7XG4gICAgICAgIHJhdGlvWSA9IChtYXhZIC0gbWluWSkgLyAyO1xuICAgICAgICBvZmZzZXRYID0gLShtYXhYICsgbWluWCkgLyAyO1xuICAgICAgICBvZmZzZXRZID0gLShtYXhZICsgbWluWSkgLyAyO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICByYXRpb1gsXG4gICAgICAgIHJhdGlvWSxcbiAgICAgICAgb2Zmc2V0WCxcbiAgICAgICAgb2Zmc2V0WVxuICAgIH07XG59XG5jbGFzcyBEb3VnaG51dENvbnRyb2xsZXIgZXh0ZW5kcyBEYXRhc2V0Q29udHJvbGxlciB7XG4gICAgc3RhdGljIGlkID0gJ2RvdWdobnV0JztcbiBzdGF0aWMgZGVmYXVsdHMgPSB7XG4gICAgICAgIGRhdGFzZXRFbGVtZW50VHlwZTogZmFsc2UsXG4gICAgICAgIGRhdGFFbGVtZW50VHlwZTogJ2FyYycsXG4gICAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAgICAgYW5pbWF0ZVJvdGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGFuaW1hdGVTY2FsZTogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgYW5pbWF0aW9uczoge1xuICAgICAgICAgICAgbnVtYmVyczoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgJ2NpcmN1bWZlcmVuY2UnLFxuICAgICAgICAgICAgICAgICAgICAnZW5kQW5nbGUnLFxuICAgICAgICAgICAgICAgICAgICAnaW5uZXJSYWRpdXMnLFxuICAgICAgICAgICAgICAgICAgICAnb3V0ZXJSYWRpdXMnLFxuICAgICAgICAgICAgICAgICAgICAnc3RhcnRBbmdsZScsXG4gICAgICAgICAgICAgICAgICAgICd4JyxcbiAgICAgICAgICAgICAgICAgICAgJ3knLFxuICAgICAgICAgICAgICAgICAgICAnb2Zmc2V0JyxcbiAgICAgICAgICAgICAgICAgICAgJ2JvcmRlcldpZHRoJyxcbiAgICAgICAgICAgICAgICAgICAgJ3NwYWNpbmcnXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjdXRvdXQ6ICc1MCUnLFxuICAgICAgICByb3RhdGlvbjogMCxcbiAgICAgICAgY2lyY3VtZmVyZW5jZTogMzYwLFxuICAgICAgICByYWRpdXM6ICcxMDAlJyxcbiAgICAgICAgc3BhY2luZzogMCxcbiAgICAgICAgaW5kZXhBeGlzOiAncidcbiAgICB9O1xuICAgIHN0YXRpYyBkZXNjcmlwdG9ycyA9IHtcbiAgICAgICAgX3NjcmlwdGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ3NwYWNpbmcnLFxuICAgICAgICBfaW5kZXhhYmxlOiAobmFtZSk9Pm5hbWUgIT09ICdzcGFjaW5nJyAmJiAhbmFtZS5zdGFydHNXaXRoKCdib3JkZXJEYXNoJykgJiYgIW5hbWUuc3RhcnRzV2l0aCgnaG92ZXJCb3JkZXJEYXNoJylcbiAgICB9O1xuIHN0YXRpYyBvdmVycmlkZXMgPSB7XG4gICAgICAgIGFzcGVjdFJhdGlvOiAxLFxuICAgICAgICBwbHVnaW5zOiB7XG4gICAgICAgICAgICBsZWdlbmQ6IHtcbiAgICAgICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICAgICAgZ2VuZXJhdGVMYWJlbHMgKGNoYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gY2hhcnQuZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmxhYmVscy5sZW5ndGggJiYgZGF0YS5kYXRhc2V0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGxhYmVsczogeyBwb2ludFN0eWxlICwgY29sb3IgIH0gIH0gPSBjaGFydC5sZWdlbmQub3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YS5sYWJlbHMubWFwKChsYWJlbCwgaSk9PntcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHlsZSA9IG1ldGEuY29udHJvbGxlci5nZXRTdHlsZShpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGxhYmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbFN0eWxlOiBzdHlsZS5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VTdHlsZTogc3R5bGUuYm9yZGVyQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250Q29sb3I6IGNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZVdpZHRoOiBzdHlsZS5ib3JkZXJXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50U3R5bGU6IHBvaW50U3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRkZW46ICFjaGFydC5nZXREYXRhVmlzaWJpbGl0eShpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4OiBpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uQ2xpY2sgKGUsIGxlZ2VuZEl0ZW0sIGxlZ2VuZCkge1xuICAgICAgICAgICAgICAgICAgICBsZWdlbmQuY2hhcnQudG9nZ2xlRGF0YVZpc2liaWxpdHkobGVnZW5kSXRlbS5pbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5jaGFydC51cGRhdGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGNoYXJ0LCBkYXRhc2V0SW5kZXgpe1xuICAgICAgICBzdXBlcihjaGFydCwgZGF0YXNldEluZGV4KTtcbiAgICAgICAgdGhpcy5lbmFibGVPcHRpb25TaGFyaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5pbm5lclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5vdXRlclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5vZmZzZXRYID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm9mZnNldFkgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGxpbmtTY2FsZXMoKSB7fVxuIHBhcnNlKHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5nZXREYXRhc2V0KCkuZGF0YTtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGlmICh0aGlzLl9wYXJzaW5nID09PSBmYWxzZSkge1xuICAgICAgICAgICAgbWV0YS5fcGFyc2VkID0gZGF0YTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBnZXR0ZXIgPSAoaSk9PitkYXRhW2ldO1xuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KGRhdGFbc3RhcnRdKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsga2V5ID0ndmFsdWUnICB9ID0gdGhpcy5fcGFyc2luZztcbiAgICAgICAgICAgICAgICBnZXR0ZXIgPSAoaSk9PityZXNvbHZlT2JqZWN0S2V5KGRhdGFbaV0sIGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgICAgIGZvcihpID0gc3RhcnQsIGlsZW4gPSBzdGFydCArIGNvdW50OyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgICAgICBtZXRhLl9wYXJzZWRbaV0gPSBnZXR0ZXIoaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gX2dldFJvdGF0aW9uKCkge1xuICAgICAgICByZXR1cm4gdG9SYWRpYW5zKHRoaXMub3B0aW9ucy5yb3RhdGlvbiAtIDkwKTtcbiAgICB9XG4gX2dldENpcmN1bWZlcmVuY2UoKSB7XG4gICAgICAgIHJldHVybiB0b1JhZGlhbnModGhpcy5vcHRpb25zLmNpcmN1bWZlcmVuY2UpO1xuICAgIH1cbiBfZ2V0Um90YXRpb25FeHRlbnRzKCkge1xuICAgICAgICBsZXQgbWluID0gVEFVO1xuICAgICAgICBsZXQgbWF4ID0gLVRBVTtcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHRoaXMuY2hhcnQuZGF0YS5kYXRhc2V0cy5sZW5ndGg7ICsraSl7XG4gICAgICAgICAgICBpZiAodGhpcy5jaGFydC5pc0RhdGFzZXRWaXNpYmxlKGkpICYmIHRoaXMuY2hhcnQuZ2V0RGF0YXNldE1ldGEoaSkudHlwZSA9PT0gdGhpcy5fdHlwZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRyb2xsZXIgPSB0aGlzLmNoYXJ0LmdldERhdGFzZXRNZXRhKGkpLmNvbnRyb2xsZXI7XG4gICAgICAgICAgICAgICAgY29uc3Qgcm90YXRpb24gPSBjb250cm9sbGVyLl9nZXRSb3RhdGlvbigpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNpcmN1bWZlcmVuY2UgPSBjb250cm9sbGVyLl9nZXRDaXJjdW1mZXJlbmNlKCk7XG4gICAgICAgICAgICAgICAgbWluID0gTWF0aC5taW4obWluLCByb3RhdGlvbik7XG4gICAgICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCByb3RhdGlvbiArIGNpcmN1bWZlcmVuY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByb3RhdGlvbjogbWluLFxuICAgICAgICAgICAgY2lyY3VtZmVyZW5jZTogbWF4IC0gbWluXG4gICAgICAgIH07XG4gICAgfVxuIHVwZGF0ZShtb2RlKSB7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgeyBjaGFydEFyZWEgIH0gPSBjaGFydDtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGFyY3MgPSBtZXRhLmRhdGE7XG4gICAgICAgIGNvbnN0IHNwYWNpbmcgPSB0aGlzLmdldE1heEJvcmRlcldpZHRoKCkgKyB0aGlzLmdldE1heE9mZnNldChhcmNzKSArIHRoaXMub3B0aW9ucy5zcGFjaW5nO1xuICAgICAgICBjb25zdCBtYXhTaXplID0gTWF0aC5tYXgoKE1hdGgubWluKGNoYXJ0QXJlYS53aWR0aCwgY2hhcnRBcmVhLmhlaWdodCkgLSBzcGFjaW5nKSAvIDIsIDApO1xuICAgICAgICBjb25zdCBjdXRvdXQgPSBNYXRoLm1pbih0b1BlcmNlbnRhZ2UodGhpcy5vcHRpb25zLmN1dG91dCwgbWF4U2l6ZSksIDEpO1xuICAgICAgICBjb25zdCBjaGFydFdlaWdodCA9IHRoaXMuX2dldFJpbmdXZWlnaHQodGhpcy5pbmRleCk7XG4gICAgICAgIGNvbnN0IHsgY2lyY3VtZmVyZW5jZSAsIHJvdGF0aW9uICB9ID0gdGhpcy5fZ2V0Um90YXRpb25FeHRlbnRzKCk7XG4gICAgICAgIGNvbnN0IHsgcmF0aW9YICwgcmF0aW9ZICwgb2Zmc2V0WCAsIG9mZnNldFkgIH0gPSBnZXRSYXRpb0FuZE9mZnNldChyb3RhdGlvbiwgY2lyY3VtZmVyZW5jZSwgY3V0b3V0KTtcbiAgICAgICAgY29uc3QgbWF4V2lkdGggPSAoY2hhcnRBcmVhLndpZHRoIC0gc3BhY2luZykgLyByYXRpb1g7XG4gICAgICAgIGNvbnN0IG1heEhlaWdodCA9IChjaGFydEFyZWEuaGVpZ2h0IC0gc3BhY2luZykgLyByYXRpb1k7XG4gICAgICAgIGNvbnN0IG1heFJhZGl1cyA9IE1hdGgubWF4KE1hdGgubWluKG1heFdpZHRoLCBtYXhIZWlnaHQpIC8gMiwgMCk7XG4gICAgICAgIGNvbnN0IG91dGVyUmFkaXVzID0gdG9EaW1lbnNpb24odGhpcy5vcHRpb25zLnJhZGl1cywgbWF4UmFkaXVzKTtcbiAgICAgICAgY29uc3QgaW5uZXJSYWRpdXMgPSBNYXRoLm1heChvdXRlclJhZGl1cyAqIGN1dG91dCwgMCk7XG4gICAgICAgIGNvbnN0IHJhZGl1c0xlbmd0aCA9IChvdXRlclJhZGl1cyAtIGlubmVyUmFkaXVzKSAvIHRoaXMuX2dldFZpc2libGVEYXRhc2V0V2VpZ2h0VG90YWwoKTtcbiAgICAgICAgdGhpcy5vZmZzZXRYID0gb2Zmc2V0WCAqIG91dGVyUmFkaXVzO1xuICAgICAgICB0aGlzLm9mZnNldFkgPSBvZmZzZXRZICogb3V0ZXJSYWRpdXM7XG4gICAgICAgIG1ldGEudG90YWwgPSB0aGlzLmNhbGN1bGF0ZVRvdGFsKCk7XG4gICAgICAgIHRoaXMub3V0ZXJSYWRpdXMgPSBvdXRlclJhZGl1cyAtIHJhZGl1c0xlbmd0aCAqIHRoaXMuX2dldFJpbmdXZWlnaHRPZmZzZXQodGhpcy5pbmRleCk7XG4gICAgICAgIHRoaXMuaW5uZXJSYWRpdXMgPSBNYXRoLm1heCh0aGlzLm91dGVyUmFkaXVzIC0gcmFkaXVzTGVuZ3RoICogY2hhcnRXZWlnaHQsIDApO1xuICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnRzKGFyY3MsIDAsIGFyY3MubGVuZ3RoLCBtb2RlKTtcbiAgICB9XG4gX2NpcmN1bWZlcmVuY2UoaSwgcmVzZXQpIHtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGNpcmN1bWZlcmVuY2UgPSB0aGlzLl9nZXRDaXJjdW1mZXJlbmNlKCk7XG4gICAgICAgIGlmIChyZXNldCAmJiBvcHRzLmFuaW1hdGlvbi5hbmltYXRlUm90YXRlIHx8ICF0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpIHx8IG1ldGEuX3BhcnNlZFtpXSA9PT0gbnVsbCB8fCBtZXRhLmRhdGFbaV0uaGlkZGVuKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5jYWxjdWxhdGVDaXJjdW1mZXJlbmNlKG1ldGEuX3BhcnNlZFtpXSAqIGNpcmN1bWZlcmVuY2UgLyBUQVUpO1xuICAgIH1cbiAgICB1cGRhdGVFbGVtZW50cyhhcmNzLCBzdGFydCwgY291bnQsIG1vZGUpIHtcbiAgICAgICAgY29uc3QgcmVzZXQgPSBtb2RlID09PSAncmVzZXQnO1xuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGNvbnN0IGNoYXJ0QXJlYSA9IGNoYXJ0LmNoYXJ0QXJlYTtcbiAgICAgICAgY29uc3Qgb3B0cyA9IGNoYXJ0Lm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbk9wdHMgPSBvcHRzLmFuaW1hdGlvbjtcbiAgICAgICAgY29uc3QgY2VudGVyWCA9IChjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS5yaWdodCkgLyAyO1xuICAgICAgICBjb25zdCBjZW50ZXJZID0gKGNoYXJ0QXJlYS50b3AgKyBjaGFydEFyZWEuYm90dG9tKSAvIDI7XG4gICAgICAgIGNvbnN0IGFuaW1hdGVTY2FsZSA9IHJlc2V0ICYmIGFuaW1hdGlvbk9wdHMuYW5pbWF0ZVNjYWxlO1xuICAgICAgICBjb25zdCBpbm5lclJhZGl1cyA9IGFuaW1hdGVTY2FsZSA/IDAgOiB0aGlzLmlubmVyUmFkaXVzO1xuICAgICAgICBjb25zdCBvdXRlclJhZGl1cyA9IGFuaW1hdGVTY2FsZSA/IDAgOiB0aGlzLm91dGVyUmFkaXVzO1xuICAgICAgICBjb25zdCB7IHNoYXJlZE9wdGlvbnMgLCBpbmNsdWRlT3B0aW9ucyAgfSA9IHRoaXMuX2dldFNoYXJlZE9wdGlvbnMoc3RhcnQsIG1vZGUpO1xuICAgICAgICBsZXQgc3RhcnRBbmdsZSA9IHRoaXMuX2dldFJvdGF0aW9uKCk7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBzdGFydDsgKytpKXtcbiAgICAgICAgICAgIHN0YXJ0QW5nbGUgKz0gdGhpcy5fY2lyY3VtZmVyZW5jZShpLCByZXNldCk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSBzdGFydDsgaSA8IHN0YXJ0ICsgY291bnQ7ICsraSl7XG4gICAgICAgICAgICBjb25zdCBjaXJjdW1mZXJlbmNlID0gdGhpcy5fY2lyY3VtZmVyZW5jZShpLCByZXNldCk7XG4gICAgICAgICAgICBjb25zdCBhcmMgPSBhcmNzW2ldO1xuICAgICAgICAgICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICB4OiBjZW50ZXJYICsgdGhpcy5vZmZzZXRYLFxuICAgICAgICAgICAgICAgIHk6IGNlbnRlclkgKyB0aGlzLm9mZnNldFksXG4gICAgICAgICAgICAgICAgc3RhcnRBbmdsZSxcbiAgICAgICAgICAgICAgICBlbmRBbmdsZTogc3RhcnRBbmdsZSArIGNpcmN1bWZlcmVuY2UsXG4gICAgICAgICAgICAgICAgY2lyY3VtZmVyZW5jZSxcbiAgICAgICAgICAgICAgICBvdXRlclJhZGl1cyxcbiAgICAgICAgICAgICAgICBpbm5lclJhZGl1c1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChpbmNsdWRlT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHByb3BlcnRpZXMub3B0aW9ucyA9IHNoYXJlZE9wdGlvbnMgfHwgdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGksIGFyYy5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RhcnRBbmdsZSArPSBjaXJjdW1mZXJlbmNlO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50KGFyYywgaSwgcHJvcGVydGllcywgbW9kZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY2FsY3VsYXRlVG90YWwoKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBtZXRhRGF0YSA9IG1ldGEuZGF0YTtcbiAgICAgICAgbGV0IHRvdGFsID0gMDtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG1ldGFEYXRhLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gbWV0YS5fcGFyc2VkW2ldO1xuICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBudWxsICYmICFpc05hTih2YWx1ZSkgJiYgdGhpcy5jaGFydC5nZXREYXRhVmlzaWJpbGl0eShpKSAmJiAhbWV0YURhdGFbaV0uaGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgdG90YWwgKz0gTWF0aC5hYnModmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0b3RhbDtcbiAgICB9XG4gICAgY2FsY3VsYXRlQ2lyY3VtZmVyZW5jZSh2YWx1ZSkge1xuICAgICAgICBjb25zdCB0b3RhbCA9IHRoaXMuX2NhY2hlZE1ldGEudG90YWw7XG4gICAgICAgIGlmICh0b3RhbCA+IDAgJiYgIWlzTmFOKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIFRBVSAqIChNYXRoLmFicyh2YWx1ZSkgLyB0b3RhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGdldExhYmVsQW5kVmFsdWUoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgbGFiZWxzID0gY2hhcnQuZGF0YS5sYWJlbHMgfHwgW107XG4gICAgICAgIGNvbnN0IHZhbHVlID0gZm9ybWF0TnVtYmVyKG1ldGEuX3BhcnNlZFtpbmRleF0sIGNoYXJ0Lm9wdGlvbnMubG9jYWxlKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxhYmVsOiBsYWJlbHNbaW5kZXhdIHx8ICcnLFxuICAgICAgICAgICAgdmFsdWVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0TWF4Qm9yZGVyV2lkdGgoYXJjcykge1xuICAgICAgICBsZXQgbWF4ID0gMDtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBsZXQgaSwgaWxlbiwgbWV0YSwgY29udHJvbGxlciwgb3B0aW9ucztcbiAgICAgICAgaWYgKCFhcmNzKSB7XG4gICAgICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBjaGFydC5kYXRhLmRhdGFzZXRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICAgICAgaWYgKGNoYXJ0LmlzRGF0YXNldFZpc2libGUoaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgICAgICAgICBhcmNzID0gbWV0YS5kYXRhO1xuICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVyID0gbWV0YS5jb250cm9sbGVyO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFhcmNzKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBhcmNzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBvcHRpb25zID0gY29udHJvbGxlci5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGkpO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYm9yZGVyQWxpZ24gIT09ICdpbm5lcicpIHtcbiAgICAgICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIG9wdGlvbnMuYm9yZGVyV2lkdGggfHwgMCwgb3B0aW9ucy5ob3ZlckJvcmRlcldpZHRoIHx8IDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXg7XG4gICAgfVxuICAgIGdldE1heE9mZnNldChhcmNzKSB7XG4gICAgICAgIGxldCBtYXggPSAwO1xuICAgICAgICBmb3IobGV0IGkgPSAwLCBpbGVuID0gYXJjcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpKTtcbiAgICAgICAgICAgIG1heCA9IE1hdGgubWF4KG1heCwgb3B0aW9ucy5vZmZzZXQgfHwgMCwgb3B0aW9ucy5ob3Zlck9mZnNldCB8fCAwKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWF4O1xuICAgIH1cbiBfZ2V0UmluZ1dlaWdodE9mZnNldChkYXRhc2V0SW5kZXgpIHtcbiAgICAgICAgbGV0IHJpbmdXZWlnaHRPZmZzZXQgPSAwO1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgZGF0YXNldEluZGV4OyArK2kpe1xuICAgICAgICAgICAgaWYgKHRoaXMuY2hhcnQuaXNEYXRhc2V0VmlzaWJsZShpKSkge1xuICAgICAgICAgICAgICAgIHJpbmdXZWlnaHRPZmZzZXQgKz0gdGhpcy5fZ2V0UmluZ1dlaWdodChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmluZ1dlaWdodE9mZnNldDtcbiAgICB9XG4gX2dldFJpbmdXZWlnaHQoZGF0YXNldEluZGV4KSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1heCh2YWx1ZU9yRGVmYXVsdCh0aGlzLmNoYXJ0LmRhdGEuZGF0YXNldHNbZGF0YXNldEluZGV4XS53ZWlnaHQsIDEpLCAwKTtcbiAgICB9XG4gX2dldFZpc2libGVEYXRhc2V0V2VpZ2h0VG90YWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRSaW5nV2VpZ2h0T2Zmc2V0KHRoaXMuY2hhcnQuZGF0YS5kYXRhc2V0cy5sZW5ndGgpIHx8IDE7XG4gICAgfVxufVxuXG5jbGFzcyBMaW5lQ29udHJvbGxlciBleHRlbmRzIERhdGFzZXRDb250cm9sbGVyIHtcbiAgICBzdGF0aWMgaWQgPSAnbGluZSc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkYXRhc2V0RWxlbWVudFR5cGU6ICdsaW5lJyxcbiAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiAncG9pbnQnLFxuICAgICAgICBzaG93TGluZTogdHJ1ZSxcbiAgICAgICAgc3BhbkdhcHM6IGZhbHNlXG4gICAgfTtcbiBzdGF0aWMgb3ZlcnJpZGVzID0ge1xuICAgICAgICBzY2FsZXM6IHtcbiAgICAgICAgICAgIF9pbmRleF86IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnY2F0ZWdvcnknXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX3ZhbHVlXzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdsaW5lYXInXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGluaXRpYWxpemUoKSB7XG4gICAgICAgIHRoaXMuZW5hYmxlT3B0aW9uU2hhcmluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuc3VwcG9ydHNEZWNpbWF0aW9uID0gdHJ1ZTtcbiAgICAgICAgc3VwZXIuaW5pdGlhbGl6ZSgpO1xuICAgIH1cbiAgICB1cGRhdGUobW9kZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgeyBkYXRhc2V0OiBsaW5lICwgZGF0YTogcG9pbnRzID0gW10gLCBfZGF0YXNldCAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnNEaXNhYmxlZCA9IHRoaXMuY2hhcnQuX2FuaW1hdGlvbnNEaXNhYmxlZDtcbiAgICAgICAgbGV0IHsgc3RhcnQgLCBjb3VudCAgfSA9IF9nZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzKG1ldGEsIHBvaW50cywgYW5pbWF0aW9uc0Rpc2FibGVkKTtcbiAgICAgICAgdGhpcy5fZHJhd1N0YXJ0ID0gc3RhcnQ7XG4gICAgICAgIHRoaXMuX2RyYXdDb3VudCA9IGNvdW50O1xuICAgICAgICBpZiAoX3NjYWxlUmFuZ2VzQ2hhbmdlZChtZXRhKSkge1xuICAgICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICAgICAgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIGxpbmUuX2NoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgbGluZS5fZGF0YXNldEluZGV4ID0gdGhpcy5pbmRleDtcbiAgICAgICAgbGluZS5fZGVjaW1hdGVkID0gISFfZGF0YXNldC5fZGVjaW1hdGVkO1xuICAgICAgICBsaW5lLnBvaW50cyA9IHBvaW50cztcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMucmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyhtb2RlKTtcbiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuc2hvd0xpbmUpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuYm9yZGVyV2lkdGggPSAwO1xuICAgICAgICB9XG4gICAgICAgIG9wdGlvbnMuc2VnbWVudCA9IHRoaXMub3B0aW9ucy5zZWdtZW50O1xuICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQobGluZSwgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgICBhbmltYXRlZDogIWFuaW1hdGlvbnNEaXNhYmxlZCxcbiAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgfSwgbW9kZSk7XG4gICAgICAgIHRoaXMudXBkYXRlRWxlbWVudHMocG9pbnRzLCBzdGFydCwgY291bnQsIG1vZGUpO1xuICAgIH1cbiAgICB1cGRhdGVFbGVtZW50cyhwb2ludHMsIHN0YXJ0LCBjb3VudCwgbW9kZSkge1xuICAgICAgICBjb25zdCByZXNldCA9IG1vZGUgPT09ICdyZXNldCc7XG4gICAgICAgIGNvbnN0IHsgaVNjYWxlICwgdlNjYWxlICwgX3N0YWNrZWQgLCBfZGF0YXNldCAgfSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IHsgc2hhcmVkT3B0aW9ucyAsIGluY2x1ZGVPcHRpb25zICB9ID0gdGhpcy5fZ2V0U2hhcmVkT3B0aW9ucyhzdGFydCwgbW9kZSk7XG4gICAgICAgIGNvbnN0IGlBeGlzID0gaVNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHZBeGlzID0gdlNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHsgc3BhbkdhcHMgLCBzZWdtZW50ICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBtYXhHYXBMZW5ndGggPSBpc051bWJlcihzcGFuR2FwcykgPyBzcGFuR2FwcyA6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgY29uc3QgZGlyZWN0VXBkYXRlID0gdGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkIHx8IHJlc2V0IHx8IG1vZGUgPT09ICdub25lJztcbiAgICAgICAgY29uc3QgZW5kID0gc3RhcnQgKyBjb3VudDtcbiAgICAgICAgY29uc3QgcG9pbnRzQ291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgICAgICBsZXQgcHJldlBhcnNlZCA9IHN0YXJ0ID4gMCAmJiB0aGlzLmdldFBhcnNlZChzdGFydCAtIDEpO1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgcG9pbnRzQ291bnQ7ICsraSl7XG4gICAgICAgICAgICBjb25zdCBwb2ludCA9IHBvaW50c1tpXTtcbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBkaXJlY3RVcGRhdGUgPyBwb2ludCA6IHt9O1xuICAgICAgICAgICAgaWYgKGkgPCBzdGFydCB8fCBpID49IGVuZCkge1xuICAgICAgICAgICAgICAgIHByb3BlcnRpZXMuc2tpcCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpKTtcbiAgICAgICAgICAgIGNvbnN0IG51bGxEYXRhID0gaXNOdWxsT3JVbmRlZihwYXJzZWRbdkF4aXNdKTtcbiAgICAgICAgICAgIGNvbnN0IGlQaXhlbCA9IHByb3BlcnRpZXNbaUF4aXNdID0gaVNjYWxlLmdldFBpeGVsRm9yVmFsdWUocGFyc2VkW2lBeGlzXSwgaSk7XG4gICAgICAgICAgICBjb25zdCB2UGl4ZWwgPSBwcm9wZXJ0aWVzW3ZBeGlzXSA9IHJlc2V0IHx8IG51bGxEYXRhID8gdlNjYWxlLmdldEJhc2VQaXhlbCgpIDogdlNjYWxlLmdldFBpeGVsRm9yVmFsdWUoX3N0YWNrZWQgPyB0aGlzLmFwcGx5U3RhY2sodlNjYWxlLCBwYXJzZWQsIF9zdGFja2VkKSA6IHBhcnNlZFt2QXhpc10sIGkpO1xuICAgICAgICAgICAgcHJvcGVydGllcy5za2lwID0gaXNOYU4oaVBpeGVsKSB8fCBpc05hTih2UGl4ZWwpIHx8IG51bGxEYXRhO1xuICAgICAgICAgICAgcHJvcGVydGllcy5zdG9wID0gaSA+IDAgJiYgTWF0aC5hYnMocGFyc2VkW2lBeGlzXSAtIHByZXZQYXJzZWRbaUF4aXNdKSA+IG1heEdhcExlbmd0aDtcbiAgICAgICAgICAgIGlmIChzZWdtZW50KSB7XG4gICAgICAgICAgICAgICAgcHJvcGVydGllcy5wYXJzZWQgPSBwYXJzZWQ7XG4gICAgICAgICAgICAgICAgcHJvcGVydGllcy5yYXcgPSBfZGF0YXNldC5kYXRhW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluY2x1ZGVPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcHJvcGVydGllcy5vcHRpb25zID0gc2hhcmVkT3B0aW9ucyB8fCB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgcG9pbnQuYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghZGlyZWN0VXBkYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50KHBvaW50LCBpLCBwcm9wZXJ0aWVzLCBtb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByZXZQYXJzZWQgPSBwYXJzZWQ7XG4gICAgICAgIH1cbiAgICB9XG4gZ2V0TWF4T3ZlcmZsb3coKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gbWV0YS5kYXRhc2V0O1xuICAgICAgICBjb25zdCBib3JkZXIgPSBkYXRhc2V0Lm9wdGlvbnMgJiYgZGF0YXNldC5vcHRpb25zLmJvcmRlcldpZHRoIHx8IDA7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBtZXRhLmRhdGEgfHwgW107XG4gICAgICAgIGlmICghZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBib3JkZXI7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZmlyc3RQb2ludCA9IGRhdGFbMF0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoMCkpO1xuICAgICAgICBjb25zdCBsYXN0UG9pbnQgPSBkYXRhW2RhdGEubGVuZ3RoIC0gMV0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoZGF0YS5sZW5ndGggLSAxKSk7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChib3JkZXIsIGZpcnN0UG9pbnQsIGxhc3RQb2ludCkgLyAyO1xuICAgIH1cbiAgICBkcmF3KCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgbWV0YS5kYXRhc2V0LnVwZGF0ZUNvbnRyb2xQb2ludHModGhpcy5jaGFydC5jaGFydEFyZWEsIG1ldGEuaVNjYWxlLmF4aXMpO1xuICAgICAgICBzdXBlci5kcmF3KCk7XG4gICAgfVxufVxuXG5jbGFzcyBQb2xhckFyZWFDb250cm9sbGVyIGV4dGVuZHMgRGF0YXNldENvbnRyb2xsZXIge1xuICAgIHN0YXRpYyBpZCA9ICdwb2xhckFyZWEnO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiAnYXJjJyxcbiAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICBhbmltYXRlUm90YXRlOiB0cnVlLFxuICAgICAgICAgICAgYW5pbWF0ZVNjYWxlOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIGFuaW1hdGlvbnM6IHtcbiAgICAgICAgICAgIG51bWJlcnM6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBbXG4gICAgICAgICAgICAgICAgICAgICd4JyxcbiAgICAgICAgICAgICAgICAgICAgJ3knLFxuICAgICAgICAgICAgICAgICAgICAnc3RhcnRBbmdsZScsXG4gICAgICAgICAgICAgICAgICAgICdlbmRBbmdsZScsXG4gICAgICAgICAgICAgICAgICAgICdpbm5lclJhZGl1cycsXG4gICAgICAgICAgICAgICAgICAgICdvdXRlclJhZGl1cydcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGluZGV4QXhpczogJ3InLFxuICAgICAgICBzdGFydEFuZ2xlOiAwXG4gICAgfTtcbiBzdGF0aWMgb3ZlcnJpZGVzID0ge1xuICAgICAgICBhc3BlY3RSYXRpbzogMSxcbiAgICAgICAgcGx1Z2luczoge1xuICAgICAgICAgICAgbGVnZW5kOiB7XG4gICAgICAgICAgICAgICAgbGFiZWxzOiB7XG4gICAgICAgICAgICAgICAgICAgIGdlbmVyYXRlTGFiZWxzIChjaGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IGNoYXJ0LmRhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5sYWJlbHMubGVuZ3RoICYmIGRhdGEuZGF0YXNldHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeyBsYWJlbHM6IHsgcG9pbnRTdHlsZSAsIGNvbG9yICB9ICB9ID0gY2hhcnQubGVnZW5kLm9wdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGEubGFiZWxzLm1hcCgobGFiZWwsIGkpPT57XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldGEgPSBjaGFydC5nZXREYXRhc2V0TWV0YSgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3R5bGUgPSBtZXRhLmNvbnRyb2xsZXIuZ2V0U3R5bGUoaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBsYWJlbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxTdHlsZTogc3R5bGUuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlU3R5bGU6IHN0eWxlLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udENvbG9yOiBjb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVXaWR0aDogc3R5bGUuYm9yZGVyV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludFN0eWxlOiBwb2ludFN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlkZGVuOiAhY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleDogaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkNsaWNrIChlLCBsZWdlbmRJdGVtLCBsZWdlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmNoYXJ0LnRvZ2dsZURhdGFWaXNpYmlsaXR5KGxlZ2VuZEl0ZW0uaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBsZWdlbmQuY2hhcnQudXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzY2FsZXM6IHtcbiAgICAgICAgICAgIHI6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAncmFkaWFsTGluZWFyJyxcbiAgICAgICAgICAgICAgICBhbmdsZUxpbmVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBiZWdpbkF0WmVybzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBncmlkOiB7XG4gICAgICAgICAgICAgICAgICAgIGNpcmN1bGFyOiB0cnVlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwb2ludExhYmVsczoge1xuICAgICAgICAgICAgICAgICAgICBkaXNwbGF5OiBmYWxzZVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc3RhcnRBbmdsZTogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihjaGFydCwgZGF0YXNldEluZGV4KXtcbiAgICAgICAgc3VwZXIoY2hhcnQsIGRhdGFzZXRJbmRleCk7XG4gICAgICAgIHRoaXMuaW5uZXJSYWRpdXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMub3V0ZXJSYWRpdXMgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGdldExhYmVsQW5kVmFsdWUoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgbGFiZWxzID0gY2hhcnQuZGF0YS5sYWJlbHMgfHwgW107XG4gICAgICAgIGNvbnN0IHZhbHVlID0gZm9ybWF0TnVtYmVyKG1ldGEuX3BhcnNlZFtpbmRleF0uciwgY2hhcnQub3B0aW9ucy5sb2NhbGUpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGFiZWw6IGxhYmVsc1tpbmRleF0gfHwgJycsXG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICB9O1xuICAgIH1cbiAgICBwYXJzZU9iamVjdERhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIHJldHVybiBfcGFyc2VPYmplY3REYXRhUmFkaWFsU2NhbGUuYmluZCh0aGlzKShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgIH1cbiAgICB1cGRhdGUobW9kZSkge1xuICAgICAgICBjb25zdCBhcmNzID0gdGhpcy5fY2FjaGVkTWV0YS5kYXRhO1xuICAgICAgICB0aGlzLl91cGRhdGVSYWRpdXMoKTtcbiAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50cyhhcmNzLCAwLCBhcmNzLmxlbmd0aCwgbW9kZSk7XG4gICAgfVxuIGdldE1pbk1heCgpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IHJhbmdlID0ge1xuICAgICAgICAgICAgbWluOiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXG4gICAgICAgICAgICBtYXg6IE51bWJlci5ORUdBVElWRV9JTkZJTklUWVxuICAgICAgICB9O1xuICAgICAgICBtZXRhLmRhdGEuZm9yRWFjaCgoZWxlbWVudCwgaW5kZXgpPT57XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpbmRleCkucjtcbiAgICAgICAgICAgIGlmICghaXNOYU4ocGFyc2VkKSAmJiB0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGluZGV4KSkge1xuICAgICAgICAgICAgICAgIGlmIChwYXJzZWQgPCByYW5nZS5taW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2UubWluID0gcGFyc2VkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocGFyc2VkID4gcmFuZ2UubWF4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlLm1heCA9IHBhcnNlZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfVxuIF91cGRhdGVSYWRpdXMoKSB7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgY2hhcnRBcmVhID0gY2hhcnQuY2hhcnRBcmVhO1xuICAgICAgICBjb25zdCBvcHRzID0gY2hhcnQub3B0aW9ucztcbiAgICAgICAgY29uc3QgbWluU2l6ZSA9IE1hdGgubWluKGNoYXJ0QXJlYS5yaWdodCAtIGNoYXJ0QXJlYS5sZWZ0LCBjaGFydEFyZWEuYm90dG9tIC0gY2hhcnRBcmVhLnRvcCk7XG4gICAgICAgIGNvbnN0IG91dGVyUmFkaXVzID0gTWF0aC5tYXgobWluU2l6ZSAvIDIsIDApO1xuICAgICAgICBjb25zdCBpbm5lclJhZGl1cyA9IE1hdGgubWF4KG9wdHMuY3V0b3V0UGVyY2VudGFnZSA/IG91dGVyUmFkaXVzIC8gMTAwICogb3B0cy5jdXRvdXRQZXJjZW50YWdlIDogMSwgMCk7XG4gICAgICAgIGNvbnN0IHJhZGl1c0xlbmd0aCA9IChvdXRlclJhZGl1cyAtIGlubmVyUmFkaXVzKSAvIGNoYXJ0LmdldFZpc2libGVEYXRhc2V0Q291bnQoKTtcbiAgICAgICAgdGhpcy5vdXRlclJhZGl1cyA9IG91dGVyUmFkaXVzIC0gcmFkaXVzTGVuZ3RoICogdGhpcy5pbmRleDtcbiAgICAgICAgdGhpcy5pbm5lclJhZGl1cyA9IHRoaXMub3V0ZXJSYWRpdXMgLSByYWRpdXNMZW5ndGg7XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKGFyY3MsIHN0YXJ0LCBjb3VudCwgbW9kZSkge1xuICAgICAgICBjb25zdCByZXNldCA9IG1vZGUgPT09ICdyZXNldCc7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3Qgb3B0cyA9IGNoYXJ0Lm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbk9wdHMgPSBvcHRzLmFuaW1hdGlvbjtcbiAgICAgICAgY29uc3Qgc2NhbGUgPSB0aGlzLl9jYWNoZWRNZXRhLnJTY2FsZTtcbiAgICAgICAgY29uc3QgY2VudGVyWCA9IHNjYWxlLnhDZW50ZXI7XG4gICAgICAgIGNvbnN0IGNlbnRlclkgPSBzY2FsZS55Q2VudGVyO1xuICAgICAgICBjb25zdCBkYXRhc2V0U3RhcnRBbmdsZSA9IHNjYWxlLmdldEluZGV4QW5nbGUoMCkgLSAwLjUgKiBQSTtcbiAgICAgICAgbGV0IGFuZ2xlID0gZGF0YXNldFN0YXJ0QW5nbGU7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBjb25zdCBkZWZhdWx0QW5nbGUgPSAzNjAgLyB0aGlzLmNvdW50VmlzaWJsZUVsZW1lbnRzKCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHN0YXJ0OyArK2kpe1xuICAgICAgICAgICAgYW5nbGUgKz0gdGhpcy5fY29tcHV0ZUFuZ2xlKGksIG1vZGUsIGRlZmF1bHRBbmdsZSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSBzdGFydDsgaSA8IHN0YXJ0ICsgY291bnQ7IGkrKyl7XG4gICAgICAgICAgICBjb25zdCBhcmMgPSBhcmNzW2ldO1xuICAgICAgICAgICAgbGV0IHN0YXJ0QW5nbGUgPSBhbmdsZTtcbiAgICAgICAgICAgIGxldCBlbmRBbmdsZSA9IGFuZ2xlICsgdGhpcy5fY29tcHV0ZUFuZ2xlKGksIG1vZGUsIGRlZmF1bHRBbmdsZSk7XG4gICAgICAgICAgICBsZXQgb3V0ZXJSYWRpdXMgPSBjaGFydC5nZXREYXRhVmlzaWJpbGl0eShpKSA/IHNjYWxlLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKHRoaXMuZ2V0UGFyc2VkKGkpLnIpIDogMDtcbiAgICAgICAgICAgIGFuZ2xlID0gZW5kQW5nbGU7XG4gICAgICAgICAgICBpZiAocmVzZXQpIHtcbiAgICAgICAgICAgICAgICBpZiAoYW5pbWF0aW9uT3B0cy5hbmltYXRlU2NhbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0ZXJSYWRpdXMgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYW5pbWF0aW9uT3B0cy5hbmltYXRlUm90YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0QW5nbGUgPSBlbmRBbmdsZSA9IGRhdGFzZXRTdGFydEFuZ2xlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgeDogY2VudGVyWCxcbiAgICAgICAgICAgICAgICB5OiBjZW50ZXJZLFxuICAgICAgICAgICAgICAgIGlubmVyUmFkaXVzOiAwLFxuICAgICAgICAgICAgICAgIG91dGVyUmFkaXVzLFxuICAgICAgICAgICAgICAgIHN0YXJ0QW5nbGUsXG4gICAgICAgICAgICAgICAgZW5kQW5nbGUsXG4gICAgICAgICAgICAgICAgb3B0aW9uczogdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGksIGFyYy5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50KGFyYywgaSwgcHJvcGVydGllcywgbW9kZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY291bnRWaXNpYmxlRWxlbWVudHMoKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBsZXQgY291bnQgPSAwO1xuICAgICAgICBtZXRhLmRhdGEuZm9yRWFjaCgoZWxlbWVudCwgaW5kZXgpPT57XG4gICAgICAgICAgICBpZiAoIWlzTmFOKHRoaXMuZ2V0UGFyc2VkKGluZGV4KS5yKSAmJiB0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGluZGV4KSkge1xuICAgICAgICAgICAgICAgIGNvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY291bnQ7XG4gICAgfVxuIF9jb21wdXRlQW5nbGUoaW5kZXgsIG1vZGUsIGRlZmF1bHRBbmdsZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jaGFydC5nZXREYXRhVmlzaWJpbGl0eShpbmRleCkgPyB0b1JhZGlhbnModGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGluZGV4LCBtb2RlKS5hbmdsZSB8fCBkZWZhdWx0QW5nbGUpIDogMDtcbiAgICB9XG59XG5cbmNsYXNzIFBpZUNvbnRyb2xsZXIgZXh0ZW5kcyBEb3VnaG51dENvbnRyb2xsZXIge1xuICAgIHN0YXRpYyBpZCA9ICdwaWUnO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgY3V0b3V0OiAwLFxuICAgICAgICByb3RhdGlvbjogMCxcbiAgICAgICAgY2lyY3VtZmVyZW5jZTogMzYwLFxuICAgICAgICByYWRpdXM6ICcxMDAlJ1xuICAgIH07XG59XG5cbmNsYXNzIFJhZGFyQ29udHJvbGxlciBleHRlbmRzIERhdGFzZXRDb250cm9sbGVyIHtcbiAgICBzdGF0aWMgaWQgPSAncmFkYXInO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgZGF0YXNldEVsZW1lbnRUeXBlOiAnbGluZScsXG4gICAgICAgIGRhdGFFbGVtZW50VHlwZTogJ3BvaW50JyxcbiAgICAgICAgaW5kZXhBeGlzOiAncicsXG4gICAgICAgIHNob3dMaW5lOiB0cnVlLFxuICAgICAgICBlbGVtZW50czoge1xuICAgICAgICAgICAgbGluZToge1xuICAgICAgICAgICAgICAgIGZpbGw6ICdzdGFydCdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gc3RhdGljIG92ZXJyaWRlcyA9IHtcbiAgICAgICAgYXNwZWN0UmF0aW86IDEsXG4gICAgICAgIHNjYWxlczoge1xuICAgICAgICAgICAgcjoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdyYWRpYWxMaW5lYXInXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuIGdldExhYmVsQW5kVmFsdWUoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgdlNjYWxlID0gdGhpcy5fY2FjaGVkTWV0YS52U2NhbGU7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxhYmVsOiB2U2NhbGUuZ2V0TGFiZWxzKClbaW5kZXhdLFxuICAgICAgICAgICAgdmFsdWU6ICcnICsgdlNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkW3ZTY2FsZS5heGlzXSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcGFyc2VPYmplY3REYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICByZXR1cm4gX3BhcnNlT2JqZWN0RGF0YVJhZGlhbFNjYWxlLmJpbmQodGhpcykobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgICB9XG4gICAgdXBkYXRlKG1vZGUpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGxpbmUgPSBtZXRhLmRhdGFzZXQ7XG4gICAgICAgIGNvbnN0IHBvaW50cyA9IG1ldGEuZGF0YSB8fCBbXTtcbiAgICAgICAgY29uc3QgbGFiZWxzID0gbWV0YS5pU2NhbGUuZ2V0TGFiZWxzKCk7XG4gICAgICAgIGxpbmUucG9pbnRzID0gcG9pbnRzO1xuICAgICAgICBpZiAobW9kZSAhPT0gJ3Jlc2l6ZScpIHtcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLnJlc29sdmVEYXRhc2V0RWxlbWVudE9wdGlvbnMobW9kZSk7XG4gICAgICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93TGluZSkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuYm9yZGVyV2lkdGggPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBfbG9vcDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBfZnVsbExvb3A6IGxhYmVscy5sZW5ndGggPT09IHBvaW50cy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRWxlbWVudChsaW5lLCB1bmRlZmluZWQsIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlRWxlbWVudHMocG9pbnRzLCAwLCBwb2ludHMubGVuZ3RoLCBtb2RlKTtcbiAgICB9XG4gICAgdXBkYXRlRWxlbWVudHMocG9pbnRzLCBzdGFydCwgY291bnQsIG1vZGUpIHtcbiAgICAgICAgY29uc3Qgc2NhbGUgPSB0aGlzLl9jYWNoZWRNZXRhLnJTY2FsZTtcbiAgICAgICAgY29uc3QgcmVzZXQgPSBtb2RlID09PSAncmVzZXQnO1xuICAgICAgICBmb3IobGV0IGkgPSBzdGFydDsgaSA8IHN0YXJ0ICsgY291bnQ7IGkrKyl7XG4gICAgICAgICAgICBjb25zdCBwb2ludCA9IHBvaW50c1tpXTtcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgcG9pbnQuYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKTtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50UG9zaXRpb24gPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUoaSwgdGhpcy5nZXRQYXJzZWQoaSkucik7XG4gICAgICAgICAgICBjb25zdCB4ID0gcmVzZXQgPyBzY2FsZS54Q2VudGVyIDogcG9pbnRQb3NpdGlvbi54O1xuICAgICAgICAgICAgY29uc3QgeSA9IHJlc2V0ID8gc2NhbGUueUNlbnRlciA6IHBvaW50UG9zaXRpb24ueTtcbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgeCxcbiAgICAgICAgICAgICAgICB5LFxuICAgICAgICAgICAgICAgIGFuZ2xlOiBwb2ludFBvc2l0aW9uLmFuZ2xlLFxuICAgICAgICAgICAgICAgIHNraXA6IGlzTmFOKHgpIHx8IGlzTmFOKHkpLFxuICAgICAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQocG9pbnQsIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5jbGFzcyBTY2F0dGVyQ29udHJvbGxlciBleHRlbmRzIERhdGFzZXRDb250cm9sbGVyIHtcbiAgICBzdGF0aWMgaWQgPSAnc2NhdHRlcic7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkYXRhc2V0RWxlbWVudFR5cGU6IGZhbHNlLFxuICAgICAgICBkYXRhRWxlbWVudFR5cGU6ICdwb2ludCcsXG4gICAgICAgIHNob3dMaW5lOiBmYWxzZSxcbiAgICAgICAgZmlsbDogZmFsc2VcbiAgICB9O1xuIHN0YXRpYyBvdmVycmlkZXMgPSB7XG4gICAgICAgIGludGVyYWN0aW9uOiB7XG4gICAgICAgICAgICBtb2RlOiAncG9pbnQnXG4gICAgICAgIH0sXG4gICAgICAgIHNjYWxlczoge1xuICAgICAgICAgICAgeDoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdsaW5lYXInXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeToge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdsaW5lYXInXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuIGdldExhYmVsQW5kVmFsdWUoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGxhYmVscyA9IHRoaXMuY2hhcnQuZGF0YS5sYWJlbHMgfHwgW107XG4gICAgICAgIGNvbnN0IHsgeFNjYWxlICwgeVNjYWxlICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gdGhpcy5nZXRQYXJzZWQoaW5kZXgpO1xuICAgICAgICBjb25zdCB4ID0geFNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkLngpO1xuICAgICAgICBjb25zdCB5ID0geVNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkLnkpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGFiZWw6IGxhYmVsc1tpbmRleF0gfHwgJycsXG4gICAgICAgICAgICB2YWx1ZTogJygnICsgeCArICcsICcgKyB5ICsgJyknXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZShtb2RlKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCB7IGRhdGE6IHBvaW50cyA9IFtdICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgYW5pbWF0aW9uc0Rpc2FibGVkID0gdGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkO1xuICAgICAgICBsZXQgeyBzdGFydCAsIGNvdW50ICB9ID0gX2dldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHMobWV0YSwgcG9pbnRzLCBhbmltYXRpb25zRGlzYWJsZWQpO1xuICAgICAgICB0aGlzLl9kcmF3U3RhcnQgPSBzdGFydDtcbiAgICAgICAgdGhpcy5fZHJhd0NvdW50ID0gY291bnQ7XG4gICAgICAgIGlmIChfc2NhbGVSYW5nZXNDaGFuZ2VkKG1ldGEpKSB7XG4gICAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgICAgICBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaG93TGluZSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkRWxlbWVudHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHsgZGF0YXNldDogbGluZSAsIF9kYXRhc2V0ICB9ID0gbWV0YTtcbiAgICAgICAgICAgIGxpbmUuX2NoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgICAgIGxpbmUuX2RhdGFzZXRJbmRleCA9IHRoaXMuaW5kZXg7XG4gICAgICAgICAgICBsaW5lLl9kZWNpbWF0ZWQgPSAhIV9kYXRhc2V0Ll9kZWNpbWF0ZWQ7XG4gICAgICAgICAgICBsaW5lLnBvaW50cyA9IHBvaW50cztcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLnJlc29sdmVEYXRhc2V0RWxlbWVudE9wdGlvbnMobW9kZSk7XG4gICAgICAgICAgICBvcHRpb25zLnNlZ21lbnQgPSB0aGlzLm9wdGlvbnMuc2VnbWVudDtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRWxlbWVudChsaW5lLCB1bmRlZmluZWQsIHtcbiAgICAgICAgICAgICAgICBhbmltYXRlZDogIWFuaW1hdGlvbnNEaXNhYmxlZCxcbiAgICAgICAgICAgICAgICBvcHRpb25zXG4gICAgICAgICAgICB9LCBtb2RlKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSkge1xuICAgICAgICAgICAgZGVsZXRlIG1ldGEuZGF0YXNldDtcbiAgICAgICAgICAgIHRoaXMuZGF0YXNldEVsZW1lbnRUeXBlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50cyhwb2ludHMsIHN0YXJ0LCBjb3VudCwgbW9kZSk7XG4gICAgfVxuICAgIGFkZEVsZW1lbnRzKCkge1xuICAgICAgICBjb25zdCB7IHNob3dMaW5lICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAoIXRoaXMuZGF0YXNldEVsZW1lbnRUeXBlICYmIHNob3dMaW5lKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSA9IHRoaXMuY2hhcnQucmVnaXN0cnkuZ2V0RWxlbWVudCgnbGluZScpO1xuICAgICAgICB9XG4gICAgICAgIHN1cGVyLmFkZEVsZW1lbnRzKCk7XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKHBvaW50cywgc3RhcnQsIGNvdW50LCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IHJlc2V0ID0gbW9kZSA9PT0gJ3Jlc2V0JztcbiAgICAgICAgY29uc3QgeyBpU2NhbGUgLCB2U2NhbGUgLCBfc3RhY2tlZCAsIF9kYXRhc2V0ICB9ID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgZmlyc3RPcHRzID0gdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKHN0YXJ0LCBtb2RlKTtcbiAgICAgICAgY29uc3Qgc2hhcmVkT3B0aW9ucyA9IHRoaXMuZ2V0U2hhcmVkT3B0aW9ucyhmaXJzdE9wdHMpO1xuICAgICAgICBjb25zdCBpbmNsdWRlT3B0aW9ucyA9IHRoaXMuaW5jbHVkZU9wdGlvbnMobW9kZSwgc2hhcmVkT3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGlBeGlzID0gaVNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHZBeGlzID0gdlNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHsgc3BhbkdhcHMgLCBzZWdtZW50ICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBtYXhHYXBMZW5ndGggPSBpc051bWJlcihzcGFuR2FwcykgPyBzcGFuR2FwcyA6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgY29uc3QgZGlyZWN0VXBkYXRlID0gdGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkIHx8IHJlc2V0IHx8IG1vZGUgPT09ICdub25lJztcbiAgICAgICAgbGV0IHByZXZQYXJzZWQgPSBzdGFydCA+IDAgJiYgdGhpcy5nZXRQYXJzZWQoc3RhcnQgLSAxKTtcbiAgICAgICAgZm9yKGxldCBpID0gc3RhcnQ7IGkgPCBzdGFydCArIGNvdW50OyArK2kpe1xuICAgICAgICAgICAgY29uc3QgcG9pbnQgPSBwb2ludHNbaV07XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpKTtcbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBkaXJlY3RVcGRhdGUgPyBwb2ludCA6IHt9O1xuICAgICAgICAgICAgY29uc3QgbnVsbERhdGEgPSBpc051bGxPclVuZGVmKHBhcnNlZFt2QXhpc10pO1xuICAgICAgICAgICAgY29uc3QgaVBpeGVsID0gcHJvcGVydGllc1tpQXhpc10gPSBpU2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShwYXJzZWRbaUF4aXNdLCBpKTtcbiAgICAgICAgICAgIGNvbnN0IHZQaXhlbCA9IHByb3BlcnRpZXNbdkF4aXNdID0gcmVzZXQgfHwgbnVsbERhdGEgPyB2U2NhbGUuZ2V0QmFzZVBpeGVsKCkgOiB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShfc3RhY2tlZCA/IHRoaXMuYXBwbHlTdGFjayh2U2NhbGUsIHBhcnNlZCwgX3N0YWNrZWQpIDogcGFyc2VkW3ZBeGlzXSwgaSk7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLnNraXAgPSBpc05hTihpUGl4ZWwpIHx8IGlzTmFOKHZQaXhlbCkgfHwgbnVsbERhdGE7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLnN0b3AgPSBpID4gMCAmJiBNYXRoLmFicyhwYXJzZWRbaUF4aXNdIC0gcHJldlBhcnNlZFtpQXhpc10pID4gbWF4R2FwTGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHNlZ21lbnQpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnBhcnNlZCA9IHBhcnNlZDtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnJhdyA9IF9kYXRhc2V0LmRhdGFbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jbHVkZU9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLm9wdGlvbnMgPSBzaGFyZWRPcHRpb25zIHx8IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpLCBwb2ludC5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFkaXJlY3RVcGRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQocG9pbnQsIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJldlBhcnNlZCA9IHBhcnNlZDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZVNoYXJlZE9wdGlvbnMoc2hhcmVkT3B0aW9ucywgbW9kZSwgZmlyc3RPcHRzKTtcbiAgICB9XG4gZ2V0TWF4T3ZlcmZsb3coKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBkYXRhID0gbWV0YS5kYXRhIHx8IFtdO1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93TGluZSkge1xuICAgICAgICAgICAgbGV0IG1heCA9IDA7XG4gICAgICAgICAgICBmb3IobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKXtcbiAgICAgICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIGRhdGFbaV0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSkpIC8gMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF4ID4gMCAmJiBtYXg7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YXNldCA9IG1ldGEuZGF0YXNldDtcbiAgICAgICAgY29uc3QgYm9yZGVyID0gZGF0YXNldC5vcHRpb25zICYmIGRhdGFzZXQub3B0aW9ucy5ib3JkZXJXaWR0aCB8fCAwO1xuICAgICAgICBpZiAoIWRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gYm9yZGVyO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZpcnN0UG9pbnQgPSBkYXRhWzBdLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKDApKTtcbiAgICAgICAgY29uc3QgbGFzdFBvaW50ID0gZGF0YVtkYXRhLmxlbmd0aCAtIDFdLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGRhdGEubGVuZ3RoIC0gMSkpO1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoYm9yZGVyLCBmaXJzdFBvaW50LCBsYXN0UG9pbnQpIC8gMjtcbiAgICB9XG59XG5cbnZhciBjb250cm9sbGVycyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbl9fcHJvdG9fXzogbnVsbCxcbkJhckNvbnRyb2xsZXI6IEJhckNvbnRyb2xsZXIsXG5CdWJibGVDb250cm9sbGVyOiBCdWJibGVDb250cm9sbGVyLFxuRG91Z2hudXRDb250cm9sbGVyOiBEb3VnaG51dENvbnRyb2xsZXIsXG5MaW5lQ29udHJvbGxlcjogTGluZUNvbnRyb2xsZXIsXG5QaWVDb250cm9sbGVyOiBQaWVDb250cm9sbGVyLFxuUG9sYXJBcmVhQ29udHJvbGxlcjogUG9sYXJBcmVhQ29udHJvbGxlcixcblJhZGFyQ29udHJvbGxlcjogUmFkYXJDb250cm9sbGVyLFxuU2NhdHRlckNvbnRyb2xsZXI6IFNjYXR0ZXJDb250cm9sbGVyXG59KTtcblxuLyoqXG4gKiBAbmFtZXNwYWNlIENoYXJ0Ll9hZGFwdGVyc1xuICogQHNpbmNlIDIuOC4wXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIGFic3RyYWN0KCkge1xuICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBtZXRob2QgaXMgbm90IGltcGxlbWVudGVkOiBDaGVjayB0aGF0IGEgY29tcGxldGUgZGF0ZSBhZGFwdGVyIGlzIHByb3ZpZGVkLicpO1xufVxuLyoqXG4gKiBEYXRlIGFkYXB0ZXIgKGN1cnJlbnQgdXNlZCBieSB0aGUgdGltZSBzY2FsZSlcbiAqIEBuYW1lc3BhY2UgQ2hhcnQuX2FkYXB0ZXJzLl9kYXRlXG4gKiBAbWVtYmVyb2YgQ2hhcnQuX2FkYXB0ZXJzXG4gKiBAcHJpdmF0ZVxuICovIGNsYXNzIERhdGVBZGFwdGVyQmFzZSB7XG4gICAgLyoqXG4gICAqIE92ZXJyaWRlIGRlZmF1bHQgZGF0ZSBhZGFwdGVyIG1ldGhvZHMuXG4gICAqIEFjY2VwdHMgdHlwZSBwYXJhbWV0ZXIgdG8gZGVmaW5lIG9wdGlvbnMgdHlwZS5cbiAgICogQGV4YW1wbGVcbiAgICogQ2hhcnQuX2FkYXB0ZXJzLl9kYXRlLm92ZXJyaWRlPHtteUFkYXB0ZXJPcHRpb246IHN0cmluZ30+KHtcbiAgICogICBpbml0KCkge1xuICAgKiAgICAgY29uc29sZS5sb2codGhpcy5vcHRpb25zLm15QWRhcHRlck9wdGlvbik7XG4gICAqICAgfVxuICAgKiB9KVxuICAgKi8gc3RhdGljIG92ZXJyaWRlKG1lbWJlcnMpIHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihEYXRlQWRhcHRlckJhc2UucHJvdG90eXBlLCBtZW1iZXJzKTtcbiAgICB9XG4gICAgb3B0aW9ucztcbiAgICBjb25zdHJ1Y3RvcihvcHRpb25zKXtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgIGluaXQoKSB7fVxuICAgIGZvcm1hdHMoKSB7XG4gICAgICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICAgIH1cbiAgICBwYXJzZSgpIHtcbiAgICAgICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gICAgfVxuICAgIGZvcm1hdCgpIHtcbiAgICAgICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gICAgfVxuICAgIGFkZCgpIHtcbiAgICAgICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gICAgfVxuICAgIGRpZmYoKSB7XG4gICAgICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICAgIH1cbiAgICBzdGFydE9mKCkge1xuICAgICAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgICB9XG4gICAgZW5kT2YoKSB7XG4gICAgICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICAgIH1cbn1cbnZhciBhZGFwdGVycyA9IHtcbiAgICBfZGF0ZTogRGF0ZUFkYXB0ZXJCYXNlXG59O1xuXG5mdW5jdGlvbiBiaW5hcnlTZWFyY2gobWV0YXNldCwgYXhpcywgdmFsdWUsIGludGVyc2VjdCkge1xuICAgIGNvbnN0IHsgY29udHJvbGxlciAsIGRhdGEgLCBfc29ydGVkICB9ID0gbWV0YXNldDtcbiAgICBjb25zdCBpU2NhbGUgPSBjb250cm9sbGVyLl9jYWNoZWRNZXRhLmlTY2FsZTtcbiAgICBjb25zdCBzcGFuR2FwcyA9IG1ldGFzZXQuZGF0YXNldCA/IG1ldGFzZXQuZGF0YXNldC5vcHRpb25zID8gbWV0YXNldC5kYXRhc2V0Lm9wdGlvbnMuc3BhbkdhcHMgOiBudWxsIDogbnVsbDtcbiAgICBpZiAoaVNjYWxlICYmIGF4aXMgPT09IGlTY2FsZS5heGlzICYmIGF4aXMgIT09ICdyJyAmJiBfc29ydGVkICYmIGRhdGEubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGxvb2t1cE1ldGhvZCA9IGlTY2FsZS5fcmV2ZXJzZVBpeGVscyA/IF9ybG9va3VwQnlLZXkgOiBfbG9va3VwQnlLZXk7XG4gICAgICAgIGlmICghaW50ZXJzZWN0KSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBsb29rdXBNZXRob2QoZGF0YSwgYXhpcywgdmFsdWUpO1xuICAgICAgICAgICAgaWYgKHNwYW5HYXBzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyB2U2NhbGUgIH0gPSBjb250cm9sbGVyLl9jYWNoZWRNZXRhO1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgX3BhcnNlZCAgfSA9IG1ldGFzZXQ7XG4gICAgICAgICAgICAgICAgY29uc3QgZGlzdGFuY2VUb0RlZmluZWRMbyA9IF9wYXJzZWQuc2xpY2UoMCwgcmVzdWx0LmxvICsgMSkucmV2ZXJzZSgpLmZpbmRJbmRleCgocG9pbnQpPT4haXNOdWxsT3JVbmRlZihwb2ludFt2U2NhbGUuYXhpc10pKTtcbiAgICAgICAgICAgICAgICByZXN1bHQubG8gLT0gTWF0aC5tYXgoMCwgZGlzdGFuY2VUb0RlZmluZWRMbyk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGlzdGFuY2VUb0RlZmluZWRIaSA9IF9wYXJzZWQuc2xpY2UocmVzdWx0LmhpKS5maW5kSW5kZXgoKHBvaW50KT0+IWlzTnVsbE9yVW5kZWYocG9pbnRbdlNjYWxlLmF4aXNdKSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmhpICs9IE1hdGgubWF4KDAsIGRpc3RhbmNlVG9EZWZpbmVkSGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBlbHNlIGlmIChjb250cm9sbGVyLl9zaGFyZWRPcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCBlbCA9IGRhdGFbMF07XG4gICAgICAgICAgICBjb25zdCByYW5nZSA9IHR5cGVvZiBlbC5nZXRSYW5nZSA9PT0gJ2Z1bmN0aW9uJyAmJiBlbC5nZXRSYW5nZShheGlzKTtcbiAgICAgICAgICAgIGlmIChyYW5nZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gbG9va3VwTWV0aG9kKGRhdGEsIGF4aXMsIHZhbHVlIC0gcmFuZ2UpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVuZCA9IGxvb2t1cE1ldGhvZChkYXRhLCBheGlzLCB2YWx1ZSArIHJhbmdlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBsbzogc3RhcnQubG8sXG4gICAgICAgICAgICAgICAgICAgIGhpOiBlbmQuaGlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGxvOiAwLFxuICAgICAgICBoaTogZGF0YS5sZW5ndGggLSAxXG4gICAgfTtcbn1cbiBmdW5jdGlvbiBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCBoYW5kbGVyLCBpbnRlcnNlY3QpIHtcbiAgICBjb25zdCBtZXRhc2V0cyA9IGNoYXJ0LmdldFNvcnRlZFZpc2libGVEYXRhc2V0TWV0YXMoKTtcbiAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW2F4aXNdO1xuICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSBtZXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBjb25zdCB7IGluZGV4ICwgZGF0YSAgfSA9IG1ldGFzZXRzW2ldO1xuICAgICAgICBjb25zdCB7IGxvICwgaGkgIH0gPSBiaW5hcnlTZWFyY2gobWV0YXNldHNbaV0sIGF4aXMsIHZhbHVlLCBpbnRlcnNlY3QpO1xuICAgICAgICBmb3IobGV0IGogPSBsbzsgaiA8PSBoaTsgKytqKXtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBkYXRhW2pdO1xuICAgICAgICAgICAgaWYgKCFlbGVtZW50LnNraXApIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVyKGVsZW1lbnQsIGluZGV4LCBqKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbiBmdW5jdGlvbiBnZXREaXN0YW5jZU1ldHJpY0ZvckF4aXMoYXhpcykge1xuICAgIGNvbnN0IHVzZVggPSBheGlzLmluZGV4T2YoJ3gnKSAhPT0gLTE7XG4gICAgY29uc3QgdXNlWSA9IGF4aXMuaW5kZXhPZigneScpICE9PSAtMTtcbiAgICByZXR1cm4gZnVuY3Rpb24ocHQxLCBwdDIpIHtcbiAgICAgICAgY29uc3QgZGVsdGFYID0gdXNlWCA/IE1hdGguYWJzKHB0MS54IC0gcHQyLngpIDogMDtcbiAgICAgICAgY29uc3QgZGVsdGFZID0gdXNlWSA/IE1hdGguYWJzKHB0MS55IC0gcHQyLnkpIDogMDtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydChNYXRoLnBvdyhkZWx0YVgsIDIpICsgTWF0aC5wb3coZGVsdGFZLCAyKSk7XG4gICAgfTtcbn1cbiBmdW5jdGlvbiBnZXRJbnRlcnNlY3RJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpIHtcbiAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgIGlmICghaW5jbHVkZUludmlzaWJsZSAmJiAhY2hhcnQuaXNQb2ludEluQXJlYShwb3NpdGlvbikpIHtcbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgIH1cbiAgICBjb25zdCBldmFsdWF0aW9uRnVuYyA9IGZ1bmN0aW9uKGVsZW1lbnQsIGRhdGFzZXRJbmRleCwgaW5kZXgpIHtcbiAgICAgICAgaWYgKCFpbmNsdWRlSW52aXNpYmxlICYmICFfaXNQb2ludEluQXJlYShlbGVtZW50LCBjaGFydC5jaGFydEFyZWEsIDApKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVsZW1lbnQuaW5SYW5nZShwb3NpdGlvbi54LCBwb3NpdGlvbi55LCB1c2VGaW5hbFBvc2l0aW9uKSkge1xuICAgICAgICAgICAgaXRlbXMucHVzaCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgaW5kZXhcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCBldmFsdWF0aW9uRnVuYywgdHJ1ZSk7XG4gICAgcmV0dXJuIGl0ZW1zO1xufVxuIGZ1bmN0aW9uIGdldE5lYXJlc3RSYWRpYWxJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBsZXQgaXRlbXMgPSBbXTtcbiAgICBmdW5jdGlvbiBldmFsdWF0aW9uRnVuYyhlbGVtZW50LCBkYXRhc2V0SW5kZXgsIGluZGV4KSB7XG4gICAgICAgIGNvbnN0IHsgc3RhcnRBbmdsZSAsIGVuZEFuZ2xlICB9ID0gZWxlbWVudC5nZXRQcm9wcyhbXG4gICAgICAgICAgICAnc3RhcnRBbmdsZScsXG4gICAgICAgICAgICAnZW5kQW5nbGUnXG4gICAgICAgIF0sIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCB7IGFuZ2xlICB9ID0gZ2V0QW5nbGVGcm9tUG9pbnQoZWxlbWVudCwge1xuICAgICAgICAgICAgeDogcG9zaXRpb24ueCxcbiAgICAgICAgICAgIHk6IHBvc2l0aW9uLnlcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChfYW5nbGVCZXR3ZWVuKGFuZ2xlLCBzdGFydEFuZ2xlLCBlbmRBbmdsZSkpIHtcbiAgICAgICAgICAgIGl0ZW1zLnB1c2goe1xuICAgICAgICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgZGF0YXNldEluZGV4LFxuICAgICAgICAgICAgICAgIGluZGV4XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCBldmFsdWF0aW9uRnVuYyk7XG4gICAgcmV0dXJuIGl0ZW1zO1xufVxuIGZ1bmN0aW9uIGdldE5lYXJlc3RDYXJ0ZXNpYW5JdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIGludGVyc2VjdCwgdXNlRmluYWxQb3NpdGlvbiwgaW5jbHVkZUludmlzaWJsZSkge1xuICAgIGxldCBpdGVtcyA9IFtdO1xuICAgIGNvbnN0IGRpc3RhbmNlTWV0cmljID0gZ2V0RGlzdGFuY2VNZXRyaWNGb3JBeGlzKGF4aXMpO1xuICAgIGxldCBtaW5EaXN0YW5jZSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICBmdW5jdGlvbiBldmFsdWF0aW9uRnVuYyhlbGVtZW50LCBkYXRhc2V0SW5kZXgsIGluZGV4KSB7XG4gICAgICAgIGNvbnN0IGluUmFuZ2UgPSBlbGVtZW50LmluUmFuZ2UocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIGlmIChpbnRlcnNlY3QgJiYgIWluUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjZW50ZXIgPSBlbGVtZW50LmdldENlbnRlclBvaW50KHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCBwb2ludEluQXJlYSA9ICEhaW5jbHVkZUludmlzaWJsZSB8fCBjaGFydC5pc1BvaW50SW5BcmVhKGNlbnRlcik7XG4gICAgICAgIGlmICghcG9pbnRJbkFyZWEgJiYgIWluUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGRpc3RhbmNlTWV0cmljKHBvc2l0aW9uLCBjZW50ZXIpO1xuICAgICAgICBpZiAoZGlzdGFuY2UgPCBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgaXRlbXMgPSBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGluZGV4XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIG1pbkRpc3RhbmNlID0gZGlzdGFuY2U7XG4gICAgICAgIH0gZWxzZSBpZiAoZGlzdGFuY2UgPT09IG1pbkRpc3RhbmNlKSB7XG4gICAgICAgICAgICBpdGVtcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgIGRhdGFzZXRJbmRleCxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZXZhbHVhdGVJbnRlcmFjdGlvbkl0ZW1zKGNoYXJ0LCBheGlzLCBwb3NpdGlvbiwgZXZhbHVhdGlvbkZ1bmMpO1xuICAgIHJldHVybiBpdGVtcztcbn1cbiBmdW5jdGlvbiBnZXROZWFyZXN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBpbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpIHtcbiAgICBpZiAoIWluY2x1ZGVJbnZpc2libGUgJiYgIWNoYXJ0LmlzUG9pbnRJbkFyZWEocG9zaXRpb24pKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgcmV0dXJuIGF4aXMgPT09ICdyJyAmJiAhaW50ZXJzZWN0ID8gZ2V0TmVhcmVzdFJhZGlhbEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgdXNlRmluYWxQb3NpdGlvbikgOiBnZXROZWFyZXN0Q2FydGVzaWFuSXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBpbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpO1xufVxuIGZ1bmN0aW9uIGdldEF4aXNJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIGludGVyc2VjdCwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgIGNvbnN0IGl0ZW1zID0gW107XG4gICAgY29uc3QgcmFuZ2VNZXRob2QgPSBheGlzID09PSAneCcgPyAnaW5YUmFuZ2UnIDogJ2luWVJhbmdlJztcbiAgICBsZXQgaW50ZXJzZWN0c0l0ZW0gPSBmYWxzZTtcbiAgICBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCAoZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleCk9PntcbiAgICAgICAgaWYgKGVsZW1lbnRbcmFuZ2VNZXRob2RdICYmIGVsZW1lbnRbcmFuZ2VNZXRob2RdKHBvc2l0aW9uW2F4aXNdLCB1c2VGaW5hbFBvc2l0aW9uKSkge1xuICAgICAgICAgICAgaXRlbXMucHVzaCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgaW5kZXhcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaW50ZXJzZWN0c0l0ZW0gPSBpbnRlcnNlY3RzSXRlbSB8fCBlbGVtZW50LmluUmFuZ2UocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoaW50ZXJzZWN0ICYmICFpbnRlcnNlY3RzSXRlbSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHJldHVybiBpdGVtcztcbn1cbiB2YXIgSW50ZXJhY3Rpb24gPSB7XG4gICAgZXZhbHVhdGVJbnRlcmFjdGlvbkl0ZW1zLFxuICAgIG1vZGVzOiB7XG4gaW5kZXggKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGdldFJlbGF0aXZlUG9zaXRpb24oZSwgY2hhcnQpO1xuICAgICAgICAgICAgY29uc3QgYXhpcyA9IG9wdGlvbnMuYXhpcyB8fCAneCc7XG4gICAgICAgICAgICBjb25zdCBpbmNsdWRlSW52aXNpYmxlID0gb3B0aW9ucy5pbmNsdWRlSW52aXNpYmxlIHx8IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgaXRlbXMgPSBvcHRpb25zLmludGVyc2VjdCA/IGdldEludGVyc2VjdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgdXNlRmluYWxQb3NpdGlvbiwgaW5jbHVkZUludmlzaWJsZSkgOiBnZXROZWFyZXN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBmYWxzZSwgdXNlRmluYWxQb3NpdGlvbiwgaW5jbHVkZUludmlzaWJsZSk7XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50cyA9IFtdO1xuICAgICAgICAgICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjaGFydC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCkuZm9yRWFjaCgobWV0YSk9PntcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IGl0ZW1zWzBdLmluZGV4O1xuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBtZXRhLmRhdGFbaW5kZXhdO1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ICYmICFlbGVtZW50LnNraXApIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXNldEluZGV4OiBtZXRhLmluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgICAgIH0sXG4gZGF0YXNldCAoY2hhcnQsIGUsIG9wdGlvbnMsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gZ2V0UmVsYXRpdmVQb3NpdGlvbihlLCBjaGFydCk7XG4gICAgICAgICAgICBjb25zdCBheGlzID0gb3B0aW9ucy5heGlzIHx8ICd4eSc7XG4gICAgICAgICAgICBjb25zdCBpbmNsdWRlSW52aXNpYmxlID0gb3B0aW9ucy5pbmNsdWRlSW52aXNpYmxlIHx8IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGl0ZW1zID0gb3B0aW9ucy5pbnRlcnNlY3QgPyBnZXRJbnRlcnNlY3RJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpIDogZ2V0TmVhcmVzdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgZmFsc2UsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpO1xuICAgICAgICAgICAgaWYgKGl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhc2V0SW5kZXggPSBpdGVtc1swXS5kYXRhc2V0SW5kZXg7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkuZGF0YTtcbiAgICAgICAgICAgICAgICBpdGVtcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgKytpKXtcbiAgICAgICAgICAgICAgICAgICAgaXRlbXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBkYXRhW2ldLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXNldEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg6IGlcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgICAgICB9LFxuIHBvaW50IChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgICAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3h5JztcbiAgICAgICAgICAgIGNvbnN0IGluY2x1ZGVJbnZpc2libGUgPSBvcHRpb25zLmluY2x1ZGVJbnZpc2libGUgfHwgZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gZ2V0SW50ZXJzZWN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCB1c2VGaW5hbFBvc2l0aW9uLCBpbmNsdWRlSW52aXNpYmxlKTtcbiAgICAgICAgfSxcbiBuZWFyZXN0IChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgICAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3h5JztcbiAgICAgICAgICAgIGNvbnN0IGluY2x1ZGVJbnZpc2libGUgPSBvcHRpb25zLmluY2x1ZGVJbnZpc2libGUgfHwgZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gZ2V0TmVhcmVzdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgb3B0aW9ucy5pbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpO1xuICAgICAgICB9LFxuIHggKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGdldFJlbGF0aXZlUG9zaXRpb24oZSwgY2hhcnQpO1xuICAgICAgICAgICAgcmV0dXJuIGdldEF4aXNJdGVtcyhjaGFydCwgcG9zaXRpb24sICd4Jywgb3B0aW9ucy5pbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICB9LFxuIHkgKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGdldFJlbGF0aXZlUG9zaXRpb24oZSwgY2hhcnQpO1xuICAgICAgICAgICAgcmV0dXJuIGdldEF4aXNJdGVtcyhjaGFydCwgcG9zaXRpb24sICd5Jywgb3B0aW9ucy5pbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuY29uc3QgU1RBVElDX1BPU0lUSU9OUyA9IFtcbiAgICAnbGVmdCcsXG4gICAgJ3RvcCcsXG4gICAgJ3JpZ2h0JyxcbiAgICAnYm90dG9tJ1xuXTtcbmZ1bmN0aW9uIGZpbHRlckJ5UG9zaXRpb24oYXJyYXksIHBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIGFycmF5LmZpbHRlcigodik9PnYucG9zID09PSBwb3NpdGlvbik7XG59XG5mdW5jdGlvbiBmaWx0ZXJEeW5hbWljUG9zaXRpb25CeUF4aXMoYXJyYXksIGF4aXMpIHtcbiAgICByZXR1cm4gYXJyYXkuZmlsdGVyKCh2KT0+U1RBVElDX1BPU0lUSU9OUy5pbmRleE9mKHYucG9zKSA9PT0gLTEgJiYgdi5ib3guYXhpcyA9PT0gYXhpcyk7XG59XG5mdW5jdGlvbiBzb3J0QnlXZWlnaHQoYXJyYXksIHJldmVyc2UpIHtcbiAgICByZXR1cm4gYXJyYXkuc29ydCgoYSwgYik9PntcbiAgICAgICAgY29uc3QgdjAgPSByZXZlcnNlID8gYiA6IGE7XG4gICAgICAgIGNvbnN0IHYxID0gcmV2ZXJzZSA/IGEgOiBiO1xuICAgICAgICByZXR1cm4gdjAud2VpZ2h0ID09PSB2MS53ZWlnaHQgPyB2MC5pbmRleCAtIHYxLmluZGV4IDogdjAud2VpZ2h0IC0gdjEud2VpZ2h0O1xuICAgIH0pO1xufVxuZnVuY3Rpb24gd3JhcEJveGVzKGJveGVzKSB7XG4gICAgY29uc3QgbGF5b3V0Qm94ZXMgPSBbXTtcbiAgICBsZXQgaSwgaWxlbiwgYm94LCBwb3MsIHN0YWNrLCBzdGFja1dlaWdodDtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSAoYm94ZXMgfHwgW10pLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGJveCA9IGJveGVzW2ldO1xuICAgICAgICAoeyBwb3NpdGlvbjogcG9zICwgb3B0aW9uczogeyBzdGFjayAsIHN0YWNrV2VpZ2h0ID0xICB9ICB9ID0gYm94KTtcbiAgICAgICAgbGF5b3V0Qm94ZXMucHVzaCh7XG4gICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICAgIGJveCxcbiAgICAgICAgICAgIHBvcyxcbiAgICAgICAgICAgIGhvcml6b250YWw6IGJveC5pc0hvcml6b250YWwoKSxcbiAgICAgICAgICAgIHdlaWdodDogYm94LndlaWdodCxcbiAgICAgICAgICAgIHN0YWNrOiBzdGFjayAmJiBwb3MgKyBzdGFjayxcbiAgICAgICAgICAgIHN0YWNrV2VpZ2h0XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gbGF5b3V0Qm94ZXM7XG59XG5mdW5jdGlvbiBidWlsZFN0YWNrcyhsYXlvdXRzKSB7XG4gICAgY29uc3Qgc3RhY2tzID0ge307XG4gICAgZm9yIChjb25zdCB3cmFwIG9mIGxheW91dHMpe1xuICAgICAgICBjb25zdCB7IHN0YWNrICwgcG9zICwgc3RhY2tXZWlnaHQgIH0gPSB3cmFwO1xuICAgICAgICBpZiAoIXN0YWNrIHx8ICFTVEFUSUNfUE9TSVRJT05TLmluY2x1ZGVzKHBvcykpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IF9zdGFjayA9IHN0YWNrc1tzdGFja10gfHwgKHN0YWNrc1tzdGFja10gPSB7XG4gICAgICAgICAgICBjb3VudDogMCxcbiAgICAgICAgICAgIHBsYWNlZDogMCxcbiAgICAgICAgICAgIHdlaWdodDogMCxcbiAgICAgICAgICAgIHNpemU6IDBcbiAgICAgICAgfSk7XG4gICAgICAgIF9zdGFjay5jb3VudCsrO1xuICAgICAgICBfc3RhY2sud2VpZ2h0ICs9IHN0YWNrV2VpZ2h0O1xuICAgIH1cbiAgICByZXR1cm4gc3RhY2tzO1xufVxuIGZ1bmN0aW9uIHNldExheW91dERpbXMobGF5b3V0cywgcGFyYW1zKSB7XG4gICAgY29uc3Qgc3RhY2tzID0gYnVpbGRTdGFja3MobGF5b3V0cyk7XG4gICAgY29uc3QgeyB2Qm94TWF4V2lkdGggLCBoQm94TWF4SGVpZ2h0ICB9ID0gcGFyYW1zO1xuICAgIGxldCBpLCBpbGVuLCBsYXlvdXQ7XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gbGF5b3V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBsYXlvdXQgPSBsYXlvdXRzW2ldO1xuICAgICAgICBjb25zdCB7IGZ1bGxTaXplICB9ID0gbGF5b3V0LmJveDtcbiAgICAgICAgY29uc3Qgc3RhY2sgPSBzdGFja3NbbGF5b3V0LnN0YWNrXTtcbiAgICAgICAgY29uc3QgZmFjdG9yID0gc3RhY2sgJiYgbGF5b3V0LnN0YWNrV2VpZ2h0IC8gc3RhY2sud2VpZ2h0O1xuICAgICAgICBpZiAobGF5b3V0Lmhvcml6b250YWwpIHtcbiAgICAgICAgICAgIGxheW91dC53aWR0aCA9IGZhY3RvciA/IGZhY3RvciAqIHZCb3hNYXhXaWR0aCA6IGZ1bGxTaXplICYmIHBhcmFtcy5hdmFpbGFibGVXaWR0aDtcbiAgICAgICAgICAgIGxheW91dC5oZWlnaHQgPSBoQm94TWF4SGVpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGF5b3V0LndpZHRoID0gdkJveE1heFdpZHRoO1xuICAgICAgICAgICAgbGF5b3V0LmhlaWdodCA9IGZhY3RvciA/IGZhY3RvciAqIGhCb3hNYXhIZWlnaHQgOiBmdWxsU2l6ZSAmJiBwYXJhbXMuYXZhaWxhYmxlSGVpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzdGFja3M7XG59XG5mdW5jdGlvbiBidWlsZExheW91dEJveGVzKGJveGVzKSB7XG4gICAgY29uc3QgbGF5b3V0Qm94ZXMgPSB3cmFwQm94ZXMoYm94ZXMpO1xuICAgIGNvbnN0IGZ1bGxTaXplID0gc29ydEJ5V2VpZ2h0KGxheW91dEJveGVzLmZpbHRlcigod3JhcCk9PndyYXAuYm94LmZ1bGxTaXplKSwgdHJ1ZSk7XG4gICAgY29uc3QgbGVmdCA9IHNvcnRCeVdlaWdodChmaWx0ZXJCeVBvc2l0aW9uKGxheW91dEJveGVzLCAnbGVmdCcpLCB0cnVlKTtcbiAgICBjb25zdCByaWdodCA9IHNvcnRCeVdlaWdodChmaWx0ZXJCeVBvc2l0aW9uKGxheW91dEJveGVzLCAncmlnaHQnKSk7XG4gICAgY29uc3QgdG9wID0gc29ydEJ5V2VpZ2h0KGZpbHRlckJ5UG9zaXRpb24obGF5b3V0Qm94ZXMsICd0b3AnKSwgdHJ1ZSk7XG4gICAgY29uc3QgYm90dG9tID0gc29ydEJ5V2VpZ2h0KGZpbHRlckJ5UG9zaXRpb24obGF5b3V0Qm94ZXMsICdib3R0b20nKSk7XG4gICAgY29uc3QgY2VudGVySG9yaXpvbnRhbCA9IGZpbHRlckR5bmFtaWNQb3NpdGlvbkJ5QXhpcyhsYXlvdXRCb3hlcywgJ3gnKTtcbiAgICBjb25zdCBjZW50ZXJWZXJ0aWNhbCA9IGZpbHRlckR5bmFtaWNQb3NpdGlvbkJ5QXhpcyhsYXlvdXRCb3hlcywgJ3knKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBmdWxsU2l6ZSxcbiAgICAgICAgbGVmdEFuZFRvcDogbGVmdC5jb25jYXQodG9wKSxcbiAgICAgICAgcmlnaHRBbmRCb3R0b206IHJpZ2h0LmNvbmNhdChjZW50ZXJWZXJ0aWNhbCkuY29uY2F0KGJvdHRvbSkuY29uY2F0KGNlbnRlckhvcml6b250YWwpLFxuICAgICAgICBjaGFydEFyZWE6IGZpbHRlckJ5UG9zaXRpb24obGF5b3V0Qm94ZXMsICdjaGFydEFyZWEnKSxcbiAgICAgICAgdmVydGljYWw6IGxlZnQuY29uY2F0KHJpZ2h0KS5jb25jYXQoY2VudGVyVmVydGljYWwpLFxuICAgICAgICBob3Jpem9udGFsOiB0b3AuY29uY2F0KGJvdHRvbSkuY29uY2F0KGNlbnRlckhvcml6b250YWwpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldENvbWJpbmVkTWF4KG1heFBhZGRpbmcsIGNoYXJ0QXJlYSwgYSwgYikge1xuICAgIHJldHVybiBNYXRoLm1heChtYXhQYWRkaW5nW2FdLCBjaGFydEFyZWFbYV0pICsgTWF0aC5tYXgobWF4UGFkZGluZ1tiXSwgY2hhcnRBcmVhW2JdKTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZU1heFBhZGRpbmcobWF4UGFkZGluZywgYm94UGFkZGluZykge1xuICAgIG1heFBhZGRpbmcudG9wID0gTWF0aC5tYXgobWF4UGFkZGluZy50b3AsIGJveFBhZGRpbmcudG9wKTtcbiAgICBtYXhQYWRkaW5nLmxlZnQgPSBNYXRoLm1heChtYXhQYWRkaW5nLmxlZnQsIGJveFBhZGRpbmcubGVmdCk7XG4gICAgbWF4UGFkZGluZy5ib3R0b20gPSBNYXRoLm1heChtYXhQYWRkaW5nLmJvdHRvbSwgYm94UGFkZGluZy5ib3R0b20pO1xuICAgIG1heFBhZGRpbmcucmlnaHQgPSBNYXRoLm1heChtYXhQYWRkaW5nLnJpZ2h0LCBib3hQYWRkaW5nLnJpZ2h0KTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZURpbXMoY2hhcnRBcmVhLCBwYXJhbXMsIGxheW91dCwgc3RhY2tzKSB7XG4gICAgY29uc3QgeyBwb3MgLCBib3ggIH0gPSBsYXlvdXQ7XG4gICAgY29uc3QgbWF4UGFkZGluZyA9IGNoYXJ0QXJlYS5tYXhQYWRkaW5nO1xuICAgIGlmICghaXNPYmplY3QocG9zKSkge1xuICAgICAgICBpZiAobGF5b3V0LnNpemUpIHtcbiAgICAgICAgICAgIGNoYXJ0QXJlYVtwb3NdIC09IGxheW91dC5zaXplO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0YWNrID0gc3RhY2tzW2xheW91dC5zdGFja10gfHwge1xuICAgICAgICAgICAgc2l6ZTogMCxcbiAgICAgICAgICAgIGNvdW50OiAxXG4gICAgICAgIH07XG4gICAgICAgIHN0YWNrLnNpemUgPSBNYXRoLm1heChzdGFjay5zaXplLCBsYXlvdXQuaG9yaXpvbnRhbCA/IGJveC5oZWlnaHQgOiBib3gud2lkdGgpO1xuICAgICAgICBsYXlvdXQuc2l6ZSA9IHN0YWNrLnNpemUgLyBzdGFjay5jb3VudDtcbiAgICAgICAgY2hhcnRBcmVhW3Bvc10gKz0gbGF5b3V0LnNpemU7XG4gICAgfVxuICAgIGlmIChib3guZ2V0UGFkZGluZykge1xuICAgICAgICB1cGRhdGVNYXhQYWRkaW5nKG1heFBhZGRpbmcsIGJveC5nZXRQYWRkaW5nKCkpO1xuICAgIH1cbiAgICBjb25zdCBuZXdXaWR0aCA9IE1hdGgubWF4KDAsIHBhcmFtcy5vdXRlcldpZHRoIC0gZ2V0Q29tYmluZWRNYXgobWF4UGFkZGluZywgY2hhcnRBcmVhLCAnbGVmdCcsICdyaWdodCcpKTtcbiAgICBjb25zdCBuZXdIZWlnaHQgPSBNYXRoLm1heCgwLCBwYXJhbXMub3V0ZXJIZWlnaHQgLSBnZXRDb21iaW5lZE1heChtYXhQYWRkaW5nLCBjaGFydEFyZWEsICd0b3AnLCAnYm90dG9tJykpO1xuICAgIGNvbnN0IHdpZHRoQ2hhbmdlZCA9IG5ld1dpZHRoICE9PSBjaGFydEFyZWEudztcbiAgICBjb25zdCBoZWlnaHRDaGFuZ2VkID0gbmV3SGVpZ2h0ICE9PSBjaGFydEFyZWEuaDtcbiAgICBjaGFydEFyZWEudyA9IG5ld1dpZHRoO1xuICAgIGNoYXJ0QXJlYS5oID0gbmV3SGVpZ2h0O1xuICAgIHJldHVybiBsYXlvdXQuaG9yaXpvbnRhbCA/IHtcbiAgICAgICAgc2FtZTogd2lkdGhDaGFuZ2VkLFxuICAgICAgICBvdGhlcjogaGVpZ2h0Q2hhbmdlZFxuICAgIH0gOiB7XG4gICAgICAgIHNhbWU6IGhlaWdodENoYW5nZWQsXG4gICAgICAgIG90aGVyOiB3aWR0aENoYW5nZWRcbiAgICB9O1xufVxuZnVuY3Rpb24gaGFuZGxlTWF4UGFkZGluZyhjaGFydEFyZWEpIHtcbiAgICBjb25zdCBtYXhQYWRkaW5nID0gY2hhcnRBcmVhLm1heFBhZGRpbmc7XG4gICAgZnVuY3Rpb24gdXBkYXRlUG9zKHBvcykge1xuICAgICAgICBjb25zdCBjaGFuZ2UgPSBNYXRoLm1heChtYXhQYWRkaW5nW3Bvc10gLSBjaGFydEFyZWFbcG9zXSwgMCk7XG4gICAgICAgIGNoYXJ0QXJlYVtwb3NdICs9IGNoYW5nZTtcbiAgICAgICAgcmV0dXJuIGNoYW5nZTtcbiAgICB9XG4gICAgY2hhcnRBcmVhLnkgKz0gdXBkYXRlUG9zKCd0b3AnKTtcbiAgICBjaGFydEFyZWEueCArPSB1cGRhdGVQb3MoJ2xlZnQnKTtcbiAgICB1cGRhdGVQb3MoJ3JpZ2h0Jyk7XG4gICAgdXBkYXRlUG9zKCdib3R0b20nKTtcbn1cbmZ1bmN0aW9uIGdldE1hcmdpbnMoaG9yaXpvbnRhbCwgY2hhcnRBcmVhKSB7XG4gICAgY29uc3QgbWF4UGFkZGluZyA9IGNoYXJ0QXJlYS5tYXhQYWRkaW5nO1xuICAgIGZ1bmN0aW9uIG1hcmdpbkZvclBvc2l0aW9ucyhwb3NpdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbWFyZ2luID0ge1xuICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIHJpZ2h0OiAwLFxuICAgICAgICAgICAgYm90dG9tOiAwXG4gICAgICAgIH07XG4gICAgICAgIHBvc2l0aW9ucy5mb3JFYWNoKChwb3MpPT57XG4gICAgICAgICAgICBtYXJnaW5bcG9zXSA9IE1hdGgubWF4KGNoYXJ0QXJlYVtwb3NdLCBtYXhQYWRkaW5nW3Bvc10pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG1hcmdpbjtcbiAgICB9XG4gICAgcmV0dXJuIGhvcml6b250YWwgPyBtYXJnaW5Gb3JQb3NpdGlvbnMoW1xuICAgICAgICAnbGVmdCcsXG4gICAgICAgICdyaWdodCdcbiAgICBdKSA6IG1hcmdpbkZvclBvc2l0aW9ucyhbXG4gICAgICAgICd0b3AnLFxuICAgICAgICAnYm90dG9tJ1xuICAgIF0pO1xufVxuZnVuY3Rpb24gZml0Qm94ZXMoYm94ZXMsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpIHtcbiAgICBjb25zdCByZWZpdEJveGVzID0gW107XG4gICAgbGV0IGksIGlsZW4sIGxheW91dCwgYm94LCByZWZpdCwgY2hhbmdlZDtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBib3hlcy5sZW5ndGgsIHJlZml0ID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGxheW91dCA9IGJveGVzW2ldO1xuICAgICAgICBib3ggPSBsYXlvdXQuYm94O1xuICAgICAgICBib3gudXBkYXRlKGxheW91dC53aWR0aCB8fCBjaGFydEFyZWEudywgbGF5b3V0LmhlaWdodCB8fCBjaGFydEFyZWEuaCwgZ2V0TWFyZ2lucyhsYXlvdXQuaG9yaXpvbnRhbCwgY2hhcnRBcmVhKSk7XG4gICAgICAgIGNvbnN0IHsgc2FtZSAsIG90aGVyICB9ID0gdXBkYXRlRGltcyhjaGFydEFyZWEsIHBhcmFtcywgbGF5b3V0LCBzdGFja3MpO1xuICAgICAgICByZWZpdCB8PSBzYW1lICYmIHJlZml0Qm94ZXMubGVuZ3RoO1xuICAgICAgICBjaGFuZ2VkID0gY2hhbmdlZCB8fCBvdGhlcjtcbiAgICAgICAgaWYgKCFib3guZnVsbFNpemUpIHtcbiAgICAgICAgICAgIHJlZml0Qm94ZXMucHVzaChsYXlvdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWZpdCAmJiBmaXRCb3hlcyhyZWZpdEJveGVzLCBjaGFydEFyZWEsIHBhcmFtcywgc3RhY2tzKSB8fCBjaGFuZ2VkO1xufVxuZnVuY3Rpb24gc2V0Qm94RGltcyhib3gsIGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCkge1xuICAgIGJveC50b3AgPSB0b3A7XG4gICAgYm94LmxlZnQgPSBsZWZ0O1xuICAgIGJveC5yaWdodCA9IGxlZnQgKyB3aWR0aDtcbiAgICBib3guYm90dG9tID0gdG9wICsgaGVpZ2h0O1xuICAgIGJveC53aWR0aCA9IHdpZHRoO1xuICAgIGJveC5oZWlnaHQgPSBoZWlnaHQ7XG59XG5mdW5jdGlvbiBwbGFjZUJveGVzKGJveGVzLCBjaGFydEFyZWEsIHBhcmFtcywgc3RhY2tzKSB7XG4gICAgY29uc3QgdXNlclBhZGRpbmcgPSBwYXJhbXMucGFkZGluZztcbiAgICBsZXQgeyB4ICwgeSAgfSA9IGNoYXJ0QXJlYTtcbiAgICBmb3IgKGNvbnN0IGxheW91dCBvZiBib3hlcyl7XG4gICAgICAgIGNvbnN0IGJveCA9IGxheW91dC5ib3g7XG4gICAgICAgIGNvbnN0IHN0YWNrID0gc3RhY2tzW2xheW91dC5zdGFja10gfHwge1xuICAgICAgICAgICAgY291bnQ6IDEsXG4gICAgICAgICAgICBwbGFjZWQ6IDAsXG4gICAgICAgICAgICB3ZWlnaHQ6IDFcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd2VpZ2h0ID0gbGF5b3V0LnN0YWNrV2VpZ2h0IC8gc3RhY2sud2VpZ2h0IHx8IDE7XG4gICAgICAgIGlmIChsYXlvdXQuaG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBjaGFydEFyZWEudyAqIHdlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHN0YWNrLnNpemUgfHwgYm94LmhlaWdodDtcbiAgICAgICAgICAgIGlmIChkZWZpbmVkKHN0YWNrLnN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHkgPSBzdGFjay5zdGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChib3guZnVsbFNpemUpIHtcbiAgICAgICAgICAgICAgICBzZXRCb3hEaW1zKGJveCwgdXNlclBhZGRpbmcubGVmdCwgeSwgcGFyYW1zLm91dGVyV2lkdGggLSB1c2VyUGFkZGluZy5yaWdodCAtIHVzZXJQYWRkaW5nLmxlZnQsIGhlaWdodCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldEJveERpbXMoYm94LCBjaGFydEFyZWEubGVmdCArIHN0YWNrLnBsYWNlZCwgeSwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdGFjay5zdGFydCA9IHk7XG4gICAgICAgICAgICBzdGFjay5wbGFjZWQgKz0gd2lkdGg7XG4gICAgICAgICAgICB5ID0gYm94LmJvdHRvbTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGNoYXJ0QXJlYS5oICogd2VpZ2h0O1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBzdGFjay5zaXplIHx8IGJveC53aWR0aDtcbiAgICAgICAgICAgIGlmIChkZWZpbmVkKHN0YWNrLnN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHggPSBzdGFjay5zdGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChib3guZnVsbFNpemUpIHtcbiAgICAgICAgICAgICAgICBzZXRCb3hEaW1zKGJveCwgeCwgdXNlclBhZGRpbmcudG9wLCB3aWR0aCwgcGFyYW1zLm91dGVySGVpZ2h0IC0gdXNlclBhZGRpbmcuYm90dG9tIC0gdXNlclBhZGRpbmcudG9wKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0Qm94RGltcyhib3gsIHgsIGNoYXJ0QXJlYS50b3AgKyBzdGFjay5wbGFjZWQsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RhY2suc3RhcnQgPSB4O1xuICAgICAgICAgICAgc3RhY2sucGxhY2VkICs9IGhlaWdodDtcbiAgICAgICAgICAgIHggPSBib3gucmlnaHQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY2hhcnRBcmVhLnggPSB4O1xuICAgIGNoYXJ0QXJlYS55ID0geTtcbn1cbnZhciBsYXlvdXRzID0ge1xuIGFkZEJveCAoY2hhcnQsIGl0ZW0pIHtcbiAgICAgICAgaWYgKCFjaGFydC5ib3hlcykge1xuICAgICAgICAgICAgY2hhcnQuYm94ZXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpdGVtLmZ1bGxTaXplID0gaXRlbS5mdWxsU2l6ZSB8fCBmYWxzZTtcbiAgICAgICAgaXRlbS5wb3NpdGlvbiA9IGl0ZW0ucG9zaXRpb24gfHwgJ3RvcCc7XG4gICAgICAgIGl0ZW0ud2VpZ2h0ID0gaXRlbS53ZWlnaHQgfHwgMDtcbiAgICAgICAgaXRlbS5fbGF5ZXJzID0gaXRlbS5fbGF5ZXJzIHx8IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHo6IDAsXG4gICAgICAgICAgICAgICAgICAgIGRyYXcgKGNoYXJ0QXJlYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS5kcmF3KGNoYXJ0QXJlYSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdO1xuICAgICAgICB9O1xuICAgICAgICBjaGFydC5ib3hlcy5wdXNoKGl0ZW0pO1xuICAgIH0sXG4gcmVtb3ZlQm94IChjaGFydCwgbGF5b3V0SXRlbSkge1xuICAgICAgICBjb25zdCBpbmRleCA9IGNoYXJ0LmJveGVzID8gY2hhcnQuYm94ZXMuaW5kZXhPZihsYXlvdXRJdGVtKSA6IC0xO1xuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICBjaGFydC5ib3hlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgfSxcbiBjb25maWd1cmUgKGNoYXJ0LCBpdGVtLCBvcHRpb25zKSB7XG4gICAgICAgIGl0ZW0uZnVsbFNpemUgPSBvcHRpb25zLmZ1bGxTaXplO1xuICAgICAgICBpdGVtLnBvc2l0aW9uID0gb3B0aW9ucy5wb3NpdGlvbjtcbiAgICAgICAgaXRlbS53ZWlnaHQgPSBvcHRpb25zLndlaWdodDtcbiAgICB9LFxuIHVwZGF0ZSAoY2hhcnQsIHdpZHRoLCBoZWlnaHQsIG1pblBhZGRpbmcpIHtcbiAgICAgICAgaWYgKCFjaGFydCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcoY2hhcnQub3B0aW9ucy5sYXlvdXQucGFkZGluZyk7XG4gICAgICAgIGNvbnN0IGF2YWlsYWJsZVdpZHRoID0gTWF0aC5tYXgod2lkdGggLSBwYWRkaW5nLndpZHRoLCAwKTtcbiAgICAgICAgY29uc3QgYXZhaWxhYmxlSGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0IC0gcGFkZGluZy5oZWlnaHQsIDApO1xuICAgICAgICBjb25zdCBib3hlcyA9IGJ1aWxkTGF5b3V0Qm94ZXMoY2hhcnQuYm94ZXMpO1xuICAgICAgICBjb25zdCB2ZXJ0aWNhbEJveGVzID0gYm94ZXMudmVydGljYWw7XG4gICAgICAgIGNvbnN0IGhvcml6b250YWxCb3hlcyA9IGJveGVzLmhvcml6b250YWw7XG4gICAgICAgIGVhY2goY2hhcnQuYm94ZXMsIChib3gpPT57XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJveC5iZWZvcmVMYXlvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBib3guYmVmb3JlTGF5b3V0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB2aXNpYmxlVmVydGljYWxCb3hDb3VudCA9IHZlcnRpY2FsQm94ZXMucmVkdWNlKCh0b3RhbCwgd3JhcCk9PndyYXAuYm94Lm9wdGlvbnMgJiYgd3JhcC5ib3gub3B0aW9ucy5kaXNwbGF5ID09PSBmYWxzZSA/IHRvdGFsIDogdG90YWwgKyAxLCAwKSB8fCAxO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgICAgIG91dGVyV2lkdGg6IHdpZHRoLFxuICAgICAgICAgICAgb3V0ZXJIZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIHBhZGRpbmcsXG4gICAgICAgICAgICBhdmFpbGFibGVXaWR0aCxcbiAgICAgICAgICAgIGF2YWlsYWJsZUhlaWdodCxcbiAgICAgICAgICAgIHZCb3hNYXhXaWR0aDogYXZhaWxhYmxlV2lkdGggLyAyIC8gdmlzaWJsZVZlcnRpY2FsQm94Q291bnQsXG4gICAgICAgICAgICBoQm94TWF4SGVpZ2h0OiBhdmFpbGFibGVIZWlnaHQgLyAyXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBtYXhQYWRkaW5nID0gT2JqZWN0LmFzc2lnbih7fSwgcGFkZGluZyk7XG4gICAgICAgIHVwZGF0ZU1heFBhZGRpbmcobWF4UGFkZGluZywgdG9QYWRkaW5nKG1pblBhZGRpbmcpKTtcbiAgICAgICAgY29uc3QgY2hhcnRBcmVhID0gT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICBtYXhQYWRkaW5nLFxuICAgICAgICAgICAgdzogYXZhaWxhYmxlV2lkdGgsXG4gICAgICAgICAgICBoOiBhdmFpbGFibGVIZWlnaHQsXG4gICAgICAgICAgICB4OiBwYWRkaW5nLmxlZnQsXG4gICAgICAgICAgICB5OiBwYWRkaW5nLnRvcFxuICAgICAgICB9LCBwYWRkaW5nKTtcbiAgICAgICAgY29uc3Qgc3RhY2tzID0gc2V0TGF5b3V0RGltcyh2ZXJ0aWNhbEJveGVzLmNvbmNhdChob3Jpem9udGFsQm94ZXMpLCBwYXJhbXMpO1xuICAgICAgICBmaXRCb3hlcyhib3hlcy5mdWxsU2l6ZSwgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcyk7XG4gICAgICAgIGZpdEJveGVzKHZlcnRpY2FsQm94ZXMsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgICAgICBpZiAoZml0Qm94ZXMoaG9yaXpvbnRhbEJveGVzLCBjaGFydEFyZWEsIHBhcmFtcywgc3RhY2tzKSkge1xuICAgICAgICAgICAgZml0Qm94ZXModmVydGljYWxCb3hlcywgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcyk7XG4gICAgICAgIH1cbiAgICAgICAgaGFuZGxlTWF4UGFkZGluZyhjaGFydEFyZWEpO1xuICAgICAgICBwbGFjZUJveGVzKGJveGVzLmxlZnRBbmRUb3AsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgICAgICBjaGFydEFyZWEueCArPSBjaGFydEFyZWEudztcbiAgICAgICAgY2hhcnRBcmVhLnkgKz0gY2hhcnRBcmVhLmg7XG4gICAgICAgIHBsYWNlQm94ZXMoYm94ZXMucmlnaHRBbmRCb3R0b20sIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgICAgICBjaGFydC5jaGFydEFyZWEgPSB7XG4gICAgICAgICAgICBsZWZ0OiBjaGFydEFyZWEubGVmdCxcbiAgICAgICAgICAgIHRvcDogY2hhcnRBcmVhLnRvcCxcbiAgICAgICAgICAgIHJpZ2h0OiBjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS53LFxuICAgICAgICAgICAgYm90dG9tOiBjaGFydEFyZWEudG9wICsgY2hhcnRBcmVhLmgsXG4gICAgICAgICAgICBoZWlnaHQ6IGNoYXJ0QXJlYS5oLFxuICAgICAgICAgICAgd2lkdGg6IGNoYXJ0QXJlYS53XG4gICAgICAgIH07XG4gICAgICAgIGVhY2goYm94ZXMuY2hhcnRBcmVhLCAobGF5b3V0KT0+e1xuICAgICAgICAgICAgY29uc3QgYm94ID0gbGF5b3V0LmJveDtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oYm94LCBjaGFydC5jaGFydEFyZWEpO1xuICAgICAgICAgICAgYm94LnVwZGF0ZShjaGFydEFyZWEudywgY2hhcnRBcmVhLmgsIHtcbiAgICAgICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgICAgICByaWdodDogMCxcbiAgICAgICAgICAgICAgICBib3R0b206IDBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG5jbGFzcyBCYXNlUGxhdGZvcm0ge1xuIGFjcXVpcmVDb250ZXh0KGNhbnZhcywgYXNwZWN0UmF0aW8pIHt9XG4gcmVsZWFzZUNvbnRleHQoY29udGV4dCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuIGFkZEV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7fVxuIHJlbW92ZUV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7fVxuIGdldERldmljZVBpeGVsUmF0aW8oKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cbiBnZXRNYXhpbXVtU2l6ZShlbGVtZW50LCB3aWR0aCwgaGVpZ2h0LCBhc3BlY3RSYXRpbykge1xuICAgICAgICB3aWR0aCA9IE1hdGgubWF4KDAsIHdpZHRoIHx8IGVsZW1lbnQud2lkdGgpO1xuICAgICAgICBoZWlnaHQgPSBoZWlnaHQgfHwgZWxlbWVudC5oZWlnaHQ7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogTWF0aC5tYXgoMCwgYXNwZWN0UmF0aW8gPyBNYXRoLmZsb29yKHdpZHRoIC8gYXNwZWN0UmF0aW8pIDogaGVpZ2h0KVxuICAgICAgICB9O1xuICAgIH1cbiBpc0F0dGFjaGVkKGNhbnZhcykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gdXBkYXRlQ29uZmlnKGNvbmZpZykge1xuICAgIH1cbn1cblxuY2xhc3MgQmFzaWNQbGF0Zm9ybSBleHRlbmRzIEJhc2VQbGF0Zm9ybSB7XG4gICAgYWNxdWlyZUNvbnRleHQoaXRlbSkge1xuICAgICAgICByZXR1cm4gaXRlbSAmJiBpdGVtLmdldENvbnRleHQgJiYgaXRlbS5nZXRDb250ZXh0KCcyZCcpIHx8IG51bGw7XG4gICAgfVxuICAgIHVwZGF0ZUNvbmZpZyhjb25maWcpIHtcbiAgICAgICAgY29uZmlnLm9wdGlvbnMuYW5pbWF0aW9uID0gZmFsc2U7XG4gICAgfVxufVxuXG5jb25zdCBFWFBBTkRPX0tFWSA9ICckY2hhcnRqcyc7XG4gY29uc3QgRVZFTlRfVFlQRVMgPSB7XG4gICAgdG91Y2hzdGFydDogJ21vdXNlZG93bicsXG4gICAgdG91Y2htb3ZlOiAnbW91c2Vtb3ZlJyxcbiAgICB0b3VjaGVuZDogJ21vdXNldXAnLFxuICAgIHBvaW50ZXJlbnRlcjogJ21vdXNlZW50ZXInLFxuICAgIHBvaW50ZXJkb3duOiAnbW91c2Vkb3duJyxcbiAgICBwb2ludGVybW92ZTogJ21vdXNlbW92ZScsXG4gICAgcG9pbnRlcnVwOiAnbW91c2V1cCcsXG4gICAgcG9pbnRlcmxlYXZlOiAnbW91c2VvdXQnLFxuICAgIHBvaW50ZXJvdXQ6ICdtb3VzZW91dCdcbn07XG5jb25zdCBpc051bGxPckVtcHR5ID0gKHZhbHVlKT0+dmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnO1xuIGZ1bmN0aW9uIGluaXRDYW52YXMoY2FudmFzLCBhc3BlY3RSYXRpbykge1xuICAgIGNvbnN0IHN0eWxlID0gY2FudmFzLnN0eWxlO1xuICAgIGNvbnN0IHJlbmRlckhlaWdodCA9IGNhbnZhcy5nZXRBdHRyaWJ1dGUoJ2hlaWdodCcpO1xuICAgIGNvbnN0IHJlbmRlcldpZHRoID0gY2FudmFzLmdldEF0dHJpYnV0ZSgnd2lkdGgnKTtcbiAgICBjYW52YXNbRVhQQU5ET19LRVldID0ge1xuICAgICAgICBpbml0aWFsOiB7XG4gICAgICAgICAgICBoZWlnaHQ6IHJlbmRlckhlaWdodCxcbiAgICAgICAgICAgIHdpZHRoOiByZW5kZXJXaWR0aCxcbiAgICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgZGlzcGxheTogc3R5bGUuZGlzcGxheSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHN0eWxlLmhlaWdodCxcbiAgICAgICAgICAgICAgICB3aWR0aDogc3R5bGUud2lkdGhcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgc3R5bGUuZGlzcGxheSA9IHN0eWxlLmRpc3BsYXkgfHwgJ2Jsb2NrJztcbiAgICBzdHlsZS5ib3hTaXppbmcgPSBzdHlsZS5ib3hTaXppbmcgfHwgJ2JvcmRlci1ib3gnO1xuICAgIGlmIChpc051bGxPckVtcHR5KHJlbmRlcldpZHRoKSkge1xuICAgICAgICBjb25zdCBkaXNwbGF5V2lkdGggPSByZWFkVXNlZFNpemUoY2FudmFzLCAnd2lkdGgnKTtcbiAgICAgICAgaWYgKGRpc3BsYXlXaWR0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjYW52YXMud2lkdGggPSBkaXNwbGF5V2lkdGg7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzTnVsbE9yRW1wdHkocmVuZGVySGVpZ2h0KSkge1xuICAgICAgICBpZiAoY2FudmFzLnN0eWxlLmhlaWdodCA9PT0gJycpIHtcbiAgICAgICAgICAgIGNhbnZhcy5oZWlnaHQgPSBjYW52YXMud2lkdGggLyAoYXNwZWN0UmF0aW8gfHwgMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBkaXNwbGF5SGVpZ2h0ID0gcmVhZFVzZWRTaXplKGNhbnZhcywgJ2hlaWdodCcpO1xuICAgICAgICAgICAgaWYgKGRpc3BsYXlIZWlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNhbnZhcy5oZWlnaHQgPSBkaXNwbGF5SGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjYW52YXM7XG59XG5jb25zdCBldmVudExpc3RlbmVyT3B0aW9ucyA9IHN1cHBvcnRzRXZlbnRMaXN0ZW5lck9wdGlvbnMgPyB7XG4gICAgcGFzc2l2ZTogdHJ1ZVxufSA6IGZhbHNlO1xuZnVuY3Rpb24gYWRkTGlzdGVuZXIobm9kZSwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICBpZiAobm9kZSkge1xuICAgICAgICBub2RlLmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIsIGV2ZW50TGlzdGVuZXJPcHRpb25zKTtcbiAgICB9XG59XG5mdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICBpZiAoY2hhcnQgJiYgY2hhcnQuY2FudmFzKSB7XG4gICAgICAgIGNoYXJ0LmNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBldmVudExpc3RlbmVyT3B0aW9ucyk7XG4gICAgfVxufVxuZnVuY3Rpb24gZnJvbU5hdGl2ZUV2ZW50KGV2ZW50LCBjaGFydCkge1xuICAgIGNvbnN0IHR5cGUgPSBFVkVOVF9UWVBFU1tldmVudC50eXBlXSB8fCBldmVudC50eXBlO1xuICAgIGNvbnN0IHsgeCAsIHkgIH0gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGV2ZW50LCBjaGFydCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZSxcbiAgICAgICAgY2hhcnQsXG4gICAgICAgIG5hdGl2ZTogZXZlbnQsXG4gICAgICAgIHg6IHggIT09IHVuZGVmaW5lZCA/IHggOiBudWxsLFxuICAgICAgICB5OiB5ICE9PSB1bmRlZmluZWQgPyB5IDogbnVsbFxuICAgIH07XG59XG5mdW5jdGlvbiBub2RlTGlzdENvbnRhaW5zKG5vZGVMaXN0LCBjYW52YXMpIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygbm9kZUxpc3Qpe1xuICAgICAgICBpZiAobm9kZSA9PT0gY2FudmFzIHx8IG5vZGUuY29udGFpbnMoY2FudmFzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBjcmVhdGVBdHRhY2hPYnNlcnZlcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICBjb25zdCBjYW52YXMgPSBjaGFydC5jYW52YXM7XG4gICAgY29uc3Qgb2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcigoZW50cmllcyk9PntcbiAgICAgICAgbGV0IHRyaWdnZXIgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKXtcbiAgICAgICAgICAgIHRyaWdnZXIgPSB0cmlnZ2VyIHx8IG5vZGVMaXN0Q29udGFpbnMoZW50cnkuYWRkZWROb2RlcywgY2FudmFzKTtcbiAgICAgICAgICAgIHRyaWdnZXIgPSB0cmlnZ2VyICYmICFub2RlTGlzdENvbnRhaW5zKGVudHJ5LnJlbW92ZWROb2RlcywgY2FudmFzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHJpZ2dlcikge1xuICAgICAgICAgICAgbGlzdGVuZXIoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIG9ic2VydmVyLm9ic2VydmUoZG9jdW1lbnQsIHtcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIG9ic2VydmVyO1xufVxuZnVuY3Rpb24gY3JlYXRlRGV0YWNoT2JzZXJ2ZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgY29uc3QgY2FudmFzID0gY2hhcnQuY2FudmFzO1xuICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKGVudHJpZXMpPT57XG4gICAgICAgIGxldCB0cmlnZ2VyID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcyl7XG4gICAgICAgICAgICB0cmlnZ2VyID0gdHJpZ2dlciB8fCBub2RlTGlzdENvbnRhaW5zKGVudHJ5LnJlbW92ZWROb2RlcywgY2FudmFzKTtcbiAgICAgICAgICAgIHRyaWdnZXIgPSB0cmlnZ2VyICYmICFub2RlTGlzdENvbnRhaW5zKGVudHJ5LmFkZGVkTm9kZXMsIGNhbnZhcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgICAgICAgIGxpc3RlbmVyKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBvYnNlcnZlci5vYnNlcnZlKGRvY3VtZW50LCB7XG4gICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcbiAgICAgICAgc3VidHJlZTogdHJ1ZVxuICAgIH0pO1xuICAgIHJldHVybiBvYnNlcnZlcjtcbn1cbmNvbnN0IGRycExpc3RlbmluZ0NoYXJ0cyA9IG5ldyBNYXAoKTtcbmxldCBvbGREZXZpY2VQaXhlbFJhdGlvID0gMDtcbmZ1bmN0aW9uIG9uV2luZG93UmVzaXplKCkge1xuICAgIGNvbnN0IGRwciA9IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvO1xuICAgIGlmIChkcHIgPT09IG9sZERldmljZVBpeGVsUmF0aW8pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBvbGREZXZpY2VQaXhlbFJhdGlvID0gZHByO1xuICAgIGRycExpc3RlbmluZ0NoYXJ0cy5mb3JFYWNoKChyZXNpemUsIGNoYXJ0KT0+e1xuICAgICAgICBpZiAoY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW8gIT09IGRwcikge1xuICAgICAgICAgICAgcmVzaXplKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGxpc3RlbkRldmljZVBpeGVsUmF0aW9DaGFuZ2VzKGNoYXJ0LCByZXNpemUpIHtcbiAgICBpZiAoIWRycExpc3RlbmluZ0NoYXJ0cy5zaXplKSB7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCBvbldpbmRvd1Jlc2l6ZSk7XG4gICAgfVxuICAgIGRycExpc3RlbmluZ0NoYXJ0cy5zZXQoY2hhcnQsIHJlc2l6ZSk7XG59XG5mdW5jdGlvbiB1bmxpc3RlbkRldmljZVBpeGVsUmF0aW9DaGFuZ2VzKGNoYXJ0KSB7XG4gICAgZHJwTGlzdGVuaW5nQ2hhcnRzLmRlbGV0ZShjaGFydCk7XG4gICAgaWYgKCFkcnBMaXN0ZW5pbmdDaGFydHMuc2l6ZSkge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgb25XaW5kb3dSZXNpemUpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGNyZWF0ZVJlc2l6ZU9ic2VydmVyKGNoYXJ0LCB0eXBlLCBsaXN0ZW5lcikge1xuICAgIGNvbnN0IGNhbnZhcyA9IGNoYXJ0LmNhbnZhcztcbiAgICBjb25zdCBjb250YWluZXIgPSBjYW52YXMgJiYgX2dldFBhcmVudE5vZGUoY2FudmFzKTtcbiAgICBpZiAoIWNvbnRhaW5lcikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHJlc2l6ZSA9IHRocm90dGxlZCgod2lkdGgsIGhlaWdodCk9PntcbiAgICAgICAgY29uc3QgdyA9IGNvbnRhaW5lci5jbGllbnRXaWR0aDtcbiAgICAgICAgbGlzdGVuZXIod2lkdGgsIGhlaWdodCk7XG4gICAgICAgIGlmICh3IDwgY29udGFpbmVyLmNsaWVudFdpZHRoKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcigpO1xuICAgICAgICB9XG4gICAgfSwgd2luZG93KTtcbiAgICBjb25zdCBvYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoZW50cmllcyk9PntcbiAgICAgICAgY29uc3QgZW50cnkgPSBlbnRyaWVzWzBdO1xuICAgICAgICBjb25zdCB3aWR0aCA9IGVudHJ5LmNvbnRlbnRSZWN0LndpZHRoO1xuICAgICAgICBjb25zdCBoZWlnaHQgPSBlbnRyeS5jb250ZW50UmVjdC5oZWlnaHQ7XG4gICAgICAgIGlmICh3aWR0aCA9PT0gMCAmJiBoZWlnaHQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZXNpemUod2lkdGgsIGhlaWdodCk7XG4gICAgfSk7XG4gICAgb2JzZXJ2ZXIub2JzZXJ2ZShjb250YWluZXIpO1xuICAgIGxpc3RlbkRldmljZVBpeGVsUmF0aW9DaGFuZ2VzKGNoYXJ0LCByZXNpemUpO1xuICAgIHJldHVybiBvYnNlcnZlcjtcbn1cbmZ1bmN0aW9uIHJlbGVhc2VPYnNlcnZlcihjaGFydCwgdHlwZSwgb2JzZXJ2ZXIpIHtcbiAgICBpZiAob2JzZXJ2ZXIpIHtcbiAgICAgICAgb2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIH1cbiAgICBpZiAodHlwZSA9PT0gJ3Jlc2l6ZScpIHtcbiAgICAgICAgdW5saXN0ZW5EZXZpY2VQaXhlbFJhdGlvQ2hhbmdlcyhjaGFydCk7XG4gICAgfVxufVxuZnVuY3Rpb24gY3JlYXRlUHJveHlBbmRMaXN0ZW4oY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgY29uc3QgY2FudmFzID0gY2hhcnQuY2FudmFzO1xuICAgIGNvbnN0IHByb3h5ID0gdGhyb3R0bGVkKChldmVudCk9PntcbiAgICAgICAgaWYgKGNoYXJ0LmN0eCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgbGlzdGVuZXIoZnJvbU5hdGl2ZUV2ZW50KGV2ZW50LCBjaGFydCkpO1xuICAgICAgICB9XG4gICAgfSwgY2hhcnQpO1xuICAgIGFkZExpc3RlbmVyKGNhbnZhcywgdHlwZSwgcHJveHkpO1xuICAgIHJldHVybiBwcm94eTtcbn1cbiBjbGFzcyBEb21QbGF0Zm9ybSBleHRlbmRzIEJhc2VQbGF0Zm9ybSB7XG4gYWNxdWlyZUNvbnRleHQoY2FudmFzLCBhc3BlY3RSYXRpbykge1xuICAgICAgICBjb25zdCBjb250ZXh0ID0gY2FudmFzICYmIGNhbnZhcy5nZXRDb250ZXh0ICYmIGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBpZiAoY29udGV4dCAmJiBjb250ZXh0LmNhbnZhcyA9PT0gY2FudmFzKSB7XG4gICAgICAgICAgICBpbml0Q2FudmFzKGNhbnZhcywgYXNwZWN0UmF0aW8pO1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuIHJlbGVhc2VDb250ZXh0KGNvbnRleHQpIHtcbiAgICAgICAgY29uc3QgY2FudmFzID0gY29udGV4dC5jYW52YXM7XG4gICAgICAgIGlmICghY2FudmFzW0VYUEFORE9fS0VZXSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGluaXRpYWwgPSBjYW52YXNbRVhQQU5ET19LRVldLmluaXRpYWw7XG4gICAgICAgIFtcbiAgICAgICAgICAgICdoZWlnaHQnLFxuICAgICAgICAgICAgJ3dpZHRoJ1xuICAgICAgICBdLmZvckVhY2goKHByb3ApPT57XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGluaXRpYWxbcHJvcF07XG4gICAgICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZih2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBjYW52YXMucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYW52YXMuc2V0QXR0cmlidXRlKHByb3AsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN0eWxlID0gaW5pdGlhbC5zdHlsZSB8fCB7fTtcbiAgICAgICAgT2JqZWN0LmtleXMoc3R5bGUpLmZvckVhY2goKGtleSk9PntcbiAgICAgICAgICAgIGNhbnZhcy5zdHlsZVtrZXldID0gc3R5bGVba2V5XTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhcy53aWR0aDtcbiAgICAgICAgZGVsZXRlIGNhbnZhc1tFWFBBTkRPX0tFWV07XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiBhZGRFdmVudExpc3RlbmVyKGNoYXJ0LCB0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUpO1xuICAgICAgICBjb25zdCBwcm94aWVzID0gY2hhcnQuJHByb3hpZXMgfHwgKGNoYXJ0LiRwcm94aWVzID0ge30pO1xuICAgICAgICBjb25zdCBoYW5kbGVycyA9IHtcbiAgICAgICAgICAgIGF0dGFjaDogY3JlYXRlQXR0YWNoT2JzZXJ2ZXIsXG4gICAgICAgICAgICBkZXRhY2g6IGNyZWF0ZURldGFjaE9ic2VydmVyLFxuICAgICAgICAgICAgcmVzaXplOiBjcmVhdGVSZXNpemVPYnNlcnZlclxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlcnNbdHlwZV0gfHwgY3JlYXRlUHJveHlBbmRMaXN0ZW47XG4gICAgICAgIHByb3hpZXNbdHlwZV0gPSBoYW5kbGVyKGNoYXJ0LCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgfVxuIHJlbW92ZUV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUpIHtcbiAgICAgICAgY29uc3QgcHJveGllcyA9IGNoYXJ0LiRwcm94aWVzIHx8IChjaGFydC4kcHJveGllcyA9IHt9KTtcbiAgICAgICAgY29uc3QgcHJveHkgPSBwcm94aWVzW3R5cGVdO1xuICAgICAgICBpZiAoIXByb3h5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaGFuZGxlcnMgPSB7XG4gICAgICAgICAgICBhdHRhY2g6IHJlbGVhc2VPYnNlcnZlcixcbiAgICAgICAgICAgIGRldGFjaDogcmVsZWFzZU9ic2VydmVyLFxuICAgICAgICAgICAgcmVzaXplOiByZWxlYXNlT2JzZXJ2ZXJcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IGhhbmRsZXJzW3R5cGVdIHx8IHJlbW92ZUxpc3RlbmVyO1xuICAgICAgICBoYW5kbGVyKGNoYXJ0LCB0eXBlLCBwcm94eSk7XG4gICAgICAgIHByb3hpZXNbdHlwZV0gPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGdldERldmljZVBpeGVsUmF0aW8oKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICB9XG4gZ2V0TWF4aW11bVNpemUoY2FudmFzLCB3aWR0aCwgaGVpZ2h0LCBhc3BlY3RSYXRpbykge1xuICAgICAgICByZXR1cm4gZ2V0TWF4aW11bVNpemUoY2FudmFzLCB3aWR0aCwgaGVpZ2h0LCBhc3BlY3RSYXRpbyk7XG4gICAgfVxuIGlzQXR0YWNoZWQoY2FudmFzKSB7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGNhbnZhcyAmJiBfZ2V0UGFyZW50Tm9kZShjYW52YXMpO1xuICAgICAgICByZXR1cm4gISEoY29udGFpbmVyICYmIGNvbnRhaW5lci5pc0Nvbm5lY3RlZCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBfZGV0ZWN0UGxhdGZvcm0oY2FudmFzKSB7XG4gICAgaWYgKCFfaXNEb21TdXBwb3J0ZWQoKSB8fCB0eXBlb2YgT2Zmc2NyZWVuQ2FudmFzICE9PSAndW5kZWZpbmVkJyAmJiBjYW52YXMgaW5zdGFuY2VvZiBPZmZzY3JlZW5DYW52YXMpIHtcbiAgICAgICAgcmV0dXJuIEJhc2ljUGxhdGZvcm07XG4gICAgfVxuICAgIHJldHVybiBEb21QbGF0Zm9ybTtcbn1cblxuY2xhc3MgRWxlbWVudCB7XG4gICAgc3RhdGljIGRlZmF1bHRzID0ge307XG4gICAgc3RhdGljIGRlZmF1bHRSb3V0ZXMgPSB1bmRlZmluZWQ7XG4gICAgeDtcbiAgICB5O1xuICAgIGFjdGl2ZSA9IGZhbHNlO1xuICAgIG9wdGlvbnM7XG4gICAgJGFuaW1hdGlvbnM7XG4gICAgdG9vbHRpcFBvc2l0aW9uKHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgY29uc3QgeyB4ICwgeSAgfSA9IHRoaXMuZ2V0UHJvcHMoW1xuICAgICAgICAgICAgJ3gnLFxuICAgICAgICAgICAgJ3knXG4gICAgICAgIF0sIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeCxcbiAgICAgICAgICAgIHlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaGFzVmFsdWUoKSB7XG4gICAgICAgIHJldHVybiBpc051bWJlcih0aGlzLngpICYmIGlzTnVtYmVyKHRoaXMueSk7XG4gICAgfVxuICAgIGdldFByb3BzKHByb3BzLCBmaW5hbCkge1xuICAgICAgICBjb25zdCBhbmltcyA9IHRoaXMuJGFuaW1hdGlvbnM7XG4gICAgICAgIGlmICghZmluYWwgfHwgIWFuaW1zKSB7XG4gICAgICAgICAgICAvLyBsZXQncyBub3QgY3JlYXRlIGFuIG9iamVjdCwgaWYgbm90IG5lZWRlZFxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmV0ID0ge307XG4gICAgICAgIHByb3BzLmZvckVhY2goKHByb3ApPT57XG4gICAgICAgICAgICByZXRbcHJvcF0gPSBhbmltc1twcm9wXSAmJiBhbmltc1twcm9wXS5hY3RpdmUoKSA/IGFuaW1zW3Byb3BdLl90byA6IHRoaXNbcHJvcF07XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gYXV0b1NraXAoc2NhbGUsIHRpY2tzKSB7XG4gICAgY29uc3QgdGlja09wdHMgPSBzY2FsZS5vcHRpb25zLnRpY2tzO1xuICAgIGNvbnN0IGRldGVybWluZWRNYXhUaWNrcyA9IGRldGVybWluZU1heFRpY2tzKHNjYWxlKTtcbiAgICBjb25zdCB0aWNrc0xpbWl0ID0gTWF0aC5taW4odGlja09wdHMubWF4VGlja3NMaW1pdCB8fCBkZXRlcm1pbmVkTWF4VGlja3MsIGRldGVybWluZWRNYXhUaWNrcyk7XG4gICAgY29uc3QgbWFqb3JJbmRpY2VzID0gdGlja09wdHMubWFqb3IuZW5hYmxlZCA/IGdldE1ham9ySW5kaWNlcyh0aWNrcykgOiBbXTtcbiAgICBjb25zdCBudW1NYWpvckluZGljZXMgPSBtYWpvckluZGljZXMubGVuZ3RoO1xuICAgIGNvbnN0IGZpcnN0ID0gbWFqb3JJbmRpY2VzWzBdO1xuICAgIGNvbnN0IGxhc3QgPSBtYWpvckluZGljZXNbbnVtTWFqb3JJbmRpY2VzIC0gMV07XG4gICAgY29uc3QgbmV3VGlja3MgPSBbXTtcbiAgICBpZiAobnVtTWFqb3JJbmRpY2VzID4gdGlja3NMaW1pdCkge1xuICAgICAgICBza2lwTWFqb3JzKHRpY2tzLCBuZXdUaWNrcywgbWFqb3JJbmRpY2VzLCBudW1NYWpvckluZGljZXMgLyB0aWNrc0xpbWl0KTtcbiAgICAgICAgcmV0dXJuIG5ld1RpY2tzO1xuICAgIH1cbiAgICBjb25zdCBzcGFjaW5nID0gY2FsY3VsYXRlU3BhY2luZyhtYWpvckluZGljZXMsIHRpY2tzLCB0aWNrc0xpbWl0KTtcbiAgICBpZiAobnVtTWFqb3JJbmRpY2VzID4gMCkge1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgY29uc3QgYXZnTWFqb3JTcGFjaW5nID0gbnVtTWFqb3JJbmRpY2VzID4gMSA/IE1hdGgucm91bmQoKGxhc3QgLSBmaXJzdCkgLyAobnVtTWFqb3JJbmRpY2VzIC0gMSkpIDogbnVsbDtcbiAgICAgICAgc2tpcCh0aWNrcywgbmV3VGlja3MsIHNwYWNpbmcsIGlzTnVsbE9yVW5kZWYoYXZnTWFqb3JTcGFjaW5nKSA/IDAgOiBmaXJzdCAtIGF2Z01ham9yU3BhY2luZywgZmlyc3QpO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBudW1NYWpvckluZGljZXMgLSAxOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgICAgIHNraXAodGlja3MsIG5ld1RpY2tzLCBzcGFjaW5nLCBtYWpvckluZGljZXNbaV0sIG1ham9ySW5kaWNlc1tpICsgMV0pO1xuICAgICAgICB9XG4gICAgICAgIHNraXAodGlja3MsIG5ld1RpY2tzLCBzcGFjaW5nLCBsYXN0LCBpc051bGxPclVuZGVmKGF2Z01ham9yU3BhY2luZykgPyB0aWNrcy5sZW5ndGggOiBsYXN0ICsgYXZnTWFqb3JTcGFjaW5nKTtcbiAgICAgICAgcmV0dXJuIG5ld1RpY2tzO1xuICAgIH1cbiAgICBza2lwKHRpY2tzLCBuZXdUaWNrcywgc3BhY2luZyk7XG4gICAgcmV0dXJuIG5ld1RpY2tzO1xufVxuZnVuY3Rpb24gZGV0ZXJtaW5lTWF4VGlja3Moc2NhbGUpIHtcbiAgICBjb25zdCBvZmZzZXQgPSBzY2FsZS5vcHRpb25zLm9mZnNldDtcbiAgICBjb25zdCB0aWNrTGVuZ3RoID0gc2NhbGUuX3RpY2tTaXplKCk7XG4gICAgY29uc3QgbWF4U2NhbGUgPSBzY2FsZS5fbGVuZ3RoIC8gdGlja0xlbmd0aCArIChvZmZzZXQgPyAwIDogMSk7XG4gICAgY29uc3QgbWF4Q2hhcnQgPSBzY2FsZS5fbWF4TGVuZ3RoIC8gdGlja0xlbmd0aDtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLm1pbihtYXhTY2FsZSwgbWF4Q2hhcnQpKTtcbn1cbiBmdW5jdGlvbiBjYWxjdWxhdGVTcGFjaW5nKG1ham9ySW5kaWNlcywgdGlja3MsIHRpY2tzTGltaXQpIHtcbiAgICBjb25zdCBldmVuTWFqb3JTcGFjaW5nID0gZ2V0RXZlblNwYWNpbmcobWFqb3JJbmRpY2VzKTtcbiAgICBjb25zdCBzcGFjaW5nID0gdGlja3MubGVuZ3RoIC8gdGlja3NMaW1pdDtcbiAgICBpZiAoIWV2ZW5NYWpvclNwYWNpbmcpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KHNwYWNpbmcsIDEpO1xuICAgIH1cbiAgICBjb25zdCBmYWN0b3JzID0gX2ZhY3Rvcml6ZShldmVuTWFqb3JTcGFjaW5nKTtcbiAgICBmb3IobGV0IGkgPSAwLCBpbGVuID0gZmFjdG9ycy5sZW5ndGggLSAxOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgY29uc3QgZmFjdG9yID0gZmFjdG9yc1tpXTtcbiAgICAgICAgaWYgKGZhY3RvciA+IHNwYWNpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWN0b3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIE1hdGgubWF4KHNwYWNpbmcsIDEpO1xufVxuIGZ1bmN0aW9uIGdldE1ham9ySW5kaWNlcyh0aWNrcykge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpLCBpbGVuO1xuICAgIGZvcihpID0gMCwgaWxlbiA9IHRpY2tzLmxlbmd0aDsgaSA8IGlsZW47IGkrKyl7XG4gICAgICAgIGlmICh0aWNrc1tpXS5tYWpvcikge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2goaSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbiBmdW5jdGlvbiBza2lwTWFqb3JzKHRpY2tzLCBuZXdUaWNrcywgbWFqb3JJbmRpY2VzLCBzcGFjaW5nKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBsZXQgbmV4dCA9IG1ham9ySW5kaWNlc1swXTtcbiAgICBsZXQgaTtcbiAgICBzcGFjaW5nID0gTWF0aC5jZWlsKHNwYWNpbmcpO1xuICAgIGZvcihpID0gMDsgaSA8IHRpY2tzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgaWYgKGkgPT09IG5leHQpIHtcbiAgICAgICAgICAgIG5ld1RpY2tzLnB1c2godGlja3NbaV0pO1xuICAgICAgICAgICAgY291bnQrKztcbiAgICAgICAgICAgIG5leHQgPSBtYWpvckluZGljZXNbY291bnQgKiBzcGFjaW5nXTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiBmdW5jdGlvbiBza2lwKHRpY2tzLCBuZXdUaWNrcywgc3BhY2luZywgbWFqb3JTdGFydCwgbWFqb3JFbmQpIHtcbiAgICBjb25zdCBzdGFydCA9IHZhbHVlT3JEZWZhdWx0KG1ham9yU3RhcnQsIDApO1xuICAgIGNvbnN0IGVuZCA9IE1hdGgubWluKHZhbHVlT3JEZWZhdWx0KG1ham9yRW5kLCB0aWNrcy5sZW5ndGgpLCB0aWNrcy5sZW5ndGgpO1xuICAgIGxldCBjb3VudCA9IDA7XG4gICAgbGV0IGxlbmd0aCwgaSwgbmV4dDtcbiAgICBzcGFjaW5nID0gTWF0aC5jZWlsKHNwYWNpbmcpO1xuICAgIGlmIChtYWpvckVuZCkge1xuICAgICAgICBsZW5ndGggPSBtYWpvckVuZCAtIG1ham9yU3RhcnQ7XG4gICAgICAgIHNwYWNpbmcgPSBsZW5ndGggLyBNYXRoLmZsb29yKGxlbmd0aCAvIHNwYWNpbmcpO1xuICAgIH1cbiAgICBuZXh0ID0gc3RhcnQ7XG4gICAgd2hpbGUobmV4dCA8IDApe1xuICAgICAgICBjb3VudCsrO1xuICAgICAgICBuZXh0ID0gTWF0aC5yb3VuZChzdGFydCArIGNvdW50ICogc3BhY2luZyk7XG4gICAgfVxuICAgIGZvcihpID0gTWF0aC5tYXgoc3RhcnQsIDApOyBpIDwgZW5kOyBpKyspe1xuICAgICAgICBpZiAoaSA9PT0gbmV4dCkge1xuICAgICAgICAgICAgbmV3VGlja3MucHVzaCh0aWNrc1tpXSk7XG4gICAgICAgICAgICBjb3VudCsrO1xuICAgICAgICAgICAgbmV4dCA9IE1hdGgucm91bmQoc3RhcnQgKyBjb3VudCAqIHNwYWNpbmcpO1xuICAgICAgICB9XG4gICAgfVxufVxuIGZ1bmN0aW9uIGdldEV2ZW5TcGFjaW5nKGFycikge1xuICAgIGNvbnN0IGxlbiA9IGFyci5sZW5ndGg7XG4gICAgbGV0IGksIGRpZmY7XG4gICAgaWYgKGxlbiA8IDIpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IoZGlmZiA9IGFyclswXSwgaSA9IDE7IGkgPCBsZW47ICsraSl7XG4gICAgICAgIGlmIChhcnJbaV0gLSBhcnJbaSAtIDFdICE9PSBkaWZmKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRpZmY7XG59XG5cbmNvbnN0IHJldmVyc2VBbGlnbiA9IChhbGlnbik9PmFsaWduID09PSAnbGVmdCcgPyAncmlnaHQnIDogYWxpZ24gPT09ICdyaWdodCcgPyAnbGVmdCcgOiBhbGlnbjtcbmNvbnN0IG9mZnNldEZyb21FZGdlID0gKHNjYWxlLCBlZGdlLCBvZmZzZXQpPT5lZGdlID09PSAndG9wJyB8fCBlZGdlID09PSAnbGVmdCcgPyBzY2FsZVtlZGdlXSArIG9mZnNldCA6IHNjYWxlW2VkZ2VdIC0gb2Zmc2V0O1xuY29uc3QgZ2V0VGlja3NMaW1pdCA9ICh0aWNrc0xlbmd0aCwgbWF4VGlja3NMaW1pdCk9Pk1hdGgubWluKG1heFRpY2tzTGltaXQgfHwgdGlja3NMZW5ndGgsIHRpY2tzTGVuZ3RoKTtcbiBmdW5jdGlvbiBzYW1wbGUoYXJyLCBudW1JdGVtcykge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGNvbnN0IGluY3JlbWVudCA9IGFyci5sZW5ndGggLyBudW1JdGVtcztcbiAgICBjb25zdCBsZW4gPSBhcnIubGVuZ3RoO1xuICAgIGxldCBpID0gMDtcbiAgICBmb3IoOyBpIDwgbGVuOyBpICs9IGluY3JlbWVudCl7XG4gICAgICAgIHJlc3VsdC5wdXNoKGFycltNYXRoLmZsb29yKGkpXSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG4gZnVuY3Rpb24gZ2V0UGl4ZWxGb3JHcmlkTGluZShzY2FsZSwgaW5kZXgsIG9mZnNldEdyaWRMaW5lcykge1xuICAgIGNvbnN0IGxlbmd0aCA9IHNjYWxlLnRpY2tzLmxlbmd0aDtcbiAgICBjb25zdCB2YWxpZEluZGV4ID0gTWF0aC5taW4oaW5kZXgsIGxlbmd0aCAtIDEpO1xuICAgIGNvbnN0IHN0YXJ0ID0gc2NhbGUuX3N0YXJ0UGl4ZWw7XG4gICAgY29uc3QgZW5kID0gc2NhbGUuX2VuZFBpeGVsO1xuICAgIGNvbnN0IGVwc2lsb24gPSAxZS02O1xuICAgIGxldCBsaW5lVmFsdWUgPSBzY2FsZS5nZXRQaXhlbEZvclRpY2sodmFsaWRJbmRleCk7XG4gICAgbGV0IG9mZnNldDtcbiAgICBpZiAob2Zmc2V0R3JpZExpbmVzKSB7XG4gICAgICAgIGlmIChsZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IE1hdGgubWF4KGxpbmVWYWx1ZSAtIHN0YXJ0LCBlbmQgLSBsaW5lVmFsdWUpO1xuICAgICAgICB9IGVsc2UgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAoc2NhbGUuZ2V0UGl4ZWxGb3JUaWNrKDEpIC0gbGluZVZhbHVlKSAvIDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAobGluZVZhbHVlIC0gc2NhbGUuZ2V0UGl4ZWxGb3JUaWNrKHZhbGlkSW5kZXggLSAxKSkgLyAyO1xuICAgICAgICB9XG4gICAgICAgIGxpbmVWYWx1ZSArPSB2YWxpZEluZGV4IDwgaW5kZXggPyBvZmZzZXQgOiAtb2Zmc2V0O1xuICAgICAgICBpZiAobGluZVZhbHVlIDwgc3RhcnQgLSBlcHNpbG9uIHx8IGxpbmVWYWx1ZSA+IGVuZCArIGVwc2lsb24pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbGluZVZhbHVlO1xufVxuIGZ1bmN0aW9uIGdhcmJhZ2VDb2xsZWN0KGNhY2hlcywgbGVuZ3RoKSB7XG4gICAgZWFjaChjYWNoZXMsIChjYWNoZSk9PntcbiAgICAgICAgY29uc3QgZ2MgPSBjYWNoZS5nYztcbiAgICAgICAgY29uc3QgZ2NMZW4gPSBnYy5sZW5ndGggLyAyO1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgaWYgKGdjTGVuID4gbGVuZ3RoKSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBnY0xlbjsgKytpKXtcbiAgICAgICAgICAgICAgICBkZWxldGUgY2FjaGUuZGF0YVtnY1tpXV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBnYy5zcGxpY2UoMCwgZ2NMZW4pO1xuICAgICAgICB9XG4gICAgfSk7XG59XG4gZnVuY3Rpb24gZ2V0VGlja01hcmtMZW5ndGgob3B0aW9ucykge1xuICAgIHJldHVybiBvcHRpb25zLmRyYXdUaWNrcyA/IG9wdGlvbnMudGlja0xlbmd0aCA6IDA7XG59XG4gZnVuY3Rpb24gZ2V0VGl0bGVIZWlnaHQob3B0aW9ucywgZmFsbGJhY2spIHtcbiAgICBpZiAoIW9wdGlvbnMuZGlzcGxheSkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgY29uc3QgZm9udCA9IHRvRm9udChvcHRpb25zLmZvbnQsIGZhbGxiYWNrKTtcbiAgICBjb25zdCBwYWRkaW5nID0gdG9QYWRkaW5nKG9wdGlvbnMucGFkZGluZyk7XG4gICAgY29uc3QgbGluZXMgPSBpc0FycmF5KG9wdGlvbnMudGV4dCkgPyBvcHRpb25zLnRleHQubGVuZ3RoIDogMTtcbiAgICByZXR1cm4gbGluZXMgKiBmb250LmxpbmVIZWlnaHQgKyBwYWRkaW5nLmhlaWdodDtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVNjYWxlQ29udGV4dChwYXJlbnQsIHNjYWxlKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUNvbnRleHQocGFyZW50LCB7XG4gICAgICAgIHNjYWxlLFxuICAgICAgICB0eXBlOiAnc2NhbGUnXG4gICAgfSk7XG59XG5mdW5jdGlvbiBjcmVhdGVUaWNrQ29udGV4dChwYXJlbnQsIGluZGV4LCB0aWNrKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUNvbnRleHQocGFyZW50LCB7XG4gICAgICAgIHRpY2ssXG4gICAgICAgIGluZGV4LFxuICAgICAgICB0eXBlOiAndGljaydcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIHRpdGxlQWxpZ24oYWxpZ24sIHBvc2l0aW9uLCByZXZlcnNlKSB7XG4gICAgIGxldCByZXQgPSBfdG9MZWZ0UmlnaHRDZW50ZXIoYWxpZ24pO1xuICAgIGlmIChyZXZlcnNlICYmIHBvc2l0aW9uICE9PSAncmlnaHQnIHx8ICFyZXZlcnNlICYmIHBvc2l0aW9uID09PSAncmlnaHQnKSB7XG4gICAgICAgIHJldCA9IHJldmVyc2VBbGlnbihyZXQpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xufVxuZnVuY3Rpb24gdGl0bGVBcmdzKHNjYWxlLCBvZmZzZXQsIHBvc2l0aW9uLCBhbGlnbikge1xuICAgIGNvbnN0IHsgdG9wICwgbGVmdCAsIGJvdHRvbSAsIHJpZ2h0ICwgY2hhcnQgIH0gPSBzY2FsZTtcbiAgICBjb25zdCB7IGNoYXJ0QXJlYSAsIHNjYWxlcyAgfSA9IGNoYXJ0O1xuICAgIGxldCByb3RhdGlvbiA9IDA7XG4gICAgbGV0IG1heFdpZHRoLCB0aXRsZVgsIHRpdGxlWTtcbiAgICBjb25zdCBoZWlnaHQgPSBib3R0b20gLSB0b3A7XG4gICAgY29uc3Qgd2lkdGggPSByaWdodCAtIGxlZnQ7XG4gICAgaWYgKHNjYWxlLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgIHRpdGxlWCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBsZWZ0LCByaWdodCk7XG4gICAgICAgIGlmIChpc09iamVjdChwb3NpdGlvbikpIHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICAgICAgICB0aXRsZVkgPSBzY2FsZXNbcG9zaXRpb25BeGlzSURdLmdldFBpeGVsRm9yVmFsdWUodmFsdWUpICsgaGVpZ2h0IC0gb2Zmc2V0O1xuICAgICAgICB9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgdGl0bGVZID0gKGNoYXJ0QXJlYS5ib3R0b20gKyBjaGFydEFyZWEudG9wKSAvIDIgKyBoZWlnaHQgLSBvZmZzZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aXRsZVkgPSBvZmZzZXRGcm9tRWRnZShzY2FsZSwgcG9zaXRpb24sIG9mZnNldCk7XG4gICAgICAgIH1cbiAgICAgICAgbWF4V2lkdGggPSByaWdodCAtIGxlZnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25BeGlzSUQgPSBPYmplY3Qua2V5cyhwb3NpdGlvbilbMF07XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW3Bvc2l0aW9uQXhpc0lEXTtcbiAgICAgICAgICAgIHRpdGxlWCA9IHNjYWxlc1twb3NpdGlvbkF4aXNJRF0uZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkgLSB3aWR0aCArIG9mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgIHRpdGxlWCA9IChjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS5yaWdodCkgLyAyIC0gd2lkdGggKyBvZmZzZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aXRsZVggPSBvZmZzZXRGcm9tRWRnZShzY2FsZSwgcG9zaXRpb24sIG9mZnNldCk7XG4gICAgICAgIH1cbiAgICAgICAgdGl0bGVZID0gX2FsaWduU3RhcnRFbmQoYWxpZ24sIGJvdHRvbSwgdG9wKTtcbiAgICAgICAgcm90YXRpb24gPSBwb3NpdGlvbiA9PT0gJ2xlZnQnID8gLUhBTEZfUEkgOiBIQUxGX1BJO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICB0aXRsZVgsXG4gICAgICAgIHRpdGxlWSxcbiAgICAgICAgbWF4V2lkdGgsXG4gICAgICAgIHJvdGF0aW9uXG4gICAgfTtcbn1cbmNsYXNzIFNjYWxlIGV4dGVuZHMgRWxlbWVudCB7XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgIHRoaXMuaWQgPSBjZmcuaWQ7XG4gICAgICAgICB0aGlzLnR5cGUgPSBjZmcudHlwZTtcbiAgICAgICAgIHRoaXMub3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuY3R4ID0gY2ZnLmN0eDtcbiAgICAgICAgIHRoaXMuY2hhcnQgPSBjZmcuY2hhcnQ7XG4gICAgICAgICB0aGlzLnRvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuYm90dG9tID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5sZWZ0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5yaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMud2lkdGggPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLmhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fbWFyZ2lucyA9IHtcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICByaWdodDogMCxcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIGJvdHRvbTogMFxuICAgICAgICB9O1xuICAgICAgICAgdGhpcy5tYXhXaWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMubWF4SGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5wYWRkaW5nVG9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5wYWRkaW5nQm90dG9tID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5wYWRkaW5nTGVmdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMucGFkZGluZ1JpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5heGlzID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5sYWJlbFJvdGF0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm1pbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5tYXggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3JhbmdlID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy50aWNrcyA9IFtdO1xuICAgICAgICAgdGhpcy5fZ3JpZExpbmVJdGVtcyA9IG51bGw7XG4gICAgICAgICB0aGlzLl9sYWJlbEl0ZW1zID0gbnVsbDtcbiAgICAgICAgIHRoaXMuX2xhYmVsU2l6ZXMgPSBudWxsO1xuICAgICAgICB0aGlzLl9sZW5ndGggPSAwO1xuICAgICAgICB0aGlzLl9tYXhMZW5ndGggPSAwO1xuICAgICAgICB0aGlzLl9sb25nZXN0VGV4dENhY2hlID0ge307XG4gICAgICAgICB0aGlzLl9zdGFydFBpeGVsID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5fZW5kUGl4ZWwgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3JldmVyc2VQaXhlbHMgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fdXNlck1heCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fdXNlck1pbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fc3VnZ2VzdGVkTWF4ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9zdWdnZXN0ZWRNaW4gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3RpY2tzTGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5fYm9yZGVyVmFsdWUgPSAwO1xuICAgICAgICB0aGlzLl9jYWNoZSA9IHt9O1xuICAgICAgICB0aGlzLl9kYXRhTGltaXRzQ2FjaGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuJGNvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgfVxuIGluaXQob3B0aW9ucykge1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KCkpO1xuICAgICAgICB0aGlzLmF4aXMgPSBvcHRpb25zLmF4aXM7XG4gICAgICAgIHRoaXMuX3VzZXJNaW4gPSB0aGlzLnBhcnNlKG9wdGlvbnMubWluKTtcbiAgICAgICAgdGhpcy5fdXNlck1heCA9IHRoaXMucGFyc2Uob3B0aW9ucy5tYXgpO1xuICAgICAgICB0aGlzLl9zdWdnZXN0ZWRNaW4gPSB0aGlzLnBhcnNlKG9wdGlvbnMuc3VnZ2VzdGVkTWluKTtcbiAgICAgICAgdGhpcy5fc3VnZ2VzdGVkTWF4ID0gdGhpcy5wYXJzZShvcHRpb25zLnN1Z2dlc3RlZE1heCk7XG4gICAgfVxuIHBhcnNlKHJhdywgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHJhdztcbiAgICB9XG4gZ2V0VXNlckJvdW5kcygpIHtcbiAgICAgICAgbGV0IHsgX3VzZXJNaW4gLCBfdXNlck1heCAsIF9zdWdnZXN0ZWRNaW4gLCBfc3VnZ2VzdGVkTWF4ICB9ID0gdGhpcztcbiAgICAgICAgX3VzZXJNaW4gPSBmaW5pdGVPckRlZmF1bHQoX3VzZXJNaW4sIE51bWJlci5QT1NJVElWRV9JTkZJTklUWSk7XG4gICAgICAgIF91c2VyTWF4ID0gZmluaXRlT3JEZWZhdWx0KF91c2VyTWF4LCBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFkpO1xuICAgICAgICBfc3VnZ2VzdGVkTWluID0gZmluaXRlT3JEZWZhdWx0KF9zdWdnZXN0ZWRNaW4sIE51bWJlci5QT1NJVElWRV9JTkZJTklUWSk7XG4gICAgICAgIF9zdWdnZXN0ZWRNYXggPSBmaW5pdGVPckRlZmF1bHQoX3N1Z2dlc3RlZE1heCwgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG1pbjogZmluaXRlT3JEZWZhdWx0KF91c2VyTWluLCBfc3VnZ2VzdGVkTWluKSxcbiAgICAgICAgICAgIG1heDogZmluaXRlT3JEZWZhdWx0KF91c2VyTWF4LCBfc3VnZ2VzdGVkTWF4KSxcbiAgICAgICAgICAgIG1pbkRlZmluZWQ6IGlzTnVtYmVyRmluaXRlKF91c2VyTWluKSxcbiAgICAgICAgICAgIG1heERlZmluZWQ6IGlzTnVtYmVyRmluaXRlKF91c2VyTWF4KVxuICAgICAgICB9O1xuICAgIH1cbiBnZXRNaW5NYXgoY2FuU3RhY2spIHtcbiAgICAgICAgbGV0IHsgbWluICwgbWF4ICwgbWluRGVmaW5lZCAsIG1heERlZmluZWQgIH0gPSB0aGlzLmdldFVzZXJCb3VuZHMoKTtcbiAgICAgICAgbGV0IHJhbmdlO1xuICAgICAgICBpZiAobWluRGVmaW5lZCAmJiBtYXhEZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1pbixcbiAgICAgICAgICAgICAgICBtYXhcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbWV0YXMgPSB0aGlzLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKCk7XG4gICAgICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSBtZXRhcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgcmFuZ2UgPSBtZXRhc1tpXS5jb250cm9sbGVyLmdldE1pbk1heCh0aGlzLCBjYW5TdGFjayk7XG4gICAgICAgICAgICBpZiAoIW1pbkRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIHJhbmdlLm1pbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW1heERlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIHJhbmdlLm1heCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbWluID0gbWF4RGVmaW5lZCAmJiBtaW4gPiBtYXggPyBtYXggOiBtaW47XG4gICAgICAgIG1heCA9IG1pbkRlZmluZWQgJiYgbWluID4gbWF4ID8gbWluIDogbWF4O1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbWluOiBmaW5pdGVPckRlZmF1bHQobWluLCBmaW5pdGVPckRlZmF1bHQobWF4LCBtaW4pKSxcbiAgICAgICAgICAgIG1heDogZmluaXRlT3JEZWZhdWx0KG1heCwgZmluaXRlT3JEZWZhdWx0KG1pbiwgbWF4KSlcbiAgICAgICAgfTtcbiAgICB9XG4gZ2V0UGFkZGluZygpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxlZnQ6IHRoaXMucGFkZGluZ0xlZnQgfHwgMCxcbiAgICAgICAgICAgIHRvcDogdGhpcy5wYWRkaW5nVG9wIHx8IDAsXG4gICAgICAgICAgICByaWdodDogdGhpcy5wYWRkaW5nUmlnaHQgfHwgMCxcbiAgICAgICAgICAgIGJvdHRvbTogdGhpcy5wYWRkaW5nQm90dG9tIHx8IDBcbiAgICAgICAgfTtcbiAgICB9XG4gZ2V0VGlja3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpY2tzO1xuICAgIH1cbiBnZXRMYWJlbHMoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmNoYXJ0LmRhdGE7XG4gICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMubGFiZWxzIHx8ICh0aGlzLmlzSG9yaXpvbnRhbCgpID8gZGF0YS54TGFiZWxzIDogZGF0YS55TGFiZWxzKSB8fCBkYXRhLmxhYmVscyB8fCBbXTtcbiAgICB9XG4gZ2V0TGFiZWxJdGVtcyhjaGFydEFyZWEgPSB0aGlzLmNoYXJ0LmNoYXJ0QXJlYSkge1xuICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuX2xhYmVsSXRlbXMgfHwgKHRoaXMuX2xhYmVsSXRlbXMgPSB0aGlzLl9jb21wdXRlTGFiZWxJdGVtcyhjaGFydEFyZWEpKTtcbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgIH1cbiAgICBiZWZvcmVMYXlvdXQoKSB7XG4gICAgICAgIHRoaXMuX2NhY2hlID0ge307XG4gICAgICAgIHRoaXMuX2RhdGFMaW1pdHNDYWNoZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgYmVmb3JlVXBkYXRlKCkge1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlVXBkYXRlLCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiB1cGRhdGUobWF4V2lkdGgsIG1heEhlaWdodCwgbWFyZ2lucykge1xuICAgICAgICBjb25zdCB7IGJlZ2luQXRaZXJvICwgZ3JhY2UgLCB0aWNrczogdGlja09wdHMgIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHNhbXBsZVNpemUgPSB0aWNrT3B0cy5zYW1wbGVTaXplO1xuICAgICAgICB0aGlzLmJlZm9yZVVwZGF0ZSgpO1xuICAgICAgICB0aGlzLm1heFdpZHRoID0gbWF4V2lkdGg7XG4gICAgICAgIHRoaXMubWF4SGVpZ2h0ID0gbWF4SGVpZ2h0O1xuICAgICAgICB0aGlzLl9tYXJnaW5zID0gbWFyZ2lucyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgIHJpZ2h0OiAwLFxuICAgICAgICAgICAgdG9wOiAwLFxuICAgICAgICAgICAgYm90dG9tOiAwXG4gICAgICAgIH0sIG1hcmdpbnMpO1xuICAgICAgICB0aGlzLnRpY2tzID0gbnVsbDtcbiAgICAgICAgdGhpcy5fbGFiZWxTaXplcyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2dyaWRMaW5lSXRlbXMgPSBudWxsO1xuICAgICAgICB0aGlzLl9sYWJlbEl0ZW1zID0gbnVsbDtcbiAgICAgICAgdGhpcy5iZWZvcmVTZXREaW1lbnNpb25zKCk7XG4gICAgICAgIHRoaXMuc2V0RGltZW5zaW9ucygpO1xuICAgICAgICB0aGlzLmFmdGVyU2V0RGltZW5zaW9ucygpO1xuICAgICAgICB0aGlzLl9tYXhMZW5ndGggPSB0aGlzLmlzSG9yaXpvbnRhbCgpID8gdGhpcy53aWR0aCArIG1hcmdpbnMubGVmdCArIG1hcmdpbnMucmlnaHQgOiB0aGlzLmhlaWdodCArIG1hcmdpbnMudG9wICsgbWFyZ2lucy5ib3R0b207XG4gICAgICAgIGlmICghdGhpcy5fZGF0YUxpbWl0c0NhY2hlZCkge1xuICAgICAgICAgICAgdGhpcy5iZWZvcmVEYXRhTGltaXRzKCk7XG4gICAgICAgICAgICB0aGlzLmRldGVybWluZURhdGFMaW1pdHMoKTtcbiAgICAgICAgICAgIHRoaXMuYWZ0ZXJEYXRhTGltaXRzKCk7XG4gICAgICAgICAgICB0aGlzLl9yYW5nZSA9IF9hZGRHcmFjZSh0aGlzLCBncmFjZSwgYmVnaW5BdFplcm8pO1xuICAgICAgICAgICAgdGhpcy5fZGF0YUxpbWl0c0NhY2hlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5iZWZvcmVCdWlsZFRpY2tzKCk7XG4gICAgICAgIHRoaXMudGlja3MgPSB0aGlzLmJ1aWxkVGlja3MoKSB8fCBbXTtcbiAgICAgICAgdGhpcy5hZnRlckJ1aWxkVGlja3MoKTtcbiAgICAgICAgY29uc3Qgc2FtcGxpbmdFbmFibGVkID0gc2FtcGxlU2l6ZSA8IHRoaXMudGlja3MubGVuZ3RoO1xuICAgICAgICB0aGlzLl9jb252ZXJ0VGlja3NUb0xhYmVscyhzYW1wbGluZ0VuYWJsZWQgPyBzYW1wbGUodGhpcy50aWNrcywgc2FtcGxlU2l6ZSkgOiB0aGlzLnRpY2tzKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmUoKTtcbiAgICAgICAgdGhpcy5iZWZvcmVDYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCk7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpO1xuICAgICAgICB0aGlzLmFmdGVyQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpO1xuICAgICAgICBpZiAodGlja09wdHMuZGlzcGxheSAmJiAodGlja09wdHMuYXV0b1NraXAgfHwgdGlja09wdHMuc291cmNlID09PSAnYXV0bycpKSB7XG4gICAgICAgICAgICB0aGlzLnRpY2tzID0gYXV0b1NraXAodGhpcywgdGhpcy50aWNrcyk7XG4gICAgICAgICAgICB0aGlzLl9sYWJlbFNpemVzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuYWZ0ZXJBdXRvU2tpcCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzYW1wbGluZ0VuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnZlcnRUaWNrc1RvTGFiZWxzKHRoaXMudGlja3MpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYmVmb3JlRml0KCk7XG4gICAgICAgIHRoaXMuZml0KCk7XG4gICAgICAgIHRoaXMuYWZ0ZXJGaXQoKTtcbiAgICAgICAgdGhpcy5hZnRlclVwZGF0ZSgpO1xuICAgIH1cbiBjb25maWd1cmUoKSB7XG4gICAgICAgIGxldCByZXZlcnNlUGl4ZWxzID0gdGhpcy5vcHRpb25zLnJldmVyc2U7XG4gICAgICAgIGxldCBzdGFydFBpeGVsLCBlbmRQaXhlbDtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIHN0YXJ0UGl4ZWwgPSB0aGlzLmxlZnQ7XG4gICAgICAgICAgICBlbmRQaXhlbCA9IHRoaXMucmlnaHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGFydFBpeGVsID0gdGhpcy50b3A7XG4gICAgICAgICAgICBlbmRQaXhlbCA9IHRoaXMuYm90dG9tO1xuICAgICAgICAgICAgcmV2ZXJzZVBpeGVscyA9ICFyZXZlcnNlUGl4ZWxzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3N0YXJ0UGl4ZWwgPSBzdGFydFBpeGVsO1xuICAgICAgICB0aGlzLl9lbmRQaXhlbCA9IGVuZFBpeGVsO1xuICAgICAgICB0aGlzLl9yZXZlcnNlUGl4ZWxzID0gcmV2ZXJzZVBpeGVscztcbiAgICAgICAgdGhpcy5fbGVuZ3RoID0gZW5kUGl4ZWwgLSBzdGFydFBpeGVsO1xuICAgICAgICB0aGlzLl9hbGlnblRvUGl4ZWxzID0gdGhpcy5vcHRpb25zLmFsaWduVG9QaXhlbHM7XG4gICAgfVxuICAgIGFmdGVyVXBkYXRlKCkge1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYWZ0ZXJVcGRhdGUsIFtcbiAgICAgICAgICAgIHRoaXNcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIGJlZm9yZVNldERpbWVuc2lvbnMoKSB7XG4gICAgICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5iZWZvcmVTZXREaW1lbnNpb25zLCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBzZXREaW1lbnNpb25zKCkge1xuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMubWF4V2lkdGg7XG4gICAgICAgICAgICB0aGlzLmxlZnQgPSAwO1xuICAgICAgICAgICAgdGhpcy5yaWdodCA9IHRoaXMud2lkdGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmhlaWdodCA9IHRoaXMubWF4SGVpZ2h0O1xuICAgICAgICAgICAgdGhpcy50b3AgPSAwO1xuICAgICAgICAgICAgdGhpcy5ib3R0b20gPSB0aGlzLmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBhZGRpbmdMZWZ0ID0gMDtcbiAgICAgICAgdGhpcy5wYWRkaW5nVG9wID0gMDtcbiAgICAgICAgdGhpcy5wYWRkaW5nUmlnaHQgPSAwO1xuICAgICAgICB0aGlzLnBhZGRpbmdCb3R0b20gPSAwO1xuICAgIH1cbiAgICBhZnRlclNldERpbWVuc2lvbnMoKSB7XG4gICAgICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlclNldERpbWVuc2lvbnMsIFtcbiAgICAgICAgICAgIHRoaXNcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIF9jYWxsSG9va3MobmFtZSkge1xuICAgICAgICB0aGlzLmNoYXJ0Lm5vdGlmeVBsdWdpbnMobmFtZSwgdGhpcy5nZXRDb250ZXh0KCkpO1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnNbbmFtZV0sIFtcbiAgICAgICAgICAgIHRoaXNcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIGJlZm9yZURhdGFMaW1pdHMoKSB7XG4gICAgICAgIHRoaXMuX2NhbGxIb29rcygnYmVmb3JlRGF0YUxpbWl0cycpO1xuICAgIH1cbiAgICBkZXRlcm1pbmVEYXRhTGltaXRzKCkge31cbiAgICBhZnRlckRhdGFMaW1pdHMoKSB7XG4gICAgICAgIHRoaXMuX2NhbGxIb29rcygnYWZ0ZXJEYXRhTGltaXRzJyk7XG4gICAgfVxuICAgIGJlZm9yZUJ1aWxkVGlja3MoKSB7XG4gICAgICAgIHRoaXMuX2NhbGxIb29rcygnYmVmb3JlQnVpbGRUaWNrcycpO1xuICAgIH1cbiBidWlsZFRpY2tzKCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGFmdGVyQnVpbGRUaWNrcygpIHtcbiAgICAgICAgdGhpcy5fY2FsbEhvb2tzKCdhZnRlckJ1aWxkVGlja3MnKTtcbiAgICB9XG4gICAgYmVmb3JlVGlja1RvTGFiZWxDb252ZXJzaW9uKCkge1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlVGlja1RvTGFiZWxDb252ZXJzaW9uLCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiBnZW5lcmF0ZVRpY2tMYWJlbHModGlja3MpIHtcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSB0aGlzLm9wdGlvbnMudGlja3M7XG4gICAgICAgIGxldCBpLCBpbGVuLCB0aWNrO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspe1xuICAgICAgICAgICAgdGljayA9IHRpY2tzW2ldO1xuICAgICAgICAgICAgdGljay5sYWJlbCA9IGNhbGxiYWNrKHRpY2tPcHRzLmNhbGxiYWNrLCBbXG4gICAgICAgICAgICAgICAgdGljay52YWx1ZSxcbiAgICAgICAgICAgICAgICBpLFxuICAgICAgICAgICAgICAgIHRpY2tzXG4gICAgICAgICAgICBdLCB0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhZnRlclRpY2tUb0xhYmVsQ29udmVyc2lvbigpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmFmdGVyVGlja1RvTGFiZWxDb252ZXJzaW9uLCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBiZWZvcmVDYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCkge1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbiwgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gICAgY2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSBvcHRpb25zLnRpY2tzO1xuICAgICAgICBjb25zdCBudW1UaWNrcyA9IGdldFRpY2tzTGltaXQodGhpcy50aWNrcy5sZW5ndGgsIG9wdGlvbnMudGlja3MubWF4VGlja3NMaW1pdCk7XG4gICAgICAgIGNvbnN0IG1pblJvdGF0aW9uID0gdGlja09wdHMubWluUm90YXRpb24gfHwgMDtcbiAgICAgICAgY29uc3QgbWF4Um90YXRpb24gPSB0aWNrT3B0cy5tYXhSb3RhdGlvbjtcbiAgICAgICAgbGV0IGxhYmVsUm90YXRpb24gPSBtaW5Sb3RhdGlvbjtcbiAgICAgICAgbGV0IHRpY2tXaWR0aCwgbWF4SGVpZ2h0LCBtYXhMYWJlbERpYWdvbmFsO1xuICAgICAgICBpZiAoIXRoaXMuX2lzVmlzaWJsZSgpIHx8ICF0aWNrT3B0cy5kaXNwbGF5IHx8IG1pblJvdGF0aW9uID49IG1heFJvdGF0aW9uIHx8IG51bVRpY2tzIDw9IDEgfHwgIXRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIHRoaXMubGFiZWxSb3RhdGlvbiA9IG1pblJvdGF0aW9uO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxhYmVsU2l6ZXMgPSB0aGlzLl9nZXRMYWJlbFNpemVzKCk7XG4gICAgICAgIGNvbnN0IG1heExhYmVsV2lkdGggPSBsYWJlbFNpemVzLndpZGVzdC53aWR0aDtcbiAgICAgICAgY29uc3QgbWF4TGFiZWxIZWlnaHQgPSBsYWJlbFNpemVzLmhpZ2hlc3QuaGVpZ2h0O1xuICAgICAgICBjb25zdCBtYXhXaWR0aCA9IF9saW1pdFZhbHVlKHRoaXMuY2hhcnQud2lkdGggLSBtYXhMYWJlbFdpZHRoLCAwLCB0aGlzLm1heFdpZHRoKTtcbiAgICAgICAgdGlja1dpZHRoID0gb3B0aW9ucy5vZmZzZXQgPyB0aGlzLm1heFdpZHRoIC8gbnVtVGlja3MgOiBtYXhXaWR0aCAvIChudW1UaWNrcyAtIDEpO1xuICAgICAgICBpZiAobWF4TGFiZWxXaWR0aCArIDYgPiB0aWNrV2lkdGgpIHtcbiAgICAgICAgICAgIHRpY2tXaWR0aCA9IG1heFdpZHRoIC8gKG51bVRpY2tzIC0gKG9wdGlvbnMub2Zmc2V0ID8gMC41IDogMSkpO1xuICAgICAgICAgICAgbWF4SGVpZ2h0ID0gdGhpcy5tYXhIZWlnaHQgLSBnZXRUaWNrTWFya0xlbmd0aChvcHRpb25zLmdyaWQpIC0gdGlja09wdHMucGFkZGluZyAtIGdldFRpdGxlSGVpZ2h0KG9wdGlvbnMudGl0bGUsIHRoaXMuY2hhcnQub3B0aW9ucy5mb250KTtcbiAgICAgICAgICAgIG1heExhYmVsRGlhZ29uYWwgPSBNYXRoLnNxcnQobWF4TGFiZWxXaWR0aCAqIG1heExhYmVsV2lkdGggKyBtYXhMYWJlbEhlaWdodCAqIG1heExhYmVsSGVpZ2h0KTtcbiAgICAgICAgICAgIGxhYmVsUm90YXRpb24gPSB0b0RlZ3JlZXMoTWF0aC5taW4oTWF0aC5hc2luKF9saW1pdFZhbHVlKChsYWJlbFNpemVzLmhpZ2hlc3QuaGVpZ2h0ICsgNikgLyB0aWNrV2lkdGgsIC0xLCAxKSksIE1hdGguYXNpbihfbGltaXRWYWx1ZShtYXhIZWlnaHQgLyBtYXhMYWJlbERpYWdvbmFsLCAtMSwgMSkpIC0gTWF0aC5hc2luKF9saW1pdFZhbHVlKG1heExhYmVsSGVpZ2h0IC8gbWF4TGFiZWxEaWFnb25hbCwgLTEsIDEpKSkpO1xuICAgICAgICAgICAgbGFiZWxSb3RhdGlvbiA9IE1hdGgubWF4KG1pblJvdGF0aW9uLCBNYXRoLm1pbihtYXhSb3RhdGlvbiwgbGFiZWxSb3RhdGlvbikpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubGFiZWxSb3RhdGlvbiA9IGxhYmVsUm90YXRpb247XG4gICAgfVxuICAgIGFmdGVyQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmFmdGVyQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbiwgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gICAgYWZ0ZXJBdXRvU2tpcCgpIHt9XG4gICAgYmVmb3JlRml0KCkge1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlRml0LCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBmaXQoKSB7XG4gICAgICAgIGNvbnN0IG1pblNpemUgPSB7XG4gICAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICAgIGhlaWdodDogMFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB7IGNoYXJ0ICwgb3B0aW9uczogeyB0aWNrczogdGlja09wdHMgLCB0aXRsZTogdGl0bGVPcHRzICwgZ3JpZDogZ3JpZE9wdHMgIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBkaXNwbGF5ID0gdGhpcy5faXNWaXNpYmxlKCk7XG4gICAgICAgIGNvbnN0IGlzSG9yaXpvbnRhbCA9IHRoaXMuaXNIb3Jpem9udGFsKCk7XG4gICAgICAgIGlmIChkaXNwbGF5KSB7XG4gICAgICAgICAgICBjb25zdCB0aXRsZUhlaWdodCA9IGdldFRpdGxlSGVpZ2h0KHRpdGxlT3B0cywgY2hhcnQub3B0aW9ucy5mb250KTtcbiAgICAgICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICBtaW5TaXplLndpZHRoID0gdGhpcy5tYXhXaWR0aDtcbiAgICAgICAgICAgICAgICBtaW5TaXplLmhlaWdodCA9IGdldFRpY2tNYXJrTGVuZ3RoKGdyaWRPcHRzKSArIHRpdGxlSGVpZ2h0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtaW5TaXplLmhlaWdodCA9IHRoaXMubWF4SGVpZ2h0O1xuICAgICAgICAgICAgICAgIG1pblNpemUud2lkdGggPSBnZXRUaWNrTWFya0xlbmd0aChncmlkT3B0cykgKyB0aXRsZUhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aWNrT3B0cy5kaXNwbGF5ICYmIHRoaXMudGlja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBmaXJzdCAsIGxhc3QgLCB3aWRlc3QgLCBoaWdoZXN0ICB9ID0gdGhpcy5fZ2V0TGFiZWxTaXplcygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRpY2tQYWRkaW5nID0gdGlja09wdHMucGFkZGluZyAqIDI7XG4gICAgICAgICAgICAgICAgY29uc3QgYW5nbGVSYWRpYW5zID0gdG9SYWRpYW5zKHRoaXMubGFiZWxSb3RhdGlvbik7XG4gICAgICAgICAgICAgICAgY29uc3QgY29zID0gTWF0aC5jb3MoYW5nbGVSYWRpYW5zKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzaW4gPSBNYXRoLnNpbihhbmdsZVJhZGlhbnMpO1xuICAgICAgICAgICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFiZWxIZWlnaHQgPSB0aWNrT3B0cy5taXJyb3IgPyAwIDogc2luICogd2lkZXN0LndpZHRoICsgY29zICogaGlnaGVzdC5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIG1pblNpemUuaGVpZ2h0ID0gTWF0aC5taW4odGhpcy5tYXhIZWlnaHQsIG1pblNpemUuaGVpZ2h0ICsgbGFiZWxIZWlnaHQgKyB0aWNrUGFkZGluZyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFiZWxXaWR0aCA9IHRpY2tPcHRzLm1pcnJvciA/IDAgOiBjb3MgKiB3aWRlc3Qud2lkdGggKyBzaW4gKiBoaWdoZXN0LmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgbWluU2l6ZS53aWR0aCA9IE1hdGgubWluKHRoaXMubWF4V2lkdGgsIG1pblNpemUud2lkdGggKyBsYWJlbFdpZHRoICsgdGlja1BhZGRpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9jYWxjdWxhdGVQYWRkaW5nKGZpcnN0LCBsYXN0LCBzaW4sIGNvcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5faGFuZGxlTWFyZ2lucygpO1xuICAgICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gdGhpcy5fbGVuZ3RoID0gY2hhcnQud2lkdGggLSB0aGlzLl9tYXJnaW5zLmxlZnQgLSB0aGlzLl9tYXJnaW5zLnJpZ2h0O1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBtaW5TaXplLmhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSBtaW5TaXplLndpZHRoO1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLl9sZW5ndGggPSBjaGFydC5oZWlnaHQgLSB0aGlzLl9tYXJnaW5zLnRvcCAtIHRoaXMuX21hcmdpbnMuYm90dG9tO1xuICAgICAgICB9XG4gICAgfVxuICAgIF9jYWxjdWxhdGVQYWRkaW5nKGZpcnN0LCBsYXN0LCBzaW4sIGNvcykge1xuICAgICAgICBjb25zdCB7IHRpY2tzOiB7IGFsaWduICwgcGFkZGluZyAgfSAsIHBvc2l0aW9uICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBpc1JvdGF0ZWQgPSB0aGlzLmxhYmVsUm90YXRpb24gIT09IDA7XG4gICAgICAgIGNvbnN0IGxhYmVsc0JlbG93VGlja3MgPSBwb3NpdGlvbiAhPT0gJ3RvcCcgJiYgdGhpcy5heGlzID09PSAneCc7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXRMZWZ0ID0gdGhpcy5nZXRQaXhlbEZvclRpY2soMCkgLSB0aGlzLmxlZnQ7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXRSaWdodCA9IHRoaXMucmlnaHQgLSB0aGlzLmdldFBpeGVsRm9yVGljayh0aGlzLnRpY2tzLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgbGV0IHBhZGRpbmdMZWZ0ID0gMDtcbiAgICAgICAgICAgIGxldCBwYWRkaW5nUmlnaHQgPSAwO1xuICAgICAgICAgICAgaWYgKGlzUm90YXRlZCkge1xuICAgICAgICAgICAgICAgIGlmIChsYWJlbHNCZWxvd1RpY2tzKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhZGRpbmdMZWZ0ID0gY29zICogZmlyc3Qud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIHBhZGRpbmdSaWdodCA9IHNpbiAqIGxhc3QuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBhZGRpbmdMZWZ0ID0gc2luICogZmlyc3QuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nUmlnaHQgPSBjb3MgKiBsYXN0LndpZHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYWxpZ24gPT09ICdzdGFydCcpIHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nUmlnaHQgPSBsYXN0LndpZHRoO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhbGlnbiA9PT0gJ2VuZCcpIHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nTGVmdCA9IGZpcnN0LndpZHRoO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhbGlnbiAhPT0gJ2lubmVyJykge1xuICAgICAgICAgICAgICAgIHBhZGRpbmdMZWZ0ID0gZmlyc3Qud2lkdGggLyAyO1xuICAgICAgICAgICAgICAgIHBhZGRpbmdSaWdodCA9IGxhc3Qud2lkdGggLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wYWRkaW5nTGVmdCA9IE1hdGgubWF4KChwYWRkaW5nTGVmdCAtIG9mZnNldExlZnQgKyBwYWRkaW5nKSAqIHRoaXMud2lkdGggLyAodGhpcy53aWR0aCAtIG9mZnNldExlZnQpLCAwKTtcbiAgICAgICAgICAgIHRoaXMucGFkZGluZ1JpZ2h0ID0gTWF0aC5tYXgoKHBhZGRpbmdSaWdodCAtIG9mZnNldFJpZ2h0ICsgcGFkZGluZykgKiB0aGlzLndpZHRoIC8gKHRoaXMud2lkdGggLSBvZmZzZXRSaWdodCksIDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IHBhZGRpbmdUb3AgPSBsYXN0LmhlaWdodCAvIDI7XG4gICAgICAgICAgICBsZXQgcGFkZGluZ0JvdHRvbSA9IGZpcnN0LmhlaWdodCAvIDI7XG4gICAgICAgICAgICBpZiAoYWxpZ24gPT09ICdzdGFydCcpIHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nVG9wID0gMDtcbiAgICAgICAgICAgICAgICBwYWRkaW5nQm90dG9tID0gZmlyc3QuaGVpZ2h0O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhbGlnbiA9PT0gJ2VuZCcpIHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nVG9wID0gbGFzdC5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgcGFkZGluZ0JvdHRvbSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnBhZGRpbmdUb3AgPSBwYWRkaW5nVG9wICsgcGFkZGluZztcbiAgICAgICAgICAgIHRoaXMucGFkZGluZ0JvdHRvbSA9IHBhZGRpbmdCb3R0b20gKyBwYWRkaW5nO1xuICAgICAgICB9XG4gICAgfVxuIF9oYW5kbGVNYXJnaW5zKCkge1xuICAgICAgICBpZiAodGhpcy5fbWFyZ2lucykge1xuICAgICAgICAgICAgdGhpcy5fbWFyZ2lucy5sZWZ0ID0gTWF0aC5tYXgodGhpcy5wYWRkaW5nTGVmdCwgdGhpcy5fbWFyZ2lucy5sZWZ0KTtcbiAgICAgICAgICAgIHRoaXMuX21hcmdpbnMudG9wID0gTWF0aC5tYXgodGhpcy5wYWRkaW5nVG9wLCB0aGlzLl9tYXJnaW5zLnRvcCk7XG4gICAgICAgICAgICB0aGlzLl9tYXJnaW5zLnJpZ2h0ID0gTWF0aC5tYXgodGhpcy5wYWRkaW5nUmlnaHQsIHRoaXMuX21hcmdpbnMucmlnaHQpO1xuICAgICAgICAgICAgdGhpcy5fbWFyZ2lucy5ib3R0b20gPSBNYXRoLm1heCh0aGlzLnBhZGRpbmdCb3R0b20sIHRoaXMuX21hcmdpbnMuYm90dG9tKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhZnRlckZpdCgpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmFmdGVyRml0LCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiBpc0hvcml6b250YWwoKSB7XG4gICAgICAgIGNvbnN0IHsgYXhpcyAsIHBvc2l0aW9uICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICByZXR1cm4gcG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJyB8fCBheGlzID09PSAneCc7XG4gICAgfVxuIGlzRnVsbFNpemUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMuZnVsbFNpemU7XG4gICAgfVxuIF9jb252ZXJ0VGlja3NUb0xhYmVscyh0aWNrcykge1xuICAgICAgICB0aGlzLmJlZm9yZVRpY2tUb0xhYmVsQ29udmVyc2lvbigpO1xuICAgICAgICB0aGlzLmdlbmVyYXRlVGlja0xhYmVscyh0aWNrcyk7XG4gICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspe1xuICAgICAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWYodGlja3NbaV0ubGFiZWwpKSB7XG4gICAgICAgICAgICAgICAgdGlja3Muc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgIGlsZW4tLTtcbiAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZnRlclRpY2tUb0xhYmVsQ29udmVyc2lvbigpO1xuICAgIH1cbiBfZ2V0TGFiZWxTaXplcygpIHtcbiAgICAgICAgbGV0IGxhYmVsU2l6ZXMgPSB0aGlzLl9sYWJlbFNpemVzO1xuICAgICAgICBpZiAoIWxhYmVsU2l6ZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHNhbXBsZVNpemUgPSB0aGlzLm9wdGlvbnMudGlja3Muc2FtcGxlU2l6ZTtcbiAgICAgICAgICAgIGxldCB0aWNrcyA9IHRoaXMudGlja3M7XG4gICAgICAgICAgICBpZiAoc2FtcGxlU2l6ZSA8IHRpY2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRpY2tzID0gc2FtcGxlKHRpY2tzLCBzYW1wbGVTaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2xhYmVsU2l6ZXMgPSBsYWJlbFNpemVzID0gdGhpcy5fY29tcHV0ZUxhYmVsU2l6ZXModGlja3MsIHRpY2tzLmxlbmd0aCwgdGhpcy5vcHRpb25zLnRpY2tzLm1heFRpY2tzTGltaXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsYWJlbFNpemVzO1xuICAgIH1cbiBfY29tcHV0ZUxhYmVsU2l6ZXModGlja3MsIGxlbmd0aCwgbWF4VGlja3NMaW1pdCkge1xuICAgICAgICBjb25zdCB7IGN0eCAsIF9sb25nZXN0VGV4dENhY2hlOiBjYWNoZXMgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB3aWR0aHMgPSBbXTtcbiAgICAgICAgY29uc3QgaGVpZ2h0cyA9IFtdO1xuICAgICAgICBjb25zdCBpbmNyZW1lbnQgPSBNYXRoLmZsb29yKGxlbmd0aCAvIGdldFRpY2tzTGltaXQobGVuZ3RoLCBtYXhUaWNrc0xpbWl0KSk7XG4gICAgICAgIGxldCB3aWRlc3RMYWJlbFNpemUgPSAwO1xuICAgICAgICBsZXQgaGlnaGVzdExhYmVsU2l6ZSA9IDA7XG4gICAgICAgIGxldCBpLCBqLCBqbGVuLCBsYWJlbCwgdGlja0ZvbnQsIGZvbnRTdHJpbmcsIGNhY2hlLCBsaW5lSGVpZ2h0LCB3aWR0aCwgaGVpZ2h0LCBuZXN0ZWRMYWJlbDtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IGluY3JlbWVudCl7XG4gICAgICAgICAgICBsYWJlbCA9IHRpY2tzW2ldLmxhYmVsO1xuICAgICAgICAgICAgdGlja0ZvbnQgPSB0aGlzLl9yZXNvbHZlVGlja0ZvbnRPcHRpb25zKGkpO1xuICAgICAgICAgICAgY3R4LmZvbnQgPSBmb250U3RyaW5nID0gdGlja0ZvbnQuc3RyaW5nO1xuICAgICAgICAgICAgY2FjaGUgPSBjYWNoZXNbZm9udFN0cmluZ10gPSBjYWNoZXNbZm9udFN0cmluZ10gfHwge1xuICAgICAgICAgICAgICAgIGRhdGE6IHt9LFxuICAgICAgICAgICAgICAgIGdjOiBbXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGxpbmVIZWlnaHQgPSB0aWNrRm9udC5saW5lSGVpZ2h0O1xuICAgICAgICAgICAgd2lkdGggPSBoZWlnaHQgPSAwO1xuICAgICAgICAgICAgaWYgKCFpc051bGxPclVuZGVmKGxhYmVsKSAmJiAhaXNBcnJheShsYWJlbCkpIHtcbiAgICAgICAgICAgICAgICB3aWR0aCA9IF9tZWFzdXJlVGV4dChjdHgsIGNhY2hlLmRhdGEsIGNhY2hlLmdjLCB3aWR0aCwgbGFiZWwpO1xuICAgICAgICAgICAgICAgIGhlaWdodCA9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkobGFiZWwpKSB7XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwLCBqbGVuID0gbGFiZWwubGVuZ3RoOyBqIDwgamxlbjsgKytqKXtcbiAgICAgICAgICAgICAgICAgICAgbmVzdGVkTGFiZWwgPSAgbGFiZWxbal07XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNOdWxsT3JVbmRlZihuZXN0ZWRMYWJlbCkgJiYgIWlzQXJyYXkobmVzdGVkTGFiZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IF9tZWFzdXJlVGV4dChjdHgsIGNhY2hlLmRhdGEsIGNhY2hlLmdjLCB3aWR0aCwgbmVzdGVkTGFiZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aWR0aHMucHVzaCh3aWR0aCk7XG4gICAgICAgICAgICBoZWlnaHRzLnB1c2goaGVpZ2h0KTtcbiAgICAgICAgICAgIHdpZGVzdExhYmVsU2l6ZSA9IE1hdGgubWF4KHdpZHRoLCB3aWRlc3RMYWJlbFNpemUpO1xuICAgICAgICAgICAgaGlnaGVzdExhYmVsU2l6ZSA9IE1hdGgubWF4KGhlaWdodCwgaGlnaGVzdExhYmVsU2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2FyYmFnZUNvbGxlY3QoY2FjaGVzLCBsZW5ndGgpO1xuICAgICAgICBjb25zdCB3aWRlc3QgPSB3aWR0aHMuaW5kZXhPZih3aWRlc3RMYWJlbFNpemUpO1xuICAgICAgICBjb25zdCBoaWdoZXN0ID0gaGVpZ2h0cy5pbmRleE9mKGhpZ2hlc3RMYWJlbFNpemUpO1xuICAgICAgICBjb25zdCB2YWx1ZUF0ID0gKGlkeCk9Pih7XG4gICAgICAgICAgICAgICAgd2lkdGg6IHdpZHRoc1tpZHhdIHx8IDAsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHRzW2lkeF0gfHwgMFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBmaXJzdDogdmFsdWVBdCgwKSxcbiAgICAgICAgICAgIGxhc3Q6IHZhbHVlQXQobGVuZ3RoIC0gMSksXG4gICAgICAgICAgICB3aWRlc3Q6IHZhbHVlQXQod2lkZXN0KSxcbiAgICAgICAgICAgIGhpZ2hlc3Q6IHZhbHVlQXQoaGlnaGVzdCksXG4gICAgICAgICAgICB3aWR0aHMsXG4gICAgICAgICAgICBoZWlnaHRzXG4gICAgICAgIH07XG4gICAgfVxuIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiBnZXRQaXhlbEZvclZhbHVlKHZhbHVlLCBpbmRleCkge1xuICAgICAgICByZXR1cm4gTmFOO1xuICAgIH1cbiBnZXRWYWx1ZUZvclBpeGVsKHBpeGVsKSB7fVxuIGdldFBpeGVsRm9yVGljayhpbmRleCkge1xuICAgICAgICBjb25zdCB0aWNrcyA9IHRoaXMudGlja3M7XG4gICAgICAgIGlmIChpbmRleCA8IDAgfHwgaW5kZXggPiB0aWNrcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRQaXhlbEZvclZhbHVlKHRpY2tzW2luZGV4XS52YWx1ZSk7XG4gICAgfVxuIGdldFBpeGVsRm9yRGVjaW1hbChkZWNpbWFsKSB7XG4gICAgICAgIGlmICh0aGlzLl9yZXZlcnNlUGl4ZWxzKSB7XG4gICAgICAgICAgICBkZWNpbWFsID0gMSAtIGRlY2ltYWw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGl4ZWwgPSB0aGlzLl9zdGFydFBpeGVsICsgZGVjaW1hbCAqIHRoaXMuX2xlbmd0aDtcbiAgICAgICAgcmV0dXJuIF9pbnQxNlJhbmdlKHRoaXMuX2FsaWduVG9QaXhlbHMgPyBfYWxpZ25QaXhlbCh0aGlzLmNoYXJ0LCBwaXhlbCwgMCkgOiBwaXhlbCk7XG4gICAgfVxuIGdldERlY2ltYWxGb3JQaXhlbChwaXhlbCkge1xuICAgICAgICBjb25zdCBkZWNpbWFsID0gKHBpeGVsIC0gdGhpcy5fc3RhcnRQaXhlbCkgLyB0aGlzLl9sZW5ndGg7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXZlcnNlUGl4ZWxzID8gMSAtIGRlY2ltYWwgOiBkZWNpbWFsO1xuICAgIH1cbiBnZXRCYXNlUGl4ZWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBpeGVsRm9yVmFsdWUodGhpcy5nZXRCYXNlVmFsdWUoKSk7XG4gICAgfVxuIGdldEJhc2VWYWx1ZSgpIHtcbiAgICAgICAgY29uc3QgeyBtaW4gLCBtYXggIH0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gbWluIDwgMCAmJiBtYXggPCAwID8gbWF4IDogbWluID4gMCAmJiBtYXggPiAwID8gbWluIDogMDtcbiAgICB9XG4gZ2V0Q29udGV4dChpbmRleCkge1xuICAgICAgICBjb25zdCB0aWNrcyA9IHRoaXMudGlja3MgfHwgW107XG4gICAgICAgIGlmIChpbmRleCA+PSAwICYmIGluZGV4IDwgdGlja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCB0aWNrID0gdGlja3NbaW5kZXhdO1xuICAgICAgICAgICAgcmV0dXJuIHRpY2suJGNvbnRleHQgfHwgKHRpY2suJGNvbnRleHQgPSBjcmVhdGVUaWNrQ29udGV4dCh0aGlzLmdldENvbnRleHQoKSwgaW5kZXgsIHRpY2spKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy4kY29udGV4dCB8fCAodGhpcy4kY29udGV4dCA9IGNyZWF0ZVNjYWxlQ29udGV4dCh0aGlzLmNoYXJ0LmdldENvbnRleHQoKSwgdGhpcykpO1xuICAgIH1cbiBfdGlja1NpemUoKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvblRpY2tzID0gdGhpcy5vcHRpb25zLnRpY2tzO1xuICAgICAgICBjb25zdCByb3QgPSB0b1JhZGlhbnModGhpcy5sYWJlbFJvdGF0aW9uKTtcbiAgICAgICAgY29uc3QgY29zID0gTWF0aC5hYnMoTWF0aC5jb3Mocm90KSk7XG4gICAgICAgIGNvbnN0IHNpbiA9IE1hdGguYWJzKE1hdGguc2luKHJvdCkpO1xuICAgICAgICBjb25zdCBsYWJlbFNpemVzID0gdGhpcy5fZ2V0TGFiZWxTaXplcygpO1xuICAgICAgICBjb25zdCBwYWRkaW5nID0gb3B0aW9uVGlja3MuYXV0b1NraXBQYWRkaW5nIHx8IDA7XG4gICAgICAgIGNvbnN0IHcgPSBsYWJlbFNpemVzID8gbGFiZWxTaXplcy53aWRlc3Qud2lkdGggKyBwYWRkaW5nIDogMDtcbiAgICAgICAgY29uc3QgaCA9IGxhYmVsU2l6ZXMgPyBsYWJlbFNpemVzLmhpZ2hlc3QuaGVpZ2h0ICsgcGFkZGluZyA6IDA7XG4gICAgICAgIHJldHVybiB0aGlzLmlzSG9yaXpvbnRhbCgpID8gaCAqIGNvcyA+IHcgKiBzaW4gPyB3IC8gY29zIDogaCAvIHNpbiA6IGggKiBzaW4gPCB3ICogY29zID8gaCAvIGNvcyA6IHcgLyBzaW47XG4gICAgfVxuIF9pc1Zpc2libGUoKSB7XG4gICAgICAgIGNvbnN0IGRpc3BsYXkgPSB0aGlzLm9wdGlvbnMuZGlzcGxheTtcbiAgICAgICAgaWYgKGRpc3BsYXkgIT09ICdhdXRvJykge1xuICAgICAgICAgICAgcmV0dXJuICEhZGlzcGxheTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRNYXRjaGluZ1Zpc2libGVNZXRhcygpLmxlbmd0aCA+IDA7XG4gICAgfVxuIF9jb21wdXRlR3JpZExpbmVJdGVtcyhjaGFydEFyZWEpIHtcbiAgICAgICAgY29uc3QgYXhpcyA9IHRoaXMuYXhpcztcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB7IGdyaWQgLCBwb3NpdGlvbiAsIGJvcmRlciAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IGdyaWQub2Zmc2V0O1xuICAgICAgICBjb25zdCBpc0hvcml6b250YWwgPSB0aGlzLmlzSG9yaXpvbnRhbCgpO1xuICAgICAgICBjb25zdCB0aWNrcyA9IHRoaXMudGlja3M7XG4gICAgICAgIGNvbnN0IHRpY2tzTGVuZ3RoID0gdGlja3MubGVuZ3RoICsgKG9mZnNldCA/IDEgOiAwKTtcbiAgICAgICAgY29uc3QgdGwgPSBnZXRUaWNrTWFya0xlbmd0aChncmlkKTtcbiAgICAgICAgY29uc3QgaXRlbXMgPSBbXTtcbiAgICAgICAgY29uc3QgYm9yZGVyT3B0cyA9IGJvcmRlci5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgY29uc3QgYXhpc1dpZHRoID0gYm9yZGVyT3B0cy5kaXNwbGF5ID8gYm9yZGVyT3B0cy53aWR0aCA6IDA7XG4gICAgICAgIGNvbnN0IGF4aXNIYWxmV2lkdGggPSBheGlzV2lkdGggLyAyO1xuICAgICAgICBjb25zdCBhbGlnbkJvcmRlclZhbHVlID0gZnVuY3Rpb24ocGl4ZWwpIHtcbiAgICAgICAgICAgIHJldHVybiBfYWxpZ25QaXhlbChjaGFydCwgcGl4ZWwsIGF4aXNXaWR0aCk7XG4gICAgICAgIH07XG4gICAgICAgIGxldCBib3JkZXJWYWx1ZSwgaSwgbGluZVZhbHVlLCBhbGlnbmVkTGluZVZhbHVlO1xuICAgICAgICBsZXQgdHgxLCB0eTEsIHR4MiwgdHkyLCB4MSwgeTEsIHgyLCB5MjtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAndG9wJykge1xuICAgICAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKHRoaXMuYm90dG9tKTtcbiAgICAgICAgICAgIHR5MSA9IHRoaXMuYm90dG9tIC0gdGw7XG4gICAgICAgICAgICB0eTIgPSBib3JkZXJWYWx1ZSAtIGF4aXNIYWxmV2lkdGg7XG4gICAgICAgICAgICB5MSA9IGFsaWduQm9yZGVyVmFsdWUoY2hhcnRBcmVhLnRvcCkgKyBheGlzSGFsZldpZHRoO1xuICAgICAgICAgICAgeTIgPSBjaGFydEFyZWEuYm90dG9tO1xuICAgICAgICB9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAnYm90dG9tJykge1xuICAgICAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKHRoaXMudG9wKTtcbiAgICAgICAgICAgIHkxID0gY2hhcnRBcmVhLnRvcDtcbiAgICAgICAgICAgIHkyID0gYWxpZ25Cb3JkZXJWYWx1ZShjaGFydEFyZWEuYm90dG9tKSAtIGF4aXNIYWxmV2lkdGg7XG4gICAgICAgICAgICB0eTEgPSBib3JkZXJWYWx1ZSArIGF4aXNIYWxmV2lkdGg7XG4gICAgICAgICAgICB0eTIgPSB0aGlzLnRvcCArIHRsO1xuICAgICAgICB9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSh0aGlzLnJpZ2h0KTtcbiAgICAgICAgICAgIHR4MSA9IHRoaXMucmlnaHQgLSB0bDtcbiAgICAgICAgICAgIHR4MiA9IGJvcmRlclZhbHVlIC0gYXhpc0hhbGZXaWR0aDtcbiAgICAgICAgICAgIHgxID0gYWxpZ25Cb3JkZXJWYWx1ZShjaGFydEFyZWEubGVmdCkgKyBheGlzSGFsZldpZHRoO1xuICAgICAgICAgICAgeDIgPSBjaGFydEFyZWEucmlnaHQ7XG4gICAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSh0aGlzLmxlZnQpO1xuICAgICAgICAgICAgeDEgPSBjaGFydEFyZWEubGVmdDtcbiAgICAgICAgICAgIHgyID0gYWxpZ25Cb3JkZXJWYWx1ZShjaGFydEFyZWEucmlnaHQpIC0gYXhpc0hhbGZXaWR0aDtcbiAgICAgICAgICAgIHR4MSA9IGJvcmRlclZhbHVlICsgYXhpc0hhbGZXaWR0aDtcbiAgICAgICAgICAgIHR4MiA9IHRoaXMubGVmdCArIHRsO1xuICAgICAgICB9IGVsc2UgaWYgKGF4aXMgPT09ICd4Jykge1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSgoY2hhcnRBcmVhLnRvcCArIGNoYXJ0QXJlYS5ib3R0b20pIC8gMiArIDAuNSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcG9zaXRpb25bcG9zaXRpb25BeGlzSURdO1xuICAgICAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSh0aGlzLmNoYXJ0LnNjYWxlc1twb3NpdGlvbkF4aXNJRF0uZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeTEgPSBjaGFydEFyZWEudG9wO1xuICAgICAgICAgICAgeTIgPSBjaGFydEFyZWEuYm90dG9tO1xuICAgICAgICAgICAgdHkxID0gYm9yZGVyVmFsdWUgKyBheGlzSGFsZldpZHRoO1xuICAgICAgICAgICAgdHkyID0gdHkxICsgdGw7XG4gICAgICAgIH0gZWxzZSBpZiAoYXhpcyA9PT0gJ3knKSB7XG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKChjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS5yaWdodCkgLyAyKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocG9zaXRpb24pKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25BeGlzSUQgPSBPYmplY3Qua2V5cyhwb3NpdGlvbilbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICAgICAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKHRoaXMuY2hhcnQuc2NhbGVzW3Bvc2l0aW9uQXhpc0lEXS5nZXRQaXhlbEZvclZhbHVlKHZhbHVlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0eDEgPSBib3JkZXJWYWx1ZSAtIGF4aXNIYWxmV2lkdGg7XG4gICAgICAgICAgICB0eDIgPSB0eDEgLSB0bDtcbiAgICAgICAgICAgIHgxID0gY2hhcnRBcmVhLmxlZnQ7XG4gICAgICAgICAgICB4MiA9IGNoYXJ0QXJlYS5yaWdodDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsaW1pdCA9IHZhbHVlT3JEZWZhdWx0KG9wdGlvbnMudGlja3MubWF4VGlja3NMaW1pdCwgdGlja3NMZW5ndGgpO1xuICAgICAgICBjb25zdCBzdGVwID0gTWF0aC5tYXgoMSwgTWF0aC5jZWlsKHRpY2tzTGVuZ3RoIC8gbGltaXQpKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgdGlja3NMZW5ndGg7IGkgKz0gc3RlcCl7XG4gICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5nZXRDb250ZXh0KGkpO1xuICAgICAgICAgICAgY29uc3Qgb3B0c0F0SW5kZXggPSBncmlkLnNldENvbnRleHQoY29udGV4dCk7XG4gICAgICAgICAgICBjb25zdCBvcHRzQXRJbmRleEJvcmRlciA9IGJvcmRlci5zZXRDb250ZXh0KGNvbnRleHQpO1xuICAgICAgICAgICAgY29uc3QgbGluZVdpZHRoID0gb3B0c0F0SW5kZXgubGluZVdpZHRoO1xuICAgICAgICAgICAgY29uc3QgbGluZUNvbG9yID0gb3B0c0F0SW5kZXguY29sb3I7XG4gICAgICAgICAgICBjb25zdCBib3JkZXJEYXNoID0gb3B0c0F0SW5kZXhCb3JkZXIuZGFzaCB8fCBbXTtcbiAgICAgICAgICAgIGNvbnN0IGJvcmRlckRhc2hPZmZzZXQgPSBvcHRzQXRJbmRleEJvcmRlci5kYXNoT2Zmc2V0O1xuICAgICAgICAgICAgY29uc3QgdGlja1dpZHRoID0gb3B0c0F0SW5kZXgudGlja1dpZHRoO1xuICAgICAgICAgICAgY29uc3QgdGlja0NvbG9yID0gb3B0c0F0SW5kZXgudGlja0NvbG9yO1xuICAgICAgICAgICAgY29uc3QgdGlja0JvcmRlckRhc2ggPSBvcHRzQXRJbmRleC50aWNrQm9yZGVyRGFzaCB8fCBbXTtcbiAgICAgICAgICAgIGNvbnN0IHRpY2tCb3JkZXJEYXNoT2Zmc2V0ID0gb3B0c0F0SW5kZXgudGlja0JvcmRlckRhc2hPZmZzZXQ7XG4gICAgICAgICAgICBsaW5lVmFsdWUgPSBnZXRQaXhlbEZvckdyaWRMaW5lKHRoaXMsIGksIG9mZnNldCk7XG4gICAgICAgICAgICBpZiAobGluZVZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFsaWduZWRMaW5lVmFsdWUgPSBfYWxpZ25QaXhlbChjaGFydCwgbGluZVZhbHVlLCBsaW5lV2lkdGgpO1xuICAgICAgICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIHR4MSA9IHR4MiA9IHgxID0geDIgPSBhbGlnbmVkTGluZVZhbHVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0eTEgPSB0eTIgPSB5MSA9IHkyID0gYWxpZ25lZExpbmVWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGl0ZW1zLnB1c2goe1xuICAgICAgICAgICAgICAgIHR4MSxcbiAgICAgICAgICAgICAgICB0eTEsXG4gICAgICAgICAgICAgICAgdHgyLFxuICAgICAgICAgICAgICAgIHR5MixcbiAgICAgICAgICAgICAgICB4MSxcbiAgICAgICAgICAgICAgICB5MSxcbiAgICAgICAgICAgICAgICB4MixcbiAgICAgICAgICAgICAgICB5MixcbiAgICAgICAgICAgICAgICB3aWR0aDogbGluZVdpZHRoLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBsaW5lQ29sb3IsXG4gICAgICAgICAgICAgICAgYm9yZGVyRGFzaCxcbiAgICAgICAgICAgICAgICBib3JkZXJEYXNoT2Zmc2V0LFxuICAgICAgICAgICAgICAgIHRpY2tXaWR0aCxcbiAgICAgICAgICAgICAgICB0aWNrQ29sb3IsXG4gICAgICAgICAgICAgICAgdGlja0JvcmRlckRhc2gsXG4gICAgICAgICAgICAgICAgdGlja0JvcmRlckRhc2hPZmZzZXRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3RpY2tzTGVuZ3RoID0gdGlja3NMZW5ndGg7XG4gICAgICAgIHRoaXMuX2JvcmRlclZhbHVlID0gYm9yZGVyVmFsdWU7XG4gICAgICAgIHJldHVybiBpdGVtcztcbiAgICB9XG4gX2NvbXB1dGVMYWJlbEl0ZW1zKGNoYXJ0QXJlYSkge1xuICAgICAgICBjb25zdCBheGlzID0gdGhpcy5heGlzO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB7IHBvc2l0aW9uICwgdGlja3M6IG9wdGlvblRpY2tzICB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgaXNIb3Jpem9udGFsID0gdGhpcy5pc0hvcml6b250YWwoKTtcbiAgICAgICAgY29uc3QgdGlja3MgPSB0aGlzLnRpY2tzO1xuICAgICAgICBjb25zdCB7IGFsaWduICwgY3Jvc3NBbGlnbiAsIHBhZGRpbmcgLCBtaXJyb3IgIH0gPSBvcHRpb25UaWNrcztcbiAgICAgICAgY29uc3QgdGwgPSBnZXRUaWNrTWFya0xlbmd0aChvcHRpb25zLmdyaWQpO1xuICAgICAgICBjb25zdCB0aWNrQW5kUGFkZGluZyA9IHRsICsgcGFkZGluZztcbiAgICAgICAgY29uc3QgaFRpY2tBbmRQYWRkaW5nID0gbWlycm9yID8gLXBhZGRpbmcgOiB0aWNrQW5kUGFkZGluZztcbiAgICAgICAgY29uc3Qgcm90YXRpb24gPSAtdG9SYWRpYW5zKHRoaXMubGFiZWxSb3RhdGlvbik7XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gW107XG4gICAgICAgIGxldCBpLCBpbGVuLCB0aWNrLCBsYWJlbCwgeCwgeSwgdGV4dEFsaWduLCBwaXhlbCwgZm9udCwgbGluZUhlaWdodCwgbGluZUNvdW50LCB0ZXh0T2Zmc2V0O1xuICAgICAgICBsZXQgdGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgIHkgPSB0aGlzLmJvdHRvbSAtIGhUaWNrQW5kUGFkZGluZztcbiAgICAgICAgICAgIHRleHRBbGlnbiA9IHRoaXMuX2dldFhBeGlzTGFiZWxBbGlnbm1lbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICAgIHkgPSB0aGlzLnRvcCArIGhUaWNrQW5kUGFkZGluZztcbiAgICAgICAgICAgIHRleHRBbGlnbiA9IHRoaXMuX2dldFhBeGlzTGFiZWxBbGlnbm1lbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSB0aGlzLl9nZXRZQXhpc0xhYmVsQWxpZ25tZW50KHRsKTtcbiAgICAgICAgICAgIHRleHRBbGlnbiA9IHJldC50ZXh0QWxpZ247XG4gICAgICAgICAgICB4ID0gcmV0Lng7XG4gICAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IHRoaXMuX2dldFlBeGlzTGFiZWxBbGlnbm1lbnQodGwpO1xuICAgICAgICAgICAgdGV4dEFsaWduID0gcmV0LnRleHRBbGlnbjtcbiAgICAgICAgICAgIHggPSByZXQueDtcbiAgICAgICAgfSBlbHNlIGlmIChheGlzID09PSAneCcpIHtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgICAgICB5ID0gKGNoYXJ0QXJlYS50b3AgKyBjaGFydEFyZWEuYm90dG9tKSAvIDIgKyB0aWNrQW5kUGFkZGluZztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocG9zaXRpb24pKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25BeGlzSUQgPSBPYmplY3Qua2V5cyhwb3NpdGlvbilbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICAgICAgICAgICAgeSA9IHRoaXMuY2hhcnQuc2NhbGVzW3Bvc2l0aW9uQXhpc0lEXS5nZXRQaXhlbEZvclZhbHVlKHZhbHVlKSArIHRpY2tBbmRQYWRkaW5nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGV4dEFsaWduID0gdGhpcy5fZ2V0WEF4aXNMYWJlbEFsaWdubWVudCgpO1xuICAgICAgICB9IGVsc2UgaWYgKGF4aXMgPT09ICd5Jykge1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgIHggPSAoY2hhcnRBcmVhLmxlZnQgKyBjaGFydEFyZWEucmlnaHQpIC8gMiAtIHRpY2tBbmRQYWRkaW5nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChwb3NpdGlvbikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvbkF4aXNJRCA9IE9iamVjdC5rZXlzKHBvc2l0aW9uKVswXTtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW3Bvc2l0aW9uQXhpc0lEXTtcbiAgICAgICAgICAgICAgICB4ID0gdGhpcy5jaGFydC5zY2FsZXNbcG9zaXRpb25BeGlzSURdLmdldFBpeGVsRm9yVmFsdWUodmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGV4dEFsaWduID0gdGhpcy5fZ2V0WUF4aXNMYWJlbEFsaWdubWVudCh0bCkudGV4dEFsaWduO1xuICAgICAgICB9XG4gICAgICAgIGlmIChheGlzID09PSAneScpIHtcbiAgICAgICAgICAgIGlmIChhbGlnbiA9PT0gJ3N0YXJ0Jykge1xuICAgICAgICAgICAgICAgIHRleHRCYXNlbGluZSA9ICd0b3AnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhbGlnbiA9PT0gJ2VuZCcpIHtcbiAgICAgICAgICAgICAgICB0ZXh0QmFzZWxpbmUgPSAnYm90dG9tJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsYWJlbFNpemVzID0gdGhpcy5fZ2V0TGFiZWxTaXplcygpO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgdGljayA9IHRpY2tzW2ldO1xuICAgICAgICAgICAgbGFiZWwgPSB0aWNrLmxhYmVsO1xuICAgICAgICAgICAgY29uc3Qgb3B0c0F0SW5kZXggPSBvcHRpb25UaWNrcy5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dChpKSk7XG4gICAgICAgICAgICBwaXhlbCA9IHRoaXMuZ2V0UGl4ZWxGb3JUaWNrKGkpICsgb3B0aW9uVGlja3MubGFiZWxPZmZzZXQ7XG4gICAgICAgICAgICBmb250ID0gdGhpcy5fcmVzb2x2ZVRpY2tGb250T3B0aW9ucyhpKTtcbiAgICAgICAgICAgIGxpbmVIZWlnaHQgPSBmb250LmxpbmVIZWlnaHQ7XG4gICAgICAgICAgICBsaW5lQ291bnQgPSBpc0FycmF5KGxhYmVsKSA/IGxhYmVsLmxlbmd0aCA6IDE7XG4gICAgICAgICAgICBjb25zdCBoYWxmQ291bnQgPSBsaW5lQ291bnQgLyAyO1xuICAgICAgICAgICAgY29uc3QgY29sb3IgPSBvcHRzQXRJbmRleC5jb2xvcjtcbiAgICAgICAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gb3B0c0F0SW5kZXgudGV4dFN0cm9rZUNvbG9yO1xuICAgICAgICAgICAgY29uc3Qgc3Ryb2tlV2lkdGggPSBvcHRzQXRJbmRleC50ZXh0U3Ryb2tlV2lkdGg7XG4gICAgICAgICAgICBsZXQgdGlja1RleHRBbGlnbiA9IHRleHRBbGlnbjtcbiAgICAgICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICB4ID0gcGl4ZWw7XG4gICAgICAgICAgICAgICAgaWYgKHRleHRBbGlnbiA9PT0gJ2lubmVyJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSA9PT0gaWxlbiAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2tUZXh0QWxpZ24gPSAhdGhpcy5vcHRpb25zLnJldmVyc2UgPyAncmlnaHQnIDogJ2xlZnQnO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2tUZXh0QWxpZ24gPSAhdGhpcy5vcHRpb25zLnJldmVyc2UgPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGlja1RleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNyb3NzQWxpZ24gPT09ICduZWFyJyB8fCByb3RhdGlvbiAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dE9mZnNldCA9IC1saW5lQ291bnQgKiBsaW5lSGVpZ2h0ICsgbGluZUhlaWdodCAvIDI7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3Jvc3NBbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRPZmZzZXQgPSAtbGFiZWxTaXplcy5oaWdoZXN0LmhlaWdodCAvIDIgLSBoYWxmQ291bnQgKiBsaW5lSGVpZ2h0ICsgbGluZUhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRPZmZzZXQgPSAtbGFiZWxTaXplcy5oaWdoZXN0LmhlaWdodCArIGxpbmVIZWlnaHQgLyAyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNyb3NzQWxpZ24gPT09ICduZWFyJyB8fCByb3RhdGlvbiAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dE9mZnNldCA9IGxpbmVIZWlnaHQgLyAyO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNyb3NzQWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0T2Zmc2V0ID0gbGFiZWxTaXplcy5oaWdoZXN0LmhlaWdodCAvIDIgLSBoYWxmQ291bnQgKiBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dE9mZnNldCA9IGxhYmVsU2l6ZXMuaGlnaGVzdC5oZWlnaHQgLSBsaW5lQ291bnQgKiBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChtaXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dE9mZnNldCAqPSAtMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJvdGF0aW9uICE9PSAwICYmICFvcHRzQXRJbmRleC5zaG93TGFiZWxCYWNrZHJvcCkge1xuICAgICAgICAgICAgICAgICAgICB4ICs9IGxpbmVIZWlnaHQgLyAyICogTWF0aC5zaW4ocm90YXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeSA9IHBpeGVsO1xuICAgICAgICAgICAgICAgIHRleHRPZmZzZXQgPSAoMSAtIGxpbmVDb3VudCkgKiBsaW5lSGVpZ2h0IC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBiYWNrZHJvcDtcbiAgICAgICAgICAgIGlmIChvcHRzQXRJbmRleC5zaG93TGFiZWxCYWNrZHJvcCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhYmVsUGFkZGluZyA9IHRvUGFkZGluZyhvcHRzQXRJbmRleC5iYWNrZHJvcFBhZGRpbmcpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGxhYmVsU2l6ZXMuaGVpZ2h0c1tpXTtcbiAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IGxhYmVsU2l6ZXMud2lkdGhzW2ldO1xuICAgICAgICAgICAgICAgIGxldCB0b3AgPSB0ZXh0T2Zmc2V0IC0gbGFiZWxQYWRkaW5nLnRvcDtcbiAgICAgICAgICAgICAgICBsZXQgbGVmdCA9IDAgLSBsYWJlbFBhZGRpbmcubGVmdDtcbiAgICAgICAgICAgICAgICBzd2l0Y2godGV4dEJhc2VsaW5lKXtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWlkZGxlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcCAtPSBoZWlnaHQgLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgICAgICAgICAgICAgICAgICB0b3AgLT0gaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN3aXRjaCh0ZXh0QWxpZ24pe1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdjZW50ZXInOlxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCAtPSB3aWR0aCAvIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdpbm5lcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaSA9PT0gaWxlbiAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0IC09IHdpZHRoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgLT0gd2lkdGggLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJhY2tkcm9wID0ge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0LFxuICAgICAgICAgICAgICAgICAgICB0b3AsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiB3aWR0aCArIGxhYmVsUGFkZGluZy53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgKyBsYWJlbFBhZGRpbmcuaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICBjb2xvcjogb3B0c0F0SW5kZXguYmFja2Ryb3BDb2xvclxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpdGVtcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBsYWJlbCxcbiAgICAgICAgICAgICAgICBmb250LFxuICAgICAgICAgICAgICAgIHRleHRPZmZzZXQsXG4gICAgICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICByb3RhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZUNvbG9yLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2VXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduOiB0aWNrVGV4dEFsaWduLFxuICAgICAgICAgICAgICAgICAgICB0ZXh0QmFzZWxpbmUsXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0aW9uOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICB4LFxuICAgICAgICAgICAgICAgICAgICAgICAgeVxuICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgICAgICBiYWNrZHJvcFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpdGVtcztcbiAgICB9XG4gICAgX2dldFhBeGlzTGFiZWxBbGlnbm1lbnQoKSB7XG4gICAgICAgIGNvbnN0IHsgcG9zaXRpb24gLCB0aWNrcyAgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3Qgcm90YXRpb24gPSAtdG9SYWRpYW5zKHRoaXMubGFiZWxSb3RhdGlvbik7XG4gICAgICAgIGlmIChyb3RhdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHBvc2l0aW9uID09PSAndG9wJyA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGFsaWduID0gJ2NlbnRlcic7XG4gICAgICAgIGlmICh0aWNrcy5hbGlnbiA9PT0gJ3N0YXJ0Jykge1xuICAgICAgICAgICAgYWxpZ24gPSAnbGVmdCc7XG4gICAgICAgIH0gZWxzZSBpZiAodGlja3MuYWxpZ24gPT09ICdlbmQnKSB7XG4gICAgICAgICAgICBhbGlnbiA9ICdyaWdodCc7XG4gICAgICAgIH0gZWxzZSBpZiAodGlja3MuYWxpZ24gPT09ICdpbm5lcicpIHtcbiAgICAgICAgICAgIGFsaWduID0gJ2lubmVyJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWxpZ247XG4gICAgfVxuICAgIF9nZXRZQXhpc0xhYmVsQWxpZ25tZW50KHRsKSB7XG4gICAgICAgIGNvbnN0IHsgcG9zaXRpb24gLCB0aWNrczogeyBjcm9zc0FsaWduICwgbWlycm9yICwgcGFkZGluZyAgfSAgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgbGFiZWxTaXplcyA9IHRoaXMuX2dldExhYmVsU2l6ZXMoKTtcbiAgICAgICAgY29uc3QgdGlja0FuZFBhZGRpbmcgPSB0bCArIHBhZGRpbmc7XG4gICAgICAgIGNvbnN0IHdpZGVzdCA9IGxhYmVsU2l6ZXMud2lkZXN0LndpZHRoO1xuICAgICAgICBsZXQgdGV4dEFsaWduO1xuICAgICAgICBsZXQgeDtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgIGlmIChtaXJyb3IpIHtcbiAgICAgICAgICAgICAgICB4ID0gdGhpcy5yaWdodCArIHBhZGRpbmc7XG4gICAgICAgICAgICAgICAgaWYgKGNyb3NzQWxpZ24gPT09ICduZWFyJykge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ24gPSAnbGVmdCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgICAgICAgICAgICAgeCArPSB3aWRlc3QgLyAyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdyaWdodCc7XG4gICAgICAgICAgICAgICAgICAgIHggKz0gd2lkZXN0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeCA9IHRoaXMucmlnaHQgLSB0aWNrQW5kUGFkZGluZztcbiAgICAgICAgICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdyaWdodCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgICAgICAgICAgICAgeCAtPSB3aWRlc3QgLyAyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgICAgICAgICAgICAgeCA9IHRoaXMubGVmdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIGlmIChtaXJyb3IpIHtcbiAgICAgICAgICAgICAgICB4ID0gdGhpcy5sZWZ0ICsgcGFkZGluZztcbiAgICAgICAgICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdyaWdodCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgICAgICAgICAgICAgeCAtPSB3aWRlc3QgLyAyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgICAgICAgICAgICAgeCAtPSB3aWRlc3Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB4ID0gdGhpcy5sZWZ0ICsgdGlja0FuZFBhZGRpbmc7XG4gICAgICAgICAgICAgICAgaWYgKGNyb3NzQWxpZ24gPT09ICduZWFyJykge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ24gPSAnbGVmdCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgICAgICAgICAgICAgeCArPSB3aWRlc3QgLyAyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdyaWdodCc7XG4gICAgICAgICAgICAgICAgICAgIHggPSB0aGlzLnJpZ2h0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRleHRBbGlnbiA9ICdyaWdodCc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRleHRBbGlnbixcbiAgICAgICAgICAgIHhcbiAgICAgICAgfTtcbiAgICB9XG4gX2NvbXB1dGVMYWJlbEFyZWEoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMudGlja3MubWlycm9yKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMub3B0aW9ucy5wb3NpdGlvbjtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAnbGVmdCcgfHwgcG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdG9wOiAwLFxuICAgICAgICAgICAgICAgIGxlZnQ6IHRoaXMubGVmdCxcbiAgICAgICAgICAgICAgICBib3R0b206IGNoYXJ0LmhlaWdodCxcbiAgICAgICAgICAgICAgICByaWdodDogdGhpcy5yaWdodFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJykge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB0b3A6IHRoaXMudG9wLFxuICAgICAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICAgICAgYm90dG9tOiB0aGlzLmJvdHRvbSxcbiAgICAgICAgICAgICAgICByaWdodDogY2hhcnQud2lkdGhcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gZHJhd0JhY2tncm91bmQoKSB7XG4gICAgICAgIGNvbnN0IHsgY3R4ICwgb3B0aW9uczogeyBiYWNrZ3JvdW5kQ29sb3IgIH0gLCBsZWZ0ICwgdG9wICwgd2lkdGggLCBoZWlnaHQgIH0gPSB0aGlzO1xuICAgICAgICBpZiAoYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgICAgIGN0eC5maWxsUmVjdChsZWZ0LCB0b3AsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXRMaW5lV2lkdGhGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICBjb25zdCBncmlkID0gdGhpcy5vcHRpb25zLmdyaWQ7XG4gICAgICAgIGlmICghdGhpcy5faXNWaXNpYmxlKCkgfHwgIWdyaWQuZGlzcGxheSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGlja3MgPSB0aGlzLnRpY2tzO1xuICAgICAgICBjb25zdCBpbmRleCA9IHRpY2tzLmZpbmRJbmRleCgodCk9PnQudmFsdWUgPT09IHZhbHVlKTtcbiAgICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgICAgIGNvbnN0IG9wdHMgPSBncmlkLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KGluZGV4KSk7XG4gICAgICAgICAgICByZXR1cm4gb3B0cy5saW5lV2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuIGRyYXdHcmlkKGNoYXJ0QXJlYSkge1xuICAgICAgICBjb25zdCBncmlkID0gdGhpcy5vcHRpb25zLmdyaWQ7XG4gICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuX2dyaWRMaW5lSXRlbXMgfHwgKHRoaXMuX2dyaWRMaW5lSXRlbXMgPSB0aGlzLl9jb21wdXRlR3JpZExpbmVJdGVtcyhjaGFydEFyZWEpKTtcbiAgICAgICAgbGV0IGksIGlsZW47XG4gICAgICAgIGNvbnN0IGRyYXdMaW5lID0gKHAxLCBwMiwgc3R5bGUpPT57XG4gICAgICAgICAgICBpZiAoIXN0eWxlLndpZHRoIHx8ICFzdHlsZS5jb2xvcikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgICAgICBjdHgubGluZVdpZHRoID0gc3R5bGUud2lkdGg7XG4gICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBzdHlsZS5jb2xvcjtcbiAgICAgICAgICAgIGN0eC5zZXRMaW5lRGFzaChzdHlsZS5ib3JkZXJEYXNoIHx8IFtdKTtcbiAgICAgICAgICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IHN0eWxlLmJvcmRlckRhc2hPZmZzZXQ7XG4gICAgICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgICAgICBjdHgubW92ZVRvKHAxLngsIHAxLnkpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhwMi54LCBwMi55KTtcbiAgICAgICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgIH07XG4gICAgICAgIGlmIChncmlkLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGl0ZW1zLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICAgICAgY29uc3QgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgICAgIGlmIChncmlkLmRyYXdPbkNoYXJ0QXJlYSkge1xuICAgICAgICAgICAgICAgICAgICBkcmF3TGluZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICB4OiBpdGVtLngxLFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogaXRlbS55MVxuICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4OiBpdGVtLngyLFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogaXRlbS55MlxuICAgICAgICAgICAgICAgICAgICB9LCBpdGVtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGdyaWQuZHJhd1RpY2tzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRyYXdMaW5lKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IGl0ZW0udHgxLFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogaXRlbS50eTFcbiAgICAgICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgeDogaXRlbS50eDIsXG4gICAgICAgICAgICAgICAgICAgICAgICB5OiBpdGVtLnR5MlxuICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogaXRlbS50aWNrQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogaXRlbS50aWNrV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJEYXNoOiBpdGVtLnRpY2tCb3JkZXJEYXNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9yZGVyRGFzaE9mZnNldDogaXRlbS50aWNrQm9yZGVyRGFzaE9mZnNldFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gZHJhd0JvcmRlcigpIHtcbiAgICAgICAgY29uc3QgeyBjaGFydCAsIGN0eCAsIG9wdGlvbnM6IHsgYm9yZGVyICwgZ3JpZCAgfSAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGJvcmRlck9wdHMgPSBib3JkZXIuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoKSk7XG4gICAgICAgIGNvbnN0IGF4aXNXaWR0aCA9IGJvcmRlci5kaXNwbGF5ID8gYm9yZGVyT3B0cy53aWR0aCA6IDA7XG4gICAgICAgIGlmICghYXhpc1dpZHRoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGFzdExpbmVXaWR0aCA9IGdyaWQuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoMCkpLmxpbmVXaWR0aDtcbiAgICAgICAgY29uc3QgYm9yZGVyVmFsdWUgPSB0aGlzLl9ib3JkZXJWYWx1ZTtcbiAgICAgICAgbGV0IHgxLCB4MiwgeTEsIHkyO1xuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgeDEgPSBfYWxpZ25QaXhlbChjaGFydCwgdGhpcy5sZWZ0LCBheGlzV2lkdGgpIC0gYXhpc1dpZHRoIC8gMjtcbiAgICAgICAgICAgIHgyID0gX2FsaWduUGl4ZWwoY2hhcnQsIHRoaXMucmlnaHQsIGxhc3RMaW5lV2lkdGgpICsgbGFzdExpbmVXaWR0aCAvIDI7XG4gICAgICAgICAgICB5MSA9IHkyID0gYm9yZGVyVmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB5MSA9IF9hbGlnblBpeGVsKGNoYXJ0LCB0aGlzLnRvcCwgYXhpc1dpZHRoKSAtIGF4aXNXaWR0aCAvIDI7XG4gICAgICAgICAgICB5MiA9IF9hbGlnblBpeGVsKGNoYXJ0LCB0aGlzLmJvdHRvbSwgbGFzdExpbmVXaWR0aCkgKyBsYXN0TGluZVdpZHRoIC8gMjtcbiAgICAgICAgICAgIHgxID0geDIgPSBib3JkZXJWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICBjdHgubGluZVdpZHRoID0gYm9yZGVyT3B0cy53aWR0aDtcbiAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gYm9yZGVyT3B0cy5jb2xvcjtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHgubW92ZVRvKHgxLCB5MSk7XG4gICAgICAgIGN0eC5saW5lVG8oeDIsIHkyKTtcbiAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH1cbiBkcmF3TGFiZWxzKGNoYXJ0QXJlYSkge1xuICAgICAgICBjb25zdCBvcHRpb25UaWNrcyA9IHRoaXMub3B0aW9ucy50aWNrcztcbiAgICAgICAgaWYgKCFvcHRpb25UaWNrcy5kaXNwbGF5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgICAgIGNvbnN0IGFyZWEgPSB0aGlzLl9jb21wdXRlTGFiZWxBcmVhKCk7XG4gICAgICAgIGlmIChhcmVhKSB7XG4gICAgICAgICAgICBjbGlwQXJlYShjdHgsIGFyZWEpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5nZXRMYWJlbEl0ZW1zKGNoYXJ0QXJlYSk7XG4gICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcyl7XG4gICAgICAgICAgICBjb25zdCByZW5kZXJUZXh0T3B0aW9ucyA9IGl0ZW0ub3B0aW9ucztcbiAgICAgICAgICAgIGNvbnN0IHRpY2tGb250ID0gaXRlbS5mb250O1xuICAgICAgICAgICAgY29uc3QgbGFiZWwgPSBpdGVtLmxhYmVsO1xuICAgICAgICAgICAgY29uc3QgeSA9IGl0ZW0udGV4dE9mZnNldDtcbiAgICAgICAgICAgIHJlbmRlclRleHQoY3R4LCBsYWJlbCwgMCwgeSwgdGlja0ZvbnQsIHJlbmRlclRleHRPcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXJlYSkge1xuICAgICAgICAgICAgdW5jbGlwQXJlYShjdHgpO1xuICAgICAgICB9XG4gICAgfVxuIGRyYXdUaXRsZSgpIHtcbiAgICAgICAgY29uc3QgeyBjdHggLCBvcHRpb25zOiB7IHBvc2l0aW9uICwgdGl0bGUgLCByZXZlcnNlICB9ICB9ID0gdGhpcztcbiAgICAgICAgaWYgKCF0aXRsZS5kaXNwbGF5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZm9udCA9IHRvRm9udCh0aXRsZS5mb250KTtcbiAgICAgICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyh0aXRsZS5wYWRkaW5nKTtcbiAgICAgICAgY29uc3QgYWxpZ24gPSB0aXRsZS5hbGlnbjtcbiAgICAgICAgbGV0IG9mZnNldCA9IGZvbnQubGluZUhlaWdodCAvIDI7XG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScgfHwgcG9zaXRpb24gPT09ICdjZW50ZXInIHx8IGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgb2Zmc2V0ICs9IHBhZGRpbmcuYm90dG9tO1xuICAgICAgICAgICAgaWYgKGlzQXJyYXkodGl0bGUudGV4dCkpIHtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gZm9udC5saW5lSGVpZ2h0ICogKHRpdGxlLnRleHQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvZmZzZXQgKz0gcGFkZGluZy50b3A7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyB0aXRsZVggLCB0aXRsZVkgLCBtYXhXaWR0aCAsIHJvdGF0aW9uICB9ID0gdGl0bGVBcmdzKHRoaXMsIG9mZnNldCwgcG9zaXRpb24sIGFsaWduKTtcbiAgICAgICAgcmVuZGVyVGV4dChjdHgsIHRpdGxlLnRleHQsIDAsIDAsIGZvbnQsIHtcbiAgICAgICAgICAgIGNvbG9yOiB0aXRsZS5jb2xvcixcbiAgICAgICAgICAgIG1heFdpZHRoLFxuICAgICAgICAgICAgcm90YXRpb24sXG4gICAgICAgICAgICB0ZXh0QWxpZ246IHRpdGxlQWxpZ24oYWxpZ24sIHBvc2l0aW9uLCByZXZlcnNlKSxcbiAgICAgICAgICAgIHRleHRCYXNlbGluZTogJ21pZGRsZScsXG4gICAgICAgICAgICB0cmFuc2xhdGlvbjogW1xuICAgICAgICAgICAgICAgIHRpdGxlWCxcbiAgICAgICAgICAgICAgICB0aXRsZVlcbiAgICAgICAgICAgIF1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGRyYXcoY2hhcnRBcmVhKSB7XG4gICAgICAgIGlmICghdGhpcy5faXNWaXNpYmxlKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRyYXdCYWNrZ3JvdW5kKCk7XG4gICAgICAgIHRoaXMuZHJhd0dyaWQoY2hhcnRBcmVhKTtcbiAgICAgICAgdGhpcy5kcmF3Qm9yZGVyKCk7XG4gICAgICAgIHRoaXMuZHJhd1RpdGxlKCk7XG4gICAgICAgIHRoaXMuZHJhd0xhYmVscyhjaGFydEFyZWEpO1xuICAgIH1cbiBfbGF5ZXJzKCkge1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB0eiA9IG9wdHMudGlja3MgJiYgb3B0cy50aWNrcy56IHx8IDA7XG4gICAgICAgIGNvbnN0IGd6ID0gdmFsdWVPckRlZmF1bHQob3B0cy5ncmlkICYmIG9wdHMuZ3JpZC56LCAtMSk7XG4gICAgICAgIGNvbnN0IGJ6ID0gdmFsdWVPckRlZmF1bHQob3B0cy5ib3JkZXIgJiYgb3B0cy5ib3JkZXIueiwgMCk7XG4gICAgICAgIGlmICghdGhpcy5faXNWaXNpYmxlKCkgfHwgdGhpcy5kcmF3ICE9PSBTY2FsZS5wcm90b3R5cGUuZHJhdykge1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHo6IHR6LFxuICAgICAgICAgICAgICAgICAgICBkcmF3OiAoY2hhcnRBcmVhKT0+e1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmF3KGNoYXJ0QXJlYSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgejogZ3osXG4gICAgICAgICAgICAgICAgZHJhdzogKGNoYXJ0QXJlYSk9PntcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmF3QmFja2dyb3VuZCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYXdHcmlkKGNoYXJ0QXJlYSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhd1RpdGxlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB6OiBieixcbiAgICAgICAgICAgICAgICBkcmF3OiAoKT0+e1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYXdCb3JkZXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHo6IHR6LFxuICAgICAgICAgICAgICAgIGRyYXc6IChjaGFydEFyZWEpPT57XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhd0xhYmVscyhjaGFydEFyZWEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgXTtcbiAgICB9XG4gZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXModHlwZSkge1xuICAgICAgICBjb25zdCBtZXRhcyA9IHRoaXMuY2hhcnQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO1xuICAgICAgICBjb25zdCBheGlzSUQgPSB0aGlzLmF4aXMgKyAnQXhpc0lEJztcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBtZXRhcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgY29uc3QgbWV0YSA9IG1ldGFzW2ldO1xuICAgICAgICAgICAgaWYgKG1ldGFbYXhpc0lEXSA9PT0gdGhpcy5pZCAmJiAoIXR5cGUgfHwgbWV0YS50eXBlID09PSB0eXBlKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKG1ldGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuIF9yZXNvbHZlVGlja0ZvbnRPcHRpb25zKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnMudGlja3Muc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoaW5kZXgpKTtcbiAgICAgICAgcmV0dXJuIHRvRm9udChvcHRzLmZvbnQpO1xuICAgIH1cbiBfbWF4RGlnaXRzKCkge1xuICAgICAgICBjb25zdCBmb250U2l6ZSA9IHRoaXMuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoMCkubGluZUhlaWdodDtcbiAgICAgICAgcmV0dXJuICh0aGlzLmlzSG9yaXpvbnRhbCgpID8gdGhpcy53aWR0aCA6IHRoaXMuaGVpZ2h0KSAvIGZvbnRTaXplO1xuICAgIH1cbn1cblxuY2xhc3MgVHlwZWRSZWdpc3RyeSB7XG4gICAgY29uc3RydWN0b3IodHlwZSwgc2NvcGUsIG92ZXJyaWRlKXtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5zY29wZSA9IHNjb3BlO1xuICAgICAgICB0aGlzLm92ZXJyaWRlID0gb3ZlcnJpZGU7XG4gICAgICAgIHRoaXMuaXRlbXMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIH1cbiAgICBpc0ZvclR5cGUodHlwZSkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mLmNhbGwodGhpcy50eXBlLnByb3RvdHlwZSwgdHlwZS5wcm90b3R5cGUpO1xuICAgIH1cbiByZWdpc3RlcihpdGVtKSB7XG4gICAgICAgIGNvbnN0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKGl0ZW0pO1xuICAgICAgICBsZXQgcGFyZW50U2NvcGU7XG4gICAgICAgIGlmIChpc0lDaGFydENvbXBvbmVudChwcm90bykpIHtcbiAgICAgICAgICAgIHBhcmVudFNjb3BlID0gdGhpcy5yZWdpc3Rlcihwcm90byk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zO1xuICAgICAgICBjb25zdCBpZCA9IGl0ZW0uaWQ7XG4gICAgICAgIGNvbnN0IHNjb3BlID0gdGhpcy5zY29wZSArICcuJyArIGlkO1xuICAgICAgICBpZiAoIWlkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsYXNzIGRvZXMgbm90IGhhdmUgaWQ6ICcgKyBpdGVtKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaWQgaW4gaXRlbXMpIHtcbiAgICAgICAgICAgIHJldHVybiBzY29wZTtcbiAgICAgICAgfVxuICAgICAgICBpdGVtc1tpZF0gPSBpdGVtO1xuICAgICAgICByZWdpc3RlckRlZmF1bHRzKGl0ZW0sIHNjb3BlLCBwYXJlbnRTY29wZSk7XG4gICAgICAgIGlmICh0aGlzLm92ZXJyaWRlKSB7XG4gICAgICAgICAgICBkZWZhdWx0cy5vdmVycmlkZShpdGVtLmlkLCBpdGVtLm92ZXJyaWRlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNjb3BlO1xuICAgIH1cbiBnZXQoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXNbaWRdO1xuICAgIH1cbiB1bnJlZ2lzdGVyKGl0ZW0pIHtcbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zO1xuICAgICAgICBjb25zdCBpZCA9IGl0ZW0uaWQ7XG4gICAgICAgIGNvbnN0IHNjb3BlID0gdGhpcy5zY29wZTtcbiAgICAgICAgaWYgKGlkIGluIGl0ZW1zKSB7XG4gICAgICAgICAgICBkZWxldGUgaXRlbXNbaWRdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzY29wZSAmJiBpZCBpbiBkZWZhdWx0c1tzY29wZV0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBkZWZhdWx0c1tzY29wZV1baWRdO1xuICAgICAgICAgICAgaWYgKHRoaXMub3ZlcnJpZGUpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgb3ZlcnJpZGVzW2lkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbmZ1bmN0aW9uIHJlZ2lzdGVyRGVmYXVsdHMoaXRlbSwgc2NvcGUsIHBhcmVudFNjb3BlKSB7XG4gICAgY29uc3QgaXRlbURlZmF1bHRzID0gbWVyZ2UoT2JqZWN0LmNyZWF0ZShudWxsKSwgW1xuICAgICAgICBwYXJlbnRTY29wZSA/IGRlZmF1bHRzLmdldChwYXJlbnRTY29wZSkgOiB7fSxcbiAgICAgICAgZGVmYXVsdHMuZ2V0KHNjb3BlKSxcbiAgICAgICAgaXRlbS5kZWZhdWx0c1xuICAgIF0pO1xuICAgIGRlZmF1bHRzLnNldChzY29wZSwgaXRlbURlZmF1bHRzKTtcbiAgICBpZiAoaXRlbS5kZWZhdWx0Um91dGVzKSB7XG4gICAgICAgIHJvdXRlRGVmYXVsdHMoc2NvcGUsIGl0ZW0uZGVmYXVsdFJvdXRlcyk7XG4gICAgfVxuICAgIGlmIChpdGVtLmRlc2NyaXB0b3JzKSB7XG4gICAgICAgIGRlZmF1bHRzLmRlc2NyaWJlKHNjb3BlLCBpdGVtLmRlc2NyaXB0b3JzKTtcbiAgICB9XG59XG5mdW5jdGlvbiByb3V0ZURlZmF1bHRzKHNjb3BlLCByb3V0ZXMpIHtcbiAgICBPYmplY3Qua2V5cyhyb3V0ZXMpLmZvckVhY2goKHByb3BlcnR5KT0+e1xuICAgICAgICBjb25zdCBwcm9wZXJ0eVBhcnRzID0gcHJvcGVydHkuc3BsaXQoJy4nKTtcbiAgICAgICAgY29uc3Qgc291cmNlTmFtZSA9IHByb3BlcnR5UGFydHMucG9wKCk7XG4gICAgICAgIGNvbnN0IHNvdXJjZVNjb3BlID0gW1xuICAgICAgICAgICAgc2NvcGVcbiAgICAgICAgXS5jb25jYXQocHJvcGVydHlQYXJ0cykuam9pbignLicpO1xuICAgICAgICBjb25zdCBwYXJ0cyA9IHJvdXRlc1twcm9wZXJ0eV0uc3BsaXQoJy4nKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0TmFtZSA9IHBhcnRzLnBvcCgpO1xuICAgICAgICBjb25zdCB0YXJnZXRTY29wZSA9IHBhcnRzLmpvaW4oJy4nKTtcbiAgICAgICAgZGVmYXVsdHMucm91dGUoc291cmNlU2NvcGUsIHNvdXJjZU5hbWUsIHRhcmdldFNjb3BlLCB0YXJnZXROYW1lKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGlzSUNoYXJ0Q29tcG9uZW50KHByb3RvKSB7XG4gICAgcmV0dXJuICdpZCcgaW4gcHJvdG8gJiYgJ2RlZmF1bHRzJyBpbiBwcm90bztcbn1cblxuY2xhc3MgUmVnaXN0cnkge1xuICAgIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMuY29udHJvbGxlcnMgPSBuZXcgVHlwZWRSZWdpc3RyeShEYXRhc2V0Q29udHJvbGxlciwgJ2RhdGFzZXRzJywgdHJ1ZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudHMgPSBuZXcgVHlwZWRSZWdpc3RyeShFbGVtZW50LCAnZWxlbWVudHMnKTtcbiAgICAgICAgdGhpcy5wbHVnaW5zID0gbmV3IFR5cGVkUmVnaXN0cnkoT2JqZWN0LCAncGx1Z2lucycpO1xuICAgICAgICB0aGlzLnNjYWxlcyA9IG5ldyBUeXBlZFJlZ2lzdHJ5KFNjYWxlLCAnc2NhbGVzJyk7XG4gICAgICAgIHRoaXMuX3R5cGVkUmVnaXN0cmllcyA9IFtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlcnMsXG4gICAgICAgICAgICB0aGlzLnNjYWxlcyxcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudHNcbiAgICAgICAgXTtcbiAgICB9XG4gYWRkKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgncmVnaXN0ZXInLCBhcmdzKTtcbiAgICB9XG4gICAgcmVtb3ZlKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgndW5yZWdpc3RlcicsIGFyZ3MpO1xuICAgIH1cbiBhZGRDb250cm9sbGVycyguLi5hcmdzKSB7XG4gICAgICAgIHRoaXMuX2VhY2goJ3JlZ2lzdGVyJywgYXJncywgdGhpcy5jb250cm9sbGVycyk7XG4gICAgfVxuIGFkZEVsZW1lbnRzKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgncmVnaXN0ZXInLCBhcmdzLCB0aGlzLmVsZW1lbnRzKTtcbiAgICB9XG4gYWRkUGx1Z2lucyguLi5hcmdzKSB7XG4gICAgICAgIHRoaXMuX2VhY2goJ3JlZ2lzdGVyJywgYXJncywgdGhpcy5wbHVnaW5zKTtcbiAgICB9XG4gYWRkU2NhbGVzKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgncmVnaXN0ZXInLCBhcmdzLCB0aGlzLnNjYWxlcyk7XG4gICAgfVxuIGdldENvbnRyb2xsZXIoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldChpZCwgdGhpcy5jb250cm9sbGVycywgJ2NvbnRyb2xsZXInKTtcbiAgICB9XG4gZ2V0RWxlbWVudChpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0KGlkLCB0aGlzLmVsZW1lbnRzLCAnZWxlbWVudCcpO1xuICAgIH1cbiBnZXRQbHVnaW4oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldChpZCwgdGhpcy5wbHVnaW5zLCAncGx1Z2luJyk7XG4gICAgfVxuIGdldFNjYWxlKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXQoaWQsIHRoaXMuc2NhbGVzLCAnc2NhbGUnKTtcbiAgICB9XG4gcmVtb3ZlQ29udHJvbGxlcnMoLi4uYXJncykge1xuICAgICAgICB0aGlzLl9lYWNoKCd1bnJlZ2lzdGVyJywgYXJncywgdGhpcy5jb250cm9sbGVycyk7XG4gICAgfVxuIHJlbW92ZUVsZW1lbnRzKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgndW5yZWdpc3RlcicsIGFyZ3MsIHRoaXMuZWxlbWVudHMpO1xuICAgIH1cbiByZW1vdmVQbHVnaW5zKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgndW5yZWdpc3RlcicsIGFyZ3MsIHRoaXMucGx1Z2lucyk7XG4gICAgfVxuIHJlbW92ZVNjYWxlcyguLi5hcmdzKSB7XG4gICAgICAgIHRoaXMuX2VhY2goJ3VucmVnaXN0ZXInLCBhcmdzLCB0aGlzLnNjYWxlcyk7XG4gICAgfVxuIF9lYWNoKG1ldGhvZCwgYXJncywgdHlwZWRSZWdpc3RyeSkge1xuICAgICAgICBbXG4gICAgICAgICAgICAuLi5hcmdzXG4gICAgICAgIF0uZm9yRWFjaCgoYXJnKT0+e1xuICAgICAgICAgICAgY29uc3QgcmVnID0gdHlwZWRSZWdpc3RyeSB8fCB0aGlzLl9nZXRSZWdpc3RyeUZvclR5cGUoYXJnKTtcbiAgICAgICAgICAgIGlmICh0eXBlZFJlZ2lzdHJ5IHx8IHJlZy5pc0ZvclR5cGUoYXJnKSB8fCByZWcgPT09IHRoaXMucGx1Z2lucyAmJiBhcmcuaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9leGVjKG1ldGhvZCwgcmVnLCBhcmcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlYWNoKGFyZywgKGl0ZW0pPT57XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1SZWcgPSB0eXBlZFJlZ2lzdHJ5IHx8IHRoaXMuX2dldFJlZ2lzdHJ5Rm9yVHlwZShpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZXhlYyhtZXRob2QsIGl0ZW1SZWcsIGl0ZW0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gX2V4ZWMobWV0aG9kLCByZWdpc3RyeSwgY29tcG9uZW50KSB7XG4gICAgICAgIGNvbnN0IGNhbWVsTWV0aG9kID0gX2NhcGl0YWxpemUobWV0aG9kKTtcbiAgICAgICAgY2FsbGJhY2soY29tcG9uZW50WydiZWZvcmUnICsgY2FtZWxNZXRob2RdLCBbXSwgY29tcG9uZW50KTtcbiAgICAgICAgcmVnaXN0cnlbbWV0aG9kXShjb21wb25lbnQpO1xuICAgICAgICBjYWxsYmFjayhjb21wb25lbnRbJ2FmdGVyJyArIGNhbWVsTWV0aG9kXSwgW10sIGNvbXBvbmVudCk7XG4gICAgfVxuIF9nZXRSZWdpc3RyeUZvclR5cGUodHlwZSkge1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5fdHlwZWRSZWdpc3RyaWVzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IHJlZyA9IHRoaXMuX3R5cGVkUmVnaXN0cmllc1tpXTtcbiAgICAgICAgICAgIGlmIChyZWcuaXNGb3JUeXBlKHR5cGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5wbHVnaW5zO1xuICAgIH1cbiBfZ2V0KGlkLCB0eXBlZFJlZ2lzdHJ5LCB0eXBlKSB7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSB0eXBlZFJlZ2lzdHJ5LmdldChpZCk7XG4gICAgICAgIGlmIChpdGVtID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignXCInICsgaWQgKyAnXCIgaXMgbm90IGEgcmVnaXN0ZXJlZCAnICsgdHlwZSArICcuJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfVxufVxudmFyIHJlZ2lzdHJ5ID0gLyogI19fUFVSRV9fICovIG5ldyBSZWdpc3RyeSgpO1xuXG5jbGFzcyBQbHVnaW5TZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLl9pbml0ID0gW107XG4gICAgfVxuIG5vdGlmeShjaGFydCwgaG9vaywgYXJncywgZmlsdGVyKSB7XG4gICAgICAgIGlmIChob29rID09PSAnYmVmb3JlSW5pdCcpIHtcbiAgICAgICAgICAgIHRoaXMuX2luaXQgPSB0aGlzLl9jcmVhdGVEZXNjcmlwdG9ycyhjaGFydCwgdHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnkodGhpcy5faW5pdCwgY2hhcnQsICdpbnN0YWxsJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGVzY3JpcHRvcnMgPSBmaWx0ZXIgPyB0aGlzLl9kZXNjcmlwdG9ycyhjaGFydCkuZmlsdGVyKGZpbHRlcikgOiB0aGlzLl9kZXNjcmlwdG9ycyhjaGFydCk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX25vdGlmeShkZXNjcmlwdG9ycywgY2hhcnQsIGhvb2ssIGFyZ3MpO1xuICAgICAgICBpZiAoaG9vayA9PT0gJ2FmdGVyRGVzdHJveScpIHtcbiAgICAgICAgICAgIHRoaXMuX25vdGlmeShkZXNjcmlwdG9ycywgY2hhcnQsICdzdG9wJyk7XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnkodGhpcy5faW5pdCwgY2hhcnQsICd1bmluc3RhbGwnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiBfbm90aWZ5KGRlc2NyaXB0b3JzLCBjaGFydCwgaG9vaywgYXJncykge1xuICAgICAgICBhcmdzID0gYXJncyB8fCB7fTtcbiAgICAgICAgZm9yIChjb25zdCBkZXNjcmlwdG9yIG9mIGRlc2NyaXB0b3JzKXtcbiAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IGRlc2NyaXB0b3IucGx1Z2luO1xuICAgICAgICAgICAgY29uc3QgbWV0aG9kID0gcGx1Z2luW2hvb2tdO1xuICAgICAgICAgICAgY29uc3QgcGFyYW1zID0gW1xuICAgICAgICAgICAgICAgIGNoYXJ0LFxuICAgICAgICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRvci5vcHRpb25zXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKG1ldGhvZCwgcGFyYW1zLCBwbHVnaW4pID09PSBmYWxzZSAmJiBhcmdzLmNhbmNlbGFibGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGludmFsaWRhdGUoKSB7XG4gICAgICAgIGlmICghaXNOdWxsT3JVbmRlZih0aGlzLl9jYWNoZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX29sZENhY2hlID0gdGhpcy5fY2FjaGU7XG4gICAgICAgICAgICB0aGlzLl9jYWNoZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH1cbiBfZGVzY3JpcHRvcnMoY2hhcnQpIHtcbiAgICAgICAgaWYgKHRoaXMuX2NhY2hlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fY2FjaGU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGVzY3JpcHRvcnMgPSB0aGlzLl9jYWNoZSA9IHRoaXMuX2NyZWF0ZURlc2NyaXB0b3JzKGNoYXJ0KTtcbiAgICAgICAgdGhpcy5fbm90aWZ5U3RhdGVDaGFuZ2VzKGNoYXJ0KTtcbiAgICAgICAgcmV0dXJuIGRlc2NyaXB0b3JzO1xuICAgIH1cbiAgICBfY3JlYXRlRGVzY3JpcHRvcnMoY2hhcnQsIGFsbCkge1xuICAgICAgICBjb25zdCBjb25maWcgPSBjaGFydCAmJiBjaGFydC5jb25maWc7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB2YWx1ZU9yRGVmYXVsdChjb25maWcub3B0aW9ucyAmJiBjb25maWcub3B0aW9ucy5wbHVnaW5zLCB7fSk7XG4gICAgICAgIGNvbnN0IHBsdWdpbnMgPSBhbGxQbHVnaW5zKGNvbmZpZyk7XG4gICAgICAgIHJldHVybiBvcHRpb25zID09PSBmYWxzZSAmJiAhYWxsID8gW10gOiBjcmVhdGVEZXNjcmlwdG9ycyhjaGFydCwgcGx1Z2lucywgb3B0aW9ucywgYWxsKTtcbiAgICB9XG4gX25vdGlmeVN0YXRlQ2hhbmdlcyhjaGFydCkge1xuICAgICAgICBjb25zdCBwcmV2aW91c0Rlc2NyaXB0b3JzID0gdGhpcy5fb2xkQ2FjaGUgfHwgW107XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0b3JzID0gdGhpcy5fY2FjaGU7XG4gICAgICAgIGNvbnN0IGRpZmYgPSAoYSwgYik9PmEuZmlsdGVyKCh4KT0+IWIuc29tZSgoeSk9PngucGx1Z2luLmlkID09PSB5LnBsdWdpbi5pZCkpO1xuICAgICAgICB0aGlzLl9ub3RpZnkoZGlmZihwcmV2aW91c0Rlc2NyaXB0b3JzLCBkZXNjcmlwdG9ycyksIGNoYXJ0LCAnc3RvcCcpO1xuICAgICAgICB0aGlzLl9ub3RpZnkoZGlmZihkZXNjcmlwdG9ycywgcHJldmlvdXNEZXNjcmlwdG9ycyksIGNoYXJ0LCAnc3RhcnQnKTtcbiAgICB9XG59XG4gZnVuY3Rpb24gYWxsUGx1Z2lucyhjb25maWcpIHtcbiAgICBjb25zdCBsb2NhbElkcyA9IHt9O1xuICAgIGNvbnN0IHBsdWdpbnMgPSBbXTtcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMocmVnaXN0cnkucGx1Z2lucy5pdGVtcyk7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspe1xuICAgICAgICBwbHVnaW5zLnB1c2gocmVnaXN0cnkuZ2V0UGx1Z2luKGtleXNbaV0pKTtcbiAgICB9XG4gICAgY29uc3QgbG9jYWwgPSBjb25maWcucGx1Z2lucyB8fCBbXTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgbG9jYWwubGVuZ3RoOyBpKyspe1xuICAgICAgICBjb25zdCBwbHVnaW4gPSBsb2NhbFtpXTtcbiAgICAgICAgaWYgKHBsdWdpbnMuaW5kZXhPZihwbHVnaW4pID09PSAtMSkge1xuICAgICAgICAgICAgcGx1Z2lucy5wdXNoKHBsdWdpbik7XG4gICAgICAgICAgICBsb2NhbElkc1twbHVnaW4uaWRdID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBwbHVnaW5zLFxuICAgICAgICBsb2NhbElkc1xuICAgIH07XG59XG5mdW5jdGlvbiBnZXRPcHRzKG9wdGlvbnMsIGFsbCkge1xuICAgIGlmICghYWxsICYmIG9wdGlvbnMgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucyA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIHJldHVybiBvcHRpb25zO1xufVxuZnVuY3Rpb24gY3JlYXRlRGVzY3JpcHRvcnMoY2hhcnQsIHsgcGx1Z2lucyAsIGxvY2FsSWRzICB9LCBvcHRpb25zLCBhbGwpIHtcbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBjb25zdCBjb250ZXh0ID0gY2hhcnQuZ2V0Q29udGV4dCgpO1xuICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHBsdWdpbnMpe1xuICAgICAgICBjb25zdCBpZCA9IHBsdWdpbi5pZDtcbiAgICAgICAgY29uc3Qgb3B0cyA9IGdldE9wdHMob3B0aW9uc1tpZF0sIGFsbCk7XG4gICAgICAgIGlmIChvcHRzID09PSBudWxsKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgICAgICBwbHVnaW4sXG4gICAgICAgICAgICBvcHRpb25zOiBwbHVnaW5PcHRzKGNoYXJ0LmNvbmZpZywge1xuICAgICAgICAgICAgICAgIHBsdWdpbixcbiAgICAgICAgICAgICAgICBsb2NhbDogbG9jYWxJZHNbaWRdXG4gICAgICAgICAgICB9LCBvcHRzLCBjb250ZXh0KVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIHBsdWdpbk9wdHMoY29uZmlnLCB7IHBsdWdpbiAsIGxvY2FsICB9LCBvcHRzLCBjb250ZXh0KSB7XG4gICAgY29uc3Qga2V5cyA9IGNvbmZpZy5wbHVnaW5TY29wZUtleXMocGx1Z2luKTtcbiAgICBjb25zdCBzY29wZXMgPSBjb25maWcuZ2V0T3B0aW9uU2NvcGVzKG9wdHMsIGtleXMpO1xuICAgIGlmIChsb2NhbCAmJiBwbHVnaW4uZGVmYXVsdHMpIHtcbiAgICAgICAgc2NvcGVzLnB1c2gocGx1Z2luLmRlZmF1bHRzKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbmZpZy5jcmVhdGVSZXNvbHZlcihzY29wZXMsIGNvbnRleHQsIFtcbiAgICAgICAgJydcbiAgICBdLCB7XG4gICAgICAgIHNjcmlwdGFibGU6IGZhbHNlLFxuICAgICAgICBpbmRleGFibGU6IGZhbHNlLFxuICAgICAgICBhbGxLZXlzOiB0cnVlXG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEluZGV4QXhpcyh0eXBlLCBvcHRpb25zKSB7XG4gICAgY29uc3QgZGF0YXNldERlZmF1bHRzID0gZGVmYXVsdHMuZGF0YXNldHNbdHlwZV0gfHwge307XG4gICAgY29uc3QgZGF0YXNldE9wdGlvbnMgPSAob3B0aW9ucy5kYXRhc2V0cyB8fCB7fSlbdHlwZV0gfHwge307XG4gICAgcmV0dXJuIGRhdGFzZXRPcHRpb25zLmluZGV4QXhpcyB8fCBvcHRpb25zLmluZGV4QXhpcyB8fCBkYXRhc2V0RGVmYXVsdHMuaW5kZXhBeGlzIHx8ICd4Jztcbn1cbmZ1bmN0aW9uIGdldEF4aXNGcm9tRGVmYXVsdFNjYWxlSUQoaWQsIGluZGV4QXhpcykge1xuICAgIGxldCBheGlzID0gaWQ7XG4gICAgaWYgKGlkID09PSAnX2luZGV4XycpIHtcbiAgICAgICAgYXhpcyA9IGluZGV4QXhpcztcbiAgICB9IGVsc2UgaWYgKGlkID09PSAnX3ZhbHVlXycpIHtcbiAgICAgICAgYXhpcyA9IGluZGV4QXhpcyA9PT0gJ3gnID8gJ3knIDogJ3gnO1xuICAgIH1cbiAgICByZXR1cm4gYXhpcztcbn1cbmZ1bmN0aW9uIGdldERlZmF1bHRTY2FsZUlERnJvbUF4aXMoYXhpcywgaW5kZXhBeGlzKSB7XG4gICAgcmV0dXJuIGF4aXMgPT09IGluZGV4QXhpcyA/ICdfaW5kZXhfJyA6ICdfdmFsdWVfJztcbn1cbmZ1bmN0aW9uIGlkTWF0Y2hlc0F4aXMoaWQpIHtcbiAgICBpZiAoaWQgPT09ICd4JyB8fCBpZCA9PT0gJ3knIHx8IGlkID09PSAncicpIHtcbiAgICAgICAgcmV0dXJuIGlkO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGF4aXNGcm9tUG9zaXRpb24ocG9zaXRpb24pIHtcbiAgICBpZiAocG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJykge1xuICAgICAgICByZXR1cm4gJ3gnO1xuICAgIH1cbiAgICBpZiAocG9zaXRpb24gPT09ICdsZWZ0JyB8fCBwb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICByZXR1cm4gJ3knO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGRldGVybWluZUF4aXMoaWQsIC4uLnNjYWxlT3B0aW9ucykge1xuICAgIGlmIChpZE1hdGNoZXNBeGlzKGlkKSkge1xuICAgICAgICByZXR1cm4gaWQ7XG4gICAgfVxuICAgIGZvciAoY29uc3Qgb3B0cyBvZiBzY2FsZU9wdGlvbnMpe1xuICAgICAgICBjb25zdCBheGlzID0gb3B0cy5heGlzIHx8IGF4aXNGcm9tUG9zaXRpb24ob3B0cy5wb3NpdGlvbikgfHwgaWQubGVuZ3RoID4gMSAmJiBpZE1hdGNoZXNBeGlzKGlkWzBdLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICBpZiAoYXhpcykge1xuICAgICAgICAgICAgcmV0dXJuIGF4aXM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZGV0ZXJtaW5lIHR5cGUgb2YgJyR7aWR9JyBheGlzLiBQbGVhc2UgcHJvdmlkZSAnYXhpcycgb3IgJ3Bvc2l0aW9uJyBvcHRpb24uYCk7XG59XG5mdW5jdGlvbiBnZXRBeGlzRnJvbURhdGFzZXQoaWQsIGF4aXMsIGRhdGFzZXQpIHtcbiAgICBpZiAoZGF0YXNldFtheGlzICsgJ0F4aXNJRCddID09PSBpZCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYXhpc1xuICAgICAgICB9O1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJldHJpZXZlQXhpc0Zyb21EYXRhc2V0cyhpZCwgY29uZmlnKSB7XG4gICAgaWYgKGNvbmZpZy5kYXRhICYmIGNvbmZpZy5kYXRhLmRhdGFzZXRzKSB7XG4gICAgICAgIGNvbnN0IGJvdW5kRHMgPSBjb25maWcuZGF0YS5kYXRhc2V0cy5maWx0ZXIoKGQpPT5kLnhBeGlzSUQgPT09IGlkIHx8IGQueUF4aXNJRCA9PT0gaWQpO1xuICAgICAgICBpZiAoYm91bmREcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBnZXRBeGlzRnJvbURhdGFzZXQoaWQsICd4JywgYm91bmREc1swXSkgfHwgZ2V0QXhpc0Zyb21EYXRhc2V0KGlkLCAneScsIGJvdW5kRHNbMF0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7fTtcbn1cbmZ1bmN0aW9uIG1lcmdlU2NhbGVDb25maWcoY29uZmlnLCBvcHRpb25zKSB7XG4gICAgY29uc3QgY2hhcnREZWZhdWx0cyA9IG92ZXJyaWRlc1tjb25maWcudHlwZV0gfHwge1xuICAgICAgICBzY2FsZXM6IHt9XG4gICAgfTtcbiAgICBjb25zdCBjb25maWdTY2FsZXMgPSBvcHRpb25zLnNjYWxlcyB8fCB7fTtcbiAgICBjb25zdCBjaGFydEluZGV4QXhpcyA9IGdldEluZGV4QXhpcyhjb25maWcudHlwZSwgb3B0aW9ucyk7XG4gICAgY29uc3Qgc2NhbGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICBPYmplY3Qua2V5cyhjb25maWdTY2FsZXMpLmZvckVhY2goKGlkKT0+e1xuICAgICAgICBjb25zdCBzY2FsZUNvbmYgPSBjb25maWdTY2FsZXNbaWRdO1xuICAgICAgICBpZiAoIWlzT2JqZWN0KHNjYWxlQ29uZikpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25zb2xlLmVycm9yKGBJbnZhbGlkIHNjYWxlIGNvbmZpZ3VyYXRpb24gZm9yIHNjYWxlOiAke2lkfWApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzY2FsZUNvbmYuX3Byb3h5KSB7XG4gICAgICAgICAgICByZXR1cm4gY29uc29sZS53YXJuKGBJZ25vcmluZyByZXNvbHZlciBwYXNzZWQgYXMgb3B0aW9ucyBmb3Igc2NhbGU6ICR7aWR9YCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYXhpcyA9IGRldGVybWluZUF4aXMoaWQsIHNjYWxlQ29uZiwgcmV0cmlldmVBeGlzRnJvbURhdGFzZXRzKGlkLCBjb25maWcpLCBkZWZhdWx0cy5zY2FsZXNbc2NhbGVDb25mLnR5cGVdKTtcbiAgICAgICAgY29uc3QgZGVmYXVsdElkID0gZ2V0RGVmYXVsdFNjYWxlSURGcm9tQXhpcyhheGlzLCBjaGFydEluZGV4QXhpcyk7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRTY2FsZU9wdGlvbnMgPSBjaGFydERlZmF1bHRzLnNjYWxlcyB8fCB7fTtcbiAgICAgICAgc2NhbGVzW2lkXSA9IG1lcmdlSWYoT2JqZWN0LmNyZWF0ZShudWxsKSwgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGF4aXNcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzY2FsZUNvbmYsXG4gICAgICAgICAgICBkZWZhdWx0U2NhbGVPcHRpb25zW2F4aXNdLFxuICAgICAgICAgICAgZGVmYXVsdFNjYWxlT3B0aW9uc1tkZWZhdWx0SWRdXG4gICAgICAgIF0pO1xuICAgIH0pO1xuICAgIGNvbmZpZy5kYXRhLmRhdGFzZXRzLmZvckVhY2goKGRhdGFzZXQpPT57XG4gICAgICAgIGNvbnN0IHR5cGUgPSBkYXRhc2V0LnR5cGUgfHwgY29uZmlnLnR5cGU7XG4gICAgICAgIGNvbnN0IGluZGV4QXhpcyA9IGRhdGFzZXQuaW5kZXhBeGlzIHx8IGdldEluZGV4QXhpcyh0eXBlLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3QgZGF0YXNldERlZmF1bHRzID0gb3ZlcnJpZGVzW3R5cGVdIHx8IHt9O1xuICAgICAgICBjb25zdCBkZWZhdWx0U2NhbGVPcHRpb25zID0gZGF0YXNldERlZmF1bHRzLnNjYWxlcyB8fCB7fTtcbiAgICAgICAgT2JqZWN0LmtleXMoZGVmYXVsdFNjYWxlT3B0aW9ucykuZm9yRWFjaCgoZGVmYXVsdElEKT0+e1xuICAgICAgICAgICAgY29uc3QgYXhpcyA9IGdldEF4aXNGcm9tRGVmYXVsdFNjYWxlSUQoZGVmYXVsdElELCBpbmRleEF4aXMpO1xuICAgICAgICAgICAgY29uc3QgaWQgPSBkYXRhc2V0W2F4aXMgKyAnQXhpc0lEJ10gfHwgYXhpcztcbiAgICAgICAgICAgIHNjYWxlc1tpZF0gPSBzY2FsZXNbaWRdIHx8IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgICAgICBtZXJnZUlmKHNjYWxlc1tpZF0sIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGF4aXNcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNvbmZpZ1NjYWxlc1tpZF0sXG4gICAgICAgICAgICAgICAgZGVmYXVsdFNjYWxlT3B0aW9uc1tkZWZhdWx0SURdXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgT2JqZWN0LmtleXMoc2NhbGVzKS5mb3JFYWNoKChrZXkpPT57XG4gICAgICAgIGNvbnN0IHNjYWxlID0gc2NhbGVzW2tleV07XG4gICAgICAgIG1lcmdlSWYoc2NhbGUsIFtcbiAgICAgICAgICAgIGRlZmF1bHRzLnNjYWxlc1tzY2FsZS50eXBlXSxcbiAgICAgICAgICAgIGRlZmF1bHRzLnNjYWxlXG4gICAgICAgIF0pO1xuICAgIH0pO1xuICAgIHJldHVybiBzY2FsZXM7XG59XG5mdW5jdGlvbiBpbml0T3B0aW9ucyhjb25maWcpIHtcbiAgICBjb25zdCBvcHRpb25zID0gY29uZmlnLm9wdGlvbnMgfHwgKGNvbmZpZy5vcHRpb25zID0ge30pO1xuICAgIG9wdGlvbnMucGx1Z2lucyA9IHZhbHVlT3JEZWZhdWx0KG9wdGlvbnMucGx1Z2lucywge30pO1xuICAgIG9wdGlvbnMuc2NhbGVzID0gbWVyZ2VTY2FsZUNvbmZpZyhjb25maWcsIG9wdGlvbnMpO1xufVxuZnVuY3Rpb24gaW5pdERhdGEoZGF0YSkge1xuICAgIGRhdGEgPSBkYXRhIHx8IHt9O1xuICAgIGRhdGEuZGF0YXNldHMgPSBkYXRhLmRhdGFzZXRzIHx8IFtdO1xuICAgIGRhdGEubGFiZWxzID0gZGF0YS5sYWJlbHMgfHwgW107XG4gICAgcmV0dXJuIGRhdGE7XG59XG5mdW5jdGlvbiBpbml0Q29uZmlnKGNvbmZpZykge1xuICAgIGNvbmZpZyA9IGNvbmZpZyB8fCB7fTtcbiAgICBjb25maWcuZGF0YSA9IGluaXREYXRhKGNvbmZpZy5kYXRhKTtcbiAgICBpbml0T3B0aW9ucyhjb25maWcpO1xuICAgIHJldHVybiBjb25maWc7XG59XG5jb25zdCBrZXlDYWNoZSA9IG5ldyBNYXAoKTtcbmNvbnN0IGtleXNDYWNoZWQgPSBuZXcgU2V0KCk7XG5mdW5jdGlvbiBjYWNoZWRLZXlzKGNhY2hlS2V5LCBnZW5lcmF0ZSkge1xuICAgIGxldCBrZXlzID0ga2V5Q2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICBpZiAoIWtleXMpIHtcbiAgICAgICAga2V5cyA9IGdlbmVyYXRlKCk7XG4gICAgICAgIGtleUNhY2hlLnNldChjYWNoZUtleSwga2V5cyk7XG4gICAgICAgIGtleXNDYWNoZWQuYWRkKGtleXMpO1xuICAgIH1cbiAgICByZXR1cm4ga2V5cztcbn1cbmNvbnN0IGFkZElmRm91bmQgPSAoc2V0LCBvYmosIGtleSk9PntcbiAgICBjb25zdCBvcHRzID0gcmVzb2x2ZU9iamVjdEtleShvYmosIGtleSk7XG4gICAgaWYgKG9wdHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXQuYWRkKG9wdHMpO1xuICAgIH1cbn07XG5jbGFzcyBDb25maWcge1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZyl7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IGluaXRDb25maWcoY29uZmlnKTtcbiAgICAgICAgdGhpcy5fc2NvcGVDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fcmVzb2x2ZXJDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB9XG4gICAgZ2V0IHBsYXRmb3JtKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29uZmlnLnBsYXRmb3JtO1xuICAgIH1cbiAgICBnZXQgdHlwZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbmZpZy50eXBlO1xuICAgIH1cbiAgICBzZXQgdHlwZSh0eXBlKSB7XG4gICAgICAgIHRoaXMuX2NvbmZpZy50eXBlID0gdHlwZTtcbiAgICB9XG4gICAgZ2V0IGRhdGEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YTtcbiAgICB9XG4gICAgc2V0IGRhdGEoZGF0YSkge1xuICAgICAgICB0aGlzLl9jb25maWcuZGF0YSA9IGluaXREYXRhKGRhdGEpO1xuICAgIH1cbiAgICBnZXQgb3B0aW9ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5vcHRpb25zO1xuICAgIH1cbiAgICBzZXQgb3B0aW9ucyhvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuX2NvbmZpZy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB9XG4gICAgZ2V0IHBsdWdpbnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb25maWcucGx1Z2lucztcbiAgICB9XG4gICAgdXBkYXRlKCkge1xuICAgICAgICBjb25zdCBjb25maWcgPSB0aGlzLl9jb25maWc7XG4gICAgICAgIHRoaXMuY2xlYXJDYWNoZSgpO1xuICAgICAgICBpbml0T3B0aW9ucyhjb25maWcpO1xuICAgIH1cbiAgICBjbGVhckNhY2hlKCkge1xuICAgICAgICB0aGlzLl9zY29wZUNhY2hlLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuX3Jlc29sdmVyQ2FjaGUuY2xlYXIoKTtcbiAgICB9XG4gZGF0YXNldFNjb3BlS2V5cyhkYXRhc2V0VHlwZSkge1xuICAgICAgICByZXR1cm4gY2FjaGVkS2V5cyhkYXRhc2V0VHlwZSwgKCk9PltcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfWAsXG4gICAgICAgICAgICAgICAgICAgICcnXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgXSk7XG4gICAgfVxuIGRhdGFzZXRBbmltYXRpb25TY29wZUtleXMoZGF0YXNldFR5cGUsIHRyYW5zaXRpb24pIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZEtleXMoYCR7ZGF0YXNldFR5cGV9LnRyYW5zaXRpb24uJHt0cmFuc2l0aW9ufWAsICgpPT5bXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICBgZGF0YXNldHMuJHtkYXRhc2V0VHlwZX0udHJhbnNpdGlvbnMuJHt0cmFuc2l0aW9ufWAsXG4gICAgICAgICAgICAgICAgICAgIGB0cmFuc2l0aW9ucy4ke3RyYW5zaXRpb259YFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICBgZGF0YXNldHMuJHtkYXRhc2V0VHlwZX1gLFxuICAgICAgICAgICAgICAgICAgICAnJ1xuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIF0pO1xuICAgIH1cbiBkYXRhc2V0RWxlbWVudFNjb3BlS2V5cyhkYXRhc2V0VHlwZSwgZWxlbWVudFR5cGUpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZEtleXMoYCR7ZGF0YXNldFR5cGV9LSR7ZWxlbWVudFR5cGV9YCwgKCk9PltcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfS5lbGVtZW50cy4ke2VsZW1lbnRUeXBlfWAsXG4gICAgICAgICAgICAgICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfWAsXG4gICAgICAgICAgICAgICAgICAgIGBlbGVtZW50cy4ke2VsZW1lbnRUeXBlfWAsXG4gICAgICAgICAgICAgICAgICAgICcnXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgXSk7XG4gICAgfVxuIHBsdWdpblNjb3BlS2V5cyhwbHVnaW4pIHtcbiAgICAgICAgY29uc3QgaWQgPSBwbHVnaW4uaWQ7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB0aGlzLnR5cGU7XG4gICAgICAgIHJldHVybiBjYWNoZWRLZXlzKGAke3R5cGV9LXBsdWdpbi0ke2lkfWAsICgpPT5bXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICBgcGx1Z2lucy4ke2lkfWAsXG4gICAgICAgICAgICAgICAgICAgIC4uLnBsdWdpbi5hZGRpdGlvbmFsT3B0aW9uU2NvcGVzIHx8IFtdXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgXSk7XG4gICAgfVxuIF9jYWNoZWRTY29wZXMobWFpblNjb3BlLCByZXNldENhY2hlKSB7XG4gICAgICAgIGNvbnN0IF9zY29wZUNhY2hlID0gdGhpcy5fc2NvcGVDYWNoZTtcbiAgICAgICAgbGV0IGNhY2hlID0gX3Njb3BlQ2FjaGUuZ2V0KG1haW5TY29wZSk7XG4gICAgICAgIGlmICghY2FjaGUgfHwgcmVzZXRDYWNoZSkge1xuICAgICAgICAgICAgY2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICBfc2NvcGVDYWNoZS5zZXQobWFpblNjb3BlLCBjYWNoZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNhY2hlO1xuICAgIH1cbiBnZXRPcHRpb25TY29wZXMobWFpblNjb3BlLCBrZXlMaXN0cywgcmVzZXRDYWNoZSkge1xuICAgICAgICBjb25zdCB7IG9wdGlvbnMgLCB0eXBlICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgY2FjaGUgPSB0aGlzLl9jYWNoZWRTY29wZXMobWFpblNjb3BlLCByZXNldENhY2hlKTtcbiAgICAgICAgY29uc3QgY2FjaGVkID0gY2FjaGUuZ2V0KGtleUxpc3RzKTtcbiAgICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzY29wZXMgPSBuZXcgU2V0KCk7XG4gICAgICAgIGtleUxpc3RzLmZvckVhY2goKGtleXMpPT57XG4gICAgICAgICAgICBpZiAobWFpblNjb3BlKSB7XG4gICAgICAgICAgICAgICAgc2NvcGVzLmFkZChtYWluU2NvcGUpO1xuICAgICAgICAgICAgICAgIGtleXMuZm9yRWFjaCgoa2V5KT0+YWRkSWZGb3VuZChzY29wZXMsIG1haW5TY29wZSwga2V5KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBrZXlzLmZvckVhY2goKGtleSk9PmFkZElmRm91bmQoc2NvcGVzLCBvcHRpb25zLCBrZXkpKTtcbiAgICAgICAgICAgIGtleXMuZm9yRWFjaCgoa2V5KT0+YWRkSWZGb3VuZChzY29wZXMsIG92ZXJyaWRlc1t0eXBlXSB8fCB7fSwga2V5KSk7XG4gICAgICAgICAgICBrZXlzLmZvckVhY2goKGtleSk9PmFkZElmRm91bmQoc2NvcGVzLCBkZWZhdWx0cywga2V5KSk7XG4gICAgICAgICAgICBrZXlzLmZvckVhY2goKGtleSk9PmFkZElmRm91bmQoc2NvcGVzLCBkZXNjcmlwdG9ycywga2V5KSk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBhcnJheSA9IEFycmF5LmZyb20oc2NvcGVzKTtcbiAgICAgICAgaWYgKGFycmF5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgYXJyYXkucHVzaChPYmplY3QuY3JlYXRlKG51bGwpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoa2V5c0NhY2hlZC5oYXMoa2V5TGlzdHMpKSB7XG4gICAgICAgICAgICBjYWNoZS5zZXQoa2V5TGlzdHMsIGFycmF5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuIGNoYXJ0T3B0aW9uU2NvcGVzKCkge1xuICAgICAgICBjb25zdCB7IG9wdGlvbnMgLCB0eXBlICB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgICBvdmVycmlkZXNbdHlwZV0gfHwge30sXG4gICAgICAgICAgICBkZWZhdWx0cy5kYXRhc2V0c1t0eXBlXSB8fCB7fSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eXBlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVmYXVsdHMsXG4gICAgICAgICAgICBkZXNjcmlwdG9yc1xuICAgICAgICBdO1xuICAgIH1cbiByZXNvbHZlTmFtZWRPcHRpb25zKHNjb3BlcywgbmFtZXMsIGNvbnRleHQsIHByZWZpeGVzID0gW1xuICAgICAgICAnJ1xuICAgIF0pIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0ge1xuICAgICAgICAgICAgJHNoYXJlZDogdHJ1ZVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB7IHJlc29sdmVyICwgc3ViUHJlZml4ZXMgIH0gPSBnZXRSZXNvbHZlcih0aGlzLl9yZXNvbHZlckNhY2hlLCBzY29wZXMsIHByZWZpeGVzKTtcbiAgICAgICAgbGV0IG9wdGlvbnMgPSByZXNvbHZlcjtcbiAgICAgICAgaWYgKG5lZWRDb250ZXh0KHJlc29sdmVyLCBuYW1lcykpIHtcbiAgICAgICAgICAgIHJlc3VsdC4kc2hhcmVkID0gZmFsc2U7XG4gICAgICAgICAgICBjb250ZXh0ID0gaXNGdW5jdGlvbihjb250ZXh0KSA/IGNvbnRleHQoKSA6IGNvbnRleHQ7XG4gICAgICAgICAgICBjb25zdCBzdWJSZXNvbHZlciA9IHRoaXMuY3JlYXRlUmVzb2x2ZXIoc2NvcGVzLCBjb250ZXh0LCBzdWJQcmVmaXhlcyk7XG4gICAgICAgICAgICBvcHRpb25zID0gX2F0dGFjaENvbnRleHQocmVzb2x2ZXIsIGNvbnRleHQsIHN1YlJlc29sdmVyKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IHByb3Agb2YgbmFtZXMpe1xuICAgICAgICAgICAgcmVzdWx0W3Byb3BdID0gb3B0aW9uc1twcm9wXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiBjcmVhdGVSZXNvbHZlcihzY29wZXMsIGNvbnRleHQsIHByZWZpeGVzID0gW1xuICAgICAgICAnJ1xuICAgIF0sIGRlc2NyaXB0b3JEZWZhdWx0cykge1xuICAgICAgICBjb25zdCB7IHJlc29sdmVyICB9ID0gZ2V0UmVzb2x2ZXIodGhpcy5fcmVzb2x2ZXJDYWNoZSwgc2NvcGVzLCBwcmVmaXhlcyk7XG4gICAgICAgIHJldHVybiBpc09iamVjdChjb250ZXh0KSA/IF9hdHRhY2hDb250ZXh0KHJlc29sdmVyLCBjb250ZXh0LCB1bmRlZmluZWQsIGRlc2NyaXB0b3JEZWZhdWx0cykgOiByZXNvbHZlcjtcbiAgICB9XG59XG5mdW5jdGlvbiBnZXRSZXNvbHZlcihyZXNvbHZlckNhY2hlLCBzY29wZXMsIHByZWZpeGVzKSB7XG4gICAgbGV0IGNhY2hlID0gcmVzb2x2ZXJDYWNoZS5nZXQoc2NvcGVzKTtcbiAgICBpZiAoIWNhY2hlKSB7XG4gICAgICAgIGNhY2hlID0gbmV3IE1hcCgpO1xuICAgICAgICByZXNvbHZlckNhY2hlLnNldChzY29wZXMsIGNhY2hlKTtcbiAgICB9XG4gICAgY29uc3QgY2FjaGVLZXkgPSBwcmVmaXhlcy5qb2luKCk7XG4gICAgbGV0IGNhY2hlZCA9IGNhY2hlLmdldChjYWNoZUtleSk7XG4gICAgaWYgKCFjYWNoZWQpIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSBfY3JlYXRlUmVzb2x2ZXIoc2NvcGVzLCBwcmVmaXhlcyk7XG4gICAgICAgIGNhY2hlZCA9IHtcbiAgICAgICAgICAgIHJlc29sdmVyLFxuICAgICAgICAgICAgc3ViUHJlZml4ZXM6IHByZWZpeGVzLmZpbHRlcigocCk9PiFwLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ2hvdmVyJykpXG4gICAgICAgIH07XG4gICAgICAgIGNhY2hlLnNldChjYWNoZUtleSwgY2FjaGVkKTtcbiAgICB9XG4gICAgcmV0dXJuIGNhY2hlZDtcbn1cbmNvbnN0IGhhc0Z1bmN0aW9uID0gKHZhbHVlKT0+aXNPYmplY3QodmFsdWUpICYmIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHZhbHVlKS5zb21lKChrZXkpPT5pc0Z1bmN0aW9uKHZhbHVlW2tleV0pKTtcbmZ1bmN0aW9uIG5lZWRDb250ZXh0KHByb3h5LCBuYW1lcykge1xuICAgIGNvbnN0IHsgaXNTY3JpcHRhYmxlICwgaXNJbmRleGFibGUgIH0gPSBfZGVzY3JpcHRvcnMocHJveHkpO1xuICAgIGZvciAoY29uc3QgcHJvcCBvZiBuYW1lcyl7XG4gICAgICAgIGNvbnN0IHNjcmlwdGFibGUgPSBpc1NjcmlwdGFibGUocHJvcCk7XG4gICAgICAgIGNvbnN0IGluZGV4YWJsZSA9IGlzSW5kZXhhYmxlKHByb3ApO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IChpbmRleGFibGUgfHwgc2NyaXB0YWJsZSkgJiYgcHJveHlbcHJvcF07XG4gICAgICAgIGlmIChzY3JpcHRhYmxlICYmIChpc0Z1bmN0aW9uKHZhbHVlKSB8fCBoYXNGdW5jdGlvbih2YWx1ZSkpIHx8IGluZGV4YWJsZSAmJiBpc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG52YXIgdmVyc2lvbiA9IFwiNC41LjBcIjtcblxuY29uc3QgS05PV05fUE9TSVRJT05TID0gW1xuICAgICd0b3AnLFxuICAgICdib3R0b20nLFxuICAgICdsZWZ0JyxcbiAgICAncmlnaHQnLFxuICAgICdjaGFydEFyZWEnXG5dO1xuZnVuY3Rpb24gcG9zaXRpb25Jc0hvcml6b250YWwocG9zaXRpb24sIGF4aXMpIHtcbiAgICByZXR1cm4gcG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJyB8fCBLTk9XTl9QT1NJVElPTlMuaW5kZXhPZihwb3NpdGlvbikgPT09IC0xICYmIGF4aXMgPT09ICd4Jztcbn1cbmZ1bmN0aW9uIGNvbXBhcmUyTGV2ZWwobDEsIGwyKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGFbbDFdID09PSBiW2wxXSA/IGFbbDJdIC0gYltsMl0gOiBhW2wxXSAtIGJbbDFdO1xuICAgIH07XG59XG5mdW5jdGlvbiBvbkFuaW1hdGlvbnNDb21wbGV0ZShjb250ZXh0KSB7XG4gICAgY29uc3QgY2hhcnQgPSBjb250ZXh0LmNoYXJ0O1xuICAgIGNvbnN0IGFuaW1hdGlvbk9wdGlvbnMgPSBjaGFydC5vcHRpb25zLmFuaW1hdGlvbjtcbiAgICBjaGFydC5ub3RpZnlQbHVnaW5zKCdhZnRlclJlbmRlcicpO1xuICAgIGNhbGxiYWNrKGFuaW1hdGlvbk9wdGlvbnMgJiYgYW5pbWF0aW9uT3B0aW9ucy5vbkNvbXBsZXRlLCBbXG4gICAgICAgIGNvbnRleHRcbiAgICBdLCBjaGFydCk7XG59XG5mdW5jdGlvbiBvbkFuaW1hdGlvblByb2dyZXNzKGNvbnRleHQpIHtcbiAgICBjb25zdCBjaGFydCA9IGNvbnRleHQuY2hhcnQ7XG4gICAgY29uc3QgYW5pbWF0aW9uT3B0aW9ucyA9IGNoYXJ0Lm9wdGlvbnMuYW5pbWF0aW9uO1xuICAgIGNhbGxiYWNrKGFuaW1hdGlvbk9wdGlvbnMgJiYgYW5pbWF0aW9uT3B0aW9ucy5vblByb2dyZXNzLCBbXG4gICAgICAgIGNvbnRleHRcbiAgICBdLCBjaGFydCk7XG59XG4gZnVuY3Rpb24gZ2V0Q2FudmFzKGl0ZW0pIHtcbiAgICBpZiAoX2lzRG9tU3VwcG9ydGVkKCkgJiYgdHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGl0ZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpdGVtKTtcbiAgICB9IGVsc2UgaWYgKGl0ZW0gJiYgaXRlbS5sZW5ndGgpIHtcbiAgICAgICAgaXRlbSA9IGl0ZW1bMF07XG4gICAgfVxuICAgIGlmIChpdGVtICYmIGl0ZW0uY2FudmFzKSB7XG4gICAgICAgIGl0ZW0gPSBpdGVtLmNhbnZhcztcbiAgICB9XG4gICAgcmV0dXJuIGl0ZW07XG59XG5jb25zdCBpbnN0YW5jZXMgPSB7fTtcbmNvbnN0IGdldENoYXJ0ID0gKGtleSk9PntcbiAgICBjb25zdCBjYW52YXMgPSBnZXRDYW52YXMoa2V5KTtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhpbnN0YW5jZXMpLmZpbHRlcigoYyk9PmMuY2FudmFzID09PSBjYW52YXMpLnBvcCgpO1xufTtcbmZ1bmN0aW9uIG1vdmVOdW1lcmljS2V5cyhvYmosIHN0YXJ0LCBtb3ZlKSB7XG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cyl7XG4gICAgICAgIGNvbnN0IGludEtleSA9ICtrZXk7XG4gICAgICAgIGlmIChpbnRLZXkgPj0gc3RhcnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gb2JqW2tleV07XG4gICAgICAgICAgICBkZWxldGUgb2JqW2tleV07XG4gICAgICAgICAgICBpZiAobW92ZSA+IDAgfHwgaW50S2V5ID4gc3RhcnQpIHtcbiAgICAgICAgICAgICAgICBvYmpbaW50S2V5ICsgbW92ZV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbiBmdW5jdGlvbiBkZXRlcm1pbmVMYXN0RXZlbnQoZSwgbGFzdEV2ZW50LCBpbkNoYXJ0QXJlYSwgaXNDbGljaykge1xuICAgIGlmICghaW5DaGFydEFyZWEgfHwgZS50eXBlID09PSAnbW91c2VvdXQnKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoaXNDbGljaykge1xuICAgICAgICByZXR1cm4gbGFzdEV2ZW50O1xuICAgIH1cbiAgICByZXR1cm4gZTtcbn1cbmNsYXNzIENoYXJ0IHtcbiAgICBzdGF0aWMgZGVmYXVsdHMgPSBkZWZhdWx0cztcbiAgICBzdGF0aWMgaW5zdGFuY2VzID0gaW5zdGFuY2VzO1xuICAgIHN0YXRpYyBvdmVycmlkZXMgPSBvdmVycmlkZXM7XG4gICAgc3RhdGljIHJlZ2lzdHJ5ID0gcmVnaXN0cnk7XG4gICAgc3RhdGljIHZlcnNpb24gPSB2ZXJzaW9uO1xuICAgIHN0YXRpYyBnZXRDaGFydCA9IGdldENoYXJ0O1xuICAgIHN0YXRpYyByZWdpc3RlciguLi5pdGVtcykge1xuICAgICAgICByZWdpc3RyeS5hZGQoLi4uaXRlbXMpO1xuICAgICAgICBpbnZhbGlkYXRlUGx1Z2lucygpO1xuICAgIH1cbiAgICBzdGF0aWMgdW5yZWdpc3RlciguLi5pdGVtcykge1xuICAgICAgICByZWdpc3RyeS5yZW1vdmUoLi4uaXRlbXMpO1xuICAgICAgICBpbnZhbGlkYXRlUGx1Z2lucygpO1xuICAgIH1cbiAgICBjb25zdHJ1Y3RvcihpdGVtLCB1c2VyQ29uZmlnKXtcbiAgICAgICAgY29uc3QgY29uZmlnID0gdGhpcy5jb25maWcgPSBuZXcgQ29uZmlnKHVzZXJDb25maWcpO1xuICAgICAgICBjb25zdCBpbml0aWFsQ2FudmFzID0gZ2V0Q2FudmFzKGl0ZW0pO1xuICAgICAgICBjb25zdCBleGlzdGluZ0NoYXJ0ID0gZ2V0Q2hhcnQoaW5pdGlhbENhbnZhcyk7XG4gICAgICAgIGlmIChleGlzdGluZ0NoYXJ0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbnZhcyBpcyBhbHJlYWR5IGluIHVzZS4gQ2hhcnQgd2l0aCBJRCBcXCcnICsgZXhpc3RpbmdDaGFydC5pZCArICdcXCcnICsgJyBtdXN0IGJlIGRlc3Ryb3llZCBiZWZvcmUgdGhlIGNhbnZhcyB3aXRoIElEIFxcJycgKyBleGlzdGluZ0NoYXJ0LmNhbnZhcy5pZCArICdcXCcgY2FuIGJlIHJldXNlZC4nKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcHRpb25zID0gY29uZmlnLmNyZWF0ZVJlc29sdmVyKGNvbmZpZy5jaGFydE9wdGlvblNjb3BlcygpLCB0aGlzLmdldENvbnRleHQoKSk7XG4gICAgICAgIHRoaXMucGxhdGZvcm0gPSBuZXcgKGNvbmZpZy5wbGF0Zm9ybSB8fCBfZGV0ZWN0UGxhdGZvcm0oaW5pdGlhbENhbnZhcykpKCk7XG4gICAgICAgIHRoaXMucGxhdGZvcm0udXBkYXRlQ29uZmlnKGNvbmZpZyk7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLnBsYXRmb3JtLmFjcXVpcmVDb250ZXh0KGluaXRpYWxDYW52YXMsIG9wdGlvbnMuYXNwZWN0UmF0aW8pO1xuICAgICAgICBjb25zdCBjYW52YXMgPSBjb250ZXh0ICYmIGNvbnRleHQuY2FudmFzO1xuICAgICAgICBjb25zdCBoZWlnaHQgPSBjYW52YXMgJiYgY2FudmFzLmhlaWdodDtcbiAgICAgICAgY29uc3Qgd2lkdGggPSBjYW52YXMgJiYgY2FudmFzLndpZHRoO1xuICAgICAgICB0aGlzLmlkID0gdWlkKCk7XG4gICAgICAgIHRoaXMuY3R4ID0gY29udGV4dDtcbiAgICAgICAgdGhpcy5jYW52YXMgPSBjYW52YXM7XG4gICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICB0aGlzLl9hc3BlY3RSYXRpbyA9IHRoaXMuYXNwZWN0UmF0aW87XG4gICAgICAgIHRoaXMuX2xheWVycyA9IFtdO1xuICAgICAgICB0aGlzLl9tZXRhc2V0cyA9IFtdO1xuICAgICAgICB0aGlzLl9zdGFja3MgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuYm94ZXMgPSBbXTtcbiAgICAgICAgdGhpcy5jdXJyZW50RGV2aWNlUGl4ZWxSYXRpbyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5jaGFydEFyZWEgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2FjdGl2ZSA9IFtdO1xuICAgICAgICB0aGlzLl9sYXN0RXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2xpc3RlbmVycyA9IHt9O1xuICAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fc29ydGVkTWV0YXNldHMgPSBbXTtcbiAgICAgICAgdGhpcy5zY2FsZXMgPSB7fTtcbiAgICAgICAgdGhpcy5fcGx1Z2lucyA9IG5ldyBQbHVnaW5TZXJ2aWNlKCk7XG4gICAgICAgIHRoaXMuJHByb3hpZXMgPSB7fTtcbiAgICAgICAgdGhpcy5faGlkZGVuSW5kaWNlcyA9IHt9O1xuICAgICAgICB0aGlzLmF0dGFjaGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2FuaW1hdGlvbnNEaXNhYmxlZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fZG9SZXNpemUgPSBkZWJvdW5jZSgobW9kZSk9PnRoaXMudXBkYXRlKG1vZGUpLCBvcHRpb25zLnJlc2l6ZURlbGF5IHx8IDApO1xuICAgICAgICB0aGlzLl9kYXRhQ2hhbmdlcyA9IFtdO1xuICAgICAgICBpbnN0YW5jZXNbdGhpcy5pZF0gPSB0aGlzO1xuICAgICAgICBpZiAoIWNvbnRleHQgfHwgIWNhbnZhcykge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkZhaWxlZCB0byBjcmVhdGUgY2hhcnQ6IGNhbid0IGFjcXVpcmUgY29udGV4dCBmcm9tIHRoZSBnaXZlbiBpdGVtXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGFuaW1hdG9yLmxpc3Rlbih0aGlzLCAnY29tcGxldGUnLCBvbkFuaW1hdGlvbnNDb21wbGV0ZSk7XG4gICAgICAgIGFuaW1hdG9yLmxpc3Rlbih0aGlzLCAncHJvZ3Jlc3MnLCBvbkFuaW1hdGlvblByb2dyZXNzKTtcbiAgICAgICAgdGhpcy5faW5pdGlhbGl6ZSgpO1xuICAgICAgICBpZiAodGhpcy5hdHRhY2hlZCkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGUoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXQgYXNwZWN0UmF0aW8oKSB7XG4gICAgICAgIGNvbnN0IHsgb3B0aW9uczogeyBhc3BlY3RSYXRpbyAsIG1haW50YWluQXNwZWN0UmF0aW8gIH0gLCB3aWR0aCAsIGhlaWdodCAsIF9hc3BlY3RSYXRpbyAgfSA9IHRoaXM7XG4gICAgICAgIGlmICghaXNOdWxsT3JVbmRlZihhc3BlY3RSYXRpbykpIHtcbiAgICAgICAgICAgIHJldHVybiBhc3BlY3RSYXRpbztcbiAgICAgICAgfVxuICAgICAgICBpZiAobWFpbnRhaW5Bc3BlY3RSYXRpbyAmJiBfYXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICAgIHJldHVybiBfYXNwZWN0UmF0aW87XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGhlaWdodCA/IHdpZHRoIC8gaGVpZ2h0IDogbnVsbDtcbiAgICB9XG4gICAgZ2V0IGRhdGEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhO1xuICAgIH1cbiAgICBzZXQgZGF0YShkYXRhKSB7XG4gICAgICAgIHRoaXMuY29uZmlnLmRhdGEgPSBkYXRhO1xuICAgIH1cbiAgICBnZXQgb3B0aW9ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gICAgfVxuICAgIHNldCBvcHRpb25zKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5jb25maWcub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfVxuICAgIGdldCByZWdpc3RyeSgpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdHJ5O1xuICAgIH1cbiBfaW5pdGlhbGl6ZSgpIHtcbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVJbml0Jyk7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmVzcG9uc2l2ZSkge1xuICAgICAgICAgICAgdGhpcy5yZXNpemUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldGluYVNjYWxlKHRoaXMsIHRoaXMub3B0aW9ucy5kZXZpY2VQaXhlbFJhdGlvKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJpbmRFdmVudHMoKTtcbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdhZnRlckluaXQnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGNsZWFyKCkge1xuICAgICAgICBjbGVhckNhbnZhcyh0aGlzLmNhbnZhcywgdGhpcy5jdHgpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc3RvcCgpIHtcbiAgICAgICAgYW5pbWF0b3Iuc3RvcCh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuIHJlc2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIGlmICghYW5pbWF0b3IucnVubmluZyh0aGlzKSkge1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplQmVmb3JlRHJhdyA9IHtcbiAgICAgICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgX3Jlc2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGNhbnZhcyA9IHRoaXMuY2FudmFzO1xuICAgICAgICBjb25zdCBhc3BlY3RSYXRpbyA9IG9wdGlvbnMubWFpbnRhaW5Bc3BlY3RSYXRpbyAmJiB0aGlzLmFzcGVjdFJhdGlvO1xuICAgICAgICBjb25zdCBuZXdTaXplID0gdGhpcy5wbGF0Zm9ybS5nZXRNYXhpbXVtU2l6ZShjYW52YXMsIHdpZHRoLCBoZWlnaHQsIGFzcGVjdFJhdGlvKTtcbiAgICAgICAgY29uc3QgbmV3UmF0aW8gPSBvcHRpb25zLmRldmljZVBpeGVsUmF0aW8gfHwgdGhpcy5wbGF0Zm9ybS5nZXREZXZpY2VQaXhlbFJhdGlvKCk7XG4gICAgICAgIGNvbnN0IG1vZGUgPSB0aGlzLndpZHRoID8gJ3Jlc2l6ZScgOiAnYXR0YWNoJztcbiAgICAgICAgdGhpcy53aWR0aCA9IG5ld1NpemUud2lkdGg7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gbmV3U2l6ZS5oZWlnaHQ7XG4gICAgICAgIHRoaXMuX2FzcGVjdFJhdGlvID0gdGhpcy5hc3BlY3RSYXRpbztcbiAgICAgICAgaWYgKCFyZXRpbmFTY2FsZSh0aGlzLCBuZXdSYXRpbywgdHJ1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ3Jlc2l6ZScsIHtcbiAgICAgICAgICAgIHNpemU6IG5ld1NpemVcbiAgICAgICAgfSk7XG4gICAgICAgIGNhbGxiYWNrKG9wdGlvbnMub25SZXNpemUsIFtcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICBuZXdTaXplXG4gICAgICAgIF0sIHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5hdHRhY2hlZCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2RvUmVzaXplKG1vZGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBlbnN1cmVTY2FsZXNIYXZlSURzKCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBzY2FsZXNPcHRpb25zID0gb3B0aW9ucy5zY2FsZXMgfHwge307XG4gICAgICAgIGVhY2goc2NhbGVzT3B0aW9ucywgKGF4aXNPcHRpb25zLCBheGlzSUQpPT57XG4gICAgICAgICAgICBheGlzT3B0aW9ucy5pZCA9IGF4aXNJRDtcbiAgICAgICAgfSk7XG4gICAgfVxuIGJ1aWxkT3JVcGRhdGVTY2FsZXMoKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHNjYWxlT3B0cyA9IG9wdGlvbnMuc2NhbGVzO1xuICAgICAgICBjb25zdCBzY2FsZXMgPSB0aGlzLnNjYWxlcztcbiAgICAgICAgY29uc3QgdXBkYXRlZCA9IE9iamVjdC5rZXlzKHNjYWxlcykucmVkdWNlKChvYmosIGlkKT0+e1xuICAgICAgICAgICAgb2JqW2lkXSA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgfSwge30pO1xuICAgICAgICBsZXQgaXRlbXMgPSBbXTtcbiAgICAgICAgaWYgKHNjYWxlT3B0cykge1xuICAgICAgICAgICAgaXRlbXMgPSBpdGVtcy5jb25jYXQoT2JqZWN0LmtleXMoc2NhbGVPcHRzKS5tYXAoKGlkKT0+e1xuICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlT3B0aW9ucyA9IHNjYWxlT3B0c1tpZF07XG4gICAgICAgICAgICAgICAgY29uc3QgYXhpcyA9IGRldGVybWluZUF4aXMoaWQsIHNjYWxlT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNSYWRpYWwgPSBheGlzID09PSAncic7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNIb3Jpem9udGFsID0gYXhpcyA9PT0gJ3gnO1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IHNjYWxlT3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgZHBvc2l0aW9uOiBpc1JhZGlhbCA/ICdjaGFydEFyZWEnIDogaXNIb3Jpem9udGFsID8gJ2JvdHRvbScgOiAnbGVmdCcsXG4gICAgICAgICAgICAgICAgICAgIGR0eXBlOiBpc1JhZGlhbCA/ICdyYWRpYWxMaW5lYXInIDogaXNIb3Jpem9udGFsID8gJ2NhdGVnb3J5JyA6ICdsaW5lYXInXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgICBlYWNoKGl0ZW1zLCAoaXRlbSk9PntcbiAgICAgICAgICAgIGNvbnN0IHNjYWxlT3B0aW9ucyA9IGl0ZW0ub3B0aW9ucztcbiAgICAgICAgICAgIGNvbnN0IGlkID0gc2NhbGVPcHRpb25zLmlkO1xuICAgICAgICAgICAgY29uc3QgYXhpcyA9IGRldGVybWluZUF4aXMoaWQsIHNjYWxlT3B0aW9ucyk7XG4gICAgICAgICAgICBjb25zdCBzY2FsZVR5cGUgPSB2YWx1ZU9yRGVmYXVsdChzY2FsZU9wdGlvbnMudHlwZSwgaXRlbS5kdHlwZSk7XG4gICAgICAgICAgICBpZiAoc2NhbGVPcHRpb25zLnBvc2l0aW9uID09PSB1bmRlZmluZWQgfHwgcG9zaXRpb25Jc0hvcml6b250YWwoc2NhbGVPcHRpb25zLnBvc2l0aW9uLCBheGlzKSAhPT0gcG9zaXRpb25Jc0hvcml6b250YWwoaXRlbS5kcG9zaXRpb24pKSB7XG4gICAgICAgICAgICAgICAgc2NhbGVPcHRpb25zLnBvc2l0aW9uID0gaXRlbS5kcG9zaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB1cGRhdGVkW2lkXSA9IHRydWU7XG4gICAgICAgICAgICBsZXQgc2NhbGUgPSBudWxsO1xuICAgICAgICAgICAgaWYgKGlkIGluIHNjYWxlcyAmJiBzY2FsZXNbaWRdLnR5cGUgPT09IHNjYWxlVHlwZSkge1xuICAgICAgICAgICAgICAgIHNjYWxlID0gc2NhbGVzW2lkXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVDbGFzcyA9IHJlZ2lzdHJ5LmdldFNjYWxlKHNjYWxlVHlwZSk7XG4gICAgICAgICAgICAgICAgc2NhbGUgPSBuZXcgc2NhbGVDbGFzcyh7XG4gICAgICAgICAgICAgICAgICAgIGlkLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBzY2FsZVR5cGUsXG4gICAgICAgICAgICAgICAgICAgIGN0eDogdGhpcy5jdHgsXG4gICAgICAgICAgICAgICAgICAgIGNoYXJ0OiB0aGlzXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc2NhbGVzW3NjYWxlLmlkXSA9IHNjYWxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2NhbGUuaW5pdChzY2FsZU9wdGlvbnMsIG9wdGlvbnMpO1xuICAgICAgICB9KTtcbiAgICAgICAgZWFjaCh1cGRhdGVkLCAoaGFzVXBkYXRlZCwgaWQpPT57XG4gICAgICAgICAgICBpZiAoIWhhc1VwZGF0ZWQpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgc2NhbGVzW2lkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGVhY2goc2NhbGVzLCAoc2NhbGUpPT57XG4gICAgICAgICAgICBsYXlvdXRzLmNvbmZpZ3VyZSh0aGlzLCBzY2FsZSwgc2NhbGUub3B0aW9ucyk7XG4gICAgICAgICAgICBsYXlvdXRzLmFkZEJveCh0aGlzLCBzY2FsZSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiBfdXBkYXRlTWV0YXNldHMoKSB7XG4gICAgICAgIGNvbnN0IG1ldGFzZXRzID0gdGhpcy5fbWV0YXNldHM7XG4gICAgICAgIGNvbnN0IG51bURhdGEgPSB0aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoO1xuICAgICAgICBjb25zdCBudW1NZXRhID0gbWV0YXNldHMubGVuZ3RoO1xuICAgICAgICBtZXRhc2V0cy5zb3J0KChhLCBiKT0+YS5pbmRleCAtIGIuaW5kZXgpO1xuICAgICAgICBpZiAobnVtTWV0YSA+IG51bURhdGEpIHtcbiAgICAgICAgICAgIGZvcihsZXQgaSA9IG51bURhdGE7IGkgPCBudW1NZXRhOyArK2kpe1xuICAgICAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lEYXRhc2V0TWV0YShpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1ldGFzZXRzLnNwbGljZShudW1EYXRhLCBudW1NZXRhIC0gbnVtRGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc29ydGVkTWV0YXNldHMgPSBtZXRhc2V0cy5zbGljZSgwKS5zb3J0KGNvbXBhcmUyTGV2ZWwoJ29yZGVyJywgJ2luZGV4JykpO1xuICAgIH1cbiBfcmVtb3ZlVW5yZWZlcmVuY2VkTWV0YXNldHMoKSB7XG4gICAgICAgIGNvbnN0IHsgX21ldGFzZXRzOiBtZXRhc2V0cyAsIGRhdGE6IHsgZGF0YXNldHMgIH0gIH0gPSB0aGlzO1xuICAgICAgICBpZiAobWV0YXNldHMubGVuZ3RoID4gZGF0YXNldHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fc3RhY2tzO1xuICAgICAgICB9XG4gICAgICAgIG1ldGFzZXRzLmZvckVhY2goKG1ldGEsIGluZGV4KT0+e1xuICAgICAgICAgICAgaWYgKGRhdGFzZXRzLmZpbHRlcigoeCk9PnggPT09IG1ldGEuX2RhdGFzZXQpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lEYXRhc2V0TWV0YShpbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBidWlsZE9yVXBkYXRlQ29udHJvbGxlcnMoKSB7XG4gICAgICAgIGNvbnN0IG5ld0NvbnRyb2xsZXJzID0gW107XG4gICAgICAgIGNvbnN0IGRhdGFzZXRzID0gdGhpcy5kYXRhLmRhdGFzZXRzO1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgdGhpcy5fcmVtb3ZlVW5yZWZlcmVuY2VkTWV0YXNldHMoKTtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IGRhdGFzZXQgPSBkYXRhc2V0c1tpXTtcbiAgICAgICAgICAgIGxldCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShpKTtcbiAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBkYXRhc2V0LnR5cGUgfHwgdGhpcy5jb25maWcudHlwZTtcbiAgICAgICAgICAgIGlmIChtZXRhLnR5cGUgJiYgbWV0YS50eXBlICE9PSB0eXBlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGVzdHJveURhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgICAgIG1ldGEgPSB0aGlzLmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWV0YS50eXBlID0gdHlwZTtcbiAgICAgICAgICAgIG1ldGEuaW5kZXhBeGlzID0gZGF0YXNldC5pbmRleEF4aXMgfHwgZ2V0SW5kZXhBeGlzKHR5cGUsIHRoaXMub3B0aW9ucyk7XG4gICAgICAgICAgICBtZXRhLm9yZGVyID0gZGF0YXNldC5vcmRlciB8fCAwO1xuICAgICAgICAgICAgbWV0YS5pbmRleCA9IGk7XG4gICAgICAgICAgICBtZXRhLmxhYmVsID0gJycgKyBkYXRhc2V0LmxhYmVsO1xuICAgICAgICAgICAgbWV0YS52aXNpYmxlID0gdGhpcy5pc0RhdGFzZXRWaXNpYmxlKGkpO1xuICAgICAgICAgICAgaWYgKG1ldGEuY29udHJvbGxlcikge1xuICAgICAgICAgICAgICAgIG1ldGEuY29udHJvbGxlci51cGRhdGVJbmRleChpKTtcbiAgICAgICAgICAgICAgICBtZXRhLmNvbnRyb2xsZXIubGlua1NjYWxlcygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBDb250cm9sbGVyQ2xhc3MgPSByZWdpc3RyeS5nZXRDb250cm9sbGVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgZGF0YXNldEVsZW1lbnRUeXBlICwgZGF0YUVsZW1lbnRUeXBlICB9ID0gZGVmYXVsdHMuZGF0YXNldHNbdHlwZV07XG4gICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihDb250cm9sbGVyQ2xhc3MsIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiByZWdpc3RyeS5nZXRFbGVtZW50KGRhdGFFbGVtZW50VHlwZSksXG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXRFbGVtZW50VHlwZTogZGF0YXNldEVsZW1lbnRUeXBlICYmIHJlZ2lzdHJ5LmdldEVsZW1lbnQoZGF0YXNldEVsZW1lbnRUeXBlKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIG1ldGEuY29udHJvbGxlciA9IG5ldyBDb250cm9sbGVyQ2xhc3ModGhpcywgaSk7XG4gICAgICAgICAgICAgICAgbmV3Q29udHJvbGxlcnMucHVzaChtZXRhLmNvbnRyb2xsZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3VwZGF0ZU1ldGFzZXRzKCk7XG4gICAgICAgIHJldHVybiBuZXdDb250cm9sbGVycztcbiAgICB9XG4gX3Jlc2V0RWxlbWVudHMoKSB7XG4gICAgICAgIGVhY2godGhpcy5kYXRhLmRhdGFzZXRzLCAoZGF0YXNldCwgZGF0YXNldEluZGV4KT0+e1xuICAgICAgICAgICAgdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpLmNvbnRyb2xsZXIucmVzZXQoKTtcbiAgICAgICAgfSwgdGhpcyk7XG4gICAgfVxuIHJlc2V0KCkge1xuICAgICAgICB0aGlzLl9yZXNldEVsZW1lbnRzKCk7XG4gICAgICAgIHRoaXMubm90aWZ5UGx1Z2lucygncmVzZXQnKTtcbiAgICB9XG4gICAgdXBkYXRlKG1vZGUpIHtcbiAgICAgICAgY29uc3QgY29uZmlnID0gdGhpcy5jb25maWc7XG4gICAgICAgIGNvbmZpZy51cGRhdGUoKTtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuX29wdGlvbnMgPSBjb25maWcuY3JlYXRlUmVzb2x2ZXIoY29uZmlnLmNoYXJ0T3B0aW9uU2NvcGVzKCksIHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgY29uc3QgYW5pbXNEaXNhYmxlZCA9IHRoaXMuX2FuaW1hdGlvbnNEaXNhYmxlZCA9ICFvcHRpb25zLmFuaW1hdGlvbjtcbiAgICAgICAgdGhpcy5fdXBkYXRlU2NhbGVzKCk7XG4gICAgICAgIHRoaXMuX2NoZWNrRXZlbnRCaW5kaW5ncygpO1xuICAgICAgICB0aGlzLl91cGRhdGVIaWRkZW5JbmRpY2VzKCk7XG4gICAgICAgIHRoaXMuX3BsdWdpbnMuaW52YWxpZGF0ZSgpO1xuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVVcGRhdGUnLCB7XG4gICAgICAgICAgICBtb2RlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgICAgICB9KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuZXdDb250cm9sbGVycyA9IHRoaXMuYnVpbGRPclVwZGF0ZUNvbnRyb2xsZXJzKCk7XG4gICAgICAgIHRoaXMubm90aWZ5UGx1Z2lucygnYmVmb3JlRWxlbWVudHNVcGRhdGUnKTtcbiAgICAgICAgbGV0IG1pblBhZGRpbmcgPSAwO1xuICAgICAgICBmb3IobGV0IGkgPSAwLCBpbGVuID0gdGhpcy5kYXRhLmRhdGFzZXRzLmxlbmd0aDsgaSA8IGlsZW47IGkrKyl7XG4gICAgICAgICAgICBjb25zdCB7IGNvbnRyb2xsZXIgIH0gPSB0aGlzLmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgY29uc3QgcmVzZXQgPSAhYW5pbXNEaXNhYmxlZCAmJiBuZXdDb250cm9sbGVycy5pbmRleE9mKGNvbnRyb2xsZXIpID09PSAtMTtcbiAgICAgICAgICAgIGNvbnRyb2xsZXIuYnVpbGRPclVwZGF0ZUVsZW1lbnRzKHJlc2V0KTtcbiAgICAgICAgICAgIG1pblBhZGRpbmcgPSBNYXRoLm1heCgrY29udHJvbGxlci5nZXRNYXhPdmVyZmxvdygpLCBtaW5QYWRkaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBtaW5QYWRkaW5nID0gdGhpcy5fbWluUGFkZGluZyA9IG9wdGlvbnMubGF5b3V0LmF1dG9QYWRkaW5nID8gbWluUGFkZGluZyA6IDA7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUxheW91dChtaW5QYWRkaW5nKTtcbiAgICAgICAgaWYgKCFhbmltc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICBlYWNoKG5ld0NvbnRyb2xsZXJzLCAoY29udHJvbGxlcik9PntcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyLnJlc2V0KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGVEYXRhc2V0cyhtb2RlKTtcbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdhZnRlclVwZGF0ZScsIHtcbiAgICAgICAgICAgIG1vZGVcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX2xheWVycy5zb3J0KGNvbXBhcmUyTGV2ZWwoJ3onLCAnX2lkeCcpKTtcbiAgICAgICAgY29uc3QgeyBfYWN0aXZlICwgX2xhc3RFdmVudCAgfSA9IHRoaXM7XG4gICAgICAgIGlmIChfbGFzdEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9ldmVudEhhbmRsZXIoX2xhc3RFdmVudCwgdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoX2FjdGl2ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUhvdmVyU3R5bGVzKF9hY3RpdmUsIF9hY3RpdmUsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgfVxuIF91cGRhdGVTY2FsZXMoKSB7XG4gICAgICAgIGVhY2godGhpcy5zY2FsZXMsIChzY2FsZSk9PntcbiAgICAgICAgICAgIGxheW91dHMucmVtb3ZlQm94KHRoaXMsIHNjYWxlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZW5zdXJlU2NhbGVzSGF2ZUlEcygpO1xuICAgICAgICB0aGlzLmJ1aWxkT3JVcGRhdGVTY2FsZXMoKTtcbiAgICB9XG4gX2NoZWNrRXZlbnRCaW5kaW5ncygpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgZXhpc3RpbmdFdmVudHMgPSBuZXcgU2V0KE9iamVjdC5rZXlzKHRoaXMuX2xpc3RlbmVycykpO1xuICAgICAgICBjb25zdCBuZXdFdmVudHMgPSBuZXcgU2V0KG9wdGlvbnMuZXZlbnRzKTtcbiAgICAgICAgaWYgKCFzZXRzRXF1YWwoZXhpc3RpbmdFdmVudHMsIG5ld0V2ZW50cykgfHwgISF0aGlzLl9yZXNwb25zaXZlTGlzdGVuZXJzICE9PSBvcHRpb25zLnJlc3BvbnNpdmUpIHtcbiAgICAgICAgICAgIHRoaXMudW5iaW5kRXZlbnRzKCk7XG4gICAgICAgICAgICB0aGlzLmJpbmRFdmVudHMoKTtcbiAgICAgICAgfVxuICAgIH1cbiBfdXBkYXRlSGlkZGVuSW5kaWNlcygpIHtcbiAgICAgICAgY29uc3QgeyBfaGlkZGVuSW5kaWNlcyAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGNoYW5nZXMgPSB0aGlzLl9nZXRVbmlmb3JtRGF0YUNoYW5nZXMoKSB8fCBbXTtcbiAgICAgICAgZm9yIChjb25zdCB7IG1ldGhvZCAsIHN0YXJ0ICwgY291bnQgIH0gb2YgY2hhbmdlcyl7XG4gICAgICAgICAgICBjb25zdCBtb3ZlID0gbWV0aG9kID09PSAnX3JlbW92ZUVsZW1lbnRzJyA/IC1jb3VudCA6IGNvdW50O1xuICAgICAgICAgICAgbW92ZU51bWVyaWNLZXlzKF9oaWRkZW5JbmRpY2VzLCBzdGFydCwgbW92ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gX2dldFVuaWZvcm1EYXRhQ2hhbmdlcygpIHtcbiAgICAgICAgY29uc3QgX2RhdGFDaGFuZ2VzID0gdGhpcy5fZGF0YUNoYW5nZXM7XG4gICAgICAgIGlmICghX2RhdGFDaGFuZ2VzIHx8ICFfZGF0YUNoYW5nZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fZGF0YUNoYW5nZXMgPSBbXTtcbiAgICAgICAgY29uc3QgZGF0YXNldENvdW50ID0gdGhpcy5kYXRhLmRhdGFzZXRzLmxlbmd0aDtcbiAgICAgICAgY29uc3QgbWFrZVNldCA9IChpZHgpPT5uZXcgU2V0KF9kYXRhQ2hhbmdlcy5maWx0ZXIoKGMpPT5jWzBdID09PSBpZHgpLm1hcCgoYywgaSk9PmkgKyAnLCcgKyBjLnNwbGljZSgxKS5qb2luKCcsJykpKTtcbiAgICAgICAgY29uc3QgY2hhbmdlU2V0ID0gbWFrZVNldCgwKTtcbiAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IGRhdGFzZXRDb3VudDsgaSsrKXtcbiAgICAgICAgICAgIGlmICghc2V0c0VxdWFsKGNoYW5nZVNldCwgbWFrZVNldChpKSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20oY2hhbmdlU2V0KS5tYXAoKGMpPT5jLnNwbGl0KCcsJykpLm1hcCgoYSk9Pih7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiBhWzFdLFxuICAgICAgICAgICAgICAgIHN0YXJ0OiArYVsyXSxcbiAgICAgICAgICAgICAgICBjb3VudDogK2FbM11cbiAgICAgICAgICAgIH0pKTtcbiAgICB9XG4gX3VwZGF0ZUxheW91dChtaW5QYWRkaW5nKSB7XG4gICAgICAgIGlmICh0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZUxheW91dCcsIHtcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgfSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGF5b3V0cy51cGRhdGUodGhpcywgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQsIG1pblBhZGRpbmcpO1xuICAgICAgICBjb25zdCBhcmVhID0gdGhpcy5jaGFydEFyZWE7XG4gICAgICAgIGNvbnN0IG5vQXJlYSA9IGFyZWEud2lkdGggPD0gMCB8fCBhcmVhLmhlaWdodCA8PSAwO1xuICAgICAgICB0aGlzLl9sYXllcnMgPSBbXTtcbiAgICAgICAgZWFjaCh0aGlzLmJveGVzLCAoYm94KT0+e1xuICAgICAgICAgICAgaWYgKG5vQXJlYSAmJiBib3gucG9zaXRpb24gPT09ICdjaGFydEFyZWEnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJveC5jb25maWd1cmUpIHtcbiAgICAgICAgICAgICAgICBib3guY29uZmlndXJlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9sYXllcnMucHVzaCguLi5ib3guX2xheWVycygpKTtcbiAgICAgICAgfSwgdGhpcyk7XG4gICAgICAgIHRoaXMuX2xheWVycy5mb3JFYWNoKChpdGVtLCBpbmRleCk9PntcbiAgICAgICAgICAgIGl0ZW0uX2lkeCA9IGluZGV4O1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdhZnRlckxheW91dCcpO1xuICAgIH1cbiBfdXBkYXRlRGF0YXNldHMobW9kZSkge1xuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVEYXRhc2V0c1VwZGF0ZScsIHtcbiAgICAgICAgICAgIG1vZGUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgICAgIH0pID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSB0aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHRoaXMuZ2V0RGF0YXNldE1ldGEoaSkuY29udHJvbGxlci5jb25maWd1cmUoKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IobGV0IGkgPSAwLCBpbGVuID0gdGhpcy5kYXRhLmRhdGFzZXRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVEYXRhc2V0KGksIGlzRnVuY3Rpb24obW9kZSkgPyBtb2RlKHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXg6IGlcbiAgICAgICAgICAgIH0pIDogbW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdhZnRlckRhdGFzZXRzVXBkYXRlJywge1xuICAgICAgICAgICAgbW9kZVxuICAgICAgICB9KTtcbiAgICB9XG4gX3VwZGF0ZURhdGFzZXQoaW5kZXgsIG1vZGUpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuZ2V0RGF0YXNldE1ldGEoaW5kZXgpO1xuICAgICAgICBjb25zdCBhcmdzID0ge1xuICAgICAgICAgICAgbWV0YSxcbiAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgbW9kZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMubm90aWZ5UGx1Z2lucygnYmVmb3JlRGF0YXNldFVwZGF0ZScsIGFyZ3MpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIG1ldGEuY29udHJvbGxlci5fdXBkYXRlKG1vZGUpO1xuICAgICAgICBhcmdzLmNhbmNlbGFibGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdhZnRlckRhdGFzZXRVcGRhdGUnLCBhcmdzKTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVSZW5kZXInLCB7XG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgICAgIH0pID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhbmltYXRvci5oYXModGhpcykpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmF0dGFjaGVkICYmICFhbmltYXRvci5ydW5uaW5nKHRoaXMpKSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0b3Iuc3RhcnQodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRyYXcoKTtcbiAgICAgICAgICAgIG9uQW5pbWF0aW9uc0NvbXBsZXRlKHtcbiAgICAgICAgICAgICAgICBjaGFydDogdGhpc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZHJhdygpIHtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGlmICh0aGlzLl9yZXNpemVCZWZvcmVEcmF3KSB7XG4gICAgICAgICAgICBjb25zdCB7IHdpZHRoICwgaGVpZ2h0ICB9ID0gdGhpcy5fcmVzaXplQmVmb3JlRHJhdztcbiAgICAgICAgICAgIHRoaXMuX3Jlc2l6ZUJlZm9yZURyYXcgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgaWYgKHRoaXMud2lkdGggPD0gMCB8fCB0aGlzLmhlaWdodCA8PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubm90aWZ5UGx1Z2lucygnYmVmb3JlRHJhdycsIHtcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgfSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGF5ZXJzID0gdGhpcy5fbGF5ZXJzO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsYXllcnMubGVuZ3RoICYmIGxheWVyc1tpXS56IDw9IDA7ICsraSl7XG4gICAgICAgICAgICBsYXllcnNbaV0uZHJhdyh0aGlzLmNoYXJ0QXJlYSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fZHJhd0RhdGFzZXRzKCk7XG4gICAgICAgIGZvcig7IGkgPCBsYXllcnMubGVuZ3RoOyArK2kpe1xuICAgICAgICAgICAgbGF5ZXJzW2ldLmRyYXcodGhpcy5jaGFydEFyZWEpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm90aWZ5UGx1Z2lucygnYWZ0ZXJEcmF3Jyk7XG4gICAgfVxuIF9nZXRTb3J0ZWREYXRhc2V0TWV0YXMoZmlsdGVyVmlzaWJsZSkge1xuICAgICAgICBjb25zdCBtZXRhc2V0cyA9IHRoaXMuX3NvcnRlZE1ldGFzZXRzO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgbGV0IGksIGlsZW47XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IG1ldGFzZXRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBjb25zdCBtZXRhID0gbWV0YXNldHNbaV07XG4gICAgICAgICAgICBpZiAoIWZpbHRlclZpc2libGUgfHwgbWV0YS52aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gobWV0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldFNvcnRlZERhdGFzZXRNZXRhcyh0cnVlKTtcbiAgICB9XG4gX2RyYXdEYXRhc2V0cygpIHtcbiAgICAgICAgaWYgKHRoaXMubm90aWZ5UGx1Z2lucygnYmVmb3JlRGF0YXNldHNEcmF3Jywge1xuICAgICAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgICAgICB9KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtZXRhc2V0cyA9IHRoaXMuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO1xuICAgICAgICBmb3IobGV0IGkgPSBtZXRhc2V0cy5sZW5ndGggLSAxOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICB0aGlzLl9kcmF3RGF0YXNldChtZXRhc2V0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdhZnRlckRhdGFzZXRzRHJhdycpO1xuICAgIH1cbiBfZHJhd0RhdGFzZXQobWV0YSkge1xuICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcbiAgICAgICAgY29uc3QgYXJncyA9IHtcbiAgICAgICAgICAgIG1ldGEsXG4gICAgICAgICAgICBpbmRleDogbWV0YS5pbmRleCxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgY2xpcCA9IGdldERhdGFzZXRDbGlwQXJlYSh0aGlzLCBtZXRhKTtcbiAgICAgICAgaWYgKHRoaXMubm90aWZ5UGx1Z2lucygnYmVmb3JlRGF0YXNldERyYXcnLCBhcmdzKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2xpcCkge1xuICAgICAgICAgICAgY2xpcEFyZWEoY3R4LCBjbGlwKTtcbiAgICAgICAgfVxuICAgICAgICBtZXRhLmNvbnRyb2xsZXIuZHJhdygpO1xuICAgICAgICBpZiAoY2xpcCkge1xuICAgICAgICAgICAgdW5jbGlwQXJlYShjdHgpO1xuICAgICAgICB9XG4gICAgICAgIGFyZ3MuY2FuY2VsYWJsZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGF0YXNldERyYXcnLCBhcmdzKTtcbiAgICB9XG4gaXNQb2ludEluQXJlYShwb2ludCkge1xuICAgICAgICByZXR1cm4gX2lzUG9pbnRJbkFyZWEocG9pbnQsIHRoaXMuY2hhcnRBcmVhLCB0aGlzLl9taW5QYWRkaW5nKTtcbiAgICB9XG4gICAgZ2V0RWxlbWVudHNBdEV2ZW50Rm9yTW9kZShlLCBtb2RlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IG1ldGhvZCA9IEludGVyYWN0aW9uLm1vZGVzW21vZGVdO1xuICAgICAgICBpZiAodHlwZW9mIG1ldGhvZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGhvZCh0aGlzLCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkge1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5kYXRhLmRhdGFzZXRzW2RhdGFzZXRJbmRleF07XG4gICAgICAgIGNvbnN0IG1ldGFzZXRzID0gdGhpcy5fbWV0YXNldHM7XG4gICAgICAgIGxldCBtZXRhID0gbWV0YXNldHMuZmlsdGVyKCh4KT0+eCAmJiB4Ll9kYXRhc2V0ID09PSBkYXRhc2V0KS5wb3AoKTtcbiAgICAgICAgaWYgKCFtZXRhKSB7XG4gICAgICAgICAgICBtZXRhID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IG51bGwsXG4gICAgICAgICAgICAgICAgZGF0YTogW10sXG4gICAgICAgICAgICAgICAgZGF0YXNldDogbnVsbCxcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBudWxsLFxuICAgICAgICAgICAgICAgIGhpZGRlbjogbnVsbCxcbiAgICAgICAgICAgICAgICB4QXhpc0lEOiBudWxsLFxuICAgICAgICAgICAgICAgIHlBeGlzSUQ6IG51bGwsXG4gICAgICAgICAgICAgICAgb3JkZXI6IGRhdGFzZXQgJiYgZGF0YXNldC5vcmRlciB8fCAwLFxuICAgICAgICAgICAgICAgIGluZGV4OiBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgX2RhdGFzZXQ6IGRhdGFzZXQsXG4gICAgICAgICAgICAgICAgX3BhcnNlZDogW10sXG4gICAgICAgICAgICAgICAgX3NvcnRlZDogZmFsc2VcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBtZXRhc2V0cy5wdXNoKG1ldGEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXRhO1xuICAgIH1cbiAgICBnZXRDb250ZXh0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kY29udGV4dCB8fCAodGhpcy4kY29udGV4dCA9IGNyZWF0ZUNvbnRleHQobnVsbCwge1xuICAgICAgICAgICAgY2hhcnQ6IHRoaXMsXG4gICAgICAgICAgICB0eXBlOiAnY2hhcnQnXG4gICAgICAgIH0pKTtcbiAgICB9XG4gICAgZ2V0VmlzaWJsZURhdGFzZXRDb3VudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpLmxlbmd0aDtcbiAgICB9XG4gICAgaXNEYXRhc2V0VmlzaWJsZShkYXRhc2V0SW5kZXgpIHtcbiAgICAgICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZGF0YS5kYXRhc2V0c1tkYXRhc2V0SW5kZXhdO1xuICAgICAgICBpZiAoIWRhdGFzZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgICByZXR1cm4gdHlwZW9mIG1ldGEuaGlkZGVuID09PSAnYm9vbGVhbicgPyAhbWV0YS5oaWRkZW4gOiAhZGF0YXNldC5oaWRkZW47XG4gICAgfVxuICAgIHNldERhdGFzZXRWaXNpYmlsaXR5KGRhdGFzZXRJbmRleCwgdmlzaWJsZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgICBtZXRhLmhpZGRlbiA9ICF2aXNpYmxlO1xuICAgIH1cbiAgICB0b2dnbGVEYXRhVmlzaWJpbGl0eShpbmRleCkge1xuICAgICAgICB0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XSA9ICF0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XTtcbiAgICB9XG4gICAgZ2V0RGF0YVZpc2liaWxpdHkoaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XTtcbiAgICB9XG4gX3VwZGF0ZVZpc2liaWxpdHkoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgsIHZpc2libGUpIHtcbiAgICAgICAgY29uc3QgbW9kZSA9IHZpc2libGUgPyAnc2hvdycgOiAnaGlkZSc7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCk7XG4gICAgICAgIGNvbnN0IGFuaW1zID0gbWV0YS5jb250cm9sbGVyLl9yZXNvbHZlQW5pbWF0aW9ucyh1bmRlZmluZWQsIG1vZGUpO1xuICAgICAgICBpZiAoZGVmaW5lZChkYXRhSW5kZXgpKSB7XG4gICAgICAgICAgICBtZXRhLmRhdGFbZGF0YUluZGV4XS5oaWRkZW4gPSAhdmlzaWJsZTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldERhdGFzZXRWaXNpYmlsaXR5KGRhdGFzZXRJbmRleCwgdmlzaWJsZSk7XG4gICAgICAgICAgICBhbmltcy51cGRhdGUobWV0YSwge1xuICAgICAgICAgICAgICAgIHZpc2libGVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGUoKGN0eCk9PmN0eC5kYXRhc2V0SW5kZXggPT09IGRhdGFzZXRJbmRleCA/IG1vZGUgOiB1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGhpZGUoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlVmlzaWJpbGl0eShkYXRhc2V0SW5kZXgsIGRhdGFJbmRleCwgZmFsc2UpO1xuICAgIH1cbiAgICBzaG93KGRhdGFzZXRJbmRleCwgZGF0YUluZGV4KSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVZpc2liaWxpdHkoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgsIHRydWUpO1xuICAgIH1cbiBfZGVzdHJveURhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fbWV0YXNldHNbZGF0YXNldEluZGV4XTtcbiAgICAgICAgaWYgKG1ldGEgJiYgbWV0YS5jb250cm9sbGVyKSB7XG4gICAgICAgICAgICBtZXRhLmNvbnRyb2xsZXIuX2Rlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgdGhpcy5fbWV0YXNldHNbZGF0YXNldEluZGV4XTtcbiAgICB9XG4gICAgX3N0b3AoKSB7XG4gICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICB0aGlzLnN0b3AoKTtcbiAgICAgICAgYW5pbWF0b3IucmVtb3ZlKHRoaXMpO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lEYXRhc2V0TWV0YShpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZURlc3Ryb3knKTtcbiAgICAgICAgY29uc3QgeyBjYW52YXMgLCBjdHggIH0gPSB0aGlzO1xuICAgICAgICB0aGlzLl9zdG9wKCk7XG4gICAgICAgIHRoaXMuY29uZmlnLmNsZWFyQ2FjaGUoKTtcbiAgICAgICAgaWYgKGNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy51bmJpbmRFdmVudHMoKTtcbiAgICAgICAgICAgIGNsZWFyQ2FudmFzKGNhbnZhcywgY3R4KTtcbiAgICAgICAgICAgIHRoaXMucGxhdGZvcm0ucmVsZWFzZUNvbnRleHQoY3R4KTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgaW5zdGFuY2VzW3RoaXMuaWRdO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGVzdHJveScpO1xuICAgIH1cbiAgICB0b0Jhc2U2NEltYWdlKC4uLmFyZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FudmFzLnRvRGF0YVVSTCguLi5hcmdzKTtcbiAgICB9XG4gYmluZEV2ZW50cygpIHtcbiAgICAgICAgdGhpcy5iaW5kVXNlckV2ZW50cygpO1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnJlc3BvbnNpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuYmluZFJlc3BvbnNpdmVFdmVudHMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYXR0YWNoZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuIGJpbmRVc2VyRXZlbnRzKCkge1xuICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7XG4gICAgICAgIGNvbnN0IHBsYXRmb3JtID0gdGhpcy5wbGF0Zm9ybTtcbiAgICAgICAgY29uc3QgX2FkZCA9ICh0eXBlLCBsaXN0ZW5lcik9PntcbiAgICAgICAgICAgIHBsYXRmb3JtLmFkZEV2ZW50TGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgbGlzdGVuZXJzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGxpc3RlbmVyID0gKGUsIHgsIHkpPT57XG4gICAgICAgICAgICBlLm9mZnNldFggPSB4O1xuICAgICAgICAgICAgZS5vZmZzZXRZID0geTtcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlcihlKTtcbiAgICAgICAgfTtcbiAgICAgICAgZWFjaCh0aGlzLm9wdGlvbnMuZXZlbnRzLCAodHlwZSk9Pl9hZGQodHlwZSwgbGlzdGVuZXIpKTtcbiAgICB9XG4gYmluZFJlc3BvbnNpdmVFdmVudHMoKSB7XG4gICAgICAgIGlmICghdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycykge1xuICAgICAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuX3Jlc3BvbnNpdmVMaXN0ZW5lcnM7XG4gICAgICAgIGNvbnN0IHBsYXRmb3JtID0gdGhpcy5wbGF0Zm9ybTtcbiAgICAgICAgY29uc3QgX2FkZCA9ICh0eXBlLCBsaXN0ZW5lcik9PntcbiAgICAgICAgICAgIHBsYXRmb3JtLmFkZEV2ZW50TGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgbGlzdGVuZXJzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IF9yZW1vdmUgPSAodHlwZSwgbGlzdGVuZXIpPT57XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW3R5cGVdKSB7XG4gICAgICAgICAgICAgICAgcGxhdGZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGxpc3RlbmVyc1t0eXBlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgbGlzdGVuZXIgPSAod2lkdGgsIGhlaWdodCk9PntcbiAgICAgICAgICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBsZXQgZGV0YWNoZWQ7XG4gICAgICAgIGNvbnN0IGF0dGFjaGVkID0gKCk9PntcbiAgICAgICAgICAgIF9yZW1vdmUoJ2F0dGFjaCcsIGF0dGFjaGVkKTtcbiAgICAgICAgICAgIHRoaXMuYXR0YWNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yZXNpemUoKTtcbiAgICAgICAgICAgIF9hZGQoJ3Jlc2l6ZScsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIF9hZGQoJ2RldGFjaCcsIGRldGFjaGVkKTtcbiAgICAgICAgfTtcbiAgICAgICAgZGV0YWNoZWQgPSAoKT0+e1xuICAgICAgICAgICAgdGhpcy5hdHRhY2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgX3JlbW92ZSgncmVzaXplJywgbGlzdGVuZXIpO1xuICAgICAgICAgICAgdGhpcy5fc3RvcCgpO1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplKDAsIDApO1xuICAgICAgICAgICAgX2FkZCgnYXR0YWNoJywgYXR0YWNoZWQpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAocGxhdGZvcm0uaXNBdHRhY2hlZCh0aGlzLmNhbnZhcykpIHtcbiAgICAgICAgICAgIGF0dGFjaGVkKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZXRhY2hlZCgpO1xuICAgICAgICB9XG4gICAgfVxuIHVuYmluZEV2ZW50cygpIHtcbiAgICAgICAgZWFjaCh0aGlzLl9saXN0ZW5lcnMsIChsaXN0ZW5lciwgdHlwZSk9PntcbiAgICAgICAgICAgIHRoaXMucGxhdGZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9saXN0ZW5lcnMgPSB7fTtcbiAgICAgICAgZWFjaCh0aGlzLl9yZXNwb25zaXZlTGlzdGVuZXJzLCAobGlzdGVuZXIsIHR5cGUpPT57XG4gICAgICAgICAgICB0aGlzLnBsYXRmb3JtLnJlbW92ZUV2ZW50TGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycyA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdXBkYXRlSG92ZXJTdHlsZShpdGVtcywgbW9kZSwgZW5hYmxlZCkge1xuICAgICAgICBjb25zdCBwcmVmaXggPSBlbmFibGVkID8gJ3NldCcgOiAncmVtb3ZlJztcbiAgICAgICAgbGV0IG1ldGEsIGl0ZW0sIGksIGlsZW47XG4gICAgICAgIGlmIChtb2RlID09PSAnZGF0YXNldCcpIHtcbiAgICAgICAgICAgIG1ldGEgPSB0aGlzLmdldERhdGFzZXRNZXRhKGl0ZW1zWzBdLmRhdGFzZXRJbmRleCk7XG4gICAgICAgICAgICBtZXRhLmNvbnRyb2xsZXJbJ18nICsgcHJlZml4ICsgJ0RhdGFzZXRIb3ZlclN0eWxlJ10oKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgY29uc3QgY29udHJvbGxlciA9IGl0ZW0gJiYgdGhpcy5nZXREYXRhc2V0TWV0YShpdGVtLmRhdGFzZXRJbmRleCkuY29udHJvbGxlcjtcbiAgICAgICAgICAgIGlmIChjb250cm9sbGVyKSB7XG4gICAgICAgICAgICAgICAgY29udHJvbGxlcltwcmVmaXggKyAnSG92ZXJTdHlsZSddKGl0ZW0uZWxlbWVudCwgaXRlbS5kYXRhc2V0SW5kZXgsIGl0ZW0uaW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuIGdldEFjdGl2ZUVsZW1lbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWN0aXZlIHx8IFtdO1xuICAgIH1cbiBzZXRBY3RpdmVFbGVtZW50cyhhY3RpdmVFbGVtZW50cykge1xuICAgICAgICBjb25zdCBsYXN0QWN0aXZlID0gdGhpcy5fYWN0aXZlIHx8IFtdO1xuICAgICAgICBjb25zdCBhY3RpdmUgPSBhY3RpdmVFbGVtZW50cy5tYXAoKHsgZGF0YXNldEluZGV4ICwgaW5kZXggIH0pPT57XG4gICAgICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgICAgICAgaWYgKCFtZXRhKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBkYXRhc2V0IGZvdW5kIGF0IGluZGV4ICcgKyBkYXRhc2V0SW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgZWxlbWVudDogbWV0YS5kYXRhW2luZGV4XSxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNoYW5nZWQgPSAhX2VsZW1lbnRzRXF1YWwoYWN0aXZlLCBsYXN0QWN0aXZlKTtcbiAgICAgICAgaWYgKGNoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2FjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgICAgICAgIHRoaXMuX2xhc3RFdmVudCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVIb3ZlclN0eWxlcyhhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgICAgICB9XG4gICAgfVxuIG5vdGlmeVBsdWdpbnMoaG9vaywgYXJncywgZmlsdGVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wbHVnaW5zLm5vdGlmeSh0aGlzLCBob29rLCBhcmdzLCBmaWx0ZXIpO1xuICAgIH1cbiBpc1BsdWdpbkVuYWJsZWQocGx1Z2luSWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BsdWdpbnMuX2NhY2hlLmZpbHRlcigocCk9PnAucGx1Z2luLmlkID09PSBwbHVnaW5JZCkubGVuZ3RoID09PSAxO1xuICAgIH1cbiBfdXBkYXRlSG92ZXJTdHlsZXMoYWN0aXZlLCBsYXN0QWN0aXZlLCByZXBsYXkpIHtcbiAgICAgICAgY29uc3QgaG92ZXJPcHRpb25zID0gdGhpcy5vcHRpb25zLmhvdmVyO1xuICAgICAgICBjb25zdCBkaWZmID0gKGEsIGIpPT5hLmZpbHRlcigoeCk9PiFiLnNvbWUoKHkpPT54LmRhdGFzZXRJbmRleCA9PT0geS5kYXRhc2V0SW5kZXggJiYgeC5pbmRleCA9PT0geS5pbmRleCkpO1xuICAgICAgICBjb25zdCBkZWFjdGl2YXRlZCA9IGRpZmYobGFzdEFjdGl2ZSwgYWN0aXZlKTtcbiAgICAgICAgY29uc3QgYWN0aXZhdGVkID0gcmVwbGF5ID8gYWN0aXZlIDogZGlmZihhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgICAgICBpZiAoZGVhY3RpdmF0ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUhvdmVyU3R5bGUoZGVhY3RpdmF0ZWQsIGhvdmVyT3B0aW9ucy5tb2RlLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGl2YXRlZC5sZW5ndGggJiYgaG92ZXJPcHRpb25zLm1vZGUpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSG92ZXJTdHlsZShhY3RpdmF0ZWQsIGhvdmVyT3B0aW9ucy5tb2RlLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cbiBfZXZlbnRIYW5kbGVyKGUsIHJlcGxheSkge1xuICAgICAgICBjb25zdCBhcmdzID0ge1xuICAgICAgICAgICAgZXZlbnQ6IGUsXG4gICAgICAgICAgICByZXBsYXksXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgaW5DaGFydEFyZWE6IHRoaXMuaXNQb2ludEluQXJlYShlKVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBldmVudEZpbHRlciA9IChwbHVnaW4pPT4ocGx1Z2luLm9wdGlvbnMuZXZlbnRzIHx8IHRoaXMub3B0aW9ucy5ldmVudHMpLmluY2x1ZGVzKGUubmF0aXZlLnR5cGUpO1xuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVFdmVudCcsIGFyZ3MsIGV2ZW50RmlsdGVyKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGFuZ2VkID0gdGhpcy5faGFuZGxlRXZlbnQoZSwgcmVwbGF5LCBhcmdzLmluQ2hhcnRBcmVhKTtcbiAgICAgICAgYXJncy5jYW5jZWxhYmxlID0gZmFsc2U7XG4gICAgICAgIHRoaXMubm90aWZ5UGx1Z2lucygnYWZ0ZXJFdmVudCcsIGFyZ3MsIGV2ZW50RmlsdGVyKTtcbiAgICAgICAgaWYgKGNoYW5nZWQgfHwgYXJncy5jaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiBfaGFuZGxlRXZlbnQoZSwgcmVwbGF5LCBpbkNoYXJ0QXJlYSkge1xuICAgICAgICBjb25zdCB7IF9hY3RpdmU6IGxhc3RBY3RpdmUgPSBbXSAsIG9wdGlvbnMgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB1c2VGaW5hbFBvc2l0aW9uID0gcmVwbGF5O1xuICAgICAgICBjb25zdCBhY3RpdmUgPSB0aGlzLl9nZXRBY3RpdmVFbGVtZW50cyhlLCBsYXN0QWN0aXZlLCBpbkNoYXJ0QXJlYSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIGNvbnN0IGlzQ2xpY2sgPSBfaXNDbGlja0V2ZW50KGUpO1xuICAgICAgICBjb25zdCBsYXN0RXZlbnQgPSBkZXRlcm1pbmVMYXN0RXZlbnQoZSwgdGhpcy5fbGFzdEV2ZW50LCBpbkNoYXJ0QXJlYSwgaXNDbGljayk7XG4gICAgICAgIGlmIChpbkNoYXJ0QXJlYSkge1xuICAgICAgICAgICAgdGhpcy5fbGFzdEV2ZW50ID0gbnVsbDtcbiAgICAgICAgICAgIGNhbGxiYWNrKG9wdGlvbnMub25Ib3ZlciwgW1xuICAgICAgICAgICAgICAgIGUsXG4gICAgICAgICAgICAgICAgYWN0aXZlLFxuICAgICAgICAgICAgICAgIHRoaXNcbiAgICAgICAgICAgIF0sIHRoaXMpO1xuICAgICAgICAgICAgaWYgKGlzQ2xpY2spIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhvcHRpb25zLm9uQ2xpY2ssIFtcbiAgICAgICAgICAgICAgICAgICAgZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlLFxuICAgICAgICAgICAgICAgICAgICB0aGlzXG4gICAgICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hhbmdlZCA9ICFfZWxlbWVudHNFcXVhbChhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgICAgICBpZiAoY2hhbmdlZCB8fCByZXBsYXkpIHtcbiAgICAgICAgICAgIHRoaXMuX2FjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUhvdmVyU3R5bGVzKGFjdGl2ZSwgbGFzdEFjdGl2ZSwgcmVwbGF5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9sYXN0RXZlbnQgPSBsYXN0RXZlbnQ7XG4gICAgICAgIHJldHVybiBjaGFuZ2VkO1xuICAgIH1cbiBfZ2V0QWN0aXZlRWxlbWVudHMoZSwgbGFzdEFjdGl2ZSwgaW5DaGFydEFyZWEsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgaWYgKGUudHlwZSA9PT0gJ21vdXNlb3V0Jykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaW5DaGFydEFyZWEpIHtcbiAgICAgICAgICAgIHJldHVybiBsYXN0QWN0aXZlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhvdmVyT3B0aW9ucyA9IHRoaXMub3B0aW9ucy5ob3ZlcjtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RWxlbWVudHNBdEV2ZW50Rm9yTW9kZShlLCBob3Zlck9wdGlvbnMubW9kZSwgaG92ZXJPcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9XG59XG5mdW5jdGlvbiBpbnZhbGlkYXRlUGx1Z2lucygpIHtcbiAgICByZXR1cm4gZWFjaChDaGFydC5pbnN0YW5jZXMsIChjaGFydCk9PmNoYXJ0Ll9wbHVnaW5zLmludmFsaWRhdGUoKSk7XG59XG5cbmZ1bmN0aW9uIGNsaXBTZWxmKGN0eCwgZWxlbWVudCwgZW5kQW5nbGUpIHtcbiAgICBjb25zdCB7IHN0YXJ0QW5nbGUgLCB4ICwgeSAsIG91dGVyUmFkaXVzICwgaW5uZXJSYWRpdXMgLCBvcHRpb25zICB9ID0gZWxlbWVudDtcbiAgICBjb25zdCB7IGJvcmRlcldpZHRoICwgYm9yZGVySm9pblN0eWxlICB9ID0gb3B0aW9ucztcbiAgICBjb25zdCBvdXRlckFuZ2xlQ2xpcCA9IE1hdGgubWluKGJvcmRlcldpZHRoIC8gb3V0ZXJSYWRpdXMsIF9ub3JtYWxpemVBbmdsZShzdGFydEFuZ2xlIC0gZW5kQW5nbGUpKTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4LmFyYyh4LCB5LCBvdXRlclJhZGl1cyAtIGJvcmRlcldpZHRoIC8gMiwgc3RhcnRBbmdsZSArIG91dGVyQW5nbGVDbGlwIC8gMiwgZW5kQW5nbGUgLSBvdXRlckFuZ2xlQ2xpcCAvIDIpO1xuICAgIGlmIChpbm5lclJhZGl1cyA+IDApIHtcbiAgICAgICAgY29uc3QgaW5uZXJBbmdsZUNsaXAgPSBNYXRoLm1pbihib3JkZXJXaWR0aCAvIGlubmVyUmFkaXVzLCBfbm9ybWFsaXplQW5nbGUoc3RhcnRBbmdsZSAtIGVuZEFuZ2xlKSk7XG4gICAgICAgIGN0eC5hcmMoeCwgeSwgaW5uZXJSYWRpdXMgKyBib3JkZXJXaWR0aCAvIDIsIGVuZEFuZ2xlIC0gaW5uZXJBbmdsZUNsaXAgLyAyLCBzdGFydEFuZ2xlICsgaW5uZXJBbmdsZUNsaXAgLyAyLCB0cnVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBjbGlwV2lkdGggPSBNYXRoLm1pbihib3JkZXJXaWR0aCAvIDIsIG91dGVyUmFkaXVzICogX25vcm1hbGl6ZUFuZ2xlKHN0YXJ0QW5nbGUgLSBlbmRBbmdsZSkpO1xuICAgICAgICBpZiAoYm9yZGVySm9pblN0eWxlID09PSAncm91bmQnKSB7XG4gICAgICAgICAgICBjdHguYXJjKHgsIHksIGNsaXBXaWR0aCwgZW5kQW5nbGUgLSBQSSAvIDIsIHN0YXJ0QW5nbGUgKyBQSSAvIDIsIHRydWUpO1xuICAgICAgICB9IGVsc2UgaWYgKGJvcmRlckpvaW5TdHlsZSA9PT0gJ2JldmVsJykge1xuICAgICAgICAgICAgY29uc3QgciA9IDIgKiBjbGlwV2lkdGggKiBjbGlwV2lkdGg7XG4gICAgICAgICAgICBjb25zdCBlbmRYID0gLXIgKiBNYXRoLmNvcyhlbmRBbmdsZSArIFBJIC8gMikgKyB4O1xuICAgICAgICAgICAgY29uc3QgZW5kWSA9IC1yICogTWF0aC5zaW4oZW5kQW5nbGUgKyBQSSAvIDIpICsgeTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0WCA9IHIgKiBNYXRoLmNvcyhzdGFydEFuZ2xlICsgUEkgLyAyKSArIHg7XG4gICAgICAgICAgICBjb25zdCBzdGFydFkgPSByICogTWF0aC5zaW4oc3RhcnRBbmdsZSArIFBJIC8gMikgKyB5O1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhlbmRYLCBlbmRZKTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oc3RhcnRYLCBzdGFydFkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBjdHgubW92ZVRvKDAsIDApO1xuICAgIGN0eC5yZWN0KDAsIDAsIGN0eC5jYW52YXMud2lkdGgsIGN0eC5jYW52YXMuaGVpZ2h0KTtcbiAgICBjdHguY2xpcCgnZXZlbm9kZCcpO1xufVxuZnVuY3Rpb24gY2xpcEFyYyhjdHgsIGVsZW1lbnQsIGVuZEFuZ2xlKSB7XG4gICAgY29uc3QgeyBzdGFydEFuZ2xlICwgcGl4ZWxNYXJnaW4gLCB4ICwgeSAsIG91dGVyUmFkaXVzICwgaW5uZXJSYWRpdXMgIH0gPSBlbGVtZW50O1xuICAgIGxldCBhbmdsZU1hcmdpbiA9IHBpeGVsTWFyZ2luIC8gb3V0ZXJSYWRpdXM7XG4gICAgLy8gRHJhdyBhbiBpbm5lciBib3JkZXIgYnkgY2xpcHBpbmcgdGhlIGFyYyBhbmQgZHJhd2luZyBhIGRvdWJsZS13aWR0aCBib3JkZXJcbiAgICAvLyBFbmxhcmdlIHRoZSBjbGlwcGluZyBhcmMgYnkgMC4zMyBwaXhlbHMgdG8gZWxpbWluYXRlIGdsaXRjaGVzIGJldHdlZW4gYm9yZGVyc1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBjdHguYXJjKHgsIHksIG91dGVyUmFkaXVzLCBzdGFydEFuZ2xlIC0gYW5nbGVNYXJnaW4sIGVuZEFuZ2xlICsgYW5nbGVNYXJnaW4pO1xuICAgIGlmIChpbm5lclJhZGl1cyA+IHBpeGVsTWFyZ2luKSB7XG4gICAgICAgIGFuZ2xlTWFyZ2luID0gcGl4ZWxNYXJnaW4gLyBpbm5lclJhZGl1cztcbiAgICAgICAgY3R4LmFyYyh4LCB5LCBpbm5lclJhZGl1cywgZW5kQW5nbGUgKyBhbmdsZU1hcmdpbiwgc3RhcnRBbmdsZSAtIGFuZ2xlTWFyZ2luLCB0cnVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjdHguYXJjKHgsIHksIHBpeGVsTWFyZ2luLCBlbmRBbmdsZSArIEhBTEZfUEksIHN0YXJ0QW5nbGUgLSBIQUxGX1BJKTtcbiAgICB9XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgIGN0eC5jbGlwKCk7XG59XG5mdW5jdGlvbiB0b1JhZGl1c0Nvcm5lcnModmFsdWUpIHtcbiAgICByZXR1cm4gX3JlYWRWYWx1ZVRvUHJvcHModmFsdWUsIFtcbiAgICAgICAgJ291dGVyU3RhcnQnLFxuICAgICAgICAnb3V0ZXJFbmQnLFxuICAgICAgICAnaW5uZXJTdGFydCcsXG4gICAgICAgICdpbm5lckVuZCdcbiAgICBdKTtcbn1cbi8qKlxuICogUGFyc2UgYm9yZGVyIHJhZGl1cyBmcm9tIHRoZSBwcm92aWRlZCBvcHRpb25zXG4gKi8gZnVuY3Rpb24gcGFyc2VCb3JkZXJSYWRpdXMkMShhcmMsIGlubmVyUmFkaXVzLCBvdXRlclJhZGl1cywgYW5nbGVEZWx0YSkge1xuICAgIGNvbnN0IG8gPSB0b1JhZGl1c0Nvcm5lcnMoYXJjLm9wdGlvbnMuYm9yZGVyUmFkaXVzKTtcbiAgICBjb25zdCBoYWxmVGhpY2tuZXNzID0gKG91dGVyUmFkaXVzIC0gaW5uZXJSYWRpdXMpIC8gMjtcbiAgICBjb25zdCBpbm5lckxpbWl0ID0gTWF0aC5taW4oaGFsZlRoaWNrbmVzcywgYW5nbGVEZWx0YSAqIGlubmVyUmFkaXVzIC8gMik7XG4gICAgLy8gT3V0ZXIgbGltaXRzIGFyZSBjb21wbGljYXRlZC4gV2Ugd2FudCB0byBjb21wdXRlIHRoZSBhdmFpbGFibGUgYW5ndWxhciBkaXN0YW5jZSBhdFxuICAgIC8vIGEgcmFkaXVzIG9mIG91dGVyUmFkaXVzIC0gYm9yZGVyUmFkaXVzIGJlY2F1c2UgZm9yIHNtYWxsIGFuZ3VsYXIgZGlzdGFuY2VzLCB0aGlzIHRlcm0gbGltaXRzLlxuICAgIC8vIFdlIGNvbXB1dGUgYXQgciA9IG91dGVyUmFkaXVzIC0gYm9yZGVyUmFkaXVzIGJlY2F1c2UgdGhpcyBjaXJjbGUgZGVmaW5lcyB0aGUgY2VudGVyIG9mIHRoZSBib3JkZXIgY29ybmVycy5cbiAgICAvL1xuICAgIC8vIElmIHRoZSBib3JkZXJSYWRpdXMgaXMgbGFyZ2UsIHRoYXQgdmFsdWUgY2FuIGJlY29tZSBuZWdhdGl2ZS5cbiAgICAvLyBUaGlzIGNhdXNlcyB0aGUgb3V0ZXIgYm9yZGVycyB0byBsb3NlIHRoZWlyIHJhZGl1cyBlbnRpcmVseSwgd2hpY2ggaXMgcmF0aGVyIHVuZXhwZWN0ZWQuIFRvIHNvbHZlIHRoYXQsIGlmIGJvcmRlclJhZGl1cyA+IG91dGVyUmFkaXVzXG4gICAgLy8gd2Uga25vdyB0aGF0IHRoZSB0aGlja25lc3MgdGVybSB3aWxsIGRvbWluYXRlIGFuZCBjb21wdXRlIHRoZSBsaW1pdHMgYXQgdGhhdCBwb2ludFxuICAgIGNvbnN0IGNvbXB1dGVPdXRlckxpbWl0ID0gKHZhbCk9PntcbiAgICAgICAgY29uc3Qgb3V0ZXJBcmNMaW1pdCA9IChvdXRlclJhZGl1cyAtIE1hdGgubWluKGhhbGZUaGlja25lc3MsIHZhbCkpICogYW5nbGVEZWx0YSAvIDI7XG4gICAgICAgIHJldHVybiBfbGltaXRWYWx1ZSh2YWwsIDAsIE1hdGgubWluKGhhbGZUaGlja25lc3MsIG91dGVyQXJjTGltaXQpKTtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICAgIG91dGVyU3RhcnQ6IGNvbXB1dGVPdXRlckxpbWl0KG8ub3V0ZXJTdGFydCksXG4gICAgICAgIG91dGVyRW5kOiBjb21wdXRlT3V0ZXJMaW1pdChvLm91dGVyRW5kKSxcbiAgICAgICAgaW5uZXJTdGFydDogX2xpbWl0VmFsdWUoby5pbm5lclN0YXJ0LCAwLCBpbm5lckxpbWl0KSxcbiAgICAgICAgaW5uZXJFbmQ6IF9saW1pdFZhbHVlKG8uaW5uZXJFbmQsIDAsIGlubmVyTGltaXQpXG4gICAgfTtcbn1cbi8qKlxuICogQ29udmVydCAociwg8J2cgykgdG8gKHgsIHkpXG4gKi8gZnVuY3Rpb24gclRoZXRhVG9YWShyLCB0aGV0YSwgeCwgeSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHg6IHggKyByICogTWF0aC5jb3ModGhldGEpLFxuICAgICAgICB5OiB5ICsgciAqIE1hdGguc2luKHRoZXRhKVxuICAgIH07XG59XG4vKipcbiAqIFBhdGggdGhlIGFyYywgcmVzcGVjdGluZyBib3JkZXIgcmFkaXVzIGJ5IHNlcGFyYXRpbmcgaW50byBsZWZ0IGFuZCByaWdodCBoYWx2ZXMuXG4gKlxuICogICBTdGFydCAgICAgIEVuZFxuICpcbiAqICAgIDEtLS0+YS0tLT4yICAgIE91dGVyXG4gKiAgIC8gICAgICAgICAgIFxcXG4gKiAgIDggICAgICAgICAgIDNcbiAqICAgfCAgICAgICAgICAgfFxuICogICB8ICAgICAgICAgICB8XG4gKiAgIDcgICAgICAgICAgIDRcbiAqICAgXFwgICAgICAgICAgIC9cbiAqICAgIDY8LS0tYjwtLS01ICAgIElubmVyXG4gKi8gZnVuY3Rpb24gcGF0aEFyYyhjdHgsIGVsZW1lbnQsIG9mZnNldCwgc3BhY2luZywgZW5kLCBjaXJjdWxhcikge1xuICAgIGNvbnN0IHsgeCAsIHkgLCBzdGFydEFuZ2xlOiBzdGFydCAsIHBpeGVsTWFyZ2luICwgaW5uZXJSYWRpdXM6IGlubmVyUiAgfSA9IGVsZW1lbnQ7XG4gICAgY29uc3Qgb3V0ZXJSYWRpdXMgPSBNYXRoLm1heChlbGVtZW50Lm91dGVyUmFkaXVzICsgc3BhY2luZyArIG9mZnNldCAtIHBpeGVsTWFyZ2luLCAwKTtcbiAgICBjb25zdCBpbm5lclJhZGl1cyA9IGlubmVyUiA+IDAgPyBpbm5lclIgKyBzcGFjaW5nICsgb2Zmc2V0ICsgcGl4ZWxNYXJnaW4gOiAwO1xuICAgIGxldCBzcGFjaW5nT2Zmc2V0ID0gMDtcbiAgICBjb25zdCBhbHBoYSA9IGVuZCAtIHN0YXJ0O1xuICAgIGlmIChzcGFjaW5nKSB7XG4gICAgICAgIC8vIFdoZW4gc3BhY2luZyBpcyBwcmVzZW50LCBpdCBpcyB0aGUgc2FtZSBmb3IgYWxsIGl0ZW1zXG4gICAgICAgIC8vIFNvIHdlIGFkanVzdCB0aGUgc3RhcnQgYW5kIGVuZCBhbmdsZSBvZiB0aGUgYXJjIHN1Y2ggdGhhdFxuICAgICAgICAvLyB0aGUgZGlzdGFuY2UgaXMgdGhlIHNhbWUgYXMgaXQgd291bGQgYmUgd2l0aG91dCB0aGUgc3BhY2luZ1xuICAgICAgICBjb25zdCBub1NwYWNpbmdJbm5lclJhZGl1cyA9IGlubmVyUiA+IDAgPyBpbm5lclIgLSBzcGFjaW5nIDogMDtcbiAgICAgICAgY29uc3Qgbm9TcGFjaW5nT3V0ZXJSYWRpdXMgPSBvdXRlclJhZGl1cyA+IDAgPyBvdXRlclJhZGl1cyAtIHNwYWNpbmcgOiAwO1xuICAgICAgICBjb25zdCBhdk5vZ1NwYWNpbmdSYWRpdXMgPSAobm9TcGFjaW5nSW5uZXJSYWRpdXMgKyBub1NwYWNpbmdPdXRlclJhZGl1cykgLyAyO1xuICAgICAgICBjb25zdCBhZGp1c3RlZEFuZ2xlID0gYXZOb2dTcGFjaW5nUmFkaXVzICE9PSAwID8gYWxwaGEgKiBhdk5vZ1NwYWNpbmdSYWRpdXMgLyAoYXZOb2dTcGFjaW5nUmFkaXVzICsgc3BhY2luZykgOiBhbHBoYTtcbiAgICAgICAgc3BhY2luZ09mZnNldCA9IChhbHBoYSAtIGFkanVzdGVkQW5nbGUpIC8gMjtcbiAgICB9XG4gICAgY29uc3QgYmV0YSA9IE1hdGgubWF4KDAuMDAxLCBhbHBoYSAqIG91dGVyUmFkaXVzIC0gb2Zmc2V0IC8gUEkpIC8gb3V0ZXJSYWRpdXM7XG4gICAgY29uc3QgYW5nbGVPZmZzZXQgPSAoYWxwaGEgLSBiZXRhKSAvIDI7XG4gICAgY29uc3Qgc3RhcnRBbmdsZSA9IHN0YXJ0ICsgYW5nbGVPZmZzZXQgKyBzcGFjaW5nT2Zmc2V0O1xuICAgIGNvbnN0IGVuZEFuZ2xlID0gZW5kIC0gYW5nbGVPZmZzZXQgLSBzcGFjaW5nT2Zmc2V0O1xuICAgIGNvbnN0IHsgb3V0ZXJTdGFydCAsIG91dGVyRW5kICwgaW5uZXJTdGFydCAsIGlubmVyRW5kICB9ID0gcGFyc2VCb3JkZXJSYWRpdXMkMShlbGVtZW50LCBpbm5lclJhZGl1cywgb3V0ZXJSYWRpdXMsIGVuZEFuZ2xlIC0gc3RhcnRBbmdsZSk7XG4gICAgY29uc3Qgb3V0ZXJTdGFydEFkanVzdGVkUmFkaXVzID0gb3V0ZXJSYWRpdXMgLSBvdXRlclN0YXJ0O1xuICAgIGNvbnN0IG91dGVyRW5kQWRqdXN0ZWRSYWRpdXMgPSBvdXRlclJhZGl1cyAtIG91dGVyRW5kO1xuICAgIGNvbnN0IG91dGVyU3RhcnRBZGp1c3RlZEFuZ2xlID0gc3RhcnRBbmdsZSArIG91dGVyU3RhcnQgLyBvdXRlclN0YXJ0QWRqdXN0ZWRSYWRpdXM7XG4gICAgY29uc3Qgb3V0ZXJFbmRBZGp1c3RlZEFuZ2xlID0gZW5kQW5nbGUgLSBvdXRlckVuZCAvIG91dGVyRW5kQWRqdXN0ZWRSYWRpdXM7XG4gICAgY29uc3QgaW5uZXJTdGFydEFkanVzdGVkUmFkaXVzID0gaW5uZXJSYWRpdXMgKyBpbm5lclN0YXJ0O1xuICAgIGNvbnN0IGlubmVyRW5kQWRqdXN0ZWRSYWRpdXMgPSBpbm5lclJhZGl1cyArIGlubmVyRW5kO1xuICAgIGNvbnN0IGlubmVyU3RhcnRBZGp1c3RlZEFuZ2xlID0gc3RhcnRBbmdsZSArIGlubmVyU3RhcnQgLyBpbm5lclN0YXJ0QWRqdXN0ZWRSYWRpdXM7XG4gICAgY29uc3QgaW5uZXJFbmRBZGp1c3RlZEFuZ2xlID0gZW5kQW5nbGUgLSBpbm5lckVuZCAvIGlubmVyRW5kQWRqdXN0ZWRSYWRpdXM7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIGlmIChjaXJjdWxhcikge1xuICAgICAgICAvLyBUaGUgZmlyc3QgYXJjIHNlZ21lbnRzIGZyb20gcG9pbnQgMSB0byBwb2ludCBhIHRvIHBvaW50IDJcbiAgICAgICAgY29uc3Qgb3V0ZXJNaWRBZGp1c3RlZEFuZ2xlID0gKG91dGVyU3RhcnRBZGp1c3RlZEFuZ2xlICsgb3V0ZXJFbmRBZGp1c3RlZEFuZ2xlKSAvIDI7XG4gICAgICAgIGN0eC5hcmMoeCwgeSwgb3V0ZXJSYWRpdXMsIG91dGVyU3RhcnRBZGp1c3RlZEFuZ2xlLCBvdXRlck1pZEFkanVzdGVkQW5nbGUpO1xuICAgICAgICBjdHguYXJjKHgsIHksIG91dGVyUmFkaXVzLCBvdXRlck1pZEFkanVzdGVkQW5nbGUsIG91dGVyRW5kQWRqdXN0ZWRBbmdsZSk7XG4gICAgICAgIC8vIFRoZSBjb3JuZXIgc2VnbWVudCBmcm9tIHBvaW50IDIgdG8gcG9pbnQgM1xuICAgICAgICBpZiAob3V0ZXJFbmQgPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBwQ2VudGVyID0gclRoZXRhVG9YWShvdXRlckVuZEFkanVzdGVkUmFkaXVzLCBvdXRlckVuZEFkanVzdGVkQW5nbGUsIHgsIHkpO1xuICAgICAgICAgICAgY3R4LmFyYyhwQ2VudGVyLngsIHBDZW50ZXIueSwgb3V0ZXJFbmQsIG91dGVyRW5kQWRqdXN0ZWRBbmdsZSwgZW5kQW5nbGUgKyBIQUxGX1BJKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgbGluZSBmcm9tIHBvaW50IDMgdG8gcG9pbnQgNFxuICAgICAgICBjb25zdCBwNCA9IHJUaGV0YVRvWFkoaW5uZXJFbmRBZGp1c3RlZFJhZGl1cywgZW5kQW5nbGUsIHgsIHkpO1xuICAgICAgICBjdHgubGluZVRvKHA0LngsIHA0LnkpO1xuICAgICAgICAvLyBUaGUgY29ybmVyIHNlZ21lbnQgZnJvbSBwb2ludCA0IHRvIHBvaW50IDVcbiAgICAgICAgaWYgKGlubmVyRW5kID4gMCkge1xuICAgICAgICAgICAgY29uc3QgcENlbnRlciA9IHJUaGV0YVRvWFkoaW5uZXJFbmRBZGp1c3RlZFJhZGl1cywgaW5uZXJFbmRBZGp1c3RlZEFuZ2xlLCB4LCB5KTtcbiAgICAgICAgICAgIGN0eC5hcmMocENlbnRlci54LCBwQ2VudGVyLnksIGlubmVyRW5kLCBlbmRBbmdsZSArIEhBTEZfUEksIGlubmVyRW5kQWRqdXN0ZWRBbmdsZSArIE1hdGguUEkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSBpbm5lciBhcmMgZnJvbSBwb2ludCA1IHRvIHBvaW50IGIgdG8gcG9pbnQgNlxuICAgICAgICBjb25zdCBpbm5lck1pZEFkanVzdGVkQW5nbGUgPSAoZW5kQW5nbGUgLSBpbm5lckVuZCAvIGlubmVyUmFkaXVzICsgKHN0YXJ0QW5nbGUgKyBpbm5lclN0YXJ0IC8gaW5uZXJSYWRpdXMpKSAvIDI7XG4gICAgICAgIGN0eC5hcmMoeCwgeSwgaW5uZXJSYWRpdXMsIGVuZEFuZ2xlIC0gaW5uZXJFbmQgLyBpbm5lclJhZGl1cywgaW5uZXJNaWRBZGp1c3RlZEFuZ2xlLCB0cnVlKTtcbiAgICAgICAgY3R4LmFyYyh4LCB5LCBpbm5lclJhZGl1cywgaW5uZXJNaWRBZGp1c3RlZEFuZ2xlLCBzdGFydEFuZ2xlICsgaW5uZXJTdGFydCAvIGlubmVyUmFkaXVzLCB0cnVlKTtcbiAgICAgICAgLy8gVGhlIGNvcm5lciBzZWdtZW50IGZyb20gcG9pbnQgNiB0byBwb2ludCA3XG4gICAgICAgIGlmIChpbm5lclN0YXJ0ID4gMCkge1xuICAgICAgICAgICAgY29uc3QgcENlbnRlciA9IHJUaGV0YVRvWFkoaW5uZXJTdGFydEFkanVzdGVkUmFkaXVzLCBpbm5lclN0YXJ0QWRqdXN0ZWRBbmdsZSwgeCwgeSk7XG4gICAgICAgICAgICBjdHguYXJjKHBDZW50ZXIueCwgcENlbnRlci55LCBpbm5lclN0YXJ0LCBpbm5lclN0YXJ0QWRqdXN0ZWRBbmdsZSArIE1hdGguUEksIHN0YXJ0QW5nbGUgLSBIQUxGX1BJKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgbGluZSBmcm9tIHBvaW50IDcgdG8gcG9pbnQgOFxuICAgICAgICBjb25zdCBwOCA9IHJUaGV0YVRvWFkob3V0ZXJTdGFydEFkanVzdGVkUmFkaXVzLCBzdGFydEFuZ2xlLCB4LCB5KTtcbiAgICAgICAgY3R4LmxpbmVUbyhwOC54LCBwOC55KTtcbiAgICAgICAgLy8gVGhlIGNvcm5lciBzZWdtZW50IGZyb20gcG9pbnQgOCB0byBwb2ludCAxXG4gICAgICAgIGlmIChvdXRlclN0YXJ0ID4gMCkge1xuICAgICAgICAgICAgY29uc3QgcENlbnRlciA9IHJUaGV0YVRvWFkob3V0ZXJTdGFydEFkanVzdGVkUmFkaXVzLCBvdXRlclN0YXJ0QWRqdXN0ZWRBbmdsZSwgeCwgeSk7XG4gICAgICAgICAgICBjdHguYXJjKHBDZW50ZXIueCwgcENlbnRlci55LCBvdXRlclN0YXJ0LCBzdGFydEFuZ2xlIC0gSEFMRl9QSSwgb3V0ZXJTdGFydEFkanVzdGVkQW5nbGUpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY3R4Lm1vdmVUbyh4LCB5KTtcbiAgICAgICAgY29uc3Qgb3V0ZXJTdGFydFggPSBNYXRoLmNvcyhvdXRlclN0YXJ0QWRqdXN0ZWRBbmdsZSkgKiBvdXRlclJhZGl1cyArIHg7XG4gICAgICAgIGNvbnN0IG91dGVyU3RhcnRZID0gTWF0aC5zaW4ob3V0ZXJTdGFydEFkanVzdGVkQW5nbGUpICogb3V0ZXJSYWRpdXMgKyB5O1xuICAgICAgICBjdHgubGluZVRvKG91dGVyU3RhcnRYLCBvdXRlclN0YXJ0WSk7XG4gICAgICAgIGNvbnN0IG91dGVyRW5kWCA9IE1hdGguY29zKG91dGVyRW5kQWRqdXN0ZWRBbmdsZSkgKiBvdXRlclJhZGl1cyArIHg7XG4gICAgICAgIGNvbnN0IG91dGVyRW5kWSA9IE1hdGguc2luKG91dGVyRW5kQWRqdXN0ZWRBbmdsZSkgKiBvdXRlclJhZGl1cyArIHk7XG4gICAgICAgIGN0eC5saW5lVG8ob3V0ZXJFbmRYLCBvdXRlckVuZFkpO1xuICAgIH1cbiAgICBjdHguY2xvc2VQYXRoKCk7XG59XG5mdW5jdGlvbiBkcmF3QXJjKGN0eCwgZWxlbWVudCwgb2Zmc2V0LCBzcGFjaW5nLCBjaXJjdWxhcikge1xuICAgIGNvbnN0IHsgZnVsbENpcmNsZXMgLCBzdGFydEFuZ2xlICwgY2lyY3VtZmVyZW5jZSAgfSA9IGVsZW1lbnQ7XG4gICAgbGV0IGVuZEFuZ2xlID0gZWxlbWVudC5lbmRBbmdsZTtcbiAgICBpZiAoZnVsbENpcmNsZXMpIHtcbiAgICAgICAgcGF0aEFyYyhjdHgsIGVsZW1lbnQsIG9mZnNldCwgc3BhY2luZywgZW5kQW5nbGUsIGNpcmN1bGFyKTtcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IGZ1bGxDaXJjbGVzOyArK2kpe1xuICAgICAgICAgICAgY3R4LmZpbGwoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzTmFOKGNpcmN1bWZlcmVuY2UpKSB7XG4gICAgICAgICAgICBlbmRBbmdsZSA9IHN0YXJ0QW5nbGUgKyAoY2lyY3VtZmVyZW5jZSAlIFRBVSB8fCBUQVUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZEFuZ2xlLCBjaXJjdWxhcik7XG4gICAgY3R4LmZpbGwoKTtcbiAgICByZXR1cm4gZW5kQW5nbGU7XG59XG5mdW5jdGlvbiBkcmF3Qm9yZGVyKGN0eCwgZWxlbWVudCwgb2Zmc2V0LCBzcGFjaW5nLCBjaXJjdWxhcikge1xuICAgIGNvbnN0IHsgZnVsbENpcmNsZXMgLCBzdGFydEFuZ2xlICwgY2lyY3VtZmVyZW5jZSAsIG9wdGlvbnMgIH0gPSBlbGVtZW50O1xuICAgIGNvbnN0IHsgYm9yZGVyV2lkdGggLCBib3JkZXJKb2luU3R5bGUgLCBib3JkZXJEYXNoICwgYm9yZGVyRGFzaE9mZnNldCAsIGJvcmRlclJhZGl1cyAgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgaW5uZXIgPSBvcHRpb25zLmJvcmRlckFsaWduID09PSAnaW5uZXInO1xuICAgIGlmICghYm9yZGVyV2lkdGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjdHguc2V0TGluZURhc2goYm9yZGVyRGFzaCB8fCBbXSk7XG4gICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gYm9yZGVyRGFzaE9mZnNldDtcbiAgICBpZiAoaW5uZXIpIHtcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IGJvcmRlcldpZHRoICogMjtcbiAgICAgICAgY3R4LmxpbmVKb2luID0gYm9yZGVySm9pblN0eWxlIHx8ICdyb3VuZCc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IGJvcmRlcldpZHRoO1xuICAgICAgICBjdHgubGluZUpvaW4gPSBib3JkZXJKb2luU3R5bGUgfHwgJ2JldmVsJztcbiAgICB9XG4gICAgbGV0IGVuZEFuZ2xlID0gZWxlbWVudC5lbmRBbmdsZTtcbiAgICBpZiAoZnVsbENpcmNsZXMpIHtcbiAgICAgICAgcGF0aEFyYyhjdHgsIGVsZW1lbnQsIG9mZnNldCwgc3BhY2luZywgZW5kQW5nbGUsIGNpcmN1bGFyKTtcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IGZ1bGxDaXJjbGVzOyArK2kpe1xuICAgICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNOYU4oY2lyY3VtZmVyZW5jZSkpIHtcbiAgICAgICAgICAgIGVuZEFuZ2xlID0gc3RhcnRBbmdsZSArIChjaXJjdW1mZXJlbmNlICUgVEFVIHx8IFRBVSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlubmVyKSB7XG4gICAgICAgIGNsaXBBcmMoY3R4LCBlbGVtZW50LCBlbmRBbmdsZSk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnNlbGZKb2luICYmIGVuZEFuZ2xlIC0gc3RhcnRBbmdsZSA+PSBQSSAmJiBib3JkZXJSYWRpdXMgPT09IDAgJiYgYm9yZGVySm9pblN0eWxlICE9PSAnbWl0ZXInKSB7XG4gICAgICAgIGNsaXBTZWxmKGN0eCwgZWxlbWVudCwgZW5kQW5nbGUpO1xuICAgIH1cbiAgICBpZiAoIWZ1bGxDaXJjbGVzKSB7XG4gICAgICAgIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZEFuZ2xlLCBjaXJjdWxhcik7XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG59XG5jbGFzcyBBcmNFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7XG4gICAgc3RhdGljIGlkID0gJ2FyYyc7XG4gICAgc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBib3JkZXJBbGlnbjogJ2NlbnRlcicsXG4gICAgICAgIGJvcmRlckNvbG9yOiAnI2ZmZicsXG4gICAgICAgIGJvcmRlckRhc2g6IFtdLFxuICAgICAgICBib3JkZXJEYXNoT2Zmc2V0OiAwLFxuICAgICAgICBib3JkZXJKb2luU3R5bGU6IHVuZGVmaW5lZCxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAwLFxuICAgICAgICBib3JkZXJXaWR0aDogMixcbiAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgICBzcGFjaW5nOiAwLFxuICAgICAgICBhbmdsZTogdW5kZWZpbmVkLFxuICAgICAgICBjaXJjdWxhcjogdHJ1ZSxcbiAgICAgICAgc2VsZkpvaW46IGZhbHNlXG4gICAgfTtcbiAgICBzdGF0aWMgZGVmYXVsdFJvdXRlcyA9IHtcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAnYmFja2dyb3VuZENvbG9yJ1xuICAgIH07XG4gICAgc3RhdGljIGRlc2NyaXB0b3JzID0ge1xuICAgICAgICBfc2NyaXB0YWJsZTogdHJ1ZSxcbiAgICAgICAgX2luZGV4YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnYm9yZGVyRGFzaCdcbiAgICB9O1xuICAgIGNpcmN1bWZlcmVuY2U7XG4gICAgZW5kQW5nbGU7XG4gICAgZnVsbENpcmNsZXM7XG4gICAgaW5uZXJSYWRpdXM7XG4gICAgb3V0ZXJSYWRpdXM7XG4gICAgcGl4ZWxNYXJnaW47XG4gICAgc3RhcnRBbmdsZTtcbiAgICBjb25zdHJ1Y3RvcihjZmcpe1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuY2lyY3VtZmVyZW5jZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zdGFydEFuZ2xlID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmVuZEFuZ2xlID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmlubmVyUmFkaXVzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm91dGVyUmFkaXVzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnBpeGVsTWFyZ2luID0gMDtcbiAgICAgICAgdGhpcy5mdWxsQ2lyY2xlcyA9IDA7XG4gICAgICAgIGlmIChjZmcpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgY2ZnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpblJhbmdlKGNoYXJ0WCwgY2hhcnRZLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IHBvaW50ID0gdGhpcy5nZXRQcm9wcyhbXG4gICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAneSdcbiAgICAgICAgXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIGNvbnN0IHsgYW5nbGUgLCBkaXN0YW5jZSAgfSA9IGdldEFuZ2xlRnJvbVBvaW50KHBvaW50LCB7XG4gICAgICAgICAgICB4OiBjaGFydFgsXG4gICAgICAgICAgICB5OiBjaGFydFlcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHsgc3RhcnRBbmdsZSAsIGVuZEFuZ2xlICwgaW5uZXJSYWRpdXMgLCBvdXRlclJhZGl1cyAsIGNpcmN1bWZlcmVuY2UgIH0gPSB0aGlzLmdldFByb3BzKFtcbiAgICAgICAgICAgICdzdGFydEFuZ2xlJyxcbiAgICAgICAgICAgICdlbmRBbmdsZScsXG4gICAgICAgICAgICAnaW5uZXJSYWRpdXMnLFxuICAgICAgICAgICAgJ291dGVyUmFkaXVzJyxcbiAgICAgICAgICAgICdjaXJjdW1mZXJlbmNlJ1xuICAgICAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgckFkanVzdCA9ICh0aGlzLm9wdGlvbnMuc3BhY2luZyArIHRoaXMub3B0aW9ucy5ib3JkZXJXaWR0aCkgLyAyO1xuICAgICAgICBjb25zdCBfY2lyY3VtZmVyZW5jZSA9IHZhbHVlT3JEZWZhdWx0KGNpcmN1bWZlcmVuY2UsIGVuZEFuZ2xlIC0gc3RhcnRBbmdsZSk7XG4gICAgICAgIGNvbnN0IG5vblplcm9CZXR3ZWVuID0gX2FuZ2xlQmV0d2VlbihhbmdsZSwgc3RhcnRBbmdsZSwgZW5kQW5nbGUpICYmIHN0YXJ0QW5nbGUgIT09IGVuZEFuZ2xlO1xuICAgICAgICBjb25zdCBiZXR3ZWVuQW5nbGVzID0gX2NpcmN1bWZlcmVuY2UgPj0gVEFVIHx8IG5vblplcm9CZXR3ZWVuO1xuICAgICAgICBjb25zdCB3aXRoaW5SYWRpdXMgPSBfaXNCZXR3ZWVuKGRpc3RhbmNlLCBpbm5lclJhZGl1cyArIHJBZGp1c3QsIG91dGVyUmFkaXVzICsgckFkanVzdCk7XG4gICAgICAgIHJldHVybiBiZXR3ZWVuQW5nbGVzICYmIHdpdGhpblJhZGl1cztcbiAgICB9XG4gICAgZ2V0Q2VudGVyUG9pbnQodXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICBjb25zdCB7IHggLCB5ICwgc3RhcnRBbmdsZSAsIGVuZEFuZ2xlICwgaW5uZXJSYWRpdXMgLCBvdXRlclJhZGl1cyAgfSA9IHRoaXMuZ2V0UHJvcHMoW1xuICAgICAgICAgICAgJ3gnLFxuICAgICAgICAgICAgJ3knLFxuICAgICAgICAgICAgJ3N0YXJ0QW5nbGUnLFxuICAgICAgICAgICAgJ2VuZEFuZ2xlJyxcbiAgICAgICAgICAgICdpbm5lclJhZGl1cycsXG4gICAgICAgICAgICAnb3V0ZXJSYWRpdXMnXG4gICAgICAgIF0sIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCB7IG9mZnNldCAsIHNwYWNpbmcgIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGhhbGZBbmdsZSA9IChzdGFydEFuZ2xlICsgZW5kQW5nbGUpIC8gMjtcbiAgICAgICAgY29uc3QgaGFsZlJhZGl1cyA9IChpbm5lclJhZGl1cyArIG91dGVyUmFkaXVzICsgc3BhY2luZyArIG9mZnNldCkgLyAyO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogeCArIE1hdGguY29zKGhhbGZBbmdsZSkgKiBoYWxmUmFkaXVzLFxuICAgICAgICAgICAgeTogeSArIE1hdGguc2luKGhhbGZBbmdsZSkgKiBoYWxmUmFkaXVzXG4gICAgICAgIH07XG4gICAgfVxuICAgIHRvb2x0aXBQb3NpdGlvbih1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENlbnRlclBvaW50KHVzZUZpbmFsUG9zaXRpb24pO1xuICAgIH1cbiAgICBkcmF3KGN0eCkge1xuICAgICAgICBjb25zdCB7IG9wdGlvbnMgLCBjaXJjdW1mZXJlbmNlICB9ID0gdGhpcztcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gKG9wdGlvbnMub2Zmc2V0IHx8IDApIC8gNDtcbiAgICAgICAgY29uc3Qgc3BhY2luZyA9IChvcHRpb25zLnNwYWNpbmcgfHwgMCkgLyAyO1xuICAgICAgICBjb25zdCBjaXJjdWxhciA9IG9wdGlvbnMuY2lyY3VsYXI7XG4gICAgICAgIHRoaXMucGl4ZWxNYXJnaW4gPSBvcHRpb25zLmJvcmRlckFsaWduID09PSAnaW5uZXInID8gMC4zMyA6IDA7XG4gICAgICAgIHRoaXMuZnVsbENpcmNsZXMgPSBjaXJjdW1mZXJlbmNlID4gVEFVID8gTWF0aC5mbG9vcihjaXJjdW1mZXJlbmNlIC8gVEFVKSA6IDA7XG4gICAgICAgIGlmIChjaXJjdW1mZXJlbmNlID09PSAwIHx8IHRoaXMuaW5uZXJSYWRpdXMgPCAwIHx8IHRoaXMub3V0ZXJSYWRpdXMgPCAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgY29uc3QgaGFsZkFuZ2xlID0gKHRoaXMuc3RhcnRBbmdsZSArIHRoaXMuZW5kQW5nbGUpIC8gMjtcbiAgICAgICAgY3R4LnRyYW5zbGF0ZShNYXRoLmNvcyhoYWxmQW5nbGUpICogb2Zmc2V0LCBNYXRoLnNpbihoYWxmQW5nbGUpICogb2Zmc2V0KTtcbiAgICAgICAgY29uc3QgZml4ID0gMSAtIE1hdGguc2luKE1hdGgubWluKFBJLCBjaXJjdW1mZXJlbmNlIHx8IDApKTtcbiAgICAgICAgY29uc3QgcmFkaXVzT2Zmc2V0ID0gb2Zmc2V0ICogZml4O1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IG9wdGlvbnMuYm9yZGVyQ29sb3I7XG4gICAgICAgIGRyYXdBcmMoY3R4LCB0aGlzLCByYWRpdXNPZmZzZXQsIHNwYWNpbmcsIGNpcmN1bGFyKTtcbiAgICAgICAgZHJhd0JvcmRlcihjdHgsIHRoaXMsIHJhZGl1c09mZnNldCwgc3BhY2luZywgY2lyY3VsYXIpO1xuICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0U3R5bGUoY3R4LCBvcHRpb25zLCBzdHlsZSA9IG9wdGlvbnMpIHtcbiAgICBjdHgubGluZUNhcCA9IHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlckNhcFN0eWxlLCBvcHRpb25zLmJvcmRlckNhcFN0eWxlKTtcbiAgICBjdHguc2V0TGluZURhc2godmFsdWVPckRlZmF1bHQoc3R5bGUuYm9yZGVyRGFzaCwgb3B0aW9ucy5ib3JkZXJEYXNoKSk7XG4gICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gdmFsdWVPckRlZmF1bHQoc3R5bGUuYm9yZGVyRGFzaE9mZnNldCwgb3B0aW9ucy5ib3JkZXJEYXNoT2Zmc2V0KTtcbiAgICBjdHgubGluZUpvaW4gPSB2YWx1ZU9yRGVmYXVsdChzdHlsZS5ib3JkZXJKb2luU3R5bGUsIG9wdGlvbnMuYm9yZGVySm9pblN0eWxlKTtcbiAgICBjdHgubGluZVdpZHRoID0gdmFsdWVPckRlZmF1bHQoc3R5bGUuYm9yZGVyV2lkdGgsIG9wdGlvbnMuYm9yZGVyV2lkdGgpO1xuICAgIGN0eC5zdHJva2VTdHlsZSA9IHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlckNvbG9yLCBvcHRpb25zLmJvcmRlckNvbG9yKTtcbn1cbmZ1bmN0aW9uIGxpbmVUbyhjdHgsIHByZXZpb3VzLCB0YXJnZXQpIHtcbiAgICBjdHgubGluZVRvKHRhcmdldC54LCB0YXJnZXQueSk7XG59XG4gZnVuY3Rpb24gZ2V0TGluZU1ldGhvZChvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMuc3RlcHBlZCkge1xuICAgICAgICByZXR1cm4gX3N0ZXBwZWRMaW5lVG87XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnRlbnNpb24gfHwgb3B0aW9ucy5jdWJpY0ludGVycG9sYXRpb25Nb2RlID09PSAnbW9ub3RvbmUnKSB7XG4gICAgICAgIHJldHVybiBfYmV6aWVyQ3VydmVUbztcbiAgICB9XG4gICAgcmV0dXJuIGxpbmVUbztcbn1cbmZ1bmN0aW9uIHBhdGhWYXJzKHBvaW50cywgc2VnbWVudCwgcGFyYW1zID0ge30pIHtcbiAgICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgY29uc3QgeyBzdGFydDogcGFyYW1zU3RhcnQgPSAwICwgZW5kOiBwYXJhbXNFbmQgPSBjb3VudCAtIDEgIH0gPSBwYXJhbXM7XG4gICAgY29uc3QgeyBzdGFydDogc2VnbWVudFN0YXJ0ICwgZW5kOiBzZWdtZW50RW5kICB9ID0gc2VnbWVudDtcbiAgICBjb25zdCBzdGFydCA9IE1hdGgubWF4KHBhcmFtc1N0YXJ0LCBzZWdtZW50U3RhcnQpO1xuICAgIGNvbnN0IGVuZCA9IE1hdGgubWluKHBhcmFtc0VuZCwgc2VnbWVudEVuZCk7XG4gICAgY29uc3Qgb3V0c2lkZSA9IHBhcmFtc1N0YXJ0IDwgc2VnbWVudFN0YXJ0ICYmIHBhcmFtc0VuZCA8IHNlZ21lbnRTdGFydCB8fCBwYXJhbXNTdGFydCA+IHNlZ21lbnRFbmQgJiYgcGFyYW1zRW5kID4gc2VnbWVudEVuZDtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb3VudCxcbiAgICAgICAgc3RhcnQsXG4gICAgICAgIGxvb3A6IHNlZ21lbnQubG9vcCxcbiAgICAgICAgaWxlbjogZW5kIDwgc3RhcnQgJiYgIW91dHNpZGUgPyBjb3VudCArIGVuZCAtIHN0YXJ0IDogZW5kIC0gc3RhcnRcbiAgICB9O1xufVxuIGZ1bmN0aW9uIHBhdGhTZWdtZW50KGN0eCwgbGluZSwgc2VnbWVudCwgcGFyYW1zKSB7XG4gICAgY29uc3QgeyBwb2ludHMgLCBvcHRpb25zICB9ID0gbGluZTtcbiAgICBjb25zdCB7IGNvdW50ICwgc3RhcnQgLCBsb29wICwgaWxlbiAgfSA9IHBhdGhWYXJzKHBvaW50cywgc2VnbWVudCwgcGFyYW1zKTtcbiAgICBjb25zdCBsaW5lTWV0aG9kID0gZ2V0TGluZU1ldGhvZChvcHRpb25zKTtcbiAgICBsZXQgeyBtb3ZlID10cnVlICwgcmV2ZXJzZSAgfSA9IHBhcmFtcyB8fCB7fTtcbiAgICBsZXQgaSwgcG9pbnQsIHByZXY7XG4gICAgZm9yKGkgPSAwOyBpIDw9IGlsZW47ICsraSl7XG4gICAgICAgIHBvaW50ID0gcG9pbnRzWyhzdGFydCArIChyZXZlcnNlID8gaWxlbiAtIGkgOiBpKSkgJSBjb3VudF07XG4gICAgICAgIGlmIChwb2ludC5za2lwKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfSBlbHNlIGlmIChtb3ZlKSB7XG4gICAgICAgICAgICBjdHgubW92ZVRvKHBvaW50LngsIHBvaW50LnkpO1xuICAgICAgICAgICAgbW92ZSA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGluZU1ldGhvZChjdHgsIHByZXYsIHBvaW50LCByZXZlcnNlLCBvcHRpb25zLnN0ZXBwZWQpO1xuICAgICAgICB9XG4gICAgICAgIHByZXYgPSBwb2ludDtcbiAgICB9XG4gICAgaWYgKGxvb3ApIHtcbiAgICAgICAgcG9pbnQgPSBwb2ludHNbKHN0YXJ0ICsgKHJldmVyc2UgPyBpbGVuIDogMCkpICUgY291bnRdO1xuICAgICAgICBsaW5lTWV0aG9kKGN0eCwgcHJldiwgcG9pbnQsIHJldmVyc2UsIG9wdGlvbnMuc3RlcHBlZCk7XG4gICAgfVxuICAgIHJldHVybiAhIWxvb3A7XG59XG4gZnVuY3Rpb24gZmFzdFBhdGhTZWdtZW50KGN0eCwgbGluZSwgc2VnbWVudCwgcGFyYW1zKSB7XG4gICAgY29uc3QgcG9pbnRzID0gbGluZS5wb2ludHM7XG4gICAgY29uc3QgeyBjb3VudCAsIHN0YXJ0ICwgaWxlbiAgfSA9IHBhdGhWYXJzKHBvaW50cywgc2VnbWVudCwgcGFyYW1zKTtcbiAgICBjb25zdCB7IG1vdmUgPXRydWUgLCByZXZlcnNlICB9ID0gcGFyYW1zIHx8IHt9O1xuICAgIGxldCBhdmdYID0gMDtcbiAgICBsZXQgY291bnRYID0gMDtcbiAgICBsZXQgaSwgcG9pbnQsIHByZXZYLCBtaW5ZLCBtYXhZLCBsYXN0WTtcbiAgICBjb25zdCBwb2ludEluZGV4ID0gKGluZGV4KT0+KHN0YXJ0ICsgKHJldmVyc2UgPyBpbGVuIC0gaW5kZXggOiBpbmRleCkpICUgY291bnQ7XG4gICAgY29uc3QgZHJhd1ggPSAoKT0+e1xuICAgICAgICBpZiAobWluWSAhPT0gbWF4WSkge1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhhdmdYLCBtYXhZKTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oYXZnWCwgbWluWSk7XG4gICAgICAgICAgICBjdHgubGluZVRvKGF2Z1gsIGxhc3RZKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgaWYgKG1vdmUpIHtcbiAgICAgICAgcG9pbnQgPSBwb2ludHNbcG9pbnRJbmRleCgwKV07XG4gICAgICAgIGN0eC5tb3ZlVG8ocG9pbnQueCwgcG9pbnQueSk7XG4gICAgfVxuICAgIGZvcihpID0gMDsgaSA8PSBpbGVuOyArK2kpe1xuICAgICAgICBwb2ludCA9IHBvaW50c1twb2ludEluZGV4KGkpXTtcbiAgICAgICAgaWYgKHBvaW50LnNraXApIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHggPSBwb2ludC54O1xuICAgICAgICBjb25zdCB5ID0gcG9pbnQueTtcbiAgICAgICAgY29uc3QgdHJ1bmNYID0geCB8IDA7XG4gICAgICAgIGlmICh0cnVuY1ggPT09IHByZXZYKSB7XG4gICAgICAgICAgICBpZiAoeSA8IG1pblkpIHtcbiAgICAgICAgICAgICAgICBtaW5ZID0geTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoeSA+IG1heFkpIHtcbiAgICAgICAgICAgICAgICBtYXhZID0geTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF2Z1ggPSAoY291bnRYICogYXZnWCArIHgpIC8gKytjb3VudFg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkcmF3WCgpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4LCB5KTtcbiAgICAgICAgICAgIHByZXZYID0gdHJ1bmNYO1xuICAgICAgICAgICAgY291bnRYID0gMDtcbiAgICAgICAgICAgIG1pblkgPSBtYXhZID0geTtcbiAgICAgICAgfVxuICAgICAgICBsYXN0WSA9IHk7XG4gICAgfVxuICAgIGRyYXdYKCk7XG59XG4gZnVuY3Rpb24gX2dldFNlZ21lbnRNZXRob2QobGluZSkge1xuICAgIGNvbnN0IG9wdHMgPSBsaW5lLm9wdGlvbnM7XG4gICAgY29uc3QgYm9yZGVyRGFzaCA9IG9wdHMuYm9yZGVyRGFzaCAmJiBvcHRzLmJvcmRlckRhc2gubGVuZ3RoO1xuICAgIGNvbnN0IHVzZUZhc3RQYXRoID0gIWxpbmUuX2RlY2ltYXRlZCAmJiAhbGluZS5fbG9vcCAmJiAhb3B0cy50ZW5zaW9uICYmIG9wdHMuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZSAhPT0gJ21vbm90b25lJyAmJiAhb3B0cy5zdGVwcGVkICYmICFib3JkZXJEYXNoO1xuICAgIHJldHVybiB1c2VGYXN0UGF0aCA/IGZhc3RQYXRoU2VnbWVudCA6IHBhdGhTZWdtZW50O1xufVxuIGZ1bmN0aW9uIF9nZXRJbnRlcnBvbGF0aW9uTWV0aG9kKG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucy5zdGVwcGVkKSB7XG4gICAgICAgIHJldHVybiBfc3RlcHBlZEludGVycG9sYXRpb247XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnRlbnNpb24gfHwgb3B0aW9ucy5jdWJpY0ludGVycG9sYXRpb25Nb2RlID09PSAnbW9ub3RvbmUnKSB7XG4gICAgICAgIHJldHVybiBfYmV6aWVySW50ZXJwb2xhdGlvbjtcbiAgICB9XG4gICAgcmV0dXJuIF9wb2ludEluTGluZTtcbn1cbmZ1bmN0aW9uIHN0cm9rZVBhdGhXaXRoQ2FjaGUoY3R4LCBsaW5lLCBzdGFydCwgY291bnQpIHtcbiAgICBsZXQgcGF0aCA9IGxpbmUuX3BhdGg7XG4gICAgaWYgKCFwYXRoKSB7XG4gICAgICAgIHBhdGggPSBsaW5lLl9wYXRoID0gbmV3IFBhdGgyRCgpO1xuICAgICAgICBpZiAobGluZS5wYXRoKHBhdGgsIHN0YXJ0LCBjb3VudCkpIHtcbiAgICAgICAgICAgIHBhdGguY2xvc2VQYXRoKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0U3R5bGUoY3R4LCBsaW5lLm9wdGlvbnMpO1xuICAgIGN0eC5zdHJva2UocGF0aCk7XG59XG5mdW5jdGlvbiBzdHJva2VQYXRoRGlyZWN0KGN0eCwgbGluZSwgc3RhcnQsIGNvdW50KSB7XG4gICAgY29uc3QgeyBzZWdtZW50cyAsIG9wdGlvbnMgIH0gPSBsaW5lO1xuICAgIGNvbnN0IHNlZ21lbnRNZXRob2QgPSBfZ2V0U2VnbWVudE1ldGhvZChsaW5lKTtcbiAgICBmb3IgKGNvbnN0IHNlZ21lbnQgb2Ygc2VnbWVudHMpe1xuICAgICAgICBzZXRTdHlsZShjdHgsIG9wdGlvbnMsIHNlZ21lbnQuc3R5bGUpO1xuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGlmIChzZWdtZW50TWV0aG9kKGN0eCwgbGluZSwgc2VnbWVudCwge1xuICAgICAgICAgICAgc3RhcnQsXG4gICAgICAgICAgICBlbmQ6IHN0YXJ0ICsgY291bnQgLSAxXG4gICAgICAgIH0pKSB7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgIH1cbn1cbmNvbnN0IHVzZVBhdGgyRCA9IHR5cGVvZiBQYXRoMkQgPT09ICdmdW5jdGlvbic7XG5mdW5jdGlvbiBkcmF3KGN0eCwgbGluZSwgc3RhcnQsIGNvdW50KSB7XG4gICAgaWYgKHVzZVBhdGgyRCAmJiAhbGluZS5vcHRpb25zLnNlZ21lbnQpIHtcbiAgICAgICAgc3Ryb2tlUGF0aFdpdGhDYWNoZShjdHgsIGxpbmUsIHN0YXJ0LCBjb3VudCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc3Ryb2tlUGF0aERpcmVjdChjdHgsIGxpbmUsIHN0YXJ0LCBjb3VudCk7XG4gICAgfVxufVxuY2xhc3MgTGluZUVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgICBzdGF0aWMgaWQgPSAnbGluZSc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBib3JkZXJDYXBTdHlsZTogJ2J1dHQnLFxuICAgICAgICBib3JkZXJEYXNoOiBbXSxcbiAgICAgICAgYm9yZGVyRGFzaE9mZnNldDogMCxcbiAgICAgICAgYm9yZGVySm9pblN0eWxlOiAnbWl0ZXInLFxuICAgICAgICBib3JkZXJXaWR0aDogMyxcbiAgICAgICAgY2FwQmV6aWVyUG9pbnRzOiB0cnVlLFxuICAgICAgICBjdWJpY0ludGVycG9sYXRpb25Nb2RlOiAnZGVmYXVsdCcsXG4gICAgICAgIGZpbGw6IGZhbHNlLFxuICAgICAgICBzcGFuR2FwczogZmFsc2UsXG4gICAgICAgIHN0ZXBwZWQ6IGZhbHNlLFxuICAgICAgICB0ZW5zaW9uOiAwXG4gICAgfTtcbiBzdGF0aWMgZGVmYXVsdFJvdXRlcyA9IHtcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAnYmFja2dyb3VuZENvbG9yJyxcbiAgICAgICAgYm9yZGVyQ29sb3I6ICdib3JkZXJDb2xvcidcbiAgICB9O1xuICAgIHN0YXRpYyBkZXNjcmlwdG9ycyA9IHtcbiAgICAgICAgX3NjcmlwdGFibGU6IHRydWUsXG4gICAgICAgIF9pbmRleGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ2JvcmRlckRhc2gnICYmIG5hbWUgIT09ICdmaWxsJ1xuICAgIH07XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5hbmltYXRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fY2hhcnQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2xvb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2Z1bGxMb29wID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9wYXRoID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9wb2ludHMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3NlZ21lbnRzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9kZWNpbWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fcG9pbnRzVXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9kYXRhc2V0SW5kZXggPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChjZmcpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgY2ZnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB1cGRhdGVDb250cm9sUG9pbnRzKGNoYXJ0QXJlYSwgaW5kZXhBeGlzKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmICgob3B0aW9ucy50ZW5zaW9uIHx8IG9wdGlvbnMuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZSA9PT0gJ21vbm90b25lJykgJiYgIW9wdGlvbnMuc3RlcHBlZCAmJiAhdGhpcy5fcG9pbnRzVXBkYXRlZCkge1xuICAgICAgICAgICAgY29uc3QgbG9vcCA9IG9wdGlvbnMuc3BhbkdhcHMgPyB0aGlzLl9sb29wIDogdGhpcy5fZnVsbExvb3A7XG4gICAgICAgICAgICBfdXBkYXRlQmV6aWVyQ29udHJvbFBvaW50cyh0aGlzLl9wb2ludHMsIG9wdGlvbnMsIGNoYXJ0QXJlYSwgbG9vcCwgaW5kZXhBeGlzKTtcbiAgICAgICAgICAgIHRoaXMuX3BvaW50c1VwZGF0ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHNldCBwb2ludHMocG9pbnRzKSB7XG4gICAgICAgIHRoaXMuX3BvaW50cyA9IHBvaW50cztcbiAgICAgICAgZGVsZXRlIHRoaXMuX3NlZ21lbnRzO1xuICAgICAgICBkZWxldGUgdGhpcy5fcGF0aDtcbiAgICAgICAgdGhpcy5fcG9pbnRzVXBkYXRlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBnZXQgcG9pbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcG9pbnRzO1xuICAgIH1cbiAgICBnZXQgc2VnbWVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZWdtZW50cyB8fCAodGhpcy5fc2VnbWVudHMgPSBfY29tcHV0ZVNlZ21lbnRzKHRoaXMsIHRoaXMub3B0aW9ucy5zZWdtZW50KSk7XG4gICAgfVxuIGZpcnN0KCkge1xuICAgICAgICBjb25zdCBzZWdtZW50cyA9IHRoaXMuc2VnbWVudHM7XG4gICAgICAgIGNvbnN0IHBvaW50cyA9IHRoaXMucG9pbnRzO1xuICAgICAgICByZXR1cm4gc2VnbWVudHMubGVuZ3RoICYmIHBvaW50c1tzZWdtZW50c1swXS5zdGFydF07XG4gICAgfVxuIGxhc3QoKSB7XG4gICAgICAgIGNvbnN0IHNlZ21lbnRzID0gdGhpcy5zZWdtZW50cztcbiAgICAgICAgY29uc3QgcG9pbnRzID0gdGhpcy5wb2ludHM7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gc2VnbWVudHMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gY291bnQgJiYgcG9pbnRzW3NlZ21lbnRzW2NvdW50IC0gMV0uZW5kXTtcbiAgICB9XG4gaW50ZXJwb2xhdGUocG9pbnQsIHByb3BlcnR5KSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gcG9pbnRbcHJvcGVydHldO1xuICAgICAgICBjb25zdCBwb2ludHMgPSB0aGlzLnBvaW50cztcbiAgICAgICAgY29uc3Qgc2VnbWVudHMgPSBfYm91bmRTZWdtZW50cyh0aGlzLCB7XG4gICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgIHN0YXJ0OiB2YWx1ZSxcbiAgICAgICAgICAgIGVuZDogdmFsdWVcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghc2VnbWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgIGNvbnN0IF9pbnRlcnBvbGF0ZSA9IF9nZXRJbnRlcnBvbGF0aW9uTWV0aG9kKG9wdGlvbnMpO1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gc2VnbWVudHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGNvbnN0IHsgc3RhcnQgLCBlbmQgIH0gPSBzZWdtZW50c1tpXTtcbiAgICAgICAgICAgIGNvbnN0IHAxID0gcG9pbnRzW3N0YXJ0XTtcbiAgICAgICAgICAgIGNvbnN0IHAyID0gcG9pbnRzW2VuZF07XG4gICAgICAgICAgICBpZiAocDEgPT09IHAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gocDEpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdCA9IE1hdGguYWJzKCh2YWx1ZSAtIHAxW3Byb3BlcnR5XSkgLyAocDJbcHJvcGVydHldIC0gcDFbcHJvcGVydHldKSk7XG4gICAgICAgICAgICBjb25zdCBpbnRlcnBvbGF0ZWQgPSBfaW50ZXJwb2xhdGUocDEsIHAyLCB0LCBvcHRpb25zLnN0ZXBwZWQpO1xuICAgICAgICAgICAgaW50ZXJwb2xhdGVkW3Byb3BlcnR5XSA9IHBvaW50W3Byb3BlcnR5XTtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGludGVycG9sYXRlZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdC5sZW5ndGggPT09IDEgPyByZXN1bHRbMF0gOiByZXN1bHQ7XG4gICAgfVxuIHBhdGhTZWdtZW50KGN0eCwgc2VnbWVudCwgcGFyYW1zKSB7XG4gICAgICAgIGNvbnN0IHNlZ21lbnRNZXRob2QgPSBfZ2V0U2VnbWVudE1ldGhvZCh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHNlZ21lbnRNZXRob2QoY3R4LCB0aGlzLCBzZWdtZW50LCBwYXJhbXMpO1xuICAgIH1cbiBwYXRoKGN0eCwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IHNlZ21lbnRzID0gdGhpcy5zZWdtZW50cztcbiAgICAgICAgY29uc3Qgc2VnbWVudE1ldGhvZCA9IF9nZXRTZWdtZW50TWV0aG9kKHRoaXMpO1xuICAgICAgICBsZXQgbG9vcCA9IHRoaXMuX2xvb3A7XG4gICAgICAgIHN0YXJ0ID0gc3RhcnQgfHwgMDtcbiAgICAgICAgY291bnQgPSBjb3VudCB8fCB0aGlzLnBvaW50cy5sZW5ndGggLSBzdGFydDtcbiAgICAgICAgZm9yIChjb25zdCBzZWdtZW50IG9mIHNlZ21lbnRzKXtcbiAgICAgICAgICAgIGxvb3AgJj0gc2VnbWVudE1ldGhvZChjdHgsIHRoaXMsIHNlZ21lbnQsIHtcbiAgICAgICAgICAgICAgICBzdGFydCxcbiAgICAgICAgICAgICAgICBlbmQ6IHN0YXJ0ICsgY291bnQgLSAxXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gISFsb29wO1xuICAgIH1cbiBkcmF3KGN0eCwgY2hhcnRBcmVhLCBzdGFydCwgY291bnQpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyB8fCB7fTtcbiAgICAgICAgY29uc3QgcG9pbnRzID0gdGhpcy5wb2ludHMgfHwgW107XG4gICAgICAgIGlmIChwb2ludHMubGVuZ3RoICYmIG9wdGlvbnMuYm9yZGVyV2lkdGgpIHtcbiAgICAgICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgICAgICBkcmF3KGN0eCwgdGhpcywgc3RhcnQsIGNvdW50KTtcbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuYW5pbWF0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3BvaW50c1VwZGF0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3BhdGggPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGluUmFuZ2UkMShlbCwgcG9zLCBheGlzLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IGVsLm9wdGlvbnM7XG4gICAgY29uc3QgeyBbYXhpc106IHZhbHVlICB9ID0gZWwuZ2V0UHJvcHMoW1xuICAgICAgICBheGlzXG4gICAgXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgcmV0dXJuIE1hdGguYWJzKHBvcyAtIHZhbHVlKSA8IG9wdGlvbnMucmFkaXVzICsgb3B0aW9ucy5oaXRSYWRpdXM7XG59XG5jbGFzcyBQb2ludEVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgICBzdGF0aWMgaWQgPSAncG9pbnQnO1xuICAgIHBhcnNlZDtcbiAgICBza2lwO1xuICAgIHN0b3A7XG4gICAgLyoqXG4gICAqIEB0eXBlIHthbnl9XG4gICAqLyBzdGF0aWMgZGVmYXVsdHMgPSB7XG4gICAgICAgIGJvcmRlcldpZHRoOiAxLFxuICAgICAgICBoaXRSYWRpdXM6IDEsXG4gICAgICAgIGhvdmVyQm9yZGVyV2lkdGg6IDEsXG4gICAgICAgIGhvdmVyUmFkaXVzOiA0LFxuICAgICAgICBwb2ludFN0eWxlOiAnY2lyY2xlJyxcbiAgICAgICAgcmFkaXVzOiAzLFxuICAgICAgICByb3RhdGlvbjogMFxuICAgIH07XG4gICAgLyoqXG4gICAqIEB0eXBlIHthbnl9XG4gICAqLyBzdGF0aWMgZGVmYXVsdFJvdXRlcyA9IHtcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAnYmFja2dyb3VuZENvbG9yJyxcbiAgICAgICAgYm9yZGVyQ29sb3I6ICdib3JkZXJDb2xvcidcbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGNmZyl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5wYXJzZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuc2tpcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zdG9wID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoY2ZnKSB7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNmZyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaW5SYW5nZShtb3VzZVgsIG1vdXNlWSwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB7IHggLCB5ICB9ID0gdGhpcy5nZXRQcm9wcyhbXG4gICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAneSdcbiAgICAgICAgXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIHJldHVybiBNYXRoLnBvdyhtb3VzZVggLSB4LCAyKSArIE1hdGgucG93KG1vdXNlWSAtIHksIDIpIDwgTWF0aC5wb3cob3B0aW9ucy5oaXRSYWRpdXMgKyBvcHRpb25zLnJhZGl1cywgMik7XG4gICAgfVxuICAgIGluWFJhbmdlKG1vdXNlWCwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICByZXR1cm4gaW5SYW5nZSQxKHRoaXMsIG1vdXNlWCwgJ3gnLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9XG4gICAgaW5ZUmFuZ2UobW91c2VZLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIHJldHVybiBpblJhbmdlJDEodGhpcywgbW91c2VZLCAneScsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgIH1cbiAgICBnZXRDZW50ZXJQb2ludCh1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IHsgeCAsIHkgIH0gPSB0aGlzLmdldFByb3BzKFtcbiAgICAgICAgICAgICd4JyxcbiAgICAgICAgICAgICd5J1xuICAgICAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICB5XG4gICAgICAgIH07XG4gICAgfVxuICAgIHNpemUob3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB0aGlzLm9wdGlvbnMgfHwge307XG4gICAgICAgIGxldCByYWRpdXMgPSBvcHRpb25zLnJhZGl1cyB8fCAwO1xuICAgICAgICByYWRpdXMgPSBNYXRoLm1heChyYWRpdXMsIHJhZGl1cyAmJiBvcHRpb25zLmhvdmVyUmFkaXVzIHx8IDApO1xuICAgICAgICBjb25zdCBib3JkZXJXaWR0aCA9IHJhZGl1cyAmJiBvcHRpb25zLmJvcmRlcldpZHRoIHx8IDA7XG4gICAgICAgIHJldHVybiAocmFkaXVzICsgYm9yZGVyV2lkdGgpICogMjtcbiAgICB9XG4gICAgZHJhdyhjdHgsIGFyZWEpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgaWYgKHRoaXMuc2tpcCB8fCBvcHRpb25zLnJhZGl1cyA8IDAuMSB8fCAhX2lzUG9pbnRJbkFyZWEodGhpcywgYXJlYSwgdGhpcy5zaXplKG9wdGlvbnMpIC8gMikpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBvcHRpb25zLmJvcmRlckNvbG9yO1xuICAgICAgICBjdHgubGluZVdpZHRoID0gb3B0aW9ucy5ib3JkZXJXaWR0aDtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yO1xuICAgICAgICBkcmF3UG9pbnQoY3R4LCBvcHRpb25zLCB0aGlzLngsIHRoaXMueSk7XG4gICAgfVxuICAgIGdldFJhbmdlKCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zIHx8IHt9O1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIEZhbGxiYWNrcyBzaG91bGQgbmV2ZXIgYmUgaGl0IGluIHByYWN0aWNlXG4gICAgICAgIHJldHVybiBvcHRpb25zLnJhZGl1cyArIG9wdGlvbnMuaGl0UmFkaXVzO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0QmFyQm91bmRzKGJhciwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgIGNvbnN0IHsgeCAsIHkgLCBiYXNlICwgd2lkdGggLCBoZWlnaHQgIH0gPSAgYmFyLmdldFByb3BzKFtcbiAgICAgICAgJ3gnLFxuICAgICAgICAneScsXG4gICAgICAgICdiYXNlJyxcbiAgICAgICAgJ3dpZHRoJyxcbiAgICAgICAgJ2hlaWdodCdcbiAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICBsZXQgbGVmdCwgcmlnaHQsIHRvcCwgYm90dG9tLCBoYWxmO1xuICAgIGlmIChiYXIuaG9yaXpvbnRhbCkge1xuICAgICAgICBoYWxmID0gaGVpZ2h0IC8gMjtcbiAgICAgICAgbGVmdCA9IE1hdGgubWluKHgsIGJhc2UpO1xuICAgICAgICByaWdodCA9IE1hdGgubWF4KHgsIGJhc2UpO1xuICAgICAgICB0b3AgPSB5IC0gaGFsZjtcbiAgICAgICAgYm90dG9tID0geSArIGhhbGY7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaGFsZiA9IHdpZHRoIC8gMjtcbiAgICAgICAgbGVmdCA9IHggLSBoYWxmO1xuICAgICAgICByaWdodCA9IHggKyBoYWxmO1xuICAgICAgICB0b3AgPSBNYXRoLm1pbih5LCBiYXNlKTtcbiAgICAgICAgYm90dG9tID0gTWF0aC5tYXgoeSwgYmFzZSk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQsXG4gICAgICAgIHRvcCxcbiAgICAgICAgcmlnaHQsXG4gICAgICAgIGJvdHRvbVxuICAgIH07XG59XG5mdW5jdGlvbiBza2lwT3JMaW1pdChza2lwLCB2YWx1ZSwgbWluLCBtYXgpIHtcbiAgICByZXR1cm4gc2tpcCA/IDAgOiBfbGltaXRWYWx1ZSh2YWx1ZSwgbWluLCBtYXgpO1xufVxuZnVuY3Rpb24gcGFyc2VCb3JkZXJXaWR0aChiYXIsIG1heFcsIG1heEgpIHtcbiAgICBjb25zdCB2YWx1ZSA9IGJhci5vcHRpb25zLmJvcmRlcldpZHRoO1xuICAgIGNvbnN0IHNraXAgPSBiYXIuYm9yZGVyU2tpcHBlZDtcbiAgICBjb25zdCBvID0gdG9UUkJMKHZhbHVlKTtcbiAgICByZXR1cm4ge1xuICAgICAgICB0OiBza2lwT3JMaW1pdChza2lwLnRvcCwgby50b3AsIDAsIG1heEgpLFxuICAgICAgICByOiBza2lwT3JMaW1pdChza2lwLnJpZ2h0LCBvLnJpZ2h0LCAwLCBtYXhXKSxcbiAgICAgICAgYjogc2tpcE9yTGltaXQoc2tpcC5ib3R0b20sIG8uYm90dG9tLCAwLCBtYXhIKSxcbiAgICAgICAgbDogc2tpcE9yTGltaXQoc2tpcC5sZWZ0LCBvLmxlZnQsIDAsIG1heFcpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlQm9yZGVyUmFkaXVzKGJhciwgbWF4VywgbWF4SCkge1xuICAgIGNvbnN0IHsgZW5hYmxlQm9yZGVyUmFkaXVzICB9ID0gYmFyLmdldFByb3BzKFtcbiAgICAgICAgJ2VuYWJsZUJvcmRlclJhZGl1cydcbiAgICBdKTtcbiAgICBjb25zdCB2YWx1ZSA9IGJhci5vcHRpb25zLmJvcmRlclJhZGl1cztcbiAgICBjb25zdCBvID0gdG9UUkJMQ29ybmVycyh2YWx1ZSk7XG4gICAgY29uc3QgbWF4UiA9IE1hdGgubWluKG1heFcsIG1heEgpO1xuICAgIGNvbnN0IHNraXAgPSBiYXIuYm9yZGVyU2tpcHBlZDtcbiAgICBjb25zdCBlbmFibGVCb3JkZXIgPSBlbmFibGVCb3JkZXJSYWRpdXMgfHwgaXNPYmplY3QodmFsdWUpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHRvcExlZnQ6IHNraXBPckxpbWl0KCFlbmFibGVCb3JkZXIgfHwgc2tpcC50b3AgfHwgc2tpcC5sZWZ0LCBvLnRvcExlZnQsIDAsIG1heFIpLFxuICAgICAgICB0b3BSaWdodDogc2tpcE9yTGltaXQoIWVuYWJsZUJvcmRlciB8fCBza2lwLnRvcCB8fCBza2lwLnJpZ2h0LCBvLnRvcFJpZ2h0LCAwLCBtYXhSKSxcbiAgICAgICAgYm90dG9tTGVmdDogc2tpcE9yTGltaXQoIWVuYWJsZUJvcmRlciB8fCBza2lwLmJvdHRvbSB8fCBza2lwLmxlZnQsIG8uYm90dG9tTGVmdCwgMCwgbWF4UiksXG4gICAgICAgIGJvdHRvbVJpZ2h0OiBza2lwT3JMaW1pdCghZW5hYmxlQm9yZGVyIHx8IHNraXAuYm90dG9tIHx8IHNraXAucmlnaHQsIG8uYm90dG9tUmlnaHQsIDAsIG1heFIpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGJvdW5kaW5nUmVjdHMoYmFyKSB7XG4gICAgY29uc3QgYm91bmRzID0gZ2V0QmFyQm91bmRzKGJhcik7XG4gICAgY29uc3Qgd2lkdGggPSBib3VuZHMucmlnaHQgLSBib3VuZHMubGVmdDtcbiAgICBjb25zdCBoZWlnaHQgPSBib3VuZHMuYm90dG9tIC0gYm91bmRzLnRvcDtcbiAgICBjb25zdCBib3JkZXIgPSBwYXJzZUJvcmRlcldpZHRoKGJhciwgd2lkdGggLyAyLCBoZWlnaHQgLyAyKTtcbiAgICBjb25zdCByYWRpdXMgPSBwYXJzZUJvcmRlclJhZGl1cyhiYXIsIHdpZHRoIC8gMiwgaGVpZ2h0IC8gMik7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgb3V0ZXI6IHtcbiAgICAgICAgICAgIHg6IGJvdW5kcy5sZWZ0LFxuICAgICAgICAgICAgeTogYm91bmRzLnRvcCxcbiAgICAgICAgICAgIHc6IHdpZHRoLFxuICAgICAgICAgICAgaDogaGVpZ2h0LFxuICAgICAgICAgICAgcmFkaXVzXG4gICAgICAgIH0sXG4gICAgICAgIGlubmVyOiB7XG4gICAgICAgICAgICB4OiBib3VuZHMubGVmdCArIGJvcmRlci5sLFxuICAgICAgICAgICAgeTogYm91bmRzLnRvcCArIGJvcmRlci50LFxuICAgICAgICAgICAgdzogd2lkdGggLSBib3JkZXIubCAtIGJvcmRlci5yLFxuICAgICAgICAgICAgaDogaGVpZ2h0IC0gYm9yZGVyLnQgLSBib3JkZXIuYixcbiAgICAgICAgICAgIHJhZGl1czoge1xuICAgICAgICAgICAgICAgIHRvcExlZnQ6IE1hdGgubWF4KDAsIHJhZGl1cy50b3BMZWZ0IC0gTWF0aC5tYXgoYm9yZGVyLnQsIGJvcmRlci5sKSksXG4gICAgICAgICAgICAgICAgdG9wUmlnaHQ6IE1hdGgubWF4KDAsIHJhZGl1cy50b3BSaWdodCAtIE1hdGgubWF4KGJvcmRlci50LCBib3JkZXIucikpLFxuICAgICAgICAgICAgICAgIGJvdHRvbUxlZnQ6IE1hdGgubWF4KDAsIHJhZGl1cy5ib3R0b21MZWZ0IC0gTWF0aC5tYXgoYm9yZGVyLmIsIGJvcmRlci5sKSksXG4gICAgICAgICAgICAgICAgYm90dG9tUmlnaHQ6IE1hdGgubWF4KDAsIHJhZGl1cy5ib3R0b21SaWdodCAtIE1hdGgubWF4KGJvcmRlci5iLCBib3JkZXIucikpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xufVxuZnVuY3Rpb24gaW5SYW5nZShiYXIsIHgsIHksIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBjb25zdCBza2lwWCA9IHggPT09IG51bGw7XG4gICAgY29uc3Qgc2tpcFkgPSB5ID09PSBudWxsO1xuICAgIGNvbnN0IHNraXBCb3RoID0gc2tpcFggJiYgc2tpcFk7XG4gICAgY29uc3QgYm91bmRzID0gYmFyICYmICFza2lwQm90aCAmJiBnZXRCYXJCb3VuZHMoYmFyLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICByZXR1cm4gYm91bmRzICYmIChza2lwWCB8fCBfaXNCZXR3ZWVuKHgsIGJvdW5kcy5sZWZ0LCBib3VuZHMucmlnaHQpKSAmJiAoc2tpcFkgfHwgX2lzQmV0d2Vlbih5LCBib3VuZHMudG9wLCBib3VuZHMuYm90dG9tKSk7XG59XG5mdW5jdGlvbiBoYXNSYWRpdXMocmFkaXVzKSB7XG4gICAgcmV0dXJuIHJhZGl1cy50b3BMZWZ0IHx8IHJhZGl1cy50b3BSaWdodCB8fCByYWRpdXMuYm90dG9tTGVmdCB8fCByYWRpdXMuYm90dG9tUmlnaHQ7XG59XG4gZnVuY3Rpb24gYWRkTm9ybWFsUmVjdFBhdGgoY3R4LCByZWN0KSB7XG4gICAgY3R4LnJlY3QocmVjdC54LCByZWN0LnksIHJlY3QudywgcmVjdC5oKTtcbn1cbmZ1bmN0aW9uIGluZmxhdGVSZWN0KHJlY3QsIGFtb3VudCwgcmVmUmVjdCA9IHt9KSB7XG4gICAgY29uc3QgeCA9IHJlY3QueCAhPT0gcmVmUmVjdC54ID8gLWFtb3VudCA6IDA7XG4gICAgY29uc3QgeSA9IHJlY3QueSAhPT0gcmVmUmVjdC55ID8gLWFtb3VudCA6IDA7XG4gICAgY29uc3QgdyA9IChyZWN0LnggKyByZWN0LncgIT09IHJlZlJlY3QueCArIHJlZlJlY3QudyA/IGFtb3VudCA6IDApIC0geDtcbiAgICBjb25zdCBoID0gKHJlY3QueSArIHJlY3QuaCAhPT0gcmVmUmVjdC55ICsgcmVmUmVjdC5oID8gYW1vdW50IDogMCkgLSB5O1xuICAgIHJldHVybiB7XG4gICAgICAgIHg6IHJlY3QueCArIHgsXG4gICAgICAgIHk6IHJlY3QueSArIHksXG4gICAgICAgIHc6IHJlY3QudyArIHcsXG4gICAgICAgIGg6IHJlY3QuaCArIGgsXG4gICAgICAgIHJhZGl1czogcmVjdC5yYWRpdXNcbiAgICB9O1xufVxuY2xhc3MgQmFyRWxlbWVudCBleHRlbmRzIEVsZW1lbnQge1xuICAgIHN0YXRpYyBpZCA9ICdiYXInO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgYm9yZGVyU2tpcHBlZDogJ3N0YXJ0JyxcbiAgICAgICAgYm9yZGVyV2lkdGg6IDAsXG4gICAgICAgIGJvcmRlclJhZGl1czogMCxcbiAgICAgICAgaW5mbGF0ZUFtb3VudDogJ2F1dG8nLFxuICAgICAgICBwb2ludFN0eWxlOiB1bmRlZmluZWRcbiAgICB9O1xuIHN0YXRpYyBkZWZhdWx0Um91dGVzID0ge1xuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6ICdiYWNrZ3JvdW5kQ29sb3InLFxuICAgICAgICBib3JkZXJDb2xvcjogJ2JvcmRlckNvbG9yJ1xuICAgIH07XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmhvcml6b250YWwgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuYmFzZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy53aWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuaW5mbGF0ZUFtb3VudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGNmZykge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBjZmcpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGRyYXcoY3R4KSB7XG4gICAgICAgIGNvbnN0IHsgaW5mbGF0ZUFtb3VudCAsIG9wdGlvbnM6IHsgYm9yZGVyQ29sb3IgLCBiYWNrZ3JvdW5kQ29sb3IgIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IGlubmVyICwgb3V0ZXIgIH0gPSBib3VuZGluZ1JlY3RzKHRoaXMpO1xuICAgICAgICBjb25zdCBhZGRSZWN0UGF0aCA9IGhhc1JhZGl1cyhvdXRlci5yYWRpdXMpID8gYWRkUm91bmRlZFJlY3RQYXRoIDogYWRkTm9ybWFsUmVjdFBhdGg7XG4gICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgIGlmIChvdXRlci53ICE9PSBpbm5lci53IHx8IG91dGVyLmggIT09IGlubmVyLmgpIHtcbiAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgIGFkZFJlY3RQYXRoKGN0eCwgaW5mbGF0ZVJlY3Qob3V0ZXIsIGluZmxhdGVBbW91bnQsIGlubmVyKSk7XG4gICAgICAgICAgICBjdHguY2xpcCgpO1xuICAgICAgICAgICAgYWRkUmVjdFBhdGgoY3R4LCBpbmZsYXRlUmVjdChpbm5lciwgLWluZmxhdGVBbW91bnQsIG91dGVyKSk7XG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gYm9yZGVyQ29sb3I7XG4gICAgICAgICAgICBjdHguZmlsbCgnZXZlbm9kZCcpO1xuICAgICAgICB9XG4gICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgYWRkUmVjdFBhdGgoY3R4LCBpbmZsYXRlUmVjdChpbm5lciwgaW5mbGF0ZUFtb3VudCkpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gYmFja2dyb3VuZENvbG9yO1xuICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH1cbiAgICBpblJhbmdlKG1vdXNlWCwgbW91c2VZLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIHJldHVybiBpblJhbmdlKHRoaXMsIG1vdXNlWCwgbW91c2VZLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9XG4gICAgaW5YUmFuZ2UobW91c2VYLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIHJldHVybiBpblJhbmdlKHRoaXMsIG1vdXNlWCwgbnVsbCwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgfVxuICAgIGluWVJhbmdlKG1vdXNlWSwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICByZXR1cm4gaW5SYW5nZSh0aGlzLCBudWxsLCBtb3VzZVksIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgIH1cbiAgICBnZXRDZW50ZXJQb2ludCh1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IHsgeCAsIHkgLCBiYXNlICwgaG9yaXpvbnRhbCAgfSA9ICB0aGlzLmdldFByb3BzKFtcbiAgICAgICAgICAgICd4JyxcbiAgICAgICAgICAgICd5JyxcbiAgICAgICAgICAgICdiYXNlJyxcbiAgICAgICAgICAgICdob3Jpem9udGFsJ1xuICAgICAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IGhvcml6b250YWwgPyAoeCArIGJhc2UpIC8gMiA6IHgsXG4gICAgICAgICAgICB5OiBob3Jpem9udGFsID8geSA6ICh5ICsgYmFzZSkgLyAyXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldFJhbmdlKGF4aXMpIHtcbiAgICAgICAgcmV0dXJuIGF4aXMgPT09ICd4JyA/IHRoaXMud2lkdGggLyAyIDogdGhpcy5oZWlnaHQgLyAyO1xuICAgIH1cbn1cblxudmFyIGVsZW1lbnRzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuX19wcm90b19fOiBudWxsLFxuQXJjRWxlbWVudDogQXJjRWxlbWVudCxcbkJhckVsZW1lbnQ6IEJhckVsZW1lbnQsXG5MaW5lRWxlbWVudDogTGluZUVsZW1lbnQsXG5Qb2ludEVsZW1lbnQ6IFBvaW50RWxlbWVudFxufSk7XG5cbmNvbnN0IEJPUkRFUl9DT0xPUlMgPSBbXG4gICAgJ3JnYig1NCwgMTYyLCAyMzUpJyxcbiAgICAncmdiKDI1NSwgOTksIDEzMiknLFxuICAgICdyZ2IoMjU1LCAxNTksIDY0KScsXG4gICAgJ3JnYigyNTUsIDIwNSwgODYpJyxcbiAgICAncmdiKDc1LCAxOTIsIDE5MiknLFxuICAgICdyZ2IoMTUzLCAxMDIsIDI1NSknLFxuICAgICdyZ2IoMjAxLCAyMDMsIDIwNyknIC8vIGdyZXlcbl07XG4vLyBCb3JkZXIgY29sb3JzIHdpdGggNTAlIHRyYW5zcGFyZW5jeVxuY29uc3QgQkFDS0dST1VORF9DT0xPUlMgPSAvKiAjX19QVVJFX18gKi8gQk9SREVSX0NPTE9SUy5tYXAoKGNvbG9yKT0+Y29sb3IucmVwbGFjZSgncmdiKCcsICdyZ2JhKCcpLnJlcGxhY2UoJyknLCAnLCAwLjUpJykpO1xuZnVuY3Rpb24gZ2V0Qm9yZGVyQ29sb3IoaSkge1xuICAgIHJldHVybiBCT1JERVJfQ09MT1JTW2kgJSBCT1JERVJfQ09MT1JTLmxlbmd0aF07XG59XG5mdW5jdGlvbiBnZXRCYWNrZ3JvdW5kQ29sb3IoaSkge1xuICAgIHJldHVybiBCQUNLR1JPVU5EX0NPTE9SU1tpICUgQkFDS0dST1VORF9DT0xPUlMubGVuZ3RoXTtcbn1cbmZ1bmN0aW9uIGNvbG9yaXplRGVmYXVsdERhdGFzZXQoZGF0YXNldCwgaSkge1xuICAgIGRhdGFzZXQuYm9yZGVyQ29sb3IgPSBnZXRCb3JkZXJDb2xvcihpKTtcbiAgICBkYXRhc2V0LmJhY2tncm91bmRDb2xvciA9IGdldEJhY2tncm91bmRDb2xvcihpKTtcbiAgICByZXR1cm4gKytpO1xufVxuZnVuY3Rpb24gY29sb3JpemVEb3VnaG51dERhdGFzZXQoZGF0YXNldCwgaSkge1xuICAgIGRhdGFzZXQuYmFja2dyb3VuZENvbG9yID0gZGF0YXNldC5kYXRhLm1hcCgoKT0+Z2V0Qm9yZGVyQ29sb3IoaSsrKSk7XG4gICAgcmV0dXJuIGk7XG59XG5mdW5jdGlvbiBjb2xvcml6ZVBvbGFyQXJlYURhdGFzZXQoZGF0YXNldCwgaSkge1xuICAgIGRhdGFzZXQuYmFja2dyb3VuZENvbG9yID0gZGF0YXNldC5kYXRhLm1hcCgoKT0+Z2V0QmFja2dyb3VuZENvbG9yKGkrKykpO1xuICAgIHJldHVybiBpO1xufVxuZnVuY3Rpb24gZ2V0Q29sb3JpemVyKGNoYXJ0KSB7XG4gICAgbGV0IGkgPSAwO1xuICAgIHJldHVybiAoZGF0YXNldCwgZGF0YXNldEluZGV4KT0+e1xuICAgICAgICBjb25zdCBjb250cm9sbGVyID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoZGF0YXNldEluZGV4KS5jb250cm9sbGVyO1xuICAgICAgICBpZiAoY29udHJvbGxlciBpbnN0YW5jZW9mIERvdWdobnV0Q29udHJvbGxlcikge1xuICAgICAgICAgICAgaSA9IGNvbG9yaXplRG91Z2hudXREYXRhc2V0KGRhdGFzZXQsIGkpO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbnRyb2xsZXIgaW5zdGFuY2VvZiBQb2xhckFyZWFDb250cm9sbGVyKSB7XG4gICAgICAgICAgICBpID0gY29sb3JpemVQb2xhckFyZWFEYXRhc2V0KGRhdGFzZXQsIGkpO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbnRyb2xsZXIpIHtcbiAgICAgICAgICAgIGkgPSBjb2xvcml6ZURlZmF1bHREYXRhc2V0KGRhdGFzZXQsIGkpO1xuICAgICAgICB9XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGNvbnRhaW5zQ29sb3JzRGVmaW5pdGlvbnMoZGVzY3JpcHRvcnMpIHtcbiAgICBsZXQgaztcbiAgICBmb3IoayBpbiBkZXNjcmlwdG9ycyl7XG4gICAgICAgIGlmIChkZXNjcmlwdG9yc1trXS5ib3JkZXJDb2xvciB8fCBkZXNjcmlwdG9yc1trXS5iYWNrZ3JvdW5kQ29sb3IpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGNvbnRhaW5zQ29sb3JzRGVmaW5pdGlvbihkZXNjcmlwdG9yKSB7XG4gICAgcmV0dXJuIGRlc2NyaXB0b3IgJiYgKGRlc2NyaXB0b3IuYm9yZGVyQ29sb3IgfHwgZGVzY3JpcHRvci5iYWNrZ3JvdW5kQ29sb3IpO1xufVxuZnVuY3Rpb24gY29udGFpbnNEZWZhdWx0Q29sb3JzRGVmZW5pdGlvbnMoKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRzLmJvcmRlckNvbG9yICE9PSAncmdiYSgwLDAsMCwwLjEpJyB8fCBkZWZhdWx0cy5iYWNrZ3JvdW5kQ29sb3IgIT09ICdyZ2JhKDAsMCwwLDAuMSknO1xufVxudmFyIHBsdWdpbl9jb2xvcnMgPSB7XG4gICAgaWQ6ICdjb2xvcnMnLFxuICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgIGZvcmNlT3ZlcnJpZGU6IGZhbHNlXG4gICAgfSxcbiAgICBiZWZvcmVMYXlvdXQgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBpZiAoIW9wdGlvbnMuZW5hYmxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgZGF0YTogeyBkYXRhc2V0cyAgfSAsIG9wdGlvbnM6IGNoYXJ0T3B0aW9ucyAgfSA9IGNoYXJ0LmNvbmZpZztcbiAgICAgICAgY29uc3QgeyBlbGVtZW50cyAgfSA9IGNoYXJ0T3B0aW9ucztcbiAgICAgICAgY29uc3QgY29udGFpbnNDb2xvckRlZmVuaXRpb24gPSBjb250YWluc0NvbG9yc0RlZmluaXRpb25zKGRhdGFzZXRzKSB8fCBjb250YWluc0NvbG9yc0RlZmluaXRpb24oY2hhcnRPcHRpb25zKSB8fCBlbGVtZW50cyAmJiBjb250YWluc0NvbG9yc0RlZmluaXRpb25zKGVsZW1lbnRzKSB8fCBjb250YWluc0RlZmF1bHRDb2xvcnNEZWZlbml0aW9ucygpO1xuICAgICAgICBpZiAoIW9wdGlvbnMuZm9yY2VPdmVycmlkZSAmJiBjb250YWluc0NvbG9yRGVmZW5pdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvbG9yaXplciA9IGdldENvbG9yaXplcihjaGFydCk7XG4gICAgICAgIGRhdGFzZXRzLmZvckVhY2goY29sb3JpemVyKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBsdHRiRGVjaW1hdGlvbihkYXRhLCBzdGFydCwgY291bnQsIGF2YWlsYWJsZVdpZHRoLCBvcHRpb25zKSB7XG4gY29uc3Qgc2FtcGxlcyA9IG9wdGlvbnMuc2FtcGxlcyB8fCBhdmFpbGFibGVXaWR0aDtcbiAgICBpZiAoc2FtcGxlcyA+PSBjb3VudCkge1xuICAgICAgICByZXR1cm4gZGF0YS5zbGljZShzdGFydCwgc3RhcnQgKyBjb3VudCk7XG4gICAgfVxuICAgIGNvbnN0IGRlY2ltYXRlZCA9IFtdO1xuICAgIGNvbnN0IGJ1Y2tldFdpZHRoID0gKGNvdW50IC0gMikgLyAoc2FtcGxlcyAtIDIpO1xuICAgIGxldCBzYW1wbGVkSW5kZXggPSAwO1xuICAgIGNvbnN0IGVuZEluZGV4ID0gc3RhcnQgKyBjb3VudCAtIDE7XG4gICAgbGV0IGEgPSBzdGFydDtcbiAgICBsZXQgaSwgbWF4QXJlYVBvaW50LCBtYXhBcmVhLCBhcmVhLCBuZXh0QTtcbiAgICBkZWNpbWF0ZWRbc2FtcGxlZEluZGV4KytdID0gZGF0YVthXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBzYW1wbGVzIC0gMjsgaSsrKXtcbiAgICAgICAgbGV0IGF2Z1ggPSAwO1xuICAgICAgICBsZXQgYXZnWSA9IDA7XG4gICAgICAgIGxldCBqO1xuICAgICAgICBjb25zdCBhdmdSYW5nZVN0YXJ0ID0gTWF0aC5mbG9vcigoaSArIDEpICogYnVja2V0V2lkdGgpICsgMSArIHN0YXJ0O1xuICAgICAgICBjb25zdCBhdmdSYW5nZUVuZCA9IE1hdGgubWluKE1hdGguZmxvb3IoKGkgKyAyKSAqIGJ1Y2tldFdpZHRoKSArIDEsIGNvdW50KSArIHN0YXJ0O1xuICAgICAgICBjb25zdCBhdmdSYW5nZUxlbmd0aCA9IGF2Z1JhbmdlRW5kIC0gYXZnUmFuZ2VTdGFydDtcbiAgICAgICAgZm9yKGogPSBhdmdSYW5nZVN0YXJ0OyBqIDwgYXZnUmFuZ2VFbmQ7IGorKyl7XG4gICAgICAgICAgICBhdmdYICs9IGRhdGFbal0ueDtcbiAgICAgICAgICAgIGF2Z1kgKz0gZGF0YVtqXS55O1xuICAgICAgICB9XG4gICAgICAgIGF2Z1ggLz0gYXZnUmFuZ2VMZW5ndGg7XG4gICAgICAgIGF2Z1kgLz0gYXZnUmFuZ2VMZW5ndGg7XG4gICAgICAgIGNvbnN0IHJhbmdlT2ZmcyA9IE1hdGguZmxvb3IoaSAqIGJ1Y2tldFdpZHRoKSArIDEgKyBzdGFydDtcbiAgICAgICAgY29uc3QgcmFuZ2VUbyA9IE1hdGgubWluKE1hdGguZmxvb3IoKGkgKyAxKSAqIGJ1Y2tldFdpZHRoKSArIDEsIGNvdW50KSArIHN0YXJ0O1xuICAgICAgICBjb25zdCB7IHg6IHBvaW50QXggLCB5OiBwb2ludEF5ICB9ID0gZGF0YVthXTtcbiAgICAgICAgbWF4QXJlYSA9IGFyZWEgPSAtMTtcbiAgICAgICAgZm9yKGogPSByYW5nZU9mZnM7IGogPCByYW5nZVRvOyBqKyspe1xuICAgICAgICAgICAgYXJlYSA9IDAuNSAqIE1hdGguYWJzKChwb2ludEF4IC0gYXZnWCkgKiAoZGF0YVtqXS55IC0gcG9pbnRBeSkgLSAocG9pbnRBeCAtIGRhdGFbal0ueCkgKiAoYXZnWSAtIHBvaW50QXkpKTtcbiAgICAgICAgICAgIGlmIChhcmVhID4gbWF4QXJlYSkge1xuICAgICAgICAgICAgICAgIG1heEFyZWEgPSBhcmVhO1xuICAgICAgICAgICAgICAgIG1heEFyZWFQb2ludCA9IGRhdGFbal07XG4gICAgICAgICAgICAgICAgbmV4dEEgPSBqO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlY2ltYXRlZFtzYW1wbGVkSW5kZXgrK10gPSBtYXhBcmVhUG9pbnQ7XG4gICAgICAgIGEgPSBuZXh0QTtcbiAgICB9XG4gICAgZGVjaW1hdGVkW3NhbXBsZWRJbmRleCsrXSA9IGRhdGFbZW5kSW5kZXhdO1xuICAgIHJldHVybiBkZWNpbWF0ZWQ7XG59XG5mdW5jdGlvbiBtaW5NYXhEZWNpbWF0aW9uKGRhdGEsIHN0YXJ0LCBjb3VudCwgYXZhaWxhYmxlV2lkdGgpIHtcbiAgICBsZXQgYXZnWCA9IDA7XG4gICAgbGV0IGNvdW50WCA9IDA7XG4gICAgbGV0IGksIHBvaW50LCB4LCB5LCBwcmV2WCwgbWluSW5kZXgsIG1heEluZGV4LCBzdGFydEluZGV4LCBtaW5ZLCBtYXhZO1xuICAgIGNvbnN0IGRlY2ltYXRlZCA9IFtdO1xuICAgIGNvbnN0IGVuZEluZGV4ID0gc3RhcnQgKyBjb3VudCAtIDE7XG4gICAgY29uc3QgeE1pbiA9IGRhdGFbc3RhcnRdLng7XG4gICAgY29uc3QgeE1heCA9IGRhdGFbZW5kSW5kZXhdLng7XG4gICAgY29uc3QgZHggPSB4TWF4IC0geE1pbjtcbiAgICBmb3IoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgKytpKXtcbiAgICAgICAgcG9pbnQgPSBkYXRhW2ldO1xuICAgICAgICB4ID0gKHBvaW50LnggLSB4TWluKSAvIGR4ICogYXZhaWxhYmxlV2lkdGg7XG4gICAgICAgIHkgPSBwb2ludC55O1xuICAgICAgICBjb25zdCB0cnVuY1ggPSB4IHwgMDtcbiAgICAgICAgaWYgKHRydW5jWCA9PT0gcHJldlgpIHtcbiAgICAgICAgICAgIGlmICh5IDwgbWluWSkge1xuICAgICAgICAgICAgICAgIG1pblkgPSB5O1xuICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gaTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoeSA+IG1heFkpIHtcbiAgICAgICAgICAgICAgICBtYXhZID0geTtcbiAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhdmdYID0gKGNvdW50WCAqIGF2Z1ggKyBwb2ludC54KSAvICsrY291bnRYO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbGFzdEluZGV4ID0gaSAtIDE7XG4gICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWYobWluSW5kZXgpICYmICFpc051bGxPclVuZGVmKG1heEluZGV4KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGludGVybWVkaWF0ZUluZGV4MSA9IE1hdGgubWluKG1pbkluZGV4LCBtYXhJbmRleCk7XG4gICAgICAgICAgICAgICAgY29uc3QgaW50ZXJtZWRpYXRlSW5kZXgyID0gTWF0aC5tYXgobWluSW5kZXgsIG1heEluZGV4KTtcbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJtZWRpYXRlSW5kZXgxICE9PSBzdGFydEluZGV4ICYmIGludGVybWVkaWF0ZUluZGV4MSAhPT0gbGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGRlY2ltYXRlZC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmRhdGFbaW50ZXJtZWRpYXRlSW5kZXgxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IGF2Z1hcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpbnRlcm1lZGlhdGVJbmRleDIgIT09IHN0YXJ0SW5kZXggJiYgaW50ZXJtZWRpYXRlSW5kZXgyICE9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVjaW1hdGVkLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uZGF0YVtpbnRlcm1lZGlhdGVJbmRleDJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgeDogYXZnWFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSA+IDAgJiYgbGFzdEluZGV4ICE9PSBzdGFydEluZGV4KSB7XG4gICAgICAgICAgICAgICAgZGVjaW1hdGVkLnB1c2goZGF0YVtsYXN0SW5kZXhdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlY2ltYXRlZC5wdXNoKHBvaW50KTtcbiAgICAgICAgICAgIHByZXZYID0gdHJ1bmNYO1xuICAgICAgICAgICAgY291bnRYID0gMDtcbiAgICAgICAgICAgIG1pblkgPSBtYXhZID0geTtcbiAgICAgICAgICAgIG1pbkluZGV4ID0gbWF4SW5kZXggPSBzdGFydEluZGV4ID0gaTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVjaW1hdGVkO1xufVxuZnVuY3Rpb24gY2xlYW5EZWNpbWF0ZWREYXRhc2V0KGRhdGFzZXQpIHtcbiAgICBpZiAoZGF0YXNldC5fZGVjaW1hdGVkKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBkYXRhc2V0Ll9kYXRhO1xuICAgICAgICBkZWxldGUgZGF0YXNldC5fZGVjaW1hdGVkO1xuICAgICAgICBkZWxldGUgZGF0YXNldC5fZGF0YTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRhdGFzZXQsICdkYXRhJywge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6IGRhdGFcbiAgICAgICAgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gY2xlYW5EZWNpbWF0ZWREYXRhKGNoYXJ0KSB7XG4gICAgY2hhcnQuZGF0YS5kYXRhc2V0cy5mb3JFYWNoKChkYXRhc2V0KT0+e1xuICAgICAgICBjbGVhbkRlY2ltYXRlZERhdGFzZXQoZGF0YXNldCk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBnZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzU2ltcGxpZmllZChtZXRhLCBwb2ludHMpIHtcbiAgICBjb25zdCBwb2ludENvdW50ID0gcG9pbnRzLmxlbmd0aDtcbiAgICBsZXQgc3RhcnQgPSAwO1xuICAgIGxldCBjb3VudDtcbiAgICBjb25zdCB7IGlTY2FsZSAgfSA9IG1ldGE7XG4gICAgY29uc3QgeyBtaW4gLCBtYXggLCBtaW5EZWZpbmVkICwgbWF4RGVmaW5lZCAgfSA9IGlTY2FsZS5nZXRVc2VyQm91bmRzKCk7XG4gICAgaWYgKG1pbkRlZmluZWQpIHtcbiAgICAgICAgc3RhcnQgPSBfbGltaXRWYWx1ZShfbG9va3VwQnlLZXkocG9pbnRzLCBpU2NhbGUuYXhpcywgbWluKS5sbywgMCwgcG9pbnRDb3VudCAtIDEpO1xuICAgIH1cbiAgICBpZiAobWF4RGVmaW5lZCkge1xuICAgICAgICBjb3VudCA9IF9saW1pdFZhbHVlKF9sb29rdXBCeUtleShwb2ludHMsIGlTY2FsZS5heGlzLCBtYXgpLmhpICsgMSwgc3RhcnQsIHBvaW50Q291bnQpIC0gc3RhcnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY291bnQgPSBwb2ludENvdW50IC0gc3RhcnQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0LFxuICAgICAgICBjb3VudFxuICAgIH07XG59XG52YXIgcGx1Z2luX2RlY2ltYXRpb24gPSB7XG4gICAgaWQ6ICdkZWNpbWF0aW9uJyxcbiAgICBkZWZhdWx0czoge1xuICAgICAgICBhbGdvcml0aG06ICdtaW4tbWF4JyxcbiAgICAgICAgZW5hYmxlZDogZmFsc2VcbiAgICB9LFxuICAgIGJlZm9yZUVsZW1lbnRzVXBkYXRlOiAoY2hhcnQsIGFyZ3MsIG9wdGlvbnMpPT57XG4gICAgICAgIGlmICghb3B0aW9ucy5lbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhbkRlY2ltYXRlZERhdGEoY2hhcnQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGF2YWlsYWJsZVdpZHRoID0gY2hhcnQud2lkdGg7XG4gICAgICAgIGNoYXJ0LmRhdGEuZGF0YXNldHMuZm9yRWFjaCgoZGF0YXNldCwgZGF0YXNldEluZGV4KT0+e1xuICAgICAgICAgICAgY29uc3QgeyBfZGF0YSAsIGluZGV4QXhpcyAgfSA9IGRhdGFzZXQ7XG4gICAgICAgICAgICBjb25zdCBtZXRhID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoZGF0YXNldEluZGV4KTtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBfZGF0YSB8fCBkYXRhc2V0LmRhdGE7XG4gICAgICAgICAgICBpZiAocmVzb2x2ZShbXG4gICAgICAgICAgICAgICAgaW5kZXhBeGlzLFxuICAgICAgICAgICAgICAgIGNoYXJ0Lm9wdGlvbnMuaW5kZXhBeGlzXG4gICAgICAgICAgICBdKSA9PT0gJ3knKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtZXRhLmNvbnRyb2xsZXIuc3VwcG9ydHNEZWNpbWF0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgeEF4aXMgPSBjaGFydC5zY2FsZXNbbWV0YS54QXhpc0lEXTtcbiAgICAgICAgICAgIGlmICh4QXhpcy50eXBlICE9PSAnbGluZWFyJyAmJiB4QXhpcy50eXBlICE9PSAndGltZScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2hhcnQub3B0aW9ucy5wYXJzaW5nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHsgc3RhcnQgLCBjb3VudCAgfSA9IGdldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHNTaW1wbGlmaWVkKG1ldGEsIGRhdGEpO1xuICAgICAgICAgICAgY29uc3QgdGhyZXNob2xkID0gb3B0aW9ucy50aHJlc2hvbGQgfHwgNCAqIGF2YWlsYWJsZVdpZHRoO1xuICAgICAgICAgICAgaWYgKGNvdW50IDw9IHRocmVzaG9sZCkge1xuICAgICAgICAgICAgICAgIGNsZWFuRGVjaW1hdGVkRGF0YXNldChkYXRhc2V0KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZihfZGF0YSkpIHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0Ll9kYXRhID0gZGF0YTtcbiAgICAgICAgICAgICAgICBkZWxldGUgZGF0YXNldC5kYXRhO1xuICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYXRhc2V0LCAnZGF0YScsIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RlY2ltYXRlZDtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRhID0gZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGRlY2ltYXRlZDtcbiAgICAgICAgICAgIHN3aXRjaChvcHRpb25zLmFsZ29yaXRobSl7XG4gICAgICAgICAgICAgICAgY2FzZSAnbHR0Yic6XG4gICAgICAgICAgICAgICAgICAgIGRlY2ltYXRlZCA9IGx0dGJEZWNpbWF0aW9uKGRhdGEsIHN0YXJ0LCBjb3VudCwgYXZhaWxhYmxlV2lkdGgsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdtaW4tbWF4JzpcbiAgICAgICAgICAgICAgICAgICAgZGVjaW1hdGVkID0gbWluTWF4RGVjaW1hdGlvbihkYXRhLCBzdGFydCwgY291bnQsIGF2YWlsYWJsZVdpZHRoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkZWNpbWF0aW9uIGFsZ29yaXRobSAnJHtvcHRpb25zLmFsZ29yaXRobX0nYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkYXRhc2V0Ll9kZWNpbWF0ZWQgPSBkZWNpbWF0ZWQ7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgZGVzdHJveSAoY2hhcnQpIHtcbiAgICAgICAgY2xlYW5EZWNpbWF0ZWREYXRhKGNoYXJ0KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBfc2VnbWVudHMobGluZSwgdGFyZ2V0LCBwcm9wZXJ0eSkge1xuICAgIGNvbnN0IHNlZ21lbnRzID0gbGluZS5zZWdtZW50cztcbiAgICBjb25zdCBwb2ludHMgPSBsaW5lLnBvaW50cztcbiAgICBjb25zdCB0cG9pbnRzID0gdGFyZ2V0LnBvaW50cztcbiAgICBjb25zdCBwYXJ0cyA9IFtdO1xuICAgIGZvciAoY29uc3Qgc2VnbWVudCBvZiBzZWdtZW50cyl7XG4gICAgICAgIGxldCB7IHN0YXJ0ICwgZW5kICB9ID0gc2VnbWVudDtcbiAgICAgICAgZW5kID0gX2ZpbmRTZWdtZW50RW5kKHN0YXJ0LCBlbmQsIHBvaW50cyk7XG4gICAgICAgIGNvbnN0IGJvdW5kcyA9IF9nZXRCb3VuZHMocHJvcGVydHksIHBvaW50c1tzdGFydF0sIHBvaW50c1tlbmRdLCBzZWdtZW50Lmxvb3ApO1xuICAgICAgICBpZiAoIXRhcmdldC5zZWdtZW50cykge1xuICAgICAgICAgICAgcGFydHMucHVzaCh7XG4gICAgICAgICAgICAgICAgc291cmNlOiBzZWdtZW50LFxuICAgICAgICAgICAgICAgIHRhcmdldDogYm91bmRzLFxuICAgICAgICAgICAgICAgIHN0YXJ0OiBwb2ludHNbc3RhcnRdLFxuICAgICAgICAgICAgICAgIGVuZDogcG9pbnRzW2VuZF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGFyZ2V0U2VnbWVudHMgPSBfYm91bmRTZWdtZW50cyh0YXJnZXQsIGJvdW5kcyk7XG4gICAgICAgIGZvciAoY29uc3QgdGd0IG9mIHRhcmdldFNlZ21lbnRzKXtcbiAgICAgICAgICAgIGNvbnN0IHN1YkJvdW5kcyA9IF9nZXRCb3VuZHMocHJvcGVydHksIHRwb2ludHNbdGd0LnN0YXJ0XSwgdHBvaW50c1t0Z3QuZW5kXSwgdGd0Lmxvb3ApO1xuICAgICAgICAgICAgY29uc3QgZmlsbFNvdXJjZXMgPSBfYm91bmRTZWdtZW50KHNlZ21lbnQsIHBvaW50cywgc3ViQm91bmRzKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZmlsbFNvdXJjZSBvZiBmaWxsU291cmNlcyl7XG4gICAgICAgICAgICAgICAgcGFydHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogZmlsbFNvdXJjZSxcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiB0Z3QsXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBbcHJvcGVydHldOiBfZ2V0RWRnZShib3VuZHMsIHN1YkJvdW5kcywgJ3N0YXJ0JywgTWF0aC5tYXgpXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGVuZDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgW3Byb3BlcnR5XTogX2dldEVkZ2UoYm91bmRzLCBzdWJCb3VuZHMsICdlbmQnLCBNYXRoLm1pbilcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJ0cztcbn1cbmZ1bmN0aW9uIF9nZXRCb3VuZHMocHJvcGVydHksIGZpcnN0LCBsYXN0LCBsb29wKSB7XG4gICAgaWYgKGxvb3ApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgc3RhcnQgPSBmaXJzdFtwcm9wZXJ0eV07XG4gICAgbGV0IGVuZCA9IGxhc3RbcHJvcGVydHldO1xuICAgIGlmIChwcm9wZXJ0eSA9PT0gJ2FuZ2xlJykge1xuICAgICAgICBzdGFydCA9IF9ub3JtYWxpemVBbmdsZShzdGFydCk7XG4gICAgICAgIGVuZCA9IF9ub3JtYWxpemVBbmdsZShlbmQpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgc3RhcnQsXG4gICAgICAgIGVuZFxuICAgIH07XG59XG5mdW5jdGlvbiBfcG9pbnRzRnJvbVNlZ21lbnRzKGJvdW5kYXJ5LCBsaW5lKSB7XG4gICAgY29uc3QgeyB4ID1udWxsICwgeSA9bnVsbCAgfSA9IGJvdW5kYXJ5IHx8IHt9O1xuICAgIGNvbnN0IGxpbmVQb2ludHMgPSBsaW5lLnBvaW50cztcbiAgICBjb25zdCBwb2ludHMgPSBbXTtcbiAgICBsaW5lLnNlZ21lbnRzLmZvckVhY2goKHsgc3RhcnQgLCBlbmQgIH0pPT57XG4gICAgICAgIGVuZCA9IF9maW5kU2VnbWVudEVuZChzdGFydCwgZW5kLCBsaW5lUG9pbnRzKTtcbiAgICAgICAgY29uc3QgZmlyc3QgPSBsaW5lUG9pbnRzW3N0YXJ0XTtcbiAgICAgICAgY29uc3QgbGFzdCA9IGxpbmVQb2ludHNbZW5kXTtcbiAgICAgICAgaWYgKHkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHBvaW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICB4OiBmaXJzdC54LFxuICAgICAgICAgICAgICAgIHlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcG9pbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgIHg6IGxhc3QueCxcbiAgICAgICAgICAgICAgICB5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmICh4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBwb2ludHMucHVzaCh7XG4gICAgICAgICAgICAgICAgeCxcbiAgICAgICAgICAgICAgICB5OiBmaXJzdC55XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBvaW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICB4LFxuICAgICAgICAgICAgICAgIHk6IGxhc3QueVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcG9pbnRzO1xufVxuZnVuY3Rpb24gX2ZpbmRTZWdtZW50RW5kKHN0YXJ0LCBlbmQsIHBvaW50cykge1xuICAgIGZvcig7IGVuZCA+IHN0YXJ0OyBlbmQtLSl7XG4gICAgICAgIGNvbnN0IHBvaW50ID0gcG9pbnRzW2VuZF07XG4gICAgICAgIGlmICghaXNOYU4ocG9pbnQueCkgJiYgIWlzTmFOKHBvaW50LnkpKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZW5kO1xufVxuZnVuY3Rpb24gX2dldEVkZ2UoYSwgYiwgcHJvcCwgZm4pIHtcbiAgICBpZiAoYSAmJiBiKSB7XG4gICAgICAgIHJldHVybiBmbihhW3Byb3BdLCBiW3Byb3BdKTtcbiAgICB9XG4gICAgcmV0dXJuIGEgPyBhW3Byb3BdIDogYiA/IGJbcHJvcF0gOiAwO1xufVxuXG5mdW5jdGlvbiBfY3JlYXRlQm91bmRhcnlMaW5lKGJvdW5kYXJ5LCBsaW5lKSB7XG4gICAgbGV0IHBvaW50cyA9IFtdO1xuICAgIGxldCBfbG9vcCA9IGZhbHNlO1xuICAgIGlmIChpc0FycmF5KGJvdW5kYXJ5KSkge1xuICAgICAgICBfbG9vcCA9IHRydWU7XG4gICAgICAgIHBvaW50cyA9IGJvdW5kYXJ5O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBvaW50cyA9IF9wb2ludHNGcm9tU2VnbWVudHMoYm91bmRhcnksIGxpbmUpO1xuICAgIH1cbiAgICByZXR1cm4gcG9pbnRzLmxlbmd0aCA/IG5ldyBMaW5lRWxlbWVudCh7XG4gICAgICAgIHBvaW50cyxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgdGVuc2lvbjogMFxuICAgICAgICB9LFxuICAgICAgICBfbG9vcCxcbiAgICAgICAgX2Z1bGxMb29wOiBfbG9vcFxuICAgIH0pIDogbnVsbDtcbn1cbmZ1bmN0aW9uIF9zaG91bGRBcHBseUZpbGwoc291cmNlKSB7XG4gICAgcmV0dXJuIHNvdXJjZSAmJiBzb3VyY2UuZmlsbCAhPT0gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIF9yZXNvbHZlVGFyZ2V0KHNvdXJjZXMsIGluZGV4LCBwcm9wYWdhdGUpIHtcbiAgICBjb25zdCBzb3VyY2UgPSBzb3VyY2VzW2luZGV4XTtcbiAgICBsZXQgZmlsbCA9IHNvdXJjZS5maWxsO1xuICAgIGNvbnN0IHZpc2l0ZWQgPSBbXG4gICAgICAgIGluZGV4XG4gICAgXTtcbiAgICBsZXQgdGFyZ2V0O1xuICAgIGlmICghcHJvcGFnYXRlKSB7XG4gICAgICAgIHJldHVybiBmaWxsO1xuICAgIH1cbiAgICB3aGlsZShmaWxsICE9PSBmYWxzZSAmJiB2aXNpdGVkLmluZGV4T2YoZmlsbCkgPT09IC0xKXtcbiAgICAgICAgaWYgKCFpc051bWJlckZpbml0ZShmaWxsKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZpbGw7XG4gICAgICAgIH1cbiAgICAgICAgdGFyZ2V0ID0gc291cmNlc1tmaWxsXTtcbiAgICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGFyZ2V0LnZpc2libGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmaWxsO1xuICAgICAgICB9XG4gICAgICAgIHZpc2l0ZWQucHVzaChmaWxsKTtcbiAgICAgICAgZmlsbCA9IHRhcmdldC5maWxsO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG4gZnVuY3Rpb24gX2RlY29kZUZpbGwobGluZSwgaW5kZXgsIGNvdW50KSB7XG4gICAgIGNvbnN0IGZpbGwgPSBwYXJzZUZpbGxPcHRpb24obGluZSk7XG4gICAgaWYgKGlzT2JqZWN0KGZpbGwpKSB7XG4gICAgICAgIHJldHVybiBpc05hTihmaWxsLnZhbHVlKSA/IGZhbHNlIDogZmlsbDtcbiAgICB9XG4gICAgbGV0IHRhcmdldCA9IHBhcnNlRmxvYXQoZmlsbCk7XG4gICAgaWYgKGlzTnVtYmVyRmluaXRlKHRhcmdldCkgJiYgTWF0aC5mbG9vcih0YXJnZXQpID09PSB0YXJnZXQpIHtcbiAgICAgICAgcmV0dXJuIGRlY29kZVRhcmdldEluZGV4KGZpbGxbMF0sIGluZGV4LCB0YXJnZXQsIGNvdW50KTtcbiAgICB9XG4gICAgcmV0dXJuIFtcbiAgICAgICAgJ29yaWdpbicsXG4gICAgICAgICdzdGFydCcsXG4gICAgICAgICdlbmQnLFxuICAgICAgICAnc3RhY2snLFxuICAgICAgICAnc2hhcGUnXG4gICAgXS5pbmRleE9mKGZpbGwpID49IDAgJiYgZmlsbDtcbn1cbmZ1bmN0aW9uIGRlY29kZVRhcmdldEluZGV4KGZpcnN0Q2gsIGluZGV4LCB0YXJnZXQsIGNvdW50KSB7XG4gICAgaWYgKGZpcnN0Q2ggPT09ICctJyB8fCBmaXJzdENoID09PSAnKycpIHtcbiAgICAgICAgdGFyZ2V0ID0gaW5kZXggKyB0YXJnZXQ7XG4gICAgfVxuICAgIGlmICh0YXJnZXQgPT09IGluZGV4IHx8IHRhcmdldCA8IDAgfHwgdGFyZ2V0ID49IGNvdW50KSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRhcmdldDtcbn1cbiBmdW5jdGlvbiBfZ2V0VGFyZ2V0UGl4ZWwoZmlsbCwgc2NhbGUpIHtcbiAgICBsZXQgcGl4ZWwgPSBudWxsO1xuICAgIGlmIChmaWxsID09PSAnc3RhcnQnKSB7XG4gICAgICAgIHBpeGVsID0gc2NhbGUuYm90dG9tO1xuICAgIH0gZWxzZSBpZiAoZmlsbCA9PT0gJ2VuZCcpIHtcbiAgICAgICAgcGl4ZWwgPSBzY2FsZS50b3A7XG4gICAgfSBlbHNlIGlmIChpc09iamVjdChmaWxsKSkge1xuICAgICAgICBwaXhlbCA9IHNjYWxlLmdldFBpeGVsRm9yVmFsdWUoZmlsbC52YWx1ZSk7XG4gICAgfSBlbHNlIGlmIChzY2FsZS5nZXRCYXNlUGl4ZWwpIHtcbiAgICAgICAgcGl4ZWwgPSBzY2FsZS5nZXRCYXNlUGl4ZWwoKTtcbiAgICB9XG4gICAgcmV0dXJuIHBpeGVsO1xufVxuIGZ1bmN0aW9uIF9nZXRUYXJnZXRWYWx1ZShmaWxsLCBzY2FsZSwgc3RhcnRWYWx1ZSkge1xuICAgIGxldCB2YWx1ZTtcbiAgICBpZiAoZmlsbCA9PT0gJ3N0YXJ0Jykge1xuICAgICAgICB2YWx1ZSA9IHN0YXJ0VmFsdWU7XG4gICAgfSBlbHNlIGlmIChmaWxsID09PSAnZW5kJykge1xuICAgICAgICB2YWx1ZSA9IHNjYWxlLm9wdGlvbnMucmV2ZXJzZSA/IHNjYWxlLm1pbiA6IHNjYWxlLm1heDtcbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGZpbGwpKSB7XG4gICAgICAgIHZhbHVlID0gZmlsbC52YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZSA9IHNjYWxlLmdldEJhc2VWYWx1ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59XG4gZnVuY3Rpb24gcGFyc2VGaWxsT3B0aW9uKGxpbmUpIHtcbiAgICBjb25zdCBvcHRpb25zID0gbGluZS5vcHRpb25zO1xuICAgIGNvbnN0IGZpbGxPcHRpb24gPSBvcHRpb25zLmZpbGw7XG4gICAgbGV0IGZpbGwgPSB2YWx1ZU9yRGVmYXVsdChmaWxsT3B0aW9uICYmIGZpbGxPcHRpb24udGFyZ2V0LCBmaWxsT3B0aW9uKTtcbiAgICBpZiAoZmlsbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGZpbGwgPSAhIW9wdGlvbnMuYmFja2dyb3VuZENvbG9yO1xuICAgIH1cbiAgICBpZiAoZmlsbCA9PT0gZmFsc2UgfHwgZmlsbCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChmaWxsID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiAnb3JpZ2luJztcbiAgICB9XG4gICAgcmV0dXJuIGZpbGw7XG59XG5cbmZ1bmN0aW9uIF9idWlsZFN0YWNrTGluZShzb3VyY2UpIHtcbiAgICBjb25zdCB7IHNjYWxlICwgaW5kZXggLCBsaW5lICB9ID0gc291cmNlO1xuICAgIGNvbnN0IHBvaW50cyA9IFtdO1xuICAgIGNvbnN0IHNlZ21lbnRzID0gbGluZS5zZWdtZW50cztcbiAgICBjb25zdCBzb3VyY2VQb2ludHMgPSBsaW5lLnBvaW50cztcbiAgICBjb25zdCBsaW5lc0JlbG93ID0gZ2V0TGluZXNCZWxvdyhzY2FsZSwgaW5kZXgpO1xuICAgIGxpbmVzQmVsb3cucHVzaChfY3JlYXRlQm91bmRhcnlMaW5lKHtcbiAgICAgICAgeDogbnVsbCxcbiAgICAgICAgeTogc2NhbGUuYm90dG9tXG4gICAgfSwgbGluZSkpO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGNvbnN0IHNlZ21lbnQgPSBzZWdtZW50c1tpXTtcbiAgICAgICAgZm9yKGxldCBqID0gc2VnbWVudC5zdGFydDsgaiA8PSBzZWdtZW50LmVuZDsgaisrKXtcbiAgICAgICAgICAgIGFkZFBvaW50c0JlbG93KHBvaW50cywgc291cmNlUG9pbnRzW2pdLCBsaW5lc0JlbG93KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3IExpbmVFbGVtZW50KHtcbiAgICAgICAgcG9pbnRzLFxuICAgICAgICBvcHRpb25zOiB7fVxuICAgIH0pO1xufVxuIGZ1bmN0aW9uIGdldExpbmVzQmVsb3coc2NhbGUsIGluZGV4KSB7XG4gICAgY29uc3QgYmVsb3cgPSBbXTtcbiAgICBjb25zdCBtZXRhcyA9IHNjYWxlLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKCdsaW5lJyk7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IG1ldGFzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgY29uc3QgbWV0YSA9IG1ldGFzW2ldO1xuICAgICAgICBpZiAobWV0YS5pbmRleCA9PT0gaW5kZXgpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbWV0YS5oaWRkZW4pIHtcbiAgICAgICAgICAgIGJlbG93LnVuc2hpZnQobWV0YS5kYXRhc2V0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmVsb3c7XG59XG4gZnVuY3Rpb24gYWRkUG9pbnRzQmVsb3cocG9pbnRzLCBzb3VyY2VQb2ludCwgbGluZXNCZWxvdykge1xuICAgIGNvbnN0IHBvc3Rwb25lZCA9IFtdO1xuICAgIGZvcihsZXQgaiA9IDA7IGogPCBsaW5lc0JlbG93Lmxlbmd0aDsgaisrKXtcbiAgICAgICAgY29uc3QgbGluZSA9IGxpbmVzQmVsb3dbal07XG4gICAgICAgIGNvbnN0IHsgZmlyc3QgLCBsYXN0ICwgcG9pbnQgIH0gPSBmaW5kUG9pbnQobGluZSwgc291cmNlUG9pbnQsICd4Jyk7XG4gICAgICAgIGlmICghcG9pbnQgfHwgZmlyc3QgJiYgbGFzdCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgICBwb3N0cG9uZWQudW5zaGlmdChwb2ludCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwb2ludHMucHVzaChwb2ludCk7XG4gICAgICAgICAgICBpZiAoIWxhc3QpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBwb2ludHMucHVzaCguLi5wb3N0cG9uZWQpO1xufVxuIGZ1bmN0aW9uIGZpbmRQb2ludChsaW5lLCBzb3VyY2VQb2ludCwgcHJvcGVydHkpIHtcbiAgICBjb25zdCBwb2ludCA9IGxpbmUuaW50ZXJwb2xhdGUoc291cmNlUG9pbnQsIHByb3BlcnR5KTtcbiAgICBpZiAoIXBvaW50KSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gICAgY29uc3QgcG9pbnRWYWx1ZSA9IHBvaW50W3Byb3BlcnR5XTtcbiAgICBjb25zdCBzZWdtZW50cyA9IGxpbmUuc2VnbWVudHM7XG4gICAgY29uc3QgbGluZVBvaW50cyA9IGxpbmUucG9pbnRzO1xuICAgIGxldCBmaXJzdCA9IGZhbHNlO1xuICAgIGxldCBsYXN0ID0gZmFsc2U7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgY29uc3Qgc2VnbWVudCA9IHNlZ21lbnRzW2ldO1xuICAgICAgICBjb25zdCBmaXJzdFZhbHVlID0gbGluZVBvaW50c1tzZWdtZW50LnN0YXJ0XVtwcm9wZXJ0eV07XG4gICAgICAgIGNvbnN0IGxhc3RWYWx1ZSA9IGxpbmVQb2ludHNbc2VnbWVudC5lbmRdW3Byb3BlcnR5XTtcbiAgICAgICAgaWYgKF9pc0JldHdlZW4ocG9pbnRWYWx1ZSwgZmlyc3RWYWx1ZSwgbGFzdFZhbHVlKSkge1xuICAgICAgICAgICAgZmlyc3QgPSBwb2ludFZhbHVlID09PSBmaXJzdFZhbHVlO1xuICAgICAgICAgICAgbGFzdCA9IHBvaW50VmFsdWUgPT09IGxhc3RWYWx1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGZpcnN0LFxuICAgICAgICBsYXN0LFxuICAgICAgICBwb2ludFxuICAgIH07XG59XG5cbmNsYXNzIHNpbXBsZUFyYyB7XG4gICAgY29uc3RydWN0b3Iob3B0cyl7XG4gICAgICAgIHRoaXMueCA9IG9wdHMueDtcbiAgICAgICAgdGhpcy55ID0gb3B0cy55O1xuICAgICAgICB0aGlzLnJhZGl1cyA9IG9wdHMucmFkaXVzO1xuICAgIH1cbiAgICBwYXRoU2VnbWVudChjdHgsIGJvdW5kcywgb3B0cykge1xuICAgICAgICBjb25zdCB7IHggLCB5ICwgcmFkaXVzICB9ID0gdGhpcztcbiAgICAgICAgYm91bmRzID0gYm91bmRzIHx8IHtcbiAgICAgICAgICAgIHN0YXJ0OiAwLFxuICAgICAgICAgICAgZW5kOiBUQVVcbiAgICAgICAgfTtcbiAgICAgICAgY3R4LmFyYyh4LCB5LCByYWRpdXMsIGJvdW5kcy5lbmQsIGJvdW5kcy5zdGFydCwgdHJ1ZSk7XG4gICAgICAgIHJldHVybiAhb3B0cy5ib3VuZHM7XG4gICAgfVxuICAgIGludGVycG9sYXRlKHBvaW50KSB7XG4gICAgICAgIGNvbnN0IHsgeCAsIHkgLCByYWRpdXMgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBhbmdsZSA9IHBvaW50LmFuZ2xlO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogeCArIE1hdGguY29zKGFuZ2xlKSAqIHJhZGl1cyxcbiAgICAgICAgICAgIHk6IHkgKyBNYXRoLnNpbihhbmdsZSkgKiByYWRpdXMsXG4gICAgICAgICAgICBhbmdsZVxuICAgICAgICB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gX2dldFRhcmdldChzb3VyY2UpIHtcbiAgICBjb25zdCB7IGNoYXJ0ICwgZmlsbCAsIGxpbmUgIH0gPSBzb3VyY2U7XG4gICAgaWYgKGlzTnVtYmVyRmluaXRlKGZpbGwpKSB7XG4gICAgICAgIHJldHVybiBnZXRMaW5lQnlJbmRleChjaGFydCwgZmlsbCk7XG4gICAgfVxuICAgIGlmIChmaWxsID09PSAnc3RhY2snKSB7XG4gICAgICAgIHJldHVybiBfYnVpbGRTdGFja0xpbmUoc291cmNlKTtcbiAgICB9XG4gICAgaWYgKGZpbGwgPT09ICdzaGFwZScpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IGJvdW5kYXJ5ID0gY29tcHV0ZUJvdW5kYXJ5KHNvdXJjZSk7XG4gICAgaWYgKGJvdW5kYXJ5IGluc3RhbmNlb2Ygc2ltcGxlQXJjKSB7XG4gICAgICAgIHJldHVybiBib3VuZGFyeTtcbiAgICB9XG4gICAgcmV0dXJuIF9jcmVhdGVCb3VuZGFyeUxpbmUoYm91bmRhcnksIGxpbmUpO1xufVxuIGZ1bmN0aW9uIGdldExpbmVCeUluZGV4KGNoYXJ0LCBpbmRleCkge1xuICAgIGNvbnN0IG1ldGEgPSBjaGFydC5nZXREYXRhc2V0TWV0YShpbmRleCk7XG4gICAgY29uc3QgdmlzaWJsZSA9IG1ldGEgJiYgY2hhcnQuaXNEYXRhc2V0VmlzaWJsZShpbmRleCk7XG4gICAgcmV0dXJuIHZpc2libGUgPyBtZXRhLmRhdGFzZXQgOiBudWxsO1xufVxuZnVuY3Rpb24gY29tcHV0ZUJvdW5kYXJ5KHNvdXJjZSkge1xuICAgIGNvbnN0IHNjYWxlID0gc291cmNlLnNjYWxlIHx8IHt9O1xuICAgIGlmIChzY2FsZS5nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGNvbXB1dGVDaXJjdWxhckJvdW5kYXJ5KHNvdXJjZSk7XG4gICAgfVxuICAgIHJldHVybiBjb21wdXRlTGluZWFyQm91bmRhcnkoc291cmNlKTtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVMaW5lYXJCb3VuZGFyeShzb3VyY2UpIHtcbiAgICBjb25zdCB7IHNjYWxlID17fSAsIGZpbGwgIH0gPSBzb3VyY2U7XG4gICAgY29uc3QgcGl4ZWwgPSBfZ2V0VGFyZ2V0UGl4ZWwoZmlsbCwgc2NhbGUpO1xuICAgIGlmIChpc051bWJlckZpbml0ZShwaXhlbCkpIHtcbiAgICAgICAgY29uc3QgaG9yaXpvbnRhbCA9IHNjYWxlLmlzSG9yaXpvbnRhbCgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogaG9yaXpvbnRhbCA/IHBpeGVsIDogbnVsbCxcbiAgICAgICAgICAgIHk6IGhvcml6b250YWwgPyBudWxsIDogcGl4ZWxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBjb21wdXRlQ2lyY3VsYXJCb3VuZGFyeShzb3VyY2UpIHtcbiAgICBjb25zdCB7IHNjYWxlICwgZmlsbCAgfSA9IHNvdXJjZTtcbiAgICBjb25zdCBvcHRpb25zID0gc2NhbGUub3B0aW9ucztcbiAgICBjb25zdCBsZW5ndGggPSBzY2FsZS5nZXRMYWJlbHMoKS5sZW5ndGg7XG4gICAgY29uc3Qgc3RhcnQgPSBvcHRpb25zLnJldmVyc2UgPyBzY2FsZS5tYXggOiBzY2FsZS5taW47XG4gICAgY29uc3QgdmFsdWUgPSBfZ2V0VGFyZ2V0VmFsdWUoZmlsbCwgc2NhbGUsIHN0YXJ0KTtcbiAgICBjb25zdCB0YXJnZXQgPSBbXTtcbiAgICBpZiAob3B0aW9ucy5ncmlkLmNpcmN1bGFyKSB7XG4gICAgICAgIGNvbnN0IGNlbnRlciA9IHNjYWxlLmdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZSgwLCBzdGFydCk7XG4gICAgICAgIHJldHVybiBuZXcgc2ltcGxlQXJjKHtcbiAgICAgICAgICAgIHg6IGNlbnRlci54LFxuICAgICAgICAgICAgeTogY2VudGVyLnksXG4gICAgICAgICAgICByYWRpdXM6IHNjYWxlLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKHZhbHVlKVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKXtcbiAgICAgICAgdGFyZ2V0LnB1c2goc2NhbGUuZ2V0UG9pbnRQb3NpdGlvbkZvclZhbHVlKGksIHZhbHVlKSk7XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQ7XG59XG5cbmZ1bmN0aW9uIF9kcmF3ZmlsbChjdHgsIHNvdXJjZSwgYXJlYSkge1xuICAgIGNvbnN0IHRhcmdldCA9IF9nZXRUYXJnZXQoc291cmNlKTtcbiAgICBjb25zdCB7IGNoYXJ0ICwgaW5kZXggLCBsaW5lICwgc2NhbGUgLCBheGlzICB9ID0gc291cmNlO1xuICAgIGNvbnN0IGxpbmVPcHRzID0gbGluZS5vcHRpb25zO1xuICAgIGNvbnN0IGZpbGxPcHRpb24gPSBsaW5lT3B0cy5maWxsO1xuICAgIGNvbnN0IGNvbG9yID0gbGluZU9wdHMuYmFja2dyb3VuZENvbG9yO1xuICAgIGNvbnN0IHsgYWJvdmUgPWNvbG9yICwgYmVsb3cgPWNvbG9yICB9ID0gZmlsbE9wdGlvbiB8fCB7fTtcbiAgICBjb25zdCBtZXRhID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoaW5kZXgpO1xuICAgIGNvbnN0IGNsaXAgPSBnZXREYXRhc2V0Q2xpcEFyZWEoY2hhcnQsIG1ldGEpO1xuICAgIGlmICh0YXJnZXQgJiYgbGluZS5wb2ludHMubGVuZ3RoKSB7XG4gICAgICAgIGNsaXBBcmVhKGN0eCwgYXJlYSk7XG4gICAgICAgIGRvRmlsbChjdHgsIHtcbiAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgICBhYm92ZSxcbiAgICAgICAgICAgIGJlbG93LFxuICAgICAgICAgICAgYXJlYSxcbiAgICAgICAgICAgIHNjYWxlLFxuICAgICAgICAgICAgYXhpcyxcbiAgICAgICAgICAgIGNsaXBcbiAgICAgICAgfSk7XG4gICAgICAgIHVuY2xpcEFyZWEoY3R4KTtcbiAgICB9XG59XG5mdW5jdGlvbiBkb0ZpbGwoY3R4LCBjZmcpIHtcbiAgICBjb25zdCB7IGxpbmUgLCB0YXJnZXQgLCBhYm92ZSAsIGJlbG93ICwgYXJlYSAsIHNjYWxlICwgY2xpcCAgfSA9IGNmZztcbiAgICBjb25zdCBwcm9wZXJ0eSA9IGxpbmUuX2xvb3AgPyAnYW5nbGUnIDogY2ZnLmF4aXM7XG4gICAgY3R4LnNhdmUoKTtcbiAgICBsZXQgZmlsbENvbG9yID0gYmVsb3c7XG4gICAgaWYgKGJlbG93ICE9PSBhYm92ZSkge1xuICAgICAgICBpZiAocHJvcGVydHkgPT09ICd4Jykge1xuICAgICAgICAgICAgY2xpcFZlcnRpY2FsKGN0eCwgdGFyZ2V0LCBhcmVhLnRvcCk7XG4gICAgICAgICAgICBmaWxsKGN0eCwge1xuICAgICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgICAgIGNvbG9yOiBhYm92ZSxcbiAgICAgICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgICAgICBjbGlwXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgY2xpcFZlcnRpY2FsKGN0eCwgdGFyZ2V0LCBhcmVhLmJvdHRvbSk7XG4gICAgICAgIH0gZWxzZSBpZiAocHJvcGVydHkgPT09ICd5Jykge1xuICAgICAgICAgICAgY2xpcEhvcml6b250YWwoY3R4LCB0YXJnZXQsIGFyZWEubGVmdCk7XG4gICAgICAgICAgICBmaWxsKGN0eCwge1xuICAgICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgICAgIGNvbG9yOiBiZWxvdyxcbiAgICAgICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgICAgICBjbGlwXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgY2xpcEhvcml6b250YWwoY3R4LCB0YXJnZXQsIGFyZWEucmlnaHQpO1xuICAgICAgICAgICAgZmlsbENvbG9yID0gYWJvdmU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZmlsbChjdHgsIHtcbiAgICAgICAgbGluZSxcbiAgICAgICAgdGFyZ2V0LFxuICAgICAgICBjb2xvcjogZmlsbENvbG9yLFxuICAgICAgICBzY2FsZSxcbiAgICAgICAgcHJvcGVydHksXG4gICAgICAgIGNsaXBcbiAgICB9KTtcbiAgICBjdHgucmVzdG9yZSgpO1xufVxuZnVuY3Rpb24gY2xpcFZlcnRpY2FsKGN0eCwgdGFyZ2V0LCBjbGlwWSkge1xuICAgIGNvbnN0IHsgc2VnbWVudHMgLCBwb2ludHMgIH0gPSB0YXJnZXQ7XG4gICAgbGV0IGZpcnN0ID0gdHJ1ZTtcbiAgICBsZXQgbGluZUxvb3AgPSBmYWxzZTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgZm9yIChjb25zdCBzZWdtZW50IG9mIHNlZ21lbnRzKXtcbiAgICAgICAgY29uc3QgeyBzdGFydCAsIGVuZCAgfSA9IHNlZ21lbnQ7XG4gICAgICAgIGNvbnN0IGZpcnN0UG9pbnQgPSBwb2ludHNbc3RhcnRdO1xuICAgICAgICBjb25zdCBsYXN0UG9pbnQgPSBwb2ludHNbX2ZpbmRTZWdtZW50RW5kKHN0YXJ0LCBlbmQsIHBvaW50cyldO1xuICAgICAgICBpZiAoZmlyc3QpIHtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oZmlyc3RQb2ludC54LCBmaXJzdFBvaW50LnkpO1xuICAgICAgICAgICAgZmlyc3QgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oZmlyc3RQb2ludC54LCBjbGlwWSk7XG4gICAgICAgICAgICBjdHgubGluZVRvKGZpcnN0UG9pbnQueCwgZmlyc3RQb2ludC55KTtcbiAgICAgICAgfVxuICAgICAgICBsaW5lTG9vcCA9ICEhdGFyZ2V0LnBhdGhTZWdtZW50KGN0eCwgc2VnbWVudCwge1xuICAgICAgICAgICAgbW92ZTogbGluZUxvb3BcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChsaW5lTG9vcCkge1xuICAgICAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhsYXN0UG9pbnQueCwgY2xpcFkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGN0eC5saW5lVG8odGFyZ2V0LmZpcnN0KCkueCwgY2xpcFkpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBjdHguY2xpcCgpO1xufVxuZnVuY3Rpb24gY2xpcEhvcml6b250YWwoY3R4LCB0YXJnZXQsIGNsaXBYKSB7XG4gICAgY29uc3QgeyBzZWdtZW50cyAsIHBvaW50cyAgfSA9IHRhcmdldDtcbiAgICBsZXQgZmlyc3QgPSB0cnVlO1xuICAgIGxldCBsaW5lTG9vcCA9IGZhbHNlO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBmb3IgKGNvbnN0IHNlZ21lbnQgb2Ygc2VnbWVudHMpe1xuICAgICAgICBjb25zdCB7IHN0YXJ0ICwgZW5kICB9ID0gc2VnbWVudDtcbiAgICAgICAgY29uc3QgZmlyc3RQb2ludCA9IHBvaW50c1tzdGFydF07XG4gICAgICAgIGNvbnN0IGxhc3RQb2ludCA9IHBvaW50c1tfZmluZFNlZ21lbnRFbmQoc3RhcnQsIGVuZCwgcG9pbnRzKV07XG4gICAgICAgIGlmIChmaXJzdCkge1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyhmaXJzdFBvaW50LngsIGZpcnN0UG9pbnQueSk7XG4gICAgICAgICAgICBmaXJzdCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhjbGlwWCwgZmlyc3RQb2ludC55KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oZmlyc3RQb2ludC54LCBmaXJzdFBvaW50LnkpO1xuICAgICAgICB9XG4gICAgICAgIGxpbmVMb29wID0gISF0YXJnZXQucGF0aFNlZ21lbnQoY3R4LCBzZWdtZW50LCB7XG4gICAgICAgICAgICBtb3ZlOiBsaW5lTG9vcFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGxpbmVMb29wKSB7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjdHgubGluZVRvKGNsaXBYLCBsYXN0UG9pbnQueSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY3R4LmxpbmVUbyhjbGlwWCwgdGFyZ2V0LmZpcnN0KCkueSk7XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgIGN0eC5jbGlwKCk7XG59XG5mdW5jdGlvbiBmaWxsKGN0eCwgY2ZnKSB7XG4gICAgY29uc3QgeyBsaW5lICwgdGFyZ2V0ICwgcHJvcGVydHkgLCBjb2xvciAsIHNjYWxlICwgY2xpcCAgfSA9IGNmZztcbiAgICBjb25zdCBzZWdtZW50cyA9IF9zZWdtZW50cyhsaW5lLCB0YXJnZXQsIHByb3BlcnR5KTtcbiAgICBmb3IgKGNvbnN0IHsgc291cmNlOiBzcmMgLCB0YXJnZXQ6IHRndCAsIHN0YXJ0ICwgZW5kICB9IG9mIHNlZ21lbnRzKXtcbiAgICAgICAgY29uc3QgeyBzdHlsZTogeyBiYWNrZ3JvdW5kQ29sb3IgPWNvbG9yICB9ID0ge30gIH0gPSBzcmM7XG4gICAgICAgIGNvbnN0IG5vdFNoYXBlID0gdGFyZ2V0ICE9PSB0cnVlO1xuICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gYmFja2dyb3VuZENvbG9yO1xuICAgICAgICBjbGlwQm91bmRzKGN0eCwgc2NhbGUsIGNsaXAsIG5vdFNoYXBlICYmIF9nZXRCb3VuZHMocHJvcGVydHksIHN0YXJ0LCBlbmQpKTtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjb25zdCBsaW5lTG9vcCA9ICEhbGluZS5wYXRoU2VnbWVudChjdHgsIHNyYyk7XG4gICAgICAgIGxldCBsb29wO1xuICAgICAgICBpZiAobm90U2hhcGUpIHtcbiAgICAgICAgICAgIGlmIChsaW5lTG9vcCkge1xuICAgICAgICAgICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaW50ZXJwb2xhdGVkTGluZVRvKGN0eCwgdGFyZ2V0LCBlbmQsIHByb3BlcnR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHRhcmdldExvb3AgPSAhIXRhcmdldC5wYXRoU2VnbWVudChjdHgsIHRndCwge1xuICAgICAgICAgICAgICAgIG1vdmU6IGxpbmVMb29wLFxuICAgICAgICAgICAgICAgIHJldmVyc2U6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgbG9vcCA9IGxpbmVMb29wICYmIHRhcmdldExvb3A7XG4gICAgICAgICAgICBpZiAoIWxvb3ApIHtcbiAgICAgICAgICAgICAgICBpbnRlcnBvbGF0ZWRMaW5lVG8oY3R4LCB0YXJnZXQsIHN0YXJ0LCBwcm9wZXJ0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICBjdHguZmlsbChsb29wID8gJ2V2ZW5vZGQnIDogJ25vbnplcm8nKTtcbiAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICB9XG59XG5mdW5jdGlvbiBjbGlwQm91bmRzKGN0eCwgc2NhbGUsIGNsaXAsIGJvdW5kcykge1xuICAgIGNvbnN0IGNoYXJ0QXJlYSA9IHNjYWxlLmNoYXJ0LmNoYXJ0QXJlYTtcbiAgICBjb25zdCB7IHByb3BlcnR5ICwgc3RhcnQgLCBlbmQgIH0gPSBib3VuZHMgfHwge307XG4gICAgaWYgKHByb3BlcnR5ID09PSAneCcgfHwgcHJvcGVydHkgPT09ICd5Jykge1xuICAgICAgICBsZXQgbGVmdCwgdG9wLCByaWdodCwgYm90dG9tO1xuICAgICAgICBpZiAocHJvcGVydHkgPT09ICd4Jykge1xuICAgICAgICAgICAgbGVmdCA9IHN0YXJ0O1xuICAgICAgICAgICAgdG9wID0gY2hhcnRBcmVhLnRvcDtcbiAgICAgICAgICAgIHJpZ2h0ID0gZW5kO1xuICAgICAgICAgICAgYm90dG9tID0gY2hhcnRBcmVhLmJvdHRvbTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxlZnQgPSBjaGFydEFyZWEubGVmdDtcbiAgICAgICAgICAgIHRvcCA9IHN0YXJ0O1xuICAgICAgICAgICAgcmlnaHQgPSBjaGFydEFyZWEucmlnaHQ7XG4gICAgICAgICAgICBib3R0b20gPSBlbmQ7XG4gICAgICAgIH1cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBpZiAoY2xpcCkge1xuICAgICAgICAgICAgbGVmdCA9IE1hdGgubWF4KGxlZnQsIGNsaXAubGVmdCk7XG4gICAgICAgICAgICByaWdodCA9IE1hdGgubWluKHJpZ2h0LCBjbGlwLnJpZ2h0KTtcbiAgICAgICAgICAgIHRvcCA9IE1hdGgubWF4KHRvcCwgY2xpcC50b3ApO1xuICAgICAgICAgICAgYm90dG9tID0gTWF0aC5taW4oYm90dG9tLCBjbGlwLmJvdHRvbSk7XG4gICAgICAgIH1cbiAgICAgICAgY3R4LnJlY3QobGVmdCwgdG9wLCByaWdodCAtIGxlZnQsIGJvdHRvbSAtIHRvcCk7XG4gICAgICAgIGN0eC5jbGlwKCk7XG4gICAgfVxufVxuZnVuY3Rpb24gaW50ZXJwb2xhdGVkTGluZVRvKGN0eCwgdGFyZ2V0LCBwb2ludCwgcHJvcGVydHkpIHtcbiAgICBjb25zdCBpbnRlcnBvbGF0ZWRQb2ludCA9IHRhcmdldC5pbnRlcnBvbGF0ZShwb2ludCwgcHJvcGVydHkpO1xuICAgIGlmIChpbnRlcnBvbGF0ZWRQb2ludCkge1xuICAgICAgICBjdHgubGluZVRvKGludGVycG9sYXRlZFBvaW50LngsIGludGVycG9sYXRlZFBvaW50LnkpO1xuICAgIH1cbn1cblxudmFyIGluZGV4ID0ge1xuICAgIGlkOiAnZmlsbGVyJyxcbiAgICBhZnRlckRhdGFzZXRzVXBkYXRlIChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgY291bnQgPSAoY2hhcnQuZGF0YS5kYXRhc2V0cyB8fCBbXSkubGVuZ3RoO1xuICAgICAgICBjb25zdCBzb3VyY2VzID0gW107XG4gICAgICAgIGxldCBtZXRhLCBpLCBsaW5lLCBzb3VyY2U7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyArK2kpe1xuICAgICAgICAgICAgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgbGluZSA9IG1ldGEuZGF0YXNldDtcbiAgICAgICAgICAgIHNvdXJjZSA9IG51bGw7XG4gICAgICAgICAgICBpZiAobGluZSAmJiBsaW5lLm9wdGlvbnMgJiYgbGluZSBpbnN0YW5jZW9mIExpbmVFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgc291cmNlID0ge1xuICAgICAgICAgICAgICAgICAgICB2aXNpYmxlOiBjaGFydC5pc0RhdGFzZXRWaXNpYmxlKGkpLFxuICAgICAgICAgICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogX2RlY29kZUZpbGwobGluZSwgaSwgY291bnQpLFxuICAgICAgICAgICAgICAgICAgICBjaGFydCxcbiAgICAgICAgICAgICAgICAgICAgYXhpczogbWV0YS5jb250cm9sbGVyLm9wdGlvbnMuaW5kZXhBeGlzLFxuICAgICAgICAgICAgICAgICAgICBzY2FsZTogbWV0YS52U2NhbGUsXG4gICAgICAgICAgICAgICAgICAgIGxpbmVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWV0YS4kZmlsbGVyID0gc291cmNlO1xuICAgICAgICAgICAgc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7ICsraSl7XG4gICAgICAgICAgICBzb3VyY2UgPSBzb3VyY2VzW2ldO1xuICAgICAgICAgICAgaWYgKCFzb3VyY2UgfHwgc291cmNlLmZpbGwgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzb3VyY2UuZmlsbCA9IF9yZXNvbHZlVGFyZ2V0KHNvdXJjZXMsIGksIG9wdGlvbnMucHJvcGFnYXRlKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgYmVmb3JlRHJhdyAoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGRyYXcgPSBvcHRpb25zLmRyYXdUaW1lID09PSAnYmVmb3JlRHJhdyc7XG4gICAgICAgIGNvbnN0IG1ldGFzZXRzID0gY2hhcnQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO1xuICAgICAgICBjb25zdCBhcmVhID0gY2hhcnQuY2hhcnRBcmVhO1xuICAgICAgICBmb3IobGV0IGkgPSBtZXRhc2V0cy5sZW5ndGggLSAxOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2UgPSBtZXRhc2V0c1tpXS4kZmlsbGVyO1xuICAgICAgICAgICAgaWYgKCFzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNvdXJjZS5saW5lLnVwZGF0ZUNvbnRyb2xQb2ludHMoYXJlYSwgc291cmNlLmF4aXMpO1xuICAgICAgICAgICAgaWYgKGRyYXcgJiYgc291cmNlLmZpbGwpIHtcbiAgICAgICAgICAgICAgICBfZHJhd2ZpbGwoY2hhcnQuY3R4LCBzb3VyY2UsIGFyZWEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICBiZWZvcmVEYXRhc2V0c0RyYXcgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucy5kcmF3VGltZSAhPT0gJ2JlZm9yZURhdGFzZXRzRHJhdycpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtZXRhc2V0cyA9IGNoYXJ0LmdldFNvcnRlZFZpc2libGVEYXRhc2V0TWV0YXMoKTtcbiAgICAgICAgZm9yKGxldCBpID0gbWV0YXNldHMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpe1xuICAgICAgICAgICAgY29uc3Qgc291cmNlID0gbWV0YXNldHNbaV0uJGZpbGxlcjtcbiAgICAgICAgICAgIGlmIChfc2hvdWxkQXBwbHlGaWxsKHNvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICBfZHJhd2ZpbGwoY2hhcnQuY3R4LCBzb3VyY2UsIGNoYXJ0LmNoYXJ0QXJlYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGJlZm9yZURhdGFzZXREcmF3IChjaGFydCwgYXJncywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBzb3VyY2UgPSBhcmdzLm1ldGEuJGZpbGxlcjtcbiAgICAgICAgaWYgKCFfc2hvdWxkQXBwbHlGaWxsKHNvdXJjZSkgfHwgb3B0aW9ucy5kcmF3VGltZSAhPT0gJ2JlZm9yZURhdGFzZXREcmF3Jykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIF9kcmF3ZmlsbChjaGFydC5jdHgsIHNvdXJjZSwgY2hhcnQuY2hhcnRBcmVhKTtcbiAgICB9LFxuICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIHByb3BhZ2F0ZTogdHJ1ZSxcbiAgICAgICAgZHJhd1RpbWU6ICdiZWZvcmVEYXRhc2V0RHJhdydcbiAgICB9XG59O1xuXG5jb25zdCBnZXRCb3hTaXplID0gKGxhYmVsT3B0cywgZm9udFNpemUpPT57XG4gICAgbGV0IHsgYm94SGVpZ2h0ID1mb250U2l6ZSAsIGJveFdpZHRoID1mb250U2l6ZSAgfSA9IGxhYmVsT3B0cztcbiAgICBpZiAobGFiZWxPcHRzLnVzZVBvaW50U3R5bGUpIHtcbiAgICAgICAgYm94SGVpZ2h0ID0gTWF0aC5taW4oYm94SGVpZ2h0LCBmb250U2l6ZSk7XG4gICAgICAgIGJveFdpZHRoID0gbGFiZWxPcHRzLnBvaW50U3R5bGVXaWR0aCB8fCBNYXRoLm1pbihib3hXaWR0aCwgZm9udFNpemUpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBib3hXaWR0aCxcbiAgICAgICAgYm94SGVpZ2h0LFxuICAgICAgICBpdGVtSGVpZ2h0OiBNYXRoLm1heChmb250U2l6ZSwgYm94SGVpZ2h0KVxuICAgIH07XG59O1xuY29uc3QgaXRlbXNFcXVhbCA9IChhLCBiKT0+YSAhPT0gbnVsbCAmJiBiICE9PSBudWxsICYmIGEuZGF0YXNldEluZGV4ID09PSBiLmRhdGFzZXRJbmRleCAmJiBhLmluZGV4ID09PSBiLmluZGV4O1xuY2xhc3MgTGVnZW5kIGV4dGVuZHMgRWxlbWVudCB7XG4gY29uc3RydWN0b3IoY29uZmlnKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5fYWRkZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5sZWdlbmRIaXRCb3hlcyA9IFtdO1xuIHRoaXMuX2hvdmVyZWRJdGVtID0gbnVsbDtcbiAgICAgICAgdGhpcy5kb3VnaG51dE1vZGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jaGFydCA9IGNvbmZpZy5jaGFydDtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gY29uZmlnLm9wdGlvbnM7XG4gICAgICAgIHRoaXMuY3R4ID0gY29uZmlnLmN0eDtcbiAgICAgICAgdGhpcy5sZWdlbmRJdGVtcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5jb2x1bW5TaXplcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5saW5lV2lkdGhzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm1heEhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5tYXhXaWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy50b3AgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuYm90dG9tID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmxlZnQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMucmlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLndpZHRoID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9tYXJnaW5zID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnBvc2l0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLndlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5mdWxsU2l6ZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdXBkYXRlKG1heFdpZHRoLCBtYXhIZWlnaHQsIG1hcmdpbnMpIHtcbiAgICAgICAgdGhpcy5tYXhXaWR0aCA9IG1heFdpZHRoO1xuICAgICAgICB0aGlzLm1heEhlaWdodCA9IG1heEhlaWdodDtcbiAgICAgICAgdGhpcy5fbWFyZ2lucyA9IG1hcmdpbnM7XG4gICAgICAgIHRoaXMuc2V0RGltZW5zaW9ucygpO1xuICAgICAgICB0aGlzLmJ1aWxkTGFiZWxzKCk7XG4gICAgICAgIHRoaXMuZml0KCk7XG4gICAgfVxuICAgIHNldERpbWVuc2lvbnMoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gdGhpcy5tYXhXaWR0aDtcbiAgICAgICAgICAgIHRoaXMubGVmdCA9IHRoaXMuX21hcmdpbnMubGVmdDtcbiAgICAgICAgICAgIHRoaXMucmlnaHQgPSB0aGlzLndpZHRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLm1heEhlaWdodDtcbiAgICAgICAgICAgIHRoaXMudG9wID0gdGhpcy5fbWFyZ2lucy50b3A7XG4gICAgICAgICAgICB0aGlzLmJvdHRvbSA9IHRoaXMuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuICAgIGJ1aWxkTGFiZWxzKCkge1xuICAgICAgICBjb25zdCBsYWJlbE9wdHMgPSB0aGlzLm9wdGlvbnMubGFiZWxzIHx8IHt9O1xuICAgICAgICBsZXQgbGVnZW5kSXRlbXMgPSBjYWxsYmFjayhsYWJlbE9wdHMuZ2VuZXJhdGVMYWJlbHMsIFtcbiAgICAgICAgICAgIHRoaXMuY2hhcnRcbiAgICAgICAgXSwgdGhpcykgfHwgW107XG4gICAgICAgIGlmIChsYWJlbE9wdHMuZmlsdGVyKSB7XG4gICAgICAgICAgICBsZWdlbmRJdGVtcyA9IGxlZ2VuZEl0ZW1zLmZpbHRlcigoaXRlbSk9PmxhYmVsT3B0cy5maWx0ZXIoaXRlbSwgdGhpcy5jaGFydC5kYXRhKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxhYmVsT3B0cy5zb3J0KSB7XG4gICAgICAgICAgICBsZWdlbmRJdGVtcyA9IGxlZ2VuZEl0ZW1zLnNvcnQoKGEsIGIpPT5sYWJlbE9wdHMuc29ydChhLCBiLCB0aGlzLmNoYXJ0LmRhdGEpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnJldmVyc2UpIHtcbiAgICAgICAgICAgIGxlZ2VuZEl0ZW1zLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxlZ2VuZEl0ZW1zID0gbGVnZW5kSXRlbXM7XG4gICAgfVxuICAgIGZpdCgpIHtcbiAgICAgICAgY29uc3QgeyBvcHRpb25zICwgY3R4ICB9ID0gdGhpcztcbiAgICAgICAgaWYgKCFvcHRpb25zLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB0aGlzLmhlaWdodCA9IDA7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGFiZWxPcHRzID0gb3B0aW9ucy5sYWJlbHM7XG4gICAgICAgIGNvbnN0IGxhYmVsRm9udCA9IHRvRm9udChsYWJlbE9wdHMuZm9udCk7XG4gICAgICAgIGNvbnN0IGZvbnRTaXplID0gbGFiZWxGb250LnNpemU7XG4gICAgICAgIGNvbnN0IHRpdGxlSGVpZ2h0ID0gdGhpcy5fY29tcHV0ZVRpdGxlSGVpZ2h0KCk7XG4gICAgICAgIGNvbnN0IHsgYm94V2lkdGggLCBpdGVtSGVpZ2h0ICB9ID0gZ2V0Qm94U2l6ZShsYWJlbE9wdHMsIGZvbnRTaXplKTtcbiAgICAgICAgbGV0IHdpZHRoLCBoZWlnaHQ7XG4gICAgICAgIGN0eC5mb250ID0gbGFiZWxGb250LnN0cmluZztcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIHdpZHRoID0gdGhpcy5tYXhXaWR0aDtcbiAgICAgICAgICAgIGhlaWdodCA9IHRoaXMuX2ZpdFJvd3ModGl0bGVIZWlnaHQsIGZvbnRTaXplLCBib3hXaWR0aCwgaXRlbUhlaWdodCkgKyAxMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhlaWdodCA9IHRoaXMubWF4SGVpZ2h0O1xuICAgICAgICAgICAgd2lkdGggPSB0aGlzLl9maXRDb2xzKHRpdGxlSGVpZ2h0LCBsYWJlbEZvbnQsIGJveFdpZHRoLCBpdGVtSGVpZ2h0KSArIDEwO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMud2lkdGggPSBNYXRoLm1pbih3aWR0aCwgb3B0aW9ucy5tYXhXaWR0aCB8fCB0aGlzLm1heFdpZHRoKTtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBNYXRoLm1pbihoZWlnaHQsIG9wdGlvbnMubWF4SGVpZ2h0IHx8IHRoaXMubWF4SGVpZ2h0KTtcbiAgICB9XG4gX2ZpdFJvd3ModGl0bGVIZWlnaHQsIGZvbnRTaXplLCBib3hXaWR0aCwgaXRlbUhlaWdodCkge1xuICAgICAgICBjb25zdCB7IGN0eCAsIG1heFdpZHRoICwgb3B0aW9uczogeyBsYWJlbHM6IHsgcGFkZGluZyAgfSAgfSAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGhpdGJveGVzID0gdGhpcy5sZWdlbmRIaXRCb3hlcyA9IFtdO1xuICAgICAgICBjb25zdCBsaW5lV2lkdGhzID0gdGhpcy5saW5lV2lkdGhzID0gW1xuICAgICAgICAgICAgMFxuICAgICAgICBdO1xuICAgICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gaXRlbUhlaWdodCArIHBhZGRpbmc7XG4gICAgICAgIGxldCB0b3RhbEhlaWdodCA9IHRpdGxlSGVpZ2h0O1xuICAgICAgICBjdHgudGV4dEFsaWduID0gJ2xlZnQnO1xuICAgICAgICBjdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgICAgIGxldCByb3cgPSAtMTtcbiAgICAgICAgbGV0IHRvcCA9IC1saW5lSGVpZ2h0O1xuICAgICAgICB0aGlzLmxlZ2VuZEl0ZW1zLmZvckVhY2goKGxlZ2VuZEl0ZW0sIGkpPT57XG4gICAgICAgICAgICBjb25zdCBpdGVtV2lkdGggPSBib3hXaWR0aCArIGZvbnRTaXplIC8gMiArIGN0eC5tZWFzdXJlVGV4dChsZWdlbmRJdGVtLnRleHQpLndpZHRoO1xuICAgICAgICAgICAgaWYgKGkgPT09IDAgfHwgbGluZVdpZHRoc1tsaW5lV2lkdGhzLmxlbmd0aCAtIDFdICsgaXRlbVdpZHRoICsgMiAqIHBhZGRpbmcgPiBtYXhXaWR0aCkge1xuICAgICAgICAgICAgICAgIHRvdGFsSGVpZ2h0ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICAgICAgbGluZVdpZHRoc1tsaW5lV2lkdGhzLmxlbmd0aCAtIChpID4gMCA/IDAgOiAxKV0gPSAwO1xuICAgICAgICAgICAgICAgIHRvcCArPSBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgIHJvdysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGl0Ym94ZXNbaV0gPSB7XG4gICAgICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgICAgICB0b3AsXG4gICAgICAgICAgICAgICAgcm93LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBpdGVtV2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBpdGVtSGVpZ2h0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbGluZVdpZHRoc1tsaW5lV2lkdGhzLmxlbmd0aCAtIDFdICs9IGl0ZW1XaWR0aCArIHBhZGRpbmc7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdG90YWxIZWlnaHQ7XG4gICAgfVxuICAgIF9maXRDb2xzKHRpdGxlSGVpZ2h0LCBsYWJlbEZvbnQsIGJveFdpZHRoLCBfaXRlbUhlaWdodCkge1xuICAgICAgICBjb25zdCB7IGN0eCAsIG1heEhlaWdodCAsIG9wdGlvbnM6IHsgbGFiZWxzOiB7IHBhZGRpbmcgIH0gIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBoaXRib3hlcyA9IHRoaXMubGVnZW5kSGl0Qm94ZXMgPSBbXTtcbiAgICAgICAgY29uc3QgY29sdW1uU2l6ZXMgPSB0aGlzLmNvbHVtblNpemVzID0gW107XG4gICAgICAgIGNvbnN0IGhlaWdodExpbWl0ID0gbWF4SGVpZ2h0IC0gdGl0bGVIZWlnaHQ7XG4gICAgICAgIGxldCB0b3RhbFdpZHRoID0gcGFkZGluZztcbiAgICAgICAgbGV0IGN1cnJlbnRDb2xXaWR0aCA9IDA7XG4gICAgICAgIGxldCBjdXJyZW50Q29sSGVpZ2h0ID0gMDtcbiAgICAgICAgbGV0IGxlZnQgPSAwO1xuICAgICAgICBsZXQgY29sID0gMDtcbiAgICAgICAgdGhpcy5sZWdlbmRJdGVtcy5mb3JFYWNoKChsZWdlbmRJdGVtLCBpKT0+e1xuICAgICAgICAgICAgY29uc3QgeyBpdGVtV2lkdGggLCBpdGVtSGVpZ2h0ICB9ID0gY2FsY3VsYXRlSXRlbVNpemUoYm94V2lkdGgsIGxhYmVsRm9udCwgY3R4LCBsZWdlbmRJdGVtLCBfaXRlbUhlaWdodCk7XG4gICAgICAgICAgICBpZiAoaSA+IDAgJiYgY3VycmVudENvbEhlaWdodCArIGl0ZW1IZWlnaHQgKyAyICogcGFkZGluZyA+IGhlaWdodExpbWl0KSB7XG4gICAgICAgICAgICAgICAgdG90YWxXaWR0aCArPSBjdXJyZW50Q29sV2lkdGggKyBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogY3VycmVudENvbFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGN1cnJlbnRDb2xIZWlnaHRcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBsZWZ0ICs9IGN1cnJlbnRDb2xXaWR0aCArIHBhZGRpbmc7XG4gICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICAgICAgY3VycmVudENvbFdpZHRoID0gY3VycmVudENvbEhlaWdodCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoaXRib3hlc1tpXSA9IHtcbiAgICAgICAgICAgICAgICBsZWZ0LFxuICAgICAgICAgICAgICAgIHRvcDogY3VycmVudENvbEhlaWdodCxcbiAgICAgICAgICAgICAgICBjb2wsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGl0ZW1XaWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGl0ZW1IZWlnaHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjdXJyZW50Q29sV2lkdGggPSBNYXRoLm1heChjdXJyZW50Q29sV2lkdGgsIGl0ZW1XaWR0aCk7XG4gICAgICAgICAgICBjdXJyZW50Q29sSGVpZ2h0ICs9IGl0ZW1IZWlnaHQgKyBwYWRkaW5nO1xuICAgICAgICB9KTtcbiAgICAgICAgdG90YWxXaWR0aCArPSBjdXJyZW50Q29sV2lkdGg7XG4gICAgICAgIGNvbHVtblNpemVzLnB1c2goe1xuICAgICAgICAgICAgd2lkdGg6IGN1cnJlbnRDb2xXaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogY3VycmVudENvbEhlaWdodFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRvdGFsV2lkdGg7XG4gICAgfVxuICAgIGFkanVzdEhpdEJveGVzKCkge1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5kaXNwbGF5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGl0bGVIZWlnaHQgPSB0aGlzLl9jb21wdXRlVGl0bGVIZWlnaHQoKTtcbiAgICAgICAgY29uc3QgeyBsZWdlbmRIaXRCb3hlczogaGl0Ym94ZXMgLCBvcHRpb25zOiB7IGFsaWduICwgbGFiZWxzOiB7IHBhZGRpbmcgIH0gLCBydGwgIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBydGxIZWxwZXIgPSBnZXRSdGxBZGFwdGVyKHJ0bCwgdGhpcy5sZWZ0LCB0aGlzLndpZHRoKTtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIGxldCByb3cgPSAwO1xuICAgICAgICAgICAgbGV0IGxlZnQgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgdGhpcy5sZWZ0ICsgcGFkZGluZywgdGhpcy5yaWdodCAtIHRoaXMubGluZVdpZHRoc1tyb3ddKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaGl0Ym94IG9mIGhpdGJveGVzKXtcbiAgICAgICAgICAgICAgICBpZiAocm93ICE9PSBoaXRib3gucm93KSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9IGhpdGJveC5yb3c7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgdGhpcy5sZWZ0ICsgcGFkZGluZywgdGhpcy5yaWdodCAtIHRoaXMubGluZVdpZHRoc1tyb3ddKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGl0Ym94LnRvcCArPSB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZztcbiAgICAgICAgICAgICAgICBoaXRib3gubGVmdCA9IHJ0bEhlbHBlci5sZWZ0Rm9yTHRyKHJ0bEhlbHBlci54KGxlZnQpLCBoaXRib3gud2lkdGgpO1xuICAgICAgICAgICAgICAgIGxlZnQgKz0gaGl0Ym94LndpZHRoICsgcGFkZGluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBjb2wgPSAwO1xuICAgICAgICAgICAgbGV0IHRvcCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZywgdGhpcy5ib3R0b20gLSB0aGlzLmNvbHVtblNpemVzW2NvbF0uaGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaGl0Ym94IG9mIGhpdGJveGVzKXtcbiAgICAgICAgICAgICAgICBpZiAoaGl0Ym94LmNvbCAhPT0gY29sKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbCA9IGhpdGJveC5jb2w7XG4gICAgICAgICAgICAgICAgICAgIHRvcCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZywgdGhpcy5ib3R0b20gLSB0aGlzLmNvbHVtblNpemVzW2NvbF0uaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGl0Ym94LnRvcCA9IHRvcDtcbiAgICAgICAgICAgICAgICBoaXRib3gubGVmdCArPSB0aGlzLmxlZnQgKyBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIGhpdGJveC5sZWZ0ID0gcnRsSGVscGVyLmxlZnRGb3JMdHIocnRsSGVscGVyLngoaGl0Ym94LmxlZnQpLCBoaXRib3gud2lkdGgpO1xuICAgICAgICAgICAgICAgIHRvcCArPSBoaXRib3guaGVpZ2h0ICsgcGFkZGluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBpc0hvcml6b250YWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMucG9zaXRpb24gPT09ICd0b3AnIHx8IHRoaXMub3B0aW9ucy5wb3NpdGlvbiA9PT0gJ2JvdHRvbSc7XG4gICAgfVxuICAgIGRyYXcoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGlzcGxheSkge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgICAgICAgICBjbGlwQXJlYShjdHgsIHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5fZHJhdygpO1xuICAgICAgICAgICAgdW5jbGlwQXJlYShjdHgpO1xuICAgICAgICB9XG4gICAgfVxuIF9kcmF3KCkge1xuICAgICAgICBjb25zdCB7IG9wdGlvbnM6IG9wdHMgLCBjb2x1bW5TaXplcyAsIGxpbmVXaWR0aHMgLCBjdHggIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IGFsaWduICwgbGFiZWxzOiBsYWJlbE9wdHMgIH0gPSBvcHRzO1xuICAgICAgICBjb25zdCBkZWZhdWx0Q29sb3IgPSBkZWZhdWx0cy5jb2xvcjtcbiAgICAgICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRzLnJ0bCwgdGhpcy5sZWZ0LCB0aGlzLndpZHRoKTtcbiAgICAgICAgY29uc3QgbGFiZWxGb250ID0gdG9Gb250KGxhYmVsT3B0cy5mb250KTtcbiAgICAgICAgY29uc3QgeyBwYWRkaW5nICB9ID0gbGFiZWxPcHRzO1xuICAgICAgICBjb25zdCBmb250U2l6ZSA9IGxhYmVsRm9udC5zaXplO1xuICAgICAgICBjb25zdCBoYWxmRm9udFNpemUgPSBmb250U2l6ZSAvIDI7XG4gICAgICAgIGxldCBjdXJzb3I7XG4gICAgICAgIHRoaXMuZHJhd1RpdGxlKCk7XG4gICAgICAgIGN0eC50ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKCdsZWZ0Jyk7XG4gICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IDAuNTtcbiAgICAgICAgY3R4LmZvbnQgPSBsYWJlbEZvbnQuc3RyaW5nO1xuICAgICAgICBjb25zdCB7IGJveFdpZHRoICwgYm94SGVpZ2h0ICwgaXRlbUhlaWdodCAgfSA9IGdldEJveFNpemUobGFiZWxPcHRzLCBmb250U2l6ZSk7XG4gICAgICAgIGNvbnN0IGRyYXdMZWdlbmRCb3ggPSBmdW5jdGlvbih4LCB5LCBsZWdlbmRJdGVtKSB7XG4gICAgICAgICAgICBpZiAoaXNOYU4oYm94V2lkdGgpIHx8IGJveFdpZHRoIDw9IDAgfHwgaXNOYU4oYm94SGVpZ2h0KSB8fCBib3hIZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmVXaWR0aCA9IHZhbHVlT3JEZWZhdWx0KGxlZ2VuZEl0ZW0ubGluZVdpZHRoLCAxKTtcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLmZpbGxTdHlsZSwgZGVmYXVsdENvbG9yKTtcbiAgICAgICAgICAgIGN0eC5saW5lQ2FwID0gdmFsdWVPckRlZmF1bHQobGVnZW5kSXRlbS5saW5lQ2FwLCAnYnV0dCcpO1xuICAgICAgICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gdmFsdWVPckRlZmF1bHQobGVnZW5kSXRlbS5saW5lRGFzaE9mZnNldCwgMCk7XG4gICAgICAgICAgICBjdHgubGluZUpvaW4gPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLmxpbmVKb2luLCAnbWl0ZXInKTtcbiAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLnN0cm9rZVN0eWxlLCBkZWZhdWx0Q29sb3IpO1xuICAgICAgICAgICAgY3R4LnNldExpbmVEYXNoKHZhbHVlT3JEZWZhdWx0KGxlZ2VuZEl0ZW0ubGluZURhc2gsIFtdKSk7XG4gICAgICAgICAgICBpZiAobGFiZWxPcHRzLnVzZVBvaW50U3R5bGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkcmF3T3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgcmFkaXVzOiBib3hIZWlnaHQgKiBNYXRoLlNRUlQyIC8gMixcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRTdHlsZTogbGVnZW5kSXRlbS5wb2ludFN0eWxlLFxuICAgICAgICAgICAgICAgICAgICByb3RhdGlvbjogbGVnZW5kSXRlbS5yb3RhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgYm9yZGVyV2lkdGg6IGxpbmVXaWR0aFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY29uc3QgY2VudGVyWCA9IHJ0bEhlbHBlci54UGx1cyh4LCBib3hXaWR0aCAvIDIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNlbnRlclkgPSB5ICsgaGFsZkZvbnRTaXplO1xuICAgICAgICAgICAgICAgIGRyYXdQb2ludExlZ2VuZChjdHgsIGRyYXdPcHRpb25zLCBjZW50ZXJYLCBjZW50ZXJZLCBsYWJlbE9wdHMucG9pbnRTdHlsZVdpZHRoICYmIGJveFdpZHRoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeUJveFRvcCA9IHkgKyBNYXRoLm1heCgoZm9udFNpemUgLSBib3hIZWlnaHQpIC8gMiwgMCk7XG4gICAgICAgICAgICAgICAgY29uc3QgeEJveExlZnQgPSBydGxIZWxwZXIubGVmdEZvckx0cih4LCBib3hXaWR0aCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYm9yZGVyUmFkaXVzID0gdG9UUkJMQ29ybmVycyhsZWdlbmRJdGVtLmJvcmRlclJhZGl1cyk7XG4gICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QudmFsdWVzKGJvcmRlclJhZGl1cykuc29tZSgodik9PnYgIT09IDApKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZFJvdW5kZWRSZWN0UGF0aChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IHhCb3hMZWZ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogeUJveFRvcCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHc6IGJveFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgaDogYm94SGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgcmFkaXVzOiBib3JkZXJSYWRpdXNcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4LnJlY3QoeEJveExlZnQsIHlCb3hUb3AsIGJveFdpZHRoLCBib3hIZWlnaHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICAgICAgICAgIGlmIChsaW5lV2lkdGggIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGZpbGxUZXh0ID0gZnVuY3Rpb24oeCwgeSwgbGVnZW5kSXRlbSkge1xuICAgICAgICAgICAgcmVuZGVyVGV4dChjdHgsIGxlZ2VuZEl0ZW0udGV4dCwgeCwgeSArIGl0ZW1IZWlnaHQgLyAyLCBsYWJlbEZvbnQsIHtcbiAgICAgICAgICAgICAgICBzdHJpa2V0aHJvdWdoOiBsZWdlbmRJdGVtLmhpZGRlbixcbiAgICAgICAgICAgICAgICB0ZXh0QWxpZ246IHJ0bEhlbHBlci50ZXh0QWxpZ24obGVnZW5kSXRlbS50ZXh0QWxpZ24pXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaXNIb3Jpem9udGFsID0gdGhpcy5pc0hvcml6b250YWwoKTtcbiAgICAgICAgY29uc3QgdGl0bGVIZWlnaHQgPSB0aGlzLl9jb21wdXRlVGl0bGVIZWlnaHQoKTtcbiAgICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgY3Vyc29yID0ge1xuICAgICAgICAgICAgICAgIHg6IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLmxlZnQgKyBwYWRkaW5nLCB0aGlzLnJpZ2h0IC0gbGluZVdpZHRoc1swXSksXG4gICAgICAgICAgICAgICAgeTogdGhpcy50b3AgKyBwYWRkaW5nICsgdGl0bGVIZWlnaHQsXG4gICAgICAgICAgICAgICAgbGluZTogMFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN1cnNvciA9IHtcbiAgICAgICAgICAgICAgICB4OiB0aGlzLmxlZnQgKyBwYWRkaW5nLFxuICAgICAgICAgICAgICAgIHk6IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZywgdGhpcy5ib3R0b20gLSBjb2x1bW5TaXplc1swXS5oZWlnaHQpLFxuICAgICAgICAgICAgICAgIGxpbmU6IDBcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uKHRoaXMuY3R4LCBvcHRzLnRleHREaXJlY3Rpb24pO1xuICAgICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gaXRlbUhlaWdodCArIHBhZGRpbmc7XG4gICAgICAgIHRoaXMubGVnZW5kSXRlbXMuZm9yRWFjaCgobGVnZW5kSXRlbSwgaSk9PntcbiAgICAgICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGxlZ2VuZEl0ZW0uZm9udENvbG9yO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGxlZ2VuZEl0ZW0uZm9udENvbG9yO1xuICAgICAgICAgICAgY29uc3QgdGV4dFdpZHRoID0gY3R4Lm1lYXN1cmVUZXh0KGxlZ2VuZEl0ZW0udGV4dCkud2lkdGg7XG4gICAgICAgICAgICBjb25zdCB0ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKGxlZ2VuZEl0ZW0udGV4dEFsaWduIHx8IChsZWdlbmRJdGVtLnRleHRBbGlnbiA9IGxhYmVsT3B0cy50ZXh0QWxpZ24pKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gYm94V2lkdGggKyBoYWxmRm9udFNpemUgKyB0ZXh0V2lkdGg7XG4gICAgICAgICAgICBsZXQgeCA9IGN1cnNvci54O1xuICAgICAgICAgICAgbGV0IHkgPSBjdXJzb3IueTtcbiAgICAgICAgICAgIHJ0bEhlbHBlci5zZXRXaWR0aCh0aGlzLndpZHRoKTtcbiAgICAgICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICBpZiAoaSA+IDAgJiYgeCArIHdpZHRoICsgcGFkZGluZyA+IHRoaXMucmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgeSA9IGN1cnNvci55ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIGN1cnNvci5saW5lKys7XG4gICAgICAgICAgICAgICAgICAgIHggPSBjdXJzb3IueCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLmxlZnQgKyBwYWRkaW5nLCB0aGlzLnJpZ2h0IC0gbGluZVdpZHRoc1tjdXJzb3IubGluZV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaSA+IDAgJiYgeSArIGxpbmVIZWlnaHQgPiB0aGlzLmJvdHRvbSkge1xuICAgICAgICAgICAgICAgIHggPSBjdXJzb3IueCA9IHggKyBjb2x1bW5TaXplc1tjdXJzb3IubGluZV0ud2lkdGggKyBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIGN1cnNvci5saW5lKys7XG4gICAgICAgICAgICAgICAgeSA9IGN1cnNvci55ID0gX2FsaWduU3RhcnRFbmQoYWxpZ24sIHRoaXMudG9wICsgdGl0bGVIZWlnaHQgKyBwYWRkaW5nLCB0aGlzLmJvdHRvbSAtIGNvbHVtblNpemVzW2N1cnNvci5saW5lXS5oZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVhbFggPSBydGxIZWxwZXIueCh4KTtcbiAgICAgICAgICAgIGRyYXdMZWdlbmRCb3gocmVhbFgsIHksIGxlZ2VuZEl0ZW0pO1xuICAgICAgICAgICAgeCA9IF90ZXh0WCh0ZXh0QWxpZ24sIHggKyBib3hXaWR0aCArIGhhbGZGb250U2l6ZSwgaXNIb3Jpem9udGFsID8geCArIHdpZHRoIDogdGhpcy5yaWdodCwgb3B0cy5ydGwpO1xuICAgICAgICAgICAgZmlsbFRleHQocnRsSGVscGVyLngoeCksIHksIGxlZ2VuZEl0ZW0pO1xuICAgICAgICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIGN1cnNvci54ICs9IHdpZHRoICsgcGFkZGluZztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxlZ2VuZEl0ZW0udGV4dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmb250TGluZUhlaWdodCA9IGxhYmVsRm9udC5saW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgIGN1cnNvci55ICs9IGNhbGN1bGF0ZUxlZ2VuZEl0ZW1IZWlnaHQobGVnZW5kSXRlbSwgZm9udExpbmVIZWlnaHQpICsgcGFkZGluZztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY3Vyc29yLnkgKz0gbGluZUhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3RvcmVUZXh0RGlyZWN0aW9uKHRoaXMuY3R4LCBvcHRzLnRleHREaXJlY3Rpb24pO1xuICAgIH1cbiBkcmF3VGl0bGUoKSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHRpdGxlT3B0cyA9IG9wdHMudGl0bGU7XG4gICAgICAgIGNvbnN0IHRpdGxlRm9udCA9IHRvRm9udCh0aXRsZU9wdHMuZm9udCk7XG4gICAgICAgIGNvbnN0IHRpdGxlUGFkZGluZyA9IHRvUGFkZGluZyh0aXRsZU9wdHMucGFkZGluZyk7XG4gICAgICAgIGlmICghdGl0bGVPcHRzLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBydGxIZWxwZXIgPSBnZXRSdGxBZGFwdGVyKG9wdHMucnRsLCB0aGlzLmxlZnQsIHRoaXMud2lkdGgpO1xuICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSB0aXRsZU9wdHMucG9zaXRpb247XG4gICAgICAgIGNvbnN0IGhhbGZGb250U2l6ZSA9IHRpdGxlRm9udC5zaXplIC8gMjtcbiAgICAgICAgY29uc3QgdG9wUGFkZGluZ1BsdXNIYWxmRm9udFNpemUgPSB0aXRsZVBhZGRpbmcudG9wICsgaGFsZkZvbnRTaXplO1xuICAgICAgICBsZXQgeTtcbiAgICAgICAgbGV0IGxlZnQgPSB0aGlzLmxlZnQ7XG4gICAgICAgIGxldCBtYXhXaWR0aCA9IHRoaXMud2lkdGg7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICBtYXhXaWR0aCA9IE1hdGgubWF4KC4uLnRoaXMubGluZVdpZHRocyk7XG4gICAgICAgICAgICB5ID0gdGhpcy50b3AgKyB0b3BQYWRkaW5nUGx1c0hhbGZGb250U2l6ZTtcbiAgICAgICAgICAgIGxlZnQgPSBfYWxpZ25TdGFydEVuZChvcHRzLmFsaWduLCBsZWZ0LCB0aGlzLnJpZ2h0IC0gbWF4V2lkdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbWF4SGVpZ2h0ID0gdGhpcy5jb2x1bW5TaXplcy5yZWR1Y2UoKGFjYywgc2l6ZSk9Pk1hdGgubWF4KGFjYywgc2l6ZS5oZWlnaHQpLCAwKTtcbiAgICAgICAgICAgIHkgPSB0b3BQYWRkaW5nUGx1c0hhbGZGb250U2l6ZSArIF9hbGlnblN0YXJ0RW5kKG9wdHMuYWxpZ24sIHRoaXMudG9wLCB0aGlzLmJvdHRvbSAtIG1heEhlaWdodCAtIG9wdHMubGFiZWxzLnBhZGRpbmcgLSB0aGlzLl9jb21wdXRlVGl0bGVIZWlnaHQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeCA9IF9hbGlnblN0YXJ0RW5kKHBvc2l0aW9uLCBsZWZ0LCBsZWZ0ICsgbWF4V2lkdGgpO1xuICAgICAgICBjdHgudGV4dEFsaWduID0gcnRsSGVscGVyLnRleHRBbGlnbihfdG9MZWZ0UmlnaHRDZW50ZXIocG9zaXRpb24pKTtcbiAgICAgICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSB0aXRsZU9wdHMuY29sb3I7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSB0aXRsZU9wdHMuY29sb3I7XG4gICAgICAgIGN0eC5mb250ID0gdGl0bGVGb250LnN0cmluZztcbiAgICAgICAgcmVuZGVyVGV4dChjdHgsIHRpdGxlT3B0cy50ZXh0LCB4LCB5LCB0aXRsZUZvbnQpO1xuICAgIH1cbiBfY29tcHV0ZVRpdGxlSGVpZ2h0KCkge1xuICAgICAgICBjb25zdCB0aXRsZU9wdHMgPSB0aGlzLm9wdGlvbnMudGl0bGU7XG4gICAgICAgIGNvbnN0IHRpdGxlRm9udCA9IHRvRm9udCh0aXRsZU9wdHMuZm9udCk7XG4gICAgICAgIGNvbnN0IHRpdGxlUGFkZGluZyA9IHRvUGFkZGluZyh0aXRsZU9wdHMucGFkZGluZyk7XG4gICAgICAgIHJldHVybiB0aXRsZU9wdHMuZGlzcGxheSA/IHRpdGxlRm9udC5saW5lSGVpZ2h0ICsgdGl0bGVQYWRkaW5nLmhlaWdodCA6IDA7XG4gICAgfVxuIF9nZXRMZWdlbmRJdGVtQXQoeCwgeSkge1xuICAgICAgICBsZXQgaSwgaGl0Qm94LCBsaDtcbiAgICAgICAgaWYgKF9pc0JldHdlZW4oeCwgdGhpcy5sZWZ0LCB0aGlzLnJpZ2h0KSAmJiBfaXNCZXR3ZWVuKHksIHRoaXMudG9wLCB0aGlzLmJvdHRvbSkpIHtcbiAgICAgICAgICAgIGxoID0gdGhpcy5sZWdlbmRIaXRCb3hlcztcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxoLmxlbmd0aDsgKytpKXtcbiAgICAgICAgICAgICAgICBoaXRCb3ggPSBsaFtpXTtcbiAgICAgICAgICAgICAgICBpZiAoX2lzQmV0d2Vlbih4LCBoaXRCb3gubGVmdCwgaGl0Qm94LmxlZnQgKyBoaXRCb3gud2lkdGgpICYmIF9pc0JldHdlZW4oeSwgaGl0Qm94LnRvcCwgaGl0Qm94LnRvcCArIGhpdEJveC5oZWlnaHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxlZ2VuZEl0ZW1zW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gaGFuZGxlRXZlbnQoZSkge1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAoIWlzTGlzdGVuZWQoZS50eXBlLCBvcHRzKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhvdmVyZWRJdGVtID0gdGhpcy5fZ2V0TGVnZW5kSXRlbUF0KGUueCwgZS55KTtcbiAgICAgICAgaWYgKGUudHlwZSA9PT0gJ21vdXNlbW92ZScgfHwgZS50eXBlID09PSAnbW91c2VvdXQnKSB7XG4gICAgICAgICAgICBjb25zdCBwcmV2aW91cyA9IHRoaXMuX2hvdmVyZWRJdGVtO1xuICAgICAgICAgICAgY29uc3Qgc2FtZUl0ZW0gPSBpdGVtc0VxdWFsKHByZXZpb3VzLCBob3ZlcmVkSXRlbSk7XG4gICAgICAgICAgICBpZiAocHJldmlvdXMgJiYgIXNhbWVJdGVtKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sob3B0cy5vbkxlYXZlLCBbXG4gICAgICAgICAgICAgICAgICAgIGUsXG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzLFxuICAgICAgICAgICAgICAgICAgICB0aGlzXG4gICAgICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9ob3ZlcmVkSXRlbSA9IGhvdmVyZWRJdGVtO1xuICAgICAgICAgICAgaWYgKGhvdmVyZWRJdGVtICYmICFzYW1lSXRlbSkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG9wdHMub25Ib3ZlciwgW1xuICAgICAgICAgICAgICAgICAgICBlLFxuICAgICAgICAgICAgICAgICAgICBob3ZlcmVkSXRlbSxcbiAgICAgICAgICAgICAgICAgICAgdGhpc1xuICAgICAgICAgICAgICAgIF0sIHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGhvdmVyZWRJdGVtKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhvcHRzLm9uQ2xpY2ssIFtcbiAgICAgICAgICAgICAgICBlLFxuICAgICAgICAgICAgICAgIGhvdmVyZWRJdGVtLFxuICAgICAgICAgICAgICAgIHRoaXNcbiAgICAgICAgICAgIF0sIHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gY2FsY3VsYXRlSXRlbVNpemUoYm94V2lkdGgsIGxhYmVsRm9udCwgY3R4LCBsZWdlbmRJdGVtLCBfaXRlbUhlaWdodCkge1xuICAgIGNvbnN0IGl0ZW1XaWR0aCA9IGNhbGN1bGF0ZUl0ZW1XaWR0aChsZWdlbmRJdGVtLCBib3hXaWR0aCwgbGFiZWxGb250LCBjdHgpO1xuICAgIGNvbnN0IGl0ZW1IZWlnaHQgPSBjYWxjdWxhdGVJdGVtSGVpZ2h0KF9pdGVtSGVpZ2h0LCBsZWdlbmRJdGVtLCBsYWJlbEZvbnQubGluZUhlaWdodCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgaXRlbVdpZHRoLFxuICAgICAgICBpdGVtSGVpZ2h0XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGNhbGN1bGF0ZUl0ZW1XaWR0aChsZWdlbmRJdGVtLCBib3hXaWR0aCwgbGFiZWxGb250LCBjdHgpIHtcbiAgICBsZXQgbGVnZW5kSXRlbVRleHQgPSBsZWdlbmRJdGVtLnRleHQ7XG4gICAgaWYgKGxlZ2VuZEl0ZW1UZXh0ICYmIHR5cGVvZiBsZWdlbmRJdGVtVGV4dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgbGVnZW5kSXRlbVRleHQgPSBsZWdlbmRJdGVtVGV4dC5yZWR1Y2UoKGEsIGIpPT5hLmxlbmd0aCA+IGIubGVuZ3RoID8gYSA6IGIpO1xuICAgIH1cbiAgICByZXR1cm4gYm94V2lkdGggKyBsYWJlbEZvbnQuc2l6ZSAvIDIgKyBjdHgubWVhc3VyZVRleHQobGVnZW5kSXRlbVRleHQpLndpZHRoO1xufVxuZnVuY3Rpb24gY2FsY3VsYXRlSXRlbUhlaWdodChfaXRlbUhlaWdodCwgbGVnZW5kSXRlbSwgZm9udExpbmVIZWlnaHQpIHtcbiAgICBsZXQgaXRlbUhlaWdodCA9IF9pdGVtSGVpZ2h0O1xuICAgIGlmICh0eXBlb2YgbGVnZW5kSXRlbS50ZXh0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICBpdGVtSGVpZ2h0ID0gY2FsY3VsYXRlTGVnZW5kSXRlbUhlaWdodChsZWdlbmRJdGVtLCBmb250TGluZUhlaWdodCk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtSGVpZ2h0O1xufVxuZnVuY3Rpb24gY2FsY3VsYXRlTGVnZW5kSXRlbUhlaWdodChsZWdlbmRJdGVtLCBmb250TGluZUhlaWdodCkge1xuICAgIGNvbnN0IGxhYmVsSGVpZ2h0ID0gbGVnZW5kSXRlbS50ZXh0ID8gbGVnZW5kSXRlbS50ZXh0Lmxlbmd0aCA6IDA7XG4gICAgcmV0dXJuIGZvbnRMaW5lSGVpZ2h0ICogbGFiZWxIZWlnaHQ7XG59XG5mdW5jdGlvbiBpc0xpc3RlbmVkKHR5cGUsIG9wdHMpIHtcbiAgICBpZiAoKHR5cGUgPT09ICdtb3VzZW1vdmUnIHx8IHR5cGUgPT09ICdtb3VzZW91dCcpICYmIChvcHRzLm9uSG92ZXIgfHwgb3B0cy5vbkxlYXZlKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKG9wdHMub25DbGljayAmJiAodHlwZSA9PT0gJ2NsaWNrJyB8fCB0eXBlID09PSAnbW91c2V1cCcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG52YXIgcGx1Z2luX2xlZ2VuZCA9IHtcbiAgICBpZDogJ2xlZ2VuZCcsXG4gX2VsZW1lbnQ6IExlZ2VuZCxcbiAgICBzdGFydCAoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGxlZ2VuZCA9IGNoYXJ0LmxlZ2VuZCA9IG5ldyBMZWdlbmQoe1xuICAgICAgICAgICAgY3R4OiBjaGFydC5jdHgsXG4gICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgY2hhcnRcbiAgICAgICAgfSk7XG4gICAgICAgIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCBsZWdlbmQsIG9wdGlvbnMpO1xuICAgICAgICBsYXlvdXRzLmFkZEJveChjaGFydCwgbGVnZW5kKTtcbiAgICB9LFxuICAgIHN0b3AgKGNoYXJ0KSB7XG4gICAgICAgIGxheW91dHMucmVtb3ZlQm94KGNoYXJ0LCBjaGFydC5sZWdlbmQpO1xuICAgICAgICBkZWxldGUgY2hhcnQubGVnZW5kO1xuICAgIH0sXG4gICAgYmVmb3JlVXBkYXRlIChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbGVnZW5kID0gY2hhcnQubGVnZW5kO1xuICAgICAgICBsYXlvdXRzLmNvbmZpZ3VyZShjaGFydCwgbGVnZW5kLCBvcHRpb25zKTtcbiAgICAgICAgbGVnZW5kLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH0sXG4gICAgYWZ0ZXJVcGRhdGUgKGNoYXJ0KSB7XG4gICAgICAgIGNvbnN0IGxlZ2VuZCA9IGNoYXJ0LmxlZ2VuZDtcbiAgICAgICAgbGVnZW5kLmJ1aWxkTGFiZWxzKCk7XG4gICAgICAgIGxlZ2VuZC5hZGp1c3RIaXRCb3hlcygpO1xuICAgIH0sXG4gICAgYWZ0ZXJFdmVudCAoY2hhcnQsIGFyZ3MpIHtcbiAgICAgICAgaWYgKCFhcmdzLnJlcGxheSkge1xuICAgICAgICAgICAgY2hhcnQubGVnZW5kLmhhbmRsZUV2ZW50KGFyZ3MuZXZlbnQpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkZWZhdWx0czoge1xuICAgICAgICBkaXNwbGF5OiB0cnVlLFxuICAgICAgICBwb3NpdGlvbjogJ3RvcCcsXG4gICAgICAgIGFsaWduOiAnY2VudGVyJyxcbiAgICAgICAgZnVsbFNpemU6IHRydWUsXG4gICAgICAgIHJldmVyc2U6IGZhbHNlLFxuICAgICAgICB3ZWlnaHQ6IDEwMDAsXG4gICAgICAgIG9uQ2xpY2sgKGUsIGxlZ2VuZEl0ZW0sIGxlZ2VuZCkge1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBsZWdlbmRJdGVtLmRhdGFzZXRJbmRleDtcbiAgICAgICAgICAgIGNvbnN0IGNpID0gbGVnZW5kLmNoYXJ0O1xuICAgICAgICAgICAgaWYgKGNpLmlzRGF0YXNldFZpc2libGUoaW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgY2kuaGlkZShpbmRleCk7XG4gICAgICAgICAgICAgICAgbGVnZW5kSXRlbS5oaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjaS5zaG93KGluZGV4KTtcbiAgICAgICAgICAgICAgICBsZWdlbmRJdGVtLmhpZGRlbiA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvbkhvdmVyOiBudWxsLFxuICAgICAgICBvbkxlYXZlOiBudWxsLFxuICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgIGNvbG9yOiAoY3R4KT0+Y3R4LmNoYXJ0Lm9wdGlvbnMuY29sb3IsXG4gICAgICAgICAgICBib3hXaWR0aDogNDAsXG4gICAgICAgICAgICBwYWRkaW5nOiAxMCxcbiAgICAgICAgICAgIGdlbmVyYXRlTGFiZWxzIChjaGFydCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFzZXRzID0gY2hhcnQuZGF0YS5kYXRhc2V0cztcbiAgICAgICAgICAgICAgICBjb25zdCB7IGxhYmVsczogeyB1c2VQb2ludFN0eWxlICwgcG9pbnRTdHlsZSAsIHRleHRBbGlnbiAsIGNvbG9yICwgdXNlQm9yZGVyUmFkaXVzICwgYm9yZGVyUmFkaXVzICB9ICB9ID0gY2hhcnQubGVnZW5kLm9wdGlvbnM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNoYXJ0Ll9nZXRTb3J0ZWREYXRhc2V0TWV0YXMoKS5tYXAoKG1ldGEpPT57XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0eWxlID0gbWV0YS5jb250cm9sbGVyLmdldFN0eWxlKHVzZVBvaW50U3R5bGUgPyAwIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYm9yZGVyV2lkdGggPSB0b1BhZGRpbmcoc3R5bGUuYm9yZGVyV2lkdGgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogZGF0YXNldHNbbWV0YS5pbmRleF0ubGFiZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxsU3R5bGU6IHN0eWxlLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRDb2xvcjogY29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICBoaWRkZW46ICFtZXRhLnZpc2libGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lQ2FwOiBzdHlsZS5ib3JkZXJDYXBTdHlsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVEYXNoOiBzdHlsZS5ib3JkZXJEYXNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGluZURhc2hPZmZzZXQ6IHN0eWxlLmJvcmRlckRhc2hPZmZzZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lSm9pbjogc3R5bGUuYm9yZGVySm9pblN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGluZVdpZHRoOiAoYm9yZGVyV2lkdGgud2lkdGggKyBib3JkZXJXaWR0aC5oZWlnaHQpIC8gNCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZVN0eWxlOiBzdHlsZS5ib3JkZXJDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50U3R5bGU6IHBvaW50U3R5bGUgfHwgc3R5bGUucG9pbnRTdHlsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uOiBzdHlsZS5yb3RhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbjogdGV4dEFsaWduIHx8IHN0eWxlLnRleHRBbGlnbixcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvcmRlclJhZGl1czogdXNlQm9yZGVyUmFkaXVzICYmIChib3JkZXJSYWRpdXMgfHwgc3R5bGUuYm9yZGVyUmFkaXVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFzZXRJbmRleDogbWV0YS5pbmRleFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0sIHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB0aXRsZToge1xuICAgICAgICAgICAgY29sb3I6IChjdHgpPT5jdHguY2hhcnQub3B0aW9ucy5jb2xvcixcbiAgICAgICAgICAgIGRpc3BsYXk6IGZhbHNlLFxuICAgICAgICAgICAgcG9zaXRpb246ICdjZW50ZXInLFxuICAgICAgICAgICAgdGV4dDogJydcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGVzY3JpcHRvcnM6IHtcbiAgICAgICAgX3NjcmlwdGFibGU6IChuYW1lKT0+IW5hbWUuc3RhcnRzV2l0aCgnb24nKSxcbiAgICAgICAgbGFiZWxzOiB7XG4gICAgICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT4hW1xuICAgICAgICAgICAgICAgICAgICAnZ2VuZXJhdGVMYWJlbHMnLFxuICAgICAgICAgICAgICAgICAgICAnZmlsdGVyJyxcbiAgICAgICAgICAgICAgICAgICAgJ3NvcnQnXG4gICAgICAgICAgICAgICAgXS5pbmNsdWRlcyhuYW1lKVxuICAgICAgICB9XG4gICAgfVxufTtcblxuY2xhc3MgVGl0bGUgZXh0ZW5kcyBFbGVtZW50IHtcbiBjb25zdHJ1Y3Rvcihjb25maWcpe1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmNoYXJ0ID0gY29uZmlnLmNoYXJ0O1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBjb25maWcub3B0aW9ucztcbiAgICAgICAgdGhpcy5jdHggPSBjb25maWcuY3R4O1xuICAgICAgICB0aGlzLl9wYWRkaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnRvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5ib3R0b20gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMubGVmdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5yaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy53aWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMucG9zaXRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMud2VpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmZ1bGxTaXplID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB1cGRhdGUobWF4V2lkdGgsIG1heEhlaWdodCkge1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICB0aGlzLmxlZnQgPSAwO1xuICAgICAgICB0aGlzLnRvcCA9IDA7XG4gICAgICAgIGlmICghb3B0cy5kaXNwbGF5KSB7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gdGhpcy5oZWlnaHQgPSB0aGlzLnJpZ2h0ID0gdGhpcy5ib3R0b20gPSAwO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMud2lkdGggPSB0aGlzLnJpZ2h0ID0gbWF4V2lkdGg7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy5ib3R0b20gPSBtYXhIZWlnaHQ7XG4gICAgICAgIGNvbnN0IGxpbmVDb3VudCA9IGlzQXJyYXkob3B0cy50ZXh0KSA/IG9wdHMudGV4dC5sZW5ndGggOiAxO1xuICAgICAgICB0aGlzLl9wYWRkaW5nID0gdG9QYWRkaW5nKG9wdHMucGFkZGluZyk7XG4gICAgICAgIGNvbnN0IHRleHRTaXplID0gbGluZUNvdW50ICogdG9Gb250KG9wdHMuZm9udCkubGluZUhlaWdodCArIHRoaXMuX3BhZGRpbmcuaGVpZ2h0O1xuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0ZXh0U2l6ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB0ZXh0U2l6ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpc0hvcml6b250YWwoKSB7XG4gICAgICAgIGNvbnN0IHBvcyA9IHRoaXMub3B0aW9ucy5wb3NpdGlvbjtcbiAgICAgICAgcmV0dXJuIHBvcyA9PT0gJ3RvcCcgfHwgcG9zID09PSAnYm90dG9tJztcbiAgICB9XG4gICAgX2RyYXdBcmdzKG9mZnNldCkge1xuICAgICAgICBjb25zdCB7IHRvcCAsIGxlZnQgLCBib3R0b20gLCByaWdodCAsIG9wdGlvbnMgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBhbGlnbiA9IG9wdGlvbnMuYWxpZ247XG4gICAgICAgIGxldCByb3RhdGlvbiA9IDA7XG4gICAgICAgIGxldCBtYXhXaWR0aCwgdGl0bGVYLCB0aXRsZVk7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICB0aXRsZVggPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgbGVmdCwgcmlnaHQpO1xuICAgICAgICAgICAgdGl0bGVZID0gdG9wICsgb2Zmc2V0O1xuICAgICAgICAgICAgbWF4V2lkdGggPSByaWdodCAtIGxlZnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5wb3NpdGlvbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgdGl0bGVYID0gbGVmdCArIG9mZnNldDtcbiAgICAgICAgICAgICAgICB0aXRsZVkgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgYm90dG9tLCB0b3ApO1xuICAgICAgICAgICAgICAgIHJvdGF0aW9uID0gUEkgKiAtMC41O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aXRsZVggPSByaWdodCAtIG9mZnNldDtcbiAgICAgICAgICAgICAgICB0aXRsZVkgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgdG9wLCBib3R0b20pO1xuICAgICAgICAgICAgICAgIHJvdGF0aW9uID0gUEkgKiAwLjU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtYXhXaWR0aCA9IGJvdHRvbSAtIHRvcDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdGl0bGVYLFxuICAgICAgICAgICAgdGl0bGVZLFxuICAgICAgICAgICAgbWF4V2lkdGgsXG4gICAgICAgICAgICByb3RhdGlvblxuICAgICAgICB9O1xuICAgIH1cbiAgICBkcmF3KCkge1xuICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgaWYgKCFvcHRzLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmb250T3B0cyA9IHRvRm9udChvcHRzLmZvbnQpO1xuICAgICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gZm9udE9wdHMubGluZUhlaWdodDtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gbGluZUhlaWdodCAvIDIgKyB0aGlzLl9wYWRkaW5nLnRvcDtcbiAgICAgICAgY29uc3QgeyB0aXRsZVggLCB0aXRsZVkgLCBtYXhXaWR0aCAsIHJvdGF0aW9uICB9ID0gdGhpcy5fZHJhd0FyZ3Mob2Zmc2V0KTtcbiAgICAgICAgcmVuZGVyVGV4dChjdHgsIG9wdHMudGV4dCwgMCwgMCwgZm9udE9wdHMsIHtcbiAgICAgICAgICAgIGNvbG9yOiBvcHRzLmNvbG9yLFxuICAgICAgICAgICAgbWF4V2lkdGgsXG4gICAgICAgICAgICByb3RhdGlvbixcbiAgICAgICAgICAgIHRleHRBbGlnbjogX3RvTGVmdFJpZ2h0Q2VudGVyKG9wdHMuYWxpZ24pLFxuICAgICAgICAgICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJyxcbiAgICAgICAgICAgIHRyYW5zbGF0aW9uOiBbXG4gICAgICAgICAgICAgICAgdGl0bGVYLFxuICAgICAgICAgICAgICAgIHRpdGxlWVxuICAgICAgICAgICAgXVxuICAgICAgICB9KTtcbiAgICB9XG59XG5mdW5jdGlvbiBjcmVhdGVUaXRsZShjaGFydCwgdGl0bGVPcHRzKSB7XG4gICAgY29uc3QgdGl0bGUgPSBuZXcgVGl0bGUoe1xuICAgICAgICBjdHg6IGNoYXJ0LmN0eCxcbiAgICAgICAgb3B0aW9uczogdGl0bGVPcHRzLFxuICAgICAgICBjaGFydFxuICAgIH0pO1xuICAgIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCB0aXRsZSwgdGl0bGVPcHRzKTtcbiAgICBsYXlvdXRzLmFkZEJveChjaGFydCwgdGl0bGUpO1xuICAgIGNoYXJ0LnRpdGxlQmxvY2sgPSB0aXRsZTtcbn1cbnZhciBwbHVnaW5fdGl0bGUgPSB7XG4gICAgaWQ6ICd0aXRsZScsXG4gX2VsZW1lbnQ6IFRpdGxlLFxuICAgIHN0YXJ0IChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY3JlYXRlVGl0bGUoY2hhcnQsIG9wdGlvbnMpO1xuICAgIH0sXG4gICAgc3RvcCAoY2hhcnQpIHtcbiAgICAgICAgY29uc3QgdGl0bGVCbG9jayA9IGNoYXJ0LnRpdGxlQmxvY2s7XG4gICAgICAgIGxheW91dHMucmVtb3ZlQm94KGNoYXJ0LCB0aXRsZUJsb2NrKTtcbiAgICAgICAgZGVsZXRlIGNoYXJ0LnRpdGxlQmxvY2s7XG4gICAgfSxcbiAgICBiZWZvcmVVcGRhdGUgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB0aXRsZSA9IGNoYXJ0LnRpdGxlQmxvY2s7XG4gICAgICAgIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCB0aXRsZSwgb3B0aW9ucyk7XG4gICAgICAgIHRpdGxlLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH0sXG4gICAgZGVmYXVsdHM6IHtcbiAgICAgICAgYWxpZ246ICdjZW50ZXInLFxuICAgICAgICBkaXNwbGF5OiBmYWxzZSxcbiAgICAgICAgZm9udDoge1xuICAgICAgICAgICAgd2VpZ2h0OiAnYm9sZCdcbiAgICAgICAgfSxcbiAgICAgICAgZnVsbFNpemU6IHRydWUsXG4gICAgICAgIHBhZGRpbmc6IDEwLFxuICAgICAgICBwb3NpdGlvbjogJ3RvcCcsXG4gICAgICAgIHRleHQ6ICcnLFxuICAgICAgICB3ZWlnaHQ6IDIwMDBcbiAgICB9LFxuICAgIGRlZmF1bHRSb3V0ZXM6IHtcbiAgICAgICAgY29sb3I6ICdjb2xvcidcbiAgICB9LFxuICAgIGRlc2NyaXB0b3JzOiB7XG4gICAgICAgIF9zY3JpcHRhYmxlOiB0cnVlLFxuICAgICAgICBfaW5kZXhhYmxlOiBmYWxzZVxuICAgIH1cbn07XG5cbmNvbnN0IG1hcCA9IG5ldyBXZWFrTWFwKCk7XG52YXIgcGx1Z2luX3N1YnRpdGxlID0ge1xuICAgIGlkOiAnc3VidGl0bGUnLFxuICAgIHN0YXJ0IChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgdGl0bGUgPSBuZXcgVGl0bGUoe1xuICAgICAgICAgICAgY3R4OiBjaGFydC5jdHgsXG4gICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgY2hhcnRcbiAgICAgICAgfSk7XG4gICAgICAgIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCB0aXRsZSwgb3B0aW9ucyk7XG4gICAgICAgIGxheW91dHMuYWRkQm94KGNoYXJ0LCB0aXRsZSk7XG4gICAgICAgIG1hcC5zZXQoY2hhcnQsIHRpdGxlKTtcbiAgICB9LFxuICAgIHN0b3AgKGNoYXJ0KSB7XG4gICAgICAgIGxheW91dHMucmVtb3ZlQm94KGNoYXJ0LCBtYXAuZ2V0KGNoYXJ0KSk7XG4gICAgICAgIG1hcC5kZWxldGUoY2hhcnQpO1xuICAgIH0sXG4gICAgYmVmb3JlVXBkYXRlIChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgdGl0bGUgPSBtYXAuZ2V0KGNoYXJ0KTtcbiAgICAgICAgbGF5b3V0cy5jb25maWd1cmUoY2hhcnQsIHRpdGxlLCBvcHRpb25zKTtcbiAgICAgICAgdGl0bGUub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfSxcbiAgICBkZWZhdWx0czoge1xuICAgICAgICBhbGlnbjogJ2NlbnRlcicsXG4gICAgICAgIGRpc3BsYXk6IGZhbHNlLFxuICAgICAgICBmb250OiB7XG4gICAgICAgICAgICB3ZWlnaHQ6ICdub3JtYWwnXG4gICAgICAgIH0sXG4gICAgICAgIGZ1bGxTaXplOiB0cnVlLFxuICAgICAgICBwYWRkaW5nOiAwLFxuICAgICAgICBwb3NpdGlvbjogJ3RvcCcsXG4gICAgICAgIHRleHQ6ICcnLFxuICAgICAgICB3ZWlnaHQ6IDE1MDBcbiAgICB9LFxuICAgIGRlZmF1bHRSb3V0ZXM6IHtcbiAgICAgICAgY29sb3I6ICdjb2xvcidcbiAgICB9LFxuICAgIGRlc2NyaXB0b3JzOiB7XG4gICAgICAgIF9zY3JpcHRhYmxlOiB0cnVlLFxuICAgICAgICBfaW5kZXhhYmxlOiBmYWxzZVxuICAgIH1cbn07XG5cbmNvbnN0IHBvc2l0aW9uZXJzID0ge1xuIGF2ZXJhZ2UgKGl0ZW1zKSB7XG4gICAgICAgIGlmICghaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGksIGxlbjtcbiAgICAgICAgbGV0IHhTZXQgPSBuZXcgU2V0KCk7XG4gICAgICAgIGxldCB5ID0gMDtcbiAgICAgICAgbGV0IGNvdW50ID0gMDtcbiAgICAgICAgZm9yKGkgPSAwLCBsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBsZW47ICsraSl7XG4gICAgICAgICAgICBjb25zdCBlbCA9IGl0ZW1zW2ldLmVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoZWwgJiYgZWwuaGFzVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvcyA9IGVsLnRvb2x0aXBQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIHhTZXQuYWRkKHBvcy54KTtcbiAgICAgICAgICAgICAgICB5ICs9IHBvcy55O1xuICAgICAgICAgICAgICAgICsrY291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvdW50ID09PSAwIHx8IHhTZXQuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHhBdmVyYWdlID0gW1xuICAgICAgICAgICAgLi4ueFNldFxuICAgICAgICBdLnJlZHVjZSgoYSwgYik9PmEgKyBiKSAvIHhTZXQuc2l6ZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IHhBdmVyYWdlLFxuICAgICAgICAgICAgeTogeSAvIGNvdW50XG4gICAgICAgIH07XG4gICAgfSxcbiBuZWFyZXN0IChpdGVtcywgZXZlbnRQb3NpdGlvbikge1xuICAgICAgICBpZiAoIWl0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGxldCB4ID0gZXZlbnRQb3NpdGlvbi54O1xuICAgICAgICBsZXQgeSA9IGV2ZW50UG9zaXRpb24ueTtcbiAgICAgICAgbGV0IG1pbkRpc3RhbmNlID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgICAgICBsZXQgaSwgbGVuLCBuZWFyZXN0RWxlbWVudDtcbiAgICAgICAgZm9yKGkgPSAwLCBsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBsZW47ICsraSl7XG4gICAgICAgICAgICBjb25zdCBlbCA9IGl0ZW1zW2ldLmVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoZWwgJiYgZWwuaGFzVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNlbnRlciA9IGVsLmdldENlbnRlclBvaW50KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZCA9IGRpc3RhbmNlQmV0d2VlblBvaW50cyhldmVudFBvc2l0aW9uLCBjZW50ZXIpO1xuICAgICAgICAgICAgICAgIGlmIChkIDwgbWluRGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluRGlzdGFuY2UgPSBkO1xuICAgICAgICAgICAgICAgICAgICBuZWFyZXN0RWxlbWVudCA9IGVsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobmVhcmVzdEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRwID0gbmVhcmVzdEVsZW1lbnQudG9vbHRpcFBvc2l0aW9uKCk7XG4gICAgICAgICAgICB4ID0gdHAueDtcbiAgICAgICAgICAgIHkgPSB0cC55O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4LFxuICAgICAgICAgICAgeVxuICAgICAgICB9O1xuICAgIH1cbn07XG5mdW5jdGlvbiBwdXNoT3JDb25jYXQoYmFzZSwgdG9QdXNoKSB7XG4gICAgaWYgKHRvUHVzaCkge1xuICAgICAgICBpZiAoaXNBcnJheSh0b1B1c2gpKSB7XG4gICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShiYXNlLCB0b1B1c2gpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYmFzZS5wdXNoKHRvUHVzaCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJhc2U7XG59XG4gZnVuY3Rpb24gc3BsaXROZXdsaW5lcyhzdHIpIHtcbiAgICBpZiAoKHR5cGVvZiBzdHIgPT09ICdzdHJpbmcnIHx8IHN0ciBpbnN0YW5jZW9mIFN0cmluZykgJiYgc3RyLmluZGV4T2YoJ1xcbicpID4gLTEpIHtcbiAgICAgICAgcmV0dXJuIHN0ci5zcGxpdCgnXFxuJyk7XG4gICAgfVxuICAgIHJldHVybiBzdHI7XG59XG4gZnVuY3Rpb24gY3JlYXRlVG9vbHRpcEl0ZW0oY2hhcnQsIGl0ZW0pIHtcbiAgICBjb25zdCB7IGVsZW1lbnQgLCBkYXRhc2V0SW5kZXggLCBpbmRleCAgfSA9IGl0ZW07XG4gICAgY29uc3QgY29udHJvbGxlciA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkuY29udHJvbGxlcjtcbiAgICBjb25zdCB7IGxhYmVsICwgdmFsdWUgIH0gPSBjb250cm9sbGVyLmdldExhYmVsQW5kVmFsdWUoaW5kZXgpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGNoYXJ0LFxuICAgICAgICBsYWJlbCxcbiAgICAgICAgcGFyc2VkOiBjb250cm9sbGVyLmdldFBhcnNlZChpbmRleCksXG4gICAgICAgIHJhdzogY2hhcnQuZGF0YS5kYXRhc2V0c1tkYXRhc2V0SW5kZXhdLmRhdGFbaW5kZXhdLFxuICAgICAgICBmb3JtYXR0ZWRWYWx1ZTogdmFsdWUsXG4gICAgICAgIGRhdGFzZXQ6IGNvbnRyb2xsZXIuZ2V0RGF0YXNldCgpLFxuICAgICAgICBkYXRhSW5kZXg6IGluZGV4LFxuICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgIGVsZW1lbnRcbiAgICB9O1xufVxuIGZ1bmN0aW9uIGdldFRvb2x0aXBTaXplKHRvb2x0aXAsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBjdHggPSB0b29sdGlwLmNoYXJ0LmN0eDtcbiAgICBjb25zdCB7IGJvZHkgLCBmb290ZXIgLCB0aXRsZSAgfSA9IHRvb2x0aXA7XG4gICAgY29uc3QgeyBib3hXaWR0aCAsIGJveEhlaWdodCAgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgYm9keUZvbnQgPSB0b0ZvbnQob3B0aW9ucy5ib2R5Rm9udCk7XG4gICAgY29uc3QgdGl0bGVGb250ID0gdG9Gb250KG9wdGlvbnMudGl0bGVGb250KTtcbiAgICBjb25zdCBmb290ZXJGb250ID0gdG9Gb250KG9wdGlvbnMuZm9vdGVyRm9udCk7XG4gICAgY29uc3QgdGl0bGVMaW5lQ291bnQgPSB0aXRsZS5sZW5ndGg7XG4gICAgY29uc3QgZm9vdGVyTGluZUNvdW50ID0gZm9vdGVyLmxlbmd0aDtcbiAgICBjb25zdCBib2R5TGluZUl0ZW1Db3VudCA9IGJvZHkubGVuZ3RoO1xuICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcob3B0aW9ucy5wYWRkaW5nKTtcbiAgICBsZXQgaGVpZ2h0ID0gcGFkZGluZy5oZWlnaHQ7XG4gICAgbGV0IHdpZHRoID0gMDtcbiAgICBsZXQgY29tYmluZWRCb2R5TGVuZ3RoID0gYm9keS5yZWR1Y2UoKGNvdW50LCBib2R5SXRlbSk9PmNvdW50ICsgYm9keUl0ZW0uYmVmb3JlLmxlbmd0aCArIGJvZHlJdGVtLmxpbmVzLmxlbmd0aCArIGJvZHlJdGVtLmFmdGVyLmxlbmd0aCwgMCk7XG4gICAgY29tYmluZWRCb2R5TGVuZ3RoICs9IHRvb2x0aXAuYmVmb3JlQm9keS5sZW5ndGggKyB0b29sdGlwLmFmdGVyQm9keS5sZW5ndGg7XG4gICAgaWYgKHRpdGxlTGluZUNvdW50KSB7XG4gICAgICAgIGhlaWdodCArPSB0aXRsZUxpbmVDb3VudCAqIHRpdGxlRm9udC5saW5lSGVpZ2h0ICsgKHRpdGxlTGluZUNvdW50IC0gMSkgKiBvcHRpb25zLnRpdGxlU3BhY2luZyArIG9wdGlvbnMudGl0bGVNYXJnaW5Cb3R0b207XG4gICAgfVxuICAgIGlmIChjb21iaW5lZEJvZHlMZW5ndGgpIHtcbiAgICAgICAgY29uc3QgYm9keUxpbmVIZWlnaHQgPSBvcHRpb25zLmRpc3BsYXlDb2xvcnMgPyBNYXRoLm1heChib3hIZWlnaHQsIGJvZHlGb250LmxpbmVIZWlnaHQpIDogYm9keUZvbnQubGluZUhlaWdodDtcbiAgICAgICAgaGVpZ2h0ICs9IGJvZHlMaW5lSXRlbUNvdW50ICogYm9keUxpbmVIZWlnaHQgKyAoY29tYmluZWRCb2R5TGVuZ3RoIC0gYm9keUxpbmVJdGVtQ291bnQpICogYm9keUZvbnQubGluZUhlaWdodCArIChjb21iaW5lZEJvZHlMZW5ndGggLSAxKSAqIG9wdGlvbnMuYm9keVNwYWNpbmc7XG4gICAgfVxuICAgIGlmIChmb290ZXJMaW5lQ291bnQpIHtcbiAgICAgICAgaGVpZ2h0ICs9IG9wdGlvbnMuZm9vdGVyTWFyZ2luVG9wICsgZm9vdGVyTGluZUNvdW50ICogZm9vdGVyRm9udC5saW5lSGVpZ2h0ICsgKGZvb3RlckxpbmVDb3VudCAtIDEpICogb3B0aW9ucy5mb290ZXJTcGFjaW5nO1xuICAgIH1cbiAgICBsZXQgd2lkdGhQYWRkaW5nID0gMDtcbiAgICBjb25zdCBtYXhMaW5lV2lkdGggPSBmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgIHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGN0eC5tZWFzdXJlVGV4dChsaW5lKS53aWR0aCArIHdpZHRoUGFkZGluZyk7XG4gICAgfTtcbiAgICBjdHguc2F2ZSgpO1xuICAgIGN0eC5mb250ID0gdGl0bGVGb250LnN0cmluZztcbiAgICBlYWNoKHRvb2x0aXAudGl0bGUsIG1heExpbmVXaWR0aCk7XG4gICAgY3R4LmZvbnQgPSBib2R5Rm9udC5zdHJpbmc7XG4gICAgZWFjaCh0b29sdGlwLmJlZm9yZUJvZHkuY29uY2F0KHRvb2x0aXAuYWZ0ZXJCb2R5KSwgbWF4TGluZVdpZHRoKTtcbiAgICB3aWR0aFBhZGRpbmcgPSBvcHRpb25zLmRpc3BsYXlDb2xvcnMgPyBib3hXaWR0aCArIDIgKyBvcHRpb25zLmJveFBhZGRpbmcgOiAwO1xuICAgIGVhY2goYm9keSwgKGJvZHlJdGVtKT0+e1xuICAgICAgICBlYWNoKGJvZHlJdGVtLmJlZm9yZSwgbWF4TGluZVdpZHRoKTtcbiAgICAgICAgZWFjaChib2R5SXRlbS5saW5lcywgbWF4TGluZVdpZHRoKTtcbiAgICAgICAgZWFjaChib2R5SXRlbS5hZnRlciwgbWF4TGluZVdpZHRoKTtcbiAgICB9KTtcbiAgICB3aWR0aFBhZGRpbmcgPSAwO1xuICAgIGN0eC5mb250ID0gZm9vdGVyRm9udC5zdHJpbmc7XG4gICAgZWFjaCh0b29sdGlwLmZvb3RlciwgbWF4TGluZVdpZHRoKTtcbiAgICBjdHgucmVzdG9yZSgpO1xuICAgIHdpZHRoICs9IHBhZGRpbmcud2lkdGg7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodFxuICAgIH07XG59XG5mdW5jdGlvbiBkZXRlcm1pbmVZQWxpZ24oY2hhcnQsIHNpemUpIHtcbiAgICBjb25zdCB7IHkgLCBoZWlnaHQgIH0gPSBzaXplO1xuICAgIGlmICh5IDwgaGVpZ2h0IC8gMikge1xuICAgICAgICByZXR1cm4gJ3RvcCc7XG4gICAgfSBlbHNlIGlmICh5ID4gY2hhcnQuaGVpZ2h0IC0gaGVpZ2h0IC8gMikge1xuICAgICAgICByZXR1cm4gJ2JvdHRvbSc7XG4gICAgfVxuICAgIHJldHVybiAnY2VudGVyJztcbn1cbmZ1bmN0aW9uIGRvZXNOb3RGaXRXaXRoQWxpZ24oeEFsaWduLCBjaGFydCwgb3B0aW9ucywgc2l6ZSkge1xuICAgIGNvbnN0IHsgeCAsIHdpZHRoICB9ID0gc2l6ZTtcbiAgICBjb25zdCBjYXJldCA9IG9wdGlvbnMuY2FyZXRTaXplICsgb3B0aW9ucy5jYXJldFBhZGRpbmc7XG4gICAgaWYgKHhBbGlnbiA9PT0gJ2xlZnQnICYmIHggKyB3aWR0aCArIGNhcmV0ID4gY2hhcnQud2lkdGgpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh4QWxpZ24gPT09ICdyaWdodCcgJiYgeCAtIHdpZHRoIC0gY2FyZXQgPCAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGRldGVybWluZVhBbGlnbihjaGFydCwgb3B0aW9ucywgc2l6ZSwgeUFsaWduKSB7XG4gICAgY29uc3QgeyB4ICwgd2lkdGggIH0gPSBzaXplO1xuICAgIGNvbnN0IHsgd2lkdGg6IGNoYXJ0V2lkdGggLCBjaGFydEFyZWE6IHsgbGVmdCAsIHJpZ2h0ICB9ICB9ID0gY2hhcnQ7XG4gICAgbGV0IHhBbGlnbiA9ICdjZW50ZXInO1xuICAgIGlmICh5QWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgIHhBbGlnbiA9IHggPD0gKGxlZnQgKyByaWdodCkgLyAyID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgICB9IGVsc2UgaWYgKHggPD0gd2lkdGggLyAyKSB7XG4gICAgICAgIHhBbGlnbiA9ICdsZWZ0JztcbiAgICB9IGVsc2UgaWYgKHggPj0gY2hhcnRXaWR0aCAtIHdpZHRoIC8gMikge1xuICAgICAgICB4QWxpZ24gPSAncmlnaHQnO1xuICAgIH1cbiAgICBpZiAoZG9lc05vdEZpdFdpdGhBbGlnbih4QWxpZ24sIGNoYXJ0LCBvcHRpb25zLCBzaXplKSkge1xuICAgICAgICB4QWxpZ24gPSAnY2VudGVyJztcbiAgICB9XG4gICAgcmV0dXJuIHhBbGlnbjtcbn1cbiBmdW5jdGlvbiBkZXRlcm1pbmVBbGlnbm1lbnQoY2hhcnQsIG9wdGlvbnMsIHNpemUpIHtcbiAgICBjb25zdCB5QWxpZ24gPSBzaXplLnlBbGlnbiB8fCBvcHRpb25zLnlBbGlnbiB8fCBkZXRlcm1pbmVZQWxpZ24oY2hhcnQsIHNpemUpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHhBbGlnbjogc2l6ZS54QWxpZ24gfHwgb3B0aW9ucy54QWxpZ24gfHwgZGV0ZXJtaW5lWEFsaWduKGNoYXJ0LCBvcHRpb25zLCBzaXplLCB5QWxpZ24pLFxuICAgICAgICB5QWxpZ25cbiAgICB9O1xufVxuZnVuY3Rpb24gYWxpZ25YKHNpemUsIHhBbGlnbikge1xuICAgIGxldCB7IHggLCB3aWR0aCAgfSA9IHNpemU7XG4gICAgaWYgKHhBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICB4IC09IHdpZHRoO1xuICAgIH0gZWxzZSBpZiAoeEFsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICB4IC09IHdpZHRoIC8gMjtcbiAgICB9XG4gICAgcmV0dXJuIHg7XG59XG5mdW5jdGlvbiBhbGlnblkoc2l6ZSwgeUFsaWduLCBwYWRkaW5nQW5kU2l6ZSkge1xuICAgIGxldCB7IHkgLCBoZWlnaHQgIH0gPSBzaXplO1xuICAgIGlmICh5QWxpZ24gPT09ICd0b3AnKSB7XG4gICAgICAgIHkgKz0gcGFkZGluZ0FuZFNpemU7XG4gICAgfSBlbHNlIGlmICh5QWxpZ24gPT09ICdib3R0b20nKSB7XG4gICAgICAgIHkgLT0gaGVpZ2h0ICsgcGFkZGluZ0FuZFNpemU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgeSAtPSBoZWlnaHQgLyAyO1xuICAgIH1cbiAgICByZXR1cm4geTtcbn1cbiBmdW5jdGlvbiBnZXRCYWNrZ3JvdW5kUG9pbnQob3B0aW9ucywgc2l6ZSwgYWxpZ25tZW50LCBjaGFydCkge1xuICAgIGNvbnN0IHsgY2FyZXRTaXplICwgY2FyZXRQYWRkaW5nICwgY29ybmVyUmFkaXVzICB9ID0gb3B0aW9ucztcbiAgICBjb25zdCB7IHhBbGlnbiAsIHlBbGlnbiAgfSA9IGFsaWdubWVudDtcbiAgICBjb25zdCBwYWRkaW5nQW5kU2l6ZSA9IGNhcmV0U2l6ZSArIGNhcmV0UGFkZGluZztcbiAgICBjb25zdCB7IHRvcExlZnQgLCB0b3BSaWdodCAsIGJvdHRvbUxlZnQgLCBib3R0b21SaWdodCAgfSA9IHRvVFJCTENvcm5lcnMoY29ybmVyUmFkaXVzKTtcbiAgICBsZXQgeCA9IGFsaWduWChzaXplLCB4QWxpZ24pO1xuICAgIGNvbnN0IHkgPSBhbGlnblkoc2l6ZSwgeUFsaWduLCBwYWRkaW5nQW5kU2l6ZSk7XG4gICAgaWYgKHlBbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgaWYgKHhBbGlnbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICB4ICs9IHBhZGRpbmdBbmRTaXplO1xuICAgICAgICB9IGVsc2UgaWYgKHhBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgeCAtPSBwYWRkaW5nQW5kU2l6ZTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAoeEFsaWduID09PSAnbGVmdCcpIHtcbiAgICAgICAgeCAtPSBNYXRoLm1heCh0b3BMZWZ0LCBib3R0b21MZWZ0KSArIGNhcmV0U2l6ZTtcbiAgICB9IGVsc2UgaWYgKHhBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICB4ICs9IE1hdGgubWF4KHRvcFJpZ2h0LCBib3R0b21SaWdodCkgKyBjYXJldFNpemU7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHg6IF9saW1pdFZhbHVlKHgsIDAsIGNoYXJ0LndpZHRoIC0gc2l6ZS53aWR0aCksXG4gICAgICAgIHk6IF9saW1pdFZhbHVlKHksIDAsIGNoYXJ0LmhlaWdodCAtIHNpemUuaGVpZ2h0KVxuICAgIH07XG59XG5mdW5jdGlvbiBnZXRBbGlnbmVkWCh0b29sdGlwLCBhbGlnbiwgb3B0aW9ucykge1xuICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcob3B0aW9ucy5wYWRkaW5nKTtcbiAgICByZXR1cm4gYWxpZ24gPT09ICdjZW50ZXInID8gdG9vbHRpcC54ICsgdG9vbHRpcC53aWR0aCAvIDIgOiBhbGlnbiA9PT0gJ3JpZ2h0JyA/IHRvb2x0aXAueCArIHRvb2x0aXAud2lkdGggLSBwYWRkaW5nLnJpZ2h0IDogdG9vbHRpcC54ICsgcGFkZGluZy5sZWZ0O1xufVxuIGZ1bmN0aW9uIGdldEJlZm9yZUFmdGVyQm9keUxpbmVzKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIHB1c2hPckNvbmNhdChbXSwgc3BsaXROZXdsaW5lcyhjYWxsYmFjaykpO1xufVxuZnVuY3Rpb24gY3JlYXRlVG9vbHRpcENvbnRleHQocGFyZW50LCB0b29sdGlwLCB0b29sdGlwSXRlbXMpIHtcbiAgICByZXR1cm4gY3JlYXRlQ29udGV4dChwYXJlbnQsIHtcbiAgICAgICAgdG9vbHRpcCxcbiAgICAgICAgdG9vbHRpcEl0ZW1zLFxuICAgICAgICB0eXBlOiAndG9vbHRpcCdcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIG92ZXJyaWRlQ2FsbGJhY2tzKGNhbGxiYWNrcywgY29udGV4dCkge1xuICAgIGNvbnN0IG92ZXJyaWRlID0gY29udGV4dCAmJiBjb250ZXh0LmRhdGFzZXQgJiYgY29udGV4dC5kYXRhc2V0LnRvb2x0aXAgJiYgY29udGV4dC5kYXRhc2V0LnRvb2x0aXAuY2FsbGJhY2tzO1xuICAgIHJldHVybiBvdmVycmlkZSA/IGNhbGxiYWNrcy5vdmVycmlkZShvdmVycmlkZSkgOiBjYWxsYmFja3M7XG59XG5jb25zdCBkZWZhdWx0Q2FsbGJhY2tzID0ge1xuICAgIGJlZm9yZVRpdGxlOiBub29wLFxuICAgIHRpdGxlICh0b29sdGlwSXRlbXMpIHtcbiAgICAgICAgaWYgKHRvb2x0aXBJdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBpdGVtID0gdG9vbHRpcEl0ZW1zWzBdO1xuICAgICAgICAgICAgY29uc3QgbGFiZWxzID0gaXRlbS5jaGFydC5kYXRhLmxhYmVscztcbiAgICAgICAgICAgIGNvbnN0IGxhYmVsQ291bnQgPSBsYWJlbHMgPyBsYWJlbHMubGVuZ3RoIDogMDtcbiAgICAgICAgICAgIGlmICh0aGlzICYmIHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMubW9kZSA9PT0gJ2RhdGFzZXQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0uZGF0YXNldC5sYWJlbCB8fCAnJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXRlbS5sYWJlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpdGVtLmxhYmVsO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYWJlbENvdW50ID4gMCAmJiBpdGVtLmRhdGFJbmRleCA8IGxhYmVsQ291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFiZWxzW2l0ZW0uZGF0YUluZGV4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfSxcbiAgICBhZnRlclRpdGxlOiBub29wLFxuICAgIGJlZm9yZUJvZHk6IG5vb3AsXG4gICAgYmVmb3JlTGFiZWw6IG5vb3AsXG4gICAgbGFiZWwgKHRvb2x0aXBJdGVtKSB7XG4gICAgICAgIGlmICh0aGlzICYmIHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMubW9kZSA9PT0gJ2RhdGFzZXQnKSB7XG4gICAgICAgICAgICByZXR1cm4gdG9vbHRpcEl0ZW0ubGFiZWwgKyAnOiAnICsgdG9vbHRpcEl0ZW0uZm9ybWF0dGVkVmFsdWUgfHwgdG9vbHRpcEl0ZW0uZm9ybWF0dGVkVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGxhYmVsID0gdG9vbHRpcEl0ZW0uZGF0YXNldC5sYWJlbCB8fCAnJztcbiAgICAgICAgaWYgKGxhYmVsKSB7XG4gICAgICAgICAgICBsYWJlbCArPSAnOiAnO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdG9vbHRpcEl0ZW0uZm9ybWF0dGVkVmFsdWU7XG4gICAgICAgIGlmICghaXNOdWxsT3JVbmRlZih2YWx1ZSkpIHtcbiAgICAgICAgICAgIGxhYmVsICs9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsYWJlbDtcbiAgICB9LFxuICAgIGxhYmVsQ29sb3IgKHRvb2x0aXBJdGVtKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0b29sdGlwSXRlbS5jaGFydC5nZXREYXRhc2V0TWV0YSh0b29sdGlwSXRlbS5kYXRhc2V0SW5kZXgpO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gbWV0YS5jb250cm9sbGVyLmdldFN0eWxlKHRvb2x0aXBJdGVtLmRhdGFJbmRleCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBib3JkZXJDb2xvcjogb3B0aW9ucy5ib3JkZXJDb2xvcixcbiAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogb3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICBib3JkZXJXaWR0aDogb3B0aW9ucy5ib3JkZXJXaWR0aCxcbiAgICAgICAgICAgIGJvcmRlckRhc2g6IG9wdGlvbnMuYm9yZGVyRGFzaCxcbiAgICAgICAgICAgIGJvcmRlckRhc2hPZmZzZXQ6IG9wdGlvbnMuYm9yZGVyRGFzaE9mZnNldCxcbiAgICAgICAgICAgIGJvcmRlclJhZGl1czogMFxuICAgICAgICB9O1xuICAgIH0sXG4gICAgbGFiZWxUZXh0Q29sb3IgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmJvZHlDb2xvcjtcbiAgICB9LFxuICAgIGxhYmVsUG9pbnRTdHlsZSAodG9vbHRpcEl0ZW0pIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRvb2x0aXBJdGVtLmNoYXJ0LmdldERhdGFzZXRNZXRhKHRvb2x0aXBJdGVtLmRhdGFzZXRJbmRleCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSBtZXRhLmNvbnRyb2xsZXIuZ2V0U3R5bGUodG9vbHRpcEl0ZW0uZGF0YUluZGV4KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHBvaW50U3R5bGU6IG9wdGlvbnMucG9pbnRTdHlsZSxcbiAgICAgICAgICAgIHJvdGF0aW9uOiBvcHRpb25zLnJvdGF0aW9uXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBhZnRlckxhYmVsOiBub29wLFxuICAgIGFmdGVyQm9keTogbm9vcCxcbiAgICBiZWZvcmVGb290ZXI6IG5vb3AsXG4gICAgZm9vdGVyOiBub29wLFxuICAgIGFmdGVyRm9vdGVyOiBub29wXG59O1xuIGZ1bmN0aW9uIGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKGNhbGxiYWNrcywgbmFtZSwgY3R4LCBhcmcpIHtcbiAgICBjb25zdCByZXN1bHQgPSBjYWxsYmFja3NbbmFtZV0uY2FsbChjdHgsIGFyZyk7XG4gICAgaWYgKHR5cGVvZiByZXN1bHQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0Q2FsbGJhY2tzW25hbWVdLmNhbGwoY3R4LCBhcmcpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuY2xhc3MgVG9vbHRpcCBleHRlbmRzIEVsZW1lbnQge1xuIHN0YXRpYyBwb3NpdGlvbmVycyA9IHBvc2l0aW9uZXJzO1xuICAgIGNvbnN0cnVjdG9yKGNvbmZpZyl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMub3BhY2l0eSA9IDA7XG4gICAgICAgIHRoaXMuX2FjdGl2ZSA9IFtdO1xuICAgICAgICB0aGlzLl9ldmVudFBvc2l0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9zaXplID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9jYWNoZWRBbmltYXRpb25zID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl90b29sdGlwSXRlbXMgPSBbXTtcbiAgICAgICAgdGhpcy4kYW5pbWF0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5jaGFydCA9IGNvbmZpZy5jaGFydDtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gY29uZmlnLm9wdGlvbnM7XG4gICAgICAgIHRoaXMuZGF0YVBvaW50cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy50aXRsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5iZWZvcmVCb2R5ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmJvZHkgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuYWZ0ZXJCb2R5ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmZvb3RlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy54QWxpZ24gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMueUFsaWduID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMueSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMud2lkdGggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuY2FyZXRYID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmNhcmV0WSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5sYWJlbENvbG9ycyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5sYWJlbFBvaW50U3R5bGVzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmxhYmVsVGV4dENvbG9ycyA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaW5pdGlhbGl6ZShvcHRpb25zKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgIHRoaXMuX2NhY2hlZEFuaW1hdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuJGNvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgfVxuIF9yZXNvbHZlQW5pbWF0aW9ucygpIHtcbiAgICAgICAgY29uc3QgY2FjaGVkID0gdGhpcy5fY2FjaGVkQW5pbWF0aW9ucztcbiAgICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoKSk7XG4gICAgICAgIGNvbnN0IG9wdHMgPSBvcHRpb25zLmVuYWJsZWQgJiYgY2hhcnQub3B0aW9ucy5hbmltYXRpb24gJiYgb3B0aW9ucy5hbmltYXRpb25zO1xuICAgICAgICBjb25zdCBhbmltYXRpb25zID0gbmV3IEFuaW1hdGlvbnModGhpcy5jaGFydCwgb3B0cyk7XG4gICAgICAgIGlmIChvcHRzLl9jYWNoZWFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuX2NhY2hlZEFuaW1hdGlvbnMgPSBPYmplY3QuZnJlZXplKGFuaW1hdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhbmltYXRpb25zO1xuICAgIH1cbiBnZXRDb250ZXh0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kY29udGV4dCB8fCAodGhpcy4kY29udGV4dCA9IGNyZWF0ZVRvb2x0aXBDb250ZXh0KHRoaXMuY2hhcnQuZ2V0Q29udGV4dCgpLCB0aGlzLCB0aGlzLl90b29sdGlwSXRlbXMpKTtcbiAgICB9XG4gICAgZ2V0VGl0bGUoY29udGV4dCwgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB7IGNhbGxiYWNrcyAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGJlZm9yZVRpdGxlID0gaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soY2FsbGJhY2tzLCAnYmVmb3JlVGl0bGUnLCB0aGlzLCBjb250ZXh0KTtcbiAgICAgICAgY29uc3QgdGl0bGUgPSBpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhjYWxsYmFja3MsICd0aXRsZScsIHRoaXMsIGNvbnRleHQpO1xuICAgICAgICBjb25zdCBhZnRlclRpdGxlID0gaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soY2FsbGJhY2tzLCAnYWZ0ZXJUaXRsZScsIHRoaXMsIGNvbnRleHQpO1xuICAgICAgICBsZXQgbGluZXMgPSBbXTtcbiAgICAgICAgbGluZXMgPSBwdXNoT3JDb25jYXQobGluZXMsIHNwbGl0TmV3bGluZXMoYmVmb3JlVGl0bGUpKTtcbiAgICAgICAgbGluZXMgPSBwdXNoT3JDb25jYXQobGluZXMsIHNwbGl0TmV3bGluZXModGl0bGUpKTtcbiAgICAgICAgbGluZXMgPSBwdXNoT3JDb25jYXQobGluZXMsIHNwbGl0TmV3bGluZXMoYWZ0ZXJUaXRsZSkpO1xuICAgICAgICByZXR1cm4gbGluZXM7XG4gICAgfVxuICAgIGdldEJlZm9yZUJvZHkodG9vbHRpcEl0ZW1zLCBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiBnZXRCZWZvcmVBZnRlckJvZHlMaW5lcyhpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhvcHRpb25zLmNhbGxiYWNrcywgJ2JlZm9yZUJvZHknLCB0aGlzLCB0b29sdGlwSXRlbXMpKTtcbiAgICB9XG4gICAgZ2V0Qm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgeyBjYWxsYmFja3MgIH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBib2R5SXRlbXMgPSBbXTtcbiAgICAgICAgZWFjaCh0b29sdGlwSXRlbXMsIChjb250ZXh0KT0+e1xuICAgICAgICAgICAgY29uc3QgYm9keUl0ZW0gPSB7XG4gICAgICAgICAgICAgICAgYmVmb3JlOiBbXSxcbiAgICAgICAgICAgICAgICBsaW5lczogW10sXG4gICAgICAgICAgICAgICAgYWZ0ZXI6IFtdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc2NvcGVkID0gb3ZlcnJpZGVDYWxsYmFja3MoY2FsbGJhY2tzLCBjb250ZXh0KTtcbiAgICAgICAgICAgIHB1c2hPckNvbmNhdChib2R5SXRlbS5iZWZvcmUsIHNwbGl0TmV3bGluZXMoaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soc2NvcGVkLCAnYmVmb3JlTGFiZWwnLCB0aGlzLCBjb250ZXh0KSkpO1xuICAgICAgICAgICAgcHVzaE9yQ29uY2F0KGJvZHlJdGVtLmxpbmVzLCBpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhzY29wZWQsICdsYWJlbCcsIHRoaXMsIGNvbnRleHQpKTtcbiAgICAgICAgICAgIHB1c2hPckNvbmNhdChib2R5SXRlbS5hZnRlciwgc3BsaXROZXdsaW5lcyhpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhzY29wZWQsICdhZnRlckxhYmVsJywgdGhpcywgY29udGV4dCkpKTtcbiAgICAgICAgICAgIGJvZHlJdGVtcy5wdXNoKGJvZHlJdGVtKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBib2R5SXRlbXM7XG4gICAgfVxuICAgIGdldEFmdGVyQm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJlZm9yZUFmdGVyQm9keUxpbmVzKGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKG9wdGlvbnMuY2FsbGJhY2tzLCAnYWZ0ZXJCb2R5JywgdGhpcywgdG9vbHRpcEl0ZW1zKSk7XG4gICAgfVxuICAgIGdldEZvb3Rlcih0b29sdGlwSXRlbXMsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgeyBjYWxsYmFja3MgIH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBiZWZvcmVGb290ZXIgPSBpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhjYWxsYmFja3MsICdiZWZvcmVGb290ZXInLCB0aGlzLCB0b29sdGlwSXRlbXMpO1xuICAgICAgICBjb25zdCBmb290ZXIgPSBpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhjYWxsYmFja3MsICdmb290ZXInLCB0aGlzLCB0b29sdGlwSXRlbXMpO1xuICAgICAgICBjb25zdCBhZnRlckZvb3RlciA9IGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKGNhbGxiYWNrcywgJ2FmdGVyRm9vdGVyJywgdGhpcywgdG9vbHRpcEl0ZW1zKTtcbiAgICAgICAgbGV0IGxpbmVzID0gW107XG4gICAgICAgIGxpbmVzID0gcHVzaE9yQ29uY2F0KGxpbmVzLCBzcGxpdE5ld2xpbmVzKGJlZm9yZUZvb3RlcikpO1xuICAgICAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyhmb290ZXIpKTtcbiAgICAgICAgbGluZXMgPSBwdXNoT3JDb25jYXQobGluZXMsIHNwbGl0TmV3bGluZXMoYWZ0ZXJGb290ZXIpKTtcbiAgICAgICAgcmV0dXJuIGxpbmVzO1xuICAgIH1cbiBfY3JlYXRlSXRlbXMob3B0aW9ucykge1xuICAgICAgICBjb25zdCBhY3RpdmUgPSB0aGlzLl9hY3RpdmU7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmNoYXJ0LmRhdGE7XG4gICAgICAgIGNvbnN0IGxhYmVsQ29sb3JzID0gW107XG4gICAgICAgIGNvbnN0IGxhYmVsUG9pbnRTdHlsZXMgPSBbXTtcbiAgICAgICAgY29uc3QgbGFiZWxUZXh0Q29sb3JzID0gW107XG4gICAgICAgIGxldCB0b29sdGlwSXRlbXMgPSBbXTtcbiAgICAgICAgbGV0IGksIGxlbjtcbiAgICAgICAgZm9yKGkgPSAwLCBsZW4gPSBhY3RpdmUubGVuZ3RoOyBpIDwgbGVuOyArK2kpe1xuICAgICAgICAgICAgdG9vbHRpcEl0ZW1zLnB1c2goY3JlYXRlVG9vbHRpcEl0ZW0odGhpcy5jaGFydCwgYWN0aXZlW2ldKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuZmlsdGVyKSB7XG4gICAgICAgICAgICB0b29sdGlwSXRlbXMgPSB0b29sdGlwSXRlbXMuZmlsdGVyKChlbGVtZW50LCBpbmRleCwgYXJyYXkpPT5vcHRpb25zLmZpbHRlcihlbGVtZW50LCBpbmRleCwgYXJyYXksIGRhdGEpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5pdGVtU29ydCkge1xuICAgICAgICAgICAgdG9vbHRpcEl0ZW1zID0gdG9vbHRpcEl0ZW1zLnNvcnQoKGEsIGIpPT5vcHRpb25zLml0ZW1Tb3J0KGEsIGIsIGRhdGEpKTtcbiAgICAgICAgfVxuICAgICAgICBlYWNoKHRvb2x0aXBJdGVtcywgKGNvbnRleHQpPT57XG4gICAgICAgICAgICBjb25zdCBzY29wZWQgPSBvdmVycmlkZUNhbGxiYWNrcyhvcHRpb25zLmNhbGxiYWNrcywgY29udGV4dCk7XG4gICAgICAgICAgICBsYWJlbENvbG9ycy5wdXNoKGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKHNjb3BlZCwgJ2xhYmVsQ29sb3InLCB0aGlzLCBjb250ZXh0KSk7XG4gICAgICAgICAgICBsYWJlbFBvaW50U3R5bGVzLnB1c2goaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soc2NvcGVkLCAnbGFiZWxQb2ludFN0eWxlJywgdGhpcywgY29udGV4dCkpO1xuICAgICAgICAgICAgbGFiZWxUZXh0Q29sb3JzLnB1c2goaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soc2NvcGVkLCAnbGFiZWxUZXh0Q29sb3InLCB0aGlzLCBjb250ZXh0KSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmxhYmVsQ29sb3JzID0gbGFiZWxDb2xvcnM7XG4gICAgICAgIHRoaXMubGFiZWxQb2ludFN0eWxlcyA9IGxhYmVsUG9pbnRTdHlsZXM7XG4gICAgICAgIHRoaXMubGFiZWxUZXh0Q29sb3JzID0gbGFiZWxUZXh0Q29sb3JzO1xuICAgICAgICB0aGlzLmRhdGFQb2ludHMgPSB0b29sdGlwSXRlbXM7XG4gICAgICAgIHJldHVybiB0b29sdGlwSXRlbXM7XG4gICAgfVxuICAgIHVwZGF0ZShjaGFuZ2VkLCByZXBsYXkpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucy5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgY29uc3QgYWN0aXZlID0gdGhpcy5fYWN0aXZlO1xuICAgICAgICBsZXQgcHJvcGVydGllcztcbiAgICAgICAgbGV0IHRvb2x0aXBJdGVtcyA9IFtdO1xuICAgICAgICBpZiAoIWFjdGl2ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm9wYWNpdHkgIT09IDApIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gcG9zaXRpb25lcnNbb3B0aW9ucy5wb3NpdGlvbl0uY2FsbCh0aGlzLCBhY3RpdmUsIHRoaXMuX2V2ZW50UG9zaXRpb24pO1xuICAgICAgICAgICAgdG9vbHRpcEl0ZW1zID0gdGhpcy5fY3JlYXRlSXRlbXMob3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLnRpdGxlID0gdGhpcy5nZXRUaXRsZSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5iZWZvcmVCb2R5ID0gdGhpcy5nZXRCZWZvcmVCb2R5KHRvb2x0aXBJdGVtcywgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmJvZHkgPSB0aGlzLmdldEJvZHkodG9vbHRpcEl0ZW1zLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMuYWZ0ZXJCb2R5ID0gdGhpcy5nZXRBZnRlckJvZHkodG9vbHRpcEl0ZW1zLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMuZm9vdGVyID0gdGhpcy5nZXRGb290ZXIodG9vbHRpcEl0ZW1zLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLl9zaXplID0gZ2V0VG9vbHRpcFNpemUodGhpcywgb3B0aW9ucyk7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbkFuZFNpemUgPSBPYmplY3QuYXNzaWduKHt9LCBwb3NpdGlvbiwgc2l6ZSk7XG4gICAgICAgICAgICBjb25zdCBhbGlnbm1lbnQgPSBkZXRlcm1pbmVBbGlnbm1lbnQodGhpcy5jaGFydCwgb3B0aW9ucywgcG9zaXRpb25BbmRTaXplKTtcbiAgICAgICAgICAgIGNvbnN0IGJhY2tncm91bmRQb2ludCA9IGdldEJhY2tncm91bmRQb2ludChvcHRpb25zLCBwb3NpdGlvbkFuZFNpemUsIGFsaWdubWVudCwgdGhpcy5jaGFydCk7XG4gICAgICAgICAgICB0aGlzLnhBbGlnbiA9IGFsaWdubWVudC54QWxpZ247XG4gICAgICAgICAgICB0aGlzLnlBbGlnbiA9IGFsaWdubWVudC55QWxpZ247XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICAgICAgeDogYmFja2dyb3VuZFBvaW50LngsXG4gICAgICAgICAgICAgICAgeTogYmFja2dyb3VuZFBvaW50LnksXG4gICAgICAgICAgICAgICAgd2lkdGg6IHNpemUud2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBzaXplLmhlaWdodCxcbiAgICAgICAgICAgICAgICBjYXJldFg6IHBvc2l0aW9uLngsXG4gICAgICAgICAgICAgICAgY2FyZXRZOiBwb3NpdGlvbi55XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3Rvb2x0aXBJdGVtcyA9IHRvb2x0aXBJdGVtcztcbiAgICAgICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXMuX3Jlc29sdmVBbmltYXRpb25zKCkudXBkYXRlKHRoaXMsIHByb3BlcnRpZXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFuZ2VkICYmIG9wdGlvbnMuZXh0ZXJuYWwpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuZXh0ZXJuYWwuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgY2hhcnQ6IHRoaXMuY2hhcnQsXG4gICAgICAgICAgICAgICAgdG9vbHRpcDogdGhpcyxcbiAgICAgICAgICAgICAgICByZXBsYXlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGRyYXdDYXJldCh0b29sdGlwUG9pbnQsIGN0eCwgc2l6ZSwgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBjYXJldFBvc2l0aW9uID0gdGhpcy5nZXRDYXJldFBvc2l0aW9uKHRvb2x0aXBQb2ludCwgc2l6ZSwgb3B0aW9ucyk7XG4gICAgICAgIGN0eC5saW5lVG8oY2FyZXRQb3NpdGlvbi54MSwgY2FyZXRQb3NpdGlvbi55MSk7XG4gICAgICAgIGN0eC5saW5lVG8oY2FyZXRQb3NpdGlvbi54MiwgY2FyZXRQb3NpdGlvbi55Mik7XG4gICAgICAgIGN0eC5saW5lVG8oY2FyZXRQb3NpdGlvbi54MywgY2FyZXRQb3NpdGlvbi55Myk7XG4gICAgfVxuICAgIGdldENhcmV0UG9zaXRpb24odG9vbHRpcFBvaW50LCBzaXplLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHsgeEFsaWduICwgeUFsaWduICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgeyBjYXJldFNpemUgLCBjb3JuZXJSYWRpdXMgIH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCB7IHRvcExlZnQgLCB0b3BSaWdodCAsIGJvdHRvbUxlZnQgLCBib3R0b21SaWdodCAgfSA9IHRvVFJCTENvcm5lcnMoY29ybmVyUmFkaXVzKTtcbiAgICAgICAgY29uc3QgeyB4OiBwdFggLCB5OiBwdFkgIH0gPSB0b29sdGlwUG9pbnQ7XG4gICAgICAgIGNvbnN0IHsgd2lkdGggLCBoZWlnaHQgIH0gPSBzaXplO1xuICAgICAgICBsZXQgeDEsIHgyLCB4MywgeTEsIHkyLCB5MztcbiAgICAgICAgaWYgKHlBbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgIHkyID0gcHRZICsgaGVpZ2h0IC8gMjtcbiAgICAgICAgICAgIGlmICh4QWxpZ24gPT09ICdsZWZ0Jykge1xuICAgICAgICAgICAgICAgIHgxID0gcHRYO1xuICAgICAgICAgICAgICAgIHgyID0geDEgLSBjYXJldFNpemU7XG4gICAgICAgICAgICAgICAgeTEgPSB5MiArIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgICAgICB5MyA9IHkyIC0gY2FyZXRTaXplO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB4MSA9IHB0WCArIHdpZHRoO1xuICAgICAgICAgICAgICAgIHgyID0geDEgKyBjYXJldFNpemU7XG4gICAgICAgICAgICAgICAgeTEgPSB5MiAtIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgICAgICB5MyA9IHkyICsgY2FyZXRTaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeDMgPSB4MTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh4QWxpZ24gPT09ICdsZWZ0Jykge1xuICAgICAgICAgICAgICAgIHgyID0gcHRYICsgTWF0aC5tYXgodG9wTGVmdCwgYm90dG9tTGVmdCkgKyBjYXJldFNpemU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHhBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgICAgIHgyID0gcHRYICsgd2lkdGggLSBNYXRoLm1heCh0b3BSaWdodCwgYm90dG9tUmlnaHQpIC0gY2FyZXRTaXplO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB4MiA9IHRoaXMuY2FyZXRYO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHlBbGlnbiA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgICB5MSA9IHB0WTtcbiAgICAgICAgICAgICAgICB5MiA9IHkxIC0gY2FyZXRTaXplO1xuICAgICAgICAgICAgICAgIHgxID0geDIgLSBjYXJldFNpemU7XG4gICAgICAgICAgICAgICAgeDMgPSB4MiArIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeTEgPSBwdFkgKyBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgeTIgPSB5MSArIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgICAgICB4MSA9IHgyICsgY2FyZXRTaXplO1xuICAgICAgICAgICAgICAgIHgzID0geDIgLSBjYXJldFNpemU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB5MyA9IHkxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4MSxcbiAgICAgICAgICAgIHgyLFxuICAgICAgICAgICAgeDMsXG4gICAgICAgICAgICB5MSxcbiAgICAgICAgICAgIHkyLFxuICAgICAgICAgICAgeTNcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZHJhd1RpdGxlKHB0LCBjdHgsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgdGl0bGUgPSB0aGlzLnRpdGxlO1xuICAgICAgICBjb25zdCBsZW5ndGggPSB0aXRsZS5sZW5ndGg7XG4gICAgICAgIGxldCB0aXRsZUZvbnQsIHRpdGxlU3BhY2luZywgaTtcbiAgICAgICAgaWYgKGxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRpb25zLnJ0bCwgdGhpcy54LCB0aGlzLndpZHRoKTtcbiAgICAgICAgICAgIHB0LnggPSBnZXRBbGlnbmVkWCh0aGlzLCBvcHRpb25zLnRpdGxlQWxpZ24sIG9wdGlvbnMpO1xuICAgICAgICAgICAgY3R4LnRleHRBbGlnbiA9IHJ0bEhlbHBlci50ZXh0QWxpZ24ob3B0aW9ucy50aXRsZUFsaWduKTtcbiAgICAgICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgICAgICAgIHRpdGxlRm9udCA9IHRvRm9udChvcHRpb25zLnRpdGxlRm9udCk7XG4gICAgICAgICAgICB0aXRsZVNwYWNpbmcgPSBvcHRpb25zLnRpdGxlU3BhY2luZztcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLnRpdGxlQ29sb3I7XG4gICAgICAgICAgICBjdHguZm9udCA9IHRpdGxlRm9udC5zdHJpbmc7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSl7XG4gICAgICAgICAgICAgICAgY3R4LmZpbGxUZXh0KHRpdGxlW2ldLCBydGxIZWxwZXIueChwdC54KSwgcHQueSArIHRpdGxlRm9udC5saW5lSGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAgICAgcHQueSArPSB0aXRsZUZvbnQubGluZUhlaWdodCArIHRpdGxlU3BhY2luZztcbiAgICAgICAgICAgICAgICBpZiAoaSArIDEgPT09IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBwdC55ICs9IG9wdGlvbnMudGl0bGVNYXJnaW5Cb3R0b20gLSB0aXRsZVNwYWNpbmc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuIF9kcmF3Q29sb3JCb3goY3R4LCBwdCwgaSwgcnRsSGVscGVyLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGxhYmVsQ29sb3IgPSB0aGlzLmxhYmVsQ29sb3JzW2ldO1xuICAgICAgICBjb25zdCBsYWJlbFBvaW50U3R5bGUgPSB0aGlzLmxhYmVsUG9pbnRTdHlsZXNbaV07XG4gICAgICAgIGNvbnN0IHsgYm94SGVpZ2h0ICwgYm94V2lkdGggIH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBib2R5Rm9udCA9IHRvRm9udChvcHRpb25zLmJvZHlGb250KTtcbiAgICAgICAgY29uc3QgY29sb3JYID0gZ2V0QWxpZ25lZFgodGhpcywgJ2xlZnQnLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3QgcnRsQ29sb3JYID0gcnRsSGVscGVyLngoY29sb3JYKTtcbiAgICAgICAgY29uc3QgeU9mZlNldCA9IGJveEhlaWdodCA8IGJvZHlGb250LmxpbmVIZWlnaHQgPyAoYm9keUZvbnQubGluZUhlaWdodCAtIGJveEhlaWdodCkgLyAyIDogMDtcbiAgICAgICAgY29uc3QgY29sb3JZID0gcHQueSArIHlPZmZTZXQ7XG4gICAgICAgIGlmIChvcHRpb25zLnVzZVBvaW50U3R5bGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGRyYXdPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIHJhZGl1czogTWF0aC5taW4oYm94V2lkdGgsIGJveEhlaWdodCkgLyAyLFxuICAgICAgICAgICAgICAgIHBvaW50U3R5bGU6IGxhYmVsUG9pbnRTdHlsZS5wb2ludFN0eWxlLFxuICAgICAgICAgICAgICAgIHJvdGF0aW9uOiBsYWJlbFBvaW50U3R5bGUucm90YXRpb24sXG4gICAgICAgICAgICAgICAgYm9yZGVyV2lkdGg6IDFcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBjZW50ZXJYID0gcnRsSGVscGVyLmxlZnRGb3JMdHIocnRsQ29sb3JYLCBib3hXaWR0aCkgKyBib3hXaWR0aCAvIDI7XG4gICAgICAgICAgICBjb25zdCBjZW50ZXJZID0gY29sb3JZICsgYm94SGVpZ2h0IC8gMjtcbiAgICAgICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IG9wdGlvbnMubXVsdGlLZXlCYWNrZ3JvdW5kO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMubXVsdGlLZXlCYWNrZ3JvdW5kO1xuICAgICAgICAgICAgZHJhd1BvaW50KGN0eCwgZHJhd09wdGlvbnMsIGNlbnRlclgsIGNlbnRlclkpO1xuICAgICAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gbGFiZWxDb2xvci5ib3JkZXJDb2xvcjtcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBsYWJlbENvbG9yLmJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgICAgIGRyYXdQb2ludChjdHgsIGRyYXdPcHRpb25zLCBjZW50ZXJYLCBjZW50ZXJZKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBpc09iamVjdChsYWJlbENvbG9yLmJvcmRlcldpZHRoKSA/IE1hdGgubWF4KC4uLk9iamVjdC52YWx1ZXMobGFiZWxDb2xvci5ib3JkZXJXaWR0aCkpIDogbGFiZWxDb2xvci5ib3JkZXJXaWR0aCB8fCAxO1xuICAgICAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gbGFiZWxDb2xvci5ib3JkZXJDb2xvcjtcbiAgICAgICAgICAgIGN0eC5zZXRMaW5lRGFzaChsYWJlbENvbG9yLmJvcmRlckRhc2ggfHwgW10pO1xuICAgICAgICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gbGFiZWxDb2xvci5ib3JkZXJEYXNoT2Zmc2V0IHx8IDA7XG4gICAgICAgICAgICBjb25zdCBvdXRlclggPSBydGxIZWxwZXIubGVmdEZvckx0cihydGxDb2xvclgsIGJveFdpZHRoKTtcbiAgICAgICAgICAgIGNvbnN0IGlubmVyWCA9IHJ0bEhlbHBlci5sZWZ0Rm9yTHRyKHJ0bEhlbHBlci54UGx1cyhydGxDb2xvclgsIDEpLCBib3hXaWR0aCAtIDIpO1xuICAgICAgICAgICAgY29uc3QgYm9yZGVyUmFkaXVzID0gdG9UUkJMQ29ybmVycyhsYWJlbENvbG9yLmJvcmRlclJhZGl1cyk7XG4gICAgICAgICAgICBpZiAoT2JqZWN0LnZhbHVlcyhib3JkZXJSYWRpdXMpLnNvbWUoKHYpPT52ICE9PSAwKSkge1xuICAgICAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5tdWx0aUtleUJhY2tncm91bmQ7XG4gICAgICAgICAgICAgICAgYWRkUm91bmRlZFJlY3RQYXRoKGN0eCwge1xuICAgICAgICAgICAgICAgICAgICB4OiBvdXRlclgsXG4gICAgICAgICAgICAgICAgICAgIHk6IGNvbG9yWSxcbiAgICAgICAgICAgICAgICAgICAgdzogYm94V2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGg6IGJveEhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgcmFkaXVzOiBib3JkZXJSYWRpdXNcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICAgICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICAgICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gbGFiZWxDb2xvci5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgICAgIGFkZFJvdW5kZWRSZWN0UGF0aChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgeDogaW5uZXJYLFxuICAgICAgICAgICAgICAgICAgICB5OiBjb2xvclkgKyAxLFxuICAgICAgICAgICAgICAgICAgICB3OiBib3hXaWR0aCAtIDIsXG4gICAgICAgICAgICAgICAgICAgIGg6IGJveEhlaWdodCAtIDIsXG4gICAgICAgICAgICAgICAgICAgIHJhZGl1czogYm9yZGVyUmFkaXVzXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY3R4LmZpbGwoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMubXVsdGlLZXlCYWNrZ3JvdW5kO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsUmVjdChvdXRlclgsIGNvbG9yWSwgYm94V2lkdGgsIGJveEhlaWdodCk7XG4gICAgICAgICAgICAgICAgY3R4LnN0cm9rZVJlY3Qob3V0ZXJYLCBjb2xvclksIGJveFdpZHRoLCBib3hIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBsYWJlbENvbG9yLmJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgICAgICAgICBjdHguZmlsbFJlY3QoaW5uZXJYLCBjb2xvclkgKyAxLCBib3hXaWR0aCAtIDIsIGJveEhlaWdodCAtIDIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSB0aGlzLmxhYmVsVGV4dENvbG9yc1tpXTtcbiAgICB9XG4gICAgZHJhd0JvZHkocHQsIGN0eCwgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB7IGJvZHkgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IGJvZHlTcGFjaW5nICwgYm9keUFsaWduICwgZGlzcGxheUNvbG9ycyAsIGJveEhlaWdodCAsIGJveFdpZHRoICwgYm94UGFkZGluZyAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGJvZHlGb250ID0gdG9Gb250KG9wdGlvbnMuYm9keUZvbnQpO1xuICAgICAgICBsZXQgYm9keUxpbmVIZWlnaHQgPSBib2R5Rm9udC5saW5lSGVpZ2h0O1xuICAgICAgICBsZXQgeExpbmVQYWRkaW5nID0gMDtcbiAgICAgICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRpb25zLnJ0bCwgdGhpcy54LCB0aGlzLndpZHRoKTtcbiAgICAgICAgY29uc3QgZmlsbExpbmVPZlRleHQgPSBmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICBjdHguZmlsbFRleHQobGluZSwgcnRsSGVscGVyLngocHQueCArIHhMaW5lUGFkZGluZyksIHB0LnkgKyBib2R5TGluZUhlaWdodCAvIDIpO1xuICAgICAgICAgICAgcHQueSArPSBib2R5TGluZUhlaWdodCArIGJvZHlTcGFjaW5nO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBib2R5QWxpZ25Gb3JDYWxjdWxhdGlvbiA9IHJ0bEhlbHBlci50ZXh0QWxpZ24oYm9keUFsaWduKTtcbiAgICAgICAgbGV0IGJvZHlJdGVtLCB0ZXh0Q29sb3IsIGxpbmVzLCBpLCBqLCBpbGVuLCBqbGVuO1xuICAgICAgICBjdHgudGV4dEFsaWduID0gYm9keUFsaWduO1xuICAgICAgICBjdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgICAgIGN0eC5mb250ID0gYm9keUZvbnQuc3RyaW5nO1xuICAgICAgICBwdC54ID0gZ2V0QWxpZ25lZFgodGhpcywgYm9keUFsaWduRm9yQ2FsY3VsYXRpb24sIG9wdGlvbnMpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5ib2R5Q29sb3I7XG4gICAgICAgIGVhY2godGhpcy5iZWZvcmVCb2R5LCBmaWxsTGluZU9mVGV4dCk7XG4gICAgICAgIHhMaW5lUGFkZGluZyA9IGRpc3BsYXlDb2xvcnMgJiYgYm9keUFsaWduRm9yQ2FsY3VsYXRpb24gIT09ICdyaWdodCcgPyBib2R5QWxpZ24gPT09ICdjZW50ZXInID8gYm94V2lkdGggLyAyICsgYm94UGFkZGluZyA6IGJveFdpZHRoICsgMiArIGJveFBhZGRpbmcgOiAwO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBib2R5Lmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBib2R5SXRlbSA9IGJvZHlbaV07XG4gICAgICAgICAgICB0ZXh0Q29sb3IgPSB0aGlzLmxhYmVsVGV4dENvbG9yc1tpXTtcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSB0ZXh0Q29sb3I7XG4gICAgICAgICAgICBlYWNoKGJvZHlJdGVtLmJlZm9yZSwgZmlsbExpbmVPZlRleHQpO1xuICAgICAgICAgICAgbGluZXMgPSBib2R5SXRlbS5saW5lcztcbiAgICAgICAgICAgIGlmIChkaXNwbGF5Q29sb3JzICYmIGxpbmVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RyYXdDb2xvckJveChjdHgsIHB0LCBpLCBydGxIZWxwZXIsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIGJvZHlMaW5lSGVpZ2h0ID0gTWF0aC5tYXgoYm9keUZvbnQubGluZUhlaWdodCwgYm94SGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvcihqID0gMCwgamxlbiA9IGxpbmVzLmxlbmd0aDsgaiA8IGpsZW47ICsrail7XG4gICAgICAgICAgICAgICAgZmlsbExpbmVPZlRleHQobGluZXNbal0pO1xuICAgICAgICAgICAgICAgIGJvZHlMaW5lSGVpZ2h0ID0gYm9keUZvbnQubGluZUhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVhY2goYm9keUl0ZW0uYWZ0ZXIsIGZpbGxMaW5lT2ZUZXh0KTtcbiAgICAgICAgfVxuICAgICAgICB4TGluZVBhZGRpbmcgPSAwO1xuICAgICAgICBib2R5TGluZUhlaWdodCA9IGJvZHlGb250LmxpbmVIZWlnaHQ7XG4gICAgICAgIGVhY2godGhpcy5hZnRlckJvZHksIGZpbGxMaW5lT2ZUZXh0KTtcbiAgICAgICAgcHQueSAtPSBib2R5U3BhY2luZztcbiAgICB9XG4gICAgZHJhd0Zvb3RlcihwdCwgY3R4LCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGZvb3RlciA9IHRoaXMuZm9vdGVyO1xuICAgICAgICBjb25zdCBsZW5ndGggPSBmb290ZXIubGVuZ3RoO1xuICAgICAgICBsZXQgZm9vdGVyRm9udCwgaTtcbiAgICAgICAgaWYgKGxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRpb25zLnJ0bCwgdGhpcy54LCB0aGlzLndpZHRoKTtcbiAgICAgICAgICAgIHB0LnggPSBnZXRBbGlnbmVkWCh0aGlzLCBvcHRpb25zLmZvb3RlckFsaWduLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHB0LnkgKz0gb3B0aW9ucy5mb290ZXJNYXJnaW5Ub3A7XG4gICAgICAgICAgICBjdHgudGV4dEFsaWduID0gcnRsSGVscGVyLnRleHRBbGlnbihvcHRpb25zLmZvb3RlckFsaWduKTtcbiAgICAgICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgICAgICAgIGZvb3RlckZvbnQgPSB0b0ZvbnQob3B0aW9ucy5mb290ZXJGb250KTtcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLmZvb3RlckNvbG9yO1xuICAgICAgICAgICAgY3R4LmZvbnQgPSBmb290ZXJGb250LnN0cmluZztcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxlbmd0aDsgKytpKXtcbiAgICAgICAgICAgICAgICBjdHguZmlsbFRleHQoZm9vdGVyW2ldLCBydGxIZWxwZXIueChwdC54KSwgcHQueSArIGZvb3RlckZvbnQubGluZUhlaWdodCAvIDIpO1xuICAgICAgICAgICAgICAgIHB0LnkgKz0gZm9vdGVyRm9udC5saW5lSGVpZ2h0ICsgb3B0aW9ucy5mb290ZXJTcGFjaW5nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGRyYXdCYWNrZ3JvdW5kKHB0LCBjdHgsIHRvb2x0aXBTaXplLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHsgeEFsaWduICwgeUFsaWduICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgeyB4ICwgeSAgfSA9IHB0O1xuICAgICAgICBjb25zdCB7IHdpZHRoICwgaGVpZ2h0ICB9ID0gdG9vbHRpcFNpemU7XG4gICAgICAgIGNvbnN0IHsgdG9wTGVmdCAsIHRvcFJpZ2h0ICwgYm90dG9tTGVmdCAsIGJvdHRvbVJpZ2h0ICB9ID0gdG9UUkJMQ29ybmVycyhvcHRpb25zLmNvcm5lclJhZGl1cyk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLmJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gb3B0aW9ucy5ib3JkZXJDb2xvcjtcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IG9wdGlvbnMuYm9yZGVyV2lkdGg7XG4gICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgY3R4Lm1vdmVUbyh4ICsgdG9wTGVmdCwgeSk7XG4gICAgICAgIGlmICh5QWxpZ24gPT09ICd0b3AnKSB7XG4gICAgICAgICAgICB0aGlzLmRyYXdDYXJldChwdCwgY3R4LCB0b29sdGlwU2l6ZSwgb3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgY3R4LmxpbmVUbyh4ICsgd2lkdGggLSB0b3BSaWdodCwgeSk7XG4gICAgICAgIGN0eC5xdWFkcmF0aWNDdXJ2ZVRvKHggKyB3aWR0aCwgeSwgeCArIHdpZHRoLCB5ICsgdG9wUmlnaHQpO1xuICAgICAgICBpZiAoeUFsaWduID09PSAnY2VudGVyJyAmJiB4QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NhcmV0KHB0LCBjdHgsIHRvb2x0aXBTaXplLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBjdHgubGluZVRvKHggKyB3aWR0aCwgeSArIGhlaWdodCAtIGJvdHRvbVJpZ2h0KTtcbiAgICAgICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCArIHdpZHRoLCB5ICsgaGVpZ2h0LCB4ICsgd2lkdGggLSBib3R0b21SaWdodCwgeSArIGhlaWdodCk7XG4gICAgICAgIGlmICh5QWxpZ24gPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICB0aGlzLmRyYXdDYXJldChwdCwgY3R4LCB0b29sdGlwU2l6ZSwgb3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgY3R4LmxpbmVUbyh4ICsgYm90dG9tTGVmdCwgeSArIGhlaWdodCk7XG4gICAgICAgIGN0eC5xdWFkcmF0aWNDdXJ2ZVRvKHgsIHkgKyBoZWlnaHQsIHgsIHkgKyBoZWlnaHQgLSBib3R0b21MZWZ0KTtcbiAgICAgICAgaWYgKHlBbGlnbiA9PT0gJ2NlbnRlcicgJiYgeEFsaWduID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NhcmV0KHB0LCBjdHgsIHRvb2x0aXBTaXplLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBjdHgubGluZVRvKHgsIHkgKyB0b3BMZWZ0KTtcbiAgICAgICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCwgeSwgeCArIHRvcExlZnQsIHkpO1xuICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG4gICAgICAgIGlmIChvcHRpb25zLmJvcmRlcldpZHRoID4gMCkge1xuICAgICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICB9XG4gICAgfVxuIF91cGRhdGVBbmltYXRpb25UYXJnZXQob3B0aW9ucykge1xuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGNvbnN0IGFuaW1zID0gdGhpcy4kYW5pbWF0aW9ucztcbiAgICAgICAgY29uc3QgYW5pbVggPSBhbmltcyAmJiBhbmltcy54O1xuICAgICAgICBjb25zdCBhbmltWSA9IGFuaW1zICYmIGFuaW1zLnk7XG4gICAgICAgIGlmIChhbmltWCB8fCBhbmltWSkge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBwb3NpdGlvbmVyc1tvcHRpb25zLnBvc2l0aW9uXS5jYWxsKHRoaXMsIHRoaXMuX2FjdGl2ZSwgdGhpcy5fZXZlbnRQb3NpdGlvbik7XG4gICAgICAgICAgICBpZiAoIXBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuX3NpemUgPSBnZXRUb29sdGlwU2l6ZSh0aGlzLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uQW5kU2l6ZSA9IE9iamVjdC5hc3NpZ24oe30sIHBvc2l0aW9uLCB0aGlzLl9zaXplKTtcbiAgICAgICAgICAgIGNvbnN0IGFsaWdubWVudCA9IGRldGVybWluZUFsaWdubWVudChjaGFydCwgb3B0aW9ucywgcG9zaXRpb25BbmRTaXplKTtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50ID0gZ2V0QmFja2dyb3VuZFBvaW50KG9wdGlvbnMsIHBvc2l0aW9uQW5kU2l6ZSwgYWxpZ25tZW50LCBjaGFydCk7XG4gICAgICAgICAgICBpZiAoYW5pbVguX3RvICE9PSBwb2ludC54IHx8IGFuaW1ZLl90byAhPT0gcG9pbnQueSkge1xuICAgICAgICAgICAgICAgIHRoaXMueEFsaWduID0gYWxpZ25tZW50LnhBbGlnbjtcbiAgICAgICAgICAgICAgICB0aGlzLnlBbGlnbiA9IGFsaWdubWVudC55QWxpZ247XG4gICAgICAgICAgICAgICAgdGhpcy53aWR0aCA9IHNpemUud2lkdGg7XG4gICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBzaXplLmhlaWdodDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhcmV0WCA9IHBvc2l0aW9uLng7XG4gICAgICAgICAgICAgICAgdGhpcy5jYXJldFkgPSBwb3NpdGlvbi55O1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc29sdmVBbmltYXRpb25zKCkudXBkYXRlKHRoaXMsIHBvaW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiBfd2lsbFJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5vcGFjaXR5O1xuICAgIH1cbiAgICBkcmF3KGN0eCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KCkpO1xuICAgICAgICBsZXQgb3BhY2l0eSA9IHRoaXMub3BhY2l0eTtcbiAgICAgICAgaWYgKCFvcGFjaXR5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdXBkYXRlQW5pbWF0aW9uVGFyZ2V0KG9wdGlvbnMpO1xuICAgICAgICBjb25zdCB0b29sdGlwU2l6ZSA9IHtcbiAgICAgICAgICAgIHdpZHRoOiB0aGlzLndpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0OiB0aGlzLmhlaWdodFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBwdCA9IHtcbiAgICAgICAgICAgIHg6IHRoaXMueCxcbiAgICAgICAgICAgIHk6IHRoaXMueVxuICAgICAgICB9O1xuICAgICAgICBvcGFjaXR5ID0gTWF0aC5hYnMob3BhY2l0eSkgPCAxZS0zID8gMCA6IG9wYWNpdHk7XG4gICAgICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcob3B0aW9ucy5wYWRkaW5nKTtcbiAgICAgICAgY29uc3QgaGFzVG9vbHRpcENvbnRlbnQgPSB0aGlzLnRpdGxlLmxlbmd0aCB8fCB0aGlzLmJlZm9yZUJvZHkubGVuZ3RoIHx8IHRoaXMuYm9keS5sZW5ndGggfHwgdGhpcy5hZnRlckJvZHkubGVuZ3RoIHx8IHRoaXMuZm9vdGVyLmxlbmd0aDtcbiAgICAgICAgaWYgKG9wdGlvbnMuZW5hYmxlZCAmJiBoYXNUb29sdGlwQ29udGVudCkge1xuICAgICAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgICAgIGN0eC5nbG9iYWxBbHBoYSA9IG9wYWNpdHk7XG4gICAgICAgICAgICB0aGlzLmRyYXdCYWNrZ3JvdW5kKHB0LCBjdHgsIHRvb2x0aXBTaXplLCBvcHRpb25zKTtcbiAgICAgICAgICAgIG92ZXJyaWRlVGV4dERpcmVjdGlvbihjdHgsIG9wdGlvbnMudGV4dERpcmVjdGlvbik7XG4gICAgICAgICAgICBwdC55ICs9IHBhZGRpbmcudG9wO1xuICAgICAgICAgICAgdGhpcy5kcmF3VGl0bGUocHQsIGN0eCwgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmRyYXdCb2R5KHB0LCBjdHgsIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5kcmF3Rm9vdGVyKHB0LCBjdHgsIG9wdGlvbnMpO1xuICAgICAgICAgICAgcmVzdG9yZVRleHREaXJlY3Rpb24oY3R4LCBvcHRpb25zLnRleHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgfVxuICAgIH1cbiBnZXRBY3RpdmVFbGVtZW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FjdGl2ZSB8fCBbXTtcbiAgICB9XG4gc2V0QWN0aXZlRWxlbWVudHMoYWN0aXZlRWxlbWVudHMsIGV2ZW50UG9zaXRpb24pIHtcbiAgICAgICAgY29uc3QgbGFzdEFjdGl2ZSA9IHRoaXMuX2FjdGl2ZTtcbiAgICAgICAgY29uc3QgYWN0aXZlID0gYWN0aXZlRWxlbWVudHMubWFwKCh7IGRhdGFzZXRJbmRleCAsIGluZGV4ICB9KT0+e1xuICAgICAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuY2hhcnQuZ2V0RGF0YXNldE1ldGEoZGF0YXNldEluZGV4KTtcbiAgICAgICAgICAgIGlmICghbWV0YSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgYSBkYXRhc2V0IGF0IGluZGV4ICcgKyBkYXRhc2V0SW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgZWxlbWVudDogbWV0YS5kYXRhW2luZGV4XSxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNoYW5nZWQgPSAhX2VsZW1lbnRzRXF1YWwobGFzdEFjdGl2ZSwgYWN0aXZlKTtcbiAgICAgICAgY29uc3QgcG9zaXRpb25DaGFuZ2VkID0gdGhpcy5fcG9zaXRpb25DaGFuZ2VkKGFjdGl2ZSwgZXZlbnRQb3NpdGlvbik7XG4gICAgICAgIGlmIChjaGFuZ2VkIHx8IHBvc2l0aW9uQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5fYWN0aXZlID0gYWN0aXZlO1xuICAgICAgICAgICAgdGhpcy5fZXZlbnRQb3NpdGlvbiA9IGV2ZW50UG9zaXRpb247XG4gICAgICAgICAgICB0aGlzLl9pZ25vcmVSZXBsYXlFdmVudHMgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy51cGRhdGUodHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gaGFuZGxlRXZlbnQoZSwgcmVwbGF5LCBpbkNoYXJ0QXJlYSA9IHRydWUpIHtcbiAgICAgICAgaWYgKHJlcGxheSAmJiB0aGlzLl9pZ25vcmVSZXBsYXlFdmVudHMpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9pZ25vcmVSZXBsYXlFdmVudHMgPSBmYWxzZTtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgbGFzdEFjdGl2ZSA9IHRoaXMuX2FjdGl2ZSB8fCBbXTtcbiAgICAgICAgY29uc3QgYWN0aXZlID0gdGhpcy5fZ2V0QWN0aXZlRWxlbWVudHMoZSwgbGFzdEFjdGl2ZSwgcmVwbGF5LCBpbkNoYXJ0QXJlYSk7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uQ2hhbmdlZCA9IHRoaXMuX3Bvc2l0aW9uQ2hhbmdlZChhY3RpdmUsIGUpO1xuICAgICAgICBjb25zdCBjaGFuZ2VkID0gcmVwbGF5IHx8ICFfZWxlbWVudHNFcXVhbChhY3RpdmUsIGxhc3RBY3RpdmUpIHx8IHBvc2l0aW9uQ2hhbmdlZDtcbiAgICAgICAgaWYgKGNoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2FjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmVuYWJsZWQgfHwgb3B0aW9ucy5leHRlcm5hbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2V2ZW50UG9zaXRpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgIHg6IGUueCxcbiAgICAgICAgICAgICAgICAgICAgeTogZS55XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh0cnVlLCByZXBsYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjaGFuZ2VkO1xuICAgIH1cbiBfZ2V0QWN0aXZlRWxlbWVudHMoZSwgbGFzdEFjdGl2ZSwgcmVwbGF5LCBpbkNoYXJ0QXJlYSkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAoZS50eXBlID09PSAnbW91c2VvdXQnKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpbkNoYXJ0QXJlYSkge1xuICAgICAgICAgICAgcmV0dXJuIGxhc3RBY3RpdmUuZmlsdGVyKChpKT0+dGhpcy5jaGFydC5kYXRhLmRhdGFzZXRzW2kuZGF0YXNldEluZGV4XSAmJiB0aGlzLmNoYXJ0LmdldERhdGFzZXRNZXRhKGkuZGF0YXNldEluZGV4KS5jb250cm9sbGVyLmdldFBhcnNlZChpLmluZGV4KSAhPT0gdW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhY3RpdmUgPSB0aGlzLmNoYXJ0LmdldEVsZW1lbnRzQXRFdmVudEZvck1vZGUoZSwgb3B0aW9ucy5tb2RlLCBvcHRpb25zLCByZXBsYXkpO1xuICAgICAgICBpZiAob3B0aW9ucy5yZXZlcnNlKSB7XG4gICAgICAgICAgICBhY3RpdmUucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3RpdmU7XG4gICAgfVxuIF9wb3NpdGlvbkNoYW5nZWQoYWN0aXZlLCBlKSB7XG4gICAgICAgIGNvbnN0IHsgY2FyZXRYICwgY2FyZXRZICwgb3B0aW9ucyAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0gcG9zaXRpb25lcnNbb3B0aW9ucy5wb3NpdGlvbl0uY2FsbCh0aGlzLCBhY3RpdmUsIGUpO1xuICAgICAgICByZXR1cm4gcG9zaXRpb24gIT09IGZhbHNlICYmIChjYXJldFggIT09IHBvc2l0aW9uLnggfHwgY2FyZXRZICE9PSBwb3NpdGlvbi55KTtcbiAgICB9XG59XG52YXIgcGx1Z2luX3Rvb2x0aXAgPSB7XG4gICAgaWQ6ICd0b29sdGlwJyxcbiAgICBfZWxlbWVudDogVG9vbHRpcCxcbiAgICBwb3NpdGlvbmVycyxcbiAgICBhZnRlckluaXQgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucykge1xuICAgICAgICAgICAgY2hhcnQudG9vbHRpcCA9IG5ldyBUb29sdGlwKHtcbiAgICAgICAgICAgICAgICBjaGFydCxcbiAgICAgICAgICAgICAgICBvcHRpb25zXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgYmVmb3JlVXBkYXRlIChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGNoYXJ0LnRvb2x0aXApIHtcbiAgICAgICAgICAgIGNoYXJ0LnRvb2x0aXAuaW5pdGlhbGl6ZShvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVzZXQgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBpZiAoY2hhcnQudG9vbHRpcCkge1xuICAgICAgICAgICAgY2hhcnQudG9vbHRpcC5pbml0aWFsaXplKG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBhZnRlckRyYXcgKGNoYXJ0KSB7XG4gICAgICAgIGNvbnN0IHRvb2x0aXAgPSBjaGFydC50b29sdGlwO1xuICAgICAgICBpZiAodG9vbHRpcCAmJiB0b29sdGlwLl93aWxsUmVuZGVyKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSB7XG4gICAgICAgICAgICAgICAgdG9vbHRpcFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChjaGFydC5ub3RpZnlQbHVnaW5zKCdiZWZvcmVUb29sdGlwRHJhdycsIHtcbiAgICAgICAgICAgICAgICAuLi5hcmdzLFxuICAgICAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgICAgIH0pID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRvb2x0aXAuZHJhdyhjaGFydC5jdHgpO1xuICAgICAgICAgICAgY2hhcnQubm90aWZ5UGx1Z2lucygnYWZ0ZXJUb29sdGlwRHJhdycsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBhZnRlckV2ZW50IChjaGFydCwgYXJncykge1xuICAgICAgICBpZiAoY2hhcnQudG9vbHRpcCkge1xuICAgICAgICAgICAgY29uc3QgdXNlRmluYWxQb3NpdGlvbiA9IGFyZ3MucmVwbGF5O1xuICAgICAgICAgICAgaWYgKGNoYXJ0LnRvb2x0aXAuaGFuZGxlRXZlbnQoYXJncy5ldmVudCwgdXNlRmluYWxQb3NpdGlvbiwgYXJncy5pbkNoYXJ0QXJlYSkpIHtcbiAgICAgICAgICAgICAgICBhcmdzLmNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICBkZWZhdWx0czoge1xuICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICBleHRlcm5hbDogbnVsbCxcbiAgICAgICAgcG9zaXRpb246ICdhdmVyYWdlJyxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAncmdiYSgwLDAsMCwwLjgpJyxcbiAgICAgICAgdGl0bGVDb2xvcjogJyNmZmYnLFxuICAgICAgICB0aXRsZUZvbnQ6IHtcbiAgICAgICAgICAgIHdlaWdodDogJ2JvbGQnXG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlU3BhY2luZzogMixcbiAgICAgICAgdGl0bGVNYXJnaW5Cb3R0b206IDYsXG4gICAgICAgIHRpdGxlQWxpZ246ICdsZWZ0JyxcbiAgICAgICAgYm9keUNvbG9yOiAnI2ZmZicsXG4gICAgICAgIGJvZHlTcGFjaW5nOiAyLFxuICAgICAgICBib2R5Rm9udDoge30sXG4gICAgICAgIGJvZHlBbGlnbjogJ2xlZnQnLFxuICAgICAgICBmb290ZXJDb2xvcjogJyNmZmYnLFxuICAgICAgICBmb290ZXJTcGFjaW5nOiAyLFxuICAgICAgICBmb290ZXJNYXJnaW5Ub3A6IDYsXG4gICAgICAgIGZvb3RlckZvbnQ6IHtcbiAgICAgICAgICAgIHdlaWdodDogJ2JvbGQnXG4gICAgICAgIH0sXG4gICAgICAgIGZvb3RlckFsaWduOiAnbGVmdCcsXG4gICAgICAgIHBhZGRpbmc6IDYsXG4gICAgICAgIGNhcmV0UGFkZGluZzogMixcbiAgICAgICAgY2FyZXRTaXplOiA1LFxuICAgICAgICBjb3JuZXJSYWRpdXM6IDYsXG4gICAgICAgIGJveEhlaWdodDogKGN0eCwgb3B0cyk9Pm9wdHMuYm9keUZvbnQuc2l6ZSxcbiAgICAgICAgYm94V2lkdGg6IChjdHgsIG9wdHMpPT5vcHRzLmJvZHlGb250LnNpemUsXG4gICAgICAgIG11bHRpS2V5QmFja2dyb3VuZDogJyNmZmYnLFxuICAgICAgICBkaXNwbGF5Q29sb3JzOiB0cnVlLFxuICAgICAgICBib3hQYWRkaW5nOiAwLFxuICAgICAgICBib3JkZXJDb2xvcjogJ3JnYmEoMCwwLDAsMCknLFxuICAgICAgICBib3JkZXJXaWR0aDogMCxcbiAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICBkdXJhdGlvbjogNDAwLFxuICAgICAgICAgICAgZWFzaW5nOiAnZWFzZU91dFF1YXJ0J1xuICAgICAgICB9LFxuICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICBudW1iZXJzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgcHJvcGVydGllczogW1xuICAgICAgICAgICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAgICAgICAgICd5JyxcbiAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJyxcbiAgICAgICAgICAgICAgICAgICAgJ2hlaWdodCcsXG4gICAgICAgICAgICAgICAgICAgICdjYXJldFgnLFxuICAgICAgICAgICAgICAgICAgICAnY2FyZXRZJ1xuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICAgICAgZWFzaW5nOiAnbGluZWFyJyxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogMjAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGxiYWNrczogZGVmYXVsdENhbGxiYWNrc1xuICAgIH0sXG4gICAgZGVmYXVsdFJvdXRlczoge1xuICAgICAgICBib2R5Rm9udDogJ2ZvbnQnLFxuICAgICAgICBmb290ZXJGb250OiAnZm9udCcsXG4gICAgICAgIHRpdGxlRm9udDogJ2ZvbnQnXG4gICAgfSxcbiAgICBkZXNjcmlwdG9yczoge1xuICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnZmlsdGVyJyAmJiBuYW1lICE9PSAnaXRlbVNvcnQnICYmIG5hbWUgIT09ICdleHRlcm5hbCcsXG4gICAgICAgIF9pbmRleGFibGU6IGZhbHNlLFxuICAgICAgICBjYWxsYmFja3M6IHtcbiAgICAgICAgICAgIF9zY3JpcHRhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIF9pbmRleGFibGU6IGZhbHNlXG4gICAgICAgIH0sXG4gICAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAgICAgX2ZhbGxiYWNrOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICBfZmFsbGJhY2s6ICdhbmltYXRpb24nXG4gICAgICAgIH1cbiAgICB9LFxuICAgIGFkZGl0aW9uYWxPcHRpb25TY29wZXM6IFtcbiAgICAgICAgJ2ludGVyYWN0aW9uJ1xuICAgIF1cbn07XG5cbnZhciBwbHVnaW5zID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuX19wcm90b19fOiBudWxsLFxuQ29sb3JzOiBwbHVnaW5fY29sb3JzLFxuRGVjaW1hdGlvbjogcGx1Z2luX2RlY2ltYXRpb24sXG5GaWxsZXI6IGluZGV4LFxuTGVnZW5kOiBwbHVnaW5fbGVnZW5kLFxuU3ViVGl0bGU6IHBsdWdpbl9zdWJ0aXRsZSxcblRpdGxlOiBwbHVnaW5fdGl0bGUsXG5Ub29sdGlwOiBwbHVnaW5fdG9vbHRpcFxufSk7XG5cbmNvbnN0IGFkZElmU3RyaW5nID0gKGxhYmVscywgcmF3LCBpbmRleCwgYWRkZWRMYWJlbHMpPT57XG4gICAgaWYgKHR5cGVvZiByYXcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGluZGV4ID0gbGFiZWxzLnB1c2gocmF3KSAtIDE7XG4gICAgICAgIGFkZGVkTGFiZWxzLnVuc2hpZnQoe1xuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICBsYWJlbDogcmF3XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAoaXNOYU4ocmF3KSkge1xuICAgICAgICBpbmRleCA9IG51bGw7XG4gICAgfVxuICAgIHJldHVybiBpbmRleDtcbn07XG5mdW5jdGlvbiBmaW5kT3JBZGRMYWJlbChsYWJlbHMsIHJhdywgaW5kZXgsIGFkZGVkTGFiZWxzKSB7XG4gICAgY29uc3QgZmlyc3QgPSBsYWJlbHMuaW5kZXhPZihyYXcpO1xuICAgIGlmIChmaXJzdCA9PT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIGFkZElmU3RyaW5nKGxhYmVscywgcmF3LCBpbmRleCwgYWRkZWRMYWJlbHMpO1xuICAgIH1cbiAgICBjb25zdCBsYXN0ID0gbGFiZWxzLmxhc3RJbmRleE9mKHJhdyk7XG4gICAgcmV0dXJuIGZpcnN0ICE9PSBsYXN0ID8gaW5kZXggOiBmaXJzdDtcbn1cbmNvbnN0IHZhbGlkSW5kZXggPSAoaW5kZXgsIG1heCk9PmluZGV4ID09PSBudWxsID8gbnVsbCA6IF9saW1pdFZhbHVlKE1hdGgucm91bmQoaW5kZXgpLCAwLCBtYXgpO1xuZnVuY3Rpb24gX2dldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICBjb25zdCBsYWJlbHMgPSB0aGlzLmdldExhYmVscygpO1xuICAgIGlmICh2YWx1ZSA+PSAwICYmIHZhbHVlIDwgbGFiZWxzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gbGFiZWxzW3ZhbHVlXTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuY2xhc3MgQ2F0ZWdvcnlTY2FsZSBleHRlbmRzIFNjYWxlIHtcbiAgICBzdGF0aWMgaWQgPSAnY2F0ZWdvcnknO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgdGlja3M6IHtcbiAgICAgICAgICAgIGNhbGxiYWNrOiBfZ2V0TGFiZWxGb3JWYWx1ZVxuICAgICAgICB9XG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihjZmcpe1xuICAgICAgICBzdXBlcihjZmcpO1xuICAgICAgICAgdGhpcy5fc3RhcnRWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fdmFsdWVSYW5nZSA9IDA7XG4gICAgICAgIHRoaXMuX2FkZGVkTGFiZWxzID0gW107XG4gICAgfVxuICAgIGluaXQoc2NhbGVPcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGFkZGVkID0gdGhpcy5fYWRkZWRMYWJlbHM7XG4gICAgICAgIGlmIChhZGRlZC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IGxhYmVscyA9IHRoaXMuZ2V0TGFiZWxzKCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHsgaW5kZXggLCBsYWJlbCAgfSBvZiBhZGRlZCl7XG4gICAgICAgICAgICAgICAgaWYgKGxhYmVsc1tpbmRleF0gPT09IGxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGxhYmVscy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2FkZGVkTGFiZWxzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIuaW5pdChzY2FsZU9wdGlvbnMpO1xuICAgIH1cbiAgICBwYXJzZShyYXcsIGluZGV4KSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmKHJhdykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxhYmVscyA9IHRoaXMuZ2V0TGFiZWxzKCk7XG4gICAgICAgIGluZGV4ID0gaXNGaW5pdGUoaW5kZXgpICYmIGxhYmVsc1tpbmRleF0gPT09IHJhdyA/IGluZGV4IDogZmluZE9yQWRkTGFiZWwobGFiZWxzLCByYXcsIHZhbHVlT3JEZWZhdWx0KGluZGV4LCByYXcpLCB0aGlzLl9hZGRlZExhYmVscyk7XG4gICAgICAgIHJldHVybiB2YWxpZEluZGV4KGluZGV4LCBsYWJlbHMubGVuZ3RoIC0gMSk7XG4gICAgfVxuICAgIGRldGVybWluZURhdGFMaW1pdHMoKSB7XG4gICAgICAgIGNvbnN0IHsgbWluRGVmaW5lZCAsIG1heERlZmluZWQgIH0gPSB0aGlzLmdldFVzZXJCb3VuZHMoKTtcbiAgICAgICAgbGV0IHsgbWluICwgbWF4ICB9ID0gdGhpcy5nZXRNaW5NYXgodHJ1ZSk7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuYm91bmRzID09PSAndGlja3MnKSB7XG4gICAgICAgICAgICBpZiAoIW1pbkRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBtaW4gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtYXhEZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWF4ID0gdGhpcy5nZXRMYWJlbHMoKS5sZW5ndGggLSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubWluID0gbWluO1xuICAgICAgICB0aGlzLm1heCA9IG1heDtcbiAgICB9XG4gICAgYnVpbGRUaWNrcygpIHtcbiAgICAgICAgY29uc3QgbWluID0gdGhpcy5taW47XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4O1xuICAgICAgICBjb25zdCBvZmZzZXQgPSB0aGlzLm9wdGlvbnMub2Zmc2V0O1xuICAgICAgICBjb25zdCB0aWNrcyA9IFtdO1xuICAgICAgICBsZXQgbGFiZWxzID0gdGhpcy5nZXRMYWJlbHMoKTtcbiAgICAgICAgbGFiZWxzID0gbWluID09PSAwICYmIG1heCA9PT0gbGFiZWxzLmxlbmd0aCAtIDEgPyBsYWJlbHMgOiBsYWJlbHMuc2xpY2UobWluLCBtYXggKyAxKTtcbiAgICAgICAgdGhpcy5fdmFsdWVSYW5nZSA9IE1hdGgubWF4KGxhYmVscy5sZW5ndGggLSAob2Zmc2V0ID8gMCA6IDEpLCAxKTtcbiAgICAgICAgdGhpcy5fc3RhcnRWYWx1ZSA9IHRoaXMubWluIC0gKG9mZnNldCA/IDAuNSA6IDApO1xuICAgICAgICBmb3IobGV0IHZhbHVlID0gbWluOyB2YWx1ZSA8PSBtYXg7IHZhbHVlKyspe1xuICAgICAgICAgICAgdGlja3MucHVzaCh7XG4gICAgICAgICAgICAgICAgdmFsdWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aWNrcztcbiAgICB9XG4gICAgZ2V0TGFiZWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gX2dldExhYmVsRm9yVmFsdWUuY2FsbCh0aGlzLCB2YWx1ZSk7XG4gICAgfVxuIGNvbmZpZ3VyZSgpIHtcbiAgICAgICAgc3VwZXIuY29uZmlndXJlKCk7XG4gICAgICAgIGlmICghdGhpcy5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgdGhpcy5fcmV2ZXJzZVBpeGVscyA9ICF0aGlzLl9yZXZlcnNlUGl4ZWxzO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldFBpeGVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy5wYXJzZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsID8gTmFOIDogdGhpcy5nZXRQaXhlbEZvckRlY2ltYWwoKHZhbHVlIC0gdGhpcy5fc3RhcnRWYWx1ZSkgLyB0aGlzLl92YWx1ZVJhbmdlKTtcbiAgICB9XG4gICAgZ2V0UGl4ZWxGb3JUaWNrKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IHRpY2tzID0gdGhpcy50aWNrcztcbiAgICAgICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+IHRpY2tzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBpeGVsRm9yVmFsdWUodGlja3NbaW5kZXhdLnZhbHVlKTtcbiAgICB9XG4gICAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCh0aGlzLl9zdGFydFZhbHVlICsgdGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpICogdGhpcy5fdmFsdWVSYW5nZSk7XG4gICAgfVxuICAgIGdldEJhc2VQaXhlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm90dG9tO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVUaWNrcyQxKGdlbmVyYXRpb25PcHRpb25zLCBkYXRhUmFuZ2UpIHtcbiAgICBjb25zdCB0aWNrcyA9IFtdO1xuICAgIGNvbnN0IE1JTl9TUEFDSU5HID0gMWUtMTQ7XG4gICAgY29uc3QgeyBib3VuZHMgLCBzdGVwICwgbWluICwgbWF4ICwgcHJlY2lzaW9uICwgY291bnQgLCBtYXhUaWNrcyAsIG1heERpZ2l0cyAsIGluY2x1ZGVCb3VuZHMgIH0gPSBnZW5lcmF0aW9uT3B0aW9ucztcbiAgICBjb25zdCB1bml0ID0gc3RlcCB8fCAxO1xuICAgIGNvbnN0IG1heFNwYWNlcyA9IG1heFRpY2tzIC0gMTtcbiAgICBjb25zdCB7IG1pbjogcm1pbiAsIG1heDogcm1heCAgfSA9IGRhdGFSYW5nZTtcbiAgICBjb25zdCBtaW5EZWZpbmVkID0gIWlzTnVsbE9yVW5kZWYobWluKTtcbiAgICBjb25zdCBtYXhEZWZpbmVkID0gIWlzTnVsbE9yVW5kZWYobWF4KTtcbiAgICBjb25zdCBjb3VudERlZmluZWQgPSAhaXNOdWxsT3JVbmRlZihjb3VudCk7XG4gICAgY29uc3QgbWluU3BhY2luZyA9IChybWF4IC0gcm1pbikgLyAobWF4RGlnaXRzICsgMSk7XG4gICAgbGV0IHNwYWNpbmcgPSBuaWNlTnVtKChybWF4IC0gcm1pbikgLyBtYXhTcGFjZXMgLyB1bml0KSAqIHVuaXQ7XG4gICAgbGV0IGZhY3RvciwgbmljZU1pbiwgbmljZU1heCwgbnVtU3BhY2VzO1xuICAgIGlmIChzcGFjaW5nIDwgTUlOX1NQQUNJTkcgJiYgIW1pbkRlZmluZWQgJiYgIW1heERlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogcm1pblxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogcm1heFxuICAgICAgICAgICAgfVxuICAgICAgICBdO1xuICAgIH1cbiAgICBudW1TcGFjZXMgPSBNYXRoLmNlaWwocm1heCAvIHNwYWNpbmcpIC0gTWF0aC5mbG9vcihybWluIC8gc3BhY2luZyk7XG4gICAgaWYgKG51bVNwYWNlcyA+IG1heFNwYWNlcykge1xuICAgICAgICBzcGFjaW5nID0gbmljZU51bShudW1TcGFjZXMgKiBzcGFjaW5nIC8gbWF4U3BhY2VzIC8gdW5pdCkgKiB1bml0O1xuICAgIH1cbiAgICBpZiAoIWlzTnVsbE9yVW5kZWYocHJlY2lzaW9uKSkge1xuICAgICAgICBmYWN0b3IgPSBNYXRoLnBvdygxMCwgcHJlY2lzaW9uKTtcbiAgICAgICAgc3BhY2luZyA9IE1hdGguY2VpbChzcGFjaW5nICogZmFjdG9yKSAvIGZhY3RvcjtcbiAgICB9XG4gICAgaWYgKGJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgICBuaWNlTWluID0gTWF0aC5mbG9vcihybWluIC8gc3BhY2luZykgKiBzcGFjaW5nO1xuICAgICAgICBuaWNlTWF4ID0gTWF0aC5jZWlsKHJtYXggLyBzcGFjaW5nKSAqIHNwYWNpbmc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmljZU1pbiA9IHJtaW47XG4gICAgICAgIG5pY2VNYXggPSBybWF4O1xuICAgIH1cbiAgICBpZiAobWluRGVmaW5lZCAmJiBtYXhEZWZpbmVkICYmIHN0ZXAgJiYgYWxtb3N0V2hvbGUoKG1heCAtIG1pbikgLyBzdGVwLCBzcGFjaW5nIC8gMTAwMCkpIHtcbiAgICAgICAgbnVtU3BhY2VzID0gTWF0aC5yb3VuZChNYXRoLm1pbigobWF4IC0gbWluKSAvIHNwYWNpbmcsIG1heFRpY2tzKSk7XG4gICAgICAgIHNwYWNpbmcgPSAobWF4IC0gbWluKSAvIG51bVNwYWNlcztcbiAgICAgICAgbmljZU1pbiA9IG1pbjtcbiAgICAgICAgbmljZU1heCA9IG1heDtcbiAgICB9IGVsc2UgaWYgKGNvdW50RGVmaW5lZCkge1xuICAgICAgICBuaWNlTWluID0gbWluRGVmaW5lZCA/IG1pbiA6IG5pY2VNaW47XG4gICAgICAgIG5pY2VNYXggPSBtYXhEZWZpbmVkID8gbWF4IDogbmljZU1heDtcbiAgICAgICAgbnVtU3BhY2VzID0gY291bnQgLSAxO1xuICAgICAgICBzcGFjaW5nID0gKG5pY2VNYXggLSBuaWNlTWluKSAvIG51bVNwYWNlcztcbiAgICB9IGVsc2Uge1xuICAgICAgICBudW1TcGFjZXMgPSAobmljZU1heCAtIG5pY2VNaW4pIC8gc3BhY2luZztcbiAgICAgICAgaWYgKGFsbW9zdEVxdWFscyhudW1TcGFjZXMsIE1hdGgucm91bmQobnVtU3BhY2VzKSwgc3BhY2luZyAvIDEwMDApKSB7XG4gICAgICAgICAgICBudW1TcGFjZXMgPSBNYXRoLnJvdW5kKG51bVNwYWNlcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBudW1TcGFjZXMgPSBNYXRoLmNlaWwobnVtU3BhY2VzKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBkZWNpbWFsUGxhY2VzID0gTWF0aC5tYXgoX2RlY2ltYWxQbGFjZXMoc3BhY2luZyksIF9kZWNpbWFsUGxhY2VzKG5pY2VNaW4pKTtcbiAgICBmYWN0b3IgPSBNYXRoLnBvdygxMCwgaXNOdWxsT3JVbmRlZihwcmVjaXNpb24pID8gZGVjaW1hbFBsYWNlcyA6IHByZWNpc2lvbik7XG4gICAgbmljZU1pbiA9IE1hdGgucm91bmQobmljZU1pbiAqIGZhY3RvcikgLyBmYWN0b3I7XG4gICAgbmljZU1heCA9IE1hdGgucm91bmQobmljZU1heCAqIGZhY3RvcikgLyBmYWN0b3I7XG4gICAgbGV0IGogPSAwO1xuICAgIGlmIChtaW5EZWZpbmVkKSB7XG4gICAgICAgIGlmIChpbmNsdWRlQm91bmRzICYmIG5pY2VNaW4gIT09IG1pbikge1xuICAgICAgICAgICAgdGlja3MucHVzaCh7XG4gICAgICAgICAgICAgICAgdmFsdWU6IG1pblxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAobmljZU1pbiA8IG1pbikge1xuICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChhbG1vc3RFcXVhbHMoTWF0aC5yb3VuZCgobmljZU1pbiArIGogKiBzcGFjaW5nKSAqIGZhY3RvcikgLyBmYWN0b3IsIG1pbiwgcmVsYXRpdmVMYWJlbFNpemUobWluLCBtaW5TcGFjaW5nLCBnZW5lcmF0aW9uT3B0aW9ucykpKSB7XG4gICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG5pY2VNaW4gPCBtaW4pIHtcbiAgICAgICAgICAgIGorKztcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IoOyBqIDwgbnVtU3BhY2VzOyArK2ope1xuICAgICAgICBjb25zdCB0aWNrVmFsdWUgPSBNYXRoLnJvdW5kKChuaWNlTWluICsgaiAqIHNwYWNpbmcpICogZmFjdG9yKSAvIGZhY3RvcjtcbiAgICAgICAgaWYgKG1heERlZmluZWQgJiYgdGlja1ZhbHVlID4gbWF4KSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aWNrcy5wdXNoKHtcbiAgICAgICAgICAgIHZhbHVlOiB0aWNrVmFsdWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChtYXhEZWZpbmVkICYmIGluY2x1ZGVCb3VuZHMgJiYgbmljZU1heCAhPT0gbWF4KSB7XG4gICAgICAgIGlmICh0aWNrcy5sZW5ndGggJiYgYWxtb3N0RXF1YWxzKHRpY2tzW3RpY2tzLmxlbmd0aCAtIDFdLnZhbHVlLCBtYXgsIHJlbGF0aXZlTGFiZWxTaXplKG1heCwgbWluU3BhY2luZywgZ2VuZXJhdGlvbk9wdGlvbnMpKSkge1xuICAgICAgICAgICAgdGlja3NbdGlja3MubGVuZ3RoIC0gMV0udmFsdWUgPSBtYXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aWNrcy5wdXNoKHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogbWF4XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIW1heERlZmluZWQgfHwgbmljZU1heCA9PT0gbWF4KSB7XG4gICAgICAgIHRpY2tzLnB1c2goe1xuICAgICAgICAgICAgdmFsdWU6IG5pY2VNYXhcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aWNrcztcbn1cbmZ1bmN0aW9uIHJlbGF0aXZlTGFiZWxTaXplKHZhbHVlLCBtaW5TcGFjaW5nLCB7IGhvcml6b250YWwgLCBtaW5Sb3RhdGlvbiAgfSkge1xuICAgIGNvbnN0IHJhZCA9IHRvUmFkaWFucyhtaW5Sb3RhdGlvbik7XG4gICAgY29uc3QgcmF0aW8gPSAoaG9yaXpvbnRhbCA/IE1hdGguc2luKHJhZCkgOiBNYXRoLmNvcyhyYWQpKSB8fCAwLjAwMTtcbiAgICBjb25zdCBsZW5ndGggPSAwLjc1ICogbWluU3BhY2luZyAqICgnJyArIHZhbHVlKS5sZW5ndGg7XG4gICAgcmV0dXJuIE1hdGgubWluKG1pblNwYWNpbmcgLyByYXRpbywgbGVuZ3RoKTtcbn1cbmNsYXNzIExpbmVhclNjYWxlQmFzZSBleHRlbmRzIFNjYWxlIHtcbiAgICBjb25zdHJ1Y3RvcihjZmcpe1xuICAgICAgICBzdXBlcihjZmcpO1xuICAgICAgICAgdGhpcy5zdGFydCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuZW5kID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5fc3RhcnRWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuX2VuZFZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl92YWx1ZVJhbmdlID0gMDtcbiAgICB9XG4gICAgcGFyc2UocmF3LCBpbmRleCkge1xuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZihyYXcpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKHR5cGVvZiByYXcgPT09ICdudW1iZXInIHx8IHJhdyBpbnN0YW5jZW9mIE51bWJlcikgJiYgIWlzRmluaXRlKCtyYXcpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gK3JhdztcbiAgICB9XG4gICAgaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpIHtcbiAgICAgICAgY29uc3QgeyBiZWdpbkF0WmVybyAgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgeyBtaW5EZWZpbmVkICwgbWF4RGVmaW5lZCAgfSA9IHRoaXMuZ2V0VXNlckJvdW5kcygpO1xuICAgICAgICBsZXQgeyBtaW4gLCBtYXggIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBzZXRNaW4gPSAodik9Pm1pbiA9IG1pbkRlZmluZWQgPyBtaW4gOiB2O1xuICAgICAgICBjb25zdCBzZXRNYXggPSAodik9Pm1heCA9IG1heERlZmluZWQgPyBtYXggOiB2O1xuICAgICAgICBpZiAoYmVnaW5BdFplcm8pIHtcbiAgICAgICAgICAgIGNvbnN0IG1pblNpZ24gPSBzaWduKG1pbik7XG4gICAgICAgICAgICBjb25zdCBtYXhTaWduID0gc2lnbihtYXgpO1xuICAgICAgICAgICAgaWYgKG1pblNpZ24gPCAwICYmIG1heFNpZ24gPCAwKSB7XG4gICAgICAgICAgICAgICAgc2V0TWF4KDApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtaW5TaWduID4gMCAmJiBtYXhTaWduID4gMCkge1xuICAgICAgICAgICAgICAgIHNldE1pbigwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobWluID09PSBtYXgpIHtcbiAgICAgICAgICAgIGxldCBvZmZzZXQgPSBtYXggPT09IDAgPyAxIDogTWF0aC5hYnMobWF4ICogMC4wNSk7XG4gICAgICAgICAgICBzZXRNYXgobWF4ICsgb2Zmc2V0KTtcbiAgICAgICAgICAgIGlmICghYmVnaW5BdFplcm8pIHtcbiAgICAgICAgICAgICAgICBzZXRNaW4obWluIC0gb2Zmc2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1pbiA9IG1pbjtcbiAgICAgICAgdGhpcy5tYXggPSBtYXg7XG4gICAgfVxuICAgIGdldFRpY2tMaW1pdCgpIHtcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSB0aGlzLm9wdGlvbnMudGlja3M7XG4gICAgICAgIGxldCB7IG1heFRpY2tzTGltaXQgLCBzdGVwU2l6ZSAgfSA9IHRpY2tPcHRzO1xuICAgICAgICBsZXQgbWF4VGlja3M7XG4gICAgICAgIGlmIChzdGVwU2l6ZSkge1xuICAgICAgICAgICAgbWF4VGlja3MgPSBNYXRoLmNlaWwodGhpcy5tYXggLyBzdGVwU2l6ZSkgLSBNYXRoLmZsb29yKHRoaXMubWluIC8gc3RlcFNpemUpICsgMTtcbiAgICAgICAgICAgIGlmIChtYXhUaWNrcyA+IDEwMDApIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYHNjYWxlcy4ke3RoaXMuaWR9LnRpY2tzLnN0ZXBTaXplOiAke3N0ZXBTaXplfSB3b3VsZCByZXN1bHQgZ2VuZXJhdGluZyB1cCB0byAke21heFRpY2tzfSB0aWNrcy4gTGltaXRpbmcgdG8gMTAwMC5gKTtcbiAgICAgICAgICAgICAgICBtYXhUaWNrcyA9IDEwMDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXhUaWNrcyA9IHRoaXMuY29tcHV0ZVRpY2tMaW1pdCgpO1xuICAgICAgICAgICAgbWF4VGlja3NMaW1pdCA9IG1heFRpY2tzTGltaXQgfHwgMTE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1heFRpY2tzTGltaXQpIHtcbiAgICAgICAgICAgIG1heFRpY2tzID0gTWF0aC5taW4obWF4VGlja3NMaW1pdCwgbWF4VGlja3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXhUaWNrcztcbiAgICB9XG4gY29tcHV0ZVRpY2tMaW1pdCgpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICB9XG4gICAgYnVpbGRUaWNrcygpIHtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSBvcHRzLnRpY2tzO1xuICAgICAgICBsZXQgbWF4VGlja3MgPSB0aGlzLmdldFRpY2tMaW1pdCgpO1xuICAgICAgICBtYXhUaWNrcyA9IE1hdGgubWF4KDIsIG1heFRpY2tzKTtcbiAgICAgICAgY29uc3QgbnVtZXJpY0dlbmVyYXRvck9wdGlvbnMgPSB7XG4gICAgICAgICAgICBtYXhUaWNrcyxcbiAgICAgICAgICAgIGJvdW5kczogb3B0cy5ib3VuZHMsXG4gICAgICAgICAgICBtaW46IG9wdHMubWluLFxuICAgICAgICAgICAgbWF4OiBvcHRzLm1heCxcbiAgICAgICAgICAgIHByZWNpc2lvbjogdGlja09wdHMucHJlY2lzaW9uLFxuICAgICAgICAgICAgc3RlcDogdGlja09wdHMuc3RlcFNpemUsXG4gICAgICAgICAgICBjb3VudDogdGlja09wdHMuY291bnQsXG4gICAgICAgICAgICBtYXhEaWdpdHM6IHRoaXMuX21heERpZ2l0cygpLFxuICAgICAgICAgICAgaG9yaXpvbnRhbDogdGhpcy5pc0hvcml6b250YWwoKSxcbiAgICAgICAgICAgIG1pblJvdGF0aW9uOiB0aWNrT3B0cy5taW5Sb3RhdGlvbiB8fCAwLFxuICAgICAgICAgICAgaW5jbHVkZUJvdW5kczogdGlja09wdHMuaW5jbHVkZUJvdW5kcyAhPT0gZmFsc2VcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZGF0YVJhbmdlID0gdGhpcy5fcmFuZ2UgfHwgdGhpcztcbiAgICAgICAgY29uc3QgdGlja3MgPSBnZW5lcmF0ZVRpY2tzJDEobnVtZXJpY0dlbmVyYXRvck9wdGlvbnMsIGRhdGFSYW5nZSk7XG4gICAgICAgIGlmIChvcHRzLmJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgICAgICAgX3NldE1pbkFuZE1heEJ5S2V5KHRpY2tzLCB0aGlzLCAndmFsdWUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0cy5yZXZlcnNlKSB7XG4gICAgICAgICAgICB0aWNrcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0ID0gdGhpcy5tYXg7XG4gICAgICAgICAgICB0aGlzLmVuZCA9IHRoaXMubWluO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zdGFydCA9IHRoaXMubWluO1xuICAgICAgICAgICAgdGhpcy5lbmQgPSB0aGlzLm1heDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGlja3M7XG4gICAgfVxuIGNvbmZpZ3VyZSgpIHtcbiAgICAgICAgY29uc3QgdGlja3MgPSB0aGlzLnRpY2tzO1xuICAgICAgICBsZXQgc3RhcnQgPSB0aGlzLm1pbjtcbiAgICAgICAgbGV0IGVuZCA9IHRoaXMubWF4O1xuICAgICAgICBzdXBlci5jb25maWd1cmUoKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5vZmZzZXQgJiYgdGlja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSAoZW5kIC0gc3RhcnQpIC8gTWF0aC5tYXgodGlja3MubGVuZ3RoIC0gMSwgMSkgLyAyO1xuICAgICAgICAgICAgc3RhcnQgLT0gb2Zmc2V0O1xuICAgICAgICAgICAgZW5kICs9IG9mZnNldDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zdGFydFZhbHVlID0gc3RhcnQ7XG4gICAgICAgIHRoaXMuX2VuZFZhbHVlID0gZW5kO1xuICAgICAgICB0aGlzLl92YWx1ZVJhbmdlID0gZW5kIC0gc3RhcnQ7XG4gICAgfVxuICAgIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGZvcm1hdE51bWJlcih2YWx1ZSwgdGhpcy5jaGFydC5vcHRpb25zLmxvY2FsZSwgdGhpcy5vcHRpb25zLnRpY2tzLmZvcm1hdCk7XG4gICAgfVxufVxuXG5jbGFzcyBMaW5lYXJTY2FsZSBleHRlbmRzIExpbmVhclNjYWxlQmFzZSB7XG4gICAgc3RhdGljIGlkID0gJ2xpbmVhcic7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICB0aWNrczoge1xuICAgICAgICAgICAgY2FsbGJhY2s6IFRpY2tzLmZvcm1hdHRlcnMubnVtZXJpY1xuICAgICAgICB9XG4gICAgfTtcbiAgICBkZXRlcm1pbmVEYXRhTGltaXRzKCkge1xuICAgICAgICBjb25zdCB7IG1pbiAsIG1heCAgfSA9IHRoaXMuZ2V0TWluTWF4KHRydWUpO1xuICAgICAgICB0aGlzLm1pbiA9IGlzTnVtYmVyRmluaXRlKG1pbikgPyBtaW4gOiAwO1xuICAgICAgICB0aGlzLm1heCA9IGlzTnVtYmVyRmluaXRlKG1heCkgPyBtYXggOiAxO1xuICAgICAgICB0aGlzLmhhbmRsZVRpY2tSYW5nZU9wdGlvbnMoKTtcbiAgICB9XG4gY29tcHV0ZVRpY2tMaW1pdCgpIHtcbiAgICAgICAgY29uc3QgaG9yaXpvbnRhbCA9IHRoaXMuaXNIb3Jpem9udGFsKCk7XG4gICAgICAgIGNvbnN0IGxlbmd0aCA9IGhvcml6b250YWwgPyB0aGlzLndpZHRoIDogdGhpcy5oZWlnaHQ7XG4gICAgICAgIGNvbnN0IG1pblJvdGF0aW9uID0gdG9SYWRpYW5zKHRoaXMub3B0aW9ucy50aWNrcy5taW5Sb3RhdGlvbik7XG4gICAgICAgIGNvbnN0IHJhdGlvID0gKGhvcml6b250YWwgPyBNYXRoLnNpbihtaW5Sb3RhdGlvbikgOiBNYXRoLmNvcyhtaW5Sb3RhdGlvbikpIHx8IDAuMDAxO1xuICAgICAgICBjb25zdCB0aWNrRm9udCA9IHRoaXMuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoMCk7XG4gICAgICAgIHJldHVybiBNYXRoLmNlaWwobGVuZ3RoIC8gTWF0aC5taW4oNDAsIHRpY2tGb250LmxpbmVIZWlnaHQgLyByYXRpbykpO1xuICAgIH1cbiAgICBnZXRQaXhlbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbCA/IE5hTiA6IHRoaXMuZ2V0UGl4ZWxGb3JEZWNpbWFsKCh2YWx1ZSAtIHRoaXMuX3N0YXJ0VmFsdWUpIC8gdGhpcy5fdmFsdWVSYW5nZSk7XG4gICAgfVxuICAgIGdldFZhbHVlRm9yUGl4ZWwocGl4ZWwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0YXJ0VmFsdWUgKyB0aGlzLmdldERlY2ltYWxGb3JQaXhlbChwaXhlbCkgKiB0aGlzLl92YWx1ZVJhbmdlO1xuICAgIH1cbn1cblxuY29uc3QgbG9nMTBGbG9vciA9ICh2KT0+TWF0aC5mbG9vcihsb2cxMCh2KSk7XG5jb25zdCBjaGFuZ2VFeHBvbmVudCA9ICh2LCBtKT0+TWF0aC5wb3coMTAsIGxvZzEwRmxvb3IodikgKyBtKTtcbmZ1bmN0aW9uIGlzTWFqb3IodGlja1ZhbCkge1xuICAgIGNvbnN0IHJlbWFpbiA9IHRpY2tWYWwgLyBNYXRoLnBvdygxMCwgbG9nMTBGbG9vcih0aWNrVmFsKSk7XG4gICAgcmV0dXJuIHJlbWFpbiA9PT0gMTtcbn1cbmZ1bmN0aW9uIHN0ZXBzKG1pbiwgbWF4LCByYW5nZUV4cCkge1xuICAgIGNvbnN0IHJhbmdlU3RlcCA9IE1hdGgucG93KDEwLCByYW5nZUV4cCk7XG4gICAgY29uc3Qgc3RhcnQgPSBNYXRoLmZsb29yKG1pbiAvIHJhbmdlU3RlcCk7XG4gICAgY29uc3QgZW5kID0gTWF0aC5jZWlsKG1heCAvIHJhbmdlU3RlcCk7XG4gICAgcmV0dXJuIGVuZCAtIHN0YXJ0O1xufVxuZnVuY3Rpb24gc3RhcnRFeHAobWluLCBtYXgpIHtcbiAgICBjb25zdCByYW5nZSA9IG1heCAtIG1pbjtcbiAgICBsZXQgcmFuZ2VFeHAgPSBsb2cxMEZsb29yKHJhbmdlKTtcbiAgICB3aGlsZShzdGVwcyhtaW4sIG1heCwgcmFuZ2VFeHApID4gMTApe1xuICAgICAgICByYW5nZUV4cCsrO1xuICAgIH1cbiAgICB3aGlsZShzdGVwcyhtaW4sIG1heCwgcmFuZ2VFeHApIDwgMTApe1xuICAgICAgICByYW5nZUV4cC0tO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5taW4ocmFuZ2VFeHAsIGxvZzEwRmxvb3IobWluKSk7XG59XG4gZnVuY3Rpb24gZ2VuZXJhdGVUaWNrcyhnZW5lcmF0aW9uT3B0aW9ucywgeyBtaW4gLCBtYXggIH0pIHtcbiAgICBtaW4gPSBmaW5pdGVPckRlZmF1bHQoZ2VuZXJhdGlvbk9wdGlvbnMubWluLCBtaW4pO1xuICAgIGNvbnN0IHRpY2tzID0gW107XG4gICAgY29uc3QgbWluRXhwID0gbG9nMTBGbG9vcihtaW4pO1xuICAgIGxldCBleHAgPSBzdGFydEV4cChtaW4sIG1heCk7XG4gICAgbGV0IHByZWNpc2lvbiA9IGV4cCA8IDAgPyBNYXRoLnBvdygxMCwgTWF0aC5hYnMoZXhwKSkgOiAxO1xuICAgIGNvbnN0IHN0ZXBTaXplID0gTWF0aC5wb3coMTAsIGV4cCk7XG4gICAgY29uc3QgYmFzZSA9IG1pbkV4cCA+IGV4cCA/IE1hdGgucG93KDEwLCBtaW5FeHApIDogMDtcbiAgICBjb25zdCBzdGFydCA9IE1hdGgucm91bmQoKG1pbiAtIGJhc2UpICogcHJlY2lzaW9uKSAvIHByZWNpc2lvbjtcbiAgICBjb25zdCBvZmZzZXQgPSBNYXRoLmZsb29yKChtaW4gLSBiYXNlKSAvIHN0ZXBTaXplIC8gMTApICogc3RlcFNpemUgKiAxMDtcbiAgICBsZXQgc2lnbmlmaWNhbmQgPSBNYXRoLmZsb29yKChzdGFydCAtIG9mZnNldCkgLyBNYXRoLnBvdygxMCwgZXhwKSk7XG4gICAgbGV0IHZhbHVlID0gZmluaXRlT3JEZWZhdWx0KGdlbmVyYXRpb25PcHRpb25zLm1pbiwgTWF0aC5yb3VuZCgoYmFzZSArIG9mZnNldCArIHNpZ25pZmljYW5kICogTWF0aC5wb3coMTAsIGV4cCkpICogcHJlY2lzaW9uKSAvIHByZWNpc2lvbik7XG4gICAgd2hpbGUodmFsdWUgPCBtYXgpe1xuICAgICAgICB0aWNrcy5wdXNoKHtcbiAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgbWFqb3I6IGlzTWFqb3IodmFsdWUpLFxuICAgICAgICAgICAgc2lnbmlmaWNhbmRcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChzaWduaWZpY2FuZCA+PSAxMCkge1xuICAgICAgICAgICAgc2lnbmlmaWNhbmQgPSBzaWduaWZpY2FuZCA8IDE1ID8gMTUgOiAyMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNpZ25pZmljYW5kKys7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNpZ25pZmljYW5kID49IDIwKSB7XG4gICAgICAgICAgICBleHArKztcbiAgICAgICAgICAgIHNpZ25pZmljYW5kID0gMjtcbiAgICAgICAgICAgIHByZWNpc2lvbiA9IGV4cCA+PSAwID8gMSA6IHByZWNpc2lvbjtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZSA9IE1hdGgucm91bmQoKGJhc2UgKyBvZmZzZXQgKyBzaWduaWZpY2FuZCAqIE1hdGgucG93KDEwLCBleHApKSAqIHByZWNpc2lvbikgLyBwcmVjaXNpb247XG4gICAgfVxuICAgIGNvbnN0IGxhc3RUaWNrID0gZmluaXRlT3JEZWZhdWx0KGdlbmVyYXRpb25PcHRpb25zLm1heCwgdmFsdWUpO1xuICAgIHRpY2tzLnB1c2goe1xuICAgICAgICB2YWx1ZTogbGFzdFRpY2ssXG4gICAgICAgIG1ham9yOiBpc01ham9yKGxhc3RUaWNrKSxcbiAgICAgICAgc2lnbmlmaWNhbmRcbiAgICB9KTtcbiAgICByZXR1cm4gdGlja3M7XG59XG5jbGFzcyBMb2dhcml0aG1pY1NjYWxlIGV4dGVuZHMgU2NhbGUge1xuICAgIHN0YXRpYyBpZCA9ICdsb2dhcml0aG1pYyc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICB0aWNrczoge1xuICAgICAgICAgICAgY2FsbGJhY2s6IFRpY2tzLmZvcm1hdHRlcnMubG9nYXJpdGhtaWMsXG4gICAgICAgICAgICBtYWpvcjoge1xuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoY2ZnKTtcbiAgICAgICAgIHRoaXMuc3RhcnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLmVuZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuX3N0YXJ0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3ZhbHVlUmFuZ2UgPSAwO1xuICAgIH1cbiAgICBwYXJzZShyYXcsIGluZGV4KSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gTGluZWFyU2NhbGVCYXNlLnByb3RvdHlwZS5wYXJzZS5hcHBseSh0aGlzLCBbXG4gICAgICAgICAgICByYXcsXG4gICAgICAgICAgICBpbmRleFxuICAgICAgICBdKTtcbiAgICAgICAgaWYgKHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLl96ZXJvID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzTnVtYmVyRmluaXRlKHZhbHVlKSAmJiB2YWx1ZSA+IDAgPyB2YWx1ZSA6IG51bGw7XG4gICAgfVxuICAgIGRldGVybWluZURhdGFMaW1pdHMoKSB7XG4gICAgICAgIGNvbnN0IHsgbWluICwgbWF4ICB9ID0gdGhpcy5nZXRNaW5NYXgodHJ1ZSk7XG4gICAgICAgIHRoaXMubWluID0gaXNOdW1iZXJGaW5pdGUobWluKSA/IE1hdGgubWF4KDAsIG1pbikgOiBudWxsO1xuICAgICAgICB0aGlzLm1heCA9IGlzTnVtYmVyRmluaXRlKG1heCkgPyBNYXRoLm1heCgwLCBtYXgpIDogbnVsbDtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5iZWdpbkF0WmVybykge1xuICAgICAgICAgICAgdGhpcy5femVybyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3plcm8gJiYgdGhpcy5taW4gIT09IHRoaXMuX3N1Z2dlc3RlZE1pbiAmJiAhaXNOdW1iZXJGaW5pdGUodGhpcy5fdXNlck1pbikpIHtcbiAgICAgICAgICAgIHRoaXMubWluID0gbWluID09PSBjaGFuZ2VFeHBvbmVudCh0aGlzLm1pbiwgMCkgPyBjaGFuZ2VFeHBvbmVudCh0aGlzLm1pbiwgLTEpIDogY2hhbmdlRXhwb25lbnQodGhpcy5taW4sIDApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpO1xuICAgIH1cbiAgICBoYW5kbGVUaWNrUmFuZ2VPcHRpb25zKCkge1xuICAgICAgICBjb25zdCB7IG1pbkRlZmluZWQgLCBtYXhEZWZpbmVkICB9ID0gdGhpcy5nZXRVc2VyQm91bmRzKCk7XG4gICAgICAgIGxldCBtaW4gPSB0aGlzLm1pbjtcbiAgICAgICAgbGV0IG1heCA9IHRoaXMubWF4O1xuICAgICAgICBjb25zdCBzZXRNaW4gPSAodik9Pm1pbiA9IG1pbkRlZmluZWQgPyBtaW4gOiB2O1xuICAgICAgICBjb25zdCBzZXRNYXggPSAodik9Pm1heCA9IG1heERlZmluZWQgPyBtYXggOiB2O1xuICAgICAgICBpZiAobWluID09PSBtYXgpIHtcbiAgICAgICAgICAgIGlmIChtaW4gPD0gMCkge1xuICAgICAgICAgICAgICAgIHNldE1pbigxKTtcbiAgICAgICAgICAgICAgICBzZXRNYXgoMTApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZXRNaW4oY2hhbmdlRXhwb25lbnQobWluLCAtMSkpO1xuICAgICAgICAgICAgICAgIHNldE1heChjaGFuZ2VFeHBvbmVudChtYXgsICsxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1pbiA8PSAwKSB7XG4gICAgICAgICAgICBzZXRNaW4oY2hhbmdlRXhwb25lbnQobWF4LCAtMSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXggPD0gMCkge1xuICAgICAgICAgICAgc2V0TWF4KGNoYW5nZUV4cG9uZW50KG1pbiwgKzEpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1pbiA9IG1pbjtcbiAgICAgICAgdGhpcy5tYXggPSBtYXg7XG4gICAgfVxuICAgIGJ1aWxkVGlja3MoKSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGdlbmVyYXRpb25PcHRpb25zID0ge1xuICAgICAgICAgICAgbWluOiB0aGlzLl91c2VyTWluLFxuICAgICAgICAgICAgbWF4OiB0aGlzLl91c2VyTWF4XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHRpY2tzID0gZ2VuZXJhdGVUaWNrcyhnZW5lcmF0aW9uT3B0aW9ucywgdGhpcyk7XG4gICAgICAgIGlmIChvcHRzLmJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgICAgICAgX3NldE1pbkFuZE1heEJ5S2V5KHRpY2tzLCB0aGlzLCAndmFsdWUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0cy5yZXZlcnNlKSB7XG4gICAgICAgICAgICB0aWNrcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0ID0gdGhpcy5tYXg7XG4gICAgICAgICAgICB0aGlzLmVuZCA9IHRoaXMubWluO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zdGFydCA9IHRoaXMubWluO1xuICAgICAgICAgICAgdGhpcy5lbmQgPSB0aGlzLm1heDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGlja3M7XG4gICAgfVxuIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPyAnMCcgOiBmb3JtYXROdW1iZXIodmFsdWUsIHRoaXMuY2hhcnQub3B0aW9ucy5sb2NhbGUsIHRoaXMub3B0aW9ucy50aWNrcy5mb3JtYXQpO1xuICAgIH1cbiBjb25maWd1cmUoKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5taW47XG4gICAgICAgIHN1cGVyLmNvbmZpZ3VyZSgpO1xuICAgICAgICB0aGlzLl9zdGFydFZhbHVlID0gbG9nMTAoc3RhcnQpO1xuICAgICAgICB0aGlzLl92YWx1ZVJhbmdlID0gbG9nMTAodGhpcy5tYXgpIC0gbG9nMTAoc3RhcnQpO1xuICAgIH1cbiAgICBnZXRQaXhlbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMubWluO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCBpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGl4ZWxGb3JEZWNpbWFsKHZhbHVlID09PSB0aGlzLm1pbiA/IDAgOiAobG9nMTAodmFsdWUpIC0gdGhpcy5fc3RhcnRWYWx1ZSkgLyB0aGlzLl92YWx1ZVJhbmdlKTtcbiAgICB9XG4gICAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgICAgICBjb25zdCBkZWNpbWFsID0gdGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpO1xuICAgICAgICByZXR1cm4gTWF0aC5wb3coMTAsIHRoaXMuX3N0YXJ0VmFsdWUgKyBkZWNpbWFsICogdGhpcy5fdmFsdWVSYW5nZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRUaWNrQmFja2Ryb3BIZWlnaHQob3B0cykge1xuICAgIGNvbnN0IHRpY2tPcHRzID0gb3B0cy50aWNrcztcbiAgICBpZiAodGlja09wdHMuZGlzcGxheSAmJiBvcHRzLmRpc3BsYXkpIHtcbiAgICAgICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyh0aWNrT3B0cy5iYWNrZHJvcFBhZGRpbmcpO1xuICAgICAgICByZXR1cm4gdmFsdWVPckRlZmF1bHQodGlja09wdHMuZm9udCAmJiB0aWNrT3B0cy5mb250LnNpemUsIGRlZmF1bHRzLmZvbnQuc2l6ZSkgKyBwYWRkaW5nLmhlaWdodDtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5mdW5jdGlvbiBtZWFzdXJlTGFiZWxTaXplKGN0eCwgZm9udCwgbGFiZWwpIHtcbiAgICBsYWJlbCA9IGlzQXJyYXkobGFiZWwpID8gbGFiZWwgOiBbXG4gICAgICAgIGxhYmVsXG4gICAgXTtcbiAgICByZXR1cm4ge1xuICAgICAgICB3OiBfbG9uZ2VzdFRleHQoY3R4LCBmb250LnN0cmluZywgbGFiZWwpLFxuICAgICAgICBoOiBsYWJlbC5sZW5ndGggKiBmb250LmxpbmVIZWlnaHRcbiAgICB9O1xufVxuZnVuY3Rpb24gZGV0ZXJtaW5lTGltaXRzKGFuZ2xlLCBwb3MsIHNpemUsIG1pbiwgbWF4KSB7XG4gICAgaWYgKGFuZ2xlID09PSBtaW4gfHwgYW5nbGUgPT09IG1heCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhcnQ6IHBvcyAtIHNpemUgLyAyLFxuICAgICAgICAgICAgZW5kOiBwb3MgKyBzaXplIC8gMlxuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZiAoYW5nbGUgPCBtaW4gfHwgYW5nbGUgPiBtYXgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN0YXJ0OiBwb3MgLSBzaXplLFxuICAgICAgICAgICAgZW5kOiBwb3NcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IHBvcyxcbiAgICAgICAgZW5kOiBwb3MgKyBzaXplXG4gICAgfTtcbn1cbiBmdW5jdGlvbiBmaXRXaXRoUG9pbnRMYWJlbHMoc2NhbGUpIHtcbiAgICBjb25zdCBvcmlnID0ge1xuICAgICAgICBsOiBzY2FsZS5sZWZ0ICsgc2NhbGUuX3BhZGRpbmcubGVmdCxcbiAgICAgICAgcjogc2NhbGUucmlnaHQgLSBzY2FsZS5fcGFkZGluZy5yaWdodCxcbiAgICAgICAgdDogc2NhbGUudG9wICsgc2NhbGUuX3BhZGRpbmcudG9wLFxuICAgICAgICBiOiBzY2FsZS5ib3R0b20gLSBzY2FsZS5fcGFkZGluZy5ib3R0b21cbiAgICB9O1xuICAgIGNvbnN0IGxpbWl0cyA9IE9iamVjdC5hc3NpZ24oe30sIG9yaWcpO1xuICAgIGNvbnN0IGxhYmVsU2l6ZXMgPSBbXTtcbiAgICBjb25zdCBwYWRkaW5nID0gW107XG4gICAgY29uc3QgdmFsdWVDb3VudCA9IHNjYWxlLl9wb2ludExhYmVscy5sZW5ndGg7XG4gICAgY29uc3QgcG9pbnRMYWJlbE9wdHMgPSBzY2FsZS5vcHRpb25zLnBvaW50TGFiZWxzO1xuICAgIGNvbnN0IGFkZGl0aW9uYWxBbmdsZSA9IHBvaW50TGFiZWxPcHRzLmNlbnRlclBvaW50TGFiZWxzID8gUEkgLyB2YWx1ZUNvdW50IDogMDtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgdmFsdWVDb3VudDsgaSsrKXtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHBvaW50TGFiZWxPcHRzLnNldENvbnRleHQoc2NhbGUuZ2V0UG9pbnRMYWJlbENvbnRleHQoaSkpO1xuICAgICAgICBwYWRkaW5nW2ldID0gb3B0cy5wYWRkaW5nO1xuICAgICAgICBjb25zdCBwb2ludFBvc2l0aW9uID0gc2NhbGUuZ2V0UG9pbnRQb3NpdGlvbihpLCBzY2FsZS5kcmF3aW5nQXJlYSArIHBhZGRpbmdbaV0sIGFkZGl0aW9uYWxBbmdsZSk7XG4gICAgICAgIGNvbnN0IHBsRm9udCA9IHRvRm9udChvcHRzLmZvbnQpO1xuICAgICAgICBjb25zdCB0ZXh0U2l6ZSA9IG1lYXN1cmVMYWJlbFNpemUoc2NhbGUuY3R4LCBwbEZvbnQsIHNjYWxlLl9wb2ludExhYmVsc1tpXSk7XG4gICAgICAgIGxhYmVsU2l6ZXNbaV0gPSB0ZXh0U2l6ZTtcbiAgICAgICAgY29uc3QgYW5nbGVSYWRpYW5zID0gX25vcm1hbGl6ZUFuZ2xlKHNjYWxlLmdldEluZGV4QW5nbGUoaSkgKyBhZGRpdGlvbmFsQW5nbGUpO1xuICAgICAgICBjb25zdCBhbmdsZSA9IE1hdGgucm91bmQodG9EZWdyZWVzKGFuZ2xlUmFkaWFucykpO1xuICAgICAgICBjb25zdCBoTGltaXRzID0gZGV0ZXJtaW5lTGltaXRzKGFuZ2xlLCBwb2ludFBvc2l0aW9uLngsIHRleHRTaXplLncsIDAsIDE4MCk7XG4gICAgICAgIGNvbnN0IHZMaW1pdHMgPSBkZXRlcm1pbmVMaW1pdHMoYW5nbGUsIHBvaW50UG9zaXRpb24ueSwgdGV4dFNpemUuaCwgOTAsIDI3MCk7XG4gICAgICAgIHVwZGF0ZUxpbWl0cyhsaW1pdHMsIG9yaWcsIGFuZ2xlUmFkaWFucywgaExpbWl0cywgdkxpbWl0cyk7XG4gICAgfVxuICAgIHNjYWxlLnNldENlbnRlclBvaW50KG9yaWcubCAtIGxpbWl0cy5sLCBsaW1pdHMuciAtIG9yaWcuciwgb3JpZy50IC0gbGltaXRzLnQsIGxpbWl0cy5iIC0gb3JpZy5iKTtcbiAgICBzY2FsZS5fcG9pbnRMYWJlbEl0ZW1zID0gYnVpbGRQb2ludExhYmVsSXRlbXMoc2NhbGUsIGxhYmVsU2l6ZXMsIHBhZGRpbmcpO1xufVxuZnVuY3Rpb24gdXBkYXRlTGltaXRzKGxpbWl0cywgb3JpZywgYW5nbGUsIGhMaW1pdHMsIHZMaW1pdHMpIHtcbiAgICBjb25zdCBzaW4gPSBNYXRoLmFicyhNYXRoLnNpbihhbmdsZSkpO1xuICAgIGNvbnN0IGNvcyA9IE1hdGguYWJzKE1hdGguY29zKGFuZ2xlKSk7XG4gICAgbGV0IHggPSAwO1xuICAgIGxldCB5ID0gMDtcbiAgICBpZiAoaExpbWl0cy5zdGFydCA8IG9yaWcubCkge1xuICAgICAgICB4ID0gKG9yaWcubCAtIGhMaW1pdHMuc3RhcnQpIC8gc2luO1xuICAgICAgICBsaW1pdHMubCA9IE1hdGgubWluKGxpbWl0cy5sLCBvcmlnLmwgLSB4KTtcbiAgICB9IGVsc2UgaWYgKGhMaW1pdHMuZW5kID4gb3JpZy5yKSB7XG4gICAgICAgIHggPSAoaExpbWl0cy5lbmQgLSBvcmlnLnIpIC8gc2luO1xuICAgICAgICBsaW1pdHMuciA9IE1hdGgubWF4KGxpbWl0cy5yLCBvcmlnLnIgKyB4KTtcbiAgICB9XG4gICAgaWYgKHZMaW1pdHMuc3RhcnQgPCBvcmlnLnQpIHtcbiAgICAgICAgeSA9IChvcmlnLnQgLSB2TGltaXRzLnN0YXJ0KSAvIGNvcztcbiAgICAgICAgbGltaXRzLnQgPSBNYXRoLm1pbihsaW1pdHMudCwgb3JpZy50IC0geSk7XG4gICAgfSBlbHNlIGlmICh2TGltaXRzLmVuZCA+IG9yaWcuYikge1xuICAgICAgICB5ID0gKHZMaW1pdHMuZW5kIC0gb3JpZy5iKSAvIGNvcztcbiAgICAgICAgbGltaXRzLmIgPSBNYXRoLm1heChsaW1pdHMuYiwgb3JpZy5iICsgeSk7XG4gICAgfVxufVxuZnVuY3Rpb24gY3JlYXRlUG9pbnRMYWJlbEl0ZW0oc2NhbGUsIGluZGV4LCBpdGVtT3B0cykge1xuICAgIGNvbnN0IG91dGVyRGlzdGFuY2UgPSBzY2FsZS5kcmF3aW5nQXJlYTtcbiAgICBjb25zdCB7IGV4dHJhICwgYWRkaXRpb25hbEFuZ2xlICwgcGFkZGluZyAsIHNpemUgIH0gPSBpdGVtT3B0cztcbiAgICBjb25zdCBwb2ludExhYmVsUG9zaXRpb24gPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uKGluZGV4LCBvdXRlckRpc3RhbmNlICsgZXh0cmEgKyBwYWRkaW5nLCBhZGRpdGlvbmFsQW5nbGUpO1xuICAgIGNvbnN0IGFuZ2xlID0gTWF0aC5yb3VuZCh0b0RlZ3JlZXMoX25vcm1hbGl6ZUFuZ2xlKHBvaW50TGFiZWxQb3NpdGlvbi5hbmdsZSArIEhBTEZfUEkpKSk7XG4gICAgY29uc3QgeSA9IHlGb3JBbmdsZShwb2ludExhYmVsUG9zaXRpb24ueSwgc2l6ZS5oLCBhbmdsZSk7XG4gICAgY29uc3QgdGV4dEFsaWduID0gZ2V0VGV4dEFsaWduRm9yQW5nbGUoYW5nbGUpO1xuICAgIGNvbnN0IGxlZnQgPSBsZWZ0Rm9yVGV4dEFsaWduKHBvaW50TGFiZWxQb3NpdGlvbi54LCBzaXplLncsIHRleHRBbGlnbik7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgeDogcG9pbnRMYWJlbFBvc2l0aW9uLngsXG4gICAgICAgIHksXG4gICAgICAgIHRleHRBbGlnbixcbiAgICAgICAgbGVmdCxcbiAgICAgICAgdG9wOiB5LFxuICAgICAgICByaWdodDogbGVmdCArIHNpemUudyxcbiAgICAgICAgYm90dG9tOiB5ICsgc2l6ZS5oXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGlzTm90T3ZlcmxhcHBlZChpdGVtLCBhcmVhKSB7XG4gICAgaWYgKCFhcmVhKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCB7IGxlZnQgLCB0b3AgLCByaWdodCAsIGJvdHRvbSAgfSA9IGl0ZW07XG4gICAgY29uc3QgYXBleGVzSW5BcmVhID0gX2lzUG9pbnRJbkFyZWEoe1xuICAgICAgICB4OiBsZWZ0LFxuICAgICAgICB5OiB0b3BcbiAgICB9LCBhcmVhKSB8fCBfaXNQb2ludEluQXJlYSh7XG4gICAgICAgIHg6IGxlZnQsXG4gICAgICAgIHk6IGJvdHRvbVxuICAgIH0sIGFyZWEpIHx8IF9pc1BvaW50SW5BcmVhKHtcbiAgICAgICAgeDogcmlnaHQsXG4gICAgICAgIHk6IHRvcFxuICAgIH0sIGFyZWEpIHx8IF9pc1BvaW50SW5BcmVhKHtcbiAgICAgICAgeDogcmlnaHQsXG4gICAgICAgIHk6IGJvdHRvbVxuICAgIH0sIGFyZWEpO1xuICAgIHJldHVybiAhYXBleGVzSW5BcmVhO1xufVxuZnVuY3Rpb24gYnVpbGRQb2ludExhYmVsSXRlbXMoc2NhbGUsIGxhYmVsU2l6ZXMsIHBhZGRpbmcpIHtcbiAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgIGNvbnN0IHZhbHVlQ291bnQgPSBzY2FsZS5fcG9pbnRMYWJlbHMubGVuZ3RoO1xuICAgIGNvbnN0IG9wdHMgPSBzY2FsZS5vcHRpb25zO1xuICAgIGNvbnN0IHsgY2VudGVyUG9pbnRMYWJlbHMgLCBkaXNwbGF5ICB9ID0gb3B0cy5wb2ludExhYmVscztcbiAgICBjb25zdCBpdGVtT3B0cyA9IHtcbiAgICAgICAgZXh0cmE6IGdldFRpY2tCYWNrZHJvcEhlaWdodChvcHRzKSAvIDIsXG4gICAgICAgIGFkZGl0aW9uYWxBbmdsZTogY2VudGVyUG9pbnRMYWJlbHMgPyBQSSAvIHZhbHVlQ291bnQgOiAwXG4gICAgfTtcbiAgICBsZXQgYXJlYTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgdmFsdWVDb3VudDsgaSsrKXtcbiAgICAgICAgaXRlbU9wdHMucGFkZGluZyA9IHBhZGRpbmdbaV07XG4gICAgICAgIGl0ZW1PcHRzLnNpemUgPSBsYWJlbFNpemVzW2ldO1xuICAgICAgICBjb25zdCBpdGVtID0gY3JlYXRlUG9pbnRMYWJlbEl0ZW0oc2NhbGUsIGksIGl0ZW1PcHRzKTtcbiAgICAgICAgaXRlbXMucHVzaChpdGVtKTtcbiAgICAgICAgaWYgKGRpc3BsYXkgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgaXRlbS52aXNpYmxlID0gaXNOb3RPdmVybGFwcGVkKGl0ZW0sIGFyZWEpO1xuICAgICAgICAgICAgaWYgKGl0ZW0udmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIGFyZWEgPSBpdGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpdGVtcztcbn1cbmZ1bmN0aW9uIGdldFRleHRBbGlnbkZvckFuZ2xlKGFuZ2xlKSB7XG4gICAgaWYgKGFuZ2xlID09PSAwIHx8IGFuZ2xlID09PSAxODApIHtcbiAgICAgICAgcmV0dXJuICdjZW50ZXInO1xuICAgIH0gZWxzZSBpZiAoYW5nbGUgPCAxODApIHtcbiAgICAgICAgcmV0dXJuICdsZWZ0JztcbiAgICB9XG4gICAgcmV0dXJuICdyaWdodCc7XG59XG5mdW5jdGlvbiBsZWZ0Rm9yVGV4dEFsaWduKHgsIHcsIGFsaWduKSB7XG4gICAgaWYgKGFsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgIHggLT0gdztcbiAgICB9IGVsc2UgaWYgKGFsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICB4IC09IHcgLyAyO1xuICAgIH1cbiAgICByZXR1cm4geDtcbn1cbmZ1bmN0aW9uIHlGb3JBbmdsZSh5LCBoLCBhbmdsZSkge1xuICAgIGlmIChhbmdsZSA9PT0gOTAgfHwgYW5nbGUgPT09IDI3MCkge1xuICAgICAgICB5IC09IGggLyAyO1xuICAgIH0gZWxzZSBpZiAoYW5nbGUgPiAyNzAgfHwgYW5nbGUgPCA5MCkge1xuICAgICAgICB5IC09IGg7XG4gICAgfVxuICAgIHJldHVybiB5O1xufVxuZnVuY3Rpb24gZHJhd1BvaW50TGFiZWxCb3goY3R4LCBvcHRzLCBpdGVtKSB7XG4gICAgY29uc3QgeyBsZWZ0ICwgdG9wICwgcmlnaHQgLCBib3R0b20gIH0gPSBpdGVtO1xuICAgIGNvbnN0IHsgYmFja2Ryb3BDb2xvciAgfSA9IG9wdHM7XG4gICAgaWYgKCFpc051bGxPclVuZGVmKGJhY2tkcm9wQ29sb3IpKSB7XG4gICAgICAgIGNvbnN0IGJvcmRlclJhZGl1cyA9IHRvVFJCTENvcm5lcnMob3B0cy5ib3JkZXJSYWRpdXMpO1xuICAgICAgICBjb25zdCBwYWRkaW5nID0gdG9QYWRkaW5nKG9wdHMuYmFja2Ryb3BQYWRkaW5nKTtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGJhY2tkcm9wQ29sb3I7XG4gICAgICAgIGNvbnN0IGJhY2tkcm9wTGVmdCA9IGxlZnQgLSBwYWRkaW5nLmxlZnQ7XG4gICAgICAgIGNvbnN0IGJhY2tkcm9wVG9wID0gdG9wIC0gcGFkZGluZy50b3A7XG4gICAgICAgIGNvbnN0IGJhY2tkcm9wV2lkdGggPSByaWdodCAtIGxlZnQgKyBwYWRkaW5nLndpZHRoO1xuICAgICAgICBjb25zdCBiYWNrZHJvcEhlaWdodCA9IGJvdHRvbSAtIHRvcCArIHBhZGRpbmcuaGVpZ2h0O1xuICAgICAgICBpZiAoT2JqZWN0LnZhbHVlcyhib3JkZXJSYWRpdXMpLnNvbWUoKHYpPT52ICE9PSAwKSkge1xuICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgYWRkUm91bmRlZFJlY3RQYXRoKGN0eCwge1xuICAgICAgICAgICAgICAgIHg6IGJhY2tkcm9wTGVmdCxcbiAgICAgICAgICAgICAgICB5OiBiYWNrZHJvcFRvcCxcbiAgICAgICAgICAgICAgICB3OiBiYWNrZHJvcFdpZHRoLFxuICAgICAgICAgICAgICAgIGg6IGJhY2tkcm9wSGVpZ2h0LFxuICAgICAgICAgICAgICAgIHJhZGl1czogYm9yZGVyUmFkaXVzXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGN0eC5maWxsKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjdHguZmlsbFJlY3QoYmFja2Ryb3BMZWZ0LCBiYWNrZHJvcFRvcCwgYmFja2Ryb3BXaWR0aCwgYmFja2Ryb3BIZWlnaHQpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gZHJhd1BvaW50TGFiZWxzKHNjYWxlLCBsYWJlbENvdW50KSB7XG4gICAgY29uc3QgeyBjdHggLCBvcHRpb25zOiB7IHBvaW50TGFiZWxzICB9ICB9ID0gc2NhbGU7XG4gICAgZm9yKGxldCBpID0gbGFiZWxDb3VudCAtIDE7IGkgPj0gMDsgaS0tKXtcbiAgICAgICAgY29uc3QgaXRlbSA9IHNjYWxlLl9wb2ludExhYmVsSXRlbXNbaV07XG4gICAgICAgIGlmICghaXRlbS52aXNpYmxlKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcHRzQXRJbmRleCA9IHBvaW50TGFiZWxzLnNldENvbnRleHQoc2NhbGUuZ2V0UG9pbnRMYWJlbENvbnRleHQoaSkpO1xuICAgICAgICBkcmF3UG9pbnRMYWJlbEJveChjdHgsIG9wdHNBdEluZGV4LCBpdGVtKTtcbiAgICAgICAgY29uc3QgcGxGb250ID0gdG9Gb250KG9wdHNBdEluZGV4LmZvbnQpO1xuICAgICAgICBjb25zdCB7IHggLCB5ICwgdGV4dEFsaWduICB9ID0gaXRlbTtcbiAgICAgICAgcmVuZGVyVGV4dChjdHgsIHNjYWxlLl9wb2ludExhYmVsc1tpXSwgeCwgeSArIHBsRm9udC5saW5lSGVpZ2h0IC8gMiwgcGxGb250LCB7XG4gICAgICAgICAgICBjb2xvcjogb3B0c0F0SW5kZXguY29sb3IsXG4gICAgICAgICAgICB0ZXh0QWxpZ246IHRleHRBbGlnbixcbiAgICAgICAgICAgIHRleHRCYXNlbGluZTogJ21pZGRsZSdcbiAgICAgICAgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcGF0aFJhZGl1c0xpbmUoc2NhbGUsIHJhZGl1cywgY2lyY3VsYXIsIGxhYmVsQ291bnQpIHtcbiAgICBjb25zdCB7IGN0eCAgfSA9IHNjYWxlO1xuICAgIGlmIChjaXJjdWxhcikge1xuICAgICAgICBjdHguYXJjKHNjYWxlLnhDZW50ZXIsIHNjYWxlLnlDZW50ZXIsIHJhZGl1cywgMCwgVEFVKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcG9pbnRQb3NpdGlvbiA9IHNjYWxlLmdldFBvaW50UG9zaXRpb24oMCwgcmFkaXVzKTtcbiAgICAgICAgY3R4Lm1vdmVUbyhwb2ludFBvc2l0aW9uLngsIHBvaW50UG9zaXRpb24ueSk7XG4gICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCBsYWJlbENvdW50OyBpKyspe1xuICAgICAgICAgICAgcG9pbnRQb3NpdGlvbiA9IHNjYWxlLmdldFBvaW50UG9zaXRpb24oaSwgcmFkaXVzKTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8ocG9pbnRQb3NpdGlvbi54LCBwb2ludFBvc2l0aW9uLnkpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gZHJhd1JhZGl1c0xpbmUoc2NhbGUsIGdyaWRMaW5lT3B0cywgcmFkaXVzLCBsYWJlbENvdW50LCBib3JkZXJPcHRzKSB7XG4gICAgY29uc3QgY3R4ID0gc2NhbGUuY3R4O1xuICAgIGNvbnN0IGNpcmN1bGFyID0gZ3JpZExpbmVPcHRzLmNpcmN1bGFyO1xuICAgIGNvbnN0IHsgY29sb3IgLCBsaW5lV2lkdGggIH0gPSBncmlkTGluZU9wdHM7XG4gICAgaWYgKCFjaXJjdWxhciAmJiAhbGFiZWxDb3VudCB8fCAhY29sb3IgfHwgIWxpbmVXaWR0aCB8fCByYWRpdXMgPCAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY3R4LnNhdmUoKTtcbiAgICBjdHguc3Ryb2tlU3R5bGUgPSBjb2xvcjtcbiAgICBjdHgubGluZVdpZHRoID0gbGluZVdpZHRoO1xuICAgIGN0eC5zZXRMaW5lRGFzaChib3JkZXJPcHRzLmRhc2ggfHwgW10pO1xuICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IGJvcmRlck9wdHMuZGFzaE9mZnNldDtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgcGF0aFJhZGl1c0xpbmUoc2NhbGUsIHJhZGl1cywgY2lyY3VsYXIsIGxhYmVsQ291bnQpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBjdHguc3Ryb2tlKCk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVBvaW50TGFiZWxDb250ZXh0KHBhcmVudCwgaW5kZXgsIGxhYmVsKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUNvbnRleHQocGFyZW50LCB7XG4gICAgICAgIGxhYmVsLFxuICAgICAgICBpbmRleCxcbiAgICAgICAgdHlwZTogJ3BvaW50TGFiZWwnXG4gICAgfSk7XG59XG5jbGFzcyBSYWRpYWxMaW5lYXJTY2FsZSBleHRlbmRzIExpbmVhclNjYWxlQmFzZSB7XG4gICAgc3RhdGljIGlkID0gJ3JhZGlhbExpbmVhcic7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkaXNwbGF5OiB0cnVlLFxuICAgICAgICBhbmltYXRlOiB0cnVlLFxuICAgICAgICBwb3NpdGlvbjogJ2NoYXJ0QXJlYScsXG4gICAgICAgIGFuZ2xlTGluZXM6IHtcbiAgICAgICAgICAgIGRpc3BsYXk6IHRydWUsXG4gICAgICAgICAgICBsaW5lV2lkdGg6IDEsXG4gICAgICAgICAgICBib3JkZXJEYXNoOiBbXSxcbiAgICAgICAgICAgIGJvcmRlckRhc2hPZmZzZXQ6IDAuMFxuICAgICAgICB9LFxuICAgICAgICBncmlkOiB7XG4gICAgICAgICAgICBjaXJjdWxhcjogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgc3RhcnRBbmdsZTogMCxcbiAgICAgICAgdGlja3M6IHtcbiAgICAgICAgICAgIHNob3dMYWJlbEJhY2tkcm9wOiB0cnVlLFxuICAgICAgICAgICAgY2FsbGJhY2s6IFRpY2tzLmZvcm1hdHRlcnMubnVtZXJpY1xuICAgICAgICB9LFxuICAgICAgICBwb2ludExhYmVsczoge1xuICAgICAgICAgICAgYmFja2Ryb3BDb2xvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgYmFja2Ryb3BQYWRkaW5nOiAyLFxuICAgICAgICAgICAgZGlzcGxheTogdHJ1ZSxcbiAgICAgICAgICAgIGZvbnQ6IHtcbiAgICAgICAgICAgICAgICBzaXplOiAxMFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhbGxiYWNrIChsYWJlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsYWJlbDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYWRkaW5nOiA1LFxuICAgICAgICAgICAgY2VudGVyUG9pbnRMYWJlbHM6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9O1xuICAgIHN0YXRpYyBkZWZhdWx0Um91dGVzID0ge1xuICAgICAgICAnYW5nbGVMaW5lcy5jb2xvcic6ICdib3JkZXJDb2xvcicsXG4gICAgICAgICdwb2ludExhYmVscy5jb2xvcic6ICdjb2xvcicsXG4gICAgICAgICd0aWNrcy5jb2xvcic6ICdjb2xvcidcbiAgICB9O1xuICAgIHN0YXRpYyBkZXNjcmlwdG9ycyA9IHtcbiAgICAgICAgYW5nbGVMaW5lczoge1xuICAgICAgICAgICAgX2ZhbGxiYWNrOiAnZ3JpZCdcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoY2ZnKTtcbiAgICAgICAgIHRoaXMueENlbnRlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMueUNlbnRlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuZHJhd2luZ0FyZWEgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLl9wb2ludExhYmVscyA9IFtdO1xuICAgICAgICB0aGlzLl9wb2ludExhYmVsSXRlbXMgPSBbXTtcbiAgICB9XG4gICAgc2V0RGltZW5zaW9ucygpIHtcbiAgICAgICAgY29uc3QgcGFkZGluZyA9IHRoaXMuX3BhZGRpbmcgPSB0b1BhZGRpbmcoZ2V0VGlja0JhY2tkcm9wSGVpZ2h0KHRoaXMub3B0aW9ucykgLyAyKTtcbiAgICAgICAgY29uc3QgdyA9IHRoaXMud2lkdGggPSB0aGlzLm1heFdpZHRoIC0gcGFkZGluZy53aWR0aDtcbiAgICAgICAgY29uc3QgaCA9IHRoaXMuaGVpZ2h0ID0gdGhpcy5tYXhIZWlnaHQgLSBwYWRkaW5nLmhlaWdodDtcbiAgICAgICAgdGhpcy54Q2VudGVyID0gTWF0aC5mbG9vcih0aGlzLmxlZnQgKyB3IC8gMiArIHBhZGRpbmcubGVmdCk7XG4gICAgICAgIHRoaXMueUNlbnRlciA9IE1hdGguZmxvb3IodGhpcy50b3AgKyBoIC8gMiArIHBhZGRpbmcudG9wKTtcbiAgICAgICAgdGhpcy5kcmF3aW5nQXJlYSA9IE1hdGguZmxvb3IoTWF0aC5taW4odywgaCkgLyAyKTtcbiAgICB9XG4gICAgZGV0ZXJtaW5lRGF0YUxpbWl0cygpIHtcbiAgICAgICAgY29uc3QgeyBtaW4gLCBtYXggIH0gPSB0aGlzLmdldE1pbk1heChmYWxzZSk7XG4gICAgICAgIHRoaXMubWluID0gaXNOdW1iZXJGaW5pdGUobWluKSAmJiAhaXNOYU4obWluKSA/IG1pbiA6IDA7XG4gICAgICAgIHRoaXMubWF4ID0gaXNOdW1iZXJGaW5pdGUobWF4KSAmJiAhaXNOYU4obWF4KSA/IG1heCA6IDA7XG4gICAgICAgIHRoaXMuaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpO1xuICAgIH1cbiBjb21wdXRlVGlja0xpbWl0KCkge1xuICAgICAgICByZXR1cm4gTWF0aC5jZWlsKHRoaXMuZHJhd2luZ0FyZWEgLyBnZXRUaWNrQmFja2Ryb3BIZWlnaHQodGhpcy5vcHRpb25zKSk7XG4gICAgfVxuICAgIGdlbmVyYXRlVGlja0xhYmVscyh0aWNrcykge1xuICAgICAgICBMaW5lYXJTY2FsZUJhc2UucHJvdG90eXBlLmdlbmVyYXRlVGlja0xhYmVscy5jYWxsKHRoaXMsIHRpY2tzKTtcbiAgICAgICAgdGhpcy5fcG9pbnRMYWJlbHMgPSB0aGlzLmdldExhYmVscygpLm1hcCgodmFsdWUsIGluZGV4KT0+e1xuICAgICAgICAgICAgY29uc3QgbGFiZWwgPSBjYWxsYmFjayh0aGlzLm9wdGlvbnMucG9pbnRMYWJlbHMuY2FsbGJhY2ssIFtcbiAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgICAgICByZXR1cm4gbGFiZWwgfHwgbGFiZWwgPT09IDAgPyBsYWJlbCA6ICcnO1xuICAgICAgICB9KS5maWx0ZXIoKHYsIGkpPT50aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpKTtcbiAgICB9XG4gICAgZml0KCkge1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAob3B0cy5kaXNwbGF5ICYmIG9wdHMucG9pbnRMYWJlbHMuZGlzcGxheSkge1xuICAgICAgICAgICAgZml0V2l0aFBvaW50TGFiZWxzKHRoaXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXRDZW50ZXJQb2ludCgwLCAwLCAwLCAwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBzZXRDZW50ZXJQb2ludChsZWZ0TW92ZW1lbnQsIHJpZ2h0TW92ZW1lbnQsIHRvcE1vdmVtZW50LCBib3R0b21Nb3ZlbWVudCkge1xuICAgICAgICB0aGlzLnhDZW50ZXIgKz0gTWF0aC5mbG9vcigobGVmdE1vdmVtZW50IC0gcmlnaHRNb3ZlbWVudCkgLyAyKTtcbiAgICAgICAgdGhpcy55Q2VudGVyICs9IE1hdGguZmxvb3IoKHRvcE1vdmVtZW50IC0gYm90dG9tTW92ZW1lbnQpIC8gMik7XG4gICAgICAgIHRoaXMuZHJhd2luZ0FyZWEgLT0gTWF0aC5taW4odGhpcy5kcmF3aW5nQXJlYSAvIDIsIE1hdGgubWF4KGxlZnRNb3ZlbWVudCwgcmlnaHRNb3ZlbWVudCwgdG9wTW92ZW1lbnQsIGJvdHRvbU1vdmVtZW50KSk7XG4gICAgfVxuICAgIGdldEluZGV4QW5nbGUoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgYW5nbGVNdWx0aXBsaWVyID0gVEFVIC8gKHRoaXMuX3BvaW50TGFiZWxzLmxlbmd0aCB8fCAxKTtcbiAgICAgICAgY29uc3Qgc3RhcnRBbmdsZSA9IHRoaXMub3B0aW9ucy5zdGFydEFuZ2xlIHx8IDA7XG4gICAgICAgIHJldHVybiBfbm9ybWFsaXplQW5nbGUoaW5kZXggKiBhbmdsZU11bHRpcGxpZXIgKyB0b1JhZGlhbnMoc3RhcnRBbmdsZSkpO1xuICAgIH1cbiAgICBnZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc2NhbGluZ0ZhY3RvciA9IHRoaXMuZHJhd2luZ0FyZWEgLyAodGhpcy5tYXggLSB0aGlzLm1pbik7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmV2ZXJzZSkge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLm1heCAtIHZhbHVlKSAqIHNjYWxpbmdGYWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICh2YWx1ZSAtIHRoaXMubWluKSAqIHNjYWxpbmdGYWN0b3I7XG4gICAgfVxuICAgIGdldFZhbHVlRm9yRGlzdGFuY2VGcm9tQ2VudGVyKGRpc3RhbmNlKSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmKGRpc3RhbmNlKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzY2FsZWREaXN0YW5jZSA9IGRpc3RhbmNlIC8gKHRoaXMuZHJhd2luZ0FyZWEgLyAodGhpcy5tYXggLSB0aGlzLm1pbikpO1xuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLnJldmVyc2UgPyB0aGlzLm1heCAtIHNjYWxlZERpc3RhbmNlIDogdGhpcy5taW4gKyBzY2FsZWREaXN0YW5jZTtcbiAgICB9XG4gICAgZ2V0UG9pbnRMYWJlbENvbnRleHQoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgcG9pbnRMYWJlbHMgPSB0aGlzLl9wb2ludExhYmVscyB8fCBbXTtcbiAgICAgICAgaWYgKGluZGV4ID49IDAgJiYgaW5kZXggPCBwb2ludExhYmVscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50TGFiZWwgPSBwb2ludExhYmVsc1tpbmRleF07XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlUG9pbnRMYWJlbENvbnRleHQodGhpcy5nZXRDb250ZXh0KCksIGluZGV4LCBwb2ludExhYmVsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXRQb2ludFBvc2l0aW9uKGluZGV4LCBkaXN0YW5jZUZyb21DZW50ZXIsIGFkZGl0aW9uYWxBbmdsZSA9IDApIHtcbiAgICAgICAgY29uc3QgYW5nbGUgPSB0aGlzLmdldEluZGV4QW5nbGUoaW5kZXgpIC0gSEFMRl9QSSArIGFkZGl0aW9uYWxBbmdsZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IE1hdGguY29zKGFuZ2xlKSAqIGRpc3RhbmNlRnJvbUNlbnRlciArIHRoaXMueENlbnRlcixcbiAgICAgICAgICAgIHk6IE1hdGguc2luKGFuZ2xlKSAqIGRpc3RhbmNlRnJvbUNlbnRlciArIHRoaXMueUNlbnRlcixcbiAgICAgICAgICAgIGFuZ2xlXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZShpbmRleCwgdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UG9pbnRQb3NpdGlvbihpbmRleCwgdGhpcy5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZSh2YWx1ZSkpO1xuICAgIH1cbiAgICBnZXRCYXNlUG9zaXRpb24oaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UG9pbnRQb3NpdGlvbkZvclZhbHVlKGluZGV4IHx8IDAsIHRoaXMuZ2V0QmFzZVZhbHVlKCkpO1xuICAgIH1cbiAgICBnZXRQb2ludExhYmVsUG9zaXRpb24oaW5kZXgpIHtcbiAgICAgICAgY29uc3QgeyBsZWZ0ICwgdG9wICwgcmlnaHQgLCBib3R0b20gIH0gPSB0aGlzLl9wb2ludExhYmVsSXRlbXNbaW5kZXhdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGVmdCxcbiAgICAgICAgICAgIHRvcCxcbiAgICAgICAgICAgIHJpZ2h0LFxuICAgICAgICAgICAgYm90dG9tXG4gICAgICAgIH07XG4gICAgfVxuIGRyYXdCYWNrZ3JvdW5kKCkge1xuICAgICAgICBjb25zdCB7IGJhY2tncm91bmRDb2xvciAsIGdyaWQ6IHsgY2lyY3VsYXIgIH0gIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmIChiYWNrZ3JvdW5kQ29sb3IpIHtcbiAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgICAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgIHBhdGhSYWRpdXNMaW5lKHRoaXMsIHRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGhpcy5fZW5kVmFsdWUpLCBjaXJjdWxhciwgdGhpcy5fcG9pbnRMYWJlbHMubGVuZ3RoKTtcbiAgICAgICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBiYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgfVxuICAgIH1cbiBkcmF3R3JpZCgpIHtcbiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHsgYW5nbGVMaW5lcyAsIGdyaWQgLCBib3JkZXIgIH0gPSBvcHRzO1xuICAgICAgICBjb25zdCBsYWJlbENvdW50ID0gdGhpcy5fcG9pbnRMYWJlbHMubGVuZ3RoO1xuICAgICAgICBsZXQgaSwgb2Zmc2V0LCBwb3NpdGlvbjtcbiAgICAgICAgaWYgKG9wdHMucG9pbnRMYWJlbHMuZGlzcGxheSkge1xuICAgICAgICAgICAgZHJhd1BvaW50TGFiZWxzKHRoaXMsIGxhYmVsQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChncmlkLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHRoaXMudGlja3MuZm9yRWFjaCgodGljaywgaW5kZXgpPT57XG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAwIHx8IGluZGV4ID09PSAwICYmIHRoaXMubWluIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQgPSB0aGlzLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKHRpY2sudmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5nZXRDb250ZXh0KGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3B0c0F0SW5kZXggPSBncmlkLnNldENvbnRleHQoY29udGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wdHNBdEluZGV4Qm9yZGVyID0gYm9yZGVyLnNldENvbnRleHQoY29udGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIGRyYXdSYWRpdXNMaW5lKHRoaXMsIG9wdHNBdEluZGV4LCBvZmZzZXQsIGxhYmVsQ291bnQsIG9wdHNBdEluZGV4Qm9yZGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYW5nbGVMaW5lcy5kaXNwbGF5KSB7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgZm9yKGkgPSBsYWJlbENvdW50IC0gMTsgaSA+PSAwOyBpLS0pe1xuICAgICAgICAgICAgICAgIGNvbnN0IG9wdHNBdEluZGV4ID0gYW5nbGVMaW5lcy5zZXRDb250ZXh0KHRoaXMuZ2V0UG9pbnRMYWJlbENvbnRleHQoaSkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgY29sb3IgLCBsaW5lV2lkdGggIH0gPSBvcHRzQXRJbmRleDtcbiAgICAgICAgICAgICAgICBpZiAoIWxpbmVXaWR0aCB8fCAhY29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgICAgICAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gY29sb3I7XG4gICAgICAgICAgICAgICAgY3R4LnNldExpbmVEYXNoKG9wdHNBdEluZGV4LmJvcmRlckRhc2gpO1xuICAgICAgICAgICAgICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IG9wdHNBdEluZGV4LmJvcmRlckRhc2hPZmZzZXQ7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gdGhpcy5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZShvcHRzLnJldmVyc2UgPyB0aGlzLm1pbiA6IHRoaXMubWF4KTtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHRoaXMuZ2V0UG9pbnRQb3NpdGlvbihpLCBvZmZzZXQpO1xuICAgICAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgICAgICBjdHgubW92ZVRvKHRoaXMueENlbnRlciwgdGhpcy55Q2VudGVyKTtcbiAgICAgICAgICAgICAgICBjdHgubGluZVRvKHBvc2l0aW9uLngsIHBvc2l0aW9uLnkpO1xuICAgICAgICAgICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgIH1cbiAgICB9XG4gZHJhd0JvcmRlcigpIHt9XG4gZHJhd0xhYmVscygpIHtcbiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHRpY2tPcHRzID0gb3B0cy50aWNrcztcbiAgICAgICAgaWYgKCF0aWNrT3B0cy5kaXNwbGF5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RhcnRBbmdsZSA9IHRoaXMuZ2V0SW5kZXhBbmdsZSgwKTtcbiAgICAgICAgbGV0IG9mZnNldCwgd2lkdGg7XG4gICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgIGN0eC50cmFuc2xhdGUodGhpcy54Q2VudGVyLCB0aGlzLnlDZW50ZXIpO1xuICAgICAgICBjdHgucm90YXRlKHN0YXJ0QW5nbGUpO1xuICAgICAgICBjdHgudGV4dEFsaWduID0gJ2NlbnRlcic7XG4gICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgICAgdGhpcy50aWNrcy5mb3JFYWNoKCh0aWNrLCBpbmRleCk9PntcbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMCAmJiB0aGlzLm1pbiA+PSAwICYmICFvcHRzLnJldmVyc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvcHRzQXRJbmRleCA9IHRpY2tPcHRzLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KGluZGV4KSk7XG4gICAgICAgICAgICBjb25zdCB0aWNrRm9udCA9IHRvRm9udChvcHRzQXRJbmRleC5mb250KTtcbiAgICAgICAgICAgIG9mZnNldCA9IHRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGhpcy50aWNrc1tpbmRleF0udmFsdWUpO1xuICAgICAgICAgICAgaWYgKG9wdHNBdEluZGV4LnNob3dMYWJlbEJhY2tkcm9wKSB7XG4gICAgICAgICAgICAgICAgY3R4LmZvbnQgPSB0aWNrRm9udC5zdHJpbmc7XG4gICAgICAgICAgICAgICAgd2lkdGggPSBjdHgubWVhc3VyZVRleHQodGljay5sYWJlbCkud2lkdGg7XG4gICAgICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdHNBdEluZGV4LmJhY2tkcm9wQ29sb3I7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRzQXRJbmRleC5iYWNrZHJvcFBhZGRpbmcpO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsUmVjdCgtd2lkdGggLyAyIC0gcGFkZGluZy5sZWZ0LCAtb2Zmc2V0IC0gdGlja0ZvbnQuc2l6ZSAvIDIgLSBwYWRkaW5nLnRvcCwgd2lkdGggKyBwYWRkaW5nLndpZHRoLCB0aWNrRm9udC5zaXplICsgcGFkZGluZy5oZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVuZGVyVGV4dChjdHgsIHRpY2subGFiZWwsIDAsIC1vZmZzZXQsIHRpY2tGb250LCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IG9wdHNBdEluZGV4LmNvbG9yLFxuICAgICAgICAgICAgICAgIHN0cm9rZUNvbG9yOiBvcHRzQXRJbmRleC50ZXh0U3Ryb2tlQ29sb3IsXG4gICAgICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IG9wdHNBdEluZGV4LnRleHRTdHJva2VXaWR0aFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH1cbiBkcmF3VGl0bGUoKSB7fVxufVxuXG5jb25zdCBJTlRFUlZBTFMgPSB7XG4gICAgbWlsbGlzZWNvbmQ6IHtcbiAgICAgICAgY29tbW9uOiB0cnVlLFxuICAgICAgICBzaXplOiAxLFxuICAgICAgICBzdGVwczogMTAwMFxuICAgIH0sXG4gICAgc2Vjb25kOiB7XG4gICAgICAgIGNvbW1vbjogdHJ1ZSxcbiAgICAgICAgc2l6ZTogMTAwMCxcbiAgICAgICAgc3RlcHM6IDYwXG4gICAgfSxcbiAgICBtaW51dGU6IHtcbiAgICAgICAgY29tbW9uOiB0cnVlLFxuICAgICAgICBzaXplOiA2MDAwMCxcbiAgICAgICAgc3RlcHM6IDYwXG4gICAgfSxcbiAgICBob3VyOiB7XG4gICAgICAgIGNvbW1vbjogdHJ1ZSxcbiAgICAgICAgc2l6ZTogMzYwMDAwMCxcbiAgICAgICAgc3RlcHM6IDI0XG4gICAgfSxcbiAgICBkYXk6IHtcbiAgICAgICAgY29tbW9uOiB0cnVlLFxuICAgICAgICBzaXplOiA4NjQwMDAwMCxcbiAgICAgICAgc3RlcHM6IDMwXG4gICAgfSxcbiAgICB3ZWVrOiB7XG4gICAgICAgIGNvbW1vbjogZmFsc2UsXG4gICAgICAgIHNpemU6IDYwNDgwMDAwMCxcbiAgICAgICAgc3RlcHM6IDRcbiAgICB9LFxuICAgIG1vbnRoOiB7XG4gICAgICAgIGNvbW1vbjogdHJ1ZSxcbiAgICAgICAgc2l6ZTogMi42MjhlOSxcbiAgICAgICAgc3RlcHM6IDEyXG4gICAgfSxcbiAgICBxdWFydGVyOiB7XG4gICAgICAgIGNvbW1vbjogZmFsc2UsXG4gICAgICAgIHNpemU6IDcuODg0ZTksXG4gICAgICAgIHN0ZXBzOiA0XG4gICAgfSxcbiAgICB5ZWFyOiB7XG4gICAgICAgIGNvbW1vbjogdHJ1ZSxcbiAgICAgICAgc2l6ZTogMy4xNTRlMTBcbiAgICB9XG59O1xuIGNvbnN0IFVOSVRTID0gIC8qICNfX1BVUkVfXyAqLyBPYmplY3Qua2V5cyhJTlRFUlZBTFMpO1xuIGZ1bmN0aW9uIHNvcnRlcihhLCBiKSB7XG4gICAgcmV0dXJuIGEgLSBiO1xufVxuIGZ1bmN0aW9uIHBhcnNlKHNjYWxlLCBpbnB1dCkge1xuICAgIGlmIChpc051bGxPclVuZGVmKGlucHV0KSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgYWRhcHRlciA9IHNjYWxlLl9hZGFwdGVyO1xuICAgIGNvbnN0IHsgcGFyc2VyICwgcm91bmQgLCBpc29XZWVrZGF5ICB9ID0gc2NhbGUuX3BhcnNlT3B0cztcbiAgICBsZXQgdmFsdWUgPSBpbnB1dDtcbiAgICBpZiAodHlwZW9mIHBhcnNlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB2YWx1ZSA9IHBhcnNlcih2YWx1ZSk7XG4gICAgfVxuICAgIGlmICghaXNOdW1iZXJGaW5pdGUodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlID0gdHlwZW9mIHBhcnNlciA9PT0gJ3N0cmluZycgPyBhZGFwdGVyLnBhcnNlKHZhbHVlLCBwYXJzZXIpIDogYWRhcHRlci5wYXJzZSh2YWx1ZSk7XG4gICAgfVxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHJvdW5kKSB7XG4gICAgICAgIHZhbHVlID0gcm91bmQgPT09ICd3ZWVrJyAmJiAoaXNOdW1iZXIoaXNvV2Vla2RheSkgfHwgaXNvV2Vla2RheSA9PT0gdHJ1ZSkgPyBhZGFwdGVyLnN0YXJ0T2YodmFsdWUsICdpc29XZWVrJywgaXNvV2Vla2RheSkgOiBhZGFwdGVyLnN0YXJ0T2YodmFsdWUsIHJvdW5kKTtcbiAgICB9XG4gICAgcmV0dXJuICt2YWx1ZTtcbn1cbiBmdW5jdGlvbiBkZXRlcm1pbmVVbml0Rm9yQXV0b1RpY2tzKG1pblVuaXQsIG1pbiwgbWF4LCBjYXBhY2l0eSkge1xuICAgIGNvbnN0IGlsZW4gPSBVTklUUy5sZW5ndGg7XG4gICAgZm9yKGxldCBpID0gVU5JVFMuaW5kZXhPZihtaW5Vbml0KTsgaSA8IGlsZW4gLSAxOyArK2kpe1xuICAgICAgICBjb25zdCBpbnRlcnZhbCA9IElOVEVSVkFMU1tVTklUU1tpXV07XG4gICAgICAgIGNvbnN0IGZhY3RvciA9IGludGVydmFsLnN0ZXBzID8gaW50ZXJ2YWwuc3RlcHMgOiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcbiAgICAgICAgaWYgKGludGVydmFsLmNvbW1vbiAmJiBNYXRoLmNlaWwoKG1heCAtIG1pbikgLyAoZmFjdG9yICogaW50ZXJ2YWwuc2l6ZSkpIDw9IGNhcGFjaXR5KSB7XG4gICAgICAgICAgICByZXR1cm4gVU5JVFNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFVOSVRTW2lsZW4gLSAxXTtcbn1cbiBmdW5jdGlvbiBkZXRlcm1pbmVVbml0Rm9yRm9ybWF0dGluZyhzY2FsZSwgbnVtVGlja3MsIG1pblVuaXQsIG1pbiwgbWF4KSB7XG4gICAgZm9yKGxldCBpID0gVU5JVFMubGVuZ3RoIC0gMTsgaSA+PSBVTklUUy5pbmRleE9mKG1pblVuaXQpOyBpLS0pe1xuICAgICAgICBjb25zdCB1bml0ID0gVU5JVFNbaV07XG4gICAgICAgIGlmIChJTlRFUlZBTFNbdW5pdF0uY29tbW9uICYmIHNjYWxlLl9hZGFwdGVyLmRpZmYobWF4LCBtaW4sIHVuaXQpID49IG51bVRpY2tzIC0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuaXQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFVOSVRTW21pblVuaXQgPyBVTklUUy5pbmRleE9mKG1pblVuaXQpIDogMF07XG59XG4gZnVuY3Rpb24gZGV0ZXJtaW5lTWFqb3JVbml0KHVuaXQpIHtcbiAgICBmb3IobGV0IGkgPSBVTklUUy5pbmRleE9mKHVuaXQpICsgMSwgaWxlbiA9IFVOSVRTLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGlmIChJTlRFUlZBTFNbVU5JVFNbaV1dLmNvbW1vbikge1xuICAgICAgICAgICAgcmV0dXJuIFVOSVRTW2ldO1xuICAgICAgICB9XG4gICAgfVxufVxuIGZ1bmN0aW9uIGFkZFRpY2sodGlja3MsIHRpbWUsIHRpbWVzdGFtcHMpIHtcbiAgICBpZiAoIXRpbWVzdGFtcHMpIHtcbiAgICAgICAgdGlja3NbdGltZV0gPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAodGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgeyBsbyAsIGhpICB9ID0gX2xvb2t1cCh0aW1lc3RhbXBzLCB0aW1lKTtcbiAgICAgICAgY29uc3QgdGltZXN0YW1wID0gdGltZXN0YW1wc1tsb10gPj0gdGltZSA/IHRpbWVzdGFtcHNbbG9dIDogdGltZXN0YW1wc1toaV07XG4gICAgICAgIHRpY2tzW3RpbWVzdGFtcF0gPSB0cnVlO1xuICAgIH1cbn1cbiBmdW5jdGlvbiBzZXRNYWpvclRpY2tzKHNjYWxlLCB0aWNrcywgbWFwLCBtYWpvclVuaXQpIHtcbiAgICBjb25zdCBhZGFwdGVyID0gc2NhbGUuX2FkYXB0ZXI7XG4gICAgY29uc3QgZmlyc3QgPSArYWRhcHRlci5zdGFydE9mKHRpY2tzWzBdLnZhbHVlLCBtYWpvclVuaXQpO1xuICAgIGNvbnN0IGxhc3QgPSB0aWNrc1t0aWNrcy5sZW5ndGggLSAxXS52YWx1ZTtcbiAgICBsZXQgbWFqb3IsIGluZGV4O1xuICAgIGZvcihtYWpvciA9IGZpcnN0OyBtYWpvciA8PSBsYXN0OyBtYWpvciA9ICthZGFwdGVyLmFkZChtYWpvciwgMSwgbWFqb3JVbml0KSl7XG4gICAgICAgIGluZGV4ID0gbWFwW21ham9yXTtcbiAgICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgICAgIHRpY2tzW2luZGV4XS5tYWpvciA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRpY2tzO1xufVxuIGZ1bmN0aW9uIHRpY2tzRnJvbVRpbWVzdGFtcHMoc2NhbGUsIHZhbHVlcywgbWFqb3JVbml0KSB7XG4gICAgY29uc3QgdGlja3MgPSBbXTtcbiAgICAgY29uc3QgbWFwID0ge307XG4gICAgY29uc3QgaWxlbiA9IHZhbHVlcy5sZW5ndGg7XG4gICAgbGV0IGksIHZhbHVlO1xuICAgIGZvcihpID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgICBtYXBbdmFsdWVdID0gaTtcbiAgICAgICAgdGlja3MucHVzaCh7XG4gICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgIG1ham9yOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGlsZW4gPT09IDAgfHwgIW1ham9yVW5pdCA/IHRpY2tzIDogc2V0TWFqb3JUaWNrcyhzY2FsZSwgdGlja3MsIG1hcCwgbWFqb3JVbml0KTtcbn1cbmNsYXNzIFRpbWVTY2FsZSBleHRlbmRzIFNjYWxlIHtcbiAgICBzdGF0aWMgaWQgPSAndGltZSc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuIGJvdW5kczogJ2RhdGEnLFxuICAgICAgICBhZGFwdGVyczoge30sXG4gICAgICAgIHRpbWU6IHtcbiAgICAgICAgICAgIHBhcnNlcjogZmFsc2UsXG4gICAgICAgICAgICB1bml0OiBmYWxzZSxcbiAgICAgICAgICAgIHJvdW5kOiBmYWxzZSxcbiAgICAgICAgICAgIGlzb1dlZWtkYXk6IGZhbHNlLFxuICAgICAgICAgICAgbWluVW5pdDogJ21pbGxpc2Vjb25kJyxcbiAgICAgICAgICAgIGRpc3BsYXlGb3JtYXRzOiB7fVxuICAgICAgICB9LFxuICAgICAgICB0aWNrczoge1xuIHNvdXJjZTogJ2F1dG8nLFxuICAgICAgICAgICAgY2FsbGJhY2s6IGZhbHNlLFxuICAgICAgICAgICAgbWFqb3I6IHtcbiAgICAgICAgICAgICAgICBlbmFibGVkOiBmYWxzZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiBjb25zdHJ1Y3Rvcihwcm9wcyl7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcbiAgICAgICAgIHRoaXMuX2NhY2hlID0ge1xuICAgICAgICAgICAgZGF0YTogW10sXG4gICAgICAgICAgICBsYWJlbHM6IFtdLFxuICAgICAgICAgICAgYWxsOiBbXVxuICAgICAgICB9O1xuICAgICAgICAgdGhpcy5fdW5pdCA9ICdkYXknO1xuICAgICAgICAgdGhpcy5fbWFqb3JVbml0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9vZmZzZXRzID0ge307XG4gICAgICAgIHRoaXMuX25vcm1hbGl6ZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fcGFyc2VPcHRzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpbml0KHNjYWxlT3B0cywgb3B0cyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IHRpbWUgPSBzY2FsZU9wdHMudGltZSB8fCAoc2NhbGVPcHRzLnRpbWUgPSB7fSk7XG4gICAgICAgICBjb25zdCBhZGFwdGVyID0gdGhpcy5fYWRhcHRlciA9IG5ldyBhZGFwdGVycy5fZGF0ZShzY2FsZU9wdHMuYWRhcHRlcnMuZGF0ZSk7XG4gICAgICAgIGFkYXB0ZXIuaW5pdChvcHRzKTtcbiAgICAgICAgbWVyZ2VJZih0aW1lLmRpc3BsYXlGb3JtYXRzLCBhZGFwdGVyLmZvcm1hdHMoKSk7XG4gICAgICAgIHRoaXMuX3BhcnNlT3B0cyA9IHtcbiAgICAgICAgICAgIHBhcnNlcjogdGltZS5wYXJzZXIsXG4gICAgICAgICAgICByb3VuZDogdGltZS5yb3VuZCxcbiAgICAgICAgICAgIGlzb1dlZWtkYXk6IHRpbWUuaXNvV2Vla2RheVxuICAgICAgICB9O1xuICAgICAgICBzdXBlci5pbml0KHNjYWxlT3B0cyk7XG4gICAgICAgIHRoaXMuX25vcm1hbGl6ZWQgPSBvcHRzLm5vcm1hbGl6ZWQ7XG4gICAgfVxuIHBhcnNlKHJhdywgaW5kZXgpIHtcbiAgICAgICAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFyc2UodGhpcywgcmF3KTtcbiAgICB9XG4gICAgYmVmb3JlTGF5b3V0KCkge1xuICAgICAgICBzdXBlci5iZWZvcmVMYXlvdXQoKTtcbiAgICAgICAgdGhpcy5fY2FjaGUgPSB7XG4gICAgICAgICAgICBkYXRhOiBbXSxcbiAgICAgICAgICAgIGxhYmVsczogW10sXG4gICAgICAgICAgICBhbGw6IFtdXG4gICAgICAgIH07XG4gICAgfVxuICAgIGRldGVybWluZURhdGFMaW1pdHMoKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLl9hZGFwdGVyO1xuICAgICAgICBjb25zdCB1bml0ID0gb3B0aW9ucy50aW1lLnVuaXQgfHwgJ2RheSc7XG4gICAgICAgIGxldCB7IG1pbiAsIG1heCAsIG1pbkRlZmluZWQgLCBtYXhEZWZpbmVkICB9ID0gdGhpcy5nZXRVc2VyQm91bmRzKCk7XG4gZnVuY3Rpb24gX2FwcGx5Qm91bmRzKGJvdW5kcykge1xuICAgICAgICAgICAgaWYgKCFtaW5EZWZpbmVkICYmICFpc05hTihib3VuZHMubWluKSkge1xuICAgICAgICAgICAgICAgIG1pbiA9IE1hdGgubWluKG1pbiwgYm91bmRzLm1pbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW1heERlZmluZWQgJiYgIWlzTmFOKGJvdW5kcy5tYXgpKSB7XG4gICAgICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCBib3VuZHMubWF4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIW1pbkRlZmluZWQgfHwgIW1heERlZmluZWQpIHtcbiAgICAgICAgICAgIF9hcHBseUJvdW5kcyh0aGlzLl9nZXRMYWJlbEJvdW5kcygpKTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmJvdW5kcyAhPT0gJ3RpY2tzJyB8fCBvcHRpb25zLnRpY2tzLnNvdXJjZSAhPT0gJ2xhYmVscycpIHtcbiAgICAgICAgICAgICAgICBfYXBwbHlCb3VuZHModGhpcy5nZXRNaW5NYXgoZmFsc2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBtaW4gPSBpc051bWJlckZpbml0ZShtaW4pICYmICFpc05hTihtaW4pID8gbWluIDogK2FkYXB0ZXIuc3RhcnRPZihEYXRlLm5vdygpLCB1bml0KTtcbiAgICAgICAgbWF4ID0gaXNOdW1iZXJGaW5pdGUobWF4KSAmJiAhaXNOYU4obWF4KSA/IG1heCA6ICthZGFwdGVyLmVuZE9mKERhdGUubm93KCksIHVuaXQpICsgMTtcbiAgICAgICAgdGhpcy5taW4gPSBNYXRoLm1pbihtaW4sIG1heCAtIDEpO1xuICAgICAgICB0aGlzLm1heCA9IE1hdGgubWF4KG1pbiArIDEsIG1heCk7XG4gICAgfVxuIF9nZXRMYWJlbEJvdW5kcygpIHtcbiAgICAgICAgY29uc3QgYXJyID0gdGhpcy5nZXRMYWJlbFRpbWVzdGFtcHMoKTtcbiAgICAgICAgbGV0IG1pbiA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgbGV0IG1heCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTtcbiAgICAgICAgaWYgKGFyci5sZW5ndGgpIHtcbiAgICAgICAgICAgIG1pbiA9IGFyclswXTtcbiAgICAgICAgICAgIG1heCA9IGFyclthcnIubGVuZ3RoIC0gMV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG1pbixcbiAgICAgICAgICAgIG1heFxuICAgICAgICB9O1xuICAgIH1cbiBidWlsZFRpY2tzKCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB0aW1lT3B0cyA9IG9wdGlvbnMudGltZTtcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSBvcHRpb25zLnRpY2tzO1xuICAgICAgICBjb25zdCB0aW1lc3RhbXBzID0gdGlja09wdHMuc291cmNlID09PSAnbGFiZWxzJyA/IHRoaXMuZ2V0TGFiZWxUaW1lc3RhbXBzKCkgOiB0aGlzLl9nZW5lcmF0ZSgpO1xuICAgICAgICBpZiAob3B0aW9ucy5ib3VuZHMgPT09ICd0aWNrcycgJiYgdGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMubWluID0gdGhpcy5fdXNlck1pbiB8fCB0aW1lc3RhbXBzWzBdO1xuICAgICAgICAgICAgdGhpcy5tYXggPSB0aGlzLl91c2VyTWF4IHx8IHRpbWVzdGFtcHNbdGltZXN0YW1wcy5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtaW4gPSB0aGlzLm1pbjtcbiAgICAgICAgY29uc3QgbWF4ID0gdGhpcy5tYXg7XG4gICAgICAgIGNvbnN0IHRpY2tzID0gX2ZpbHRlckJldHdlZW4odGltZXN0YW1wcywgbWluLCBtYXgpO1xuICAgICAgICB0aGlzLl91bml0ID0gdGltZU9wdHMudW5pdCB8fCAodGlja09wdHMuYXV0b1NraXAgPyBkZXRlcm1pbmVVbml0Rm9yQXV0b1RpY2tzKHRpbWVPcHRzLm1pblVuaXQsIHRoaXMubWluLCB0aGlzLm1heCwgdGhpcy5fZ2V0TGFiZWxDYXBhY2l0eShtaW4pKSA6IGRldGVybWluZVVuaXRGb3JGb3JtYXR0aW5nKHRoaXMsIHRpY2tzLmxlbmd0aCwgdGltZU9wdHMubWluVW5pdCwgdGhpcy5taW4sIHRoaXMubWF4KSk7XG4gICAgICAgIHRoaXMuX21ham9yVW5pdCA9ICF0aWNrT3B0cy5tYWpvci5lbmFibGVkIHx8IHRoaXMuX3VuaXQgPT09ICd5ZWFyJyA/IHVuZGVmaW5lZCA6IGRldGVybWluZU1ham9yVW5pdCh0aGlzLl91bml0KTtcbiAgICAgICAgdGhpcy5pbml0T2Zmc2V0cyh0aW1lc3RhbXBzKTtcbiAgICAgICAgaWYgKG9wdGlvbnMucmV2ZXJzZSkge1xuICAgICAgICAgICAgdGlja3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aWNrc0Zyb21UaW1lc3RhbXBzKHRoaXMsIHRpY2tzLCB0aGlzLl9tYWpvclVuaXQpO1xuICAgIH1cbiAgICBhZnRlckF1dG9Ta2lwKCkge1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLm9mZnNldEFmdGVyQXV0b3NraXApIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdE9mZnNldHModGhpcy50aWNrcy5tYXAoKHRpY2spPT4rdGljay52YWx1ZSkpO1xuICAgICAgICB9XG4gICAgfVxuIGluaXRPZmZzZXRzKHRpbWVzdGFtcHMgPSBbXSkge1xuICAgICAgICBsZXQgc3RhcnQgPSAwO1xuICAgICAgICBsZXQgZW5kID0gMDtcbiAgICAgICAgbGV0IGZpcnN0LCBsYXN0O1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLm9mZnNldCAmJiB0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgZmlyc3QgPSB0aGlzLmdldERlY2ltYWxGb3JWYWx1ZSh0aW1lc3RhbXBzWzBdKTtcbiAgICAgICAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gMSAtIGZpcnN0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdGFydCA9ICh0aGlzLmdldERlY2ltYWxGb3JWYWx1ZSh0aW1lc3RhbXBzWzFdKSAtIGZpcnN0KSAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYXN0ID0gdGhpcy5nZXREZWNpbWFsRm9yVmFsdWUodGltZXN0YW1wc1t0aW1lc3RhbXBzLmxlbmd0aCAtIDFdKTtcbiAgICAgICAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGVuZCA9IGxhc3Q7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVuZCA9IChsYXN0IC0gdGhpcy5nZXREZWNpbWFsRm9yVmFsdWUodGltZXN0YW1wc1t0aW1lc3RhbXBzLmxlbmd0aCAtIDJdKSkgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxpbWl0ID0gdGltZXN0YW1wcy5sZW5ndGggPCAzID8gMC41IDogMC4yNTtcbiAgICAgICAgc3RhcnQgPSBfbGltaXRWYWx1ZShzdGFydCwgMCwgbGltaXQpO1xuICAgICAgICBlbmQgPSBfbGltaXRWYWx1ZShlbmQsIDAsIGxpbWl0KTtcbiAgICAgICAgdGhpcy5fb2Zmc2V0cyA9IHtcbiAgICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgICAgZW5kLFxuICAgICAgICAgICAgZmFjdG9yOiAxIC8gKHN0YXJ0ICsgMSArIGVuZClcbiAgICAgICAgfTtcbiAgICB9XG4gX2dlbmVyYXRlKCkge1xuICAgICAgICBjb25zdCBhZGFwdGVyID0gdGhpcy5fYWRhcHRlcjtcbiAgICAgICAgY29uc3QgbWluID0gdGhpcy5taW47XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4O1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB0aW1lT3B0cyA9IG9wdGlvbnMudGltZTtcbiAgICAgICAgY29uc3QgbWlub3IgPSB0aW1lT3B0cy51bml0IHx8IGRldGVybWluZVVuaXRGb3JBdXRvVGlja3ModGltZU9wdHMubWluVW5pdCwgbWluLCBtYXgsIHRoaXMuX2dldExhYmVsQ2FwYWNpdHkobWluKSk7XG4gICAgICAgIGNvbnN0IHN0ZXBTaXplID0gdmFsdWVPckRlZmF1bHQob3B0aW9ucy50aWNrcy5zdGVwU2l6ZSwgMSk7XG4gICAgICAgIGNvbnN0IHdlZWtkYXkgPSBtaW5vciA9PT0gJ3dlZWsnID8gdGltZU9wdHMuaXNvV2Vla2RheSA6IGZhbHNlO1xuICAgICAgICBjb25zdCBoYXNXZWVrZGF5ID0gaXNOdW1iZXIod2Vla2RheSkgfHwgd2Vla2RheSA9PT0gdHJ1ZTtcbiAgICAgICAgY29uc3QgdGlja3MgPSB7fTtcbiAgICAgICAgbGV0IGZpcnN0ID0gbWluO1xuICAgICAgICBsZXQgdGltZSwgY291bnQ7XG4gICAgICAgIGlmIChoYXNXZWVrZGF5KSB7XG4gICAgICAgICAgICBmaXJzdCA9ICthZGFwdGVyLnN0YXJ0T2YoZmlyc3QsICdpc29XZWVrJywgd2Vla2RheSk7XG4gICAgICAgIH1cbiAgICAgICAgZmlyc3QgPSArYWRhcHRlci5zdGFydE9mKGZpcnN0LCBoYXNXZWVrZGF5ID8gJ2RheScgOiBtaW5vcik7XG4gICAgICAgIGlmIChhZGFwdGVyLmRpZmYobWF4LCBtaW4sIG1pbm9yKSA+IDEwMDAwMCAqIHN0ZXBTaXplKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWluICsgJyBhbmQgJyArIG1heCArICcgYXJlIHRvbyBmYXIgYXBhcnQgd2l0aCBzdGVwU2l6ZSBvZiAnICsgc3RlcFNpemUgKyAnICcgKyBtaW5vcik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGltZXN0YW1wcyA9IG9wdGlvbnMudGlja3Muc291cmNlID09PSAnZGF0YScgJiYgdGhpcy5nZXREYXRhVGltZXN0YW1wcygpO1xuICAgICAgICBmb3IodGltZSA9IGZpcnN0LCBjb3VudCA9IDA7IHRpbWUgPCBtYXg7IHRpbWUgPSArYWRhcHRlci5hZGQodGltZSwgc3RlcFNpemUsIG1pbm9yKSwgY291bnQrKyl7XG4gICAgICAgICAgICBhZGRUaWNrKHRpY2tzLCB0aW1lLCB0aW1lc3RhbXBzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGltZSA9PT0gbWF4IHx8IG9wdGlvbnMuYm91bmRzID09PSAndGlja3MnIHx8IGNvdW50ID09PSAxKSB7XG4gICAgICAgICAgICBhZGRUaWNrKHRpY2tzLCB0aW1lLCB0aW1lc3RhbXBzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGlja3MpLnNvcnQoc29ydGVyKS5tYXAoKHgpPT4reCk7XG4gICAgfVxuIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgY29uc3QgYWRhcHRlciA9IHRoaXMuX2FkYXB0ZXI7XG4gICAgICAgIGNvbnN0IHRpbWVPcHRzID0gdGhpcy5vcHRpb25zLnRpbWU7XG4gICAgICAgIGlmICh0aW1lT3B0cy50b29sdGlwRm9ybWF0KSB7XG4gICAgICAgICAgICByZXR1cm4gYWRhcHRlci5mb3JtYXQodmFsdWUsIHRpbWVPcHRzLnRvb2x0aXBGb3JtYXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhZGFwdGVyLmZvcm1hdCh2YWx1ZSwgdGltZU9wdHMuZGlzcGxheUZvcm1hdHMuZGF0ZXRpbWUpO1xuICAgIH1cbiBmb3JtYXQodmFsdWUsIGZvcm1hdCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBmb3JtYXRzID0gb3B0aW9ucy50aW1lLmRpc3BsYXlGb3JtYXRzO1xuICAgICAgICBjb25zdCB1bml0ID0gdGhpcy5fdW5pdDtcbiAgICAgICAgY29uc3QgZm10ID0gZm9ybWF0IHx8IGZvcm1hdHNbdW5pdF07XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGFwdGVyLmZvcm1hdCh2YWx1ZSwgZm10KTtcbiAgICB9XG4gX3RpY2tGb3JtYXRGdW5jdGlvbih0aW1lLCBpbmRleCwgdGlja3MsIGZvcm1hdCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBmb3JtYXR0ZXIgPSBvcHRpb25zLnRpY2tzLmNhbGxiYWNrO1xuICAgICAgICBpZiAoZm9ybWF0dGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZm9ybWF0dGVyLCBbXG4gICAgICAgICAgICAgICAgdGltZSxcbiAgICAgICAgICAgICAgICBpbmRleCxcbiAgICAgICAgICAgICAgICB0aWNrc1xuICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZm9ybWF0cyA9IG9wdGlvbnMudGltZS5kaXNwbGF5Rm9ybWF0cztcbiAgICAgICAgY29uc3QgdW5pdCA9IHRoaXMuX3VuaXQ7XG4gICAgICAgIGNvbnN0IG1ham9yVW5pdCA9IHRoaXMuX21ham9yVW5pdDtcbiAgICAgICAgY29uc3QgbWlub3JGb3JtYXQgPSB1bml0ICYmIGZvcm1hdHNbdW5pdF07XG4gICAgICAgIGNvbnN0IG1ham9yRm9ybWF0ID0gbWFqb3JVbml0ICYmIGZvcm1hdHNbbWFqb3JVbml0XTtcbiAgICAgICAgY29uc3QgdGljayA9IHRpY2tzW2luZGV4XTtcbiAgICAgICAgY29uc3QgbWFqb3IgPSBtYWpvclVuaXQgJiYgbWFqb3JGb3JtYXQgJiYgdGljayAmJiB0aWNrLm1ham9yO1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRhcHRlci5mb3JtYXQodGltZSwgZm9ybWF0IHx8IChtYWpvciA/IG1ham9yRm9ybWF0IDogbWlub3JGb3JtYXQpKTtcbiAgICB9XG4gZ2VuZXJhdGVUaWNrTGFiZWxzKHRpY2tzKSB7XG4gICAgICAgIGxldCBpLCBpbGVuLCB0aWNrO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgdGljayA9IHRpY2tzW2ldO1xuICAgICAgICAgICAgdGljay5sYWJlbCA9IHRoaXMuX3RpY2tGb3JtYXRGdW5jdGlvbih0aWNrLnZhbHVlLCBpLCB0aWNrcyk7XG4gICAgICAgIH1cbiAgICB9XG4gZ2V0RGVjaW1hbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbCA/IE5hTiA6ICh2YWx1ZSAtIHRoaXMubWluKSAvICh0aGlzLm1heCAtIHRoaXMubWluKTtcbiAgICB9XG4gZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICBjb25zdCBvZmZzZXRzID0gdGhpcy5fb2Zmc2V0cztcbiAgICAgICAgY29uc3QgcG9zID0gdGhpcy5nZXREZWNpbWFsRm9yVmFsdWUodmFsdWUpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRQaXhlbEZvckRlY2ltYWwoKG9mZnNldHMuc3RhcnQgKyBwb3MpICogb2Zmc2V0cy5mYWN0b3IpO1xuICAgIH1cbiBnZXRWYWx1ZUZvclBpeGVsKHBpeGVsKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldHMgPSB0aGlzLl9vZmZzZXRzO1xuICAgICAgICBjb25zdCBwb3MgPSB0aGlzLmdldERlY2ltYWxGb3JQaXhlbChwaXhlbCkgLyBvZmZzZXRzLmZhY3RvciAtIG9mZnNldHMuZW5kO1xuICAgICAgICByZXR1cm4gdGhpcy5taW4gKyBwb3MgKiAodGhpcy5tYXggLSB0aGlzLm1pbik7XG4gICAgfVxuIF9nZXRMYWJlbFNpemUobGFiZWwpIHtcbiAgICAgICAgY29uc3QgdGlja3NPcHRzID0gdGhpcy5vcHRpb25zLnRpY2tzO1xuICAgICAgICBjb25zdCB0aWNrTGFiZWxXaWR0aCA9IHRoaXMuY3R4Lm1lYXN1cmVUZXh0KGxhYmVsKS53aWR0aDtcbiAgICAgICAgY29uc3QgYW5nbGUgPSB0b1JhZGlhbnModGhpcy5pc0hvcml6b250YWwoKSA/IHRpY2tzT3B0cy5tYXhSb3RhdGlvbiA6IHRpY2tzT3B0cy5taW5Sb3RhdGlvbik7XG4gICAgICAgIGNvbnN0IGNvc1JvdGF0aW9uID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgICAgICBjb25zdCBzaW5Sb3RhdGlvbiA9IE1hdGguc2luKGFuZ2xlKTtcbiAgICAgICAgY29uc3QgdGlja0ZvbnRTaXplID0gdGhpcy5fcmVzb2x2ZVRpY2tGb250T3B0aW9ucygwKS5zaXplO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdzogdGlja0xhYmVsV2lkdGggKiBjb3NSb3RhdGlvbiArIHRpY2tGb250U2l6ZSAqIHNpblJvdGF0aW9uLFxuICAgICAgICAgICAgaDogdGlja0xhYmVsV2lkdGggKiBzaW5Sb3RhdGlvbiArIHRpY2tGb250U2l6ZSAqIGNvc1JvdGF0aW9uXG4gICAgICAgIH07XG4gICAgfVxuIF9nZXRMYWJlbENhcGFjaXR5KGV4YW1wbGVUaW1lKSB7XG4gICAgICAgIGNvbnN0IHRpbWVPcHRzID0gdGhpcy5vcHRpb25zLnRpbWU7XG4gICAgICAgIGNvbnN0IGRpc3BsYXlGb3JtYXRzID0gdGltZU9wdHMuZGlzcGxheUZvcm1hdHM7XG4gICAgICAgIGNvbnN0IGZvcm1hdCA9IGRpc3BsYXlGb3JtYXRzW3RpbWVPcHRzLnVuaXRdIHx8IGRpc3BsYXlGb3JtYXRzLm1pbGxpc2Vjb25kO1xuICAgICAgICBjb25zdCBleGFtcGxlTGFiZWwgPSB0aGlzLl90aWNrRm9ybWF0RnVuY3Rpb24oZXhhbXBsZVRpbWUsIDAsIHRpY2tzRnJvbVRpbWVzdGFtcHModGhpcywgW1xuICAgICAgICAgICAgZXhhbXBsZVRpbWVcbiAgICAgICAgXSwgdGhpcy5fbWFqb3JVbml0KSwgZm9ybWF0KTtcbiAgICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuX2dldExhYmVsU2l6ZShleGFtcGxlTGFiZWwpO1xuICAgICAgICBjb25zdCBjYXBhY2l0eSA9IE1hdGguZmxvb3IodGhpcy5pc0hvcml6b250YWwoKSA/IHRoaXMud2lkdGggLyBzaXplLncgOiB0aGlzLmhlaWdodCAvIHNpemUuaCkgLSAxO1xuICAgICAgICByZXR1cm4gY2FwYWNpdHkgPiAwID8gY2FwYWNpdHkgOiAxO1xuICAgIH1cbiBnZXREYXRhVGltZXN0YW1wcygpIHtcbiAgICAgICAgbGV0IHRpbWVzdGFtcHMgPSB0aGlzLl9jYWNoZS5kYXRhIHx8IFtdO1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgaWYgKHRpbWVzdGFtcHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGltZXN0YW1wcztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtZXRhcyA9IHRoaXMuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXMoKTtcbiAgICAgICAgaWYgKHRoaXMuX25vcm1hbGl6ZWQgJiYgbWV0YXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fY2FjaGUuZGF0YSA9IG1ldGFzWzBdLmNvbnRyb2xsZXIuZ2V0QWxsUGFyc2VkVmFsdWVzKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IG1ldGFzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICB0aW1lc3RhbXBzID0gdGltZXN0YW1wcy5jb25jYXQobWV0YXNbaV0uY29udHJvbGxlci5nZXRBbGxQYXJzZWRWYWx1ZXModGhpcykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5kYXRhID0gdGhpcy5ub3JtYWxpemUodGltZXN0YW1wcyk7XG4gICAgfVxuIGdldExhYmVsVGltZXN0YW1wcygpIHtcbiAgICAgICAgY29uc3QgdGltZXN0YW1wcyA9IHRoaXMuX2NhY2hlLmxhYmVscyB8fCBbXTtcbiAgICAgICAgbGV0IGksIGlsZW47XG4gICAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHRpbWVzdGFtcHM7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGFiZWxzID0gdGhpcy5nZXRMYWJlbHMoKTtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gbGFiZWxzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICB0aW1lc3RhbXBzLnB1c2gocGFyc2UodGhpcywgbGFiZWxzW2ldKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlLmxhYmVscyA9IHRoaXMuX25vcm1hbGl6ZWQgPyB0aW1lc3RhbXBzIDogdGhpcy5ub3JtYWxpemUodGltZXN0YW1wcyk7XG4gICAgfVxuIG5vcm1hbGl6ZSh2YWx1ZXMpIHtcbiAgICAgICAgcmV0dXJuIF9hcnJheVVuaXF1ZSh2YWx1ZXMuc29ydChzb3J0ZXIpKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKHRhYmxlLCB2YWwsIHJldmVyc2UpIHtcbiAgICBsZXQgbG8gPSAwO1xuICAgIGxldCBoaSA9IHRhYmxlLmxlbmd0aCAtIDE7XG4gICAgbGV0IHByZXZTb3VyY2UsIG5leHRTb3VyY2UsIHByZXZUYXJnZXQsIG5leHRUYXJnZXQ7XG4gICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgaWYgKHZhbCA+PSB0YWJsZVtsb10ucG9zICYmIHZhbCA8PSB0YWJsZVtoaV0ucG9zKSB7XG4gICAgICAgICAgICAoeyBsbyAsIGhpICB9ID0gX2xvb2t1cEJ5S2V5KHRhYmxlLCAncG9zJywgdmFsKSk7XG4gICAgICAgIH1cbiAgICAgICAgKHsgcG9zOiBwcmV2U291cmNlICwgdGltZTogcHJldlRhcmdldCAgfSA9IHRhYmxlW2xvXSk7XG4gICAgICAgICh7IHBvczogbmV4dFNvdXJjZSAsIHRpbWU6IG5leHRUYXJnZXQgIH0gPSB0YWJsZVtoaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh2YWwgPj0gdGFibGVbbG9dLnRpbWUgJiYgdmFsIDw9IHRhYmxlW2hpXS50aW1lKSB7XG4gICAgICAgICAgICAoeyBsbyAsIGhpICB9ID0gX2xvb2t1cEJ5S2V5KHRhYmxlLCAndGltZScsIHZhbCkpO1xuICAgICAgICB9XG4gICAgICAgICh7IHRpbWU6IHByZXZTb3VyY2UgLCBwb3M6IHByZXZUYXJnZXQgIH0gPSB0YWJsZVtsb10pO1xuICAgICAgICAoeyB0aW1lOiBuZXh0U291cmNlICwgcG9zOiBuZXh0VGFyZ2V0ICB9ID0gdGFibGVbaGldKTtcbiAgICB9XG4gICAgY29uc3Qgc3BhbiA9IG5leHRTb3VyY2UgLSBwcmV2U291cmNlO1xuICAgIHJldHVybiBzcGFuID8gcHJldlRhcmdldCArIChuZXh0VGFyZ2V0IC0gcHJldlRhcmdldCkgKiAodmFsIC0gcHJldlNvdXJjZSkgLyBzcGFuIDogcHJldlRhcmdldDtcbn1cbmNsYXNzIFRpbWVTZXJpZXNTY2FsZSBleHRlbmRzIFRpbWVTY2FsZSB7XG4gICAgc3RhdGljIGlkID0gJ3RpbWVzZXJpZXMnO1xuIHN0YXRpYyBkZWZhdWx0cyA9IFRpbWVTY2FsZS5kZWZhdWx0cztcbiBjb25zdHJ1Y3Rvcihwcm9wcyl7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcbiAgICAgICAgIHRoaXMuX3RhYmxlID0gW107XG4gICAgICAgICB0aGlzLl9taW5Qb3MgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLl90YWJsZVJhbmdlID0gdW5kZWZpbmVkO1xuICAgIH1cbiBpbml0T2Zmc2V0cygpIHtcbiAgICAgICAgY29uc3QgdGltZXN0YW1wcyA9IHRoaXMuX2dldFRpbWVzdGFtcHNGb3JUYWJsZSgpO1xuICAgICAgICBjb25zdCB0YWJsZSA9IHRoaXMuX3RhYmxlID0gdGhpcy5idWlsZExvb2t1cFRhYmxlKHRpbWVzdGFtcHMpO1xuICAgICAgICB0aGlzLl9taW5Qb3MgPSBpbnRlcnBvbGF0ZSh0YWJsZSwgdGhpcy5taW4pO1xuICAgICAgICB0aGlzLl90YWJsZVJhbmdlID0gaW50ZXJwb2xhdGUodGFibGUsIHRoaXMubWF4KSAtIHRoaXMuX21pblBvcztcbiAgICAgICAgc3VwZXIuaW5pdE9mZnNldHModGltZXN0YW1wcyk7XG4gICAgfVxuIGJ1aWxkTG9va3VwVGFibGUodGltZXN0YW1wcykge1xuICAgICAgICBjb25zdCB7IG1pbiAsIG1heCAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gW107XG4gICAgICAgIGNvbnN0IHRhYmxlID0gW107XG4gICAgICAgIGxldCBpLCBpbGVuLCBwcmV2LCBjdXJyLCBuZXh0O1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aW1lc3RhbXBzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBjdXJyID0gdGltZXN0YW1wc1tpXTtcbiAgICAgICAgICAgIGlmIChjdXJyID49IG1pbiAmJiBjdXJyIDw9IG1heCkge1xuICAgICAgICAgICAgICAgIGl0ZW1zLnB1c2goY3Vycik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGl0ZW1zLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0aW1lOiBtaW4sXG4gICAgICAgICAgICAgICAgICAgIHBvczogMFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0aW1lOiBtYXgsXG4gICAgICAgICAgICAgICAgICAgIHBvczogMVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gaXRlbXMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIG5leHQgPSBpdGVtc1tpICsgMV07XG4gICAgICAgICAgICBwcmV2ID0gaXRlbXNbaSAtIDFdO1xuICAgICAgICAgICAgY3VyciA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgaWYgKE1hdGgucm91bmQoKG5leHQgKyBwcmV2KSAvIDIpICE9PSBjdXJyKSB7XG4gICAgICAgICAgICAgICAgdGFibGUucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHRpbWU6IGN1cnIsXG4gICAgICAgICAgICAgICAgICAgIHBvczogaSAvIChpbGVuIC0gMSlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGFibGU7XG4gICAgfVxuIF9nZW5lcmF0ZSgpIHtcbiAgICAgICAgY29uc3QgbWluID0gdGhpcy5taW47XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4O1xuICAgICAgICBsZXQgdGltZXN0YW1wcyA9IHN1cGVyLmdldERhdGFUaW1lc3RhbXBzKCk7XG4gICAgICAgIGlmICghdGltZXN0YW1wcy5pbmNsdWRlcyhtaW4pIHx8ICF0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGltZXN0YW1wcy5zcGxpY2UoMCwgMCwgbWluKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRpbWVzdGFtcHMuaW5jbHVkZXMobWF4KSB8fCB0aW1lc3RhbXBzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgdGltZXN0YW1wcy5wdXNoKG1heCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRpbWVzdGFtcHMuc29ydCgoYSwgYik9PmEgLSBiKTtcbiAgICB9XG4gX2dldFRpbWVzdGFtcHNGb3JUYWJsZSgpIHtcbiAgICAgICAgbGV0IHRpbWVzdGFtcHMgPSB0aGlzLl9jYWNoZS5hbGwgfHwgW107XG4gICAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHRpbWVzdGFtcHM7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZ2V0RGF0YVRpbWVzdGFtcHMoKTtcbiAgICAgICAgY29uc3QgbGFiZWwgPSB0aGlzLmdldExhYmVsVGltZXN0YW1wcygpO1xuICAgICAgICBpZiAoZGF0YS5sZW5ndGggJiYgbGFiZWwubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aW1lc3RhbXBzID0gdGhpcy5ub3JtYWxpemUoZGF0YS5jb25jYXQobGFiZWwpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRpbWVzdGFtcHMgPSBkYXRhLmxlbmd0aCA/IGRhdGEgOiBsYWJlbDtcbiAgICAgICAgfVxuICAgICAgICB0aW1lc3RhbXBzID0gdGhpcy5fY2FjaGUuYWxsID0gdGltZXN0YW1wcztcbiAgICAgICAgcmV0dXJuIHRpbWVzdGFtcHM7XG4gICAgfVxuIGdldERlY2ltYWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gKGludGVycG9sYXRlKHRoaXMuX3RhYmxlLCB2YWx1ZSkgLSB0aGlzLl9taW5Qb3MpIC8gdGhpcy5fdGFibGVSYW5nZTtcbiAgICB9XG4gZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgICAgICBjb25zdCBvZmZzZXRzID0gdGhpcy5fb2Zmc2V0cztcbiAgICAgICAgY29uc3QgZGVjaW1hbCA9IHRoaXMuZ2V0RGVjaW1hbEZvclBpeGVsKHBpeGVsKSAvIG9mZnNldHMuZmFjdG9yIC0gb2Zmc2V0cy5lbmQ7XG4gICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZSh0aGlzLl90YWJsZSwgZGVjaW1hbCAqIHRoaXMuX3RhYmxlUmFuZ2UgKyB0aGlzLl9taW5Qb3MsIHRydWUpO1xuICAgIH1cbn1cblxudmFyIHNjYWxlcyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbl9fcHJvdG9fXzogbnVsbCxcbkNhdGVnb3J5U2NhbGU6IENhdGVnb3J5U2NhbGUsXG5MaW5lYXJTY2FsZTogTGluZWFyU2NhbGUsXG5Mb2dhcml0aG1pY1NjYWxlOiBMb2dhcml0aG1pY1NjYWxlLFxuUmFkaWFsTGluZWFyU2NhbGU6IFJhZGlhbExpbmVhclNjYWxlLFxuVGltZVNjYWxlOiBUaW1lU2NhbGUsXG5UaW1lU2VyaWVzU2NhbGU6IFRpbWVTZXJpZXNTY2FsZVxufSk7XG5cbmNvbnN0IHJlZ2lzdGVyYWJsZXMgPSBbXG4gICAgY29udHJvbGxlcnMsXG4gICAgZWxlbWVudHMsXG4gICAgcGx1Z2lucyxcbiAgICBzY2FsZXNcbl07XG5cbmV4cG9ydCB7IEFuaW1hdGlvbiwgQW5pbWF0aW9ucywgQXJjRWxlbWVudCwgQmFyQ29udHJvbGxlciwgQmFyRWxlbWVudCwgQmFzZVBsYXRmb3JtLCBCYXNpY1BsYXRmb3JtLCBCdWJibGVDb250cm9sbGVyLCBDYXRlZ29yeVNjYWxlLCBDaGFydCwgcGx1Z2luX2NvbG9ycyBhcyBDb2xvcnMsIERhdGFzZXRDb250cm9sbGVyLCBwbHVnaW5fZGVjaW1hdGlvbiBhcyBEZWNpbWF0aW9uLCBEb21QbGF0Zm9ybSwgRG91Z2hudXRDb250cm9sbGVyLCBFbGVtZW50LCBpbmRleCBhcyBGaWxsZXIsIEludGVyYWN0aW9uLCBwbHVnaW5fbGVnZW5kIGFzIExlZ2VuZCwgTGluZUNvbnRyb2xsZXIsIExpbmVFbGVtZW50LCBMaW5lYXJTY2FsZSwgTG9nYXJpdGhtaWNTY2FsZSwgUGllQ29udHJvbGxlciwgUG9pbnRFbGVtZW50LCBQb2xhckFyZWFDb250cm9sbGVyLCBSYWRhckNvbnRyb2xsZXIsIFJhZGlhbExpbmVhclNjYWxlLCBTY2FsZSwgU2NhdHRlckNvbnRyb2xsZXIsIHBsdWdpbl9zdWJ0aXRsZSBhcyBTdWJUaXRsZSwgVGlja3MsIFRpbWVTY2FsZSwgVGltZVNlcmllc1NjYWxlLCBwbHVnaW5fdGl0bGUgYXMgVGl0bGUsIHBsdWdpbl90b29sdGlwIGFzIFRvb2x0aXAsIGFkYXB0ZXJzIGFzIF9hZGFwdGVycywgX2RldGVjdFBsYXRmb3JtLCBhbmltYXRvciwgY29udHJvbGxlcnMsIGRlZmF1bHRzLCBlbGVtZW50cywgbGF5b3V0cywgcGx1Z2lucywgcmVnaXN0ZXJhYmxlcywgcmVnaXN0cnksIHNjYWxlcyB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y2hhcnQuanMubWFwXG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/chart.js/dist/chart.js\n"); /***/ }), /***/ "./node_modules/chart.js/dist/chunks/helpers.dataset.js": /*!**************************************************************!*\ !*** ./node_modules/chart.js/dist/chunks/helpers.dataset.js ***! \**************************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ $: () => (/* binding */ unclipArea),\n/* harmony export */ A: () => (/* binding */ _rlookupByKey),\n/* harmony export */ B: () => (/* binding */ _lookupByKey),\n/* harmony export */ C: () => (/* binding */ _isPointInArea),\n/* harmony export */ D: () => (/* binding */ getAngleFromPoint),\n/* harmony export */ E: () => (/* binding */ toPadding),\n/* harmony export */ F: () => (/* binding */ each),\n/* harmony export */ G: () => (/* binding */ getMaximumSize),\n/* harmony export */ H: () => (/* binding */ HALF_PI),\n/* harmony export */ I: () => (/* binding */ _getParentNode),\n/* harmony export */ J: () => (/* binding */ readUsedSize),\n/* harmony export */ K: () => (/* binding */ supportsEventListenerOptions),\n/* harmony export */ L: () => (/* binding */ throttled),\n/* harmony export */ M: () => (/* binding */ _isDomSupported),\n/* harmony export */ N: () => (/* binding */ _factorize),\n/* harmony export */ O: () => (/* binding */ finiteOrDefault),\n/* harmony export */ P: () => (/* binding */ PI),\n/* harmony export */ Q: () => (/* binding */ callback),\n/* harmony export */ R: () => (/* binding */ _addGrace),\n/* harmony export */ S: () => (/* binding */ _limitValue),\n/* harmony export */ T: () => (/* binding */ TAU),\n/* harmony export */ U: () => (/* binding */ toDegrees),\n/* harmony export */ V: () => (/* binding */ _measureText),\n/* harmony export */ W: () => (/* binding */ _int16Range),\n/* harmony export */ X: () => (/* binding */ _alignPixel),\n/* harmony export */ Y: () => (/* binding */ clipArea),\n/* harmony export */ Z: () => (/* binding */ renderText),\n/* harmony export */ _: () => (/* binding */ _arrayUnique),\n/* harmony export */ a: () => (/* binding */ resolve),\n/* harmony export */ a$: () => (/* binding */ getStyle),\n/* harmony export */ a0: () => (/* binding */ toFont),\n/* harmony export */ a1: () => (/* binding */ _toLeftRightCenter),\n/* harmony export */ a2: () => (/* binding */ _alignStartEnd),\n/* harmony export */ a3: () => (/* binding */ overrides),\n/* harmony export */ a4: () => (/* binding */ merge),\n/* harmony export */ a5: () => (/* binding */ _capitalize),\n/* harmony export */ a6: () => (/* binding */ descriptors),\n/* harmony export */ a7: () => (/* binding */ isFunction),\n/* harmony export */ a8: () => (/* binding */ _attachContext),\n/* harmony export */ a9: () => (/* binding */ _createResolver),\n/* harmony export */ aA: () => (/* binding */ getRtlAdapter),\n/* harmony export */ aB: () => (/* binding */ overrideTextDirection),\n/* harmony export */ aC: () => (/* binding */ _textX),\n/* harmony export */ aD: () => (/* binding */ restoreTextDirection),\n/* harmony export */ aE: () => (/* binding */ drawPointLegend),\n/* harmony export */ aF: () => (/* binding */ distanceBetweenPoints),\n/* harmony export */ aG: () => (/* binding */ noop),\n/* harmony export */ aH: () => (/* binding */ _setMinAndMaxByKey),\n/* harmony export */ aI: () => (/* binding */ niceNum),\n/* harmony export */ aJ: () => (/* binding */ almostWhole),\n/* harmony export */ aK: () => (/* binding */ almostEquals),\n/* harmony export */ aL: () => (/* binding */ _decimalPlaces),\n/* harmony export */ aM: () => (/* binding */ Ticks),\n/* harmony export */ aN: () => (/* binding */ log10),\n/* harmony export */ aO: () => (/* binding */ _longestText),\n/* harmony export */ aP: () => (/* binding */ _filterBetween),\n/* harmony export */ aQ: () => (/* binding */ _lookup),\n/* harmony export */ aR: () => (/* binding */ isPatternOrGradient),\n/* harmony export */ aS: () => (/* binding */ getHoverColor),\n/* harmony export */ aT: () => (/* binding */ clone),\n/* harmony export */ aU: () => (/* binding */ _merger),\n/* harmony export */ aV: () => (/* binding */ _mergerIf),\n/* harmony export */ aW: () => (/* binding */ _deprecated),\n/* harmony export */ aX: () => (/* binding */ _splitKey),\n/* harmony export */ aY: () => (/* binding */ toFontString),\n/* harmony export */ aZ: () => (/* binding */ splineCurve),\n/* harmony export */ a_: () => (/* binding */ splineCurveMonotone),\n/* harmony export */ aa: () => (/* binding */ _descriptors),\n/* harmony export */ ab: () => (/* binding */ mergeIf),\n/* harmony export */ ac: () => (/* binding */ uid),\n/* harmony export */ ad: () => (/* binding */ debounce),\n/* harmony export */ ae: () => (/* binding */ retinaScale),\n/* harmony export */ af: () => (/* binding */ clearCanvas),\n/* harmony export */ ag: () => (/* binding */ setsEqual),\n/* harmony export */ ah: () => (/* binding */ getDatasetClipArea),\n/* harmony export */ ai: () => (/* binding */ _elementsEqual),\n/* harmony export */ aj: () => (/* binding */ _isClickEvent),\n/* harmony export */ ak: () => (/* binding */ _isBetween),\n/* harmony export */ al: () => (/* binding */ _normalizeAngle),\n/* harmony export */ am: () => (/* binding */ _readValueToProps),\n/* harmony export */ an: () => (/* binding */ _updateBezierControlPoints),\n/* harmony export */ ao: () => (/* binding */ _computeSegments),\n/* harmony export */ ap: () => (/* binding */ _boundSegments),\n/* harmony export */ aq: () => (/* binding */ _steppedInterpolation),\n/* harmony export */ ar: () => (/* binding */ _bezierInterpolation),\n/* harmony export */ as: () => (/* binding */ _pointInLine),\n/* harmony export */ at: () => (/* binding */ _steppedLineTo),\n/* harmony export */ au: () => (/* binding */ _bezierCurveTo),\n/* harmony export */ av: () => (/* binding */ drawPoint),\n/* harmony export */ aw: () => (/* binding */ addRoundedRectPath),\n/* harmony export */ ax: () => (/* binding */ toTRBL),\n/* harmony export */ ay: () => (/* binding */ toTRBLCorners),\n/* harmony export */ az: () => (/* binding */ _boundSegment),\n/* harmony export */ b: () => (/* binding */ isArray),\n/* harmony export */ b0: () => (/* binding */ fontString),\n/* harmony export */ b1: () => (/* binding */ toLineHeight),\n/* harmony export */ b2: () => (/* binding */ PITAU),\n/* harmony export */ b3: () => (/* binding */ INFINITY),\n/* harmony export */ b4: () => (/* binding */ RAD_PER_DEG),\n/* harmony export */ b5: () => (/* binding */ QUARTER_PI),\n/* harmony export */ b6: () => (/* binding */ TWO_THIRDS_PI),\n/* harmony export */ b7: () => (/* binding */ _angleDiff),\n/* harmony export */ c: () => (/* binding */ color),\n/* harmony export */ d: () => (/* binding */ defaults),\n/* harmony export */ e: () => (/* binding */ effects),\n/* harmony export */ f: () => (/* binding */ resolveObjectKey),\n/* harmony export */ g: () => (/* binding */ isNumberFinite),\n/* harmony export */ h: () => (/* binding */ defined),\n/* harmony export */ i: () => (/* binding */ isObject),\n/* harmony export */ j: () => (/* binding */ createContext),\n/* harmony export */ k: () => (/* binding */ isNullOrUndef),\n/* harmony export */ l: () => (/* binding */ listenArrayEvents),\n/* harmony export */ m: () => (/* binding */ toPercentage),\n/* harmony export */ n: () => (/* binding */ toDimension),\n/* harmony export */ o: () => (/* binding */ formatNumber),\n/* harmony export */ p: () => (/* binding */ _angleBetween),\n/* harmony export */ q: () => (/* binding */ _getStartAndCountOfVisiblePoints),\n/* harmony export */ r: () => (/* binding */ requestAnimFrame),\n/* harmony export */ s: () => (/* binding */ sign),\n/* harmony export */ t: () => (/* binding */ toRadians),\n/* harmony export */ u: () => (/* binding */ unlistenArrayEvents),\n/* harmony export */ v: () => (/* binding */ valueOrDefault),\n/* harmony export */ w: () => (/* binding */ _scaleRangesChanged),\n/* harmony export */ x: () => (/* binding */ isNumber),\n/* harmony export */ y: () => (/* binding */ _parseObjectDataRadialScale),\n/* harmony export */ z: () => (/* binding */ getRelativePosition)\n/* harmony export */ });\n/* harmony import */ var _kurkle_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kurkle/color */ \"./node_modules/@kurkle/color/dist/color.esm.js\");\n/*!\n * Chart.js v4.5.0\n * https://www.chartjs.org\n * (c) 2025 Chart.js Contributors\n * Released under the MIT License\n */\n\n\n/**\n * @namespace Chart.helpers\n */ /**\n * An empty function that can be used, for example, for optional callback.\n */ function noop() {\n/* noop */ }\n/**\n * Returns a unique id, sequentially generated from a global variable.\n */ const uid = (()=>{\n let id = 0;\n return ()=>id++;\n})();\n/**\n * Returns true if `value` is neither null nor undefined, else returns false.\n * @param value - The value to test.\n * @since 2.7.0\n */ function isNullOrUndef(value) {\n return value === null || value === undefined;\n}\n/**\n * Returns true if `value` is an array (including typed arrays), else returns false.\n * @param value - The value to test.\n * @function\n */ function isArray(value) {\n if (Array.isArray && Array.isArray(value)) {\n return true;\n }\n const type = Object.prototype.toString.call(value);\n if (type.slice(0, 7) === '[object' && type.slice(-6) === 'Array]') {\n return true;\n }\n return false;\n}\n/**\n * Returns true if `value` is an object (excluding null), else returns false.\n * @param value - The value to test.\n * @since 2.7.0\n */ function isObject(value) {\n return value !== null && Object.prototype.toString.call(value) === '[object Object]';\n}\n/**\n * Returns true if `value` is a finite number, else returns false\n * @param value - The value to test.\n */ function isNumberFinite(value) {\n return (typeof value === 'number' || value instanceof Number) && isFinite(+value);\n}\n/**\n * Returns `value` if finite, else returns `defaultValue`.\n * @param value - The value to return if defined.\n * @param defaultValue - The value to return if `value` is not finite.\n */ function finiteOrDefault(value, defaultValue) {\n return isNumberFinite(value) ? value : defaultValue;\n}\n/**\n * Returns `value` if defined, else returns `defaultValue`.\n * @param value - The value to return if defined.\n * @param defaultValue - The value to return if `value` is undefined.\n */ function valueOrDefault(value, defaultValue) {\n return typeof value === 'undefined' ? defaultValue : value;\n}\nconst toPercentage = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 : +value / dimension;\nconst toDimension = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 * dimension : +value;\n/**\n * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the\n * value returned by `fn`. If `fn` is not a function, this method returns undefined.\n * @param fn - The function to call.\n * @param args - The arguments with which `fn` should be called.\n * @param [thisArg] - The value of `this` provided for the call to `fn`.\n */ function callback(fn, args, thisArg) {\n if (fn && typeof fn.call === 'function') {\n return fn.apply(thisArg, args);\n }\n}\nfunction each(loopable, fn, thisArg, reverse) {\n let i, len, keys;\n if (isArray(loopable)) {\n len = loopable.length;\n if (reverse) {\n for(i = len - 1; i >= 0; i--){\n fn.call(thisArg, loopable[i], i);\n }\n } else {\n for(i = 0; i < len; i++){\n fn.call(thisArg, loopable[i], i);\n }\n }\n } else if (isObject(loopable)) {\n keys = Object.keys(loopable);\n len = keys.length;\n for(i = 0; i < len; i++){\n fn.call(thisArg, loopable[keys[i]], keys[i]);\n }\n }\n}\n/**\n * Returns true if the `a0` and `a1` arrays have the same content, else returns false.\n * @param a0 - The array to compare\n * @param a1 - The array to compare\n * @private\n */ function _elementsEqual(a0, a1) {\n let i, ilen, v0, v1;\n if (!a0 || !a1 || a0.length !== a1.length) {\n return false;\n }\n for(i = 0, ilen = a0.length; i < ilen; ++i){\n v0 = a0[i];\n v1 = a1[i];\n if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) {\n return false;\n }\n }\n return true;\n}\n/**\n * Returns a deep copy of `source` without keeping references on objects and arrays.\n * @param source - The value to clone.\n */ function clone(source) {\n if (isArray(source)) {\n return source.map(clone);\n }\n if (isObject(source)) {\n const target = Object.create(null);\n const keys = Object.keys(source);\n const klen = keys.length;\n let k = 0;\n for(; k < klen; ++k){\n target[keys[k]] = clone(source[keys[k]]);\n }\n return target;\n }\n return source;\n}\nfunction isValidKey(key) {\n return [\n '__proto__',\n 'prototype',\n 'constructor'\n ].indexOf(key) === -1;\n}\n/**\n * The default merger when Chart.helpers.merge is called without merger option.\n * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback.\n * @private\n */ function _merger(key, target, source, options) {\n if (!isValidKey(key)) {\n return;\n }\n const tval = target[key];\n const sval = source[key];\n if (isObject(tval) && isObject(sval)) {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n merge(tval, sval, options);\n } else {\n target[key] = clone(sval);\n }\n}\nfunction merge(target, source, options) {\n const sources = isArray(source) ? source : [\n source\n ];\n const ilen = sources.length;\n if (!isObject(target)) {\n return target;\n }\n options = options || {};\n const merger = options.merger || _merger;\n let current;\n for(let i = 0; i < ilen; ++i){\n current = sources[i];\n if (!isObject(current)) {\n continue;\n }\n const keys = Object.keys(current);\n for(let k = 0, klen = keys.length; k < klen; ++k){\n merger(keys[k], target, current, options);\n }\n }\n return target;\n}\nfunction mergeIf(target, source) {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n return merge(target, source, {\n merger: _mergerIf\n });\n}\n/**\n * Merges source[key] in target[key] only if target[key] is undefined.\n * @private\n */ function _mergerIf(key, target, source) {\n if (!isValidKey(key)) {\n return;\n }\n const tval = target[key];\n const sval = source[key];\n if (isObject(tval) && isObject(sval)) {\n mergeIf(tval, sval);\n } else if (!Object.prototype.hasOwnProperty.call(target, key)) {\n target[key] = clone(sval);\n }\n}\n/**\n * @private\n */ function _deprecated(scope, value, previous, current) {\n if (value !== undefined) {\n console.warn(scope + ': \"' + previous + '\" is deprecated. Please use \"' + current + '\" instead');\n }\n}\n// resolveObjectKey resolver cache\nconst keyResolvers = {\n // Chart.helpers.core resolveObjectKey should resolve empty key to root object\n '': (v)=>v,\n // default resolvers\n x: (o)=>o.x,\n y: (o)=>o.y\n};\n/**\n * @private\n */ function _splitKey(key) {\n const parts = key.split('.');\n const keys = [];\n let tmp = '';\n for (const part of parts){\n tmp += part;\n if (tmp.endsWith('\\\\')) {\n tmp = tmp.slice(0, -1) + '.';\n } else {\n keys.push(tmp);\n tmp = '';\n }\n }\n return keys;\n}\nfunction _getKeyResolver(key) {\n const keys = _splitKey(key);\n return (obj)=>{\n for (const k of keys){\n if (k === '') {\n break;\n }\n obj = obj && obj[k];\n }\n return obj;\n };\n}\nfunction resolveObjectKey(obj, key) {\n const resolver = keyResolvers[key] || (keyResolvers[key] = _getKeyResolver(key));\n return resolver(obj);\n}\n/**\n * @private\n */ function _capitalize(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\nconst defined = (value)=>typeof value !== 'undefined';\nconst isFunction = (value)=>typeof value === 'function';\n// Adapted from https://stackoverflow.com/questions/31128855/comparing-ecma6-sets-for-equality#31129384\nconst setsEqual = (a, b)=>{\n if (a.size !== b.size) {\n return false;\n }\n for (const item of a){\n if (!b.has(item)) {\n return false;\n }\n }\n return true;\n};\n/**\n * @param e - The event\n * @private\n */ function _isClickEvent(e) {\n return e.type === 'mouseup' || e.type === 'click' || e.type === 'contextmenu';\n}\n\n/**\n * @alias Chart.helpers.math\n * @namespace\n */ const PI = Math.PI;\nconst TAU = 2 * PI;\nconst PITAU = TAU + PI;\nconst INFINITY = Number.POSITIVE_INFINITY;\nconst RAD_PER_DEG = PI / 180;\nconst HALF_PI = PI / 2;\nconst QUARTER_PI = PI / 4;\nconst TWO_THIRDS_PI = PI * 2 / 3;\nconst log10 = Math.log10;\nconst sign = Math.sign;\nfunction almostEquals(x, y, epsilon) {\n return Math.abs(x - y) < epsilon;\n}\n/**\n * Implementation of the nice number algorithm used in determining where axis labels will go\n */ function niceNum(range) {\n const roundedRange = Math.round(range);\n range = almostEquals(range, roundedRange, range / 1000) ? roundedRange : range;\n const niceRange = Math.pow(10, Math.floor(log10(range)));\n const fraction = range / niceRange;\n const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;\n return niceFraction * niceRange;\n}\n/**\n * Returns an array of factors sorted from 1 to sqrt(value)\n * @private\n */ function _factorize(value) {\n const result = [];\n const sqrt = Math.sqrt(value);\n let i;\n for(i = 1; i < sqrt; i++){\n if (value % i === 0) {\n result.push(i);\n result.push(value / i);\n }\n }\n if (sqrt === (sqrt | 0)) {\n result.push(sqrt);\n }\n result.sort((a, b)=>a - b).pop();\n return result;\n}\n/**\n * Verifies that attempting to coerce n to string or number won't throw a TypeError.\n */ function isNonPrimitive(n) {\n return typeof n === 'symbol' || typeof n === 'object' && n !== null && !(Symbol.toPrimitive in n || 'toString' in n || 'valueOf' in n);\n}\nfunction isNumber(n) {\n return !isNonPrimitive(n) && !isNaN(parseFloat(n)) && isFinite(n);\n}\nfunction almostWhole(x, epsilon) {\n const rounded = Math.round(x);\n return rounded - epsilon <= x && rounded + epsilon >= x;\n}\n/**\n * @private\n */ function _setMinAndMaxByKey(array, target, property) {\n let i, ilen, value;\n for(i = 0, ilen = array.length; i < ilen; i++){\n value = array[i][property];\n if (!isNaN(value)) {\n target.min = Math.min(target.min, value);\n target.max = Math.max(target.max, value);\n }\n }\n}\nfunction toRadians(degrees) {\n return degrees * (PI / 180);\n}\nfunction toDegrees(radians) {\n return radians * (180 / PI);\n}\n/**\n * Returns the number of decimal places\n * i.e. the number of digits after the decimal point, of the value of this Number.\n * @param x - A number.\n * @returns The number of decimal places.\n * @private\n */ function _decimalPlaces(x) {\n if (!isNumberFinite(x)) {\n return;\n }\n let e = 1;\n let p = 0;\n while(Math.round(x * e) / e !== x){\n e *= 10;\n p++;\n }\n return p;\n}\n// Gets the angle from vertical upright to the point about a centre.\nfunction getAngleFromPoint(centrePoint, anglePoint) {\n const distanceFromXCenter = anglePoint.x - centrePoint.x;\n const distanceFromYCenter = anglePoint.y - centrePoint.y;\n const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);\n let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);\n if (angle < -0.5 * PI) {\n angle += TAU; // make sure the returned angle is in the range of (-PI/2, 3PI/2]\n }\n return {\n angle,\n distance: radialDistanceFromCenter\n };\n}\nfunction distanceBetweenPoints(pt1, pt2) {\n return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));\n}\n/**\n * Shortest distance between angles, in either direction.\n * @private\n */ function _angleDiff(a, b) {\n return (a - b + PITAU) % TAU - PI;\n}\n/**\n * Normalize angle to be between 0 and 2*PI\n * @private\n */ function _normalizeAngle(a) {\n return (a % TAU + TAU) % TAU;\n}\n/**\n * @private\n */ function _angleBetween(angle, start, end, sameAngleIsFullCircle) {\n const a = _normalizeAngle(angle);\n const s = _normalizeAngle(start);\n const e = _normalizeAngle(end);\n const angleToStart = _normalizeAngle(s - a);\n const angleToEnd = _normalizeAngle(e - a);\n const startToAngle = _normalizeAngle(a - s);\n const endToAngle = _normalizeAngle(a - e);\n return a === s || a === e || sameAngleIsFullCircle && s === e || angleToStart > angleToEnd && startToAngle < endToAngle;\n}\n/**\n * Limit `value` between `min` and `max`\n * @param value\n * @param min\n * @param max\n * @private\n */ function _limitValue(value, min, max) {\n return Math.max(min, Math.min(max, value));\n}\n/**\n * @param {number} value\n * @private\n */ function _int16Range(value) {\n return _limitValue(value, -32768, 32767);\n}\n/**\n * @param value\n * @param start\n * @param end\n * @param [epsilon]\n * @private\n */ function _isBetween(value, start, end, epsilon = 1e-6) {\n return value >= Math.min(start, end) - epsilon && value <= Math.max(start, end) + epsilon;\n}\n\nfunction _lookup(table, value, cmp) {\n cmp = cmp || ((index)=>table[index] < value);\n let hi = table.length - 1;\n let lo = 0;\n let mid;\n while(hi - lo > 1){\n mid = lo + hi >> 1;\n if (cmp(mid)) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n return {\n lo,\n hi\n };\n}\n/**\n * Binary search\n * @param table - the table search. must be sorted!\n * @param key - property name for the value in each entry\n * @param value - value to find\n * @param last - lookup last index\n * @private\n */ const _lookupByKey = (table, key, value, last)=>_lookup(table, value, last ? (index)=>{\n const ti = table[index][key];\n return ti < value || ti === value && table[index + 1][key] === value;\n } : (index)=>table[index][key] < value);\n/**\n * Reverse binary search\n * @param table - the table search. must be sorted!\n * @param key - property name for the value in each entry\n * @param value - value to find\n * @private\n */ const _rlookupByKey = (table, key, value)=>_lookup(table, value, (index)=>table[index][key] >= value);\n/**\n * Return subset of `values` between `min` and `max` inclusive.\n * Values are assumed to be in sorted order.\n * @param values - sorted array of values\n * @param min - min value\n * @param max - max value\n */ function _filterBetween(values, min, max) {\n let start = 0;\n let end = values.length;\n while(start < end && values[start] < min){\n start++;\n }\n while(end > start && values[end - 1] > max){\n end--;\n }\n return start > 0 || end < values.length ? values.slice(start, end) : values;\n}\nconst arrayEvents = [\n 'push',\n 'pop',\n 'shift',\n 'splice',\n 'unshift'\n];\nfunction listenArrayEvents(array, listener) {\n if (array._chartjs) {\n array._chartjs.listeners.push(listener);\n return;\n }\n Object.defineProperty(array, '_chartjs', {\n configurable: true,\n enumerable: false,\n value: {\n listeners: [\n listener\n ]\n }\n });\n arrayEvents.forEach((key)=>{\n const method = '_onData' + _capitalize(key);\n const base = array[key];\n Object.defineProperty(array, key, {\n configurable: true,\n enumerable: false,\n value (...args) {\n const res = base.apply(this, args);\n array._chartjs.listeners.forEach((object)=>{\n if (typeof object[method] === 'function') {\n object[method](...args);\n }\n });\n return res;\n }\n });\n });\n}\nfunction unlistenArrayEvents(array, listener) {\n const stub = array._chartjs;\n if (!stub) {\n return;\n }\n const listeners = stub.listeners;\n const index = listeners.indexOf(listener);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n if (listeners.length > 0) {\n return;\n }\n arrayEvents.forEach((key)=>{\n delete array[key];\n });\n delete array._chartjs;\n}\n/**\n * @param items\n */ function _arrayUnique(items) {\n const set = new Set(items);\n if (set.size === items.length) {\n return items;\n }\n return Array.from(set);\n}\n\nfunction fontString(pixelSize, fontStyle, fontFamily) {\n return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;\n}\n/**\n* Request animation polyfill\n*/ const requestAnimFrame = function() {\n if (typeof window === 'undefined') {\n return function(callback) {\n return callback();\n };\n }\n return window.requestAnimationFrame;\n}();\n/**\n * Throttles calling `fn` once per animation frame\n * Latest arguments are used on the actual call\n */ function throttled(fn, thisArg) {\n let argsToUse = [];\n let ticking = false;\n return function(...args) {\n // Save the args for use later\n argsToUse = args;\n if (!ticking) {\n ticking = true;\n requestAnimFrame.call(window, ()=>{\n ticking = false;\n fn.apply(thisArg, argsToUse);\n });\n }\n };\n}\n/**\n * Debounces calling `fn` for `delay` ms\n */ function debounce(fn, delay) {\n let timeout;\n return function(...args) {\n if (delay) {\n clearTimeout(timeout);\n timeout = setTimeout(fn, delay, args);\n } else {\n fn.apply(this, args);\n }\n return delay;\n };\n}\n/**\n * Converts 'start' to 'left', 'end' to 'right' and others to 'center'\n * @private\n */ const _toLeftRightCenter = (align)=>align === 'start' ? 'left' : align === 'end' ? 'right' : 'center';\n/**\n * Returns `start`, `end` or `(start + end) / 2` depending on `align`. Defaults to `center`\n * @private\n */ const _alignStartEnd = (align, start, end)=>align === 'start' ? start : align === 'end' ? end : (start + end) / 2;\n/**\n * Returns `left`, `right` or `(left + right) / 2` depending on `align`. Defaults to `left`\n * @private\n */ const _textX = (align, left, right, rtl)=>{\n const check = rtl ? 'left' : 'right';\n return align === check ? right : align === 'center' ? (left + right) / 2 : left;\n};\n/**\n * Return start and count of visible points.\n * @private\n */ function _getStartAndCountOfVisiblePoints(meta, points, animationsDisabled) {\n const pointCount = points.length;\n let start = 0;\n let count = pointCount;\n if (meta._sorted) {\n const { iScale , vScale , _parsed } = meta;\n const spanGaps = meta.dataset ? meta.dataset.options ? meta.dataset.options.spanGaps : null : null;\n const axis = iScale.axis;\n const { min , max , minDefined , maxDefined } = iScale.getUserBounds();\n if (minDefined) {\n start = Math.min(// @ts-expect-error Need to type _parsed\n _lookupByKey(_parsed, axis, min).lo, // @ts-expect-error Need to fix types on _lookupByKey\n animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo);\n if (spanGaps) {\n const distanceToDefinedLo = _parsed.slice(0, start + 1).reverse().findIndex((point)=>!isNullOrUndef(point[vScale.axis]));\n start -= Math.max(0, distanceToDefinedLo);\n }\n start = _limitValue(start, 0, pointCount - 1);\n }\n if (maxDefined) {\n let end = Math.max(// @ts-expect-error Need to type _parsed\n _lookupByKey(_parsed, iScale.axis, max, true).hi + 1, // @ts-expect-error Need to fix types on _lookupByKey\n animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max), true).hi + 1);\n if (spanGaps) {\n const distanceToDefinedHi = _parsed.slice(end - 1).findIndex((point)=>!isNullOrUndef(point[vScale.axis]));\n end += Math.max(0, distanceToDefinedHi);\n }\n count = _limitValue(end, start, pointCount) - start;\n } else {\n count = pointCount - start;\n }\n }\n return {\n start,\n count\n };\n}\n/**\n * Checks if the scale ranges have changed.\n * @param {object} meta - dataset meta.\n * @returns {boolean}\n * @private\n */ function _scaleRangesChanged(meta) {\n const { xScale , yScale , _scaleRanges } = meta;\n const newRanges = {\n xmin: xScale.min,\n xmax: xScale.max,\n ymin: yScale.min,\n ymax: yScale.max\n };\n if (!_scaleRanges) {\n meta._scaleRanges = newRanges;\n return true;\n }\n const changed = _scaleRanges.xmin !== xScale.min || _scaleRanges.xmax !== xScale.max || _scaleRanges.ymin !== yScale.min || _scaleRanges.ymax !== yScale.max;\n Object.assign(_scaleRanges, newRanges);\n return changed;\n}\n\nconst atEdge = (t)=>t === 0 || t === 1;\nconst elasticIn = (t, s, p)=>-(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * TAU / p));\nconst elasticOut = (t, s, p)=>Math.pow(2, -10 * t) * Math.sin((t - s) * TAU / p) + 1;\n/**\n * Easing functions adapted from Robert Penner's easing equations.\n * @namespace Chart.helpers.easing.effects\n * @see http://www.robertpenner.com/easing/\n */ const effects = {\n linear: (t)=>t,\n easeInQuad: (t)=>t * t,\n easeOutQuad: (t)=>-t * (t - 2),\n easeInOutQuad: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t : -0.5 * (--t * (t - 2) - 1),\n easeInCubic: (t)=>t * t * t,\n easeOutCubic: (t)=>(t -= 1) * t * t + 1,\n easeInOutCubic: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t : 0.5 * ((t -= 2) * t * t + 2),\n easeInQuart: (t)=>t * t * t * t,\n easeOutQuart: (t)=>-((t -= 1) * t * t * t - 1),\n easeInOutQuart: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t : -0.5 * ((t -= 2) * t * t * t - 2),\n easeInQuint: (t)=>t * t * t * t * t,\n easeOutQuint: (t)=>(t -= 1) * t * t * t * t + 1,\n easeInOutQuint: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t * t : 0.5 * ((t -= 2) * t * t * t * t + 2),\n easeInSine: (t)=>-Math.cos(t * HALF_PI) + 1,\n easeOutSine: (t)=>Math.sin(t * HALF_PI),\n easeInOutSine: (t)=>-0.5 * (Math.cos(PI * t) - 1),\n easeInExpo: (t)=>t === 0 ? 0 : Math.pow(2, 10 * (t - 1)),\n easeOutExpo: (t)=>t === 1 ? 1 : -Math.pow(2, -10 * t) + 1,\n easeInOutExpo: (t)=>atEdge(t) ? t : t < 0.5 ? 0.5 * Math.pow(2, 10 * (t * 2 - 1)) : 0.5 * (-Math.pow(2, -10 * (t * 2 - 1)) + 2),\n easeInCirc: (t)=>t >= 1 ? t : -(Math.sqrt(1 - t * t) - 1),\n easeOutCirc: (t)=>Math.sqrt(1 - (t -= 1) * t),\n easeInOutCirc: (t)=>(t /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1),\n easeInElastic: (t)=>atEdge(t) ? t : elasticIn(t, 0.075, 0.3),\n easeOutElastic: (t)=>atEdge(t) ? t : elasticOut(t, 0.075, 0.3),\n easeInOutElastic (t) {\n const s = 0.1125;\n const p = 0.45;\n return atEdge(t) ? t : t < 0.5 ? 0.5 * elasticIn(t * 2, s, p) : 0.5 + 0.5 * elasticOut(t * 2 - 1, s, p);\n },\n easeInBack (t) {\n const s = 1.70158;\n return t * t * ((s + 1) * t - s);\n },\n easeOutBack (t) {\n const s = 1.70158;\n return (t -= 1) * t * ((s + 1) * t + s) + 1;\n },\n easeInOutBack (t) {\n let s = 1.70158;\n if ((t /= 0.5) < 1) {\n return 0.5 * (t * t * (((s *= 1.525) + 1) * t - s));\n }\n return 0.5 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);\n },\n easeInBounce: (t)=>1 - effects.easeOutBounce(1 - t),\n easeOutBounce (t) {\n const m = 7.5625;\n const d = 2.75;\n if (t < 1 / d) {\n return m * t * t;\n }\n if (t < 2 / d) {\n return m * (t -= 1.5 / d) * t + 0.75;\n }\n if (t < 2.5 / d) {\n return m * (t -= 2.25 / d) * t + 0.9375;\n }\n return m * (t -= 2.625 / d) * t + 0.984375;\n },\n easeInOutBounce: (t)=>t < 0.5 ? effects.easeInBounce(t * 2) * 0.5 : effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5\n};\n\nfunction isPatternOrGradient(value) {\n if (value && typeof value === 'object') {\n const type = value.toString();\n return type === '[object CanvasPattern]' || type === '[object CanvasGradient]';\n }\n return false;\n}\nfunction color(value) {\n return isPatternOrGradient(value) ? value : new _kurkle_color__WEBPACK_IMPORTED_MODULE_0__.Color(value);\n}\nfunction getHoverColor(value) {\n return isPatternOrGradient(value) ? value : new _kurkle_color__WEBPACK_IMPORTED_MODULE_0__.Color(value).saturate(0.5).darken(0.1).hexString();\n}\n\nconst numbers = [\n 'x',\n 'y',\n 'borderWidth',\n 'radius',\n 'tension'\n];\nconst colors = [\n 'color',\n 'borderColor',\n 'backgroundColor'\n];\nfunction applyAnimationsDefaults(defaults) {\n defaults.set('animation', {\n delay: undefined,\n duration: 1000,\n easing: 'easeOutQuart',\n fn: undefined,\n from: undefined,\n loop: undefined,\n to: undefined,\n type: undefined\n });\n defaults.describe('animation', {\n _fallback: false,\n _indexable: false,\n _scriptable: (name)=>name !== 'onProgress' && name !== 'onComplete' && name !== 'fn'\n });\n defaults.set('animations', {\n colors: {\n type: 'color',\n properties: colors\n },\n numbers: {\n type: 'number',\n properties: numbers\n }\n });\n defaults.describe('animations', {\n _fallback: 'animation'\n });\n defaults.set('transitions', {\n active: {\n animation: {\n duration: 400\n }\n },\n resize: {\n animation: {\n duration: 0\n }\n },\n show: {\n animations: {\n colors: {\n from: 'transparent'\n },\n visible: {\n type: 'boolean',\n duration: 0\n }\n }\n },\n hide: {\n animations: {\n colors: {\n to: 'transparent'\n },\n visible: {\n type: 'boolean',\n easing: 'linear',\n fn: (v)=>v | 0\n }\n }\n }\n });\n}\n\nfunction applyLayoutsDefaults(defaults) {\n defaults.set('layout', {\n autoPadding: true,\n padding: {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n }\n });\n}\n\nconst intlCache = new Map();\nfunction getNumberFormat(locale, options) {\n options = options || {};\n const cacheKey = locale + JSON.stringify(options);\n let formatter = intlCache.get(cacheKey);\n if (!formatter) {\n formatter = new Intl.NumberFormat(locale, options);\n intlCache.set(cacheKey, formatter);\n }\n return formatter;\n}\nfunction formatNumber(num, locale, options) {\n return getNumberFormat(locale, options).format(num);\n}\n\nconst formatters = {\n values (value) {\n return isArray(value) ? value : '' + value;\n },\n numeric (tickValue, index, ticks) {\n if (tickValue === 0) {\n return '0';\n }\n const locale = this.chart.options.locale;\n let notation;\n let delta = tickValue;\n if (ticks.length > 1) {\n const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));\n if (maxTick < 1e-4 || maxTick > 1e+15) {\n notation = 'scientific';\n }\n delta = calculateDelta(tickValue, ticks);\n }\n const logDelta = log10(Math.abs(delta));\n const numDecimal = isNaN(logDelta) ? 1 : Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0);\n const options = {\n notation,\n minimumFractionDigits: numDecimal,\n maximumFractionDigits: numDecimal\n };\n Object.assign(options, this.options.ticks.format);\n return formatNumber(tickValue, locale, options);\n },\n logarithmic (tickValue, index, ticks) {\n if (tickValue === 0) {\n return '0';\n }\n const remain = ticks[index].significand || tickValue / Math.pow(10, Math.floor(log10(tickValue)));\n if ([\n 1,\n 2,\n 3,\n 5,\n 10,\n 15\n ].includes(remain) || index > 0.8 * ticks.length) {\n return formatters.numeric.call(this, tickValue, index, ticks);\n }\n return '';\n }\n};\nfunction calculateDelta(tickValue, ticks) {\n let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;\n if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) {\n delta = tickValue - Math.floor(tickValue);\n }\n return delta;\n}\n var Ticks = {\n formatters\n};\n\nfunction applyScaleDefaults(defaults) {\n defaults.set('scale', {\n display: true,\n offset: false,\n reverse: false,\n beginAtZero: false,\n bounds: 'ticks',\n clip: true,\n grace: 0,\n grid: {\n display: true,\n lineWidth: 1,\n drawOnChartArea: true,\n drawTicks: true,\n tickLength: 8,\n tickWidth: (_ctx, options)=>options.lineWidth,\n tickColor: (_ctx, options)=>options.color,\n offset: false\n },\n border: {\n display: true,\n dash: [],\n dashOffset: 0.0,\n width: 1\n },\n title: {\n display: false,\n text: '',\n padding: {\n top: 4,\n bottom: 4\n }\n },\n ticks: {\n minRotation: 0,\n maxRotation: 50,\n mirror: false,\n textStrokeWidth: 0,\n textStrokeColor: '',\n padding: 3,\n display: true,\n autoSkip: true,\n autoSkipPadding: 3,\n labelOffset: 0,\n callback: Ticks.formatters.values,\n minor: {},\n major: {},\n align: 'center',\n crossAlign: 'near',\n showLabelBackdrop: false,\n backdropColor: 'rgba(255, 255, 255, 0.75)',\n backdropPadding: 2\n }\n });\n defaults.route('scale.ticks', 'color', '', 'color');\n defaults.route('scale.grid', 'color', '', 'borderColor');\n defaults.route('scale.border', 'color', '', 'borderColor');\n defaults.route('scale.title', 'color', '', 'color');\n defaults.describe('scale', {\n _fallback: false,\n _scriptable: (name)=>!name.startsWith('before') && !name.startsWith('after') && name !== 'callback' && name !== 'parser',\n _indexable: (name)=>name !== 'borderDash' && name !== 'tickBorderDash' && name !== 'dash'\n });\n defaults.describe('scales', {\n _fallback: 'scale'\n });\n defaults.describe('scale.ticks', {\n _scriptable: (name)=>name !== 'backdropPadding' && name !== 'callback',\n _indexable: (name)=>name !== 'backdropPadding'\n });\n}\n\nconst overrides = Object.create(null);\nconst descriptors = Object.create(null);\n function getScope$1(node, key) {\n if (!key) {\n return node;\n }\n const keys = key.split('.');\n for(let i = 0, n = keys.length; i < n; ++i){\n const k = keys[i];\n node = node[k] || (node[k] = Object.create(null));\n }\n return node;\n}\nfunction set(root, scope, values) {\n if (typeof scope === 'string') {\n return merge(getScope$1(root, scope), values);\n }\n return merge(getScope$1(root, ''), scope);\n}\n class Defaults {\n constructor(_descriptors, _appliers){\n this.animation = undefined;\n this.backgroundColor = 'rgba(0,0,0,0.1)';\n this.borderColor = 'rgba(0,0,0,0.1)';\n this.color = '#666';\n this.datasets = {};\n this.devicePixelRatio = (context)=>context.chart.platform.getDevicePixelRatio();\n this.elements = {};\n this.events = [\n 'mousemove',\n 'mouseout',\n 'click',\n 'touchstart',\n 'touchmove'\n ];\n this.font = {\n family: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n size: 12,\n style: 'normal',\n lineHeight: 1.2,\n weight: null\n };\n this.hover = {};\n this.hoverBackgroundColor = (ctx, options)=>getHoverColor(options.backgroundColor);\n this.hoverBorderColor = (ctx, options)=>getHoverColor(options.borderColor);\n this.hoverColor = (ctx, options)=>getHoverColor(options.color);\n this.indexAxis = 'x';\n this.interaction = {\n mode: 'nearest',\n intersect: true,\n includeInvisible: false\n };\n this.maintainAspectRatio = true;\n this.onHover = null;\n this.onClick = null;\n this.parsing = true;\n this.plugins = {};\n this.responsive = true;\n this.scale = undefined;\n this.scales = {};\n this.showLine = true;\n this.drawActiveElementsOnTop = true;\n this.describe(_descriptors);\n this.apply(_appliers);\n }\n set(scope, values) {\n return set(this, scope, values);\n }\n get(scope) {\n return getScope$1(this, scope);\n }\n describe(scope, values) {\n return set(descriptors, scope, values);\n }\n override(scope, values) {\n return set(overrides, scope, values);\n }\n route(scope, name, targetScope, targetName) {\n const scopeObject = getScope$1(this, scope);\n const targetScopeObject = getScope$1(this, targetScope);\n const privateName = '_' + name;\n Object.defineProperties(scopeObject, {\n [privateName]: {\n value: scopeObject[name],\n writable: true\n },\n [name]: {\n enumerable: true,\n get () {\n const local = this[privateName];\n const target = targetScopeObject[targetName];\n if (isObject(local)) {\n return Object.assign({}, target, local);\n }\n return valueOrDefault(local, target);\n },\n set (value) {\n this[privateName] = value;\n }\n }\n });\n }\n apply(appliers) {\n appliers.forEach((apply)=>apply(this));\n }\n}\nvar defaults = /* #__PURE__ */ new Defaults({\n _scriptable: (name)=>!name.startsWith('on'),\n _indexable: (name)=>name !== 'events',\n hover: {\n _fallback: 'interaction'\n },\n interaction: {\n _scriptable: false,\n _indexable: false\n }\n}, [\n applyAnimationsDefaults,\n applyLayoutsDefaults,\n applyScaleDefaults\n]);\n\n/**\n * Converts the given font object into a CSS font string.\n * @param font - A font object.\n * @return The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font\n * @private\n */ function toFontString(font) {\n if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) {\n return null;\n }\n return (font.style ? font.style + ' ' : '') + (font.weight ? font.weight + ' ' : '') + font.size + 'px ' + font.family;\n}\n/**\n * @private\n */ function _measureText(ctx, data, gc, longest, string) {\n let textWidth = data[string];\n if (!textWidth) {\n textWidth = data[string] = ctx.measureText(string).width;\n gc.push(string);\n }\n if (textWidth > longest) {\n longest = textWidth;\n }\n return longest;\n}\n/**\n * @private\n */ // eslint-disable-next-line complexity\nfunction _longestText(ctx, font, arrayOfThings, cache) {\n cache = cache || {};\n let data = cache.data = cache.data || {};\n let gc = cache.garbageCollect = cache.garbageCollect || [];\n if (cache.font !== font) {\n data = cache.data = {};\n gc = cache.garbageCollect = [];\n cache.font = font;\n }\n ctx.save();\n ctx.font = font;\n let longest = 0;\n const ilen = arrayOfThings.length;\n let i, j, jlen, thing, nestedThing;\n for(i = 0; i < ilen; i++){\n thing = arrayOfThings[i];\n // Undefined strings and arrays should not be measured\n if (thing !== undefined && thing !== null && !isArray(thing)) {\n longest = _measureText(ctx, data, gc, longest, thing);\n } else if (isArray(thing)) {\n // if it is an array lets measure each element\n // to do maybe simplify this function a bit so we can do this more recursively?\n for(j = 0, jlen = thing.length; j < jlen; j++){\n nestedThing = thing[j];\n // Undefined strings and arrays should not be measured\n if (nestedThing !== undefined && nestedThing !== null && !isArray(nestedThing)) {\n longest = _measureText(ctx, data, gc, longest, nestedThing);\n }\n }\n }\n }\n ctx.restore();\n const gcLen = gc.length / 2;\n if (gcLen > arrayOfThings.length) {\n for(i = 0; i < gcLen; i++){\n delete data[gc[i]];\n }\n gc.splice(0, gcLen);\n }\n return longest;\n}\n/**\n * Returns the aligned pixel value to avoid anti-aliasing blur\n * @param chart - The chart instance.\n * @param pixel - A pixel value.\n * @param width - The width of the element.\n * @returns The aligned pixel value.\n * @private\n */ function _alignPixel(chart, pixel, width) {\n const devicePixelRatio = chart.currentDevicePixelRatio;\n const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0;\n return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth;\n}\n/**\n * Clears the entire canvas.\n */ function clearCanvas(canvas, ctx) {\n if (!ctx && !canvas) {\n return;\n }\n ctx = ctx || canvas.getContext('2d');\n ctx.save();\n // canvas.width and canvas.height do not consider the canvas transform,\n // while clearRect does\n ctx.resetTransform();\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.restore();\n}\nfunction drawPoint(ctx, options, x, y) {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n drawPointLegend(ctx, options, x, y, null);\n}\n// eslint-disable-next-line complexity\nfunction drawPointLegend(ctx, options, x, y, w) {\n let type, xOffset, yOffset, size, cornerRadius, width, xOffsetW, yOffsetW;\n const style = options.pointStyle;\n const rotation = options.rotation;\n const radius = options.radius;\n let rad = (rotation || 0) * RAD_PER_DEG;\n if (style && typeof style === 'object') {\n type = style.toString();\n if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {\n ctx.save();\n ctx.translate(x, y);\n ctx.rotate(rad);\n ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);\n ctx.restore();\n return;\n }\n }\n if (isNaN(radius) || radius <= 0) {\n return;\n }\n ctx.beginPath();\n switch(style){\n // Default includes circle\n default:\n if (w) {\n ctx.ellipse(x, y, w / 2, radius, 0, 0, TAU);\n } else {\n ctx.arc(x, y, radius, 0, TAU);\n }\n ctx.closePath();\n break;\n case 'triangle':\n width = w ? w / 2 : radius;\n ctx.moveTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);\n rad += TWO_THIRDS_PI;\n ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);\n rad += TWO_THIRDS_PI;\n ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);\n ctx.closePath();\n break;\n case 'rectRounded':\n // NOTE: the rounded rect implementation changed to use `arc` instead of\n // `quadraticCurveTo` since it generates better results when rect is\n // almost a circle. 0.516 (instead of 0.5) produces results with visually\n // closer proportion to the previous impl and it is inscribed in the\n // circle with `radius`. For more details, see the following PRs:\n // https://github.com/chartjs/Chart.js/issues/5597\n // https://github.com/chartjs/Chart.js/issues/5858\n cornerRadius = radius * 0.516;\n size = radius - cornerRadius;\n xOffset = Math.cos(rad + QUARTER_PI) * size;\n xOffsetW = Math.cos(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);\n yOffset = Math.sin(rad + QUARTER_PI) * size;\n yOffsetW = Math.sin(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);\n ctx.arc(x - xOffsetW, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);\n ctx.arc(x + yOffsetW, y - xOffset, cornerRadius, rad - HALF_PI, rad);\n ctx.arc(x + xOffsetW, y + yOffset, cornerRadius, rad, rad + HALF_PI);\n ctx.arc(x - yOffsetW, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);\n ctx.closePath();\n break;\n case 'rect':\n if (!rotation) {\n size = Math.SQRT1_2 * radius;\n width = w ? w / 2 : size;\n ctx.rect(x - width, y - size, 2 * width, 2 * size);\n break;\n }\n rad += QUARTER_PI;\n /* falls through */ case 'rectRot':\n xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n ctx.moveTo(x - xOffsetW, y - yOffset);\n ctx.lineTo(x + yOffsetW, y - xOffset);\n ctx.lineTo(x + xOffsetW, y + yOffset);\n ctx.lineTo(x - yOffsetW, y + xOffset);\n ctx.closePath();\n break;\n case 'crossRot':\n rad += QUARTER_PI;\n /* falls through */ case 'cross':\n xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n ctx.moveTo(x - xOffsetW, y - yOffset);\n ctx.lineTo(x + xOffsetW, y + yOffset);\n ctx.moveTo(x + yOffsetW, y - xOffset);\n ctx.lineTo(x - yOffsetW, y + xOffset);\n break;\n case 'star':\n xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n ctx.moveTo(x - xOffsetW, y - yOffset);\n ctx.lineTo(x + xOffsetW, y + yOffset);\n ctx.moveTo(x + yOffsetW, y - xOffset);\n ctx.lineTo(x - yOffsetW, y + xOffset);\n rad += QUARTER_PI;\n xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n ctx.moveTo(x - xOffsetW, y - yOffset);\n ctx.lineTo(x + xOffsetW, y + yOffset);\n ctx.moveTo(x + yOffsetW, y - xOffset);\n ctx.lineTo(x - yOffsetW, y + xOffset);\n break;\n case 'line':\n xOffset = w ? w / 2 : Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n ctx.moveTo(x - xOffset, y - yOffset);\n ctx.lineTo(x + xOffset, y + yOffset);\n break;\n case 'dash':\n ctx.moveTo(x, y);\n ctx.lineTo(x + Math.cos(rad) * (w ? w / 2 : radius), y + Math.sin(rad) * radius);\n break;\n case false:\n ctx.closePath();\n break;\n }\n ctx.fill();\n if (options.borderWidth > 0) {\n ctx.stroke();\n }\n}\n/**\n * Returns true if the point is inside the rectangle\n * @param point - The point to test\n * @param area - The rectangle\n * @param margin - allowed margin\n * @private\n */ function _isPointInArea(point, area, margin) {\n margin = margin || 0.5; // margin - default is to match rounded decimals\n return !area || point && point.x > area.left - margin && point.x < area.right + margin && point.y > area.top - margin && point.y < area.bottom + margin;\n}\nfunction clipArea(ctx, area) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);\n ctx.clip();\n}\nfunction unclipArea(ctx) {\n ctx.restore();\n}\n/**\n * @private\n */ function _steppedLineTo(ctx, previous, target, flip, mode) {\n if (!previous) {\n return ctx.lineTo(target.x, target.y);\n }\n if (mode === 'middle') {\n const midpoint = (previous.x + target.x) / 2.0;\n ctx.lineTo(midpoint, previous.y);\n ctx.lineTo(midpoint, target.y);\n } else if (mode === 'after' !== !!flip) {\n ctx.lineTo(previous.x, target.y);\n } else {\n ctx.lineTo(target.x, previous.y);\n }\n ctx.lineTo(target.x, target.y);\n}\n/**\n * @private\n */ function _bezierCurveTo(ctx, previous, target, flip) {\n if (!previous) {\n return ctx.lineTo(target.x, target.y);\n }\n ctx.bezierCurveTo(flip ? previous.cp1x : previous.cp2x, flip ? previous.cp1y : previous.cp2y, flip ? target.cp2x : target.cp1x, flip ? target.cp2y : target.cp1y, target.x, target.y);\n}\nfunction setRenderOpts(ctx, opts) {\n if (opts.translation) {\n ctx.translate(opts.translation[0], opts.translation[1]);\n }\n if (!isNullOrUndef(opts.rotation)) {\n ctx.rotate(opts.rotation);\n }\n if (opts.color) {\n ctx.fillStyle = opts.color;\n }\n if (opts.textAlign) {\n ctx.textAlign = opts.textAlign;\n }\n if (opts.textBaseline) {\n ctx.textBaseline = opts.textBaseline;\n }\n}\nfunction decorateText(ctx, x, y, line, opts) {\n if (opts.strikethrough || opts.underline) {\n /**\n * Now that IE11 support has been dropped, we can use more\n * of the TextMetrics object. The actual bounding boxes\n * are unflagged in Chrome, Firefox, Edge, and Safari so they\n * can be safely used.\n * See https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics#Browser_compatibility\n */ const metrics = ctx.measureText(line);\n const left = x - metrics.actualBoundingBoxLeft;\n const right = x + metrics.actualBoundingBoxRight;\n const top = y - metrics.actualBoundingBoxAscent;\n const bottom = y + metrics.actualBoundingBoxDescent;\n const yDecoration = opts.strikethrough ? (top + bottom) / 2 : bottom;\n ctx.strokeStyle = ctx.fillStyle;\n ctx.beginPath();\n ctx.lineWidth = opts.decorationWidth || 2;\n ctx.moveTo(left, yDecoration);\n ctx.lineTo(right, yDecoration);\n ctx.stroke();\n }\n}\nfunction drawBackdrop(ctx, opts) {\n const oldColor = ctx.fillStyle;\n ctx.fillStyle = opts.color;\n ctx.fillRect(opts.left, opts.top, opts.width, opts.height);\n ctx.fillStyle = oldColor;\n}\n/**\n * Render text onto the canvas\n */ function renderText(ctx, text, x, y, font, opts = {}) {\n const lines = isArray(text) ? text : [\n text\n ];\n const stroke = opts.strokeWidth > 0 && opts.strokeColor !== '';\n let i, line;\n ctx.save();\n ctx.font = font.string;\n setRenderOpts(ctx, opts);\n for(i = 0; i < lines.length; ++i){\n line = lines[i];\n if (opts.backdrop) {\n drawBackdrop(ctx, opts.backdrop);\n }\n if (stroke) {\n if (opts.strokeColor) {\n ctx.strokeStyle = opts.strokeColor;\n }\n if (!isNullOrUndef(opts.strokeWidth)) {\n ctx.lineWidth = opts.strokeWidth;\n }\n ctx.strokeText(line, x, y, opts.maxWidth);\n }\n ctx.fillText(line, x, y, opts.maxWidth);\n decorateText(ctx, x, y, line, opts);\n y += Number(font.lineHeight);\n }\n ctx.restore();\n}\n/**\n * Add a path of a rectangle with rounded corners to the current sub-path\n * @param ctx - Context\n * @param rect - Bounding rect\n */ function addRoundedRectPath(ctx, rect) {\n const { x , y , w , h , radius } = rect;\n // top left arc\n ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, 1.5 * PI, PI, true);\n // line from top left to bottom left\n ctx.lineTo(x, y + h - radius.bottomLeft);\n // bottom left arc\n ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true);\n // line from bottom left to bottom right\n ctx.lineTo(x + w - radius.bottomRight, y + h);\n // bottom right arc\n ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true);\n // line from bottom right to top right\n ctx.lineTo(x + w, y + radius.topRight);\n // top right arc\n ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true);\n // line from top right to top left\n ctx.lineTo(x + radius.topLeft, y);\n}\n\nconst LINE_HEIGHT = /^(normal|(\\d+(?:\\.\\d+)?)(px|em|%)?)$/;\nconst FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;\n/**\n * @alias Chart.helpers.options\n * @namespace\n */ /**\n * Converts the given line height `value` in pixels for a specific font `size`.\n * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').\n * @param size - The font size (in pixels) used to resolve relative `value`.\n * @returns The effective line height in pixels (size * 1.2 if value is invalid).\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\n * @since 2.7.0\n */ function toLineHeight(value, size) {\n const matches = ('' + value).match(LINE_HEIGHT);\n if (!matches || matches[1] === 'normal') {\n return size * 1.2;\n }\n value = +matches[2];\n switch(matches[3]){\n case 'px':\n return value;\n case '%':\n value /= 100;\n break;\n }\n return size * value;\n}\nconst numberOrZero = (v)=>+v || 0;\nfunction _readValueToProps(value, props) {\n const ret = {};\n const objProps = isObject(props);\n const keys = objProps ? Object.keys(props) : props;\n const read = isObject(value) ? objProps ? (prop)=>valueOrDefault(value[prop], value[props[prop]]) : (prop)=>value[prop] : ()=>value;\n for (const prop of keys){\n ret[prop] = numberOrZero(read(prop));\n }\n return ret;\n}\n/**\n * Converts the given value into a TRBL object.\n * @param value - If a number, set the value to all TRBL component,\n * else, if an object, use defined properties and sets undefined ones to 0.\n * x / y are shorthands for same value for left/right and top/bottom.\n * @returns The padding values (top, right, bottom, left)\n * @since 3.0.0\n */ function toTRBL(value) {\n return _readValueToProps(value, {\n top: 'y',\n right: 'x',\n bottom: 'y',\n left: 'x'\n });\n}\n/**\n * Converts the given value into a TRBL corners object (similar with css border-radius).\n * @param value - If a number, set the value to all TRBL corner components,\n * else, if an object, use defined properties and sets undefined ones to 0.\n * @returns The TRBL corner values (topLeft, topRight, bottomLeft, bottomRight)\n * @since 3.0.0\n */ function toTRBLCorners(value) {\n return _readValueToProps(value, [\n 'topLeft',\n 'topRight',\n 'bottomLeft',\n 'bottomRight'\n ]);\n}\n/**\n * Converts the given value into a padding object with pre-computed width/height.\n * @param value - If a number, set the value to all TRBL component,\n * else, if an object, use defined properties and sets undefined ones to 0.\n * x / y are shorthands for same value for left/right and top/bottom.\n * @returns The padding values (top, right, bottom, left, width, height)\n * @since 2.7.0\n */ function toPadding(value) {\n const obj = toTRBL(value);\n obj.width = obj.left + obj.right;\n obj.height = obj.top + obj.bottom;\n return obj;\n}\n/**\n * Parses font options and returns the font object.\n * @param options - A object that contains font options to be parsed.\n * @param fallback - A object that contains fallback font options.\n * @return The font object.\n * @private\n */ function toFont(options, fallback) {\n options = options || {};\n fallback = fallback || defaults.font;\n let size = valueOrDefault(options.size, fallback.size);\n if (typeof size === 'string') {\n size = parseInt(size, 10);\n }\n let style = valueOrDefault(options.style, fallback.style);\n if (style && !('' + style).match(FONT_STYLE)) {\n console.warn('Invalid font style specified: \"' + style + '\"');\n style = undefined;\n }\n const font = {\n family: valueOrDefault(options.family, fallback.family),\n lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size),\n size,\n style,\n weight: valueOrDefault(options.weight, fallback.weight),\n string: ''\n };\n font.string = toFontString(font);\n return font;\n}\n/**\n * Evaluates the given `inputs` sequentially and returns the first defined value.\n * @param inputs - An array of values, falling back to the last value.\n * @param context - If defined and the current value is a function, the value\n * is called with `context` as first argument and the result becomes the new input.\n * @param index - If defined and the current value is an array, the value\n * at `index` become the new input.\n * @param info - object to return information about resolution in\n * @param info.cacheable - Will be set to `false` if option is not cacheable.\n * @since 2.7.0\n */ function resolve(inputs, context, index, info) {\n let cacheable = true;\n let i, ilen, value;\n for(i = 0, ilen = inputs.length; i < ilen; ++i){\n value = inputs[i];\n if (value === undefined) {\n continue;\n }\n if (context !== undefined && typeof value === 'function') {\n value = value(context);\n cacheable = false;\n }\n if (index !== undefined && isArray(value)) {\n value = value[index % value.length];\n cacheable = false;\n }\n if (value !== undefined) {\n if (info && !cacheable) {\n info.cacheable = false;\n }\n return value;\n }\n }\n}\n/**\n * @param minmax\n * @param grace\n * @param beginAtZero\n * @private\n */ function _addGrace(minmax, grace, beginAtZero) {\n const { min , max } = minmax;\n const change = toDimension(grace, (max - min) / 2);\n const keepZero = (value, add)=>beginAtZero && value === 0 ? 0 : value + add;\n return {\n min: keepZero(min, -Math.abs(change)),\n max: keepZero(max, change)\n };\n}\nfunction createContext(parentContext, context) {\n return Object.assign(Object.create(parentContext), context);\n}\n\n/**\n * Creates a Proxy for resolving raw values for options.\n * @param scopes - The option scopes to look for values, in resolution order\n * @param prefixes - The prefixes for values, in resolution order.\n * @param rootScopes - The root option scopes\n * @param fallback - Parent scopes fallback\n * @param getTarget - callback for getting the target for changed values\n * @returns Proxy\n * @private\n */ function _createResolver(scopes, prefixes = [\n ''\n], rootScopes, fallback, getTarget = ()=>scopes[0]) {\n const finalRootScopes = rootScopes || scopes;\n if (typeof fallback === 'undefined') {\n fallback = _resolve('_fallback', scopes);\n }\n const cache = {\n [Symbol.toStringTag]: 'Object',\n _cacheable: true,\n _scopes: scopes,\n _rootScopes: finalRootScopes,\n _fallback: fallback,\n _getTarget: getTarget,\n override: (scope)=>_createResolver([\n scope,\n ...scopes\n ], prefixes, finalRootScopes, fallback)\n };\n return new Proxy(cache, {\n /**\n * A trap for the delete operator.\n */ deleteProperty (target, prop) {\n delete target[prop]; // remove from cache\n delete target._keys; // remove cached keys\n delete scopes[0][prop]; // remove from top level scope\n return true;\n },\n /**\n * A trap for getting property values.\n */ get (target, prop) {\n return _cached(target, prop, ()=>_resolveWithPrefixes(prop, prefixes, scopes, target));\n },\n /**\n * A trap for Object.getOwnPropertyDescriptor.\n * Also used by Object.hasOwnProperty.\n */ getOwnPropertyDescriptor (target, prop) {\n return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop);\n },\n /**\n * A trap for Object.getPrototypeOf.\n */ getPrototypeOf () {\n return Reflect.getPrototypeOf(scopes[0]);\n },\n /**\n * A trap for the in operator.\n */ has (target, prop) {\n return getKeysFromAllScopes(target).includes(prop);\n },\n /**\n * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.\n */ ownKeys (target) {\n return getKeysFromAllScopes(target);\n },\n /**\n * A trap for setting property values.\n */ set (target, prop, value) {\n const storage = target._storage || (target._storage = getTarget());\n target[prop] = storage[prop] = value; // set to top level scope + cache\n delete target._keys; // remove cached keys\n return true;\n }\n });\n}\n/**\n * Returns an Proxy for resolving option values with context.\n * @param proxy - The Proxy returned by `_createResolver`\n * @param context - Context object for scriptable/indexable options\n * @param subProxy - The proxy provided for scriptable options\n * @param descriptorDefaults - Defaults for descriptors\n * @private\n */ function _attachContext(proxy, context, subProxy, descriptorDefaults) {\n const cache = {\n _cacheable: false,\n _proxy: proxy,\n _context: context,\n _subProxy: subProxy,\n _stack: new Set(),\n _descriptors: _descriptors(proxy, descriptorDefaults),\n setContext: (ctx)=>_attachContext(proxy, ctx, subProxy, descriptorDefaults),\n override: (scope)=>_attachContext(proxy.override(scope), context, subProxy, descriptorDefaults)\n };\n return new Proxy(cache, {\n /**\n * A trap for the delete operator.\n */ deleteProperty (target, prop) {\n delete target[prop]; // remove from cache\n delete proxy[prop]; // remove from proxy\n return true;\n },\n /**\n * A trap for getting property values.\n */ get (target, prop, receiver) {\n return _cached(target, prop, ()=>_resolveWithContext(target, prop, receiver));\n },\n /**\n * A trap for Object.getOwnPropertyDescriptor.\n * Also used by Object.hasOwnProperty.\n */ getOwnPropertyDescriptor (target, prop) {\n return target._descriptors.allKeys ? Reflect.has(proxy, prop) ? {\n enumerable: true,\n configurable: true\n } : undefined : Reflect.getOwnPropertyDescriptor(proxy, prop);\n },\n /**\n * A trap for Object.getPrototypeOf.\n */ getPrototypeOf () {\n return Reflect.getPrototypeOf(proxy);\n },\n /**\n * A trap for the in operator.\n */ has (target, prop) {\n return Reflect.has(proxy, prop);\n },\n /**\n * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.\n */ ownKeys () {\n return Reflect.ownKeys(proxy);\n },\n /**\n * A trap for setting property values.\n */ set (target, prop, value) {\n proxy[prop] = value; // set to proxy\n delete target[prop]; // remove from cache\n return true;\n }\n });\n}\n/**\n * @private\n */ function _descriptors(proxy, defaults = {\n scriptable: true,\n indexable: true\n}) {\n const { _scriptable =defaults.scriptable , _indexable =defaults.indexable , _allKeys =defaults.allKeys } = proxy;\n return {\n allKeys: _allKeys,\n scriptable: _scriptable,\n indexable: _indexable,\n isScriptable: isFunction(_scriptable) ? _scriptable : ()=>_scriptable,\n isIndexable: isFunction(_indexable) ? _indexable : ()=>_indexable\n };\n}\nconst readKey = (prefix, name)=>prefix ? prefix + _capitalize(name) : name;\nconst needsSubResolver = (prop, value)=>isObject(value) && prop !== 'adapters' && (Object.getPrototypeOf(value) === null || value.constructor === Object);\nfunction _cached(target, prop, resolve) {\n if (Object.prototype.hasOwnProperty.call(target, prop) || prop === 'constructor') {\n return target[prop];\n }\n const value = resolve();\n // cache the resolved value\n target[prop] = value;\n return value;\n}\nfunction _resolveWithContext(target, prop, receiver) {\n const { _proxy , _context , _subProxy , _descriptors: descriptors } = target;\n let value = _proxy[prop]; // resolve from proxy\n // resolve with context\n if (isFunction(value) && descriptors.isScriptable(prop)) {\n value = _resolveScriptable(prop, value, target, receiver);\n }\n if (isArray(value) && value.length) {\n value = _resolveArray(prop, value, target, descriptors.isIndexable);\n }\n if (needsSubResolver(prop, value)) {\n // if the resolved value is an object, create a sub resolver for it\n value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors);\n }\n return value;\n}\nfunction _resolveScriptable(prop, getValue, target, receiver) {\n const { _proxy , _context , _subProxy , _stack } = target;\n if (_stack.has(prop)) {\n throw new Error('Recursion detected: ' + Array.from(_stack).join('->') + '->' + prop);\n }\n _stack.add(prop);\n let value = getValue(_context, _subProxy || receiver);\n _stack.delete(prop);\n if (needsSubResolver(prop, value)) {\n // When scriptable option returns an object, create a resolver on that.\n value = createSubResolver(_proxy._scopes, _proxy, prop, value);\n }\n return value;\n}\nfunction _resolveArray(prop, value, target, isIndexable) {\n const { _proxy , _context , _subProxy , _descriptors: descriptors } = target;\n if (typeof _context.index !== 'undefined' && isIndexable(prop)) {\n return value[_context.index % value.length];\n } else if (isObject(value[0])) {\n // Array of objects, return array or resolvers\n const arr = value;\n const scopes = _proxy._scopes.filter((s)=>s !== arr);\n value = [];\n for (const item of arr){\n const resolver = createSubResolver(scopes, _proxy, prop, item);\n value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors));\n }\n }\n return value;\n}\nfunction resolveFallback(fallback, prop, value) {\n return isFunction(fallback) ? fallback(prop, value) : fallback;\n}\nconst getScope = (key, parent)=>key === true ? parent : typeof key === 'string' ? resolveObjectKey(parent, key) : undefined;\nfunction addScopes(set, parentScopes, key, parentFallback, value) {\n for (const parent of parentScopes){\n const scope = getScope(key, parent);\n if (scope) {\n set.add(scope);\n const fallback = resolveFallback(scope._fallback, key, value);\n if (typeof fallback !== 'undefined' && fallback !== key && fallback !== parentFallback) {\n // When we reach the descriptor that defines a new _fallback, return that.\n // The fallback will resume to that new scope.\n return fallback;\n }\n } else if (scope === false && typeof parentFallback !== 'undefined' && key !== parentFallback) {\n // Fallback to `false` results to `false`, when falling back to different key.\n // For example `interaction` from `hover` or `plugins.tooltip` and `animation` from `animations`\n return null;\n }\n }\n return false;\n}\nfunction createSubResolver(parentScopes, resolver, prop, value) {\n const rootScopes = resolver._rootScopes;\n const fallback = resolveFallback(resolver._fallback, prop, value);\n const allScopes = [\n ...parentScopes,\n ...rootScopes\n ];\n const set = new Set();\n set.add(value);\n let key = addScopesFromKey(set, allScopes, prop, fallback || prop, value);\n if (key === null) {\n return false;\n }\n if (typeof fallback !== 'undefined' && fallback !== prop) {\n key = addScopesFromKey(set, allScopes, fallback, key, value);\n if (key === null) {\n return false;\n }\n }\n return _createResolver(Array.from(set), [\n ''\n ], rootScopes, fallback, ()=>subGetTarget(resolver, prop, value));\n}\nfunction addScopesFromKey(set, allScopes, key, fallback, item) {\n while(key){\n key = addScopes(set, allScopes, key, fallback, item);\n }\n return key;\n}\nfunction subGetTarget(resolver, prop, value) {\n const parent = resolver._getTarget();\n if (!(prop in parent)) {\n parent[prop] = {};\n }\n const target = parent[prop];\n if (isArray(target) && isObject(value)) {\n // For array of objects, the object is used to store updated values\n return value;\n }\n return target || {};\n}\nfunction _resolveWithPrefixes(prop, prefixes, scopes, proxy) {\n let value;\n for (const prefix of prefixes){\n value = _resolve(readKey(prefix, prop), scopes);\n if (typeof value !== 'undefined') {\n return needsSubResolver(prop, value) ? createSubResolver(scopes, proxy, prop, value) : value;\n }\n }\n}\nfunction _resolve(key, scopes) {\n for (const scope of scopes){\n if (!scope) {\n continue;\n }\n const value = scope[key];\n if (typeof value !== 'undefined') {\n return value;\n }\n }\n}\nfunction getKeysFromAllScopes(target) {\n let keys = target._keys;\n if (!keys) {\n keys = target._keys = resolveKeysFromAllScopes(target._scopes);\n }\n return keys;\n}\nfunction resolveKeysFromAllScopes(scopes) {\n const set = new Set();\n for (const scope of scopes){\n for (const key of Object.keys(scope).filter((k)=>!k.startsWith('_'))){\n set.add(key);\n }\n }\n return Array.from(set);\n}\nfunction _parseObjectDataRadialScale(meta, data, start, count) {\n const { iScale } = meta;\n const { key ='r' } = this._parsing;\n const parsed = new Array(count);\n let i, ilen, index, item;\n for(i = 0, ilen = count; i < ilen; ++i){\n index = i + start;\n item = data[index];\n parsed[i] = {\n r: iScale.parse(resolveObjectKey(item, key), index)\n };\n }\n return parsed;\n}\n\nconst EPSILON = Number.EPSILON || 1e-14;\nconst getPoint = (points, i)=>i < points.length && !points[i].skip && points[i];\nconst getValueAxis = (indexAxis)=>indexAxis === 'x' ? 'y' : 'x';\nfunction splineCurve(firstPoint, middlePoint, afterPoint, t) {\n // Props to Rob Spencer at scaled innovation for his post on splining between points\n // http://scaledinnovation.com/analytics/splines/aboutSplines.html\n // This function must also respect \"skipped\" points\n const previous = firstPoint.skip ? middlePoint : firstPoint;\n const current = middlePoint;\n const next = afterPoint.skip ? middlePoint : afterPoint;\n const d01 = distanceBetweenPoints(current, previous);\n const d12 = distanceBetweenPoints(next, current);\n let s01 = d01 / (d01 + d12);\n let s12 = d12 / (d01 + d12);\n // If all points are the same, s01 & s02 will be inf\n s01 = isNaN(s01) ? 0 : s01;\n s12 = isNaN(s12) ? 0 : s12;\n const fa = t * s01; // scaling factor for triangle Ta\n const fb = t * s12;\n return {\n previous: {\n x: current.x - fa * (next.x - previous.x),\n y: current.y - fa * (next.y - previous.y)\n },\n next: {\n x: current.x + fb * (next.x - previous.x),\n y: current.y + fb * (next.y - previous.y)\n }\n };\n}\n/**\n * Adjust tangents to ensure monotonic properties\n */ function monotoneAdjust(points, deltaK, mK) {\n const pointsLen = points.length;\n let alphaK, betaK, tauK, squaredMagnitude, pointCurrent;\n let pointAfter = getPoint(points, 0);\n for(let i = 0; i < pointsLen - 1; ++i){\n pointCurrent = pointAfter;\n pointAfter = getPoint(points, i + 1);\n if (!pointCurrent || !pointAfter) {\n continue;\n }\n if (almostEquals(deltaK[i], 0, EPSILON)) {\n mK[i] = mK[i + 1] = 0;\n continue;\n }\n alphaK = mK[i] / deltaK[i];\n betaK = mK[i + 1] / deltaK[i];\n squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);\n if (squaredMagnitude <= 9) {\n continue;\n }\n tauK = 3 / Math.sqrt(squaredMagnitude);\n mK[i] = alphaK * tauK * deltaK[i];\n mK[i + 1] = betaK * tauK * deltaK[i];\n }\n}\nfunction monotoneCompute(points, mK, indexAxis = 'x') {\n const valueAxis = getValueAxis(indexAxis);\n const pointsLen = points.length;\n let delta, pointBefore, pointCurrent;\n let pointAfter = getPoint(points, 0);\n for(let i = 0; i < pointsLen; ++i){\n pointBefore = pointCurrent;\n pointCurrent = pointAfter;\n pointAfter = getPoint(points, i + 1);\n if (!pointCurrent) {\n continue;\n }\n const iPixel = pointCurrent[indexAxis];\n const vPixel = pointCurrent[valueAxis];\n if (pointBefore) {\n delta = (iPixel - pointBefore[indexAxis]) / 3;\n pointCurrent[`cp1${indexAxis}`] = iPixel - delta;\n pointCurrent[`cp1${valueAxis}`] = vPixel - delta * mK[i];\n }\n if (pointAfter) {\n delta = (pointAfter[indexAxis] - iPixel) / 3;\n pointCurrent[`cp2${indexAxis}`] = iPixel + delta;\n pointCurrent[`cp2${valueAxis}`] = vPixel + delta * mK[i];\n }\n }\n}\n/**\n * This function calculates Bézier control points in a similar way than |splineCurve|,\n * but preserves monotonicity of the provided data and ensures no local extremums are added\n * between the dataset discrete points due to the interpolation.\n * See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation\n */ function splineCurveMonotone(points, indexAxis = 'x') {\n const valueAxis = getValueAxis(indexAxis);\n const pointsLen = points.length;\n const deltaK = Array(pointsLen).fill(0);\n const mK = Array(pointsLen);\n // Calculate slopes (deltaK) and initialize tangents (mK)\n let i, pointBefore, pointCurrent;\n let pointAfter = getPoint(points, 0);\n for(i = 0; i < pointsLen; ++i){\n pointBefore = pointCurrent;\n pointCurrent = pointAfter;\n pointAfter = getPoint(points, i + 1);\n if (!pointCurrent) {\n continue;\n }\n if (pointAfter) {\n const slopeDelta = pointAfter[indexAxis] - pointCurrent[indexAxis];\n // In the case of two points that appear at the same x pixel, slopeDeltaX is 0\n deltaK[i] = slopeDelta !== 0 ? (pointAfter[valueAxis] - pointCurrent[valueAxis]) / slopeDelta : 0;\n }\n mK[i] = !pointBefore ? deltaK[i] : !pointAfter ? deltaK[i - 1] : sign(deltaK[i - 1]) !== sign(deltaK[i]) ? 0 : (deltaK[i - 1] + deltaK[i]) / 2;\n }\n monotoneAdjust(points, deltaK, mK);\n monotoneCompute(points, mK, indexAxis);\n}\nfunction capControlPoint(pt, min, max) {\n return Math.max(Math.min(pt, max), min);\n}\nfunction capBezierPoints(points, area) {\n let i, ilen, point, inArea, inAreaPrev;\n let inAreaNext = _isPointInArea(points[0], area);\n for(i = 0, ilen = points.length; i < ilen; ++i){\n inAreaPrev = inArea;\n inArea = inAreaNext;\n inAreaNext = i < ilen - 1 && _isPointInArea(points[i + 1], area);\n if (!inArea) {\n continue;\n }\n point = points[i];\n if (inAreaPrev) {\n point.cp1x = capControlPoint(point.cp1x, area.left, area.right);\n point.cp1y = capControlPoint(point.cp1y, area.top, area.bottom);\n }\n if (inAreaNext) {\n point.cp2x = capControlPoint(point.cp2x, area.left, area.right);\n point.cp2y = capControlPoint(point.cp2y, area.top, area.bottom);\n }\n }\n}\n/**\n * @private\n */ function _updateBezierControlPoints(points, options, area, loop, indexAxis) {\n let i, ilen, point, controlPoints;\n // Only consider points that are drawn in case the spanGaps option is used\n if (options.spanGaps) {\n points = points.filter((pt)=>!pt.skip);\n }\n if (options.cubicInterpolationMode === 'monotone') {\n splineCurveMonotone(points, indexAxis);\n } else {\n let prev = loop ? points[points.length - 1] : points[0];\n for(i = 0, ilen = points.length; i < ilen; ++i){\n point = points[i];\n controlPoints = splineCurve(prev, point, points[Math.min(i + 1, ilen - (loop ? 0 : 1)) % ilen], options.tension);\n point.cp1x = controlPoints.previous.x;\n point.cp1y = controlPoints.previous.y;\n point.cp2x = controlPoints.next.x;\n point.cp2y = controlPoints.next.y;\n prev = point;\n }\n }\n if (options.capBezierPoints) {\n capBezierPoints(points, area);\n }\n}\n\n/**\n * @private\n */ function _isDomSupported() {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n/**\n * @private\n */ function _getParentNode(domNode) {\n let parent = domNode.parentNode;\n if (parent && parent.toString() === '[object ShadowRoot]') {\n parent = parent.host;\n }\n return parent;\n}\n/**\n * convert max-width/max-height values that may be percentages into a number\n * @private\n */ function parseMaxStyle(styleValue, node, parentProperty) {\n let valueInPixels;\n if (typeof styleValue === 'string') {\n valueInPixels = parseInt(styleValue, 10);\n if (styleValue.indexOf('%') !== -1) {\n // percentage * size in dimension\n valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];\n }\n } else {\n valueInPixels = styleValue;\n }\n return valueInPixels;\n}\nconst getComputedStyle = (element)=>element.ownerDocument.defaultView.getComputedStyle(element, null);\nfunction getStyle(el, property) {\n return getComputedStyle(el).getPropertyValue(property);\n}\nconst positions = [\n 'top',\n 'right',\n 'bottom',\n 'left'\n];\nfunction getPositionedStyle(styles, style, suffix) {\n const result = {};\n suffix = suffix ? '-' + suffix : '';\n for(let i = 0; i < 4; i++){\n const pos = positions[i];\n result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0;\n }\n result.width = result.left + result.right;\n result.height = result.top + result.bottom;\n return result;\n}\nconst useOffsetPos = (x, y, target)=>(x > 0 || y > 0) && (!target || !target.shadowRoot);\n/**\n * @param e\n * @param canvas\n * @returns Canvas position\n */ function getCanvasPosition(e, canvas) {\n const touches = e.touches;\n const source = touches && touches.length ? touches[0] : e;\n const { offsetX , offsetY } = source;\n let box = false;\n let x, y;\n if (useOffsetPos(offsetX, offsetY, e.target)) {\n x = offsetX;\n y = offsetY;\n } else {\n const rect = canvas.getBoundingClientRect();\n x = source.clientX - rect.left;\n y = source.clientY - rect.top;\n box = true;\n }\n return {\n x,\n y,\n box\n };\n}\n/**\n * Gets an event's x, y coordinates, relative to the chart area\n * @param event\n * @param chart\n * @returns x and y coordinates of the event\n */ function getRelativePosition(event, chart) {\n if ('native' in event) {\n return event;\n }\n const { canvas , currentDevicePixelRatio } = chart;\n const style = getComputedStyle(canvas);\n const borderBox = style.boxSizing === 'border-box';\n const paddings = getPositionedStyle(style, 'padding');\n const borders = getPositionedStyle(style, 'border', 'width');\n const { x , y , box } = getCanvasPosition(event, canvas);\n const xOffset = paddings.left + (box && borders.left);\n const yOffset = paddings.top + (box && borders.top);\n let { width , height } = chart;\n if (borderBox) {\n width -= paddings.width + borders.width;\n height -= paddings.height + borders.height;\n }\n return {\n x: Math.round((x - xOffset) / width * canvas.width / currentDevicePixelRatio),\n y: Math.round((y - yOffset) / height * canvas.height / currentDevicePixelRatio)\n };\n}\nfunction getContainerSize(canvas, width, height) {\n let maxWidth, maxHeight;\n if (width === undefined || height === undefined) {\n const container = canvas && _getParentNode(canvas);\n if (!container) {\n width = canvas.clientWidth;\n height = canvas.clientHeight;\n } else {\n const rect = container.getBoundingClientRect(); // this is the border box of the container\n const containerStyle = getComputedStyle(container);\n const containerBorder = getPositionedStyle(containerStyle, 'border', 'width');\n const containerPadding = getPositionedStyle(containerStyle, 'padding');\n width = rect.width - containerPadding.width - containerBorder.width;\n height = rect.height - containerPadding.height - containerBorder.height;\n maxWidth = parseMaxStyle(containerStyle.maxWidth, container, 'clientWidth');\n maxHeight = parseMaxStyle(containerStyle.maxHeight, container, 'clientHeight');\n }\n }\n return {\n width,\n height,\n maxWidth: maxWidth || INFINITY,\n maxHeight: maxHeight || INFINITY\n };\n}\nconst round1 = (v)=>Math.round(v * 10) / 10;\n// eslint-disable-next-line complexity\nfunction getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) {\n const style = getComputedStyle(canvas);\n const margins = getPositionedStyle(style, 'margin');\n const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY;\n const maxHeight = parseMaxStyle(style.maxHeight, canvas, 'clientHeight') || INFINITY;\n const containerSize = getContainerSize(canvas, bbWidth, bbHeight);\n let { width , height } = containerSize;\n if (style.boxSizing === 'content-box') {\n const borders = getPositionedStyle(style, 'border', 'width');\n const paddings = getPositionedStyle(style, 'padding');\n width -= paddings.width + borders.width;\n height -= paddings.height + borders.height;\n }\n width = Math.max(0, width - margins.width);\n height = Math.max(0, aspectRatio ? width / aspectRatio : height - margins.height);\n width = round1(Math.min(width, maxWidth, containerSize.maxWidth));\n height = round1(Math.min(height, maxHeight, containerSize.maxHeight));\n if (width && !height) {\n // https://github.com/chartjs/Chart.js/issues/4659\n // If the canvas has width, but no height, default to aspectRatio of 2 (canvas default)\n height = round1(width / 2);\n }\n const maintainHeight = bbWidth !== undefined || bbHeight !== undefined;\n if (maintainHeight && aspectRatio && containerSize.height && height > containerSize.height) {\n height = containerSize.height;\n width = round1(Math.floor(height * aspectRatio));\n }\n return {\n width,\n height\n };\n}\n/**\n * @param chart\n * @param forceRatio\n * @param forceStyle\n * @returns True if the canvas context size or transformation has changed.\n */ function retinaScale(chart, forceRatio, forceStyle) {\n const pixelRatio = forceRatio || 1;\n const deviceHeight = Math.floor(chart.height * pixelRatio);\n const deviceWidth = Math.floor(chart.width * pixelRatio);\n chart.height = Math.floor(chart.height);\n chart.width = Math.floor(chart.width);\n const canvas = chart.canvas;\n // If no style has been set on the canvas, the render size is used as display size,\n // making the chart visually bigger, so let's enforce it to the \"correct\" values.\n // See https://github.com/chartjs/Chart.js/issues/3575\n if (canvas.style && (forceStyle || !canvas.style.height && !canvas.style.width)) {\n canvas.style.height = `${chart.height}px`;\n canvas.style.width = `${chart.width}px`;\n }\n if (chart.currentDevicePixelRatio !== pixelRatio || canvas.height !== deviceHeight || canvas.width !== deviceWidth) {\n chart.currentDevicePixelRatio = pixelRatio;\n canvas.height = deviceHeight;\n canvas.width = deviceWidth;\n chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\n return true;\n }\n return false;\n}\n/**\n * Detects support for options object argument in addEventListener.\n * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support\n * @private\n */ const supportsEventListenerOptions = function() {\n let passiveSupported = false;\n try {\n const options = {\n get passive () {\n passiveSupported = true;\n return false;\n }\n };\n if (_isDomSupported()) {\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n }\n } catch (e) {\n // continue regardless of error\n }\n return passiveSupported;\n}();\n/**\n * The \"used\" size is the final value of a dimension property after all calculations have\n * been performed. This method uses the computed style of `element` but returns undefined\n * if the computed style is not expressed in pixels. That can happen in some cases where\n * `element` has a size relative to its parent and this last one is not yet displayed,\n * for example because of `display: none` on a parent node.\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value\n * @returns Size in pixels or undefined if unknown.\n */ function readUsedSize(element, property) {\n const value = getStyle(element, property);\n const matches = value && value.match(/^(\\d+)(\\.\\d+)?px$/);\n return matches ? +matches[1] : undefined;\n}\n\n/**\n * @private\n */ function _pointInLine(p1, p2, t, mode) {\n return {\n x: p1.x + t * (p2.x - p1.x),\n y: p1.y + t * (p2.y - p1.y)\n };\n}\n/**\n * @private\n */ function _steppedInterpolation(p1, p2, t, mode) {\n return {\n x: p1.x + t * (p2.x - p1.x),\n y: mode === 'middle' ? t < 0.5 ? p1.y : p2.y : mode === 'after' ? t < 1 ? p1.y : p2.y : t > 0 ? p2.y : p1.y\n };\n}\n/**\n * @private\n */ function _bezierInterpolation(p1, p2, t, mode) {\n const cp1 = {\n x: p1.cp2x,\n y: p1.cp2y\n };\n const cp2 = {\n x: p2.cp1x,\n y: p2.cp1y\n };\n const a = _pointInLine(p1, cp1, t);\n const b = _pointInLine(cp1, cp2, t);\n const c = _pointInLine(cp2, p2, t);\n const d = _pointInLine(a, b, t);\n const e = _pointInLine(b, c, t);\n return _pointInLine(d, e, t);\n}\n\nconst getRightToLeftAdapter = function(rectX, width) {\n return {\n x (x) {\n return rectX + rectX + width - x;\n },\n setWidth (w) {\n width = w;\n },\n textAlign (align) {\n if (align === 'center') {\n return align;\n }\n return align === 'right' ? 'left' : 'right';\n },\n xPlus (x, value) {\n return x - value;\n },\n leftForLtr (x, itemWidth) {\n return x - itemWidth;\n }\n };\n};\nconst getLeftToRightAdapter = function() {\n return {\n x (x) {\n return x;\n },\n setWidth (w) {},\n textAlign (align) {\n return align;\n },\n xPlus (x, value) {\n return x + value;\n },\n leftForLtr (x, _itemWidth) {\n return x;\n }\n };\n};\nfunction getRtlAdapter(rtl, rectX, width) {\n return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter();\n}\nfunction overrideTextDirection(ctx, direction) {\n let style, original;\n if (direction === 'ltr' || direction === 'rtl') {\n style = ctx.canvas.style;\n original = [\n style.getPropertyValue('direction'),\n style.getPropertyPriority('direction')\n ];\n style.setProperty('direction', direction, 'important');\n ctx.prevTextDirection = original;\n }\n}\nfunction restoreTextDirection(ctx, original) {\n if (original !== undefined) {\n delete ctx.prevTextDirection;\n ctx.canvas.style.setProperty('direction', original[0], original[1]);\n }\n}\n\nfunction propertyFn(property) {\n if (property === 'angle') {\n return {\n between: _angleBetween,\n compare: _angleDiff,\n normalize: _normalizeAngle\n };\n }\n return {\n between: _isBetween,\n compare: (a, b)=>a - b,\n normalize: (x)=>x\n };\n}\nfunction normalizeSegment({ start , end , count , loop , style }) {\n return {\n start: start % count,\n end: end % count,\n loop: loop && (end - start + 1) % count === 0,\n style\n };\n}\nfunction getSegment(segment, points, bounds) {\n const { property , start: startBound , end: endBound } = bounds;\n const { between , normalize } = propertyFn(property);\n const count = points.length;\n let { start , end , loop } = segment;\n let i, ilen;\n if (loop) {\n start += count;\n end += count;\n for(i = 0, ilen = count; i < ilen; ++i){\n if (!between(normalize(points[start % count][property]), startBound, endBound)) {\n break;\n }\n start--;\n end--;\n }\n start %= count;\n end %= count;\n }\n if (end < start) {\n end += count;\n }\n return {\n start,\n end,\n loop,\n style: segment.style\n };\n}\n function _boundSegment(segment, points, bounds) {\n if (!bounds) {\n return [\n segment\n ];\n }\n const { property , start: startBound , end: endBound } = bounds;\n const count = points.length;\n const { compare , between , normalize } = propertyFn(property);\n const { start , end , loop , style } = getSegment(segment, points, bounds);\n const result = [];\n let inside = false;\n let subStart = null;\n let value, point, prevValue;\n const startIsBefore = ()=>between(startBound, prevValue, value) && compare(startBound, prevValue) !== 0;\n const endIsBefore = ()=>compare(endBound, value) === 0 || between(endBound, prevValue, value);\n const shouldStart = ()=>inside || startIsBefore();\n const shouldStop = ()=>!inside || endIsBefore();\n for(let i = start, prev = start; i <= end; ++i){\n point = points[i % count];\n if (point.skip) {\n continue;\n }\n value = normalize(point[property]);\n if (value === prevValue) {\n continue;\n }\n inside = between(value, startBound, endBound);\n if (subStart === null && shouldStart()) {\n subStart = compare(value, startBound) === 0 ? i : prev;\n }\n if (subStart !== null && shouldStop()) {\n result.push(normalizeSegment({\n start: subStart,\n end: i,\n loop,\n count,\n style\n }));\n subStart = null;\n }\n prev = i;\n prevValue = value;\n }\n if (subStart !== null) {\n result.push(normalizeSegment({\n start: subStart,\n end,\n loop,\n count,\n style\n }));\n }\n return result;\n}\n function _boundSegments(line, bounds) {\n const result = [];\n const segments = line.segments;\n for(let i = 0; i < segments.length; i++){\n const sub = _boundSegment(segments[i], line.points, bounds);\n if (sub.length) {\n result.push(...sub);\n }\n }\n return result;\n}\n function findStartAndEnd(points, count, loop, spanGaps) {\n let start = 0;\n let end = count - 1;\n if (loop && !spanGaps) {\n while(start < count && !points[start].skip){\n start++;\n }\n }\n while(start < count && points[start].skip){\n start++;\n }\n start %= count;\n if (loop) {\n end += start;\n }\n while(end > start && points[end % count].skip){\n end--;\n }\n end %= count;\n return {\n start,\n end\n };\n}\n function solidSegments(points, start, max, loop) {\n const count = points.length;\n const result = [];\n let last = start;\n let prev = points[start];\n let end;\n for(end = start + 1; end <= max; ++end){\n const cur = points[end % count];\n if (cur.skip || cur.stop) {\n if (!prev.skip) {\n loop = false;\n result.push({\n start: start % count,\n end: (end - 1) % count,\n loop\n });\n start = last = cur.stop ? end : null;\n }\n } else {\n last = end;\n if (prev.skip) {\n start = end;\n }\n }\n prev = cur;\n }\n if (last !== null) {\n result.push({\n start: start % count,\n end: last % count,\n loop\n });\n }\n return result;\n}\n function _computeSegments(line, segmentOptions) {\n const points = line.points;\n const spanGaps = line.options.spanGaps;\n const count = points.length;\n if (!count) {\n return [];\n }\n const loop = !!line._loop;\n const { start , end } = findStartAndEnd(points, count, loop, spanGaps);\n if (spanGaps === true) {\n return splitByStyles(line, [\n {\n start,\n end,\n loop\n }\n ], points, segmentOptions);\n }\n const max = end < start ? end + count : end;\n const completeLoop = !!line._fullLoop && start === 0 && end === count - 1;\n return splitByStyles(line, solidSegments(points, start, max, completeLoop), points, segmentOptions);\n}\n function splitByStyles(line, segments, points, segmentOptions) {\n if (!segmentOptions || !segmentOptions.setContext || !points) {\n return segments;\n }\n return doSplitByStyles(line, segments, points, segmentOptions);\n}\n function doSplitByStyles(line, segments, points, segmentOptions) {\n const chartContext = line._chart.getContext();\n const baseStyle = readStyle(line.options);\n const { _datasetIndex: datasetIndex , options: { spanGaps } } = line;\n const count = points.length;\n const result = [];\n let prevStyle = baseStyle;\n let start = segments[0].start;\n let i = start;\n function addStyle(s, e, l, st) {\n const dir = spanGaps ? -1 : 1;\n if (s === e) {\n return;\n }\n s += count;\n while(points[s % count].skip){\n s -= dir;\n }\n while(points[e % count].skip){\n e += dir;\n }\n if (s % count !== e % count) {\n result.push({\n start: s % count,\n end: e % count,\n loop: l,\n style: st\n });\n prevStyle = st;\n start = e % count;\n }\n }\n for (const segment of segments){\n start = spanGaps ? start : segment.start;\n let prev = points[start % count];\n let style;\n for(i = start + 1; i <= segment.end; i++){\n const pt = points[i % count];\n style = readStyle(segmentOptions.setContext(createContext(chartContext, {\n type: 'segment',\n p0: prev,\n p1: pt,\n p0DataIndex: (i - 1) % count,\n p1DataIndex: i % count,\n datasetIndex\n })));\n if (styleChanged(style, prevStyle)) {\n addStyle(start, i - 1, segment.loop, prevStyle);\n }\n prev = pt;\n prevStyle = style;\n }\n if (start < i - 1) {\n addStyle(start, i - 1, segment.loop, prevStyle);\n }\n }\n return result;\n}\nfunction readStyle(options) {\n return {\n backgroundColor: options.backgroundColor,\n borderCapStyle: options.borderCapStyle,\n borderDash: options.borderDash,\n borderDashOffset: options.borderDashOffset,\n borderJoinStyle: options.borderJoinStyle,\n borderWidth: options.borderWidth,\n borderColor: options.borderColor\n };\n}\nfunction styleChanged(style, prevStyle) {\n if (!prevStyle) {\n return false;\n }\n const cache = [];\n const replacer = function(key, value) {\n if (!isPatternOrGradient(value)) {\n return value;\n }\n if (!cache.includes(value)) {\n cache.push(value);\n }\n return cache.indexOf(value);\n };\n return JSON.stringify(style, replacer) !== JSON.stringify(prevStyle, replacer);\n}\n\nfunction getSizeForArea(scale, chartArea, field) {\n return scale.options.clip ? scale[field] : chartArea[field];\n}\nfunction getDatasetArea(meta, chartArea) {\n const { xScale , yScale } = meta;\n if (xScale && yScale) {\n return {\n left: getSizeForArea(xScale, chartArea, 'left'),\n right: getSizeForArea(xScale, chartArea, 'right'),\n top: getSizeForArea(yScale, chartArea, 'top'),\n bottom: getSizeForArea(yScale, chartArea, 'bottom')\n };\n }\n return chartArea;\n}\nfunction getDatasetClipArea(chart, meta) {\n const clip = meta._clip;\n if (clip.disabled) {\n return false;\n }\n const area = getDatasetArea(meta, chart.chartArea);\n return {\n left: clip.left === false ? 0 : area.left - (clip.left === true ? 0 : clip.left),\n right: clip.right === false ? chart.width : area.right + (clip.right === true ? 0 : clip.right),\n top: clip.top === false ? 0 : area.top - (clip.top === true ? 0 : clip.top),\n bottom: clip.bottom === false ? chart.height : area.bottom + (clip.bottom === true ? 0 : clip.bottom)\n };\n}\n\n\n//# sourceMappingURL=helpers.dataset.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvZGlzdC9jaHVua3MvaGVscGVycy5kYXRhc2V0LmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDc0M7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLFFBQVE7QUFDckM7QUFDQTtBQUNBLFVBQVU7QUFDVix1QkFBdUIsU0FBUztBQUNoQztBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBLG1CQUFtQixTQUFTO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsVUFBVTtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxVQUFVO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixVQUFVO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsVUFBVTtBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxVQUFVO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxVQUFVO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsNkJBQTZCO0FBQzdDO0FBQ0E7QUFDQSxnQkFBZ0IsdUNBQXVDO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0EsWUFBWSxrQ0FBa0M7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0QsZ0RBQUs7QUFDekQ7QUFDQTtBQUNBLG9EQUFvRCxnREFBSztBQUN6RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DLE9BQU87QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0M7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxVQUFVO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQSw0Q0FBNEMsVUFBVTtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFdBQVc7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLGtCQUFrQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLDBCQUEwQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxVQUFVO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGFBQWE7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQztBQUNqQyxpQ0FBaUM7QUFDakMsb0NBQW9DO0FBQ3BDO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Q7QUFDbEQsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQztBQUNqQyxnQ0FBZ0M7QUFDaEM7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2QsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQztBQUNqQyxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0QsWUFBWSxrR0FBa0c7QUFDOUc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksNkRBQTZEO0FBQ3pFLDhCQUE4QjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSwwQ0FBMEM7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLDZEQUE2RDtBQUN6RTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsa0JBQWtCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsYUFBYTtBQUM5QyxnQ0FBZ0MsWUFBWTtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxtQkFBbUI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFMDZFO0FBQzE2RSIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jaGFydC5qcy9kaXN0L2NodW5rcy9oZWxwZXJzLmRhdGFzZXQuanM/YmZjMyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIENoYXJ0LmpzIHY0LjUuMFxuICogaHR0cHM6Ly93d3cuY2hhcnRqcy5vcmdcbiAqIChjKSAyMDI1IENoYXJ0LmpzIENvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gKi9cbmltcG9ydCB7IENvbG9yIH0gZnJvbSAnQGt1cmtsZS9jb2xvcic7XG5cbi8qKlxuICogQG5hbWVzcGFjZSBDaGFydC5oZWxwZXJzXG4gKi8gLyoqXG4gKiBBbiBlbXB0eSBmdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkLCBmb3IgZXhhbXBsZSwgZm9yIG9wdGlvbmFsIGNhbGxiYWNrLlxuICovIGZ1bmN0aW9uIG5vb3AoKSB7XG4vKiBub29wICovIH1cbi8qKlxuICogUmV0dXJucyBhIHVuaXF1ZSBpZCwgc2VxdWVudGlhbGx5IGdlbmVyYXRlZCBmcm9tIGEgZ2xvYmFsIHZhcmlhYmxlLlxuICovIGNvbnN0IHVpZCA9ICgoKT0+e1xuICAgIGxldCBpZCA9IDA7XG4gICAgcmV0dXJuICgpPT5pZCsrO1xufSkoKTtcbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIGB2YWx1ZWAgaXMgbmVpdGhlciBudWxsIG5vciB1bmRlZmluZWQsIGVsc2UgcmV0dXJucyBmYWxzZS5cbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byB0ZXN0LlxuICogQHNpbmNlIDIuNy4wXG4gKi8gZnVuY3Rpb24gaXNOdWxsT3JVbmRlZih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkO1xufVxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgYHZhbHVlYCBpcyBhbiBhcnJheSAoaW5jbHVkaW5nIHR5cGVkIGFycmF5cyksIGVsc2UgcmV0dXJucyBmYWxzZS5cbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byB0ZXN0LlxuICogQGZ1bmN0aW9uXG4gKi8gZnVuY3Rpb24gaXNBcnJheSh2YWx1ZSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5ICYmIEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCB0eXBlID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgICBpZiAodHlwZS5zbGljZSgwLCA3KSA9PT0gJ1tvYmplY3QnICYmIHR5cGUuc2xpY2UoLTYpID09PSAnQXJyYXldJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QgKGV4Y2x1ZGluZyBudWxsKSwgZWxzZSByZXR1cm5zIGZhbHNlLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIHRlc3QuXG4gKiBAc2luY2UgMi43LjBcbiAqLyBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSAhPT0gbnVsbCAmJiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09PSAnW29iamVjdCBPYmplY3RdJztcbn1cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIGB2YWx1ZWAgaXMgYSBmaW5pdGUgbnVtYmVyLCBlbHNlIHJldHVybnMgZmFsc2VcbiAqIEBwYXJhbSB2YWx1ZSAgLSBUaGUgdmFsdWUgdG8gdGVzdC5cbiAqLyBmdW5jdGlvbiBpc051bWJlckZpbml0ZSh2YWx1ZSkge1xuICAgIHJldHVybiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyB8fCB2YWx1ZSBpbnN0YW5jZW9mIE51bWJlcikgJiYgaXNGaW5pdGUoK3ZhbHVlKTtcbn1cbi8qKlxuICogUmV0dXJucyBgdmFsdWVgIGlmIGZpbml0ZSwgZWxzZSByZXR1cm5zIGBkZWZhdWx0VmFsdWVgLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIHJldHVybiBpZiBkZWZpbmVkLlxuICogQHBhcmFtIGRlZmF1bHRWYWx1ZSAtIFRoZSB2YWx1ZSB0byByZXR1cm4gaWYgYHZhbHVlYCBpcyBub3QgZmluaXRlLlxuICovIGZ1bmN0aW9uIGZpbml0ZU9yRGVmYXVsdCh2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgcmV0dXJuIGlzTnVtYmVyRmluaXRlKHZhbHVlKSA/IHZhbHVlIDogZGVmYXVsdFZhbHVlO1xufVxuLyoqXG4gKiBSZXR1cm5zIGB2YWx1ZWAgaWYgZGVmaW5lZCwgZWxzZSByZXR1cm5zIGBkZWZhdWx0VmFsdWVgLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIHJldHVybiBpZiBkZWZpbmVkLlxuICogQHBhcmFtIGRlZmF1bHRWYWx1ZSAtIFRoZSB2YWx1ZSB0byByZXR1cm4gaWYgYHZhbHVlYCBpcyB1bmRlZmluZWQuXG4gKi8gZnVuY3Rpb24gdmFsdWVPckRlZmF1bHQodmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnID8gZGVmYXVsdFZhbHVlIDogdmFsdWU7XG59XG5jb25zdCB0b1BlcmNlbnRhZ2UgPSAodmFsdWUsIGRpbWVuc2lvbik9PnR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUuZW5kc1dpdGgoJyUnKSA/IHBhcnNlRmxvYXQodmFsdWUpIC8gMTAwIDogK3ZhbHVlIC8gZGltZW5zaW9uO1xuY29uc3QgdG9EaW1lbnNpb24gPSAodmFsdWUsIGRpbWVuc2lvbik9PnR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUuZW5kc1dpdGgoJyUnKSA/IHBhcnNlRmxvYXQodmFsdWUpIC8gMTAwICogZGltZW5zaW9uIDogK3ZhbHVlO1xuLyoqXG4gKiBDYWxscyBgZm5gIHdpdGggdGhlIGdpdmVuIGBhcmdzYCBpbiB0aGUgc2NvcGUgZGVmaW5lZCBieSBgdGhpc0FyZ2AgYW5kIHJldHVybnMgdGhlXG4gKiB2YWx1ZSByZXR1cm5lZCBieSBgZm5gLiBJZiBgZm5gIGlzIG5vdCBhIGZ1bmN0aW9uLCB0aGlzIG1ldGhvZCByZXR1cm5zIHVuZGVmaW5lZC5cbiAqIEBwYXJhbSBmbiAtIFRoZSBmdW5jdGlvbiB0byBjYWxsLlxuICogQHBhcmFtIGFyZ3MgLSBUaGUgYXJndW1lbnRzIHdpdGggd2hpY2ggYGZuYCBzaG91bGQgYmUgY2FsbGVkLlxuICogQHBhcmFtIFt0aGlzQXJnXSAtIFRoZSB2YWx1ZSBvZiBgdGhpc2AgcHJvdmlkZWQgZm9yIHRoZSBjYWxsIHRvIGBmbmAuXG4gKi8gZnVuY3Rpb24gY2FsbGJhY2soZm4sIGFyZ3MsIHRoaXNBcmcpIHtcbiAgICBpZiAoZm4gJiYgdHlwZW9mIGZuLmNhbGwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGVhY2gobG9vcGFibGUsIGZuLCB0aGlzQXJnLCByZXZlcnNlKSB7XG4gICAgbGV0IGksIGxlbiwga2V5cztcbiAgICBpZiAoaXNBcnJheShsb29wYWJsZSkpIHtcbiAgICAgICAgbGVuID0gbG9vcGFibGUubGVuZ3RoO1xuICAgICAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgICAgICAgZm9yKGkgPSBsZW4gLSAxOyBpID49IDA7IGktLSl7XG4gICAgICAgICAgICAgICAgZm4uY2FsbCh0aGlzQXJnLCBsb29wYWJsZVtpXSwgaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKyl7XG4gICAgICAgICAgICAgICAgZm4uY2FsbCh0aGlzQXJnLCBsb29wYWJsZVtpXSwgaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGxvb3BhYmxlKSkge1xuICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMobG9vcGFibGUpO1xuICAgICAgICBsZW4gPSBrZXlzLmxlbmd0aDtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspe1xuICAgICAgICAgICAgZm4uY2FsbCh0aGlzQXJnLCBsb29wYWJsZVtrZXlzW2ldXSwga2V5c1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgYGEwYCBhbmQgYGExYCBhcnJheXMgaGF2ZSB0aGUgc2FtZSBjb250ZW50LCBlbHNlIHJldHVybnMgZmFsc2UuXG4gKiBAcGFyYW0gYTAgLSBUaGUgYXJyYXkgdG8gY29tcGFyZVxuICogQHBhcmFtIGExIC0gVGhlIGFycmF5IHRvIGNvbXBhcmVcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2VsZW1lbnRzRXF1YWwoYTAsIGExKSB7XG4gICAgbGV0IGksIGlsZW4sIHYwLCB2MTtcbiAgICBpZiAoIWEwIHx8ICFhMSB8fCBhMC5sZW5ndGggIT09IGExLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvcihpID0gMCwgaWxlbiA9IGEwLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIHYwID0gYTBbaV07XG4gICAgICAgIHYxID0gYTFbaV07XG4gICAgICAgIGlmICh2MC5kYXRhc2V0SW5kZXggIT09IHYxLmRhdGFzZXRJbmRleCB8fCB2MC5pbmRleCAhPT0gdjEuaW5kZXgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbi8qKlxuICogUmV0dXJucyBhIGRlZXAgY29weSBvZiBgc291cmNlYCB3aXRob3V0IGtlZXBpbmcgcmVmZXJlbmNlcyBvbiBvYmplY3RzIGFuZCBhcnJheXMuXG4gKiBAcGFyYW0gc291cmNlIC0gVGhlIHZhbHVlIHRvIGNsb25lLlxuICovIGZ1bmN0aW9uIGNsb25lKHNvdXJjZSkge1xuICAgIGlmIChpc0FycmF5KHNvdXJjZSkpIHtcbiAgICAgICAgcmV0dXJuIHNvdXJjZS5tYXAoY2xvbmUpO1xuICAgIH1cbiAgICBpZiAoaXNPYmplY3Qoc291cmNlKSkge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoc291cmNlKTtcbiAgICAgICAgY29uc3Qga2xlbiA9IGtleXMubGVuZ3RoO1xuICAgICAgICBsZXQgayA9IDA7XG4gICAgICAgIGZvcig7IGsgPCBrbGVuOyArK2spe1xuICAgICAgICAgICAgdGFyZ2V0W2tleXNba11dID0gY2xvbmUoc291cmNlW2tleXNba11dKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlO1xufVxuZnVuY3Rpb24gaXNWYWxpZEtleShrZXkpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICAnX19wcm90b19fJyxcbiAgICAgICAgJ3Byb3RvdHlwZScsXG4gICAgICAgICdjb25zdHJ1Y3RvcidcbiAgICBdLmluZGV4T2Yoa2V5KSA9PT0gLTE7XG59XG4vKipcbiAqIFRoZSBkZWZhdWx0IG1lcmdlciB3aGVuIENoYXJ0LmhlbHBlcnMubWVyZ2UgaXMgY2FsbGVkIHdpdGhvdXQgbWVyZ2VyIG9wdGlvbi5cbiAqIE5vdGUoU0IpOiBhbHNvIHVzZWQgYnkgbWVyZ2VDb25maWcgYW5kIG1lcmdlU2NhbGVDb25maWcgYXMgZmFsbGJhY2suXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9tZXJnZXIoa2V5LCB0YXJnZXQsIHNvdXJjZSwgb3B0aW9ucykge1xuICAgIGlmICghaXNWYWxpZEtleShrZXkpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdHZhbCA9IHRhcmdldFtrZXldO1xuICAgIGNvbnN0IHN2YWwgPSBzb3VyY2Vba2V5XTtcbiAgICBpZiAoaXNPYmplY3QodHZhbCkgJiYgaXNPYmplY3Qoc3ZhbCkpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11c2UtYmVmb3JlLWRlZmluZVxuICAgICAgICBtZXJnZSh0dmFsLCBzdmFsLCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0YXJnZXRba2V5XSA9IGNsb25lKHN2YWwpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIG1lcmdlKHRhcmdldCwgc291cmNlLCBvcHRpb25zKSB7XG4gICAgY29uc3Qgc291cmNlcyA9IGlzQXJyYXkoc291cmNlKSA/IHNvdXJjZSA6IFtcbiAgICAgICAgc291cmNlXG4gICAgXTtcbiAgICBjb25zdCBpbGVuID0gc291cmNlcy5sZW5ndGg7XG4gICAgaWYgKCFpc09iamVjdCh0YXJnZXQpKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgfVxuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIGNvbnN0IG1lcmdlciA9IG9wdGlvbnMubWVyZ2VyIHx8IF9tZXJnZXI7XG4gICAgbGV0IGN1cnJlbnQ7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGN1cnJlbnQgPSBzb3VyY2VzW2ldO1xuICAgICAgICBpZiAoIWlzT2JqZWN0KGN1cnJlbnQpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoY3VycmVudCk7XG4gICAgICAgIGZvcihsZXQgayA9IDAsIGtsZW4gPSBrZXlzLmxlbmd0aDsgayA8IGtsZW47ICsrayl7XG4gICAgICAgICAgICBtZXJnZXIoa2V5c1trXSwgdGFyZ2V0LCBjdXJyZW50LCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGFyZ2V0O1xufVxuZnVuY3Rpb24gbWVyZ2VJZih0YXJnZXQsIHNvdXJjZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdXNlLWJlZm9yZS1kZWZpbmVcbiAgICByZXR1cm4gbWVyZ2UodGFyZ2V0LCBzb3VyY2UsIHtcbiAgICAgICAgbWVyZ2VyOiBfbWVyZ2VySWZcbiAgICB9KTtcbn1cbi8qKlxuICogTWVyZ2VzIHNvdXJjZVtrZXldIGluIHRhcmdldFtrZXldIG9ubHkgaWYgdGFyZ2V0W2tleV0gaXMgdW5kZWZpbmVkLlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfbWVyZ2VySWYoa2V5LCB0YXJnZXQsIHNvdXJjZSkge1xuICAgIGlmICghaXNWYWxpZEtleShrZXkpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdHZhbCA9IHRhcmdldFtrZXldO1xuICAgIGNvbnN0IHN2YWwgPSBzb3VyY2Vba2V5XTtcbiAgICBpZiAoaXNPYmplY3QodHZhbCkgJiYgaXNPYmplY3Qoc3ZhbCkpIHtcbiAgICAgICAgbWVyZ2VJZih0dmFsLCBzdmFsKTtcbiAgICB9IGVsc2UgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGFyZ2V0LCBrZXkpKSB7XG4gICAgICAgIHRhcmdldFtrZXldID0gY2xvbmUoc3ZhbCk7XG4gICAgfVxufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9kZXByZWNhdGVkKHNjb3BlLCB2YWx1ZSwgcHJldmlvdXMsIGN1cnJlbnQpIHtcbiAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oc2NvcGUgKyAnOiBcIicgKyBwcmV2aW91cyArICdcIiBpcyBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIFwiJyArIGN1cnJlbnQgKyAnXCIgaW5zdGVhZCcpO1xuICAgIH1cbn1cbi8vIHJlc29sdmVPYmplY3RLZXkgcmVzb2x2ZXIgY2FjaGVcbmNvbnN0IGtleVJlc29sdmVycyA9IHtcbiAgICAvLyBDaGFydC5oZWxwZXJzLmNvcmUgcmVzb2x2ZU9iamVjdEtleSBzaG91bGQgcmVzb2x2ZSBlbXB0eSBrZXkgdG8gcm9vdCBvYmplY3RcbiAgICAnJzogKHYpPT52LFxuICAgIC8vIGRlZmF1bHQgcmVzb2x2ZXJzXG4gICAgeDogKG8pPT5vLngsXG4gICAgeTogKG8pPT5vLnlcbn07XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX3NwbGl0S2V5KGtleSkge1xuICAgIGNvbnN0IHBhcnRzID0ga2V5LnNwbGl0KCcuJyk7XG4gICAgY29uc3Qga2V5cyA9IFtdO1xuICAgIGxldCB0bXAgPSAnJztcbiAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGFydHMpe1xuICAgICAgICB0bXAgKz0gcGFydDtcbiAgICAgICAgaWYgKHRtcC5lbmRzV2l0aCgnXFxcXCcpKSB7XG4gICAgICAgICAgICB0bXAgPSB0bXAuc2xpY2UoMCwgLTEpICsgJy4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAga2V5cy5wdXNoKHRtcCk7XG4gICAgICAgICAgICB0bXAgPSAnJztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ga2V5cztcbn1cbmZ1bmN0aW9uIF9nZXRLZXlSZXNvbHZlcihrZXkpIHtcbiAgICBjb25zdCBrZXlzID0gX3NwbGl0S2V5KGtleSk7XG4gICAgcmV0dXJuIChvYmopPT57XG4gICAgICAgIGZvciAoY29uc3QgayBvZiBrZXlzKXtcbiAgICAgICAgICAgIGlmIChrID09PSAnJykge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb2JqID0gb2JqICYmIG9ialtrXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH07XG59XG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0S2V5KG9iaiwga2V5KSB7XG4gICAgY29uc3QgcmVzb2x2ZXIgPSBrZXlSZXNvbHZlcnNba2V5XSB8fCAoa2V5UmVzb2x2ZXJzW2tleV0gPSBfZ2V0S2V5UmVzb2x2ZXIoa2V5KSk7XG4gICAgcmV0dXJuIHJlc29sdmVyKG9iaik7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2NhcGl0YWxpemUoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0ci5zbGljZSgxKTtcbn1cbmNvbnN0IGRlZmluZWQgPSAodmFsdWUpPT50eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnO1xuY29uc3QgaXNGdW5jdGlvbiA9ICh2YWx1ZSk9PnR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcbi8vIEFkYXB0ZWQgZnJvbSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8zMTEyODg1NS9jb21wYXJpbmctZWNtYTYtc2V0cy1mb3ItZXF1YWxpdHkjMzExMjkzODRcbmNvbnN0IHNldHNFcXVhbCA9IChhLCBiKT0+e1xuICAgIGlmIChhLnNpemUgIT09IGIuc2l6ZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAoY29uc3QgaXRlbSBvZiBhKXtcbiAgICAgICAgaWYgKCFiLmhhcyhpdGVtKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcbi8qKlxuICogQHBhcmFtIGUgLSBUaGUgZXZlbnRcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2lzQ2xpY2tFdmVudChlKSB7XG4gICAgcmV0dXJuIGUudHlwZSA9PT0gJ21vdXNldXAnIHx8IGUudHlwZSA9PT0gJ2NsaWNrJyB8fCBlLnR5cGUgPT09ICdjb250ZXh0bWVudSc7XG59XG5cbi8qKlxuICogQGFsaWFzIENoYXJ0LmhlbHBlcnMubWF0aFxuICogQG5hbWVzcGFjZVxuICovIGNvbnN0IFBJID0gTWF0aC5QSTtcbmNvbnN0IFRBVSA9IDIgKiBQSTtcbmNvbnN0IFBJVEFVID0gVEFVICsgUEk7XG5jb25zdCBJTkZJTklUWSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbmNvbnN0IFJBRF9QRVJfREVHID0gUEkgLyAxODA7XG5jb25zdCBIQUxGX1BJID0gUEkgLyAyO1xuY29uc3QgUVVBUlRFUl9QSSA9IFBJIC8gNDtcbmNvbnN0IFRXT19USElSRFNfUEkgPSBQSSAqIDIgLyAzO1xuY29uc3QgbG9nMTAgPSBNYXRoLmxvZzEwO1xuY29uc3Qgc2lnbiA9IE1hdGguc2lnbjtcbmZ1bmN0aW9uIGFsbW9zdEVxdWFscyh4LCB5LCBlcHNpbG9uKSB7XG4gICAgcmV0dXJuIE1hdGguYWJzKHggLSB5KSA8IGVwc2lsb247XG59XG4vKipcbiAqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBuaWNlIG51bWJlciBhbGdvcml0aG0gdXNlZCBpbiBkZXRlcm1pbmluZyB3aGVyZSBheGlzIGxhYmVscyB3aWxsIGdvXG4gKi8gZnVuY3Rpb24gbmljZU51bShyYW5nZSkge1xuICAgIGNvbnN0IHJvdW5kZWRSYW5nZSA9IE1hdGgucm91bmQocmFuZ2UpO1xuICAgIHJhbmdlID0gYWxtb3N0RXF1YWxzKHJhbmdlLCByb3VuZGVkUmFuZ2UsIHJhbmdlIC8gMTAwMCkgPyByb3VuZGVkUmFuZ2UgOiByYW5nZTtcbiAgICBjb25zdCBuaWNlUmFuZ2UgPSBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihsb2cxMChyYW5nZSkpKTtcbiAgICBjb25zdCBmcmFjdGlvbiA9IHJhbmdlIC8gbmljZVJhbmdlO1xuICAgIGNvbnN0IG5pY2VGcmFjdGlvbiA9IGZyYWN0aW9uIDw9IDEgPyAxIDogZnJhY3Rpb24gPD0gMiA/IDIgOiBmcmFjdGlvbiA8PSA1ID8gNSA6IDEwO1xuICAgIHJldHVybiBuaWNlRnJhY3Rpb24gKiBuaWNlUmFuZ2U7XG59XG4vKipcbiAqIFJldHVybnMgYW4gYXJyYXkgb2YgZmFjdG9ycyBzb3J0ZWQgZnJvbSAxIHRvIHNxcnQodmFsdWUpXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9mYWN0b3JpemUodmFsdWUpIHtcbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBjb25zdCBzcXJ0ID0gTWF0aC5zcXJ0KHZhbHVlKTtcbiAgICBsZXQgaTtcbiAgICBmb3IoaSA9IDE7IGkgPCBzcXJ0OyBpKyspe1xuICAgICAgICBpZiAodmFsdWUgJSBpID09PSAwKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaChpKTtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlIC8gaSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHNxcnQgPT09IChzcXJ0IHwgMCkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goc3FydCk7XG4gICAgfVxuICAgIHJlc3VsdC5zb3J0KChhLCBiKT0+YSAtIGIpLnBvcCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG4vKipcbiAqIFZlcmlmaWVzIHRoYXQgYXR0ZW1wdGluZyB0byBjb2VyY2UgbiB0byBzdHJpbmcgb3IgbnVtYmVyIHdvbid0IHRocm93IGEgVHlwZUVycm9yLlxuICovIGZ1bmN0aW9uIGlzTm9uUHJpbWl0aXZlKG4pIHtcbiAgICByZXR1cm4gdHlwZW9mIG4gPT09ICdzeW1ib2wnIHx8IHR5cGVvZiBuID09PSAnb2JqZWN0JyAmJiBuICE9PSBudWxsICYmICEoU3ltYm9sLnRvUHJpbWl0aXZlIGluIG4gfHwgJ3RvU3RyaW5nJyBpbiBuIHx8ICd2YWx1ZU9mJyBpbiBuKTtcbn1cbmZ1bmN0aW9uIGlzTnVtYmVyKG4pIHtcbiAgICByZXR1cm4gIWlzTm9uUHJpbWl0aXZlKG4pICYmICFpc05hTihwYXJzZUZsb2F0KG4pKSAmJiBpc0Zpbml0ZShuKTtcbn1cbmZ1bmN0aW9uIGFsbW9zdFdob2xlKHgsIGVwc2lsb24pIHtcbiAgICBjb25zdCByb3VuZGVkID0gTWF0aC5yb3VuZCh4KTtcbiAgICByZXR1cm4gcm91bmRlZCAtIGVwc2lsb24gPD0geCAmJiByb3VuZGVkICsgZXBzaWxvbiA+PSB4O1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9zZXRNaW5BbmRNYXhCeUtleShhcnJheSwgdGFyZ2V0LCBwcm9wZXJ0eSkge1xuICAgIGxldCBpLCBpbGVuLCB2YWx1ZTtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBhcnJheS5sZW5ndGg7IGkgPCBpbGVuOyBpKyspe1xuICAgICAgICB2YWx1ZSA9IGFycmF5W2ldW3Byb3BlcnR5XTtcbiAgICAgICAgaWYgKCFpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRhcmdldC5taW4gPSBNYXRoLm1pbih0YXJnZXQubWluLCB2YWx1ZSk7XG4gICAgICAgICAgICB0YXJnZXQubWF4ID0gTWF0aC5tYXgodGFyZ2V0Lm1heCwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gdG9SYWRpYW5zKGRlZ3JlZXMpIHtcbiAgICByZXR1cm4gZGVncmVlcyAqIChQSSAvIDE4MCk7XG59XG5mdW5jdGlvbiB0b0RlZ3JlZXMocmFkaWFucykge1xuICAgIHJldHVybiByYWRpYW5zICogKDE4MCAvIFBJKTtcbn1cbi8qKlxuICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzXG4gKiBpLmUuIHRoZSBudW1iZXIgb2YgZGlnaXRzIGFmdGVyIHRoZSBkZWNpbWFsIHBvaW50LCBvZiB0aGUgdmFsdWUgb2YgdGhpcyBOdW1iZXIuXG4gKiBAcGFyYW0geCAtIEEgbnVtYmVyLlxuICogQHJldHVybnMgVGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcy5cbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2RlY2ltYWxQbGFjZXMoeCkge1xuICAgIGlmICghaXNOdW1iZXJGaW5pdGUoeCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgZSA9IDE7XG4gICAgbGV0IHAgPSAwO1xuICAgIHdoaWxlKE1hdGgucm91bmQoeCAqIGUpIC8gZSAhPT0geCl7XG4gICAgICAgIGUgKj0gMTA7XG4gICAgICAgIHArKztcbiAgICB9XG4gICAgcmV0dXJuIHA7XG59XG4vLyBHZXRzIHRoZSBhbmdsZSBmcm9tIHZlcnRpY2FsIHVwcmlnaHQgdG8gdGhlIHBvaW50IGFib3V0IGEgY2VudHJlLlxuZnVuY3Rpb24gZ2V0QW5nbGVGcm9tUG9pbnQoY2VudHJlUG9pbnQsIGFuZ2xlUG9pbnQpIHtcbiAgICBjb25zdCBkaXN0YW5jZUZyb21YQ2VudGVyID0gYW5nbGVQb2ludC54IC0gY2VudHJlUG9pbnQueDtcbiAgICBjb25zdCBkaXN0YW5jZUZyb21ZQ2VudGVyID0gYW5nbGVQb2ludC55IC0gY2VudHJlUG9pbnQueTtcbiAgICBjb25zdCByYWRpYWxEaXN0YW5jZUZyb21DZW50ZXIgPSBNYXRoLnNxcnQoZGlzdGFuY2VGcm9tWENlbnRlciAqIGRpc3RhbmNlRnJvbVhDZW50ZXIgKyBkaXN0YW5jZUZyb21ZQ2VudGVyICogZGlzdGFuY2VGcm9tWUNlbnRlcik7XG4gICAgbGV0IGFuZ2xlID0gTWF0aC5hdGFuMihkaXN0YW5jZUZyb21ZQ2VudGVyLCBkaXN0YW5jZUZyb21YQ2VudGVyKTtcbiAgICBpZiAoYW5nbGUgPCAtMC41ICogUEkpIHtcbiAgICAgICAgYW5nbGUgKz0gVEFVOyAvLyBtYWtlIHN1cmUgdGhlIHJldHVybmVkIGFuZ2xlIGlzIGluIHRoZSByYW5nZSBvZiAoLVBJLzIsIDNQSS8yXVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBhbmdsZSxcbiAgICAgICAgZGlzdGFuY2U6IHJhZGlhbERpc3RhbmNlRnJvbUNlbnRlclxuICAgIH07XG59XG5mdW5jdGlvbiBkaXN0YW5jZUJldHdlZW5Qb2ludHMocHQxLCBwdDIpIHtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KE1hdGgucG93KHB0Mi54IC0gcHQxLngsIDIpICsgTWF0aC5wb3cocHQyLnkgLSBwdDEueSwgMikpO1xufVxuLyoqXG4gKiBTaG9ydGVzdCBkaXN0YW5jZSBiZXR3ZWVuIGFuZ2xlcywgaW4gZWl0aGVyIGRpcmVjdGlvbi5cbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2FuZ2xlRGlmZihhLCBiKSB7XG4gICAgcmV0dXJuIChhIC0gYiArIFBJVEFVKSAlIFRBVSAtIFBJO1xufVxuLyoqXG4gKiBOb3JtYWxpemUgYW5nbGUgdG8gYmUgYmV0d2VlbiAwIGFuZCAyKlBJXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9ub3JtYWxpemVBbmdsZShhKSB7XG4gICAgcmV0dXJuIChhICUgVEFVICsgVEFVKSAlIFRBVTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfYW5nbGVCZXR3ZWVuKGFuZ2xlLCBzdGFydCwgZW5kLCBzYW1lQW5nbGVJc0Z1bGxDaXJjbGUpIHtcbiAgICBjb25zdCBhID0gX25vcm1hbGl6ZUFuZ2xlKGFuZ2xlKTtcbiAgICBjb25zdCBzID0gX25vcm1hbGl6ZUFuZ2xlKHN0YXJ0KTtcbiAgICBjb25zdCBlID0gX25vcm1hbGl6ZUFuZ2xlKGVuZCk7XG4gICAgY29uc3QgYW5nbGVUb1N0YXJ0ID0gX25vcm1hbGl6ZUFuZ2xlKHMgLSBhKTtcbiAgICBjb25zdCBhbmdsZVRvRW5kID0gX25vcm1hbGl6ZUFuZ2xlKGUgLSBhKTtcbiAgICBjb25zdCBzdGFydFRvQW5nbGUgPSBfbm9ybWFsaXplQW5nbGUoYSAtIHMpO1xuICAgIGNvbnN0IGVuZFRvQW5nbGUgPSBfbm9ybWFsaXplQW5nbGUoYSAtIGUpO1xuICAgIHJldHVybiBhID09PSBzIHx8IGEgPT09IGUgfHwgc2FtZUFuZ2xlSXNGdWxsQ2lyY2xlICYmIHMgPT09IGUgfHwgYW5nbGVUb1N0YXJ0ID4gYW5nbGVUb0VuZCAmJiBzdGFydFRvQW5nbGUgPCBlbmRUb0FuZ2xlO1xufVxuLyoqXG4gKiBMaW1pdCBgdmFsdWVgIGJldHdlZW4gYG1pbmAgYW5kIGBtYXhgXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEBwYXJhbSBtaW5cbiAqIEBwYXJhbSBtYXhcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2xpbWl0VmFsdWUodmFsdWUsIG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4obWF4LCB2YWx1ZSkpO1xufVxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2ludDE2UmFuZ2UodmFsdWUpIHtcbiAgICByZXR1cm4gX2xpbWl0VmFsdWUodmFsdWUsIC0zMjc2OCwgMzI3NjcpO1xufVxuLyoqXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEBwYXJhbSBzdGFydFxuICogQHBhcmFtIGVuZFxuICogQHBhcmFtIFtlcHNpbG9uXVxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfaXNCZXR3ZWVuKHZhbHVlLCBzdGFydCwgZW5kLCBlcHNpbG9uID0gMWUtNikge1xuICAgIHJldHVybiB2YWx1ZSA+PSBNYXRoLm1pbihzdGFydCwgZW5kKSAtIGVwc2lsb24gJiYgdmFsdWUgPD0gTWF0aC5tYXgoc3RhcnQsIGVuZCkgKyBlcHNpbG9uO1xufVxuXG5mdW5jdGlvbiBfbG9va3VwKHRhYmxlLCB2YWx1ZSwgY21wKSB7XG4gICAgY21wID0gY21wIHx8ICgoaW5kZXgpPT50YWJsZVtpbmRleF0gPCB2YWx1ZSk7XG4gICAgbGV0IGhpID0gdGFibGUubGVuZ3RoIC0gMTtcbiAgICBsZXQgbG8gPSAwO1xuICAgIGxldCBtaWQ7XG4gICAgd2hpbGUoaGkgLSBsbyA+IDEpe1xuICAgICAgICBtaWQgPSBsbyArIGhpID4+IDE7XG4gICAgICAgIGlmIChjbXAobWlkKSkge1xuICAgICAgICAgICAgbG8gPSBtaWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoaSA9IG1pZDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBsbyxcbiAgICAgICAgaGlcbiAgICB9O1xufVxuLyoqXG4gKiBCaW5hcnkgc2VhcmNoXG4gKiBAcGFyYW0gdGFibGUgLSB0aGUgdGFibGUgc2VhcmNoLiBtdXN0IGJlIHNvcnRlZCFcbiAqIEBwYXJhbSBrZXkgLSBwcm9wZXJ0eSBuYW1lIGZvciB0aGUgdmFsdWUgaW4gZWFjaCBlbnRyeVxuICogQHBhcmFtIHZhbHVlIC0gdmFsdWUgdG8gZmluZFxuICogQHBhcmFtIGxhc3QgLSBsb29rdXAgbGFzdCBpbmRleFxuICogQHByaXZhdGVcbiAqLyBjb25zdCBfbG9va3VwQnlLZXkgPSAodGFibGUsIGtleSwgdmFsdWUsIGxhc3QpPT5fbG9va3VwKHRhYmxlLCB2YWx1ZSwgbGFzdCA/IChpbmRleCk9PntcbiAgICAgICAgY29uc3QgdGkgPSB0YWJsZVtpbmRleF1ba2V5XTtcbiAgICAgICAgcmV0dXJuIHRpIDwgdmFsdWUgfHwgdGkgPT09IHZhbHVlICYmIHRhYmxlW2luZGV4ICsgMV1ba2V5XSA9PT0gdmFsdWU7XG4gICAgfSA6IChpbmRleCk9PnRhYmxlW2luZGV4XVtrZXldIDwgdmFsdWUpO1xuLyoqXG4gKiBSZXZlcnNlIGJpbmFyeSBzZWFyY2hcbiAqIEBwYXJhbSB0YWJsZSAtIHRoZSB0YWJsZSBzZWFyY2guIG11c3QgYmUgc29ydGVkIVxuICogQHBhcmFtIGtleSAtIHByb3BlcnR5IG5hbWUgZm9yIHRoZSB2YWx1ZSBpbiBlYWNoIGVudHJ5XG4gKiBAcGFyYW0gdmFsdWUgLSB2YWx1ZSB0byBmaW5kXG4gKiBAcHJpdmF0ZVxuICovIGNvbnN0IF9ybG9va3VwQnlLZXkgPSAodGFibGUsIGtleSwgdmFsdWUpPT5fbG9va3VwKHRhYmxlLCB2YWx1ZSwgKGluZGV4KT0+dGFibGVbaW5kZXhdW2tleV0gPj0gdmFsdWUpO1xuLyoqXG4gKiBSZXR1cm4gc3Vic2V0IG9mIGB2YWx1ZXNgIGJldHdlZW4gYG1pbmAgYW5kIGBtYXhgIGluY2x1c2l2ZS5cbiAqIFZhbHVlcyBhcmUgYXNzdW1lZCB0byBiZSBpbiBzb3J0ZWQgb3JkZXIuXG4gKiBAcGFyYW0gdmFsdWVzIC0gc29ydGVkIGFycmF5IG9mIHZhbHVlc1xuICogQHBhcmFtIG1pbiAtIG1pbiB2YWx1ZVxuICogQHBhcmFtIG1heCAtIG1heCB2YWx1ZVxuICovIGZ1bmN0aW9uIF9maWx0ZXJCZXR3ZWVuKHZhbHVlcywgbWluLCBtYXgpIHtcbiAgICBsZXQgc3RhcnQgPSAwO1xuICAgIGxldCBlbmQgPSB2YWx1ZXMubGVuZ3RoO1xuICAgIHdoaWxlKHN0YXJ0IDwgZW5kICYmIHZhbHVlc1tzdGFydF0gPCBtaW4pe1xuICAgICAgICBzdGFydCsrO1xuICAgIH1cbiAgICB3aGlsZShlbmQgPiBzdGFydCAmJiB2YWx1ZXNbZW5kIC0gMV0gPiBtYXgpe1xuICAgICAgICBlbmQtLTtcbiAgICB9XG4gICAgcmV0dXJuIHN0YXJ0ID4gMCB8fCBlbmQgPCB2YWx1ZXMubGVuZ3RoID8gdmFsdWVzLnNsaWNlKHN0YXJ0LCBlbmQpIDogdmFsdWVzO1xufVxuY29uc3QgYXJyYXlFdmVudHMgPSBbXG4gICAgJ3B1c2gnLFxuICAgICdwb3AnLFxuICAgICdzaGlmdCcsXG4gICAgJ3NwbGljZScsXG4gICAgJ3Vuc2hpZnQnXG5dO1xuZnVuY3Rpb24gbGlzdGVuQXJyYXlFdmVudHMoYXJyYXksIGxpc3RlbmVyKSB7XG4gICAgaWYgKGFycmF5Ll9jaGFydGpzKSB7XG4gICAgICAgIGFycmF5Ll9jaGFydGpzLmxpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoYXJyYXksICdfY2hhcnRqcycsIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICAgIGxpc3RlbmVyczogW1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyXG4gICAgICAgICAgICBdXG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBhcnJheUV2ZW50cy5mb3JFYWNoKChrZXkpPT57XG4gICAgICAgIGNvbnN0IG1ldGhvZCA9ICdfb25EYXRhJyArIF9jYXBpdGFsaXplKGtleSk7XG4gICAgICAgIGNvbnN0IGJhc2UgPSBhcnJheVtrZXldO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoYXJyYXksIGtleSwge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICB2YWx1ZSAoLi4uYXJncykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcyA9IGJhc2UuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICAgICAgYXJyYXkuX2NoYXJ0anMubGlzdGVuZXJzLmZvckVhY2goKG9iamVjdCk9PntcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3RbbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0W21ldGhvZF0oLi4uYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIHVubGlzdGVuQXJyYXlFdmVudHMoYXJyYXksIGxpc3RlbmVyKSB7XG4gICAgY29uc3Qgc3R1YiA9IGFycmF5Ll9jaGFydGpzO1xuICAgIGlmICghc3R1Yikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGxpc3RlbmVycyA9IHN0dWIubGlzdGVuZXJzO1xuICAgIGNvbnN0IGluZGV4ID0gbGlzdGVuZXJzLmluZGV4T2YobGlzdGVuZXIpO1xuICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgbGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7XG4gICAgfVxuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGFycmF5RXZlbnRzLmZvckVhY2goKGtleSk9PntcbiAgICAgICAgZGVsZXRlIGFycmF5W2tleV07XG4gICAgfSk7XG4gICAgZGVsZXRlIGFycmF5Ll9jaGFydGpzO1xufVxuLyoqXG4gKiBAcGFyYW0gaXRlbXNcbiAqLyBmdW5jdGlvbiBfYXJyYXlVbmlxdWUoaXRlbXMpIHtcbiAgICBjb25zdCBzZXQgPSBuZXcgU2V0KGl0ZW1zKTtcbiAgICBpZiAoc2V0LnNpemUgPT09IGl0ZW1zLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gaXRlbXM7XG4gICAgfVxuICAgIHJldHVybiBBcnJheS5mcm9tKHNldCk7XG59XG5cbmZ1bmN0aW9uIGZvbnRTdHJpbmcocGl4ZWxTaXplLCBmb250U3R5bGUsIGZvbnRGYW1pbHkpIHtcbiAgICByZXR1cm4gZm9udFN0eWxlICsgJyAnICsgcGl4ZWxTaXplICsgJ3B4ICcgKyBmb250RmFtaWx5O1xufVxuLyoqXG4qIFJlcXVlc3QgYW5pbWF0aW9uIHBvbHlmaWxsXG4qLyBjb25zdCByZXF1ZXN0QW5pbUZyYW1lID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lO1xufSgpO1xuLyoqXG4gKiBUaHJvdHRsZXMgY2FsbGluZyBgZm5gIG9uY2UgcGVyIGFuaW1hdGlvbiBmcmFtZVxuICogTGF0ZXN0IGFyZ3VtZW50cyBhcmUgdXNlZCBvbiB0aGUgYWN0dWFsIGNhbGxcbiAqLyBmdW5jdGlvbiB0aHJvdHRsZWQoZm4sIHRoaXNBcmcpIHtcbiAgICBsZXQgYXJnc1RvVXNlID0gW107XG4gICAgbGV0IHRpY2tpbmcgPSBmYWxzZTtcbiAgICByZXR1cm4gZnVuY3Rpb24oLi4uYXJncykge1xuICAgICAgICAvLyBTYXZlIHRoZSBhcmdzIGZvciB1c2UgbGF0ZXJcbiAgICAgICAgYXJnc1RvVXNlID0gYXJncztcbiAgICAgICAgaWYgKCF0aWNraW5nKSB7XG4gICAgICAgICAgICB0aWNraW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHJlcXVlc3RBbmltRnJhbWUuY2FsbCh3aW5kb3csICgpPT57XG4gICAgICAgICAgICAgICAgdGlja2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZuLmFwcGx5KHRoaXNBcmcsIGFyZ3NUb1VzZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG59XG4vKipcbiAqIERlYm91bmNlcyBjYWxsaW5nIGBmbmAgZm9yIGBkZWxheWAgbXNcbiAqLyBmdW5jdGlvbiBkZWJvdW5jZShmbiwgZGVsYXkpIHtcbiAgICBsZXQgdGltZW91dDtcbiAgICByZXR1cm4gZnVuY3Rpb24oLi4uYXJncykge1xuICAgICAgICBpZiAoZGVsYXkpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGZuLCBkZWxheSwgYXJncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmbi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGVsYXk7XG4gICAgfTtcbn1cbi8qKlxuICogQ29udmVydHMgJ3N0YXJ0JyB0byAnbGVmdCcsICdlbmQnIHRvICdyaWdodCcgYW5kIG90aGVycyB0byAnY2VudGVyJ1xuICogQHByaXZhdGVcbiAqLyBjb25zdCBfdG9MZWZ0UmlnaHRDZW50ZXIgPSAoYWxpZ24pPT5hbGlnbiA9PT0gJ3N0YXJ0JyA/ICdsZWZ0JyA6IGFsaWduID09PSAnZW5kJyA/ICdyaWdodCcgOiAnY2VudGVyJztcbi8qKlxuICogUmV0dXJucyBgc3RhcnRgLCBgZW5kYCBvciBgKHN0YXJ0ICsgZW5kKSAvIDJgIGRlcGVuZGluZyBvbiBgYWxpZ25gLiBEZWZhdWx0cyB0byBgY2VudGVyYFxuICogQHByaXZhdGVcbiAqLyBjb25zdCBfYWxpZ25TdGFydEVuZCA9IChhbGlnbiwgc3RhcnQsIGVuZCk9PmFsaWduID09PSAnc3RhcnQnID8gc3RhcnQgOiBhbGlnbiA9PT0gJ2VuZCcgPyBlbmQgOiAoc3RhcnQgKyBlbmQpIC8gMjtcbi8qKlxuICogUmV0dXJucyBgbGVmdGAsIGByaWdodGAgb3IgYChsZWZ0ICsgcmlnaHQpIC8gMmAgZGVwZW5kaW5nIG9uIGBhbGlnbmAuIERlZmF1bHRzIHRvIGBsZWZ0YFxuICogQHByaXZhdGVcbiAqLyBjb25zdCBfdGV4dFggPSAoYWxpZ24sIGxlZnQsIHJpZ2h0LCBydGwpPT57XG4gICAgY29uc3QgY2hlY2sgPSBydGwgPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgIHJldHVybiBhbGlnbiA9PT0gY2hlY2sgPyByaWdodCA6IGFsaWduID09PSAnY2VudGVyJyA/IChsZWZ0ICsgcmlnaHQpIC8gMiA6IGxlZnQ7XG59O1xuLyoqXG4gKiBSZXR1cm4gc3RhcnQgYW5kIGNvdW50IG9mIHZpc2libGUgcG9pbnRzLlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfZ2V0U3RhcnRBbmRDb3VudE9mVmlzaWJsZVBvaW50cyhtZXRhLCBwb2ludHMsIGFuaW1hdGlvbnNEaXNhYmxlZCkge1xuICAgIGNvbnN0IHBvaW50Q291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IGNvdW50ID0gcG9pbnRDb3VudDtcbiAgICBpZiAobWV0YS5fc29ydGVkKSB7XG4gICAgICAgIGNvbnN0IHsgaVNjYWxlICwgdlNjYWxlICwgX3BhcnNlZCAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IHNwYW5HYXBzID0gbWV0YS5kYXRhc2V0ID8gbWV0YS5kYXRhc2V0Lm9wdGlvbnMgPyBtZXRhLmRhdGFzZXQub3B0aW9ucy5zcGFuR2FwcyA6IG51bGwgOiBudWxsO1xuICAgICAgICBjb25zdCBheGlzID0gaVNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHsgbWluICwgbWF4ICwgbWluRGVmaW5lZCAsIG1heERlZmluZWQgIH0gPSBpU2NhbGUuZ2V0VXNlckJvdW5kcygpO1xuICAgICAgICBpZiAobWluRGVmaW5lZCkge1xuICAgICAgICAgICAgc3RhcnQgPSBNYXRoLm1pbigvLyBAdHMtZXhwZWN0LWVycm9yIE5lZWQgdG8gdHlwZSBfcGFyc2VkXG4gICAgICAgICAgICBfbG9va3VwQnlLZXkoX3BhcnNlZCwgYXhpcywgbWluKS5sbywgLy8gQHRzLWV4cGVjdC1lcnJvciBOZWVkIHRvIGZpeCB0eXBlcyBvbiBfbG9va3VwQnlLZXlcbiAgICAgICAgICAgIGFuaW1hdGlvbnNEaXNhYmxlZCA/IHBvaW50Q291bnQgOiBfbG9va3VwQnlLZXkocG9pbnRzLCBheGlzLCBpU2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShtaW4pKS5sbyk7XG4gICAgICAgICAgICBpZiAoc3BhbkdhcHMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkaXN0YW5jZVRvRGVmaW5lZExvID0gX3BhcnNlZC5zbGljZSgwLCBzdGFydCArIDEpLnJldmVyc2UoKS5maW5kSW5kZXgoKHBvaW50KT0+IWlzTnVsbE9yVW5kZWYocG9pbnRbdlNjYWxlLmF4aXNdKSk7XG4gICAgICAgICAgICAgICAgc3RhcnQgLT0gTWF0aC5tYXgoMCwgZGlzdGFuY2VUb0RlZmluZWRMbyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdGFydCA9IF9saW1pdFZhbHVlKHN0YXJ0LCAwLCBwb2ludENvdW50IC0gMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1heERlZmluZWQpIHtcbiAgICAgICAgICAgIGxldCBlbmQgPSBNYXRoLm1heCgvLyBAdHMtZXhwZWN0LWVycm9yIE5lZWQgdG8gdHlwZSBfcGFyc2VkXG4gICAgICAgICAgICBfbG9va3VwQnlLZXkoX3BhcnNlZCwgaVNjYWxlLmF4aXMsIG1heCwgdHJ1ZSkuaGkgKyAxLCAvLyBAdHMtZXhwZWN0LWVycm9yIE5lZWQgdG8gZml4IHR5cGVzIG9uIF9sb29rdXBCeUtleVxuICAgICAgICAgICAgYW5pbWF0aW9uc0Rpc2FibGVkID8gMCA6IF9sb29rdXBCeUtleShwb2ludHMsIGF4aXMsIGlTY2FsZS5nZXRQaXhlbEZvclZhbHVlKG1heCksIHRydWUpLmhpICsgMSk7XG4gICAgICAgICAgICBpZiAoc3BhbkdhcHMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkaXN0YW5jZVRvRGVmaW5lZEhpID0gX3BhcnNlZC5zbGljZShlbmQgLSAxKS5maW5kSW5kZXgoKHBvaW50KT0+IWlzTnVsbE9yVW5kZWYocG9pbnRbdlNjYWxlLmF4aXNdKSk7XG4gICAgICAgICAgICAgICAgZW5kICs9IE1hdGgubWF4KDAsIGRpc3RhbmNlVG9EZWZpbmVkSGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY291bnQgPSBfbGltaXRWYWx1ZShlbmQsIHN0YXJ0LCBwb2ludENvdW50KSAtIHN0YXJ0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY291bnQgPSBwb2ludENvdW50IC0gc3RhcnQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQsXG4gICAgICAgIGNvdW50XG4gICAgfTtcbn1cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBzY2FsZSByYW5nZXMgaGF2ZSBjaGFuZ2VkLlxuICogQHBhcmFtIHtvYmplY3R9IG1ldGEgLSBkYXRhc2V0IG1ldGEuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX3NjYWxlUmFuZ2VzQ2hhbmdlZChtZXRhKSB7XG4gICAgY29uc3QgeyB4U2NhbGUgLCB5U2NhbGUgLCBfc2NhbGVSYW5nZXMgIH0gPSBtZXRhO1xuICAgIGNvbnN0IG5ld1JhbmdlcyA9IHtcbiAgICAgICAgeG1pbjogeFNjYWxlLm1pbixcbiAgICAgICAgeG1heDogeFNjYWxlLm1heCxcbiAgICAgICAgeW1pbjogeVNjYWxlLm1pbixcbiAgICAgICAgeW1heDogeVNjYWxlLm1heFxuICAgIH07XG4gICAgaWYgKCFfc2NhbGVSYW5nZXMpIHtcbiAgICAgICAgbWV0YS5fc2NhbGVSYW5nZXMgPSBuZXdSYW5nZXM7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCBjaGFuZ2VkID0gX3NjYWxlUmFuZ2VzLnhtaW4gIT09IHhTY2FsZS5taW4gfHwgX3NjYWxlUmFuZ2VzLnhtYXggIT09IHhTY2FsZS5tYXggfHwgX3NjYWxlUmFuZ2VzLnltaW4gIT09IHlTY2FsZS5taW4gfHwgX3NjYWxlUmFuZ2VzLnltYXggIT09IHlTY2FsZS5tYXg7XG4gICAgT2JqZWN0LmFzc2lnbihfc2NhbGVSYW5nZXMsIG5ld1Jhbmdlcyk7XG4gICAgcmV0dXJuIGNoYW5nZWQ7XG59XG5cbmNvbnN0IGF0RWRnZSA9ICh0KT0+dCA9PT0gMCB8fCB0ID09PSAxO1xuY29uc3QgZWxhc3RpY0luID0gKHQsIHMsIHApPT4tKE1hdGgucG93KDIsIDEwICogKHQgLT0gMSkpICogTWF0aC5zaW4oKHQgLSBzKSAqIFRBVSAvIHApKTtcbmNvbnN0IGVsYXN0aWNPdXQgPSAodCwgcywgcCk9Pk1hdGgucG93KDIsIC0xMCAqIHQpICogTWF0aC5zaW4oKHQgLSBzKSAqIFRBVSAvIHApICsgMTtcbi8qKlxuICogRWFzaW5nIGZ1bmN0aW9ucyBhZGFwdGVkIGZyb20gUm9iZXJ0IFBlbm5lcidzIGVhc2luZyBlcXVhdGlvbnMuXG4gKiBAbmFtZXNwYWNlIENoYXJ0LmhlbHBlcnMuZWFzaW5nLmVmZmVjdHNcbiAqIEBzZWUgaHR0cDovL3d3dy5yb2JlcnRwZW5uZXIuY29tL2Vhc2luZy9cbiAqLyBjb25zdCBlZmZlY3RzID0ge1xuICAgIGxpbmVhcjogKHQpPT50LFxuICAgIGVhc2VJblF1YWQ6ICh0KT0+dCAqIHQsXG4gICAgZWFzZU91dFF1YWQ6ICh0KT0+LXQgKiAodCAtIDIpLFxuICAgIGVhc2VJbk91dFF1YWQ6ICh0KT0+KHQgLz0gMC41KSA8IDEgPyAwLjUgKiB0ICogdCA6IC0wLjUgKiAoLS10ICogKHQgLSAyKSAtIDEpLFxuICAgIGVhc2VJbkN1YmljOiAodCk9PnQgKiB0ICogdCxcbiAgICBlYXNlT3V0Q3ViaWM6ICh0KT0+KHQgLT0gMSkgKiB0ICogdCArIDEsXG4gICAgZWFzZUluT3V0Q3ViaWM6ICh0KT0+KHQgLz0gMC41KSA8IDEgPyAwLjUgKiB0ICogdCAqIHQgOiAwLjUgKiAoKHQgLT0gMikgKiB0ICogdCArIDIpLFxuICAgIGVhc2VJblF1YXJ0OiAodCk9PnQgKiB0ICogdCAqIHQsXG4gICAgZWFzZU91dFF1YXJ0OiAodCk9Pi0oKHQgLT0gMSkgKiB0ICogdCAqIHQgLSAxKSxcbiAgICBlYXNlSW5PdXRRdWFydDogKHQpPT4odCAvPSAwLjUpIDwgMSA/IDAuNSAqIHQgKiB0ICogdCAqIHQgOiAtMC41ICogKCh0IC09IDIpICogdCAqIHQgKiB0IC0gMiksXG4gICAgZWFzZUluUXVpbnQ6ICh0KT0+dCAqIHQgKiB0ICogdCAqIHQsXG4gICAgZWFzZU91dFF1aW50OiAodCk9Pih0IC09IDEpICogdCAqIHQgKiB0ICogdCArIDEsXG4gICAgZWFzZUluT3V0UXVpbnQ6ICh0KT0+KHQgLz0gMC41KSA8IDEgPyAwLjUgKiB0ICogdCAqIHQgKiB0ICogdCA6IDAuNSAqICgodCAtPSAyKSAqIHQgKiB0ICogdCAqIHQgKyAyKSxcbiAgICBlYXNlSW5TaW5lOiAodCk9Pi1NYXRoLmNvcyh0ICogSEFMRl9QSSkgKyAxLFxuICAgIGVhc2VPdXRTaW5lOiAodCk9Pk1hdGguc2luKHQgKiBIQUxGX1BJKSxcbiAgICBlYXNlSW5PdXRTaW5lOiAodCk9Pi0wLjUgKiAoTWF0aC5jb3MoUEkgKiB0KSAtIDEpLFxuICAgIGVhc2VJbkV4cG86ICh0KT0+dCA9PT0gMCA/IDAgOiBNYXRoLnBvdygyLCAxMCAqICh0IC0gMSkpLFxuICAgIGVhc2VPdXRFeHBvOiAodCk9PnQgPT09IDEgPyAxIDogLU1hdGgucG93KDIsIC0xMCAqIHQpICsgMSxcbiAgICBlYXNlSW5PdXRFeHBvOiAodCk9PmF0RWRnZSh0KSA/IHQgOiB0IDwgMC41ID8gMC41ICogTWF0aC5wb3coMiwgMTAgKiAodCAqIDIgLSAxKSkgOiAwLjUgKiAoLU1hdGgucG93KDIsIC0xMCAqICh0ICogMiAtIDEpKSArIDIpLFxuICAgIGVhc2VJbkNpcmM6ICh0KT0+dCA+PSAxID8gdCA6IC0oTWF0aC5zcXJ0KDEgLSB0ICogdCkgLSAxKSxcbiAgICBlYXNlT3V0Q2lyYzogKHQpPT5NYXRoLnNxcnQoMSAtICh0IC09IDEpICogdCksXG4gICAgZWFzZUluT3V0Q2lyYzogKHQpPT4odCAvPSAwLjUpIDwgMSA/IC0wLjUgKiAoTWF0aC5zcXJ0KDEgLSB0ICogdCkgLSAxKSA6IDAuNSAqIChNYXRoLnNxcnQoMSAtICh0IC09IDIpICogdCkgKyAxKSxcbiAgICBlYXNlSW5FbGFzdGljOiAodCk9PmF0RWRnZSh0KSA/IHQgOiBlbGFzdGljSW4odCwgMC4wNzUsIDAuMyksXG4gICAgZWFzZU91dEVsYXN0aWM6ICh0KT0+YXRFZGdlKHQpID8gdCA6IGVsYXN0aWNPdXQodCwgMC4wNzUsIDAuMyksXG4gICAgZWFzZUluT3V0RWxhc3RpYyAodCkge1xuICAgICAgICBjb25zdCBzID0gMC4xMTI1O1xuICAgICAgICBjb25zdCBwID0gMC40NTtcbiAgICAgICAgcmV0dXJuIGF0RWRnZSh0KSA/IHQgOiB0IDwgMC41ID8gMC41ICogZWxhc3RpY0luKHQgKiAyLCBzLCBwKSA6IDAuNSArIDAuNSAqIGVsYXN0aWNPdXQodCAqIDIgLSAxLCBzLCBwKTtcbiAgICB9LFxuICAgIGVhc2VJbkJhY2sgKHQpIHtcbiAgICAgICAgY29uc3QgcyA9IDEuNzAxNTg7XG4gICAgICAgIHJldHVybiB0ICogdCAqICgocyArIDEpICogdCAtIHMpO1xuICAgIH0sXG4gICAgZWFzZU91dEJhY2sgKHQpIHtcbiAgICAgICAgY29uc3QgcyA9IDEuNzAxNTg7XG4gICAgICAgIHJldHVybiAodCAtPSAxKSAqIHQgKiAoKHMgKyAxKSAqIHQgKyBzKSArIDE7XG4gICAgfSxcbiAgICBlYXNlSW5PdXRCYWNrICh0KSB7XG4gICAgICAgIGxldCBzID0gMS43MDE1ODtcbiAgICAgICAgaWYgKCh0IC89IDAuNSkgPCAxKSB7XG4gICAgICAgICAgICByZXR1cm4gMC41ICogKHQgKiB0ICogKCgocyAqPSAxLjUyNSkgKyAxKSAqIHQgLSBzKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDAuNSAqICgodCAtPSAyKSAqIHQgKiAoKChzICo9IDEuNTI1KSArIDEpICogdCArIHMpICsgMik7XG4gICAgfSxcbiAgICBlYXNlSW5Cb3VuY2U6ICh0KT0+MSAtIGVmZmVjdHMuZWFzZU91dEJvdW5jZSgxIC0gdCksXG4gICAgZWFzZU91dEJvdW5jZSAodCkge1xuICAgICAgICBjb25zdCBtID0gNy41NjI1O1xuICAgICAgICBjb25zdCBkID0gMi43NTtcbiAgICAgICAgaWYgKHQgPCAxIC8gZCkge1xuICAgICAgICAgICAgcmV0dXJuIG0gKiB0ICogdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodCA8IDIgLyBkKSB7XG4gICAgICAgICAgICByZXR1cm4gbSAqICh0IC09IDEuNSAvIGQpICogdCArIDAuNzU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHQgPCAyLjUgLyBkKSB7XG4gICAgICAgICAgICByZXR1cm4gbSAqICh0IC09IDIuMjUgLyBkKSAqIHQgKyAwLjkzNzU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG0gKiAodCAtPSAyLjYyNSAvIGQpICogdCArIDAuOTg0Mzc1O1xuICAgIH0sXG4gICAgZWFzZUluT3V0Qm91bmNlOiAodCk9PnQgPCAwLjUgPyBlZmZlY3RzLmVhc2VJbkJvdW5jZSh0ICogMikgKiAwLjUgOiBlZmZlY3RzLmVhc2VPdXRCb3VuY2UodCAqIDIgLSAxKSAqIDAuNSArIDAuNVxufTtcblxuZnVuY3Rpb24gaXNQYXR0ZXJuT3JHcmFkaWVudCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICByZXR1cm4gdHlwZSA9PT0gJ1tvYmplY3QgQ2FudmFzUGF0dGVybl0nIHx8IHR5cGUgPT09ICdbb2JqZWN0IENhbnZhc0dyYWRpZW50XSc7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGNvbG9yKHZhbHVlKSB7XG4gICAgcmV0dXJuIGlzUGF0dGVybk9yR3JhZGllbnQodmFsdWUpID8gdmFsdWUgOiBuZXcgQ29sb3IodmFsdWUpO1xufVxuZnVuY3Rpb24gZ2V0SG92ZXJDb2xvcih2YWx1ZSkge1xuICAgIHJldHVybiBpc1BhdHRlcm5PckdyYWRpZW50KHZhbHVlKSA/IHZhbHVlIDogbmV3IENvbG9yKHZhbHVlKS5zYXR1cmF0ZSgwLjUpLmRhcmtlbigwLjEpLmhleFN0cmluZygpO1xufVxuXG5jb25zdCBudW1iZXJzID0gW1xuICAgICd4JyxcbiAgICAneScsXG4gICAgJ2JvcmRlcldpZHRoJyxcbiAgICAncmFkaXVzJyxcbiAgICAndGVuc2lvbidcbl07XG5jb25zdCBjb2xvcnMgPSBbXG4gICAgJ2NvbG9yJyxcbiAgICAnYm9yZGVyQ29sb3InLFxuICAgICdiYWNrZ3JvdW5kQ29sb3InXG5dO1xuZnVuY3Rpb24gYXBwbHlBbmltYXRpb25zRGVmYXVsdHMoZGVmYXVsdHMpIHtcbiAgICBkZWZhdWx0cy5zZXQoJ2FuaW1hdGlvbicsIHtcbiAgICAgICAgZGVsYXk6IHVuZGVmaW5lZCxcbiAgICAgICAgZHVyYXRpb246IDEwMDAsXG4gICAgICAgIGVhc2luZzogJ2Vhc2VPdXRRdWFydCcsXG4gICAgICAgIGZuOiB1bmRlZmluZWQsXG4gICAgICAgIGZyb206IHVuZGVmaW5lZCxcbiAgICAgICAgbG9vcDogdW5kZWZpbmVkLFxuICAgICAgICB0bzogdW5kZWZpbmVkLFxuICAgICAgICB0eXBlOiB1bmRlZmluZWRcbiAgICB9KTtcbiAgICBkZWZhdWx0cy5kZXNjcmliZSgnYW5pbWF0aW9uJywge1xuICAgICAgICBfZmFsbGJhY2s6IGZhbHNlLFxuICAgICAgICBfaW5kZXhhYmxlOiBmYWxzZSxcbiAgICAgICAgX3NjcmlwdGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ29uUHJvZ3Jlc3MnICYmIG5hbWUgIT09ICdvbkNvbXBsZXRlJyAmJiBuYW1lICE9PSAnZm4nXG4gICAgfSk7XG4gICAgZGVmYXVsdHMuc2V0KCdhbmltYXRpb25zJywge1xuICAgICAgICBjb2xvcnM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiBjb2xvcnNcbiAgICAgICAgfSxcbiAgICAgICAgbnVtYmVyczoge1xuICAgICAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiBudW1iZXJzXG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBkZWZhdWx0cy5kZXNjcmliZSgnYW5pbWF0aW9ucycsIHtcbiAgICAgICAgX2ZhbGxiYWNrOiAnYW5pbWF0aW9uJ1xuICAgIH0pO1xuICAgIGRlZmF1bHRzLnNldCgndHJhbnNpdGlvbnMnLCB7XG4gICAgICAgIGFjdGl2ZToge1xuICAgICAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb246IDQwMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICByZXNpemU6IHtcbiAgICAgICAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNob3c6IHtcbiAgICAgICAgICAgIGFuaW1hdGlvbnM6IHtcbiAgICAgICAgICAgICAgICBjb2xvcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogJ3RyYW5zcGFyZW50J1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBoaWRlOiB7XG4gICAgICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICAgICAgY29sb3JzOiB7XG4gICAgICAgICAgICAgICAgICAgIHRvOiAndHJhbnNwYXJlbnQnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgICAgICAgICAgZWFzaW5nOiAnbGluZWFyJyxcbiAgICAgICAgICAgICAgICAgICAgZm46ICh2KT0+diB8IDBcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYXBwbHlMYXlvdXRzRGVmYXVsdHMoZGVmYXVsdHMpIHtcbiAgICBkZWZhdWx0cy5zZXQoJ2xheW91dCcsIHtcbiAgICAgICAgYXV0b1BhZGRpbmc6IHRydWUsXG4gICAgICAgIHBhZGRpbmc6IHtcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIHJpZ2h0OiAwLFxuICAgICAgICAgICAgYm90dG9tOiAwLFxuICAgICAgICAgICAgbGVmdDogMFxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmNvbnN0IGludGxDYWNoZSA9IG5ldyBNYXAoKTtcbmZ1bmN0aW9uIGdldE51bWJlckZvcm1hdChsb2NhbGUsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICBjb25zdCBjYWNoZUtleSA9IGxvY2FsZSArIEpTT04uc3RyaW5naWZ5KG9wdGlvbnMpO1xuICAgIGxldCBmb3JtYXR0ZXIgPSBpbnRsQ2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICBpZiAoIWZvcm1hdHRlcikge1xuICAgICAgICBmb3JtYXR0ZXIgPSBuZXcgSW50bC5OdW1iZXJGb3JtYXQobG9jYWxlLCBvcHRpb25zKTtcbiAgICAgICAgaW50bENhY2hlLnNldChjYWNoZUtleSwgZm9ybWF0dGVyKTtcbiAgICB9XG4gICAgcmV0dXJuIGZvcm1hdHRlcjtcbn1cbmZ1bmN0aW9uIGZvcm1hdE51bWJlcihudW0sIGxvY2FsZSwgb3B0aW9ucykge1xuICAgIHJldHVybiBnZXROdW1iZXJGb3JtYXQobG9jYWxlLCBvcHRpb25zKS5mb3JtYXQobnVtKTtcbn1cblxuY29uc3QgZm9ybWF0dGVycyA9IHtcbiB2YWx1ZXMgKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBpc0FycmF5KHZhbHVlKSA/ICB2YWx1ZSA6ICcnICsgdmFsdWU7XG4gICAgfSxcbiBudW1lcmljICh0aWNrVmFsdWUsIGluZGV4LCB0aWNrcykge1xuICAgICAgICBpZiAodGlja1ZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gJzAnO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxvY2FsZSA9IHRoaXMuY2hhcnQub3B0aW9ucy5sb2NhbGU7XG4gICAgICAgIGxldCBub3RhdGlvbjtcbiAgICAgICAgbGV0IGRlbHRhID0gdGlja1ZhbHVlO1xuICAgICAgICBpZiAodGlja3MubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgY29uc3QgbWF4VGljayA9IE1hdGgubWF4KE1hdGguYWJzKHRpY2tzWzBdLnZhbHVlKSwgTWF0aC5hYnModGlja3NbdGlja3MubGVuZ3RoIC0gMV0udmFsdWUpKTtcbiAgICAgICAgICAgIGlmIChtYXhUaWNrIDwgMWUtNCB8fCBtYXhUaWNrID4gMWUrMTUpIHtcbiAgICAgICAgICAgICAgICBub3RhdGlvbiA9ICdzY2llbnRpZmljJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbHRhID0gY2FsY3VsYXRlRGVsdGEodGlja1ZhbHVlLCB0aWNrcyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbG9nRGVsdGEgPSBsb2cxMChNYXRoLmFicyhkZWx0YSkpO1xuICAgICAgICBjb25zdCBudW1EZWNpbWFsID0gaXNOYU4obG9nRGVsdGEpID8gMSA6IE1hdGgubWF4KE1hdGgubWluKC0xICogTWF0aC5mbG9vcihsb2dEZWx0YSksIDIwKSwgMCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBub3RhdGlvbixcbiAgICAgICAgICAgIG1pbmltdW1GcmFjdGlvbkRpZ2l0czogbnVtRGVjaW1hbCxcbiAgICAgICAgICAgIG1heGltdW1GcmFjdGlvbkRpZ2l0czogbnVtRGVjaW1hbFxuICAgICAgICB9O1xuICAgICAgICBPYmplY3QuYXNzaWduKG9wdGlvbnMsIHRoaXMub3B0aW9ucy50aWNrcy5mb3JtYXQpO1xuICAgICAgICByZXR1cm4gZm9ybWF0TnVtYmVyKHRpY2tWYWx1ZSwgbG9jYWxlLCBvcHRpb25zKTtcbiAgICB9LFxuIGxvZ2FyaXRobWljICh0aWNrVmFsdWUsIGluZGV4LCB0aWNrcykge1xuICAgICAgICBpZiAodGlja1ZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gJzAnO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJlbWFpbiA9IHRpY2tzW2luZGV4XS5zaWduaWZpY2FuZCB8fCB0aWNrVmFsdWUgLyBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihsb2cxMCh0aWNrVmFsdWUpKSk7XG4gICAgICAgIGlmIChbXG4gICAgICAgICAgICAxLFxuICAgICAgICAgICAgMixcbiAgICAgICAgICAgIDMsXG4gICAgICAgICAgICA1LFxuICAgICAgICAgICAgMTAsXG4gICAgICAgICAgICAxNVxuICAgICAgICBdLmluY2x1ZGVzKHJlbWFpbikgfHwgaW5kZXggPiAwLjggKiB0aWNrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZXJzLm51bWVyaWMuY2FsbCh0aGlzLCB0aWNrVmFsdWUsIGluZGV4LCB0aWNrcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbn07XG5mdW5jdGlvbiBjYWxjdWxhdGVEZWx0YSh0aWNrVmFsdWUsIHRpY2tzKSB7XG4gICAgbGV0IGRlbHRhID0gdGlja3MubGVuZ3RoID4gMyA/IHRpY2tzWzJdLnZhbHVlIC0gdGlja3NbMV0udmFsdWUgOiB0aWNrc1sxXS52YWx1ZSAtIHRpY2tzWzBdLnZhbHVlO1xuICAgIGlmIChNYXRoLmFicyhkZWx0YSkgPj0gMSAmJiB0aWNrVmFsdWUgIT09IE1hdGguZmxvb3IodGlja1ZhbHVlKSkge1xuICAgICAgICBkZWx0YSA9IHRpY2tWYWx1ZSAtIE1hdGguZmxvb3IodGlja1ZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIGRlbHRhO1xufVxuIHZhciBUaWNrcyA9IHtcbiAgICBmb3JtYXR0ZXJzXG59O1xuXG5mdW5jdGlvbiBhcHBseVNjYWxlRGVmYXVsdHMoZGVmYXVsdHMpIHtcbiAgICBkZWZhdWx0cy5zZXQoJ3NjYWxlJywge1xuICAgICAgICBkaXNwbGF5OiB0cnVlLFxuICAgICAgICBvZmZzZXQ6IGZhbHNlLFxuICAgICAgICByZXZlcnNlOiBmYWxzZSxcbiAgICAgICAgYmVnaW5BdFplcm86IGZhbHNlLFxuIGJvdW5kczogJ3RpY2tzJyxcbiAgICAgICAgY2xpcDogdHJ1ZSxcbiBncmFjZTogMCxcbiAgICAgICAgZ3JpZDoge1xuICAgICAgICAgICAgZGlzcGxheTogdHJ1ZSxcbiAgICAgICAgICAgIGxpbmVXaWR0aDogMSxcbiAgICAgICAgICAgIGRyYXdPbkNoYXJ0QXJlYTogdHJ1ZSxcbiAgICAgICAgICAgIGRyYXdUaWNrczogdHJ1ZSxcbiAgICAgICAgICAgIHRpY2tMZW5ndGg6IDgsXG4gICAgICAgICAgICB0aWNrV2lkdGg6IChfY3R4LCBvcHRpb25zKT0+b3B0aW9ucy5saW5lV2lkdGgsXG4gICAgICAgICAgICB0aWNrQ29sb3I6IChfY3R4LCBvcHRpb25zKT0+b3B0aW9ucy5jb2xvcixcbiAgICAgICAgICAgIG9mZnNldDogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgYm9yZGVyOiB7XG4gICAgICAgICAgICBkaXNwbGF5OiB0cnVlLFxuICAgICAgICAgICAgZGFzaDogW10sXG4gICAgICAgICAgICBkYXNoT2Zmc2V0OiAwLjAsXG4gICAgICAgICAgICB3aWR0aDogMVxuICAgICAgICB9LFxuICAgICAgICB0aXRsZToge1xuICAgICAgICAgICAgZGlzcGxheTogZmFsc2UsXG4gICAgICAgICAgICB0ZXh0OiAnJyxcbiAgICAgICAgICAgIHBhZGRpbmc6IHtcbiAgICAgICAgICAgICAgICB0b3A6IDQsXG4gICAgICAgICAgICAgICAgYm90dG9tOiA0XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHRpY2tzOiB7XG4gICAgICAgICAgICBtaW5Sb3RhdGlvbjogMCxcbiAgICAgICAgICAgIG1heFJvdGF0aW9uOiA1MCxcbiAgICAgICAgICAgIG1pcnJvcjogZmFsc2UsXG4gICAgICAgICAgICB0ZXh0U3Ryb2tlV2lkdGg6IDAsXG4gICAgICAgICAgICB0ZXh0U3Ryb2tlQ29sb3I6ICcnLFxuICAgICAgICAgICAgcGFkZGluZzogMyxcbiAgICAgICAgICAgIGRpc3BsYXk6IHRydWUsXG4gICAgICAgICAgICBhdXRvU2tpcDogdHJ1ZSxcbiAgICAgICAgICAgIGF1dG9Ta2lwUGFkZGluZzogMyxcbiAgICAgICAgICAgIGxhYmVsT2Zmc2V0OiAwLFxuICAgICAgICAgICAgY2FsbGJhY2s6IFRpY2tzLmZvcm1hdHRlcnMudmFsdWVzLFxuICAgICAgICAgICAgbWlub3I6IHt9LFxuICAgICAgICAgICAgbWFqb3I6IHt9LFxuICAgICAgICAgICAgYWxpZ246ICdjZW50ZXInLFxuICAgICAgICAgICAgY3Jvc3NBbGlnbjogJ25lYXInLFxuICAgICAgICAgICAgc2hvd0xhYmVsQmFja2Ryb3A6IGZhbHNlLFxuICAgICAgICAgICAgYmFja2Ryb3BDb2xvcjogJ3JnYmEoMjU1LCAyNTUsIDI1NSwgMC43NSknLFxuICAgICAgICAgICAgYmFja2Ryb3BQYWRkaW5nOiAyXG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBkZWZhdWx0cy5yb3V0ZSgnc2NhbGUudGlja3MnLCAnY29sb3InLCAnJywgJ2NvbG9yJyk7XG4gICAgZGVmYXVsdHMucm91dGUoJ3NjYWxlLmdyaWQnLCAnY29sb3InLCAnJywgJ2JvcmRlckNvbG9yJyk7XG4gICAgZGVmYXVsdHMucm91dGUoJ3NjYWxlLmJvcmRlcicsICdjb2xvcicsICcnLCAnYm9yZGVyQ29sb3InKTtcbiAgICBkZWZhdWx0cy5yb3V0ZSgnc2NhbGUudGl0bGUnLCAnY29sb3InLCAnJywgJ2NvbG9yJyk7XG4gICAgZGVmYXVsdHMuZGVzY3JpYmUoJ3NjYWxlJywge1xuICAgICAgICBfZmFsbGJhY2s6IGZhbHNlLFxuICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT4hbmFtZS5zdGFydHNXaXRoKCdiZWZvcmUnKSAmJiAhbmFtZS5zdGFydHNXaXRoKCdhZnRlcicpICYmIG5hbWUgIT09ICdjYWxsYmFjaycgJiYgbmFtZSAhPT0gJ3BhcnNlcicsXG4gICAgICAgIF9pbmRleGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ2JvcmRlckRhc2gnICYmIG5hbWUgIT09ICd0aWNrQm9yZGVyRGFzaCcgJiYgbmFtZSAhPT0gJ2Rhc2gnXG4gICAgfSk7XG4gICAgZGVmYXVsdHMuZGVzY3JpYmUoJ3NjYWxlcycsIHtcbiAgICAgICAgX2ZhbGxiYWNrOiAnc2NhbGUnXG4gICAgfSk7XG4gICAgZGVmYXVsdHMuZGVzY3JpYmUoJ3NjYWxlLnRpY2tzJywge1xuICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnYmFja2Ryb3BQYWRkaW5nJyAmJiBuYW1lICE9PSAnY2FsbGJhY2snLFxuICAgICAgICBfaW5kZXhhYmxlOiAobmFtZSk9Pm5hbWUgIT09ICdiYWNrZHJvcFBhZGRpbmcnXG4gICAgfSk7XG59XG5cbmNvbnN0IG92ZXJyaWRlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5jb25zdCBkZXNjcmlwdG9ycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gZnVuY3Rpb24gZ2V0U2NvcGUkMShub2RlLCBrZXkpIHtcbiAgICBpZiAoIWtleSkge1xuICAgICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG4gICAgY29uc3Qga2V5cyA9IGtleS5zcGxpdCgnLicpO1xuICAgIGZvcihsZXQgaSA9IDAsIG4gPSBrZXlzLmxlbmd0aDsgaSA8IG47ICsraSl7XG4gICAgICAgIGNvbnN0IGsgPSBrZXlzW2ldO1xuICAgICAgICBub2RlID0gbm9kZVtrXSB8fCAobm9kZVtrXSA9IE9iamVjdC5jcmVhdGUobnVsbCkpO1xuICAgIH1cbiAgICByZXR1cm4gbm9kZTtcbn1cbmZ1bmN0aW9uIHNldChyb290LCBzY29wZSwgdmFsdWVzKSB7XG4gICAgaWYgKHR5cGVvZiBzY29wZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIG1lcmdlKGdldFNjb3BlJDEocm9vdCwgc2NvcGUpLCB2YWx1ZXMpO1xuICAgIH1cbiAgICByZXR1cm4gbWVyZ2UoZ2V0U2NvcGUkMShyb290LCAnJyksIHNjb3BlKTtcbn1cbiBjbGFzcyBEZWZhdWx0cyB7XG4gICAgY29uc3RydWN0b3IoX2Rlc2NyaXB0b3JzLCBfYXBwbGllcnMpe1xuICAgICAgICB0aGlzLmFuaW1hdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSAncmdiYSgwLDAsMCwwLjEpJztcbiAgICAgICAgdGhpcy5ib3JkZXJDb2xvciA9ICdyZ2JhKDAsMCwwLDAuMSknO1xuICAgICAgICB0aGlzLmNvbG9yID0gJyM2NjYnO1xuICAgICAgICB0aGlzLmRhdGFzZXRzID0ge307XG4gICAgICAgIHRoaXMuZGV2aWNlUGl4ZWxSYXRpbyA9IChjb250ZXh0KT0+Y29udGV4dC5jaGFydC5wbGF0Zm9ybS5nZXREZXZpY2VQaXhlbFJhdGlvKCk7XG4gICAgICAgIHRoaXMuZWxlbWVudHMgPSB7fTtcbiAgICAgICAgdGhpcy5ldmVudHMgPSBbXG4gICAgICAgICAgICAnbW91c2Vtb3ZlJyxcbiAgICAgICAgICAgICdtb3VzZW91dCcsXG4gICAgICAgICAgICAnY2xpY2snLFxuICAgICAgICAgICAgJ3RvdWNoc3RhcnQnLFxuICAgICAgICAgICAgJ3RvdWNobW92ZSdcbiAgICAgICAgXTtcbiAgICAgICAgdGhpcy5mb250ID0ge1xuICAgICAgICAgICAgZmFtaWx5OiBcIidIZWx2ZXRpY2EgTmV1ZScsICdIZWx2ZXRpY2EnLCAnQXJpYWwnLCBzYW5zLXNlcmlmXCIsXG4gICAgICAgICAgICBzaXplOiAxMixcbiAgICAgICAgICAgIHN0eWxlOiAnbm9ybWFsJyxcbiAgICAgICAgICAgIGxpbmVIZWlnaHQ6IDEuMixcbiAgICAgICAgICAgIHdlaWdodDogbnVsbFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhvdmVyID0ge307XG4gICAgICAgIHRoaXMuaG92ZXJCYWNrZ3JvdW5kQ29sb3IgPSAoY3R4LCBvcHRpb25zKT0+Z2V0SG92ZXJDb2xvcihvcHRpb25zLmJhY2tncm91bmRDb2xvcik7XG4gICAgICAgIHRoaXMuaG92ZXJCb3JkZXJDb2xvciA9IChjdHgsIG9wdGlvbnMpPT5nZXRIb3ZlckNvbG9yKG9wdGlvbnMuYm9yZGVyQ29sb3IpO1xuICAgICAgICB0aGlzLmhvdmVyQ29sb3IgPSAoY3R4LCBvcHRpb25zKT0+Z2V0SG92ZXJDb2xvcihvcHRpb25zLmNvbG9yKTtcbiAgICAgICAgdGhpcy5pbmRleEF4aXMgPSAneCc7XG4gICAgICAgIHRoaXMuaW50ZXJhY3Rpb24gPSB7XG4gICAgICAgICAgICBtb2RlOiAnbmVhcmVzdCcsXG4gICAgICAgICAgICBpbnRlcnNlY3Q6IHRydWUsXG4gICAgICAgICAgICBpbmNsdWRlSW52aXNpYmxlOiBmYWxzZVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLm1haW50YWluQXNwZWN0UmF0aW8gPSB0cnVlO1xuICAgICAgICB0aGlzLm9uSG92ZXIgPSBudWxsO1xuICAgICAgICB0aGlzLm9uQ2xpY2sgPSBudWxsO1xuICAgICAgICB0aGlzLnBhcnNpbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLnBsdWdpbnMgPSB7fTtcbiAgICAgICAgdGhpcy5yZXNwb25zaXZlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zY2FsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zY2FsZXMgPSB7fTtcbiAgICAgICAgdGhpcy5zaG93TGluZSA9IHRydWU7XG4gICAgICAgIHRoaXMuZHJhd0FjdGl2ZUVsZW1lbnRzT25Ub3AgPSB0cnVlO1xuICAgICAgICB0aGlzLmRlc2NyaWJlKF9kZXNjcmlwdG9ycyk7XG4gICAgICAgIHRoaXMuYXBwbHkoX2FwcGxpZXJzKTtcbiAgICB9XG4gc2V0KHNjb3BlLCB2YWx1ZXMpIHtcbiAgICAgICAgcmV0dXJuIHNldCh0aGlzLCBzY29wZSwgdmFsdWVzKTtcbiAgICB9XG4gZ2V0KHNjb3BlKSB7XG4gICAgICAgIHJldHVybiBnZXRTY29wZSQxKHRoaXMsIHNjb3BlKTtcbiAgICB9XG4gZGVzY3JpYmUoc2NvcGUsIHZhbHVlcykge1xuICAgICAgICByZXR1cm4gc2V0KGRlc2NyaXB0b3JzLCBzY29wZSwgdmFsdWVzKTtcbiAgICB9XG4gICAgb3ZlcnJpZGUoc2NvcGUsIHZhbHVlcykge1xuICAgICAgICByZXR1cm4gc2V0KG92ZXJyaWRlcywgc2NvcGUsIHZhbHVlcyk7XG4gICAgfVxuIHJvdXRlKHNjb3BlLCBuYW1lLCB0YXJnZXRTY29wZSwgdGFyZ2V0TmFtZSkge1xuICAgICAgICBjb25zdCBzY29wZU9iamVjdCA9IGdldFNjb3BlJDEodGhpcywgc2NvcGUpO1xuICAgICAgICBjb25zdCB0YXJnZXRTY29wZU9iamVjdCA9IGdldFNjb3BlJDEodGhpcywgdGFyZ2V0U2NvcGUpO1xuICAgICAgICBjb25zdCBwcml2YXRlTmFtZSA9ICdfJyArIG5hbWU7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHNjb3BlT2JqZWN0LCB7XG4gICAgICAgICAgICBbcHJpdmF0ZU5hbWVdOiB7XG4gICAgICAgICAgICAgICAgdmFsdWU6IHNjb3BlT2JqZWN0W25hbWVdLFxuICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW25hbWVdOiB7XG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBnZXQgKCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbCA9IHRoaXNbcHJpdmF0ZU5hbWVdO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXQgPSB0YXJnZXRTY29wZU9iamVjdFt0YXJnZXROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KGxvY2FsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHRhcmdldCwgbG9jYWwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZU9yRGVmYXVsdChsb2NhbCwgdGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldCAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpc1twcml2YXRlTmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBhcHBseShhcHBsaWVycykge1xuICAgICAgICBhcHBsaWVycy5mb3JFYWNoKChhcHBseSk9PmFwcGx5KHRoaXMpKTtcbiAgICB9XG59XG52YXIgZGVmYXVsdHMgPSAvKiAjX19QVVJFX18gKi8gbmV3IERlZmF1bHRzKHtcbiAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT4hbmFtZS5zdGFydHNXaXRoKCdvbicpLFxuICAgIF9pbmRleGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ2V2ZW50cycsXG4gICAgaG92ZXI6IHtcbiAgICAgICAgX2ZhbGxiYWNrOiAnaW50ZXJhY3Rpb24nXG4gICAgfSxcbiAgICBpbnRlcmFjdGlvbjoge1xuICAgICAgICBfc2NyaXB0YWJsZTogZmFsc2UsXG4gICAgICAgIF9pbmRleGFibGU6IGZhbHNlXG4gICAgfVxufSwgW1xuICAgIGFwcGx5QW5pbWF0aW9uc0RlZmF1bHRzLFxuICAgIGFwcGx5TGF5b3V0c0RlZmF1bHRzLFxuICAgIGFwcGx5U2NhbGVEZWZhdWx0c1xuXSk7XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIGZvbnQgb2JqZWN0IGludG8gYSBDU1MgZm9udCBzdHJpbmcuXG4gKiBAcGFyYW0gZm9udCAtIEEgZm9udCBvYmplY3QuXG4gKiBAcmV0dXJuIFRoZSBDU1MgZm9udCBzdHJpbmcuIFNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9DU1MvZm9udFxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiB0b0ZvbnRTdHJpbmcoZm9udCkge1xuICAgIGlmICghZm9udCB8fCBpc051bGxPclVuZGVmKGZvbnQuc2l6ZSkgfHwgaXNOdWxsT3JVbmRlZihmb250LmZhbWlseSkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiAoZm9udC5zdHlsZSA/IGZvbnQuc3R5bGUgKyAnICcgOiAnJykgKyAoZm9udC53ZWlnaHQgPyBmb250LndlaWdodCArICcgJyA6ICcnKSArIGZvbnQuc2l6ZSArICdweCAnICsgZm9udC5mYW1pbHk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX21lYXN1cmVUZXh0KGN0eCwgZGF0YSwgZ2MsIGxvbmdlc3QsIHN0cmluZykge1xuICAgIGxldCB0ZXh0V2lkdGggPSBkYXRhW3N0cmluZ107XG4gICAgaWYgKCF0ZXh0V2lkdGgpIHtcbiAgICAgICAgdGV4dFdpZHRoID0gZGF0YVtzdHJpbmddID0gY3R4Lm1lYXN1cmVUZXh0KHN0cmluZykud2lkdGg7XG4gICAgICAgIGdjLnB1c2goc3RyaW5nKTtcbiAgICB9XG4gICAgaWYgKHRleHRXaWR0aCA+IGxvbmdlc3QpIHtcbiAgICAgICAgbG9uZ2VzdCA9IHRleHRXaWR0aDtcbiAgICB9XG4gICAgcmV0dXJuIGxvbmdlc3Q7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmZ1bmN0aW9uIF9sb25nZXN0VGV4dChjdHgsIGZvbnQsIGFycmF5T2ZUaGluZ3MsIGNhY2hlKSB7XG4gICAgY2FjaGUgPSBjYWNoZSB8fCB7fTtcbiAgICBsZXQgZGF0YSA9IGNhY2hlLmRhdGEgPSBjYWNoZS5kYXRhIHx8IHt9O1xuICAgIGxldCBnYyA9IGNhY2hlLmdhcmJhZ2VDb2xsZWN0ID0gY2FjaGUuZ2FyYmFnZUNvbGxlY3QgfHwgW107XG4gICAgaWYgKGNhY2hlLmZvbnQgIT09IGZvbnQpIHtcbiAgICAgICAgZGF0YSA9IGNhY2hlLmRhdGEgPSB7fTtcbiAgICAgICAgZ2MgPSBjYWNoZS5nYXJiYWdlQ29sbGVjdCA9IFtdO1xuICAgICAgICBjYWNoZS5mb250ID0gZm9udDtcbiAgICB9XG4gICAgY3R4LnNhdmUoKTtcbiAgICBjdHguZm9udCA9IGZvbnQ7XG4gICAgbGV0IGxvbmdlc3QgPSAwO1xuICAgIGNvbnN0IGlsZW4gPSBhcnJheU9mVGhpbmdzLmxlbmd0aDtcbiAgICBsZXQgaSwgaiwgamxlbiwgdGhpbmcsIG5lc3RlZFRoaW5nO1xuICAgIGZvcihpID0gMDsgaSA8IGlsZW47IGkrKyl7XG4gICAgICAgIHRoaW5nID0gYXJyYXlPZlRoaW5nc1tpXTtcbiAgICAgICAgLy8gVW5kZWZpbmVkIHN0cmluZ3MgYW5kIGFycmF5cyBzaG91bGQgbm90IGJlIG1lYXN1cmVkXG4gICAgICAgIGlmICh0aGluZyAhPT0gdW5kZWZpbmVkICYmIHRoaW5nICE9PSBudWxsICYmICFpc0FycmF5KHRoaW5nKSkge1xuICAgICAgICAgICAgbG9uZ2VzdCA9IF9tZWFzdXJlVGV4dChjdHgsIGRhdGEsIGdjLCBsb25nZXN0LCB0aGluZyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheSh0aGluZykpIHtcbiAgICAgICAgICAgIC8vIGlmIGl0IGlzIGFuIGFycmF5IGxldHMgbWVhc3VyZSBlYWNoIGVsZW1lbnRcbiAgICAgICAgICAgIC8vIHRvIGRvIG1heWJlIHNpbXBsaWZ5IHRoaXMgZnVuY3Rpb24gYSBiaXQgc28gd2UgY2FuIGRvIHRoaXMgbW9yZSByZWN1cnNpdmVseT9cbiAgICAgICAgICAgIGZvcihqID0gMCwgamxlbiA9IHRoaW5nLmxlbmd0aDsgaiA8IGpsZW47IGorKyl7XG4gICAgICAgICAgICAgICAgbmVzdGVkVGhpbmcgPSB0aGluZ1tqXTtcbiAgICAgICAgICAgICAgICAvLyBVbmRlZmluZWQgc3RyaW5ncyBhbmQgYXJyYXlzIHNob3VsZCBub3QgYmUgbWVhc3VyZWRcbiAgICAgICAgICAgICAgICBpZiAobmVzdGVkVGhpbmcgIT09IHVuZGVmaW5lZCAmJiBuZXN0ZWRUaGluZyAhPT0gbnVsbCAmJiAhaXNBcnJheShuZXN0ZWRUaGluZykpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9uZ2VzdCA9IF9tZWFzdXJlVGV4dChjdHgsIGRhdGEsIGdjLCBsb25nZXN0LCBuZXN0ZWRUaGluZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgY29uc3QgZ2NMZW4gPSBnYy5sZW5ndGggLyAyO1xuICAgIGlmIChnY0xlbiA+IGFycmF5T2ZUaGluZ3MubGVuZ3RoKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGdjTGVuOyBpKyspe1xuICAgICAgICAgICAgZGVsZXRlIGRhdGFbZ2NbaV1dO1xuICAgICAgICB9XG4gICAgICAgIGdjLnNwbGljZSgwLCBnY0xlbik7XG4gICAgfVxuICAgIHJldHVybiBsb25nZXN0O1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBhbGlnbmVkIHBpeGVsIHZhbHVlIHRvIGF2b2lkIGFudGktYWxpYXNpbmcgYmx1clxuICogQHBhcmFtIGNoYXJ0IC0gVGhlIGNoYXJ0IGluc3RhbmNlLlxuICogQHBhcmFtIHBpeGVsIC0gQSBwaXhlbCB2YWx1ZS5cbiAqIEBwYXJhbSB3aWR0aCAtIFRoZSB3aWR0aCBvZiB0aGUgZWxlbWVudC5cbiAqIEByZXR1cm5zIFRoZSBhbGlnbmVkIHBpeGVsIHZhbHVlLlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfYWxpZ25QaXhlbChjaGFydCwgcGl4ZWwsIHdpZHRoKSB7XG4gICAgY29uc3QgZGV2aWNlUGl4ZWxSYXRpbyA9IGNoYXJ0LmN1cnJlbnREZXZpY2VQaXhlbFJhdGlvO1xuICAgIGNvbnN0IGhhbGZXaWR0aCA9IHdpZHRoICE9PSAwID8gTWF0aC5tYXgod2lkdGggLyAyLCAwLjUpIDogMDtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCgocGl4ZWwgLSBoYWxmV2lkdGgpICogZGV2aWNlUGl4ZWxSYXRpbykgLyBkZXZpY2VQaXhlbFJhdGlvICsgaGFsZldpZHRoO1xufVxuLyoqXG4gKiBDbGVhcnMgdGhlIGVudGlyZSBjYW52YXMuXG4gKi8gZnVuY3Rpb24gY2xlYXJDYW52YXMoY2FudmFzLCBjdHgpIHtcbiAgICBpZiAoIWN0eCAmJiAhY2FudmFzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY3R4ID0gY3R4IHx8IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIGN0eC5zYXZlKCk7XG4gICAgLy8gY2FudmFzLndpZHRoIGFuZCBjYW52YXMuaGVpZ2h0IGRvIG5vdCBjb25zaWRlciB0aGUgY2FudmFzIHRyYW5zZm9ybSxcbiAgICAvLyB3aGlsZSBjbGVhclJlY3QgZG9lc1xuICAgIGN0eC5yZXNldFRyYW5zZm9ybSgpO1xuICAgIGN0eC5jbGVhclJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICBjdHgucmVzdG9yZSgpO1xufVxuZnVuY3Rpb24gZHJhd1BvaW50KGN0eCwgb3B0aW9ucywgeCwgeSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdXNlLWJlZm9yZS1kZWZpbmVcbiAgICBkcmF3UG9pbnRMZWdlbmQoY3R4LCBvcHRpb25zLCB4LCB5LCBudWxsKTtcbn1cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBkcmF3UG9pbnRMZWdlbmQoY3R4LCBvcHRpb25zLCB4LCB5LCB3KSB7XG4gICAgbGV0IHR5cGUsIHhPZmZzZXQsIHlPZmZzZXQsIHNpemUsIGNvcm5lclJhZGl1cywgd2lkdGgsIHhPZmZzZXRXLCB5T2Zmc2V0VztcbiAgICBjb25zdCBzdHlsZSA9IG9wdGlvbnMucG9pbnRTdHlsZTtcbiAgICBjb25zdCByb3RhdGlvbiA9IG9wdGlvbnMucm90YXRpb247XG4gICAgY29uc3QgcmFkaXVzID0gb3B0aW9ucy5yYWRpdXM7XG4gICAgbGV0IHJhZCA9IChyb3RhdGlvbiB8fCAwKSAqIFJBRF9QRVJfREVHO1xuICAgIGlmIChzdHlsZSAmJiB0eXBlb2Ygc3R5bGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHR5cGUgPSBzdHlsZS50b1N0cmluZygpO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ1tvYmplY3QgSFRNTEltYWdlRWxlbWVudF0nIHx8IHR5cGUgPT09ICdbb2JqZWN0IEhUTUxDYW52YXNFbGVtZW50XScpIHtcbiAgICAgICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgICAgICBjdHgudHJhbnNsYXRlKHgsIHkpO1xuICAgICAgICAgICAgY3R4LnJvdGF0ZShyYWQpO1xuICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShzdHlsZSwgLXN0eWxlLndpZHRoIC8gMiwgLXN0eWxlLmhlaWdodCAvIDIsIHN0eWxlLndpZHRoLCBzdHlsZS5oZWlnaHQpO1xuICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoaXNOYU4ocmFkaXVzKSB8fCByYWRpdXMgPD0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBzd2l0Y2goc3R5bGUpe1xuICAgICAgICAvLyBEZWZhdWx0IGluY2x1ZGVzIGNpcmNsZVxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgaWYgKHcpIHtcbiAgICAgICAgICAgICAgICBjdHguZWxsaXBzZSh4LCB5LCB3IC8gMiwgcmFkaXVzLCAwLCAwLCBUQVUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjdHguYXJjKHgsIHksIHJhZGl1cywgMCwgVEFVKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd0cmlhbmdsZSc6XG4gICAgICAgICAgICB3aWR0aCA9IHcgPyB3IC8gMiA6IHJhZGl1cztcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oeCArIE1hdGguc2luKHJhZCkgKiB3aWR0aCwgeSAtIE1hdGguY29zKHJhZCkgKiByYWRpdXMpO1xuICAgICAgICAgICAgcmFkICs9IFRXT19USElSRFNfUEk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggKyBNYXRoLnNpbihyYWQpICogd2lkdGgsIHkgLSBNYXRoLmNvcyhyYWQpICogcmFkaXVzKTtcbiAgICAgICAgICAgIHJhZCArPSBUV09fVEhJUkRTX1BJO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4ICsgTWF0aC5zaW4ocmFkKSAqIHdpZHRoLCB5IC0gTWF0aC5jb3MocmFkKSAqIHJhZGl1cyk7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncmVjdFJvdW5kZWQnOlxuICAgICAgICAgICAgLy8gTk9URTogdGhlIHJvdW5kZWQgcmVjdCBpbXBsZW1lbnRhdGlvbiBjaGFuZ2VkIHRvIHVzZSBgYXJjYCBpbnN0ZWFkIG9mXG4gICAgICAgICAgICAvLyBgcXVhZHJhdGljQ3VydmVUb2Agc2luY2UgaXQgZ2VuZXJhdGVzIGJldHRlciByZXN1bHRzIHdoZW4gcmVjdCBpc1xuICAgICAgICAgICAgLy8gYWxtb3N0IGEgY2lyY2xlLiAwLjUxNiAoaW5zdGVhZCBvZiAwLjUpIHByb2R1Y2VzIHJlc3VsdHMgd2l0aCB2aXN1YWxseVxuICAgICAgICAgICAgLy8gY2xvc2VyIHByb3BvcnRpb24gdG8gdGhlIHByZXZpb3VzIGltcGwgYW5kIGl0IGlzIGluc2NyaWJlZCBpbiB0aGVcbiAgICAgICAgICAgIC8vIGNpcmNsZSB3aXRoIGByYWRpdXNgLiBGb3IgbW9yZSBkZXRhaWxzLCBzZWUgdGhlIGZvbGxvd2luZyBQUnM6XG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vY2hhcnRqcy9DaGFydC5qcy9pc3N1ZXMvNTU5N1xuICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2NoYXJ0anMvQ2hhcnQuanMvaXNzdWVzLzU4NThcbiAgICAgICAgICAgIGNvcm5lclJhZGl1cyA9IHJhZGl1cyAqIDAuNTE2O1xuICAgICAgICAgICAgc2l6ZSA9IHJhZGl1cyAtIGNvcm5lclJhZGl1cztcbiAgICAgICAgICAgIHhPZmZzZXQgPSBNYXRoLmNvcyhyYWQgKyBRVUFSVEVSX1BJKSAqIHNpemU7XG4gICAgICAgICAgICB4T2Zmc2V0VyA9IE1hdGguY29zKHJhZCArIFFVQVJURVJfUEkpICogKHcgPyB3IC8gMiAtIGNvcm5lclJhZGl1cyA6IHNpemUpO1xuICAgICAgICAgICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCArIFFVQVJURVJfUEkpICogc2l6ZTtcbiAgICAgICAgICAgIHlPZmZzZXRXID0gTWF0aC5zaW4ocmFkICsgUVVBUlRFUl9QSSkgKiAodyA/IHcgLyAyIC0gY29ybmVyUmFkaXVzIDogc2l6ZSk7XG4gICAgICAgICAgICBjdHguYXJjKHggLSB4T2Zmc2V0VywgeSAtIHlPZmZzZXQsIGNvcm5lclJhZGl1cywgcmFkIC0gUEksIHJhZCAtIEhBTEZfUEkpO1xuICAgICAgICAgICAgY3R4LmFyYyh4ICsgeU9mZnNldFcsIHkgLSB4T2Zmc2V0LCBjb3JuZXJSYWRpdXMsIHJhZCAtIEhBTEZfUEksIHJhZCk7XG4gICAgICAgICAgICBjdHguYXJjKHggKyB4T2Zmc2V0VywgeSArIHlPZmZzZXQsIGNvcm5lclJhZGl1cywgcmFkLCByYWQgKyBIQUxGX1BJKTtcbiAgICAgICAgICAgIGN0eC5hcmMoeCAtIHlPZmZzZXRXLCB5ICsgeE9mZnNldCwgY29ybmVyUmFkaXVzLCByYWQgKyBIQUxGX1BJLCByYWQgKyBQSSk7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncmVjdCc6XG4gICAgICAgICAgICBpZiAoIXJvdGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgc2l6ZSA9IE1hdGguU1FSVDFfMiAqIHJhZGl1cztcbiAgICAgICAgICAgICAgICB3aWR0aCA9IHcgPyB3IC8gMiA6IHNpemU7XG4gICAgICAgICAgICAgICAgY3R4LnJlY3QoeCAtIHdpZHRoLCB5IC0gc2l6ZSwgMiAqIHdpZHRoLCAyICogc2l6ZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByYWQgKz0gUVVBUlRFUl9QSTtcbiAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLyBjYXNlICdyZWN0Um90JzpcbiAgICAgICAgICAgIHhPZmZzZXRXID0gTWF0aC5jb3MocmFkKSAqICh3ID8gdyAvIDIgOiByYWRpdXMpO1xuICAgICAgICAgICAgeE9mZnNldCA9IE1hdGguY29zKHJhZCkgKiByYWRpdXM7XG4gICAgICAgICAgICB5T2Zmc2V0ID0gTWF0aC5zaW4ocmFkKSAqIHJhZGl1cztcbiAgICAgICAgICAgIHlPZmZzZXRXID0gTWF0aC5zaW4ocmFkKSAqICh3ID8gdyAvIDIgOiByYWRpdXMpO1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyh4IC0geE9mZnNldFcsIHkgLSB5T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCArIHlPZmZzZXRXLCB5IC0geE9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggKyB4T2Zmc2V0VywgeSArIHlPZmZzZXQpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4IC0geU9mZnNldFcsIHkgKyB4T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdjcm9zc1JvdCc6XG4gICAgICAgICAgICByYWQgKz0gUVVBUlRFUl9QSTtcbiAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLyBjYXNlICdjcm9zcyc6XG4gICAgICAgICAgICB4T2Zmc2V0VyA9IE1hdGguY29zKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIHhPZmZzZXQgPSBNYXRoLmNvcyhyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgICAgICAgICB5T2Zmc2V0VyA9IE1hdGguc2luKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oeCAtIHhPZmZzZXRXLCB5IC0geU9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggKyB4T2Zmc2V0VywgeSArIHlPZmZzZXQpO1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyh4ICsgeU9mZnNldFcsIHkgLSB4T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCAtIHlPZmZzZXRXLCB5ICsgeE9mZnNldCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnc3Rhcic6XG4gICAgICAgICAgICB4T2Zmc2V0VyA9IE1hdGguY29zKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIHhPZmZzZXQgPSBNYXRoLmNvcyhyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgICAgICAgICB5T2Zmc2V0VyA9IE1hdGguc2luKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oeCAtIHhPZmZzZXRXLCB5IC0geU9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggKyB4T2Zmc2V0VywgeSArIHlPZmZzZXQpO1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyh4ICsgeU9mZnNldFcsIHkgLSB4T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCAtIHlPZmZzZXRXLCB5ICsgeE9mZnNldCk7XG4gICAgICAgICAgICByYWQgKz0gUVVBUlRFUl9QSTtcbiAgICAgICAgICAgIHhPZmZzZXRXID0gTWF0aC5jb3MocmFkKSAqICh3ID8gdyAvIDIgOiByYWRpdXMpO1xuICAgICAgICAgICAgeE9mZnNldCA9IE1hdGguY29zKHJhZCkgKiByYWRpdXM7XG4gICAgICAgICAgICB5T2Zmc2V0ID0gTWF0aC5zaW4ocmFkKSAqIHJhZGl1cztcbiAgICAgICAgICAgIHlPZmZzZXRXID0gTWF0aC5zaW4ocmFkKSAqICh3ID8gdyAvIDIgOiByYWRpdXMpO1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyh4IC0geE9mZnNldFcsIHkgLSB5T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCArIHhPZmZzZXRXLCB5ICsgeU9mZnNldCk7XG4gICAgICAgICAgICBjdHgubW92ZVRvKHggKyB5T2Zmc2V0VywgeSAtIHhPZmZzZXQpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4IC0geU9mZnNldFcsIHkgKyB4T2Zmc2V0KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdsaW5lJzpcbiAgICAgICAgICAgIHhPZmZzZXQgPSB3ID8gdyAvIDIgOiBNYXRoLmNvcyhyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgICAgICAgICBjdHgubW92ZVRvKHggLSB4T2Zmc2V0LCB5IC0geU9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggKyB4T2Zmc2V0LCB5ICsgeU9mZnNldCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZGFzaCc6XG4gICAgICAgICAgICBjdHgubW92ZVRvKHgsIHkpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4ICsgTWF0aC5jb3MocmFkKSAqICh3ID8gdyAvIDIgOiByYWRpdXMpLCB5ICsgTWF0aC5zaW4ocmFkKSAqIHJhZGl1cyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBmYWxzZTpcbiAgICAgICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjdHguZmlsbCgpO1xuICAgIGlmIChvcHRpb25zLmJvcmRlcldpZHRoID4gMCkge1xuICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfVxufVxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHBvaW50IGlzIGluc2lkZSB0aGUgcmVjdGFuZ2xlXG4gKiBAcGFyYW0gcG9pbnQgLSBUaGUgcG9pbnQgdG8gdGVzdFxuICogQHBhcmFtIGFyZWEgLSBUaGUgcmVjdGFuZ2xlXG4gKiBAcGFyYW0gbWFyZ2luIC0gYWxsb3dlZCBtYXJnaW5cbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2lzUG9pbnRJbkFyZWEocG9pbnQsIGFyZWEsIG1hcmdpbikge1xuICAgIG1hcmdpbiA9IG1hcmdpbiB8fCAwLjU7IC8vIG1hcmdpbiAtIGRlZmF1bHQgaXMgdG8gbWF0Y2ggcm91bmRlZCBkZWNpbWFsc1xuICAgIHJldHVybiAhYXJlYSB8fCBwb2ludCAmJiBwb2ludC54ID4gYXJlYS5sZWZ0IC0gbWFyZ2luICYmIHBvaW50LnggPCBhcmVhLnJpZ2h0ICsgbWFyZ2luICYmIHBvaW50LnkgPiBhcmVhLnRvcCAtIG1hcmdpbiAmJiBwb2ludC55IDwgYXJlYS5ib3R0b20gKyBtYXJnaW47XG59XG5mdW5jdGlvbiBjbGlwQXJlYShjdHgsIGFyZWEpIHtcbiAgICBjdHguc2F2ZSgpO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBjdHgucmVjdChhcmVhLmxlZnQsIGFyZWEudG9wLCBhcmVhLnJpZ2h0IC0gYXJlYS5sZWZ0LCBhcmVhLmJvdHRvbSAtIGFyZWEudG9wKTtcbiAgICBjdHguY2xpcCgpO1xufVxuZnVuY3Rpb24gdW5jbGlwQXJlYShjdHgpIHtcbiAgICBjdHgucmVzdG9yZSgpO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9zdGVwcGVkTGluZVRvKGN0eCwgcHJldmlvdXMsIHRhcmdldCwgZmxpcCwgbW9kZSkge1xuICAgIGlmICghcHJldmlvdXMpIHtcbiAgICAgICAgcmV0dXJuIGN0eC5saW5lVG8odGFyZ2V0LngsIHRhcmdldC55KTtcbiAgICB9XG4gICAgaWYgKG1vZGUgPT09ICdtaWRkbGUnKSB7XG4gICAgICAgIGNvbnN0IG1pZHBvaW50ID0gKHByZXZpb3VzLnggKyB0YXJnZXQueCkgLyAyLjA7XG4gICAgICAgIGN0eC5saW5lVG8obWlkcG9pbnQsIHByZXZpb3VzLnkpO1xuICAgICAgICBjdHgubGluZVRvKG1pZHBvaW50LCB0YXJnZXQueSk7XG4gICAgfSBlbHNlIGlmIChtb2RlID09PSAnYWZ0ZXInICE9PSAhIWZsaXApIHtcbiAgICAgICAgY3R4LmxpbmVUbyhwcmV2aW91cy54LCB0YXJnZXQueSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY3R4LmxpbmVUbyh0YXJnZXQueCwgcHJldmlvdXMueSk7XG4gICAgfVxuICAgIGN0eC5saW5lVG8odGFyZ2V0LngsIHRhcmdldC55KTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfYmV6aWVyQ3VydmVUbyhjdHgsIHByZXZpb3VzLCB0YXJnZXQsIGZsaXApIHtcbiAgICBpZiAoIXByZXZpb3VzKSB7XG4gICAgICAgIHJldHVybiBjdHgubGluZVRvKHRhcmdldC54LCB0YXJnZXQueSk7XG4gICAgfVxuICAgIGN0eC5iZXppZXJDdXJ2ZVRvKGZsaXAgPyBwcmV2aW91cy5jcDF4IDogcHJldmlvdXMuY3AyeCwgZmxpcCA/IHByZXZpb3VzLmNwMXkgOiBwcmV2aW91cy5jcDJ5LCBmbGlwID8gdGFyZ2V0LmNwMnggOiB0YXJnZXQuY3AxeCwgZmxpcCA/IHRhcmdldC5jcDJ5IDogdGFyZ2V0LmNwMXksIHRhcmdldC54LCB0YXJnZXQueSk7XG59XG5mdW5jdGlvbiBzZXRSZW5kZXJPcHRzKGN0eCwgb3B0cykge1xuICAgIGlmIChvcHRzLnRyYW5zbGF0aW9uKSB7XG4gICAgICAgIGN0eC50cmFuc2xhdGUob3B0cy50cmFuc2xhdGlvblswXSwgb3B0cy50cmFuc2xhdGlvblsxXSk7XG4gICAgfVxuICAgIGlmICghaXNOdWxsT3JVbmRlZihvcHRzLnJvdGF0aW9uKSkge1xuICAgICAgICBjdHgucm90YXRlKG9wdHMucm90YXRpb24pO1xuICAgIH1cbiAgICBpZiAob3B0cy5jb2xvcikge1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gb3B0cy5jb2xvcjtcbiAgICB9XG4gICAgaWYgKG9wdHMudGV4dEFsaWduKSB7XG4gICAgICAgIGN0eC50ZXh0QWxpZ24gPSBvcHRzLnRleHRBbGlnbjtcbiAgICB9XG4gICAgaWYgKG9wdHMudGV4dEJhc2VsaW5lKSB7XG4gICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSBvcHRzLnRleHRCYXNlbGluZTtcbiAgICB9XG59XG5mdW5jdGlvbiBkZWNvcmF0ZVRleHQoY3R4LCB4LCB5LCBsaW5lLCBvcHRzKSB7XG4gICAgaWYgKG9wdHMuc3RyaWtldGhyb3VnaCB8fCBvcHRzLnVuZGVybGluZSkge1xuICAgICAgICAvKipcbiAgICAgKiBOb3cgdGhhdCBJRTExIHN1cHBvcnQgaGFzIGJlZW4gZHJvcHBlZCwgd2UgY2FuIHVzZSBtb3JlXG4gICAgICogb2YgdGhlIFRleHRNZXRyaWNzIG9iamVjdC4gVGhlIGFjdHVhbCBib3VuZGluZyBib3hlc1xuICAgICAqIGFyZSB1bmZsYWdnZWQgaW4gQ2hyb21lLCBGaXJlZm94LCBFZGdlLCBhbmQgU2FmYXJpIHNvIHRoZXlcbiAgICAgKiBjYW4gYmUgc2FmZWx5IHVzZWQuXG4gICAgICogU2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9UZXh0TWV0cmljcyNCcm93c2VyX2NvbXBhdGliaWxpdHlcbiAgICAgKi8gY29uc3QgbWV0cmljcyA9IGN0eC5tZWFzdXJlVGV4dChsaW5lKTtcbiAgICAgICAgY29uc3QgbGVmdCA9IHggLSBtZXRyaWNzLmFjdHVhbEJvdW5kaW5nQm94TGVmdDtcbiAgICAgICAgY29uc3QgcmlnaHQgPSB4ICsgbWV0cmljcy5hY3R1YWxCb3VuZGluZ0JveFJpZ2h0O1xuICAgICAgICBjb25zdCB0b3AgPSB5IC0gbWV0cmljcy5hY3R1YWxCb3VuZGluZ0JveEFzY2VudDtcbiAgICAgICAgY29uc3QgYm90dG9tID0geSArIG1ldHJpY3MuYWN0dWFsQm91bmRpbmdCb3hEZXNjZW50O1xuICAgICAgICBjb25zdCB5RGVjb3JhdGlvbiA9IG9wdHMuc3RyaWtldGhyb3VnaCA/ICh0b3AgKyBib3R0b20pIC8gMiA6IGJvdHRvbTtcbiAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gY3R4LmZpbGxTdHlsZTtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHgubGluZVdpZHRoID0gb3B0cy5kZWNvcmF0aW9uV2lkdGggfHwgMjtcbiAgICAgICAgY3R4Lm1vdmVUbyhsZWZ0LCB5RGVjb3JhdGlvbik7XG4gICAgICAgIGN0eC5saW5lVG8ocmlnaHQsIHlEZWNvcmF0aW9uKTtcbiAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGRyYXdCYWNrZHJvcChjdHgsIG9wdHMpIHtcbiAgICBjb25zdCBvbGRDb2xvciA9IGN0eC5maWxsU3R5bGU7XG4gICAgY3R4LmZpbGxTdHlsZSA9IG9wdHMuY29sb3I7XG4gICAgY3R4LmZpbGxSZWN0KG9wdHMubGVmdCwgb3B0cy50b3AsIG9wdHMud2lkdGgsIG9wdHMuaGVpZ2h0KTtcbiAgICBjdHguZmlsbFN0eWxlID0gb2xkQ29sb3I7XG59XG4vKipcbiAqIFJlbmRlciB0ZXh0IG9udG8gdGhlIGNhbnZhc1xuICovIGZ1bmN0aW9uIHJlbmRlclRleHQoY3R4LCB0ZXh0LCB4LCB5LCBmb250LCBvcHRzID0ge30pIHtcbiAgICBjb25zdCBsaW5lcyA9IGlzQXJyYXkodGV4dCkgPyB0ZXh0IDogW1xuICAgICAgICB0ZXh0XG4gICAgXTtcbiAgICBjb25zdCBzdHJva2UgPSBvcHRzLnN0cm9rZVdpZHRoID4gMCAmJiBvcHRzLnN0cm9rZUNvbG9yICE9PSAnJztcbiAgICBsZXQgaSwgbGluZTtcbiAgICBjdHguc2F2ZSgpO1xuICAgIGN0eC5mb250ID0gZm9udC5zdHJpbmc7XG4gICAgc2V0UmVuZGVyT3B0cyhjdHgsIG9wdHMpO1xuICAgIGZvcihpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgKytpKXtcbiAgICAgICAgbGluZSA9IGxpbmVzW2ldO1xuICAgICAgICBpZiAob3B0cy5iYWNrZHJvcCkge1xuICAgICAgICAgICAgZHJhd0JhY2tkcm9wKGN0eCwgb3B0cy5iYWNrZHJvcCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0cm9rZSkge1xuICAgICAgICAgICAgaWYgKG9wdHMuc3Ryb2tlQ29sb3IpIHtcbiAgICAgICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBvcHRzLnN0cm9rZUNvbG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc051bGxPclVuZGVmKG9wdHMuc3Ryb2tlV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgY3R4LmxpbmVXaWR0aCA9IG9wdHMuc3Ryb2tlV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdHguc3Ryb2tlVGV4dChsaW5lLCB4LCB5LCBvcHRzLm1heFdpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICBjdHguZmlsbFRleHQobGluZSwgeCwgeSwgb3B0cy5tYXhXaWR0aCk7XG4gICAgICAgIGRlY29yYXRlVGV4dChjdHgsIHgsIHksIGxpbmUsIG9wdHMpO1xuICAgICAgICB5ICs9IE51bWJlcihmb250LmxpbmVIZWlnaHQpO1xuICAgIH1cbiAgICBjdHgucmVzdG9yZSgpO1xufVxuLyoqXG4gKiBBZGQgYSBwYXRoIG9mIGEgcmVjdGFuZ2xlIHdpdGggcm91bmRlZCBjb3JuZXJzIHRvIHRoZSBjdXJyZW50IHN1Yi1wYXRoXG4gKiBAcGFyYW0gY3R4IC0gQ29udGV4dFxuICogQHBhcmFtIHJlY3QgLSBCb3VuZGluZyByZWN0XG4gKi8gZnVuY3Rpb24gYWRkUm91bmRlZFJlY3RQYXRoKGN0eCwgcmVjdCkge1xuICAgIGNvbnN0IHsgeCAsIHkgLCB3ICwgaCAsIHJhZGl1cyAgfSA9IHJlY3Q7XG4gICAgLy8gdG9wIGxlZnQgYXJjXG4gICAgY3R4LmFyYyh4ICsgcmFkaXVzLnRvcExlZnQsIHkgKyByYWRpdXMudG9wTGVmdCwgcmFkaXVzLnRvcExlZnQsIDEuNSAqIFBJLCBQSSwgdHJ1ZSk7XG4gICAgLy8gbGluZSBmcm9tIHRvcCBsZWZ0IHRvIGJvdHRvbSBsZWZ0XG4gICAgY3R4LmxpbmVUbyh4LCB5ICsgaCAtIHJhZGl1cy5ib3R0b21MZWZ0KTtcbiAgICAvLyBib3R0b20gbGVmdCBhcmNcbiAgICBjdHguYXJjKHggKyByYWRpdXMuYm90dG9tTGVmdCwgeSArIGggLSByYWRpdXMuYm90dG9tTGVmdCwgcmFkaXVzLmJvdHRvbUxlZnQsIFBJLCBIQUxGX1BJLCB0cnVlKTtcbiAgICAvLyBsaW5lIGZyb20gYm90dG9tIGxlZnQgdG8gYm90dG9tIHJpZ2h0XG4gICAgY3R4LmxpbmVUbyh4ICsgdyAtIHJhZGl1cy5ib3R0b21SaWdodCwgeSArIGgpO1xuICAgIC8vIGJvdHRvbSByaWdodCBhcmNcbiAgICBjdHguYXJjKHggKyB3IC0gcmFkaXVzLmJvdHRvbVJpZ2h0LCB5ICsgaCAtIHJhZGl1cy5ib3R0b21SaWdodCwgcmFkaXVzLmJvdHRvbVJpZ2h0LCBIQUxGX1BJLCAwLCB0cnVlKTtcbiAgICAvLyBsaW5lIGZyb20gYm90dG9tIHJpZ2h0IHRvIHRvcCByaWdodFxuICAgIGN0eC5saW5lVG8oeCArIHcsIHkgKyByYWRpdXMudG9wUmlnaHQpO1xuICAgIC8vIHRvcCByaWdodCBhcmNcbiAgICBjdHguYXJjKHggKyB3IC0gcmFkaXVzLnRvcFJpZ2h0LCB5ICsgcmFkaXVzLnRvcFJpZ2h0LCByYWRpdXMudG9wUmlnaHQsIDAsIC1IQUxGX1BJLCB0cnVlKTtcbiAgICAvLyBsaW5lIGZyb20gdG9wIHJpZ2h0IHRvIHRvcCBsZWZ0XG4gICAgY3R4LmxpbmVUbyh4ICsgcmFkaXVzLnRvcExlZnQsIHkpO1xufVxuXG5jb25zdCBMSU5FX0hFSUdIVCA9IC9eKG5vcm1hbHwoXFxkKyg/OlxcLlxcZCspPykocHh8ZW18JSk/KSQvO1xuY29uc3QgRk9OVF9TVFlMRSA9IC9eKG5vcm1hbHxpdGFsaWN8aW5pdGlhbHxpbmhlcml0fHVuc2V0fChvYmxpcXVlKCAtP1swLTldP1swLTldZGVnKT8pKSQvO1xuLyoqXG4gKiBAYWxpYXMgQ2hhcnQuaGVscGVycy5vcHRpb25zXG4gKiBAbmFtZXNwYWNlXG4gKi8gLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gbGluZSBoZWlnaHQgYHZhbHVlYCBpbiBwaXhlbHMgZm9yIGEgc3BlY2lmaWMgZm9udCBgc2l6ZWAuXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgbGluZUhlaWdodCB0byBwYXJzZSAoZWcuIDEuNiwgJzE0cHgnLCAnNzUlJywgJzEuNmVtJykuXG4gKiBAcGFyYW0gc2l6ZSAtIFRoZSBmb250IHNpemUgKGluIHBpeGVscykgdXNlZCB0byByZXNvbHZlIHJlbGF0aXZlIGB2YWx1ZWAuXG4gKiBAcmV0dXJucyBUaGUgZWZmZWN0aXZlIGxpbmUgaGVpZ2h0IGluIHBpeGVscyAoc2l6ZSAqIDEuMiBpZiB2YWx1ZSBpcyBpbnZhbGlkKS5cbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL2xpbmUtaGVpZ2h0XG4gKiBAc2luY2UgMi43LjBcbiAqLyBmdW5jdGlvbiB0b0xpbmVIZWlnaHQodmFsdWUsIHNpemUpIHtcbiAgICBjb25zdCBtYXRjaGVzID0gKCcnICsgdmFsdWUpLm1hdGNoKExJTkVfSEVJR0hUKTtcbiAgICBpZiAoIW1hdGNoZXMgfHwgbWF0Y2hlc1sxXSA9PT0gJ25vcm1hbCcpIHtcbiAgICAgICAgcmV0dXJuIHNpemUgKiAxLjI7XG4gICAgfVxuICAgIHZhbHVlID0gK21hdGNoZXNbMl07XG4gICAgc3dpdGNoKG1hdGNoZXNbM10pe1xuICAgICAgICBjYXNlICdweCc6XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIGNhc2UgJyUnOlxuICAgICAgICAgICAgdmFsdWUgLz0gMTAwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiBzaXplICogdmFsdWU7XG59XG5jb25zdCBudW1iZXJPclplcm8gPSAodik9Pit2IHx8IDA7XG5mdW5jdGlvbiBfcmVhZFZhbHVlVG9Qcm9wcyh2YWx1ZSwgcHJvcHMpIHtcbiAgICBjb25zdCByZXQgPSB7fTtcbiAgICBjb25zdCBvYmpQcm9wcyA9IGlzT2JqZWN0KHByb3BzKTtcbiAgICBjb25zdCBrZXlzID0gb2JqUHJvcHMgPyBPYmplY3Qua2V5cyhwcm9wcykgOiBwcm9wcztcbiAgICBjb25zdCByZWFkID0gaXNPYmplY3QodmFsdWUpID8gb2JqUHJvcHMgPyAocHJvcCk9PnZhbHVlT3JEZWZhdWx0KHZhbHVlW3Byb3BdLCB2YWx1ZVtwcm9wc1twcm9wXV0pIDogKHByb3ApPT52YWx1ZVtwcm9wXSA6ICgpPT52YWx1ZTtcbiAgICBmb3IgKGNvbnN0IHByb3Agb2Yga2V5cyl7XG4gICAgICAgIHJldFtwcm9wXSA9IG51bWJlck9yWmVybyhyZWFkKHByb3ApKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbn1cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIHZhbHVlIGludG8gYSBUUkJMIG9iamVjdC5cbiAqIEBwYXJhbSB2YWx1ZSAtIElmIGEgbnVtYmVyLCBzZXQgdGhlIHZhbHVlIHRvIGFsbCBUUkJMIGNvbXBvbmVudCxcbiAqICBlbHNlLCBpZiBhbiBvYmplY3QsIHVzZSBkZWZpbmVkIHByb3BlcnRpZXMgYW5kIHNldHMgdW5kZWZpbmVkIG9uZXMgdG8gMC5cbiAqICB4IC8geSBhcmUgc2hvcnRoYW5kcyBmb3Igc2FtZSB2YWx1ZSBmb3IgbGVmdC9yaWdodCBhbmQgdG9wL2JvdHRvbS5cbiAqIEByZXR1cm5zIFRoZSBwYWRkaW5nIHZhbHVlcyAodG9wLCByaWdodCwgYm90dG9tLCBsZWZ0KVxuICogQHNpbmNlIDMuMC4wXG4gKi8gZnVuY3Rpb24gdG9UUkJMKHZhbHVlKSB7XG4gICAgcmV0dXJuIF9yZWFkVmFsdWVUb1Byb3BzKHZhbHVlLCB7XG4gICAgICAgIHRvcDogJ3knLFxuICAgICAgICByaWdodDogJ3gnLFxuICAgICAgICBib3R0b206ICd5JyxcbiAgICAgICAgbGVmdDogJ3gnXG4gICAgfSk7XG59XG4vKipcbiAqIENvbnZlcnRzIHRoZSBnaXZlbiB2YWx1ZSBpbnRvIGEgVFJCTCBjb3JuZXJzIG9iamVjdCAoc2ltaWxhciB3aXRoIGNzcyBib3JkZXItcmFkaXVzKS5cbiAqIEBwYXJhbSB2YWx1ZSAtIElmIGEgbnVtYmVyLCBzZXQgdGhlIHZhbHVlIHRvIGFsbCBUUkJMIGNvcm5lciBjb21wb25lbnRzLFxuICogIGVsc2UsIGlmIGFuIG9iamVjdCwgdXNlIGRlZmluZWQgcHJvcGVydGllcyBhbmQgc2V0cyB1bmRlZmluZWQgb25lcyB0byAwLlxuICogQHJldHVybnMgVGhlIFRSQkwgY29ybmVyIHZhbHVlcyAodG9wTGVmdCwgdG9wUmlnaHQsIGJvdHRvbUxlZnQsIGJvdHRvbVJpZ2h0KVxuICogQHNpbmNlIDMuMC4wXG4gKi8gZnVuY3Rpb24gdG9UUkJMQ29ybmVycyh2YWx1ZSkge1xuICAgIHJldHVybiBfcmVhZFZhbHVlVG9Qcm9wcyh2YWx1ZSwgW1xuICAgICAgICAndG9wTGVmdCcsXG4gICAgICAgICd0b3BSaWdodCcsXG4gICAgICAgICdib3R0b21MZWZ0JyxcbiAgICAgICAgJ2JvdHRvbVJpZ2h0J1xuICAgIF0pO1xufVxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gdmFsdWUgaW50byBhIHBhZGRpbmcgb2JqZWN0IHdpdGggcHJlLWNvbXB1dGVkIHdpZHRoL2hlaWdodC5cbiAqIEBwYXJhbSB2YWx1ZSAtIElmIGEgbnVtYmVyLCBzZXQgdGhlIHZhbHVlIHRvIGFsbCBUUkJMIGNvbXBvbmVudCxcbiAqICBlbHNlLCBpZiBhbiBvYmplY3QsIHVzZSBkZWZpbmVkIHByb3BlcnRpZXMgYW5kIHNldHMgdW5kZWZpbmVkIG9uZXMgdG8gMC5cbiAqICB4IC8geSBhcmUgc2hvcnRoYW5kcyBmb3Igc2FtZSB2YWx1ZSBmb3IgbGVmdC9yaWdodCBhbmQgdG9wL2JvdHRvbS5cbiAqIEByZXR1cm5zIFRoZSBwYWRkaW5nIHZhbHVlcyAodG9wLCByaWdodCwgYm90dG9tLCBsZWZ0LCB3aWR0aCwgaGVpZ2h0KVxuICogQHNpbmNlIDIuNy4wXG4gKi8gZnVuY3Rpb24gdG9QYWRkaW5nKHZhbHVlKSB7XG4gICAgY29uc3Qgb2JqID0gdG9UUkJMKHZhbHVlKTtcbiAgICBvYmoud2lkdGggPSBvYmoubGVmdCArIG9iai5yaWdodDtcbiAgICBvYmouaGVpZ2h0ID0gb2JqLnRvcCArIG9iai5ib3R0b207XG4gICAgcmV0dXJuIG9iajtcbn1cbi8qKlxuICogUGFyc2VzIGZvbnQgb3B0aW9ucyBhbmQgcmV0dXJucyB0aGUgZm9udCBvYmplY3QuXG4gKiBAcGFyYW0gb3B0aW9ucyAtIEEgb2JqZWN0IHRoYXQgY29udGFpbnMgZm9udCBvcHRpb25zIHRvIGJlIHBhcnNlZC5cbiAqIEBwYXJhbSBmYWxsYmFjayAtIEEgb2JqZWN0IHRoYXQgY29udGFpbnMgZmFsbGJhY2sgZm9udCBvcHRpb25zLlxuICogQHJldHVybiBUaGUgZm9udCBvYmplY3QuXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIHRvRm9udChvcHRpb25zLCBmYWxsYmFjaykge1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIGZhbGxiYWNrID0gZmFsbGJhY2sgfHwgZGVmYXVsdHMuZm9udDtcbiAgICBsZXQgc2l6ZSA9IHZhbHVlT3JEZWZhdWx0KG9wdGlvbnMuc2l6ZSwgZmFsbGJhY2suc2l6ZSk7XG4gICAgaWYgKHR5cGVvZiBzaXplID09PSAnc3RyaW5nJykge1xuICAgICAgICBzaXplID0gcGFyc2VJbnQoc2l6ZSwgMTApO1xuICAgIH1cbiAgICBsZXQgc3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLnN0eWxlLCBmYWxsYmFjay5zdHlsZSk7XG4gICAgaWYgKHN0eWxlICYmICEoJycgKyBzdHlsZSkubWF0Y2goRk9OVF9TVFlMRSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdJbnZhbGlkIGZvbnQgc3R5bGUgc3BlY2lmaWVkOiBcIicgKyBzdHlsZSArICdcIicpO1xuICAgICAgICBzdHlsZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgY29uc3QgZm9udCA9IHtcbiAgICAgICAgZmFtaWx5OiB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLmZhbWlseSwgZmFsbGJhY2suZmFtaWx5KSxcbiAgICAgICAgbGluZUhlaWdodDogdG9MaW5lSGVpZ2h0KHZhbHVlT3JEZWZhdWx0KG9wdGlvbnMubGluZUhlaWdodCwgZmFsbGJhY2subGluZUhlaWdodCksIHNpemUpLFxuICAgICAgICBzaXplLFxuICAgICAgICBzdHlsZSxcbiAgICAgICAgd2VpZ2h0OiB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLndlaWdodCwgZmFsbGJhY2sud2VpZ2h0KSxcbiAgICAgICAgc3RyaW5nOiAnJ1xuICAgIH07XG4gICAgZm9udC5zdHJpbmcgPSB0b0ZvbnRTdHJpbmcoZm9udCk7XG4gICAgcmV0dXJuIGZvbnQ7XG59XG4vKipcbiAqIEV2YWx1YXRlcyB0aGUgZ2l2ZW4gYGlucHV0c2Agc2VxdWVudGlhbGx5IGFuZCByZXR1cm5zIHRoZSBmaXJzdCBkZWZpbmVkIHZhbHVlLlxuICogQHBhcmFtIGlucHV0cyAtIEFuIGFycmF5IG9mIHZhbHVlcywgZmFsbGluZyBiYWNrIHRvIHRoZSBsYXN0IHZhbHVlLlxuICogQHBhcmFtIGNvbnRleHQgLSBJZiBkZWZpbmVkIGFuZCB0aGUgY3VycmVudCB2YWx1ZSBpcyBhIGZ1bmN0aW9uLCB0aGUgdmFsdWVcbiAqIGlzIGNhbGxlZCB3aXRoIGBjb250ZXh0YCBhcyBmaXJzdCBhcmd1bWVudCBhbmQgdGhlIHJlc3VsdCBiZWNvbWVzIHRoZSBuZXcgaW5wdXQuXG4gKiBAcGFyYW0gaW5kZXggLSBJZiBkZWZpbmVkIGFuZCB0aGUgY3VycmVudCB2YWx1ZSBpcyBhbiBhcnJheSwgdGhlIHZhbHVlXG4gKiBhdCBgaW5kZXhgIGJlY29tZSB0aGUgbmV3IGlucHV0LlxuICogQHBhcmFtIGluZm8gLSBvYmplY3QgdG8gcmV0dXJuIGluZm9ybWF0aW9uIGFib3V0IHJlc29sdXRpb24gaW5cbiAqIEBwYXJhbSBpbmZvLmNhY2hlYWJsZSAtIFdpbGwgYmUgc2V0IHRvIGBmYWxzZWAgaWYgb3B0aW9uIGlzIG5vdCBjYWNoZWFibGUuXG4gKiBAc2luY2UgMi43LjBcbiAqLyBmdW5jdGlvbiByZXNvbHZlKGlucHV0cywgY29udGV4dCwgaW5kZXgsIGluZm8pIHtcbiAgICBsZXQgY2FjaGVhYmxlID0gdHJ1ZTtcbiAgICBsZXQgaSwgaWxlbiwgdmFsdWU7XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gaW5wdXRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIHZhbHVlID0gaW5wdXRzW2ldO1xuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbnRleHQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUoY29udGV4dCk7XG4gICAgICAgICAgICBjYWNoZWFibGUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW5kZXggIT09IHVuZGVmaW5lZCAmJiBpc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZVtpbmRleCAlIHZhbHVlLmxlbmd0aF07XG4gICAgICAgICAgICBjYWNoZWFibGUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKGluZm8gJiYgIWNhY2hlYWJsZSkge1xuICAgICAgICAgICAgICAgIGluZm8uY2FjaGVhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG59XG4vKipcbiAqIEBwYXJhbSBtaW5tYXhcbiAqIEBwYXJhbSBncmFjZVxuICogQHBhcmFtIGJlZ2luQXRaZXJvXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9hZGRHcmFjZShtaW5tYXgsIGdyYWNlLCBiZWdpbkF0WmVybykge1xuICAgIGNvbnN0IHsgbWluICwgbWF4ICB9ID0gbWlubWF4O1xuICAgIGNvbnN0IGNoYW5nZSA9IHRvRGltZW5zaW9uKGdyYWNlLCAobWF4IC0gbWluKSAvIDIpO1xuICAgIGNvbnN0IGtlZXBaZXJvID0gKHZhbHVlLCBhZGQpPT5iZWdpbkF0WmVybyAmJiB2YWx1ZSA9PT0gMCA/IDAgOiB2YWx1ZSArIGFkZDtcbiAgICByZXR1cm4ge1xuICAgICAgICBtaW46IGtlZXBaZXJvKG1pbiwgLU1hdGguYWJzKGNoYW5nZSkpLFxuICAgICAgICBtYXg6IGtlZXBaZXJvKG1heCwgY2hhbmdlKVxuICAgIH07XG59XG5mdW5jdGlvbiBjcmVhdGVDb250ZXh0KHBhcmVudENvbnRleHQsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKHBhcmVudENvbnRleHQpLCBjb250ZXh0KTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgUHJveHkgZm9yIHJlc29sdmluZyByYXcgdmFsdWVzIGZvciBvcHRpb25zLlxuICogQHBhcmFtIHNjb3BlcyAtIFRoZSBvcHRpb24gc2NvcGVzIHRvIGxvb2sgZm9yIHZhbHVlcywgaW4gcmVzb2x1dGlvbiBvcmRlclxuICogQHBhcmFtIHByZWZpeGVzIC0gVGhlIHByZWZpeGVzIGZvciB2YWx1ZXMsIGluIHJlc29sdXRpb24gb3JkZXIuXG4gKiBAcGFyYW0gcm9vdFNjb3BlcyAtIFRoZSByb290IG9wdGlvbiBzY29wZXNcbiAqIEBwYXJhbSBmYWxsYmFjayAtIFBhcmVudCBzY29wZXMgZmFsbGJhY2tcbiAqIEBwYXJhbSBnZXRUYXJnZXQgLSBjYWxsYmFjayBmb3IgZ2V0dGluZyB0aGUgdGFyZ2V0IGZvciBjaGFuZ2VkIHZhbHVlc1xuICogQHJldHVybnMgUHJveHlcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2NyZWF0ZVJlc29sdmVyKHNjb3BlcywgcHJlZml4ZXMgPSBbXG4gICAgJydcbl0sIHJvb3RTY29wZXMsIGZhbGxiYWNrLCBnZXRUYXJnZXQgPSAoKT0+c2NvcGVzWzBdKSB7XG4gICAgY29uc3QgZmluYWxSb290U2NvcGVzID0gcm9vdFNjb3BlcyB8fCBzY29wZXM7XG4gICAgaWYgKHR5cGVvZiBmYWxsYmFjayA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgZmFsbGJhY2sgPSBfcmVzb2x2ZSgnX2ZhbGxiYWNrJywgc2NvcGVzKTtcbiAgICB9XG4gICAgY29uc3QgY2FjaGUgPSB7XG4gICAgICAgIFtTeW1ib2wudG9TdHJpbmdUYWddOiAnT2JqZWN0JyxcbiAgICAgICAgX2NhY2hlYWJsZTogdHJ1ZSxcbiAgICAgICAgX3Njb3Blczogc2NvcGVzLFxuICAgICAgICBfcm9vdFNjb3BlczogZmluYWxSb290U2NvcGVzLFxuICAgICAgICBfZmFsbGJhY2s6IGZhbGxiYWNrLFxuICAgICAgICBfZ2V0VGFyZ2V0OiBnZXRUYXJnZXQsXG4gICAgICAgIG92ZXJyaWRlOiAoc2NvcGUpPT5fY3JlYXRlUmVzb2x2ZXIoW1xuICAgICAgICAgICAgICAgIHNjb3BlLFxuICAgICAgICAgICAgICAgIC4uLnNjb3Blc1xuICAgICAgICAgICAgXSwgcHJlZml4ZXMsIGZpbmFsUm9vdFNjb3BlcywgZmFsbGJhY2spXG4gICAgfTtcbiAgICByZXR1cm4gbmV3IFByb3h5KGNhY2hlLCB7XG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgdGhlIGRlbGV0ZSBvcGVyYXRvci5cbiAgICAgKi8gZGVsZXRlUHJvcGVydHkgKHRhcmdldCwgcHJvcCkge1xuICAgICAgICAgICAgZGVsZXRlIHRhcmdldFtwcm9wXTsgLy8gcmVtb3ZlIGZyb20gY2FjaGVcbiAgICAgICAgICAgIGRlbGV0ZSB0YXJnZXQuX2tleXM7IC8vIHJlbW92ZSBjYWNoZWQga2V5c1xuICAgICAgICAgICAgZGVsZXRlIHNjb3Blc1swXVtwcm9wXTsgLy8gcmVtb3ZlIGZyb20gdG9wIGxldmVsIHNjb3BlXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciBnZXR0aW5nIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKi8gZ2V0ICh0YXJnZXQsIHByb3ApIHtcbiAgICAgICAgICAgIHJldHVybiBfY2FjaGVkKHRhcmdldCwgcHJvcCwgKCk9Pl9yZXNvbHZlV2l0aFByZWZpeGVzKHByb3AsIHByZWZpeGVzLCBzY29wZXMsIHRhcmdldCkpO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IuXG4gICAgICogQWxzbyB1c2VkIGJ5IE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5cbiAgICAgKi8gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yICh0YXJnZXQsIHByb3ApIHtcbiAgICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQuX3Njb3Blc1swXSwgcHJvcCk7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgT2JqZWN0LmdldFByb3RvdHlwZU9mLlxuICAgICAqLyBnZXRQcm90b3R5cGVPZiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXRQcm90b3R5cGVPZihzY29wZXNbMF0pO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIHRoZSBpbiBvcGVyYXRvci5cbiAgICAgKi8gaGFzICh0YXJnZXQsIHByb3ApIHtcbiAgICAgICAgICAgIHJldHVybiBnZXRLZXlzRnJvbUFsbFNjb3Blcyh0YXJnZXQpLmluY2x1ZGVzKHByb3ApO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIGFuZCBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzLlxuICAgICAqLyBvd25LZXlzICh0YXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBnZXRLZXlzRnJvbUFsbFNjb3Blcyh0YXJnZXQpO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIHNldHRpbmcgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqLyBzZXQgKHRhcmdldCwgcHJvcCwgdmFsdWUpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JhZ2UgPSB0YXJnZXQuX3N0b3JhZ2UgfHwgKHRhcmdldC5fc3RvcmFnZSA9IGdldFRhcmdldCgpKTtcbiAgICAgICAgICAgIHRhcmdldFtwcm9wXSA9IHN0b3JhZ2VbcHJvcF0gPSB2YWx1ZTsgLy8gc2V0IHRvIHRvcCBsZXZlbCBzY29wZSArIGNhY2hlXG4gICAgICAgICAgICBkZWxldGUgdGFyZ2V0Ll9rZXlzOyAvLyByZW1vdmUgY2FjaGVkIGtleXNcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfSk7XG59XG4vKipcbiAqIFJldHVybnMgYW4gUHJveHkgZm9yIHJlc29sdmluZyBvcHRpb24gdmFsdWVzIHdpdGggY29udGV4dC5cbiAqIEBwYXJhbSBwcm94eSAtIFRoZSBQcm94eSByZXR1cm5lZCBieSBgX2NyZWF0ZVJlc29sdmVyYFxuICogQHBhcmFtIGNvbnRleHQgLSBDb250ZXh0IG9iamVjdCBmb3Igc2NyaXB0YWJsZS9pbmRleGFibGUgb3B0aW9uc1xuICogQHBhcmFtIHN1YlByb3h5IC0gVGhlIHByb3h5IHByb3ZpZGVkIGZvciBzY3JpcHRhYmxlIG9wdGlvbnNcbiAqIEBwYXJhbSBkZXNjcmlwdG9yRGVmYXVsdHMgLSBEZWZhdWx0cyBmb3IgZGVzY3JpcHRvcnNcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2F0dGFjaENvbnRleHQocHJveHksIGNvbnRleHQsIHN1YlByb3h5LCBkZXNjcmlwdG9yRGVmYXVsdHMpIHtcbiAgICBjb25zdCBjYWNoZSA9IHtcbiAgICAgICAgX2NhY2hlYWJsZTogZmFsc2UsXG4gICAgICAgIF9wcm94eTogcHJveHksXG4gICAgICAgIF9jb250ZXh0OiBjb250ZXh0LFxuICAgICAgICBfc3ViUHJveHk6IHN1YlByb3h5LFxuICAgICAgICBfc3RhY2s6IG5ldyBTZXQoKSxcbiAgICAgICAgX2Rlc2NyaXB0b3JzOiBfZGVzY3JpcHRvcnMocHJveHksIGRlc2NyaXB0b3JEZWZhdWx0cyksXG4gICAgICAgIHNldENvbnRleHQ6IChjdHgpPT5fYXR0YWNoQ29udGV4dChwcm94eSwgY3R4LCBzdWJQcm94eSwgZGVzY3JpcHRvckRlZmF1bHRzKSxcbiAgICAgICAgb3ZlcnJpZGU6IChzY29wZSk9Pl9hdHRhY2hDb250ZXh0KHByb3h5Lm92ZXJyaWRlKHNjb3BlKSwgY29udGV4dCwgc3ViUHJveHksIGRlc2NyaXB0b3JEZWZhdWx0cylcbiAgICB9O1xuICAgIHJldHVybiBuZXcgUHJveHkoY2FjaGUsIHtcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciB0aGUgZGVsZXRlIG9wZXJhdG9yLlxuICAgICAqLyBkZWxldGVQcm9wZXJ0eSAodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgICAgICBkZWxldGUgdGFyZ2V0W3Byb3BdOyAvLyByZW1vdmUgZnJvbSBjYWNoZVxuICAgICAgICAgICAgZGVsZXRlIHByb3h5W3Byb3BdOyAvLyByZW1vdmUgZnJvbSBwcm94eVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgZ2V0dGluZyBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICovIGdldCAodGFyZ2V0LCBwcm9wLCByZWNlaXZlcikge1xuICAgICAgICAgICAgcmV0dXJuIF9jYWNoZWQodGFyZ2V0LCBwcm9wLCAoKT0+X3Jlc29sdmVXaXRoQ29udGV4dCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKSk7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvci5cbiAgICAgKiBBbHNvIHVzZWQgYnkgT2JqZWN0Lmhhc093blByb3BlcnR5LlxuICAgICAqLyBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgKHRhcmdldCwgcHJvcCkge1xuICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5fZGVzY3JpcHRvcnMuYWxsS2V5cyA/IFJlZmxlY3QuaGFzKHByb3h5LCBwcm9wKSA/IHtcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICAgICAgfSA6IHVuZGVmaW5lZCA6IFJlZmxlY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHByb3h5LCBwcm9wKTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciBPYmplY3QuZ2V0UHJvdG90eXBlT2YuXG4gICAgICovIGdldFByb3RvdHlwZU9mICgpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldFByb3RvdHlwZU9mKHByb3h5KTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciB0aGUgaW4gb3BlcmF0b3IuXG4gICAgICovIGhhcyAodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5oYXMocHJveHksIHByb3ApO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIGFuZCBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzLlxuICAgICAqLyBvd25LZXlzICgpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWZsZWN0Lm93bktleXMocHJveHkpO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIHNldHRpbmcgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqLyBzZXQgKHRhcmdldCwgcHJvcCwgdmFsdWUpIHtcbiAgICAgICAgICAgIHByb3h5W3Byb3BdID0gdmFsdWU7IC8vIHNldCB0byBwcm94eVxuICAgICAgICAgICAgZGVsZXRlIHRhcmdldFtwcm9wXTsgLy8gcmVtb3ZlIGZyb20gY2FjaGVcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfSk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2Rlc2NyaXB0b3JzKHByb3h5LCBkZWZhdWx0cyA9IHtcbiAgICBzY3JpcHRhYmxlOiB0cnVlLFxuICAgIGluZGV4YWJsZTogdHJ1ZVxufSkge1xuICAgIGNvbnN0IHsgX3NjcmlwdGFibGUgPWRlZmF1bHRzLnNjcmlwdGFibGUgLCBfaW5kZXhhYmxlID1kZWZhdWx0cy5pbmRleGFibGUgLCBfYWxsS2V5cyA9ZGVmYXVsdHMuYWxsS2V5cyAgfSA9IHByb3h5O1xuICAgIHJldHVybiB7XG4gICAgICAgIGFsbEtleXM6IF9hbGxLZXlzLFxuICAgICAgICBzY3JpcHRhYmxlOiBfc2NyaXB0YWJsZSxcbiAgICAgICAgaW5kZXhhYmxlOiBfaW5kZXhhYmxlLFxuICAgICAgICBpc1NjcmlwdGFibGU6IGlzRnVuY3Rpb24oX3NjcmlwdGFibGUpID8gX3NjcmlwdGFibGUgOiAoKT0+X3NjcmlwdGFibGUsXG4gICAgICAgIGlzSW5kZXhhYmxlOiBpc0Z1bmN0aW9uKF9pbmRleGFibGUpID8gX2luZGV4YWJsZSA6ICgpPT5faW5kZXhhYmxlXG4gICAgfTtcbn1cbmNvbnN0IHJlYWRLZXkgPSAocHJlZml4LCBuYW1lKT0+cHJlZml4ID8gcHJlZml4ICsgX2NhcGl0YWxpemUobmFtZSkgOiBuYW1lO1xuY29uc3QgbmVlZHNTdWJSZXNvbHZlciA9IChwcm9wLCB2YWx1ZSk9PmlzT2JqZWN0KHZhbHVlKSAmJiBwcm9wICE9PSAnYWRhcHRlcnMnICYmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpID09PSBudWxsIHx8IHZhbHVlLmNvbnN0cnVjdG9yID09PSBPYmplY3QpO1xuZnVuY3Rpb24gX2NhY2hlZCh0YXJnZXQsIHByb3AsIHJlc29sdmUpIHtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRhcmdldCwgcHJvcCkgfHwgcHJvcCA9PT0gJ2NvbnN0cnVjdG9yJykge1xuICAgICAgICByZXR1cm4gdGFyZ2V0W3Byb3BdO1xuICAgIH1cbiAgICBjb25zdCB2YWx1ZSA9IHJlc29sdmUoKTtcbiAgICAvLyBjYWNoZSB0aGUgcmVzb2x2ZWQgdmFsdWVcbiAgICB0YXJnZXRbcHJvcF0gPSB2YWx1ZTtcbiAgICByZXR1cm4gdmFsdWU7XG59XG5mdW5jdGlvbiBfcmVzb2x2ZVdpdGhDb250ZXh0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpIHtcbiAgICBjb25zdCB7IF9wcm94eSAsIF9jb250ZXh0ICwgX3N1YlByb3h5ICwgX2Rlc2NyaXB0b3JzOiBkZXNjcmlwdG9ycyAgfSA9IHRhcmdldDtcbiAgICBsZXQgdmFsdWUgPSBfcHJveHlbcHJvcF07IC8vIHJlc29sdmUgZnJvbSBwcm94eVxuICAgIC8vIHJlc29sdmUgd2l0aCBjb250ZXh0XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpICYmIGRlc2NyaXB0b3JzLmlzU2NyaXB0YWJsZShwcm9wKSkge1xuICAgICAgICB2YWx1ZSA9IF9yZXNvbHZlU2NyaXB0YWJsZShwcm9wLCB2YWx1ZSwgdGFyZ2V0LCByZWNlaXZlcik7XG4gICAgfVxuICAgIGlmIChpc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgICAgdmFsdWUgPSBfcmVzb2x2ZUFycmF5KHByb3AsIHZhbHVlLCB0YXJnZXQsIGRlc2NyaXB0b3JzLmlzSW5kZXhhYmxlKTtcbiAgICB9XG4gICAgaWYgKG5lZWRzU3ViUmVzb2x2ZXIocHJvcCwgdmFsdWUpKSB7XG4gICAgICAgIC8vIGlmIHRoZSByZXNvbHZlZCB2YWx1ZSBpcyBhbiBvYmplY3QsIGNyZWF0ZSBhIHN1YiByZXNvbHZlciBmb3IgaXRcbiAgICAgICAgdmFsdWUgPSBfYXR0YWNoQ29udGV4dCh2YWx1ZSwgX2NvbnRleHQsIF9zdWJQcm94eSAmJiBfc3ViUHJveHlbcHJvcF0sIGRlc2NyaXB0b3JzKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuZnVuY3Rpb24gX3Jlc29sdmVTY3JpcHRhYmxlKHByb3AsIGdldFZhbHVlLCB0YXJnZXQsIHJlY2VpdmVyKSB7XG4gICAgY29uc3QgeyBfcHJveHkgLCBfY29udGV4dCAsIF9zdWJQcm94eSAsIF9zdGFjayAgfSA9IHRhcmdldDtcbiAgICBpZiAoX3N0YWNrLmhhcyhwcm9wKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlY3Vyc2lvbiBkZXRlY3RlZDogJyArIEFycmF5LmZyb20oX3N0YWNrKS5qb2luKCctPicpICsgJy0+JyArIHByb3ApO1xuICAgIH1cbiAgICBfc3RhY2suYWRkKHByb3ApO1xuICAgIGxldCB2YWx1ZSA9IGdldFZhbHVlKF9jb250ZXh0LCBfc3ViUHJveHkgfHwgcmVjZWl2ZXIpO1xuICAgIF9zdGFjay5kZWxldGUocHJvcCk7XG4gICAgaWYgKG5lZWRzU3ViUmVzb2x2ZXIocHJvcCwgdmFsdWUpKSB7XG4gICAgICAgIC8vIFdoZW4gc2NyaXB0YWJsZSBvcHRpb24gcmV0dXJucyBhbiBvYmplY3QsIGNyZWF0ZSBhIHJlc29sdmVyIG9uIHRoYXQuXG4gICAgICAgIHZhbHVlID0gY3JlYXRlU3ViUmVzb2x2ZXIoX3Byb3h5Ll9zY29wZXMsIF9wcm94eSwgcHJvcCwgdmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59XG5mdW5jdGlvbiBfcmVzb2x2ZUFycmF5KHByb3AsIHZhbHVlLCB0YXJnZXQsIGlzSW5kZXhhYmxlKSB7XG4gICAgY29uc3QgeyBfcHJveHkgLCBfY29udGV4dCAsIF9zdWJQcm94eSAsIF9kZXNjcmlwdG9yczogZGVzY3JpcHRvcnMgIH0gPSB0YXJnZXQ7XG4gICAgaWYgKHR5cGVvZiBfY29udGV4dC5pbmRleCAhPT0gJ3VuZGVmaW5lZCcgJiYgaXNJbmRleGFibGUocHJvcCkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlW19jb250ZXh0LmluZGV4ICUgdmFsdWUubGVuZ3RoXTtcbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHZhbHVlWzBdKSkge1xuICAgICAgICAvLyBBcnJheSBvZiBvYmplY3RzLCByZXR1cm4gYXJyYXkgb3IgcmVzb2x2ZXJzXG4gICAgICAgIGNvbnN0IGFyciA9IHZhbHVlO1xuICAgICAgICBjb25zdCBzY29wZXMgPSBfcHJveHkuX3Njb3Blcy5maWx0ZXIoKHMpPT5zICE9PSBhcnIpO1xuICAgICAgICB2YWx1ZSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXJyKXtcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVyID0gY3JlYXRlU3ViUmVzb2x2ZXIoc2NvcGVzLCBfcHJveHksIHByb3AsIGl0ZW0pO1xuICAgICAgICAgICAgdmFsdWUucHVzaChfYXR0YWNoQ29udGV4dChyZXNvbHZlciwgX2NvbnRleHQsIF9zdWJQcm94eSAmJiBfc3ViUHJveHlbcHJvcF0sIGRlc2NyaXB0b3JzKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuZnVuY3Rpb24gcmVzb2x2ZUZhbGxiYWNrKGZhbGxiYWNrLCBwcm9wLCB2YWx1ZSkge1xuICAgIHJldHVybiBpc0Z1bmN0aW9uKGZhbGxiYWNrKSA/IGZhbGxiYWNrKHByb3AsIHZhbHVlKSA6IGZhbGxiYWNrO1xufVxuY29uc3QgZ2V0U2NvcGUgPSAoa2V5LCBwYXJlbnQpPT5rZXkgPT09IHRydWUgPyBwYXJlbnQgOiB0eXBlb2Yga2V5ID09PSAnc3RyaW5nJyA/IHJlc29sdmVPYmplY3RLZXkocGFyZW50LCBrZXkpIDogdW5kZWZpbmVkO1xuZnVuY3Rpb24gYWRkU2NvcGVzKHNldCwgcGFyZW50U2NvcGVzLCBrZXksIHBhcmVudEZhbGxiYWNrLCB2YWx1ZSkge1xuICAgIGZvciAoY29uc3QgcGFyZW50IG9mIHBhcmVudFNjb3Blcyl7XG4gICAgICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoa2V5LCBwYXJlbnQpO1xuICAgICAgICBpZiAoc2NvcGUpIHtcbiAgICAgICAgICAgIHNldC5hZGQoc2NvcGUpO1xuICAgICAgICAgICAgY29uc3QgZmFsbGJhY2sgPSByZXNvbHZlRmFsbGJhY2soc2NvcGUuX2ZhbGxiYWNrLCBrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZmFsbGJhY2sgIT09ICd1bmRlZmluZWQnICYmIGZhbGxiYWNrICE9PSBrZXkgJiYgZmFsbGJhY2sgIT09IHBhcmVudEZhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgLy8gV2hlbiB3ZSByZWFjaCB0aGUgZGVzY3JpcHRvciB0aGF0IGRlZmluZXMgYSBuZXcgX2ZhbGxiYWNrLCByZXR1cm4gdGhhdC5cbiAgICAgICAgICAgICAgICAvLyBUaGUgZmFsbGJhY2sgd2lsbCByZXN1bWUgdG8gdGhhdCBuZXcgc2NvcGUuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbGxiYWNrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHNjb3BlID09PSBmYWxzZSAmJiB0eXBlb2YgcGFyZW50RmFsbGJhY2sgIT09ICd1bmRlZmluZWQnICYmIGtleSAhPT0gcGFyZW50RmFsbGJhY2spIHtcbiAgICAgICAgICAgIC8vIEZhbGxiYWNrIHRvIGBmYWxzZWAgcmVzdWx0cyB0byBgZmFsc2VgLCB3aGVuIGZhbGxpbmcgYmFjayB0byBkaWZmZXJlbnQga2V5LlxuICAgICAgICAgICAgLy8gRm9yIGV4YW1wbGUgYGludGVyYWN0aW9uYCBmcm9tIGBob3ZlcmAgb3IgYHBsdWdpbnMudG9vbHRpcGAgYW5kIGBhbmltYXRpb25gIGZyb20gYGFuaW1hdGlvbnNgXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiBjcmVhdGVTdWJSZXNvbHZlcihwYXJlbnRTY29wZXMsIHJlc29sdmVyLCBwcm9wLCB2YWx1ZSkge1xuICAgIGNvbnN0IHJvb3RTY29wZXMgPSByZXNvbHZlci5fcm9vdFNjb3BlcztcbiAgICBjb25zdCBmYWxsYmFjayA9IHJlc29sdmVGYWxsYmFjayhyZXNvbHZlci5fZmFsbGJhY2ssIHByb3AsIHZhbHVlKTtcbiAgICBjb25zdCBhbGxTY29wZXMgPSBbXG4gICAgICAgIC4uLnBhcmVudFNjb3BlcyxcbiAgICAgICAgLi4ucm9vdFNjb3Blc1xuICAgIF07XG4gICAgY29uc3Qgc2V0ID0gbmV3IFNldCgpO1xuICAgIHNldC5hZGQodmFsdWUpO1xuICAgIGxldCBrZXkgPSBhZGRTY29wZXNGcm9tS2V5KHNldCwgYWxsU2NvcGVzLCBwcm9wLCBmYWxsYmFjayB8fCBwcm9wLCB2YWx1ZSk7XG4gICAgaWYgKGtleSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZmFsbGJhY2sgIT09ICd1bmRlZmluZWQnICYmIGZhbGxiYWNrICE9PSBwcm9wKSB7XG4gICAgICAgIGtleSA9IGFkZFNjb3Blc0Zyb21LZXkoc2V0LCBhbGxTY29wZXMsIGZhbGxiYWNrLCBrZXksIHZhbHVlKTtcbiAgICAgICAgaWYgKGtleSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBfY3JlYXRlUmVzb2x2ZXIoQXJyYXkuZnJvbShzZXQpLCBbXG4gICAgICAgICcnXG4gICAgXSwgcm9vdFNjb3BlcywgZmFsbGJhY2ssICgpPT5zdWJHZXRUYXJnZXQocmVzb2x2ZXIsIHByb3AsIHZhbHVlKSk7XG59XG5mdW5jdGlvbiBhZGRTY29wZXNGcm9tS2V5KHNldCwgYWxsU2NvcGVzLCBrZXksIGZhbGxiYWNrLCBpdGVtKSB7XG4gICAgd2hpbGUoa2V5KXtcbiAgICAgICAga2V5ID0gYWRkU2NvcGVzKHNldCwgYWxsU2NvcGVzLCBrZXksIGZhbGxiYWNrLCBpdGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIGtleTtcbn1cbmZ1bmN0aW9uIHN1YkdldFRhcmdldChyZXNvbHZlciwgcHJvcCwgdmFsdWUpIHtcbiAgICBjb25zdCBwYXJlbnQgPSByZXNvbHZlci5fZ2V0VGFyZ2V0KCk7XG4gICAgaWYgKCEocHJvcCBpbiBwYXJlbnQpKSB7XG4gICAgICAgIHBhcmVudFtwcm9wXSA9IHt9O1xuICAgIH1cbiAgICBjb25zdCB0YXJnZXQgPSBwYXJlbnRbcHJvcF07XG4gICAgaWYgKGlzQXJyYXkodGFyZ2V0KSAmJiBpc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgLy8gRm9yIGFycmF5IG9mIG9iamVjdHMsIHRoZSBvYmplY3QgaXMgdXNlZCB0byBzdG9yZSB1cGRhdGVkIHZhbHVlc1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQgfHwge307XG59XG5mdW5jdGlvbiBfcmVzb2x2ZVdpdGhQcmVmaXhlcyhwcm9wLCBwcmVmaXhlcywgc2NvcGVzLCBwcm94eSkge1xuICAgIGxldCB2YWx1ZTtcbiAgICBmb3IgKGNvbnN0IHByZWZpeCBvZiBwcmVmaXhlcyl7XG4gICAgICAgIHZhbHVlID0gX3Jlc29sdmUocmVhZEtleShwcmVmaXgsIHByb3ApLCBzY29wZXMpO1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgcmV0dXJuIG5lZWRzU3ViUmVzb2x2ZXIocHJvcCwgdmFsdWUpID8gY3JlYXRlU3ViUmVzb2x2ZXIoc2NvcGVzLCBwcm94eSwgcHJvcCwgdmFsdWUpIDogdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBfcmVzb2x2ZShrZXksIHNjb3Blcykge1xuICAgIGZvciAoY29uc3Qgc2NvcGUgb2Ygc2NvcGVzKXtcbiAgICAgICAgaWYgKCFzY29wZSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdmFsdWUgPSBzY29wZVtrZXldO1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0S2V5c0Zyb21BbGxTY29wZXModGFyZ2V0KSB7XG4gICAgbGV0IGtleXMgPSB0YXJnZXQuX2tleXM7XG4gICAgaWYgKCFrZXlzKSB7XG4gICAgICAgIGtleXMgPSB0YXJnZXQuX2tleXMgPSByZXNvbHZlS2V5c0Zyb21BbGxTY29wZXModGFyZ2V0Ll9zY29wZXMpO1xuICAgIH1cbiAgICByZXR1cm4ga2V5cztcbn1cbmZ1bmN0aW9uIHJlc29sdmVLZXlzRnJvbUFsbFNjb3BlcyhzY29wZXMpIHtcbiAgICBjb25zdCBzZXQgPSBuZXcgU2V0KCk7XG4gICAgZm9yIChjb25zdCBzY29wZSBvZiBzY29wZXMpe1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzY29wZSkuZmlsdGVyKChrKT0+IWsuc3RhcnRzV2l0aCgnXycpKSl7XG4gICAgICAgICAgICBzZXQuYWRkKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIEFycmF5LmZyb20oc2V0KTtcbn1cbmZ1bmN0aW9uIF9wYXJzZU9iamVjdERhdGFSYWRpYWxTY2FsZShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpIHtcbiAgICBjb25zdCB7IGlTY2FsZSAgfSA9IG1ldGE7XG4gICAgY29uc3QgeyBrZXkgPSdyJyAgfSA9IHRoaXMuX3BhcnNpbmc7XG4gICAgY29uc3QgcGFyc2VkID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICBsZXQgaSwgaWxlbiwgaW5kZXgsIGl0ZW07XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gY291bnQ7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBpbmRleCA9IGkgKyBzdGFydDtcbiAgICAgICAgaXRlbSA9IGRhdGFbaW5kZXhdO1xuICAgICAgICBwYXJzZWRbaV0gPSB7XG4gICAgICAgICAgICByOiBpU2NhbGUucGFyc2UocmVzb2x2ZU9iamVjdEtleShpdGVtLCBrZXkpLCBpbmRleClcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlZDtcbn1cblxuY29uc3QgRVBTSUxPTiA9IE51bWJlci5FUFNJTE9OIHx8IDFlLTE0O1xuY29uc3QgZ2V0UG9pbnQgPSAocG9pbnRzLCBpKT0+aSA8IHBvaW50cy5sZW5ndGggJiYgIXBvaW50c1tpXS5za2lwICYmIHBvaW50c1tpXTtcbmNvbnN0IGdldFZhbHVlQXhpcyA9IChpbmRleEF4aXMpPT5pbmRleEF4aXMgPT09ICd4JyA/ICd5JyA6ICd4JztcbmZ1bmN0aW9uIHNwbGluZUN1cnZlKGZpcnN0UG9pbnQsIG1pZGRsZVBvaW50LCBhZnRlclBvaW50LCB0KSB7XG4gICAgLy8gUHJvcHMgdG8gUm9iIFNwZW5jZXIgYXQgc2NhbGVkIGlubm92YXRpb24gZm9yIGhpcyBwb3N0IG9uIHNwbGluaW5nIGJldHdlZW4gcG9pbnRzXG4gICAgLy8gaHR0cDovL3NjYWxlZGlubm92YXRpb24uY29tL2FuYWx5dGljcy9zcGxpbmVzL2Fib3V0U3BsaW5lcy5odG1sXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBtdXN0IGFsc28gcmVzcGVjdCBcInNraXBwZWRcIiBwb2ludHNcbiAgICBjb25zdCBwcmV2aW91cyA9IGZpcnN0UG9pbnQuc2tpcCA/IG1pZGRsZVBvaW50IDogZmlyc3RQb2ludDtcbiAgICBjb25zdCBjdXJyZW50ID0gbWlkZGxlUG9pbnQ7XG4gICAgY29uc3QgbmV4dCA9IGFmdGVyUG9pbnQuc2tpcCA/IG1pZGRsZVBvaW50IDogYWZ0ZXJQb2ludDtcbiAgICBjb25zdCBkMDEgPSBkaXN0YW5jZUJldHdlZW5Qb2ludHMoY3VycmVudCwgcHJldmlvdXMpO1xuICAgIGNvbnN0IGQxMiA9IGRpc3RhbmNlQmV0d2VlblBvaW50cyhuZXh0LCBjdXJyZW50KTtcbiAgICBsZXQgczAxID0gZDAxIC8gKGQwMSArIGQxMik7XG4gICAgbGV0IHMxMiA9IGQxMiAvIChkMDEgKyBkMTIpO1xuICAgIC8vIElmIGFsbCBwb2ludHMgYXJlIHRoZSBzYW1lLCBzMDEgJiBzMDIgd2lsbCBiZSBpbmZcbiAgICBzMDEgPSBpc05hTihzMDEpID8gMCA6IHMwMTtcbiAgICBzMTIgPSBpc05hTihzMTIpID8gMCA6IHMxMjtcbiAgICBjb25zdCBmYSA9IHQgKiBzMDE7IC8vIHNjYWxpbmcgZmFjdG9yIGZvciB0cmlhbmdsZSBUYVxuICAgIGNvbnN0IGZiID0gdCAqIHMxMjtcbiAgICByZXR1cm4ge1xuICAgICAgICBwcmV2aW91czoge1xuICAgICAgICAgICAgeDogY3VycmVudC54IC0gZmEgKiAobmV4dC54IC0gcHJldmlvdXMueCksXG4gICAgICAgICAgICB5OiBjdXJyZW50LnkgLSBmYSAqIChuZXh0LnkgLSBwcmV2aW91cy55KVxuICAgICAgICB9LFxuICAgICAgICBuZXh0OiB7XG4gICAgICAgICAgICB4OiBjdXJyZW50LnggKyBmYiAqIChuZXh0LnggLSBwcmV2aW91cy54KSxcbiAgICAgICAgICAgIHk6IGN1cnJlbnQueSArIGZiICogKG5leHQueSAtIHByZXZpb3VzLnkpXG4gICAgICAgIH1cbiAgICB9O1xufVxuLyoqXG4gKiBBZGp1c3QgdGFuZ2VudHMgdG8gZW5zdXJlIG1vbm90b25pYyBwcm9wZXJ0aWVzXG4gKi8gZnVuY3Rpb24gbW9ub3RvbmVBZGp1c3QocG9pbnRzLCBkZWx0YUssIG1LKSB7XG4gICAgY29uc3QgcG9pbnRzTGVuID0gcG9pbnRzLmxlbmd0aDtcbiAgICBsZXQgYWxwaGFLLCBiZXRhSywgdGF1Sywgc3F1YXJlZE1hZ25pdHVkZSwgcG9pbnRDdXJyZW50O1xuICAgIGxldCBwb2ludEFmdGVyID0gZ2V0UG9pbnQocG9pbnRzLCAwKTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgcG9pbnRzTGVuIC0gMTsgKytpKXtcbiAgICAgICAgcG9pbnRDdXJyZW50ID0gcG9pbnRBZnRlcjtcbiAgICAgICAgcG9pbnRBZnRlciA9IGdldFBvaW50KHBvaW50cywgaSArIDEpO1xuICAgICAgICBpZiAoIXBvaW50Q3VycmVudCB8fCAhcG9pbnRBZnRlcikge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFsbW9zdEVxdWFscyhkZWx0YUtbaV0sIDAsIEVQU0lMT04pKSB7XG4gICAgICAgICAgICBtS1tpXSA9IG1LW2kgKyAxXSA9IDA7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBhbHBoYUsgPSBtS1tpXSAvIGRlbHRhS1tpXTtcbiAgICAgICAgYmV0YUsgPSBtS1tpICsgMV0gLyBkZWx0YUtbaV07XG4gICAgICAgIHNxdWFyZWRNYWduaXR1ZGUgPSBNYXRoLnBvdyhhbHBoYUssIDIpICsgTWF0aC5wb3coYmV0YUssIDIpO1xuICAgICAgICBpZiAoc3F1YXJlZE1hZ25pdHVkZSA8PSA5KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0YXVLID0gMyAvIE1hdGguc3FydChzcXVhcmVkTWFnbml0dWRlKTtcbiAgICAgICAgbUtbaV0gPSBhbHBoYUsgKiB0YXVLICogZGVsdGFLW2ldO1xuICAgICAgICBtS1tpICsgMV0gPSBiZXRhSyAqIHRhdUsgKiBkZWx0YUtbaV07XG4gICAgfVxufVxuZnVuY3Rpb24gbW9ub3RvbmVDb21wdXRlKHBvaW50cywgbUssIGluZGV4QXhpcyA9ICd4Jykge1xuICAgIGNvbnN0IHZhbHVlQXhpcyA9IGdldFZhbHVlQXhpcyhpbmRleEF4aXMpO1xuICAgIGNvbnN0IHBvaW50c0xlbiA9IHBvaW50cy5sZW5ndGg7XG4gICAgbGV0IGRlbHRhLCBwb2ludEJlZm9yZSwgcG9pbnRDdXJyZW50O1xuICAgIGxldCBwb2ludEFmdGVyID0gZ2V0UG9pbnQocG9pbnRzLCAwKTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgcG9pbnRzTGVuOyArK2kpe1xuICAgICAgICBwb2ludEJlZm9yZSA9IHBvaW50Q3VycmVudDtcbiAgICAgICAgcG9pbnRDdXJyZW50ID0gcG9pbnRBZnRlcjtcbiAgICAgICAgcG9pbnRBZnRlciA9IGdldFBvaW50KHBvaW50cywgaSArIDEpO1xuICAgICAgICBpZiAoIXBvaW50Q3VycmVudCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaVBpeGVsID0gcG9pbnRDdXJyZW50W2luZGV4QXhpc107XG4gICAgICAgIGNvbnN0IHZQaXhlbCA9IHBvaW50Q3VycmVudFt2YWx1ZUF4aXNdO1xuICAgICAgICBpZiAocG9pbnRCZWZvcmUpIHtcbiAgICAgICAgICAgIGRlbHRhID0gKGlQaXhlbCAtIHBvaW50QmVmb3JlW2luZGV4QXhpc10pIC8gMztcbiAgICAgICAgICAgIHBvaW50Q3VycmVudFtgY3AxJHtpbmRleEF4aXN9YF0gPSBpUGl4ZWwgLSBkZWx0YTtcbiAgICAgICAgICAgIHBvaW50Q3VycmVudFtgY3AxJHt2YWx1ZUF4aXN9YF0gPSB2UGl4ZWwgLSBkZWx0YSAqIG1LW2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb2ludEFmdGVyKSB7XG4gICAgICAgICAgICBkZWx0YSA9IChwb2ludEFmdGVyW2luZGV4QXhpc10gLSBpUGl4ZWwpIC8gMztcbiAgICAgICAgICAgIHBvaW50Q3VycmVudFtgY3AyJHtpbmRleEF4aXN9YF0gPSBpUGl4ZWwgKyBkZWx0YTtcbiAgICAgICAgICAgIHBvaW50Q3VycmVudFtgY3AyJHt2YWx1ZUF4aXN9YF0gPSB2UGl4ZWwgKyBkZWx0YSAqIG1LW2ldO1xuICAgICAgICB9XG4gICAgfVxufVxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGNhbGN1bGF0ZXMgQsOpemllciBjb250cm9sIHBvaW50cyBpbiBhIHNpbWlsYXIgd2F5IHRoYW4gfHNwbGluZUN1cnZlfCxcbiAqIGJ1dCBwcmVzZXJ2ZXMgbW9ub3RvbmljaXR5IG9mIHRoZSBwcm92aWRlZCBkYXRhIGFuZCBlbnN1cmVzIG5vIGxvY2FsIGV4dHJlbXVtcyBhcmUgYWRkZWRcbiAqIGJldHdlZW4gdGhlIGRhdGFzZXQgZGlzY3JldGUgcG9pbnRzIGR1ZSB0byB0aGUgaW50ZXJwb2xhdGlvbi5cbiAqIFNlZSA6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01vbm90b25lX2N1YmljX2ludGVycG9sYXRpb25cbiAqLyBmdW5jdGlvbiBzcGxpbmVDdXJ2ZU1vbm90b25lKHBvaW50cywgaW5kZXhBeGlzID0gJ3gnKSB7XG4gICAgY29uc3QgdmFsdWVBeGlzID0gZ2V0VmFsdWVBeGlzKGluZGV4QXhpcyk7XG4gICAgY29uc3QgcG9pbnRzTGVuID0gcG9pbnRzLmxlbmd0aDtcbiAgICBjb25zdCBkZWx0YUsgPSBBcnJheShwb2ludHNMZW4pLmZpbGwoMCk7XG4gICAgY29uc3QgbUsgPSBBcnJheShwb2ludHNMZW4pO1xuICAgIC8vIENhbGN1bGF0ZSBzbG9wZXMgKGRlbHRhSykgYW5kIGluaXRpYWxpemUgdGFuZ2VudHMgKG1LKVxuICAgIGxldCBpLCBwb2ludEJlZm9yZSwgcG9pbnRDdXJyZW50O1xuICAgIGxldCBwb2ludEFmdGVyID0gZ2V0UG9pbnQocG9pbnRzLCAwKTtcbiAgICBmb3IoaSA9IDA7IGkgPCBwb2ludHNMZW47ICsraSl7XG4gICAgICAgIHBvaW50QmVmb3JlID0gcG9pbnRDdXJyZW50O1xuICAgICAgICBwb2ludEN1cnJlbnQgPSBwb2ludEFmdGVyO1xuICAgICAgICBwb2ludEFmdGVyID0gZ2V0UG9pbnQocG9pbnRzLCBpICsgMSk7XG4gICAgICAgIGlmICghcG9pbnRDdXJyZW50KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocG9pbnRBZnRlcikge1xuICAgICAgICAgICAgY29uc3Qgc2xvcGVEZWx0YSA9IHBvaW50QWZ0ZXJbaW5kZXhBeGlzXSAtIHBvaW50Q3VycmVudFtpbmRleEF4aXNdO1xuICAgICAgICAgICAgLy8gSW4gdGhlIGNhc2Ugb2YgdHdvIHBvaW50cyB0aGF0IGFwcGVhciBhdCB0aGUgc2FtZSB4IHBpeGVsLCBzbG9wZURlbHRhWCBpcyAwXG4gICAgICAgICAgICBkZWx0YUtbaV0gPSBzbG9wZURlbHRhICE9PSAwID8gKHBvaW50QWZ0ZXJbdmFsdWVBeGlzXSAtIHBvaW50Q3VycmVudFt2YWx1ZUF4aXNdKSAvIHNsb3BlRGVsdGEgOiAwO1xuICAgICAgICB9XG4gICAgICAgIG1LW2ldID0gIXBvaW50QmVmb3JlID8gZGVsdGFLW2ldIDogIXBvaW50QWZ0ZXIgPyBkZWx0YUtbaSAtIDFdIDogc2lnbihkZWx0YUtbaSAtIDFdKSAhPT0gc2lnbihkZWx0YUtbaV0pID8gMCA6IChkZWx0YUtbaSAtIDFdICsgZGVsdGFLW2ldKSAvIDI7XG4gICAgfVxuICAgIG1vbm90b25lQWRqdXN0KHBvaW50cywgZGVsdGFLLCBtSyk7XG4gICAgbW9ub3RvbmVDb21wdXRlKHBvaW50cywgbUssIGluZGV4QXhpcyk7XG59XG5mdW5jdGlvbiBjYXBDb250cm9sUG9pbnQocHQsIG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KE1hdGgubWluKHB0LCBtYXgpLCBtaW4pO1xufVxuZnVuY3Rpb24gY2FwQmV6aWVyUG9pbnRzKHBvaW50cywgYXJlYSkge1xuICAgIGxldCBpLCBpbGVuLCBwb2ludCwgaW5BcmVhLCBpbkFyZWFQcmV2O1xuICAgIGxldCBpbkFyZWFOZXh0ID0gX2lzUG9pbnRJbkFyZWEocG9pbnRzWzBdLCBhcmVhKTtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgaW5BcmVhUHJldiA9IGluQXJlYTtcbiAgICAgICAgaW5BcmVhID0gaW5BcmVhTmV4dDtcbiAgICAgICAgaW5BcmVhTmV4dCA9IGkgPCBpbGVuIC0gMSAmJiBfaXNQb2ludEluQXJlYShwb2ludHNbaSArIDFdLCBhcmVhKTtcbiAgICAgICAgaWYgKCFpbkFyZWEpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgICBpZiAoaW5BcmVhUHJldikge1xuICAgICAgICAgICAgcG9pbnQuY3AxeCA9IGNhcENvbnRyb2xQb2ludChwb2ludC5jcDF4LCBhcmVhLmxlZnQsIGFyZWEucmlnaHQpO1xuICAgICAgICAgICAgcG9pbnQuY3AxeSA9IGNhcENvbnRyb2xQb2ludChwb2ludC5jcDF5LCBhcmVhLnRvcCwgYXJlYS5ib3R0b20pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpbkFyZWFOZXh0KSB7XG4gICAgICAgICAgICBwb2ludC5jcDJ4ID0gY2FwQ29udHJvbFBvaW50KHBvaW50LmNwMngsIGFyZWEubGVmdCwgYXJlYS5yaWdodCk7XG4gICAgICAgICAgICBwb2ludC5jcDJ5ID0gY2FwQ29udHJvbFBvaW50KHBvaW50LmNwMnksIGFyZWEudG9wLCBhcmVhLmJvdHRvbSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX3VwZGF0ZUJlemllckNvbnRyb2xQb2ludHMocG9pbnRzLCBvcHRpb25zLCBhcmVhLCBsb29wLCBpbmRleEF4aXMpIHtcbiAgICBsZXQgaSwgaWxlbiwgcG9pbnQsIGNvbnRyb2xQb2ludHM7XG4gICAgLy8gT25seSBjb25zaWRlciBwb2ludHMgdGhhdCBhcmUgZHJhd24gaW4gY2FzZSB0aGUgc3BhbkdhcHMgb3B0aW9uIGlzIHVzZWRcbiAgICBpZiAob3B0aW9ucy5zcGFuR2Fwcykge1xuICAgICAgICBwb2ludHMgPSBwb2ludHMuZmlsdGVyKChwdCk9PiFwdC5za2lwKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZSA9PT0gJ21vbm90b25lJykge1xuICAgICAgICBzcGxpbmVDdXJ2ZU1vbm90b25lKHBvaW50cywgaW5kZXhBeGlzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcHJldiA9IGxvb3AgPyBwb2ludHNbcG9pbnRzLmxlbmd0aCAtIDFdIDogcG9pbnRzWzBdO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgICAgICAgY29udHJvbFBvaW50cyA9IHNwbGluZUN1cnZlKHByZXYsIHBvaW50LCBwb2ludHNbTWF0aC5taW4oaSArIDEsIGlsZW4gLSAobG9vcCA/IDAgOiAxKSkgJSBpbGVuXSwgb3B0aW9ucy50ZW5zaW9uKTtcbiAgICAgICAgICAgIHBvaW50LmNwMXggPSBjb250cm9sUG9pbnRzLnByZXZpb3VzLng7XG4gICAgICAgICAgICBwb2ludC5jcDF5ID0gY29udHJvbFBvaW50cy5wcmV2aW91cy55O1xuICAgICAgICAgICAgcG9pbnQuY3AyeCA9IGNvbnRyb2xQb2ludHMubmV4dC54O1xuICAgICAgICAgICAgcG9pbnQuY3AyeSA9IGNvbnRyb2xQb2ludHMubmV4dC55O1xuICAgICAgICAgICAgcHJldiA9IHBvaW50O1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmNhcEJlemllclBvaW50cykge1xuICAgICAgICBjYXBCZXppZXJQb2ludHMocG9pbnRzLCBhcmVhKTtcbiAgICB9XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfaXNEb21TdXBwb3J0ZWQoKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCc7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2dldFBhcmVudE5vZGUoZG9tTm9kZSkge1xuICAgIGxldCBwYXJlbnQgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgaWYgKHBhcmVudCAmJiBwYXJlbnQudG9TdHJpbmcoKSA9PT0gJ1tvYmplY3QgU2hhZG93Um9vdF0nKSB7XG4gICAgICAgIHBhcmVudCA9IHBhcmVudC5ob3N0O1xuICAgIH1cbiAgICByZXR1cm4gcGFyZW50O1xufVxuLyoqXG4gKiBjb252ZXJ0IG1heC13aWR0aC9tYXgtaGVpZ2h0IHZhbHVlcyB0aGF0IG1heSBiZSBwZXJjZW50YWdlcyBpbnRvIGEgbnVtYmVyXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIHBhcnNlTWF4U3R5bGUoc3R5bGVWYWx1ZSwgbm9kZSwgcGFyZW50UHJvcGVydHkpIHtcbiAgICBsZXQgdmFsdWVJblBpeGVscztcbiAgICBpZiAodHlwZW9mIHN0eWxlVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHZhbHVlSW5QaXhlbHMgPSBwYXJzZUludChzdHlsZVZhbHVlLCAxMCk7XG4gICAgICAgIGlmIChzdHlsZVZhbHVlLmluZGV4T2YoJyUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIHBlcmNlbnRhZ2UgKiBzaXplIGluIGRpbWVuc2lvblxuICAgICAgICAgICAgdmFsdWVJblBpeGVscyA9IHZhbHVlSW5QaXhlbHMgLyAxMDAgKiBub2RlLnBhcmVudE5vZGVbcGFyZW50UHJvcGVydHldO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWVJblBpeGVscyA9IHN0eWxlVmFsdWU7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZUluUGl4ZWxzO1xufVxuY29uc3QgZ2V0Q29tcHV0ZWRTdHlsZSA9IChlbGVtZW50KT0+ZWxlbWVudC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCwgbnVsbCk7XG5mdW5jdGlvbiBnZXRTdHlsZShlbCwgcHJvcGVydHkpIHtcbiAgICByZXR1cm4gZ2V0Q29tcHV0ZWRTdHlsZShlbCkuZ2V0UHJvcGVydHlWYWx1ZShwcm9wZXJ0eSk7XG59XG5jb25zdCBwb3NpdGlvbnMgPSBbXG4gICAgJ3RvcCcsXG4gICAgJ3JpZ2h0JyxcbiAgICAnYm90dG9tJyxcbiAgICAnbGVmdCdcbl07XG5mdW5jdGlvbiBnZXRQb3NpdGlvbmVkU3R5bGUoc3R5bGVzLCBzdHlsZSwgc3VmZml4KSB7XG4gICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgc3VmZml4ID0gc3VmZml4ID8gJy0nICsgc3VmZml4IDogJyc7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IDQ7IGkrKyl7XG4gICAgICAgIGNvbnN0IHBvcyA9IHBvc2l0aW9uc1tpXTtcbiAgICAgICAgcmVzdWx0W3Bvc10gPSBwYXJzZUZsb2F0KHN0eWxlc1tzdHlsZSArICctJyArIHBvcyArIHN1ZmZpeF0pIHx8IDA7XG4gICAgfVxuICAgIHJlc3VsdC53aWR0aCA9IHJlc3VsdC5sZWZ0ICsgcmVzdWx0LnJpZ2h0O1xuICAgIHJlc3VsdC5oZWlnaHQgPSByZXN1bHQudG9wICsgcmVzdWx0LmJvdHRvbTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuY29uc3QgdXNlT2Zmc2V0UG9zID0gKHgsIHksIHRhcmdldCk9Pih4ID4gMCB8fCB5ID4gMCkgJiYgKCF0YXJnZXQgfHwgIXRhcmdldC5zaGFkb3dSb290KTtcbi8qKlxuICogQHBhcmFtIGVcbiAqIEBwYXJhbSBjYW52YXNcbiAqIEByZXR1cm5zIENhbnZhcyBwb3NpdGlvblxuICovIGZ1bmN0aW9uIGdldENhbnZhc1Bvc2l0aW9uKGUsIGNhbnZhcykge1xuICAgIGNvbnN0IHRvdWNoZXMgPSBlLnRvdWNoZXM7XG4gICAgY29uc3Qgc291cmNlID0gdG91Y2hlcyAmJiB0b3VjaGVzLmxlbmd0aCA/IHRvdWNoZXNbMF0gOiBlO1xuICAgIGNvbnN0IHsgb2Zmc2V0WCAsIG9mZnNldFkgIH0gPSBzb3VyY2U7XG4gICAgbGV0IGJveCA9IGZhbHNlO1xuICAgIGxldCB4LCB5O1xuICAgIGlmICh1c2VPZmZzZXRQb3Mob2Zmc2V0WCwgb2Zmc2V0WSwgZS50YXJnZXQpKSB7XG4gICAgICAgIHggPSBvZmZzZXRYO1xuICAgICAgICB5ID0gb2Zmc2V0WTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCByZWN0ID0gY2FudmFzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB4ID0gc291cmNlLmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgICAgIHkgPSBzb3VyY2UuY2xpZW50WSAtIHJlY3QudG9wO1xuICAgICAgICBib3ggPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICB4LFxuICAgICAgICB5LFxuICAgICAgICBib3hcbiAgICB9O1xufVxuLyoqXG4gKiBHZXRzIGFuIGV2ZW50J3MgeCwgeSBjb29yZGluYXRlcywgcmVsYXRpdmUgdG8gdGhlIGNoYXJ0IGFyZWFcbiAqIEBwYXJhbSBldmVudFxuICogQHBhcmFtIGNoYXJ0XG4gKiBAcmV0dXJucyB4IGFuZCB5IGNvb3JkaW5hdGVzIG9mIHRoZSBldmVudFxuICovIGZ1bmN0aW9uIGdldFJlbGF0aXZlUG9zaXRpb24oZXZlbnQsIGNoYXJ0KSB7XG4gICAgaWYgKCduYXRpdmUnIGluIGV2ZW50KSB7XG4gICAgICAgIHJldHVybiBldmVudDtcbiAgICB9XG4gICAgY29uc3QgeyBjYW52YXMgLCBjdXJyZW50RGV2aWNlUGl4ZWxSYXRpbyAgfSA9IGNoYXJ0O1xuICAgIGNvbnN0IHN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShjYW52YXMpO1xuICAgIGNvbnN0IGJvcmRlckJveCA9IHN0eWxlLmJveFNpemluZyA9PT0gJ2JvcmRlci1ib3gnO1xuICAgIGNvbnN0IHBhZGRpbmdzID0gZ2V0UG9zaXRpb25lZFN0eWxlKHN0eWxlLCAncGFkZGluZycpO1xuICAgIGNvbnN0IGJvcmRlcnMgPSBnZXRQb3NpdGlvbmVkU3R5bGUoc3R5bGUsICdib3JkZXInLCAnd2lkdGgnKTtcbiAgICBjb25zdCB7IHggLCB5ICwgYm94ICB9ID0gZ2V0Q2FudmFzUG9zaXRpb24oZXZlbnQsIGNhbnZhcyk7XG4gICAgY29uc3QgeE9mZnNldCA9IHBhZGRpbmdzLmxlZnQgKyAoYm94ICYmIGJvcmRlcnMubGVmdCk7XG4gICAgY29uc3QgeU9mZnNldCA9IHBhZGRpbmdzLnRvcCArIChib3ggJiYgYm9yZGVycy50b3ApO1xuICAgIGxldCB7IHdpZHRoICwgaGVpZ2h0ICB9ID0gY2hhcnQ7XG4gICAgaWYgKGJvcmRlckJveCkge1xuICAgICAgICB3aWR0aCAtPSBwYWRkaW5ncy53aWR0aCArIGJvcmRlcnMud2lkdGg7XG4gICAgICAgIGhlaWdodCAtPSBwYWRkaW5ncy5oZWlnaHQgKyBib3JkZXJzLmhlaWdodDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogTWF0aC5yb3VuZCgoeCAtIHhPZmZzZXQpIC8gd2lkdGggKiBjYW52YXMud2lkdGggLyBjdXJyZW50RGV2aWNlUGl4ZWxSYXRpbyksXG4gICAgICAgIHk6IE1hdGgucm91bmQoKHkgLSB5T2Zmc2V0KSAvIGhlaWdodCAqIGNhbnZhcy5oZWlnaHQgLyBjdXJyZW50RGV2aWNlUGl4ZWxSYXRpbylcbiAgICB9O1xufVxuZnVuY3Rpb24gZ2V0Q29udGFpbmVyU2l6ZShjYW52YXMsIHdpZHRoLCBoZWlnaHQpIHtcbiAgICBsZXQgbWF4V2lkdGgsIG1heEhlaWdodDtcbiAgICBpZiAod2lkdGggPT09IHVuZGVmaW5lZCB8fCBoZWlnaHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCBjb250YWluZXIgPSBjYW52YXMgJiYgX2dldFBhcmVudE5vZGUoY2FudmFzKTtcbiAgICAgICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgICAgICAgIHdpZHRoID0gY2FudmFzLmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgaGVpZ2h0ID0gY2FudmFzLmNsaWVudEhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IC8vIHRoaXMgaXMgdGhlIGJvcmRlciBib3ggb2YgdGhlIGNvbnRhaW5lclxuICAgICAgICAgICAgY29uc3QgY29udGFpbmVyU3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGNvbnRhaW5lcik7XG4gICAgICAgICAgICBjb25zdCBjb250YWluZXJCb3JkZXIgPSBnZXRQb3NpdGlvbmVkU3R5bGUoY29udGFpbmVyU3R5bGUsICdib3JkZXInLCAnd2lkdGgnKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lclBhZGRpbmcgPSBnZXRQb3NpdGlvbmVkU3R5bGUoY29udGFpbmVyU3R5bGUsICdwYWRkaW5nJyk7XG4gICAgICAgICAgICB3aWR0aCA9IHJlY3Qud2lkdGggLSBjb250YWluZXJQYWRkaW5nLndpZHRoIC0gY29udGFpbmVyQm9yZGVyLndpZHRoO1xuICAgICAgICAgICAgaGVpZ2h0ID0gcmVjdC5oZWlnaHQgLSBjb250YWluZXJQYWRkaW5nLmhlaWdodCAtIGNvbnRhaW5lckJvcmRlci5oZWlnaHQ7XG4gICAgICAgICAgICBtYXhXaWR0aCA9IHBhcnNlTWF4U3R5bGUoY29udGFpbmVyU3R5bGUubWF4V2lkdGgsIGNvbnRhaW5lciwgJ2NsaWVudFdpZHRoJyk7XG4gICAgICAgICAgICBtYXhIZWlnaHQgPSBwYXJzZU1heFN0eWxlKGNvbnRhaW5lclN0eWxlLm1heEhlaWdodCwgY29udGFpbmVyLCAnY2xpZW50SGVpZ2h0Jyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodCxcbiAgICAgICAgbWF4V2lkdGg6IG1heFdpZHRoIHx8IElORklOSVRZLFxuICAgICAgICBtYXhIZWlnaHQ6IG1heEhlaWdodCB8fCBJTkZJTklUWVxuICAgIH07XG59XG5jb25zdCByb3VuZDEgPSAodik9Pk1hdGgucm91bmQodiAqIDEwKSAvIDEwO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmZ1bmN0aW9uIGdldE1heGltdW1TaXplKGNhbnZhcywgYmJXaWR0aCwgYmJIZWlnaHQsIGFzcGVjdFJhdGlvKSB7XG4gICAgY29uc3Qgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGNhbnZhcyk7XG4gICAgY29uc3QgbWFyZ2lucyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ21hcmdpbicpO1xuICAgIGNvbnN0IG1heFdpZHRoID0gcGFyc2VNYXhTdHlsZShzdHlsZS5tYXhXaWR0aCwgY2FudmFzLCAnY2xpZW50V2lkdGgnKSB8fCBJTkZJTklUWTtcbiAgICBjb25zdCBtYXhIZWlnaHQgPSBwYXJzZU1heFN0eWxlKHN0eWxlLm1heEhlaWdodCwgY2FudmFzLCAnY2xpZW50SGVpZ2h0JykgfHwgSU5GSU5JVFk7XG4gICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IGdldENvbnRhaW5lclNpemUoY2FudmFzLCBiYldpZHRoLCBiYkhlaWdodCk7XG4gICAgbGV0IHsgd2lkdGggLCBoZWlnaHQgIH0gPSBjb250YWluZXJTaXplO1xuICAgIGlmIChzdHlsZS5ib3hTaXppbmcgPT09ICdjb250ZW50LWJveCcpIHtcbiAgICAgICAgY29uc3QgYm9yZGVycyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ2JvcmRlcicsICd3aWR0aCcpO1xuICAgICAgICBjb25zdCBwYWRkaW5ncyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ3BhZGRpbmcnKTtcbiAgICAgICAgd2lkdGggLT0gcGFkZGluZ3Mud2lkdGggKyBib3JkZXJzLndpZHRoO1xuICAgICAgICBoZWlnaHQgLT0gcGFkZGluZ3MuaGVpZ2h0ICsgYm9yZGVycy5oZWlnaHQ7XG4gICAgfVxuICAgIHdpZHRoID0gTWF0aC5tYXgoMCwgd2lkdGggLSBtYXJnaW5zLndpZHRoKTtcbiAgICBoZWlnaHQgPSBNYXRoLm1heCgwLCBhc3BlY3RSYXRpbyA/IHdpZHRoIC8gYXNwZWN0UmF0aW8gOiBoZWlnaHQgLSBtYXJnaW5zLmhlaWdodCk7XG4gICAgd2lkdGggPSByb3VuZDEoTWF0aC5taW4od2lkdGgsIG1heFdpZHRoLCBjb250YWluZXJTaXplLm1heFdpZHRoKSk7XG4gICAgaGVpZ2h0ID0gcm91bmQxKE1hdGgubWluKGhlaWdodCwgbWF4SGVpZ2h0LCBjb250YWluZXJTaXplLm1heEhlaWdodCkpO1xuICAgIGlmICh3aWR0aCAmJiAhaGVpZ2h0KSB7XG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL0NoYXJ0LmpzL2lzc3Vlcy80NjU5XG4gICAgICAgIC8vIElmIHRoZSBjYW52YXMgaGFzIHdpZHRoLCBidXQgbm8gaGVpZ2h0LCBkZWZhdWx0IHRvIGFzcGVjdFJhdGlvIG9mIDIgKGNhbnZhcyBkZWZhdWx0KVxuICAgICAgICBoZWlnaHQgPSByb3VuZDEod2lkdGggLyAyKTtcbiAgICB9XG4gICAgY29uc3QgbWFpbnRhaW5IZWlnaHQgPSBiYldpZHRoICE9PSB1bmRlZmluZWQgfHwgYmJIZWlnaHQgIT09IHVuZGVmaW5lZDtcbiAgICBpZiAobWFpbnRhaW5IZWlnaHQgJiYgYXNwZWN0UmF0aW8gJiYgY29udGFpbmVyU2l6ZS5oZWlnaHQgJiYgaGVpZ2h0ID4gY29udGFpbmVyU2l6ZS5oZWlnaHQpIHtcbiAgICAgICAgaGVpZ2h0ID0gY29udGFpbmVyU2l6ZS5oZWlnaHQ7XG4gICAgICAgIHdpZHRoID0gcm91bmQxKE1hdGguZmxvb3IoaGVpZ2h0ICogYXNwZWN0UmF0aW8pKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodFxuICAgIH07XG59XG4vKipcbiAqIEBwYXJhbSBjaGFydFxuICogQHBhcmFtIGZvcmNlUmF0aW9cbiAqIEBwYXJhbSBmb3JjZVN0eWxlXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBjYW52YXMgY29udGV4dCBzaXplIG9yIHRyYW5zZm9ybWF0aW9uIGhhcyBjaGFuZ2VkLlxuICovIGZ1bmN0aW9uIHJldGluYVNjYWxlKGNoYXJ0LCBmb3JjZVJhdGlvLCBmb3JjZVN0eWxlKSB7XG4gICAgY29uc3QgcGl4ZWxSYXRpbyA9IGZvcmNlUmF0aW8gfHwgMTtcbiAgICBjb25zdCBkZXZpY2VIZWlnaHQgPSBNYXRoLmZsb29yKGNoYXJ0LmhlaWdodCAqIHBpeGVsUmF0aW8pO1xuICAgIGNvbnN0IGRldmljZVdpZHRoID0gTWF0aC5mbG9vcihjaGFydC53aWR0aCAqIHBpeGVsUmF0aW8pO1xuICAgIGNoYXJ0LmhlaWdodCA9IE1hdGguZmxvb3IoY2hhcnQuaGVpZ2h0KTtcbiAgICBjaGFydC53aWR0aCA9IE1hdGguZmxvb3IoY2hhcnQud2lkdGgpO1xuICAgIGNvbnN0IGNhbnZhcyA9IGNoYXJ0LmNhbnZhcztcbiAgICAvLyBJZiBubyBzdHlsZSBoYXMgYmVlbiBzZXQgb24gdGhlIGNhbnZhcywgdGhlIHJlbmRlciBzaXplIGlzIHVzZWQgYXMgZGlzcGxheSBzaXplLFxuICAgIC8vIG1ha2luZyB0aGUgY2hhcnQgdmlzdWFsbHkgYmlnZ2VyLCBzbyBsZXQncyBlbmZvcmNlIGl0IHRvIHRoZSBcImNvcnJlY3RcIiB2YWx1ZXMuXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL0NoYXJ0LmpzL2lzc3Vlcy8zNTc1XG4gICAgaWYgKGNhbnZhcy5zdHlsZSAmJiAoZm9yY2VTdHlsZSB8fCAhY2FudmFzLnN0eWxlLmhlaWdodCAmJiAhY2FudmFzLnN0eWxlLndpZHRoKSkge1xuICAgICAgICBjYW52YXMuc3R5bGUuaGVpZ2h0ID0gYCR7Y2hhcnQuaGVpZ2h0fXB4YDtcbiAgICAgICAgY2FudmFzLnN0eWxlLndpZHRoID0gYCR7Y2hhcnQud2lkdGh9cHhgO1xuICAgIH1cbiAgICBpZiAoY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW8gIT09IHBpeGVsUmF0aW8gfHwgY2FudmFzLmhlaWdodCAhPT0gZGV2aWNlSGVpZ2h0IHx8IGNhbnZhcy53aWR0aCAhPT0gZGV2aWNlV2lkdGgpIHtcbiAgICAgICAgY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW8gPSBwaXhlbFJhdGlvO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gZGV2aWNlSGVpZ2h0O1xuICAgICAgICBjYW52YXMud2lkdGggPSBkZXZpY2VXaWR0aDtcbiAgICAgICAgY2hhcnQuY3R4LnNldFRyYW5zZm9ybShwaXhlbFJhdGlvLCAwLCAwLCBwaXhlbFJhdGlvLCAwLCAwKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbi8qKlxuICogRGV0ZWN0cyBzdXBwb3J0IGZvciBvcHRpb25zIG9iamVjdCBhcmd1bWVudCBpbiBhZGRFdmVudExpc3RlbmVyLlxuICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIjU2FmZWx5X2RldGVjdGluZ19vcHRpb25fc3VwcG9ydFxuICogQHByaXZhdGVcbiAqLyBjb25zdCBzdXBwb3J0c0V2ZW50TGlzdGVuZXJPcHRpb25zID0gZnVuY3Rpb24oKSB7XG4gICAgbGV0IHBhc3NpdmVTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgZ2V0IHBhc3NpdmUgKCkge1xuICAgICAgICAgICAgICAgIHBhc3NpdmVTdXBwb3J0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKF9pc0RvbVN1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigndGVzdCcsIG51bGwsIG9wdGlvbnMpO1xuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCBudWxsLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBjb250aW51ZSByZWdhcmRsZXNzIG9mIGVycm9yXG4gICAgfVxuICAgIHJldHVybiBwYXNzaXZlU3VwcG9ydGVkO1xufSgpO1xuLyoqXG4gKiBUaGUgXCJ1c2VkXCIgc2l6ZSBpcyB0aGUgZmluYWwgdmFsdWUgb2YgYSBkaW1lbnNpb24gcHJvcGVydHkgYWZ0ZXIgYWxsIGNhbGN1bGF0aW9ucyBoYXZlXG4gKiBiZWVuIHBlcmZvcm1lZC4gVGhpcyBtZXRob2QgdXNlcyB0aGUgY29tcHV0ZWQgc3R5bGUgb2YgYGVsZW1lbnRgIGJ1dCByZXR1cm5zIHVuZGVmaW5lZFxuICogaWYgdGhlIGNvbXB1dGVkIHN0eWxlIGlzIG5vdCBleHByZXNzZWQgaW4gcGl4ZWxzLiBUaGF0IGNhbiBoYXBwZW4gaW4gc29tZSBjYXNlcyB3aGVyZVxuICogYGVsZW1lbnRgIGhhcyBhIHNpemUgcmVsYXRpdmUgdG8gaXRzIHBhcmVudCBhbmQgdGhpcyBsYXN0IG9uZSBpcyBub3QgeWV0IGRpc3BsYXllZCxcbiAqIGZvciBleGFtcGxlIGJlY2F1c2Ugb2YgYGRpc3BsYXk6IG5vbmVgIG9uIGEgcGFyZW50IG5vZGUuXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0NTUy91c2VkX3ZhbHVlXG4gKiBAcmV0dXJucyBTaXplIGluIHBpeGVscyBvciB1bmRlZmluZWQgaWYgdW5rbm93bi5cbiAqLyBmdW5jdGlvbiByZWFkVXNlZFNpemUoZWxlbWVudCwgcHJvcGVydHkpIHtcbiAgICBjb25zdCB2YWx1ZSA9IGdldFN0eWxlKGVsZW1lbnQsIHByb3BlcnR5KTtcbiAgICBjb25zdCBtYXRjaGVzID0gdmFsdWUgJiYgdmFsdWUubWF0Y2goL14oXFxkKykoXFwuXFxkKyk/cHgkLyk7XG4gICAgcmV0dXJuIG1hdGNoZXMgPyArbWF0Y2hlc1sxXSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9wb2ludEluTGluZShwMSwgcDIsIHQsIG1vZGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiBwMS54ICsgdCAqIChwMi54IC0gcDEueCksXG4gICAgICAgIHk6IHAxLnkgKyB0ICogKHAyLnkgLSBwMS55KVxuICAgIH07XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX3N0ZXBwZWRJbnRlcnBvbGF0aW9uKHAxLCBwMiwgdCwgbW9kZSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHg6IHAxLnggKyB0ICogKHAyLnggLSBwMS54KSxcbiAgICAgICAgeTogbW9kZSA9PT0gJ21pZGRsZScgPyB0IDwgMC41ID8gcDEueSA6IHAyLnkgOiBtb2RlID09PSAnYWZ0ZXInID8gdCA8IDEgPyBwMS55IDogcDIueSA6IHQgPiAwID8gcDIueSA6IHAxLnlcbiAgICB9O1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9iZXppZXJJbnRlcnBvbGF0aW9uKHAxLCBwMiwgdCwgbW9kZSkge1xuICAgIGNvbnN0IGNwMSA9IHtcbiAgICAgICAgeDogcDEuY3AyeCxcbiAgICAgICAgeTogcDEuY3AyeVxuICAgIH07XG4gICAgY29uc3QgY3AyID0ge1xuICAgICAgICB4OiBwMi5jcDF4LFxuICAgICAgICB5OiBwMi5jcDF5XG4gICAgfTtcbiAgICBjb25zdCBhID0gX3BvaW50SW5MaW5lKHAxLCBjcDEsIHQpO1xuICAgIGNvbnN0IGIgPSBfcG9pbnRJbkxpbmUoY3AxLCBjcDIsIHQpO1xuICAgIGNvbnN0IGMgPSBfcG9pbnRJbkxpbmUoY3AyLCBwMiwgdCk7XG4gICAgY29uc3QgZCA9IF9wb2ludEluTGluZShhLCBiLCB0KTtcbiAgICBjb25zdCBlID0gX3BvaW50SW5MaW5lKGIsIGMsIHQpO1xuICAgIHJldHVybiBfcG9pbnRJbkxpbmUoZCwgZSwgdCk7XG59XG5cbmNvbnN0IGdldFJpZ2h0VG9MZWZ0QWRhcHRlciA9IGZ1bmN0aW9uKHJlY3RYLCB3aWR0aCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHggKHgpIHtcbiAgICAgICAgICAgIHJldHVybiByZWN0WCArIHJlY3RYICsgd2lkdGggLSB4O1xuICAgICAgICB9LFxuICAgICAgICBzZXRXaWR0aCAodykge1xuICAgICAgICAgICAgd2lkdGggPSB3O1xuICAgICAgICB9LFxuICAgICAgICB0ZXh0QWxpZ24gKGFsaWduKSB7XG4gICAgICAgICAgICBpZiAoYWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFsaWduO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGFsaWduID09PSAncmlnaHQnID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgICAgICAgfSxcbiAgICAgICAgeFBsdXMgKHgsIHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4geCAtIHZhbHVlO1xuICAgICAgICB9LFxuICAgICAgICBsZWZ0Rm9yTHRyICh4LCBpdGVtV2lkdGgpIHtcbiAgICAgICAgICAgIHJldHVybiB4IC0gaXRlbVdpZHRoO1xuICAgICAgICB9XG4gICAgfTtcbn07XG5jb25zdCBnZXRMZWZ0VG9SaWdodEFkYXB0ZXIgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4ICh4KSB7XG4gICAgICAgICAgICByZXR1cm4geDtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0V2lkdGggKHcpIHt9LFxuICAgICAgICB0ZXh0QWxpZ24gKGFsaWduKSB7XG4gICAgICAgICAgICByZXR1cm4gYWxpZ247XG4gICAgICAgIH0sXG4gICAgICAgIHhQbHVzICh4LCB2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHggKyB2YWx1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgbGVmdEZvckx0ciAoeCwgX2l0ZW1XaWR0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHg7XG4gICAgICAgIH1cbiAgICB9O1xufTtcbmZ1bmN0aW9uIGdldFJ0bEFkYXB0ZXIocnRsLCByZWN0WCwgd2lkdGgpIHtcbiAgICByZXR1cm4gcnRsID8gZ2V0UmlnaHRUb0xlZnRBZGFwdGVyKHJlY3RYLCB3aWR0aCkgOiBnZXRMZWZ0VG9SaWdodEFkYXB0ZXIoKTtcbn1cbmZ1bmN0aW9uIG92ZXJyaWRlVGV4dERpcmVjdGlvbihjdHgsIGRpcmVjdGlvbikge1xuICAgIGxldCBzdHlsZSwgb3JpZ2luYWw7XG4gICAgaWYgKGRpcmVjdGlvbiA9PT0gJ2x0cicgfHwgZGlyZWN0aW9uID09PSAncnRsJykge1xuICAgICAgICBzdHlsZSA9IGN0eC5jYW52YXMuc3R5bGU7XG4gICAgICAgIG9yaWdpbmFsID0gW1xuICAgICAgICAgICAgc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnZGlyZWN0aW9uJyksXG4gICAgICAgICAgICBzdHlsZS5nZXRQcm9wZXJ0eVByaW9yaXR5KCdkaXJlY3Rpb24nKVxuICAgICAgICBdO1xuICAgICAgICBzdHlsZS5zZXRQcm9wZXJ0eSgnZGlyZWN0aW9uJywgZGlyZWN0aW9uLCAnaW1wb3J0YW50Jyk7XG4gICAgICAgIGN0eC5wcmV2VGV4dERpcmVjdGlvbiA9IG9yaWdpbmFsO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlc3RvcmVUZXh0RGlyZWN0aW9uKGN0eCwgb3JpZ2luYWwpIHtcbiAgICBpZiAob3JpZ2luYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBkZWxldGUgY3R4LnByZXZUZXh0RGlyZWN0aW9uO1xuICAgICAgICBjdHguY2FudmFzLnN0eWxlLnNldFByb3BlcnR5KCdkaXJlY3Rpb24nLCBvcmlnaW5hbFswXSwgb3JpZ2luYWxbMV0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcHJvcGVydHlGbihwcm9wZXJ0eSkge1xuICAgIGlmIChwcm9wZXJ0eSA9PT0gJ2FuZ2xlJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYmV0d2VlbjogX2FuZ2xlQmV0d2VlbixcbiAgICAgICAgICAgIGNvbXBhcmU6IF9hbmdsZURpZmYsXG4gICAgICAgICAgICBub3JtYWxpemU6IF9ub3JtYWxpemVBbmdsZVxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBiZXR3ZWVuOiBfaXNCZXR3ZWVuLFxuICAgICAgICBjb21wYXJlOiAoYSwgYik9PmEgLSBiLFxuICAgICAgICBub3JtYWxpemU6ICh4KT0+eFxuICAgIH07XG59XG5mdW5jdGlvbiBub3JtYWxpemVTZWdtZW50KHsgc3RhcnQgLCBlbmQgLCBjb3VudCAsIGxvb3AgLCBzdHlsZSAgfSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiBzdGFydCAlIGNvdW50LFxuICAgICAgICBlbmQ6IGVuZCAlIGNvdW50LFxuICAgICAgICBsb29wOiBsb29wICYmIChlbmQgLSBzdGFydCArIDEpICUgY291bnQgPT09IDAsXG4gICAgICAgIHN0eWxlXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldFNlZ21lbnQoc2VnbWVudCwgcG9pbnRzLCBib3VuZHMpIHtcbiAgICBjb25zdCB7IHByb3BlcnR5ICwgc3RhcnQ6IHN0YXJ0Qm91bmQgLCBlbmQ6IGVuZEJvdW5kICB9ID0gYm91bmRzO1xuICAgIGNvbnN0IHsgYmV0d2VlbiAsIG5vcm1hbGl6ZSAgfSA9IHByb3BlcnR5Rm4ocHJvcGVydHkpO1xuICAgIGNvbnN0IGNvdW50ID0gcG9pbnRzLmxlbmd0aDtcbiAgICBsZXQgeyBzdGFydCAsIGVuZCAsIGxvb3AgIH0gPSBzZWdtZW50O1xuICAgIGxldCBpLCBpbGVuO1xuICAgIGlmIChsb29wKSB7XG4gICAgICAgIHN0YXJ0ICs9IGNvdW50O1xuICAgICAgICBlbmQgKz0gY291bnQ7XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGNvdW50OyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGlmICghYmV0d2Vlbihub3JtYWxpemUocG9pbnRzW3N0YXJ0ICUgY291bnRdW3Byb3BlcnR5XSksIHN0YXJ0Qm91bmQsIGVuZEJvdW5kKSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RhcnQtLTtcbiAgICAgICAgICAgIGVuZC0tO1xuICAgICAgICB9XG4gICAgICAgIHN0YXJ0ICU9IGNvdW50O1xuICAgICAgICBlbmQgJT0gY291bnQ7XG4gICAgfVxuICAgIGlmIChlbmQgPCBzdGFydCkge1xuICAgICAgICBlbmQgKz0gY291bnQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0LFxuICAgICAgICBlbmQsXG4gICAgICAgIGxvb3AsXG4gICAgICAgIHN0eWxlOiBzZWdtZW50LnN0eWxlXG4gICAgfTtcbn1cbiBmdW5jdGlvbiBfYm91bmRTZWdtZW50KHNlZ21lbnQsIHBvaW50cywgYm91bmRzKSB7XG4gICAgaWYgKCFib3VuZHMpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHNlZ21lbnRcbiAgICAgICAgXTtcbiAgICB9XG4gICAgY29uc3QgeyBwcm9wZXJ0eSAsIHN0YXJ0OiBzdGFydEJvdW5kICwgZW5kOiBlbmRCb3VuZCAgfSA9IGJvdW5kcztcbiAgICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgY29uc3QgeyBjb21wYXJlICwgYmV0d2VlbiAsIG5vcm1hbGl6ZSAgfSA9IHByb3BlcnR5Rm4ocHJvcGVydHkpO1xuICAgIGNvbnN0IHsgc3RhcnQgLCBlbmQgLCBsb29wICwgc3R5bGUgIH0gPSBnZXRTZWdtZW50KHNlZ21lbnQsIHBvaW50cywgYm91bmRzKTtcbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5zaWRlID0gZmFsc2U7XG4gICAgbGV0IHN1YlN0YXJ0ID0gbnVsbDtcbiAgICBsZXQgdmFsdWUsIHBvaW50LCBwcmV2VmFsdWU7XG4gICAgY29uc3Qgc3RhcnRJc0JlZm9yZSA9ICgpPT5iZXR3ZWVuKHN0YXJ0Qm91bmQsIHByZXZWYWx1ZSwgdmFsdWUpICYmIGNvbXBhcmUoc3RhcnRCb3VuZCwgcHJldlZhbHVlKSAhPT0gMDtcbiAgICBjb25zdCBlbmRJc0JlZm9yZSA9ICgpPT5jb21wYXJlKGVuZEJvdW5kLCB2YWx1ZSkgPT09IDAgfHwgYmV0d2VlbihlbmRCb3VuZCwgcHJldlZhbHVlLCB2YWx1ZSk7XG4gICAgY29uc3Qgc2hvdWxkU3RhcnQgPSAoKT0+aW5zaWRlIHx8IHN0YXJ0SXNCZWZvcmUoKTtcbiAgICBjb25zdCBzaG91bGRTdG9wID0gKCk9PiFpbnNpZGUgfHwgZW5kSXNCZWZvcmUoKTtcbiAgICBmb3IobGV0IGkgPSBzdGFydCwgcHJldiA9IHN0YXJ0OyBpIDw9IGVuZDsgKytpKXtcbiAgICAgICAgcG9pbnQgPSBwb2ludHNbaSAlIGNvdW50XTtcbiAgICAgICAgaWYgKHBvaW50LnNraXApIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhbHVlID0gbm9ybWFsaXplKHBvaW50W3Byb3BlcnR5XSk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gcHJldlZhbHVlKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpbnNpZGUgPSBiZXR3ZWVuKHZhbHVlLCBzdGFydEJvdW5kLCBlbmRCb3VuZCk7XG4gICAgICAgIGlmIChzdWJTdGFydCA9PT0gbnVsbCAmJiBzaG91bGRTdGFydCgpKSB7XG4gICAgICAgICAgICBzdWJTdGFydCA9IGNvbXBhcmUodmFsdWUsIHN0YXJ0Qm91bmQpID09PSAwID8gaSA6IHByZXY7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN1YlN0YXJ0ICE9PSBudWxsICYmIHNob3VsZFN0b3AoKSkge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gobm9ybWFsaXplU2VnbWVudCh7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IHN1YlN0YXJ0LFxuICAgICAgICAgICAgICAgIGVuZDogaSxcbiAgICAgICAgICAgICAgICBsb29wLFxuICAgICAgICAgICAgICAgIGNvdW50LFxuICAgICAgICAgICAgICAgIHN0eWxlXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICBzdWJTdGFydCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcHJldiA9IGk7XG4gICAgICAgIHByZXZWYWx1ZSA9IHZhbHVlO1xuICAgIH1cbiAgICBpZiAoc3ViU3RhcnQgIT09IG51bGwpIHtcbiAgICAgICAgcmVzdWx0LnB1c2gobm9ybWFsaXplU2VnbWVudCh7XG4gICAgICAgICAgICBzdGFydDogc3ViU3RhcnQsXG4gICAgICAgICAgICBlbmQsXG4gICAgICAgICAgICBsb29wLFxuICAgICAgICAgICAgY291bnQsXG4gICAgICAgICAgICBzdHlsZVxuICAgICAgICB9KSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG4gZnVuY3Rpb24gX2JvdW5kU2VnbWVudHMobGluZSwgYm91bmRzKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgY29uc3Qgc2VnbWVudHMgPSBsaW5lLnNlZ21lbnRzO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGNvbnN0IHN1YiA9IF9ib3VuZFNlZ21lbnQoc2VnbWVudHNbaV0sIGxpbmUucG9pbnRzLCBib3VuZHMpO1xuICAgICAgICBpZiAoc3ViLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2goLi4uc3ViKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuIGZ1bmN0aW9uIGZpbmRTdGFydEFuZEVuZChwb2ludHMsIGNvdW50LCBsb29wLCBzcGFuR2Fwcykge1xuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IGVuZCA9IGNvdW50IC0gMTtcbiAgICBpZiAobG9vcCAmJiAhc3BhbkdhcHMpIHtcbiAgICAgICAgd2hpbGUoc3RhcnQgPCBjb3VudCAmJiAhcG9pbnRzW3N0YXJ0XS5za2lwKXtcbiAgICAgICAgICAgIHN0YXJ0Kys7XG4gICAgICAgIH1cbiAgICB9XG4gICAgd2hpbGUoc3RhcnQgPCBjb3VudCAmJiBwb2ludHNbc3RhcnRdLnNraXApe1xuICAgICAgICBzdGFydCsrO1xuICAgIH1cbiAgICBzdGFydCAlPSBjb3VudDtcbiAgICBpZiAobG9vcCkge1xuICAgICAgICBlbmQgKz0gc3RhcnQ7XG4gICAgfVxuICAgIHdoaWxlKGVuZCA+IHN0YXJ0ICYmIHBvaW50c1tlbmQgJSBjb3VudF0uc2tpcCl7XG4gICAgICAgIGVuZC0tO1xuICAgIH1cbiAgICBlbmQgJT0gY291bnQ7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQsXG4gICAgICAgIGVuZFxuICAgIH07XG59XG4gZnVuY3Rpb24gc29saWRTZWdtZW50cyhwb2ludHMsIHN0YXJ0LCBtYXgsIGxvb3ApIHtcbiAgICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgbGV0IGxhc3QgPSBzdGFydDtcbiAgICBsZXQgcHJldiA9IHBvaW50c1tzdGFydF07XG4gICAgbGV0IGVuZDtcbiAgICBmb3IoZW5kID0gc3RhcnQgKyAxOyBlbmQgPD0gbWF4OyArK2VuZCl7XG4gICAgICAgIGNvbnN0IGN1ciA9IHBvaW50c1tlbmQgJSBjb3VudF07XG4gICAgICAgIGlmIChjdXIuc2tpcCB8fCBjdXIuc3RvcCkge1xuICAgICAgICAgICAgaWYgKCFwcmV2LnNraXApIHtcbiAgICAgICAgICAgICAgICBsb29wID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogc3RhcnQgJSBjb3VudCxcbiAgICAgICAgICAgICAgICAgICAgZW5kOiAoZW5kIC0gMSkgJSBjb3VudCxcbiAgICAgICAgICAgICAgICAgICAgbG9vcFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gbGFzdCA9IGN1ci5zdG9wID8gZW5kIDogbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxhc3QgPSBlbmQ7XG4gICAgICAgICAgICBpZiAocHJldi5za2lwKSB7XG4gICAgICAgICAgICAgICAgc3RhcnQgPSBlbmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcHJldiA9IGN1cjtcbiAgICB9XG4gICAgaWYgKGxhc3QgIT09IG51bGwpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICAgICAgc3RhcnQ6IHN0YXJ0ICUgY291bnQsXG4gICAgICAgICAgICBlbmQ6IGxhc3QgJSBjb3VudCxcbiAgICAgICAgICAgIGxvb3BcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG4gZnVuY3Rpb24gX2NvbXB1dGVTZWdtZW50cyhsaW5lLCBzZWdtZW50T3B0aW9ucykge1xuICAgIGNvbnN0IHBvaW50cyA9IGxpbmUucG9pbnRzO1xuICAgIGNvbnN0IHNwYW5HYXBzID0gbGluZS5vcHRpb25zLnNwYW5HYXBzO1xuICAgIGNvbnN0IGNvdW50ID0gcG9pbnRzLmxlbmd0aDtcbiAgICBpZiAoIWNvdW50KSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgY29uc3QgbG9vcCA9ICEhbGluZS5fbG9vcDtcbiAgICBjb25zdCB7IHN0YXJ0ICwgZW5kICB9ID0gZmluZFN0YXJ0QW5kRW5kKHBvaW50cywgY291bnQsIGxvb3AsIHNwYW5HYXBzKTtcbiAgICBpZiAoc3BhbkdhcHMgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIHNwbGl0QnlTdHlsZXMobGluZSwgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgICAgICAgIGVuZCxcbiAgICAgICAgICAgICAgICBsb29wXG4gICAgICAgICAgICB9XG4gICAgICAgIF0sIHBvaW50cywgc2VnbWVudE9wdGlvbnMpO1xuICAgIH1cbiAgICBjb25zdCBtYXggPSBlbmQgPCBzdGFydCA/IGVuZCArIGNvdW50IDogZW5kO1xuICAgIGNvbnN0IGNvbXBsZXRlTG9vcCA9ICEhbGluZS5fZnVsbExvb3AgJiYgc3RhcnQgPT09IDAgJiYgZW5kID09PSBjb3VudCAtIDE7XG4gICAgcmV0dXJuIHNwbGl0QnlTdHlsZXMobGluZSwgc29saWRTZWdtZW50cyhwb2ludHMsIHN0YXJ0LCBtYXgsIGNvbXBsZXRlTG9vcCksIHBvaW50cywgc2VnbWVudE9wdGlvbnMpO1xufVxuIGZ1bmN0aW9uIHNwbGl0QnlTdHlsZXMobGluZSwgc2VnbWVudHMsIHBvaW50cywgc2VnbWVudE9wdGlvbnMpIHtcbiAgICBpZiAoIXNlZ21lbnRPcHRpb25zIHx8ICFzZWdtZW50T3B0aW9ucy5zZXRDb250ZXh0IHx8ICFwb2ludHMpIHtcbiAgICAgICAgcmV0dXJuIHNlZ21lbnRzO1xuICAgIH1cbiAgICByZXR1cm4gZG9TcGxpdEJ5U3R5bGVzKGxpbmUsIHNlZ21lbnRzLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKTtcbn1cbiBmdW5jdGlvbiBkb1NwbGl0QnlTdHlsZXMobGluZSwgc2VnbWVudHMsIHBvaW50cywgc2VnbWVudE9wdGlvbnMpIHtcbiAgICBjb25zdCBjaGFydENvbnRleHQgPSBsaW5lLl9jaGFydC5nZXRDb250ZXh0KCk7XG4gICAgY29uc3QgYmFzZVN0eWxlID0gcmVhZFN0eWxlKGxpbmUub3B0aW9ucyk7XG4gICAgY29uc3QgeyBfZGF0YXNldEluZGV4OiBkYXRhc2V0SW5kZXggLCBvcHRpb25zOiB7IHNwYW5HYXBzICB9ICB9ID0gbGluZTtcbiAgICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgbGV0IHByZXZTdHlsZSA9IGJhc2VTdHlsZTtcbiAgICBsZXQgc3RhcnQgPSBzZWdtZW50c1swXS5zdGFydDtcbiAgICBsZXQgaSA9IHN0YXJ0O1xuICAgIGZ1bmN0aW9uIGFkZFN0eWxlKHMsIGUsIGwsIHN0KSB7XG4gICAgICAgIGNvbnN0IGRpciA9IHNwYW5HYXBzID8gLTEgOiAxO1xuICAgICAgICBpZiAocyA9PT0gZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHMgKz0gY291bnQ7XG4gICAgICAgIHdoaWxlKHBvaW50c1tzICUgY291bnRdLnNraXApe1xuICAgICAgICAgICAgcyAtPSBkaXI7XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUocG9pbnRzW2UgJSBjb3VudF0uc2tpcCl7XG4gICAgICAgICAgICBlICs9IGRpcjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocyAlIGNvdW50ICE9PSBlICUgY291bnQpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHtcbiAgICAgICAgICAgICAgICBzdGFydDogcyAlIGNvdW50LFxuICAgICAgICAgICAgICAgIGVuZDogZSAlIGNvdW50LFxuICAgICAgICAgICAgICAgIGxvb3A6IGwsXG4gICAgICAgICAgICAgICAgc3R5bGU6IHN0XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHByZXZTdHlsZSA9IHN0O1xuICAgICAgICAgICAgc3RhcnQgPSBlICUgY291bnQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCBzZWdtZW50IG9mIHNlZ21lbnRzKXtcbiAgICAgICAgc3RhcnQgPSBzcGFuR2FwcyA/IHN0YXJ0IDogc2VnbWVudC5zdGFydDtcbiAgICAgICAgbGV0IHByZXYgPSBwb2ludHNbc3RhcnQgJSBjb3VudF07XG4gICAgICAgIGxldCBzdHlsZTtcbiAgICAgICAgZm9yKGkgPSBzdGFydCArIDE7IGkgPD0gc2VnbWVudC5lbmQ7IGkrKyl7XG4gICAgICAgICAgICBjb25zdCBwdCA9IHBvaW50c1tpICUgY291bnRdO1xuICAgICAgICAgICAgc3R5bGUgPSByZWFkU3R5bGUoc2VnbWVudE9wdGlvbnMuc2V0Q29udGV4dChjcmVhdGVDb250ZXh0KGNoYXJ0Q29udGV4dCwge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdzZWdtZW50JyxcbiAgICAgICAgICAgICAgICBwMDogcHJldixcbiAgICAgICAgICAgICAgICBwMTogcHQsXG4gICAgICAgICAgICAgICAgcDBEYXRhSW5kZXg6IChpIC0gMSkgJSBjb3VudCxcbiAgICAgICAgICAgICAgICBwMURhdGFJbmRleDogaSAlIGNvdW50LFxuICAgICAgICAgICAgICAgIGRhdGFzZXRJbmRleFxuICAgICAgICAgICAgfSkpKTtcbiAgICAgICAgICAgIGlmIChzdHlsZUNoYW5nZWQoc3R5bGUsIHByZXZTdHlsZSkpIHtcbiAgICAgICAgICAgICAgICBhZGRTdHlsZShzdGFydCwgaSAtIDEsIHNlZ21lbnQubG9vcCwgcHJldlN0eWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByZXYgPSBwdDtcbiAgICAgICAgICAgIHByZXZTdHlsZSA9IHN0eWxlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGFydCA8IGkgLSAxKSB7XG4gICAgICAgICAgICBhZGRTdHlsZShzdGFydCwgaSAtIDEsIHNlZ21lbnQubG9vcCwgcHJldlN0eWxlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gcmVhZFN0eWxlKG9wdGlvbnMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICBib3JkZXJDYXBTdHlsZTogb3B0aW9ucy5ib3JkZXJDYXBTdHlsZSxcbiAgICAgICAgYm9yZGVyRGFzaDogb3B0aW9ucy5ib3JkZXJEYXNoLFxuICAgICAgICBib3JkZXJEYXNoT2Zmc2V0OiBvcHRpb25zLmJvcmRlckRhc2hPZmZzZXQsXG4gICAgICAgIGJvcmRlckpvaW5TdHlsZTogb3B0aW9ucy5ib3JkZXJKb2luU3R5bGUsXG4gICAgICAgIGJvcmRlcldpZHRoOiBvcHRpb25zLmJvcmRlcldpZHRoLFxuICAgICAgICBib3JkZXJDb2xvcjogb3B0aW9ucy5ib3JkZXJDb2xvclxuICAgIH07XG59XG5mdW5jdGlvbiBzdHlsZUNoYW5nZWQoc3R5bGUsIHByZXZTdHlsZSkge1xuICAgIGlmICghcHJldlN0eWxlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgY2FjaGUgPSBbXTtcbiAgICBjb25zdCByZXBsYWNlciA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKCFpc1BhdHRlcm5PckdyYWRpZW50KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY2FjaGUuaW5jbHVkZXModmFsdWUpKSB7XG4gICAgICAgICAgICBjYWNoZS5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FjaGUuaW5kZXhPZih2YWx1ZSk7XG4gICAgfTtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoc3R5bGUsIHJlcGxhY2VyKSAhPT0gSlNPTi5zdHJpbmdpZnkocHJldlN0eWxlLCByZXBsYWNlcik7XG59XG5cbmZ1bmN0aW9uIGdldFNpemVGb3JBcmVhKHNjYWxlLCBjaGFydEFyZWEsIGZpZWxkKSB7XG4gICAgcmV0dXJuIHNjYWxlLm9wdGlvbnMuY2xpcCA/IHNjYWxlW2ZpZWxkXSA6IGNoYXJ0QXJlYVtmaWVsZF07XG59XG5mdW5jdGlvbiBnZXREYXRhc2V0QXJlYShtZXRhLCBjaGFydEFyZWEpIHtcbiAgICBjb25zdCB7IHhTY2FsZSAsIHlTY2FsZSAgfSA9IG1ldGE7XG4gICAgaWYgKHhTY2FsZSAmJiB5U2NhbGUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxlZnQ6IGdldFNpemVGb3JBcmVhKHhTY2FsZSwgY2hhcnRBcmVhLCAnbGVmdCcpLFxuICAgICAgICAgICAgcmlnaHQ6IGdldFNpemVGb3JBcmVhKHhTY2FsZSwgY2hhcnRBcmVhLCAncmlnaHQnKSxcbiAgICAgICAgICAgIHRvcDogZ2V0U2l6ZUZvckFyZWEoeVNjYWxlLCBjaGFydEFyZWEsICd0b3AnKSxcbiAgICAgICAgICAgIGJvdHRvbTogZ2V0U2l6ZUZvckFyZWEoeVNjYWxlLCBjaGFydEFyZWEsICdib3R0b20nKVxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gY2hhcnRBcmVhO1xufVxuZnVuY3Rpb24gZ2V0RGF0YXNldENsaXBBcmVhKGNoYXJ0LCBtZXRhKSB7XG4gICAgY29uc3QgY2xpcCA9IG1ldGEuX2NsaXA7XG4gICAgaWYgKGNsaXAuZGlzYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBhcmVhID0gZ2V0RGF0YXNldEFyZWEobWV0YSwgY2hhcnQuY2hhcnRBcmVhKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiBjbGlwLmxlZnQgPT09IGZhbHNlID8gMCA6IGFyZWEubGVmdCAtIChjbGlwLmxlZnQgPT09IHRydWUgPyAwIDogY2xpcC5sZWZ0KSxcbiAgICAgICAgcmlnaHQ6IGNsaXAucmlnaHQgPT09IGZhbHNlID8gY2hhcnQud2lkdGggOiBhcmVhLnJpZ2h0ICsgKGNsaXAucmlnaHQgPT09IHRydWUgPyAwIDogY2xpcC5yaWdodCksXG4gICAgICAgIHRvcDogY2xpcC50b3AgPT09IGZhbHNlID8gMCA6IGFyZWEudG9wIC0gKGNsaXAudG9wID09PSB0cnVlID8gMCA6IGNsaXAudG9wKSxcbiAgICAgICAgYm90dG9tOiBjbGlwLmJvdHRvbSA9PT0gZmFsc2UgPyBjaGFydC5oZWlnaHQgOiBhcmVhLmJvdHRvbSArIChjbGlwLmJvdHRvbSA9PT0gdHJ1ZSA/IDAgOiBjbGlwLmJvdHRvbSlcbiAgICB9O1xufVxuXG5leHBvcnQgeyB1bmNsaXBBcmVhIGFzICQsIF9ybG9va3VwQnlLZXkgYXMgQSwgX2xvb2t1cEJ5S2V5IGFzIEIsIF9pc1BvaW50SW5BcmVhIGFzIEMsIGdldEFuZ2xlRnJvbVBvaW50IGFzIEQsIHRvUGFkZGluZyBhcyBFLCBlYWNoIGFzIEYsIGdldE1heGltdW1TaXplIGFzIEcsIEhBTEZfUEkgYXMgSCwgX2dldFBhcmVudE5vZGUgYXMgSSwgcmVhZFVzZWRTaXplIGFzIEosIHN1cHBvcnRzRXZlbnRMaXN0ZW5lck9wdGlvbnMgYXMgSywgdGhyb3R0bGVkIGFzIEwsIF9pc0RvbVN1cHBvcnRlZCBhcyBNLCBfZmFjdG9yaXplIGFzIE4sIGZpbml0ZU9yRGVmYXVsdCBhcyBPLCBQSSBhcyBQLCBjYWxsYmFjayBhcyBRLCBfYWRkR3JhY2UgYXMgUiwgX2xpbWl0VmFsdWUgYXMgUywgVEFVIGFzIFQsIHRvRGVncmVlcyBhcyBVLCBfbWVhc3VyZVRleHQgYXMgViwgX2ludDE2UmFuZ2UgYXMgVywgX2FsaWduUGl4ZWwgYXMgWCwgY2xpcEFyZWEgYXMgWSwgcmVuZGVyVGV4dCBhcyBaLCBfYXJyYXlVbmlxdWUgYXMgXywgcmVzb2x2ZSBhcyBhLCBnZXRTdHlsZSBhcyBhJCwgdG9Gb250IGFzIGEwLCBfdG9MZWZ0UmlnaHRDZW50ZXIgYXMgYTEsIF9hbGlnblN0YXJ0RW5kIGFzIGEyLCBvdmVycmlkZXMgYXMgYTMsIG1lcmdlIGFzIGE0LCBfY2FwaXRhbGl6ZSBhcyBhNSwgZGVzY3JpcHRvcnMgYXMgYTYsIGlzRnVuY3Rpb24gYXMgYTcsIF9hdHRhY2hDb250ZXh0IGFzIGE4LCBfY3JlYXRlUmVzb2x2ZXIgYXMgYTksIGdldFJ0bEFkYXB0ZXIgYXMgYUEsIG92ZXJyaWRlVGV4dERpcmVjdGlvbiBhcyBhQiwgX3RleHRYIGFzIGFDLCByZXN0b3JlVGV4dERpcmVjdGlvbiBhcyBhRCwgZHJhd1BvaW50TGVnZW5kIGFzIGFFLCBkaXN0YW5jZUJldHdlZW5Qb2ludHMgYXMgYUYsIG5vb3AgYXMgYUcsIF9zZXRNaW5BbmRNYXhCeUtleSBhcyBhSCwgbmljZU51bSBhcyBhSSwgYWxtb3N0V2hvbGUgYXMgYUosIGFsbW9zdEVxdWFscyBhcyBhSywgX2RlY2ltYWxQbGFjZXMgYXMgYUwsIFRpY2tzIGFzIGFNLCBsb2cxMCBhcyBhTiwgX2xvbmdlc3RUZXh0IGFzIGFPLCBfZmlsdGVyQmV0d2VlbiBhcyBhUCwgX2xvb2t1cCBhcyBhUSwgaXNQYXR0ZXJuT3JHcmFkaWVudCBhcyBhUiwgZ2V0SG92ZXJDb2xvciBhcyBhUywgY2xvbmUgYXMgYVQsIF9tZXJnZXIgYXMgYVUsIF9tZXJnZXJJZiBhcyBhViwgX2RlcHJlY2F0ZWQgYXMgYVcsIF9zcGxpdEtleSBhcyBhWCwgdG9Gb250U3RyaW5nIGFzIGFZLCBzcGxpbmVDdXJ2ZSBhcyBhWiwgc3BsaW5lQ3VydmVNb25vdG9uZSBhcyBhXywgX2Rlc2NyaXB0b3JzIGFzIGFhLCBtZXJnZUlmIGFzIGFiLCB1aWQgYXMgYWMsIGRlYm91bmNlIGFzIGFkLCByZXRpbmFTY2FsZSBhcyBhZSwgY2xlYXJDYW52YXMgYXMgYWYsIHNldHNFcXVhbCBhcyBhZywgZ2V0RGF0YXNldENsaXBBcmVhIGFzIGFoLCBfZWxlbWVudHNFcXVhbCBhcyBhaSwgX2lzQ2xpY2tFdmVudCBhcyBhaiwgX2lzQmV0d2VlbiBhcyBhaywgX25vcm1hbGl6ZUFuZ2xlIGFzIGFsLCBfcmVhZFZhbHVlVG9Qcm9wcyBhcyBhbSwgX3VwZGF0ZUJlemllckNvbnRyb2xQb2ludHMgYXMgYW4sIF9jb21wdXRlU2VnbWVudHMgYXMgYW8sIF9ib3VuZFNlZ21lbnRzIGFzIGFwLCBfc3RlcHBlZEludGVycG9sYXRpb24gYXMgYXEsIF9iZXppZXJJbnRlcnBvbGF0aW9uIGFzIGFyLCBfcG9pbnRJbkxpbmUgYXMgYXMsIF9zdGVwcGVkTGluZVRvIGFzIGF0LCBfYmV6aWVyQ3VydmVUbyBhcyBhdSwgZHJhd1BvaW50IGFzIGF2LCBhZGRSb3VuZGVkUmVjdFBhdGggYXMgYXcsIHRvVFJCTCBhcyBheCwgdG9UUkJMQ29ybmVycyBhcyBheSwgX2JvdW5kU2VnbWVudCBhcyBheiwgaXNBcnJheSBhcyBiLCBmb250U3RyaW5nIGFzIGIwLCB0b0xpbmVIZWlnaHQgYXMgYjEsIFBJVEFVIGFzIGIyLCBJTkZJTklUWSBhcyBiMywgUkFEX1BFUl9ERUcgYXMgYjQsIFFVQVJURVJfUEkgYXMgYjUsIFRXT19USElSRFNfUEkgYXMgYjYsIF9hbmdsZURpZmYgYXMgYjcsIGNvbG9yIGFzIGMsIGRlZmF1bHRzIGFzIGQsIGVmZmVjdHMgYXMgZSwgcmVzb2x2ZU9iamVjdEtleSBhcyBmLCBpc051bWJlckZpbml0ZSBhcyBnLCBkZWZpbmVkIGFzIGgsIGlzT2JqZWN0IGFzIGksIGNyZWF0ZUNvbnRleHQgYXMgaiwgaXNOdWxsT3JVbmRlZiBhcyBrLCBsaXN0ZW5BcnJheUV2ZW50cyBhcyBsLCB0b1BlcmNlbnRhZ2UgYXMgbSwgdG9EaW1lbnNpb24gYXMgbiwgZm9ybWF0TnVtYmVyIGFzIG8sIF9hbmdsZUJldHdlZW4gYXMgcCwgX2dldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHMgYXMgcSwgcmVxdWVzdEFuaW1GcmFtZSBhcyByLCBzaWduIGFzIHMsIHRvUmFkaWFucyBhcyB0LCB1bmxpc3RlbkFycmF5RXZlbnRzIGFzIHUsIHZhbHVlT3JEZWZhdWx0IGFzIHYsIF9zY2FsZVJhbmdlc0NoYW5nZWQgYXMgdywgaXNOdW1iZXIgYXMgeCwgX3BhcnNlT2JqZWN0RGF0YVJhZGlhbFNjYWxlIGFzIHksIGdldFJlbGF0aXZlUG9zaXRpb24gYXMgeiB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aGVscGVycy5kYXRhc2V0LmpzLm1hcFxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/chart.js/dist/chunks/helpers.dataset.js\n"); /***/ }), /***/ "./node_modules/chart.js/dist/helpers.js": /*!***********************************************!*\ !*** ./node_modules/chart.js/dist/helpers.js ***! \***********************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ HALF_PI: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H),\n/* harmony export */ INFINITY: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b3),\n/* harmony export */ PI: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P),\n/* harmony export */ PITAU: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b2),\n/* harmony export */ QUARTER_PI: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b5),\n/* harmony export */ RAD_PER_DEG: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b4),\n/* harmony export */ TAU: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T),\n/* harmony export */ TWO_THIRDS_PI: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b6),\n/* harmony export */ _addGrace: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.R),\n/* harmony export */ _alignPixel: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X),\n/* harmony export */ _alignStartEnd: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2),\n/* harmony export */ _angleBetween: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p),\n/* harmony export */ _angleDiff: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b7),\n/* harmony export */ _arrayUnique: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__._),\n/* harmony export */ _attachContext: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a8),\n/* harmony export */ _bezierCurveTo: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.au),\n/* harmony export */ _bezierInterpolation: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ar),\n/* harmony export */ _boundSegment: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.az),\n/* harmony export */ _boundSegments: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ap),\n/* harmony export */ _capitalize: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a5),\n/* harmony export */ _computeSegments: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ao),\n/* harmony export */ _createResolver: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a9),\n/* harmony export */ _decimalPlaces: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aL),\n/* harmony export */ _deprecated: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aW),\n/* harmony export */ _descriptors: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aa),\n/* harmony export */ _elementsEqual: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai),\n/* harmony export */ _factorize: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.N),\n/* harmony export */ _filterBetween: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aP),\n/* harmony export */ _getParentNode: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.I),\n/* harmony export */ _getStartAndCountOfVisiblePoints: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.q),\n/* harmony export */ _int16Range: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.W),\n/* harmony export */ _isBetween: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak),\n/* harmony export */ _isClickEvent: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aj),\n/* harmony export */ _isDomSupported: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.M),\n/* harmony export */ _isPointInArea: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C),\n/* harmony export */ _limitValue: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S),\n/* harmony export */ _longestText: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aO),\n/* harmony export */ _lookup: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aQ),\n/* harmony export */ _lookupByKey: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B),\n/* harmony export */ _measureText: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.V),\n/* harmony export */ _merger: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aU),\n/* harmony export */ _mergerIf: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aV),\n/* harmony export */ _normalizeAngle: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al),\n/* harmony export */ _parseObjectDataRadialScale: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.y),\n/* harmony export */ _pointInLine: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.as),\n/* harmony export */ _readValueToProps: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.am),\n/* harmony export */ _rlookupByKey: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.A),\n/* harmony export */ _scaleRangesChanged: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.w),\n/* harmony export */ _setMinAndMaxByKey: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aH),\n/* harmony export */ _splitKey: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aX),\n/* harmony export */ _steppedInterpolation: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aq),\n/* harmony export */ _steppedLineTo: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.at),\n/* harmony export */ _textX: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aC),\n/* harmony export */ _toLeftRightCenter: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a1),\n/* harmony export */ _updateBezierControlPoints: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.an),\n/* harmony export */ addRoundedRectPath: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw),\n/* harmony export */ almostEquals: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aK),\n/* harmony export */ almostWhole: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aJ),\n/* harmony export */ callback: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q),\n/* harmony export */ clearCanvas: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.af),\n/* harmony export */ clipArea: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y),\n/* harmony export */ clone: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aT),\n/* harmony export */ color: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.c),\n/* harmony export */ createContext: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j),\n/* harmony export */ debounce: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ad),\n/* harmony export */ defined: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h),\n/* harmony export */ distanceBetweenPoints: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aF),\n/* harmony export */ drawPoint: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.av),\n/* harmony export */ drawPointLegend: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aE),\n/* harmony export */ each: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F),\n/* harmony export */ easingEffects: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.e),\n/* harmony export */ finiteOrDefault: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O),\n/* harmony export */ fontString: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b0),\n/* harmony export */ formatNumber: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o),\n/* harmony export */ getAngleFromPoint: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.D),\n/* harmony export */ getDatasetClipArea: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ah),\n/* harmony export */ getHoverColor: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aS),\n/* harmony export */ getMaximumSize: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.G),\n/* harmony export */ getRelativePosition: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z),\n/* harmony export */ getRtlAdapter: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA),\n/* harmony export */ getStyle: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a$),\n/* harmony export */ isArray: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b),\n/* harmony export */ isFinite: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g),\n/* harmony export */ isFunction: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7),\n/* harmony export */ isNullOrUndef: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k),\n/* harmony export */ isNumber: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x),\n/* harmony export */ isObject: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i),\n/* harmony export */ isPatternOrGradient: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aR),\n/* harmony export */ listenArrayEvents: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.l),\n/* harmony export */ log10: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN),\n/* harmony export */ merge: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a4),\n/* harmony export */ mergeIf: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab),\n/* harmony export */ niceNum: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aI),\n/* harmony export */ noop: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG),\n/* harmony export */ overrideTextDirection: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aB),\n/* harmony export */ readUsedSize: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.J),\n/* harmony export */ renderText: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z),\n/* harmony export */ requestAnimFrame: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.r),\n/* harmony export */ resolve: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a),\n/* harmony export */ resolveObjectKey: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f),\n/* harmony export */ restoreTextDirection: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aD),\n/* harmony export */ retinaScale: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ae),\n/* harmony export */ setsEqual: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ag),\n/* harmony export */ sign: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s),\n/* harmony export */ splineCurve: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aZ),\n/* harmony export */ splineCurveMonotone: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a_),\n/* harmony export */ supportsEventListenerOptions: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.K),\n/* harmony export */ throttled: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.L),\n/* harmony export */ toDegrees: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.U),\n/* harmony export */ toDimension: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.n),\n/* harmony export */ toFont: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0),\n/* harmony export */ toFontString: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aY),\n/* harmony export */ toLineHeight: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b1),\n/* harmony export */ toPadding: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E),\n/* harmony export */ toPercentage: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.m),\n/* harmony export */ toRadians: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t),\n/* harmony export */ toTRBL: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ax),\n/* harmony export */ toTRBLCorners: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay),\n/* harmony export */ uid: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ac),\n/* harmony export */ unclipArea: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$),\n/* harmony export */ unlistenArrayEvents: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.u),\n/* harmony export */ valueOrDefault: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)\n/* harmony export */ });\n/* harmony import */ var _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chunks/helpers.dataset.js */ \"./node_modules/chart.js/dist/chunks/helpers.dataset.js\");\n/*!\n * Chart.js v4.5.0\n * https://www.chartjs.org\n * (c) 2025 Chart.js Contributors\n * Released under the MIT License\n */\n\n\n//# sourceMappingURL=helpers.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvZGlzdC9oZWxwZXJzLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUM2NEU7QUFDdDNFO0FBQ3ZCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NoYXJ0LmpzL2Rpc3QvaGVscGVycy5qcz8wYjQ3Il0sInNvdXJjZXNDb250ZW50IjpbIi8qIVxuICogQ2hhcnQuanMgdjQuNS4wXG4gKiBodHRwczovL3d3dy5jaGFydGpzLm9yZ1xuICogKGMpIDIwMjUgQ2hhcnQuanMgQ29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAqL1xuZXhwb3J0IHsgSCBhcyBIQUxGX1BJLCBiMyBhcyBJTkZJTklUWSwgUCBhcyBQSSwgYjIgYXMgUElUQVUsIGI1IGFzIFFVQVJURVJfUEksIGI0IGFzIFJBRF9QRVJfREVHLCBUIGFzIFRBVSwgYjYgYXMgVFdPX1RISVJEU19QSSwgUiBhcyBfYWRkR3JhY2UsIFggYXMgX2FsaWduUGl4ZWwsIGEyIGFzIF9hbGlnblN0YXJ0RW5kLCBwIGFzIF9hbmdsZUJldHdlZW4sIGI3IGFzIF9hbmdsZURpZmYsIF8gYXMgX2FycmF5VW5pcXVlLCBhOCBhcyBfYXR0YWNoQ29udGV4dCwgYXUgYXMgX2JlemllckN1cnZlVG8sIGFyIGFzIF9iZXppZXJJbnRlcnBvbGF0aW9uLCBheiBhcyBfYm91bmRTZWdtZW50LCBhcCBhcyBfYm91bmRTZWdtZW50cywgYTUgYXMgX2NhcGl0YWxpemUsIGFvIGFzIF9jb21wdXRlU2VnbWVudHMsIGE5IGFzIF9jcmVhdGVSZXNvbHZlciwgYUwgYXMgX2RlY2ltYWxQbGFjZXMsIGFXIGFzIF9kZXByZWNhdGVkLCBhYSBhcyBfZGVzY3JpcHRvcnMsIGFpIGFzIF9lbGVtZW50c0VxdWFsLCBOIGFzIF9mYWN0b3JpemUsIGFQIGFzIF9maWx0ZXJCZXR3ZWVuLCBJIGFzIF9nZXRQYXJlbnROb2RlLCBxIGFzIF9nZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzLCBXIGFzIF9pbnQxNlJhbmdlLCBhayBhcyBfaXNCZXR3ZWVuLCBhaiBhcyBfaXNDbGlja0V2ZW50LCBNIGFzIF9pc0RvbVN1cHBvcnRlZCwgQyBhcyBfaXNQb2ludEluQXJlYSwgUyBhcyBfbGltaXRWYWx1ZSwgYU8gYXMgX2xvbmdlc3RUZXh0LCBhUSBhcyBfbG9va3VwLCBCIGFzIF9sb29rdXBCeUtleSwgViBhcyBfbWVhc3VyZVRleHQsIGFVIGFzIF9tZXJnZXIsIGFWIGFzIF9tZXJnZXJJZiwgYWwgYXMgX25vcm1hbGl6ZUFuZ2xlLCB5IGFzIF9wYXJzZU9iamVjdERhdGFSYWRpYWxTY2FsZSwgYXMgYXMgX3BvaW50SW5MaW5lLCBhbSBhcyBfcmVhZFZhbHVlVG9Qcm9wcywgQSBhcyBfcmxvb2t1cEJ5S2V5LCB3IGFzIF9zY2FsZVJhbmdlc0NoYW5nZWQsIGFIIGFzIF9zZXRNaW5BbmRNYXhCeUtleSwgYVggYXMgX3NwbGl0S2V5LCBhcSBhcyBfc3RlcHBlZEludGVycG9sYXRpb24sIGF0IGFzIF9zdGVwcGVkTGluZVRvLCBhQyBhcyBfdGV4dFgsIGExIGFzIF90b0xlZnRSaWdodENlbnRlciwgYW4gYXMgX3VwZGF0ZUJlemllckNvbnRyb2xQb2ludHMsIGF3IGFzIGFkZFJvdW5kZWRSZWN0UGF0aCwgYUsgYXMgYWxtb3N0RXF1YWxzLCBhSiBhcyBhbG1vc3RXaG9sZSwgUSBhcyBjYWxsYmFjaywgYWYgYXMgY2xlYXJDYW52YXMsIFkgYXMgY2xpcEFyZWEsIGFUIGFzIGNsb25lLCBjIGFzIGNvbG9yLCBqIGFzIGNyZWF0ZUNvbnRleHQsIGFkIGFzIGRlYm91bmNlLCBoIGFzIGRlZmluZWQsIGFGIGFzIGRpc3RhbmNlQmV0d2VlblBvaW50cywgYXYgYXMgZHJhd1BvaW50LCBhRSBhcyBkcmF3UG9pbnRMZWdlbmQsIEYgYXMgZWFjaCwgZSBhcyBlYXNpbmdFZmZlY3RzLCBPIGFzIGZpbml0ZU9yRGVmYXVsdCwgYjAgYXMgZm9udFN0cmluZywgbyBhcyBmb3JtYXROdW1iZXIsIEQgYXMgZ2V0QW5nbGVGcm9tUG9pbnQsIGFoIGFzIGdldERhdGFzZXRDbGlwQXJlYSwgYVMgYXMgZ2V0SG92ZXJDb2xvciwgRyBhcyBnZXRNYXhpbXVtU2l6ZSwgeiBhcyBnZXRSZWxhdGl2ZVBvc2l0aW9uLCBhQSBhcyBnZXRSdGxBZGFwdGVyLCBhJCBhcyBnZXRTdHlsZSwgYiBhcyBpc0FycmF5LCBnIGFzIGlzRmluaXRlLCBhNyBhcyBpc0Z1bmN0aW9uLCBrIGFzIGlzTnVsbE9yVW5kZWYsIHggYXMgaXNOdW1iZXIsIGkgYXMgaXNPYmplY3QsIGFSIGFzIGlzUGF0dGVybk9yR3JhZGllbnQsIGwgYXMgbGlzdGVuQXJyYXlFdmVudHMsIGFOIGFzIGxvZzEwLCBhNCBhcyBtZXJnZSwgYWIgYXMgbWVyZ2VJZiwgYUkgYXMgbmljZU51bSwgYUcgYXMgbm9vcCwgYUIgYXMgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uLCBKIGFzIHJlYWRVc2VkU2l6ZSwgWiBhcyByZW5kZXJUZXh0LCByIGFzIHJlcXVlc3RBbmltRnJhbWUsIGEgYXMgcmVzb2x2ZSwgZiBhcyByZXNvbHZlT2JqZWN0S2V5LCBhRCBhcyByZXN0b3JlVGV4dERpcmVjdGlvbiwgYWUgYXMgcmV0aW5hU2NhbGUsIGFnIGFzIHNldHNFcXVhbCwgcyBhcyBzaWduLCBhWiBhcyBzcGxpbmVDdXJ2ZSwgYV8gYXMgc3BsaW5lQ3VydmVNb25vdG9uZSwgSyBhcyBzdXBwb3J0c0V2ZW50TGlzdGVuZXJPcHRpb25zLCBMIGFzIHRocm90dGxlZCwgVSBhcyB0b0RlZ3JlZXMsIG4gYXMgdG9EaW1lbnNpb24sIGEwIGFzIHRvRm9udCwgYVkgYXMgdG9Gb250U3RyaW5nLCBiMSBhcyB0b0xpbmVIZWlnaHQsIEUgYXMgdG9QYWRkaW5nLCBtIGFzIHRvUGVyY2VudGFnZSwgdCBhcyB0b1JhZGlhbnMsIGF4IGFzIHRvVFJCTCwgYXkgYXMgdG9UUkJMQ29ybmVycywgYWMgYXMgdWlkLCAkIGFzIHVuY2xpcEFyZWEsIHUgYXMgdW5saXN0ZW5BcnJheUV2ZW50cywgdiBhcyB2YWx1ZU9yRGVmYXVsdCB9IGZyb20gJy4vY2h1bmtzL2hlbHBlcnMuZGF0YXNldC5qcyc7XG5pbXBvcnQgJ0BrdXJrbGUvY29sb3InO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aGVscGVycy5qcy5tYXBcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/chart.js/dist/helpers.js\n"); /***/ }), /***/ "./node_modules/chart.js/helpers/helpers.js": /*!**************************************************!*\ !*** ./node_modules/chart.js/helpers/helpers.js ***! \**************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ HALF_PI: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.HALF_PI),\n/* harmony export */ INFINITY: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.INFINITY),\n/* harmony export */ PI: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.PI),\n/* harmony export */ PITAU: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.PITAU),\n/* harmony export */ QUARTER_PI: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.QUARTER_PI),\n/* harmony export */ RAD_PER_DEG: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.RAD_PER_DEG),\n/* harmony export */ TAU: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.TAU),\n/* harmony export */ TWO_THIRDS_PI: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.TWO_THIRDS_PI),\n/* harmony export */ _addGrace: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._addGrace),\n/* harmony export */ _alignPixel: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._alignPixel),\n/* harmony export */ _alignStartEnd: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._alignStartEnd),\n/* harmony export */ _angleBetween: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._angleBetween),\n/* harmony export */ _angleDiff: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._angleDiff),\n/* harmony export */ _arrayUnique: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._arrayUnique),\n/* harmony export */ _attachContext: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._attachContext),\n/* harmony export */ _bezierCurveTo: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._bezierCurveTo),\n/* harmony export */ _bezierInterpolation: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._bezierInterpolation),\n/* harmony export */ _boundSegment: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._boundSegment),\n/* harmony export */ _boundSegments: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._boundSegments),\n/* harmony export */ _capitalize: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._capitalize),\n/* harmony export */ _computeSegments: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._computeSegments),\n/* harmony export */ _createResolver: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._createResolver),\n/* harmony export */ _decimalPlaces: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._decimalPlaces),\n/* harmony export */ _deprecated: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._deprecated),\n/* harmony export */ _descriptors: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._descriptors),\n/* harmony export */ _elementsEqual: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._elementsEqual),\n/* harmony export */ _factorize: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._factorize),\n/* harmony export */ _filterBetween: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._filterBetween),\n/* harmony export */ _getParentNode: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._getParentNode),\n/* harmony export */ _getStartAndCountOfVisiblePoints: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._getStartAndCountOfVisiblePoints),\n/* harmony export */ _int16Range: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._int16Range),\n/* harmony export */ _isBetween: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._isBetween),\n/* harmony export */ _isClickEvent: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._isClickEvent),\n/* harmony export */ _isDomSupported: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._isDomSupported),\n/* harmony export */ _isPointInArea: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._isPointInArea),\n/* harmony export */ _limitValue: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._limitValue),\n/* harmony export */ _longestText: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._longestText),\n/* harmony export */ _lookup: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._lookup),\n/* harmony export */ _lookupByKey: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._lookupByKey),\n/* harmony export */ _measureText: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._measureText),\n/* harmony export */ _merger: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._merger),\n/* harmony export */ _mergerIf: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._mergerIf),\n/* harmony export */ _normalizeAngle: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._normalizeAngle),\n/* harmony export */ _parseObjectDataRadialScale: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._parseObjectDataRadialScale),\n/* harmony export */ _pointInLine: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._pointInLine),\n/* harmony export */ _readValueToProps: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._readValueToProps),\n/* harmony export */ _rlookupByKey: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._rlookupByKey),\n/* harmony export */ _scaleRangesChanged: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._scaleRangesChanged),\n/* harmony export */ _setMinAndMaxByKey: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._setMinAndMaxByKey),\n/* harmony export */ _splitKey: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._splitKey),\n/* harmony export */ _steppedInterpolation: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._steppedInterpolation),\n/* harmony export */ _steppedLineTo: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._steppedLineTo),\n/* harmony export */ _textX: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._textX),\n/* harmony export */ _toLeftRightCenter: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._toLeftRightCenter),\n/* harmony export */ _updateBezierControlPoints: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__._updateBezierControlPoints),\n/* harmony export */ addRoundedRectPath: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.addRoundedRectPath),\n/* harmony export */ almostEquals: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.almostEquals),\n/* harmony export */ almostWhole: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.almostWhole),\n/* harmony export */ callback: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.callback),\n/* harmony export */ clearCanvas: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.clearCanvas),\n/* harmony export */ clipArea: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.clipArea),\n/* harmony export */ clone: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.clone),\n/* harmony export */ color: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.color),\n/* harmony export */ createContext: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.createContext),\n/* harmony export */ debounce: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.debounce),\n/* harmony export */ defined: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.defined),\n/* harmony export */ distanceBetweenPoints: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.distanceBetweenPoints),\n/* harmony export */ drawPoint: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.drawPoint),\n/* harmony export */ drawPointLegend: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.drawPointLegend),\n/* harmony export */ each: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.each),\n/* harmony export */ easingEffects: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.easingEffects),\n/* harmony export */ finiteOrDefault: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.finiteOrDefault),\n/* harmony export */ fontString: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.fontString),\n/* harmony export */ formatNumber: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.formatNumber),\n/* harmony export */ getAngleFromPoint: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getAngleFromPoint),\n/* harmony export */ getDatasetClipArea: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getDatasetClipArea),\n/* harmony export */ getHoverColor: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getHoverColor),\n/* harmony export */ getMaximumSize: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getMaximumSize),\n/* harmony export */ getRelativePosition: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getRelativePosition),\n/* harmony export */ getRtlAdapter: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getRtlAdapter),\n/* harmony export */ getStyle: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getStyle),\n/* harmony export */ isArray: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.isArray),\n/* harmony export */ isFinite: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.isFinite),\n/* harmony export */ isFunction: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.isFunction),\n/* harmony export */ isNullOrUndef: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndef),\n/* harmony export */ isNumber: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.isNumber),\n/* harmony export */ isObject: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.isObject),\n/* harmony export */ isPatternOrGradient: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.isPatternOrGradient),\n/* harmony export */ listenArrayEvents: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.listenArrayEvents),\n/* harmony export */ log10: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.log10),\n/* harmony export */ merge: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.merge),\n/* harmony export */ mergeIf: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.mergeIf),\n/* harmony export */ niceNum: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.niceNum),\n/* harmony export */ noop: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.noop),\n/* harmony export */ overrideTextDirection: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.overrideTextDirection),\n/* harmony export */ readUsedSize: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.readUsedSize),\n/* harmony export */ renderText: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.renderText),\n/* harmony export */ requestAnimFrame: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.requestAnimFrame),\n/* harmony export */ resolve: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.resolve),\n/* harmony export */ resolveObjectKey: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.resolveObjectKey),\n/* harmony export */ restoreTextDirection: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreTextDirection),\n/* harmony export */ retinaScale: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.retinaScale),\n/* harmony export */ setsEqual: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.setsEqual),\n/* harmony export */ sign: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.sign),\n/* harmony export */ splineCurve: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.splineCurve),\n/* harmony export */ splineCurveMonotone: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.splineCurveMonotone),\n/* harmony export */ supportsEventListenerOptions: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.supportsEventListenerOptions),\n/* harmony export */ throttled: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.throttled),\n/* harmony export */ toDegrees: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toDegrees),\n/* harmony export */ toDimension: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toDimension),\n/* harmony export */ toFont: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toFont),\n/* harmony export */ toFontString: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toFontString),\n/* harmony export */ toLineHeight: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toLineHeight),\n/* harmony export */ toPadding: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toPadding),\n/* harmony export */ toPercentage: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toPercentage),\n/* harmony export */ toRadians: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toRadians),\n/* harmony export */ toTRBL: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toTRBL),\n/* harmony export */ toTRBLCorners: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.toTRBLCorners),\n/* harmony export */ uid: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.uid),\n/* harmony export */ unclipArea: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.unclipArea),\n/* harmony export */ unlistenArrayEvents: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.unlistenArrayEvents),\n/* harmony export */ valueOrDefault: () => (/* reexport safe */ _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__.valueOrDefault)\n/* harmony export */ });\n/* harmony import */ var _dist_helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../dist/helpers.js */ \"./node_modules/chart.js/dist/helpers.js\");\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvaGVscGVycy9oZWxwZXJzLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFtQyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jaGFydC5qcy9oZWxwZXJzL2hlbHBlcnMuanM/OTFmYiJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuLi9kaXN0L2hlbHBlcnMuanMnO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/chart.js/helpers/helpers.js\n"); /***/ }), /***/ "./node_modules/chartjs-plugin-datalabels/dist/chartjs-plugin-datalabels.esm.js": /*!**************************************************************************************!*\ !*** ./node_modules/chartjs-plugin-datalabels/dist/chartjs-plugin-datalabels.esm.js ***! \**************************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ plugin)\n/* harmony export */ });\n/* harmony import */ var chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! chart.js/helpers */ \"./node_modules/chart.js/helpers/helpers.js\");\n/* harmony import */ var chart_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! chart.js */ \"./node_modules/chart.js/dist/chart.js\");\n/* harmony import */ var chart_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! chart.js */ \"./node_modules/chart.js/dist/chunks/helpers.dataset.js\");\n/*!\n * chartjs-plugin-datalabels v2.2.0\n * https://chartjs-plugin-datalabels.netlify.app\n * (c) 2017-2022 chartjs-plugin-datalabels contributors\n * Released under the MIT license\n */\n\n\n\nvar devicePixelRatio = (function() {\n if (typeof window !== 'undefined') {\n if (window.devicePixelRatio) {\n return window.devicePixelRatio;\n }\n\n // devicePixelRatio is undefined on IE10\n // https://stackoverflow.com/a/20204180/8837887\n // https://github.com/chartjs/chartjs-plugin-datalabels/issues/85\n var screen = window.screen;\n if (screen) {\n return (screen.deviceXDPI || 1) / (screen.logicalXDPI || 1);\n }\n }\n\n return 1;\n}());\n\nvar utils = {\n // @todo move this in Chart.helpers.toTextLines\n toTextLines: function(inputs) {\n var lines = [];\n var input;\n\n inputs = [].concat(inputs);\n while (inputs.length) {\n input = inputs.pop();\n if (typeof input === 'string') {\n lines.unshift.apply(lines, input.split('\\n'));\n } else if (Array.isArray(input)) {\n inputs.push.apply(inputs, input);\n } else if (!(0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndef)(inputs)) {\n lines.unshift('' + input);\n }\n }\n\n return lines;\n },\n\n // @todo move this in Chart.helpers.canvas.textSize\n // @todo cache calls of measureText if font doesn't change?!\n textSize: function(ctx, lines, font) {\n var items = [].concat(lines);\n var ilen = items.length;\n var prev = ctx.font;\n var width = 0;\n var i;\n\n ctx.font = font.string;\n\n for (i = 0; i < ilen; ++i) {\n width = Math.max(ctx.measureText(items[i]).width, width);\n }\n\n ctx.font = prev;\n\n return {\n height: ilen * font.lineHeight,\n width: width\n };\n },\n\n /**\n * Returns value bounded by min and max. This is equivalent to max(min, min(value, max)).\n * @todo move this method in Chart.helpers.bound\n * https://doc.qt.io/qt-5/qtglobal.html#qBound\n */\n bound: function(min, value, max) {\n return Math.max(min, Math.min(value, max));\n },\n\n /**\n * Returns an array of pair [value, state] where state is:\n * * -1: value is only in a0 (removed)\n * * 1: value is only in a1 (added)\n */\n arrayDiff: function(a0, a1) {\n var prev = a0.slice();\n var updates = [];\n var i, j, ilen, v;\n\n for (i = 0, ilen = a1.length; i < ilen; ++i) {\n v = a1[i];\n j = prev.indexOf(v);\n\n if (j === -1) {\n updates.push([v, 1]);\n } else {\n prev.splice(j, 1);\n }\n }\n\n for (i = 0, ilen = prev.length; i < ilen; ++i) {\n updates.push([prev[i], -1]);\n }\n\n return updates;\n },\n\n /**\n * https://github.com/chartjs/chartjs-plugin-datalabels/issues/70\n */\n rasterize: function(v) {\n return Math.round(v * devicePixelRatio) / devicePixelRatio;\n }\n};\n\nfunction orient(point, origin) {\n var x0 = origin.x;\n var y0 = origin.y;\n\n if (x0 === null) {\n return {x: 0, y: -1};\n }\n if (y0 === null) {\n return {x: 1, y: 0};\n }\n\n var dx = point.x - x0;\n var dy = point.y - y0;\n var ln = Math.sqrt(dx * dx + dy * dy);\n\n return {\n x: ln ? dx / ln : 0,\n y: ln ? dy / ln : -1\n };\n}\n\nfunction aligned(x, y, vx, vy, align) {\n switch (align) {\n case 'center':\n vx = vy = 0;\n break;\n case 'bottom':\n vx = 0;\n vy = 1;\n break;\n case 'right':\n vx = 1;\n vy = 0;\n break;\n case 'left':\n vx = -1;\n vy = 0;\n break;\n case 'top':\n vx = 0;\n vy = -1;\n break;\n case 'start':\n vx = -vx;\n vy = -vy;\n break;\n case 'end':\n // keep natural orientation\n break;\n default:\n // clockwise rotation (in degree)\n align *= (Math.PI / 180);\n vx = Math.cos(align);\n vy = Math.sin(align);\n break;\n }\n\n return {\n x: x,\n y: y,\n vx: vx,\n vy: vy\n };\n}\n\n// Line clipping (Cohen–Sutherland algorithm)\n// https://en.wikipedia.org/wiki/Cohen–Sutherland_algorithm\n\nvar R_INSIDE = 0;\nvar R_LEFT = 1;\nvar R_RIGHT = 2;\nvar R_BOTTOM = 4;\nvar R_TOP = 8;\n\nfunction region(x, y, rect) {\n var res = R_INSIDE;\n\n if (x < rect.left) {\n res |= R_LEFT;\n } else if (x > rect.right) {\n res |= R_RIGHT;\n }\n if (y < rect.top) {\n res |= R_TOP;\n } else if (y > rect.bottom) {\n res |= R_BOTTOM;\n }\n\n return res;\n}\n\nfunction clipped(segment, area) {\n var x0 = segment.x0;\n var y0 = segment.y0;\n var x1 = segment.x1;\n var y1 = segment.y1;\n var r0 = region(x0, y0, area);\n var r1 = region(x1, y1, area);\n var r, x, y;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n if (!(r0 | r1) || (r0 & r1)) {\n // both points inside or on the same side: no clipping\n break;\n }\n\n // at least one point is outside\n r = r0 || r1;\n\n if (r & R_TOP) {\n x = x0 + (x1 - x0) * (area.top - y0) / (y1 - y0);\n y = area.top;\n } else if (r & R_BOTTOM) {\n x = x0 + (x1 - x0) * (area.bottom - y0) / (y1 - y0);\n y = area.bottom;\n } else if (r & R_RIGHT) {\n y = y0 + (y1 - y0) * (area.right - x0) / (x1 - x0);\n x = area.right;\n } else if (r & R_LEFT) {\n y = y0 + (y1 - y0) * (area.left - x0) / (x1 - x0);\n x = area.left;\n }\n\n if (r === r0) {\n x0 = x;\n y0 = y;\n r0 = region(x0, y0, area);\n } else {\n x1 = x;\n y1 = y;\n r1 = region(x1, y1, area);\n }\n }\n\n return {\n x0: x0,\n x1: x1,\n y0: y0,\n y1: y1\n };\n}\n\nfunction compute$1(range, config) {\n var anchor = config.anchor;\n var segment = range;\n var x, y;\n\n if (config.clamp) {\n segment = clipped(segment, config.area);\n }\n\n if (anchor === 'start') {\n x = segment.x0;\n y = segment.y0;\n } else if (anchor === 'end') {\n x = segment.x1;\n y = segment.y1;\n } else {\n x = (segment.x0 + segment.x1) / 2;\n y = (segment.y0 + segment.y1) / 2;\n }\n\n return aligned(x, y, range.vx, range.vy, config.align);\n}\n\nvar positioners = {\n arc: function(el, config) {\n var angle = (el.startAngle + el.endAngle) / 2;\n var vx = Math.cos(angle);\n var vy = Math.sin(angle);\n var r0 = el.innerRadius;\n var r1 = el.outerRadius;\n\n return compute$1({\n x0: el.x + vx * r0,\n y0: el.y + vy * r0,\n x1: el.x + vx * r1,\n y1: el.y + vy * r1,\n vx: vx,\n vy: vy\n }, config);\n },\n\n point: function(el, config) {\n var v = orient(el, config.origin);\n var rx = v.x * el.options.radius;\n var ry = v.y * el.options.radius;\n\n return compute$1({\n x0: el.x - rx,\n y0: el.y - ry,\n x1: el.x + rx,\n y1: el.y + ry,\n vx: v.x,\n vy: v.y\n }, config);\n },\n\n bar: function(el, config) {\n var v = orient(el, config.origin);\n var x = el.x;\n var y = el.y;\n var sx = 0;\n var sy = 0;\n\n if (el.horizontal) {\n x = Math.min(el.x, el.base);\n sx = Math.abs(el.base - el.x);\n } else {\n y = Math.min(el.y, el.base);\n sy = Math.abs(el.base - el.y);\n }\n\n return compute$1({\n x0: x,\n y0: y + sy,\n x1: x + sx,\n y1: y,\n vx: v.x,\n vy: v.y\n }, config);\n },\n\n fallback: function(el, config) {\n var v = orient(el, config.origin);\n\n return compute$1({\n x0: el.x,\n y0: el.y,\n x1: el.x + (el.width || 0),\n y1: el.y + (el.height || 0),\n vx: v.x,\n vy: v.y\n }, config);\n }\n};\n\nvar rasterize = utils.rasterize;\n\nfunction boundingRects(model) {\n var borderWidth = model.borderWidth || 0;\n var padding = model.padding;\n var th = model.size.height;\n var tw = model.size.width;\n var tx = -tw / 2;\n var ty = -th / 2;\n\n return {\n frame: {\n x: tx - padding.left - borderWidth,\n y: ty - padding.top - borderWidth,\n w: tw + padding.width + borderWidth * 2,\n h: th + padding.height + borderWidth * 2\n },\n text: {\n x: tx,\n y: ty,\n w: tw,\n h: th\n }\n };\n}\n\nfunction getScaleOrigin(el, context) {\n var scale = context.chart.getDatasetMeta(context.datasetIndex).vScale;\n\n if (!scale) {\n return null;\n }\n\n if (scale.xCenter !== undefined && scale.yCenter !== undefined) {\n return {x: scale.xCenter, y: scale.yCenter};\n }\n\n var pixel = scale.getBasePixel();\n return el.horizontal ?\n {x: pixel, y: null} :\n {x: null, y: pixel};\n}\n\nfunction getPositioner(el) {\n if (el instanceof chart_js__WEBPACK_IMPORTED_MODULE_1__.ArcElement) {\n return positioners.arc;\n }\n if (el instanceof chart_js__WEBPACK_IMPORTED_MODULE_1__.PointElement) {\n return positioners.point;\n }\n if (el instanceof chart_js__WEBPACK_IMPORTED_MODULE_1__.BarElement) {\n return positioners.bar;\n }\n return positioners.fallback;\n}\n\nfunction drawRoundedRect(ctx, x, y, w, h, radius) {\n var HALF_PI = Math.PI / 2;\n\n if (radius) {\n var r = Math.min(radius, h / 2, w / 2);\n var left = x + r;\n var top = y + r;\n var right = x + w - r;\n var bottom = y + h - r;\n\n ctx.moveTo(x, top);\n if (left < right && top < bottom) {\n ctx.arc(left, top, r, -Math.PI, -HALF_PI);\n ctx.arc(right, top, r, -HALF_PI, 0);\n ctx.arc(right, bottom, r, 0, HALF_PI);\n ctx.arc(left, bottom, r, HALF_PI, Math.PI);\n } else if (left < right) {\n ctx.moveTo(left, y);\n ctx.arc(right, top, r, -HALF_PI, HALF_PI);\n ctx.arc(left, top, r, HALF_PI, Math.PI + HALF_PI);\n } else if (top < bottom) {\n ctx.arc(left, top, r, -Math.PI, 0);\n ctx.arc(left, bottom, r, 0, Math.PI);\n } else {\n ctx.arc(left, top, r, -Math.PI, Math.PI);\n }\n ctx.closePath();\n ctx.moveTo(x, y);\n } else {\n ctx.rect(x, y, w, h);\n }\n}\n\nfunction drawFrame(ctx, rect, model) {\n var bgColor = model.backgroundColor;\n var borderColor = model.borderColor;\n var borderWidth = model.borderWidth;\n\n if (!bgColor && (!borderColor || !borderWidth)) {\n return;\n }\n\n ctx.beginPath();\n\n drawRoundedRect(\n ctx,\n rasterize(rect.x) + borderWidth / 2,\n rasterize(rect.y) + borderWidth / 2,\n rasterize(rect.w) - borderWidth,\n rasterize(rect.h) - borderWidth,\n model.borderRadius);\n\n ctx.closePath();\n\n if (bgColor) {\n ctx.fillStyle = bgColor;\n ctx.fill();\n }\n\n if (borderColor && borderWidth) {\n ctx.strokeStyle = borderColor;\n ctx.lineWidth = borderWidth;\n ctx.lineJoin = 'miter';\n ctx.stroke();\n }\n}\n\nfunction textGeometry(rect, align, font) {\n var h = font.lineHeight;\n var w = rect.w;\n var x = rect.x;\n var y = rect.y + h / 2;\n\n if (align === 'center') {\n x += w / 2;\n } else if (align === 'end' || align === 'right') {\n x += w;\n }\n\n return {\n h: h,\n w: w,\n x: x,\n y: y\n };\n}\n\nfunction drawTextLine(ctx, text, cfg) {\n var shadow = ctx.shadowBlur;\n var stroked = cfg.stroked;\n var x = rasterize(cfg.x);\n var y = rasterize(cfg.y);\n var w = rasterize(cfg.w);\n\n if (stroked) {\n ctx.strokeText(text, x, y, w);\n }\n\n if (cfg.filled) {\n if (shadow && stroked) {\n // Prevent drawing shadow on both the text stroke and fill, so\n // if the text is stroked, remove the shadow for the text fill.\n ctx.shadowBlur = 0;\n }\n\n ctx.fillText(text, x, y, w);\n\n if (shadow && stroked) {\n ctx.shadowBlur = shadow;\n }\n }\n}\n\nfunction drawText(ctx, lines, rect, model) {\n var align = model.textAlign;\n var color = model.color;\n var filled = !!color;\n var font = model.font;\n var ilen = lines.length;\n var strokeColor = model.textStrokeColor;\n var strokeWidth = model.textStrokeWidth;\n var stroked = strokeColor && strokeWidth;\n var i;\n\n if (!ilen || (!filled && !stroked)) {\n return;\n }\n\n // Adjust coordinates based on text alignment and line height\n rect = textGeometry(rect, align, font);\n\n ctx.font = font.string;\n ctx.textAlign = align;\n ctx.textBaseline = 'middle';\n ctx.shadowBlur = model.textShadowBlur;\n ctx.shadowColor = model.textShadowColor;\n\n if (filled) {\n ctx.fillStyle = color;\n }\n if (stroked) {\n ctx.lineJoin = 'round';\n ctx.lineWidth = strokeWidth;\n ctx.strokeStyle = strokeColor;\n }\n\n for (i = 0, ilen = lines.length; i < ilen; ++i) {\n drawTextLine(ctx, lines[i], {\n stroked: stroked,\n filled: filled,\n w: rect.w,\n x: rect.x,\n y: rect.y + rect.h * i\n });\n }\n}\n\nvar Label = function(config, ctx, el, index) {\n var me = this;\n\n me._config = config;\n me._index = index;\n me._model = null;\n me._rects = null;\n me._ctx = ctx;\n me._el = el;\n};\n\n(0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.merge)(Label.prototype, {\n /**\n * @private\n */\n _modelize: function(display, lines, config, context) {\n var me = this;\n var index = me._index;\n var font = (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.toFont)((0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.font, {}], context, index));\n var color = (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.color, chart_js__WEBPACK_IMPORTED_MODULE_2__.d.color], context, index);\n\n return {\n align: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.align, 'center'], context, index),\n anchor: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.anchor, 'center'], context, index),\n area: context.chart.chartArea,\n backgroundColor: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.backgroundColor, null], context, index),\n borderColor: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.borderColor, null], context, index),\n borderRadius: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.borderRadius, 0], context, index),\n borderWidth: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.borderWidth, 0], context, index),\n clamp: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.clamp, false], context, index),\n clip: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.clip, false], context, index),\n color: color,\n display: display,\n font: font,\n lines: lines,\n offset: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.offset, 4], context, index),\n opacity: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.opacity, 1], context, index),\n origin: getScaleOrigin(me._el, context),\n padding: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.toPadding)((0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.padding, 4], context, index)),\n positioner: getPositioner(me._el),\n rotation: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.rotation, 0], context, index) * (Math.PI / 180),\n size: utils.textSize(me._ctx, lines, font),\n textAlign: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.textAlign, 'start'], context, index),\n textShadowBlur: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.textShadowBlur, 0], context, index),\n textShadowColor: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.textShadowColor, color], context, index),\n textStrokeColor: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.textStrokeColor, color], context, index),\n textStrokeWidth: (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.textStrokeWidth, 0], context, index)\n };\n },\n\n update: function(context) {\n var me = this;\n var model = null;\n var rects = null;\n var index = me._index;\n var config = me._config;\n var value, label, lines;\n\n // We first resolve the display option (separately) to avoid computing\n // other options in case the label is hidden (i.e. display: false).\n var display = (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.resolve)([config.display, true], context, index);\n\n if (display) {\n value = context.dataset.data[index];\n label = (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.valueOrDefault)((0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.callback)(config.formatter, [value, context]), value);\n lines = (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndef)(label) ? [] : utils.toTextLines(label);\n\n if (lines.length) {\n model = me._modelize(display, lines, config, context);\n rects = boundingRects(model);\n }\n }\n\n me._model = model;\n me._rects = rects;\n },\n\n geometry: function() {\n return this._rects ? this._rects.frame : {};\n },\n\n rotation: function() {\n return this._model ? this._model.rotation : 0;\n },\n\n visible: function() {\n return this._model && this._model.opacity;\n },\n\n model: function() {\n return this._model;\n },\n\n draw: function(chart, center) {\n var me = this;\n var ctx = chart.ctx;\n var model = me._model;\n var rects = me._rects;\n var area;\n\n if (!this.visible()) {\n return;\n }\n\n ctx.save();\n\n if (model.clip) {\n area = model.area;\n ctx.beginPath();\n ctx.rect(\n area.left,\n area.top,\n area.right - area.left,\n area.bottom - area.top);\n ctx.clip();\n }\n\n ctx.globalAlpha = utils.bound(0, model.opacity, 1);\n ctx.translate(rasterize(center.x), rasterize(center.y));\n ctx.rotate(model.rotation);\n\n drawFrame(ctx, rects.frame, model);\n drawText(ctx, model.lines, rects.text, model);\n\n ctx.restore();\n }\n});\n\nvar MIN_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991; // eslint-disable-line es/no-number-minsafeinteger\nvar MAX_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; // eslint-disable-line es/no-number-maxsafeinteger\n\nfunction rotated(point, center, angle) {\n var cos = Math.cos(angle);\n var sin = Math.sin(angle);\n var cx = center.x;\n var cy = center.y;\n\n return {\n x: cx + cos * (point.x - cx) - sin * (point.y - cy),\n y: cy + sin * (point.x - cx) + cos * (point.y - cy)\n };\n}\n\nfunction projected(points, axis) {\n var min = MAX_INTEGER;\n var max = MIN_INTEGER;\n var origin = axis.origin;\n var i, pt, vx, vy, dp;\n\n for (i = 0; i < points.length; ++i) {\n pt = points[i];\n vx = pt.x - origin.x;\n vy = pt.y - origin.y;\n dp = axis.vx * vx + axis.vy * vy;\n min = Math.min(min, dp);\n max = Math.max(max, dp);\n }\n\n return {\n min: min,\n max: max\n };\n}\n\nfunction toAxis(p0, p1) {\n var vx = p1.x - p0.x;\n var vy = p1.y - p0.y;\n var ln = Math.sqrt(vx * vx + vy * vy);\n\n return {\n vx: (p1.x - p0.x) / ln,\n vy: (p1.y - p0.y) / ln,\n origin: p0,\n ln: ln\n };\n}\n\nvar HitBox = function() {\n this._rotation = 0;\n this._rect = {\n x: 0,\n y: 0,\n w: 0,\n h: 0\n };\n};\n\n(0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.merge)(HitBox.prototype, {\n center: function() {\n var r = this._rect;\n return {\n x: r.x + r.w / 2,\n y: r.y + r.h / 2\n };\n },\n\n update: function(center, rect, rotation) {\n this._rotation = rotation;\n this._rect = {\n x: rect.x + center.x,\n y: rect.y + center.y,\n w: rect.w,\n h: rect.h\n };\n },\n\n contains: function(point) {\n var me = this;\n var margin = 1;\n var rect = me._rect;\n\n point = rotated(point, me.center(), -me._rotation);\n\n return !(point.x < rect.x - margin\n || point.y < rect.y - margin\n || point.x > rect.x + rect.w + margin * 2\n || point.y > rect.y + rect.h + margin * 2);\n },\n\n // Separating Axis Theorem\n // https://gamedevelopment.tutsplus.com/tutorials/collision-detection-using-the-separating-axis-theorem--gamedev-169\n intersects: function(other) {\n var r0 = this._points();\n var r1 = other._points();\n var axes = [\n toAxis(r0[0], r0[1]),\n toAxis(r0[0], r0[3])\n ];\n var i, pr0, pr1;\n\n if (this._rotation !== other._rotation) {\n // Only separate with r1 axis if the rotation is different,\n // else it's enough to separate r0 and r1 with r0 axis only!\n axes.push(\n toAxis(r1[0], r1[1]),\n toAxis(r1[0], r1[3])\n );\n }\n\n for (i = 0; i < axes.length; ++i) {\n pr0 = projected(r0, axes[i]);\n pr1 = projected(r1, axes[i]);\n\n if (pr0.max < pr1.min || pr1.max < pr0.min) {\n return false;\n }\n }\n\n return true;\n },\n\n /**\n * @private\n */\n _points: function() {\n var me = this;\n var rect = me._rect;\n var angle = me._rotation;\n var center = me.center();\n\n return [\n rotated({x: rect.x, y: rect.y}, center, angle),\n rotated({x: rect.x + rect.w, y: rect.y}, center, angle),\n rotated({x: rect.x + rect.w, y: rect.y + rect.h}, center, angle),\n rotated({x: rect.x, y: rect.y + rect.h}, center, angle)\n ];\n }\n});\n\nfunction coordinates(el, model, geometry) {\n var point = model.positioner(el, model);\n var vx = point.vx;\n var vy = point.vy;\n\n if (!vx && !vy) {\n // if aligned center, we don't want to offset the center point\n return {x: point.x, y: point.y};\n }\n\n var w = geometry.w;\n var h = geometry.h;\n\n // take in account the label rotation\n var rotation = model.rotation;\n var dx = Math.abs(w / 2 * Math.cos(rotation)) + Math.abs(h / 2 * Math.sin(rotation));\n var dy = Math.abs(w / 2 * Math.sin(rotation)) + Math.abs(h / 2 * Math.cos(rotation));\n\n // scale the unit vector (vx, vy) to get at least dx or dy equal to\n // w or h respectively (else we would calculate the distance to the\n // ellipse inscribed in the bounding rect)\n var vs = 1 / Math.max(Math.abs(vx), Math.abs(vy));\n dx *= vx * vs;\n dy *= vy * vs;\n\n // finally, include the explicit offset\n dx += model.offset * vx;\n dy += model.offset * vy;\n\n return {\n x: point.x + dx,\n y: point.y + dy\n };\n}\n\nfunction collide(labels, collider) {\n var i, j, s0, s1;\n\n // IMPORTANT Iterate in the reverse order since items at the end of the\n // list have an higher weight/priority and thus should be less impacted\n // by the overlapping strategy.\n\n for (i = labels.length - 1; i >= 0; --i) {\n s0 = labels[i].$layout;\n\n for (j = i - 1; j >= 0 && s0._visible; --j) {\n s1 = labels[j].$layout;\n\n if (s1._visible && s0._box.intersects(s1._box)) {\n collider(s0, s1);\n }\n }\n }\n\n return labels;\n}\n\nfunction compute(labels) {\n var i, ilen, label, state, geometry, center, proxy;\n\n // Initialize labels for overlap detection\n for (i = 0, ilen = labels.length; i < ilen; ++i) {\n label = labels[i];\n state = label.$layout;\n\n if (state._visible) {\n // Chart.js 3 removed el._model in favor of getProps(), making harder to\n // abstract reading values in positioners. Also, using string arrays to\n // read values (i.e. var {a,b,c} = el.getProps([\"a\",\"b\",\"c\"])) would make\n // positioners inefficient in the normal case (i.e. not the final values)\n // and the code a bit ugly, so let's use a Proxy instead.\n proxy = new Proxy(label._el, {get: (el, p) => el.getProps([p], true)[p]});\n\n geometry = label.geometry();\n center = coordinates(proxy, label.model(), geometry);\n state._box.update(center, geometry, label.rotation());\n }\n }\n\n // Auto hide overlapping labels\n return collide(labels, function(s0, s1) {\n var h0 = s0._hidable;\n var h1 = s1._hidable;\n\n if ((h0 && h1) || h1) {\n s1._visible = false;\n } else if (h0) {\n s0._visible = false;\n }\n });\n}\n\nvar layout = {\n prepare: function(datasets) {\n var labels = [];\n var i, j, ilen, jlen, label;\n\n for (i = 0, ilen = datasets.length; i < ilen; ++i) {\n for (j = 0, jlen = datasets[i].length; j < jlen; ++j) {\n label = datasets[i][j];\n labels.push(label);\n label.$layout = {\n _box: new HitBox(),\n _hidable: false,\n _visible: true,\n _set: i,\n _idx: label._index\n };\n }\n }\n\n // TODO New `z` option: labels with a higher z-index are drawn\n // of top of the ones with a lower index. Lowest z-index labels\n // are also discarded first when hiding overlapping labels.\n labels.sort(function(a, b) {\n var sa = a.$layout;\n var sb = b.$layout;\n\n return sa._idx === sb._idx\n ? sb._set - sa._set\n : sb._idx - sa._idx;\n });\n\n this.update(labels);\n\n return labels;\n },\n\n update: function(labels) {\n var dirty = false;\n var i, ilen, label, model, state;\n\n for (i = 0, ilen = labels.length; i < ilen; ++i) {\n label = labels[i];\n model = label.model();\n state = label.$layout;\n state._hidable = model && model.display === 'auto';\n state._visible = label.visible();\n dirty |= state._hidable;\n }\n\n if (dirty) {\n compute(labels);\n }\n },\n\n lookup: function(labels, point) {\n var i, state;\n\n // IMPORTANT Iterate in the reverse order since items at the end of\n // the list have an higher z-index, thus should be picked first.\n\n for (i = labels.length - 1; i >= 0; --i) {\n state = labels[i].$layout;\n\n if (state && state._visible && state._box.contains(point)) {\n return labels[i];\n }\n }\n\n return null;\n },\n\n draw: function(chart, labels) {\n var i, ilen, label, state, geometry, center;\n\n for (i = 0, ilen = labels.length; i < ilen; ++i) {\n label = labels[i];\n state = label.$layout;\n\n if (state._visible) {\n geometry = label.geometry();\n center = coordinates(label._el, label.model(), geometry);\n state._box.update(center, geometry, label.rotation());\n label.draw(chart, center);\n }\n }\n }\n};\n\nvar formatter = function(value) {\n if ((0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndef)(value)) {\n return null;\n }\n\n var label = value;\n var keys, klen, k;\n if ((0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.isObject)(value)) {\n if (!(0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndef)(value.label)) {\n label = value.label;\n } else if (!(0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndef)(value.r)) {\n label = value.r;\n } else {\n label = '';\n keys = Object.keys(value);\n for (k = 0, klen = keys.length; k < klen; ++k) {\n label += (k !== 0 ? ', ' : '') + keys[k] + ': ' + value[keys[k]];\n }\n }\n }\n\n return '' + label;\n};\n\n/**\n * IMPORTANT: make sure to also update tests and TypeScript definition\n * files (`/test/specs/defaults.spec.js` and `/types/options.d.ts`)\n */\n\nvar defaults = {\n align: 'center',\n anchor: 'center',\n backgroundColor: null,\n borderColor: null,\n borderRadius: 0,\n borderWidth: 0,\n clamp: false,\n clip: false,\n color: undefined,\n display: true,\n font: {\n family: undefined,\n lineHeight: 1.2,\n size: undefined,\n style: undefined,\n weight: null\n },\n formatter: formatter,\n labels: undefined,\n listeners: {},\n offset: 4,\n opacity: 1,\n padding: {\n top: 4,\n right: 4,\n bottom: 4,\n left: 4\n },\n rotation: 0,\n textAlign: 'start',\n textStrokeColor: undefined,\n textStrokeWidth: 0,\n textShadowBlur: 0,\n textShadowColor: undefined\n};\n\n/**\n * @see https://github.com/chartjs/Chart.js/issues/4176\n */\n\nvar EXPANDO_KEY = '$datalabels';\nvar DEFAULT_KEY = '$default';\n\nfunction configure(dataset, options) {\n var override = dataset.datalabels;\n var listeners = {};\n var configs = [];\n var labels, keys;\n\n if (override === false) {\n return null;\n }\n if (override === true) {\n override = {};\n }\n\n options = (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.merge)({}, [options, override]);\n labels = options.labels || {};\n keys = Object.keys(labels);\n delete options.labels;\n\n if (keys.length) {\n keys.forEach(function(key) {\n if (labels[key]) {\n configs.push((0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.merge)({}, [\n options,\n labels[key],\n {_key: key}\n ]));\n }\n });\n } else {\n // Default label if no \"named\" label defined.\n configs.push(options);\n }\n\n // listeners: {: {: }}\n listeners = configs.reduce(function(target, config) {\n (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.each)(config.listeners || {}, function(fn, event) {\n target[event] = target[event] || {};\n target[event][config._key || DEFAULT_KEY] = fn;\n });\n\n delete config.listeners;\n return target;\n }, {});\n\n return {\n labels: configs,\n listeners: listeners\n };\n}\n\nfunction dispatchEvent(chart, listeners, label, event) {\n if (!listeners) {\n return;\n }\n\n var context = label.$context;\n var groups = label.$groups;\n var callback$1;\n\n if (!listeners[groups._set]) {\n return;\n }\n\n callback$1 = listeners[groups._set][groups._key];\n if (!callback$1) {\n return;\n }\n\n if ((0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.callback)(callback$1, [context, event]) === true) {\n // Users are allowed to tweak the given context by injecting values that can be\n // used in scriptable options to display labels differently based on the current\n // event (e.g. highlight an hovered label). That's why we update the label with\n // the output context and schedule a new chart render by setting it dirty.\n chart[EXPANDO_KEY]._dirty = true;\n label.update(context);\n }\n}\n\nfunction dispatchMoveEvents(chart, listeners, previous, label, event) {\n var enter, leave;\n\n if (!previous && !label) {\n return;\n }\n\n if (!previous) {\n enter = true;\n } else if (!label) {\n leave = true;\n } else if (previous !== label) {\n leave = enter = true;\n }\n\n if (leave) {\n dispatchEvent(chart, listeners.leave, previous, event);\n }\n if (enter) {\n dispatchEvent(chart, listeners.enter, label, event);\n }\n}\n\nfunction handleMoveEvents(chart, event) {\n var expando = chart[EXPANDO_KEY];\n var listeners = expando._listeners;\n var previous, label;\n\n if (!listeners.enter && !listeners.leave) {\n return;\n }\n\n if (event.type === 'mousemove') {\n label = layout.lookup(expando._labels, event);\n } else if (event.type !== 'mouseout') {\n return;\n }\n\n previous = expando._hovered;\n expando._hovered = label;\n dispatchMoveEvents(chart, listeners, previous, label, event);\n}\n\nfunction handleClickEvents(chart, event) {\n var expando = chart[EXPANDO_KEY];\n var handlers = expando._listeners.click;\n var label = handlers && layout.lookup(expando._labels, event);\n if (label) {\n dispatchEvent(chart, handlers, label, event);\n }\n}\n\nvar plugin = {\n id: 'datalabels',\n\n defaults: defaults,\n\n beforeInit: function(chart) {\n chart[EXPANDO_KEY] = {\n _actives: []\n };\n },\n\n beforeUpdate: function(chart) {\n var expando = chart[EXPANDO_KEY];\n expando._listened = false;\n expando._listeners = {}; // {: {: {: }}}\n expando._datasets = []; // per dataset labels: [Label[]]\n expando._labels = []; // layouted labels: Label[]\n },\n\n afterDatasetUpdate: function(chart, args, options) {\n var datasetIndex = args.index;\n var expando = chart[EXPANDO_KEY];\n var labels = expando._datasets[datasetIndex] = [];\n var visible = chart.isDatasetVisible(datasetIndex);\n var dataset = chart.data.datasets[datasetIndex];\n var config = configure(dataset, options);\n var elements = args.meta.data || [];\n var ctx = chart.ctx;\n var i, j, ilen, jlen, cfg, key, el, label;\n\n ctx.save();\n\n for (i = 0, ilen = elements.length; i < ilen; ++i) {\n el = elements[i];\n el[EXPANDO_KEY] = [];\n\n if (visible && el && chart.getDataVisibility(i) && !el.skip) {\n for (j = 0, jlen = config.labels.length; j < jlen; ++j) {\n cfg = config.labels[j];\n key = cfg._key;\n\n label = new Label(cfg, ctx, el, i);\n label.$groups = {\n _set: datasetIndex,\n _key: key || DEFAULT_KEY\n };\n label.$context = {\n active: false,\n chart: chart,\n dataIndex: i,\n dataset: dataset,\n datasetIndex: datasetIndex\n };\n\n label.update(label.$context);\n el[EXPANDO_KEY].push(label);\n labels.push(label);\n }\n }\n }\n\n ctx.restore();\n\n // Store listeners at the chart level and per event type to optimize\n // cases where no listeners are registered for a specific event.\n (0,chart_js_helpers__WEBPACK_IMPORTED_MODULE_0__.merge)(expando._listeners, config.listeners, {\n merger: function(event, target, source) {\n target[event] = target[event] || {};\n target[event][args.index] = source[event];\n expando._listened = true;\n }\n });\n },\n\n afterUpdate: function(chart) {\n chart[EXPANDO_KEY]._labels = layout.prepare(chart[EXPANDO_KEY]._datasets);\n },\n\n // Draw labels on top of all dataset elements\n // https://github.com/chartjs/chartjs-plugin-datalabels/issues/29\n // https://github.com/chartjs/chartjs-plugin-datalabels/issues/32\n afterDatasetsDraw: function(chart) {\n layout.draw(chart, chart[EXPANDO_KEY]._labels);\n },\n\n beforeEvent: function(chart, args) {\n // If there is no listener registered for this chart, `listened` will be false,\n // meaning we can immediately ignore the incoming event and avoid useless extra\n // computation for users who don't implement label interactions.\n if (chart[EXPANDO_KEY]._listened) {\n var event = args.event;\n switch (event.type) {\n case 'mousemove':\n case 'mouseout':\n handleMoveEvents(chart, event);\n break;\n case 'click':\n handleClickEvents(chart, event);\n break;\n }\n }\n },\n\n afterEvent: function(chart) {\n var expando = chart[EXPANDO_KEY];\n var previous = expando._actives;\n var actives = expando._actives = chart.getActiveElements();\n var updates = utils.arrayDiff(previous, actives);\n var i, ilen, j, jlen, update, label, labels;\n\n for (i = 0, ilen = updates.length; i < ilen; ++i) {\n update = updates[i];\n if (update[1]) {\n labels = update[0].element[EXPANDO_KEY] || [];\n for (j = 0, jlen = labels.length; j < jlen; ++j) {\n label = labels[j];\n label.$context.active = (update[1] === 1);\n label.update(label.$context);\n }\n }\n }\n\n if (expando._dirty || updates.length) {\n layout.update(expando._labels);\n chart.render();\n }\n\n delete expando._dirty;\n }\n};\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY2hhcnRqcy1wbHVnaW4tZGF0YWxhYmVscy9kaXN0L2NoYXJ0anMtcGx1Z2luLWRhdGFsYWJlbHMuZXNtLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDOEg7QUFDdEM7O0FBRXhGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUSxVQUFVLCtEQUFhO0FBQy9CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxnQkFBZ0IsVUFBVTtBQUMxQjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtDQUFrQyxVQUFVO0FBQzVDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DLFVBQVU7QUFDOUM7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7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QTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRCxnRUFBZ0U7QUFDaEUsZ0VBQWdFOztBQUVoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLG1CQUFtQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1REFBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLGlCQUFpQjtBQUNqQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtB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QTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1Q0FBdUMsVUFBVTtBQUNqRDtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsVUFBVTtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUU2QiIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jaGFydGpzLXBsdWdpbi1kYXRhbGFiZWxzL2Rpc3QvY2hhcnRqcy1wbHVnaW4tZGF0YWxhYmVscy5lc20uanM/MGQwZiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIGNoYXJ0anMtcGx1Z2luLWRhdGFsYWJlbHMgdjIuMi4wXG4gKiBodHRwczovL2NoYXJ0anMtcGx1Z2luLWRhdGFsYWJlbHMubmV0bGlmeS5hcHBcbiAqIChjKSAyMDE3LTIwMjIgY2hhcnRqcy1wbHVnaW4tZGF0YWxhYmVscyBjb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZVxuICovXG5pbXBvcnQgeyBpc051bGxPclVuZGVmLCBtZXJnZSwgdG9Gb250LCByZXNvbHZlLCB0b1BhZGRpbmcsIHZhbHVlT3JEZWZhdWx0LCBjYWxsYmFjaywgaXNPYmplY3QsIGVhY2ggfSBmcm9tICdjaGFydC5qcy9oZWxwZXJzJztcbmltcG9ydCB7IGRlZmF1bHRzIGFzIGRlZmF1bHRzJDEsIEFyY0VsZW1lbnQsIFBvaW50RWxlbWVudCwgQmFyRWxlbWVudCB9IGZyb20gJ2NoYXJ0LmpzJztcblxudmFyIGRldmljZVBpeGVsUmF0aW8gPSAoZnVuY3Rpb24oKSB7XG4gIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmICh3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbykge1xuICAgICAgcmV0dXJuIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvO1xuICAgIH1cblxuICAgIC8vIGRldmljZVBpeGVsUmF0aW8gaXMgdW5kZWZpbmVkIG9uIElFMTBcbiAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjAyMDQxODAvODgzNzg4N1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL2NoYXJ0anMtcGx1Z2luLWRhdGFsYWJlbHMvaXNzdWVzLzg1XG4gICAgdmFyIHNjcmVlbiA9IHdpbmRvdy5zY3JlZW47XG4gICAgaWYgKHNjcmVlbikge1xuICAgICAgcmV0dXJuIChzY3JlZW4uZGV2aWNlWERQSSB8fCAxKSAvIChzY3JlZW4ubG9naWNhbFhEUEkgfHwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIDE7XG59KCkpO1xuXG52YXIgdXRpbHMgPSB7XG4gIC8vIEB0b2RvIG1vdmUgdGhpcyBpbiBDaGFydC5oZWxwZXJzLnRvVGV4dExpbmVzXG4gIHRvVGV4dExpbmVzOiBmdW5jdGlvbihpbnB1dHMpIHtcbiAgICB2YXIgbGluZXMgPSBbXTtcbiAgICB2YXIgaW5wdXQ7XG5cbiAgICBpbnB1dHMgPSBbXS5jb25jYXQoaW5wdXRzKTtcbiAgICB3aGlsZSAoaW5wdXRzLmxlbmd0aCkge1xuICAgICAgaW5wdXQgPSBpbnB1dHMucG9wKCk7XG4gICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICBsaW5lcy51bnNoaWZ0LmFwcGx5KGxpbmVzLCBpbnB1dC5zcGxpdCgnXFxuJykpO1xuICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICBpbnB1dHMucHVzaC5hcHBseShpbnB1dHMsIGlucHV0KTtcbiAgICAgIH0gZWxzZSBpZiAoIWlzTnVsbE9yVW5kZWYoaW5wdXRzKSkge1xuICAgICAgICBsaW5lcy51bnNoaWZ0KCcnICsgaW5wdXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBsaW5lcztcbiAgfSxcblxuICAvLyBAdG9kbyBtb3ZlIHRoaXMgaW4gQ2hhcnQuaGVscGVycy5jYW52YXMudGV4dFNpemVcbiAgLy8gQHRvZG8gY2FjaGUgY2FsbHMgb2YgbWVhc3VyZVRleHQgaWYgZm9udCBkb2Vzbid0IGNoYW5nZT8hXG4gIHRleHRTaXplOiBmdW5jdGlvbihjdHgsIGxpbmVzLCBmb250KSB7XG4gICAgdmFyIGl0ZW1zID0gW10uY29uY2F0KGxpbmVzKTtcbiAgICB2YXIgaWxlbiA9IGl0ZW1zLmxlbmd0aDtcbiAgICB2YXIgcHJldiA9IGN0eC5mb250O1xuICAgIHZhciB3aWR0aCA9IDA7XG4gICAgdmFyIGk7XG5cbiAgICBjdHguZm9udCA9IGZvbnQuc3RyaW5nO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgd2lkdGggPSBNYXRoLm1heChjdHgubWVhc3VyZVRleHQoaXRlbXNbaV0pLndpZHRoLCB3aWR0aCk7XG4gICAgfVxuXG4gICAgY3R4LmZvbnQgPSBwcmV2O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGhlaWdodDogaWxlbiAqIGZvbnQubGluZUhlaWdodCxcbiAgICAgIHdpZHRoOiB3aWR0aFxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdmFsdWUgYm91bmRlZCBieSBtaW4gYW5kIG1heC4gVGhpcyBpcyBlcXVpdmFsZW50IHRvIG1heChtaW4sIG1pbih2YWx1ZSwgbWF4KSkuXG4gICAqIEB0b2RvIG1vdmUgdGhpcyBtZXRob2QgaW4gQ2hhcnQuaGVscGVycy5ib3VuZFxuICAgKiBodHRwczovL2RvYy5xdC5pby9xdC01L3F0Z2xvYmFsLmh0bWwjcUJvdW5kXG4gICAqL1xuICBib3VuZDogZnVuY3Rpb24obWluLCB2YWx1ZSwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4odmFsdWUsIG1heCkpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGFycmF5IG9mIHBhaXIgW3ZhbHVlLCBzdGF0ZV0gd2hlcmUgc3RhdGUgaXM6XG4gICAqICogLTE6IHZhbHVlIGlzIG9ubHkgaW4gYTAgKHJlbW92ZWQpXG4gICAqICogIDE6IHZhbHVlIGlzIG9ubHkgaW4gYTEgKGFkZGVkKVxuICAgKi9cbiAgYXJyYXlEaWZmOiBmdW5jdGlvbihhMCwgYTEpIHtcbiAgICB2YXIgcHJldiA9IGEwLnNsaWNlKCk7XG4gICAgdmFyIHVwZGF0ZXMgPSBbXTtcbiAgICB2YXIgaSwgaiwgaWxlbiwgdjtcblxuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBhMS5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIHYgPSBhMVtpXTtcbiAgICAgIGogPSBwcmV2LmluZGV4T2Yodik7XG5cbiAgICAgIGlmIChqID09PSAtMSkge1xuICAgICAgICB1cGRhdGVzLnB1c2goW3YsIDFdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHByZXYuc3BsaWNlKGosIDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBwcmV2Lmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgdXBkYXRlcy5wdXNoKFtwcmV2W2ldLCAtMV0pO1xuICAgIH1cblxuICAgIHJldHVybiB1cGRhdGVzO1xuICB9LFxuXG4gIC8qKlxuICAgKiBodHRwczovL2dpdGh1Yi5jb20vY2hhcnRqcy9jaGFydGpzLXBsdWdpbi1kYXRhbGFiZWxzL2lzc3Vlcy83MFxuICAgKi9cbiAgcmFzdGVyaXplOiBmdW5jdGlvbih2KSB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQodiAqIGRldmljZVBpeGVsUmF0aW8pIC8gZGV2aWNlUGl4ZWxSYXRpbztcbiAgfVxufTtcblxuZnVuY3Rpb24gb3JpZW50KHBvaW50LCBvcmlnaW4pIHtcbiAgdmFyIHgwID0gb3JpZ2luLng7XG4gIHZhciB5MCA9IG9yaWdpbi55O1xuXG4gIGlmICh4MCA9PT0gbnVsbCkge1xuICAgIHJldHVybiB7eDogMCwgeTogLTF9O1xuICB9XG4gIGlmICh5MCA9PT0gbnVsbCkge1xuICAgIHJldHVybiB7eDogMSwgeTogMH07XG4gIH1cblxuICB2YXIgZHggPSBwb2ludC54IC0geDA7XG4gIHZhciBkeSA9IHBvaW50LnkgLSB5MDtcbiAgdmFyIGxuID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcblxuICByZXR1cm4ge1xuICAgIHg6IGxuID8gZHggLyBsbiA6IDAsXG4gICAgeTogbG4gPyBkeSAvIGxuIDogLTFcbiAgfTtcbn1cblxuZnVuY3Rpb24gYWxpZ25lZCh4LCB5LCB2eCwgdnksIGFsaWduKSB7XG4gIHN3aXRjaCAoYWxpZ24pIHtcbiAgY2FzZSAnY2VudGVyJzpcbiAgICB2eCA9IHZ5ID0gMDtcbiAgICBicmVhaztcbiAgY2FzZSAnYm90dG9tJzpcbiAgICB2eCA9IDA7XG4gICAgdnkgPSAxO1xuICAgIGJyZWFrO1xuICBjYXNlICdyaWdodCc6XG4gICAgdnggPSAxO1xuICAgIHZ5ID0gMDtcbiAgICBicmVhaztcbiAgY2FzZSAnbGVmdCc6XG4gICAgdnggPSAtMTtcbiAgICB2eSA9IDA7XG4gICAgYnJlYWs7XG4gIGNhc2UgJ3RvcCc6XG4gICAgdnggPSAwO1xuICAgIHZ5ID0gLTE7XG4gICAgYnJlYWs7XG4gIGNhc2UgJ3N0YXJ0JzpcbiAgICB2eCA9IC12eDtcbiAgICB2eSA9IC12eTtcbiAgICBicmVhaztcbiAgY2FzZSAnZW5kJzpcbiAgICAvLyBrZWVwIG5hdHVyYWwgb3JpZW50YXRpb25cbiAgICBicmVhaztcbiAgZGVmYXVsdDpcbiAgICAvLyBjbG9ja3dpc2Ugcm90YXRpb24gKGluIGRlZ3JlZSlcbiAgICBhbGlnbiAqPSAoTWF0aC5QSSAvIDE4MCk7XG4gICAgdnggPSBNYXRoLmNvcyhhbGlnbik7XG4gICAgdnkgPSBNYXRoLnNpbihhbGlnbik7XG4gICAgYnJlYWs7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHg6IHgsXG4gICAgeTogeSxcbiAgICB2eDogdngsXG4gICAgdnk6IHZ5XG4gIH07XG59XG5cbi8vIExpbmUgY2xpcHBpbmcgKENvaGVu4oCTU3V0aGVybGFuZCBhbGdvcml0aG0pXG4vLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db2hlbuKAk1N1dGhlcmxhbmRfYWxnb3JpdGhtXG5cbnZhciBSX0lOU0lERSA9IDA7XG52YXIgUl9MRUZUID0gMTtcbnZhciBSX1JJR0hUID0gMjtcbnZhciBSX0JPVFRPTSA9IDQ7XG52YXIgUl9UT1AgPSA4O1xuXG5mdW5jdGlvbiByZWdpb24oeCwgeSwgcmVjdCkge1xuICB2YXIgcmVzID0gUl9JTlNJREU7XG5cbiAgaWYgKHggPCByZWN0LmxlZnQpIHtcbiAgICByZXMgfD0gUl9MRUZUO1xuICB9IGVsc2UgaWYgKHggPiByZWN0LnJpZ2h0KSB7XG4gICAgcmVzIHw9IFJfUklHSFQ7XG4gIH1cbiAgaWYgKHkgPCByZWN0LnRvcCkge1xuICAgIHJlcyB8PSBSX1RPUDtcbiAgfSBlbHNlIGlmICh5ID4gcmVjdC5ib3R0b20pIHtcbiAgICByZXMgfD0gUl9CT1RUT007XG4gIH1cblxuICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBjbGlwcGVkKHNlZ21lbnQsIGFyZWEpIHtcbiAgdmFyIHgwID0gc2VnbWVudC54MDtcbiAgdmFyIHkwID0gc2VnbWVudC55MDtcbiAgdmFyIHgxID0gc2VnbWVudC54MTtcbiAgdmFyIHkxID0gc2VnbWVudC55MTtcbiAgdmFyIHIwID0gcmVnaW9uKHgwLCB5MCwgYXJlYSk7XG4gIHZhciByMSA9IHJlZ2lvbih4MSwgeTEsIGFyZWEpO1xuICB2YXIgciwgeCwgeTtcblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc3RhbnQtY29uZGl0aW9uXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgaWYgKCEocjAgfCByMSkgfHwgKHIwICYgcjEpKSB7XG4gICAgICAvLyBib3RoIHBvaW50cyBpbnNpZGUgb3Igb24gdGhlIHNhbWUgc2lkZTogbm8gY2xpcHBpbmdcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8vIGF0IGxlYXN0IG9uZSBwb2ludCBpcyBvdXRzaWRlXG4gICAgciA9IHIwIHx8IHIxO1xuXG4gICAgaWYgKHIgJiBSX1RPUCkge1xuICAgICAgeCA9IHgwICsgKHgxIC0geDApICogKGFyZWEudG9wIC0geTApIC8gKHkxIC0geTApO1xuICAgICAgeSA9IGFyZWEudG9wO1xuICAgIH0gZWxzZSBpZiAociAmIFJfQk9UVE9NKSB7XG4gICAgICB4ID0geDAgKyAoeDEgLSB4MCkgKiAoYXJlYS5ib3R0b20gLSB5MCkgLyAoeTEgLSB5MCk7XG4gICAgICB5ID0gYXJlYS5ib3R0b207XG4gICAgfSBlbHNlIGlmIChyICYgUl9SSUdIVCkge1xuICAgICAgeSA9IHkwICsgKHkxIC0geTApICogKGFyZWEucmlnaHQgLSB4MCkgLyAoeDEgLSB4MCk7XG4gICAgICB4ID0gYXJlYS5yaWdodDtcbiAgICB9IGVsc2UgaWYgKHIgJiBSX0xFRlQpIHtcbiAgICAgIHkgPSB5MCArICh5MSAtIHkwKSAqIChhcmVhLmxlZnQgLSB4MCkgLyAoeDEgLSB4MCk7XG4gICAgICB4ID0gYXJlYS5sZWZ0O1xuICAgIH1cblxuICAgIGlmIChyID09PSByMCkge1xuICAgICAgeDAgPSB4O1xuICAgICAgeTAgPSB5O1xuICAgICAgcjAgPSByZWdpb24oeDAsIHkwLCBhcmVhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgeDEgPSB4O1xuICAgICAgeTEgPSB5O1xuICAgICAgcjEgPSByZWdpb24oeDEsIHkxLCBhcmVhKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHgwOiB4MCxcbiAgICB4MTogeDEsXG4gICAgeTA6IHkwLFxuICAgIHkxOiB5MVxuICB9O1xufVxuXG5mdW5jdGlvbiBjb21wdXRlJDEocmFuZ2UsIGNvbmZpZykge1xuICB2YXIgYW5jaG9yID0gY29uZmlnLmFuY2hvcjtcbiAgdmFyIHNlZ21lbnQgPSByYW5nZTtcbiAgdmFyIHgsIHk7XG5cbiAgaWYgKGNvbmZpZy5jbGFtcCkge1xuICAgIHNlZ21lbnQgPSBjbGlwcGVkKHNlZ21lbnQsIGNvbmZpZy5hcmVhKTtcbiAgfVxuXG4gIGlmIChhbmNob3IgPT09ICdzdGFydCcpIHtcbiAgICB4ID0gc2VnbWVudC54MDtcbiAgICB5ID0gc2VnbWVudC55MDtcbiAgfSBlbHNlIGlmIChhbmNob3IgPT09ICdlbmQnKSB7XG4gICAgeCA9IHNlZ21lbnQueDE7XG4gICAgeSA9IHNlZ21lbnQueTE7XG4gIH0gZWxzZSB7XG4gICAgeCA9IChzZWdtZW50LngwICsgc2VnbWVudC54MSkgLyAyO1xuICAgIHkgPSAoc2VnbWVudC55MCArIHNlZ21lbnQueTEpIC8gMjtcbiAgfVxuXG4gIHJldHVybiBhbGlnbmVkKHgsIHksIHJhbmdlLnZ4LCByYW5nZS52eSwgY29uZmlnLmFsaWduKTtcbn1cblxudmFyIHBvc2l0aW9uZXJzID0ge1xuICBhcmM6IGZ1bmN0aW9uKGVsLCBjb25maWcpIHtcbiAgICB2YXIgYW5nbGUgPSAoZWwuc3RhcnRBbmdsZSArIGVsLmVuZEFuZ2xlKSAvIDI7XG4gICAgdmFyIHZ4ID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHZhciB2eSA9IE1hdGguc2luKGFuZ2xlKTtcbiAgICB2YXIgcjAgPSBlbC5pbm5lclJhZGl1cztcbiAgICB2YXIgcjEgPSBlbC5vdXRlclJhZGl1cztcblxuICAgIHJldHVybiBjb21wdXRlJDEoe1xuICAgICAgeDA6IGVsLnggKyB2eCAqIHIwLFxuICAgICAgeTA6IGVsLnkgKyB2eSAqIHIwLFxuICAgICAgeDE6IGVsLnggKyB2eCAqIHIxLFxuICAgICAgeTE6IGVsLnkgKyB2eSAqIHIxLFxuICAgICAgdng6IHZ4LFxuICAgICAgdnk6IHZ5XG4gICAgfSwgY29uZmlnKTtcbiAgfSxcblxuICBwb2ludDogZnVuY3Rpb24oZWwsIGNvbmZpZykge1xuICAgIHZhciB2ID0gb3JpZW50KGVsLCBjb25maWcub3JpZ2luKTtcbiAgICB2YXIgcnggPSB2LnggKiBlbC5vcHRpb25zLnJhZGl1cztcbiAgICB2YXIgcnkgPSB2LnkgKiBlbC5vcHRpb25zLnJhZGl1cztcblxuICAgIHJldHVybiBjb21wdXRlJDEoe1xuICAgICAgeDA6IGVsLnggLSByeCxcbiAgICAgIHkwOiBlbC55IC0gcnksXG4gICAgICB4MTogZWwueCArIHJ4LFxuICAgICAgeTE6IGVsLnkgKyByeSxcbiAgICAgIHZ4OiB2LngsXG4gICAgICB2eTogdi55XG4gICAgfSwgY29uZmlnKTtcbiAgfSxcblxuICBiYXI6IGZ1bmN0aW9uKGVsLCBjb25maWcpIHtcbiAgICB2YXIgdiA9IG9yaWVudChlbCwgY29uZmlnLm9yaWdpbik7XG4gICAgdmFyIHggPSBlbC54O1xuICAgIHZhciB5ID0gZWwueTtcbiAgICB2YXIgc3ggPSAwO1xuICAgIHZhciBzeSA9IDA7XG5cbiAgICBpZiAoZWwuaG9yaXpvbnRhbCkge1xuICAgICAgeCA9IE1hdGgubWluKGVsLngsIGVsLmJhc2UpO1xuICAgICAgc3ggPSBNYXRoLmFicyhlbC5iYXNlIC0gZWwueCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHkgPSBNYXRoLm1pbihlbC55LCBlbC5iYXNlKTtcbiAgICAgIHN5ID0gTWF0aC5hYnMoZWwuYmFzZSAtIGVsLnkpO1xuICAgIH1cblxuICAgIHJldHVybiBjb21wdXRlJDEoe1xuICAgICAgeDA6IHgsXG4gICAgICB5MDogeSArIHN5LFxuICAgICAgeDE6IHggKyBzeCxcbiAgICAgIHkxOiB5LFxuICAgICAgdng6IHYueCxcbiAgICAgIHZ5OiB2LnlcbiAgICB9LCBjb25maWcpO1xuICB9LFxuXG4gIGZhbGxiYWNrOiBmdW5jdGlvbihlbCwgY29uZmlnKSB7XG4gICAgdmFyIHYgPSBvcmllbnQoZWwsIGNvbmZpZy5vcmlnaW4pO1xuXG4gICAgcmV0dXJuIGNvbXB1dGUkMSh7XG4gICAgICB4MDogZWwueCxcbiAgICAgIHkwOiBlbC55LFxuICAgICAgeDE6IGVsLnggKyAoZWwud2lkdGggfHwgMCksXG4gICAgICB5MTogZWwueSArIChlbC5oZWlnaHQgfHwgMCksXG4gICAgICB2eDogdi54LFxuICAgICAgdnk6IHYueVxuICAgIH0sIGNvbmZpZyk7XG4gIH1cbn07XG5cbnZhciByYXN0ZXJpemUgPSB1dGlscy5yYXN0ZXJpemU7XG5cbmZ1bmN0aW9uIGJvdW5kaW5nUmVjdHMobW9kZWwpIHtcbiAgdmFyIGJvcmRlcldpZHRoID0gbW9kZWwuYm9yZGVyV2lkdGggfHwgMDtcbiAgdmFyIHBhZGRpbmcgPSBtb2RlbC5wYWRkaW5nO1xuICB2YXIgdGggPSBtb2RlbC5zaXplLmhlaWdodDtcbiAgdmFyIHR3ID0gbW9kZWwuc2l6ZS53aWR0aDtcbiAgdmFyIHR4ID0gLXR3IC8gMjtcbiAgdmFyIHR5ID0gLXRoIC8gMjtcblxuICByZXR1cm4ge1xuICAgIGZyYW1lOiB7XG4gICAgICB4OiB0eCAtIHBhZGRpbmcubGVmdCAtIGJvcmRlcldpZHRoLFxuICAgICAgeTogdHkgLSBwYWRkaW5nLnRvcCAtIGJvcmRlcldpZHRoLFxuICAgICAgdzogdHcgKyBwYWRkaW5nLndpZHRoICsgYm9yZGVyV2lkdGggKiAyLFxuICAgICAgaDogdGggKyBwYWRkaW5nLmhlaWdodCArIGJvcmRlcldpZHRoICogMlxuICAgIH0sXG4gICAgdGV4dDoge1xuICAgICAgeDogdHgsXG4gICAgICB5OiB0eSxcbiAgICAgIHc6IHR3LFxuICAgICAgaDogdGhcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjYWxlT3JpZ2luKGVsLCBjb250ZXh0KSB7XG4gIHZhciBzY2FsZSA9IGNvbnRleHQuY2hhcnQuZ2V0RGF0YXNldE1ldGEoY29udGV4dC5kYXRhc2V0SW5kZXgpLnZTY2FsZTtcblxuICBpZiAoIXNjYWxlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoc2NhbGUueENlbnRlciAhPT0gdW5kZWZpbmVkICYmIHNjYWxlLnlDZW50ZXIgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB7eDogc2NhbGUueENlbnRlciwgeTogc2NhbGUueUNlbnRlcn07XG4gIH1cblxuICB2YXIgcGl4ZWwgPSBzY2FsZS5nZXRCYXNlUGl4ZWwoKTtcbiAgcmV0dXJuIGVsLmhvcml6b250YWwgP1xuICAgIHt4OiBwaXhlbCwgeTogbnVsbH0gOlxuICAgIHt4OiBudWxsLCB5OiBwaXhlbH07XG59XG5cbmZ1bmN0aW9uIGdldFBvc2l0aW9uZXIoZWwpIHtcbiAgaWYgKGVsIGluc3RhbmNlb2YgQXJjRWxlbWVudCkge1xuICAgIHJldHVybiBwb3NpdGlvbmVycy5hcmM7XG4gIH1cbiAgaWYgKGVsIGluc3RhbmNlb2YgUG9pbnRFbGVtZW50KSB7XG4gICAgcmV0dXJuIHBvc2l0aW9uZXJzLnBvaW50O1xuICB9XG4gIGlmIChlbCBpbnN0YW5jZW9mIEJhckVsZW1lbnQpIHtcbiAgICByZXR1cm4gcG9zaXRpb25lcnMuYmFyO1xuICB9XG4gIHJldHVybiBwb3NpdGlvbmVycy5mYWxsYmFjaztcbn1cblxuZnVuY3Rpb24gZHJhd1JvdW5kZWRSZWN0KGN0eCwgeCwgeSwgdywgaCwgcmFkaXVzKSB7XG4gIHZhciBIQUxGX1BJID0gTWF0aC5QSSAvIDI7XG5cbiAgaWYgKHJhZGl1cykge1xuICAgIHZhciByID0gTWF0aC5taW4ocmFkaXVzLCBoIC8gMiwgdyAvIDIpO1xuICAgIHZhciBsZWZ0ID0geCArIHI7XG4gICAgdmFyIHRvcCA9IHkgKyByO1xuICAgIHZhciByaWdodCA9IHggKyB3IC0gcjtcbiAgICB2YXIgYm90dG9tID0geSArIGggLSByO1xuXG4gICAgY3R4Lm1vdmVUbyh4LCB0b3ApO1xuICAgIGlmIChsZWZ0IDwgcmlnaHQgJiYgdG9wIDwgYm90dG9tKSB7XG4gICAgICBjdHguYXJjKGxlZnQsIHRvcCwgciwgLU1hdGguUEksIC1IQUxGX1BJKTtcbiAgICAgIGN0eC5hcmMocmlnaHQsIHRvcCwgciwgLUhBTEZfUEksIDApO1xuICAgICAgY3R4LmFyYyhyaWdodCwgYm90dG9tLCByLCAwLCBIQUxGX1BJKTtcbiAgICAgIGN0eC5hcmMobGVmdCwgYm90dG9tLCByLCBIQUxGX1BJLCBNYXRoLlBJKTtcbiAgICB9IGVsc2UgaWYgKGxlZnQgPCByaWdodCkge1xuICAgICAgY3R4Lm1vdmVUbyhsZWZ0LCB5KTtcbiAgICAgIGN0eC5hcmMocmlnaHQsIHRvcCwgciwgLUhBTEZfUEksIEhBTEZfUEkpO1xuICAgICAgY3R4LmFyYyhsZWZ0LCB0b3AsIHIsIEhBTEZfUEksIE1hdGguUEkgKyBIQUxGX1BJKTtcbiAgICB9IGVsc2UgaWYgKHRvcCA8IGJvdHRvbSkge1xuICAgICAgY3R4LmFyYyhsZWZ0LCB0b3AsIHIsIC1NYXRoLlBJLCAwKTtcbiAgICAgIGN0eC5hcmMobGVmdCwgYm90dG9tLCByLCAwLCBNYXRoLlBJKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3R4LmFyYyhsZWZ0LCB0b3AsIHIsIC1NYXRoLlBJLCBNYXRoLlBJKTtcbiAgICB9XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgIGN0eC5tb3ZlVG8oeCwgeSk7XG4gIH0gZWxzZSB7XG4gICAgY3R4LnJlY3QoeCwgeSwgdywgaCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZHJhd0ZyYW1lKGN0eCwgcmVjdCwgbW9kZWwpIHtcbiAgdmFyIGJnQ29sb3IgPSBtb2RlbC5iYWNrZ3JvdW5kQ29sb3I7XG4gIHZhciBib3JkZXJDb2xvciA9IG1vZGVsLmJvcmRlckNvbG9yO1xuICB2YXIgYm9yZGVyV2lkdGggPSBtb2RlbC5ib3JkZXJXaWR0aDtcblxuICBpZiAoIWJnQ29sb3IgJiYgKCFib3JkZXJDb2xvciB8fCAhYm9yZGVyV2lkdGgpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY3R4LmJlZ2luUGF0aCgpO1xuXG4gIGRyYXdSb3VuZGVkUmVjdChcbiAgICBjdHgsXG4gICAgcmFzdGVyaXplKHJlY3QueCkgKyBib3JkZXJXaWR0aCAvIDIsXG4gICAgcmFzdGVyaXplKHJlY3QueSkgKyBib3JkZXJXaWR0aCAvIDIsXG4gICAgcmFzdGVyaXplKHJlY3QudykgLSBib3JkZXJXaWR0aCxcbiAgICByYXN0ZXJpemUocmVjdC5oKSAtIGJvcmRlcldpZHRoLFxuICAgIG1vZGVsLmJvcmRlclJhZGl1cyk7XG5cbiAgY3R4LmNsb3NlUGF0aCgpO1xuXG4gIGlmIChiZ0NvbG9yKSB7XG4gICAgY3R4LmZpbGxTdHlsZSA9IGJnQ29sb3I7XG4gICAgY3R4LmZpbGwoKTtcbiAgfVxuXG4gIGlmIChib3JkZXJDb2xvciAmJiBib3JkZXJXaWR0aCkge1xuICAgIGN0eC5zdHJva2VTdHlsZSA9IGJvcmRlckNvbG9yO1xuICAgIGN0eC5saW5lV2lkdGggPSBib3JkZXJXaWR0aDtcbiAgICBjdHgubGluZUpvaW4gPSAnbWl0ZXInO1xuICAgIGN0eC5zdHJva2UoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0ZXh0R2VvbWV0cnkocmVjdCwgYWxpZ24sIGZvbnQpIHtcbiAgdmFyIGggPSBmb250LmxpbmVIZWlnaHQ7XG4gIHZhciB3ID0gcmVjdC53O1xuICB2YXIgeCA9IHJlY3QueDtcbiAgdmFyIHkgPSByZWN0LnkgKyBoIC8gMjtcblxuICBpZiAoYWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgeCArPSB3IC8gMjtcbiAgfSBlbHNlIGlmIChhbGlnbiA9PT0gJ2VuZCcgfHwgYWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICB4ICs9IHc7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGg6IGgsXG4gICAgdzogdyxcbiAgICB4OiB4LFxuICAgIHk6IHlcbiAgfTtcbn1cblxuZnVuY3Rpb24gZHJhd1RleHRMaW5lKGN0eCwgdGV4dCwgY2ZnKSB7XG4gIHZhciBzaGFkb3cgPSBjdHguc2hhZG93Qmx1cjtcbiAgdmFyIHN0cm9rZWQgPSBjZmcuc3Ryb2tlZDtcbiAgdmFyIHggPSByYXN0ZXJpemUoY2ZnLngpO1xuICB2YXIgeSA9IHJhc3Rlcml6ZShjZmcueSk7XG4gIHZhciB3ID0gcmFzdGVyaXplKGNmZy53KTtcblxuICBpZiAoc3Ryb2tlZCkge1xuICAgIGN0eC5zdHJva2VUZXh0KHRleHQsIHgsIHksIHcpO1xuICB9XG5cbiAgaWYgKGNmZy5maWxsZWQpIHtcbiAgICBpZiAoc2hhZG93ICYmIHN0cm9rZWQpIHtcbiAgICAgIC8vIFByZXZlbnQgZHJhd2luZyBzaGFkb3cgb24gYm90aCB0aGUgdGV4dCBzdHJva2UgYW5kIGZpbGwsIHNvXG4gICAgICAvLyBpZiB0aGUgdGV4dCBpcyBzdHJva2VkLCByZW1vdmUgdGhlIHNoYWRvdyBmb3IgdGhlIHRleHQgZmlsbC5cbiAgICAgIGN0eC5zaGFkb3dCbHVyID0gMDtcbiAgICB9XG5cbiAgICBjdHguZmlsbFRleHQodGV4dCwgeCwgeSwgdyk7XG5cbiAgICBpZiAoc2hhZG93ICYmIHN0cm9rZWQpIHtcbiAgICAgIGN0eC5zaGFkb3dCbHVyID0gc2hhZG93O1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBkcmF3VGV4dChjdHgsIGxpbmVzLCByZWN0LCBtb2RlbCkge1xuICB2YXIgYWxpZ24gPSBtb2RlbC50ZXh0QWxpZ247XG4gIHZhciBjb2xvciA9IG1vZGVsLmNvbG9yO1xuICB2YXIgZmlsbGVkID0gISFjb2xvcjtcbiAgdmFyIGZvbnQgPSBtb2RlbC5mb250O1xuICB2YXIgaWxlbiA9IGxpbmVzLmxlbmd0aDtcbiAgdmFyIHN0cm9rZUNvbG9yID0gbW9kZWwudGV4dFN0cm9rZUNvbG9yO1xuICB2YXIgc3Ryb2tlV2lkdGggPSBtb2RlbC50ZXh0U3Ryb2tlV2lkdGg7XG4gIHZhciBzdHJva2VkID0gc3Ryb2tlQ29sb3IgJiYgc3Ryb2tlV2lkdGg7XG4gIHZhciBpO1xuXG4gIGlmICghaWxlbiB8fCAoIWZpbGxlZCAmJiAhc3Ryb2tlZCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBBZGp1c3QgY29vcmRpbmF0ZXMgYmFzZWQgb24gdGV4dCBhbGlnbm1lbnQgYW5kIGxpbmUgaGVpZ2h0XG4gIHJlY3QgPSB0ZXh0R2VvbWV0cnkocmVjdCwgYWxpZ24sIGZvbnQpO1xuXG4gIGN0eC5mb250ID0gZm9udC5zdHJpbmc7XG4gIGN0eC50ZXh0QWxpZ24gPSBhbGlnbjtcbiAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICBjdHguc2hhZG93Qmx1ciA9IG1vZGVsLnRleHRTaGFkb3dCbHVyO1xuICBjdHguc2hhZG93Q29sb3IgPSBtb2RlbC50ZXh0U2hhZG93Q29sb3I7XG5cbiAgaWYgKGZpbGxlZCkge1xuICAgIGN0eC5maWxsU3R5bGUgPSBjb2xvcjtcbiAgfVxuICBpZiAoc3Ryb2tlZCkge1xuICAgIGN0eC5saW5lSm9pbiA9ICdyb3VuZCc7XG4gICAgY3R4LmxpbmVXaWR0aCA9IHN0cm9rZVdpZHRoO1xuICAgIGN0eC5zdHJva2VTdHlsZSA9IHN0cm9rZUNvbG9yO1xuICB9XG5cbiAgZm9yIChpID0gMCwgaWxlbiA9IGxpbmVzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgIGRyYXdUZXh0TGluZShjdHgsIGxpbmVzW2ldLCB7XG4gICAgICBzdHJva2VkOiBzdHJva2VkLFxuICAgICAgZmlsbGVkOiBmaWxsZWQsXG4gICAgICB3OiByZWN0LncsXG4gICAgICB4OiByZWN0LngsXG4gICAgICB5OiByZWN0LnkgKyByZWN0LmggKiBpXG4gICAgfSk7XG4gIH1cbn1cblxudmFyIExhYmVsID0gZnVuY3Rpb24oY29uZmlnLCBjdHgsIGVsLCBpbmRleCkge1xuICB2YXIgbWUgPSB0aGlzO1xuXG4gIG1lLl9jb25maWcgPSBjb25maWc7XG4gIG1lLl9pbmRleCA9IGluZGV4O1xuICBtZS5fbW9kZWwgPSBudWxsO1xuICBtZS5fcmVjdHMgPSBudWxsO1xuICBtZS5fY3R4ID0gY3R4O1xuICBtZS5fZWwgPSBlbDtcbn07XG5cbm1lcmdlKExhYmVsLnByb3RvdHlwZSwge1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9tb2RlbGl6ZTogZnVuY3Rpb24oZGlzcGxheSwgbGluZXMsIGNvbmZpZywgY29udGV4dCkge1xuICAgIHZhciBtZSA9IHRoaXM7XG4gICAgdmFyIGluZGV4ID0gbWUuX2luZGV4O1xuICAgIHZhciBmb250ID0gdG9Gb250KHJlc29sdmUoW2NvbmZpZy5mb250LCB7fV0sIGNvbnRleHQsIGluZGV4KSk7XG4gICAgdmFyIGNvbG9yID0gcmVzb2x2ZShbY29uZmlnLmNvbG9yLCBkZWZhdWx0cyQxLmNvbG9yXSwgY29udGV4dCwgaW5kZXgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFsaWduOiByZXNvbHZlKFtjb25maWcuYWxpZ24sICdjZW50ZXInXSwgY29udGV4dCwgaW5kZXgpLFxuICAgICAgYW5jaG9yOiByZXNvbHZlKFtjb25maWcuYW5jaG9yLCAnY2VudGVyJ10sIGNvbnRleHQsIGluZGV4KSxcbiAgICAgIGFyZWE6IGNvbnRleHQuY2hhcnQuY2hhcnRBcmVhLFxuICAgICAgYmFja2dyb3VuZENvbG9yOiByZXNvbHZlKFtjb25maWcuYmFja2dyb3VuZENvbG9yLCBudWxsXSwgY29udGV4dCwgaW5kZXgpLFxuICAgICAgYm9yZGVyQ29sb3I6IHJlc29sdmUoW2NvbmZpZy5ib3JkZXJDb2xvciwgbnVsbF0sIGNvbnRleHQsIGluZGV4KSxcbiAgICAgIGJvcmRlclJhZGl1czogcmVzb2x2ZShbY29uZmlnLmJvcmRlclJhZGl1cywgMF0sIGNvbnRleHQsIGluZGV4KSxcbiAgICAgIGJvcmRlcldpZHRoOiByZXNvbHZlKFtjb25maWcuYm9yZGVyV2lkdGgsIDBdLCBjb250ZXh0LCBpbmRleCksXG4gICAgICBjbGFtcDogcmVzb2x2ZShbY29uZmlnLmNsYW1wLCBmYWxzZV0sIGNvbnRleHQsIGluZGV4KSxcbiAgICAgIGNsaXA6IHJlc29sdmUoW2NvbmZpZy5jbGlwLCBmYWxzZV0sIGNvbnRleHQsIGluZGV4KSxcbiAgICAgIGNvbG9yOiBjb2xvcixcbiAgICAgIGRpc3BsYXk6IGRpc3BsYXksXG4gICAgICBmb250OiBmb250LFxuICAgICAgbGluZXM6IGxpbmVzLFxuICAgICAgb2Zmc2V0OiByZXNvbHZlKFtjb25maWcub2Zmc2V0LCA0XSwgY29udGV4dCwgaW5kZXgpLFxuICAgICAgb3BhY2l0eTogcmVzb2x2ZShbY29uZmlnLm9wYWNpdHksIDFdLCBjb250ZXh0LCBpbmRleCksXG4gICAgICBvcmlnaW46IGdldFNjYWxlT3JpZ2luKG1lLl9lbCwgY29udGV4dCksXG4gICAgICBwYWRkaW5nOiB0b1BhZGRpbmcocmVzb2x2ZShbY29uZmlnLnBhZGRpbmcsIDRdLCBjb250ZXh0LCBpbmRleCkpLFxuICAgICAgcG9zaXRpb25lcjogZ2V0UG9zaXRpb25lcihtZS5fZWwpLFxuICAgICAgcm90YXRpb246IHJlc29sdmUoW2NvbmZpZy5yb3RhdGlvbiwgMF0sIGNvbnRleHQsIGluZGV4KSAqIChNYXRoLlBJIC8gMTgwKSxcbiAgICAgIHNpemU6IHV0aWxzLnRleHRTaXplKG1lLl9jdHgsIGxpbmVzLCBmb250KSxcbiAgICAgIHRleHRBbGlnbjogcmVzb2x2ZShbY29uZmlnLnRleHRBbGlnbiwgJ3N0YXJ0J10sIGNvbnRleHQsIGluZGV4KSxcbiAgICAgIHRleHRTaGFkb3dCbHVyOiByZXNvbHZlKFtjb25maWcudGV4dFNoYWRvd0JsdXIsIDBdLCBjb250ZXh0LCBpbmRleCksXG4gICAgICB0ZXh0U2hhZG93Q29sb3I6IHJlc29sdmUoW2NvbmZpZy50ZXh0U2hhZG93Q29sb3IsIGNvbG9yXSwgY29udGV4dCwgaW5kZXgpLFxuICAgICAgdGV4dFN0cm9rZUNvbG9yOiByZXNvbHZlKFtjb25maWcudGV4dFN0cm9rZUNvbG9yLCBjb2xvcl0sIGNvbnRleHQsIGluZGV4KSxcbiAgICAgIHRleHRTdHJva2VXaWR0aDogcmVzb2x2ZShbY29uZmlnLnRleHRTdHJva2VXaWR0aCwgMF0sIGNvbnRleHQsIGluZGV4KVxuICAgIH07XG4gIH0sXG5cbiAgdXBkYXRlOiBmdW5jdGlvbihjb250ZXh0KSB7XG4gICAgdmFyIG1lID0gdGhpcztcbiAgICB2YXIgbW9kZWwgPSBudWxsO1xuICAgIHZhciByZWN0cyA9IG51bGw7XG4gICAgdmFyIGluZGV4ID0gbWUuX2luZGV4O1xuICAgIHZhciBjb25maWcgPSBtZS5fY29uZmlnO1xuICAgIHZhciB2YWx1ZSwgbGFiZWwsIGxpbmVzO1xuXG4gICAgLy8gV2UgZmlyc3QgcmVzb2x2ZSB0aGUgZGlzcGxheSBvcHRpb24gKHNlcGFyYXRlbHkpIHRvIGF2b2lkIGNvbXB1dGluZ1xuICAgIC8vIG90aGVyIG9wdGlvbnMgaW4gY2FzZSB0aGUgbGFiZWwgaXMgaGlkZGVuIChpLmUuIGRpc3BsYXk6IGZhbHNlKS5cbiAgICB2YXIgZGlzcGxheSA9IHJlc29sdmUoW2NvbmZpZy5kaXNwbGF5LCB0cnVlXSwgY29udGV4dCwgaW5kZXgpO1xuXG4gICAgaWYgKGRpc3BsYXkpIHtcbiAgICAgIHZhbHVlID0gY29udGV4dC5kYXRhc2V0LmRhdGFbaW5kZXhdO1xuICAgICAgbGFiZWwgPSB2YWx1ZU9yRGVmYXVsdChjYWxsYmFjayhjb25maWcuZm9ybWF0dGVyLCBbdmFsdWUsIGNvbnRleHRdKSwgdmFsdWUpO1xuICAgICAgbGluZXMgPSBpc051bGxPclVuZGVmKGxhYmVsKSA/IFtdIDogdXRpbHMudG9UZXh0TGluZXMobGFiZWwpO1xuXG4gICAgICBpZiAobGluZXMubGVuZ3RoKSB7XG4gICAgICAgIG1vZGVsID0gbWUuX21vZGVsaXplKGRpc3BsYXksIGxpbmVzLCBjb25maWcsIGNvbnRleHQpO1xuICAgICAgICByZWN0cyA9IGJvdW5kaW5nUmVjdHMobW9kZWwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIG1lLl9tb2RlbCA9IG1vZGVsO1xuICAgIG1lLl9yZWN0cyA9IHJlY3RzO1xuICB9LFxuXG4gIGdlb21ldHJ5OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fcmVjdHMgPyB0aGlzLl9yZWN0cy5mcmFtZSA6IHt9O1xuICB9LFxuXG4gIHJvdGF0aW9uOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kZWwgPyB0aGlzLl9tb2RlbC5yb3RhdGlvbiA6IDA7XG4gIH0sXG5cbiAgdmlzaWJsZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vZGVsICYmIHRoaXMuX21vZGVsLm9wYWNpdHk7XG4gIH0sXG5cbiAgbW9kZWw6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl9tb2RlbDtcbiAgfSxcblxuICBkcmF3OiBmdW5jdGlvbihjaGFydCwgY2VudGVyKSB7XG4gICAgdmFyIG1lID0gdGhpcztcbiAgICB2YXIgY3R4ID0gY2hhcnQuY3R4O1xuICAgIHZhciBtb2RlbCA9IG1lLl9tb2RlbDtcbiAgICB2YXIgcmVjdHMgPSBtZS5fcmVjdHM7XG4gICAgdmFyIGFyZWE7XG5cbiAgICBpZiAoIXRoaXMudmlzaWJsZSgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY3R4LnNhdmUoKTtcblxuICAgIGlmIChtb2RlbC5jbGlwKSB7XG4gICAgICBhcmVhID0gbW9kZWwuYXJlYTtcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgIGN0eC5yZWN0KFxuICAgICAgICBhcmVhLmxlZnQsXG4gICAgICAgIGFyZWEudG9wLFxuICAgICAgICBhcmVhLnJpZ2h0IC0gYXJlYS5sZWZ0LFxuICAgICAgICBhcmVhLmJvdHRvbSAtIGFyZWEudG9wKTtcbiAgICAgIGN0eC5jbGlwKCk7XG4gICAgfVxuXG4gICAgY3R4Lmdsb2JhbEFscGhhID0gdXRpbHMuYm91bmQoMCwgbW9kZWwub3BhY2l0eSwgMSk7XG4gICAgY3R4LnRyYW5zbGF0ZShyYXN0ZXJpemUoY2VudGVyLngpLCByYXN0ZXJpemUoY2VudGVyLnkpKTtcbiAgICBjdHgucm90YXRlKG1vZGVsLnJvdGF0aW9uKTtcblxuICAgIGRyYXdGcmFtZShjdHgsIHJlY3RzLmZyYW1lLCBtb2RlbCk7XG4gICAgZHJhd1RleHQoY3R4LCBtb2RlbC5saW5lcywgcmVjdHMudGV4dCwgbW9kZWwpO1xuXG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgfVxufSk7XG5cbnZhciBNSU5fSU5URUdFUiA9IE51bWJlci5NSU5fU0FGRV9JTlRFR0VSIHx8IC05MDA3MTk5MjU0NzQwOTkxOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGVzL25vLW51bWJlci1taW5zYWZlaW50ZWdlclxudmFyIE1BWF9JTlRFR0VSID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIgfHwgOTAwNzE5OTI1NDc0MDk5MTsgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZXMvbm8tbnVtYmVyLW1heHNhZmVpbnRlZ2VyXG5cbmZ1bmN0aW9uIHJvdGF0ZWQocG9pbnQsIGNlbnRlciwgYW5nbGUpIHtcbiAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKTtcbiAgdmFyIHNpbiA9IE1hdGguc2luKGFuZ2xlKTtcbiAgdmFyIGN4ID0gY2VudGVyLng7XG4gIHZhciBjeSA9IGNlbnRlci55O1xuXG4gIHJldHVybiB7XG4gICAgeDogY3ggKyBjb3MgKiAocG9pbnQueCAtIGN4KSAtIHNpbiAqIChwb2ludC55IC0gY3kpLFxuICAgIHk6IGN5ICsgc2luICogKHBvaW50LnggLSBjeCkgKyBjb3MgKiAocG9pbnQueSAtIGN5KVxuICB9O1xufVxuXG5mdW5jdGlvbiBwcm9qZWN0ZWQocG9pbnRzLCBheGlzKSB7XG4gIHZhciBtaW4gPSBNQVhfSU5URUdFUjtcbiAgdmFyIG1heCA9IE1JTl9JTlRFR0VSO1xuICB2YXIgb3JpZ2luID0gYXhpcy5vcmlnaW47XG4gIHZhciBpLCBwdCwgdngsIHZ5LCBkcDtcblxuICBmb3IgKGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgcHQgPSBwb2ludHNbaV07XG4gICAgdnggPSBwdC54IC0gb3JpZ2luLng7XG4gICAgdnkgPSBwdC55IC0gb3JpZ2luLnk7XG4gICAgZHAgPSBheGlzLnZ4ICogdnggKyBheGlzLnZ5ICogdnk7XG4gICAgbWluID0gTWF0aC5taW4obWluLCBkcCk7XG4gICAgbWF4ID0gTWF0aC5tYXgobWF4LCBkcCk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG1pbjogbWluLFxuICAgIG1heDogbWF4XG4gIH07XG59XG5cbmZ1bmN0aW9uIHRvQXhpcyhwMCwgcDEpIHtcbiAgdmFyIHZ4ID0gcDEueCAtIHAwLng7XG4gIHZhciB2eSA9IHAxLnkgLSBwMC55O1xuICB2YXIgbG4gPSBNYXRoLnNxcnQodnggKiB2eCArIHZ5ICogdnkpO1xuXG4gIHJldHVybiB7XG4gICAgdng6IChwMS54IC0gcDAueCkgLyBsbixcbiAgICB2eTogKHAxLnkgLSBwMC55KSAvIGxuLFxuICAgIG9yaWdpbjogcDAsXG4gICAgbG46IGxuXG4gIH07XG59XG5cbnZhciBIaXRCb3ggPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fcm90YXRpb24gPSAwO1xuICB0aGlzLl9yZWN0ID0ge1xuICAgIHg6IDAsXG4gICAgeTogMCxcbiAgICB3OiAwLFxuICAgIGg6IDBcbiAgfTtcbn07XG5cbm1lcmdlKEhpdEJveC5wcm90b3R5cGUsIHtcbiAgY2VudGVyOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgciA9IHRoaXMuX3JlY3Q7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHIueCArIHIudyAvIDIsXG4gICAgICB5OiByLnkgKyByLmggLyAyXG4gICAgfTtcbiAgfSxcblxuICB1cGRhdGU6IGZ1bmN0aW9uKGNlbnRlciwgcmVjdCwgcm90YXRpb24pIHtcbiAgICB0aGlzLl9yb3RhdGlvbiA9IHJvdGF0aW9uO1xuICAgIHRoaXMuX3JlY3QgPSB7XG4gICAgICB4OiByZWN0LnggKyBjZW50ZXIueCxcbiAgICAgIHk6IHJlY3QueSArIGNlbnRlci55LFxuICAgICAgdzogcmVjdC53LFxuICAgICAgaDogcmVjdC5oXG4gICAgfTtcbiAgfSxcblxuICBjb250YWluczogZnVuY3Rpb24ocG9pbnQpIHtcbiAgICB2YXIgbWUgPSB0aGlzO1xuICAgIHZhciBtYXJnaW4gPSAxO1xuICAgIHZhciByZWN0ID0gbWUuX3JlY3Q7XG5cbiAgICBwb2ludCA9IHJvdGF0ZWQocG9pbnQsIG1lLmNlbnRlcigpLCAtbWUuX3JvdGF0aW9uKTtcblxuICAgIHJldHVybiAhKHBvaW50LnggPCByZWN0LnggLSBtYXJnaW5cbiAgICAgIHx8IHBvaW50LnkgPCByZWN0LnkgLSBtYXJnaW5cbiAgICAgIHx8IHBvaW50LnggPiByZWN0LnggKyByZWN0LncgKyBtYXJnaW4gKiAyXG4gICAgICB8fCBwb2ludC55ID4gcmVjdC55ICsgcmVjdC5oICsgbWFyZ2luICogMik7XG4gIH0sXG5cbiAgLy8gU2VwYXJhdGluZyBBeGlzIFRoZW9yZW1cbiAgLy8gaHR0cHM6Ly9nYW1lZGV2ZWxvcG1lbnQudHV0c3BsdXMuY29tL3R1dG9yaWFscy9jb2xsaXNpb24tZGV0ZWN0aW9uLXVzaW5nLXRoZS1zZXBhcmF0aW5nLWF4aXMtdGhlb3JlbS0tZ2FtZWRldi0xNjlcbiAgaW50ZXJzZWN0czogZnVuY3Rpb24ob3RoZXIpIHtcbiAgICB2YXIgcjAgPSB0aGlzLl9wb2ludHMoKTtcbiAgICB2YXIgcjEgPSBvdGhlci5fcG9pbnRzKCk7XG4gICAgdmFyIGF4ZXMgPSBbXG4gICAgICB0b0F4aXMocjBbMF0sIHIwWzFdKSxcbiAgICAgIHRvQXhpcyhyMFswXSwgcjBbM10pXG4gICAgXTtcbiAgICB2YXIgaSwgcHIwLCBwcjE7XG5cbiAgICBpZiAodGhpcy5fcm90YXRpb24gIT09IG90aGVyLl9yb3RhdGlvbikge1xuICAgICAgLy8gT25seSBzZXBhcmF0ZSB3aXRoIHIxIGF4aXMgaWYgdGhlIHJvdGF0aW9uIGlzIGRpZmZlcmVudCxcbiAgICAgIC8vIGVsc2UgaXQncyBlbm91Z2ggdG8gc2VwYXJhdGUgcjAgYW5kIHIxIHdpdGggcjAgYXhpcyBvbmx5IVxuICAgICAgYXhlcy5wdXNoKFxuICAgICAgICB0b0F4aXMocjFbMF0sIHIxWzFdKSxcbiAgICAgICAgdG9BeGlzKHIxWzBdLCByMVszXSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHByMCA9IHByb2plY3RlZChyMCwgYXhlc1tpXSk7XG4gICAgICBwcjEgPSBwcm9qZWN0ZWQocjEsIGF4ZXNbaV0pO1xuXG4gICAgICBpZiAocHIwLm1heCA8IHByMS5taW4gfHwgcHIxLm1heCA8IHByMC5taW4pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3BvaW50czogZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1lID0gdGhpcztcbiAgICB2YXIgcmVjdCA9IG1lLl9yZWN0O1xuICAgIHZhciBhbmdsZSA9IG1lLl9yb3RhdGlvbjtcbiAgICB2YXIgY2VudGVyID0gbWUuY2VudGVyKCk7XG5cbiAgICByZXR1cm4gW1xuICAgICAgcm90YXRlZCh7eDogcmVjdC54LCB5OiByZWN0Lnl9LCBjZW50ZXIsIGFuZ2xlKSxcbiAgICAgIHJvdGF0ZWQoe3g6IHJlY3QueCArIHJlY3QudywgeTogcmVjdC55fSwgY2VudGVyLCBhbmdsZSksXG4gICAgICByb3RhdGVkKHt4OiByZWN0LnggKyByZWN0LncsIHk6IHJlY3QueSArIHJlY3QuaH0sIGNlbnRlciwgYW5nbGUpLFxuICAgICAgcm90YXRlZCh7eDogcmVjdC54LCB5OiByZWN0LnkgKyByZWN0Lmh9LCBjZW50ZXIsIGFuZ2xlKVxuICAgIF07XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiBjb29yZGluYXRlcyhlbCwgbW9kZWwsIGdlb21ldHJ5KSB7XG4gIHZhciBwb2ludCA9IG1vZGVsLnBvc2l0aW9uZXIoZWwsIG1vZGVsKTtcbiAgdmFyIHZ4ID0gcG9pbnQudng7XG4gIHZhciB2eSA9IHBvaW50LnZ5O1xuXG4gIGlmICghdnggJiYgIXZ5KSB7XG4gICAgLy8gaWYgYWxpZ25lZCBjZW50ZXIsIHdlIGRvbid0IHdhbnQgdG8gb2Zmc2V0IHRoZSBjZW50ZXIgcG9pbnRcbiAgICByZXR1cm4ge3g6IHBvaW50LngsIHk6IHBvaW50Lnl9O1xuICB9XG5cbiAgdmFyIHcgPSBnZW9tZXRyeS53O1xuICB2YXIgaCA9IGdlb21ldHJ5Lmg7XG5cbiAgLy8gdGFrZSBpbiBhY2NvdW50IHRoZSBsYWJlbCByb3RhdGlvblxuICB2YXIgcm90YXRpb24gPSBtb2RlbC5yb3RhdGlvbjtcbiAgdmFyIGR4ID0gTWF0aC5hYnModyAvIDIgKiBNYXRoLmNvcyhyb3RhdGlvbikpICsgTWF0aC5hYnMoaCAvIDIgKiBNYXRoLnNpbihyb3RhdGlvbikpO1xuICB2YXIgZHkgPSBNYXRoLmFicyh3IC8gMiAqIE1hdGguc2luKHJvdGF0aW9uKSkgKyBNYXRoLmFicyhoIC8gMiAqIE1hdGguY29zKHJvdGF0aW9uKSk7XG5cbiAgLy8gc2NhbGUgdGhlIHVuaXQgdmVjdG9yICh2eCwgdnkpIHRvIGdldCBhdCBsZWFzdCBkeCBvciBkeSBlcXVhbCB0b1xuICAvLyB3IG9yIGggcmVzcGVjdGl2ZWx5IChlbHNlIHdlIHdvdWxkIGNhbGN1bGF0ZSB0aGUgZGlzdGFuY2UgdG8gdGhlXG4gIC8vIGVsbGlwc2UgaW5zY3JpYmVkIGluIHRoZSBib3VuZGluZyByZWN0KVxuICB2YXIgdnMgPSAxIC8gTWF0aC5tYXgoTWF0aC5hYnModngpLCBNYXRoLmFicyh2eSkpO1xuICBkeCAqPSB2eCAqIHZzO1xuICBkeSAqPSB2eSAqIHZzO1xuXG4gIC8vIGZpbmFsbHksIGluY2x1ZGUgdGhlIGV4cGxpY2l0IG9mZnNldFxuICBkeCArPSBtb2RlbC5vZmZzZXQgKiB2eDtcbiAgZHkgKz0gbW9kZWwub2Zmc2V0ICogdnk7XG5cbiAgcmV0dXJuIHtcbiAgICB4OiBwb2ludC54ICsgZHgsXG4gICAgeTogcG9pbnQueSArIGR5XG4gIH07XG59XG5cbmZ1bmN0aW9uIGNvbGxpZGUobGFiZWxzLCBjb2xsaWRlcikge1xuICB2YXIgaSwgaiwgczAsIHMxO1xuXG4gIC8vIElNUE9SVEFOVCBJdGVyYXRlIGluIHRoZSByZXZlcnNlIG9yZGVyIHNpbmNlIGl0ZW1zIGF0IHRoZSBlbmQgb2YgdGhlXG4gIC8vIGxpc3QgaGF2ZSBhbiBoaWdoZXIgd2VpZ2h0L3ByaW9yaXR5IGFuZCB0aHVzIHNob3VsZCBiZSBsZXNzIGltcGFjdGVkXG4gIC8vIGJ5IHRoZSBvdmVybGFwcGluZyBzdHJhdGVneS5cblxuICBmb3IgKGkgPSBsYWJlbHMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICBzMCA9IGxhYmVsc1tpXS4kbGF5b3V0O1xuXG4gICAgZm9yIChqID0gaSAtIDE7IGogPj0gMCAmJiBzMC5fdmlzaWJsZTsgLS1qKSB7XG4gICAgICBzMSA9IGxhYmVsc1tqXS4kbGF5b3V0O1xuXG4gICAgICBpZiAoczEuX3Zpc2libGUgJiYgczAuX2JveC5pbnRlcnNlY3RzKHMxLl9ib3gpKSB7XG4gICAgICAgIGNvbGxpZGVyKHMwLCBzMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxhYmVscztcbn1cblxuZnVuY3Rpb24gY29tcHV0ZShsYWJlbHMpIHtcbiAgdmFyIGksIGlsZW4sIGxhYmVsLCBzdGF0ZSwgZ2VvbWV0cnksIGNlbnRlciwgcHJveHk7XG5cbiAgLy8gSW5pdGlhbGl6ZSBsYWJlbHMgZm9yIG92ZXJsYXAgZGV0ZWN0aW9uXG4gIGZvciAoaSA9IDAsIGlsZW4gPSBsYWJlbHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgbGFiZWwgPSBsYWJlbHNbaV07XG4gICAgc3RhdGUgPSBsYWJlbC4kbGF5b3V0O1xuXG4gICAgaWYgKHN0YXRlLl92aXNpYmxlKSB7XG4gICAgICAvLyBDaGFydC5qcyAzIHJlbW92ZWQgZWwuX21vZGVsIGluIGZhdm9yIG9mIGdldFByb3BzKCksIG1ha2luZyBoYXJkZXIgdG9cbiAgICAgIC8vIGFic3RyYWN0IHJlYWRpbmcgdmFsdWVzIGluIHBvc2l0aW9uZXJzLiBBbHNvLCB1c2luZyBzdHJpbmcgYXJyYXlzIHRvXG4gICAgICAvLyByZWFkIHZhbHVlcyAoaS5lLiB2YXIge2EsYixjfSA9IGVsLmdldFByb3BzKFtcImFcIixcImJcIixcImNcIl0pKSB3b3VsZCBtYWtlXG4gICAgICAvLyBwb3NpdGlvbmVycyBpbmVmZmljaWVudCBpbiB0aGUgbm9ybWFsIGNhc2UgKGkuZS4gbm90IHRoZSBmaW5hbCB2YWx1ZXMpXG4gICAgICAvLyBhbmQgdGhlIGNvZGUgYSBiaXQgdWdseSwgc28gbGV0J3MgdXNlIGEgUHJveHkgaW5zdGVhZC5cbiAgICAgIHByb3h5ID0gbmV3IFByb3h5KGxhYmVsLl9lbCwge2dldDogKGVsLCBwKSA9PiBlbC5nZXRQcm9wcyhbcF0sIHRydWUpW3BdfSk7XG5cbiAgICAgIGdlb21ldHJ5ID0gbGFiZWwuZ2VvbWV0cnkoKTtcbiAgICAgIGNlbnRlciA9IGNvb3JkaW5hdGVzKHByb3h5LCBsYWJlbC5tb2RlbCgpLCBnZW9tZXRyeSk7XG4gICAgICBzdGF0ZS5fYm94LnVwZGF0ZShjZW50ZXIsIGdlb21ldHJ5LCBsYWJlbC5yb3RhdGlvbigpKTtcbiAgICB9XG4gIH1cblxuICAvLyBBdXRvIGhpZGUgb3ZlcmxhcHBpbmcgbGFiZWxzXG4gIHJldHVybiBjb2xsaWRlKGxhYmVscywgZnVuY3Rpb24oczAsIHMxKSB7XG4gICAgdmFyIGgwID0gczAuX2hpZGFibGU7XG4gICAgdmFyIGgxID0gczEuX2hpZGFibGU7XG5cbiAgICBpZiAoKGgwICYmIGgxKSB8fCBoMSkge1xuICAgICAgczEuX3Zpc2libGUgPSBmYWxzZTtcbiAgICB9IGVsc2UgaWYgKGgwKSB7XG4gICAgICBzMC5fdmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cbiAgfSk7XG59XG5cbnZhciBsYXlvdXQgPSB7XG4gIHByZXBhcmU6IGZ1bmN0aW9uKGRhdGFzZXRzKSB7XG4gICAgdmFyIGxhYmVscyA9IFtdO1xuICAgIHZhciBpLCBqLCBpbGVuLCBqbGVuLCBsYWJlbDtcblxuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBkYXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGZvciAoaiA9IDAsIGpsZW4gPSBkYXRhc2V0c1tpXS5sZW5ndGg7IGogPCBqbGVuOyArK2opIHtcbiAgICAgICAgbGFiZWwgPSBkYXRhc2V0c1tpXVtqXTtcbiAgICAgICAgbGFiZWxzLnB1c2gobGFiZWwpO1xuICAgICAgICBsYWJlbC4kbGF5b3V0ID0ge1xuICAgICAgICAgIF9ib3g6IG5ldyBIaXRCb3goKSxcbiAgICAgICAgICBfaGlkYWJsZTogZmFsc2UsXG4gICAgICAgICAgX3Zpc2libGU6IHRydWUsXG4gICAgICAgICAgX3NldDogaSxcbiAgICAgICAgICBfaWR4OiBsYWJlbC5faW5kZXhcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUT0RPIE5ldyBgemAgb3B0aW9uOiBsYWJlbHMgd2l0aCBhIGhpZ2hlciB6LWluZGV4IGFyZSBkcmF3blxuICAgIC8vIG9mIHRvcCBvZiB0aGUgb25lcyB3aXRoIGEgbG93ZXIgaW5kZXguIExvd2VzdCB6LWluZGV4IGxhYmVsc1xuICAgIC8vIGFyZSBhbHNvIGRpc2NhcmRlZCBmaXJzdCB3aGVuIGhpZGluZyBvdmVybGFwcGluZyBsYWJlbHMuXG4gICAgbGFiZWxzLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgdmFyIHNhID0gYS4kbGF5b3V0O1xuICAgICAgdmFyIHNiID0gYi4kbGF5b3V0O1xuXG4gICAgICByZXR1cm4gc2EuX2lkeCA9PT0gc2IuX2lkeFxuICAgICAgICA/IHNiLl9zZXQgLSBzYS5fc2V0XG4gICAgICAgIDogc2IuX2lkeCAtIHNhLl9pZHg7XG4gICAgfSk7XG5cbiAgICB0aGlzLnVwZGF0ZShsYWJlbHMpO1xuXG4gICAgcmV0dXJuIGxhYmVscztcbiAgfSxcblxuICB1cGRhdGU6IGZ1bmN0aW9uKGxhYmVscykge1xuICAgIHZhciBkaXJ0eSA9IGZhbHNlO1xuICAgIHZhciBpLCBpbGVuLCBsYWJlbCwgbW9kZWwsIHN0YXRlO1xuXG4gICAgZm9yIChpID0gMCwgaWxlbiA9IGxhYmVscy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGxhYmVsID0gbGFiZWxzW2ldO1xuICAgICAgbW9kZWwgPSBsYWJlbC5tb2RlbCgpO1xuICAgICAgc3RhdGUgPSBsYWJlbC4kbGF5b3V0O1xuICAgICAgc3RhdGUuX2hpZGFibGUgPSBtb2RlbCAmJiBtb2RlbC5kaXNwbGF5ID09PSAnYXV0byc7XG4gICAgICBzdGF0ZS5fdmlzaWJsZSA9IGxhYmVsLnZpc2libGUoKTtcbiAgICAgIGRpcnR5IHw9IHN0YXRlLl9oaWRhYmxlO1xuICAgIH1cblxuICAgIGlmIChkaXJ0eSkge1xuICAgICAgY29tcHV0ZShsYWJlbHMpO1xuICAgIH1cbiAgfSxcblxuICBsb29rdXA6IGZ1bmN0aW9uKGxhYmVscywgcG9pbnQpIHtcbiAgICB2YXIgaSwgc3RhdGU7XG5cbiAgICAvLyBJTVBPUlRBTlQgSXRlcmF0ZSBpbiB0aGUgcmV2ZXJzZSBvcmRlciBzaW5jZSBpdGVtcyBhdCB0aGUgZW5kIG9mXG4gICAgLy8gdGhlIGxpc3QgaGF2ZSBhbiBoaWdoZXIgei1pbmRleCwgdGh1cyBzaG91bGQgYmUgcGlja2VkIGZpcnN0LlxuXG4gICAgZm9yIChpID0gbGFiZWxzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICBzdGF0ZSA9IGxhYmVsc1tpXS4kbGF5b3V0O1xuXG4gICAgICBpZiAoc3RhdGUgJiYgc3RhdGUuX3Zpc2libGUgJiYgc3RhdGUuX2JveC5jb250YWlucyhwb2ludCkpIHtcbiAgICAgICAgcmV0dXJuIGxhYmVsc1tpXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBkcmF3OiBmdW5jdGlvbihjaGFydCwgbGFiZWxzKSB7XG4gICAgdmFyIGksIGlsZW4sIGxhYmVsLCBzdGF0ZSwgZ2VvbWV0cnksIGNlbnRlcjtcblxuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBsYWJlbHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgICBsYWJlbCA9IGxhYmVsc1tpXTtcbiAgICAgIHN0YXRlID0gbGFiZWwuJGxheW91dDtcblxuICAgICAgaWYgKHN0YXRlLl92aXNpYmxlKSB7XG4gICAgICAgIGdlb21ldHJ5ID0gbGFiZWwuZ2VvbWV0cnkoKTtcbiAgICAgICAgY2VudGVyID0gY29vcmRpbmF0ZXMobGFiZWwuX2VsLCBsYWJlbC5tb2RlbCgpLCBnZW9tZXRyeSk7XG4gICAgICAgIHN0YXRlLl9ib3gudXBkYXRlKGNlbnRlciwgZ2VvbWV0cnksIGxhYmVsLnJvdGF0aW9uKCkpO1xuICAgICAgICBsYWJlbC5kcmF3KGNoYXJ0LCBjZW50ZXIpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxudmFyIGZvcm1hdHRlciA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIGlmIChpc051bGxPclVuZGVmKHZhbHVlKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIGxhYmVsID0gdmFsdWU7XG4gIHZhciBrZXlzLCBrbGVuLCBrO1xuICBpZiAoaXNPYmplY3QodmFsdWUpKSB7XG4gICAgaWYgKCFpc051bGxPclVuZGVmKHZhbHVlLmxhYmVsKSkge1xuICAgICAgbGFiZWwgPSB2YWx1ZS5sYWJlbDtcbiAgICB9IGVsc2UgaWYgKCFpc051bGxPclVuZGVmKHZhbHVlLnIpKSB7XG4gICAgICBsYWJlbCA9IHZhbHVlLnI7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxhYmVsID0gJyc7XG4gICAgICBrZXlzID0gT2JqZWN0LmtleXModmFsdWUpO1xuICAgICAgZm9yIChrID0gMCwga2xlbiA9IGtleXMubGVuZ3RoOyBrIDwga2xlbjsgKytrKSB7XG4gICAgICAgIGxhYmVsICs9IChrICE9PSAwID8gJywgJyA6ICcnKSArIGtleXNba10gKyAnOiAnICsgdmFsdWVba2V5c1trXV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuICcnICsgbGFiZWw7XG59O1xuXG4vKipcbiAqIElNUE9SVEFOVDogbWFrZSBzdXJlIHRvIGFsc28gdXBkYXRlIHRlc3RzIGFuZCBUeXBlU2NyaXB0IGRlZmluaXRpb25cbiAqIGZpbGVzIChgL3Rlc3Qvc3BlY3MvZGVmYXVsdHMuc3BlYy5qc2AgYW5kIGAvdHlwZXMvb3B0aW9ucy5kLnRzYClcbiAqL1xuXG52YXIgZGVmYXVsdHMgPSB7XG4gIGFsaWduOiAnY2VudGVyJyxcbiAgYW5jaG9yOiAnY2VudGVyJyxcbiAgYmFja2dyb3VuZENvbG9yOiBudWxsLFxuICBib3JkZXJDb2xvcjogbnVsbCxcbiAgYm9yZGVyUmFkaXVzOiAwLFxuICBib3JkZXJXaWR0aDogMCxcbiAgY2xhbXA6IGZhbHNlLFxuICBjbGlwOiBmYWxzZSxcbiAgY29sb3I6IHVuZGVmaW5lZCxcbiAgZGlzcGxheTogdHJ1ZSxcbiAgZm9udDoge1xuICAgIGZhbWlseTogdW5kZWZpbmVkLFxuICAgIGxpbmVIZWlnaHQ6IDEuMixcbiAgICBzaXplOiB1bmRlZmluZWQsXG4gICAgc3R5bGU6IHVuZGVmaW5lZCxcbiAgICB3ZWlnaHQ6IG51bGxcbiAgfSxcbiAgZm9ybWF0dGVyOiBmb3JtYXR0ZXIsXG4gIGxhYmVsczogdW5kZWZpbmVkLFxuICBsaXN0ZW5lcnM6IHt9LFxuICBvZmZzZXQ6IDQsXG4gIG9wYWNpdHk6IDEsXG4gIHBhZGRpbmc6IHtcbiAgICB0b3A6IDQsXG4gICAgcmlnaHQ6IDQsXG4gICAgYm90dG9tOiA0LFxuICAgIGxlZnQ6IDRcbiAgfSxcbiAgcm90YXRpb246IDAsXG4gIHRleHRBbGlnbjogJ3N0YXJ0JyxcbiAgdGV4dFN0cm9rZUNvbG9yOiB1bmRlZmluZWQsXG4gIHRleHRTdHJva2VXaWR0aDogMCxcbiAgdGV4dFNoYWRvd0JsdXI6IDAsXG4gIHRleHRTaGFkb3dDb2xvcjogdW5kZWZpbmVkXG59O1xuXG4vKipcbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2NoYXJ0anMvQ2hhcnQuanMvaXNzdWVzLzQxNzZcbiAqL1xuXG52YXIgRVhQQU5ET19LRVkgPSAnJGRhdGFsYWJlbHMnO1xudmFyIERFRkFVTFRfS0VZID0gJyRkZWZhdWx0JztcblxuZnVuY3Rpb24gY29uZmlndXJlKGRhdGFzZXQsIG9wdGlvbnMpIHtcbiAgdmFyIG92ZXJyaWRlID0gZGF0YXNldC5kYXRhbGFiZWxzO1xuICB2YXIgbGlzdGVuZXJzID0ge307XG4gIHZhciBjb25maWdzID0gW107XG4gIHZhciBsYWJlbHMsIGtleXM7XG5cbiAgaWYgKG92ZXJyaWRlID09PSBmYWxzZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGlmIChvdmVycmlkZSA9PT0gdHJ1ZSkge1xuICAgIG92ZXJyaWRlID0ge307XG4gIH1cblxuICBvcHRpb25zID0gbWVyZ2Uoe30sIFtvcHRpb25zLCBvdmVycmlkZV0pO1xuICBsYWJlbHMgPSBvcHRpb25zLmxhYmVscyB8fCB7fTtcbiAga2V5cyA9IE9iamVjdC5rZXlzKGxhYmVscyk7XG4gIGRlbGV0ZSBvcHRpb25zLmxhYmVscztcblxuICBpZiAoa2V5cy5sZW5ndGgpIHtcbiAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgICBpZiAobGFiZWxzW2tleV0pIHtcbiAgICAgICAgY29uZmlncy5wdXNoKG1lcmdlKHt9LCBbXG4gICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICBsYWJlbHNba2V5XSxcbiAgICAgICAgICB7X2tleToga2V5fVxuICAgICAgICBdKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gRGVmYXVsdCBsYWJlbCBpZiBubyBcIm5hbWVkXCIgbGFiZWwgZGVmaW5lZC5cbiAgICBjb25maWdzLnB1c2gob3B0aW9ucyk7XG4gIH1cblxuICAvLyBsaXN0ZW5lcnM6IHs8ZXZlbnQtdHlwZT46IHs8bGFiZWwta2V5PjogPGZuPn19XG4gIGxpc3RlbmVycyA9IGNvbmZpZ3MucmVkdWNlKGZ1bmN0aW9uKHRhcmdldCwgY29uZmlnKSB7XG4gICAgZWFjaChjb25maWcubGlzdGVuZXJzIHx8IHt9LCBmdW5jdGlvbihmbiwgZXZlbnQpIHtcbiAgICAgIHRhcmdldFtldmVudF0gPSB0YXJnZXRbZXZlbnRdIHx8IHt9O1xuICAgICAgdGFyZ2V0W2V2ZW50XVtjb25maWcuX2tleSB8fCBERUZBVUxUX0tFWV0gPSBmbjtcbiAgICB9KTtcblxuICAgIGRlbGV0ZSBjb25maWcubGlzdGVuZXJzO1xuICAgIHJldHVybiB0YXJnZXQ7XG4gIH0sIHt9KTtcblxuICByZXR1cm4ge1xuICAgIGxhYmVsczogY29uZmlncyxcbiAgICBsaXN0ZW5lcnM6IGxpc3RlbmVyc1xuICB9O1xufVxuXG5mdW5jdGlvbiBkaXNwYXRjaEV2ZW50KGNoYXJ0LCBsaXN0ZW5lcnMsIGxhYmVsLCBldmVudCkge1xuICBpZiAoIWxpc3RlbmVycykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBjb250ZXh0ID0gbGFiZWwuJGNvbnRleHQ7XG4gIHZhciBncm91cHMgPSBsYWJlbC4kZ3JvdXBzO1xuICB2YXIgY2FsbGJhY2skMTtcblxuICBpZiAoIWxpc3RlbmVyc1tncm91cHMuX3NldF0pIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjYWxsYmFjayQxID0gbGlzdGVuZXJzW2dyb3Vwcy5fc2V0XVtncm91cHMuX2tleV07XG4gIGlmICghY2FsbGJhY2skMSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChjYWxsYmFjayhjYWxsYmFjayQxLCBbY29udGV4dCwgZXZlbnRdKSA9PT0gdHJ1ZSkge1xuICAgIC8vIFVzZXJzIGFyZSBhbGxvd2VkIHRvIHR3ZWFrIHRoZSBnaXZlbiBjb250ZXh0IGJ5IGluamVjdGluZyB2YWx1ZXMgdGhhdCBjYW4gYmVcbiAgICAvLyB1c2VkIGluIHNjcmlwdGFibGUgb3B0aW9ucyB0byBkaXNwbGF5IGxhYmVscyBkaWZmZXJlbnRseSBiYXNlZCBvbiB0aGUgY3VycmVudFxuICAgIC8vIGV2ZW50IChlLmcuIGhpZ2hsaWdodCBhbiBob3ZlcmVkIGxhYmVsKS4gVGhhdCdzIHdoeSB3ZSB1cGRhdGUgdGhlIGxhYmVsIHdpdGhcbiAgICAvLyB0aGUgb3V0cHV0IGNvbnRleHQgYW5kIHNjaGVkdWxlIGEgbmV3IGNoYXJ0IHJlbmRlciBieSBzZXR0aW5nIGl0IGRpcnR5LlxuICAgIGNoYXJ0W0VYUEFORE9fS0VZXS5fZGlydHkgPSB0cnVlO1xuICAgIGxhYmVsLnVwZGF0ZShjb250ZXh0KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBkaXNwYXRjaE1vdmVFdmVudHMoY2hhcnQsIGxpc3RlbmVycywgcHJldmlvdXMsIGxhYmVsLCBldmVudCkge1xuICB2YXIgZW50ZXIsIGxlYXZlO1xuXG4gIGlmICghcHJldmlvdXMgJiYgIWxhYmVsKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFwcmV2aW91cykge1xuICAgIGVudGVyID0gdHJ1ZTtcbiAgfSBlbHNlIGlmICghbGFiZWwpIHtcbiAgICBsZWF2ZSA9IHRydWU7XG4gIH0gZWxzZSBpZiAocHJldmlvdXMgIT09IGxhYmVsKSB7XG4gICAgbGVhdmUgPSBlbnRlciA9IHRydWU7XG4gIH1cblxuICBpZiAobGVhdmUpIHtcbiAgICBkaXNwYXRjaEV2ZW50KGNoYXJ0LCBsaXN0ZW5lcnMubGVhdmUsIHByZXZpb3VzLCBldmVudCk7XG4gIH1cbiAgaWYgKGVudGVyKSB7XG4gICAgZGlzcGF0Y2hFdmVudChjaGFydCwgbGlzdGVuZXJzLmVudGVyLCBsYWJlbCwgZXZlbnQpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU1vdmVFdmVudHMoY2hhcnQsIGV2ZW50KSB7XG4gIHZhciBleHBhbmRvID0gY2hhcnRbRVhQQU5ET19LRVldO1xuICB2YXIgbGlzdGVuZXJzID0gZXhwYW5kby5fbGlzdGVuZXJzO1xuICB2YXIgcHJldmlvdXMsIGxhYmVsO1xuXG4gIGlmICghbGlzdGVuZXJzLmVudGVyICYmICFsaXN0ZW5lcnMubGVhdmUpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoZXZlbnQudHlwZSA9PT0gJ21vdXNlbW92ZScpIHtcbiAgICBsYWJlbCA9IGxheW91dC5sb29rdXAoZXhwYW5kby5fbGFiZWxzLCBldmVudCk7XG4gIH0gZWxzZSBpZiAoZXZlbnQudHlwZSAhPT0gJ21vdXNlb3V0Jykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHByZXZpb3VzID0gZXhwYW5kby5faG92ZXJlZDtcbiAgZXhwYW5kby5faG92ZXJlZCA9IGxhYmVsO1xuICBkaXNwYXRjaE1vdmVFdmVudHMoY2hhcnQsIGxpc3RlbmVycywgcHJldmlvdXMsIGxhYmVsLCBldmVudCk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUNsaWNrRXZlbnRzKGNoYXJ0LCBldmVudCkge1xuICB2YXIgZXhwYW5kbyA9IGNoYXJ0W0VYUEFORE9fS0VZXTtcbiAgdmFyIGhhbmRsZXJzID0gZXhwYW5kby5fbGlzdGVuZXJzLmNsaWNrO1xuICB2YXIgbGFiZWwgPSBoYW5kbGVycyAmJiBsYXlvdXQubG9va3VwKGV4cGFuZG8uX2xhYmVscywgZXZlbnQpO1xuICBpZiAobGFiZWwpIHtcbiAgICBkaXNwYXRjaEV2ZW50KGNoYXJ0LCBoYW5kbGVycywgbGFiZWwsIGV2ZW50KTtcbiAgfVxufVxuXG52YXIgcGx1Z2luID0ge1xuICBpZDogJ2RhdGFsYWJlbHMnLFxuXG4gIGRlZmF1bHRzOiBkZWZhdWx0cyxcblxuICBiZWZvcmVJbml0OiBmdW5jdGlvbihjaGFydCkge1xuICAgIGNoYXJ0W0VYUEFORE9fS0VZXSA9IHtcbiAgICAgIF9hY3RpdmVzOiBbXVxuICAgIH07XG4gIH0sXG5cbiAgYmVmb3JlVXBkYXRlOiBmdW5jdGlvbihjaGFydCkge1xuICAgIHZhciBleHBhbmRvID0gY2hhcnRbRVhQQU5ET19LRVldO1xuICAgIGV4cGFuZG8uX2xpc3RlbmVkID0gZmFsc2U7XG4gICAgZXhwYW5kby5fbGlzdGVuZXJzID0ge307ICAgICAvLyB7PGV2ZW50LXR5cGU+OiB7PGRhdGFzZXQtaW5kZXg+OiB7PGxhYmVsLWtleT46IDxmbj59fX1cbiAgICBleHBhbmRvLl9kYXRhc2V0cyA9IFtdOyAgICAgIC8vIHBlciBkYXRhc2V0IGxhYmVsczogW0xhYmVsW11dXG4gICAgZXhwYW5kby5fbGFiZWxzID0gW107ICAgICAgICAvLyBsYXlvdXRlZCBsYWJlbHM6IExhYmVsW11cbiAgfSxcblxuICBhZnRlckRhdGFzZXRVcGRhdGU6IGZ1bmN0aW9uKGNoYXJ0LCBhcmdzLCBvcHRpb25zKSB7XG4gICAgdmFyIGRhdGFzZXRJbmRleCA9IGFyZ3MuaW5kZXg7XG4gICAgdmFyIGV4cGFuZG8gPSBjaGFydFtFWFBBTkRPX0tFWV07XG4gICAgdmFyIGxhYmVscyA9IGV4cGFuZG8uX2RhdGFzZXRzW2RhdGFzZXRJbmRleF0gPSBbXTtcbiAgICB2YXIgdmlzaWJsZSA9IGNoYXJ0LmlzRGF0YXNldFZpc2libGUoZGF0YXNldEluZGV4KTtcbiAgICB2YXIgZGF0YXNldCA9IGNoYXJ0LmRhdGEuZGF0YXNldHNbZGF0YXNldEluZGV4XTtcbiAgICB2YXIgY29uZmlnID0gY29uZmlndXJlKGRhdGFzZXQsIG9wdGlvbnMpO1xuICAgIHZhciBlbGVtZW50cyA9IGFyZ3MubWV0YS5kYXRhIHx8IFtdO1xuICAgIHZhciBjdHggPSBjaGFydC5jdHg7XG4gICAgdmFyIGksIGosIGlsZW4sIGpsZW4sIGNmZywga2V5LCBlbCwgbGFiZWw7XG5cbiAgICBjdHguc2F2ZSgpO1xuXG4gICAgZm9yIChpID0gMCwgaWxlbiA9IGVsZW1lbnRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgZWwgPSBlbGVtZW50c1tpXTtcbiAgICAgIGVsW0VYUEFORE9fS0VZXSA9IFtdO1xuXG4gICAgICBpZiAodmlzaWJsZSAmJiBlbCAmJiBjaGFydC5nZXREYXRhVmlzaWJpbGl0eShpKSAmJiAhZWwuc2tpcCkge1xuICAgICAgICBmb3IgKGogPSAwLCBqbGVuID0gY29uZmlnLmxhYmVscy5sZW5ndGg7IGogPCBqbGVuOyArK2opIHtcbiAgICAgICAgICBjZmcgPSBjb25maWcubGFiZWxzW2pdO1xuICAgICAgICAgIGtleSA9IGNmZy5fa2V5O1xuXG4gICAgICAgICAgbGFiZWwgPSBuZXcgTGFiZWwoY2ZnLCBjdHgsIGVsLCBpKTtcbiAgICAgICAgICBsYWJlbC4kZ3JvdXBzID0ge1xuICAgICAgICAgICAgX3NldDogZGF0YXNldEluZGV4LFxuICAgICAgICAgICAgX2tleToga2V5IHx8IERFRkFVTFRfS0VZXG4gICAgICAgICAgfTtcbiAgICAgICAgICBsYWJlbC4kY29udGV4dCA9IHtcbiAgICAgICAgICAgIGFjdGl2ZTogZmFsc2UsXG4gICAgICAgICAgICBjaGFydDogY2hhcnQsXG4gICAgICAgICAgICBkYXRhSW5kZXg6IGksXG4gICAgICAgICAgICBkYXRhc2V0OiBkYXRhc2V0LFxuICAgICAgICAgICAgZGF0YXNldEluZGV4OiBkYXRhc2V0SW5kZXhcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgbGFiZWwudXBkYXRlKGxhYmVsLiRjb250ZXh0KTtcbiAgICAgICAgICBlbFtFWFBBTkRPX0tFWV0ucHVzaChsYWJlbCk7XG4gICAgICAgICAgbGFiZWxzLnB1c2gobGFiZWwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY3R4LnJlc3RvcmUoKTtcblxuICAgIC8vIFN0b3JlIGxpc3RlbmVycyBhdCB0aGUgY2hhcnQgbGV2ZWwgYW5kIHBlciBldmVudCB0eXBlIHRvIG9wdGltaXplXG4gICAgLy8gY2FzZXMgd2hlcmUgbm8gbGlzdGVuZXJzIGFyZSByZWdpc3RlcmVkIGZvciBhIHNwZWNpZmljIGV2ZW50LlxuICAgIG1lcmdlKGV4cGFuZG8uX2xpc3RlbmVycywgY29uZmlnLmxpc3RlbmVycywge1xuICAgICAgbWVyZ2VyOiBmdW5jdGlvbihldmVudCwgdGFyZ2V0LCBzb3VyY2UpIHtcbiAgICAgICAgdGFyZ2V0W2V2ZW50XSA9IHRhcmdldFtldmVudF0gfHwge307XG4gICAgICAgIHRhcmdldFtldmVudF1bYXJncy5pbmRleF0gPSBzb3VyY2VbZXZlbnRdO1xuICAgICAgICBleHBhbmRvLl9saXN0ZW5lZCA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gIH0sXG5cbiAgYWZ0ZXJVcGRhdGU6IGZ1bmN0aW9uKGNoYXJ0KSB7XG4gICAgY2hhcnRbRVhQQU5ET19LRVldLl9sYWJlbHMgPSBsYXlvdXQucHJlcGFyZShjaGFydFtFWFBBTkRPX0tFWV0uX2RhdGFzZXRzKTtcbiAgfSxcblxuICAvLyBEcmF3IGxhYmVscyBvbiB0b3Agb2YgYWxsIGRhdGFzZXQgZWxlbWVudHNcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2NoYXJ0anMvY2hhcnRqcy1wbHVnaW4tZGF0YWxhYmVscy9pc3N1ZXMvMjlcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2NoYXJ0anMvY2hhcnRqcy1wbHVnaW4tZGF0YWxhYmVscy9pc3N1ZXMvMzJcbiAgYWZ0ZXJEYXRhc2V0c0RyYXc6IGZ1bmN0aW9uKGNoYXJ0KSB7XG4gICAgbGF5b3V0LmRyYXcoY2hhcnQsIGNoYXJ0W0VYUEFORE9fS0VZXS5fbGFiZWxzKTtcbiAgfSxcblxuICBiZWZvcmVFdmVudDogZnVuY3Rpb24oY2hhcnQsIGFyZ3MpIHtcbiAgICAvLyBJZiB0aGVyZSBpcyBubyBsaXN0ZW5lciByZWdpc3RlcmVkIGZvciB0aGlzIGNoYXJ0LCBgbGlzdGVuZWRgIHdpbGwgYmUgZmFsc2UsXG4gICAgLy8gbWVhbmluZyB3ZSBjYW4gaW1tZWRpYXRlbHkgaWdub3JlIHRoZSBpbmNvbWluZyBldmVudCBhbmQgYXZvaWQgdXNlbGVzcyBleHRyYVxuICAgIC8vIGNvbXB1dGF0aW9uIGZvciB1c2VycyB3aG8gZG9uJ3QgaW1wbGVtZW50IGxhYmVsIGludGVyYWN0aW9ucy5cbiAgICBpZiAoY2hhcnRbRVhQQU5ET19LRVldLl9saXN0ZW5lZCkge1xuICAgICAgdmFyIGV2ZW50ID0gYXJncy5ldmVudDtcbiAgICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xuICAgICAgY2FzZSAnbW91c2Vtb3ZlJzpcbiAgICAgIGNhc2UgJ21vdXNlb3V0JzpcbiAgICAgICAgaGFuZGxlTW92ZUV2ZW50cyhjaGFydCwgZXZlbnQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NsaWNrJzpcbiAgICAgICAgaGFuZGxlQ2xpY2tFdmVudHMoY2hhcnQsIGV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIGFmdGVyRXZlbnQ6IGZ1bmN0aW9uKGNoYXJ0KSB7XG4gICAgdmFyIGV4cGFuZG8gPSBjaGFydFtFWFBBTkRPX0tFWV07XG4gICAgdmFyIHByZXZpb3VzID0gZXhwYW5kby5fYWN0aXZlcztcbiAgICB2YXIgYWN0aXZlcyA9IGV4cGFuZG8uX2FjdGl2ZXMgPSBjaGFydC5nZXRBY3RpdmVFbGVtZW50cygpO1xuICAgIHZhciB1cGRhdGVzID0gdXRpbHMuYXJyYXlEaWZmKHByZXZpb3VzLCBhY3RpdmVzKTtcbiAgICB2YXIgaSwgaWxlbiwgaiwgamxlbiwgdXBkYXRlLCBsYWJlbCwgbGFiZWxzO1xuXG4gICAgZm9yIChpID0gMCwgaWxlbiA9IHVwZGF0ZXMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgICB1cGRhdGUgPSB1cGRhdGVzW2ldO1xuICAgICAgaWYgKHVwZGF0ZVsxXSkge1xuICAgICAgICBsYWJlbHMgPSB1cGRhdGVbMF0uZWxlbWVudFtFWFBBTkRPX0tFWV0gfHwgW107XG4gICAgICAgIGZvciAoaiA9IDAsIGpsZW4gPSBsYWJlbHMubGVuZ3RoOyBqIDwgamxlbjsgKytqKSB7XG4gICAgICAgICAgbGFiZWwgPSBsYWJlbHNbal07XG4gICAgICAgICAgbGFiZWwuJGNvbnRleHQuYWN0aXZlID0gKHVwZGF0ZVsxXSA9PT0gMSk7XG4gICAgICAgICAgbGFiZWwudXBkYXRlKGxhYmVsLiRjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChleHBhbmRvLl9kaXJ0eSB8fCB1cGRhdGVzLmxlbmd0aCkge1xuICAgICAgbGF5b3V0LnVwZGF0ZShleHBhbmRvLl9sYWJlbHMpO1xuICAgICAgY2hhcnQucmVuZGVyKCk7XG4gICAgfVxuXG4gICAgZGVsZXRlIGV4cGFuZG8uX2RpcnR5O1xuICB9XG59O1xuXG5leHBvcnQgeyBwbHVnaW4gYXMgZGVmYXVsdCB9O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/chartjs-plugin-datalabels/dist/chartjs-plugin-datalabels.esm.js\n"); /***/ }), /***/ "./node_modules/datatables.net-bs4/js/dataTables.bootstrap4.mjs": /*!**********************************************************************!*\ !*** ./node_modules/datatables.net-bs4/js/dataTables.bootstrap4.mjs ***! \**********************************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\");\n/* harmony import */ var datatables_net__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! datatables.net */ \"./node_modules/datatables.net/js/jquery.dataTables.mjs\");\n/*! DataTables Bootstrap 4 integration\n * ©2011-2017 SpryMedia Ltd - datatables.net/license\n */\n\n\n\n\n// Allow reassignment of the $ variable\nlet $ = jquery__WEBPACK_IMPORTED_MODULE_0__;\n\n\n/**\n * DataTables integration for Bootstrap 4. This requires Bootstrap 4 and\n * DataTables 1.10 or newer.\n *\n * This file sets the defaults and adds options to DataTables to style its\n * controls using Bootstrap. See https://datatables.net/manual/styling/bootstrap\n * for further information.\n */\n\n/* Set the defaults for DataTables initialisation */\n$.extend( true, datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].defaults, {\n\tdom:\n\t\t\"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>\" +\n\t\t\"<'row'<'col-sm-12'tr>>\" +\n\t\t\"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>\",\n\trenderer: 'bootstrap'\n} );\n\n\n/* Default class modification */\n$.extend( datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].ext.classes, {\n\tsWrapper: \"dataTables_wrapper dt-bootstrap4\",\n\tsFilterInput: \"form-control form-control-sm\",\n\tsLengthSelect: \"custom-select custom-select-sm form-control form-control-sm\",\n\tsProcessing: \"dataTables_processing card\",\n\tsPageButton: \"paginate_button page-item\"\n} );\n\n\n/* Bootstrap paging button renderer */\ndatatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {\n\tvar api = new datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Api( settings );\n\tvar classes = settings.oClasses;\n\tvar lang = settings.oLanguage.oPaginate;\n\tvar aria = settings.oLanguage.oAria.paginate || {};\n\tvar btnDisplay, btnClass;\n\n\tvar attach = function( container, buttons ) {\n\t\tvar i, ien, node, button;\n\t\tvar clickHandler = function ( e ) {\n\t\t\te.preventDefault();\n\t\t\tif ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {\n\t\t\t\tapi.page( e.data.action ).draw( 'page' );\n\t\t\t}\n\t\t};\n\n\t\tfor ( i=0, ien=buttons.length ; i 0 ?\n\t\t\t\t\t\t\t'' : ' disabled');\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'previous':\n\t\t\t\t\t\tbtnDisplay = lang.sPrevious;\n\t\t\t\t\t\tbtnClass = button + (page > 0 ?\n\t\t\t\t\t\t\t'' : ' disabled');\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'next':\n\t\t\t\t\t\tbtnDisplay = lang.sNext;\n\t\t\t\t\t\tbtnClass = button + (page < pages-1 ?\n\t\t\t\t\t\t\t'' : ' disabled');\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'last':\n\t\t\t\t\t\tbtnDisplay = lang.sLast;\n\t\t\t\t\t\tbtnClass = button + (page < pages-1 ?\n\t\t\t\t\t\t\t'' : ' disabled');\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbtnDisplay = button + 1;\n\t\t\t\t\t\tbtnClass = page === button ?\n\t\t\t\t\t\t\t'active' : '';\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( btnDisplay ) {\n\t\t\t\t\tvar disabled = btnClass.indexOf('disabled') !== -1;\n\n\t\t\t\t\tnode = $('
  • ', {\n\t\t\t\t\t\t\t'class': classes.sPageButton+' '+btnClass,\n\t\t\t\t\t\t\t'id': idx === 0 && typeof button === 'string' ?\n\t\t\t\t\t\t\t\tsettings.sTableId +'_'+ button :\n\t\t\t\t\t\t\t\tnull\n\t\t\t\t\t\t} )\n\t\t\t\t\t\t.append( $('', {\n\t\t\t\t\t\t\t\t'href': disabled ? null : '#',\n\t\t\t\t\t\t\t\t'aria-controls': settings.sTableId,\n\t\t\t\t\t\t\t\t'aria-disabled': disabled ? 'true' : null,\n\t\t\t\t\t\t\t\t'aria-label': aria[ button ],\n\t\t\t\t\t\t\t\t'role': 'link',\n\t\t\t\t\t\t\t\t'aria-current': btnClass === 'active' ? 'page' : null,\n\t\t\t\t\t\t\t\t'data-dt-idx': button,\n\t\t\t\t\t\t\t\t'tabindex': disabled ? -1 : settings.iTabIndex,\n\t\t\t\t\t\t\t\t'class': 'page-link'\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t.html( btnDisplay )\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.appendTo( container );\n\n\t\t\t\t\tsettings.oApi._fnBindAction(\n\t\t\t\t\t\tnode, {action: button}, clickHandler\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t// IE9 throws an 'unknown error' if document.activeElement is used\n\t// inside an iframe or frame. \n\tvar activeEl;\n\n\ttry {\n\t\t// Because this approach is destroying and recreating the paging\n\t\t// elements, focus is lost on the select button which is bad for\n\t\t// accessibility. So we want to restore focus once the draw has\n\t\t// completed\n\t\tactiveEl = $(host).find(document.activeElement).data('dt-idx');\n\t}\n\tcatch (e) {}\n\n\tattach(\n\t\t$(host).empty().html('
      ').children('ul'),\n\t\tbuttons\n\t);\n\n\tif ( activeEl !== undefined ) {\n\t\t$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');\n\t}\n};\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtYnM0L2pzL2RhdGFUYWJsZXMuYm9vdHN0cmFwNC5tanMiLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7QUFDQTtBQUNBOztBQUU0QjtBQUNXOztBQUV2QztBQUNBLFFBQVEsbUNBQU07OztBQUdkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnQkFBZ0Isc0RBQVM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0EsVUFBVSxzREFBUztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQSxzREFBUztBQUNULG1CQUFtQixzREFBUztBQUM1QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtDQUFrQyxRQUFRO0FBQzFDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWEsZUFBZTtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxpRUFBZSxzREFBUyxFQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2RhdGF0YWJsZXMubmV0LWJzNC9qcy9kYXRhVGFibGVzLmJvb3RzdHJhcDQubWpzPzVkN2IiXSwic291cmNlc0NvbnRlbnQiOlsiLyohIERhdGFUYWJsZXMgQm9vdHN0cmFwIDQgaW50ZWdyYXRpb25cbiAqIMKpMjAxMS0yMDE3IFNwcnlNZWRpYSBMdGQgLSBkYXRhdGFibGVzLm5ldC9saWNlbnNlXG4gKi9cblxuaW1wb3J0IGpRdWVyeSBmcm9tICdqcXVlcnknO1xuaW1wb3J0IERhdGFUYWJsZSBmcm9tICdkYXRhdGFibGVzLm5ldCc7XG5cbi8vIEFsbG93IHJlYXNzaWdubWVudCBvZiB0aGUgJCB2YXJpYWJsZVxubGV0ICQgPSBqUXVlcnk7XG5cblxuLyoqXG4gKiBEYXRhVGFibGVzIGludGVncmF0aW9uIGZvciBCb290c3RyYXAgNC4gVGhpcyByZXF1aXJlcyBCb290c3RyYXAgNCBhbmRcbiAqIERhdGFUYWJsZXMgMS4xMCBvciBuZXdlci5cbiAqXG4gKiBUaGlzIGZpbGUgc2V0cyB0aGUgZGVmYXVsdHMgYW5kIGFkZHMgb3B0aW9ucyB0byBEYXRhVGFibGVzIHRvIHN0eWxlIGl0c1xuICogY29udHJvbHMgdXNpbmcgQm9vdHN0cmFwLiBTZWUgaHR0cHM6Ly9kYXRhdGFibGVzLm5ldC9tYW51YWwvc3R5bGluZy9ib290c3RyYXBcbiAqIGZvciBmdXJ0aGVyIGluZm9ybWF0aW9uLlxuICovXG5cbi8qIFNldCB0aGUgZGVmYXVsdHMgZm9yIERhdGFUYWJsZXMgaW5pdGlhbGlzYXRpb24gKi9cbiQuZXh0ZW5kKCB0cnVlLCBEYXRhVGFibGUuZGVmYXVsdHMsIHtcblx0ZG9tOlxuXHRcdFwiPCdyb3cnPCdjb2wtc20tMTIgY29sLW1kLTYnbD48J2NvbC1zbS0xMiBjb2wtbWQtNidmPj5cIiArXG5cdFx0XCI8J3Jvdyc8J2NvbC1zbS0xMid0cj4+XCIgK1xuXHRcdFwiPCdyb3cnPCdjb2wtc20tMTIgY29sLW1kLTUnaT48J2NvbC1zbS0xMiBjb2wtbWQtNydwPj5cIixcblx0cmVuZGVyZXI6ICdib290c3RyYXAnXG59ICk7XG5cblxuLyogRGVmYXVsdCBjbGFzcyBtb2RpZmljYXRpb24gKi9cbiQuZXh0ZW5kKCBEYXRhVGFibGUuZXh0LmNsYXNzZXMsIHtcblx0c1dyYXBwZXI6ICAgICAgXCJkYXRhVGFibGVzX3dyYXBwZXIgZHQtYm9vdHN0cmFwNFwiLFxuXHRzRmlsdGVySW5wdXQ6ICBcImZvcm0tY29udHJvbCBmb3JtLWNvbnRyb2wtc21cIixcblx0c0xlbmd0aFNlbGVjdDogXCJjdXN0b20tc2VsZWN0IGN1c3RvbS1zZWxlY3Qtc20gZm9ybS1jb250cm9sIGZvcm0tY29udHJvbC1zbVwiLFxuXHRzUHJvY2Vzc2luZzogICBcImRhdGFUYWJsZXNfcHJvY2Vzc2luZyBjYXJkXCIsXG5cdHNQYWdlQnV0dG9uOiAgIFwicGFnaW5hdGVfYnV0dG9uIHBhZ2UtaXRlbVwiXG59ICk7XG5cblxuLyogQm9vdHN0cmFwIHBhZ2luZyBidXR0b24gcmVuZGVyZXIgKi9cbkRhdGFUYWJsZS5leHQucmVuZGVyZXIucGFnZUJ1dHRvbi5ib290c3RyYXAgPSBmdW5jdGlvbiAoIHNldHRpbmdzLCBob3N0LCBpZHgsIGJ1dHRvbnMsIHBhZ2UsIHBhZ2VzICkge1xuXHR2YXIgYXBpICAgICA9IG5ldyBEYXRhVGFibGUuQXBpKCBzZXR0aW5ncyApO1xuXHR2YXIgY2xhc3NlcyA9IHNldHRpbmdzLm9DbGFzc2VzO1xuXHR2YXIgbGFuZyAgICA9IHNldHRpbmdzLm9MYW5ndWFnZS5vUGFnaW5hdGU7XG5cdHZhciBhcmlhID0gc2V0dGluZ3Mub0xhbmd1YWdlLm9BcmlhLnBhZ2luYXRlIHx8IHt9O1xuXHR2YXIgYnRuRGlzcGxheSwgYnRuQ2xhc3M7XG5cblx0dmFyIGF0dGFjaCA9IGZ1bmN0aW9uKCBjb250YWluZXIsIGJ1dHRvbnMgKSB7XG5cdFx0dmFyIGksIGllbiwgbm9kZSwgYnV0dG9uO1xuXHRcdHZhciBjbGlja0hhbmRsZXIgPSBmdW5jdGlvbiAoIGUgKSB7XG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRpZiAoICEkKGUuY3VycmVudFRhcmdldCkuaGFzQ2xhc3MoJ2Rpc2FibGVkJykgJiYgYXBpLnBhZ2UoKSAhPSBlLmRhdGEuYWN0aW9uICkge1xuXHRcdFx0XHRhcGkucGFnZSggZS5kYXRhLmFjdGlvbiApLmRyYXcoICdwYWdlJyApO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0XHRmb3IgKCBpPTAsIGllbj1idXR0b25zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0YnV0dG9uID0gYnV0dG9uc1tpXTtcblxuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBidXR0b24gKSApIHtcblx0XHRcdFx0YXR0YWNoKCBjb250YWluZXIsIGJ1dHRvbiApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGJ0bkRpc3BsYXkgPSAnJztcblx0XHRcdFx0YnRuQ2xhc3MgPSAnJztcblxuXHRcdFx0XHRzd2l0Y2ggKCBidXR0b24gKSB7XG5cdFx0XHRcdFx0Y2FzZSAnZWxsaXBzaXMnOlxuXHRcdFx0XHRcdFx0YnRuRGlzcGxheSA9ICcmI3gyMDI2Oyc7XG5cdFx0XHRcdFx0XHRidG5DbGFzcyA9ICdkaXNhYmxlZCc7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdGNhc2UgJ2ZpcnN0Jzpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBsYW5nLnNGaXJzdDtcblx0XHRcdFx0XHRcdGJ0bkNsYXNzID0gYnV0dG9uICsgKHBhZ2UgPiAwID9cblx0XHRcdFx0XHRcdFx0JycgOiAnIGRpc2FibGVkJyk7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdGNhc2UgJ3ByZXZpb3VzJzpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBsYW5nLnNQcmV2aW91cztcblx0XHRcdFx0XHRcdGJ0bkNsYXNzID0gYnV0dG9uICsgKHBhZ2UgPiAwID9cblx0XHRcdFx0XHRcdFx0JycgOiAnIGRpc2FibGVkJyk7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdGNhc2UgJ25leHQnOlxuXHRcdFx0XHRcdFx0YnRuRGlzcGxheSA9IGxhbmcuc05leHQ7XG5cdFx0XHRcdFx0XHRidG5DbGFzcyA9IGJ1dHRvbiArIChwYWdlIDwgcGFnZXMtMSA/XG5cdFx0XHRcdFx0XHRcdCcnIDogJyBkaXNhYmxlZCcpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0XHRjYXNlICdsYXN0Jzpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBsYW5nLnNMYXN0O1xuXHRcdFx0XHRcdFx0YnRuQ2xhc3MgPSBidXR0b24gKyAocGFnZSA8IHBhZ2VzLTEgP1xuXHRcdFx0XHRcdFx0XHQnJyA6ICcgZGlzYWJsZWQnKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBidXR0b24gKyAxO1xuXHRcdFx0XHRcdFx0YnRuQ2xhc3MgPSBwYWdlID09PSBidXR0b24gP1xuXHRcdFx0XHRcdFx0XHQnYWN0aXZlJyA6ICcnO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGJ0bkRpc3BsYXkgKSB7XG5cdFx0XHRcdFx0dmFyIGRpc2FibGVkID0gYnRuQ2xhc3MuaW5kZXhPZignZGlzYWJsZWQnKSAhPT0gLTE7XG5cblx0XHRcdFx0XHRub2RlID0gJCgnPGxpPicsIHtcblx0XHRcdFx0XHRcdFx0J2NsYXNzJzogY2xhc3Nlcy5zUGFnZUJ1dHRvbisnICcrYnRuQ2xhc3MsXG5cdFx0XHRcdFx0XHRcdCdpZCc6IGlkeCA9PT0gMCAmJiB0eXBlb2YgYnV0dG9uID09PSAnc3RyaW5nJyA/XG5cdFx0XHRcdFx0XHRcdFx0c2V0dGluZ3Muc1RhYmxlSWQgKydfJysgYnV0dG9uIDpcblx0XHRcdFx0XHRcdFx0XHRudWxsXG5cdFx0XHRcdFx0XHR9IClcblx0XHRcdFx0XHRcdC5hcHBlbmQoICQoJzxhPicsIHtcblx0XHRcdFx0XHRcdFx0XHQnaHJlZic6IGRpc2FibGVkID8gbnVsbCA6ICcjJyxcblx0XHRcdFx0XHRcdFx0XHQnYXJpYS1jb250cm9scyc6IHNldHRpbmdzLnNUYWJsZUlkLFxuXHRcdFx0XHRcdFx0XHRcdCdhcmlhLWRpc2FibGVkJzogZGlzYWJsZWQgPyAndHJ1ZScgOiBudWxsLFxuXHRcdFx0XHRcdFx0XHRcdCdhcmlhLWxhYmVsJzogYXJpYVsgYnV0dG9uIF0sXG5cdFx0XHRcdFx0XHRcdFx0J3JvbGUnOiAnbGluaycsXG5cdFx0XHRcdFx0XHRcdFx0J2FyaWEtY3VycmVudCc6IGJ0bkNsYXNzID09PSAnYWN0aXZlJyA/ICdwYWdlJyA6IG51bGwsXG5cdFx0XHRcdFx0XHRcdFx0J2RhdGEtZHQtaWR4JzogYnV0dG9uLFxuXHRcdFx0XHRcdFx0XHRcdCd0YWJpbmRleCc6IGRpc2FibGVkID8gLTEgOiBzZXR0aW5ncy5pVGFiSW5kZXgsXG5cdFx0XHRcdFx0XHRcdFx0J2NsYXNzJzogJ3BhZ2UtbGluaydcblx0XHRcdFx0XHRcdFx0fSApXG5cdFx0XHRcdFx0XHRcdC5odG1sKCBidG5EaXNwbGF5IClcblx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdC5hcHBlbmRUbyggY29udGFpbmVyICk7XG5cblx0XHRcdFx0XHRzZXR0aW5ncy5vQXBpLl9mbkJpbmRBY3Rpb24oXG5cdFx0XHRcdFx0XHRub2RlLCB7YWN0aW9uOiBidXR0b259LCBjbGlja0hhbmRsZXJcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdC8vIElFOSB0aHJvd3MgYW4gJ3Vua25vd24gZXJyb3InIGlmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgaXMgdXNlZFxuXHQvLyBpbnNpZGUgYW4gaWZyYW1lIG9yIGZyYW1lLiBcblx0dmFyIGFjdGl2ZUVsO1xuXG5cdHRyeSB7XG5cdFx0Ly8gQmVjYXVzZSB0aGlzIGFwcHJvYWNoIGlzIGRlc3Ryb3lpbmcgYW5kIHJlY3JlYXRpbmcgdGhlIHBhZ2luZ1xuXHRcdC8vIGVsZW1lbnRzLCBmb2N1cyBpcyBsb3N0IG9uIHRoZSBzZWxlY3QgYnV0dG9uIHdoaWNoIGlzIGJhZCBmb3Jcblx0XHQvLyBhY2Nlc3NpYmlsaXR5LiBTbyB3ZSB3YW50IHRvIHJlc3RvcmUgZm9jdXMgb25jZSB0aGUgZHJhdyBoYXNcblx0XHQvLyBjb21wbGV0ZWRcblx0XHRhY3RpdmVFbCA9ICQoaG9zdCkuZmluZChkb2N1bWVudC5hY3RpdmVFbGVtZW50KS5kYXRhKCdkdC1pZHgnKTtcblx0fVxuXHRjYXRjaCAoZSkge31cblxuXHRhdHRhY2goXG5cdFx0JChob3N0KS5lbXB0eSgpLmh0bWwoJzx1bCBjbGFzcz1cInBhZ2luYXRpb25cIi8+JykuY2hpbGRyZW4oJ3VsJyksXG5cdFx0YnV0dG9uc1xuXHQpO1xuXG5cdGlmICggYWN0aXZlRWwgIT09IHVuZGVmaW5lZCApIHtcblx0XHQkKGhvc3QpLmZpbmQoICdbZGF0YS1kdC1pZHg9JythY3RpdmVFbCsnXScgKS50cmlnZ2VyKCdmb2N1cycpO1xuXHR9XG59O1xuXG5cbmV4cG9ydCBkZWZhdWx0IERhdGFUYWJsZTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-bs4/js/dataTables.bootstrap4.mjs\n"); /***/ }), /***/ "./node_modules/datatables.net-fixedcolumns-bs4/js/fixedColumns.bootstrap4.mjs": /*!*************************************************************************************!*\ !*** ./node_modules/datatables.net-fixedcolumns-bs4/js/fixedColumns.bootstrap4.mjs ***! \*************************************************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\");\n/* harmony import */ var datatables_net_bs4__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! datatables.net-bs4 */ \"./node_modules/datatables.net-bs4/js/dataTables.bootstrap4.mjs\");\n/* harmony import */ var datatables_net_fixedcolumns__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! datatables.net-fixedcolumns */ \"./node_modules/datatables.net-fixedcolumns/js/dataTables.fixedColumns.mjs\");\n/*! Bootstrap 4 integration for DataTables' FixedColumns\n * © SpryMedia Ltd - datatables.net/license\n */\n\n\n\n\n\n// Allow reassignment of the $ variable\nlet $ = jquery__WEBPACK_IMPORTED_MODULE_0__;\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (datatables_net_bs4__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtZml4ZWRjb2x1bW5zLWJzNC9qcy9maXhlZENvbHVtbnMuYm9vdHN0cmFwNC5tanMiLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBO0FBQ0E7QUFDQTs7QUFFNEI7QUFDZTtBQUNZOztBQUV2RDtBQUNBLFFBQVEsbUNBQU07Ozs7QUFJZCxpRUFBZSwwREFBUyxFQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2RhdGF0YWJsZXMubmV0LWZpeGVkY29sdW1ucy1iczQvanMvZml4ZWRDb2x1bW5zLmJvb3RzdHJhcDQubWpzPzIwYzQiXSwic291cmNlc0NvbnRlbnQiOlsiLyohIEJvb3RzdHJhcCA0IGludGVncmF0aW9uIGZvciBEYXRhVGFibGVzJyBGaXhlZENvbHVtbnNcbiAqIMKpIFNwcnlNZWRpYSBMdGQgLSBkYXRhdGFibGVzLm5ldC9saWNlbnNlXG4gKi9cblxuaW1wb3J0IGpRdWVyeSBmcm9tICdqcXVlcnknO1xuaW1wb3J0IERhdGFUYWJsZSBmcm9tICdkYXRhdGFibGVzLm5ldC1iczQnO1xuaW1wb3J0IEZpeGVkQ29sdW1ucyBmcm9tICdkYXRhdGFibGVzLm5ldC1maXhlZGNvbHVtbnMnO1xuXG4vLyBBbGxvdyByZWFzc2lnbm1lbnQgb2YgdGhlICQgdmFyaWFibGVcbmxldCAkID0galF1ZXJ5O1xuXG5cblxuZXhwb3J0IGRlZmF1bHQgRGF0YVRhYmxlO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-fixedcolumns-bs4/js/fixedColumns.bootstrap4.mjs\n"); /***/ }), /***/ "./node_modules/datatables.net-fixedcolumns/js/dataTables.fixedColumns.mjs": /*!*********************************************************************************!*\ !*** ./node_modules/datatables.net-fixedcolumns/js/dataTables.fixedColumns.mjs ***! \*********************************************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\");\n/* harmony import */ var datatables_net__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! datatables.net */ \"./node_modules/datatables.net/js/jquery.dataTables.mjs\");\n/*! FixedColumns 4.3.0\n * © SpryMedia Ltd - datatables.net/license\n */\n\n\n\n\n// Allow reassignment of the $ variable\nlet $ = jquery__WEBPACK_IMPORTED_MODULE_0__;\n\n(function () {\n 'use strict';\n\n var $$1;\n var dataTable;\n function setJQuery(jq) {\n $$1 = jq;\n dataTable = $$1.fn.dataTable;\n }\n var FixedColumns = /** @class */ (function () {\n function FixedColumns(settings, opts) {\n var _this = this;\n // Check that the required version of DataTables is included\n if (!dataTable || !dataTable.versionCheck || !dataTable.versionCheck('1.10.0')) {\n throw new Error('FixedColumns requires DataTables 1.10 or newer');\n }\n var table = new dataTable.Api(settings);\n this.classes = $$1.extend(true, {}, FixedColumns.classes);\n // Get options from user\n this.c = $$1.extend(true, {}, FixedColumns.defaults, opts);\n // Backwards compatibility for deprecated leftColumns\n if ((!opts || opts.left === undefined) && this.c.leftColumns !== undefined) {\n this.c.left = this.c.leftColumns;\n }\n // Backwards compatibility for deprecated rightColumns\n if ((!opts || opts.right === undefined) && this.c.rightColumns !== undefined) {\n this.c.right = this.c.rightColumns;\n }\n this.s = {\n barWidth: 0,\n dt: table,\n rtl: $$1('body').css('direction') === 'rtl'\n };\n // Common CSS for all blockers\n var blockerCSS = {\n 'bottom': '0px',\n 'display': 'block',\n 'position': 'absolute',\n 'width': this.s.barWidth + 1 + 'px'\n };\n this.dom = {\n leftBottomBlocker: $$1('
      ')\n .css(blockerCSS)\n .css('left', 0)\n .addClass(this.classes.leftBottomBlocker),\n leftTopBlocker: $$1('
      ')\n .css(blockerCSS)\n .css({\n left: 0,\n top: 0\n })\n .addClass(this.classes.leftTopBlocker),\n rightBottomBlocker: $$1('
      ')\n .css(blockerCSS)\n .css('right', 0)\n .addClass(this.classes.rightBottomBlocker),\n rightTopBlocker: $$1('
      ')\n .css(blockerCSS)\n .css({\n right: 0,\n top: 0\n })\n .addClass(this.classes.rightTopBlocker)\n };\n if (this.s.dt.settings()[0]._bInitComplete) {\n // Fixed Columns Initialisation\n this._addStyles();\n this._setKeyTableListener();\n }\n else {\n table.one('init.dt.dtfc', function () {\n // Fixed Columns Initialisation\n _this._addStyles();\n _this._setKeyTableListener();\n });\n }\n table.on('column-sizing.dt.dtfc', function () { return _this._addStyles(); });\n // Make class available through dt object\n table.settings()[0]._fixedColumns = this;\n table.on('destroy', function () { return _this._destroy(); });\n return this;\n }\n FixedColumns.prototype.left = function (newVal) {\n // If the value is to change\n if (newVal !== undefined) {\n if (newVal >= 0 && newVal <= this.s.dt.columns().count()) {\n // Set the new values and redraw the columns\n this.c.left = newVal;\n this._addStyles();\n }\n return this;\n }\n return this.c.left;\n };\n FixedColumns.prototype.right = function (newVal) {\n // If the value is to change\n if (newVal !== undefined) {\n if (newVal >= 0 && newVal <= this.s.dt.columns().count()) {\n // Set the new values and redraw the columns\n this.c.right = newVal;\n this._addStyles();\n }\n return this;\n }\n return this.c.right;\n };\n /**\n * Iterates over the columns, fixing the appropriate ones to the left and right\n */\n FixedColumns.prototype._addStyles = function () {\n // Set the bar width if vertical scrolling is enabled\n if (this.s.dt.settings()[0].oScroll.sY) {\n var scroll_1 = $$1(this.s.dt.table().node()).closest('div.dataTables_scrollBody')[0];\n var barWidth = this.s.dt.settings()[0].oBrowser.barWidth;\n if (scroll_1.offsetWidth - scroll_1.clientWidth >= barWidth) {\n this.s.barWidth = barWidth;\n }\n else {\n this.s.barWidth = 0;\n }\n this.dom.rightTopBlocker.css('width', this.s.barWidth + 1);\n this.dom.leftTopBlocker.css('width', this.s.barWidth + 1);\n this.dom.rightBottomBlocker.css('width', this.s.barWidth + 1);\n this.dom.leftBottomBlocker.css('width', this.s.barWidth + 1);\n }\n var parentDiv = null;\n // Get the header and it's height\n var header = this.s.dt.column(0).header();\n var headerHeight = null;\n if (header !== null) {\n header = $$1(header);\n headerHeight = header.outerHeight() + 1;\n parentDiv = $$1(header.closest('div.dataTables_scroll')).css('position', 'relative');\n }\n // Get the footer and it's height\n var footer = this.s.dt.column(0).footer();\n var footerHeight = null;\n if (footer !== null) {\n footer = $$1(footer);\n footerHeight = footer.outerHeight();\n // Only attempt to retrieve the parentDiv if it has not been retrieved already\n if (parentDiv === null) {\n parentDiv = $$1(footer.closest('div.dataTables_scroll')).css('position', 'relative');\n }\n }\n // Get the number of columns in the table - this is used often so better to only make 1 api call\n var numCols = this.s.dt.columns().data().toArray().length;\n // Tracker for the number of pixels should be left to the left of the table\n var distLeft = 0;\n // Sometimes the headers have slightly different widths so need to track them individually\n var headLeft = 0;\n // Get all of the row elements in the table\n var rows = $$1(this.s.dt.table().node()).children('tbody').children('tr');\n var invisibles = 0;\n // When working from right to left we need to know how many are invisible before a point,\n // without including those that are invisible after\n var prevInvisible = new Map();\n // Iterate over all of the columns\n for (var i = 0; i < numCols; i++) {\n var column = this.s.dt.column(i);\n // Set the map for the previous column\n if (i > 0) {\n prevInvisible.set(i - 1, invisibles);\n }\n if (!column.visible()) {\n invisibles++;\n continue;\n }\n // Get the columns header and footer element\n var colHeader = $$1(column.header());\n var colFooter = $$1(column.footer());\n // If i is less than the value of left then this column should be fixed left\n if (i - invisibles < this.c.left) {\n $$1(this.s.dt.table().node()).addClass(this.classes.tableFixedLeft);\n parentDiv.addClass(this.classes.tableFixedLeft);\n // Add the width of the previous node - only if we are on atleast the second column\n if (i - invisibles > 0) {\n var prevIdx = i;\n // Simply using the number of hidden columns doesn't work here,\n // if the first is hidden then this would be thrown off\n while (prevIdx + 1 < numCols) {\n var prevCol = this.s.dt.column(prevIdx - 1, { page: 'current' });\n if (prevCol.visible()) {\n distLeft += $$1(prevCol.nodes()[0]).outerWidth();\n headLeft += prevCol.header() ?\n $$1(prevCol.header()).outerWidth() :\n prevCol.footer() ?\n $$1(prevCol.header()).outerWidth() :\n 0;\n break;\n }\n prevIdx--;\n }\n }\n // Iterate over all of the rows, fixing the cell to the left\n for (var _i = 0, rows_1 = rows; _i < rows_1.length; _i++) {\n var row = rows_1[_i];\n $$1($$1(row).children()[i - invisibles])\n .css(this._getCellCSS(false, distLeft, 'left'))\n .addClass(this.classes.fixedLeft);\n }\n // Add the css for the header and the footer\n colHeader\n .css(this._getCellCSS(true, headLeft, 'left'))\n .addClass(this.classes.fixedLeft);\n colFooter\n .css(this._getCellCSS(true, headLeft, 'left'))\n .addClass(this.classes.fixedLeft);\n }\n else {\n // Iteriate through all of the rows, making sure they aren't currently trying to fix left\n for (var _a = 0, rows_2 = rows; _a < rows_2.length; _a++) {\n var row = rows_2[_a];\n var cell = $$1($$1(row).children()[i - invisibles]);\n // If the cell is trying to fix to the left, remove the class and the css\n if (cell.hasClass(this.classes.fixedLeft)) {\n cell\n .css(this._clearCellCSS('left'))\n .removeClass(this.classes.fixedLeft);\n }\n }\n // Make sure the header for this column isn't fixed left\n if (colHeader.hasClass(this.classes.fixedLeft)) {\n colHeader\n .css(this._clearCellCSS('left'))\n .removeClass(this.classes.fixedLeft);\n }\n // Make sure the footer for this column isn't fixed left\n if (colFooter.hasClass(this.classes.fixedLeft)) {\n colFooter\n .css(this._clearCellCSS('left'))\n .removeClass(this.classes.fixedLeft);\n }\n }\n }\n var distRight = 0;\n var headRight = 0;\n // Counter for the number of invisible columns so far\n var rightInvisibles = 0;\n for (var i = numCols - 1; i >= 0; i--) {\n var column = this.s.dt.column(i);\n // If a column is invisible just skip it\n if (!column.visible()) {\n rightInvisibles++;\n continue;\n }\n // Get the columns header and footer element\n var colHeader = $$1(column.header());\n var colFooter = $$1(column.footer());\n // Get the number of visible columns that came before this one\n var prev = prevInvisible.get(i);\n if (prev === undefined) {\n // If it wasn't set then it was the last column so just use the final value\n prev = invisibles;\n }\n if (i + rightInvisibles >= numCols - this.c.right) {\n $$1(this.s.dt.table().node()).addClass(this.classes.tableFixedRight);\n parentDiv.addClass(this.classes.tableFixedRight);\n // Add the widht of the previous node, only if we are on atleast the second column\n if (i + 1 + rightInvisibles < numCols) {\n var prevIdx = i;\n // Simply using the number of hidden columns doesn't work here,\n // if the first is hidden then this would be thrown off\n while (prevIdx + 1 < numCols) {\n var prevCol = this.s.dt.column(prevIdx + 1, { page: 'current' });\n if (prevCol.visible()) {\n distRight += $$1(prevCol.nodes()[0]).outerWidth();\n headRight += prevCol.header() ?\n $$1(prevCol.header()).outerWidth() :\n prevCol.footer() ?\n $$1(prevCol.header()).outerWidth() :\n 0;\n break;\n }\n prevIdx++;\n }\n }\n // Iterate over all of the rows, fixing the cell to the right\n for (var _b = 0, rows_3 = rows; _b < rows_3.length; _b++) {\n var row = rows_3[_b];\n $$1($$1(row).children()[i - prev])\n .css(this._getCellCSS(false, distRight, 'right'))\n .addClass(this.classes.fixedRight);\n }\n // Add the css for the header and the footer\n colHeader\n .css(this._getCellCSS(true, headRight, 'right'))\n .addClass(this.classes.fixedRight);\n colFooter\n .css(this._getCellCSS(true, headRight, 'right'))\n .addClass(this.classes.fixedRight);\n }\n else {\n // Iteriate through all of the rows, making sure they aren't currently trying to fix right\n for (var _c = 0, rows_4 = rows; _c < rows_4.length; _c++) {\n var row = rows_4[_c];\n var cell = $$1($$1(row).children()[i - prev]);\n // If the cell is trying to fix to the right, remove the class and the css\n if (cell.hasClass(this.classes.fixedRight)) {\n cell\n .css(this._clearCellCSS('right'))\n .removeClass(this.classes.fixedRight);\n }\n }\n // Make sure the header for this column isn't fixed right\n if (colHeader.hasClass(this.classes.fixedRight)) {\n colHeader\n .css(this._clearCellCSS('right'))\n .removeClass(this.classes.fixedRight);\n }\n // Make sure the footer for this column isn't fixed right\n if (colFooter.hasClass(this.classes.fixedRight)) {\n colFooter\n .css(this._clearCellCSS('right'))\n .removeClass(this.classes.fixedRight);\n }\n }\n }\n // If there is a header with the index class and reading rtl then add right top blocker\n if (header) {\n if (!this.s.rtl) {\n this.dom.rightTopBlocker.outerHeight(headerHeight);\n parentDiv.append(this.dom.rightTopBlocker);\n }\n else {\n this.dom.leftTopBlocker.outerHeight(headerHeight);\n parentDiv.append(this.dom.leftTopBlocker);\n }\n }\n // If there is a footer with the index class and reading rtl then add right bottom blocker\n if (footer) {\n if (!this.s.rtl) {\n this.dom.rightBottomBlocker.outerHeight(footerHeight);\n parentDiv.append(this.dom.rightBottomBlocker);\n }\n else {\n this.dom.leftBottomBlocker.outerHeight(footerHeight);\n parentDiv.append(this.dom.leftBottomBlocker);\n }\n }\n };\n /**\n * Clean up\n */\n FixedColumns.prototype._destroy = function () {\n this.s.dt.off('.dtfc');\n this.dom.leftBottomBlocker.remove();\n this.dom.leftTopBlocker.remove();\n this.dom.rightBottomBlocker.remove();\n this.dom.rightTopBlocker.remove();\n };\n /**\n * Gets the correct CSS for the cell, header or footer based on options provided\n *\n * @param header Whether this cell is a header or a footer\n * @param dist The distance that the cell should be moved away from the edge\n * @param lr Indicator of fixing to the left or the right\n * @returns An object containing the correct css\n */\n FixedColumns.prototype._getCellCSS = function (header, dist, lr) {\n if (lr === 'left') {\n return this.s.rtl\n ? {\n position: 'sticky',\n right: dist + 'px'\n }\n : {\n left: dist + 'px',\n position: 'sticky'\n };\n }\n else {\n return this.s.rtl\n ? {\n left: dist + (header ? this.s.barWidth : 0) + 'px',\n position: 'sticky'\n }\n : {\n position: 'sticky',\n right: dist + (header ? this.s.barWidth : 0) + 'px'\n };\n }\n };\n /**\n * Gets the css that is required to clear the fixing to a side\n *\n * @param lr Indicator of fixing to the left or the right\n * @returns An object containing the correct css\n */\n FixedColumns.prototype._clearCellCSS = function (lr) {\n if (lr === 'left') {\n return !this.s.rtl ?\n {\n left: '',\n position: ''\n } :\n {\n position: '',\n right: ''\n };\n }\n else {\n return !this.s.rtl ?\n {\n position: '',\n right: ''\n } :\n {\n left: '',\n position: ''\n };\n }\n };\n FixedColumns.prototype._setKeyTableListener = function () {\n var _this = this;\n this.s.dt.on('key-focus.dt.dtfc', function (e, dt, cell) {\n var cellPos = $$1(cell.node()).offset();\n var scroll = $$1($$1(_this.s.dt.table().node()).closest('div.dataTables_scrollBody'));\n // If there are fixed columns to the left\n if (_this.c.left > 0) {\n // Get the rightmost left fixed column header, it's position and it's width\n var rightMost = $$1(_this.s.dt.column(_this.c.left - 1).header());\n var rightMostPos = rightMost.offset();\n var rightMostWidth = rightMost.outerWidth();\n // If the current highlighted cell is left of the rightmost cell on the screen\n if (cellPos.left < rightMostPos.left + rightMostWidth) {\n // Scroll it into view\n var currScroll = scroll.scrollLeft();\n scroll.scrollLeft(currScroll - (rightMostPos.left + rightMostWidth - cellPos.left));\n }\n }\n // If there are fixed columns to the right\n if (_this.c.right > 0) {\n // Get the number of columns and the width of the cell as doing right side calc\n var numCols = _this.s.dt.columns().data().toArray().length;\n var cellWidth = $$1(cell.node()).outerWidth();\n // Get the leftmost right fixed column header and it's position\n var leftMost = $$1(_this.s.dt.column(numCols - _this.c.right).header());\n var leftMostPos = leftMost.offset();\n // If the current highlighted cell is right of the leftmost cell on the screen\n if (cellPos.left + cellWidth > leftMostPos.left) {\n // Scroll it into view\n var currScroll = scroll.scrollLeft();\n scroll.scrollLeft(currScroll - (leftMostPos.left - (cellPos.left + cellWidth)));\n }\n }\n });\n // Whenever a draw occurs there is potential for the data to have changed and therefore also the column widths\n // Therefore it is necessary to recalculate the values for the fixed columns\n this.s.dt.on('draw.dt.dtfc', function () {\n _this._addStyles();\n });\n this.s.dt.on('column-reorder.dt.dtfc', function () {\n _this._addStyles();\n });\n this.s.dt.on('column-visibility.dt.dtfc', function (e, settings, column, state, recalc) {\n if (recalc && !settings.bDestroying) {\n setTimeout(function () {\n _this._addStyles();\n }, 50);\n }\n });\n };\n FixedColumns.version = '4.3.0';\n FixedColumns.classes = {\n fixedLeft: 'dtfc-fixed-left',\n fixedRight: 'dtfc-fixed-right',\n leftBottomBlocker: 'dtfc-left-bottom-blocker',\n leftTopBlocker: 'dtfc-left-top-blocker',\n rightBottomBlocker: 'dtfc-right-bottom-blocker',\n rightTopBlocker: 'dtfc-right-top-blocker',\n tableFixedLeft: 'dtfc-has-left',\n tableFixedRight: 'dtfc-has-right'\n };\n FixedColumns.defaults = {\n i18n: {\n button: 'FixedColumns'\n },\n left: 1,\n right: 0\n };\n return FixedColumns;\n }());\n\n /*! FixedColumns 4.3.0\n * © SpryMedia Ltd - datatables.net/license\n */\n setJQuery($);\n $.fn.dataTable.FixedColumns = FixedColumns;\n $.fn.DataTable.FixedColumns = FixedColumns;\n var apiRegister = datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Api.register;\n apiRegister('fixedColumns()', function () {\n return this;\n });\n apiRegister('fixedColumns().left()', function (newVal) {\n var ctx = this.context[0];\n if (newVal !== undefined) {\n ctx._fixedColumns.left(newVal);\n return this;\n }\n else {\n return ctx._fixedColumns.left();\n }\n });\n apiRegister('fixedColumns().right()', function (newVal) {\n var ctx = this.context[0];\n if (newVal !== undefined) {\n ctx._fixedColumns.right(newVal);\n return this;\n }\n else {\n return ctx._fixedColumns.right();\n }\n });\n datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].ext.buttons.fixedColumns = {\n action: function (e, dt, node, config) {\n if ($(node).attr('active')) {\n $(node).removeAttr('active').removeClass('active');\n dt.fixedColumns().left(0);\n dt.fixedColumns().right(0);\n }\n else {\n $(node).attr('active', 'true').addClass('active');\n dt.fixedColumns().left(config.config.left);\n dt.fixedColumns().right(config.config.right);\n }\n },\n config: {\n left: 1,\n right: 0\n },\n init: function (dt, node, config) {\n if (dt.settings()[0]._fixedColumns === undefined) {\n _init(dt.settings(), config);\n }\n $(node).attr('active', 'true').addClass('active');\n dt.button(node).text(config.text || dt.i18n('buttons.fixedColumns', dt.settings()[0]._fixedColumns.c.i18n.button));\n },\n text: null\n };\n function _init(settings, options) {\n if (options === void 0) { options = null; }\n var api = new datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Api(settings);\n var opts = options\n ? options\n : api.init().fixedColumns || datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].defaults.fixedColumns;\n var fixedColumns = new FixedColumns(api, opts);\n return fixedColumns;\n }\n // Attach a listener to the document which listens for DataTables initialisation\n // events so we can automatically initialise\n $(document).on('plugin-init.dt', function (e, settings) {\n if (e.namespace !== 'dt') {\n return;\n }\n if (settings.oInit.fixedColumns ||\n datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"].defaults.fixedColumns) {\n if (!settings._fixedColumns) {\n _init(settings, null);\n }\n }\n });\n\n}());\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (datatables_net__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtZml4ZWRjb2x1bW5zL2pzL2RhdGFUYWJsZXMuZml4ZWRDb2x1bW5zLm1qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTtBQUNBO0FBQ0E7O0FBRTRCO0FBQ1c7O0FBRXZDO0FBQ0EsUUFBUSxtQ0FBTTs7QUFFZDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLDREQUE0RCw0QkFBNEI7QUFDeEY7QUFDQTtBQUNBLDhDQUE4QywwQkFBMEI7QUFDeEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGFBQWE7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwRUFBMEUsaUJBQWlCO0FBQzNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9ELG9CQUFvQjtBQUN4RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0Qsb0JBQW9CO0FBQ3hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxRQUFRO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBFQUEwRSxpQkFBaUI7QUFDM0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0Qsb0JBQW9CO0FBQ3hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9EQUFvRCxvQkFBb0I7QUFDeEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0Isc0RBQVM7QUFDL0I7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUksc0RBQVM7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDO0FBQ2xDLHNCQUFzQixzREFBUztBQUMvQjtBQUNBO0FBQ0EseUNBQXlDLHNEQUFTO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxzREFBUztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUwsQ0FBQzs7O0FBR0QsaUVBQWUsc0RBQVMsRUFBQyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9kYXRhdGFibGVzLm5ldC1maXhlZGNvbHVtbnMvanMvZGF0YVRhYmxlcy5maXhlZENvbHVtbnMubWpzP2UwZDQiXSwic291cmNlc0NvbnRlbnQiOlsiLyohIEZpeGVkQ29sdW1ucyA0LjMuMFxuICogwqkgU3ByeU1lZGlhIEx0ZCAtIGRhdGF0YWJsZXMubmV0L2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQgalF1ZXJ5IGZyb20gJ2pxdWVyeSc7XG5pbXBvcnQgRGF0YVRhYmxlIGZyb20gJ2RhdGF0YWJsZXMubmV0JztcblxuLy8gQWxsb3cgcmVhc3NpZ25tZW50IG9mIHRoZSAkIHZhcmlhYmxlXG5sZXQgJCA9IGpRdWVyeTtcblxuKGZ1bmN0aW9uICgpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICB2YXIgJCQxO1xuICAgIHZhciBkYXRhVGFibGU7XG4gICAgZnVuY3Rpb24gc2V0SlF1ZXJ5KGpxKSB7XG4gICAgICAgICQkMSA9IGpxO1xuICAgICAgICBkYXRhVGFibGUgPSAkJDEuZm4uZGF0YVRhYmxlO1xuICAgIH1cbiAgICB2YXIgRml4ZWRDb2x1bW5zID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBGaXhlZENvbHVtbnMoc2V0dGluZ3MsIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICAvLyBDaGVjayB0aGF0IHRoZSByZXF1aXJlZCB2ZXJzaW9uIG9mIERhdGFUYWJsZXMgaXMgaW5jbHVkZWRcbiAgICAgICAgICAgIGlmICghZGF0YVRhYmxlIHx8ICFkYXRhVGFibGUudmVyc2lvbkNoZWNrIHx8ICFkYXRhVGFibGUudmVyc2lvbkNoZWNrKCcxLjEwLjAnKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRml4ZWRDb2x1bW5zIHJlcXVpcmVzIERhdGFUYWJsZXMgMS4xMCBvciBuZXdlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHRhYmxlID0gbmV3IGRhdGFUYWJsZS5BcGkoc2V0dGluZ3MpO1xuICAgICAgICAgICAgdGhpcy5jbGFzc2VzID0gJCQxLmV4dGVuZCh0cnVlLCB7fSwgRml4ZWRDb2x1bW5zLmNsYXNzZXMpO1xuICAgICAgICAgICAgLy8gR2V0IG9wdGlvbnMgZnJvbSB1c2VyXG4gICAgICAgICAgICB0aGlzLmMgPSAkJDEuZXh0ZW5kKHRydWUsIHt9LCBGaXhlZENvbHVtbnMuZGVmYXVsdHMsIG9wdHMpO1xuICAgICAgICAgICAgLy8gQmFja3dhcmRzIGNvbXBhdGliaWxpdHkgZm9yIGRlcHJlY2F0ZWQgbGVmdENvbHVtbnNcbiAgICAgICAgICAgIGlmICgoIW9wdHMgfHwgb3B0cy5sZWZ0ID09PSB1bmRlZmluZWQpICYmIHRoaXMuYy5sZWZ0Q29sdW1ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jLmxlZnQgPSB0aGlzLmMubGVmdENvbHVtbnM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBmb3IgZGVwcmVjYXRlZCByaWdodENvbHVtbnNcbiAgICAgICAgICAgIGlmICgoIW9wdHMgfHwgb3B0cy5yaWdodCA9PT0gdW5kZWZpbmVkKSAmJiB0aGlzLmMucmlnaHRDb2x1bW5zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmMucmlnaHQgPSB0aGlzLmMucmlnaHRDb2x1bW5zO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zID0ge1xuICAgICAgICAgICAgICAgIGJhcldpZHRoOiAwLFxuICAgICAgICAgICAgICAgIGR0OiB0YWJsZSxcbiAgICAgICAgICAgICAgICBydGw6ICQkMSgnYm9keScpLmNzcygnZGlyZWN0aW9uJykgPT09ICdydGwnXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gQ29tbW9uIENTUyBmb3IgYWxsIGJsb2NrZXJzXG4gICAgICAgICAgICB2YXIgYmxvY2tlckNTUyA9IHtcbiAgICAgICAgICAgICAgICAnYm90dG9tJzogJzBweCcsXG4gICAgICAgICAgICAgICAgJ2Rpc3BsYXknOiAnYmxvY2snLFxuICAgICAgICAgICAgICAgICdwb3NpdGlvbic6ICdhYnNvbHV0ZScsXG4gICAgICAgICAgICAgICAgJ3dpZHRoJzogdGhpcy5zLmJhcldpZHRoICsgMSArICdweCdcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmRvbSA9IHtcbiAgICAgICAgICAgICAgICBsZWZ0Qm90dG9tQmxvY2tlcjogJCQxKCc8ZGl2PicpXG4gICAgICAgICAgICAgICAgICAgIC5jc3MoYmxvY2tlckNTUylcbiAgICAgICAgICAgICAgICAgICAgLmNzcygnbGVmdCcsIDApXG4gICAgICAgICAgICAgICAgICAgIC5hZGRDbGFzcyh0aGlzLmNsYXNzZXMubGVmdEJvdHRvbUJsb2NrZXIpLFxuICAgICAgICAgICAgICAgIGxlZnRUb3BCbG9ja2VyOiAkJDEoJzxkaXY+JylcbiAgICAgICAgICAgICAgICAgICAgLmNzcyhibG9ja2VyQ1NTKVxuICAgICAgICAgICAgICAgICAgICAuY3NzKHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiAwXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy5sZWZ0VG9wQmxvY2tlciksXG4gICAgICAgICAgICAgICAgcmlnaHRCb3R0b21CbG9ja2VyOiAkJDEoJzxkaXY+JylcbiAgICAgICAgICAgICAgICAgICAgLmNzcyhibG9ja2VyQ1NTKVxuICAgICAgICAgICAgICAgICAgICAuY3NzKCdyaWdodCcsIDApXG4gICAgICAgICAgICAgICAgICAgIC5hZGRDbGFzcyh0aGlzLmNsYXNzZXMucmlnaHRCb3R0b21CbG9ja2VyKSxcbiAgICAgICAgICAgICAgICByaWdodFRvcEJsb2NrZXI6ICQkMSgnPGRpdj4nKVxuICAgICAgICAgICAgICAgICAgICAuY3NzKGJsb2NrZXJDU1MpXG4gICAgICAgICAgICAgICAgICAgIC5jc3Moe1xuICAgICAgICAgICAgICAgICAgICByaWdodDogMCxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiAwXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy5yaWdodFRvcEJsb2NrZXIpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKHRoaXMucy5kdC5zZXR0aW5ncygpWzBdLl9iSW5pdENvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgLy8gRml4ZWQgQ29sdW1ucyBJbml0aWFsaXNhdGlvblxuICAgICAgICAgICAgICAgIHRoaXMuX2FkZFN0eWxlcygpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldEtleVRhYmxlTGlzdGVuZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRhYmxlLm9uZSgnaW5pdC5kdC5kdGZjJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBGaXhlZCBDb2x1bW5zIEluaXRpYWxpc2F0aW9uXG4gICAgICAgICAgICAgICAgICAgIF90aGlzLl9hZGRTdHlsZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuX3NldEtleVRhYmxlTGlzdGVuZXIoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRhYmxlLm9uKCdjb2x1bW4tc2l6aW5nLmR0LmR0ZmMnLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5fYWRkU3R5bGVzKCk7IH0pO1xuICAgICAgICAgICAgLy8gTWFrZSBjbGFzcyBhdmFpbGFibGUgdGhyb3VnaCBkdCBvYmplY3RcbiAgICAgICAgICAgIHRhYmxlLnNldHRpbmdzKClbMF0uX2ZpeGVkQ29sdW1ucyA9IHRoaXM7XG4gICAgICAgICAgICB0YWJsZS5vbignZGVzdHJveScsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLl9kZXN0cm95KCk7IH0pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgRml4ZWRDb2x1bW5zLnByb3RvdHlwZS5sZWZ0ID0gZnVuY3Rpb24gKG5ld1ZhbCkge1xuICAgICAgICAgICAgLy8gSWYgdGhlIHZhbHVlIGlzIHRvIGNoYW5nZVxuICAgICAgICAgICAgaWYgKG5ld1ZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5ld1ZhbCA+PSAwICYmIG5ld1ZhbCA8PSB0aGlzLnMuZHQuY29sdW1ucygpLmNvdW50KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBuZXcgdmFsdWVzIGFuZCByZWRyYXcgdGhlIGNvbHVtbnNcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jLmxlZnQgPSBuZXdWYWw7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZFN0eWxlcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmMubGVmdDtcbiAgICAgICAgfTtcbiAgICAgICAgRml4ZWRDb2x1bW5zLnByb3RvdHlwZS5yaWdodCA9IGZ1bmN0aW9uIChuZXdWYWwpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSB2YWx1ZSBpcyB0byBjaGFuZ2VcbiAgICAgICAgICAgIGlmIChuZXdWYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmIChuZXdWYWwgPj0gMCAmJiBuZXdWYWwgPD0gdGhpcy5zLmR0LmNvbHVtbnMoKS5jb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgbmV3IHZhbHVlcyBhbmQgcmVkcmF3IHRoZSBjb2x1bW5zXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYy5yaWdodCA9IG5ld1ZhbDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkU3R5bGVzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYy5yaWdodDtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEl0ZXJhdGVzIG92ZXIgdGhlIGNvbHVtbnMsIGZpeGluZyB0aGUgYXBwcm9wcmlhdGUgb25lcyB0byB0aGUgbGVmdCBhbmQgcmlnaHRcbiAgICAgICAgICovXG4gICAgICAgIEZpeGVkQ29sdW1ucy5wcm90b3R5cGUuX2FkZFN0eWxlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIFNldCB0aGUgYmFyIHdpZHRoIGlmIHZlcnRpY2FsIHNjcm9sbGluZyBpcyBlbmFibGVkXG4gICAgICAgICAgICBpZiAodGhpcy5zLmR0LnNldHRpbmdzKClbMF0ub1Njcm9sbC5zWSkge1xuICAgICAgICAgICAgICAgIHZhciBzY3JvbGxfMSA9ICQkMSh0aGlzLnMuZHQudGFibGUoKS5ub2RlKCkpLmNsb3Nlc3QoJ2Rpdi5kYXRhVGFibGVzX3Njcm9sbEJvZHknKVswXTtcbiAgICAgICAgICAgICAgICB2YXIgYmFyV2lkdGggPSB0aGlzLnMuZHQuc2V0dGluZ3MoKVswXS5vQnJvd3Nlci5iYXJXaWR0aDtcbiAgICAgICAgICAgICAgICBpZiAoc2Nyb2xsXzEub2Zmc2V0V2lkdGggLSBzY3JvbGxfMS5jbGllbnRXaWR0aCA+PSBiYXJXaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnMuYmFyV2lkdGggPSBiYXJXaWR0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucy5iYXJXaWR0aCA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZG9tLnJpZ2h0VG9wQmxvY2tlci5jc3MoJ3dpZHRoJywgdGhpcy5zLmJhcldpZHRoICsgMSk7XG4gICAgICAgICAgICAgICAgdGhpcy5kb20ubGVmdFRvcEJsb2NrZXIuY3NzKCd3aWR0aCcsIHRoaXMucy5iYXJXaWR0aCArIDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tLnJpZ2h0Qm90dG9tQmxvY2tlci5jc3MoJ3dpZHRoJywgdGhpcy5zLmJhcldpZHRoICsgMSk7XG4gICAgICAgICAgICAgICAgdGhpcy5kb20ubGVmdEJvdHRvbUJsb2NrZXIuY3NzKCd3aWR0aCcsIHRoaXMucy5iYXJXaWR0aCArIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHBhcmVudERpdiA9IG51bGw7XG4gICAgICAgICAgICAvLyBHZXQgdGhlIGhlYWRlciBhbmQgaXQncyBoZWlnaHRcbiAgICAgICAgICAgIHZhciBoZWFkZXIgPSB0aGlzLnMuZHQuY29sdW1uKDApLmhlYWRlcigpO1xuICAgICAgICAgICAgdmFyIGhlYWRlckhlaWdodCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoaGVhZGVyICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaGVhZGVyID0gJCQxKGhlYWRlcik7XG4gICAgICAgICAgICAgICAgaGVhZGVySGVpZ2h0ID0gaGVhZGVyLm91dGVySGVpZ2h0KCkgKyAxO1xuICAgICAgICAgICAgICAgIHBhcmVudERpdiA9ICQkMShoZWFkZXIuY2xvc2VzdCgnZGl2LmRhdGFUYWJsZXNfc2Nyb2xsJykpLmNzcygncG9zaXRpb24nLCAncmVsYXRpdmUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEdldCB0aGUgZm9vdGVyIGFuZCBpdCdzIGhlaWdodFxuICAgICAgICAgICAgdmFyIGZvb3RlciA9IHRoaXMucy5kdC5jb2x1bW4oMCkuZm9vdGVyKCk7XG4gICAgICAgICAgICB2YXIgZm9vdGVySGVpZ2h0ID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChmb290ZXIgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmb290ZXIgPSAkJDEoZm9vdGVyKTtcbiAgICAgICAgICAgICAgICBmb290ZXJIZWlnaHQgPSBmb290ZXIub3V0ZXJIZWlnaHQoKTtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IGF0dGVtcHQgdG8gcmV0cmlldmUgdGhlIHBhcmVudERpdiBpZiBpdCBoYXMgbm90IGJlZW4gcmV0cmlldmVkIGFscmVhZHlcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50RGl2ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudERpdiA9ICQkMShmb290ZXIuY2xvc2VzdCgnZGl2LmRhdGFUYWJsZXNfc2Nyb2xsJykpLmNzcygncG9zaXRpb24nLCAncmVsYXRpdmUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBHZXQgdGhlIG51bWJlciBvZiBjb2x1bW5zIGluIHRoZSB0YWJsZSAtIHRoaXMgaXMgdXNlZCBvZnRlbiBzbyBiZXR0ZXIgdG8gb25seSBtYWtlIDEgYXBpIGNhbGxcbiAgICAgICAgICAgIHZhciBudW1Db2xzID0gdGhpcy5zLmR0LmNvbHVtbnMoKS5kYXRhKCkudG9BcnJheSgpLmxlbmd0aDtcbiAgICAgICAgICAgIC8vIFRyYWNrZXIgZm9yIHRoZSBudW1iZXIgb2YgcGl4ZWxzIHNob3VsZCBiZSBsZWZ0IHRvIHRoZSBsZWZ0IG9mIHRoZSB0YWJsZVxuICAgICAgICAgICAgdmFyIGRpc3RMZWZ0ID0gMDtcbiAgICAgICAgICAgIC8vIFNvbWV0aW1lcyB0aGUgaGVhZGVycyBoYXZlIHNsaWdodGx5IGRpZmZlcmVudCB3aWR0aHMgc28gbmVlZCB0byB0cmFjayB0aGVtIGluZGl2aWR1YWxseVxuICAgICAgICAgICAgdmFyIGhlYWRMZWZ0ID0gMDtcbiAgICAgICAgICAgIC8vIEdldCBhbGwgb2YgdGhlIHJvdyBlbGVtZW50cyBpbiB0aGUgdGFibGVcbiAgICAgICAgICAgIHZhciByb3dzID0gJCQxKHRoaXMucy5kdC50YWJsZSgpLm5vZGUoKSkuY2hpbGRyZW4oJ3Rib2R5JykuY2hpbGRyZW4oJ3RyJyk7XG4gICAgICAgICAgICB2YXIgaW52aXNpYmxlcyA9IDA7XG4gICAgICAgICAgICAvLyBXaGVuIHdvcmtpbmcgZnJvbSByaWdodCB0byBsZWZ0IHdlIG5lZWQgdG8ga25vdyBob3cgbWFueSBhcmUgaW52aXNpYmxlIGJlZm9yZSBhIHBvaW50LFxuICAgICAgICAgICAgLy8gd2l0aG91dCBpbmNsdWRpbmcgdGhvc2UgdGhhdCBhcmUgaW52aXNpYmxlIGFmdGVyXG4gICAgICAgICAgICB2YXIgcHJldkludmlzaWJsZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIC8vIEl0ZXJhdGUgb3ZlciBhbGwgb2YgdGhlIGNvbHVtbnNcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtQ29sczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMucy5kdC5jb2x1bW4oaSk7XG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBtYXAgZm9yIHRoZSBwcmV2aW91cyBjb2x1bW5cbiAgICAgICAgICAgICAgICBpZiAoaSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcHJldkludmlzaWJsZS5zZXQoaSAtIDEsIGludmlzaWJsZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbi52aXNpYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaW52aXNpYmxlcysrO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gR2V0IHRoZSBjb2x1bW5zIGhlYWRlciBhbmQgZm9vdGVyIGVsZW1lbnRcbiAgICAgICAgICAgICAgICB2YXIgY29sSGVhZGVyID0gJCQxKGNvbHVtbi5oZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgdmFyIGNvbEZvb3RlciA9ICQkMShjb2x1bW4uZm9vdGVyKCkpO1xuICAgICAgICAgICAgICAgIC8vIElmIGkgaXMgbGVzcyB0aGFuIHRoZSB2YWx1ZSBvZiBsZWZ0IHRoZW4gdGhpcyBjb2x1bW4gc2hvdWxkIGJlIGZpeGVkIGxlZnRcbiAgICAgICAgICAgICAgICBpZiAoaSAtIGludmlzaWJsZXMgPCB0aGlzLmMubGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAkJDEodGhpcy5zLmR0LnRhYmxlKCkubm9kZSgpKS5hZGRDbGFzcyh0aGlzLmNsYXNzZXMudGFibGVGaXhlZExlZnQpO1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnREaXYuYWRkQ2xhc3ModGhpcy5jbGFzc2VzLnRhYmxlRml4ZWRMZWZ0KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIHRoZSB3aWR0aCBvZiB0aGUgcHJldmlvdXMgbm9kZSAtIG9ubHkgaWYgd2UgYXJlIG9uIGF0bGVhc3QgdGhlIHNlY29uZCBjb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgLSBpbnZpc2libGVzID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZJZHggPSBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2ltcGx5IHVzaW5nIHRoZSBudW1iZXIgb2YgaGlkZGVuIGNvbHVtbnMgZG9lc24ndCB3b3JrIGhlcmUsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgZmlyc3QgaXMgaGlkZGVuIHRoZW4gdGhpcyB3b3VsZCBiZSB0aHJvd24gb2ZmXG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocHJldklkeCArIDEgPCBudW1Db2xzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZDb2wgPSB0aGlzLnMuZHQuY29sdW1uKHByZXZJZHggLSAxLCB7IHBhZ2U6ICdjdXJyZW50JyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJldkNvbC52aXNpYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdExlZnQgKz0gJCQxKHByZXZDb2wubm9kZXMoKVswXSkub3V0ZXJXaWR0aCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkTGVmdCArPSBwcmV2Q29sLmhlYWRlcigpID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQkMShwcmV2Q29sLmhlYWRlcigpKS5vdXRlcldpZHRoKCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldkNvbC5mb290ZXIoKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCQxKHByZXZDb2wuaGVhZGVyKCkpLm91dGVyV2lkdGgoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZJZHgtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIG92ZXIgYWxsIG9mIHRoZSByb3dzLCBmaXhpbmcgdGhlIGNlbGwgdG8gdGhlIGxlZnRcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByb3dzXzEgPSByb3dzOyBfaSA8IHJvd3NfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByb3cgPSByb3dzXzFbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgJCQxKCQkMShyb3cpLmNoaWxkcmVuKClbaSAtIGludmlzaWJsZXNdKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jc3ModGhpcy5fZ2V0Q2VsbENTUyhmYWxzZSwgZGlzdExlZnQsICdsZWZ0JykpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy5maXhlZExlZnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGUgY3NzIGZvciB0aGUgaGVhZGVyIGFuZCB0aGUgZm9vdGVyXG4gICAgICAgICAgICAgICAgICAgIGNvbEhlYWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgLmNzcyh0aGlzLl9nZXRDZWxsQ1NTKHRydWUsIGhlYWRMZWZ0LCAnbGVmdCcpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy5maXhlZExlZnQpO1xuICAgICAgICAgICAgICAgICAgICBjb2xGb290ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jc3ModGhpcy5fZ2V0Q2VsbENTUyh0cnVlLCBoZWFkTGVmdCwgJ2xlZnQnKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hZGRDbGFzcyh0aGlzLmNsYXNzZXMuZml4ZWRMZWZ0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEl0ZXJpYXRlIHRocm91Z2ggYWxsIG9mIHRoZSByb3dzLCBtYWtpbmcgc3VyZSB0aGV5IGFyZW4ndCBjdXJyZW50bHkgdHJ5aW5nIHRvIGZpeCBsZWZ0XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIF9hID0gMCwgcm93c18yID0gcm93czsgX2EgPCByb3dzXzIubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcm93ID0gcm93c18yW19hXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gJCQxKCQkMShyb3cpLmNoaWxkcmVuKClbaSAtIGludmlzaWJsZXNdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBjZWxsIGlzIHRyeWluZyB0byBmaXggdG8gdGhlIGxlZnQsIHJlbW92ZSB0aGUgY2xhc3MgYW5kIHRoZSBjc3NcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjZWxsLmhhc0NsYXNzKHRoaXMuY2xhc3Nlcy5maXhlZExlZnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY3NzKHRoaXMuX2NsZWFyQ2VsbENTUygnbGVmdCcpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkTGVmdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBoZWFkZXIgZm9yIHRoaXMgY29sdW1uIGlzbid0IGZpeGVkIGxlZnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbEhlYWRlci5oYXNDbGFzcyh0aGlzLmNsYXNzZXMuZml4ZWRMZWZ0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sSGVhZGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNzcyh0aGlzLl9jbGVhckNlbGxDU1MoJ2xlZnQnKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkTGVmdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBmb290ZXIgZm9yIHRoaXMgY29sdW1uIGlzbid0IGZpeGVkIGxlZnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbEZvb3Rlci5oYXNDbGFzcyh0aGlzLmNsYXNzZXMuZml4ZWRMZWZ0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sRm9vdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNzcyh0aGlzLl9jbGVhckNlbGxDU1MoJ2xlZnQnKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkTGVmdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGlzdFJpZ2h0ID0gMDtcbiAgICAgICAgICAgIHZhciBoZWFkUmlnaHQgPSAwO1xuICAgICAgICAgICAgLy8gQ291bnRlciBmb3IgdGhlIG51bWJlciBvZiBpbnZpc2libGUgY29sdW1ucyBzbyBmYXJcbiAgICAgICAgICAgIHZhciByaWdodEludmlzaWJsZXMgPSAwO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IG51bUNvbHMgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLnMuZHQuY29sdW1uKGkpO1xuICAgICAgICAgICAgICAgIC8vIElmIGEgY29sdW1uIGlzIGludmlzaWJsZSBqdXN0IHNraXAgaXRcbiAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbi52aXNpYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmlnaHRJbnZpc2libGVzKys7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIGNvbHVtbnMgaGVhZGVyIGFuZCBmb290ZXIgZWxlbWVudFxuICAgICAgICAgICAgICAgIHZhciBjb2xIZWFkZXIgPSAkJDEoY29sdW1uLmhlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB2YXIgY29sRm9vdGVyID0gJCQxKGNvbHVtbi5mb290ZXIoKSk7XG4gICAgICAgICAgICAgICAgLy8gR2V0IHRoZSBudW1iZXIgb2YgdmlzaWJsZSBjb2x1bW5zIHRoYXQgY2FtZSBiZWZvcmUgdGhpcyBvbmVcbiAgICAgICAgICAgICAgICB2YXIgcHJldiA9IHByZXZJbnZpc2libGUuZ2V0KGkpO1xuICAgICAgICAgICAgICAgIGlmIChwcmV2ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgaXQgd2Fzbid0IHNldCB0aGVuIGl0IHdhcyB0aGUgbGFzdCBjb2x1bW4gc28ganVzdCB1c2UgdGhlIGZpbmFsIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIHByZXYgPSBpbnZpc2libGVzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaSArIHJpZ2h0SW52aXNpYmxlcyA+PSBudW1Db2xzIC0gdGhpcy5jLnJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICQkMSh0aGlzLnMuZHQudGFibGUoKS5ub2RlKCkpLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy50YWJsZUZpeGVkUmlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnREaXYuYWRkQ2xhc3ModGhpcy5jbGFzc2VzLnRhYmxlRml4ZWRSaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGUgd2lkaHQgb2YgdGhlIHByZXZpb3VzIG5vZGUsIG9ubHkgaWYgd2UgYXJlIG9uIGF0bGVhc3QgdGhlIHNlY29uZCBjb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgKyAxICsgcmlnaHRJbnZpc2libGVzIDwgbnVtQ29scykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZJZHggPSBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2ltcGx5IHVzaW5nIHRoZSBudW1iZXIgb2YgaGlkZGVuIGNvbHVtbnMgZG9lc24ndCB3b3JrIGhlcmUsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgZmlyc3QgaXMgaGlkZGVuIHRoZW4gdGhpcyB3b3VsZCBiZSB0aHJvd24gb2ZmXG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocHJldklkeCArIDEgPCBudW1Db2xzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZDb2wgPSB0aGlzLnMuZHQuY29sdW1uKHByZXZJZHggKyAxLCB7IHBhZ2U6ICdjdXJyZW50JyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJldkNvbC52aXNpYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdFJpZ2h0ICs9ICQkMShwcmV2Q29sLm5vZGVzKClbMF0pLm91dGVyV2lkdGgoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZFJpZ2h0ICs9IHByZXZDb2wuaGVhZGVyKCkgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCQxKHByZXZDb2wuaGVhZGVyKCkpLm91dGVyV2lkdGgoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2Q29sLmZvb3RlcigpID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkJDEocHJldkNvbC5oZWFkZXIoKSkub3V0ZXJXaWR0aCgpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldklkeCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgb3ZlciBhbGwgb2YgdGhlIHJvd3MsIGZpeGluZyB0aGUgY2VsbCB0byB0aGUgcmlnaHRcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2IgPSAwLCByb3dzXzMgPSByb3dzOyBfYiA8IHJvd3NfMy5sZW5ndGg7IF9iKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByb3cgPSByb3dzXzNbX2JdO1xuICAgICAgICAgICAgICAgICAgICAgICAgJCQxKCQkMShyb3cpLmNoaWxkcmVuKClbaSAtIHByZXZdKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jc3ModGhpcy5fZ2V0Q2VsbENTUyhmYWxzZSwgZGlzdFJpZ2h0LCAncmlnaHQnKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYWRkQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkUmlnaHQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGUgY3NzIGZvciB0aGUgaGVhZGVyIGFuZCB0aGUgZm9vdGVyXG4gICAgICAgICAgICAgICAgICAgIGNvbEhlYWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgLmNzcyh0aGlzLl9nZXRDZWxsQ1NTKHRydWUsIGhlYWRSaWdodCwgJ3JpZ2h0JykpXG4gICAgICAgICAgICAgICAgICAgICAgICAuYWRkQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkUmlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBjb2xGb290ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jc3ModGhpcy5fZ2V0Q2VsbENTUyh0cnVlLCBoZWFkUmlnaHQsICdyaWdodCcpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy5maXhlZFJpZ2h0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEl0ZXJpYXRlIHRocm91Z2ggYWxsIG9mIHRoZSByb3dzLCBtYWtpbmcgc3VyZSB0aGV5IGFyZW4ndCBjdXJyZW50bHkgdHJ5aW5nIHRvIGZpeCByaWdodFxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBfYyA9IDAsIHJvd3NfNCA9IHJvd3M7IF9jIDwgcm93c180Lmxlbmd0aDsgX2MrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJvdyA9IHJvd3NfNFtfY107XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9ICQkMSgkJDEocm93KS5jaGlsZHJlbigpW2kgLSBwcmV2XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY2VsbCBpcyB0cnlpbmcgdG8gZml4IHRvIHRoZSByaWdodCwgcmVtb3ZlIHRoZSBjbGFzcyBhbmQgdGhlIGNzc1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNlbGwuaGFzQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkUmlnaHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY3NzKHRoaXMuX2NsZWFyQ2VsbENTUygncmlnaHQnKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUNsYXNzKHRoaXMuY2xhc3Nlcy5maXhlZFJpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGhlYWRlciBmb3IgdGhpcyBjb2x1bW4gaXNuJ3QgZml4ZWQgcmlnaHRcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbEhlYWRlci5oYXNDbGFzcyh0aGlzLmNsYXNzZXMuZml4ZWRSaWdodCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbEhlYWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jc3ModGhpcy5fY2xlYXJDZWxsQ1NTKCdyaWdodCcpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVDbGFzcyh0aGlzLmNsYXNzZXMuZml4ZWRSaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBmb290ZXIgZm9yIHRoaXMgY29sdW1uIGlzbid0IGZpeGVkIHJpZ2h0XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2xGb290ZXIuaGFzQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkUmlnaHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xGb290ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY3NzKHRoaXMuX2NsZWFyQ2VsbENTUygncmlnaHQnKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3ModGhpcy5jbGFzc2VzLmZpeGVkUmlnaHQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgaXMgYSBoZWFkZXIgd2l0aCB0aGUgaW5kZXggY2xhc3MgYW5kIHJlYWRpbmcgcnRsIHRoZW4gYWRkIHJpZ2h0IHRvcCBibG9ja2VyXG4gICAgICAgICAgICBpZiAoaGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnMucnRsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZG9tLnJpZ2h0VG9wQmxvY2tlci5vdXRlckhlaWdodChoZWFkZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnREaXYuYXBwZW5kKHRoaXMuZG9tLnJpZ2h0VG9wQmxvY2tlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRvbS5sZWZ0VG9wQmxvY2tlci5vdXRlckhlaWdodChoZWFkZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnREaXYuYXBwZW5kKHRoaXMuZG9tLmxlZnRUb3BCbG9ja2VyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIGZvb3RlciB3aXRoIHRoZSBpbmRleCBjbGFzcyBhbmQgcmVhZGluZyBydGwgdGhlbiBhZGQgcmlnaHQgYm90dG9tIGJsb2NrZXJcbiAgICAgICAgICAgIGlmIChmb290ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMucy5ydGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kb20ucmlnaHRCb3R0b21CbG9ja2VyLm91dGVySGVpZ2h0KGZvb3RlckhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudERpdi5hcHBlbmQodGhpcy5kb20ucmlnaHRCb3R0b21CbG9ja2VyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZG9tLmxlZnRCb3R0b21CbG9ja2VyLm91dGVySGVpZ2h0KGZvb3RlckhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudERpdi5hcHBlbmQodGhpcy5kb20ubGVmdEJvdHRvbUJsb2NrZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENsZWFuIHVwXG4gICAgICAgICAqL1xuICAgICAgICBGaXhlZENvbHVtbnMucHJvdG90eXBlLl9kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5zLmR0Lm9mZignLmR0ZmMnKTtcbiAgICAgICAgICAgIHRoaXMuZG9tLmxlZnRCb3R0b21CbG9ja2VyLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy5kb20ubGVmdFRvcEJsb2NrZXIucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLmRvbS5yaWdodEJvdHRvbUJsb2NrZXIucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLmRvbS5yaWdodFRvcEJsb2NrZXIucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXRzIHRoZSBjb3JyZWN0IENTUyBmb3IgdGhlIGNlbGwsIGhlYWRlciBvciBmb290ZXIgYmFzZWQgb24gb3B0aW9ucyBwcm92aWRlZFxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaGVhZGVyIFdoZXRoZXIgdGhpcyBjZWxsIGlzIGEgaGVhZGVyIG9yIGEgZm9vdGVyXG4gICAgICAgICAqIEBwYXJhbSBkaXN0IFRoZSBkaXN0YW5jZSB0aGF0IHRoZSBjZWxsIHNob3VsZCBiZSBtb3ZlZCBhd2F5IGZyb20gdGhlIGVkZ2VcbiAgICAgICAgICogQHBhcmFtIGxyIEluZGljYXRvciBvZiBmaXhpbmcgdG8gdGhlIGxlZnQgb3IgdGhlIHJpZ2h0XG4gICAgICAgICAqIEByZXR1cm5zIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBjb3JyZWN0IGNzc1xuICAgICAgICAgKi9cbiAgICAgICAgRml4ZWRDb2x1bW5zLnByb3RvdHlwZS5fZ2V0Q2VsbENTUyA9IGZ1bmN0aW9uIChoZWFkZXIsIGRpc3QsIGxyKSB7XG4gICAgICAgICAgICBpZiAobHIgPT09ICdsZWZ0Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnMucnRsXG4gICAgICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246ICdzdGlja3knLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGRpc3QgKyAncHgnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBkaXN0ICsgJ3B4JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnc3RpY2t5J1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucy5ydGxcbiAgICAgICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBkaXN0ICsgKGhlYWRlciA/IHRoaXMucy5iYXJXaWR0aCA6IDApICsgJ3B4JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnc3RpY2t5J1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246ICdzdGlja3knLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGRpc3QgKyAoaGVhZGVyID8gdGhpcy5zLmJhcldpZHRoIDogMCkgKyAncHgnXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXRzIHRoZSBjc3MgdGhhdCBpcyByZXF1aXJlZCB0byBjbGVhciB0aGUgZml4aW5nIHRvIGEgc2lkZVxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbHIgSW5kaWNhdG9yIG9mIGZpeGluZyB0byB0aGUgbGVmdCBvciB0aGUgcmlnaHRcbiAgICAgICAgICogQHJldHVybnMgQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNvcnJlY3QgY3NzXG4gICAgICAgICAqL1xuICAgICAgICBGaXhlZENvbHVtbnMucHJvdG90eXBlLl9jbGVhckNlbGxDU1MgPSBmdW5jdGlvbiAobHIpIHtcbiAgICAgICAgICAgIGlmIChsciA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLnMucnRsID9cbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogJydcbiAgICAgICAgICAgICAgICAgICAgfSA6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0OiAnJ1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLnMucnRsID9cbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6ICcnXG4gICAgICAgICAgICAgICAgICAgIH0gOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnJ1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBGaXhlZENvbHVtbnMucHJvdG90eXBlLl9zZXRLZXlUYWJsZUxpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMucy5kdC5vbigna2V5LWZvY3VzLmR0LmR0ZmMnLCBmdW5jdGlvbiAoZSwgZHQsIGNlbGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2VsbFBvcyA9ICQkMShjZWxsLm5vZGUoKSkub2Zmc2V0KCk7XG4gICAgICAgICAgICAgICAgdmFyIHNjcm9sbCA9ICQkMSgkJDEoX3RoaXMucy5kdC50YWJsZSgpLm5vZGUoKSkuY2xvc2VzdCgnZGl2LmRhdGFUYWJsZXNfc2Nyb2xsQm9keScpKTtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgZml4ZWQgY29sdW1ucyB0byB0aGUgbGVmdFxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jLmxlZnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgcmlnaHRtb3N0IGxlZnQgZml4ZWQgY29sdW1uIGhlYWRlciwgaXQncyBwb3NpdGlvbiBhbmQgaXQncyB3aWR0aFxuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHRNb3N0ID0gJCQxKF90aGlzLnMuZHQuY29sdW1uKF90aGlzLmMubGVmdCAtIDEpLmhlYWRlcigpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0TW9zdFBvcyA9IHJpZ2h0TW9zdC5vZmZzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0TW9zdFdpZHRoID0gcmlnaHRNb3N0Lm91dGVyV2lkdGgoKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGN1cnJlbnQgaGlnaGxpZ2h0ZWQgY2VsbCBpcyBsZWZ0IG9mIHRoZSByaWdodG1vc3QgY2VsbCBvbiB0aGUgc2NyZWVuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjZWxsUG9zLmxlZnQgPCByaWdodE1vc3RQb3MubGVmdCArIHJpZ2h0TW9zdFdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTY3JvbGwgaXQgaW50byB2aWV3XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY3VyclNjcm9sbCA9IHNjcm9sbC5zY3JvbGxMZWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGwuc2Nyb2xsTGVmdChjdXJyU2Nyb2xsIC0gKHJpZ2h0TW9zdFBvcy5sZWZ0ICsgcmlnaHRNb3N0V2lkdGggLSBjZWxsUG9zLmxlZnQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgZml4ZWQgY29sdW1ucyB0byB0aGUgcmlnaHRcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYy5yaWdodCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSBudW1iZXIgb2YgY29sdW1ucyBhbmQgdGhlIHdpZHRoIG9mIHRoZSBjZWxsIGFzIGRvaW5nIHJpZ2h0IHNpZGUgY2FsY1xuICAgICAgICAgICAgICAgICAgICB2YXIgbnVtQ29scyA9IF90aGlzLnMuZHQuY29sdW1ucygpLmRhdGEoKS50b0FycmF5KCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbFdpZHRoID0gJCQxKGNlbGwubm9kZSgpKS5vdXRlcldpZHRoKCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgbGVmdG1vc3QgcmlnaHQgZml4ZWQgY29sdW1uIGhlYWRlciBhbmQgaXQncyBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE1vc3QgPSAkJDEoX3RoaXMucy5kdC5jb2x1bW4obnVtQ29scyAtIF90aGlzLmMucmlnaHQpLmhlYWRlcigpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnRNb3N0UG9zID0gbGVmdE1vc3Qub2Zmc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBjdXJyZW50IGhpZ2hsaWdodGVkIGNlbGwgaXMgcmlnaHQgb2YgdGhlIGxlZnRtb3N0IGNlbGwgb24gdGhlIHNjcmVlblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2VsbFBvcy5sZWZ0ICsgY2VsbFdpZHRoID4gbGVmdE1vc3RQb3MubGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Nyb2xsIGl0IGludG8gdmlld1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJTY3JvbGwgPSBzY3JvbGwuc2Nyb2xsTGVmdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsLnNjcm9sbExlZnQoY3VyclNjcm9sbCAtIChsZWZ0TW9zdFBvcy5sZWZ0IC0gKGNlbGxQb3MubGVmdCArIGNlbGxXaWR0aCkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gV2hlbmV2ZXIgYSBkcmF3IG9jY3VycyB0aGVyZSBpcyBwb3RlbnRpYWwgZm9yIHRoZSBkYXRhIHRvIGhhdmUgY2hhbmdlZCBhbmQgdGhlcmVmb3JlIGFsc28gdGhlIGNvbHVtbiB3aWR0aHNcbiAgICAgICAgICAgIC8vIFRoZXJlZm9yZSBpdCBpcyBuZWNlc3NhcnkgdG8gcmVjYWxjdWxhdGUgdGhlIHZhbHVlcyBmb3IgdGhlIGZpeGVkIGNvbHVtbnNcbiAgICAgICAgICAgIHRoaXMucy5kdC5vbignZHJhdy5kdC5kdGZjJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLl9hZGRTdHlsZXMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zLmR0Lm9uKCdjb2x1bW4tcmVvcmRlci5kdC5kdGZjJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLl9hZGRTdHlsZXMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zLmR0Lm9uKCdjb2x1bW4tdmlzaWJpbGl0eS5kdC5kdGZjJywgZnVuY3Rpb24gKGUsIHNldHRpbmdzLCBjb2x1bW4sIHN0YXRlLCByZWNhbGMpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVjYWxjICYmICFzZXR0aW5ncy5iRGVzdHJveWluZykge1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLl9hZGRTdHlsZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgNTApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBGaXhlZENvbHVtbnMudmVyc2lvbiA9ICc0LjMuMCc7XG4gICAgICAgIEZpeGVkQ29sdW1ucy5jbGFzc2VzID0ge1xuICAgICAgICAgICAgZml4ZWRMZWZ0OiAnZHRmYy1maXhlZC1sZWZ0JyxcbiAgICAgICAgICAgIGZpeGVkUmlnaHQ6ICdkdGZjLWZpeGVkLXJpZ2h0JyxcbiAgICAgICAgICAgIGxlZnRCb3R0b21CbG9ja2VyOiAnZHRmYy1sZWZ0LWJvdHRvbS1ibG9ja2VyJyxcbiAgICAgICAgICAgIGxlZnRUb3BCbG9ja2VyOiAnZHRmYy1sZWZ0LXRvcC1ibG9ja2VyJyxcbiAgICAgICAgICAgIHJpZ2h0Qm90dG9tQmxvY2tlcjogJ2R0ZmMtcmlnaHQtYm90dG9tLWJsb2NrZXInLFxuICAgICAgICAgICAgcmlnaHRUb3BCbG9ja2VyOiAnZHRmYy1yaWdodC10b3AtYmxvY2tlcicsXG4gICAgICAgICAgICB0YWJsZUZpeGVkTGVmdDogJ2R0ZmMtaGFzLWxlZnQnLFxuICAgICAgICAgICAgdGFibGVGaXhlZFJpZ2h0OiAnZHRmYy1oYXMtcmlnaHQnXG4gICAgICAgIH07XG4gICAgICAgIEZpeGVkQ29sdW1ucy5kZWZhdWx0cyA9IHtcbiAgICAgICAgICAgIGkxOG46IHtcbiAgICAgICAgICAgICAgICBidXR0b246ICdGaXhlZENvbHVtbnMnXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGVmdDogMSxcbiAgICAgICAgICAgIHJpZ2h0OiAwXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBGaXhlZENvbHVtbnM7XG4gICAgfSgpKTtcblxuICAgIC8qISBGaXhlZENvbHVtbnMgNC4zLjBcbiAgICAgKiDCqSBTcHJ5TWVkaWEgTHRkIC0gZGF0YXRhYmxlcy5uZXQvbGljZW5zZVxuICAgICAqL1xuICAgIHNldEpRdWVyeSgkKTtcbiAgICAkLmZuLmRhdGFUYWJsZS5GaXhlZENvbHVtbnMgPSBGaXhlZENvbHVtbnM7XG4gICAgJC5mbi5EYXRhVGFibGUuRml4ZWRDb2x1bW5zID0gRml4ZWRDb2x1bW5zO1xuICAgIHZhciBhcGlSZWdpc3RlciA9IERhdGFUYWJsZS5BcGkucmVnaXN0ZXI7XG4gICAgYXBpUmVnaXN0ZXIoJ2ZpeGVkQ29sdW1ucygpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9KTtcbiAgICBhcGlSZWdpc3RlcignZml4ZWRDb2x1bW5zKCkubGVmdCgpJywgZnVuY3Rpb24gKG5ld1ZhbCkge1xuICAgICAgICB2YXIgY3R4ID0gdGhpcy5jb250ZXh0WzBdO1xuICAgICAgICBpZiAobmV3VmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGN0eC5fZml4ZWRDb2x1bW5zLmxlZnQobmV3VmFsKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGN0eC5fZml4ZWRDb2x1bW5zLmxlZnQoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGFwaVJlZ2lzdGVyKCdmaXhlZENvbHVtbnMoKS5yaWdodCgpJywgZnVuY3Rpb24gKG5ld1ZhbCkge1xuICAgICAgICB2YXIgY3R4ID0gdGhpcy5jb250ZXh0WzBdO1xuICAgICAgICBpZiAobmV3VmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGN0eC5fZml4ZWRDb2x1bW5zLnJpZ2h0KG5ld1ZhbCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBjdHguX2ZpeGVkQ29sdW1ucy5yaWdodCgpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgRGF0YVRhYmxlLmV4dC5idXR0b25zLmZpeGVkQ29sdW1ucyA9IHtcbiAgICAgICAgYWN0aW9uOiBmdW5jdGlvbiAoZSwgZHQsIG5vZGUsIGNvbmZpZykge1xuICAgICAgICAgICAgaWYgKCQobm9kZSkuYXR0cignYWN0aXZlJykpIHtcbiAgICAgICAgICAgICAgICAkKG5vZGUpLnJlbW92ZUF0dHIoJ2FjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgICAgICBkdC5maXhlZENvbHVtbnMoKS5sZWZ0KDApO1xuICAgICAgICAgICAgICAgIGR0LmZpeGVkQ29sdW1ucygpLnJpZ2h0KDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgJChub2RlKS5hdHRyKCdhY3RpdmUnLCAndHJ1ZScpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgICAgICBkdC5maXhlZENvbHVtbnMoKS5sZWZ0KGNvbmZpZy5jb25maWcubGVmdCk7XG4gICAgICAgICAgICAgICAgZHQuZml4ZWRDb2x1bW5zKCkucmlnaHQoY29uZmlnLmNvbmZpZy5yaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNvbmZpZzoge1xuICAgICAgICAgICAgbGVmdDogMSxcbiAgICAgICAgICAgIHJpZ2h0OiAwXG4gICAgICAgIH0sXG4gICAgICAgIGluaXQ6IGZ1bmN0aW9uIChkdCwgbm9kZSwgY29uZmlnKSB7XG4gICAgICAgICAgICBpZiAoZHQuc2V0dGluZ3MoKVswXS5fZml4ZWRDb2x1bW5zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBfaW5pdChkdC5zZXR0aW5ncygpLCBjb25maWcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJChub2RlKS5hdHRyKCdhY3RpdmUnLCAndHJ1ZScpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgIGR0LmJ1dHRvbihub2RlKS50ZXh0KGNvbmZpZy50ZXh0IHx8IGR0LmkxOG4oJ2J1dHRvbnMuZml4ZWRDb2x1bW5zJywgZHQuc2V0dGluZ3MoKVswXS5fZml4ZWRDb2x1bW5zLmMuaTE4bi5idXR0b24pKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGV4dDogbnVsbFxuICAgIH07XG4gICAgZnVuY3Rpb24gX2luaXQoc2V0dGluZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0gbnVsbDsgfVxuICAgICAgICB2YXIgYXBpID0gbmV3IERhdGFUYWJsZS5BcGkoc2V0dGluZ3MpO1xuICAgICAgICB2YXIgb3B0cyA9IG9wdGlvbnNcbiAgICAgICAgICAgID8gb3B0aW9uc1xuICAgICAgICAgICAgOiBhcGkuaW5pdCgpLmZpeGVkQ29sdW1ucyB8fCBEYXRhVGFibGUuZGVmYXVsdHMuZml4ZWRDb2x1bW5zO1xuICAgICAgICB2YXIgZml4ZWRDb2x1bW5zID0gbmV3IEZpeGVkQ29sdW1ucyhhcGksIG9wdHMpO1xuICAgICAgICByZXR1cm4gZml4ZWRDb2x1bW5zO1xuICAgIH1cbiAgICAvLyBBdHRhY2ggYSBsaXN0ZW5lciB0byB0aGUgZG9jdW1lbnQgd2hpY2ggbGlzdGVucyBmb3IgRGF0YVRhYmxlcyBpbml0aWFsaXNhdGlvblxuICAgIC8vIGV2ZW50cyBzbyB3ZSBjYW4gYXV0b21hdGljYWxseSBpbml0aWFsaXNlXG4gICAgJChkb2N1bWVudCkub24oJ3BsdWdpbi1pbml0LmR0JywgZnVuY3Rpb24gKGUsIHNldHRpbmdzKSB7XG4gICAgICAgIGlmIChlLm5hbWVzcGFjZSAhPT0gJ2R0Jykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZXR0aW5ncy5vSW5pdC5maXhlZENvbHVtbnMgfHxcbiAgICAgICAgICAgIERhdGFUYWJsZS5kZWZhdWx0cy5maXhlZENvbHVtbnMpIHtcbiAgICAgICAgICAgIGlmICghc2V0dGluZ3MuX2ZpeGVkQ29sdW1ucykge1xuICAgICAgICAgICAgICAgIF9pbml0KHNldHRpbmdzLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG59KCkpO1xuXG5cbmV4cG9ydCBkZWZhdWx0IERhdGFUYWJsZTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-fixedcolumns/js/dataTables.fixedColumns.mjs\n"); /***/ }), /***/ "./node_modules/datatables.net/js/jquery.dataTables.mjs": /*!**************************************************************!*\ !*** ./node_modules/datatables.net/js/jquery.dataTables.mjs ***! \**************************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\");\n/*! DataTables 1.13.11\n * ©2008-2024 SpryMedia Ltd - datatables.net/license\n */\n\n\n\n// DataTables code uses $ internally, but we want to be able to\n// reassign $ with the `use` method, so it is a regular var.\nvar $ = jquery__WEBPACK_IMPORTED_MODULE_0__;\n\n\nvar DataTable = function ( selector, options )\n{\n\t// Check if called with a window or jQuery object for DOM less applications\n\t// This is for backwards compatibility\n\tif (DataTable.factory(selector, options)) {\n\t\treturn DataTable;\n\t}\n\n\t// When creating with `new`, create a new DataTable, returning the API instance\n\tif (this instanceof DataTable) {\n\t\treturn $(selector).DataTable(options);\n\t}\n\telse {\n\t\t// Argument switching\n\t\toptions = selector;\n\t}\n\n\t/**\n\t * Perform a jQuery selector action on the table's TR elements (from the tbody) and\n\t * return the resulting jQuery object.\n\t * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on\n\t * @param {object} [oOpts] Optional parameters for modifying the rows to be included\n\t * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter\n\t * criterion (\"applied\") or all TR elements (i.e. no filter).\n\t * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.\n\t * Can be either 'current', whereby the current sorting of the table is used, or\n\t * 'original' whereby the original order the data was read into the table is used.\n\t * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page\n\t * (\"current\") or not (\"all\"). If 'current' is given, then order is assumed to be\n\t * 'current' and filter is 'applied', regardless of what they might be given as.\n\t * @returns {object} jQuery object, filtered by the given selector.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Highlight every second row\n\t * oTable.$('tr:odd').css('backgroundColor', 'blue');\n\t * } );\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Filter to rows with 'Webkit' in them, add a background colour and then\n\t * // remove the filter, thus highlighting the 'Webkit' rows only.\n\t * oTable.fnFilter('Webkit');\n\t * oTable.$('tr', {\"search\": \"applied\"}).css('backgroundColor', 'blue');\n\t * oTable.fnFilter('');\n\t * } );\n\t */\n\tthis.$ = function ( sSelector, oOpts )\n\t{\n\t\treturn this.api(true).$( sSelector, oOpts );\n\t};\n\t\n\t\n\t/**\n\t * Almost identical to $ in operation, but in this case returns the data for the matched\n\t * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes\n\t * rather than any descendants, so the data can be obtained for the row/cell. If matching\n\t * rows are found, the data returned is the original data array/object that was used to\n\t * create the row (or a generated array if from a DOM source).\n\t *\n\t * This method is often useful in-combination with $ where both functions are given the\n\t * same parameters and the array indexes will match identically.\n\t * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on\n\t * @param {object} [oOpts] Optional parameters for modifying the rows to be included\n\t * @param {string} [oOpts.filter=none] Select elements that meet the current filter\n\t * criterion (\"applied\") or all elements (i.e. no filter).\n\t * @param {string} [oOpts.order=current] Order of the data in the processed array.\n\t * Can be either 'current', whereby the current sorting of the table is used, or\n\t * 'original' whereby the original order the data was read into the table is used.\n\t * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page\n\t * (\"current\") or not (\"all\"). If 'current' is given, then order is assumed to be\n\t * 'current' and filter is 'applied', regardless of what they might be given as.\n\t * @returns {array} Data for the matched elements. If any elements, as a result of the\n\t * selector, were not TR, TD or TH elements in the DataTable, they will have a null\n\t * entry in the array.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Get the data from the first row in the table\n\t * var data = oTable._('tr:first');\n\t *\n\t * // Do something useful with the data\n\t * alert( \"First cell is: \"+data[0] );\n\t * } );\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Filter to 'Webkit' and get all data for\n\t * oTable.fnFilter('Webkit');\n\t * var data = oTable._('tr', {\"search\": \"applied\"});\n\t *\n\t * // Do something with the data\n\t * alert( data.length+\" rows matched the search\" );\n\t * } );\n\t */\n\tthis._ = function ( sSelector, oOpts )\n\t{\n\t\treturn this.api(true).rows( sSelector, oOpts ).data();\n\t};\n\t\n\t\n\t/**\n\t * Create a DataTables Api instance, with the currently selected tables for\n\t * the Api's context.\n\t * @param {boolean} [traditional=false] Set the API instance's context to be\n\t * only the table referred to by the `DataTable.ext.iApiIndex` option, as was\n\t * used in the API presented by DataTables 1.9- (i.e. the traditional mode),\n\t * or if all tables captured in the jQuery object should be used.\n\t * @return {DataTables.Api}\n\t */\n\tthis.api = function ( traditional )\n\t{\n\t\treturn traditional ?\n\t\t\tnew _Api(\n\t\t\t\t_fnSettingsFromNode( this[ _ext.iApiIndex ] )\n\t\t\t) :\n\t\t\tnew _Api( this );\n\t};\n\t\n\t\n\t/**\n\t * Add a single new row or multiple rows of data to the table. Please note\n\t * that this is suitable for client-side processing only - if you are using\n\t * server-side processing (i.e. \"bServerSide\": true), then to add data, you\n\t * must add it to the data source, i.e. the server-side, through an Ajax call.\n\t * @param {array|object} data The data to be added to the table. This can be:\n\t *
        \n\t *
      • 1D array of data - add a single row with the data provided
      • \n\t *
      • 2D array of arrays - add multiple rows in a single call
      • \n\t *
      • object - data object when using mData
      • \n\t *
      • array of objects - multiple data objects when using mData
      • \n\t *
      \n\t * @param {bool} [redraw=true] redraw the table or not\n\t * @returns {array} An array of integers, representing the list of indexes in\n\t * aoData ({@link DataTable.models.oSettings}) that have been added to\n\t * the table.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * // Global var for counter\n\t * var giCount = 2;\n\t *\n\t * $(document).ready(function() {\n\t * $('#example').dataTable();\n\t * } );\n\t *\n\t * function fnClickAddRow() {\n\t * $('#example').dataTable().fnAddData( [\n\t * giCount+\".1\",\n\t * giCount+\".2\",\n\t * giCount+\".3\",\n\t * giCount+\".4\" ]\n\t * );\n\t *\n\t * giCount++;\n\t * }\n\t */\n\tthis.fnAddData = function( data, redraw )\n\t{\n\t\tvar api = this.api( true );\n\t\n\t\t/* Check if we want to add multiple rows or not */\n\t\tvar rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?\n\t\t\tapi.rows.add( data ) :\n\t\t\tapi.row.add( data );\n\t\n\t\tif ( redraw === undefined || redraw ) {\n\t\t\tapi.draw();\n\t\t}\n\t\n\t\treturn rows.flatten().toArray();\n\t};\n\t\n\t\n\t/**\n\t * This function will make DataTables recalculate the column sizes, based on the data\n\t * contained in the table and the sizes applied to the columns (in the DOM, CSS or\n\t * through the sWidth parameter). This can be useful when the width of the table's\n\t * parent element changes (for example a window resize).\n\t * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable( {\n\t * \"sScrollY\": \"200px\",\n\t * \"bPaginate\": false\n\t * } );\n\t *\n\t * $(window).on('resize', function () {\n\t * oTable.fnAdjustColumnSizing();\n\t * } );\n\t * } );\n\t */\n\tthis.fnAdjustColumnSizing = function ( bRedraw )\n\t{\n\t\tvar api = this.api( true ).columns.adjust();\n\t\tvar settings = api.settings()[0];\n\t\tvar scroll = settings.oScroll;\n\t\n\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\tapi.draw( false );\n\t\t}\n\t\telse if ( scroll.sX !== \"\" || scroll.sY !== \"\" ) {\n\t\t\t/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */\n\t\t\t_fnScrollDraw( settings );\n\t\t}\n\t};\n\t\n\t\n\t/**\n\t * Quickly and simply clear a table\n\t * @param {bool} [bRedraw=true] redraw the table or not\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)\n\t * oTable.fnClearTable();\n\t * } );\n\t */\n\tthis.fnClearTable = function( bRedraw )\n\t{\n\t\tvar api = this.api( true ).clear();\n\t\n\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\tapi.draw();\n\t\t}\n\t};\n\t\n\t\n\t/**\n\t * The exact opposite of 'opening' a row, this function will close any rows which\n\t * are currently 'open'.\n\t * @param {node} nTr the table row to 'close'\n\t * @returns {int} 0 on success, or 1 if failed (can't find the row)\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable;\n\t *\n\t * // 'open' an information row when a row is clicked on\n\t * $('#example tbody tr').click( function () {\n\t * if ( oTable.fnIsOpen(this) ) {\n\t * oTable.fnClose( this );\n\t * } else {\n\t * oTable.fnOpen( this, \"Temporary row opened\", \"info_row\" );\n\t * }\n\t * } );\n\t *\n\t * oTable = $('#example').dataTable();\n\t * } );\n\t */\n\tthis.fnClose = function( nTr )\n\t{\n\t\tthis.api( true ).row( nTr ).child.hide();\n\t};\n\t\n\t\n\t/**\n\t * Remove a row for the table\n\t * @param {mixed} target The index of the row from aoData to be deleted, or\n\t * the TR element you want to delete\n\t * @param {function|null} [callBack] Callback function\n\t * @param {bool} [redraw=true] Redraw the table or not\n\t * @returns {array} The row that was deleted\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Immediately remove the first row\n\t * oTable.fnDeleteRow( 0 );\n\t * } );\n\t */\n\tthis.fnDeleteRow = function( target, callback, redraw )\n\t{\n\t\tvar api = this.api( true );\n\t\tvar rows = api.rows( target );\n\t\tvar settings = rows.settings()[0];\n\t\tvar data = settings.aoData[ rows[0][0] ];\n\t\n\t\trows.remove();\n\t\n\t\tif ( callback ) {\n\t\t\tcallback.call( this, settings, data );\n\t\t}\n\t\n\t\tif ( redraw === undefined || redraw ) {\n\t\t\tapi.draw();\n\t\t}\n\t\n\t\treturn data;\n\t};\n\t\n\t\n\t/**\n\t * Restore the table to it's original state in the DOM by removing all of DataTables\n\t * enhancements, alterations to the DOM structure of the table and event listeners.\n\t * @param {boolean} [remove=false] Completely remove the table from the DOM\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * // This example is fairly pointless in reality, but shows how fnDestroy can be used\n\t * var oTable = $('#example').dataTable();\n\t * oTable.fnDestroy();\n\t * } );\n\t */\n\tthis.fnDestroy = function ( remove )\n\t{\n\t\tthis.api( true ).destroy( remove );\n\t};\n\t\n\t\n\t/**\n\t * Redraw the table\n\t * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)\n\t * oTable.fnDraw();\n\t * } );\n\t */\n\tthis.fnDraw = function( complete )\n\t{\n\t\t// Note that this isn't an exact match to the old call to _fnDraw - it takes\n\t\t// into account the new data, but can hold position.\n\t\tthis.api( true ).draw( complete );\n\t};\n\t\n\t\n\t/**\n\t * Filter the input based on data\n\t * @param {string} sInput String to filter the table on\n\t * @param {int|null} [iColumn] Column to limit filtering to\n\t * @param {bool} [bRegex=false] Treat as regular expression or not\n\t * @param {bool} [bSmart=true] Perform smart filtering or not\n\t * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)\n\t * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Sometime later - filter...\n\t * oTable.fnFilter( 'test string' );\n\t * } );\n\t */\n\tthis.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )\n\t{\n\t\tvar api = this.api( true );\n\t\n\t\tif ( iColumn === null || iColumn === undefined ) {\n\t\t\tapi.search( sInput, bRegex, bSmart, bCaseInsensitive );\n\t\t}\n\t\telse {\n\t\t\tapi.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );\n\t\t}\n\t\n\t\tapi.draw();\n\t};\n\t\n\t\n\t/**\n\t * Get the data for the whole table, an individual row or an individual cell based on the\n\t * provided parameters.\n\t * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as\n\t * a TR node then the data source for the whole row will be returned. If given as a\n\t * TD/TH cell node then iCol will be automatically calculated and the data for the\n\t * cell returned. If given as an integer, then this is treated as the aoData internal\n\t * data index for the row (see fnGetPosition) and the data for that row used.\n\t * @param {int} [col] Optional column index that you want the data of.\n\t * @returns {array|object|string} If mRow is undefined, then the data for all rows is\n\t * returned. If mRow is defined, just data for that row, and is iCol is\n\t * defined, only data for the designated cell is returned.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * // Row data\n\t * $(document).ready(function() {\n\t * oTable = $('#example').dataTable();\n\t *\n\t * oTable.$('tr').click( function () {\n\t * var data = oTable.fnGetData( this );\n\t * // ... do something with the array / object of data for the row\n\t * } );\n\t * } );\n\t *\n\t * @example\n\t * // Individual cell data\n\t * $(document).ready(function() {\n\t * oTable = $('#example').dataTable();\n\t *\n\t * oTable.$('td').click( function () {\n\t * var sData = oTable.fnGetData( this );\n\t * alert( 'The cell clicked on had the value of '+sData );\n\t * } );\n\t * } );\n\t */\n\tthis.fnGetData = function( src, col )\n\t{\n\t\tvar api = this.api( true );\n\t\n\t\tif ( src !== undefined ) {\n\t\t\tvar type = src.nodeName ? src.nodeName.toLowerCase() : '';\n\t\n\t\t\treturn col !== undefined || type == 'td' || type == 'th' ?\n\t\t\t\tapi.cell( src, col ).data() :\n\t\t\t\tapi.row( src ).data() || null;\n\t\t}\n\t\n\t\treturn api.data().toArray();\n\t};\n\t\n\t\n\t/**\n\t * Get an array of the TR nodes that are used in the table's body. Note that you will\n\t * typically want to use the '$' API method in preference to this as it is more\n\t * flexible.\n\t * @param {int} [iRow] Optional row index for the TR element you want\n\t * @returns {array|node} If iRow is undefined, returns an array of all TR elements\n\t * in the table's body, or iRow is defined, just the TR element requested.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Get the nodes from the table\n\t * var nNodes = oTable.fnGetNodes( );\n\t * } );\n\t */\n\tthis.fnGetNodes = function( iRow )\n\t{\n\t\tvar api = this.api( true );\n\t\n\t\treturn iRow !== undefined ?\n\t\t\tapi.row( iRow ).node() :\n\t\t\tapi.rows().nodes().flatten().toArray();\n\t};\n\t\n\t\n\t/**\n\t * Get the array indexes of a particular cell from it's DOM element\n\t * and column index including hidden columns\n\t * @param {node} node this can either be a TR, TD or TH in the table's body\n\t * @returns {int} If nNode is given as a TR, then a single index is returned, or\n\t * if given as a cell, an array of [row index, column index (visible),\n\t * column index (all)] is given.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * $('#example tbody td').click( function () {\n\t * // Get the position of the current data from the node\n\t * var aPos = oTable.fnGetPosition( this );\n\t *\n\t * // Get the data array for this row\n\t * var aData = oTable.fnGetData( aPos[0] );\n\t *\n\t * // Update the data array and return the value\n\t * aData[ aPos[1] ] = 'clicked';\n\t * this.innerHTML = 'clicked';\n\t * } );\n\t *\n\t * // Init DataTables\n\t * oTable = $('#example').dataTable();\n\t * } );\n\t */\n\tthis.fnGetPosition = function( node )\n\t{\n\t\tvar api = this.api( true );\n\t\tvar nodeName = node.nodeName.toUpperCase();\n\t\n\t\tif ( nodeName == 'TR' ) {\n\t\t\treturn api.row( node ).index();\n\t\t}\n\t\telse if ( nodeName == 'TD' || nodeName == 'TH' ) {\n\t\t\tvar cell = api.cell( node ).index();\n\t\n\t\t\treturn [\n\t\t\t\tcell.row,\n\t\t\t\tcell.columnVisible,\n\t\t\t\tcell.column\n\t\t\t];\n\t\t}\n\t\treturn null;\n\t};\n\t\n\t\n\t/**\n\t * Check to see if a row is 'open' or not.\n\t * @param {node} nTr the table row to check\n\t * @returns {boolean} true if the row is currently open, false otherwise\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable;\n\t *\n\t * // 'open' an information row when a row is clicked on\n\t * $('#example tbody tr').click( function () {\n\t * if ( oTable.fnIsOpen(this) ) {\n\t * oTable.fnClose( this );\n\t * } else {\n\t * oTable.fnOpen( this, \"Temporary row opened\", \"info_row\" );\n\t * }\n\t * } );\n\t *\n\t * oTable = $('#example').dataTable();\n\t * } );\n\t */\n\tthis.fnIsOpen = function( nTr )\n\t{\n\t\treturn this.api( true ).row( nTr ).child.isShown();\n\t};\n\t\n\t\n\t/**\n\t * This function will place a new row directly after a row which is currently\n\t * on display on the page, with the HTML contents that is passed into the\n\t * function. This can be used, for example, to ask for confirmation that a\n\t * particular record should be deleted.\n\t * @param {node} nTr The table row to 'open'\n\t * @param {string|node|jQuery} mHtml The HTML to put into the row\n\t * @param {string} sClass Class to give the new TD cell\n\t * @returns {node} The row opened. Note that if the table row passed in as the\n\t * first parameter, is not found in the table, this method will silently\n\t * return.\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable;\n\t *\n\t * // 'open' an information row when a row is clicked on\n\t * $('#example tbody tr').click( function () {\n\t * if ( oTable.fnIsOpen(this) ) {\n\t * oTable.fnClose( this );\n\t * } else {\n\t * oTable.fnOpen( this, \"Temporary row opened\", \"info_row\" );\n\t * }\n\t * } );\n\t *\n\t * oTable = $('#example').dataTable();\n\t * } );\n\t */\n\tthis.fnOpen = function( nTr, mHtml, sClass )\n\t{\n\t\treturn this.api( true )\n\t\t\t.row( nTr )\n\t\t\t.child( mHtml, sClass )\n\t\t\t.show()\n\t\t\t.child()[0];\n\t};\n\t\n\t\n\t/**\n\t * Change the pagination - provides the internal logic for pagination in a simple API\n\t * function. With this function you can have a DataTables table go to the next,\n\t * previous, first or last pages.\n\t * @param {string|int} mAction Paging action to take: \"first\", \"previous\", \"next\" or \"last\"\n\t * or page number to jump to (integer), note that page 0 is the first page.\n\t * @param {bool} [bRedraw=true] Redraw the table or not\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t * oTable.fnPageChange( 'next' );\n\t * } );\n\t */\n\tthis.fnPageChange = function ( mAction, bRedraw )\n\t{\n\t\tvar api = this.api( true ).page( mAction );\n\t\n\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\tapi.draw(false);\n\t\t}\n\t};\n\t\n\t\n\t/**\n\t * Show a particular column\n\t * @param {int} iCol The column whose display should be changed\n\t * @param {bool} bShow Show (true) or hide (false) the column\n\t * @param {bool} [bRedraw=true] Redraw the table or not\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Hide the second column after initialisation\n\t * oTable.fnSetColumnVis( 1, false );\n\t * } );\n\t */\n\tthis.fnSetColumnVis = function ( iCol, bShow, bRedraw )\n\t{\n\t\tvar api = this.api( true ).column( iCol ).visible( bShow );\n\t\n\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\tapi.columns.adjust().draw();\n\t\t}\n\t};\n\t\n\t\n\t/**\n\t * Get the settings for a particular table for external manipulation\n\t * @returns {object} DataTables settings object. See\n\t * {@link DataTable.models.oSettings}\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t * var oSettings = oTable.fnSettings();\n\t *\n\t * // Show an example parameter from the settings\n\t * alert( oSettings._iDisplayStart );\n\t * } );\n\t */\n\tthis.fnSettings = function()\n\t{\n\t\treturn _fnSettingsFromNode( this[_ext.iApiIndex] );\n\t};\n\t\n\t\n\t/**\n\t * Sort the table by a particular column\n\t * @param {int} iCol the data index to sort on. Note that this will not match the\n\t * 'display index' if you have hidden data entries\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Sort immediately with columns 0 and 1\n\t * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );\n\t * } );\n\t */\n\tthis.fnSort = function( aaSort )\n\t{\n\t\tthis.api( true ).order( aaSort ).draw();\n\t};\n\t\n\t\n\t/**\n\t * Attach a sort listener to an element for a given column\n\t * @param {node} nNode the element to attach the sort listener to\n\t * @param {int} iColumn the column that a click on this node will sort on\n\t * @param {function} [fnCallback] callback function when sort is run\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t *\n\t * // Sort on column 1, when 'sorter' is clicked on\n\t * oTable.fnSortListener( document.getElementById('sorter'), 1 );\n\t * } );\n\t */\n\tthis.fnSortListener = function( nNode, iColumn, fnCallback )\n\t{\n\t\tthis.api( true ).order.listener( nNode, iColumn, fnCallback );\n\t};\n\t\n\t\n\t/**\n\t * Update a table cell or row - this method will accept either a single value to\n\t * update the cell with, an array of values with one element for each column or\n\t * an object in the same format as the original data source. The function is\n\t * self-referencing in order to make the multi column updates easier.\n\t * @param {object|array|string} mData Data to update the cell/row with\n\t * @param {node|int} mRow TR element you want to update or the aoData index\n\t * @param {int} [iColumn] The column to update, give as null or undefined to\n\t * update a whole row.\n\t * @param {bool} [bRedraw=true] Redraw the table or not\n\t * @param {bool} [bAction=true] Perform pre-draw actions or not\n\t * @returns {int} 0 on success, 1 on error\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell\n\t * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row\n\t * } );\n\t */\n\tthis.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )\n\t{\n\t\tvar api = this.api( true );\n\t\n\t\tif ( iColumn === undefined || iColumn === null ) {\n\t\t\tapi.row( mRow ).data( mData );\n\t\t}\n\t\telse {\n\t\t\tapi.cell( mRow, iColumn ).data( mData );\n\t\t}\n\t\n\t\tif ( bAction === undefined || bAction ) {\n\t\t\tapi.columns.adjust();\n\t\t}\n\t\n\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\tapi.draw();\n\t\t}\n\t\treturn 0;\n\t};\n\t\n\t\n\t/**\n\t * Provide a common method for plug-ins to check the version of DataTables being used, in order\n\t * to ensure compatibility.\n\t * @param {string} sVersion Version string to check for, in the format \"X.Y.Z\". Note that the\n\t * formats \"X\" and \"X.Y\" are also acceptable.\n\t * @returns {boolean} true if this version of DataTables is greater or equal to the required\n\t * version, or false if this version of DataTales is not suitable\n\t * @method\n\t * @dtopt API\n\t * @deprecated Since v1.10\n\t *\n\t * @example\n\t * $(document).ready(function() {\n\t * var oTable = $('#example').dataTable();\n\t * alert( oTable.fnVersionCheck( '1.9.0' ) );\n\t * } );\n\t */\n\tthis.fnVersionCheck = _ext.fnVersionCheck;\n\t\n\n\tvar _that = this;\n\tvar emptyInit = options === undefined;\n\tvar len = this.length;\n\n\tif ( emptyInit ) {\n\t\toptions = {};\n\t}\n\n\tthis.oApi = this.internal = _ext.internal;\n\n\t// Extend with old style plug-in API methods\n\tfor ( var fn in DataTable.ext.internal ) {\n\t\tif ( fn ) {\n\t\t\tthis[fn] = _fnExternApiFunc(fn);\n\t\t}\n\t}\n\n\tthis.each(function() {\n\t\t// For each initialisation we want to give it a clean initialisation\n\t\t// object that can be bashed around\n\t\tvar o = {};\n\t\tvar oInit = len > 1 ? // optimisation for single table case\n\t\t\t_fnExtend( o, options, true ) :\n\t\t\toptions;\n\n\t\t/*global oInit,_that,emptyInit*/\n\t\tvar i=0, iLen, j, jLen, k, kLen;\n\t\tvar sId = this.getAttribute( 'id' );\n\t\tvar bInitHandedOff = false;\n\t\tvar defaults = DataTable.defaults;\n\t\tvar $this = $(this);\n\t\t\n\t\t\n\t\t/* Sanity check */\n\t\tif ( this.nodeName.toLowerCase() != 'table' )\n\t\t{\n\t\t\t_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t/* Backwards compatibility for the defaults */\n\t\t_fnCompatOpts( defaults );\n\t\t_fnCompatCols( defaults.column );\n\t\t\n\t\t/* Convert the camel-case defaults to Hungarian */\n\t\t_fnCamelToHungarian( defaults, defaults, true );\n\t\t_fnCamelToHungarian( defaults.column, defaults.column, true );\n\t\t\n\t\t/* Setting up the initialisation object */\n\t\t_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );\n\t\t\n\t\t\n\t\t\n\t\t/* Check to see if we are re-initialising a table */\n\t\tvar allSettings = DataTable.settings;\n\t\tfor ( i=0, iLen=allSettings.length ; i').appendTo($this);\n\t\t\t}\n\t\t\toSettings.nTHead = thead[0];\n\t\t\n\t\t\tvar tbody = $this.children('tbody');\n\t\t\tif ( tbody.length === 0 ) {\n\t\t\t\ttbody = $('').insertAfter(thead);\n\t\t\t}\n\t\t\toSettings.nTBody = tbody[0];\n\t\t\n\t\t\tvar tfoot = $this.children('tfoot');\n\t\t\tif ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== \"\" || oSettings.oScroll.sY !== \"\") ) {\n\t\t\t\t// If we are a scrolling table, and no footer has been given, then we need to create\n\t\t\t\t// a tfoot element for the caption element to be appended to\n\t\t\t\ttfoot = $('').appendTo($this);\n\t\t\t}\n\t\t\n\t\t\tif ( tfoot.length === 0 || tfoot.children().length === 0 ) {\n\t\t\t\t$this.addClass( oClasses.sNoFooter );\n\t\t\t}\n\t\t\telse if ( tfoot.length > 0 ) {\n\t\t\t\toSettings.nTFoot = tfoot[0];\n\t\t\t\t_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );\n\t\t\t}\n\t\t\n\t\t\t/* Check if there is data passing into the constructor */\n\t\t\tif ( oInit.aaData ) {\n\t\t\t\tfor ( i=0 ; i/g;\n\n// This is not strict ISO8601 - Date.parse() is quite lax, although\n// implementations differ between browsers.\nvar _re_date = /^\\d{2,4}[\\.\\/\\-]\\d{1,2}[\\.\\/\\-]\\d{1,2}([T ]{1}\\d{1,2}[:\\.]\\d{2}([\\.:]\\d{2})?)?$/;\n\n// Escape regular expression special characters\nvar _re_escape_regex = new RegExp( '(\\\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\\\', '$', '^', '-' ].join('|\\\\') + ')', 'g' );\n\n// https://en.wikipedia.org/wiki/Foreign_exchange_market\n// - \\u20BD - Russian ruble.\n// - \\u20a9 - South Korean Won\n// - \\u20BA - Turkish Lira\n// - \\u20B9 - Indian Rupee\n// - R - Brazil (R$) and South Africa\n// - fr - Swiss Franc\n// - kr - Swedish krona, Norwegian krone and Danish krone\n// - \\u2009 is thin space and \\u202F is narrow no-break space, both used in many\n// - Ƀ - Bitcoin\n// - Ξ - Ethereum\n// standards as thousands separators.\nvar _re_formatted_numeric = /['\\u00A0,$£€¥%\\u2009\\u202F\\u20BD\\u20a9\\u20BArfkɃΞ]/gi;\n\n\nvar _empty = function ( d ) {\n\treturn !d || d === true || d === '-' ? true : false;\n};\n\n\nvar _intVal = function ( s ) {\n\tvar integer = parseInt( s, 10 );\n\treturn !isNaN(integer) && isFinite(s) ? integer : null;\n};\n\n// Convert from a formatted number with characters other than `.` as the\n// decimal place, to a Javascript number\nvar _numToDecimal = function ( num, decimalPoint ) {\n\t// Cache created regular expressions for speed as this function is called often\n\tif ( ! _re_dic[ decimalPoint ] ) {\n\t\t_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );\n\t}\n\treturn typeof num === 'string' && decimalPoint !== '.' ?\n\t\tnum.replace( /\\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :\n\t\tnum;\n};\n\n\nvar _isNumber = function ( d, decimalPoint, formatted ) {\n\tvar type = typeof d;\n\tvar strType = type === 'string';\n\n\tif ( type === 'number' || type === 'bigint') {\n\t\treturn true;\n\t}\n\n\t// If empty return immediately so there must be a number if it is a\n\t// formatted string (this stops the string \"k\", or \"kr\", etc being detected\n\t// as a formatted number for currency\n\tif ( _empty( d ) ) {\n\t\treturn true;\n\t}\n\n\tif ( decimalPoint && strType ) {\n\t\td = _numToDecimal( d, decimalPoint );\n\t}\n\n\tif ( formatted && strType ) {\n\t\td = d.replace( _re_formatted_numeric, '' );\n\t}\n\n\treturn !isNaN( parseFloat(d) ) && isFinite( d );\n};\n\n\n// A string without HTML in it can be considered to be HTML still\nvar _isHtml = function ( d ) {\n\treturn _empty( d ) || typeof d === 'string';\n};\n\n\nvar _htmlNumeric = function ( d, decimalPoint, formatted ) {\n\tif ( _empty( d ) ) {\n\t\treturn true;\n\t}\n\n\tvar html = _isHtml( d );\n\treturn ! html ?\n\t\tnull :\n\t\t_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?\n\t\t\ttrue :\n\t\t\tnull;\n};\n\n\nvar _pluck = function ( a, prop, prop2 ) {\n\tvar out = [];\n\tvar i=0, ien=a.length;\n\n\t// Could have the test in the loop for slightly smaller code, but speed\n\t// is essential here\n\tif ( prop2 !== undefined ) {\n\t\tfor ( ; i')\n\t\t\t.css( {\n\t\t\t\tposition: 'fixed',\n\t\t\t\ttop: 0,\n\t\t\t\tleft: $(window).scrollLeft()*-1, // allow for scrolling\n\t\t\t\theight: 1,\n\t\t\t\twidth: 1,\n\t\t\t\toverflow: 'hidden'\n\t\t\t} )\n\t\t\t.append(\n\t\t\t\t$('
      ')\n\t\t\t\t\t.css( {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: 1,\n\t\t\t\t\t\tleft: 1,\n\t\t\t\t\t\twidth: 100,\n\t\t\t\t\t\toverflow: 'scroll'\n\t\t\t\t\t} )\n\t\t\t\t\t.append(\n\t\t\t\t\t\t$('
      ')\n\t\t\t\t\t\t\t.css( {\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\theight: 10\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.appendTo( 'body' );\n\n\t\tvar outer = n.children();\n\t\tvar inner = outer.children();\n\n\t\t// Numbers below, in order, are:\n\t\t// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth\n\t\t//\n\t\t// IE6 XP: 100 100 100 83\n\t\t// IE7 Vista: 100 100 100 83\n\t\t// IE 8+ Windows: 83 83 100 83\n\t\t// Evergreen Windows: 83 83 100 83\n\t\t// Evergreen Mac with scrollbars: 85 85 100 85\n\t\t// Evergreen Mac without scrollbars: 100 100 100 100\n\n\t\t// Get scrollbar width\n\t\tbrowser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;\n\n\t\t// IE6/7 will oversize a width 100% element inside a scrolling element, to\n\t\t// include the width of the scrollbar, while other browsers ensure the inner\n\t\t// element is contained without forcing scrolling\n\t\tbrowser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;\n\n\t\t// In rtl text layout, some browsers (most, but not all) will place the\n\t\t// scrollbar on the left, rather than the right.\n\t\tbrowser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;\n\n\t\t// IE8- don't provide height and width for getBoundingClientRect\n\t\tbrowser.bBounding = n[0].getBoundingClientRect().width ? true : false;\n\n\t\tn.remove();\n\t}\n\n\t$.extend( settings.oBrowser, DataTable.__browser );\n\tsettings.oScroll.iBarWidth = DataTable.__browser.barWidth;\n}\n\n\n/**\n * Array.prototype reduce[Right] method, used for browsers which don't support\n * JS 1.6. Done this way to reduce code size, since we iterate either way\n * @param {object} settings dataTables settings object\n * @memberof DataTable#oApi\n */\nfunction _fnReduce ( that, fn, init, start, end, inc )\n{\n\tvar\n\t\ti = start,\n\t\tvalue,\n\t\tisSet = false;\n\n\tif ( init !== undefined ) {\n\t\tvalue = init;\n\t\tisSet = true;\n\t}\n\n\twhile ( i !== end ) {\n\t\tif ( ! that.hasOwnProperty(i) ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalue = isSet ?\n\t\t\tfn( value, that[i], i, that ) :\n\t\t\tthat[i];\n\n\t\tisSet = true;\n\t\ti += inc;\n\t}\n\n\treturn value;\n}\n\n/**\n * Add a column to the list used for the table with default values\n * @param {object} oSettings dataTables settings object\n * @param {node} nTh The th element for this column\n * @memberof DataTable#oApi\n */\nfunction _fnAddColumn( oSettings, nTh )\n{\n\t// Add column to aoColumns array\n\tvar oDefaults = DataTable.defaults.column;\n\tvar iCol = oSettings.aoColumns.length;\n\tvar oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {\n\t\t\"nTh\": nTh ? nTh : document.createElement('th'),\n\t\t\"sTitle\": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',\n\t\t\"aDataSort\": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],\n\t\t\"mData\": oDefaults.mData ? oDefaults.mData : iCol,\n\t\tidx: iCol\n\t} );\n\toSettings.aoColumns.push( oCol );\n\n\t// Add search object for column specific search. Note that the `searchCols[ iCol ]`\n\t// passed into extend can be undefined. This allows the user to give a default\n\t// with only some of the parameters defined, and also not give a default\n\tvar searchCols = oSettings.aoPreSearchCols;\n\tsearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );\n\n\t// Use the default column options function to initialise classes etc\n\t_fnColumnOptions( oSettings, iCol, $(nTh).data() );\n}\n\n\n/**\n * Apply options for a column\n * @param {object} oSettings dataTables settings object\n * @param {int} iCol column index to consider\n * @param {object} oOptions object with sType, bVisible and bSearchable etc\n * @memberof DataTable#oApi\n */\nfunction _fnColumnOptions( oSettings, iCol, oOptions )\n{\n\tvar oCol = oSettings.aoColumns[ iCol ];\n\tvar oClasses = oSettings.oClasses;\n\tvar th = $(oCol.nTh);\n\n\t// Try to get width information from the DOM. We can't get it from CSS\n\t// as we'd need to parse the CSS stylesheet. `width` option can override\n\tif ( ! oCol.sWidthOrig ) {\n\t\t// Width attribute\n\t\toCol.sWidthOrig = th.attr('width') || null;\n\n\t\t// Style attribute\n\t\tvar t = (th.attr('style') || '').match(/width:\\s*(\\d+[pxem%]+)/);\n\t\tif ( t ) {\n\t\t\toCol.sWidthOrig = t[1];\n\t\t}\n\t}\n\n\t/* User specified column options */\n\tif ( oOptions !== undefined && oOptions !== null )\n\t{\n\t\t// Backwards compatibility\n\t\t_fnCompatCols( oOptions );\n\n\t\t// Map camel case parameters to their Hungarian counterparts\n\t\t_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );\n\n\t\t/* Backwards compatibility for mDataProp */\n\t\tif ( oOptions.mDataProp !== undefined && !oOptions.mData )\n\t\t{\n\t\t\toOptions.mData = oOptions.mDataProp;\n\t\t}\n\n\t\tif ( oOptions.sType )\n\t\t{\n\t\t\toCol._sManualType = oOptions.sType;\n\t\t}\n\n\t\t// `class` is a reserved word in Javascript, so we need to provide\n\t\t// the ability to use a valid name for the camel case input\n\t\tif ( oOptions.className && ! oOptions.sClass )\n\t\t{\n\t\t\toOptions.sClass = oOptions.className;\n\t\t}\n\t\tif ( oOptions.sClass ) {\n\t\t\tth.addClass( oOptions.sClass );\n\t\t}\n\n\t\tvar origClass = oCol.sClass;\n\n\t\t$.extend( oCol, oOptions );\n\t\t_fnMap( oCol, oOptions, \"sWidth\", \"sWidthOrig\" );\n\n\t\t// Merge class from previously defined classes with this one, rather than just\n\t\t// overwriting it in the extend above\n\t\tif (origClass !== oCol.sClass) {\n\t\t\toCol.sClass = origClass + ' ' + oCol.sClass;\n\t\t}\n\n\t\t/* iDataSort to be applied (backwards compatibility), but aDataSort will take\n\t\t * priority if defined\n\t\t */\n\t\tif ( oOptions.iDataSort !== undefined )\n\t\t{\n\t\t\toCol.aDataSort = [ oOptions.iDataSort ];\n\t\t}\n\t\t_fnMap( oCol, oOptions, \"aDataSort\" );\n\n\t\t// Fall back to the aria-label attribute on the table header if no ariaTitle is\n\t\t// provided.\n\t\tif (! oCol.ariaTitle) {\n\t\t\toCol.ariaTitle = th.attr(\"aria-label\");\n\t\t}\n\t}\n\n\t/* Cache the data get and set functions for speed */\n\tvar mDataSrc = oCol.mData;\n\tvar mData = _fnGetObjectDataFn( mDataSrc );\n\tvar mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;\n\n\tvar attrTest = function( src ) {\n\t\treturn typeof src === 'string' && src.indexOf('@') !== -1;\n\t};\n\toCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (\n\t\tattrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)\n\t);\n\toCol._setter = null;\n\n\toCol.fnGetData = function (rowData, type, meta) {\n\t\tvar innerData = mData( rowData, type, undefined, meta );\n\n\t\treturn mRender && type ?\n\t\t\tmRender( innerData, type, rowData, meta ) :\n\t\t\tinnerData;\n\t};\n\toCol.fnSetData = function ( rowData, val, meta ) {\n\t\treturn _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );\n\t};\n\n\t// Indicate if DataTables should read DOM data as an object or array\n\t// Used in _fnGetRowElements\n\tif ( typeof mDataSrc !== 'number' && ! oCol._isArrayHost ) {\n\t\toSettings._rowReadObject = true;\n\t}\n\n\t/* Feature sorting overrides column specific when off */\n\tif ( !oSettings.oFeatures.bSort )\n\t{\n\t\toCol.bSortable = false;\n\t\tth.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called\n\t}\n\n\t/* Check that the class assignment is correct for sorting */\n\tvar bAsc = $.inArray('asc', oCol.asSorting) !== -1;\n\tvar bDesc = $.inArray('desc', oCol.asSorting) !== -1;\n\tif ( !oCol.bSortable || (!bAsc && !bDesc) )\n\t{\n\t\toCol.sSortingClass = oClasses.sSortableNone;\n\t\toCol.sSortingClassJUI = \"\";\n\t}\n\telse if ( bAsc && !bDesc )\n\t{\n\t\toCol.sSortingClass = oClasses.sSortableAsc;\n\t\toCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;\n\t}\n\telse if ( !bAsc && bDesc )\n\t{\n\t\toCol.sSortingClass = oClasses.sSortableDesc;\n\t\toCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;\n\t}\n\telse\n\t{\n\t\toCol.sSortingClass = oClasses.sSortable;\n\t\toCol.sSortingClassJUI = oClasses.sSortJUI;\n\t}\n}\n\n\n/**\n * Adjust the table column widths for new data. Note: you would probably want to\n * do a redraw after calling this function!\n * @param {object} settings dataTables settings object\n * @memberof DataTable#oApi\n */\nfunction _fnAdjustColumnSizing ( settings )\n{\n\t/* Not interested in doing column width calculation if auto-width is disabled */\n\tif ( settings.oFeatures.bAutoWidth !== false )\n\t{\n\t\tvar columns = settings.aoColumns;\n\n\t\t_fnCalculateColumnWidths( settings );\n\t\tfor ( var i=0 , iLen=columns.length ; i