import { debounce, memo, notUndefined, approxEqual } from "/_nuxt/@fs/D:/speckle-server/packages/ui-components/node_modules/@tanstack/virtual-core/dist/esm/utils.js?v=e4f18c29"; const defaultKeyExtractor = (index) => index; const defaultRangeExtractor = (range) => { const start = Math.max(range.startIndex - range.overscan, 0); const end = Math.min(range.endIndex + range.overscan, range.count - 1); const arr = []; for (let i = start; i <= end; i++) { arr.push(i); } return arr; }; const observeElementRect = (instance, cb) => { const element = instance.scrollElement; if (!element) { return; } const targetWindow = instance.targetWindow; if (!targetWindow) { return; } const handler = (rect) => { const { width, height } = rect; cb({ width: Math.round(width), height: Math.round(height) }); }; handler(element.getBoundingClientRect()); if (!targetWindow.ResizeObserver) { return () => { }; } const observer = new targetWindow.ResizeObserver((entries) => { const run = () => { const entry = entries[0]; if (entry == null ? void 0 : entry.borderBoxSize) { const box = entry.borderBoxSize[0]; if (box) { handler({ width: box.inlineSize, height: box.blockSize }); return; } } handler(element.getBoundingClientRect()); }; instance.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run(); }); observer.observe(element, { box: "border-box" }); return () => { observer.unobserve(element); }; }; const addEventListenerOptions = { passive: true }; const observeWindowRect = (instance, cb) => { const element = instance.scrollElement; if (!element) { return; } const handler = () => { cb({ width: element.innerWidth, height: element.innerHeight }); }; handler(); element.addEventListener("resize", handler, addEventListenerOptions); return () => { element.removeEventListener("resize", handler); }; }; const supportsScrollend = typeof window == "undefined" ? true : "onscrollend" in window; const observeElementOffset = (instance, cb) => { const element = instance.scrollElement; if (!element) { return; } const targetWindow = instance.targetWindow; if (!targetWindow) { return; } let offset = 0; const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : debounce( targetWindow, () => { cb(offset, false); }, instance.options.isScrollingResetDelay ); const createHandler = (isScrolling) => () => { const { horizontal, isRtl } = instance.options; offset = horizontal ? element["scrollLeft"] * (isRtl && -1 || 1) : element["scrollTop"]; fallback(); cb(offset, isScrolling); }; const handler = createHandler(true); const endHandler = createHandler(false); endHandler(); element.addEventListener("scroll", handler, addEventListenerOptions); const registerScrollendEvent = instance.options.useScrollendEvent && supportsScrollend; if (registerScrollendEvent) { element.addEventListener("scrollend", endHandler, addEventListenerOptions); } return () => { element.removeEventListener("scroll", handler); if (registerScrollendEvent) { element.removeEventListener("scrollend", endHandler); } }; }; const observeWindowOffset = (instance, cb) => { const element = instance.scrollElement; if (!element) { return; } const targetWindow = instance.targetWindow; if (!targetWindow) { return; } let offset = 0; const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : debounce( targetWindow, () => { cb(offset, false); }, instance.options.isScrollingResetDelay ); const createHandler = (isScrolling) => () => { offset = element[instance.options.horizontal ? "scrollX" : "scrollY"]; fallback(); cb(offset, isScrolling); }; const handler = createHandler(true); const endHandler = createHandler(false); endHandler(); element.addEventListener("scroll", handler, addEventListenerOptions); const registerScrollendEvent = instance.options.useScrollendEvent && supportsScrollend; if (registerScrollendEvent) { element.addEventListener("scrollend", endHandler, addEventListenerOptions); } return () => { element.removeEventListener("scroll", handler); if (registerScrollendEvent) { element.removeEventListener("scrollend", endHandler); } }; }; const measureElement = (element, entry, instance) => { if (entry == null ? void 0 : entry.borderBoxSize) { const box = entry.borderBoxSize[0]; if (box) { const size = Math.round( box[instance.options.horizontal ? "inlineSize" : "blockSize"] ); return size; } } return Math.round( element.getBoundingClientRect()[instance.options.horizontal ? "width" : "height"] ); }; const windowScroll = (offset, { adjustments = 0, behavior }, instance) => { var _a, _b; const toOffset = offset + adjustments; (_b = (_a = instance.scrollElement) == null ? void 0 : _a.scrollTo) == null ? void 0 : _b.call(_a, { [instance.options.horizontal ? "left" : "top"]: toOffset, behavior }); }; const elementScroll = (offset, { adjustments = 0, behavior }, instance) => { var _a, _b; const toOffset = offset + adjustments; (_b = (_a = instance.scrollElement) == null ? void 0 : _a.scrollTo) == null ? void 0 : _b.call(_a, { [instance.options.horizontal ? "left" : "top"]: toOffset, behavior }); }; class Virtualizer { constructor(opts) { this.unsubs = []; this.scrollElement = null; this.targetWindow = null; this.isScrolling = false; this.scrollToIndexTimeoutId = null; this.measurementsCache = []; this.itemSizeCache = /* @__PURE__ */ new Map(); this.pendingMeasuredCacheIndexes = []; this.scrollRect = null; this.scrollOffset = null; this.scrollDirection = null; this.scrollAdjustments = 0; this.elementsCache = /* @__PURE__ */ new Map(); this.observer = /* @__PURE__ */ (() => { let _ro = null; const get = () => { if (_ro) { return _ro; } if (!this.targetWindow || !this.targetWindow.ResizeObserver) { return null; } return _ro = new this.targetWindow.ResizeObserver((entries) => { entries.forEach((entry) => { const run = () => { this._measureElement(entry.target, entry); }; this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run(); }); }); }; return { disconnect: () => { var _a; (_a = get()) == null ? void 0 : _a.disconnect(); _ro = null; }, observe: (target) => { var _a; return (_a = get()) == null ? void 0 : _a.observe(target, { box: "border-box" }); }, unobserve: (target) => { var _a; return (_a = get()) == null ? void 0 : _a.unobserve(target); } }; })(); this.range = null; this.setOptions = (opts2) => { Object.entries(opts2).forEach(([key, value]) => { if (typeof value === "undefined") delete opts2[key]; }); this.options = { debug: false, initialOffset: 0, overscan: 1, paddingStart: 0, paddingEnd: 0, scrollPaddingStart: 0, scrollPaddingEnd: 0, horizontal: false, getItemKey: defaultKeyExtractor, rangeExtractor: defaultRangeExtractor, onChange: () => { }, measureElement, initialRect: { width: 0, height: 0 }, scrollMargin: 0, gap: 0, indexAttribute: "data-index", initialMeasurementsCache: [], lanes: 1, isScrollingResetDelay: 150, enabled: true, isRtl: false, useScrollendEvent: false, useAnimationFrameWithResizeObserver: false, ...opts2 }; }; this.notify = (sync) => { var _a, _b; (_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, sync); }; this.maybeNotify = memo( () => { this.calculateRange(); return [ this.isScrolling, this.range ? this.range.startIndex : null, this.range ? this.range.endIndex : null ]; }, (isScrolling) => { this.notify(isScrolling); }, { key: "maybeNotify", debug: () => this.options.debug, initialDeps: [ this.isScrolling, this.range ? this.range.startIndex : null, this.range ? this.range.endIndex : null ] } ); this.cleanup = () => { this.unsubs.filter(Boolean).forEach((d) => d()); this.unsubs = []; this.observer.disconnect(); this.scrollElement = null; this.targetWindow = null; }; this._didMount = () => { return () => { this.cleanup(); }; }; this._willUpdate = () => { var _a; const scrollElement = this.options.enabled ? this.options.getScrollElement() : null; if (this.scrollElement !== scrollElement) { this.cleanup(); if (!scrollElement) { this.maybeNotify(); return; } this.scrollElement = scrollElement; if (this.scrollElement && "ownerDocument" in this.scrollElement) { this.targetWindow = this.scrollElement.ownerDocument.defaultView; } else { this.targetWindow = ((_a = this.scrollElement) == null ? void 0 : _a.window) ?? null; } this.elementsCache.forEach((cached) => { this.observer.observe(cached); }); this._scrollToOffset(this.getScrollOffset(), { adjustments: void 0, behavior: void 0 }); this.unsubs.push( this.options.observeElementRect(this, (rect) => { this.scrollRect = rect; this.maybeNotify(); }) ); this.unsubs.push( this.options.observeElementOffset(this, (offset, isScrolling) => { this.scrollAdjustments = 0; this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? "forward" : "backward" : null; this.scrollOffset = offset; this.isScrolling = isScrolling; this.maybeNotify(); }) ); } }; this.getSize = () => { if (!this.options.enabled) { this.scrollRect = null; return 0; } this.scrollRect = this.scrollRect ?? this.options.initialRect; return this.scrollRect[this.options.horizontal ? "width" : "height"]; }; this.getScrollOffset = () => { if (!this.options.enabled) { this.scrollOffset = null; return 0; } this.scrollOffset = this.scrollOffset ?? (typeof this.options.initialOffset === "function" ? this.options.initialOffset() : this.options.initialOffset); return this.scrollOffset; }; this.getFurthestMeasurement = (measurements, index) => { const furthestMeasurementsFound = /* @__PURE__ */ new Map(); const furthestMeasurements = /* @__PURE__ */ new Map(); for (let m = index - 1; m >= 0; m--) { const measurement = measurements[m]; if (furthestMeasurementsFound.has(measurement.lane)) { continue; } const previousFurthestMeasurement = furthestMeasurements.get( measurement.lane ); if (previousFurthestMeasurement == null || measurement.end > previousFurthestMeasurement.end) { furthestMeasurements.set(measurement.lane, measurement); } else if (measurement.end < previousFurthestMeasurement.end) { furthestMeasurementsFound.set(measurement.lane, true); } if (furthestMeasurementsFound.size === this.options.lanes) { break; } } return furthestMeasurements.size === this.options.lanes ? Array.from(furthestMeasurements.values()).sort((a, b) => { if (a.end === b.end) { return a.index - b.index; } return a.end - b.end; })[0] : void 0; }; this.getMeasurementOptions = memo( () => [ this.options.count, this.options.paddingStart, this.options.scrollMargin, this.options.getItemKey, this.options.enabled ], (count, paddingStart, scrollMargin, getItemKey, enabled) => { this.pendingMeasuredCacheIndexes = []; return { count, paddingStart, scrollMargin, getItemKey, enabled }; }, { key: false } ); this.getMeasurements = memo( () => [this.getMeasurementOptions(), this.itemSizeCache], ({ count, paddingStart, scrollMargin, getItemKey, enabled }, itemSizeCache) => { if (!enabled) { this.measurementsCache = []; this.itemSizeCache.clear(); return []; } if (this.measurementsCache.length === 0) { this.measurementsCache = this.options.initialMeasurementsCache; this.measurementsCache.forEach((item) => { this.itemSizeCache.set(item.key, item.size); }); } const min = this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0; this.pendingMeasuredCacheIndexes = []; const measurements = this.measurementsCache.slice(0, min); for (let i = min; i < count; i++) { const key = getItemKey(i); const furthestMeasurement = this.options.lanes === 1 ? measurements[i - 1] : this.getFurthestMeasurement(measurements, i); const start = furthestMeasurement ? furthestMeasurement.end + this.options.gap : paddingStart + scrollMargin; const measuredSize = itemSizeCache.get(key); const size = typeof measuredSize === "number" ? measuredSize : this.options.estimateSize(i); const end = start + size; const lane = furthestMeasurement ? furthestMeasurement.lane : i % this.options.lanes; measurements[i] = { index: i, start, size, end, key, lane }; } this.measurementsCache = measurements; return measurements; }, { key: "getMeasurements", debug: () => this.options.debug } ); this.calculateRange = memo( () => [ this.getMeasurements(), this.getSize(), this.getScrollOffset(), this.options.lanes ], (measurements, outerSize, scrollOffset, lanes) => { return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({ measurements, outerSize, scrollOffset, lanes }) : null; }, { key: "calculateRange", debug: () => this.options.debug } ); this.getVirtualIndexes = memo( () => { let startIndex = null; let endIndex = null; const range = this.calculateRange(); if (range) { startIndex = range.startIndex; endIndex = range.endIndex; } this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex]); return [ this.options.rangeExtractor, this.options.overscan, this.options.count, startIndex, endIndex ]; }, (rangeExtractor, overscan, count, startIndex, endIndex) => { return startIndex === null || endIndex === null ? [] : rangeExtractor({ startIndex, endIndex, overscan, count }); }, { key: "getVirtualIndexes", debug: () => this.options.debug } ); this.indexFromElement = (node) => { const attributeName = this.options.indexAttribute; const indexStr = node.getAttribute(attributeName); if (!indexStr) { console.warn( `Missing attribute name '${attributeName}={index}' on measured element.` ); return -1; } return parseInt(indexStr, 10); }; this._measureElement = (node, entry) => { const index = this.indexFromElement(node); const item = this.measurementsCache[index]; if (!item) { return; } const key = item.key; const prevNode = this.elementsCache.get(key); if (prevNode !== node) { if (prevNode) { this.observer.unobserve(prevNode); } this.observer.observe(node); this.elementsCache.set(key, node); } if (node.isConnected) { this.resizeItem(index, this.options.measureElement(node, entry, this)); } }; this.resizeItem = (index, size) => { const item = this.measurementsCache[index]; if (!item) { return; } const itemSize = this.itemSizeCache.get(item.key) ?? item.size; const delta = size - itemSize; if (delta !== 0) { if (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments) { if (this.options.debug) { console.info("correction", delta); } this._scrollToOffset(this.getScrollOffset(), { adjustments: this.scrollAdjustments += delta, behavior: void 0 }); } this.pendingMeasuredCacheIndexes.push(item.index); this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size)); this.notify(false); } }; this.measureElement = (node) => { if (!node) { this.elementsCache.forEach((cached, key) => { if (!cached.isConnected) { this.observer.unobserve(cached); this.elementsCache.delete(key); } }); return; } this._measureElement(node, void 0); }; this.getVirtualItems = memo( () => [this.getVirtualIndexes(), this.getMeasurements()], (indexes, measurements) => { const virtualItems = []; for (let k = 0, len = indexes.length; k < len; k++) { const i = indexes[k]; const measurement = measurements[i]; virtualItems.push(measurement); } return virtualItems; }, { key: "getVirtualItems", debug: () => this.options.debug } ); this.getVirtualItemForOffset = (offset) => { const measurements = this.getMeasurements(); if (measurements.length === 0) { return void 0; } return notUndefined( measurements[findNearestBinarySearch( 0, measurements.length - 1, (index) => notUndefined(measurements[index]).start, offset )] ); }; this.getOffsetForAlignment = (toOffset, align, itemSize = 0) => { const size = this.getSize(); const scrollOffset = this.getScrollOffset(); if (align === "auto") { align = toOffset >= scrollOffset + size ? "end" : "start"; } if (align === "center") { toOffset += (itemSize - size) / 2; } else if (align === "end") { toOffset -= size; } const scrollSizeProp = this.options.horizontal ? "scrollWidth" : "scrollHeight"; const scrollSize = this.scrollElement ? "document" in this.scrollElement ? this.scrollElement.document.documentElement[scrollSizeProp] : this.scrollElement[scrollSizeProp] : 0; const maxOffset = scrollSize - size; return Math.max(Math.min(maxOffset, toOffset), 0); }; this.getOffsetForIndex = (index, align = "auto") => { index = Math.max(0, Math.min(index, this.options.count - 1)); const item = this.measurementsCache[index]; if (!item) { return void 0; } const size = this.getSize(); const scrollOffset = this.getScrollOffset(); if (align === "auto") { if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) { align = "end"; } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) { align = "start"; } else { return [scrollOffset, align]; } } const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart; return [ this.getOffsetForAlignment(toOffset, align, item.size), align ]; }; this.isDynamicMode = () => this.elementsCache.size > 0; this.cancelScrollToIndex = () => { if (this.scrollToIndexTimeoutId !== null && this.targetWindow) { this.targetWindow.clearTimeout(this.scrollToIndexTimeoutId); this.scrollToIndexTimeoutId = null; } }; this.scrollToOffset = (toOffset, { align = "start", behavior } = {}) => { this.cancelScrollToIndex(); if (behavior === "smooth" && this.isDynamicMode()) { console.warn( "The `smooth` scroll behavior is not fully supported with dynamic size." ); } this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), { adjustments: void 0, behavior }); }; this.scrollToIndex = (index, { align: initialAlign = "auto", behavior } = {}) => { index = Math.max(0, Math.min(index, this.options.count - 1)); this.cancelScrollToIndex(); if (behavior === "smooth" && this.isDynamicMode()) { console.warn( "The `smooth` scroll behavior is not fully supported with dynamic size." ); } const offsetAndAlign = this.getOffsetForIndex(index, initialAlign); if (!offsetAndAlign) return; const [offset, align] = offsetAndAlign; this._scrollToOffset(offset, { adjustments: void 0, behavior }); if (behavior !== "smooth" && this.isDynamicMode() && this.targetWindow) { this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => { this.scrollToIndexTimeoutId = null; const elementInDOM = this.elementsCache.has( this.options.getItemKey(index) ); if (elementInDOM) { const [latestOffset] = notUndefined( this.getOffsetForIndex(index, align) ); if (!approxEqual(latestOffset, this.getScrollOffset())) { this.scrollToIndex(index, { align, behavior }); } } else { this.scrollToIndex(index, { align, behavior }); } }); } }; this.scrollBy = (delta, { behavior } = {}) => { this.cancelScrollToIndex(); if (behavior === "smooth" && this.isDynamicMode()) { console.warn( "The `smooth` scroll behavior is not fully supported with dynamic size." ); } this._scrollToOffset(this.getScrollOffset() + delta, { adjustments: void 0, behavior }); }; this.getTotalSize = () => { var _a; const measurements = this.getMeasurements(); let end; if (measurements.length === 0) { end = this.options.paddingStart; } else if (this.options.lanes === 1) { end = ((_a = measurements[measurements.length - 1]) == null ? void 0 : _a.end) ?? 0; } else { const endByLane = Array(this.options.lanes).fill(null); let endIndex = measurements.length - 1; while (endIndex >= 0 && endByLane.some((val) => val === null)) { const item = measurements[endIndex]; if (endByLane[item.lane] === null) { endByLane[item.lane] = item.end; } endIndex--; } end = Math.max(...endByLane.filter((val) => val !== null)); } return Math.max( end - this.options.scrollMargin + this.options.paddingEnd, 0 ); }; this._scrollToOffset = (offset, { adjustments, behavior }) => { this.options.scrollToFn(offset, { behavior, adjustments }, this); }; this.measure = () => { this.itemSizeCache = /* @__PURE__ */ new Map(); this.notify(false); }; this.setOptions(opts); } } const findNearestBinarySearch = (low, high, getCurrentValue, value) => { while (low <= high) { const middle = (low + high) / 2 | 0; const currentValue = getCurrentValue(middle); if (currentValue < value) { low = middle + 1; } else if (currentValue > value) { high = middle - 1; } else { return middle; } } if (low > 0) { return low - 1; } else { return 0; } }; function calculateRange({ measurements, outerSize, scrollOffset, lanes }) { const lastIndex = measurements.length - 1; const getOffset = (index) => measurements[index].start; if (measurements.length <= lanes) { return { startIndex: 0, endIndex: lastIndex }; } let startIndex = findNearestBinarySearch( 0, lastIndex, getOffset, scrollOffset ); let endIndex = startIndex; if (lanes === 1) { while (endIndex < lastIndex && measurements[endIndex].end < scrollOffset + outerSize) { endIndex++; } } else if (lanes > 1) { const endPerLane = Array(lanes).fill(0); while (endIndex < lastIndex && endPerLane.some((pos) => pos < scrollOffset + outerSize)) { const item = measurements[endIndex]; endPerLane[item.lane] = item.end; endIndex++; } const startPerLane = Array(lanes).fill(scrollOffset + outerSize); while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) { const item = measurements[startIndex]; startPerLane[item.lane] = item.start; startIndex--; } startIndex = Math.max(0, startIndex - startIndex % lanes); endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - endIndex % lanes)); } return { startIndex, endIndex }; } export { Virtualizer, approxEqual, debounce, defaultKeyExtractor, defaultRangeExtractor, elementScroll, measureElement, memo, notUndefined, observeElementOffset, observeElementRect, observeWindowOffset, observeWindowRect, windowScroll }; //# sourceMappingURL=data:application/json;base64,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Q0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUNGLEdBS0c7QUFDSyxvQkFBWSxhQUFhLFNBQVM7QUFDeEMsUUFBTSxZQUFZLENBQUMsVUFBa0IsYUFBYSxLQUFLLEVBQUc7QUFHdEQsbUJBQWEsVUFBVSxPQUFPO0FBQ3pCO0FBQUEsTUFDTCxZQUFZO0FBQUEsTUFDWixVQUFVO0FBQUEsSUFDWjtBQUFBO0FBR0YsTUFBSSxhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLEVBQ0Y7QUFDQSxNQUFJLFdBQVc7QUFFZixNQUFJLFVBQVUsR0FBRztBQUNmLFdBQ0UsV0FBVyxhQUNYLGFBQWEsUUFBUSxFQUFHLE1BQU0sZUFBZSxXQUM3QztBQUNBO0FBQUE7QUFBQSxFQUNGLFdBQ1MsUUFBUSxHQUFHO0FBR3BCLFVBQU0sYUFBYSxNQUFNLEtBQUssRUFBRSxLQUFLLENBQUM7QUFFcEMsc0JBQVcsYUFDWCxXQUFXLEtBQUssQ0FBQyxRQUFRLE1BQU0sZUFBZSxTQUFTLEdBQ3ZEO0FBQ00sbUJBQU8sYUFBYSxRQUFRO0FBQ3ZCLHNCQUFLLElBQUksSUFBSSxLQUFLO0FBQzdCO0FBQUE7QUFLRixVQUFNLGVBQWUsTUFBTSxLQUFLLEVBQUUsS0FBSyxlQUFlLFNBQVM7QUFDeEQseUJBQWMsS0FBSyxhQUFhLEtBQUssQ0FBQyxRQUFRLE9BQU8sWUFBWSxHQUFHO0FBQ25FLG1CQUFPLGFBQWEsVUFBVTtBQUN2Qix3QkFBSyxJQUFJLElBQUksS0FBSztBQUMvQjtBQUFBO0FBSUYsaUJBQWEsS0FBSyxJQUFJLEdBQUcsYUFBYyxhQUFhLEtBQU07QUFFMUQsZUFBVyxLQUFLLElBQUksV0FBVyxZQUFZLFFBQVEsSUFBSyxXQUFXLE1BQU87QUFBQTtBQUdyRSxXQUFFLFlBQVksU0FBUztBQUNoQyIsIm5hbWVzIjpbIm9wdHMiXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGFwcHJveEVxdWFsLCBkZWJvdW5jZSwgbWVtbywgbm90VW5kZWZpbmVkIH0gZnJvbSAnLi91dGlscydcblxuZXhwb3J0ICogZnJvbSAnLi91dGlscydcblxuLy9cblxudHlwZSBTY3JvbGxEaXJlY3Rpb24gPSAnZm9yd2FyZCcgfCAnYmFja3dhcmQnXG5cbnR5cGUgU2Nyb2xsQWxpZ25tZW50ID0gJ3N0YXJ0JyB8ICdjZW50ZXInIHwgJ2VuZCcgfCAnYXV0bydcblxudHlwZSBTY3JvbGxCZWhhdmlvciA9ICdhdXRvJyB8ICdzbW9vdGgnXG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Nyb2xsVG9PcHRpb25zIHtcbiAgYWxpZ24/OiBTY3JvbGxBbGlnbm1lbnRcbiAgYmVoYXZpb3I/OiBTY3JvbGxCZWhhdmlvclxufVxuXG50eXBlIFNjcm9sbFRvT2Zmc2V0T3B0aW9ucyA9IFNjcm9sbFRvT3B0aW9uc1xuXG50eXBlIFNjcm9sbFRvSW5kZXhPcHRpb25zID0gU2Nyb2xsVG9PcHRpb25zXG5cbmV4cG9ydCBpbnRlcmZhY2UgUmFuZ2Uge1xuICBzdGFydEluZGV4OiBudW1iZXJcbiAgZW5kSW5kZXg6IG51bWJlclxuICBvdmVyc2NhbjogbnVtYmVyXG4gIGNvdW50OiBudW1iZXJcbn1cblxudHlwZSBLZXkgPSBudW1iZXIgfCBzdHJpbmcgfCBiaWdpbnRcblxuZXhwb3J0IGludGVyZmFjZSBWaXJ0dWFsSXRlbSB7XG4gIGtleTogS2V5XG4gIGluZGV4OiBudW1iZXJcbiAgc3RhcnQ6IG51bWJlclxuICBlbmQ6IG51bWJlclxuICBzaXplOiBudW1iZXJcbiAgbGFuZTogbnVtYmVyXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVjdCB7XG4gIHdpZHRoOiBudW1iZXJcbiAgaGVpZ2h0OiBudW1iZXJcbn1cblxuLy9cblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRLZXlFeHRyYWN0b3IgPSAoaW5kZXg6IG51bWJlcikgPT4gaW5kZXhcblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRSYW5nZUV4dHJhY3RvciA9IChyYW5nZTogUmFuZ2UpID0+IHtcbiAgY29uc3Qgc3RhcnQgPSBNYXRoLm1heChyYW5nZS5zdGFydEluZGV4IC0gcmFuZ2Uub3ZlcnNjYW4sIDApXG4gIGNvbnN0IGVuZCA9IE1hdGgubWluKHJhbmdlLmVuZEluZGV4ICsgcmFuZ2Uub3ZlcnNjYW4sIHJhbmdlLmNvdW50IC0gMSlcblxuICBjb25zdCBhcnIgPSBbXVxuXG4gIGZvciAobGV0IGkgPSBzdGFydDsgaSA8PSBlbmQ7IGkrKykge1xuICAgIGFyci5wdXNoKGkpXG4gIH1cblxuICByZXR1cm4gYXJyXG59XG5cbmV4cG9ydCBjb25zdCBvYnNlcnZlRWxlbWVudFJlY3QgPSA8VCBleHRlbmRzIEVsZW1lbnQ+KFxuICBpbnN0YW5jZTogVmlydHVhbGl6ZXI8VCwgYW55PixcbiAgY2I6IChyZWN0OiBSZWN0KSA9PiB2b2lkLFxuKSA9PiB7XG4gIGNvbnN0IGVsZW1lbnQgPSBpbnN0YW5jZS5zY3JvbGxFbGVtZW50XG4gIGlmICghZWxlbWVudCkge1xuICAgIHJldHVyblxuICB9XG4gIGNvbnN0IHRhcmdldFdpbmRvdyA9IGluc3RhbmNlLnRhcmdldFdpbmRvd1xuICBpZiAoIXRhcmdldFdpbmRvdykge1xuICAgIHJldHVyblxuICB9XG5cbiAgY29uc3QgaGFuZGxlciA9IChyZWN0OiBSZWN0KSA9PiB7XG4gICAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSByZWN0XG4gICAgY2IoeyB3aWR0aDogTWF0aC5yb3VuZCh3aWR0aCksIGhlaWdodDogTWF0aC5yb3VuZChoZWlnaHQpIH0pXG4gIH1cblxuICBoYW5kbGVyKGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkpXG5cbiAgaWYgKCF0YXJnZXRXaW5kb3cuUmVzaXplT2JzZXJ2ZXIpIHtcbiAgICByZXR1cm4gKCkgPT4ge31cbiAgfVxuXG4gIGNvbnN0IG9ic2VydmVyID0gbmV3IHRhcmdldFdpbmRvdy5SZXNpemVPYnNlcnZlcigoZW50cmllcykgPT4ge1xuICAgIGNvbnN0IHJ1biA9ICgpID0+IHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1swXVxuICAgICAgaWYgKGVudHJ5Py5ib3JkZXJCb3hTaXplKSB7XG4gICAgICAgIGNvbnN0IGJveCA9IGVudHJ5LmJvcmRlckJveFNpemVbMF1cbiAgICAgICAgaWYgKGJveCkge1xuICAgICAgICAgIGhhbmRsZXIoeyB3aWR0aDogYm94LmlubGluZVNpemUsIGhlaWdodDogYm94LmJsb2NrU2l6ZSB9KVxuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYW5kbGVyKGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkpXG4gICAgfVxuXG4gICAgaW5zdGFuY2Uub3B0aW9ucy51c2VBbmltYXRpb25GcmFtZVdpdGhSZXNpemVPYnNlcnZlclxuICAgICAgPyByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocnVuKVxuICAgICAgOiBydW4oKVxuICB9KVxuXG4gIG9ic2VydmVyLm9ic2VydmUoZWxlbWVudCwgeyBib3g6ICdib3JkZXItYm94JyB9KVxuXG4gIHJldHVybiAoKSA9PiB7XG4gICAgb2JzZXJ2ZXIudW5vYnNlcnZlKGVsZW1lbnQpXG4gIH1cbn1cblxuY29uc3QgYWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMgPSB7XG4gIHBhc3NpdmU6IHRydWUsXG59XG5cbmV4cG9ydCBjb25zdCBvYnNlcnZlV2luZG93UmVjdCA9IChcbiAgaW5zdGFuY2U6IFZpcnR1YWxpemVyPFdpbmRvdywgYW55PixcbiAgY2I6IChyZWN0OiBSZWN0KSA9PiB2b2lkLFxuKSA9PiB7XG4gIGNvbnN0IGVsZW1lbnQgPSBpbnN0YW5jZS5zY3JvbGxFbGVtZW50XG4gIGlmICghZWxlbWVudCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgY29uc3QgaGFuZGxlciA9ICgpID0+IHtcbiAgICBjYih7IHdpZHRoOiBlbGVtZW50LmlubmVyV2lkdGgsIGhlaWdodDogZWxlbWVudC5pbm5lckhlaWdodCB9KVxuICB9XG4gIGhhbmRsZXIoKVxuXG4gIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgaGFuZGxlciwgYWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMpXG5cbiAgcmV0dXJuICgpID0+IHtcbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIGhhbmRsZXIpXG4gIH1cbn1cblxuY29uc3Qgc3VwcG9ydHNTY3JvbGxlbmQgPVxuICB0eXBlb2Ygd2luZG93ID09ICd1bmRlZmluZWQnID8gdHJ1ZSA6ICdvbnNjcm9sbGVuZCcgaW4gd2luZG93XG5cbnR5cGUgT2JzZXJ2ZU9mZnNldENhbGxCYWNrID0gKG9mZnNldDogbnVtYmVyLCBpc1Njcm9sbGluZzogYm9vbGVhbikgPT4gdm9pZFxuXG5leHBvcnQgY29uc3Qgb2JzZXJ2ZUVsZW1lbnRPZmZzZXQgPSA8VCBleHRlbmRzIEVsZW1lbnQ+KFxuICBpbnN0YW5jZTogVmlydHVhbGl6ZXI8VCwgYW55PixcbiAgY2I6IE9ic2VydmVPZmZzZXRDYWxsQmFjayxcbikgPT4ge1xuICBjb25zdCBlbGVtZW50ID0gaW5zdGFuY2Uuc2Nyb2xsRWxlbWVudFxuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm5cbiAgfVxuICBjb25zdCB0YXJnZXRXaW5kb3cgPSBpbnN0YW5jZS50YXJnZXRXaW5kb3dcbiAgaWYgKCF0YXJnZXRXaW5kb3cpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIGxldCBvZmZzZXQgPSAwXG4gIGNvbnN0IGZhbGxiYWNrID1cbiAgICBpbnN0YW5jZS5vcHRpb25zLnVzZVNjcm9sbGVuZEV2ZW50ICYmIHN1cHBvcnRzU2Nyb2xsZW5kXG4gICAgICA/ICgpID0+IHVuZGVmaW5lZFxuICAgICAgOiBkZWJvdW5jZShcbiAgICAgICAgICB0YXJnZXRXaW5kb3csXG4gICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgY2Iob2Zmc2V0LCBmYWxzZSlcbiAgICAgICAgICB9LFxuICAgICAgICAgIGluc3RhbmNlLm9wdGlvbnMuaXNTY3JvbGxpbmdSZXNldERlbGF5LFxuICAgICAgICApXG5cbiAgY29uc3QgY3JlYXRlSGFuZGxlciA9IChpc1Njcm9sbGluZzogYm9vbGVhbikgPT4gKCkgPT4ge1xuICAgIGNvbnN0IHsgaG9yaXpvbnRhbCwgaXNSdGwgfSA9IGluc3RhbmNlLm9wdGlvbnNcbiAgICBvZmZzZXQgPSBob3Jpem9udGFsXG4gICAgICA/IGVsZW1lbnRbJ3Njcm9sbExlZnQnXSAqICgoaXNSdGwgJiYgLTEpIHx8IDEpXG4gICAgICA6IGVsZW1lbnRbJ3Njcm9sbFRvcCddXG4gICAgZmFsbGJhY2soKVxuICAgIGNiKG9mZnNldCwgaXNTY3JvbGxpbmcpXG4gIH1cbiAgY29uc3QgaGFuZGxlciA9IGNyZWF0ZUhhbmRsZXIodHJ1ZSlcbiAgY29uc3QgZW5kSGFuZGxlciA9IGNyZWF0ZUhhbmRsZXIoZmFsc2UpXG4gIGVuZEhhbmRsZXIoKVxuXG4gIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgaGFuZGxlciwgYWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMpXG4gIGNvbnN0IHJlZ2lzdGVyU2Nyb2xsZW5kRXZlbnQgPVxuICAgIGluc3RhbmNlLm9wdGlvbnMudXNlU2Nyb2xsZW5kRXZlbnQgJiYgc3VwcG9ydHNTY3JvbGxlbmRcbiAgaWYgKHJlZ2lzdGVyU2Nyb2xsZW5kRXZlbnQpIHtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbGVuZCcsIGVuZEhhbmRsZXIsIGFkZEV2ZW50TGlzdGVuZXJPcHRpb25zKVxuICB9XG4gIHJldHVybiAoKSA9PiB7XG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBoYW5kbGVyKVxuICAgIGlmIChyZWdpc3RlclNjcm9sbGVuZEV2ZW50KSB7XG4gICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbGVuZCcsIGVuZEhhbmRsZXIpXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBvYnNlcnZlV2luZG93T2Zmc2V0ID0gKFxuICBpbnN0YW5jZTogVmlydHVhbGl6ZXI8V2luZG93LCBhbnk+LFxuICBjYjogT2JzZXJ2ZU9mZnNldENhbGxCYWNrLFxuKSA9PiB7XG4gIGNvbnN0IGVsZW1lbnQgPSBpbnN0YW5jZS5zY3JvbGxFbGVtZW50XG4gIGlmICghZWxlbWVudCkge1xuICAgIHJldHVyblxuICB9XG4gIGNvbnN0IHRhcmdldFdpbmRvdyA9IGluc3RhbmNlLnRhcmdldFdpbmRvd1xuICBpZiAoIXRhcmdldFdpbmRvdykge1xuICAgIHJldHVyblxuICB9XG5cbiAgbGV0IG9mZnNldCA9IDBcbiAgY29uc3QgZmFsbGJhY2sgPVxuICAgIGluc3RhbmNlLm9wdGlvbnMudXNlU2Nyb2xsZW5kRXZlbnQgJiYgc3VwcG9ydHNTY3JvbGxlbmRcbiAgICAgID8gKCkgPT4gdW5kZWZpbmVkXG4gICAgICA6IGRlYm91bmNlKFxuICAgICAgICAgIHRhcmdldFdpbmRvdyxcbiAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICBjYihvZmZzZXQsIGZhbHNlKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW5zdGFuY2Uub3B0aW9ucy5pc1Njcm9sbGluZ1Jlc2V0RGVsYXksXG4gICAgICAgIClcblxuICBjb25zdCBjcmVhdGVIYW5kbGVyID0gKGlzU2Nyb2xsaW5nOiBib29sZWFuKSA9PiAoKSA9PiB7XG4gICAgb2Zmc2V0ID0gZWxlbWVudFtpbnN0YW5jZS5vcHRpb25zLmhvcml6b250YWwgPyAnc2Nyb2xsWCcgOiAnc2Nyb2xsWSddXG4gICAgZmFsbGJhY2soKVxuICAgIGNiKG9mZnNldCwgaXNTY3JvbGxpbmcpXG4gIH1cbiAgY29uc3QgaGFuZGxlciA9IGNyZWF0ZUhhbmRsZXIodHJ1ZSlcbiAgY29uc3QgZW5kSGFuZGxlciA9IGNyZWF0ZUhhbmRsZXIoZmFsc2UpXG4gIGVuZEhhbmRsZXIoKVxuXG4gIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgaGFuZGxlciwgYWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMpXG4gIGNvbnN0IHJlZ2lzdGVyU2Nyb2xsZW5kRXZlbnQgPVxuICAgIGluc3RhbmNlLm9wdGlvbnMudXNlU2Nyb2xsZW5kRXZlbnQgJiYgc3VwcG9ydHNTY3JvbGxlbmRcbiAgaWYgKHJlZ2lzdGVyU2Nyb2xsZW5kRXZlbnQpIHtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbGVuZCcsIGVuZEhhbmRsZXIsIGFkZEV2ZW50TGlzdGVuZXJPcHRpb25zKVxuICB9XG4gIHJldHVybiAoKSA9PiB7XG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBoYW5kbGVyKVxuICAgIGlmIChyZWdpc3RlclNjcm9sbGVuZEV2ZW50KSB7XG4gICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbGVuZCcsIGVuZEhhbmRsZXIpXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBtZWFzdXJlRWxlbWVudCA9IDxUSXRlbUVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50PihcbiAgZWxlbWVudDogVEl0ZW1FbGVtZW50LFxuICBlbnRyeTogUmVzaXplT2JzZXJ2ZXJFbnRyeSB8IHVuZGVmaW5lZCxcbiAgaW5zdGFuY2U6IFZpcnR1YWxpemVyPGFueSwgVEl0ZW1FbGVtZW50PixcbikgPT4ge1xuICBpZiAoZW50cnk/LmJvcmRlckJveFNpemUpIHtcbiAgICBjb25zdCBib3ggPSBlbnRyeS5ib3JkZXJCb3hTaXplWzBdXG4gICAgaWYgKGJveCkge1xuICAgICAgY29uc3Qgc2l6ZSA9IE1hdGgucm91bmQoXG4gICAgICAgIGJveFtpbnN0YW5jZS5vcHRpb25zLmhvcml6b250YWwgPyAnaW5saW5lU2l6ZScgOiAnYmxvY2tTaXplJ10sXG4gICAgICApXG4gICAgICByZXR1cm4gc2l6ZVxuICAgIH1cbiAgfVxuICByZXR1cm4gTWF0aC5yb3VuZChcbiAgICBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpW1xuICAgICAgaW5zdGFuY2Uub3B0aW9ucy5ob3Jpem9udGFsID8gJ3dpZHRoJyA6ICdoZWlnaHQnXG4gICAgXSxcbiAgKVxufVxuXG5leHBvcnQgY29uc3Qgd2luZG93U2Nyb2xsID0gPFQgZXh0ZW5kcyBXaW5kb3c+KFxuICBvZmZzZXQ6IG51bWJlcixcbiAge1xuICAgIGFkanVzdG1lbnRzID0gMCxcbiAgICBiZWhhdmlvcixcbiAgfTogeyBhZGp1c3RtZW50cz86IG51bWJlcjsgYmVoYXZpb3I/OiBTY3JvbGxCZWhhdmlvciB9LFxuICBpbnN0YW5jZTogVmlydHVhbGl6ZXI8VCwgYW55PixcbikgPT4ge1xuICBjb25zdCB0b09mZnNldCA9IG9mZnNldCArIGFkanVzdG1lbnRzXG5cbiAgaW5zdGFuY2Uuc2Nyb2xsRWxlbWVudD8uc2Nyb2xsVG8/Lih7XG4gICAgW2luc3RhbmNlLm9wdGlvbnMuaG9yaXpvbnRhbCA/ICdsZWZ0JyA6ICd0b3AnXTogdG9PZmZzZXQsXG4gICAgYmVoYXZpb3IsXG4gIH0pXG59XG5cbmV4cG9ydCBjb25zdCBlbGVtZW50U2Nyb2xsID0gPFQgZXh0ZW5kcyBFbGVtZW50PihcbiAgb2Zmc2V0OiBudW1iZXIsXG4gIHtcbiAgICBhZGp1c3RtZW50cyA9IDAsXG4gICAgYmVoYXZpb3IsXG4gIH06IHsgYWRqdXN0bWVudHM/OiBudW1iZXI7IGJlaGF2aW9yPzogU2Nyb2xsQmVoYXZpb3IgfSxcbiAgaW5zdGFuY2U6IFZpcnR1YWxpemVyPFQsIGFueT4sXG4pID0+IHtcbiAgY29uc3QgdG9PZmZzZXQgPSBvZmZzZXQgKyBhZGp1c3RtZW50c1xuXG4gIGluc3RhbmNlLnNjcm9sbEVsZW1lbnQ/LnNjcm9sbFRvPy4oe1xuICAgIFtpbnN0YW5jZS5vcHRpb25zLmhvcml6b250YWwgPyAnbGVmdCcgOiAndG9wJ106IHRvT2Zmc2V0LFxuICAgIGJlaGF2aW9yLFxuICB9KVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZpcnR1YWxpemVyT3B0aW9uczxcbiAgVFNjcm9sbEVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHwgV2luZG93LFxuICBUSXRlbUVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50LFxuPiB7XG4gIC8vIFJlcXVpcmVkIGZyb20gdGhlIHVzZXJcbiAgY291bnQ6IG51bWJlclxuICBnZXRTY3JvbGxFbGVtZW50OiAoKSA9PiBUU2Nyb2xsRWxlbWVudCB8IG51bGxcbiAgZXN0aW1hdGVTaXplOiAoaW5kZXg6IG51bWJlcikgPT4gbnVtYmVyXG5cbiAgLy8gUmVxdWlyZWQgZnJvbSB0aGUgZnJhbWV3b3JrIGFkYXB0ZXIgKGJ1dCBjYW4gYmUgb3ZlcnJpZGRlbilcbiAgc2Nyb2xsVG9GbjogKFxuICAgIG9mZnNldDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgYWRqdXN0bWVudHM/OiBudW1iZXI7IGJlaGF2aW9yPzogU2Nyb2xsQmVoYXZpb3IgfSxcbiAgICBpbnN0YW5jZTogVmlydHVhbGl6ZXI8VFNjcm9sbEVsZW1lbnQsIFRJdGVtRWxlbWVudD4sXG4gICkgPT4gdm9pZFxuICBvYnNlcnZlRWxlbWVudFJlY3Q6IChcbiAgICBpbnN0YW5jZTogVmlydHVhbGl6ZXI8VFNjcm9sbEVsZW1lbnQsIFRJdGVtRWxlbWVudD4sXG4gICAgY2I6IChyZWN0OiBSZWN0KSA9PiB2b2lkLFxuICApID0+IHZvaWQgfCAoKCkgPT4gdm9pZClcbiAgb2JzZXJ2ZUVsZW1lbnRPZmZzZXQ6IChcbiAgICBpbnN0YW5jZTogVmlydHVhbGl6ZXI8VFNjcm9sbEVsZW1lbnQsIFRJdGVtRWxlbWVudD4sXG4gICAgY2I6IE9ic2VydmVPZmZzZXRDYWxsQmFjayxcbiAgKSA9PiB2b2lkIHwgKCgpID0+IHZvaWQpXG4gIC8vIE9wdGlvbmFsXG4gIGRlYnVnPzogYm9vbGVhblxuICBpbml0aWFsUmVjdD86IFJlY3RcbiAgb25DaGFuZ2U/OiAoXG4gICAgaW5zdGFuY2U6IFZpcnR1YWxpemVyPFRTY3JvbGxFbGVtZW50LCBUSXRlbUVsZW1lbnQ+LFxuICAgIHN5bmM6IGJvb2xlYW4sXG4gICkgPT4gdm9pZFxuICBtZWFzdXJlRWxlbWVudD86IChcbiAgICBlbGVtZW50OiBUSXRlbUVsZW1lbnQsXG4gICAgZW50cnk6IFJlc2l6ZU9ic2VydmVyRW50cnkgfCB1bmRlZmluZWQsXG4gICAgaW5zdGFuY2U6IFZpcnR1YWxpemVyPFRTY3JvbGxFbGVtZW50LCBUSXRlbUVsZW1lbnQ+LFxuICApID0+IG51bWJlclxuICBvdmVyc2Nhbj86IG51bWJlclxuICBob3Jpem9udGFsPzogYm9vbGVhblxuICBwYWRkaW5nU3RhcnQ/OiBudW1iZXJcbiAgcGFkZGluZ0VuZD86IG51bWJlclxuICBzY3JvbGxQYWRkaW5nU3RhcnQ/OiBudW1iZXJcbiAgc2Nyb2xsUGFkZGluZ0VuZD86IG51bWJlclxuICBpbml0aWFsT2Zmc2V0PzogbnVtYmVyIHwgKCgpID0+IG51bWJlcilcbiAgZ2V0SXRlbUtleT86IChpbmRleDogbnVtYmVyKSA9PiBLZXlcbiAgcmFuZ2VFeHRyYWN0b3I/OiAocmFuZ2U6IFJhbmdlKSA9PiBBcnJheTxudW1iZXI+XG4gIHNjcm9sbE1hcmdpbj86IG51bWJlclxuICBnYXA/OiBudW1iZXJcbiAgaW5kZXhBdHRyaWJ1dGU/OiBzdHJpbmdcbiAgaW5pdGlhbE1lYXN1cmVtZW50c0NhY2hlPzogQXJyYXk8VmlydHVhbEl0ZW0+XG4gIGxhbmVzPzogbnVtYmVyXG4gIGlzU2Nyb2xsaW5nUmVzZXREZWxheT86IG51bWJlclxuICB1c2VTY3JvbGxlbmRFdmVudD86IGJvb2xlYW5cbiAgZW5hYmxlZD86IGJvb2xlYW5cbiAgaXNSdGw/OiBib29sZWFuXG4gIHVzZUFuaW1hdGlvbkZyYW1lV2l0aFJlc2l6ZU9ic2VydmVyPzogYm9vbGVhblxufVxuXG5leHBvcnQgY2xhc3MgVmlydHVhbGl6ZXI8XG4gIFRTY3JvbGxFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB8IFdpbmRvdyxcbiAgVEl0ZW1FbGVtZW50IGV4dGVuZHMgRWxlbWVudCxcbj4ge1xuICBwcml2YXRlIHVuc3ViczogQXJyYXk8dm9pZCB8ICgoKSA9PiB2b2lkKT4gPSBbXVxuICBvcHRpb25zITogUmVxdWlyZWQ8VmlydHVhbGl6ZXJPcHRpb25zPFRTY3JvbGxFbGVtZW50LCBUSXRlbUVsZW1lbnQ+PlxuICBzY3JvbGxFbGVtZW50OiBUU2Nyb2xsRWxlbWVudCB8IG51bGwgPSBudWxsXG4gIHRhcmdldFdpbmRvdzogKFdpbmRvdyAmIHR5cGVvZiBnbG9iYWxUaGlzKSB8IG51bGwgPSBudWxsXG4gIGlzU2Nyb2xsaW5nID0gZmFsc2VcbiAgcHJpdmF0ZSBzY3JvbGxUb0luZGV4VGltZW91dElkOiBudW1iZXIgfCBudWxsID0gbnVsbFxuICBtZWFzdXJlbWVudHNDYWNoZTogQXJyYXk8VmlydHVhbEl0ZW0+ID0gW11cbiAgcHJpdmF0ZSBpdGVtU2l6ZUNhY2hlID0gbmV3IE1hcDxLZXksIG51bWJlcj4oKVxuICBwcml2YXRlIHBlbmRpbmdNZWFzdXJlZENhY2hlSW5kZXhlczogQXJyYXk8bnVtYmVyPiA9IFtdXG4gIHNjcm9sbFJlY3Q6IFJlY3QgfCBudWxsID0gbnVsbFxuICBzY3JvbGxPZmZzZXQ6IG51bWJlciB8IG51bGwgPSBudWxsXG4gIHNjcm9sbERpcmVjdGlvbjogU2Nyb2xsRGlyZWN0aW9uIHwgbnVsbCA9IG51bGxcbiAgcHJpdmF0ZSBzY3JvbGxBZGp1c3RtZW50cyA9IDBcbiAgc2hvdWxkQWRqdXN0U2Nyb2xsUG9zaXRpb25Pbkl0ZW1TaXplQ2hhbmdlOlxuICAgIHwgdW5kZWZpbmVkXG4gICAgfCAoKFxuICAgICAgICBpdGVtOiBWaXJ0dWFsSXRlbSxcbiAgICAgICAgZGVsdGE6IG51bWJlcixcbiAgICAgICAgaW5zdGFuY2U6IFZpcnR1YWxpemVyPFRTY3JvbGxFbGVtZW50LCBUSXRlbUVsZW1lbnQ+LFxuICAgICAgKSA9PiBib29sZWFuKVxuICBlbGVtZW50c0NhY2hlID0gbmV3IE1hcDxLZXksIFRJdGVtRWxlbWVudD4oKVxuICBwcml2YXRlIG9ic2VydmVyID0gKCgpID0+IHtcbiAgICBsZXQgX3JvOiBSZXNpemVPYnNlcnZlciB8IG51bGwgPSBudWxsXG5cbiAgICBjb25zdCBnZXQgPSAoKSA9PiB7XG4gICAgICBpZiAoX3JvKSB7XG4gICAgICAgIHJldHVybiBfcm9cbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLnRhcmdldFdpbmRvdyB8fCAhdGhpcy50YXJnZXRXaW5kb3cuUmVzaXplT2JzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIChfcm8gPSBuZXcgdGhpcy50YXJnZXRXaW5kb3cuUmVzaXplT2JzZXJ2ZXIoKGVudHJpZXMpID0+IHtcbiAgICAgICAgZW50cmllcy5mb3JFYWNoKChlbnRyeSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHJ1biA9ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX21lYXN1cmVFbGVtZW50KGVudHJ5LnRhcmdldCBhcyBUSXRlbUVsZW1lbnQsIGVudHJ5KVxuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLm9wdGlvbnMudXNlQW5pbWF0aW9uRnJhbWVXaXRoUmVzaXplT2JzZXJ2ZXJcbiAgICAgICAgICAgID8gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHJ1bilcbiAgICAgICAgICAgIDogcnVuKClcbiAgICAgICAgfSlcbiAgICAgIH0pKVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkaXNjb25uZWN0OiAoKSA9PiB7XG4gICAgICAgIGdldCgpPy5kaXNjb25uZWN0KClcbiAgICAgICAgX3JvID0gbnVsbFxuICAgICAgfSxcbiAgICAgIG9ic2VydmU6ICh0YXJnZXQ6IEVsZW1lbnQpID0+XG4gICAgICAgIGdldCgpPy5vYnNlcnZlKHRhcmdldCwgeyBib3g6ICdib3JkZXItYm94JyB9KSxcbiAgICAgIHVub2JzZXJ2ZTogKHRhcmdldDogRWxlbWVudCkgPT4gZ2V0KCk/LnVub2JzZXJ2ZSh0YXJnZXQpLFxuICAgIH1cbiAgfSkoKVxuICByYW5nZTogeyBzdGFydEluZGV4OiBudW1iZXI7IGVuZEluZGV4OiBudW1iZXIgfSB8IG51bGwgPSBudWxsXG5cbiAgY29uc3RydWN0b3Iob3B0czogVmlydHVhbGl6ZXJPcHRpb25zPFRTY3JvbGxFbGVtZW50LCBUSXRlbUVsZW1lbnQ+KSB7XG4gICAgdGhpcy5zZXRPcHRpb25zKG9wdHMpXG4gIH1cblxuICBzZXRPcHRpb25zID0gKG9wdHM6IFZpcnR1YWxpemVyT3B0aW9uczxUU2Nyb2xsRWxlbWVudCwgVEl0ZW1FbGVtZW50PikgPT4ge1xuICAgIE9iamVjdC5lbnRyaWVzKG9wdHMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCcpIGRlbGV0ZSAob3B0cyBhcyBhbnkpW2tleV1cbiAgICB9KVxuXG4gICAgdGhpcy5vcHRpb25zID0ge1xuICAgICAgZGVidWc6IGZhbHNlLFxuICAgICAgaW5pdGlhbE9mZnNldDogMCxcbiAgICAgIG92ZXJzY2FuOiAxLFxuICAgICAgcGFkZGluZ1N0YXJ0OiAwLFxuICAgICAgcGFkZGluZ0VuZDogMCxcbiAgICAgIHNjcm9sbFBhZGRpbmdTdGFydDogMCxcbiAgICAgIHNjcm9sbFBhZGRpbmdFbmQ6IDAsXG4gICAgICBob3Jpem9udGFsOiBmYWxzZSxcbiAgICAgIGdldEl0ZW1LZXk6IGRlZmF1bHRLZXlFeHRyYWN0b3IsXG4gICAgICByYW5nZUV4dHJhY3RvcjogZGVmYXVsdFJhbmdlRXh0cmFjdG9yLFxuICAgICAgb25DaGFuZ2U6ICgpID0+IHt9LFxuICAgICAgbWVhc3VyZUVsZW1lbnQsXG4gICAgICBpbml0aWFsUmVjdDogeyB3aWR0aDogMCwgaGVpZ2h0OiAwIH0sXG4gICAgICBzY3JvbGxNYXJnaW46IDAsXG4gICAgICBnYXA6IDAsXG4gICAgICBpbmRleEF0dHJpYnV0ZTogJ2RhdGEtaW5kZXgnLFxuICAgICAgaW5pdGlhbE1lYXN1cmVtZW50c0NhY2hlOiBbXSxcbiAgICAgIGxhbmVzOiAxLFxuICAgICAgaXNTY3JvbGxpbmdSZXNldERlbGF5OiAxNTAsXG4gICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgaXNSdGw6IGZhbHNlLFxuICAgICAgdXNlU2Nyb2xsZW5kRXZlbnQ6IGZhbHNlLFxuICAgICAgdXNlQW5pbWF0aW9uRnJhbWVXaXRoUmVzaXplT2JzZXJ2ZXI6IGZhbHNlLFxuICAgICAgLi4ub3B0cyxcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG5vdGlmeSA9IChzeW5jOiBib29sZWFuKSA9PiB7XG4gICAgdGhpcy5vcHRpb25zLm9uQ2hhbmdlPy4odGhpcywgc3luYylcbiAgfVxuXG4gIHByaXZhdGUgbWF5YmVOb3RpZnkgPSBtZW1vKFxuICAgICgpID0+IHtcbiAgICAgIHRoaXMuY2FsY3VsYXRlUmFuZ2UoKVxuXG4gICAgICByZXR1cm4gW1xuICAgICAgICB0aGlzLmlzU2Nyb2xsaW5nLFxuICAgICAgICB0aGlzLnJhbmdlID8gdGhpcy5yYW5nZS5zdGFydEluZGV4IDogbnVsbCxcbiAgICAgICAgdGhpcy5yYW5nZSA/IHRoaXMucmFuZ2UuZW5kSW5kZXggOiBudWxsLFxuICAgICAgXVxuICAgIH0sXG4gICAgKGlzU2Nyb2xsaW5nKSA9PiB7XG4gICAgICB0aGlzLm5vdGlmeShpc1Njcm9sbGluZylcbiAgICB9LFxuICAgIHtcbiAgICAgIGtleTogcHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJyAmJiAnbWF5YmVOb3RpZnknLFxuICAgICAgZGVidWc6ICgpID0+IHRoaXMub3B0aW9ucy5kZWJ1ZyxcbiAgICAgIGluaXRpYWxEZXBzOiBbXG4gICAgICAgIHRoaXMuaXNTY3JvbGxpbmcsXG4gICAgICAgIHRoaXMucmFuZ2UgPyB0aGlzLnJhbmdlLnN0YXJ0SW5kZXggOiBudWxsLFxuICAgICAgICB0aGlzLnJhbmdlID8gdGhpcy5yYW5nZS5lbmRJbmRleCA6IG51bGwsXG4gICAgICBdIGFzIFtib29sZWFuLCBudW1iZXIgfCBudWxsLCBudW1iZXIgfCBudWxsXSxcbiAgICB9LFxuICApXG5cbiAgcHJpdmF0ZSBjbGVhbnVwID0gKCkgPT4ge1xuICAgIHRoaXMudW5zdWJzLmZpbHRlcihCb29sZWFuKS5mb3JFYWNoKChkKSA9PiBkISgpKVxuICAgIHRoaXMudW5zdWJzID0gW11cbiAgICB0aGlzLm9ic2VydmVyLmRpc2Nvbm5lY3QoKVxuICAgIHRoaXMuc2Nyb2xsRWxlbWVudCA9IG51bGxcbiAgICB0aGlzLnRhcmdldFdpbmRvdyA9IG51bGxcbiAgfVxuXG4gIF9kaWRNb3VudCA9ICgpID0+IHtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgdGhpcy5jbGVhbnVwKClcbiAgICB9XG4gIH1cblxuICBfd2lsbFVwZGF0ZSA9ICgpID0+IHtcbiAgICBjb25zdCBzY3JvbGxFbGVtZW50ID0gdGhpcy5vcHRpb25zLmVuYWJsZWRcbiAgICAgID8gdGhpcy5vcHRpb25zLmdldFNjcm9sbEVsZW1lbnQoKVxuICAgICAgOiBudWxsXG5cbiAgICBpZiAodGhpcy5zY3JvbGxFbGVtZW50ICE9PSBzY3JvbGxFbGVtZW50KSB7XG4gICAgICB0aGlzLmNsZWFudXAoKVxuXG4gICAgICBpZiAoIXNjcm9sbEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5tYXliZU5vdGlmeSgpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICB0aGlzLnNjcm9sbEVsZW1lbnQgPSBzY3JvbGxFbGVtZW50XG5cbiAgICAgIGlmICh0aGlzLnNjcm9sbEVsZW1lbnQgJiYgJ293bmVyRG9jdW1lbnQnIGluIHRoaXMuc2Nyb2xsRWxlbWVudCkge1xuICAgICAgICB0aGlzLnRhcmdldFdpbmRvdyA9IHRoaXMuc2Nyb2xsRWxlbWVudC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnRhcmdldFdpbmRvdyA9IHRoaXMuc2Nyb2xsRWxlbWVudD8ud2luZG93ID8/IG51bGxcbiAgICAgIH1cblxuICAgICAgdGhpcy5lbGVtZW50c0NhY2hlLmZvckVhY2goKGNhY2hlZCkgPT4ge1xuICAgICAgICB0aGlzLm9ic2VydmVyLm9ic2VydmUoY2FjaGVkKVxuICAgICAgfSlcblxuICAgICAgdGhpcy5fc2Nyb2xsVG9PZmZzZXQodGhpcy5nZXRTY3JvbGxPZmZzZXQoKSwge1xuICAgICAgICBhZGp1c3RtZW50czogdW5kZWZpbmVkLFxuICAgICAgICBiZWhhdmlvcjogdW5kZWZpbmVkLFxuICAgICAgfSlcblxuICAgICAgdGhpcy51bnN1YnMucHVzaChcbiAgICAgICAgdGhpcy5vcHRpb25zLm9ic2VydmVFbGVtZW50UmVjdCh0aGlzLCAocmVjdCkgPT4ge1xuICAgICAgICAgIHRoaXMuc2Nyb2xsUmVjdCA9IHJlY3RcbiAgICAgICAgICB0aGlzLm1heWJlTm90aWZ5KClcbiAgICAgICAgfSksXG4gICAgICApXG5cbiAgICAgIHRoaXMudW5zdWJzLnB1c2goXG4gICAgICAgIHRoaXMub3B0aW9ucy5vYnNlcnZlRWxlbWVudE9mZnNldCh0aGlzLCAob2Zmc2V0LCBpc1Njcm9sbGluZykgPT4ge1xuICAgICAgICAgIHRoaXMuc2Nyb2xsQWRqdXN0bWVudHMgPSAwXG4gICAgICAgICAgdGhpcy5zY3JvbGxEaXJlY3Rpb24gPSBpc1Njcm9sbGluZ1xuICAgICAgICAgICAgPyB0aGlzLmdldFNjcm9sbE9mZnNldCgpIDwgb2Zmc2V0XG4gICAgICAgICAgICAgID8gJ2ZvcndhcmQnXG4gICAgICAgICAgICAgIDogJ2JhY2t3YXJkJ1xuICAgICAgICAgICAgOiBudWxsXG4gICAgICAgICAgdGhpcy5zY3JvbGxPZmZzZXQgPSBvZmZzZXRcbiAgICAgICAgICB0aGlzLmlzU2Nyb2xsaW5nID0gaXNTY3JvbGxpbmdcblxuICAgICAgICAgIHRoaXMubWF5YmVOb3RpZnkoKVxuICAgICAgICB9KSxcbiAgICAgIClcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldFNpemUgPSAoKSA9PiB7XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZW5hYmxlZCkge1xuICAgICAgdGhpcy5zY3JvbGxSZWN0ID0gbnVsbFxuICAgICAgcmV0dXJuIDBcbiAgICB9XG5cbiAgICB0aGlzLnNjcm9sbFJlY3QgPSB0aGlzLnNjcm9sbFJlY3QgPz8gdGhpcy5vcHRpb25zLmluaXRpYWxSZWN0XG5cbiAgICByZXR1cm4gdGhpcy5zY3JvbGxSZWN0W3RoaXMub3B0aW9ucy5ob3Jpem9udGFsID8gJ3dpZHRoJyA6ICdoZWlnaHQnXVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRTY3JvbGxPZmZzZXQgPSAoKSA9PiB7XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZW5hYmxlZCkge1xuICAgICAgdGhpcy5zY3JvbGxPZmZzZXQgPSBudWxsXG4gICAgICByZXR1cm4gMFxuICAgIH1cblxuICAgIHRoaXMuc2Nyb2xsT2Zmc2V0ID1cbiAgICAgIHRoaXMuc2Nyb2xsT2Zmc2V0ID8/XG4gICAgICAodHlwZW9mIHRoaXMub3B0aW9ucy5pbml0aWFsT2Zmc2V0ID09PSAnZnVuY3Rpb24nXG4gICAgICAgID8gdGhpcy5vcHRpb25zLmluaXRpYWxPZmZzZXQoKVxuICAgICAgICA6IHRoaXMub3B0aW9ucy5pbml0aWFsT2Zmc2V0KVxuXG4gICAgcmV0dXJuIHRoaXMuc2Nyb2xsT2Zmc2V0XG4gIH1cblxuICBwcml2YXRlIGdldEZ1cnRoZXN0TWVhc3VyZW1lbnQgPSAoXG4gICAgbWVhc3VyZW1lbnRzOiBBcnJheTxWaXJ0dWFsSXRlbT4sXG4gICAgaW5kZXg6IG51bWJlcixcbiAgKSA9PiB7XG4gICAgY29uc3QgZnVydGhlc3RNZWFzdXJlbWVudHNGb3VuZCA9IG5ldyBNYXA8bnVtYmVyLCB0cnVlPigpXG4gICAgY29uc3QgZnVydGhlc3RNZWFzdXJlbWVudHMgPSBuZXcgTWFwPG51bWJlciwgVmlydHVhbEl0ZW0+KClcbiAgICBmb3IgKGxldCBtID0gaW5kZXggLSAxOyBtID49IDA7IG0tLSkge1xuICAgICAgY29uc3QgbWVhc3VyZW1lbnQgPSBtZWFzdXJlbWVudHNbbV0hXG5cbiAgICAgIGlmIChmdXJ0aGVzdE1lYXN1cmVtZW50c0ZvdW5kLmhhcyhtZWFzdXJlbWVudC5sYW5lKSkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjb25zdCBwcmV2aW91c0Z1cnRoZXN0TWVhc3VyZW1lbnQgPSBmdXJ0aGVzdE1lYXN1cmVtZW50cy5nZXQoXG4gICAgICAgIG1lYXN1cmVtZW50LmxhbmUsXG4gICAgICApXG4gICAgICBpZiAoXG4gICAgICAgIHByZXZpb3VzRnVydGhlc3RNZWFzdXJlbWVudCA9PSBudWxsIHx8XG4gICAgICAgIG1lYXN1cmVtZW50LmVuZCA+IHByZXZpb3VzRnVydGhlc3RNZWFzdXJlbWVudC5lbmRcbiAgICAgICkge1xuICAgICAgICBmdXJ0aGVzdE1lYXN1cmVtZW50cy5zZXQobWVhc3VyZW1lbnQubGFuZSwgbWVhc3VyZW1lbnQpXG4gICAgICB9IGVsc2UgaWYgKG1lYXN1cmVtZW50LmVuZCA8IHByZXZpb3VzRnVydGhlc3RNZWFzdXJlbWVudC5lbmQpIHtcbiAgICAgICAgZnVydGhlc3RNZWFzdXJlbWVudHNGb3VuZC5zZXQobWVhc3VyZW1lbnQubGFuZSwgdHJ1ZSlcbiAgICAgIH1cblxuICAgICAgaWYgKGZ1cnRoZXN0TWVhc3VyZW1lbnRzRm91bmQuc2l6ZSA9PT0gdGhpcy5vcHRpb25zLmxhbmVzKSB7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1cnRoZXN0TWVhc3VyZW1lbnRzLnNpemUgPT09IHRoaXMub3B0aW9ucy5sYW5lc1xuICAgICAgPyBBcnJheS5mcm9tKGZ1cnRoZXN0TWVhc3VyZW1lbnRzLnZhbHVlcygpKS5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgaWYgKGEuZW5kID09PSBiLmVuZCkge1xuICAgICAgICAgICAgcmV0dXJuIGEuaW5kZXggLSBiLmluZGV4XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGEuZW5kIC0gYi5lbmRcbiAgICAgICAgfSlbMF1cbiAgICAgIDogdW5kZWZpbmVkXG4gIH1cblxuICBwcml2YXRlIGdldE1lYXN1cmVtZW50T3B0aW9ucyA9IG1lbW8oXG4gICAgKCkgPT4gW1xuICAgICAgdGhpcy5vcHRpb25zLmNvdW50LFxuICAgICAgdGhpcy5vcHRpb25zLnBhZGRpbmdTdGFydCxcbiAgICAgIHRoaXMub3B0aW9ucy5zY3JvbGxNYXJnaW4sXG4gICAgICB0aGlzLm9wdGlvbnMuZ2V0SXRlbUtleSxcbiAgICAgIHRoaXMub3B0aW9ucy5lbmFibGVkLFxuICAgIF0sXG4gICAgKGNvdW50LCBwYWRkaW5nU3RhcnQsIHNjcm9sbE1hcmdpbiwgZ2V0SXRlbUtleSwgZW5hYmxlZCkgPT4ge1xuICAgICAgdGhpcy5wZW5kaW5nTWVhc3VyZWRDYWNoZUluZGV4ZXMgPSBbXVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY291bnQsXG4gICAgICAgIHBhZGRpbmdTdGFydCxcbiAgICAgICAgc2Nyb2xsTWFyZ2luLFxuICAgICAgICBnZXRJdGVtS2V5LFxuICAgICAgICBlbmFibGVkLFxuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAga2V5OiBmYWxzZSxcbiAgICB9LFxuICApXG5cbiAgcHJpdmF0ZSBnZXRNZWFzdXJlbWVudHMgPSBtZW1vKFxuICAgICgpID0+IFt0aGlzLmdldE1lYXN1cmVtZW50T3B0aW9ucygpLCB0aGlzLml0ZW1TaXplQ2FjaGVdLFxuICAgIChcbiAgICAgIHsgY291bnQsIHBhZGRpbmdTdGFydCwgc2Nyb2xsTWFyZ2luLCBnZXRJdGVtS2V5LCBlbmFibGVkIH0sXG4gICAgICBpdGVtU2l6ZUNhY2hlLFxuICAgICkgPT4ge1xuICAgICAgaWYgKCFlbmFibGVkKSB7XG4gICAgICAgIHRoaXMubWVhc3VyZW1lbnRzQ2FjaGUgPSBbXVxuICAgICAgICB0aGlzLml0ZW1TaXplQ2FjaGUuY2xlYXIoKVxuICAgICAgICByZXR1cm4gW11cbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubWVhc3VyZW1lbnRzQ2FjaGUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRoaXMubWVhc3VyZW1lbnRzQ2FjaGUgPSB0aGlzLm9wdGlvbnMuaW5pdGlhbE1lYXN1cmVtZW50c0NhY2hlXG4gICAgICAgIHRoaXMubWVhc3VyZW1lbnRzQ2FjaGUuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgIHRoaXMuaXRlbVNpemVDYWNoZS5zZXQoaXRlbS5rZXksIGl0ZW0uc2l6ZSlcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWluID1cbiAgICAgICAgdGhpcy5wZW5kaW5nTWVhc3VyZWRDYWNoZUluZGV4ZXMubGVuZ3RoID4gMFxuICAgICAgICAgID8gTWF0aC5taW4oLi4udGhpcy5wZW5kaW5nTWVhc3VyZWRDYWNoZUluZGV4ZXMpXG4gICAgICAgICAgOiAwXG4gICAgICB0aGlzLnBlbmRpbmdNZWFzdXJlZENhY2hlSW5kZXhlcyA9IFtdXG5cbiAgICAgIGNvbnN0IG1lYXN1cmVtZW50cyA9IHRoaXMubWVhc3VyZW1lbnRzQ2FjaGUuc2xpY2UoMCwgbWluKVxuXG4gICAgICBmb3IgKGxldCBpID0gbWluOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICBjb25zdCBrZXkgPSBnZXRJdGVtS2V5KGkpXG5cbiAgICAgICAgY29uc3QgZnVydGhlc3RNZWFzdXJlbWVudCA9XG4gICAgICAgICAgdGhpcy5vcHRpb25zLmxhbmVzID09PSAxXG4gICAgICAgICAgICA/IG1lYXN1cmVtZW50c1tpIC0gMV1cbiAgICAgICAgICAgIDogdGhpcy5nZXRGdXJ0aGVzdE1lYXN1cmVtZW50KG1lYXN1cmVtZW50cywgaSlcblxuICAgICAgICBjb25zdCBzdGFydCA9IGZ1cnRoZXN0TWVhc3VyZW1lbnRcbiAgICAgICAgICA/IGZ1cnRoZXN0TWVhc3VyZW1lbnQuZW5kICsgdGhpcy5vcHRpb25zLmdhcFxuICAgICAgICAgIDogcGFkZGluZ1N0YXJ0ICsgc2Nyb2xsTWFyZ2luXG5cbiAgICAgICAgY29uc3QgbWVhc3VyZWRTaXplID0gaXRlbVNpemVDYWNoZS5nZXQoa2V5KVxuICAgICAgICBjb25zdCBzaXplID1cbiAgICAgICAgICB0eXBlb2YgbWVhc3VyZWRTaXplID09PSAnbnVtYmVyJ1xuICAgICAgICAgICAgPyBtZWFzdXJlZFNpemVcbiAgICAgICAgICAgIDogdGhpcy5vcHRpb25zLmVzdGltYXRlU2l6ZShpKVxuXG4gICAgICAgIGNvbnN0IGVuZCA9IHN0YXJ0ICsgc2l6ZVxuXG4gICAgICAgIGNvbnN0IGxhbmUgPSBmdXJ0aGVzdE1lYXN1cmVtZW50XG4gICAgICAgICAgPyBmdXJ0aGVzdE1lYXN1cmVtZW50LmxhbmVcbiAgICAgICAgICA6IGkgJSB0aGlzLm9wdGlvbnMubGFuZXNcblxuICAgICAgICBtZWFzdXJlbWVudHNbaV0gPSB7XG4gICAgICAgICAgaW5kZXg6IGksXG4gICAgICAgICAgc3RhcnQsXG4gICAgICAgICAgc2l6ZSxcbiAgICAgICAgICBlbmQsXG4gICAgICAgICAga2V5LFxuICAgICAgICAgIGxhbmUsXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5tZWFzdXJlbWVudHNDYWNoZSA9IG1lYXN1cmVtZW50c1xuXG4gICAgICByZXR1cm4gbWVhc3VyZW1lbnRzXG4gICAgfSxcbiAgICB7XG4gICAgICBrZXk6IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiYgJ2dldE1lYXN1cmVtZW50cycsXG4gICAgICBkZWJ1ZzogKCkgPT4gdGhpcy5vcHRpb25zLmRlYnVnLFxuICAgIH0sXG4gIClcblxuICBjYWxjdWxhdGVSYW5nZSA9IG1lbW8oXG4gICAgKCkgPT4gW1xuICAgICAgdGhpcy5nZXRNZWFzdXJlbWVudHMoKSxcbiAgICAgIHRoaXMuZ2V0U2l6ZSgpLFxuICAgICAgdGhpcy5nZXRTY3JvbGxPZmZzZXQoKSxcbiAgICAgIHRoaXMub3B0aW9ucy5sYW5lcyxcbiAgICBdLFxuICAgIChtZWFzdXJlbWVudHMsIG91dGVyU2l6ZSwgc2Nyb2xsT2Zmc2V0LCBsYW5lcykgPT4ge1xuICAgICAgcmV0dXJuICh0aGlzLnJhbmdlID1cbiAgICAgICAgbWVhc3VyZW1lbnRzLmxlbmd0aCA+IDAgJiYgb3V0ZXJTaXplID4gMFxuICAgICAgICAgID8gY2FsY3VsYXRlUmFuZ2Uoe1xuICAgICAgICAgICAgICBtZWFzdXJlbWVudHMsXG4gICAgICAgICAgICAgIG91dGVyU2l6ZSxcbiAgICAgICAgICAgICAgc2Nyb2xsT2Zmc2V0LFxuICAgICAgICAgICAgICBsYW5lcyxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgOiBudWxsKVxuICAgIH0sXG4gICAge1xuICAgICAga2V5OiBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmICdjYWxjdWxhdGVSYW5nZScsXG4gICAgICBkZWJ1ZzogKCkgPT4gdGhpcy5vcHRpb25zLmRlYnVnLFxuICAgIH0sXG4gIClcblxuICBnZXRWaXJ0dWFsSW5kZXhlcyA9IG1lbW8oXG4gICAgKCkgPT4ge1xuICAgICAgbGV0IHN0YXJ0SW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsXG4gICAgICBsZXQgZW5kSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsXG4gICAgICBjb25zdCByYW5nZSA9IHRoaXMuY2FsY3VsYXRlUmFuZ2UoKVxuICAgICAgaWYgKHJhbmdlKSB7XG4gICAgICAgIHN0YXJ0SW5kZXggPSByYW5nZS5zdGFydEluZGV4XG4gICAgICAgIGVuZEluZGV4ID0gcmFuZ2UuZW5kSW5kZXhcbiAgICAgIH1cbiAgICAgIHRoaXMubWF5YmVOb3RpZnkudXBkYXRlRGVwcyhbdGhpcy5pc1Njcm9sbGluZywgc3RhcnRJbmRleCwgZW5kSW5kZXhdKVxuICAgICAgcmV0dXJuIFtcbiAgICAgICAgdGhpcy5vcHRpb25zLnJhbmdlRXh0cmFjdG9yLFxuICAgICAgICB0aGlzLm9wdGlvbnMub3ZlcnNjYW4sXG4gICAgICAgIHRoaXMub3B0aW9ucy5jb3VudCxcbiAgICAgICAgc3RhcnRJbmRleCxcbiAgICAgICAgZW5kSW5kZXgsXG4gICAgICBdXG4gICAgfSxcbiAgICAocmFuZ2VFeHRyYWN0b3IsIG92ZXJzY2FuLCBjb3VudCwgc3RhcnRJbmRleCwgZW5kSW5kZXgpID0+IHtcbiAgICAgIHJldHVybiBzdGFydEluZGV4ID09PSBudWxsIHx8IGVuZEluZGV4ID09PSBudWxsXG4gICAgICAgID8gW11cbiAgICAgICAgOiByYW5nZUV4dHJhY3Rvcih7XG4gICAgICAgICAgICBzdGFydEluZGV4LFxuICAgICAgICAgICAgZW5kSW5kZXgsXG4gICAgICAgICAgICBvdmVyc2NhbixcbiAgICAgICAgICAgIGNvdW50LFxuICAgICAgICAgIH0pXG4gICAgfSxcbiAgICB7XG4gICAgICBrZXk6IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiYgJ2dldFZpcnR1YWxJbmRleGVzJyxcbiAgICAgIGRlYnVnOiAoKSA9PiB0aGlzLm9wdGlvbnMuZGVidWcsXG4gICAgfSxcbiAgKVxuXG4gIGluZGV4RnJvbUVsZW1lbnQgPSAobm9kZTogVEl0ZW1FbGVtZW50KSA9PiB7XG4gICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IHRoaXMub3B0aW9ucy5pbmRleEF0dHJpYnV0ZVxuICAgIGNvbnN0IGluZGV4U3RyID0gbm9kZS5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSlcblxuICAgIGlmICghaW5kZXhTdHIpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYE1pc3NpbmcgYXR0cmlidXRlIG5hbWUgJyR7YXR0cmlidXRlTmFtZX09e2luZGV4fScgb24gbWVhc3VyZWQgZWxlbWVudC5gLFxuICAgICAgKVxuICAgICAgcmV0dXJuIC0xXG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcnNlSW50KGluZGV4U3RyLCAxMClcbiAgfVxuXG4gIHByaXZhdGUgX21lYXN1cmVFbGVtZW50ID0gKFxuICAgIG5vZGU6IFRJdGVtRWxlbWVudCxcbiAgICBlbnRyeTogUmVzaXplT2JzZXJ2ZXJFbnRyeSB8IHVuZGVmaW5lZCxcbiAgKSA9PiB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLmluZGV4RnJvbUVsZW1lbnQobm9kZSlcbiAgICBjb25zdCBpdGVtID0gdGhpcy5tZWFzdXJlbWVudHNDYWNoZVtpbmRleF1cbiAgICBpZiAoIWl0ZW0pIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBjb25zdCBrZXkgPSBpdGVtLmtleVxuICAgIGNvbnN0IHByZXZOb2RlID0gdGhpcy5lbGVtZW50c0NhY2hlLmdldChrZXkpXG5cbiAgICBpZiAocHJldk5vZGUgIT09IG5vZGUpIHtcbiAgICAgIGlmIChwcmV2Tm9kZSkge1xuICAgICAgICB0aGlzLm9ic2VydmVyLnVub2JzZXJ2ZShwcmV2Tm9kZSlcbiAgICAgIH1cbiAgICAgIHRoaXMub2JzZXJ2ZXIub2JzZXJ2ZShub2RlKVxuICAgICAgdGhpcy5lbGVtZW50c0NhY2hlLnNldChrZXksIG5vZGUpXG4gICAgfVxuXG4gICAgaWYgKG5vZGUuaXNDb25uZWN0ZWQpIHtcbiAgICAgIHRoaXMucmVzaXplSXRlbShpbmRleCwgdGhpcy5vcHRpb25zLm1lYXN1cmVFbGVtZW50KG5vZGUsIGVudHJ5LCB0aGlzKSlcbiAgICB9XG4gIH1cblxuICByZXNpemVJdGVtID0gKGluZGV4OiBudW1iZXIsIHNpemU6IG51bWJlcikgPT4ge1xuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLm1lYXN1cmVtZW50c0NhY2hlW2luZGV4XVxuICAgIGlmICghaXRlbSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvbnN0IGl0ZW1TaXplID0gdGhpcy5pdGVtU2l6ZUNhY2hlLmdldChpdGVtLmtleSkgPz8gaXRlbS5zaXplXG4gICAgY29uc3QgZGVsdGEgPSBzaXplIC0gaXRlbVNpemVcblxuICAgIGlmIChkZWx0YSAhPT0gMCkge1xuICAgICAgaWYgKFxuICAgICAgICB0aGlzLnNob3VsZEFkanVzdFNjcm9sbFBvc2l0aW9uT25JdGVtU2l6ZUNoYW5nZSAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyB0aGlzLnNob3VsZEFkanVzdFNjcm9sbFBvc2l0aW9uT25JdGVtU2l6ZUNoYW5nZShpdGVtLCBkZWx0YSwgdGhpcylcbiAgICAgICAgICA6IGl0ZW0uc3RhcnQgPCB0aGlzLmdldFNjcm9sbE9mZnNldCgpICsgdGhpcy5zY3JvbGxBZGp1c3RtZW50c1xuICAgICAgKSB7XG4gICAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmIHRoaXMub3B0aW9ucy5kZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUuaW5mbygnY29ycmVjdGlvbicsIGRlbHRhKVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc2Nyb2xsVG9PZmZzZXQodGhpcy5nZXRTY3JvbGxPZmZzZXQoKSwge1xuICAgICAgICAgIGFkanVzdG1lbnRzOiAodGhpcy5zY3JvbGxBZGp1c3RtZW50cyArPSBkZWx0YSksXG4gICAgICAgICAgYmVoYXZpb3I6IHVuZGVmaW5lZCxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZW5kaW5nTWVhc3VyZWRDYWNoZUluZGV4ZXMucHVzaChpdGVtLmluZGV4KVxuICAgICAgdGhpcy5pdGVtU2l6ZUNhY2hlID0gbmV3IE1hcCh0aGlzLml0ZW1TaXplQ2FjaGUuc2V0KGl0ZW0ua2V5LCBzaXplKSlcblxuICAgICAgdGhpcy5ub3RpZnkoZmFsc2UpXG4gICAgfVxuICB9XG5cbiAgbWVhc3VyZUVsZW1lbnQgPSAobm9kZTogVEl0ZW1FbGVtZW50IHwgbnVsbCB8IHVuZGVmaW5lZCkgPT4ge1xuICAgIGlmICghbm9kZSkge1xuICAgICAgdGhpcy5lbGVtZW50c0NhY2hlLmZvckVhY2goKGNhY2hlZCwga2V5KSA9PiB7XG4gICAgICAgIGlmICghY2FjaGVkLmlzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgdGhpcy5vYnNlcnZlci51bm9ic2VydmUoY2FjaGVkKVxuICAgICAgICAgIHRoaXMuZWxlbWVudHNDYWNoZS5kZWxldGUoa2V5KVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5fbWVhc3VyZUVsZW1lbnQobm9kZSwgdW5kZWZpbmVkKVxuICB9XG5cbiAgZ2V0VmlydHVhbEl0ZW1zID0gbWVtbyhcbiAgICAoKSA9PiBbdGhpcy5nZXRWaXJ0dWFsSW5kZXhlcygpLCB0aGlzLmdldE1lYXN1cmVtZW50cygpXSxcbiAgICAoaW5kZXhlcywgbWVhc3VyZW1lbnRzKSA9PiB7XG4gICAgICBjb25zdCB2aXJ0dWFsSXRlbXM6IEFycmF5PFZpcnR1YWxJdGVtPiA9IFtdXG5cbiAgICAgIGZvciAobGV0IGsgPSAwLCBsZW4gPSBpbmRleGVzLmxlbmd0aDsgayA8IGxlbjsgaysrKSB7XG4gICAgICAgIGNvbnN0IGkgPSBpbmRleGVzW2tdIVxuICAgICAgICBjb25zdCBtZWFzdXJlbWVudCA9IG1lYXN1cmVtZW50c1tpXSFcblxuICAgICAgICB2aXJ0dWFsSXRlbXMucHVzaChtZWFzdXJlbWVudClcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHZpcnR1YWxJdGVtc1xuICAgIH0sXG4gICAge1xuICAgICAga2V5OiBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmICdnZXRWaXJ0dWFsSXRlbXMnLFxuICAgICAgZGVidWc6ICgpID0+IHRoaXMub3B0aW9ucy5kZWJ1ZyxcbiAgICB9LFxuICApXG5cbiAgZ2V0VmlydHVhbEl0ZW1Gb3JPZmZzZXQgPSAob2Zmc2V0OiBudW1iZXIpID0+IHtcbiAgICBjb25zdCBtZWFzdXJlbWVudHMgPSB0aGlzLmdldE1lYXN1cmVtZW50cygpXG4gICAgaWYgKG1lYXN1cmVtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9XG4gICAgcmV0dXJuIG5vdFVuZGVmaW5lZChcbiAgICAgIG1lYXN1cmVtZW50c1tcbiAgICAgICAgZmluZE5lYXJlc3RCaW5hcnlTZWFyY2goXG4gICAgICAgICAgMCxcbiAgICAgICAgICBtZWFzdXJlbWVudHMubGVuZ3RoIC0gMSxcbiAgICAgICAgICAoaW5kZXg6IG51bWJlcikgPT4gbm90VW5kZWZpbmVkKG1lYXN1cmVtZW50c1tpbmRleF0pLnN0YXJ0LFxuICAgICAgICAgIG9mZnNldCxcbiAgICAgICAgKVxuICAgICAgXSxcbiAgICApXG4gIH1cblxuICBnZXRPZmZzZXRGb3JBbGlnbm1lbnQgPSAoXG4gICAgdG9PZmZzZXQ6IG51bWJlcixcbiAgICBhbGlnbjogU2Nyb2xsQWxpZ25tZW50LFxuICAgIGl0ZW1TaXplID0gMCxcbiAgKSA9PiB7XG4gICAgY29uc3Qgc2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpXG4gICAgY29uc3Qgc2Nyb2xsT2Zmc2V0ID0gdGhpcy5nZXRTY3JvbGxPZmZzZXQoKVxuXG4gICAgaWYgKGFsaWduID09PSAnYXV0bycpIHtcbiAgICAgIGFsaWduID0gdG9PZmZzZXQgPj0gc2Nyb2xsT2Zmc2V0ICsgc2l6ZSA/ICdlbmQnIDogJ3N0YXJ0J1xuICAgIH1cblxuICAgIGlmIChhbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIC8vIFdoZW4gYWxpZ25pbmcgdG8gYSBwYXJ0aWN1bGFyIGl0ZW0gKGUuZy4gd2l0aCBzY3JvbGxUb0luZGV4KSxcbiAgICAgIC8vIGFkanVzdCBvZmZzZXQgYnkgdGhlIHNpemUgb2YgdGhlIGl0ZW0gdG8gY2VudGVyIG9uIHRoZSBpdGVtXG4gICAgICB0b09mZnNldCArPSAoaXRlbVNpemUgLSBzaXplKSAvIDJcbiAgICB9IGVsc2UgaWYgKGFsaWduID09PSAnZW5kJykge1xuICAgICAgdG9PZmZzZXQgLT0gc2l6ZVxuICAgIH1cblxuICAgIGNvbnN0IHNjcm9sbFNpemVQcm9wID0gdGhpcy5vcHRpb25zLmhvcml6b250YWxcbiAgICAgID8gJ3Njcm9sbFdpZHRoJ1xuICAgICAgOiAnc2Nyb2xsSGVpZ2h0J1xuICAgIGNvbnN0IHNjcm9sbFNpemUgPSB0aGlzLnNjcm9sbEVsZW1lbnRcbiAgICAgID8gJ2RvY3VtZW50JyBpbiB0aGlzLnNjcm9sbEVsZW1lbnRcbiAgICAgICAgPyB0aGlzLnNjcm9sbEVsZW1lbnQuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50W3Njcm9sbFNpemVQcm9wXVxuICAgICAgICA6IHRoaXMuc2Nyb2xsRWxlbWVudFtzY3JvbGxTaXplUHJvcF1cbiAgICAgIDogMFxuXG4gICAgY29uc3QgbWF4T2Zmc2V0ID0gc2Nyb2xsU2l6ZSAtIHNpemVcblxuICAgIHJldHVybiBNYXRoLm1heChNYXRoLm1pbihtYXhPZmZzZXQsIHRvT2Zmc2V0KSwgMClcbiAgfVxuXG4gIGdldE9mZnNldEZvckluZGV4ID0gKGluZGV4OiBudW1iZXIsIGFsaWduOiBTY3JvbGxBbGlnbm1lbnQgPSAnYXV0bycpID0+IHtcbiAgICBpbmRleCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGluZGV4LCB0aGlzLm9wdGlvbnMuY291bnQgLSAxKSlcblxuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLm1lYXN1cmVtZW50c0NhY2hlW2luZGV4XVxuICAgIGlmICghaXRlbSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxuICAgIH1cblxuICAgIGNvbnN0IHNpemUgPSB0aGlzLmdldFNpemUoKVxuICAgIGNvbnN0IHNjcm9sbE9mZnNldCA9IHRoaXMuZ2V0U2Nyb2xsT2Zmc2V0KClcblxuICAgIGlmIChhbGlnbiA9PT0gJ2F1dG8nKSB7XG4gICAgICBpZiAoaXRlbS5lbmQgPj0gc2Nyb2xsT2Zmc2V0ICsgc2l6ZSAtIHRoaXMub3B0aW9ucy5zY3JvbGxQYWRkaW5nRW5kKSB7XG4gICAgICAgIGFsaWduID0gJ2VuZCdcbiAgICAgIH0gZWxzZSBpZiAoaXRlbS5zdGFydCA8PSBzY3JvbGxPZmZzZXQgKyB0aGlzLm9wdGlvbnMuc2Nyb2xsUGFkZGluZ1N0YXJ0KSB7XG4gICAgICAgIGFsaWduID0gJ3N0YXJ0J1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFtzY3JvbGxPZmZzZXQsIGFsaWduXSBhcyBjb25zdFxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHRvT2Zmc2V0ID1cbiAgICAgIGFsaWduID09PSAnZW5kJ1xuICAgICAgICA/IGl0ZW0uZW5kICsgdGhpcy5vcHRpb25zLnNjcm9sbFBhZGRpbmdFbmRcbiAgICAgICAgOiBpdGVtLnN0YXJ0IC0gdGhpcy5vcHRpb25zLnNjcm9sbFBhZGRpbmdTdGFydFxuXG4gICAgcmV0dXJuIFtcbiAgICAgIHRoaXMuZ2V0T2Zmc2V0Rm9yQWxpZ25tZW50KHRvT2Zmc2V0LCBhbGlnbiwgaXRlbS5zaXplKSxcbiAgICAgIGFsaWduLFxuICAgIF0gYXMgY29uc3RcbiAgfVxuXG4gIHByaXZhdGUgaXNEeW5hbWljTW9kZSA9ICgpID0+IHRoaXMuZWxlbWVudHNDYWNoZS5zaXplID4gMFxuXG4gIHByaXZhdGUgY2FuY2VsU2Nyb2xsVG9JbmRleCA9ICgpID0+IHtcbiAgICBpZiAodGhpcy5zY3JvbGxUb0luZGV4VGltZW91dElkICE9PSBudWxsICYmIHRoaXMudGFyZ2V0V2luZG93KSB7XG4gICAgICB0aGlzLnRhcmdldFdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5zY3JvbGxUb0luZGV4VGltZW91dElkKVxuICAgICAgdGhpcy5zY3JvbGxUb0luZGV4VGltZW91dElkID0gbnVsbFxuICAgIH1cbiAgfVxuXG4gIHNjcm9sbFRvT2Zmc2V0ID0gKFxuICAgIHRvT2Zmc2V0OiBudW1iZXIsXG4gICAgeyBhbGlnbiA9ICdzdGFydCcsIGJlaGF2aW9yIH06IFNjcm9sbFRvT2Zmc2V0T3B0aW9ucyA9IHt9LFxuICApID0+IHtcbiAgICB0aGlzLmNhbmNlbFNjcm9sbFRvSW5kZXgoKVxuXG4gICAgaWYgKGJlaGF2aW9yID09PSAnc21vb3RoJyAmJiB0aGlzLmlzRHluYW1pY01vZGUoKSkge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAnVGhlIGBzbW9vdGhgIHNjcm9sbCBiZWhhdmlvciBpcyBub3QgZnVsbHkgc3VwcG9ydGVkIHdpdGggZHluYW1pYyBzaXplLicsXG4gICAgICApXG4gICAgfVxuXG4gICAgdGhpcy5fc2Nyb2xsVG9PZmZzZXQodGhpcy5nZXRPZmZzZXRGb3JBbGlnbm1lbnQodG9PZmZzZXQsIGFsaWduKSwge1xuICAgICAgYWRqdXN0bWVudHM6IHVuZGVmaW5lZCxcbiAgICAgIGJlaGF2aW9yLFxuICAgIH0pXG4gIH1cblxuICBzY3JvbGxUb0luZGV4ID0gKFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgeyBhbGlnbjogaW5pdGlhbEFsaWduID0gJ2F1dG8nLCBiZWhhdmlvciB9OiBTY3JvbGxUb0luZGV4T3B0aW9ucyA9IHt9LFxuICApID0+IHtcbiAgICBpbmRleCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGluZGV4LCB0aGlzLm9wdGlvbnMuY291bnQgLSAxKSlcblxuICAgIHRoaXMuY2FuY2VsU2Nyb2xsVG9JbmRleCgpXG5cbiAgICBpZiAoYmVoYXZpb3IgPT09ICdzbW9vdGgnICYmIHRoaXMuaXNEeW5hbWljTW9kZSgpKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdUaGUgYHNtb290aGAgc2Nyb2xsIGJlaGF2aW9yIGlzIG5vdCBmdWxseSBzdXBwb3J0ZWQgd2l0aCBkeW5hbWljIHNpemUuJyxcbiAgICAgIClcbiAgICB9XG5cbiAgICBjb25zdCBvZmZzZXRBbmRBbGlnbiA9IHRoaXMuZ2V0T2Zmc2V0Rm9ySW5kZXgoaW5kZXgsIGluaXRpYWxBbGlnbilcbiAgICBpZiAoIW9mZnNldEFuZEFsaWduKSByZXR1cm5cblxuICAgIGNvbnN0IFtvZmZzZXQsIGFsaWduXSA9IG9mZnNldEFuZEFsaWduXG5cbiAgICB0aGlzLl9zY3JvbGxUb09mZnNldChvZmZzZXQsIHsgYWRqdXN0bWVudHM6IHVuZGVmaW5lZCwgYmVoYXZpb3IgfSlcblxuICAgIGlmIChiZWhhdmlvciAhPT0gJ3Ntb290aCcgJiYgdGhpcy5pc0R5bmFtaWNNb2RlKCkgJiYgdGhpcy50YXJnZXRXaW5kb3cpIHtcbiAgICAgIHRoaXMuc2Nyb2xsVG9JbmRleFRpbWVvdXRJZCA9IHRoaXMudGFyZ2V0V2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcm9sbFRvSW5kZXhUaW1lb3V0SWQgPSBudWxsXG5cbiAgICAgICAgY29uc3QgZWxlbWVudEluRE9NID0gdGhpcy5lbGVtZW50c0NhY2hlLmhhcyhcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuZ2V0SXRlbUtleShpbmRleCksXG4gICAgICAgIClcblxuICAgICAgICBpZiAoZWxlbWVudEluRE9NKSB7XG4gICAgICAgICAgY29uc3QgW2xhdGVzdE9mZnNldF0gPSBub3RVbmRlZmluZWQoXG4gICAgICAgICAgICB0aGlzLmdldE9mZnNldEZvckluZGV4KGluZGV4LCBhbGlnbiksXG4gICAgICAgICAgKVxuXG4gICAgICAgICAgaWYgKCFhcHByb3hFcXVhbChsYXRlc3RPZmZzZXQsIHRoaXMuZ2V0U2Nyb2xsT2Zmc2V0KCkpKSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFRvSW5kZXgoaW5kZXgsIHsgYWxpZ24sIGJlaGF2aW9yIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2Nyb2xsVG9JbmRleChpbmRleCwgeyBhbGlnbiwgYmVoYXZpb3IgfSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICBzY3JvbGxCeSA9IChkZWx0YTogbnVtYmVyLCB7IGJlaGF2aW9yIH06IFNjcm9sbFRvT2Zmc2V0T3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgdGhpcy5jYW5jZWxTY3JvbGxUb0luZGV4KClcblxuICAgIGlmIChiZWhhdmlvciA9PT0gJ3Ntb290aCcgJiYgdGhpcy5pc0R5bmFtaWNNb2RlKCkpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ1RoZSBgc21vb3RoYCBzY3JvbGwgYmVoYXZpb3IgaXMgbm90IGZ1bGx5IHN1cHBvcnRlZCB3aXRoIGR5bmFtaWMgc2l6ZS4nLFxuICAgICAgKVxuICAgIH1cblxuICAgIHRoaXMuX3Njcm9sbFRvT2Zmc2V0KHRoaXMuZ2V0U2Nyb2xsT2Zmc2V0KCkgKyBkZWx0YSwge1xuICAgICAgYWRqdXN0bWVudHM6IHVuZGVmaW5lZCxcbiAgICAgIGJlaGF2aW9yLFxuICAgIH0pXG4gIH1cblxuICBnZXRUb3RhbFNpemUgPSAoKSA9PiB7XG4gICAgY29uc3QgbWVhc3VyZW1lbnRzID0gdGhpcy5nZXRNZWFzdXJlbWVudHMoKVxuXG4gICAgbGV0IGVuZDogbnVtYmVyXG4gICAgLy8gSWYgdGhlcmUgYXJlIG5vIG1lYXN1cmVtZW50cywgc2V0IHRoZSBlbmQgdG8gcGFkZGluZ1N0YXJ0XG4gICAgLy8gSWYgdGhlcmUgaXMgb25seSBvbmUgbGFuZSwgdXNlIHRoZSBsYXN0IG1lYXN1cmVtZW50J3MgZW5kXG4gICAgLy8gT3RoZXJ3aXNlIGZpbmQgdGhlIG1heGltdW0gZW5kIHZhbHVlIGFtb25nIGFsbCBtZWFzdXJlbWVudHNcbiAgICBpZiAobWVhc3VyZW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZW5kID0gdGhpcy5vcHRpb25zLnBhZGRpbmdTdGFydFxuICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLmxhbmVzID09PSAxKSB7XG4gICAgICBlbmQgPSBtZWFzdXJlbWVudHNbbWVhc3VyZW1lbnRzLmxlbmd0aCAtIDFdPy5lbmQgPz8gMFxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBlbmRCeUxhbmUgPSBBcnJheTxudW1iZXIgfCBudWxsPih0aGlzLm9wdGlvbnMubGFuZXMpLmZpbGwobnVsbClcbiAgICAgIGxldCBlbmRJbmRleCA9IG1lYXN1cmVtZW50cy5sZW5ndGggLSAxXG4gICAgICB3aGlsZSAoZW5kSW5kZXggPj0gMCAmJiBlbmRCeUxhbmUuc29tZSgodmFsKSA9PiB2YWwgPT09IG51bGwpKSB7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSBtZWFzdXJlbWVudHNbZW5kSW5kZXhdIVxuICAgICAgICBpZiAoZW5kQnlMYW5lW2l0ZW0ubGFuZV0gPT09IG51bGwpIHtcbiAgICAgICAgICBlbmRCeUxhbmVbaXRlbS5sYW5lXSA9IGl0ZW0uZW5kXG4gICAgICAgIH1cblxuICAgICAgICBlbmRJbmRleC0tXG4gICAgICB9XG5cbiAgICAgIGVuZCA9IE1hdGgubWF4KC4uLmVuZEJ5TGFuZS5maWx0ZXIoKHZhbCk6IHZhbCBpcyBudW1iZXIgPT4gdmFsICE9PSBudWxsKSlcbiAgICB9XG5cbiAgICByZXR1cm4gTWF0aC5tYXgoXG4gICAgICBlbmQgLSB0aGlzLm9wdGlvbnMuc2Nyb2xsTWFyZ2luICsgdGhpcy5vcHRpb25zLnBhZGRpbmdFbmQsXG4gICAgICAwLFxuICAgIClcbiAgfVxuXG4gIHByaXZhdGUgX3Njcm9sbFRvT2Zmc2V0ID0gKFxuICAgIG9mZnNldDogbnVtYmVyLFxuICAgIHtcbiAgICAgIGFkanVzdG1lbnRzLFxuICAgICAgYmVoYXZpb3IsXG4gICAgfToge1xuICAgICAgYWRqdXN0bWVudHM6IG51bWJlciB8IHVuZGVmaW5lZFxuICAgICAgYmVoYXZpb3I6IFNjcm9sbEJlaGF2aW9yIHwgdW5kZWZpbmVkXG4gICAgfSxcbiAgKSA9PiB7XG4gICAgdGhpcy5vcHRpb25zLnNjcm9sbFRvRm4ob2Zmc2V0LCB7IGJlaGF2aW9yLCBhZGp1c3RtZW50cyB9LCB0aGlzKVxuICB9XG5cbiAgbWVhc3VyZSA9ICgpID0+IHtcbiAgICB0aGlzLml0ZW1TaXplQ2FjaGUgPSBuZXcgTWFwKClcbiAgICB0aGlzLm5vdGlmeShmYWxzZSlcbiAgfVxufVxuXG5jb25zdCBmaW5kTmVhcmVzdEJpbmFyeVNlYXJjaCA9IChcbiAgbG93OiBudW1iZXIsXG4gIGhpZ2g6IG51bWJlcixcbiAgZ2V0Q3VycmVudFZhbHVlOiAoaTogbnVtYmVyKSA9PiBudW1iZXIsXG4gIHZhbHVlOiBudW1iZXIsXG4pID0+IHtcbiAgd2hpbGUgKGxvdyA8PSBoaWdoKSB7XG4gICAgY29uc3QgbWlkZGxlID0gKChsb3cgKyBoaWdoKSAvIDIpIHwgMFxuICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGdldEN1cnJlbnRWYWx1ZShtaWRkbGUpXG5cbiAgICBpZiAoY3VycmVudFZhbHVlIDwgdmFsdWUpIHtcbiAgICAgIGxvdyA9IG1pZGRsZSArIDFcbiAgICB9IGVsc2UgaWYgKGN1cnJlbnRWYWx1ZSA+IHZhbHVlKSB7XG4gICAgICBoaWdoID0gbWlkZGxlIC0gMVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWlkZGxlXG4gICAgfVxuICB9XG5cbiAgaWYgKGxvdyA+IDApIHtcbiAgICByZXR1cm4gbG93IC0gMVxuICB9IGVsc2Uge1xuICAgIHJldHVybiAwXG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlUmFuZ2Uoe1xuICBtZWFzdXJlbWVudHMsXG4gIG91dGVyU2l6ZSxcbiAgc2Nyb2xsT2Zmc2V0LFxuICBsYW5lcyxcbn06IHtcbiAgbWVhc3VyZW1lbnRzOiBBcnJheTxWaXJ0dWFsSXRlbT5cbiAgb3V0ZXJTaXplOiBudW1iZXJcbiAgc2Nyb2xsT2Zmc2V0OiBudW1iZXJcbiAgbGFuZXM6IG51bWJlclxufSkge1xuICBjb25zdCBsYXN0SW5kZXggPSBtZWFzdXJlbWVudHMubGVuZ3RoIC0gMVxuICBjb25zdCBnZXRPZmZzZXQgPSAoaW5kZXg6IG51bWJlcikgPT4gbWVhc3VyZW1lbnRzW2luZGV4XSEuc3RhcnRcblxuICAvLyBoYW5kbGUgY2FzZSB3aGVuIGl0ZW0gY291bnQgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGxhbmVzXG4gIGlmIChtZWFzdXJlbWVudHMubGVuZ3RoIDw9IGxhbmVzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXJ0SW5kZXg6IDAsXG4gICAgICBlbmRJbmRleDogbGFzdEluZGV4LFxuICAgIH1cbiAgfVxuXG4gIGxldCBzdGFydEluZGV4ID0gZmluZE5lYXJlc3RCaW5hcnlTZWFyY2goXG4gICAgMCxcbiAgICBsYXN0SW5kZXgsXG4gICAgZ2V0T2Zmc2V0LFxuICAgIHNjcm9sbE9mZnNldCxcbiAgKVxuICBsZXQgZW5kSW5kZXggPSBzdGFydEluZGV4XG5cbiAgaWYgKGxhbmVzID09PSAxKSB7XG4gICAgd2hpbGUgKFxuICAgICAgZW5kSW5kZXggPCBsYXN0SW5kZXggJiZcbiAgICAgIG1lYXN1cmVtZW50c1tlbmRJbmRleF0hLmVuZCA8IHNjcm9sbE9mZnNldCArIG91dGVyU2l6ZVxuICAgICkge1xuICAgICAgZW5kSW5kZXgrK1xuICAgIH1cbiAgfSBlbHNlIGlmIChsYW5lcyA+IDEpIHtcbiAgICAvLyBFeHBhbmQgZm9yd2FyZCB1bnRpbCB3ZSBpbmNsdWRlIHRoZSB2aXNpYmxlIGl0ZW1zIGZyb20gYWxsIGxhbmVzXG4gICAgLy8gd2hpY2ggYXJlIGNsb3NlciB0byB0aGUgZW5kIG9mIHRoZSB2aXJ0dWFsaXplciB3aW5kb3dcbiAgICBjb25zdCBlbmRQZXJMYW5lID0gQXJyYXkobGFuZXMpLmZpbGwoMClcbiAgICB3aGlsZSAoXG4gICAgICBlbmRJbmRleCA8IGxhc3RJbmRleCAmJlxuICAgICAgZW5kUGVyTGFuZS5zb21lKChwb3MpID0+IHBvcyA8IHNjcm9sbE9mZnNldCArIG91dGVyU2l6ZSlcbiAgICApIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSBtZWFzdXJlbWVudHNbZW5kSW5kZXhdIVxuICAgICAgZW5kUGVyTGFuZVtpdGVtLmxhbmVdID0gaXRlbS5lbmRcbiAgICAgIGVuZEluZGV4KytcbiAgICB9XG5cbiAgICAvLyBFeHBhbmQgYmFja3dhcmQgdW50aWwgd2UgaW5jbHVkZSBhbGwgbGFuZXMnIHZpc2libGUgaXRlbXNcbiAgICAvLyBjbG9zZXIgdG8gdGhlIHRvcFxuICAgIGNvbnN0IHN0YXJ0UGVyTGFuZSA9IEFycmF5KGxhbmVzKS5maWxsKHNjcm9sbE9mZnNldCArIG91dGVyU2l6ZSlcbiAgICB3aGlsZSAoc3RhcnRJbmRleCA+PSAwICYmIHN0YXJ0UGVyTGFuZS5zb21lKChwb3MpID0+IHBvcyA+PSBzY3JvbGxPZmZzZXQpKSB7XG4gICAgICBjb25zdCBpdGVtID0gbWVhc3VyZW1lbnRzW3N0YXJ0SW5kZXhdIVxuICAgICAgc3RhcnRQZXJMYW5lW2l0ZW0ubGFuZV0gPSBpdGVtLnN0YXJ0XG4gICAgICBzdGFydEluZGV4LS1cbiAgICB9XG5cbiAgICAvLyBBbGlnbiBzdGFydEluZGV4IHRvIHRoZSBiZWdpbm5pbmcgb2YgaXRzIGxhbmVcbiAgICBzdGFydEluZGV4ID0gTWF0aC5tYXgoMCwgc3RhcnRJbmRleCAtIChzdGFydEluZGV4ICUgbGFuZXMpKVxuICAgIC8vIEFsaWduIGVuZEluZGV4IHRvIHRoZSBlbmQgb2YgaXRzIGxhbmVcbiAgICBlbmRJbmRleCA9IE1hdGgubWluKGxhc3RJbmRleCwgZW5kSW5kZXggKyAobGFuZXMgLSAxIC0gKGVuZEluZGV4ICUgbGFuZXMpKSlcbiAgfVxuXG4gIHJldHVybiB7IHN0YXJ0SW5kZXgsIGVuZEluZGV4IH1cbn1cbiJdLCJmaWxlIjoiRDovc3BlY2tsZS1zZXJ2ZXIvcGFja2FnZXMvdWktY29tcG9uZW50cy9ub2RlX21vZHVsZXMvQHRhbnN0YWNrL3ZpcnR1YWwtY29yZS9kaXN0L2VzbS9pbmRleC5qcyIsInhfZ29vZ2xlX2lnbm9yZUxpc3QiOlswXX0=