UNPKG

@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
(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\">&times;</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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