@cloukit/pagination
Version:
574 lines (559 loc) • 70.1 kB
JavaScript
(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