UNPKG

@cloukit/pagination

Version:

574 lines (559 loc) 70.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@cloukit/theme'), require('@angular/core'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('@cloukit/pagination', ['exports', '@cloukit/theme', '@angular/core', '@angular/common'], factory) : (factory((global.cloukit = global.cloukit || {}, global.cloukit.pagination = {}),global.theme,global.ng.core,global.ng.common)); }(this, (function (exports,theme,core,common) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /*! * @license MIT * Copyright (c) 2017 Bernhard Grünewaldt - codeclou.io * https://github.com/cloukit/legal */ var PaginationButtonClickEvent = /** @class */ (function () { function PaginationButtonClickEvent(type, page) { this.type = type; this.page = page; } return PaginationButtonClickEvent; }()); /** @enum {number} */ var PaginationButtonType = { normal: 1, previous: 2, next: 3, }; PaginationButtonType[PaginationButtonType.normal] = 'normal'; PaginationButtonType[PaginationButtonType.previous] = 'previous'; PaginationButtonType[PaginationButtonType.next] = 'next'; var PaginationItem = /** @class */ (function () { function PaginationItem(page, isActive, isFiller, label) { this.page = page; this.isActive = isActive; this.isFiller = isFiller; this.label = label; } return PaginationItem; }()); var Ui = /** @class */ (function () { function Ui() { } Ui.elements = { filler: 'filler', button: 'button', wrapper: 'wrapper', }; Ui.states = { normal: 'normal', active: 'active', disabled: 'disabled', }; Ui.modifier = { base: 'base', hover: 'hover', }; return Ui; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var CloukitPaginationComponentThemeDefault = /** @class */ (function (_super) { __extends(CloukitPaginationComponentThemeDefault, _super); function CloukitPaginationComponentThemeDefault() { var _this = _super.call(this) || this; // // WRAPPER // _this.buildStyle(Ui.elements.wrapper, Ui.states.normal, Ui.modifier.base) .withStyles(( /** @type {?} */({ display: 'flex', }))); // // BUTTON // _this.buildStyle(Ui.elements.button, Ui.states.normal, Ui.modifier.base) .withStyles(( /** @type {?} */({ alignSelf: 'center', display: 'inline-flex', flexWrap: 'nowrap', maxWidth: '100%', color: '#0052cc', textDecoration: 'none', fontStyle: 'normal', fontSize: 'inherit', margin: 0, outline: 'none', textAlign: 'center', userSelect: 'none', verticalAlign: 'middle', whiteSpace: 'nowrap', boxSizing: 'border-box', padding: '2px 6px 3px', border: 0, backgroundColor: 'transparent', cursor: 'pointer', }))); _this.buildStyle(Ui.elements.button, Ui.states.active, Ui.modifier.base) .inheritFrom(Ui.elements.button, Ui.states.normal, Ui.modifier.base) .withStyles(( /** @type {?} */({ backgroundColor: '#0052cc', color: '#ffffff', cursor: 'default', }))); _this.buildStyle(Ui.elements.button, Ui.states.normal, Ui.modifier.hover) .inheritFrom(Ui.elements.button, Ui.states.normal, Ui.modifier.base) .withStyles(( /** @type {?} */({ textDecoration: 'underline', }))); _this.buildStyle(Ui.elements.button, Ui.states.disabled, Ui.modifier.base) .inheritFrom(Ui.elements.button, Ui.states.normal, Ui.modifier.base) .withStyles(( /** @type {?} */({ color: '#777', cursor: 'not-allowed', }))); // // FILLER // _this.buildStyle(Ui.elements.filler, Ui.states.normal, Ui.modifier.base) .inheritFrom(Ui.elements.button, Ui.states.normal, Ui.modifier.base) .withStyles(( /** @type {?} */({ color: '#555', cursor: 'default', }))); _this.buildStyle(Ui.elements.filler, Ui.states.disabled, Ui.modifier.base) .inheritFrom(Ui.elements.filler, Ui.states.normal, Ui.modifier.base) .withStyles(( /** @type {?} */({ color: '#efefef', cursor: 'not-allowed', }))); return _this; } return CloukitPaginationComponentThemeDefault; }(theme.CloukitComponentTheme)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ // // HELPER FUNCTIONS // /** @type {?} */ var createFiller = function () { return new PaginationItem(-1, false, true, '...'); }; /** @type {?} */ var createAnItem = function (page, active) { return new PaginationItem(page, active, false, "" + page); }; /** * Provides the pages with a total of seven. See Unit Test. * Examples: * CASE 1: 1 2 3 *4* 5 6 7 * 1 2 3 *4* 5 * CASE 2: 1 2 3 *4* 5 .. 50 * CASE 3: 1 .. 46 *47* 48 49 50 * CASE 4: 1 .. 49 *50* 51 .. 90 * @type {?} */ var calculatePaginationItems = function (total, current) { /** @type {?} */ var paginationItems = []; if (total === undefined || total === null || current === undefined || current === null) { return paginationItems; } // // CASE 1: Total is smaller or equal seven // if (total <= 7) { for (var i = 1; i <= total; i++) { paginationItems.push(new PaginationItem(i, current === i, false, "" + i)); } } else // // CASE 2: Total is greater than seven AND page is in range of [1-4] // if (total > 7 && current <= 4) { for (var i = 1; i <= 5; i++) { paginationItems.push(createAnItem(i, current === i)); } paginationItems.push(createFiller()); paginationItems.push(createAnItem(total, false)); } else // // CASE 3: Total is greater than seven AND page is greater than four AND page is near total // if (total > 7 && current > 4 && current + 3 >= total) { paginationItems.push(createAnItem(1, false)); paginationItems.push(createFiller()); for (var i = total - 4; i <= total; i++) { paginationItems.push(createAnItem(i, current === i)); } } else // // CASE 4: Total is greater than seven AND page is greater than four // if (total > 7 && current > 4) { paginationItems.push(createAnItem(1, false)); paginationItems.push(createFiller()); paginationItems.push(createAnItem(current - 1, false)); paginationItems.push(createAnItem(current, true)); paginationItems.push(createAnItem(current + 1, false)); paginationItems.push(createFiller()); paginationItems.push(createAnItem(total, false)); } // // END // return paginationItems; }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * Pagination Component. * * Just use this inside your templates: * * ```html * <cloukit-pagination ...></cloukit-pagination> * ``` */ var CloukitPaginationComponent = /** @class */ (function () { function CloukitPaginationComponent(themeService) { this.themeService = themeService; /** * External way to disable the whole pagination e.g. * during loading external data */ this.disabled = false; /** * Event emitted, when page is clicked. */ this.onPageSelect = new core.EventEmitter(); this.PaginationButtonType = PaginationButtonType; this.state = { pages: [] }; this.themeSelected = this.themeService.getComponentTheme('pagination'); } /** * @param {?} element * @return {?} */ CloukitPaginationComponent.prototype.getStyle = /** * @param {?} element * @return {?} */ function (element) { /** @type {?} */ var style = this.themeSelected.getStyle(element, 'normal', 'base'); return this.themeService.prefixStyle(style); }; /** * @overrides OnChanges * @hidden */ /** * \@overrides OnChanges * @hidden * @return {?} */ CloukitPaginationComponent.prototype.ngOnChanges = /** * \@overrides OnChanges * @hidden * @return {?} */ function () { if (this.theme !== undefined && this.theme !== null) { this.themeSelected = this.themeService.getComponentTheme(this.theme); if (this.themeSelected === null) { console.log("WARN: requested theme " + this.theme + " does not exist. Falling back to default theme for pagination."); this.themeSelected = this.themeService.getComponentTheme('pagination'); } } this.state.pages = calculatePaginationItems(this.total, this.current); }; /** * @param {?} event * @return {?} */ CloukitPaginationComponent.prototype.selectPage = /** * @param {?} event * @return {?} */ function (event) { if (event.type === PaginationButtonType['previous'] && this.isPreviousPossible()) { this.onPageSelect.emit(this.current - 1); } else if (event.type === PaginationButtonType['next'] && this.isNextPossible()) { this.onPageSelect.emit(this.current + 1); } else if (event.type === PaginationButtonType['normal']) { this.onPageSelect.emit(event.page); } }; /** * @return {?} */ CloukitPaginationComponent.prototype.previousDummyPaginationItem = /** * @return {?} */ function () { /** @type {?} */ var label = 'Prev'; if (this.labelPrev !== undefined && this.labelPrev !== null) { label = this.labelPrev; } return new PaginationItem(-1, false, false, label); }; /** * @return {?} */ CloukitPaginationComponent.prototype.nextDummyPaginationItem = /** * @return {?} */ function () { /** @type {?} */ var label = 'Next'; if (this.labelNext !== undefined && this.labelNext !== null) { label = this.labelNext; } return new PaginationItem(-1, false, false, label); }; /** * @return {?} */ CloukitPaginationComponent.prototype.isPreviousPossible = /** * @return {?} */ function () { return this.current > 1; }; /** * @return {?} */ CloukitPaginationComponent.prototype.isNextPossible = /** * @return {?} */ function () { return this.current < this.total; }; CloukitPaginationComponent.decorators = [ { type: core.Component, args: [{ selector: 'cloukit-pagination', template: "\n <div [ngStyle]=\"getStyle('wrapper').style\">\n <cloukit-pagination-button\n [disabled]=\"!isPreviousPossible() || disabled\"\n [paginationItem]=\"previousDummyPaginationItem()\"\n [themeSelected]=\"themeSelected\"\n [type]=\"PaginationButtonType['previous']\"\n (clicked)=\"selectPage($event)\"\n ></cloukit-pagination-button>\n <cloukit-pagination-button\n *ngFor=\"let page of state.pages\"\n [disabled]=\"disabled\"\n [paginationItem]=\"page\"\n [themeSelected]=\"themeSelected\"\n [type]=\"PaginationButtonType['normal']\"\n (clicked)=\"selectPage($event)\"\n ></cloukit-pagination-button>\n <cloukit-pagination-button\n [disabled]=\"!isNextPossible() || disabled\"\n [paginationItem]=\"nextDummyPaginationItem()\"\n [themeSelected]=\"themeSelected\"\n [type]=\"PaginationButtonType['next']\"\n (clicked)=\"selectPage($event)\"\n ></cloukit-pagination-button>\n </div>" }] } ]; /** @nocollapse */ CloukitPaginationComponent.ctorParameters = function () { return [ { type: theme.CloukitThemeService } ]; }; CloukitPaginationComponent.propDecorators = { theme: [{ type: core.Input }], total: [{ type: core.Input }], current: [{ type: core.Input }], disabled: [{ type: core.Input }], labelNext: [{ type: core.Input }], labelPrev: [{ type: core.Input }], onPageSelect: [{ type: core.Output }] }; return CloukitPaginationComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var CloukitPaginationButtonComponent = /** @class */ (function () { function CloukitPaginationButtonComponent(themeService) { this.themeService = themeService; this.clicked = new core.EventEmitter(); this.isMouseStillOver = false; } /** * @param {?} pageItem * @return {?} */ CloukitPaginationButtonComponent.transform = /** * @param {?} pageItem * @return {?} */ function (pageItem) { if (pageItem === undefined || pageItem === null) { return new theme.UiElement(Ui.elements.filler, Ui.states.disabled, Ui.modifier.base); } /** @type {?} */ var uiElement = pageItem.isFiller ? Ui.elements.filler : Ui.elements.button; /** @type {?} */ var uiState = pageItem.isActive ? Ui.states.active : Ui.states.normal; return new theme.UiElement(uiElement, uiState, Ui.modifier.base); }; /** * @return {?} */ CloukitPaginationButtonComponent.prototype.updateStyle = /** * @return {?} */ function () { /** @type {?} */ var style = this.themeSelected.getUiStyle(this.ui); if (style !== null) { this.style = this.themeService.prefixStyle(style); } }; /** * @return {?} */ CloukitPaginationButtonComponent.prototype.ngOnChanges = /** * @return {?} */ function () { // retain mouseEnter and mouseLeave modifier changes! /** @type {?} */ var modifier = null; if (this.ui !== null && this.ui !== undefined) { modifier = this.ui.modifier; } this.ui = CloukitPaginationButtonComponent.transform(this.paginationItem); if (modifier !== null && this.isMouseStillOver) { this.ui.modifier = modifier; } if (this.disabled === true) { this.ui.state = Ui.states.disabled; this.ui.modifier = Ui.modifier.base; } this.updateStyle(); }; /** * @return {?} */ CloukitPaginationButtonComponent.prototype.mouseEnter = /** * @return {?} */ function () { this.ui.modifier = Ui.modifier.hover; this.isMouseStillOver = true; this.updateStyle(); }; /** * @return {?} */ CloukitPaginationButtonComponent.prototype.mouseLeave = /** * @return {?} */ function () { this.ui.modifier = Ui.modifier.base; this.isMouseStillOver = false; this.updateStyle(); }; /** * @return {?} */ CloukitPaginationButtonComponent.prototype.doClick = /** * @return {?} */ function () { if (!this.paginationItem.isFiller) { this.clicked.emit(new PaginationButtonClickEvent(this.type, this.paginationItem.page)); } }; CloukitPaginationButtonComponent.decorators = [ { type: core.Component, args: [{ selector: 'cloukit-pagination-button', template: "\n <button\n type=\"button\"\n [disabled]=\"disabled\"\n [ngStyle]=\"style?.style\"\n (click)=\"doClick()\"\n (mouseenter)=\"mouseEnter()\"\n (mouseleave)=\"mouseLeave()\"\n >\n {{paginationItem.label}}\n </button>" }] } ]; /** @nocollapse */ CloukitPaginationButtonComponent.ctorParameters = function () { return [ { type: theme.CloukitThemeService } ]; }; CloukitPaginationButtonComponent.propDecorators = { disabled: [{ type: core.Input }], type: [{ type: core.Input }], paginationItem: [{ type: core.Input }], themeSelected: [{ type: core.Input }], clicked: [{ type: core.Output }] }; return CloukitPaginationButtonComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var CloukitPaginationModule = /** @class */ (function () { function CloukitPaginationModule(themeService) { this.themeService = themeService; if (this.themeService.getComponentTheme('pagination') === null) { this.themeService.registerComponentTheme('pagination', new CloukitPaginationComponentThemeDefault()); } } CloukitPaginationModule.decorators = [ { type: core.NgModule, args: [{ imports: [common.CommonModule], exports: [CloukitPaginationComponent], declarations: [CloukitPaginationComponent, CloukitPaginationButtonComponent], },] } ]; /** @nocollapse */ CloukitPaginationModule.ctorParameters = function () { return [ { type: theme.CloukitThemeService } ]; }; return CloukitPaginationModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ exports.CloukitPaginationComponentThemeDefault = CloukitPaginationComponentThemeDefault; exports.CloukitPaginationComponent = CloukitPaginationComponent; exports.CloukitPaginationModule = CloukitPaginationModule; exports.PaginationButtonClickEvent = PaginationButtonClickEvent; exports.PaginationButtonType = PaginationButtonType; exports.PaginationItem = PaginationItem; exports.Ui = Ui; exports.CloukitPaginationButtonComponent = CloukitPaginationButtonComponent; exports.calculatePaginationItems = calculatePaginationItems; exports.createFiller = createFiller; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvdWtpdC1wYWdpbmF0aW9uLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy90c2xpYi90c2xpYi5lczYuanMiLCJuZzovL0BjbG91a2l0L3BhZ2luYXRpb24vbGliL3BhZ2luYXRpb24ubW9kZWwudHMiLCJuZzovL0BjbG91a2l0L3BhZ2luYXRpb24vbGliL3BhZ2luYXRpb24udGhlbWUudHMiLCJuZzovL0BjbG91a2l0L3BhZ2luYXRpb24vbGliL2xvZ2ljL3BhZ2luYXRpb24taGVscGVyLnRzIiwibmc6Ly9AY2xvdWtpdC9wYWdpbmF0aW9uL2xpYi9wYWdpbmF0aW9uLmNvbXBvbmVudC50cyIsIm5nOi8vQGNsb3VraXQvcGFnaW5hdGlvbi9saWIvY2hpbGRyZW4vcGFnaW5hdGlvbi1idXR0b24uY29tcG9uZW50LnRzIiwibmc6Ly9AY2xvdWtpdC9wYWdpbmF0aW9uL2xpYi9wYWdpbmF0aW9uLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZVxyXG50aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZVxyXG5MaWNlbnNlIGF0IGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxyXG5cclxuVEhJUyBDT0RFIElTIFBST1ZJREVEIE9OIEFOICpBUyBJUyogQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxyXG5LSU5ELCBFSVRIRVIgRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgV0lUSE9VVCBMSU1JVEFUSU9OIEFOWSBJTVBMSUVEXHJcbldBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBUSVRMRSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsXHJcbk1FUkNIQU5UQUJMSVRZIE9SIE5PTi1JTkZSSU5HRU1FTlQuXHJcblxyXG5TZWUgdGhlIEFwYWNoZSBWZXJzaW9uIDIuMCBMaWNlbnNlIGZvciBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcclxuYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDApXHJcbiAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUocmVzdWx0LnZhbHVlKTsgfSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcclxuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XHJcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xyXG4gICAgICAgIHdoaWxlIChfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgZXhwb3J0cykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAoIWV4cG9ydHMuaGFzT3duUHJvcGVydHkocCkpIGV4cG9ydHNbcF0gPSBtW3BdO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IG4gPT09IFwicmV0dXJuXCIgfSA6IGYgPyBmKHYpIDogdjsgfSA6IGY7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNWYWx1ZXMobykge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBtID0gb1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0sIGk7XHJcbiAgICByZXR1cm4gbSA/IG0uY2FsbChvKSA6IChvID0gdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpLCBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaSk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCBkLCB2KSB7IFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGZ1bmN0aW9uKHYpIHsgcmVzb2x2ZSh7IHZhbHVlOiB2LCBkb25lOiBkIH0pOyB9LCByZWplY3QpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSByZXN1bHRba10gPSBtb2Rba107XHJcbiAgICByZXN1bHQuZGVmYXVsdCA9IG1vZDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcbiIsIi8qIVxuICogQGxpY2Vuc2UgTUlUXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTcgQmVybmhhcmQgR3LDg8K8bmV3YWxkdCAtIGNvZGVjbG91LmlvXG4gKiBodHRwczovL2dpdGh1Yi5jb20vY2xvdWtpdC9sZWdhbFxuICovXG5cbmV4cG9ydCBjbGFzcyBQYWdpbmF0aW9uQnV0dG9uQ2xpY2tFdmVudCB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyB0eXBlOiBQYWdpbmF0aW9uQnV0dG9uVHlwZSwgcHVibGljIHBhZ2U6IG51bWJlcikge31cbn1cblxuZXhwb3J0IGVudW0gUGFnaW5hdGlvbkJ1dHRvblR5cGUge1xuICBub3JtYWwgPSAxLFxuICBwcmV2aW91cyA9IDIsXG4gIG5leHQgPSAzLFxufVxuXG5leHBvcnQgY2xhc3MgUGFnaW5hdGlvbkl0ZW0ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcGFnZTogbnVtYmVyLFxuICAgIHB1YmxpYyBpc0FjdGl2ZTogYm9vbGVhbixcbiAgICBwdWJsaWMgaXNGaWxsZXI6IGJvb2xlYW4sXG4gICAgcHVibGljIGxhYmVsOiBzdHJpbmcpIHt9XG59XG5cbmV4cG9ydCBjbGFzcyBVaSB7XG4gIHB1YmxpYyBzdGF0aWMgZWxlbWVudHM6IGFueSA9IHtcbiAgICBmaWxsZXI6ICdmaWxsZXInLFxuICAgIGJ1dHRvbjogJ2J1dHRvbicsXG4gICAgd3JhcHBlcjogJ3dyYXBwZXInLFxuICB9O1xuICBwdWJsaWMgc3RhdGljIHN0YXRlczogYW55ID0ge1xuICAgIG5vcm1hbDogJ25vcm1hbCcsXG4gICAgYWN0aXZlOiAnYWN0aXZlJyxcbiAgICBkaXNhYmxlZDogJ2Rpc2FibGVkJyxcbiAgfTtcbiAgcHVibGljIHN0YXRpYyBtb2RpZmllcjogYW55ID0ge1xuICAgIGJhc2U6ICdiYXNlJyxcbiAgICBob3ZlcjogJ2hvdmVyJyxcbiAgfTtcbn1cbiIsIi8qIVxuICogQGxpY2Vuc2UgTUlUXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTcgQmVybmhhcmQgR3LDg8K8bmV3YWxkdCAtIGNvZGVjbG91LmlvXG4gKiBodHRwczovL2dpdGh1Yi5jb20vY2xvdWtpdC9sZWdhbFxuICovXG5pbXBvcnQgeyBDbG91a2l0QmFzZUNzc0RlZmluaXRpb25zLCBDbG91a2l0Q29tcG9uZW50VGhlbWUgfSBmcm9tICdAY2xvdWtpdC90aGVtZSc7XG5pbXBvcnQgeyBVaSB9IGZyb20gJy4vcGFnaW5hdGlvbi5tb2RlbCc7XG5cbmV4cG9ydCBjbGFzcyBDbG91a2l0UGFnaW5hdGlvbkNvbXBvbmVudFRoZW1lRGVmYXVsdCBleHRlbmRzIENsb3VraXRDb21wb25lbnRUaGVtZSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgICAvL1xuICAgIC8vIFdSQVBQRVJcbiAgICAvL1xuICAgIHRoaXMuYnVpbGRTdHlsZShVaS5lbGVtZW50cy53cmFwcGVyLCBVaS5zdGF0ZXMubm9ybWFsLCBVaS5tb2RpZmllci5iYXNlKVxuICAgICAgLndpdGhTdHlsZXMoPENsb3VraXRCYXNlQ3NzRGVmaW5pdGlvbnM+e1xuICAgICAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgICB9KTtcblxuICAgIC8vXG4gICAgLy8gQlVUVE9OXG4gICAgLy9cbiAgICB0aGlzLmJ1aWxkU3R5bGUoVWkuZWxlbWVudHMuYnV0dG9uLCBVaS5zdGF0ZXMubm9ybWFsLCBVaS5tb2RpZmllci5iYXNlKVxuICAgICAgLndpdGhTdHlsZXMoPENsb3VraXRCYXNlQ3NzRGVmaW5pdGlvbnM+e1xuICAgICAgICBhbGlnblNlbGY6ICdjZW50ZXInLFxuICAgICAgICBkaXNwbGF5OiAnaW5saW5lLWZsZXgnLFxuICAgICAgICBmbGV4V3JhcDogJ25vd3JhcCcsXG4gICAgICAgIG1heFdpZHRoOiAnMTAwJScsXG4gICAgICAgIGNvbG9yOiAnIzAwNTJjYycsXG4gICAgICAgIHRleHREZWNvcmF0aW9uOiAnbm9uZScsXG4gICAgICAgIGZvbnRTdHlsZTogJ25vcm1hbCcsXG4gICAgICAgIGZvbnRTaXplOiAnaW5oZXJpdCcsXG4gICAgICAgIG1hcmdpbjogMCxcbiAgICAgICAgb3V0bGluZTogJ25vbmUnLFxuICAgICAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICAgICAgICB1c2VyU2VsZWN0OiAnbm9uZScsXG4gICAgICAgIHZlcnRpY2FsQWxpZ246ICdtaWRkbGUnLFxuICAgICAgICB3aGl0ZVNwYWNlOiAnbm93cmFwJyxcbiAgICAgICAgYm94U2l6aW5nOiAnYm9yZGVyLWJveCcsXG4gICAgICAgIHBhZGRpbmc6ICcycHggNnB4IDNweCcsXG4gICAgICAgIGJvcmRlcjogMCxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnLFxuICAgICAgICBjdXJzb3I6ICdwb2ludGVyJyxcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5idWlsZFN0eWxlKFVpLmVsZW1lbnRzLmJ1dHRvbiwgVWkuc3RhdGVzLmFjdGl2ZSwgVWkubW9kaWZpZXIuYmFzZSlcbiAgICAgIC5pbmhlcml0RnJvbShVaS5lbGVtZW50cy5idXR0b24sIFVpLnN0YXRlcy5ub3JtYWwsIFVpLm1vZGlmaWVyLmJhc2UpXG4gICAgICAud2l0aFN0eWxlcyg8Q2xvdWtpdEJhc2VDc3NEZWZpbml0aW9ucz57XG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogJyMwMDUyY2MnLFxuICAgICAgICBjb2xvcjogJyNmZmZmZmYnLFxuICAgICAgICBjdXJzb3I6ICdkZWZhdWx0JyxcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5idWlsZFN0eWxlKFVpLmVsZW1lbnRzLmJ1dHRvbiwgVWkuc3RhdGVzLm5vcm1hbCwgVWkubW9kaWZpZXIuaG92ZXIpXG4gICAgICAuaW5oZXJpdEZyb20oVWkuZWxlbWVudHMuYnV0dG9uLCBVaS5zdGF0ZXMubm9ybWFsLCBVaS5tb2RpZmllci5iYXNlKVxuICAgICAgLndpdGhTdHlsZXMoPENsb3VraXRCYXNlQ3NzRGVmaW5pdGlvbnM+e1xuICAgICAgICB0ZXh0RGVjb3JhdGlvbjogJ3VuZGVybGluZScsXG4gICAgICB9KTtcblxuICAgIHRoaXMuYnVpbGRTdHlsZShVaS5lbGVtZW50cy5idXR0b24sIFVpLnN0YXRlcy5kaXNhYmxlZCwgVWkubW9kaWZpZXIuYmFzZSlcbiAgICAgIC5pbmhlcml0RnJvbShVaS5lbGVtZW50cy5idXR0b24sIFVpLnN0YXRlcy5ub3JtYWwsIFVpLm1vZGlmaWVyLmJhc2UpXG4gICAgICAud2l0aFN0eWxlcyg8Q2xvdWtpdEJhc2VDc3NEZWZpbml0aW9ucz57XG4gICAgICAgIGNvbG9yOiAnIzc3NycsXG4gICAgICAgIGN1cnNvcjogJ25vdC1hbGxvd2VkJyxcbiAgICAgIH0pO1xuXG4gICAgLy9cbiAgICAvLyBGSUxMRVJcbiAgICAvL1xuICAgIHRoaXMuYnVpbGRTdHlsZShVaS5lbGVtZW50cy5maWxsZXIsIFVpLnN0YXRlcy5ub3JtYWwsIFVpLm1vZGlmaWVyLmJhc2UpXG4gICAgICAuaW5oZXJpdEZyb20oVWkuZWxlbWVudHMuYnV0dG9uLCBVaS5zdGF0ZXMubm9ybWFsLCBVaS5tb2RpZmllci5iYXNlKVxuICAgICAgLndpdGhTdHlsZXMoPENsb3VraXRCYXNlQ3NzRGVmaW5pdGlvbnM+e1xuICAgICAgICBjb2xvcjogJyM1NTUnLFxuICAgICAgICBjdXJzb3I6ICdkZWZhdWx0JyxcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5idWlsZFN0eWxlKFVpLmVsZW1lbnRzLmZpbGxlciwgVWkuc3RhdGVzLmRpc2FibGVkLCBVaS5tb2RpZmllci5iYXNlKVxuICAgICAgLmluaGVyaXRGcm9tKFVpLmVsZW1lbnRzLmZpbGxlciwgVWkuc3RhdGVzLm5vcm1hbCwgVWkubW9kaWZpZXIuYmFzZSlcbiAgICAgIC53aXRoU3R5bGVzKDxDbG91a2l0QmFzZUNzc0RlZmluaXRpb25zPntcbiAgICAgICAgY29sb3I6ICcjZWZlZmVmJyxcbiAgICAgICAgY3Vyc29yOiAnbm90LWFsbG93ZWQnLFxuICAgICAgfSk7XG4gIH1cblxufVxuXG4iLCIvKiFcbiAqIEBsaWNlbnNlIE1JVFxuICogQ29weXJpZ2h0IChjKSAyMDE3IEJlcm5oYXJkIEdyw4PCvG5ld2FsZHQgLSBjb2RlY2xvdS5pb1xuICogaHR0cHM6Ly9naXRodWIuY29tL2Nsb3VraXQvbGVnYWxcbiAqL1xuaW1wb3J0IHsgUGFnaW5hdGlvbkl0ZW0gfSBmcm9tICcuLi9wYWdpbmF0aW9uLm1vZGVsJztcblxuLy9cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vXG5jb25zdCBjcmVhdGVGaWxsZXIgPSAoKSA9PiBuZXcgUGFnaW5hdGlvbkl0ZW0oLTEsIGZhbHNlLCB0cnVlLCAnLi4uJyk7XG5jb25zdCBjcmVhdGVBbkl0ZW0gPSAocGFnZTogbnVtYmVyLCBhY3RpdmU6IGJvb2xlYW4pID0+IG5ldyBQYWdpbmF0aW9uSXRlbShwYWdlLCBhY3RpdmUsIGZhbHNlLCBgJHtwYWdlfWApO1xuXG4vKipcbiAqIFByb3ZpZGVzIHRoZSBwYWdlcyB3aXRoIGEgdG90YWwgb2Ygc2V2ZW4uIFNlZSBVbml0IFRlc3QuXG4gKiBFeGFtcGxlczpcbiAqICAgQ0FTRSAxOiAgMSAgIDIgICAzICAgKjQqICAgNSAgIDYgICA3XG4gKiAgICAgICAgICAgIDEgICAyICAgMyAgICo0KiAgIDVcbiAqICAgQ0FTRSAyOiAgMSAgIDIgICAzICAgKjQqICAgNSAgIC4uICA1MFxuICogICBDQVNFIDM6ICAxICAgLi4gIDQ2ICAqNDcqICA0OCAgNDkgIDUwXG4gKiAgIENBU0UgNDogIDEgICAuLiAgNDkgICo1MCogIDUxICAuLiAgOTBcbiAqL1xuY29uc3QgY2FsY3VsYXRlUGFnaW5hdGlvbkl0ZW1zID0gKHRvdGFsOiBudW1iZXIsIGN1cnJlbnQ6IG51bWJlcikgPT4ge1xuICBjb25zdCBwYWdpbmF0aW9uSXRlbXM6IFBhZ2luYXRpb25JdGVtW10gPSBbXTtcbiAgaWYgKHRvdGFsID09PSB1bmRlZmluZWQgfHwgdG90YWwgPT09IG51bGwgfHwgY3VycmVudCA9PT0gdW5kZWZpbmVkIHx8IGN1cnJlbnQgPT09IG51bGwpIHtcbiAgICByZXR1cm4gcGFnaW5hdGlvbkl0ZW1zO1xuICB9XG4gIC8vXG4gIC8vIENBU0UgMTogVG90YWwgaXMgc21hbGxlciBvciBlcXVhbCBzZXZlblxuICAvL1xuICBpZiAodG90YWwgPD0gNykge1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IHRvdGFsOyBpKyspIHtcbiAgICAgIHBhZ2luYXRpb25JdGVtcy5wdXNoKG5ldyBQYWdpbmF0aW9uSXRlbShpLCBjdXJyZW50ID09PSBpLCBmYWxzZSwgYCR7aX1gKSk7XG4gICAgfVxuICB9IGVsc2VcbiAgLy9cbiAgLy8gQ0FTRSAyOiBUb3RhbCBpcyBncmVhdGVyIHRoYW4gc2V2ZW4gQU5EIHBhZ2UgaXMgaW4gcmFuZ2Ugb2YgWzEtNF1cbiAgLy9cbiAgaWYgKHRvdGFsID4gNyAmJiBjdXJyZW50IDw9IDQpIHtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSA1OyBpKyspIHtcbiAgICAgIHBhZ2luYXRpb25JdGVtcy5wdXNoKGNyZWF0ZUFuSXRlbShpLCBjdXJyZW50ID09PSBpKSk7XG4gICAgfVxuICAgIHBhZ2luYXRpb25JdGVtcy5wdXNoKGNyZWF0ZUZpbGxlcigpKTtcbiAgICBwYWdpbmF0aW9uSXRlbXMucHVzaChjcmVhdGVBbkl0ZW0odG90YWwsIGZhbHNlKSk7XG4gIH0gZWxzZVxuICAvL1xuICAvLyBDQVNFIDM6IFRvdGFsIGlzIGdyZWF0ZXIgdGhhbiBzZXZlbiBBTkQgcGFnZSBpcyBncmVhdGVyIHRoYW4gZm91ciBBTkQgcGFnZSBpcyBuZWFyIHRvdGFsXG4gIC8vXG4gIGlmICh0b3RhbCA+IDcgJiYgY3VycmVudCA+IDQgJiYgY3VycmVudCArIDMgPj0gdG90YWwpIHtcbiAgICBwYWdpbmF0aW9uSXRlbXMucHVzaChjcmVhdGVBbkl0ZW0oMSwgZmFsc2UpKTtcbiAgICBwYWdpbmF0aW9uSXRlbXMucHVzaChjcmVhdGVGaWxsZXIoKSk7XG4gICAgZm9yIChsZXQgaSA9IHRvdGFsIC0gNDsgaSA8PSB0b3RhbDsgaSsrKSB7XG4gICAgICBwYWdpbmF0aW9uSXRlbXMucHVzaChjcmVhdGVBbkl0ZW0oaSwgY3VycmVudCA9PT0gaSkpO1xuICAgIH1cbiAgfSBlbHNlXG4gIC8vXG4gIC8vIENBU0UgNDogVG90YWwgaXMgZ3JlYXRlciB0aGFuIHNldmVuIEFORCBwYWdlIGlzIGdyZWF0ZXIgdGhhbiBmb3VyXG4gIC8vXG4gIGlmICh0b3RhbCA+IDcgJiYgY3VycmVudCA+IDQpIHtcbiAgICBwYWdpbmF0aW9uSXRlbXMucHVzaChjcmVhdGVBbkl0ZW0oMSwgZmFsc2UpKTtcbiAgICBwYWdpbmF0aW9uSXRlbXMucHVzaChjcmVhdGVGaWxsZXIoKSk7XG4gICAgcGFnaW5hdGlvbkl0ZW1zLnB1c2goY3JlYXRlQW5JdGVtKGN1cnJlbnQgLSAxLCBmYWxzZSkpO1xuICAgIHBhZ2luYXRpb25JdGVtcy5wdXNoKGNyZWF0ZUFuSXRlbShjdXJyZW50LCB0cnVlKSk7XG4gICAgcGFnaW5hdGlvbkl0ZW1zLnB1c2goY3JlYXRlQW5JdGVtKGN1cnJlbnQgKyAxLCBmYWxzZSkpO1xuICAgIHBhZ2luYXRpb25JdGVtcy5wdXNoKGNyZWF0ZUZpbGxlcigpKTtcbiAgICBwYWdpbmF0aW9uSXRlbXMucHVzaChjcmVhdGVBbkl0ZW0odG90YWwsIGZhbHNlKSk7XG4gIH1cbiAgLy9cbiAgLy8gRU5EXG4gIC8vXG4gIHJldHVybiBwYWdpbmF0aW9uSXRlbXM7XG59O1xuXG5leHBvcnQgeyBjYWxjdWxhdGVQYWdpbmF0aW9uSXRlbXMsIGNyZWF0ZUZpbGxlciB9O1xuIiwiLyohXG4gKiBAbGljZW5zZSBNSVRcbiAqIENvcHlyaWdodCAoYykgMjAxNyBCZXJuaGFyZCBHcsODwrxuZXdhbGR0IC0gY29kZWNsb3UuaW9cbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9jbG91a2l0L2xlZ2FsXG4gKi9cbmltcG9ydCB7IEV2ZW50RW1pdHRlciwgQ29tcG9uZW50LCBJbnB1dCwgT25DaGFuZ2VzLCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIENsb3VraXRDb21wb25lbnRUaGVtZSwgQ2xvdWtpdFN0YXRlZnVsQW5kTW9kaWZpZXJBd2FyZUVsZW1lbnRUaGVtZVN0eWxlRGVmaW5pdGlvbixcbiAgQ2xvdWtpdFRoZW1lU2VydmljZSxcbn0gZnJvbSAnQGNsb3VraXQvdGhlbWUnO1xuaW1wb3J0IHsgY2FsY3VsYXRlUGFnaW5hdGlvbkl0ZW1zIH0gZnJvbSAnLi9sb2dpYy9wYWdpbmF0aW9uLWhlbHBlcic7XG5pbXBvcnQgeyBQYWdpbmF0aW9uQnV0dG9uQ2xpY2tFdmVudCwgUGFnaW5hdGlvbkJ1dHRvblR5cGUsIFBhZ2luYXRpb25JdGVtIH0gZnJvbSAnLi9wYWdpbmF0aW9uLm1vZGVsJztcblxuLyoqXG4gKiBQYWdpbmF0aW9uIENvbXBvbmVudC5cbiAqXG4gKiBKdXN0IHVzZSB0aGlzIGluc2lkZSB5b3VyIHRlbXBsYXRlczpcbiAqXG4gKiBgYGBodG1sXG4gKiA8Y2xvdWtpdC1wYWdpbmF0aW9uIC4uLj48L2Nsb3VraXQtcGFnaW5hdGlvbj5cbiAqIGBgYFxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjbG91a2l0LXBhZ2luYXRpb24nLFxuICB0ZW1wbGF0ZTogYFxuICA8ZGl2IFtuZ1N0eWxlXT1cImdldFN0eWxlKCd3cmFwcGVyJykuc3R5bGVcIj5cbiAgICA8Y2xvdWtpdC1wYWdpbmF0aW9uLWJ1dHRvblxuICAgICAgW2Rpc2FibGVkXT1cIiFpc1ByZXZpb3VzUG9zc2libGUoKSB8fCBkaXNhYmxlZFwiXG4gICAgICBbcGFnaW5hdGlvbkl0ZW1dPVwicHJldmlvdXNEdW1teVBhZ2luYXRpb25JdGVtKClcIlxuICAgICAgW3RoZW1lU2VsZWN0ZWRdPVwidGhlbWVTZWxlY3RlZFwiXG4gICAgICBbdHlwZV09XCJQYWdpbmF0aW9uQnV0dG9uVHlwZVsncHJldmlvdXMnXVwiXG4gICAgICAoY2xpY2tlZCk9XCJzZWxlY3RQYWdlKCRldmVudClcIlxuICAgID48L2Nsb3VraXQtcGFnaW5hdGlvbi1idXR0b24+XG4gICAgPGNsb3VraXQtcGFnaW5hdGlvbi1idXR0b25cbiAgICAgICpuZ0Zvcj1cImxldCBwYWdlIG9mIHN0YXRlLnBhZ2VzXCJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICBbcGFnaW5hdGlvbkl0ZW1dPVwicGFnZVwiXG4gICAgICBbdGhlbWVTZWxlY3RlZF09XCJ0aGVtZVNlbGVjdGVkXCJcbiAgICAgIFt0eXBlXT1cIlBhZ2luYXRpb25CdXR0b25UeXBlWydub3JtYWwnXVwiXG4gICAgICAoY2xpY2tlZCk9XCJzZWxlY3RQYWdlKCRldmVudClcIlxuICAgID48L2Nsb3VraXQtcGFnaW5hdGlvbi1idXR0b24+XG4gICAgPGNsb3VraXQtcGFnaW5hdGlvbi1idXR0b25cbiAgICAgIFtkaXNhYmxlZF09XCIhaXNOZXh0UG9zc2libGUoKSB8fCBkaXNhYmxlZFwiXG4gICAgICBbcGFnaW5hdGlvbkl0ZW1dPVwibmV4dER1bW15UGFnaW5hdGlvbkl0ZW0oKVwiXG4gICAgICBbdGhlbWVTZWxlY3RlZF09XCJ0aGVtZVNlbGVjdGVkXCJcbiAgICAgIFt0eXBlXT1cIlBhZ2luYXRpb25CdXR0b25UeXBlWyduZXh0J11cIlxuICAgICAgKGNsaWNrZWQpPVwic2VsZWN0UGFnZSgkZXZlbnQpXCJcbiAgICA+PC9jbG91a2l0LXBhZ2luYXRpb24tYnV0dG9uPlxuICA8L2Rpdj5gLFxuICBzdHlsZXM6IFsgXSxcbn0pXG5leHBvcnQgY2xhc3MgQ2xvdWtpdFBhZ2luYXRpb25Db21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCB0aGVtZSBzZWxlY3Rvci4gT25seSB1c2UgYHRoZW1lYCB3aGVuIHlvdSBoYXZlIHJlZ2lzdGVyZWQgYSB2YWxpZCB0aGVtZVxuICAgKiB2aWEgdGhlIGBDbG91a2l0VGhlbWVTZXJ2aWNlYCBmcm9tIFtgQGNsb3VraXQvdGhlbWVgXXtAbGluayBodHRwczovL2Nsb3VraXQuZ2l0aHViLmlvLyMvY29tcG9uZW50L3RoZW1lfS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyB0aGVtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgdG90YWwgUGFnZXNcbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyB0b3RhbDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBDdXJyZW50IFBhZ2VcbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjdXJyZW50OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEV4dGVybmFsIHdheSB0byBkaXNhYmxlIHRoZSB3aG9sZSBwYWdpbmF0aW9uIGUuZy5cbiAgICogZHVyaW5nIGxvYWRpbmcgZXh0ZXJuYWwgZGF0YVxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGRpc2FibGVkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIExhYmVsIGZvciB0aGUgXCJOZXh0XCIgYnV0dG9uLCBkZWZhdWx0cyB0byBcIk5leHRcIlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGxhYmVsTmV4dDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBMYWJlbCBmb3IgdGhlIFwiUHJldmlvdXNcIiBidXR0b24sIGRlZmF1bHRzIHRvIFwiUHJldlwiXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgbGFiZWxQcmV2OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEV2ZW50IGVtaXR0ZWQsIHdoZW4gcGFnZSBpcyBjbGlja2VkLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZVxuICBwdWJsaWMgb25QYWdlU2VsZWN0OiBFdmVudEVtaXR0ZXI8bnVtYmVyPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAvLyBJTlRFUk5BTCBWQVJJQUJMRVNcbiAgcHVibGljIHRoZW1lU2VsZWN0ZWQ6IENsb3VraXRDb21wb25lbnRUaGVtZTtcbiAgcHVibGljIFBhZ2luYXRpb25CdXR0b25UeXBlID0gUGFnaW5hdGlvbkJ1dHRvblR5cGU7XG4gIHB1YmxpYyBzdGF0ZSA9IHtcbiAgICBwYWdlczogW11cbiAgfTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHRoZW1lU2VydmljZTogQ2xvdWtpdFRoZW1lU2VydmljZSkge1xuICAgIHRoaXMudGhlbWVTZWxlY3RlZCA9IHRoaXMudGhlbWVTZXJ2aWNlLmdldENvbXBvbmVudFRoZW1lKCdwYWdpbmF0aW9uJyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0U3R5bGUoZWxlbWVudDogc3RyaW5nKTogQ2xvdWtpdFN0YXRlZnVsQW5kTW9kaWZpZXJBd2FyZUVsZW1lbnRUaGVtZVN0eWxlRGVmaW5pdGlvbiB7XG4gICAgY29uc3Qgc3R5bGUgPSB0aGlzLnRoZW1lU2VsZWN0ZWQuZ2V0U3R5bGUoZWxlbWVudCwgJ25vcm1hbCcsICdiYXNlJyk7XG4gICAgcmV0dXJuIHRoaXMudGhlbWVTZXJ2aWNlLnByZWZpeFN0eWxlKHN0eWxlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAb3ZlcnJpZGVzIE9uQ2hhbmdlc1xuICAgKiBAaGlkZGVuXG4gICAqL1xuICBuZ09uQ2hhbmdlcygpIHtcbiAgICBpZiAodGhpcy50aGVtZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMudGhlbWUgIT09IG51bGwpIHtcbiAgICAgIHRoaXMudGhlbWVTZWxlY3RlZCA9IHRoaXMudGhlbWVTZXJ2aWNlLmdldENvbXBvbmVudFRoZW1lKHRoaXMudGhlbWUpO1xuICAgICAgaWYgKHRoaXMudGhlbWVTZWxlY3RlZCA9PT0gbnVsbCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgV0FSTjogcmVxdWVzdGVkIHRoZW1lICR7dGhpcy50aGVtZX0gZG9lcyBub3QgZXhpc3QuIEZhbGxpbmcgYmFjayB0byBkZWZhdWx0IHRoZW1lIGZvciBwYWdpbmF0aW9uLmApO1xuICAgICAgICB0aGlzLnRoZW1lU2VsZWN0ZWQgPSB0aGlzLnRoZW1lU2VydmljZS5nZXRDb21wb25lbnRUaGVtZSgncGFnaW5hdGlvbicpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnN0YXRlLnBhZ2VzID0gY2FsY3VsYXRlUGFnaW5hdGlvbkl0ZW1zKHRoaXMudG90YWwsIHRoaXMuY3VycmVudCk7XG4gIH1cblxuICBzZWxlY3RQYWdlKGV2ZW50OiBQYWdpbmF0aW9uQnV0dG9uQ2xpY2tFdmVudCkge1xuICAgIGlmIChldmVudC50eXBlID09PSBQYWdpbmF0aW9uQnV0dG9uVHlwZVsncHJldmlvdXMnXSAmJlxuICAgICAgdGhpcy5pc1ByZXZpb3VzUG9zc2libGUoKSkge1xuICAgICAgdGhpcy5vblBhZ2VTZWxlY3QuZW1pdCh0aGlzLmN1cnJlbnQgLSAxKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09IFBhZ2luYXRpb25CdXR0b25UeXBlWyduZXh0J10gJiZcbiAgICAgIHRoaXMuaXNOZXh0UG9zc2libGUoKSkge1xuICAgICAgdGhpcy5vblBhZ2VTZWxlY3QuZW1pdCh0aGlzLmN1cnJlbnQgKyAxKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09IFBhZ2luYXRpb25CdXR0b25UeXBlWydub3JtYWwnXSkge1xuICAgICAgdGhpcy5vblBhZ2VTZWxlY3QuZW1pdChldmVudC5wYWdlKTtcbiAgICB9XG4gIH1cblxuICBwcmV2aW91c0R1bW15