/******/ (function() { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./node_modules/chart.js/auto/auto.esm.js": /*!************************************************!*\ !*** ./node_modules/chart.js/auto/auto.esm.js ***! \************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* harmony import */ var _dist_chart_esm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../dist/chart.esm */ "./node_modules/chart.js/dist/chart.esm.js"); _dist_chart_esm__WEBPACK_IMPORTED_MODULE_0__.Chart.register(..._dist_chart_esm__WEBPACK_IMPORTED_MODULE_0__.registerables); /* harmony default export */ __webpack_exports__["default"] = (_dist_chart_esm__WEBPACK_IMPORTED_MODULE_0__.Chart); /***/ }), /***/ "./node_modules/chart.js/dist/chart.esm.js": /*!*************************************************!*\ !*** ./node_modules/chart.js/dist/chart.esm.js ***! \*************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "defaults": function() { return /* reexport safe */ _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d; }, /* harmony export */ "Animation": function() { return /* binding */ Animation; }, /* harmony export */ "Animations": function() { return /* binding */ Animations; }, /* harmony export */ "ArcElement": function() { return /* binding */ ArcElement; }, /* harmony export */ "BarController": function() { return /* binding */ BarController; }, /* harmony export */ "BarElement": function() { return /* binding */ BarElement; }, /* harmony export */ "BasePlatform": function() { return /* binding */ BasePlatform; }, /* harmony export */ "BasicPlatform": function() { return /* binding */ BasicPlatform; }, /* harmony export */ "BubbleController": function() { return /* binding */ BubbleController; }, /* harmony export */ "CategoryScale": function() { return /* binding */ CategoryScale; }, /* harmony export */ "Chart": function() { return /* binding */ Chart; }, /* harmony export */ "DatasetController": function() { return /* binding */ DatasetController; }, /* harmony export */ "Decimation": function() { return /* binding */ plugin_decimation; }, /* harmony export */ "DomPlatform": function() { return /* binding */ DomPlatform; }, /* harmony export */ "DoughnutController": function() { return /* binding */ DoughnutController; }, /* harmony export */ "Element": function() { return /* binding */ Element; }, /* harmony export */ "Filler": function() { return /* binding */ plugin_filler; }, /* harmony export */ "Interaction": function() { return /* binding */ Interaction; }, /* harmony export */ "Legend": function() { return /* binding */ plugin_legend; }, /* harmony export */ "LineController": function() { return /* binding */ LineController; }, /* harmony export */ "LineElement": function() { return /* binding */ LineElement; }, /* harmony export */ "LinearScale": function() { return /* binding */ LinearScale; }, /* harmony export */ "LogarithmicScale": function() { return /* binding */ LogarithmicScale; }, /* harmony export */ "PieController": function() { return /* binding */ PieController; }, /* harmony export */ "PointElement": function() { return /* binding */ PointElement; }, /* harmony export */ "PolarAreaController": function() { return /* binding */ PolarAreaController; }, /* harmony export */ "RadarController": function() { return /* binding */ RadarController; }, /* harmony export */ "RadialLinearScale": function() { return /* binding */ RadialLinearScale; }, /* harmony export */ "Scale": function() { return /* binding */ Scale; }, /* harmony export */ "ScatterController": function() { return /* binding */ ScatterController; }, /* harmony export */ "SubTitle": function() { return /* binding */ plugin_subtitle; }, /* harmony export */ "Ticks": function() { return /* binding */ Ticks; }, /* harmony export */ "TimeScale": function() { return /* binding */ TimeScale; }, /* harmony export */ "TimeSeriesScale": function() { return /* binding */ TimeSeriesScale; }, /* harmony export */ "Title": function() { return /* binding */ plugin_title; }, /* harmony export */ "Tooltip": function() { return /* binding */ plugin_tooltip; }, /* harmony export */ "_adapters": function() { return /* binding */ adapters; }, /* harmony export */ "_detectPlatform": function() { return /* binding */ _detectPlatform; }, /* harmony export */ "animator": function() { return /* binding */ animator; }, /* harmony export */ "controllers": function() { return /* binding */ controllers; }, /* harmony export */ "elements": function() { return /* binding */ elements; }, /* harmony export */ "layouts": function() { return /* binding */ layouts; }, /* harmony export */ "plugins": function() { return /* binding */ plugins; }, /* harmony export */ "registerables": function() { return /* binding */ registerables; }, /* harmony export */ "registry": function() { return /* binding */ registry; }, /* harmony export */ "scales": function() { return /* binding */ scales; } /* harmony export */ }); /* harmony import */ var _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chunks/helpers.segment.js */ "./node_modules/chart.js/dist/chunks/helpers.segment.js"); /*! * Chart.js v3.5.1 * https://www.chartjs.org * (c) 2021 Chart.js Contributors * Released under the MIT License */ class Animator { constructor() { this._request = null; this._charts = new Map(); this._running = false; this._lastDate = undefined; } _notify(chart, anims, date, type) { const callbacks = anims.listeners[type]; const numSteps = anims.duration; callbacks.forEach(fn => fn({ chart, initial: anims.initial, numSteps, currentStep: Math.min(date - anims.start, numSteps) })); } _refresh() { const me = this; if (me._request) { return; } me._running = true; me._request = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.r.call(window, () => { me._update(); me._request = null; if (me._running) { me._refresh(); } }); } _update(date = Date.now()) { const me = this; let remaining = 0; me._charts.forEach((anims, chart) => { if (!anims.running || !anims.items.length) { return; } const items = anims.items; let i = items.length - 1; let draw = false; let item; for (; i >= 0; --i) { item = items[i]; if (item._active) { if (item._total > anims.duration) { anims.duration = item._total; } item.tick(date); draw = true; } else { items[i] = items[items.length - 1]; items.pop(); } } if (draw) { chart.draw(); me._notify(chart, anims, date, 'progress'); } if (!items.length) { anims.running = false; me._notify(chart, anims, date, 'complete'); anims.initial = false; } remaining += items.length; }); me._lastDate = date; if (remaining === 0) { me._running = false; } } _getAnims(chart) { const charts = this._charts; let anims = charts.get(chart); if (!anims) { anims = { running: false, initial: true, items: [], listeners: { complete: [], progress: [] } }; charts.set(chart, anims); } return anims; } listen(chart, event, cb) { this._getAnims(chart).listeners[event].push(cb); } add(chart, items) { if (!items || !items.length) { return; } this._getAnims(chart).items.push(...items); } has(chart) { return this._getAnims(chart).items.length > 0; } start(chart) { const anims = this._charts.get(chart); if (!anims) { return; } anims.running = true; anims.start = Date.now(); anims.duration = anims.items.reduce((acc, cur) => Math.max(acc, cur._duration), 0); this._refresh(); } running(chart) { if (!this._running) { return false; } const anims = this._charts.get(chart); if (!anims || !anims.running || !anims.items.length) { return false; } return true; } stop(chart) { const anims = this._charts.get(chart); if (!anims || !anims.items.length) { return; } const items = anims.items; let i = items.length - 1; for (; i >= 0; --i) { items[i].cancel(); } anims.items = []; this._notify(chart, anims, Date.now(), 'complete'); } remove(chart) { return this._charts.delete(chart); } } var animator = new Animator(); const transparent = 'transparent'; const interpolators = { boolean(from, to, factor) { return factor > 0.5 ? to : from; }, color(from, to, factor) { const c0 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.c)(from || transparent); const c1 = c0.valid && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.c)(to || transparent); return c1 && c1.valid ? c1.mix(c0, factor).hexString() : to; }, number(from, to, factor) { return from + (to - from) * factor; } }; class Animation { constructor(cfg, target, prop, to) { const currentValue = target[prop]; to = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([cfg.to, to, currentValue, cfg.from]); const from = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([cfg.from, currentValue, to]); this._active = true; this._fn = cfg.fn || interpolators[cfg.type || typeof from]; this._easing = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.e[cfg.easing] || _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.e.linear; this._start = Math.floor(Date.now() + (cfg.delay || 0)); this._duration = this._total = Math.floor(cfg.duration); this._loop = !!cfg.loop; this._target = target; this._prop = prop; this._from = from; this._to = to; this._promises = undefined; } active() { return this._active; } update(cfg, to, date) { const me = this; if (me._active) { me._notify(false); const currentValue = me._target[me._prop]; const elapsed = date - me._start; const remain = me._duration - elapsed; me._start = date; me._duration = Math.floor(Math.max(remain, cfg.duration)); me._total += elapsed; me._loop = !!cfg.loop; me._to = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([cfg.to, to, currentValue, cfg.from]); me._from = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([cfg.from, currentValue, to]); } } cancel() { const me = this; if (me._active) { me.tick(Date.now()); me._active = false; me._notify(false); } } tick(date) { const me = this; const elapsed = date - me._start; const duration = me._duration; const prop = me._prop; const from = me._from; const loop = me._loop; const to = me._to; let factor; me._active = from !== to && (loop || (elapsed < duration)); if (!me._active) { me._target[prop] = to; me._notify(true); return; } if (elapsed < 0) { me._target[prop] = from; return; } factor = (elapsed / duration) % 2; factor = loop && factor > 1 ? 2 - factor : factor; factor = me._easing(Math.min(1, Math.max(0, factor))); me._target[prop] = me._fn(from, to, factor); } wait() { const promises = this._promises || (this._promises = []); return new Promise((res, rej) => { promises.push({res, rej}); }); } _notify(resolved) { const method = resolved ? 'res' : 'rej'; const promises = this._promises || []; for (let i = 0; i < promises.length; i++) { promises[i][method](); } } } const numbers = ['x', 'y', 'borderWidth', 'radius', 'tension']; const colors = ['color', 'borderColor', 'backgroundColor']; _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.set('animation', { delay: undefined, duration: 1000, easing: 'easeOutQuart', fn: undefined, from: undefined, loop: undefined, to: undefined, type: undefined, }); const animationOptions = Object.keys(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.animation); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.describe('animation', { _fallback: false, _indexable: false, _scriptable: (name) => name !== 'onProgress' && name !== 'onComplete' && name !== 'fn', }); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.set('animations', { colors: { type: 'color', properties: colors }, numbers: { type: 'number', properties: numbers }, }); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.describe('animations', { _fallback: 'animation', }); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.set('transitions', { active: { animation: { duration: 400 } }, resize: { animation: { duration: 0 } }, show: { animations: { colors: { from: 'transparent' }, visible: { type: 'boolean', duration: 0 }, } }, hide: { animations: { colors: { to: 'transparent' }, visible: { type: 'boolean', easing: 'linear', fn: v => v | 0 }, } } }); class Animations { constructor(chart, config) { this._chart = chart; this._properties = new Map(); this.configure(config); } configure(config) { if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(config)) { return; } const animatedProps = this._properties; Object.getOwnPropertyNames(config).forEach(key => { const cfg = config[key]; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(cfg)) { return; } const resolved = {}; for (const option of animationOptions) { resolved[option] = cfg[option]; } ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(cfg.properties) && cfg.properties || [key]).forEach((prop) => { if (prop === key || !animatedProps.has(prop)) { animatedProps.set(prop, resolved); } }); }); } _animateOptions(target, values) { const newOptions = values.options; const options = resolveTargetOptions(target, newOptions); if (!options) { return []; } const animations = this._createAnimations(options, newOptions); if (newOptions.$shared) { awaitAll(target.options.$animations, newOptions).then(() => { target.options = newOptions; }, () => { }); } return animations; } _createAnimations(target, values) { const animatedProps = this._properties; const animations = []; const running = target.$animations || (target.$animations = {}); const props = Object.keys(values); const date = Date.now(); let i; for (i = props.length - 1; i >= 0; --i) { const prop = props[i]; if (prop.charAt(0) === '$') { continue; } if (prop === 'options') { animations.push(...this._animateOptions(target, values)); continue; } const value = values[prop]; let animation = running[prop]; const cfg = animatedProps.get(prop); if (animation) { if (cfg && animation.active()) { animation.update(cfg, value, date); continue; } else { animation.cancel(); } } if (!cfg || !cfg.duration) { target[prop] = value; continue; } running[prop] = animation = new Animation(cfg, target, prop, value); animations.push(animation); } return animations; } update(target, values) { if (this._properties.size === 0) { Object.assign(target, values); return; } const animations = this._createAnimations(target, values); if (animations.length) { animator.add(this._chart, animations); return true; } } } function awaitAll(animations, properties) { const running = []; const keys = Object.keys(properties); for (let i = 0; i < keys.length; i++) { const anim = animations[keys[i]]; if (anim && anim.active()) { running.push(anim.wait()); } } return Promise.all(running); } function resolveTargetOptions(target, newOptions) { if (!newOptions) { return; } let options = target.options; if (!options) { target.options = newOptions; return; } if (options.$shared) { target.options = options = Object.assign({}, options, {$shared: false, $animations: {}}); } return options; } function scaleClip(scale, allowedOverflow) { const opts = scale && scale.options || {}; const reverse = opts.reverse; const min = opts.min === undefined ? allowedOverflow : 0; const max = opts.max === undefined ? allowedOverflow : 0; return { start: reverse ? max : min, end: reverse ? min : max }; } function defaultClip(xScale, yScale, allowedOverflow) { if (allowedOverflow === false) { return false; } const x = scaleClip(xScale, allowedOverflow); const y = scaleClip(yScale, allowedOverflow); return { top: y.end, right: x.end, bottom: y.start, left: x.start }; } function toClip(value) { let t, r, b, l; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(value)) { t = value.top; r = value.right; b = value.bottom; l = value.left; } else { t = r = b = l = value; } return { top: t, right: r, bottom: b, left: l, disabled: value === false }; } function getSortedDatasetIndices(chart, filterVisible) { const keys = []; const metasets = chart._getSortedDatasetMetas(filterVisible); let i, ilen; for (i = 0, ilen = metasets.length; i < ilen; ++i) { keys.push(metasets[i].index); } return keys; } function applyStack(stack, value, dsIndex, options) { const keys = stack.keys; const singleMode = options.mode === 'single'; let i, ilen, datasetIndex, otherValue; if (value === null) { return; } for (i = 0, ilen = keys.length; i < ilen; ++i) { datasetIndex = +keys[i]; if (datasetIndex === dsIndex) { if (options.all) { continue; } break; } otherValue = stack.values[datasetIndex]; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(otherValue) && (singleMode || (value === 0 || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) === (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(otherValue)))) { value += otherValue; } } return value; } function convertObjectDataToArray(data) { const keys = Object.keys(data); const adata = new Array(keys.length); let i, ilen, key; for (i = 0, ilen = keys.length; i < ilen; ++i) { key = keys[i]; adata[i] = { x: key, y: data[key] }; } return adata; } function isStacked(scale, meta) { const stacked = scale && scale.options.stacked; return stacked || (stacked === undefined && meta.stack !== undefined); } function getStackKey(indexScale, valueScale, meta) { return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`; } function getUserBounds(scale) { const {min, max, minDefined, maxDefined} = scale.getUserBounds(); return { min: minDefined ? min : Number.NEGATIVE_INFINITY, max: maxDefined ? max : Number.POSITIVE_INFINITY }; } function getOrCreateStack(stacks, stackKey, indexValue) { const subStack = stacks[stackKey] || (stacks[stackKey] = {}); return subStack[indexValue] || (subStack[indexValue] = {}); } function getLastIndexInStack(stack, vScale, positive) { for (const meta of vScale.getMatchingVisibleMetas('bar').reverse()) { const value = stack[meta.index]; if ((positive && value > 0) || (!positive && value < 0)) { return meta.index; } } return null; } function updateStacks(controller, parsed) { const {chart, _cachedMeta: meta} = controller; const stacks = chart._stacks || (chart._stacks = {}); const {iScale, vScale, index: datasetIndex} = meta; const iAxis = iScale.axis; const vAxis = vScale.axis; const key = getStackKey(iScale, vScale, meta); const ilen = parsed.length; let stack; for (let i = 0; i < ilen; ++i) { const item = parsed[i]; const {[iAxis]: index, [vAxis]: value} = item; const itemStacks = item._stacks || (item._stacks = {}); stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index); stack[datasetIndex] = value; stack._top = getLastIndexInStack(stack, vScale, true); stack._bottom = getLastIndexInStack(stack, vScale, false); } } function getFirstScaleId(chart, axis) { const scales = chart.scales; return Object.keys(scales).filter(key => scales[key].axis === axis).shift(); } function createDatasetContext(parent, index) { return Object.assign(Object.create(parent), { active: false, dataset: undefined, datasetIndex: index, index, mode: 'default', type: 'dataset' } ); } function createDataContext(parent, index, element) { return Object.assign(Object.create(parent), { active: false, dataIndex: index, parsed: undefined, raw: undefined, element, index, mode: 'default', type: 'data' }); } function clearStacks(meta, items) { const datasetIndex = meta.controller.index; const axis = meta.vScale && meta.vScale.axis; if (!axis) { return; } items = items || meta._parsed; for (const parsed of items) { const stacks = parsed._stacks; if (!stacks || stacks[axis] === undefined || stacks[axis][datasetIndex] === undefined) { return; } delete stacks[axis][datasetIndex]; } } const isDirectUpdateMode = (mode) => mode === 'reset' || mode === 'none'; const cloneIfNotShared = (cached, shared) => shared ? cached : Object.assign({}, cached); class DatasetController { constructor(chart, datasetIndex) { this.chart = chart; this._ctx = chart.ctx; this.index = datasetIndex; this._cachedDataOpts = {}; this._cachedMeta = this.getMeta(); this._type = this._cachedMeta.type; this.options = undefined; this._parsing = false; this._data = undefined; this._objectData = undefined; this._sharedOptions = undefined; this._drawStart = undefined; this._drawCount = undefined; this.enableOptionSharing = false; this.$context = undefined; this._syncList = []; this.initialize(); } initialize() { const me = this; const meta = me._cachedMeta; me.configure(); me.linkScales(); meta._stacked = isStacked(meta.vScale, meta); me.addElements(); } updateIndex(datasetIndex) { if (this.index !== datasetIndex) { clearStacks(this._cachedMeta); } this.index = datasetIndex; } linkScales() { const me = this; const chart = me.chart; const meta = me._cachedMeta; const dataset = me.getDataset(); const chooseId = (axis, x, y, r) => axis === 'x' ? x : axis === 'r' ? r : y; const xid = meta.xAxisID = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.xAxisID, getFirstScaleId(chart, 'x')); const yid = meta.yAxisID = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.yAxisID, getFirstScaleId(chart, 'y')); const rid = meta.rAxisID = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.rAxisID, getFirstScaleId(chart, 'r')); const indexAxis = meta.indexAxis; const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid); const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid); meta.xScale = me.getScaleForId(xid); meta.yScale = me.getScaleForId(yid); meta.rScale = me.getScaleForId(rid); meta.iScale = me.getScaleForId(iid); meta.vScale = me.getScaleForId(vid); } getDataset() { return this.chart.data.datasets[this.index]; } getMeta() { return this.chart.getDatasetMeta(this.index); } getScaleForId(scaleID) { return this.chart.scales[scaleID]; } _getOtherScale(scale) { const meta = this._cachedMeta; return scale === meta.iScale ? meta.vScale : meta.iScale; } reset() { this._update('reset'); } _destroy() { const meta = this._cachedMeta; if (this._data) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.u)(this._data, this); } if (meta._stacked) { clearStacks(meta); } } _dataCheck() { const me = this; const dataset = me.getDataset(); const data = dataset.data || (dataset.data = []); const _data = me._data; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(data)) { me._data = convertObjectDataToArray(data); } else if (_data !== data) { if (_data) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.u)(_data, me); const meta = me._cachedMeta; clearStacks(meta); meta._parsed = []; } if (data && Object.isExtensible(data)) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.l)(data, me); } me._syncList = []; me._data = data; } } addElements() { const me = this; const meta = me._cachedMeta; me._dataCheck(); if (me.datasetElementType) { meta.dataset = new me.datasetElementType(); } } buildOrUpdateElements(resetNewElements) { const me = this; const meta = me._cachedMeta; const dataset = me.getDataset(); let stackChanged = false; me._dataCheck(); const oldStacked = meta._stacked; meta._stacked = isStacked(meta.vScale, meta); if (meta.stack !== dataset.stack) { stackChanged = true; clearStacks(meta); meta.stack = dataset.stack; } me._resyncElements(resetNewElements); if (stackChanged || oldStacked !== meta._stacked) { updateStacks(me, meta._parsed); } } configure() { const me = this; const config = me.chart.config; const scopeKeys = config.datasetScopeKeys(me._type); const scopes = config.getOptionScopes(me.getDataset(), scopeKeys, true); me.options = config.createResolver(scopes, me.getContext()); me._parsing = me.options.parsing; } parse(start, count) { const me = this; const {_cachedMeta: meta, _data: data} = me; const {iScale, _stacked} = meta; const iAxis = iScale.axis; let sorted = start === 0 && count === data.length ? true : meta._sorted; let prev = start > 0 && meta._parsed[start - 1]; let i, cur, parsed; if (me._parsing === false) { meta._parsed = data; meta._sorted = true; parsed = data; } else { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(data[start])) { parsed = me.parseArrayData(meta, data, start, count); } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(data[start])) { parsed = me.parseObjectData(meta, data, start, count); } else { parsed = me.parsePrimitiveData(meta, data, start, count); } const isNotInOrderComparedToPrev = () => cur[iAxis] === null || (prev && cur[iAxis] < prev[iAxis]); for (i = 0; i < count; ++i) { meta._parsed[i + start] = cur = parsed[i]; if (sorted) { if (isNotInOrderComparedToPrev()) { sorted = false; } prev = cur; } } meta._sorted = sorted; } if (_stacked) { updateStacks(me, parsed); } } parsePrimitiveData(meta, data, start, count) { const {iScale, vScale} = meta; const iAxis = iScale.axis; const vAxis = vScale.axis; const labels = iScale.getLabels(); const singleScale = iScale === vScale; const parsed = new Array(count); let i, ilen, index; for (i = 0, ilen = count; i < ilen; ++i) { index = i + start; parsed[i] = { [iAxis]: singleScale || iScale.parse(labels[index], index), [vAxis]: vScale.parse(data[index], index) }; } return parsed; } parseArrayData(meta, data, start, count) { const {xScale, yScale} = meta; const parsed = new Array(count); let i, ilen, index, item; for (i = 0, ilen = count; i < ilen; ++i) { index = i + start; item = data[index]; parsed[i] = { x: xScale.parse(item[0], index), y: yScale.parse(item[1], index) }; } return parsed; } parseObjectData(meta, data, start, count) { const {xScale, yScale} = meta; const {xAxisKey = 'x', yAxisKey = 'y'} = this._parsing; const parsed = new Array(count); let i, ilen, index, item; for (i = 0, ilen = count; i < ilen; ++i) { index = i + start; item = data[index]; parsed[i] = { x: xScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, xAxisKey), index), y: yScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, yAxisKey), index) }; } return parsed; } getParsed(index) { return this._cachedMeta._parsed[index]; } getDataElement(index) { return this._cachedMeta.data[index]; } applyStack(scale, parsed, mode) { const chart = this.chart; const meta = this._cachedMeta; const value = parsed[scale.axis]; const stack = { keys: getSortedDatasetIndices(chart, true), values: parsed._stacks[scale.axis] }; return applyStack(stack, value, meta.index, {mode}); } updateRangeFromParsed(range, scale, parsed, stack) { const parsedValue = parsed[scale.axis]; let value = parsedValue === null ? NaN : parsedValue; const values = stack && parsed._stacks[scale.axis]; if (stack && values) { stack.values = values; range.min = Math.min(range.min, value); range.max = Math.max(range.max, value); value = applyStack(stack, parsedValue, this._cachedMeta.index, {all: true}); } range.min = Math.min(range.min, value); range.max = Math.max(range.max, value); } getMinMax(scale, canStack) { const me = this; const meta = me._cachedMeta; const _parsed = meta._parsed; const sorted = meta._sorted && scale === meta.iScale; const ilen = _parsed.length; const otherScale = me._getOtherScale(scale); const stack = canStack && meta._stacked && {keys: getSortedDatasetIndices(me.chart, true), values: null}; const range = {min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY}; const {min: otherMin, max: otherMax} = getUserBounds(otherScale); let i, value, parsed, otherValue; function _skip() { parsed = _parsed[i]; value = parsed[scale.axis]; otherValue = parsed[otherScale.axis]; return !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(value) || otherMin > otherValue || otherMax < otherValue; } for (i = 0; i < ilen; ++i) { if (_skip()) { continue; } me.updateRangeFromParsed(range, scale, parsed, stack); if (sorted) { break; } } if (sorted) { for (i = ilen - 1; i >= 0; --i) { if (_skip()) { continue; } me.updateRangeFromParsed(range, scale, parsed, stack); break; } } return range; } getAllParsedValues(scale) { const parsed = this._cachedMeta._parsed; const values = []; let i, ilen, value; for (i = 0, ilen = parsed.length; i < ilen; ++i) { value = parsed[i][scale.axis]; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) { values.push(value); } } return values; } getMaxOverflow() { return false; } getLabelAndValue(index) { const me = this; const meta = me._cachedMeta; const iScale = meta.iScale; const vScale = meta.vScale; const parsed = me.getParsed(index); return { label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '', value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : '' }; } _update(mode) { const me = this; const meta = me._cachedMeta; me.configure(); me._cachedDataOpts = {}; me.update(mode || 'default'); meta._clip = toClip((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(me.options.clip, defaultClip(meta.xScale, meta.yScale, me.getMaxOverflow()))); } update(mode) {} draw() { const me = this; const ctx = me._ctx; const chart = me.chart; const meta = me._cachedMeta; const elements = meta.data || []; const area = chart.chartArea; const active = []; const start = me._drawStart || 0; const count = me._drawCount || (elements.length - start); let i; if (meta.dataset) { meta.dataset.draw(ctx, area, start, count); } for (i = start; i < start + count; ++i) { const element = elements[i]; if (element.hidden) { continue; } if (element.active) { active.push(element); } else { element.draw(ctx, area); } } for (i = 0; i < active.length; ++i) { active[i].draw(ctx, area); } } getStyle(index, active) { const mode = active ? 'active' : 'default'; return index === undefined && this._cachedMeta.dataset ? this.resolveDatasetElementOptions(mode) : this.resolveDataElementOptions(index || 0, mode); } getContext(index, active, mode) { const me = this; const dataset = me.getDataset(); let context; if (index >= 0 && index < me._cachedMeta.data.length) { const element = me._cachedMeta.data[index]; context = element.$context || (element.$context = createDataContext(me.getContext(), index, element)); context.parsed = me.getParsed(index); context.raw = dataset.data[index]; context.index = context.dataIndex = index; } else { context = me.$context || (me.$context = createDatasetContext(me.chart.getContext(), me.index)); context.dataset = dataset; context.index = context.datasetIndex = me.index; } context.active = !!active; context.mode = mode; return context; } resolveDatasetElementOptions(mode) { return this._resolveElementOptions(this.datasetElementType.id, mode); } resolveDataElementOptions(index, mode) { return this._resolveElementOptions(this.dataElementType.id, mode, index); } _resolveElementOptions(elementType, mode = 'default', index) { const me = this; const active = mode === 'active'; const cache = me._cachedDataOpts; const cacheKey = elementType + '-' + mode; const cached = cache[cacheKey]; const sharing = me.enableOptionSharing && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(index); if (cached) { return cloneIfNotShared(cached, sharing); } const config = me.chart.config; const scopeKeys = config.datasetElementScopeKeys(me._type, elementType); const prefixes = active ? [`${elementType}Hover`, 'hover', elementType, ''] : [elementType, '']; const scopes = config.getOptionScopes(me.getDataset(), scopeKeys); const names = Object.keys(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.elements[elementType]); const context = () => me.getContext(index, active); const values = config.resolveNamedOptions(scopes, names, context, prefixes); if (values.$shared) { values.$shared = sharing; cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing)); } return values; } _resolveAnimations(index, transition, active) { const me = this; const chart = me.chart; const cache = me._cachedDataOpts; const cacheKey = `animation-${transition}`; const cached = cache[cacheKey]; if (cached) { return cached; } let options; if (chart.options.animation !== false) { const config = me.chart.config; const scopeKeys = config.datasetAnimationScopeKeys(me._type, transition); const scopes = config.getOptionScopes(me.getDataset(), scopeKeys); options = config.createResolver(scopes, me.getContext(index, active, transition)); } const animations = new Animations(chart, options && options.animations); if (options && options._cacheable) { cache[cacheKey] = Object.freeze(animations); } return animations; } getSharedOptions(options) { if (!options.$shared) { return; } return this._sharedOptions || (this._sharedOptions = Object.assign({}, options)); } includeOptions(mode, sharedOptions) { return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled; } updateElement(element, index, properties, mode) { if (isDirectUpdateMode(mode)) { Object.assign(element, properties); } else { this._resolveAnimations(index, mode).update(element, properties); } } updateSharedOptions(sharedOptions, mode, newOptions) { if (sharedOptions && !isDirectUpdateMode(mode)) { this._resolveAnimations(undefined, mode).update(sharedOptions, newOptions); } } _setStyle(element, index, mode, active) { element.active = active; const options = this.getStyle(index, active); this._resolveAnimations(index, mode, active).update(element, { options: (!active && this.getSharedOptions(options)) || options }); } removeHoverStyle(element, datasetIndex, index) { this._setStyle(element, index, 'active', false); } setHoverStyle(element, datasetIndex, index) { this._setStyle(element, index, 'active', true); } _removeDatasetHoverStyle() { const element = this._cachedMeta.dataset; if (element) { this._setStyle(element, undefined, 'active', false); } } _setDatasetHoverStyle() { const element = this._cachedMeta.dataset; if (element) { this._setStyle(element, undefined, 'active', true); } } _resyncElements(resetNewElements) { const me = this; const data = me._data; const elements = me._cachedMeta.data; for (const [method, arg1, arg2] of me._syncList) { me[method](arg1, arg2); } me._syncList = []; const numMeta = elements.length; const numData = data.length; const count = Math.min(numData, numMeta); if (count) { me.parse(0, count); } if (numData > numMeta) { me._insertElements(numMeta, numData - numMeta, resetNewElements); } else if (numData < numMeta) { me._removeElements(numData, numMeta - numData); } } _insertElements(start, count, resetNewElements = true) { const me = this; const meta = me._cachedMeta; const data = meta.data; const end = start + count; let i; const move = (arr) => { arr.length += count; for (i = arr.length - 1; i >= end; i--) { arr[i] = arr[i - count]; } }; move(data); for (i = start; i < end; ++i) { data[i] = new me.dataElementType(); } if (me._parsing) { move(meta._parsed); } me.parse(start, count); if (resetNewElements) { me.updateElements(data, start, count, 'reset'); } } updateElements(element, start, count, mode) {} _removeElements(start, count) { const me = this; const meta = me._cachedMeta; if (me._parsing) { const removed = meta._parsed.splice(start, count); if (meta._stacked) { clearStacks(meta, removed); } } meta.data.splice(start, count); } _sync(args) { if (this._parsing) { this._syncList.push(args); } else { const [method, arg1, arg2] = args; this[method](arg1, arg2); } } _onDataPush() { const count = arguments.length; this._sync(['_insertElements', this.getDataset().data.length - count, count]); } _onDataPop() { this._sync(['_removeElements', this._cachedMeta.data.length - 1, 1]); } _onDataShift() { this._sync(['_removeElements', 0, 1]); } _onDataSplice(start, count) { this._sync(['_removeElements', start, count]); this._sync(['_insertElements', start, arguments.length - 2]); } _onDataUnshift() { this._sync(['_insertElements', 0, arguments.length]); } } DatasetController.defaults = {}; DatasetController.prototype.datasetElementType = null; DatasetController.prototype.dataElementType = null; function getAllScaleValues(scale) { if (!scale._cache.$bar) { const metas = scale.getMatchingVisibleMetas('bar'); let values = []; for (let i = 0, ilen = metas.length; i < ilen; i++) { values = values.concat(metas[i].controller.getAllParsedValues(scale)); } scale._cache.$bar = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort((a, b) => a - b)); } return scale._cache.$bar; } function computeMinSampleSize(scale) { const values = getAllScaleValues(scale); let min = scale._length; let i, ilen, curr, prev; const updateMinAndPrev = () => { if (curr === 32767 || curr === -32768) { return; } if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(prev)) { min = Math.min(min, Math.abs(curr - prev) || min); } prev = curr; }; for (i = 0, ilen = values.length; i < ilen; ++i) { curr = scale.getPixelForValue(values[i]); updateMinAndPrev(); } prev = undefined; for (i = 0, ilen = scale.ticks.length; i < ilen; ++i) { curr = scale.getPixelForTick(i); updateMinAndPrev(); } return min; } function computeFitCategoryTraits(index, ruler, options, stackCount) { const thickness = options.barThickness; let size, ratio; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(thickness)) { size = ruler.min * options.categoryPercentage; ratio = options.barPercentage; } else { size = thickness * stackCount; ratio = 1; } return { chunk: size / stackCount, ratio, start: ruler.pixels[index] - (size / 2) }; } function computeFlexCategoryTraits(index, ruler, options, stackCount) { const pixels = ruler.pixels; const curr = pixels[index]; let prev = index > 0 ? pixels[index - 1] : null; let next = index < pixels.length - 1 ? pixels[index + 1] : null; const percent = options.categoryPercentage; if (prev === null) { prev = curr - (next === null ? ruler.end - ruler.start : next - curr); } if (next === null) { next = curr + curr - prev; } const start = curr - (curr - Math.min(prev, next)) / 2 * percent; const size = Math.abs(next - prev) / 2 * percent; return { chunk: size / stackCount, ratio: options.barPercentage, start }; } function parseFloatBar(entry, item, vScale, i) { const startValue = vScale.parse(entry[0], i); const endValue = vScale.parse(entry[1], i); const min = Math.min(startValue, endValue); const max = Math.max(startValue, endValue); let barStart = min; let barEnd = max; if (Math.abs(min) > Math.abs(max)) { barStart = max; barEnd = min; } item[vScale.axis] = barEnd; item._custom = { barStart, barEnd, start: startValue, end: endValue, min, max }; } function parseValue(entry, item, vScale, i) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(entry)) { parseFloatBar(entry, item, vScale, i); } else { item[vScale.axis] = vScale.parse(entry, i); } return item; } function parseArrayOrPrimitive(meta, data, start, count) { const iScale = meta.iScale; const vScale = meta.vScale; const labels = iScale.getLabels(); const singleScale = iScale === vScale; const parsed = []; let i, ilen, item, entry; for (i = start, ilen = start + count; i < ilen; ++i) { entry = data[i]; item = {}; item[iScale.axis] = singleScale || iScale.parse(labels[i], i); parsed.push(parseValue(entry, item, vScale, i)); } return parsed; } function isFloatBar(custom) { return custom && custom.barStart !== undefined && custom.barEnd !== undefined; } function barSign(size, vScale, actualBase) { if (size !== 0) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(size); } return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1); } function borderProps(properties) { let reverse, start, end, top, bottom; if (properties.horizontal) { reverse = properties.base > properties.x; start = 'left'; end = 'right'; } else { reverse = properties.base < properties.y; start = 'bottom'; end = 'top'; } if (reverse) { top = 'end'; bottom = 'start'; } else { top = 'start'; bottom = 'end'; } return {start, end, reverse, top, bottom}; } function setBorderSkipped(properties, options, stack, index) { let edge = options.borderSkipped; const res = {}; if (!edge) { properties.borderSkipped = res; return; } const {start, end, reverse, top, bottom} = borderProps(properties); if (edge === 'middle' && stack) { properties.enableBorderRadius = true; if ((stack._top || 0) === index) { edge = top; } else if ((stack._bottom || 0) === index) { edge = bottom; } else { res[parseEdge(bottom, start, end, reverse)] = true; edge = top; } } res[parseEdge(edge, start, end, reverse)] = true; properties.borderSkipped = res; } function parseEdge(edge, a, b, reverse) { if (reverse) { edge = swap(edge, a, b); edge = startEnd(edge, b, a); } else { edge = startEnd(edge, a, b); } return edge; } function swap(orig, v1, v2) { return orig === v1 ? v2 : orig === v2 ? v1 : orig; } function startEnd(v, start, end) { return v === 'start' ? start : v === 'end' ? end : v; } class BarController extends DatasetController { parsePrimitiveData(meta, data, start, count) { return parseArrayOrPrimitive(meta, data, start, count); } parseArrayData(meta, data, start, count) { return parseArrayOrPrimitive(meta, data, start, count); } parseObjectData(meta, data, start, count) { const {iScale, vScale} = meta; const {xAxisKey = 'x', yAxisKey = 'y'} = this._parsing; const iAxisKey = iScale.axis === 'x' ? xAxisKey : yAxisKey; const vAxisKey = vScale.axis === 'x' ? xAxisKey : yAxisKey; const parsed = []; let i, ilen, item, obj; for (i = start, ilen = start + count; i < ilen; ++i) { obj = data[i]; item = {}; item[iScale.axis] = iScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, iAxisKey), i); parsed.push(parseValue((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, vAxisKey), item, vScale, i)); } return parsed; } updateRangeFromParsed(range, scale, parsed, stack) { super.updateRangeFromParsed(range, scale, parsed, stack); const custom = parsed._custom; if (custom && scale === this._cachedMeta.vScale) { range.min = Math.min(range.min, custom.min); range.max = Math.max(range.max, custom.max); } } getMaxOverflow() { return 0; } getLabelAndValue(index) { const me = this; const meta = me._cachedMeta; const {iScale, vScale} = meta; const parsed = me.getParsed(index); const custom = parsed._custom; const value = isFloatBar(custom) ? '[' + custom.start + ', ' + custom.end + ']' : '' + vScale.getLabelForValue(parsed[vScale.axis]); return { label: '' + iScale.getLabelForValue(parsed[iScale.axis]), value }; } initialize() { const me = this; me.enableOptionSharing = true; super.initialize(); const meta = me._cachedMeta; meta.stack = me.getDataset().stack; } update(mode) { const me = this; const meta = me._cachedMeta; me.updateElements(meta.data, 0, meta.data.length, mode); } updateElements(bars, start, count, mode) { const me = this; const reset = mode === 'reset'; const {index, _cachedMeta: {vScale}} = me; const base = vScale.getBasePixel(); const horizontal = vScale.isHorizontal(); const ruler = me._getRuler(); const firstOpts = me.resolveDataElementOptions(start, mode); const sharedOptions = me.getSharedOptions(firstOpts); const includeOptions = me.includeOptions(mode, sharedOptions); me.updateSharedOptions(sharedOptions, mode, firstOpts); for (let i = start; i < start + count; i++) { const parsed = me.getParsed(i); const vpixels = reset || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parsed[vScale.axis]) ? {base, head: base} : me._calculateBarValuePixels(i); const ipixels = me._calculateBarIndexPixels(i, ruler); const stack = (parsed._stacks || {})[vScale.axis]; const properties = { horizontal, base: vpixels.base, enableBorderRadius: !stack || isFloatBar(parsed._custom) || (index === stack._top || index === stack._bottom), x: horizontal ? vpixels.head : ipixels.center, y: horizontal ? ipixels.center : vpixels.head, height: horizontal ? ipixels.size : Math.abs(vpixels.size), width: horizontal ? Math.abs(vpixels.size) : ipixels.size }; if (includeOptions) { properties.options = sharedOptions || me.resolveDataElementOptions(i, bars[i].active ? 'active' : mode); } setBorderSkipped(properties, properties.options || bars[i].options, stack, index); me.updateElement(bars[i], i, properties, mode); } } _getStacks(last, dataIndex) { const me = this; const meta = me._cachedMeta; const iScale = meta.iScale; const metasets = iScale.getMatchingVisibleMetas(me._type); const stacked = iScale.options.stacked; const ilen = metasets.length; const stacks = []; let i, item; for (i = 0; i < ilen; ++i) { item = metasets[i]; if (!item.controller.options.grouped) { continue; } if (typeof dataIndex !== 'undefined') { const val = item.controller.getParsed(dataIndex)[ item.controller._cachedMeta.vScale.axis ]; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(val) || isNaN(val)) { continue; } } if (stacked === false || stacks.indexOf(item.stack) === -1 || (stacked === undefined && item.stack === undefined)) { stacks.push(item.stack); } if (item.index === last) { break; } } if (!stacks.length) { stacks.push(undefined); } return stacks; } _getStackCount(index) { return this._getStacks(undefined, index).length; } _getStackIndex(datasetIndex, name, dataIndex) { const stacks = this._getStacks(datasetIndex, dataIndex); const index = (name !== undefined) ? stacks.indexOf(name) : -1; return (index === -1) ? stacks.length - 1 : index; } _getRuler() { const me = this; const opts = me.options; const meta = me._cachedMeta; const iScale = meta.iScale; const pixels = []; let i, ilen; for (i = 0, ilen = meta.data.length; i < ilen; ++i) { pixels.push(iScale.getPixelForValue(me.getParsed(i)[iScale.axis], i)); } const barThickness = opts.barThickness; const min = barThickness || computeMinSampleSize(iScale); return { min, pixels, start: iScale._startPixel, end: iScale._endPixel, stackCount: me._getStackCount(), scale: iScale, grouped: opts.grouped, ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage }; } _calculateBarValuePixels(index) { const me = this; const {_cachedMeta: {vScale, _stacked}, options: {base: baseValue, minBarLength}} = me; const actualBase = baseValue || 0; const parsed = me.getParsed(index); const custom = parsed._custom; const floating = isFloatBar(custom); let value = parsed[vScale.axis]; let start = 0; let length = _stacked ? me.applyStack(vScale, parsed, _stacked) : value; let head, size; if (length !== value) { start = length - value; length = value; } if (floating) { value = custom.barStart; length = custom.barEnd - custom.barStart; if (value !== 0 && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) !== (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(custom.barEnd)) { start = 0; } start += value; } const startValue = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(baseValue) && !floating ? baseValue : start; let base = vScale.getPixelForValue(startValue); if (me.chart.getDataVisibility(index)) { head = vScale.getPixelForValue(start + length); } else { head = base; } size = head - base; if (Math.abs(size) < minBarLength) { size = barSign(size, vScale, actualBase) * minBarLength; if (value === actualBase) { base -= size / 2; } head = base + size; } if (base === vScale.getPixelForValue(actualBase)) { const halfGrid = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(size) * vScale.getLineWidthForValue(actualBase) / 2; base += halfGrid; size -= halfGrid; } return { size, base, head, center: head + size / 2 }; } _calculateBarIndexPixels(index, ruler) { const me = this; const scale = ruler.scale; const options = me.options; const skipNull = options.skipNull; const maxBarThickness = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.maxBarThickness, Infinity); let center, size; if (ruler.grouped) { const stackCount = skipNull ? me._getStackCount(index) : ruler.stackCount; const range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options, stackCount) : computeFitCategoryTraits(index, ruler, options, stackCount); const stackIndex = me._getStackIndex(me.index, me._cachedMeta.stack, skipNull ? index : undefined); center = range.start + (range.chunk * stackIndex) + (range.chunk / 2); size = Math.min(maxBarThickness, range.chunk * range.ratio); } else { center = scale.getPixelForValue(me.getParsed(index)[scale.axis], index); size = Math.min(maxBarThickness, ruler.min * ruler.ratio); } return { base: center - size / 2, head: center + size / 2, center, size }; } draw() { const me = this; const meta = me._cachedMeta; const vScale = meta.vScale; const rects = meta.data; const ilen = rects.length; let i = 0; for (; i < ilen; ++i) { if (me.getParsed(i)[vScale.axis] !== null) { rects[i].draw(me._ctx); } } } } BarController.id = 'bar'; BarController.defaults = { datasetElementType: false, dataElementType: 'bar', categoryPercentage: 0.8, barPercentage: 0.9, grouped: true, animations: { numbers: { type: 'number', properties: ['x', 'y', 'base', 'width', 'height'] } } }; BarController.overrides = { scales: { _index_: { type: 'category', offset: true, grid: { offset: true } }, _value_: { type: 'linear', beginAtZero: true, } } }; class BubbleController extends DatasetController { initialize() { this.enableOptionSharing = true; super.initialize(); } parseObjectData(meta, data, start, count) { const {xScale, yScale} = meta; const {xAxisKey = 'x', yAxisKey = 'y'} = this._parsing; const parsed = []; let i, ilen, item; for (i = start, ilen = start + count; i < ilen; ++i) { item = data[i]; parsed.push({ x: xScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, xAxisKey), i), y: yScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, yAxisKey), i), _custom: item && item.r && +item.r }); } return parsed; } getMaxOverflow() { const {data, _parsed} = this._cachedMeta; let max = 0; for (let i = data.length - 1; i >= 0; --i) { max = Math.max(max, data[i].size() / 2, _parsed[i]._custom); } return max > 0 && max; } getLabelAndValue(index) { const me = this; const meta = me._cachedMeta; const {xScale, yScale} = meta; const parsed = me.getParsed(index); const x = xScale.getLabelForValue(parsed.x); const y = yScale.getLabelForValue(parsed.y); const r = parsed._custom; return { label: meta.label, value: '(' + x + ', ' + y + (r ? ', ' + r : '') + ')' }; } update(mode) { const me = this; const points = me._cachedMeta.data; me.updateElements(points, 0, points.length, mode); } updateElements(points, start, count, mode) { const me = this; const reset = mode === 'reset'; const {iScale, vScale} = me._cachedMeta; const firstOpts = me.resolveDataElementOptions(start, mode); const sharedOptions = me.getSharedOptions(firstOpts); const includeOptions = me.includeOptions(mode, sharedOptions); const iAxis = iScale.axis; const vAxis = vScale.axis; for (let i = start; i < start + count; i++) { const point = points[i]; const parsed = !reset && me.getParsed(i); const properties = {}; const iPixel = properties[iAxis] = reset ? iScale.getPixelForDecimal(0.5) : iScale.getPixelForValue(parsed[iAxis]); const vPixel = properties[vAxis] = reset ? vScale.getBasePixel() : vScale.getPixelForValue(parsed[vAxis]); properties.skip = isNaN(iPixel) || isNaN(vPixel); if (includeOptions) { properties.options = me.resolveDataElementOptions(i, point.active ? 'active' : mode); if (reset) { properties.options.radius = 0; } } me.updateElement(point, i, properties, mode); } me.updateSharedOptions(sharedOptions, mode, firstOpts); } resolveDataElementOptions(index, mode) { const parsed = this.getParsed(index); let values = super.resolveDataElementOptions(index, mode); if (values.$shared) { values = Object.assign({}, values, {$shared: false}); } const radius = values.radius; if (mode !== 'active') { values.radius = 0; } values.radius += (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(parsed && parsed._custom, radius); return values; } } BubbleController.id = 'bubble'; BubbleController.defaults = { datasetElementType: false, dataElementType: 'point', animations: { numbers: { type: 'number', properties: ['x', 'y', 'borderWidth', 'radius'] } } }; BubbleController.overrides = { scales: { x: { type: 'linear' }, y: { type: 'linear' } }, plugins: { tooltip: { callbacks: { title() { return ''; } } } } }; function getRatioAndOffset(rotation, circumference, cutout) { let ratioX = 1; let ratioY = 1; let offsetX = 0; let offsetY = 0; if (circumference < _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T) { const startAngle = rotation; const endAngle = startAngle + circumference; const startX = Math.cos(startAngle); const startY = Math.sin(startAngle); const endX = Math.cos(endAngle); const endY = Math.sin(endAngle); const calcMax = (angle, a, b) => (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.o)(angle, startAngle, endAngle, true) ? 1 : Math.max(a, a * cutout, b, b * cutout); const calcMin = (angle, a, b) => (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.o)(angle, startAngle, endAngle, true) ? -1 : Math.min(a, a * cutout, b, b * cutout); const maxX = calcMax(0, startX, endX); const maxY = calcMax(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY); const minX = calcMin(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P, startX, endX); const minY = calcMin(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY); ratioX = (maxX - minX) / 2; ratioY = (maxY - minY) / 2; offsetX = -(maxX + minX) / 2; offsetY = -(maxY + minY) / 2; } return {ratioX, ratioY, offsetX, offsetY}; } class DoughnutController extends DatasetController { constructor(chart, datasetIndex) { super(chart, datasetIndex); this.enableOptionSharing = true; this.innerRadius = undefined; this.outerRadius = undefined; this.offsetX = undefined; this.offsetY = undefined; } linkScales() {} parse(start, count) { const data = this.getDataset().data; const meta = this._cachedMeta; let i, ilen; for (i = start, ilen = start + count; i < ilen; ++i) { meta._parsed[i] = +data[i]; } } _getRotation() { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.rotation - 90); } _getCircumference() { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.circumference); } _getRotationExtents() { let min = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T; let max = -_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T; const me = this; for (let i = 0; i < me.chart.data.datasets.length; ++i) { if (me.chart.isDatasetVisible(i)) { const controller = me.chart.getDatasetMeta(i).controller; const rotation = controller._getRotation(); const circumference = controller._getCircumference(); min = Math.min(min, rotation); max = Math.max(max, rotation + circumference); } } return { rotation: min, circumference: max - min, }; } update(mode) { const me = this; const chart = me.chart; const {chartArea} = chart; const meta = me._cachedMeta; const arcs = meta.data; const spacing = me.getMaxBorderWidth() + me.getMaxOffset(arcs) + me.options.spacing; const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0); const cutout = Math.min((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(me.options.cutout, maxSize), 1); const chartWeight = me._getRingWeight(me.index); const {circumference, rotation} = me._getRotationExtents(); const {ratioX, ratioY, offsetX, offsetY} = getRatioAndOffset(rotation, circumference, cutout); const maxWidth = (chartArea.width - spacing) / ratioX; const maxHeight = (chartArea.height - spacing) / ratioY; const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0); const outerRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.m)(me.options.radius, maxRadius); const innerRadius = Math.max(outerRadius * cutout, 0); const radiusLength = (outerRadius - innerRadius) / me._getVisibleDatasetWeightTotal(); me.offsetX = offsetX * outerRadius; me.offsetY = offsetY * outerRadius; meta.total = me.calculateTotal(); me.outerRadius = outerRadius - radiusLength * me._getRingWeightOffset(me.index); me.innerRadius = Math.max(me.outerRadius - radiusLength * chartWeight, 0); me.updateElements(arcs, 0, arcs.length, mode); } _circumference(i, reset) { const me = this; const opts = me.options; const meta = me._cachedMeta; const circumference = me._getCircumference(); if ((reset && opts.animation.animateRotate) || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) { return 0; } return me.calculateCircumference(meta._parsed[i] * circumference / _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); } updateElements(arcs, start, count, mode) { const me = this; const reset = mode === 'reset'; const chart = me.chart; const chartArea = chart.chartArea; const opts = chart.options; const animationOpts = opts.animation; const centerX = (chartArea.left + chartArea.right) / 2; const centerY = (chartArea.top + chartArea.bottom) / 2; const animateScale = reset && animationOpts.animateScale; const innerRadius = animateScale ? 0 : me.innerRadius; const outerRadius = animateScale ? 0 : me.outerRadius; const firstOpts = me.resolveDataElementOptions(start, mode); const sharedOptions = me.getSharedOptions(firstOpts); const includeOptions = me.includeOptions(mode, sharedOptions); let startAngle = me._getRotation(); let i; for (i = 0; i < start; ++i) { startAngle += me._circumference(i, reset); } for (i = start; i < start + count; ++i) { const circumference = me._circumference(i, reset); const arc = arcs[i]; const properties = { x: centerX + me.offsetX, y: centerY + me.offsetY, startAngle, endAngle: startAngle + circumference, circumference, outerRadius, innerRadius }; if (includeOptions) { properties.options = sharedOptions || me.resolveDataElementOptions(i, arc.active ? 'active' : mode); } startAngle += circumference; me.updateElement(arc, i, properties, mode); } me.updateSharedOptions(sharedOptions, mode, firstOpts); } calculateTotal() { const meta = this._cachedMeta; const metaData = meta.data; let total = 0; let i; for (i = 0; i < metaData.length; i++) { const value = meta._parsed[i]; if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) { total += Math.abs(value); } } return total; } calculateCircumference(value) { const total = this._cachedMeta.total; if (total > 0 && !isNaN(value)) { return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T * (Math.abs(value) / total); } return 0; } getLabelAndValue(index) { const me = this; const meta = me._cachedMeta; const chart = me.chart; const labels = chart.data.labels || []; const value = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.n)(meta._parsed[index], chart.options.locale); return { label: labels[index] || '', value, }; } getMaxBorderWidth(arcs) { const me = this; let max = 0; const chart = me.chart; let i, ilen, meta, controller, options; if (!arcs) { for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) { if (chart.isDatasetVisible(i)) { meta = chart.getDatasetMeta(i); arcs = meta.data; controller = meta.controller; if (controller !== me) { controller.configure(); } break; } } } if (!arcs) { return 0; } for (i = 0, ilen = arcs.length; i < ilen; ++i) { options = controller.resolveDataElementOptions(i); if (options.borderAlign !== 'inner') { max = Math.max(max, options.borderWidth || 0, options.hoverBorderWidth || 0); } } return max; } getMaxOffset(arcs) { let max = 0; for (let i = 0, ilen = arcs.length; i < ilen; ++i) { const options = this.resolveDataElementOptions(i); max = Math.max(max, options.offset || 0, options.hoverOffset || 0); } return max; } _getRingWeightOffset(datasetIndex) { let ringWeightOffset = 0; for (let i = 0; i < datasetIndex; ++i) { if (this.chart.isDatasetVisible(i)) { ringWeightOffset += this._getRingWeight(i); } } return ringWeightOffset; } _getRingWeight(datasetIndex) { return Math.max((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.chart.data.datasets[datasetIndex].weight, 1), 0); } _getVisibleDatasetWeightTotal() { return this._getRingWeightOffset(this.chart.data.datasets.length) || 1; } } DoughnutController.id = 'doughnut'; DoughnutController.defaults = { datasetElementType: false, dataElementType: 'arc', animation: { animateRotate: true, animateScale: false }, animations: { numbers: { type: 'number', properties: ['circumference', 'endAngle', 'innerRadius', 'outerRadius', 'startAngle', 'x', 'y', 'offset', 'borderWidth', 'spacing'] }, }, cutout: '50%', rotation: 0, circumference: 360, radius: '100%', spacing: 0, indexAxis: 'r', }; DoughnutController.descriptors = { _scriptable: (name) => name !== 'spacing', _indexable: (name) => name !== 'spacing', }; DoughnutController.overrides = { aspectRatio: 1, plugins: { legend: { labels: { generateLabels(chart) { const data = chart.data; if (data.labels.length && data.datasets.length) { const {labels: {pointStyle}} = chart.legend.options; return data.labels.map((label, i) => { const meta = chart.getDatasetMeta(0); const style = meta.controller.getStyle(i); return { text: label, fillStyle: style.backgroundColor, strokeStyle: style.borderColor, lineWidth: style.borderWidth, pointStyle: pointStyle, hidden: !chart.getDataVisibility(i), index: i }; }); } return []; } }, onClick(e, legendItem, legend) { legend.chart.toggleDataVisibility(legendItem.index); legend.chart.update(); } }, tooltip: { callbacks: { title() { return ''; }, label(tooltipItem) { let dataLabel = tooltipItem.label; const value = ': ' + tooltipItem.formattedValue; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(dataLabel)) { dataLabel = dataLabel.slice(); dataLabel[0] += value; } else { dataLabel += value; } return dataLabel; } } } } }; class LineController extends DatasetController { initialize() { this.enableOptionSharing = true; super.initialize(); } update(mode) { const me = this; const meta = me._cachedMeta; const {dataset: line, data: points = [], _dataset} = meta; const animationsDisabled = me.chart._animationsDisabled; let {start, count} = getStartAndCountOfVisiblePoints(meta, points, animationsDisabled); me._drawStart = start; me._drawCount = count; if (scaleRangesChanged(meta)) { start = 0; count = points.length; } line._datasetIndex = me.index; line._decimated = !!_dataset._decimated; line.points = points; const options = me.resolveDatasetElementOptions(mode); if (!me.options.showLine) { options.borderWidth = 0; } options.segment = me.options.segment; me.updateElement(line, undefined, { animated: !animationsDisabled, options }, mode); me.updateElements(points, start, count, mode); } updateElements(points, start, count, mode) { const me = this; const reset = mode === 'reset'; const {iScale, vScale, _stacked} = me._cachedMeta; const firstOpts = me.resolveDataElementOptions(start, mode); const sharedOptions = me.getSharedOptions(firstOpts); const includeOptions = me.includeOptions(mode, sharedOptions); const iAxis = iScale.axis; const vAxis = vScale.axis; const spanGaps = me.options.spanGaps; const maxGapLength = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY; const directUpdate = me.chart._animationsDisabled || reset || mode === 'none'; let prevParsed = start > 0 && me.getParsed(start - 1); for (let i = start; i < start + count; ++i) { const point = points[i]; const parsed = me.getParsed(i); const properties = directUpdate ? point : {}; const nullData = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parsed[vAxis]); const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i); const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? me.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i); properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData; properties.stop = i > 0 && (parsed[iAxis] - prevParsed[iAxis]) > maxGapLength; properties.parsed = parsed; if (includeOptions) { properties.options = sharedOptions || me.resolveDataElementOptions(i, point.active ? 'active' : mode); } if (!directUpdate) { me.updateElement(point, i, properties, mode); } prevParsed = parsed; } me.updateSharedOptions(sharedOptions, mode, firstOpts); } getMaxOverflow() { const me = this; const meta = me._cachedMeta; const dataset = meta.dataset; const border = dataset.options && dataset.options.borderWidth || 0; const data = meta.data || []; if (!data.length) { return border; } const firstPoint = data[0].size(me.resolveDataElementOptions(0)); const lastPoint = data[data.length - 1].size(me.resolveDataElementOptions(data.length - 1)); return Math.max(border, firstPoint, lastPoint) / 2; } draw() { const meta = this._cachedMeta; meta.dataset.updateControlPoints(this.chart.chartArea, meta.iScale.axis); super.draw(); } } LineController.id = 'line'; LineController.defaults = { datasetElementType: 'line', dataElementType: 'point', showLine: true, spanGaps: false, }; LineController.overrides = { scales: { _index_: { type: 'category', }, _value_: { type: 'linear', }, } }; function getStartAndCountOfVisiblePoints(meta, points, animationsDisabled) { const pointCount = points.length; let start = 0; let count = pointCount; if (meta._sorted) { const {iScale, _parsed} = meta; const axis = iScale.axis; const {min, max, minDefined, maxDefined} = iScale.getUserBounds(); if (minDefined) { start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(Math.min( (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(_parsed, iScale.axis, min).lo, animationsDisabled ? pointCount : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(points, axis, iScale.getPixelForValue(min)).lo), 0, pointCount - 1); } if (maxDefined) { count = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(Math.max( (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(_parsed, iScale.axis, max).hi + 1, animationsDisabled ? 0 : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(points, axis, iScale.getPixelForValue(max)).hi + 1), start, pointCount) - start; } else { count = pointCount - start; } } return {start, count}; } function scaleRangesChanged(meta) { const {xScale, yScale, _scaleRanges} = meta; const newRanges = { xmin: xScale.min, xmax: xScale.max, ymin: yScale.min, ymax: yScale.max }; if (!_scaleRanges) { meta._scaleRanges = newRanges; return true; } const changed = _scaleRanges.xmin !== xScale.min || _scaleRanges.xmax !== xScale.max || _scaleRanges.ymin !== yScale.min || _scaleRanges.ymax !== yScale.max; Object.assign(_scaleRanges, newRanges); return changed; } class PolarAreaController extends DatasetController { constructor(chart, datasetIndex) { super(chart, datasetIndex); this.innerRadius = undefined; this.outerRadius = undefined; } getLabelAndValue(index) { const me = this; const meta = me._cachedMeta; const chart = me.chart; const labels = chart.data.labels || []; const value = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.n)(meta._parsed[index].r, chart.options.locale); return { label: labels[index] || '', value, }; } update(mode) { const arcs = this._cachedMeta.data; this._updateRadius(); this.updateElements(arcs, 0, arcs.length, mode); } _updateRadius() { const me = this; const chart = me.chart; const chartArea = chart.chartArea; const opts = chart.options; const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); const outerRadius = Math.max(minSize / 2, 0); const innerRadius = Math.max(opts.cutoutPercentage ? (outerRadius / 100) * (opts.cutoutPercentage) : 1, 0); const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount(); me.outerRadius = outerRadius - (radiusLength * me.index); me.innerRadius = me.outerRadius - radiusLength; } updateElements(arcs, start, count, mode) { const me = this; const reset = mode === 'reset'; const chart = me.chart; const dataset = me.getDataset(); const opts = chart.options; const animationOpts = opts.animation; const scale = me._cachedMeta.rScale; const centerX = scale.xCenter; const centerY = scale.yCenter; const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P; let angle = datasetStartAngle; let i; const defaultAngle = 360 / me.countVisibleElements(); for (i = 0; i < start; ++i) { angle += me._computeAngle(i, mode, defaultAngle); } for (i = start; i < start + count; i++) { const arc = arcs[i]; let startAngle = angle; let endAngle = angle + me._computeAngle(i, mode, defaultAngle); let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(dataset.data[i]) : 0; angle = endAngle; if (reset) { if (animationOpts.animateScale) { outerRadius = 0; } if (animationOpts.animateRotate) { startAngle = endAngle = datasetStartAngle; } } const properties = { x: centerX, y: centerY, innerRadius: 0, outerRadius, startAngle, endAngle, options: me.resolveDataElementOptions(i, arc.active ? 'active' : mode) }; me.updateElement(arc, i, properties, mode); } } countVisibleElements() { const dataset = this.getDataset(); const meta = this._cachedMeta; let count = 0; meta.data.forEach((element, index) => { if (!isNaN(dataset.data[index]) && this.chart.getDataVisibility(index)) { count++; } }); return count; } _computeAngle(index, mode, defaultAngle) { return this.chart.getDataVisibility(index) ? (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.resolveDataElementOptions(index, mode).angle || defaultAngle) : 0; } } PolarAreaController.id = 'polarArea'; PolarAreaController.defaults = { dataElementType: 'arc', animation: { animateRotate: true, animateScale: true }, animations: { numbers: { type: 'number', properties: ['x', 'y', 'startAngle', 'endAngle', 'innerRadius', 'outerRadius'] }, }, indexAxis: 'r', startAngle: 0, }; PolarAreaController.overrides = { aspectRatio: 1, plugins: { legend: { labels: { generateLabels(chart) { const data = chart.data; if (data.labels.length && data.datasets.length) { const {labels: {pointStyle}} = chart.legend.options; return data.labels.map((label, i) => { const meta = chart.getDatasetMeta(0); const style = meta.controller.getStyle(i); return { text: label, fillStyle: style.backgroundColor, strokeStyle: style.borderColor, lineWidth: style.borderWidth, pointStyle: pointStyle, hidden: !chart.getDataVisibility(i), index: i }; }); } return []; } }, onClick(e, legendItem, legend) { legend.chart.toggleDataVisibility(legendItem.index); legend.chart.update(); } }, tooltip: { callbacks: { title() { return ''; }, label(context) { return context.chart.data.labels[context.dataIndex] + ': ' + context.formattedValue; } } } }, scales: { r: { type: 'radialLinear', angleLines: { display: false }, beginAtZero: true, grid: { circular: true }, pointLabels: { display: false }, startAngle: 0 } } }; class PieController extends DoughnutController { } PieController.id = 'pie'; PieController.defaults = { cutout: 0, rotation: 0, circumference: 360, radius: '100%' }; class RadarController extends DatasetController { getLabelAndValue(index) { const me = this; const vScale = me._cachedMeta.vScale; const parsed = me.getParsed(index); return { label: vScale.getLabels()[index], value: '' + vScale.getLabelForValue(parsed[vScale.axis]) }; } update(mode) { const me = this; const meta = me._cachedMeta; const line = meta.dataset; const points = meta.data || []; const labels = meta.iScale.getLabels(); line.points = points; if (mode !== 'resize') { const options = me.resolveDatasetElementOptions(mode); if (!me.options.showLine) { options.borderWidth = 0; } const properties = { _loop: true, _fullLoop: labels.length === points.length, options }; me.updateElement(line, undefined, properties, mode); } me.updateElements(points, 0, points.length, mode); } updateElements(points, start, count, mode) { const me = this; const dataset = me.getDataset(); const scale = me._cachedMeta.rScale; const reset = mode === 'reset'; for (let i = start; i < start + count; i++) { const point = points[i]; const options = me.resolveDataElementOptions(i, point.active ? 'active' : mode); const pointPosition = scale.getPointPositionForValue(i, dataset.data[i]); const x = reset ? scale.xCenter : pointPosition.x; const y = reset ? scale.yCenter : pointPosition.y; const properties = { x, y, angle: pointPosition.angle, skip: isNaN(x) || isNaN(y), options }; me.updateElement(point, i, properties, mode); } } } RadarController.id = 'radar'; RadarController.defaults = { datasetElementType: 'line', dataElementType: 'point', indexAxis: 'r', showLine: true, elements: { line: { fill: 'start' } }, }; RadarController.overrides = { aspectRatio: 1, scales: { r: { type: 'radialLinear', } } }; class ScatterController extends LineController { } ScatterController.id = 'scatter'; ScatterController.defaults = { showLine: false, fill: false }; ScatterController.overrides = { interaction: { mode: 'point' }, plugins: { tooltip: { callbacks: { title() { return ''; }, label(item) { return '(' + item.label + ', ' + item.formattedValue + ')'; } } } }, scales: { x: { type: 'linear' }, y: { type: 'linear' } } }; var controllers = /*#__PURE__*/Object.freeze({ __proto__: null, BarController: BarController, BubbleController: BubbleController, DoughnutController: DoughnutController, LineController: LineController, PolarAreaController: PolarAreaController, PieController: PieController, RadarController: RadarController, ScatterController: ScatterController }); function abstract() { throw new Error('This method is not implemented: Check that a complete date adapter is provided.'); } class DateAdapter { constructor(options) { this.options = options || {}; } formats() { return abstract(); } parse(value, format) { return abstract(); } format(timestamp, format) { return abstract(); } add(timestamp, amount, unit) { return abstract(); } diff(a, b, unit) { return abstract(); } startOf(timestamp, unit, weekday) { return abstract(); } endOf(timestamp, unit) { return abstract(); } } DateAdapter.override = function(members) { Object.assign(DateAdapter.prototype, members); }; var adapters = { _date: DateAdapter }; function getRelativePosition(e, chart) { if ('native' in e) { return { x: e.x, y: e.y }; } return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(e, chart); } function evaluateAllVisibleItems(chart, handler) { const metasets = chart.getSortedVisibleDatasetMetas(); let index, data, element; for (let i = 0, ilen = metasets.length; i < ilen; ++i) { ({index, data} = metasets[i]); for (let j = 0, jlen = data.length; j < jlen; ++j) { element = data[j]; if (!element.skip) { handler(element, index, j); } } } } function binarySearch(metaset, axis, value, intersect) { const {controller, data, _sorted} = metaset; const iScale = controller._cachedMeta.iScale; if (iScale && axis === iScale.axis && _sorted && data.length) { const lookupMethod = iScale._reversePixels ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z : _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w; if (!intersect) { return lookupMethod(data, axis, value); } else if (controller._sharedOptions) { const el = data[0]; const range = typeof el.getRange === 'function' && el.getRange(axis); if (range) { const start = lookupMethod(data, axis, value - range); const end = lookupMethod(data, axis, value + range); return {lo: start.lo, hi: end.hi}; } } } return {lo: 0, hi: data.length - 1}; } function optimizedEvaluateItems(chart, axis, position, handler, intersect) { const metasets = chart.getSortedVisibleDatasetMetas(); const value = position[axis]; for (let i = 0, ilen = metasets.length; i < ilen; ++i) { const {index, data} = metasets[i]; const {lo, hi} = binarySearch(metasets[i], axis, value, intersect); for (let j = lo; j <= hi; ++j) { const element = data[j]; if (!element.skip) { handler(element, index, j); } } } } function getDistanceMetricForAxis(axis) { const useX = axis.indexOf('x') !== -1; const useY = axis.indexOf('y') !== -1; return function(pt1, pt2) { const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0; const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0; return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); }; } function getIntersectItems(chart, position, axis, useFinalPosition) { const items = []; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.y)(position, chart.chartArea, chart._minPadding)) { return items; } const evaluationFunc = function(element, datasetIndex, index) { if (element.inRange(position.x, position.y, useFinalPosition)) { items.push({element, datasetIndex, index}); } }; optimizedEvaluateItems(chart, axis, position, evaluationFunc, true); return items; } function getNearestItems(chart, position, axis, intersect, useFinalPosition) { const distanceMetric = getDistanceMetricForAxis(axis); let minDistance = Number.POSITIVE_INFINITY; let items = []; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.y)(position, chart.chartArea, chart._minPadding)) { return items; } const evaluationFunc = function(element, datasetIndex, index) { if (intersect && !element.inRange(position.x, position.y, useFinalPosition)) { return; } const center = element.getCenterPoint(useFinalPosition); if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.y)(center, chart.chartArea, chart._minPadding) && !element.inRange(position.x, position.y, useFinalPosition)) { return; } const distance = distanceMetric(position, center); if (distance < minDistance) { items = [{element, datasetIndex, index}]; minDistance = distance; } else if (distance === minDistance) { items.push({element, datasetIndex, index}); } }; optimizedEvaluateItems(chart, axis, position, evaluationFunc); return items; } function getAxisItems(chart, e, options, useFinalPosition) { const position = getRelativePosition(e, chart); const items = []; const axis = options.axis; const rangeMethod = axis === 'x' ? 'inXRange' : 'inYRange'; let intersectsItem = false; evaluateAllVisibleItems(chart, (element, datasetIndex, index) => { if (element[rangeMethod](position[axis], useFinalPosition)) { items.push({element, datasetIndex, index}); } if (element.inRange(position.x, position.y, useFinalPosition)) { intersectsItem = true; } }); if (options.intersect && !intersectsItem) { return []; } return items; } var Interaction = { modes: { index(chart, e, options, useFinalPosition) { const position = getRelativePosition(e, chart); const axis = options.axis || 'x'; const items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition) : getNearestItems(chart, position, axis, false, useFinalPosition); const elements = []; if (!items.length) { return []; } chart.getSortedVisibleDatasetMetas().forEach((meta) => { const index = items[0].index; const element = meta.data[index]; if (element && !element.skip) { elements.push({element, datasetIndex: meta.index, index}); } }); return elements; }, dataset(chart, e, options, useFinalPosition) { const position = getRelativePosition(e, chart); const axis = options.axis || 'xy'; let items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition) : getNearestItems(chart, position, axis, false, useFinalPosition); if (items.length > 0) { const datasetIndex = items[0].datasetIndex; const data = chart.getDatasetMeta(datasetIndex).data; items = []; for (let i = 0; i < data.length; ++i) { items.push({element: data[i], datasetIndex, index: i}); } } return items; }, point(chart, e, options, useFinalPosition) { const position = getRelativePosition(e, chart); const axis = options.axis || 'xy'; return getIntersectItems(chart, position, axis, useFinalPosition); }, nearest(chart, e, options, useFinalPosition) { const position = getRelativePosition(e, chart); const axis = options.axis || 'xy'; return getNearestItems(chart, position, axis, options.intersect, useFinalPosition); }, x(chart, e, options, useFinalPosition) { options.axis = 'x'; return getAxisItems(chart, e, options, useFinalPosition); }, y(chart, e, options, useFinalPosition) { options.axis = 'y'; return getAxisItems(chart, e, options, useFinalPosition); } } }; const STATIC_POSITIONS = ['left', 'top', 'right', 'bottom']; function filterByPosition(array, position) { return array.filter(v => v.pos === position); } function filterDynamicPositionByAxis(array, axis) { return array.filter(v => STATIC_POSITIONS.indexOf(v.pos) === -1 && v.box.axis === axis); } function sortByWeight(array, reverse) { return array.sort((a, b) => { const v0 = reverse ? b : a; const v1 = reverse ? a : b; return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight; }); } function wrapBoxes(boxes) { const layoutBoxes = []; let i, ilen, box, pos, stack, stackWeight; for (i = 0, ilen = (boxes || []).length; i < ilen; ++i) { box = boxes[i]; ({position: pos, options: {stack, stackWeight = 1}} = box); layoutBoxes.push({ index: i, box, pos, horizontal: box.isHorizontal(), weight: box.weight, stack: stack && (pos + stack), stackWeight }); } return layoutBoxes; } function buildStacks(layouts) { const stacks = {}; for (const wrap of layouts) { const {stack, pos, stackWeight} = wrap; if (!stack || !STATIC_POSITIONS.includes(pos)) { continue; } const _stack = stacks[stack] || (stacks[stack] = {count: 0, placed: 0, weight: 0, size: 0}); _stack.count++; _stack.weight += stackWeight; } return stacks; } function setLayoutDims(layouts, params) { const stacks = buildStacks(layouts); const {vBoxMaxWidth, hBoxMaxHeight} = params; let i, ilen, layout; for (i = 0, ilen = layouts.length; i < ilen; ++i) { layout = layouts[i]; const {fullSize} = layout.box; const stack = stacks[layout.stack]; const factor = stack && layout.stackWeight / stack.weight; if (layout.horizontal) { layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth; layout.height = hBoxMaxHeight; } else { layout.width = vBoxMaxWidth; layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight; } } return stacks; } function buildLayoutBoxes(boxes) { const layoutBoxes = wrapBoxes(boxes); const fullSize = sortByWeight(layoutBoxes.filter(wrap => wrap.box.fullSize), true); const left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true); const right = sortByWeight(filterByPosition(layoutBoxes, 'right')); const top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true); const bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom')); const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, 'x'); const centerVertical = filterDynamicPositionByAxis(layoutBoxes, 'y'); return { fullSize, leftAndTop: left.concat(top), rightAndBottom: right.concat(centerVertical).concat(bottom).concat(centerHorizontal), chartArea: filterByPosition(layoutBoxes, 'chartArea'), vertical: left.concat(right).concat(centerVertical), horizontal: top.concat(bottom).concat(centerHorizontal) }; } function getCombinedMax(maxPadding, chartArea, a, b) { return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]); } function updateMaxPadding(maxPadding, boxPadding) { maxPadding.top = Math.max(maxPadding.top, boxPadding.top); maxPadding.left = Math.max(maxPadding.left, boxPadding.left); maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom); maxPadding.right = Math.max(maxPadding.right, boxPadding.right); } function updateDims(chartArea, params, layout, stacks) { const {pos, box} = layout; const maxPadding = chartArea.maxPadding; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(pos)) { if (layout.size) { chartArea[pos] -= layout.size; } const stack = stacks[layout.stack] || {size: 0, count: 1}; stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width); layout.size = stack.size / stack.count; chartArea[pos] += layout.size; } if (box.getPadding) { updateMaxPadding(maxPadding, box.getPadding()); } const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right')); const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom')); const widthChanged = newWidth !== chartArea.w; const heightChanged = newHeight !== chartArea.h; chartArea.w = newWidth; chartArea.h = newHeight; return layout.horizontal ? {same: widthChanged, other: heightChanged} : {same: heightChanged, other: widthChanged}; } function handleMaxPadding(chartArea) { const maxPadding = chartArea.maxPadding; function updatePos(pos) { const change = Math.max(maxPadding[pos] - chartArea[pos], 0); chartArea[pos] += change; return change; } chartArea.y += updatePos('top'); chartArea.x += updatePos('left'); updatePos('right'); updatePos('bottom'); } function getMargins(horizontal, chartArea) { const maxPadding = chartArea.maxPadding; function marginForPositions(positions) { const margin = {left: 0, top: 0, right: 0, bottom: 0}; positions.forEach((pos) => { margin[pos] = Math.max(chartArea[pos], maxPadding[pos]); }); return margin; } return horizontal ? marginForPositions(['left', 'right']) : marginForPositions(['top', 'bottom']); } function fitBoxes(boxes, chartArea, params, stacks) { const refitBoxes = []; let i, ilen, layout, box, refit, changed; for (i = 0, ilen = boxes.length, refit = 0; i < ilen; ++i) { layout = boxes[i]; box = layout.box; box.update( layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea) ); const {same, other} = updateDims(chartArea, params, layout, stacks); refit |= same && refitBoxes.length; changed = changed || other; if (!box.fullSize) { refitBoxes.push(layout); } } return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed; } function setBoxDims(box, left, top, width, height) { box.top = top; box.left = left; box.right = left + width; box.bottom = top + height; box.width = width; box.height = height; } function placeBoxes(boxes, chartArea, params, stacks) { const userPadding = params.padding; let {x, y} = chartArea; for (const layout of boxes) { const box = layout.box; const stack = stacks[layout.stack] || {count: 1, placed: 0, weight: 1}; const weight = (layout.stackWeight / stack.weight) || 1; if (layout.horizontal) { const width = chartArea.w * weight; const height = stack.size || box.height; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) { y = stack.start; } if (box.fullSize) { setBoxDims(box, userPadding.left, y, params.outerWidth - userPadding.right - userPadding.left, height); } else { setBoxDims(box, chartArea.left + stack.placed, y, width, height); } stack.start = y; stack.placed += width; y = box.bottom; } else { const height = chartArea.h * weight; const width = stack.size || box.width; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) { x = stack.start; } if (box.fullSize) { setBoxDims(box, x, userPadding.top, width, params.outerHeight - userPadding.bottom - userPadding.top); } else { setBoxDims(box, x, chartArea.top + stack.placed, width, height); } stack.start = x; stack.placed += height; x = box.right; } } chartArea.x = x; chartArea.y = y; } _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.set('layout', { padding: { top: 0, right: 0, bottom: 0, left: 0 } }); var layouts = { addBox(chart, item) { if (!chart.boxes) { chart.boxes = []; } item.fullSize = item.fullSize || false; item.position = item.position || 'top'; item.weight = item.weight || 0; item._layers = item._layers || function() { return [{ z: 0, draw(chartArea) { item.draw(chartArea); } }]; }; chart.boxes.push(item); }, removeBox(chart, layoutItem) { const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1; if (index !== -1) { chart.boxes.splice(index, 1); } }, configure(chart, item, options) { item.fullSize = options.fullSize; item.position = options.position; item.weight = options.weight; }, update(chart, width, height, minPadding) { if (!chart) { return; } const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(chart.options.layout.padding); const availableWidth = Math.max(width - padding.width, 0); const availableHeight = Math.max(height - padding.height, 0); const boxes = buildLayoutBoxes(chart.boxes); const verticalBoxes = boxes.vertical; const horizontalBoxes = boxes.horizontal; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(chart.boxes, box => { if (typeof box.beforeLayout === 'function') { box.beforeLayout(); } }); const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap) => wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1; const params = Object.freeze({ outerWidth: width, outerHeight: height, padding, availableWidth, availableHeight, vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount, hBoxMaxHeight: availableHeight / 2 }); const maxPadding = Object.assign({}, padding); updateMaxPadding(maxPadding, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(minPadding)); const chartArea = Object.assign({ maxPadding, w: availableWidth, h: availableHeight, x: padding.left, y: padding.top }, padding); const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params); fitBoxes(boxes.fullSize, chartArea, params, stacks); fitBoxes(verticalBoxes, chartArea, params, stacks); if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) { fitBoxes(verticalBoxes, chartArea, params, stacks); } handleMaxPadding(chartArea); placeBoxes(boxes.leftAndTop, chartArea, params, stacks); chartArea.x += chartArea.w; chartArea.y += chartArea.h; placeBoxes(boxes.rightAndBottom, chartArea, params, stacks); chart.chartArea = { left: chartArea.left, top: chartArea.top, right: chartArea.left + chartArea.w, bottom: chartArea.top + chartArea.h, height: chartArea.h, width: chartArea.w, }; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(boxes.chartArea, (layout) => { const box = layout.box; Object.assign(box, chart.chartArea); box.update(chartArea.w, chartArea.h); }); } }; class BasePlatform { acquireContext(canvas, aspectRatio) {} releaseContext(context) { return false; } addEventListener(chart, type, listener) {} removeEventListener(chart, type, listener) {} getDevicePixelRatio() { return 1; } getMaximumSize(element, width, height, aspectRatio) { width = Math.max(0, width || element.width); height = height || element.height; return { width, height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height) }; } isAttached(canvas) { return true; } } class BasicPlatform extends BasePlatform { acquireContext(item) { return item && item.getContext && item.getContext('2d') || null; } } const EXPANDO_KEY = '$chartjs'; const EVENT_TYPES = { touchstart: 'mousedown', touchmove: 'mousemove', touchend: 'mouseup', pointerenter: 'mouseenter', pointerdown: 'mousedown', pointermove: 'mousemove', pointerup: 'mouseup', pointerleave: 'mouseout', pointerout: 'mouseout' }; const isNullOrEmpty = value => value === null || value === ''; function initCanvas(canvas, aspectRatio) { const style = canvas.style; const renderHeight = canvas.getAttribute('height'); const renderWidth = canvas.getAttribute('width'); canvas[EXPANDO_KEY] = { initial: { height: renderHeight, width: renderWidth, style: { display: style.display, height: style.height, width: style.width } } }; style.display = style.display || 'block'; style.boxSizing = style.boxSizing || 'border-box'; if (isNullOrEmpty(renderWidth)) { const displayWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(canvas, 'width'); if (displayWidth !== undefined) { canvas.width = displayWidth; } } if (isNullOrEmpty(renderHeight)) { if (canvas.style.height === '') { canvas.height = canvas.width / (aspectRatio || 2); } else { const displayHeight = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(canvas, 'height'); if (displayHeight !== undefined) { canvas.height = displayHeight; } } } return canvas; } const eventListenerOptions = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.G ? {passive: true} : false; function addListener(node, type, listener) { node.addEventListener(type, listener, eventListenerOptions); } function removeListener(chart, type, listener) { chart.canvas.removeEventListener(type, listener, eventListenerOptions); } function fromNativeEvent(event, chart) { const type = EVENT_TYPES[event.type] || event.type; const {x, y} = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(event, chart); return { type, chart, native: event, x: x !== undefined ? x : null, y: y !== undefined ? y : null, }; } function createAttachObserver(chart, type, listener) { const canvas = chart.canvas; const container = canvas && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.D)(canvas); const element = container || canvas; const observer = new MutationObserver(entries => { const parent = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.D)(element); entries.forEach(entry => { for (let i = 0; i < entry.addedNodes.length; i++) { const added = entry.addedNodes[i]; if (added === element || added === parent) { listener(entry.target); } } }); }); observer.observe(document, {childList: true, subtree: true}); return observer; } function createDetachObserver(chart, type, listener) { const canvas = chart.canvas; const container = canvas && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.D)(canvas); if (!container) { return; } const observer = new MutationObserver(entries => { entries.forEach(entry => { for (let i = 0; i < entry.removedNodes.length; i++) { if (entry.removedNodes[i] === canvas) { listener(); break; } } }); }); observer.observe(container, {childList: true}); return observer; } const drpListeningCharts = new Map(); let oldDevicePixelRatio = 0; function onWindowResize() { const dpr = window.devicePixelRatio; if (dpr === oldDevicePixelRatio) { return; } oldDevicePixelRatio = dpr; drpListeningCharts.forEach((resize, chart) => { if (chart.currentDevicePixelRatio !== dpr) { resize(); } }); } function listenDevicePixelRatioChanges(chart, resize) { if (!drpListeningCharts.size) { window.addEventListener('resize', onWindowResize); } drpListeningCharts.set(chart, resize); } function unlistenDevicePixelRatioChanges(chart) { drpListeningCharts.delete(chart); if (!drpListeningCharts.size) { window.removeEventListener('resize', onWindowResize); } } function createResizeObserver(chart, type, listener) { const canvas = chart.canvas; const container = canvas && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.D)(canvas); if (!container) { return; } const resize = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)((width, height) => { const w = container.clientWidth; listener(width, height); if (w < container.clientWidth) { listener(); } }, window); const observer = new ResizeObserver(entries => { const entry = entries[0]; const width = entry.contentRect.width; const height = entry.contentRect.height; if (width === 0 && height === 0) { return; } resize(width, height); }); observer.observe(container); listenDevicePixelRatioChanges(chart, resize); return observer; } function releaseObserver(chart, type, observer) { if (observer) { observer.disconnect(); } if (type === 'resize') { unlistenDevicePixelRatioChanges(chart); } } function createProxyAndListen(chart, type, listener) { const canvas = chart.canvas; const proxy = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)((event) => { if (chart.ctx !== null) { listener(fromNativeEvent(event, chart)); } }, chart, (args) => { const event = args[0]; return [event, event.offsetX, event.offsetY]; }); addListener(canvas, type, proxy); return proxy; } class DomPlatform extends BasePlatform { acquireContext(canvas, aspectRatio) { const context = canvas && canvas.getContext && canvas.getContext('2d'); if (context && context.canvas === canvas) { initCanvas(canvas, aspectRatio); return context; } return null; } releaseContext(context) { const canvas = context.canvas; if (!canvas[EXPANDO_KEY]) { return false; } const initial = canvas[EXPANDO_KEY].initial; ['height', 'width'].forEach((prop) => { const value = initial[prop]; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(value)) { canvas.removeAttribute(prop); } else { canvas.setAttribute(prop, value); } }); const style = initial.style || {}; Object.keys(style).forEach((key) => { canvas.style[key] = style[key]; }); canvas.width = canvas.width; delete canvas[EXPANDO_KEY]; return true; } addEventListener(chart, type, listener) { this.removeEventListener(chart, type); const proxies = chart.$proxies || (chart.$proxies = {}); const handlers = { attach: createAttachObserver, detach: createDetachObserver, resize: createResizeObserver }; const handler = handlers[type] || createProxyAndListen; proxies[type] = handler(chart, type, listener); } removeEventListener(chart, type) { const proxies = chart.$proxies || (chart.$proxies = {}); const proxy = proxies[type]; if (!proxy) { return; } const handlers = { attach: releaseObserver, detach: releaseObserver, resize: releaseObserver }; const handler = handlers[type] || removeListener; handler(chart, type, proxy); proxies[type] = undefined; } getDevicePixelRatio() { return window.devicePixelRatio; } getMaximumSize(canvas, width, height, aspectRatio) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)(canvas, width, height, aspectRatio); } isAttached(canvas) { const container = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.D)(canvas); return !!(container && container.isConnected); } } function _detectPlatform(canvas) { if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.I)() || (typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas)) { return BasicPlatform; } return DomPlatform; } class Element { constructor() { this.x = undefined; this.y = undefined; this.active = false; this.options = undefined; this.$animations = undefined; } tooltipPosition(useFinalPosition) { const {x, y} = this.getProps(['x', 'y'], useFinalPosition); return {x, y}; } hasValue() { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(this.x) && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(this.y); } getProps(props, final) { const me = this; const anims = this.$animations; if (!final || !anims) { return me; } const ret = {}; props.forEach(prop => { ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : me[prop]; }); return ret; } } Element.defaults = {}; Element.defaultRoutes = undefined; const formatters = { values(value) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(value) ? value : '' + value; }, numeric(tickValue, index, ticks) { if (tickValue === 0) { return '0'; } const locale = this.chart.options.locale; let notation; let delta = tickValue; if (ticks.length > 1) { const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value)); if (maxTick < 1e-4 || maxTick > 1e+15) { notation = 'scientific'; } delta = calculateDelta(tickValue, ticks); } const logDelta = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(Math.abs(delta)); const numDecimal = Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0); const options = {notation, minimumFractionDigits: numDecimal, maximumFractionDigits: numDecimal}; Object.assign(options, this.options.ticks.format); return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.n)(tickValue, locale, options); }, logarithmic(tickValue, index, ticks) { if (tickValue === 0) { return '0'; } const remain = tickValue / (Math.pow(10, Math.floor((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(tickValue)))); if (remain === 1 || remain === 2 || remain === 5) { return formatters.numeric.call(this, tickValue, index, ticks); } return ''; } }; function calculateDelta(tickValue, ticks) { let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value; if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) { delta = tickValue - Math.floor(tickValue); } return delta; } var Ticks = {formatters}; _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.set('scale', { display: true, offset: false, reverse: false, beginAtZero: false, bounds: 'ticks', grace: 0, grid: { display: true, lineWidth: 1, drawBorder: true, drawOnChartArea: true, drawTicks: true, tickLength: 8, tickWidth: (_ctx, options) => options.lineWidth, tickColor: (_ctx, options) => options.color, offset: false, borderDash: [], borderDashOffset: 0.0, borderWidth: 1 }, title: { display: false, text: '', padding: { top: 4, bottom: 4 } }, ticks: { minRotation: 0, maxRotation: 50, mirror: false, textStrokeWidth: 0, textStrokeColor: '', padding: 3, display: true, autoSkip: true, autoSkipPadding: 3, labelOffset: 0, callback: Ticks.formatters.values, minor: {}, major: {}, align: 'center', crossAlign: 'near', showLabelBackdrop: false, backdropColor: 'rgba(255, 255, 255, 0.75)', backdropPadding: 2, } }); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.route('scale.ticks', 'color', '', 'color'); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.route('scale.grid', 'color', '', 'borderColor'); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.route('scale.grid', 'borderColor', '', 'borderColor'); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.route('scale.title', 'color', '', 'color'); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.describe('scale', { _fallback: false, _scriptable: (name) => !name.startsWith('before') && !name.startsWith('after') && name !== 'callback' && name !== 'parser', _indexable: (name) => name !== 'borderDash' && name !== 'tickBorderDash', }); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.describe('scales', { _fallback: 'scale', }); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.describe('scale.ticks', { _scriptable: (name) => name !== 'backdropPadding' && name !== 'callback', _indexable: (name) => name !== 'backdropPadding', }); function autoSkip(scale, ticks) { const tickOpts = scale.options.ticks; const ticksLimit = tickOpts.maxTicksLimit || determineMaxTicks(scale); const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : []; const numMajorIndices = majorIndices.length; const first = majorIndices[0]; const last = majorIndices[numMajorIndices - 1]; const newTicks = []; if (numMajorIndices > ticksLimit) { skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit); return newTicks; } const spacing = calculateSpacing(majorIndices, ticks, ticksLimit); if (numMajorIndices > 0) { let i, ilen; const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null; skip(ticks, newTicks, spacing, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first); for (i = 0, ilen = numMajorIndices - 1; i < ilen; i++) { skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]); } skip(ticks, newTicks, spacing, last, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing); return newTicks; } skip(ticks, newTicks, spacing); return newTicks; } function determineMaxTicks(scale) { const offset = scale.options.offset; const tickLength = scale._tickSize(); const maxScale = scale._length / tickLength + (offset ? 0 : 1); const maxChart = scale._maxLength / tickLength; return Math.floor(Math.min(maxScale, maxChart)); } function calculateSpacing(majorIndices, ticks, ticksLimit) { const evenMajorSpacing = getEvenSpacing(majorIndices); const spacing = ticks.length / ticksLimit; if (!evenMajorSpacing) { return Math.max(spacing, 1); } const factors = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.K)(evenMajorSpacing); for (let i = 0, ilen = factors.length - 1; i < ilen; i++) { const factor = factors[i]; if (factor > spacing) { return factor; } } return Math.max(spacing, 1); } function getMajorIndices(ticks) { const result = []; let i, ilen; for (i = 0, ilen = ticks.length; i < ilen; i++) { if (ticks[i].major) { result.push(i); } } return result; } function skipMajors(ticks, newTicks, majorIndices, spacing) { let count = 0; let next = majorIndices[0]; let i; spacing = Math.ceil(spacing); for (i = 0; i < ticks.length; i++) { if (i === next) { newTicks.push(ticks[i]); count++; next = majorIndices[count * spacing]; } } } function skip(ticks, newTicks, spacing, majorStart, majorEnd) { const start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorStart, 0); const end = Math.min((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorEnd, ticks.length), ticks.length); let count = 0; let length, i, next; spacing = Math.ceil(spacing); if (majorEnd) { length = majorEnd - majorStart; spacing = length / Math.floor(length / spacing); } next = start; while (next < 0) { count++; next = Math.round(start + count * spacing); } for (i = Math.max(start, 0); i < end; i++) { if (i === next) { newTicks.push(ticks[i]); count++; next = Math.round(start + count * spacing); } } } function getEvenSpacing(arr) { const len = arr.length; let i, diff; if (len < 2) { return false; } for (diff = arr[0], i = 1; i < len; ++i) { if (arr[i] - arr[i - 1] !== diff) { return false; } } return diff; } const reverseAlign = (align) => align === 'left' ? 'right' : align === 'right' ? 'left' : align; const offsetFromEdge = (scale, edge, offset) => edge === 'top' || edge === 'left' ? scale[edge] + offset : scale[edge] - offset; function sample(arr, numItems) { const result = []; const increment = arr.length / numItems; const len = arr.length; let i = 0; for (; i < len; i += increment) { result.push(arr[Math.floor(i)]); } return result; } function getPixelForGridLine(scale, index, offsetGridLines) { const length = scale.ticks.length; const validIndex = Math.min(index, length - 1); const start = scale._startPixel; const end = scale._endPixel; const epsilon = 1e-6; let lineValue = scale.getPixelForTick(validIndex); let offset; if (offsetGridLines) { if (length === 1) { offset = Math.max(lineValue - start, end - lineValue); } else if (index === 0) { offset = (scale.getPixelForTick(1) - lineValue) / 2; } else { offset = (lineValue - scale.getPixelForTick(validIndex - 1)) / 2; } lineValue += validIndex < index ? offset : -offset; if (lineValue < start - epsilon || lineValue > end + epsilon) { return; } } return lineValue; } function garbageCollect(caches, length) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(caches, (cache) => { const gc = cache.gc; const gcLen = gc.length / 2; let i; if (gcLen > length) { for (i = 0; i < gcLen; ++i) { delete cache.data[gc[i]]; } gc.splice(0, gcLen); } }); } function getTickMarkLength(options) { return options.drawTicks ? options.tickLength : 0; } function getTitleHeight(options, fallback) { if (!options.display) { return 0; } const font = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.font, fallback); const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(options.padding); const lines = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(options.text) ? options.text.length : 1; return (lines * font.lineHeight) + padding.height; } function createScaleContext(parent, scale) { return Object.assign(Object.create(parent), { scale, type: 'scale' }); } function createTickContext(parent, index, tick) { return Object.assign(Object.create(parent), { tick, index, type: 'tick' }); } function titleAlign(align, position, reverse) { let ret = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Y)(align); if ((reverse && position !== 'right') || (!reverse && position === 'right')) { ret = reverseAlign(ret); } return ret; } function titleArgs(scale, offset, position, align) { const {top, left, bottom, right, chart} = scale; const {chartArea, scales} = chart; let rotation = 0; let maxWidth, titleX, titleY; const height = bottom - top; const width = right - left; if (scale.isHorizontal()) { titleX = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, left, right); if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { const positionAxisID = Object.keys(position)[0]; const value = position[positionAxisID]; titleY = scales[positionAxisID].getPixelForValue(value) + height - offset; } else if (position === 'center') { titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset; } else { titleY = offsetFromEdge(scale, position, offset); } maxWidth = right - left; } else { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { const positionAxisID = Object.keys(position)[0]; const value = position[positionAxisID]; titleX = scales[positionAxisID].getPixelForValue(value) - width + offset; } else if (position === 'center') { titleX = (chartArea.left + chartArea.right) / 2 - width + offset; } else { titleX = offsetFromEdge(scale, position, offset); } titleY = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, bottom, top); rotation = position === 'left' ? -_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H : _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H; } return {titleX, titleY, maxWidth, rotation}; } class Scale extends Element { constructor(cfg) { super(); this.id = cfg.id; this.type = cfg.type; this.options = undefined; this.ctx = cfg.ctx; this.chart = cfg.chart; this.top = undefined; this.bottom = undefined; this.left = undefined; this.right = undefined; this.width = undefined; this.height = undefined; this._margins = { left: 0, right: 0, top: 0, bottom: 0 }; this.maxWidth = undefined; this.maxHeight = undefined; this.paddingTop = undefined; this.paddingBottom = undefined; this.paddingLeft = undefined; this.paddingRight = undefined; this.axis = undefined; this.labelRotation = undefined; this.min = undefined; this.max = undefined; this._range = undefined; this.ticks = []; this._gridLineItems = null; this._labelItems = null; this._labelSizes = null; this._length = 0; this._maxLength = 0; this._longestTextCache = {}; this._startPixel = undefined; this._endPixel = undefined; this._reversePixels = false; this._userMax = undefined; this._userMin = undefined; this._suggestedMax = undefined; this._suggestedMin = undefined; this._ticksLength = 0; this._borderValue = 0; this._cache = {}; this._dataLimitsCached = false; this.$context = undefined; } init(options) { const me = this; me.options = options.setContext(me.getContext()); me.axis = options.axis; me._userMin = me.parse(options.min); me._userMax = me.parse(options.max); me._suggestedMin = me.parse(options.suggestedMin); me._suggestedMax = me.parse(options.suggestedMax); } parse(raw, index) { return raw; } getUserBounds() { let {_userMin, _userMax, _suggestedMin, _suggestedMax} = this; _userMin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(_userMin, Number.POSITIVE_INFINITY); _userMax = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(_userMax, Number.NEGATIVE_INFINITY); _suggestedMin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(_suggestedMin, Number.POSITIVE_INFINITY); _suggestedMax = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(_suggestedMax, Number.NEGATIVE_INFINITY); return { min: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(_userMin, _suggestedMin), max: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(_userMax, _suggestedMax), minDefined: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMin), maxDefined: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMax) }; } getMinMax(canStack) { const me = this; let {min, max, minDefined, maxDefined} = me.getUserBounds(); let range; if (minDefined && maxDefined) { return {min, max}; } const metas = me.getMatchingVisibleMetas(); for (let i = 0, ilen = metas.length; i < ilen; ++i) { range = metas[i].controller.getMinMax(me, canStack); if (!minDefined) { min = Math.min(min, range.min); } if (!maxDefined) { max = Math.max(max, range.max); } } return { min: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(min, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(max, min)), max: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(max, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(min, max)) }; } getPadding() { const me = this; return { left: me.paddingLeft || 0, top: me.paddingTop || 0, right: me.paddingRight || 0, bottom: me.paddingBottom || 0 }; } getTicks() { return this.ticks; } getLabels() { const data = this.chart.data; return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || []; } beforeLayout() { this._cache = {}; this._dataLimitsCached = false; } beforeUpdate() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.beforeUpdate, [this]); } update(maxWidth, maxHeight, margins) { const me = this; const tickOpts = me.options.ticks; const sampleSize = tickOpts.sampleSize; me.beforeUpdate(); me.maxWidth = maxWidth; me.maxHeight = maxHeight; me._margins = margins = Object.assign({ left: 0, right: 0, top: 0, bottom: 0 }, margins); me.ticks = null; me._labelSizes = null; me._gridLineItems = null; me._labelItems = null; me.beforeSetDimensions(); me.setDimensions(); me.afterSetDimensions(); me._maxLength = me.isHorizontal() ? me.width + margins.left + margins.right : me.height + margins.top + margins.bottom; if (!me._dataLimitsCached) { me.beforeDataLimits(); me.determineDataLimits(); me.afterDataLimits(); me._range = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.N)(me, me.options.grace); me._dataLimitsCached = true; } me.beforeBuildTicks(); me.ticks = me.buildTicks() || []; me.afterBuildTicks(); const samplingEnabled = sampleSize < me.ticks.length; me._convertTicksToLabels(samplingEnabled ? sample(me.ticks, sampleSize) : me.ticks); me.configure(); me.beforeCalculateLabelRotation(); me.calculateLabelRotation(); me.afterCalculateLabelRotation(); if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) { me.ticks = autoSkip(me, me.ticks); me._labelSizes = null; } if (samplingEnabled) { me._convertTicksToLabels(me.ticks); } me.beforeFit(); me.fit(); me.afterFit(); me.afterUpdate(); } configure() { const me = this; let reversePixels = me.options.reverse; let startPixel, endPixel; if (me.isHorizontal()) { startPixel = me.left; endPixel = me.right; } else { startPixel = me.top; endPixel = me.bottom; reversePixels = !reversePixels; } me._startPixel = startPixel; me._endPixel = endPixel; me._reversePixels = reversePixels; me._length = endPixel - startPixel; me._alignToPixels = me.options.alignToPixels; } afterUpdate() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.afterUpdate, [this]); } beforeSetDimensions() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.beforeSetDimensions, [this]); } setDimensions() { const me = this; if (me.isHorizontal()) { me.width = me.maxWidth; me.left = 0; me.right = me.width; } else { me.height = me.maxHeight; me.top = 0; me.bottom = me.height; } me.paddingLeft = 0; me.paddingTop = 0; me.paddingRight = 0; me.paddingBottom = 0; } afterSetDimensions() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.afterSetDimensions, [this]); } _callHooks(name) { const me = this; me.chart.notifyPlugins(name, me.getContext()); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(me.options[name], [me]); } beforeDataLimits() { this._callHooks('beforeDataLimits'); } determineDataLimits() {} afterDataLimits() { this._callHooks('afterDataLimits'); } beforeBuildTicks() { this._callHooks('beforeBuildTicks'); } buildTicks() { return []; } afterBuildTicks() { this._callHooks('afterBuildTicks'); } beforeTickToLabelConversion() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.beforeTickToLabelConversion, [this]); } generateTickLabels(ticks) { const me = this; const tickOpts = me.options.ticks; let i, ilen, tick; for (i = 0, ilen = ticks.length; i < ilen; i++) { tick = ticks[i]; tick.label = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(tickOpts.callback, [tick.value, i, ticks], me); } } afterTickToLabelConversion() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.afterTickToLabelConversion, [this]); } beforeCalculateLabelRotation() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.beforeCalculateLabelRotation, [this]); } calculateLabelRotation() { const me = this; const options = me.options; const tickOpts = options.ticks; const numTicks = me.ticks.length; const minRotation = tickOpts.minRotation || 0; const maxRotation = tickOpts.maxRotation; let labelRotation = minRotation; let tickWidth, maxHeight, maxLabelDiagonal; if (!me._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !me.isHorizontal()) { me.labelRotation = minRotation; return; } const labelSizes = me._getLabelSizes(); const maxLabelWidth = labelSizes.widest.width; const maxLabelHeight = labelSizes.highest.height; const maxWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(me.chart.width - maxLabelWidth, 0, me.maxWidth); tickWidth = options.offset ? me.maxWidth / numTicks : maxWidth / (numTicks - 1); if (maxLabelWidth + 6 > tickWidth) { tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1)); maxHeight = me.maxHeight - getTickMarkLength(options.grid) - tickOpts.padding - getTitleHeight(options.title, me.chart.options.font); maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight); labelRotation = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(Math.min( Math.asin((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)((labelSizes.highest.height + 6) / tickWidth, -1, 1)), Math.asin((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(maxLabelHeight / maxLabelDiagonal, -1, 1)) )); labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation)); } me.labelRotation = labelRotation; } afterCalculateLabelRotation() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.afterCalculateLabelRotation, [this]); } beforeFit() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.beforeFit, [this]); } fit() { const me = this; const minSize = { width: 0, height: 0 }; const {chart, options: {ticks: tickOpts, title: titleOpts, grid: gridOpts}} = me; const display = me._isVisible(); const isHorizontal = me.isHorizontal(); if (display) { const titleHeight = getTitleHeight(titleOpts, chart.options.font); if (isHorizontal) { minSize.width = me.maxWidth; minSize.height = getTickMarkLength(gridOpts) + titleHeight; } else { minSize.height = me.maxHeight; minSize.width = getTickMarkLength(gridOpts) + titleHeight; } if (tickOpts.display && me.ticks.length) { const {first, last, widest, highest} = me._getLabelSizes(); const tickPadding = tickOpts.padding * 2; const angleRadians = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(me.labelRotation); const cos = Math.cos(angleRadians); const sin = Math.sin(angleRadians); if (isHorizontal) { const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height; minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding); } else { const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height; minSize.width = Math.min(me.maxWidth, minSize.width + labelWidth + tickPadding); } me._calculatePadding(first, last, sin, cos); } } me._handleMargins(); if (isHorizontal) { me.width = me._length = chart.width - me._margins.left - me._margins.right; me.height = minSize.height; } else { me.width = minSize.width; me.height = me._length = chart.height - me._margins.top - me._margins.bottom; } } _calculatePadding(first, last, sin, cos) { const me = this; const {ticks: {align, padding}, position} = me.options; const isRotated = me.labelRotation !== 0; const labelsBelowTicks = position !== 'top' && me.axis === 'x'; if (me.isHorizontal()) { const offsetLeft = me.getPixelForTick(0) - me.left; const offsetRight = me.right - me.getPixelForTick(me.ticks.length - 1); let paddingLeft = 0; let paddingRight = 0; if (isRotated) { if (labelsBelowTicks) { paddingLeft = cos * first.width; paddingRight = sin * last.height; } else { paddingLeft = sin * first.height; paddingRight = cos * last.width; } } else if (align === 'start') { paddingRight = last.width; } else if (align === 'end') { paddingLeft = first.width; } else { paddingLeft = first.width / 2; paddingRight = last.width / 2; } me.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * me.width / (me.width - offsetLeft), 0); me.paddingRight = Math.max((paddingRight - offsetRight + padding) * me.width / (me.width - offsetRight), 0); } else { let paddingTop = last.height / 2; let paddingBottom = first.height / 2; if (align === 'start') { paddingTop = 0; paddingBottom = first.height; } else if (align === 'end') { paddingTop = last.height; paddingBottom = 0; } me.paddingTop = paddingTop + padding; me.paddingBottom = paddingBottom + padding; } } _handleMargins() { const me = this; if (me._margins) { me._margins.left = Math.max(me.paddingLeft, me._margins.left); me._margins.top = Math.max(me.paddingTop, me._margins.top); me._margins.right = Math.max(me.paddingRight, me._margins.right); me._margins.bottom = Math.max(me.paddingBottom, me._margins.bottom); } } afterFit() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(this.options.afterFit, [this]); } isHorizontal() { const {axis, position} = this.options; return position === 'top' || position === 'bottom' || axis === 'x'; } isFullSize() { return this.options.fullSize; } _convertTicksToLabels(ticks) { const me = this; me.beforeTickToLabelConversion(); me.generateTickLabels(ticks); let i, ilen; for (i = 0, ilen = ticks.length; i < ilen; i++) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(ticks[i].label)) { ticks.splice(i, 1); ilen--; i--; } } me.afterTickToLabelConversion(); } _getLabelSizes() { const me = this; let labelSizes = me._labelSizes; if (!labelSizes) { const sampleSize = me.options.ticks.sampleSize; let ticks = me.ticks; if (sampleSize < ticks.length) { ticks = sample(ticks, sampleSize); } me._labelSizes = labelSizes = me._computeLabelSizes(ticks, ticks.length); } return labelSizes; } _computeLabelSizes(ticks, length) { const {ctx, _longestTextCache: caches} = this; const widths = []; const heights = []; let widestLabelSize = 0; let highestLabelSize = 0; let i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel; for (i = 0; i < length; ++i) { label = ticks[i].label; tickFont = this._resolveTickFontOptions(i); ctx.font = fontString = tickFont.string; cache = caches[fontString] = caches[fontString] || {data: {}, gc: []}; lineHeight = tickFont.lineHeight; width = height = 0; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(label) && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) { width = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(ctx, cache.data, cache.gc, width, label); height = lineHeight; } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) { for (j = 0, jlen = label.length; j < jlen; ++j) { nestedLabel = label[j]; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(nestedLabel) && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(nestedLabel)) { width = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(ctx, cache.data, cache.gc, width, nestedLabel); height += lineHeight; } } } widths.push(width); heights.push(height); widestLabelSize = Math.max(width, widestLabelSize); highestLabelSize = Math.max(height, highestLabelSize); } garbageCollect(caches, length); const widest = widths.indexOf(widestLabelSize); const highest = heights.indexOf(highestLabelSize); const valueAt = (idx) => ({width: widths[idx] || 0, height: heights[idx] || 0}); return { first: valueAt(0), last: valueAt(length - 1), widest: valueAt(widest), highest: valueAt(highest), widths, heights, }; } getLabelForValue(value) { return value; } getPixelForValue(value, index) { return NaN; } getValueForPixel(pixel) {} getPixelForTick(index) { const ticks = this.ticks; if (index < 0 || index > ticks.length - 1) { return null; } return this.getPixelForValue(ticks[index].value); } getPixelForDecimal(decimal) { const me = this; if (me._reversePixels) { decimal = 1 - decimal; } const pixel = me._startPixel + decimal * me._length; return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.R)(me._alignToPixels ? (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(me.chart, pixel, 0) : pixel); } getDecimalForPixel(pixel) { const decimal = (pixel - this._startPixel) / this._length; return this._reversePixels ? 1 - decimal : decimal; } getBasePixel() { return this.getPixelForValue(this.getBaseValue()); } getBaseValue() { const {min, max} = this; return min < 0 && max < 0 ? max : min > 0 && max > 0 ? min : 0; } getContext(index) { const me = this; const ticks = me.ticks || []; if (index >= 0 && index < ticks.length) { const tick = ticks[index]; return tick.$context || (tick.$context = createTickContext(me.getContext(), index, tick)); } return me.$context || (me.$context = createScaleContext(me.chart.getContext(), me)); } _tickSize() { const me = this; const optionTicks = me.options.ticks; const rot = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(me.labelRotation); const cos = Math.abs(Math.cos(rot)); const sin = Math.abs(Math.sin(rot)); const labelSizes = me._getLabelSizes(); const padding = optionTicks.autoSkipPadding || 0; const w = labelSizes ? labelSizes.widest.width + padding : 0; const h = labelSizes ? labelSizes.highest.height + padding : 0; return me.isHorizontal() ? h * cos > w * sin ? w / cos : h / sin : h * sin < w * cos ? h / cos : w / sin; } _isVisible() { const display = this.options.display; if (display !== 'auto') { return !!display; } return this.getMatchingVisibleMetas().length > 0; } _computeGridLineItems(chartArea) { const me = this; const axis = me.axis; const chart = me.chart; const options = me.options; const {grid, position} = options; const offset = grid.offset; const isHorizontal = me.isHorizontal(); const ticks = me.ticks; const ticksLength = ticks.length + (offset ? 1 : 0); const tl = getTickMarkLength(grid); const items = []; const borderOpts = grid.setContext(me.getContext()); const axisWidth = borderOpts.drawBorder ? borderOpts.borderWidth : 0; const axisHalfWidth = axisWidth / 2; const alignBorderValue = function(pixel) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(chart, pixel, axisWidth); }; let borderValue, i, lineValue, alignedLineValue; let tx1, ty1, tx2, ty2, x1, y1, x2, y2; if (position === 'top') { borderValue = alignBorderValue(me.bottom); ty1 = me.bottom - tl; ty2 = borderValue - axisHalfWidth; y1 = alignBorderValue(chartArea.top) + axisHalfWidth; y2 = chartArea.bottom; } else if (position === 'bottom') { borderValue = alignBorderValue(me.top); y1 = chartArea.top; y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth; ty1 = borderValue + axisHalfWidth; ty2 = me.top + tl; } else if (position === 'left') { borderValue = alignBorderValue(me.right); tx1 = me.right - tl; tx2 = borderValue - axisHalfWidth; x1 = alignBorderValue(chartArea.left) + axisHalfWidth; x2 = chartArea.right; } else if (position === 'right') { borderValue = alignBorderValue(me.left); x1 = chartArea.left; x2 = alignBorderValue(chartArea.right) - axisHalfWidth; tx1 = borderValue + axisHalfWidth; tx2 = me.left + tl; } else if (axis === 'x') { if (position === 'center') { borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5); } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { const positionAxisID = Object.keys(position)[0]; const value = position[positionAxisID]; borderValue = alignBorderValue(me.chart.scales[positionAxisID].getPixelForValue(value)); } y1 = chartArea.top; y2 = chartArea.bottom; ty1 = borderValue + axisHalfWidth; ty2 = ty1 + tl; } else if (axis === 'y') { if (position === 'center') { borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2); } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { const positionAxisID = Object.keys(position)[0]; const value = position[positionAxisID]; borderValue = alignBorderValue(me.chart.scales[positionAxisID].getPixelForValue(value)); } tx1 = borderValue - axisHalfWidth; tx2 = tx1 - tl; x1 = chartArea.left; x2 = chartArea.right; } const limit = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.ticks.maxTicksLimit, ticksLength); const step = Math.max(1, Math.ceil(ticksLength / limit)); for (i = 0; i < ticksLength; i += step) { const optsAtIndex = grid.setContext(me.getContext(i)); const lineWidth = optsAtIndex.lineWidth; const lineColor = optsAtIndex.color; const borderDash = grid.borderDash || []; const borderDashOffset = optsAtIndex.borderDashOffset; const tickWidth = optsAtIndex.tickWidth; const tickColor = optsAtIndex.tickColor; const tickBorderDash = optsAtIndex.tickBorderDash || []; const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset; lineValue = getPixelForGridLine(me, i, offset); if (lineValue === undefined) { continue; } alignedLineValue = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(chart, lineValue, lineWidth); if (isHorizontal) { tx1 = tx2 = x1 = x2 = alignedLineValue; } else { ty1 = ty2 = y1 = y2 = alignedLineValue; } items.push({ tx1, ty1, tx2, ty2, x1, y1, x2, y2, width: lineWidth, color: lineColor, borderDash, borderDashOffset, tickWidth, tickColor, tickBorderDash, tickBorderDashOffset, }); } me._ticksLength = ticksLength; me._borderValue = borderValue; return items; } _computeLabelItems(chartArea) { const me = this; const axis = me.axis; const options = me.options; const {position, ticks: optionTicks} = options; const isHorizontal = me.isHorizontal(); const ticks = me.ticks; const {align, crossAlign, padding, mirror} = optionTicks; const tl = getTickMarkLength(options.grid); const tickAndPadding = tl + padding; const hTickAndPadding = mirror ? -padding : tickAndPadding; const rotation = -(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(me.labelRotation); const items = []; let i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset; let textBaseline = 'middle'; if (position === 'top') { y = me.bottom - hTickAndPadding; textAlign = me._getXAxisLabelAlignment(); } else if (position === 'bottom') { y = me.top + hTickAndPadding; textAlign = me._getXAxisLabelAlignment(); } else if (position === 'left') { const ret = me._getYAxisLabelAlignment(tl); textAlign = ret.textAlign; x = ret.x; } else if (position === 'right') { const ret = me._getYAxisLabelAlignment(tl); textAlign = ret.textAlign; x = ret.x; } else if (axis === 'x') { if (position === 'center') { y = ((chartArea.top + chartArea.bottom) / 2) + tickAndPadding; } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { const positionAxisID = Object.keys(position)[0]; const value = position[positionAxisID]; y = me.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding; } textAlign = me._getXAxisLabelAlignment(); } else if (axis === 'y') { if (position === 'center') { x = ((chartArea.left + chartArea.right) / 2) - tickAndPadding; } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { const positionAxisID = Object.keys(position)[0]; const value = position[positionAxisID]; x = me.chart.scales[positionAxisID].getPixelForValue(value); } textAlign = me._getYAxisLabelAlignment(tl).textAlign; } if (axis === 'y') { if (align === 'start') { textBaseline = 'top'; } else if (align === 'end') { textBaseline = 'bottom'; } } const labelSizes = me._getLabelSizes(); for (i = 0, ilen = ticks.length; i < ilen; ++i) { tick = ticks[i]; label = tick.label; const optsAtIndex = optionTicks.setContext(me.getContext(i)); pixel = me.getPixelForTick(i) + optionTicks.labelOffset; font = me._resolveTickFontOptions(i); lineHeight = font.lineHeight; lineCount = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label.length : 1; const halfCount = lineCount / 2; const color = optsAtIndex.color; const strokeColor = optsAtIndex.textStrokeColor; const strokeWidth = optsAtIndex.textStrokeWidth; if (isHorizontal) { x = pixel; if (position === 'top') { if (crossAlign === 'near' || rotation !== 0) { textOffset = -lineCount * lineHeight + lineHeight / 2; } else if (crossAlign === 'center') { textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight; } else { textOffset = -labelSizes.highest.height + lineHeight / 2; } } else { if (crossAlign === 'near' || rotation !== 0) { textOffset = lineHeight / 2; } else if (crossAlign === 'center') { textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight; } else { textOffset = labelSizes.highest.height - lineCount * lineHeight; } } if (mirror) { textOffset *= -1; } } else { y = pixel; textOffset = (1 - lineCount) * lineHeight / 2; } let backdrop; if (optsAtIndex.showLabelBackdrop) { const labelPadding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(optsAtIndex.backdropPadding); const height = labelSizes.heights[i]; const width = labelSizes.widths[i]; let top = y + textOffset - labelPadding.top; let left = x - labelPadding.left; switch (textBaseline) { case 'middle': top -= height / 2; break; case 'bottom': top -= height; break; } switch (textAlign) { case 'center': left -= width / 2; break; case 'right': left -= width; break; } backdrop = { left, top, width: width + labelPadding.width, height: height + labelPadding.height, color: optsAtIndex.backdropColor, }; } items.push({ rotation, label, font, color, strokeColor, strokeWidth, textOffset, textAlign, textBaseline, translation: [x, y], backdrop, }); } return items; } _getXAxisLabelAlignment() { const me = this; const {position, ticks} = me.options; const rotation = -(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(me.labelRotation); if (rotation) { return position === 'top' ? 'left' : 'right'; } let align = 'center'; if (ticks.align === 'start') { align = 'left'; } else if (ticks.align === 'end') { align = 'right'; } return align; } _getYAxisLabelAlignment(tl) { const me = this; const {position, ticks: {crossAlign, mirror, padding}} = me.options; const labelSizes = me._getLabelSizes(); const tickAndPadding = tl + padding; const widest = labelSizes.widest.width; let textAlign; let x; if (position === 'left') { if (mirror) { x = me.right + padding; if (crossAlign === 'near') { textAlign = 'left'; } else if (crossAlign === 'center') { textAlign = 'center'; x += (widest / 2); } else { textAlign = 'right'; x += widest; } } else { x = me.right - tickAndPadding; if (crossAlign === 'near') { textAlign = 'right'; } else if (crossAlign === 'center') { textAlign = 'center'; x -= (widest / 2); } else { textAlign = 'left'; x = me.left; } } } else if (position === 'right') { if (mirror) { x = me.left + padding; if (crossAlign === 'near') { textAlign = 'right'; } else if (crossAlign === 'center') { textAlign = 'center'; x -= (widest / 2); } else { textAlign = 'left'; x -= widest; } } else { x = me.left + tickAndPadding; if (crossAlign === 'near') { textAlign = 'left'; } else if (crossAlign === 'center') { textAlign = 'center'; x += widest / 2; } else { textAlign = 'right'; x = me.right; } } } else { textAlign = 'right'; } return {textAlign, x}; } _computeLabelArea() { const me = this; if (me.options.ticks.mirror) { return; } const chart = me.chart; const position = me.options.position; if (position === 'left' || position === 'right') { return {top: 0, left: me.left, bottom: chart.height, right: me.right}; } if (position === 'top' || position === 'bottom') { return {top: me.top, left: 0, bottom: me.bottom, right: chart.width}; } } drawBackground() { const {ctx, options: {backgroundColor}, left, top, width, height} = this; if (backgroundColor) { ctx.save(); ctx.fillStyle = backgroundColor; ctx.fillRect(left, top, width, height); ctx.restore(); } } getLineWidthForValue(value) { const me = this; const grid = me.options.grid; if (!me._isVisible() || !grid.display) { return 0; } const ticks = me.ticks; const index = ticks.findIndex(t => t.value === value); if (index >= 0) { const opts = grid.setContext(me.getContext(index)); return opts.lineWidth; } return 0; } drawGrid(chartArea) { const me = this; const grid = me.options.grid; const ctx = me.ctx; const items = me._gridLineItems || (me._gridLineItems = me._computeGridLineItems(chartArea)); let i, ilen; const drawLine = (p1, p2, style) => { if (!style.width || !style.color) { return; } ctx.save(); ctx.lineWidth = style.width; ctx.strokeStyle = style.color; ctx.setLineDash(style.borderDash || []); ctx.lineDashOffset = style.borderDashOffset; ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); ctx.restore(); }; if (grid.display) { for (i = 0, ilen = items.length; i < ilen; ++i) { const item = items[i]; if (grid.drawOnChartArea) { drawLine( {x: item.x1, y: item.y1}, {x: item.x2, y: item.y2}, item ); } if (grid.drawTicks) { drawLine( {x: item.tx1, y: item.ty1}, {x: item.tx2, y: item.ty2}, { color: item.tickColor, width: item.tickWidth, borderDash: item.tickBorderDash, borderDashOffset: item.tickBorderDashOffset } ); } } } } drawBorder() { const me = this; const {chart, ctx, options: {grid}} = me; const borderOpts = grid.setContext(me.getContext()); const axisWidth = grid.drawBorder ? borderOpts.borderWidth : 0; if (!axisWidth) { return; } const lastLineWidth = grid.setContext(me.getContext(0)).lineWidth; const borderValue = me._borderValue; let x1, x2, y1, y2; if (me.isHorizontal()) { x1 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(chart, me.left, axisWidth) - axisWidth / 2; x2 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(chart, me.right, lastLineWidth) + lastLineWidth / 2; y1 = y2 = borderValue; } else { y1 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(chart, me.top, axisWidth) - axisWidth / 2; y2 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(chart, me.bottom, lastLineWidth) + lastLineWidth / 2; x1 = x2 = borderValue; } ctx.save(); ctx.lineWidth = borderOpts.borderWidth; ctx.strokeStyle = borderOpts.borderColor; ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); ctx.restore(); } drawLabels(chartArea) { const me = this; const optionTicks = me.options.ticks; if (!optionTicks.display) { return; } const ctx = me.ctx; const area = me._computeLabelArea(); if (area) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.U)(ctx, area); } const items = me._labelItems || (me._labelItems = me._computeLabelItems(chartArea)); let i, ilen; for (i = 0, ilen = items.length; i < ilen; ++i) { const item = items[i]; const tickFont = item.font; const label = item.label; if (item.backdrop) { ctx.fillStyle = item.backdrop.color; ctx.fillRect(item.backdrop.left, item.backdrop.top, item.backdrop.width, item.backdrop.height); } let y = item.textOffset; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, label, 0, y, tickFont, item); } if (area) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.W)(ctx); } } drawTitle() { const {ctx, options: {position, title, reverse}} = this; if (!title.display) { return; } const font = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(title.font); const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(title.padding); const align = title.align; let offset = font.lineHeight / 2; if (position === 'bottom' || position === 'center' || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { offset += padding.bottom; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(title.text)) { offset += font.lineHeight * (title.text.length - 1); } } else { offset += padding.top; } const {titleX, titleY, maxWidth, rotation} = titleArgs(this, offset, position, align); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, title.text, 0, 0, font, { color: title.color, maxWidth, rotation, textAlign: titleAlign(align, position, reverse), textBaseline: 'middle', translation: [titleX, titleY], }); } draw(chartArea) { const me = this; if (!me._isVisible()) { return; } me.drawBackground(); me.drawGrid(chartArea); me.drawBorder(); me.drawTitle(); me.drawLabels(chartArea); } _layers() { const me = this; const opts = me.options; const tz = opts.ticks && opts.ticks.z || 0; const gz = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(opts.grid && opts.grid.z, -1); if (!me._isVisible() || me.draw !== Scale.prototype.draw) { return [{ z: tz, draw(chartArea) { me.draw(chartArea); } }]; } return [{ z: gz, draw(chartArea) { me.drawBackground(); me.drawGrid(chartArea); me.drawTitle(); } }, { z: gz + 1, draw() { me.drawBorder(); } }, { z: tz, draw(chartArea) { me.drawLabels(chartArea); } }]; } getMatchingVisibleMetas(type) { const me = this; const metas = me.chart.getSortedVisibleDatasetMetas(); const axisID = me.axis + 'AxisID'; const result = []; let i, ilen; for (i = 0, ilen = metas.length; i < ilen; ++i) { const meta = metas[i]; if (meta[axisID] === me.id && (!type || meta.type === type)) { result.push(meta); } } return result; } _resolveTickFontOptions(index) { const opts = this.options.ticks.setContext(this.getContext(index)); return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(opts.font); } _maxDigits() { const me = this; const fontSize = me._resolveTickFontOptions(0).lineHeight; return (me.isHorizontal() ? me.width : me.height) / fontSize; } } class TypedRegistry { constructor(type, scope, override) { this.type = type; this.scope = scope; this.override = override; this.items = Object.create(null); } isForType(type) { return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype); } register(item) { const me = this; const proto = Object.getPrototypeOf(item); let parentScope; if (isIChartComponent(proto)) { parentScope = me.register(proto); } const items = me.items; const id = item.id; const scope = me.scope + '.' + id; if (!id) { throw new Error('class does not have id: ' + item); } if (id in items) { return scope; } items[id] = item; registerDefaults(item, scope, parentScope); if (me.override) { _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.override(item.id, item.overrides); } return scope; } get(id) { return this.items[id]; } unregister(item) { const items = this.items; const id = item.id; const scope = this.scope; if (id in items) { delete items[id]; } if (scope && id in _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d[scope]) { delete _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d[scope][id]; if (this.override) { delete _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$[id]; } } } } function registerDefaults(item, scope, parentScope) { const itemDefaults = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(Object.create(null), [ parentScope ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.get(parentScope) : {}, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.get(scope), item.defaults ]); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.set(scope, itemDefaults); if (item.defaultRoutes) { routeDefaults(scope, item.defaultRoutes); } if (item.descriptors) { _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.describe(scope, item.descriptors); } } function routeDefaults(scope, routes) { Object.keys(routes).forEach(property => { const propertyParts = property.split('.'); const sourceName = propertyParts.pop(); const sourceScope = [scope].concat(propertyParts).join('.'); const parts = routes[property].split('.'); const targetName = parts.pop(); const targetScope = parts.join('.'); _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.route(sourceScope, sourceName, targetScope, targetName); }); } function isIChartComponent(proto) { return 'id' in proto && 'defaults' in proto; } class Registry { constructor() { this.controllers = new TypedRegistry(DatasetController, 'datasets', true); this.elements = new TypedRegistry(Element, 'elements'); this.plugins = new TypedRegistry(Object, 'plugins'); this.scales = new TypedRegistry(Scale, 'scales'); this._typedRegistries = [this.controllers, this.scales, this.elements]; } add(...args) { this._each('register', args); } remove(...args) { this._each('unregister', args); } addControllers(...args) { this._each('register', args, this.controllers); } addElements(...args) { this._each('register', args, this.elements); } addPlugins(...args) { this._each('register', args, this.plugins); } addScales(...args) { this._each('register', args, this.scales); } getController(id) { return this._get(id, this.controllers, 'controller'); } getElement(id) { return this._get(id, this.elements, 'element'); } getPlugin(id) { return this._get(id, this.plugins, 'plugin'); } getScale(id) { return this._get(id, this.scales, 'scale'); } removeControllers(...args) { this._each('unregister', args, this.controllers); } removeElements(...args) { this._each('unregister', args, this.elements); } removePlugins(...args) { this._each('unregister', args, this.plugins); } removeScales(...args) { this._each('unregister', args, this.scales); } _each(method, args, typedRegistry) { const me = this; [...args].forEach(arg => { const reg = typedRegistry || me._getRegistryForType(arg); if (typedRegistry || reg.isForType(arg) || (reg === me.plugins && arg.id)) { me._exec(method, reg, arg); } else { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(arg, item => { const itemReg = typedRegistry || me._getRegistryForType(item); me._exec(method, itemReg, item); }); } }); } _exec(method, registry, component) { const camelMethod = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a1)(method); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(component['before' + camelMethod], [], component); registry[method](component); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(component['after' + camelMethod], [], component); } _getRegistryForType(type) { for (let i = 0; i < this._typedRegistries.length; i++) { const reg = this._typedRegistries[i]; if (reg.isForType(type)) { return reg; } } return this.plugins; } _get(id, typedRegistry, type) { const item = typedRegistry.get(id); if (item === undefined) { throw new Error('"' + id + '" is not a registered ' + type + '.'); } return item; } } var registry = new Registry(); class PluginService { constructor() { this._init = []; } notify(chart, hook, args, filter) { const me = this; if (hook === 'beforeInit') { me._init = me._createDescriptors(chart, true); me._notify(me._init, chart, 'install'); } const descriptors = filter ? me._descriptors(chart).filter(filter) : me._descriptors(chart); const result = me._notify(descriptors, chart, hook, args); if (hook === 'destroy') { me._notify(descriptors, chart, 'stop'); me._notify(me._init, chart, 'uninstall'); } return result; } _notify(descriptors, chart, hook, args) { args = args || {}; for (const descriptor of descriptors) { const plugin = descriptor.plugin; const method = plugin[hook]; const params = [chart, args, descriptor.options]; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(method, params, plugin) === false && args.cancelable) { return false; } } return true; } invalidate() { if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(this._cache)) { this._oldCache = this._cache; this._cache = undefined; } } _descriptors(chart) { if (this._cache) { return this._cache; } const descriptors = this._cache = this._createDescriptors(chart); this._notifyStateChanges(chart); return descriptors; } _createDescriptors(chart, all) { const config = chart && chart.config; const options = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(config.options && config.options.plugins, {}); const plugins = allPlugins(config); return options === false && !all ? [] : createDescriptors(chart, plugins, options, all); } _notifyStateChanges(chart) { const previousDescriptors = this._oldCache || []; const descriptors = this._cache; const diff = (a, b) => a.filter(x => !b.some(y => x.plugin.id === y.plugin.id)); this._notify(diff(previousDescriptors, descriptors), chart, 'stop'); this._notify(diff(descriptors, previousDescriptors), chart, 'start'); } } function allPlugins(config) { const plugins = []; const keys = Object.keys(registry.plugins.items); for (let i = 0; i < keys.length; i++) { plugins.push(registry.getPlugin(keys[i])); } const local = config.plugins || []; for (let i = 0; i < local.length; i++) { const plugin = local[i]; if (plugins.indexOf(plugin) === -1) { plugins.push(plugin); } } return plugins; } function getOpts(options, all) { if (!all && options === false) { return null; } if (options === true) { return {}; } return options; } function createDescriptors(chart, plugins, options, all) { const result = []; const context = chart.getContext(); for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; const id = plugin.id; const opts = getOpts(options[id], all); if (opts === null) { continue; } result.push({ plugin, options: pluginOpts(chart.config, plugin, opts, context) }); } return result; } function pluginOpts(config, plugin, opts, context) { const keys = config.pluginScopeKeys(plugin); const scopes = config.getOptionScopes(opts, keys); return config.createResolver(scopes, context, [''], {scriptable: false, indexable: false, allKeys: true}); } function getIndexAxis(type, options) { const datasetDefaults = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {}; const datasetOptions = (options.datasets || {})[type] || {}; return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x'; } function getAxisFromDefaultScaleID(id, indexAxis) { let axis = id; if (id === '_index_') { axis = indexAxis; } else if (id === '_value_') { axis = indexAxis === 'x' ? 'y' : 'x'; } return axis; } function getDefaultScaleIDFromAxis(axis, indexAxis) { return axis === indexAxis ? '_index_' : '_value_'; } function axisFromPosition(position) { if (position === 'top' || position === 'bottom') { return 'x'; } if (position === 'left' || position === 'right') { return 'y'; } } function determineAxis(id, scaleOptions) { if (id === 'x' || id === 'y') { return id; } return scaleOptions.axis || axisFromPosition(scaleOptions.position) || id.charAt(0).toLowerCase(); } function mergeScaleConfig(config, options) { const chartDefaults = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$[config.type] || {scales: {}}; const configScales = options.scales || {}; const chartIndexAxis = getIndexAxis(config.type, options); const firstIDs = Object.create(null); const scales = Object.create(null); Object.keys(configScales).forEach(id => { const scaleConf = configScales[id]; const axis = determineAxis(id, scaleConf); const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis); const defaultScaleOptions = chartDefaults.scales || {}; firstIDs[axis] = firstIDs[axis] || id; scales[id] = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(Object.create(null), [{axis}, scaleConf, defaultScaleOptions[axis], defaultScaleOptions[defaultId]]); }); config.data.datasets.forEach(dataset => { const type = dataset.type || config.type; const indexAxis = dataset.indexAxis || getIndexAxis(type, options); const datasetDefaults = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$[type] || {}; const defaultScaleOptions = datasetDefaults.scales || {}; Object.keys(defaultScaleOptions).forEach(defaultID => { const axis = getAxisFromDefaultScaleID(defaultID, indexAxis); const id = dataset[axis + 'AxisID'] || firstIDs[axis] || axis; scales[id] = scales[id] || Object.create(null); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(scales[id], [{axis}, configScales[id], defaultScaleOptions[defaultID]]); }); }); Object.keys(scales).forEach(key => { const scale = scales[key]; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(scale, [_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.scales[scale.type], _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.scale]); }); return scales; } function initOptions(config) { const options = config.options || (config.options = {}); options.plugins = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.plugins, {}); options.scales = mergeScaleConfig(config, options); } function initData(data) { data = data || {}; data.datasets = data.datasets || []; data.labels = data.labels || []; return data; } function initConfig(config) { config = config || {}; config.data = initData(config.data); initOptions(config); return config; } const keyCache = new Map(); const keysCached = new Set(); function cachedKeys(cacheKey, generate) { let keys = keyCache.get(cacheKey); if (!keys) { keys = generate(); keyCache.set(cacheKey, keys); keysCached.add(keys); } return keys; } const addIfFound = (set, obj, key) => { const opts = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, key); if (opts !== undefined) { set.add(opts); } }; class Config { constructor(config) { this._config = initConfig(config); this._scopeCache = new Map(); this._resolverCache = new Map(); } get platform() { return this._config.platform; } get type() { return this._config.type; } set type(type) { this._config.type = type; } get data() { return this._config.data; } set data(data) { this._config.data = initData(data); } get options() { return this._config.options; } set options(options) { this._config.options = options; } get plugins() { return this._config.plugins; } update() { const config = this._config; this.clearCache(); initOptions(config); } clearCache() { this._scopeCache.clear(); this._resolverCache.clear(); } datasetScopeKeys(datasetType) { return cachedKeys(datasetType, () => [[ `datasets.${datasetType}`, '' ]]); } datasetAnimationScopeKeys(datasetType, transition) { return cachedKeys(`${datasetType}.transition.${transition}`, () => [ [ `datasets.${datasetType}.transitions.${transition}`, `transitions.${transition}`, ], [ `datasets.${datasetType}`, '' ] ]); } datasetElementScopeKeys(datasetType, elementType) { return cachedKeys(`${datasetType}-${elementType}`, () => [[ `datasets.${datasetType}.elements.${elementType}`, `datasets.${datasetType}`, `elements.${elementType}`, '' ]]); } pluginScopeKeys(plugin) { const id = plugin.id; const type = this.type; return cachedKeys(`${type}-plugin-${id}`, () => [[ `plugins.${id}`, ...plugin.additionalOptionScopes || [], ]]); } _cachedScopes(mainScope, resetCache) { const _scopeCache = this._scopeCache; let cache = _scopeCache.get(mainScope); if (!cache || resetCache) { cache = new Map(); _scopeCache.set(mainScope, cache); } return cache; } getOptionScopes(mainScope, keyLists, resetCache) { const {options, type} = this; const cache = this._cachedScopes(mainScope, resetCache); const cached = cache.get(keyLists); if (cached) { return cached; } const scopes = new Set(); keyLists.forEach(keys => { if (mainScope) { scopes.add(mainScope); keys.forEach(key => addIfFound(scopes, mainScope, key)); } keys.forEach(key => addIfFound(scopes, options, key)); keys.forEach(key => addIfFound(scopes, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$[type] || {}, key)); keys.forEach(key => addIfFound(scopes, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d, key)); keys.forEach(key => addIfFound(scopes, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2, key)); }); const array = Array.from(scopes); if (array.length === 0) { array.push(Object.create(null)); } if (keysCached.has(keyLists)) { cache.set(keyLists, array); } return array; } chartOptionScopes() { const {options, type} = this; return [ options, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$[type] || {}, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {}, {type}, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2 ]; } resolveNamedOptions(scopes, names, context, prefixes = ['']) { const result = {$shared: true}; const {resolver, subPrefixes} = getResolver(this._resolverCache, scopes, prefixes); let options = resolver; if (needContext(resolver, names)) { result.$shared = false; context = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3)(context) ? context() : context; const subResolver = this.createResolver(scopes, context, subPrefixes); options = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a4)(resolver, context, subResolver); } for (const prop of names) { result[prop] = options[prop]; } return result; } createResolver(scopes, context, prefixes = [''], descriptorDefaults) { const {resolver} = getResolver(this._resolverCache, scopes, prefixes); return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(context) ? (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a4)(resolver, context, undefined, descriptorDefaults) : resolver; } } function getResolver(resolverCache, scopes, prefixes) { let cache = resolverCache.get(scopes); if (!cache) { cache = new Map(); resolverCache.set(scopes, cache); } const cacheKey = prefixes.join(); let cached = cache.get(cacheKey); if (!cached) { const resolver = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a5)(scopes, prefixes); cached = { resolver, subPrefixes: prefixes.filter(p => !p.toLowerCase().includes('hover')) }; cache.set(cacheKey, cached); } return cached; } function needContext(proxy, names) { const {isScriptable, isIndexable} = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a6)(proxy); for (const prop of names) { if ((isScriptable(prop) && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3)(proxy[prop])) || (isIndexable(prop) && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(proxy[prop]))) { return true; } } return false; } var version = "3.5.1"; const KNOWN_POSITIONS = ['top', 'bottom', 'left', 'right', 'chartArea']; function positionIsHorizontal(position, axis) { return position === 'top' || position === 'bottom' || (KNOWN_POSITIONS.indexOf(position) === -1 && axis === 'x'); } function compare2Level(l1, l2) { return function(a, b) { return a[l1] === b[l1] ? a[l2] - b[l2] : a[l1] - b[l1]; }; } function onAnimationsComplete(context) { const chart = context.chart; const animationOptions = chart.options.animation; chart.notifyPlugins('afterRender'); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(animationOptions && animationOptions.onComplete, [context], chart); } function onAnimationProgress(context) { const chart = context.chart; const animationOptions = chart.options.animation; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(animationOptions && animationOptions.onProgress, [context], chart); } function getCanvas(item) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.I)() && typeof item === 'string') { item = document.getElementById(item); } else if (item && item.length) { item = item[0]; } if (item && item.canvas) { item = item.canvas; } return item; } const instances = {}; const getChart = (key) => { const canvas = getCanvas(key); return Object.values(instances).filter((c) => c.canvas === canvas).pop(); }; class Chart { constructor(item, userConfig) { const me = this; const config = this.config = new Config(userConfig); const initialCanvas = getCanvas(item); const existingChart = getChart(initialCanvas); if (existingChart) { throw new Error( 'Canvas is already in use. Chart with ID \'' + existingChart.id + '\'' + ' must be destroyed before the canvas can be reused.' ); } const options = config.createResolver(config.chartOptionScopes(), me.getContext()); this.platform = new (config.platform || _detectPlatform(initialCanvas))(); const context = me.platform.acquireContext(initialCanvas, options.aspectRatio); const canvas = context && context.canvas; const height = canvas && canvas.height; const width = canvas && canvas.width; this.id = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a8)(); this.ctx = context; this.canvas = canvas; this.width = width; this.height = height; this._options = options; this._aspectRatio = this.aspectRatio; this._layers = []; this._metasets = []; this._stacks = undefined; this.boxes = []; this.currentDevicePixelRatio = undefined; this.chartArea = undefined; this._active = []; this._lastEvent = undefined; this._listeners = {}; this._responsiveListeners = undefined; this._sortedMetasets = []; this.scales = {}; this._plugins = new PluginService(); this.$proxies = {}; this._hiddenIndices = {}; this.attached = false; this._animationsDisabled = undefined; this.$context = undefined; this._doResize = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a9)(() => this.update('resize'), options.resizeDelay || 0); instances[me.id] = me; if (!context || !canvas) { console.error("Failed to create chart: can't acquire context from the given item"); return; } animator.listen(me, 'complete', onAnimationsComplete); animator.listen(me, 'progress', onAnimationProgress); me._initialize(); if (me.attached) { me.update(); } } get aspectRatio() { const {options: {aspectRatio, maintainAspectRatio}, width, height, _aspectRatio} = this; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(aspectRatio)) { return aspectRatio; } if (maintainAspectRatio && _aspectRatio) { return _aspectRatio; } return height ? width / height : null; } get data() { return this.config.data; } set data(data) { this.config.data = data; } get options() { return this._options; } set options(options) { this.config.options = options; } _initialize() { const me = this; me.notifyPlugins('beforeInit'); if (me.options.responsive) { me.resize(); } else { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aa)(me, me.options.devicePixelRatio); } me.bindEvents(); me.notifyPlugins('afterInit'); return me; } clear() { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ab)(this.canvas, this.ctx); return this; } stop() { animator.stop(this); return this; } resize(width, height) { if (!animator.running(this)) { this._resize(width, height); } else { this._resizeBeforeDraw = {width, height}; } } _resize(width, height) { const me = this; const options = me.options; const canvas = me.canvas; const aspectRatio = options.maintainAspectRatio && me.aspectRatio; const newSize = me.platform.getMaximumSize(canvas, width, height, aspectRatio); const newRatio = options.devicePixelRatio || me.platform.getDevicePixelRatio(); me.width = newSize.width; me.height = newSize.height; me._aspectRatio = me.aspectRatio; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aa)(me, newRatio, true)) { return; } me.notifyPlugins('resize', {size: newSize}); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(options.onResize, [me, newSize], me); if (me.attached) { if (me._doResize()) { me.render(); } } } ensureScalesHaveIDs() { const options = this.options; const scalesOptions = options.scales || {}; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(scalesOptions, (axisOptions, axisID) => { axisOptions.id = axisID; }); } buildOrUpdateScales() { const me = this; const options = me.options; const scaleOpts = options.scales; const scales = me.scales; const updated = Object.keys(scales).reduce((obj, id) => { obj[id] = false; return obj; }, {}); let items = []; if (scaleOpts) { items = items.concat( Object.keys(scaleOpts).map((id) => { const scaleOptions = scaleOpts[id]; const axis = determineAxis(id, scaleOptions); const isRadial = axis === 'r'; const isHorizontal = axis === 'x'; return { options: scaleOptions, dposition: isRadial ? 'chartArea' : isHorizontal ? 'bottom' : 'left', dtype: isRadial ? 'radialLinear' : isHorizontal ? 'category' : 'linear' }; }) ); } (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(items, (item) => { const scaleOptions = item.options; const id = scaleOptions.id; const axis = determineAxis(id, scaleOptions); const scaleType = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(scaleOptions.type, item.dtype); if (scaleOptions.position === undefined || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) { scaleOptions.position = item.dposition; } updated[id] = true; let scale = null; if (id in scales && scales[id].type === scaleType) { scale = scales[id]; } else { const scaleClass = registry.getScale(scaleType); scale = new scaleClass({ id, type: scaleType, ctx: me.ctx, chart: me }); scales[scale.id] = scale; } scale.init(scaleOptions, options); }); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(updated, (hasUpdated, id) => { if (!hasUpdated) { delete scales[id]; } }); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(scales, (scale) => { layouts.configure(me, scale, scale.options); layouts.addBox(me, scale); }); } _updateMetasets() { const me = this; const metasets = me._metasets; const numData = me.data.datasets.length; const numMeta = metasets.length; metasets.sort((a, b) => a.index - b.index); if (numMeta > numData) { for (let i = numData; i < numMeta; ++i) { me._destroyDatasetMeta(i); } metasets.splice(numData, numMeta - numData); } me._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index')); } _removeUnreferencedMetasets() { const me = this; const {_metasets: metasets, data: {datasets}} = me; if (metasets.length > datasets.length) { delete me._stacks; } metasets.forEach((meta, index) => { if (datasets.filter(x => x === meta._dataset).length === 0) { me._destroyDatasetMeta(index); } }); } buildOrUpdateControllers() { const me = this; const newControllers = []; const datasets = me.data.datasets; let i, ilen; me._removeUnreferencedMetasets(); for (i = 0, ilen = datasets.length; i < ilen; i++) { const dataset = datasets[i]; let meta = me.getDatasetMeta(i); const type = dataset.type || me.config.type; if (meta.type && meta.type !== type) { me._destroyDatasetMeta(i); meta = me.getDatasetMeta(i); } meta.type = type; meta.indexAxis = dataset.indexAxis || getIndexAxis(type, me.options); meta.order = dataset.order || 0; meta.index = i; meta.label = '' + dataset.label; meta.visible = me.isDatasetVisible(i); if (meta.controller) { meta.controller.updateIndex(i); meta.controller.linkScales(); } else { const ControllerClass = registry.getController(type); const {datasetElementType, dataElementType} = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type]; Object.assign(ControllerClass.prototype, { dataElementType: registry.getElement(dataElementType), datasetElementType: datasetElementType && registry.getElement(datasetElementType) }); meta.controller = new ControllerClass(me, i); newControllers.push(meta.controller); } } me._updateMetasets(); return newControllers; } _resetElements() { const me = this; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me.data.datasets, (dataset, datasetIndex) => { me.getDatasetMeta(datasetIndex).controller.reset(); }, me); } reset() { this._resetElements(); this.notifyPlugins('reset'); } update(mode) { const me = this; const config = me.config; config.update(); me._options = config.createResolver(config.chartOptionScopes(), me.getContext()); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me.scales, (scale) => { layouts.removeBox(me, scale); }); const animsDisabled = me._animationsDisabled = !me.options.animation; me.ensureScalesHaveIDs(); me.buildOrUpdateScales(); const existingEvents = new Set(Object.keys(me._listeners)); const newEvents = new Set(me.options.events); if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ac)(existingEvents, newEvents) || !!this._responsiveListeners !== me.options.responsive) { me.unbindEvents(); me.bindEvents(); } me._plugins.invalidate(); if (me.notifyPlugins('beforeUpdate', {mode, cancelable: true}) === false) { return; } const newControllers = me.buildOrUpdateControllers(); me.notifyPlugins('beforeElementsUpdate'); let minPadding = 0; for (let i = 0, ilen = me.data.datasets.length; i < ilen; i++) { const {controller} = me.getDatasetMeta(i); const reset = !animsDisabled && newControllers.indexOf(controller) === -1; controller.buildOrUpdateElements(reset); minPadding = Math.max(+controller.getMaxOverflow(), minPadding); } me._minPadding = minPadding; me._updateLayout(minPadding); if (!animsDisabled) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(newControllers, (controller) => { controller.reset(); }); } me._updateDatasets(mode); me.notifyPlugins('afterUpdate', {mode}); me._layers.sort(compare2Level('z', '_idx')); if (me._lastEvent) { me._eventHandler(me._lastEvent, true); } me.render(); } _updateLayout(minPadding) { const me = this; if (me.notifyPlugins('beforeLayout', {cancelable: true}) === false) { return; } layouts.update(me, me.width, me.height, minPadding); const area = me.chartArea; const noArea = area.width <= 0 || area.height <= 0; me._layers = []; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me.boxes, (box) => { if (noArea && box.position === 'chartArea') { return; } if (box.configure) { box.configure(); } me._layers.push(...box._layers()); }, me); me._layers.forEach((item, index) => { item._idx = index; }); me.notifyPlugins('afterLayout'); } _updateDatasets(mode) { const me = this; const isFunction = typeof mode === 'function'; if (me.notifyPlugins('beforeDatasetsUpdate', {mode, cancelable: true}) === false) { return; } for (let i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { me._updateDataset(i, isFunction ? mode({datasetIndex: i}) : mode); } me.notifyPlugins('afterDatasetsUpdate', {mode}); } _updateDataset(index, mode) { const me = this; const meta = me.getDatasetMeta(index); const args = {meta, index, mode, cancelable: true}; if (me.notifyPlugins('beforeDatasetUpdate', args) === false) { return; } meta.controller._update(mode); args.cancelable = false; me.notifyPlugins('afterDatasetUpdate', args); } render() { const me = this; if (me.notifyPlugins('beforeRender', {cancelable: true}) === false) { return; } if (animator.has(me)) { if (me.attached && !animator.running(me)) { animator.start(me); } } else { me.draw(); onAnimationsComplete({chart: me}); } } draw() { const me = this; let i; if (me._resizeBeforeDraw) { const {width, height} = me._resizeBeforeDraw; me._resize(width, height); me._resizeBeforeDraw = null; } me.clear(); if (me.width <= 0 || me.height <= 0) { return; } if (me.notifyPlugins('beforeDraw', {cancelable: true}) === false) { return; } const layers = me._layers; for (i = 0; i < layers.length && layers[i].z <= 0; ++i) { layers[i].draw(me.chartArea); } me._drawDatasets(); for (; i < layers.length; ++i) { layers[i].draw(me.chartArea); } me.notifyPlugins('afterDraw'); } _getSortedDatasetMetas(filterVisible) { const me = this; const metasets = me._sortedMetasets; const result = []; let i, ilen; for (i = 0, ilen = metasets.length; i < ilen; ++i) { const meta = metasets[i]; if (!filterVisible || meta.visible) { result.push(meta); } } return result; } getSortedVisibleDatasetMetas() { return this._getSortedDatasetMetas(true); } _drawDatasets() { const me = this; if (me.notifyPlugins('beforeDatasetsDraw', {cancelable: true}) === false) { return; } const metasets = me.getSortedVisibleDatasetMetas(); for (let i = metasets.length - 1; i >= 0; --i) { me._drawDataset(metasets[i]); } me.notifyPlugins('afterDatasetsDraw'); } _drawDataset(meta) { const me = this; const ctx = me.ctx; const clip = meta._clip; const useClip = !clip.disabled; const area = me.chartArea; const args = { meta, index: meta.index, cancelable: true }; if (me.notifyPlugins('beforeDatasetDraw', args) === false) { return; } if (useClip) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.U)(ctx, { left: clip.left === false ? 0 : area.left - clip.left, right: clip.right === false ? me.width : area.right + clip.right, top: clip.top === false ? 0 : area.top - clip.top, bottom: clip.bottom === false ? me.height : area.bottom + clip.bottom }); } meta.controller.draw(); if (useClip) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.W)(ctx); } args.cancelable = false; me.notifyPlugins('afterDatasetDraw', args); } getElementsAtEventForMode(e, mode, options, useFinalPosition) { const method = Interaction.modes[mode]; if (typeof method === 'function') { return method(this, e, options, useFinalPosition); } return []; } getDatasetMeta(datasetIndex) { const me = this; const dataset = me.data.datasets[datasetIndex]; const metasets = me._metasets; let meta = metasets.filter(x => x && x._dataset === dataset).pop(); if (!meta) { meta = { type: null, data: [], dataset: null, controller: null, hidden: null, xAxisID: null, yAxisID: null, order: dataset && dataset.order || 0, index: datasetIndex, _dataset: dataset, _parsed: [], _sorted: false }; metasets.push(meta); } return meta; } getContext() { return this.$context || (this.$context = {chart: this, type: 'chart'}); } getVisibleDatasetCount() { return this.getSortedVisibleDatasetMetas().length; } isDatasetVisible(datasetIndex) { const dataset = this.data.datasets[datasetIndex]; if (!dataset) { return false; } const meta = this.getDatasetMeta(datasetIndex); return typeof meta.hidden === 'boolean' ? !meta.hidden : !dataset.hidden; } setDatasetVisibility(datasetIndex, visible) { const meta = this.getDatasetMeta(datasetIndex); meta.hidden = !visible; } toggleDataVisibility(index) { this._hiddenIndices[index] = !this._hiddenIndices[index]; } getDataVisibility(index) { return !this._hiddenIndices[index]; } _updateVisibility(datasetIndex, dataIndex, visible) { const me = this; const mode = visible ? 'show' : 'hide'; const meta = me.getDatasetMeta(datasetIndex); const anims = meta.controller._resolveAnimations(undefined, mode); if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(dataIndex)) { meta.data[dataIndex].hidden = !visible; me.update(); } else { me.setDatasetVisibility(datasetIndex, visible); anims.update(meta, {visible}); me.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined); } } hide(datasetIndex, dataIndex) { this._updateVisibility(datasetIndex, dataIndex, false); } show(datasetIndex, dataIndex) { this._updateVisibility(datasetIndex, dataIndex, true); } _destroyDatasetMeta(datasetIndex) { const me = this; const meta = me._metasets && me._metasets[datasetIndex]; if (meta && meta.controller) { meta.controller._destroy(); delete me._metasets[datasetIndex]; } } destroy() { const me = this; const {canvas, ctx} = me; let i, ilen; me.stop(); animator.remove(me); for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { me._destroyDatasetMeta(i); } me.config.clearCache(); if (canvas) { me.unbindEvents(); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ab)(canvas, ctx); me.platform.releaseContext(ctx); me.canvas = null; me.ctx = null; } me.notifyPlugins('destroy'); delete instances[me.id]; } toBase64Image(...args) { return this.canvas.toDataURL(...args); } bindEvents() { this.bindUserEvents(); if (this.options.responsive) { this.bindResponsiveEvents(); } else { this.attached = true; } } bindUserEvents() { const me = this; const listeners = me._listeners; const platform = me.platform; const _add = (type, listener) => { platform.addEventListener(me, type, listener); listeners[type] = listener; }; const listener = function(e, x, y) { e.offsetX = x; e.offsetY = y; me._eventHandler(e); }; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me.options.events, (type) => _add(type, listener)); } bindResponsiveEvents() { const me = this; if (!me._responsiveListeners) { me._responsiveListeners = {}; } const listeners = me._responsiveListeners; const platform = me.platform; const _add = (type, listener) => { platform.addEventListener(me, type, listener); listeners[type] = listener; }; const _remove = (type, listener) => { if (listeners[type]) { platform.removeEventListener(me, type, listener); delete listeners[type]; } }; const listener = (width, height) => { if (me.canvas) { me.resize(width, height); } }; let detached; const attached = () => { _remove('attach', attached); me.attached = true; me.resize(); _add('resize', listener); _add('detach', detached); }; detached = () => { me.attached = false; _remove('resize', listener); _add('attach', attached); }; if (platform.isAttached(me.canvas)) { attached(); } else { detached(); } } unbindEvents() { const me = this; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me._listeners, (listener, type) => { me.platform.removeEventListener(me, type, listener); }); me._listeners = {}; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me._responsiveListeners, (listener, type) => { me.platform.removeEventListener(me, type, listener); }); me._responsiveListeners = undefined; } updateHoverStyle(items, mode, enabled) { const prefix = enabled ? 'set' : 'remove'; let meta, item, i, ilen; if (mode === 'dataset') { meta = this.getDatasetMeta(items[0].datasetIndex); meta.controller['_' + prefix + 'DatasetHoverStyle'](); } for (i = 0, ilen = items.length; i < ilen; ++i) { item = items[i]; const controller = item && this.getDatasetMeta(item.datasetIndex).controller; if (controller) { controller[prefix + 'HoverStyle'](item.element, item.datasetIndex, item.index); } } } getActiveElements() { return this._active || []; } setActiveElements(activeElements) { const me = this; const lastActive = me._active || []; const active = activeElements.map(({datasetIndex, index}) => { const meta = me.getDatasetMeta(datasetIndex); if (!meta) { throw new Error('No dataset found at index ' + datasetIndex); } return { datasetIndex, element: meta.data[index], index, }; }); const changed = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ad)(active, lastActive); if (changed) { me._active = active; me._updateHoverStyles(active, lastActive); } } notifyPlugins(hook, args, filter) { return this._plugins.notify(this, hook, args, filter); } _updateHoverStyles(active, lastActive, replay) { const me = this; const hoverOptions = me.options.hover; const diff = (a, b) => a.filter(x => !b.some(y => x.datasetIndex === y.datasetIndex && x.index === y.index)); const deactivated = diff(lastActive, active); const activated = replay ? active : diff(active, lastActive); if (deactivated.length) { me.updateHoverStyle(deactivated, hoverOptions.mode, false); } if (activated.length && hoverOptions.mode) { me.updateHoverStyle(activated, hoverOptions.mode, true); } } _eventHandler(e, replay) { const me = this; const args = {event: e, replay, cancelable: true}; const eventFilter = (plugin) => (plugin.options.events || this.options.events).includes(e.type); if (me.notifyPlugins('beforeEvent', args, eventFilter) === false) { return; } const changed = me._handleEvent(e, replay); args.cancelable = false; me.notifyPlugins('afterEvent', args, eventFilter); if (changed || args.changed) { me.render(); } return me; } _handleEvent(e, replay) { const me = this; const {_active: lastActive = [], options} = me; const hoverOptions = options.hover; const useFinalPosition = replay; let active = []; let changed = false; let lastEvent = null; if (e.type !== 'mouseout') { active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition); lastEvent = e.type === 'click' ? me._lastEvent : e; } me._lastEvent = null; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.y)(e, me.chartArea, me._minPadding)) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(options.onHover, [e, active, me], me); if (e.type === 'mouseup' || e.type === 'click' || e.type === 'contextmenu') { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(options.onClick, [e, active, me], me); } } changed = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ad)(active, lastActive); if (changed || replay) { me._active = active; me._updateHoverStyles(active, lastActive, replay); } me._lastEvent = lastEvent; return changed; } } const invalidatePlugins = () => (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(Chart.instances, (chart) => chart._plugins.invalidate()); const enumerable = true; Object.defineProperties(Chart, { defaults: { enumerable, value: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d }, instances: { enumerable, value: instances }, overrides: { enumerable, value: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$ }, registry: { enumerable, value: registry }, version: { enumerable, value: version }, getChart: { enumerable, value: getChart }, register: { enumerable, value: (...items) => { registry.add(...items); invalidatePlugins(); } }, unregister: { enumerable, value: (...items) => { registry.remove(...items); invalidatePlugins(); } } }); function clipArc(ctx, element, endAngle) { const {startAngle, pixelMargin, x, y, outerRadius, innerRadius} = element; let angleMargin = pixelMargin / outerRadius; ctx.beginPath(); ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin); if (innerRadius > pixelMargin) { angleMargin = pixelMargin / innerRadius; ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true); } else { ctx.arc(x, y, pixelMargin, endAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, startAngle - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H); } ctx.closePath(); ctx.clip(); } function toRadiusCorners(value) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.af)(value, ['outerStart', 'outerEnd', 'innerStart', 'innerEnd']); } function parseBorderRadius$1(arc, innerRadius, outerRadius, angleDelta) { const o = toRadiusCorners(arc.options.borderRadius); const halfThickness = (outerRadius - innerRadius) / 2; const innerLimit = Math.min(halfThickness, angleDelta * innerRadius / 2); const computeOuterLimit = (val) => { const outerArcLimit = (outerRadius - Math.min(halfThickness, val)) * angleDelta / 2; return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(val, 0, Math.min(halfThickness, outerArcLimit)); }; return { outerStart: computeOuterLimit(o.outerStart), outerEnd: computeOuterLimit(o.outerEnd), innerStart: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(o.innerStart, 0, innerLimit), innerEnd: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(o.innerEnd, 0, innerLimit), }; } function rThetaToXY(r, theta, x, y) { return { x: x + r * Math.cos(theta), y: y + r * Math.sin(theta), }; } function pathArc(ctx, element, offset, spacing, end) { const {x, y, startAngle: start, pixelMargin, innerRadius: innerR} = element; const outerRadius = Math.max(element.outerRadius + spacing + offset - pixelMargin, 0); const innerRadius = innerR > 0 ? innerR + spacing + offset + pixelMargin : 0; let spacingOffset = 0; const alpha = end - start; if (spacing) { const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0; const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0; const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2; const adjustedAngle = avNogSpacingRadius !== 0 ? (alpha * avNogSpacingRadius) / (avNogSpacingRadius + spacing) : alpha; spacingOffset = (alpha - adjustedAngle) / 2; } const beta = Math.max(0.001, alpha * outerRadius - offset / _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P) / outerRadius; const angleOffset = (alpha - beta) / 2; const startAngle = start + angleOffset + spacingOffset; const endAngle = end - angleOffset - spacingOffset; const {outerStart, outerEnd, innerStart, innerEnd} = parseBorderRadius$1(element, innerRadius, outerRadius, endAngle - startAngle); const outerStartAdjustedRadius = outerRadius - outerStart; const outerEndAdjustedRadius = outerRadius - outerEnd; const outerStartAdjustedAngle = startAngle + outerStart / outerStartAdjustedRadius; const outerEndAdjustedAngle = endAngle - outerEnd / outerEndAdjustedRadius; const innerStartAdjustedRadius = innerRadius + innerStart; const innerEndAdjustedRadius = innerRadius + innerEnd; const innerStartAdjustedAngle = startAngle + innerStart / innerStartAdjustedRadius; const innerEndAdjustedAngle = endAngle - innerEnd / innerEndAdjustedRadius; ctx.beginPath(); ctx.arc(x, y, outerRadius, outerStartAdjustedAngle, outerEndAdjustedAngle); if (outerEnd > 0) { const pCenter = rThetaToXY(outerEndAdjustedRadius, outerEndAdjustedAngle, x, y); ctx.arc(pCenter.x, pCenter.y, outerEnd, outerEndAdjustedAngle, endAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H); } const p4 = rThetaToXY(innerEndAdjustedRadius, endAngle, x, y); ctx.lineTo(p4.x, p4.y); if (innerEnd > 0) { const pCenter = rThetaToXY(innerEndAdjustedRadius, innerEndAdjustedAngle, x, y); ctx.arc(pCenter.x, pCenter.y, innerEnd, endAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, innerEndAdjustedAngle + Math.PI); } ctx.arc(x, y, innerRadius, endAngle - (innerEnd / innerRadius), startAngle + (innerStart / innerRadius), true); if (innerStart > 0) { const pCenter = rThetaToXY(innerStartAdjustedRadius, innerStartAdjustedAngle, x, y); ctx.arc(pCenter.x, pCenter.y, innerStart, innerStartAdjustedAngle + Math.PI, startAngle - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H); } const p8 = rThetaToXY(outerStartAdjustedRadius, startAngle, x, y); ctx.lineTo(p8.x, p8.y); if (outerStart > 0) { const pCenter = rThetaToXY(outerStartAdjustedRadius, outerStartAdjustedAngle, x, y); ctx.arc(pCenter.x, pCenter.y, outerStart, startAngle - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, outerStartAdjustedAngle); } ctx.closePath(); } function drawArc(ctx, element, offset, spacing) { const {fullCircles, startAngle, circumference} = element; let endAngle = element.endAngle; if (fullCircles) { pathArc(ctx, element, offset, spacing, startAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); for (let i = 0; i < fullCircles; ++i) { ctx.fill(); } if (!isNaN(circumference)) { endAngle = startAngle + circumference % _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T; if (circumference % _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T === 0) { endAngle += _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T; } } } pathArc(ctx, element, offset, spacing, endAngle); ctx.fill(); return endAngle; } function drawFullCircleBorders(ctx, element, inner) { const {x, y, startAngle, pixelMargin, fullCircles} = element; const outerRadius = Math.max(element.outerRadius - pixelMargin, 0); const innerRadius = element.innerRadius + pixelMargin; let i; if (inner) { clipArc(ctx, element, startAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); } ctx.beginPath(); ctx.arc(x, y, innerRadius, startAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T, startAngle, true); for (i = 0; i < fullCircles; ++i) { ctx.stroke(); } ctx.beginPath(); ctx.arc(x, y, outerRadius, startAngle, startAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); for (i = 0; i < fullCircles; ++i) { ctx.stroke(); } } function drawBorder(ctx, element, offset, spacing, endAngle) { const {options} = element; const inner = options.borderAlign === 'inner'; if (!options.borderWidth) { return; } if (inner) { ctx.lineWidth = options.borderWidth * 2; ctx.lineJoin = 'round'; } else { ctx.lineWidth = options.borderWidth; ctx.lineJoin = 'bevel'; } if (element.fullCircles) { drawFullCircleBorders(ctx, element, inner); } if (inner) { clipArc(ctx, element, endAngle); } pathArc(ctx, element, offset, spacing, endAngle); ctx.stroke(); } class ArcElement extends Element { constructor(cfg) { super(); this.options = undefined; this.circumference = undefined; this.startAngle = undefined; this.endAngle = undefined; this.innerRadius = undefined; this.outerRadius = undefined; this.pixelMargin = 0; this.fullCircles = 0; if (cfg) { Object.assign(this, cfg); } } inRange(chartX, chartY, useFinalPosition) { const point = this.getProps(['x', 'y'], useFinalPosition); const {angle, distance} = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ae)(point, {x: chartX, y: chartY}); const {startAngle, endAngle, innerRadius, outerRadius, circumference} = this.getProps([ 'startAngle', 'endAngle', 'innerRadius', 'outerRadius', 'circumference' ], useFinalPosition); const rAdjust = this.options.spacing / 2; const betweenAngles = circumference >= _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.o)(angle, startAngle, endAngle); const withinRadius = (distance >= innerRadius + rAdjust && distance <= outerRadius + rAdjust); return (betweenAngles && withinRadius); } getCenterPoint(useFinalPosition) { const {x, y, startAngle, endAngle, innerRadius, outerRadius} = this.getProps([ 'x', 'y', 'startAngle', 'endAngle', 'innerRadius', 'outerRadius', 'circumference', ], useFinalPosition); const {offset, spacing} = this.options; const halfAngle = (startAngle + endAngle) / 2; const halfRadius = (innerRadius + outerRadius + spacing + offset) / 2; return { x: x + Math.cos(halfAngle) * halfRadius, y: y + Math.sin(halfAngle) * halfRadius }; } tooltipPosition(useFinalPosition) { return this.getCenterPoint(useFinalPosition); } draw(ctx) { const me = this; const {options, circumference} = me; const offset = (options.offset || 0) / 2; const spacing = (options.spacing || 0) / 2; me.pixelMargin = (options.borderAlign === 'inner') ? 0.33 : 0; me.fullCircles = circumference > _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T ? Math.floor(circumference / _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T) : 0; if (circumference === 0 || me.innerRadius < 0 || me.outerRadius < 0) { return; } ctx.save(); let radiusOffset = 0; if (offset) { radiusOffset = offset / 2; const halfAngle = (me.startAngle + me.endAngle) / 2; ctx.translate(Math.cos(halfAngle) * radiusOffset, Math.sin(halfAngle) * radiusOffset); if (me.circumference >= _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P) { radiusOffset = offset; } } ctx.fillStyle = options.backgroundColor; ctx.strokeStyle = options.borderColor; const endAngle = drawArc(ctx, me, radiusOffset, spacing); drawBorder(ctx, me, radiusOffset, spacing, endAngle); ctx.restore(); } } ArcElement.id = 'arc'; ArcElement.defaults = { borderAlign: 'center', borderColor: '#fff', borderRadius: 0, borderWidth: 2, offset: 0, spacing: 0, angle: undefined, }; ArcElement.defaultRoutes = { backgroundColor: 'backgroundColor' }; function setStyle(ctx, options, style = options) { ctx.lineCap = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderCapStyle, options.borderCapStyle); ctx.setLineDash((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDash, options.borderDash)); ctx.lineDashOffset = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDashOffset, options.borderDashOffset); ctx.lineJoin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderJoinStyle, options.borderJoinStyle); ctx.lineWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderWidth, options.borderWidth); ctx.strokeStyle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderColor, options.borderColor); } function lineTo(ctx, previous, target) { ctx.lineTo(target.x, target.y); } function getLineMethod(options) { if (options.stepped) { return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.am; } if (options.tension || options.cubicInterpolationMode === 'monotone') { return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.an; } return lineTo; } function pathVars(points, segment, params = {}) { const count = points.length; const {start: paramsStart = 0, end: paramsEnd = count - 1} = params; const {start: segmentStart, end: segmentEnd} = segment; const start = Math.max(paramsStart, segmentStart); const end = Math.min(paramsEnd, segmentEnd); const outside = paramsStart < segmentStart && paramsEnd < segmentStart || paramsStart > segmentEnd && paramsEnd > segmentEnd; return { count, start, loop: segment.loop, ilen: end < start && !outside ? count + end - start : end - start }; } function pathSegment(ctx, line, segment, params) { const {points, options} = line; const {count, start, loop, ilen} = pathVars(points, segment, params); const lineMethod = getLineMethod(options); let {move = true, reverse} = params || {}; let i, point, prev; for (i = 0; i <= ilen; ++i) { point = points[(start + (reverse ? ilen - i : i)) % count]; if (point.skip) { continue; } else if (move) { ctx.moveTo(point.x, point.y); move = false; } else { lineMethod(ctx, prev, point, reverse, options.stepped); } prev = point; } if (loop) { point = points[(start + (reverse ? ilen : 0)) % count]; lineMethod(ctx, prev, point, reverse, options.stepped); } return !!loop; } function fastPathSegment(ctx, line, segment, params) { const points = line.points; const {count, start, ilen} = pathVars(points, segment, params); const {move = true, reverse} = params || {}; let avgX = 0; let countX = 0; let i, point, prevX, minY, maxY, lastY; const pointIndex = (index) => (start + (reverse ? ilen - index : index)) % count; const drawX = () => { if (minY !== maxY) { ctx.lineTo(avgX, maxY); ctx.lineTo(avgX, minY); ctx.lineTo(avgX, lastY); } }; if (move) { point = points[pointIndex(0)]; ctx.moveTo(point.x, point.y); } for (i = 0; i <= ilen; ++i) { point = points[pointIndex(i)]; if (point.skip) { continue; } const x = point.x; const y = point.y; const truncX = x | 0; if (truncX === prevX) { if (y < minY) { minY = y; } else if (y > maxY) { maxY = y; } avgX = (countX * avgX + x) / ++countX; } else { drawX(); ctx.lineTo(x, y); prevX = truncX; countX = 0; minY = maxY = y; } lastY = y; } drawX(); } function _getSegmentMethod(line) { const opts = line.options; const borderDash = opts.borderDash && opts.borderDash.length; const useFastPath = !line._decimated && !line._loop && !opts.tension && opts.cubicInterpolationMode !== 'monotone' && !opts.stepped && !borderDash; return useFastPath ? fastPathSegment : pathSegment; } function _getInterpolationMethod(options) { if (options.stepped) { return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj; } if (options.tension || options.cubicInterpolationMode === 'monotone') { return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ak; } return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.al; } function strokePathWithCache(ctx, line, start, count) { let path = line._path; if (!path) { path = line._path = new Path2D(); if (line.path(path, start, count)) { path.closePath(); } } setStyle(ctx, line.options); ctx.stroke(path); } function strokePathDirect(ctx, line, start, count) { const {segments, options} = line; const segmentMethod = _getSegmentMethod(line); for (const segment of segments) { setStyle(ctx, options, segment.style); ctx.beginPath(); if (segmentMethod(ctx, line, segment, {start, end: start + count - 1})) { ctx.closePath(); } ctx.stroke(); } } const usePath2D = typeof Path2D === 'function'; function draw(ctx, line, start, count) { if (usePath2D && line.segments.length === 1) { strokePathWithCache(ctx, line, start, count); } else { strokePathDirect(ctx, line, start, count); } } class LineElement extends Element { constructor(cfg) { super(); this.animated = true; this.options = undefined; this._loop = undefined; this._fullLoop = undefined; this._path = undefined; this._points = undefined; this._segments = undefined; this._decimated = false; this._pointsUpdated = false; this._datasetIndex = undefined; if (cfg) { Object.assign(this, cfg); } } updateControlPoints(chartArea, indexAxis) { const me = this; const options = me.options; if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !me._pointsUpdated) { const loop = options.spanGaps ? me._loop : me._fullLoop; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ag)(me._points, options, chartArea, loop, indexAxis); me._pointsUpdated = true; } } set points(points) { const me = this; me._points = points; delete me._segments; delete me._path; me._pointsUpdated = false; } get points() { return this._points; } get segments() { return this._segments || (this._segments = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ah)(this, this.options.segment)); } first() { const segments = this.segments; const points = this.points; return segments.length && points[segments[0].start]; } last() { const segments = this.segments; const points = this.points; const count = segments.length; return count && points[segments[count - 1].end]; } interpolate(point, property) { const me = this; const options = me.options; const value = point[property]; const points = me.points; const segments = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ai)(me, {property, start: value, end: value}); if (!segments.length) { return; } const result = []; const _interpolate = _getInterpolationMethod(options); let i, ilen; for (i = 0, ilen = segments.length; i < ilen; ++i) { const {start, end} = segments[i]; const p1 = points[start]; const p2 = points[end]; if (p1 === p2) { result.push(p1); continue; } const t = Math.abs((value - p1[property]) / (p2[property] - p1[property])); const interpolated = _interpolate(p1, p2, t, options.stepped); interpolated[property] = point[property]; result.push(interpolated); } return result.length === 1 ? result[0] : result; } pathSegment(ctx, segment, params) { const segmentMethod = _getSegmentMethod(this); return segmentMethod(ctx, this, segment, params); } path(ctx, start, count) { const me = this; const segments = me.segments; const segmentMethod = _getSegmentMethod(me); let loop = me._loop; start = start || 0; count = count || (me.points.length - start); for (const segment of segments) { loop &= segmentMethod(ctx, me, segment, {start, end: start + count - 1}); } return !!loop; } draw(ctx, chartArea, start, count) { const me = this; const options = me.options || {}; const points = me.points || []; if (!points.length || !options.borderWidth) { return; } ctx.save(); draw(ctx, me, start, count); ctx.restore(); if (me.animated) { me._pointsUpdated = false; me._path = undefined; } } } LineElement.id = 'line'; LineElement.defaults = { borderCapStyle: 'butt', borderDash: [], borderDashOffset: 0, borderJoinStyle: 'miter', borderWidth: 3, capBezierPoints: true, cubicInterpolationMode: 'default', fill: false, spanGaps: false, stepped: false, tension: 0, }; LineElement.defaultRoutes = { backgroundColor: 'backgroundColor', borderColor: 'borderColor' }; LineElement.descriptors = { _scriptable: true, _indexable: (name) => name !== 'borderDash' && name !== 'fill', }; function inRange$1(el, pos, axis, useFinalPosition) { const options = el.options; const {[axis]: value} = el.getProps([axis], useFinalPosition); return (Math.abs(pos - value) < options.radius + options.hitRadius); } class PointElement extends Element { constructor(cfg) { super(); this.options = undefined; this.parsed = undefined; this.skip = undefined; this.stop = undefined; if (cfg) { Object.assign(this, cfg); } } inRange(mouseX, mouseY, useFinalPosition) { const options = this.options; const {x, y} = this.getProps(['x', 'y'], useFinalPosition); return ((Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2)) < Math.pow(options.hitRadius + options.radius, 2)); } inXRange(mouseX, useFinalPosition) { return inRange$1(this, mouseX, 'x', useFinalPosition); } inYRange(mouseY, useFinalPosition) { return inRange$1(this, mouseY, 'y', useFinalPosition); } getCenterPoint(useFinalPosition) { const {x, y} = this.getProps(['x', 'y'], useFinalPosition); return {x, y}; } size(options) { options = options || this.options || {}; let radius = options.radius || 0; radius = Math.max(radius, radius && options.hoverRadius || 0); const borderWidth = radius && options.borderWidth || 0; return (radius + borderWidth) * 2; } draw(ctx, area) { const me = this; const options = me.options; if (me.skip || options.radius < 0.1 || !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.y)(me, area, me.size(options) / 2)) { return; } ctx.strokeStyle = options.borderColor; ctx.lineWidth = options.borderWidth; ctx.fillStyle = options.backgroundColor; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ao)(ctx, options, me.x, me.y); } getRange() { const options = this.options || {}; return options.radius + options.hitRadius; } } PointElement.id = 'point'; PointElement.defaults = { borderWidth: 1, hitRadius: 1, hoverBorderWidth: 1, hoverRadius: 4, pointStyle: 'circle', radius: 3, rotation: 0 }; PointElement.defaultRoutes = { backgroundColor: 'backgroundColor', borderColor: 'borderColor' }; function getBarBounds(bar, useFinalPosition) { const {x, y, base, width, height} = bar.getProps(['x', 'y', 'base', 'width', 'height'], useFinalPosition); let left, right, top, bottom, half; if (bar.horizontal) { half = height / 2; left = Math.min(x, base); right = Math.max(x, base); top = y - half; bottom = y + half; } else { half = width / 2; left = x - half; right = x + half; top = Math.min(y, base); bottom = Math.max(y, base); } return {left, top, right, bottom}; } function skipOrLimit(skip, value, min, max) { return skip ? 0 : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(value, min, max); } function parseBorderWidth(bar, maxW, maxH) { const value = bar.options.borderWidth; const skip = bar.borderSkipped; const o = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aq)(value); return { t: skipOrLimit(skip.top, o.top, 0, maxH), r: skipOrLimit(skip.right, o.right, 0, maxW), b: skipOrLimit(skip.bottom, o.bottom, 0, maxH), l: skipOrLimit(skip.left, o.left, 0, maxW) }; } function parseBorderRadius(bar, maxW, maxH) { const {enableBorderRadius} = bar.getProps(['enableBorderRadius']); const value = bar.options.borderRadius; const o = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ar)(value); const maxR = Math.min(maxW, maxH); const skip = bar.borderSkipped; const enableBorder = enableBorderRadius || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(value); return { topLeft: skipOrLimit(!enableBorder || skip.top || skip.left, o.topLeft, 0, maxR), topRight: skipOrLimit(!enableBorder || skip.top || skip.right, o.topRight, 0, maxR), bottomLeft: skipOrLimit(!enableBorder || skip.bottom || skip.left, o.bottomLeft, 0, maxR), bottomRight: skipOrLimit(!enableBorder || skip.bottom || skip.right, o.bottomRight, 0, maxR) }; } function boundingRects(bar) { const bounds = getBarBounds(bar); const width = bounds.right - bounds.left; const height = bounds.bottom - bounds.top; const border = parseBorderWidth(bar, width / 2, height / 2); const radius = parseBorderRadius(bar, width / 2, height / 2); return { outer: { x: bounds.left, y: bounds.top, w: width, h: height, radius }, inner: { x: bounds.left + border.l, y: bounds.top + border.t, w: width - border.l - border.r, h: height - border.t - border.b, radius: { topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)), topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)), bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)), bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r)), } } }; } function inRange(bar, x, y, useFinalPosition) { const skipX = x === null; const skipY = y === null; const skipBoth = skipX && skipY; const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition); return bounds && (skipX || x >= bounds.left && x <= bounds.right) && (skipY || y >= bounds.top && y <= bounds.bottom); } function hasRadius(radius) { return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight; } function addNormalRectPath(ctx, rect) { ctx.rect(rect.x, rect.y, rect.w, rect.h); } function inflateRect(rect, amount, refRect = {}) { const x = rect.x !== refRect.x ? -amount : 0; const y = rect.y !== refRect.y ? -amount : 0; const w = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x; const h = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y; return { x: rect.x + x, y: rect.y + y, w: rect.w + w, h: rect.h + h, radius: rect.radius }; } class BarElement extends Element { constructor(cfg) { super(); this.options = undefined; this.horizontal = undefined; this.base = undefined; this.width = undefined; this.height = undefined; if (cfg) { Object.assign(this, cfg); } } draw(ctx) { const options = this.options; const {inner, outer} = boundingRects(this); const addRectPath = hasRadius(outer.radius) ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ap : addNormalRectPath; const inflateAmount = 0.33; ctx.save(); if (outer.w !== inner.w || outer.h !== inner.h) { ctx.beginPath(); addRectPath(ctx, inflateRect(outer, inflateAmount, inner)); ctx.clip(); addRectPath(ctx, inflateRect(inner, -inflateAmount, outer)); ctx.fillStyle = options.borderColor; ctx.fill('evenodd'); } ctx.beginPath(); addRectPath(ctx, inflateRect(inner, inflateAmount, outer)); ctx.fillStyle = options.backgroundColor; ctx.fill(); ctx.restore(); } inRange(mouseX, mouseY, useFinalPosition) { return inRange(this, mouseX, mouseY, useFinalPosition); } inXRange(mouseX, useFinalPosition) { return inRange(this, mouseX, null, useFinalPosition); } inYRange(mouseY, useFinalPosition) { return inRange(this, null, mouseY, useFinalPosition); } getCenterPoint(useFinalPosition) { const {x, y, base, horizontal} = this.getProps(['x', 'y', 'base', 'horizontal'], useFinalPosition); return { x: horizontal ? (x + base) / 2 : x, y: horizontal ? y : (y + base) / 2 }; } getRange(axis) { return axis === 'x' ? this.width / 2 : this.height / 2; } } BarElement.id = 'bar'; BarElement.defaults = { borderSkipped: 'start', borderWidth: 0, borderRadius: 0, enableBorderRadius: true, pointStyle: undefined }; BarElement.defaultRoutes = { backgroundColor: 'backgroundColor', borderColor: 'borderColor' }; var elements = /*#__PURE__*/Object.freeze({ __proto__: null, ArcElement: ArcElement, LineElement: LineElement, PointElement: PointElement, BarElement: BarElement }); function lttbDecimation(data, start, count, availableWidth, options) { const samples = options.samples || availableWidth; if (samples >= count) { return data.slice(start, start + count); } const decimated = []; const bucketWidth = (count - 2) / (samples - 2); let sampledIndex = 0; const endIndex = start + count - 1; let a = start; let i, maxAreaPoint, maxArea, area, nextA; decimated[sampledIndex++] = data[a]; for (i = 0; i < samples - 2; i++) { let avgX = 0; let avgY = 0; let j; const avgRangeStart = Math.floor((i + 1) * bucketWidth) + 1 + start; const avgRangeEnd = Math.min(Math.floor((i + 2) * bucketWidth) + 1, count) + start; const avgRangeLength = avgRangeEnd - avgRangeStart; for (j = avgRangeStart; j < avgRangeEnd; j++) { avgX += data[j].x; avgY += data[j].y; } avgX /= avgRangeLength; avgY /= avgRangeLength; const rangeOffs = Math.floor(i * bucketWidth) + 1 + start; const rangeTo = Math.min(Math.floor((i + 1) * bucketWidth) + 1, count) + start; const {x: pointAx, y: pointAy} = data[a]; maxArea = area = -1; for (j = rangeOffs; j < rangeTo; j++) { area = 0.5 * Math.abs( (pointAx - avgX) * (data[j].y - pointAy) - (pointAx - data[j].x) * (avgY - pointAy) ); if (area > maxArea) { maxArea = area; maxAreaPoint = data[j]; nextA = j; } } decimated[sampledIndex++] = maxAreaPoint; a = nextA; } decimated[sampledIndex++] = data[endIndex]; return decimated; } function minMaxDecimation(data, start, count, availableWidth) { let avgX = 0; let countX = 0; let i, point, x, y, prevX, minIndex, maxIndex, startIndex, minY, maxY; const decimated = []; const endIndex = start + count - 1; const xMin = data[start].x; const xMax = data[endIndex].x; const dx = xMax - xMin; for (i = start; i < start + count; ++i) { point = data[i]; x = (point.x - xMin) / dx * availableWidth; y = point.y; const truncX = x | 0; if (truncX === prevX) { if (y < minY) { minY = y; minIndex = i; } else if (y > maxY) { maxY = y; maxIndex = i; } avgX = (countX * avgX + point.x) / ++countX; } else { const lastIndex = i - 1; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(minIndex) && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(maxIndex)) { const intermediateIndex1 = Math.min(minIndex, maxIndex); const intermediateIndex2 = Math.max(minIndex, maxIndex); if (intermediateIndex1 !== startIndex && intermediateIndex1 !== lastIndex) { decimated.push({ ...data[intermediateIndex1], x: avgX, }); } if (intermediateIndex2 !== startIndex && intermediateIndex2 !== lastIndex) { decimated.push({ ...data[intermediateIndex2], x: avgX }); } } if (i > 0 && lastIndex !== startIndex) { decimated.push(data[lastIndex]); } decimated.push(point); prevX = truncX; countX = 0; minY = maxY = y; minIndex = maxIndex = startIndex = i; } } return decimated; } function cleanDecimatedDataset(dataset) { if (dataset._decimated) { const data = dataset._data; delete dataset._decimated; delete dataset._data; Object.defineProperty(dataset, 'data', {value: data}); } } function cleanDecimatedData(chart) { chart.data.datasets.forEach((dataset) => { cleanDecimatedDataset(dataset); }); } function getStartAndCountOfVisiblePointsSimplified(meta, points) { const pointCount = points.length; let start = 0; let count; const {iScale} = meta; const {min, max, minDefined, maxDefined} = iScale.getUserBounds(); if (minDefined) { start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(points, iScale.axis, min).lo, 0, pointCount - 1); } if (maxDefined) { count = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(points, iScale.axis, max).hi + 1, start, pointCount) - start; } else { count = pointCount - start; } return {start, count}; } var plugin_decimation = { id: 'decimation', defaults: { algorithm: 'min-max', enabled: false, }, beforeElementsUpdate: (chart, args, options) => { if (!options.enabled) { cleanDecimatedData(chart); return; } const availableWidth = chart.width; chart.data.datasets.forEach((dataset, datasetIndex) => { const {_data, indexAxis} = dataset; const meta = chart.getDatasetMeta(datasetIndex); const data = _data || dataset.data; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([indexAxis, chart.options.indexAxis]) === 'y') { return; } if (meta.type !== 'line') { return; } const xAxis = chart.scales[meta.xAxisID]; if (xAxis.type !== 'linear' && xAxis.type !== 'time') { return; } if (chart.options.parsing) { return; } let {start, count} = getStartAndCountOfVisiblePointsSimplified(meta, data); const threshold = options.threshold || 4 * availableWidth; if (count <= threshold) { cleanDecimatedDataset(dataset); return; } if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(_data)) { dataset._data = data; delete dataset.data; Object.defineProperty(dataset, 'data', { configurable: true, enumerable: true, get: function() { return this._decimated; }, set: function(d) { this._data = d; } }); } let decimated; switch (options.algorithm) { case 'lttb': decimated = lttbDecimation(data, start, count, availableWidth, options); break; case 'min-max': decimated = minMaxDecimation(data, start, count, availableWidth); break; default: throw new Error(`Unsupported decimation algorithm '${options.algorithm}'`); } dataset._decimated = decimated; }); }, destroy(chart) { cleanDecimatedData(chart); } }; function getLineByIndex(chart, index) { const meta = chart.getDatasetMeta(index); const visible = meta && chart.isDatasetVisible(index); return visible ? meta.dataset : null; } function parseFillOption(line) { const options = line.options; const fillOption = options.fill; let fill = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(fillOption && fillOption.target, fillOption); if (fill === undefined) { fill = !!options.backgroundColor; } if (fill === false || fill === null) { return false; } if (fill === true) { return 'origin'; } return fill; } function decodeFill(line, index, count) { const fill = parseFillOption(line); if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) { return isNaN(fill.value) ? false : fill; } let target = parseFloat(fill); if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(target) && Math.floor(target) === target) { if (fill[0] === '-' || fill[0] === '+') { target = index + target; } if (target === index || target < 0 || target >= count) { return false; } return target; } return ['origin', 'start', 'end', 'stack', 'shape'].indexOf(fill) >= 0 && fill; } function computeLinearBoundary(source) { const {scale = {}, fill} = source; let target = null; let horizontal; if (fill === 'start') { target = scale.bottom; } else if (fill === 'end') { target = scale.top; } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) { target = scale.getPixelForValue(fill.value); } else if (scale.getBasePixel) { target = scale.getBasePixel(); } if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(target)) { horizontal = scale.isHorizontal(); return { x: horizontal ? target : null, y: horizontal ? null : target }; } return null; } class simpleArc { constructor(opts) { this.x = opts.x; this.y = opts.y; this.radius = opts.radius; } pathSegment(ctx, bounds, opts) { const {x, y, radius} = this; bounds = bounds || {start: 0, end: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T}; ctx.arc(x, y, radius, bounds.end, bounds.start, true); return !opts.bounds; } interpolate(point) { const {x, y, radius} = this; const angle = point.angle; return { x: x + Math.cos(angle) * radius, y: y + Math.sin(angle) * radius, angle }; } } function computeCircularBoundary(source) { const {scale, fill} = source; const options = scale.options; const length = scale.getLabels().length; const target = []; const start = options.reverse ? scale.max : scale.min; const end = options.reverse ? scale.min : scale.max; let i, center, value; if (fill === 'start') { value = start; } else if (fill === 'end') { value = end; } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) { value = fill.value; } else { value = scale.getBaseValue(); } if (options.grid.circular) { center = scale.getPointPositionForValue(0, start); return new simpleArc({ x: center.x, y: center.y, radius: scale.getDistanceFromCenterForValue(value) }); } for (i = 0; i < length; ++i) { target.push(scale.getPointPositionForValue(i, value)); } return target; } function computeBoundary(source) { const scale = source.scale || {}; if (scale.getPointPositionForValue) { return computeCircularBoundary(source); } return computeLinearBoundary(source); } function findSegmentEnd(start, end, points) { for (;end > start; end--) { const point = points[end]; if (!isNaN(point.x) && !isNaN(point.y)) { break; } } return end; } function pointsFromSegments(boundary, line) { const {x = null, y = null} = boundary || {}; const linePoints = line.points; const points = []; line.segments.forEach(({start, end}) => { end = findSegmentEnd(start, end, linePoints); const first = linePoints[start]; const last = linePoints[end]; if (y !== null) { points.push({x: first.x, y}); points.push({x: last.x, y}); } else if (x !== null) { points.push({x, y: first.y}); points.push({x, y: last.y}); } }); return points; } function buildStackLine(source) { const {chart, scale, index, line} = source; const points = []; const segments = line.segments; const sourcePoints = line.points; const linesBelow = getLinesBelow(chart, index); linesBelow.push(createBoundaryLine({x: null, y: scale.bottom}, line)); for (let i = 0; i < segments.length; i++) { const segment = segments[i]; for (let j = segment.start; j <= segment.end; j++) { addPointsBelow(points, sourcePoints[j], linesBelow); } } return new LineElement({points, options: {}}); } const isLineAndNotInHideAnimation = (meta) => meta.type === 'line' && !meta.hidden; function getLinesBelow(chart, index) { const below = []; const metas = chart.getSortedVisibleDatasetMetas(); for (let i = 0; i < metas.length; i++) { const meta = metas[i]; if (meta.index === index) { break; } if (isLineAndNotInHideAnimation(meta)) { below.unshift(meta.dataset); } } return below; } function addPointsBelow(points, sourcePoint, linesBelow) { const postponed = []; for (let j = 0; j < linesBelow.length; j++) { const line = linesBelow[j]; const {first, last, point} = findPoint(line, sourcePoint, 'x'); if (!point || (first && last)) { continue; } if (first) { postponed.unshift(point); } else { points.push(point); if (!last) { break; } } } points.push(...postponed); } function findPoint(line, sourcePoint, property) { const point = line.interpolate(sourcePoint, property); if (!point) { return {}; } const pointValue = point[property]; const segments = line.segments; const linePoints = line.points; let first = false; let last = false; for (let i = 0; i < segments.length; i++) { const segment = segments[i]; const firstValue = linePoints[segment.start][property]; const lastValue = linePoints[segment.end][property]; if (pointValue >= firstValue && pointValue <= lastValue) { first = pointValue === firstValue; last = pointValue === lastValue; break; } } return {first, last, point}; } function getTarget(source) { const {chart, fill, line} = source; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) { return getLineByIndex(chart, fill); } if (fill === 'stack') { return buildStackLine(source); } if (fill === 'shape') { return true; } const boundary = computeBoundary(source); if (boundary instanceof simpleArc) { return boundary; } return createBoundaryLine(boundary, line); } function createBoundaryLine(boundary, line) { let points = []; let _loop = false; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(boundary)) { _loop = true; points = boundary; } else { points = pointsFromSegments(boundary, line); } return points.length ? new LineElement({ points, options: {tension: 0}, _loop, _fullLoop: _loop }) : null; } function resolveTarget(sources, index, propagate) { const source = sources[index]; let fill = source.fill; const visited = [index]; let target; if (!propagate) { return fill; } while (fill !== false && visited.indexOf(fill) === -1) { if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) { return fill; } target = sources[fill]; if (!target) { return false; } if (target.visible) { return fill; } visited.push(fill); fill = target.fill; } return false; } function _clip(ctx, target, clipY) { ctx.beginPath(); target.path(ctx); ctx.lineTo(target.last().x, clipY); ctx.lineTo(target.first().x, clipY); ctx.closePath(); ctx.clip(); } function getBounds(property, first, last, loop) { if (loop) { return; } let start = first[property]; let end = last[property]; if (property === 'angle') { start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.at)(start); end = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.at)(end); } return {property, start, end}; } function _getEdge(a, b, prop, fn) { if (a && b) { return fn(a[prop], b[prop]); } return a ? a[prop] : b ? b[prop] : 0; } function _segments(line, target, property) { const segments = line.segments; const points = line.points; const tpoints = target.points; const parts = []; for (const segment of segments) { let {start, end} = segment; end = findSegmentEnd(start, end, points); const bounds = getBounds(property, points[start], points[end], segment.loop); if (!target.segments) { parts.push({ source: segment, target: bounds, start: points[start], end: points[end] }); continue; } const targetSegments = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ai)(target, bounds); for (const tgt of targetSegments) { const subBounds = getBounds(property, tpoints[tgt.start], tpoints[tgt.end], tgt.loop); const fillSources = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.as)(segment, points, subBounds); for (const fillSource of fillSources) { parts.push({ source: fillSource, target: tgt, start: { [property]: _getEdge(bounds, subBounds, 'start', Math.max) }, end: { [property]: _getEdge(bounds, subBounds, 'end', Math.min) } }); } } } return parts; } function clipBounds(ctx, scale, bounds) { const {top, bottom} = scale.chart.chartArea; const {property, start, end} = bounds || {}; if (property === 'x') { ctx.beginPath(); ctx.rect(start, top, end - start, bottom - top); ctx.clip(); } } function interpolatedLineTo(ctx, target, point, property) { const interpolatedPoint = target.interpolate(point, property); if (interpolatedPoint) { ctx.lineTo(interpolatedPoint.x, interpolatedPoint.y); } } function _fill(ctx, cfg) { const {line, target, property, color, scale} = cfg; const segments = _segments(line, target, property); for (const {source: src, target: tgt, start, end} of segments) { const {style: {backgroundColor = color} = {}} = src; const notShape = target !== true; ctx.save(); ctx.fillStyle = backgroundColor; clipBounds(ctx, scale, notShape && getBounds(property, start, end)); ctx.beginPath(); const lineLoop = !!line.pathSegment(ctx, src); let loop; if (notShape) { if (lineLoop) { ctx.closePath(); } else { interpolatedLineTo(ctx, target, end, property); } const targetLoop = !!target.pathSegment(ctx, tgt, {move: lineLoop, reverse: true}); loop = lineLoop && targetLoop; if (!loop) { interpolatedLineTo(ctx, target, start, property); } } ctx.closePath(); ctx.fill(loop ? 'evenodd' : 'nonzero'); ctx.restore(); } } function doFill(ctx, cfg) { const {line, target, above, below, area, scale} = cfg; const property = line._loop ? 'angle' : cfg.axis; ctx.save(); if (property === 'x' && below !== above) { _clip(ctx, target, area.top); _fill(ctx, {line, target, color: above, scale, property}); ctx.restore(); ctx.save(); _clip(ctx, target, area.bottom); } _fill(ctx, {line, target, color: below, scale, property}); ctx.restore(); } function drawfill(ctx, source, area) { const target = getTarget(source); const {line, scale, axis} = source; const lineOpts = line.options; const fillOption = lineOpts.fill; const color = lineOpts.backgroundColor; const {above = color, below = color} = fillOption || {}; if (target && line.points.length) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.U)(ctx, area); doFill(ctx, {line, target, above, below, area, scale, axis}); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.W)(ctx); } } var plugin_filler = { id: 'filler', afterDatasetsUpdate(chart, _args, options) { const count = (chart.data.datasets || []).length; const sources = []; let meta, i, line, source; for (i = 0; i < count; ++i) { meta = chart.getDatasetMeta(i); line = meta.dataset; source = null; if (line && line.options && line instanceof LineElement) { source = { visible: chart.isDatasetVisible(i), index: i, fill: decodeFill(line, i, count), chart, axis: meta.controller.options.indexAxis, scale: meta.vScale, line, }; } meta.$filler = source; sources.push(source); } for (i = 0; i < count; ++i) { source = sources[i]; if (!source || source.fill === false) { continue; } source.fill = resolveTarget(sources, i, options.propagate); } }, beforeDraw(chart, _args, options) { const draw = options.drawTime === 'beforeDraw'; const metasets = chart.getSortedVisibleDatasetMetas(); const area = chart.chartArea; for (let i = metasets.length - 1; i >= 0; --i) { const source = metasets[i].$filler; if (!source) { continue; } source.line.updateControlPoints(area, source.axis); if (draw) { drawfill(chart.ctx, source, area); } } }, beforeDatasetsDraw(chart, _args, options) { if (options.drawTime !== 'beforeDatasetsDraw') { return; } const metasets = chart.getSortedVisibleDatasetMetas(); for (let i = metasets.length - 1; i >= 0; --i) { const source = metasets[i].$filler; if (source) { drawfill(chart.ctx, source, chart.chartArea); } } }, beforeDatasetDraw(chart, args, options) { const source = args.meta.$filler; if (!source || source.fill === false || options.drawTime !== 'beforeDatasetDraw') { return; } drawfill(chart.ctx, source, chart.chartArea); }, defaults: { propagate: true, drawTime: 'beforeDatasetDraw' } }; const getBoxSize = (labelOpts, fontSize) => { let {boxHeight = fontSize, boxWidth = fontSize} = labelOpts; if (labelOpts.usePointStyle) { boxHeight = Math.min(boxHeight, fontSize); boxWidth = Math.min(boxWidth, fontSize); } return { boxWidth, boxHeight, itemHeight: Math.max(fontSize, boxHeight) }; }; const itemsEqual = (a, b) => a !== null && b !== null && a.datasetIndex === b.datasetIndex && a.index === b.index; class Legend extends Element { constructor(config) { super(); this._added = false; this.legendHitBoxes = []; this._hoveredItem = null; this.doughnutMode = false; this.chart = config.chart; this.options = config.options; this.ctx = config.ctx; this.legendItems = undefined; this.columnSizes = undefined; this.lineWidths = undefined; this.maxHeight = undefined; this.maxWidth = undefined; this.top = undefined; this.bottom = undefined; this.left = undefined; this.right = undefined; this.height = undefined; this.width = undefined; this._margins = undefined; this.position = undefined; this.weight = undefined; this.fullSize = undefined; } update(maxWidth, maxHeight, margins) { const me = this; me.maxWidth = maxWidth; me.maxHeight = maxHeight; me._margins = margins; me.setDimensions(); me.buildLabels(); me.fit(); } setDimensions() { const me = this; if (me.isHorizontal()) { me.width = me.maxWidth; me.left = me._margins.left; me.right = me.width; } else { me.height = me.maxHeight; me.top = me._margins.top; me.bottom = me.height; } } buildLabels() { const me = this; const labelOpts = me.options.labels || {}; let legendItems = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(labelOpts.generateLabels, [me.chart], me) || []; if (labelOpts.filter) { legendItems = legendItems.filter((item) => labelOpts.filter(item, me.chart.data)); } if (labelOpts.sort) { legendItems = legendItems.sort((a, b) => labelOpts.sort(a, b, me.chart.data)); } if (me.options.reverse) { legendItems.reverse(); } me.legendItems = legendItems; } fit() { const me = this; const {options, ctx} = me; if (!options.display) { me.width = me.height = 0; return; } const labelOpts = options.labels; const labelFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(labelOpts.font); const fontSize = labelFont.size; const titleHeight = me._computeTitleHeight(); const {boxWidth, itemHeight} = getBoxSize(labelOpts, fontSize); let width, height; ctx.font = labelFont.string; if (me.isHorizontal()) { width = me.maxWidth; height = me._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10; } else { height = me.maxHeight; width = me._fitCols(titleHeight, fontSize, boxWidth, itemHeight) + 10; } me.width = Math.min(width, options.maxWidth || me.maxWidth); me.height = Math.min(height, options.maxHeight || me.maxHeight); } _fitRows(titleHeight, fontSize, boxWidth, itemHeight) { const me = this; const {ctx, maxWidth, options: {labels: {padding}}} = me; const hitboxes = me.legendHitBoxes = []; const lineWidths = me.lineWidths = [0]; const lineHeight = itemHeight + padding; let totalHeight = titleHeight; ctx.textAlign = 'left'; ctx.textBaseline = 'middle'; let row = -1; let top = -lineHeight; me.legendItems.forEach((legendItem, i) => { const itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) { totalHeight += lineHeight; lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0; top += lineHeight; row++; } hitboxes[i] = {left: 0, top, row, width: itemWidth, height: itemHeight}; lineWidths[lineWidths.length - 1] += itemWidth + padding; }); return totalHeight; } _fitCols(titleHeight, fontSize, boxWidth, itemHeight) { const me = this; const {ctx, maxHeight, options: {labels: {padding}}} = me; const hitboxes = me.legendHitBoxes = []; const columnSizes = me.columnSizes = []; const heightLimit = maxHeight - titleHeight; let totalWidth = padding; let currentColWidth = 0; let currentColHeight = 0; let left = 0; let col = 0; me.legendItems.forEach((legendItem, i) => { const itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; if (i > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) { totalWidth += currentColWidth + padding; columnSizes.push({width: currentColWidth, height: currentColHeight}); left += currentColWidth + padding; col++; currentColWidth = currentColHeight = 0; } hitboxes[i] = {left, top: currentColHeight, col, width: itemWidth, height: itemHeight}; currentColWidth = Math.max(currentColWidth, itemWidth); currentColHeight += itemHeight + padding; }); totalWidth += currentColWidth; columnSizes.push({width: currentColWidth, height: currentColHeight}); return totalWidth; } adjustHitBoxes() { const me = this; if (!me.options.display) { return; } const titleHeight = me._computeTitleHeight(); const {legendHitBoxes: hitboxes, options: {align, labels: {padding}, rtl}} = me; const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(rtl, me.left, me.width); if (this.isHorizontal()) { let row = 0; let left = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.left + padding, me.right - me.lineWidths[row]); for (const hitbox of hitboxes) { if (row !== hitbox.row) { row = hitbox.row; left = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.left + padding, me.right - me.lineWidths[row]); } hitbox.top += me.top + titleHeight + padding; hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width); left += hitbox.width + padding; } } else { let col = 0; let top = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.top + titleHeight + padding, me.bottom - me.columnSizes[col].height); for (const hitbox of hitboxes) { if (hitbox.col !== col) { col = hitbox.col; top = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.top + titleHeight + padding, me.bottom - me.columnSizes[col].height); } hitbox.top = top; hitbox.left += me.left + padding; hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width); top += hitbox.height + padding; } } } isHorizontal() { return this.options.position === 'top' || this.options.position === 'bottom'; } draw() { const me = this; if (me.options.display) { const ctx = me.ctx; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.U)(ctx, me); me._draw(); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.W)(ctx); } } _draw() { const me = this; const {options: opts, columnSizes, lineWidths, ctx} = me; const {align, labels: labelOpts} = opts; const defaultColor = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.color; const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(opts.rtl, me.left, me.width); const labelFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(labelOpts.font); const {color: fontColor, padding} = labelOpts; const fontSize = labelFont.size; const halfFontSize = fontSize / 2; let cursor; me.drawTitle(); ctx.textAlign = rtlHelper.textAlign('left'); ctx.textBaseline = 'middle'; ctx.lineWidth = 0.5; ctx.font = labelFont.string; const {boxWidth, boxHeight, itemHeight} = getBoxSize(labelOpts, fontSize); const drawLegendBox = function(x, y, legendItem) { if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) { return; } ctx.save(); const lineWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineWidth, 1); ctx.fillStyle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.fillStyle, defaultColor); ctx.lineCap = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineCap, 'butt'); ctx.lineDashOffset = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDashOffset, 0); ctx.lineJoin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineJoin, 'miter'); ctx.lineWidth = lineWidth; ctx.strokeStyle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.strokeStyle, defaultColor); ctx.setLineDash((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDash, [])); if (labelOpts.usePointStyle) { const drawOptions = { radius: boxWidth * Math.SQRT2 / 2, pointStyle: legendItem.pointStyle, rotation: legendItem.rotation, borderWidth: lineWidth }; const centerX = rtlHelper.xPlus(x, boxWidth / 2); const centerY = y + halfFontSize; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ao)(ctx, drawOptions, centerX, centerY); } else { const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0); const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth); const borderRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ar)(legendItem.borderRadius); ctx.beginPath(); if (Object.values(borderRadius).some(v => v !== 0)) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ap)(ctx, { x: xBoxLeft, y: yBoxTop, w: boxWidth, h: boxHeight, radius: borderRadius, }); } else { ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight); } ctx.fill(); if (lineWidth !== 0) { ctx.stroke(); } } ctx.restore(); }; const fillText = function(x, y, legendItem) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, legendItem.text, x, y + (itemHeight / 2), labelFont, { strikethrough: legendItem.hidden, textAlign: rtlHelper.textAlign(legendItem.textAlign) }); }; const isHorizontal = me.isHorizontal(); const titleHeight = this._computeTitleHeight(); if (isHorizontal) { cursor = { x: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.left + padding, me.right - lineWidths[0]), y: me.top + padding + titleHeight, line: 0 }; } else { cursor = { x: me.left + padding, y: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.top + titleHeight + padding, me.bottom - columnSizes[0].height), line: 0 }; } (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.av)(me.ctx, opts.textDirection); const lineHeight = itemHeight + padding; me.legendItems.forEach((legendItem, i) => { ctx.strokeStyle = legendItem.fontColor || fontColor; ctx.fillStyle = legendItem.fontColor || fontColor; const textWidth = ctx.measureText(legendItem.text).width; const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign)); const width = boxWidth + halfFontSize + textWidth; let x = cursor.x; let y = cursor.y; rtlHelper.setWidth(me.width); if (isHorizontal) { if (i > 0 && x + width + padding > me.right) { y = cursor.y += lineHeight; cursor.line++; x = cursor.x = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.left + padding, me.right - lineWidths[cursor.line]); } } else if (i > 0 && y + lineHeight > me.bottom) { x = cursor.x = x + columnSizes[cursor.line].width + padding; cursor.line++; y = cursor.y = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, me.top + titleHeight + padding, me.bottom - columnSizes[cursor.line].height); } const realX = rtlHelper.x(x); drawLegendBox(realX, y, legendItem); x = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : me.right, opts.rtl); fillText(rtlHelper.x(x), y, legendItem); if (isHorizontal) { cursor.x += width + padding; } else { cursor.y += lineHeight; } }); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ax)(me.ctx, opts.textDirection); } drawTitle() { const me = this; const opts = me.options; const titleOpts = opts.title; const titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(titleOpts.font); const titlePadding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(titleOpts.padding); if (!titleOpts.display) { return; } const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(opts.rtl, me.left, me.width); const ctx = me.ctx; const position = titleOpts.position; const halfFontSize = titleFont.size / 2; const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize; let y; let left = me.left; let maxWidth = me.width; if (this.isHorizontal()) { maxWidth = Math.max(...me.lineWidths); y = me.top + topPaddingPlusHalfFontSize; left = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(opts.align, left, me.right - maxWidth); } else { const maxHeight = me.columnSizes.reduce((acc, size) => Math.max(acc, size.height), 0); y = topPaddingPlusHalfFontSize + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(opts.align, me.top, me.bottom - maxHeight - opts.labels.padding - me._computeTitleHeight()); } const x = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(position, left, left + maxWidth); ctx.textAlign = rtlHelper.textAlign((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Y)(position)); ctx.textBaseline = 'middle'; ctx.strokeStyle = titleOpts.color; ctx.fillStyle = titleOpts.color; ctx.font = titleFont.string; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, titleOpts.text, x, y, titleFont); } _computeTitleHeight() { const titleOpts = this.options.title; const titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(titleOpts.font); const titlePadding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(titleOpts.padding); return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0; } _getLegendItemAt(x, y) { const me = this; let i, hitBox, lh; if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) { lh = me.legendHitBoxes; for (i = 0; i < lh.length; ++i) { hitBox = lh[i]; if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) { return me.legendItems[i]; } } } return null; } handleEvent(e) { const me = this; const opts = me.options; if (!isListened(e.type, opts)) { return; } const hoveredItem = me._getLegendItemAt(e.x, e.y); if (e.type === 'mousemove') { const previous = me._hoveredItem; const sameItem = itemsEqual(previous, hoveredItem); if (previous && !sameItem) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(opts.onLeave, [e, previous, me], me); } me._hoveredItem = hoveredItem; if (hoveredItem && !sameItem) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(opts.onHover, [e, hoveredItem, me], me); } } else if (hoveredItem) { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(opts.onClick, [e, hoveredItem, me], me); } } } function isListened(type, opts) { if (type === 'mousemove' && (opts.onHover || opts.onLeave)) { return true; } if (opts.onClick && (type === 'click' || type === 'mouseup')) { return true; } return false; } var plugin_legend = { id: 'legend', _element: Legend, start(chart, _args, options) { const legend = chart.legend = new Legend({ctx: chart.ctx, options, chart}); layouts.configure(chart, legend, options); layouts.addBox(chart, legend); }, stop(chart) { layouts.removeBox(chart, chart.legend); delete chart.legend; }, beforeUpdate(chart, _args, options) { const legend = chart.legend; layouts.configure(chart, legend, options); legend.options = options; }, afterUpdate(chart) { const legend = chart.legend; legend.buildLabels(); legend.adjustHitBoxes(); }, afterEvent(chart, args) { if (!args.replay) { chart.legend.handleEvent(args.event); } }, defaults: { display: true, position: 'top', align: 'center', fullSize: true, reverse: false, weight: 1000, onClick(e, legendItem, legend) { const index = legendItem.datasetIndex; const ci = legend.chart; if (ci.isDatasetVisible(index)) { ci.hide(index); legendItem.hidden = true; } else { ci.show(index); legendItem.hidden = false; } }, onHover: null, onLeave: null, labels: { color: (ctx) => ctx.chart.options.color, boxWidth: 40, padding: 10, generateLabels(chart) { const datasets = chart.data.datasets; const {labels: {usePointStyle, pointStyle, textAlign, color}} = chart.legend.options; return chart._getSortedDatasetMetas().map((meta) => { const style = meta.controller.getStyle(usePointStyle ? 0 : undefined); const borderWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(style.borderWidth); return { text: datasets[meta.index].label, fillStyle: style.backgroundColor, fontColor: color, hidden: !meta.visible, lineCap: style.borderCapStyle, lineDash: style.borderDash, lineDashOffset: style.borderDashOffset, lineJoin: style.borderJoinStyle, lineWidth: (borderWidth.width + borderWidth.height) / 4, strokeStyle: style.borderColor, pointStyle: pointStyle || style.pointStyle, rotation: style.rotation, textAlign: textAlign || style.textAlign, borderRadius: 0, datasetIndex: meta.index }; }, this); } }, title: { color: (ctx) => ctx.chart.options.color, display: false, position: 'center', text: '', } }, descriptors: { _scriptable: (name) => !name.startsWith('on'), labels: { _scriptable: (name) => !['generateLabels', 'filter', 'sort'].includes(name), } }, }; class Title extends Element { constructor(config) { super(); this.chart = config.chart; this.options = config.options; this.ctx = config.ctx; this._padding = undefined; this.top = undefined; this.bottom = undefined; this.left = undefined; this.right = undefined; this.width = undefined; this.height = undefined; this.position = undefined; this.weight = undefined; this.fullSize = undefined; } update(maxWidth, maxHeight) { const me = this; const opts = me.options; me.left = 0; me.top = 0; if (!opts.display) { me.width = me.height = me.right = me.bottom = 0; return; } me.width = me.right = maxWidth; me.height = me.bottom = maxHeight; const lineCount = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(opts.text) ? opts.text.length : 1; me._padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(opts.padding); const textSize = lineCount * (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(opts.font).lineHeight + me._padding.height; if (me.isHorizontal()) { me.height = textSize; } else { me.width = textSize; } } isHorizontal() { const pos = this.options.position; return pos === 'top' || pos === 'bottom'; } _drawArgs(offset) { const {top, left, bottom, right, options} = this; const align = options.align; let rotation = 0; let maxWidth, titleX, titleY; if (this.isHorizontal()) { titleX = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, left, right); titleY = top + offset; maxWidth = right - left; } else { if (options.position === 'left') { titleX = left + offset; titleY = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, bottom, top); rotation = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P * -0.5; } else { titleX = right - offset; titleY = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(align, top, bottom); rotation = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P * 0.5; } maxWidth = bottom - top; } return {titleX, titleY, maxWidth, rotation}; } draw() { const me = this; const ctx = me.ctx; const opts = me.options; if (!opts.display) { return; } const fontOpts = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(opts.font); const lineHeight = fontOpts.lineHeight; const offset = lineHeight / 2 + me._padding.top; const {titleX, titleY, maxWidth, rotation} = me._drawArgs(offset); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, opts.text, 0, 0, fontOpts, { color: opts.color, maxWidth, rotation, textAlign: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Y)(opts.align), textBaseline: 'middle', translation: [titleX, titleY], }); } } function createTitle(chart, titleOpts) { const title = new Title({ ctx: chart.ctx, options: titleOpts, chart }); layouts.configure(chart, title, titleOpts); layouts.addBox(chart, title); chart.titleBlock = title; } var plugin_title = { id: 'title', _element: Title, start(chart, _args, options) { createTitle(chart, options); }, stop(chart) { const titleBlock = chart.titleBlock; layouts.removeBox(chart, titleBlock); delete chart.titleBlock; }, beforeUpdate(chart, _args, options) { const title = chart.titleBlock; layouts.configure(chart, title, options); title.options = options; }, defaults: { align: 'center', display: false, font: { weight: 'bold', }, fullSize: true, padding: 10, position: 'top', text: '', weight: 2000 }, defaultRoutes: { color: 'color' }, descriptors: { _scriptable: true, _indexable: false, }, }; const map = new WeakMap(); var plugin_subtitle = { id: 'subtitle', start(chart, _args, options) { const title = new Title({ ctx: chart.ctx, options, chart }); layouts.configure(chart, title, options); layouts.addBox(chart, title); map.set(chart, title); }, stop(chart) { layouts.removeBox(chart, map.get(chart)); map.delete(chart); }, beforeUpdate(chart, _args, options) { const title = map.get(chart); layouts.configure(chart, title, options); title.options = options; }, defaults: { align: 'center', display: false, font: { weight: 'normal', }, fullSize: true, padding: 0, position: 'top', text: '', weight: 1500 }, defaultRoutes: { color: 'color' }, descriptors: { _scriptable: true, _indexable: false, }, }; const positioners = { average(items) { if (!items.length) { return false; } let i, len; let x = 0; let y = 0; let count = 0; for (i = 0, len = items.length; i < len; ++i) { const el = items[i].element; if (el && el.hasValue()) { const pos = el.tooltipPosition(); x += pos.x; y += pos.y; ++count; } } return { x: x / count, y: y / count }; }, nearest(items, eventPosition) { if (!items.length) { return false; } let x = eventPosition.x; let y = eventPosition.y; let minDistance = Number.POSITIVE_INFINITY; let i, len, nearestElement; for (i = 0, len = items.length; i < len; ++i) { const el = items[i].element; if (el && el.hasValue()) { const center = el.getCenterPoint(); const d = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.az)(eventPosition, center); if (d < minDistance) { minDistance = d; nearestElement = el; } } } if (nearestElement) { const tp = nearestElement.tooltipPosition(); x = tp.x; y = tp.y; } return { x, y }; } }; function pushOrConcat(base, toPush) { if (toPush) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(toPush)) { Array.prototype.push.apply(base, toPush); } else { base.push(toPush); } } return base; } function splitNewlines(str) { if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) { return str.split('\n'); } return str; } function createTooltipItem(chart, item) { const {element, datasetIndex, index} = item; const controller = chart.getDatasetMeta(datasetIndex).controller; const {label, value} = controller.getLabelAndValue(index); return { chart, label, parsed: controller.getParsed(index), raw: chart.data.datasets[datasetIndex].data[index], formattedValue: value, dataset: controller.getDataset(), dataIndex: index, datasetIndex, element }; } function getTooltipSize(tooltip, options) { const ctx = tooltip._chart.ctx; const {body, footer, title} = tooltip; const {boxWidth, boxHeight} = options; const bodyFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.bodyFont); const titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.titleFont); const footerFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.footerFont); const titleLineCount = title.length; const footerLineCount = footer.length; const bodyLineItemCount = body.length; const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(options.padding); let height = padding.height; let width = 0; let combinedBodyLength = body.reduce((count, bodyItem) => count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0); combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length; if (titleLineCount) { height += titleLineCount * titleFont.lineHeight + (titleLineCount - 1) * options.titleSpacing + options.titleMarginBottom; } if (combinedBodyLength) { const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight; height += bodyLineItemCount * bodyLineHeight + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight + (combinedBodyLength - 1) * options.bodySpacing; } if (footerLineCount) { height += options.footerMarginTop + footerLineCount * footerFont.lineHeight + (footerLineCount - 1) * options.footerSpacing; } let widthPadding = 0; const maxLineWidth = function(line) { width = Math.max(width, ctx.measureText(line).width + widthPadding); }; ctx.save(); ctx.font = titleFont.string; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(tooltip.title, maxLineWidth); ctx.font = bodyFont.string; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth); widthPadding = options.displayColors ? (boxWidth + 2) : 0; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(body, (bodyItem) => { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(bodyItem.before, maxLineWidth); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(bodyItem.lines, maxLineWidth); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(bodyItem.after, maxLineWidth); }); widthPadding = 0; ctx.font = footerFont.string; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(tooltip.footer, maxLineWidth); ctx.restore(); width += padding.width; return {width, height}; } function determineYAlign(chart, size) { const {y, height} = size; if (y < height / 2) { return 'top'; } else if (y > (chart.height - height / 2)) { return 'bottom'; } return 'center'; } function doesNotFitWithAlign(xAlign, chart, options, size) { const {x, width} = size; const caret = options.caretSize + options.caretPadding; if (xAlign === 'left' && x + width + caret > chart.width) { return true; } if (xAlign === 'right' && x - width - caret < 0) { return true; } } function determineXAlign(chart, options, size, yAlign) { const {x, width} = size; const {width: chartWidth, chartArea: {left, right}} = chart; let xAlign = 'center'; if (yAlign === 'center') { xAlign = x <= (left + right) / 2 ? 'left' : 'right'; } else if (x <= width / 2) { xAlign = 'left'; } else if (x >= chartWidth - width / 2) { xAlign = 'right'; } if (doesNotFitWithAlign(xAlign, chart, options, size)) { xAlign = 'center'; } return xAlign; } function determineAlignment(chart, options, size) { const yAlign = options.yAlign || determineYAlign(chart, size); return { xAlign: options.xAlign || determineXAlign(chart, options, size, yAlign), yAlign }; } function alignX(size, xAlign) { let {x, width} = size; if (xAlign === 'right') { x -= width; } else if (xAlign === 'center') { x -= (width / 2); } return x; } function alignY(size, yAlign, paddingAndSize) { let {y, height} = size; if (yAlign === 'top') { y += paddingAndSize; } else if (yAlign === 'bottom') { y -= height + paddingAndSize; } else { y -= (height / 2); } return y; } function getBackgroundPoint(options, size, alignment, chart) { const {caretSize, caretPadding, cornerRadius} = options; const {xAlign, yAlign} = alignment; const paddingAndSize = caretSize + caretPadding; const radiusAndPadding = cornerRadius + caretPadding; let x = alignX(size, xAlign); const y = alignY(size, yAlign, paddingAndSize); if (yAlign === 'center') { if (xAlign === 'left') { x += paddingAndSize; } else if (xAlign === 'right') { x -= paddingAndSize; } } else if (xAlign === 'left') { x -= radiusAndPadding; } else if (xAlign === 'right') { x += radiusAndPadding; } return { x: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(x, 0, chart.width - size.width), y: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(y, 0, chart.height - size.height) }; } function getAlignedX(tooltip, align, options) { const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(options.padding); return align === 'center' ? tooltip.x + tooltip.width / 2 : align === 'right' ? tooltip.x + tooltip.width - padding.right : tooltip.x + padding.left; } function getBeforeAfterBodyLines(callback) { return pushOrConcat([], splitNewlines(callback)); } function createTooltipContext(parent, tooltip, tooltipItems) { return Object.assign(Object.create(parent), { tooltip, tooltipItems, type: 'tooltip' }); } function overrideCallbacks(callbacks, context) { const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks; return override ? callbacks.override(override) : callbacks; } class Tooltip extends Element { constructor(config) { super(); this.opacity = 0; this._active = []; this._chart = config._chart; this._eventPosition = undefined; this._size = undefined; this._cachedAnimations = undefined; this._tooltipItems = []; this.$animations = undefined; this.$context = undefined; this.options = config.options; this.dataPoints = undefined; this.title = undefined; this.beforeBody = undefined; this.body = undefined; this.afterBody = undefined; this.footer = undefined; this.xAlign = undefined; this.yAlign = undefined; this.x = undefined; this.y = undefined; this.height = undefined; this.width = undefined; this.caretX = undefined; this.caretY = undefined; this.labelColors = undefined; this.labelPointStyles = undefined; this.labelTextColors = undefined; } initialize(options) { this.options = options; this._cachedAnimations = undefined; this.$context = undefined; } _resolveAnimations() { const me = this; const cached = me._cachedAnimations; if (cached) { return cached; } const chart = me._chart; const options = me.options.setContext(me.getContext()); const opts = options.enabled && chart.options.animation && options.animations; const animations = new Animations(me._chart, opts); if (opts._cacheable) { me._cachedAnimations = Object.freeze(animations); } return animations; } getContext() { const me = this; return me.$context || (me.$context = createTooltipContext(me._chart.getContext(), me, me._tooltipItems)); } getTitle(context, options) { const me = this; const {callbacks} = options; const beforeTitle = callbacks.beforeTitle.apply(me, [context]); const title = callbacks.title.apply(me, [context]); const afterTitle = callbacks.afterTitle.apply(me, [context]); let lines = []; lines = pushOrConcat(lines, splitNewlines(beforeTitle)); lines = pushOrConcat(lines, splitNewlines(title)); lines = pushOrConcat(lines, splitNewlines(afterTitle)); return lines; } getBeforeBody(tooltipItems, options) { return getBeforeAfterBodyLines(options.callbacks.beforeBody.apply(this, [tooltipItems])); } getBody(tooltipItems, options) { const me = this; const {callbacks} = options; const bodyItems = []; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(tooltipItems, (context) => { const bodyItem = { before: [], lines: [], after: [] }; const scoped = overrideCallbacks(callbacks, context); pushOrConcat(bodyItem.before, splitNewlines(scoped.beforeLabel.call(me, context))); pushOrConcat(bodyItem.lines, scoped.label.call(me, context)); pushOrConcat(bodyItem.after, splitNewlines(scoped.afterLabel.call(me, context))); bodyItems.push(bodyItem); }); return bodyItems; } getAfterBody(tooltipItems, options) { return getBeforeAfterBodyLines(options.callbacks.afterBody.apply(this, [tooltipItems])); } getFooter(tooltipItems, options) { const me = this; const {callbacks} = options; const beforeFooter = callbacks.beforeFooter.apply(me, [tooltipItems]); const footer = callbacks.footer.apply(me, [tooltipItems]); const afterFooter = callbacks.afterFooter.apply(me, [tooltipItems]); let lines = []; lines = pushOrConcat(lines, splitNewlines(beforeFooter)); lines = pushOrConcat(lines, splitNewlines(footer)); lines = pushOrConcat(lines, splitNewlines(afterFooter)); return lines; } _createItems(options) { const me = this; const active = me._active; const data = me._chart.data; const labelColors = []; const labelPointStyles = []; const labelTextColors = []; let tooltipItems = []; let i, len; for (i = 0, len = active.length; i < len; ++i) { tooltipItems.push(createTooltipItem(me._chart, active[i])); } if (options.filter) { tooltipItems = tooltipItems.filter((element, index, array) => options.filter(element, index, array, data)); } if (options.itemSort) { tooltipItems = tooltipItems.sort((a, b) => options.itemSort(a, b, data)); } (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(tooltipItems, (context) => { const scoped = overrideCallbacks(options.callbacks, context); labelColors.push(scoped.labelColor.call(me, context)); labelPointStyles.push(scoped.labelPointStyle.call(me, context)); labelTextColors.push(scoped.labelTextColor.call(me, context)); }); me.labelColors = labelColors; me.labelPointStyles = labelPointStyles; me.labelTextColors = labelTextColors; me.dataPoints = tooltipItems; return tooltipItems; } update(changed, replay) { const me = this; const options = me.options.setContext(me.getContext()); const active = me._active; let properties; let tooltipItems = []; if (!active.length) { if (me.opacity !== 0) { properties = { opacity: 0 }; } } else { const position = positioners[options.position].call(me, active, me._eventPosition); tooltipItems = me._createItems(options); me.title = me.getTitle(tooltipItems, options); me.beforeBody = me.getBeforeBody(tooltipItems, options); me.body = me.getBody(tooltipItems, options); me.afterBody = me.getAfterBody(tooltipItems, options); me.footer = me.getFooter(tooltipItems, options); const size = me._size = getTooltipSize(me, options); const positionAndSize = Object.assign({}, position, size); const alignment = determineAlignment(me._chart, options, positionAndSize); const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, me._chart); me.xAlign = alignment.xAlign; me.yAlign = alignment.yAlign; properties = { opacity: 1, x: backgroundPoint.x, y: backgroundPoint.y, width: size.width, height: size.height, caretX: position.x, caretY: position.y }; } me._tooltipItems = tooltipItems; me.$context = undefined; if (properties) { me._resolveAnimations().update(me, properties); } if (changed && options.external) { options.external.call(me, {chart: me._chart, tooltip: me, replay}); } } drawCaret(tooltipPoint, ctx, size, options) { const caretPosition = this.getCaretPosition(tooltipPoint, size, options); ctx.lineTo(caretPosition.x1, caretPosition.y1); ctx.lineTo(caretPosition.x2, caretPosition.y2); ctx.lineTo(caretPosition.x3, caretPosition.y3); } getCaretPosition(tooltipPoint, size, options) { const {xAlign, yAlign} = this; const {cornerRadius, caretSize} = options; const {x: ptX, y: ptY} = tooltipPoint; const {width, height} = size; let x1, x2, x3, y1, y2, y3; if (yAlign === 'center') { y2 = ptY + (height / 2); if (xAlign === 'left') { x1 = ptX; x2 = x1 - caretSize; y1 = y2 + caretSize; y3 = y2 - caretSize; } else { x1 = ptX + width; x2 = x1 + caretSize; y1 = y2 - caretSize; y3 = y2 + caretSize; } x3 = x1; } else { if (xAlign === 'left') { x2 = ptX + cornerRadius + (caretSize); } else if (xAlign === 'right') { x2 = ptX + width - cornerRadius - caretSize; } else { x2 = this.caretX; } if (yAlign === 'top') { y1 = ptY; y2 = y1 - caretSize; x1 = x2 - caretSize; x3 = x2 + caretSize; } else { y1 = ptY + height; y2 = y1 + caretSize; x1 = x2 + caretSize; x3 = x2 - caretSize; } y3 = y1; } return {x1, x2, x3, y1, y2, y3}; } drawTitle(pt, ctx, options) { const me = this; const title = me.title; const length = title.length; let titleFont, titleSpacing, i; if (length) { const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(options.rtl, me.x, me.width); pt.x = getAlignedX(me, options.titleAlign, options); ctx.textAlign = rtlHelper.textAlign(options.titleAlign); ctx.textBaseline = 'middle'; titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.titleFont); titleSpacing = options.titleSpacing; ctx.fillStyle = options.titleColor; ctx.font = titleFont.string; for (i = 0; i < length; ++i) { ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2); pt.y += titleFont.lineHeight + titleSpacing; if (i + 1 === length) { pt.y += options.titleMarginBottom - titleSpacing; } } } } _drawColorBox(ctx, pt, i, rtlHelper, options) { const me = this; const labelColors = me.labelColors[i]; const labelPointStyle = me.labelPointStyles[i]; const {boxHeight, boxWidth} = options; const bodyFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.bodyFont); const colorX = getAlignedX(me, 'left', options); const rtlColorX = rtlHelper.x(colorX); const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0; const colorY = pt.y + yOffSet; if (options.usePointStyle) { const drawOptions = { radius: Math.min(boxWidth, boxHeight) / 2, pointStyle: labelPointStyle.pointStyle, rotation: labelPointStyle.rotation, borderWidth: 1 }; const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2; const centerY = colorY + boxHeight / 2; ctx.strokeStyle = options.multiKeyBackground; ctx.fillStyle = options.multiKeyBackground; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ao)(ctx, drawOptions, centerX, centerY); ctx.strokeStyle = labelColors.borderColor; ctx.fillStyle = labelColors.backgroundColor; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ao)(ctx, drawOptions, centerX, centerY); } else { ctx.lineWidth = labelColors.borderWidth || 1; ctx.strokeStyle = labelColors.borderColor; ctx.setLineDash(labelColors.borderDash || []); ctx.lineDashOffset = labelColors.borderDashOffset || 0; const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth); const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2); const borderRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ar)(labelColors.borderRadius); if (Object.values(borderRadius).some(v => v !== 0)) { ctx.beginPath(); ctx.fillStyle = options.multiKeyBackground; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ap)(ctx, { x: outerX, y: colorY, w: boxWidth, h: boxHeight, radius: borderRadius, }); ctx.fill(); ctx.stroke(); ctx.fillStyle = labelColors.backgroundColor; ctx.beginPath(); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ap)(ctx, { x: innerX, y: colorY + 1, w: boxWidth - 2, h: boxHeight - 2, radius: borderRadius, }); ctx.fill(); } else { ctx.fillStyle = options.multiKeyBackground; ctx.fillRect(outerX, colorY, boxWidth, boxHeight); ctx.strokeRect(outerX, colorY, boxWidth, boxHeight); ctx.fillStyle = labelColors.backgroundColor; ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2); } } ctx.fillStyle = me.labelTextColors[i]; } drawBody(pt, ctx, options) { const me = this; const {body} = me; const {bodySpacing, bodyAlign, displayColors, boxHeight, boxWidth} = options; const bodyFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.bodyFont); let bodyLineHeight = bodyFont.lineHeight; let xLinePadding = 0; const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(options.rtl, me.x, me.width); const fillLineOfText = function(line) { ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2); pt.y += bodyLineHeight + bodySpacing; }; const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign); let bodyItem, textColor, lines, i, j, ilen, jlen; ctx.textAlign = bodyAlign; ctx.textBaseline = 'middle'; ctx.font = bodyFont.string; pt.x = getAlignedX(me, bodyAlignForCalculation, options); ctx.fillStyle = options.bodyColor; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me.beforeBody, fillLineOfText); xLinePadding = displayColors && bodyAlignForCalculation !== 'right' ? bodyAlign === 'center' ? (boxWidth / 2 + 1) : (boxWidth + 2) : 0; for (i = 0, ilen = body.length; i < ilen; ++i) { bodyItem = body[i]; textColor = me.labelTextColors[i]; ctx.fillStyle = textColor; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(bodyItem.before, fillLineOfText); lines = bodyItem.lines; if (displayColors && lines.length) { me._drawColorBox(ctx, pt, i, rtlHelper, options); bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight); } for (j = 0, jlen = lines.length; j < jlen; ++j) { fillLineOfText(lines[j]); bodyLineHeight = bodyFont.lineHeight; } (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(bodyItem.after, fillLineOfText); } xLinePadding = 0; bodyLineHeight = bodyFont.lineHeight; (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(me.afterBody, fillLineOfText); pt.y -= bodySpacing; } drawFooter(pt, ctx, options) { const me = this; const footer = me.footer; const length = footer.length; let footerFont, i; if (length) { const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(options.rtl, me.x, me.width); pt.x = getAlignedX(me, options.footerAlign, options); pt.y += options.footerMarginTop; ctx.textAlign = rtlHelper.textAlign(options.footerAlign); ctx.textBaseline = 'middle'; footerFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(options.footerFont); ctx.fillStyle = options.footerColor; ctx.font = footerFont.string; for (i = 0; i < length; ++i) { ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2); pt.y += footerFont.lineHeight + options.footerSpacing; } } } drawBackground(pt, ctx, tooltipSize, options) { const {xAlign, yAlign} = this; const {x, y} = pt; const {width, height} = tooltipSize; const radius = options.cornerRadius; ctx.fillStyle = options.backgroundColor; ctx.strokeStyle = options.borderColor; ctx.lineWidth = options.borderWidth; ctx.beginPath(); ctx.moveTo(x + radius, y); if (yAlign === 'top') { this.drawCaret(pt, ctx, tooltipSize, options); } ctx.lineTo(x + width - radius, y); ctx.quadraticCurveTo(x + width, y, x + width, y + radius); if (yAlign === 'center' && xAlign === 'right') { this.drawCaret(pt, ctx, tooltipSize, options); } ctx.lineTo(x + width, y + height - radius); ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); if (yAlign === 'bottom') { this.drawCaret(pt, ctx, tooltipSize, options); } ctx.lineTo(x + radius, y + height); ctx.quadraticCurveTo(x, y + height, x, y + height - radius); if (yAlign === 'center' && xAlign === 'left') { this.drawCaret(pt, ctx, tooltipSize, options); } ctx.lineTo(x, y + radius); ctx.quadraticCurveTo(x, y, x + radius, y); ctx.closePath(); ctx.fill(); if (options.borderWidth > 0) { ctx.stroke(); } } _updateAnimationTarget(options) { const me = this; const chart = me._chart; const anims = me.$animations; const animX = anims && anims.x; const animY = anims && anims.y; if (animX || animY) { const position = positioners[options.position].call(me, me._active, me._eventPosition); if (!position) { return; } const size = me._size = getTooltipSize(me, options); const positionAndSize = Object.assign({}, position, me._size); const alignment = determineAlignment(chart, options, positionAndSize); const point = getBackgroundPoint(options, positionAndSize, alignment, chart); if (animX._to !== point.x || animY._to !== point.y) { me.xAlign = alignment.xAlign; me.yAlign = alignment.yAlign; me.width = size.width; me.height = size.height; me.caretX = position.x; me.caretY = position.y; me._resolveAnimations().update(me, point); } } } draw(ctx) { const me = this; const options = me.options.setContext(me.getContext()); let opacity = me.opacity; if (!opacity) { return; } me._updateAnimationTarget(options); const tooltipSize = { width: me.width, height: me.height }; const pt = { x: me.x, y: me.y }; opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity; const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(options.padding); const hasTooltipContent = me.title.length || me.beforeBody.length || me.body.length || me.afterBody.length || me.footer.length; if (options.enabled && hasTooltipContent) { ctx.save(); ctx.globalAlpha = opacity; me.drawBackground(pt, ctx, tooltipSize, options); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.av)(ctx, options.textDirection); pt.y += padding.top; me.drawTitle(pt, ctx, options); me.drawBody(pt, ctx, options); me.drawFooter(pt, ctx, options); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ax)(ctx, options.textDirection); ctx.restore(); } } getActiveElements() { return this._active || []; } setActiveElements(activeElements, eventPosition) { const me = this; const lastActive = me._active; const active = activeElements.map(({datasetIndex, index}) => { const meta = me._chart.getDatasetMeta(datasetIndex); if (!meta) { throw new Error('Cannot find a dataset at index ' + datasetIndex); } return { datasetIndex, element: meta.data[index], index, }; }); const changed = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ad)(lastActive, active); const positionChanged = me._positionChanged(active, eventPosition); if (changed || positionChanged) { me._active = active; me._eventPosition = eventPosition; me.update(true); } } handleEvent(e, replay) { const me = this; const options = me.options; const lastActive = me._active || []; let changed = false; let active = []; if (e.type !== 'mouseout') { active = me._chart.getElementsAtEventForMode(e, options.mode, options, replay); if (options.reverse) { active.reverse(); } } const positionChanged = me._positionChanged(active, e); changed = replay || !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ad)(active, lastActive) || positionChanged; if (changed) { me._active = active; if (options.enabled || options.external) { me._eventPosition = { x: e.x, y: e.y }; me.update(true, replay); } } return changed; } _positionChanged(active, e) { const {caretX, caretY, options} = this; const position = positioners[options.position].call(this, active, e); return position !== false && (caretX !== position.x || caretY !== position.y); } } Tooltip.positioners = positioners; var plugin_tooltip = { id: 'tooltip', _element: Tooltip, positioners, afterInit(chart, _args, options) { if (options) { chart.tooltip = new Tooltip({_chart: chart, options}); } }, beforeUpdate(chart, _args, options) { if (chart.tooltip) { chart.tooltip.initialize(options); } }, reset(chart, _args, options) { if (chart.tooltip) { chart.tooltip.initialize(options); } }, afterDraw(chart) { const tooltip = chart.tooltip; const args = { tooltip }; if (chart.notifyPlugins('beforeTooltipDraw', args) === false) { return; } if (tooltip) { tooltip.draw(chart.ctx); } chart.notifyPlugins('afterTooltipDraw', args); }, afterEvent(chart, args) { if (chart.tooltip) { const useFinalPosition = args.replay; if (chart.tooltip.handleEvent(args.event, useFinalPosition)) { args.changed = true; } } }, defaults: { enabled: true, external: null, position: 'average', backgroundColor: 'rgba(0,0,0,0.8)', titleColor: '#fff', titleFont: { weight: 'bold', }, titleSpacing: 2, titleMarginBottom: 6, titleAlign: 'left', bodyColor: '#fff', bodySpacing: 2, bodyFont: { }, bodyAlign: 'left', footerColor: '#fff', footerSpacing: 2, footerMarginTop: 6, footerFont: { weight: 'bold', }, footerAlign: 'left', padding: 6, caretPadding: 2, caretSize: 5, cornerRadius: 6, boxHeight: (ctx, opts) => opts.bodyFont.size, boxWidth: (ctx, opts) => opts.bodyFont.size, multiKeyBackground: '#fff', displayColors: true, borderColor: 'rgba(0,0,0,0)', borderWidth: 0, animation: { duration: 400, easing: 'easeOutQuart', }, animations: { numbers: { type: 'number', properties: ['x', 'y', 'width', 'height', 'caretX', 'caretY'], }, opacity: { easing: 'linear', duration: 200 } }, callbacks: { beforeTitle: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, title(tooltipItems) { if (tooltipItems.length > 0) { const item = tooltipItems[0]; const labels = item.chart.data.labels; const labelCount = labels ? labels.length : 0; if (this && this.options && this.options.mode === 'dataset') { return item.dataset.label || ''; } else if (item.label) { return item.label; } else if (labelCount > 0 && item.dataIndex < labelCount) { return labels[item.dataIndex]; } } return ''; }, afterTitle: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, beforeBody: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, beforeLabel: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, label(tooltipItem) { if (this && this.options && this.options.mode === 'dataset') { return tooltipItem.label + ': ' + tooltipItem.formattedValue || tooltipItem.formattedValue; } let label = tooltipItem.dataset.label || ''; if (label) { label += ': '; } const value = tooltipItem.formattedValue; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(value)) { label += value; } return label; }, labelColor(tooltipItem) { const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex); const options = meta.controller.getStyle(tooltipItem.dataIndex); return { borderColor: options.borderColor, backgroundColor: options.backgroundColor, borderWidth: options.borderWidth, borderDash: options.borderDash, borderDashOffset: options.borderDashOffset, borderRadius: 0, }; }, labelTextColor() { return this.options.bodyColor; }, labelPointStyle(tooltipItem) { const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex); const options = meta.controller.getStyle(tooltipItem.dataIndex); return { pointStyle: options.pointStyle, rotation: options.rotation, }; }, afterLabel: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, afterBody: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, beforeFooter: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, footer: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay, afterFooter: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay } }, defaultRoutes: { bodyFont: 'font', footerFont: 'font', titleFont: 'font' }, descriptors: { _scriptable: (name) => name !== 'filter' && name !== 'itemSort' && name !== 'external', _indexable: false, callbacks: { _scriptable: false, _indexable: false, }, animation: { _fallback: false }, animations: { _fallback: 'animation' } }, additionalOptionScopes: ['interaction'] }; var plugins = /*#__PURE__*/Object.freeze({ __proto__: null, Decimation: plugin_decimation, Filler: plugin_filler, Legend: plugin_legend, SubTitle: plugin_subtitle, Title: plugin_title, Tooltip: plugin_tooltip }); const addIfString = (labels, raw, index) => typeof raw === 'string' ? labels.push(raw) - 1 : isNaN(raw) ? null : index; function findOrAddLabel(labels, raw, index) { const first = labels.indexOf(raw); if (first === -1) { return addIfString(labels, raw, index); } const last = labels.lastIndexOf(raw); return first !== last ? index : first; } const validIndex = (index, max) => index === null ? null : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(Math.round(index), 0, max); class CategoryScale extends Scale { constructor(cfg) { super(cfg); this._startValue = undefined; this._valueRange = 0; } parse(raw, index) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(raw)) { return null; } const labels = this.getLabels(); index = isFinite(index) && labels[index] === raw ? index : findOrAddLabel(labels, raw, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(index, raw)); return validIndex(index, labels.length - 1); } determineDataLimits() { const me = this; const {minDefined, maxDefined} = me.getUserBounds(); let {min, max} = me.getMinMax(true); if (me.options.bounds === 'ticks') { if (!minDefined) { min = 0; } if (!maxDefined) { max = me.getLabels().length - 1; } } me.min = min; me.max = max; } buildTicks() { const me = this; const min = me.min; const max = me.max; const offset = me.options.offset; const ticks = []; let labels = me.getLabels(); labels = (min === 0 && max === labels.length - 1) ? labels : labels.slice(min, max + 1); me._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1); me._startValue = me.min - (offset ? 0.5 : 0); for (let value = min; value <= max; value++) { ticks.push({value}); } return ticks; } getLabelForValue(value) { const me = this; const labels = me.getLabels(); if (value >= 0 && value < labels.length) { return labels[value]; } return value; } configure() { const me = this; super.configure(); if (!me.isHorizontal()) { me._reversePixels = !me._reversePixels; } } getPixelForValue(value) { const me = this; if (typeof value !== 'number') { value = me.parse(value); } return value === null ? NaN : me.getPixelForDecimal((value - me._startValue) / me._valueRange); } getPixelForTick(index) { const me = this; const ticks = me.ticks; if (index < 0 || index > ticks.length - 1) { return null; } return me.getPixelForValue(ticks[index].value); } getValueForPixel(pixel) { const me = this; return Math.round(me._startValue + me.getDecimalForPixel(pixel) * me._valueRange); } getBasePixel() { return this.bottom; } } CategoryScale.id = 'category'; CategoryScale.defaults = { ticks: { callback: CategoryScale.prototype.getLabelForValue } }; function generateTicks$1(generationOptions, dataRange) { const ticks = []; const MIN_SPACING = 1e-14; const {bounds, step, min, max, precision, count, maxTicks, maxDigits, includeBounds} = generationOptions; const unit = step || 1; const maxSpaces = maxTicks - 1; const {min: rmin, max: rmax} = dataRange; const minDefined = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(min); const maxDefined = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(max); const countDefined = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(count); const minSpacing = (rmax - rmin) / (maxDigits + 1); let spacing = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aB)((rmax - rmin) / maxSpaces / unit) * unit; let factor, niceMin, niceMax, numSpaces; if (spacing < MIN_SPACING && !minDefined && !maxDefined) { return [{value: rmin}, {value: rmax}]; } numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing); if (numSpaces > maxSpaces) { spacing = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aB)(numSpaces * spacing / maxSpaces / unit) * unit; } if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(precision)) { factor = Math.pow(10, precision); spacing = Math.ceil(spacing * factor) / factor; } if (bounds === 'ticks') { niceMin = Math.floor(rmin / spacing) * spacing; niceMax = Math.ceil(rmax / spacing) * spacing; } else { niceMin = rmin; niceMax = rmax; } if (minDefined && maxDefined && step && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aC)((max - min) / step, spacing / 1000)) { numSpaces = Math.round(Math.min((max - min) / spacing, maxTicks)); spacing = (max - min) / numSpaces; niceMin = min; niceMax = max; } else if (countDefined) { niceMin = minDefined ? min : niceMin; niceMax = maxDefined ? max : niceMax; numSpaces = count - 1; spacing = (niceMax - niceMin) / numSpaces; } else { numSpaces = (niceMax - niceMin) / spacing; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aD)(numSpaces, Math.round(numSpaces), spacing / 1000)) { numSpaces = Math.round(numSpaces); } else { numSpaces = Math.ceil(numSpaces); } } const decimalPlaces = Math.max( (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aE)(spacing), (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aE)(niceMin) ); factor = Math.pow(10, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(precision) ? decimalPlaces : precision); niceMin = Math.round(niceMin * factor) / factor; niceMax = Math.round(niceMax * factor) / factor; let j = 0; if (minDefined) { if (includeBounds && niceMin !== min) { ticks.push({value: min}); if (niceMin < min) { j++; } if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aD)(Math.round((niceMin + j * spacing) * factor) / factor, min, relativeLabelSize(min, minSpacing, generationOptions))) { j++; } } else if (niceMin < min) { j++; } } for (; j < numSpaces; ++j) { ticks.push({value: Math.round((niceMin + j * spacing) * factor) / factor}); } if (maxDefined && includeBounds && niceMax !== max) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aD)(ticks[ticks.length - 1].value, max, relativeLabelSize(max, minSpacing, generationOptions))) { ticks[ticks.length - 1].value = max; } else { ticks.push({value: max}); } } else if (!maxDefined || niceMax === max) { ticks.push({value: niceMax}); } return ticks; } function relativeLabelSize(value, minSpacing, {horizontal, minRotation}) { const rad = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(minRotation); const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 0.001; const length = 0.75 * minSpacing * ('' + value).length; return Math.min(minSpacing / ratio, length); } class LinearScaleBase extends Scale { constructor(cfg) { super(cfg); this.start = undefined; this.end = undefined; this._startValue = undefined; this._endValue = undefined; this._valueRange = 0; } parse(raw, index) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(raw)) { return null; } if ((typeof raw === 'number' || raw instanceof Number) && !isFinite(+raw)) { return null; } return +raw; } handleTickRangeOptions() { const me = this; const {beginAtZero} = me.options; const {minDefined, maxDefined} = me.getUserBounds(); let {min, max} = me; const setMin = v => (min = minDefined ? min : v); const setMax = v => (max = maxDefined ? max : v); if (beginAtZero) { const minSign = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(min); const maxSign = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(max); if (minSign < 0 && maxSign < 0) { setMax(0); } else if (minSign > 0 && maxSign > 0) { setMin(0); } } if (min === max) { let offset = 1; if (max >= Number.MAX_SAFE_INTEGER || min <= Number.MIN_SAFE_INTEGER) { offset = Math.abs(max * 0.05); } setMax(max + offset); if (!beginAtZero) { setMin(min - offset); } } me.min = min; me.max = max; } getTickLimit() { const me = this; const tickOpts = me.options.ticks; let {maxTicksLimit, stepSize} = tickOpts; let maxTicks; if (stepSize) { maxTicks = Math.ceil(me.max / stepSize) - Math.floor(me.min / stepSize) + 1; } else { maxTicks = me.computeTickLimit(); maxTicksLimit = maxTicksLimit || 11; } if (maxTicksLimit) { maxTicks = Math.min(maxTicksLimit, maxTicks); } return maxTicks; } computeTickLimit() { return Number.POSITIVE_INFINITY; } buildTicks() { const me = this; const opts = me.options; const tickOpts = opts.ticks; let maxTicks = me.getTickLimit(); maxTicks = Math.max(2, maxTicks); const numericGeneratorOptions = { maxTicks, bounds: opts.bounds, min: opts.min, max: opts.max, precision: tickOpts.precision, step: tickOpts.stepSize, count: tickOpts.count, maxDigits: me._maxDigits(), horizontal: me.isHorizontal(), minRotation: tickOpts.minRotation || 0, includeBounds: tickOpts.includeBounds !== false }; const dataRange = me._range || me; const ticks = generateTicks$1(numericGeneratorOptions, dataRange); if (opts.bounds === 'ticks') { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aA)(ticks, me, 'value'); } if (opts.reverse) { ticks.reverse(); me.start = me.max; me.end = me.min; } else { me.start = me.min; me.end = me.max; } return ticks; } configure() { const me = this; const ticks = me.ticks; let start = me.min; let end = me.max; super.configure(); if (me.options.offset && ticks.length) { const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2; start -= offset; end += offset; } me._startValue = start; me._endValue = end; me._valueRange = end - start; } getLabelForValue(value) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.n)(value, this.chart.options.locale); } } class LinearScale extends LinearScaleBase { determineDataLimits() { const me = this; const {min, max} = me.getMinMax(true); me.min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? min : 0; me.max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? max : 1; me.handleTickRangeOptions(); } computeTickLimit() { const me = this; const horizontal = me.isHorizontal(); const length = horizontal ? me.width : me.height; const minRotation = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(me.options.ticks.minRotation); const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 0.001; const tickFont = me._resolveTickFontOptions(0); return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio)); } getPixelForValue(value) { return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange); } getValueForPixel(pixel) { return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange; } } LinearScale.id = 'linear'; LinearScale.defaults = { ticks: { callback: Ticks.formatters.numeric } }; function isMajor(tickVal) { const remain = tickVal / (Math.pow(10, Math.floor((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(tickVal)))); return remain === 1; } function generateTicks(generationOptions, dataRange) { const endExp = Math.floor((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(dataRange.max)); const endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp)); const ticks = []; let tickVal = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(generationOptions.min, Math.pow(10, Math.floor((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(dataRange.min)))); let exp = Math.floor((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(tickVal)); let significand = Math.floor(tickVal / Math.pow(10, exp)); let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1; do { ticks.push({value: tickVal, major: isMajor(tickVal)}); ++significand; if (significand === 10) { significand = 1; ++exp; precision = exp >= 0 ? 1 : precision; } tickVal = Math.round(significand * Math.pow(10, exp) * precision) / precision; } while (exp < endExp || (exp === endExp && significand < endSignificand)); const lastTick = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)(generationOptions.max, tickVal); ticks.push({value: lastTick, major: isMajor(tickVal)}); return ticks; } class LogarithmicScale extends Scale { constructor(cfg) { super(cfg); this.start = undefined; this.end = undefined; this._startValue = undefined; this._valueRange = 0; } parse(raw, index) { const value = LinearScaleBase.prototype.parse.apply(this, [raw, index]); if (value === 0) { this._zero = true; return undefined; } return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(value) && value > 0 ? value : null; } determineDataLimits() { const me = this; const {min, max} = me.getMinMax(true); me.min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? Math.max(0, min) : null; me.max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? Math.max(0, max) : null; if (me.options.beginAtZero) { me._zero = true; } me.handleTickRangeOptions(); } handleTickRangeOptions() { const me = this; const {minDefined, maxDefined} = me.getUserBounds(); let min = me.min; let max = me.max; const setMin = v => (min = minDefined ? min : v); const setMax = v => (max = maxDefined ? max : v); const exp = (v, m) => Math.pow(10, Math.floor((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(v)) + m); if (min === max) { if (min <= 0) { setMin(1); setMax(10); } else { setMin(exp(min, -1)); setMax(exp(max, +1)); } } if (min <= 0) { setMin(exp(max, -1)); } if (max <= 0) { setMax(exp(min, +1)); } if (me._zero && me.min !== me._suggestedMin && min === exp(me.min, 0)) { setMin(exp(min, -1)); } me.min = min; me.max = max; } buildTicks() { const me = this; const opts = me.options; const generationOptions = { min: me._userMin, max: me._userMax }; const ticks = generateTicks(generationOptions, me); if (opts.bounds === 'ticks') { (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aA)(ticks, me, 'value'); } if (opts.reverse) { ticks.reverse(); me.start = me.max; me.end = me.min; } else { me.start = me.min; me.end = me.max; } return ticks; } getLabelForValue(value) { return value === undefined ? '0' : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.n)(value, this.chart.options.locale); } configure() { const me = this; const start = me.min; super.configure(); me._startValue = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(start); me._valueRange = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(me.max) - (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(start); } getPixelForValue(value) { const me = this; if (value === undefined || value === 0) { value = me.min; } if (value === null || isNaN(value)) { return NaN; } return me.getPixelForDecimal(value === me.min ? 0 : ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(value) - me._startValue) / me._valueRange); } getValueForPixel(pixel) { const me = this; const decimal = me.getDecimalForPixel(pixel); return Math.pow(10, me._startValue + decimal * me._valueRange); } } LogarithmicScale.id = 'logarithmic'; LogarithmicScale.defaults = { ticks: { callback: Ticks.formatters.logarithmic, major: { enabled: true } } }; function getTickBackdropHeight(opts) { const tickOpts = opts.ticks; if (tickOpts.display && opts.display) { const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(tickOpts.backdropPadding); return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(tickOpts.font && tickOpts.font.size, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.font.size) + padding.height; } return 0; } function measureLabelSize(ctx, font, label) { label = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label : [label]; return { w: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF)(ctx, font.string, label), h: label.length * font.lineHeight }; } function determineLimits(angle, pos, size, min, max) { if (angle === min || angle === max) { return { start: pos - (size / 2), end: pos + (size / 2) }; } else if (angle < min || angle > max) { return { start: pos - size, end: pos }; } return { start: pos, end: pos + size }; } function fitWithPointLabels(scale) { const furthestLimits = { l: 0, r: scale.width, t: 0, b: scale.height - scale.paddingTop }; const furthestAngles = {}; const labelSizes = []; const padding = []; const valueCount = scale.getLabels().length; for (let i = 0; i < valueCount; i++) { const opts = scale.options.pointLabels.setContext(scale.getPointLabelContext(i)); padding[i] = opts.padding; const pointPosition = scale.getPointPosition(i, scale.drawingArea + padding[i]); const plFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(opts.font); const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i]); labelSizes[i] = textSize; const angleRadians = scale.getIndexAngle(i); const angle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(angleRadians); const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); if (hLimits.start < furthestLimits.l) { furthestLimits.l = hLimits.start; furthestAngles.l = angleRadians; } if (hLimits.end > furthestLimits.r) { furthestLimits.r = hLimits.end; furthestAngles.r = angleRadians; } if (vLimits.start < furthestLimits.t) { furthestLimits.t = vLimits.start; furthestAngles.t = angleRadians; } if (vLimits.end > furthestLimits.b) { furthestLimits.b = vLimits.end; furthestAngles.b = angleRadians; } } scale._setReductions(scale.drawingArea, furthestLimits, furthestAngles); scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding); } function buildPointLabelItems(scale, labelSizes, padding) { const items = []; const valueCount = scale.getLabels().length; const opts = scale.options; const tickBackdropHeight = getTickBackdropHeight(opts); const outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max); for (let i = 0; i < valueCount; i++) { const extra = (i === 0 ? tickBackdropHeight / 2 : 0); const pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + padding[i]); const angle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(scale.getIndexAngle(i)); const size = labelSizes[i]; const y = yForAngle(pointLabelPosition.y, size.h, angle); const textAlign = getTextAlignForAngle(angle); const left = leftForTextAlign(pointLabelPosition.x, size.w, textAlign); items.push({ x: pointLabelPosition.x, y, textAlign, left, top: y, right: left + size.w, bottom: y + size.h }); } return items; } function getTextAlignForAngle(angle) { if (angle === 0 || angle === 180) { return 'center'; } else if (angle < 180) { return 'left'; } return 'right'; } function leftForTextAlign(x, w, align) { if (align === 'right') { x -= w; } else if (align === 'center') { x -= (w / 2); } return x; } function yForAngle(y, h, angle) { if (angle === 90 || angle === 270) { y -= (h / 2); } else if (angle > 270 || angle < 90) { y -= h; } return y; } function drawPointLabels(scale, labelCount) { const {ctx, options: {pointLabels}} = scale; for (let i = labelCount - 1; i >= 0; i--) { const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i)); const plFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(optsAtIndex.font); const {x, y, textAlign, left, top, right, bottom} = scale._pointLabelItems[i]; const {backdropColor} = optsAtIndex; if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(backdropColor)) { const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(optsAtIndex.backdropPadding); ctx.fillStyle = backdropColor; ctx.fillRect(left - padding.left, top - padding.top, right - left + padding.width, bottom - top + padding.height); } (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)( ctx, scale._pointLabels[i], x, y + (plFont.lineHeight / 2), plFont, { color: optsAtIndex.color, textAlign: textAlign, textBaseline: 'middle' } ); } } function pathRadiusLine(scale, radius, circular, labelCount) { const {ctx} = scale; if (circular) { ctx.arc(scale.xCenter, scale.yCenter, radius, 0, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); } else { let pointPosition = scale.getPointPosition(0, radius); ctx.moveTo(pointPosition.x, pointPosition.y); for (let i = 1; i < labelCount; i++) { pointPosition = scale.getPointPosition(i, radius); ctx.lineTo(pointPosition.x, pointPosition.y); } } } function drawRadiusLine(scale, gridLineOpts, radius, labelCount) { const ctx = scale.ctx; const circular = gridLineOpts.circular; const {color, lineWidth} = gridLineOpts; if ((!circular && !labelCount) || !color || !lineWidth || radius < 0) { return; } ctx.save(); ctx.strokeStyle = color; ctx.lineWidth = lineWidth; ctx.setLineDash(gridLineOpts.borderDash); ctx.lineDashOffset = gridLineOpts.borderDashOffset; ctx.beginPath(); pathRadiusLine(scale, radius, circular, labelCount); ctx.closePath(); ctx.stroke(); ctx.restore(); } function numberOrZero(param) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(param) ? param : 0; } function createPointLabelContext(parent, index, label) { return Object.assign(Object.create(parent), { label, index, type: 'pointLabel' }); } class RadialLinearScale extends LinearScaleBase { constructor(cfg) { super(cfg); this.xCenter = undefined; this.yCenter = undefined; this.drawingArea = undefined; this._pointLabels = []; this._pointLabelItems = []; } setDimensions() { const me = this; me.width = me.maxWidth; me.height = me.maxHeight; me.paddingTop = getTickBackdropHeight(me.options) / 2; me.xCenter = Math.floor(me.width / 2); me.yCenter = Math.floor((me.height - me.paddingTop) / 2); me.drawingArea = Math.min(me.height - me.paddingTop, me.width) / 2; } determineDataLimits() { const me = this; const {min, max} = me.getMinMax(false); me.min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : 0; me.max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : 0; me.handleTickRangeOptions(); } computeTickLimit() { return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options)); } generateTickLabels(ticks) { const me = this; LinearScaleBase.prototype.generateTickLabels.call(me, ticks); me._pointLabels = me.getLabels().map((value, index) => { const label = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(me.options.pointLabels.callback, [value, index], me); return label || label === 0 ? label : ''; }); } fit() { const me = this; const opts = me.options; if (opts.display && opts.pointLabels.display) { fitWithPointLabels(me); } else { me.setCenterPoint(0, 0, 0, 0); } } _setReductions(largestPossibleRadius, furthestLimits, furthestAngles) { const me = this; let radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l); let radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r); let radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t); let radiusReductionBottom = -Math.max(furthestLimits.b - (me.height - me.paddingTop), 0) / Math.cos(furthestAngles.b); radiusReductionLeft = numberOrZero(radiusReductionLeft); radiusReductionRight = numberOrZero(radiusReductionRight); radiusReductionTop = numberOrZero(radiusReductionTop); radiusReductionBottom = numberOrZero(radiusReductionBottom); me.drawingArea = Math.max(largestPossibleRadius / 2, Math.min( Math.floor(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2), Math.floor(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2))); me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom); } setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) { const me = this; const maxRight = me.width - rightMovement - me.drawingArea; const maxLeft = leftMovement + me.drawingArea; const maxTop = topMovement + me.drawingArea; const maxBottom = (me.height - me.paddingTop) - bottomMovement - me.drawingArea; me.xCenter = Math.floor(((maxLeft + maxRight) / 2) + me.left); me.yCenter = Math.floor(((maxTop + maxBottom) / 2) + me.top + me.paddingTop); } getIndexAngle(index) { const angleMultiplier = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T / this.getLabels().length; const startAngle = this.options.startAngle || 0; return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.at)(index * angleMultiplier + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(startAngle)); } getDistanceFromCenterForValue(value) { const me = this; if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(value)) { return NaN; } const scalingFactor = me.drawingArea / (me.max - me.min); if (me.options.reverse) { return (me.max - value) * scalingFactor; } return (value - me.min) * scalingFactor; } getValueForDistanceFromCenter(distance) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(distance)) { return NaN; } const me = this; const scaledDistance = distance / (me.drawingArea / (me.max - me.min)); return me.options.reverse ? me.max - scaledDistance : me.min + scaledDistance; } getPointLabelContext(index) { const me = this; const pointLabels = me._pointLabels || []; if (index >= 0 && index < pointLabels.length) { const pointLabel = pointLabels[index]; return createPointLabelContext(me.getContext(), index, pointLabel); } } getPointPosition(index, distanceFromCenter) { const me = this; const angle = me.getIndexAngle(index) - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H; return { x: Math.cos(angle) * distanceFromCenter + me.xCenter, y: Math.sin(angle) * distanceFromCenter + me.yCenter, angle }; } getPointPositionForValue(index, value) { return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); } getBasePosition(index) { return this.getPointPositionForValue(index || 0, this.getBaseValue()); } getPointLabelPosition(index) { const {left, top, right, bottom} = this._pointLabelItems[index]; return { left, top, right, bottom, }; } drawBackground() { const me = this; const {backgroundColor, grid: {circular}} = me.options; if (backgroundColor) { const ctx = me.ctx; ctx.save(); ctx.beginPath(); pathRadiusLine(me, me.getDistanceFromCenterForValue(me._endValue), circular, me.getLabels().length); ctx.closePath(); ctx.fillStyle = backgroundColor; ctx.fill(); ctx.restore(); } } drawGrid() { const me = this; const ctx = me.ctx; const opts = me.options; const {angleLines, grid} = opts; const labelCount = me.getLabels().length; let i, offset, position; if (opts.pointLabels.display) { drawPointLabels(me, labelCount); } if (grid.display) { me.ticks.forEach((tick, index) => { if (index !== 0) { offset = me.getDistanceFromCenterForValue(tick.value); const optsAtIndex = grid.setContext(me.getContext(index - 1)); drawRadiusLine(me, optsAtIndex, offset, labelCount); } }); } if (angleLines.display) { ctx.save(); for (i = me.getLabels().length - 1; i >= 0; i--) { const optsAtIndex = angleLines.setContext(me.getPointLabelContext(i)); const {color, lineWidth} = optsAtIndex; if (!lineWidth || !color) { continue; } ctx.lineWidth = lineWidth; ctx.strokeStyle = color; ctx.setLineDash(optsAtIndex.borderDash); ctx.lineDashOffset = optsAtIndex.borderDashOffset; offset = me.getDistanceFromCenterForValue(opts.ticks.reverse ? me.min : me.max); position = me.getPointPosition(i, offset); ctx.beginPath(); ctx.moveTo(me.xCenter, me.yCenter); ctx.lineTo(position.x, position.y); ctx.stroke(); } ctx.restore(); } } drawBorder() {} drawLabels() { const me = this; const ctx = me.ctx; const opts = me.options; const tickOpts = opts.ticks; if (!tickOpts.display) { return; } const startAngle = me.getIndexAngle(0); let offset, width; ctx.save(); ctx.translate(me.xCenter, me.yCenter); ctx.rotate(startAngle); ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; me.ticks.forEach((tick, index) => { if (index === 0 && !opts.reverse) { return; } const optsAtIndex = tickOpts.setContext(me.getContext(index)); const tickFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(optsAtIndex.font); offset = me.getDistanceFromCenterForValue(me.ticks[index].value); if (optsAtIndex.showLabelBackdrop) { ctx.font = tickFont.string; width = ctx.measureText(tick.label).width; ctx.fillStyle = optsAtIndex.backdropColor; const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A)(optsAtIndex.backdropPadding); ctx.fillRect( -width / 2 - padding.left, -offset - tickFont.size / 2 - padding.top, width + padding.width, tickFont.size + padding.height ); } (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, tick.label, 0, -offset, tickFont, { color: optsAtIndex.color, }); }); ctx.restore(); } drawTitle() {} } RadialLinearScale.id = 'radialLinear'; RadialLinearScale.defaults = { display: true, animate: true, position: 'chartArea', angleLines: { display: true, lineWidth: 1, borderDash: [], borderDashOffset: 0.0 }, grid: { circular: false }, startAngle: 0, ticks: { showLabelBackdrop: true, callback: Ticks.formatters.numeric }, pointLabels: { backdropColor: undefined, backdropPadding: 2, display: true, font: { size: 10 }, callback(label) { return label; }, padding: 5 } }; RadialLinearScale.defaultRoutes = { 'angleLines.color': 'borderColor', 'pointLabels.color': 'color', 'ticks.color': 'color' }; RadialLinearScale.descriptors = { angleLines: { _fallback: 'grid' } }; const INTERVALS = { millisecond: {common: true, size: 1, steps: 1000}, second: {common: true, size: 1000, steps: 60}, minute: {common: true, size: 60000, steps: 60}, hour: {common: true, size: 3600000, steps: 24}, day: {common: true, size: 86400000, steps: 30}, week: {common: false, size: 604800000, steps: 4}, month: {common: true, size: 2.628e9, steps: 12}, quarter: {common: false, size: 7.884e9, steps: 4}, year: {common: true, size: 3.154e10} }; const UNITS = (Object.keys(INTERVALS)); function sorter(a, b) { return a - b; } function parse(scale, input) { if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(input)) { return null; } const adapter = scale._adapter; const {parser, round, isoWeekday} = scale._parseOpts; let value = input; if (typeof parser === 'function') { value = parser(value); } if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) { value = typeof parser === 'string' ? adapter.parse(value, parser) : adapter.parse(value); } if (value === null) { return null; } if (round) { value = round === 'week' && ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, 'isoWeek', isoWeekday) : adapter.startOf(value, round); } return +value; } function determineUnitForAutoTicks(minUnit, min, max, capacity) { const ilen = UNITS.length; for (let i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) { const interval = INTERVALS[UNITS[i]]; const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER; if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) { return UNITS[i]; } } return UNITS[ilen - 1]; } function determineUnitForFormatting(scale, numTicks, minUnit, min, max) { for (let i = UNITS.length - 1; i >= UNITS.indexOf(minUnit); i--) { const unit = UNITS[i]; if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= numTicks - 1) { return unit; } } return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0]; } function determineMajorUnit(unit) { for (let i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) { if (INTERVALS[UNITS[i]].common) { return UNITS[i]; } } } function addTick(ticks, time, timestamps) { if (!timestamps) { ticks[time] = true; } else if (timestamps.length) { const {lo, hi} = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aH)(timestamps, time); const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi]; ticks[timestamp] = true; } } function setMajorTicks(scale, ticks, map, majorUnit) { const adapter = scale._adapter; const first = +adapter.startOf(ticks[0].value, majorUnit); const last = ticks[ticks.length - 1].value; let major, index; for (major = first; major <= last; major = +adapter.add(major, 1, majorUnit)) { index = map[major]; if (index >= 0) { ticks[index].major = true; } } return ticks; } function ticksFromTimestamps(scale, values, majorUnit) { const ticks = []; const map = {}; const ilen = values.length; let i, value; for (i = 0; i < ilen; ++i) { value = values[i]; map[value] = i; ticks.push({ value, major: false }); } return (ilen === 0 || !majorUnit) ? ticks : setMajorTicks(scale, ticks, map, majorUnit); } class TimeScale extends Scale { constructor(props) { super(props); this._cache = { data: [], labels: [], all: [] }; this._unit = 'day'; this._majorUnit = undefined; this._offsets = {}; this._normalized = false; this._parseOpts = undefined; } init(scaleOpts, opts) { const time = scaleOpts.time || (scaleOpts.time = {}); const adapter = this._adapter = new adapters._date(scaleOpts.adapters.date); (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(time.displayFormats, adapter.formats()); this._parseOpts = { parser: time.parser, round: time.round, isoWeekday: time.isoWeekday }; super.init(scaleOpts); this._normalized = opts.normalized; } parse(raw, index) { if (raw === undefined) { return null; } return parse(this, raw); } beforeLayout() { super.beforeLayout(); this._cache = { data: [], labels: [], all: [] }; } determineDataLimits() { const me = this; const options = me.options; const adapter = me._adapter; const unit = options.time.unit || 'day'; let {min, max, minDefined, maxDefined} = me.getUserBounds(); function _applyBounds(bounds) { if (!minDefined && !isNaN(bounds.min)) { min = Math.min(min, bounds.min); } if (!maxDefined && !isNaN(bounds.max)) { max = Math.max(max, bounds.max); } } if (!minDefined || !maxDefined) { _applyBounds(me._getLabelBounds()); if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') { _applyBounds(me.getMinMax(false)); } } min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit); max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1; me.min = Math.min(min, max - 1); me.max = Math.max(min + 1, max); } _getLabelBounds() { const arr = this.getLabelTimestamps(); let min = Number.POSITIVE_INFINITY; let max = Number.NEGATIVE_INFINITY; if (arr.length) { min = arr[0]; max = arr[arr.length - 1]; } return {min, max}; } buildTicks() { const me = this; const options = me.options; const timeOpts = options.time; const tickOpts = options.ticks; const timestamps = tickOpts.source === 'labels' ? me.getLabelTimestamps() : me._generate(); if (options.bounds === 'ticks' && timestamps.length) { me.min = me._userMin || timestamps[0]; me.max = me._userMax || timestamps[timestamps.length - 1]; } const min = me.min; const max = me.max; const ticks = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aG)(timestamps, min, max); me._unit = timeOpts.unit || (tickOpts.autoSkip ? determineUnitForAutoTicks(timeOpts.minUnit, me.min, me.max, me._getLabelCapacity(min)) : determineUnitForFormatting(me, ticks.length, timeOpts.minUnit, me.min, me.max)); me._majorUnit = !tickOpts.major.enabled || me._unit === 'year' ? undefined : determineMajorUnit(me._unit); me.initOffsets(timestamps); if (options.reverse) { ticks.reverse(); } return ticksFromTimestamps(me, ticks, me._majorUnit); } initOffsets(timestamps) { const me = this; let start = 0; let end = 0; let first, last; if (me.options.offset && timestamps.length) { first = me.getDecimalForValue(timestamps[0]); if (timestamps.length === 1) { start = 1 - first; } else { start = (me.getDecimalForValue(timestamps[1]) - first) / 2; } last = me.getDecimalForValue(timestamps[timestamps.length - 1]); if (timestamps.length === 1) { end = last; } else { end = (last - me.getDecimalForValue(timestamps[timestamps.length - 2])) / 2; } } const limit = timestamps.length < 3 ? 0.5 : 0.25; start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(start, 0, limit); end = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(end, 0, limit); me._offsets = {start, end, factor: 1 / (start + 1 + end)}; } _generate() { const me = this; const adapter = me._adapter; const min = me.min; const max = me.max; const options = me.options; const timeOpts = options.time; const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, me._getLabelCapacity(min)); const stepSize = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(timeOpts.stepSize, 1); const weekday = minor === 'week' ? timeOpts.isoWeekday : false; const hasWeekday = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(weekday) || weekday === true; const ticks = {}; let first = min; let time, count; if (hasWeekday) { first = +adapter.startOf(first, 'isoWeek', weekday); } first = +adapter.startOf(first, hasWeekday ? 'day' : minor); if (adapter.diff(max, min, minor) > 100000 * stepSize) { throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor); } const timestamps = options.ticks.source === 'data' && me.getDataTimestamps(); for (time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++) { addTick(ticks, time, timestamps); } if (time === max || options.bounds === 'ticks' || count === 1) { addTick(ticks, time, timestamps); } return Object.keys(ticks).sort((a, b) => a - b).map(x => +x); } getLabelForValue(value) { const me = this; const adapter = me._adapter; const timeOpts = me.options.time; if (timeOpts.tooltipFormat) { return adapter.format(value, timeOpts.tooltipFormat); } return adapter.format(value, timeOpts.displayFormats.datetime); } _tickFormatFunction(time, index, ticks, format) { const me = this; const options = me.options; const formats = options.time.displayFormats; const unit = me._unit; const majorUnit = me._majorUnit; const minorFormat = unit && formats[unit]; const majorFormat = majorUnit && formats[majorUnit]; const tick = ticks[index]; const major = majorUnit && majorFormat && tick && tick.major; const label = me._adapter.format(time, format || (major ? majorFormat : minorFormat)); const formatter = options.ticks.callback; return formatter ? (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)(formatter, [label, index, ticks], me) : label; } generateTickLabels(ticks) { let i, ilen, tick; for (i = 0, ilen = ticks.length; i < ilen; ++i) { tick = ticks[i]; tick.label = this._tickFormatFunction(tick.value, i, ticks); } } getDecimalForValue(value) { const me = this; return value === null ? NaN : (value - me.min) / (me.max - me.min); } getPixelForValue(value) { const me = this; const offsets = me._offsets; const pos = me.getDecimalForValue(value); return me.getPixelForDecimal((offsets.start + pos) * offsets.factor); } getValueForPixel(pixel) { const me = this; const offsets = me._offsets; const pos = me.getDecimalForPixel(pixel) / offsets.factor - offsets.end; return me.min + pos * (me.max - me.min); } _getLabelSize(label) { const me = this; const ticksOpts = me.options.ticks; const tickLabelWidth = me.ctx.measureText(label).width; const angle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(me.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation); const cosRotation = Math.cos(angle); const sinRotation = Math.sin(angle); const tickFontSize = me._resolveTickFontOptions(0).size; return { w: (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation), h: (tickLabelWidth * sinRotation) + (tickFontSize * cosRotation) }; } _getLabelCapacity(exampleTime) { const me = this; const timeOpts = me.options.time; const displayFormats = timeOpts.displayFormats; const format = displayFormats[timeOpts.unit] || displayFormats.millisecond; const exampleLabel = me._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(me, [exampleTime], me._majorUnit), format); const size = me._getLabelSize(exampleLabel); const capacity = Math.floor(me.isHorizontal() ? me.width / size.w : me.height / size.h) - 1; return capacity > 0 ? capacity : 1; } getDataTimestamps() { const me = this; let timestamps = me._cache.data || []; let i, ilen; if (timestamps.length) { return timestamps; } const metas = me.getMatchingVisibleMetas(); if (me._normalized && metas.length) { return (me._cache.data = metas[0].controller.getAllParsedValues(me)); } for (i = 0, ilen = metas.length; i < ilen; ++i) { timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(me)); } return (me._cache.data = me.normalize(timestamps)); } getLabelTimestamps() { const me = this; const timestamps = me._cache.labels || []; let i, ilen; if (timestamps.length) { return timestamps; } const labels = me.getLabels(); for (i = 0, ilen = labels.length; i < ilen; ++i) { timestamps.push(parse(me, labels[i])); } return (me._cache.labels = me._normalized ? timestamps : me.normalize(timestamps)); } normalize(values) { return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort(sorter)); } } TimeScale.id = 'time'; TimeScale.defaults = { bounds: 'data', adapters: {}, time: { parser: false, unit: false, round: false, isoWeekday: false, minUnit: 'millisecond', displayFormats: {} }, ticks: { source: 'auto', major: { enabled: false } } }; function interpolate(table, val, reverse) { let lo = 0; let hi = table.length - 1; let prevSource, nextSource, prevTarget, nextTarget; if (reverse) { if (val >= table[lo].pos && val <= table[hi].pos) { ({lo, hi} = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(table, 'pos', val)); } ({pos: prevSource, time: prevTarget} = table[lo]); ({pos: nextSource, time: nextTarget} = table[hi]); } else { if (val >= table[lo].time && val <= table[hi].time) { ({lo, hi} = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(table, 'time', val)); } ({time: prevSource, pos: prevTarget} = table[lo]); ({time: nextSource, pos: nextTarget} = table[hi]); } const span = nextSource - prevSource; return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget; } class TimeSeriesScale extends TimeScale { constructor(props) { super(props); this._table = []; this._minPos = undefined; this._tableRange = undefined; } initOffsets() { const me = this; const timestamps = me._getTimestampsForTable(); const table = me._table = me.buildLookupTable(timestamps); me._minPos = interpolate(table, me.min); me._tableRange = interpolate(table, me.max) - me._minPos; super.initOffsets(timestamps); } buildLookupTable(timestamps) { const {min, max} = this; const items = []; const table = []; let i, ilen, prev, curr, next; for (i = 0, ilen = timestamps.length; i < ilen; ++i) { curr = timestamps[i]; if (curr >= min && curr <= max) { items.push(curr); } } if (items.length < 2) { return [ {time: min, pos: 0}, {time: max, pos: 1} ]; } for (i = 0, ilen = items.length; i < ilen; ++i) { next = items[i + 1]; prev = items[i - 1]; curr = items[i]; if (Math.round((next + prev) / 2) !== curr) { table.push({time: curr, pos: i / (ilen - 1)}); } } return table; } _getTimestampsForTable() { const me = this; let timestamps = me._cache.all || []; if (timestamps.length) { return timestamps; } const data = me.getDataTimestamps(); const label = me.getLabelTimestamps(); if (data.length && label.length) { timestamps = me.normalize(data.concat(label)); } else { timestamps = data.length ? data : label; } timestamps = me._cache.all = timestamps; return timestamps; } getDecimalForValue(value) { return (interpolate(this._table, value) - this._minPos) / this._tableRange; } getValueForPixel(pixel) { const me = this; const offsets = me._offsets; const decimal = me.getDecimalForPixel(pixel) / offsets.factor - offsets.end; return interpolate(me._table, decimal * me._tableRange + me._minPos, true); } } TimeSeriesScale.id = 'timeseries'; TimeSeriesScale.defaults = TimeScale.defaults; var scales = /*#__PURE__*/Object.freeze({ __proto__: null, CategoryScale: CategoryScale, LinearScale: LinearScale, LogarithmicScale: LogarithmicScale, RadialLinearScale: RadialLinearScale, TimeScale: TimeScale, TimeSeriesScale: TimeSeriesScale }); const registerables = [ controllers, elements, plugins, scales, ]; /***/ }), /***/ "./node_modules/chart.js/dist/chunks/helpers.segment.js": /*!**************************************************************!*\ !*** ./node_modules/chart.js/dist/chunks/helpers.segment.js ***! \**************************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "$": function() { return /* binding */ overrides; }, /* harmony export */ "A": function() { return /* binding */ toPadding; }, /* harmony export */ "B": function() { return /* binding */ each; }, /* harmony export */ "C": function() { return /* binding */ getMaximumSize; }, /* harmony export */ "D": function() { return /* binding */ _getParentNode; }, /* harmony export */ "E": function() { return /* binding */ readUsedSize; }, /* harmony export */ "F": function() { return /* binding */ throttled; }, /* harmony export */ "G": function() { return /* binding */ supportsEventListenerOptions; }, /* harmony export */ "H": function() { return /* binding */ HALF_PI; }, /* harmony export */ "I": function() { return /* binding */ _isDomSupported; }, /* harmony export */ "J": function() { return /* binding */ log10; }, /* harmony export */ "K": function() { return /* binding */ _factorize; }, /* harmony export */ "L": function() { return /* binding */ finiteOrDefault; }, /* harmony export */ "M": function() { return /* binding */ callback; }, /* harmony export */ "N": function() { return /* binding */ _addGrace; }, /* harmony export */ "O": function() { return /* binding */ toDegrees; }, /* harmony export */ "P": function() { return /* binding */ PI; }, /* harmony export */ "Q": function() { return /* binding */ _measureText; }, /* harmony export */ "R": function() { return /* binding */ _int16Range; }, /* harmony export */ "S": function() { return /* binding */ _alignPixel; }, /* harmony export */ "T": function() { return /* binding */ TAU; }, /* harmony export */ "U": function() { return /* binding */ clipArea; }, /* harmony export */ "V": function() { return /* binding */ renderText; }, /* harmony export */ "W": function() { return /* binding */ unclipArea; }, /* harmony export */ "X": function() { return /* binding */ toFont; }, /* harmony export */ "Y": function() { return /* binding */ _toLeftRightCenter; }, /* harmony export */ "Z": function() { return /* binding */ _alignStartEnd; }, /* harmony export */ "_": function() { return /* binding */ _arrayUnique; }, /* harmony export */ "a": function() { return /* binding */ resolve; }, /* harmony export */ "a0": function() { return /* binding */ merge; }, /* harmony export */ "a1": function() { return /* binding */ _capitalize; }, /* harmony export */ "a2": function() { return /* binding */ descriptors; }, /* harmony export */ "a3": function() { return /* binding */ isFunction; }, /* harmony export */ "a4": function() { return /* binding */ _attachContext; }, /* harmony export */ "a5": function() { return /* binding */ _createResolver; }, /* harmony export */ "a6": function() { return /* binding */ _descriptors; }, /* harmony export */ "a7": function() { return /* binding */ mergeIf; }, /* harmony export */ "a8": function() { return /* binding */ uid; }, /* harmony export */ "a9": function() { return /* binding */ debounce; }, /* harmony export */ "aA": function() { return /* binding */ _setMinAndMaxByKey; }, /* harmony export */ "aB": function() { return /* binding */ niceNum; }, /* harmony export */ "aC": function() { return /* binding */ almostWhole; }, /* harmony export */ "aD": function() { return /* binding */ almostEquals; }, /* harmony export */ "aE": function() { return /* binding */ _decimalPlaces; }, /* harmony export */ "aF": function() { return /* binding */ _longestText; }, /* harmony export */ "aG": function() { return /* binding */ _filterBetween; }, /* harmony export */ "aH": function() { return /* binding */ _lookup; }, /* harmony export */ "aI": function() { return /* binding */ getHoverColor; }, /* harmony export */ "aJ": function() { return /* binding */ clone$1; }, /* harmony export */ "aK": function() { return /* binding */ _merger; }, /* harmony export */ "aL": function() { return /* binding */ _mergerIf; }, /* harmony export */ "aM": function() { return /* binding */ _deprecated; }, /* harmony export */ "aN": function() { return /* binding */ toFontString; }, /* harmony export */ "aO": function() { return /* binding */ splineCurve; }, /* harmony export */ "aP": function() { return /* binding */ splineCurveMonotone; }, /* harmony export */ "aQ": function() { return /* binding */ getStyle; }, /* harmony export */ "aR": function() { return /* binding */ fontString; }, /* harmony export */ "aS": function() { return /* binding */ toLineHeight; }, /* harmony export */ "aT": function() { return /* binding */ PITAU; }, /* harmony export */ "aU": function() { return /* binding */ INFINITY; }, /* harmony export */ "aV": function() { return /* binding */ RAD_PER_DEG; }, /* harmony export */ "aW": function() { return /* binding */ QUARTER_PI; }, /* harmony export */ "aX": function() { return /* binding */ TWO_THIRDS_PI; }, /* harmony export */ "aY": function() { return /* binding */ _angleDiff; }, /* harmony export */ "aa": function() { return /* binding */ retinaScale; }, /* harmony export */ "ab": function() { return /* binding */ clearCanvas; }, /* harmony export */ "ac": function() { return /* binding */ setsEqual; }, /* harmony export */ "ad": function() { return /* binding */ _elementsEqual; }, /* harmony export */ "ae": function() { return /* binding */ getAngleFromPoint; }, /* harmony export */ "af": function() { return /* binding */ _readValueToProps; }, /* harmony export */ "ag": function() { return /* binding */ _updateBezierControlPoints; }, /* harmony export */ "ah": function() { return /* binding */ _computeSegments; }, /* harmony export */ "ai": function() { return /* binding */ _boundSegments; }, /* harmony export */ "aj": function() { return /* binding */ _steppedInterpolation; }, /* harmony export */ "ak": function() { return /* binding */ _bezierInterpolation; }, /* harmony export */ "al": function() { return /* binding */ _pointInLine; }, /* harmony export */ "am": function() { return /* binding */ _steppedLineTo; }, /* harmony export */ "an": function() { return /* binding */ _bezierCurveTo; }, /* harmony export */ "ao": function() { return /* binding */ drawPoint; }, /* harmony export */ "ap": function() { return /* binding */ addRoundedRectPath; }, /* harmony export */ "aq": function() { return /* binding */ toTRBL; }, /* harmony export */ "ar": function() { return /* binding */ toTRBLCorners; }, /* harmony export */ "as": function() { return /* binding */ _boundSegment; }, /* harmony export */ "at": function() { return /* binding */ _normalizeAngle; }, /* harmony export */ "au": function() { return /* binding */ getRtlAdapter; }, /* harmony export */ "av": function() { return /* binding */ overrideTextDirection; }, /* harmony export */ "aw": function() { return /* binding */ _textX; }, /* harmony export */ "ax": function() { return /* binding */ restoreTextDirection; }, /* harmony export */ "ay": function() { return /* binding */ noop; }, /* harmony export */ "az": function() { return /* binding */ distanceBetweenPoints; }, /* harmony export */ "b": function() { return /* binding */ isArray; }, /* harmony export */ "c": function() { return /* binding */ color; }, /* harmony export */ "d": function() { return /* binding */ defaults; }, /* harmony export */ "e": function() { return /* binding */ effects; }, /* harmony export */ "f": function() { return /* binding */ resolveObjectKey; }, /* harmony export */ "g": function() { return /* binding */ isNumberFinite; }, /* harmony export */ "h": function() { return /* binding */ defined; }, /* harmony export */ "i": function() { return /* binding */ isObject; }, /* harmony export */ "j": function() { return /* binding */ isNullOrUndef; }, /* harmony export */ "k": function() { return /* binding */ toPercentage; }, /* harmony export */ "l": function() { return /* binding */ listenArrayEvents; }, /* harmony export */ "m": function() { return /* binding */ toDimension; }, /* harmony export */ "n": function() { return /* binding */ formatNumber; }, /* harmony export */ "o": function() { return /* binding */ _angleBetween; }, /* harmony export */ "p": function() { return /* binding */ isNumber; }, /* harmony export */ "q": function() { return /* binding */ _limitValue; }, /* harmony export */ "r": function() { return /* binding */ requestAnimFrame; }, /* harmony export */ "s": function() { return /* binding */ sign; }, /* harmony export */ "t": function() { return /* binding */ toRadians; }, /* harmony export */ "u": function() { return /* binding */ unlistenArrayEvents; }, /* harmony export */ "v": function() { return /* binding */ valueOrDefault; }, /* harmony export */ "w": function() { return /* binding */ _lookupByKey; }, /* harmony export */ "x": function() { return /* binding */ getRelativePosition; }, /* harmony export */ "y": function() { return /* binding */ _isPointInArea; }, /* harmony export */ "z": function() { return /* binding */ _rlookupByKey; } /* harmony export */ }); /*! * Chart.js v3.5.1 * https://www.chartjs.org * (c) 2021 Chart.js Contributors * Released under the MIT License */ function fontString(pixelSize, fontStyle, fontFamily) { return fontStyle + ' ' + pixelSize + 'px ' + fontFamily; } const requestAnimFrame = (function() { if (typeof window === 'undefined') { return function(callback) { return callback(); }; } return window.requestAnimationFrame; }()); function throttled(fn, thisArg, updateFn) { const updateArgs = updateFn || ((args) => Array.prototype.slice.call(args)); let ticking = false; let args = []; return function(...rest) { args = updateArgs(rest); if (!ticking) { ticking = true; requestAnimFrame.call(window, () => { ticking = false; fn.apply(thisArg, args); }); } }; } function debounce(fn, delay) { let timeout; return function() { if (delay) { clearTimeout(timeout); timeout = setTimeout(fn, delay); } else { fn(); } return delay; }; } const _toLeftRightCenter = (align) => align === 'start' ? 'left' : align === 'end' ? 'right' : 'center'; const _alignStartEnd = (align, start, end) => align === 'start' ? start : align === 'end' ? end : (start + end) / 2; const _textX = (align, left, right, rtl) => { const check = rtl ? 'left' : 'right'; return align === check ? right : align === 'center' ? (left + right) / 2 : left; }; function noop() {} const uid = (function() { let id = 0; return function() { return id++; }; }()); function isNullOrUndef(value) { return value === null || typeof value === 'undefined'; } function isArray(value) { if (Array.isArray && Array.isArray(value)) { return true; } const type = Object.prototype.toString.call(value); if (type.substr(0, 7) === '[object' && type.substr(-6) === 'Array]') { return true; } return false; } function isObject(value) { return value !== null && Object.prototype.toString.call(value) === '[object Object]'; } const isNumberFinite = (value) => (typeof value === 'number' || value instanceof Number) && isFinite(+value); function finiteOrDefault(value, defaultValue) { return isNumberFinite(value) ? value : defaultValue; } function valueOrDefault(value, defaultValue) { return typeof value === 'undefined' ? defaultValue : value; } const toPercentage = (value, dimension) => typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 : value / dimension; const toDimension = (value, dimension) => typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 * dimension : +value; function callback(fn, args, thisArg) { if (fn && typeof fn.call === 'function') { return fn.apply(thisArg, args); } } function each(loopable, fn, thisArg, reverse) { let i, len, keys; if (isArray(loopable)) { len = loopable.length; if (reverse) { for (i = len - 1; i >= 0; i--) { fn.call(thisArg, loopable[i], i); } } else { for (i = 0; i < len; i++) { fn.call(thisArg, loopable[i], i); } } } else if (isObject(loopable)) { keys = Object.keys(loopable); len = keys.length; for (i = 0; i < len; i++) { fn.call(thisArg, loopable[keys[i]], keys[i]); } } } function _elementsEqual(a0, a1) { let i, ilen, v0, v1; if (!a0 || !a1 || a0.length !== a1.length) { return false; } for (i = 0, ilen = a0.length; i < ilen; ++i) { v0 = a0[i]; v1 = a1[i]; if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) { return false; } } return true; } function clone$1(source) { if (isArray(source)) { return source.map(clone$1); } if (isObject(source)) { const target = Object.create(null); const keys = Object.keys(source); const klen = keys.length; let k = 0; for (; k < klen; ++k) { target[keys[k]] = clone$1(source[keys[k]]); } return target; } return source; } function isValidKey(key) { return ['__proto__', 'prototype', 'constructor'].indexOf(key) === -1; } function _merger(key, target, source, options) { if (!isValidKey(key)) { return; } const tval = target[key]; const sval = source[key]; if (isObject(tval) && isObject(sval)) { merge(tval, sval, options); } else { target[key] = clone$1(sval); } } function merge(target, source, options) { const sources = isArray(source) ? source : [source]; const ilen = sources.length; if (!isObject(target)) { return target; } options = options || {}; const merger = options.merger || _merger; for (let i = 0; i < ilen; ++i) { source = sources[i]; if (!isObject(source)) { continue; } const keys = Object.keys(source); for (let k = 0, klen = keys.length; k < klen; ++k) { merger(keys[k], target, source, options); } } return target; } function mergeIf(target, source) { return merge(target, source, {merger: _mergerIf}); } function _mergerIf(key, target, source) { if (!isValidKey(key)) { return; } const tval = target[key]; const sval = source[key]; if (isObject(tval) && isObject(sval)) { mergeIf(tval, sval); } else if (!Object.prototype.hasOwnProperty.call(target, key)) { target[key] = clone$1(sval); } } function _deprecated(scope, value, previous, current) { if (value !== undefined) { console.warn(scope + ': "' + previous + '" is deprecated. Please use "' + current + '" instead'); } } const emptyString = ''; const dot = '.'; function indexOfDotOrLength(key, start) { const idx = key.indexOf(dot, start); return idx === -1 ? key.length : idx; } function resolveObjectKey(obj, key) { if (key === emptyString) { return obj; } let pos = 0; let idx = indexOfDotOrLength(key, pos); while (obj && idx > pos) { obj = obj[key.substr(pos, idx - pos)]; pos = idx + 1; idx = indexOfDotOrLength(key, pos); } return obj; } function _capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } const defined = (value) => typeof value !== 'undefined'; const isFunction = (value) => typeof value === 'function'; const setsEqual = (a, b) => { if (a.size !== b.size) { return false; } for (const item of a) { if (!b.has(item)) { return false; } } return true; }; const PI = Math.PI; const TAU = 2 * PI; const PITAU = TAU + PI; const INFINITY = Number.POSITIVE_INFINITY; const RAD_PER_DEG = PI / 180; const HALF_PI = PI / 2; const QUARTER_PI = PI / 4; const TWO_THIRDS_PI = PI * 2 / 3; const log10 = Math.log10; const sign = Math.sign; function niceNum(range) { const roundedRange = Math.round(range); range = almostEquals(range, roundedRange, range / 1000) ? roundedRange : range; const niceRange = Math.pow(10, Math.floor(log10(range))); const fraction = range / niceRange; const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10; return niceFraction * niceRange; } function _factorize(value) { const result = []; const sqrt = Math.sqrt(value); let i; for (i = 1; i < sqrt; i++) { if (value % i === 0) { result.push(i); result.push(value / i); } } if (sqrt === (sqrt | 0)) { result.push(sqrt); } result.sort((a, b) => a - b).pop(); return result; } function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } function almostEquals(x, y, epsilon) { return Math.abs(x - y) < epsilon; } function almostWhole(x, epsilon) { const rounded = Math.round(x); return ((rounded - epsilon) <= x) && ((rounded + epsilon) >= x); } function _setMinAndMaxByKey(array, target, property) { let i, ilen, value; for (i = 0, ilen = array.length; i < ilen; i++) { value = array[i][property]; if (!isNaN(value)) { target.min = Math.min(target.min, value); target.max = Math.max(target.max, value); } } } function toRadians(degrees) { return degrees * (PI / 180); } function toDegrees(radians) { return radians * (180 / PI); } function _decimalPlaces(x) { if (!isNumberFinite(x)) { return; } let e = 1; let p = 0; while (Math.round(x * e) / e !== x) { e *= 10; p++; } return p; } function getAngleFromPoint(centrePoint, anglePoint) { const distanceFromXCenter = anglePoint.x - centrePoint.x; const distanceFromYCenter = anglePoint.y - centrePoint.y; const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter); if (angle < (-0.5 * PI)) { angle += TAU; } return { angle, distance: radialDistanceFromCenter }; } function distanceBetweenPoints(pt1, pt2) { return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2)); } function _angleDiff(a, b) { return (a - b + PITAU) % TAU - PI; } function _normalizeAngle(a) { return (a % TAU + TAU) % TAU; } function _angleBetween(angle, start, end, sameAngleIsFullCircle) { const a = _normalizeAngle(angle); const s = _normalizeAngle(start); const e = _normalizeAngle(end); const angleToStart = _normalizeAngle(s - a); const angleToEnd = _normalizeAngle(e - a); const startToAngle = _normalizeAngle(a - s); const endToAngle = _normalizeAngle(a - e); return a === s || a === e || (sameAngleIsFullCircle && s === e) || (angleToStart > angleToEnd && startToAngle < endToAngle); } function _limitValue(value, min, max) { return Math.max(min, Math.min(max, value)); } function _int16Range(value) { return _limitValue(value, -32768, 32767); } const atEdge = (t) => t === 0 || t === 1; const elasticIn = (t, s, p) => -(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * TAU / p)); const elasticOut = (t, s, p) => Math.pow(2, -10 * t) * Math.sin((t - s) * TAU / p) + 1; const effects = { linear: t => t, easeInQuad: t => t * t, easeOutQuad: t => -t * (t - 2), easeInOutQuad: t => ((t /= 0.5) < 1) ? 0.5 * t * t : -0.5 * ((--t) * (t - 2) - 1), easeInCubic: t => t * t * t, easeOutCubic: t => (t -= 1) * t * t + 1, easeInOutCubic: t => ((t /= 0.5) < 1) ? 0.5 * t * t * t : 0.5 * ((t -= 2) * t * t + 2), easeInQuart: t => t * t * t * t, easeOutQuart: t => -((t -= 1) * t * t * t - 1), easeInOutQuart: t => ((t /= 0.5) < 1) ? 0.5 * t * t * t * t : -0.5 * ((t -= 2) * t * t * t - 2), easeInQuint: t => t * t * t * t * t, easeOutQuint: t => (t -= 1) * t * t * t * t + 1, easeInOutQuint: t => ((t /= 0.5) < 1) ? 0.5 * t * t * t * t * t : 0.5 * ((t -= 2) * t * t * t * t + 2), easeInSine: t => -Math.cos(t * HALF_PI) + 1, easeOutSine: t => Math.sin(t * HALF_PI), easeInOutSine: t => -0.5 * (Math.cos(PI * t) - 1), easeInExpo: t => (t === 0) ? 0 : Math.pow(2, 10 * (t - 1)), easeOutExpo: t => (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1, 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), easeInCirc: t => (t >= 1) ? t : -(Math.sqrt(1 - t * t) - 1), easeOutCirc: t => Math.sqrt(1 - (t -= 1) * t), easeInOutCirc: t => ((t /= 0.5) < 1) ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1), easeInElastic: t => atEdge(t) ? t : elasticIn(t, 0.075, 0.3), easeOutElastic: t => atEdge(t) ? t : elasticOut(t, 0.075, 0.3), easeInOutElastic(t) { const s = 0.1125; const p = 0.45; return atEdge(t) ? t : t < 0.5 ? 0.5 * elasticIn(t * 2, s, p) : 0.5 + 0.5 * elasticOut(t * 2 - 1, s, p); }, easeInBack(t) { const s = 1.70158; return t * t * ((s + 1) * t - s); }, easeOutBack(t) { const s = 1.70158; return (t -= 1) * t * ((s + 1) * t + s) + 1; }, easeInOutBack(t) { let s = 1.70158; if ((t /= 0.5) < 1) { return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s)); } return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); }, easeInBounce: t => 1 - effects.easeOutBounce(1 - t), easeOutBounce(t) { const m = 7.5625; const d = 2.75; if (t < (1 / d)) { return m * t * t; } if (t < (2 / d)) { return m * (t -= (1.5 / d)) * t + 0.75; } if (t < (2.5 / d)) { return m * (t -= (2.25 / d)) * t + 0.9375; } return m * (t -= (2.625 / d)) * t + 0.984375; }, easeInOutBounce: t => (t < 0.5) ? effects.easeInBounce(t * 2) * 0.5 : effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5, }; /*! * @kurkle/color v0.1.9 * https://github.com/kurkle/color#readme * (c) 2020 Jukka Kurkela * Released under the MIT License */ const map = {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}; const hex = '0123456789ABCDEF'; const h1 = (b) => hex[b & 0xF]; const h2 = (b) => hex[(b & 0xF0) >> 4] + hex[b & 0xF]; const eq = (b) => (((b & 0xF0) >> 4) === (b & 0xF)); function isShort(v) { return eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a); } function hexParse(str) { var len = str.length; var ret; if (str[0] === '#') { if (len === 4 || len === 5) { ret = { r: 255 & map[str[1]] * 17, g: 255 & map[str[2]] * 17, b: 255 & map[str[3]] * 17, a: len === 5 ? map[str[4]] * 17 : 255 }; } else if (len === 7 || len === 9) { ret = { r: map[str[1]] << 4 | map[str[2]], g: map[str[3]] << 4 | map[str[4]], b: map[str[5]] << 4 | map[str[6]], a: len === 9 ? (map[str[7]] << 4 | map[str[8]]) : 255 }; } } return ret; } function hexString(v) { var f = isShort(v) ? h1 : h2; return v ? '#' + f(v.r) + f(v.g) + f(v.b) + (v.a < 255 ? f(v.a) : '') : v; } function round(v) { return v + 0.5 | 0; } const lim = (v, l, h) => Math.max(Math.min(v, h), l); function p2b(v) { return lim(round(v * 2.55), 0, 255); } function n2b(v) { return lim(round(v * 255), 0, 255); } function b2n(v) { return lim(round(v / 2.55) / 100, 0, 1); } function n2p(v) { return lim(round(v * 100), 0, 100); } const RGB_RE = /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/; function rgbParse(str) { const m = RGB_RE.exec(str); let a = 255; let r, g, b; if (!m) { return; } if (m[7] !== r) { const v = +m[7]; a = 255 & (m[8] ? p2b(v) : v * 255); } r = +m[1]; g = +m[3]; b = +m[5]; r = 255 & (m[2] ? p2b(r) : r); g = 255 & (m[4] ? p2b(g) : g); b = 255 & (m[6] ? p2b(b) : b); return { r: r, g: g, b: b, a: a }; } function rgbString(v) { return v && ( v.a < 255 ? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})` : `rgb(${v.r}, ${v.g}, ${v.b})` ); } const HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/; function hsl2rgbn(h, s, l) { const a = s * Math.min(l, 1 - l); const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); return [f(0), f(8), f(4)]; } function hsv2rgbn(h, s, v) { const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0); return [f(5), f(3), f(1)]; } function hwb2rgbn(h, w, b) { const rgb = hsl2rgbn(h, 1, 0.5); let i; if (w + b > 1) { i = 1 / (w + b); w *= i; b *= i; } for (i = 0; i < 3; i++) { rgb[i] *= 1 - w - b; rgb[i] += w; } return rgb; } function rgb2hsl(v) { const range = 255; const r = v.r / range; const g = v.g / range; const b = v.b / range; const max = Math.max(r, g, b); const min = Math.min(r, g, b); const l = (max + min) / 2; let h, s, d; if (max !== min) { d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); h = max === r ? ((g - b) / d) + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4; h = h * 60 + 0.5; } return [h | 0, s || 0, l]; } function calln(f, a, b, c) { return ( Array.isArray(a) ? f(a[0], a[1], a[2]) : f(a, b, c) ).map(n2b); } function hsl2rgb(h, s, l) { return calln(hsl2rgbn, h, s, l); } function hwb2rgb(h, w, b) { return calln(hwb2rgbn, h, w, b); } function hsv2rgb(h, s, v) { return calln(hsv2rgbn, h, s, v); } function hue(h) { return (h % 360 + 360) % 360; } function hueParse(str) { const m = HUE_RE.exec(str); let a = 255; let v; if (!m) { return; } if (m[5] !== v) { a = m[6] ? p2b(+m[5]) : n2b(+m[5]); } const h = hue(+m[2]); const p1 = +m[3] / 100; const p2 = +m[4] / 100; if (m[1] === 'hwb') { v = hwb2rgb(h, p1, p2); } else if (m[1] === 'hsv') { v = hsv2rgb(h, p1, p2); } else { v = hsl2rgb(h, p1, p2); } return { r: v[0], g: v[1], b: v[2], a: a }; } function rotate(v, deg) { var h = rgb2hsl(v); h[0] = hue(h[0] + deg); h = hsl2rgb(h); v.r = h[0]; v.g = h[1]; v.b = h[2]; } function hslString(v) { if (!v) { return; } const a = rgb2hsl(v); const h = a[0]; const s = n2p(a[1]); const l = n2p(a[2]); return v.a < 255 ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})` : `hsl(${h}, ${s}%, ${l}%)`; } const map$1 = { x: 'dark', Z: 'light', Y: 're', X: 'blu', W: 'gr', V: 'medium', U: 'slate', A: 'ee', T: 'ol', S: 'or', B: 'ra', C: 'lateg', D: 'ights', R: 'in', Q: 'turquois', E: 'hi', P: 'ro', O: 'al', N: 'le', M: 'de', L: 'yello', F: 'en', K: 'ch', G: 'arks', H: 'ea', I: 'ightg', J: 'wh' }; const names = { OiceXe: 'f0f8ff', antiquewEte: 'faebd7', aqua: 'ffff', aquamarRe: '7fffd4', azuY: 'f0ffff', beige: 'f5f5dc', bisque: 'ffe4c4', black: '0', blanKedOmond: 'ffebcd', Xe: 'ff', XeviTet: '8a2be2', bPwn: 'a52a2a', burlywood: 'deb887', caMtXe: '5f9ea0', KartYuse: '7fff00', KocTate: 'd2691e', cSO: 'ff7f50', cSnflowerXe: '6495ed', cSnsilk: 'fff8dc', crimson: 'dc143c', cyan: 'ffff', xXe: '8b', xcyan: '8b8b', xgTMnPd: 'b8860b', xWay: 'a9a9a9', xgYF: '6400', xgYy: 'a9a9a9', xkhaki: 'bdb76b', xmagFta: '8b008b', xTivegYF: '556b2f', xSange: 'ff8c00', xScEd: '9932cc', xYd: '8b0000', xsOmon: 'e9967a', xsHgYF: '8fbc8f', xUXe: '483d8b', xUWay: '2f4f4f', xUgYy: '2f4f4f', xQe: 'ced1', xviTet: '9400d3', dAppRk: 'ff1493', dApskyXe: 'bfff', dimWay: '696969', dimgYy: '696969', dodgerXe: '1e90ff', fiYbrick: 'b22222', flSOwEte: 'fffaf0', foYstWAn: '228b22', fuKsia: 'ff00ff', gaRsbSo: 'dcdcdc', ghostwEte: 'f8f8ff', gTd: 'ffd700', gTMnPd: 'daa520', Way: '808080', gYF: '8000', gYFLw: 'adff2f', gYy: '808080', honeyMw: 'f0fff0', hotpRk: 'ff69b4', RdianYd: 'cd5c5c', Rdigo: '4b0082', ivSy: 'fffff0', khaki: 'f0e68c', lavFMr: 'e6e6fa', lavFMrXsh: 'fff0f5', lawngYF: '7cfc00', NmoncEffon: 'fffacd', ZXe: 'add8e6', ZcSO: 'f08080', Zcyan: 'e0ffff', ZgTMnPdLw: 'fafad2', ZWay: 'd3d3d3', ZgYF: '90ee90', ZgYy: 'd3d3d3', ZpRk: 'ffb6c1', ZsOmon: 'ffa07a', ZsHgYF: '20b2aa', ZskyXe: '87cefa', ZUWay: '778899', ZUgYy: '778899', ZstAlXe: 'b0c4de', ZLw: 'ffffe0', lime: 'ff00', limegYF: '32cd32', lRF: 'faf0e6', magFta: 'ff00ff', maPon: '800000', VaquamarRe: '66cdaa', VXe: 'cd', VScEd: 'ba55d3', VpurpN: '9370db', VsHgYF: '3cb371', VUXe: '7b68ee', VsprRggYF: 'fa9a', VQe: '48d1cc', VviTetYd: 'c71585', midnightXe: '191970', mRtcYam: 'f5fffa', mistyPse: 'ffe4e1', moccasR: 'ffe4b5', navajowEte: 'ffdead', navy: '80', Tdlace: 'fdf5e6', Tive: '808000', TivedBb: '6b8e23', Sange: 'ffa500', SangeYd: 'ff4500', ScEd: 'da70d6', pOegTMnPd: 'eee8aa', pOegYF: '98fb98', pOeQe: 'afeeee', pOeviTetYd: 'db7093', papayawEp: 'ffefd5', pHKpuff: 'ffdab9', peru: 'cd853f', pRk: 'ffc0cb', plum: 'dda0dd', powMrXe: 'b0e0e6', purpN: '800080', YbeccapurpN: '663399', Yd: 'ff0000', Psybrown: 'bc8f8f', PyOXe: '4169e1', saddNbPwn: '8b4513', sOmon: 'fa8072', sandybPwn: 'f4a460', sHgYF: '2e8b57', sHshell: 'fff5ee', siFna: 'a0522d', silver: 'c0c0c0', skyXe: '87ceeb', UXe: '6a5acd', UWay: '708090', UgYy: '708090', snow: 'fffafa', sprRggYF: 'ff7f', stAlXe: '4682b4', tan: 'd2b48c', teO: '8080', tEstN: 'd8bfd8', tomato: 'ff6347', Qe: '40e0d0', viTet: 'ee82ee', JHt: 'f5deb3', wEte: 'ffffff', wEtesmoke: 'f5f5f5', Lw: 'ffff00', LwgYF: '9acd32' }; function unpack() { const unpacked = {}; const keys = Object.keys(names); const tkeys = Object.keys(map$1); let i, j, k, ok, nk; for (i = 0; i < keys.length; i++) { ok = nk = keys[i]; for (j = 0; j < tkeys.length; j++) { k = tkeys[j]; nk = nk.replace(k, map$1[k]); } k = parseInt(names[ok], 16); unpacked[nk] = [k >> 16 & 0xFF, k >> 8 & 0xFF, k & 0xFF]; } return unpacked; } let names$1; function nameParse(str) { if (!names$1) { names$1 = unpack(); names$1.transparent = [0, 0, 0, 0]; } const a = names$1[str.toLowerCase()]; return a && { r: a[0], g: a[1], b: a[2], a: a.length === 4 ? a[3] : 255 }; } function modHSL(v, i, ratio) { if (v) { let tmp = rgb2hsl(v); tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1)); tmp = hsl2rgb(tmp); v.r = tmp[0]; v.g = tmp[1]; v.b = tmp[2]; } } function clone(v, proto) { return v ? Object.assign(proto || {}, v) : v; } function fromObject(input) { var v = {r: 0, g: 0, b: 0, a: 255}; if (Array.isArray(input)) { if (input.length >= 3) { v = {r: input[0], g: input[1], b: input[2], a: 255}; if (input.length > 3) { v.a = n2b(input[3]); } } } else { v = clone(input, {r: 0, g: 0, b: 0, a: 1}); v.a = n2b(v.a); } return v; } function functionParse(str) { if (str.charAt(0) === 'r') { return rgbParse(str); } return hueParse(str); } class Color { constructor(input) { if (input instanceof Color) { return input; } const type = typeof input; let v; if (type === 'object') { v = fromObject(input); } else if (type === 'string') { v = hexParse(input) || nameParse(input) || functionParse(input); } this._rgb = v; this._valid = !!v; } get valid() { return this._valid; } get rgb() { var v = clone(this._rgb); if (v) { v.a = b2n(v.a); } return v; } set rgb(obj) { this._rgb = fromObject(obj); } rgbString() { return this._valid ? rgbString(this._rgb) : this._rgb; } hexString() { return this._valid ? hexString(this._rgb) : this._rgb; } hslString() { return this._valid ? hslString(this._rgb) : this._rgb; } mix(color, weight) { const me = this; if (color) { const c1 = me.rgb; const c2 = color.rgb; let w2; const p = weight === w2 ? 0.5 : weight; const w = 2 * p - 1; const a = c1.a - c2.a; const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0; w2 = 1 - w1; c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5; c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5; c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5; c1.a = p * c1.a + (1 - p) * c2.a; me.rgb = c1; } return me; } clone() { return new Color(this.rgb); } alpha(a) { this._rgb.a = n2b(a); return this; } clearer(ratio) { const rgb = this._rgb; rgb.a *= 1 - ratio; return this; } greyscale() { const rgb = this._rgb; const val = round(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11); rgb.r = rgb.g = rgb.b = val; return this; } opaquer(ratio) { const rgb = this._rgb; rgb.a *= 1 + ratio; return this; } negate() { const v = this._rgb; v.r = 255 - v.r; v.g = 255 - v.g; v.b = 255 - v.b; return this; } lighten(ratio) { modHSL(this._rgb, 2, ratio); return this; } darken(ratio) { modHSL(this._rgb, 2, -ratio); return this; } saturate(ratio) { modHSL(this._rgb, 1, ratio); return this; } desaturate(ratio) { modHSL(this._rgb, 1, -ratio); return this; } rotate(deg) { rotate(this._rgb, deg); return this; } } function index_esm(input) { return new Color(input); } const isPatternOrGradient = (value) => value instanceof CanvasGradient || value instanceof CanvasPattern; function color(value) { return isPatternOrGradient(value) ? value : index_esm(value); } function getHoverColor(value) { return isPatternOrGradient(value) ? value : index_esm(value).saturate(0.5).darken(0.1).hexString(); } const overrides = Object.create(null); const descriptors = Object.create(null); function getScope$1(node, key) { if (!key) { return node; } const keys = key.split('.'); for (let i = 0, n = keys.length; i < n; ++i) { const k = keys[i]; node = node[k] || (node[k] = Object.create(null)); } return node; } function set(root, scope, values) { if (typeof scope === 'string') { return merge(getScope$1(root, scope), values); } return merge(getScope$1(root, ''), scope); } class Defaults { constructor(_descriptors) { this.animation = undefined; this.backgroundColor = 'rgba(0,0,0,0.1)'; this.borderColor = 'rgba(0,0,0,0.1)'; this.color = '#666'; this.datasets = {}; this.devicePixelRatio = (context) => context.chart.platform.getDevicePixelRatio(); this.elements = {}; this.events = [ 'mousemove', 'mouseout', 'click', 'touchstart', 'touchmove' ]; this.font = { family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", size: 12, style: 'normal', lineHeight: 1.2, weight: null }; this.hover = {}; this.hoverBackgroundColor = (ctx, options) => getHoverColor(options.backgroundColor); this.hoverBorderColor = (ctx, options) => getHoverColor(options.borderColor); this.hoverColor = (ctx, options) => getHoverColor(options.color); this.indexAxis = 'x'; this.interaction = { mode: 'nearest', intersect: true }; this.maintainAspectRatio = true; this.onHover = null; this.onClick = null; this.parsing = true; this.plugins = {}; this.responsive = true; this.scale = undefined; this.scales = {}; this.showLine = true; this.describe(_descriptors); } set(scope, values) { return set(this, scope, values); } get(scope) { return getScope$1(this, scope); } describe(scope, values) { return set(descriptors, scope, values); } override(scope, values) { return set(overrides, scope, values); } route(scope, name, targetScope, targetName) { const scopeObject = getScope$1(this, scope); const targetScopeObject = getScope$1(this, targetScope); const privateName = '_' + name; Object.defineProperties(scopeObject, { [privateName]: { value: scopeObject[name], writable: true }, [name]: { enumerable: true, get() { const local = this[privateName]; const target = targetScopeObject[targetName]; if (isObject(local)) { return Object.assign({}, target, local); } return valueOrDefault(local, target); }, set(value) { this[privateName] = value; } } }); } } var defaults = new Defaults({ _scriptable: (name) => !name.startsWith('on'), _indexable: (name) => name !== 'events', hover: { _fallback: 'interaction' }, interaction: { _scriptable: false, _indexable: false, } }); function toFontString(font) { if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) { return null; } return (font.style ? font.style + ' ' : '') + (font.weight ? font.weight + ' ' : '') + font.size + 'px ' + font.family; } function _measureText(ctx, data, gc, longest, string) { let textWidth = data[string]; if (!textWidth) { textWidth = data[string] = ctx.measureText(string).width; gc.push(string); } if (textWidth > longest) { longest = textWidth; } return longest; } function _longestText(ctx, font, arrayOfThings, cache) { cache = cache || {}; let data = cache.data = cache.data || {}; let gc = cache.garbageCollect = cache.garbageCollect || []; if (cache.font !== font) { data = cache.data = {}; gc = cache.garbageCollect = []; cache.font = font; } ctx.save(); ctx.font = font; let longest = 0; const ilen = arrayOfThings.length; let i, j, jlen, thing, nestedThing; for (i = 0; i < ilen; i++) { thing = arrayOfThings[i]; if (thing !== undefined && thing !== null && isArray(thing) !== true) { longest = _measureText(ctx, data, gc, longest, thing); } else if (isArray(thing)) { for (j = 0, jlen = thing.length; j < jlen; j++) { nestedThing = thing[j]; if (nestedThing !== undefined && nestedThing !== null && !isArray(nestedThing)) { longest = _measureText(ctx, data, gc, longest, nestedThing); } } } } ctx.restore(); const gcLen = gc.length / 2; if (gcLen > arrayOfThings.length) { for (i = 0; i < gcLen; i++) { delete data[gc[i]]; } gc.splice(0, gcLen); } return longest; } function _alignPixel(chart, pixel, width) { const devicePixelRatio = chart.currentDevicePixelRatio; const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0; return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth; } function clearCanvas(canvas, ctx) { ctx = ctx || canvas.getContext('2d'); ctx.save(); ctx.resetTransform(); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.restore(); } function drawPoint(ctx, options, x, y) { let type, xOffset, yOffset, size, cornerRadius; const style = options.pointStyle; const rotation = options.rotation; const radius = options.radius; let rad = (rotation || 0) * RAD_PER_DEG; if (style && typeof style === 'object') { type = style.toString(); if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { ctx.save(); ctx.translate(x, y); ctx.rotate(rad); ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height); ctx.restore(); return; } } if (isNaN(radius) || radius <= 0) { return; } ctx.beginPath(); switch (style) { default: ctx.arc(x, y, radius, 0, TAU); ctx.closePath(); break; case 'triangle': ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); rad += TWO_THIRDS_PI; ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); rad += TWO_THIRDS_PI; ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); ctx.closePath(); break; case 'rectRounded': cornerRadius = radius * 0.516; size = radius - cornerRadius; xOffset = Math.cos(rad + QUARTER_PI) * size; yOffset = Math.sin(rad + QUARTER_PI) * size; ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI); ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad); ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI); ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI); ctx.closePath(); break; case 'rect': if (!rotation) { size = Math.SQRT1_2 * radius; ctx.rect(x - size, y - size, 2 * size, 2 * size); break; } rad += QUARTER_PI; case 'rectRot': xOffset = Math.cos(rad) * radius; yOffset = Math.sin(rad) * radius; ctx.moveTo(x - xOffset, y - yOffset); ctx.lineTo(x + yOffset, y - xOffset); ctx.lineTo(x + xOffset, y + yOffset); ctx.lineTo(x - yOffset, y + xOffset); ctx.closePath(); break; case 'crossRot': rad += QUARTER_PI; case 'cross': xOffset = Math.cos(rad) * radius; yOffset = Math.sin(rad) * radius; ctx.moveTo(x - xOffset, y - yOffset); ctx.lineTo(x + xOffset, y + yOffset); ctx.moveTo(x + yOffset, y - xOffset); ctx.lineTo(x - yOffset, y + xOffset); break; case 'star': xOffset = Math.cos(rad) * radius; yOffset = Math.sin(rad) * radius; ctx.moveTo(x - xOffset, y - yOffset); ctx.lineTo(x + xOffset, y + yOffset); ctx.moveTo(x + yOffset, y - xOffset); ctx.lineTo(x - yOffset, y + xOffset); rad += QUARTER_PI; xOffset = Math.cos(rad) * radius; yOffset = Math.sin(rad) * radius; ctx.moveTo(x - xOffset, y - yOffset); ctx.lineTo(x + xOffset, y + yOffset); ctx.moveTo(x + yOffset, y - xOffset); ctx.lineTo(x - yOffset, y + xOffset); break; case 'line': xOffset = Math.cos(rad) * radius; yOffset = Math.sin(rad) * radius; ctx.moveTo(x - xOffset, y - yOffset); ctx.lineTo(x + xOffset, y + yOffset); break; case 'dash': ctx.moveTo(x, y); ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius); break; } ctx.fill(); if (options.borderWidth > 0) { ctx.stroke(); } } function _isPointInArea(point, area, margin) { margin = margin || 0.5; return !area || (point && point.x > area.left - margin && point.x < area.right + margin && point.y > area.top - margin && point.y < area.bottom + margin); } function clipArea(ctx, area) { ctx.save(); ctx.beginPath(); ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top); ctx.clip(); } function unclipArea(ctx) { ctx.restore(); } function _steppedLineTo(ctx, previous, target, flip, mode) { if (!previous) { return ctx.lineTo(target.x, target.y); } if (mode === 'middle') { const midpoint = (previous.x + target.x) / 2.0; ctx.lineTo(midpoint, previous.y); ctx.lineTo(midpoint, target.y); } else if (mode === 'after' !== !!flip) { ctx.lineTo(previous.x, target.y); } else { ctx.lineTo(target.x, previous.y); } ctx.lineTo(target.x, target.y); } function _bezierCurveTo(ctx, previous, target, flip) { if (!previous) { return ctx.lineTo(target.x, target.y); } 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); } function renderText(ctx, text, x, y, font, opts = {}) { const lines = isArray(text) ? text : [text]; const stroke = opts.strokeWidth > 0 && opts.strokeColor !== ''; let i, line; ctx.save(); ctx.font = font.string; setRenderOpts(ctx, opts); for (i = 0; i < lines.length; ++i) { line = lines[i]; if (stroke) { if (opts.strokeColor) { ctx.strokeStyle = opts.strokeColor; } if (!isNullOrUndef(opts.strokeWidth)) { ctx.lineWidth = opts.strokeWidth; } ctx.strokeText(line, x, y, opts.maxWidth); } ctx.fillText(line, x, y, opts.maxWidth); decorateText(ctx, x, y, line, opts); y += font.lineHeight; } ctx.restore(); } function setRenderOpts(ctx, opts) { if (opts.translation) { ctx.translate(opts.translation[0], opts.translation[1]); } if (!isNullOrUndef(opts.rotation)) { ctx.rotate(opts.rotation); } if (opts.color) { ctx.fillStyle = opts.color; } if (opts.textAlign) { ctx.textAlign = opts.textAlign; } if (opts.textBaseline) { ctx.textBaseline = opts.textBaseline; } } function decorateText(ctx, x, y, line, opts) { if (opts.strikethrough || opts.underline) { const metrics = ctx.measureText(line); const left = x - metrics.actualBoundingBoxLeft; const right = x + metrics.actualBoundingBoxRight; const top = y - metrics.actualBoundingBoxAscent; const bottom = y + metrics.actualBoundingBoxDescent; const yDecoration = opts.strikethrough ? (top + bottom) / 2 : bottom; ctx.strokeStyle = ctx.fillStyle; ctx.beginPath(); ctx.lineWidth = opts.decorationWidth || 2; ctx.moveTo(left, yDecoration); ctx.lineTo(right, yDecoration); ctx.stroke(); } } function addRoundedRectPath(ctx, rect) { const {x, y, w, h, radius} = rect; ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, -HALF_PI, PI, true); ctx.lineTo(x, y + h - radius.bottomLeft); ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true); ctx.lineTo(x + w - radius.bottomRight, y + h); ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true); ctx.lineTo(x + w, y + radius.topRight); ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true); ctx.lineTo(x + radius.topLeft, y); } const LINE_HEIGHT = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/); const FONT_STYLE = new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/); function toLineHeight(value, size) { const matches = ('' + value).match(LINE_HEIGHT); if (!matches || matches[1] === 'normal') { return size * 1.2; } value = +matches[2]; switch (matches[3]) { case 'px': return value; case '%': value /= 100; break; } return size * value; } const numberOrZero = v => +v || 0; function _readValueToProps(value, props) { const ret = {}; const objProps = isObject(props); const keys = objProps ? Object.keys(props) : props; const read = isObject(value) ? objProps ? prop => valueOrDefault(value[prop], value[props[prop]]) : prop => value[prop] : () => value; for (const prop of keys) { ret[prop] = numberOrZero(read(prop)); } return ret; } function toTRBL(value) { return _readValueToProps(value, {top: 'y', right: 'x', bottom: 'y', left: 'x'}); } function toTRBLCorners(value) { return _readValueToProps(value, ['topLeft', 'topRight', 'bottomLeft', 'bottomRight']); } function toPadding(value) { const obj = toTRBL(value); obj.width = obj.left + obj.right; obj.height = obj.top + obj.bottom; return obj; } function toFont(options, fallback) { options = options || {}; fallback = fallback || defaults.font; let size = valueOrDefault(options.size, fallback.size); if (typeof size === 'string') { size = parseInt(size, 10); } let style = valueOrDefault(options.style, fallback.style); if (style && !('' + style).match(FONT_STYLE)) { console.warn('Invalid font style specified: "' + style + '"'); style = ''; } const font = { family: valueOrDefault(options.family, fallback.family), lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size), size, style, weight: valueOrDefault(options.weight, fallback.weight), string: '' }; font.string = toFontString(font); return font; } function resolve(inputs, context, index, info) { let cacheable = true; let i, ilen, value; for (i = 0, ilen = inputs.length; i < ilen; ++i) { value = inputs[i]; if (value === undefined) { continue; } if (context !== undefined && typeof value === 'function') { value = value(context); cacheable = false; } if (index !== undefined && isArray(value)) { value = value[index % value.length]; cacheable = false; } if (value !== undefined) { if (info && !cacheable) { info.cacheable = false; } return value; } } } function _addGrace(minmax, grace) { const {min, max} = minmax; return { min: min - Math.abs(toDimension(grace, min)), max: max + toDimension(grace, max) }; } function _lookup(table, value, cmp) { cmp = cmp || ((index) => table[index] < value); let hi = table.length - 1; let lo = 0; let mid; while (hi - lo > 1) { mid = (lo + hi) >> 1; if (cmp(mid)) { lo = mid; } else { hi = mid; } } return {lo, hi}; } const _lookupByKey = (table, key, value) => _lookup(table, value, index => table[index][key] < value); const _rlookupByKey = (table, key, value) => _lookup(table, value, index => table[index][key] >= value); function _filterBetween(values, min, max) { let start = 0; let end = values.length; while (start < end && values[start] < min) { start++; } while (end > start && values[end - 1] > max) { end--; } return start > 0 || end < values.length ? values.slice(start, end) : values; } const arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift']; function listenArrayEvents(array, listener) { if (array._chartjs) { array._chartjs.listeners.push(listener); return; } Object.defineProperty(array, '_chartjs', { configurable: true, enumerable: false, value: { listeners: [listener] } }); arrayEvents.forEach((key) => { const method = '_onData' + _capitalize(key); const base = array[key]; Object.defineProperty(array, key, { configurable: true, enumerable: false, value(...args) { const res = base.apply(this, args); array._chartjs.listeners.forEach((object) => { if (typeof object[method] === 'function') { object[method](...args); } }); return res; } }); }); } function unlistenArrayEvents(array, listener) { const stub = array._chartjs; if (!stub) { return; } const listeners = stub.listeners; const index = listeners.indexOf(listener); if (index !== -1) { listeners.splice(index, 1); } if (listeners.length > 0) { return; } arrayEvents.forEach((key) => { delete array[key]; }); delete array._chartjs; } function _arrayUnique(items) { const set = new Set(); let i, ilen; for (i = 0, ilen = items.length; i < ilen; ++i) { set.add(items[i]); } if (set.size === ilen) { return items; } return Array.from(set); } function _createResolver(scopes, prefixes = [''], rootScopes = scopes, fallback, getTarget = () => scopes[0]) { if (!defined(fallback)) { fallback = _resolve('_fallback', scopes); } const cache = { [Symbol.toStringTag]: 'Object', _cacheable: true, _scopes: scopes, _rootScopes: rootScopes, _fallback: fallback, _getTarget: getTarget, override: (scope) => _createResolver([scope, ...scopes], prefixes, rootScopes, fallback), }; return new Proxy(cache, { deleteProperty(target, prop) { delete target[prop]; delete target._keys; delete scopes[0][prop]; return true; }, get(target, prop) { return _cached(target, prop, () => _resolveWithPrefixes(prop, prefixes, scopes, target)); }, getOwnPropertyDescriptor(target, prop) { return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop); }, getPrototypeOf() { return Reflect.getPrototypeOf(scopes[0]); }, has(target, prop) { return getKeysFromAllScopes(target).includes(prop); }, ownKeys(target) { return getKeysFromAllScopes(target); }, set(target, prop, value) { const storage = target._storage || (target._storage = getTarget()); storage[prop] = value; delete target[prop]; delete target._keys; return true; } }); } function _attachContext(proxy, context, subProxy, descriptorDefaults) { const cache = { _cacheable: false, _proxy: proxy, _context: context, _subProxy: subProxy, _stack: new Set(), _descriptors: _descriptors(proxy, descriptorDefaults), setContext: (ctx) => _attachContext(proxy, ctx, subProxy, descriptorDefaults), override: (scope) => _attachContext(proxy.override(scope), context, subProxy, descriptorDefaults) }; return new Proxy(cache, { deleteProperty(target, prop) { delete target[prop]; delete proxy[prop]; return true; }, get(target, prop, receiver) { return _cached(target, prop, () => _resolveWithContext(target, prop, receiver)); }, getOwnPropertyDescriptor(target, prop) { return target._descriptors.allKeys ? Reflect.has(proxy, prop) ? {enumerable: true, configurable: true} : undefined : Reflect.getOwnPropertyDescriptor(proxy, prop); }, getPrototypeOf() { return Reflect.getPrototypeOf(proxy); }, has(target, prop) { return Reflect.has(proxy, prop); }, ownKeys() { return Reflect.ownKeys(proxy); }, set(target, prop, value) { proxy[prop] = value; delete target[prop]; return true; } }); } function _descriptors(proxy, defaults = {scriptable: true, indexable: true}) { const {_scriptable = defaults.scriptable, _indexable = defaults.indexable, _allKeys = defaults.allKeys} = proxy; return { allKeys: _allKeys, scriptable: _scriptable, indexable: _indexable, isScriptable: isFunction(_scriptable) ? _scriptable : () => _scriptable, isIndexable: isFunction(_indexable) ? _indexable : () => _indexable }; } const readKey = (prefix, name) => prefix ? prefix + _capitalize(name) : name; const needsSubResolver = (prop, value) => isObject(value) && prop !== 'adapters'; function _cached(target, prop, resolve) { let value = target[prop]; if (defined(value)) { return value; } value = resolve(); if (defined(value)) { target[prop] = value; } return value; } function _resolveWithContext(target, prop, receiver) { const {_proxy, _context, _subProxy, _descriptors: descriptors} = target; let value = _proxy[prop]; if (isFunction(value) && descriptors.isScriptable(prop)) { value = _resolveScriptable(prop, value, target, receiver); } if (isArray(value) && value.length) { value = _resolveArray(prop, value, target, descriptors.isIndexable); } if (needsSubResolver(prop, value)) { value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors); } return value; } function _resolveScriptable(prop, value, target, receiver) { const {_proxy, _context, _subProxy, _stack} = target; if (_stack.has(prop)) { throw new Error('Recursion detected: ' + Array.from(_stack).join('->') + '->' + prop); } _stack.add(prop); value = value(_context, _subProxy || receiver); _stack.delete(prop); if (isObject(value)) { value = createSubResolver(_proxy._scopes, _proxy, prop, value); } return value; } function _resolveArray(prop, value, target, isIndexable) { const {_proxy, _context, _subProxy, _descriptors: descriptors} = target; if (defined(_context.index) && isIndexable(prop)) { value = value[_context.index % value.length]; } else if (isObject(value[0])) { const arr = value; const scopes = _proxy._scopes.filter(s => s !== arr); value = []; for (const item of arr) { const resolver = createSubResolver(scopes, _proxy, prop, item); value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors)); } } return value; } function resolveFallback(fallback, prop, value) { return isFunction(fallback) ? fallback(prop, value) : fallback; } const getScope = (key, parent) => key === true ? parent : typeof key === 'string' ? resolveObjectKey(parent, key) : undefined; function addScopes(set, parentScopes, key, parentFallback) { for (const parent of parentScopes) { const scope = getScope(key, parent); if (scope) { set.add(scope); const fallback = resolveFallback(scope._fallback, key, scope); if (defined(fallback) && fallback !== key && fallback !== parentFallback) { return fallback; } } else if (scope === false && defined(parentFallback) && key !== parentFallback) { return null; } } return false; } function createSubResolver(parentScopes, resolver, prop, value) { const rootScopes = resolver._rootScopes; const fallback = resolveFallback(resolver._fallback, prop, value); const allScopes = [...parentScopes, ...rootScopes]; const set = new Set(); set.add(value); let key = addScopesFromKey(set, allScopes, prop, fallback || prop); if (key === null) { return false; } if (defined(fallback) && fallback !== prop) { key = addScopesFromKey(set, allScopes, fallback, key); if (key === null) { return false; } } return _createResolver(Array.from(set), [''], rootScopes, fallback, () => subGetTarget(resolver, prop, value)); } function addScopesFromKey(set, allScopes, key, fallback) { while (key) { key = addScopes(set, allScopes, key, fallback); } return key; } function subGetTarget(resolver, prop, value) { const parent = resolver._getTarget(); if (!(prop in parent)) { parent[prop] = {}; } const target = parent[prop]; if (isArray(target) && isObject(value)) { return value; } return target; } function _resolveWithPrefixes(prop, prefixes, scopes, proxy) { let value; for (const prefix of prefixes) { value = _resolve(readKey(prefix, prop), scopes); if (defined(value)) { return needsSubResolver(prop, value) ? createSubResolver(scopes, proxy, prop, value) : value; } } } function _resolve(key, scopes) { for (const scope of scopes) { if (!scope) { continue; } const value = scope[key]; if (defined(value)) { return value; } } } function getKeysFromAllScopes(target) { let keys = target._keys; if (!keys) { keys = target._keys = resolveKeysFromAllScopes(target._scopes); } return keys; } function resolveKeysFromAllScopes(scopes) { const set = new Set(); for (const scope of scopes) { for (const key of Object.keys(scope).filter(k => !k.startsWith('_'))) { set.add(key); } } return Array.from(set); } const EPSILON = Number.EPSILON || 1e-14; const getPoint = (points, i) => i < points.length && !points[i].skip && points[i]; const getValueAxis = (indexAxis) => indexAxis === 'x' ? 'y' : 'x'; function splineCurve(firstPoint, middlePoint, afterPoint, t) { const previous = firstPoint.skip ? middlePoint : firstPoint; const current = middlePoint; const next = afterPoint.skip ? middlePoint : afterPoint; const d01 = distanceBetweenPoints(current, previous); const d12 = distanceBetweenPoints(next, current); let s01 = d01 / (d01 + d12); let s12 = d12 / (d01 + d12); s01 = isNaN(s01) ? 0 : s01; s12 = isNaN(s12) ? 0 : s12; const fa = t * s01; const fb = t * s12; return { previous: { x: current.x - fa * (next.x - previous.x), y: current.y - fa * (next.y - previous.y) }, next: { x: current.x + fb * (next.x - previous.x), y: current.y + fb * (next.y - previous.y) } }; } function monotoneAdjust(points, deltaK, mK) { const pointsLen = points.length; let alphaK, betaK, tauK, squaredMagnitude, pointCurrent; let pointAfter = getPoint(points, 0); for (let i = 0; i < pointsLen - 1; ++i) { pointCurrent = pointAfter; pointAfter = getPoint(points, i + 1); if (!pointCurrent || !pointAfter) { continue; } if (almostEquals(deltaK[i], 0, EPSILON)) { mK[i] = mK[i + 1] = 0; continue; } alphaK = mK[i] / deltaK[i]; betaK = mK[i + 1] / deltaK[i]; squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2); if (squaredMagnitude <= 9) { continue; } tauK = 3 / Math.sqrt(squaredMagnitude); mK[i] = alphaK * tauK * deltaK[i]; mK[i + 1] = betaK * tauK * deltaK[i]; } } function monotoneCompute(points, mK, indexAxis = 'x') { const valueAxis = getValueAxis(indexAxis); const pointsLen = points.length; let delta, pointBefore, pointCurrent; let pointAfter = getPoint(points, 0); for (let i = 0; i < pointsLen; ++i) { pointBefore = pointCurrent; pointCurrent = pointAfter; pointAfter = getPoint(points, i + 1); if (!pointCurrent) { continue; } const iPixel = pointCurrent[indexAxis]; const vPixel = pointCurrent[valueAxis]; if (pointBefore) { delta = (iPixel - pointBefore[indexAxis]) / 3; pointCurrent[`cp1${indexAxis}`] = iPixel - delta; pointCurrent[`cp1${valueAxis}`] = vPixel - delta * mK[i]; } if (pointAfter) { delta = (pointAfter[indexAxis] - iPixel) / 3; pointCurrent[`cp2${indexAxis}`] = iPixel + delta; pointCurrent[`cp2${valueAxis}`] = vPixel + delta * mK[i]; } } } function splineCurveMonotone(points, indexAxis = 'x') { const valueAxis = getValueAxis(indexAxis); const pointsLen = points.length; const deltaK = Array(pointsLen).fill(0); const mK = Array(pointsLen); let i, pointBefore, pointCurrent; let pointAfter = getPoint(points, 0); for (i = 0; i < pointsLen; ++i) { pointBefore = pointCurrent; pointCurrent = pointAfter; pointAfter = getPoint(points, i + 1); if (!pointCurrent) { continue; } if (pointAfter) { const slopeDelta = pointAfter[indexAxis] - pointCurrent[indexAxis]; deltaK[i] = slopeDelta !== 0 ? (pointAfter[valueAxis] - pointCurrent[valueAxis]) / slopeDelta : 0; } mK[i] = !pointBefore ? deltaK[i] : !pointAfter ? deltaK[i - 1] : (sign(deltaK[i - 1]) !== sign(deltaK[i])) ? 0 : (deltaK[i - 1] + deltaK[i]) / 2; } monotoneAdjust(points, deltaK, mK); monotoneCompute(points, mK, indexAxis); } function capControlPoint(pt, min, max) { return Math.max(Math.min(pt, max), min); } function capBezierPoints(points, area) { let i, ilen, point, inArea, inAreaPrev; let inAreaNext = _isPointInArea(points[0], area); for (i = 0, ilen = points.length; i < ilen; ++i) { inAreaPrev = inArea; inArea = inAreaNext; inAreaNext = i < ilen - 1 && _isPointInArea(points[i + 1], area); if (!inArea) { continue; } point = points[i]; if (inAreaPrev) { point.cp1x = capControlPoint(point.cp1x, area.left, area.right); point.cp1y = capControlPoint(point.cp1y, area.top, area.bottom); } if (inAreaNext) { point.cp2x = capControlPoint(point.cp2x, area.left, area.right); point.cp2y = capControlPoint(point.cp2y, area.top, area.bottom); } } } function _updateBezierControlPoints(points, options, area, loop, indexAxis) { let i, ilen, point, controlPoints; if (options.spanGaps) { points = points.filter((pt) => !pt.skip); } if (options.cubicInterpolationMode === 'monotone') { splineCurveMonotone(points, indexAxis); } else { let prev = loop ? points[points.length - 1] : points[0]; for (i = 0, ilen = points.length; i < ilen; ++i) { point = points[i]; controlPoints = splineCurve( prev, point, points[Math.min(i + 1, ilen - (loop ? 0 : 1)) % ilen], options.tension ); point.cp1x = controlPoints.previous.x; point.cp1y = controlPoints.previous.y; point.cp2x = controlPoints.next.x; point.cp2y = controlPoints.next.y; prev = point; } } if (options.capBezierPoints) { capBezierPoints(points, area); } } function _isDomSupported() { return typeof window !== 'undefined' && typeof document !== 'undefined'; } function _getParentNode(domNode) { let parent = domNode.parentNode; if (parent && parent.toString() === '[object ShadowRoot]') { parent = parent.host; } return parent; } function parseMaxStyle(styleValue, node, parentProperty) { let valueInPixels; if (typeof styleValue === 'string') { valueInPixels = parseInt(styleValue, 10); if (styleValue.indexOf('%') !== -1) { valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty]; } } else { valueInPixels = styleValue; } return valueInPixels; } const getComputedStyle = (element) => window.getComputedStyle(element, null); function getStyle(el, property) { return getComputedStyle(el).getPropertyValue(property); } const positions = ['top', 'right', 'bottom', 'left']; function getPositionedStyle(styles, style, suffix) { const result = {}; suffix = suffix ? '-' + suffix : ''; for (let i = 0; i < 4; i++) { const pos = positions[i]; result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0; } result.width = result.left + result.right; result.height = result.top + result.bottom; return result; } const useOffsetPos = (x, y, target) => (x > 0 || y > 0) && (!target || !target.shadowRoot); function getCanvasPosition(evt, canvas) { const e = evt.native || evt; const touches = e.touches; const source = touches && touches.length ? touches[0] : e; const {offsetX, offsetY} = source; let box = false; let x, y; if (useOffsetPos(offsetX, offsetY, e.target)) { x = offsetX; y = offsetY; } else { const rect = canvas.getBoundingClientRect(); x = source.clientX - rect.left; y = source.clientY - rect.top; box = true; } return {x, y, box}; } function getRelativePosition(evt, chart) { const {canvas, currentDevicePixelRatio} = chart; const style = getComputedStyle(canvas); const borderBox = style.boxSizing === 'border-box'; const paddings = getPositionedStyle(style, 'padding'); const borders = getPositionedStyle(style, 'border', 'width'); const {x, y, box} = getCanvasPosition(evt, canvas); const xOffset = paddings.left + (box && borders.left); const yOffset = paddings.top + (box && borders.top); let {width, height} = chart; if (borderBox) { width -= paddings.width + borders.width; height -= paddings.height + borders.height; } return { x: Math.round((x - xOffset) / width * canvas.width / currentDevicePixelRatio), y: Math.round((y - yOffset) / height * canvas.height / currentDevicePixelRatio) }; } function getContainerSize(canvas, width, height) { let maxWidth, maxHeight; if (width === undefined || height === undefined) { const container = _getParentNode(canvas); if (!container) { width = canvas.clientWidth; height = canvas.clientHeight; } else { const rect = container.getBoundingClientRect(); const containerStyle = getComputedStyle(container); const containerBorder = getPositionedStyle(containerStyle, 'border', 'width'); const containerPadding = getPositionedStyle(containerStyle, 'padding'); width = rect.width - containerPadding.width - containerBorder.width; height = rect.height - containerPadding.height - containerBorder.height; maxWidth = parseMaxStyle(containerStyle.maxWidth, container, 'clientWidth'); maxHeight = parseMaxStyle(containerStyle.maxHeight, container, 'clientHeight'); } } return { width, height, maxWidth: maxWidth || INFINITY, maxHeight: maxHeight || INFINITY }; } const round1 = v => Math.round(v * 10) / 10; function getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) { const style = getComputedStyle(canvas); const margins = getPositionedStyle(style, 'margin'); const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY; const maxHeight = parseMaxStyle(style.maxHeight, canvas, 'clientHeight') || INFINITY; const containerSize = getContainerSize(canvas, bbWidth, bbHeight); let {width, height} = containerSize; if (style.boxSizing === 'content-box') { const borders = getPositionedStyle(style, 'border', 'width'); const paddings = getPositionedStyle(style, 'padding'); width -= paddings.width + borders.width; height -= paddings.height + borders.height; } width = Math.max(0, width - margins.width); height = Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height - margins.height); width = round1(Math.min(width, maxWidth, containerSize.maxWidth)); height = round1(Math.min(height, maxHeight, containerSize.maxHeight)); if (width && !height) { height = round1(width / 2); } return { width, height }; } function retinaScale(chart, forceRatio, forceStyle) { const pixelRatio = forceRatio || 1; const deviceHeight = Math.floor(chart.height * pixelRatio); const deviceWidth = Math.floor(chart.width * pixelRatio); chart.height = deviceHeight / pixelRatio; chart.width = deviceWidth / pixelRatio; const canvas = chart.canvas; if (canvas.style && (forceStyle || (!canvas.style.height && !canvas.style.width))) { canvas.style.height = `${chart.height}px`; canvas.style.width = `${chart.width}px`; } if (chart.currentDevicePixelRatio !== pixelRatio || canvas.height !== deviceHeight || canvas.width !== deviceWidth) { chart.currentDevicePixelRatio = pixelRatio; canvas.height = deviceHeight; canvas.width = deviceWidth; chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); return true; } return false; } const supportsEventListenerOptions = (function() { let passiveSupported = false; try { const options = { get passive() { passiveSupported = true; return false; } }; window.addEventListener('test', null, options); window.removeEventListener('test', null, options); } catch (e) { } return passiveSupported; }()); function readUsedSize(element, property) { const value = getStyle(element, property); const matches = value && value.match(/^(\d+)(\.\d+)?px$/); return matches ? +matches[1] : undefined; } function _pointInLine(p1, p2, t, mode) { return { x: p1.x + t * (p2.x - p1.x), y: p1.y + t * (p2.y - p1.y) }; } function _steppedInterpolation(p1, p2, t, mode) { return { x: p1.x + t * (p2.x - p1.x), y: mode === 'middle' ? t < 0.5 ? p1.y : p2.y : mode === 'after' ? t < 1 ? p1.y : p2.y : t > 0 ? p2.y : p1.y }; } function _bezierInterpolation(p1, p2, t, mode) { const cp1 = {x: p1.cp2x, y: p1.cp2y}; const cp2 = {x: p2.cp1x, y: p2.cp1y}; const a = _pointInLine(p1, cp1, t); const b = _pointInLine(cp1, cp2, t); const c = _pointInLine(cp2, p2, t); const d = _pointInLine(a, b, t); const e = _pointInLine(b, c, t); return _pointInLine(d, e, t); } const intlCache = new Map(); function getNumberFormat(locale, options) { options = options || {}; const cacheKey = locale + JSON.stringify(options); let formatter = intlCache.get(cacheKey); if (!formatter) { formatter = new Intl.NumberFormat(locale, options); intlCache.set(cacheKey, formatter); } return formatter; } function formatNumber(num, locale, options) { return getNumberFormat(locale, options).format(num); } const getRightToLeftAdapter = function(rectX, width) { return { x(x) { return rectX + rectX + width - x; }, setWidth(w) { width = w; }, textAlign(align) { if (align === 'center') { return align; } return align === 'right' ? 'left' : 'right'; }, xPlus(x, value) { return x - value; }, leftForLtr(x, itemWidth) { return x - itemWidth; }, }; }; const getLeftToRightAdapter = function() { return { x(x) { return x; }, setWidth(w) { }, textAlign(align) { return align; }, xPlus(x, value) { return x + value; }, leftForLtr(x, _itemWidth) { return x; }, }; }; function getRtlAdapter(rtl, rectX, width) { return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter(); } function overrideTextDirection(ctx, direction) { let style, original; if (direction === 'ltr' || direction === 'rtl') { style = ctx.canvas.style; original = [ style.getPropertyValue('direction'), style.getPropertyPriority('direction'), ]; style.setProperty('direction', direction, 'important'); ctx.prevTextDirection = original; } } function restoreTextDirection(ctx, original) { if (original !== undefined) { delete ctx.prevTextDirection; ctx.canvas.style.setProperty('direction', original[0], original[1]); } } function propertyFn(property) { if (property === 'angle') { return { between: _angleBetween, compare: _angleDiff, normalize: _normalizeAngle, }; } return { between: (n, s, e) => n >= Math.min(s, e) && n <= Math.max(e, s), compare: (a, b) => a - b, normalize: x => x }; } function normalizeSegment({start, end, count, loop, style}) { return { start: start % count, end: end % count, loop: loop && (end - start + 1) % count === 0, style }; } function getSegment(segment, points, bounds) { const {property, start: startBound, end: endBound} = bounds; const {between, normalize} = propertyFn(property); const count = points.length; let {start, end, loop} = segment; let i, ilen; if (loop) { start += count; end += count; for (i = 0, ilen = count; i < ilen; ++i) { if (!between(normalize(points[start % count][property]), startBound, endBound)) { break; } start--; end--; } start %= count; end %= count; } if (end < start) { end += count; } return {start, end, loop, style: segment.style}; } function _boundSegment(segment, points, bounds) { if (!bounds) { return [segment]; } const {property, start: startBound, end: endBound} = bounds; const count = points.length; const {compare, between, normalize} = propertyFn(property); const {start, end, loop, style} = getSegment(segment, points, bounds); const result = []; let inside = false; let subStart = null; let value, point, prevValue; const startIsBefore = () => between(startBound, prevValue, value) && compare(startBound, prevValue) !== 0; const endIsBefore = () => compare(endBound, value) === 0 || between(endBound, prevValue, value); const shouldStart = () => inside || startIsBefore(); const shouldStop = () => !inside || endIsBefore(); for (let i = start, prev = start; i <= end; ++i) { point = points[i % count]; if (point.skip) { continue; } value = normalize(point[property]); if (value === prevValue) { continue; } inside = between(value, startBound, endBound); if (subStart === null && shouldStart()) { subStart = compare(value, startBound) === 0 ? i : prev; } if (subStart !== null && shouldStop()) { result.push(normalizeSegment({start: subStart, end: i, loop, count, style})); subStart = null; } prev = i; prevValue = value; } if (subStart !== null) { result.push(normalizeSegment({start: subStart, end, loop, count, style})); } return result; } function _boundSegments(line, bounds) { const result = []; const segments = line.segments; for (let i = 0; i < segments.length; i++) { const sub = _boundSegment(segments[i], line.points, bounds); if (sub.length) { result.push(...sub); } } return result; } function findStartAndEnd(points, count, loop, spanGaps) { let start = 0; let end = count - 1; if (loop && !spanGaps) { while (start < count && !points[start].skip) { start++; } } while (start < count && points[start].skip) { start++; } start %= count; if (loop) { end += start; } while (end > start && points[end % count].skip) { end--; } end %= count; return {start, end}; } function solidSegments(points, start, max, loop) { const count = points.length; const result = []; let last = start; let prev = points[start]; let end; for (end = start + 1; end <= max; ++end) { const cur = points[end % count]; if (cur.skip || cur.stop) { if (!prev.skip) { loop = false; result.push({start: start % count, end: (end - 1) % count, loop}); start = last = cur.stop ? end : null; } } else { last = end; if (prev.skip) { start = end; } } prev = cur; } if (last !== null) { result.push({start: start % count, end: last % count, loop}); } return result; } function _computeSegments(line, segmentOptions) { const points = line.points; const spanGaps = line.options.spanGaps; const count = points.length; if (!count) { return []; } const loop = !!line._loop; const {start, end} = findStartAndEnd(points, count, loop, spanGaps); if (spanGaps === true) { return splitByStyles(line, [{start, end, loop}], points, segmentOptions); } const max = end < start ? end + count : end; const completeLoop = !!line._fullLoop && start === 0 && end === count - 1; return splitByStyles(line, solidSegments(points, start, max, completeLoop), points, segmentOptions); } function splitByStyles(line, segments, points, segmentOptions) { if (!segmentOptions || !segmentOptions.setContext || !points) { return segments; } return doSplitByStyles(line, segments, points, segmentOptions); } function doSplitByStyles(line, segments, points, segmentOptions) { const baseStyle = readStyle(line.options); const count = points.length; const result = []; let start = segments[0].start; let i = start; for (const segment of segments) { let prevStyle = baseStyle; let prev = points[start % count]; let style; for (i = start + 1; i <= segment.end; i++) { const pt = points[i % count]; style = readStyle(segmentOptions.setContext({ type: 'segment', p0: prev, p1: pt, p0DataIndex: (i - 1) % count, p1DataIndex: i % count, datasetIndex: line._datasetIndex })); if (styleChanged(style, prevStyle)) { result.push({start: start, end: i - 1, loop: segment.loop, style: prevStyle}); prevStyle = style; start = i - 1; } prev = pt; prevStyle = style; } if (start < i - 1) { result.push({start, end: i - 1, loop: segment.loop, style}); start = i - 1; } } return result; } function readStyle(options) { return { backgroundColor: options.backgroundColor, borderCapStyle: options.borderCapStyle, borderDash: options.borderDash, borderDashOffset: options.borderDashOffset, borderJoinStyle: options.borderJoinStyle, borderWidth: options.borderWidth, borderColor: options.borderColor }; } function styleChanged(style, prevStyle) { return prevStyle && JSON.stringify(style) !== JSON.stringify(prevStyle); } /***/ }), /***/ "./src/chartPlugins.js": /*!*****************************!*\ !*** ./src/chartPlugins.js ***! \*****************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "drawYLine": function() { return /* binding */ drawYLine; } /* harmony export */ }); const drawYLine = chart => { if (chart.tooltip._active && chart.tooltip._active.length) { const activePoint = chart.tooltip._active[0] const ctx = chart.ctx const y = activePoint.element.y const leftX = chart.scales.x.left const rightX = chart.scales.x.right const color = activePoint.element.options.borderColor const value = chart.tooltip.dataPoints[0]?.formattedValue ctx.save() ctx.beginPath() ctx.moveTo(leftX, y) ctx.lineTo(rightX, y) ctx.lineWidth = 1 ctx.strokeStyle = color ctx.setLineDash([4, 4]) ctx.stroke() ctx.restore() ctx.fillStyle = color ctx.strokeStyle = color ctx.font = '20px' const textWidth = ctx.measureText(value).width const rightSpace = ctx.canvas.offsetWidth - rightX const left = rightX - Math.max(0, textWidth + 10 - rightSpace) roundRect(ctx, left, y - 10, textWidth + 10, 20, 5, true) ctx.fillStyle = 'white' ctx.fillText(value, left + 5, y + 3) } } function roundRect(ctx, x, y, width, height, radius, fill, stroke) { if (typeof stroke === 'undefined') { stroke = true } if (typeof radius === 'undefined') { radius = 5 } if (typeof radius === 'number') { radius = { tl: radius, tr: radius, br: radius, bl: radius } } else { const defaultRadius = { tl: 0, tr: 0, br: 0, bl: 0 } for (let side in defaultRadius) { radius[side] = radius[side] || defaultRadius[side] } } ctx.beginPath() ctx.moveTo(x + radius.tl, y) ctx.lineTo(x + width - radius.tr, y) ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr) ctx.lineTo(x + width, y + height - radius.br) ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height) ctx.lineTo(x + radius.bl, y + height) ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl) ctx.lineTo(x, y + radius.tl) ctx.quadraticCurveTo(x, y, x + radius.tl, y) ctx.closePath() if (fill) { ctx.fill() } if (stroke) { ctx.stroke() } } /***/ }), /***/ "./src/requestClient.js": /*!******************************!*\ !*** ./src/requestClient.js ***! \******************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "REQUEST_METHODS": function() { return /* binding */ REQUEST_METHODS; }, /* harmony export */ "request": function() { return /* binding */ request; }, /* harmony export */ "stringifyQuery": function() { return /* binding */ stringifyQuery; } /* harmony export */ }); const UNKNOWN_ERROR = { responseStatus: 520, responseMessage: 'Web Server Returned an Unknown Error', errorMessage: 'Web Server Returned an Unknown Error' } const CONTENT_TYPE_HEADER = 'content-type' const APPLICATION_JSON = 'application/json' const TEXT_HTML = 'text/html' const REQUEST_METHODS = Object.freeze({ GET: 'GET' }) const commonHeaders = { [CONTENT_TYPE_HEADER]: APPLICATION_JSON } /** * Check on html response body * * @param {*} headers * @returns */ const isHeaderContainHtml = headers => { if (!headers) { return false } return headers.get(CONTENT_TYPE_HEADER)?.indexOf(TEXT_HTML) > -1 || false } /** * Request client * * @param {*} url * @param {*} body * @param {*} method * @param {*} header * @returns */ const request = async ({ host, headers, url, method, body }) => { const requestUrl = `${host}/${url}` const requestParams = { method, headers: { ...commonHeaders, ...headers } } if (body) { requestParams.body = JSON.stringify(body) } const response = await fetch(requestUrl, requestParams) .then(async (response) => { if (response.ok) { const isJson = response.headers.get(CONTENT_TYPE_HEADER)?.includes(APPLICATION_JSON) return { responseStatus: 200, data: isJson ? await response.json() : null } } if (isHeaderContainHtml(response.headers)) { return Promise.reject(UNKNOWN_ERROR) } return Promise.reject({ responseStatus: 500, data: await response.text() }) }) .then((data) => { const status = data.responseStatus if (status >= 200 && status < 300) { return Promise.resolve(data) } else { return Promise.reject(UNKNOWN_ERROR) } }) .catch((error) => { console.error(error) return Promise.reject(UNKNOWN_ERROR) }) return response } /** * Stringify query * * @param {*} query * @returns */ const stringifyQuery = query => { const searchParams = new URLSearchParams() for (const [key, value] of Object.entries(query)) { if (!!value || value === 0) { searchParams.append(key, value) } } return searchParams.toString() } /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/define property getters */ /******/ !function() { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = function(exports, definition) { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ !function() { /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } /******/ }(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ !function() { /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ }(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. !function() { /*!**********************!*\ !*** ./src/index.js ***! \**********************/ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "_disCharts": function() { return /* binding */ _disCharts; } /* harmony export */ }); /* harmony import */ var chart_js_auto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! chart.js/auto */ "./node_modules/chart.js/auto/auto.esm.js"); /* harmony import */ var _requestClient__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./requestClient */ "./src/requestClient.js"); /* harmony import */ var _chartPlugins__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./chartPlugins */ "./src/chartPlugins.js"); const CHART_URL = 'api/v1/market/charts/range' const CHART_TYPE = { line: 'line' } const CHART_RANGE = Object.freeze({ ONE_DAY: 'ONE_DAY', SEVEN_DAYS: 'SEVEN_DAYS', THIRTY_DAYS: 'THIRTY_DAYS', HALF_YEAR: 'HALF_YEAR', ONE_YEAR: 'ONE_YEAR', THREE_YEAR: 'THREE_YEAR' }) const KIND = { Positive: 'positive', Negative: 'negative' } const THEME_TYPE = { dark: 'dark', light: 'light' } const THEME = { [THEME_TYPE.light]: { charts: { tickColor: '#879299', gridColor: '#F6F8FB', positive: { hex: '#30AF70', rgb: { red: '48', green: '175', blue: '112' } }, negative: { hex: '#E66668', rgb: { red: '230', green: '102', blue: '104' } } } }, [THEME_TYPE.dark]: { charts: { tickColor: '#A5A6AD', gridColor: '#343545', positive: { hex: '#30AF70', rgb: { red: '48', green: '175', blue: '112' } }, negative: { hex: '#E66668', rgb: { red: '230', green: '102', blue: '104' } }, } } } const _disCharts = (function (window) { 'use strict'; const getTokenChart = async ({ host, headers, code, range, conversionCurrency }) => { if (!code || !range || !conversionCurrency) { console.log(`Undefined params [code]=${code}, [range]=${range}, [conversionCurrency]=${conversionCurrency}`) return } const query = (0,_requestClient__WEBPACK_IMPORTED_MODULE_1__.stringifyQuery)({ conversionCurrency }) const payload = await (0,_requestClient__WEBPACK_IMPORTED_MODULE_1__.request)({ host, headers, url: `${CHART_URL}/${code}/${range}?${query}`, method: _requestClient__WEBPACK_IMPORTED_MODULE_1__.REQUEST_METHODS.GET }) return payload } // CHARTS const getThemeColors = ({ theme }) => { return THEME[THEME_TYPE[theme] || THEME_TYPE.light] } const getChartDefaultOptions = ({ tickColor, gridColor }) => { return { responsive: true, layout: { padding: 0 }, plugins: { legend: { display: false }, tooltips: { enabled: false } }, interaction: { intersect: false }, scales: { x: { ticks: { align: 'start', font: { family: "'Arial', sans-serif", size: 10, lineHeight: 4 }, color: tickColor, minRotation: 0, maxRotation: 0, autoSkip: true, autoSkipPadding: 24, beginAtZero: true }, grid: { lineWidth: 1, color: gridColor, drawTicks: false, drawBorder: false } }, y: { position: 'right', ticks: { font: { family: "'Arial', sans-serif", size: 10, lineHeight: 1 }, color: tickColor, minRotation: 0, maxRotation: 0, padding: 16 }, grid: { lineWidth: 1, color: gridColor, drawTicks: false, drawBorder: false } } } } } const getPlagins = () => { return [ { beforeTooltipDraw: _chartPlugins__WEBPACK_IMPORTED_MODULE_2__.drawYLine, } ] } const setChartProps = async ({ theme, host, headers, code, range, conversionCurrency, canvasSelectors }) => { const ctx = document.querySelector(canvasSelectors) if (!ctx) { console.log('Cant\'t find by [canvasSelectors] =', canvasSelectors) return } const payload = await getTokenChart({ host, headers, code, range: CHART_RANGE[range] || CHART_RANGE.THIRTY_DAYS, conversionCurrency }) if (payload.responseStatus !== 200) { console.log('Response error', payload) return } const themeColors = getThemeColors({ theme }) const marketChart = payload.data if (marketChart.data?.lenght <= 0) { console.log('The data of chart is empty') return } const chartKind = marketChart.percent < 0 ? KIND.Negative : KIND.Positive const chartColors = themeColors.charts[chartKind] const gradientColor = `${chartColors.rgb.red},${chartColors.rgb.green},${chartColors.rgb.blue}` const borderColor = chartColors.hex const options = getChartDefaultOptions({ tickColor: themeColors.charts.tickColor, gridColor: themeColors.charts.gridColor }) const plugins = getPlagins() const config = { type: CHART_TYPE.line, options, plugins, data: { labels: marketChart.labels || [], datasets: [ { data: marketChart.data || [], borderColor, backgroundColor: function (context) { const chart = context.chart const { ctx } = chart const gradient = ctx.createLinearGradient(0, 0, 0, 400) gradient.addColorStop(0, `rgba(${gradientColor}, 0.64)`) gradient.addColorStop(0.35, `rgba(${gradientColor}, 0.2)`) gradient.addColorStop(1, 'rgba(255,255,255,0)') return gradient }, fill: true, cubicInterpolationMode: 'monotone', borderWidth: 1, pointRadius: 0 } ] } } new chart_js_auto__WEBPACK_IMPORTED_MODULE_0__.default(ctx, config) } class Prot { } Prot.prototype.setChartProps = setChartProps Prot.prototype.range = CHART_RANGE Prot.prototype.theme = THEME_TYPE const _disChats = { setChartProps: function (props) { return new Prot().setChartProps(props) }, range: new Prot().range, theme: new Prot().theme } window._disChats = _disChats return _disChats })(window) // Sample // window._disChats.setChartProps({ // theme: window._disChats.theme.light, // host: 'http://localhost:3010', // code: 'BTC', // range: window._disChats.range.THIRTY_DAYS, // conversionCurrency: 'EUR', // canvasSelectors: '[data-element="chart"]' // }) // window._disChats.setChartProps({ // theme: window._disChats.theme.light, // host: 'https://gpo.devdigitalinvestmentsolutions.de', // code: 'BTC', // range: window._disChats.range.THIRTY_DAYS, // conversionCurrency: 'EUR', // canvasSelectors: '[data-element="chart"]' // }) }(); /******/ })() ; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly93ZWJmbG93LWNoYXJ0anMvLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvYXV0by9hdXRvLmVzbS5qcyIsIndlYnBhY2s6Ly93ZWJmbG93LWNoYXJ0anMvLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvZGlzdC9jaGFydC5lc20uanMiLCJ3ZWJwYWNrOi8vd2ViZmxvdy1jaGFydGpzLy4vbm9kZV9tb2R1bGVzL2NoYXJ0LmpzL2Rpc3QvY2h1bmtzL2hlbHBlcnMuc2VnbWVudC5qcyIsIndlYnBhY2s6Ly93ZWJmbG93LWNoYXJ0anMvLi9zcmMvY2hhcnRQbHVnaW5zLmpzIiwid2VicGFjazovL3dlYmZsb3ctY2hhcnRqcy8uL3NyYy9yZXF1ZXN0Q2xpZW50LmpzIiwid2VicGFjazovL3dlYmZsb3ctY2hhcnRqcy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly93ZWJmbG93LWNoYXJ0anMvd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL3dlYmZsb3ctY2hhcnRqcy93ZWJwYWNrL3J1bnRpbWUvaGFzT3duUHJvcGVydHkgc2hvcnRoYW5kIiwid2VicGFjazovL3dlYmZsb3ctY2hhcnRqcy93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3dlYmZsb3ctY2hhcnRqcy8uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBdUQ7O0FBRXZELDJEQUFjLElBQUksMERBQWE7O0FBRS9CLCtEQUFlLGtEQUFLLEVBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNKckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQzY0RDtBQUNqMUQ7O0FBRTVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsVUFBVTtBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixTQUFTO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLFVBQVU7QUFDbEQ7QUFDQTtBQUNBLHdCQUF3Qiw2REFBWTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSw2REFBTztBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLFVBQVU7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsVUFBVTtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTSw2REFBYTtBQUNuQjtBQUNBO0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLG1CQUFtQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLDZEQUFxQjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxVQUFVO0FBQ25ELE1BQU0s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QTtBQUNBLGtCQUFrQiw2REFBUztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsVUFBVTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxVQUFVO0FBQ3JCO0FBQ0EsSUFBSSw2REFBSTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxVQUFVO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxTQUFTO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJLDZEQUFJO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFVBQVU7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQyxVQUFVO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsSUFBSSxJQUFJLElBQUksSUFBSSxJQUFJLElBQUksU0FBUztBQUM5QyxZQUFZLElBQUksSUFBSSxJQUFJLElBQUksSUFBSTtBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxTQUFTO0FBQ3pDLFdBQVcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGlCQUFpQjtBQUM3QjtBQUNBLGFBQWEsa0JBQWtCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Ysb0JBQW9CLHVCQUF1QjtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsT0FBTztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsVUFBVTtBQUN2QjtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsc0NBQXNDLFVBQVU7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxrQkFBa0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsbUJBQW1CO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsNkNBQTZDO0FBQ2hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxVQUFVO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsU0FBUztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLFVBQVU7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLHNDQUFzQyxxQ0FBcUM7QUFDM0U7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLHlDQUF5QyxrQ0FBa0M7QUFDM0UsU0FBUyxnR0FBZ0c7QUFDekc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLHVEQUF1RDtBQUNoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsb0NBQW9DO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsdURBQXVEO0FBQ2hFO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLG1CQUFtQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixlQUFlO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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eUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxZQUFZLGtEQUFLO0FBQ2pCOztBQUVBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFb0I7O0FBRXJCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSSxDIiwiZmlsZSI6Im1haW4uMjViZTEwNWMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0NoYXJ0LCByZWdpc3RlcmFibGVzfSBmcm9tICcuLi9kaXN0L2NoYXJ0LmVzbSc7XG5cbkNoYXJ0LnJlZ2lzdGVyKC4uLnJlZ2lzdGVyYWJsZXMpO1xuXG5leHBvcnQgZGVmYXVsdCBDaGFydDtcbiIsIi8qIVxuICogQ2hhcnQuanMgdjMuNS4xXG4gKiBodHRwczovL3d3dy5jaGFydGpzLm9yZ1xuICogKGMpIDIwMjEgQ2hhcnQuanMgQ29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAqL1xuaW1wb3J0IHsgciBhcyByZXF1ZXN0QW5pbUZyYW1lLCBhIGFzIHJlc29sdmUsIGUgYXMgZWZmZWN0cywgYyBhcyBjb2xvciwgZCBhcyBkZWZhdWx0cywgaSBhcyBpc09iamVjdCwgYiBhcyBpc0FycmF5LCB2IGFzIHZhbHVlT3JEZWZhdWx0LCB1IGFzIHVubGlzdGVuQXJyYXlFdmVudHMsIGwgYXMgbGlzdGVuQXJyYXlFdmVudHMsIGYgYXMgcmVzb2x2ZU9iamVjdEtleSwgZyBhcyBpc051bWJlckZpbml0ZSwgaCBhcyBkZWZpbmVkLCBzIGFzIHNpZ24sIGogYXMgaXNOdWxsT3JVbmRlZiwgXyBhcyBfYXJyYXlVbmlxdWUsIHQgYXMgdG9SYWRpYW5zLCBrIGFzIHRvUGVyY2VudGFnZSwgbSBhcyB0b0RpbWVuc2lvbiwgVCBhcyBUQVUsIG4gYXMgZm9ybWF0TnVtYmVyLCBvIGFzIF9hbmdsZUJldHdlZW4sIEggYXMgSEFMRl9QSSwgUCBhcyBQSSwgcCBhcyBpc051bWJlciwgcSBhcyBfbGltaXRWYWx1ZSwgdyBhcyBfbG9va3VwQnlLZXksIHggYXMgZ2V0UmVsYXRpdmVQb3NpdGlvbiQxLCB5IGFzIF9pc1BvaW50SW5BcmVhLCB6IGFzIF9ybG9va3VwQnlLZXksIEEgYXMgdG9QYWRkaW5nLCBCIGFzIGVhY2gsIEMgYXMgZ2V0TWF4aW11bVNpemUsIEQgYXMgX2dldFBhcmVudE5vZGUsIEUgYXMgcmVhZFVzZWRTaXplLCBGIGFzIHRocm90dGxlZCwgRyBhcyBzdXBwb3J0c0V2ZW50TGlzdGVuZXJPcHRpb25zLCBJIGFzIF9pc0RvbVN1cHBvcnRlZCwgSiBhcyBsb2cxMCwgSyBhcyBfZmFjdG9yaXplLCBMIGFzIGZpbml0ZU9yRGVmYXVsdCwgTSBhcyBjYWxsYmFjaywgTiBhcyBfYWRkR3JhY2UsIE8gYXMgdG9EZWdyZWVzLCBRIGFzIF9tZWFzdXJlVGV4dCwgUiBhcyBfaW50MTZSYW5nZSwgUyBhcyBfYWxpZ25QaXhlbCwgVSBhcyBjbGlwQXJlYSwgViBhcyByZW5kZXJUZXh0LCBXIGFzIHVuY2xpcEFyZWEsIFggYXMgdG9Gb250LCBZIGFzIF90b0xlZnRSaWdodENlbnRlciwgWiBhcyBfYWxpZ25TdGFydEVuZCwgJCBhcyBvdmVycmlkZXMsIGEwIGFzIG1lcmdlLCBhMSBhcyBfY2FwaXRhbGl6ZSwgYTIgYXMgZGVzY3JpcHRvcnMsIGEzIGFzIGlzRnVuY3Rpb24sIGE0IGFzIF9hdHRhY2hDb250ZXh0LCBhNSBhcyBfY3JlYXRlUmVzb2x2ZXIsIGE2IGFzIF9kZXNjcmlwdG9ycywgYTcgYXMgbWVyZ2VJZiwgYTggYXMgdWlkLCBhOSBhcyBkZWJvdW5jZSwgYWEgYXMgcmV0aW5hU2NhbGUsIGFiIGFzIGNsZWFyQ2FudmFzLCBhYyBhcyBzZXRzRXF1YWwsIGFkIGFzIF9lbGVtZW50c0VxdWFsLCBhZSBhcyBnZXRBbmdsZUZyb21Qb2ludCwgYWYgYXMgX3JlYWRWYWx1ZVRvUHJvcHMsIGFnIGFzIF91cGRhdGVCZXppZXJDb250cm9sUG9pbnRzLCBhaCBhcyBfY29tcHV0ZVNlZ21lbnRzLCBhaSBhcyBfYm91bmRTZWdtZW50cywgYWogYXMgX3N0ZXBwZWRJbnRlcnBvbGF0aW9uLCBhayBhcyBfYmV6aWVySW50ZXJwb2xhdGlvbiwgYWwgYXMgX3BvaW50SW5MaW5lLCBhbSBhcyBfc3RlcHBlZExpbmVUbywgYW4gYXMgX2JlemllckN1cnZlVG8sIGFvIGFzIGRyYXdQb2ludCwgYXAgYXMgYWRkUm91bmRlZFJlY3RQYXRoLCBhcSBhcyB0b1RSQkwsIGFyIGFzIHRvVFJCTENvcm5lcnMsIGFzIGFzIF9ib3VuZFNlZ21lbnQsIGF0IGFzIF9ub3JtYWxpemVBbmdsZSwgYXUgYXMgZ2V0UnRsQWRhcHRlciwgYXYgYXMgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uLCBhdyBhcyBfdGV4dFgsIGF4IGFzIHJlc3RvcmVUZXh0RGlyZWN0aW9uLCBheSBhcyBub29wLCBheiBhcyBkaXN0YW5jZUJldHdlZW5Qb2ludHMsIGFBIGFzIF9zZXRNaW5BbmRNYXhCeUtleSwgYUIgYXMgbmljZU51bSwgYUMgYXMgYWxtb3N0V2hvbGUsIGFEIGFzIGFsbW9zdEVxdWFscywgYUUgYXMgX2RlY2ltYWxQbGFjZXMsIGFGIGFzIF9sb25nZXN0VGV4dCwgYUcgYXMgX2ZpbHRlckJldHdlZW4sIGFIIGFzIF9sb29rdXAgfSBmcm9tICcuL2NodW5rcy9oZWxwZXJzLnNlZ21lbnQuanMnO1xuZXhwb3J0IHsgZCBhcyBkZWZhdWx0cyB9IGZyb20gJy4vY2h1bmtzL2hlbHBlcnMuc2VnbWVudC5qcyc7XG5cbmNsYXNzIEFuaW1hdG9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5fcmVxdWVzdCA9IG51bGw7XG4gICAgdGhpcy5fY2hhcnRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuX3J1bm5pbmcgPSBmYWxzZTtcbiAgICB0aGlzLl9sYXN0RGF0ZSA9IHVuZGVmaW5lZDtcbiAgfVxuICBfbm90aWZ5KGNoYXJ0LCBhbmltcywgZGF0ZSwgdHlwZSkge1xuICAgIGNvbnN0IGNhbGxiYWNrcyA9IGFuaW1zLmxpc3RlbmVyc1t0eXBlXTtcbiAgICBjb25zdCBudW1TdGVwcyA9IGFuaW1zLmR1cmF0aW9uO1xuICAgIGNhbGxiYWNrcy5mb3JFYWNoKGZuID0+IGZuKHtcbiAgICAgIGNoYXJ0LFxuICAgICAgaW5pdGlhbDogYW5pbXMuaW5pdGlhbCxcbiAgICAgIG51bVN0ZXBzLFxuICAgICAgY3VycmVudFN0ZXA6IE1hdGgubWluKGRhdGUgLSBhbmltcy5zdGFydCwgbnVtU3RlcHMpXG4gICAgfSkpO1xuICB9XG4gIF9yZWZyZXNoKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBpZiAobWUuX3JlcXVlc3QpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbWUuX3J1bm5pbmcgPSB0cnVlO1xuICAgIG1lLl9yZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZS5jYWxsKHdpbmRvdywgKCkgPT4ge1xuICAgICAgbWUuX3VwZGF0ZSgpO1xuICAgICAgbWUuX3JlcXVlc3QgPSBudWxsO1xuICAgICAgaWYgKG1lLl9ydW5uaW5nKSB7XG4gICAgICAgIG1lLl9yZWZyZXNoKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbiAgX3VwZGF0ZShkYXRlID0gRGF0ZS5ub3coKSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBsZXQgcmVtYWluaW5nID0gMDtcbiAgICBtZS5fY2hhcnRzLmZvckVhY2goKGFuaW1zLCBjaGFydCkgPT4ge1xuICAgICAgaWYgKCFhbmltcy5ydW5uaW5nIHx8ICFhbmltcy5pdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgaXRlbXMgPSBhbmltcy5pdGVtcztcbiAgICAgIGxldCBpID0gaXRlbXMubGVuZ3RoIC0gMTtcbiAgICAgIGxldCBkcmF3ID0gZmFsc2U7XG4gICAgICBsZXQgaXRlbTtcbiAgICAgIGZvciAoOyBpID49IDA7IC0taSkge1xuICAgICAgICBpdGVtID0gaXRlbXNbaV07XG4gICAgICAgIGlmIChpdGVtLl9hY3RpdmUpIHtcbiAgICAgICAgICBpZiAoaXRlbS5fdG90YWwgPiBhbmltcy5kdXJhdGlvbikge1xuICAgICAgICAgICAgYW5pbXMuZHVyYXRpb24gPSBpdGVtLl90b3RhbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaXRlbS50aWNrKGRhdGUpO1xuICAgICAgICAgIGRyYXcgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGl0ZW1zW2ldID0gaXRlbXNbaXRlbXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgaXRlbXMucG9wKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChkcmF3KSB7XG4gICAgICAgIGNoYXJ0LmRyYXcoKTtcbiAgICAgICAgbWUuX25vdGlmeShjaGFydCwgYW5pbXMsIGRhdGUsICdwcm9ncmVzcycpO1xuICAgICAgfVxuICAgICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgYW5pbXMucnVubmluZyA9IGZhbHNlO1xuICAgICAgICBtZS5fbm90aWZ5KGNoYXJ0LCBhbmltcywgZGF0ZSwgJ2NvbXBsZXRlJyk7XG4gICAgICAgIGFuaW1zLmluaXRpYWwgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJlbWFpbmluZyArPSBpdGVtcy5sZW5ndGg7XG4gICAgfSk7XG4gICAgbWUuX2xhc3REYXRlID0gZGF0ZTtcbiAgICBpZiAocmVtYWluaW5nID09PSAwKSB7XG4gICAgICBtZS5fcnVubmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuICBfZ2V0QW5pbXMoY2hhcnQpIHtcbiAgICBjb25zdCBjaGFydHMgPSB0aGlzLl9jaGFydHM7XG4gICAgbGV0IGFuaW1zID0gY2hhcnRzLmdldChjaGFydCk7XG4gICAgaWYgKCFhbmltcykge1xuICAgICAgYW5pbXMgPSB7XG4gICAgICAgIHJ1bm5pbmc6IGZhbHNlLFxuICAgICAgICBpbml0aWFsOiB0cnVlLFxuICAgICAgICBpdGVtczogW10sXG4gICAgICAgIGxpc3RlbmVyczoge1xuICAgICAgICAgIGNvbXBsZXRlOiBbXSxcbiAgICAgICAgICBwcm9ncmVzczogW11cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGNoYXJ0cy5zZXQoY2hhcnQsIGFuaW1zKTtcbiAgICB9XG4gICAgcmV0dXJuIGFuaW1zO1xuICB9XG4gIGxpc3RlbihjaGFydCwgZXZlbnQsIGNiKSB7XG4gICAgdGhpcy5fZ2V0QW5pbXMoY2hhcnQpLmxpc3RlbmVyc1tldmVudF0ucHVzaChjYik7XG4gIH1cbiAgYWRkKGNoYXJ0LCBpdGVtcykge1xuICAgIGlmICghaXRlbXMgfHwgIWl0ZW1zLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl9nZXRBbmltcyhjaGFydCkuaXRlbXMucHVzaCguLi5pdGVtcyk7XG4gIH1cbiAgaGFzKGNoYXJ0KSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldEFuaW1zKGNoYXJ0KS5pdGVtcy5sZW5ndGggPiAwO1xuICB9XG4gIHN0YXJ0KGNoYXJ0KSB7XG4gICAgY29uc3QgYW5pbXMgPSB0aGlzLl9jaGFydHMuZ2V0KGNoYXJ0KTtcbiAgICBpZiAoIWFuaW1zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGFuaW1zLnJ1bm5pbmcgPSB0cnVlO1xuICAgIGFuaW1zLnN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICBhbmltcy5kdXJhdGlvbiA9IGFuaW1zLml0ZW1zLnJlZHVjZSgoYWNjLCBjdXIpID0+IE1hdGgubWF4KGFjYywgY3VyLl9kdXJhdGlvbiksIDApO1xuICAgIHRoaXMuX3JlZnJlc2goKTtcbiAgfVxuICBydW5uaW5nKGNoYXJ0KSB7XG4gICAgaWYgKCF0aGlzLl9ydW5uaW5nKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGFuaW1zID0gdGhpcy5fY2hhcnRzLmdldChjaGFydCk7XG4gICAgaWYgKCFhbmltcyB8fCAhYW5pbXMucnVubmluZyB8fCAhYW5pbXMuaXRlbXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHN0b3AoY2hhcnQpIHtcbiAgICBjb25zdCBhbmltcyA9IHRoaXMuX2NoYXJ0cy5nZXQoY2hhcnQpO1xuICAgIGlmICghYW5pbXMgfHwgIWFuaW1zLml0ZW1zLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpdGVtcyA9IGFuaW1zLml0ZW1zO1xuICAgIGxldCBpID0gaXRlbXMubGVuZ3RoIC0gMTtcbiAgICBmb3IgKDsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIGl0ZW1zW2ldLmNhbmNlbCgpO1xuICAgIH1cbiAgICBhbmltcy5pdGVtcyA9IFtdO1xuICAgIHRoaXMuX25vdGlmeShjaGFydCwgYW5pbXMsIERhdGUubm93KCksICdjb21wbGV0ZScpO1xuICB9XG4gIHJlbW92ZShjaGFydCkge1xuICAgIHJldHVybiB0aGlzLl9jaGFydHMuZGVsZXRlKGNoYXJ0KTtcbiAgfVxufVxudmFyIGFuaW1hdG9yID0gbmV3IEFuaW1hdG9yKCk7XG5cbmNvbnN0IHRyYW5zcGFyZW50ID0gJ3RyYW5zcGFyZW50JztcbmNvbnN0IGludGVycG9sYXRvcnMgPSB7XG4gIGJvb2xlYW4oZnJvbSwgdG8sIGZhY3Rvcikge1xuICAgIHJldHVybiBmYWN0b3IgPiAwLjUgPyB0byA6IGZyb207XG4gIH0sXG4gIGNvbG9yKGZyb20sIHRvLCBmYWN0b3IpIHtcbiAgICBjb25zdCBjMCA9IGNvbG9yKGZyb20gfHwgdHJhbnNwYXJlbnQpO1xuICAgIGNvbnN0IGMxID0gYzAudmFsaWQgJiYgY29sb3IodG8gfHwgdHJhbnNwYXJlbnQpO1xuICAgIHJldHVybiBjMSAmJiBjMS52YWxpZFxuICAgICAgPyBjMS5taXgoYzAsIGZhY3RvcikuaGV4U3RyaW5nKClcbiAgICAgIDogdG87XG4gIH0sXG4gIG51bWJlcihmcm9tLCB0bywgZmFjdG9yKSB7XG4gICAgcmV0dXJuIGZyb20gKyAodG8gLSBmcm9tKSAqIGZhY3RvcjtcbiAgfVxufTtcbmNsYXNzIEFuaW1hdGlvbiB7XG4gIGNvbnN0cnVjdG9yKGNmZywgdGFyZ2V0LCBwcm9wLCB0bykge1xuICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IHRhcmdldFtwcm9wXTtcbiAgICB0byA9IHJlc29sdmUoW2NmZy50bywgdG8sIGN1cnJlbnRWYWx1ZSwgY2ZnLmZyb21dKTtcbiAgICBjb25zdCBmcm9tID0gcmVzb2x2ZShbY2ZnLmZyb20sIGN1cnJlbnRWYWx1ZSwgdG9dKTtcbiAgICB0aGlzLl9hY3RpdmUgPSB0cnVlO1xuICAgIHRoaXMuX2ZuID0gY2ZnLmZuIHx8IGludGVycG9sYXRvcnNbY2ZnLnR5cGUgfHwgdHlwZW9mIGZyb21dO1xuICAgIHRoaXMuX2Vhc2luZyA9IGVmZmVjdHNbY2ZnLmVhc2luZ10gfHwgZWZmZWN0cy5saW5lYXI7XG4gICAgdGhpcy5fc3RhcnQgPSBNYXRoLmZsb29yKERhdGUubm93KCkgKyAoY2ZnLmRlbGF5IHx8IDApKTtcbiAgICB0aGlzLl9kdXJhdGlvbiA9IHRoaXMuX3RvdGFsID0gTWF0aC5mbG9vcihjZmcuZHVyYXRpb24pO1xuICAgIHRoaXMuX2xvb3AgPSAhIWNmZy5sb29wO1xuICAgIHRoaXMuX3RhcmdldCA9IHRhcmdldDtcbiAgICB0aGlzLl9wcm9wID0gcHJvcDtcbiAgICB0aGlzLl9mcm9tID0gZnJvbTtcbiAgICB0aGlzLl90byA9IHRvO1xuICAgIHRoaXMuX3Byb21pc2VzID0gdW5kZWZpbmVkO1xuICB9XG4gIGFjdGl2ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fYWN0aXZlO1xuICB9XG4gIHVwZGF0ZShjZmcsIHRvLCBkYXRlKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmIChtZS5fYWN0aXZlKSB7XG4gICAgICBtZS5fbm90aWZ5KGZhbHNlKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IG1lLl90YXJnZXRbbWUuX3Byb3BdO1xuICAgICAgY29uc3QgZWxhcHNlZCA9IGRhdGUgLSBtZS5fc3RhcnQ7XG4gICAgICBjb25zdCByZW1haW4gPSBtZS5fZHVyYXRpb24gLSBlbGFwc2VkO1xuICAgICAgbWUuX3N0YXJ0ID0gZGF0ZTtcbiAgICAgIG1lLl9kdXJhdGlvbiA9IE1hdGguZmxvb3IoTWF0aC5tYXgocmVtYWluLCBjZmcuZHVyYXRpb24pKTtcbiAgICAgIG1lLl90b3RhbCArPSBlbGFwc2VkO1xuICAgICAgbWUuX2xvb3AgPSAhIWNmZy5sb29wO1xuICAgICAgbWUuX3RvID0gcmVzb2x2ZShbY2ZnLnRvLCB0bywgY3VycmVudFZhbHVlLCBjZmcuZnJvbV0pO1xuICAgICAgbWUuX2Zyb20gPSByZXNvbHZlKFtjZmcuZnJvbSwgY3VycmVudFZhbHVlLCB0b10pO1xuICAgIH1cbiAgfVxuICBjYW5jZWwoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmIChtZS5fYWN0aXZlKSB7XG4gICAgICBtZS50aWNrKERhdGUubm93KCkpO1xuICAgICAgbWUuX2FjdGl2ZSA9IGZhbHNlO1xuICAgICAgbWUuX25vdGlmeShmYWxzZSk7XG4gICAgfVxuICB9XG4gIHRpY2soZGF0ZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBlbGFwc2VkID0gZGF0ZSAtIG1lLl9zdGFydDtcbiAgICBjb25zdCBkdXJhdGlvbiA9IG1lLl9kdXJhdGlvbjtcbiAgICBjb25zdCBwcm9wID0gbWUuX3Byb3A7XG4gICAgY29uc3QgZnJvbSA9IG1lLl9mcm9tO1xuICAgIGNvbnN0IGxvb3AgPSBtZS5fbG9vcDtcbiAgICBjb25zdCB0byA9IG1lLl90bztcbiAgICBsZXQgZmFjdG9yO1xuICAgIG1lLl9hY3RpdmUgPSBmcm9tICE9PSB0byAmJiAobG9vcCB8fCAoZWxhcHNlZCA8IGR1cmF0aW9uKSk7XG4gICAgaWYgKCFtZS5fYWN0aXZlKSB7XG4gICAgICBtZS5fdGFyZ2V0W3Byb3BdID0gdG87XG4gICAgICBtZS5fbm90aWZ5KHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZWxhcHNlZCA8IDApIHtcbiAgICAgIG1lLl90YXJnZXRbcHJvcF0gPSBmcm9tO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmYWN0b3IgPSAoZWxhcHNlZCAvIGR1cmF0aW9uKSAlIDI7XG4gICAgZmFjdG9yID0gbG9vcCAmJiBmYWN0b3IgPiAxID8gMiAtIGZhY3RvciA6IGZhY3RvcjtcbiAgICBmYWN0b3IgPSBtZS5fZWFzaW5nKE1hdGgubWluKDEsIE1hdGgubWF4KDAsIGZhY3RvcikpKTtcbiAgICBtZS5fdGFyZ2V0W3Byb3BdID0gbWUuX2ZuKGZyb20sIHRvLCBmYWN0b3IpO1xuICB9XG4gIHdhaXQoKSB7XG4gICAgY29uc3QgcHJvbWlzZXMgPSB0aGlzLl9wcm9taXNlcyB8fCAodGhpcy5fcHJvbWlzZXMgPSBbXSk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXMsIHJlaikgPT4ge1xuICAgICAgcHJvbWlzZXMucHVzaCh7cmVzLCByZWp9KTtcbiAgICB9KTtcbiAgfVxuICBfbm90aWZ5KHJlc29sdmVkKSB7XG4gICAgY29uc3QgbWV0aG9kID0gcmVzb2x2ZWQgPyAncmVzJyA6ICdyZWonO1xuICAgIGNvbnN0IHByb21pc2VzID0gdGhpcy5fcHJvbWlzZXMgfHwgW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwcm9taXNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgcHJvbWlzZXNbaV1bbWV0aG9kXSgpO1xuICAgIH1cbiAgfVxufVxuXG5jb25zdCBudW1iZXJzID0gWyd4JywgJ3knLCAnYm9yZGVyV2lkdGgnLCAncmFkaXVzJywgJ3RlbnNpb24nXTtcbmNvbnN0IGNvbG9ycyA9IFsnY29sb3InLCAnYm9yZGVyQ29sb3InLCAnYmFja2dyb3VuZENvbG9yJ107XG5kZWZhdWx0cy5zZXQoJ2FuaW1hdGlvbicsIHtcbiAgZGVsYXk6IHVuZGVmaW5lZCxcbiAgZHVyYXRpb246IDEwMDAsXG4gIGVhc2luZzogJ2Vhc2VPdXRRdWFydCcsXG4gIGZuOiB1bmRlZmluZWQsXG4gIGZyb206IHVuZGVmaW5lZCxcbiAgbG9vcDogdW5kZWZpbmVkLFxuICB0bzogdW5kZWZpbmVkLFxuICB0eXBlOiB1bmRlZmluZWQsXG59KTtcbmNvbnN0IGFuaW1hdGlvbk9wdGlvbnMgPSBPYmplY3Qua2V5cyhkZWZhdWx0cy5hbmltYXRpb24pO1xuZGVmYXVsdHMuZGVzY3JpYmUoJ2FuaW1hdGlvbicsIHtcbiAgX2ZhbGxiYWNrOiBmYWxzZSxcbiAgX2luZGV4YWJsZTogZmFsc2UsXG4gIF9zY3JpcHRhYmxlOiAobmFtZSkgPT4gbmFtZSAhPT0gJ29uUHJvZ3Jlc3MnICYmIG5hbWUgIT09ICdvbkNvbXBsZXRlJyAmJiBuYW1lICE9PSAnZm4nLFxufSk7XG5kZWZhdWx0cy5zZXQoJ2FuaW1hdGlvbnMnLCB7XG4gIGNvbG9yczoge1xuICAgIHR5cGU6ICdjb2xvcicsXG4gICAgcHJvcGVydGllczogY29sb3JzXG4gIH0sXG4gIG51bWJlcnM6IHtcbiAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICBwcm9wZXJ0aWVzOiBudW1iZXJzXG4gIH0sXG59KTtcbmRlZmF1bHRzLmRlc2NyaWJlKCdhbmltYXRpb25zJywge1xuICBfZmFsbGJhY2s6ICdhbmltYXRpb24nLFxufSk7XG5kZWZhdWx0cy5zZXQoJ3RyYW5zaXRpb25zJywge1xuICBhY3RpdmU6IHtcbiAgICBhbmltYXRpb246IHtcbiAgICAgIGR1cmF0aW9uOiA0MDBcbiAgICB9XG4gIH0sXG4gIHJlc2l6ZToge1xuICAgIGFuaW1hdGlvbjoge1xuICAgICAgZHVyYXRpb246IDBcbiAgICB9XG4gIH0sXG4gIHNob3c6IHtcbiAgICBhbmltYXRpb25zOiB7XG4gICAgICBjb2xvcnM6IHtcbiAgICAgICAgZnJvbTogJ3RyYW5zcGFyZW50J1xuICAgICAgfSxcbiAgICAgIHZpc2libGU6IHtcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgfSxcbiAgICB9XG4gIH0sXG4gIGhpZGU6IHtcbiAgICBhbmltYXRpb25zOiB7XG4gICAgICBjb2xvcnM6IHtcbiAgICAgICAgdG86ICd0cmFuc3BhcmVudCdcbiAgICAgIH0sXG4gICAgICB2aXNpYmxlOiB7XG4gICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZWFzaW5nOiAnbGluZWFyJyxcbiAgICAgICAgZm46IHYgPT4gdiB8IDBcbiAgICAgIH0sXG4gICAgfVxuICB9XG59KTtcbmNsYXNzIEFuaW1hdGlvbnMge1xuICBjb25zdHJ1Y3RvcihjaGFydCwgY29uZmlnKSB7XG4gICAgdGhpcy5fY2hhcnQgPSBjaGFydDtcbiAgICB0aGlzLl9wcm9wZXJ0aWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuY29uZmlndXJlKGNvbmZpZyk7XG4gIH1cbiAgY29uZmlndXJlKGNvbmZpZykge1xuICAgIGlmICghaXNPYmplY3QoY29uZmlnKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBhbmltYXRlZFByb3BzID0gdGhpcy5fcHJvcGVydGllcztcbiAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhjb25maWcpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIGNvbnN0IGNmZyA9IGNvbmZpZ1trZXldO1xuICAgICAgaWYgKCFpc09iamVjdChjZmcpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlc29sdmVkID0ge307XG4gICAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBhbmltYXRpb25PcHRpb25zKSB7XG4gICAgICAgIHJlc29sdmVkW29wdGlvbl0gPSBjZmdbb3B0aW9uXTtcbiAgICAgIH1cbiAgICAgIChpc0FycmF5KGNmZy5wcm9wZXJ0aWVzKSAmJiBjZmcucHJvcGVydGllcyB8fCBba2V5XSkuZm9yRWFjaCgocHJvcCkgPT4ge1xuICAgICAgICBpZiAocHJvcCA9PT0ga2V5IHx8ICFhbmltYXRlZFByb3BzLmhhcyhwcm9wKSkge1xuICAgICAgICAgIGFuaW1hdGVkUHJvcHMuc2V0KHByb3AsIHJlc29sdmVkKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgX2FuaW1hdGVPcHRpb25zKHRhcmdldCwgdmFsdWVzKSB7XG4gICAgY29uc3QgbmV3T3B0aW9ucyA9IHZhbHVlcy5vcHRpb25zO1xuICAgIGNvbnN0IG9wdGlvbnMgPSByZXNvbHZlVGFyZ2V0T3B0aW9ucyh0YXJnZXQsIG5ld09wdGlvbnMpO1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBjb25zdCBhbmltYXRpb25zID0gdGhpcy5fY3JlYXRlQW5pbWF0aW9ucyhvcHRpb25zLCBuZXdPcHRpb25zKTtcbiAgICBpZiAobmV3T3B0aW9ucy4kc2hhcmVkKSB7XG4gICAgICBhd2FpdEFsbCh0YXJnZXQub3B0aW9ucy4kYW5pbWF0aW9ucywgbmV3T3B0aW9ucykudGhlbigoKSA9PiB7XG4gICAgICAgIHRhcmdldC5vcHRpb25zID0gbmV3T3B0aW9ucztcbiAgICAgIH0sICgpID0+IHtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gYW5pbWF0aW9ucztcbiAgfVxuICBfY3JlYXRlQW5pbWF0aW9ucyh0YXJnZXQsIHZhbHVlcykge1xuICAgIGNvbnN0IGFuaW1hdGVkUHJvcHMgPSB0aGlzLl9wcm9wZXJ0aWVzO1xuICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBbXTtcbiAgICBjb25zdCBydW5uaW5nID0gdGFyZ2V0LiRhbmltYXRpb25zIHx8ICh0YXJnZXQuJGFuaW1hdGlvbnMgPSB7fSk7XG4gICAgY29uc3QgcHJvcHMgPSBPYmplY3Qua2V5cyh2YWx1ZXMpO1xuICAgIGNvbnN0IGRhdGUgPSBEYXRlLm5vdygpO1xuICAgIGxldCBpO1xuICAgIGZvciAoaSA9IHByb3BzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICBjb25zdCBwcm9wID0gcHJvcHNbaV07XG4gICAgICBpZiAocHJvcC5jaGFyQXQoMCkgPT09ICckJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9wID09PSAnb3B0aW9ucycpIHtcbiAgICAgICAgYW5pbWF0aW9ucy5wdXNoKC4uLnRoaXMuX2FuaW1hdGVPcHRpb25zKHRhcmdldCwgdmFsdWVzKSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgdmFsdWUgPSB2YWx1ZXNbcHJvcF07XG4gICAgICBsZXQgYW5pbWF0aW9uID0gcnVubmluZ1twcm9wXTtcbiAgICAgIGNvbnN0IGNmZyA9IGFuaW1hdGVkUHJvcHMuZ2V0KHByb3ApO1xuICAgICAgaWYgKGFuaW1hdGlvbikge1xuICAgICAgICBpZiAoY2ZnICYmIGFuaW1hdGlvbi5hY3RpdmUoKSkge1xuICAgICAgICAgIGFuaW1hdGlvbi51cGRhdGUoY2ZnLCB2YWx1ZSwgZGF0ZSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYW5pbWF0aW9uLmNhbmNlbCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIWNmZyB8fCAhY2ZnLmR1cmF0aW9uKSB7XG4gICAgICAgIHRhcmdldFtwcm9wXSA9IHZhbHVlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHJ1bm5pbmdbcHJvcF0gPSBhbmltYXRpb24gPSBuZXcgQW5pbWF0aW9uKGNmZywgdGFyZ2V0LCBwcm9wLCB2YWx1ZSk7XG4gICAgICBhbmltYXRpb25zLnB1c2goYW5pbWF0aW9uKTtcbiAgICB9XG4gICAgcmV0dXJuIGFuaW1hdGlvbnM7XG4gIH1cbiAgdXBkYXRlKHRhcmdldCwgdmFsdWVzKSB7XG4gICAgaWYgKHRoaXMuX3Byb3BlcnRpZXMuc2l6ZSA9PT0gMCkge1xuICAgICAgT2JqZWN0LmFzc2lnbih0YXJnZXQsIHZhbHVlcyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGFuaW1hdGlvbnMgPSB0aGlzLl9jcmVhdGVBbmltYXRpb25zKHRhcmdldCwgdmFsdWVzKTtcbiAgICBpZiAoYW5pbWF0aW9ucy5sZW5ndGgpIHtcbiAgICAgIGFuaW1hdG9yLmFkZCh0aGlzLl9jaGFydCwgYW5pbWF0aW9ucyk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uIGF3YWl0QWxsKGFuaW1hdGlvbnMsIHByb3BlcnRpZXMpIHtcbiAgY29uc3QgcnVubmluZyA9IFtdO1xuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGFuaW0gPSBhbmltYXRpb25zW2tleXNbaV1dO1xuICAgIGlmIChhbmltICYmIGFuaW0uYWN0aXZlKCkpIHtcbiAgICAgIHJ1bm5pbmcucHVzaChhbmltLndhaXQoKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBQcm9taXNlLmFsbChydW5uaW5nKTtcbn1cbmZ1bmN0aW9uIHJlc29sdmVUYXJnZXRPcHRpb25zKHRhcmdldCwgbmV3T3B0aW9ucykge1xuICBpZiAoIW5ld09wdGlvbnMpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgbGV0IG9wdGlvbnMgPSB0YXJnZXQub3B0aW9ucztcbiAgaWYgKCFvcHRpb25zKSB7XG4gICAgdGFyZ2V0Lm9wdGlvbnMgPSBuZXdPcHRpb25zO1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAob3B0aW9ucy4kc2hhcmVkKSB7XG4gICAgdGFyZ2V0Lm9wdGlvbnMgPSBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgb3B0aW9ucywgeyRzaGFyZWQ6IGZhbHNlLCAkYW5pbWF0aW9uczoge319KTtcbiAgfVxuICByZXR1cm4gb3B0aW9ucztcbn1cblxuZnVuY3Rpb24gc2NhbGVDbGlwKHNjYWxlLCBhbGxvd2VkT3ZlcmZsb3cpIHtcbiAgY29uc3Qgb3B0cyA9IHNjYWxlICYmIHNjYWxlLm9wdGlvbnMgfHwge307XG4gIGNvbnN0IHJldmVyc2UgPSBvcHRzLnJldmVyc2U7XG4gIGNvbnN0IG1pbiA9IG9wdHMubWluID09PSB1bmRlZmluZWQgPyBhbGxvd2VkT3ZlcmZsb3cgOiAwO1xuICBjb25zdCBtYXggPSBvcHRzLm1heCA9PT0gdW5kZWZpbmVkID8gYWxsb3dlZE92ZXJmbG93IDogMDtcbiAgcmV0dXJuIHtcbiAgICBzdGFydDogcmV2ZXJzZSA/IG1heCA6IG1pbixcbiAgICBlbmQ6IHJldmVyc2UgPyBtaW4gOiBtYXhcbiAgfTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGlwKHhTY2FsZSwgeVNjYWxlLCBhbGxvd2VkT3ZlcmZsb3cpIHtcbiAgaWYgKGFsbG93ZWRPdmVyZmxvdyA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgeCA9IHNjYWxlQ2xpcCh4U2NhbGUsIGFsbG93ZWRPdmVyZmxvdyk7XG4gIGNvbnN0IHkgPSBzY2FsZUNsaXAoeVNjYWxlLCBhbGxvd2VkT3ZlcmZsb3cpO1xuICByZXR1cm4ge1xuICAgIHRvcDogeS5lbmQsXG4gICAgcmlnaHQ6IHguZW5kLFxuICAgIGJvdHRvbTogeS5zdGFydCxcbiAgICBsZWZ0OiB4LnN0YXJ0XG4gIH07XG59XG5mdW5jdGlvbiB0b0NsaXAodmFsdWUpIHtcbiAgbGV0IHQsIHIsIGIsIGw7XG4gIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICB0ID0gdmFsdWUudG9wO1xuICAgIHIgPSB2YWx1ZS5yaWdodDtcbiAgICBiID0gdmFsdWUuYm90dG9tO1xuICAgIGwgPSB2YWx1ZS5sZWZ0O1xuICB9IGVsc2Uge1xuICAgIHQgPSByID0gYiA9IGwgPSB2YWx1ZTtcbiAgfVxuICByZXR1cm4ge1xuICAgIHRvcDogdCxcbiAgICByaWdodDogcixcbiAgICBib3R0b206IGIsXG4gICAgbGVmdDogbCxcbiAgICBkaXNhYmxlZDogdmFsdWUgPT09IGZhbHNlXG4gIH07XG59XG5mdW5jdGlvbiBnZXRTb3J0ZWREYXRhc2V0SW5kaWNlcyhjaGFydCwgZmlsdGVyVmlzaWJsZSkge1xuICBjb25zdCBrZXlzID0gW107XG4gIGNvbnN0IG1ldGFzZXRzID0gY2hhcnQuX2dldFNvcnRlZERhdGFzZXRNZXRhcyhmaWx0ZXJWaXNpYmxlKTtcbiAgbGV0IGksIGlsZW47XG4gIGZvciAoaSA9IDAsIGlsZW4gPSBtZXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICBrZXlzLnB1c2gobWV0YXNldHNbaV0uaW5kZXgpO1xuICB9XG4gIHJldHVybiBrZXlzO1xufVxuZnVuY3Rpb24gYXBwbHlTdGFjayhzdGFjaywgdmFsdWUsIGRzSW5kZXgsIG9wdGlvbnMpIHtcbiAgY29uc3Qga2V5cyA9IHN0YWNrLmtleXM7XG4gIGNvbnN0IHNpbmdsZU1vZGUgPSBvcHRpb25zLm1vZGUgPT09ICdzaW5nbGUnO1xuICBsZXQgaSwgaWxlbiwgZGF0YXNldEluZGV4LCBvdGhlclZhbHVlO1xuICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgZm9yIChpID0gMCwgaWxlbiA9IGtleXMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgZGF0YXNldEluZGV4ID0gK2tleXNbaV07XG4gICAgaWYgKGRhdGFzZXRJbmRleCA9PT0gZHNJbmRleCkge1xuICAgICAgaWYgKG9wdGlvbnMuYWxsKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIG90aGVyVmFsdWUgPSBzdGFjay52YWx1ZXNbZGF0YXNldEluZGV4XTtcbiAgICBpZiAoaXNOdW1iZXJGaW5pdGUob3RoZXJWYWx1ZSkgJiYgKHNpbmdsZU1vZGUgfHwgKHZhbHVlID09PSAwIHx8IHNpZ24odmFsdWUpID09PSBzaWduKG90aGVyVmFsdWUpKSkpIHtcbiAgICAgIHZhbHVlICs9IG90aGVyVmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIGNvbnZlcnRPYmplY3REYXRhVG9BcnJheShkYXRhKSB7XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhkYXRhKTtcbiAgY29uc3QgYWRhdGEgPSBuZXcgQXJyYXkoa2V5cy5sZW5ndGgpO1xuICBsZXQgaSwgaWxlbiwga2V5O1xuICBmb3IgKGkgPSAwLCBpbGVuID0ga2V5cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICBrZXkgPSBrZXlzW2ldO1xuICAgIGFkYXRhW2ldID0ge1xuICAgICAgeDoga2V5LFxuICAgICAgeTogZGF0YVtrZXldXG4gICAgfTtcbiAgfVxuICByZXR1cm4gYWRhdGE7XG59XG5mdW5jdGlvbiBpc1N0YWNrZWQoc2NhbGUsIG1ldGEpIHtcbiAgY29uc3Qgc3RhY2tlZCA9IHNjYWxlICYmIHNjYWxlLm9wdGlvbnMuc3RhY2tlZDtcbiAgcmV0dXJuIHN0YWNrZWQgfHwgKHN0YWNrZWQgPT09IHVuZGVmaW5lZCAmJiBtZXRhLnN0YWNrICE9PSB1bmRlZmluZWQpO1xufVxuZnVuY3Rpb24gZ2V0U3RhY2tLZXkoaW5kZXhTY2FsZSwgdmFsdWVTY2FsZSwgbWV0YSkge1xuICByZXR1cm4gYCR7aW5kZXhTY2FsZS5pZH0uJHt2YWx1ZVNjYWxlLmlkfS4ke21ldGEuc3RhY2sgfHwgbWV0YS50eXBlfWA7XG59XG5mdW5jdGlvbiBnZXRVc2VyQm91bmRzKHNjYWxlKSB7XG4gIGNvbnN0IHttaW4sIG1heCwgbWluRGVmaW5lZCwgbWF4RGVmaW5lZH0gPSBzY2FsZS5nZXRVc2VyQm91bmRzKCk7XG4gIHJldHVybiB7XG4gICAgbWluOiBtaW5EZWZpbmVkID8gbWluIDogTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZLFxuICAgIG1heDogbWF4RGVmaW5lZCA/IG1heCA6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWVxuICB9O1xufVxuZnVuY3Rpb24gZ2V0T3JDcmVhdGVTdGFjayhzdGFja3MsIHN0YWNrS2V5LCBpbmRleFZhbHVlKSB7XG4gIGNvbnN0IHN1YlN0YWNrID0gc3RhY2tzW3N0YWNrS2V5XSB8fCAoc3RhY2tzW3N0YWNrS2V5XSA9IHt9KTtcbiAgcmV0dXJuIHN1YlN0YWNrW2luZGV4VmFsdWVdIHx8IChzdWJTdGFja1tpbmRleFZhbHVlXSA9IHt9KTtcbn1cbmZ1bmN0aW9uIGdldExhc3RJbmRleEluU3RhY2soc3RhY2ssIHZTY2FsZSwgcG9zaXRpdmUpIHtcbiAgZm9yIChjb25zdCBtZXRhIG9mIHZTY2FsZS5nZXRNYXRjaGluZ1Zpc2libGVNZXRhcygnYmFyJykucmV2ZXJzZSgpKSB7XG4gICAgY29uc3QgdmFsdWUgPSBzdGFja1ttZXRhLmluZGV4XTtcbiAgICBpZiAoKHBvc2l0aXZlICYmIHZhbHVlID4gMCkgfHwgKCFwb3NpdGl2ZSAmJiB2YWx1ZSA8IDApKSB7XG4gICAgICByZXR1cm4gbWV0YS5pbmRleDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiB1cGRhdGVTdGFja3MoY29udHJvbGxlciwgcGFyc2VkKSB7XG4gIGNvbnN0IHtjaGFydCwgX2NhY2hlZE1ldGE6IG1ldGF9ID0gY29udHJvbGxlcjtcbiAgY29uc3Qgc3RhY2tzID0gY2hhcnQuX3N0YWNrcyB8fCAoY2hhcnQuX3N0YWNrcyA9IHt9KTtcbiAgY29uc3Qge2lTY2FsZSwgdlNjYWxlLCBpbmRleDogZGF0YXNldEluZGV4fSA9IG1ldGE7XG4gIGNvbnN0IGlBeGlzID0gaVNjYWxlLmF4aXM7XG4gIGNvbnN0IHZBeGlzID0gdlNjYWxlLmF4aXM7XG4gIGNvbnN0IGtleSA9IGdldFN0YWNrS2V5KGlTY2FsZSwgdlNjYWxlLCBtZXRhKTtcbiAgY29uc3QgaWxlbiA9IHBhcnNlZC5sZW5ndGg7XG4gIGxldCBzdGFjaztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbGVuOyArK2kpIHtcbiAgICBjb25zdCBpdGVtID0gcGFyc2VkW2ldO1xuICAgIGNvbnN0IHtbaUF4aXNdOiBpbmRleCwgW3ZBeGlzXTogdmFsdWV9ID0gaXRlbTtcbiAgICBjb25zdCBpdGVtU3RhY2tzID0gaXRlbS5fc3RhY2tzIHx8IChpdGVtLl9zdGFja3MgPSB7fSk7XG4gICAgc3RhY2sgPSBpdGVtU3RhY2tzW3ZBeGlzXSA9IGdldE9yQ3JlYXRlU3RhY2soc3RhY2tzLCBrZXksIGluZGV4KTtcbiAgICBzdGFja1tkYXRhc2V0SW5kZXhdID0gdmFsdWU7XG4gICAgc3RhY2suX3RvcCA9IGdldExhc3RJbmRleEluU3RhY2soc3RhY2ssIHZTY2FsZSwgdHJ1ZSk7XG4gICAgc3RhY2suX2JvdHRvbSA9IGdldExhc3RJbmRleEluU3RhY2soc3RhY2ssIHZTY2FsZSwgZmFsc2UpO1xuICB9XG59XG5mdW5jdGlvbiBnZXRGaXJzdFNjYWxlSWQoY2hhcnQsIGF4aXMpIHtcbiAgY29uc3Qgc2NhbGVzID0gY2hhcnQuc2NhbGVzO1xuICByZXR1cm4gT2JqZWN0LmtleXMoc2NhbGVzKS5maWx0ZXIoa2V5ID0+IHNjYWxlc1trZXldLmF4aXMgPT09IGF4aXMpLnNoaWZ0KCk7XG59XG5mdW5jdGlvbiBjcmVhdGVEYXRhc2V0Q29udGV4dChwYXJlbnQsIGluZGV4KSB7XG4gIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUocGFyZW50KSxcbiAgICB7XG4gICAgICBhY3RpdmU6IGZhbHNlLFxuICAgICAgZGF0YXNldDogdW5kZWZpbmVkLFxuICAgICAgZGF0YXNldEluZGV4OiBpbmRleCxcbiAgICAgIGluZGV4LFxuICAgICAgbW9kZTogJ2RlZmF1bHQnLFxuICAgICAgdHlwZTogJ2RhdGFzZXQnXG4gICAgfVxuICApO1xufVxuZnVuY3Rpb24gY3JlYXRlRGF0YUNvbnRleHQocGFyZW50LCBpbmRleCwgZWxlbWVudCkge1xuICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKHBhcmVudCksIHtcbiAgICBhY3RpdmU6IGZhbHNlLFxuICAgIGRhdGFJbmRleDogaW5kZXgsXG4gICAgcGFyc2VkOiB1bmRlZmluZWQsXG4gICAgcmF3OiB1bmRlZmluZWQsXG4gICAgZWxlbWVudCxcbiAgICBpbmRleCxcbiAgICBtb2RlOiAnZGVmYXVsdCcsXG4gICAgdHlwZTogJ2RhdGEnXG4gIH0pO1xufVxuZnVuY3Rpb24gY2xlYXJTdGFja3MobWV0YSwgaXRlbXMpIHtcbiAgY29uc3QgZGF0YXNldEluZGV4ID0gbWV0YS5jb250cm9sbGVyLmluZGV4O1xuICBjb25zdCBheGlzID0gbWV0YS52U2NhbGUgJiYgbWV0YS52U2NhbGUuYXhpcztcbiAgaWYgKCFheGlzKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGl0ZW1zID0gaXRlbXMgfHwgbWV0YS5fcGFyc2VkO1xuICBmb3IgKGNvbnN0IHBhcnNlZCBvZiBpdGVtcykge1xuICAgIGNvbnN0IHN0YWNrcyA9IHBhcnNlZC5fc3RhY2tzO1xuICAgIGlmICghc3RhY2tzIHx8IHN0YWNrc1theGlzXSA9PT0gdW5kZWZpbmVkIHx8IHN0YWNrc1theGlzXVtkYXRhc2V0SW5kZXhdID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZGVsZXRlIHN0YWNrc1theGlzXVtkYXRhc2V0SW5kZXhdO1xuICB9XG59XG5jb25zdCBpc0RpcmVjdFVwZGF0ZU1vZGUgPSAobW9kZSkgPT4gbW9kZSA9PT0gJ3Jlc2V0JyB8fCBtb2RlID09PSAnbm9uZSc7XG5jb25zdCBjbG9uZUlmTm90U2hhcmVkID0gKGNhY2hlZCwgc2hhcmVkKSA9PiBzaGFyZWQgPyBjYWNoZWQgOiBPYmplY3QuYXNzaWduKHt9LCBjYWNoZWQpO1xuY2xhc3MgRGF0YXNldENvbnRyb2xsZXIge1xuICBjb25zdHJ1Y3RvcihjaGFydCwgZGF0YXNldEluZGV4KSB7XG4gICAgdGhpcy5jaGFydCA9IGNoYXJ0O1xuICAgIHRoaXMuX2N0eCA9IGNoYXJ0LmN0eDtcbiAgICB0aGlzLmluZGV4ID0gZGF0YXNldEluZGV4O1xuICAgIHRoaXMuX2NhY2hlZERhdGFPcHRzID0ge307XG4gICAgdGhpcy5fY2FjaGVkTWV0YSA9IHRoaXMuZ2V0TWV0YSgpO1xuICAgIHRoaXMuX3R5cGUgPSB0aGlzLl9jYWNoZWRNZXRhLnR5cGU7XG4gICAgdGhpcy5vcHRpb25zID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3BhcnNpbmcgPSBmYWxzZTtcbiAgICB0aGlzLl9kYXRhID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX29iamVjdERhdGEgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fc2hhcmVkT3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9kcmF3U3RhcnQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fZHJhd0NvdW50ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZW5hYmxlT3B0aW9uU2hhcmluZyA9IGZhbHNlO1xuICAgIHRoaXMuJGNvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fc3luY0xpc3QgPSBbXTtcbiAgICB0aGlzLmluaXRpYWxpemUoKTtcbiAgfVxuICBpbml0aWFsaXplKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgbWUuY29uZmlndXJlKCk7XG4gICAgbWUubGlua1NjYWxlcygpO1xuICAgIG1ldGEuX3N0YWNrZWQgPSBpc1N0YWNrZWQobWV0YS52U2NhbGUsIG1ldGEpO1xuICAgIG1lLmFkZEVsZW1lbnRzKCk7XG4gIH1cbiAgdXBkYXRlSW5kZXgoZGF0YXNldEluZGV4KSB7XG4gICAgaWYgKHRoaXMuaW5kZXggIT09IGRhdGFzZXRJbmRleCkge1xuICAgICAgY2xlYXJTdGFja3ModGhpcy5fY2FjaGVkTWV0YSk7XG4gICAgfVxuICAgIHRoaXMuaW5kZXggPSBkYXRhc2V0SW5kZXg7XG4gIH1cbiAgbGlua1NjYWxlcygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgY2hhcnQgPSBtZS5jaGFydDtcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgZGF0YXNldCA9IG1lLmdldERhdGFzZXQoKTtcbiAgICBjb25zdCBjaG9vc2VJZCA9IChheGlzLCB4LCB5LCByKSA9PiBheGlzID09PSAneCcgPyB4IDogYXhpcyA9PT0gJ3InID8gciA6IHk7XG4gICAgY29uc3QgeGlkID0gbWV0YS54QXhpc0lEID0gdmFsdWVPckRlZmF1bHQoZGF0YXNldC54QXhpc0lELCBnZXRGaXJzdFNjYWxlSWQoY2hhcnQsICd4JykpO1xuICAgIGNvbnN0IHlpZCA9IG1ldGEueUF4aXNJRCA9IHZhbHVlT3JEZWZhdWx0KGRhdGFzZXQueUF4aXNJRCwgZ2V0Rmlyc3RTY2FsZUlkKGNoYXJ0LCAneScpKTtcbiAgICBjb25zdCByaWQgPSBtZXRhLnJBeGlzSUQgPSB2YWx1ZU9yRGVmYXVsdChkYXRhc2V0LnJBeGlzSUQsIGdldEZpcnN0U2NhbGVJZChjaGFydCwgJ3InKSk7XG4gICAgY29uc3QgaW5kZXhBeGlzID0gbWV0YS5pbmRleEF4aXM7XG4gICAgY29uc3QgaWlkID0gbWV0YS5pQXhpc0lEID0gY2hvb3NlSWQoaW5kZXhBeGlzLCB4aWQsIHlpZCwgcmlkKTtcbiAgICBjb25zdCB2aWQgPSBtZXRhLnZBeGlzSUQgPSBjaG9vc2VJZChpbmRleEF4aXMsIHlpZCwgeGlkLCByaWQpO1xuICAgIG1ldGEueFNjYWxlID0gbWUuZ2V0U2NhbGVGb3JJZCh4aWQpO1xuICAgIG1ldGEueVNjYWxlID0gbWUuZ2V0U2NhbGVGb3JJZCh5aWQpO1xuICAgIG1ldGEuclNjYWxlID0gbWUuZ2V0U2NhbGVGb3JJZChyaWQpO1xuICAgIG1ldGEuaVNjYWxlID0gbWUuZ2V0U2NhbGVGb3JJZChpaWQpO1xuICAgIG1ldGEudlNjYWxlID0gbWUuZ2V0U2NhbGVGb3JJZCh2aWQpO1xuICB9XG4gIGdldERhdGFzZXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hhcnQuZGF0YS5kYXRhc2V0c1t0aGlzLmluZGV4XTtcbiAgfVxuICBnZXRNZXRhKCkge1xuICAgIHJldHVybiB0aGlzLmNoYXJ0LmdldERhdGFzZXRNZXRhKHRoaXMuaW5kZXgpO1xuICB9XG4gIGdldFNjYWxlRm9ySWQoc2NhbGVJRCkge1xuICAgIHJldHVybiB0aGlzLmNoYXJ0LnNjYWxlc1tzY2FsZUlEXTtcbiAgfVxuICBfZ2V0T3RoZXJTY2FsZShzY2FsZSkge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgIHJldHVybiBzY2FsZSA9PT0gbWV0YS5pU2NhbGVcbiAgICAgID8gbWV0YS52U2NhbGVcbiAgICAgIDogbWV0YS5pU2NhbGU7XG4gIH1cbiAgcmVzZXQoKSB7XG4gICAgdGhpcy5fdXBkYXRlKCdyZXNldCcpO1xuICB9XG4gIF9kZXN0cm95KCkge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgIGlmICh0aGlzLl9kYXRhKSB7XG4gICAgICB1bmxpc3RlbkFycmF5RXZlbnRzKHRoaXMuX2RhdGEsIHRoaXMpO1xuICAgIH1cbiAgICBpZiAobWV0YS5fc3RhY2tlZCkge1xuICAgICAgY2xlYXJTdGFja3MobWV0YSk7XG4gICAgfVxuICB9XG4gIF9kYXRhQ2hlY2soKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGRhdGFzZXQgPSBtZS5nZXREYXRhc2V0KCk7XG4gICAgY29uc3QgZGF0YSA9IGRhdGFzZXQuZGF0YSB8fCAoZGF0YXNldC5kYXRhID0gW10pO1xuICAgIGNvbnN0IF9kYXRhID0gbWUuX2RhdGE7XG4gICAgaWYgKGlzT2JqZWN0KGRhdGEpKSB7XG4gICAgICBtZS5fZGF0YSA9IGNvbnZlcnRPYmplY3REYXRhVG9BcnJheShkYXRhKTtcbiAgICB9IGVsc2UgaWYgKF9kYXRhICE9PSBkYXRhKSB7XG4gICAgICBpZiAoX2RhdGEpIHtcbiAgICAgICAgdW5saXN0ZW5BcnJheUV2ZW50cyhfZGF0YSwgbWUpO1xuICAgICAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNsZWFyU3RhY2tzKG1ldGEpO1xuICAgICAgICBtZXRhLl9wYXJzZWQgPSBbXTtcbiAgICAgIH1cbiAgICAgIGlmIChkYXRhICYmIE9iamVjdC5pc0V4dGVuc2libGUoZGF0YSkpIHtcbiAgICAgICAgbGlzdGVuQXJyYXlFdmVudHMoZGF0YSwgbWUpO1xuICAgICAgfVxuICAgICAgbWUuX3N5bmNMaXN0ID0gW107XG4gICAgICBtZS5fZGF0YSA9IGRhdGE7XG4gICAgfVxuICB9XG4gIGFkZEVsZW1lbnRzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgbWUuX2RhdGFDaGVjaygpO1xuICAgIGlmIChtZS5kYXRhc2V0RWxlbWVudFR5cGUpIHtcbiAgICAgIG1ldGEuZGF0YXNldCA9IG5ldyBtZS5kYXRhc2V0RWxlbWVudFR5cGUoKTtcbiAgICB9XG4gIH1cbiAgYnVpbGRPclVwZGF0ZUVsZW1lbnRzKHJlc2V0TmV3RWxlbWVudHMpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbWV0YSA9IG1lLl9jYWNoZWRNZXRhO1xuICAgIGNvbnN0IGRhdGFzZXQgPSBtZS5nZXREYXRhc2V0KCk7XG4gICAgbGV0IHN0YWNrQ2hhbmdlZCA9IGZhbHNlO1xuICAgIG1lLl9kYXRhQ2hlY2soKTtcbiAgICBjb25zdCBvbGRTdGFja2VkID0gbWV0YS5fc3RhY2tlZDtcbiAgICBtZXRhLl9zdGFja2VkID0gaXNTdGFja2VkKG1ldGEudlNjYWxlLCBtZXRhKTtcbiAgICBpZiAobWV0YS5zdGFjayAhPT0gZGF0YXNldC5zdGFjaykge1xuICAgICAgc3RhY2tDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgIGNsZWFyU3RhY2tzKG1ldGEpO1xuICAgICAgbWV0YS5zdGFjayA9IGRhdGFzZXQuc3RhY2s7XG4gICAgfVxuICAgIG1lLl9yZXN5bmNFbGVtZW50cyhyZXNldE5ld0VsZW1lbnRzKTtcbiAgICBpZiAoc3RhY2tDaGFuZ2VkIHx8IG9sZFN0YWNrZWQgIT09IG1ldGEuX3N0YWNrZWQpIHtcbiAgICAgIHVwZGF0ZVN0YWNrcyhtZSwgbWV0YS5fcGFyc2VkKTtcbiAgICB9XG4gIH1cbiAgY29uZmlndXJlKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBjb25maWcgPSBtZS5jaGFydC5jb25maWc7XG4gICAgY29uc3Qgc2NvcGVLZXlzID0gY29uZmlnLmRhdGFzZXRTY29wZUtleXMobWUuX3R5cGUpO1xuICAgIGNvbnN0IHNjb3BlcyA9IGNvbmZpZy5nZXRPcHRpb25TY29wZXMobWUuZ2V0RGF0YXNldCgpLCBzY29wZUtleXMsIHRydWUpO1xuICAgIG1lLm9wdGlvbnMgPSBjb25maWcuY3JlYXRlUmVzb2x2ZXIoc2NvcGVzLCBtZS5nZXRDb250ZXh0KCkpO1xuICAgIG1lLl9wYXJzaW5nID0gbWUub3B0aW9ucy5wYXJzaW5nO1xuICB9XG4gIHBhcnNlKHN0YXJ0LCBjb3VudCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB7X2NhY2hlZE1ldGE6IG1ldGEsIF9kYXRhOiBkYXRhfSA9IG1lO1xuICAgIGNvbnN0IHtpU2NhbGUsIF9zdGFja2VkfSA9IG1ldGE7XG4gICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICBsZXQgc29ydGVkID0gc3RhcnQgPT09IDAgJiYgY291bnQgPT09IGRhdGEubGVuZ3RoID8gdHJ1ZSA6IG1ldGEuX3NvcnRlZDtcbiAgICBsZXQgcHJldiA9IHN0YXJ0ID4gMCAmJiBtZXRhLl9wYXJzZWRbc3RhcnQgLSAxXTtcbiAgICBsZXQgaSwgY3VyLCBwYXJzZWQ7XG4gICAgaWYgKG1lLl9wYXJzaW5nID09PSBmYWxzZSkge1xuICAgICAgbWV0YS5fcGFyc2VkID0gZGF0YTtcbiAgICAgIG1ldGEuX3NvcnRlZCA9IHRydWU7XG4gICAgICBwYXJzZWQgPSBkYXRhO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaXNBcnJheShkYXRhW3N0YXJ0XSkpIHtcbiAgICAgICAgcGFyc2VkID0gbWUucGFyc2VBcnJheURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoZGF0YVtzdGFydF0pKSB7XG4gICAgICAgIHBhcnNlZCA9IG1lLnBhcnNlT2JqZWN0RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyc2VkID0gbWUucGFyc2VQcmltaXRpdmVEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCk7XG4gICAgICB9XG4gICAgICBjb25zdCBpc05vdEluT3JkZXJDb21wYXJlZFRvUHJldiA9ICgpID0+IGN1cltpQXhpc10gPT09IG51bGwgfHwgKHByZXYgJiYgY3VyW2lBeGlzXSA8IHByZXZbaUF4aXNdKTtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7XG4gICAgICAgIG1ldGEuX3BhcnNlZFtpICsgc3RhcnRdID0gY3VyID0gcGFyc2VkW2ldO1xuICAgICAgICBpZiAoc29ydGVkKSB7XG4gICAgICAgICAgaWYgKGlzTm90SW5PcmRlckNvbXBhcmVkVG9QcmV2KCkpIHtcbiAgICAgICAgICAgIHNvcnRlZCA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwcmV2ID0gY3VyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBtZXRhLl9zb3J0ZWQgPSBzb3J0ZWQ7XG4gICAgfVxuICAgIGlmIChfc3RhY2tlZCkge1xuICAgICAgdXBkYXRlU3RhY2tzKG1lLCBwYXJzZWQpO1xuICAgIH1cbiAgfVxuICBwYXJzZVByaW1pdGl2ZURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgY29uc3Qge2lTY2FsZSwgdlNjYWxlfSA9IG1ldGE7XG4gICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICBjb25zdCB2QXhpcyA9IHZTY2FsZS5heGlzO1xuICAgIGNvbnN0IGxhYmVscyA9IGlTY2FsZS5nZXRMYWJlbHMoKTtcbiAgICBjb25zdCBzaW5nbGVTY2FsZSA9IGlTY2FsZSA9PT0gdlNjYWxlO1xuICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgbGV0IGksIGlsZW4sIGluZGV4O1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgaW5kZXggPSBpICsgc3RhcnQ7XG4gICAgICBwYXJzZWRbaV0gPSB7XG4gICAgICAgIFtpQXhpc106IHNpbmdsZVNjYWxlIHx8IGlTY2FsZS5wYXJzZShsYWJlbHNbaW5kZXhdLCBpbmRleCksXG4gICAgICAgIFt2QXhpc106IHZTY2FsZS5wYXJzZShkYXRhW2luZGV4XSwgaW5kZXgpXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VkO1xuICB9XG4gIHBhcnNlQXJyYXlEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgIGNvbnN0IHt4U2NhbGUsIHlTY2FsZX0gPSBtZXRhO1xuICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgbGV0IGksIGlsZW4sIGluZGV4LCBpdGVtO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgaW5kZXggPSBpICsgc3RhcnQ7XG4gICAgICBpdGVtID0gZGF0YVtpbmRleF07XG4gICAgICBwYXJzZWRbaV0gPSB7XG4gICAgICAgIHg6IHhTY2FsZS5wYXJzZShpdGVtWzBdLCBpbmRleCksXG4gICAgICAgIHk6IHlTY2FsZS5wYXJzZShpdGVtWzFdLCBpbmRleClcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBwYXJzZWQ7XG4gIH1cbiAgcGFyc2VPYmplY3REYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgIGNvbnN0IHt4U2NhbGUsIHlTY2FsZX0gPSBtZXRhO1xuICAgIGNvbnN0IHt4QXhpc0tleSA9ICd4JywgeUF4aXNLZXkgPSAneSd9ID0gdGhpcy5fcGFyc2luZztcbiAgICBjb25zdCBwYXJzZWQgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgIGxldCBpLCBpbGVuLCBpbmRleCwgaXRlbTtcbiAgICBmb3IgKGkgPSAwLCBpbGVuID0gY291bnQ7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGluZGV4ID0gaSArIHN0YXJ0O1xuICAgICAgaXRlbSA9IGRhdGFbaW5kZXhdO1xuICAgICAgcGFyc2VkW2ldID0ge1xuICAgICAgICB4OiB4U2NhbGUucGFyc2UocmVzb2x2ZU9iamVjdEtleShpdGVtLCB4QXhpc0tleSksIGluZGV4KSxcbiAgICAgICAgeTogeVNjYWxlLnBhcnNlKHJlc29sdmVPYmplY3RLZXkoaXRlbSwgeUF4aXNLZXkpLCBpbmRleClcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBwYXJzZWQ7XG4gIH1cbiAgZ2V0UGFyc2VkKGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlZE1ldGEuX3BhcnNlZFtpbmRleF07XG4gIH1cbiAgZ2V0RGF0YUVsZW1lbnQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5fY2FjaGVkTWV0YS5kYXRhW2luZGV4XTtcbiAgfVxuICBhcHBseVN0YWNrKHNjYWxlLCBwYXJzZWQsIG1vZGUpIHtcbiAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgdmFsdWUgPSBwYXJzZWRbc2NhbGUuYXhpc107XG4gICAgY29uc3Qgc3RhY2sgPSB7XG4gICAgICBrZXlzOiBnZXRTb3J0ZWREYXRhc2V0SW5kaWNlcyhjaGFydCwgdHJ1ZSksXG4gICAgICB2YWx1ZXM6IHBhcnNlZC5fc3RhY2tzW3NjYWxlLmF4aXNdXG4gICAgfTtcbiAgICByZXR1cm4gYXBwbHlTdGFjayhzdGFjaywgdmFsdWUsIG1ldGEuaW5kZXgsIHttb2RlfSk7XG4gIH1cbiAgdXBkYXRlUmFuZ2VGcm9tUGFyc2VkKHJhbmdlLCBzY2FsZSwgcGFyc2VkLCBzdGFjaykge1xuICAgIGNvbnN0IHBhcnNlZFZhbHVlID0gcGFyc2VkW3NjYWxlLmF4aXNdO1xuICAgIGxldCB2YWx1ZSA9IHBhcnNlZFZhbHVlID09PSBudWxsID8gTmFOIDogcGFyc2VkVmFsdWU7XG4gICAgY29uc3QgdmFsdWVzID0gc3RhY2sgJiYgcGFyc2VkLl9zdGFja3Nbc2NhbGUuYXhpc107XG4gICAgaWYgKHN0YWNrICYmIHZhbHVlcykge1xuICAgICAgc3RhY2sudmFsdWVzID0gdmFsdWVzO1xuICAgICAgcmFuZ2UubWluID0gTWF0aC5taW4ocmFuZ2UubWluLCB2YWx1ZSk7XG4gICAgICByYW5nZS5tYXggPSBNYXRoLm1heChyYW5nZS5tYXgsIHZhbHVlKTtcbiAgICAgIHZhbHVlID0gYXBwbHlTdGFjayhzdGFjaywgcGFyc2VkVmFsdWUsIHRoaXMuX2NhY2hlZE1ldGEuaW5kZXgsIHthbGw6IHRydWV9KTtcbiAgICB9XG4gICAgcmFuZ2UubWluID0gTWF0aC5taW4ocmFuZ2UubWluLCB2YWx1ZSk7XG4gICAgcmFuZ2UubWF4ID0gTWF0aC5tYXgocmFuZ2UubWF4LCB2YWx1ZSk7XG4gIH1cbiAgZ2V0TWluTWF4KHNjYWxlLCBjYW5TdGFjaykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgX3BhcnNlZCA9IG1ldGEuX3BhcnNlZDtcbiAgICBjb25zdCBzb3J0ZWQgPSBtZXRhLl9zb3J0ZWQgJiYgc2NhbGUgPT09IG1ldGEuaVNjYWxlO1xuICAgIGNvbnN0IGlsZW4gPSBfcGFyc2VkLmxlbmd0aDtcbiAgICBjb25zdCBvdGhlclNjYWxlID0gbWUuX2dldE90aGVyU2NhbGUoc2NhbGUpO1xuICAgIGNvbnN0IHN0YWNrID0gY2FuU3RhY2sgJiYgbWV0YS5fc3RhY2tlZCAmJiB7a2V5czogZ2V0U29ydGVkRGF0YXNldEluZGljZXMobWUuY2hhcnQsIHRydWUpLCB2YWx1ZXM6IG51bGx9O1xuICAgIGNvbnN0IHJhbmdlID0ge21pbjogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLCBtYXg6IE51bWJlci5ORUdBVElWRV9JTkZJTklUWX07XG4gICAgY29uc3Qge21pbjogb3RoZXJNaW4sIG1heDogb3RoZXJNYXh9ID0gZ2V0VXNlckJvdW5kcyhvdGhlclNjYWxlKTtcbiAgICBsZXQgaSwgdmFsdWUsIHBhcnNlZCwgb3RoZXJWYWx1ZTtcbiAgICBmdW5jdGlvbiBfc2tpcCgpIHtcbiAgICAgIHBhcnNlZCA9IF9wYXJzZWRbaV07XG4gICAgICB2YWx1ZSA9IHBhcnNlZFtzY2FsZS5heGlzXTtcbiAgICAgIG90aGVyVmFsdWUgPSBwYXJzZWRbb3RoZXJTY2FsZS5heGlzXTtcbiAgICAgIHJldHVybiAhaXNOdW1iZXJGaW5pdGUodmFsdWUpIHx8IG90aGVyTWluID4gb3RoZXJWYWx1ZSB8fCBvdGhlck1heCA8IG90aGVyVmFsdWU7XG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGlmIChfc2tpcCgpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgbWUudXBkYXRlUmFuZ2VGcm9tUGFyc2VkKHJhbmdlLCBzY2FsZSwgcGFyc2VkLCBzdGFjayk7XG4gICAgICBpZiAoc29ydGVkKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoc29ydGVkKSB7XG4gICAgICBmb3IgKGkgPSBpbGVuIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgaWYgKF9za2lwKCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBtZS51cGRhdGVSYW5nZUZyb21QYXJzZWQocmFuZ2UsIHNjYWxlLCBwYXJzZWQsIHN0YWNrKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByYW5nZTtcbiAgfVxuICBnZXRBbGxQYXJzZWRWYWx1ZXMoc2NhbGUpIHtcbiAgICBjb25zdCBwYXJzZWQgPSB0aGlzLl9jYWNoZWRNZXRhLl9wYXJzZWQ7XG4gICAgY29uc3QgdmFsdWVzID0gW107XG4gICAgbGV0IGksIGlsZW4sIHZhbHVlO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBwYXJzZWQubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgICB2YWx1ZSA9IHBhcnNlZFtpXVtzY2FsZS5heGlzXTtcbiAgICAgIGlmIChpc051bWJlckZpbml0ZSh2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWVzO1xuICB9XG4gIGdldE1heE92ZXJmbG93KCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBnZXRMYWJlbEFuZFZhbHVlKGluZGV4KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBjb25zdCBpU2NhbGUgPSBtZXRhLmlTY2FsZTtcbiAgICBjb25zdCB2U2NhbGUgPSBtZXRhLnZTY2FsZTtcbiAgICBjb25zdCBwYXJzZWQgPSBtZS5nZXRQYXJzZWQoaW5kZXgpO1xuICAgIHJldHVybiB7XG4gICAgICBsYWJlbDogaVNjYWxlID8gJycgKyBpU2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWRbaVNjYWxlLmF4aXNdKSA6ICcnLFxuICAgICAgdmFsdWU6IHZTY2FsZSA/ICcnICsgdlNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkW3ZTY2FsZS5heGlzXSkgOiAnJ1xuICAgIH07XG4gIH1cbiAgX3VwZGF0ZShtb2RlKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBtZS5jb25maWd1cmUoKTtcbiAgICBtZS5fY2FjaGVkRGF0YU9wdHMgPSB7fTtcbiAgICBtZS51cGRhdGUobW9kZSB8fCAnZGVmYXVsdCcpO1xuICAgIG1ldGEuX2NsaXAgPSB0b0NsaXAodmFsdWVPckRlZmF1bHQobWUub3B0aW9ucy5jbGlwLCBkZWZhdWx0Q2xpcChtZXRhLnhTY2FsZSwgbWV0YS55U2NhbGUsIG1lLmdldE1heE92ZXJmbG93KCkpKSk7XG4gIH1cbiAgdXBkYXRlKG1vZGUpIHt9XG4gIGRyYXcoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGN0eCA9IG1lLl9jdHg7XG4gICAgY29uc3QgY2hhcnQgPSBtZS5jaGFydDtcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgZWxlbWVudHMgPSBtZXRhLmRhdGEgfHwgW107XG4gICAgY29uc3QgYXJlYSA9IGNoYXJ0LmNoYXJ0QXJlYTtcbiAgICBjb25zdCBhY3RpdmUgPSBbXTtcbiAgICBjb25zdCBzdGFydCA9IG1lLl9kcmF3U3RhcnQgfHwgMDtcbiAgICBjb25zdCBjb3VudCA9IG1lLl9kcmF3Q291bnQgfHwgKGVsZW1lbnRzLmxlbmd0aCAtIHN0YXJ0KTtcbiAgICBsZXQgaTtcbiAgICBpZiAobWV0YS5kYXRhc2V0KSB7XG4gICAgICBtZXRhLmRhdGFzZXQuZHJhdyhjdHgsIGFyZWEsIHN0YXJ0LCBjb3VudCk7XG4gICAgfVxuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgKytpKSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gZWxlbWVudHNbaV07XG4gICAgICBpZiAoZWxlbWVudC5oaWRkZW4pIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoZWxlbWVudC5hY3RpdmUpIHtcbiAgICAgICAgYWN0aXZlLnB1c2goZWxlbWVudCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbGVtZW50LmRyYXcoY3R4LCBhcmVhKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IGFjdGl2ZS5sZW5ndGg7ICsraSkge1xuICAgICAgYWN0aXZlW2ldLmRyYXcoY3R4LCBhcmVhKTtcbiAgICB9XG4gIH1cbiAgZ2V0U3R5bGUoaW5kZXgsIGFjdGl2ZSkge1xuICAgIGNvbnN0IG1vZGUgPSBhY3RpdmUgPyAnYWN0aXZlJyA6ICdkZWZhdWx0JztcbiAgICByZXR1cm4gaW5kZXggPT09IHVuZGVmaW5lZCAmJiB0aGlzLl9jYWNoZWRNZXRhLmRhdGFzZXRcbiAgICAgID8gdGhpcy5yZXNvbHZlRGF0YXNldEVsZW1lbnRPcHRpb25zKG1vZGUpXG4gICAgICA6IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpbmRleCB8fCAwLCBtb2RlKTtcbiAgfVxuICBnZXRDb250ZXh0KGluZGV4LCBhY3RpdmUsIG1vZGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgZGF0YXNldCA9IG1lLmdldERhdGFzZXQoKTtcbiAgICBsZXQgY29udGV4dDtcbiAgICBpZiAoaW5kZXggPj0gMCAmJiBpbmRleCA8IG1lLl9jYWNoZWRNZXRhLmRhdGEubGVuZ3RoKSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gbWUuX2NhY2hlZE1ldGEuZGF0YVtpbmRleF07XG4gICAgICBjb250ZXh0ID0gZWxlbWVudC4kY29udGV4dCB8fFxuICAgICAgICAoZWxlbWVudC4kY29udGV4dCA9IGNyZWF0ZURhdGFDb250ZXh0KG1lLmdldENvbnRleHQoKSwgaW5kZXgsIGVsZW1lbnQpKTtcbiAgICAgIGNvbnRleHQucGFyc2VkID0gbWUuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICAgIGNvbnRleHQucmF3ID0gZGF0YXNldC5kYXRhW2luZGV4XTtcbiAgICAgIGNvbnRleHQuaW5kZXggPSBjb250ZXh0LmRhdGFJbmRleCA9IGluZGV4O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0ID0gbWUuJGNvbnRleHQgfHxcbiAgICAgICAgKG1lLiRjb250ZXh0ID0gY3JlYXRlRGF0YXNldENvbnRleHQobWUuY2hhcnQuZ2V0Q29udGV4dCgpLCBtZS5pbmRleCkpO1xuICAgICAgY29udGV4dC5kYXRhc2V0ID0gZGF0YXNldDtcbiAgICAgIGNvbnRleHQuaW5kZXggPSBjb250ZXh0LmRhdGFzZXRJbmRleCA9IG1lLmluZGV4O1xuICAgIH1cbiAgICBjb250ZXh0LmFjdGl2ZSA9ICEhYWN0aXZlO1xuICAgIGNvbnRleHQubW9kZSA9IG1vZGU7XG4gICAgcmV0dXJuIGNvbnRleHQ7XG4gIH1cbiAgcmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyhtb2RlKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Jlc29sdmVFbGVtZW50T3B0aW9ucyh0aGlzLmRhdGFzZXRFbGVtZW50VHlwZS5pZCwgbW9kZSk7XG4gIH1cbiAgcmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpbmRleCwgbW9kZSkge1xuICAgIHJldHVybiB0aGlzLl9yZXNvbHZlRWxlbWVudE9wdGlvbnModGhpcy5kYXRhRWxlbWVudFR5cGUuaWQsIG1vZGUsIGluZGV4KTtcbiAgfVxuICBfcmVzb2x2ZUVsZW1lbnRPcHRpb25zKGVsZW1lbnRUeXBlLCBtb2RlID0gJ2RlZmF1bHQnLCBpbmRleCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBhY3RpdmUgPSBtb2RlID09PSAnYWN0aXZlJztcbiAgICBjb25zdCBjYWNoZSA9IG1lLl9jYWNoZWREYXRhT3B0cztcbiAgICBjb25zdCBjYWNoZUtleSA9IGVsZW1lbnRUeXBlICsgJy0nICsgbW9kZTtcbiAgICBjb25zdCBjYWNoZWQgPSBjYWNoZVtjYWNoZUtleV07XG4gICAgY29uc3Qgc2hhcmluZyA9IG1lLmVuYWJsZU9wdGlvblNoYXJpbmcgJiYgZGVmaW5lZChpbmRleCk7XG4gICAgaWYgKGNhY2hlZCkge1xuICAgICAgcmV0dXJuIGNsb25lSWZOb3RTaGFyZWQoY2FjaGVkLCBzaGFyaW5nKTtcbiAgICB9XG4gICAgY29uc3QgY29uZmlnID0gbWUuY2hhcnQuY29uZmlnO1xuICAgIGNvbnN0IHNjb3BlS2V5cyA9IGNvbmZpZy5kYXRhc2V0RWxlbWVudFNjb3BlS2V5cyhtZS5fdHlwZSwgZWxlbWVudFR5cGUpO1xuICAgIGNvbnN0IHByZWZpeGVzID0gYWN0aXZlID8gW2Ake2VsZW1lbnRUeXBlfUhvdmVyYCwgJ2hvdmVyJywgZWxlbWVudFR5cGUsICcnXSA6IFtlbGVtZW50VHlwZSwgJyddO1xuICAgIGNvbnN0IHNjb3BlcyA9IGNvbmZpZy5nZXRPcHRpb25TY29wZXMobWUuZ2V0RGF0YXNldCgpLCBzY29wZUtleXMpO1xuICAgIGNvbnN0IG5hbWVzID0gT2JqZWN0LmtleXMoZGVmYXVsdHMuZWxlbWVudHNbZWxlbWVudFR5cGVdKTtcbiAgICBjb25zdCBjb250ZXh0ID0gKCkgPT4gbWUuZ2V0Q29udGV4dChpbmRleCwgYWN0aXZlKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBjb25maWcucmVzb2x2ZU5hbWVkT3B0aW9ucyhzY29wZXMsIG5hbWVzLCBjb250ZXh0LCBwcmVmaXhlcyk7XG4gICAgaWYgKHZhbHVlcy4kc2hhcmVkKSB7XG4gICAgICB2YWx1ZXMuJHNoYXJlZCA9IHNoYXJpbmc7XG4gICAgICBjYWNoZVtjYWNoZUtleV0gPSBPYmplY3QuZnJlZXplKGNsb25lSWZOb3RTaGFyZWQodmFsdWVzLCBzaGFyaW5nKSk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH1cbiAgX3Jlc29sdmVBbmltYXRpb25zKGluZGV4LCB0cmFuc2l0aW9uLCBhY3RpdmUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgY2hhcnQgPSBtZS5jaGFydDtcbiAgICBjb25zdCBjYWNoZSA9IG1lLl9jYWNoZWREYXRhT3B0cztcbiAgICBjb25zdCBjYWNoZUtleSA9IGBhbmltYXRpb24tJHt0cmFuc2l0aW9ufWA7XG4gICAgY29uc3QgY2FjaGVkID0gY2FjaGVbY2FjaGVLZXldO1xuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuICAgIGxldCBvcHRpb25zO1xuICAgIGlmIChjaGFydC5vcHRpb25zLmFuaW1hdGlvbiAhPT0gZmFsc2UpIHtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IG1lLmNoYXJ0LmNvbmZpZztcbiAgICAgIGNvbnN0IHNjb3BlS2V5cyA9IGNvbmZpZy5kYXRhc2V0QW5pbWF0aW9uU2NvcGVLZXlzKG1lLl90eXBlLCB0cmFuc2l0aW9uKTtcbiAgICAgIGNvbnN0IHNjb3BlcyA9IGNvbmZpZy5nZXRPcHRpb25TY29wZXMobWUuZ2V0RGF0YXNldCgpLCBzY29wZUtleXMpO1xuICAgICAgb3B0aW9ucyA9IGNvbmZpZy5jcmVhdGVSZXNvbHZlcihzY29wZXMsIG1lLmdldENvbnRleHQoaW5kZXgsIGFjdGl2ZSwgdHJhbnNpdGlvbikpO1xuICAgIH1cbiAgICBjb25zdCBhbmltYXRpb25zID0gbmV3IEFuaW1hdGlvbnMoY2hhcnQsIG9wdGlvbnMgJiYgb3B0aW9ucy5hbmltYXRpb25zKTtcbiAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLl9jYWNoZWFibGUpIHtcbiAgICAgIGNhY2hlW2NhY2hlS2V5XSA9IE9iamVjdC5mcmVlemUoYW5pbWF0aW9ucyk7XG4gICAgfVxuICAgIHJldHVybiBhbmltYXRpb25zO1xuICB9XG4gIGdldFNoYXJlZE9wdGlvbnMob3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucy4kc2hhcmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9zaGFyZWRPcHRpb25zIHx8ICh0aGlzLl9zaGFyZWRPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgb3B0aW9ucykpO1xuICB9XG4gIGluY2x1ZGVPcHRpb25zKG1vZGUsIHNoYXJlZE9wdGlvbnMpIHtcbiAgICByZXR1cm4gIXNoYXJlZE9wdGlvbnMgfHwgaXNEaXJlY3RVcGRhdGVNb2RlKG1vZGUpIHx8IHRoaXMuY2hhcnQuX2FuaW1hdGlvbnNEaXNhYmxlZDtcbiAgfVxuICB1cGRhdGVFbGVtZW50KGVsZW1lbnQsIGluZGV4LCBwcm9wZXJ0aWVzLCBtb2RlKSB7XG4gICAgaWYgKGlzRGlyZWN0VXBkYXRlTW9kZShtb2RlKSkge1xuICAgICAgT2JqZWN0LmFzc2lnbihlbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnMoaW5kZXgsIG1vZGUpLnVwZGF0ZShlbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICB9XG4gIH1cbiAgdXBkYXRlU2hhcmVkT3B0aW9ucyhzaGFyZWRPcHRpb25zLCBtb2RlLCBuZXdPcHRpb25zKSB7XG4gICAgaWYgKHNoYXJlZE9wdGlvbnMgJiYgIWlzRGlyZWN0VXBkYXRlTW9kZShtb2RlKSkge1xuICAgICAgdGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnModW5kZWZpbmVkLCBtb2RlKS51cGRhdGUoc2hhcmVkT3B0aW9ucywgbmV3T3B0aW9ucyk7XG4gICAgfVxuICB9XG4gIF9zZXRTdHlsZShlbGVtZW50LCBpbmRleCwgbW9kZSwgYWN0aXZlKSB7XG4gICAgZWxlbWVudC5hY3RpdmUgPSBhY3RpdmU7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuZ2V0U3R5bGUoaW5kZXgsIGFjdGl2ZSk7XG4gICAgdGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnMoaW5kZXgsIG1vZGUsIGFjdGl2ZSkudXBkYXRlKGVsZW1lbnQsIHtcbiAgICAgIG9wdGlvbnM6ICghYWN0aXZlICYmIHRoaXMuZ2V0U2hhcmVkT3B0aW9ucyhvcHRpb25zKSkgfHwgb3B0aW9uc1xuICAgIH0pO1xuICB9XG4gIHJlbW92ZUhvdmVyU3R5bGUoZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleCkge1xuICAgIHRoaXMuX3NldFN0eWxlKGVsZW1lbnQsIGluZGV4LCAnYWN0aXZlJywgZmFsc2UpO1xuICB9XG4gIHNldEhvdmVyU3R5bGUoZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleCkge1xuICAgIHRoaXMuX3NldFN0eWxlKGVsZW1lbnQsIGluZGV4LCAnYWN0aXZlJywgdHJ1ZSk7XG4gIH1cbiAgX3JlbW92ZURhdGFzZXRIb3ZlclN0eWxlKCkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGFzZXQ7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX3NldFN0eWxlKGVsZW1lbnQsIHVuZGVmaW5lZCwgJ2FjdGl2ZScsIGZhbHNlKTtcbiAgICB9XG4gIH1cbiAgX3NldERhdGFzZXRIb3ZlclN0eWxlKCkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGFzZXQ7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX3NldFN0eWxlKGVsZW1lbnQsIHVuZGVmaW5lZCwgJ2FjdGl2ZScsIHRydWUpO1xuICAgIH1cbiAgfVxuICBfcmVzeW5jRWxlbWVudHMocmVzZXROZXdFbGVtZW50cykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBkYXRhID0gbWUuX2RhdGE7XG4gICAgY29uc3QgZWxlbWVudHMgPSBtZS5fY2FjaGVkTWV0YS5kYXRhO1xuICAgIGZvciAoY29uc3QgW21ldGhvZCwgYXJnMSwgYXJnMl0gb2YgbWUuX3N5bmNMaXN0KSB7XG4gICAgICBtZVttZXRob2RdKGFyZzEsIGFyZzIpO1xuICAgIH1cbiAgICBtZS5fc3luY0xpc3QgPSBbXTtcbiAgICBjb25zdCBudW1NZXRhID0gZWxlbWVudHMubGVuZ3RoO1xuICAgIGNvbnN0IG51bURhdGEgPSBkYXRhLmxlbmd0aDtcbiAgICBjb25zdCBjb3VudCA9IE1hdGgubWluKG51bURhdGEsIG51bU1ldGEpO1xuICAgIGlmIChjb3VudCkge1xuICAgICAgbWUucGFyc2UoMCwgY291bnQpO1xuICAgIH1cbiAgICBpZiAobnVtRGF0YSA+IG51bU1ldGEpIHtcbiAgICAgIG1lLl9pbnNlcnRFbGVtZW50cyhudW1NZXRhLCBudW1EYXRhIC0gbnVtTWV0YSwgcmVzZXROZXdFbGVtZW50cyk7XG4gICAgfSBlbHNlIGlmIChudW1EYXRhIDwgbnVtTWV0YSkge1xuICAgICAgbWUuX3JlbW92ZUVsZW1lbnRzKG51bURhdGEsIG51bU1ldGEgLSBudW1EYXRhKTtcbiAgICB9XG4gIH1cbiAgX2luc2VydEVsZW1lbnRzKHN0YXJ0LCBjb3VudCwgcmVzZXROZXdFbGVtZW50cyA9IHRydWUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbWV0YSA9IG1lLl9jYWNoZWRNZXRhO1xuICAgIGNvbnN0IGRhdGEgPSBtZXRhLmRhdGE7XG4gICAgY29uc3QgZW5kID0gc3RhcnQgKyBjb3VudDtcbiAgICBsZXQgaTtcbiAgICBjb25zdCBtb3ZlID0gKGFycikgPT4ge1xuICAgICAgYXJyLmxlbmd0aCArPSBjb3VudDtcbiAgICAgIGZvciAoaSA9IGFyci5sZW5ndGggLSAxOyBpID49IGVuZDsgaS0tKSB7XG4gICAgICAgIGFycltpXSA9IGFycltpIC0gY291bnRdO1xuICAgICAgfVxuICAgIH07XG4gICAgbW92ZShkYXRhKTtcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgICBkYXRhW2ldID0gbmV3IG1lLmRhdGFFbGVtZW50VHlwZSgpO1xuICAgIH1cbiAgICBpZiAobWUuX3BhcnNpbmcpIHtcbiAgICAgIG1vdmUobWV0YS5fcGFyc2VkKTtcbiAgICB9XG4gICAgbWUucGFyc2Uoc3RhcnQsIGNvdW50KTtcbiAgICBpZiAocmVzZXROZXdFbGVtZW50cykge1xuICAgICAgbWUudXBkYXRlRWxlbWVudHMoZGF0YSwgc3RhcnQsIGNvdW50LCAncmVzZXQnKTtcbiAgICB9XG4gIH1cbiAgdXBkYXRlRWxlbWVudHMoZWxlbWVudCwgc3RhcnQsIGNvdW50LCBtb2RlKSB7fVxuICBfcmVtb3ZlRWxlbWVudHMoc3RhcnQsIGNvdW50KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBpZiAobWUuX3BhcnNpbmcpIHtcbiAgICAgIGNvbnN0IHJlbW92ZWQgPSBtZXRhLl9wYXJzZWQuc3BsaWNlKHN0YXJ0LCBjb3VudCk7XG4gICAgICBpZiAobWV0YS5fc3RhY2tlZCkge1xuICAgICAgICBjbGVhclN0YWNrcyhtZXRhLCByZW1vdmVkKTtcbiAgICAgIH1cbiAgICB9XG4gICAgbWV0YS5kYXRhLnNwbGljZShzdGFydCwgY291bnQpO1xuICB9XG4gIF9zeW5jKGFyZ3MpIHtcbiAgICBpZiAodGhpcy5fcGFyc2luZykge1xuICAgICAgdGhpcy5fc3luY0xpc3QucHVzaChhcmdzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgW21ldGhvZCwgYXJnMSwgYXJnMl0gPSBhcmdzO1xuICAgICAgdGhpc1ttZXRob2RdKGFyZzEsIGFyZzIpO1xuICAgIH1cbiAgfVxuICBfb25EYXRhUHVzaCgpIHtcbiAgICBjb25zdCBjb3VudCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgdGhpcy5fc3luYyhbJ19pbnNlcnRFbGVtZW50cycsIHRoaXMuZ2V0RGF0YXNldCgpLmRhdGEubGVuZ3RoIC0gY291bnQsIGNvdW50XSk7XG4gIH1cbiAgX29uRGF0YVBvcCgpIHtcbiAgICB0aGlzLl9zeW5jKFsnX3JlbW92ZUVsZW1lbnRzJywgdGhpcy5fY2FjaGVkTWV0YS5kYXRhLmxlbmd0aCAtIDEsIDFdKTtcbiAgfVxuICBfb25EYXRhU2hpZnQoKSB7XG4gICAgdGhpcy5fc3luYyhbJ19yZW1vdmVFbGVtZW50cycsIDAsIDFdKTtcbiAgfVxuICBfb25EYXRhU3BsaWNlKHN0YXJ0LCBjb3VudCkge1xuICAgIHRoaXMuX3N5bmMoWydfcmVtb3ZlRWxlbWVudHMnLCBzdGFydCwgY291bnRdKTtcbiAgICB0aGlzLl9zeW5jKFsnX2luc2VydEVsZW1lbnRzJywgc3RhcnQsIGFyZ3VtZW50cy5sZW5ndGggLSAyXSk7XG4gIH1cbiAgX29uRGF0YVVuc2hpZnQoKSB7XG4gICAgdGhpcy5fc3luYyhbJ19pbnNlcnRFbGVtZW50cycsIDAsIGFyZ3VtZW50cy5sZW5ndGhdKTtcbiAgfVxufVxuRGF0YXNldENvbnRyb2xsZXIuZGVmYXVsdHMgPSB7fTtcbkRhdGFzZXRDb250cm9sbGVyLnByb3RvdHlwZS5kYXRhc2V0RWxlbWVudFR5cGUgPSBudWxsO1xuRGF0YXNldENvbnRyb2xsZXIucHJvdG90eXBlLmRhdGFFbGVtZW50VHlwZSA9IG51bGw7XG5cbmZ1bmN0aW9uIGdldEFsbFNjYWxlVmFsdWVzKHNjYWxlKSB7XG4gIGlmICghc2NhbGUuX2NhY2hlLiRiYXIpIHtcbiAgICBjb25zdCBtZXRhcyA9IHNjYWxlLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKCdiYXInKTtcbiAgICBsZXQgdmFsdWVzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDAsIGlsZW4gPSBtZXRhcy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspIHtcbiAgICAgIHZhbHVlcyA9IHZhbHVlcy5jb25jYXQobWV0YXNbaV0uY29udHJvbGxlci5nZXRBbGxQYXJzZWRWYWx1ZXMoc2NhbGUpKTtcbiAgICB9XG4gICAgc2NhbGUuX2NhY2hlLiRiYXIgPSBfYXJyYXlVbmlxdWUodmFsdWVzLnNvcnQoKGEsIGIpID0+IGEgLSBiKSk7XG4gIH1cbiAgcmV0dXJuIHNjYWxlLl9jYWNoZS4kYmFyO1xufVxuZnVuY3Rpb24gY29tcHV0ZU1pblNhbXBsZVNpemUoc2NhbGUpIHtcbiAgY29uc3QgdmFsdWVzID0gZ2V0QWxsU2NhbGVWYWx1ZXMoc2NhbGUpO1xuICBsZXQgbWluID0gc2NhbGUuX2xlbmd0aDtcbiAgbGV0IGksIGlsZW4sIGN1cnIsIHByZXY7XG4gIGNvbnN0IHVwZGF0ZU1pbkFuZFByZXYgPSAoKSA9PiB7XG4gICAgaWYgKGN1cnIgPT09IDMyNzY3IHx8IGN1cnIgPT09IC0zMjc2OCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZGVmaW5lZChwcmV2KSkge1xuICAgICAgbWluID0gTWF0aC5taW4obWluLCBNYXRoLmFicyhjdXJyIC0gcHJldikgfHwgbWluKTtcbiAgICB9XG4gICAgcHJldiA9IGN1cnI7XG4gIH07XG4gIGZvciAoaSA9IDAsIGlsZW4gPSB2YWx1ZXMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgY3VyciA9IHNjYWxlLmdldFBpeGVsRm9yVmFsdWUodmFsdWVzW2ldKTtcbiAgICB1cGRhdGVNaW5BbmRQcmV2KCk7XG4gIH1cbiAgcHJldiA9IHVuZGVmaW5lZDtcbiAgZm9yIChpID0gMCwgaWxlbiA9IHNjYWxlLnRpY2tzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgIGN1cnIgPSBzY2FsZS5nZXRQaXhlbEZvclRpY2soaSk7XG4gICAgdXBkYXRlTWluQW5kUHJldigpO1xuICB9XG4gIHJldHVybiBtaW47XG59XG5mdW5jdGlvbiBjb21wdXRlRml0Q2F0ZWdvcnlUcmFpdHMoaW5kZXgsIHJ1bGVyLCBvcHRpb25zLCBzdGFja0NvdW50KSB7XG4gIGNvbnN0IHRoaWNrbmVzcyA9IG9wdGlvbnMuYmFyVGhpY2tuZXNzO1xuICBsZXQgc2l6ZSwgcmF0aW87XG4gIGlmIChpc051bGxPclVuZGVmKHRoaWNrbmVzcykpIHtcbiAgICBzaXplID0gcnVsZXIubWluICogb3B0aW9ucy5jYXRlZ29yeVBlcmNlbnRhZ2U7XG4gICAgcmF0aW8gPSBvcHRpb25zLmJhclBlcmNlbnRhZ2U7XG4gIH0gZWxzZSB7XG4gICAgc2l6ZSA9IHRoaWNrbmVzcyAqIHN0YWNrQ291bnQ7XG4gICAgcmF0aW8gPSAxO1xuICB9XG4gIHJldHVybiB7XG4gICAgY2h1bms6IHNpemUgLyBzdGFja0NvdW50LFxuICAgIHJhdGlvLFxuICAgIHN0YXJ0OiBydWxlci5waXhlbHNbaW5kZXhdIC0gKHNpemUgLyAyKVxuICB9O1xufVxuZnVuY3Rpb24gY29tcHV0ZUZsZXhDYXRlZ29yeVRyYWl0cyhpbmRleCwgcnVsZXIsIG9wdGlvbnMsIHN0YWNrQ291bnQpIHtcbiAgY29uc3QgcGl4ZWxzID0gcnVsZXIucGl4ZWxzO1xuICBjb25zdCBjdXJyID0gcGl4ZWxzW2luZGV4XTtcbiAgbGV0IHByZXYgPSBpbmRleCA+IDAgPyBwaXhlbHNbaW5kZXggLSAxXSA6IG51bGw7XG4gIGxldCBuZXh0ID0gaW5kZXggPCBwaXhlbHMubGVuZ3RoIC0gMSA/IHBpeGVsc1tpbmRleCArIDFdIDogbnVsbDtcbiAgY29uc3QgcGVyY2VudCA9IG9wdGlvbnMuY2F0ZWdvcnlQZXJjZW50YWdlO1xuICBpZiAocHJldiA9PT0gbnVsbCkge1xuICAgIHByZXYgPSBjdXJyIC0gKG5leHQgPT09IG51bGwgPyBydWxlci5lbmQgLSBydWxlci5zdGFydCA6IG5leHQgLSBjdXJyKTtcbiAgfVxuICBpZiAobmV4dCA9PT0gbnVsbCkge1xuICAgIG5leHQgPSBjdXJyICsgY3VyciAtIHByZXY7XG4gIH1cbiAgY29uc3Qgc3RhcnQgPSBjdXJyIC0gKGN1cnIgLSBNYXRoLm1pbihwcmV2LCBuZXh0KSkgLyAyICogcGVyY2VudDtcbiAgY29uc3Qgc2l6ZSA9IE1hdGguYWJzKG5leHQgLSBwcmV2KSAvIDIgKiBwZXJjZW50O1xuICByZXR1cm4ge1xuICAgIGNodW5rOiBzaXplIC8gc3RhY2tDb3VudCxcbiAgICByYXRpbzogb3B0aW9ucy5iYXJQZXJjZW50YWdlLFxuICAgIHN0YXJ0XG4gIH07XG59XG5mdW5jdGlvbiBwYXJzZUZsb2F0QmFyKGVudHJ5LCBpdGVtLCB2U2NhbGUsIGkpIHtcbiAgY29uc3Qgc3RhcnRWYWx1ZSA9IHZTY2FsZS5wYXJzZShlbnRyeVswXSwgaSk7XG4gIGNvbnN0IGVuZFZhbHVlID0gdlNjYWxlLnBhcnNlKGVudHJ5WzFdLCBpKTtcbiAgY29uc3QgbWluID0gTWF0aC5taW4oc3RhcnRWYWx1ZSwgZW5kVmFsdWUpO1xuICBjb25zdCBtYXggPSBNYXRoLm1heChzdGFydFZhbHVlLCBlbmRWYWx1ZSk7XG4gIGxldCBiYXJTdGFydCA9IG1pbjtcbiAgbGV0IGJhckVuZCA9IG1heDtcbiAgaWYgKE1hdGguYWJzKG1pbikgPiBNYXRoLmFicyhtYXgpKSB7XG4gICAgYmFyU3RhcnQgPSBtYXg7XG4gICAgYmFyRW5kID0gbWluO1xuICB9XG4gIGl0ZW1bdlNjYWxlLmF4aXNdID0gYmFyRW5kO1xuICBpdGVtLl9jdXN0b20gPSB7XG4gICAgYmFyU3RhcnQsXG4gICAgYmFyRW5kLFxuICAgIHN0YXJ0OiBzdGFydFZhbHVlLFxuICAgIGVuZDogZW5kVmFsdWUsXG4gICAgbWluLFxuICAgIG1heFxuICB9O1xufVxuZnVuY3Rpb24gcGFyc2VWYWx1ZShlbnRyeSwgaXRlbSwgdlNjYWxlLCBpKSB7XG4gIGlmIChpc0FycmF5KGVudHJ5KSkge1xuICAgIHBhcnNlRmxvYXRCYXIoZW50cnksIGl0ZW0sIHZTY2FsZSwgaSk7XG4gIH0gZWxzZSB7XG4gICAgaXRlbVt2U2NhbGUuYXhpc10gPSB2U2NhbGUucGFyc2UoZW50cnksIGkpO1xuICB9XG4gIHJldHVybiBpdGVtO1xufVxuZnVuY3Rpb24gcGFyc2VBcnJheU9yUHJpbWl0aXZlKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICBjb25zdCBpU2NhbGUgPSBtZXRhLmlTY2FsZTtcbiAgY29uc3QgdlNjYWxlID0gbWV0YS52U2NhbGU7XG4gIGNvbnN0IGxhYmVscyA9IGlTY2FsZS5nZXRMYWJlbHMoKTtcbiAgY29uc3Qgc2luZ2xlU2NhbGUgPSBpU2NhbGUgPT09IHZTY2FsZTtcbiAgY29uc3QgcGFyc2VkID0gW107XG4gIGxldCBpLCBpbGVuLCBpdGVtLCBlbnRyeTtcbiAgZm9yIChpID0gc3RhcnQsIGlsZW4gPSBzdGFydCArIGNvdW50OyBpIDwgaWxlbjsgKytpKSB7XG4gICAgZW50cnkgPSBkYXRhW2ldO1xuICAgIGl0ZW0gPSB7fTtcbiAgICBpdGVtW2lTY2FsZS5heGlzXSA9IHNpbmdsZVNjYWxlIHx8IGlTY2FsZS5wYXJzZShsYWJlbHNbaV0sIGkpO1xuICAgIHBhcnNlZC5wdXNoKHBhcnNlVmFsdWUoZW50cnksIGl0ZW0sIHZTY2FsZSwgaSkpO1xuICB9XG4gIHJldHVybiBwYXJzZWQ7XG59XG5mdW5jdGlvbiBpc0Zsb2F0QmFyKGN1c3RvbSkge1xuICByZXR1cm4gY3VzdG9tICYmIGN1c3RvbS5iYXJTdGFydCAhPT0gdW5kZWZpbmVkICYmIGN1c3RvbS5iYXJFbmQgIT09IHVuZGVmaW5lZDtcbn1cbmZ1bmN0aW9uIGJhclNpZ24oc2l6ZSwgdlNjYWxlLCBhY3R1YWxCYXNlKSB7XG4gIGlmIChzaXplICE9PSAwKSB7XG4gICAgcmV0dXJuIHNpZ24oc2l6ZSk7XG4gIH1cbiAgcmV0dXJuICh2U2NhbGUuaXNIb3Jpem9udGFsKCkgPyAxIDogLTEpICogKHZTY2FsZS5taW4gPj0gYWN0dWFsQmFzZSA/IDEgOiAtMSk7XG59XG5mdW5jdGlvbiBib3JkZXJQcm9wcyhwcm9wZXJ0aWVzKSB7XG4gIGxldCByZXZlcnNlLCBzdGFydCwgZW5kLCB0b3AsIGJvdHRvbTtcbiAgaWYgKHByb3BlcnRpZXMuaG9yaXpvbnRhbCkge1xuICAgIHJldmVyc2UgPSBwcm9wZXJ0aWVzLmJhc2UgPiBwcm9wZXJ0aWVzLng7XG4gICAgc3RhcnQgPSAnbGVmdCc7XG4gICAgZW5kID0gJ3JpZ2h0JztcbiAgfSBlbHNlIHtcbiAgICByZXZlcnNlID0gcHJvcGVydGllcy5iYXNlIDwgcHJvcGVydGllcy55O1xuICAgIHN0YXJ0ID0gJ2JvdHRvbSc7XG4gICAgZW5kID0gJ3RvcCc7XG4gIH1cbiAgaWYgKHJldmVyc2UpIHtcbiAgICB0b3AgPSAnZW5kJztcbiAgICBib3R0b20gPSAnc3RhcnQnO1xuICB9IGVsc2Uge1xuICAgIHRvcCA9ICdzdGFydCc7XG4gICAgYm90dG9tID0gJ2VuZCc7XG4gIH1cbiAgcmV0dXJuIHtzdGFydCwgZW5kLCByZXZlcnNlLCB0b3AsIGJvdHRvbX07XG59XG5mdW5jdGlvbiBzZXRCb3JkZXJTa2lwcGVkKHByb3BlcnRpZXMsIG9wdGlvbnMsIHN0YWNrLCBpbmRleCkge1xuICBsZXQgZWRnZSA9IG9wdGlvbnMuYm9yZGVyU2tpcHBlZDtcbiAgY29uc3QgcmVzID0ge307XG4gIGlmICghZWRnZSkge1xuICAgIHByb3BlcnRpZXMuYm9yZGVyU2tpcHBlZCA9IHJlcztcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qge3N0YXJ0LCBlbmQsIHJldmVyc2UsIHRvcCwgYm90dG9tfSA9IGJvcmRlclByb3BzKHByb3BlcnRpZXMpO1xuICBpZiAoZWRnZSA9PT0gJ21pZGRsZScgJiYgc3RhY2spIHtcbiAgICBwcm9wZXJ0aWVzLmVuYWJsZUJvcmRlclJhZGl1cyA9IHRydWU7XG4gICAgaWYgKChzdGFjay5fdG9wIHx8IDApID09PSBpbmRleCkge1xuICAgICAgZWRnZSA9IHRvcDtcbiAgICB9IGVsc2UgaWYgKChzdGFjay5fYm90dG9tIHx8IDApID09PSBpbmRleCkge1xuICAgICAgZWRnZSA9IGJvdHRvbTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzW3BhcnNlRWRnZShib3R0b20sIHN0YXJ0LCBlbmQsIHJldmVyc2UpXSA9IHRydWU7XG4gICAgICBlZGdlID0gdG9wO1xuICAgIH1cbiAgfVxuICByZXNbcGFyc2VFZGdlKGVkZ2UsIHN0YXJ0LCBlbmQsIHJldmVyc2UpXSA9IHRydWU7XG4gIHByb3BlcnRpZXMuYm9yZGVyU2tpcHBlZCA9IHJlcztcbn1cbmZ1bmN0aW9uIHBhcnNlRWRnZShlZGdlLCBhLCBiLCByZXZlcnNlKSB7XG4gIGlmIChyZXZlcnNlKSB7XG4gICAgZWRnZSA9IHN3YXAoZWRnZSwgYSwgYik7XG4gICAgZWRnZSA9IHN0YXJ0RW5kKGVkZ2UsIGIsIGEpO1xuICB9IGVsc2Uge1xuICAgIGVkZ2UgPSBzdGFydEVuZChlZGdlLCBhLCBiKTtcbiAgfVxuICByZXR1cm4gZWRnZTtcbn1cbmZ1bmN0aW9uIHN3YXAob3JpZywgdjEsIHYyKSB7XG4gIHJldHVybiBvcmlnID09PSB2MSA/IHYyIDogb3JpZyA9PT0gdjIgPyB2MSA6IG9yaWc7XG59XG5mdW5jdGlvbiBzdGFydEVuZCh2LCBzdGFydCwgZW5kKSB7XG4gIHJldHVybiB2ID09PSAnc3RhcnQnID8gc3RhcnQgOiB2ID09PSAnZW5kJyA/IGVuZCA6IHY7XG59XG5jbGFzcyBCYXJDb250cm9sbGVyIGV4dGVuZHMgRGF0YXNldENvbnRyb2xsZXIge1xuICBwYXJzZVByaW1pdGl2ZURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgcmV0dXJuIHBhcnNlQXJyYXlPclByaW1pdGl2ZShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICB9XG4gIHBhcnNlQXJyYXlEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgIHJldHVybiBwYXJzZUFycmF5T3JQcmltaXRpdmUobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgfVxuICBwYXJzZU9iamVjdERhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgY29uc3Qge2lTY2FsZSwgdlNjYWxlfSA9IG1ldGE7XG4gICAgY29uc3Qge3hBeGlzS2V5ID0gJ3gnLCB5QXhpc0tleSA9ICd5J30gPSB0aGlzLl9wYXJzaW5nO1xuICAgIGNvbnN0IGlBeGlzS2V5ID0gaVNjYWxlLmF4aXMgPT09ICd4JyA/IHhBeGlzS2V5IDogeUF4aXNLZXk7XG4gICAgY29uc3QgdkF4aXNLZXkgPSB2U2NhbGUuYXhpcyA9PT0gJ3gnID8geEF4aXNLZXkgOiB5QXhpc0tleTtcbiAgICBjb25zdCBwYXJzZWQgPSBbXTtcbiAgICBsZXQgaSwgaWxlbiwgaXRlbSwgb2JqO1xuICAgIGZvciAoaSA9IHN0YXJ0LCBpbGVuID0gc3RhcnQgKyBjb3VudDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgb2JqID0gZGF0YVtpXTtcbiAgICAgIGl0ZW0gPSB7fTtcbiAgICAgIGl0ZW1baVNjYWxlLmF4aXNdID0gaVNjYWxlLnBhcnNlKHJlc29sdmVPYmplY3RLZXkob2JqLCBpQXhpc0tleSksIGkpO1xuICAgICAgcGFyc2VkLnB1c2gocGFyc2VWYWx1ZShyZXNvbHZlT2JqZWN0S2V5KG9iaiwgdkF4aXNLZXkpLCBpdGVtLCB2U2NhbGUsIGkpKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlZDtcbiAgfVxuICB1cGRhdGVSYW5nZUZyb21QYXJzZWQocmFuZ2UsIHNjYWxlLCBwYXJzZWQsIHN0YWNrKSB7XG4gICAgc3VwZXIudXBkYXRlUmFuZ2VGcm9tUGFyc2VkKHJhbmdlLCBzY2FsZSwgcGFyc2VkLCBzdGFjayk7XG4gICAgY29uc3QgY3VzdG9tID0gcGFyc2VkLl9jdXN0b207XG4gICAgaWYgKGN1c3RvbSAmJiBzY2FsZSA9PT0gdGhpcy5fY2FjaGVkTWV0YS52U2NhbGUpIHtcbiAgICAgIHJhbmdlLm1pbiA9IE1hdGgubWluKHJhbmdlLm1pbiwgY3VzdG9tLm1pbik7XG4gICAgICByYW5nZS5tYXggPSBNYXRoLm1heChyYW5nZS5tYXgsIGN1c3RvbS5tYXgpO1xuICAgIH1cbiAgfVxuICBnZXRNYXhPdmVyZmxvdygpIHtcbiAgICByZXR1cm4gMDtcbiAgfVxuICBnZXRMYWJlbEFuZFZhbHVlKGluZGV4KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBjb25zdCB7aVNjYWxlLCB2U2NhbGV9ID0gbWV0YTtcbiAgICBjb25zdCBwYXJzZWQgPSBtZS5nZXRQYXJzZWQoaW5kZXgpO1xuICAgIGNvbnN0IGN1c3RvbSA9IHBhcnNlZC5fY3VzdG9tO1xuICAgIGNvbnN0IHZhbHVlID0gaXNGbG9hdEJhcihjdXN0b20pXG4gICAgICA/ICdbJyArIGN1c3RvbS5zdGFydCArICcsICcgKyBjdXN0b20uZW5kICsgJ10nXG4gICAgICA6ICcnICsgdlNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkW3ZTY2FsZS5heGlzXSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsOiAnJyArIGlTY2FsZS5nZXRMYWJlbEZvclZhbHVlKHBhcnNlZFtpU2NhbGUuYXhpc10pLFxuICAgICAgdmFsdWVcbiAgICB9O1xuICB9XG4gIGluaXRpYWxpemUoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIG1lLmVuYWJsZU9wdGlvblNoYXJpbmcgPSB0cnVlO1xuICAgIHN1cGVyLmluaXRpYWxpemUoKTtcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgbWV0YS5zdGFjayA9IG1lLmdldERhdGFzZXQoKS5zdGFjaztcbiAgfVxuICB1cGRhdGUobW9kZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgbWUudXBkYXRlRWxlbWVudHMobWV0YS5kYXRhLCAwLCBtZXRhLmRhdGEubGVuZ3RoLCBtb2RlKTtcbiAgfVxuICB1cGRhdGVFbGVtZW50cyhiYXJzLCBzdGFydCwgY291bnQsIG1vZGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgcmVzZXQgPSBtb2RlID09PSAncmVzZXQnO1xuICAgIGNvbnN0IHtpbmRleCwgX2NhY2hlZE1ldGE6IHt2U2NhbGV9fSA9IG1lO1xuICAgIGNvbnN0IGJhc2UgPSB2U2NhbGUuZ2V0QmFzZVBpeGVsKCk7XG4gICAgY29uc3QgaG9yaXpvbnRhbCA9IHZTY2FsZS5pc0hvcml6b250YWwoKTtcbiAgICBjb25zdCBydWxlciA9IG1lLl9nZXRSdWxlcigpO1xuICAgIGNvbnN0IGZpcnN0T3B0cyA9IG1lLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoc3RhcnQsIG1vZGUpO1xuICAgIGNvbnN0IHNoYXJlZE9wdGlvbnMgPSBtZS5nZXRTaGFyZWRPcHRpb25zKGZpcnN0T3B0cyk7XG4gICAgY29uc3QgaW5jbHVkZU9wdGlvbnMgPSBtZS5pbmNsdWRlT3B0aW9ucyhtb2RlLCBzaGFyZWRPcHRpb25zKTtcbiAgICBtZS51cGRhdGVTaGFyZWRPcHRpb25zKHNoYXJlZE9wdGlvbnMsIG1vZGUsIGZpcnN0T3B0cyk7XG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBtZS5nZXRQYXJzZWQoaSk7XG4gICAgICBjb25zdCB2cGl4ZWxzID0gcmVzZXQgfHwgaXNOdWxsT3JVbmRlZihwYXJzZWRbdlNjYWxlLmF4aXNdKSA/IHtiYXNlLCBoZWFkOiBiYXNlfSA6IG1lLl9jYWxjdWxhdGVCYXJWYWx1ZVBpeGVscyhpKTtcbiAgICAgIGNvbnN0IGlwaXhlbHMgPSBtZS5fY2FsY3VsYXRlQmFySW5kZXhQaXhlbHMoaSwgcnVsZXIpO1xuICAgICAgY29uc3Qgc3RhY2sgPSAocGFyc2VkLl9zdGFja3MgfHwge30pW3ZTY2FsZS5heGlzXTtcbiAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGhvcml6b250YWwsXG4gICAgICAgIGJhc2U6IHZwaXhlbHMuYmFzZSxcbiAgICAgICAgZW5hYmxlQm9yZGVyUmFkaXVzOiAhc3RhY2sgfHwgaXNGbG9hdEJhcihwYXJzZWQuX2N1c3RvbSkgfHwgKGluZGV4ID09PSBzdGFjay5fdG9wIHx8IGluZGV4ID09PSBzdGFjay5fYm90dG9tKSxcbiAgICAgICAgeDogaG9yaXpvbnRhbCA/IHZwaXhlbHMuaGVhZCA6IGlwaXhlbHMuY2VudGVyLFxuICAgICAgICB5OiBob3Jpem9udGFsID8gaXBpeGVscy5jZW50ZXIgOiB2cGl4ZWxzLmhlYWQsXG4gICAgICAgIGhlaWdodDogaG9yaXpvbnRhbCA/IGlwaXhlbHMuc2l6ZSA6IE1hdGguYWJzKHZwaXhlbHMuc2l6ZSksXG4gICAgICAgIHdpZHRoOiBob3Jpem9udGFsID8gTWF0aC5hYnModnBpeGVscy5zaXplKSA6IGlwaXhlbHMuc2l6ZVxuICAgICAgfTtcbiAgICAgIGlmIChpbmNsdWRlT3B0aW9ucykge1xuICAgICAgICBwcm9wZXJ0aWVzLm9wdGlvbnMgPSBzaGFyZWRPcHRpb25zIHx8IG1lLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgYmFyc1tpXS5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpO1xuICAgICAgfVxuICAgICAgc2V0Qm9yZGVyU2tpcHBlZChwcm9wZXJ0aWVzLCBwcm9wZXJ0aWVzLm9wdGlvbnMgfHwgYmFyc1tpXS5vcHRpb25zLCBzdGFjaywgaW5kZXgpO1xuICAgICAgbWUudXBkYXRlRWxlbWVudChiYXJzW2ldLCBpLCBwcm9wZXJ0aWVzLCBtb2RlKTtcbiAgICB9XG4gIH1cbiAgX2dldFN0YWNrcyhsYXN0LCBkYXRhSW5kZXgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbWV0YSA9IG1lLl9jYWNoZWRNZXRhO1xuICAgIGNvbnN0IGlTY2FsZSA9IG1ldGEuaVNjYWxlO1xuICAgIGNvbnN0IG1ldGFzZXRzID0gaVNjYWxlLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKG1lLl90eXBlKTtcbiAgICBjb25zdCBzdGFja2VkID0gaVNjYWxlLm9wdGlvbnMuc3RhY2tlZDtcbiAgICBjb25zdCBpbGVuID0gbWV0YXNldHMubGVuZ3RoO1xuICAgIGNvbnN0IHN0YWNrcyA9IFtdO1xuICAgIGxldCBpLCBpdGVtO1xuICAgIGZvciAoaSA9IDA7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGl0ZW0gPSBtZXRhc2V0c1tpXTtcbiAgICAgIGlmICghaXRlbS5jb250cm9sbGVyLm9wdGlvbnMuZ3JvdXBlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgZGF0YUluZGV4ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBjb25zdCB2YWwgPSBpdGVtLmNvbnRyb2xsZXIuZ2V0UGFyc2VkKGRhdGFJbmRleClbXG4gICAgICAgICAgaXRlbS5jb250cm9sbGVyLl9jYWNoZWRNZXRhLnZTY2FsZS5heGlzXG4gICAgICAgIF07XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmKHZhbCkgfHwgaXNOYU4odmFsKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhY2tlZCA9PT0gZmFsc2UgfHwgc3RhY2tzLmluZGV4T2YoaXRlbS5zdGFjaykgPT09IC0xIHx8XG5cdFx0XHRcdChzdGFja2VkID09PSB1bmRlZmluZWQgJiYgaXRlbS5zdGFjayA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgICBzdGFja3MucHVzaChpdGVtLnN0YWNrKTtcbiAgICAgIH1cbiAgICAgIGlmIChpdGVtLmluZGV4ID09PSBsYXN0KSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXN0YWNrcy5sZW5ndGgpIHtcbiAgICAgIHN0YWNrcy5wdXNoKHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIHJldHVybiBzdGFja3M7XG4gIH1cbiAgX2dldFN0YWNrQ291bnQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0U3RhY2tzKHVuZGVmaW5lZCwgaW5kZXgpLmxlbmd0aDtcbiAgfVxuICBfZ2V0U3RhY2tJbmRleChkYXRhc2V0SW5kZXgsIG5hbWUsIGRhdGFJbmRleCkge1xuICAgIGNvbnN0IHN0YWNrcyA9IHRoaXMuX2dldFN0YWNrcyhkYXRhc2V0SW5kZXgsIGRhdGFJbmRleCk7XG4gICAgY29uc3QgaW5kZXggPSAobmFtZSAhPT0gdW5kZWZpbmVkKVxuICAgICAgPyBzdGFja3MuaW5kZXhPZihuYW1lKVxuICAgICAgOiAtMTtcbiAgICByZXR1cm4gKGluZGV4ID09PSAtMSlcbiAgICAgID8gc3RhY2tzLmxlbmd0aCAtIDFcbiAgICAgIDogaW5kZXg7XG4gIH1cbiAgX2dldFJ1bGVyKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRzID0gbWUub3B0aW9ucztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgaVNjYWxlID0gbWV0YS5pU2NhbGU7XG4gICAgY29uc3QgcGl4ZWxzID0gW107XG4gICAgbGV0IGksIGlsZW47XG4gICAgZm9yIChpID0gMCwgaWxlbiA9IG1ldGEuZGF0YS5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIHBpeGVscy5wdXNoKGlTY2FsZS5nZXRQaXhlbEZvclZhbHVlKG1lLmdldFBhcnNlZChpKVtpU2NhbGUuYXhpc10sIGkpKTtcbiAgICB9XG4gICAgY29uc3QgYmFyVGhpY2tuZXNzID0gb3B0cy5iYXJUaGlja25lc3M7XG4gICAgY29uc3QgbWluID0gYmFyVGhpY2tuZXNzIHx8IGNvbXB1dGVNaW5TYW1wbGVTaXplKGlTY2FsZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIG1pbixcbiAgICAgIHBpeGVscyxcbiAgICAgIHN0YXJ0OiBpU2NhbGUuX3N0YXJ0UGl4ZWwsXG4gICAgICBlbmQ6IGlTY2FsZS5fZW5kUGl4ZWwsXG4gICAgICBzdGFja0NvdW50OiBtZS5fZ2V0U3RhY2tDb3VudCgpLFxuICAgICAgc2NhbGU6IGlTY2FsZSxcbiAgICAgIGdyb3VwZWQ6IG9wdHMuZ3JvdXBlZCxcbiAgICAgIHJhdGlvOiBiYXJUaGlja25lc3MgPyAxIDogb3B0cy5jYXRlZ29yeVBlcmNlbnRhZ2UgKiBvcHRzLmJhclBlcmNlbnRhZ2VcbiAgICB9O1xuICB9XG4gIF9jYWxjdWxhdGVCYXJWYWx1ZVBpeGVscyhpbmRleCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB7X2NhY2hlZE1ldGE6IHt2U2NhbGUsIF9zdGFja2VkfSwgb3B0aW9uczoge2Jhc2U6IGJhc2VWYWx1ZSwgbWluQmFyTGVuZ3RofX0gPSBtZTtcbiAgICBjb25zdCBhY3R1YWxCYXNlID0gYmFzZVZhbHVlIHx8IDA7XG4gICAgY29uc3QgcGFyc2VkID0gbWUuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICBjb25zdCBjdXN0b20gPSBwYXJzZWQuX2N1c3RvbTtcbiAgICBjb25zdCBmbG9hdGluZyA9IGlzRmxvYXRCYXIoY3VzdG9tKTtcbiAgICBsZXQgdmFsdWUgPSBwYXJzZWRbdlNjYWxlLmF4aXNdO1xuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IGxlbmd0aCA9IF9zdGFja2VkID8gbWUuYXBwbHlTdGFjayh2U2NhbGUsIHBhcnNlZCwgX3N0YWNrZWQpIDogdmFsdWU7XG4gICAgbGV0IGhlYWQsIHNpemU7XG4gICAgaWYgKGxlbmd0aCAhPT0gdmFsdWUpIHtcbiAgICAgIHN0YXJ0ID0gbGVuZ3RoIC0gdmFsdWU7XG4gICAgICBsZW5ndGggPSB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKGZsb2F0aW5nKSB7XG4gICAgICB2YWx1ZSA9IGN1c3RvbS5iYXJTdGFydDtcbiAgICAgIGxlbmd0aCA9IGN1c3RvbS5iYXJFbmQgLSBjdXN0b20uYmFyU3RhcnQ7XG4gICAgICBpZiAodmFsdWUgIT09IDAgJiYgc2lnbih2YWx1ZSkgIT09IHNpZ24oY3VzdG9tLmJhckVuZCkpIHtcbiAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgfVxuICAgICAgc3RhcnQgKz0gdmFsdWU7XG4gICAgfVxuICAgIGNvbnN0IHN0YXJ0VmFsdWUgPSAhaXNOdWxsT3JVbmRlZihiYXNlVmFsdWUpICYmICFmbG9hdGluZyA/IGJhc2VWYWx1ZSA6IHN0YXJ0O1xuICAgIGxldCBiYXNlID0gdlNjYWxlLmdldFBpeGVsRm9yVmFsdWUoc3RhcnRWYWx1ZSk7XG4gICAgaWYgKG1lLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGluZGV4KSkge1xuICAgICAgaGVhZCA9IHZTY2FsZS5nZXRQaXhlbEZvclZhbHVlKHN0YXJ0ICsgbGVuZ3RoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGVhZCA9IGJhc2U7XG4gICAgfVxuICAgIHNpemUgPSBoZWFkIC0gYmFzZTtcbiAgICBpZiAoTWF0aC5hYnMoc2l6ZSkgPCBtaW5CYXJMZW5ndGgpIHtcbiAgICAgIHNpemUgPSBiYXJTaWduKHNpemUsIHZTY2FsZSwgYWN0dWFsQmFzZSkgKiBtaW5CYXJMZW5ndGg7XG4gICAgICBpZiAodmFsdWUgPT09IGFjdHVhbEJhc2UpIHtcbiAgICAgICAgYmFzZSAtPSBzaXplIC8gMjtcbiAgICAgIH1cbiAgICAgIGhlYWQgPSBiYXNlICsgc2l6ZTtcbiAgICB9XG4gICAgaWYgKGJhc2UgPT09IHZTY2FsZS5nZXRQaXhlbEZvclZhbHVlKGFjdHVhbEJhc2UpKSB7XG4gICAgICBjb25zdCBoYWxmR3JpZCA9IHNpZ24oc2l6ZSkgKiB2U2NhbGUuZ2V0TGluZVdpZHRoRm9yVmFsdWUoYWN0dWFsQmFzZSkgLyAyO1xuICAgICAgYmFzZSArPSBoYWxmR3JpZDtcbiAgICAgIHNpemUgLT0gaGFsZkdyaWQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBzaXplLFxuICAgICAgYmFzZSxcbiAgICAgIGhlYWQsXG4gICAgICBjZW50ZXI6IGhlYWQgKyBzaXplIC8gMlxuICAgIH07XG4gIH1cbiAgX2NhbGN1bGF0ZUJhckluZGV4UGl4ZWxzKGluZGV4LCBydWxlcikge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBzY2FsZSA9IHJ1bGVyLnNjYWxlO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IHNraXBOdWxsID0gb3B0aW9ucy5za2lwTnVsbDtcbiAgICBjb25zdCBtYXhCYXJUaGlja25lc3MgPSB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLm1heEJhclRoaWNrbmVzcywgSW5maW5pdHkpO1xuICAgIGxldCBjZW50ZXIsIHNpemU7XG4gICAgaWYgKHJ1bGVyLmdyb3VwZWQpIHtcbiAgICAgIGNvbnN0IHN0YWNrQ291bnQgPSBza2lwTnVsbCA/IG1lLl9nZXRTdGFja0NvdW50KGluZGV4KSA6IHJ1bGVyLnN0YWNrQ291bnQ7XG4gICAgICBjb25zdCByYW5nZSA9IG9wdGlvbnMuYmFyVGhpY2tuZXNzID09PSAnZmxleCdcbiAgICAgICAgPyBjb21wdXRlRmxleENhdGVnb3J5VHJhaXRzKGluZGV4LCBydWxlciwgb3B0aW9ucywgc3RhY2tDb3VudClcbiAgICAgICAgOiBjb21wdXRlRml0Q2F0ZWdvcnlUcmFpdHMoaW5kZXgsIHJ1bGVyLCBvcHRpb25zLCBzdGFja0NvdW50KTtcbiAgICAgIGNvbnN0IHN0YWNrSW5kZXggPSBtZS5fZ2V0U3RhY2tJbmRleChtZS5pbmRleCwgbWUuX2NhY2hlZE1ldGEuc3RhY2ssIHNraXBOdWxsID8gaW5kZXggOiB1bmRlZmluZWQpO1xuICAgICAgY2VudGVyID0gcmFuZ2Uuc3RhcnQgKyAocmFuZ2UuY2h1bmsgKiBzdGFja0luZGV4KSArIChyYW5nZS5jaHVuayAvIDIpO1xuICAgICAgc2l6ZSA9IE1hdGgubWluKG1heEJhclRoaWNrbmVzcywgcmFuZ2UuY2h1bmsgKiByYW5nZS5yYXRpbyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNlbnRlciA9IHNjYWxlLmdldFBpeGVsRm9yVmFsdWUobWUuZ2V0UGFyc2VkKGluZGV4KVtzY2FsZS5heGlzXSwgaW5kZXgpO1xuICAgICAgc2l6ZSA9IE1hdGgubWluKG1heEJhclRoaWNrbmVzcywgcnVsZXIubWluICogcnVsZXIucmF0aW8pO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgYmFzZTogY2VudGVyIC0gc2l6ZSAvIDIsXG4gICAgICBoZWFkOiBjZW50ZXIgKyBzaXplIC8gMixcbiAgICAgIGNlbnRlcixcbiAgICAgIHNpemVcbiAgICB9O1xuICB9XG4gIGRyYXcoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBjb25zdCB2U2NhbGUgPSBtZXRhLnZTY2FsZTtcbiAgICBjb25zdCByZWN0cyA9IG1ldGEuZGF0YTtcbiAgICBjb25zdCBpbGVuID0gcmVjdHMubGVuZ3RoO1xuICAgIGxldCBpID0gMDtcbiAgICBmb3IgKDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgaWYgKG1lLmdldFBhcnNlZChpKVt2U2NhbGUuYXhpc10gIT09IG51bGwpIHtcbiAgICAgICAgcmVjdHNbaV0uZHJhdyhtZS5fY3R4KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbkJhckNvbnRyb2xsZXIuaWQgPSAnYmFyJztcbkJhckNvbnRyb2xsZXIuZGVmYXVsdHMgPSB7XG4gIGRhdGFzZXRFbGVtZW50VHlwZTogZmFsc2UsXG4gIGRhdGFFbGVtZW50VHlwZTogJ2JhcicsXG4gIGNhdGVnb3J5UGVyY2VudGFnZTogMC44LFxuICBiYXJQZXJjZW50YWdlOiAwLjksXG4gIGdyb3VwZWQ6IHRydWUsXG4gIGFuaW1hdGlvbnM6IHtcbiAgICBudW1iZXJzOiB7XG4gICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgIHByb3BlcnRpZXM6IFsneCcsICd5JywgJ2Jhc2UnLCAnd2lkdGgnLCAnaGVpZ2h0J11cbiAgICB9XG4gIH1cbn07XG5CYXJDb250cm9sbGVyLm92ZXJyaWRlcyA9IHtcbiAgc2NhbGVzOiB7XG4gICAgX2luZGV4Xzoge1xuICAgICAgdHlwZTogJ2NhdGVnb3J5JyxcbiAgICAgIG9mZnNldDogdHJ1ZSxcbiAgICAgIGdyaWQ6IHtcbiAgICAgICAgb2Zmc2V0OiB0cnVlXG4gICAgICB9XG4gICAgfSxcbiAgICBfdmFsdWVfOiB7XG4gICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgIGJlZ2luQXRaZXJvOiB0cnVlLFxuICAgIH1cbiAgfVxufTtcblxuY2xhc3MgQnViYmxlQ29udHJvbGxlciBleHRlbmRzIERhdGFzZXRDb250cm9sbGVyIHtcbiAgaW5pdGlhbGl6ZSgpIHtcbiAgICB0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmcgPSB0cnVlO1xuICAgIHN1cGVyLmluaXRpYWxpemUoKTtcbiAgfVxuICBwYXJzZU9iamVjdERhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgY29uc3Qge3hTY2FsZSwgeVNjYWxlfSA9IG1ldGE7XG4gICAgY29uc3Qge3hBeGlzS2V5ID0gJ3gnLCB5QXhpc0tleSA9ICd5J30gPSB0aGlzLl9wYXJzaW5nO1xuICAgIGNvbnN0IHBhcnNlZCA9IFtdO1xuICAgIGxldCBpLCBpbGVuLCBpdGVtO1xuICAgIGZvciAoaSA9IHN0YXJ0LCBpbGVuID0gc3RhcnQgKyBjb3VudDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgaXRlbSA9IGRhdGFbaV07XG4gICAgICBwYXJzZWQucHVzaCh7XG4gICAgICAgIHg6IHhTY2FsZS5wYXJzZShyZXNvbHZlT2JqZWN0S2V5KGl0ZW0sIHhBeGlzS2V5KSwgaSksXG4gICAgICAgIHk6IHlTY2FsZS5wYXJzZShyZXNvbHZlT2JqZWN0S2V5KGl0ZW0sIHlBeGlzS2V5KSwgaSksXG4gICAgICAgIF9jdXN0b206IGl0ZW0gJiYgaXRlbS5yICYmICtpdGVtLnJcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VkO1xuICB9XG4gIGdldE1heE92ZXJmbG93KCkge1xuICAgIGNvbnN0IHtkYXRhLCBfcGFyc2VkfSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgbGV0IG1heCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIG1heCA9IE1hdGgubWF4KG1heCwgZGF0YVtpXS5zaXplKCkgLyAyLCBfcGFyc2VkW2ldLl9jdXN0b20pO1xuICAgIH1cbiAgICByZXR1cm4gbWF4ID4gMCAmJiBtYXg7XG4gIH1cbiAgZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3Qge3hTY2FsZSwgeVNjYWxlfSA9IG1ldGE7XG4gICAgY29uc3QgcGFyc2VkID0gbWUuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICBjb25zdCB4ID0geFNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkLngpO1xuICAgIGNvbnN0IHkgPSB5U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWQueSk7XG4gICAgY29uc3QgciA9IHBhcnNlZC5fY3VzdG9tO1xuICAgIHJldHVybiB7XG4gICAgICBsYWJlbDogbWV0YS5sYWJlbCxcbiAgICAgIHZhbHVlOiAnKCcgKyB4ICsgJywgJyArIHkgKyAociA/ICcsICcgKyByIDogJycpICsgJyknXG4gICAgfTtcbiAgfVxuICB1cGRhdGUobW9kZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBwb2ludHMgPSBtZS5fY2FjaGVkTWV0YS5kYXRhO1xuICAgIG1lLnVwZGF0ZUVsZW1lbnRzKHBvaW50cywgMCwgcG9pbnRzLmxlbmd0aCwgbW9kZSk7XG4gIH1cbiAgdXBkYXRlRWxlbWVudHMocG9pbnRzLCBzdGFydCwgY291bnQsIG1vZGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgcmVzZXQgPSBtb2RlID09PSAncmVzZXQnO1xuICAgIGNvbnN0IHtpU2NhbGUsIHZTY2FsZX0gPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBjb25zdCBmaXJzdE9wdHMgPSBtZS5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKHN0YXJ0LCBtb2RlKTtcbiAgICBjb25zdCBzaGFyZWRPcHRpb25zID0gbWUuZ2V0U2hhcmVkT3B0aW9ucyhmaXJzdE9wdHMpO1xuICAgIGNvbnN0IGluY2x1ZGVPcHRpb25zID0gbWUuaW5jbHVkZU9wdGlvbnMobW9kZSwgc2hhcmVkT3B0aW9ucyk7XG4gICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICBjb25zdCB2QXhpcyA9IHZTY2FsZS5heGlzO1xuICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IHN0YXJ0ICsgY291bnQ7IGkrKykge1xuICAgICAgY29uc3QgcG9pbnQgPSBwb2ludHNbaV07XG4gICAgICBjb25zdCBwYXJzZWQgPSAhcmVzZXQgJiYgbWUuZ2V0UGFyc2VkKGkpO1xuICAgICAgY29uc3QgcHJvcGVydGllcyA9IHt9O1xuICAgICAgY29uc3QgaVBpeGVsID0gcHJvcGVydGllc1tpQXhpc10gPSByZXNldCA/IGlTY2FsZS5nZXRQaXhlbEZvckRlY2ltYWwoMC41KSA6IGlTY2FsZS5nZXRQaXhlbEZvclZhbHVlKHBhcnNlZFtpQXhpc10pO1xuICAgICAgY29uc3QgdlBpeGVsID0gcHJvcGVydGllc1t2QXhpc10gPSByZXNldCA/IHZTY2FsZS5nZXRCYXNlUGl4ZWwoKSA6IHZTY2FsZS5nZXRQaXhlbEZvclZhbHVlKHBhcnNlZFt2QXhpc10pO1xuICAgICAgcHJvcGVydGllcy5za2lwID0gaXNOYU4oaVBpeGVsKSB8fCBpc05hTih2UGl4ZWwpO1xuICAgICAgaWYgKGluY2x1ZGVPcHRpb25zKSB7XG4gICAgICAgIHByb3BlcnRpZXMub3B0aW9ucyA9IG1lLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgcG9pbnQuYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKTtcbiAgICAgICAgaWYgKHJlc2V0KSB7XG4gICAgICAgICAgcHJvcGVydGllcy5vcHRpb25zLnJhZGl1cyA9IDA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIG1lLnVwZGF0ZUVsZW1lbnQocG9pbnQsIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgIH1cbiAgICBtZS51cGRhdGVTaGFyZWRPcHRpb25zKHNoYXJlZE9wdGlvbnMsIG1vZGUsIGZpcnN0T3B0cyk7XG4gIH1cbiAgcmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpbmRleCwgbW9kZSkge1xuICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICBsZXQgdmFsdWVzID0gc3VwZXIucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpbmRleCwgbW9kZSk7XG4gICAgaWYgKHZhbHVlcy4kc2hhcmVkKSB7XG4gICAgICB2YWx1ZXMgPSBPYmplY3QuYXNzaWduKHt9LCB2YWx1ZXMsIHskc2hhcmVkOiBmYWxzZX0pO1xuICAgIH1cbiAgICBjb25zdCByYWRpdXMgPSB2YWx1ZXMucmFkaXVzO1xuICAgIGlmIChtb2RlICE9PSAnYWN0aXZlJykge1xuICAgICAgdmFsdWVzLnJhZGl1cyA9IDA7XG4gICAgfVxuICAgIHZhbHVlcy5yYWRpdXMgKz0gdmFsdWVPckRlZmF1bHQocGFyc2VkICYmIHBhcnNlZC5fY3VzdG9tLCByYWRpdXMpO1xuICAgIHJldHVybiB2YWx1ZXM7XG4gIH1cbn1cbkJ1YmJsZUNvbnRyb2xsZXIuaWQgPSAnYnViYmxlJztcbkJ1YmJsZUNvbnRyb2xsZXIuZGVmYXVsdHMgPSB7XG4gIGRhdGFzZXRFbGVtZW50VHlwZTogZmFsc2UsXG4gIGRhdGFFbGVtZW50VHlwZTogJ3BvaW50JyxcbiAgYW5pbWF0aW9uczoge1xuICAgIG51bWJlcnM6IHtcbiAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgcHJvcGVydGllczogWyd4JywgJ3knLCAnYm9yZGVyV2lkdGgnLCAncmFkaXVzJ11cbiAgICB9XG4gIH1cbn07XG5CdWJibGVDb250cm9sbGVyLm92ZXJyaWRlcyA9IHtcbiAgc2NhbGVzOiB7XG4gICAgeDoge1xuICAgICAgdHlwZTogJ2xpbmVhcidcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgIHR5cGU6ICdsaW5lYXInXG4gICAgfVxuICB9LFxuICBwbHVnaW5zOiB7XG4gICAgdG9vbHRpcDoge1xuICAgICAgY2FsbGJhY2tzOiB7XG4gICAgICAgIHRpdGxlKCkge1xuICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuZnVuY3Rpb24gZ2V0UmF0aW9BbmRPZmZzZXQocm90YXRpb24sIGNpcmN1bWZlcmVuY2UsIGN1dG91dCkge1xuICBsZXQgcmF0aW9YID0gMTtcbiAgbGV0IHJhdGlvWSA9IDE7XG4gIGxldCBvZmZzZXRYID0gMDtcbiAgbGV0IG9mZnNldFkgPSAwO1xuICBpZiAoY2lyY3VtZmVyZW5jZSA8IFRBVSkge1xuICAgIGNvbnN0IHN0YXJ0QW5nbGUgPSByb3RhdGlvbjtcbiAgICBjb25zdCBlbmRBbmdsZSA9IHN0YXJ0QW5nbGUgKyBjaXJjdW1mZXJlbmNlO1xuICAgIGNvbnN0IHN0YXJ0WCA9IE1hdGguY29zKHN0YXJ0QW5nbGUpO1xuICAgIGNvbnN0IHN0YXJ0WSA9IE1hdGguc2luKHN0YXJ0QW5nbGUpO1xuICAgIGNvbnN0IGVuZFggPSBNYXRoLmNvcyhlbmRBbmdsZSk7XG4gICAgY29uc3QgZW5kWSA9IE1hdGguc2luKGVuZEFuZ2xlKTtcbiAgICBjb25zdCBjYWxjTWF4ID0gKGFuZ2xlLCBhLCBiKSA9PiBfYW5nbGVCZXR3ZWVuKGFuZ2xlLCBzdGFydEFuZ2xlLCBlbmRBbmdsZSwgdHJ1ZSkgPyAxIDogTWF0aC5tYXgoYSwgYSAqIGN1dG91dCwgYiwgYiAqIGN1dG91dCk7XG4gICAgY29uc3QgY2FsY01pbiA9IChhbmdsZSwgYSwgYikgPT4gX2FuZ2xlQmV0d2VlbihhbmdsZSwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIHRydWUpID8gLTEgOiBNYXRoLm1pbihhLCBhICogY3V0b3V0LCBiLCBiICogY3V0b3V0KTtcbiAgICBjb25zdCBtYXhYID0gY2FsY01heCgwLCBzdGFydFgsIGVuZFgpO1xuICAgIGNvbnN0IG1heFkgPSBjYWxjTWF4KEhBTEZfUEksIHN0YXJ0WSwgZW5kWSk7XG4gICAgY29uc3QgbWluWCA9IGNhbGNNaW4oUEksIHN0YXJ0WCwgZW5kWCk7XG4gICAgY29uc3QgbWluWSA9IGNhbGNNaW4oUEkgKyBIQUxGX1BJLCBzdGFydFksIGVuZFkpO1xuICAgIHJhdGlvWCA9IChtYXhYIC0gbWluWCkgLyAyO1xuICAgIHJhdGlvWSA9IChtYXhZIC0gbWluWSkgLyAyO1xuICAgIG9mZnNldFggPSAtKG1heFggKyBtaW5YKSAvIDI7XG4gICAgb2Zmc2V0WSA9IC0obWF4WSArIG1pblkpIC8gMjtcbiAgfVxuICByZXR1cm4ge3JhdGlvWCwgcmF0aW9ZLCBvZmZzZXRYLCBvZmZzZXRZfTtcbn1cbmNsYXNzIERvdWdobnV0Q29udHJvbGxlciBleHRlbmRzIERhdGFzZXRDb250cm9sbGVyIHtcbiAgY29uc3RydWN0b3IoY2hhcnQsIGRhdGFzZXRJbmRleCkge1xuICAgIHN1cGVyKGNoYXJ0LCBkYXRhc2V0SW5kZXgpO1xuICAgIHRoaXMuZW5hYmxlT3B0aW9uU2hhcmluZyA9IHRydWU7XG4gICAgdGhpcy5pbm5lclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm91dGVyUmFkaXVzID0gdW5kZWZpbmVkO1xuICAgIHRoaXMub2Zmc2V0WCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm9mZnNldFkgPSB1bmRlZmluZWQ7XG4gIH1cbiAgbGlua1NjYWxlcygpIHt9XG4gIHBhcnNlKHN0YXJ0LCBjb3VudCkge1xuICAgIGNvbnN0IGRhdGEgPSB0aGlzLmdldERhdGFzZXQoKS5kYXRhO1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgIGxldCBpLCBpbGVuO1xuICAgIGZvciAoaSA9IHN0YXJ0LCBpbGVuID0gc3RhcnQgKyBjb3VudDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgbWV0YS5fcGFyc2VkW2ldID0gK2RhdGFbaV07XG4gICAgfVxuICB9XG4gIF9nZXRSb3RhdGlvbigpIHtcbiAgICByZXR1cm4gdG9SYWRpYW5zKHRoaXMub3B0aW9ucy5yb3RhdGlvbiAtIDkwKTtcbiAgfVxuICBfZ2V0Q2lyY3VtZmVyZW5jZSgpIHtcbiAgICByZXR1cm4gdG9SYWRpYW5zKHRoaXMub3B0aW9ucy5jaXJjdW1mZXJlbmNlKTtcbiAgfVxuICBfZ2V0Um90YXRpb25FeHRlbnRzKCkge1xuICAgIGxldCBtaW4gPSBUQVU7XG4gICAgbGV0IG1heCA9IC1UQVU7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWUuY2hhcnQuZGF0YS5kYXRhc2V0cy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKG1lLmNoYXJ0LmlzRGF0YXNldFZpc2libGUoaSkpIHtcbiAgICAgICAgY29uc3QgY29udHJvbGxlciA9IG1lLmNoYXJ0LmdldERhdGFzZXRNZXRhKGkpLmNvbnRyb2xsZXI7XG4gICAgICAgIGNvbnN0IHJvdGF0aW9uID0gY29udHJvbGxlci5fZ2V0Um90YXRpb24oKTtcbiAgICAgICAgY29uc3QgY2lyY3VtZmVyZW5jZSA9IGNvbnRyb2xsZXIuX2dldENpcmN1bWZlcmVuY2UoKTtcbiAgICAgICAgbWluID0gTWF0aC5taW4obWluLCByb3RhdGlvbik7XG4gICAgICAgIG1heCA9IE1hdGgubWF4KG1heCwgcm90YXRpb24gKyBjaXJjdW1mZXJlbmNlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIHJvdGF0aW9uOiBtaW4sXG4gICAgICBjaXJjdW1mZXJlbmNlOiBtYXggLSBtaW4sXG4gICAgfTtcbiAgfVxuICB1cGRhdGUobW9kZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBjaGFydCA9IG1lLmNoYXJ0O1xuICAgIGNvbnN0IHtjaGFydEFyZWF9ID0gY2hhcnQ7XG4gICAgY29uc3QgbWV0YSA9IG1lLl9jYWNoZWRNZXRhO1xuICAgIGNvbnN0IGFyY3MgPSBtZXRhLmRhdGE7XG4gICAgY29uc3Qgc3BhY2luZyA9IG1lLmdldE1heEJvcmRlcldpZHRoKCkgKyBtZS5nZXRNYXhPZmZzZXQoYXJjcykgKyBtZS5vcHRpb25zLnNwYWNpbmc7XG4gICAgY29uc3QgbWF4U2l6ZSA9IE1hdGgubWF4KChNYXRoLm1pbihjaGFydEFyZWEud2lkdGgsIGNoYXJ0QXJlYS5oZWlnaHQpIC0gc3BhY2luZykgLyAyLCAwKTtcbiAgICBjb25zdCBjdXRvdXQgPSBNYXRoLm1pbih0b1BlcmNlbnRhZ2UobWUub3B0aW9ucy5jdXRvdXQsIG1heFNpemUpLCAxKTtcbiAgICBjb25zdCBjaGFydFdlaWdodCA9IG1lLl9nZXRSaW5nV2VpZ2h0KG1lLmluZGV4KTtcbiAgICBjb25zdCB7Y2lyY3VtZmVyZW5jZSwgcm90YXRpb259ID0gbWUuX2dldFJvdGF0aW9uRXh0ZW50cygpO1xuICAgIGNvbnN0IHtyYXRpb1gsIHJhdGlvWSwgb2Zmc2V0WCwgb2Zmc2V0WX0gPSBnZXRSYXRpb0FuZE9mZnNldChyb3RhdGlvbiwgY2lyY3VtZmVyZW5jZSwgY3V0b3V0KTtcbiAgICBjb25zdCBtYXhXaWR0aCA9IChjaGFydEFyZWEud2lkdGggLSBzcGFjaW5nKSAvIHJhdGlvWDtcbiAgICBjb25zdCBtYXhIZWlnaHQgPSAoY2hhcnRBcmVhLmhlaWdodCAtIHNwYWNpbmcpIC8gcmF0aW9ZO1xuICAgIGNvbnN0IG1heFJhZGl1cyA9IE1hdGgubWF4KE1hdGgubWluKG1heFdpZHRoLCBtYXhIZWlnaHQpIC8gMiwgMCk7XG4gICAgY29uc3Qgb3V0ZXJSYWRpdXMgPSB0b0RpbWVuc2lvbihtZS5vcHRpb25zLnJhZGl1cywgbWF4UmFkaXVzKTtcbiAgICBjb25zdCBpbm5lclJhZGl1cyA9IE1hdGgubWF4KG91dGVyUmFkaXVzICogY3V0b3V0LCAwKTtcbiAgICBjb25zdCByYWRpdXNMZW5ndGggPSAob3V0ZXJSYWRpdXMgLSBpbm5lclJhZGl1cykgLyBtZS5fZ2V0VmlzaWJsZURhdGFzZXRXZWlnaHRUb3RhbCgpO1xuICAgIG1lLm9mZnNldFggPSBvZmZzZXRYICogb3V0ZXJSYWRpdXM7XG4gICAgbWUub2Zmc2V0WSA9IG9mZnNldFkgKiBvdXRlclJhZGl1cztcbiAgICBtZXRhLnRvdGFsID0gbWUuY2FsY3VsYXRlVG90YWwoKTtcbiAgICBtZS5vdXRlclJhZGl1cyA9IG91dGVyUmFkaXVzIC0gcmFkaXVzTGVuZ3RoICogbWUuX2dldFJpbmdXZWlnaHRPZmZzZXQobWUuaW5kZXgpO1xuICAgIG1lLmlubmVyUmFkaXVzID0gTWF0aC5tYXgobWUub3V0ZXJSYWRpdXMgLSByYWRpdXNMZW5ndGggKiBjaGFydFdlaWdodCwgMCk7XG4gICAgbWUudXBkYXRlRWxlbWVudHMoYXJjcywgMCwgYXJjcy5sZW5ndGgsIG1vZGUpO1xuICB9XG4gIF9jaXJjdW1mZXJlbmNlKGksIHJlc2V0KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdHMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBjb25zdCBjaXJjdW1mZXJlbmNlID0gbWUuX2dldENpcmN1bWZlcmVuY2UoKTtcbiAgICBpZiAoKHJlc2V0ICYmIG9wdHMuYW5pbWF0aW9uLmFuaW1hdGVSb3RhdGUpIHx8ICF0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpIHx8IG1ldGEuX3BhcnNlZFtpXSA9PT0gbnVsbCB8fCBtZXRhLmRhdGFbaV0uaGlkZGVuKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgcmV0dXJuIG1lLmNhbGN1bGF0ZUNpcmN1bWZlcmVuY2UobWV0YS5fcGFyc2VkW2ldICogY2lyY3VtZmVyZW5jZSAvIFRBVSk7XG4gIH1cbiAgdXBkYXRlRWxlbWVudHMoYXJjcywgc3RhcnQsIGNvdW50LCBtb2RlKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHJlc2V0ID0gbW9kZSA9PT0gJ3Jlc2V0JztcbiAgICBjb25zdCBjaGFydCA9IG1lLmNoYXJ0O1xuICAgIGNvbnN0IGNoYXJ0QXJlYSA9IGNoYXJ0LmNoYXJ0QXJlYTtcbiAgICBjb25zdCBvcHRzID0gY2hhcnQub3B0aW9ucztcbiAgICBjb25zdCBhbmltYXRpb25PcHRzID0gb3B0cy5hbmltYXRpb247XG4gICAgY29uc3QgY2VudGVyWCA9IChjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS5yaWdodCkgLyAyO1xuICAgIGNvbnN0IGNlbnRlclkgPSAoY2hhcnRBcmVhLnRvcCArIGNoYXJ0QXJlYS5ib3R0b20pIC8gMjtcbiAgICBjb25zdCBhbmltYXRlU2NhbGUgPSByZXNldCAmJiBhbmltYXRpb25PcHRzLmFuaW1hdGVTY2FsZTtcbiAgICBjb25zdCBpbm5lclJhZGl1cyA9IGFuaW1hdGVTY2FsZSA/IDAgOiBtZS5pbm5lclJhZGl1cztcbiAgICBjb25zdCBvdXRlclJhZGl1cyA9IGFuaW1hdGVTY2FsZSA/IDAgOiBtZS5vdXRlclJhZGl1cztcbiAgICBjb25zdCBmaXJzdE9wdHMgPSBtZS5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKHN0YXJ0LCBtb2RlKTtcbiAgICBjb25zdCBzaGFyZWRPcHRpb25zID0gbWUuZ2V0U2hhcmVkT3B0aW9ucyhmaXJzdE9wdHMpO1xuICAgIGNvbnN0IGluY2x1ZGVPcHRpb25zID0gbWUuaW5jbHVkZU9wdGlvbnMobW9kZSwgc2hhcmVkT3B0aW9ucyk7XG4gICAgbGV0IHN0YXJ0QW5nbGUgPSBtZS5fZ2V0Um90YXRpb24oKTtcbiAgICBsZXQgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgc3RhcnQ7ICsraSkge1xuICAgICAgc3RhcnRBbmdsZSArPSBtZS5fY2lyY3VtZmVyZW5jZShpLCByZXNldCk7XG4gICAgfVxuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgKytpKSB7XG4gICAgICBjb25zdCBjaXJjdW1mZXJlbmNlID0gbWUuX2NpcmN1bWZlcmVuY2UoaSwgcmVzZXQpO1xuICAgICAgY29uc3QgYXJjID0gYXJjc1tpXTtcbiAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7XG4gICAgICAgIHg6IGNlbnRlclggKyBtZS5vZmZzZXRYLFxuICAgICAgICB5OiBjZW50ZXJZICsgbWUub2Zmc2V0WSxcbiAgICAgICAgc3RhcnRBbmdsZSxcbiAgICAgICAgZW5kQW5nbGU6IHN0YXJ0QW5nbGUgKyBjaXJjdW1mZXJlbmNlLFxuICAgICAgICBjaXJjdW1mZXJlbmNlLFxuICAgICAgICBvdXRlclJhZGl1cyxcbiAgICAgICAgaW5uZXJSYWRpdXNcbiAgICAgIH07XG4gICAgICBpZiAoaW5jbHVkZU9wdGlvbnMpIHtcbiAgICAgICAgcHJvcGVydGllcy5vcHRpb25zID0gc2hhcmVkT3B0aW9ucyB8fCBtZS5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGksIGFyYy5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpO1xuICAgICAgfVxuICAgICAgc3RhcnRBbmdsZSArPSBjaXJjdW1mZXJlbmNlO1xuICAgICAgbWUudXBkYXRlRWxlbWVudChhcmMsIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgIH1cbiAgICBtZS51cGRhdGVTaGFyZWRPcHRpb25zKHNoYXJlZE9wdGlvbnMsIG1vZGUsIGZpcnN0T3B0cyk7XG4gIH1cbiAgY2FsY3VsYXRlVG90YWwoKSB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgbWV0YURhdGEgPSBtZXRhLmRhdGE7XG4gICAgbGV0IHRvdGFsID0gMDtcbiAgICBsZXQgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbWV0YURhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gbWV0YS5fcGFyc2VkW2ldO1xuICAgICAgaWYgKHZhbHVlICE9PSBudWxsICYmICFpc05hTih2YWx1ZSkgJiYgdGhpcy5jaGFydC5nZXREYXRhVmlzaWJpbGl0eShpKSAmJiAhbWV0YURhdGFbaV0uaGlkZGVuKSB7XG4gICAgICAgIHRvdGFsICs9IE1hdGguYWJzKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRvdGFsO1xuICB9XG4gIGNhbGN1bGF0ZUNpcmN1bWZlcmVuY2UodmFsdWUpIHtcbiAgICBjb25zdCB0b3RhbCA9IHRoaXMuX2NhY2hlZE1ldGEudG90YWw7XG4gICAgaWYgKHRvdGFsID4gMCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICByZXR1cm4gVEFVICogKE1hdGguYWJzKHZhbHVlKSAvIHRvdGFsKTtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgY2hhcnQgPSBtZS5jaGFydDtcbiAgICBjb25zdCBsYWJlbHMgPSBjaGFydC5kYXRhLmxhYmVscyB8fCBbXTtcbiAgICBjb25zdCB2YWx1ZSA9IGZvcm1hdE51bWJlcihtZXRhLl9wYXJzZWRbaW5kZXhdLCBjaGFydC5vcHRpb25zLmxvY2FsZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsOiBsYWJlbHNbaW5kZXhdIHx8ICcnLFxuICAgICAgdmFsdWUsXG4gICAgfTtcbiAgfVxuICBnZXRNYXhCb3JkZXJXaWR0aChhcmNzKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGxldCBtYXggPSAwO1xuICAgIGNvbnN0IGNoYXJ0ID0gbWUuY2hhcnQ7XG4gICAgbGV0IGksIGlsZW4sIG1ldGEsIGNvbnRyb2xsZXIsIG9wdGlvbnM7XG4gICAgaWYgKCFhcmNzKSB7XG4gICAgICBmb3IgKGkgPSAwLCBpbGVuID0gY2hhcnQuZGF0YS5kYXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgICAgaWYgKGNoYXJ0LmlzRGF0YXNldFZpc2libGUoaSkpIHtcbiAgICAgICAgICBtZXRhID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoaSk7XG4gICAgICAgICAgYXJjcyA9IG1ldGEuZGF0YTtcbiAgICAgICAgICBjb250cm9sbGVyID0gbWV0YS5jb250cm9sbGVyO1xuICAgICAgICAgIGlmIChjb250cm9sbGVyICE9PSBtZSkge1xuICAgICAgICAgICAgY29udHJvbGxlci5jb25maWd1cmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFhcmNzKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgZm9yIChpID0gMCwgaWxlbiA9IGFyY3MubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgICBvcHRpb25zID0gY29udHJvbGxlci5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGkpO1xuICAgICAgaWYgKG9wdGlvbnMuYm9yZGVyQWxpZ24gIT09ICdpbm5lcicpIHtcbiAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCBvcHRpb25zLmJvcmRlcldpZHRoIHx8IDAsIG9wdGlvbnMuaG92ZXJCb3JkZXJXaWR0aCB8fCAwKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG1heDtcbiAgfVxuICBnZXRNYXhPZmZzZXQoYXJjcykge1xuICAgIGxldCBtYXggPSAwO1xuICAgIGZvciAobGV0IGkgPSAwLCBpbGVuID0gYXJjcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSk7XG4gICAgICBtYXggPSBNYXRoLm1heChtYXgsIG9wdGlvbnMub2Zmc2V0IHx8IDAsIG9wdGlvbnMuaG92ZXJPZmZzZXQgfHwgMCk7XG4gICAgfVxuICAgIHJldHVybiBtYXg7XG4gIH1cbiAgX2dldFJpbmdXZWlnaHRPZmZzZXQoZGF0YXNldEluZGV4KSB7XG4gICAgbGV0IHJpbmdXZWlnaHRPZmZzZXQgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YXNldEluZGV4OyArK2kpIHtcbiAgICAgIGlmICh0aGlzLmNoYXJ0LmlzRGF0YXNldFZpc2libGUoaSkpIHtcbiAgICAgICAgcmluZ1dlaWdodE9mZnNldCArPSB0aGlzLl9nZXRSaW5nV2VpZ2h0KGkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmluZ1dlaWdodE9mZnNldDtcbiAgfVxuICBfZ2V0UmluZ1dlaWdodChkYXRhc2V0SW5kZXgpIHtcbiAgICByZXR1cm4gTWF0aC5tYXgodmFsdWVPckRlZmF1bHQodGhpcy5jaGFydC5kYXRhLmRhdGFzZXRzW2RhdGFzZXRJbmRleF0ud2VpZ2h0LCAxKSwgMCk7XG4gIH1cbiAgX2dldFZpc2libGVEYXRhc2V0V2VpZ2h0VG90YWwoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldFJpbmdXZWlnaHRPZmZzZXQodGhpcy5jaGFydC5kYXRhLmRhdGFzZXRzLmxlbmd0aCkgfHwgMTtcbiAgfVxufVxuRG91Z2hudXRDb250cm9sbGVyLmlkID0gJ2RvdWdobnV0JztcbkRvdWdobnV0Q29udHJvbGxlci5kZWZhdWx0cyA9IHtcbiAgZGF0YXNldEVsZW1lbnRUeXBlOiBmYWxzZSxcbiAgZGF0YUVsZW1lbnRUeXBlOiAnYXJjJyxcbiAgYW5pbWF0aW9uOiB7XG4gICAgYW5pbWF0ZVJvdGF0ZTogdHJ1ZSxcbiAgICBhbmltYXRlU2NhbGU6IGZhbHNlXG4gIH0sXG4gIGFuaW1hdGlvbnM6IHtcbiAgICBudW1iZXJzOiB7XG4gICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgIHByb3BlcnRpZXM6IFsnY2lyY3VtZmVyZW5jZScsICdlbmRBbmdsZScsICdpbm5lclJhZGl1cycsICdvdXRlclJhZGl1cycsICdzdGFydEFuZ2xlJywgJ3gnLCAneScsICdvZmZzZXQnLCAnYm9yZGVyV2lkdGgnLCAnc3BhY2luZyddXG4gICAgfSxcbiAgfSxcbiAgY3V0b3V0OiAnNTAlJyxcbiAgcm90YXRpb246IDAsXG4gIGNpcmN1bWZlcmVuY2U6IDM2MCxcbiAgcmFkaXVzOiAnMTAwJScsXG4gIHNwYWNpbmc6IDAsXG4gIGluZGV4QXhpczogJ3InLFxufTtcbkRvdWdobnV0Q29udHJvbGxlci5kZXNjcmlwdG9ycyA9IHtcbiAgX3NjcmlwdGFibGU6IChuYW1lKSA9PiBuYW1lICE9PSAnc3BhY2luZycsXG4gIF9pbmRleGFibGU6IChuYW1lKSA9PiBuYW1lICE9PSAnc3BhY2luZycsXG59O1xuRG91Z2hudXRDb250cm9sbGVyLm92ZXJyaWRlcyA9IHtcbiAgYXNwZWN0UmF0aW86IDEsXG4gIHBsdWdpbnM6IHtcbiAgICBsZWdlbmQ6IHtcbiAgICAgIGxhYmVsczoge1xuICAgICAgICBnZW5lcmF0ZUxhYmVscyhjaGFydCkge1xuICAgICAgICAgIGNvbnN0IGRhdGEgPSBjaGFydC5kYXRhO1xuICAgICAgICAgIGlmIChkYXRhLmxhYmVscy5sZW5ndGggJiYgZGF0YS5kYXRhc2V0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHtsYWJlbHM6IHtwb2ludFN0eWxlfX0gPSBjaGFydC5sZWdlbmQub3B0aW9ucztcbiAgICAgICAgICAgIHJldHVybiBkYXRhLmxhYmVscy5tYXAoKGxhYmVsLCBpKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IG1ldGEgPSBjaGFydC5nZXREYXRhc2V0TWV0YSgwKTtcbiAgICAgICAgICAgICAgY29uc3Qgc3R5bGUgPSBtZXRhLmNvbnRyb2xsZXIuZ2V0U3R5bGUoaSk7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdGV4dDogbGFiZWwsXG4gICAgICAgICAgICAgICAgZmlsbFN0eWxlOiBzdHlsZS5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICAgICAgc3Ryb2tlU3R5bGU6IHN0eWxlLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgICAgIGxpbmVXaWR0aDogc3R5bGUuYm9yZGVyV2lkdGgsXG4gICAgICAgICAgICAgICAgcG9pbnRTdHlsZTogcG9pbnRTdHlsZSxcbiAgICAgICAgICAgICAgICBoaWRkZW46ICFjaGFydC5nZXREYXRhVmlzaWJpbGl0eShpKSxcbiAgICAgICAgICAgICAgICBpbmRleDogaVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIG9uQ2xpY2soZSwgbGVnZW5kSXRlbSwgbGVnZW5kKSB7XG4gICAgICAgIGxlZ2VuZC5jaGFydC50b2dnbGVEYXRhVmlzaWJpbGl0eShsZWdlbmRJdGVtLmluZGV4KTtcbiAgICAgICAgbGVnZW5kLmNoYXJ0LnVwZGF0ZSgpO1xuICAgICAgfVxuICAgIH0sXG4gICAgdG9vbHRpcDoge1xuICAgICAgY2FsbGJhY2tzOiB7XG4gICAgICAgIHRpdGxlKCkge1xuICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFiZWwodG9vbHRpcEl0ZW0pIHtcbiAgICAgICAgICBsZXQgZGF0YUxhYmVsID0gdG9vbHRpcEl0ZW0ubGFiZWw7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSAnOiAnICsgdG9vbHRpcEl0ZW0uZm9ybWF0dGVkVmFsdWU7XG4gICAgICAgICAgaWYgKGlzQXJyYXkoZGF0YUxhYmVsKSkge1xuICAgICAgICAgICAgZGF0YUxhYmVsID0gZGF0YUxhYmVsLnNsaWNlKCk7XG4gICAgICAgICAgICBkYXRhTGFiZWxbMF0gKz0gdmFsdWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRhdGFMYWJlbCArPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGRhdGFMYWJlbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuY2xhc3MgTGluZUNvbnRyb2xsZXIgZXh0ZW5kcyBEYXRhc2V0Q29udHJvbGxlciB7XG4gIGluaXRpYWxpemUoKSB7XG4gICAgdGhpcy5lbmFibGVPcHRpb25TaGFyaW5nID0gdHJ1ZTtcbiAgICBzdXBlci5pbml0aWFsaXplKCk7XG4gIH1cbiAgdXBkYXRlKG1vZGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbWV0YSA9IG1lLl9jYWNoZWRNZXRhO1xuICAgIGNvbnN0IHtkYXRhc2V0OiBsaW5lLCBkYXRhOiBwb2ludHMgPSBbXSwgX2RhdGFzZXR9ID0gbWV0YTtcbiAgICBjb25zdCBhbmltYXRpb25zRGlzYWJsZWQgPSBtZS5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkO1xuICAgIGxldCB7c3RhcnQsIGNvdW50fSA9IGdldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHMobWV0YSwgcG9pbnRzLCBhbmltYXRpb25zRGlzYWJsZWQpO1xuICAgIG1lLl9kcmF3U3RhcnQgPSBzdGFydDtcbiAgICBtZS5fZHJhd0NvdW50ID0gY291bnQ7XG4gICAgaWYgKHNjYWxlUmFuZ2VzQ2hhbmdlZChtZXRhKSkge1xuICAgICAgc3RhcnQgPSAwO1xuICAgICAgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgIH1cbiAgICBsaW5lLl9kYXRhc2V0SW5kZXggPSBtZS5pbmRleDtcbiAgICBsaW5lLl9kZWNpbWF0ZWQgPSAhIV9kYXRhc2V0Ll9kZWNpbWF0ZWQ7XG4gICAgbGluZS5wb2ludHMgPSBwb2ludHM7XG4gICAgY29uc3Qgb3B0aW9ucyA9IG1lLnJlc29sdmVEYXRhc2V0RWxlbWVudE9wdGlvbnMobW9kZSk7XG4gICAgaWYgKCFtZS5vcHRpb25zLnNob3dMaW5lKSB7XG4gICAgICBvcHRpb25zLmJvcmRlcldpZHRoID0gMDtcbiAgICB9XG4gICAgb3B0aW9ucy5zZWdtZW50ID0gbWUub3B0aW9ucy5zZWdtZW50O1xuICAgIG1lLnVwZGF0ZUVsZW1lbnQobGluZSwgdW5kZWZpbmVkLCB7XG4gICAgICBhbmltYXRlZDogIWFuaW1hdGlvbnNEaXNhYmxlZCxcbiAgICAgIG9wdGlvbnNcbiAgICB9LCBtb2RlKTtcbiAgICBtZS51cGRhdGVFbGVtZW50cyhwb2ludHMsIHN0YXJ0LCBjb3VudCwgbW9kZSk7XG4gIH1cbiAgdXBkYXRlRWxlbWVudHMocG9pbnRzLCBzdGFydCwgY291bnQsIG1vZGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgcmVzZXQgPSBtb2RlID09PSAncmVzZXQnO1xuICAgIGNvbnN0IHtpU2NhbGUsIHZTY2FsZSwgX3N0YWNrZWR9ID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgZmlyc3RPcHRzID0gbWUucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhzdGFydCwgbW9kZSk7XG4gICAgY29uc3Qgc2hhcmVkT3B0aW9ucyA9IG1lLmdldFNoYXJlZE9wdGlvbnMoZmlyc3RPcHRzKTtcbiAgICBjb25zdCBpbmNsdWRlT3B0aW9ucyA9IG1lLmluY2x1ZGVPcHRpb25zKG1vZGUsIHNoYXJlZE9wdGlvbnMpO1xuICAgIGNvbnN0IGlBeGlzID0gaVNjYWxlLmF4aXM7XG4gICAgY29uc3QgdkF4aXMgPSB2U2NhbGUuYXhpcztcbiAgICBjb25zdCBzcGFuR2FwcyA9IG1lLm9wdGlvbnMuc3BhbkdhcHM7XG4gICAgY29uc3QgbWF4R2FwTGVuZ3RoID0gaXNOdW1iZXIoc3BhbkdhcHMpID8gc3BhbkdhcHMgOiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gICAgY29uc3QgZGlyZWN0VXBkYXRlID0gbWUuY2hhcnQuX2FuaW1hdGlvbnNEaXNhYmxlZCB8fCByZXNldCB8fCBtb2RlID09PSAnbm9uZSc7XG4gICAgbGV0IHByZXZQYXJzZWQgPSBzdGFydCA+IDAgJiYgbWUuZ2V0UGFyc2VkKHN0YXJ0IC0gMSk7XG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgKytpKSB7XG4gICAgICBjb25zdCBwb2ludCA9IHBvaW50c1tpXTtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IG1lLmdldFBhcnNlZChpKTtcbiAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBkaXJlY3RVcGRhdGUgPyBwb2ludCA6IHt9O1xuICAgICAgY29uc3QgbnVsbERhdGEgPSBpc051bGxPclVuZGVmKHBhcnNlZFt2QXhpc10pO1xuICAgICAgY29uc3QgaVBpeGVsID0gcHJvcGVydGllc1tpQXhpc10gPSBpU2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShwYXJzZWRbaUF4aXNdLCBpKTtcbiAgICAgIGNvbnN0IHZQaXhlbCA9IHByb3BlcnRpZXNbdkF4aXNdID0gcmVzZXQgfHwgbnVsbERhdGEgPyB2U2NhbGUuZ2V0QmFzZVBpeGVsKCkgOiB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShfc3RhY2tlZCA/IG1lLmFwcGx5U3RhY2sodlNjYWxlLCBwYXJzZWQsIF9zdGFja2VkKSA6IHBhcnNlZFt2QXhpc10sIGkpO1xuICAgICAgcHJvcGVydGllcy5za2lwID0gaXNOYU4oaVBpeGVsKSB8fCBpc05hTih2UGl4ZWwpIHx8IG51bGxEYXRhO1xuICAgICAgcHJvcGVydGllcy5zdG9wID0gaSA+IDAgJiYgKHBhcnNlZFtpQXhpc10gLSBwcmV2UGFyc2VkW2lBeGlzXSkgPiBtYXhHYXBMZW5ndGg7XG4gICAgICBwcm9wZXJ0aWVzLnBhcnNlZCA9IHBhcnNlZDtcbiAgICAgIGlmIChpbmNsdWRlT3B0aW9ucykge1xuICAgICAgICBwcm9wZXJ0aWVzLm9wdGlvbnMgPSBzaGFyZWRPcHRpb25zIHx8IG1lLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgcG9pbnQuYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKTtcbiAgICAgIH1cbiAgICAgIGlmICghZGlyZWN0VXBkYXRlKSB7XG4gICAgICAgIG1lLnVwZGF0ZUVsZW1lbnQocG9pbnQsIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgICAgfVxuICAgICAgcHJldlBhcnNlZCA9IHBhcnNlZDtcbiAgICB9XG4gICAgbWUudXBkYXRlU2hhcmVkT3B0aW9ucyhzaGFyZWRPcHRpb25zLCBtb2RlLCBmaXJzdE9wdHMpO1xuICB9XG4gIGdldE1heE92ZXJmbG93KCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgZGF0YXNldCA9IG1ldGEuZGF0YXNldDtcbiAgICBjb25zdCBib3JkZXIgPSBkYXRhc2V0Lm9wdGlvbnMgJiYgZGF0YXNldC5vcHRpb25zLmJvcmRlcldpZHRoIHx8IDA7XG4gICAgY29uc3QgZGF0YSA9IG1ldGEuZGF0YSB8fCBbXTtcbiAgICBpZiAoIWRhdGEubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gYm9yZGVyO1xuICAgIH1cbiAgICBjb25zdCBmaXJzdFBvaW50ID0gZGF0YVswXS5zaXplKG1lLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoMCkpO1xuICAgIGNvbnN0IGxhc3RQb2ludCA9IGRhdGFbZGF0YS5sZW5ndGggLSAxXS5zaXplKG1lLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoZGF0YS5sZW5ndGggLSAxKSk7XG4gICAgcmV0dXJuIE1hdGgubWF4KGJvcmRlciwgZmlyc3RQb2ludCwgbGFzdFBvaW50KSAvIDI7XG4gIH1cbiAgZHJhdygpIHtcbiAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICBtZXRhLmRhdGFzZXQudXBkYXRlQ29udHJvbFBvaW50cyh0aGlzLmNoYXJ0LmNoYXJ0QXJlYSwgbWV0YS5pU2NhbGUuYXhpcyk7XG4gICAgc3VwZXIuZHJhdygpO1xuICB9XG59XG5MaW5lQ29udHJvbGxlci5pZCA9ICdsaW5lJztcbkxpbmVDb250cm9sbGVyLmRlZmF1bHRzID0ge1xuICBkYXRhc2V0RWxlbWVudFR5cGU6ICdsaW5lJyxcbiAgZGF0YUVsZW1lbnRUeXBlOiAncG9pbnQnLFxuICBzaG93TGluZTogdHJ1ZSxcbiAgc3BhbkdhcHM6IGZhbHNlLFxufTtcbkxpbmVDb250cm9sbGVyLm92ZXJyaWRlcyA9IHtcbiAgc2NhbGVzOiB7XG4gICAgX2luZGV4Xzoge1xuICAgICAgdHlwZTogJ2NhdGVnb3J5JyxcbiAgICB9LFxuICAgIF92YWx1ZV86IHtcbiAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgIH0sXG4gIH1cbn07XG5mdW5jdGlvbiBnZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzKG1ldGEsIHBvaW50cywgYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gIGNvbnN0IHBvaW50Q291bnQgPSBwb2ludHMubGVuZ3RoO1xuICBsZXQgc3RhcnQgPSAwO1xuICBsZXQgY291bnQgPSBwb2ludENvdW50O1xuICBpZiAobWV0YS5fc29ydGVkKSB7XG4gICAgY29uc3Qge2lTY2FsZSwgX3BhcnNlZH0gPSBtZXRhO1xuICAgIGNvbnN0IGF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICBjb25zdCB7bWluLCBtYXgsIG1pbkRlZmluZWQsIG1heERlZmluZWR9ID0gaVNjYWxlLmdldFVzZXJCb3VuZHMoKTtcbiAgICBpZiAobWluRGVmaW5lZCkge1xuICAgICAgc3RhcnQgPSBfbGltaXRWYWx1ZShNYXRoLm1pbihcbiAgICAgICAgX2xvb2t1cEJ5S2V5KF9wYXJzZWQsIGlTY2FsZS5heGlzLCBtaW4pLmxvLFxuICAgICAgICBhbmltYXRpb25zRGlzYWJsZWQgPyBwb2ludENvdW50IDogX2xvb2t1cEJ5S2V5KHBvaW50cywgYXhpcywgaVNjYWxlLmdldFBpeGVsRm9yVmFsdWUobWluKSkubG8pLFxuICAgICAgMCwgcG9pbnRDb3VudCAtIDEpO1xuICAgIH1cbiAgICBpZiAobWF4RGVmaW5lZCkge1xuICAgICAgY291bnQgPSBfbGltaXRWYWx1ZShNYXRoLm1heChcbiAgICAgICAgX2xvb2t1cEJ5S2V5KF9wYXJzZWQsIGlTY2FsZS5heGlzLCBtYXgpLmhpICsgMSxcbiAgICAgICAgYW5pbWF0aW9uc0Rpc2FibGVkID8gMCA6IF9sb29rdXBCeUtleShwb2ludHMsIGF4aXMsIGlTY2FsZS5nZXRQaXhlbEZvclZhbHVlKG1heCkpLmhpICsgMSksXG4gICAgICBzdGFydCwgcG9pbnRDb3VudCkgLSBzdGFydDtcbiAgICB9IGVsc2Uge1xuICAgICAgY291bnQgPSBwb2ludENvdW50IC0gc3RhcnQ7XG4gICAgfVxuICB9XG4gIHJldHVybiB7c3RhcnQsIGNvdW50fTtcbn1cbmZ1bmN0aW9uIHNjYWxlUmFuZ2VzQ2hhbmdlZChtZXRhKSB7XG4gIGNvbnN0IHt4U2NhbGUsIHlTY2FsZSwgX3NjYWxlUmFuZ2VzfSA9IG1ldGE7XG4gIGNvbnN0IG5ld1JhbmdlcyA9IHtcbiAgICB4bWluOiB4U2NhbGUubWluLFxuICAgIHhtYXg6IHhTY2FsZS5tYXgsXG4gICAgeW1pbjogeVNjYWxlLm1pbixcbiAgICB5bWF4OiB5U2NhbGUubWF4XG4gIH07XG4gIGlmICghX3NjYWxlUmFuZ2VzKSB7XG4gICAgbWV0YS5fc2NhbGVSYW5nZXMgPSBuZXdSYW5nZXM7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgY29uc3QgY2hhbmdlZCA9IF9zY2FsZVJhbmdlcy54bWluICE9PSB4U2NhbGUubWluXG5cdFx0fHwgX3NjYWxlUmFuZ2VzLnhtYXggIT09IHhTY2FsZS5tYXhcblx0XHR8fCBfc2NhbGVSYW5nZXMueW1pbiAhPT0geVNjYWxlLm1pblxuXHRcdHx8IF9zY2FsZVJhbmdlcy55bWF4ICE9PSB5U2NhbGUubWF4O1xuICBPYmplY3QuYXNzaWduKF9zY2FsZVJhbmdlcywgbmV3UmFuZ2VzKTtcbiAgcmV0dXJuIGNoYW5nZWQ7XG59XG5cbmNsYXNzIFBvbGFyQXJlYUNvbnRyb2xsZXIgZXh0ZW5kcyBEYXRhc2V0Q29udHJvbGxlciB7XG4gIGNvbnN0cnVjdG9yKGNoYXJ0LCBkYXRhc2V0SW5kZXgpIHtcbiAgICBzdXBlcihjaGFydCwgZGF0YXNldEluZGV4KTtcbiAgICB0aGlzLmlubmVyUmFkaXVzID0gdW5kZWZpbmVkO1xuICAgIHRoaXMub3V0ZXJSYWRpdXMgPSB1bmRlZmluZWQ7XG4gIH1cbiAgZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX2NhY2hlZE1ldGE7XG4gICAgY29uc3QgY2hhcnQgPSBtZS5jaGFydDtcbiAgICBjb25zdCBsYWJlbHMgPSBjaGFydC5kYXRhLmxhYmVscyB8fCBbXTtcbiAgICBjb25zdCB2YWx1ZSA9IGZvcm1hdE51bWJlcihtZXRhLl9wYXJzZWRbaW5kZXhdLnIsIGNoYXJ0Lm9wdGlvbnMubG9jYWxlKTtcbiAgICByZXR1cm4ge1xuICAgICAgbGFiZWw6IGxhYmVsc1tpbmRleF0gfHwgJycsXG4gICAgICB2YWx1ZSxcbiAgICB9O1xuICB9XG4gIHVwZGF0ZShtb2RlKSB7XG4gICAgY29uc3QgYXJjcyA9IHRoaXMuX2NhY2hlZE1ldGEuZGF0YTtcbiAgICB0aGlzLl91cGRhdGVSYWRpdXMoKTtcbiAgICB0aGlzLnVwZGF0ZUVsZW1lbnRzKGFyY3MsIDAsIGFyY3MubGVuZ3RoLCBtb2RlKTtcbiAgfVxuICBfdXBkYXRlUmFkaXVzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBjaGFydCA9IG1lLmNoYXJ0O1xuICAgIGNvbnN0IGNoYXJ0QXJlYSA9IGNoYXJ0LmNoYXJ0QXJlYTtcbiAgICBjb25zdCBvcHRzID0gY2hhcnQub3B0aW9ucztcbiAgICBjb25zdCBtaW5TaXplID0gTWF0aC5taW4oY2hhcnRBcmVhLnJpZ2h0IC0gY2hhcnRBcmVhLmxlZnQsIGNoYXJ0QXJlYS5ib3R0b20gLSBjaGFydEFyZWEudG9wKTtcbiAgICBjb25zdCBvdXRlclJhZGl1cyA9IE1hdGgubWF4KG1pblNpemUgLyAyLCAwKTtcbiAgICBjb25zdCBpbm5lclJhZGl1cyA9IE1hdGgubWF4KG9wdHMuY3V0b3V0UGVyY2VudGFnZSA/IChvdXRlclJhZGl1cyAvIDEwMCkgKiAob3B0cy5jdXRvdXRQZXJjZW50YWdlKSA6IDEsIDApO1xuICAgIGNvbnN0IHJhZGl1c0xlbmd0aCA9IChvdXRlclJhZGl1cyAtIGlubmVyUmFkaXVzKSAvIGNoYXJ0LmdldFZpc2libGVEYXRhc2V0Q291bnQoKTtcbiAgICBtZS5vdXRlclJhZGl1cyA9IG91dGVyUmFkaXVzIC0gKHJhZGl1c0xlbmd0aCAqIG1lLmluZGV4KTtcbiAgICBtZS5pbm5lclJhZGl1cyA9IG1lLm91dGVyUmFkaXVzIC0gcmFkaXVzTGVuZ3RoO1xuICB9XG4gIHVwZGF0ZUVsZW1lbnRzKGFyY3MsIHN0YXJ0LCBjb3VudCwgbW9kZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCByZXNldCA9IG1vZGUgPT09ICdyZXNldCc7XG4gICAgY29uc3QgY2hhcnQgPSBtZS5jaGFydDtcbiAgICBjb25zdCBkYXRhc2V0ID0gbWUuZ2V0RGF0YXNldCgpO1xuICAgIGNvbnN0IG9wdHMgPSBjaGFydC5vcHRpb25zO1xuICAgIGNvbnN0IGFuaW1hdGlvbk9wdHMgPSBvcHRzLmFuaW1hdGlvbjtcbiAgICBjb25zdCBzY2FsZSA9IG1lLl9jYWNoZWRNZXRhLnJTY2FsZTtcbiAgICBjb25zdCBjZW50ZXJYID0gc2NhbGUueENlbnRlcjtcbiAgICBjb25zdCBjZW50ZXJZID0gc2NhbGUueUNlbnRlcjtcbiAgICBjb25zdCBkYXRhc2V0U3RhcnRBbmdsZSA9IHNjYWxlLmdldEluZGV4QW5nbGUoMCkgLSAwLjUgKiBQSTtcbiAgICBsZXQgYW5nbGUgPSBkYXRhc2V0U3RhcnRBbmdsZTtcbiAgICBsZXQgaTtcbiAgICBjb25zdCBkZWZhdWx0QW5nbGUgPSAzNjAgLyBtZS5jb3VudFZpc2libGVFbGVtZW50cygpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBzdGFydDsgKytpKSB7XG4gICAgICBhbmdsZSArPSBtZS5fY29tcHV0ZUFuZ2xlKGksIG1vZGUsIGRlZmF1bHRBbmdsZSk7XG4gICAgfVxuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBhcmMgPSBhcmNzW2ldO1xuICAgICAgbGV0IHN0YXJ0QW5nbGUgPSBhbmdsZTtcbiAgICAgIGxldCBlbmRBbmdsZSA9IGFuZ2xlICsgbWUuX2NvbXB1dGVBbmdsZShpLCBtb2RlLCBkZWZhdWx0QW5nbGUpO1xuICAgICAgbGV0IG91dGVyUmFkaXVzID0gY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaSkgPyBzY2FsZS5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZShkYXRhc2V0LmRhdGFbaV0pIDogMDtcbiAgICAgIGFuZ2xlID0gZW5kQW5nbGU7XG4gICAgICBpZiAocmVzZXQpIHtcbiAgICAgICAgaWYgKGFuaW1hdGlvbk9wdHMuYW5pbWF0ZVNjYWxlKSB7XG4gICAgICAgICAgb3V0ZXJSYWRpdXMgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhbmltYXRpb25PcHRzLmFuaW1hdGVSb3RhdGUpIHtcbiAgICAgICAgICBzdGFydEFuZ2xlID0gZW5kQW5nbGUgPSBkYXRhc2V0U3RhcnRBbmdsZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgICAgeDogY2VudGVyWCxcbiAgICAgICAgeTogY2VudGVyWSxcbiAgICAgICAgaW5uZXJSYWRpdXM6IDAsXG4gICAgICAgIG91dGVyUmFkaXVzLFxuICAgICAgICBzdGFydEFuZ2xlLFxuICAgICAgICBlbmRBbmdsZSxcbiAgICAgICAgb3B0aW9uczogbWUucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpLCBhcmMuYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKVxuICAgICAgfTtcbiAgICAgIG1lLnVwZGF0ZUVsZW1lbnQoYXJjLCBpLCBwcm9wZXJ0aWVzLCBtb2RlKTtcbiAgICB9XG4gIH1cbiAgY291bnRWaXNpYmxlRWxlbWVudHMoKSB7XG4gICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZ2V0RGF0YXNldCgpO1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgIGxldCBjb3VudCA9IDA7XG4gICAgbWV0YS5kYXRhLmZvckVhY2goKGVsZW1lbnQsIGluZGV4KSA9PiB7XG4gICAgICBpZiAoIWlzTmFOKGRhdGFzZXQuZGF0YVtpbmRleF0pICYmIHRoaXMuY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaW5kZXgpKSB7XG4gICAgICAgIGNvdW50Kys7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvdW50O1xuICB9XG4gIF9jb21wdXRlQW5nbGUoaW5kZXgsIG1vZGUsIGRlZmF1bHRBbmdsZSkge1xuICAgIHJldHVybiB0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGluZGV4KVxuICAgICAgPyB0b1JhZGlhbnModGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGluZGV4LCBtb2RlKS5hbmdsZSB8fCBkZWZhdWx0QW5nbGUpXG4gICAgICA6IDA7XG4gIH1cbn1cblBvbGFyQXJlYUNvbnRyb2xsZXIuaWQgPSAncG9sYXJBcmVhJztcblBvbGFyQXJlYUNvbnRyb2xsZXIuZGVmYXVsdHMgPSB7XG4gIGRhdGFFbGVtZW50VHlwZTogJ2FyYycsXG4gIGFuaW1hdGlvbjoge1xuICAgIGFuaW1hdGVSb3RhdGU6IHRydWUsXG4gICAgYW5pbWF0ZVNjYWxlOiB0cnVlXG4gIH0sXG4gIGFuaW1hdGlvbnM6IHtcbiAgICBudW1iZXJzOiB7XG4gICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgIHByb3BlcnRpZXM6IFsneCcsICd5JywgJ3N0YXJ0QW5nbGUnLCAnZW5kQW5nbGUnLCAnaW5uZXJSYWRpdXMnLCAnb3V0ZXJSYWRpdXMnXVxuICAgIH0sXG4gIH0sXG4gIGluZGV4QXhpczogJ3InLFxuICBzdGFydEFuZ2xlOiAwLFxufTtcblBvbGFyQXJlYUNvbnRyb2xsZXIub3ZlcnJpZGVzID0ge1xuICBhc3BlY3RSYXRpbzogMSxcbiAgcGx1Z2luczoge1xuICAgIGxlZ2VuZDoge1xuICAgICAgbGFiZWxzOiB7XG4gICAgICAgIGdlbmVyYXRlTGFiZWxzKGNoYXJ0KSB7XG4gICAgICAgICAgY29uc3QgZGF0YSA9IGNoYXJ0LmRhdGE7XG4gICAgICAgICAgaWYgKGRhdGEubGFiZWxzLmxlbmd0aCAmJiBkYXRhLmRhdGFzZXRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3Qge2xhYmVsczoge3BvaW50U3R5bGV9fSA9IGNoYXJ0LmxlZ2VuZC5vcHRpb25zO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGEubGFiZWxzLm1hcCgobGFiZWwsIGkpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKDApO1xuICAgICAgICAgICAgICBjb25zdCBzdHlsZSA9IG1ldGEuY29udHJvbGxlci5nZXRTdHlsZShpKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB0ZXh0OiBsYWJlbCxcbiAgICAgICAgICAgICAgICBmaWxsU3R5bGU6IHN0eWxlLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICAgICAgICBzdHJva2VTdHlsZTogc3R5bGUuYm9yZGVyQ29sb3IsXG4gICAgICAgICAgICAgICAgbGluZVdpZHRoOiBzdHlsZS5ib3JkZXJXaWR0aCxcbiAgICAgICAgICAgICAgICBwb2ludFN0eWxlOiBwb2ludFN0eWxlLFxuICAgICAgICAgICAgICAgIGhpZGRlbjogIWNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpLFxuICAgICAgICAgICAgICAgIGluZGV4OiBpXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgb25DbGljayhlLCBsZWdlbmRJdGVtLCBsZWdlbmQpIHtcbiAgICAgICAgbGVnZW5kLmNoYXJ0LnRvZ2dsZURhdGFWaXNpYmlsaXR5KGxlZ2VuZEl0ZW0uaW5kZXgpO1xuICAgICAgICBsZWdlbmQuY2hhcnQudXBkYXRlKCk7XG4gICAgICB9XG4gICAgfSxcbiAgICB0b29sdGlwOiB7XG4gICAgICBjYWxsYmFja3M6IHtcbiAgICAgICAgdGl0bGUoKSB7XG4gICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9LFxuICAgICAgICBsYWJlbChjb250ZXh0KSB7XG4gICAgICAgICAgcmV0dXJuIGNvbnRleHQuY2hhcnQuZGF0YS5sYWJlbHNbY29udGV4dC5kYXRhSW5kZXhdICsgJzogJyArIGNvbnRleHQuZm9ybWF0dGVkVmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIHNjYWxlczoge1xuICAgIHI6IHtcbiAgICAgIHR5cGU6ICdyYWRpYWxMaW5lYXInLFxuICAgICAgYW5nbGVMaW5lczoge1xuICAgICAgICBkaXNwbGF5OiBmYWxzZVxuICAgICAgfSxcbiAgICAgIGJlZ2luQXRaZXJvOiB0cnVlLFxuICAgICAgZ3JpZDoge1xuICAgICAgICBjaXJjdWxhcjogdHJ1ZVxuICAgICAgfSxcbiAgICAgIHBvaW50TGFiZWxzOiB7XG4gICAgICAgIGRpc3BsYXk6IGZhbHNlXG4gICAgICB9LFxuICAgICAgc3RhcnRBbmdsZTogMFxuICAgIH1cbiAgfVxufTtcblxuY2xhc3MgUGllQ29udHJvbGxlciBleHRlbmRzIERvdWdobnV0Q29udHJvbGxlciB7XG59XG5QaWVDb250cm9sbGVyLmlkID0gJ3BpZSc7XG5QaWVDb250cm9sbGVyLmRlZmF1bHRzID0ge1xuICBjdXRvdXQ6IDAsXG4gIHJvdGF0aW9uOiAwLFxuICBjaXJjdW1mZXJlbmNlOiAzNjAsXG4gIHJhZGl1czogJzEwMCUnXG59O1xuXG5jbGFzcyBSYWRhckNvbnRyb2xsZXIgZXh0ZW5kcyBEYXRhc2V0Q29udHJvbGxlciB7XG4gIGdldExhYmVsQW5kVmFsdWUoaW5kZXgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgdlNjYWxlID0gbWUuX2NhY2hlZE1ldGEudlNjYWxlO1xuICAgIGNvbnN0IHBhcnNlZCA9IG1lLmdldFBhcnNlZChpbmRleCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsOiB2U2NhbGUuZ2V0TGFiZWxzKClbaW5kZXhdLFxuICAgICAgdmFsdWU6ICcnICsgdlNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkW3ZTY2FsZS5heGlzXSlcbiAgICB9O1xuICB9XG4gIHVwZGF0ZShtb2RlKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5fY2FjaGVkTWV0YTtcbiAgICBjb25zdCBsaW5lID0gbWV0YS5kYXRhc2V0O1xuICAgIGNvbnN0IHBvaW50cyA9IG1ldGEuZGF0YSB8fCBbXTtcbiAgICBjb25zdCBsYWJlbHMgPSBtZXRhLmlTY2FsZS5nZXRMYWJlbHMoKTtcbiAgICBsaW5lLnBvaW50cyA9IHBvaW50cztcbiAgICBpZiAobW9kZSAhPT0gJ3Jlc2l6ZScpIHtcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5yZXNvbHZlRGF0YXNldEVsZW1lbnRPcHRpb25zKG1vZGUpO1xuICAgICAgaWYgKCFtZS5vcHRpb25zLnNob3dMaW5lKSB7XG4gICAgICAgIG9wdGlvbnMuYm9yZGVyV2lkdGggPSAwO1xuICAgICAgfVxuICAgICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgICAgX2xvb3A6IHRydWUsXG4gICAgICAgIF9mdWxsTG9vcDogbGFiZWxzLmxlbmd0aCA9PT0gcG9pbnRzLmxlbmd0aCxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgfTtcbiAgICAgIG1lLnVwZGF0ZUVsZW1lbnQobGluZSwgdW5kZWZpbmVkLCBwcm9wZXJ0aWVzLCBtb2RlKTtcbiAgICB9XG4gICAgbWUudXBkYXRlRWxlbWVudHMocG9pbnRzLCAwLCBwb2ludHMubGVuZ3RoLCBtb2RlKTtcbiAgfVxuICB1cGRhdGVFbGVtZW50cyhwb2ludHMsIHN0YXJ0LCBjb3VudCwgbW9kZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBkYXRhc2V0ID0gbWUuZ2V0RGF0YXNldCgpO1xuICAgIGNvbnN0IHNjYWxlID0gbWUuX2NhY2hlZE1ldGEuclNjYWxlO1xuICAgIGNvbnN0IHJlc2V0ID0gbW9kZSA9PT0gJ3Jlc2V0JztcbiAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBzdGFydCArIGNvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgY29uc3Qgb3B0aW9ucyA9IG1lLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgcG9pbnQuYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKTtcbiAgICAgIGNvbnN0IHBvaW50UG9zaXRpb24gPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUoaSwgZGF0YXNldC5kYXRhW2ldKTtcbiAgICAgIGNvbnN0IHggPSByZXNldCA/IHNjYWxlLnhDZW50ZXIgOiBwb2ludFBvc2l0aW9uLng7XG4gICAgICBjb25zdCB5ID0gcmVzZXQgPyBzY2FsZS55Q2VudGVyIDogcG9pbnRQb3NpdGlvbi55O1xuICAgICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgICAgeCxcbiAgICAgICAgeSxcbiAgICAgICAgYW5nbGU6IHBvaW50UG9zaXRpb24uYW5nbGUsXG4gICAgICAgIHNraXA6IGlzTmFOKHgpIHx8IGlzTmFOKHkpLFxuICAgICAgICBvcHRpb25zXG4gICAgICB9O1xuICAgICAgbWUudXBkYXRlRWxlbWVudChwb2ludCwgaSwgcHJvcGVydGllcywgbW9kZSk7XG4gICAgfVxuICB9XG59XG5SYWRhckNvbnRyb2xsZXIuaWQgPSAncmFkYXInO1xuUmFkYXJDb250cm9sbGVyLmRlZmF1bHRzID0ge1xuICBkYXRhc2V0RWxlbWVudFR5cGU6ICdsaW5lJyxcbiAgZGF0YUVsZW1lbnRUeXBlOiAncG9pbnQnLFxuICBpbmRleEF4aXM6ICdyJyxcbiAgc2hvd0xpbmU6IHRydWUsXG4gIGVsZW1lbnRzOiB7XG4gICAgbGluZToge1xuICAgICAgZmlsbDogJ3N0YXJ0J1xuICAgIH1cbiAgfSxcbn07XG5SYWRhckNvbnRyb2xsZXIub3ZlcnJpZGVzID0ge1xuICBhc3BlY3RSYXRpbzogMSxcbiAgc2NhbGVzOiB7XG4gICAgcjoge1xuICAgICAgdHlwZTogJ3JhZGlhbExpbmVhcicsXG4gICAgfVxuICB9XG59O1xuXG5jbGFzcyBTY2F0dGVyQ29udHJvbGxlciBleHRlbmRzIExpbmVDb250cm9sbGVyIHtcbn1cblNjYXR0ZXJDb250cm9sbGVyLmlkID0gJ3NjYXR0ZXInO1xuU2NhdHRlckNvbnRyb2xsZXIuZGVmYXVsdHMgPSB7XG4gIHNob3dMaW5lOiBmYWxzZSxcbiAgZmlsbDogZmFsc2Vcbn07XG5TY2F0dGVyQ29udHJvbGxlci5vdmVycmlkZXMgPSB7XG4gIGludGVyYWN0aW9uOiB7XG4gICAgbW9kZTogJ3BvaW50J1xuICB9LFxuICBwbHVnaW5zOiB7XG4gICAgdG9vbHRpcDoge1xuICAgICAgY2FsbGJhY2tzOiB7XG4gICAgICAgIHRpdGxlKCkge1xuICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFiZWwoaXRlbSkge1xuICAgICAgICAgIHJldHVybiAnKCcgKyBpdGVtLmxhYmVsICsgJywgJyArIGl0ZW0uZm9ybWF0dGVkVmFsdWUgKyAnKSc7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIHNjYWxlczoge1xuICAgIHg6IHtcbiAgICAgIHR5cGU6ICdsaW5lYXInXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICB0eXBlOiAnbGluZWFyJ1xuICAgIH1cbiAgfVxufTtcblxudmFyIGNvbnRyb2xsZXJzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuX19wcm90b19fOiBudWxsLFxuQmFyQ29udHJvbGxlcjogQmFyQ29udHJvbGxlcixcbkJ1YmJsZUNvbnRyb2xsZXI6IEJ1YmJsZUNvbnRyb2xsZXIsXG5Eb3VnaG51dENvbnRyb2xsZXI6IERvdWdobnV0Q29udHJvbGxlcixcbkxpbmVDb250cm9sbGVyOiBMaW5lQ29udHJvbGxlcixcblBvbGFyQXJlYUNvbnRyb2xsZXI6IFBvbGFyQXJlYUNvbnRyb2xsZXIsXG5QaWVDb250cm9sbGVyOiBQaWVDb250cm9sbGVyLFxuUmFkYXJDb250cm9sbGVyOiBSYWRhckNvbnRyb2xsZXIsXG5TY2F0dGVyQ29udHJvbGxlcjogU2NhdHRlckNvbnRyb2xsZXJcbn0pO1xuXG5mdW5jdGlvbiBhYnN0cmFjdCgpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdUaGlzIG1ldGhvZCBpcyBub3QgaW1wbGVtZW50ZWQ6IENoZWNrIHRoYXQgYSBjb21wbGV0ZSBkYXRlIGFkYXB0ZXIgaXMgcHJvdmlkZWQuJyk7XG59XG5jbGFzcyBEYXRlQWRhcHRlciB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB9XG4gIGZvcm1hdHMoKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH1cbiAgcGFyc2UodmFsdWUsIGZvcm1hdCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9XG4gIGZvcm1hdCh0aW1lc3RhbXAsIGZvcm1hdCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9XG4gIGFkZCh0aW1lc3RhbXAsIGFtb3VudCwgdW5pdCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9XG4gIGRpZmYoYSwgYiwgdW5pdCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9XG4gIHN0YXJ0T2YodGltZXN0YW1wLCB1bml0LCB3ZWVrZGF5KSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH1cbiAgZW5kT2YodGltZXN0YW1wLCB1bml0KSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH1cbn1cbkRhdGVBZGFwdGVyLm92ZXJyaWRlID0gZnVuY3Rpb24obWVtYmVycykge1xuICBPYmplY3QuYXNzaWduKERhdGVBZGFwdGVyLnByb3RvdHlwZSwgbWVtYmVycyk7XG59O1xudmFyIGFkYXB0ZXJzID0ge1xuICBfZGF0ZTogRGF0ZUFkYXB0ZXJcbn07XG5cbmZ1bmN0aW9uIGdldFJlbGF0aXZlUG9zaXRpb24oZSwgY2hhcnQpIHtcbiAgaWYgKCduYXRpdmUnIGluIGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgeDogZS54LFxuICAgICAgeTogZS55XG4gICAgfTtcbiAgfVxuICByZXR1cm4gZ2V0UmVsYXRpdmVQb3NpdGlvbiQxKGUsIGNoYXJ0KTtcbn1cbmZ1bmN0aW9uIGV2YWx1YXRlQWxsVmlzaWJsZUl0ZW1zKGNoYXJ0LCBoYW5kbGVyKSB7XG4gIGNvbnN0IG1ldGFzZXRzID0gY2hhcnQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO1xuICBsZXQgaW5kZXgsIGRhdGEsIGVsZW1lbnQ7XG4gIGZvciAobGV0IGkgPSAwLCBpbGVuID0gbWV0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgKHtpbmRleCwgZGF0YX0gPSBtZXRhc2V0c1tpXSk7XG4gICAgZm9yIChsZXQgaiA9IDAsIGpsZW4gPSBkYXRhLmxlbmd0aDsgaiA8IGpsZW47ICsraikge1xuICAgICAgZWxlbWVudCA9IGRhdGFbal07XG4gICAgICBpZiAoIWVsZW1lbnQuc2tpcCkge1xuICAgICAgICBoYW5kbGVyKGVsZW1lbnQsIGluZGV4LCBqKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uIGJpbmFyeVNlYXJjaChtZXRhc2V0LCBheGlzLCB2YWx1ZSwgaW50ZXJzZWN0KSB7XG4gIGNvbnN0IHtjb250cm9sbGVyLCBkYXRhLCBfc29ydGVkfSA9IG1ldGFzZXQ7XG4gIGNvbnN0IGlTY2FsZSA9IGNvbnRyb2xsZXIuX2NhY2hlZE1ldGEuaVNjYWxlO1xuICBpZiAoaVNjYWxlICYmIGF4aXMgPT09IGlTY2FsZS5heGlzICYmIF9zb3J0ZWQgJiYgZGF0YS5sZW5ndGgpIHtcbiAgICBjb25zdCBsb29rdXBNZXRob2QgPSBpU2NhbGUuX3JldmVyc2VQaXhlbHMgPyBfcmxvb2t1cEJ5S2V5IDogX2xvb2t1cEJ5S2V5O1xuICAgIGlmICghaW50ZXJzZWN0KSB7XG4gICAgICByZXR1cm4gbG9va3VwTWV0aG9kKGRhdGEsIGF4aXMsIHZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKGNvbnRyb2xsZXIuX3NoYXJlZE9wdGlvbnMpIHtcbiAgICAgIGNvbnN0IGVsID0gZGF0YVswXTtcbiAgICAgIGNvbnN0IHJhbmdlID0gdHlwZW9mIGVsLmdldFJhbmdlID09PSAnZnVuY3Rpb24nICYmIGVsLmdldFJhbmdlKGF4aXMpO1xuICAgICAgaWYgKHJhbmdlKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gbG9va3VwTWV0aG9kKGRhdGEsIGF4aXMsIHZhbHVlIC0gcmFuZ2UpO1xuICAgICAgICBjb25zdCBlbmQgPSBsb29rdXBNZXRob2QoZGF0YSwgYXhpcywgdmFsdWUgKyByYW5nZSk7XG4gICAgICAgIHJldHVybiB7bG86IHN0YXJ0LmxvLCBoaTogZW5kLmhpfTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtsbzogMCwgaGk6IGRhdGEubGVuZ3RoIC0gMX07XG59XG5mdW5jdGlvbiBvcHRpbWl6ZWRFdmFsdWF0ZUl0ZW1zKGNoYXJ0LCBheGlzLCBwb3NpdGlvbiwgaGFuZGxlciwgaW50ZXJzZWN0KSB7XG4gIGNvbnN0IG1ldGFzZXRzID0gY2hhcnQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO1xuICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW2F4aXNdO1xuICBmb3IgKGxldCBpID0gMCwgaWxlbiA9IG1ldGFzZXRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgIGNvbnN0IHtpbmRleCwgZGF0YX0gPSBtZXRhc2V0c1tpXTtcbiAgICBjb25zdCB7bG8sIGhpfSA9IGJpbmFyeVNlYXJjaChtZXRhc2V0c1tpXSwgYXhpcywgdmFsdWUsIGludGVyc2VjdCk7XG4gICAgZm9yIChsZXQgaiA9IGxvOyBqIDw9IGhpOyArK2opIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBkYXRhW2pdO1xuICAgICAgaWYgKCFlbGVtZW50LnNraXApIHtcbiAgICAgICAgaGFuZGxlcihlbGVtZW50LCBpbmRleCwgaik7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5mdW5jdGlvbiBnZXREaXN0YW5jZU1ldHJpY0ZvckF4aXMoYXhpcykge1xuICBjb25zdCB1c2VYID0gYXhpcy5pbmRleE9mKCd4JykgIT09IC0xO1xuICBjb25zdCB1c2VZID0gYXhpcy5pbmRleE9mKCd5JykgIT09IC0xO1xuICByZXR1cm4gZnVuY3Rpb24ocHQxLCBwdDIpIHtcbiAgICBjb25zdCBkZWx0YVggPSB1c2VYID8gTWF0aC5hYnMocHQxLnggLSBwdDIueCkgOiAwO1xuICAgIGNvbnN0IGRlbHRhWSA9IHVzZVkgPyBNYXRoLmFicyhwdDEueSAtIHB0Mi55KSA6IDA7XG4gICAgcmV0dXJuIE1hdGguc3FydChNYXRoLnBvdyhkZWx0YVgsIDIpICsgTWF0aC5wb3coZGVsdGFZLCAyKSk7XG4gIH07XG59XG5mdW5jdGlvbiBnZXRJbnRlcnNlY3RJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgY29uc3QgaXRlbXMgPSBbXTtcbiAgaWYgKCFfaXNQb2ludEluQXJlYShwb3NpdGlvbiwgY2hhcnQuY2hhcnRBcmVhLCBjaGFydC5fbWluUGFkZGluZykpIHtcbiAgICByZXR1cm4gaXRlbXM7XG4gIH1cbiAgY29uc3QgZXZhbHVhdGlvbkZ1bmMgPSBmdW5jdGlvbihlbGVtZW50LCBkYXRhc2V0SW5kZXgsIGluZGV4KSB7XG4gICAgaWYgKGVsZW1lbnQuaW5SYW5nZShwb3NpdGlvbi54LCBwb3NpdGlvbi55LCB1c2VGaW5hbFBvc2l0aW9uKSkge1xuICAgICAgaXRlbXMucHVzaCh7ZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleH0pO1xuICAgIH1cbiAgfTtcbiAgb3B0aW1pemVkRXZhbHVhdGVJdGVtcyhjaGFydCwgYXhpcywgcG9zaXRpb24sIGV2YWx1YXRpb25GdW5jLCB0cnVlKTtcbiAgcmV0dXJuIGl0ZW1zO1xufVxuZnVuY3Rpb24gZ2V0TmVhcmVzdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgaW50ZXJzZWN0LCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gIGNvbnN0IGRpc3RhbmNlTWV0cmljID0gZ2V0RGlzdGFuY2VNZXRyaWNGb3JBeGlzKGF4aXMpO1xuICBsZXQgbWluRGlzdGFuY2UgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gIGxldCBpdGVtcyA9IFtdO1xuICBpZiAoIV9pc1BvaW50SW5BcmVhKHBvc2l0aW9uLCBjaGFydC5jaGFydEFyZWEsIGNoYXJ0Ll9taW5QYWRkaW5nKSkge1xuICAgIHJldHVybiBpdGVtcztcbiAgfVxuICBjb25zdCBldmFsdWF0aW9uRnVuYyA9IGZ1bmN0aW9uKGVsZW1lbnQsIGRhdGFzZXRJbmRleCwgaW5kZXgpIHtcbiAgICBpZiAoaW50ZXJzZWN0ICYmICFlbGVtZW50LmluUmFuZ2UocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgdXNlRmluYWxQb3NpdGlvbikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY2VudGVyID0gZWxlbWVudC5nZXRDZW50ZXJQb2ludCh1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICBpZiAoIV9pc1BvaW50SW5BcmVhKGNlbnRlciwgY2hhcnQuY2hhcnRBcmVhLCBjaGFydC5fbWluUGFkZGluZykgJiYgIWVsZW1lbnQuaW5SYW5nZShwb3NpdGlvbi54LCBwb3NpdGlvbi55LCB1c2VGaW5hbFBvc2l0aW9uKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBkaXN0YW5jZSA9IGRpc3RhbmNlTWV0cmljKHBvc2l0aW9uLCBjZW50ZXIpO1xuICAgIGlmIChkaXN0YW5jZSA8IG1pbkRpc3RhbmNlKSB7XG4gICAgICBpdGVtcyA9IFt7ZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleH1dO1xuICAgICAgbWluRGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICB9IGVsc2UgaWYgKGRpc3RhbmNlID09PSBtaW5EaXN0YW5jZSkge1xuICAgICAgaXRlbXMucHVzaCh7ZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleH0pO1xuICAgIH1cbiAgfTtcbiAgb3B0aW1pemVkRXZhbHVhdGVJdGVtcyhjaGFydCwgYXhpcywgcG9zaXRpb24sIGV2YWx1YXRpb25GdW5jKTtcbiAgcmV0dXJuIGl0ZW1zO1xufVxuZnVuY3Rpb24gZ2V0QXhpc0l0ZW1zKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gIGNvbnN0IHBvc2l0aW9uID0gZ2V0UmVsYXRpdmVQb3NpdGlvbihlLCBjaGFydCk7XG4gIGNvbnN0IGl0ZW1zID0gW107XG4gIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXM7XG4gIGNvbnN0IHJhbmdlTWV0aG9kID0gYXhpcyA9PT0gJ3gnID8gJ2luWFJhbmdlJyA6ICdpbllSYW5nZSc7XG4gIGxldCBpbnRlcnNlY3RzSXRlbSA9IGZhbHNlO1xuICBldmFsdWF0ZUFsbFZpc2libGVJdGVtcyhjaGFydCwgKGVsZW1lbnQsIGRhdGFzZXRJbmRleCwgaW5kZXgpID0+IHtcbiAgICBpZiAoZWxlbWVudFtyYW5nZU1ldGhvZF0ocG9zaXRpb25bYXhpc10sIHVzZUZpbmFsUG9zaXRpb24pKSB7XG4gICAgICBpdGVtcy5wdXNoKHtlbGVtZW50LCBkYXRhc2V0SW5kZXgsIGluZGV4fSk7XG4gICAgfVxuICAgIGlmIChlbGVtZW50LmluUmFuZ2UocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgdXNlRmluYWxQb3NpdGlvbikpIHtcbiAgICAgIGludGVyc2VjdHNJdGVtID0gdHJ1ZTtcbiAgICB9XG4gIH0pO1xuICBpZiAob3B0aW9ucy5pbnRlcnNlY3QgJiYgIWludGVyc2VjdHNJdGVtKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiBpdGVtcztcbn1cbnZhciBJbnRlcmFjdGlvbiA9IHtcbiAgbW9kZXM6IHtcbiAgICBpbmRleChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3gnO1xuICAgICAgY29uc3QgaXRlbXMgPSBvcHRpb25zLmludGVyc2VjdFxuICAgICAgICA/IGdldEludGVyc2VjdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgdXNlRmluYWxQb3NpdGlvbilcbiAgICAgICAgOiBnZXROZWFyZXN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBmYWxzZSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICBjb25zdCBlbGVtZW50cyA9IFtdO1xuICAgICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgY2hhcnQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpLmZvckVhY2goKG1ldGEpID0+IHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBpdGVtc1swXS5pbmRleDtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IG1ldGEuZGF0YVtpbmRleF07XG4gICAgICAgIGlmIChlbGVtZW50ICYmICFlbGVtZW50LnNraXApIHtcbiAgICAgICAgICBlbGVtZW50cy5wdXNoKHtlbGVtZW50LCBkYXRhc2V0SW5kZXg6IG1ldGEuaW5kZXgsIGluZGV4fSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGVsZW1lbnRzO1xuICAgIH0sXG4gICAgZGF0YXNldChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3h5JztcbiAgICAgIGxldCBpdGVtcyA9IG9wdGlvbnMuaW50ZXJzZWN0XG4gICAgICAgID8gZ2V0SW50ZXJzZWN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCB1c2VGaW5hbFBvc2l0aW9uKSA6XG4gICAgICAgIGdldE5lYXJlc3RJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIGZhbHNlLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgIGlmIChpdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGRhdGFzZXRJbmRleCA9IGl0ZW1zWzBdLmRhdGFzZXRJbmRleDtcbiAgICAgICAgY29uc3QgZGF0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkuZGF0YTtcbiAgICAgICAgaXRlbXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgaXRlbXMucHVzaCh7ZWxlbWVudDogZGF0YVtpXSwgZGF0YXNldEluZGV4LCBpbmRleDogaX0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gaXRlbXM7XG4gICAgfSxcbiAgICBwb2ludChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3h5JztcbiAgICAgIHJldHVybiBnZXRJbnRlcnNlY3RJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgIH0sXG4gICAgbmVhcmVzdChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3h5JztcbiAgICAgIHJldHVybiBnZXROZWFyZXN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBvcHRpb25zLmludGVyc2VjdCwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgfSxcbiAgICB4KGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICBvcHRpb25zLmF4aXMgPSAneCc7XG4gICAgICByZXR1cm4gZ2V0QXhpc0l0ZW1zKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9LFxuICAgIHkoY2hhcnQsIGUsIG9wdGlvbnMsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgIG9wdGlvbnMuYXhpcyA9ICd5JztcbiAgICAgIHJldHVybiBnZXRBeGlzSXRlbXMoY2hhcnQsIGUsIG9wdGlvbnMsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgU1RBVElDX1BPU0lUSU9OUyA9IFsnbGVmdCcsICd0b3AnLCAncmlnaHQnLCAnYm90dG9tJ107XG5mdW5jdGlvbiBmaWx0ZXJCeVBvc2l0aW9uKGFycmF5LCBwb3NpdGlvbikge1xuICByZXR1cm4gYXJyYXkuZmlsdGVyKHYgPT4gdi5wb3MgPT09IHBvc2l0aW9uKTtcbn1cbmZ1bmN0aW9uIGZpbHRlckR5bmFtaWNQb3NpdGlvbkJ5QXhpcyhhcnJheSwgYXhpcykge1xuICByZXR1cm4gYXJyYXkuZmlsdGVyKHYgPT4gU1RBVElDX1BPU0lUSU9OUy5pbmRleE9mKHYucG9zKSA9PT0gLTEgJiYgdi5ib3guYXhpcyA9PT0gYXhpcyk7XG59XG5mdW5jdGlvbiBzb3J0QnlXZWlnaHQoYXJyYXksIHJldmVyc2UpIHtcbiAgcmV0dXJuIGFycmF5LnNvcnQoKGEsIGIpID0+IHtcbiAgICBjb25zdCB2MCA9IHJldmVyc2UgPyBiIDogYTtcbiAgICBjb25zdCB2MSA9IHJldmVyc2UgPyBhIDogYjtcbiAgICByZXR1cm4gdjAud2VpZ2h0ID09PSB2MS53ZWlnaHQgP1xuICAgICAgdjAuaW5kZXggLSB2MS5pbmRleCA6XG4gICAgICB2MC53ZWlnaHQgLSB2MS53ZWlnaHQ7XG4gIH0pO1xufVxuZnVuY3Rpb24gd3JhcEJveGVzKGJveGVzKSB7XG4gIGNvbnN0IGxheW91dEJveGVzID0gW107XG4gIGxldCBpLCBpbGVuLCBib3gsIHBvcywgc3RhY2ssIHN0YWNrV2VpZ2h0O1xuICBmb3IgKGkgPSAwLCBpbGVuID0gKGJveGVzIHx8IFtdKS5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICBib3ggPSBib3hlc1tpXTtcbiAgICAoe3Bvc2l0aW9uOiBwb3MsIG9wdGlvbnM6IHtzdGFjaywgc3RhY2tXZWlnaHQgPSAxfX0gPSBib3gpO1xuICAgIGxheW91dEJveGVzLnB1c2goe1xuICAgICAgaW5kZXg6IGksXG4gICAgICBib3gsXG4gICAgICBwb3MsXG4gICAgICBob3Jpem9udGFsOiBib3guaXNIb3Jpem9udGFsKCksXG4gICAgICB3ZWlnaHQ6IGJveC53ZWlnaHQsXG4gICAgICBzdGFjazogc3RhY2sgJiYgKHBvcyArIHN0YWNrKSxcbiAgICAgIHN0YWNrV2VpZ2h0XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGxheW91dEJveGVzO1xufVxuZnVuY3Rpb24gYnVpbGRTdGFja3MobGF5b3V0cykge1xuICBjb25zdCBzdGFja3MgPSB7fTtcbiAgZm9yIChjb25zdCB3cmFwIG9mIGxheW91dHMpIHtcbiAgICBjb25zdCB7c3RhY2ssIHBvcywgc3RhY2tXZWlnaHR9ID0gd3JhcDtcbiAgICBpZiAoIXN0YWNrIHx8ICFTVEFUSUNfUE9TSVRJT05TLmluY2x1ZGVzKHBvcykpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBfc3RhY2sgPSBzdGFja3Nbc3RhY2tdIHx8IChzdGFja3Nbc3RhY2tdID0ge2NvdW50OiAwLCBwbGFjZWQ6IDAsIHdlaWdodDogMCwgc2l6ZTogMH0pO1xuICAgIF9zdGFjay5jb3VudCsrO1xuICAgIF9zdGFjay53ZWlnaHQgKz0gc3RhY2tXZWlnaHQ7XG4gIH1cbiAgcmV0dXJuIHN0YWNrcztcbn1cbmZ1bmN0aW9uIHNldExheW91dERpbXMobGF5b3V0cywgcGFyYW1zKSB7XG4gIGNvbnN0IHN0YWNrcyA9IGJ1aWxkU3RhY2tzKGxheW91dHMpO1xuICBjb25zdCB7dkJveE1heFdpZHRoLCBoQm94TWF4SGVpZ2h0fSA9IHBhcmFtcztcbiAgbGV0IGksIGlsZW4sIGxheW91dDtcbiAgZm9yIChpID0gMCwgaWxlbiA9IGxheW91dHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgbGF5b3V0ID0gbGF5b3V0c1tpXTtcbiAgICBjb25zdCB7ZnVsbFNpemV9ID0gbGF5b3V0LmJveDtcbiAgICBjb25zdCBzdGFjayA9IHN0YWNrc1tsYXlvdXQuc3RhY2tdO1xuICAgIGNvbnN0IGZhY3RvciA9IHN0YWNrICYmIGxheW91dC5zdGFja1dlaWdodCAvIHN0YWNrLndlaWdodDtcbiAgICBpZiAobGF5b3V0Lmhvcml6b250YWwpIHtcbiAgICAgIGxheW91dC53aWR0aCA9IGZhY3RvciA/IGZhY3RvciAqIHZCb3hNYXhXaWR0aCA6IGZ1bGxTaXplICYmIHBhcmFtcy5hdmFpbGFibGVXaWR0aDtcbiAgICAgIGxheW91dC5oZWlnaHQgPSBoQm94TWF4SGVpZ2h0O1xuICAgIH0gZWxzZSB7XG4gICAgICBsYXlvdXQud2lkdGggPSB2Qm94TWF4V2lkdGg7XG4gICAgICBsYXlvdXQuaGVpZ2h0ID0gZmFjdG9yID8gZmFjdG9yICogaEJveE1heEhlaWdodCA6IGZ1bGxTaXplICYmIHBhcmFtcy5hdmFpbGFibGVIZWlnaHQ7XG4gICAgfVxuICB9XG4gIHJldHVybiBzdGFja3M7XG59XG5mdW5jdGlvbiBidWlsZExheW91dEJveGVzKGJveGVzKSB7XG4gIGNvbnN0IGxheW91dEJveGVzID0gd3JhcEJveGVzKGJveGVzKTtcbiAgY29uc3QgZnVsbFNpemUgPSBzb3J0QnlXZWlnaHQobGF5b3V0Qm94ZXMuZmlsdGVyKHdyYXAgPT4gd3JhcC5ib3guZnVsbFNpemUpLCB0cnVlKTtcbiAgY29uc3QgbGVmdCA9IHNvcnRCeVdlaWdodChmaWx0ZXJCeVBvc2l0aW9uKGxheW91dEJveGVzLCAnbGVmdCcpLCB0cnVlKTtcbiAgY29uc3QgcmlnaHQgPSBzb3J0QnlXZWlnaHQoZmlsdGVyQnlQb3NpdGlvbihsYXlvdXRCb3hlcywgJ3JpZ2h0JykpO1xuICBjb25zdCB0b3AgPSBzb3J0QnlXZWlnaHQoZmlsdGVyQnlQb3NpdGlvbihsYXlvdXRCb3hlcywgJ3RvcCcpLCB0cnVlKTtcbiAgY29uc3QgYm90dG9tID0gc29ydEJ5V2VpZ2h0KGZpbHRlckJ5UG9zaXRpb24obGF5b3V0Qm94ZXMsICdib3R0b20nKSk7XG4gIGNvbnN0IGNlbnRlckhvcml6b250YWwgPSBmaWx0ZXJEeW5hbWljUG9zaXRpb25CeUF4aXMobGF5b3V0Qm94ZXMsICd4Jyk7XG4gIGNvbnN0IGNlbnRlclZlcnRpY2FsID0gZmlsdGVyRHluYW1pY1Bvc2l0aW9uQnlBeGlzKGxheW91dEJveGVzLCAneScpO1xuICByZXR1cm4ge1xuICAgIGZ1bGxTaXplLFxuICAgIGxlZnRBbmRUb3A6IGxlZnQuY29uY2F0KHRvcCksXG4gICAgcmlnaHRBbmRCb3R0b206IHJpZ2h0LmNvbmNhdChjZW50ZXJWZXJ0aWNhbCkuY29uY2F0KGJvdHRvbSkuY29uY2F0KGNlbnRlckhvcml6b250YWwpLFxuICAgIGNoYXJ0QXJlYTogZmlsdGVyQnlQb3NpdGlvbihsYXlvdXRCb3hlcywgJ2NoYXJ0QXJlYScpLFxuICAgIHZlcnRpY2FsOiBsZWZ0LmNvbmNhdChyaWdodCkuY29uY2F0KGNlbnRlclZlcnRpY2FsKSxcbiAgICBob3Jpem9udGFsOiB0b3AuY29uY2F0KGJvdHRvbSkuY29uY2F0KGNlbnRlckhvcml6b250YWwpXG4gIH07XG59XG5mdW5jdGlvbiBnZXRDb21iaW5lZE1heChtYXhQYWRkaW5nLCBjaGFydEFyZWEsIGEsIGIpIHtcbiAgcmV0dXJuIE1hdGgubWF4KG1heFBhZGRpbmdbYV0sIGNoYXJ0QXJlYVthXSkgKyBNYXRoLm1heChtYXhQYWRkaW5nW2JdLCBjaGFydEFyZWFbYl0pO1xufVxuZnVuY3Rpb24gdXBkYXRlTWF4UGFkZGluZyhtYXhQYWRkaW5nLCBib3hQYWRkaW5nKSB7XG4gIG1heFBhZGRpbmcudG9wID0gTWF0aC5tYXgobWF4UGFkZGluZy50b3AsIGJveFBhZGRpbmcudG9wKTtcbiAgbWF4UGFkZGluZy5sZWZ0ID0gTWF0aC5tYXgobWF4UGFkZGluZy5sZWZ0LCBib3hQYWRkaW5nLmxlZnQpO1xuICBtYXhQYWRkaW5nLmJvdHRvbSA9IE1hdGgubWF4KG1heFBhZGRpbmcuYm90dG9tLCBib3hQYWRkaW5nLmJvdHRvbSk7XG4gIG1heFBhZGRpbmcucmlnaHQgPSBNYXRoLm1heChtYXhQYWRkaW5nLnJpZ2h0LCBib3hQYWRkaW5nLnJpZ2h0KTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZURpbXMoY2hhcnRBcmVhLCBwYXJhbXMsIGxheW91dCwgc3RhY2tzKSB7XG4gIGNvbnN0IHtwb3MsIGJveH0gPSBsYXlvdXQ7XG4gIGNvbnN0IG1heFBhZGRpbmcgPSBjaGFydEFyZWEubWF4UGFkZGluZztcbiAgaWYgKCFpc09iamVjdChwb3MpKSB7XG4gICAgaWYgKGxheW91dC5zaXplKSB7XG4gICAgICBjaGFydEFyZWFbcG9zXSAtPSBsYXlvdXQuc2l6ZTtcbiAgICB9XG4gICAgY29uc3Qgc3RhY2sgPSBzdGFja3NbbGF5b3V0LnN0YWNrXSB8fCB7c2l6ZTogMCwgY291bnQ6IDF9O1xuICAgIHN0YWNrLnNpemUgPSBNYXRoLm1heChzdGFjay5zaXplLCBsYXlvdXQuaG9yaXpvbnRhbCA/IGJveC5oZWlnaHQgOiBib3gud2lkdGgpO1xuICAgIGxheW91dC5zaXplID0gc3RhY2suc2l6ZSAvIHN0YWNrLmNvdW50O1xuICAgIGNoYXJ0QXJlYVtwb3NdICs9IGxheW91dC5zaXplO1xuICB9XG4gIGlmIChib3guZ2V0UGFkZGluZykge1xuICAgIHVwZGF0ZU1heFBhZGRpbmcobWF4UGFkZGluZywgYm94LmdldFBhZGRpbmcoKSk7XG4gIH1cbiAgY29uc3QgbmV3V2lkdGggPSBNYXRoLm1heCgwLCBwYXJhbXMub3V0ZXJXaWR0aCAtIGdldENvbWJpbmVkTWF4KG1heFBhZGRpbmcsIGNoYXJ0QXJlYSwgJ2xlZnQnLCAncmlnaHQnKSk7XG4gIGNvbnN0IG5ld0hlaWdodCA9IE1hdGgubWF4KDAsIHBhcmFtcy5vdXRlckhlaWdodCAtIGdldENvbWJpbmVkTWF4KG1heFBhZGRpbmcsIGNoYXJ0QXJlYSwgJ3RvcCcsICdib3R0b20nKSk7XG4gIGNvbnN0IHdpZHRoQ2hhbmdlZCA9IG5ld1dpZHRoICE9PSBjaGFydEFyZWEudztcbiAgY29uc3QgaGVpZ2h0Q2hhbmdlZCA9IG5ld0hlaWdodCAhPT0gY2hhcnRBcmVhLmg7XG4gIGNoYXJ0QXJlYS53ID0gbmV3V2lkdGg7XG4gIGNoYXJ0QXJlYS5oID0gbmV3SGVpZ2h0O1xuICByZXR1cm4gbGF5b3V0Lmhvcml6b250YWxcbiAgICA/IHtzYW1lOiB3aWR0aENoYW5nZWQsIG90aGVyOiBoZWlnaHRDaGFuZ2VkfVxuICAgIDoge3NhbWU6IGhlaWdodENoYW5nZWQsIG90aGVyOiB3aWR0aENoYW5nZWR9O1xufVxuZnVuY3Rpb24gaGFuZGxlTWF4UGFkZGluZyhjaGFydEFyZWEpIHtcbiAgY29uc3QgbWF4UGFkZGluZyA9IGNoYXJ0QXJlYS5tYXhQYWRkaW5nO1xuICBmdW5jdGlvbiB1cGRhdGVQb3MocG9zKSB7XG4gICAgY29uc3QgY2hhbmdlID0gTWF0aC5tYXgobWF4UGFkZGluZ1twb3NdIC0gY2hhcnRBcmVhW3Bvc10sIDApO1xuICAgIGNoYXJ0QXJlYVtwb3NdICs9IGNoYW5nZTtcbiAgICByZXR1cm4gY2hhbmdlO1xuICB9XG4gIGNoYXJ0QXJlYS55ICs9IHVwZGF0ZVBvcygndG9wJyk7XG4gIGNoYXJ0QXJlYS54ICs9IHVwZGF0ZVBvcygnbGVmdCcpO1xuICB1cGRhdGVQb3MoJ3JpZ2h0Jyk7XG4gIHVwZGF0ZVBvcygnYm90dG9tJyk7XG59XG5mdW5jdGlvbiBnZXRNYXJnaW5zKGhvcml6b250YWwsIGNoYXJ0QXJlYSkge1xuICBjb25zdCBtYXhQYWRkaW5nID0gY2hhcnRBcmVhLm1heFBhZGRpbmc7XG4gIGZ1bmN0aW9uIG1hcmdpbkZvclBvc2l0aW9ucyhwb3NpdGlvbnMpIHtcbiAgICBjb25zdCBtYXJnaW4gPSB7bGVmdDogMCwgdG9wOiAwLCByaWdodDogMCwgYm90dG9tOiAwfTtcbiAgICBwb3NpdGlvbnMuZm9yRWFjaCgocG9zKSA9PiB7XG4gICAgICBtYXJnaW5bcG9zXSA9IE1hdGgubWF4KGNoYXJ0QXJlYVtwb3NdLCBtYXhQYWRkaW5nW3Bvc10pO1xuICAgIH0pO1xuICAgIHJldHVybiBtYXJnaW47XG4gIH1cbiAgcmV0dXJuIGhvcml6b250YWxcbiAgICA/IG1hcmdpbkZvclBvc2l0aW9ucyhbJ2xlZnQnLCAncmlnaHQnXSlcbiAgICA6IG1hcmdpbkZvclBvc2l0aW9ucyhbJ3RvcCcsICdib3R0b20nXSk7XG59XG5mdW5jdGlvbiBmaXRCb3hlcyhib3hlcywgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcykge1xuICBjb25zdCByZWZpdEJveGVzID0gW107XG4gIGxldCBpLCBpbGVuLCBsYXlvdXQsIGJveCwgcmVmaXQsIGNoYW5nZWQ7XG4gIGZvciAoaSA9IDAsIGlsZW4gPSBib3hlcy5sZW5ndGgsIHJlZml0ID0gMDsgaSA8IGlsZW47ICsraSkge1xuICAgIGxheW91dCA9IGJveGVzW2ldO1xuICAgIGJveCA9IGxheW91dC5ib3g7XG4gICAgYm94LnVwZGF0ZShcbiAgICAgIGxheW91dC53aWR0aCB8fCBjaGFydEFyZWEudyxcbiAgICAgIGxheW91dC5oZWlnaHQgfHwgY2hhcnRBcmVhLmgsXG4gICAgICBnZXRNYXJnaW5zKGxheW91dC5ob3Jpem9udGFsLCBjaGFydEFyZWEpXG4gICAgKTtcbiAgICBjb25zdCB7c2FtZSwgb3RoZXJ9ID0gdXBkYXRlRGltcyhjaGFydEFyZWEsIHBhcmFtcywgbGF5b3V0LCBzdGFja3MpO1xuICAgIHJlZml0IHw9IHNhbWUgJiYgcmVmaXRCb3hlcy5sZW5ndGg7XG4gICAgY2hhbmdlZCA9IGNoYW5nZWQgfHwgb3RoZXI7XG4gICAgaWYgKCFib3guZnVsbFNpemUpIHtcbiAgICAgIHJlZml0Qm94ZXMucHVzaChsYXlvdXQpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVmaXQgJiYgZml0Qm94ZXMocmVmaXRCb3hlcywgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcykgfHwgY2hhbmdlZDtcbn1cbmZ1bmN0aW9uIHNldEJveERpbXMoYm94LCBsZWZ0LCB0b3AsIHdpZHRoLCBoZWlnaHQpIHtcbiAgYm94LnRvcCA9IHRvcDtcbiAgYm94LmxlZnQgPSBsZWZ0O1xuICBib3gucmlnaHQgPSBsZWZ0ICsgd2lkdGg7XG4gIGJveC5ib3R0b20gPSB0b3AgKyBoZWlnaHQ7XG4gIGJveC53aWR0aCA9IHdpZHRoO1xuICBib3guaGVpZ2h0ID0gaGVpZ2h0O1xufVxuZnVuY3Rpb24gcGxhY2VCb3hlcyhib3hlcywgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcykge1xuICBjb25zdCB1c2VyUGFkZGluZyA9IHBhcmFtcy5wYWRkaW5nO1xuICBsZXQge3gsIHl9ID0gY2hhcnRBcmVhO1xuICBmb3IgKGNvbnN0IGxheW91dCBvZiBib3hlcykge1xuICAgIGNvbnN0IGJveCA9IGxheW91dC5ib3g7XG4gICAgY29uc3Qgc3RhY2sgPSBzdGFja3NbbGF5b3V0LnN0YWNrXSB8fCB7Y291bnQ6IDEsIHBsYWNlZDogMCwgd2VpZ2h0OiAxfTtcbiAgICBjb25zdCB3ZWlnaHQgPSAobGF5b3V0LnN0YWNrV2VpZ2h0IC8gc3RhY2sud2VpZ2h0KSB8fCAxO1xuICAgIGlmIChsYXlvdXQuaG9yaXpvbnRhbCkge1xuICAgICAgY29uc3Qgd2lkdGggPSBjaGFydEFyZWEudyAqIHdlaWdodDtcbiAgICAgIGNvbnN0IGhlaWdodCA9IHN0YWNrLnNpemUgfHwgYm94LmhlaWdodDtcbiAgICAgIGlmIChkZWZpbmVkKHN0YWNrLnN0YXJ0KSkge1xuICAgICAgICB5ID0gc3RhY2suc3RhcnQ7XG4gICAgICB9XG4gICAgICBpZiAoYm94LmZ1bGxTaXplKSB7XG4gICAgICAgIHNldEJveERpbXMoYm94LCB1c2VyUGFkZGluZy5sZWZ0LCB5LCBwYXJhbXMub3V0ZXJXaWR0aCAtIHVzZXJQYWRkaW5nLnJpZ2h0IC0gdXNlclBhZGRpbmcubGVmdCwgaGVpZ2h0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNldEJveERpbXMoYm94LCBjaGFydEFyZWEubGVmdCArIHN0YWNrLnBsYWNlZCwgeSwgd2lkdGgsIGhlaWdodCk7XG4gICAgICB9XG4gICAgICBzdGFjay5zdGFydCA9IHk7XG4gICAgICBzdGFjay5wbGFjZWQgKz0gd2lkdGg7XG4gICAgICB5ID0gYm94LmJvdHRvbTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgaGVpZ2h0ID0gY2hhcnRBcmVhLmggKiB3ZWlnaHQ7XG4gICAgICBjb25zdCB3aWR0aCA9IHN0YWNrLnNpemUgfHwgYm94LndpZHRoO1xuICAgICAgaWYgKGRlZmluZWQoc3RhY2suc3RhcnQpKSB7XG4gICAgICAgIHggPSBzdGFjay5zdGFydDtcbiAgICAgIH1cbiAgICAgIGlmIChib3guZnVsbFNpemUpIHtcbiAgICAgICAgc2V0Qm94RGltcyhib3gsIHgsIHVzZXJQYWRkaW5nLnRvcCwgd2lkdGgsIHBhcmFtcy5vdXRlckhlaWdodCAtIHVzZXJQYWRkaW5nLmJvdHRvbSAtIHVzZXJQYWRkaW5nLnRvcCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXRCb3hEaW1zKGJveCwgeCwgY2hhcnRBcmVhLnRvcCArIHN0YWNrLnBsYWNlZCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICB9XG4gICAgICBzdGFjay5zdGFydCA9IHg7XG4gICAgICBzdGFjay5wbGFjZWQgKz0gaGVpZ2h0O1xuICAgICAgeCA9IGJveC5yaWdodDtcbiAgICB9XG4gIH1cbiAgY2hhcnRBcmVhLnggPSB4O1xuICBjaGFydEFyZWEueSA9IHk7XG59XG5kZWZhdWx0cy5zZXQoJ2xheW91dCcsIHtcbiAgcGFkZGluZzoge1xuICAgIHRvcDogMCxcbiAgICByaWdodDogMCxcbiAgICBib3R0b206IDAsXG4gICAgbGVmdDogMFxuICB9XG59KTtcbnZhciBsYXlvdXRzID0ge1xuICBhZGRCb3goY2hhcnQsIGl0ZW0pIHtcbiAgICBpZiAoIWNoYXJ0LmJveGVzKSB7XG4gICAgICBjaGFydC5ib3hlcyA9IFtdO1xuICAgIH1cbiAgICBpdGVtLmZ1bGxTaXplID0gaXRlbS5mdWxsU2l6ZSB8fCBmYWxzZTtcbiAgICBpdGVtLnBvc2l0aW9uID0gaXRlbS5wb3NpdGlvbiB8fCAndG9wJztcbiAgICBpdGVtLndlaWdodCA9IGl0ZW0ud2VpZ2h0IHx8IDA7XG4gICAgaXRlbS5fbGF5ZXJzID0gaXRlbS5fbGF5ZXJzIHx8IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIFt7XG4gICAgICAgIHo6IDAsXG4gICAgICAgIGRyYXcoY2hhcnRBcmVhKSB7XG4gICAgICAgICAgaXRlbS5kcmF3KGNoYXJ0QXJlYSk7XG4gICAgICAgIH1cbiAgICAgIH1dO1xuICAgIH07XG4gICAgY2hhcnQuYm94ZXMucHVzaChpdGVtKTtcbiAgfSxcbiAgcmVtb3ZlQm94KGNoYXJ0LCBsYXlvdXRJdGVtKSB7XG4gICAgY29uc3QgaW5kZXggPSBjaGFydC5ib3hlcyA/IGNoYXJ0LmJveGVzLmluZGV4T2YobGF5b3V0SXRlbSkgOiAtMTtcbiAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICBjaGFydC5ib3hlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH1cbiAgfSxcbiAgY29uZmlndXJlKGNoYXJ0LCBpdGVtLCBvcHRpb25zKSB7XG4gICAgaXRlbS5mdWxsU2l6ZSA9IG9wdGlvbnMuZnVsbFNpemU7XG4gICAgaXRlbS5wb3NpdGlvbiA9IG9wdGlvbnMucG9zaXRpb247XG4gICAgaXRlbS53ZWlnaHQgPSBvcHRpb25zLndlaWdodDtcbiAgfSxcbiAgdXBkYXRlKGNoYXJ0LCB3aWR0aCwgaGVpZ2h0LCBtaW5QYWRkaW5nKSB7XG4gICAgaWYgKCFjaGFydCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBwYWRkaW5nID0gdG9QYWRkaW5nKGNoYXJ0Lm9wdGlvbnMubGF5b3V0LnBhZGRpbmcpO1xuICAgIGNvbnN0IGF2YWlsYWJsZVdpZHRoID0gTWF0aC5tYXgod2lkdGggLSBwYWRkaW5nLndpZHRoLCAwKTtcbiAgICBjb25zdCBhdmFpbGFibGVIZWlnaHQgPSBNYXRoLm1heChoZWlnaHQgLSBwYWRkaW5nLmhlaWdodCwgMCk7XG4gICAgY29uc3QgYm94ZXMgPSBidWlsZExheW91dEJveGVzKGNoYXJ0LmJveGVzKTtcbiAgICBjb25zdCB2ZXJ0aWNhbEJveGVzID0gYm94ZXMudmVydGljYWw7XG4gICAgY29uc3QgaG9yaXpvbnRhbEJveGVzID0gYm94ZXMuaG9yaXpvbnRhbDtcbiAgICBlYWNoKGNoYXJ0LmJveGVzLCBib3ggPT4ge1xuICAgICAgaWYgKHR5cGVvZiBib3guYmVmb3JlTGF5b3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGJveC5iZWZvcmVMYXlvdXQoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjb25zdCB2aXNpYmxlVmVydGljYWxCb3hDb3VudCA9IHZlcnRpY2FsQm94ZXMucmVkdWNlKCh0b3RhbCwgd3JhcCkgPT5cbiAgICAgIHdyYXAuYm94Lm9wdGlvbnMgJiYgd3JhcC5ib3gub3B0aW9ucy5kaXNwbGF5ID09PSBmYWxzZSA/IHRvdGFsIDogdG90YWwgKyAxLCAwKSB8fCAxO1xuICAgIGNvbnN0IHBhcmFtcyA9IE9iamVjdC5mcmVlemUoe1xuICAgICAgb3V0ZXJXaWR0aDogd2lkdGgsXG4gICAgICBvdXRlckhlaWdodDogaGVpZ2h0LFxuICAgICAgcGFkZGluZyxcbiAgICAgIGF2YWlsYWJsZVdpZHRoLFxuICAgICAgYXZhaWxhYmxlSGVpZ2h0LFxuICAgICAgdkJveE1heFdpZHRoOiBhdmFpbGFibGVXaWR0aCAvIDIgLyB2aXNpYmxlVmVydGljYWxCb3hDb3VudCxcbiAgICAgIGhCb3hNYXhIZWlnaHQ6IGF2YWlsYWJsZUhlaWdodCAvIDJcbiAgICB9KTtcbiAgICBjb25zdCBtYXhQYWRkaW5nID0gT2JqZWN0LmFzc2lnbih7fSwgcGFkZGluZyk7XG4gICAgdXBkYXRlTWF4UGFkZGluZyhtYXhQYWRkaW5nLCB0b1BhZGRpbmcobWluUGFkZGluZykpO1xuICAgIGNvbnN0IGNoYXJ0QXJlYSA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgbWF4UGFkZGluZyxcbiAgICAgIHc6IGF2YWlsYWJsZVdpZHRoLFxuICAgICAgaDogYXZhaWxhYmxlSGVpZ2h0LFxuICAgICAgeDogcGFkZGluZy5sZWZ0LFxuICAgICAgeTogcGFkZGluZy50b3BcbiAgICB9LCBwYWRkaW5nKTtcbiAgICBjb25zdCBzdGFja3MgPSBzZXRMYXlvdXREaW1zKHZlcnRpY2FsQm94ZXMuY29uY2F0KGhvcml6b250YWxCb3hlcyksIHBhcmFtcyk7XG4gICAgZml0Qm94ZXMoYm94ZXMuZnVsbFNpemUsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgIGZpdEJveGVzKHZlcnRpY2FsQm94ZXMsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgIGlmIChmaXRCb3hlcyhob3Jpem9udGFsQm94ZXMsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpKSB7XG4gICAgICBmaXRCb3hlcyh2ZXJ0aWNhbEJveGVzLCBjaGFydEFyZWEsIHBhcmFtcywgc3RhY2tzKTtcbiAgICB9XG4gICAgaGFuZGxlTWF4UGFkZGluZyhjaGFydEFyZWEpO1xuICAgIHBsYWNlQm94ZXMoYm94ZXMubGVmdEFuZFRvcCwgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcyk7XG4gICAgY2hhcnRBcmVhLnggKz0gY2hhcnRBcmVhLnc7XG4gICAgY2hhcnRBcmVhLnkgKz0gY2hhcnRBcmVhLmg7XG4gICAgcGxhY2VCb3hlcyhib3hlcy5yaWdodEFuZEJvdHRvbSwgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcyk7XG4gICAgY2hhcnQuY2hhcnRBcmVhID0ge1xuICAgICAgbGVmdDogY2hhcnRBcmVhLmxlZnQsXG4gICAgICB0b3A6IGNoYXJ0QXJlYS50b3AsXG4gICAgICByaWdodDogY2hhcnRBcmVhLmxlZnQgKyBjaGFydEFyZWEudyxcbiAgICAgIGJvdHRvbTogY2hhcnRBcmVhLnRvcCArIGNoYXJ0QXJlYS5oLFxuICAgICAgaGVpZ2h0OiBjaGFydEFyZWEuaCxcbiAgICAgIHdpZHRoOiBjaGFydEFyZWEudyxcbiAgICB9O1xuICAgIGVhY2goYm94ZXMuY2hhcnRBcmVhLCAobGF5b3V0KSA9PiB7XG4gICAgICBjb25zdCBib3ggPSBsYXlvdXQuYm94O1xuICAgICAgT2JqZWN0LmFzc2lnbihib3gsIGNoYXJ0LmNoYXJ0QXJlYSk7XG4gICAgICBib3gudXBkYXRlKGNoYXJ0QXJlYS53LCBjaGFydEFyZWEuaCk7XG4gICAgfSk7XG4gIH1cbn07XG5cbmNsYXNzIEJhc2VQbGF0Zm9ybSB7XG4gIGFjcXVpcmVDb250ZXh0KGNhbnZhcywgYXNwZWN0UmF0aW8pIHt9XG4gIHJlbGVhc2VDb250ZXh0KGNvbnRleHQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgYWRkRXZlbnRMaXN0ZW5lcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHt9XG4gIHJlbW92ZUV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7fVxuICBnZXREZXZpY2VQaXhlbFJhdGlvKCkge1xuICAgIHJldHVybiAxO1xuICB9XG4gIGdldE1heGltdW1TaXplKGVsZW1lbnQsIHdpZHRoLCBoZWlnaHQsIGFzcGVjdFJhdGlvKSB7XG4gICAgd2lkdGggPSBNYXRoLm1heCgwLCB3aWR0aCB8fCBlbGVtZW50LndpZHRoKTtcbiAgICBoZWlnaHQgPSBoZWlnaHQgfHwgZWxlbWVudC5oZWlnaHQ7XG4gICAgcmV0dXJuIHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0OiBNYXRoLm1heCgwLCBhc3BlY3RSYXRpbyA/IE1hdGguZmxvb3Iod2lkdGggLyBhc3BlY3RSYXRpbykgOiBoZWlnaHQpXG4gICAgfTtcbiAgfVxuICBpc0F0dGFjaGVkKGNhbnZhcykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmNsYXNzIEJhc2ljUGxhdGZvcm0gZXh0ZW5kcyBCYXNlUGxhdGZvcm0ge1xuICBhY3F1aXJlQ29udGV4dChpdGVtKSB7XG4gICAgcmV0dXJuIGl0ZW0gJiYgaXRlbS5nZXRDb250ZXh0ICYmIGl0ZW0uZ2V0Q29udGV4dCgnMmQnKSB8fCBudWxsO1xuICB9XG59XG5cbmNvbnN0IEVYUEFORE9fS0VZID0gJyRjaGFydGpzJztcbmNvbnN0IEVWRU5UX1RZUEVTID0ge1xuICB0b3VjaHN0YXJ0OiAnbW91c2Vkb3duJyxcbiAgdG91Y2htb3ZlOiAnbW91c2Vtb3ZlJyxcbiAgdG91Y2hlbmQ6ICdtb3VzZXVwJyxcbiAgcG9pbnRlcmVudGVyOiAnbW91c2VlbnRlcicsXG4gIHBvaW50ZXJkb3duOiAnbW91c2Vkb3duJyxcbiAgcG9pbnRlcm1vdmU6ICdtb3VzZW1vdmUnLFxuICBwb2ludGVydXA6ICdtb3VzZXVwJyxcbiAgcG9pbnRlcmxlYXZlOiAnbW91c2VvdXQnLFxuICBwb2ludGVyb3V0OiAnbW91c2VvdXQnXG59O1xuY29uc3QgaXNOdWxsT3JFbXB0eSA9IHZhbHVlID0+IHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnJztcbmZ1bmN0aW9uIGluaXRDYW52YXMoY2FudmFzLCBhc3BlY3RSYXRpbykge1xuICBjb25zdCBzdHlsZSA9IGNhbnZhcy5zdHlsZTtcbiAgY29uc3QgcmVuZGVySGVpZ2h0ID0gY2FudmFzLmdldEF0dHJpYnV0ZSgnaGVpZ2h0Jyk7XG4gIGNvbnN0IHJlbmRlcldpZHRoID0gY2FudmFzLmdldEF0dHJpYnV0ZSgnd2lkdGgnKTtcbiAgY2FudmFzW0VYUEFORE9fS0VZXSA9IHtcbiAgICBpbml0aWFsOiB7XG4gICAgICBoZWlnaHQ6IHJlbmRlckhlaWdodCxcbiAgICAgIHdpZHRoOiByZW5kZXJXaWR0aCxcbiAgICAgIHN0eWxlOiB7XG4gICAgICAgIGRpc3BsYXk6IHN0eWxlLmRpc3BsYXksXG4gICAgICAgIGhlaWdodDogc3R5bGUuaGVpZ2h0LFxuICAgICAgICB3aWR0aDogc3R5bGUud2lkdGhcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIHN0eWxlLmRpc3BsYXkgPSBzdHlsZS5kaXNwbGF5IHx8ICdibG9jayc7XG4gIHN0eWxlLmJveFNpemluZyA9IHN0eWxlLmJveFNpemluZyB8fCAnYm9yZGVyLWJveCc7XG4gIGlmIChpc051bGxPckVtcHR5KHJlbmRlcldpZHRoKSkge1xuICAgIGNvbnN0IGRpc3BsYXlXaWR0aCA9IHJlYWRVc2VkU2l6ZShjYW52YXMsICd3aWR0aCcpO1xuICAgIGlmIChkaXNwbGF5V2lkdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2FudmFzLndpZHRoID0gZGlzcGxheVdpZHRoO1xuICAgIH1cbiAgfVxuICBpZiAoaXNOdWxsT3JFbXB0eShyZW5kZXJIZWlnaHQpKSB7XG4gICAgaWYgKGNhbnZhcy5zdHlsZS5oZWlnaHQgPT09ICcnKSB7XG4gICAgICBjYW52YXMuaGVpZ2h0ID0gY2FudmFzLndpZHRoIC8gKGFzcGVjdFJhdGlvIHx8IDIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBkaXNwbGF5SGVpZ2h0ID0gcmVhZFVzZWRTaXplKGNhbnZhcywgJ2hlaWdodCcpO1xuICAgICAgaWYgKGRpc3BsYXlIZWlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gZGlzcGxheUhlaWdodDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNhbnZhcztcbn1cbmNvbnN0IGV2ZW50TGlzdGVuZXJPcHRpb25zID0gc3VwcG9ydHNFdmVudExpc3RlbmVyT3B0aW9ucyA/IHtwYXNzaXZlOiB0cnVlfSA6IGZhbHNlO1xuZnVuY3Rpb24gYWRkTGlzdGVuZXIobm9kZSwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgbm9kZS5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBldmVudExpc3RlbmVyT3B0aW9ucyk7XG59XG5mdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgY2hhcnQuY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIsIGV2ZW50TGlzdGVuZXJPcHRpb25zKTtcbn1cbmZ1bmN0aW9uIGZyb21OYXRpdmVFdmVudChldmVudCwgY2hhcnQpIHtcbiAgY29uc3QgdHlwZSA9IEVWRU5UX1RZUEVTW2V2ZW50LnR5cGVdIHx8IGV2ZW50LnR5cGU7XG4gIGNvbnN0IHt4LCB5fSA9IGdldFJlbGF0aXZlUG9zaXRpb24kMShldmVudCwgY2hhcnQpO1xuICByZXR1cm4ge1xuICAgIHR5cGUsXG4gICAgY2hhcnQsXG4gICAgbmF0aXZlOiBldmVudCxcbiAgICB4OiB4ICE9PSB1bmRlZmluZWQgPyB4IDogbnVsbCxcbiAgICB5OiB5ICE9PSB1bmRlZmluZWQgPyB5IDogbnVsbCxcbiAgfTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZUF0dGFjaE9ic2VydmVyKGNoYXJ0LCB0eXBlLCBsaXN0ZW5lcikge1xuICBjb25zdCBjYW52YXMgPSBjaGFydC5jYW52YXM7XG4gIGNvbnN0IGNvbnRhaW5lciA9IGNhbnZhcyAmJiBfZ2V0UGFyZW50Tm9kZShjYW52YXMpO1xuICBjb25zdCBlbGVtZW50ID0gY29udGFpbmVyIHx8IGNhbnZhcztcbiAgY29uc3Qgb2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcihlbnRyaWVzID0+IHtcbiAgICBjb25zdCBwYXJlbnQgPSBfZ2V0UGFyZW50Tm9kZShlbGVtZW50KTtcbiAgICBlbnRyaWVzLmZvckVhY2goZW50cnkgPT4ge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbnRyeS5hZGRlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGFkZGVkID0gZW50cnkuYWRkZWROb2Rlc1tpXTtcbiAgICAgICAgaWYgKGFkZGVkID09PSBlbGVtZW50IHx8IGFkZGVkID09PSBwYXJlbnQpIHtcbiAgICAgICAgICBsaXN0ZW5lcihlbnRyeS50YXJnZXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICBvYnNlcnZlci5vYnNlcnZlKGRvY3VtZW50LCB7Y2hpbGRMaXN0OiB0cnVlLCBzdWJ0cmVlOiB0cnVlfSk7XG4gIHJldHVybiBvYnNlcnZlcjtcbn1cbmZ1bmN0aW9uIGNyZWF0ZURldGFjaE9ic2VydmVyKGNoYXJ0LCB0eXBlLCBsaXN0ZW5lcikge1xuICBjb25zdCBjYW52YXMgPSBjaGFydC5jYW52YXM7XG4gIGNvbnN0IGNvbnRhaW5lciA9IGNhbnZhcyAmJiBfZ2V0UGFyZW50Tm9kZShjYW52YXMpO1xuICBpZiAoIWNvbnRhaW5lcikge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKGVudHJpZXMgPT4ge1xuICAgIGVudHJpZXMuZm9yRWFjaChlbnRyeSA9PiB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVudHJ5LnJlbW92ZWROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoZW50cnkucmVtb3ZlZE5vZGVzW2ldID09PSBjYW52YXMpIHtcbiAgICAgICAgICBsaXN0ZW5lcigpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICBvYnNlcnZlci5vYnNlcnZlKGNvbnRhaW5lciwge2NoaWxkTGlzdDogdHJ1ZX0pO1xuICByZXR1cm4gb2JzZXJ2ZXI7XG59XG5jb25zdCBkcnBMaXN0ZW5pbmdDaGFydHMgPSBuZXcgTWFwKCk7XG5sZXQgb2xkRGV2aWNlUGl4ZWxSYXRpbyA9IDA7XG5mdW5jdGlvbiBvbldpbmRvd1Jlc2l6ZSgpIHtcbiAgY29uc3QgZHByID0gd2luZG93LmRldmljZVBpeGVsUmF0aW87XG4gIGlmIChkcHIgPT09IG9sZERldmljZVBpeGVsUmF0aW8pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgb2xkRGV2aWNlUGl4ZWxSYXRpbyA9IGRwcjtcbiAgZHJwTGlzdGVuaW5nQ2hhcnRzLmZvckVhY2goKHJlc2l6ZSwgY2hhcnQpID0+IHtcbiAgICBpZiAoY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW8gIT09IGRwcikge1xuICAgICAgcmVzaXplKCk7XG4gICAgfVxuICB9KTtcbn1cbmZ1bmN0aW9uIGxpc3RlbkRldmljZVBpeGVsUmF0aW9DaGFuZ2VzKGNoYXJ0LCByZXNpemUpIHtcbiAgaWYgKCFkcnBMaXN0ZW5pbmdDaGFydHMuc2l6ZSkge1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCBvbldpbmRvd1Jlc2l6ZSk7XG4gIH1cbiAgZHJwTGlzdGVuaW5nQ2hhcnRzLnNldChjaGFydCwgcmVzaXplKTtcbn1cbmZ1bmN0aW9uIHVubGlzdGVuRGV2aWNlUGl4ZWxSYXRpb0NoYW5nZXMoY2hhcnQpIHtcbiAgZHJwTGlzdGVuaW5nQ2hhcnRzLmRlbGV0ZShjaGFydCk7XG4gIGlmICghZHJwTGlzdGVuaW5nQ2hhcnRzLnNpemUpIHtcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgb25XaW5kb3dSZXNpemUpO1xuICB9XG59XG5mdW5jdGlvbiBjcmVhdGVSZXNpemVPYnNlcnZlcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgY29uc3QgY2FudmFzID0gY2hhcnQuY2FudmFzO1xuICBjb25zdCBjb250YWluZXIgPSBjYW52YXMgJiYgX2dldFBhcmVudE5vZGUoY2FudmFzKTtcbiAgaWYgKCFjb250YWluZXIpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgcmVzaXplID0gdGhyb3R0bGVkKCh3aWR0aCwgaGVpZ2h0KSA9PiB7XG4gICAgY29uc3QgdyA9IGNvbnRhaW5lci5jbGllbnRXaWR0aDtcbiAgICBsaXN0ZW5lcih3aWR0aCwgaGVpZ2h0KTtcbiAgICBpZiAodyA8IGNvbnRhaW5lci5jbGllbnRXaWR0aCkge1xuICAgICAgbGlzdGVuZXIoKTtcbiAgICB9XG4gIH0sIHdpbmRvdyk7XG4gIGNvbnN0IG9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKGVudHJpZXMgPT4ge1xuICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1swXTtcbiAgICBjb25zdCB3aWR0aCA9IGVudHJ5LmNvbnRlbnRSZWN0LndpZHRoO1xuICAgIGNvbnN0IGhlaWdodCA9IGVudHJ5LmNvbnRlbnRSZWN0LmhlaWdodDtcbiAgICBpZiAod2lkdGggPT09IDAgJiYgaGVpZ2h0ID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJlc2l6ZSh3aWR0aCwgaGVpZ2h0KTtcbiAgfSk7XG4gIG9ic2VydmVyLm9ic2VydmUoY29udGFpbmVyKTtcbiAgbGlzdGVuRGV2aWNlUGl4ZWxSYXRpb0NoYW5nZXMoY2hhcnQsIHJlc2l6ZSk7XG4gIHJldHVybiBvYnNlcnZlcjtcbn1cbmZ1bmN0aW9uIHJlbGVhc2VPYnNlcnZlcihjaGFydCwgdHlwZSwgb2JzZXJ2ZXIpIHtcbiAgaWYgKG9ic2VydmVyKSB7XG4gICAgb2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICB9XG4gIGlmICh0eXBlID09PSAncmVzaXplJykge1xuICAgIHVubGlzdGVuRGV2aWNlUGl4ZWxSYXRpb0NoYW5nZXMoY2hhcnQpO1xuICB9XG59XG5mdW5jdGlvbiBjcmVhdGVQcm94eUFuZExpc3RlbihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgY29uc3QgY2FudmFzID0gY2hhcnQuY2FudmFzO1xuICBjb25zdCBwcm94eSA9IHRocm90dGxlZCgoZXZlbnQpID0+IHtcbiAgICBpZiAoY2hhcnQuY3R4ICE9PSBudWxsKSB7XG4gICAgICBsaXN0ZW5lcihmcm9tTmF0aXZlRXZlbnQoZXZlbnQsIGNoYXJ0KSk7XG4gICAgfVxuICB9LCBjaGFydCwgKGFyZ3MpID0+IHtcbiAgICBjb25zdCBldmVudCA9IGFyZ3NbMF07XG4gICAgcmV0dXJuIFtldmVudCwgZXZlbnQub2Zmc2V0WCwgZXZlbnQub2Zmc2V0WV07XG4gIH0pO1xuICBhZGRMaXN0ZW5lcihjYW52YXMsIHR5cGUsIHByb3h5KTtcbiAgcmV0dXJuIHByb3h5O1xufVxuY2xhc3MgRG9tUGxhdGZvcm0gZXh0ZW5kcyBCYXNlUGxhdGZvcm0ge1xuICBhY3F1aXJlQ29udGV4dChjYW52YXMsIGFzcGVjdFJhdGlvKSB7XG4gICAgY29uc3QgY29udGV4dCA9IGNhbnZhcyAmJiBjYW52YXMuZ2V0Q29udGV4dCAmJiBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBpZiAoY29udGV4dCAmJiBjb250ZXh0LmNhbnZhcyA9PT0gY2FudmFzKSB7XG4gICAgICBpbml0Q2FudmFzKGNhbnZhcywgYXNwZWN0UmF0aW8pO1xuICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJlbGVhc2VDb250ZXh0KGNvbnRleHQpIHtcbiAgICBjb25zdCBjYW52YXMgPSBjb250ZXh0LmNhbnZhcztcbiAgICBpZiAoIWNhbnZhc1tFWFBBTkRPX0tFWV0pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgaW5pdGlhbCA9IGNhbnZhc1tFWFBBTkRPX0tFWV0uaW5pdGlhbDtcbiAgICBbJ2hlaWdodCcsICd3aWR0aCddLmZvckVhY2goKHByb3ApID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gaW5pdGlhbFtwcm9wXTtcbiAgICAgIGlmIChpc051bGxPclVuZGVmKHZhbHVlKSkge1xuICAgICAgICBjYW52YXMucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FudmFzLnNldEF0dHJpYnV0ZShwcm9wLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29uc3Qgc3R5bGUgPSBpbml0aWFsLnN0eWxlIHx8IHt9O1xuICAgIE9iamVjdC5rZXlzKHN0eWxlKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgIGNhbnZhcy5zdHlsZVtrZXldID0gc3R5bGVba2V5XTtcbiAgICB9KTtcbiAgICBjYW52YXMud2lkdGggPSBjYW52YXMud2lkdGg7XG4gICAgZGVsZXRlIGNhbnZhc1tFWFBBTkRPX0tFWV07XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgYWRkRXZlbnRMaXN0ZW5lcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUpO1xuICAgIGNvbnN0IHByb3hpZXMgPSBjaGFydC4kcHJveGllcyB8fCAoY2hhcnQuJHByb3hpZXMgPSB7fSk7XG4gICAgY29uc3QgaGFuZGxlcnMgPSB7XG4gICAgICBhdHRhY2g6IGNyZWF0ZUF0dGFjaE9ic2VydmVyLFxuICAgICAgZGV0YWNoOiBjcmVhdGVEZXRhY2hPYnNlcnZlcixcbiAgICAgIHJlc2l6ZTogY3JlYXRlUmVzaXplT2JzZXJ2ZXJcbiAgICB9O1xuICAgIGNvbnN0IGhhbmRsZXIgPSBoYW5kbGVyc1t0eXBlXSB8fCBjcmVhdGVQcm94eUFuZExpc3RlbjtcbiAgICBwcm94aWVzW3R5cGVdID0gaGFuZGxlcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpO1xuICB9XG4gIHJlbW92ZUV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUpIHtcbiAgICBjb25zdCBwcm94aWVzID0gY2hhcnQuJHByb3hpZXMgfHwgKGNoYXJ0LiRwcm94aWVzID0ge30pO1xuICAgIGNvbnN0IHByb3h5ID0gcHJveGllc1t0eXBlXTtcbiAgICBpZiAoIXByb3h5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGhhbmRsZXJzID0ge1xuICAgICAgYXR0YWNoOiByZWxlYXNlT2JzZXJ2ZXIsXG4gICAgICBkZXRhY2g6IHJlbGVhc2VPYnNlcnZlcixcbiAgICAgIHJlc2l6ZTogcmVsZWFzZU9ic2VydmVyXG4gICAgfTtcbiAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlcnNbdHlwZV0gfHwgcmVtb3ZlTGlzdGVuZXI7XG4gICAgaGFuZGxlcihjaGFydCwgdHlwZSwgcHJveHkpO1xuICAgIHByb3hpZXNbdHlwZV0gPSB1bmRlZmluZWQ7XG4gIH1cbiAgZ2V0RGV2aWNlUGl4ZWxSYXRpbygpIHtcbiAgICByZXR1cm4gd2luZG93LmRldmljZVBpeGVsUmF0aW87XG4gIH1cbiAgZ2V0TWF4aW11bVNpemUoY2FudmFzLCB3aWR0aCwgaGVpZ2h0LCBhc3BlY3RSYXRpbykge1xuICAgIHJldHVybiBnZXRNYXhpbXVtU2l6ZShjYW52YXMsIHdpZHRoLCBoZWlnaHQsIGFzcGVjdFJhdGlvKTtcbiAgfVxuICBpc0F0dGFjaGVkKGNhbnZhcykge1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IF9nZXRQYXJlbnROb2RlKGNhbnZhcyk7XG4gICAgcmV0dXJuICEhKGNvbnRhaW5lciAmJiBjb250YWluZXIuaXNDb25uZWN0ZWQpO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9kZXRlY3RQbGF0Zm9ybShjYW52YXMpIHtcbiAgaWYgKCFfaXNEb21TdXBwb3J0ZWQoKSB8fCAodHlwZW9mIE9mZnNjcmVlbkNhbnZhcyAhPT0gJ3VuZGVmaW5lZCcgJiYgY2FudmFzIGluc3RhbmNlb2YgT2Zmc2NyZWVuQ2FudmFzKSkge1xuICAgIHJldHVybiBCYXNpY1BsYXRmb3JtO1xuICB9XG4gIHJldHVybiBEb21QbGF0Zm9ybTtcbn1cblxuY2xhc3MgRWxlbWVudCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMueCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnkgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5hY3RpdmUgPSBmYWxzZTtcbiAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy4kYW5pbWF0aW9ucyA9IHVuZGVmaW5lZDtcbiAgfVxuICB0b29sdGlwUG9zaXRpb24odXNlRmluYWxQb3NpdGlvbikge1xuICAgIGNvbnN0IHt4LCB5fSA9IHRoaXMuZ2V0UHJvcHMoWyd4JywgJ3knXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgcmV0dXJuIHt4LCB5fTtcbiAgfVxuICBoYXNWYWx1ZSgpIHtcbiAgICByZXR1cm4gaXNOdW1iZXIodGhpcy54KSAmJiBpc051bWJlcih0aGlzLnkpO1xuICB9XG4gIGdldFByb3BzKHByb3BzLCBmaW5hbCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBhbmltcyA9IHRoaXMuJGFuaW1hdGlvbnM7XG4gICAgaWYgKCFmaW5hbCB8fCAhYW5pbXMpIHtcbiAgICAgIHJldHVybiBtZTtcbiAgICB9XG4gICAgY29uc3QgcmV0ID0ge307XG4gICAgcHJvcHMuZm9yRWFjaChwcm9wID0+IHtcbiAgICAgIHJldFtwcm9wXSA9IGFuaW1zW3Byb3BdICYmIGFuaW1zW3Byb3BdLmFjdGl2ZSgpID8gYW5pbXNbcHJvcF0uX3RvIDogbWVbcHJvcF07XG4gICAgfSk7XG4gICAgcmV0dXJuIHJldDtcbiAgfVxufVxuRWxlbWVudC5kZWZhdWx0cyA9IHt9O1xuRWxlbWVudC5kZWZhdWx0Um91dGVzID0gdW5kZWZpbmVkO1xuXG5jb25zdCBmb3JtYXR0ZXJzID0ge1xuICB2YWx1ZXModmFsdWUpIHtcbiAgICByZXR1cm4gaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6ICcnICsgdmFsdWU7XG4gIH0sXG4gIG51bWVyaWModGlja1ZhbHVlLCBpbmRleCwgdGlja3MpIHtcbiAgICBpZiAodGlja1ZhbHVlID09PSAwKSB7XG4gICAgICByZXR1cm4gJzAnO1xuICAgIH1cbiAgICBjb25zdCBsb2NhbGUgPSB0aGlzLmNoYXJ0Lm9wdGlvbnMubG9jYWxlO1xuICAgIGxldCBub3RhdGlvbjtcbiAgICBsZXQgZGVsdGEgPSB0aWNrVmFsdWU7XG4gICAgaWYgKHRpY2tzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGNvbnN0IG1heFRpY2sgPSBNYXRoLm1heChNYXRoLmFicyh0aWNrc1swXS52YWx1ZSksIE1hdGguYWJzKHRpY2tzW3RpY2tzLmxlbmd0aCAtIDFdLnZhbHVlKSk7XG4gICAgICBpZiAobWF4VGljayA8IDFlLTQgfHwgbWF4VGljayA+IDFlKzE1KSB7XG4gICAgICAgIG5vdGF0aW9uID0gJ3NjaWVudGlmaWMnO1xuICAgICAgfVxuICAgICAgZGVsdGEgPSBjYWxjdWxhdGVEZWx0YSh0aWNrVmFsdWUsIHRpY2tzKTtcbiAgICB9XG4gICAgY29uc3QgbG9nRGVsdGEgPSBsb2cxMChNYXRoLmFicyhkZWx0YSkpO1xuICAgIGNvbnN0IG51bURlY2ltYWwgPSBNYXRoLm1heChNYXRoLm1pbigtMSAqIE1hdGguZmxvb3IobG9nRGVsdGEpLCAyMCksIDApO1xuICAgIGNvbnN0IG9wdGlvbnMgPSB7bm90YXRpb24sIG1pbmltdW1GcmFjdGlvbkRpZ2l0czogbnVtRGVjaW1hbCwgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiBudW1EZWNpbWFsfTtcbiAgICBPYmplY3QuYXNzaWduKG9wdGlvbnMsIHRoaXMub3B0aW9ucy50aWNrcy5mb3JtYXQpO1xuICAgIHJldHVybiBmb3JtYXROdW1iZXIodGlja1ZhbHVlLCBsb2NhbGUsIG9wdGlvbnMpO1xuICB9LFxuICBsb2dhcml0aG1pYyh0aWNrVmFsdWUsIGluZGV4LCB0aWNrcykge1xuICAgIGlmICh0aWNrVmFsdWUgPT09IDApIHtcbiAgICAgIHJldHVybiAnMCc7XG4gICAgfVxuICAgIGNvbnN0IHJlbWFpbiA9IHRpY2tWYWx1ZSAvIChNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihsb2cxMCh0aWNrVmFsdWUpKSkpO1xuICAgIGlmIChyZW1haW4gPT09IDEgfHwgcmVtYWluID09PSAyIHx8IHJlbWFpbiA9PT0gNSkge1xuICAgICAgcmV0dXJuIGZvcm1hdHRlcnMubnVtZXJpYy5jYWxsKHRoaXMsIHRpY2tWYWx1ZSwgaW5kZXgsIHRpY2tzKTtcbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG59O1xuZnVuY3Rpb24gY2FsY3VsYXRlRGVsdGEodGlja1ZhbHVlLCB0aWNrcykge1xuICBsZXQgZGVsdGEgPSB0aWNrcy5sZW5ndGggPiAzID8gdGlja3NbMl0udmFsdWUgLSB0aWNrc1sxXS52YWx1ZSA6IHRpY2tzWzFdLnZhbHVlIC0gdGlja3NbMF0udmFsdWU7XG4gIGlmIChNYXRoLmFicyhkZWx0YSkgPj0gMSAmJiB0aWNrVmFsdWUgIT09IE1hdGguZmxvb3IodGlja1ZhbHVlKSkge1xuICAgIGRlbHRhID0gdGlja1ZhbHVlIC0gTWF0aC5mbG9vcih0aWNrVmFsdWUpO1xuICB9XG4gIHJldHVybiBkZWx0YTtcbn1cbnZhciBUaWNrcyA9IHtmb3JtYXR0ZXJzfTtcblxuZGVmYXVsdHMuc2V0KCdzY2FsZScsIHtcbiAgZGlzcGxheTogdHJ1ZSxcbiAgb2Zmc2V0OiBmYWxzZSxcbiAgcmV2ZXJzZTogZmFsc2UsXG4gIGJlZ2luQXRaZXJvOiBmYWxzZSxcbiAgYm91bmRzOiAndGlja3MnLFxuICBncmFjZTogMCxcbiAgZ3JpZDoge1xuICAgIGRpc3BsYXk6IHRydWUsXG4gICAgbGluZVdpZHRoOiAxLFxuICAgIGRyYXdCb3JkZXI6IHRydWUsXG4gICAgZHJhd09uQ2hhcnRBcmVhOiB0cnVlLFxuICAgIGRyYXdUaWNrczogdHJ1ZSxcbiAgICB0aWNrTGVuZ3RoOiA4LFxuICAgIHRpY2tXaWR0aDogKF9jdHgsIG9wdGlvbnMpID0+IG9wdGlvbnMubGluZVdpZHRoLFxuICAgIHRpY2tDb2xvcjogKF9jdHgsIG9wdGlvbnMpID0+IG9wdGlvbnMuY29sb3IsXG4gICAgb2Zmc2V0OiBmYWxzZSxcbiAgICBib3JkZXJEYXNoOiBbXSxcbiAgICBib3JkZXJEYXNoT2Zmc2V0OiAwLjAsXG4gICAgYm9yZGVyV2lkdGg6IDFcbiAgfSxcbiAgdGl0bGU6IHtcbiAgICBkaXNwbGF5OiBmYWxzZSxcbiAgICB0ZXh0OiAnJyxcbiAgICBwYWRkaW5nOiB7XG4gICAgICB0b3A6IDQsXG4gICAgICBib3R0b206IDRcbiAgICB9XG4gIH0sXG4gIHRpY2tzOiB7XG4gICAgbWluUm90YXRpb246IDAsXG4gICAgbWF4Um90YXRpb246IDUwLFxuICAgIG1pcnJvcjogZmFsc2UsXG4gICAgdGV4dFN0cm9rZVdpZHRoOiAwLFxuICAgIHRleHRTdHJva2VDb2xvcjogJycsXG4gICAgcGFkZGluZzogMyxcbiAgICBkaXNwbGF5OiB0cnVlLFxuICAgIGF1dG9Ta2lwOiB0cnVlLFxuICAgIGF1dG9Ta2lwUGFkZGluZzogMyxcbiAgICBsYWJlbE9mZnNldDogMCxcbiAgICBjYWxsYmFjazogVGlja3MuZm9ybWF0dGVycy52YWx1ZXMsXG4gICAgbWlub3I6IHt9LFxuICAgIG1ham9yOiB7fSxcbiAgICBhbGlnbjogJ2NlbnRlcicsXG4gICAgY3Jvc3NBbGlnbjogJ25lYXInLFxuICAgIHNob3dMYWJlbEJhY2tkcm9wOiBmYWxzZSxcbiAgICBiYWNrZHJvcENvbG9yOiAncmdiYSgyNTUsIDI1NSwgMjU1LCAwLjc1KScsXG4gICAgYmFja2Ryb3BQYWRkaW5nOiAyLFxuICB9XG59KTtcbmRlZmF1bHRzLnJvdXRlKCdzY2FsZS50aWNrcycsICdjb2xvcicsICcnLCAnY29sb3InKTtcbmRlZmF1bHRzLnJvdXRlKCdzY2FsZS5ncmlkJywgJ2NvbG9yJywgJycsICdib3JkZXJDb2xvcicpO1xuZGVmYXVsdHMucm91dGUoJ3NjYWxlLmdyaWQnLCAnYm9yZGVyQ29sb3InLCAnJywgJ2JvcmRlckNvbG9yJyk7XG5kZWZhdWx0cy5yb3V0ZSgnc2NhbGUudGl0bGUnLCAnY29sb3InLCAnJywgJ2NvbG9yJyk7XG5kZWZhdWx0cy5kZXNjcmliZSgnc2NhbGUnLCB7XG4gIF9mYWxsYmFjazogZmFsc2UsXG4gIF9zY3JpcHRhYmxlOiAobmFtZSkgPT4gIW5hbWUuc3RhcnRzV2l0aCgnYmVmb3JlJykgJiYgIW5hbWUuc3RhcnRzV2l0aCgnYWZ0ZXInKSAmJiBuYW1lICE9PSAnY2FsbGJhY2snICYmIG5hbWUgIT09ICdwYXJzZXInLFxuICBfaW5kZXhhYmxlOiAobmFtZSkgPT4gbmFtZSAhPT0gJ2JvcmRlckRhc2gnICYmIG5hbWUgIT09ICd0aWNrQm9yZGVyRGFzaCcsXG59KTtcbmRlZmF1bHRzLmRlc2NyaWJlKCdzY2FsZXMnLCB7XG4gIF9mYWxsYmFjazogJ3NjYWxlJyxcbn0pO1xuZGVmYXVsdHMuZGVzY3JpYmUoJ3NjYWxlLnRpY2tzJywge1xuICBfc2NyaXB0YWJsZTogKG5hbWUpID0+IG5hbWUgIT09ICdiYWNrZHJvcFBhZGRpbmcnICYmIG5hbWUgIT09ICdjYWxsYmFjaycsXG4gIF9pbmRleGFibGU6IChuYW1lKSA9PiBuYW1lICE9PSAnYmFja2Ryb3BQYWRkaW5nJyxcbn0pO1xuXG5mdW5jdGlvbiBhdXRvU2tpcChzY2FsZSwgdGlja3MpIHtcbiAgY29uc3QgdGlja09wdHMgPSBzY2FsZS5vcHRpb25zLnRpY2tzO1xuICBjb25zdCB0aWNrc0xpbWl0ID0gdGlja09wdHMubWF4VGlja3NMaW1pdCB8fCBkZXRlcm1pbmVNYXhUaWNrcyhzY2FsZSk7XG4gIGNvbnN0IG1ham9ySW5kaWNlcyA9IHRpY2tPcHRzLm1ham9yLmVuYWJsZWQgPyBnZXRNYWpvckluZGljZXModGlja3MpIDogW107XG4gIGNvbnN0IG51bU1ham9ySW5kaWNlcyA9IG1ham9ySW5kaWNlcy5sZW5ndGg7XG4gIGNvbnN0IGZpcnN0ID0gbWFqb3JJbmRpY2VzWzBdO1xuICBjb25zdCBsYXN0ID0gbWFqb3JJbmRpY2VzW251bU1ham9ySW5kaWNlcyAtIDFdO1xuICBjb25zdCBuZXdUaWNrcyA9IFtdO1xuICBpZiAobnVtTWFqb3JJbmRpY2VzID4gdGlja3NMaW1pdCkge1xuICAgIHNraXBNYWpvcnModGlja3MsIG5ld1RpY2tzLCBtYWpvckluZGljZXMsIG51bU1ham9ySW5kaWNlcyAvIHRpY2tzTGltaXQpO1xuICAgIHJldHVybiBuZXdUaWNrcztcbiAgfVxuICBjb25zdCBzcGFjaW5nID0gY2FsY3VsYXRlU3BhY2luZyhtYWpvckluZGljZXMsIHRpY2tzLCB0aWNrc0xpbWl0KTtcbiAgaWYgKG51bU1ham9ySW5kaWNlcyA+IDApIHtcbiAgICBsZXQgaSwgaWxlbjtcbiAgICBjb25zdCBhdmdNYWpvclNwYWNpbmcgPSBudW1NYWpvckluZGljZXMgPiAxID8gTWF0aC5yb3VuZCgobGFzdCAtIGZpcnN0KSAvIChudW1NYWpvckluZGljZXMgLSAxKSkgOiBudWxsO1xuICAgIHNraXAodGlja3MsIG5ld1RpY2tzLCBzcGFjaW5nLCBpc051bGxPclVuZGVmKGF2Z01ham9yU3BhY2luZykgPyAwIDogZmlyc3QgLSBhdmdNYWpvclNwYWNpbmcsIGZpcnN0KTtcbiAgICBmb3IgKGkgPSAwLCBpbGVuID0gbnVtTWFqb3JJbmRpY2VzIC0gMTsgaSA8IGlsZW47IGkrKykge1xuICAgICAgc2tpcCh0aWNrcywgbmV3VGlja3MsIHNwYWNpbmcsIG1ham9ySW5kaWNlc1tpXSwgbWFqb3JJbmRpY2VzW2kgKyAxXSk7XG4gICAgfVxuICAgIHNraXAodGlja3MsIG5ld1RpY2tzLCBzcGFjaW5nLCBsYXN0LCBpc051bGxPclVuZGVmKGF2Z01ham9yU3BhY2luZykgPyB0aWNrcy5sZW5ndGggOiBsYXN0ICsgYXZnTWFqb3JTcGFjaW5nKTtcbiAgICByZXR1cm4gbmV3VGlja3M7XG4gIH1cbiAgc2tpcCh0aWNrcywgbmV3VGlja3MsIHNwYWNpbmcpO1xuICByZXR1cm4gbmV3VGlja3M7XG59XG5mdW5jdGlvbiBkZXRlcm1pbmVNYXhUaWNrcyhzY2FsZSkge1xuICBjb25zdCBvZmZzZXQgPSBzY2FsZS5vcHRpb25zLm9mZnNldDtcbiAgY29uc3QgdGlja0xlbmd0aCA9IHNjYWxlLl90aWNrU2l6ZSgpO1xuICBjb25zdCBtYXhTY2FsZSA9IHNjYWxlLl9sZW5ndGggLyB0aWNrTGVuZ3RoICsgKG9mZnNldCA/IDAgOiAxKTtcbiAgY29uc3QgbWF4Q2hhcnQgPSBzY2FsZS5fbWF4TGVuZ3RoIC8gdGlja0xlbmd0aDtcbiAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5taW4obWF4U2NhbGUsIG1heENoYXJ0KSk7XG59XG5mdW5jdGlvbiBjYWxjdWxhdGVTcGFjaW5nKG1ham9ySW5kaWNlcywgdGlja3MsIHRpY2tzTGltaXQpIHtcbiAgY29uc3QgZXZlbk1ham9yU3BhY2luZyA9IGdldEV2ZW5TcGFjaW5nKG1ham9ySW5kaWNlcyk7XG4gIGNvbnN0IHNwYWNpbmcgPSB0aWNrcy5sZW5ndGggLyB0aWNrc0xpbWl0O1xuICBpZiAoIWV2ZW5NYWpvclNwYWNpbmcpIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoc3BhY2luZywgMSk7XG4gIH1cbiAgY29uc3QgZmFjdG9ycyA9IF9mYWN0b3JpemUoZXZlbk1ham9yU3BhY2luZyk7XG4gIGZvciAobGV0IGkgPSAwLCBpbGVuID0gZmFjdG9ycy5sZW5ndGggLSAxOyBpIDwgaWxlbjsgaSsrKSB7XG4gICAgY29uc3QgZmFjdG9yID0gZmFjdG9yc1tpXTtcbiAgICBpZiAoZmFjdG9yID4gc3BhY2luZykge1xuICAgICAgcmV0dXJuIGZhY3RvcjtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIE1hdGgubWF4KHNwYWNpbmcsIDEpO1xufVxuZnVuY3Rpb24gZ2V0TWFqb3JJbmRpY2VzKHRpY2tzKSB7XG4gIGNvbnN0IHJlc3VsdCA9IFtdO1xuICBsZXQgaSwgaWxlbjtcbiAgZm9yIChpID0gMCwgaWxlbiA9IHRpY2tzLmxlbmd0aDsgaSA8IGlsZW47IGkrKykge1xuICAgIGlmICh0aWNrc1tpXS5tYWpvcikge1xuICAgICAgcmVzdWx0LnB1c2goaSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBza2lwTWFqb3JzKHRpY2tzLCBuZXdUaWNrcywgbWFqb3JJbmRpY2VzLCBzcGFjaW5nKSB7XG4gIGxldCBjb3VudCA9IDA7XG4gIGxldCBuZXh0ID0gbWFqb3JJbmRpY2VzWzBdO1xuICBsZXQgaTtcbiAgc3BhY2luZyA9IE1hdGguY2VpbChzcGFjaW5nKTtcbiAgZm9yIChpID0gMDsgaSA8IHRpY2tzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IG5leHQpIHtcbiAgICAgIG5ld1RpY2tzLnB1c2godGlja3NbaV0pO1xuICAgICAgY291bnQrKztcbiAgICAgIG5leHQgPSBtYWpvckluZGljZXNbY291bnQgKiBzcGFjaW5nXTtcbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uIHNraXAodGlja3MsIG5ld1RpY2tzLCBzcGFjaW5nLCBtYWpvclN0YXJ0LCBtYWpvckVuZCkge1xuICBjb25zdCBzdGFydCA9IHZhbHVlT3JEZWZhdWx0KG1ham9yU3RhcnQsIDApO1xuICBjb25zdCBlbmQgPSBNYXRoLm1pbih2YWx1ZU9yRGVmYXVsdChtYWpvckVuZCwgdGlja3MubGVuZ3RoKSwgdGlja3MubGVuZ3RoKTtcbiAgbGV0IGNvdW50ID0gMDtcbiAgbGV0IGxlbmd0aCwgaSwgbmV4dDtcbiAgc3BhY2luZyA9IE1hdGguY2VpbChzcGFjaW5nKTtcbiAgaWYgKG1ham9yRW5kKSB7XG4gICAgbGVuZ3RoID0gbWFqb3JFbmQgLSBtYWpvclN0YXJ0O1xuICAgIHNwYWNpbmcgPSBsZW5ndGggLyBNYXRoLmZsb29yKGxlbmd0aCAvIHNwYWNpbmcpO1xuICB9XG4gIG5leHQgPSBzdGFydDtcbiAgd2hpbGUgKG5leHQgPCAwKSB7XG4gICAgY291bnQrKztcbiAgICBuZXh0ID0gTWF0aC5yb3VuZChzdGFydCArIGNvdW50ICogc3BhY2luZyk7XG4gIH1cbiAgZm9yIChpID0gTWF0aC5tYXgoc3RhcnQsIDApOyBpIDwgZW5kOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gbmV4dCkge1xuICAgICAgbmV3VGlja3MucHVzaCh0aWNrc1tpXSk7XG4gICAgICBjb3VudCsrO1xuICAgICAgbmV4dCA9IE1hdGgucm91bmQoc3RhcnQgKyBjb3VudCAqIHNwYWNpbmcpO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gZ2V0RXZlblNwYWNpbmcoYXJyKSB7XG4gIGNvbnN0IGxlbiA9IGFyci5sZW5ndGg7XG4gIGxldCBpLCBkaWZmO1xuICBpZiAobGVuIDwgMikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKGRpZmYgPSBhcnJbMF0sIGkgPSAxOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAoYXJyW2ldIC0gYXJyW2kgLSAxXSAhPT0gZGlmZikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZGlmZjtcbn1cblxuY29uc3QgcmV2ZXJzZUFsaWduID0gKGFsaWduKSA9PiBhbGlnbiA9PT0gJ2xlZnQnID8gJ3JpZ2h0JyA6IGFsaWduID09PSAncmlnaHQnID8gJ2xlZnQnIDogYWxpZ247XG5jb25zdCBvZmZzZXRGcm9tRWRnZSA9IChzY2FsZSwgZWRnZSwgb2Zmc2V0KSA9PiBlZGdlID09PSAndG9wJyB8fCBlZGdlID09PSAnbGVmdCcgPyBzY2FsZVtlZGdlXSArIG9mZnNldCA6IHNjYWxlW2VkZ2VdIC0gb2Zmc2V0O1xuZnVuY3Rpb24gc2FtcGxlKGFyciwgbnVtSXRlbXMpIHtcbiAgY29uc3QgcmVzdWx0ID0gW107XG4gIGNvbnN0IGluY3JlbWVudCA9IGFyci5sZW5ndGggLyBudW1JdGVtcztcbiAgY29uc3QgbGVuID0gYXJyLmxlbmd0aDtcbiAgbGV0IGkgPSAwO1xuICBmb3IgKDsgaSA8IGxlbjsgaSArPSBpbmNyZW1lbnQpIHtcbiAgICByZXN1bHQucHVzaChhcnJbTWF0aC5mbG9vcihpKV0pO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBnZXRQaXhlbEZvckdyaWRMaW5lKHNjYWxlLCBpbmRleCwgb2Zmc2V0R3JpZExpbmVzKSB7XG4gIGNvbnN0IGxlbmd0aCA9IHNjYWxlLnRpY2tzLmxlbmd0aDtcbiAgY29uc3QgdmFsaWRJbmRleCA9IE1hdGgubWluKGluZGV4LCBsZW5ndGggLSAxKTtcbiAgY29uc3Qgc3RhcnQgPSBzY2FsZS5fc3RhcnRQaXhlbDtcbiAgY29uc3QgZW5kID0gc2NhbGUuX2VuZFBpeGVsO1xuICBjb25zdCBlcHNpbG9uID0gMWUtNjtcbiAgbGV0IGxpbmVWYWx1ZSA9IHNjYWxlLmdldFBpeGVsRm9yVGljayh2YWxpZEluZGV4KTtcbiAgbGV0IG9mZnNldDtcbiAgaWYgKG9mZnNldEdyaWRMaW5lcykge1xuICAgIGlmIChsZW5ndGggPT09IDEpIHtcbiAgICAgIG9mZnNldCA9IE1hdGgubWF4KGxpbmVWYWx1ZSAtIHN0YXJ0LCBlbmQgLSBsaW5lVmFsdWUpO1xuICAgIH0gZWxzZSBpZiAoaW5kZXggPT09IDApIHtcbiAgICAgIG9mZnNldCA9IChzY2FsZS5nZXRQaXhlbEZvclRpY2soMSkgLSBsaW5lVmFsdWUpIC8gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgb2Zmc2V0ID0gKGxpbmVWYWx1ZSAtIHNjYWxlLmdldFBpeGVsRm9yVGljayh2YWxpZEluZGV4IC0gMSkpIC8gMjtcbiAgICB9XG4gICAgbGluZVZhbHVlICs9IHZhbGlkSW5kZXggPCBpbmRleCA/IG9mZnNldCA6IC1vZmZzZXQ7XG4gICAgaWYgKGxpbmVWYWx1ZSA8IHN0YXJ0IC0gZXBzaWxvbiB8fCBsaW5lVmFsdWUgPiBlbmQgKyBlcHNpbG9uKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG4gIHJldHVybiBsaW5lVmFsdWU7XG59XG5mdW5jdGlvbiBnYXJiYWdlQ29sbGVjdChjYWNoZXMsIGxlbmd0aCkge1xuICBlYWNoKGNhY2hlcywgKGNhY2hlKSA9PiB7XG4gICAgY29uc3QgZ2MgPSBjYWNoZS5nYztcbiAgICBjb25zdCBnY0xlbiA9IGdjLmxlbmd0aCAvIDI7XG4gICAgbGV0IGk7XG4gICAgaWYgKGdjTGVuID4gbGVuZ3RoKSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgZ2NMZW47ICsraSkge1xuICAgICAgICBkZWxldGUgY2FjaGUuZGF0YVtnY1tpXV07XG4gICAgICB9XG4gICAgICBnYy5zcGxpY2UoMCwgZ2NMZW4pO1xuICAgIH1cbiAgfSk7XG59XG5mdW5jdGlvbiBnZXRUaWNrTWFya0xlbmd0aChvcHRpb25zKSB7XG4gIHJldHVybiBvcHRpb25zLmRyYXdUaWNrcyA/IG9wdGlvbnMudGlja0xlbmd0aCA6IDA7XG59XG5mdW5jdGlvbiBnZXRUaXRsZUhlaWdodChvcHRpb25zLCBmYWxsYmFjaykge1xuICBpZiAoIW9wdGlvbnMuZGlzcGxheSkge1xuICAgIHJldHVybiAwO1xuICB9XG4gIGNvbnN0IGZvbnQgPSB0b0ZvbnQob3B0aW9ucy5mb250LCBmYWxsYmFjayk7XG4gIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcob3B0aW9ucy5wYWRkaW5nKTtcbiAgY29uc3QgbGluZXMgPSBpc0FycmF5KG9wdGlvbnMudGV4dCkgPyBvcHRpb25zLnRleHQubGVuZ3RoIDogMTtcbiAgcmV0dXJuIChsaW5lcyAqIGZvbnQubGluZUhlaWdodCkgKyBwYWRkaW5nLmhlaWdodDtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVNjYWxlQ29udGV4dChwYXJlbnQsIHNjYWxlKSB7XG4gIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUocGFyZW50KSwge1xuICAgIHNjYWxlLFxuICAgIHR5cGU6ICdzY2FsZSdcbiAgfSk7XG59XG5mdW5jdGlvbiBjcmVhdGVUaWNrQ29udGV4dChwYXJlbnQsIGluZGV4LCB0aWNrKSB7XG4gIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUocGFyZW50KSwge1xuICAgIHRpY2ssXG4gICAgaW5kZXgsXG4gICAgdHlwZTogJ3RpY2snXG4gIH0pO1xufVxuZnVuY3Rpb24gdGl0bGVBbGlnbihhbGlnbiwgcG9zaXRpb24sIHJldmVyc2UpIHtcbiAgbGV0IHJldCA9IF90b0xlZnRSaWdodENlbnRlcihhbGlnbik7XG4gIGlmICgocmV2ZXJzZSAmJiBwb3NpdGlvbiAhPT0gJ3JpZ2h0JykgfHwgKCFyZXZlcnNlICYmIHBvc2l0aW9uID09PSAncmlnaHQnKSkge1xuICAgIHJldCA9IHJldmVyc2VBbGlnbihyZXQpO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5mdW5jdGlvbiB0aXRsZUFyZ3Moc2NhbGUsIG9mZnNldCwgcG9zaXRpb24sIGFsaWduKSB7XG4gIGNvbnN0IHt0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQsIGNoYXJ0fSA9IHNjYWxlO1xuICBjb25zdCB7Y2hhcnRBcmVhLCBzY2FsZXN9ID0gY2hhcnQ7XG4gIGxldCByb3RhdGlvbiA9IDA7XG4gIGxldCBtYXhXaWR0aCwgdGl0bGVYLCB0aXRsZVk7XG4gIGNvbnN0IGhlaWdodCA9IGJvdHRvbSAtIHRvcDtcbiAgY29uc3Qgd2lkdGggPSByaWdodCAtIGxlZnQ7XG4gIGlmIChzY2FsZS5pc0hvcml6b250YWwoKSkge1xuICAgIHRpdGxlWCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBsZWZ0LCByaWdodCk7XG4gICAgaWYgKGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgY29uc3QgcG9zaXRpb25BeGlzSUQgPSBPYmplY3Qua2V5cyhwb3NpdGlvbilbMF07XG4gICAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW3Bvc2l0aW9uQXhpc0lEXTtcbiAgICAgIHRpdGxlWSA9IHNjYWxlc1twb3NpdGlvbkF4aXNJRF0uZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkgKyBoZWlnaHQgLSBvZmZzZXQ7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIHRpdGxlWSA9IChjaGFydEFyZWEuYm90dG9tICsgY2hhcnRBcmVhLnRvcCkgLyAyICsgaGVpZ2h0IC0gb2Zmc2V0O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aXRsZVkgPSBvZmZzZXRGcm9tRWRnZShzY2FsZSwgcG9zaXRpb24sIG9mZnNldCk7XG4gICAgfVxuICAgIG1heFdpZHRoID0gcmlnaHQgLSBsZWZ0O1xuICB9IGVsc2Uge1xuICAgIGlmIChpc09iamVjdChwb3NpdGlvbikpIHtcbiAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICB0aXRsZVggPSBzY2FsZXNbcG9zaXRpb25BeGlzSURdLmdldFBpeGVsRm9yVmFsdWUodmFsdWUpIC0gd2lkdGggKyBvZmZzZXQ7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIHRpdGxlWCA9IChjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS5yaWdodCkgLyAyIC0gd2lkdGggKyBvZmZzZXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRpdGxlWCA9IG9mZnNldEZyb21FZGdlKHNjYWxlLCBwb3NpdGlvbiwgb2Zmc2V0KTtcbiAgICB9XG4gICAgdGl0bGVZID0gX2FsaWduU3RhcnRFbmQoYWxpZ24sIGJvdHRvbSwgdG9wKTtcbiAgICByb3RhdGlvbiA9IHBvc2l0aW9uID09PSAnbGVmdCcgPyAtSEFMRl9QSSA6IEhBTEZfUEk7XG4gIH1cbiAgcmV0dXJuIHt0aXRsZVgsIHRpdGxlWSwgbWF4V2lkdGgsIHJvdGF0aW9ufTtcbn1cbmNsYXNzIFNjYWxlIGV4dGVuZHMgRWxlbWVudCB7XG4gIGNvbnN0cnVjdG9yKGNmZykge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5pZCA9IGNmZy5pZDtcbiAgICB0aGlzLnR5cGUgPSBjZmcudHlwZTtcbiAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5jdHggPSBjZmcuY3R4O1xuICAgIHRoaXMuY2hhcnQgPSBjZmcuY2hhcnQ7XG4gICAgdGhpcy50b3AgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5ib3R0b20gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5sZWZ0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMucmlnaHQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy53aWR0aCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9tYXJnaW5zID0ge1xuICAgICAgbGVmdDogMCxcbiAgICAgIHJpZ2h0OiAwLFxuICAgICAgdG9wOiAwLFxuICAgICAgYm90dG9tOiAwXG4gICAgfTtcbiAgICB0aGlzLm1heFdpZHRoID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWF4SGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMucGFkZGluZ1RvcCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnBhZGRpbmdCb3R0b20gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5wYWRkaW5nTGVmdCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnBhZGRpbmdSaWdodCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmF4aXMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5sYWJlbFJvdGF0aW9uID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWluID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWF4ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3JhbmdlID0gdW5kZWZpbmVkO1xuICAgIHRoaXMudGlja3MgPSBbXTtcbiAgICB0aGlzLl9ncmlkTGluZUl0ZW1zID0gbnVsbDtcbiAgICB0aGlzLl9sYWJlbEl0ZW1zID0gbnVsbDtcbiAgICB0aGlzLl9sYWJlbFNpemVzID0gbnVsbDtcbiAgICB0aGlzLl9sZW5ndGggPSAwO1xuICAgIHRoaXMuX21heExlbmd0aCA9IDA7XG4gICAgdGhpcy5fbG9uZ2VzdFRleHRDYWNoZSA9IHt9O1xuICAgIHRoaXMuX3N0YXJ0UGl4ZWwgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fZW5kUGl4ZWwgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fcmV2ZXJzZVBpeGVscyA9IGZhbHNlO1xuICAgIHRoaXMuX3VzZXJNYXggPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fdXNlck1pbiA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9zdWdnZXN0ZWRNYXggPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fc3VnZ2VzdGVkTWluID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3RpY2tzTGVuZ3RoID0gMDtcbiAgICB0aGlzLl9ib3JkZXJWYWx1ZSA9IDA7XG4gICAgdGhpcy5fY2FjaGUgPSB7fTtcbiAgICB0aGlzLl9kYXRhTGltaXRzQ2FjaGVkID0gZmFsc2U7XG4gICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgfVxuICBpbml0KG9wdGlvbnMpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgbWUub3B0aW9ucyA9IG9wdGlvbnMuc2V0Q29udGV4dChtZS5nZXRDb250ZXh0KCkpO1xuICAgIG1lLmF4aXMgPSBvcHRpb25zLmF4aXM7XG4gICAgbWUuX3VzZXJNaW4gPSBtZS5wYXJzZShvcHRpb25zLm1pbik7XG4gICAgbWUuX3VzZXJNYXggPSBtZS5wYXJzZShvcHRpb25zLm1heCk7XG4gICAgbWUuX3N1Z2dlc3RlZE1pbiA9IG1lLnBhcnNlKG9wdGlvbnMuc3VnZ2VzdGVkTWluKTtcbiAgICBtZS5fc3VnZ2VzdGVkTWF4ID0gbWUucGFyc2Uob3B0aW9ucy5zdWdnZXN0ZWRNYXgpO1xuICB9XG4gIHBhcnNlKHJhdywgaW5kZXgpIHtcbiAgICByZXR1cm4gcmF3O1xuICB9XG4gIGdldFVzZXJCb3VuZHMoKSB7XG4gICAgbGV0IHtfdXNlck1pbiwgX3VzZXJNYXgsIF9zdWdnZXN0ZWRNaW4sIF9zdWdnZXN0ZWRNYXh9ID0gdGhpcztcbiAgICBfdXNlck1pbiA9IGZpbml0ZU9yRGVmYXVsdChfdXNlck1pbiwgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZKTtcbiAgICBfdXNlck1heCA9IGZpbml0ZU9yRGVmYXVsdChfdXNlck1heCwgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZKTtcbiAgICBfc3VnZ2VzdGVkTWluID0gZmluaXRlT3JEZWZhdWx0KF9zdWdnZXN0ZWRNaW4sIE51bWJlci5QT1NJVElWRV9JTkZJTklUWSk7XG4gICAgX3N1Z2dlc3RlZE1heCA9IGZpbml0ZU9yRGVmYXVsdChfc3VnZ2VzdGVkTWF4LCBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFkpO1xuICAgIHJldHVybiB7XG4gICAgICBtaW46IGZpbml0ZU9yRGVmYXVsdChfdXNlck1pbiwgX3N1Z2dlc3RlZE1pbiksXG4gICAgICBtYXg6IGZpbml0ZU9yRGVmYXVsdChfdXNlck1heCwgX3N1Z2dlc3RlZE1heCksXG4gICAgICBtaW5EZWZpbmVkOiBpc051bWJlckZpbml0ZShfdXNlck1pbiksXG4gICAgICBtYXhEZWZpbmVkOiBpc051bWJlckZpbml0ZShfdXNlck1heClcbiAgICB9O1xuICB9XG4gIGdldE1pbk1heChjYW5TdGFjaykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBsZXQge21pbiwgbWF4LCBtaW5EZWZpbmVkLCBtYXhEZWZpbmVkfSA9IG1lLmdldFVzZXJCb3VuZHMoKTtcbiAgICBsZXQgcmFuZ2U7XG4gICAgaWYgKG1pbkRlZmluZWQgJiYgbWF4RGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHttaW4sIG1heH07XG4gICAgfVxuICAgIGNvbnN0IG1ldGFzID0gbWUuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXMoKTtcbiAgICBmb3IgKGxldCBpID0gMCwgaWxlbiA9IG1ldGFzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgcmFuZ2UgPSBtZXRhc1tpXS5jb250cm9sbGVyLmdldE1pbk1heChtZSwgY2FuU3RhY2spO1xuICAgICAgaWYgKCFtaW5EZWZpbmVkKSB7XG4gICAgICAgIG1pbiA9IE1hdGgubWluKG1pbiwgcmFuZ2UubWluKTtcbiAgICAgIH1cbiAgICAgIGlmICghbWF4RGVmaW5lZCkge1xuICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIHJhbmdlLm1heCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBtaW46IGZpbml0ZU9yRGVmYXVsdChtaW4sIGZpbml0ZU9yRGVmYXVsdChtYXgsIG1pbikpLFxuICAgICAgbWF4OiBmaW5pdGVPckRlZmF1bHQobWF4LCBmaW5pdGVPckRlZmF1bHQobWluLCBtYXgpKVxuICAgIH07XG4gIH1cbiAgZ2V0UGFkZGluZygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxlZnQ6IG1lLnBhZGRpbmdMZWZ0IHx8IDAsXG4gICAgICB0b3A6IG1lLnBhZGRpbmdUb3AgfHwgMCxcbiAgICAgIHJpZ2h0OiBtZS5wYWRkaW5nUmlnaHQgfHwgMCxcbiAgICAgIGJvdHRvbTogbWUucGFkZGluZ0JvdHRvbSB8fCAwXG4gICAgfTtcbiAgfVxuICBnZXRUaWNrcygpIHtcbiAgICByZXR1cm4gdGhpcy50aWNrcztcbiAgfVxuICBnZXRMYWJlbHMoKSB7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMuY2hhcnQuZGF0YTtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmxhYmVscyB8fCAodGhpcy5pc0hvcml6b250YWwoKSA/IGRhdGEueExhYmVscyA6IGRhdGEueUxhYmVscykgfHwgZGF0YS5sYWJlbHMgfHwgW107XG4gIH1cbiAgYmVmb3JlTGF5b3V0KCkge1xuICAgIHRoaXMuX2NhY2hlID0ge307XG4gICAgdGhpcy5fZGF0YUxpbWl0c0NhY2hlZCA9IGZhbHNlO1xuICB9XG4gIGJlZm9yZVVwZGF0ZSgpIHtcbiAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlVXBkYXRlLCBbdGhpc10pO1xuICB9XG4gIHVwZGF0ZShtYXhXaWR0aCwgbWF4SGVpZ2h0LCBtYXJnaW5zKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHRpY2tPcHRzID0gbWUub3B0aW9ucy50aWNrcztcbiAgICBjb25zdCBzYW1wbGVTaXplID0gdGlja09wdHMuc2FtcGxlU2l6ZTtcbiAgICBtZS5iZWZvcmVVcGRhdGUoKTtcbiAgICBtZS5tYXhXaWR0aCA9IG1heFdpZHRoO1xuICAgIG1lLm1heEhlaWdodCA9IG1heEhlaWdodDtcbiAgICBtZS5fbWFyZ2lucyA9IG1hcmdpbnMgPSBPYmplY3QuYXNzaWduKHtcbiAgICAgIGxlZnQ6IDAsXG4gICAgICByaWdodDogMCxcbiAgICAgIHRvcDogMCxcbiAgICAgIGJvdHRvbTogMFxuICAgIH0sIG1hcmdpbnMpO1xuICAgIG1lLnRpY2tzID0gbnVsbDtcbiAgICBtZS5fbGFiZWxTaXplcyA9IG51bGw7XG4gICAgbWUuX2dyaWRMaW5lSXRlbXMgPSBudWxsO1xuICAgIG1lLl9sYWJlbEl0ZW1zID0gbnVsbDtcbiAgICBtZS5iZWZvcmVTZXREaW1lbnNpb25zKCk7XG4gICAgbWUuc2V0RGltZW5zaW9ucygpO1xuICAgIG1lLmFmdGVyU2V0RGltZW5zaW9ucygpO1xuICAgIG1lLl9tYXhMZW5ndGggPSBtZS5pc0hvcml6b250YWwoKVxuICAgICAgPyBtZS53aWR0aCArIG1hcmdpbnMubGVmdCArIG1hcmdpbnMucmlnaHRcbiAgICAgIDogbWUuaGVpZ2h0ICsgbWFyZ2lucy50b3AgKyBtYXJnaW5zLmJvdHRvbTtcbiAgICBpZiAoIW1lLl9kYXRhTGltaXRzQ2FjaGVkKSB7XG4gICAgICBtZS5iZWZvcmVEYXRhTGltaXRzKCk7XG4gICAgICBtZS5kZXRlcm1pbmVEYXRhTGltaXRzKCk7XG4gICAgICBtZS5hZnRlckRhdGFMaW1pdHMoKTtcbiAgICAgIG1lLl9yYW5nZSA9IF9hZGRHcmFjZShtZSwgbWUub3B0aW9ucy5ncmFjZSk7XG4gICAgICBtZS5fZGF0YUxpbWl0c0NhY2hlZCA9IHRydWU7XG4gICAgfVxuICAgIG1lLmJlZm9yZUJ1aWxkVGlja3MoKTtcbiAgICBtZS50aWNrcyA9IG1lLmJ1aWxkVGlja3MoKSB8fCBbXTtcbiAgICBtZS5hZnRlckJ1aWxkVGlja3MoKTtcbiAgICBjb25zdCBzYW1wbGluZ0VuYWJsZWQgPSBzYW1wbGVTaXplIDwgbWUudGlja3MubGVuZ3RoO1xuICAgIG1lLl9jb252ZXJ0VGlja3NUb0xhYmVscyhzYW1wbGluZ0VuYWJsZWQgPyBzYW1wbGUobWUudGlja3MsIHNhbXBsZVNpemUpIDogbWUudGlja3MpO1xuICAgIG1lLmNvbmZpZ3VyZSgpO1xuICAgIG1lLmJlZm9yZUNhbGN1bGF0ZUxhYmVsUm90YXRpb24oKTtcbiAgICBtZS5jYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCk7XG4gICAgbWUuYWZ0ZXJDYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCk7XG4gICAgaWYgKHRpY2tPcHRzLmRpc3BsYXkgJiYgKHRpY2tPcHRzLmF1dG9Ta2lwIHx8IHRpY2tPcHRzLnNvdXJjZSA9PT0gJ2F1dG8nKSkge1xuICAgICAgbWUudGlja3MgPSBhdXRvU2tpcChtZSwgbWUudGlja3MpO1xuICAgICAgbWUuX2xhYmVsU2l6ZXMgPSBudWxsO1xuICAgIH1cbiAgICBpZiAoc2FtcGxpbmdFbmFibGVkKSB7XG4gICAgICBtZS5fY29udmVydFRpY2tzVG9MYWJlbHMobWUudGlja3MpO1xuICAgIH1cbiAgICBtZS5iZWZvcmVGaXQoKTtcbiAgICBtZS5maXQoKTtcbiAgICBtZS5hZnRlckZpdCgpO1xuICAgIG1lLmFmdGVyVXBkYXRlKCk7XG4gIH1cbiAgY29uZmlndXJlKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBsZXQgcmV2ZXJzZVBpeGVscyA9IG1lLm9wdGlvbnMucmV2ZXJzZTtcbiAgICBsZXQgc3RhcnRQaXhlbCwgZW5kUGl4ZWw7XG4gICAgaWYgKG1lLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICBzdGFydFBpeGVsID0gbWUubGVmdDtcbiAgICAgIGVuZFBpeGVsID0gbWUucmlnaHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXJ0UGl4ZWwgPSBtZS50b3A7XG4gICAgICBlbmRQaXhlbCA9IG1lLmJvdHRvbTtcbiAgICAgIHJldmVyc2VQaXhlbHMgPSAhcmV2ZXJzZVBpeGVscztcbiAgICB9XG4gICAgbWUuX3N0YXJ0UGl4ZWwgPSBzdGFydFBpeGVsO1xuICAgIG1lLl9lbmRQaXhlbCA9IGVuZFBpeGVsO1xuICAgIG1lLl9yZXZlcnNlUGl4ZWxzID0gcmV2ZXJzZVBpeGVscztcbiAgICBtZS5fbGVuZ3RoID0gZW5kUGl4ZWwgLSBzdGFydFBpeGVsO1xuICAgIG1lLl9hbGlnblRvUGl4ZWxzID0gbWUub3B0aW9ucy5hbGlnblRvUGl4ZWxzO1xuICB9XG4gIGFmdGVyVXBkYXRlKCkge1xuICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlclVwZGF0ZSwgW3RoaXNdKTtcbiAgfVxuICBiZWZvcmVTZXREaW1lbnNpb25zKCkge1xuICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5iZWZvcmVTZXREaW1lbnNpb25zLCBbdGhpc10pO1xuICB9XG4gIHNldERpbWVuc2lvbnMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmIChtZS5pc0hvcml6b250YWwoKSkge1xuICAgICAgbWUud2lkdGggPSBtZS5tYXhXaWR0aDtcbiAgICAgIG1lLmxlZnQgPSAwO1xuICAgICAgbWUucmlnaHQgPSBtZS53aWR0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgbWUuaGVpZ2h0ID0gbWUubWF4SGVpZ2h0O1xuICAgICAgbWUudG9wID0gMDtcbiAgICAgIG1lLmJvdHRvbSA9IG1lLmhlaWdodDtcbiAgICB9XG4gICAgbWUucGFkZGluZ0xlZnQgPSAwO1xuICAgIG1lLnBhZGRpbmdUb3AgPSAwO1xuICAgIG1lLnBhZGRpbmdSaWdodCA9IDA7XG4gICAgbWUucGFkZGluZ0JvdHRvbSA9IDA7XG4gIH1cbiAgYWZ0ZXJTZXREaW1lbnNpb25zKCkge1xuICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlclNldERpbWVuc2lvbnMsIFt0aGlzXSk7XG4gIH1cbiAgX2NhbGxIb29rcyhuYW1lKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIG1lLmNoYXJ0Lm5vdGlmeVBsdWdpbnMobmFtZSwgbWUuZ2V0Q29udGV4dCgpKTtcbiAgICBjYWxsYmFjayhtZS5vcHRpb25zW25hbWVdLCBbbWVdKTtcbiAgfVxuICBiZWZvcmVEYXRhTGltaXRzKCkge1xuICAgIHRoaXMuX2NhbGxIb29rcygnYmVmb3JlRGF0YUxpbWl0cycpO1xuICB9XG4gIGRldGVybWluZURhdGFMaW1pdHMoKSB7fVxuICBhZnRlckRhdGFMaW1pdHMoKSB7XG4gICAgdGhpcy5fY2FsbEhvb2tzKCdhZnRlckRhdGFMaW1pdHMnKTtcbiAgfVxuICBiZWZvcmVCdWlsZFRpY2tzKCkge1xuICAgIHRoaXMuX2NhbGxIb29rcygnYmVmb3JlQnVpbGRUaWNrcycpO1xuICB9XG4gIGJ1aWxkVGlja3MoKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGFmdGVyQnVpbGRUaWNrcygpIHtcbiAgICB0aGlzLl9jYWxsSG9va3MoJ2FmdGVyQnVpbGRUaWNrcycpO1xuICB9XG4gIGJlZm9yZVRpY2tUb0xhYmVsQ29udmVyc2lvbigpIHtcbiAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlVGlja1RvTGFiZWxDb252ZXJzaW9uLCBbdGhpc10pO1xuICB9XG4gIGdlbmVyYXRlVGlja0xhYmVscyh0aWNrcykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB0aWNrT3B0cyA9IG1lLm9wdGlvbnMudGlja3M7XG4gICAgbGV0IGksIGlsZW4sIHRpY2s7XG4gICAgZm9yIChpID0gMCwgaWxlbiA9IHRpY2tzLmxlbmd0aDsgaSA8IGlsZW47IGkrKykge1xuICAgICAgdGljayA9IHRpY2tzW2ldO1xuICAgICAgdGljay5sYWJlbCA9IGNhbGxiYWNrKHRpY2tPcHRzLmNhbGxiYWNrLCBbdGljay52YWx1ZSwgaSwgdGlja3NdLCBtZSk7XG4gICAgfVxuICB9XG4gIGFmdGVyVGlja1RvTGFiZWxDb252ZXJzaW9uKCkge1xuICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlclRpY2tUb0xhYmVsQ29udmVyc2lvbiwgW3RoaXNdKTtcbiAgfVxuICBiZWZvcmVDYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCkge1xuICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5iZWZvcmVDYWxjdWxhdGVMYWJlbFJvdGF0aW9uLCBbdGhpc10pO1xuICB9XG4gIGNhbGN1bGF0ZUxhYmVsUm90YXRpb24oKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IHRpY2tPcHRzID0gb3B0aW9ucy50aWNrcztcbiAgICBjb25zdCBudW1UaWNrcyA9IG1lLnRpY2tzLmxlbmd0aDtcbiAgICBjb25zdCBtaW5Sb3RhdGlvbiA9IHRpY2tPcHRzLm1pblJvdGF0aW9uIHx8IDA7XG4gICAgY29uc3QgbWF4Um90YXRpb24gPSB0aWNrT3B0cy5tYXhSb3RhdGlvbjtcbiAgICBsZXQgbGFiZWxSb3RhdGlvbiA9IG1pblJvdGF0aW9uO1xuICAgIGxldCB0aWNrV2lkdGgsIG1heEhlaWdodCwgbWF4TGFiZWxEaWFnb25hbDtcbiAgICBpZiAoIW1lLl9pc1Zpc2libGUoKSB8fCAhdGlja09wdHMuZGlzcGxheSB8fCBtaW5Sb3RhdGlvbiA+PSBtYXhSb3RhdGlvbiB8fCBudW1UaWNrcyA8PSAxIHx8ICFtZS5pc0hvcml6b250YWwoKSkge1xuICAgICAgbWUubGFiZWxSb3RhdGlvbiA9IG1pblJvdGF0aW9uO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBsYWJlbFNpemVzID0gbWUuX2dldExhYmVsU2l6ZXMoKTtcbiAgICBjb25zdCBtYXhMYWJlbFdpZHRoID0gbGFiZWxTaXplcy53aWRlc3Qud2lkdGg7XG4gICAgY29uc3QgbWF4TGFiZWxIZWlnaHQgPSBsYWJlbFNpemVzLmhpZ2hlc3QuaGVpZ2h0O1xuICAgIGNvbnN0IG1heFdpZHRoID0gX2xpbWl0VmFsdWUobWUuY2hhcnQud2lkdGggLSBtYXhMYWJlbFdpZHRoLCAwLCBtZS5tYXhXaWR0aCk7XG4gICAgdGlja1dpZHRoID0gb3B0aW9ucy5vZmZzZXQgPyBtZS5tYXhXaWR0aCAvIG51bVRpY2tzIDogbWF4V2lkdGggLyAobnVtVGlja3MgLSAxKTtcbiAgICBpZiAobWF4TGFiZWxXaWR0aCArIDYgPiB0aWNrV2lkdGgpIHtcbiAgICAgIHRpY2tXaWR0aCA9IG1heFdpZHRoIC8gKG51bVRpY2tzIC0gKG9wdGlvbnMub2Zmc2V0ID8gMC41IDogMSkpO1xuICAgICAgbWF4SGVpZ2h0ID0gbWUubWF4SGVpZ2h0IC0gZ2V0VGlja01hcmtMZW5ndGgob3B0aW9ucy5ncmlkKVxuXHRcdFx0XHQtIHRpY2tPcHRzLnBhZGRpbmcgLSBnZXRUaXRsZUhlaWdodChvcHRpb25zLnRpdGxlLCBtZS5jaGFydC5vcHRpb25zLmZvbnQpO1xuICAgICAgbWF4TGFiZWxEaWFnb25hbCA9IE1hdGguc3FydChtYXhMYWJlbFdpZHRoICogbWF4TGFiZWxXaWR0aCArIG1heExhYmVsSGVpZ2h0ICogbWF4TGFiZWxIZWlnaHQpO1xuICAgICAgbGFiZWxSb3RhdGlvbiA9IHRvRGVncmVlcyhNYXRoLm1pbihcbiAgICAgICAgTWF0aC5hc2luKF9saW1pdFZhbHVlKChsYWJlbFNpemVzLmhpZ2hlc3QuaGVpZ2h0ICsgNikgLyB0aWNrV2lkdGgsIC0xLCAxKSksXG4gICAgICAgIE1hdGguYXNpbihfbGltaXRWYWx1ZShtYXhIZWlnaHQgLyBtYXhMYWJlbERpYWdvbmFsLCAtMSwgMSkpIC0gTWF0aC5hc2luKF9saW1pdFZhbHVlKG1heExhYmVsSGVpZ2h0IC8gbWF4TGFiZWxEaWFnb25hbCwgLTEsIDEpKVxuICAgICAgKSk7XG4gICAgICBsYWJlbFJvdGF0aW9uID0gTWF0aC5tYXgobWluUm90YXRpb24sIE1hdGgubWluKG1heFJvdGF0aW9uLCBsYWJlbFJvdGF0aW9uKSk7XG4gICAgfVxuICAgIG1lLmxhYmVsUm90YXRpb24gPSBsYWJlbFJvdGF0aW9uO1xuICB9XG4gIGFmdGVyQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpIHtcbiAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYWZ0ZXJDYWxjdWxhdGVMYWJlbFJvdGF0aW9uLCBbdGhpc10pO1xuICB9XG4gIGJlZm9yZUZpdCgpIHtcbiAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlRml0LCBbdGhpc10pO1xuICB9XG4gIGZpdCgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbWluU2l6ZSA9IHtcbiAgICAgIHdpZHRoOiAwLFxuICAgICAgaGVpZ2h0OiAwXG4gICAgfTtcbiAgICBjb25zdCB7Y2hhcnQsIG9wdGlvbnM6IHt0aWNrczogdGlja09wdHMsIHRpdGxlOiB0aXRsZU9wdHMsIGdyaWQ6IGdyaWRPcHRzfX0gPSBtZTtcbiAgICBjb25zdCBkaXNwbGF5ID0gbWUuX2lzVmlzaWJsZSgpO1xuICAgIGNvbnN0IGlzSG9yaXpvbnRhbCA9IG1lLmlzSG9yaXpvbnRhbCgpO1xuICAgIGlmIChkaXNwbGF5KSB7XG4gICAgICBjb25zdCB0aXRsZUhlaWdodCA9IGdldFRpdGxlSGVpZ2h0KHRpdGxlT3B0cywgY2hhcnQub3B0aW9ucy5mb250KTtcbiAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgbWluU2l6ZS53aWR0aCA9IG1lLm1heFdpZHRoO1xuICAgICAgICBtaW5TaXplLmhlaWdodCA9IGdldFRpY2tNYXJrTGVuZ3RoKGdyaWRPcHRzKSArIHRpdGxlSGVpZ2h0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWluU2l6ZS5oZWlnaHQgPSBtZS5tYXhIZWlnaHQ7XG4gICAgICAgIG1pblNpemUud2lkdGggPSBnZXRUaWNrTWFya0xlbmd0aChncmlkT3B0cykgKyB0aXRsZUhlaWdodDtcbiAgICAgIH1cbiAgICAgIGlmICh0aWNrT3B0cy5kaXNwbGF5ICYmIG1lLnRpY2tzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCB7Zmlyc3QsIGxhc3QsIHdpZGVzdCwgaGlnaGVzdH0gPSBtZS5fZ2V0TGFiZWxTaXplcygpO1xuICAgICAgICBjb25zdCB0aWNrUGFkZGluZyA9IHRpY2tPcHRzLnBhZGRpbmcgKiAyO1xuICAgICAgICBjb25zdCBhbmdsZVJhZGlhbnMgPSB0b1JhZGlhbnMobWUubGFiZWxSb3RhdGlvbik7XG4gICAgICAgIGNvbnN0IGNvcyA9IE1hdGguY29zKGFuZ2xlUmFkaWFucyk7XG4gICAgICAgIGNvbnN0IHNpbiA9IE1hdGguc2luKGFuZ2xlUmFkaWFucyk7XG4gICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICBjb25zdCBsYWJlbEhlaWdodCA9IHRpY2tPcHRzLm1pcnJvciA/IDAgOiBzaW4gKiB3aWRlc3Qud2lkdGggKyBjb3MgKiBoaWdoZXN0LmhlaWdodDtcbiAgICAgICAgICBtaW5TaXplLmhlaWdodCA9IE1hdGgubWluKG1lLm1heEhlaWdodCwgbWluU2l6ZS5oZWlnaHQgKyBsYWJlbEhlaWdodCArIHRpY2tQYWRkaW5nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBsYWJlbFdpZHRoID0gdGlja09wdHMubWlycm9yID8gMCA6IGNvcyAqIHdpZGVzdC53aWR0aCArIHNpbiAqIGhpZ2hlc3QuaGVpZ2h0O1xuICAgICAgICAgIG1pblNpemUud2lkdGggPSBNYXRoLm1pbihtZS5tYXhXaWR0aCwgbWluU2l6ZS53aWR0aCArIGxhYmVsV2lkdGggKyB0aWNrUGFkZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgbWUuX2NhbGN1bGF0ZVBhZGRpbmcoZmlyc3QsIGxhc3QsIHNpbiwgY29zKTtcbiAgICAgIH1cbiAgICB9XG4gICAgbWUuX2hhbmRsZU1hcmdpbnMoKTtcbiAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICBtZS53aWR0aCA9IG1lLl9sZW5ndGggPSBjaGFydC53aWR0aCAtIG1lLl9tYXJnaW5zLmxlZnQgLSBtZS5fbWFyZ2lucy5yaWdodDtcbiAgICAgIG1lLmhlaWdodCA9IG1pblNpemUuaGVpZ2h0O1xuICAgIH0gZWxzZSB7XG4gICAgICBtZS53aWR0aCA9IG1pblNpemUud2lkdGg7XG4gICAgICBtZS5oZWlnaHQgPSBtZS5fbGVuZ3RoID0gY2hhcnQuaGVpZ2h0IC0gbWUuX21hcmdpbnMudG9wIC0gbWUuX21hcmdpbnMuYm90dG9tO1xuICAgIH1cbiAgfVxuICBfY2FsY3VsYXRlUGFkZGluZyhmaXJzdCwgbGFzdCwgc2luLCBjb3MpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge3RpY2tzOiB7YWxpZ24sIHBhZGRpbmd9LCBwb3NpdGlvbn0gPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IGlzUm90YXRlZCA9IG1lLmxhYmVsUm90YXRpb24gIT09IDA7XG4gICAgY29uc3QgbGFiZWxzQmVsb3dUaWNrcyA9IHBvc2l0aW9uICE9PSAndG9wJyAmJiBtZS5heGlzID09PSAneCc7XG4gICAgaWYgKG1lLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICBjb25zdCBvZmZzZXRMZWZ0ID0gbWUuZ2V0UGl4ZWxGb3JUaWNrKDApIC0gbWUubGVmdDtcbiAgICAgIGNvbnN0IG9mZnNldFJpZ2h0ID0gbWUucmlnaHQgLSBtZS5nZXRQaXhlbEZvclRpY2sobWUudGlja3MubGVuZ3RoIC0gMSk7XG4gICAgICBsZXQgcGFkZGluZ0xlZnQgPSAwO1xuICAgICAgbGV0IHBhZGRpbmdSaWdodCA9IDA7XG4gICAgICBpZiAoaXNSb3RhdGVkKSB7XG4gICAgICAgIGlmIChsYWJlbHNCZWxvd1RpY2tzKSB7XG4gICAgICAgICAgcGFkZGluZ0xlZnQgPSBjb3MgKiBmaXJzdC53aWR0aDtcbiAgICAgICAgICBwYWRkaW5nUmlnaHQgPSBzaW4gKiBsYXN0LmhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYWRkaW5nTGVmdCA9IHNpbiAqIGZpcnN0LmhlaWdodDtcbiAgICAgICAgICBwYWRkaW5nUmlnaHQgPSBjb3MgKiBsYXN0LndpZHRoO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGFsaWduID09PSAnc3RhcnQnKSB7XG4gICAgICAgIHBhZGRpbmdSaWdodCA9IGxhc3Qud2lkdGg7XG4gICAgICB9IGVsc2UgaWYgKGFsaWduID09PSAnZW5kJykge1xuICAgICAgICBwYWRkaW5nTGVmdCA9IGZpcnN0LndpZHRoO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFkZGluZ0xlZnQgPSBmaXJzdC53aWR0aCAvIDI7XG4gICAgICAgIHBhZGRpbmdSaWdodCA9IGxhc3Qud2lkdGggLyAyO1xuICAgICAgfVxuICAgICAgbWUucGFkZGluZ0xlZnQgPSBNYXRoLm1heCgocGFkZGluZ0xlZnQgLSBvZmZzZXRMZWZ0ICsgcGFkZGluZykgKiBtZS53aWR0aCAvIChtZS53aWR0aCAtIG9mZnNldExlZnQpLCAwKTtcbiAgICAgIG1lLnBhZGRpbmdSaWdodCA9IE1hdGgubWF4KChwYWRkaW5nUmlnaHQgLSBvZmZzZXRSaWdodCArIHBhZGRpbmcpICogbWUud2lkdGggLyAobWUud2lkdGggLSBvZmZzZXRSaWdodCksIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGFkZGluZ1RvcCA9IGxhc3QuaGVpZ2h0IC8gMjtcbiAgICAgIGxldCBwYWRkaW5nQm90dG9tID0gZmlyc3QuaGVpZ2h0IC8gMjtcbiAgICAgIGlmIChhbGlnbiA9PT0gJ3N0YXJ0Jykge1xuICAgICAgICBwYWRkaW5nVG9wID0gMDtcbiAgICAgICAgcGFkZGluZ0JvdHRvbSA9IGZpcnN0LmhlaWdodDtcbiAgICAgIH0gZWxzZSBpZiAoYWxpZ24gPT09ICdlbmQnKSB7XG4gICAgICAgIHBhZGRpbmdUb3AgPSBsYXN0LmhlaWdodDtcbiAgICAgICAgcGFkZGluZ0JvdHRvbSA9IDA7XG4gICAgICB9XG4gICAgICBtZS5wYWRkaW5nVG9wID0gcGFkZGluZ1RvcCArIHBhZGRpbmc7XG4gICAgICBtZS5wYWRkaW5nQm90dG9tID0gcGFkZGluZ0JvdHRvbSArIHBhZGRpbmc7XG4gICAgfVxuICB9XG4gIF9oYW5kbGVNYXJnaW5zKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBpZiAobWUuX21hcmdpbnMpIHtcbiAgICAgIG1lLl9tYXJnaW5zLmxlZnQgPSBNYXRoLm1heChtZS5wYWRkaW5nTGVmdCwgbWUuX21hcmdpbnMubGVmdCk7XG4gICAgICBtZS5fbWFyZ2lucy50b3AgPSBNYXRoLm1heChtZS5wYWRkaW5nVG9wLCBtZS5fbWFyZ2lucy50b3ApO1xuICAgICAgbWUuX21hcmdpbnMucmlnaHQgPSBNYXRoLm1heChtZS5wYWRkaW5nUmlnaHQsIG1lLl9tYXJnaW5zLnJpZ2h0KTtcbiAgICAgIG1lLl9tYXJnaW5zLmJvdHRvbSA9IE1hdGgubWF4KG1lLnBhZGRpbmdCb3R0b20sIG1lLl9tYXJnaW5zLmJvdHRvbSk7XG4gICAgfVxuICB9XG4gIGFmdGVyRml0KCkge1xuICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlckZpdCwgW3RoaXNdKTtcbiAgfVxuICBpc0hvcml6b250YWwoKSB7XG4gICAgY29uc3Qge2F4aXMsIHBvc2l0aW9ufSA9IHRoaXMub3B0aW9ucztcbiAgICByZXR1cm4gcG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJyB8fCBheGlzID09PSAneCc7XG4gIH1cbiAgaXNGdWxsU2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmZ1bGxTaXplO1xuICB9XG4gIF9jb252ZXJ0VGlja3NUb0xhYmVscyh0aWNrcykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBtZS5iZWZvcmVUaWNrVG9MYWJlbENvbnZlcnNpb24oKTtcbiAgICBtZS5nZW5lcmF0ZVRpY2tMYWJlbHModGlja3MpO1xuICAgIGxldCBpLCBpbGVuO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspIHtcbiAgICAgIGlmIChpc051bGxPclVuZGVmKHRpY2tzW2ldLmxhYmVsKSkge1xuICAgICAgICB0aWNrcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIGlsZW4tLTtcbiAgICAgICAgaS0tO1xuICAgICAgfVxuICAgIH1cbiAgICBtZS5hZnRlclRpY2tUb0xhYmVsQ29udmVyc2lvbigpO1xuICB9XG4gIF9nZXRMYWJlbFNpemVzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBsZXQgbGFiZWxTaXplcyA9IG1lLl9sYWJlbFNpemVzO1xuICAgIGlmICghbGFiZWxTaXplcykge1xuICAgICAgY29uc3Qgc2FtcGxlU2l6ZSA9IG1lLm9wdGlvbnMudGlja3Muc2FtcGxlU2l6ZTtcbiAgICAgIGxldCB0aWNrcyA9IG1lLnRpY2tzO1xuICAgICAgaWYgKHNhbXBsZVNpemUgPCB0aWNrcy5sZW5ndGgpIHtcbiAgICAgICAgdGlja3MgPSBzYW1wbGUodGlja3MsIHNhbXBsZVNpemUpO1xuICAgICAgfVxuICAgICAgbWUuX2xhYmVsU2l6ZXMgPSBsYWJlbFNpemVzID0gbWUuX2NvbXB1dGVMYWJlbFNpemVzKHRpY2tzLCB0aWNrcy5sZW5ndGgpO1xuICAgIH1cbiAgICByZXR1cm4gbGFiZWxTaXplcztcbiAgfVxuICBfY29tcHV0ZUxhYmVsU2l6ZXModGlja3MsIGxlbmd0aCkge1xuICAgIGNvbnN0IHtjdHgsIF9sb25nZXN0VGV4dENhY2hlOiBjYWNoZXN9ID0gdGhpcztcbiAgICBjb25zdCB3aWR0aHMgPSBbXTtcbiAgICBjb25zdCBoZWlnaHRzID0gW107XG4gICAgbGV0IHdpZGVzdExhYmVsU2l6ZSA9IDA7XG4gICAgbGV0IGhpZ2hlc3RMYWJlbFNpemUgPSAwO1xuICAgIGxldCBpLCBqLCBqbGVuLCBsYWJlbCwgdGlja0ZvbnQsIGZvbnRTdHJpbmcsIGNhY2hlLCBsaW5lSGVpZ2h0LCB3aWR0aCwgaGVpZ2h0LCBuZXN0ZWRMYWJlbDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICAgIGxhYmVsID0gdGlja3NbaV0ubGFiZWw7XG4gICAgICB0aWNrRm9udCA9IHRoaXMuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoaSk7XG4gICAgICBjdHguZm9udCA9IGZvbnRTdHJpbmcgPSB0aWNrRm9udC5zdHJpbmc7XG4gICAgICBjYWNoZSA9IGNhY2hlc1tmb250U3RyaW5nXSA9IGNhY2hlc1tmb250U3RyaW5nXSB8fCB7ZGF0YToge30sIGdjOiBbXX07XG4gICAgICBsaW5lSGVpZ2h0ID0gdGlja0ZvbnQubGluZUhlaWdodDtcbiAgICAgIHdpZHRoID0gaGVpZ2h0ID0gMDtcbiAgICAgIGlmICghaXNOdWxsT3JVbmRlZihsYWJlbCkgJiYgIWlzQXJyYXkobGFiZWwpKSB7XG4gICAgICAgIHdpZHRoID0gX21lYXN1cmVUZXh0KGN0eCwgY2FjaGUuZGF0YSwgY2FjaGUuZ2MsIHdpZHRoLCBsYWJlbCk7XG4gICAgICAgIGhlaWdodCA9IGxpbmVIZWlnaHQ7XG4gICAgICB9IGVsc2UgaWYgKGlzQXJyYXkobGFiZWwpKSB7XG4gICAgICAgIGZvciAoaiA9IDAsIGpsZW4gPSBsYWJlbC5sZW5ndGg7IGogPCBqbGVuOyArK2opIHtcbiAgICAgICAgICBuZXN0ZWRMYWJlbCA9IGxhYmVsW2pdO1xuICAgICAgICAgIGlmICghaXNOdWxsT3JVbmRlZihuZXN0ZWRMYWJlbCkgJiYgIWlzQXJyYXkobmVzdGVkTGFiZWwpKSB7XG4gICAgICAgICAgICB3aWR0aCA9IF9tZWFzdXJlVGV4dChjdHgsIGNhY2hlLmRhdGEsIGNhY2hlLmdjLCB3aWR0aCwgbmVzdGVkTGFiZWwpO1xuICAgICAgICAgICAgaGVpZ2h0ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aWR0aHMucHVzaCh3aWR0aCk7XG4gICAgICBoZWlnaHRzLnB1c2goaGVpZ2h0KTtcbiAgICAgIHdpZGVzdExhYmVsU2l6ZSA9IE1hdGgubWF4KHdpZHRoLCB3aWRlc3RMYWJlbFNpemUpO1xuICAgICAgaGlnaGVzdExhYmVsU2l6ZSA9IE1hdGgubWF4KGhlaWdodCwgaGlnaGVzdExhYmVsU2l6ZSk7XG4gICAgfVxuICAgIGdhcmJhZ2VDb2xsZWN0KGNhY2hlcywgbGVuZ3RoKTtcbiAgICBjb25zdCB3aWRlc3QgPSB3aWR0aHMuaW5kZXhPZih3aWRlc3RMYWJlbFNpemUpO1xuICAgIGNvbnN0IGhpZ2hlc3QgPSBoZWlnaHRzLmluZGV4T2YoaGlnaGVzdExhYmVsU2l6ZSk7XG4gICAgY29uc3QgdmFsdWVBdCA9IChpZHgpID0+ICh7d2lkdGg6IHdpZHRoc1tpZHhdIHx8IDAsIGhlaWdodDogaGVpZ2h0c1tpZHhdIHx8IDB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgZmlyc3Q6IHZhbHVlQXQoMCksXG4gICAgICBsYXN0OiB2YWx1ZUF0KGxlbmd0aCAtIDEpLFxuICAgICAgd2lkZXN0OiB2YWx1ZUF0KHdpZGVzdCksXG4gICAgICBoaWdoZXN0OiB2YWx1ZUF0KGhpZ2hlc3QpLFxuICAgICAgd2lkdGhzLFxuICAgICAgaGVpZ2h0cyxcbiAgICB9O1xuICB9XG4gIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSwgaW5kZXgpIHtcbiAgICByZXR1cm4gTmFOO1xuICB9XG4gIGdldFZhbHVlRm9yUGl4ZWwocGl4ZWwpIHt9XG4gIGdldFBpeGVsRm9yVGljayhpbmRleCkge1xuICAgIGNvbnN0IHRpY2tzID0gdGhpcy50aWNrcztcbiAgICBpZiAoaW5kZXggPCAwIHx8IGluZGV4ID4gdGlja3MubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldFBpeGVsRm9yVmFsdWUodGlja3NbaW5kZXhdLnZhbHVlKTtcbiAgfVxuICBnZXRQaXhlbEZvckRlY2ltYWwoZGVjaW1hbCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBpZiAobWUuX3JldmVyc2VQaXhlbHMpIHtcbiAgICAgIGRlY2ltYWwgPSAxIC0gZGVjaW1hbDtcbiAgICB9XG4gICAgY29uc3QgcGl4ZWwgPSBtZS5fc3RhcnRQaXhlbCArIGRlY2ltYWwgKiBtZS5fbGVuZ3RoO1xuICAgIHJldHVybiBfaW50MTZSYW5nZShtZS5fYWxpZ25Ub1BpeGVscyA/IF9hbGlnblBpeGVsKG1lLmNoYXJ0LCBwaXhlbCwgMCkgOiBwaXhlbCk7XG4gIH1cbiAgZ2V0RGVjaW1hbEZvclBpeGVsKHBpeGVsKSB7XG4gICAgY29uc3QgZGVjaW1hbCA9IChwaXhlbCAtIHRoaXMuX3N0YXJ0UGl4ZWwpIC8gdGhpcy5fbGVuZ3RoO1xuICAgIHJldHVybiB0aGlzLl9yZXZlcnNlUGl4ZWxzID8gMSAtIGRlY2ltYWwgOiBkZWNpbWFsO1xuICB9XG4gIGdldEJhc2VQaXhlbCgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRQaXhlbEZvclZhbHVlKHRoaXMuZ2V0QmFzZVZhbHVlKCkpO1xuICB9XG4gIGdldEJhc2VWYWx1ZSgpIHtcbiAgICBjb25zdCB7bWluLCBtYXh9ID0gdGhpcztcbiAgICByZXR1cm4gbWluIDwgMCAmJiBtYXggPCAwID8gbWF4IDpcbiAgICAgIG1pbiA+IDAgJiYgbWF4ID4gMCA/IG1pbiA6XG4gICAgICAwO1xuICB9XG4gIGdldENvbnRleHQoaW5kZXgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgdGlja3MgPSBtZS50aWNrcyB8fCBbXTtcbiAgICBpZiAoaW5kZXggPj0gMCAmJiBpbmRleCA8IHRpY2tzLmxlbmd0aCkge1xuICAgICAgY29uc3QgdGljayA9IHRpY2tzW2luZGV4XTtcbiAgICAgIHJldHVybiB0aWNrLiRjb250ZXh0IHx8XG5cdFx0XHRcdCh0aWNrLiRjb250ZXh0ID0gY3JlYXRlVGlja0NvbnRleHQobWUuZ2V0Q29udGV4dCgpLCBpbmRleCwgdGljaykpO1xuICAgIH1cbiAgICByZXR1cm4gbWUuJGNvbnRleHQgfHxcblx0XHRcdChtZS4kY29udGV4dCA9IGNyZWF0ZVNjYWxlQ29udGV4dChtZS5jaGFydC5nZXRDb250ZXh0KCksIG1lKSk7XG4gIH1cbiAgX3RpY2tTaXplKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRpb25UaWNrcyA9IG1lLm9wdGlvbnMudGlja3M7XG4gICAgY29uc3Qgcm90ID0gdG9SYWRpYW5zKG1lLmxhYmVsUm90YXRpb24pO1xuICAgIGNvbnN0IGNvcyA9IE1hdGguYWJzKE1hdGguY29zKHJvdCkpO1xuICAgIGNvbnN0IHNpbiA9IE1hdGguYWJzKE1hdGguc2luKHJvdCkpO1xuICAgIGNvbnN0IGxhYmVsU2l6ZXMgPSBtZS5fZ2V0TGFiZWxTaXplcygpO1xuICAgIGNvbnN0IHBhZGRpbmcgPSBvcHRpb25UaWNrcy5hdXRvU2tpcFBhZGRpbmcgfHwgMDtcbiAgICBjb25zdCB3ID0gbGFiZWxTaXplcyA/IGxhYmVsU2l6ZXMud2lkZXN0LndpZHRoICsgcGFkZGluZyA6IDA7XG4gICAgY29uc3QgaCA9IGxhYmVsU2l6ZXMgPyBsYWJlbFNpemVzLmhpZ2hlc3QuaGVpZ2h0ICsgcGFkZGluZyA6IDA7XG4gICAgcmV0dXJuIG1lLmlzSG9yaXpvbnRhbCgpXG4gICAgICA/IGggKiBjb3MgPiB3ICogc2luID8gdyAvIGNvcyA6IGggLyBzaW5cbiAgICAgIDogaCAqIHNpbiA8IHcgKiBjb3MgPyBoIC8gY29zIDogdyAvIHNpbjtcbiAgfVxuICBfaXNWaXNpYmxlKCkge1xuICAgIGNvbnN0IGRpc3BsYXkgPSB0aGlzLm9wdGlvbnMuZGlzcGxheTtcbiAgICBpZiAoZGlzcGxheSAhPT0gJ2F1dG8nKSB7XG4gICAgICByZXR1cm4gISFkaXNwbGF5O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5nZXRNYXRjaGluZ1Zpc2libGVNZXRhcygpLmxlbmd0aCA+IDA7XG4gIH1cbiAgX2NvbXB1dGVHcmlkTGluZUl0ZW1zKGNoYXJ0QXJlYSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBheGlzID0gbWUuYXhpcztcbiAgICBjb25zdCBjaGFydCA9IG1lLmNoYXJ0O1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IHtncmlkLCBwb3NpdGlvbn0gPSBvcHRpb25zO1xuICAgIGNvbnN0IG9mZnNldCA9IGdyaWQub2Zmc2V0O1xuICAgIGNvbnN0IGlzSG9yaXpvbnRhbCA9IG1lLmlzSG9yaXpvbnRhbCgpO1xuICAgIGNvbnN0IHRpY2tzID0gbWUudGlja3M7XG4gICAgY29uc3QgdGlja3NMZW5ndGggPSB0aWNrcy5sZW5ndGggKyAob2Zmc2V0ID8gMSA6IDApO1xuICAgIGNvbnN0IHRsID0gZ2V0VGlja01hcmtMZW5ndGgoZ3JpZCk7XG4gICAgY29uc3QgaXRlbXMgPSBbXTtcbiAgICBjb25zdCBib3JkZXJPcHRzID0gZ3JpZC5zZXRDb250ZXh0KG1lLmdldENvbnRleHQoKSk7XG4gICAgY29uc3QgYXhpc1dpZHRoID0gYm9yZGVyT3B0cy5kcmF3Qm9yZGVyID8gYm9yZGVyT3B0cy5ib3JkZXJXaWR0aCA6IDA7XG4gICAgY29uc3QgYXhpc0hhbGZXaWR0aCA9IGF4aXNXaWR0aCAvIDI7XG4gICAgY29uc3QgYWxpZ25Cb3JkZXJWYWx1ZSA9IGZ1bmN0aW9uKHBpeGVsKSB7XG4gICAgICByZXR1cm4gX2FsaWduUGl4ZWwoY2hhcnQsIHBpeGVsLCBheGlzV2lkdGgpO1xuICAgIH07XG4gICAgbGV0IGJvcmRlclZhbHVlLCBpLCBsaW5lVmFsdWUsIGFsaWduZWRMaW5lVmFsdWU7XG4gICAgbGV0IHR4MSwgdHkxLCB0eDIsIHR5MiwgeDEsIHkxLCB4MiwgeTI7XG4gICAgaWYgKHBvc2l0aW9uID09PSAndG9wJykge1xuICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKG1lLmJvdHRvbSk7XG4gICAgICB0eTEgPSBtZS5ib3R0b20gLSB0bDtcbiAgICAgIHR5MiA9IGJvcmRlclZhbHVlIC0gYXhpc0hhbGZXaWR0aDtcbiAgICAgIHkxID0gYWxpZ25Cb3JkZXJWYWx1ZShjaGFydEFyZWEudG9wKSArIGF4aXNIYWxmV2lkdGg7XG4gICAgICB5MiA9IGNoYXJ0QXJlYS5ib3R0b207XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZShtZS50b3ApO1xuICAgICAgeTEgPSBjaGFydEFyZWEudG9wO1xuICAgICAgeTIgPSBhbGlnbkJvcmRlclZhbHVlKGNoYXJ0QXJlYS5ib3R0b20pIC0gYXhpc0hhbGZXaWR0aDtcbiAgICAgIHR5MSA9IGJvcmRlclZhbHVlICsgYXhpc0hhbGZXaWR0aDtcbiAgICAgIHR5MiA9IG1lLnRvcCArIHRsO1xuICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdsZWZ0Jykge1xuICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKG1lLnJpZ2h0KTtcbiAgICAgIHR4MSA9IG1lLnJpZ2h0IC0gdGw7XG4gICAgICB0eDIgPSBib3JkZXJWYWx1ZSAtIGF4aXNIYWxmV2lkdGg7XG4gICAgICB4MSA9IGFsaWduQm9yZGVyVmFsdWUoY2hhcnRBcmVhLmxlZnQpICsgYXhpc0hhbGZXaWR0aDtcbiAgICAgIHgyID0gY2hhcnRBcmVhLnJpZ2h0O1xuICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZShtZS5sZWZ0KTtcbiAgICAgIHgxID0gY2hhcnRBcmVhLmxlZnQ7XG4gICAgICB4MiA9IGFsaWduQm9yZGVyVmFsdWUoY2hhcnRBcmVhLnJpZ2h0KSAtIGF4aXNIYWxmV2lkdGg7XG4gICAgICB0eDEgPSBib3JkZXJWYWx1ZSArIGF4aXNIYWxmV2lkdGg7XG4gICAgICB0eDIgPSBtZS5sZWZ0ICsgdGw7XG4gICAgfSBlbHNlIGlmIChheGlzID09PSAneCcpIHtcbiAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKChjaGFydEFyZWEudG9wICsgY2hhcnRBcmVhLmJvdHRvbSkgLyAyICsgMC41KTtcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocG9zaXRpb24pKSB7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW3Bvc2l0aW9uQXhpc0lEXTtcbiAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKG1lLmNoYXJ0LnNjYWxlc1twb3NpdGlvbkF4aXNJRF0uZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkpO1xuICAgICAgfVxuICAgICAgeTEgPSBjaGFydEFyZWEudG9wO1xuICAgICAgeTIgPSBjaGFydEFyZWEuYm90dG9tO1xuICAgICAgdHkxID0gYm9yZGVyVmFsdWUgKyBheGlzSGFsZldpZHRoO1xuICAgICAgdHkyID0gdHkxICsgdGw7XG4gICAgfSBlbHNlIGlmIChheGlzID09PSAneScpIHtcbiAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKChjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS5yaWdodCkgLyAyKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocG9zaXRpb24pKSB7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW3Bvc2l0aW9uQXhpc0lEXTtcbiAgICAgICAgYm9yZGVyVmFsdWUgPSBhbGlnbkJvcmRlclZhbHVlKG1lLmNoYXJ0LnNjYWxlc1twb3NpdGlvbkF4aXNJRF0uZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkpO1xuICAgICAgfVxuICAgICAgdHgxID0gYm9yZGVyVmFsdWUgLSBheGlzSGFsZldpZHRoO1xuICAgICAgdHgyID0gdHgxIC0gdGw7XG4gICAgICB4MSA9IGNoYXJ0QXJlYS5sZWZ0O1xuICAgICAgeDIgPSBjaGFydEFyZWEucmlnaHQ7XG4gICAgfVxuICAgIGNvbnN0IGxpbWl0ID0gdmFsdWVPckRlZmF1bHQob3B0aW9ucy50aWNrcy5tYXhUaWNrc0xpbWl0LCB0aWNrc0xlbmd0aCk7XG4gICAgY29uc3Qgc3RlcCA9IE1hdGgubWF4KDEsIE1hdGguY2VpbCh0aWNrc0xlbmd0aCAvIGxpbWl0KSk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRpY2tzTGVuZ3RoOyBpICs9IHN0ZXApIHtcbiAgICAgIGNvbnN0IG9wdHNBdEluZGV4ID0gZ3JpZC5zZXRDb250ZXh0KG1lLmdldENvbnRleHQoaSkpO1xuICAgICAgY29uc3QgbGluZVdpZHRoID0gb3B0c0F0SW5kZXgubGluZVdpZHRoO1xuICAgICAgY29uc3QgbGluZUNvbG9yID0gb3B0c0F0SW5kZXguY29sb3I7XG4gICAgICBjb25zdCBib3JkZXJEYXNoID0gZ3JpZC5ib3JkZXJEYXNoIHx8IFtdO1xuICAgICAgY29uc3QgYm9yZGVyRGFzaE9mZnNldCA9IG9wdHNBdEluZGV4LmJvcmRlckRhc2hPZmZzZXQ7XG4gICAgICBjb25zdCB0aWNrV2lkdGggPSBvcHRzQXRJbmRleC50aWNrV2lkdGg7XG4gICAgICBjb25zdCB0aWNrQ29sb3IgPSBvcHRzQXRJbmRleC50aWNrQ29sb3I7XG4gICAgICBjb25zdCB0aWNrQm9yZGVyRGFzaCA9IG9wdHNBdEluZGV4LnRpY2tCb3JkZXJEYXNoIHx8IFtdO1xuICAgICAgY29uc3QgdGlja0JvcmRlckRhc2hPZmZzZXQgPSBvcHRzQXRJbmRleC50aWNrQm9yZGVyRGFzaE9mZnNldDtcbiAgICAgIGxpbmVWYWx1ZSA9IGdldFBpeGVsRm9yR3JpZExpbmUobWUsIGksIG9mZnNldCk7XG4gICAgICBpZiAobGluZVZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBhbGlnbmVkTGluZVZhbHVlID0gX2FsaWduUGl4ZWwoY2hhcnQsIGxpbmVWYWx1ZSwgbGluZVdpZHRoKTtcbiAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgdHgxID0gdHgyID0geDEgPSB4MiA9IGFsaWduZWRMaW5lVmFsdWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0eTEgPSB0eTIgPSB5MSA9IHkyID0gYWxpZ25lZExpbmVWYWx1ZTtcbiAgICAgIH1cbiAgICAgIGl0ZW1zLnB1c2goe1xuICAgICAgICB0eDEsXG4gICAgICAgIHR5MSxcbiAgICAgICAgdHgyLFxuICAgICAgICB0eTIsXG4gICAgICAgIHgxLFxuICAgICAgICB5MSxcbiAgICAgICAgeDIsXG4gICAgICAgIHkyLFxuICAgICAgICB3aWR0aDogbGluZVdpZHRoLFxuICAgICAgICBjb2xvcjogbGluZUNvbG9yLFxuICAgICAgICBib3JkZXJEYXNoLFxuICAgICAgICBib3JkZXJEYXNoT2Zmc2V0LFxuICAgICAgICB0aWNrV2lkdGgsXG4gICAgICAgIHRpY2tDb2xvcixcbiAgICAgICAgdGlja0JvcmRlckRhc2gsXG4gICAgICAgIHRpY2tCb3JkZXJEYXNoT2Zmc2V0LFxuICAgICAgfSk7XG4gICAgfVxuICAgIG1lLl90aWNrc0xlbmd0aCA9IHRpY2tzTGVuZ3RoO1xuICAgIG1lLl9ib3JkZXJWYWx1ZSA9IGJvcmRlclZhbHVlO1xuICAgIHJldHVybiBpdGVtcztcbiAgfVxuICBfY29tcHV0ZUxhYmVsSXRlbXMoY2hhcnRBcmVhKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGF4aXMgPSBtZS5heGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IHtwb3NpdGlvbiwgdGlja3M6IG9wdGlvblRpY2tzfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgaXNIb3Jpem9udGFsID0gbWUuaXNIb3Jpem9udGFsKCk7XG4gICAgY29uc3QgdGlja3MgPSBtZS50aWNrcztcbiAgICBjb25zdCB7YWxpZ24sIGNyb3NzQWxpZ24sIHBhZGRpbmcsIG1pcnJvcn0gPSBvcHRpb25UaWNrcztcbiAgICBjb25zdCB0bCA9IGdldFRpY2tNYXJrTGVuZ3RoKG9wdGlvbnMuZ3JpZCk7XG4gICAgY29uc3QgdGlja0FuZFBhZGRpbmcgPSB0bCArIHBhZGRpbmc7XG4gICAgY29uc3QgaFRpY2tBbmRQYWRkaW5nID0gbWlycm9yID8gLXBhZGRpbmcgOiB0aWNrQW5kUGFkZGluZztcbiAgICBjb25zdCByb3RhdGlvbiA9IC10b1JhZGlhbnMobWUubGFiZWxSb3RhdGlvbik7XG4gICAgY29uc3QgaXRlbXMgPSBbXTtcbiAgICBsZXQgaSwgaWxlbiwgdGljaywgbGFiZWwsIHgsIHksIHRleHRBbGlnbiwgcGl4ZWwsIGZvbnQsIGxpbmVIZWlnaHQsIGxpbmVDb3VudCwgdGV4dE9mZnNldDtcbiAgICBsZXQgdGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgaWYgKHBvc2l0aW9uID09PSAndG9wJykge1xuICAgICAgeSA9IG1lLmJvdHRvbSAtIGhUaWNrQW5kUGFkZGluZztcbiAgICAgIHRleHRBbGlnbiA9IG1lLl9nZXRYQXhpc0xhYmVsQWxpZ25tZW50KCk7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIHkgPSBtZS50b3AgKyBoVGlja0FuZFBhZGRpbmc7XG4gICAgICB0ZXh0QWxpZ24gPSBtZS5fZ2V0WEF4aXNMYWJlbEFsaWdubWVudCgpO1xuICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdsZWZ0Jykge1xuICAgICAgY29uc3QgcmV0ID0gbWUuX2dldFlBeGlzTGFiZWxBbGlnbm1lbnQodGwpO1xuICAgICAgdGV4dEFsaWduID0gcmV0LnRleHRBbGlnbjtcbiAgICAgIHggPSByZXQueDtcbiAgICB9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAncmlnaHQnKSB7XG4gICAgICBjb25zdCByZXQgPSBtZS5fZ2V0WUF4aXNMYWJlbEFsaWdubWVudCh0bCk7XG4gICAgICB0ZXh0QWxpZ24gPSByZXQudGV4dEFsaWduO1xuICAgICAgeCA9IHJldC54O1xuICAgIH0gZWxzZSBpZiAoYXhpcyA9PT0gJ3gnKSB7XG4gICAgICBpZiAocG9zaXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgIHkgPSAoKGNoYXJ0QXJlYS50b3AgKyBjaGFydEFyZWEuYm90dG9tKSAvIDIpICsgdGlja0FuZFBhZGRpbmc7XG4gICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgICBjb25zdCBwb3NpdGlvbkF4aXNJRCA9IE9iamVjdC5rZXlzKHBvc2l0aW9uKVswXTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICAgIHkgPSBtZS5jaGFydC5zY2FsZXNbcG9zaXRpb25BeGlzSURdLmdldFBpeGVsRm9yVmFsdWUodmFsdWUpICsgdGlja0FuZFBhZGRpbmc7XG4gICAgICB9XG4gICAgICB0ZXh0QWxpZ24gPSBtZS5fZ2V0WEF4aXNMYWJlbEFsaWdubWVudCgpO1xuICAgIH0gZWxzZSBpZiAoYXhpcyA9PT0gJ3knKSB7XG4gICAgICBpZiAocG9zaXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgIHggPSAoKGNoYXJ0QXJlYS5sZWZ0ICsgY2hhcnRBcmVhLnJpZ2h0KSAvIDIpIC0gdGlja0FuZFBhZGRpbmc7XG4gICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgICBjb25zdCBwb3NpdGlvbkF4aXNJRCA9IE9iamVjdC5rZXlzKHBvc2l0aW9uKVswXTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICAgIHggPSBtZS5jaGFydC5zY2FsZXNbcG9zaXRpb25BeGlzSURdLmdldFBpeGVsRm9yVmFsdWUodmFsdWUpO1xuICAgICAgfVxuICAgICAgdGV4dEFsaWduID0gbWUuX2dldFlBeGlzTGFiZWxBbGlnbm1lbnQodGwpLnRleHRBbGlnbjtcbiAgICB9XG4gICAgaWYgKGF4aXMgPT09ICd5Jykge1xuICAgICAgaWYgKGFsaWduID09PSAnc3RhcnQnKSB7XG4gICAgICAgIHRleHRCYXNlbGluZSA9ICd0b3AnO1xuICAgICAgfSBlbHNlIGlmIChhbGlnbiA9PT0gJ2VuZCcpIHtcbiAgICAgICAgdGV4dEJhc2VsaW5lID0gJ2JvdHRvbSc7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGxhYmVsU2l6ZXMgPSBtZS5fZ2V0TGFiZWxTaXplcygpO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIHRpY2sgPSB0aWNrc1tpXTtcbiAgICAgIGxhYmVsID0gdGljay5sYWJlbDtcbiAgICAgIGNvbnN0IG9wdHNBdEluZGV4ID0gb3B0aW9uVGlja3Muc2V0Q29udGV4dChtZS5nZXRDb250ZXh0KGkpKTtcbiAgICAgIHBpeGVsID0gbWUuZ2V0UGl4ZWxGb3JUaWNrKGkpICsgb3B0aW9uVGlja3MubGFiZWxPZmZzZXQ7XG4gICAgICBmb250ID0gbWUuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoaSk7XG4gICAgICBsaW5lSGVpZ2h0ID0gZm9udC5saW5lSGVpZ2h0O1xuICAgICAgbGluZUNvdW50ID0gaXNBcnJheShsYWJlbCkgPyBsYWJlbC5sZW5ndGggOiAxO1xuICAgICAgY29uc3QgaGFsZkNvdW50ID0gbGluZUNvdW50IC8gMjtcbiAgICAgIGNvbnN0IGNvbG9yID0gb3B0c0F0SW5kZXguY29sb3I7XG4gICAgICBjb25zdCBzdHJva2VDb2xvciA9IG9wdHNBdEluZGV4LnRleHRTdHJva2VDb2xvcjtcbiAgICAgIGNvbnN0IHN0cm9rZVdpZHRoID0gb3B0c0F0SW5kZXgudGV4dFN0cm9rZVdpZHRoO1xuICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICB4ID0gcGl4ZWw7XG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInIHx8IHJvdGF0aW9uICE9PSAwKSB7XG4gICAgICAgICAgICB0ZXh0T2Zmc2V0ID0gLWxpbmVDb3VudCAqIGxpbmVIZWlnaHQgKyBsaW5lSGVpZ2h0IC8gMjtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNyb3NzQWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICB0ZXh0T2Zmc2V0ID0gLWxhYmVsU2l6ZXMuaGlnaGVzdC5oZWlnaHQgLyAyIC0gaGFsZkNvdW50ICogbGluZUhlaWdodCArIGxpbmVIZWlnaHQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRleHRPZmZzZXQgPSAtbGFiZWxTaXplcy5oaWdoZXN0LmhlaWdodCArIGxpbmVIZWlnaHQgLyAyO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInIHx8IHJvdGF0aW9uICE9PSAwKSB7XG4gICAgICAgICAgICB0ZXh0T2Zmc2V0ID0gbGluZUhlaWdodCAvIDI7XG4gICAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgdGV4dE9mZnNldCA9IGxhYmVsU2l6ZXMuaGlnaGVzdC5oZWlnaHQgLyAyIC0gaGFsZkNvdW50ICogbGluZUhlaWdodDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGV4dE9mZnNldCA9IGxhYmVsU2l6ZXMuaGlnaGVzdC5oZWlnaHQgLSBsaW5lQ291bnQgKiBsaW5lSGVpZ2h0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobWlycm9yKSB7XG4gICAgICAgICAgdGV4dE9mZnNldCAqPSAtMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeSA9IHBpeGVsO1xuICAgICAgICB0ZXh0T2Zmc2V0ID0gKDEgLSBsaW5lQ291bnQpICogbGluZUhlaWdodCAvIDI7XG4gICAgICB9XG4gICAgICBsZXQgYmFja2Ryb3A7XG4gICAgICBpZiAob3B0c0F0SW5kZXguc2hvd0xhYmVsQmFja2Ryb3ApIHtcbiAgICAgICAgY29uc3QgbGFiZWxQYWRkaW5nID0gdG9QYWRkaW5nKG9wdHNBdEluZGV4LmJhY2tkcm9wUGFkZGluZyk7XG4gICAgICAgIGNvbnN0IGhlaWdodCA9IGxhYmVsU2l6ZXMuaGVpZ2h0c1tpXTtcbiAgICAgICAgY29uc3Qgd2lkdGggPSBsYWJlbFNpemVzLndpZHRoc1tpXTtcbiAgICAgICAgbGV0IHRvcCA9IHkgKyB0ZXh0T2Zmc2V0IC0gbGFiZWxQYWRkaW5nLnRvcDtcbiAgICAgICAgbGV0IGxlZnQgPSB4IC0gbGFiZWxQYWRkaW5nLmxlZnQ7XG4gICAgICAgIHN3aXRjaCAodGV4dEJhc2VsaW5lKSB7XG4gICAgICAgIGNhc2UgJ21pZGRsZSc6XG4gICAgICAgICAgdG9wIC09IGhlaWdodCAvIDI7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgICAgdG9wIC09IGhlaWdodDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKHRleHRBbGlnbikge1xuICAgICAgICBjYXNlICdjZW50ZXInOlxuICAgICAgICAgIGxlZnQgLT0gd2lkdGggLyAyO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBiYWNrZHJvcCA9IHtcbiAgICAgICAgICBsZWZ0LFxuICAgICAgICAgIHRvcCxcbiAgICAgICAgICB3aWR0aDogd2lkdGggKyBsYWJlbFBhZGRpbmcud2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgKyBsYWJlbFBhZGRpbmcuaGVpZ2h0LFxuICAgICAgICAgIGNvbG9yOiBvcHRzQXRJbmRleC5iYWNrZHJvcENvbG9yLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaXRlbXMucHVzaCh7XG4gICAgICAgIHJvdGF0aW9uLFxuICAgICAgICBsYWJlbCxcbiAgICAgICAgZm9udCxcbiAgICAgICAgY29sb3IsXG4gICAgICAgIHN0cm9rZUNvbG9yLFxuICAgICAgICBzdHJva2VXaWR0aCxcbiAgICAgICAgdGV4dE9mZnNldCxcbiAgICAgICAgdGV4dEFsaWduLFxuICAgICAgICB0ZXh0QmFzZWxpbmUsXG4gICAgICAgIHRyYW5zbGF0aW9uOiBbeCwgeV0sXG4gICAgICAgIGJhY2tkcm9wLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtcztcbiAgfVxuICBfZ2V0WEF4aXNMYWJlbEFsaWdubWVudCgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge3Bvc2l0aW9uLCB0aWNrc30gPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IHJvdGF0aW9uID0gLXRvUmFkaWFucyhtZS5sYWJlbFJvdGF0aW9uKTtcbiAgICBpZiAocm90YXRpb24pIHtcbiAgICAgIHJldHVybiBwb3NpdGlvbiA9PT0gJ3RvcCcgPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgIH1cbiAgICBsZXQgYWxpZ24gPSAnY2VudGVyJztcbiAgICBpZiAodGlja3MuYWxpZ24gPT09ICdzdGFydCcpIHtcbiAgICAgIGFsaWduID0gJ2xlZnQnO1xuICAgIH0gZWxzZSBpZiAodGlja3MuYWxpZ24gPT09ICdlbmQnKSB7XG4gICAgICBhbGlnbiA9ICdyaWdodCc7XG4gICAgfVxuICAgIHJldHVybiBhbGlnbjtcbiAgfVxuICBfZ2V0WUF4aXNMYWJlbEFsaWdubWVudCh0bCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB7cG9zaXRpb24sIHRpY2tzOiB7Y3Jvc3NBbGlnbiwgbWlycm9yLCBwYWRkaW5nfX0gPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IGxhYmVsU2l6ZXMgPSBtZS5fZ2V0TGFiZWxTaXplcygpO1xuICAgIGNvbnN0IHRpY2tBbmRQYWRkaW5nID0gdGwgKyBwYWRkaW5nO1xuICAgIGNvbnN0IHdpZGVzdCA9IGxhYmVsU2l6ZXMud2lkZXN0LndpZHRoO1xuICAgIGxldCB0ZXh0QWxpZ247XG4gICAgbGV0IHg7XG4gICAgaWYgKHBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgIGlmIChtaXJyb3IpIHtcbiAgICAgICAgeCA9IG1lLnJpZ2h0ICsgcGFkZGluZztcbiAgICAgICAgaWYgKGNyb3NzQWxpZ24gPT09ICduZWFyJykge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgIHggKz0gKHdpZGVzdCAvIDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdyaWdodCc7XG4gICAgICAgICAgeCArPSB3aWRlc3Q7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHggPSBtZS5yaWdodCAtIHRpY2tBbmRQYWRkaW5nO1xuICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInKSB7XG4gICAgICAgICAgdGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgIHggLT0gKHdpZGVzdCAvIDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgICB4ID0gbWUubGVmdDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgIGlmIChtaXJyb3IpIHtcbiAgICAgICAgeCA9IG1lLmxlZnQgKyBwYWRkaW5nO1xuICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInKSB7XG4gICAgICAgICAgdGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgIHggLT0gKHdpZGVzdCAvIDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgICB4IC09IHdpZGVzdDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeCA9IG1lLmxlZnQgKyB0aWNrQW5kUGFkZGluZztcbiAgICAgICAgaWYgKGNyb3NzQWxpZ24gPT09ICduZWFyJykge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgIHggKz0gd2lkZXN0IC8gMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0ZXh0QWxpZ24gPSAncmlnaHQnO1xuICAgICAgICAgIHggPSBtZS5yaWdodDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0ZXh0QWxpZ24gPSAncmlnaHQnO1xuICAgIH1cbiAgICByZXR1cm4ge3RleHRBbGlnbiwgeH07XG4gIH1cbiAgX2NvbXB1dGVMYWJlbEFyZWEoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmIChtZS5vcHRpb25zLnRpY2tzLm1pcnJvcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBjaGFydCA9IG1lLmNoYXJ0O1xuICAgIGNvbnN0IHBvc2l0aW9uID0gbWUub3B0aW9ucy5wb3NpdGlvbjtcbiAgICBpZiAocG9zaXRpb24gPT09ICdsZWZ0JyB8fCBwb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgcmV0dXJuIHt0b3A6IDAsIGxlZnQ6IG1lLmxlZnQsIGJvdHRvbTogY2hhcnQuaGVpZ2h0LCByaWdodDogbWUucmlnaHR9O1xuICAgIH0gaWYgKHBvc2l0aW9uID09PSAndG9wJyB8fCBwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIHJldHVybiB7dG9wOiBtZS50b3AsIGxlZnQ6IDAsIGJvdHRvbTogbWUuYm90dG9tLCByaWdodDogY2hhcnQud2lkdGh9O1xuICAgIH1cbiAgfVxuICBkcmF3QmFja2dyb3VuZCgpIHtcbiAgICBjb25zdCB7Y3R4LCBvcHRpb25zOiB7YmFja2dyb3VuZENvbG9yfSwgbGVmdCwgdG9wLCB3aWR0aCwgaGVpZ2h0fSA9IHRoaXM7XG4gICAgaWYgKGJhY2tncm91bmRDb2xvcikge1xuICAgICAgY3R4LnNhdmUoKTtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSBiYWNrZ3JvdW5kQ29sb3I7XG4gICAgICBjdHguZmlsbFJlY3QobGVmdCwgdG9wLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgfVxuICB9XG4gIGdldExpbmVXaWR0aEZvclZhbHVlKHZhbHVlKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGdyaWQgPSBtZS5vcHRpb25zLmdyaWQ7XG4gICAgaWYgKCFtZS5faXNWaXNpYmxlKCkgfHwgIWdyaWQuZGlzcGxheSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGNvbnN0IHRpY2tzID0gbWUudGlja3M7XG4gICAgY29uc3QgaW5kZXggPSB0aWNrcy5maW5kSW5kZXgodCA9PiB0LnZhbHVlID09PSB2YWx1ZSk7XG4gICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgIGNvbnN0IG9wdHMgPSBncmlkLnNldENvbnRleHQobWUuZ2V0Q29udGV4dChpbmRleCkpO1xuICAgICAgcmV0dXJuIG9wdHMubGluZVdpZHRoO1xuICAgIH1cbiAgICByZXR1cm4gMDtcbiAgfVxuICBkcmF3R3JpZChjaGFydEFyZWEpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgZ3JpZCA9IG1lLm9wdGlvbnMuZ3JpZDtcbiAgICBjb25zdCBjdHggPSBtZS5jdHg7XG4gICAgY29uc3QgaXRlbXMgPSBtZS5fZ3JpZExpbmVJdGVtcyB8fCAobWUuX2dyaWRMaW5lSXRlbXMgPSBtZS5fY29tcHV0ZUdyaWRMaW5lSXRlbXMoY2hhcnRBcmVhKSk7XG4gICAgbGV0IGksIGlsZW47XG4gICAgY29uc3QgZHJhd0xpbmUgPSAocDEsIHAyLCBzdHlsZSkgPT4ge1xuICAgICAgaWYgKCFzdHlsZS53aWR0aCB8fCAhc3R5bGUuY29sb3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY3R4LnNhdmUoKTtcbiAgICAgIGN0eC5saW5lV2lkdGggPSBzdHlsZS53aWR0aDtcbiAgICAgIGN0eC5zdHJva2VTdHlsZSA9IHN0eWxlLmNvbG9yO1xuICAgICAgY3R4LnNldExpbmVEYXNoKHN0eWxlLmJvcmRlckRhc2ggfHwgW10pO1xuICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gc3R5bGUuYm9yZGVyRGFzaE9mZnNldDtcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgIGN0eC5tb3ZlVG8ocDEueCwgcDEueSk7XG4gICAgICBjdHgubGluZVRvKHAyLngsIHAyLnkpO1xuICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICB9O1xuICAgIGlmIChncmlkLmRpc3BsYXkpIHtcbiAgICAgIGZvciAoaSA9IDAsIGlsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgICAgY29uc3QgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgICBpZiAoZ3JpZC5kcmF3T25DaGFydEFyZWEpIHtcbiAgICAgICAgICBkcmF3TGluZShcbiAgICAgICAgICAgIHt4OiBpdGVtLngxLCB5OiBpdGVtLnkxfSxcbiAgICAgICAgICAgIHt4OiBpdGVtLngyLCB5OiBpdGVtLnkyfSxcbiAgICAgICAgICAgIGl0ZW1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChncmlkLmRyYXdUaWNrcykge1xuICAgICAgICAgIGRyYXdMaW5lKFxuICAgICAgICAgICAge3g6IGl0ZW0udHgxLCB5OiBpdGVtLnR5MX0sXG4gICAgICAgICAgICB7eDogaXRlbS50eDIsIHk6IGl0ZW0udHkyfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgY29sb3I6IGl0ZW0udGlja0NvbG9yLFxuICAgICAgICAgICAgICB3aWR0aDogaXRlbS50aWNrV2lkdGgsXG4gICAgICAgICAgICAgIGJvcmRlckRhc2g6IGl0ZW0udGlja0JvcmRlckRhc2gsXG4gICAgICAgICAgICAgIGJvcmRlckRhc2hPZmZzZXQ6IGl0ZW0udGlja0JvcmRlckRhc2hPZmZzZXRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGRyYXdCb3JkZXIoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtjaGFydCwgY3R4LCBvcHRpb25zOiB7Z3JpZH19ID0gbWU7XG4gICAgY29uc3QgYm9yZGVyT3B0cyA9IGdyaWQuc2V0Q29udGV4dChtZS5nZXRDb250ZXh0KCkpO1xuICAgIGNvbnN0IGF4aXNXaWR0aCA9IGdyaWQuZHJhd0JvcmRlciA/IGJvcmRlck9wdHMuYm9yZGVyV2lkdGggOiAwO1xuICAgIGlmICghYXhpc1dpZHRoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGxhc3RMaW5lV2lkdGggPSBncmlkLnNldENvbnRleHQobWUuZ2V0Q29udGV4dCgwKSkubGluZVdpZHRoO1xuICAgIGNvbnN0IGJvcmRlclZhbHVlID0gbWUuX2JvcmRlclZhbHVlO1xuICAgIGxldCB4MSwgeDIsIHkxLCB5MjtcbiAgICBpZiAobWUuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgIHgxID0gX2FsaWduUGl4ZWwoY2hhcnQsIG1lLmxlZnQsIGF4aXNXaWR0aCkgLSBheGlzV2lkdGggLyAyO1xuICAgICAgeDIgPSBfYWxpZ25QaXhlbChjaGFydCwgbWUucmlnaHQsIGxhc3RMaW5lV2lkdGgpICsgbGFzdExpbmVXaWR0aCAvIDI7XG4gICAgICB5MSA9IHkyID0gYm9yZGVyVmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHkxID0gX2FsaWduUGl4ZWwoY2hhcnQsIG1lLnRvcCwgYXhpc1dpZHRoKSAtIGF4aXNXaWR0aCAvIDI7XG4gICAgICB5MiA9IF9hbGlnblBpeGVsKGNoYXJ0LCBtZS5ib3R0b20sIGxhc3RMaW5lV2lkdGgpICsgbGFzdExpbmVXaWR0aCAvIDI7XG4gICAgICB4MSA9IHgyID0gYm9yZGVyVmFsdWU7XG4gICAgfVxuICAgIGN0eC5zYXZlKCk7XG4gICAgY3R4LmxpbmVXaWR0aCA9IGJvcmRlck9wdHMuYm9yZGVyV2lkdGg7XG4gICAgY3R4LnN0cm9rZVN0eWxlID0gYm9yZGVyT3B0cy5ib3JkZXJDb2xvcjtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4Lm1vdmVUbyh4MSwgeTEpO1xuICAgIGN0eC5saW5lVG8oeDIsIHkyKTtcbiAgICBjdHguc3Ryb2tlKCk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgfVxuICBkcmF3TGFiZWxzKGNoYXJ0QXJlYSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRpb25UaWNrcyA9IG1lLm9wdGlvbnMudGlja3M7XG4gICAgaWYgKCFvcHRpb25UaWNrcy5kaXNwbGF5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGN0eCA9IG1lLmN0eDtcbiAgICBjb25zdCBhcmVhID0gbWUuX2NvbXB1dGVMYWJlbEFyZWEoKTtcbiAgICBpZiAoYXJlYSkge1xuICAgICAgY2xpcEFyZWEoY3R4LCBhcmVhKTtcbiAgICB9XG4gICAgY29uc3QgaXRlbXMgPSBtZS5fbGFiZWxJdGVtcyB8fCAobWUuX2xhYmVsSXRlbXMgPSBtZS5fY29tcHV0ZUxhYmVsSXRlbXMoY2hhcnRBcmVhKSk7XG4gICAgbGV0IGksIGlsZW47XG4gICAgZm9yIChpID0gMCwgaWxlbiA9IGl0ZW1zLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgY29uc3QgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgY29uc3QgdGlja0ZvbnQgPSBpdGVtLmZvbnQ7XG4gICAgICBjb25zdCBsYWJlbCA9IGl0ZW0ubGFiZWw7XG4gICAgICBpZiAoaXRlbS5iYWNrZHJvcCkge1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gaXRlbS5iYWNrZHJvcC5jb2xvcjtcbiAgICAgICAgY3R4LmZpbGxSZWN0KGl0ZW0uYmFja2Ryb3AubGVmdCwgaXRlbS5iYWNrZHJvcC50b3AsIGl0ZW0uYmFja2Ryb3Aud2lkdGgsIGl0ZW0uYmFja2Ryb3AuaGVpZ2h0KTtcbiAgICAgIH1cbiAgICAgIGxldCB5ID0gaXRlbS50ZXh0T2Zmc2V0O1xuICAgICAgcmVuZGVyVGV4dChjdHgsIGxhYmVsLCAwLCB5LCB0aWNrRm9udCwgaXRlbSk7XG4gICAgfVxuICAgIGlmIChhcmVhKSB7XG4gICAgICB1bmNsaXBBcmVhKGN0eCk7XG4gICAgfVxuICB9XG4gIGRyYXdUaXRsZSgpIHtcbiAgICBjb25zdCB7Y3R4LCBvcHRpb25zOiB7cG9zaXRpb24sIHRpdGxlLCByZXZlcnNlfX0gPSB0aGlzO1xuICAgIGlmICghdGl0bGUuZGlzcGxheSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBmb250ID0gdG9Gb250KHRpdGxlLmZvbnQpO1xuICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcodGl0bGUucGFkZGluZyk7XG4gICAgY29uc3QgYWxpZ24gPSB0aXRsZS5hbGlnbjtcbiAgICBsZXQgb2Zmc2V0ID0gZm9udC5saW5lSGVpZ2h0IC8gMjtcbiAgICBpZiAocG9zaXRpb24gPT09ICdib3R0b20nIHx8IHBvc2l0aW9uID09PSAnY2VudGVyJyB8fCBpc09iamVjdChwb3NpdGlvbikpIHtcbiAgICAgIG9mZnNldCArPSBwYWRkaW5nLmJvdHRvbTtcbiAgICAgIGlmIChpc0FycmF5KHRpdGxlLnRleHQpKSB7XG4gICAgICAgIG9mZnNldCArPSBmb250LmxpbmVIZWlnaHQgKiAodGl0bGUudGV4dC5sZW5ndGggLSAxKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgb2Zmc2V0ICs9IHBhZGRpbmcudG9wO1xuICAgIH1cbiAgICBjb25zdCB7dGl0bGVYLCB0aXRsZVksIG1heFdpZHRoLCByb3RhdGlvbn0gPSB0aXRsZUFyZ3ModGhpcywgb2Zmc2V0LCBwb3NpdGlvbiwgYWxpZ24pO1xuICAgIHJlbmRlclRleHQoY3R4LCB0aXRsZS50ZXh0LCAwLCAwLCBmb250LCB7XG4gICAgICBjb2xvcjogdGl0bGUuY29sb3IsXG4gICAgICBtYXhXaWR0aCxcbiAgICAgIHJvdGF0aW9uLFxuICAgICAgdGV4dEFsaWduOiB0aXRsZUFsaWduKGFsaWduLCBwb3NpdGlvbiwgcmV2ZXJzZSksXG4gICAgICB0ZXh0QmFzZWxpbmU6ICdtaWRkbGUnLFxuICAgICAgdHJhbnNsYXRpb246IFt0aXRsZVgsIHRpdGxlWV0sXG4gICAgfSk7XG4gIH1cbiAgZHJhdyhjaGFydEFyZWEpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgaWYgKCFtZS5faXNWaXNpYmxlKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbWUuZHJhd0JhY2tncm91bmQoKTtcbiAgICBtZS5kcmF3R3JpZChjaGFydEFyZWEpO1xuICAgIG1lLmRyYXdCb3JkZXIoKTtcbiAgICBtZS5kcmF3VGl0bGUoKTtcbiAgICBtZS5kcmF3TGFiZWxzKGNoYXJ0QXJlYSk7XG4gIH1cbiAgX2xheWVycygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qgb3B0cyA9IG1lLm9wdGlvbnM7XG4gICAgY29uc3QgdHogPSBvcHRzLnRpY2tzICYmIG9wdHMudGlja3MueiB8fCAwO1xuICAgIGNvbnN0IGd6ID0gdmFsdWVPckRlZmF1bHQob3B0cy5ncmlkICYmIG9wdHMuZ3JpZC56LCAtMSk7XG4gICAgaWYgKCFtZS5faXNWaXNpYmxlKCkgfHwgbWUuZHJhdyAhPT0gU2NhbGUucHJvdG90eXBlLmRyYXcpIHtcbiAgICAgIHJldHVybiBbe1xuICAgICAgICB6OiB0eixcbiAgICAgICAgZHJhdyhjaGFydEFyZWEpIHtcbiAgICAgICAgICBtZS5kcmF3KGNoYXJ0QXJlYSk7XG4gICAgICAgIH1cbiAgICAgIH1dO1xuICAgIH1cbiAgICByZXR1cm4gW3tcbiAgICAgIHo6IGd6LFxuICAgICAgZHJhdyhjaGFydEFyZWEpIHtcbiAgICAgICAgbWUuZHJhd0JhY2tncm91bmQoKTtcbiAgICAgICAgbWUuZHJhd0dyaWQoY2hhcnRBcmVhKTtcbiAgICAgICAgbWUuZHJhd1RpdGxlKCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAgejogZ3ogKyAxLFxuICAgICAgZHJhdygpIHtcbiAgICAgICAgbWUuZHJhd0JvcmRlcigpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIHo6IHR6LFxuICAgICAgZHJhdyhjaGFydEFyZWEpIHtcbiAgICAgICAgbWUuZHJhd0xhYmVscyhjaGFydEFyZWEpO1xuICAgICAgfVxuICAgIH1dO1xuICB9XG4gIGdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKHR5cGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbWV0YXMgPSBtZS5jaGFydC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCk7XG4gICAgY29uc3QgYXhpc0lEID0gbWUuYXhpcyArICdBeGlzSUQnO1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpLCBpbGVuO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBtZXRhcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGNvbnN0IG1ldGEgPSBtZXRhc1tpXTtcbiAgICAgIGlmIChtZXRhW2F4aXNJRF0gPT09IG1lLmlkICYmICghdHlwZSB8fCBtZXRhLnR5cGUgPT09IHR5cGUpKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKG1ldGEpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIF9yZXNvbHZlVGlja0ZvbnRPcHRpb25zKGluZGV4KSB7XG4gICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucy50aWNrcy5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dChpbmRleCkpO1xuICAgIHJldHVybiB0b0ZvbnQob3B0cy5mb250KTtcbiAgfVxuICBfbWF4RGlnaXRzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBmb250U2l6ZSA9IG1lLl9yZXNvbHZlVGlja0ZvbnRPcHRpb25zKDApLmxpbmVIZWlnaHQ7XG4gICAgcmV0dXJuIChtZS5pc0hvcml6b250YWwoKSA/IG1lLndpZHRoIDogbWUuaGVpZ2h0KSAvIGZvbnRTaXplO1xuICB9XG59XG5cbmNsYXNzIFR5cGVkUmVnaXN0cnkge1xuICBjb25zdHJ1Y3Rvcih0eXBlLCBzY29wZSwgb3ZlcnJpZGUpIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMuc2NvcGUgPSBzY29wZTtcbiAgICB0aGlzLm92ZXJyaWRlID0gb3ZlcnJpZGU7XG4gICAgdGhpcy5pdGVtcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gIH1cbiAgaXNGb3JUeXBlKHR5cGUpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mLmNhbGwodGhpcy50eXBlLnByb3RvdHlwZSwgdHlwZS5wcm90b3R5cGUpO1xuICB9XG4gIHJlZ2lzdGVyKGl0ZW0pIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoaXRlbSk7XG4gICAgbGV0IHBhcmVudFNjb3BlO1xuICAgIGlmIChpc0lDaGFydENvbXBvbmVudChwcm90bykpIHtcbiAgICAgIHBhcmVudFNjb3BlID0gbWUucmVnaXN0ZXIocHJvdG8pO1xuICAgIH1cbiAgICBjb25zdCBpdGVtcyA9IG1lLml0ZW1zO1xuICAgIGNvbnN0IGlkID0gaXRlbS5pZDtcbiAgICBjb25zdCBzY29wZSA9IG1lLnNjb3BlICsgJy4nICsgaWQ7XG4gICAgaWYgKCFpZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjbGFzcyBkb2VzIG5vdCBoYXZlIGlkOiAnICsgaXRlbSk7XG4gICAgfVxuICAgIGlmIChpZCBpbiBpdGVtcykge1xuICAgICAgcmV0dXJuIHNjb3BlO1xuICAgIH1cbiAgICBpdGVtc1tpZF0gPSBpdGVtO1xuICAgIHJlZ2lzdGVyRGVmYXVsdHMoaXRlbSwgc2NvcGUsIHBhcmVudFNjb3BlKTtcbiAgICBpZiAobWUub3ZlcnJpZGUpIHtcbiAgICAgIGRlZmF1bHRzLm92ZXJyaWRlKGl0ZW0uaWQsIGl0ZW0ub3ZlcnJpZGVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHNjb3BlO1xuICB9XG4gIGdldChpZCkge1xuICAgIHJldHVybiB0aGlzLml0ZW1zW2lkXTtcbiAgfVxuICB1bnJlZ2lzdGVyKGl0ZW0pIHtcbiAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgY29uc3QgaWQgPSBpdGVtLmlkO1xuICAgIGNvbnN0IHNjb3BlID0gdGhpcy5zY29wZTtcbiAgICBpZiAoaWQgaW4gaXRlbXMpIHtcbiAgICAgIGRlbGV0ZSBpdGVtc1tpZF07XG4gICAgfVxuICAgIGlmIChzY29wZSAmJiBpZCBpbiBkZWZhdWx0c1tzY29wZV0pIHtcbiAgICAgIGRlbGV0ZSBkZWZhdWx0c1tzY29wZV1baWRdO1xuICAgICAgaWYgKHRoaXMub3ZlcnJpZGUpIHtcbiAgICAgICAgZGVsZXRlIG92ZXJyaWRlc1tpZF07XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5mdW5jdGlvbiByZWdpc3RlckRlZmF1bHRzKGl0ZW0sIHNjb3BlLCBwYXJlbnRTY29wZSkge1xuICBjb25zdCBpdGVtRGVmYXVsdHMgPSBtZXJnZShPYmplY3QuY3JlYXRlKG51bGwpLCBbXG4gICAgcGFyZW50U2NvcGUgPyBkZWZhdWx0cy5nZXQocGFyZW50U2NvcGUpIDoge30sXG4gICAgZGVmYXVsdHMuZ2V0KHNjb3BlKSxcbiAgICBpdGVtLmRlZmF1bHRzXG4gIF0pO1xuICBkZWZhdWx0cy5zZXQoc2NvcGUsIGl0ZW1EZWZhdWx0cyk7XG4gIGlmIChpdGVtLmRlZmF1bHRSb3V0ZXMpIHtcbiAgICByb3V0ZURlZmF1bHRzKHNjb3BlLCBpdGVtLmRlZmF1bHRSb3V0ZXMpO1xuICB9XG4gIGlmIChpdGVtLmRlc2NyaXB0b3JzKSB7XG4gICAgZGVmYXVsdHMuZGVzY3JpYmUoc2NvcGUsIGl0ZW0uZGVzY3JpcHRvcnMpO1xuICB9XG59XG5mdW5jdGlvbiByb3V0ZURlZmF1bHRzKHNjb3BlLCByb3V0ZXMpIHtcbiAgT2JqZWN0LmtleXMocm91dGVzKS5mb3JFYWNoKHByb3BlcnR5ID0+IHtcbiAgICBjb25zdCBwcm9wZXJ0eVBhcnRzID0gcHJvcGVydHkuc3BsaXQoJy4nKTtcbiAgICBjb25zdCBzb3VyY2VOYW1lID0gcHJvcGVydHlQYXJ0cy5wb3AoKTtcbiAgICBjb25zdCBzb3VyY2VTY29wZSA9IFtzY29wZV0uY29uY2F0KHByb3BlcnR5UGFydHMpLmpvaW4oJy4nKTtcbiAgICBjb25zdCBwYXJ0cyA9IHJvdXRlc1twcm9wZXJ0eV0uc3BsaXQoJy4nKTtcbiAgICBjb25zdCB0YXJnZXROYW1lID0gcGFydHMucG9wKCk7XG4gICAgY29uc3QgdGFyZ2V0U2NvcGUgPSBwYXJ0cy5qb2luKCcuJyk7XG4gICAgZGVmYXVsdHMucm91dGUoc291cmNlU2NvcGUsIHNvdXJjZU5hbWUsIHRhcmdldFNjb3BlLCB0YXJnZXROYW1lKTtcbiAgfSk7XG59XG5mdW5jdGlvbiBpc0lDaGFydENvbXBvbmVudChwcm90bykge1xuICByZXR1cm4gJ2lkJyBpbiBwcm90byAmJiAnZGVmYXVsdHMnIGluIHByb3RvO1xufVxuXG5jbGFzcyBSZWdpc3RyeSB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuY29udHJvbGxlcnMgPSBuZXcgVHlwZWRSZWdpc3RyeShEYXRhc2V0Q29udHJvbGxlciwgJ2RhdGFzZXRzJywgdHJ1ZSk7XG4gICAgdGhpcy5lbGVtZW50cyA9IG5ldyBUeXBlZFJlZ2lzdHJ5KEVsZW1lbnQsICdlbGVtZW50cycpO1xuICAgIHRoaXMucGx1Z2lucyA9IG5ldyBUeXBlZFJlZ2lzdHJ5KE9iamVjdCwgJ3BsdWdpbnMnKTtcbiAgICB0aGlzLnNjYWxlcyA9IG5ldyBUeXBlZFJlZ2lzdHJ5KFNjYWxlLCAnc2NhbGVzJyk7XG4gICAgdGhpcy5fdHlwZWRSZWdpc3RyaWVzID0gW3RoaXMuY29udHJvbGxlcnMsIHRoaXMuc2NhbGVzLCB0aGlzLmVsZW1lbnRzXTtcbiAgfVxuICBhZGQoLi4uYXJncykge1xuICAgIHRoaXMuX2VhY2goJ3JlZ2lzdGVyJywgYXJncyk7XG4gIH1cbiAgcmVtb3ZlKC4uLmFyZ3MpIHtcbiAgICB0aGlzLl9lYWNoKCd1bnJlZ2lzdGVyJywgYXJncyk7XG4gIH1cbiAgYWRkQ29udHJvbGxlcnMoLi4uYXJncykge1xuICAgIHRoaXMuX2VhY2goJ3JlZ2lzdGVyJywgYXJncywgdGhpcy5jb250cm9sbGVycyk7XG4gIH1cbiAgYWRkRWxlbWVudHMoLi4uYXJncykge1xuICAgIHRoaXMuX2VhY2goJ3JlZ2lzdGVyJywgYXJncywgdGhpcy5lbGVtZW50cyk7XG4gIH1cbiAgYWRkUGx1Z2lucyguLi5hcmdzKSB7XG4gICAgdGhpcy5fZWFjaCgncmVnaXN0ZXInLCBhcmdzLCB0aGlzLnBsdWdpbnMpO1xuICB9XG4gIGFkZFNjYWxlcyguLi5hcmdzKSB7XG4gICAgdGhpcy5fZWFjaCgncmVnaXN0ZXInLCBhcmdzLCB0aGlzLnNjYWxlcyk7XG4gIH1cbiAgZ2V0Q29udHJvbGxlcihpZCkge1xuICAgIHJldHVybiB0aGlzLl9nZXQoaWQsIHRoaXMuY29udHJvbGxlcnMsICdjb250cm9sbGVyJyk7XG4gIH1cbiAgZ2V0RWxlbWVudChpZCkge1xuICAgIHJldHVybiB0aGlzLl9nZXQoaWQsIHRoaXMuZWxlbWVudHMsICdlbGVtZW50Jyk7XG4gIH1cbiAgZ2V0UGx1Z2luKGlkKSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldChpZCwgdGhpcy5wbHVnaW5zLCAncGx1Z2luJyk7XG4gIH1cbiAgZ2V0U2NhbGUoaWQpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0KGlkLCB0aGlzLnNjYWxlcywgJ3NjYWxlJyk7XG4gIH1cbiAgcmVtb3ZlQ29udHJvbGxlcnMoLi4uYXJncykge1xuICAgIHRoaXMuX2VhY2goJ3VucmVnaXN0ZXInLCBhcmdzLCB0aGlzLmNvbnRyb2xsZXJzKTtcbiAgfVxuICByZW1vdmVFbGVtZW50cyguLi5hcmdzKSB7XG4gICAgdGhpcy5fZWFjaCgndW5yZWdpc3RlcicsIGFyZ3MsIHRoaXMuZWxlbWVudHMpO1xuICB9XG4gIHJlbW92ZVBsdWdpbnMoLi4uYXJncykge1xuICAgIHRoaXMuX2VhY2goJ3VucmVnaXN0ZXInLCBhcmdzLCB0aGlzLnBsdWdpbnMpO1xuICB9XG4gIHJlbW92ZVNjYWxlcyguLi5hcmdzKSB7XG4gICAgdGhpcy5fZWFjaCgndW5yZWdpc3RlcicsIGFyZ3MsIHRoaXMuc2NhbGVzKTtcbiAgfVxuICBfZWFjaChtZXRob2QsIGFyZ3MsIHR5cGVkUmVnaXN0cnkpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgWy4uLmFyZ3NdLmZvckVhY2goYXJnID0+IHtcbiAgICAgIGNvbnN0IHJlZyA9IHR5cGVkUmVnaXN0cnkgfHwgbWUuX2dldFJlZ2lzdHJ5Rm9yVHlwZShhcmcpO1xuICAgICAgaWYgKHR5cGVkUmVnaXN0cnkgfHwgcmVnLmlzRm9yVHlwZShhcmcpIHx8IChyZWcgPT09IG1lLnBsdWdpbnMgJiYgYXJnLmlkKSkge1xuICAgICAgICBtZS5fZXhlYyhtZXRob2QsIHJlZywgYXJnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVhY2goYXJnLCBpdGVtID0+IHtcbiAgICAgICAgICBjb25zdCBpdGVtUmVnID0gdHlwZWRSZWdpc3RyeSB8fCBtZS5fZ2V0UmVnaXN0cnlGb3JUeXBlKGl0ZW0pO1xuICAgICAgICAgIG1lLl9leGVjKG1ldGhvZCwgaXRlbVJlZywgaXRlbSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIF9leGVjKG1ldGhvZCwgcmVnaXN0cnksIGNvbXBvbmVudCkge1xuICAgIGNvbnN0IGNhbWVsTWV0aG9kID0gX2NhcGl0YWxpemUobWV0aG9kKTtcbiAgICBjYWxsYmFjayhjb21wb25lbnRbJ2JlZm9yZScgKyBjYW1lbE1ldGhvZF0sIFtdLCBjb21wb25lbnQpO1xuICAgIHJlZ2lzdHJ5W21ldGhvZF0oY29tcG9uZW50KTtcbiAgICBjYWxsYmFjayhjb21wb25lbnRbJ2FmdGVyJyArIGNhbWVsTWV0aG9kXSwgW10sIGNvbXBvbmVudCk7XG4gIH1cbiAgX2dldFJlZ2lzdHJ5Rm9yVHlwZSh0eXBlKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl90eXBlZFJlZ2lzdHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHJlZyA9IHRoaXMuX3R5cGVkUmVnaXN0cmllc1tpXTtcbiAgICAgIGlmIChyZWcuaXNGb3JUeXBlKHR5cGUpKSB7XG4gICAgICAgIHJldHVybiByZWc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnBsdWdpbnM7XG4gIH1cbiAgX2dldChpZCwgdHlwZWRSZWdpc3RyeSwgdHlwZSkge1xuICAgIGNvbnN0IGl0ZW0gPSB0eXBlZFJlZ2lzdHJ5LmdldChpZCk7XG4gICAgaWYgKGl0ZW0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIicgKyBpZCArICdcIiBpcyBub3QgYSByZWdpc3RlcmVkICcgKyB0eXBlICsgJy4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGl0ZW07XG4gIH1cbn1cbnZhciByZWdpc3RyeSA9IG5ldyBSZWdpc3RyeSgpO1xuXG5jbGFzcyBQbHVnaW5TZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5faW5pdCA9IFtdO1xuICB9XG4gIG5vdGlmeShjaGFydCwgaG9vaywgYXJncywgZmlsdGVyKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmIChob29rID09PSAnYmVmb3JlSW5pdCcpIHtcbiAgICAgIG1lLl9pbml0ID0gbWUuX2NyZWF0ZURlc2NyaXB0b3JzKGNoYXJ0LCB0cnVlKTtcbiAgICAgIG1lLl9ub3RpZnkobWUuX2luaXQsIGNoYXJ0LCAnaW5zdGFsbCcpO1xuICAgIH1cbiAgICBjb25zdCBkZXNjcmlwdG9ycyA9IGZpbHRlciA/IG1lLl9kZXNjcmlwdG9ycyhjaGFydCkuZmlsdGVyKGZpbHRlcikgOiBtZS5fZGVzY3JpcHRvcnMoY2hhcnQpO1xuICAgIGNvbnN0IHJlc3VsdCA9IG1lLl9ub3RpZnkoZGVzY3JpcHRvcnMsIGNoYXJ0LCBob29rLCBhcmdzKTtcbiAgICBpZiAoaG9vayA9PT0gJ2Rlc3Ryb3knKSB7XG4gICAgICBtZS5fbm90aWZ5KGRlc2NyaXB0b3JzLCBjaGFydCwgJ3N0b3AnKTtcbiAgICAgIG1lLl9ub3RpZnkobWUuX2luaXQsIGNoYXJ0LCAndW5pbnN0YWxsJyk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgX25vdGlmeShkZXNjcmlwdG9ycywgY2hhcnQsIGhvb2ssIGFyZ3MpIHtcbiAgICBhcmdzID0gYXJncyB8fCB7fTtcbiAgICBmb3IgKGNvbnN0IGRlc2NyaXB0b3Igb2YgZGVzY3JpcHRvcnMpIHtcbiAgICAgIGNvbnN0IHBsdWdpbiA9IGRlc2NyaXB0b3IucGx1Z2luO1xuICAgICAgY29uc3QgbWV0aG9kID0gcGx1Z2luW2hvb2tdO1xuICAgICAgY29uc3QgcGFyYW1zID0gW2NoYXJ0LCBhcmdzLCBkZXNjcmlwdG9yLm9wdGlvbnNdO1xuICAgICAgaWYgKGNhbGxiYWNrKG1ldGhvZCwgcGFyYW1zLCBwbHVnaW4pID09PSBmYWxzZSAmJiBhcmdzLmNhbmNlbGFibGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBpbnZhbGlkYXRlKCkge1xuICAgIGlmICghaXNOdWxsT3JVbmRlZih0aGlzLl9jYWNoZSkpIHtcbiAgICAgIHRoaXMuX29sZENhY2hlID0gdGhpcy5fY2FjaGU7XG4gICAgICB0aGlzLl9jYWNoZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cbiAgX2Rlc2NyaXB0b3JzKGNoYXJ0KSB7XG4gICAgaWYgKHRoaXMuX2NhY2hlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY2FjaGU7XG4gICAgfVxuICAgIGNvbnN0IGRlc2NyaXB0b3JzID0gdGhpcy5fY2FjaGUgPSB0aGlzLl9jcmVhdGVEZXNjcmlwdG9ycyhjaGFydCk7XG4gICAgdGhpcy5fbm90aWZ5U3RhdGVDaGFuZ2VzKGNoYXJ0KTtcbiAgICByZXR1cm4gZGVzY3JpcHRvcnM7XG4gIH1cbiAgX2NyZWF0ZURlc2NyaXB0b3JzKGNoYXJ0LCBhbGwpIHtcbiAgICBjb25zdCBjb25maWcgPSBjaGFydCAmJiBjaGFydC5jb25maWc7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHZhbHVlT3JEZWZhdWx0KGNvbmZpZy5vcHRpb25zICYmIGNvbmZpZy5vcHRpb25zLnBsdWdpbnMsIHt9KTtcbiAgICBjb25zdCBwbHVnaW5zID0gYWxsUGx1Z2lucyhjb25maWcpO1xuICAgIHJldHVybiBvcHRpb25zID09PSBmYWxzZSAmJiAhYWxsID8gW10gOiBjcmVhdGVEZXNjcmlwdG9ycyhjaGFydCwgcGx1Z2lucywgb3B0aW9ucywgYWxsKTtcbiAgfVxuICBfbm90aWZ5U3RhdGVDaGFuZ2VzKGNoYXJ0KSB7XG4gICAgY29uc3QgcHJldmlvdXNEZXNjcmlwdG9ycyA9IHRoaXMuX29sZENhY2hlIHx8IFtdO1xuICAgIGNvbnN0IGRlc2NyaXB0b3JzID0gdGhpcy5fY2FjaGU7XG4gICAgY29uc3QgZGlmZiA9IChhLCBiKSA9PiBhLmZpbHRlcih4ID0+ICFiLnNvbWUoeSA9PiB4LnBsdWdpbi5pZCA9PT0geS5wbHVnaW4uaWQpKTtcbiAgICB0aGlzLl9ub3RpZnkoZGlmZihwcmV2aW91c0Rlc2NyaXB0b3JzLCBkZXNjcmlwdG9ycyksIGNoYXJ0LCAnc3RvcCcpO1xuICAgIHRoaXMuX25vdGlmeShkaWZmKGRlc2NyaXB0b3JzLCBwcmV2aW91c0Rlc2NyaXB0b3JzKSwgY2hhcnQsICdzdGFydCcpO1xuICB9XG59XG5mdW5jdGlvbiBhbGxQbHVnaW5zKGNvbmZpZykge1xuICBjb25zdCBwbHVnaW5zID0gW107XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhyZWdpc3RyeS5wbHVnaW5zLml0ZW1zKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgcGx1Z2lucy5wdXNoKHJlZ2lzdHJ5LmdldFBsdWdpbihrZXlzW2ldKSk7XG4gIH1cbiAgY29uc3QgbG9jYWwgPSBjb25maWcucGx1Z2lucyB8fCBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsb2NhbC5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IHBsdWdpbiA9IGxvY2FsW2ldO1xuICAgIGlmIChwbHVnaW5zLmluZGV4T2YocGx1Z2luKSA9PT0gLTEpIHtcbiAgICAgIHBsdWdpbnMucHVzaChwbHVnaW4pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcGx1Z2lucztcbn1cbmZ1bmN0aW9uIGdldE9wdHMob3B0aW9ucywgYWxsKSB7XG4gIGlmICghYWxsICYmIG9wdGlvbnMgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgaWYgKG9wdGlvbnMgPT09IHRydWUpIHtcbiAgICByZXR1cm4ge307XG4gIH1cbiAgcmV0dXJuIG9wdGlvbnM7XG59XG5mdW5jdGlvbiBjcmVhdGVEZXNjcmlwdG9ycyhjaGFydCwgcGx1Z2lucywgb3B0aW9ucywgYWxsKSB7XG4gIGNvbnN0IHJlc3VsdCA9IFtdO1xuICBjb25zdCBjb250ZXh0ID0gY2hhcnQuZ2V0Q29udGV4dCgpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHBsdWdpbnMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBwbHVnaW4gPSBwbHVnaW5zW2ldO1xuICAgIGNvbnN0IGlkID0gcGx1Z2luLmlkO1xuICAgIGNvbnN0IG9wdHMgPSBnZXRPcHRzKG9wdGlvbnNbaWRdLCBhbGwpO1xuICAgIGlmIChvcHRzID09PSBudWxsKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgcmVzdWx0LnB1c2goe1xuICAgICAgcGx1Z2luLFxuICAgICAgb3B0aW9uczogcGx1Z2luT3B0cyhjaGFydC5jb25maWcsIHBsdWdpbiwgb3B0cywgY29udGV4dClcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gcGx1Z2luT3B0cyhjb25maWcsIHBsdWdpbiwgb3B0cywgY29udGV4dCkge1xuICBjb25zdCBrZXlzID0gY29uZmlnLnBsdWdpblNjb3BlS2V5cyhwbHVnaW4pO1xuICBjb25zdCBzY29wZXMgPSBjb25maWcuZ2V0T3B0aW9uU2NvcGVzKG9wdHMsIGtleXMpO1xuICByZXR1cm4gY29uZmlnLmNyZWF0ZVJlc29sdmVyKHNjb3BlcywgY29udGV4dCwgWycnXSwge3NjcmlwdGFibGU6IGZhbHNlLCBpbmRleGFibGU6IGZhbHNlLCBhbGxLZXlzOiB0cnVlfSk7XG59XG5cbmZ1bmN0aW9uIGdldEluZGV4QXhpcyh0eXBlLCBvcHRpb25zKSB7XG4gIGNvbnN0IGRhdGFzZXREZWZhdWx0cyA9IGRlZmF1bHRzLmRhdGFzZXRzW3R5cGVdIHx8IHt9O1xuICBjb25zdCBkYXRhc2V0T3B0aW9ucyA9IChvcHRpb25zLmRhdGFzZXRzIHx8IHt9KVt0eXBlXSB8fCB7fTtcbiAgcmV0dXJuIGRhdGFzZXRPcHRpb25zLmluZGV4QXhpcyB8fCBvcHRpb25zLmluZGV4QXhpcyB8fCBkYXRhc2V0RGVmYXVsdHMuaW5kZXhBeGlzIHx8ICd4Jztcbn1cbmZ1bmN0aW9uIGdldEF4aXNGcm9tRGVmYXVsdFNjYWxlSUQoaWQsIGluZGV4QXhpcykge1xuICBsZXQgYXhpcyA9IGlkO1xuICBpZiAoaWQgPT09ICdfaW5kZXhfJykge1xuICAgIGF4aXMgPSBpbmRleEF4aXM7XG4gIH0gZWxzZSBpZiAoaWQgPT09ICdfdmFsdWVfJykge1xuICAgIGF4aXMgPSBpbmRleEF4aXMgPT09ICd4JyA/ICd5JyA6ICd4JztcbiAgfVxuICByZXR1cm4gYXhpcztcbn1cbmZ1bmN0aW9uIGdldERlZmF1bHRTY2FsZUlERnJvbUF4aXMoYXhpcywgaW5kZXhBeGlzKSB7XG4gIHJldHVybiBheGlzID09PSBpbmRleEF4aXMgPyAnX2luZGV4XycgOiAnX3ZhbHVlXyc7XG59XG5mdW5jdGlvbiBheGlzRnJvbVBvc2l0aW9uKHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgcG9zaXRpb24gPT09ICdib3R0b20nKSB7XG4gICAgcmV0dXJuICd4JztcbiAgfVxuICBpZiAocG9zaXRpb24gPT09ICdsZWZ0JyB8fCBwb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgIHJldHVybiAneSc7XG4gIH1cbn1cbmZ1bmN0aW9uIGRldGVybWluZUF4aXMoaWQsIHNjYWxlT3B0aW9ucykge1xuICBpZiAoaWQgPT09ICd4JyB8fCBpZCA9PT0gJ3knKSB7XG4gICAgcmV0dXJuIGlkO1xuICB9XG4gIHJldHVybiBzY2FsZU9wdGlvbnMuYXhpcyB8fCBheGlzRnJvbVBvc2l0aW9uKHNjYWxlT3B0aW9ucy5wb3NpdGlvbikgfHwgaWQuY2hhckF0KDApLnRvTG93ZXJDYXNlKCk7XG59XG5mdW5jdGlvbiBtZXJnZVNjYWxlQ29uZmlnKGNvbmZpZywgb3B0aW9ucykge1xuICBjb25zdCBjaGFydERlZmF1bHRzID0gb3ZlcnJpZGVzW2NvbmZpZy50eXBlXSB8fCB7c2NhbGVzOiB7fX07XG4gIGNvbnN0IGNvbmZpZ1NjYWxlcyA9IG9wdGlvbnMuc2NhbGVzIHx8IHt9O1xuICBjb25zdCBjaGFydEluZGV4QXhpcyA9IGdldEluZGV4QXhpcyhjb25maWcudHlwZSwgb3B0aW9ucyk7XG4gIGNvbnN0IGZpcnN0SURzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgY29uc3Qgc2NhbGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgT2JqZWN0LmtleXMoY29uZmlnU2NhbGVzKS5mb3JFYWNoKGlkID0+IHtcbiAgICBjb25zdCBzY2FsZUNvbmYgPSBjb25maWdTY2FsZXNbaWRdO1xuICAgIGNvbnN0IGF4aXMgPSBkZXRlcm1pbmVBeGlzKGlkLCBzY2FsZUNvbmYpO1xuICAgIGNvbnN0IGRlZmF1bHRJZCA9IGdldERlZmF1bHRTY2FsZUlERnJvbUF4aXMoYXhpcywgY2hhcnRJbmRleEF4aXMpO1xuICAgIGNvbnN0IGRlZmF1bHRTY2FsZU9wdGlvbnMgPSBjaGFydERlZmF1bHRzLnNjYWxlcyB8fCB7fTtcbiAgICBmaXJzdElEc1theGlzXSA9IGZpcnN0SURzW2F4aXNdIHx8IGlkO1xuICAgIHNjYWxlc1tpZF0gPSBtZXJnZUlmKE9iamVjdC5jcmVhdGUobnVsbCksIFt7YXhpc30sIHNjYWxlQ29uZiwgZGVmYXVsdFNjYWxlT3B0aW9uc1theGlzXSwgZGVmYXVsdFNjYWxlT3B0aW9uc1tkZWZhdWx0SWRdXSk7XG4gIH0pO1xuICBjb25maWcuZGF0YS5kYXRhc2V0cy5mb3JFYWNoKGRhdGFzZXQgPT4ge1xuICAgIGNvbnN0IHR5cGUgPSBkYXRhc2V0LnR5cGUgfHwgY29uZmlnLnR5cGU7XG4gICAgY29uc3QgaW5kZXhBeGlzID0gZGF0YXNldC5pbmRleEF4aXMgfHwgZ2V0SW5kZXhBeGlzKHR5cGUsIG9wdGlvbnMpO1xuICAgIGNvbnN0IGRhdGFzZXREZWZhdWx0cyA9IG92ZXJyaWRlc1t0eXBlXSB8fCB7fTtcbiAgICBjb25zdCBkZWZhdWx0U2NhbGVPcHRpb25zID0gZGF0YXNldERlZmF1bHRzLnNjYWxlcyB8fCB7fTtcbiAgICBPYmplY3Qua2V5cyhkZWZhdWx0U2NhbGVPcHRpb25zKS5mb3JFYWNoKGRlZmF1bHRJRCA9PiB7XG4gICAgICBjb25zdCBheGlzID0gZ2V0QXhpc0Zyb21EZWZhdWx0U2NhbGVJRChkZWZhdWx0SUQsIGluZGV4QXhpcyk7XG4gICAgICBjb25zdCBpZCA9IGRhdGFzZXRbYXhpcyArICdBeGlzSUQnXSB8fCBmaXJzdElEc1theGlzXSB8fCBheGlzO1xuICAgICAgc2NhbGVzW2lkXSA9IHNjYWxlc1tpZF0gfHwgT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgIG1lcmdlSWYoc2NhbGVzW2lkXSwgW3theGlzfSwgY29uZmlnU2NhbGVzW2lkXSwgZGVmYXVsdFNjYWxlT3B0aW9uc1tkZWZhdWx0SURdXSk7XG4gICAgfSk7XG4gIH0pO1xuICBPYmplY3Qua2V5cyhzY2FsZXMpLmZvckVhY2goa2V5ID0+IHtcbiAgICBjb25zdCBzY2FsZSA9IHNjYWxlc1trZXldO1xuICAgIG1lcmdlSWYoc2NhbGUsIFtkZWZhdWx0cy5zY2FsZXNbc2NhbGUudHlwZV0sIGRlZmF1bHRzLnNjYWxlXSk7XG4gIH0pO1xuICByZXR1cm4gc2NhbGVzO1xufVxuZnVuY3Rpb24gaW5pdE9wdGlvbnMoY29uZmlnKSB7XG4gIGNvbnN0IG9wdGlvbnMgPSBjb25maWcub3B0aW9ucyB8fCAoY29uZmlnLm9wdGlvbnMgPSB7fSk7XG4gIG9wdGlvbnMucGx1Z2lucyA9IHZhbHVlT3JEZWZhdWx0KG9wdGlvbnMucGx1Z2lucywge30pO1xuICBvcHRpb25zLnNjYWxlcyA9IG1lcmdlU2NhbGVDb25maWcoY29uZmlnLCBvcHRpb25zKTtcbn1cbmZ1bmN0aW9uIGluaXREYXRhKGRhdGEpIHtcbiAgZGF0YSA9IGRhdGEgfHwge307XG4gIGRhdGEuZGF0YXNldHMgPSBkYXRhLmRhdGFzZXRzIHx8IFtdO1xuICBkYXRhLmxhYmVscyA9IGRhdGEubGFiZWxzIHx8IFtdO1xuICByZXR1cm4gZGF0YTtcbn1cbmZ1bmN0aW9uIGluaXRDb25maWcoY29uZmlnKSB7XG4gIGNvbmZpZyA9IGNvbmZpZyB8fCB7fTtcbiAgY29uZmlnLmRhdGEgPSBpbml0RGF0YShjb25maWcuZGF0YSk7XG4gIGluaXRPcHRpb25zKGNvbmZpZyk7XG4gIHJldHVybiBjb25maWc7XG59XG5jb25zdCBrZXlDYWNoZSA9IG5ldyBNYXAoKTtcbmNvbnN0IGtleXNDYWNoZWQgPSBuZXcgU2V0KCk7XG5mdW5jdGlvbiBjYWNoZWRLZXlzKGNhY2hlS2V5LCBnZW5lcmF0ZSkge1xuICBsZXQga2V5cyA9IGtleUNhY2hlLmdldChjYWNoZUtleSk7XG4gIGlmICgha2V5cykge1xuICAgIGtleXMgPSBnZW5lcmF0ZSgpO1xuICAgIGtleUNhY2hlLnNldChjYWNoZUtleSwga2V5cyk7XG4gICAga2V5c0NhY2hlZC5hZGQoa2V5cyk7XG4gIH1cbiAgcmV0dXJuIGtleXM7XG59XG5jb25zdCBhZGRJZkZvdW5kID0gKHNldCwgb2JqLCBrZXkpID0+IHtcbiAgY29uc3Qgb3B0cyA9IHJlc29sdmVPYmplY3RLZXkob2JqLCBrZXkpO1xuICBpZiAob3B0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgc2V0LmFkZChvcHRzKTtcbiAgfVxufTtcbmNsYXNzIENvbmZpZyB7XG4gIGNvbnN0cnVjdG9yKGNvbmZpZykge1xuICAgIHRoaXMuX2NvbmZpZyA9IGluaXRDb25maWcoY29uZmlnKTtcbiAgICB0aGlzLl9zY29wZUNhY2hlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuX3Jlc29sdmVyQ2FjaGUgPSBuZXcgTWFwKCk7XG4gIH1cbiAgZ2V0IHBsYXRmb3JtKCkge1xuICAgIHJldHVybiB0aGlzLl9jb25maWcucGxhdGZvcm07XG4gIH1cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy50eXBlO1xuICB9XG4gIHNldCB0eXBlKHR5cGUpIHtcbiAgICB0aGlzLl9jb25maWcudHlwZSA9IHR5cGU7XG4gIH1cbiAgZ2V0IGRhdGEoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhO1xuICB9XG4gIHNldCBkYXRhKGRhdGEpIHtcbiAgICB0aGlzLl9jb25maWcuZGF0YSA9IGluaXREYXRhKGRhdGEpO1xuICB9XG4gIGdldCBvcHRpb25zKCkge1xuICAgIHJldHVybiB0aGlzLl9jb25maWcub3B0aW9ucztcbiAgfVxuICBzZXQgb3B0aW9ucyhvcHRpb25zKSB7XG4gICAgdGhpcy5fY29uZmlnLm9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG4gIGdldCBwbHVnaW5zKCkge1xuICAgIHJldHVybiB0aGlzLl9jb25maWcucGx1Z2lucztcbiAgfVxuICB1cGRhdGUoKSB7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5fY29uZmlnO1xuICAgIHRoaXMuY2xlYXJDYWNoZSgpO1xuICAgIGluaXRPcHRpb25zKGNvbmZpZyk7XG4gIH1cbiAgY2xlYXJDYWNoZSgpIHtcbiAgICB0aGlzLl9zY29wZUNhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5fcmVzb2x2ZXJDYWNoZS5jbGVhcigpO1xuICB9XG4gIGRhdGFzZXRTY29wZUtleXMoZGF0YXNldFR5cGUpIHtcbiAgICByZXR1cm4gY2FjaGVkS2V5cyhkYXRhc2V0VHlwZSxcbiAgICAgICgpID0+IFtbXG4gICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfWAsXG4gICAgICAgICcnXG4gICAgICBdXSk7XG4gIH1cbiAgZGF0YXNldEFuaW1hdGlvblNjb3BlS2V5cyhkYXRhc2V0VHlwZSwgdHJhbnNpdGlvbikge1xuICAgIHJldHVybiBjYWNoZWRLZXlzKGAke2RhdGFzZXRUeXBlfS50cmFuc2l0aW9uLiR7dHJhbnNpdGlvbn1gLFxuICAgICAgKCkgPT4gW1xuICAgICAgICBbXG4gICAgICAgICAgYGRhdGFzZXRzLiR7ZGF0YXNldFR5cGV9LnRyYW5zaXRpb25zLiR7dHJhbnNpdGlvbn1gLFxuICAgICAgICAgIGB0cmFuc2l0aW9ucy4ke3RyYW5zaXRpb259YCxcbiAgICAgICAgXSxcbiAgICAgICAgW1xuICAgICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfWAsXG4gICAgICAgICAgJydcbiAgICAgICAgXVxuICAgICAgXSk7XG4gIH1cbiAgZGF0YXNldEVsZW1lbnRTY29wZUtleXMoZGF0YXNldFR5cGUsIGVsZW1lbnRUeXBlKSB7XG4gICAgcmV0dXJuIGNhY2hlZEtleXMoYCR7ZGF0YXNldFR5cGV9LSR7ZWxlbWVudFR5cGV9YCxcbiAgICAgICgpID0+IFtbXG4gICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfS5lbGVtZW50cy4ke2VsZW1lbnRUeXBlfWAsXG4gICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfWAsXG4gICAgICAgIGBlbGVtZW50cy4ke2VsZW1lbnRUeXBlfWAsXG4gICAgICAgICcnXG4gICAgICBdXSk7XG4gIH1cbiAgcGx1Z2luU2NvcGVLZXlzKHBsdWdpbikge1xuICAgIGNvbnN0IGlkID0gcGx1Z2luLmlkO1xuICAgIGNvbnN0IHR5cGUgPSB0aGlzLnR5cGU7XG4gICAgcmV0dXJuIGNhY2hlZEtleXMoYCR7dHlwZX0tcGx1Z2luLSR7aWR9YCxcbiAgICAgICgpID0+IFtbXG4gICAgICAgIGBwbHVnaW5zLiR7aWR9YCxcbiAgICAgICAgLi4ucGx1Z2luLmFkZGl0aW9uYWxPcHRpb25TY29wZXMgfHwgW10sXG4gICAgICBdXSk7XG4gIH1cbiAgX2NhY2hlZFNjb3BlcyhtYWluU2NvcGUsIHJlc2V0Q2FjaGUpIHtcbiAgICBjb25zdCBfc2NvcGVDYWNoZSA9IHRoaXMuX3Njb3BlQ2FjaGU7XG4gICAgbGV0IGNhY2hlID0gX3Njb3BlQ2FjaGUuZ2V0KG1haW5TY29wZSk7XG4gICAgaWYgKCFjYWNoZSB8fCByZXNldENhY2hlKSB7XG4gICAgICBjYWNoZSA9IG5ldyBNYXAoKTtcbiAgICAgIF9zY29wZUNhY2hlLnNldChtYWluU2NvcGUsIGNhY2hlKTtcbiAgICB9XG4gICAgcmV0dXJuIGNhY2hlO1xuICB9XG4gIGdldE9wdGlvblNjb3BlcyhtYWluU2NvcGUsIGtleUxpc3RzLCByZXNldENhY2hlKSB7XG4gICAgY29uc3Qge29wdGlvbnMsIHR5cGV9ID0gdGhpcztcbiAgICBjb25zdCBjYWNoZSA9IHRoaXMuX2NhY2hlZFNjb3BlcyhtYWluU2NvcGUsIHJlc2V0Q2FjaGUpO1xuICAgIGNvbnN0IGNhY2hlZCA9IGNhY2hlLmdldChrZXlMaXN0cyk7XG4gICAgaWYgKGNhY2hlZCkge1xuICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG4gICAgY29uc3Qgc2NvcGVzID0gbmV3IFNldCgpO1xuICAgIGtleUxpc3RzLmZvckVhY2goa2V5cyA9PiB7XG4gICAgICBpZiAobWFpblNjb3BlKSB7XG4gICAgICAgIHNjb3Blcy5hZGQobWFpblNjb3BlKTtcbiAgICAgICAga2V5cy5mb3JFYWNoKGtleSA9PiBhZGRJZkZvdW5kKHNjb3BlcywgbWFpblNjb3BlLCBrZXkpKTtcbiAgICAgIH1cbiAgICAgIGtleXMuZm9yRWFjaChrZXkgPT4gYWRkSWZGb3VuZChzY29wZXMsIG9wdGlvbnMsIGtleSkpO1xuICAgICAga2V5cy5mb3JFYWNoKGtleSA9PiBhZGRJZkZvdW5kKHNjb3Blcywgb3ZlcnJpZGVzW3R5cGVdIHx8IHt9LCBrZXkpKTtcbiAgICAgIGtleXMuZm9yRWFjaChrZXkgPT4gYWRkSWZGb3VuZChzY29wZXMsIGRlZmF1bHRzLCBrZXkpKTtcbiAgICAgIGtleXMuZm9yRWFjaChrZXkgPT4gYWRkSWZGb3VuZChzY29wZXMsIGRlc2NyaXB0b3JzLCBrZXkpKTtcbiAgICB9KTtcbiAgICBjb25zdCBhcnJheSA9IEFycmF5LmZyb20oc2NvcGVzKTtcbiAgICBpZiAoYXJyYXkubGVuZ3RoID09PSAwKSB7XG4gICAgICBhcnJheS5wdXNoKE9iamVjdC5jcmVhdGUobnVsbCkpO1xuICAgIH1cbiAgICBpZiAoa2V5c0NhY2hlZC5oYXMoa2V5TGlzdHMpKSB7XG4gICAgICBjYWNoZS5zZXQoa2V5TGlzdHMsIGFycmF5KTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG4gIGNoYXJ0T3B0aW9uU2NvcGVzKCkge1xuICAgIGNvbnN0IHtvcHRpb25zLCB0eXBlfSA9IHRoaXM7XG4gICAgcmV0dXJuIFtcbiAgICAgIG9wdGlvbnMsXG4gICAgICBvdmVycmlkZXNbdHlwZV0gfHwge30sXG4gICAgICBkZWZhdWx0cy5kYXRhc2V0c1t0eXBlXSB8fCB7fSxcbiAgICAgIHt0eXBlfSxcbiAgICAgIGRlZmF1bHRzLFxuICAgICAgZGVzY3JpcHRvcnNcbiAgICBdO1xuICB9XG4gIHJlc29sdmVOYW1lZE9wdGlvbnMoc2NvcGVzLCBuYW1lcywgY29udGV4dCwgcHJlZml4ZXMgPSBbJyddKSB7XG4gICAgY29uc3QgcmVzdWx0ID0geyRzaGFyZWQ6IHRydWV9O1xuICAgIGNvbnN0IHtyZXNvbHZlciwgc3ViUHJlZml4ZXN9ID0gZ2V0UmVzb2x2ZXIodGhpcy5fcmVzb2x2ZXJDYWNoZSwgc2NvcGVzLCBwcmVmaXhlcyk7XG4gICAgbGV0IG9wdGlvbnMgPSByZXNvbHZlcjtcbiAgICBpZiAobmVlZENvbnRleHQocmVzb2x2ZXIsIG5hbWVzKSkge1xuICAgICAgcmVzdWx0LiRzaGFyZWQgPSBmYWxzZTtcbiAgICAgIGNvbnRleHQgPSBpc0Z1bmN0aW9uKGNvbnRleHQpID8gY29udGV4dCgpIDogY29udGV4dDtcbiAgICAgIGNvbnN0IHN1YlJlc29sdmVyID0gdGhpcy5jcmVhdGVSZXNvbHZlcihzY29wZXMsIGNvbnRleHQsIHN1YlByZWZpeGVzKTtcbiAgICAgIG9wdGlvbnMgPSBfYXR0YWNoQ29udGV4dChyZXNvbHZlciwgY29udGV4dCwgc3ViUmVzb2x2ZXIpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IHByb3Agb2YgbmFtZXMpIHtcbiAgICAgIHJlc3VsdFtwcm9wXSA9IG9wdGlvbnNbcHJvcF07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgY3JlYXRlUmVzb2x2ZXIoc2NvcGVzLCBjb250ZXh0LCBwcmVmaXhlcyA9IFsnJ10sIGRlc2NyaXB0b3JEZWZhdWx0cykge1xuICAgIGNvbnN0IHtyZXNvbHZlcn0gPSBnZXRSZXNvbHZlcih0aGlzLl9yZXNvbHZlckNhY2hlLCBzY29wZXMsIHByZWZpeGVzKTtcbiAgICByZXR1cm4gaXNPYmplY3QoY29udGV4dClcbiAgICAgID8gX2F0dGFjaENvbnRleHQocmVzb2x2ZXIsIGNvbnRleHQsIHVuZGVmaW5lZCwgZGVzY3JpcHRvckRlZmF1bHRzKVxuICAgICAgOiByZXNvbHZlcjtcbiAgfVxufVxuZnVuY3Rpb24gZ2V0UmVzb2x2ZXIocmVzb2x2ZXJDYWNoZSwgc2NvcGVzLCBwcmVmaXhlcykge1xuICBsZXQgY2FjaGUgPSByZXNvbHZlckNhY2hlLmdldChzY29wZXMpO1xuICBpZiAoIWNhY2hlKSB7XG4gICAgY2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgcmVzb2x2ZXJDYWNoZS5zZXQoc2NvcGVzLCBjYWNoZSk7XG4gIH1cbiAgY29uc3QgY2FjaGVLZXkgPSBwcmVmaXhlcy5qb2luKCk7XG4gIGxldCBjYWNoZWQgPSBjYWNoZS5nZXQoY2FjaGVLZXkpO1xuICBpZiAoIWNhY2hlZCkge1xuICAgIGNvbnN0IHJlc29sdmVyID0gX2NyZWF0ZVJlc29sdmVyKHNjb3BlcywgcHJlZml4ZXMpO1xuICAgIGNhY2hlZCA9IHtcbiAgICAgIHJlc29sdmVyLFxuICAgICAgc3ViUHJlZml4ZXM6IHByZWZpeGVzLmZpbHRlcihwID0+ICFwLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ2hvdmVyJykpXG4gICAgfTtcbiAgICBjYWNoZS5zZXQoY2FjaGVLZXksIGNhY2hlZCk7XG4gIH1cbiAgcmV0dXJuIGNhY2hlZDtcbn1cbmZ1bmN0aW9uIG5lZWRDb250ZXh0KHByb3h5LCBuYW1lcykge1xuICBjb25zdCB7aXNTY3JpcHRhYmxlLCBpc0luZGV4YWJsZX0gPSBfZGVzY3JpcHRvcnMocHJveHkpO1xuICBmb3IgKGNvbnN0IHByb3Agb2YgbmFtZXMpIHtcbiAgICBpZiAoKGlzU2NyaXB0YWJsZShwcm9wKSAmJiBpc0Z1bmN0aW9uKHByb3h5W3Byb3BdKSlcbiAgICAgIHx8IChpc0luZGV4YWJsZShwcm9wKSAmJiBpc0FycmF5KHByb3h5W3Byb3BdKSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbnZhciB2ZXJzaW9uID0gXCIzLjUuMVwiO1xuXG5jb25zdCBLTk9XTl9QT1NJVElPTlMgPSBbJ3RvcCcsICdib3R0b20nLCAnbGVmdCcsICdyaWdodCcsICdjaGFydEFyZWEnXTtcbmZ1bmN0aW9uIHBvc2l0aW9uSXNIb3Jpem9udGFsKHBvc2l0aW9uLCBheGlzKSB7XG4gIHJldHVybiBwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgcG9zaXRpb24gPT09ICdib3R0b20nIHx8IChLTk9XTl9QT1NJVElPTlMuaW5kZXhPZihwb3NpdGlvbikgPT09IC0xICYmIGF4aXMgPT09ICd4Jyk7XG59XG5mdW5jdGlvbiBjb21wYXJlMkxldmVsKGwxLCBsMikge1xuICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBhW2wxXSA9PT0gYltsMV1cbiAgICAgID8gYVtsMl0gLSBiW2wyXVxuICAgICAgOiBhW2wxXSAtIGJbbDFdO1xuICB9O1xufVxuZnVuY3Rpb24gb25BbmltYXRpb25zQ29tcGxldGUoY29udGV4dCkge1xuICBjb25zdCBjaGFydCA9IGNvbnRleHQuY2hhcnQ7XG4gIGNvbnN0IGFuaW1hdGlvbk9wdGlvbnMgPSBjaGFydC5vcHRpb25zLmFuaW1hdGlvbjtcbiAgY2hhcnQubm90aWZ5UGx1Z2lucygnYWZ0ZXJSZW5kZXInKTtcbiAgY2FsbGJhY2soYW5pbWF0aW9uT3B0aW9ucyAmJiBhbmltYXRpb25PcHRpb25zLm9uQ29tcGxldGUsIFtjb250ZXh0XSwgY2hhcnQpO1xufVxuZnVuY3Rpb24gb25BbmltYXRpb25Qcm9ncmVzcyhjb250ZXh0KSB7XG4gIGNvbnN0IGNoYXJ0ID0gY29udGV4dC5jaGFydDtcbiAgY29uc3QgYW5pbWF0aW9uT3B0aW9ucyA9IGNoYXJ0Lm9wdGlvbnMuYW5pbWF0aW9uO1xuICBjYWxsYmFjayhhbmltYXRpb25PcHRpb25zICYmIGFuaW1hdGlvbk9wdGlvbnMub25Qcm9ncmVzcywgW2NvbnRleHRdLCBjaGFydCk7XG59XG5mdW5jdGlvbiBnZXRDYW52YXMoaXRlbSkge1xuICBpZiAoX2lzRG9tU3VwcG9ydGVkKCkgJiYgdHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnKSB7XG4gICAgaXRlbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGl0ZW0pO1xuICB9IGVsc2UgaWYgKGl0ZW0gJiYgaXRlbS5sZW5ndGgpIHtcbiAgICBpdGVtID0gaXRlbVswXTtcbiAgfVxuICBpZiAoaXRlbSAmJiBpdGVtLmNhbnZhcykge1xuICAgIGl0ZW0gPSBpdGVtLmNhbnZhcztcbiAgfVxuICByZXR1cm4gaXRlbTtcbn1cbmNvbnN0IGluc3RhbmNlcyA9IHt9O1xuY29uc3QgZ2V0Q2hhcnQgPSAoa2V5KSA9PiB7XG4gIGNvbnN0IGNhbnZhcyA9IGdldENhbnZhcyhrZXkpO1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhpbnN0YW5jZXMpLmZpbHRlcigoYykgPT4gYy5jYW52YXMgPT09IGNhbnZhcykucG9wKCk7XG59O1xuY2xhc3MgQ2hhcnQge1xuICBjb25zdHJ1Y3RvcihpdGVtLCB1c2VyQ29uZmlnKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuY29uZmlnID0gbmV3IENvbmZpZyh1c2VyQ29uZmlnKTtcbiAgICBjb25zdCBpbml0aWFsQ2FudmFzID0gZ2V0Q2FudmFzKGl0ZW0pO1xuICAgIGNvbnN0IGV4aXN0aW5nQ2hhcnQgPSBnZXRDaGFydChpbml0aWFsQ2FudmFzKTtcbiAgICBpZiAoZXhpc3RpbmdDaGFydCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnQ2FudmFzIGlzIGFscmVhZHkgaW4gdXNlLiBDaGFydCB3aXRoIElEIFxcJycgKyBleGlzdGluZ0NoYXJ0LmlkICsgJ1xcJycgK1xuXHRcdFx0XHQnIG11c3QgYmUgZGVzdHJveWVkIGJlZm9yZSB0aGUgY2FudmFzIGNhbiBiZSByZXVzZWQuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3Qgb3B0aW9ucyA9IGNvbmZpZy5jcmVhdGVSZXNvbHZlcihjb25maWcuY2hhcnRPcHRpb25TY29wZXMoKSwgbWUuZ2V0Q29udGV4dCgpKTtcbiAgICB0aGlzLnBsYXRmb3JtID0gbmV3IChjb25maWcucGxhdGZvcm0gfHwgX2RldGVjdFBsYXRmb3JtKGluaXRpYWxDYW52YXMpKSgpO1xuICAgIGNvbnN0IGNvbnRleHQgPSBtZS5wbGF0Zm9ybS5hY3F1aXJlQ29udGV4dChpbml0aWFsQ2FudmFzLCBvcHRpb25zLmFzcGVjdFJhdGlvKTtcbiAgICBjb25zdCBjYW52YXMgPSBjb250ZXh0ICYmIGNvbnRleHQuY2FudmFzO1xuICAgIGNvbnN0IGhlaWdodCA9IGNhbnZhcyAmJiBjYW52YXMuaGVpZ2h0O1xuICAgIGNvbnN0IHdpZHRoID0gY2FudmFzICYmIGNhbnZhcy53aWR0aDtcbiAgICB0aGlzLmlkID0gdWlkKCk7XG4gICAgdGhpcy5jdHggPSBjb250ZXh0O1xuICAgIHRoaXMuY2FudmFzID0gY2FudmFzO1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLl9hc3BlY3RSYXRpbyA9IHRoaXMuYXNwZWN0UmF0aW87XG4gICAgdGhpcy5fbGF5ZXJzID0gW107XG4gICAgdGhpcy5fbWV0YXNldHMgPSBbXTtcbiAgICB0aGlzLl9zdGFja3MgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5ib3hlcyA9IFtdO1xuICAgIHRoaXMuY3VycmVudERldmljZVBpeGVsUmF0aW8gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5jaGFydEFyZWEgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fYWN0aXZlID0gW107XG4gICAgdGhpcy5fbGFzdEV2ZW50ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX2xpc3RlbmVycyA9IHt9O1xuICAgIHRoaXMuX3Jlc3BvbnNpdmVMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fc29ydGVkTWV0YXNldHMgPSBbXTtcbiAgICB0aGlzLnNjYWxlcyA9IHt9O1xuICAgIHRoaXMuX3BsdWdpbnMgPSBuZXcgUGx1Z2luU2VydmljZSgpO1xuICAgIHRoaXMuJHByb3hpZXMgPSB7fTtcbiAgICB0aGlzLl9oaWRkZW5JbmRpY2VzID0ge307XG4gICAgdGhpcy5hdHRhY2hlZCA9IGZhbHNlO1xuICAgIHRoaXMuX2FuaW1hdGlvbnNEaXNhYmxlZCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLiRjb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX2RvUmVzaXplID0gZGVib3VuY2UoKCkgPT4gdGhpcy51cGRhdGUoJ3Jlc2l6ZScpLCBvcHRpb25zLnJlc2l6ZURlbGF5IHx8IDApO1xuICAgIGluc3RhbmNlc1ttZS5pZF0gPSBtZTtcbiAgICBpZiAoIWNvbnRleHQgfHwgIWNhbnZhcykge1xuICAgICAgY29uc29sZS5lcnJvcihcIkZhaWxlZCB0byBjcmVhdGUgY2hhcnQ6IGNhbid0IGFjcXVpcmUgY29udGV4dCBmcm9tIHRoZSBnaXZlbiBpdGVtXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhbmltYXRvci5saXN0ZW4obWUsICdjb21wbGV0ZScsIG9uQW5pbWF0aW9uc0NvbXBsZXRlKTtcbiAgICBhbmltYXRvci5saXN0ZW4obWUsICdwcm9ncmVzcycsIG9uQW5pbWF0aW9uUHJvZ3Jlc3MpO1xuICAgIG1lLl9pbml0aWFsaXplKCk7XG4gICAgaWYgKG1lLmF0dGFjaGVkKSB7XG4gICAgICBtZS51cGRhdGUoKTtcbiAgICB9XG4gIH1cbiAgZ2V0IGFzcGVjdFJhdGlvKCkge1xuICAgIGNvbnN0IHtvcHRpb25zOiB7YXNwZWN0UmF0aW8sIG1haW50YWluQXNwZWN0UmF0aW99LCB3aWR0aCwgaGVpZ2h0LCBfYXNwZWN0UmF0aW99ID0gdGhpcztcbiAgICBpZiAoIWlzTnVsbE9yVW5kZWYoYXNwZWN0UmF0aW8pKSB7XG4gICAgICByZXR1cm4gYXNwZWN0UmF0aW87XG4gICAgfVxuICAgIGlmIChtYWludGFpbkFzcGVjdFJhdGlvICYmIF9hc3BlY3RSYXRpbykge1xuICAgICAgcmV0dXJuIF9hc3BlY3RSYXRpbztcbiAgICB9XG4gICAgcmV0dXJuIGhlaWdodCA/IHdpZHRoIC8gaGVpZ2h0IDogbnVsbDtcbiAgfVxuICBnZXQgZGF0YSgpIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YTtcbiAgfVxuICBzZXQgZGF0YShkYXRhKSB7XG4gICAgdGhpcy5jb25maWcuZGF0YSA9IGRhdGE7XG4gIH1cbiAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gIH1cbiAgc2V0IG9wdGlvbnMob3B0aW9ucykge1xuICAgIHRoaXMuY29uZmlnLm9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG4gIF9pbml0aWFsaXplKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBtZS5ub3RpZnlQbHVnaW5zKCdiZWZvcmVJbml0Jyk7XG4gICAgaWYgKG1lLm9wdGlvbnMucmVzcG9uc2l2ZSkge1xuICAgICAgbWUucmVzaXplKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldGluYVNjYWxlKG1lLCBtZS5vcHRpb25zLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIH1cbiAgICBtZS5iaW5kRXZlbnRzKCk7XG4gICAgbWUubm90aWZ5UGx1Z2lucygnYWZ0ZXJJbml0Jyk7XG4gICAgcmV0dXJuIG1lO1xuICB9XG4gIGNsZWFyKCkge1xuICAgIGNsZWFyQ2FudmFzKHRoaXMuY2FudmFzLCB0aGlzLmN0eCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgc3RvcCgpIHtcbiAgICBhbmltYXRvci5zdG9wKHRoaXMpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIHJlc2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgaWYgKCFhbmltYXRvci5ydW5uaW5nKHRoaXMpKSB7XG4gICAgICB0aGlzLl9yZXNpemUod2lkdGgsIGhlaWdodCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3Jlc2l6ZUJlZm9yZURyYXcgPSB7d2lkdGgsIGhlaWdodH07XG4gICAgfVxuICB9XG4gIF9yZXNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRpb25zID0gbWUub3B0aW9ucztcbiAgICBjb25zdCBjYW52YXMgPSBtZS5jYW52YXM7XG4gICAgY29uc3QgYXNwZWN0UmF0aW8gPSBvcHRpb25zLm1haW50YWluQXNwZWN0UmF0aW8gJiYgbWUuYXNwZWN0UmF0aW87XG4gICAgY29uc3QgbmV3U2l6ZSA9IG1lLnBsYXRmb3JtLmdldE1heGltdW1TaXplKGNhbnZhcywgd2lkdGgsIGhlaWdodCwgYXNwZWN0UmF0aW8pO1xuICAgIGNvbnN0IG5ld1JhdGlvID0gb3B0aW9ucy5kZXZpY2VQaXhlbFJhdGlvIHx8IG1lLnBsYXRmb3JtLmdldERldmljZVBpeGVsUmF0aW8oKTtcbiAgICBtZS53aWR0aCA9IG5ld1NpemUud2lkdGg7XG4gICAgbWUuaGVpZ2h0ID0gbmV3U2l6ZS5oZWlnaHQ7XG4gICAgbWUuX2FzcGVjdFJhdGlvID0gbWUuYXNwZWN0UmF0aW87XG4gICAgaWYgKCFyZXRpbmFTY2FsZShtZSwgbmV3UmF0aW8sIHRydWUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIG1lLm5vdGlmeVBsdWdpbnMoJ3Jlc2l6ZScsIHtzaXplOiBuZXdTaXplfSk7XG4gICAgY2FsbGJhY2sob3B0aW9ucy5vblJlc2l6ZSwgW21lLCBuZXdTaXplXSwgbWUpO1xuICAgIGlmIChtZS5hdHRhY2hlZCkge1xuICAgICAgaWYgKG1lLl9kb1Jlc2l6ZSgpKSB7XG4gICAgICAgIG1lLnJlbmRlcigpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBlbnN1cmVTY2FsZXNIYXZlSURzKCkge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgY29uc3Qgc2NhbGVzT3B0aW9ucyA9IG9wdGlvbnMuc2NhbGVzIHx8IHt9O1xuICAgIGVhY2goc2NhbGVzT3B0aW9ucywgKGF4aXNPcHRpb25zLCBheGlzSUQpID0+IHtcbiAgICAgIGF4aXNPcHRpb25zLmlkID0gYXhpc0lEO1xuICAgIH0pO1xuICB9XG4gIGJ1aWxkT3JVcGRhdGVTY2FsZXMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IHNjYWxlT3B0cyA9IG9wdGlvbnMuc2NhbGVzO1xuICAgIGNvbnN0IHNjYWxlcyA9IG1lLnNjYWxlcztcbiAgICBjb25zdCB1cGRhdGVkID0gT2JqZWN0LmtleXMoc2NhbGVzKS5yZWR1Y2UoKG9iaiwgaWQpID0+IHtcbiAgICAgIG9ialtpZF0gPSBmYWxzZTtcbiAgICAgIHJldHVybiBvYmo7XG4gICAgfSwge30pO1xuICAgIGxldCBpdGVtcyA9IFtdO1xuICAgIGlmIChzY2FsZU9wdHMpIHtcbiAgICAgIGl0ZW1zID0gaXRlbXMuY29uY2F0KFxuICAgICAgICBPYmplY3Qua2V5cyhzY2FsZU9wdHMpLm1hcCgoaWQpID0+IHtcbiAgICAgICAgICBjb25zdCBzY2FsZU9wdGlvbnMgPSBzY2FsZU9wdHNbaWRdO1xuICAgICAgICAgIGNvbnN0IGF4aXMgPSBkZXRlcm1pbmVBeGlzKGlkLCBzY2FsZU9wdGlvbnMpO1xuICAgICAgICAgIGNvbnN0IGlzUmFkaWFsID0gYXhpcyA9PT0gJ3InO1xuICAgICAgICAgIGNvbnN0IGlzSG9yaXpvbnRhbCA9IGF4aXMgPT09ICd4JztcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb3B0aW9uczogc2NhbGVPcHRpb25zLFxuICAgICAgICAgICAgZHBvc2l0aW9uOiBpc1JhZGlhbCA/ICdjaGFydEFyZWEnIDogaXNIb3Jpem9udGFsID8gJ2JvdHRvbScgOiAnbGVmdCcsXG4gICAgICAgICAgICBkdHlwZTogaXNSYWRpYWwgPyAncmFkaWFsTGluZWFyJyA6IGlzSG9yaXpvbnRhbCA/ICdjYXRlZ29yeScgOiAnbGluZWFyJ1xuICAgICAgICAgIH07XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cbiAgICBlYWNoKGl0ZW1zLCAoaXRlbSkgPT4ge1xuICAgICAgY29uc3Qgc2NhbGVPcHRpb25zID0gaXRlbS5vcHRpb25zO1xuICAgICAgY29uc3QgaWQgPSBzY2FsZU9wdGlvbnMuaWQ7XG4gICAgICBjb25zdCBheGlzID0gZGV0ZXJtaW5lQXhpcyhpZCwgc2NhbGVPcHRpb25zKTtcbiAgICAgIGNvbnN0IHNjYWxlVHlwZSA9IHZhbHVlT3JEZWZhdWx0KHNjYWxlT3B0aW9ucy50eXBlLCBpdGVtLmR0eXBlKTtcbiAgICAgIGlmIChzY2FsZU9wdGlvbnMucG9zaXRpb24gPT09IHVuZGVmaW5lZCB8fCBwb3NpdGlvbklzSG9yaXpvbnRhbChzY2FsZU9wdGlvbnMucG9zaXRpb24sIGF4aXMpICE9PSBwb3NpdGlvbklzSG9yaXpvbnRhbChpdGVtLmRwb3NpdGlvbikpIHtcbiAgICAgICAgc2NhbGVPcHRpb25zLnBvc2l0aW9uID0gaXRlbS5kcG9zaXRpb247XG4gICAgICB9XG4gICAgICB1cGRhdGVkW2lkXSA9IHRydWU7XG4gICAgICBsZXQgc2NhbGUgPSBudWxsO1xuICAgICAgaWYgKGlkIGluIHNjYWxlcyAmJiBzY2FsZXNbaWRdLnR5cGUgPT09IHNjYWxlVHlwZSkge1xuICAgICAgICBzY2FsZSA9IHNjYWxlc1tpZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBzY2FsZUNsYXNzID0gcmVnaXN0cnkuZ2V0U2NhbGUoc2NhbGVUeXBlKTtcbiAgICAgICAgc2NhbGUgPSBuZXcgc2NhbGVDbGFzcyh7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgdHlwZTogc2NhbGVUeXBlLFxuICAgICAgICAgIGN0eDogbWUuY3R4LFxuICAgICAgICAgIGNoYXJ0OiBtZVxuICAgICAgICB9KTtcbiAgICAgICAgc2NhbGVzW3NjYWxlLmlkXSA9IHNjYWxlO1xuICAgICAgfVxuICAgICAgc2NhbGUuaW5pdChzY2FsZU9wdGlvbnMsIG9wdGlvbnMpO1xuICAgIH0pO1xuICAgIGVhY2godXBkYXRlZCwgKGhhc1VwZGF0ZWQsIGlkKSA9PiB7XG4gICAgICBpZiAoIWhhc1VwZGF0ZWQpIHtcbiAgICAgICAgZGVsZXRlIHNjYWxlc1tpZF07XG4gICAgICB9XG4gICAgfSk7XG4gICAgZWFjaChzY2FsZXMsIChzY2FsZSkgPT4ge1xuICAgICAgbGF5b3V0cy5jb25maWd1cmUobWUsIHNjYWxlLCBzY2FsZS5vcHRpb25zKTtcbiAgICAgIGxheW91dHMuYWRkQm94KG1lLCBzY2FsZSk7XG4gICAgfSk7XG4gIH1cbiAgX3VwZGF0ZU1ldGFzZXRzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhc2V0cyA9IG1lLl9tZXRhc2V0cztcbiAgICBjb25zdCBudW1EYXRhID0gbWUuZGF0YS5kYXRhc2V0cy5sZW5ndGg7XG4gICAgY29uc3QgbnVtTWV0YSA9IG1ldGFzZXRzLmxlbmd0aDtcbiAgICBtZXRhc2V0cy5zb3J0KChhLCBiKSA9PiBhLmluZGV4IC0gYi5pbmRleCk7XG4gICAgaWYgKG51bU1ldGEgPiBudW1EYXRhKSB7XG4gICAgICBmb3IgKGxldCBpID0gbnVtRGF0YTsgaSA8IG51bU1ldGE7ICsraSkge1xuICAgICAgICBtZS5fZGVzdHJveURhdGFzZXRNZXRhKGkpO1xuICAgICAgfVxuICAgICAgbWV0YXNldHMuc3BsaWNlKG51bURhdGEsIG51bU1ldGEgLSBudW1EYXRhKTtcbiAgICB9XG4gICAgbWUuX3NvcnRlZE1ldGFzZXRzID0gbWV0YXNldHMuc2xpY2UoMCkuc29ydChjb21wYXJlMkxldmVsKCdvcmRlcicsICdpbmRleCcpKTtcbiAgfVxuICBfcmVtb3ZlVW5yZWZlcmVuY2VkTWV0YXNldHMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtfbWV0YXNldHM6IG1ldGFzZXRzLCBkYXRhOiB7ZGF0YXNldHN9fSA9IG1lO1xuICAgIGlmIChtZXRhc2V0cy5sZW5ndGggPiBkYXRhc2V0cy5sZW5ndGgpIHtcbiAgICAgIGRlbGV0ZSBtZS5fc3RhY2tzO1xuICAgIH1cbiAgICBtZXRhc2V0cy5mb3JFYWNoKChtZXRhLCBpbmRleCkgPT4ge1xuICAgICAgaWYgKGRhdGFzZXRzLmZpbHRlcih4ID0+IHggPT09IG1ldGEuX2RhdGFzZXQpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBtZS5fZGVzdHJveURhdGFzZXRNZXRhKGluZGV4KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICBidWlsZE9yVXBkYXRlQ29udHJvbGxlcnMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG5ld0NvbnRyb2xsZXJzID0gW107XG4gICAgY29uc3QgZGF0YXNldHMgPSBtZS5kYXRhLmRhdGFzZXRzO1xuICAgIGxldCBpLCBpbGVuO1xuICAgIG1lLl9yZW1vdmVVbnJlZmVyZW5jZWRNZXRhc2V0cygpO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBkYXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IGRhdGFzZXQgPSBkYXRhc2V0c1tpXTtcbiAgICAgIGxldCBtZXRhID0gbWUuZ2V0RGF0YXNldE1ldGEoaSk7XG4gICAgICBjb25zdCB0eXBlID0gZGF0YXNldC50eXBlIHx8IG1lLmNvbmZpZy50eXBlO1xuICAgICAgaWYgKG1ldGEudHlwZSAmJiBtZXRhLnR5cGUgIT09IHR5cGUpIHtcbiAgICAgICAgbWUuX2Rlc3Ryb3lEYXRhc2V0TWV0YShpKTtcbiAgICAgICAgbWV0YSA9IG1lLmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgfVxuICAgICAgbWV0YS50eXBlID0gdHlwZTtcbiAgICAgIG1ldGEuaW5kZXhBeGlzID0gZGF0YXNldC5pbmRleEF4aXMgfHwgZ2V0SW5kZXhBeGlzKHR5cGUsIG1lLm9wdGlvbnMpO1xuICAgICAgbWV0YS5vcmRlciA9IGRhdGFzZXQub3JkZXIgfHwgMDtcbiAgICAgIG1ldGEuaW5kZXggPSBpO1xuICAgICAgbWV0YS5sYWJlbCA9ICcnICsgZGF0YXNldC5sYWJlbDtcbiAgICAgIG1ldGEudmlzaWJsZSA9IG1lLmlzRGF0YXNldFZpc2libGUoaSk7XG4gICAgICBpZiAobWV0YS5jb250cm9sbGVyKSB7XG4gICAgICAgIG1ldGEuY29udHJvbGxlci51cGRhdGVJbmRleChpKTtcbiAgICAgICAgbWV0YS5jb250cm9sbGVyLmxpbmtTY2FsZXMoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IENvbnRyb2xsZXJDbGFzcyA9IHJlZ2lzdHJ5LmdldENvbnRyb2xsZXIodHlwZSk7XG4gICAgICAgIGNvbnN0IHtkYXRhc2V0RWxlbWVudFR5cGUsIGRhdGFFbGVtZW50VHlwZX0gPSBkZWZhdWx0cy5kYXRhc2V0c1t0eXBlXTtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihDb250cm9sbGVyQ2xhc3MucHJvdG90eXBlLCB7XG4gICAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiByZWdpc3RyeS5nZXRFbGVtZW50KGRhdGFFbGVtZW50VHlwZSksXG4gICAgICAgICAgZGF0YXNldEVsZW1lbnRUeXBlOiBkYXRhc2V0RWxlbWVudFR5cGUgJiYgcmVnaXN0cnkuZ2V0RWxlbWVudChkYXRhc2V0RWxlbWVudFR5cGUpXG4gICAgICAgIH0pO1xuICAgICAgICBtZXRhLmNvbnRyb2xsZXIgPSBuZXcgQ29udHJvbGxlckNsYXNzKG1lLCBpKTtcbiAgICAgICAgbmV3Q29udHJvbGxlcnMucHVzaChtZXRhLmNvbnRyb2xsZXIpO1xuICAgICAgfVxuICAgIH1cbiAgICBtZS5fdXBkYXRlTWV0YXNldHMoKTtcbiAgICByZXR1cm4gbmV3Q29udHJvbGxlcnM7XG4gIH1cbiAgX3Jlc2V0RWxlbWVudHMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGVhY2gobWUuZGF0YS5kYXRhc2V0cywgKGRhdGFzZXQsIGRhdGFzZXRJbmRleCkgPT4ge1xuICAgICAgbWUuZ2V0RGF0YXNldE1ldGEoZGF0YXNldEluZGV4KS5jb250cm9sbGVyLnJlc2V0KCk7XG4gICAgfSwgbWUpO1xuICB9XG4gIHJlc2V0KCkge1xuICAgIHRoaXMuX3Jlc2V0RWxlbWVudHMoKTtcbiAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ3Jlc2V0Jyk7XG4gIH1cbiAgdXBkYXRlKG1vZGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgY29uZmlnID0gbWUuY29uZmlnO1xuICAgIGNvbmZpZy51cGRhdGUoKTtcbiAgICBtZS5fb3B0aW9ucyA9IGNvbmZpZy5jcmVhdGVSZXNvbHZlcihjb25maWcuY2hhcnRPcHRpb25TY29wZXMoKSwgbWUuZ2V0Q29udGV4dCgpKTtcbiAgICBlYWNoKG1lLnNjYWxlcywgKHNjYWxlKSA9PiB7XG4gICAgICBsYXlvdXRzLnJlbW92ZUJveChtZSwgc2NhbGUpO1xuICAgIH0pO1xuICAgIGNvbnN0IGFuaW1zRGlzYWJsZWQgPSBtZS5fYW5pbWF0aW9uc0Rpc2FibGVkID0gIW1lLm9wdGlvbnMuYW5pbWF0aW9uO1xuICAgIG1lLmVuc3VyZVNjYWxlc0hhdmVJRHMoKTtcbiAgICBtZS5idWlsZE9yVXBkYXRlU2NhbGVzKCk7XG4gICAgY29uc3QgZXhpc3RpbmdFdmVudHMgPSBuZXcgU2V0KE9iamVjdC5rZXlzKG1lLl9saXN0ZW5lcnMpKTtcbiAgICBjb25zdCBuZXdFdmVudHMgPSBuZXcgU2V0KG1lLm9wdGlvbnMuZXZlbnRzKTtcbiAgICBpZiAoIXNldHNFcXVhbChleGlzdGluZ0V2ZW50cywgbmV3RXZlbnRzKSB8fCAhIXRoaXMuX3Jlc3BvbnNpdmVMaXN0ZW5lcnMgIT09IG1lLm9wdGlvbnMucmVzcG9uc2l2ZSkge1xuICAgICAgbWUudW5iaW5kRXZlbnRzKCk7XG4gICAgICBtZS5iaW5kRXZlbnRzKCk7XG4gICAgfVxuICAgIG1lLl9wbHVnaW5zLmludmFsaWRhdGUoKTtcbiAgICBpZiAobWUubm90aWZ5UGx1Z2lucygnYmVmb3JlVXBkYXRlJywge21vZGUsIGNhbmNlbGFibGU6IHRydWV9KSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbmV3Q29udHJvbGxlcnMgPSBtZS5idWlsZE9yVXBkYXRlQ29udHJvbGxlcnMoKTtcbiAgICBtZS5ub3RpZnlQbHVnaW5zKCdiZWZvcmVFbGVtZW50c1VwZGF0ZScpO1xuICAgIGxldCBtaW5QYWRkaW5nID0gMDtcbiAgICBmb3IgKGxldCBpID0gMCwgaWxlbiA9IG1lLmRhdGEuZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKSB7XG4gICAgICBjb25zdCB7Y29udHJvbGxlcn0gPSBtZS5nZXREYXRhc2V0TWV0YShpKTtcbiAgICAgIGNvbnN0IHJlc2V0ID0gIWFuaW1zRGlzYWJsZWQgJiYgbmV3Q29udHJvbGxlcnMuaW5kZXhPZihjb250cm9sbGVyKSA9PT0gLTE7XG4gICAgICBjb250cm9sbGVyLmJ1aWxkT3JVcGRhdGVFbGVtZW50cyhyZXNldCk7XG4gICAgICBtaW5QYWRkaW5nID0gTWF0aC5tYXgoK2NvbnRyb2xsZXIuZ2V0TWF4T3ZlcmZsb3coKSwgbWluUGFkZGluZyk7XG4gICAgfVxuICAgIG1lLl9taW5QYWRkaW5nID0gbWluUGFkZGluZztcbiAgICBtZS5fdXBkYXRlTGF5b3V0KG1pblBhZGRpbmcpO1xuICAgIGlmICghYW5pbXNEaXNhYmxlZCkge1xuICAgICAgZWFjaChuZXdDb250cm9sbGVycywgKGNvbnRyb2xsZXIpID0+IHtcbiAgICAgICAgY29udHJvbGxlci5yZXNldCgpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIG1lLl91cGRhdGVEYXRhc2V0cyhtb2RlKTtcbiAgICBtZS5ub3RpZnlQbHVnaW5zKCdhZnRlclVwZGF0ZScsIHttb2RlfSk7XG4gICAgbWUuX2xheWVycy5zb3J0KGNvbXBhcmUyTGV2ZWwoJ3onLCAnX2lkeCcpKTtcbiAgICBpZiAobWUuX2xhc3RFdmVudCkge1xuICAgICAgbWUuX2V2ZW50SGFuZGxlcihtZS5fbGFzdEV2ZW50LCB0cnVlKTtcbiAgICB9XG4gICAgbWUucmVuZGVyKCk7XG4gIH1cbiAgX3VwZGF0ZUxheW91dChtaW5QYWRkaW5nKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmIChtZS5ub3RpZnlQbHVnaW5zKCdiZWZvcmVMYXlvdXQnLCB7Y2FuY2VsYWJsZTogdHJ1ZX0pID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsYXlvdXRzLnVwZGF0ZShtZSwgbWUud2lkdGgsIG1lLmhlaWdodCwgbWluUGFkZGluZyk7XG4gICAgY29uc3QgYXJlYSA9IG1lLmNoYXJ0QXJlYTtcbiAgICBjb25zdCBub0FyZWEgPSBhcmVhLndpZHRoIDw9IDAgfHwgYXJlYS5oZWlnaHQgPD0gMDtcbiAgICBtZS5fbGF5ZXJzID0gW107XG4gICAgZWFjaChtZS5ib3hlcywgKGJveCkgPT4ge1xuICAgICAgaWYgKG5vQXJlYSAmJiBib3gucG9zaXRpb24gPT09ICdjaGFydEFyZWEnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChib3guY29uZmlndXJlKSB7XG4gICAgICAgIGJveC5jb25maWd1cmUoKTtcbiAgICAgIH1cbiAgICAgIG1lLl9sYXllcnMucHVzaCguLi5ib3guX2xheWVycygpKTtcbiAgICB9LCBtZSk7XG4gICAgbWUuX2xheWVycy5mb3JFYWNoKChpdGVtLCBpbmRleCkgPT4ge1xuICAgICAgaXRlbS5faWR4ID0gaW5kZXg7XG4gICAgfSk7XG4gICAgbWUubm90aWZ5UGx1Z2lucygnYWZ0ZXJMYXlvdXQnKTtcbiAgfVxuICBfdXBkYXRlRGF0YXNldHMobW9kZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBpc0Z1bmN0aW9uID0gdHlwZW9mIG1vZGUgPT09ICdmdW5jdGlvbic7XG4gICAgaWYgKG1lLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZURhdGFzZXRzVXBkYXRlJywge21vZGUsIGNhbmNlbGFibGU6IHRydWV9KSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDAsIGlsZW4gPSBtZS5kYXRhLmRhdGFzZXRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgbWUuX3VwZGF0ZURhdGFzZXQoaSwgaXNGdW5jdGlvbiA/IG1vZGUoe2RhdGFzZXRJbmRleDogaX0pIDogbW9kZSk7XG4gICAgfVxuICAgIG1lLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGF0YXNldHNVcGRhdGUnLCB7bW9kZX0pO1xuICB9XG4gIF91cGRhdGVEYXRhc2V0KGluZGV4LCBtb2RlKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGEgPSBtZS5nZXREYXRhc2V0TWV0YShpbmRleCk7XG4gICAgY29uc3QgYXJncyA9IHttZXRhLCBpbmRleCwgbW9kZSwgY2FuY2VsYWJsZTogdHJ1ZX07XG4gICAgaWYgKG1lLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZURhdGFzZXRVcGRhdGUnLCBhcmdzKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbWV0YS5jb250cm9sbGVyLl91cGRhdGUobW9kZSk7XG4gICAgYXJncy5jYW5jZWxhYmxlID0gZmFsc2U7XG4gICAgbWUubm90aWZ5UGx1Z2lucygnYWZ0ZXJEYXRhc2V0VXBkYXRlJywgYXJncyk7XG4gIH1cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBpZiAobWUubm90aWZ5UGx1Z2lucygnYmVmb3JlUmVuZGVyJywge2NhbmNlbGFibGU6IHRydWV9KSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGFuaW1hdG9yLmhhcyhtZSkpIHtcbiAgICAgIGlmIChtZS5hdHRhY2hlZCAmJiAhYW5pbWF0b3IucnVubmluZyhtZSkpIHtcbiAgICAgICAgYW5pbWF0b3Iuc3RhcnQobWUpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBtZS5kcmF3KCk7XG4gICAgICBvbkFuaW1hdGlvbnNDb21wbGV0ZSh7Y2hhcnQ6IG1lfSk7XG4gICAgfVxuICB9XG4gIGRyYXcoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGxldCBpO1xuICAgIGlmIChtZS5fcmVzaXplQmVmb3JlRHJhdykge1xuICAgICAgY29uc3Qge3dpZHRoLCBoZWlnaHR9ID0gbWUuX3Jlc2l6ZUJlZm9yZURyYXc7XG4gICAgICBtZS5fcmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgbWUuX3Jlc2l6ZUJlZm9yZURyYXcgPSBudWxsO1xuICAgIH1cbiAgICBtZS5jbGVhcigpO1xuICAgIGlmIChtZS53aWR0aCA8PSAwIHx8IG1lLmhlaWdodCA8PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChtZS5ub3RpZnlQbHVnaW5zKCdiZWZvcmVEcmF3Jywge2NhbmNlbGFibGU6IHRydWV9KSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbGF5ZXJzID0gbWUuX2xheWVycztcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aCAmJiBsYXllcnNbaV0ueiA8PSAwOyArK2kpIHtcbiAgICAgIGxheWVyc1tpXS5kcmF3KG1lLmNoYXJ0QXJlYSk7XG4gICAgfVxuICAgIG1lLl9kcmF3RGF0YXNldHMoKTtcbiAgICBmb3IgKDsgaSA8IGxheWVycy5sZW5ndGg7ICsraSkge1xuICAgICAgbGF5ZXJzW2ldLmRyYXcobWUuY2hhcnRBcmVhKTtcbiAgICB9XG4gICAgbWUubm90aWZ5UGx1Z2lucygnYWZ0ZXJEcmF3Jyk7XG4gIH1cbiAgX2dldFNvcnRlZERhdGFzZXRNZXRhcyhmaWx0ZXJWaXNpYmxlKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG1ldGFzZXRzID0gbWUuX3NvcnRlZE1ldGFzZXRzO1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpLCBpbGVuO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBtZXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGNvbnN0IG1ldGEgPSBtZXRhc2V0c1tpXTtcbiAgICAgIGlmICghZmlsdGVyVmlzaWJsZSB8fCBtZXRhLnZpc2libGUpIHtcbiAgICAgICAgcmVzdWx0LnB1c2gobWV0YSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0U29ydGVkRGF0YXNldE1ldGFzKHRydWUpO1xuICB9XG4gIF9kcmF3RGF0YXNldHMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmIChtZS5ub3RpZnlQbHVnaW5zKCdiZWZvcmVEYXRhc2V0c0RyYXcnLCB7Y2FuY2VsYWJsZTogdHJ1ZX0pID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBtZXRhc2V0cyA9IG1lLmdldFNvcnRlZFZpc2libGVEYXRhc2V0TWV0YXMoKTtcbiAgICBmb3IgKGxldCBpID0gbWV0YXNldHMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIG1lLl9kcmF3RGF0YXNldChtZXRhc2V0c1tpXSk7XG4gICAgfVxuICAgIG1lLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGF0YXNldHNEcmF3Jyk7XG4gIH1cbiAgX2RyYXdEYXRhc2V0KG1ldGEpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgY3R4ID0gbWUuY3R4O1xuICAgIGNvbnN0IGNsaXAgPSBtZXRhLl9jbGlwO1xuICAgIGNvbnN0IHVzZUNsaXAgPSAhY2xpcC5kaXNhYmxlZDtcbiAgICBjb25zdCBhcmVhID0gbWUuY2hhcnRBcmVhO1xuICAgIGNvbnN0IGFyZ3MgPSB7XG4gICAgICBtZXRhLFxuICAgICAgaW5kZXg6IG1ldGEuaW5kZXgsXG4gICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgfTtcbiAgICBpZiAobWUubm90aWZ5UGx1Z2lucygnYmVmb3JlRGF0YXNldERyYXcnLCBhcmdzKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHVzZUNsaXApIHtcbiAgICAgIGNsaXBBcmVhKGN0eCwge1xuICAgICAgICBsZWZ0OiBjbGlwLmxlZnQgPT09IGZhbHNlID8gMCA6IGFyZWEubGVmdCAtIGNsaXAubGVmdCxcbiAgICAgICAgcmlnaHQ6IGNsaXAucmlnaHQgPT09IGZhbHNlID8gbWUud2lkdGggOiBhcmVhLnJpZ2h0ICsgY2xpcC5yaWdodCxcbiAgICAgICAgdG9wOiBjbGlwLnRvcCA9PT0gZmFsc2UgPyAwIDogYXJlYS50b3AgLSBjbGlwLnRvcCxcbiAgICAgICAgYm90dG9tOiBjbGlwLmJvdHRvbSA9PT0gZmFsc2UgPyBtZS5oZWlnaHQgOiBhcmVhLmJvdHRvbSArIGNsaXAuYm90dG9tXG4gICAgICB9KTtcbiAgICB9XG4gICAgbWV0YS5jb250cm9sbGVyLmRyYXcoKTtcbiAgICBpZiAodXNlQ2xpcCkge1xuICAgICAgdW5jbGlwQXJlYShjdHgpO1xuICAgIH1cbiAgICBhcmdzLmNhbmNlbGFibGUgPSBmYWxzZTtcbiAgICBtZS5ub3RpZnlQbHVnaW5zKCdhZnRlckRhdGFzZXREcmF3JywgYXJncyk7XG4gIH1cbiAgZ2V0RWxlbWVudHNBdEV2ZW50Rm9yTW9kZShlLCBtb2RlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgY29uc3QgbWV0aG9kID0gSW50ZXJhY3Rpb24ubW9kZXNbbW9kZV07XG4gICAgaWYgKHR5cGVvZiBtZXRob2QgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiBtZXRob2QodGhpcywgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuICBnZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgZGF0YXNldCA9IG1lLmRhdGEuZGF0YXNldHNbZGF0YXNldEluZGV4XTtcbiAgICBjb25zdCBtZXRhc2V0cyA9IG1lLl9tZXRhc2V0cztcbiAgICBsZXQgbWV0YSA9IG1ldGFzZXRzLmZpbHRlcih4ID0+IHggJiYgeC5fZGF0YXNldCA9PT0gZGF0YXNldCkucG9wKCk7XG4gICAgaWYgKCFtZXRhKSB7XG4gICAgICBtZXRhID0ge1xuICAgICAgICB0eXBlOiBudWxsLFxuICAgICAgICBkYXRhOiBbXSxcbiAgICAgICAgZGF0YXNldDogbnVsbCxcbiAgICAgICAgY29udHJvbGxlcjogbnVsbCxcbiAgICAgICAgaGlkZGVuOiBudWxsLFxuICAgICAgICB4QXhpc0lEOiBudWxsLFxuICAgICAgICB5QXhpc0lEOiBudWxsLFxuICAgICAgICBvcmRlcjogZGF0YXNldCAmJiBkYXRhc2V0Lm9yZGVyIHx8IDAsXG4gICAgICAgIGluZGV4OiBkYXRhc2V0SW5kZXgsXG4gICAgICAgIF9kYXRhc2V0OiBkYXRhc2V0LFxuICAgICAgICBfcGFyc2VkOiBbXSxcbiAgICAgICAgX3NvcnRlZDogZmFsc2VcbiAgICAgIH07XG4gICAgICBtZXRhc2V0cy5wdXNoKG1ldGEpO1xuICAgIH1cbiAgICByZXR1cm4gbWV0YTtcbiAgfVxuICBnZXRDb250ZXh0KCkge1xuICAgIHJldHVybiB0aGlzLiRjb250ZXh0IHx8ICh0aGlzLiRjb250ZXh0ID0ge2NoYXJ0OiB0aGlzLCB0eXBlOiAnY2hhcnQnfSk7XG4gIH1cbiAgZ2V0VmlzaWJsZURhdGFzZXRDb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCkubGVuZ3RoO1xuICB9XG4gIGlzRGF0YXNldFZpc2libGUoZGF0YXNldEluZGV4KSB7XG4gICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZGF0YS5kYXRhc2V0c1tkYXRhc2V0SW5kZXhdO1xuICAgIGlmICghZGF0YXNldCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgIHJldHVybiB0eXBlb2YgbWV0YS5oaWRkZW4gPT09ICdib29sZWFuJyA/ICFtZXRhLmhpZGRlbiA6ICFkYXRhc2V0LmhpZGRlbjtcbiAgfVxuICBzZXREYXRhc2V0VmlzaWJpbGl0eShkYXRhc2V0SW5kZXgsIHZpc2libGUpIHtcbiAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgIG1ldGEuaGlkZGVuID0gIXZpc2libGU7XG4gIH1cbiAgdG9nZ2xlRGF0YVZpc2liaWxpdHkoaW5kZXgpIHtcbiAgICB0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XSA9ICF0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XTtcbiAgfVxuICBnZXREYXRhVmlzaWJpbGl0eShpbmRleCkge1xuICAgIHJldHVybiAhdGhpcy5faGlkZGVuSW5kaWNlc1tpbmRleF07XG4gIH1cbiAgX3VwZGF0ZVZpc2liaWxpdHkoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgsIHZpc2libGUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbW9kZSA9IHZpc2libGUgPyAnc2hvdycgOiAnaGlkZSc7XG4gICAgY29uc3QgbWV0YSA9IG1lLmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCk7XG4gICAgY29uc3QgYW5pbXMgPSBtZXRhLmNvbnRyb2xsZXIuX3Jlc29sdmVBbmltYXRpb25zKHVuZGVmaW5lZCwgbW9kZSk7XG4gICAgaWYgKGRlZmluZWQoZGF0YUluZGV4KSkge1xuICAgICAgbWV0YS5kYXRhW2RhdGFJbmRleF0uaGlkZGVuID0gIXZpc2libGU7XG4gICAgICBtZS51cGRhdGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbWUuc2V0RGF0YXNldFZpc2liaWxpdHkoZGF0YXNldEluZGV4LCB2aXNpYmxlKTtcbiAgICAgIGFuaW1zLnVwZGF0ZShtZXRhLCB7dmlzaWJsZX0pO1xuICAgICAgbWUudXBkYXRlKChjdHgpID0+IGN0eC5kYXRhc2V0SW5kZXggPT09IGRhdGFzZXRJbmRleCA/IG1vZGUgOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfVxuICBoaWRlKGRhdGFzZXRJbmRleCwgZGF0YUluZGV4KSB7XG4gICAgdGhpcy5fdXBkYXRlVmlzaWJpbGl0eShkYXRhc2V0SW5kZXgsIGRhdGFJbmRleCwgZmFsc2UpO1xuICB9XG4gIHNob3coZGF0YXNldEluZGV4LCBkYXRhSW5kZXgpIHtcbiAgICB0aGlzLl91cGRhdGVWaXNpYmlsaXR5KGRhdGFzZXRJbmRleCwgZGF0YUluZGV4LCB0cnVlKTtcbiAgfVxuICBfZGVzdHJveURhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtZXRhID0gbWUuX21ldGFzZXRzICYmIG1lLl9tZXRhc2V0c1tkYXRhc2V0SW5kZXhdO1xuICAgIGlmIChtZXRhICYmIG1ldGEuY29udHJvbGxlcikge1xuICAgICAgbWV0YS5jb250cm9sbGVyLl9kZXN0cm95KCk7XG4gICAgICBkZWxldGUgbWUuX21ldGFzZXRzW2RhdGFzZXRJbmRleF07XG4gICAgfVxuICB9XG4gIGRlc3Ryb3koKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtjYW52YXMsIGN0eH0gPSBtZTtcbiAgICBsZXQgaSwgaWxlbjtcbiAgICBtZS5zdG9wKCk7XG4gICAgYW5pbWF0b3IucmVtb3ZlKG1lKTtcbiAgICBmb3IgKGkgPSAwLCBpbGVuID0gbWUuZGF0YS5kYXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIG1lLl9kZXN0cm95RGF0YXNldE1ldGEoaSk7XG4gICAgfVxuICAgIG1lLmNvbmZpZy5jbGVhckNhY2hlKCk7XG4gICAgaWYgKGNhbnZhcykge1xuICAgICAgbWUudW5iaW5kRXZlbnRzKCk7XG4gICAgICBjbGVhckNhbnZhcyhjYW52YXMsIGN0eCk7XG4gICAgICBtZS5wbGF0Zm9ybS5yZWxlYXNlQ29udGV4dChjdHgpO1xuICAgICAgbWUuY2FudmFzID0gbnVsbDtcbiAgICAgIG1lLmN0eCA9IG51bGw7XG4gICAgfVxuICAgIG1lLm5vdGlmeVBsdWdpbnMoJ2Rlc3Ryb3knKTtcbiAgICBkZWxldGUgaW5zdGFuY2VzW21lLmlkXTtcbiAgfVxuICB0b0Jhc2U2NEltYWdlKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gdGhpcy5jYW52YXMudG9EYXRhVVJMKC4uLmFyZ3MpO1xuICB9XG4gIGJpbmRFdmVudHMoKSB7XG4gICAgdGhpcy5iaW5kVXNlckV2ZW50cygpO1xuICAgIGlmICh0aGlzLm9wdGlvbnMucmVzcG9uc2l2ZSkge1xuICAgICAgdGhpcy5iaW5kUmVzcG9uc2l2ZUV2ZW50cygpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmF0dGFjaGVkID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgYmluZFVzZXJFdmVudHMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGxpc3RlbmVycyA9IG1lLl9saXN0ZW5lcnM7XG4gICAgY29uc3QgcGxhdGZvcm0gPSBtZS5wbGF0Zm9ybTtcbiAgICBjb25zdCBfYWRkID0gKHR5cGUsIGxpc3RlbmVyKSA9PiB7XG4gICAgICBwbGF0Zm9ybS5hZGRFdmVudExpc3RlbmVyKG1lLCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgICBsaXN0ZW5lcnNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICB9O1xuICAgIGNvbnN0IGxpc3RlbmVyID0gZnVuY3Rpb24oZSwgeCwgeSkge1xuICAgICAgZS5vZmZzZXRYID0geDtcbiAgICAgIGUub2Zmc2V0WSA9IHk7XG4gICAgICBtZS5fZXZlbnRIYW5kbGVyKGUpO1xuICAgIH07XG4gICAgZWFjaChtZS5vcHRpb25zLmV2ZW50cywgKHR5cGUpID0+IF9hZGQodHlwZSwgbGlzdGVuZXIpKTtcbiAgfVxuICBiaW5kUmVzcG9uc2l2ZUV2ZW50cygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgaWYgKCFtZS5fcmVzcG9uc2l2ZUxpc3RlbmVycykge1xuICAgICAgbWUuX3Jlc3BvbnNpdmVMaXN0ZW5lcnMgPSB7fTtcbiAgICB9XG4gICAgY29uc3QgbGlzdGVuZXJzID0gbWUuX3Jlc3BvbnNpdmVMaXN0ZW5lcnM7XG4gICAgY29uc3QgcGxhdGZvcm0gPSBtZS5wbGF0Zm9ybTtcbiAgICBjb25zdCBfYWRkID0gKHR5cGUsIGxpc3RlbmVyKSA9PiB7XG4gICAgICBwbGF0Zm9ybS5hZGRFdmVudExpc3RlbmVyKG1lLCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgICBsaXN0ZW5lcnNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICB9O1xuICAgIGNvbnN0IF9yZW1vdmUgPSAodHlwZSwgbGlzdGVuZXIpID0+IHtcbiAgICAgIGlmIChsaXN0ZW5lcnNbdHlwZV0pIHtcbiAgICAgICAgcGxhdGZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcihtZSwgdHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICBkZWxldGUgbGlzdGVuZXJzW3R5cGVdO1xuICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgbGlzdGVuZXIgPSAod2lkdGgsIGhlaWdodCkgPT4ge1xuICAgICAgaWYgKG1lLmNhbnZhcykge1xuICAgICAgICBtZS5yZXNpemUod2lkdGgsIGhlaWdodCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBsZXQgZGV0YWNoZWQ7XG4gICAgY29uc3QgYXR0YWNoZWQgPSAoKSA9PiB7XG4gICAgICBfcmVtb3ZlKCdhdHRhY2gnLCBhdHRhY2hlZCk7XG4gICAgICBtZS5hdHRhY2hlZCA9IHRydWU7XG4gICAgICBtZS5yZXNpemUoKTtcbiAgICAgIF9hZGQoJ3Jlc2l6ZScsIGxpc3RlbmVyKTtcbiAgICAgIF9hZGQoJ2RldGFjaCcsIGRldGFjaGVkKTtcbiAgICB9O1xuICAgIGRldGFjaGVkID0gKCkgPT4ge1xuICAgICAgbWUuYXR0YWNoZWQgPSBmYWxzZTtcbiAgICAgIF9yZW1vdmUoJ3Jlc2l6ZScsIGxpc3RlbmVyKTtcbiAgICAgIF9hZGQoJ2F0dGFjaCcsIGF0dGFjaGVkKTtcbiAgICB9O1xuICAgIGlmIChwbGF0Zm9ybS5pc0F0dGFjaGVkKG1lLmNhbnZhcykpIHtcbiAgICAgIGF0dGFjaGVkKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRldGFjaGVkKCk7XG4gICAgfVxuICB9XG4gIHVuYmluZEV2ZW50cygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgZWFjaChtZS5fbGlzdGVuZXJzLCAobGlzdGVuZXIsIHR5cGUpID0+IHtcbiAgICAgIG1lLnBsYXRmb3JtLnJlbW92ZUV2ZW50TGlzdGVuZXIobWUsIHR5cGUsIGxpc3RlbmVyKTtcbiAgICB9KTtcbiAgICBtZS5fbGlzdGVuZXJzID0ge307XG4gICAgZWFjaChtZS5fcmVzcG9uc2l2ZUxpc3RlbmVycywgKGxpc3RlbmVyLCB0eXBlKSA9PiB7XG4gICAgICBtZS5wbGF0Zm9ybS5yZW1vdmVFdmVudExpc3RlbmVyKG1lLCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgfSk7XG4gICAgbWUuX3Jlc3BvbnNpdmVMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG4gIH1cbiAgdXBkYXRlSG92ZXJTdHlsZShpdGVtcywgbW9kZSwgZW5hYmxlZCkge1xuICAgIGNvbnN0IHByZWZpeCA9IGVuYWJsZWQgPyAnc2V0JyA6ICdyZW1vdmUnO1xuICAgIGxldCBtZXRhLCBpdGVtLCBpLCBpbGVuO1xuICAgIGlmIChtb2RlID09PSAnZGF0YXNldCcpIHtcbiAgICAgIG1ldGEgPSB0aGlzLmdldERhdGFzZXRNZXRhKGl0ZW1zWzBdLmRhdGFzZXRJbmRleCk7XG4gICAgICBtZXRhLmNvbnRyb2xsZXJbJ18nICsgcHJlZml4ICsgJ0RhdGFzZXRIb3ZlclN0eWxlJ10oKTtcbiAgICB9XG4gICAgZm9yIChpID0gMCwgaWxlbiA9IGl0ZW1zLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgY29uc3QgY29udHJvbGxlciA9IGl0ZW0gJiYgdGhpcy5nZXREYXRhc2V0TWV0YShpdGVtLmRhdGFzZXRJbmRleCkuY29udHJvbGxlcjtcbiAgICAgIGlmIChjb250cm9sbGVyKSB7XG4gICAgICAgIGNvbnRyb2xsZXJbcHJlZml4ICsgJ0hvdmVyU3R5bGUnXShpdGVtLmVsZW1lbnQsIGl0ZW0uZGF0YXNldEluZGV4LCBpdGVtLmluZGV4KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZ2V0QWN0aXZlRWxlbWVudHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FjdGl2ZSB8fCBbXTtcbiAgfVxuICBzZXRBY3RpdmVFbGVtZW50cyhhY3RpdmVFbGVtZW50cykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBsYXN0QWN0aXZlID0gbWUuX2FjdGl2ZSB8fCBbXTtcbiAgICBjb25zdCBhY3RpdmUgPSBhY3RpdmVFbGVtZW50cy5tYXAoKHtkYXRhc2V0SW5kZXgsIGluZGV4fSkgPT4ge1xuICAgICAgY29uc3QgbWV0YSA9IG1lLmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCk7XG4gICAgICBpZiAoIW1ldGEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBkYXRhc2V0IGZvdW5kIGF0IGluZGV4ICcgKyBkYXRhc2V0SW5kZXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGF0YXNldEluZGV4LFxuICAgICAgICBlbGVtZW50OiBtZXRhLmRhdGFbaW5kZXhdLFxuICAgICAgICBpbmRleCxcbiAgICAgIH07XG4gICAgfSk7XG4gICAgY29uc3QgY2hhbmdlZCA9ICFfZWxlbWVudHNFcXVhbChhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICBtZS5fYWN0aXZlID0gYWN0aXZlO1xuICAgICAgbWUuX3VwZGF0ZUhvdmVyU3R5bGVzKGFjdGl2ZSwgbGFzdEFjdGl2ZSk7XG4gICAgfVxuICB9XG4gIG5vdGlmeVBsdWdpbnMoaG9vaywgYXJncywgZmlsdGVyKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BsdWdpbnMubm90aWZ5KHRoaXMsIGhvb2ssIGFyZ3MsIGZpbHRlcik7XG4gIH1cbiAgX3VwZGF0ZUhvdmVyU3R5bGVzKGFjdGl2ZSwgbGFzdEFjdGl2ZSwgcmVwbGF5KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGhvdmVyT3B0aW9ucyA9IG1lLm9wdGlvbnMuaG92ZXI7XG4gICAgY29uc3QgZGlmZiA9IChhLCBiKSA9PiBhLmZpbHRlcih4ID0+ICFiLnNvbWUoeSA9PiB4LmRhdGFzZXRJbmRleCA9PT0geS5kYXRhc2V0SW5kZXggJiYgeC5pbmRleCA9PT0geS5pbmRleCkpO1xuICAgIGNvbnN0IGRlYWN0aXZhdGVkID0gZGlmZihsYXN0QWN0aXZlLCBhY3RpdmUpO1xuICAgIGNvbnN0IGFjdGl2YXRlZCA9IHJlcGxheSA/IGFjdGl2ZSA6IGRpZmYoYWN0aXZlLCBsYXN0QWN0aXZlKTtcbiAgICBpZiAoZGVhY3RpdmF0ZWQubGVuZ3RoKSB7XG4gICAgICBtZS51cGRhdGVIb3ZlclN0eWxlKGRlYWN0aXZhdGVkLCBob3Zlck9wdGlvbnMubW9kZSwgZmFsc2UpO1xuICAgIH1cbiAgICBpZiAoYWN0aXZhdGVkLmxlbmd0aCAmJiBob3Zlck9wdGlvbnMubW9kZSkge1xuICAgICAgbWUudXBkYXRlSG92ZXJTdHlsZShhY3RpdmF0ZWQsIGhvdmVyT3B0aW9ucy5tb2RlLCB0cnVlKTtcbiAgICB9XG4gIH1cbiAgX2V2ZW50SGFuZGxlcihlLCByZXBsYXkpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgYXJncyA9IHtldmVudDogZSwgcmVwbGF5LCBjYW5jZWxhYmxlOiB0cnVlfTtcbiAgICBjb25zdCBldmVudEZpbHRlciA9IChwbHVnaW4pID0+IChwbHVnaW4ub3B0aW9ucy5ldmVudHMgfHwgdGhpcy5vcHRpb25zLmV2ZW50cykuaW5jbHVkZXMoZS50eXBlKTtcbiAgICBpZiAobWUubm90aWZ5UGx1Z2lucygnYmVmb3JlRXZlbnQnLCBhcmdzLCBldmVudEZpbHRlcikgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNoYW5nZWQgPSBtZS5faGFuZGxlRXZlbnQoZSwgcmVwbGF5KTtcbiAgICBhcmdzLmNhbmNlbGFibGUgPSBmYWxzZTtcbiAgICBtZS5ub3RpZnlQbHVnaW5zKCdhZnRlckV2ZW50JywgYXJncywgZXZlbnRGaWx0ZXIpO1xuICAgIGlmIChjaGFuZ2VkIHx8IGFyZ3MuY2hhbmdlZCkge1xuICAgICAgbWUucmVuZGVyKCk7XG4gICAgfVxuICAgIHJldHVybiBtZTtcbiAgfVxuICBfaGFuZGxlRXZlbnQoZSwgcmVwbGF5KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtfYWN0aXZlOiBsYXN0QWN0aXZlID0gW10sIG9wdGlvbnN9ID0gbWU7XG4gICAgY29uc3QgaG92ZXJPcHRpb25zID0gb3B0aW9ucy5ob3ZlcjtcbiAgICBjb25zdCB1c2VGaW5hbFBvc2l0aW9uID0gcmVwbGF5O1xuICAgIGxldCBhY3RpdmUgPSBbXTtcbiAgICBsZXQgY2hhbmdlZCA9IGZhbHNlO1xuICAgIGxldCBsYXN0RXZlbnQgPSBudWxsO1xuICAgIGlmIChlLnR5cGUgIT09ICdtb3VzZW91dCcpIHtcbiAgICAgIGFjdGl2ZSA9IG1lLmdldEVsZW1lbnRzQXRFdmVudEZvck1vZGUoZSwgaG92ZXJPcHRpb25zLm1vZGUsIGhvdmVyT3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICBsYXN0RXZlbnQgPSBlLnR5cGUgPT09ICdjbGljaycgPyBtZS5fbGFzdEV2ZW50IDogZTtcbiAgICB9XG4gICAgbWUuX2xhc3RFdmVudCA9IG51bGw7XG4gICAgaWYgKF9pc1BvaW50SW5BcmVhKGUsIG1lLmNoYXJ0QXJlYSwgbWUuX21pblBhZGRpbmcpKSB7XG4gICAgICBjYWxsYmFjayhvcHRpb25zLm9uSG92ZXIsIFtlLCBhY3RpdmUsIG1lXSwgbWUpO1xuICAgICAgaWYgKGUudHlwZSA9PT0gJ21vdXNldXAnIHx8IGUudHlwZSA9PT0gJ2NsaWNrJyB8fCBlLnR5cGUgPT09ICdjb250ZXh0bWVudScpIHtcbiAgICAgICAgY2FsbGJhY2sob3B0aW9ucy5vbkNsaWNrLCBbZSwgYWN0aXZlLCBtZV0sIG1lKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY2hhbmdlZCA9ICFfZWxlbWVudHNFcXVhbChhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgIGlmIChjaGFuZ2VkIHx8IHJlcGxheSkge1xuICAgICAgbWUuX2FjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgIG1lLl91cGRhdGVIb3ZlclN0eWxlcyhhY3RpdmUsIGxhc3RBY3RpdmUsIHJlcGxheSk7XG4gICAgfVxuICAgIG1lLl9sYXN0RXZlbnQgPSBsYXN0RXZlbnQ7XG4gICAgcmV0dXJuIGNoYW5nZWQ7XG4gIH1cbn1cbmNvbnN0IGludmFsaWRhdGVQbHVnaW5zID0gKCkgPT4gZWFjaChDaGFydC5pbnN0YW5jZXMsIChjaGFydCkgPT4gY2hhcnQuX3BsdWdpbnMuaW52YWxpZGF0ZSgpKTtcbmNvbnN0IGVudW1lcmFibGUgPSB0cnVlO1xuT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoQ2hhcnQsIHtcbiAgZGVmYXVsdHM6IHtcbiAgICBlbnVtZXJhYmxlLFxuICAgIHZhbHVlOiBkZWZhdWx0c1xuICB9LFxuICBpbnN0YW5jZXM6IHtcbiAgICBlbnVtZXJhYmxlLFxuICAgIHZhbHVlOiBpbnN0YW5jZXNcbiAgfSxcbiAgb3ZlcnJpZGVzOiB7XG4gICAgZW51bWVyYWJsZSxcbiAgICB2YWx1ZTogb3ZlcnJpZGVzXG4gIH0sXG4gIHJlZ2lzdHJ5OiB7XG4gICAgZW51bWVyYWJsZSxcbiAgICB2YWx1ZTogcmVnaXN0cnlcbiAgfSxcbiAgdmVyc2lvbjoge1xuICAgIGVudW1lcmFibGUsXG4gICAgdmFsdWU6IHZlcnNpb25cbiAgfSxcbiAgZ2V0Q2hhcnQ6IHtcbiAgICBlbnVtZXJhYmxlLFxuICAgIHZhbHVlOiBnZXRDaGFydFxuICB9LFxuICByZWdpc3Rlcjoge1xuICAgIGVudW1lcmFibGUsXG4gICAgdmFsdWU6ICguLi5pdGVtcykgPT4ge1xuICAgICAgcmVnaXN0cnkuYWRkKC4uLml0ZW1zKTtcbiAgICAgIGludmFsaWRhdGVQbHVnaW5zKCk7XG4gICAgfVxuICB9LFxuICB1bnJlZ2lzdGVyOiB7XG4gICAgZW51bWVyYWJsZSxcbiAgICB2YWx1ZTogKC4uLml0ZW1zKSA9PiB7XG4gICAgICByZWdpc3RyeS5yZW1vdmUoLi4uaXRlbXMpO1xuICAgICAgaW52YWxpZGF0ZVBsdWdpbnMoKTtcbiAgICB9XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiBjbGlwQXJjKGN0eCwgZWxlbWVudCwgZW5kQW5nbGUpIHtcbiAgY29uc3Qge3N0YXJ0QW5nbGUsIHBpeGVsTWFyZ2luLCB4LCB5LCBvdXRlclJhZGl1cywgaW5uZXJSYWRpdXN9ID0gZWxlbWVudDtcbiAgbGV0IGFuZ2xlTWFyZ2luID0gcGl4ZWxNYXJnaW4gLyBvdXRlclJhZGl1cztcbiAgY3R4LmJlZ2luUGF0aCgpO1xuICBjdHguYXJjKHgsIHksIG91dGVyUmFkaXVzLCBzdGFydEFuZ2xlIC0gYW5nbGVNYXJnaW4sIGVuZEFuZ2xlICsgYW5nbGVNYXJnaW4pO1xuICBpZiAoaW5uZXJSYWRpdXMgPiBwaXhlbE1hcmdpbikge1xuICAgIGFuZ2xlTWFyZ2luID0gcGl4ZWxNYXJnaW4gLyBpbm5lclJhZGl1cztcbiAgICBjdHguYXJjKHgsIHksIGlubmVyUmFkaXVzLCBlbmRBbmdsZSArIGFuZ2xlTWFyZ2luLCBzdGFydEFuZ2xlIC0gYW5nbGVNYXJnaW4sIHRydWUpO1xuICB9IGVsc2Uge1xuICAgIGN0eC5hcmMoeCwgeSwgcGl4ZWxNYXJnaW4sIGVuZEFuZ2xlICsgSEFMRl9QSSwgc3RhcnRBbmdsZSAtIEhBTEZfUEkpO1xuICB9XG4gIGN0eC5jbG9zZVBhdGgoKTtcbiAgY3R4LmNsaXAoKTtcbn1cbmZ1bmN0aW9uIHRvUmFkaXVzQ29ybmVycyh2YWx1ZSkge1xuICByZXR1cm4gX3JlYWRWYWx1ZVRvUHJvcHModmFsdWUsIFsnb3V0ZXJTdGFydCcsICdvdXRlckVuZCcsICdpbm5lclN0YXJ0JywgJ2lubmVyRW5kJ10pO1xufVxuZnVuY3Rpb24gcGFyc2VCb3JkZXJSYWRpdXMkMShhcmMsIGlubmVyUmFkaXVzLCBvdXRlclJhZGl1cywgYW5nbGVEZWx0YSkge1xuICBjb25zdCBvID0gdG9SYWRpdXNDb3JuZXJzKGFyYy5vcHRpb25zLmJvcmRlclJhZGl1cyk7XG4gIGNvbnN0IGhhbGZUaGlja25lc3MgPSAob3V0ZXJSYWRpdXMgLSBpbm5lclJhZGl1cykgLyAyO1xuICBjb25zdCBpbm5lckxpbWl0ID0gTWF0aC5taW4oaGFsZlRoaWNrbmVzcywgYW5nbGVEZWx0YSAqIGlubmVyUmFkaXVzIC8gMik7XG4gIGNvbnN0IGNvbXB1dGVPdXRlckxpbWl0ID0gKHZhbCkgPT4ge1xuICAgIGNvbnN0IG91dGVyQXJjTGltaXQgPSAob3V0ZXJSYWRpdXMgLSBNYXRoLm1pbihoYWxmVGhpY2tuZXNzLCB2YWwpKSAqIGFuZ2xlRGVsdGEgLyAyO1xuICAgIHJldHVybiBfbGltaXRWYWx1ZSh2YWwsIDAsIE1hdGgubWluKGhhbGZUaGlja25lc3MsIG91dGVyQXJjTGltaXQpKTtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBvdXRlclN0YXJ0OiBjb21wdXRlT3V0ZXJMaW1pdChvLm91dGVyU3RhcnQpLFxuICAgIG91dGVyRW5kOiBjb21wdXRlT3V0ZXJMaW1pdChvLm91dGVyRW5kKSxcbiAgICBpbm5lclN0YXJ0OiBfbGltaXRWYWx1ZShvLmlubmVyU3RhcnQsIDAsIGlubmVyTGltaXQpLFxuICAgIGlubmVyRW5kOiBfbGltaXRWYWx1ZShvLmlubmVyRW5kLCAwLCBpbm5lckxpbWl0KSxcbiAgfTtcbn1cbmZ1bmN0aW9uIHJUaGV0YVRvWFkociwgdGhldGEsIHgsIHkpIHtcbiAgcmV0dXJuIHtcbiAgICB4OiB4ICsgciAqIE1hdGguY29zKHRoZXRhKSxcbiAgICB5OiB5ICsgciAqIE1hdGguc2luKHRoZXRhKSxcbiAgfTtcbn1cbmZ1bmN0aW9uIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZCkge1xuICBjb25zdCB7eCwgeSwgc3RhcnRBbmdsZTogc3RhcnQsIHBpeGVsTWFyZ2luLCBpbm5lclJhZGl1czogaW5uZXJSfSA9IGVsZW1lbnQ7XG4gIGNvbnN0IG91dGVyUmFkaXVzID0gTWF0aC5tYXgoZWxlbWVudC5vdXRlclJhZGl1cyArIHNwYWNpbmcgKyBvZmZzZXQgLSBwaXhlbE1hcmdpbiwgMCk7XG4gIGNvbnN0IGlubmVyUmFkaXVzID0gaW5uZXJSID4gMCA/IGlubmVyUiArIHNwYWNpbmcgKyBvZmZzZXQgKyBwaXhlbE1hcmdpbiA6IDA7XG4gIGxldCBzcGFjaW5nT2Zmc2V0ID0gMDtcbiAgY29uc3QgYWxwaGEgPSBlbmQgLSBzdGFydDtcbiAgaWYgKHNwYWNpbmcpIHtcbiAgICBjb25zdCBub1NwYWNpbmdJbm5lclJhZGl1cyA9IGlubmVyUiA+IDAgPyBpbm5lclIgLSBzcGFjaW5nIDogMDtcbiAgICBjb25zdCBub1NwYWNpbmdPdXRlclJhZGl1cyA9IG91dGVyUmFkaXVzID4gMCA/IG91dGVyUmFkaXVzIC0gc3BhY2luZyA6IDA7XG4gICAgY29uc3QgYXZOb2dTcGFjaW5nUmFkaXVzID0gKG5vU3BhY2luZ0lubmVyUmFkaXVzICsgbm9TcGFjaW5nT3V0ZXJSYWRpdXMpIC8gMjtcbiAgICBjb25zdCBhZGp1c3RlZEFuZ2xlID0gYXZOb2dTcGFjaW5nUmFkaXVzICE9PSAwID8gKGFscGhhICogYXZOb2dTcGFjaW5nUmFkaXVzKSAvIChhdk5vZ1NwYWNpbmdSYWRpdXMgKyBzcGFjaW5nKSA6IGFscGhhO1xuICAgIHNwYWNpbmdPZmZzZXQgPSAoYWxwaGEgLSBhZGp1c3RlZEFuZ2xlKSAvIDI7XG4gIH1cbiAgY29uc3QgYmV0YSA9IE1hdGgubWF4KDAuMDAxLCBhbHBoYSAqIG91dGVyUmFkaXVzIC0gb2Zmc2V0IC8gUEkpIC8gb3V0ZXJSYWRpdXM7XG4gIGNvbnN0IGFuZ2xlT2Zmc2V0ID0gKGFscGhhIC0gYmV0YSkgLyAyO1xuICBjb25zdCBzdGFydEFuZ2xlID0gc3RhcnQgKyBhbmdsZU9mZnNldCArIHNwYWNpbmdPZmZzZXQ7XG4gIGNvbnN0IGVuZEFuZ2xlID0gZW5kIC0gYW5nbGVPZmZzZXQgLSBzcGFjaW5nT2Zmc2V0O1xuICBjb25zdCB7b3V0ZXJTdGFydCwgb3V0ZXJFbmQsIGlubmVyU3RhcnQsIGlubmVyRW5kfSA9IHBhcnNlQm9yZGVyUmFkaXVzJDEoZWxlbWVudCwgaW5uZXJSYWRpdXMsIG91dGVyUmFkaXVzLCBlbmRBbmdsZSAtIHN0YXJ0QW5nbGUpO1xuICBjb25zdCBvdXRlclN0YXJ0QWRqdXN0ZWRSYWRpdXMgPSBvdXRlclJhZGl1cyAtIG91dGVyU3RhcnQ7XG4gIGNvbnN0IG91dGVyRW5kQWRqdXN0ZWRSYWRpdXMgPSBvdXRlclJhZGl1cyAtIG91dGVyRW5kO1xuICBjb25zdCBvdXRlclN0YXJ0QWRqdXN0ZWRBbmdsZSA9IHN0YXJ0QW5nbGUgKyBvdXRlclN0YXJ0IC8gb3V0ZXJTdGFydEFkanVzdGVkUmFkaXVzO1xuICBjb25zdCBvdXRlckVuZEFkanVzdGVkQW5nbGUgPSBlbmRBbmdsZSAtIG91dGVyRW5kIC8gb3V0ZXJFbmRBZGp1c3RlZFJhZGl1cztcbiAgY29uc3QgaW5uZXJTdGFydEFkanVzdGVkUmFkaXVzID0gaW5uZXJSYWRpdXMgKyBpbm5lclN0YXJ0O1xuICBjb25zdCBpbm5lckVuZEFkanVzdGVkUmFkaXVzID0gaW5uZXJSYWRpdXMgKyBpbm5lckVuZDtcbiAgY29uc3QgaW5uZXJTdGFydEFkanVzdGVkQW5nbGUgPSBzdGFydEFuZ2xlICsgaW5uZXJTdGFydCAvIGlubmVyU3RhcnRBZGp1c3RlZFJhZGl1cztcbiAgY29uc3QgaW5uZXJFbmRBZGp1c3RlZEFuZ2xlID0gZW5kQW5nbGUgLSBpbm5lckVuZCAvIGlubmVyRW5kQWRqdXN0ZWRSYWRpdXM7XG4gIGN0eC5iZWdpblBhdGgoKTtcbiAgY3R4LmFyYyh4LCB5LCBvdXRlclJhZGl1cywgb3V0ZXJTdGFydEFkanVzdGVkQW5nbGUsIG91dGVyRW5kQWRqdXN0ZWRBbmdsZSk7XG4gIGlmIChvdXRlckVuZCA+IDApIHtcbiAgICBjb25zdCBwQ2VudGVyID0gclRoZXRhVG9YWShvdXRlckVuZEFkanVzdGVkUmFkaXVzLCBvdXRlckVuZEFkanVzdGVkQW5nbGUsIHgsIHkpO1xuICAgIGN0eC5hcmMocENlbnRlci54LCBwQ2VudGVyLnksIG91dGVyRW5kLCBvdXRlckVuZEFkanVzdGVkQW5nbGUsIGVuZEFuZ2xlICsgSEFMRl9QSSk7XG4gIH1cbiAgY29uc3QgcDQgPSByVGhldGFUb1hZKGlubmVyRW5kQWRqdXN0ZWRSYWRpdXMsIGVuZEFuZ2xlLCB4LCB5KTtcbiAgY3R4LmxpbmVUbyhwNC54LCBwNC55KTtcbiAgaWYgKGlubmVyRW5kID4gMCkge1xuICAgIGNvbnN0IHBDZW50ZXIgPSByVGhldGFUb1hZKGlubmVyRW5kQWRqdXN0ZWRSYWRpdXMsIGlubmVyRW5kQWRqdXN0ZWRBbmdsZSwgeCwgeSk7XG4gICAgY3R4LmFyYyhwQ2VudGVyLngsIHBDZW50ZXIueSwgaW5uZXJFbmQsIGVuZEFuZ2xlICsgSEFMRl9QSSwgaW5uZXJFbmRBZGp1c3RlZEFuZ2xlICsgTWF0aC5QSSk7XG4gIH1cbiAgY3R4LmFyYyh4LCB5LCBpbm5lclJhZGl1cywgZW5kQW5nbGUgLSAoaW5uZXJFbmQgLyBpbm5lclJhZGl1cyksIHN0YXJ0QW5nbGUgKyAoaW5uZXJTdGFydCAvIGlubmVyUmFkaXVzKSwgdHJ1ZSk7XG4gIGlmIChpbm5lclN0YXJ0ID4gMCkge1xuICAgIGNvbnN0IHBDZW50ZXIgPSByVGhldGFUb1hZKGlubmVyU3RhcnRBZGp1c3RlZFJhZGl1cywgaW5uZXJTdGFydEFkanVzdGVkQW5nbGUsIHgsIHkpO1xuICAgIGN0eC5hcmMocENlbnRlci54LCBwQ2VudGVyLnksIGlubmVyU3RhcnQsIGlubmVyU3RhcnRBZGp1c3RlZEFuZ2xlICsgTWF0aC5QSSwgc3RhcnRBbmdsZSAtIEhBTEZfUEkpO1xuICB9XG4gIGNvbnN0IHA4ID0gclRoZXRhVG9YWShvdXRlclN0YXJ0QWRqdXN0ZWRSYWRpdXMsIHN0YXJ0QW5nbGUsIHgsIHkpO1xuICBjdHgubGluZVRvKHA4LngsIHA4LnkpO1xuICBpZiAob3V0ZXJTdGFydCA+IDApIHtcbiAgICBjb25zdCBwQ2VudGVyID0gclRoZXRhVG9YWShvdXRlclN0YXJ0QWRqdXN0ZWRSYWRpdXMsIG91dGVyU3RhcnRBZGp1c3RlZEFuZ2xlLCB4LCB5KTtcbiAgICBjdHguYXJjKHBDZW50ZXIueCwgcENlbnRlci55LCBvdXRlclN0YXJ0LCBzdGFydEFuZ2xlIC0gSEFMRl9QSSwgb3V0ZXJTdGFydEFkanVzdGVkQW5nbGUpO1xuICB9XG4gIGN0eC5jbG9zZVBhdGgoKTtcbn1cbmZ1bmN0aW9uIGRyYXdBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcpIHtcbiAgY29uc3Qge2Z1bGxDaXJjbGVzLCBzdGFydEFuZ2xlLCBjaXJjdW1mZXJlbmNlfSA9IGVsZW1lbnQ7XG4gIGxldCBlbmRBbmdsZSA9IGVsZW1lbnQuZW5kQW5nbGU7XG4gIGlmIChmdWxsQ2lyY2xlcykge1xuICAgIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIHN0YXJ0QW5nbGUgKyBUQVUpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnVsbENpcmNsZXM7ICsraSkge1xuICAgICAgY3R4LmZpbGwoKTtcbiAgICB9XG4gICAgaWYgKCFpc05hTihjaXJjdW1mZXJlbmNlKSkge1xuICAgICAgZW5kQW5nbGUgPSBzdGFydEFuZ2xlICsgY2lyY3VtZmVyZW5jZSAlIFRBVTtcbiAgICAgIGlmIChjaXJjdW1mZXJlbmNlICUgVEFVID09PSAwKSB7XG4gICAgICAgIGVuZEFuZ2xlICs9IFRBVTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcGF0aEFyYyhjdHgsIGVsZW1lbnQsIG9mZnNldCwgc3BhY2luZywgZW5kQW5nbGUpO1xuICBjdHguZmlsbCgpO1xuICByZXR1cm4gZW5kQW5nbGU7XG59XG5mdW5jdGlvbiBkcmF3RnVsbENpcmNsZUJvcmRlcnMoY3R4LCBlbGVtZW50LCBpbm5lcikge1xuICBjb25zdCB7eCwgeSwgc3RhcnRBbmdsZSwgcGl4ZWxNYXJnaW4sIGZ1bGxDaXJjbGVzfSA9IGVsZW1lbnQ7XG4gIGNvbnN0IG91dGVyUmFkaXVzID0gTWF0aC5tYXgoZWxlbWVudC5vdXRlclJhZGl1cyAtIHBpeGVsTWFyZ2luLCAwKTtcbiAgY29uc3QgaW5uZXJSYWRpdXMgPSBlbGVtZW50LmlubmVyUmFkaXVzICsgcGl4ZWxNYXJnaW47XG4gIGxldCBpO1xuICBpZiAoaW5uZXIpIHtcbiAgICBjbGlwQXJjKGN0eCwgZWxlbWVudCwgc3RhcnRBbmdsZSArIFRBVSk7XG4gIH1cbiAgY3R4LmJlZ2luUGF0aCgpO1xuICBjdHguYXJjKHgsIHksIGlubmVyUmFkaXVzLCBzdGFydEFuZ2xlICsgVEFVLCBzdGFydEFuZ2xlLCB0cnVlKTtcbiAgZm9yIChpID0gMDsgaSA8IGZ1bGxDaXJjbGVzOyArK2kpIHtcbiAgICBjdHguc3Ryb2tlKCk7XG4gIH1cbiAgY3R4LmJlZ2luUGF0aCgpO1xuICBjdHguYXJjKHgsIHksIG91dGVyUmFkaXVzLCBzdGFydEFuZ2xlLCBzdGFydEFuZ2xlICsgVEFVKTtcbiAgZm9yIChpID0gMDsgaSA8IGZ1bGxDaXJjbGVzOyArK2kpIHtcbiAgICBjdHguc3Ryb2tlKCk7XG4gIH1cbn1cbmZ1bmN0aW9uIGRyYXdCb3JkZXIoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZEFuZ2xlKSB7XG4gIGNvbnN0IHtvcHRpb25zfSA9IGVsZW1lbnQ7XG4gIGNvbnN0IGlubmVyID0gb3B0aW9ucy5ib3JkZXJBbGlnbiA9PT0gJ2lubmVyJztcbiAgaWYgKCFvcHRpb25zLmJvcmRlcldpZHRoKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChpbm5lcikge1xuICAgIGN0eC5saW5lV2lkdGggPSBvcHRpb25zLmJvcmRlcldpZHRoICogMjtcbiAgICBjdHgubGluZUpvaW4gPSAncm91bmQnO1xuICB9IGVsc2Uge1xuICAgIGN0eC5saW5lV2lkdGggPSBvcHRpb25zLmJvcmRlcldpZHRoO1xuICAgIGN0eC5saW5lSm9pbiA9ICdiZXZlbCc7XG4gIH1cbiAgaWYgKGVsZW1lbnQuZnVsbENpcmNsZXMpIHtcbiAgICBkcmF3RnVsbENpcmNsZUJvcmRlcnMoY3R4LCBlbGVtZW50LCBpbm5lcik7XG4gIH1cbiAgaWYgKGlubmVyKSB7XG4gICAgY2xpcEFyYyhjdHgsIGVsZW1lbnQsIGVuZEFuZ2xlKTtcbiAgfVxuICBwYXRoQXJjKGN0eCwgZWxlbWVudCwgb2Zmc2V0LCBzcGFjaW5nLCBlbmRBbmdsZSk7XG4gIGN0eC5zdHJva2UoKTtcbn1cbmNsYXNzIEFyY0VsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgY29uc3RydWN0b3IoY2ZnKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5jaXJjdW1mZXJlbmNlID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuc3RhcnRBbmdsZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmVuZEFuZ2xlID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuaW5uZXJSYWRpdXMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5vdXRlclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnBpeGVsTWFyZ2luID0gMDtcbiAgICB0aGlzLmZ1bGxDaXJjbGVzID0gMDtcbiAgICBpZiAoY2ZnKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNmZyk7XG4gICAgfVxuICB9XG4gIGluUmFuZ2UoY2hhcnRYLCBjaGFydFksIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBjb25zdCBwb2ludCA9IHRoaXMuZ2V0UHJvcHMoWyd4JywgJ3knXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgY29uc3Qge2FuZ2xlLCBkaXN0YW5jZX0gPSBnZXRBbmdsZUZyb21Qb2ludChwb2ludCwge3g6IGNoYXJ0WCwgeTogY2hhcnRZfSk7XG4gICAgY29uc3Qge3N0YXJ0QW5nbGUsIGVuZEFuZ2xlLCBpbm5lclJhZGl1cywgb3V0ZXJSYWRpdXMsIGNpcmN1bWZlcmVuY2V9ID0gdGhpcy5nZXRQcm9wcyhbXG4gICAgICAnc3RhcnRBbmdsZScsXG4gICAgICAnZW5kQW5nbGUnLFxuICAgICAgJ2lubmVyUmFkaXVzJyxcbiAgICAgICdvdXRlclJhZGl1cycsXG4gICAgICAnY2lyY3VtZmVyZW5jZSdcbiAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICBjb25zdCByQWRqdXN0ID0gdGhpcy5vcHRpb25zLnNwYWNpbmcgLyAyO1xuICAgIGNvbnN0IGJldHdlZW5BbmdsZXMgPSBjaXJjdW1mZXJlbmNlID49IFRBVSB8fCBfYW5nbGVCZXR3ZWVuKGFuZ2xlLCBzdGFydEFuZ2xlLCBlbmRBbmdsZSk7XG4gICAgY29uc3Qgd2l0aGluUmFkaXVzID0gKGRpc3RhbmNlID49IGlubmVyUmFkaXVzICsgckFkanVzdCAmJiBkaXN0YW5jZSA8PSBvdXRlclJhZGl1cyArIHJBZGp1c3QpO1xuICAgIHJldHVybiAoYmV0d2VlbkFuZ2xlcyAmJiB3aXRoaW5SYWRpdXMpO1xuICB9XG4gIGdldENlbnRlclBvaW50KHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBjb25zdCB7eCwgeSwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIGlubmVyUmFkaXVzLCBvdXRlclJhZGl1c30gPSB0aGlzLmdldFByb3BzKFtcbiAgICAgICd4JyxcbiAgICAgICd5JyxcbiAgICAgICdzdGFydEFuZ2xlJyxcbiAgICAgICdlbmRBbmdsZScsXG4gICAgICAnaW5uZXJSYWRpdXMnLFxuICAgICAgJ291dGVyUmFkaXVzJyxcbiAgICAgICdjaXJjdW1mZXJlbmNlJyxcbiAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICBjb25zdCB7b2Zmc2V0LCBzcGFjaW5nfSA9IHRoaXMub3B0aW9ucztcbiAgICBjb25zdCBoYWxmQW5nbGUgPSAoc3RhcnRBbmdsZSArIGVuZEFuZ2xlKSAvIDI7XG4gICAgY29uc3QgaGFsZlJhZGl1cyA9IChpbm5lclJhZGl1cyArIG91dGVyUmFkaXVzICsgc3BhY2luZyArIG9mZnNldCkgLyAyO1xuICAgIHJldHVybiB7XG4gICAgICB4OiB4ICsgTWF0aC5jb3MoaGFsZkFuZ2xlKSAqIGhhbGZSYWRpdXMsXG4gICAgICB5OiB5ICsgTWF0aC5zaW4oaGFsZkFuZ2xlKSAqIGhhbGZSYWRpdXNcbiAgICB9O1xuICB9XG4gIHRvb2x0aXBQb3NpdGlvbih1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Q2VudGVyUG9pbnQodXNlRmluYWxQb3NpdGlvbik7XG4gIH1cbiAgZHJhdyhjdHgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge29wdGlvbnMsIGNpcmN1bWZlcmVuY2V9ID0gbWU7XG4gICAgY29uc3Qgb2Zmc2V0ID0gKG9wdGlvbnMub2Zmc2V0IHx8IDApIC8gMjtcbiAgICBjb25zdCBzcGFjaW5nID0gKG9wdGlvbnMuc3BhY2luZyB8fCAwKSAvIDI7XG4gICAgbWUucGl4ZWxNYXJnaW4gPSAob3B0aW9ucy5ib3JkZXJBbGlnbiA9PT0gJ2lubmVyJykgPyAwLjMzIDogMDtcbiAgICBtZS5mdWxsQ2lyY2xlcyA9IGNpcmN1bWZlcmVuY2UgPiBUQVUgPyBNYXRoLmZsb29yKGNpcmN1bWZlcmVuY2UgLyBUQVUpIDogMDtcbiAgICBpZiAoY2lyY3VtZmVyZW5jZSA9PT0gMCB8fCBtZS5pbm5lclJhZGl1cyA8IDAgfHwgbWUub3V0ZXJSYWRpdXMgPCAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGN0eC5zYXZlKCk7XG4gICAgbGV0IHJhZGl1c09mZnNldCA9IDA7XG4gICAgaWYgKG9mZnNldCkge1xuICAgICAgcmFkaXVzT2Zmc2V0ID0gb2Zmc2V0IC8gMjtcbiAgICAgIGNvbnN0IGhhbGZBbmdsZSA9IChtZS5zdGFydEFuZ2xlICsgbWUuZW5kQW5nbGUpIC8gMjtcbiAgICAgIGN0eC50cmFuc2xhdGUoTWF0aC5jb3MoaGFsZkFuZ2xlKSAqIHJhZGl1c09mZnNldCwgTWF0aC5zaW4oaGFsZkFuZ2xlKSAqIHJhZGl1c09mZnNldCk7XG4gICAgICBpZiAobWUuY2lyY3VtZmVyZW5jZSA+PSBQSSkge1xuICAgICAgICByYWRpdXNPZmZzZXQgPSBvZmZzZXQ7XG4gICAgICB9XG4gICAgfVxuICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLmJhY2tncm91bmRDb2xvcjtcbiAgICBjdHguc3Ryb2tlU3R5bGUgPSBvcHRpb25zLmJvcmRlckNvbG9yO1xuICAgIGNvbnN0IGVuZEFuZ2xlID0gZHJhd0FyYyhjdHgsIG1lLCByYWRpdXNPZmZzZXQsIHNwYWNpbmcpO1xuICAgIGRyYXdCb3JkZXIoY3R4LCBtZSwgcmFkaXVzT2Zmc2V0LCBzcGFjaW5nLCBlbmRBbmdsZSk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgfVxufVxuQXJjRWxlbWVudC5pZCA9ICdhcmMnO1xuQXJjRWxlbWVudC5kZWZhdWx0cyA9IHtcbiAgYm9yZGVyQWxpZ246ICdjZW50ZXInLFxuICBib3JkZXJDb2xvcjogJyNmZmYnLFxuICBib3JkZXJSYWRpdXM6IDAsXG4gIGJvcmRlcldpZHRoOiAyLFxuICBvZmZzZXQ6IDAsXG4gIHNwYWNpbmc6IDAsXG4gIGFuZ2xlOiB1bmRlZmluZWQsXG59O1xuQXJjRWxlbWVudC5kZWZhdWx0Um91dGVzID0ge1xuICBiYWNrZ3JvdW5kQ29sb3I6ICdiYWNrZ3JvdW5kQ29sb3InXG59O1xuXG5mdW5jdGlvbiBzZXRTdHlsZShjdHgsIG9wdGlvbnMsIHN0eWxlID0gb3B0aW9ucykge1xuICBjdHgubGluZUNhcCA9IHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlckNhcFN0eWxlLCBvcHRpb25zLmJvcmRlckNhcFN0eWxlKTtcbiAgY3R4LnNldExpbmVEYXNoKHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlckRhc2gsIG9wdGlvbnMuYm9yZGVyRGFzaCkpO1xuICBjdHgubGluZURhc2hPZmZzZXQgPSB2YWx1ZU9yRGVmYXVsdChzdHlsZS5ib3JkZXJEYXNoT2Zmc2V0LCBvcHRpb25zLmJvcmRlckRhc2hPZmZzZXQpO1xuICBjdHgubGluZUpvaW4gPSB2YWx1ZU9yRGVmYXVsdChzdHlsZS5ib3JkZXJKb2luU3R5bGUsIG9wdGlvbnMuYm9yZGVySm9pblN0eWxlKTtcbiAgY3R4LmxpbmVXaWR0aCA9IHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlcldpZHRoLCBvcHRpb25zLmJvcmRlcldpZHRoKTtcbiAgY3R4LnN0cm9rZVN0eWxlID0gdmFsdWVPckRlZmF1bHQoc3R5bGUuYm9yZGVyQ29sb3IsIG9wdGlvbnMuYm9yZGVyQ29sb3IpO1xufVxuZnVuY3Rpb24gbGluZVRvKGN0eCwgcHJldmlvdXMsIHRhcmdldCkge1xuICBjdHgubGluZVRvKHRhcmdldC54LCB0YXJnZXQueSk7XG59XG5mdW5jdGlvbiBnZXRMaW5lTWV0aG9kKG9wdGlvbnMpIHtcbiAgaWYgKG9wdGlvbnMuc3RlcHBlZCkge1xuICAgIHJldHVybiBfc3RlcHBlZExpbmVUbztcbiAgfVxuICBpZiAob3B0aW9ucy50ZW5zaW9uIHx8IG9wdGlvbnMuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZSA9PT0gJ21vbm90b25lJykge1xuICAgIHJldHVybiBfYmV6aWVyQ3VydmVUbztcbiAgfVxuICByZXR1cm4gbGluZVRvO1xufVxuZnVuY3Rpb24gcGF0aFZhcnMocG9pbnRzLCBzZWdtZW50LCBwYXJhbXMgPSB7fSkge1xuICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gIGNvbnN0IHtzdGFydDogcGFyYW1zU3RhcnQgPSAwLCBlbmQ6IHBhcmFtc0VuZCA9IGNvdW50IC0gMX0gPSBwYXJhbXM7XG4gIGNvbnN0IHtzdGFydDogc2VnbWVudFN0YXJ0LCBlbmQ6IHNlZ21lbnRFbmR9ID0gc2VnbWVudDtcbiAgY29uc3Qgc3RhcnQgPSBNYXRoLm1heChwYXJhbXNTdGFydCwgc2VnbWVudFN0YXJ0KTtcbiAgY29uc3QgZW5kID0gTWF0aC5taW4ocGFyYW1zRW5kLCBzZWdtZW50RW5kKTtcbiAgY29uc3Qgb3V0c2lkZSA9IHBhcmFtc1N0YXJ0IDwgc2VnbWVudFN0YXJ0ICYmIHBhcmFtc0VuZCA8IHNlZ21lbnRTdGFydCB8fCBwYXJhbXNTdGFydCA+IHNlZ21lbnRFbmQgJiYgcGFyYW1zRW5kID4gc2VnbWVudEVuZDtcbiAgcmV0dXJuIHtcbiAgICBjb3VudCxcbiAgICBzdGFydCxcbiAgICBsb29wOiBzZWdtZW50Lmxvb3AsXG4gICAgaWxlbjogZW5kIDwgc3RhcnQgJiYgIW91dHNpZGUgPyBjb3VudCArIGVuZCAtIHN0YXJ0IDogZW5kIC0gc3RhcnRcbiAgfTtcbn1cbmZ1bmN0aW9uIHBhdGhTZWdtZW50KGN0eCwgbGluZSwgc2VnbWVudCwgcGFyYW1zKSB7XG4gIGNvbnN0IHtwb2ludHMsIG9wdGlvbnN9ID0gbGluZTtcbiAgY29uc3Qge2NvdW50LCBzdGFydCwgbG9vcCwgaWxlbn0gPSBwYXRoVmFycyhwb2ludHMsIHNlZ21lbnQsIHBhcmFtcyk7XG4gIGNvbnN0IGxpbmVNZXRob2QgPSBnZXRMaW5lTWV0aG9kKG9wdGlvbnMpO1xuICBsZXQge21vdmUgPSB0cnVlLCByZXZlcnNlfSA9IHBhcmFtcyB8fCB7fTtcbiAgbGV0IGksIHBvaW50LCBwcmV2O1xuICBmb3IgKGkgPSAwOyBpIDw9IGlsZW47ICsraSkge1xuICAgIHBvaW50ID0gcG9pbnRzWyhzdGFydCArIChyZXZlcnNlID8gaWxlbiAtIGkgOiBpKSkgJSBjb3VudF07XG4gICAgaWYgKHBvaW50LnNraXApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH0gZWxzZSBpZiAobW92ZSkge1xuICAgICAgY3R4Lm1vdmVUbyhwb2ludC54LCBwb2ludC55KTtcbiAgICAgIG1vdmUgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGluZU1ldGhvZChjdHgsIHByZXYsIHBvaW50LCByZXZlcnNlLCBvcHRpb25zLnN0ZXBwZWQpO1xuICAgIH1cbiAgICBwcmV2ID0gcG9pbnQ7XG4gIH1cbiAgaWYgKGxvb3ApIHtcbiAgICBwb2ludCA9IHBvaW50c1soc3RhcnQgKyAocmV2ZXJzZSA/IGlsZW4gOiAwKSkgJSBjb3VudF07XG4gICAgbGluZU1ldGhvZChjdHgsIHByZXYsIHBvaW50LCByZXZlcnNlLCBvcHRpb25zLnN0ZXBwZWQpO1xuICB9XG4gIHJldHVybiAhIWxvb3A7XG59XG5mdW5jdGlvbiBmYXN0UGF0aFNlZ21lbnQoY3R4LCBsaW5lLCBzZWdtZW50LCBwYXJhbXMpIHtcbiAgY29uc3QgcG9pbnRzID0gbGluZS5wb2ludHM7XG4gIGNvbnN0IHtjb3VudCwgc3RhcnQsIGlsZW59ID0gcGF0aFZhcnMocG9pbnRzLCBzZWdtZW50LCBwYXJhbXMpO1xuICBjb25zdCB7bW92ZSA9IHRydWUsIHJldmVyc2V9ID0gcGFyYW1zIHx8IHt9O1xuICBsZXQgYXZnWCA9IDA7XG4gIGxldCBjb3VudFggPSAwO1xuICBsZXQgaSwgcG9pbnQsIHByZXZYLCBtaW5ZLCBtYXhZLCBsYXN0WTtcbiAgY29uc3QgcG9pbnRJbmRleCA9IChpbmRleCkgPT4gKHN0YXJ0ICsgKHJldmVyc2UgPyBpbGVuIC0gaW5kZXggOiBpbmRleCkpICUgY291bnQ7XG4gIGNvbnN0IGRyYXdYID0gKCkgPT4ge1xuICAgIGlmIChtaW5ZICE9PSBtYXhZKSB7XG4gICAgICBjdHgubGluZVRvKGF2Z1gsIG1heFkpO1xuICAgICAgY3R4LmxpbmVUbyhhdmdYLCBtaW5ZKTtcbiAgICAgIGN0eC5saW5lVG8oYXZnWCwgbGFzdFkpO1xuICAgIH1cbiAgfTtcbiAgaWYgKG1vdmUpIHtcbiAgICBwb2ludCA9IHBvaW50c1twb2ludEluZGV4KDApXTtcbiAgICBjdHgubW92ZVRvKHBvaW50LngsIHBvaW50LnkpO1xuICB9XG4gIGZvciAoaSA9IDA7IGkgPD0gaWxlbjsgKytpKSB7XG4gICAgcG9pbnQgPSBwb2ludHNbcG9pbnRJbmRleChpKV07XG4gICAgaWYgKHBvaW50LnNraXApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCB4ID0gcG9pbnQueDtcbiAgICBjb25zdCB5ID0gcG9pbnQueTtcbiAgICBjb25zdCB0cnVuY1ggPSB4IHwgMDtcbiAgICBpZiAodHJ1bmNYID09PSBwcmV2WCkge1xuICAgICAgaWYgKHkgPCBtaW5ZKSB7XG4gICAgICAgIG1pblkgPSB5O1xuICAgICAgfSBlbHNlIGlmICh5ID4gbWF4WSkge1xuICAgICAgICBtYXhZID0geTtcbiAgICAgIH1cbiAgICAgIGF2Z1ggPSAoY291bnRYICogYXZnWCArIHgpIC8gKytjb3VudFg7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRyYXdYKCk7XG4gICAgICBjdHgubGluZVRvKHgsIHkpO1xuICAgICAgcHJldlggPSB0cnVuY1g7XG4gICAgICBjb3VudFggPSAwO1xuICAgICAgbWluWSA9IG1heFkgPSB5O1xuICAgIH1cbiAgICBsYXN0WSA9IHk7XG4gIH1cbiAgZHJhd1goKTtcbn1cbmZ1bmN0aW9uIF9nZXRTZWdtZW50TWV0aG9kKGxpbmUpIHtcbiAgY29uc3Qgb3B0cyA9IGxpbmUub3B0aW9ucztcbiAgY29uc3QgYm9yZGVyRGFzaCA9IG9wdHMuYm9yZGVyRGFzaCAmJiBvcHRzLmJvcmRlckRhc2gubGVuZ3RoO1xuICBjb25zdCB1c2VGYXN0UGF0aCA9ICFsaW5lLl9kZWNpbWF0ZWQgJiYgIWxpbmUuX2xvb3AgJiYgIW9wdHMudGVuc2lvbiAmJiBvcHRzLmN1YmljSW50ZXJwb2xhdGlvbk1vZGUgIT09ICdtb25vdG9uZScgJiYgIW9wdHMuc3RlcHBlZCAmJiAhYm9yZGVyRGFzaDtcbiAgcmV0dXJuIHVzZUZhc3RQYXRoID8gZmFzdFBhdGhTZWdtZW50IDogcGF0aFNlZ21lbnQ7XG59XG5mdW5jdGlvbiBfZ2V0SW50ZXJwb2xhdGlvbk1ldGhvZChvcHRpb25zKSB7XG4gIGlmIChvcHRpb25zLnN0ZXBwZWQpIHtcbiAgICByZXR1cm4gX3N0ZXBwZWRJbnRlcnBvbGF0aW9uO1xuICB9XG4gIGlmIChvcHRpb25zLnRlbnNpb24gfHwgb3B0aW9ucy5jdWJpY0ludGVycG9sYXRpb25Nb2RlID09PSAnbW9ub3RvbmUnKSB7XG4gICAgcmV0dXJuIF9iZXppZXJJbnRlcnBvbGF0aW9uO1xuICB9XG4gIHJldHVybiBfcG9pbnRJbkxpbmU7XG59XG5mdW5jdGlvbiBzdHJva2VQYXRoV2l0aENhY2hlKGN0eCwgbGluZSwgc3RhcnQsIGNvdW50KSB7XG4gIGxldCBwYXRoID0gbGluZS5fcGF0aDtcbiAgaWYgKCFwYXRoKSB7XG4gICAgcGF0aCA9IGxpbmUuX3BhdGggPSBuZXcgUGF0aDJEKCk7XG4gICAgaWYgKGxpbmUucGF0aChwYXRoLCBzdGFydCwgY291bnQpKSB7XG4gICAgICBwYXRoLmNsb3NlUGF0aCgpO1xuICAgIH1cbiAgfVxuICBzZXRTdHlsZShjdHgsIGxpbmUub3B0aW9ucyk7XG4gIGN0eC5zdHJva2UocGF0aCk7XG59XG5mdW5jdGlvbiBzdHJva2VQYXRoRGlyZWN0KGN0eCwgbGluZSwgc3RhcnQsIGNvdW50KSB7XG4gIGNvbnN0IHtzZWdtZW50cywgb3B0aW9uc30gPSBsaW5lO1xuICBjb25zdCBzZWdtZW50TWV0aG9kID0gX2dldFNlZ21lbnRNZXRob2QobGluZSk7XG4gIGZvciAoY29uc3Qgc2VnbWVudCBvZiBzZWdtZW50cykge1xuICAgIHNldFN0eWxlKGN0eCwgb3B0aW9ucywgc2VnbWVudC5zdHlsZSk7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIGlmIChzZWdtZW50TWV0aG9kKGN0eCwgbGluZSwgc2VnbWVudCwge3N0YXJ0LCBlbmQ6IHN0YXJ0ICsgY291bnQgLSAxfSkpIHtcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICB9XG4gICAgY3R4LnN0cm9rZSgpO1xuICB9XG59XG5jb25zdCB1c2VQYXRoMkQgPSB0eXBlb2YgUGF0aDJEID09PSAnZnVuY3Rpb24nO1xuZnVuY3Rpb24gZHJhdyhjdHgsIGxpbmUsIHN0YXJ0LCBjb3VudCkge1xuICBpZiAodXNlUGF0aDJEICYmIGxpbmUuc2VnbWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgc3Ryb2tlUGF0aFdpdGhDYWNoZShjdHgsIGxpbmUsIHN0YXJ0LCBjb3VudCk7XG4gIH0gZWxzZSB7XG4gICAgc3Ryb2tlUGF0aERpcmVjdChjdHgsIGxpbmUsIHN0YXJ0LCBjb3VudCk7XG4gIH1cbn1cbmNsYXNzIExpbmVFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7XG4gIGNvbnN0cnVjdG9yKGNmZykge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5hbmltYXRlZCA9IHRydWU7XG4gICAgdGhpcy5vcHRpb25zID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX2xvb3AgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fZnVsbExvb3AgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fcGF0aCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9wb2ludHMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fc2VnbWVudHMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fZGVjaW1hdGVkID0gZmFsc2U7XG4gICAgdGhpcy5fcG9pbnRzVXBkYXRlZCA9IGZhbHNlO1xuICAgIHRoaXMuX2RhdGFzZXRJbmRleCA9IHVuZGVmaW5lZDtcbiAgICBpZiAoY2ZnKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNmZyk7XG4gICAgfVxuICB9XG4gIHVwZGF0ZUNvbnRyb2xQb2ludHMoY2hhcnRBcmVhLCBpbmRleEF4aXMpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qgb3B0aW9ucyA9IG1lLm9wdGlvbnM7XG4gICAgaWYgKChvcHRpb25zLnRlbnNpb24gfHwgb3B0aW9ucy5jdWJpY0ludGVycG9sYXRpb25Nb2RlID09PSAnbW9ub3RvbmUnKSAmJiAhb3B0aW9ucy5zdGVwcGVkICYmICFtZS5fcG9pbnRzVXBkYXRlZCkge1xuICAgICAgY29uc3QgbG9vcCA9IG9wdGlvbnMuc3BhbkdhcHMgPyBtZS5fbG9vcCA6IG1lLl9mdWxsTG9vcDtcbiAgICAgIF91cGRhdGVCZXppZXJDb250cm9sUG9pbnRzKG1lLl9wb2ludHMsIG9wdGlvbnMsIGNoYXJ0QXJlYSwgbG9vcCwgaW5kZXhBeGlzKTtcbiAgICAgIG1lLl9wb2ludHNVcGRhdGVkID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgc2V0IHBvaW50cyhwb2ludHMpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgbWUuX3BvaW50cyA9IHBvaW50cztcbiAgICBkZWxldGUgbWUuX3NlZ21lbnRzO1xuICAgIGRlbGV0ZSBtZS5fcGF0aDtcbiAgICBtZS5fcG9pbnRzVXBkYXRlZCA9IGZhbHNlO1xuICB9XG4gIGdldCBwb2ludHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BvaW50cztcbiAgfVxuICBnZXQgc2VnbWVudHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NlZ21lbnRzIHx8ICh0aGlzLl9zZWdtZW50cyA9IF9jb21wdXRlU2VnbWVudHModGhpcywgdGhpcy5vcHRpb25zLnNlZ21lbnQpKTtcbiAgfVxuICBmaXJzdCgpIHtcbiAgICBjb25zdCBzZWdtZW50cyA9IHRoaXMuc2VnbWVudHM7XG4gICAgY29uc3QgcG9pbnRzID0gdGhpcy5wb2ludHM7XG4gICAgcmV0dXJuIHNlZ21lbnRzLmxlbmd0aCAmJiBwb2ludHNbc2VnbWVudHNbMF0uc3RhcnRdO1xuICB9XG4gIGxhc3QoKSB7XG4gICAgY29uc3Qgc2VnbWVudHMgPSB0aGlzLnNlZ21lbnRzO1xuICAgIGNvbnN0IHBvaW50cyA9IHRoaXMucG9pbnRzO1xuICAgIGNvbnN0IGNvdW50ID0gc2VnbWVudHMubGVuZ3RoO1xuICAgIHJldHVybiBjb3VudCAmJiBwb2ludHNbc2VnbWVudHNbY291bnQgLSAxXS5lbmRdO1xuICB9XG4gIGludGVycG9sYXRlKHBvaW50LCBwcm9wZXJ0eSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRpb25zID0gbWUub3B0aW9ucztcbiAgICBjb25zdCB2YWx1ZSA9IHBvaW50W3Byb3BlcnR5XTtcbiAgICBjb25zdCBwb2ludHMgPSBtZS5wb2ludHM7XG4gICAgY29uc3Qgc2VnbWVudHMgPSBfYm91bmRTZWdtZW50cyhtZSwge3Byb3BlcnR5LCBzdGFydDogdmFsdWUsIGVuZDogdmFsdWV9KTtcbiAgICBpZiAoIXNlZ21lbnRzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBjb25zdCBfaW50ZXJwb2xhdGUgPSBfZ2V0SW50ZXJwb2xhdGlvbk1ldGhvZChvcHRpb25zKTtcbiAgICBsZXQgaSwgaWxlbjtcbiAgICBmb3IgKGkgPSAwLCBpbGVuID0gc2VnbWVudHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgICBjb25zdCB7c3RhcnQsIGVuZH0gPSBzZWdtZW50c1tpXTtcbiAgICAgIGNvbnN0IHAxID0gcG9pbnRzW3N0YXJ0XTtcbiAgICAgIGNvbnN0IHAyID0gcG9pbnRzW2VuZF07XG4gICAgICBpZiAocDEgPT09IHAyKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHAxKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCB0ID0gTWF0aC5hYnMoKHZhbHVlIC0gcDFbcHJvcGVydHldKSAvIChwMltwcm9wZXJ0eV0gLSBwMVtwcm9wZXJ0eV0pKTtcbiAgICAgIGNvbnN0IGludGVycG9sYXRlZCA9IF9pbnRlcnBvbGF0ZShwMSwgcDIsIHQsIG9wdGlvbnMuc3RlcHBlZCk7XG4gICAgICBpbnRlcnBvbGF0ZWRbcHJvcGVydHldID0gcG9pbnRbcHJvcGVydHldO1xuICAgICAgcmVzdWx0LnB1c2goaW50ZXJwb2xhdGVkKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdC5sZW5ndGggPT09IDEgPyByZXN1bHRbMF0gOiByZXN1bHQ7XG4gIH1cbiAgcGF0aFNlZ21lbnQoY3R4LCBzZWdtZW50LCBwYXJhbXMpIHtcbiAgICBjb25zdCBzZWdtZW50TWV0aG9kID0gX2dldFNlZ21lbnRNZXRob2QodGhpcyk7XG4gICAgcmV0dXJuIHNlZ21lbnRNZXRob2QoY3R4LCB0aGlzLCBzZWdtZW50LCBwYXJhbXMpO1xuICB9XG4gIHBhdGgoY3R4LCBzdGFydCwgY291bnQpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qgc2VnbWVudHMgPSBtZS5zZWdtZW50cztcbiAgICBjb25zdCBzZWdtZW50TWV0aG9kID0gX2dldFNlZ21lbnRNZXRob2QobWUpO1xuICAgIGxldCBsb29wID0gbWUuX2xvb3A7XG4gICAgc3RhcnQgPSBzdGFydCB8fCAwO1xuICAgIGNvdW50ID0gY291bnQgfHwgKG1lLnBvaW50cy5sZW5ndGggLSBzdGFydCk7XG4gICAgZm9yIChjb25zdCBzZWdtZW50IG9mIHNlZ21lbnRzKSB7XG4gICAgICBsb29wICY9IHNlZ21lbnRNZXRob2QoY3R4LCBtZSwgc2VnbWVudCwge3N0YXJ0LCBlbmQ6IHN0YXJ0ICsgY291bnQgLSAxfSk7XG4gICAgfVxuICAgIHJldHVybiAhIWxvb3A7XG4gIH1cbiAgZHJhdyhjdHgsIGNoYXJ0QXJlYSwgc3RhcnQsIGNvdW50KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zIHx8IHt9O1xuICAgIGNvbnN0IHBvaW50cyA9IG1lLnBvaW50cyB8fCBbXTtcbiAgICBpZiAoIXBvaW50cy5sZW5ndGggfHwgIW9wdGlvbnMuYm9yZGVyV2lkdGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY3R4LnNhdmUoKTtcbiAgICBkcmF3KGN0eCwgbWUsIHN0YXJ0LCBjb3VudCk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgICBpZiAobWUuYW5pbWF0ZWQpIHtcbiAgICAgIG1lLl9wb2ludHNVcGRhdGVkID0gZmFsc2U7XG4gICAgICBtZS5fcGF0aCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cbn1cbkxpbmVFbGVtZW50LmlkID0gJ2xpbmUnO1xuTGluZUVsZW1lbnQuZGVmYXVsdHMgPSB7XG4gIGJvcmRlckNhcFN0eWxlOiAnYnV0dCcsXG4gIGJvcmRlckRhc2g6IFtdLFxuICBib3JkZXJEYXNoT2Zmc2V0OiAwLFxuICBib3JkZXJKb2luU3R5bGU6ICdtaXRlcicsXG4gIGJvcmRlcldpZHRoOiAzLFxuICBjYXBCZXppZXJQb2ludHM6IHRydWUsXG4gIGN1YmljSW50ZXJwb2xhdGlvbk1vZGU6ICdkZWZhdWx0JyxcbiAgZmlsbDogZmFsc2UsXG4gIHNwYW5HYXBzOiBmYWxzZSxcbiAgc3RlcHBlZDogZmFsc2UsXG4gIHRlbnNpb246IDAsXG59O1xuTGluZUVsZW1lbnQuZGVmYXVsdFJvdXRlcyA9IHtcbiAgYmFja2dyb3VuZENvbG9yOiAnYmFja2dyb3VuZENvbG9yJyxcbiAgYm9yZGVyQ29sb3I6ICdib3JkZXJDb2xvcidcbn07XG5MaW5lRWxlbWVudC5kZXNjcmlwdG9ycyA9IHtcbiAgX3NjcmlwdGFibGU6IHRydWUsXG4gIF9pbmRleGFibGU6IChuYW1lKSA9PiBuYW1lICE9PSAnYm9yZGVyRGFzaCcgJiYgbmFtZSAhPT0gJ2ZpbGwnLFxufTtcblxuZnVuY3Rpb24gaW5SYW5nZSQxKGVsLCBwb3MsIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgY29uc3Qgb3B0aW9ucyA9IGVsLm9wdGlvbnM7XG4gIGNvbnN0IHtbYXhpc106IHZhbHVlfSA9IGVsLmdldFByb3BzKFtheGlzXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gIHJldHVybiAoTWF0aC5hYnMocG9zIC0gdmFsdWUpIDwgb3B0aW9ucy5yYWRpdXMgKyBvcHRpb25zLmhpdFJhZGl1cyk7XG59XG5jbGFzcyBQb2ludEVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgY29uc3RydWN0b3IoY2ZnKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5wYXJzZWQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5za2lwID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuc3RvcCA9IHVuZGVmaW5lZDtcbiAgICBpZiAoY2ZnKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNmZyk7XG4gICAgfVxuICB9XG4gIGluUmFuZ2UobW91c2VYLCBtb3VzZVksIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgIGNvbnN0IHt4LCB5fSA9IHRoaXMuZ2V0UHJvcHMoWyd4JywgJ3knXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgcmV0dXJuICgoTWF0aC5wb3cobW91c2VYIC0geCwgMikgKyBNYXRoLnBvdyhtb3VzZVkgLSB5LCAyKSkgPCBNYXRoLnBvdyhvcHRpb25zLmhpdFJhZGl1cyArIG9wdGlvbnMucmFkaXVzLCAyKSk7XG4gIH1cbiAgaW5YUmFuZ2UobW91c2VYLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIGluUmFuZ2UkMSh0aGlzLCBtb3VzZVgsICd4JywgdXNlRmluYWxQb3NpdGlvbik7XG4gIH1cbiAgaW5ZUmFuZ2UobW91c2VZLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIGluUmFuZ2UkMSh0aGlzLCBtb3VzZVksICd5JywgdXNlRmluYWxQb3NpdGlvbik7XG4gIH1cbiAgZ2V0Q2VudGVyUG9pbnQodXNlRmluYWxQb3NpdGlvbikge1xuICAgIGNvbnN0IHt4LCB5fSA9IHRoaXMuZ2V0UHJvcHMoWyd4JywgJ3knXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgcmV0dXJuIHt4LCB5fTtcbiAgfVxuICBzaXplKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB0aGlzLm9wdGlvbnMgfHwge307XG4gICAgbGV0IHJhZGl1cyA9IG9wdGlvbnMucmFkaXVzIHx8IDA7XG4gICAgcmFkaXVzID0gTWF0aC5tYXgocmFkaXVzLCByYWRpdXMgJiYgb3B0aW9ucy5ob3ZlclJhZGl1cyB8fCAwKTtcbiAgICBjb25zdCBib3JkZXJXaWR0aCA9IHJhZGl1cyAmJiBvcHRpb25zLmJvcmRlcldpZHRoIHx8IDA7XG4gICAgcmV0dXJuIChyYWRpdXMgKyBib3JkZXJXaWR0aCkgKiAyO1xuICB9XG4gIGRyYXcoY3R4LCBhcmVhKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGlmIChtZS5za2lwIHx8IG9wdGlvbnMucmFkaXVzIDwgMC4xIHx8ICFfaXNQb2ludEluQXJlYShtZSwgYXJlYSwgbWUuc2l6ZShvcHRpb25zKSAvIDIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGN0eC5zdHJva2VTdHlsZSA9IG9wdGlvbnMuYm9yZGVyQ29sb3I7XG4gICAgY3R4LmxpbmVXaWR0aCA9IG9wdGlvbnMuYm9yZGVyV2lkdGg7XG4gICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yO1xuICAgIGRyYXdQb2ludChjdHgsIG9wdGlvbnMsIG1lLngsIG1lLnkpO1xuICB9XG4gIGdldFJhbmdlKCkge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgfHwge307XG4gICAgcmV0dXJuIG9wdGlvbnMucmFkaXVzICsgb3B0aW9ucy5oaXRSYWRpdXM7XG4gIH1cbn1cblBvaW50RWxlbWVudC5pZCA9ICdwb2ludCc7XG5Qb2ludEVsZW1lbnQuZGVmYXVsdHMgPSB7XG4gIGJvcmRlcldpZHRoOiAxLFxuICBoaXRSYWRpdXM6IDEsXG4gIGhvdmVyQm9yZGVyV2lkdGg6IDEsXG4gIGhvdmVyUmFkaXVzOiA0LFxuICBwb2ludFN0eWxlOiAnY2lyY2xlJyxcbiAgcmFkaXVzOiAzLFxuICByb3RhdGlvbjogMFxufTtcblBvaW50RWxlbWVudC5kZWZhdWx0Um91dGVzID0ge1xuICBiYWNrZ3JvdW5kQ29sb3I6ICdiYWNrZ3JvdW5kQ29sb3InLFxuICBib3JkZXJDb2xvcjogJ2JvcmRlckNvbG9yJ1xufTtcblxuZnVuY3Rpb24gZ2V0QmFyQm91bmRzKGJhciwgdXNlRmluYWxQb3NpdGlvbikge1xuICBjb25zdCB7eCwgeSwgYmFzZSwgd2lkdGgsIGhlaWdodH0gPSBiYXIuZ2V0UHJvcHMoWyd4JywgJ3knLCAnYmFzZScsICd3aWR0aCcsICdoZWlnaHQnXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gIGxldCBsZWZ0LCByaWdodCwgdG9wLCBib3R0b20sIGhhbGY7XG4gIGlmIChiYXIuaG9yaXpvbnRhbCkge1xuICAgIGhhbGYgPSBoZWlnaHQgLyAyO1xuICAgIGxlZnQgPSBNYXRoLm1pbih4LCBiYXNlKTtcbiAgICByaWdodCA9IE1hdGgubWF4KHgsIGJhc2UpO1xuICAgIHRvcCA9IHkgLSBoYWxmO1xuICAgIGJvdHRvbSA9IHkgKyBoYWxmO1xuICB9IGVsc2Uge1xuICAgIGhhbGYgPSB3aWR0aCAvIDI7XG4gICAgbGVmdCA9IHggLSBoYWxmO1xuICAgIHJpZ2h0ID0geCArIGhhbGY7XG4gICAgdG9wID0gTWF0aC5taW4oeSwgYmFzZSk7XG4gICAgYm90dG9tID0gTWF0aC5tYXgoeSwgYmFzZSk7XG4gIH1cbiAgcmV0dXJuIHtsZWZ0LCB0b3AsIHJpZ2h0LCBib3R0b219O1xufVxuZnVuY3Rpb24gc2tpcE9yTGltaXQoc2tpcCwgdmFsdWUsIG1pbiwgbWF4KSB7XG4gIHJldHVybiBza2lwID8gMCA6IF9saW1pdFZhbHVlKHZhbHVlLCBtaW4sIG1heCk7XG59XG5mdW5jdGlvbiBwYXJzZUJvcmRlcldpZHRoKGJhciwgbWF4VywgbWF4SCkge1xuICBjb25zdCB2YWx1ZSA9IGJhci5vcHRpb25zLmJvcmRlcldpZHRoO1xuICBjb25zdCBza2lwID0gYmFyLmJvcmRlclNraXBwZWQ7XG4gIGNvbnN0IG8gPSB0b1RSQkwodmFsdWUpO1xuICByZXR1cm4ge1xuICAgIHQ6IHNraXBPckxpbWl0KHNraXAudG9wLCBvLnRvcCwgMCwgbWF4SCksXG4gICAgcjogc2tpcE9yTGltaXQoc2tpcC5yaWdodCwgby5yaWdodCwgMCwgbWF4VyksXG4gICAgYjogc2tpcE9yTGltaXQoc2tpcC5ib3R0b20sIG8uYm90dG9tLCAwLCBtYXhIKSxcbiAgICBsOiBza2lwT3JMaW1pdChza2lwLmxlZnQsIG8ubGVmdCwgMCwgbWF4VylcbiAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlQm9yZGVyUmFkaXVzKGJhciwgbWF4VywgbWF4SCkge1xuICBjb25zdCB7ZW5hYmxlQm9yZGVyUmFkaXVzfSA9IGJhci5nZXRQcm9wcyhbJ2VuYWJsZUJvcmRlclJhZGl1cyddKTtcbiAgY29uc3QgdmFsdWUgPSBiYXIub3B0aW9ucy5ib3JkZXJSYWRpdXM7XG4gIGNvbnN0IG8gPSB0b1RSQkxDb3JuZXJzKHZhbHVlKTtcbiAgY29uc3QgbWF4UiA9IE1hdGgubWluKG1heFcsIG1heEgpO1xuICBjb25zdCBza2lwID0gYmFyLmJvcmRlclNraXBwZWQ7XG4gIGNvbnN0IGVuYWJsZUJvcmRlciA9IGVuYWJsZUJvcmRlclJhZGl1cyB8fCBpc09iamVjdCh2YWx1ZSk7XG4gIHJldHVybiB7XG4gICAgdG9wTGVmdDogc2tpcE9yTGltaXQoIWVuYWJsZUJvcmRlciB8fCBza2lwLnRvcCB8fCBza2lwLmxlZnQsIG8udG9wTGVmdCwgMCwgbWF4UiksXG4gICAgdG9wUmlnaHQ6IHNraXBPckxpbWl0KCFlbmFibGVCb3JkZXIgfHwgc2tpcC50b3AgfHwgc2tpcC5yaWdodCwgby50b3BSaWdodCwgMCwgbWF4UiksXG4gICAgYm90dG9tTGVmdDogc2tpcE9yTGltaXQoIWVuYWJsZUJvcmRlciB8fCBza2lwLmJvdHRvbSB8fCBza2lwLmxlZnQsIG8uYm90dG9tTGVmdCwgMCwgbWF4UiksXG4gICAgYm90dG9tUmlnaHQ6IHNraXBPckxpbWl0KCFlbmFibGVCb3JkZXIgfHwgc2tpcC5ib3R0b20gfHwgc2tpcC5yaWdodCwgby5ib3R0b21SaWdodCwgMCwgbWF4UilcbiAgfTtcbn1cbmZ1bmN0aW9uIGJvdW5kaW5nUmVjdHMoYmFyKSB7XG4gIGNvbnN0IGJvdW5kcyA9IGdldEJhckJvdW5kcyhiYXIpO1xuICBjb25zdCB3aWR0aCA9IGJvdW5kcy5yaWdodCAtIGJvdW5kcy5sZWZ0O1xuICBjb25zdCBoZWlnaHQgPSBib3VuZHMuYm90dG9tIC0gYm91bmRzLnRvcDtcbiAgY29uc3QgYm9yZGVyID0gcGFyc2VCb3JkZXJXaWR0aChiYXIsIHdpZHRoIC8gMiwgaGVpZ2h0IC8gMik7XG4gIGNvbnN0IHJhZGl1cyA9IHBhcnNlQm9yZGVyUmFkaXVzKGJhciwgd2lkdGggLyAyLCBoZWlnaHQgLyAyKTtcbiAgcmV0dXJuIHtcbiAgICBvdXRlcjoge1xuICAgICAgeDogYm91bmRzLmxlZnQsXG4gICAgICB5OiBib3VuZHMudG9wLFxuICAgICAgdzogd2lkdGgsXG4gICAgICBoOiBoZWlnaHQsXG4gICAgICByYWRpdXNcbiAgICB9LFxuICAgIGlubmVyOiB7XG4gICAgICB4OiBib3VuZHMubGVmdCArIGJvcmRlci5sLFxuICAgICAgeTogYm91bmRzLnRvcCArIGJvcmRlci50LFxuICAgICAgdzogd2lkdGggLSBib3JkZXIubCAtIGJvcmRlci5yLFxuICAgICAgaDogaGVpZ2h0IC0gYm9yZGVyLnQgLSBib3JkZXIuYixcbiAgICAgIHJhZGl1czoge1xuICAgICAgICB0b3BMZWZ0OiBNYXRoLm1heCgwLCByYWRpdXMudG9wTGVmdCAtIE1hdGgubWF4KGJvcmRlci50LCBib3JkZXIubCkpLFxuICAgICAgICB0b3BSaWdodDogTWF0aC5tYXgoMCwgcmFkaXVzLnRvcFJpZ2h0IC0gTWF0aC5tYXgoYm9yZGVyLnQsIGJvcmRlci5yKSksXG4gICAgICAgIGJvdHRvbUxlZnQ6IE1hdGgubWF4KDAsIHJhZGl1cy5ib3R0b21MZWZ0IC0gTWF0aC5tYXgoYm9yZGVyLmIsIGJvcmRlci5sKSksXG4gICAgICAgIGJvdHRvbVJpZ2h0OiBNYXRoLm1heCgwLCByYWRpdXMuYm90dG9tUmlnaHQgLSBNYXRoLm1heChib3JkZXIuYiwgYm9yZGVyLnIpKSxcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5mdW5jdGlvbiBpblJhbmdlKGJhciwgeCwgeSwgdXNlRmluYWxQb3NpdGlvbikge1xuICBjb25zdCBza2lwWCA9IHggPT09IG51bGw7XG4gIGNvbnN0IHNraXBZID0geSA9PT0gbnVsbDtcbiAgY29uc3Qgc2tpcEJvdGggPSBza2lwWCAmJiBza2lwWTtcbiAgY29uc3QgYm91bmRzID0gYmFyICYmICFza2lwQm90aCAmJiBnZXRCYXJCb3VuZHMoYmFyLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgcmV0dXJuIGJvdW5kc1xuXHRcdCYmIChza2lwWCB8fCB4ID49IGJvdW5kcy5sZWZ0ICYmIHggPD0gYm91bmRzLnJpZ2h0KVxuXHRcdCYmIChza2lwWSB8fCB5ID49IGJvdW5kcy50b3AgJiYgeSA8PSBib3VuZHMuYm90dG9tKTtcbn1cbmZ1bmN0aW9uIGhhc1JhZGl1cyhyYWRpdXMpIHtcbiAgcmV0dXJuIHJhZGl1cy50b3BMZWZ0IHx8IHJhZGl1cy50b3BSaWdodCB8fCByYWRpdXMuYm90dG9tTGVmdCB8fCByYWRpdXMuYm90dG9tUmlnaHQ7XG59XG5mdW5jdGlvbiBhZGROb3JtYWxSZWN0UGF0aChjdHgsIHJlY3QpIHtcbiAgY3R4LnJlY3QocmVjdC54LCByZWN0LnksIHJlY3QudywgcmVjdC5oKTtcbn1cbmZ1bmN0aW9uIGluZmxhdGVSZWN0KHJlY3QsIGFtb3VudCwgcmVmUmVjdCA9IHt9KSB7XG4gIGNvbnN0IHggPSByZWN0LnggIT09IHJlZlJlY3QueCA/IC1hbW91bnQgOiAwO1xuICBjb25zdCB5ID0gcmVjdC55ICE9PSByZWZSZWN0LnkgPyAtYW1vdW50IDogMDtcbiAgY29uc3QgdyA9IChyZWN0LnggKyByZWN0LncgIT09IHJlZlJlY3QueCArIHJlZlJlY3QudyA/IGFtb3VudCA6IDApIC0geDtcbiAgY29uc3QgaCA9IChyZWN0LnkgKyByZWN0LmggIT09IHJlZlJlY3QueSArIHJlZlJlY3QuaCA/IGFtb3VudCA6IDApIC0geTtcbiAgcmV0dXJuIHtcbiAgICB4OiByZWN0LnggKyB4LFxuICAgIHk6IHJlY3QueSArIHksXG4gICAgdzogcmVjdC53ICsgdyxcbiAgICBoOiByZWN0LmggKyBoLFxuICAgIHJhZGl1czogcmVjdC5yYWRpdXNcbiAgfTtcbn1cbmNsYXNzIEJhckVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgY29uc3RydWN0b3IoY2ZnKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5ob3Jpem9udGFsID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuYmFzZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLndpZHRoID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuaGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgIGlmIChjZmcpIHtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgY2ZnKTtcbiAgICB9XG4gIH1cbiAgZHJhdyhjdHgpIHtcbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgIGNvbnN0IHtpbm5lciwgb3V0ZXJ9ID0gYm91bmRpbmdSZWN0cyh0aGlzKTtcbiAgICBjb25zdCBhZGRSZWN0UGF0aCA9IGhhc1JhZGl1cyhvdXRlci5yYWRpdXMpID8gYWRkUm91bmRlZFJlY3RQYXRoIDogYWRkTm9ybWFsUmVjdFBhdGg7XG4gICAgY29uc3QgaW5mbGF0ZUFtb3VudCA9IDAuMzM7XG4gICAgY3R4LnNhdmUoKTtcbiAgICBpZiAob3V0ZXIudyAhPT0gaW5uZXIudyB8fCBvdXRlci5oICE9PSBpbm5lci5oKSB7XG4gICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICBhZGRSZWN0UGF0aChjdHgsIGluZmxhdGVSZWN0KG91dGVyLCBpbmZsYXRlQW1vdW50LCBpbm5lcikpO1xuICAgICAgY3R4LmNsaXAoKTtcbiAgICAgIGFkZFJlY3RQYXRoKGN0eCwgaW5mbGF0ZVJlY3QoaW5uZXIsIC1pbmZsYXRlQW1vdW50LCBvdXRlcikpO1xuICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMuYm9yZGVyQ29sb3I7XG4gICAgICBjdHguZmlsbCgnZXZlbm9kZCcpO1xuICAgIH1cbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgYWRkUmVjdFBhdGgoY3R4LCBpbmZsYXRlUmVjdChpbm5lciwgaW5mbGF0ZUFtb3VudCwgb3V0ZXIpKTtcbiAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgY3R4LmZpbGwoKTtcbiAgICBjdHgucmVzdG9yZSgpO1xuICB9XG4gIGluUmFuZ2UobW91c2VYLCBtb3VzZVksIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICByZXR1cm4gaW5SYW5nZSh0aGlzLCBtb3VzZVgsIG1vdXNlWSwgdXNlRmluYWxQb3NpdGlvbik7XG4gIH1cbiAgaW5YUmFuZ2UobW91c2VYLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIGluUmFuZ2UodGhpcywgbW91c2VYLCBudWxsLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgfVxuICBpbllSYW5nZShtb3VzZVksIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICByZXR1cm4gaW5SYW5nZSh0aGlzLCBudWxsLCBtb3VzZVksIHVzZUZpbmFsUG9zaXRpb24pO1xuICB9XG4gIGdldENlbnRlclBvaW50KHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBjb25zdCB7eCwgeSwgYmFzZSwgaG9yaXpvbnRhbH0gPSB0aGlzLmdldFByb3BzKFsneCcsICd5JywgJ2Jhc2UnLCAnaG9yaXpvbnRhbCddLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICByZXR1cm4ge1xuICAgICAgeDogaG9yaXpvbnRhbCA/ICh4ICsgYmFzZSkgLyAyIDogeCxcbiAgICAgIHk6IGhvcml6b250YWwgPyB5IDogKHkgKyBiYXNlKSAvIDJcbiAgICB9O1xuICB9XG4gIGdldFJhbmdlKGF4aXMpIHtcbiAgICByZXR1cm4gYXhpcyA9PT0gJ3gnID8gdGhpcy53aWR0aCAvIDIgOiB0aGlzLmhlaWdodCAvIDI7XG4gIH1cbn1cbkJhckVsZW1lbnQuaWQgPSAnYmFyJztcbkJhckVsZW1lbnQuZGVmYXVsdHMgPSB7XG4gIGJvcmRlclNraXBwZWQ6ICdzdGFydCcsXG4gIGJvcmRlcldpZHRoOiAwLFxuICBib3JkZXJSYWRpdXM6IDAsXG4gIGVuYWJsZUJvcmRlclJhZGl1czogdHJ1ZSxcbiAgcG9pbnRTdHlsZTogdW5kZWZpbmVkXG59O1xuQmFyRWxlbWVudC5kZWZhdWx0Um91dGVzID0ge1xuICBiYWNrZ3JvdW5kQ29sb3I6ICdiYWNrZ3JvdW5kQ29sb3InLFxuICBib3JkZXJDb2xvcjogJ2JvcmRlckNvbG9yJ1xufTtcblxudmFyIGVsZW1lbnRzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuX19wcm90b19fOiBudWxsLFxuQXJjRWxlbWVudDogQXJjRWxlbWVudCxcbkxpbmVFbGVtZW50OiBMaW5lRWxlbWVudCxcblBvaW50RWxlbWVudDogUG9pbnRFbGVtZW50LFxuQmFyRWxlbWVudDogQmFyRWxlbWVudFxufSk7XG5cbmZ1bmN0aW9uIGx0dGJEZWNpbWF0aW9uKGRhdGEsIHN0YXJ0LCBjb3VudCwgYXZhaWxhYmxlV2lkdGgsIG9wdGlvbnMpIHtcbiAgY29uc3Qgc2FtcGxlcyA9IG9wdGlvbnMuc2FtcGxlcyB8fCBhdmFpbGFibGVXaWR0aDtcbiAgaWYgKHNhbXBsZXMgPj0gY291bnQpIHtcbiAgICByZXR1cm4gZGF0YS5zbGljZShzdGFydCwgc3RhcnQgKyBjb3VudCk7XG4gIH1cbiAgY29uc3QgZGVjaW1hdGVkID0gW107XG4gIGNvbnN0IGJ1Y2tldFdpZHRoID0gKGNvdW50IC0gMikgLyAoc2FtcGxlcyAtIDIpO1xuICBsZXQgc2FtcGxlZEluZGV4ID0gMDtcbiAgY29uc3QgZW5kSW5kZXggPSBzdGFydCArIGNvdW50IC0gMTtcbiAgbGV0IGEgPSBzdGFydDtcbiAgbGV0IGksIG1heEFyZWFQb2ludCwgbWF4QXJlYSwgYXJlYSwgbmV4dEE7XG4gIGRlY2ltYXRlZFtzYW1wbGVkSW5kZXgrK10gPSBkYXRhW2FdO1xuICBmb3IgKGkgPSAwOyBpIDwgc2FtcGxlcyAtIDI7IGkrKykge1xuICAgIGxldCBhdmdYID0gMDtcbiAgICBsZXQgYXZnWSA9IDA7XG4gICAgbGV0IGo7XG4gICAgY29uc3QgYXZnUmFuZ2VTdGFydCA9IE1hdGguZmxvb3IoKGkgKyAxKSAqIGJ1Y2tldFdpZHRoKSArIDEgKyBzdGFydDtcbiAgICBjb25zdCBhdmdSYW5nZUVuZCA9IE1hdGgubWluKE1hdGguZmxvb3IoKGkgKyAyKSAqIGJ1Y2tldFdpZHRoKSArIDEsIGNvdW50KSArIHN0YXJ0O1xuICAgIGNvbnN0IGF2Z1JhbmdlTGVuZ3RoID0gYXZnUmFuZ2VFbmQgLSBhdmdSYW5nZVN0YXJ0O1xuICAgIGZvciAoaiA9IGF2Z1JhbmdlU3RhcnQ7IGogPCBhdmdSYW5nZUVuZDsgaisrKSB7XG4gICAgICBhdmdYICs9IGRhdGFbal0ueDtcbiAgICAgIGF2Z1kgKz0gZGF0YVtqXS55O1xuICAgIH1cbiAgICBhdmdYIC89IGF2Z1JhbmdlTGVuZ3RoO1xuICAgIGF2Z1kgLz0gYXZnUmFuZ2VMZW5ndGg7XG4gICAgY29uc3QgcmFuZ2VPZmZzID0gTWF0aC5mbG9vcihpICogYnVja2V0V2lkdGgpICsgMSArIHN0YXJ0O1xuICAgIGNvbnN0IHJhbmdlVG8gPSBNYXRoLm1pbihNYXRoLmZsb29yKChpICsgMSkgKiBidWNrZXRXaWR0aCkgKyAxLCBjb3VudCkgKyBzdGFydDtcbiAgICBjb25zdCB7eDogcG9pbnRBeCwgeTogcG9pbnRBeX0gPSBkYXRhW2FdO1xuICAgIG1heEFyZWEgPSBhcmVhID0gLTE7XG4gICAgZm9yIChqID0gcmFuZ2VPZmZzOyBqIDwgcmFuZ2VUbzsgaisrKSB7XG4gICAgICBhcmVhID0gMC41ICogTWF0aC5hYnMoXG4gICAgICAgIChwb2ludEF4IC0gYXZnWCkgKiAoZGF0YVtqXS55IC0gcG9pbnRBeSkgLVxuICAgICAgICAocG9pbnRBeCAtIGRhdGFbal0ueCkgKiAoYXZnWSAtIHBvaW50QXkpXG4gICAgICApO1xuICAgICAgaWYgKGFyZWEgPiBtYXhBcmVhKSB7XG4gICAgICAgIG1heEFyZWEgPSBhcmVhO1xuICAgICAgICBtYXhBcmVhUG9pbnQgPSBkYXRhW2pdO1xuICAgICAgICBuZXh0QSA9IGo7XG4gICAgICB9XG4gICAgfVxuICAgIGRlY2ltYXRlZFtzYW1wbGVkSW5kZXgrK10gPSBtYXhBcmVhUG9pbnQ7XG4gICAgYSA9IG5leHRBO1xuICB9XG4gIGRlY2ltYXRlZFtzYW1wbGVkSW5kZXgrK10gPSBkYXRhW2VuZEluZGV4XTtcbiAgcmV0dXJuIGRlY2ltYXRlZDtcbn1cbmZ1bmN0aW9uIG1pbk1heERlY2ltYXRpb24oZGF0YSwgc3RhcnQsIGNvdW50LCBhdmFpbGFibGVXaWR0aCkge1xuICBsZXQgYXZnWCA9IDA7XG4gIGxldCBjb3VudFggPSAwO1xuICBsZXQgaSwgcG9pbnQsIHgsIHksIHByZXZYLCBtaW5JbmRleCwgbWF4SW5kZXgsIHN0YXJ0SW5kZXgsIG1pblksIG1heFk7XG4gIGNvbnN0IGRlY2ltYXRlZCA9IFtdO1xuICBjb25zdCBlbmRJbmRleCA9IHN0YXJ0ICsgY291bnQgLSAxO1xuICBjb25zdCB4TWluID0gZGF0YVtzdGFydF0ueDtcbiAgY29uc3QgeE1heCA9IGRhdGFbZW5kSW5kZXhdLng7XG4gIGNvbnN0IGR4ID0geE1heCAtIHhNaW47XG4gIGZvciAoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgKytpKSB7XG4gICAgcG9pbnQgPSBkYXRhW2ldO1xuICAgIHggPSAocG9pbnQueCAtIHhNaW4pIC8gZHggKiBhdmFpbGFibGVXaWR0aDtcbiAgICB5ID0gcG9pbnQueTtcbiAgICBjb25zdCB0cnVuY1ggPSB4IHwgMDtcbiAgICBpZiAodHJ1bmNYID09PSBwcmV2WCkge1xuICAgICAgaWYgKHkgPCBtaW5ZKSB7XG4gICAgICAgIG1pblkgPSB5O1xuICAgICAgICBtaW5JbmRleCA9IGk7XG4gICAgICB9IGVsc2UgaWYgKHkgPiBtYXhZKSB7XG4gICAgICAgIG1heFkgPSB5O1xuICAgICAgICBtYXhJbmRleCA9IGk7XG4gICAgICB9XG4gICAgICBhdmdYID0gKGNvdW50WCAqIGF2Z1ggKyBwb2ludC54KSAvICsrY291bnRYO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBsYXN0SW5kZXggPSBpIC0gMTtcbiAgICAgIGlmICghaXNOdWxsT3JVbmRlZihtaW5JbmRleCkgJiYgIWlzTnVsbE9yVW5kZWYobWF4SW5kZXgpKSB7XG4gICAgICAgIGNvbnN0IGludGVybWVkaWF0ZUluZGV4MSA9IE1hdGgubWluKG1pbkluZGV4LCBtYXhJbmRleCk7XG4gICAgICAgIGNvbnN0IGludGVybWVkaWF0ZUluZGV4MiA9IE1hdGgubWF4KG1pbkluZGV4LCBtYXhJbmRleCk7XG4gICAgICAgIGlmIChpbnRlcm1lZGlhdGVJbmRleDEgIT09IHN0YXJ0SW5kZXggJiYgaW50ZXJtZWRpYXRlSW5kZXgxICE9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICBkZWNpbWF0ZWQucHVzaCh7XG4gICAgICAgICAgICAuLi5kYXRhW2ludGVybWVkaWF0ZUluZGV4MV0sXG4gICAgICAgICAgICB4OiBhdmdYLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpbnRlcm1lZGlhdGVJbmRleDIgIT09IHN0YXJ0SW5kZXggJiYgaW50ZXJtZWRpYXRlSW5kZXgyICE9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICBkZWNpbWF0ZWQucHVzaCh7XG4gICAgICAgICAgICAuLi5kYXRhW2ludGVybWVkaWF0ZUluZGV4Ml0sXG4gICAgICAgICAgICB4OiBhdmdYXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChpID4gMCAmJiBsYXN0SW5kZXggIT09IHN0YXJ0SW5kZXgpIHtcbiAgICAgICAgZGVjaW1hdGVkLnB1c2goZGF0YVtsYXN0SW5kZXhdKTtcbiAgICAgIH1cbiAgICAgIGRlY2ltYXRlZC5wdXNoKHBvaW50KTtcbiAgICAgIHByZXZYID0gdHJ1bmNYO1xuICAgICAgY291bnRYID0gMDtcbiAgICAgIG1pblkgPSBtYXhZID0geTtcbiAgICAgIG1pbkluZGV4ID0gbWF4SW5kZXggPSBzdGFydEluZGV4ID0gaTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlY2ltYXRlZDtcbn1cbmZ1bmN0aW9uIGNsZWFuRGVjaW1hdGVkRGF0YXNldChkYXRhc2V0KSB7XG4gIGlmIChkYXRhc2V0Ll9kZWNpbWF0ZWQpIHtcbiAgICBjb25zdCBkYXRhID0gZGF0YXNldC5fZGF0YTtcbiAgICBkZWxldGUgZGF0YXNldC5fZGVjaW1hdGVkO1xuICAgIGRlbGV0ZSBkYXRhc2V0Ll9kYXRhO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYXRhc2V0LCAnZGF0YScsIHt2YWx1ZTogZGF0YX0pO1xuICB9XG59XG5mdW5jdGlvbiBjbGVhbkRlY2ltYXRlZERhdGEoY2hhcnQpIHtcbiAgY2hhcnQuZGF0YS5kYXRhc2V0cy5mb3JFYWNoKChkYXRhc2V0KSA9PiB7XG4gICAgY2xlYW5EZWNpbWF0ZWREYXRhc2V0KGRhdGFzZXQpO1xuICB9KTtcbn1cbmZ1bmN0aW9uIGdldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHNTaW1wbGlmaWVkKG1ldGEsIHBvaW50cykge1xuICBjb25zdCBwb2ludENvdW50ID0gcG9pbnRzLmxlbmd0aDtcbiAgbGV0IHN0YXJ0ID0gMDtcbiAgbGV0IGNvdW50O1xuICBjb25zdCB7aVNjYWxlfSA9IG1ldGE7XG4gIGNvbnN0IHttaW4sIG1heCwgbWluRGVmaW5lZCwgbWF4RGVmaW5lZH0gPSBpU2NhbGUuZ2V0VXNlckJvdW5kcygpO1xuICBpZiAobWluRGVmaW5lZCkge1xuICAgIHN0YXJ0ID0gX2xpbWl0VmFsdWUoX2xvb2t1cEJ5S2V5KHBvaW50cywgaVNjYWxlLmF4aXMsIG1pbikubG8sIDAsIHBvaW50Q291bnQgLSAxKTtcbiAgfVxuICBpZiAobWF4RGVmaW5lZCkge1xuICAgIGNvdW50ID0gX2xpbWl0VmFsdWUoX2xvb2t1cEJ5S2V5KHBvaW50cywgaVNjYWxlLmF4aXMsIG1heCkuaGkgKyAxLCBzdGFydCwgcG9pbnRDb3VudCkgLSBzdGFydDtcbiAgfSBlbHNlIHtcbiAgICBjb3VudCA9IHBvaW50Q291bnQgLSBzdGFydDtcbiAgfVxuICByZXR1cm4ge3N0YXJ0LCBjb3VudH07XG59XG52YXIgcGx1Z2luX2RlY2ltYXRpb24gPSB7XG4gIGlkOiAnZGVjaW1hdGlvbicsXG4gIGRlZmF1bHRzOiB7XG4gICAgYWxnb3JpdGhtOiAnbWluLW1heCcsXG4gICAgZW5hYmxlZDogZmFsc2UsXG4gIH0sXG4gIGJlZm9yZUVsZW1lbnRzVXBkYXRlOiAoY2hhcnQsIGFyZ3MsIG9wdGlvbnMpID0+IHtcbiAgICBpZiAoIW9wdGlvbnMuZW5hYmxlZCkge1xuICAgICAgY2xlYW5EZWNpbWF0ZWREYXRhKGNoYXJ0KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgYXZhaWxhYmxlV2lkdGggPSBjaGFydC53aWR0aDtcbiAgICBjaGFydC5kYXRhLmRhdGFzZXRzLmZvckVhY2goKGRhdGFzZXQsIGRhdGFzZXRJbmRleCkgPT4ge1xuICAgICAgY29uc3Qge19kYXRhLCBpbmRleEF4aXN9ID0gZGF0YXNldDtcbiAgICAgIGNvbnN0IG1ldGEgPSBjaGFydC5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgY29uc3QgZGF0YSA9IF9kYXRhIHx8IGRhdGFzZXQuZGF0YTtcbiAgICAgIGlmIChyZXNvbHZlKFtpbmRleEF4aXMsIGNoYXJ0Lm9wdGlvbnMuaW5kZXhBeGlzXSkgPT09ICd5Jykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAobWV0YS50eXBlICE9PSAnbGluZScpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgeEF4aXMgPSBjaGFydC5zY2FsZXNbbWV0YS54QXhpc0lEXTtcbiAgICAgIGlmICh4QXhpcy50eXBlICE9PSAnbGluZWFyJyAmJiB4QXhpcy50eXBlICE9PSAndGltZScpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXJ0Lm9wdGlvbnMucGFyc2luZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBsZXQge3N0YXJ0LCBjb3VudH0gPSBnZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzU2ltcGxpZmllZChtZXRhLCBkYXRhKTtcbiAgICAgIGNvbnN0IHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkIHx8IDQgKiBhdmFpbGFibGVXaWR0aDtcbiAgICAgIGlmIChjb3VudCA8PSB0aHJlc2hvbGQpIHtcbiAgICAgICAgY2xlYW5EZWNpbWF0ZWREYXRhc2V0KGRhdGFzZXQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoaXNOdWxsT3JVbmRlZihfZGF0YSkpIHtcbiAgICAgICAgZGF0YXNldC5fZGF0YSA9IGRhdGE7XG4gICAgICAgIGRlbGV0ZSBkYXRhc2V0LmRhdGE7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYXRhc2V0LCAnZGF0YScsIHtcbiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RlY2ltYXRlZDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNldDogZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdGhpcy5fZGF0YSA9IGQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGxldCBkZWNpbWF0ZWQ7XG4gICAgICBzd2l0Y2ggKG9wdGlvbnMuYWxnb3JpdGhtKSB7XG4gICAgICBjYXNlICdsdHRiJzpcbiAgICAgICAgZGVjaW1hdGVkID0gbHR0YkRlY2ltYXRpb24oZGF0YSwgc3RhcnQsIGNvdW50LCBhdmFpbGFibGVXaWR0aCwgb3B0aW9ucyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbWluLW1heCc6XG4gICAgICAgIGRlY2ltYXRlZCA9IG1pbk1heERlY2ltYXRpb24oZGF0YSwgc3RhcnQsIGNvdW50LCBhdmFpbGFibGVXaWR0aCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkZWNpbWF0aW9uIGFsZ29yaXRobSAnJHtvcHRpb25zLmFsZ29yaXRobX0nYCk7XG4gICAgICB9XG4gICAgICBkYXRhc2V0Ll9kZWNpbWF0ZWQgPSBkZWNpbWF0ZWQ7XG4gICAgfSk7XG4gIH0sXG4gIGRlc3Ryb3koY2hhcnQpIHtcbiAgICBjbGVhbkRlY2ltYXRlZERhdGEoY2hhcnQpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBnZXRMaW5lQnlJbmRleChjaGFydCwgaW5kZXgpIHtcbiAgY29uc3QgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGluZGV4KTtcbiAgY29uc3QgdmlzaWJsZSA9IG1ldGEgJiYgY2hhcnQuaXNEYXRhc2V0VmlzaWJsZShpbmRleCk7XG4gIHJldHVybiB2aXNpYmxlID8gbWV0YS5kYXRhc2V0IDogbnVsbDtcbn1cbmZ1bmN0aW9uIHBhcnNlRmlsbE9wdGlvbihsaW5lKSB7XG4gIGNvbnN0IG9wdGlvbnMgPSBsaW5lLm9wdGlvbnM7XG4gIGNvbnN0IGZpbGxPcHRpb24gPSBvcHRpb25zLmZpbGw7XG4gIGxldCBmaWxsID0gdmFsdWVPckRlZmF1bHQoZmlsbE9wdGlvbiAmJiBmaWxsT3B0aW9uLnRhcmdldCwgZmlsbE9wdGlvbik7XG4gIGlmIChmaWxsID09PSB1bmRlZmluZWQpIHtcbiAgICBmaWxsID0gISFvcHRpb25zLmJhY2tncm91bmRDb2xvcjtcbiAgfVxuICBpZiAoZmlsbCA9PT0gZmFsc2UgfHwgZmlsbCA9PT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoZmlsbCA9PT0gdHJ1ZSkge1xuICAgIHJldHVybiAnb3JpZ2luJztcbiAgfVxuICByZXR1cm4gZmlsbDtcbn1cbmZ1bmN0aW9uIGRlY29kZUZpbGwobGluZSwgaW5kZXgsIGNvdW50KSB7XG4gIGNvbnN0IGZpbGwgPSBwYXJzZUZpbGxPcHRpb24obGluZSk7XG4gIGlmIChpc09iamVjdChmaWxsKSkge1xuICAgIHJldHVybiBpc05hTihmaWxsLnZhbHVlKSA/IGZhbHNlIDogZmlsbDtcbiAgfVxuICBsZXQgdGFyZ2V0ID0gcGFyc2VGbG9hdChmaWxsKTtcbiAgaWYgKGlzTnVtYmVyRmluaXRlKHRhcmdldCkgJiYgTWF0aC5mbG9vcih0YXJnZXQpID09PSB0YXJnZXQpIHtcbiAgICBpZiAoZmlsbFswXSA9PT0gJy0nIHx8IGZpbGxbMF0gPT09ICcrJykge1xuICAgICAgdGFyZ2V0ID0gaW5kZXggKyB0YXJnZXQ7XG4gICAgfVxuICAgIGlmICh0YXJnZXQgPT09IGluZGV4IHx8IHRhcmdldCA8IDAgfHwgdGFyZ2V0ID49IGNvdW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQ7XG4gIH1cbiAgcmV0dXJuIFsnb3JpZ2luJywgJ3N0YXJ0JywgJ2VuZCcsICdzdGFjaycsICdzaGFwZSddLmluZGV4T2YoZmlsbCkgPj0gMCAmJiBmaWxsO1xufVxuZnVuY3Rpb24gY29tcHV0ZUxpbmVhckJvdW5kYXJ5KHNvdXJjZSkge1xuICBjb25zdCB7c2NhbGUgPSB7fSwgZmlsbH0gPSBzb3VyY2U7XG4gIGxldCB0YXJnZXQgPSBudWxsO1xuICBsZXQgaG9yaXpvbnRhbDtcbiAgaWYgKGZpbGwgPT09ICdzdGFydCcpIHtcbiAgICB0YXJnZXQgPSBzY2FsZS5ib3R0b207XG4gIH0gZWxzZSBpZiAoZmlsbCA9PT0gJ2VuZCcpIHtcbiAgICB0YXJnZXQgPSBzY2FsZS50b3A7XG4gIH0gZWxzZSBpZiAoaXNPYmplY3QoZmlsbCkpIHtcbiAgICB0YXJnZXQgPSBzY2FsZS5nZXRQaXhlbEZvclZhbHVlKGZpbGwudmFsdWUpO1xuICB9IGVsc2UgaWYgKHNjYWxlLmdldEJhc2VQaXhlbCkge1xuICAgIHRhcmdldCA9IHNjYWxlLmdldEJhc2VQaXhlbCgpO1xuICB9XG4gIGlmIChpc051bWJlckZpbml0ZSh0YXJnZXQpKSB7XG4gICAgaG9yaXpvbnRhbCA9IHNjYWxlLmlzSG9yaXpvbnRhbCgpO1xuICAgIHJldHVybiB7XG4gICAgICB4OiBob3Jpem9udGFsID8gdGFyZ2V0IDogbnVsbCxcbiAgICAgIHk6IGhvcml6b250YWwgPyBudWxsIDogdGFyZ2V0XG4gICAgfTtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cbmNsYXNzIHNpbXBsZUFyYyB7XG4gIGNvbnN0cnVjdG9yKG9wdHMpIHtcbiAgICB0aGlzLnggPSBvcHRzLng7XG4gICAgdGhpcy55ID0gb3B0cy55O1xuICAgIHRoaXMucmFkaXVzID0gb3B0cy5yYWRpdXM7XG4gIH1cbiAgcGF0aFNlZ21lbnQoY3R4LCBib3VuZHMsIG9wdHMpIHtcbiAgICBjb25zdCB7eCwgeSwgcmFkaXVzfSA9IHRoaXM7XG4gICAgYm91bmRzID0gYm91bmRzIHx8IHtzdGFydDogMCwgZW5kOiBUQVV9O1xuICAgIGN0eC5hcmMoeCwgeSwgcmFkaXVzLCBib3VuZHMuZW5kLCBib3VuZHMuc3RhcnQsIHRydWUpO1xuICAgIHJldHVybiAhb3B0cy5ib3VuZHM7XG4gIH1cbiAgaW50ZXJwb2xhdGUocG9pbnQpIHtcbiAgICBjb25zdCB7eCwgeSwgcmFkaXVzfSA9IHRoaXM7XG4gICAgY29uc3QgYW5nbGUgPSBwb2ludC5hbmdsZTtcbiAgICByZXR1cm4ge1xuICAgICAgeDogeCArIE1hdGguY29zKGFuZ2xlKSAqIHJhZGl1cyxcbiAgICAgIHk6IHkgKyBNYXRoLnNpbihhbmdsZSkgKiByYWRpdXMsXG4gICAgICBhbmdsZVxuICAgIH07XG4gIH1cbn1cbmZ1bmN0aW9uIGNvbXB1dGVDaXJjdWxhckJvdW5kYXJ5KHNvdXJjZSkge1xuICBjb25zdCB7c2NhbGUsIGZpbGx9ID0gc291cmNlO1xuICBjb25zdCBvcHRpb25zID0gc2NhbGUub3B0aW9ucztcbiAgY29uc3QgbGVuZ3RoID0gc2NhbGUuZ2V0TGFiZWxzKCkubGVuZ3RoO1xuICBjb25zdCB0YXJnZXQgPSBbXTtcbiAgY29uc3Qgc3RhcnQgPSBvcHRpb25zLnJldmVyc2UgPyBzY2FsZS5tYXggOiBzY2FsZS5taW47XG4gIGNvbnN0IGVuZCA9IG9wdGlvbnMucmV2ZXJzZSA/IHNjYWxlLm1pbiA6IHNjYWxlLm1heDtcbiAgbGV0IGksIGNlbnRlciwgdmFsdWU7XG4gIGlmIChmaWxsID09PSAnc3RhcnQnKSB7XG4gICAgdmFsdWUgPSBzdGFydDtcbiAgfSBlbHNlIGlmIChmaWxsID09PSAnZW5kJykge1xuICAgIHZhbHVlID0gZW5kO1xuICB9IGVsc2UgaWYgKGlzT2JqZWN0KGZpbGwpKSB7XG4gICAgdmFsdWUgPSBmaWxsLnZhbHVlO1xuICB9IGVsc2Uge1xuICAgIHZhbHVlID0gc2NhbGUuZ2V0QmFzZVZhbHVlKCk7XG4gIH1cbiAgaWYgKG9wdGlvbnMuZ3JpZC5jaXJjdWxhcikge1xuICAgIGNlbnRlciA9IHNjYWxlLmdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZSgwLCBzdGFydCk7XG4gICAgcmV0dXJuIG5ldyBzaW1wbGVBcmMoe1xuICAgICAgeDogY2VudGVyLngsXG4gICAgICB5OiBjZW50ZXIueSxcbiAgICAgIHJhZGl1czogc2NhbGUuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodmFsdWUpXG4gICAgfSk7XG4gIH1cbiAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgdGFyZ2V0LnB1c2goc2NhbGUuZ2V0UG9pbnRQb3NpdGlvbkZvclZhbHVlKGksIHZhbHVlKSk7XG4gIH1cbiAgcmV0dXJuIHRhcmdldDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVCb3VuZGFyeShzb3VyY2UpIHtcbiAgY29uc3Qgc2NhbGUgPSBzb3VyY2Uuc2NhbGUgfHwge307XG4gIGlmIChzY2FsZS5nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUpIHtcbiAgICByZXR1cm4gY29tcHV0ZUNpcmN1bGFyQm91bmRhcnkoc291cmNlKTtcbiAgfVxuICByZXR1cm4gY29tcHV0ZUxpbmVhckJvdW5kYXJ5KHNvdXJjZSk7XG59XG5mdW5jdGlvbiBmaW5kU2VnbWVudEVuZChzdGFydCwgZW5kLCBwb2ludHMpIHtcbiAgZm9yICg7ZW5kID4gc3RhcnQ7IGVuZC0tKSB7XG4gICAgY29uc3QgcG9pbnQgPSBwb2ludHNbZW5kXTtcbiAgICBpZiAoIWlzTmFOKHBvaW50LngpICYmICFpc05hTihwb2ludC55KSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBlbmQ7XG59XG5mdW5jdGlvbiBwb2ludHNGcm9tU2VnbWVudHMoYm91bmRhcnksIGxpbmUpIHtcbiAgY29uc3Qge3ggPSBudWxsLCB5ID0gbnVsbH0gPSBib3VuZGFyeSB8fCB7fTtcbiAgY29uc3QgbGluZVBvaW50cyA9IGxpbmUucG9pbnRzO1xuICBjb25zdCBwb2ludHMgPSBbXTtcbiAgbGluZS5zZWdtZW50cy5mb3JFYWNoKCh7c3RhcnQsIGVuZH0pID0+IHtcbiAgICBlbmQgPSBmaW5kU2VnbWVudEVuZChzdGFydCwgZW5kLCBsaW5lUG9pbnRzKTtcbiAgICBjb25zdCBmaXJzdCA9IGxpbmVQb2ludHNbc3RhcnRdO1xuICAgIGNvbnN0IGxhc3QgPSBsaW5lUG9pbnRzW2VuZF07XG4gICAgaWYgKHkgIT09IG51bGwpIHtcbiAgICAgIHBvaW50cy5wdXNoKHt4OiBmaXJzdC54LCB5fSk7XG4gICAgICBwb2ludHMucHVzaCh7eDogbGFzdC54LCB5fSk7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBudWxsKSB7XG4gICAgICBwb2ludHMucHVzaCh7eCwgeTogZmlyc3QueX0pO1xuICAgICAgcG9pbnRzLnB1c2goe3gsIHk6IGxhc3QueX0pO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBwb2ludHM7XG59XG5mdW5jdGlvbiBidWlsZFN0YWNrTGluZShzb3VyY2UpIHtcbiAgY29uc3Qge2NoYXJ0LCBzY2FsZSwgaW5kZXgsIGxpbmV9ID0gc291cmNlO1xuICBjb25zdCBwb2ludHMgPSBbXTtcbiAgY29uc3Qgc2VnbWVudHMgPSBsaW5lLnNlZ21lbnRzO1xuICBjb25zdCBzb3VyY2VQb2ludHMgPSBsaW5lLnBvaW50cztcbiAgY29uc3QgbGluZXNCZWxvdyA9IGdldExpbmVzQmVsb3coY2hhcnQsIGluZGV4KTtcbiAgbGluZXNCZWxvdy5wdXNoKGNyZWF0ZUJvdW5kYXJ5TGluZSh7eDogbnVsbCwgeTogc2NhbGUuYm90dG9tfSwgbGluZSkpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3Qgc2VnbWVudCA9IHNlZ21lbnRzW2ldO1xuICAgIGZvciAobGV0IGogPSBzZWdtZW50LnN0YXJ0OyBqIDw9IHNlZ21lbnQuZW5kOyBqKyspIHtcbiAgICAgIGFkZFBvaW50c0JlbG93KHBvaW50cywgc291cmNlUG9pbnRzW2pdLCBsaW5lc0JlbG93KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5ldyBMaW5lRWxlbWVudCh7cG9pbnRzLCBvcHRpb25zOiB7fX0pO1xufVxuY29uc3QgaXNMaW5lQW5kTm90SW5IaWRlQW5pbWF0aW9uID0gKG1ldGEpID0+IG1ldGEudHlwZSA9PT0gJ2xpbmUnICYmICFtZXRhLmhpZGRlbjtcbmZ1bmN0aW9uIGdldExpbmVzQmVsb3coY2hhcnQsIGluZGV4KSB7XG4gIGNvbnN0IGJlbG93ID0gW107XG4gIGNvbnN0IG1ldGFzID0gY2hhcnQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG1ldGFzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgbWV0YSA9IG1ldGFzW2ldO1xuICAgIGlmIChtZXRhLmluZGV4ID09PSBpbmRleCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGlmIChpc0xpbmVBbmROb3RJbkhpZGVBbmltYXRpb24obWV0YSkpIHtcbiAgICAgIGJlbG93LnVuc2hpZnQobWV0YS5kYXRhc2V0KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJlbG93O1xufVxuZnVuY3Rpb24gYWRkUG9pbnRzQmVsb3cocG9pbnRzLCBzb3VyY2VQb2ludCwgbGluZXNCZWxvdykge1xuICBjb25zdCBwb3N0cG9uZWQgPSBbXTtcbiAgZm9yIChsZXQgaiA9IDA7IGogPCBsaW5lc0JlbG93Lmxlbmd0aDsgaisrKSB7XG4gICAgY29uc3QgbGluZSA9IGxpbmVzQmVsb3dbal07XG4gICAgY29uc3Qge2ZpcnN0LCBsYXN0LCBwb2ludH0gPSBmaW5kUG9pbnQobGluZSwgc291cmNlUG9pbnQsICd4Jyk7XG4gICAgaWYgKCFwb2ludCB8fCAoZmlyc3QgJiYgbGFzdCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoZmlyc3QpIHtcbiAgICAgIHBvc3Rwb25lZC51bnNoaWZ0KHBvaW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcG9pbnRzLnB1c2gocG9pbnQpO1xuICAgICAgaWYgKCFsYXN0KSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBwb2ludHMucHVzaCguLi5wb3N0cG9uZWQpO1xufVxuZnVuY3Rpb24gZmluZFBvaW50KGxpbmUsIHNvdXJjZVBvaW50LCBwcm9wZXJ0eSkge1xuICBjb25zdCBwb2ludCA9IGxpbmUuaW50ZXJwb2xhdGUoc291cmNlUG9pbnQsIHByb3BlcnR5KTtcbiAgaWYgKCFwb2ludCkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuICBjb25zdCBwb2ludFZhbHVlID0gcG9pbnRbcHJvcGVydHldO1xuICBjb25zdCBzZWdtZW50cyA9IGxpbmUuc2VnbWVudHM7XG4gIGNvbnN0IGxpbmVQb2ludHMgPSBsaW5lLnBvaW50cztcbiAgbGV0IGZpcnN0ID0gZmFsc2U7XG4gIGxldCBsYXN0ID0gZmFsc2U7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBzZWdtZW50ID0gc2VnbWVudHNbaV07XG4gICAgY29uc3QgZmlyc3RWYWx1ZSA9IGxpbmVQb2ludHNbc2VnbWVudC5zdGFydF1bcHJvcGVydHldO1xuICAgIGNvbnN0IGxhc3RWYWx1ZSA9IGxpbmVQb2ludHNbc2VnbWVudC5lbmRdW3Byb3BlcnR5XTtcbiAgICBpZiAocG9pbnRWYWx1ZSA+PSBmaXJzdFZhbHVlICYmIHBvaW50VmFsdWUgPD0gbGFzdFZhbHVlKSB7XG4gICAgICBmaXJzdCA9IHBvaW50VmFsdWUgPT09IGZpcnN0VmFsdWU7XG4gICAgICBsYXN0ID0gcG9pbnRWYWx1ZSA9PT0gbGFzdFZhbHVlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiB7Zmlyc3QsIGxhc3QsIHBvaW50fTtcbn1cbmZ1bmN0aW9uIGdldFRhcmdldChzb3VyY2UpIHtcbiAgY29uc3Qge2NoYXJ0LCBmaWxsLCBsaW5lfSA9IHNvdXJjZTtcbiAgaWYgKGlzTnVtYmVyRmluaXRlKGZpbGwpKSB7XG4gICAgcmV0dXJuIGdldExpbmVCeUluZGV4KGNoYXJ0LCBmaWxsKTtcbiAgfVxuICBpZiAoZmlsbCA9PT0gJ3N0YWNrJykge1xuICAgIHJldHVybiBidWlsZFN0YWNrTGluZShzb3VyY2UpO1xuICB9XG4gIGlmIChmaWxsID09PSAnc2hhcGUnKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgY29uc3QgYm91bmRhcnkgPSBjb21wdXRlQm91bmRhcnkoc291cmNlKTtcbiAgaWYgKGJvdW5kYXJ5IGluc3RhbmNlb2Ygc2ltcGxlQXJjKSB7XG4gICAgcmV0dXJuIGJvdW5kYXJ5O1xuICB9XG4gIHJldHVybiBjcmVhdGVCb3VuZGFyeUxpbmUoYm91bmRhcnksIGxpbmUpO1xufVxuZnVuY3Rpb24gY3JlYXRlQm91bmRhcnlMaW5lKGJvdW5kYXJ5LCBsaW5lKSB7XG4gIGxldCBwb2ludHMgPSBbXTtcbiAgbGV0IF9sb29wID0gZmFsc2U7XG4gIGlmIChpc0FycmF5KGJvdW5kYXJ5KSkge1xuICAgIF9sb29wID0gdHJ1ZTtcbiAgICBwb2ludHMgPSBib3VuZGFyeTtcbiAgfSBlbHNlIHtcbiAgICBwb2ludHMgPSBwb2ludHNGcm9tU2VnbWVudHMoYm91bmRhcnksIGxpbmUpO1xuICB9XG4gIHJldHVybiBwb2ludHMubGVuZ3RoID8gbmV3IExpbmVFbGVtZW50KHtcbiAgICBwb2ludHMsXG4gICAgb3B0aW9uczoge3RlbnNpb246IDB9LFxuICAgIF9sb29wLFxuICAgIF9mdWxsTG9vcDogX2xvb3BcbiAgfSkgOiBudWxsO1xufVxuZnVuY3Rpb24gcmVzb2x2ZVRhcmdldChzb3VyY2VzLCBpbmRleCwgcHJvcGFnYXRlKSB7XG4gIGNvbnN0IHNvdXJjZSA9IHNvdXJjZXNbaW5kZXhdO1xuICBsZXQgZmlsbCA9IHNvdXJjZS5maWxsO1xuICBjb25zdCB2aXNpdGVkID0gW2luZGV4XTtcbiAgbGV0IHRhcmdldDtcbiAgaWYgKCFwcm9wYWdhdGUpIHtcbiAgICByZXR1cm4gZmlsbDtcbiAgfVxuICB3aGlsZSAoZmlsbCAhPT0gZmFsc2UgJiYgdmlzaXRlZC5pbmRleE9mKGZpbGwpID09PSAtMSkge1xuICAgIGlmICghaXNOdW1iZXJGaW5pdGUoZmlsbCkpIHtcbiAgICAgIHJldHVybiBmaWxsO1xuICAgIH1cbiAgICB0YXJnZXQgPSBzb3VyY2VzW2ZpbGxdO1xuICAgIGlmICghdGFyZ2V0KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICh0YXJnZXQudmlzaWJsZSkge1xuICAgICAgcmV0dXJuIGZpbGw7XG4gICAgfVxuICAgIHZpc2l0ZWQucHVzaChmaWxsKTtcbiAgICBmaWxsID0gdGFyZ2V0LmZpbGw7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gX2NsaXAoY3R4LCB0YXJnZXQsIGNsaXBZKSB7XG4gIGN0eC5iZWdpblBhdGgoKTtcbiAgdGFyZ2V0LnBhdGgoY3R4KTtcbiAgY3R4LmxpbmVUbyh0YXJnZXQubGFzdCgpLngsIGNsaXBZKTtcbiAgY3R4LmxpbmVUbyh0YXJnZXQuZmlyc3QoKS54LCBjbGlwWSk7XG4gIGN0eC5jbG9zZVBhdGgoKTtcbiAgY3R4LmNsaXAoKTtcbn1cbmZ1bmN0aW9uIGdldEJvdW5kcyhwcm9wZXJ0eSwgZmlyc3QsIGxhc3QsIGxvb3ApIHtcbiAgaWYgKGxvb3ApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgbGV0IHN0YXJ0ID0gZmlyc3RbcHJvcGVydHldO1xuICBsZXQgZW5kID0gbGFzdFtwcm9wZXJ0eV07XG4gIGlmIChwcm9wZXJ0eSA9PT0gJ2FuZ2xlJykge1xuICAgIHN0YXJ0ID0gX25vcm1hbGl6ZUFuZ2xlKHN0YXJ0KTtcbiAgICBlbmQgPSBfbm9ybWFsaXplQW5nbGUoZW5kKTtcbiAgfVxuICByZXR1cm4ge3Byb3BlcnR5LCBzdGFydCwgZW5kfTtcbn1cbmZ1bmN0aW9uIF9nZXRFZGdlKGEsIGIsIHByb3AsIGZuKSB7XG4gIGlmIChhICYmIGIpIHtcbiAgICByZXR1cm4gZm4oYVtwcm9wXSwgYltwcm9wXSk7XG4gIH1cbiAgcmV0dXJuIGEgPyBhW3Byb3BdIDogYiA/IGJbcHJvcF0gOiAwO1xufVxuZnVuY3Rpb24gX3NlZ21lbnRzKGxpbmUsIHRhcmdldCwgcHJvcGVydHkpIHtcbiAgY29uc3Qgc2VnbWVudHMgPSBsaW5lLnNlZ21lbnRzO1xuICBjb25zdCBwb2ludHMgPSBsaW5lLnBvaW50cztcbiAgY29uc3QgdHBvaW50cyA9IHRhcmdldC5wb2ludHM7XG4gIGNvbnN0IHBhcnRzID0gW107XG4gIGZvciAoY29uc3Qgc2VnbWVudCBvZiBzZWdtZW50cykge1xuICAgIGxldCB7c3RhcnQsIGVuZH0gPSBzZWdtZW50O1xuICAgIGVuZCA9IGZpbmRTZWdtZW50RW5kKHN0YXJ0LCBlbmQsIHBvaW50cyk7XG4gICAgY29uc3QgYm91bmRzID0gZ2V0Qm91bmRzKHByb3BlcnR5LCBwb2ludHNbc3RhcnRdLCBwb2ludHNbZW5kXSwgc2VnbWVudC5sb29wKTtcbiAgICBpZiAoIXRhcmdldC5zZWdtZW50cykge1xuICAgICAgcGFydHMucHVzaCh7XG4gICAgICAgIHNvdXJjZTogc2VnbWVudCxcbiAgICAgICAgdGFyZ2V0OiBib3VuZHMsXG4gICAgICAgIHN0YXJ0OiBwb2ludHNbc3RhcnRdLFxuICAgICAgICBlbmQ6IHBvaW50c1tlbmRdXG4gICAgICB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCB0YXJnZXRTZWdtZW50cyA9IF9ib3VuZFNlZ21lbnRzKHRhcmdldCwgYm91bmRzKTtcbiAgICBmb3IgKGNvbnN0IHRndCBvZiB0YXJnZXRTZWdtZW50cykge1xuICAgICAgY29uc3Qgc3ViQm91bmRzID0gZ2V0Qm91bmRzKHByb3BlcnR5LCB0cG9pbnRzW3RndC5zdGFydF0sIHRwb2ludHNbdGd0LmVuZF0sIHRndC5sb29wKTtcbiAgICAgIGNvbnN0IGZpbGxTb3VyY2VzID0gX2JvdW5kU2VnbWVudChzZWdtZW50LCBwb2ludHMsIHN1YkJvdW5kcyk7XG4gICAgICBmb3IgKGNvbnN0IGZpbGxTb3VyY2Ugb2YgZmlsbFNvdXJjZXMpIHtcbiAgICAgICAgcGFydHMucHVzaCh7XG4gICAgICAgICAgc291cmNlOiBmaWxsU291cmNlLFxuICAgICAgICAgIHRhcmdldDogdGd0LFxuICAgICAgICAgIHN0YXJ0OiB7XG4gICAgICAgICAgICBbcHJvcGVydHldOiBfZ2V0RWRnZShib3VuZHMsIHN1YkJvdW5kcywgJ3N0YXJ0JywgTWF0aC5tYXgpXG4gICAgICAgICAgfSxcbiAgICAgICAgICBlbmQ6IHtcbiAgICAgICAgICAgIFtwcm9wZXJ0eV06IF9nZXRFZGdlKGJvdW5kcywgc3ViQm91bmRzLCAnZW5kJywgTWF0aC5taW4pXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHBhcnRzO1xufVxuZnVuY3Rpb24gY2xpcEJvdW5kcyhjdHgsIHNjYWxlLCBib3VuZHMpIHtcbiAgY29uc3Qge3RvcCwgYm90dG9tfSA9IHNjYWxlLmNoYXJ0LmNoYXJ0QXJlYTtcbiAgY29uc3Qge3Byb3BlcnR5LCBzdGFydCwgZW5kfSA9IGJvdW5kcyB8fCB7fTtcbiAgaWYgKHByb3BlcnR5ID09PSAneCcpIHtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4LnJlY3Qoc3RhcnQsIHRvcCwgZW5kIC0gc3RhcnQsIGJvdHRvbSAtIHRvcCk7XG4gICAgY3R4LmNsaXAoKTtcbiAgfVxufVxuZnVuY3Rpb24gaW50ZXJwb2xhdGVkTGluZVRvKGN0eCwgdGFyZ2V0LCBwb2ludCwgcHJvcGVydHkpIHtcbiAgY29uc3QgaW50ZXJwb2xhdGVkUG9pbnQgPSB0YXJnZXQuaW50ZXJwb2xhdGUocG9pbnQsIHByb3BlcnR5KTtcbiAgaWYgKGludGVycG9sYXRlZFBvaW50KSB7XG4gICAgY3R4LmxpbmVUbyhpbnRlcnBvbGF0ZWRQb2ludC54LCBpbnRlcnBvbGF0ZWRQb2ludC55KTtcbiAgfVxufVxuZnVuY3Rpb24gX2ZpbGwoY3R4LCBjZmcpIHtcbiAgY29uc3Qge2xpbmUsIHRhcmdldCwgcHJvcGVydHksIGNvbG9yLCBzY2FsZX0gPSBjZmc7XG4gIGNvbnN0IHNlZ21lbnRzID0gX3NlZ21lbnRzKGxpbmUsIHRhcmdldCwgcHJvcGVydHkpO1xuICBmb3IgKGNvbnN0IHtzb3VyY2U6IHNyYywgdGFyZ2V0OiB0Z3QsIHN0YXJ0LCBlbmR9IG9mIHNlZ21lbnRzKSB7XG4gICAgY29uc3Qge3N0eWxlOiB7YmFja2dyb3VuZENvbG9yID0gY29sb3J9ID0ge319ID0gc3JjO1xuICAgIGNvbnN0IG5vdFNoYXBlID0gdGFyZ2V0ICE9PSB0cnVlO1xuICAgIGN0eC5zYXZlKCk7XG4gICAgY3R4LmZpbGxTdHlsZSA9IGJhY2tncm91bmRDb2xvcjtcbiAgICBjbGlwQm91bmRzKGN0eCwgc2NhbGUsIG5vdFNoYXBlICYmIGdldEJvdW5kcyhwcm9wZXJ0eSwgc3RhcnQsIGVuZCkpO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBjb25zdCBsaW5lTG9vcCA9ICEhbGluZS5wYXRoU2VnbWVudChjdHgsIHNyYyk7XG4gICAgbGV0IGxvb3A7XG4gICAgaWYgKG5vdFNoYXBlKSB7XG4gICAgICBpZiAobGluZUxvb3ApIHtcbiAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW50ZXJwb2xhdGVkTGluZVRvKGN0eCwgdGFyZ2V0LCBlbmQsIHByb3BlcnR5KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRhcmdldExvb3AgPSAhIXRhcmdldC5wYXRoU2VnbWVudChjdHgsIHRndCwge21vdmU6IGxpbmVMb29wLCByZXZlcnNlOiB0cnVlfSk7XG4gICAgICBsb29wID0gbGluZUxvb3AgJiYgdGFyZ2V0TG9vcDtcbiAgICAgIGlmICghbG9vcCkge1xuICAgICAgICBpbnRlcnBvbGF0ZWRMaW5lVG8oY3R4LCB0YXJnZXQsIHN0YXJ0LCBwcm9wZXJ0eSk7XG4gICAgICB9XG4gICAgfVxuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBjdHguZmlsbChsb29wID8gJ2V2ZW5vZGQnIDogJ25vbnplcm8nKTtcbiAgICBjdHgucmVzdG9yZSgpO1xuICB9XG59XG5mdW5jdGlvbiBkb0ZpbGwoY3R4LCBjZmcpIHtcbiAgY29uc3Qge2xpbmUsIHRhcmdldCwgYWJvdmUsIGJlbG93LCBhcmVhLCBzY2FsZX0gPSBjZmc7XG4gIGNvbnN0IHByb3BlcnR5ID0gbGluZS5fbG9vcCA/ICdhbmdsZScgOiBjZmcuYXhpcztcbiAgY3R4LnNhdmUoKTtcbiAgaWYgKHByb3BlcnR5ID09PSAneCcgJiYgYmVsb3cgIT09IGFib3ZlKSB7XG4gICAgX2NsaXAoY3R4LCB0YXJnZXQsIGFyZWEudG9wKTtcbiAgICBfZmlsbChjdHgsIHtsaW5lLCB0YXJnZXQsIGNvbG9yOiBhYm92ZSwgc2NhbGUsIHByb3BlcnR5fSk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgICBjdHguc2F2ZSgpO1xuICAgIF9jbGlwKGN0eCwgdGFyZ2V0LCBhcmVhLmJvdHRvbSk7XG4gIH1cbiAgX2ZpbGwoY3R4LCB7bGluZSwgdGFyZ2V0LCBjb2xvcjogYmVsb3csIHNjYWxlLCBwcm9wZXJ0eX0pO1xuICBjdHgucmVzdG9yZSgpO1xufVxuZnVuY3Rpb24gZHJhd2ZpbGwoY3R4LCBzb3VyY2UsIGFyZWEpIHtcbiAgY29uc3QgdGFyZ2V0ID0gZ2V0VGFyZ2V0KHNvdXJjZSk7XG4gIGNvbnN0IHtsaW5lLCBzY2FsZSwgYXhpc30gPSBzb3VyY2U7XG4gIGNvbnN0IGxpbmVPcHRzID0gbGluZS5vcHRpb25zO1xuICBjb25zdCBmaWxsT3B0aW9uID0gbGluZU9wdHMuZmlsbDtcbiAgY29uc3QgY29sb3IgPSBsaW5lT3B0cy5iYWNrZ3JvdW5kQ29sb3I7XG4gIGNvbnN0IHthYm92ZSA9IGNvbG9yLCBiZWxvdyA9IGNvbG9yfSA9IGZpbGxPcHRpb24gfHwge307XG4gIGlmICh0YXJnZXQgJiYgbGluZS5wb2ludHMubGVuZ3RoKSB7XG4gICAgY2xpcEFyZWEoY3R4LCBhcmVhKTtcbiAgICBkb0ZpbGwoY3R4LCB7bGluZSwgdGFyZ2V0LCBhYm92ZSwgYmVsb3csIGFyZWEsIHNjYWxlLCBheGlzfSk7XG4gICAgdW5jbGlwQXJlYShjdHgpO1xuICB9XG59XG52YXIgcGx1Z2luX2ZpbGxlciA9IHtcbiAgaWQ6ICdmaWxsZXInLFxuICBhZnRlckRhdGFzZXRzVXBkYXRlKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgIGNvbnN0IGNvdW50ID0gKGNoYXJ0LmRhdGEuZGF0YXNldHMgfHwgW10pLmxlbmd0aDtcbiAgICBjb25zdCBzb3VyY2VzID0gW107XG4gICAgbGV0IG1ldGEsIGksIGxpbmUsIHNvdXJjZTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7ICsraSkge1xuICAgICAgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgbGluZSA9IG1ldGEuZGF0YXNldDtcbiAgICAgIHNvdXJjZSA9IG51bGw7XG4gICAgICBpZiAobGluZSAmJiBsaW5lLm9wdGlvbnMgJiYgbGluZSBpbnN0YW5jZW9mIExpbmVFbGVtZW50KSB7XG4gICAgICAgIHNvdXJjZSA9IHtcbiAgICAgICAgICB2aXNpYmxlOiBjaGFydC5pc0RhdGFzZXRWaXNpYmxlKGkpLFxuICAgICAgICAgIGluZGV4OiBpLFxuICAgICAgICAgIGZpbGw6IGRlY29kZUZpbGwobGluZSwgaSwgY291bnQpLFxuICAgICAgICAgIGNoYXJ0LFxuICAgICAgICAgIGF4aXM6IG1ldGEuY29udHJvbGxlci5vcHRpb25zLmluZGV4QXhpcyxcbiAgICAgICAgICBzY2FsZTogbWV0YS52U2NhbGUsXG4gICAgICAgICAgbGluZSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIG1ldGEuJGZpbGxlciA9IHNvdXJjZTtcbiAgICAgIHNvdXJjZXMucHVzaChzb3VyY2UpO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7ICsraSkge1xuICAgICAgc291cmNlID0gc291cmNlc1tpXTtcbiAgICAgIGlmICghc291cmNlIHx8IHNvdXJjZS5maWxsID09PSBmYWxzZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHNvdXJjZS5maWxsID0gcmVzb2x2ZVRhcmdldChzb3VyY2VzLCBpLCBvcHRpb25zLnByb3BhZ2F0ZSk7XG4gICAgfVxuICB9LFxuICBiZWZvcmVEcmF3KGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgIGNvbnN0IGRyYXcgPSBvcHRpb25zLmRyYXdUaW1lID09PSAnYmVmb3JlRHJhdyc7XG4gICAgY29uc3QgbWV0YXNldHMgPSBjaGFydC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCk7XG4gICAgY29uc3QgYXJlYSA9IGNoYXJ0LmNoYXJ0QXJlYTtcbiAgICBmb3IgKGxldCBpID0gbWV0YXNldHMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IG1ldGFzZXRzW2ldLiRmaWxsZXI7XG4gICAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHNvdXJjZS5saW5lLnVwZGF0ZUNvbnRyb2xQb2ludHMoYXJlYSwgc291cmNlLmF4aXMpO1xuICAgICAgaWYgKGRyYXcpIHtcbiAgICAgICAgZHJhd2ZpbGwoY2hhcnQuY3R4LCBzb3VyY2UsIGFyZWEpO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgYmVmb3JlRGF0YXNldHNEcmF3KGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmRyYXdUaW1lICE9PSAnYmVmb3JlRGF0YXNldHNEcmF3Jykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBtZXRhc2V0cyA9IGNoYXJ0LmdldFNvcnRlZFZpc2libGVEYXRhc2V0TWV0YXMoKTtcbiAgICBmb3IgKGxldCBpID0gbWV0YXNldHMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IG1ldGFzZXRzW2ldLiRmaWxsZXI7XG4gICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgIGRyYXdmaWxsKGNoYXJ0LmN0eCwgc291cmNlLCBjaGFydC5jaGFydEFyZWEpO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgYmVmb3JlRGF0YXNldERyYXcoY2hhcnQsIGFyZ3MsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBzb3VyY2UgPSBhcmdzLm1ldGEuJGZpbGxlcjtcbiAgICBpZiAoIXNvdXJjZSB8fCBzb3VyY2UuZmlsbCA9PT0gZmFsc2UgfHwgb3B0aW9ucy5kcmF3VGltZSAhPT0gJ2JlZm9yZURhdGFzZXREcmF3Jykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmF3ZmlsbChjaGFydC5jdHgsIHNvdXJjZSwgY2hhcnQuY2hhcnRBcmVhKTtcbiAgfSxcbiAgZGVmYXVsdHM6IHtcbiAgICBwcm9wYWdhdGU6IHRydWUsXG4gICAgZHJhd1RpbWU6ICdiZWZvcmVEYXRhc2V0RHJhdydcbiAgfVxufTtcblxuY29uc3QgZ2V0Qm94U2l6ZSA9IChsYWJlbE9wdHMsIGZvbnRTaXplKSA9PiB7XG4gIGxldCB7Ym94SGVpZ2h0ID0gZm9udFNpemUsIGJveFdpZHRoID0gZm9udFNpemV9ID0gbGFiZWxPcHRzO1xuICBpZiAobGFiZWxPcHRzLnVzZVBvaW50U3R5bGUpIHtcbiAgICBib3hIZWlnaHQgPSBNYXRoLm1pbihib3hIZWlnaHQsIGZvbnRTaXplKTtcbiAgICBib3hXaWR0aCA9IE1hdGgubWluKGJveFdpZHRoLCBmb250U2l6ZSk7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBib3hXaWR0aCxcbiAgICBib3hIZWlnaHQsXG4gICAgaXRlbUhlaWdodDogTWF0aC5tYXgoZm9udFNpemUsIGJveEhlaWdodClcbiAgfTtcbn07XG5jb25zdCBpdGVtc0VxdWFsID0gKGEsIGIpID0+IGEgIT09IG51bGwgJiYgYiAhPT0gbnVsbCAmJiBhLmRhdGFzZXRJbmRleCA9PT0gYi5kYXRhc2V0SW5kZXggJiYgYS5pbmRleCA9PT0gYi5pbmRleDtcbmNsYXNzIExlZ2VuZCBleHRlbmRzIEVsZW1lbnQge1xuICBjb25zdHJ1Y3Rvcihjb25maWcpIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuX2FkZGVkID0gZmFsc2U7XG4gICAgdGhpcy5sZWdlbmRIaXRCb3hlcyA9IFtdO1xuICAgIHRoaXMuX2hvdmVyZWRJdGVtID0gbnVsbDtcbiAgICB0aGlzLmRvdWdobnV0TW9kZSA9IGZhbHNlO1xuICAgIHRoaXMuY2hhcnQgPSBjb25maWcuY2hhcnQ7XG4gICAgdGhpcy5vcHRpb25zID0gY29uZmlnLm9wdGlvbnM7XG4gICAgdGhpcy5jdHggPSBjb25maWcuY3R4O1xuICAgIHRoaXMubGVnZW5kSXRlbXMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5jb2x1bW5TaXplcyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmxpbmVXaWR0aHMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5tYXhIZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5tYXhXaWR0aCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnRvcCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmJvdHRvbSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmxlZnQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5yaWdodCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLndpZHRoID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX21hcmdpbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5wb3NpdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLndlaWdodCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmZ1bGxTaXplID0gdW5kZWZpbmVkO1xuICB9XG4gIHVwZGF0ZShtYXhXaWR0aCwgbWF4SGVpZ2h0LCBtYXJnaW5zKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIG1lLm1heFdpZHRoID0gbWF4V2lkdGg7XG4gICAgbWUubWF4SGVpZ2h0ID0gbWF4SGVpZ2h0O1xuICAgIG1lLl9tYXJnaW5zID0gbWFyZ2lucztcbiAgICBtZS5zZXREaW1lbnNpb25zKCk7XG4gICAgbWUuYnVpbGRMYWJlbHMoKTtcbiAgICBtZS5maXQoKTtcbiAgfVxuICBzZXREaW1lbnNpb25zKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBpZiAobWUuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgIG1lLndpZHRoID0gbWUubWF4V2lkdGg7XG4gICAgICBtZS5sZWZ0ID0gbWUuX21hcmdpbnMubGVmdDtcbiAgICAgIG1lLnJpZ2h0ID0gbWUud2lkdGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1lLmhlaWdodCA9IG1lLm1heEhlaWdodDtcbiAgICAgIG1lLnRvcCA9IG1lLl9tYXJnaW5zLnRvcDtcbiAgICAgIG1lLmJvdHRvbSA9IG1lLmhlaWdodDtcbiAgICB9XG4gIH1cbiAgYnVpbGRMYWJlbHMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGxhYmVsT3B0cyA9IG1lLm9wdGlvbnMubGFiZWxzIHx8IHt9O1xuICAgIGxldCBsZWdlbmRJdGVtcyA9IGNhbGxiYWNrKGxhYmVsT3B0cy5nZW5lcmF0ZUxhYmVscywgW21lLmNoYXJ0XSwgbWUpIHx8IFtdO1xuICAgIGlmIChsYWJlbE9wdHMuZmlsdGVyKSB7XG4gICAgICBsZWdlbmRJdGVtcyA9IGxlZ2VuZEl0ZW1zLmZpbHRlcigoaXRlbSkgPT4gbGFiZWxPcHRzLmZpbHRlcihpdGVtLCBtZS5jaGFydC5kYXRhKSk7XG4gICAgfVxuICAgIGlmIChsYWJlbE9wdHMuc29ydCkge1xuICAgICAgbGVnZW5kSXRlbXMgPSBsZWdlbmRJdGVtcy5zb3J0KChhLCBiKSA9PiBsYWJlbE9wdHMuc29ydChhLCBiLCBtZS5jaGFydC5kYXRhKSk7XG4gICAgfVxuICAgIGlmIChtZS5vcHRpb25zLnJldmVyc2UpIHtcbiAgICAgIGxlZ2VuZEl0ZW1zLnJldmVyc2UoKTtcbiAgICB9XG4gICAgbWUubGVnZW5kSXRlbXMgPSBsZWdlbmRJdGVtcztcbiAgfVxuICBmaXQoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtvcHRpb25zLCBjdHh9ID0gbWU7XG4gICAgaWYgKCFvcHRpb25zLmRpc3BsYXkpIHtcbiAgICAgIG1lLndpZHRoID0gbWUuaGVpZ2h0ID0gMDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbGFiZWxPcHRzID0gb3B0aW9ucy5sYWJlbHM7XG4gICAgY29uc3QgbGFiZWxGb250ID0gdG9Gb250KGxhYmVsT3B0cy5mb250KTtcbiAgICBjb25zdCBmb250U2l6ZSA9IGxhYmVsRm9udC5zaXplO1xuICAgIGNvbnN0IHRpdGxlSGVpZ2h0ID0gbWUuX2NvbXB1dGVUaXRsZUhlaWdodCgpO1xuICAgIGNvbnN0IHtib3hXaWR0aCwgaXRlbUhlaWdodH0gPSBnZXRCb3hTaXplKGxhYmVsT3B0cywgZm9udFNpemUpO1xuICAgIGxldCB3aWR0aCwgaGVpZ2h0O1xuICAgIGN0eC5mb250ID0gbGFiZWxGb250LnN0cmluZztcbiAgICBpZiAobWUuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgIHdpZHRoID0gbWUubWF4V2lkdGg7XG4gICAgICBoZWlnaHQgPSBtZS5fZml0Um93cyh0aXRsZUhlaWdodCwgZm9udFNpemUsIGJveFdpZHRoLCBpdGVtSGVpZ2h0KSArIDEwO1xuICAgIH0gZWxzZSB7XG4gICAgICBoZWlnaHQgPSBtZS5tYXhIZWlnaHQ7XG4gICAgICB3aWR0aCA9IG1lLl9maXRDb2xzKHRpdGxlSGVpZ2h0LCBmb250U2l6ZSwgYm94V2lkdGgsIGl0ZW1IZWlnaHQpICsgMTA7XG4gICAgfVxuICAgIG1lLndpZHRoID0gTWF0aC5taW4od2lkdGgsIG9wdGlvbnMubWF4V2lkdGggfHwgbWUubWF4V2lkdGgpO1xuICAgIG1lLmhlaWdodCA9IE1hdGgubWluKGhlaWdodCwgb3B0aW9ucy5tYXhIZWlnaHQgfHwgbWUubWF4SGVpZ2h0KTtcbiAgfVxuICBfZml0Um93cyh0aXRsZUhlaWdodCwgZm9udFNpemUsIGJveFdpZHRoLCBpdGVtSGVpZ2h0KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtjdHgsIG1heFdpZHRoLCBvcHRpb25zOiB7bGFiZWxzOiB7cGFkZGluZ319fSA9IG1lO1xuICAgIGNvbnN0IGhpdGJveGVzID0gbWUubGVnZW5kSGl0Qm94ZXMgPSBbXTtcbiAgICBjb25zdCBsaW5lV2lkdGhzID0gbWUubGluZVdpZHRocyA9IFswXTtcbiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gaXRlbUhlaWdodCArIHBhZGRpbmc7XG4gICAgbGV0IHRvdGFsSGVpZ2h0ID0gdGl0bGVIZWlnaHQ7XG4gICAgY3R4LnRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICBjdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgbGV0IHJvdyA9IC0xO1xuICAgIGxldCB0b3AgPSAtbGluZUhlaWdodDtcbiAgICBtZS5sZWdlbmRJdGVtcy5mb3JFYWNoKChsZWdlbmRJdGVtLCBpKSA9PiB7XG4gICAgICBjb25zdCBpdGVtV2lkdGggPSBib3hXaWR0aCArIChmb250U2l6ZSAvIDIpICsgY3R4Lm1lYXN1cmVUZXh0KGxlZ2VuZEl0ZW0udGV4dCkud2lkdGg7XG4gICAgICBpZiAoaSA9PT0gMCB8fCBsaW5lV2lkdGhzW2xpbmVXaWR0aHMubGVuZ3RoIC0gMV0gKyBpdGVtV2lkdGggKyAyICogcGFkZGluZyA+IG1heFdpZHRoKSB7XG4gICAgICAgIHRvdGFsSGVpZ2h0ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgIGxpbmVXaWR0aHNbbGluZVdpZHRocy5sZW5ndGggLSAoaSA+IDAgPyAwIDogMSldID0gMDtcbiAgICAgICAgdG9wICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgIHJvdysrO1xuICAgICAgfVxuICAgICAgaGl0Ym94ZXNbaV0gPSB7bGVmdDogMCwgdG9wLCByb3csIHdpZHRoOiBpdGVtV2lkdGgsIGhlaWdodDogaXRlbUhlaWdodH07XG4gICAgICBsaW5lV2lkdGhzW2xpbmVXaWR0aHMubGVuZ3RoIC0gMV0gKz0gaXRlbVdpZHRoICsgcGFkZGluZztcbiAgICB9KTtcbiAgICByZXR1cm4gdG90YWxIZWlnaHQ7XG4gIH1cbiAgX2ZpdENvbHModGl0bGVIZWlnaHQsIGZvbnRTaXplLCBib3hXaWR0aCwgaXRlbUhlaWdodCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB7Y3R4LCBtYXhIZWlnaHQsIG9wdGlvbnM6IHtsYWJlbHM6IHtwYWRkaW5nfX19ID0gbWU7XG4gICAgY29uc3QgaGl0Ym94ZXMgPSBtZS5sZWdlbmRIaXRCb3hlcyA9IFtdO1xuICAgIGNvbnN0IGNvbHVtblNpemVzID0gbWUuY29sdW1uU2l6ZXMgPSBbXTtcbiAgICBjb25zdCBoZWlnaHRMaW1pdCA9IG1heEhlaWdodCAtIHRpdGxlSGVpZ2h0O1xuICAgIGxldCB0b3RhbFdpZHRoID0gcGFkZGluZztcbiAgICBsZXQgY3VycmVudENvbFdpZHRoID0gMDtcbiAgICBsZXQgY3VycmVudENvbEhlaWdodCA9IDA7XG4gICAgbGV0IGxlZnQgPSAwO1xuICAgIGxldCBjb2wgPSAwO1xuICAgIG1lLmxlZ2VuZEl0ZW1zLmZvckVhY2goKGxlZ2VuZEl0ZW0sIGkpID0+IHtcbiAgICAgIGNvbnN0IGl0ZW1XaWR0aCA9IGJveFdpZHRoICsgKGZvbnRTaXplIC8gMikgKyBjdHgubWVhc3VyZVRleHQobGVnZW5kSXRlbS50ZXh0KS53aWR0aDtcbiAgICAgIGlmIChpID4gMCAmJiBjdXJyZW50Q29sSGVpZ2h0ICsgaXRlbUhlaWdodCArIDIgKiBwYWRkaW5nID4gaGVpZ2h0TGltaXQpIHtcbiAgICAgICAgdG90YWxXaWR0aCArPSBjdXJyZW50Q29sV2lkdGggKyBwYWRkaW5nO1xuICAgICAgICBjb2x1bW5TaXplcy5wdXNoKHt3aWR0aDogY3VycmVudENvbFdpZHRoLCBoZWlnaHQ6IGN1cnJlbnRDb2xIZWlnaHR9KTtcbiAgICAgICAgbGVmdCArPSBjdXJyZW50Q29sV2lkdGggKyBwYWRkaW5nO1xuICAgICAgICBjb2wrKztcbiAgICAgICAgY3VycmVudENvbFdpZHRoID0gY3VycmVudENvbEhlaWdodCA9IDA7XG4gICAgICB9XG4gICAgICBoaXRib3hlc1tpXSA9IHtsZWZ0LCB0b3A6IGN1cnJlbnRDb2xIZWlnaHQsIGNvbCwgd2lkdGg6IGl0ZW1XaWR0aCwgaGVpZ2h0OiBpdGVtSGVpZ2h0fTtcbiAgICAgIGN1cnJlbnRDb2xXaWR0aCA9IE1hdGgubWF4KGN1cnJlbnRDb2xXaWR0aCwgaXRlbVdpZHRoKTtcbiAgICAgIGN1cnJlbnRDb2xIZWlnaHQgKz0gaXRlbUhlaWdodCArIHBhZGRpbmc7XG4gICAgfSk7XG4gICAgdG90YWxXaWR0aCArPSBjdXJyZW50Q29sV2lkdGg7XG4gICAgY29sdW1uU2l6ZXMucHVzaCh7d2lkdGg6IGN1cnJlbnRDb2xXaWR0aCwgaGVpZ2h0OiBjdXJyZW50Q29sSGVpZ2h0fSk7XG4gICAgcmV0dXJuIHRvdGFsV2lkdGg7XG4gIH1cbiAgYWRqdXN0SGl0Qm94ZXMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGlmICghbWUub3B0aW9ucy5kaXNwbGF5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHRpdGxlSGVpZ2h0ID0gbWUuX2NvbXB1dGVUaXRsZUhlaWdodCgpO1xuICAgIGNvbnN0IHtsZWdlbmRIaXRCb3hlczogaGl0Ym94ZXMsIG9wdGlvbnM6IHthbGlnbiwgbGFiZWxzOiB7cGFkZGluZ30sIHJ0bH19ID0gbWU7XG4gICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihydGwsIG1lLmxlZnQsIG1lLndpZHRoKTtcbiAgICBpZiAodGhpcy5pc0hvcml6b250YWwoKSkge1xuICAgICAgbGV0IHJvdyA9IDA7XG4gICAgICBsZXQgbGVmdCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBtZS5sZWZ0ICsgcGFkZGluZywgbWUucmlnaHQgLSBtZS5saW5lV2lkdGhzW3Jvd10pO1xuICAgICAgZm9yIChjb25zdCBoaXRib3ggb2YgaGl0Ym94ZXMpIHtcbiAgICAgICAgaWYgKHJvdyAhPT0gaGl0Ym94LnJvdykge1xuICAgICAgICAgIHJvdyA9IGhpdGJveC5yb3c7XG4gICAgICAgICAgbGVmdCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBtZS5sZWZ0ICsgcGFkZGluZywgbWUucmlnaHQgLSBtZS5saW5lV2lkdGhzW3Jvd10pO1xuICAgICAgICB9XG4gICAgICAgIGhpdGJveC50b3AgKz0gbWUudG9wICsgdGl0bGVIZWlnaHQgKyBwYWRkaW5nO1xuICAgICAgICBoaXRib3gubGVmdCA9IHJ0bEhlbHBlci5sZWZ0Rm9yTHRyKHJ0bEhlbHBlci54KGxlZnQpLCBoaXRib3gud2lkdGgpO1xuICAgICAgICBsZWZ0ICs9IGhpdGJveC53aWR0aCArIHBhZGRpbmc7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBjb2wgPSAwO1xuICAgICAgbGV0IHRvcCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBtZS50b3AgKyB0aXRsZUhlaWdodCArIHBhZGRpbmcsIG1lLmJvdHRvbSAtIG1lLmNvbHVtblNpemVzW2NvbF0uaGVpZ2h0KTtcbiAgICAgIGZvciAoY29uc3QgaGl0Ym94IG9mIGhpdGJveGVzKSB7XG4gICAgICAgIGlmIChoaXRib3guY29sICE9PSBjb2wpIHtcbiAgICAgICAgICBjb2wgPSBoaXRib3guY29sO1xuICAgICAgICAgIHRvcCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBtZS50b3AgKyB0aXRsZUhlaWdodCArIHBhZGRpbmcsIG1lLmJvdHRvbSAtIG1lLmNvbHVtblNpemVzW2NvbF0uaGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICBoaXRib3gudG9wID0gdG9wO1xuICAgICAgICBoaXRib3gubGVmdCArPSBtZS5sZWZ0ICsgcGFkZGluZztcbiAgICAgICAgaGl0Ym94LmxlZnQgPSBydGxIZWxwZXIubGVmdEZvckx0cihydGxIZWxwZXIueChoaXRib3gubGVmdCksIGhpdGJveC53aWR0aCk7XG4gICAgICAgIHRvcCArPSBoaXRib3guaGVpZ2h0ICsgcGFkZGluZztcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgaXNIb3Jpem9udGFsKCkge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMucG9zaXRpb24gPT09ICd0b3AnIHx8IHRoaXMub3B0aW9ucy5wb3NpdGlvbiA9PT0gJ2JvdHRvbSc7XG4gIH1cbiAgZHJhdygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgaWYgKG1lLm9wdGlvbnMuZGlzcGxheSkge1xuICAgICAgY29uc3QgY3R4ID0gbWUuY3R4O1xuICAgICAgY2xpcEFyZWEoY3R4LCBtZSk7XG4gICAgICBtZS5fZHJhdygpO1xuICAgICAgdW5jbGlwQXJlYShjdHgpO1xuICAgIH1cbiAgfVxuICBfZHJhdygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge29wdGlvbnM6IG9wdHMsIGNvbHVtblNpemVzLCBsaW5lV2lkdGhzLCBjdHh9ID0gbWU7XG4gICAgY29uc3Qge2FsaWduLCBsYWJlbHM6IGxhYmVsT3B0c30gPSBvcHRzO1xuICAgIGNvbnN0IGRlZmF1bHRDb2xvciA9IGRlZmF1bHRzLmNvbG9yO1xuICAgIGNvbnN0IHJ0bEhlbHBlciA9IGdldFJ0bEFkYXB0ZXIob3B0cy5ydGwsIG1lLmxlZnQsIG1lLndpZHRoKTtcbiAgICBjb25zdCBsYWJlbEZvbnQgPSB0b0ZvbnQobGFiZWxPcHRzLmZvbnQpO1xuICAgIGNvbnN0IHtjb2xvcjogZm9udENvbG9yLCBwYWRkaW5nfSA9IGxhYmVsT3B0cztcbiAgICBjb25zdCBmb250U2l6ZSA9IGxhYmVsRm9udC5zaXplO1xuICAgIGNvbnN0IGhhbGZGb250U2l6ZSA9IGZvbnRTaXplIC8gMjtcbiAgICBsZXQgY3Vyc29yO1xuICAgIG1lLmRyYXdUaXRsZSgpO1xuICAgIGN0eC50ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKCdsZWZ0Jyk7XG4gICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgIGN0eC5saW5lV2lkdGggPSAwLjU7XG4gICAgY3R4LmZvbnQgPSBsYWJlbEZvbnQuc3RyaW5nO1xuICAgIGNvbnN0IHtib3hXaWR0aCwgYm94SGVpZ2h0LCBpdGVtSGVpZ2h0fSA9IGdldEJveFNpemUobGFiZWxPcHRzLCBmb250U2l6ZSk7XG4gICAgY29uc3QgZHJhd0xlZ2VuZEJveCA9IGZ1bmN0aW9uKHgsIHksIGxlZ2VuZEl0ZW0pIHtcbiAgICAgIGlmIChpc05hTihib3hXaWR0aCkgfHwgYm94V2lkdGggPD0gMCB8fCBpc05hTihib3hIZWlnaHQpIHx8IGJveEhlaWdodCA8IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY3R4LnNhdmUoKTtcbiAgICAgIGNvbnN0IGxpbmVXaWR0aCA9IHZhbHVlT3JEZWZhdWx0KGxlZ2VuZEl0ZW0ubGluZVdpZHRoLCAxKTtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLmZpbGxTdHlsZSwgZGVmYXVsdENvbG9yKTtcbiAgICAgIGN0eC5saW5lQ2FwID0gdmFsdWVPckRlZmF1bHQobGVnZW5kSXRlbS5saW5lQ2FwLCAnYnV0dCcpO1xuICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gdmFsdWVPckRlZmF1bHQobGVnZW5kSXRlbS5saW5lRGFzaE9mZnNldCwgMCk7XG4gICAgICBjdHgubGluZUpvaW4gPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLmxpbmVKb2luLCAnbWl0ZXInKTtcbiAgICAgIGN0eC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgICBjdHguc3Ryb2tlU3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLnN0cm9rZVN0eWxlLCBkZWZhdWx0Q29sb3IpO1xuICAgICAgY3R4LnNldExpbmVEYXNoKHZhbHVlT3JEZWZhdWx0KGxlZ2VuZEl0ZW0ubGluZURhc2gsIFtdKSk7XG4gICAgICBpZiAobGFiZWxPcHRzLnVzZVBvaW50U3R5bGUpIHtcbiAgICAgICAgY29uc3QgZHJhd09wdGlvbnMgPSB7XG4gICAgICAgICAgcmFkaXVzOiBib3hXaWR0aCAqIE1hdGguU1FSVDIgLyAyLFxuICAgICAgICAgIHBvaW50U3R5bGU6IGxlZ2VuZEl0ZW0ucG9pbnRTdHlsZSxcbiAgICAgICAgICByb3RhdGlvbjogbGVnZW5kSXRlbS5yb3RhdGlvbixcbiAgICAgICAgICBib3JkZXJXaWR0aDogbGluZVdpZHRoXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGNlbnRlclggPSBydGxIZWxwZXIueFBsdXMoeCwgYm94V2lkdGggLyAyKTtcbiAgICAgICAgY29uc3QgY2VudGVyWSA9IHkgKyBoYWxmRm9udFNpemU7XG4gICAgICAgIGRyYXdQb2ludChjdHgsIGRyYXdPcHRpb25zLCBjZW50ZXJYLCBjZW50ZXJZKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHlCb3hUb3AgPSB5ICsgTWF0aC5tYXgoKGZvbnRTaXplIC0gYm94SGVpZ2h0KSAvIDIsIDApO1xuICAgICAgICBjb25zdCB4Qm94TGVmdCA9IHJ0bEhlbHBlci5sZWZ0Rm9yTHRyKHgsIGJveFdpZHRoKTtcbiAgICAgICAgY29uc3QgYm9yZGVyUmFkaXVzID0gdG9UUkJMQ29ybmVycyhsZWdlbmRJdGVtLmJvcmRlclJhZGl1cyk7XG4gICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgaWYgKE9iamVjdC52YWx1ZXMoYm9yZGVyUmFkaXVzKS5zb21lKHYgPT4gdiAhPT0gMCkpIHtcbiAgICAgICAgICBhZGRSb3VuZGVkUmVjdFBhdGgoY3R4LCB7XG4gICAgICAgICAgICB4OiB4Qm94TGVmdCxcbiAgICAgICAgICAgIHk6IHlCb3hUb3AsXG4gICAgICAgICAgICB3OiBib3hXaWR0aCxcbiAgICAgICAgICAgIGg6IGJveEhlaWdodCxcbiAgICAgICAgICAgIHJhZGl1czogYm9yZGVyUmFkaXVzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGN0eC5yZWN0KHhCb3hMZWZ0LCB5Qm94VG9wLCBib3hXaWR0aCwgYm94SGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICBpZiAobGluZVdpZHRoICE9PSAwKSB7XG4gICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH07XG4gICAgY29uc3QgZmlsbFRleHQgPSBmdW5jdGlvbih4LCB5LCBsZWdlbmRJdGVtKSB7XG4gICAgICByZW5kZXJUZXh0KGN0eCwgbGVnZW5kSXRlbS50ZXh0LCB4LCB5ICsgKGl0ZW1IZWlnaHQgLyAyKSwgbGFiZWxGb250LCB7XG4gICAgICAgIHN0cmlrZXRocm91Z2g6IGxlZ2VuZEl0ZW0uaGlkZGVuLFxuICAgICAgICB0ZXh0QWxpZ246IHJ0bEhlbHBlci50ZXh0QWxpZ24obGVnZW5kSXRlbS50ZXh0QWxpZ24pXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IGlzSG9yaXpvbnRhbCA9IG1lLmlzSG9yaXpvbnRhbCgpO1xuICAgIGNvbnN0IHRpdGxlSGVpZ2h0ID0gdGhpcy5fY29tcHV0ZVRpdGxlSGVpZ2h0KCk7XG4gICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgY3Vyc29yID0ge1xuICAgICAgICB4OiBfYWxpZ25TdGFydEVuZChhbGlnbiwgbWUubGVmdCArIHBhZGRpbmcsIG1lLnJpZ2h0IC0gbGluZVdpZHRoc1swXSksXG4gICAgICAgIHk6IG1lLnRvcCArIHBhZGRpbmcgKyB0aXRsZUhlaWdodCxcbiAgICAgICAgbGluZTogMFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3Vyc29yID0ge1xuICAgICAgICB4OiBtZS5sZWZ0ICsgcGFkZGluZyxcbiAgICAgICAgeTogX2FsaWduU3RhcnRFbmQoYWxpZ24sIG1lLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZywgbWUuYm90dG9tIC0gY29sdW1uU2l6ZXNbMF0uaGVpZ2h0KSxcbiAgICAgICAgbGluZTogMFxuICAgICAgfTtcbiAgICB9XG4gICAgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uKG1lLmN0eCwgb3B0cy50ZXh0RGlyZWN0aW9uKTtcbiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gaXRlbUhlaWdodCArIHBhZGRpbmc7XG4gICAgbWUubGVnZW5kSXRlbXMuZm9yRWFjaCgobGVnZW5kSXRlbSwgaSkgPT4ge1xuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gbGVnZW5kSXRlbS5mb250Q29sb3IgfHwgZm9udENvbG9yO1xuICAgICAgY3R4LmZpbGxTdHlsZSA9IGxlZ2VuZEl0ZW0uZm9udENvbG9yIHx8IGZvbnRDb2xvcjtcbiAgICAgIGNvbnN0IHRleHRXaWR0aCA9IGN0eC5tZWFzdXJlVGV4dChsZWdlbmRJdGVtLnRleHQpLndpZHRoO1xuICAgICAgY29uc3QgdGV4dEFsaWduID0gcnRsSGVscGVyLnRleHRBbGlnbihsZWdlbmRJdGVtLnRleHRBbGlnbiB8fCAobGVnZW5kSXRlbS50ZXh0QWxpZ24gPSBsYWJlbE9wdHMudGV4dEFsaWduKSk7XG4gICAgICBjb25zdCB3aWR0aCA9IGJveFdpZHRoICsgaGFsZkZvbnRTaXplICsgdGV4dFdpZHRoO1xuICAgICAgbGV0IHggPSBjdXJzb3IueDtcbiAgICAgIGxldCB5ID0gY3Vyc29yLnk7XG4gICAgICBydGxIZWxwZXIuc2V0V2lkdGgobWUud2lkdGgpO1xuICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICBpZiAoaSA+IDAgJiYgeCArIHdpZHRoICsgcGFkZGluZyA+IG1lLnJpZ2h0KSB7XG4gICAgICAgICAgeSA9IGN1cnNvci55ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgY3Vyc29yLmxpbmUrKztcbiAgICAgICAgICB4ID0gY3Vyc29yLnggPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgbWUubGVmdCArIHBhZGRpbmcsIG1lLnJpZ2h0IC0gbGluZVdpZHRoc1tjdXJzb3IubGluZV0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGkgPiAwICYmIHkgKyBsaW5lSGVpZ2h0ID4gbWUuYm90dG9tKSB7XG4gICAgICAgIHggPSBjdXJzb3IueCA9IHggKyBjb2x1bW5TaXplc1tjdXJzb3IubGluZV0ud2lkdGggKyBwYWRkaW5nO1xuICAgICAgICBjdXJzb3IubGluZSsrO1xuICAgICAgICB5ID0gY3Vyc29yLnkgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgbWUudG9wICsgdGl0bGVIZWlnaHQgKyBwYWRkaW5nLCBtZS5ib3R0b20gLSBjb2x1bW5TaXplc1tjdXJzb3IubGluZV0uaGVpZ2h0KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlYWxYID0gcnRsSGVscGVyLngoeCk7XG4gICAgICBkcmF3TGVnZW5kQm94KHJlYWxYLCB5LCBsZWdlbmRJdGVtKTtcbiAgICAgIHggPSBfdGV4dFgodGV4dEFsaWduLCB4ICsgYm94V2lkdGggKyBoYWxmRm9udFNpemUsIGlzSG9yaXpvbnRhbCA/IHggKyB3aWR0aCA6IG1lLnJpZ2h0LCBvcHRzLnJ0bCk7XG4gICAgICBmaWxsVGV4dChydGxIZWxwZXIueCh4KSwgeSwgbGVnZW5kSXRlbSk7XG4gICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgIGN1cnNvci54ICs9IHdpZHRoICsgcGFkZGluZztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGN1cnNvci55ICs9IGxpbmVIZWlnaHQ7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmVzdG9yZVRleHREaXJlY3Rpb24obWUuY3R4LCBvcHRzLnRleHREaXJlY3Rpb24pO1xuICB9XG4gIGRyYXdUaXRsZSgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qgb3B0cyA9IG1lLm9wdGlvbnM7XG4gICAgY29uc3QgdGl0bGVPcHRzID0gb3B0cy50aXRsZTtcbiAgICBjb25zdCB0aXRsZUZvbnQgPSB0b0ZvbnQodGl0bGVPcHRzLmZvbnQpO1xuICAgIGNvbnN0IHRpdGxlUGFkZGluZyA9IHRvUGFkZGluZyh0aXRsZU9wdHMucGFkZGluZyk7XG4gICAgaWYgKCF0aXRsZU9wdHMuZGlzcGxheSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBydGxIZWxwZXIgPSBnZXRSdGxBZGFwdGVyKG9wdHMucnRsLCBtZS5sZWZ0LCBtZS53aWR0aCk7XG4gICAgY29uc3QgY3R4ID0gbWUuY3R4O1xuICAgIGNvbnN0IHBvc2l0aW9uID0gdGl0bGVPcHRzLnBvc2l0aW9uO1xuICAgIGNvbnN0IGhhbGZGb250U2l6ZSA9IHRpdGxlRm9udC5zaXplIC8gMjtcbiAgICBjb25zdCB0b3BQYWRkaW5nUGx1c0hhbGZGb250U2l6ZSA9IHRpdGxlUGFkZGluZy50b3AgKyBoYWxmRm9udFNpemU7XG4gICAgbGV0IHk7XG4gICAgbGV0IGxlZnQgPSBtZS5sZWZ0O1xuICAgIGxldCBtYXhXaWR0aCA9IG1lLndpZHRoO1xuICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICBtYXhXaWR0aCA9IE1hdGgubWF4KC4uLm1lLmxpbmVXaWR0aHMpO1xuICAgICAgeSA9IG1lLnRvcCArIHRvcFBhZGRpbmdQbHVzSGFsZkZvbnRTaXplO1xuICAgICAgbGVmdCA9IF9hbGlnblN0YXJ0RW5kKG9wdHMuYWxpZ24sIGxlZnQsIG1lLnJpZ2h0IC0gbWF4V2lkdGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBtYXhIZWlnaHQgPSBtZS5jb2x1bW5TaXplcy5yZWR1Y2UoKGFjYywgc2l6ZSkgPT4gTWF0aC5tYXgoYWNjLCBzaXplLmhlaWdodCksIDApO1xuICAgICAgeSA9IHRvcFBhZGRpbmdQbHVzSGFsZkZvbnRTaXplICsgX2FsaWduU3RhcnRFbmQob3B0cy5hbGlnbiwgbWUudG9wLCBtZS5ib3R0b20gLSBtYXhIZWlnaHQgLSBvcHRzLmxhYmVscy5wYWRkaW5nIC0gbWUuX2NvbXB1dGVUaXRsZUhlaWdodCgpKTtcbiAgICB9XG4gICAgY29uc3QgeCA9IF9hbGlnblN0YXJ0RW5kKHBvc2l0aW9uLCBsZWZ0LCBsZWZ0ICsgbWF4V2lkdGgpO1xuICAgIGN0eC50ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKF90b0xlZnRSaWdodENlbnRlcihwb3NpdGlvbikpO1xuICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICBjdHguc3Ryb2tlU3R5bGUgPSB0aXRsZU9wdHMuY29sb3I7XG4gICAgY3R4LmZpbGxTdHlsZSA9IHRpdGxlT3B0cy5jb2xvcjtcbiAgICBjdHguZm9udCA9IHRpdGxlRm9udC5zdHJpbmc7XG4gICAgcmVuZGVyVGV4dChjdHgsIHRpdGxlT3B0cy50ZXh0LCB4LCB5LCB0aXRsZUZvbnQpO1xuICB9XG4gIF9jb21wdXRlVGl0bGVIZWlnaHQoKSB7XG4gICAgY29uc3QgdGl0bGVPcHRzID0gdGhpcy5vcHRpb25zLnRpdGxlO1xuICAgIGNvbnN0IHRpdGxlRm9udCA9IHRvRm9udCh0aXRsZU9wdHMuZm9udCk7XG4gICAgY29uc3QgdGl0bGVQYWRkaW5nID0gdG9QYWRkaW5nKHRpdGxlT3B0cy5wYWRkaW5nKTtcbiAgICByZXR1cm4gdGl0bGVPcHRzLmRpc3BsYXkgPyB0aXRsZUZvbnQubGluZUhlaWdodCArIHRpdGxlUGFkZGluZy5oZWlnaHQgOiAwO1xuICB9XG4gIF9nZXRMZWdlbmRJdGVtQXQoeCwgeSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBsZXQgaSwgaGl0Qm94LCBsaDtcbiAgICBpZiAoeCA+PSBtZS5sZWZ0ICYmIHggPD0gbWUucmlnaHQgJiYgeSA+PSBtZS50b3AgJiYgeSA8PSBtZS5ib3R0b20pIHtcbiAgICAgIGxoID0gbWUubGVnZW5kSGl0Qm94ZXM7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGgubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaGl0Qm94ID0gbGhbaV07XG4gICAgICAgIGlmICh4ID49IGhpdEJveC5sZWZ0ICYmIHggPD0gaGl0Qm94LmxlZnQgKyBoaXRCb3gud2lkdGggJiYgeSA+PSBoaXRCb3gudG9wICYmIHkgPD0gaGl0Qm94LnRvcCArIGhpdEJveC5oZWlnaHQpIHtcbiAgICAgICAgICByZXR1cm4gbWUubGVnZW5kSXRlbXNbaV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgaGFuZGxlRXZlbnQoZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRzID0gbWUub3B0aW9ucztcbiAgICBpZiAoIWlzTGlzdGVuZWQoZS50eXBlLCBvcHRzKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBob3ZlcmVkSXRlbSA9IG1lLl9nZXRMZWdlbmRJdGVtQXQoZS54LCBlLnkpO1xuICAgIGlmIChlLnR5cGUgPT09ICdtb3VzZW1vdmUnKSB7XG4gICAgICBjb25zdCBwcmV2aW91cyA9IG1lLl9ob3ZlcmVkSXRlbTtcbiAgICAgIGNvbnN0IHNhbWVJdGVtID0gaXRlbXNFcXVhbChwcmV2aW91cywgaG92ZXJlZEl0ZW0pO1xuICAgICAgaWYgKHByZXZpb3VzICYmICFzYW1lSXRlbSkge1xuICAgICAgICBjYWxsYmFjayhvcHRzLm9uTGVhdmUsIFtlLCBwcmV2aW91cywgbWVdLCBtZSk7XG4gICAgICB9XG4gICAgICBtZS5faG92ZXJlZEl0ZW0gPSBob3ZlcmVkSXRlbTtcbiAgICAgIGlmIChob3ZlcmVkSXRlbSAmJiAhc2FtZUl0ZW0pIHtcbiAgICAgICAgY2FsbGJhY2sob3B0cy5vbkhvdmVyLCBbZSwgaG92ZXJlZEl0ZW0sIG1lXSwgbWUpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoaG92ZXJlZEl0ZW0pIHtcbiAgICAgIGNhbGxiYWNrKG9wdHMub25DbGljaywgW2UsIGhvdmVyZWRJdGVtLCBtZV0sIG1lKTtcbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uIGlzTGlzdGVuZWQodHlwZSwgb3B0cykge1xuICBpZiAodHlwZSA9PT0gJ21vdXNlbW92ZScgJiYgKG9wdHMub25Ib3ZlciB8fCBvcHRzLm9uTGVhdmUpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKG9wdHMub25DbGljayAmJiAodHlwZSA9PT0gJ2NsaWNrJyB8fCB0eXBlID09PSAnbW91c2V1cCcpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxudmFyIHBsdWdpbl9sZWdlbmQgPSB7XG4gIGlkOiAnbGVnZW5kJyxcbiAgX2VsZW1lbnQ6IExlZ2VuZCxcbiAgc3RhcnQoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgY29uc3QgbGVnZW5kID0gY2hhcnQubGVnZW5kID0gbmV3IExlZ2VuZCh7Y3R4OiBjaGFydC5jdHgsIG9wdGlvbnMsIGNoYXJ0fSk7XG4gICAgbGF5b3V0cy5jb25maWd1cmUoY2hhcnQsIGxlZ2VuZCwgb3B0aW9ucyk7XG4gICAgbGF5b3V0cy5hZGRCb3goY2hhcnQsIGxlZ2VuZCk7XG4gIH0sXG4gIHN0b3AoY2hhcnQpIHtcbiAgICBsYXlvdXRzLnJlbW92ZUJveChjaGFydCwgY2hhcnQubGVnZW5kKTtcbiAgICBkZWxldGUgY2hhcnQubGVnZW5kO1xuICB9LFxuICBiZWZvcmVVcGRhdGUoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgY29uc3QgbGVnZW5kID0gY2hhcnQubGVnZW5kO1xuICAgIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCBsZWdlbmQsIG9wdGlvbnMpO1xuICAgIGxlZ2VuZC5vcHRpb25zID0gb3B0aW9ucztcbiAgfSxcbiAgYWZ0ZXJVcGRhdGUoY2hhcnQpIHtcbiAgICBjb25zdCBsZWdlbmQgPSBjaGFydC5sZWdlbmQ7XG4gICAgbGVnZW5kLmJ1aWxkTGFiZWxzKCk7XG4gICAgbGVnZW5kLmFkanVzdEhpdEJveGVzKCk7XG4gIH0sXG4gIGFmdGVyRXZlbnQoY2hhcnQsIGFyZ3MpIHtcbiAgICBpZiAoIWFyZ3MucmVwbGF5KSB7XG4gICAgICBjaGFydC5sZWdlbmQuaGFuZGxlRXZlbnQoYXJncy5ldmVudCk7XG4gICAgfVxuICB9LFxuICBkZWZhdWx0czoge1xuICAgIGRpc3BsYXk6IHRydWUsXG4gICAgcG9zaXRpb246ICd0b3AnLFxuICAgIGFsaWduOiAnY2VudGVyJyxcbiAgICBmdWxsU2l6ZTogdHJ1ZSxcbiAgICByZXZlcnNlOiBmYWxzZSxcbiAgICB3ZWlnaHQ6IDEwMDAsXG4gICAgb25DbGljayhlLCBsZWdlbmRJdGVtLCBsZWdlbmQpIHtcbiAgICAgIGNvbnN0IGluZGV4ID0gbGVnZW5kSXRlbS5kYXRhc2V0SW5kZXg7XG4gICAgICBjb25zdCBjaSA9IGxlZ2VuZC5jaGFydDtcbiAgICAgIGlmIChjaS5pc0RhdGFzZXRWaXNpYmxlKGluZGV4KSkge1xuICAgICAgICBjaS5oaWRlKGluZGV4KTtcbiAgICAgICAgbGVnZW5kSXRlbS5oaWRkZW4gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2kuc2hvdyhpbmRleCk7XG4gICAgICAgIGxlZ2VuZEl0ZW0uaGlkZGVuID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSxcbiAgICBvbkhvdmVyOiBudWxsLFxuICAgIG9uTGVhdmU6IG51bGwsXG4gICAgbGFiZWxzOiB7XG4gICAgICBjb2xvcjogKGN0eCkgPT4gY3R4LmNoYXJ0Lm9wdGlvbnMuY29sb3IsXG4gICAgICBib3hXaWR0aDogNDAsXG4gICAgICBwYWRkaW5nOiAxMCxcbiAgICAgIGdlbmVyYXRlTGFiZWxzKGNoYXJ0KSB7XG4gICAgICAgIGNvbnN0IGRhdGFzZXRzID0gY2hhcnQuZGF0YS5kYXRhc2V0cztcbiAgICAgICAgY29uc3Qge2xhYmVsczoge3VzZVBvaW50U3R5bGUsIHBvaW50U3R5bGUsIHRleHRBbGlnbiwgY29sb3J9fSA9IGNoYXJ0LmxlZ2VuZC5vcHRpb25zO1xuICAgICAgICByZXR1cm4gY2hhcnQuX2dldFNvcnRlZERhdGFzZXRNZXRhcygpLm1hcCgobWV0YSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHN0eWxlID0gbWV0YS5jb250cm9sbGVyLmdldFN0eWxlKHVzZVBvaW50U3R5bGUgPyAwIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICBjb25zdCBib3JkZXJXaWR0aCA9IHRvUGFkZGluZyhzdHlsZS5ib3JkZXJXaWR0aCk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRleHQ6IGRhdGFzZXRzW21ldGEuaW5kZXhdLmxhYmVsLFxuICAgICAgICAgICAgZmlsbFN0eWxlOiBzdHlsZS5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICBmb250Q29sb3I6IGNvbG9yLFxuICAgICAgICAgICAgaGlkZGVuOiAhbWV0YS52aXNpYmxlLFxuICAgICAgICAgICAgbGluZUNhcDogc3R5bGUuYm9yZGVyQ2FwU3R5bGUsXG4gICAgICAgICAgICBsaW5lRGFzaDogc3R5bGUuYm9yZGVyRGFzaCxcbiAgICAgICAgICAgIGxpbmVEYXNoT2Zmc2V0OiBzdHlsZS5ib3JkZXJEYXNoT2Zmc2V0LFxuICAgICAgICAgICAgbGluZUpvaW46IHN0eWxlLmJvcmRlckpvaW5TdHlsZSxcbiAgICAgICAgICAgIGxpbmVXaWR0aDogKGJvcmRlcldpZHRoLndpZHRoICsgYm9yZGVyV2lkdGguaGVpZ2h0KSAvIDQsXG4gICAgICAgICAgICBzdHJva2VTdHlsZTogc3R5bGUuYm9yZGVyQ29sb3IsXG4gICAgICAgICAgICBwb2ludFN0eWxlOiBwb2ludFN0eWxlIHx8IHN0eWxlLnBvaW50U3R5bGUsXG4gICAgICAgICAgICByb3RhdGlvbjogc3R5bGUucm90YXRpb24sXG4gICAgICAgICAgICB0ZXh0QWxpZ246IHRleHRBbGlnbiB8fCBzdHlsZS50ZXh0QWxpZ24sXG4gICAgICAgICAgICBib3JkZXJSYWRpdXM6IDAsXG4gICAgICAgICAgICBkYXRhc2V0SW5kZXg6IG1ldGEuaW5kZXhcbiAgICAgICAgICB9O1xuICAgICAgICB9LCB0aGlzKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHRpdGxlOiB7XG4gICAgICBjb2xvcjogKGN0eCkgPT4gY3R4LmNoYXJ0Lm9wdGlvbnMuY29sb3IsXG4gICAgICBkaXNwbGF5OiBmYWxzZSxcbiAgICAgIHBvc2l0aW9uOiAnY2VudGVyJyxcbiAgICAgIHRleHQ6ICcnLFxuICAgIH1cbiAgfSxcbiAgZGVzY3JpcHRvcnM6IHtcbiAgICBfc2NyaXB0YWJsZTogKG5hbWUpID0+ICFuYW1lLnN0YXJ0c1dpdGgoJ29uJyksXG4gICAgbGFiZWxzOiB7XG4gICAgICBfc2NyaXB0YWJsZTogKG5hbWUpID0+ICFbJ2dlbmVyYXRlTGFiZWxzJywgJ2ZpbHRlcicsICdzb3J0J10uaW5jbHVkZXMobmFtZSksXG4gICAgfVxuICB9LFxufTtcblxuY2xhc3MgVGl0bGUgZXh0ZW5kcyBFbGVtZW50IHtcbiAgY29uc3RydWN0b3IoY29uZmlnKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLmNoYXJ0ID0gY29uZmlnLmNoYXJ0O1xuICAgIHRoaXMub3B0aW9ucyA9IGNvbmZpZy5vcHRpb25zO1xuICAgIHRoaXMuY3R4ID0gY29uZmlnLmN0eDtcbiAgICB0aGlzLl9wYWRkaW5nID0gdW5kZWZpbmVkO1xuICAgIHRoaXMudG9wID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuYm90dG9tID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubGVmdCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnJpZ2h0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMud2lkdGggPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5oZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5wb3NpdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLndlaWdodCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmZ1bGxTaXplID0gdW5kZWZpbmVkO1xuICB9XG4gIHVwZGF0ZShtYXhXaWR0aCwgbWF4SGVpZ2h0KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdHMgPSBtZS5vcHRpb25zO1xuICAgIG1lLmxlZnQgPSAwO1xuICAgIG1lLnRvcCA9IDA7XG4gICAgaWYgKCFvcHRzLmRpc3BsYXkpIHtcbiAgICAgIG1lLndpZHRoID0gbWUuaGVpZ2h0ID0gbWUucmlnaHQgPSBtZS5ib3R0b20gPSAwO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBtZS53aWR0aCA9IG1lLnJpZ2h0ID0gbWF4V2lkdGg7XG4gICAgbWUuaGVpZ2h0ID0gbWUuYm90dG9tID0gbWF4SGVpZ2h0O1xuICAgIGNvbnN0IGxpbmVDb3VudCA9IGlzQXJyYXkob3B0cy50ZXh0KSA/IG9wdHMudGV4dC5sZW5ndGggOiAxO1xuICAgIG1lLl9wYWRkaW5nID0gdG9QYWRkaW5nKG9wdHMucGFkZGluZyk7XG4gICAgY29uc3QgdGV4dFNpemUgPSBsaW5lQ291bnQgKiB0b0ZvbnQob3B0cy5mb250KS5saW5lSGVpZ2h0ICsgbWUuX3BhZGRpbmcuaGVpZ2h0O1xuICAgIGlmIChtZS5pc0hvcml6b250YWwoKSkge1xuICAgICAgbWUuaGVpZ2h0ID0gdGV4dFNpemU7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1lLndpZHRoID0gdGV4dFNpemU7XG4gICAgfVxuICB9XG4gIGlzSG9yaXpvbnRhbCgpIHtcbiAgICBjb25zdCBwb3MgPSB0aGlzLm9wdGlvbnMucG9zaXRpb247XG4gICAgcmV0dXJuIHBvcyA9PT0gJ3RvcCcgfHwgcG9zID09PSAnYm90dG9tJztcbiAgfVxuICBfZHJhd0FyZ3Mob2Zmc2V0KSB7XG4gICAgY29uc3Qge3RvcCwgbGVmdCwgYm90dG9tLCByaWdodCwgb3B0aW9uc30gPSB0aGlzO1xuICAgIGNvbnN0IGFsaWduID0gb3B0aW9ucy5hbGlnbjtcbiAgICBsZXQgcm90YXRpb24gPSAwO1xuICAgIGxldCBtYXhXaWR0aCwgdGl0bGVYLCB0aXRsZVk7XG4gICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgIHRpdGxlWCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBsZWZ0LCByaWdodCk7XG4gICAgICB0aXRsZVkgPSB0b3AgKyBvZmZzZXQ7XG4gICAgICBtYXhXaWR0aCA9IHJpZ2h0IC0gbGVmdDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG9wdGlvbnMucG9zaXRpb24gPT09ICdsZWZ0Jykge1xuICAgICAgICB0aXRsZVggPSBsZWZ0ICsgb2Zmc2V0O1xuICAgICAgICB0aXRsZVkgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgYm90dG9tLCB0b3ApO1xuICAgICAgICByb3RhdGlvbiA9IFBJICogLTAuNTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpdGxlWCA9IHJpZ2h0IC0gb2Zmc2V0O1xuICAgICAgICB0aXRsZVkgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgdG9wLCBib3R0b20pO1xuICAgICAgICByb3RhdGlvbiA9IFBJICogMC41O1xuICAgICAgfVxuICAgICAgbWF4V2lkdGggPSBib3R0b20gLSB0b3A7XG4gICAgfVxuICAgIHJldHVybiB7dGl0bGVYLCB0aXRsZVksIG1heFdpZHRoLCByb3RhdGlvbn07XG4gIH1cbiAgZHJhdygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgY3R4ID0gbWUuY3R4O1xuICAgIGNvbnN0IG9wdHMgPSBtZS5vcHRpb25zO1xuICAgIGlmICghb3B0cy5kaXNwbGF5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGZvbnRPcHRzID0gdG9Gb250KG9wdHMuZm9udCk7XG4gICAgY29uc3QgbGluZUhlaWdodCA9IGZvbnRPcHRzLmxpbmVIZWlnaHQ7XG4gICAgY29uc3Qgb2Zmc2V0ID0gbGluZUhlaWdodCAvIDIgKyBtZS5fcGFkZGluZy50b3A7XG4gICAgY29uc3Qge3RpdGxlWCwgdGl0bGVZLCBtYXhXaWR0aCwgcm90YXRpb259ID0gbWUuX2RyYXdBcmdzKG9mZnNldCk7XG4gICAgcmVuZGVyVGV4dChjdHgsIG9wdHMudGV4dCwgMCwgMCwgZm9udE9wdHMsIHtcbiAgICAgIGNvbG9yOiBvcHRzLmNvbG9yLFxuICAgICAgbWF4V2lkdGgsXG4gICAgICByb3RhdGlvbixcbiAgICAgIHRleHRBbGlnbjogX3RvTGVmdFJpZ2h0Q2VudGVyKG9wdHMuYWxpZ24pLFxuICAgICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJyxcbiAgICAgIHRyYW5zbGF0aW9uOiBbdGl0bGVYLCB0aXRsZVldLFxuICAgIH0pO1xuICB9XG59XG5mdW5jdGlvbiBjcmVhdGVUaXRsZShjaGFydCwgdGl0bGVPcHRzKSB7XG4gIGNvbnN0IHRpdGxlID0gbmV3IFRpdGxlKHtcbiAgICBjdHg6IGNoYXJ0LmN0eCxcbiAgICBvcHRpb25zOiB0aXRsZU9wdHMsXG4gICAgY2hhcnRcbiAgfSk7XG4gIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCB0aXRsZSwgdGl0bGVPcHRzKTtcbiAgbGF5b3V0cy5hZGRCb3goY2hhcnQsIHRpdGxlKTtcbiAgY2hhcnQudGl0bGVCbG9jayA9IHRpdGxlO1xufVxudmFyIHBsdWdpbl90aXRsZSA9IHtcbiAgaWQ6ICd0aXRsZScsXG4gIF9lbGVtZW50OiBUaXRsZSxcbiAgc3RhcnQoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgY3JlYXRlVGl0bGUoY2hhcnQsIG9wdGlvbnMpO1xuICB9LFxuICBzdG9wKGNoYXJ0KSB7XG4gICAgY29uc3QgdGl0bGVCbG9jayA9IGNoYXJ0LnRpdGxlQmxvY2s7XG4gICAgbGF5b3V0cy5yZW1vdmVCb3goY2hhcnQsIHRpdGxlQmxvY2spO1xuICAgIGRlbGV0ZSBjaGFydC50aXRsZUJsb2NrO1xuICB9LFxuICBiZWZvcmVVcGRhdGUoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgY29uc3QgdGl0bGUgPSBjaGFydC50aXRsZUJsb2NrO1xuICAgIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCB0aXRsZSwgb3B0aW9ucyk7XG4gICAgdGl0bGUub3B0aW9ucyA9IG9wdGlvbnM7XG4gIH0sXG4gIGRlZmF1bHRzOiB7XG4gICAgYWxpZ246ICdjZW50ZXInLFxuICAgIGRpc3BsYXk6IGZhbHNlLFxuICAgIGZvbnQ6IHtcbiAgICAgIHdlaWdodDogJ2JvbGQnLFxuICAgIH0sXG4gICAgZnVsbFNpemU6IHRydWUsXG4gICAgcGFkZGluZzogMTAsXG4gICAgcG9zaXRpb246ICd0b3AnLFxuICAgIHRleHQ6ICcnLFxuICAgIHdlaWdodDogMjAwMFxuICB9LFxuICBkZWZhdWx0Um91dGVzOiB7XG4gICAgY29sb3I6ICdjb2xvcidcbiAgfSxcbiAgZGVzY3JpcHRvcnM6IHtcbiAgICBfc2NyaXB0YWJsZTogdHJ1ZSxcbiAgICBfaW5kZXhhYmxlOiBmYWxzZSxcbiAgfSxcbn07XG5cbmNvbnN0IG1hcCA9IG5ldyBXZWFrTWFwKCk7XG52YXIgcGx1Z2luX3N1YnRpdGxlID0ge1xuICBpZDogJ3N1YnRpdGxlJyxcbiAgc3RhcnQoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgY29uc3QgdGl0bGUgPSBuZXcgVGl0bGUoe1xuICAgICAgY3R4OiBjaGFydC5jdHgsXG4gICAgICBvcHRpb25zLFxuICAgICAgY2hhcnRcbiAgICB9KTtcbiAgICBsYXlvdXRzLmNvbmZpZ3VyZShjaGFydCwgdGl0bGUsIG9wdGlvbnMpO1xuICAgIGxheW91dHMuYWRkQm94KGNoYXJ0LCB0aXRsZSk7XG4gICAgbWFwLnNldChjaGFydCwgdGl0bGUpO1xuICB9LFxuICBzdG9wKGNoYXJ0KSB7XG4gICAgbGF5b3V0cy5yZW1vdmVCb3goY2hhcnQsIG1hcC5nZXQoY2hhcnQpKTtcbiAgICBtYXAuZGVsZXRlKGNoYXJ0KTtcbiAgfSxcbiAgYmVmb3JlVXBkYXRlKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgIGNvbnN0IHRpdGxlID0gbWFwLmdldChjaGFydCk7XG4gICAgbGF5b3V0cy5jb25maWd1cmUoY2hhcnQsIHRpdGxlLCBvcHRpb25zKTtcbiAgICB0aXRsZS5vcHRpb25zID0gb3B0aW9ucztcbiAgfSxcbiAgZGVmYXVsdHM6IHtcbiAgICBhbGlnbjogJ2NlbnRlcicsXG4gICAgZGlzcGxheTogZmFsc2UsXG4gICAgZm9udDoge1xuICAgICAgd2VpZ2h0OiAnbm9ybWFsJyxcbiAgICB9LFxuICAgIGZ1bGxTaXplOiB0cnVlLFxuICAgIHBhZGRpbmc6IDAsXG4gICAgcG9zaXRpb246ICd0b3AnLFxuICAgIHRleHQ6ICcnLFxuICAgIHdlaWdodDogMTUwMFxuICB9LFxuICBkZWZhdWx0Um91dGVzOiB7XG4gICAgY29sb3I6ICdjb2xvcidcbiAgfSxcbiAgZGVzY3JpcHRvcnM6IHtcbiAgICBfc2NyaXB0YWJsZTogdHJ1ZSxcbiAgICBfaW5kZXhhYmxlOiBmYWxzZSxcbiAgfSxcbn07XG5cbmNvbnN0IHBvc2l0aW9uZXJzID0ge1xuICBhdmVyYWdlKGl0ZW1zKSB7XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgbGV0IGksIGxlbjtcbiAgICBsZXQgeCA9IDA7XG4gICAgbGV0IHkgPSAwO1xuICAgIGxldCBjb3VudCA9IDA7XG4gICAgZm9yIChpID0gMCwgbGVuID0gaXRlbXMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgIGNvbnN0IGVsID0gaXRlbXNbaV0uZWxlbWVudDtcbiAgICAgIGlmIChlbCAmJiBlbC5oYXNWYWx1ZSgpKSB7XG4gICAgICAgIGNvbnN0IHBvcyA9IGVsLnRvb2x0aXBQb3NpdGlvbigpO1xuICAgICAgICB4ICs9IHBvcy54O1xuICAgICAgICB5ICs9IHBvcy55O1xuICAgICAgICArK2NvdW50O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgeDogeCAvIGNvdW50LFxuICAgICAgeTogeSAvIGNvdW50XG4gICAgfTtcbiAgfSxcbiAgbmVhcmVzdChpdGVtcywgZXZlbnRQb3NpdGlvbikge1xuICAgIGlmICghaXRlbXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGxldCB4ID0gZXZlbnRQb3NpdGlvbi54O1xuICAgIGxldCB5ID0gZXZlbnRQb3NpdGlvbi55O1xuICAgIGxldCBtaW5EaXN0YW5jZSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICBsZXQgaSwgbGVuLCBuZWFyZXN0RWxlbWVudDtcbiAgICBmb3IgKGkgPSAwLCBsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICAgICAgY29uc3QgZWwgPSBpdGVtc1tpXS5lbGVtZW50O1xuICAgICAgaWYgKGVsICYmIGVsLmhhc1ZhbHVlKCkpIHtcbiAgICAgICAgY29uc3QgY2VudGVyID0gZWwuZ2V0Q2VudGVyUG9pbnQoKTtcbiAgICAgICAgY29uc3QgZCA9IGRpc3RhbmNlQmV0d2VlblBvaW50cyhldmVudFBvc2l0aW9uLCBjZW50ZXIpO1xuICAgICAgICBpZiAoZCA8IG1pbkRpc3RhbmNlKSB7XG4gICAgICAgICAgbWluRGlzdGFuY2UgPSBkO1xuICAgICAgICAgIG5lYXJlc3RFbGVtZW50ID0gZWw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG5lYXJlc3RFbGVtZW50KSB7XG4gICAgICBjb25zdCB0cCA9IG5lYXJlc3RFbGVtZW50LnRvb2x0aXBQb3NpdGlvbigpO1xuICAgICAgeCA9IHRwLng7XG4gICAgICB5ID0gdHAueTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIHgsXG4gICAgICB5XG4gICAgfTtcbiAgfVxufTtcbmZ1bmN0aW9uIHB1c2hPckNvbmNhdChiYXNlLCB0b1B1c2gpIHtcbiAgaWYgKHRvUHVzaCkge1xuICAgIGlmIChpc0FycmF5KHRvUHVzaCkpIHtcbiAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGJhc2UsIHRvUHVzaCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJhc2UucHVzaCh0b1B1c2gpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYmFzZTtcbn1cbmZ1bmN0aW9uIHNwbGl0TmV3bGluZXMoc3RyKSB7XG4gIGlmICgodHlwZW9mIHN0ciA9PT0gJ3N0cmluZycgfHwgc3RyIGluc3RhbmNlb2YgU3RyaW5nKSAmJiBzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgIHJldHVybiBzdHIuc3BsaXQoJ1xcbicpO1xuICB9XG4gIHJldHVybiBzdHI7XG59XG5mdW5jdGlvbiBjcmVhdGVUb29sdGlwSXRlbShjaGFydCwgaXRlbSkge1xuICBjb25zdCB7ZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleH0gPSBpdGVtO1xuICBjb25zdCBjb250cm9sbGVyID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoZGF0YXNldEluZGV4KS5jb250cm9sbGVyO1xuICBjb25zdCB7bGFiZWwsIHZhbHVlfSA9IGNvbnRyb2xsZXIuZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCk7XG4gIHJldHVybiB7XG4gICAgY2hhcnQsXG4gICAgbGFiZWwsXG4gICAgcGFyc2VkOiBjb250cm9sbGVyLmdldFBhcnNlZChpbmRleCksXG4gICAgcmF3OiBjaGFydC5kYXRhLmRhdGFzZXRzW2RhdGFzZXRJbmRleF0uZGF0YVtpbmRleF0sXG4gICAgZm9ybWF0dGVkVmFsdWU6IHZhbHVlLFxuICAgIGRhdGFzZXQ6IGNvbnRyb2xsZXIuZ2V0RGF0YXNldCgpLFxuICAgIGRhdGFJbmRleDogaW5kZXgsXG4gICAgZGF0YXNldEluZGV4LFxuICAgIGVsZW1lbnRcbiAgfTtcbn1cbmZ1bmN0aW9uIGdldFRvb2x0aXBTaXplKHRvb2x0aXAsIG9wdGlvbnMpIHtcbiAgY29uc3QgY3R4ID0gdG9vbHRpcC5fY2hhcnQuY3R4O1xuICBjb25zdCB7Ym9keSwgZm9vdGVyLCB0aXRsZX0gPSB0b29sdGlwO1xuICBjb25zdCB7Ym94V2lkdGgsIGJveEhlaWdodH0gPSBvcHRpb25zO1xuICBjb25zdCBib2R5Rm9udCA9IHRvRm9udChvcHRpb25zLmJvZHlGb250KTtcbiAgY29uc3QgdGl0bGVGb250ID0gdG9Gb250KG9wdGlvbnMudGl0bGVGb250KTtcbiAgY29uc3QgZm9vdGVyRm9udCA9IHRvRm9udChvcHRpb25zLmZvb3RlckZvbnQpO1xuICBjb25zdCB0aXRsZUxpbmVDb3VudCA9IHRpdGxlLmxlbmd0aDtcbiAgY29uc3QgZm9vdGVyTGluZUNvdW50ID0gZm9vdGVyLmxlbmd0aDtcbiAgY29uc3QgYm9keUxpbmVJdGVtQ291bnQgPSBib2R5Lmxlbmd0aDtcbiAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRpb25zLnBhZGRpbmcpO1xuICBsZXQgaGVpZ2h0ID0gcGFkZGluZy5oZWlnaHQ7XG4gIGxldCB3aWR0aCA9IDA7XG4gIGxldCBjb21iaW5lZEJvZHlMZW5ndGggPSBib2R5LnJlZHVjZSgoY291bnQsIGJvZHlJdGVtKSA9PiBjb3VudCArIGJvZHlJdGVtLmJlZm9yZS5sZW5ndGggKyBib2R5SXRlbS5saW5lcy5sZW5ndGggKyBib2R5SXRlbS5hZnRlci5sZW5ndGgsIDApO1xuICBjb21iaW5lZEJvZHlMZW5ndGggKz0gdG9vbHRpcC5iZWZvcmVCb2R5Lmxlbmd0aCArIHRvb2x0aXAuYWZ0ZXJCb2R5Lmxlbmd0aDtcbiAgaWYgKHRpdGxlTGluZUNvdW50KSB7XG4gICAgaGVpZ2h0ICs9IHRpdGxlTGluZUNvdW50ICogdGl0bGVGb250LmxpbmVIZWlnaHRcblx0XHRcdCsgKHRpdGxlTGluZUNvdW50IC0gMSkgKiBvcHRpb25zLnRpdGxlU3BhY2luZ1xuXHRcdFx0KyBvcHRpb25zLnRpdGxlTWFyZ2luQm90dG9tO1xuICB9XG4gIGlmIChjb21iaW5lZEJvZHlMZW5ndGgpIHtcbiAgICBjb25zdCBib2R5TGluZUhlaWdodCA9IG9wdGlvbnMuZGlzcGxheUNvbG9ycyA/IE1hdGgubWF4KGJveEhlaWdodCwgYm9keUZvbnQubGluZUhlaWdodCkgOiBib2R5Rm9udC5saW5lSGVpZ2h0O1xuICAgIGhlaWdodCArPSBib2R5TGluZUl0ZW1Db3VudCAqIGJvZHlMaW5lSGVpZ2h0XG5cdFx0XHQrIChjb21iaW5lZEJvZHlMZW5ndGggLSBib2R5TGluZUl0ZW1Db3VudCkgKiBib2R5Rm9udC5saW5lSGVpZ2h0XG5cdFx0XHQrIChjb21iaW5lZEJvZHlMZW5ndGggLSAxKSAqIG9wdGlvbnMuYm9keVNwYWNpbmc7XG4gIH1cbiAgaWYgKGZvb3RlckxpbmVDb3VudCkge1xuICAgIGhlaWdodCArPSBvcHRpb25zLmZvb3Rlck1hcmdpblRvcFxuXHRcdFx0KyBmb290ZXJMaW5lQ291bnQgKiBmb290ZXJGb250LmxpbmVIZWlnaHRcblx0XHRcdCsgKGZvb3RlckxpbmVDb3VudCAtIDEpICogb3B0aW9ucy5mb290ZXJTcGFjaW5nO1xuICB9XG4gIGxldCB3aWR0aFBhZGRpbmcgPSAwO1xuICBjb25zdCBtYXhMaW5lV2lkdGggPSBmdW5jdGlvbihsaW5lKSB7XG4gICAgd2lkdGggPSBNYXRoLm1heCh3aWR0aCwgY3R4Lm1lYXN1cmVUZXh0KGxpbmUpLndpZHRoICsgd2lkdGhQYWRkaW5nKTtcbiAgfTtcbiAgY3R4LnNhdmUoKTtcbiAgY3R4LmZvbnQgPSB0aXRsZUZvbnQuc3RyaW5nO1xuICBlYWNoKHRvb2x0aXAudGl0bGUsIG1heExpbmVXaWR0aCk7XG4gIGN0eC5mb250ID0gYm9keUZvbnQuc3RyaW5nO1xuICBlYWNoKHRvb2x0aXAuYmVmb3JlQm9keS5jb25jYXQodG9vbHRpcC5hZnRlckJvZHkpLCBtYXhMaW5lV2lkdGgpO1xuICB3aWR0aFBhZGRpbmcgPSBvcHRpb25zLmRpc3BsYXlDb2xvcnMgPyAoYm94V2lkdGggKyAyKSA6IDA7XG4gIGVhY2goYm9keSwgKGJvZHlJdGVtKSA9PiB7XG4gICAgZWFjaChib2R5SXRlbS5iZWZvcmUsIG1heExpbmVXaWR0aCk7XG4gICAgZWFjaChib2R5SXRlbS5saW5lcywgbWF4TGluZVdpZHRoKTtcbiAgICBlYWNoKGJvZHlJdGVtLmFmdGVyLCBtYXhMaW5lV2lkdGgpO1xuICB9KTtcbiAgd2lkdGhQYWRkaW5nID0gMDtcbiAgY3R4LmZvbnQgPSBmb290ZXJGb250LnN0cmluZztcbiAgZWFjaCh0b29sdGlwLmZvb3RlciwgbWF4TGluZVdpZHRoKTtcbiAgY3R4LnJlc3RvcmUoKTtcbiAgd2lkdGggKz0gcGFkZGluZy53aWR0aDtcbiAgcmV0dXJuIHt3aWR0aCwgaGVpZ2h0fTtcbn1cbmZ1bmN0aW9uIGRldGVybWluZVlBbGlnbihjaGFydCwgc2l6ZSkge1xuICBjb25zdCB7eSwgaGVpZ2h0fSA9IHNpemU7XG4gIGlmICh5IDwgaGVpZ2h0IC8gMikge1xuICAgIHJldHVybiAndG9wJztcbiAgfSBlbHNlIGlmICh5ID4gKGNoYXJ0LmhlaWdodCAtIGhlaWdodCAvIDIpKSB7XG4gICAgcmV0dXJuICdib3R0b20nO1xuICB9XG4gIHJldHVybiAnY2VudGVyJztcbn1cbmZ1bmN0aW9uIGRvZXNOb3RGaXRXaXRoQWxpZ24oeEFsaWduLCBjaGFydCwgb3B0aW9ucywgc2l6ZSkge1xuICBjb25zdCB7eCwgd2lkdGh9ID0gc2l6ZTtcbiAgY29uc3QgY2FyZXQgPSBvcHRpb25zLmNhcmV0U2l6ZSArIG9wdGlvbnMuY2FyZXRQYWRkaW5nO1xuICBpZiAoeEFsaWduID09PSAnbGVmdCcgJiYgeCArIHdpZHRoICsgY2FyZXQgPiBjaGFydC53aWR0aCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGlmICh4QWxpZ24gPT09ICdyaWdodCcgJiYgeCAtIHdpZHRoIC0gY2FyZXQgPCAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbmZ1bmN0aW9uIGRldGVybWluZVhBbGlnbihjaGFydCwgb3B0aW9ucywgc2l6ZSwgeUFsaWduKSB7XG4gIGNvbnN0IHt4LCB3aWR0aH0gPSBzaXplO1xuICBjb25zdCB7d2lkdGg6IGNoYXJ0V2lkdGgsIGNoYXJ0QXJlYToge2xlZnQsIHJpZ2h0fX0gPSBjaGFydDtcbiAgbGV0IHhBbGlnbiA9ICdjZW50ZXInO1xuICBpZiAoeUFsaWduID09PSAnY2VudGVyJykge1xuICAgIHhBbGlnbiA9IHggPD0gKGxlZnQgKyByaWdodCkgLyAyID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgfSBlbHNlIGlmICh4IDw9IHdpZHRoIC8gMikge1xuICAgIHhBbGlnbiA9ICdsZWZ0JztcbiAgfSBlbHNlIGlmICh4ID49IGNoYXJ0V2lkdGggLSB3aWR0aCAvIDIpIHtcbiAgICB4QWxpZ24gPSAncmlnaHQnO1xuICB9XG4gIGlmIChkb2VzTm90Rml0V2l0aEFsaWduKHhBbGlnbiwgY2hhcnQsIG9wdGlvbnMsIHNpemUpKSB7XG4gICAgeEFsaWduID0gJ2NlbnRlcic7XG4gIH1cbiAgcmV0dXJuIHhBbGlnbjtcbn1cbmZ1bmN0aW9uIGRldGVybWluZUFsaWdubWVudChjaGFydCwgb3B0aW9ucywgc2l6ZSkge1xuICBjb25zdCB5QWxpZ24gPSBvcHRpb25zLnlBbGlnbiB8fCBkZXRlcm1pbmVZQWxpZ24oY2hhcnQsIHNpemUpO1xuICByZXR1cm4ge1xuICAgIHhBbGlnbjogb3B0aW9ucy54QWxpZ24gfHwgZGV0ZXJtaW5lWEFsaWduKGNoYXJ0LCBvcHRpb25zLCBzaXplLCB5QWxpZ24pLFxuICAgIHlBbGlnblxuICB9O1xufVxuZnVuY3Rpb24gYWxpZ25YKHNpemUsIHhBbGlnbikge1xuICBsZXQge3gsIHdpZHRofSA9IHNpemU7XG4gIGlmICh4QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICB4IC09IHdpZHRoO1xuICB9IGVsc2UgaWYgKHhBbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICB4IC09ICh3aWR0aCAvIDIpO1xuICB9XG4gIHJldHVybiB4O1xufVxuZnVuY3Rpb24gYWxpZ25ZKHNpemUsIHlBbGlnbiwgcGFkZGluZ0FuZFNpemUpIHtcbiAgbGV0IHt5LCBoZWlnaHR9ID0gc2l6ZTtcbiAgaWYgKHlBbGlnbiA9PT0gJ3RvcCcpIHtcbiAgICB5ICs9IHBhZGRpbmdBbmRTaXplO1xuICB9IGVsc2UgaWYgKHlBbGlnbiA9PT0gJ2JvdHRvbScpIHtcbiAgICB5IC09IGhlaWdodCArIHBhZGRpbmdBbmRTaXplO1xuICB9IGVsc2Uge1xuICAgIHkgLT0gKGhlaWdodCAvIDIpO1xuICB9XG4gIHJldHVybiB5O1xufVxuZnVuY3Rpb24gZ2V0QmFja2dyb3VuZFBvaW50KG9wdGlvbnMsIHNpemUsIGFsaWdubWVudCwgY2hhcnQpIHtcbiAgY29uc3Qge2NhcmV0U2l6ZSwgY2FyZXRQYWRkaW5nLCBjb3JuZXJSYWRpdXN9ID0gb3B0aW9ucztcbiAgY29uc3Qge3hBbGlnbiwgeUFsaWdufSA9IGFsaWdubWVudDtcbiAgY29uc3QgcGFkZGluZ0FuZFNpemUgPSBjYXJldFNpemUgKyBjYXJldFBhZGRpbmc7XG4gIGNvbnN0IHJhZGl1c0FuZFBhZGRpbmcgPSBjb3JuZXJSYWRpdXMgKyBjYXJldFBhZGRpbmc7XG4gIGxldCB4ID0gYWxpZ25YKHNpemUsIHhBbGlnbik7XG4gIGNvbnN0IHkgPSBhbGlnblkoc2l6ZSwgeUFsaWduLCBwYWRkaW5nQW5kU2l6ZSk7XG4gIGlmICh5QWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgaWYgKHhBbGlnbiA9PT0gJ2xlZnQnKSB7XG4gICAgICB4ICs9IHBhZGRpbmdBbmRTaXplO1xuICAgIH0gZWxzZSBpZiAoeEFsaWduID09PSAncmlnaHQnKSB7XG4gICAgICB4IC09IHBhZGRpbmdBbmRTaXplO1xuICAgIH1cbiAgfSBlbHNlIGlmICh4QWxpZ24gPT09ICdsZWZ0Jykge1xuICAgIHggLT0gcmFkaXVzQW5kUGFkZGluZztcbiAgfSBlbHNlIGlmICh4QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICB4ICs9IHJhZGl1c0FuZFBhZGRpbmc7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICB4OiBfbGltaXRWYWx1ZSh4LCAwLCBjaGFydC53aWR0aCAtIHNpemUud2lkdGgpLFxuICAgIHk6IF9saW1pdFZhbHVlKHksIDAsIGNoYXJ0LmhlaWdodCAtIHNpemUuaGVpZ2h0KVxuICB9O1xufVxuZnVuY3Rpb24gZ2V0QWxpZ25lZFgodG9vbHRpcCwgYWxpZ24sIG9wdGlvbnMpIHtcbiAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRpb25zLnBhZGRpbmcpO1xuICByZXR1cm4gYWxpZ24gPT09ICdjZW50ZXInXG4gICAgPyB0b29sdGlwLnggKyB0b29sdGlwLndpZHRoIC8gMlxuICAgIDogYWxpZ24gPT09ICdyaWdodCdcbiAgICAgID8gdG9vbHRpcC54ICsgdG9vbHRpcC53aWR0aCAtIHBhZGRpbmcucmlnaHRcbiAgICAgIDogdG9vbHRpcC54ICsgcGFkZGluZy5sZWZ0O1xufVxuZnVuY3Rpb24gZ2V0QmVmb3JlQWZ0ZXJCb2R5TGluZXMoY2FsbGJhY2spIHtcbiAgcmV0dXJuIHB1c2hPckNvbmNhdChbXSwgc3BsaXROZXdsaW5lcyhjYWxsYmFjaykpO1xufVxuZnVuY3Rpb24gY3JlYXRlVG9vbHRpcENvbnRleHQocGFyZW50LCB0b29sdGlwLCB0b29sdGlwSXRlbXMpIHtcbiAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShwYXJlbnQpLCB7XG4gICAgdG9vbHRpcCxcbiAgICB0b29sdGlwSXRlbXMsXG4gICAgdHlwZTogJ3Rvb2x0aXAnXG4gIH0pO1xufVxuZnVuY3Rpb24gb3ZlcnJpZGVDYWxsYmFja3MoY2FsbGJhY2tzLCBjb250ZXh0KSB7XG4gIGNvbnN0IG92ZXJyaWRlID0gY29udGV4dCAmJiBjb250ZXh0LmRhdGFzZXQgJiYgY29udGV4dC5kYXRhc2V0LnRvb2x0aXAgJiYgY29udGV4dC5kYXRhc2V0LnRvb2x0aXAuY2FsbGJhY2tzO1xuICByZXR1cm4gb3ZlcnJpZGUgPyBjYWxsYmFja3Mub3ZlcnJpZGUob3ZlcnJpZGUpIDogY2FsbGJhY2tzO1xufVxuY2xhc3MgVG9vbHRpcCBleHRlbmRzIEVsZW1lbnQge1xuICBjb25zdHJ1Y3Rvcihjb25maWcpIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMub3BhY2l0eSA9IDA7XG4gICAgdGhpcy5fYWN0aXZlID0gW107XG4gICAgdGhpcy5fY2hhcnQgPSBjb25maWcuX2NoYXJ0O1xuICAgIHRoaXMuX2V2ZW50UG9zaXRpb24gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fc2l6ZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9jYWNoZWRBbmltYXRpb25zID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3Rvb2x0aXBJdGVtcyA9IFtdO1xuICAgIHRoaXMuJGFuaW1hdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm9wdGlvbnMgPSBjb25maWcub3B0aW9ucztcbiAgICB0aGlzLmRhdGFQb2ludHMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy50aXRsZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmJlZm9yZUJvZHkgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5ib2R5ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuYWZ0ZXJCb2R5ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZm9vdGVyID0gdW5kZWZpbmVkO1xuICAgIHRoaXMueEFsaWduID0gdW5kZWZpbmVkO1xuICAgIHRoaXMueUFsaWduID0gdW5kZWZpbmVkO1xuICAgIHRoaXMueCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnkgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5oZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy53aWR0aCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmNhcmV0WCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmNhcmV0WSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmxhYmVsQ29sb3JzID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubGFiZWxQb2ludFN0eWxlcyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmxhYmVsVGV4dENvbG9ycyA9IHVuZGVmaW5lZDtcbiAgfVxuICBpbml0aWFsaXplKG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMuX2NhY2hlZEFuaW1hdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgfVxuICBfcmVzb2x2ZUFuaW1hdGlvbnMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGNhY2hlZCA9IG1lLl9jYWNoZWRBbmltYXRpb25zO1xuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuICAgIGNvbnN0IGNoYXJ0ID0gbWUuX2NoYXJ0O1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zLnNldENvbnRleHQobWUuZ2V0Q29udGV4dCgpKTtcbiAgICBjb25zdCBvcHRzID0gb3B0aW9ucy5lbmFibGVkICYmIGNoYXJ0Lm9wdGlvbnMuYW5pbWF0aW9uICYmIG9wdGlvbnMuYW5pbWF0aW9ucztcbiAgICBjb25zdCBhbmltYXRpb25zID0gbmV3IEFuaW1hdGlvbnMobWUuX2NoYXJ0LCBvcHRzKTtcbiAgICBpZiAob3B0cy5fY2FjaGVhYmxlKSB7XG4gICAgICBtZS5fY2FjaGVkQW5pbWF0aW9ucyA9IE9iamVjdC5mcmVlemUoYW5pbWF0aW9ucyk7XG4gICAgfVxuICAgIHJldHVybiBhbmltYXRpb25zO1xuICB9XG4gIGdldENvbnRleHQoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIHJldHVybiBtZS4kY29udGV4dCB8fFxuXHRcdFx0KG1lLiRjb250ZXh0ID0gY3JlYXRlVG9vbHRpcENvbnRleHQobWUuX2NoYXJ0LmdldENvbnRleHQoKSwgbWUsIG1lLl90b29sdGlwSXRlbXMpKTtcbiAgfVxuICBnZXRUaXRsZShjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtjYWxsYmFja3N9ID0gb3B0aW9ucztcbiAgICBjb25zdCBiZWZvcmVUaXRsZSA9IGNhbGxiYWNrcy5iZWZvcmVUaXRsZS5hcHBseShtZSwgW2NvbnRleHRdKTtcbiAgICBjb25zdCB0aXRsZSA9IGNhbGxiYWNrcy50aXRsZS5hcHBseShtZSwgW2NvbnRleHRdKTtcbiAgICBjb25zdCBhZnRlclRpdGxlID0gY2FsbGJhY2tzLmFmdGVyVGl0bGUuYXBwbHkobWUsIFtjb250ZXh0XSk7XG4gICAgbGV0IGxpbmVzID0gW107XG4gICAgbGluZXMgPSBwdXNoT3JDb25jYXQobGluZXMsIHNwbGl0TmV3bGluZXMoYmVmb3JlVGl0bGUpKTtcbiAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyh0aXRsZSkpO1xuICAgIGxpbmVzID0gcHVzaE9yQ29uY2F0KGxpbmVzLCBzcGxpdE5ld2xpbmVzKGFmdGVyVGl0bGUpKTtcbiAgICByZXR1cm4gbGluZXM7XG4gIH1cbiAgZ2V0QmVmb3JlQm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gZ2V0QmVmb3JlQWZ0ZXJCb2R5TGluZXMob3B0aW9ucy5jYWxsYmFja3MuYmVmb3JlQm9keS5hcHBseSh0aGlzLCBbdG9vbHRpcEl0ZW1zXSkpO1xuICB9XG4gIGdldEJvZHkodG9vbHRpcEl0ZW1zLCBvcHRpb25zKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHtjYWxsYmFja3N9ID0gb3B0aW9ucztcbiAgICBjb25zdCBib2R5SXRlbXMgPSBbXTtcbiAgICBlYWNoKHRvb2x0aXBJdGVtcywgKGNvbnRleHQpID0+IHtcbiAgICAgIGNvbnN0IGJvZHlJdGVtID0ge1xuICAgICAgICBiZWZvcmU6IFtdLFxuICAgICAgICBsaW5lczogW10sXG4gICAgICAgIGFmdGVyOiBbXVxuICAgICAgfTtcbiAgICAgIGNvbnN0IHNjb3BlZCA9IG92ZXJyaWRlQ2FsbGJhY2tzKGNhbGxiYWNrcywgY29udGV4dCk7XG4gICAgICBwdXNoT3JDb25jYXQoYm9keUl0ZW0uYmVmb3JlLCBzcGxpdE5ld2xpbmVzKHNjb3BlZC5iZWZvcmVMYWJlbC5jYWxsKG1lLCBjb250ZXh0KSkpO1xuICAgICAgcHVzaE9yQ29uY2F0KGJvZHlJdGVtLmxpbmVzLCBzY29wZWQubGFiZWwuY2FsbChtZSwgY29udGV4dCkpO1xuICAgICAgcHVzaE9yQ29uY2F0KGJvZHlJdGVtLmFmdGVyLCBzcGxpdE5ld2xpbmVzKHNjb3BlZC5hZnRlckxhYmVsLmNhbGwobWUsIGNvbnRleHQpKSk7XG4gICAgICBib2R5SXRlbXMucHVzaChib2R5SXRlbSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGJvZHlJdGVtcztcbiAgfVxuICBnZXRBZnRlckJvZHkodG9vbHRpcEl0ZW1zLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGdldEJlZm9yZUFmdGVyQm9keUxpbmVzKG9wdGlvbnMuY2FsbGJhY2tzLmFmdGVyQm9keS5hcHBseSh0aGlzLCBbdG9vbHRpcEl0ZW1zXSkpO1xuICB9XG4gIGdldEZvb3Rlcih0b29sdGlwSXRlbXMsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge2NhbGxiYWNrc30gPSBvcHRpb25zO1xuICAgIGNvbnN0IGJlZm9yZUZvb3RlciA9IGNhbGxiYWNrcy5iZWZvcmVGb290ZXIuYXBwbHkobWUsIFt0b29sdGlwSXRlbXNdKTtcbiAgICBjb25zdCBmb290ZXIgPSBjYWxsYmFja3MuZm9vdGVyLmFwcGx5KG1lLCBbdG9vbHRpcEl0ZW1zXSk7XG4gICAgY29uc3QgYWZ0ZXJGb290ZXIgPSBjYWxsYmFja3MuYWZ0ZXJGb290ZXIuYXBwbHkobWUsIFt0b29sdGlwSXRlbXNdKTtcbiAgICBsZXQgbGluZXMgPSBbXTtcbiAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyhiZWZvcmVGb290ZXIpKTtcbiAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyhmb290ZXIpKTtcbiAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyhhZnRlckZvb3RlcikpO1xuICAgIHJldHVybiBsaW5lcztcbiAgfVxuICBfY3JlYXRlSXRlbXMob3B0aW9ucykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBhY3RpdmUgPSBtZS5fYWN0aXZlO1xuICAgIGNvbnN0IGRhdGEgPSBtZS5fY2hhcnQuZGF0YTtcbiAgICBjb25zdCBsYWJlbENvbG9ycyA9IFtdO1xuICAgIGNvbnN0IGxhYmVsUG9pbnRTdHlsZXMgPSBbXTtcbiAgICBjb25zdCBsYWJlbFRleHRDb2xvcnMgPSBbXTtcbiAgICBsZXQgdG9vbHRpcEl0ZW1zID0gW107XG4gICAgbGV0IGksIGxlbjtcbiAgICBmb3IgKGkgPSAwLCBsZW4gPSBhY3RpdmUubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgIHRvb2x0aXBJdGVtcy5wdXNoKGNyZWF0ZVRvb2x0aXBJdGVtKG1lLl9jaGFydCwgYWN0aXZlW2ldKSk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmZpbHRlcikge1xuICAgICAgdG9vbHRpcEl0ZW1zID0gdG9vbHRpcEl0ZW1zLmZpbHRlcigoZWxlbWVudCwgaW5kZXgsIGFycmF5KSA9PiBvcHRpb25zLmZpbHRlcihlbGVtZW50LCBpbmRleCwgYXJyYXksIGRhdGEpKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuaXRlbVNvcnQpIHtcbiAgICAgIHRvb2x0aXBJdGVtcyA9IHRvb2x0aXBJdGVtcy5zb3J0KChhLCBiKSA9PiBvcHRpb25zLml0ZW1Tb3J0KGEsIGIsIGRhdGEpKTtcbiAgICB9XG4gICAgZWFjaCh0b29sdGlwSXRlbXMsIChjb250ZXh0KSA9PiB7XG4gICAgICBjb25zdCBzY29wZWQgPSBvdmVycmlkZUNhbGxiYWNrcyhvcHRpb25zLmNhbGxiYWNrcywgY29udGV4dCk7XG4gICAgICBsYWJlbENvbG9ycy5wdXNoKHNjb3BlZC5sYWJlbENvbG9yLmNhbGwobWUsIGNvbnRleHQpKTtcbiAgICAgIGxhYmVsUG9pbnRTdHlsZXMucHVzaChzY29wZWQubGFiZWxQb2ludFN0eWxlLmNhbGwobWUsIGNvbnRleHQpKTtcbiAgICAgIGxhYmVsVGV4dENvbG9ycy5wdXNoKHNjb3BlZC5sYWJlbFRleHRDb2xvci5jYWxsKG1lLCBjb250ZXh0KSk7XG4gICAgfSk7XG4gICAgbWUubGFiZWxDb2xvcnMgPSBsYWJlbENvbG9ycztcbiAgICBtZS5sYWJlbFBvaW50U3R5bGVzID0gbGFiZWxQb2ludFN0eWxlcztcbiAgICBtZS5sYWJlbFRleHRDb2xvcnMgPSBsYWJlbFRleHRDb2xvcnM7XG4gICAgbWUuZGF0YVBvaW50cyA9IHRvb2x0aXBJdGVtcztcbiAgICByZXR1cm4gdG9vbHRpcEl0ZW1zO1xuICB9XG4gIHVwZGF0ZShjaGFuZ2VkLCByZXBsYXkpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qgb3B0aW9ucyA9IG1lLm9wdGlvbnMuc2V0Q29udGV4dChtZS5nZXRDb250ZXh0KCkpO1xuICAgIGNvbnN0IGFjdGl2ZSA9IG1lLl9hY3RpdmU7XG4gICAgbGV0IHByb3BlcnRpZXM7XG4gICAgbGV0IHRvb2x0aXBJdGVtcyA9IFtdO1xuICAgIGlmICghYWN0aXZlLmxlbmd0aCkge1xuICAgICAgaWYgKG1lLm9wYWNpdHkgIT09IDApIHtcbiAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHBvc2l0aW9uID0gcG9zaXRpb25lcnNbb3B0aW9ucy5wb3NpdGlvbl0uY2FsbChtZSwgYWN0aXZlLCBtZS5fZXZlbnRQb3NpdGlvbik7XG4gICAgICB0b29sdGlwSXRlbXMgPSBtZS5fY3JlYXRlSXRlbXMob3B0aW9ucyk7XG4gICAgICBtZS50aXRsZSA9IG1lLmdldFRpdGxlKHRvb2x0aXBJdGVtcywgb3B0aW9ucyk7XG4gICAgICBtZS5iZWZvcmVCb2R5ID0gbWUuZ2V0QmVmb3JlQm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpO1xuICAgICAgbWUuYm9keSA9IG1lLmdldEJvZHkodG9vbHRpcEl0ZW1zLCBvcHRpb25zKTtcbiAgICAgIG1lLmFmdGVyQm9keSA9IG1lLmdldEFmdGVyQm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpO1xuICAgICAgbWUuZm9vdGVyID0gbWUuZ2V0Rm9vdGVyKHRvb2x0aXBJdGVtcywgb3B0aW9ucyk7XG4gICAgICBjb25zdCBzaXplID0gbWUuX3NpemUgPSBnZXRUb29sdGlwU2l6ZShtZSwgb3B0aW9ucyk7XG4gICAgICBjb25zdCBwb3NpdGlvbkFuZFNpemUgPSBPYmplY3QuYXNzaWduKHt9LCBwb3NpdGlvbiwgc2l6ZSk7XG4gICAgICBjb25zdCBhbGlnbm1lbnQgPSBkZXRlcm1pbmVBbGlnbm1lbnQobWUuX2NoYXJ0LCBvcHRpb25zLCBwb3NpdGlvbkFuZFNpemUpO1xuICAgICAgY29uc3QgYmFja2dyb3VuZFBvaW50ID0gZ2V0QmFja2dyb3VuZFBvaW50KG9wdGlvbnMsIHBvc2l0aW9uQW5kU2l6ZSwgYWxpZ25tZW50LCBtZS5fY2hhcnQpO1xuICAgICAgbWUueEFsaWduID0gYWxpZ25tZW50LnhBbGlnbjtcbiAgICAgIG1lLnlBbGlnbiA9IGFsaWdubWVudC55QWxpZ247XG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICB4OiBiYWNrZ3JvdW5kUG9pbnQueCxcbiAgICAgICAgeTogYmFja2dyb3VuZFBvaW50LnksXG4gICAgICAgIHdpZHRoOiBzaXplLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IHNpemUuaGVpZ2h0LFxuICAgICAgICBjYXJldFg6IHBvc2l0aW9uLngsXG4gICAgICAgIGNhcmV0WTogcG9zaXRpb24ueVxuICAgICAgfTtcbiAgICB9XG4gICAgbWUuX3Rvb2x0aXBJdGVtcyA9IHRvb2x0aXBJdGVtcztcbiAgICBtZS4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICBpZiAocHJvcGVydGllcykge1xuICAgICAgbWUuX3Jlc29sdmVBbmltYXRpb25zKCkudXBkYXRlKG1lLCBwcm9wZXJ0aWVzKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZWQgJiYgb3B0aW9ucy5leHRlcm5hbCkge1xuICAgICAgb3B0aW9ucy5leHRlcm5hbC5jYWxsKG1lLCB7Y2hhcnQ6IG1lLl9jaGFydCwgdG9vbHRpcDogbWUsIHJlcGxheX0pO1xuICAgIH1cbiAgfVxuICBkcmF3Q2FyZXQodG9vbHRpcFBvaW50LCBjdHgsIHNpemUsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBjYXJldFBvc2l0aW9uID0gdGhpcy5nZXRDYXJldFBvc2l0aW9uKHRvb2x0aXBQb2ludCwgc2l6ZSwgb3B0aW9ucyk7XG4gICAgY3R4LmxpbmVUbyhjYXJldFBvc2l0aW9uLngxLCBjYXJldFBvc2l0aW9uLnkxKTtcbiAgICBjdHgubGluZVRvKGNhcmV0UG9zaXRpb24ueDIsIGNhcmV0UG9zaXRpb24ueTIpO1xuICAgIGN0eC5saW5lVG8oY2FyZXRQb3NpdGlvbi54MywgY2FyZXRQb3NpdGlvbi55Myk7XG4gIH1cbiAgZ2V0Q2FyZXRQb3NpdGlvbih0b29sdGlwUG9pbnQsIHNpemUsIG9wdGlvbnMpIHtcbiAgICBjb25zdCB7eEFsaWduLCB5QWxpZ259ID0gdGhpcztcbiAgICBjb25zdCB7Y29ybmVyUmFkaXVzLCBjYXJldFNpemV9ID0gb3B0aW9ucztcbiAgICBjb25zdCB7eDogcHRYLCB5OiBwdFl9ID0gdG9vbHRpcFBvaW50O1xuICAgIGNvbnN0IHt3aWR0aCwgaGVpZ2h0fSA9IHNpemU7XG4gICAgbGV0IHgxLCB4MiwgeDMsIHkxLCB5MiwgeTM7XG4gICAgaWYgKHlBbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIHkyID0gcHRZICsgKGhlaWdodCAvIDIpO1xuICAgICAgaWYgKHhBbGlnbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgIHgxID0gcHRYO1xuICAgICAgICB4MiA9IHgxIC0gY2FyZXRTaXplO1xuICAgICAgICB5MSA9IHkyICsgY2FyZXRTaXplO1xuICAgICAgICB5MyA9IHkyIC0gY2FyZXRTaXplO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeDEgPSBwdFggKyB3aWR0aDtcbiAgICAgICAgeDIgPSB4MSArIGNhcmV0U2l6ZTtcbiAgICAgICAgeTEgPSB5MiAtIGNhcmV0U2l6ZTtcbiAgICAgICAgeTMgPSB5MiArIGNhcmV0U2l6ZTtcbiAgICAgIH1cbiAgICAgIHgzID0geDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh4QWxpZ24gPT09ICdsZWZ0Jykge1xuICAgICAgICB4MiA9IHB0WCArIGNvcm5lclJhZGl1cyArIChjYXJldFNpemUpO1xuICAgICAgfSBlbHNlIGlmICh4QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgeDIgPSBwdFggKyB3aWR0aCAtIGNvcm5lclJhZGl1cyAtIGNhcmV0U2l6ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHgyID0gdGhpcy5jYXJldFg7XG4gICAgICB9XG4gICAgICBpZiAoeUFsaWduID09PSAndG9wJykge1xuICAgICAgICB5MSA9IHB0WTtcbiAgICAgICAgeTIgPSB5MSAtIGNhcmV0U2l6ZTtcbiAgICAgICAgeDEgPSB4MiAtIGNhcmV0U2l6ZTtcbiAgICAgICAgeDMgPSB4MiArIGNhcmV0U2l6ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHkxID0gcHRZICsgaGVpZ2h0O1xuICAgICAgICB5MiA9IHkxICsgY2FyZXRTaXplO1xuICAgICAgICB4MSA9IHgyICsgY2FyZXRTaXplO1xuICAgICAgICB4MyA9IHgyIC0gY2FyZXRTaXplO1xuICAgICAgfVxuICAgICAgeTMgPSB5MTtcbiAgICB9XG4gICAgcmV0dXJuIHt4MSwgeDIsIHgzLCB5MSwgeTIsIHkzfTtcbiAgfVxuICBkcmF3VGl0bGUocHQsIGN0eCwgb3B0aW9ucykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB0aXRsZSA9IG1lLnRpdGxlO1xuICAgIGNvbnN0IGxlbmd0aCA9IHRpdGxlLmxlbmd0aDtcbiAgICBsZXQgdGl0bGVGb250LCB0aXRsZVNwYWNpbmcsIGk7XG4gICAgaWYgKGxlbmd0aCkge1xuICAgICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRpb25zLnJ0bCwgbWUueCwgbWUud2lkdGgpO1xuICAgICAgcHQueCA9IGdldEFsaWduZWRYKG1lLCBvcHRpb25zLnRpdGxlQWxpZ24sIG9wdGlvbnMpO1xuICAgICAgY3R4LnRleHRBbGlnbiA9IHJ0bEhlbHBlci50ZXh0QWxpZ24ob3B0aW9ucy50aXRsZUFsaWduKTtcbiAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgIHRpdGxlRm9udCA9IHRvRm9udChvcHRpb25zLnRpdGxlRm9udCk7XG4gICAgICB0aXRsZVNwYWNpbmcgPSBvcHRpb25zLnRpdGxlU3BhY2luZztcbiAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLnRpdGxlQ29sb3I7XG4gICAgICBjdHguZm9udCA9IHRpdGxlRm9udC5zdHJpbmc7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICAgICAgY3R4LmZpbGxUZXh0KHRpdGxlW2ldLCBydGxIZWxwZXIueChwdC54KSwgcHQueSArIHRpdGxlRm9udC5saW5lSGVpZ2h0IC8gMik7XG4gICAgICAgIHB0LnkgKz0gdGl0bGVGb250LmxpbmVIZWlnaHQgKyB0aXRsZVNwYWNpbmc7XG4gICAgICAgIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgcHQueSArPSBvcHRpb25zLnRpdGxlTWFyZ2luQm90dG9tIC0gdGl0bGVTcGFjaW5nO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIF9kcmF3Q29sb3JCb3goY3R4LCBwdCwgaSwgcnRsSGVscGVyLCBvcHRpb25zKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGxhYmVsQ29sb3JzID0gbWUubGFiZWxDb2xvcnNbaV07XG4gICAgY29uc3QgbGFiZWxQb2ludFN0eWxlID0gbWUubGFiZWxQb2ludFN0eWxlc1tpXTtcbiAgICBjb25zdCB7Ym94SGVpZ2h0LCBib3hXaWR0aH0gPSBvcHRpb25zO1xuICAgIGNvbnN0IGJvZHlGb250ID0gdG9Gb250KG9wdGlvbnMuYm9keUZvbnQpO1xuICAgIGNvbnN0IGNvbG9yWCA9IGdldEFsaWduZWRYKG1lLCAnbGVmdCcsIG9wdGlvbnMpO1xuICAgIGNvbnN0IHJ0bENvbG9yWCA9IHJ0bEhlbHBlci54KGNvbG9yWCk7XG4gICAgY29uc3QgeU9mZlNldCA9IGJveEhlaWdodCA8IGJvZHlGb250LmxpbmVIZWlnaHQgPyAoYm9keUZvbnQubGluZUhlaWdodCAtIGJveEhlaWdodCkgLyAyIDogMDtcbiAgICBjb25zdCBjb2xvclkgPSBwdC55ICsgeU9mZlNldDtcbiAgICBpZiAob3B0aW9ucy51c2VQb2ludFN0eWxlKSB7XG4gICAgICBjb25zdCBkcmF3T3B0aW9ucyA9IHtcbiAgICAgICAgcmFkaXVzOiBNYXRoLm1pbihib3hXaWR0aCwgYm94SGVpZ2h0KSAvIDIsXG4gICAgICAgIHBvaW50U3R5bGU6IGxhYmVsUG9pbnRTdHlsZS5wb2ludFN0eWxlLFxuICAgICAgICByb3RhdGlvbjogbGFiZWxQb2ludFN0eWxlLnJvdGF0aW9uLFxuICAgICAgICBib3JkZXJXaWR0aDogMVxuICAgICAgfTtcbiAgICAgIGNvbnN0IGNlbnRlclggPSBydGxIZWxwZXIubGVmdEZvckx0cihydGxDb2xvclgsIGJveFdpZHRoKSArIGJveFdpZHRoIC8gMjtcbiAgICAgIGNvbnN0IGNlbnRlclkgPSBjb2xvclkgKyBib3hIZWlnaHQgLyAyO1xuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gb3B0aW9ucy5tdWx0aUtleUJhY2tncm91bmQ7XG4gICAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5tdWx0aUtleUJhY2tncm91bmQ7XG4gICAgICBkcmF3UG9pbnQoY3R4LCBkcmF3T3B0aW9ucywgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICBjdHguc3Ryb2tlU3R5bGUgPSBsYWJlbENvbG9ycy5ib3JkZXJDb2xvcjtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSBsYWJlbENvbG9ycy5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICBkcmF3UG9pbnQoY3R4LCBkcmF3T3B0aW9ucywgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN0eC5saW5lV2lkdGggPSBsYWJlbENvbG9ycy5ib3JkZXJXaWR0aCB8fCAxO1xuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gbGFiZWxDb2xvcnMuYm9yZGVyQ29sb3I7XG4gICAgICBjdHguc2V0TGluZURhc2gobGFiZWxDb2xvcnMuYm9yZGVyRGFzaCB8fCBbXSk7XG4gICAgICBjdHgubGluZURhc2hPZmZzZXQgPSBsYWJlbENvbG9ycy5ib3JkZXJEYXNoT2Zmc2V0IHx8IDA7XG4gICAgICBjb25zdCBvdXRlclggPSBydGxIZWxwZXIubGVmdEZvckx0cihydGxDb2xvclgsIGJveFdpZHRoKTtcbiAgICAgIGNvbnN0IGlubmVyWCA9IHJ0bEhlbHBlci5sZWZ0Rm9yTHRyKHJ0bEhlbHBlci54UGx1cyhydGxDb2xvclgsIDEpLCBib3hXaWR0aCAtIDIpO1xuICAgICAgY29uc3QgYm9yZGVyUmFkaXVzID0gdG9UUkJMQ29ybmVycyhsYWJlbENvbG9ycy5ib3JkZXJSYWRpdXMpO1xuICAgICAgaWYgKE9iamVjdC52YWx1ZXMoYm9yZGVyUmFkaXVzKS5zb21lKHYgPT4gdiAhPT0gMCkpIHtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5tdWx0aUtleUJhY2tncm91bmQ7XG4gICAgICAgIGFkZFJvdW5kZWRSZWN0UGF0aChjdHgsIHtcbiAgICAgICAgICB4OiBvdXRlclgsXG4gICAgICAgICAgeTogY29sb3JZLFxuICAgICAgICAgIHc6IGJveFdpZHRoLFxuICAgICAgICAgIGg6IGJveEhlaWdodCxcbiAgICAgICAgICByYWRpdXM6IGJvcmRlclJhZGl1cyxcbiAgICAgICAgfSk7XG4gICAgICAgIGN0eC5maWxsKCk7XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGxhYmVsQ29sb3JzLmJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBhZGRSb3VuZGVkUmVjdFBhdGgoY3R4LCB7XG4gICAgICAgICAgeDogaW5uZXJYLFxuICAgICAgICAgIHk6IGNvbG9yWSArIDEsXG4gICAgICAgICAgdzogYm94V2lkdGggLSAyLFxuICAgICAgICAgIGg6IGJveEhlaWdodCAtIDIsXG4gICAgICAgICAgcmFkaXVzOiBib3JkZXJSYWRpdXMsXG4gICAgICAgIH0pO1xuICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMubXVsdGlLZXlCYWNrZ3JvdW5kO1xuICAgICAgICBjdHguZmlsbFJlY3Qob3V0ZXJYLCBjb2xvclksIGJveFdpZHRoLCBib3hIZWlnaHQpO1xuICAgICAgICBjdHguc3Ryb2tlUmVjdChvdXRlclgsIGNvbG9yWSwgYm94V2lkdGgsIGJveEhlaWdodCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSBsYWJlbENvbG9ycy5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgIGN0eC5maWxsUmVjdChpbm5lclgsIGNvbG9yWSArIDEsIGJveFdpZHRoIC0gMiwgYm94SGVpZ2h0IC0gMik7XG4gICAgICB9XG4gICAgfVxuICAgIGN0eC5maWxsU3R5bGUgPSBtZS5sYWJlbFRleHRDb2xvcnNbaV07XG4gIH1cbiAgZHJhd0JvZHkocHQsIGN0eCwgb3B0aW9ucykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB7Ym9keX0gPSBtZTtcbiAgICBjb25zdCB7Ym9keVNwYWNpbmcsIGJvZHlBbGlnbiwgZGlzcGxheUNvbG9ycywgYm94SGVpZ2h0LCBib3hXaWR0aH0gPSBvcHRpb25zO1xuICAgIGNvbnN0IGJvZHlGb250ID0gdG9Gb250KG9wdGlvbnMuYm9keUZvbnQpO1xuICAgIGxldCBib2R5TGluZUhlaWdodCA9IGJvZHlGb250LmxpbmVIZWlnaHQ7XG4gICAgbGV0IHhMaW5lUGFkZGluZyA9IDA7XG4gICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRpb25zLnJ0bCwgbWUueCwgbWUud2lkdGgpO1xuICAgIGNvbnN0IGZpbGxMaW5lT2ZUZXh0ID0gZnVuY3Rpb24obGluZSkge1xuICAgICAgY3R4LmZpbGxUZXh0KGxpbmUsIHJ0bEhlbHBlci54KHB0LnggKyB4TGluZVBhZGRpbmcpLCBwdC55ICsgYm9keUxpbmVIZWlnaHQgLyAyKTtcbiAgICAgIHB0LnkgKz0gYm9keUxpbmVIZWlnaHQgKyBib2R5U3BhY2luZztcbiAgICB9O1xuICAgIGNvbnN0IGJvZHlBbGlnbkZvckNhbGN1bGF0aW9uID0gcnRsSGVscGVyLnRleHRBbGlnbihib2R5QWxpZ24pO1xuICAgIGxldCBib2R5SXRlbSwgdGV4dENvbG9yLCBsaW5lcywgaSwgaiwgaWxlbiwgamxlbjtcbiAgICBjdHgudGV4dEFsaWduID0gYm9keUFsaWduO1xuICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICBjdHguZm9udCA9IGJvZHlGb250LnN0cmluZztcbiAgICBwdC54ID0gZ2V0QWxpZ25lZFgobWUsIGJvZHlBbGlnbkZvckNhbGN1bGF0aW9uLCBvcHRpb25zKTtcbiAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5ib2R5Q29sb3I7XG4gICAgZWFjaChtZS5iZWZvcmVCb2R5LCBmaWxsTGluZU9mVGV4dCk7XG4gICAgeExpbmVQYWRkaW5nID0gZGlzcGxheUNvbG9ycyAmJiBib2R5QWxpZ25Gb3JDYWxjdWxhdGlvbiAhPT0gJ3JpZ2h0J1xuICAgICAgPyBib2R5QWxpZ24gPT09ICdjZW50ZXInID8gKGJveFdpZHRoIC8gMiArIDEpIDogKGJveFdpZHRoICsgMilcbiAgICAgIDogMDtcbiAgICBmb3IgKGkgPSAwLCBpbGVuID0gYm9keS5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIGJvZHlJdGVtID0gYm9keVtpXTtcbiAgICAgIHRleHRDb2xvciA9IG1lLmxhYmVsVGV4dENvbG9yc1tpXTtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSB0ZXh0Q29sb3I7XG4gICAgICBlYWNoKGJvZHlJdGVtLmJlZm9yZSwgZmlsbExpbmVPZlRleHQpO1xuICAgICAgbGluZXMgPSBib2R5SXRlbS5saW5lcztcbiAgICAgIGlmIChkaXNwbGF5Q29sb3JzICYmIGxpbmVzLmxlbmd0aCkge1xuICAgICAgICBtZS5fZHJhd0NvbG9yQm94KGN0eCwgcHQsIGksIHJ0bEhlbHBlciwgb3B0aW9ucyk7XG4gICAgICAgIGJvZHlMaW5lSGVpZ2h0ID0gTWF0aC5tYXgoYm9keUZvbnQubGluZUhlaWdodCwgYm94SGVpZ2h0KTtcbiAgICAgIH1cbiAgICAgIGZvciAoaiA9IDAsIGpsZW4gPSBsaW5lcy5sZW5ndGg7IGogPCBqbGVuOyArK2opIHtcbiAgICAgICAgZmlsbExpbmVPZlRleHQobGluZXNbal0pO1xuICAgICAgICBib2R5TGluZUhlaWdodCA9IGJvZHlGb250LmxpbmVIZWlnaHQ7XG4gICAgICB9XG4gICAgICBlYWNoKGJvZHlJdGVtLmFmdGVyLCBmaWxsTGluZU9mVGV4dCk7XG4gICAgfVxuICAgIHhMaW5lUGFkZGluZyA9IDA7XG4gICAgYm9keUxpbmVIZWlnaHQgPSBib2R5Rm9udC5saW5lSGVpZ2h0O1xuICAgIGVhY2gobWUuYWZ0ZXJCb2R5LCBmaWxsTGluZU9mVGV4dCk7XG4gICAgcHQueSAtPSBib2R5U3BhY2luZztcbiAgfVxuICBkcmF3Rm9vdGVyKHB0LCBjdHgsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgZm9vdGVyID0gbWUuZm9vdGVyO1xuICAgIGNvbnN0IGxlbmd0aCA9IGZvb3Rlci5sZW5ndGg7XG4gICAgbGV0IGZvb3RlckZvbnQsIGk7XG4gICAgaWYgKGxlbmd0aCkge1xuICAgICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRpb25zLnJ0bCwgbWUueCwgbWUud2lkdGgpO1xuICAgICAgcHQueCA9IGdldEFsaWduZWRYKG1lLCBvcHRpb25zLmZvb3RlckFsaWduLCBvcHRpb25zKTtcbiAgICAgIHB0LnkgKz0gb3B0aW9ucy5mb290ZXJNYXJnaW5Ub3A7XG4gICAgICBjdHgudGV4dEFsaWduID0gcnRsSGVscGVyLnRleHRBbGlnbihvcHRpb25zLmZvb3RlckFsaWduKTtcbiAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgIGZvb3RlckZvbnQgPSB0b0ZvbnQob3B0aW9ucy5mb290ZXJGb250KTtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLmZvb3RlckNvbG9yO1xuICAgICAgY3R4LmZvbnQgPSBmb290ZXJGb250LnN0cmluZztcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgICAgICBjdHguZmlsbFRleHQoZm9vdGVyW2ldLCBydGxIZWxwZXIueChwdC54KSwgcHQueSArIGZvb3RlckZvbnQubGluZUhlaWdodCAvIDIpO1xuICAgICAgICBwdC55ICs9IGZvb3RlckZvbnQubGluZUhlaWdodCArIG9wdGlvbnMuZm9vdGVyU3BhY2luZztcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZHJhd0JhY2tncm91bmQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpIHtcbiAgICBjb25zdCB7eEFsaWduLCB5QWxpZ259ID0gdGhpcztcbiAgICBjb25zdCB7eCwgeX0gPSBwdDtcbiAgICBjb25zdCB7d2lkdGgsIGhlaWdodH0gPSB0b29sdGlwU2l6ZTtcbiAgICBjb25zdCByYWRpdXMgPSBvcHRpb25zLmNvcm5lclJhZGl1cztcbiAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgY3R4LnN0cm9rZVN0eWxlID0gb3B0aW9ucy5ib3JkZXJDb2xvcjtcbiAgICBjdHgubGluZVdpZHRoID0gb3B0aW9ucy5ib3JkZXJXaWR0aDtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4Lm1vdmVUbyh4ICsgcmFkaXVzLCB5KTtcbiAgICBpZiAoeUFsaWduID09PSAndG9wJykge1xuICAgICAgdGhpcy5kcmF3Q2FyZXQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpO1xuICAgIH1cbiAgICBjdHgubGluZVRvKHggKyB3aWR0aCAtIHJhZGl1cywgeSk7XG4gICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCArIHdpZHRoLCB5LCB4ICsgd2lkdGgsIHkgKyByYWRpdXMpO1xuICAgIGlmICh5QWxpZ24gPT09ICdjZW50ZXInICYmIHhBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgdGhpcy5kcmF3Q2FyZXQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpO1xuICAgIH1cbiAgICBjdHgubGluZVRvKHggKyB3aWR0aCwgeSArIGhlaWdodCAtIHJhZGl1cyk7XG4gICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCArIHdpZHRoLCB5ICsgaGVpZ2h0LCB4ICsgd2lkdGggLSByYWRpdXMsIHkgKyBoZWlnaHQpO1xuICAgIGlmICh5QWxpZ24gPT09ICdib3R0b20nKSB7XG4gICAgICB0aGlzLmRyYXdDYXJldChwdCwgY3R4LCB0b29sdGlwU2l6ZSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIGN0eC5saW5lVG8oeCArIHJhZGl1cywgeSArIGhlaWdodCk7XG4gICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCwgeSArIGhlaWdodCwgeCwgeSArIGhlaWdodCAtIHJhZGl1cyk7XG4gICAgaWYgKHlBbGlnbiA9PT0gJ2NlbnRlcicgJiYgeEFsaWduID09PSAnbGVmdCcpIHtcbiAgICAgIHRoaXMuZHJhd0NhcmV0KHB0LCBjdHgsIHRvb2x0aXBTaXplLCBvcHRpb25zKTtcbiAgICB9XG4gICAgY3R4LmxpbmVUbyh4LCB5ICsgcmFkaXVzKTtcbiAgICBjdHgucXVhZHJhdGljQ3VydmVUbyh4LCB5LCB4ICsgcmFkaXVzLCB5KTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgY3R4LmZpbGwoKTtcbiAgICBpZiAob3B0aW9ucy5ib3JkZXJXaWR0aCA+IDApIHtcbiAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG4gIH1cbiAgX3VwZGF0ZUFuaW1hdGlvblRhcmdldChvcHRpb25zKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGNoYXJ0ID0gbWUuX2NoYXJ0O1xuICAgIGNvbnN0IGFuaW1zID0gbWUuJGFuaW1hdGlvbnM7XG4gICAgY29uc3QgYW5pbVggPSBhbmltcyAmJiBhbmltcy54O1xuICAgIGNvbnN0IGFuaW1ZID0gYW5pbXMgJiYgYW5pbXMueTtcbiAgICBpZiAoYW5pbVggfHwgYW5pbVkpIHtcbiAgICAgIGNvbnN0IHBvc2l0aW9uID0gcG9zaXRpb25lcnNbb3B0aW9ucy5wb3NpdGlvbl0uY2FsbChtZSwgbWUuX2FjdGl2ZSwgbWUuX2V2ZW50UG9zaXRpb24pO1xuICAgICAgaWYgKCFwb3NpdGlvbikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBzaXplID0gbWUuX3NpemUgPSBnZXRUb29sdGlwU2l6ZShtZSwgb3B0aW9ucyk7XG4gICAgICBjb25zdCBwb3NpdGlvbkFuZFNpemUgPSBPYmplY3QuYXNzaWduKHt9LCBwb3NpdGlvbiwgbWUuX3NpemUpO1xuICAgICAgY29uc3QgYWxpZ25tZW50ID0gZGV0ZXJtaW5lQWxpZ25tZW50KGNoYXJ0LCBvcHRpb25zLCBwb3NpdGlvbkFuZFNpemUpO1xuICAgICAgY29uc3QgcG9pbnQgPSBnZXRCYWNrZ3JvdW5kUG9pbnQob3B0aW9ucywgcG9zaXRpb25BbmRTaXplLCBhbGlnbm1lbnQsIGNoYXJ0KTtcbiAgICAgIGlmIChhbmltWC5fdG8gIT09IHBvaW50LnggfHwgYW5pbVkuX3RvICE9PSBwb2ludC55KSB7XG4gICAgICAgIG1lLnhBbGlnbiA9IGFsaWdubWVudC54QWxpZ247XG4gICAgICAgIG1lLnlBbGlnbiA9IGFsaWdubWVudC55QWxpZ247XG4gICAgICAgIG1lLndpZHRoID0gc2l6ZS53aWR0aDtcbiAgICAgICAgbWUuaGVpZ2h0ID0gc2l6ZS5oZWlnaHQ7XG4gICAgICAgIG1lLmNhcmV0WCA9IHBvc2l0aW9uLng7XG4gICAgICAgIG1lLmNhcmV0WSA9IHBvc2l0aW9uLnk7XG4gICAgICAgIG1lLl9yZXNvbHZlQW5pbWF0aW9ucygpLnVwZGF0ZShtZSwgcG9pbnQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBkcmF3KGN0eCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRpb25zID0gbWUub3B0aW9ucy5zZXRDb250ZXh0KG1lLmdldENvbnRleHQoKSk7XG4gICAgbGV0IG9wYWNpdHkgPSBtZS5vcGFjaXR5O1xuICAgIGlmICghb3BhY2l0eSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBtZS5fdXBkYXRlQW5pbWF0aW9uVGFyZ2V0KG9wdGlvbnMpO1xuICAgIGNvbnN0IHRvb2x0aXBTaXplID0ge1xuICAgICAgd2lkdGg6IG1lLndpZHRoLFxuICAgICAgaGVpZ2h0OiBtZS5oZWlnaHRcbiAgICB9O1xuICAgIGNvbnN0IHB0ID0ge1xuICAgICAgeDogbWUueCxcbiAgICAgIHk6IG1lLnlcbiAgICB9O1xuICAgIG9wYWNpdHkgPSBNYXRoLmFicyhvcGFjaXR5KSA8IDFlLTMgPyAwIDogb3BhY2l0eTtcbiAgICBjb25zdCBwYWRkaW5nID0gdG9QYWRkaW5nKG9wdGlvbnMucGFkZGluZyk7XG4gICAgY29uc3QgaGFzVG9vbHRpcENvbnRlbnQgPSBtZS50aXRsZS5sZW5ndGggfHwgbWUuYmVmb3JlQm9keS5sZW5ndGggfHwgbWUuYm9keS5sZW5ndGggfHwgbWUuYWZ0ZXJCb2R5Lmxlbmd0aCB8fCBtZS5mb290ZXIubGVuZ3RoO1xuICAgIGlmIChvcHRpb25zLmVuYWJsZWQgJiYgaGFzVG9vbHRpcENvbnRlbnQpIHtcbiAgICAgIGN0eC5zYXZlKCk7XG4gICAgICBjdHguZ2xvYmFsQWxwaGEgPSBvcGFjaXR5O1xuICAgICAgbWUuZHJhd0JhY2tncm91bmQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpO1xuICAgICAgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uKGN0eCwgb3B0aW9ucy50ZXh0RGlyZWN0aW9uKTtcbiAgICAgIHB0LnkgKz0gcGFkZGluZy50b3A7XG4gICAgICBtZS5kcmF3VGl0bGUocHQsIGN0eCwgb3B0aW9ucyk7XG4gICAgICBtZS5kcmF3Qm9keShwdCwgY3R4LCBvcHRpb25zKTtcbiAgICAgIG1lLmRyYXdGb290ZXIocHQsIGN0eCwgb3B0aW9ucyk7XG4gICAgICByZXN0b3JlVGV4dERpcmVjdGlvbihjdHgsIG9wdGlvbnMudGV4dERpcmVjdGlvbik7XG4gICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH1cbiAgfVxuICBnZXRBY3RpdmVFbGVtZW50cygpIHtcbiAgICByZXR1cm4gdGhpcy5fYWN0aXZlIHx8IFtdO1xuICB9XG4gIHNldEFjdGl2ZUVsZW1lbnRzKGFjdGl2ZUVsZW1lbnRzLCBldmVudFBvc2l0aW9uKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGxhc3RBY3RpdmUgPSBtZS5fYWN0aXZlO1xuICAgIGNvbnN0IGFjdGl2ZSA9IGFjdGl2ZUVsZW1lbnRzLm1hcCgoe2RhdGFzZXRJbmRleCwgaW5kZXh9KSA9PiB7XG4gICAgICBjb25zdCBtZXRhID0gbWUuX2NoYXJ0LmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCk7XG4gICAgICBpZiAoIW1ldGEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBhIGRhdGFzZXQgYXQgaW5kZXggJyArIGRhdGFzZXRJbmRleCk7XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgIGVsZW1lbnQ6IG1ldGEuZGF0YVtpbmRleF0sXG4gICAgICAgIGluZGV4LFxuICAgICAgfTtcbiAgICB9KTtcbiAgICBjb25zdCBjaGFuZ2VkID0gIV9lbGVtZW50c0VxdWFsKGxhc3RBY3RpdmUsIGFjdGl2ZSk7XG4gICAgY29uc3QgcG9zaXRpb25DaGFuZ2VkID0gbWUuX3Bvc2l0aW9uQ2hhbmdlZChhY3RpdmUsIGV2ZW50UG9zaXRpb24pO1xuICAgIGlmIChjaGFuZ2VkIHx8IHBvc2l0aW9uQ2hhbmdlZCkge1xuICAgICAgbWUuX2FjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgIG1lLl9ldmVudFBvc2l0aW9uID0gZXZlbnRQb3NpdGlvbjtcbiAgICAgIG1lLnVwZGF0ZSh0cnVlKTtcbiAgICB9XG4gIH1cbiAgaGFuZGxlRXZlbnQoZSwgcmVwbGF5KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IGxhc3RBY3RpdmUgPSBtZS5fYWN0aXZlIHx8IFtdO1xuICAgIGxldCBjaGFuZ2VkID0gZmFsc2U7XG4gICAgbGV0IGFjdGl2ZSA9IFtdO1xuICAgIGlmIChlLnR5cGUgIT09ICdtb3VzZW91dCcpIHtcbiAgICAgIGFjdGl2ZSA9IG1lLl9jaGFydC5nZXRFbGVtZW50c0F0RXZlbnRGb3JNb2RlKGUsIG9wdGlvbnMubW9kZSwgb3B0aW9ucywgcmVwbGF5KTtcbiAgICAgIGlmIChvcHRpb25zLnJldmVyc2UpIHtcbiAgICAgICAgYWN0aXZlLnJldmVyc2UoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcG9zaXRpb25DaGFuZ2VkID0gbWUuX3Bvc2l0aW9uQ2hhbmdlZChhY3RpdmUsIGUpO1xuICAgIGNoYW5nZWQgPSByZXBsYXkgfHwgIV9lbGVtZW50c0VxdWFsKGFjdGl2ZSwgbGFzdEFjdGl2ZSkgfHwgcG9zaXRpb25DaGFuZ2VkO1xuICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICBtZS5fYWN0aXZlID0gYWN0aXZlO1xuICAgICAgaWYgKG9wdGlvbnMuZW5hYmxlZCB8fCBvcHRpb25zLmV4dGVybmFsKSB7XG4gICAgICAgIG1lLl9ldmVudFBvc2l0aW9uID0ge1xuICAgICAgICAgIHg6IGUueCxcbiAgICAgICAgICB5OiBlLnlcbiAgICAgICAgfTtcbiAgICAgICAgbWUudXBkYXRlKHRydWUsIHJlcGxheSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjaGFuZ2VkO1xuICB9XG4gIF9wb3NpdGlvbkNoYW5nZWQoYWN0aXZlLCBlKSB7XG4gICAgY29uc3Qge2NhcmV0WCwgY2FyZXRZLCBvcHRpb25zfSA9IHRoaXM7XG4gICAgY29uc3QgcG9zaXRpb24gPSBwb3NpdGlvbmVyc1tvcHRpb25zLnBvc2l0aW9uXS5jYWxsKHRoaXMsIGFjdGl2ZSwgZSk7XG4gICAgcmV0dXJuIHBvc2l0aW9uICE9PSBmYWxzZSAmJiAoY2FyZXRYICE9PSBwb3NpdGlvbi54IHx8IGNhcmV0WSAhPT0gcG9zaXRpb24ueSk7XG4gIH1cbn1cblRvb2x0aXAucG9zaXRpb25lcnMgPSBwb3NpdGlvbmVycztcbnZhciBwbHVnaW5fdG9vbHRpcCA9IHtcbiAgaWQ6ICd0b29sdGlwJyxcbiAgX2VsZW1lbnQ6IFRvb2x0aXAsXG4gIHBvc2l0aW9uZXJzLFxuICBhZnRlckluaXQoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgIGNoYXJ0LnRvb2x0aXAgPSBuZXcgVG9vbHRpcCh7X2NoYXJ0OiBjaGFydCwgb3B0aW9uc30pO1xuICAgIH1cbiAgfSxcbiAgYmVmb3JlVXBkYXRlKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgIGlmIChjaGFydC50b29sdGlwKSB7XG4gICAgICBjaGFydC50b29sdGlwLmluaXRpYWxpemUob3B0aW9ucyk7XG4gICAgfVxuICB9LFxuICByZXNldChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICBpZiAoY2hhcnQudG9vbHRpcCkge1xuICAgICAgY2hhcnQudG9vbHRpcC5pbml0aWFsaXplKG9wdGlvbnMpO1xuICAgIH1cbiAgfSxcbiAgYWZ0ZXJEcmF3KGNoYXJ0KSB7XG4gICAgY29uc3QgdG9vbHRpcCA9IGNoYXJ0LnRvb2x0aXA7XG4gICAgY29uc3QgYXJncyA9IHtcbiAgICAgIHRvb2x0aXBcbiAgICB9O1xuICAgIGlmIChjaGFydC5ub3RpZnlQbHVnaW5zKCdiZWZvcmVUb29sdGlwRHJhdycsIGFyZ3MpID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodG9vbHRpcCkge1xuICAgICAgdG9vbHRpcC5kcmF3KGNoYXJ0LmN0eCk7XG4gICAgfVxuICAgIGNoYXJ0Lm5vdGlmeVBsdWdpbnMoJ2FmdGVyVG9vbHRpcERyYXcnLCBhcmdzKTtcbiAgfSxcbiAgYWZ0ZXJFdmVudChjaGFydCwgYXJncykge1xuICAgIGlmIChjaGFydC50b29sdGlwKSB7XG4gICAgICBjb25zdCB1c2VGaW5hbFBvc2l0aW9uID0gYXJncy5yZXBsYXk7XG4gICAgICBpZiAoY2hhcnQudG9vbHRpcC5oYW5kbGVFdmVudChhcmdzLmV2ZW50LCB1c2VGaW5hbFBvc2l0aW9uKSkge1xuICAgICAgICBhcmdzLmNoYW5nZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgZGVmYXVsdHM6IHtcbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIGV4dGVybmFsOiBudWxsLFxuICAgIHBvc2l0aW9uOiAnYXZlcmFnZScsXG4gICAgYmFja2dyb3VuZENvbG9yOiAncmdiYSgwLDAsMCwwLjgpJyxcbiAgICB0aXRsZUNvbG9yOiAnI2ZmZicsXG4gICAgdGl0bGVGb250OiB7XG4gICAgICB3ZWlnaHQ6ICdib2xkJyxcbiAgICB9LFxuICAgIHRpdGxlU3BhY2luZzogMixcbiAgICB0aXRsZU1hcmdpbkJvdHRvbTogNixcbiAgICB0aXRsZUFsaWduOiAnbGVmdCcsXG4gICAgYm9keUNvbG9yOiAnI2ZmZicsXG4gICAgYm9keVNwYWNpbmc6IDIsXG4gICAgYm9keUZvbnQ6IHtcbiAgICB9LFxuICAgIGJvZHlBbGlnbjogJ2xlZnQnLFxuICAgIGZvb3RlckNvbG9yOiAnI2ZmZicsXG4gICAgZm9vdGVyU3BhY2luZzogMixcbiAgICBmb290ZXJNYXJnaW5Ub3A6IDYsXG4gICAgZm9vdGVyRm9udDoge1xuICAgICAgd2VpZ2h0OiAnYm9sZCcsXG4gICAgfSxcbiAgICBmb290ZXJBbGlnbjogJ2xlZnQnLFxuICAgIHBhZGRpbmc6IDYsXG4gICAgY2FyZXRQYWRkaW5nOiAyLFxuICAgIGNhcmV0U2l6ZTogNSxcbiAgICBjb3JuZXJSYWRpdXM6IDYsXG4gICAgYm94SGVpZ2h0OiAoY3R4LCBvcHRzKSA9PiBvcHRzLmJvZHlGb250LnNpemUsXG4gICAgYm94V2lkdGg6IChjdHgsIG9wdHMpID0+IG9wdHMuYm9keUZvbnQuc2l6ZSxcbiAgICBtdWx0aUtleUJhY2tncm91bmQ6ICcjZmZmJyxcbiAgICBkaXNwbGF5Q29sb3JzOiB0cnVlLFxuICAgIGJvcmRlckNvbG9yOiAncmdiYSgwLDAsMCwwKScsXG4gICAgYm9yZGVyV2lkdGg6IDAsXG4gICAgYW5pbWF0aW9uOiB7XG4gICAgICBkdXJhdGlvbjogNDAwLFxuICAgICAgZWFzaW5nOiAnZWFzZU91dFF1YXJ0JyxcbiAgICB9LFxuICAgIGFuaW1hdGlvbnM6IHtcbiAgICAgIG51bWJlcnM6IHtcbiAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgIHByb3BlcnRpZXM6IFsneCcsICd5JywgJ3dpZHRoJywgJ2hlaWdodCcsICdjYXJldFgnLCAnY2FyZXRZJ10sXG4gICAgICB9LFxuICAgICAgb3BhY2l0eToge1xuICAgICAgICBlYXNpbmc6ICdsaW5lYXInLFxuICAgICAgICBkdXJhdGlvbjogMjAwXG4gICAgICB9XG4gICAgfSxcbiAgICBjYWxsYmFja3M6IHtcbiAgICAgIGJlZm9yZVRpdGxlOiBub29wLFxuICAgICAgdGl0bGUodG9vbHRpcEl0ZW1zKSB7XG4gICAgICAgIGlmICh0b29sdGlwSXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IGl0ZW0gPSB0b29sdGlwSXRlbXNbMF07XG4gICAgICAgICAgY29uc3QgbGFiZWxzID0gaXRlbS5jaGFydC5kYXRhLmxhYmVscztcbiAgICAgICAgICBjb25zdCBsYWJlbENvdW50ID0gbGFiZWxzID8gbGFiZWxzLmxlbmd0aCA6IDA7XG4gICAgICAgICAgaWYgKHRoaXMgJiYgdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5tb2RlID09PSAnZGF0YXNldCcpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLmRhdGFzZXQubGFiZWwgfHwgJyc7XG4gICAgICAgICAgfSBlbHNlIGlmIChpdGVtLmxhYmVsKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbS5sYWJlbDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGxhYmVsQ291bnQgPiAwICYmIGl0ZW0uZGF0YUluZGV4IDwgbGFiZWxDb3VudCkge1xuICAgICAgICAgICAgcmV0dXJuIGxhYmVsc1tpdGVtLmRhdGFJbmRleF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH0sXG4gICAgICBhZnRlclRpdGxlOiBub29wLFxuICAgICAgYmVmb3JlQm9keTogbm9vcCxcbiAgICAgIGJlZm9yZUxhYmVsOiBub29wLFxuICAgICAgbGFiZWwodG9vbHRpcEl0ZW0pIHtcbiAgICAgICAgaWYgKHRoaXMgJiYgdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5tb2RlID09PSAnZGF0YXNldCcpIHtcbiAgICAgICAgICByZXR1cm4gdG9vbHRpcEl0ZW0ubGFiZWwgKyAnOiAnICsgdG9vbHRpcEl0ZW0uZm9ybWF0dGVkVmFsdWUgfHwgdG9vbHRpcEl0ZW0uZm9ybWF0dGVkVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGxhYmVsID0gdG9vbHRpcEl0ZW0uZGF0YXNldC5sYWJlbCB8fCAnJztcbiAgICAgICAgaWYgKGxhYmVsKSB7XG4gICAgICAgICAgbGFiZWwgKz0gJzogJztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWx1ZSA9IHRvb2x0aXBJdGVtLmZvcm1hdHRlZFZhbHVlO1xuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWYodmFsdWUpKSB7XG4gICAgICAgICAgbGFiZWwgKz0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxhYmVsO1xuICAgICAgfSxcbiAgICAgIGxhYmVsQ29sb3IodG9vbHRpcEl0ZW0pIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRvb2x0aXBJdGVtLmNoYXJ0LmdldERhdGFzZXRNZXRhKHRvb2x0aXBJdGVtLmRhdGFzZXRJbmRleCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSBtZXRhLmNvbnRyb2xsZXIuZ2V0U3R5bGUodG9vbHRpcEl0ZW0uZGF0YUluZGV4KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBib3JkZXJDb2xvcjogb3B0aW9ucy5ib3JkZXJDb2xvcixcbiAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgIGJvcmRlcldpZHRoOiBvcHRpb25zLmJvcmRlcldpZHRoLFxuICAgICAgICAgIGJvcmRlckRhc2g6IG9wdGlvbnMuYm9yZGVyRGFzaCxcbiAgICAgICAgICBib3JkZXJEYXNoT2Zmc2V0OiBvcHRpb25zLmJvcmRlckRhc2hPZmZzZXQsXG4gICAgICAgICAgYm9yZGVyUmFkaXVzOiAwLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIGxhYmVsVGV4dENvbG9yKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmJvZHlDb2xvcjtcbiAgICAgIH0sXG4gICAgICBsYWJlbFBvaW50U3R5bGUodG9vbHRpcEl0ZW0pIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRvb2x0aXBJdGVtLmNoYXJ0LmdldERhdGFzZXRNZXRhKHRvb2x0aXBJdGVtLmRhdGFzZXRJbmRleCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSBtZXRhLmNvbnRyb2xsZXIuZ2V0U3R5bGUodG9vbHRpcEl0ZW0uZGF0YUluZGV4KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwb2ludFN0eWxlOiBvcHRpb25zLnBvaW50U3R5bGUsXG4gICAgICAgICAgcm90YXRpb246IG9wdGlvbnMucm90YXRpb24sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgYWZ0ZXJMYWJlbDogbm9vcCxcbiAgICAgIGFmdGVyQm9keTogbm9vcCxcbiAgICAgIGJlZm9yZUZvb3Rlcjogbm9vcCxcbiAgICAgIGZvb3Rlcjogbm9vcCxcbiAgICAgIGFmdGVyRm9vdGVyOiBub29wXG4gICAgfVxuICB9LFxuICBkZWZhdWx0Um91dGVzOiB7XG4gICAgYm9keUZvbnQ6ICdmb250JyxcbiAgICBmb290ZXJGb250OiAnZm9udCcsXG4gICAgdGl0bGVGb250OiAnZm9udCdcbiAgfSxcbiAgZGVzY3JpcHRvcnM6IHtcbiAgICBfc2NyaXB0YWJsZTogKG5hbWUpID0+IG5hbWUgIT09ICdmaWx0ZXInICYmIG5hbWUgIT09ICdpdGVtU29ydCcgJiYgbmFtZSAhPT0gJ2V4dGVybmFsJyxcbiAgICBfaW5kZXhhYmxlOiBmYWxzZSxcbiAgICBjYWxsYmFja3M6IHtcbiAgICAgIF9zY3JpcHRhYmxlOiBmYWxzZSxcbiAgICAgIF9pbmRleGFibGU6IGZhbHNlLFxuICAgIH0sXG4gICAgYW5pbWF0aW9uOiB7XG4gICAgICBfZmFsbGJhY2s6IGZhbHNlXG4gICAgfSxcbiAgICBhbmltYXRpb25zOiB7XG4gICAgICBfZmFsbGJhY2s6ICdhbmltYXRpb24nXG4gICAgfVxuICB9LFxuICBhZGRpdGlvbmFsT3B0aW9uU2NvcGVzOiBbJ2ludGVyYWN0aW9uJ11cbn07XG5cbnZhciBwbHVnaW5zID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuX19wcm90b19fOiBudWxsLFxuRGVjaW1hdGlvbjogcGx1Z2luX2RlY2ltYXRpb24sXG5GaWxsZXI6IHBsdWdpbl9maWxsZXIsXG5MZWdlbmQ6IHBsdWdpbl9sZWdlbmQsXG5TdWJUaXRsZTogcGx1Z2luX3N1YnRpdGxlLFxuVGl0bGU6IHBsdWdpbl90aXRsZSxcblRvb2x0aXA6IHBsdWdpbl90b29sdGlwXG59KTtcblxuY29uc3QgYWRkSWZTdHJpbmcgPSAobGFiZWxzLCByYXcsIGluZGV4KSA9PiB0eXBlb2YgcmF3ID09PSAnc3RyaW5nJ1xuICA/IGxhYmVscy5wdXNoKHJhdykgLSAxXG4gIDogaXNOYU4ocmF3KSA/IG51bGwgOiBpbmRleDtcbmZ1bmN0aW9uIGZpbmRPckFkZExhYmVsKGxhYmVscywgcmF3LCBpbmRleCkge1xuICBjb25zdCBmaXJzdCA9IGxhYmVscy5pbmRleE9mKHJhdyk7XG4gIGlmIChmaXJzdCA9PT0gLTEpIHtcbiAgICByZXR1cm4gYWRkSWZTdHJpbmcobGFiZWxzLCByYXcsIGluZGV4KTtcbiAgfVxuICBjb25zdCBsYXN0ID0gbGFiZWxzLmxhc3RJbmRleE9mKHJhdyk7XG4gIHJldHVybiBmaXJzdCAhPT0gbGFzdCA/IGluZGV4IDogZmlyc3Q7XG59XG5jb25zdCB2YWxpZEluZGV4ID0gKGluZGV4LCBtYXgpID0+IGluZGV4ID09PSBudWxsID8gbnVsbCA6IF9saW1pdFZhbHVlKE1hdGgucm91bmQoaW5kZXgpLCAwLCBtYXgpO1xuY2xhc3MgQ2F0ZWdvcnlTY2FsZSBleHRlbmRzIFNjYWxlIHtcbiAgY29uc3RydWN0b3IoY2ZnKSB7XG4gICAgc3VwZXIoY2ZnKTtcbiAgICB0aGlzLl9zdGFydFZhbHVlID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3ZhbHVlUmFuZ2UgPSAwO1xuICB9XG4gIHBhcnNlKHJhdywgaW5kZXgpIHtcbiAgICBpZiAoaXNOdWxsT3JVbmRlZihyYXcpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgbGFiZWxzID0gdGhpcy5nZXRMYWJlbHMoKTtcbiAgICBpbmRleCA9IGlzRmluaXRlKGluZGV4KSAmJiBsYWJlbHNbaW5kZXhdID09PSByYXcgPyBpbmRleFxuICAgICAgOiBmaW5kT3JBZGRMYWJlbChsYWJlbHMsIHJhdywgdmFsdWVPckRlZmF1bHQoaW5kZXgsIHJhdykpO1xuICAgIHJldHVybiB2YWxpZEluZGV4KGluZGV4LCBsYWJlbHMubGVuZ3RoIC0gMSk7XG4gIH1cbiAgZGV0ZXJtaW5lRGF0YUxpbWl0cygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge21pbkRlZmluZWQsIG1heERlZmluZWR9ID0gbWUuZ2V0VXNlckJvdW5kcygpO1xuICAgIGxldCB7bWluLCBtYXh9ID0gbWUuZ2V0TWluTWF4KHRydWUpO1xuICAgIGlmIChtZS5vcHRpb25zLmJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgaWYgKCFtaW5EZWZpbmVkKSB7XG4gICAgICAgIG1pbiA9IDA7XG4gICAgICB9XG4gICAgICBpZiAoIW1heERlZmluZWQpIHtcbiAgICAgICAgbWF4ID0gbWUuZ2V0TGFiZWxzKCkubGVuZ3RoIC0gMTtcbiAgICAgIH1cbiAgICB9XG4gICAgbWUubWluID0gbWluO1xuICAgIG1lLm1heCA9IG1heDtcbiAgfVxuICBidWlsZFRpY2tzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBtaW4gPSBtZS5taW47XG4gICAgY29uc3QgbWF4ID0gbWUubWF4O1xuICAgIGNvbnN0IG9mZnNldCA9IG1lLm9wdGlvbnMub2Zmc2V0O1xuICAgIGNvbnN0IHRpY2tzID0gW107XG4gICAgbGV0IGxhYmVscyA9IG1lLmdldExhYmVscygpO1xuICAgIGxhYmVscyA9IChtaW4gPT09IDAgJiYgbWF4ID09PSBsYWJlbHMubGVuZ3RoIC0gMSkgPyBsYWJlbHMgOiBsYWJlbHMuc2xpY2UobWluLCBtYXggKyAxKTtcbiAgICBtZS5fdmFsdWVSYW5nZSA9IE1hdGgubWF4KGxhYmVscy5sZW5ndGggLSAob2Zmc2V0ID8gMCA6IDEpLCAxKTtcbiAgICBtZS5fc3RhcnRWYWx1ZSA9IG1lLm1pbiAtIChvZmZzZXQgPyAwLjUgOiAwKTtcbiAgICBmb3IgKGxldCB2YWx1ZSA9IG1pbjsgdmFsdWUgPD0gbWF4OyB2YWx1ZSsrKSB7XG4gICAgICB0aWNrcy5wdXNoKHt2YWx1ZX0pO1xuICAgIH1cbiAgICByZXR1cm4gdGlja3M7XG4gIH1cbiAgZ2V0TGFiZWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBsYWJlbHMgPSBtZS5nZXRMYWJlbHMoKTtcbiAgICBpZiAodmFsdWUgPj0gMCAmJiB2YWx1ZSA8IGxhYmVscy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBsYWJlbHNbdmFsdWVdO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgY29uZmlndXJlKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBzdXBlci5jb25maWd1cmUoKTtcbiAgICBpZiAoIW1lLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICBtZS5fcmV2ZXJzZVBpeGVscyA9ICFtZS5fcmV2ZXJzZVBpeGVscztcbiAgICB9XG4gIH1cbiAgZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJykge1xuICAgICAgdmFsdWUgPSBtZS5wYXJzZSh2YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbCA/IE5hTiA6IG1lLmdldFBpeGVsRm9yRGVjaW1hbCgodmFsdWUgLSBtZS5fc3RhcnRWYWx1ZSkgLyBtZS5fdmFsdWVSYW5nZSk7XG4gIH1cbiAgZ2V0UGl4ZWxGb3JUaWNrKGluZGV4KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHRpY2tzID0gbWUudGlja3M7XG4gICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+IHRpY2tzLmxlbmd0aCAtIDEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gbWUuZ2V0UGl4ZWxGb3JWYWx1ZSh0aWNrc1tpbmRleF0udmFsdWUpO1xuICB9XG4gIGdldFZhbHVlRm9yUGl4ZWwocGl4ZWwpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgcmV0dXJuIE1hdGgucm91bmQobWUuX3N0YXJ0VmFsdWUgKyBtZS5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpICogbWUuX3ZhbHVlUmFuZ2UpO1xuICB9XG4gIGdldEJhc2VQaXhlbCgpIHtcbiAgICByZXR1cm4gdGhpcy5ib3R0b207XG4gIH1cbn1cbkNhdGVnb3J5U2NhbGUuaWQgPSAnY2F0ZWdvcnknO1xuQ2F0ZWdvcnlTY2FsZS5kZWZhdWx0cyA9IHtcbiAgdGlja3M6IHtcbiAgICBjYWxsYmFjazogQ2F0ZWdvcnlTY2FsZS5wcm90b3R5cGUuZ2V0TGFiZWxGb3JWYWx1ZVxuICB9XG59O1xuXG5mdW5jdGlvbiBnZW5lcmF0ZVRpY2tzJDEoZ2VuZXJhdGlvbk9wdGlvbnMsIGRhdGFSYW5nZSkge1xuICBjb25zdCB0aWNrcyA9IFtdO1xuICBjb25zdCBNSU5fU1BBQ0lORyA9IDFlLTE0O1xuICBjb25zdCB7Ym91bmRzLCBzdGVwLCBtaW4sIG1heCwgcHJlY2lzaW9uLCBjb3VudCwgbWF4VGlja3MsIG1heERpZ2l0cywgaW5jbHVkZUJvdW5kc30gPSBnZW5lcmF0aW9uT3B0aW9ucztcbiAgY29uc3QgdW5pdCA9IHN0ZXAgfHwgMTtcbiAgY29uc3QgbWF4U3BhY2VzID0gbWF4VGlja3MgLSAxO1xuICBjb25zdCB7bWluOiBybWluLCBtYXg6IHJtYXh9ID0gZGF0YVJhbmdlO1xuICBjb25zdCBtaW5EZWZpbmVkID0gIWlzTnVsbE9yVW5kZWYobWluKTtcbiAgY29uc3QgbWF4RGVmaW5lZCA9ICFpc051bGxPclVuZGVmKG1heCk7XG4gIGNvbnN0IGNvdW50RGVmaW5lZCA9ICFpc051bGxPclVuZGVmKGNvdW50KTtcbiAgY29uc3QgbWluU3BhY2luZyA9IChybWF4IC0gcm1pbikgLyAobWF4RGlnaXRzICsgMSk7XG4gIGxldCBzcGFjaW5nID0gbmljZU51bSgocm1heCAtIHJtaW4pIC8gbWF4U3BhY2VzIC8gdW5pdCkgKiB1bml0O1xuICBsZXQgZmFjdG9yLCBuaWNlTWluLCBuaWNlTWF4LCBudW1TcGFjZXM7XG4gIGlmIChzcGFjaW5nIDwgTUlOX1NQQUNJTkcgJiYgIW1pbkRlZmluZWQgJiYgIW1heERlZmluZWQpIHtcbiAgICByZXR1cm4gW3t2YWx1ZTogcm1pbn0sIHt2YWx1ZTogcm1heH1dO1xuICB9XG4gIG51bVNwYWNlcyA9IE1hdGguY2VpbChybWF4IC8gc3BhY2luZykgLSBNYXRoLmZsb29yKHJtaW4gLyBzcGFjaW5nKTtcbiAgaWYgKG51bVNwYWNlcyA+IG1heFNwYWNlcykge1xuICAgIHNwYWNpbmcgPSBuaWNlTnVtKG51bVNwYWNlcyAqIHNwYWNpbmcgLyBtYXhTcGFjZXMgLyB1bml0KSAqIHVuaXQ7XG4gIH1cbiAgaWYgKCFpc051bGxPclVuZGVmKHByZWNpc2lvbikpIHtcbiAgICBmYWN0b3IgPSBNYXRoLnBvdygxMCwgcHJlY2lzaW9uKTtcbiAgICBzcGFjaW5nID0gTWF0aC5jZWlsKHNwYWNpbmcgKiBmYWN0b3IpIC8gZmFjdG9yO1xuICB9XG4gIGlmIChib3VuZHMgPT09ICd0aWNrcycpIHtcbiAgICBuaWNlTWluID0gTWF0aC5mbG9vcihybWluIC8gc3BhY2luZykgKiBzcGFjaW5nO1xuICAgIG5pY2VNYXggPSBNYXRoLmNlaWwocm1heCAvIHNwYWNpbmcpICogc3BhY2luZztcbiAgfSBlbHNlIHtcbiAgICBuaWNlTWluID0gcm1pbjtcbiAgICBuaWNlTWF4ID0gcm1heDtcbiAgfVxuICBpZiAobWluRGVmaW5lZCAmJiBtYXhEZWZpbmVkICYmIHN0ZXAgJiYgYWxtb3N0V2hvbGUoKG1heCAtIG1pbikgLyBzdGVwLCBzcGFjaW5nIC8gMTAwMCkpIHtcbiAgICBudW1TcGFjZXMgPSBNYXRoLnJvdW5kKE1hdGgubWluKChtYXggLSBtaW4pIC8gc3BhY2luZywgbWF4VGlja3MpKTtcbiAgICBzcGFjaW5nID0gKG1heCAtIG1pbikgLyBudW1TcGFjZXM7XG4gICAgbmljZU1pbiA9IG1pbjtcbiAgICBuaWNlTWF4ID0gbWF4O1xuICB9IGVsc2UgaWYgKGNvdW50RGVmaW5lZCkge1xuICAgIG5pY2VNaW4gPSBtaW5EZWZpbmVkID8gbWluIDogbmljZU1pbjtcbiAgICBuaWNlTWF4ID0gbWF4RGVmaW5lZCA/IG1heCA6IG5pY2VNYXg7XG4gICAgbnVtU3BhY2VzID0gY291bnQgLSAxO1xuICAgIHNwYWNpbmcgPSAobmljZU1heCAtIG5pY2VNaW4pIC8gbnVtU3BhY2VzO1xuICB9IGVsc2Uge1xuICAgIG51bVNwYWNlcyA9IChuaWNlTWF4IC0gbmljZU1pbikgLyBzcGFjaW5nO1xuICAgIGlmIChhbG1vc3RFcXVhbHMobnVtU3BhY2VzLCBNYXRoLnJvdW5kKG51bVNwYWNlcyksIHNwYWNpbmcgLyAxMDAwKSkge1xuICAgICAgbnVtU3BhY2VzID0gTWF0aC5yb3VuZChudW1TcGFjZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBudW1TcGFjZXMgPSBNYXRoLmNlaWwobnVtU3BhY2VzKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgZGVjaW1hbFBsYWNlcyA9IE1hdGgubWF4KFxuICAgIF9kZWNpbWFsUGxhY2VzKHNwYWNpbmcpLFxuICAgIF9kZWNpbWFsUGxhY2VzKG5pY2VNaW4pXG4gICk7XG4gIGZhY3RvciA9IE1hdGgucG93KDEwLCBpc051bGxPclVuZGVmKHByZWNpc2lvbikgPyBkZWNpbWFsUGxhY2VzIDogcHJlY2lzaW9uKTtcbiAgbmljZU1pbiA9IE1hdGgucm91bmQobmljZU1pbiAqIGZhY3RvcikgLyBmYWN0b3I7XG4gIG5pY2VNYXggPSBNYXRoLnJvdW5kKG5pY2VNYXggKiBmYWN0b3IpIC8gZmFjdG9yO1xuICBsZXQgaiA9IDA7XG4gIGlmIChtaW5EZWZpbmVkKSB7XG4gICAgaWYgKGluY2x1ZGVCb3VuZHMgJiYgbmljZU1pbiAhPT0gbWluKSB7XG4gICAgICB0aWNrcy5wdXNoKHt2YWx1ZTogbWlufSk7XG4gICAgICBpZiAobmljZU1pbiA8IG1pbikge1xuICAgICAgICBqKys7XG4gICAgICB9XG4gICAgICBpZiAoYWxtb3N0RXF1YWxzKE1hdGgucm91bmQoKG5pY2VNaW4gKyBqICogc3BhY2luZykgKiBmYWN0b3IpIC8gZmFjdG9yLCBtaW4sIHJlbGF0aXZlTGFiZWxTaXplKG1pbiwgbWluU3BhY2luZywgZ2VuZXJhdGlvbk9wdGlvbnMpKSkge1xuICAgICAgICBqKys7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChuaWNlTWluIDwgbWluKSB7XG4gICAgICBqKys7XG4gICAgfVxuICB9XG4gIGZvciAoOyBqIDwgbnVtU3BhY2VzOyArK2opIHtcbiAgICB0aWNrcy5wdXNoKHt2YWx1ZTogTWF0aC5yb3VuZCgobmljZU1pbiArIGogKiBzcGFjaW5nKSAqIGZhY3RvcikgLyBmYWN0b3J9KTtcbiAgfVxuICBpZiAobWF4RGVmaW5lZCAmJiBpbmNsdWRlQm91bmRzICYmIG5pY2VNYXggIT09IG1heCkge1xuICAgIGlmIChhbG1vc3RFcXVhbHModGlja3NbdGlja3MubGVuZ3RoIC0gMV0udmFsdWUsIG1heCwgcmVsYXRpdmVMYWJlbFNpemUobWF4LCBtaW5TcGFjaW5nLCBnZW5lcmF0aW9uT3B0aW9ucykpKSB7XG4gICAgICB0aWNrc1t0aWNrcy5sZW5ndGggLSAxXS52YWx1ZSA9IG1heDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGlja3MucHVzaCh7dmFsdWU6IG1heH0pO1xuICAgIH1cbiAgfSBlbHNlIGlmICghbWF4RGVmaW5lZCB8fCBuaWNlTWF4ID09PSBtYXgpIHtcbiAgICB0aWNrcy5wdXNoKHt2YWx1ZTogbmljZU1heH0pO1xuICB9XG4gIHJldHVybiB0aWNrcztcbn1cbmZ1bmN0aW9uIHJlbGF0aXZlTGFiZWxTaXplKHZhbHVlLCBtaW5TcGFjaW5nLCB7aG9yaXpvbnRhbCwgbWluUm90YXRpb259KSB7XG4gIGNvbnN0IHJhZCA9IHRvUmFkaWFucyhtaW5Sb3RhdGlvbik7XG4gIGNvbnN0IHJhdGlvID0gKGhvcml6b250YWwgPyBNYXRoLnNpbihyYWQpIDogTWF0aC5jb3MocmFkKSkgfHwgMC4wMDE7XG4gIGNvbnN0IGxlbmd0aCA9IDAuNzUgKiBtaW5TcGFjaW5nICogKCcnICsgdmFsdWUpLmxlbmd0aDtcbiAgcmV0dXJuIE1hdGgubWluKG1pblNwYWNpbmcgLyByYXRpbywgbGVuZ3RoKTtcbn1cbmNsYXNzIExpbmVhclNjYWxlQmFzZSBleHRlbmRzIFNjYWxlIHtcbiAgY29uc3RydWN0b3IoY2ZnKSB7XG4gICAgc3VwZXIoY2ZnKTtcbiAgICB0aGlzLnN0YXJ0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZW5kID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3N0YXJ0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fZW5kVmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fdmFsdWVSYW5nZSA9IDA7XG4gIH1cbiAgcGFyc2UocmF3LCBpbmRleCkge1xuICAgIGlmIChpc051bGxPclVuZGVmKHJhdykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoKHR5cGVvZiByYXcgPT09ICdudW1iZXInIHx8IHJhdyBpbnN0YW5jZW9mIE51bWJlcikgJiYgIWlzRmluaXRlKCtyYXcpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuICtyYXc7XG4gIH1cbiAgaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge2JlZ2luQXRaZXJvfSA9IG1lLm9wdGlvbnM7XG4gICAgY29uc3Qge21pbkRlZmluZWQsIG1heERlZmluZWR9ID0gbWUuZ2V0VXNlckJvdW5kcygpO1xuICAgIGxldCB7bWluLCBtYXh9ID0gbWU7XG4gICAgY29uc3Qgc2V0TWluID0gdiA9PiAobWluID0gbWluRGVmaW5lZCA/IG1pbiA6IHYpO1xuICAgIGNvbnN0IHNldE1heCA9IHYgPT4gKG1heCA9IG1heERlZmluZWQgPyBtYXggOiB2KTtcbiAgICBpZiAoYmVnaW5BdFplcm8pIHtcbiAgICAgIGNvbnN0IG1pblNpZ24gPSBzaWduKG1pbik7XG4gICAgICBjb25zdCBtYXhTaWduID0gc2lnbihtYXgpO1xuICAgICAgaWYgKG1pblNpZ24gPCAwICYmIG1heFNpZ24gPCAwKSB7XG4gICAgICAgIHNldE1heCgwKTtcbiAgICAgIH0gZWxzZSBpZiAobWluU2lnbiA+IDAgJiYgbWF4U2lnbiA+IDApIHtcbiAgICAgICAgc2V0TWluKDApO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobWluID09PSBtYXgpIHtcbiAgICAgIGxldCBvZmZzZXQgPSAxO1xuICAgICAgaWYgKG1heCA+PSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiB8fCBtaW4gPD0gTnVtYmVyLk1JTl9TQUZFX0lOVEVHRVIpIHtcbiAgICAgICAgb2Zmc2V0ID0gTWF0aC5hYnMobWF4ICogMC4wNSk7XG4gICAgICB9XG4gICAgICBzZXRNYXgobWF4ICsgb2Zmc2V0KTtcbiAgICAgIGlmICghYmVnaW5BdFplcm8pIHtcbiAgICAgICAgc2V0TWluKG1pbiAtIG9mZnNldCk7XG4gICAgICB9XG4gICAgfVxuICAgIG1lLm1pbiA9IG1pbjtcbiAgICBtZS5tYXggPSBtYXg7XG4gIH1cbiAgZ2V0VGlja0xpbWl0KCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB0aWNrT3B0cyA9IG1lLm9wdGlvbnMudGlja3M7XG4gICAgbGV0IHttYXhUaWNrc0xpbWl0LCBzdGVwU2l6ZX0gPSB0aWNrT3B0cztcbiAgICBsZXQgbWF4VGlja3M7XG4gICAgaWYgKHN0ZXBTaXplKSB7XG4gICAgICBtYXhUaWNrcyA9IE1hdGguY2VpbChtZS5tYXggLyBzdGVwU2l6ZSkgLSBNYXRoLmZsb29yKG1lLm1pbiAvIHN0ZXBTaXplKSArIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1heFRpY2tzID0gbWUuY29tcHV0ZVRpY2tMaW1pdCgpO1xuICAgICAgbWF4VGlja3NMaW1pdCA9IG1heFRpY2tzTGltaXQgfHwgMTE7XG4gICAgfVxuICAgIGlmIChtYXhUaWNrc0xpbWl0KSB7XG4gICAgICBtYXhUaWNrcyA9IE1hdGgubWluKG1heFRpY2tzTGltaXQsIG1heFRpY2tzKTtcbiAgICB9XG4gICAgcmV0dXJuIG1heFRpY2tzO1xuICB9XG4gIGNvbXB1dGVUaWNrTGltaXQoKSB7XG4gICAgcmV0dXJuIE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgfVxuICBidWlsZFRpY2tzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRzID0gbWUub3B0aW9ucztcbiAgICBjb25zdCB0aWNrT3B0cyA9IG9wdHMudGlja3M7XG4gICAgbGV0IG1heFRpY2tzID0gbWUuZ2V0VGlja0xpbWl0KCk7XG4gICAgbWF4VGlja3MgPSBNYXRoLm1heCgyLCBtYXhUaWNrcyk7XG4gICAgY29uc3QgbnVtZXJpY0dlbmVyYXRvck9wdGlvbnMgPSB7XG4gICAgICBtYXhUaWNrcyxcbiAgICAgIGJvdW5kczogb3B0cy5ib3VuZHMsXG4gICAgICBtaW46IG9wdHMubWluLFxuICAgICAgbWF4OiBvcHRzLm1heCxcbiAgICAgIHByZWNpc2lvbjogdGlja09wdHMucHJlY2lzaW9uLFxuICAgICAgc3RlcDogdGlja09wdHMuc3RlcFNpemUsXG4gICAgICBjb3VudDogdGlja09wdHMuY291bnQsXG4gICAgICBtYXhEaWdpdHM6IG1lLl9tYXhEaWdpdHMoKSxcbiAgICAgIGhvcml6b250YWw6IG1lLmlzSG9yaXpvbnRhbCgpLFxuICAgICAgbWluUm90YXRpb246IHRpY2tPcHRzLm1pblJvdGF0aW9uIHx8IDAsXG4gICAgICBpbmNsdWRlQm91bmRzOiB0aWNrT3B0cy5pbmNsdWRlQm91bmRzICE9PSBmYWxzZVxuICAgIH07XG4gICAgY29uc3QgZGF0YVJhbmdlID0gbWUuX3JhbmdlIHx8IG1lO1xuICAgIGNvbnN0IHRpY2tzID0gZ2VuZXJhdGVUaWNrcyQxKG51bWVyaWNHZW5lcmF0b3JPcHRpb25zLCBkYXRhUmFuZ2UpO1xuICAgIGlmIChvcHRzLmJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgX3NldE1pbkFuZE1heEJ5S2V5KHRpY2tzLCBtZSwgJ3ZhbHVlJyk7XG4gICAgfVxuICAgIGlmIChvcHRzLnJldmVyc2UpIHtcbiAgICAgIHRpY2tzLnJldmVyc2UoKTtcbiAgICAgIG1lLnN0YXJ0ID0gbWUubWF4O1xuICAgICAgbWUuZW5kID0gbWUubWluO1xuICAgIH0gZWxzZSB7XG4gICAgICBtZS5zdGFydCA9IG1lLm1pbjtcbiAgICAgIG1lLmVuZCA9IG1lLm1heDtcbiAgICB9XG4gICAgcmV0dXJuIHRpY2tzO1xuICB9XG4gIGNvbmZpZ3VyZSgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgdGlja3MgPSBtZS50aWNrcztcbiAgICBsZXQgc3RhcnQgPSBtZS5taW47XG4gICAgbGV0IGVuZCA9IG1lLm1heDtcbiAgICBzdXBlci5jb25maWd1cmUoKTtcbiAgICBpZiAobWUub3B0aW9ucy5vZmZzZXQgJiYgdGlja3MubGVuZ3RoKSB7XG4gICAgICBjb25zdCBvZmZzZXQgPSAoZW5kIC0gc3RhcnQpIC8gTWF0aC5tYXgodGlja3MubGVuZ3RoIC0gMSwgMSkgLyAyO1xuICAgICAgc3RhcnQgLT0gb2Zmc2V0O1xuICAgICAgZW5kICs9IG9mZnNldDtcbiAgICB9XG4gICAgbWUuX3N0YXJ0VmFsdWUgPSBzdGFydDtcbiAgICBtZS5fZW5kVmFsdWUgPSBlbmQ7XG4gICAgbWUuX3ZhbHVlUmFuZ2UgPSBlbmQgLSBzdGFydDtcbiAgfVxuICBnZXRMYWJlbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgcmV0dXJuIGZvcm1hdE51bWJlcih2YWx1ZSwgdGhpcy5jaGFydC5vcHRpb25zLmxvY2FsZSk7XG4gIH1cbn1cblxuY2xhc3MgTGluZWFyU2NhbGUgZXh0ZW5kcyBMaW5lYXJTY2FsZUJhc2Uge1xuICBkZXRlcm1pbmVEYXRhTGltaXRzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB7bWluLCBtYXh9ID0gbWUuZ2V0TWluTWF4KHRydWUpO1xuICAgIG1lLm1pbiA9IGlzTnVtYmVyRmluaXRlKG1pbikgPyBtaW4gOiAwO1xuICAgIG1lLm1heCA9IGlzTnVtYmVyRmluaXRlKG1heCkgPyBtYXggOiAxO1xuICAgIG1lLmhhbmRsZVRpY2tSYW5nZU9wdGlvbnMoKTtcbiAgfVxuICBjb21wdXRlVGlja0xpbWl0KCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBob3Jpem9udGFsID0gbWUuaXNIb3Jpem9udGFsKCk7XG4gICAgY29uc3QgbGVuZ3RoID0gaG9yaXpvbnRhbCA/IG1lLndpZHRoIDogbWUuaGVpZ2h0O1xuICAgIGNvbnN0IG1pblJvdGF0aW9uID0gdG9SYWRpYW5zKG1lLm9wdGlvbnMudGlja3MubWluUm90YXRpb24pO1xuICAgIGNvbnN0IHJhdGlvID0gKGhvcml6b250YWwgPyBNYXRoLnNpbihtaW5Sb3RhdGlvbikgOiBNYXRoLmNvcyhtaW5Sb3RhdGlvbikpIHx8IDAuMDAxO1xuICAgIGNvbnN0IHRpY2tGb250ID0gbWUuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoMCk7XG4gICAgcmV0dXJuIE1hdGguY2VpbChsZW5ndGggLyBNYXRoLm1pbig0MCwgdGlja0ZvbnQubGluZUhlaWdodCAvIHJhdGlvKSk7XG4gIH1cbiAgZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbCA/IE5hTiA6IHRoaXMuZ2V0UGl4ZWxGb3JEZWNpbWFsKCh2YWx1ZSAtIHRoaXMuX3N0YXJ0VmFsdWUpIC8gdGhpcy5fdmFsdWVSYW5nZSk7XG4gIH1cbiAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgIHJldHVybiB0aGlzLl9zdGFydFZhbHVlICsgdGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpICogdGhpcy5fdmFsdWVSYW5nZTtcbiAgfVxufVxuTGluZWFyU2NhbGUuaWQgPSAnbGluZWFyJztcbkxpbmVhclNjYWxlLmRlZmF1bHRzID0ge1xuICB0aWNrczoge1xuICAgIGNhbGxiYWNrOiBUaWNrcy5mb3JtYXR0ZXJzLm51bWVyaWNcbiAgfVxufTtcblxuZnVuY3Rpb24gaXNNYWpvcih0aWNrVmFsKSB7XG4gIGNvbnN0IHJlbWFpbiA9IHRpY2tWYWwgLyAoTWF0aC5wb3coMTAsIE1hdGguZmxvb3IobG9nMTAodGlja1ZhbCkpKSk7XG4gIHJldHVybiByZW1haW4gPT09IDE7XG59XG5mdW5jdGlvbiBnZW5lcmF0ZVRpY2tzKGdlbmVyYXRpb25PcHRpb25zLCBkYXRhUmFuZ2UpIHtcbiAgY29uc3QgZW5kRXhwID0gTWF0aC5mbG9vcihsb2cxMChkYXRhUmFuZ2UubWF4KSk7XG4gIGNvbnN0IGVuZFNpZ25pZmljYW5kID0gTWF0aC5jZWlsKGRhdGFSYW5nZS5tYXggLyBNYXRoLnBvdygxMCwgZW5kRXhwKSk7XG4gIGNvbnN0IHRpY2tzID0gW107XG4gIGxldCB0aWNrVmFsID0gZmluaXRlT3JEZWZhdWx0KGdlbmVyYXRpb25PcHRpb25zLm1pbiwgTWF0aC5wb3coMTAsIE1hdGguZmxvb3IobG9nMTAoZGF0YVJhbmdlLm1pbikpKSk7XG4gIGxldCBleHAgPSBNYXRoLmZsb29yKGxvZzEwKHRpY2tWYWwpKTtcbiAgbGV0IHNpZ25pZmljYW5kID0gTWF0aC5mbG9vcih0aWNrVmFsIC8gTWF0aC5wb3coMTAsIGV4cCkpO1xuICBsZXQgcHJlY2lzaW9uID0gZXhwIDwgMCA/IE1hdGgucG93KDEwLCBNYXRoLmFicyhleHApKSA6IDE7XG4gIGRvIHtcbiAgICB0aWNrcy5wdXNoKHt2YWx1ZTogdGlja1ZhbCwgbWFqb3I6IGlzTWFqb3IodGlja1ZhbCl9KTtcbiAgICArK3NpZ25pZmljYW5kO1xuICAgIGlmIChzaWduaWZpY2FuZCA9PT0gMTApIHtcbiAgICAgIHNpZ25pZmljYW5kID0gMTtcbiAgICAgICsrZXhwO1xuICAgICAgcHJlY2lzaW9uID0gZXhwID49IDAgPyAxIDogcHJlY2lzaW9uO1xuICAgIH1cbiAgICB0aWNrVmFsID0gTWF0aC5yb3VuZChzaWduaWZpY2FuZCAqIE1hdGgucG93KDEwLCBleHApICogcHJlY2lzaW9uKSAvIHByZWNpc2lvbjtcbiAgfSB3aGlsZSAoZXhwIDwgZW5kRXhwIHx8IChleHAgPT09IGVuZEV4cCAmJiBzaWduaWZpY2FuZCA8IGVuZFNpZ25pZmljYW5kKSk7XG4gIGNvbnN0IGxhc3RUaWNrID0gZmluaXRlT3JEZWZhdWx0KGdlbmVyYXRpb25PcHRpb25zLm1heCwgdGlja1ZhbCk7XG4gIHRpY2tzLnB1c2goe3ZhbHVlOiBsYXN0VGljaywgbWFqb3I6IGlzTWFqb3IodGlja1ZhbCl9KTtcbiAgcmV0dXJuIHRpY2tzO1xufVxuY2xhc3MgTG9nYXJpdGhtaWNTY2FsZSBleHRlbmRzIFNjYWxlIHtcbiAgY29uc3RydWN0b3IoY2ZnKSB7XG4gICAgc3VwZXIoY2ZnKTtcbiAgICB0aGlzLnN0YXJ0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZW5kID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3N0YXJ0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fdmFsdWVSYW5nZSA9IDA7XG4gIH1cbiAgcGFyc2UocmF3LCBpbmRleCkge1xuICAgIGNvbnN0IHZhbHVlID0gTGluZWFyU2NhbGVCYXNlLnByb3RvdHlwZS5wYXJzZS5hcHBseSh0aGlzLCBbcmF3LCBpbmRleF0pO1xuICAgIGlmICh2YWx1ZSA9PT0gMCkge1xuICAgICAgdGhpcy5femVybyA9IHRydWU7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gaXNOdW1iZXJGaW5pdGUodmFsdWUpICYmIHZhbHVlID4gMCA/IHZhbHVlIDogbnVsbDtcbiAgfVxuICBkZXRlcm1pbmVEYXRhTGltaXRzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB7bWluLCBtYXh9ID0gbWUuZ2V0TWluTWF4KHRydWUpO1xuICAgIG1lLm1pbiA9IGlzTnVtYmVyRmluaXRlKG1pbikgPyBNYXRoLm1heCgwLCBtaW4pIDogbnVsbDtcbiAgICBtZS5tYXggPSBpc051bWJlckZpbml0ZShtYXgpID8gTWF0aC5tYXgoMCwgbWF4KSA6IG51bGw7XG4gICAgaWYgKG1lLm9wdGlvbnMuYmVnaW5BdFplcm8pIHtcbiAgICAgIG1lLl96ZXJvID0gdHJ1ZTtcbiAgICB9XG4gICAgbWUuaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpO1xuICB9XG4gIGhhbmRsZVRpY2tSYW5nZU9wdGlvbnMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHttaW5EZWZpbmVkLCBtYXhEZWZpbmVkfSA9IG1lLmdldFVzZXJCb3VuZHMoKTtcbiAgICBsZXQgbWluID0gbWUubWluO1xuICAgIGxldCBtYXggPSBtZS5tYXg7XG4gICAgY29uc3Qgc2V0TWluID0gdiA9PiAobWluID0gbWluRGVmaW5lZCA/IG1pbiA6IHYpO1xuICAgIGNvbnN0IHNldE1heCA9IHYgPT4gKG1heCA9IG1heERlZmluZWQgPyBtYXggOiB2KTtcbiAgICBjb25zdCBleHAgPSAodiwgbSkgPT4gTWF0aC5wb3coMTAsIE1hdGguZmxvb3IobG9nMTAodikpICsgbSk7XG4gICAgaWYgKG1pbiA9PT0gbWF4KSB7XG4gICAgICBpZiAobWluIDw9IDApIHtcbiAgICAgICAgc2V0TWluKDEpO1xuICAgICAgICBzZXRNYXgoMTApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2V0TWluKGV4cChtaW4sIC0xKSk7XG4gICAgICAgIHNldE1heChleHAobWF4LCArMSkpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobWluIDw9IDApIHtcbiAgICAgIHNldE1pbihleHAobWF4LCAtMSkpO1xuICAgIH1cbiAgICBpZiAobWF4IDw9IDApIHtcbiAgICAgIHNldE1heChleHAobWluLCArMSkpO1xuICAgIH1cbiAgICBpZiAobWUuX3plcm8gJiYgbWUubWluICE9PSBtZS5fc3VnZ2VzdGVkTWluICYmIG1pbiA9PT0gZXhwKG1lLm1pbiwgMCkpIHtcbiAgICAgIHNldE1pbihleHAobWluLCAtMSkpO1xuICAgIH1cbiAgICBtZS5taW4gPSBtaW47XG4gICAgbWUubWF4ID0gbWF4O1xuICB9XG4gIGJ1aWxkVGlja3MoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdHMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IGdlbmVyYXRpb25PcHRpb25zID0ge1xuICAgICAgbWluOiBtZS5fdXNlck1pbixcbiAgICAgIG1heDogbWUuX3VzZXJNYXhcbiAgICB9O1xuICAgIGNvbnN0IHRpY2tzID0gZ2VuZXJhdGVUaWNrcyhnZW5lcmF0aW9uT3B0aW9ucywgbWUpO1xuICAgIGlmIChvcHRzLmJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgX3NldE1pbkFuZE1heEJ5S2V5KHRpY2tzLCBtZSwgJ3ZhbHVlJyk7XG4gICAgfVxuICAgIGlmIChvcHRzLnJldmVyc2UpIHtcbiAgICAgIHRpY2tzLnJldmVyc2UoKTtcbiAgICAgIG1lLnN0YXJ0ID0gbWUubWF4O1xuICAgICAgbWUuZW5kID0gbWUubWluO1xuICAgIH0gZWxzZSB7XG4gICAgICBtZS5zdGFydCA9IG1lLm1pbjtcbiAgICAgIG1lLmVuZCA9IG1lLm1heDtcbiAgICB9XG4gICAgcmV0dXJuIHRpY2tzO1xuICB9XG4gIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZCA/ICcwJyA6IGZvcm1hdE51bWJlcih2YWx1ZSwgdGhpcy5jaGFydC5vcHRpb25zLmxvY2FsZSk7XG4gIH1cbiAgY29uZmlndXJlKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBzdGFydCA9IG1lLm1pbjtcbiAgICBzdXBlci5jb25maWd1cmUoKTtcbiAgICBtZS5fc3RhcnRWYWx1ZSA9IGxvZzEwKHN0YXJ0KTtcbiAgICBtZS5fdmFsdWVSYW5nZSA9IGxvZzEwKG1lLm1heCkgLSBsb2cxMChzdGFydCk7XG4gIH1cbiAgZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gMCkge1xuICAgICAgdmFsdWUgPSBtZS5taW47XG4gICAgfVxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCBpc05hTih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBOYU47XG4gICAgfVxuICAgIHJldHVybiBtZS5nZXRQaXhlbEZvckRlY2ltYWwodmFsdWUgPT09IG1lLm1pblxuICAgICAgPyAwXG4gICAgICA6IChsb2cxMCh2YWx1ZSkgLSBtZS5fc3RhcnRWYWx1ZSkgLyBtZS5fdmFsdWVSYW5nZSk7XG4gIH1cbiAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBkZWNpbWFsID0gbWUuZ2V0RGVjaW1hbEZvclBpeGVsKHBpeGVsKTtcbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIG1lLl9zdGFydFZhbHVlICsgZGVjaW1hbCAqIG1lLl92YWx1ZVJhbmdlKTtcbiAgfVxufVxuTG9nYXJpdGhtaWNTY2FsZS5pZCA9ICdsb2dhcml0aG1pYyc7XG5Mb2dhcml0aG1pY1NjYWxlLmRlZmF1bHRzID0ge1xuICB0aWNrczoge1xuICAgIGNhbGxiYWNrOiBUaWNrcy5mb3JtYXR0ZXJzLmxvZ2FyaXRobWljLFxuICAgIG1ham9yOiB7XG4gICAgICBlbmFibGVkOiB0cnVlXG4gICAgfVxuICB9XG59O1xuXG5mdW5jdGlvbiBnZXRUaWNrQmFja2Ryb3BIZWlnaHQob3B0cykge1xuICBjb25zdCB0aWNrT3B0cyA9IG9wdHMudGlja3M7XG4gIGlmICh0aWNrT3B0cy5kaXNwbGF5ICYmIG9wdHMuZGlzcGxheSkge1xuICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcodGlja09wdHMuYmFja2Ryb3BQYWRkaW5nKTtcbiAgICByZXR1cm4gdmFsdWVPckRlZmF1bHQodGlja09wdHMuZm9udCAmJiB0aWNrT3B0cy5mb250LnNpemUsIGRlZmF1bHRzLmZvbnQuc2l6ZSkgKyBwYWRkaW5nLmhlaWdodDtcbiAgfVxuICByZXR1cm4gMDtcbn1cbmZ1bmN0aW9uIG1lYXN1cmVMYWJlbFNpemUoY3R4LCBmb250LCBsYWJlbCkge1xuICBsYWJlbCA9IGlzQXJyYXkobGFiZWwpID8gbGFiZWwgOiBbbGFiZWxdO1xuICByZXR1cm4ge1xuICAgIHc6IF9sb25nZXN0VGV4dChjdHgsIGZvbnQuc3RyaW5nLCBsYWJlbCksXG4gICAgaDogbGFiZWwubGVuZ3RoICogZm9udC5saW5lSGVpZ2h0XG4gIH07XG59XG5mdW5jdGlvbiBkZXRlcm1pbmVMaW1pdHMoYW5nbGUsIHBvcywgc2l6ZSwgbWluLCBtYXgpIHtcbiAgaWYgKGFuZ2xlID09PSBtaW4gfHwgYW5nbGUgPT09IG1heCkge1xuICAgIHJldHVybiB7XG4gICAgICBzdGFydDogcG9zIC0gKHNpemUgLyAyKSxcbiAgICAgIGVuZDogcG9zICsgKHNpemUgLyAyKVxuICAgIH07XG4gIH0gZWxzZSBpZiAoYW5nbGUgPCBtaW4gfHwgYW5nbGUgPiBtYXgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnQ6IHBvcyAtIHNpemUsXG4gICAgICBlbmQ6IHBvc1xuICAgIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBzdGFydDogcG9zLFxuICAgIGVuZDogcG9zICsgc2l6ZVxuICB9O1xufVxuZnVuY3Rpb24gZml0V2l0aFBvaW50TGFiZWxzKHNjYWxlKSB7XG4gIGNvbnN0IGZ1cnRoZXN0TGltaXRzID0ge1xuICAgIGw6IDAsXG4gICAgcjogc2NhbGUud2lkdGgsXG4gICAgdDogMCxcbiAgICBiOiBzY2FsZS5oZWlnaHQgLSBzY2FsZS5wYWRkaW5nVG9wXG4gIH07XG4gIGNvbnN0IGZ1cnRoZXN0QW5nbGVzID0ge307XG4gIGNvbnN0IGxhYmVsU2l6ZXMgPSBbXTtcbiAgY29uc3QgcGFkZGluZyA9IFtdO1xuICBjb25zdCB2YWx1ZUNvdW50ID0gc2NhbGUuZ2V0TGFiZWxzKCkubGVuZ3RoO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHVlQ291bnQ7IGkrKykge1xuICAgIGNvbnN0IG9wdHMgPSBzY2FsZS5vcHRpb25zLnBvaW50TGFiZWxzLnNldENvbnRleHQoc2NhbGUuZ2V0UG9pbnRMYWJlbENvbnRleHQoaSkpO1xuICAgIHBhZGRpbmdbaV0gPSBvcHRzLnBhZGRpbmc7XG4gICAgY29uc3QgcG9pbnRQb3NpdGlvbiA9IHNjYWxlLmdldFBvaW50UG9zaXRpb24oaSwgc2NhbGUuZHJhd2luZ0FyZWEgKyBwYWRkaW5nW2ldKTtcbiAgICBjb25zdCBwbEZvbnQgPSB0b0ZvbnQob3B0cy5mb250KTtcbiAgICBjb25zdCB0ZXh0U2l6ZSA9IG1lYXN1cmVMYWJlbFNpemUoc2NhbGUuY3R4LCBwbEZvbnQsIHNjYWxlLl9wb2ludExhYmVsc1tpXSk7XG4gICAgbGFiZWxTaXplc1tpXSA9IHRleHRTaXplO1xuICAgIGNvbnN0IGFuZ2xlUmFkaWFucyA9IHNjYWxlLmdldEluZGV4QW5nbGUoaSk7XG4gICAgY29uc3QgYW5nbGUgPSB0b0RlZ3JlZXMoYW5nbGVSYWRpYW5zKTtcbiAgICBjb25zdCBoTGltaXRzID0gZGV0ZXJtaW5lTGltaXRzKGFuZ2xlLCBwb2ludFBvc2l0aW9uLngsIHRleHRTaXplLncsIDAsIDE4MCk7XG4gICAgY29uc3QgdkxpbWl0cyA9IGRldGVybWluZUxpbWl0cyhhbmdsZSwgcG9pbnRQb3NpdGlvbi55LCB0ZXh0U2l6ZS5oLCA5MCwgMjcwKTtcbiAgICBpZiAoaExpbWl0cy5zdGFydCA8IGZ1cnRoZXN0TGltaXRzLmwpIHtcbiAgICAgIGZ1cnRoZXN0TGltaXRzLmwgPSBoTGltaXRzLnN0YXJ0O1xuICAgICAgZnVydGhlc3RBbmdsZXMubCA9IGFuZ2xlUmFkaWFucztcbiAgICB9XG4gICAgaWYgKGhMaW1pdHMuZW5kID4gZnVydGhlc3RMaW1pdHMucikge1xuICAgICAgZnVydGhlc3RMaW1pdHMuciA9IGhMaW1pdHMuZW5kO1xuICAgICAgZnVydGhlc3RBbmdsZXMuciA9IGFuZ2xlUmFkaWFucztcbiAgICB9XG4gICAgaWYgKHZMaW1pdHMuc3RhcnQgPCBmdXJ0aGVzdExpbWl0cy50KSB7XG4gICAgICBmdXJ0aGVzdExpbWl0cy50ID0gdkxpbWl0cy5zdGFydDtcbiAgICAgIGZ1cnRoZXN0QW5nbGVzLnQgPSBhbmdsZVJhZGlhbnM7XG4gICAgfVxuICAgIGlmICh2TGltaXRzLmVuZCA+IGZ1cnRoZXN0TGltaXRzLmIpIHtcbiAgICAgIGZ1cnRoZXN0TGltaXRzLmIgPSB2TGltaXRzLmVuZDtcbiAgICAgIGZ1cnRoZXN0QW5nbGVzLmIgPSBhbmdsZVJhZGlhbnM7XG4gICAgfVxuICB9XG4gIHNjYWxlLl9zZXRSZWR1Y3Rpb25zKHNjYWxlLmRyYXdpbmdBcmVhLCBmdXJ0aGVzdExpbWl0cywgZnVydGhlc3RBbmdsZXMpO1xuICBzY2FsZS5fcG9pbnRMYWJlbEl0ZW1zID0gYnVpbGRQb2ludExhYmVsSXRlbXMoc2NhbGUsIGxhYmVsU2l6ZXMsIHBhZGRpbmcpO1xufVxuZnVuY3Rpb24gYnVpbGRQb2ludExhYmVsSXRlbXMoc2NhbGUsIGxhYmVsU2l6ZXMsIHBhZGRpbmcpIHtcbiAgY29uc3QgaXRlbXMgPSBbXTtcbiAgY29uc3QgdmFsdWVDb3VudCA9IHNjYWxlLmdldExhYmVscygpLmxlbmd0aDtcbiAgY29uc3Qgb3B0cyA9IHNjYWxlLm9wdGlvbnM7XG4gIGNvbnN0IHRpY2tCYWNrZHJvcEhlaWdodCA9IGdldFRpY2tCYWNrZHJvcEhlaWdodChvcHRzKTtcbiAgY29uc3Qgb3V0ZXJEaXN0YW5jZSA9IHNjYWxlLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKG9wdHMudGlja3MucmV2ZXJzZSA/IHNjYWxlLm1pbiA6IHNjYWxlLm1heCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdmFsdWVDb3VudDsgaSsrKSB7XG4gICAgY29uc3QgZXh0cmEgPSAoaSA9PT0gMCA/IHRpY2tCYWNrZHJvcEhlaWdodCAvIDIgOiAwKTtcbiAgICBjb25zdCBwb2ludExhYmVsUG9zaXRpb24gPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uKGksIG91dGVyRGlzdGFuY2UgKyBleHRyYSArIHBhZGRpbmdbaV0pO1xuICAgIGNvbnN0IGFuZ2xlID0gdG9EZWdyZWVzKHNjYWxlLmdldEluZGV4QW5nbGUoaSkpO1xuICAgIGNvbnN0IHNpemUgPSBsYWJlbFNpemVzW2ldO1xuICAgIGNvbnN0IHkgPSB5Rm9yQW5nbGUocG9pbnRMYWJlbFBvc2l0aW9uLnksIHNpemUuaCwgYW5nbGUpO1xuICAgIGNvbnN0IHRleHRBbGlnbiA9IGdldFRleHRBbGlnbkZvckFuZ2xlKGFuZ2xlKTtcbiAgICBjb25zdCBsZWZ0ID0gbGVmdEZvclRleHRBbGlnbihwb2ludExhYmVsUG9zaXRpb24ueCwgc2l6ZS53LCB0ZXh0QWxpZ24pO1xuICAgIGl0ZW1zLnB1c2goe1xuICAgICAgeDogcG9pbnRMYWJlbFBvc2l0aW9uLngsXG4gICAgICB5LFxuICAgICAgdGV4dEFsaWduLFxuICAgICAgbGVmdCxcbiAgICAgIHRvcDogeSxcbiAgICAgIHJpZ2h0OiBsZWZ0ICsgc2l6ZS53LFxuICAgICAgYm90dG9tOiB5ICsgc2l6ZS5oXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGl0ZW1zO1xufVxuZnVuY3Rpb24gZ2V0VGV4dEFsaWduRm9yQW5nbGUoYW5nbGUpIHtcbiAgaWYgKGFuZ2xlID09PSAwIHx8IGFuZ2xlID09PSAxODApIHtcbiAgICByZXR1cm4gJ2NlbnRlcic7XG4gIH0gZWxzZSBpZiAoYW5nbGUgPCAxODApIHtcbiAgICByZXR1cm4gJ2xlZnQnO1xuICB9XG4gIHJldHVybiAncmlnaHQnO1xufVxuZnVuY3Rpb24gbGVmdEZvclRleHRBbGlnbih4LCB3LCBhbGlnbikge1xuICBpZiAoYWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICB4IC09IHc7XG4gIH0gZWxzZSBpZiAoYWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgeCAtPSAodyAvIDIpO1xuICB9XG4gIHJldHVybiB4O1xufVxuZnVuY3Rpb24geUZvckFuZ2xlKHksIGgsIGFuZ2xlKSB7XG4gIGlmIChhbmdsZSA9PT0gOTAgfHwgYW5nbGUgPT09IDI3MCkge1xuICAgIHkgLT0gKGggLyAyKTtcbiAgfSBlbHNlIGlmIChhbmdsZSA+IDI3MCB8fCBhbmdsZSA8IDkwKSB7XG4gICAgeSAtPSBoO1xuICB9XG4gIHJldHVybiB5O1xufVxuZnVuY3Rpb24gZHJhd1BvaW50TGFiZWxzKHNjYWxlLCBsYWJlbENvdW50KSB7XG4gIGNvbnN0IHtjdHgsIG9wdGlvbnM6IHtwb2ludExhYmVsc319ID0gc2NhbGU7XG4gIGZvciAobGV0IGkgPSBsYWJlbENvdW50IC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBjb25zdCBvcHRzQXRJbmRleCA9IHBvaW50TGFiZWxzLnNldENvbnRleHQoc2NhbGUuZ2V0UG9pbnRMYWJlbENvbnRleHQoaSkpO1xuICAgIGNvbnN0IHBsRm9udCA9IHRvRm9udChvcHRzQXRJbmRleC5mb250KTtcbiAgICBjb25zdCB7eCwgeSwgdGV4dEFsaWduLCBsZWZ0LCB0b3AsIHJpZ2h0LCBib3R0b219ID0gc2NhbGUuX3BvaW50TGFiZWxJdGVtc1tpXTtcbiAgICBjb25zdCB7YmFja2Ryb3BDb2xvcn0gPSBvcHRzQXRJbmRleDtcbiAgICBpZiAoIWlzTnVsbE9yVW5kZWYoYmFja2Ryb3BDb2xvcikpIHtcbiAgICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcob3B0c0F0SW5kZXguYmFja2Ryb3BQYWRkaW5nKTtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSBiYWNrZHJvcENvbG9yO1xuICAgICAgY3R4LmZpbGxSZWN0KGxlZnQgLSBwYWRkaW5nLmxlZnQsIHRvcCAtIHBhZGRpbmcudG9wLCByaWdodCAtIGxlZnQgKyBwYWRkaW5nLndpZHRoLCBib3R0b20gLSB0b3AgKyBwYWRkaW5nLmhlaWdodCk7XG4gICAgfVxuICAgIHJlbmRlclRleHQoXG4gICAgICBjdHgsXG4gICAgICBzY2FsZS5fcG9pbnRMYWJlbHNbaV0sXG4gICAgICB4LFxuICAgICAgeSArIChwbEZvbnQubGluZUhlaWdodCAvIDIpLFxuICAgICAgcGxGb250LFxuICAgICAge1xuICAgICAgICBjb2xvcjogb3B0c0F0SW5kZXguY29sb3IsXG4gICAgICAgIHRleHRBbGlnbjogdGV4dEFsaWduLFxuICAgICAgICB0ZXh0QmFzZWxpbmU6ICdtaWRkbGUnXG4gICAgICB9XG4gICAgKTtcbiAgfVxufVxuZnVuY3Rpb24gcGF0aFJhZGl1c0xpbmUoc2NhbGUsIHJhZGl1cywgY2lyY3VsYXIsIGxhYmVsQ291bnQpIHtcbiAgY29uc3Qge2N0eH0gPSBzY2FsZTtcbiAgaWYgKGNpcmN1bGFyKSB7XG4gICAgY3R4LmFyYyhzY2FsZS54Q2VudGVyLCBzY2FsZS55Q2VudGVyLCByYWRpdXMsIDAsIFRBVSk7XG4gIH0gZWxzZSB7XG4gICAgbGV0IHBvaW50UG9zaXRpb24gPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uKDAsIHJhZGl1cyk7XG4gICAgY3R4Lm1vdmVUbyhwb2ludFBvc2l0aW9uLngsIHBvaW50UG9zaXRpb24ueSk7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsYWJlbENvdW50OyBpKyspIHtcbiAgICAgIHBvaW50UG9zaXRpb24gPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uKGksIHJhZGl1cyk7XG4gICAgICBjdHgubGluZVRvKHBvaW50UG9zaXRpb24ueCwgcG9pbnRQb3NpdGlvbi55KTtcbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uIGRyYXdSYWRpdXNMaW5lKHNjYWxlLCBncmlkTGluZU9wdHMsIHJhZGl1cywgbGFiZWxDb3VudCkge1xuICBjb25zdCBjdHggPSBzY2FsZS5jdHg7XG4gIGNvbnN0IGNpcmN1bGFyID0gZ3JpZExpbmVPcHRzLmNpcmN1bGFyO1xuICBjb25zdCB7Y29sb3IsIGxpbmVXaWR0aH0gPSBncmlkTGluZU9wdHM7XG4gIGlmICgoIWNpcmN1bGFyICYmICFsYWJlbENvdW50KSB8fCAhY29sb3IgfHwgIWxpbmVXaWR0aCB8fCByYWRpdXMgPCAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGN0eC5zYXZlKCk7XG4gIGN0eC5zdHJva2VTdHlsZSA9IGNvbG9yO1xuICBjdHgubGluZVdpZHRoID0gbGluZVdpZHRoO1xuICBjdHguc2V0TGluZURhc2goZ3JpZExpbmVPcHRzLmJvcmRlckRhc2gpO1xuICBjdHgubGluZURhc2hPZmZzZXQgPSBncmlkTGluZU9wdHMuYm9yZGVyRGFzaE9mZnNldDtcbiAgY3R4LmJlZ2luUGF0aCgpO1xuICBwYXRoUmFkaXVzTGluZShzY2FsZSwgcmFkaXVzLCBjaXJjdWxhciwgbGFiZWxDb3VudCk7XG4gIGN0eC5jbG9zZVBhdGgoKTtcbiAgY3R4LnN0cm9rZSgpO1xuICBjdHgucmVzdG9yZSgpO1xufVxuZnVuY3Rpb24gbnVtYmVyT3JaZXJvKHBhcmFtKSB7XG4gIHJldHVybiBpc051bWJlcihwYXJhbSkgPyBwYXJhbSA6IDA7XG59XG5mdW5jdGlvbiBjcmVhdGVQb2ludExhYmVsQ29udGV4dChwYXJlbnQsIGluZGV4LCBsYWJlbCkge1xuICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKHBhcmVudCksIHtcbiAgICBsYWJlbCxcbiAgICBpbmRleCxcbiAgICB0eXBlOiAncG9pbnRMYWJlbCdcbiAgfSk7XG59XG5jbGFzcyBSYWRpYWxMaW5lYXJTY2FsZSBleHRlbmRzIExpbmVhclNjYWxlQmFzZSB7XG4gIGNvbnN0cnVjdG9yKGNmZykge1xuICAgIHN1cGVyKGNmZyk7XG4gICAgdGhpcy54Q2VudGVyID0gdW5kZWZpbmVkO1xuICAgIHRoaXMueUNlbnRlciA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmRyYXdpbmdBcmVhID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3BvaW50TGFiZWxzID0gW107XG4gICAgdGhpcy5fcG9pbnRMYWJlbEl0ZW1zID0gW107XG4gIH1cbiAgc2V0RGltZW5zaW9ucygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgbWUud2lkdGggPSBtZS5tYXhXaWR0aDtcbiAgICBtZS5oZWlnaHQgPSBtZS5tYXhIZWlnaHQ7XG4gICAgbWUucGFkZGluZ1RvcCA9IGdldFRpY2tCYWNrZHJvcEhlaWdodChtZS5vcHRpb25zKSAvIDI7XG4gICAgbWUueENlbnRlciA9IE1hdGguZmxvb3IobWUud2lkdGggLyAyKTtcbiAgICBtZS55Q2VudGVyID0gTWF0aC5mbG9vcigobWUuaGVpZ2h0IC0gbWUucGFkZGluZ1RvcCkgLyAyKTtcbiAgICBtZS5kcmF3aW5nQXJlYSA9IE1hdGgubWluKG1lLmhlaWdodCAtIG1lLnBhZGRpbmdUb3AsIG1lLndpZHRoKSAvIDI7XG4gIH1cbiAgZGV0ZXJtaW5lRGF0YUxpbWl0cygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge21pbiwgbWF4fSA9IG1lLmdldE1pbk1heChmYWxzZSk7XG4gICAgbWUubWluID0gaXNOdW1iZXJGaW5pdGUobWluKSAmJiAhaXNOYU4obWluKSA/IG1pbiA6IDA7XG4gICAgbWUubWF4ID0gaXNOdW1iZXJGaW5pdGUobWF4KSAmJiAhaXNOYU4obWF4KSA/IG1heCA6IDA7XG4gICAgbWUuaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpO1xuICB9XG4gIGNvbXB1dGVUaWNrTGltaXQoKSB7XG4gICAgcmV0dXJuIE1hdGguY2VpbCh0aGlzLmRyYXdpbmdBcmVhIC8gZ2V0VGlja0JhY2tkcm9wSGVpZ2h0KHRoaXMub3B0aW9ucykpO1xuICB9XG4gIGdlbmVyYXRlVGlja0xhYmVscyh0aWNrcykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBMaW5lYXJTY2FsZUJhc2UucHJvdG90eXBlLmdlbmVyYXRlVGlja0xhYmVscy5jYWxsKG1lLCB0aWNrcyk7XG4gICAgbWUuX3BvaW50TGFiZWxzID0gbWUuZ2V0TGFiZWxzKCkubWFwKCh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IGxhYmVsID0gY2FsbGJhY2sobWUub3B0aW9ucy5wb2ludExhYmVscy5jYWxsYmFjaywgW3ZhbHVlLCBpbmRleF0sIG1lKTtcbiAgICAgIHJldHVybiBsYWJlbCB8fCBsYWJlbCA9PT0gMCA/IGxhYmVsIDogJyc7XG4gICAgfSk7XG4gIH1cbiAgZml0KCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRzID0gbWUub3B0aW9ucztcbiAgICBpZiAob3B0cy5kaXNwbGF5ICYmIG9wdHMucG9pbnRMYWJlbHMuZGlzcGxheSkge1xuICAgICAgZml0V2l0aFBvaW50TGFiZWxzKG1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbWUuc2V0Q2VudGVyUG9pbnQoMCwgMCwgMCwgMCk7XG4gICAgfVxuICB9XG4gIF9zZXRSZWR1Y3Rpb25zKGxhcmdlc3RQb3NzaWJsZVJhZGl1cywgZnVydGhlc3RMaW1pdHMsIGZ1cnRoZXN0QW5nbGVzKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGxldCByYWRpdXNSZWR1Y3Rpb25MZWZ0ID0gZnVydGhlc3RMaW1pdHMubCAvIE1hdGguc2luKGZ1cnRoZXN0QW5nbGVzLmwpO1xuICAgIGxldCByYWRpdXNSZWR1Y3Rpb25SaWdodCA9IE1hdGgubWF4KGZ1cnRoZXN0TGltaXRzLnIgLSBtZS53aWR0aCwgMCkgLyBNYXRoLnNpbihmdXJ0aGVzdEFuZ2xlcy5yKTtcbiAgICBsZXQgcmFkaXVzUmVkdWN0aW9uVG9wID0gLWZ1cnRoZXN0TGltaXRzLnQgLyBNYXRoLmNvcyhmdXJ0aGVzdEFuZ2xlcy50KTtcbiAgICBsZXQgcmFkaXVzUmVkdWN0aW9uQm90dG9tID0gLU1hdGgubWF4KGZ1cnRoZXN0TGltaXRzLmIgLSAobWUuaGVpZ2h0IC0gbWUucGFkZGluZ1RvcCksIDApIC8gTWF0aC5jb3MoZnVydGhlc3RBbmdsZXMuYik7XG4gICAgcmFkaXVzUmVkdWN0aW9uTGVmdCA9IG51bWJlck9yWmVybyhyYWRpdXNSZWR1Y3Rpb25MZWZ0KTtcbiAgICByYWRpdXNSZWR1Y3Rpb25SaWdodCA9IG51bWJlck9yWmVybyhyYWRpdXNSZWR1Y3Rpb25SaWdodCk7XG4gICAgcmFkaXVzUmVkdWN0aW9uVG9wID0gbnVtYmVyT3JaZXJvKHJhZGl1c1JlZHVjdGlvblRvcCk7XG4gICAgcmFkaXVzUmVkdWN0aW9uQm90dG9tID0gbnVtYmVyT3JaZXJvKHJhZGl1c1JlZHVjdGlvbkJvdHRvbSk7XG4gICAgbWUuZHJhd2luZ0FyZWEgPSBNYXRoLm1heChsYXJnZXN0UG9zc2libGVSYWRpdXMgLyAyLCBNYXRoLm1pbihcbiAgICAgIE1hdGguZmxvb3IobGFyZ2VzdFBvc3NpYmxlUmFkaXVzIC0gKHJhZGl1c1JlZHVjdGlvbkxlZnQgKyByYWRpdXNSZWR1Y3Rpb25SaWdodCkgLyAyKSxcbiAgICAgIE1hdGguZmxvb3IobGFyZ2VzdFBvc3NpYmxlUmFkaXVzIC0gKHJhZGl1c1JlZHVjdGlvblRvcCArIHJhZGl1c1JlZHVjdGlvbkJvdHRvbSkgLyAyKSkpO1xuICAgIG1lLnNldENlbnRlclBvaW50KHJhZGl1c1JlZHVjdGlvbkxlZnQsIHJhZGl1c1JlZHVjdGlvblJpZ2h0LCByYWRpdXNSZWR1Y3Rpb25Ub3AsIHJhZGl1c1JlZHVjdGlvbkJvdHRvbSk7XG4gIH1cbiAgc2V0Q2VudGVyUG9pbnQobGVmdE1vdmVtZW50LCByaWdodE1vdmVtZW50LCB0b3BNb3ZlbWVudCwgYm90dG9tTW92ZW1lbnQpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgbWF4UmlnaHQgPSBtZS53aWR0aCAtIHJpZ2h0TW92ZW1lbnQgLSBtZS5kcmF3aW5nQXJlYTtcbiAgICBjb25zdCBtYXhMZWZ0ID0gbGVmdE1vdmVtZW50ICsgbWUuZHJhd2luZ0FyZWE7XG4gICAgY29uc3QgbWF4VG9wID0gdG9wTW92ZW1lbnQgKyBtZS5kcmF3aW5nQXJlYTtcbiAgICBjb25zdCBtYXhCb3R0b20gPSAobWUuaGVpZ2h0IC0gbWUucGFkZGluZ1RvcCkgLSBib3R0b21Nb3ZlbWVudCAtIG1lLmRyYXdpbmdBcmVhO1xuICAgIG1lLnhDZW50ZXIgPSBNYXRoLmZsb29yKCgobWF4TGVmdCArIG1heFJpZ2h0KSAvIDIpICsgbWUubGVmdCk7XG4gICAgbWUueUNlbnRlciA9IE1hdGguZmxvb3IoKChtYXhUb3AgKyBtYXhCb3R0b20pIC8gMikgKyBtZS50b3AgKyBtZS5wYWRkaW5nVG9wKTtcbiAgfVxuICBnZXRJbmRleEFuZ2xlKGluZGV4KSB7XG4gICAgY29uc3QgYW5nbGVNdWx0aXBsaWVyID0gVEFVIC8gdGhpcy5nZXRMYWJlbHMoKS5sZW5ndGg7XG4gICAgY29uc3Qgc3RhcnRBbmdsZSA9IHRoaXMub3B0aW9ucy5zdGFydEFuZ2xlIHx8IDA7XG4gICAgcmV0dXJuIF9ub3JtYWxpemVBbmdsZShpbmRleCAqIGFuZ2xlTXVsdGlwbGllciArIHRvUmFkaWFucyhzdGFydEFuZ2xlKSk7XG4gIH1cbiAgZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodmFsdWUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgaWYgKGlzTnVsbE9yVW5kZWYodmFsdWUpKSB7XG4gICAgICByZXR1cm4gTmFOO1xuICAgIH1cbiAgICBjb25zdCBzY2FsaW5nRmFjdG9yID0gbWUuZHJhd2luZ0FyZWEgLyAobWUubWF4IC0gbWUubWluKTtcbiAgICBpZiAobWUub3B0aW9ucy5yZXZlcnNlKSB7XG4gICAgICByZXR1cm4gKG1lLm1heCAtIHZhbHVlKSAqIHNjYWxpbmdGYWN0b3I7XG4gICAgfVxuICAgIHJldHVybiAodmFsdWUgLSBtZS5taW4pICogc2NhbGluZ0ZhY3RvcjtcbiAgfVxuICBnZXRWYWx1ZUZvckRpc3RhbmNlRnJvbUNlbnRlcihkaXN0YW5jZSkge1xuICAgIGlmIChpc051bGxPclVuZGVmKGRpc3RhbmNlKSkge1xuICAgICAgcmV0dXJuIE5hTjtcbiAgICB9XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IHNjYWxlZERpc3RhbmNlID0gZGlzdGFuY2UgLyAobWUuZHJhd2luZ0FyZWEgLyAobWUubWF4IC0gbWUubWluKSk7XG4gICAgcmV0dXJuIG1lLm9wdGlvbnMucmV2ZXJzZSA/IG1lLm1heCAtIHNjYWxlZERpc3RhbmNlIDogbWUubWluICsgc2NhbGVkRGlzdGFuY2U7XG4gIH1cbiAgZ2V0UG9pbnRMYWJlbENvbnRleHQoaW5kZXgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgcG9pbnRMYWJlbHMgPSBtZS5fcG9pbnRMYWJlbHMgfHwgW107XG4gICAgaWYgKGluZGV4ID49IDAgJiYgaW5kZXggPCBwb2ludExhYmVscy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHBvaW50TGFiZWwgPSBwb2ludExhYmVsc1tpbmRleF07XG4gICAgICByZXR1cm4gY3JlYXRlUG9pbnRMYWJlbENvbnRleHQobWUuZ2V0Q29udGV4dCgpLCBpbmRleCwgcG9pbnRMYWJlbCk7XG4gICAgfVxuICB9XG4gIGdldFBvaW50UG9zaXRpb24oaW5kZXgsIGRpc3RhbmNlRnJvbUNlbnRlcikge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBhbmdsZSA9IG1lLmdldEluZGV4QW5nbGUoaW5kZXgpIC0gSEFMRl9QSTtcbiAgICByZXR1cm4ge1xuICAgICAgeDogTWF0aC5jb3MoYW5nbGUpICogZGlzdGFuY2VGcm9tQ2VudGVyICsgbWUueENlbnRlcixcbiAgICAgIHk6IE1hdGguc2luKGFuZ2xlKSAqIGRpc3RhbmNlRnJvbUNlbnRlciArIG1lLnlDZW50ZXIsXG4gICAgICBhbmdsZVxuICAgIH07XG4gIH1cbiAgZ2V0UG9pbnRQb3NpdGlvbkZvclZhbHVlKGluZGV4LCB2YWx1ZSkge1xuICAgIHJldHVybiB0aGlzLmdldFBvaW50UG9zaXRpb24oaW5kZXgsIHRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodmFsdWUpKTtcbiAgfVxuICBnZXRCYXNlUG9zaXRpb24oaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUoaW5kZXggfHwgMCwgdGhpcy5nZXRCYXNlVmFsdWUoKSk7XG4gIH1cbiAgZ2V0UG9pbnRMYWJlbFBvc2l0aW9uKGluZGV4KSB7XG4gICAgY29uc3Qge2xlZnQsIHRvcCwgcmlnaHQsIGJvdHRvbX0gPSB0aGlzLl9wb2ludExhYmVsSXRlbXNbaW5kZXhdO1xuICAgIHJldHVybiB7XG4gICAgICBsZWZ0LFxuICAgICAgdG9wLFxuICAgICAgcmlnaHQsXG4gICAgICBib3R0b20sXG4gICAgfTtcbiAgfVxuICBkcmF3QmFja2dyb3VuZCgpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qge2JhY2tncm91bmRDb2xvciwgZ3JpZDoge2NpcmN1bGFyfX0gPSBtZS5vcHRpb25zO1xuICAgIGlmIChiYWNrZ3JvdW5kQ29sb3IpIHtcbiAgICAgIGNvbnN0IGN0eCA9IG1lLmN0eDtcbiAgICAgIGN0eC5zYXZlKCk7XG4gICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICBwYXRoUmFkaXVzTGluZShtZSwgbWUuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUobWUuX2VuZFZhbHVlKSwgY2lyY3VsYXIsIG1lLmdldExhYmVscygpLmxlbmd0aCk7XG4gICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICBjdHguZmlsbFN0eWxlID0gYmFja2dyb3VuZENvbG9yO1xuICAgICAgY3R4LmZpbGwoKTtcbiAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgfVxuICB9XG4gIGRyYXdHcmlkKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBjdHggPSBtZS5jdHg7XG4gICAgY29uc3Qgb3B0cyA9IG1lLm9wdGlvbnM7XG4gICAgY29uc3Qge2FuZ2xlTGluZXMsIGdyaWR9ID0gb3B0cztcbiAgICBjb25zdCBsYWJlbENvdW50ID0gbWUuZ2V0TGFiZWxzKCkubGVuZ3RoO1xuICAgIGxldCBpLCBvZmZzZXQsIHBvc2l0aW9uO1xuICAgIGlmIChvcHRzLnBvaW50TGFiZWxzLmRpc3BsYXkpIHtcbiAgICAgIGRyYXdQb2ludExhYmVscyhtZSwgbGFiZWxDb3VudCk7XG4gICAgfVxuICAgIGlmIChncmlkLmRpc3BsYXkpIHtcbiAgICAgIG1lLnRpY2tzLmZvckVhY2goKHRpY2ssIGluZGV4KSA9PiB7XG4gICAgICAgIGlmIChpbmRleCAhPT0gMCkge1xuICAgICAgICAgIG9mZnNldCA9IG1lLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKHRpY2sudmFsdWUpO1xuICAgICAgICAgIGNvbnN0IG9wdHNBdEluZGV4ID0gZ3JpZC5zZXRDb250ZXh0KG1lLmdldENvbnRleHQoaW5kZXggLSAxKSk7XG4gICAgICAgICAgZHJhd1JhZGl1c0xpbmUobWUsIG9wdHNBdEluZGV4LCBvZmZzZXQsIGxhYmVsQ291bnQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGFuZ2xlTGluZXMuZGlzcGxheSkge1xuICAgICAgY3R4LnNhdmUoKTtcbiAgICAgIGZvciAoaSA9IG1lLmdldExhYmVscygpLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGNvbnN0IG9wdHNBdEluZGV4ID0gYW5nbGVMaW5lcy5zZXRDb250ZXh0KG1lLmdldFBvaW50TGFiZWxDb250ZXh0KGkpKTtcbiAgICAgICAgY29uc3Qge2NvbG9yLCBsaW5lV2lkdGh9ID0gb3B0c0F0SW5kZXg7XG4gICAgICAgIGlmICghbGluZVdpZHRoIHx8ICFjb2xvcikge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGNvbG9yO1xuICAgICAgICBjdHguc2V0TGluZURhc2gob3B0c0F0SW5kZXguYm9yZGVyRGFzaCk7XG4gICAgICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IG9wdHNBdEluZGV4LmJvcmRlckRhc2hPZmZzZXQ7XG4gICAgICAgIG9mZnNldCA9IG1lLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKG9wdHMudGlja3MucmV2ZXJzZSA/IG1lLm1pbiA6IG1lLm1heCk7XG4gICAgICAgIHBvc2l0aW9uID0gbWUuZ2V0UG9pbnRQb3NpdGlvbihpLCBvZmZzZXQpO1xuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5tb3ZlVG8obWUueENlbnRlciwgbWUueUNlbnRlcik7XG4gICAgICAgIGN0eC5saW5lVG8ocG9zaXRpb24ueCwgcG9zaXRpb24ueSk7XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICAgIH1cbiAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgfVxuICB9XG4gIGRyYXdCb3JkZXIoKSB7fVxuICBkcmF3TGFiZWxzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBjdHggPSBtZS5jdHg7XG4gICAgY29uc3Qgb3B0cyA9IG1lLm9wdGlvbnM7XG4gICAgY29uc3QgdGlja09wdHMgPSBvcHRzLnRpY2tzO1xuICAgIGlmICghdGlja09wdHMuZGlzcGxheSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzdGFydEFuZ2xlID0gbWUuZ2V0SW5kZXhBbmdsZSgwKTtcbiAgICBsZXQgb2Zmc2V0LCB3aWR0aDtcbiAgICBjdHguc2F2ZSgpO1xuICAgIGN0eC50cmFuc2xhdGUobWUueENlbnRlciwgbWUueUNlbnRlcik7XG4gICAgY3R4LnJvdGF0ZShzdGFydEFuZ2xlKTtcbiAgICBjdHgudGV4dEFsaWduID0gJ2NlbnRlcic7XG4gICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgIG1lLnRpY2tzLmZvckVhY2goKHRpY2ssIGluZGV4KSA9PiB7XG4gICAgICBpZiAoaW5kZXggPT09IDAgJiYgIW9wdHMucmV2ZXJzZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBvcHRzQXRJbmRleCA9IHRpY2tPcHRzLnNldENvbnRleHQobWUuZ2V0Q29udGV4dChpbmRleCkpO1xuICAgICAgY29uc3QgdGlja0ZvbnQgPSB0b0ZvbnQob3B0c0F0SW5kZXguZm9udCk7XG4gICAgICBvZmZzZXQgPSBtZS5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZShtZS50aWNrc1tpbmRleF0udmFsdWUpO1xuICAgICAgaWYgKG9wdHNBdEluZGV4LnNob3dMYWJlbEJhY2tkcm9wKSB7XG4gICAgICAgIGN0eC5mb250ID0gdGlja0ZvbnQuc3RyaW5nO1xuICAgICAgICB3aWR0aCA9IGN0eC5tZWFzdXJlVGV4dCh0aWNrLmxhYmVsKS53aWR0aDtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdHNBdEluZGV4LmJhY2tkcm9wQ29sb3I7XG4gICAgICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcob3B0c0F0SW5kZXguYmFja2Ryb3BQYWRkaW5nKTtcbiAgICAgICAgY3R4LmZpbGxSZWN0KFxuICAgICAgICAgIC13aWR0aCAvIDIgLSBwYWRkaW5nLmxlZnQsXG4gICAgICAgICAgLW9mZnNldCAtIHRpY2tGb250LnNpemUgLyAyIC0gcGFkZGluZy50b3AsXG4gICAgICAgICAgd2lkdGggKyBwYWRkaW5nLndpZHRoLFxuICAgICAgICAgIHRpY2tGb250LnNpemUgKyBwYWRkaW5nLmhlaWdodFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmVuZGVyVGV4dChjdHgsIHRpY2subGFiZWwsIDAsIC1vZmZzZXQsIHRpY2tGb250LCB7XG4gICAgICAgIGNvbG9yOiBvcHRzQXRJbmRleC5jb2xvcixcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGN0eC5yZXN0b3JlKCk7XG4gIH1cbiAgZHJhd1RpdGxlKCkge31cbn1cblJhZGlhbExpbmVhclNjYWxlLmlkID0gJ3JhZGlhbExpbmVhcic7XG5SYWRpYWxMaW5lYXJTY2FsZS5kZWZhdWx0cyA9IHtcbiAgZGlzcGxheTogdHJ1ZSxcbiAgYW5pbWF0ZTogdHJ1ZSxcbiAgcG9zaXRpb246ICdjaGFydEFyZWEnLFxuICBhbmdsZUxpbmVzOiB7XG4gICAgZGlzcGxheTogdHJ1ZSxcbiAgICBsaW5lV2lkdGg6IDEsXG4gICAgYm9yZGVyRGFzaDogW10sXG4gICAgYm9yZGVyRGFzaE9mZnNldDogMC4wXG4gIH0sXG4gIGdyaWQ6IHtcbiAgICBjaXJjdWxhcjogZmFsc2VcbiAgfSxcbiAgc3RhcnRBbmdsZTogMCxcbiAgdGlja3M6IHtcbiAgICBzaG93TGFiZWxCYWNrZHJvcDogdHJ1ZSxcbiAgICBjYWxsYmFjazogVGlja3MuZm9ybWF0dGVycy5udW1lcmljXG4gIH0sXG4gIHBvaW50TGFiZWxzOiB7XG4gICAgYmFja2Ryb3BDb2xvcjogdW5kZWZpbmVkLFxuICAgIGJhY2tkcm9wUGFkZGluZzogMixcbiAgICBkaXNwbGF5OiB0cnVlLFxuICAgIGZvbnQ6IHtcbiAgICAgIHNpemU6IDEwXG4gICAgfSxcbiAgICBjYWxsYmFjayhsYWJlbCkge1xuICAgICAgcmV0dXJuIGxhYmVsO1xuICAgIH0sXG4gICAgcGFkZGluZzogNVxuICB9XG59O1xuUmFkaWFsTGluZWFyU2NhbGUuZGVmYXVsdFJvdXRlcyA9IHtcbiAgJ2FuZ2xlTGluZXMuY29sb3InOiAnYm9yZGVyQ29sb3InLFxuICAncG9pbnRMYWJlbHMuY29sb3InOiAnY29sb3InLFxuICAndGlja3MuY29sb3InOiAnY29sb3InXG59O1xuUmFkaWFsTGluZWFyU2NhbGUuZGVzY3JpcHRvcnMgPSB7XG4gIGFuZ2xlTGluZXM6IHtcbiAgICBfZmFsbGJhY2s6ICdncmlkJ1xuICB9XG59O1xuXG5jb25zdCBJTlRFUlZBTFMgPSB7XG4gIG1pbGxpc2Vjb25kOiB7Y29tbW9uOiB0cnVlLCBzaXplOiAxLCBzdGVwczogMTAwMH0sXG4gIHNlY29uZDoge2NvbW1vbjogdHJ1ZSwgc2l6ZTogMTAwMCwgc3RlcHM6IDYwfSxcbiAgbWludXRlOiB7Y29tbW9uOiB0cnVlLCBzaXplOiA2MDAwMCwgc3RlcHM6IDYwfSxcbiAgaG91cjoge2NvbW1vbjogdHJ1ZSwgc2l6ZTogMzYwMDAwMCwgc3RlcHM6IDI0fSxcbiAgZGF5OiB7Y29tbW9uOiB0cnVlLCBzaXplOiA4NjQwMDAwMCwgc3RlcHM6IDMwfSxcbiAgd2Vlazoge2NvbW1vbjogZmFsc2UsIHNpemU6IDYwNDgwMDAwMCwgc3RlcHM6IDR9LFxuICBtb250aDoge2NvbW1vbjogdHJ1ZSwgc2l6ZTogMi42MjhlOSwgc3RlcHM6IDEyfSxcbiAgcXVhcnRlcjoge2NvbW1vbjogZmFsc2UsIHNpemU6IDcuODg0ZTksIHN0ZXBzOiA0fSxcbiAgeWVhcjoge2NvbW1vbjogdHJ1ZSwgc2l6ZTogMy4xNTRlMTB9XG59O1xuY29uc3QgVU5JVFMgPSAoT2JqZWN0LmtleXMoSU5URVJWQUxTKSk7XG5mdW5jdGlvbiBzb3J0ZXIoYSwgYikge1xuICByZXR1cm4gYSAtIGI7XG59XG5mdW5jdGlvbiBwYXJzZShzY2FsZSwgaW5wdXQpIHtcbiAgaWYgKGlzTnVsbE9yVW5kZWYoaW5wdXQpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgYWRhcHRlciA9IHNjYWxlLl9hZGFwdGVyO1xuICBjb25zdCB7cGFyc2VyLCByb3VuZCwgaXNvV2Vla2RheX0gPSBzY2FsZS5fcGFyc2VPcHRzO1xuICBsZXQgdmFsdWUgPSBpbnB1dDtcbiAgaWYgKHR5cGVvZiBwYXJzZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICB2YWx1ZSA9IHBhcnNlcih2YWx1ZSk7XG4gIH1cbiAgaWYgKCFpc051bWJlckZpbml0ZSh2YWx1ZSkpIHtcbiAgICB2YWx1ZSA9IHR5cGVvZiBwYXJzZXIgPT09ICdzdHJpbmcnXG4gICAgICA/IGFkYXB0ZXIucGFyc2UodmFsdWUsIHBhcnNlcilcbiAgICAgIDogYWRhcHRlci5wYXJzZSh2YWx1ZSk7XG4gIH1cbiAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgaWYgKHJvdW5kKSB7XG4gICAgdmFsdWUgPSByb3VuZCA9PT0gJ3dlZWsnICYmIChpc051bWJlcihpc29XZWVrZGF5KSB8fCBpc29XZWVrZGF5ID09PSB0cnVlKVxuICAgICAgPyBhZGFwdGVyLnN0YXJ0T2YodmFsdWUsICdpc29XZWVrJywgaXNvV2Vla2RheSlcbiAgICAgIDogYWRhcHRlci5zdGFydE9mKHZhbHVlLCByb3VuZCk7XG4gIH1cbiAgcmV0dXJuICt2YWx1ZTtcbn1cbmZ1bmN0aW9uIGRldGVybWluZVVuaXRGb3JBdXRvVGlja3MobWluVW5pdCwgbWluLCBtYXgsIGNhcGFjaXR5KSB7XG4gIGNvbnN0IGlsZW4gPSBVTklUUy5sZW5ndGg7XG4gIGZvciAobGV0IGkgPSBVTklUUy5pbmRleE9mKG1pblVuaXQpOyBpIDwgaWxlbiAtIDE7ICsraSkge1xuICAgIGNvbnN0IGludGVydmFsID0gSU5URVJWQUxTW1VOSVRTW2ldXTtcbiAgICBjb25zdCBmYWN0b3IgPSBpbnRlcnZhbC5zdGVwcyA/IGludGVydmFsLnN0ZXBzIDogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG4gICAgaWYgKGludGVydmFsLmNvbW1vbiAmJiBNYXRoLmNlaWwoKG1heCAtIG1pbikgLyAoZmFjdG9yICogaW50ZXJ2YWwuc2l6ZSkpIDw9IGNhcGFjaXR5KSB7XG4gICAgICByZXR1cm4gVU5JVFNbaV07XG4gICAgfVxuICB9XG4gIHJldHVybiBVTklUU1tpbGVuIC0gMV07XG59XG5mdW5jdGlvbiBkZXRlcm1pbmVVbml0Rm9yRm9ybWF0dGluZyhzY2FsZSwgbnVtVGlja3MsIG1pblVuaXQsIG1pbiwgbWF4KSB7XG4gIGZvciAobGV0IGkgPSBVTklUUy5sZW5ndGggLSAxOyBpID49IFVOSVRTLmluZGV4T2YobWluVW5pdCk7IGktLSkge1xuICAgIGNvbnN0IHVuaXQgPSBVTklUU1tpXTtcbiAgICBpZiAoSU5URVJWQUxTW3VuaXRdLmNvbW1vbiAmJiBzY2FsZS5fYWRhcHRlci5kaWZmKG1heCwgbWluLCB1bml0KSA+PSBudW1UaWNrcyAtIDEpIHtcbiAgICAgIHJldHVybiB1bml0O1xuICAgIH1cbiAgfVxuICByZXR1cm4gVU5JVFNbbWluVW5pdCA/IFVOSVRTLmluZGV4T2YobWluVW5pdCkgOiAwXTtcbn1cbmZ1bmN0aW9uIGRldGVybWluZU1ham9yVW5pdCh1bml0KSB7XG4gIGZvciAobGV0IGkgPSBVTklUUy5pbmRleE9mKHVuaXQpICsgMSwgaWxlbiA9IFVOSVRTLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgIGlmIChJTlRFUlZBTFNbVU5JVFNbaV1dLmNvbW1vbikge1xuICAgICAgcmV0dXJuIFVOSVRTW2ldO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gYWRkVGljayh0aWNrcywgdGltZSwgdGltZXN0YW1wcykge1xuICBpZiAoIXRpbWVzdGFtcHMpIHtcbiAgICB0aWNrc1t0aW1lXSA9IHRydWU7XG4gIH0gZWxzZSBpZiAodGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICBjb25zdCB7bG8sIGhpfSA9IF9sb29rdXAodGltZXN0YW1wcywgdGltZSk7XG4gICAgY29uc3QgdGltZXN0YW1wID0gdGltZXN0YW1wc1tsb10gPj0gdGltZSA/IHRpbWVzdGFtcHNbbG9dIDogdGltZXN0YW1wc1toaV07XG4gICAgdGlja3NbdGltZXN0YW1wXSA9IHRydWU7XG4gIH1cbn1cbmZ1bmN0aW9uIHNldE1ham9yVGlja3Moc2NhbGUsIHRpY2tzLCBtYXAsIG1ham9yVW5pdCkge1xuICBjb25zdCBhZGFwdGVyID0gc2NhbGUuX2FkYXB0ZXI7XG4gIGNvbnN0IGZpcnN0ID0gK2FkYXB0ZXIuc3RhcnRPZih0aWNrc1swXS52YWx1ZSwgbWFqb3JVbml0KTtcbiAgY29uc3QgbGFzdCA9IHRpY2tzW3RpY2tzLmxlbmd0aCAtIDFdLnZhbHVlO1xuICBsZXQgbWFqb3IsIGluZGV4O1xuICBmb3IgKG1ham9yID0gZmlyc3Q7IG1ham9yIDw9IGxhc3Q7IG1ham9yID0gK2FkYXB0ZXIuYWRkKG1ham9yLCAxLCBtYWpvclVuaXQpKSB7XG4gICAgaW5kZXggPSBtYXBbbWFqb3JdO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICB0aWNrc1tpbmRleF0ubWFqb3IgPSB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdGlja3M7XG59XG5mdW5jdGlvbiB0aWNrc0Zyb21UaW1lc3RhbXBzKHNjYWxlLCB2YWx1ZXMsIG1ham9yVW5pdCkge1xuICBjb25zdCB0aWNrcyA9IFtdO1xuICBjb25zdCBtYXAgPSB7fTtcbiAgY29uc3QgaWxlbiA9IHZhbHVlcy5sZW5ndGg7XG4gIGxldCBpLCB2YWx1ZTtcbiAgZm9yIChpID0gMDsgaSA8IGlsZW47ICsraSkge1xuICAgIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgIG1hcFt2YWx1ZV0gPSBpO1xuICAgIHRpY2tzLnB1c2goe1xuICAgICAgdmFsdWUsXG4gICAgICBtYWpvcjogZmFsc2VcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gKGlsZW4gPT09IDAgfHwgIW1ham9yVW5pdCkgPyB0aWNrcyA6IHNldE1ham9yVGlja3Moc2NhbGUsIHRpY2tzLCBtYXAsIG1ham9yVW5pdCk7XG59XG5jbGFzcyBUaW1lU2NhbGUgZXh0ZW5kcyBTY2FsZSB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuICAgIHRoaXMuX2NhY2hlID0ge1xuICAgICAgZGF0YTogW10sXG4gICAgICBsYWJlbHM6IFtdLFxuICAgICAgYWxsOiBbXVxuICAgIH07XG4gICAgdGhpcy5fdW5pdCA9ICdkYXknO1xuICAgIHRoaXMuX21ham9yVW5pdCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9vZmZzZXRzID0ge307XG4gICAgdGhpcy5fbm9ybWFsaXplZCA9IGZhbHNlO1xuICAgIHRoaXMuX3BhcnNlT3B0cyA9IHVuZGVmaW5lZDtcbiAgfVxuICBpbml0KHNjYWxlT3B0cywgb3B0cykge1xuICAgIGNvbnN0IHRpbWUgPSBzY2FsZU9wdHMudGltZSB8fCAoc2NhbGVPcHRzLnRpbWUgPSB7fSk7XG4gICAgY29uc3QgYWRhcHRlciA9IHRoaXMuX2FkYXB0ZXIgPSBuZXcgYWRhcHRlcnMuX2RhdGUoc2NhbGVPcHRzLmFkYXB0ZXJzLmRhdGUpO1xuICAgIG1lcmdlSWYodGltZS5kaXNwbGF5Rm9ybWF0cywgYWRhcHRlci5mb3JtYXRzKCkpO1xuICAgIHRoaXMuX3BhcnNlT3B0cyA9IHtcbiAgICAgIHBhcnNlcjogdGltZS5wYXJzZXIsXG4gICAgICByb3VuZDogdGltZS5yb3VuZCxcbiAgICAgIGlzb1dlZWtkYXk6IHRpbWUuaXNvV2Vla2RheVxuICAgIH07XG4gICAgc3VwZXIuaW5pdChzY2FsZU9wdHMpO1xuICAgIHRoaXMuX25vcm1hbGl6ZWQgPSBvcHRzLm5vcm1hbGl6ZWQ7XG4gIH1cbiAgcGFyc2UocmF3LCBpbmRleCkge1xuICAgIGlmIChyYXcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBwYXJzZSh0aGlzLCByYXcpO1xuICB9XG4gIGJlZm9yZUxheW91dCgpIHtcbiAgICBzdXBlci5iZWZvcmVMYXlvdXQoKTtcbiAgICB0aGlzLl9jYWNoZSA9IHtcbiAgICAgIGRhdGE6IFtdLFxuICAgICAgbGFiZWxzOiBbXSxcbiAgICAgIGFsbDogW11cbiAgICB9O1xuICB9XG4gIGRldGVybWluZURhdGFMaW1pdHMoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IGFkYXB0ZXIgPSBtZS5fYWRhcHRlcjtcbiAgICBjb25zdCB1bml0ID0gb3B0aW9ucy50aW1lLnVuaXQgfHwgJ2RheSc7XG4gICAgbGV0IHttaW4sIG1heCwgbWluRGVmaW5lZCwgbWF4RGVmaW5lZH0gPSBtZS5nZXRVc2VyQm91bmRzKCk7XG4gICAgZnVuY3Rpb24gX2FwcGx5Qm91bmRzKGJvdW5kcykge1xuICAgICAgaWYgKCFtaW5EZWZpbmVkICYmICFpc05hTihib3VuZHMubWluKSkge1xuICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIGJvdW5kcy5taW4pO1xuICAgICAgfVxuICAgICAgaWYgKCFtYXhEZWZpbmVkICYmICFpc05hTihib3VuZHMubWF4KSkge1xuICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIGJvdW5kcy5tYXgpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIW1pbkRlZmluZWQgfHwgIW1heERlZmluZWQpIHtcbiAgICAgIF9hcHBseUJvdW5kcyhtZS5fZ2V0TGFiZWxCb3VuZHMoKSk7XG4gICAgICBpZiAob3B0aW9ucy5ib3VuZHMgIT09ICd0aWNrcycgfHwgb3B0aW9ucy50aWNrcy5zb3VyY2UgIT09ICdsYWJlbHMnKSB7XG4gICAgICAgIF9hcHBseUJvdW5kcyhtZS5nZXRNaW5NYXgoZmFsc2UpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgbWluID0gaXNOdW1iZXJGaW5pdGUobWluKSAmJiAhaXNOYU4obWluKSA/IG1pbiA6ICthZGFwdGVyLnN0YXJ0T2YoRGF0ZS5ub3coKSwgdW5pdCk7XG4gICAgbWF4ID0gaXNOdW1iZXJGaW5pdGUobWF4KSAmJiAhaXNOYU4obWF4KSA/IG1heCA6ICthZGFwdGVyLmVuZE9mKERhdGUubm93KCksIHVuaXQpICsgMTtcbiAgICBtZS5taW4gPSBNYXRoLm1pbihtaW4sIG1heCAtIDEpO1xuICAgIG1lLm1heCA9IE1hdGgubWF4KG1pbiArIDEsIG1heCk7XG4gIH1cbiAgX2dldExhYmVsQm91bmRzKCkge1xuICAgIGNvbnN0IGFyciA9IHRoaXMuZ2V0TGFiZWxUaW1lc3RhbXBzKCk7XG4gICAgbGV0IG1pbiA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICBsZXQgbWF4ID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO1xuICAgIGlmIChhcnIubGVuZ3RoKSB7XG4gICAgICBtaW4gPSBhcnJbMF07XG4gICAgICBtYXggPSBhcnJbYXJyLmxlbmd0aCAtIDFdO1xuICAgIH1cbiAgICByZXR1cm4ge21pbiwgbWF4fTtcbiAgfVxuICBidWlsZFRpY2tzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvcHRpb25zID0gbWUub3B0aW9ucztcbiAgICBjb25zdCB0aW1lT3B0cyA9IG9wdGlvbnMudGltZTtcbiAgICBjb25zdCB0aWNrT3B0cyA9IG9wdGlvbnMudGlja3M7XG4gICAgY29uc3QgdGltZXN0YW1wcyA9IHRpY2tPcHRzLnNvdXJjZSA9PT0gJ2xhYmVscycgPyBtZS5nZXRMYWJlbFRpbWVzdGFtcHMoKSA6IG1lLl9nZW5lcmF0ZSgpO1xuICAgIGlmIChvcHRpb25zLmJvdW5kcyA9PT0gJ3RpY2tzJyAmJiB0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgbWUubWluID0gbWUuX3VzZXJNaW4gfHwgdGltZXN0YW1wc1swXTtcbiAgICAgIG1lLm1heCA9IG1lLl91c2VyTWF4IHx8IHRpbWVzdGFtcHNbdGltZXN0YW1wcy5sZW5ndGggLSAxXTtcbiAgICB9XG4gICAgY29uc3QgbWluID0gbWUubWluO1xuICAgIGNvbnN0IG1heCA9IG1lLm1heDtcbiAgICBjb25zdCB0aWNrcyA9IF9maWx0ZXJCZXR3ZWVuKHRpbWVzdGFtcHMsIG1pbiwgbWF4KTtcbiAgICBtZS5fdW5pdCA9IHRpbWVPcHRzLnVuaXQgfHwgKHRpY2tPcHRzLmF1dG9Ta2lwXG4gICAgICA/IGRldGVybWluZVVuaXRGb3JBdXRvVGlja3ModGltZU9wdHMubWluVW5pdCwgbWUubWluLCBtZS5tYXgsIG1lLl9nZXRMYWJlbENhcGFjaXR5KG1pbikpXG4gICAgICA6IGRldGVybWluZVVuaXRGb3JGb3JtYXR0aW5nKG1lLCB0aWNrcy5sZW5ndGgsIHRpbWVPcHRzLm1pblVuaXQsIG1lLm1pbiwgbWUubWF4KSk7XG4gICAgbWUuX21ham9yVW5pdCA9ICF0aWNrT3B0cy5tYWpvci5lbmFibGVkIHx8IG1lLl91bml0ID09PSAneWVhcicgPyB1bmRlZmluZWRcbiAgICAgIDogZGV0ZXJtaW5lTWFqb3JVbml0KG1lLl91bml0KTtcbiAgICBtZS5pbml0T2Zmc2V0cyh0aW1lc3RhbXBzKTtcbiAgICBpZiAob3B0aW9ucy5yZXZlcnNlKSB7XG4gICAgICB0aWNrcy5yZXZlcnNlKCk7XG4gICAgfVxuICAgIHJldHVybiB0aWNrc0Zyb21UaW1lc3RhbXBzKG1lLCB0aWNrcywgbWUuX21ham9yVW5pdCk7XG4gIH1cbiAgaW5pdE9mZnNldHModGltZXN0YW1wcykge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBsZXQgc3RhcnQgPSAwO1xuICAgIGxldCBlbmQgPSAwO1xuICAgIGxldCBmaXJzdCwgbGFzdDtcbiAgICBpZiAobWUub3B0aW9ucy5vZmZzZXQgJiYgdGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICAgIGZpcnN0ID0gbWUuZ2V0RGVjaW1hbEZvclZhbHVlKHRpbWVzdGFtcHNbMF0pO1xuICAgICAgaWYgKHRpbWVzdGFtcHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHN0YXJ0ID0gMSAtIGZpcnN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RhcnQgPSAobWUuZ2V0RGVjaW1hbEZvclZhbHVlKHRpbWVzdGFtcHNbMV0pIC0gZmlyc3QpIC8gMjtcbiAgICAgIH1cbiAgICAgIGxhc3QgPSBtZS5nZXREZWNpbWFsRm9yVmFsdWUodGltZXN0YW1wc1t0aW1lc3RhbXBzLmxlbmd0aCAtIDFdKTtcbiAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBlbmQgPSBsYXN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW5kID0gKGxhc3QgLSBtZS5nZXREZWNpbWFsRm9yVmFsdWUodGltZXN0YW1wc1t0aW1lc3RhbXBzLmxlbmd0aCAtIDJdKSkgLyAyO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBsaW1pdCA9IHRpbWVzdGFtcHMubGVuZ3RoIDwgMyA/IDAuNSA6IDAuMjU7XG4gICAgc3RhcnQgPSBfbGltaXRWYWx1ZShzdGFydCwgMCwgbGltaXQpO1xuICAgIGVuZCA9IF9saW1pdFZhbHVlKGVuZCwgMCwgbGltaXQpO1xuICAgIG1lLl9vZmZzZXRzID0ge3N0YXJ0LCBlbmQsIGZhY3RvcjogMSAvIChzdGFydCArIDEgKyBlbmQpfTtcbiAgfVxuICBfZ2VuZXJhdGUoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IGFkYXB0ZXIgPSBtZS5fYWRhcHRlcjtcbiAgICBjb25zdCBtaW4gPSBtZS5taW47XG4gICAgY29uc3QgbWF4ID0gbWUubWF4O1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IHRpbWVPcHRzID0gb3B0aW9ucy50aW1lO1xuICAgIGNvbnN0IG1pbm9yID0gdGltZU9wdHMudW5pdCB8fCBkZXRlcm1pbmVVbml0Rm9yQXV0b1RpY2tzKHRpbWVPcHRzLm1pblVuaXQsIG1pbiwgbWF4LCBtZS5fZ2V0TGFiZWxDYXBhY2l0eShtaW4pKTtcbiAgICBjb25zdCBzdGVwU2l6ZSA9IHZhbHVlT3JEZWZhdWx0KHRpbWVPcHRzLnN0ZXBTaXplLCAxKTtcbiAgICBjb25zdCB3ZWVrZGF5ID0gbWlub3IgPT09ICd3ZWVrJyA/IHRpbWVPcHRzLmlzb1dlZWtkYXkgOiBmYWxzZTtcbiAgICBjb25zdCBoYXNXZWVrZGF5ID0gaXNOdW1iZXIod2Vla2RheSkgfHwgd2Vla2RheSA9PT0gdHJ1ZTtcbiAgICBjb25zdCB0aWNrcyA9IHt9O1xuICAgIGxldCBmaXJzdCA9IG1pbjtcbiAgICBsZXQgdGltZSwgY291bnQ7XG4gICAgaWYgKGhhc1dlZWtkYXkpIHtcbiAgICAgIGZpcnN0ID0gK2FkYXB0ZXIuc3RhcnRPZihmaXJzdCwgJ2lzb1dlZWsnLCB3ZWVrZGF5KTtcbiAgICB9XG4gICAgZmlyc3QgPSArYWRhcHRlci5zdGFydE9mKGZpcnN0LCBoYXNXZWVrZGF5ID8gJ2RheScgOiBtaW5vcik7XG4gICAgaWYgKGFkYXB0ZXIuZGlmZihtYXgsIG1pbiwgbWlub3IpID4gMTAwMDAwICogc3RlcFNpemUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihtaW4gKyAnIGFuZCAnICsgbWF4ICsgJyBhcmUgdG9vIGZhciBhcGFydCB3aXRoIHN0ZXBTaXplIG9mICcgKyBzdGVwU2l6ZSArICcgJyArIG1pbm9yKTtcbiAgICB9XG4gICAgY29uc3QgdGltZXN0YW1wcyA9IG9wdGlvbnMudGlja3Muc291cmNlID09PSAnZGF0YScgJiYgbWUuZ2V0RGF0YVRpbWVzdGFtcHMoKTtcbiAgICBmb3IgKHRpbWUgPSBmaXJzdCwgY291bnQgPSAwOyB0aW1lIDwgbWF4OyB0aW1lID0gK2FkYXB0ZXIuYWRkKHRpbWUsIHN0ZXBTaXplLCBtaW5vciksIGNvdW50KyspIHtcbiAgICAgIGFkZFRpY2sodGlja3MsIHRpbWUsIHRpbWVzdGFtcHMpO1xuICAgIH1cbiAgICBpZiAodGltZSA9PT0gbWF4IHx8IG9wdGlvbnMuYm91bmRzID09PSAndGlja3MnIHx8IGNvdW50ID09PSAxKSB7XG4gICAgICBhZGRUaWNrKHRpY2tzLCB0aW1lLCB0aW1lc3RhbXBzKTtcbiAgICB9XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRpY2tzKS5zb3J0KChhLCBiKSA9PiBhIC0gYikubWFwKHggPT4gK3gpO1xuICB9XG4gIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgYWRhcHRlciA9IG1lLl9hZGFwdGVyO1xuICAgIGNvbnN0IHRpbWVPcHRzID0gbWUub3B0aW9ucy50aW1lO1xuICAgIGlmICh0aW1lT3B0cy50b29sdGlwRm9ybWF0KSB7XG4gICAgICByZXR1cm4gYWRhcHRlci5mb3JtYXQodmFsdWUsIHRpbWVPcHRzLnRvb2x0aXBGb3JtYXQpO1xuICAgIH1cbiAgICByZXR1cm4gYWRhcHRlci5mb3JtYXQodmFsdWUsIHRpbWVPcHRzLmRpc3BsYXlGb3JtYXRzLmRhdGV0aW1lKTtcbiAgfVxuICBfdGlja0Zvcm1hdEZ1bmN0aW9uKHRpbWUsIGluZGV4LCB0aWNrcywgZm9ybWF0KSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZS5vcHRpb25zO1xuICAgIGNvbnN0IGZvcm1hdHMgPSBvcHRpb25zLnRpbWUuZGlzcGxheUZvcm1hdHM7XG4gICAgY29uc3QgdW5pdCA9IG1lLl91bml0O1xuICAgIGNvbnN0IG1ham9yVW5pdCA9IG1lLl9tYWpvclVuaXQ7XG4gICAgY29uc3QgbWlub3JGb3JtYXQgPSB1bml0ICYmIGZvcm1hdHNbdW5pdF07XG4gICAgY29uc3QgbWFqb3JGb3JtYXQgPSBtYWpvclVuaXQgJiYgZm9ybWF0c1ttYWpvclVuaXRdO1xuICAgIGNvbnN0IHRpY2sgPSB0aWNrc1tpbmRleF07XG4gICAgY29uc3QgbWFqb3IgPSBtYWpvclVuaXQgJiYgbWFqb3JGb3JtYXQgJiYgdGljayAmJiB0aWNrLm1ham9yO1xuICAgIGNvbnN0IGxhYmVsID0gbWUuX2FkYXB0ZXIuZm9ybWF0KHRpbWUsIGZvcm1hdCB8fCAobWFqb3IgPyBtYWpvckZvcm1hdCA6IG1pbm9yRm9ybWF0KSk7XG4gICAgY29uc3QgZm9ybWF0dGVyID0gb3B0aW9ucy50aWNrcy5jYWxsYmFjaztcbiAgICByZXR1cm4gZm9ybWF0dGVyID8gY2FsbGJhY2soZm9ybWF0dGVyLCBbbGFiZWwsIGluZGV4LCB0aWNrc10sIG1lKSA6IGxhYmVsO1xuICB9XG4gIGdlbmVyYXRlVGlja0xhYmVscyh0aWNrcykge1xuICAgIGxldCBpLCBpbGVuLCB0aWNrO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIHRpY2sgPSB0aWNrc1tpXTtcbiAgICAgIHRpY2subGFiZWwgPSB0aGlzLl90aWNrRm9ybWF0RnVuY3Rpb24odGljay52YWx1ZSwgaSwgdGlja3MpO1xuICAgIH1cbiAgfVxuICBnZXREZWNpbWFsRm9yVmFsdWUodmFsdWUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgcmV0dXJuIHZhbHVlID09PSBudWxsID8gTmFOIDogKHZhbHVlIC0gbWUubWluKSAvIChtZS5tYXggLSBtZS5taW4pO1xuICB9XG4gIGdldFBpeGVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3Qgb2Zmc2V0cyA9IG1lLl9vZmZzZXRzO1xuICAgIGNvbnN0IHBvcyA9IG1lLmdldERlY2ltYWxGb3JWYWx1ZSh2YWx1ZSk7XG4gICAgcmV0dXJuIG1lLmdldFBpeGVsRm9yRGVjaW1hbCgob2Zmc2V0cy5zdGFydCArIHBvcykgKiBvZmZzZXRzLmZhY3Rvcik7XG4gIH1cbiAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvZmZzZXRzID0gbWUuX29mZnNldHM7XG4gICAgY29uc3QgcG9zID0gbWUuZ2V0RGVjaW1hbEZvclBpeGVsKHBpeGVsKSAvIG9mZnNldHMuZmFjdG9yIC0gb2Zmc2V0cy5lbmQ7XG4gICAgcmV0dXJuIG1lLm1pbiArIHBvcyAqIChtZS5tYXggLSBtZS5taW4pO1xuICB9XG4gIF9nZXRMYWJlbFNpemUobGFiZWwpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgdGlja3NPcHRzID0gbWUub3B0aW9ucy50aWNrcztcbiAgICBjb25zdCB0aWNrTGFiZWxXaWR0aCA9IG1lLmN0eC5tZWFzdXJlVGV4dChsYWJlbCkud2lkdGg7XG4gICAgY29uc3QgYW5nbGUgPSB0b1JhZGlhbnMobWUuaXNIb3Jpem9udGFsKCkgPyB0aWNrc09wdHMubWF4Um90YXRpb24gOiB0aWNrc09wdHMubWluUm90YXRpb24pO1xuICAgIGNvbnN0IGNvc1JvdGF0aW9uID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIGNvbnN0IHNpblJvdGF0aW9uID0gTWF0aC5zaW4oYW5nbGUpO1xuICAgIGNvbnN0IHRpY2tGb250U2l6ZSA9IG1lLl9yZXNvbHZlVGlja0ZvbnRPcHRpb25zKDApLnNpemU7XG4gICAgcmV0dXJuIHtcbiAgICAgIHc6ICh0aWNrTGFiZWxXaWR0aCAqIGNvc1JvdGF0aW9uKSArICh0aWNrRm9udFNpemUgKiBzaW5Sb3RhdGlvbiksXG4gICAgICBoOiAodGlja0xhYmVsV2lkdGggKiBzaW5Sb3RhdGlvbikgKyAodGlja0ZvbnRTaXplICogY29zUm90YXRpb24pXG4gICAgfTtcbiAgfVxuICBfZ2V0TGFiZWxDYXBhY2l0eShleGFtcGxlVGltZSkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB0aW1lT3B0cyA9IG1lLm9wdGlvbnMudGltZTtcbiAgICBjb25zdCBkaXNwbGF5Rm9ybWF0cyA9IHRpbWVPcHRzLmRpc3BsYXlGb3JtYXRzO1xuICAgIGNvbnN0IGZvcm1hdCA9IGRpc3BsYXlGb3JtYXRzW3RpbWVPcHRzLnVuaXRdIHx8IGRpc3BsYXlGb3JtYXRzLm1pbGxpc2Vjb25kO1xuICAgIGNvbnN0IGV4YW1wbGVMYWJlbCA9IG1lLl90aWNrRm9ybWF0RnVuY3Rpb24oZXhhbXBsZVRpbWUsIDAsIHRpY2tzRnJvbVRpbWVzdGFtcHMobWUsIFtleGFtcGxlVGltZV0sIG1lLl9tYWpvclVuaXQpLCBmb3JtYXQpO1xuICAgIGNvbnN0IHNpemUgPSBtZS5fZ2V0TGFiZWxTaXplKGV4YW1wbGVMYWJlbCk7XG4gICAgY29uc3QgY2FwYWNpdHkgPSBNYXRoLmZsb29yKG1lLmlzSG9yaXpvbnRhbCgpID8gbWUud2lkdGggLyBzaXplLncgOiBtZS5oZWlnaHQgLyBzaXplLmgpIC0gMTtcbiAgICByZXR1cm4gY2FwYWNpdHkgPiAwID8gY2FwYWNpdHkgOiAxO1xuICB9XG4gIGdldERhdGFUaW1lc3RhbXBzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBsZXQgdGltZXN0YW1wcyA9IG1lLl9jYWNoZS5kYXRhIHx8IFtdO1xuICAgIGxldCBpLCBpbGVuO1xuICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRpbWVzdGFtcHM7XG4gICAgfVxuICAgIGNvbnN0IG1ldGFzID0gbWUuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXMoKTtcbiAgICBpZiAobWUuX25vcm1hbGl6ZWQgJiYgbWV0YXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gKG1lLl9jYWNoZS5kYXRhID0gbWV0YXNbMF0uY29udHJvbGxlci5nZXRBbGxQYXJzZWRWYWx1ZXMobWUpKTtcbiAgICB9XG4gICAgZm9yIChpID0gMCwgaWxlbiA9IG1ldGFzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgdGltZXN0YW1wcyA9IHRpbWVzdGFtcHMuY29uY2F0KG1ldGFzW2ldLmNvbnRyb2xsZXIuZ2V0QWxsUGFyc2VkVmFsdWVzKG1lKSk7XG4gICAgfVxuICAgIHJldHVybiAobWUuX2NhY2hlLmRhdGEgPSBtZS5ub3JtYWxpemUodGltZXN0YW1wcykpO1xuICB9XG4gIGdldExhYmVsVGltZXN0YW1wcygpIHtcbiAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgY29uc3QgdGltZXN0YW1wcyA9IG1lLl9jYWNoZS5sYWJlbHMgfHwgW107XG4gICAgbGV0IGksIGlsZW47XG4gICAgaWYgKHRpbWVzdGFtcHMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGltZXN0YW1wcztcbiAgICB9XG4gICAgY29uc3QgbGFiZWxzID0gbWUuZ2V0TGFiZWxzKCk7XG4gICAgZm9yIChpID0gMCwgaWxlbiA9IGxhYmVscy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIHRpbWVzdGFtcHMucHVzaChwYXJzZShtZSwgbGFiZWxzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiAobWUuX2NhY2hlLmxhYmVscyA9IG1lLl9ub3JtYWxpemVkID8gdGltZXN0YW1wcyA6IG1lLm5vcm1hbGl6ZSh0aW1lc3RhbXBzKSk7XG4gIH1cbiAgbm9ybWFsaXplKHZhbHVlcykge1xuICAgIHJldHVybiBfYXJyYXlVbmlxdWUodmFsdWVzLnNvcnQoc29ydGVyKSk7XG4gIH1cbn1cblRpbWVTY2FsZS5pZCA9ICd0aW1lJztcblRpbWVTY2FsZS5kZWZhdWx0cyA9IHtcbiAgYm91bmRzOiAnZGF0YScsXG4gIGFkYXB0ZXJzOiB7fSxcbiAgdGltZToge1xuICAgIHBhcnNlcjogZmFsc2UsXG4gICAgdW5pdDogZmFsc2UsXG4gICAgcm91bmQ6IGZhbHNlLFxuICAgIGlzb1dlZWtkYXk6IGZhbHNlLFxuICAgIG1pblVuaXQ6ICdtaWxsaXNlY29uZCcsXG4gICAgZGlzcGxheUZvcm1hdHM6IHt9XG4gIH0sXG4gIHRpY2tzOiB7XG4gICAgc291cmNlOiAnYXV0bycsXG4gICAgbWFqb3I6IHtcbiAgICAgIGVuYWJsZWQ6IGZhbHNlXG4gICAgfVxuICB9XG59O1xuXG5mdW5jdGlvbiBpbnRlcnBvbGF0ZSh0YWJsZSwgdmFsLCByZXZlcnNlKSB7XG4gIGxldCBsbyA9IDA7XG4gIGxldCBoaSA9IHRhYmxlLmxlbmd0aCAtIDE7XG4gIGxldCBwcmV2U291cmNlLCBuZXh0U291cmNlLCBwcmV2VGFyZ2V0LCBuZXh0VGFyZ2V0O1xuICBpZiAocmV2ZXJzZSkge1xuICAgIGlmICh2YWwgPj0gdGFibGVbbG9dLnBvcyAmJiB2YWwgPD0gdGFibGVbaGldLnBvcykge1xuICAgICAgKHtsbywgaGl9ID0gX2xvb2t1cEJ5S2V5KHRhYmxlLCAncG9zJywgdmFsKSk7XG4gICAgfVxuICAgICh7cG9zOiBwcmV2U291cmNlLCB0aW1lOiBwcmV2VGFyZ2V0fSA9IHRhYmxlW2xvXSk7XG4gICAgKHtwb3M6IG5leHRTb3VyY2UsIHRpbWU6IG5leHRUYXJnZXR9ID0gdGFibGVbaGldKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAodmFsID49IHRhYmxlW2xvXS50aW1lICYmIHZhbCA8PSB0YWJsZVtoaV0udGltZSkge1xuICAgICAgKHtsbywgaGl9ID0gX2xvb2t1cEJ5S2V5KHRhYmxlLCAndGltZScsIHZhbCkpO1xuICAgIH1cbiAgICAoe3RpbWU6IHByZXZTb3VyY2UsIHBvczogcHJldlRhcmdldH0gPSB0YWJsZVtsb10pO1xuICAgICh7dGltZTogbmV4dFNvdXJjZSwgcG9zOiBuZXh0VGFyZ2V0fSA9IHRhYmxlW2hpXSk7XG4gIH1cbiAgY29uc3Qgc3BhbiA9IG5leHRTb3VyY2UgLSBwcmV2U291cmNlO1xuICByZXR1cm4gc3BhbiA/IHByZXZUYXJnZXQgKyAobmV4dFRhcmdldCAtIHByZXZUYXJnZXQpICogKHZhbCAtIHByZXZTb3VyY2UpIC8gc3BhbiA6IHByZXZUYXJnZXQ7XG59XG5jbGFzcyBUaW1lU2VyaWVzU2NhbGUgZXh0ZW5kcyBUaW1lU2NhbGUge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcbiAgICB0aGlzLl90YWJsZSA9IFtdO1xuICAgIHRoaXMuX21pblBvcyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl90YWJsZVJhbmdlID0gdW5kZWZpbmVkO1xuICB9XG4gIGluaXRPZmZzZXRzKCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCB0aW1lc3RhbXBzID0gbWUuX2dldFRpbWVzdGFtcHNGb3JUYWJsZSgpO1xuICAgIGNvbnN0IHRhYmxlID0gbWUuX3RhYmxlID0gbWUuYnVpbGRMb29rdXBUYWJsZSh0aW1lc3RhbXBzKTtcbiAgICBtZS5fbWluUG9zID0gaW50ZXJwb2xhdGUodGFibGUsIG1lLm1pbik7XG4gICAgbWUuX3RhYmxlUmFuZ2UgPSBpbnRlcnBvbGF0ZSh0YWJsZSwgbWUubWF4KSAtIG1lLl9taW5Qb3M7XG4gICAgc3VwZXIuaW5pdE9mZnNldHModGltZXN0YW1wcyk7XG4gIH1cbiAgYnVpbGRMb29rdXBUYWJsZSh0aW1lc3RhbXBzKSB7XG4gICAgY29uc3Qge21pbiwgbWF4fSA9IHRoaXM7XG4gICAgY29uc3QgaXRlbXMgPSBbXTtcbiAgICBjb25zdCB0YWJsZSA9IFtdO1xuICAgIGxldCBpLCBpbGVuLCBwcmV2LCBjdXJyLCBuZXh0O1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSB0aW1lc3RhbXBzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgY3VyciA9IHRpbWVzdGFtcHNbaV07XG4gICAgICBpZiAoY3VyciA+PSBtaW4gJiYgY3VyciA8PSBtYXgpIHtcbiAgICAgICAgaXRlbXMucHVzaChjdXJyKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGl0ZW1zLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHt0aW1lOiBtaW4sIHBvczogMH0sXG4gICAgICAgIHt0aW1lOiBtYXgsIHBvczogMX1cbiAgICAgIF07XG4gICAgfVxuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICAgIG5leHQgPSBpdGVtc1tpICsgMV07XG4gICAgICBwcmV2ID0gaXRlbXNbaSAtIDFdO1xuICAgICAgY3VyciA9IGl0ZW1zW2ldO1xuICAgICAgaWYgKE1hdGgucm91bmQoKG5leHQgKyBwcmV2KSAvIDIpICE9PSBjdXJyKSB7XG4gICAgICAgIHRhYmxlLnB1c2goe3RpbWU6IGN1cnIsIHBvczogaSAvIChpbGVuIC0gMSl9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRhYmxlO1xuICB9XG4gIF9nZXRUaW1lc3RhbXBzRm9yVGFibGUoKSB7XG4gICAgY29uc3QgbWUgPSB0aGlzO1xuICAgIGxldCB0aW1lc3RhbXBzID0gbWUuX2NhY2hlLmFsbCB8fCBbXTtcbiAgICBpZiAodGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0aW1lc3RhbXBzO1xuICAgIH1cbiAgICBjb25zdCBkYXRhID0gbWUuZ2V0RGF0YVRpbWVzdGFtcHMoKTtcbiAgICBjb25zdCBsYWJlbCA9IG1lLmdldExhYmVsVGltZXN0YW1wcygpO1xuICAgIGlmIChkYXRhLmxlbmd0aCAmJiBsYWJlbC5sZW5ndGgpIHtcbiAgICAgIHRpbWVzdGFtcHMgPSBtZS5ub3JtYWxpemUoZGF0YS5jb25jYXQobGFiZWwpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGltZXN0YW1wcyA9IGRhdGEubGVuZ3RoID8gZGF0YSA6IGxhYmVsO1xuICAgIH1cbiAgICB0aW1lc3RhbXBzID0gbWUuX2NhY2hlLmFsbCA9IHRpbWVzdGFtcHM7XG4gICAgcmV0dXJuIHRpbWVzdGFtcHM7XG4gIH1cbiAgZ2V0RGVjaW1hbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgcmV0dXJuIChpbnRlcnBvbGF0ZSh0aGlzLl90YWJsZSwgdmFsdWUpIC0gdGhpcy5fbWluUG9zKSAvIHRoaXMuX3RhYmxlUmFuZ2U7XG4gIH1cbiAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgIGNvbnN0IG1lID0gdGhpcztcbiAgICBjb25zdCBvZmZzZXRzID0gbWUuX29mZnNldHM7XG4gICAgY29uc3QgZGVjaW1hbCA9IG1lLmdldERlY2ltYWxGb3JQaXhlbChwaXhlbCkgLyBvZmZzZXRzLmZhY3RvciAtIG9mZnNldHMuZW5kO1xuICAgIHJldHVybiBpbnRlcnBvbGF0ZShtZS5fdGFibGUsIGRlY2ltYWwgKiBtZS5fdGFibGVSYW5nZSArIG1lLl9taW5Qb3MsIHRydWUpO1xuICB9XG59XG5UaW1lU2VyaWVzU2NhbGUuaWQgPSAndGltZXNlcmllcyc7XG5UaW1lU2VyaWVzU2NhbGUuZGVmYXVsdHMgPSBUaW1lU2NhbGUuZGVmYXVsdHM7XG5cbnZhciBzY2FsZXMgPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG5fX3Byb3RvX186IG51bGwsXG5DYXRlZ29yeVNjYWxlOiBDYXRlZ29yeVNjYWxlLFxuTGluZWFyU2NhbGU6IExpbmVhclNjYWxlLFxuTG9nYXJpdGhtaWNTY2FsZTogTG9nYXJpdGhtaWNTY2FsZSxcblJhZGlhbExpbmVhclNjYWxlOiBSYWRpYWxMaW5lYXJTY2FsZSxcblRpbWVTY2FsZTogVGltZVNjYWxlLFxuVGltZVNlcmllc1NjYWxlOiBUaW1lU2VyaWVzU2NhbGVcbn0pO1xuXG5jb25zdCByZWdpc3RlcmFibGVzID0gW1xuICBjb250cm9sbGVycyxcbiAgZWxlbWVudHMsXG4gIHBsdWdpbnMsXG4gIHNjYWxlcyxcbl07XG5cbmV4cG9ydCB7IEFuaW1hdGlvbiwgQW5pbWF0aW9ucywgQXJjRWxlbWVudCwgQmFyQ29udHJvbGxlciwgQmFyRWxlbWVudCwgQmFzZVBsYXRmb3JtLCBCYXNpY1BsYXRmb3JtLCBCdWJibGVDb250cm9sbGVyLCBDYXRlZ29yeVNjYWxlLCBDaGFydCwgRGF0YXNldENvbnRyb2xsZXIsIHBsdWdpbl9kZWNpbWF0aW9uIGFzIERlY2ltYXRpb24sIERvbVBsYXRmb3JtLCBEb3VnaG51dENvbnRyb2xsZXIsIEVsZW1lbnQsIHBsdWdpbl9maWxsZXIgYXMgRmlsbGVyLCBJbnRlcmFjdGlvbiwgcGx1Z2luX2xlZ2VuZCBhcyBMZWdlbmQsIExpbmVDb250cm9sbGVyLCBMaW5lRWxlbWVudCwgTGluZWFyU2NhbGUsIExvZ2FyaXRobWljU2NhbGUsIFBpZUNvbnRyb2xsZXIsIFBvaW50RWxlbWVudCwgUG9sYXJBcmVhQ29udHJvbGxlciwgUmFkYXJDb250cm9sbGVyLCBSYWRpYWxMaW5lYXJTY2FsZSwgU2NhbGUsIFNjYXR0ZXJDb250cm9sbGVyLCBwbHVnaW5fc3VidGl0bGUgYXMgU3ViVGl0bGUsIFRpY2tzLCBUaW1lU2NhbGUsIFRpbWVTZXJpZXNTY2FsZSwgcGx1Z2luX3RpdGxlIGFzIFRpdGxlLCBwbHVnaW5fdG9vbHRpcCBhcyBUb29sdGlwLCBhZGFwdGVycyBhcyBfYWRhcHRlcnMsIF9kZXRlY3RQbGF0Zm9ybSwgYW5pbWF0b3IsIGNvbnRyb2xsZXJzLCBlbGVtZW50cywgbGF5b3V0cywgcGx1Z2lucywgcmVnaXN0ZXJhYmxlcywgcmVnaXN0cnksIHNjYWxlcyB9O1xuIiwiLyohXG4gKiBDaGFydC5qcyB2My41LjFcbiAqIGh0dHBzOi8vd3d3LmNoYXJ0anMub3JnXG4gKiAoYykgMjAyMSBDaGFydC5qcyBDb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICovXG5mdW5jdGlvbiBmb250U3RyaW5nKHBpeGVsU2l6ZSwgZm9udFN0eWxlLCBmb250RmFtaWx5KSB7XG4gIHJldHVybiBmb250U3R5bGUgKyAnICcgKyBwaXhlbFNpemUgKyAncHggJyArIGZvbnRGYW1pbHk7XG59XG5jb25zdCByZXF1ZXN0QW5pbUZyYW1lID0gKGZ1bmN0aW9uKCkge1xuICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgIH07XG4gIH1cbiAgcmV0dXJuIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWU7XG59KCkpO1xuZnVuY3Rpb24gdGhyb3R0bGVkKGZuLCB0aGlzQXJnLCB1cGRhdGVGbikge1xuICBjb25zdCB1cGRhdGVBcmdzID0gdXBkYXRlRm4gfHwgKChhcmdzKSA9PiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmdzKSk7XG4gIGxldCB0aWNraW5nID0gZmFsc2U7XG4gIGxldCBhcmdzID0gW107XG4gIHJldHVybiBmdW5jdGlvbiguLi5yZXN0KSB7XG4gICAgYXJncyA9IHVwZGF0ZUFyZ3MocmVzdCk7XG4gICAgaWYgKCF0aWNraW5nKSB7XG4gICAgICB0aWNraW5nID0gdHJ1ZTtcbiAgICAgIHJlcXVlc3RBbmltRnJhbWUuY2FsbCh3aW5kb3csICgpID0+IHtcbiAgICAgICAgdGlja2luZyA9IGZhbHNlO1xuICAgICAgICBmbi5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfTtcbn1cbmZ1bmN0aW9uIGRlYm91bmNlKGZuLCBkZWxheSkge1xuICBsZXQgdGltZW91dDtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIGlmIChkZWxheSkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoZm4sIGRlbGF5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm4oKTtcbiAgICB9XG4gICAgcmV0dXJuIGRlbGF5O1xuICB9O1xufVxuY29uc3QgX3RvTGVmdFJpZ2h0Q2VudGVyID0gKGFsaWduKSA9PiBhbGlnbiA9PT0gJ3N0YXJ0JyA/ICdsZWZ0JyA6IGFsaWduID09PSAnZW5kJyA/ICdyaWdodCcgOiAnY2VudGVyJztcbmNvbnN0IF9hbGlnblN0YXJ0RW5kID0gKGFsaWduLCBzdGFydCwgZW5kKSA9PiBhbGlnbiA9PT0gJ3N0YXJ0JyA/IHN0YXJ0IDogYWxpZ24gPT09ICdlbmQnID8gZW5kIDogKHN0YXJ0ICsgZW5kKSAvIDI7XG5jb25zdCBfdGV4dFggPSAoYWxpZ24sIGxlZnQsIHJpZ2h0LCBydGwpID0+IHtcbiAgY29uc3QgY2hlY2sgPSBydGwgPyAnbGVmdCcgOiAncmlnaHQnO1xuICByZXR1cm4gYWxpZ24gPT09IGNoZWNrID8gcmlnaHQgOiBhbGlnbiA9PT0gJ2NlbnRlcicgPyAobGVmdCArIHJpZ2h0KSAvIDIgOiBsZWZ0O1xufTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5jb25zdCB1aWQgPSAoZnVuY3Rpb24oKSB7XG4gIGxldCBpZCA9IDA7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gaWQrKztcbiAgfTtcbn0oKSk7XG5mdW5jdGlvbiBpc051bGxPclVuZGVmKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbCB8fCB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuZnVuY3Rpb24gaXNBcnJheSh2YWx1ZSkge1xuICBpZiAoQXJyYXkuaXNBcnJheSAmJiBBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGNvbnN0IHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICBpZiAodHlwZS5zdWJzdHIoMCwgNykgPT09ICdbb2JqZWN0JyAmJiB0eXBlLnN1YnN0cigtNikgPT09ICdBcnJheV0nKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICE9PSBudWxsICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09ICdbb2JqZWN0IE9iamVjdF0nO1xufVxuY29uc3QgaXNOdW1iZXJGaW5pdGUgPSAodmFsdWUpID0+ICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInIHx8IHZhbHVlIGluc3RhbmNlb2YgTnVtYmVyKSAmJiBpc0Zpbml0ZSgrdmFsdWUpO1xuZnVuY3Rpb24gZmluaXRlT3JEZWZhdWx0KHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgcmV0dXJuIGlzTnVtYmVyRmluaXRlKHZhbHVlKSA/IHZhbHVlIDogZGVmYXVsdFZhbHVlO1xufVxuZnVuY3Rpb24gdmFsdWVPckRlZmF1bHQodmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyA/IGRlZmF1bHRWYWx1ZSA6IHZhbHVlO1xufVxuY29uc3QgdG9QZXJjZW50YWdlID0gKHZhbHVlLCBkaW1lbnNpb24pID0+XG4gIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUuZW5kc1dpdGgoJyUnKSA/XG4gICAgcGFyc2VGbG9hdCh2YWx1ZSkgLyAxMDBcbiAgICA6IHZhbHVlIC8gZGltZW5zaW9uO1xuY29uc3QgdG9EaW1lbnNpb24gPSAodmFsdWUsIGRpbWVuc2lvbikgPT5cbiAgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5lbmRzV2l0aCgnJScpID9cbiAgICBwYXJzZUZsb2F0KHZhbHVlKSAvIDEwMCAqIGRpbWVuc2lvblxuICAgIDogK3ZhbHVlO1xuZnVuY3Rpb24gY2FsbGJhY2soZm4sIGFyZ3MsIHRoaXNBcmcpIHtcbiAgaWYgKGZuICYmIHR5cGVvZiBmbi5jYWxsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICB9XG59XG5mdW5jdGlvbiBlYWNoKGxvb3BhYmxlLCBmbiwgdGhpc0FyZywgcmV2ZXJzZSkge1xuICBsZXQgaSwgbGVuLCBrZXlzO1xuICBpZiAoaXNBcnJheShsb29wYWJsZSkpIHtcbiAgICBsZW4gPSBsb29wYWJsZS5sZW5ndGg7XG4gICAgaWYgKHJldmVyc2UpIHtcbiAgICAgIGZvciAoaSA9IGxlbiAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGZuLmNhbGwodGhpc0FyZywgbG9vcGFibGVbaV0sIGkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgZm4uY2FsbCh0aGlzQXJnLCBsb29wYWJsZVtpXSwgaSk7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzT2JqZWN0KGxvb3BhYmxlKSkge1xuICAgIGtleXMgPSBPYmplY3Qua2V5cyhsb29wYWJsZSk7XG4gICAgbGVuID0ga2V5cy5sZW5ndGg7XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBmbi5jYWxsKHRoaXNBcmcsIGxvb3BhYmxlW2tleXNbaV1dLCBrZXlzW2ldKTtcbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uIF9lbGVtZW50c0VxdWFsKGEwLCBhMSkge1xuICBsZXQgaSwgaWxlbiwgdjAsIHYxO1xuICBpZiAoIWEwIHx8ICFhMSB8fCBhMC5sZW5ndGggIT09IGExLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKGkgPSAwLCBpbGVuID0gYTAubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgdjAgPSBhMFtpXTtcbiAgICB2MSA9IGExW2ldO1xuICAgIGlmICh2MC5kYXRhc2V0SW5kZXggIT09IHYxLmRhdGFzZXRJbmRleCB8fCB2MC5pbmRleCAhPT0gdjEuaW5kZXgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiBjbG9uZSQxKHNvdXJjZSkge1xuICBpZiAoaXNBcnJheShzb3VyY2UpKSB7XG4gICAgcmV0dXJuIHNvdXJjZS5tYXAoY2xvbmUkMSk7XG4gIH1cbiAgaWYgKGlzT2JqZWN0KHNvdXJjZSkpIHtcbiAgICBjb25zdCB0YXJnZXQgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhzb3VyY2UpO1xuICAgIGNvbnN0IGtsZW4gPSBrZXlzLmxlbmd0aDtcbiAgICBsZXQgayA9IDA7XG4gICAgZm9yICg7IGsgPCBrbGVuOyArK2spIHtcbiAgICAgIHRhcmdldFtrZXlzW2tdXSA9IGNsb25lJDEoc291cmNlW2tleXNba11dKTtcbiAgICB9XG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfVxuICByZXR1cm4gc291cmNlO1xufVxuZnVuY3Rpb24gaXNWYWxpZEtleShrZXkpIHtcbiAgcmV0dXJuIFsnX19wcm90b19fJywgJ3Byb3RvdHlwZScsICdjb25zdHJ1Y3RvciddLmluZGV4T2Yoa2V5KSA9PT0gLTE7XG59XG5mdW5jdGlvbiBfbWVyZ2VyKGtleSwgdGFyZ2V0LCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgaWYgKCFpc1ZhbGlkS2V5KGtleSkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgdHZhbCA9IHRhcmdldFtrZXldO1xuICBjb25zdCBzdmFsID0gc291cmNlW2tleV07XG4gIGlmIChpc09iamVjdCh0dmFsKSAmJiBpc09iamVjdChzdmFsKSkge1xuICAgIG1lcmdlKHR2YWwsIHN2YWwsIG9wdGlvbnMpO1xuICB9IGVsc2Uge1xuICAgIHRhcmdldFtrZXldID0gY2xvbmUkMShzdmFsKTtcbiAgfVxufVxuZnVuY3Rpb24gbWVyZ2UodGFyZ2V0LCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgY29uc3Qgc291cmNlcyA9IGlzQXJyYXkoc291cmNlKSA/IHNvdXJjZSA6IFtzb3VyY2VdO1xuICBjb25zdCBpbGVuID0gc291cmNlcy5sZW5ndGg7XG4gIGlmICghaXNPYmplY3QodGFyZ2V0KSkge1xuICAgIHJldHVybiB0YXJnZXQ7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGNvbnN0IG1lcmdlciA9IG9wdGlvbnMubWVyZ2VyIHx8IF9tZXJnZXI7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgc291cmNlID0gc291cmNlc1tpXTtcbiAgICBpZiAoIWlzT2JqZWN0KHNvdXJjZSkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoc291cmNlKTtcbiAgICBmb3IgKGxldCBrID0gMCwga2xlbiA9IGtleXMubGVuZ3RoOyBrIDwga2xlbjsgKytrKSB7XG4gICAgICBtZXJnZXIoa2V5c1trXSwgdGFyZ2V0LCBzb3VyY2UsIG9wdGlvbnMpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdGFyZ2V0O1xufVxuZnVuY3Rpb24gbWVyZ2VJZih0YXJnZXQsIHNvdXJjZSkge1xuICByZXR1cm4gbWVyZ2UodGFyZ2V0LCBzb3VyY2UsIHttZXJnZXI6IF9tZXJnZXJJZn0pO1xufVxuZnVuY3Rpb24gX21lcmdlcklmKGtleSwgdGFyZ2V0LCBzb3VyY2UpIHtcbiAgaWYgKCFpc1ZhbGlkS2V5KGtleSkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgdHZhbCA9IHRhcmdldFtrZXldO1xuICBjb25zdCBzdmFsID0gc291cmNlW2tleV07XG4gIGlmIChpc09iamVjdCh0dmFsKSAmJiBpc09iamVjdChzdmFsKSkge1xuICAgIG1lcmdlSWYodHZhbCwgc3ZhbCk7XG4gIH0gZWxzZSBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0YXJnZXQsIGtleSkpIHtcbiAgICB0YXJnZXRba2V5XSA9IGNsb25lJDEoc3ZhbCk7XG4gIH1cbn1cbmZ1bmN0aW9uIF9kZXByZWNhdGVkKHNjb3BlLCB2YWx1ZSwgcHJldmlvdXMsIGN1cnJlbnQpIHtcbiAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zb2xlLndhcm4oc2NvcGUgKyAnOiBcIicgKyBwcmV2aW91cyArXG5cdFx0XHQnXCIgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBcIicgKyBjdXJyZW50ICsgJ1wiIGluc3RlYWQnKTtcbiAgfVxufVxuY29uc3QgZW1wdHlTdHJpbmcgPSAnJztcbmNvbnN0IGRvdCA9ICcuJztcbmZ1bmN0aW9uIGluZGV4T2ZEb3RPckxlbmd0aChrZXksIHN0YXJ0KSB7XG4gIGNvbnN0IGlkeCA9IGtleS5pbmRleE9mKGRvdCwgc3RhcnQpO1xuICByZXR1cm4gaWR4ID09PSAtMSA/IGtleS5sZW5ndGggOiBpZHg7XG59XG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0S2V5KG9iaiwga2V5KSB7XG4gIGlmIChrZXkgPT09IGVtcHR5U3RyaW5nKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuICBsZXQgcG9zID0gMDtcbiAgbGV0IGlkeCA9IGluZGV4T2ZEb3RPckxlbmd0aChrZXksIHBvcyk7XG4gIHdoaWxlIChvYmogJiYgaWR4ID4gcG9zKSB7XG4gICAgb2JqID0gb2JqW2tleS5zdWJzdHIocG9zLCBpZHggLSBwb3MpXTtcbiAgICBwb3MgPSBpZHggKyAxO1xuICAgIGlkeCA9IGluZGV4T2ZEb3RPckxlbmd0aChrZXksIHBvcyk7XG4gIH1cbiAgcmV0dXJuIG9iajtcbn1cbmZ1bmN0aW9uIF9jYXBpdGFsaXplKHN0cikge1xuICByZXR1cm4gc3RyLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyLnNsaWNlKDEpO1xufVxuY29uc3QgZGVmaW5lZCA9ICh2YWx1ZSkgPT4gdHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJztcbmNvbnN0IGlzRnVuY3Rpb24gPSAodmFsdWUpID0+IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcbmNvbnN0IHNldHNFcXVhbCA9IChhLCBiKSA9PiB7XG4gIGlmIChhLnNpemUgIT09IGIuc2l6ZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKGNvbnN0IGl0ZW0gb2YgYSkge1xuICAgIGlmICghYi5oYXMoaXRlbSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5jb25zdCBQSSA9IE1hdGguUEk7XG5jb25zdCBUQVUgPSAyICogUEk7XG5jb25zdCBQSVRBVSA9IFRBVSArIFBJO1xuY29uc3QgSU5GSU5JVFkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG5jb25zdCBSQURfUEVSX0RFRyA9IFBJIC8gMTgwO1xuY29uc3QgSEFMRl9QSSA9IFBJIC8gMjtcbmNvbnN0IFFVQVJURVJfUEkgPSBQSSAvIDQ7XG5jb25zdCBUV09fVEhJUkRTX1BJID0gUEkgKiAyIC8gMztcbmNvbnN0IGxvZzEwID0gTWF0aC5sb2cxMDtcbmNvbnN0IHNpZ24gPSBNYXRoLnNpZ247XG5mdW5jdGlvbiBuaWNlTnVtKHJhbmdlKSB7XG4gIGNvbnN0IHJvdW5kZWRSYW5nZSA9IE1hdGgucm91bmQocmFuZ2UpO1xuICByYW5nZSA9IGFsbW9zdEVxdWFscyhyYW5nZSwgcm91bmRlZFJhbmdlLCByYW5nZSAvIDEwMDApID8gcm91bmRlZFJhbmdlIDogcmFuZ2U7XG4gIGNvbnN0IG5pY2VSYW5nZSA9IE1hdGgucG93KDEwLCBNYXRoLmZsb29yKGxvZzEwKHJhbmdlKSkpO1xuICBjb25zdCBmcmFjdGlvbiA9IHJhbmdlIC8gbmljZVJhbmdlO1xuICBjb25zdCBuaWNlRnJhY3Rpb24gPSBmcmFjdGlvbiA8PSAxID8gMSA6IGZyYWN0aW9uIDw9IDIgPyAyIDogZnJhY3Rpb24gPD0gNSA/IDUgOiAxMDtcbiAgcmV0dXJuIG5pY2VGcmFjdGlvbiAqIG5pY2VSYW5nZTtcbn1cbmZ1bmN0aW9uIF9mYWN0b3JpemUodmFsdWUpIHtcbiAgY29uc3QgcmVzdWx0ID0gW107XG4gIGNvbnN0IHNxcnQgPSBNYXRoLnNxcnQodmFsdWUpO1xuICBsZXQgaTtcbiAgZm9yIChpID0gMTsgaSA8IHNxcnQ7IGkrKykge1xuICAgIGlmICh2YWx1ZSAlIGkgPT09IDApIHtcbiAgICAgIHJlc3VsdC5wdXNoKGkpO1xuICAgICAgcmVzdWx0LnB1c2godmFsdWUgLyBpKTtcbiAgICB9XG4gIH1cbiAgaWYgKHNxcnQgPT09IChzcXJ0IHwgMCkpIHtcbiAgICByZXN1bHQucHVzaChzcXJ0KTtcbiAgfVxuICByZXN1bHQuc29ydCgoYSwgYikgPT4gYSAtIGIpLnBvcCgpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gaXNOdW1iZXIobikge1xuICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xufVxuZnVuY3Rpb24gYWxtb3N0RXF1YWxzKHgsIHksIGVwc2lsb24pIHtcbiAgcmV0dXJuIE1hdGguYWJzKHggLSB5KSA8IGVwc2lsb247XG59XG5mdW5jdGlvbiBhbG1vc3RXaG9sZSh4LCBlcHNpbG9uKSB7XG4gIGNvbnN0IHJvdW5kZWQgPSBNYXRoLnJvdW5kKHgpO1xuICByZXR1cm4gKChyb3VuZGVkIC0gZXBzaWxvbikgPD0geCkgJiYgKChyb3VuZGVkICsgZXBzaWxvbikgPj0geCk7XG59XG5mdW5jdGlvbiBfc2V0TWluQW5kTWF4QnlLZXkoYXJyYXksIHRhcmdldCwgcHJvcGVydHkpIHtcbiAgbGV0IGksIGlsZW4sIHZhbHVlO1xuICBmb3IgKGkgPSAwLCBpbGVuID0gYXJyYXkubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKSB7XG4gICAgdmFsdWUgPSBhcnJheVtpXVtwcm9wZXJ0eV07XG4gICAgaWYgKCFpc05hTih2YWx1ZSkpIHtcbiAgICAgIHRhcmdldC5taW4gPSBNYXRoLm1pbih0YXJnZXQubWluLCB2YWx1ZSk7XG4gICAgICB0YXJnZXQubWF4ID0gTWF0aC5tYXgodGFyZ2V0Lm1heCwgdmFsdWUpO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gdG9SYWRpYW5zKGRlZ3JlZXMpIHtcbiAgcmV0dXJuIGRlZ3JlZXMgKiAoUEkgLyAxODApO1xufVxuZnVuY3Rpb24gdG9EZWdyZWVzKHJhZGlhbnMpIHtcbiAgcmV0dXJuIHJhZGlhbnMgKiAoMTgwIC8gUEkpO1xufVxuZnVuY3Rpb24gX2RlY2ltYWxQbGFjZXMoeCkge1xuICBpZiAoIWlzTnVtYmVyRmluaXRlKHgpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGxldCBlID0gMTtcbiAgbGV0IHAgPSAwO1xuICB3aGlsZSAoTWF0aC5yb3VuZCh4ICogZSkgLyBlICE9PSB4KSB7XG4gICAgZSAqPSAxMDtcbiAgICBwKys7XG4gIH1cbiAgcmV0dXJuIHA7XG59XG5mdW5jdGlvbiBnZXRBbmdsZUZyb21Qb2ludChjZW50cmVQb2ludCwgYW5nbGVQb2ludCkge1xuICBjb25zdCBkaXN0YW5jZUZyb21YQ2VudGVyID0gYW5nbGVQb2ludC54IC0gY2VudHJlUG9pbnQueDtcbiAgY29uc3QgZGlzdGFuY2VGcm9tWUNlbnRlciA9IGFuZ2xlUG9pbnQueSAtIGNlbnRyZVBvaW50Lnk7XG4gIGNvbnN0IHJhZGlhbERpc3RhbmNlRnJvbUNlbnRlciA9IE1hdGguc3FydChkaXN0YW5jZUZyb21YQ2VudGVyICogZGlzdGFuY2VGcm9tWENlbnRlciArIGRpc3RhbmNlRnJvbVlDZW50ZXIgKiBkaXN0YW5jZUZyb21ZQ2VudGVyKTtcbiAgbGV0IGFuZ2xlID0gTWF0aC5hdGFuMihkaXN0YW5jZUZyb21ZQ2VudGVyLCBkaXN0YW5jZUZyb21YQ2VudGVyKTtcbiAgaWYgKGFuZ2xlIDwgKC0wLjUgKiBQSSkpIHtcbiAgICBhbmdsZSArPSBUQVU7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBhbmdsZSxcbiAgICBkaXN0YW5jZTogcmFkaWFsRGlzdGFuY2VGcm9tQ2VudGVyXG4gIH07XG59XG5mdW5jdGlvbiBkaXN0YW5jZUJldHdlZW5Qb2ludHMocHQxLCBwdDIpIHtcbiAgcmV0dXJuIE1hdGguc3FydChNYXRoLnBvdyhwdDIueCAtIHB0MS54LCAyKSArIE1hdGgucG93KHB0Mi55IC0gcHQxLnksIDIpKTtcbn1cbmZ1bmN0aW9uIF9hbmdsZURpZmYoYSwgYikge1xuICByZXR1cm4gKGEgLSBiICsgUElUQVUpICUgVEFVIC0gUEk7XG59XG5mdW5jdGlvbiBfbm9ybWFsaXplQW5nbGUoYSkge1xuICByZXR1cm4gKGEgJSBUQVUgKyBUQVUpICUgVEFVO1xufVxuZnVuY3Rpb24gX2FuZ2xlQmV0d2VlbihhbmdsZSwgc3RhcnQsIGVuZCwgc2FtZUFuZ2xlSXNGdWxsQ2lyY2xlKSB7XG4gIGNvbnN0IGEgPSBfbm9ybWFsaXplQW5nbGUoYW5nbGUpO1xuICBjb25zdCBzID0gX25vcm1hbGl6ZUFuZ2xlKHN0YXJ0KTtcbiAgY29uc3QgZSA9IF9ub3JtYWxpemVBbmdsZShlbmQpO1xuICBjb25zdCBhbmdsZVRvU3RhcnQgPSBfbm9ybWFsaXplQW5nbGUocyAtIGEpO1xuICBjb25zdCBhbmdsZVRvRW5kID0gX25vcm1hbGl6ZUFuZ2xlKGUgLSBhKTtcbiAgY29uc3Qgc3RhcnRUb0FuZ2xlID0gX25vcm1hbGl6ZUFuZ2xlKGEgLSBzKTtcbiAgY29uc3QgZW5kVG9BbmdsZSA9IF9ub3JtYWxpemVBbmdsZShhIC0gZSk7XG4gIHJldHVybiBhID09PSBzIHx8IGEgPT09IGUgfHwgKHNhbWVBbmdsZUlzRnVsbENpcmNsZSAmJiBzID09PSBlKVxuICAgIHx8IChhbmdsZVRvU3RhcnQgPiBhbmdsZVRvRW5kICYmIHN0YXJ0VG9BbmdsZSA8IGVuZFRvQW5nbGUpO1xufVxuZnVuY3Rpb24gX2xpbWl0VmFsdWUodmFsdWUsIG1pbiwgbWF4KSB7XG4gIHJldHVybiBNYXRoLm1heChtaW4sIE1hdGgubWluKG1heCwgdmFsdWUpKTtcbn1cbmZ1bmN0aW9uIF9pbnQxNlJhbmdlKHZhbHVlKSB7XG4gIHJldHVybiBfbGltaXRWYWx1ZSh2YWx1ZSwgLTMyNzY4LCAzMjc2Nyk7XG59XG5cbmNvbnN0IGF0RWRnZSA9ICh0KSA9PiB0ID09PSAwIHx8IHQgPT09IDE7XG5jb25zdCBlbGFzdGljSW4gPSAodCwgcywgcCkgPT4gLShNYXRoLnBvdygyLCAxMCAqICh0IC09IDEpKSAqIE1hdGguc2luKCh0IC0gcykgKiBUQVUgLyBwKSk7XG5jb25zdCBlbGFzdGljT3V0ID0gKHQsIHMsIHApID0+IE1hdGgucG93KDIsIC0xMCAqIHQpICogTWF0aC5zaW4oKHQgLSBzKSAqIFRBVSAvIHApICsgMTtcbmNvbnN0IGVmZmVjdHMgPSB7XG4gIGxpbmVhcjogdCA9PiB0LFxuICBlYXNlSW5RdWFkOiB0ID0+IHQgKiB0LFxuICBlYXNlT3V0UXVhZDogdCA9PiAtdCAqICh0IC0gMiksXG4gIGVhc2VJbk91dFF1YWQ6IHQgPT4gKCh0IC89IDAuNSkgPCAxKVxuICAgID8gMC41ICogdCAqIHRcbiAgICA6IC0wLjUgKiAoKC0tdCkgKiAodCAtIDIpIC0gMSksXG4gIGVhc2VJbkN1YmljOiB0ID0+IHQgKiB0ICogdCxcbiAgZWFzZU91dEN1YmljOiB0ID0+ICh0IC09IDEpICogdCAqIHQgKyAxLFxuICBlYXNlSW5PdXRDdWJpYzogdCA9PiAoKHQgLz0gMC41KSA8IDEpXG4gICAgPyAwLjUgKiB0ICogdCAqIHRcbiAgICA6IDAuNSAqICgodCAtPSAyKSAqIHQgKiB0ICsgMiksXG4gIGVhc2VJblF1YXJ0OiB0ID0+IHQgKiB0ICogdCAqIHQsXG4gIGVhc2VPdXRRdWFydDogdCA9PiAtKCh0IC09IDEpICogdCAqIHQgKiB0IC0gMSksXG4gIGVhc2VJbk91dFF1YXJ0OiB0ID0+ICgodCAvPSAwLjUpIDwgMSlcbiAgICA/IDAuNSAqIHQgKiB0ICogdCAqIHRcbiAgICA6IC0wLjUgKiAoKHQgLT0gMikgKiB0ICogdCAqIHQgLSAyKSxcbiAgZWFzZUluUXVpbnQ6IHQgPT4gdCAqIHQgKiB0ICogdCAqIHQsXG4gIGVhc2VPdXRRdWludDogdCA9PiAodCAtPSAxKSAqIHQgKiB0ICogdCAqIHQgKyAxLFxuICBlYXNlSW5PdXRRdWludDogdCA9PiAoKHQgLz0gMC41KSA8IDEpXG4gICAgPyAwLjUgKiB0ICogdCAqIHQgKiB0ICogdFxuICAgIDogMC41ICogKCh0IC09IDIpICogdCAqIHQgKiB0ICogdCArIDIpLFxuICBlYXNlSW5TaW5lOiB0ID0+IC1NYXRoLmNvcyh0ICogSEFMRl9QSSkgKyAxLFxuICBlYXNlT3V0U2luZTogdCA9PiBNYXRoLnNpbih0ICogSEFMRl9QSSksXG4gIGVhc2VJbk91dFNpbmU6IHQgPT4gLTAuNSAqIChNYXRoLmNvcyhQSSAqIHQpIC0gMSksXG4gIGVhc2VJbkV4cG86IHQgPT4gKHQgPT09IDApID8gMCA6IE1hdGgucG93KDIsIDEwICogKHQgLSAxKSksXG4gIGVhc2VPdXRFeHBvOiB0ID0+ICh0ID09PSAxKSA/IDEgOiAtTWF0aC5wb3coMiwgLTEwICogdCkgKyAxLFxuICBlYXNlSW5PdXRFeHBvOiB0ID0+IGF0RWRnZSh0KSA/IHQgOiB0IDwgMC41XG4gICAgPyAwLjUgKiBNYXRoLnBvdygyLCAxMCAqICh0ICogMiAtIDEpKVxuICAgIDogMC41ICogKC1NYXRoLnBvdygyLCAtMTAgKiAodCAqIDIgLSAxKSkgKyAyKSxcbiAgZWFzZUluQ2lyYzogdCA9PiAodCA+PSAxKSA/IHQgOiAtKE1hdGguc3FydCgxIC0gdCAqIHQpIC0gMSksXG4gIGVhc2VPdXRDaXJjOiB0ID0+IE1hdGguc3FydCgxIC0gKHQgLT0gMSkgKiB0KSxcbiAgZWFzZUluT3V0Q2lyYzogdCA9PiAoKHQgLz0gMC41KSA8IDEpXG4gICAgPyAtMC41ICogKE1hdGguc3FydCgxIC0gdCAqIHQpIC0gMSlcbiAgICA6IDAuNSAqIChNYXRoLnNxcnQoMSAtICh0IC09IDIpICogdCkgKyAxKSxcbiAgZWFzZUluRWxhc3RpYzogdCA9PiBhdEVkZ2UodCkgPyB0IDogZWxhc3RpY0luKHQsIDAuMDc1LCAwLjMpLFxuICBlYXNlT3V0RWxhc3RpYzogdCA9PiBhdEVkZ2UodCkgPyB0IDogZWxhc3RpY091dCh0LCAwLjA3NSwgMC4zKSxcbiAgZWFzZUluT3V0RWxhc3RpYyh0KSB7XG4gICAgY29uc3QgcyA9IDAuMTEyNTtcbiAgICBjb25zdCBwID0gMC40NTtcbiAgICByZXR1cm4gYXRFZGdlKHQpID8gdCA6XG4gICAgICB0IDwgMC41XG4gICAgICAgID8gMC41ICogZWxhc3RpY0luKHQgKiAyLCBzLCBwKVxuICAgICAgICA6IDAuNSArIDAuNSAqIGVsYXN0aWNPdXQodCAqIDIgLSAxLCBzLCBwKTtcbiAgfSxcbiAgZWFzZUluQmFjayh0KSB7XG4gICAgY29uc3QgcyA9IDEuNzAxNTg7XG4gICAgcmV0dXJuIHQgKiB0ICogKChzICsgMSkgKiB0IC0gcyk7XG4gIH0sXG4gIGVhc2VPdXRCYWNrKHQpIHtcbiAgICBjb25zdCBzID0gMS43MDE1ODtcbiAgICByZXR1cm4gKHQgLT0gMSkgKiB0ICogKChzICsgMSkgKiB0ICsgcykgKyAxO1xuICB9LFxuICBlYXNlSW5PdXRCYWNrKHQpIHtcbiAgICBsZXQgcyA9IDEuNzAxNTg7XG4gICAgaWYgKCh0IC89IDAuNSkgPCAxKSB7XG4gICAgICByZXR1cm4gMC41ICogKHQgKiB0ICogKCgocyAqPSAoMS41MjUpKSArIDEpICogdCAtIHMpKTtcbiAgICB9XG4gICAgcmV0dXJuIDAuNSAqICgodCAtPSAyKSAqIHQgKiAoKChzICo9ICgxLjUyNSkpICsgMSkgKiB0ICsgcykgKyAyKTtcbiAgfSxcbiAgZWFzZUluQm91bmNlOiB0ID0+IDEgLSBlZmZlY3RzLmVhc2VPdXRCb3VuY2UoMSAtIHQpLFxuICBlYXNlT3V0Qm91bmNlKHQpIHtcbiAgICBjb25zdCBtID0gNy41NjI1O1xuICAgIGNvbnN0IGQgPSAyLjc1O1xuICAgIGlmICh0IDwgKDEgLyBkKSkge1xuICAgICAgcmV0dXJuIG0gKiB0ICogdDtcbiAgICB9XG4gICAgaWYgKHQgPCAoMiAvIGQpKSB7XG4gICAgICByZXR1cm4gbSAqICh0IC09ICgxLjUgLyBkKSkgKiB0ICsgMC43NTtcbiAgICB9XG4gICAgaWYgKHQgPCAoMi41IC8gZCkpIHtcbiAgICAgIHJldHVybiBtICogKHQgLT0gKDIuMjUgLyBkKSkgKiB0ICsgMC45Mzc1O1xuICAgIH1cbiAgICByZXR1cm4gbSAqICh0IC09ICgyLjYyNSAvIGQpKSAqIHQgKyAwLjk4NDM3NTtcbiAgfSxcbiAgZWFzZUluT3V0Qm91bmNlOiB0ID0+ICh0IDwgMC41KVxuICAgID8gZWZmZWN0cy5lYXNlSW5Cb3VuY2UodCAqIDIpICogMC41XG4gICAgOiBlZmZlY3RzLmVhc2VPdXRCb3VuY2UodCAqIDIgLSAxKSAqIDAuNSArIDAuNSxcbn07XG5cbi8qIVxuICogQGt1cmtsZS9jb2xvciB2MC4xLjlcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9rdXJrbGUvY29sb3IjcmVhZG1lXG4gKiAoYykgMjAyMCBKdWtrYSBLdXJrZWxhXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAqL1xuY29uc3QgbWFwID0gezA6IDAsIDE6IDEsIDI6IDIsIDM6IDMsIDQ6IDQsIDU6IDUsIDY6IDYsIDc6IDcsIDg6IDgsIDk6IDksIEE6IDEwLCBCOiAxMSwgQzogMTIsIEQ6IDEzLCBFOiAxNCwgRjogMTUsIGE6IDEwLCBiOiAxMSwgYzogMTIsIGQ6IDEzLCBlOiAxNCwgZjogMTV9O1xuY29uc3QgaGV4ID0gJzAxMjM0NTY3ODlBQkNERUYnO1xuY29uc3QgaDEgPSAoYikgPT4gaGV4W2IgJiAweEZdO1xuY29uc3QgaDIgPSAoYikgPT4gaGV4WyhiICYgMHhGMCkgPj4gNF0gKyBoZXhbYiAmIDB4Rl07XG5jb25zdCBlcSA9IChiKSA9PiAoKChiICYgMHhGMCkgPj4gNCkgPT09IChiICYgMHhGKSk7XG5mdW5jdGlvbiBpc1Nob3J0KHYpIHtcblx0cmV0dXJuIGVxKHYucikgJiYgZXEodi5nKSAmJiBlcSh2LmIpICYmIGVxKHYuYSk7XG59XG5mdW5jdGlvbiBoZXhQYXJzZShzdHIpIHtcblx0dmFyIGxlbiA9IHN0ci5sZW5ndGg7XG5cdHZhciByZXQ7XG5cdGlmIChzdHJbMF0gPT09ICcjJykge1xuXHRcdGlmIChsZW4gPT09IDQgfHwgbGVuID09PSA1KSB7XG5cdFx0XHRyZXQgPSB7XG5cdFx0XHRcdHI6IDI1NSAmIG1hcFtzdHJbMV1dICogMTcsXG5cdFx0XHRcdGc6IDI1NSAmIG1hcFtzdHJbMl1dICogMTcsXG5cdFx0XHRcdGI6IDI1NSAmIG1hcFtzdHJbM11dICogMTcsXG5cdFx0XHRcdGE6IGxlbiA9PT0gNSA/IG1hcFtzdHJbNF1dICogMTcgOiAyNTVcblx0XHRcdH07XG5cdFx0fSBlbHNlIGlmIChsZW4gPT09IDcgfHwgbGVuID09PSA5KSB7XG5cdFx0XHRyZXQgPSB7XG5cdFx0XHRcdHI6IG1hcFtzdHJbMV1dIDw8IDQgfCBtYXBbc3RyWzJdXSxcblx0XHRcdFx0ZzogbWFwW3N0clszXV0gPDwgNCB8IG1hcFtzdHJbNF1dLFxuXHRcdFx0XHRiOiBtYXBbc3RyWzVdXSA8PCA0IHwgbWFwW3N0cls2XV0sXG5cdFx0XHRcdGE6IGxlbiA9PT0gOSA/IChtYXBbc3RyWzddXSA8PCA0IHwgbWFwW3N0cls4XV0pIDogMjU1XG5cdFx0XHR9O1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuZnVuY3Rpb24gaGV4U3RyaW5nKHYpIHtcblx0dmFyIGYgPSBpc1Nob3J0KHYpID8gaDEgOiBoMjtcblx0cmV0dXJuIHZcblx0XHQ/ICcjJyArIGYodi5yKSArIGYodi5nKSArIGYodi5iKSArICh2LmEgPCAyNTUgPyBmKHYuYSkgOiAnJylcblx0XHQ6IHY7XG59XG5mdW5jdGlvbiByb3VuZCh2KSB7XG5cdHJldHVybiB2ICsgMC41IHwgMDtcbn1cbmNvbnN0IGxpbSA9ICh2LCBsLCBoKSA9PiBNYXRoLm1heChNYXRoLm1pbih2LCBoKSwgbCk7XG5mdW5jdGlvbiBwMmIodikge1xuXHRyZXR1cm4gbGltKHJvdW5kKHYgKiAyLjU1KSwgMCwgMjU1KTtcbn1cbmZ1bmN0aW9uIG4yYih2KSB7XG5cdHJldHVybiBsaW0ocm91bmQodiAqIDI1NSksIDAsIDI1NSk7XG59XG5mdW5jdGlvbiBiMm4odikge1xuXHRyZXR1cm4gbGltKHJvdW5kKHYgLyAyLjU1KSAvIDEwMCwgMCwgMSk7XG59XG5mdW5jdGlvbiBuMnAodikge1xuXHRyZXR1cm4gbGltKHJvdW5kKHYgKiAxMDApLCAwLCAxMDApO1xufVxuY29uc3QgUkdCX1JFID0gL15yZ2JhP1xcKFxccyooWy0rLlxcZF0rKSglKT9bXFxzLF0rKFstKy5lXFxkXSspKCUpP1tcXHMsXSsoWy0rLmVcXGRdKykoJSk/KD86W1xccywvXSsoWy0rLmVcXGRdKykoJSk/KT9cXHMqXFwpJC87XG5mdW5jdGlvbiByZ2JQYXJzZShzdHIpIHtcblx0Y29uc3QgbSA9IFJHQl9SRS5leGVjKHN0cik7XG5cdGxldCBhID0gMjU1O1xuXHRsZXQgciwgZywgYjtcblx0aWYgKCFtKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGlmIChtWzddICE9PSByKSB7XG5cdFx0Y29uc3QgdiA9ICttWzddO1xuXHRcdGEgPSAyNTUgJiAobVs4XSA/IHAyYih2KSA6IHYgKiAyNTUpO1xuXHR9XG5cdHIgPSArbVsxXTtcblx0ZyA9ICttWzNdO1xuXHRiID0gK21bNV07XG5cdHIgPSAyNTUgJiAobVsyXSA/IHAyYihyKSA6IHIpO1xuXHRnID0gMjU1ICYgKG1bNF0gPyBwMmIoZykgOiBnKTtcblx0YiA9IDI1NSAmIChtWzZdID8gcDJiKGIpIDogYik7XG5cdHJldHVybiB7XG5cdFx0cjogcixcblx0XHRnOiBnLFxuXHRcdGI6IGIsXG5cdFx0YTogYVxuXHR9O1xufVxuZnVuY3Rpb24gcmdiU3RyaW5nKHYpIHtcblx0cmV0dXJuIHYgJiYgKFxuXHRcdHYuYSA8IDI1NVxuXHRcdFx0PyBgcmdiYSgke3Yucn0sICR7di5nfSwgJHt2LmJ9LCAke2Iybih2LmEpfSlgXG5cdFx0XHQ6IGByZ2IoJHt2LnJ9LCAke3YuZ30sICR7di5ifSlgXG5cdCk7XG59XG5jb25zdCBIVUVfUkUgPSAvXihoc2xhP3xod2J8aHN2KVxcKFxccyooWy0rLmVcXGRdKykoPzpkZWcpP1tcXHMsXSsoWy0rLmVcXGRdKyklW1xccyxdKyhbLSsuZVxcZF0rKSUoPzpbXFxzLF0rKFstKy5lXFxkXSspKCUpPyk/XFxzKlxcKSQvO1xuZnVuY3Rpb24gaHNsMnJnYm4oaCwgcywgbCkge1xuXHRjb25zdCBhID0gcyAqIE1hdGgubWluKGwsIDEgLSBsKTtcblx0Y29uc3QgZiA9IChuLCBrID0gKG4gKyBoIC8gMzApICUgMTIpID0+IGwgLSBhICogTWF0aC5tYXgoTWF0aC5taW4oayAtIDMsIDkgLSBrLCAxKSwgLTEpO1xuXHRyZXR1cm4gW2YoMCksIGYoOCksIGYoNCldO1xufVxuZnVuY3Rpb24gaHN2MnJnYm4oaCwgcywgdikge1xuXHRjb25zdCBmID0gKG4sIGsgPSAobiArIGggLyA2MCkgJSA2KSA9PiB2IC0gdiAqIHMgKiBNYXRoLm1heChNYXRoLm1pbihrLCA0IC0gaywgMSksIDApO1xuXHRyZXR1cm4gW2YoNSksIGYoMyksIGYoMSldO1xufVxuZnVuY3Rpb24gaHdiMnJnYm4oaCwgdywgYikge1xuXHRjb25zdCByZ2IgPSBoc2wycmdibihoLCAxLCAwLjUpO1xuXHRsZXQgaTtcblx0aWYgKHcgKyBiID4gMSkge1xuXHRcdGkgPSAxIC8gKHcgKyBiKTtcblx0XHR3ICo9IGk7XG5cdFx0YiAqPSBpO1xuXHR9XG5cdGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcblx0XHRyZ2JbaV0gKj0gMSAtIHcgLSBiO1xuXHRcdHJnYltpXSArPSB3O1xuXHR9XG5cdHJldHVybiByZ2I7XG59XG5mdW5jdGlvbiByZ2IyaHNsKHYpIHtcblx0Y29uc3QgcmFuZ2UgPSAyNTU7XG5cdGNvbnN0IHIgPSB2LnIgLyByYW5nZTtcblx0Y29uc3QgZyA9IHYuZyAvIHJhbmdlO1xuXHRjb25zdCBiID0gdi5iIC8gcmFuZ2U7XG5cdGNvbnN0IG1heCA9IE1hdGgubWF4KHIsIGcsIGIpO1xuXHRjb25zdCBtaW4gPSBNYXRoLm1pbihyLCBnLCBiKTtcblx0Y29uc3QgbCA9IChtYXggKyBtaW4pIC8gMjtcblx0bGV0IGgsIHMsIGQ7XG5cdGlmIChtYXggIT09IG1pbikge1xuXHRcdGQgPSBtYXggLSBtaW47XG5cdFx0cyA9IGwgPiAwLjUgPyBkIC8gKDIgLSBtYXggLSBtaW4pIDogZCAvIChtYXggKyBtaW4pO1xuXHRcdGggPSBtYXggPT09IHJcblx0XHRcdD8gKChnIC0gYikgLyBkKSArIChnIDwgYiA/IDYgOiAwKVxuXHRcdFx0OiBtYXggPT09IGdcblx0XHRcdFx0PyAoYiAtIHIpIC8gZCArIDJcblx0XHRcdFx0OiAociAtIGcpIC8gZCArIDQ7XG5cdFx0aCA9IGggKiA2MCArIDAuNTtcblx0fVxuXHRyZXR1cm4gW2ggfCAwLCBzIHx8IDAsIGxdO1xufVxuZnVuY3Rpb24gY2FsbG4oZiwgYSwgYiwgYykge1xuXHRyZXR1cm4gKFxuXHRcdEFycmF5LmlzQXJyYXkoYSlcblx0XHRcdD8gZihhWzBdLCBhWzFdLCBhWzJdKVxuXHRcdFx0OiBmKGEsIGIsIGMpXG5cdCkubWFwKG4yYik7XG59XG5mdW5jdGlvbiBoc2wycmdiKGgsIHMsIGwpIHtcblx0cmV0dXJuIGNhbGxuKGhzbDJyZ2JuLCBoLCBzLCBsKTtcbn1cbmZ1bmN0aW9uIGh3YjJyZ2IoaCwgdywgYikge1xuXHRyZXR1cm4gY2FsbG4oaHdiMnJnYm4sIGgsIHcsIGIpO1xufVxuZnVuY3Rpb24gaHN2MnJnYihoLCBzLCB2KSB7XG5cdHJldHVybiBjYWxsbihoc3YycmdibiwgaCwgcywgdik7XG59XG5mdW5jdGlvbiBodWUoaCkge1xuXHRyZXR1cm4gKGggJSAzNjAgKyAzNjApICUgMzYwO1xufVxuZnVuY3Rpb24gaHVlUGFyc2Uoc3RyKSB7XG5cdGNvbnN0IG0gPSBIVUVfUkUuZXhlYyhzdHIpO1xuXHRsZXQgYSA9IDI1NTtcblx0bGV0IHY7XG5cdGlmICghbSkge1xuXHRcdHJldHVybjtcblx0fVxuXHRpZiAobVs1XSAhPT0gdikge1xuXHRcdGEgPSBtWzZdID8gcDJiKCttWzVdKSA6IG4yYigrbVs1XSk7XG5cdH1cblx0Y29uc3QgaCA9IGh1ZSgrbVsyXSk7XG5cdGNvbnN0IHAxID0gK21bM10gLyAxMDA7XG5cdGNvbnN0IHAyID0gK21bNF0gLyAxMDA7XG5cdGlmIChtWzFdID09PSAnaHdiJykge1xuXHRcdHYgPSBod2IycmdiKGgsIHAxLCBwMik7XG5cdH0gZWxzZSBpZiAobVsxXSA9PT0gJ2hzdicpIHtcblx0XHR2ID0gaHN2MnJnYihoLCBwMSwgcDIpO1xuXHR9IGVsc2Uge1xuXHRcdHYgPSBoc2wycmdiKGgsIHAxLCBwMik7XG5cdH1cblx0cmV0dXJuIHtcblx0XHRyOiB2WzBdLFxuXHRcdGc6IHZbMV0sXG5cdFx0YjogdlsyXSxcblx0XHRhOiBhXG5cdH07XG59XG5mdW5jdGlvbiByb3RhdGUodiwgZGVnKSB7XG5cdHZhciBoID0gcmdiMmhzbCh2KTtcblx0aFswXSA9IGh1ZShoWzBdICsgZGVnKTtcblx0aCA9IGhzbDJyZ2IoaCk7XG5cdHYuciA9IGhbMF07XG5cdHYuZyA9IGhbMV07XG5cdHYuYiA9IGhbMl07XG59XG5mdW5jdGlvbiBoc2xTdHJpbmcodikge1xuXHRpZiAoIXYpIHtcblx0XHRyZXR1cm47XG5cdH1cblx0Y29uc3QgYSA9IHJnYjJoc2wodik7XG5cdGNvbnN0IGggPSBhWzBdO1xuXHRjb25zdCBzID0gbjJwKGFbMV0pO1xuXHRjb25zdCBsID0gbjJwKGFbMl0pO1xuXHRyZXR1cm4gdi5hIDwgMjU1XG5cdFx0PyBgaHNsYSgke2h9LCAke3N9JSwgJHtsfSUsICR7YjJuKHYuYSl9KWBcblx0XHQ6IGBoc2woJHtofSwgJHtzfSUsICR7bH0lKWA7XG59XG5jb25zdCBtYXAkMSA9IHtcblx0eDogJ2RhcmsnLFxuXHRaOiAnbGlnaHQnLFxuXHRZOiAncmUnLFxuXHRYOiAnYmx1Jyxcblx0VzogJ2dyJyxcblx0VjogJ21lZGl1bScsXG5cdFU6ICdzbGF0ZScsXG5cdEE6ICdlZScsXG5cdFQ6ICdvbCcsXG5cdFM6ICdvcicsXG5cdEI6ICdyYScsXG5cdEM6ICdsYXRlZycsXG5cdEQ6ICdpZ2h0cycsXG5cdFI6ICdpbicsXG5cdFE6ICd0dXJxdW9pcycsXG5cdEU6ICdoaScsXG5cdFA6ICdybycsXG5cdE86ICdhbCcsXG5cdE46ICdsZScsXG5cdE06ICdkZScsXG5cdEw6ICd5ZWxsbycsXG5cdEY6ICdlbicsXG5cdEs6ICdjaCcsXG5cdEc6ICdhcmtzJyxcblx0SDogJ2VhJyxcblx0STogJ2lnaHRnJyxcblx0SjogJ3doJ1xufTtcbmNvbnN0IG5hbWVzID0ge1xuXHRPaWNlWGU6ICdmMGY4ZmYnLFxuXHRhbnRpcXVld0V0ZTogJ2ZhZWJkNycsXG5cdGFxdWE6ICdmZmZmJyxcblx0YXF1YW1hclJlOiAnN2ZmZmQ0Jyxcblx0YXp1WTogJ2YwZmZmZicsXG5cdGJlaWdlOiAnZjVmNWRjJyxcblx0YmlzcXVlOiAnZmZlNGM0Jyxcblx0YmxhY2s6ICcwJyxcblx0YmxhbktlZE9tb25kOiAnZmZlYmNkJyxcblx0WGU6ICdmZicsXG5cdFhldmlUZXQ6ICc4YTJiZTInLFxuXHRiUHduOiAnYTUyYTJhJyxcblx0YnVybHl3b29kOiAnZGViODg3Jyxcblx0Y2FNdFhlOiAnNWY5ZWEwJyxcblx0S2FydFl1c2U6ICc3ZmZmMDAnLFxuXHRLb2NUYXRlOiAnZDI2OTFlJyxcblx0Y1NPOiAnZmY3ZjUwJyxcblx0Y1NuZmxvd2VyWGU6ICc2NDk1ZWQnLFxuXHRjU25zaWxrOiAnZmZmOGRjJyxcblx0Y3JpbXNvbjogJ2RjMTQzYycsXG5cdGN5YW46ICdmZmZmJyxcblx0eFhlOiAnOGInLFxuXHR4Y3lhbjogJzhiOGInLFxuXHR4Z1RNblBkOiAnYjg4NjBiJyxcblx0eFdheTogJ2E5YTlhOScsXG5cdHhnWUY6ICc2NDAwJyxcblx0eGdZeTogJ2E5YTlhOScsXG5cdHhraGFraTogJ2JkYjc2YicsXG5cdHhtYWdGdGE6ICc4YjAwOGInLFxuXHR4VGl2ZWdZRjogJzU1NmIyZicsXG5cdHhTYW5nZTogJ2ZmOGMwMCcsXG5cdHhTY0VkOiAnOTkzMmNjJyxcblx0eFlkOiAnOGIwMDAwJyxcblx0eHNPbW9uOiAnZTk5NjdhJyxcblx0eHNIZ1lGOiAnOGZiYzhmJyxcblx0eFVYZTogJzQ4M2Q4YicsXG5cdHhVV2F5OiAnMmY0ZjRmJyxcblx0eFVnWXk6ICcyZjRmNGYnLFxuXHR4UWU6ICdjZWQxJyxcblx0eHZpVGV0OiAnOTQwMGQzJyxcblx0ZEFwcFJrOiAnZmYxNDkzJyxcblx0ZEFwc2t5WGU6ICdiZmZmJyxcblx0ZGltV2F5OiAnNjk2OTY5Jyxcblx0ZGltZ1l5OiAnNjk2OTY5Jyxcblx0ZG9kZ2VyWGU6ICcxZTkwZmYnLFxuXHRmaVlicmljazogJ2IyMjIyMicsXG5cdGZsU093RXRlOiAnZmZmYWYwJyxcblx0Zm9Zc3RXQW46ICcyMjhiMjInLFxuXHRmdUtzaWE6ICdmZjAwZmYnLFxuXHRnYVJzYlNvOiAnZGNkY2RjJyxcblx0Z2hvc3R3RXRlOiAnZjhmOGZmJyxcblx0Z1RkOiAnZmZkNzAwJyxcblx0Z1RNblBkOiAnZGFhNTIwJyxcblx0V2F5OiAnODA4MDgwJyxcblx0Z1lGOiAnODAwMCcsXG5cdGdZRkx3OiAnYWRmZjJmJyxcblx0Z1l5OiAnODA4MDgwJyxcblx0aG9uZXlNdzogJ2YwZmZmMCcsXG5cdGhvdHBSazogJ2ZmNjliNCcsXG5cdFJkaWFuWWQ6ICdjZDVjNWMnLFxuXHRSZGlnbzogJzRiMDA4MicsXG5cdGl2U3k6ICdmZmZmZjAnLFxuXHRraGFraTogJ2YwZTY4YycsXG5cdGxhdkZNcjogJ2U2ZTZmYScsXG5cdGxhdkZNclhzaDogJ2ZmZjBmNScsXG5cdGxhd25nWUY6ICc3Y2ZjMDAnLFxuXHRObW9uY0VmZm9uOiAnZmZmYWNkJyxcblx0WlhlOiAnYWRkOGU2Jyxcblx0WmNTTzogJ2YwODA4MCcsXG5cdFpjeWFuOiAnZTBmZmZmJyxcblx0WmdUTW5QZEx3OiAnZmFmYWQyJyxcblx0WldheTogJ2QzZDNkMycsXG5cdFpnWUY6ICc5MGVlOTAnLFxuXHRaZ1l5OiAnZDNkM2QzJyxcblx0WnBSazogJ2ZmYjZjMScsXG5cdFpzT21vbjogJ2ZmYTA3YScsXG5cdFpzSGdZRjogJzIwYjJhYScsXG5cdFpza3lYZTogJzg3Y2VmYScsXG5cdFpVV2F5OiAnNzc4ODk5Jyxcblx0WlVnWXk6ICc3Nzg4OTknLFxuXHRac3RBbFhlOiAnYjBjNGRlJyxcblx0Wkx3OiAnZmZmZmUwJyxcblx0bGltZTogJ2ZmMDAnLFxuXHRsaW1lZ1lGOiAnMzJjZDMyJyxcblx0bFJGOiAnZmFmMGU2Jyxcblx0bWFnRnRhOiAnZmYwMGZmJyxcblx0bWFQb246ICc4MDAwMDAnLFxuXHRWYXF1YW1hclJlOiAnNjZjZGFhJyxcblx0VlhlOiAnY2QnLFxuXHRWU2NFZDogJ2JhNTVkMycsXG5cdFZwdXJwTjogJzkzNzBkYicsXG5cdFZzSGdZRjogJzNjYjM3MScsXG5cdFZVWGU6ICc3YjY4ZWUnLFxuXHRWc3ByUmdnWUY6ICdmYTlhJyxcblx0VlFlOiAnNDhkMWNjJyxcblx0VnZpVGV0WWQ6ICdjNzE1ODUnLFxuXHRtaWRuaWdodFhlOiAnMTkxOTcwJyxcblx0bVJ0Y1lhbTogJ2Y1ZmZmYScsXG5cdG1pc3R5UHNlOiAnZmZlNGUxJyxcblx0bW9jY2FzUjogJ2ZmZTRiNScsXG5cdG5hdmFqb3dFdGU6ICdmZmRlYWQnLFxuXHRuYXZ5OiAnODAnLFxuXHRUZGxhY2U6ICdmZGY1ZTYnLFxuXHRUaXZlOiAnODA4MDAwJyxcblx0VGl2ZWRCYjogJzZiOGUyMycsXG5cdFNhbmdlOiAnZmZhNTAwJyxcblx0U2FuZ2VZZDogJ2ZmNDUwMCcsXG5cdFNjRWQ6ICdkYTcwZDYnLFxuXHRwT2VnVE1uUGQ6ICdlZWU4YWEnLFxuXHRwT2VnWUY6ICc5OGZiOTgnLFxuXHRwT2VRZTogJ2FmZWVlZScsXG5cdHBPZXZpVGV0WWQ6ICdkYjcwOTMnLFxuXHRwYXBheWF3RXA6ICdmZmVmZDUnLFxuXHRwSEtwdWZmOiAnZmZkYWI5Jyxcblx0cGVydTogJ2NkODUzZicsXG5cdHBSazogJ2ZmYzBjYicsXG5cdHBsdW06ICdkZGEwZGQnLFxuXHRwb3dNclhlOiAnYjBlMGU2Jyxcblx0cHVycE46ICc4MDAwODAnLFxuXHRZYmVjY2FwdXJwTjogJzY2MzM5OScsXG5cdFlkOiAnZmYwMDAwJyxcblx0UHN5YnJvd246ICdiYzhmOGYnLFxuXHRQeU9YZTogJzQxNjllMScsXG5cdHNhZGROYlB3bjogJzhiNDUxMycsXG5cdHNPbW9uOiAnZmE4MDcyJyxcblx0c2FuZHliUHduOiAnZjRhNDYwJyxcblx0c0hnWUY6ICcyZThiNTcnLFxuXHRzSHNoZWxsOiAnZmZmNWVlJyxcblx0c2lGbmE6ICdhMDUyMmQnLFxuXHRzaWx2ZXI6ICdjMGMwYzAnLFxuXHRza3lYZTogJzg3Y2VlYicsXG5cdFVYZTogJzZhNWFjZCcsXG5cdFVXYXk6ICc3MDgwOTAnLFxuXHRVZ1l5OiAnNzA4MDkwJyxcblx0c25vdzogJ2ZmZmFmYScsXG5cdHNwclJnZ1lGOiAnZmY3ZicsXG5cdHN0QWxYZTogJzQ2ODJiNCcsXG5cdHRhbjogJ2QyYjQ4YycsXG5cdHRlTzogJzgwODAnLFxuXHR0RXN0TjogJ2Q4YmZkOCcsXG5cdHRvbWF0bzogJ2ZmNjM0NycsXG5cdFFlOiAnNDBlMGQwJyxcblx0dmlUZXQ6ICdlZTgyZWUnLFxuXHRKSHQ6ICdmNWRlYjMnLFxuXHR3RXRlOiAnZmZmZmZmJyxcblx0d0V0ZXNtb2tlOiAnZjVmNWY1Jyxcblx0THc6ICdmZmZmMDAnLFxuXHRMd2dZRjogJzlhY2QzMidcbn07XG5mdW5jdGlvbiB1bnBhY2soKSB7XG5cdGNvbnN0IHVucGFja2VkID0ge307XG5cdGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhuYW1lcyk7XG5cdGNvbnN0IHRrZXlzID0gT2JqZWN0LmtleXMobWFwJDEpO1xuXHRsZXQgaSwgaiwgaywgb2ssIG5rO1xuXHRmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuXHRcdG9rID0gbmsgPSBrZXlzW2ldO1xuXHRcdGZvciAoaiA9IDA7IGogPCB0a2V5cy5sZW5ndGg7IGorKykge1xuXHRcdFx0ayA9IHRrZXlzW2pdO1xuXHRcdFx0bmsgPSBuay5yZXBsYWNlKGssIG1hcCQxW2tdKTtcblx0XHR9XG5cdFx0ayA9IHBhcnNlSW50KG5hbWVzW29rXSwgMTYpO1xuXHRcdHVucGFja2VkW25rXSA9IFtrID4+IDE2ICYgMHhGRiwgayA+PiA4ICYgMHhGRiwgayAmIDB4RkZdO1xuXHR9XG5cdHJldHVybiB1bnBhY2tlZDtcbn1cbmxldCBuYW1lcyQxO1xuZnVuY3Rpb24gbmFtZVBhcnNlKHN0cikge1xuXHRpZiAoIW5hbWVzJDEpIHtcblx0XHRuYW1lcyQxID0gdW5wYWNrKCk7XG5cdFx0bmFtZXMkMS50cmFuc3BhcmVudCA9IFswLCAwLCAwLCAwXTtcblx0fVxuXHRjb25zdCBhID0gbmFtZXMkMVtzdHIudG9Mb3dlckNhc2UoKV07XG5cdHJldHVybiBhICYmIHtcblx0XHRyOiBhWzBdLFxuXHRcdGc6IGFbMV0sXG5cdFx0YjogYVsyXSxcblx0XHRhOiBhLmxlbmd0aCA9PT0gNCA/IGFbM10gOiAyNTVcblx0fTtcbn1cbmZ1bmN0aW9uIG1vZEhTTCh2LCBpLCByYXRpbykge1xuXHRpZiAodikge1xuXHRcdGxldCB0bXAgPSByZ2IyaHNsKHYpO1xuXHRcdHRtcFtpXSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHRtcFtpXSArIHRtcFtpXSAqIHJhdGlvLCBpID09PSAwID8gMzYwIDogMSkpO1xuXHRcdHRtcCA9IGhzbDJyZ2IodG1wKTtcblx0XHR2LnIgPSB0bXBbMF07XG5cdFx0di5nID0gdG1wWzFdO1xuXHRcdHYuYiA9IHRtcFsyXTtcblx0fVxufVxuZnVuY3Rpb24gY2xvbmUodiwgcHJvdG8pIHtcblx0cmV0dXJuIHYgPyBPYmplY3QuYXNzaWduKHByb3RvIHx8IHt9LCB2KSA6IHY7XG59XG5mdW5jdGlvbiBmcm9tT2JqZWN0KGlucHV0KSB7XG5cdHZhciB2ID0ge3I6IDAsIGc6IDAsIGI6IDAsIGE6IDI1NX07XG5cdGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuXHRcdGlmIChpbnB1dC5sZW5ndGggPj0gMykge1xuXHRcdFx0diA9IHtyOiBpbnB1dFswXSwgZzogaW5wdXRbMV0sIGI6IGlucHV0WzJdLCBhOiAyNTV9O1xuXHRcdFx0aWYgKGlucHV0Lmxlbmd0aCA+IDMpIHtcblx0XHRcdFx0di5hID0gbjJiKGlucHV0WzNdKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0diA9IGNsb25lKGlucHV0LCB7cjogMCwgZzogMCwgYjogMCwgYTogMX0pO1xuXHRcdHYuYSA9IG4yYih2LmEpO1xuXHR9XG5cdHJldHVybiB2O1xufVxuZnVuY3Rpb24gZnVuY3Rpb25QYXJzZShzdHIpIHtcblx0aWYgKHN0ci5jaGFyQXQoMCkgPT09ICdyJykge1xuXHRcdHJldHVybiByZ2JQYXJzZShzdHIpO1xuXHR9XG5cdHJldHVybiBodWVQYXJzZShzdHIpO1xufVxuY2xhc3MgQ29sb3Ige1xuXHRjb25zdHJ1Y3RvcihpbnB1dCkge1xuXHRcdGlmIChpbnB1dCBpbnN0YW5jZW9mIENvbG9yKSB7XG5cdFx0XHRyZXR1cm4gaW5wdXQ7XG5cdFx0fVxuXHRcdGNvbnN0IHR5cGUgPSB0eXBlb2YgaW5wdXQ7XG5cdFx0bGV0IHY7XG5cdFx0aWYgKHR5cGUgPT09ICdvYmplY3QnKSB7XG5cdFx0XHR2ID0gZnJvbU9iamVjdChpbnB1dCk7XG5cdFx0fSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuXHRcdFx0diA9IGhleFBhcnNlKGlucHV0KSB8fCBuYW1lUGFyc2UoaW5wdXQpIHx8IGZ1bmN0aW9uUGFyc2UoaW5wdXQpO1xuXHRcdH1cblx0XHR0aGlzLl9yZ2IgPSB2O1xuXHRcdHRoaXMuX3ZhbGlkID0gISF2O1xuXHR9XG5cdGdldCB2YWxpZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdmFsaWQ7XG5cdH1cblx0Z2V0IHJnYigpIHtcblx0XHR2YXIgdiA9IGNsb25lKHRoaXMuX3JnYik7XG5cdFx0aWYgKHYpIHtcblx0XHRcdHYuYSA9IGIybih2LmEpO1xuXHRcdH1cblx0XHRyZXR1cm4gdjtcblx0fVxuXHRzZXQgcmdiKG9iaikge1xuXHRcdHRoaXMuX3JnYiA9IGZyb21PYmplY3Qob2JqKTtcblx0fVxuXHRyZ2JTdHJpbmcoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3ZhbGlkID8gcmdiU3RyaW5nKHRoaXMuX3JnYikgOiB0aGlzLl9yZ2I7XG5cdH1cblx0aGV4U3RyaW5nKCkge1xuXHRcdHJldHVybiB0aGlzLl92YWxpZCA/IGhleFN0cmluZyh0aGlzLl9yZ2IpIDogdGhpcy5fcmdiO1xuXHR9XG5cdGhzbFN0cmluZygpIHtcblx0XHRyZXR1cm4gdGhpcy5fdmFsaWQgPyBoc2xTdHJpbmcodGhpcy5fcmdiKSA6IHRoaXMuX3JnYjtcblx0fVxuXHRtaXgoY29sb3IsIHdlaWdodCkge1xuXHRcdGNvbnN0IG1lID0gdGhpcztcblx0XHRpZiAoY29sb3IpIHtcblx0XHRcdGNvbnN0IGMxID0gbWUucmdiO1xuXHRcdFx0Y29uc3QgYzIgPSBjb2xvci5yZ2I7XG5cdFx0XHRsZXQgdzI7XG5cdFx0XHRjb25zdCBwID0gd2VpZ2h0ID09PSB3MiA/IDAuNSA6IHdlaWdodDtcblx0XHRcdGNvbnN0IHcgPSAyICogcCAtIDE7XG5cdFx0XHRjb25zdCBhID0gYzEuYSAtIGMyLmE7XG5cdFx0XHRjb25zdCB3MSA9ICgodyAqIGEgPT09IC0xID8gdyA6ICh3ICsgYSkgLyAoMSArIHcgKiBhKSkgKyAxKSAvIDIuMDtcblx0XHRcdHcyID0gMSAtIHcxO1xuXHRcdFx0YzEuciA9IDB4RkYgJiB3MSAqIGMxLnIgKyB3MiAqIGMyLnIgKyAwLjU7XG5cdFx0XHRjMS5nID0gMHhGRiAmIHcxICogYzEuZyArIHcyICogYzIuZyArIDAuNTtcblx0XHRcdGMxLmIgPSAweEZGICYgdzEgKiBjMS5iICsgdzIgKiBjMi5iICsgMC41O1xuXHRcdFx0YzEuYSA9IHAgKiBjMS5hICsgKDEgLSBwKSAqIGMyLmE7XG5cdFx0XHRtZS5yZ2IgPSBjMTtcblx0XHR9XG5cdFx0cmV0dXJuIG1lO1xuXHR9XG5cdGNsb25lKCkge1xuXHRcdHJldHVybiBuZXcgQ29sb3IodGhpcy5yZ2IpO1xuXHR9XG5cdGFscGhhKGEpIHtcblx0XHR0aGlzLl9yZ2IuYSA9IG4yYihhKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXHRjbGVhcmVyKHJhdGlvKSB7XG5cdFx0Y29uc3QgcmdiID0gdGhpcy5fcmdiO1xuXHRcdHJnYi5hICo9IDEgLSByYXRpbztcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXHRncmV5c2NhbGUoKSB7XG5cdFx0Y29uc3QgcmdiID0gdGhpcy5fcmdiO1xuXHRcdGNvbnN0IHZhbCA9IHJvdW5kKHJnYi5yICogMC4zICsgcmdiLmcgKiAwLjU5ICsgcmdiLmIgKiAwLjExKTtcblx0XHRyZ2IuciA9IHJnYi5nID0gcmdiLmIgPSB2YWw7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblx0b3BhcXVlcihyYXRpbykge1xuXHRcdGNvbnN0IHJnYiA9IHRoaXMuX3JnYjtcblx0XHRyZ2IuYSAqPSAxICsgcmF0aW87XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblx0bmVnYXRlKCkge1xuXHRcdGNvbnN0IHYgPSB0aGlzLl9yZ2I7XG5cdFx0di5yID0gMjU1IC0gdi5yO1xuXHRcdHYuZyA9IDI1NSAtIHYuZztcblx0XHR2LmIgPSAyNTUgLSB2LmI7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblx0bGlnaHRlbihyYXRpbykge1xuXHRcdG1vZEhTTCh0aGlzLl9yZ2IsIDIsIHJhdGlvKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXHRkYXJrZW4ocmF0aW8pIHtcblx0XHRtb2RIU0wodGhpcy5fcmdiLCAyLCAtcmF0aW8pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cdHNhdHVyYXRlKHJhdGlvKSB7XG5cdFx0bW9kSFNMKHRoaXMuX3JnYiwgMSwgcmF0aW8pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cdGRlc2F0dXJhdGUocmF0aW8pIHtcblx0XHRtb2RIU0wodGhpcy5fcmdiLCAxLCAtcmF0aW8pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cdHJvdGF0ZShkZWcpIHtcblx0XHRyb3RhdGUodGhpcy5fcmdiLCBkZWcpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG59XG5mdW5jdGlvbiBpbmRleF9lc20oaW5wdXQpIHtcblx0cmV0dXJuIG5ldyBDb2xvcihpbnB1dCk7XG59XG5cbmNvbnN0IGlzUGF0dGVybk9yR3JhZGllbnQgPSAodmFsdWUpID0+IHZhbHVlIGluc3RhbmNlb2YgQ2FudmFzR3JhZGllbnQgfHwgdmFsdWUgaW5zdGFuY2VvZiBDYW52YXNQYXR0ZXJuO1xuZnVuY3Rpb24gY29sb3IodmFsdWUpIHtcbiAgcmV0dXJuIGlzUGF0dGVybk9yR3JhZGllbnQodmFsdWUpID8gdmFsdWUgOiBpbmRleF9lc20odmFsdWUpO1xufVxuZnVuY3Rpb24gZ2V0SG92ZXJDb2xvcih2YWx1ZSkge1xuICByZXR1cm4gaXNQYXR0ZXJuT3JHcmFkaWVudCh2YWx1ZSlcbiAgICA/IHZhbHVlXG4gICAgOiBpbmRleF9lc20odmFsdWUpLnNhdHVyYXRlKDAuNSkuZGFya2VuKDAuMSkuaGV4U3RyaW5nKCk7XG59XG5cbmNvbnN0IG92ZXJyaWRlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5jb25zdCBkZXNjcmlwdG9ycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5mdW5jdGlvbiBnZXRTY29wZSQxKG5vZGUsIGtleSkge1xuICBpZiAoIWtleSkge1xuICAgIHJldHVybiBub2RlO1xuICB9XG4gIGNvbnN0IGtleXMgPSBrZXkuc3BsaXQoJy4nKTtcbiAgZm9yIChsZXQgaSA9IDAsIG4gPSBrZXlzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgIGNvbnN0IGsgPSBrZXlzW2ldO1xuICAgIG5vZGUgPSBub2RlW2tdIHx8IChub2RlW2tdID0gT2JqZWN0LmNyZWF0ZShudWxsKSk7XG4gIH1cbiAgcmV0dXJuIG5vZGU7XG59XG5mdW5jdGlvbiBzZXQocm9vdCwgc2NvcGUsIHZhbHVlcykge1xuICBpZiAodHlwZW9mIHNjb3BlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBtZXJnZShnZXRTY29wZSQxKHJvb3QsIHNjb3BlKSwgdmFsdWVzKTtcbiAgfVxuICByZXR1cm4gbWVyZ2UoZ2V0U2NvcGUkMShyb290LCAnJyksIHNjb3BlKTtcbn1cbmNsYXNzIERlZmF1bHRzIHtcbiAgY29uc3RydWN0b3IoX2Rlc2NyaXB0b3JzKSB7XG4gICAgdGhpcy5hbmltYXRpb24gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSAncmdiYSgwLDAsMCwwLjEpJztcbiAgICB0aGlzLmJvcmRlckNvbG9yID0gJ3JnYmEoMCwwLDAsMC4xKSc7XG4gICAgdGhpcy5jb2xvciA9ICcjNjY2JztcbiAgICB0aGlzLmRhdGFzZXRzID0ge307XG4gICAgdGhpcy5kZXZpY2VQaXhlbFJhdGlvID0gKGNvbnRleHQpID0+IGNvbnRleHQuY2hhcnQucGxhdGZvcm0uZ2V0RGV2aWNlUGl4ZWxSYXRpbygpO1xuICAgIHRoaXMuZWxlbWVudHMgPSB7fTtcbiAgICB0aGlzLmV2ZW50cyA9IFtcbiAgICAgICdtb3VzZW1vdmUnLFxuICAgICAgJ21vdXNlb3V0JyxcbiAgICAgICdjbGljaycsXG4gICAgICAndG91Y2hzdGFydCcsXG4gICAgICAndG91Y2htb3ZlJ1xuICAgIF07XG4gICAgdGhpcy5mb250ID0ge1xuICAgICAgZmFtaWx5OiBcIidIZWx2ZXRpY2EgTmV1ZScsICdIZWx2ZXRpY2EnLCAnQXJpYWwnLCBzYW5zLXNlcmlmXCIsXG4gICAgICBzaXplOiAxMixcbiAgICAgIHN0eWxlOiAnbm9ybWFsJyxcbiAgICAgIGxpbmVIZWlnaHQ6IDEuMixcbiAgICAgIHdlaWdodDogbnVsbFxuICAgIH07XG4gICAgdGhpcy5ob3ZlciA9IHt9O1xuICAgIHRoaXMuaG92ZXJCYWNrZ3JvdW5kQ29sb3IgPSAoY3R4LCBvcHRpb25zKSA9PiBnZXRIb3ZlckNvbG9yKG9wdGlvbnMuYmFja2dyb3VuZENvbG9yKTtcbiAgICB0aGlzLmhvdmVyQm9yZGVyQ29sb3IgPSAoY3R4LCBvcHRpb25zKSA9PiBnZXRIb3ZlckNvbG9yKG9wdGlvbnMuYm9yZGVyQ29sb3IpO1xuICAgIHRoaXMuaG92ZXJDb2xvciA9IChjdHgsIG9wdGlvbnMpID0+IGdldEhvdmVyQ29sb3Iob3B0aW9ucy5jb2xvcik7XG4gICAgdGhpcy5pbmRleEF4aXMgPSAneCc7XG4gICAgdGhpcy5pbnRlcmFjdGlvbiA9IHtcbiAgICAgIG1vZGU6ICduZWFyZXN0JyxcbiAgICAgIGludGVyc2VjdDogdHJ1ZVxuICAgIH07XG4gICAgdGhpcy5tYWludGFpbkFzcGVjdFJhdGlvID0gdHJ1ZTtcbiAgICB0aGlzLm9uSG92ZXIgPSBudWxsO1xuICAgIHRoaXMub25DbGljayA9IG51bGw7XG4gICAgdGhpcy5wYXJzaW5nID0gdHJ1ZTtcbiAgICB0aGlzLnBsdWdpbnMgPSB7fTtcbiAgICB0aGlzLnJlc3BvbnNpdmUgPSB0cnVlO1xuICAgIHRoaXMuc2NhbGUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5zY2FsZXMgPSB7fTtcbiAgICB0aGlzLnNob3dMaW5lID0gdHJ1ZTtcbiAgICB0aGlzLmRlc2NyaWJlKF9kZXNjcmlwdG9ycyk7XG4gIH1cbiAgc2V0KHNjb3BlLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gc2V0KHRoaXMsIHNjb3BlLCB2YWx1ZXMpO1xuICB9XG4gIGdldChzY29wZSkge1xuICAgIHJldHVybiBnZXRTY29wZSQxKHRoaXMsIHNjb3BlKTtcbiAgfVxuICBkZXNjcmliZShzY29wZSwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIHNldChkZXNjcmlwdG9ycywgc2NvcGUsIHZhbHVlcyk7XG4gIH1cbiAgb3ZlcnJpZGUoc2NvcGUsIHZhbHVlcykge1xuICAgIHJldHVybiBzZXQob3ZlcnJpZGVzLCBzY29wZSwgdmFsdWVzKTtcbiAgfVxuICByb3V0ZShzY29wZSwgbmFtZSwgdGFyZ2V0U2NvcGUsIHRhcmdldE5hbWUpIHtcbiAgICBjb25zdCBzY29wZU9iamVjdCA9IGdldFNjb3BlJDEodGhpcywgc2NvcGUpO1xuICAgIGNvbnN0IHRhcmdldFNjb3BlT2JqZWN0ID0gZ2V0U2NvcGUkMSh0aGlzLCB0YXJnZXRTY29wZSk7XG4gICAgY29uc3QgcHJpdmF0ZU5hbWUgPSAnXycgKyBuYW1lO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHNjb3BlT2JqZWN0LCB7XG4gICAgICBbcHJpdmF0ZU5hbWVdOiB7XG4gICAgICAgIHZhbHVlOiBzY29wZU9iamVjdFtuYW1lXSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0sXG4gICAgICBbbmFtZV06IHtcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgZ2V0KCkge1xuICAgICAgICAgIGNvbnN0IGxvY2FsID0gdGhpc1twcml2YXRlTmFtZV07XG4gICAgICAgICAgY29uc3QgdGFyZ2V0ID0gdGFyZ2V0U2NvcGVPYmplY3RbdGFyZ2V0TmFtZV07XG4gICAgICAgICAgaWYgKGlzT2JqZWN0KGxvY2FsKSkge1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHRhcmdldCwgbG9jYWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdmFsdWVPckRlZmF1bHQobG9jYWwsIHRhcmdldCk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldCh2YWx1ZSkge1xuICAgICAgICAgIHRoaXNbcHJpdmF0ZU5hbWVdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxudmFyIGRlZmF1bHRzID0gbmV3IERlZmF1bHRzKHtcbiAgX3NjcmlwdGFibGU6IChuYW1lKSA9PiAhbmFtZS5zdGFydHNXaXRoKCdvbicpLFxuICBfaW5kZXhhYmxlOiAobmFtZSkgPT4gbmFtZSAhPT0gJ2V2ZW50cycsXG4gIGhvdmVyOiB7XG4gICAgX2ZhbGxiYWNrOiAnaW50ZXJhY3Rpb24nXG4gIH0sXG4gIGludGVyYWN0aW9uOiB7XG4gICAgX3NjcmlwdGFibGU6IGZhbHNlLFxuICAgIF9pbmRleGFibGU6IGZhbHNlLFxuICB9XG59KTtcblxuZnVuY3Rpb24gdG9Gb250U3RyaW5nKGZvbnQpIHtcbiAgaWYgKCFmb250IHx8IGlzTnVsbE9yVW5kZWYoZm9udC5zaXplKSB8fCBpc051bGxPclVuZGVmKGZvbnQuZmFtaWx5KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiAoZm9udC5zdHlsZSA/IGZvbnQuc3R5bGUgKyAnICcgOiAnJylcblx0XHQrIChmb250LndlaWdodCA/IGZvbnQud2VpZ2h0ICsgJyAnIDogJycpXG5cdFx0KyBmb250LnNpemUgKyAncHggJ1xuXHRcdCsgZm9udC5mYW1pbHk7XG59XG5mdW5jdGlvbiBfbWVhc3VyZVRleHQoY3R4LCBkYXRhLCBnYywgbG9uZ2VzdCwgc3RyaW5nKSB7XG4gIGxldCB0ZXh0V2lkdGggPSBkYXRhW3N0cmluZ107XG4gIGlmICghdGV4dFdpZHRoKSB7XG4gICAgdGV4dFdpZHRoID0gZGF0YVtzdHJpbmddID0gY3R4Lm1lYXN1cmVUZXh0KHN0cmluZykud2lkdGg7XG4gICAgZ2MucHVzaChzdHJpbmcpO1xuICB9XG4gIGlmICh0ZXh0V2lkdGggPiBsb25nZXN0KSB7XG4gICAgbG9uZ2VzdCA9IHRleHRXaWR0aDtcbiAgfVxuICByZXR1cm4gbG9uZ2VzdDtcbn1cbmZ1bmN0aW9uIF9sb25nZXN0VGV4dChjdHgsIGZvbnQsIGFycmF5T2ZUaGluZ3MsIGNhY2hlKSB7XG4gIGNhY2hlID0gY2FjaGUgfHwge307XG4gIGxldCBkYXRhID0gY2FjaGUuZGF0YSA9IGNhY2hlLmRhdGEgfHwge307XG4gIGxldCBnYyA9IGNhY2hlLmdhcmJhZ2VDb2xsZWN0ID0gY2FjaGUuZ2FyYmFnZUNvbGxlY3QgfHwgW107XG4gIGlmIChjYWNoZS5mb250ICE9PSBmb250KSB7XG4gICAgZGF0YSA9IGNhY2hlLmRhdGEgPSB7fTtcbiAgICBnYyA9IGNhY2hlLmdhcmJhZ2VDb2xsZWN0ID0gW107XG4gICAgY2FjaGUuZm9udCA9IGZvbnQ7XG4gIH1cbiAgY3R4LnNhdmUoKTtcbiAgY3R4LmZvbnQgPSBmb250O1xuICBsZXQgbG9uZ2VzdCA9IDA7XG4gIGNvbnN0IGlsZW4gPSBhcnJheU9mVGhpbmdzLmxlbmd0aDtcbiAgbGV0IGksIGosIGpsZW4sIHRoaW5nLCBuZXN0ZWRUaGluZztcbiAgZm9yIChpID0gMDsgaSA8IGlsZW47IGkrKykge1xuICAgIHRoaW5nID0gYXJyYXlPZlRoaW5nc1tpXTtcbiAgICBpZiAodGhpbmcgIT09IHVuZGVmaW5lZCAmJiB0aGluZyAhPT0gbnVsbCAmJiBpc0FycmF5KHRoaW5nKSAhPT0gdHJ1ZSkge1xuICAgICAgbG9uZ2VzdCA9IF9tZWFzdXJlVGV4dChjdHgsIGRhdGEsIGdjLCBsb25nZXN0LCB0aGluZyk7XG4gICAgfSBlbHNlIGlmIChpc0FycmF5KHRoaW5nKSkge1xuICAgICAgZm9yIChqID0gMCwgamxlbiA9IHRoaW5nLmxlbmd0aDsgaiA8IGpsZW47IGorKykge1xuICAgICAgICBuZXN0ZWRUaGluZyA9IHRoaW5nW2pdO1xuICAgICAgICBpZiAobmVzdGVkVGhpbmcgIT09IHVuZGVmaW5lZCAmJiBuZXN0ZWRUaGluZyAhPT0gbnVsbCAmJiAhaXNBcnJheShuZXN0ZWRUaGluZykpIHtcbiAgICAgICAgICBsb25nZXN0ID0gX21lYXN1cmVUZXh0KGN0eCwgZGF0YSwgZ2MsIGxvbmdlc3QsIG5lc3RlZFRoaW5nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBjdHgucmVzdG9yZSgpO1xuICBjb25zdCBnY0xlbiA9IGdjLmxlbmd0aCAvIDI7XG4gIGlmIChnY0xlbiA+IGFycmF5T2ZUaGluZ3MubGVuZ3RoKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IGdjTGVuOyBpKyspIHtcbiAgICAgIGRlbGV0ZSBkYXRhW2djW2ldXTtcbiAgICB9XG4gICAgZ2Muc3BsaWNlKDAsIGdjTGVuKTtcbiAgfVxuICByZXR1cm4gbG9uZ2VzdDtcbn1cbmZ1bmN0aW9uIF9hbGlnblBpeGVsKGNoYXJ0LCBwaXhlbCwgd2lkdGgpIHtcbiAgY29uc3QgZGV2aWNlUGl4ZWxSYXRpbyA9IGNoYXJ0LmN1cnJlbnREZXZpY2VQaXhlbFJhdGlvO1xuICBjb25zdCBoYWxmV2lkdGggPSB3aWR0aCAhPT0gMCA/IE1hdGgubWF4KHdpZHRoIC8gMiwgMC41KSA6IDA7XG4gIHJldHVybiBNYXRoLnJvdW5kKChwaXhlbCAtIGhhbGZXaWR0aCkgKiBkZXZpY2VQaXhlbFJhdGlvKSAvIGRldmljZVBpeGVsUmF0aW8gKyBoYWxmV2lkdGg7XG59XG5mdW5jdGlvbiBjbGVhckNhbnZhcyhjYW52YXMsIGN0eCkge1xuICBjdHggPSBjdHggfHwgY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gIGN0eC5zYXZlKCk7XG4gIGN0eC5yZXNldFRyYW5zZm9ybSgpO1xuICBjdHguY2xlYXJSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gIGN0eC5yZXN0b3JlKCk7XG59XG5mdW5jdGlvbiBkcmF3UG9pbnQoY3R4LCBvcHRpb25zLCB4LCB5KSB7XG4gIGxldCB0eXBlLCB4T2Zmc2V0LCB5T2Zmc2V0LCBzaXplLCBjb3JuZXJSYWRpdXM7XG4gIGNvbnN0IHN0eWxlID0gb3B0aW9ucy5wb2ludFN0eWxlO1xuICBjb25zdCByb3RhdGlvbiA9IG9wdGlvbnMucm90YXRpb247XG4gIGNvbnN0IHJhZGl1cyA9IG9wdGlvbnMucmFkaXVzO1xuICBsZXQgcmFkID0gKHJvdGF0aW9uIHx8IDApICogUkFEX1BFUl9ERUc7XG4gIGlmIChzdHlsZSAmJiB0eXBlb2Ygc3R5bGUgPT09ICdvYmplY3QnKSB7XG4gICAgdHlwZSA9IHN0eWxlLnRvU3RyaW5nKCk7XG4gICAgaWYgKHR5cGUgPT09ICdbb2JqZWN0IEhUTUxJbWFnZUVsZW1lbnRdJyB8fCB0eXBlID09PSAnW29iamVjdCBIVE1MQ2FudmFzRWxlbWVudF0nKSB7XG4gICAgICBjdHguc2F2ZSgpO1xuICAgICAgY3R4LnRyYW5zbGF0ZSh4LCB5KTtcbiAgICAgIGN0eC5yb3RhdGUocmFkKTtcbiAgICAgIGN0eC5kcmF3SW1hZ2Uoc3R5bGUsIC1zdHlsZS53aWR0aCAvIDIsIC1zdHlsZS5oZWlnaHQgLyAyLCBzdHlsZS53aWR0aCwgc3R5bGUuaGVpZ2h0KTtcbiAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG4gIGlmIChpc05hTihyYWRpdXMpIHx8IHJhZGl1cyA8PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGN0eC5iZWdpblBhdGgoKTtcbiAgc3dpdGNoIChzdHlsZSkge1xuICBkZWZhdWx0OlxuICAgIGN0eC5hcmMoeCwgeSwgcmFkaXVzLCAwLCBUQVUpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBicmVhaztcbiAgY2FzZSAndHJpYW5nbGUnOlxuICAgIGN0eC5tb3ZlVG8oeCArIE1hdGguc2luKHJhZCkgKiByYWRpdXMsIHkgLSBNYXRoLmNvcyhyYWQpICogcmFkaXVzKTtcbiAgICByYWQgKz0gVFdPX1RISVJEU19QSTtcbiAgICBjdHgubGluZVRvKHggKyBNYXRoLnNpbihyYWQpICogcmFkaXVzLCB5IC0gTWF0aC5jb3MocmFkKSAqIHJhZGl1cyk7XG4gICAgcmFkICs9IFRXT19USElSRFNfUEk7XG4gICAgY3R4LmxpbmVUbyh4ICsgTWF0aC5zaW4ocmFkKSAqIHJhZGl1cywgeSAtIE1hdGguY29zKHJhZCkgKiByYWRpdXMpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBicmVhaztcbiAgY2FzZSAncmVjdFJvdW5kZWQnOlxuICAgIGNvcm5lclJhZGl1cyA9IHJhZGl1cyAqIDAuNTE2O1xuICAgIHNpemUgPSByYWRpdXMgLSBjb3JuZXJSYWRpdXM7XG4gICAgeE9mZnNldCA9IE1hdGguY29zKHJhZCArIFFVQVJURVJfUEkpICogc2l6ZTtcbiAgICB5T2Zmc2V0ID0gTWF0aC5zaW4ocmFkICsgUVVBUlRFUl9QSSkgKiBzaXplO1xuICAgIGN0eC5hcmMoeCAtIHhPZmZzZXQsIHkgLSB5T2Zmc2V0LCBjb3JuZXJSYWRpdXMsIHJhZCAtIFBJLCByYWQgLSBIQUxGX1BJKTtcbiAgICBjdHguYXJjKHggKyB5T2Zmc2V0LCB5IC0geE9mZnNldCwgY29ybmVyUmFkaXVzLCByYWQgLSBIQUxGX1BJLCByYWQpO1xuICAgIGN0eC5hcmMoeCArIHhPZmZzZXQsIHkgKyB5T2Zmc2V0LCBjb3JuZXJSYWRpdXMsIHJhZCwgcmFkICsgSEFMRl9QSSk7XG4gICAgY3R4LmFyYyh4IC0geU9mZnNldCwgeSArIHhPZmZzZXQsIGNvcm5lclJhZGl1cywgcmFkICsgSEFMRl9QSSwgcmFkICsgUEkpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBicmVhaztcbiAgY2FzZSAncmVjdCc6XG4gICAgaWYgKCFyb3RhdGlvbikge1xuICAgICAgc2l6ZSA9IE1hdGguU1FSVDFfMiAqIHJhZGl1cztcbiAgICAgIGN0eC5yZWN0KHggLSBzaXplLCB5IC0gc2l6ZSwgMiAqIHNpemUsIDIgKiBzaXplKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByYWQgKz0gUVVBUlRFUl9QSTtcbiAgY2FzZSAncmVjdFJvdCc6XG4gICAgeE9mZnNldCA9IE1hdGguY29zKHJhZCkgKiByYWRpdXM7XG4gICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgY3R4Lm1vdmVUbyh4IC0geE9mZnNldCwgeSAtIHlPZmZzZXQpO1xuICAgIGN0eC5saW5lVG8oeCArIHlPZmZzZXQsIHkgLSB4T2Zmc2V0KTtcbiAgICBjdHgubGluZVRvKHggKyB4T2Zmc2V0LCB5ICsgeU9mZnNldCk7XG4gICAgY3R4LmxpbmVUbyh4IC0geU9mZnNldCwgeSArIHhPZmZzZXQpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBicmVhaztcbiAgY2FzZSAnY3Jvc3NSb3QnOlxuICAgIHJhZCArPSBRVUFSVEVSX1BJO1xuICBjYXNlICdjcm9zcyc6XG4gICAgeE9mZnNldCA9IE1hdGguY29zKHJhZCkgKiByYWRpdXM7XG4gICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgY3R4Lm1vdmVUbyh4IC0geE9mZnNldCwgeSAtIHlPZmZzZXQpO1xuICAgIGN0eC5saW5lVG8oeCArIHhPZmZzZXQsIHkgKyB5T2Zmc2V0KTtcbiAgICBjdHgubW92ZVRvKHggKyB5T2Zmc2V0LCB5IC0geE9mZnNldCk7XG4gICAgY3R4LmxpbmVUbyh4IC0geU9mZnNldCwgeSArIHhPZmZzZXQpO1xuICAgIGJyZWFrO1xuICBjYXNlICdzdGFyJzpcbiAgICB4T2Zmc2V0ID0gTWF0aC5jb3MocmFkKSAqIHJhZGl1cztcbiAgICB5T2Zmc2V0ID0gTWF0aC5zaW4ocmFkKSAqIHJhZGl1cztcbiAgICBjdHgubW92ZVRvKHggLSB4T2Zmc2V0LCB5IC0geU9mZnNldCk7XG4gICAgY3R4LmxpbmVUbyh4ICsgeE9mZnNldCwgeSArIHlPZmZzZXQpO1xuICAgIGN0eC5tb3ZlVG8oeCArIHlPZmZzZXQsIHkgLSB4T2Zmc2V0KTtcbiAgICBjdHgubGluZVRvKHggLSB5T2Zmc2V0LCB5ICsgeE9mZnNldCk7XG4gICAgcmFkICs9IFFVQVJURVJfUEk7XG4gICAgeE9mZnNldCA9IE1hdGguY29zKHJhZCkgKiByYWRpdXM7XG4gICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgY3R4Lm1vdmVUbyh4IC0geE9mZnNldCwgeSAtIHlPZmZzZXQpO1xuICAgIGN0eC5saW5lVG8oeCArIHhPZmZzZXQsIHkgKyB5T2Zmc2V0KTtcbiAgICBjdHgubW92ZVRvKHggKyB5T2Zmc2V0LCB5IC0geE9mZnNldCk7XG4gICAgY3R4LmxpbmVUbyh4IC0geU9mZnNldCwgeSArIHhPZmZzZXQpO1xuICAgIGJyZWFrO1xuICBjYXNlICdsaW5lJzpcbiAgICB4T2Zmc2V0ID0gTWF0aC5jb3MocmFkKSAqIHJhZGl1cztcbiAgICB5T2Zmc2V0ID0gTWF0aC5zaW4ocmFkKSAqIHJhZGl1cztcbiAgICBjdHgubW92ZVRvKHggLSB4T2Zmc2V0LCB5IC0geU9mZnNldCk7XG4gICAgY3R4LmxpbmVUbyh4ICsgeE9mZnNldCwgeSArIHlPZmZzZXQpO1xuICAgIGJyZWFrO1xuICBjYXNlICdkYXNoJzpcbiAgICBjdHgubW92ZVRvKHgsIHkpO1xuICAgIGN0eC5saW5lVG8oeCArIE1hdGguY29zKHJhZCkgKiByYWRpdXMsIHkgKyBNYXRoLnNpbihyYWQpICogcmFkaXVzKTtcbiAgICBicmVhaztcbiAgfVxuICBjdHguZmlsbCgpO1xuICBpZiAob3B0aW9ucy5ib3JkZXJXaWR0aCA+IDApIHtcbiAgICBjdHguc3Ryb2tlKCk7XG4gIH1cbn1cbmZ1bmN0aW9uIF9pc1BvaW50SW5BcmVhKHBvaW50LCBhcmVhLCBtYXJnaW4pIHtcbiAgbWFyZ2luID0gbWFyZ2luIHx8IDAuNTtcbiAgcmV0dXJuICFhcmVhIHx8IChwb2ludCAmJiBwb2ludC54ID4gYXJlYS5sZWZ0IC0gbWFyZ2luICYmIHBvaW50LnggPCBhcmVhLnJpZ2h0ICsgbWFyZ2luICYmXG5cdFx0cG9pbnQueSA+IGFyZWEudG9wIC0gbWFyZ2luICYmIHBvaW50LnkgPCBhcmVhLmJvdHRvbSArIG1hcmdpbik7XG59XG5mdW5jdGlvbiBjbGlwQXJlYShjdHgsIGFyZWEpIHtcbiAgY3R4LnNhdmUoKTtcbiAgY3R4LmJlZ2luUGF0aCgpO1xuICBjdHgucmVjdChhcmVhLmxlZnQsIGFyZWEudG9wLCBhcmVhLnJpZ2h0IC0gYXJlYS5sZWZ0LCBhcmVhLmJvdHRvbSAtIGFyZWEudG9wKTtcbiAgY3R4LmNsaXAoKTtcbn1cbmZ1bmN0aW9uIHVuY2xpcEFyZWEoY3R4KSB7XG4gIGN0eC5yZXN0b3JlKCk7XG59XG5mdW5jdGlvbiBfc3RlcHBlZExpbmVUbyhjdHgsIHByZXZpb3VzLCB0YXJnZXQsIGZsaXAsIG1vZGUpIHtcbiAgaWYgKCFwcmV2aW91cykge1xuICAgIHJldHVybiBjdHgubGluZVRvKHRhcmdldC54LCB0YXJnZXQueSk7XG4gIH1cbiAgaWYgKG1vZGUgPT09ICdtaWRkbGUnKSB7XG4gICAgY29uc3QgbWlkcG9pbnQgPSAocHJldmlvdXMueCArIHRhcmdldC54KSAvIDIuMDtcbiAgICBjdHgubGluZVRvKG1pZHBvaW50LCBwcmV2aW91cy55KTtcbiAgICBjdHgubGluZVRvKG1pZHBvaW50LCB0YXJnZXQueSk7XG4gIH0gZWxzZSBpZiAobW9kZSA9PT0gJ2FmdGVyJyAhPT0gISFmbGlwKSB7XG4gICAgY3R4LmxpbmVUbyhwcmV2aW91cy54LCB0YXJnZXQueSk7XG4gIH0gZWxzZSB7XG4gICAgY3R4LmxpbmVUbyh0YXJnZXQueCwgcHJldmlvdXMueSk7XG4gIH1cbiAgY3R4LmxpbmVUbyh0YXJnZXQueCwgdGFyZ2V0LnkpO1xufVxuZnVuY3Rpb24gX2JlemllckN1cnZlVG8oY3R4LCBwcmV2aW91cywgdGFyZ2V0LCBmbGlwKSB7XG4gIGlmICghcHJldmlvdXMpIHtcbiAgICByZXR1cm4gY3R4LmxpbmVUbyh0YXJnZXQueCwgdGFyZ2V0LnkpO1xuICB9XG4gIGN0eC5iZXppZXJDdXJ2ZVRvKFxuICAgIGZsaXAgPyBwcmV2aW91cy5jcDF4IDogcHJldmlvdXMuY3AyeCxcbiAgICBmbGlwID8gcHJldmlvdXMuY3AxeSA6IHByZXZpb3VzLmNwMnksXG4gICAgZmxpcCA/IHRhcmdldC5jcDJ4IDogdGFyZ2V0LmNwMXgsXG4gICAgZmxpcCA/IHRhcmdldC5jcDJ5IDogdGFyZ2V0LmNwMXksXG4gICAgdGFyZ2V0LngsXG4gICAgdGFyZ2V0LnkpO1xufVxuZnVuY3Rpb24gcmVuZGVyVGV4dChjdHgsIHRleHQsIHgsIHksIGZvbnQsIG9wdHMgPSB7fSkge1xuICBjb25zdCBsaW5lcyA9IGlzQXJyYXkodGV4dCkgPyB0ZXh0IDogW3RleHRdO1xuICBjb25zdCBzdHJva2UgPSBvcHRzLnN0cm9rZVdpZHRoID4gMCAmJiBvcHRzLnN0cm9rZUNvbG9yICE9PSAnJztcbiAgbGV0IGksIGxpbmU7XG4gIGN0eC5zYXZlKCk7XG4gIGN0eC5mb250ID0gZm9udC5zdHJpbmc7XG4gIHNldFJlbmRlck9wdHMoY3R4LCBvcHRzKTtcbiAgZm9yIChpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgKytpKSB7XG4gICAgbGluZSA9IGxpbmVzW2ldO1xuICAgIGlmIChzdHJva2UpIHtcbiAgICAgIGlmIChvcHRzLnN0cm9rZUNvbG9yKSB7XG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IG9wdHMuc3Ryb2tlQ29sb3I7XG4gICAgICB9XG4gICAgICBpZiAoIWlzTnVsbE9yVW5kZWYob3B0cy5zdHJva2VXaWR0aCkpIHtcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IG9wdHMuc3Ryb2tlV2lkdGg7XG4gICAgICB9XG4gICAgICBjdHguc3Ryb2tlVGV4dChsaW5lLCB4LCB5LCBvcHRzLm1heFdpZHRoKTtcbiAgICB9XG4gICAgY3R4LmZpbGxUZXh0KGxpbmUsIHgsIHksIG9wdHMubWF4V2lkdGgpO1xuICAgIGRlY29yYXRlVGV4dChjdHgsIHgsIHksIGxpbmUsIG9wdHMpO1xuICAgIHkgKz0gZm9udC5saW5lSGVpZ2h0O1xuICB9XG4gIGN0eC5yZXN0b3JlKCk7XG59XG5mdW5jdGlvbiBzZXRSZW5kZXJPcHRzKGN0eCwgb3B0cykge1xuICBpZiAob3B0cy50cmFuc2xhdGlvbikge1xuICAgIGN0eC50cmFuc2xhdGUob3B0cy50cmFuc2xhdGlvblswXSwgb3B0cy50cmFuc2xhdGlvblsxXSk7XG4gIH1cbiAgaWYgKCFpc051bGxPclVuZGVmKG9wdHMucm90YXRpb24pKSB7XG4gICAgY3R4LnJvdGF0ZShvcHRzLnJvdGF0aW9uKTtcbiAgfVxuICBpZiAob3B0cy5jb2xvcikge1xuICAgIGN0eC5maWxsU3R5bGUgPSBvcHRzLmNvbG9yO1xuICB9XG4gIGlmIChvcHRzLnRleHRBbGlnbikge1xuICAgIGN0eC50ZXh0QWxpZ24gPSBvcHRzLnRleHRBbGlnbjtcbiAgfVxuICBpZiAob3B0cy50ZXh0QmFzZWxpbmUpIHtcbiAgICBjdHgudGV4dEJhc2VsaW5lID0gb3B0cy50ZXh0QmFzZWxpbmU7XG4gIH1cbn1cbmZ1bmN0aW9uIGRlY29yYXRlVGV4dChjdHgsIHgsIHksIGxpbmUsIG9wdHMpIHtcbiAgaWYgKG9wdHMuc3RyaWtldGhyb3VnaCB8fCBvcHRzLnVuZGVybGluZSkge1xuICAgIGNvbnN0IG1ldHJpY3MgPSBjdHgubWVhc3VyZVRleHQobGluZSk7XG4gICAgY29uc3QgbGVmdCA9IHggLSBtZXRyaWNzLmFjdHVhbEJvdW5kaW5nQm94TGVmdDtcbiAgICBjb25zdCByaWdodCA9IHggKyBtZXRyaWNzLmFjdHVhbEJvdW5kaW5nQm94UmlnaHQ7XG4gICAgY29uc3QgdG9wID0geSAtIG1ldHJpY3MuYWN0dWFsQm91bmRpbmdCb3hBc2NlbnQ7XG4gICAgY29uc3QgYm90dG9tID0geSArIG1ldHJpY3MuYWN0dWFsQm91bmRpbmdCb3hEZXNjZW50O1xuICAgIGNvbnN0IHlEZWNvcmF0aW9uID0gb3B0cy5zdHJpa2V0aHJvdWdoID8gKHRvcCArIGJvdHRvbSkgLyAyIDogYm90dG9tO1xuICAgIGN0eC5zdHJva2VTdHlsZSA9IGN0eC5maWxsU3R5bGU7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIGN0eC5saW5lV2lkdGggPSBvcHRzLmRlY29yYXRpb25XaWR0aCB8fCAyO1xuICAgIGN0eC5tb3ZlVG8obGVmdCwgeURlY29yYXRpb24pO1xuICAgIGN0eC5saW5lVG8ocmlnaHQsIHlEZWNvcmF0aW9uKTtcbiAgICBjdHguc3Ryb2tlKCk7XG4gIH1cbn1cbmZ1bmN0aW9uIGFkZFJvdW5kZWRSZWN0UGF0aChjdHgsIHJlY3QpIHtcbiAgY29uc3Qge3gsIHksIHcsIGgsIHJhZGl1c30gPSByZWN0O1xuICBjdHguYXJjKHggKyByYWRpdXMudG9wTGVmdCwgeSArIHJhZGl1cy50b3BMZWZ0LCByYWRpdXMudG9wTGVmdCwgLUhBTEZfUEksIFBJLCB0cnVlKTtcbiAgY3R4LmxpbmVUbyh4LCB5ICsgaCAtIHJhZGl1cy5ib3R0b21MZWZ0KTtcbiAgY3R4LmFyYyh4ICsgcmFkaXVzLmJvdHRvbUxlZnQsIHkgKyBoIC0gcmFkaXVzLmJvdHRvbUxlZnQsIHJhZGl1cy5ib3R0b21MZWZ0LCBQSSwgSEFMRl9QSSwgdHJ1ZSk7XG4gIGN0eC5saW5lVG8oeCArIHcgLSByYWRpdXMuYm90dG9tUmlnaHQsIHkgKyBoKTtcbiAgY3R4LmFyYyh4ICsgdyAtIHJhZGl1cy5ib3R0b21SaWdodCwgeSArIGggLSByYWRpdXMuYm90dG9tUmlnaHQsIHJhZGl1cy5ib3R0b21SaWdodCwgSEFMRl9QSSwgMCwgdHJ1ZSk7XG4gIGN0eC5saW5lVG8oeCArIHcsIHkgKyByYWRpdXMudG9wUmlnaHQpO1xuICBjdHguYXJjKHggKyB3IC0gcmFkaXVzLnRvcFJpZ2h0LCB5ICsgcmFkaXVzLnRvcFJpZ2h0LCByYWRpdXMudG9wUmlnaHQsIDAsIC1IQUxGX1BJLCB0cnVlKTtcbiAgY3R4LmxpbmVUbyh4ICsgcmFkaXVzLnRvcExlZnQsIHkpO1xufVxuXG5jb25zdCBMSU5FX0hFSUdIVCA9IG5ldyBSZWdFeHAoL14obm9ybWFsfChcXGQrKD86XFwuXFxkKyk/KShweHxlbXwlKT8pJC8pO1xuY29uc3QgRk9OVF9TVFlMRSA9IG5ldyBSZWdFeHAoL14obm9ybWFsfGl0YWxpY3xpbml0aWFsfGluaGVyaXR8dW5zZXR8KG9ibGlxdWUoIC0/WzAtOV0/WzAtOV1kZWcpPykpJC8pO1xuZnVuY3Rpb24gdG9MaW5lSGVpZ2h0KHZhbHVlLCBzaXplKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSAoJycgKyB2YWx1ZSkubWF0Y2goTElORV9IRUlHSFQpO1xuICBpZiAoIW1hdGNoZXMgfHwgbWF0Y2hlc1sxXSA9PT0gJ25vcm1hbCcpIHtcbiAgICByZXR1cm4gc2l6ZSAqIDEuMjtcbiAgfVxuICB2YWx1ZSA9ICttYXRjaGVzWzJdO1xuICBzd2l0Y2ggKG1hdGNoZXNbM10pIHtcbiAgY2FzZSAncHgnOlxuICAgIHJldHVybiB2YWx1ZTtcbiAgY2FzZSAnJSc6XG4gICAgdmFsdWUgLz0gMTAwO1xuICAgIGJyZWFrO1xuICB9XG4gIHJldHVybiBzaXplICogdmFsdWU7XG59XG5jb25zdCBudW1iZXJPclplcm8gPSB2ID0+ICt2IHx8IDA7XG5mdW5jdGlvbiBfcmVhZFZhbHVlVG9Qcm9wcyh2YWx1ZSwgcHJvcHMpIHtcbiAgY29uc3QgcmV0ID0ge307XG4gIGNvbnN0IG9ialByb3BzID0gaXNPYmplY3QocHJvcHMpO1xuICBjb25zdCBrZXlzID0gb2JqUHJvcHMgPyBPYmplY3Qua2V5cyhwcm9wcykgOiBwcm9wcztcbiAgY29uc3QgcmVhZCA9IGlzT2JqZWN0KHZhbHVlKVxuICAgID8gb2JqUHJvcHNcbiAgICAgID8gcHJvcCA9PiB2YWx1ZU9yRGVmYXVsdCh2YWx1ZVtwcm9wXSwgdmFsdWVbcHJvcHNbcHJvcF1dKVxuICAgICAgOiBwcm9wID0+IHZhbHVlW3Byb3BdXG4gICAgOiAoKSA9PiB2YWx1ZTtcbiAgZm9yIChjb25zdCBwcm9wIG9mIGtleXMpIHtcbiAgICByZXRbcHJvcF0gPSBudW1iZXJPclplcm8ocmVhZChwcm9wKSk7XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cbmZ1bmN0aW9uIHRvVFJCTCh2YWx1ZSkge1xuICByZXR1cm4gX3JlYWRWYWx1ZVRvUHJvcHModmFsdWUsIHt0b3A6ICd5JywgcmlnaHQ6ICd4JywgYm90dG9tOiAneScsIGxlZnQ6ICd4J30pO1xufVxuZnVuY3Rpb24gdG9UUkJMQ29ybmVycyh2YWx1ZSkge1xuICByZXR1cm4gX3JlYWRWYWx1ZVRvUHJvcHModmFsdWUsIFsndG9wTGVmdCcsICd0b3BSaWdodCcsICdib3R0b21MZWZ0JywgJ2JvdHRvbVJpZ2h0J10pO1xufVxuZnVuY3Rpb24gdG9QYWRkaW5nKHZhbHVlKSB7XG4gIGNvbnN0IG9iaiA9IHRvVFJCTCh2YWx1ZSk7XG4gIG9iai53aWR0aCA9IG9iai5sZWZ0ICsgb2JqLnJpZ2h0O1xuICBvYmouaGVpZ2h0ID0gb2JqLnRvcCArIG9iai5ib3R0b207XG4gIHJldHVybiBvYmo7XG59XG5mdW5jdGlvbiB0b0ZvbnQob3B0aW9ucywgZmFsbGJhY2spIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGZhbGxiYWNrID0gZmFsbGJhY2sgfHwgZGVmYXVsdHMuZm9udDtcbiAgbGV0IHNpemUgPSB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLnNpemUsIGZhbGxiYWNrLnNpemUpO1xuICBpZiAodHlwZW9mIHNpemUgPT09ICdzdHJpbmcnKSB7XG4gICAgc2l6ZSA9IHBhcnNlSW50KHNpemUsIDEwKTtcbiAgfVxuICBsZXQgc3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLnN0eWxlLCBmYWxsYmFjay5zdHlsZSk7XG4gIGlmIChzdHlsZSAmJiAhKCcnICsgc3R5bGUpLm1hdGNoKEZPTlRfU1RZTEUpKSB7XG4gICAgY29uc29sZS53YXJuKCdJbnZhbGlkIGZvbnQgc3R5bGUgc3BlY2lmaWVkOiBcIicgKyBzdHlsZSArICdcIicpO1xuICAgIHN0eWxlID0gJyc7XG4gIH1cbiAgY29uc3QgZm9udCA9IHtcbiAgICBmYW1pbHk6IHZhbHVlT3JEZWZhdWx0KG9wdGlvbnMuZmFtaWx5LCBmYWxsYmFjay5mYW1pbHkpLFxuICAgIGxpbmVIZWlnaHQ6IHRvTGluZUhlaWdodCh2YWx1ZU9yRGVmYXVsdChvcHRpb25zLmxpbmVIZWlnaHQsIGZhbGxiYWNrLmxpbmVIZWlnaHQpLCBzaXplKSxcbiAgICBzaXplLFxuICAgIHN0eWxlLFxuICAgIHdlaWdodDogdmFsdWVPckRlZmF1bHQob3B0aW9ucy53ZWlnaHQsIGZhbGxiYWNrLndlaWdodCksXG4gICAgc3RyaW5nOiAnJ1xuICB9O1xuICBmb250LnN0cmluZyA9IHRvRm9udFN0cmluZyhmb250KTtcbiAgcmV0dXJuIGZvbnQ7XG59XG5mdW5jdGlvbiByZXNvbHZlKGlucHV0cywgY29udGV4dCwgaW5kZXgsIGluZm8pIHtcbiAgbGV0IGNhY2hlYWJsZSA9IHRydWU7XG4gIGxldCBpLCBpbGVuLCB2YWx1ZTtcbiAgZm9yIChpID0gMCwgaWxlbiA9IGlucHV0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICB2YWx1ZSA9IGlucHV0c1tpXTtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChjb250ZXh0ICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB2YWx1ZSA9IHZhbHVlKGNvbnRleHQpO1xuICAgICAgY2FjaGVhYmxlID0gZmFsc2U7XG4gICAgfVxuICAgIGlmIChpbmRleCAhPT0gdW5kZWZpbmVkICYmIGlzQXJyYXkodmFsdWUpKSB7XG4gICAgICB2YWx1ZSA9IHZhbHVlW2luZGV4ICUgdmFsdWUubGVuZ3RoXTtcbiAgICAgIGNhY2hlYWJsZSA9IGZhbHNlO1xuICAgIH1cbiAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGluZm8gJiYgIWNhY2hlYWJsZSkge1xuICAgICAgICBpbmZvLmNhY2hlYWJsZSA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gX2FkZEdyYWNlKG1pbm1heCwgZ3JhY2UpIHtcbiAgY29uc3Qge21pbiwgbWF4fSA9IG1pbm1heDtcbiAgcmV0dXJuIHtcbiAgICBtaW46IG1pbiAtIE1hdGguYWJzKHRvRGltZW5zaW9uKGdyYWNlLCBtaW4pKSxcbiAgICBtYXg6IG1heCArIHRvRGltZW5zaW9uKGdyYWNlLCBtYXgpXG4gIH07XG59XG5cbmZ1bmN0aW9uIF9sb29rdXAodGFibGUsIHZhbHVlLCBjbXApIHtcbiAgY21wID0gY21wIHx8ICgoaW5kZXgpID0+IHRhYmxlW2luZGV4XSA8IHZhbHVlKTtcbiAgbGV0IGhpID0gdGFibGUubGVuZ3RoIC0gMTtcbiAgbGV0IGxvID0gMDtcbiAgbGV0IG1pZDtcbiAgd2hpbGUgKGhpIC0gbG8gPiAxKSB7XG4gICAgbWlkID0gKGxvICsgaGkpID4+IDE7XG4gICAgaWYgKGNtcChtaWQpKSB7XG4gICAgICBsbyA9IG1pZDtcbiAgICB9IGVsc2Uge1xuICAgICAgaGkgPSBtaWQ7XG4gICAgfVxuICB9XG4gIHJldHVybiB7bG8sIGhpfTtcbn1cbmNvbnN0IF9sb29rdXBCeUtleSA9ICh0YWJsZSwga2V5LCB2YWx1ZSkgPT5cbiAgX2xvb2t1cCh0YWJsZSwgdmFsdWUsIGluZGV4ID0+IHRhYmxlW2luZGV4XVtrZXldIDwgdmFsdWUpO1xuY29uc3QgX3Jsb29rdXBCeUtleSA9ICh0YWJsZSwga2V5LCB2YWx1ZSkgPT5cbiAgX2xvb2t1cCh0YWJsZSwgdmFsdWUsIGluZGV4ID0+IHRhYmxlW2luZGV4XVtrZXldID49IHZhbHVlKTtcbmZ1bmN0aW9uIF9maWx0ZXJCZXR3ZWVuKHZhbHVlcywgbWluLCBtYXgpIHtcbiAgbGV0IHN0YXJ0ID0gMDtcbiAgbGV0IGVuZCA9IHZhbHVlcy5sZW5ndGg7XG4gIHdoaWxlIChzdGFydCA8IGVuZCAmJiB2YWx1ZXNbc3RhcnRdIDwgbWluKSB7XG4gICAgc3RhcnQrKztcbiAgfVxuICB3aGlsZSAoZW5kID4gc3RhcnQgJiYgdmFsdWVzW2VuZCAtIDFdID4gbWF4KSB7XG4gICAgZW5kLS07XG4gIH1cbiAgcmV0dXJuIHN0YXJ0ID4gMCB8fCBlbmQgPCB2YWx1ZXMubGVuZ3RoXG4gICAgPyB2YWx1ZXMuc2xpY2Uoc3RhcnQsIGVuZClcbiAgICA6IHZhbHVlcztcbn1cbmNvbnN0IGFycmF5RXZlbnRzID0gWydwdXNoJywgJ3BvcCcsICdzaGlmdCcsICdzcGxpY2UnLCAndW5zaGlmdCddO1xuZnVuY3Rpb24gbGlzdGVuQXJyYXlFdmVudHMoYXJyYXksIGxpc3RlbmVyKSB7XG4gIGlmIChhcnJheS5fY2hhcnRqcykge1xuICAgIGFycmF5Ll9jaGFydGpzLmxpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcbiAgICByZXR1cm47XG4gIH1cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFycmF5LCAnX2NoYXJ0anMnLCB7XG4gICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIHZhbHVlOiB7XG4gICAgICBsaXN0ZW5lcnM6IFtsaXN0ZW5lcl1cbiAgICB9XG4gIH0pO1xuICBhcnJheUV2ZW50cy5mb3JFYWNoKChrZXkpID0+IHtcbiAgICBjb25zdCBtZXRob2QgPSAnX29uRGF0YScgKyBfY2FwaXRhbGl6ZShrZXkpO1xuICAgIGNvbnN0IGJhc2UgPSBhcnJheVtrZXldO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhcnJheSwga2V5LCB7XG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIHZhbHVlKC4uLmFyZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzID0gYmFzZS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgYXJyYXkuX2NoYXJ0anMubGlzdGVuZXJzLmZvckVhY2goKG9iamVjdCkgPT4ge1xuICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0W21ldGhvZF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIG9iamVjdFttZXRob2RdKC4uLmFyZ3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuZnVuY3Rpb24gdW5saXN0ZW5BcnJheUV2ZW50cyhhcnJheSwgbGlzdGVuZXIpIHtcbiAgY29uc3Qgc3R1YiA9IGFycmF5Ll9jaGFydGpzO1xuICBpZiAoIXN0dWIpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgbGlzdGVuZXJzID0gc3R1Yi5saXN0ZW5lcnM7XG4gIGNvbnN0IGluZGV4ID0gbGlzdGVuZXJzLmluZGV4T2YobGlzdGVuZXIpO1xuICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgbGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbiAgaWYgKGxpc3RlbmVycy5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGFycmF5RXZlbnRzLmZvckVhY2goKGtleSkgPT4ge1xuICAgIGRlbGV0ZSBhcnJheVtrZXldO1xuICB9KTtcbiAgZGVsZXRlIGFycmF5Ll9jaGFydGpzO1xufVxuZnVuY3Rpb24gX2FycmF5VW5pcXVlKGl0ZW1zKSB7XG4gIGNvbnN0IHNldCA9IG5ldyBTZXQoKTtcbiAgbGV0IGksIGlsZW47XG4gIGZvciAoaSA9IDAsIGlsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpIHtcbiAgICBzZXQuYWRkKGl0ZW1zW2ldKTtcbiAgfVxuICBpZiAoc2V0LnNpemUgPT09IGlsZW4pIHtcbiAgICByZXR1cm4gaXRlbXM7XG4gIH1cbiAgcmV0dXJuIEFycmF5LmZyb20oc2V0KTtcbn1cblxuZnVuY3Rpb24gX2NyZWF0ZVJlc29sdmVyKHNjb3BlcywgcHJlZml4ZXMgPSBbJyddLCByb290U2NvcGVzID0gc2NvcGVzLCBmYWxsYmFjaywgZ2V0VGFyZ2V0ID0gKCkgPT4gc2NvcGVzWzBdKSB7XG4gIGlmICghZGVmaW5lZChmYWxsYmFjaykpIHtcbiAgICBmYWxsYmFjayA9IF9yZXNvbHZlKCdfZmFsbGJhY2snLCBzY29wZXMpO1xuICB9XG4gIGNvbnN0IGNhY2hlID0ge1xuICAgIFtTeW1ib2wudG9TdHJpbmdUYWddOiAnT2JqZWN0JyxcbiAgICBfY2FjaGVhYmxlOiB0cnVlLFxuICAgIF9zY29wZXM6IHNjb3BlcyxcbiAgICBfcm9vdFNjb3Blczogcm9vdFNjb3BlcyxcbiAgICBfZmFsbGJhY2s6IGZhbGxiYWNrLFxuICAgIF9nZXRUYXJnZXQ6IGdldFRhcmdldCxcbiAgICBvdmVycmlkZTogKHNjb3BlKSA9PiBfY3JlYXRlUmVzb2x2ZXIoW3Njb3BlLCAuLi5zY29wZXNdLCBwcmVmaXhlcywgcm9vdFNjb3BlcywgZmFsbGJhY2spLFxuICB9O1xuICByZXR1cm4gbmV3IFByb3h5KGNhY2hlLCB7XG4gICAgZGVsZXRlUHJvcGVydHkodGFyZ2V0LCBwcm9wKSB7XG4gICAgICBkZWxldGUgdGFyZ2V0W3Byb3BdO1xuICAgICAgZGVsZXRlIHRhcmdldC5fa2V5cztcbiAgICAgIGRlbGV0ZSBzY29wZXNbMF1bcHJvcF07XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9LFxuICAgIGdldCh0YXJnZXQsIHByb3ApIHtcbiAgICAgIHJldHVybiBfY2FjaGVkKHRhcmdldCwgcHJvcCxcbiAgICAgICAgKCkgPT4gX3Jlc29sdmVXaXRoUHJlZml4ZXMocHJvcCwgcHJlZml4ZXMsIHNjb3BlcywgdGFyZ2V0KSk7XG4gICAgfSxcbiAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBwcm9wKSB7XG4gICAgICByZXR1cm4gUmVmbGVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0Ll9zY29wZXNbMF0sIHByb3ApO1xuICAgIH0sXG4gICAgZ2V0UHJvdG90eXBlT2YoKSB7XG4gICAgICByZXR1cm4gUmVmbGVjdC5nZXRQcm90b3R5cGVPZihzY29wZXNbMF0pO1xuICAgIH0sXG4gICAgaGFzKHRhcmdldCwgcHJvcCkge1xuICAgICAgcmV0dXJuIGdldEtleXNGcm9tQWxsU2NvcGVzKHRhcmdldCkuaW5jbHVkZXMocHJvcCk7XG4gICAgfSxcbiAgICBvd25LZXlzKHRhcmdldCkge1xuICAgICAgcmV0dXJuIGdldEtleXNGcm9tQWxsU2NvcGVzKHRhcmdldCk7XG4gICAgfSxcbiAgICBzZXQodGFyZ2V0LCBwcm9wLCB2YWx1ZSkge1xuICAgICAgY29uc3Qgc3RvcmFnZSA9IHRhcmdldC5fc3RvcmFnZSB8fCAodGFyZ2V0Ll9zdG9yYWdlID0gZ2V0VGFyZ2V0KCkpO1xuICAgICAgc3RvcmFnZVtwcm9wXSA9IHZhbHVlO1xuICAgICAgZGVsZXRlIHRhcmdldFtwcm9wXTtcbiAgICAgIGRlbGV0ZSB0YXJnZXQuX2tleXM7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0pO1xufVxuZnVuY3Rpb24gX2F0dGFjaENvbnRleHQocHJveHksIGNvbnRleHQsIHN1YlByb3h5LCBkZXNjcmlwdG9yRGVmYXVsdHMpIHtcbiAgY29uc3QgY2FjaGUgPSB7XG4gICAgX2NhY2hlYWJsZTogZmFsc2UsXG4gICAgX3Byb3h5OiBwcm94eSxcbiAgICBfY29udGV4dDogY29udGV4dCxcbiAgICBfc3ViUHJveHk6IHN1YlByb3h5LFxuICAgIF9zdGFjazogbmV3IFNldCgpLFxuICAgIF9kZXNjcmlwdG9yczogX2Rlc2NyaXB0b3JzKHByb3h5LCBkZXNjcmlwdG9yRGVmYXVsdHMpLFxuICAgIHNldENvbnRleHQ6IChjdHgpID0+IF9hdHRhY2hDb250ZXh0KHByb3h5LCBjdHgsIHN1YlByb3h5LCBkZXNjcmlwdG9yRGVmYXVsdHMpLFxuICAgIG92ZXJyaWRlOiAoc2NvcGUpID0+IF9hdHRhY2hDb250ZXh0KHByb3h5Lm92ZXJyaWRlKHNjb3BlKSwgY29udGV4dCwgc3ViUHJveHksIGRlc2NyaXB0b3JEZWZhdWx0cylcbiAgfTtcbiAgcmV0dXJuIG5ldyBQcm94eShjYWNoZSwge1xuICAgIGRlbGV0ZVByb3BlcnR5KHRhcmdldCwgcHJvcCkge1xuICAgICAgZGVsZXRlIHRhcmdldFtwcm9wXTtcbiAgICAgIGRlbGV0ZSBwcm94eVtwcm9wXTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpIHtcbiAgICAgIHJldHVybiBfY2FjaGVkKHRhcmdldCwgcHJvcCxcbiAgICAgICAgKCkgPT4gX3Jlc29sdmVXaXRoQ29udGV4dCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKSk7XG4gICAgfSxcbiAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBwcm9wKSB7XG4gICAgICByZXR1cm4gdGFyZ2V0Ll9kZXNjcmlwdG9ycy5hbGxLZXlzXG4gICAgICAgID8gUmVmbGVjdC5oYXMocHJveHksIHByb3ApID8ge2VudW1lcmFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZX0gOiB1bmRlZmluZWRcbiAgICAgICAgOiBSZWZsZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihwcm94eSwgcHJvcCk7XG4gICAgfSxcbiAgICBnZXRQcm90b3R5cGVPZigpIHtcbiAgICAgIHJldHVybiBSZWZsZWN0LmdldFByb3RvdHlwZU9mKHByb3h5KTtcbiAgICB9LFxuICAgIGhhcyh0YXJnZXQsIHByb3ApIHtcbiAgICAgIHJldHVybiBSZWZsZWN0Lmhhcyhwcm94eSwgcHJvcCk7XG4gICAgfSxcbiAgICBvd25LZXlzKCkge1xuICAgICAgcmV0dXJuIFJlZmxlY3Qub3duS2V5cyhwcm94eSk7XG4gICAgfSxcbiAgICBzZXQodGFyZ2V0LCBwcm9wLCB2YWx1ZSkge1xuICAgICAgcHJveHlbcHJvcF0gPSB2YWx1ZTtcbiAgICAgIGRlbGV0ZSB0YXJnZXRbcHJvcF07XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0pO1xufVxuZnVuY3Rpb24gX2Rlc2NyaXB0b3JzKHByb3h5LCBkZWZhdWx0cyA9IHtzY3JpcHRhYmxlOiB0cnVlLCBpbmRleGFibGU6IHRydWV9KSB7XG4gIGNvbnN0IHtfc2NyaXB0YWJsZSA9IGRlZmF1bHRzLnNjcmlwdGFibGUsIF9pbmRleGFibGUgPSBkZWZhdWx0cy5pbmRleGFibGUsIF9hbGxLZXlzID0gZGVmYXVsdHMuYWxsS2V5c30gPSBwcm94eTtcbiAgcmV0dXJuIHtcbiAgICBhbGxLZXlzOiBfYWxsS2V5cyxcbiAgICBzY3JpcHRhYmxlOiBfc2NyaXB0YWJsZSxcbiAgICBpbmRleGFibGU6IF9pbmRleGFibGUsXG4gICAgaXNTY3JpcHRhYmxlOiBpc0Z1bmN0aW9uKF9zY3JpcHRhYmxlKSA/IF9zY3JpcHRhYmxlIDogKCkgPT4gX3NjcmlwdGFibGUsXG4gICAgaXNJbmRleGFibGU6IGlzRnVuY3Rpb24oX2luZGV4YWJsZSkgPyBfaW5kZXhhYmxlIDogKCkgPT4gX2luZGV4YWJsZVxuICB9O1xufVxuY29uc3QgcmVhZEtleSA9IChwcmVmaXgsIG5hbWUpID0+IHByZWZpeCA/IHByZWZpeCArIF9jYXBpdGFsaXplKG5hbWUpIDogbmFtZTtcbmNvbnN0IG5lZWRzU3ViUmVzb2x2ZXIgPSAocHJvcCwgdmFsdWUpID0+IGlzT2JqZWN0KHZhbHVlKSAmJiBwcm9wICE9PSAnYWRhcHRlcnMnO1xuZnVuY3Rpb24gX2NhY2hlZCh0YXJnZXQsIHByb3AsIHJlc29sdmUpIHtcbiAgbGV0IHZhbHVlID0gdGFyZ2V0W3Byb3BdO1xuICBpZiAoZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgdmFsdWUgPSByZXNvbHZlKCk7XG4gIGlmIChkZWZpbmVkKHZhbHVlKSkge1xuICAgIHRhcmdldFtwcm9wXSA9IHZhbHVlO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIF9yZXNvbHZlV2l0aENvbnRleHQodGFyZ2V0LCBwcm9wLCByZWNlaXZlcikge1xuICBjb25zdCB7X3Byb3h5LCBfY29udGV4dCwgX3N1YlByb3h5LCBfZGVzY3JpcHRvcnM6IGRlc2NyaXB0b3JzfSA9IHRhcmdldDtcbiAgbGV0IHZhbHVlID0gX3Byb3h5W3Byb3BdO1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkgJiYgZGVzY3JpcHRvcnMuaXNTY3JpcHRhYmxlKHByb3ApKSB7XG4gICAgdmFsdWUgPSBfcmVzb2x2ZVNjcmlwdGFibGUocHJvcCwgdmFsdWUsIHRhcmdldCwgcmVjZWl2ZXIpO1xuICB9XG4gIGlmIChpc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGgpIHtcbiAgICB2YWx1ZSA9IF9yZXNvbHZlQXJyYXkocHJvcCwgdmFsdWUsIHRhcmdldCwgZGVzY3JpcHRvcnMuaXNJbmRleGFibGUpO1xuICB9XG4gIGlmIChuZWVkc1N1YlJlc29sdmVyKHByb3AsIHZhbHVlKSkge1xuICAgIHZhbHVlID0gX2F0dGFjaENvbnRleHQodmFsdWUsIF9jb250ZXh0LCBfc3ViUHJveHkgJiYgX3N1YlByb3h5W3Byb3BdLCBkZXNjcmlwdG9ycyk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuZnVuY3Rpb24gX3Jlc29sdmVTY3JpcHRhYmxlKHByb3AsIHZhbHVlLCB0YXJnZXQsIHJlY2VpdmVyKSB7XG4gIGNvbnN0IHtfcHJveHksIF9jb250ZXh0LCBfc3ViUHJveHksIF9zdGFja30gPSB0YXJnZXQ7XG4gIGlmIChfc3RhY2suaGFzKHByb3ApKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdSZWN1cnNpb24gZGV0ZWN0ZWQ6ICcgKyBBcnJheS5mcm9tKF9zdGFjaykuam9pbignLT4nKSArICctPicgKyBwcm9wKTtcbiAgfVxuICBfc3RhY2suYWRkKHByb3ApO1xuICB2YWx1ZSA9IHZhbHVlKF9jb250ZXh0LCBfc3ViUHJveHkgfHwgcmVjZWl2ZXIpO1xuICBfc3RhY2suZGVsZXRlKHByb3ApO1xuICBpZiAoaXNPYmplY3QodmFsdWUpKSB7XG4gICAgdmFsdWUgPSBjcmVhdGVTdWJSZXNvbHZlcihfcHJveHkuX3Njb3BlcywgX3Byb3h5LCBwcm9wLCB2YWx1ZSk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuZnVuY3Rpb24gX3Jlc29sdmVBcnJheShwcm9wLCB2YWx1ZSwgdGFyZ2V0LCBpc0luZGV4YWJsZSkge1xuICBjb25zdCB7X3Byb3h5LCBfY29udGV4dCwgX3N1YlByb3h5LCBfZGVzY3JpcHRvcnM6IGRlc2NyaXB0b3JzfSA9IHRhcmdldDtcbiAgaWYgKGRlZmluZWQoX2NvbnRleHQuaW5kZXgpICYmIGlzSW5kZXhhYmxlKHByb3ApKSB7XG4gICAgdmFsdWUgPSB2YWx1ZVtfY29udGV4dC5pbmRleCAlIHZhbHVlLmxlbmd0aF07XG4gIH0gZWxzZSBpZiAoaXNPYmplY3QodmFsdWVbMF0pKSB7XG4gICAgY29uc3QgYXJyID0gdmFsdWU7XG4gICAgY29uc3Qgc2NvcGVzID0gX3Byb3h5Ll9zY29wZXMuZmlsdGVyKHMgPT4gcyAhPT0gYXJyKTtcbiAgICB2YWx1ZSA9IFtdO1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBhcnIpIHtcbiAgICAgIGNvbnN0IHJlc29sdmVyID0gY3JlYXRlU3ViUmVzb2x2ZXIoc2NvcGVzLCBfcHJveHksIHByb3AsIGl0ZW0pO1xuICAgICAgdmFsdWUucHVzaChfYXR0YWNoQ29udGV4dChyZXNvbHZlciwgX2NvbnRleHQsIF9zdWJQcm94eSAmJiBfc3ViUHJveHlbcHJvcF0sIGRlc2NyaXB0b3JzKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIHJlc29sdmVGYWxsYmFjayhmYWxsYmFjaywgcHJvcCwgdmFsdWUpIHtcbiAgcmV0dXJuIGlzRnVuY3Rpb24oZmFsbGJhY2spID8gZmFsbGJhY2socHJvcCwgdmFsdWUpIDogZmFsbGJhY2s7XG59XG5jb25zdCBnZXRTY29wZSA9IChrZXksIHBhcmVudCkgPT4ga2V5ID09PSB0cnVlID8gcGFyZW50XG4gIDogdHlwZW9mIGtleSA9PT0gJ3N0cmluZycgPyByZXNvbHZlT2JqZWN0S2V5KHBhcmVudCwga2V5KSA6IHVuZGVmaW5lZDtcbmZ1bmN0aW9uIGFkZFNjb3BlcyhzZXQsIHBhcmVudFNjb3Blcywga2V5LCBwYXJlbnRGYWxsYmFjaykge1xuICBmb3IgKGNvbnN0IHBhcmVudCBvZiBwYXJlbnRTY29wZXMpIHtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKGtleSwgcGFyZW50KTtcbiAgICBpZiAoc2NvcGUpIHtcbiAgICAgIHNldC5hZGQoc2NvcGUpO1xuICAgICAgY29uc3QgZmFsbGJhY2sgPSByZXNvbHZlRmFsbGJhY2soc2NvcGUuX2ZhbGxiYWNrLCBrZXksIHNjb3BlKTtcbiAgICAgIGlmIChkZWZpbmVkKGZhbGxiYWNrKSAmJiBmYWxsYmFjayAhPT0ga2V5ICYmIGZhbGxiYWNrICE9PSBwYXJlbnRGYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gZmFsbGJhY2s7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChzY29wZSA9PT0gZmFsc2UgJiYgZGVmaW5lZChwYXJlbnRGYWxsYmFjaykgJiYga2V5ICE9PSBwYXJlbnRGYWxsYmFjaykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVN1YlJlc29sdmVyKHBhcmVudFNjb3BlcywgcmVzb2x2ZXIsIHByb3AsIHZhbHVlKSB7XG4gIGNvbnN0IHJvb3RTY29wZXMgPSByZXNvbHZlci5fcm9vdFNjb3BlcztcbiAgY29uc3QgZmFsbGJhY2sgPSByZXNvbHZlRmFsbGJhY2socmVzb2x2ZXIuX2ZhbGxiYWNrLCBwcm9wLCB2YWx1ZSk7XG4gIGNvbnN0IGFsbFNjb3BlcyA9IFsuLi5wYXJlbnRTY29wZXMsIC4uLnJvb3RTY29wZXNdO1xuICBjb25zdCBzZXQgPSBuZXcgU2V0KCk7XG4gIHNldC5hZGQodmFsdWUpO1xuICBsZXQga2V5ID0gYWRkU2NvcGVzRnJvbUtleShzZXQsIGFsbFNjb3BlcywgcHJvcCwgZmFsbGJhY2sgfHwgcHJvcCk7XG4gIGlmIChrZXkgPT09IG51bGwpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGRlZmluZWQoZmFsbGJhY2spICYmIGZhbGxiYWNrICE9PSBwcm9wKSB7XG4gICAga2V5ID0gYWRkU2NvcGVzRnJvbUtleShzZXQsIGFsbFNjb3BlcywgZmFsbGJhY2ssIGtleSk7XG4gICAgaWYgKGtleSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gX2NyZWF0ZVJlc29sdmVyKEFycmF5LmZyb20oc2V0KSwgWycnXSwgcm9vdFNjb3BlcywgZmFsbGJhY2ssXG4gICAgKCkgPT4gc3ViR2V0VGFyZ2V0KHJlc29sdmVyLCBwcm9wLCB2YWx1ZSkpO1xufVxuZnVuY3Rpb24gYWRkU2NvcGVzRnJvbUtleShzZXQsIGFsbFNjb3Blcywga2V5LCBmYWxsYmFjaykge1xuICB3aGlsZSAoa2V5KSB7XG4gICAga2V5ID0gYWRkU2NvcGVzKHNldCwgYWxsU2NvcGVzLCBrZXksIGZhbGxiYWNrKTtcbiAgfVxuICByZXR1cm4ga2V5O1xufVxuZnVuY3Rpb24gc3ViR2V0VGFyZ2V0KHJlc29sdmVyLCBwcm9wLCB2YWx1ZSkge1xuICBjb25zdCBwYXJlbnQgPSByZXNvbHZlci5fZ2V0VGFyZ2V0KCk7XG4gIGlmICghKHByb3AgaW4gcGFyZW50KSkge1xuICAgIHBhcmVudFtwcm9wXSA9IHt9O1xuICB9XG4gIGNvbnN0IHRhcmdldCA9IHBhcmVudFtwcm9wXTtcbiAgaWYgKGlzQXJyYXkodGFyZ2V0KSAmJiBpc09iamVjdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIHRhcmdldDtcbn1cbmZ1bmN0aW9uIF9yZXNvbHZlV2l0aFByZWZpeGVzKHByb3AsIHByZWZpeGVzLCBzY29wZXMsIHByb3h5KSB7XG4gIGxldCB2YWx1ZTtcbiAgZm9yIChjb25zdCBwcmVmaXggb2YgcHJlZml4ZXMpIHtcbiAgICB2YWx1ZSA9IF9yZXNvbHZlKHJlYWRLZXkocHJlZml4LCBwcm9wKSwgc2NvcGVzKTtcbiAgICBpZiAoZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBuZWVkc1N1YlJlc29sdmVyKHByb3AsIHZhbHVlKVxuICAgICAgICA/IGNyZWF0ZVN1YlJlc29sdmVyKHNjb3BlcywgcHJveHksIHByb3AsIHZhbHVlKVxuICAgICAgICA6IHZhbHVlO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gX3Jlc29sdmUoa2V5LCBzY29wZXMpIHtcbiAgZm9yIChjb25zdCBzY29wZSBvZiBzY29wZXMpIHtcbiAgICBpZiAoIXNjb3BlKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgdmFsdWUgPSBzY29wZVtrZXldO1xuICAgIGlmIChkZWZpbmVkKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gZ2V0S2V5c0Zyb21BbGxTY29wZXModGFyZ2V0KSB7XG4gIGxldCBrZXlzID0gdGFyZ2V0Ll9rZXlzO1xuICBpZiAoIWtleXMpIHtcbiAgICBrZXlzID0gdGFyZ2V0Ll9rZXlzID0gcmVzb2x2ZUtleXNGcm9tQWxsU2NvcGVzKHRhcmdldC5fc2NvcGVzKTtcbiAgfVxuICByZXR1cm4ga2V5cztcbn1cbmZ1bmN0aW9uIHJlc29sdmVLZXlzRnJvbUFsbFNjb3BlcyhzY29wZXMpIHtcbiAgY29uc3Qgc2V0ID0gbmV3IFNldCgpO1xuICBmb3IgKGNvbnN0IHNjb3BlIG9mIHNjb3Blcykge1xuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHNjb3BlKS5maWx0ZXIoayA9PiAhay5zdGFydHNXaXRoKCdfJykpKSB7XG4gICAgICBzZXQuYWRkKGtleSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBBcnJheS5mcm9tKHNldCk7XG59XG5cbmNvbnN0IEVQU0lMT04gPSBOdW1iZXIuRVBTSUxPTiB8fCAxZS0xNDtcbmNvbnN0IGdldFBvaW50ID0gKHBvaW50cywgaSkgPT4gaSA8IHBvaW50cy5sZW5ndGggJiYgIXBvaW50c1tpXS5za2lwICYmIHBvaW50c1tpXTtcbmNvbnN0IGdldFZhbHVlQXhpcyA9IChpbmRleEF4aXMpID0+IGluZGV4QXhpcyA9PT0gJ3gnID8gJ3knIDogJ3gnO1xuZnVuY3Rpb24gc3BsaW5lQ3VydmUoZmlyc3RQb2ludCwgbWlkZGxlUG9pbnQsIGFmdGVyUG9pbnQsIHQpIHtcbiAgY29uc3QgcHJldmlvdXMgPSBmaXJzdFBvaW50LnNraXAgPyBtaWRkbGVQb2ludCA6IGZpcnN0UG9pbnQ7XG4gIGNvbnN0IGN1cnJlbnQgPSBtaWRkbGVQb2ludDtcbiAgY29uc3QgbmV4dCA9IGFmdGVyUG9pbnQuc2tpcCA/IG1pZGRsZVBvaW50IDogYWZ0ZXJQb2ludDtcbiAgY29uc3QgZDAxID0gZGlzdGFuY2VCZXR3ZWVuUG9pbnRzKGN1cnJlbnQsIHByZXZpb3VzKTtcbiAgY29uc3QgZDEyID0gZGlzdGFuY2VCZXR3ZWVuUG9pbnRzKG5leHQsIGN1cnJlbnQpO1xuICBsZXQgczAxID0gZDAxIC8gKGQwMSArIGQxMik7XG4gIGxldCBzMTIgPSBkMTIgLyAoZDAxICsgZDEyKTtcbiAgczAxID0gaXNOYU4oczAxKSA/IDAgOiBzMDE7XG4gIHMxMiA9IGlzTmFOKHMxMikgPyAwIDogczEyO1xuICBjb25zdCBmYSA9IHQgKiBzMDE7XG4gIGNvbnN0IGZiID0gdCAqIHMxMjtcbiAgcmV0dXJuIHtcbiAgICBwcmV2aW91czoge1xuICAgICAgeDogY3VycmVudC54IC0gZmEgKiAobmV4dC54IC0gcHJldmlvdXMueCksXG4gICAgICB5OiBjdXJyZW50LnkgLSBmYSAqIChuZXh0LnkgLSBwcmV2aW91cy55KVxuICAgIH0sXG4gICAgbmV4dDoge1xuICAgICAgeDogY3VycmVudC54ICsgZmIgKiAobmV4dC54IC0gcHJldmlvdXMueCksXG4gICAgICB5OiBjdXJyZW50LnkgKyBmYiAqIChuZXh0LnkgLSBwcmV2aW91cy55KVxuICAgIH1cbiAgfTtcbn1cbmZ1bmN0aW9uIG1vbm90b25lQWRqdXN0KHBvaW50cywgZGVsdGFLLCBtSykge1xuICBjb25zdCBwb2ludHNMZW4gPSBwb2ludHMubGVuZ3RoO1xuICBsZXQgYWxwaGFLLCBiZXRhSywgdGF1Sywgc3F1YXJlZE1hZ25pdHVkZSwgcG9pbnRDdXJyZW50O1xuICBsZXQgcG9pbnRBZnRlciA9IGdldFBvaW50KHBvaW50cywgMCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzTGVuIC0gMTsgKytpKSB7XG4gICAgcG9pbnRDdXJyZW50ID0gcG9pbnRBZnRlcjtcbiAgICBwb2ludEFmdGVyID0gZ2V0UG9pbnQocG9pbnRzLCBpICsgMSk7XG4gICAgaWYgKCFwb2ludEN1cnJlbnQgfHwgIXBvaW50QWZ0ZXIpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoYWxtb3N0RXF1YWxzKGRlbHRhS1tpXSwgMCwgRVBTSUxPTikpIHtcbiAgICAgIG1LW2ldID0gbUtbaSArIDFdID0gMDtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBhbHBoYUsgPSBtS1tpXSAvIGRlbHRhS1tpXTtcbiAgICBiZXRhSyA9IG1LW2kgKyAxXSAvIGRlbHRhS1tpXTtcbiAgICBzcXVhcmVkTWFnbml0dWRlID0gTWF0aC5wb3coYWxwaGFLLCAyKSArIE1hdGgucG93KGJldGFLLCAyKTtcbiAgICBpZiAoc3F1YXJlZE1hZ25pdHVkZSA8PSA5KSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgdGF1SyA9IDMgLyBNYXRoLnNxcnQoc3F1YXJlZE1hZ25pdHVkZSk7XG4gICAgbUtbaV0gPSBhbHBoYUsgKiB0YXVLICogZGVsdGFLW2ldO1xuICAgIG1LW2kgKyAxXSA9IGJldGFLICogdGF1SyAqIGRlbHRhS1tpXTtcbiAgfVxufVxuZnVuY3Rpb24gbW9ub3RvbmVDb21wdXRlKHBvaW50cywgbUssIGluZGV4QXhpcyA9ICd4Jykge1xuICBjb25zdCB2YWx1ZUF4aXMgPSBnZXRWYWx1ZUF4aXMoaW5kZXhBeGlzKTtcbiAgY29uc3QgcG9pbnRzTGVuID0gcG9pbnRzLmxlbmd0aDtcbiAgbGV0IGRlbHRhLCBwb2ludEJlZm9yZSwgcG9pbnRDdXJyZW50O1xuICBsZXQgcG9pbnRBZnRlciA9IGdldFBvaW50KHBvaW50cywgMCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzTGVuOyArK2kpIHtcbiAgICBwb2ludEJlZm9yZSA9IHBvaW50Q3VycmVudDtcbiAgICBwb2ludEN1cnJlbnQgPSBwb2ludEFmdGVyO1xuICAgIHBvaW50QWZ0ZXIgPSBnZXRQb2ludChwb2ludHMsIGkgKyAxKTtcbiAgICBpZiAoIXBvaW50Q3VycmVudCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IGlQaXhlbCA9IHBvaW50Q3VycmVudFtpbmRleEF4aXNdO1xuICAgIGNvbnN0IHZQaXhlbCA9IHBvaW50Q3VycmVudFt2YWx1ZUF4aXNdO1xuICAgIGlmIChwb2ludEJlZm9yZSkge1xuICAgICAgZGVsdGEgPSAoaVBpeGVsIC0gcG9pbnRCZWZvcmVbaW5kZXhBeGlzXSkgLyAzO1xuICAgICAgcG9pbnRDdXJyZW50W2BjcDEke2luZGV4QXhpc31gXSA9IGlQaXhlbCAtIGRlbHRhO1xuICAgICAgcG9pbnRDdXJyZW50W2BjcDEke3ZhbHVlQXhpc31gXSA9IHZQaXhlbCAtIGRlbHRhICogbUtbaV07XG4gICAgfVxuICAgIGlmIChwb2ludEFmdGVyKSB7XG4gICAgICBkZWx0YSA9IChwb2ludEFmdGVyW2luZGV4QXhpc10gLSBpUGl4ZWwpIC8gMztcbiAgICAgIHBvaW50Q3VycmVudFtgY3AyJHtpbmRleEF4aXN9YF0gPSBpUGl4ZWwgKyBkZWx0YTtcbiAgICAgIHBvaW50Q3VycmVudFtgY3AyJHt2YWx1ZUF4aXN9YF0gPSB2UGl4ZWwgKyBkZWx0YSAqIG1LW2ldO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gc3BsaW5lQ3VydmVNb25vdG9uZShwb2ludHMsIGluZGV4QXhpcyA9ICd4Jykge1xuICBjb25zdCB2YWx1ZUF4aXMgPSBnZXRWYWx1ZUF4aXMoaW5kZXhBeGlzKTtcbiAgY29uc3QgcG9pbnRzTGVuID0gcG9pbnRzLmxlbmd0aDtcbiAgY29uc3QgZGVsdGFLID0gQXJyYXkocG9pbnRzTGVuKS5maWxsKDApO1xuICBjb25zdCBtSyA9IEFycmF5KHBvaW50c0xlbik7XG4gIGxldCBpLCBwb2ludEJlZm9yZSwgcG9pbnRDdXJyZW50O1xuICBsZXQgcG9pbnRBZnRlciA9IGdldFBvaW50KHBvaW50cywgMCk7XG4gIGZvciAoaSA9IDA7IGkgPCBwb2ludHNMZW47ICsraSkge1xuICAgIHBvaW50QmVmb3JlID0gcG9pbnRDdXJyZW50O1xuICAgIHBvaW50Q3VycmVudCA9IHBvaW50QWZ0ZXI7XG4gICAgcG9pbnRBZnRlciA9IGdldFBvaW50KHBvaW50cywgaSArIDEpO1xuICAgIGlmICghcG9pbnRDdXJyZW50KSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKHBvaW50QWZ0ZXIpIHtcbiAgICAgIGNvbnN0IHNsb3BlRGVsdGEgPSBwb2ludEFmdGVyW2luZGV4QXhpc10gLSBwb2ludEN1cnJlbnRbaW5kZXhBeGlzXTtcbiAgICAgIGRlbHRhS1tpXSA9IHNsb3BlRGVsdGEgIT09IDAgPyAocG9pbnRBZnRlclt2YWx1ZUF4aXNdIC0gcG9pbnRDdXJyZW50W3ZhbHVlQXhpc10pIC8gc2xvcGVEZWx0YSA6IDA7XG4gICAgfVxuICAgIG1LW2ldID0gIXBvaW50QmVmb3JlID8gZGVsdGFLW2ldXG4gICAgICA6ICFwb2ludEFmdGVyID8gZGVsdGFLW2kgLSAxXVxuICAgICAgOiAoc2lnbihkZWx0YUtbaSAtIDFdKSAhPT0gc2lnbihkZWx0YUtbaV0pKSA/IDBcbiAgICAgIDogKGRlbHRhS1tpIC0gMV0gKyBkZWx0YUtbaV0pIC8gMjtcbiAgfVxuICBtb25vdG9uZUFkanVzdChwb2ludHMsIGRlbHRhSywgbUspO1xuICBtb25vdG9uZUNvbXB1dGUocG9pbnRzLCBtSywgaW5kZXhBeGlzKTtcbn1cbmZ1bmN0aW9uIGNhcENvbnRyb2xQb2ludChwdCwgbWluLCBtYXgpIHtcbiAgcmV0dXJuIE1hdGgubWF4KE1hdGgubWluKHB0LCBtYXgpLCBtaW4pO1xufVxuZnVuY3Rpb24gY2FwQmV6aWVyUG9pbnRzKHBvaW50cywgYXJlYSkge1xuICBsZXQgaSwgaWxlbiwgcG9pbnQsIGluQXJlYSwgaW5BcmVhUHJldjtcbiAgbGV0IGluQXJlYU5leHQgPSBfaXNQb2ludEluQXJlYShwb2ludHNbMF0sIGFyZWEpO1xuICBmb3IgKGkgPSAwLCBpbGVuID0gcG9pbnRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSkge1xuICAgIGluQXJlYVByZXYgPSBpbkFyZWE7XG4gICAgaW5BcmVhID0gaW5BcmVhTmV4dDtcbiAgICBpbkFyZWFOZXh0ID0gaSA8IGlsZW4gLSAxICYmIF9pc1BvaW50SW5BcmVhKHBvaW50c1tpICsgMV0sIGFyZWEpO1xuICAgIGlmICghaW5BcmVhKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgcG9pbnQgPSBwb2ludHNbaV07XG4gICAgaWYgKGluQXJlYVByZXYpIHtcbiAgICAgIHBvaW50LmNwMXggPSBjYXBDb250cm9sUG9pbnQocG9pbnQuY3AxeCwgYXJlYS5sZWZ0LCBhcmVhLnJpZ2h0KTtcbiAgICAgIHBvaW50LmNwMXkgPSBjYXBDb250cm9sUG9pbnQocG9pbnQuY3AxeSwgYXJlYS50b3AsIGFyZWEuYm90dG9tKTtcbiAgICB9XG4gICAgaWYgKGluQXJlYU5leHQpIHtcbiAgICAgIHBvaW50LmNwMnggPSBjYXBDb250cm9sUG9pbnQocG9pbnQuY3AyeCwgYXJlYS5sZWZ0LCBhcmVhLnJpZ2h0KTtcbiAgICAgIHBvaW50LmNwMnkgPSBjYXBDb250cm9sUG9pbnQocG9pbnQuY3AyeSwgYXJlYS50b3AsIGFyZWEuYm90dG9tKTtcbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uIF91cGRhdGVCZXppZXJDb250cm9sUG9pbnRzKHBvaW50cywgb3B0aW9ucywgYXJlYSwgbG9vcCwgaW5kZXhBeGlzKSB7XG4gIGxldCBpLCBpbGVuLCBwb2ludCwgY29udHJvbFBvaW50cztcbiAgaWYgKG9wdGlvbnMuc3BhbkdhcHMpIHtcbiAgICBwb2ludHMgPSBwb2ludHMuZmlsdGVyKChwdCkgPT4gIXB0LnNraXApO1xuICB9XG4gIGlmIChvcHRpb25zLmN1YmljSW50ZXJwb2xhdGlvbk1vZGUgPT09ICdtb25vdG9uZScpIHtcbiAgICBzcGxpbmVDdXJ2ZU1vbm90b25lKHBvaW50cywgaW5kZXhBeGlzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgcHJldiA9IGxvb3AgPyBwb2ludHNbcG9pbnRzLmxlbmd0aCAtIDFdIDogcG9pbnRzWzBdO1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKSB7XG4gICAgICBwb2ludCA9IHBvaW50c1tpXTtcbiAgICAgIGNvbnRyb2xQb2ludHMgPSBzcGxpbmVDdXJ2ZShcbiAgICAgICAgcHJldixcbiAgICAgICAgcG9pbnQsXG4gICAgICAgIHBvaW50c1tNYXRoLm1pbihpICsgMSwgaWxlbiAtIChsb29wID8gMCA6IDEpKSAlIGlsZW5dLFxuICAgICAgICBvcHRpb25zLnRlbnNpb25cbiAgICAgICk7XG4gICAgICBwb2ludC5jcDF4ID0gY29udHJvbFBvaW50cy5wcmV2aW91cy54O1xuICAgICAgcG9pbnQuY3AxeSA9IGNvbnRyb2xQb2ludHMucHJldmlvdXMueTtcbiAgICAgIHBvaW50LmNwMnggPSBjb250cm9sUG9pbnRzLm5leHQueDtcbiAgICAgIHBvaW50LmNwMnkgPSBjb250cm9sUG9pbnRzLm5leHQueTtcbiAgICAgIHByZXYgPSBwb2ludDtcbiAgICB9XG4gIH1cbiAgaWYgKG9wdGlvbnMuY2FwQmV6aWVyUG9pbnRzKSB7XG4gICAgY2FwQmV6aWVyUG9pbnRzKHBvaW50cywgYXJlYSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX2lzRG9tU3VwcG9ydGVkKCkge1xuICByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJztcbn1cbmZ1bmN0aW9uIF9nZXRQYXJlbnROb2RlKGRvbU5vZGUpIHtcbiAgbGV0IHBhcmVudCA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgaWYgKHBhcmVudCAmJiBwYXJlbnQudG9TdHJpbmcoKSA9PT0gJ1tvYmplY3QgU2hhZG93Um9vdF0nKSB7XG4gICAgcGFyZW50ID0gcGFyZW50Lmhvc3Q7XG4gIH1cbiAgcmV0dXJuIHBhcmVudDtcbn1cbmZ1bmN0aW9uIHBhcnNlTWF4U3R5bGUoc3R5bGVWYWx1ZSwgbm9kZSwgcGFyZW50UHJvcGVydHkpIHtcbiAgbGV0IHZhbHVlSW5QaXhlbHM7XG4gIGlmICh0eXBlb2Ygc3R5bGVWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICB2YWx1ZUluUGl4ZWxzID0gcGFyc2VJbnQoc3R5bGVWYWx1ZSwgMTApO1xuICAgIGlmIChzdHlsZVZhbHVlLmluZGV4T2YoJyUnKSAhPT0gLTEpIHtcbiAgICAgIHZhbHVlSW5QaXhlbHMgPSB2YWx1ZUluUGl4ZWxzIC8gMTAwICogbm9kZS5wYXJlbnROb2RlW3BhcmVudFByb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFsdWVJblBpeGVscyA9IHN0eWxlVmFsdWU7XG4gIH1cbiAgcmV0dXJuIHZhbHVlSW5QaXhlbHM7XG59XG5jb25zdCBnZXRDb21wdXRlZFN0eWxlID0gKGVsZW1lbnQpID0+IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQsIG51bGwpO1xuZnVuY3Rpb24gZ2V0U3R5bGUoZWwsIHByb3BlcnR5KSB7XG4gIHJldHVybiBnZXRDb21wdXRlZFN0eWxlKGVsKS5nZXRQcm9wZXJ0eVZhbHVlKHByb3BlcnR5KTtcbn1cbmNvbnN0IHBvc2l0aW9ucyA9IFsndG9wJywgJ3JpZ2h0JywgJ2JvdHRvbScsICdsZWZ0J107XG5mdW5jdGlvbiBnZXRQb3NpdGlvbmVkU3R5bGUoc3R5bGVzLCBzdHlsZSwgc3VmZml4KSB7XG4gIGNvbnN0IHJlc3VsdCA9IHt9O1xuICBzdWZmaXggPSBzdWZmaXggPyAnLScgKyBzdWZmaXggOiAnJztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICBjb25zdCBwb3MgPSBwb3NpdGlvbnNbaV07XG4gICAgcmVzdWx0W3Bvc10gPSBwYXJzZUZsb2F0KHN0eWxlc1tzdHlsZSArICctJyArIHBvcyArIHN1ZmZpeF0pIHx8IDA7XG4gIH1cbiAgcmVzdWx0LndpZHRoID0gcmVzdWx0LmxlZnQgKyByZXN1bHQucmlnaHQ7XG4gIHJlc3VsdC5oZWlnaHQgPSByZXN1bHQudG9wICsgcmVzdWx0LmJvdHRvbTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cbmNvbnN0IHVzZU9mZnNldFBvcyA9ICh4LCB5LCB0YXJnZXQpID0+ICh4ID4gMCB8fCB5ID4gMCkgJiYgKCF0YXJnZXQgfHwgIXRhcmdldC5zaGFkb3dSb290KTtcbmZ1bmN0aW9uIGdldENhbnZhc1Bvc2l0aW9uKGV2dCwgY2FudmFzKSB7XG4gIGNvbnN0IGUgPSBldnQubmF0aXZlIHx8IGV2dDtcbiAgY29uc3QgdG91Y2hlcyA9IGUudG91Y2hlcztcbiAgY29uc3Qgc291cmNlID0gdG91Y2hlcyAmJiB0b3VjaGVzLmxlbmd0aCA/IHRvdWNoZXNbMF0gOiBlO1xuICBjb25zdCB7b2Zmc2V0WCwgb2Zmc2V0WX0gPSBzb3VyY2U7XG4gIGxldCBib3ggPSBmYWxzZTtcbiAgbGV0IHgsIHk7XG4gIGlmICh1c2VPZmZzZXRQb3Mob2Zmc2V0WCwgb2Zmc2V0WSwgZS50YXJnZXQpKSB7XG4gICAgeCA9IG9mZnNldFg7XG4gICAgeSA9IG9mZnNldFk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgcmVjdCA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB4ID0gc291cmNlLmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgeSA9IHNvdXJjZS5jbGllbnRZIC0gcmVjdC50b3A7XG4gICAgYm94ID0gdHJ1ZTtcbiAgfVxuICByZXR1cm4ge3gsIHksIGJveH07XG59XG5mdW5jdGlvbiBnZXRSZWxhdGl2ZVBvc2l0aW9uKGV2dCwgY2hhcnQpIHtcbiAgY29uc3Qge2NhbnZhcywgY3VycmVudERldmljZVBpeGVsUmF0aW99ID0gY2hhcnQ7XG4gIGNvbnN0IHN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShjYW52YXMpO1xuICBjb25zdCBib3JkZXJCb3ggPSBzdHlsZS5ib3hTaXppbmcgPT09ICdib3JkZXItYm94JztcbiAgY29uc3QgcGFkZGluZ3MgPSBnZXRQb3NpdGlvbmVkU3R5bGUoc3R5bGUsICdwYWRkaW5nJyk7XG4gIGNvbnN0IGJvcmRlcnMgPSBnZXRQb3NpdGlvbmVkU3R5bGUoc3R5bGUsICdib3JkZXInLCAnd2lkdGgnKTtcbiAgY29uc3Qge3gsIHksIGJveH0gPSBnZXRDYW52YXNQb3NpdGlvbihldnQsIGNhbnZhcyk7XG4gIGNvbnN0IHhPZmZzZXQgPSBwYWRkaW5ncy5sZWZ0ICsgKGJveCAmJiBib3JkZXJzLmxlZnQpO1xuICBjb25zdCB5T2Zmc2V0ID0gcGFkZGluZ3MudG9wICsgKGJveCAmJiBib3JkZXJzLnRvcCk7XG4gIGxldCB7d2lkdGgsIGhlaWdodH0gPSBjaGFydDtcbiAgaWYgKGJvcmRlckJveCkge1xuICAgIHdpZHRoIC09IHBhZGRpbmdzLndpZHRoICsgYm9yZGVycy53aWR0aDtcbiAgICBoZWlnaHQgLT0gcGFkZGluZ3MuaGVpZ2h0ICsgYm9yZGVycy5oZWlnaHQ7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICB4OiBNYXRoLnJvdW5kKCh4IC0geE9mZnNldCkgLyB3aWR0aCAqIGNhbnZhcy53aWR0aCAvIGN1cnJlbnREZXZpY2VQaXhlbFJhdGlvKSxcbiAgICB5OiBNYXRoLnJvdW5kKCh5IC0geU9mZnNldCkgLyBoZWlnaHQgKiBjYW52YXMuaGVpZ2h0IC8gY3VycmVudERldmljZVBpeGVsUmF0aW8pXG4gIH07XG59XG5mdW5jdGlvbiBnZXRDb250YWluZXJTaXplKGNhbnZhcywgd2lkdGgsIGhlaWdodCkge1xuICBsZXQgbWF4V2lkdGgsIG1heEhlaWdodDtcbiAgaWYgKHdpZHRoID09PSB1bmRlZmluZWQgfHwgaGVpZ2h0ID09PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCBjb250YWluZXIgPSBfZ2V0UGFyZW50Tm9kZShjYW52YXMpO1xuICAgIGlmICghY29udGFpbmVyKSB7XG4gICAgICB3aWR0aCA9IGNhbnZhcy5jbGllbnRXaWR0aDtcbiAgICAgIGhlaWdodCA9IGNhbnZhcy5jbGllbnRIZWlnaHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBjb25zdCBjb250YWluZXJTdHlsZSA9IGdldENvbXB1dGVkU3R5bGUoY29udGFpbmVyKTtcbiAgICAgIGNvbnN0IGNvbnRhaW5lckJvcmRlciA9IGdldFBvc2l0aW9uZWRTdHlsZShjb250YWluZXJTdHlsZSwgJ2JvcmRlcicsICd3aWR0aCcpO1xuICAgICAgY29uc3QgY29udGFpbmVyUGFkZGluZyA9IGdldFBvc2l0aW9uZWRTdHlsZShjb250YWluZXJTdHlsZSwgJ3BhZGRpbmcnKTtcbiAgICAgIHdpZHRoID0gcmVjdC53aWR0aCAtIGNvbnRhaW5lclBhZGRpbmcud2lkdGggLSBjb250YWluZXJCb3JkZXIud2lkdGg7XG4gICAgICBoZWlnaHQgPSByZWN0LmhlaWdodCAtIGNvbnRhaW5lclBhZGRpbmcuaGVpZ2h0IC0gY29udGFpbmVyQm9yZGVyLmhlaWdodDtcbiAgICAgIG1heFdpZHRoID0gcGFyc2VNYXhTdHlsZShjb250YWluZXJTdHlsZS5tYXhXaWR0aCwgY29udGFpbmVyLCAnY2xpZW50V2lkdGgnKTtcbiAgICAgIG1heEhlaWdodCA9IHBhcnNlTWF4U3R5bGUoY29udGFpbmVyU3R5bGUubWF4SGVpZ2h0LCBjb250YWluZXIsICdjbGllbnRIZWlnaHQnKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICB3aWR0aCxcbiAgICBoZWlnaHQsXG4gICAgbWF4V2lkdGg6IG1heFdpZHRoIHx8IElORklOSVRZLFxuICAgIG1heEhlaWdodDogbWF4SGVpZ2h0IHx8IElORklOSVRZXG4gIH07XG59XG5jb25zdCByb3VuZDEgPSB2ID0+IE1hdGgucm91bmQodiAqIDEwKSAvIDEwO1xuZnVuY3Rpb24gZ2V0TWF4aW11bVNpemUoY2FudmFzLCBiYldpZHRoLCBiYkhlaWdodCwgYXNwZWN0UmF0aW8pIHtcbiAgY29uc3Qgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGNhbnZhcyk7XG4gIGNvbnN0IG1hcmdpbnMgPSBnZXRQb3NpdGlvbmVkU3R5bGUoc3R5bGUsICdtYXJnaW4nKTtcbiAgY29uc3QgbWF4V2lkdGggPSBwYXJzZU1heFN0eWxlKHN0eWxlLm1heFdpZHRoLCBjYW52YXMsICdjbGllbnRXaWR0aCcpIHx8IElORklOSVRZO1xuICBjb25zdCBtYXhIZWlnaHQgPSBwYXJzZU1heFN0eWxlKHN0eWxlLm1heEhlaWdodCwgY2FudmFzLCAnY2xpZW50SGVpZ2h0JykgfHwgSU5GSU5JVFk7XG4gIGNvbnN0IGNvbnRhaW5lclNpemUgPSBnZXRDb250YWluZXJTaXplKGNhbnZhcywgYmJXaWR0aCwgYmJIZWlnaHQpO1xuICBsZXQge3dpZHRoLCBoZWlnaHR9ID0gY29udGFpbmVyU2l6ZTtcbiAgaWYgKHN0eWxlLmJveFNpemluZyA9PT0gJ2NvbnRlbnQtYm94Jykge1xuICAgIGNvbnN0IGJvcmRlcnMgPSBnZXRQb3NpdGlvbmVkU3R5bGUoc3R5bGUsICdib3JkZXInLCAnd2lkdGgnKTtcbiAgICBjb25zdCBwYWRkaW5ncyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ3BhZGRpbmcnKTtcbiAgICB3aWR0aCAtPSBwYWRkaW5ncy53aWR0aCArIGJvcmRlcnMud2lkdGg7XG4gICAgaGVpZ2h0IC09IHBhZGRpbmdzLmhlaWdodCArIGJvcmRlcnMuaGVpZ2h0O1xuICB9XG4gIHdpZHRoID0gTWF0aC5tYXgoMCwgd2lkdGggLSBtYXJnaW5zLndpZHRoKTtcbiAgaGVpZ2h0ID0gTWF0aC5tYXgoMCwgYXNwZWN0UmF0aW8gPyBNYXRoLmZsb29yKHdpZHRoIC8gYXNwZWN0UmF0aW8pIDogaGVpZ2h0IC0gbWFyZ2lucy5oZWlnaHQpO1xuICB3aWR0aCA9IHJvdW5kMShNYXRoLm1pbih3aWR0aCwgbWF4V2lkdGgsIGNvbnRhaW5lclNpemUubWF4V2lkdGgpKTtcbiAgaGVpZ2h0ID0gcm91bmQxKE1hdGgubWluKGhlaWdodCwgbWF4SGVpZ2h0LCBjb250YWluZXJTaXplLm1heEhlaWdodCkpO1xuICBpZiAod2lkdGggJiYgIWhlaWdodCkge1xuICAgIGhlaWdodCA9IHJvdW5kMSh3aWR0aCAvIDIpO1xuICB9XG4gIHJldHVybiB7XG4gICAgd2lkdGgsXG4gICAgaGVpZ2h0XG4gIH07XG59XG5mdW5jdGlvbiByZXRpbmFTY2FsZShjaGFydCwgZm9yY2VSYXRpbywgZm9yY2VTdHlsZSkge1xuICBjb25zdCBwaXhlbFJhdGlvID0gZm9yY2VSYXRpbyB8fCAxO1xuICBjb25zdCBkZXZpY2VIZWlnaHQgPSBNYXRoLmZsb29yKGNoYXJ0LmhlaWdodCAqIHBpeGVsUmF0aW8pO1xuICBjb25zdCBkZXZpY2VXaWR0aCA9IE1hdGguZmxvb3IoY2hhcnQud2lkdGggKiBwaXhlbFJhdGlvKTtcbiAgY2hhcnQuaGVpZ2h0ID0gZGV2aWNlSGVpZ2h0IC8gcGl4ZWxSYXRpbztcbiAgY2hhcnQud2lkdGggPSBkZXZpY2VXaWR0aCAvIHBpeGVsUmF0aW87XG4gIGNvbnN0IGNhbnZhcyA9IGNoYXJ0LmNhbnZhcztcbiAgaWYgKGNhbnZhcy5zdHlsZSAmJiAoZm9yY2VTdHlsZSB8fCAoIWNhbnZhcy5zdHlsZS5oZWlnaHQgJiYgIWNhbnZhcy5zdHlsZS53aWR0aCkpKSB7XG4gICAgY2FudmFzLnN0eWxlLmhlaWdodCA9IGAke2NoYXJ0LmhlaWdodH1weGA7XG4gICAgY2FudmFzLnN0eWxlLndpZHRoID0gYCR7Y2hhcnQud2lkdGh9cHhgO1xuICB9XG4gIGlmIChjaGFydC5jdXJyZW50RGV2aWNlUGl4ZWxSYXRpbyAhPT0gcGl4ZWxSYXRpb1xuICAgICAgfHwgY2FudmFzLmhlaWdodCAhPT0gZGV2aWNlSGVpZ2h0XG4gICAgICB8fCBjYW52YXMud2lkdGggIT09IGRldmljZVdpZHRoKSB7XG4gICAgY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW8gPSBwaXhlbFJhdGlvO1xuICAgIGNhbnZhcy5oZWlnaHQgPSBkZXZpY2VIZWlnaHQ7XG4gICAgY2FudmFzLndpZHRoID0gZGV2aWNlV2lkdGg7XG4gICAgY2hhcnQuY3R4LnNldFRyYW5zZm9ybShwaXhlbFJhdGlvLCAwLCAwLCBwaXhlbFJhdGlvLCAwLCAwKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5jb25zdCBzdXBwb3J0c0V2ZW50TGlzdGVuZXJPcHRpb25zID0gKGZ1bmN0aW9uKCkge1xuICBsZXQgcGFzc2l2ZVN1cHBvcnRlZCA9IGZhbHNlO1xuICB0cnkge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICBnZXQgcGFzc2l2ZSgpIHtcbiAgICAgICAgcGFzc2l2ZVN1cHBvcnRlZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd0ZXN0JywgbnVsbCwgb3B0aW9ucyk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCBudWxsLCBvcHRpb25zKTtcbiAgfSBjYXRjaCAoZSkge1xuICB9XG4gIHJldHVybiBwYXNzaXZlU3VwcG9ydGVkO1xufSgpKTtcbmZ1bmN0aW9uIHJlYWRVc2VkU2l6ZShlbGVtZW50LCBwcm9wZXJ0eSkge1xuICBjb25zdCB2YWx1ZSA9IGdldFN0eWxlKGVsZW1lbnQsIHByb3BlcnR5KTtcbiAgY29uc3QgbWF0Y2hlcyA9IHZhbHVlICYmIHZhbHVlLm1hdGNoKC9eKFxcZCspKFxcLlxcZCspP3B4JC8pO1xuICByZXR1cm4gbWF0Y2hlcyA/ICttYXRjaGVzWzFdIDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBfcG9pbnRJbkxpbmUocDEsIHAyLCB0LCBtb2RlKSB7XG4gIHJldHVybiB7XG4gICAgeDogcDEueCArIHQgKiAocDIueCAtIHAxLngpLFxuICAgIHk6IHAxLnkgKyB0ICogKHAyLnkgLSBwMS55KVxuICB9O1xufVxuZnVuY3Rpb24gX3N0ZXBwZWRJbnRlcnBvbGF0aW9uKHAxLCBwMiwgdCwgbW9kZSkge1xuICByZXR1cm4ge1xuICAgIHg6IHAxLnggKyB0ICogKHAyLnggLSBwMS54KSxcbiAgICB5OiBtb2RlID09PSAnbWlkZGxlJyA/IHQgPCAwLjUgPyBwMS55IDogcDIueVxuICAgIDogbW9kZSA9PT0gJ2FmdGVyJyA/IHQgPCAxID8gcDEueSA6IHAyLnlcbiAgICA6IHQgPiAwID8gcDIueSA6IHAxLnlcbiAgfTtcbn1cbmZ1bmN0aW9uIF9iZXppZXJJbnRlcnBvbGF0aW9uKHAxLCBwMiwgdCwgbW9kZSkge1xuICBjb25zdCBjcDEgPSB7eDogcDEuY3AyeCwgeTogcDEuY3AyeX07XG4gIGNvbnN0IGNwMiA9IHt4OiBwMi5jcDF4LCB5OiBwMi5jcDF5fTtcbiAgY29uc3QgYSA9IF9wb2ludEluTGluZShwMSwgY3AxLCB0KTtcbiAgY29uc3QgYiA9IF9wb2ludEluTGluZShjcDEsIGNwMiwgdCk7XG4gIGNvbnN0IGMgPSBfcG9pbnRJbkxpbmUoY3AyLCBwMiwgdCk7XG4gIGNvbnN0IGQgPSBfcG9pbnRJbkxpbmUoYSwgYiwgdCk7XG4gIGNvbnN0IGUgPSBfcG9pbnRJbkxpbmUoYiwgYywgdCk7XG4gIHJldHVybiBfcG9pbnRJbkxpbmUoZCwgZSwgdCk7XG59XG5cbmNvbnN0IGludGxDYWNoZSA9IG5ldyBNYXAoKTtcbmZ1bmN0aW9uIGdldE51bWJlckZvcm1hdChsb2NhbGUsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGNvbnN0IGNhY2hlS2V5ID0gbG9jYWxlICsgSlNPTi5zdHJpbmdpZnkob3B0aW9ucyk7XG4gIGxldCBmb3JtYXR0ZXIgPSBpbnRsQ2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgaWYgKCFmb3JtYXR0ZXIpIHtcbiAgICBmb3JtYXR0ZXIgPSBuZXcgSW50bC5OdW1iZXJGb3JtYXQobG9jYWxlLCBvcHRpb25zKTtcbiAgICBpbnRsQ2FjaGUuc2V0KGNhY2hlS2V5LCBmb3JtYXR0ZXIpO1xuICB9XG4gIHJldHVybiBmb3JtYXR0ZXI7XG59XG5mdW5jdGlvbiBmb3JtYXROdW1iZXIobnVtLCBsb2NhbGUsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGdldE51bWJlckZvcm1hdChsb2NhbGUsIG9wdGlvbnMpLmZvcm1hdChudW0pO1xufVxuXG5jb25zdCBnZXRSaWdodFRvTGVmdEFkYXB0ZXIgPSBmdW5jdGlvbihyZWN0WCwgd2lkdGgpIHtcbiAgcmV0dXJuIHtcbiAgICB4KHgpIHtcbiAgICAgIHJldHVybiByZWN0WCArIHJlY3RYICsgd2lkdGggLSB4O1xuICAgIH0sXG4gICAgc2V0V2lkdGgodykge1xuICAgICAgd2lkdGggPSB3O1xuICAgIH0sXG4gICAgdGV4dEFsaWduKGFsaWduKSB7XG4gICAgICBpZiAoYWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgIHJldHVybiBhbGlnbjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhbGlnbiA9PT0gJ3JpZ2h0JyA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgfSxcbiAgICB4UGx1cyh4LCB2YWx1ZSkge1xuICAgICAgcmV0dXJuIHggLSB2YWx1ZTtcbiAgICB9LFxuICAgIGxlZnRGb3JMdHIoeCwgaXRlbVdpZHRoKSB7XG4gICAgICByZXR1cm4geCAtIGl0ZW1XaWR0aDtcbiAgICB9LFxuICB9O1xufTtcbmNvbnN0IGdldExlZnRUb1JpZ2h0QWRhcHRlciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4ge1xuICAgIHgoeCkge1xuICAgICAgcmV0dXJuIHg7XG4gICAgfSxcbiAgICBzZXRXaWR0aCh3KSB7XG4gICAgfSxcbiAgICB0ZXh0QWxpZ24oYWxpZ24pIHtcbiAgICAgIHJldHVybiBhbGlnbjtcbiAgICB9LFxuICAgIHhQbHVzKHgsIHZhbHVlKSB7XG4gICAgICByZXR1cm4geCArIHZhbHVlO1xuICAgIH0sXG4gICAgbGVmdEZvckx0cih4LCBfaXRlbVdpZHRoKSB7XG4gICAgICByZXR1cm4geDtcbiAgICB9LFxuICB9O1xufTtcbmZ1bmN0aW9uIGdldFJ0bEFkYXB0ZXIocnRsLCByZWN0WCwgd2lkdGgpIHtcbiAgcmV0dXJuIHJ0bCA/IGdldFJpZ2h0VG9MZWZ0QWRhcHRlcihyZWN0WCwgd2lkdGgpIDogZ2V0TGVmdFRvUmlnaHRBZGFwdGVyKCk7XG59XG5mdW5jdGlvbiBvdmVycmlkZVRleHREaXJlY3Rpb24oY3R4LCBkaXJlY3Rpb24pIHtcbiAgbGV0IHN0eWxlLCBvcmlnaW5hbDtcbiAgaWYgKGRpcmVjdGlvbiA9PT0gJ2x0cicgfHwgZGlyZWN0aW9uID09PSAncnRsJykge1xuICAgIHN0eWxlID0gY3R4LmNhbnZhcy5zdHlsZTtcbiAgICBvcmlnaW5hbCA9IFtcbiAgICAgIHN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2RpcmVjdGlvbicpLFxuICAgICAgc3R5bGUuZ2V0UHJvcGVydHlQcmlvcml0eSgnZGlyZWN0aW9uJyksXG4gICAgXTtcbiAgICBzdHlsZS5zZXRQcm9wZXJ0eSgnZGlyZWN0aW9uJywgZGlyZWN0aW9uLCAnaW1wb3J0YW50Jyk7XG4gICAgY3R4LnByZXZUZXh0RGlyZWN0aW9uID0gb3JpZ2luYWw7XG4gIH1cbn1cbmZ1bmN0aW9uIHJlc3RvcmVUZXh0RGlyZWN0aW9uKGN0eCwgb3JpZ2luYWwpIHtcbiAgaWYgKG9yaWdpbmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICBkZWxldGUgY3R4LnByZXZUZXh0RGlyZWN0aW9uO1xuICAgIGN0eC5jYW52YXMuc3R5bGUuc2V0UHJvcGVydHkoJ2RpcmVjdGlvbicsIG9yaWdpbmFsWzBdLCBvcmlnaW5hbFsxXSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcHJvcGVydHlGbihwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgPT09ICdhbmdsZScpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmV0d2VlbjogX2FuZ2xlQmV0d2VlbixcbiAgICAgIGNvbXBhcmU6IF9hbmdsZURpZmYsXG4gICAgICBub3JtYWxpemU6IF9ub3JtYWxpemVBbmdsZSxcbiAgICB9O1xuICB9XG4gIHJldHVybiB7XG4gICAgYmV0d2VlbjogKG4sIHMsIGUpID0+IG4gPj0gTWF0aC5taW4ocywgZSkgJiYgbiA8PSBNYXRoLm1heChlLCBzKSxcbiAgICBjb21wYXJlOiAoYSwgYikgPT4gYSAtIGIsXG4gICAgbm9ybWFsaXplOiB4ID0+IHhcbiAgfTtcbn1cbmZ1bmN0aW9uIG5vcm1hbGl6ZVNlZ21lbnQoe3N0YXJ0LCBlbmQsIGNvdW50LCBsb29wLCBzdHlsZX0pIHtcbiAgcmV0dXJuIHtcbiAgICBzdGFydDogc3RhcnQgJSBjb3VudCxcbiAgICBlbmQ6IGVuZCAlIGNvdW50LFxuICAgIGxvb3A6IGxvb3AgJiYgKGVuZCAtIHN0YXJ0ICsgMSkgJSBjb3VudCA9PT0gMCxcbiAgICBzdHlsZVxuICB9O1xufVxuZnVuY3Rpb24gZ2V0U2VnbWVudChzZWdtZW50LCBwb2ludHMsIGJvdW5kcykge1xuICBjb25zdCB7cHJvcGVydHksIHN0YXJ0OiBzdGFydEJvdW5kLCBlbmQ6IGVuZEJvdW5kfSA9IGJvdW5kcztcbiAgY29uc3Qge2JldHdlZW4sIG5vcm1hbGl6ZX0gPSBwcm9wZXJ0eUZuKHByb3BlcnR5KTtcbiAgY29uc3QgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICBsZXQge3N0YXJ0LCBlbmQsIGxvb3B9ID0gc2VnbWVudDtcbiAgbGV0IGksIGlsZW47XG4gIGlmIChsb29wKSB7XG4gICAgc3RhcnQgKz0gY291bnQ7XG4gICAgZW5kICs9IGNvdW50O1xuICAgIGZvciAoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSkge1xuICAgICAgaWYgKCFiZXR3ZWVuKG5vcm1hbGl6ZShwb2ludHNbc3RhcnQgJSBjb3VudF1bcHJvcGVydHldKSwgc3RhcnRCb3VuZCwgZW5kQm91bmQpKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgc3RhcnQtLTtcbiAgICAgIGVuZC0tO1xuICAgIH1cbiAgICBzdGFydCAlPSBjb3VudDtcbiAgICBlbmQgJT0gY291bnQ7XG4gIH1cbiAgaWYgKGVuZCA8IHN0YXJ0KSB7XG4gICAgZW5kICs9IGNvdW50O1xuICB9XG4gIHJldHVybiB7c3RhcnQsIGVuZCwgbG9vcCwgc3R5bGU6IHNlZ21lbnQuc3R5bGV9O1xufVxuZnVuY3Rpb24gX2JvdW5kU2VnbWVudChzZWdtZW50LCBwb2ludHMsIGJvdW5kcykge1xuICBpZiAoIWJvdW5kcykge1xuICAgIHJldHVybiBbc2VnbWVudF07XG4gIH1cbiAgY29uc3Qge3Byb3BlcnR5LCBzdGFydDogc3RhcnRCb3VuZCwgZW5kOiBlbmRCb3VuZH0gPSBib3VuZHM7XG4gIGNvbnN0IGNvdW50ID0gcG9pbnRzLmxlbmd0aDtcbiAgY29uc3Qge2NvbXBhcmUsIGJldHdlZW4sIG5vcm1hbGl6ZX0gPSBwcm9wZXJ0eUZuKHByb3BlcnR5KTtcbiAgY29uc3Qge3N0YXJ0LCBlbmQsIGxvb3AsIHN0eWxlfSA9IGdldFNlZ21lbnQoc2VnbWVudCwgcG9pbnRzLCBib3VuZHMpO1xuICBjb25zdCByZXN1bHQgPSBbXTtcbiAgbGV0IGluc2lkZSA9IGZhbHNlO1xuICBsZXQgc3ViU3RhcnQgPSBudWxsO1xuICBsZXQgdmFsdWUsIHBvaW50LCBwcmV2VmFsdWU7XG4gIGNvbnN0IHN0YXJ0SXNCZWZvcmUgPSAoKSA9PiBiZXR3ZWVuKHN0YXJ0Qm91bmQsIHByZXZWYWx1ZSwgdmFsdWUpICYmIGNvbXBhcmUoc3RhcnRCb3VuZCwgcHJldlZhbHVlKSAhPT0gMDtcbiAgY29uc3QgZW5kSXNCZWZvcmUgPSAoKSA9PiBjb21wYXJlKGVuZEJvdW5kLCB2YWx1ZSkgPT09IDAgfHwgYmV0d2VlbihlbmRCb3VuZCwgcHJldlZhbHVlLCB2YWx1ZSk7XG4gIGNvbnN0IHNob3VsZFN0YXJ0ID0gKCkgPT4gaW5zaWRlIHx8IHN0YXJ0SXNCZWZvcmUoKTtcbiAgY29uc3Qgc2hvdWxkU3RvcCA9ICgpID0+ICFpbnNpZGUgfHwgZW5kSXNCZWZvcmUoKTtcbiAgZm9yIChsZXQgaSA9IHN0YXJ0LCBwcmV2ID0gc3RhcnQ7IGkgPD0gZW5kOyArK2kpIHtcbiAgICBwb2ludCA9IHBvaW50c1tpICUgY291bnRdO1xuICAgIGlmIChwb2ludC5za2lwKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgdmFsdWUgPSBub3JtYWxpemUocG9pbnRbcHJvcGVydHldKTtcbiAgICBpZiAodmFsdWUgPT09IHByZXZWYWx1ZSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGluc2lkZSA9IGJldHdlZW4odmFsdWUsIHN0YXJ0Qm91bmQsIGVuZEJvdW5kKTtcbiAgICBpZiAoc3ViU3RhcnQgPT09IG51bGwgJiYgc2hvdWxkU3RhcnQoKSkge1xuICAgICAgc3ViU3RhcnQgPSBjb21wYXJlKHZhbHVlLCBzdGFydEJvdW5kKSA9PT0gMCA/IGkgOiBwcmV2O1xuICAgIH1cbiAgICBpZiAoc3ViU3RhcnQgIT09IG51bGwgJiYgc2hvdWxkU3RvcCgpKSB7XG4gICAgICByZXN1bHQucHVzaChub3JtYWxpemVTZWdtZW50KHtzdGFydDogc3ViU3RhcnQsIGVuZDogaSwgbG9vcCwgY291bnQsIHN0eWxlfSkpO1xuICAgICAgc3ViU3RhcnQgPSBudWxsO1xuICAgIH1cbiAgICBwcmV2ID0gaTtcbiAgICBwcmV2VmFsdWUgPSB2YWx1ZTtcbiAgfVxuICBpZiAoc3ViU3RhcnQgIT09IG51bGwpIHtcbiAgICByZXN1bHQucHVzaChub3JtYWxpemVTZWdtZW50KHtzdGFydDogc3ViU3RhcnQsIGVuZCwgbG9vcCwgY291bnQsIHN0eWxlfSkpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBfYm91bmRTZWdtZW50cyhsaW5lLCBib3VuZHMpIHtcbiAgY29uc3QgcmVzdWx0ID0gW107XG4gIGNvbnN0IHNlZ21lbnRzID0gbGluZS5zZWdtZW50cztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IHN1YiA9IF9ib3VuZFNlZ21lbnQoc2VnbWVudHNbaV0sIGxpbmUucG9pbnRzLCBib3VuZHMpO1xuICAgIGlmIChzdWIubGVuZ3RoKSB7XG4gICAgICByZXN1bHQucHVzaCguLi5zdWIpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gZmluZFN0YXJ0QW5kRW5kKHBvaW50cywgY291bnQsIGxvb3AsIHNwYW5HYXBzKSB7XG4gIGxldCBzdGFydCA9IDA7XG4gIGxldCBlbmQgPSBjb3VudCAtIDE7XG4gIGlmIChsb29wICYmICFzcGFuR2Fwcykge1xuICAgIHdoaWxlIChzdGFydCA8IGNvdW50ICYmICFwb2ludHNbc3RhcnRdLnNraXApIHtcbiAgICAgIHN0YXJ0Kys7XG4gICAgfVxuICB9XG4gIHdoaWxlIChzdGFydCA8IGNvdW50ICYmIHBvaW50c1tzdGFydF0uc2tpcCkge1xuICAgIHN0YXJ0Kys7XG4gIH1cbiAgc3RhcnQgJT0gY291bnQ7XG4gIGlmIChsb29wKSB7XG4gICAgZW5kICs9IHN0YXJ0O1xuICB9XG4gIHdoaWxlIChlbmQgPiBzdGFydCAmJiBwb2ludHNbZW5kICUgY291bnRdLnNraXApIHtcbiAgICBlbmQtLTtcbiAgfVxuICBlbmQgJT0gY291bnQ7XG4gIHJldHVybiB7c3RhcnQsIGVuZH07XG59XG5mdW5jdGlvbiBzb2xpZFNlZ21lbnRzKHBvaW50cywgc3RhcnQsIG1heCwgbG9vcCkge1xuICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gIGNvbnN0IHJlc3VsdCA9IFtdO1xuICBsZXQgbGFzdCA9IHN0YXJ0O1xuICBsZXQgcHJldiA9IHBvaW50c1tzdGFydF07XG4gIGxldCBlbmQ7XG4gIGZvciAoZW5kID0gc3RhcnQgKyAxOyBlbmQgPD0gbWF4OyArK2VuZCkge1xuICAgIGNvbnN0IGN1ciA9IHBvaW50c1tlbmQgJSBjb3VudF07XG4gICAgaWYgKGN1ci5za2lwIHx8IGN1ci5zdG9wKSB7XG4gICAgICBpZiAoIXByZXYuc2tpcCkge1xuICAgICAgICBsb29wID0gZmFsc2U7XG4gICAgICAgIHJlc3VsdC5wdXNoKHtzdGFydDogc3RhcnQgJSBjb3VudCwgZW5kOiAoZW5kIC0gMSkgJSBjb3VudCwgbG9vcH0pO1xuICAgICAgICBzdGFydCA9IGxhc3QgPSBjdXIuc3RvcCA/IGVuZCA6IG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxhc3QgPSBlbmQ7XG4gICAgICBpZiAocHJldi5za2lwKSB7XG4gICAgICAgIHN0YXJ0ID0gZW5kO1xuICAgICAgfVxuICAgIH1cbiAgICBwcmV2ID0gY3VyO1xuICB9XG4gIGlmIChsYXN0ICE9PSBudWxsKSB7XG4gICAgcmVzdWx0LnB1c2goe3N0YXJ0OiBzdGFydCAlIGNvdW50LCBlbmQ6IGxhc3QgJSBjb3VudCwgbG9vcH0pO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBfY29tcHV0ZVNlZ21lbnRzKGxpbmUsIHNlZ21lbnRPcHRpb25zKSB7XG4gIGNvbnN0IHBvaW50cyA9IGxpbmUucG9pbnRzO1xuICBjb25zdCBzcGFuR2FwcyA9IGxpbmUub3B0aW9ucy5zcGFuR2FwcztcbiAgY29uc3QgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICBpZiAoIWNvdW50KSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGNvbnN0IGxvb3AgPSAhIWxpbmUuX2xvb3A7XG4gIGNvbnN0IHtzdGFydCwgZW5kfSA9IGZpbmRTdGFydEFuZEVuZChwb2ludHMsIGNvdW50LCBsb29wLCBzcGFuR2Fwcyk7XG4gIGlmIChzcGFuR2FwcyA9PT0gdHJ1ZSkge1xuICAgIHJldHVybiBzcGxpdEJ5U3R5bGVzKGxpbmUsIFt7c3RhcnQsIGVuZCwgbG9vcH1dLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKTtcbiAgfVxuICBjb25zdCBtYXggPSBlbmQgPCBzdGFydCA/IGVuZCArIGNvdW50IDogZW5kO1xuICBjb25zdCBjb21wbGV0ZUxvb3AgPSAhIWxpbmUuX2Z1bGxMb29wICYmIHN0YXJ0ID09PSAwICYmIGVuZCA9PT0gY291bnQgLSAxO1xuICByZXR1cm4gc3BsaXRCeVN0eWxlcyhsaW5lLCBzb2xpZFNlZ21lbnRzKHBvaW50cywgc3RhcnQsIG1heCwgY29tcGxldGVMb29wKSwgcG9pbnRzLCBzZWdtZW50T3B0aW9ucyk7XG59XG5mdW5jdGlvbiBzcGxpdEJ5U3R5bGVzKGxpbmUsIHNlZ21lbnRzLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKSB7XG4gIGlmICghc2VnbWVudE9wdGlvbnMgfHwgIXNlZ21lbnRPcHRpb25zLnNldENvbnRleHQgfHwgIXBvaW50cykge1xuICAgIHJldHVybiBzZWdtZW50cztcbiAgfVxuICByZXR1cm4gZG9TcGxpdEJ5U3R5bGVzKGxpbmUsIHNlZ21lbnRzLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKTtcbn1cbmZ1bmN0aW9uIGRvU3BsaXRCeVN0eWxlcyhsaW5lLCBzZWdtZW50cywgcG9pbnRzLCBzZWdtZW50T3B0aW9ucykge1xuICBjb25zdCBiYXNlU3R5bGUgPSByZWFkU3R5bGUobGluZS5vcHRpb25zKTtcbiAgY29uc3QgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICBjb25zdCByZXN1bHQgPSBbXTtcbiAgbGV0IHN0YXJ0ID0gc2VnbWVudHNbMF0uc3RhcnQ7XG4gIGxldCBpID0gc3RhcnQ7XG4gIGZvciAoY29uc3Qgc2VnbWVudCBvZiBzZWdtZW50cykge1xuICAgIGxldCBwcmV2U3R5bGUgPSBiYXNlU3R5bGU7XG4gICAgbGV0IHByZXYgPSBwb2ludHNbc3RhcnQgJSBjb3VudF07XG4gICAgbGV0IHN0eWxlO1xuICAgIGZvciAoaSA9IHN0YXJ0ICsgMTsgaSA8PSBzZWdtZW50LmVuZDsgaSsrKSB7XG4gICAgICBjb25zdCBwdCA9IHBvaW50c1tpICUgY291bnRdO1xuICAgICAgc3R5bGUgPSByZWFkU3R5bGUoc2VnbWVudE9wdGlvbnMuc2V0Q29udGV4dCh7XG4gICAgICAgIHR5cGU6ICdzZWdtZW50JyxcbiAgICAgICAgcDA6IHByZXYsXG4gICAgICAgIHAxOiBwdCxcbiAgICAgICAgcDBEYXRhSW5kZXg6IChpIC0gMSkgJSBjb3VudCxcbiAgICAgICAgcDFEYXRhSW5kZXg6IGkgJSBjb3VudCxcbiAgICAgICAgZGF0YXNldEluZGV4OiBsaW5lLl9kYXRhc2V0SW5kZXhcbiAgICAgIH0pKTtcbiAgICAgIGlmIChzdHlsZUNoYW5nZWQoc3R5bGUsIHByZXZTdHlsZSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goe3N0YXJ0OiBzdGFydCwgZW5kOiBpIC0gMSwgbG9vcDogc2VnbWVudC5sb29wLCBzdHlsZTogcHJldlN0eWxlfSk7XG4gICAgICAgIHByZXZTdHlsZSA9IHN0eWxlO1xuICAgICAgICBzdGFydCA9IGkgLSAxO1xuICAgICAgfVxuICAgICAgcHJldiA9IHB0O1xuICAgICAgcHJldlN0eWxlID0gc3R5bGU7XG4gICAgfVxuICAgIGlmIChzdGFydCA8IGkgLSAxKSB7XG4gICAgICByZXN1bHQucHVzaCh7c3RhcnQsIGVuZDogaSAtIDEsIGxvb3A6IHNlZ21lbnQubG9vcCwgc3R5bGV9KTtcbiAgICAgIHN0YXJ0ID0gaSAtIDE7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiByZWFkU3R5bGUob3B0aW9ucykge1xuICByZXR1cm4ge1xuICAgIGJhY2tncm91bmRDb2xvcjogb3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgYm9yZGVyQ2FwU3R5bGU6IG9wdGlvbnMuYm9yZGVyQ2FwU3R5bGUsXG4gICAgYm9yZGVyRGFzaDogb3B0aW9ucy5ib3JkZXJEYXNoLFxuICAgIGJvcmRlckRhc2hPZmZzZXQ6IG9wdGlvbnMuYm9yZGVyRGFzaE9mZnNldCxcbiAgICBib3JkZXJKb2luU3R5bGU6IG9wdGlvbnMuYm9yZGVySm9pblN0eWxlLFxuICAgIGJvcmRlcldpZHRoOiBvcHRpb25zLmJvcmRlcldpZHRoLFxuICAgIGJvcmRlckNvbG9yOiBvcHRpb25zLmJvcmRlckNvbG9yXG4gIH07XG59XG5mdW5jdGlvbiBzdHlsZUNoYW5nZWQoc3R5bGUsIHByZXZTdHlsZSkge1xuICByZXR1cm4gcHJldlN0eWxlICYmIEpTT04uc3RyaW5naWZ5KHN0eWxlKSAhPT0gSlNPTi5zdHJpbmdpZnkocHJldlN0eWxlKTtcbn1cblxuZXhwb3J0IHsgb3ZlcnJpZGVzIGFzICQsIHRvUGFkZGluZyBhcyBBLCBlYWNoIGFzIEIsIGdldE1heGltdW1TaXplIGFzIEMsIF9nZXRQYXJlbnROb2RlIGFzIEQsIHJlYWRVc2VkU2l6ZSBhcyBFLCB0aHJvdHRsZWQgYXMgRiwgc3VwcG9ydHNFdmVudExpc3RlbmVyT3B0aW9ucyBhcyBHLCBIQUxGX1BJIGFzIEgsIF9pc0RvbVN1cHBvcnRlZCBhcyBJLCBsb2cxMCBhcyBKLCBfZmFjdG9yaXplIGFzIEssIGZpbml0ZU9yRGVmYXVsdCBhcyBMLCBjYWxsYmFjayBhcyBNLCBfYWRkR3JhY2UgYXMgTiwgdG9EZWdyZWVzIGFzIE8sIFBJIGFzIFAsIF9tZWFzdXJlVGV4dCBhcyBRLCBfaW50MTZSYW5nZSBhcyBSLCBfYWxpZ25QaXhlbCBhcyBTLCBUQVUgYXMgVCwgY2xpcEFyZWEgYXMgVSwgcmVuZGVyVGV4dCBhcyBWLCB1bmNsaXBBcmVhIGFzIFcsIHRvRm9udCBhcyBYLCBfdG9MZWZ0UmlnaHRDZW50ZXIgYXMgWSwgX2FsaWduU3RhcnRFbmQgYXMgWiwgX2FycmF5VW5pcXVlIGFzIF8sIHJlc29sdmUgYXMgYSwgbWVyZ2UgYXMgYTAsIF9jYXBpdGFsaXplIGFzIGExLCBkZXNjcmlwdG9ycyBhcyBhMiwgaXNGdW5jdGlvbiBhcyBhMywgX2F0dGFjaENvbnRleHQgYXMgYTQsIF9jcmVhdGVSZXNvbHZlciBhcyBhNSwgX2Rlc2NyaXB0b3JzIGFzIGE2LCBtZXJnZUlmIGFzIGE3LCB1aWQgYXMgYTgsIGRlYm91bmNlIGFzIGE5LCBfc2V0TWluQW5kTWF4QnlLZXkgYXMgYUEsIG5pY2VOdW0gYXMgYUIsIGFsbW9zdFdob2xlIGFzIGFDLCBhbG1vc3RFcXVhbHMgYXMgYUQsIF9kZWNpbWFsUGxhY2VzIGFzIGFFLCBfbG9uZ2VzdFRleHQgYXMgYUYsIF9maWx0ZXJCZXR3ZWVuIGFzIGFHLCBfbG9va3VwIGFzIGFILCBnZXRIb3ZlckNvbG9yIGFzIGFJLCBjbG9uZSQxIGFzIGFKLCBfbWVyZ2VyIGFzIGFLLCBfbWVyZ2VySWYgYXMgYUwsIF9kZXByZWNhdGVkIGFzIGFNLCB0b0ZvbnRTdHJpbmcgYXMgYU4sIHNwbGluZUN1cnZlIGFzIGFPLCBzcGxpbmVDdXJ2ZU1vbm90b25lIGFzIGFQLCBnZXRTdHlsZSBhcyBhUSwgZm9udFN0cmluZyBhcyBhUiwgdG9MaW5lSGVpZ2h0IGFzIGFTLCBQSVRBVSBhcyBhVCwgSU5GSU5JVFkgYXMgYVUsIFJBRF9QRVJfREVHIGFzIGFWLCBRVUFSVEVSX1BJIGFzIGFXLCBUV09fVEhJUkRTX1BJIGFzIGFYLCBfYW5nbGVEaWZmIGFzIGFZLCByZXRpbmFTY2FsZSBhcyBhYSwgY2xlYXJDYW52YXMgYXMgYWIsIHNldHNFcXVhbCBhcyBhYywgX2VsZW1lbnRzRXF1YWwgYXMgYWQsIGdldEFuZ2xlRnJvbVBvaW50IGFzIGFlLCBfcmVhZFZhbHVlVG9Qcm9wcyBhcyBhZiwgX3VwZGF0ZUJlemllckNvbnRyb2xQb2ludHMgYXMgYWcsIF9jb21wdXRlU2VnbWVudHMgYXMgYWgsIF9ib3VuZFNlZ21lbnRzIGFzIGFpLCBfc3RlcHBlZEludGVycG9sYXRpb24gYXMgYWosIF9iZXppZXJJbnRlcnBvbGF0aW9uIGFzIGFrLCBfcG9pbnRJbkxpbmUgYXMgYWwsIF9zdGVwcGVkTGluZVRvIGFzIGFtLCBfYmV6aWVyQ3VydmVUbyBhcyBhbiwgZHJhd1BvaW50IGFzIGFvLCBhZGRSb3VuZGVkUmVjdFBhdGggYXMgYXAsIHRvVFJCTCBhcyBhcSwgdG9UUkJMQ29ybmVycyBhcyBhciwgX2JvdW5kU2VnbWVudCBhcyBhcywgX25vcm1hbGl6ZUFuZ2xlIGFzIGF0LCBnZXRSdGxBZGFwdGVyIGFzIGF1LCBvdmVycmlkZVRleHREaXJlY3Rpb24gYXMgYXYsIF90ZXh0WCBhcyBhdywgcmVzdG9yZVRleHREaXJlY3Rpb24gYXMgYXgsIG5vb3AgYXMgYXksIGRpc3RhbmNlQmV0d2VlblBvaW50cyBhcyBheiwgaXNBcnJheSBhcyBiLCBjb2xvciBhcyBjLCBkZWZhdWx0cyBhcyBkLCBlZmZlY3RzIGFzIGUsIHJlc29sdmVPYmplY3RLZXkgYXMgZiwgaXNOdW1iZXJGaW5pdGUgYXMgZywgZGVmaW5lZCBhcyBoLCBpc09iamVjdCBhcyBpLCBpc051bGxPclVuZGVmIGFzIGosIHRvUGVyY2VudGFnZSBhcyBrLCBsaXN0ZW5BcnJheUV2ZW50cyBhcyBsLCB0b0RpbWVuc2lvbiBhcyBtLCBmb3JtYXROdW1iZXIgYXMgbiwgX2FuZ2xlQmV0d2VlbiBhcyBvLCBpc051bWJlciBhcyBwLCBfbGltaXRWYWx1ZSBhcyBxLCByZXF1ZXN0QW5pbUZyYW1lIGFzIHIsIHNpZ24gYXMgcywgdG9SYWRpYW5zIGFzIHQsIHVubGlzdGVuQXJyYXlFdmVudHMgYXMgdSwgdmFsdWVPckRlZmF1bHQgYXMgdiwgX2xvb2t1cEJ5S2V5IGFzIHcsIGdldFJlbGF0aXZlUG9zaXRpb24gYXMgeCwgX2lzUG9pbnRJbkFyZWEgYXMgeSwgX3Jsb29rdXBCeUtleSBhcyB6IH07XG4iLCJleHBvcnQgY29uc3QgZHJhd1lMaW5lID0gY2hhcnQgPT4ge1xuICAgIGlmIChjaGFydC50b29sdGlwLl9hY3RpdmUgJiYgY2hhcnQudG9vbHRpcC5fYWN0aXZlLmxlbmd0aCkge1xuICAgICAgICBjb25zdCBhY3RpdmVQb2ludCA9IGNoYXJ0LnRvb2x0aXAuX2FjdGl2ZVswXVxuICAgICAgICBjb25zdCBjdHggPSBjaGFydC5jdHhcbiAgICAgICAgY29uc3QgeSA9IGFjdGl2ZVBvaW50LmVsZW1lbnQueVxuICAgICAgICBjb25zdCBsZWZ0WCA9IGNoYXJ0LnNjYWxlcy54LmxlZnRcbiAgICAgICAgY29uc3QgcmlnaHRYID0gY2hhcnQuc2NhbGVzLngucmlnaHRcbiAgICAgICAgY29uc3QgY29sb3IgPSBhY3RpdmVQb2ludC5lbGVtZW50Lm9wdGlvbnMuYm9yZGVyQ29sb3JcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjaGFydC50b29sdGlwLmRhdGFQb2ludHNbMF0/LmZvcm1hdHRlZFZhbHVlXG5cbiAgICAgICAgY3R4LnNhdmUoKVxuICAgICAgICBjdHguYmVnaW5QYXRoKClcbiAgICAgICAgY3R4Lm1vdmVUbyhsZWZ0WCwgeSlcbiAgICAgICAgY3R4LmxpbmVUbyhyaWdodFgsIHkpXG4gICAgICAgIGN0eC5saW5lV2lkdGggPSAxXG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGNvbG9yXG4gICAgICAgIGN0eC5zZXRMaW5lRGFzaChbNCwgNF0pXG4gICAgICAgIGN0eC5zdHJva2UoKVxuICAgICAgICBjdHgucmVzdG9yZSgpXG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSBjb2xvclxuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBjb2xvclxuXG4gICAgICAgIGN0eC5mb250ID0gJzIwcHgnXG4gICAgICAgIGNvbnN0IHRleHRXaWR0aCA9IGN0eC5tZWFzdXJlVGV4dCh2YWx1ZSkud2lkdGhcbiAgICAgICAgY29uc3QgcmlnaHRTcGFjZSA9IGN0eC5jYW52YXMub2Zmc2V0V2lkdGggLSByaWdodFhcbiAgICAgICAgY29uc3QgbGVmdCA9IHJpZ2h0WCAtIE1hdGgubWF4KDAsIHRleHRXaWR0aCArIDEwIC0gcmlnaHRTcGFjZSlcbiAgICAgICAgcm91bmRSZWN0KGN0eCwgbGVmdCwgeSAtIDEwLCB0ZXh0V2lkdGggKyAxMCwgMjAsIDUsIHRydWUpXG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSAnd2hpdGUnXG4gICAgICAgIGN0eC5maWxsVGV4dCh2YWx1ZSwgbGVmdCArIDUsIHkgKyAzKVxuICAgIH1cbn1cblxuZnVuY3Rpb24gcm91bmRSZWN0KGN0eCwgeCwgeSwgd2lkdGgsIGhlaWdodCwgcmFkaXVzLCBmaWxsLCBzdHJva2UpIHtcbiAgICBpZiAodHlwZW9mIHN0cm9rZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgc3Ryb2tlID0gdHJ1ZVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHJhZGl1cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmFkaXVzID0gNVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHJhZGl1cyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgcmFkaXVzID0geyB0bDogcmFkaXVzLCB0cjogcmFkaXVzLCBicjogcmFkaXVzLCBibDogcmFkaXVzIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBkZWZhdWx0UmFkaXVzID0geyB0bDogMCwgdHI6IDAsIGJyOiAwLCBibDogMCB9XG4gICAgICAgIGZvciAobGV0IHNpZGUgaW4gZGVmYXVsdFJhZGl1cykge1xuICAgICAgICAgICAgcmFkaXVzW3NpZGVdID0gcmFkaXVzW3NpZGVdIHx8IGRlZmF1bHRSYWRpdXNbc2lkZV1cbiAgICAgICAgfVxuICAgIH1cbiAgICBjdHguYmVnaW5QYXRoKClcbiAgICBjdHgubW92ZVRvKHggKyByYWRpdXMudGwsIHkpXG4gICAgY3R4LmxpbmVUbyh4ICsgd2lkdGggLSByYWRpdXMudHIsIHkpXG4gICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCArIHdpZHRoLCB5LCB4ICsgd2lkdGgsIHkgKyByYWRpdXMudHIpXG4gICAgY3R4LmxpbmVUbyh4ICsgd2lkdGgsIHkgKyBoZWlnaHQgLSByYWRpdXMuYnIpXG4gICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCArIHdpZHRoLCB5ICsgaGVpZ2h0LCB4ICsgd2lkdGggLSByYWRpdXMuYnIsIHkgKyBoZWlnaHQpXG4gICAgY3R4LmxpbmVUbyh4ICsgcmFkaXVzLmJsLCB5ICsgaGVpZ2h0KVxuICAgIGN0eC5xdWFkcmF0aWNDdXJ2ZVRvKHgsIHkgKyBoZWlnaHQsIHgsIHkgKyBoZWlnaHQgLSByYWRpdXMuYmwpXG4gICAgY3R4LmxpbmVUbyh4LCB5ICsgcmFkaXVzLnRsKVxuICAgIGN0eC5xdWFkcmF0aWNDdXJ2ZVRvKHgsIHksIHggKyByYWRpdXMudGwsIHkpXG4gICAgY3R4LmNsb3NlUGF0aCgpXG4gICAgaWYgKGZpbGwpIHtcbiAgICAgICAgY3R4LmZpbGwoKVxuICAgIH1cbiAgICBpZiAoc3Ryb2tlKSB7XG4gICAgICAgIGN0eC5zdHJva2UoKVxuICAgIH1cbn1cbiIsIlxuY29uc3QgVU5LTk9XTl9FUlJPUiA9IHtcbiAgICByZXNwb25zZVN0YXR1czogNTIwLFxuICAgIHJlc3BvbnNlTWVzc2FnZTogJ1dlYiBTZXJ2ZXIgUmV0dXJuZWQgYW4gVW5rbm93biBFcnJvcicsXG4gICAgZXJyb3JNZXNzYWdlOiAnV2ViIFNlcnZlciBSZXR1cm5lZCBhbiBVbmtub3duIEVycm9yJ1xufVxuXG5jb25zdCBDT05URU5UX1RZUEVfSEVBREVSID0gJ2NvbnRlbnQtdHlwZSdcblxuY29uc3QgQVBQTElDQVRJT05fSlNPTiA9ICdhcHBsaWNhdGlvbi9qc29uJ1xuY29uc3QgVEVYVF9IVE1MID0gJ3RleHQvaHRtbCdcblxuZXhwb3J0IGNvbnN0IFJFUVVFU1RfTUVUSE9EUyA9IE9iamVjdC5mcmVlemUoe1xuICAgIEdFVDogJ0dFVCdcbn0pXG5cbmNvbnN0IGNvbW1vbkhlYWRlcnMgPSB7XG4gICAgW0NPTlRFTlRfVFlQRV9IRUFERVJdOiBBUFBMSUNBVElPTl9KU09OXG59XG5cbi8qKlxuICogQ2hlY2sgb24gaHRtbCByZXNwb25zZSBib2R5XG4gKiBcbiAqIEBwYXJhbSB7Kn0gaGVhZGVycyBcbiAqIEByZXR1cm5zIFxuICovXG5jb25zdCBpc0hlYWRlckNvbnRhaW5IdG1sID0gaGVhZGVycyA9PiB7XG4gICAgaWYgKCFoZWFkZXJzKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICByZXR1cm4gaGVhZGVycy5nZXQoQ09OVEVOVF9UWVBFX0hFQURFUik/LmluZGV4T2YoVEVYVF9IVE1MKSA+IC0xIHx8IGZhbHNlXG59XG5cbi8qKlxuICogUmVxdWVzdCBjbGllbnRcbiAqIFxuICogQHBhcmFtIHsqfSB1cmwgXG4gKiBAcGFyYW0geyp9IGJvZHkgXG4gKiBAcGFyYW0geyp9IG1ldGhvZCBcbiAqIEBwYXJhbSB7Kn0gaGVhZGVyIFxuICogQHJldHVybnMgXG4gKi9cbmV4cG9ydCBjb25zdCByZXF1ZXN0ID0gYXN5bmMgKHtcbiAgICBob3N0LFxuICAgIGhlYWRlcnMsXG4gICAgdXJsLFxuICAgIG1ldGhvZCxcbiAgICBib2R5XG59KSA9PiB7XG4gICAgY29uc3QgcmVxdWVzdFVybCA9IGAke2hvc3R9LyR7dXJsfWBcblxuICAgIGNvbnN0IHJlcXVlc3RQYXJhbXMgPSB7XG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgLi4uY29tbW9uSGVhZGVycyxcbiAgICAgICAgICAgIC4uLmhlYWRlcnNcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoYm9keSkge1xuICAgICAgICByZXF1ZXN0UGFyYW1zLmJvZHkgPSBKU09OLnN0cmluZ2lmeShib2R5KVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2gocmVxdWVzdFVybCwgcmVxdWVzdFBhcmFtcylcbiAgICAgICAgLnRoZW4oYXN5bmMgKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpc0pzb24gPSByZXNwb25zZS5oZWFkZXJzLmdldChDT05URU5UX1RZUEVfSEVBREVSKT8uaW5jbHVkZXMoQVBQTElDQVRJT05fSlNPTilcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVN0YXR1czogMjAwLFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiBpc0pzb24gPyBhd2FpdCByZXNwb25zZS5qc29uKCkgOiBudWxsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaXNIZWFkZXJDb250YWluSHRtbChyZXNwb25zZS5oZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChVTktOT1dOX0VSUk9SKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3Qoe1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlU3RhdHVzOiA1MDAsXG4gICAgICAgICAgICAgICAgZGF0YTogYXdhaXQgcmVzcG9uc2UudGV4dCgpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9KVxuICAgICAgICAudGhlbigoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhdHVzID0gZGF0YS5yZXNwb25zZVN0YXR1c1xuICAgICAgICAgICAgaWYgKHN0YXR1cyA+PSAyMDAgJiYgc3RhdHVzIDwgMzAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoVU5LTk9XTl9FUlJPUilcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcilcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChVTktOT1dOX0VSUk9SKVxuICAgICAgICB9KVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlXG59XG5cbi8qKlxuICogU3RyaW5naWZ5IHF1ZXJ5XG4gKiBcbiAqIEBwYXJhbSB7Kn0gcXVlcnkgXG4gKiBAcmV0dXJucyBcbiAqL1xuZXhwb3J0IGNvbnN0IHN0cmluZ2lmeVF1ZXJ5ID0gcXVlcnkgPT4ge1xuICAgIGNvbnN0IHNlYXJjaFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKVxuXG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMocXVlcnkpKSB7XG4gICAgICAgIGlmICghIXZhbHVlIHx8IHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICBzZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgdmFsdWUpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VhcmNoUGFyYW1zLnRvU3RyaW5nKClcbn1cbiIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBkZWZpbml0aW9uKSB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iaiwgcHJvcCkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7IH0iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSBmdW5jdGlvbihleHBvcnRzKSB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCBDaGFydCBmcm9tICdjaGFydC5qcy9hdXRvJ1xuXG5pbXBvcnQgeyBzdHJpbmdpZnlRdWVyeSwgcmVxdWVzdCwgUkVRVUVTVF9NRVRIT0RTIH0gZnJvbSAnLi9yZXF1ZXN0Q2xpZW50J1xuXG5pbXBvcnQgeyBkcmF3WUxpbmUgfSBmcm9tICcuL2NoYXJ0UGx1Z2lucydcblxuY29uc3QgQ0hBUlRfVVJMID0gJ2FwaS92MS9tYXJrZXQvY2hhcnRzL3JhbmdlJ1xuXG5jb25zdCBDSEFSVF9UWVBFID0ge1xuICAgIGxpbmU6ICdsaW5lJ1xufVxuXG5jb25zdCBDSEFSVF9SQU5HRSA9IE9iamVjdC5mcmVlemUoe1xuICAgIE9ORV9EQVk6ICdPTkVfREFZJyxcbiAgICBTRVZFTl9EQVlTOiAnU0VWRU5fREFZUycsXG4gICAgVEhJUlRZX0RBWVM6ICdUSElSVFlfREFZUycsXG4gICAgSEFMRl9ZRUFSOiAnSEFMRl9ZRUFSJyxcbiAgICBPTkVfWUVBUjogJ09ORV9ZRUFSJyxcbiAgICBUSFJFRV9ZRUFSOiAnVEhSRUVfWUVBUidcbn0pXG5cbmNvbnN0IEtJTkQgPSB7XG4gICAgUG9zaXRpdmU6ICdwb3NpdGl2ZScsXG4gICAgTmVnYXRpdmU6ICduZWdhdGl2ZSdcbn1cblxuY29uc3QgVEhFTUVfVFlQRSA9IHtcbiAgICBkYXJrOiAnZGFyaycsXG4gICAgbGlnaHQ6ICdsaWdodCdcbn1cblxuY29uc3QgVEhFTUUgPSB7XG4gICAgW1RIRU1FX1RZUEUubGlnaHRdOiB7XG4gICAgICAgIGNoYXJ0czoge1xuICAgICAgICAgICAgdGlja0NvbG9yOiAnIzg3OTI5OScsXG4gICAgICAgICAgICBncmlkQ29sb3I6ICcjRjZGOEZCJyxcbiAgICAgICAgICAgIHBvc2l0aXZlOiB7XG4gICAgICAgICAgICAgICAgaGV4OiAnIzMwQUY3MCcsXG4gICAgICAgICAgICAgICAgcmdiOiB7XG4gICAgICAgICAgICAgICAgICAgIHJlZDogJzQ4JyxcbiAgICAgICAgICAgICAgICAgICAgZ3JlZW46ICcxNzUnLFxuICAgICAgICAgICAgICAgICAgICBibHVlOiAnMTEyJ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZWdhdGl2ZToge1xuICAgICAgICAgICAgICAgIGhleDogJyNFNjY2NjgnLFxuICAgICAgICAgICAgICAgIHJnYjoge1xuICAgICAgICAgICAgICAgICAgICByZWQ6ICcyMzAnLFxuICAgICAgICAgICAgICAgICAgICBncmVlbjogJzEwMicsXG4gICAgICAgICAgICAgICAgICAgIGJsdWU6ICcxMDQnXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICBbVEhFTUVfVFlQRS5kYXJrXToge1xuICAgICAgICBjaGFydHM6IHtcbiAgICAgICAgICAgIHRpY2tDb2xvcjogJyNBNUE2QUQnLFxuICAgICAgICAgICAgZ3JpZENvbG9yOiAnIzM0MzU0NScsXG4gICAgICAgICAgICBwb3NpdGl2ZToge1xuICAgICAgICAgICAgICAgIGhleDogJyMzMEFGNzAnLFxuICAgICAgICAgICAgICAgIHJnYjoge1xuICAgICAgICAgICAgICAgICAgICByZWQ6ICc0OCcsXG4gICAgICAgICAgICAgICAgICAgIGdyZWVuOiAnMTc1JyxcbiAgICAgICAgICAgICAgICAgICAgYmx1ZTogJzExMidcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmVnYXRpdmU6IHtcbiAgICAgICAgICAgICAgICBoZXg6ICcjRTY2NjY4JyxcbiAgICAgICAgICAgICAgICByZ2I6IHtcbiAgICAgICAgICAgICAgICAgICAgcmVkOiAnMjMwJyxcbiAgICAgICAgICAgICAgICAgICAgZ3JlZW46ICcxMDInLFxuICAgICAgICAgICAgICAgICAgICBibHVlOiAnMTA0J1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH1cbiAgICB9XG59XG5cbmNvbnN0IF9kaXNDaGFydHMgPSAoZnVuY3Rpb24gKHdpbmRvdykge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIGNvbnN0IGdldFRva2VuQ2hhcnQgPSBhc3luYyAoe1xuICAgICAgICBob3N0LFxuICAgICAgICBoZWFkZXJzLFxuICAgICAgICBjb2RlLFxuICAgICAgICByYW5nZSxcbiAgICAgICAgY29udmVyc2lvbkN1cnJlbmN5XG4gICAgfSkgPT4ge1xuICAgICAgICBpZiAoIWNvZGUgfHwgIXJhbmdlIHx8ICFjb252ZXJzaW9uQ3VycmVuY3kpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBVbmRlZmluZWQgcGFyYW1zIFtjb2RlXT0ke2NvZGV9LCBbcmFuZ2VdPSR7cmFuZ2V9LCBbY29udmVyc2lvbkN1cnJlbmN5XT0ke2NvbnZlcnNpb25DdXJyZW5jeX1gKVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBxdWVyeSA9IHN0cmluZ2lmeVF1ZXJ5KHsgY29udmVyc2lvbkN1cnJlbmN5IH0pXG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSBhd2FpdCByZXF1ZXN0KHtcbiAgICAgICAgICAgIGhvc3QsXG4gICAgICAgICAgICBoZWFkZXJzLFxuICAgICAgICAgICAgdXJsOiBgJHtDSEFSVF9VUkx9LyR7Y29kZX0vJHtyYW5nZX0/JHtxdWVyeX1gLFxuICAgICAgICAgICAgbWV0aG9kOiBSRVFVRVNUX01FVEhPRFMuR0VUXG4gICAgICAgIH0pXG5cbiAgICAgICAgcmV0dXJuIHBheWxvYWRcbiAgICB9XG5cbiAgICAvLyBDSEFSVFNcblxuICAgIGNvbnN0IGdldFRoZW1lQ29sb3JzID0gKHsgdGhlbWUgfSkgPT4ge1xuICAgICAgICByZXR1cm4gVEhFTUVbVEhFTUVfVFlQRVt0aGVtZV0gfHwgVEhFTUVfVFlQRS5saWdodF1cbiAgICB9XG5cbiAgICBjb25zdCBnZXRDaGFydERlZmF1bHRPcHRpb25zID0gKHsgdGlja0NvbG9yLCBncmlkQ29sb3IgfSkgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcmVzcG9uc2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgIGxheW91dDoge1xuICAgICAgICAgICAgICAgIHBhZGRpbmc6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwbHVnaW5zOiB7XG4gICAgICAgICAgICAgICAgbGVnZW5kOiB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB0b29sdGlwczoge1xuICAgICAgICAgICAgICAgICAgICBlbmFibGVkOiBmYWxzZVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlcmFjdGlvbjoge1xuICAgICAgICAgICAgICAgIGludGVyc2VjdDogZmFsc2VcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzY2FsZXM6IHtcbiAgICAgICAgICAgICAgICB4OiB7XG4gICAgICAgICAgICAgICAgICAgIHRpY2tzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGlnbjogJ3N0YXJ0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHk6IFwiJ0FyaWFsJywgc2Fucy1zZXJpZlwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVIZWlnaHQ6IDRcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogdGlja0NvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWluUm90YXRpb246IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhSb3RhdGlvbjogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9Ta2lwOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b1NraXBQYWRkaW5nOiAyNCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luQXRaZXJvOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGdyaWQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVXaWR0aDogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBncmlkQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICBkcmF3VGlja3M6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZHJhd0JvcmRlcjogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgeToge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogJ3JpZ2h0JyxcbiAgICAgICAgICAgICAgICAgICAgdGlja3M6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHk6IFwiJ0FyaWFsJywgc2Fucy1zZXJpZlwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVIZWlnaHQ6IDFcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogdGlja0NvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWluUm90YXRpb246IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhSb3RhdGlvbjogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhZGRpbmc6IDE2XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGdyaWQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVXaWR0aDogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBncmlkQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICBkcmF3VGlja3M6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZHJhd0JvcmRlcjogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGdldFBsYWdpbnMgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYmVmb3JlVG9vbHRpcERyYXc6IGRyYXdZTGluZSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgXVxuICAgIH1cblxuICAgIGNvbnN0IHNldENoYXJ0UHJvcHMgPSBhc3luYyAoe1xuICAgICAgICB0aGVtZSxcbiAgICAgICAgaG9zdCxcbiAgICAgICAgaGVhZGVycyxcbiAgICAgICAgY29kZSxcbiAgICAgICAgcmFuZ2UsXG4gICAgICAgIGNvbnZlcnNpb25DdXJyZW5jeSxcbiAgICAgICAgY2FudmFzU2VsZWN0b3JzXG4gICAgfSkgPT4ge1xuICAgICAgICBjb25zdCBjdHggPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGNhbnZhc1NlbGVjdG9ycylcbiAgICAgICAgaWYgKCFjdHgpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdDYW50XFwndCBmaW5kIGJ5IFtjYW52YXNTZWxlY3RvcnNdID0nLCBjYW52YXNTZWxlY3RvcnMpXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSBhd2FpdCBnZXRUb2tlbkNoYXJ0KHtcbiAgICAgICAgICAgIGhvc3QsXG4gICAgICAgICAgICBoZWFkZXJzLFxuICAgICAgICAgICAgY29kZSxcbiAgICAgICAgICAgIHJhbmdlOiBDSEFSVF9SQU5HRVtyYW5nZV0gfHwgQ0hBUlRfUkFOR0UuVEhJUlRZX0RBWVMsXG4gICAgICAgICAgICBjb252ZXJzaW9uQ3VycmVuY3lcbiAgICAgICAgfSlcblxuICAgICAgICBpZiAocGF5bG9hZC5yZXNwb25zZVN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnUmVzcG9uc2UgZXJyb3InLCBwYXlsb2FkKVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0aGVtZUNvbG9ycyA9IGdldFRoZW1lQ29sb3JzKHsgdGhlbWUgfSlcblxuICAgICAgICBjb25zdCBtYXJrZXRDaGFydCA9IHBheWxvYWQuZGF0YVxuXG4gICAgICAgIGlmIChtYXJrZXRDaGFydC5kYXRhPy5sZW5naHQgPD0gMCkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1RoZSBkYXRhIG9mIGNoYXJ0IGlzIGVtcHR5JylcbiAgICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2hhcnRLaW5kID0gbWFya2V0Q2hhcnQucGVyY2VudCA8IDAgPyBLSU5ELk5lZ2F0aXZlIDogS0lORC5Qb3NpdGl2ZVxuICAgICAgICBjb25zdCBjaGFydENvbG9ycyA9IHRoZW1lQ29sb3JzLmNoYXJ0c1tjaGFydEtpbmRdXG4gICAgICAgIGNvbnN0IGdyYWRpZW50Q29sb3IgPSBgJHtjaGFydENvbG9ycy5yZ2IucmVkfSwke2NoYXJ0Q29sb3JzLnJnYi5ncmVlbn0sJHtjaGFydENvbG9ycy5yZ2IuYmx1ZX1gXG4gICAgICAgIGNvbnN0IGJvcmRlckNvbG9yID0gY2hhcnRDb2xvcnMuaGV4XG5cbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IGdldENoYXJ0RGVmYXVsdE9wdGlvbnMoe1xuICAgICAgICAgICAgdGlja0NvbG9yOiB0aGVtZUNvbG9ycy5jaGFydHMudGlja0NvbG9yLFxuICAgICAgICAgICAgZ3JpZENvbG9yOiB0aGVtZUNvbG9ycy5jaGFydHMuZ3JpZENvbG9yXG4gICAgICAgIH0pXG5cbiAgICAgICAgY29uc3QgcGx1Z2lucyA9IGdldFBsYWdpbnMoKVxuXG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgICAgICAgIHR5cGU6IENIQVJUX1RZUEUubGluZSxcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgICBwbHVnaW5zLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIGxhYmVsczogbWFya2V0Q2hhcnQubGFiZWxzIHx8IFtdLFxuICAgICAgICAgICAgICAgIGRhdGFzZXRzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IG1hcmtldENoYXJ0LmRhdGEgfHwgW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFydCA9IGNvbnRleHQuY2hhcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGN0eCB9ID0gY2hhcnRcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdyYWRpZW50ID0gY3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50KDAsIDAsIDAsIDQwMClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5hZGRDb2xvclN0b3AoMCwgYHJnYmEoJHtncmFkaWVudENvbG9yfSwgMC42NClgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWRpZW50LmFkZENvbG9yU3RvcCgwLjM1LCBgcmdiYSgke2dyYWRpZW50Q29sb3J9LCAwLjIpYClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5hZGRDb2xvclN0b3AoMSwgJ3JnYmEoMjU1LDI1NSwyNTUsMCknKVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdyYWRpZW50XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1YmljSW50ZXJwb2xhdGlvbk1vZGU6ICdtb25vdG9uZScsXG4gICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJXaWR0aDogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50UmFkaXVzOiAwXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBuZXcgQ2hhcnQoY3R4LCBjb25maWcpXG4gICAgfVxuXG4gICAgY2xhc3MgUHJvdCB7IH1cbiAgICBQcm90LnByb3RvdHlwZS5zZXRDaGFydFByb3BzID0gc2V0Q2hhcnRQcm9wc1xuICAgIFByb3QucHJvdG90eXBlLnJhbmdlID0gQ0hBUlRfUkFOR0VcbiAgICBQcm90LnByb3RvdHlwZS50aGVtZSA9IFRIRU1FX1RZUEVcblxuICAgIGNvbnN0IF9kaXNDaGF0cyA9IHtcbiAgICAgICAgc2V0Q2hhcnRQcm9wczogZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb3QoKS5zZXRDaGFydFByb3BzKHByb3BzKVxuICAgICAgICB9LFxuICAgICAgICByYW5nZTogbmV3IFByb3QoKS5yYW5nZSxcbiAgICAgICAgdGhlbWU6IG5ldyBQcm90KCkudGhlbWVcbiAgICB9XG5cbiAgICB3aW5kb3cuX2Rpc0NoYXRzID0gX2Rpc0NoYXRzXG4gICAgcmV0dXJuIF9kaXNDaGF0c1xufSkod2luZG93KVxuXG5leHBvcnQgeyBfZGlzQ2hhcnRzIH1cblxuLy8gU2FtcGxlXG4vLyB3aW5kb3cuX2Rpc0NoYXRzLnNldENoYXJ0UHJvcHMoe1xuLy8gICAgIHRoZW1lOiB3aW5kb3cuX2Rpc0NoYXRzLnRoZW1lLmxpZ2h0LCBcbi8vICAgICBob3N0OiAnaHR0cDovL2xvY2FsaG9zdDozMDEwJyxcbi8vICAgICBjb2RlOiAnQlRDJyxcbi8vICAgICByYW5nZTogd2luZG93Ll9kaXNDaGF0cy5yYW5nZS5USElSVFlfREFZUyxcbi8vICAgICBjb252ZXJzaW9uQ3VycmVuY3k6ICdFVVInLFxuLy8gICAgIGNhbnZhc1NlbGVjdG9yczogJ1tkYXRhLWVsZW1lbnQ9XCJjaGFydFwiXSdcbi8vIH0pXG5cbi8vIHdpbmRvdy5fZGlzQ2hhdHMuc2V0Q2hhcnRQcm9wcyh7XG4vLyAgICAgdGhlbWU6IHdpbmRvdy5fZGlzQ2hhdHMudGhlbWUubGlnaHQsXG4vLyAgICAgaG9zdDogJ2h0dHBzOi8vZ3BvLmRldmRpZ2l0YWxpbnZlc3RtZW50c29sdXRpb25zLmRlJyxcbi8vICAgICBjb2RlOiAnQlRDJyxcbi8vICAgICByYW5nZTogd2luZG93Ll9kaXNDaGF0cy5yYW5nZS5USElSVFlfREFZUyxcbi8vICAgICBjb252ZXJzaW9uQ3VycmVuY3k6ICdFVVInLFxuLy8gICAgIGNhbnZhc1NlbGVjdG9yczogJ1tkYXRhLWVsZW1lbnQ9XCJjaGFydFwiXSdcbi8vIH0pIl0sInNvdXJjZVJvb3QiOiIifQ==