@angular-generic-table/column-settings
Version:
angular-generic-table extension that makes it easy to toggle column visibility and reoder columns.
397 lines (386 loc) • 51.5 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('ng2-dragula'), require('@angular/common'), require('@angular-generic-table/core')) :
typeof define === 'function' && define.amd ? define('@angular-generic-table/column-settings', ['exports', '@angular/core', 'ng2-dragula', '@angular/common', '@angular-generic-table/core'], factory) :
(factory((global['angular-generic-table'] = global['angular-generic-table'] || {}, global['angular-generic-table']['column-settings'] = {}),global.ng.core,global.DragulaModule,global.ng.common,global.GenericTableModule));
}(this, (function (exports,core,ng2Dragula,common,core$1) { '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.
***************************************************************************** */
var __assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var GtColumnPipe = (function () {
function GtColumnPipe() {
}
/**
* Sort by column order
* @param {?} a
* @param {?} b
* @return {?}
*/
GtColumnPipe.prototype.getColumnOrder = /**
* Sort by column order
* @param {?} a
* @param {?} b
* @return {?}
*/
function (a, b) {
if (a.columnOrder < b.columnOrder) {
return -1;
}
if (a.columnOrder > b.columnOrder || typeof a.columnOrder === 'undefined') {
return 1;
}
return 0;
};
/**
* return enabled columns that are not locked for editing
* @param {?} column
* @return {?}
*/
GtColumnPipe.prototype.getEnabled = /**
* return enabled columns that are not locked for editing
* @param {?} column
* @return {?}
*/
function (column) {
return column.enabled !== false && column.lockSettings !== true
? column
: null;
};
/**
* @param {?} settings
* @return {?}
*/
GtColumnPipe.prototype.transform = /**
* @param {?} settings
* @return {?}
*/
function (settings) {
return settings.filter(this.getEnabled).sort(this.getColumnOrder);
};
GtColumnPipe.decorators = [
{ type: core.Pipe, args: [{
name: 'gtColumn'
},] },
];
return GtColumnPipe;
}());
var GtColumnSettingsComponent = (function () {
function GtColumnSettingsComponent(dragulaService, changeDetectorRef) {
var _this = this;
this.dragulaService = dragulaService;
this.changeDetectorRef = changeDetectorRef;
this.gtHeaderClasses = 'px-3 pt-3 pb-2 table-bordered border-left-0 border-right-0 border-bottom-0 alert-info';
this.gtWrapperClasses = 'px-3 pb-3 table-bordered border-left-0 border-right-0 border-top-0 alert-info';
this.overlay = true;
this.gtDefaultTexts = {
title: 'Columns',
help: 'Double click to toggle visibility, drag and drop to reorder.'
};
this.gtTexts = this.gtDefaultTexts;
this.gtEvent = new core.EventEmitter();
this.active = false;
this.reordered = false;
/**
* Extend object function.
*/
this.extend = function (a, b) {
for (var /** @type {?} */ key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
};
dragulaService.drop.subscribe(function (value) {
if (value[0] === _this.bagId) {
_this._onDrop(value.slice(1));
}
});
}
Object.defineProperty(GtColumnSettingsComponent.prototype, "genericTable", {
get: /**
* @return {?}
*/ function () {
return this._genericTable;
},
set: /**
* @param {?} value
* @return {?}
*/ function (value) {
this._genericTable = value;
},
enumerable: true,
configurable: true
});
/**
* Check offset height on window resize.
* @return {?}
*/
GtColumnSettingsComponent.prototype.onResize = /**
* Check offset height on window resize.
* @return {?}
*/
function () {
this.offset = this._getTableHeadHeight();
this.heightAdjust = this._getColumnSettingsHeaderHeight();
};
/**
* @return {?}
*/
GtColumnSettingsComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.bagId = this.generateId();
// setup texts
this.gtTexts = /** @type {?} */ (this.extend(this.gtDefaultTexts, this.gtTexts));
};
/**
* Toggle column settings visibility.
* @return {?}
*/
GtColumnSettingsComponent.prototype.toggleColumnSettings = /**
* Toggle column settings visibility.
* @return {?}
*/
function () {
var _this = this;
this.active = !this.active;
if (this.active) {
this.offset = this._getTableHeadHeight();
// check and adjust height offset
setTimeout(function () {
_this.heightAdjust = _this._getColumnSettingsHeaderHeight();
}, 0);
}
};
/**
* Toggle column visibility.
* @param {?} column - column object.
* @return {?}
*/
GtColumnSettingsComponent.prototype.toggleColumnVisibility = /**
* Toggle column visibility.
* @param {?} column - column object.
* @return {?}
*/
function (column) {
var _this = this;
// toggle column visibility
column.visible =
typeof column.visible === 'undefined' ? false : !column.visible;
// redraw table
this._genericTable.redraw();
// emit event
this.gtEvent.emit({
name: 'gt-column-visibility-change',
value: {
column: __assign({}, column),
settings: __spread(this._genericTable.gtSettings)
}
});
// check and reset offset
setTimeout(function () {
_this.offset = _this._getTableHeadHeight();
}, 0);
};
/**
* Order table by object key.
* @param {?} args - name of key to sort on.
* @return {?}
*/
GtColumnSettingsComponent.prototype._onDrop = /**
* Order table by object key.
* @param {?} args - name of key to sort on.
* @return {?}
*/
function (args) {
this.reordered = true;
var _a = __read(args, 2), e = _a[0], target = _a[1];
var /** @type {?} */ order = {};
for (var /** @type {?} */ i = 0; i < target.children.length; i++) {
order[target.children[i].getAttribute('data-object-key')] = i;
}
for (var /** @type {?} */ i = 0; i < this._genericTable.gtSettings.length; i++) {
this._genericTable.gtSettings[i].columnOrder =
order[this._genericTable.gtSettings[i].objectKey];
}
// reset array to trigger change detection
this._genericTable.gtSettings = __spread(this._genericTable.gtSettings);
this.changeDetectorRef.markForCheck();
this._genericTable.redraw();
this.gtEvent.emit({
name: 'gt-column-order-change',
value: {
settings: __spread(this._genericTable.gtSettings)
}
});
};
/**
* Get height of table head element ie. first row containing table headers.
* @return {?} offset height for table header in px.
*/
GtColumnSettingsComponent.prototype._getTableHeadHeight = /**
* Get height of table head element ie. first row containing table headers.
* @return {?} offset height for table header in px.
*/
function () {
try {
if (this.elementView.elementRef.nativeElement.nextElementSibling
.firstElementChild.firstElementChild.tagName === 'THEAD') {
return (this.elementView.elementRef.nativeElement.nextElementSibling
.firstElementChild.firstElementChild.offsetHeight + 'px');
}
if (this.elementView.elementRef.nativeElement.nextElementSibling
.firstElementChild.firstElementChild.firstElementChild.tagName ===
'THEAD') {
return (this.elementView.elementRef.nativeElement.nextElementSibling
.firstElementChild.firstElementChild.firstElementChild
.offsetHeight + 'px');
}
return '0px';
}
catch (error) {
return '0px';
}
};
/**
* Get height of table head element ie. first row containing table headers.
* @return {?} offset height for table header in px.
*/
GtColumnSettingsComponent.prototype._getColumnSettingsHeaderHeight = /**
* Get height of table head element ie. first row containing table headers.
* @return {?} offset height for table header in px.
*/
function () {
try {
return this.gtColumnSettingsHeader.nativeElement.offsetHeight + 'px';
}
catch (error) {
return '0px';
}
};
/**
* generate a unique id for dragula instance i.e. a unique bag name
* @return {?}
*/
GtColumnSettingsComponent.prototype.generateId = /**
* generate a unique id for dragula instance i.e. a unique bag name
* @return {?}
*/
function () {
var /** @type {?} */ d = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var /** @type {?} */ r = ((d + Math.random() * 16) % 16) | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
});
};
GtColumnSettingsComponent.decorators = [
{ type: core.Component, args: [{
selector: 'gt-column-settings',
template: "\n <ng-template #columnItem let-column let-index=\"index\">\n <span class=\"badge badge-secondary\">{{index}}</span>\n <span (dblclick)=\"toggleColumnVisibility(column)\" class=\"badge\" [ngClass]=\"{'badge-success':column.visible !== false, 'badge-danger':column.visible === false}\">{{genericTable.gtFields | gtProperty:column.objectKey:'name'}}</span>\n </ng-template>\n <div class=\"gt-column-settings\">\n <div class=\"gt-column-settings-panel\" *ngIf=\"active\" [style.padding-top]=\"offset\" [style.height]=\"'calc(100% - '+offset+')'\">\n <div #gtColumnSettingsHeader class=\"gt-column-settings-header border-bottom-0\" [ngClass]=\"gtHeaderClasses\">\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"toggleColumnSettings()\">\n <span aria-hidden=\"true\">×</span>\n </button>\n <h6 class=\"gt-column-settings-title\" *ngIf=\"gtTexts.title\">{{gtTexts.title}}</h6>\n <small class=\"gt-column-settings-help form-text text-muted\" *ngIf=\"gtTexts.help\">{{gtTexts.help}}</small>\n </div>\n <div class=\"gt-column-settings-item-wrapper\" [ngClass]=\"gtWrapperClasses\" [dragula]='bagId' data-visible=\"true\" [style.max-height]=\"'calc(100% - '+heightAdjust+')'\">\n <div class=\"gt-column-settings-item pr-0 pr-sm-4\" *ngFor=\"let i = index;let column of genericTable.gtSettings | gtColumn\" [attr.data-object-key]=\"column.objectKey\">\n <ng-template [ngTemplateOutlet]=\"gtColumnItem ? gtColumnItem:columnItem\" [ngTemplateOutletContext]=\"{$implicit: column,index: this.reordered ? column.columnOrder+1:i+1, name: (genericTable.gtFields | gtProperty:column.objectKey:'name')}\"></ng-template>\n </div>\n </div>\n <div class=\"gt-overlay\" *ngIf=\"active && overlay\" (click)=\"toggleColumnSettings()\" [style.height]=\"'calc(100% - -'+offset+')'\"></div>\n </div>\n <ng-template #genericTableElement [ngIf]=\"genericTable\">\n <ng-content></ng-content>\n </ng-template>\n </div>\n "
},] },
];
/* tslint:enable */
/** @nocollapse */
GtColumnSettingsComponent.ctorParameters = function () {
return [
{ type: ng2Dragula.DragulaService, },
{ type: core.ChangeDetectorRef, },
];
};
GtColumnSettingsComponent.propDecorators = {
"genericTable": [{ type: core.Input },],
"elementView": [{ type: core.ViewChild, args: ['genericTableElement',] },],
"gtColumnSettingsHeader": [{ type: core.ViewChild, args: ['gtColumnSettingsHeader',] },],
"gtHeaderClasses": [{ type: core.Input },],
"gtWrapperClasses": [{ type: core.Input },],
"overlay": [{ type: core.Input },],
"gtColumnItem": [{ type: core.Input },],
"gtTexts": [{ type: core.Input },],
"gtEvent": [{ type: core.Output },],
"onResize": [{ type: core.HostListener, args: ['window:resize', [],] },],
};
return GtColumnSettingsComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var ColumnSettingsModule = (function () {
function ColumnSettingsModule() {
}
ColumnSettingsModule.decorators = [
{ type: core.NgModule, args: [{
imports: [common.CommonModule, core$1.GenericTableModule, ng2Dragula.DragulaModule],
declarations: [GtColumnSettingsComponent, GtColumnPipe],
exports: [GtColumnSettingsComponent, GtColumnPipe]
},] },
];
return ColumnSettingsModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
exports.ColumnSettingsModule = ColumnSettingsModule;
exports.ɵa = GtColumnPipe;
exports.ɵb = GtColumnSettingsComponent;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1nZW5lcmljLXRhYmxlLWNvbHVtbi1zZXR0aW5ncy51bWQuanMubWFwIiwic291cmNlcyI6W251bGwsIm5nOi8vQGFuZ3VsYXItZ2VuZXJpYy10YWJsZS9jb2x1bW4tc2V0dGluZ3MvY29tcG9uZW50cy9ndC1jb2x1bW4tc2V0dGluZ3MuY29tcG9uZW50LnRzIiwibmc6Ly9AYW5ndWxhci1nZW5lcmljLXRhYmxlL2NvbHVtbi1zZXR0aW5ncy9jb2x1bW4tc2V0dGluZ3MubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlXHJcbnRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlXHJcbkxpY2Vuc2UgYXQgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXHJcblxyXG5USElTIENPREUgSVMgUFJPVklERUQgT04gQU4gKkFTIElTKiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXHJcbktJTkQsIEVJVEhFUiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04gQU5ZIElNUExJRURcclxuV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIFRJVExFLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSxcclxuTUVSQ0hBTlRBQkxJVFkgT1IgTk9OLUlORlJJTkdFTUVOVC5cclxuXHJcblNlZSB0aGUgQXBhY2hlIFZlcnNpb24gMi4wIExpY2Vuc2UgZm9yIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xyXG5hbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIGlmIChlLmluZGV4T2YocFtpXSkgPCAwKVxyXG4gICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0geVtvcFswXSAmIDIgPyBcInJldHVyblwiIDogb3BbMF0gPyBcInRocm93XCIgOiBcIm5leHRcIl0pICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gWzAsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBleHBvcnRzKSB7XHJcbiAgICBmb3IgKHZhciBwIGluIG0pIGlmICghZXhwb3J0cy5oYXNPd25Qcm9wZXJ0eShwKSkgZXhwb3J0c1twXSA9IG1bcF07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl0sIGkgPSAwO1xyXG4gICAgaWYgKG0pIHJldHVybiBtLmNhbGwobyk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWQoKSB7XHJcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcclxuICAgICAgICBhciA9IGFyLmNvbmNhdChfX3JlYWQoYXJndW1lbnRzW2ldKSk7XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0KHYpIHtcclxuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgX19hd2FpdCA/ICh0aGlzLnYgPSB2LCB0aGlzKSA6IG5ldyBfX2F3YWl0KHYpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0dlbmVyYXRvcih0aGlzQXJnLCBfYXJndW1lbnRzLCBnZW5lcmF0b3IpIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgZyA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSwgaSwgcSA9IFtdO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlmIChnW25dKSBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiByZXN1bWUobiwgdikgeyB0cnkgeyBzdGVwKGdbbl0odikpOyB9IGNhdGNoIChlKSB7IHNldHRsZShxWzBdWzNdLCBlKTsgfSB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKHIpIHsgci52YWx1ZSBpbnN0YW5jZW9mIF9fYXdhaXQgPyBQcm9taXNlLnJlc29sdmUoci52YWx1ZS52KS50aGVuKGZ1bGZpbGwsIHJlamVjdCkgOiBzZXR0bGUocVswXVsyXSwgcik7ICB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpZiAob1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IG4gPT09IFwicmV0dXJuXCIgfSA6IGYgPyBmKHYpIDogdjsgfTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY1ZhbHVlcyhvKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIG0gPSBvW1N5bWJvbC5hc3luY0l0ZXJhdG9yXTtcclxuICAgIHJldHVybiBtID8gbS5jYWxsKG8pIDogdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG4iLCJpbXBvcnQge1xuXHRDb21wb25lbnQsXG5cdElucHV0LFxuXHRWaWV3Q2hpbGQsXG5cdFRlbXBsYXRlUmVmLFxuXHRFbGVtZW50UmVmLFxuXHRQaXBlLFxuXHRQaXBlVHJhbnNmb3JtLFxuXHRPbkluaXQsXG5cdENoYW5nZURldGVjdG9yUmVmLFxuXHRIb3N0TGlzdGVuZXIsXG5cdE91dHB1dCxcblx0RXZlbnRFbWl0dGVyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcblx0R2VuZXJpY1RhYmxlQ29tcG9uZW50LFxuXHRHdFJvdyxcblx0R3RDb25maWdTZXR0aW5nXG59IGZyb20gJ0Bhbmd1bGFyLWdlbmVyaWMtdGFibGUvY29yZSc7XG5pbXBvcnQgeyBEcmFndWxhU2VydmljZSB9IGZyb20gJ25nMi1kcmFndWxhJztcbmltcG9ydCB7IEd0Q29sdW1uU2V0dGluZ3NUZXh0cyB9IGZyb20gJy4uL2ludGVyZmFjZXMvZ3QtY29sdW1uLXNldHRpbmdzLXRleHRzJztcblxuQFBpcGUoe1xuXHRuYW1lOiAnZ3RDb2x1bW4nXG59KVxuZXhwb3J0IGNsYXNzIEd0Q29sdW1uUGlwZSBpbXBsZW1lbnRzIFBpcGVUcmFuc2Zvcm0ge1xuXHQvLyBUT0RPOiBtb3ZlIHRvIGhlbHBlciBmdW5jdGlvbnNcblx0LyoqIFNvcnQgYnkgY29sdW1uIG9yZGVyICovXG5cdHByaXZhdGUgZ2V0Q29sdW1uT3JkZXIoYTogYW55LCBiOiBhbnkpIHtcblx0XHRpZiAoYS5jb2x1bW5PcmRlciA8IGIuY29sdW1uT3JkZXIpIHtcblx0XHRcdHJldHVybiAtMTtcblx0XHR9XG5cdFx0aWYgKGEuY29sdW1uT3JkZXIgPiBiLmNvbHVtbk9yZGVyIHx8IHR5cGVvZiBhLmNvbHVtbk9yZGVyID09PSAndW5kZWZpbmVkJykge1xuXHRcdFx0cmV0dXJuIDE7XG5cdFx0fVxuXHRcdHJldHVybiAwO1xuXHR9XG5cblx0LyoqIHJldHVybiBlbmFibGVkIGNvbHVtbnMgdGhhdCBhcmUgbm90IGxvY2tlZCBmb3IgZWRpdGluZyAqL1xuXHRwcml2YXRlIGdldEVuYWJsZWQoY29sdW1uOiBHdENvbmZpZ1NldHRpbmcpIHtcblx0XHRyZXR1cm4gY29sdW1uLmVuYWJsZWQgIT09IGZhbHNlICYmIGNvbHVtbi5sb2NrU2V0dGluZ3MgIT09IHRydWVcblx0XHRcdD8gY29sdW1uXG5cdFx0XHQ6IG51bGw7XG5cdH1cblxuXHR0cmFuc2Zvcm0oc2V0dGluZ3M6IEFycmF5PEd0Q29uZmlnU2V0dGluZz4pOiBBcnJheTxHdENvbmZpZ1NldHRpbmc+IHtcblx0XHRyZXR1cm4gc2V0dGluZ3MuZmlsdGVyKHRoaXMuZ2V0RW5hYmxlZCkuc29ydCh0aGlzLmdldENvbHVtbk9yZGVyKTtcblx0fVxufVxuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6ICdndC1jb2x1bW4tc2V0dGluZ3MnLFxuXHR0ZW1wbGF0ZTogYFxuICAgICAgICA8bmctdGVtcGxhdGUgI2NvbHVtbkl0ZW0gbGV0LWNvbHVtbiBsZXQtaW5kZXg9XCJpbmRleFwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJiYWRnZSBiYWRnZS1zZWNvbmRhcnlcIj57e2luZGV4fX08L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiAoZGJsY2xpY2spPVwidG9nZ2xlQ29sdW1uVmlzaWJpbGl0eShjb2x1bW4pXCIgY2xhc3M9XCJiYWRnZVwiIFtuZ0NsYXNzXT1cInsnYmFkZ2Utc3VjY2Vzcyc6Y29sdW1uLnZpc2libGUgIT09IGZhbHNlLCAnYmFkZ2UtZGFuZ2VyJzpjb2x1bW4udmlzaWJsZSA9PT0gZmFsc2V9XCI+e3tnZW5lcmljVGFibGUuZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J25hbWUnfX08L3NwYW4+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJndC1jb2x1bW4tc2V0dGluZ3NcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJndC1jb2x1bW4tc2V0dGluZ3MtcGFuZWxcIiAgKm5nSWY9XCJhY3RpdmVcIiBbc3R5bGUucGFkZGluZy10b3BdPVwib2Zmc2V0XCIgW3N0eWxlLmhlaWdodF09XCInY2FsYygxMDAlIC0gJytvZmZzZXQrJyknXCI+XG4gICAgICAgICAgICAgICAgPGRpdiAjZ3RDb2x1bW5TZXR0aW5nc0hlYWRlciBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5ncy1oZWFkZXIgYm9yZGVyLWJvdHRvbS0wXCIgW25nQ2xhc3NdPVwiZ3RIZWFkZXJDbGFzc2VzXCI+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiY2xvc2VcIiBhcmlhLWxhYmVsPVwiQ2xvc2VcIiAoY2xpY2spPVwidG9nZ2xlQ29sdW1uU2V0dGluZ3MoKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JnRpbWVzOzwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxoNiBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5ncy10aXRsZVwiICpuZ0lmPVwiZ3RUZXh0cy50aXRsZVwiPnt7Z3RUZXh0cy50aXRsZX19PC9oNj5cbiAgICAgICAgICAgICAgICAgICAgPHNtYWxsIGNsYXNzPVwiZ3QtY29sdW1uLXNldHRpbmdzLWhlbHAgZm9ybS10ZXh0IHRleHQtbXV0ZWRcIiAqbmdJZj1cImd0VGV4dHMuaGVscFwiPnt7Z3RUZXh0cy5oZWxwfX08L3NtYWxsPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJndC1jb2x1bW4tc2V0dGluZ3MtaXRlbS13cmFwcGVyXCIgW25nQ2xhc3NdPVwiZ3RXcmFwcGVyQ2xhc3Nlc1wiIFtkcmFndWxhXT0nYmFnSWQnICBkYXRhLXZpc2libGU9XCJ0cnVlXCIgW3N0eWxlLm1heC1oZWlnaHRdPVwiJ2NhbGMoMTAwJSAtICcraGVpZ2h0QWRqdXN0KycpJ1wiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ3QtY29sdW1uLXNldHRpbmdzLWl0ZW0gcHItMCBwci1zbS00XCIgKm5nRm9yPVwibGV0IGkgPSBpbmRleDtsZXQgY29sdW1uIG9mIGdlbmVyaWNUYWJsZS5ndFNldHRpbmdzIHwgZ3RDb2x1bW5cIiBbYXR0ci5kYXRhLW9iamVjdC1rZXldPVwiY29sdW1uLm9iamVjdEtleVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImd0Q29sdW1uSXRlbSA/IGd0Q29sdW1uSXRlbTpjb2x1bW5JdGVtXCIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInskaW1wbGljaXQ6IGNvbHVtbixpbmRleDogdGhpcy5yZW9yZGVyZWQgPyBjb2x1bW4uY29sdW1uT3JkZXIrMTppKzEsIG5hbWU6IChnZW5lcmljVGFibGUuZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J25hbWUnKX1cIj48L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ3Qtb3ZlcmxheVwiICpuZ0lmPVwiYWN0aXZlICYmIG92ZXJsYXlcIiAoY2xpY2spPVwidG9nZ2xlQ29sdW1uU2V0dGluZ3MoKVwiIFtzdHlsZS5oZWlnaHRdPVwiJ2NhbGMoMTAwJSAtIC0nK29mZnNldCsnKSdcIj48L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNnZW5lcmljVGFibGVFbGVtZW50IFtuZ0lmXT1cImdlbmVyaWNUYWJsZVwiPlxuICAgICAgICAgICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvZGl2PlxuICAgIGBcbn0pXG5leHBvcnQgY2xhc3MgR3RDb2x1bW5TZXR0aW5nc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cdGdldCBnZW5lcmljVGFibGUoKTogR2VuZXJpY1RhYmxlQ29tcG9uZW50PGFueSwgYW55PiB7XG5cdFx0cmV0dXJuIHRoaXMuX2dlbmVyaWNUYWJsZTtcblx0fVxuXG5cdEBJbnB1dCgpXG5cdHNldCBnZW5lcmljVGFibGUodmFsdWU6IEdlbmVyaWNUYWJsZUNvbXBvbmVudDxhbnksIGFueT4pIHtcblx0XHR0aGlzLl9nZW5lcmljVGFibGUgPSB2YWx1ZTtcblx0fVxuXG5cdEBWaWV3Q2hpbGQoJ2dlbmVyaWNUYWJsZUVsZW1lbnQnKSBlbGVtZW50VmlldzogVGVtcGxhdGVSZWY8RWxlbWVudFJlZj47XG5cdEBWaWV3Q2hpbGQoJ2d0Q29sdW1uU2V0dGluZ3NIZWFkZXInKSBndENvbHVtblNldHRpbmdzSGVhZGVyOiBFbGVtZW50UmVmO1xuXG5cdHByaXZhdGUgX2dlbmVyaWNUYWJsZTogR2VuZXJpY1RhYmxlQ29tcG9uZW50PEd0Um93LCBhbnk+O1xuXHRASW5wdXQoKVxuXHRndEhlYWRlckNsYXNzZXMgPSAncHgtMyBwdC0zIHBiLTIgdGFibGUtYm9yZGVyZWQgYm9yZGVyLWxlZnQtMCBib3JkZXItcmlnaHQtMCBib3JkZXItYm90dG9tLTAgYWxlcnQtaW5mbyc7XG5cdEBJbnB1dCgpXG5cdGd0V3JhcHBlckNsYXNzZXMgPSAncHgtMyBwYi0zIHRhYmxlLWJvcmRlcmVkIGJvcmRlci1sZWZ0LTAgYm9yZGVyLXJpZ2h0LTAgYm9yZGVyLXRvcC0wIGFsZXJ0LWluZm8nO1xuXHRASW5wdXQoKSBvdmVybGF5ID0gdHJ1ZTtcblx0QElucHV0KCkgZ3RDb2x1bW5JdGVtOiBUZW1wbGF0ZVJlZjxFbGVtZW50UmVmPjtcblx0cHVibGljIGd0RGVmYXVsdFRleHRzOiBHdENvbHVtblNldHRpbmdzVGV4dHMgPSB7XG5cdFx0dGl0bGU6ICdDb2x1bW5zJyxcblx0XHRoZWxwOiAnRG91YmxlIGNsaWNrIHRvIHRvZ2dsZSB2aXNpYmlsaXR5LCBkcmFnIGFuZCBkcm9wIHRvIHJlb3JkZXIuJ1xuXHR9O1xuXHRASW5wdXQoKSBndFRleHRzOiBHdENvbHVtblNldHRpbmdzVGV4dHMgPSB0aGlzLmd0RGVmYXVsdFRleHRzO1xuXG5cdEBPdXRwdXQoKSBwdWJsaWMgZ3RFdmVudDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuXHRwdWJsaWMgYWN0aXZlID0gZmFsc2U7XG5cdHB1YmxpYyBvZmZzZXQ6IHN0cmluZztcblx0cHVibGljIGhlaWdodEFkanVzdDogc3RyaW5nO1xuXHRwdWJsaWMgcmVvcmRlcmVkID0gZmFsc2U7XG5cdHB1YmxpYyBiYWdJZDogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBDaGVjayBvZmZzZXQgaGVpZ2h0IG9uIHdpbmRvdyByZXNpemUuXG5cdCAqL1xuXHRASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJywgW10pXG5cdHB1YmxpYyBvblJlc2l6ZSgpIHtcblx0XHR0aGlzLm9mZnNldCA9IHRoaXMuX2dldFRhYmxlSGVhZEhlaWdodCgpO1xuXHRcdHRoaXMuaGVpZ2h0QWRqdXN0ID0gdGhpcy5fZ2V0Q29sdW1uU2V0dGluZ3NIZWFkZXJIZWlnaHQoKTtcblx0fVxuXG5cdGNvbnN0cnVjdG9yKFxuXHRcdHByaXZhdGUgZHJhZ3VsYVNlcnZpY2U6IERyYWd1bGFTZXJ2aWNlLFxuXHRcdHByaXZhdGUgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmXG5cdCkge1xuXHRcdGRyYWd1bGFTZXJ2aWNlLmRyb3Auc3Vic2NyaWJlKCh2YWx1ZTogQXJyYXk8YW55PikgPT4ge1xuXHRcdFx0aWYgKHZhbHVlWzBdID09PSB0aGlzLmJhZ0lkKSB7XG5cdFx0XHRcdHRoaXMuX29uRHJvcCh2YWx1ZS5zbGljZSgxKSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRuZ09uSW5pdCgpIHtcblx0XHR0aGlzLmJhZ0lkID0gdGhpcy5nZW5lcmF0ZUlkKCk7XG5cdFx0Ly8gc2V0dXAgdGV4dHNcblx0XHR0aGlzLmd0VGV4dHMgPSA8R3RDb2x1bW5TZXR0aW5nc1RleHRzPnRoaXMuZXh0ZW5kKFxuXHRcdFx0dGhpcy5ndERlZmF1bHRUZXh0cyxcblx0XHRcdHRoaXMuZ3RUZXh0c1xuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogIEV4dGVuZCBvYmplY3QgZnVuY3Rpb24uXG5cdCAqL1xuXHRwcml2YXRlIGV4dGVuZCA9IGZ1bmN0aW9uKGE6IE9iamVjdCwgYjogT2JqZWN0KSB7XG5cdFx0Zm9yIChjb25zdCBrZXkgaW4gYikge1xuXHRcdFx0aWYgKGIuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuXHRcdFx0XHRhW2tleV0gPSBiW2tleV07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBhO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBUb2dnbGUgY29sdW1uIHNldHRpbmdzIHZpc2liaWxpdHkuXG5cdCAqL1xuXHRwdWJsaWMgdG9nZ2xlQ29sdW1uU2V0dGluZ3MoKSB7XG5cdFx0dGhpcy5hY3RpdmUgPSAhdGhpcy5hY3RpdmU7XG5cblx0XHRpZiAodGhpcy5hY3RpdmUpIHtcblx0XHRcdHRoaXMub2Zmc2V0ID0gdGhpcy5fZ2V0VGFibGVIZWFkSGVpZ2h0KCk7XG5cblx0XHRcdC8vIGNoZWNrIGFuZCBhZGp1c3QgaGVpZ2h0IG9mZnNldFxuXHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdHRoaXMuaGVpZ2h0QWRqdXN0ID0gdGhpcy5fZ2V0Q29sdW1uU2V0dGluZ3NIZWFkZXJIZWlnaHQoKTtcblx0XHRcdH0sIDApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUb2dnbGUgY29sdW1uIHZpc2liaWxpdHkuXG5cdCAqIEBwYXJhbSBjb2x1bW4gLSBjb2x1bW4gb2JqZWN0LlxuXHQgKi9cblx0cHVibGljIHRvZ2dsZUNvbHVtblZpc2liaWxpdHkoY29sdW1uOiBhbnkpIHtcblx0XHQvLyB0b2dnbGUgY29sdW1uIHZpc2liaWxpdHlcblx0XHRjb2x1bW4udmlzaWJsZSA9XG5cdFx0XHR0eXBlb2YgY29sdW1uLnZpc2libGUgPT09ICd1bmRlZmluZWQnID8gZmFsc2UgOiAhY29sdW1uLnZpc2libGU7XG5cblx0XHQvLyByZWRyYXcgdGFibGVcblx0XHR0aGlzLl9nZW5lcmljVGFibGUucmVkcmF3KCk7XG5cblx0XHQvLyBlbWl0IGV2ZW50XG5cdFx0dGhpcy5ndEV2ZW50LmVtaXQoe1xuXHRcdFx0bmFtZTogJ2d0LWNvbHVtbi12aXNpYmlsaXR5LWNoYW5nZScsXG5cdFx0XHR2YWx1ZToge1xuXHRcdFx0XHRjb2x1bW46IHsgLi4uY29sdW1uIH0sXG5cdFx0XHRcdHNldHRpbmdzOiBbLi4udGhpcy5fZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3NdXG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQvLyBjaGVjayBhbmQgcmVzZXQgb2Zmc2V0XG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHR0aGlzLm9mZnNldCA9IHRoaXMuX2dldFRhYmxlSGVhZEhlaWdodCgpO1xuXHRcdH0sIDApO1xuXHR9XG5cblx0LyoqXG5cdCAqIE9yZGVyIHRhYmxlIGJ5IG9iamVjdCBrZXkuXG5cdCAqIEBwYXJhbSBhcmdzIC0gbmFtZSBvZiBrZXkgdG8gc29ydCBvbi5cblx0ICovXG5cdHByaXZhdGUgX29uRHJvcChhcmdzOiBBcnJheTxhbnk+KSB7XG5cdFx0dGhpcy5yZW9yZGVyZWQgPSB0cnVlO1xuXHRcdGNvbnN0IFtlLCB0YXJnZXRdID0gYXJncztcblx0XHRjb25zdCBvcmRlciA9IHt9O1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGFyZ2V0LmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRvcmRlclt0YXJnZXQuY2hpbGRyZW5baV0uZ2V0QXR0cmlidXRlKCdkYXRhLW9iamVjdC1rZXknKV0gPSBpO1xuXHRcdH1cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2dlbmVyaWNUYWJsZS5ndFNldHRpbmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5nc1tpXS5jb2x1bW5PcmRlciA9XG5cdFx0XHRcdG9yZGVyW3RoaXMuX2dlbmVyaWNUYWJsZS5ndFNldHRpbmdzW2ldLm9iamVjdEtleV07XG5cdFx0fVxuXG5cdFx0Ly8gcmVzZXQgYXJyYXkgdG8gdHJpZ2dlciBjaGFuZ2UgZGV0ZWN0aW9uXG5cdFx0dGhpcy5fZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3MgPSBbLi4udGhpcy5fZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3NdO1xuXHRcdHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cblx0XHR0aGlzLl9nZW5lcmljVGFibGUucmVkcmF3KCk7XG5cdFx0dGhpcy5ndEV2ZW50LmVtaXQoe1xuXHRcdFx0bmFtZTogJ2d0LWNvbHVtbi1vcmRlci1jaGFuZ2UnLFxuXHRcdFx0dmFsdWU6IHtcblx0XHRcdFx0c2V0dGluZ3M6IFsuLi50aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5nc11cblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgaGVpZ2h0IG9mIHRhYmxlIGhlYWQgZWxlbWVudCBpZS4gZmlyc3Qgcm93IGNvbnRhaW5pbmcgdGFibGUgaGVhZGVycy5cblx0ICogQHJldHVybnMgb2Zmc2V0IGhlaWdodCBmb3IgdGFibGUgaGVhZGVyIGluIHB4LlxuXHQgKi9cblx0cHJpdmF0ZSBfZ2V0VGFibGVIZWFkSGVpZ2h0KCk6IHN0cmluZyB7XG5cdFx0dHJ5IHtcblx0XHRcdGlmIChcblx0XHRcdFx0dGhpcy5lbGVtZW50Vmlldy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nXG5cdFx0XHRcdFx0LmZpcnN0RWxlbWVudENoaWxkLmZpcnN0RWxlbWVudENoaWxkLnRhZ05hbWUgPT09ICdUSEVBRCdcblx0XHRcdCkge1xuXHRcdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHRcdHRoaXMuZWxlbWVudFZpZXcuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50Lm5leHRFbGVtZW50U2libGluZ1xuXHRcdFx0XHRcdFx0LmZpcnN0RWxlbWVudENoaWxkLmZpcnN0RWxlbWVudENoaWxkLm9mZnNldEhlaWdodCArICdweCdcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHRcdGlmIChcblx0XHRcdFx0dGhpcy5lbGVtZW50Vmlldy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nXG5cdFx0XHRcdFx0LmZpcnN0RWxlbWVudENoaWxkLmZpcnN0RWxlbWVudENoaWxkLmZpcnN0RWxlbWVudENoaWxkLnRhZ05hbWUgPT09XG5cdFx0XHRcdCdUSEVBRCdcblx0XHRcdCkge1xuXHRcdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHRcdHRoaXMuZWxlbWVudFZpZXcuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50Lm5leHRFbGVtZW50U2libGluZ1xuXHRcdFx0XHRcdFx0LmZpcnN0RWxlbWVudENoaWxkLmZpcnN0RWxlbWVudENoaWxkLmZpcnN0RWxlbWVudENoaWxkXG5cdFx0XHRcdFx0XHQub2Zmc2V0SGVpZ2h0ICsgJ3B4J1xuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuICcwcHgnO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRyZXR1cm4gJzBweCc7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldCBoZWlnaHQgb2YgdGFibGUgaGVhZCBlbGVtZW50IGllLiBmaXJzdCByb3cgY29udGFpbmluZyB0YWJsZSBoZWFkZXJzLlxuXHQgKiBAcmV0dXJucyBvZmZzZXQgaGVpZ2h0IGZvciB0YWJsZSBoZWFkZXIgaW4gcHguXG5cdCAqL1xuXHRwcml2YXRlIF9nZXRDb2x1bW5TZXR0aW5nc0hlYWRlckhlaWdodCgpOiBzdHJpbmcge1xuXHRcdHRyeSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5ndENvbHVtblNldHRpbmdzSGVhZGVyLm5hdGl2ZUVsZW1lbnQub2Zmc2V0SGVpZ2h0ICsgJ3B4Jztcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0cmV0dXJuICcwcHgnO1xuXHRcdH1cblx0fVxuXG5cdC8qKiBnZW5lcmF0ZSBhIHVuaXF1ZSBpZCBmb3IgZHJhZ3VsYSBpbnN0YW5jZSBpLmUuIGEgdW5pcXVlIGJhZyBuYW1lKi9cblx0LyogdHNsaW50OmRpc2FibGUgKi9cblx0cHJpdmF0ZSBnZW5lcmF0ZUlkKCkge1xuXHRcdGxldCBkID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cdFx0cmV0dXJuICd4eHh4eHh4eC14eHh4LTR4eHgteXh4eC14eHh4eHh4eHh4eHgnLnJlcGxhY2UoL1t4eV0vZywgZnVuY3Rpb24oYykge1xuXHRcdFx0Y29uc3QgciA9ICgoZCArIE1hdGgucmFuZG9tKCkgKiAxNikgJSAxNikgfCAwO1xuXHRcdFx0ZCA9IE1hdGguZmxvb3IoZCAvIDE2KTtcblx0XHRcdHJldHVybiAoYyA9PT0gJ3gnID8gciA6IChyICYgMHgzKSB8IDB4OCkudG9TdHJpbmcoMTYpO1xuXHRcdH0pO1xuXHR9XG5cdC8qIHRzbGludDplbmFibGUgKi9cbn1cbiIsImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcblx0R3RDb2x1bW5QaXBlLFxuXHRHdENvbHVtblNldHRpbmdzQ29tcG9uZW50XG59IGZyb20gJy4vY29tcG9uZW50cy9ndC1jb2x1bW4tc2V0dGluZ3MuY29tcG9uZW50JztcbmltcG9ydCB7IEdlbmVyaWNUYWJsZU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyLWdlbmVyaWMtdGFibGUvY29yZSc7XG5pbXBvcnQgeyBEcmFndWxhTW9kdWxlIH0gZnJvbSAnbmcyLWRyYWd1bGEnO1xuXG5ATmdNb2R1bGUoe1xuXHRpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBHZW5lcmljVGFibGVNb2R1bGUsIERyYWd1bGFNb2R1bGVdLFxuXHRkZWNsYXJhdGlvbnM6IFtHdENvbHVtblNldHRpbmdzQ29tcG9uZW50LCBHdENvbHVtblBpcGVdLFxuXHRleHBvcnRzOiBbR3RDb2x1bW5TZXR0aW5nc0NvbXBvbmVudCwgR3RDb2x1bW5QaXBlXVxufSlcbmV4cG9ydCBjbGFzcyBDb2x1bW5TZXR0aW5nc01vZHVsZSB7fVxuIl0sIm5hbWVzIjpbIlBpcGUiLCJFdmVudEVtaXR0ZXIiLCJDb21wb25lbnQiLCJEcmFndWxhU2VydmljZSIsIkNoYW5nZURldGVjdG9yUmVmIiwiSW5wdXQiLCJWaWV3Q2hpbGQiLCJPdXRwdXQiLCJIb3N0TGlzdGVuZXIiLCJOZ01vZHVsZSIsIkNvbW1vbk1vZHVsZSIsIkdlbmVyaWNUYWJsZU1vZHVsZSIsIkRyYWd1bGFNb2R1bGUiXSwibWFwcGluZ3MiOiI7Ozs7OztJQUFBOzs7Ozs7Ozs7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