UNPKG

vix-ui

Version:

307 lines 38.8 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Component, EventEmitter, Input, Output } from '@angular/core'; export class VixPerformanceStatsComponent { constructor() { this.averageableColumns = []; this.summableColumns = []; this.decimalPts = 4; this.onConceptClick = null; this.pageSize = 0; this.data = {}; this.tableExport = new EventEmitter(); this.concepts = []; this.selectedConcepts = []; this.nPages = 1; this.pageNums = []; this.summaries = {}; this.averageType = 'weighted'; this.taskIds = []; this.rowOrdering = []; this.page = 1; this.conceptsFiltered = []; this.sortCriteria = {}; } /** * @return {?} */ getRowsToShow() { this.conceptsFiltered = this.concepts.slice(); if (this.selectedConcepts.length) { this.conceptsFiltered = this.conceptsFiltered.filter(concept => this.selectedConcepts.indexOf(concept) !== -1); } this.nPages = this.pageSize ? Math.ceil(this.conceptsFiltered.length / this.pageSize) : 1; this.computeAverage(); this.sortRows(); } /** * @return {?} */ sortRows() { if (!this.sortCriteria || !this.sortCriteria.column || !this.sortCriteria.taskId) { this.conceptsFiltered.sort(); if (this.sortCriteria && this.sortCriteria.direction === 'desc') { this.conceptsFiltered.reverse(); } } else { /** @type {?} */ const direction = this.sortCriteria.direction || 'desc'; this.conceptsFiltered.sort((a, b) => { /** @type {?} */ const first = this.data[this.sortCriteria.taskId].metrics[this.sortCriteria.column][a] || 0; /** @type {?} */ const second = this.data[this.sortCriteria.taskId].metrics[this.sortCriteria.column][b] || 0; return (first - second) * (direction === 'desc' ? -1 : 1); }); } this.page = 1; this.changePage(); } /** * @return {?} */ computeAverage() { this.summaries = {}; for (const id of Object.keys(this.data)) { this.summaries[id] = this.summaries[id] || {}; for (const metric of this.averageableColumns) { this.summaries[id][metric] = this.summaries[id][metric] || {}; /** @type {?} */ const values = []; /** @type {?} */ const weights = []; const { weightColumn } = this.data[id]; for (const concept of Object.keys(this.data[id].metrics[metric])) { if (!this.selectedConcepts.length || this.selectedConcepts.indexOf(concept) > -1) { if (typeof this.data[id].metrics[metric][concept] === 'number') { values.push(this.data[id].metrics[metric][concept]); if (weightColumn && this.averageType === 'weighted') { weights.push(+this.data[id].metrics[weightColumn][concept] || 0); } else { weights.push(1); } } } } /** @type {?} */ let weightedSumOfMetrics = 0; /** @type {?} */ let sum = 0; for (let i = 0; i < values.length; i++) { weightedSumOfMetrics += (values[i] || 0) * weights[i]; sum += weights[i]; } this.summaries[id][metric].simpleAverage = values.length ? weightedSumOfMetrics / sum : 0; } } for (const id of Object.keys(this.data)) { this.summaries[id] = this.summaries[id] || {}; for (const metric of this.summableColumns) { this.summaries[id][metric] = this.summaries[id][metric] || {}; /** @type {?} */ const values = []; for (const concept of Object.keys(this.data[id].metrics[metric])) { if (!this.selectedConcepts.length || this.selectedConcepts.indexOf(concept) > -1) { values.push(this.data[id].metrics[metric][concept]); } } this.summaries[id][metric].sum = values.reduce((a, b) => a + (b || 0), 0); } } } /** * @param {?=} page * @return {?} */ changePage(page) { if (page) { this.page = page; } this.page = Math.min(Math.max(+this.page, 1), this.nPages); this.pageNums = []; /** @type {?} */ let lowLimit; /** @type {?} */ let uppLimit; if (this.page <= 2) { lowLimit = 1; uppLimit = Math.min(5, this.nPages); } else if (Math.abs(this.page - this.nPages) <= 1) { lowLimit = Math.max(1, this.nPages - 4); uppLimit = this.nPages; } else { lowLimit = this.page - 2; uppLimit = this.page + 2; } for (let i = lowLimit; i <= uppLimit; i++) { this.pageNums = this.pageNums.concat([i]); } this.rowOrdering = this.conceptsFiltered.slice(); if (!this.pageSize) { // No paging required return; } this.rowOrdering = this.rowOrdering.slice((this.page - 1) * this.pageSize, this.page * this.pageSize); } /** * @param {?} event * @return {?} */ onChange(event) { this.selectedConcepts = event; this.getRowsToShow(); } /** * @param {?} i * @return {?} */ counter(i) { return new Array(i); } /** * @param {?=} taskId * @param {?=} column * @return {?} */ toggleSort(taskId, column) { if (!taskId || !column) { /** @type {?} */ let direction = 'asc'; if (this.sortCriteria.direction === 'asc') { direction = 'desc'; } this.sortCriteria = { direction }; } else { /** @type {?} */ let direction = 'desc'; if (this.sortCriteria.taskId === taskId && this.sortCriteria.column === column && this.sortCriteria.direction === 'desc') { direction = 'asc'; } this.sortCriteria = { column, taskId, direction }; } this.sortRows(); } /** * @return {?} */ getTableData() { /** @type {?} */ const combinedColumns = this.averageableColumns.concat(this.summableColumns); /** @type {?} */ const tableHeader = ['concept'].concat(combinedColumns); /** @type {?} */ const tableData = []; for (const concept of this.conceptsFiltered) { /** @type {?} */ const row = { concept }; for (const column of combinedColumns) { row[column] = this.taskIds.map(taskId => this.data[taskId].metrics[column][concept]).join(' / '); } tableData.push(row); } this.tableExport.emit({ tableHeader, tableData }); } /** * @return {?} */ ngOnInit() { // Decimal pts must be between 0-8 inclusive this.decimalPts = Math.min(Math.max(this.decimalPts, 0), 8); // Page size must be non-zero; page size = 0 means all to be displayed without paging this.pageSize = Math.max(this.pageSize, 0); this.initialize(); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (changes.data) { this.initialize(); } } /** * @return {?} */ initialize() { this.taskIds = Object.keys(this.data); this.sortCriteria = {}; this.selectedConcepts = []; /** @type {?} */ let conceptsCombined = []; for (const taskId of this.taskIds) { conceptsCombined = conceptsCombined.concat(this.data[taskId].concepts); } this.concepts = Array.from(new Set(conceptsCombined)); for (const taskId of this.taskIds) { for (const column of this.averageableColumns.concat(this.summableColumns)) { this.data[taskId].metrics[column] = this.data[taskId].metrics[column] || {}; } } this.getRowsToShow(); } } VixPerformanceStatsComponent.decorators = [ { type: Component, args: [{ selector: 'vix-performance-stats', template: "<ng-select\n style=\"margin-bottom: 15px; max-width: 600px;\"\n placeholder=\"Select concepts to display\"\n [dropdownPosition]=\"'top'\"\n [items]=\"concepts\"\n [multiple]=\"true\"\n [closeOnSelect]=\"false\"\n (ngModelChange)=\"onChange($event)\"\n [(ngModel)]=\"selectedConcepts\">\n</ng-select>\n<div class=\"table-container\">\n <table class=\"performance-stats-table\">\n <thead>\n <tr class=\"first-row\" *ngIf=\"taskIds.length === 1\">\n <th class=\"first-col\" (click)=\"toggleSort()\">Concept</th>\n <th *ngFor=\"let column of averageableColumns\" (click)=\"toggleSort(taskIds[0], column)\">{{ column }}</th>\n <th *ngFor=\"let column of summableColumns\" (click)=\"toggleSort(taskIds[0], column)\">{{ column }}</th>\n </tr>\n <tr class=\"first-row\" *ngIf=\"taskIds.length > 1\">\n <th class=\"first-col\" [attr.rowspan]=\"taskIds.length === 1 ? 1 : 2\" (click)=\"toggleSort()\">Concept</th>\n <th *ngFor=\"let column of averageableColumns\" [attr.colspan]=\"taskIds.length === 2 ? 3 : taskIds.length\">{{ column }}</th>\n <th *ngFor=\"let column of summableColumns\" [attr.colspan]=\"taskIds.length === 2 ? 3 : taskIds.length\">{{ column }}</th>\n </tr>\n <tr class=\"first-row\" *ngIf=\"taskIds.length > 1\">\n <ng-template ngFor let-column [ngForOf]=\"averageableColumns\">\n <ng-template ngFor let-taskId [ngForOf]=\"taskIds\">\n <th (click)=\"toggleSort(taskId, column)\">{{ taskId }}</th>\n </ng-template>\n <th *ngIf=\"taskIds.length === 2\">Delta</th>\n </ng-template> \n <ng-template ngFor let-column [ngForOf]=\"summableColumns\">\n <ng-template ngFor let-taskId [ngForOf]=\"taskIds\">\n <th (click)=\"toggleSort(taskId, column)\">{{ taskId }}</th>\n </ng-template>\n <th *ngIf=\"taskIds.length === 2\">Delta</th>\n </ng-template>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of rowOrdering\">\n <td class=\"first-col\" *ngIf=\"onConceptClick\"><a href=\"javascript:;\" (click)=\"onConceptClick(row)\">{{ row }}</a></td>\n <td class=\"first-col\" *ngIf=\"!onConceptClick\">{{ row }}</td>\n <ng-template ngFor let-column [ngForOf]=\"averageableColumns\">\n <ng-template ngFor let-taskId [ngForOf]=\"taskIds\">\n <td>{{ data[taskId].metrics[column][row] | decimalPoints:decimalPts }}</td>\n </ng-template>\n <td *ngIf=\"taskIds.length === 2\">\n <vix-delta [first]=\"data[taskIds[0]].metrics[column][row]\" [second]=\"data[taskIds[1]].metrics[column][row]\" [decimalPts]=\"decimalPts\"></vix-delta>\n </td>\n </ng-template> \n <ng-template ngFor let-column [ngForOf]=\"summableColumns\">\n <ng-template ngFor let-taskId [ngForOf]=\"taskIds\">\n <td>{{ data[taskId].metrics[column][row] }}</td>\n </ng-template>\n <td *ngIf=\"taskIds.length === 2\">\n <vix-delta [first]=\"data[taskIds[0]].metrics[column][row]\" [second]=\"data[taskIds[1]].metrics[column][row]\" [decimalPts]=\"decimalPts\"></vix-delta>\n </td>\n </ng-template>\n </tr>\n\n <!-- Summary row -->\n <tr class=\"last-row\">\n <td class=\"first-col\">Average / Total</td>\n <ng-template ngFor let-column [ngForOf]=\"averageableColumns\">\n <ng-template ngFor let-taskId [ngForOf]=\"taskIds\">\n <td>{{ summaries[taskId][column].simpleAverage | decimalPoints:decimalPts }}</td>\n </ng-template>\n <td *ngIf=\"taskIds.length === 2\">\n <vix-delta [first]=\"summaries[taskIds[0]][column].simpleAverage\" [second]=\"summaries[taskIds[1]][column].simpleAverage\" [decimalPts]=\"decimalPts\"></vix-delta>\n </td>\n </ng-template> \n <ng-template ngFor let-column [ngForOf]=\"summableColumns\">\n <ng-template ngFor let-taskId [ngForOf]=\"taskIds\">\n <td>{{ summaries[taskId][column].sum }}</td>\n </ng-template>\n <td *ngIf=\"taskIds.length === 2\">\n <vix-delta [first]=\"summaries[taskIds[0]][column].sum\" [second]=\"summaries[taskIds[1]][column].sum\" [decimalPts]=\"decimalPts\"></vix-delta>\n </td>\n </ng-template>\n </tr>\n </tbody>\n </table>\n</div>\n<div *ngIf=\"averageableColumns.length\" style=\"margin-top: 15px\">\n Select average type:\n <select [(ngModel)]=\"averageType\" (ngModelChange)=\"computeAverage()\">\n <option value=\"simple\">Simple average</option>\n <option value=\"weighted\">Weighted average</option>\n </select>\n</div>\n<div *ngIf=\"nPages > 1\" style=\"margin-top: 15px\">\n <span class=\"paginator\" (click)=\"changePage(1)\">\n <i class=\"ion-ios-rewind\"></i>\n </span>\n <span class=\"paginator\" (click)=\"changePage(page - 1)\">\n <i class=\"ion-android-arrow-dropleft\"></i>\n </span>\n <span *ngFor=\"let pageNum of pageNums\">\n <span class=\"paginator\" [ngClass]=\"{'active': page === pageNum}\" (click)=\"changePage(pageNum)\">{{ pageNum }}</span>\n </span>\n <span class=\"paginator\" (click)=\"changePage(page + 1)\">\n <i class=\"ion-android-arrow-dropright\"></i>\n </span>\n <span class=\"paginator\" (click)=\"changePage(nPages)\">\n <i class=\"ion-ios-fastforward\"></i>\n </span>\n Jump to page:\n <select [(ngModel)]=\"page\" (ngModelChange)=\"changePage()\">\n <option *ngFor=\"let in of counter(nPages); let i = index\" value=\"{{ i + 1 }}\">{{ i + 1 }}</option>\n </select>\n</div>\n<div style=\"margin-top: 15px;\">\n <a href=\"javascript:;\" (click)=\"getTableData()\">\n Download Table as CSV\n </a>\n</div>\n", styles: [".table-container{max-width:100%;overflow-x:auto}.performance-stats-table{border:1px solid gray}.performance-stats-table td,.performance-stats-table th{border:1px solid #d7d7d7;font-size:12px;min-width:60px;padding:6px}.performance-stats-table th{text-align:center}.performance-stats-table .first-col{background-color:#f5f6f7}.performance-stats-table .first-row{cursor:pointer}.performance-stats-table .first-row,.performance-stats-table .last-row{background-color:#f5f6f7;font-size:13px;font-weight:600}.paginator{padding-left:7px;padding-right:7px}.paginator:hover{background-color:#eee;cursor:pointer}.paginator.active{background-color:#ddd}:host /deep/ .ng-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option{font-size:12px}:host /deep/ .ng-select .ng-select-container .ng-value-container .ng-input,:host /deep/ .ng-select .ng-select-container .ng-value-container .ng-value-label{font-size:12px}:host /deep/ .ng-select .ng-select-container .ng-value-container .ng-placeholder{font-size:13px}"] }] } ]; VixPerformanceStatsComponent.ctorParameters = () => []; VixPerformanceStatsComponent.propDecorators = { averageableColumns: [{ type: Input }], summableColumns: [{ type: Input }], decimalPts: [{ type: Input }], onConceptClick: [{ type: Input }], pageSize: [{ type: Input }], data: [{ type: Input }], tableExport: [{ type: Output }] }; if (false) { /** @type {?} */ VixPerformanceStatsComponent.prototype.averageableColumns; /** @type {?} */ VixPerformanceStatsComponent.prototype.summableColumns; /** @type {?} */ VixPerformanceStatsComponent.prototype.decimalPts; /** @type {?} */ VixPerformanceStatsComponent.prototype.onConceptClick; /** @type {?} */ VixPerformanceStatsComponent.prototype.pageSize; /** @type {?} */ VixPerformanceStatsComponent.prototype.data; /** @type {?} */ VixPerformanceStatsComponent.prototype.tableExport; /** @type {?} */ VixPerformanceStatsComponent.prototype.concepts; /** @type {?} */ VixPerformanceStatsComponent.prototype.selectedConcepts; /** @type {?} */ VixPerformanceStatsComponent.prototype.nPages; /** @type {?} */ VixPerformanceStatsComponent.prototype.pageNums; /** @type {?} */ VixPerformanceStatsComponent.prototype.summaries; /** @type {?} */ VixPerformanceStatsComponent.prototype.averageType; /** @type {?} */ VixPerformanceStatsComponent.prototype.taskIds; /** @type {?} */ VixPerformanceStatsComponent.prototype.rowOrdering; /** @type {?} */ VixPerformanceStatsComponent.prototype.page; /** @type {?} */ VixPerformanceStatsComponent.prototype.conceptsFiltered; /** @type {?} */ VixPerformanceStatsComponent.prototype.sortCriteria; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidml4LXBlcmZvcm1hbmNlLXN0YXRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3ZpeC11aS8iLCJzb3VyY2VzIjpbInZpeC1wZXJmb3JtYW5jZS1zdGF0cy92aXgtcGVyZm9ybWFuY2Utc3RhdHMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFvQyxNQUFNLGVBQWUsQ0FBQztBQU96RyxNQUFNO0lBd0JKO1FBdEJTLHVCQUFrQixHQUFhLEVBQUUsQ0FBQztRQUNsQyxvQkFBZSxHQUFhLEVBQUUsQ0FBQztRQUMvQixlQUFVLEdBQUssQ0FBQyxDQUFDO1FBQ2pCLG1CQUFjLEdBQXNCLElBQUksQ0FBQztRQUN6QyxhQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2IsU0FBSSxHQUFRLEVBQUUsQ0FBQztRQUVkLGdCQUFXLEdBQXNCLElBQUksWUFBWSxFQUFPLENBQUM7UUFFbkUsYUFBUSxHQUFhLEVBQUUsQ0FBQztRQUN4QixxQkFBZ0IsR0FBYSxFQUFFLENBQUM7UUFDaEMsV0FBTSxHQUFHLENBQUMsQ0FBQztRQUNYLGFBQVEsR0FBRyxFQUFFLENBQUM7UUFDZCxjQUFTLEdBQVEsRUFBRSxDQUFDO1FBQ3BCLGdCQUFXLEdBQUcsVUFBVSxDQUFDO1FBQ3pCLFlBQU8sR0FBVSxFQUFFLENBQUM7UUFDcEIsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFDM0IsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUVELHFCQUFnQixHQUFhLEVBQUUsQ0FBQztRQUNoQyxpQkFBWSxHQUFRLEVBQUUsQ0FBQztJQUVoQixDQUFDOzs7O0lBRVIsYUFBYTtRQUNuQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUU5QyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUU7WUFDaEMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQy9EO1FBRUQsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUYsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsQixDQUFDOzs7O0lBRU8sUUFBUTtRQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRTtZQUNoRixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDN0IsSUFBSSxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxLQUFLLE1BQU0sRUFBRTtnQkFDL0QsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFDO2FBQ2pDO1NBQ0Y7YUFBTTs7a0JBQ0MsU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxJQUFJLE1BQU07WUFDdkQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTs7c0JBQzVCLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQzs7c0JBQ3JGLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDNUYsT0FBTyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1RCxDQUFDLENBQUMsQ0FBQztTQUNKO1FBRUQsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7UUFDZCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQzs7OztJQUVELGNBQWM7UUFDWixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNwQixLQUFLLE1BQU0sRUFBRSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3ZDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDOUMsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUU7Z0JBQzVDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7O3NCQUN4RCxNQUFNLEdBQUcsRUFBRTs7c0JBQ1gsT0FBTyxHQUFHLEVBQUU7c0JBQ1osRUFBRSxZQUFZLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDdEMsS0FBSyxNQUFNLE9BQU8sSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUU7b0JBQ2hFLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7d0JBQ2hGLElBQUksT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUU7NEJBQzlELE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQzs0QkFDcEQsSUFBSSxZQUFZLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxVQUFVLEVBQUU7Z0NBQ25ELE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzs2QkFDbEU7aUNBQU07Z0NBQ0wsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQzs2QkFDakI7eUJBQ0Y7cUJBQ0Y7aUJBQ0Y7O29CQUVHLG9CQUFvQixHQUFHLENBQUM7O29CQUN4QixHQUFHLEdBQUcsQ0FBQztnQkFDWCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDdEMsb0JBQW9CLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUN0RCxHQUFHLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUNuQjtnQkFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMzRjtTQUNGO1FBQ0QsS0FBSyxNQUFNLEVBQUUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN2QyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlDLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRTtnQkFDekMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQzs7c0JBQ3hELE1BQU0sR0FBRyxFQUFFO2dCQUNqQixLQUFLLE1BQU0sT0FBTyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRTtvQkFDaEUsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRTt3QkFDaEYsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO3FCQUNyRDtpQkFDRjtnQkFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBUyxFQUFFLENBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQzNGO1NBQ0Y7SUFDSCxDQUFDOzs7OztJQUVELFVBQVUsQ0FBQyxJQUFhO1FBQ3RCLElBQUksSUFBSSxFQUFFO1lBQ1IsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7U0FDbEI7UUFDRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDOztZQUNmLFFBQVE7O1lBQ1IsUUFBUTtRQUNaLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLEVBQUU7WUFDbEIsUUFBUSxHQUFHLENBQUMsQ0FBQztZQUNiLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDckM7YUFBTSxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ2pELFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1NBQ3hCO2FBQU07WUFDTCxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7WUFDekIsUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1NBQzFCO1FBQ0QsS0FBSyxJQUFJLENBQUMsR0FBRyxRQUFRLEVBQUUsQ0FBQyxJQUFJLFFBQVEsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN6QyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUMzQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2xCLHFCQUFxQjtZQUNyQixPQUFPO1NBQ1I7UUFDRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hHLENBQUM7Ozs7O0lBRUQsUUFBUSxDQUFDLEtBQVU7UUFDakIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztRQUM5QixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDdkIsQ0FBQzs7Ozs7SUFFRCxPQUFPLENBQUMsQ0FBUztRQUNmLE9BQU8sSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEIsQ0FBQzs7Ozs7O0lBRUQsVUFBVSxDQUFDLE1BQWUsRUFBRSxNQUFlO1FBQ3pDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUU7O2dCQUNsQixTQUFTLEdBQUcsS0FBSztZQUNyQixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxLQUFLLEtBQUssRUFBRTtnQkFDekMsU0FBUyxHQUFHLE1BQU0sQ0FBQzthQUNwQjtZQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxTQUFTLEVBQUUsQ0FBQztTQUNuQzthQUFNOztnQkFDRCxTQUFTLEdBQUcsTUFBTTtZQUN0QixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxLQUFLLE1BQU0sSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sS0FBSyxNQUFNO21CQUN2RSxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsS0FBSyxNQUFNLEVBQUU7Z0JBQzdDLFNBQVMsR0FBRyxLQUFLLENBQUM7YUFDbkI7WUFDRCxJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsQ0FBQztTQUNuRDtRQUNELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsQixDQUFDOzs7O0lBRUQsWUFBWTs7Y0FDSixlQUFlLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDOztjQUN0RSxXQUFXLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDOztjQUNqRCxTQUFTLEdBQUcsRUFBRTtRQUNwQixLQUFLLE1BQU0sT0FBTyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTs7a0JBQ3JDLEdBQUcsR0FBRyxFQUFFLE9BQU8sRUFBRTtZQUN2QixLQUFLLE1BQU0sTUFBTSxJQUFJLGVBQWUsRUFBRTtnQkFDcEMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDbEc7WUFDRCxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3JCO1FBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUNwRCxDQUFDOzs7O0lBRUQsUUFBUTtRQUNOLDRDQUE0QztRQUM1QyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTVELHFGQUFxRjtRQUNyRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQzs7Ozs7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFO1lBQ2hCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztTQUNuQjtJQUNILENBQUM7Ozs7SUFFRCxVQUFVO1FBQ1IsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QyxJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDOztZQUV2QixnQkFBZ0IsR0FBRyxFQUFFO1FBQ3pCLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNqQyxnQkFBZ0IsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUN4RTtRQUNELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7UUFFdEQsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2pDLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLEVBQUU7Z0JBQ3pFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQzthQUM3RTtTQUNGO1FBRUQsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7OztZQXJORixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLHVCQUF1QjtnQkFDakMsc25MQUFxRDs7YUFFdEQ7Ozs7aUNBR0UsS0FBSzs4QkFDTCxLQUFLO3lCQUNMLEtBQUs7NkJBQ0wsS0FBSzt1QkFDTCxLQUFLO21CQUNMLEtBQUs7MEJBRUwsTUFBTTs7OztJQVBQLDBEQUEyQzs7SUFDM0MsdURBQXdDOztJQUN4QyxrREFBMEI7O0lBQzFCLHNEQUFrRDs7SUFDbEQsZ0RBQXNCOztJQUN0Qiw0Q0FBd0I7O0lBRXhCLG1EQUFtRTs7SUFFbkUsZ0RBQXdCOztJQUN4Qix3REFBZ0M7O0lBQ2hDLDhDQUFXOztJQUNYLGdEQUFjOztJQUNkLGlEQUFvQjs7SUFDcEIsbURBQXlCOztJQUN6QiwrQ0FBb0I7O0lBQ3BCLG1EQUEyQjs7SUFDM0IsNENBQVM7O0lBRVQsd0RBQXdDOztJQUN4QyxvREFBK0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE91dHB1dCwgT25DaGFuZ2VzLCBPbkluaXQsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndml4LXBlcmZvcm1hbmNlLXN0YXRzJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3ZpeC1wZXJmb3JtYW5jZS1zdGF0cy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3ZpeC1wZXJmb3JtYW5jZS1zdGF0cy5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBWaXhQZXJmb3JtYW5jZVN0YXRzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuXG4gIEBJbnB1dCgpIGF2ZXJhZ2VhYmxlQ29sdW1uczogc3RyaW5nW10gPSBbXTtcbiAgQElucHV0KCkgc3VtbWFibGVDb2x1bW5zOiBzdHJpbmdbXSA9IFtdO1xuICBASW5wdXQoKSBkZWNpbWFsUHRzID8gPSA0O1xuICBASW5wdXQoKSBvbkNvbmNlcHRDbGljaz86IChzdHJpbmcpID0+IHZvaWQgPSBudWxsO1xuICBASW5wdXQoKSBwYWdlU2l6ZSA9IDA7XG4gIEBJbnB1dCgpIGRhdGE6IGFueSA9IHt9O1xuXG4gIEBPdXRwdXQoKSB0YWJsZUV4cG9ydDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBjb25jZXB0czogc3RyaW5nW10gPSBbXTtcbiAgc2VsZWN0ZWRDb25jZXB0czogc3RyaW5nW10gPSBbXTtcbiAgblBhZ2VzID0gMTtcbiAgcGFnZU51bXMgPSBbXTtcbiAgc3VtbWFyaWVzOiBhbnkgPSB7fTtcbiAgYXZlcmFnZVR5cGUgPSAnd2VpZ2h0ZWQnO1xuICB0YXNrSWRzOiBhbnlbXSA9IFtdO1xuICByb3dPcmRlcmluZzogc3RyaW5nW10gPSBbXTtcbiAgcGFnZSA9IDE7XG5cbiAgcHJpdmF0ZSBjb25jZXB0c0ZpbHRlcmVkOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIHNvcnRDcml0ZXJpYTogYW55ID0ge307XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIHByaXZhdGUgZ2V0Um93c1RvU2hvdygpOiB2b2lkIHtcbiAgICB0aGlzLmNvbmNlcHRzRmlsdGVyZWQgPSB0aGlzLmNvbmNlcHRzLnNsaWNlKCk7XG5cbiAgICBpZiAodGhpcy5zZWxlY3RlZENvbmNlcHRzLmxlbmd0aCkge1xuICAgICAgdGhpcy5jb25jZXB0c0ZpbHRlcmVkID0gdGhpcy5jb25jZXB0c0ZpbHRlcmVkLmZpbHRlcihcbiAgICAgICAgICBjb25jZXB0ID0+IHRoaXMuc2VsZWN0ZWRDb25jZXB0cy5pbmRleE9mKGNvbmNlcHQpICE9PSAtMSk7XG4gICAgfVxuXG4gICAgdGhpcy5uUGFnZXMgPSB0aGlzLnBhZ2VTaXplID8gTWF0aC5jZWlsKHRoaXMuY29uY2VwdHNGaWx0ZXJlZC5sZW5ndGggLyB0aGlzLnBhZ2VTaXplKSA6IDE7XG4gICAgdGhpcy5jb21wdXRlQXZlcmFnZSgpO1xuICAgIHRoaXMuc29ydFJvd3MoKTtcbiAgfVxuXG4gIHByaXZhdGUgc29ydFJvd3MoKSB7XG4gICAgaWYgKCF0aGlzLnNvcnRDcml0ZXJpYSB8fCAhdGhpcy5zb3J0Q3JpdGVyaWEuY29sdW1uIHx8ICF0aGlzLnNvcnRDcml0ZXJpYS50YXNrSWQpIHtcbiAgICAgIHRoaXMuY29uY2VwdHNGaWx0ZXJlZC5zb3J0KCk7XG4gICAgICBpZiAodGhpcy5zb3J0Q3JpdGVyaWEgJiYgdGhpcy5zb3J0Q3JpdGVyaWEuZGlyZWN0aW9uID09PSAnZGVzYycpIHtcbiAgICAgICAgdGhpcy5jb25jZXB0c0ZpbHRlcmVkLnJldmVyc2UoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZGlyZWN0aW9uID0gdGhpcy5zb3J0Q3JpdGVyaWEuZGlyZWN0aW9uIHx8ICdkZXNjJztcbiAgICAgIHRoaXMuY29uY2VwdHNGaWx0ZXJlZC5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpcnN0ID0gdGhpcy5kYXRhW3RoaXMuc29ydENyaXRlcmlhLnRhc2tJZF0ubWV0cmljc1t0aGlzLnNvcnRDcml0ZXJpYS5jb2x1bW5dW2FdIHx8IDA7XG4gICAgICAgIGNvbnN0IHNlY29uZCA9IHRoaXMuZGF0YVt0aGlzLnNvcnRDcml0ZXJpYS50YXNrSWRdLm1ldHJpY3NbdGhpcy5zb3J0Q3JpdGVyaWEuY29sdW1uXVtiXSB8fCAwO1xuICAgICAgICByZXR1cm4gKGZpcnN0IC0gc2Vjb25kKSAqIChkaXJlY3Rpb24gPT09ICdkZXNjJyA/IC0xIDogMSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnBhZ2UgPSAxO1xuICAgIHRoaXMuY2hhbmdlUGFnZSgpO1xuICB9XG5cbiAgY29tcHV0ZUF2ZXJhZ2UoKTogdm9pZCB7XG4gICAgdGhpcy5zdW1tYXJpZXMgPSB7fTtcbiAgICBmb3IgKGNvbnN0IGlkIG9mIE9iamVjdC5rZXlzKHRoaXMuZGF0YSkpIHtcbiAgICAgIHRoaXMuc3VtbWFyaWVzW2lkXSA9IHRoaXMuc3VtbWFyaWVzW2lkXSB8fCB7fTtcbiAgICAgIGZvciAoY29uc3QgbWV0cmljIG9mIHRoaXMuYXZlcmFnZWFibGVDb2x1bW5zKSB7XG4gICAgICAgIHRoaXMuc3VtbWFyaWVzW2lkXVttZXRyaWNdID0gdGhpcy5zdW1tYXJpZXNbaWRdW21ldHJpY10gfHwge307XG4gICAgICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgICAgICBjb25zdCB3ZWlnaHRzID0gW107XG4gICAgICAgIGNvbnN0IHsgd2VpZ2h0Q29sdW1uIH0gPSB0aGlzLmRhdGFbaWRdO1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmNlcHQgb2YgT2JqZWN0LmtleXModGhpcy5kYXRhW2lkXS5tZXRyaWNzW21ldHJpY10pKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkQ29uY2VwdHMubGVuZ3RoIHx8IHRoaXMuc2VsZWN0ZWRDb25jZXB0cy5pbmRleE9mKGNvbmNlcHQpID4gLTEpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5kYXRhW2lkXS5tZXRyaWNzW21ldHJpY11bY29uY2VwdF0gPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRoaXMuZGF0YVtpZF0ubWV0cmljc1ttZXRyaWNdW2NvbmNlcHRdKTtcbiAgICAgICAgICAgICAgaWYgKHdlaWdodENvbHVtbiAmJiB0aGlzLmF2ZXJhZ2VUeXBlID09PSAnd2VpZ2h0ZWQnKSB7XG4gICAgICAgICAgICAgICAgd2VpZ2h0cy5wdXNoKCt0aGlzLmRhdGFbaWRdLm1ldHJpY3Nbd2VpZ2h0Q29sdW1uXVtjb25jZXB0XSB8fCAwKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB3ZWlnaHRzLnB1c2goMSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgd2VpZ2h0ZWRTdW1PZk1ldHJpY3MgPSAwO1xuICAgICAgICBsZXQgc3VtID0gMDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB3ZWlnaHRlZFN1bU9mTWV0cmljcyArPSAodmFsdWVzW2ldIHx8IDApICogd2VpZ2h0c1tpXTtcbiAgICAgICAgICBzdW0gKz0gd2VpZ2h0c1tpXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN1bW1hcmllc1tpZF1bbWV0cmljXS5zaW1wbGVBdmVyYWdlID0gdmFsdWVzLmxlbmd0aCA/IHdlaWdodGVkU3VtT2ZNZXRyaWNzIC8gc3VtIDogMDtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCBpZCBvZiBPYmplY3Qua2V5cyh0aGlzLmRhdGEpKSB7XG4gICAgICB0aGlzLnN1bW1hcmllc1tpZF0gPSB0aGlzLnN1bW1hcmllc1tpZF0gfHwge307XG4gICAgICBmb3IgKGNvbnN0IG1ldHJpYyBvZiB0aGlzLnN1bW1hYmxlQ29sdW1ucykge1xuICAgICAgICB0aGlzLnN1bW1hcmllc1tpZF1bbWV0cmljXSA9IHRoaXMuc3VtbWFyaWVzW2lkXVttZXRyaWNdIHx8IHt9O1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBjb25jZXB0IG9mIE9iamVjdC5rZXlzKHRoaXMuZGF0YVtpZF0ubWV0cmljc1ttZXRyaWNdKSkge1xuICAgICAgICAgIGlmICghdGhpcy5zZWxlY3RlZENvbmNlcHRzLmxlbmd0aCB8fCB0aGlzLnNlbGVjdGVkQ29uY2VwdHMuaW5kZXhPZihjb25jZXB0KSA+IC0xKSB7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaCh0aGlzLmRhdGFbaWRdLm1ldHJpY3NbbWV0cmljXVtjb25jZXB0XSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3VtbWFyaWVzW2lkXVttZXRyaWNdLnN1bSA9IHZhbHVlcy5yZWR1Y2UoKGE6IG51bWJlciwgYjogbnVtYmVyKSA9PiBhICsgKGIgfHwgMCksIDApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNoYW5nZVBhZ2UocGFnZT86IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChwYWdlKSB7XG4gICAgICB0aGlzLnBhZ2UgPSBwYWdlO1xuICAgIH1cbiAgICB0aGlzLnBhZ2UgPSBNYXRoLm1pbihNYXRoLm1heCgrdGhpcy5wYWdlLCAxKSwgdGhpcy5uUGFnZXMpO1xuICAgIHRoaXMucGFnZU51bXMgPSBbXTtcbiAgICBsZXQgbG93TGltaXQ7XG4gICAgbGV0IHVwcExpbWl0O1xuICAgIGlmICh0aGlzLnBhZ2UgPD0gMikge1xuICAgICAgbG93TGltaXQgPSAxO1xuICAgICAgdXBwTGltaXQgPSBNYXRoLm1pbig1LCB0aGlzLm5QYWdlcyk7XG4gICAgfSBlbHNlIGlmIChNYXRoLmFicyh0aGlzLnBhZ2UgLSB0aGlzLm5QYWdlcykgPD0gMSkge1xuICAgICAgbG93TGltaXQgPSBNYXRoLm1heCgxLCB0aGlzLm5QYWdlcyAtIDQpO1xuICAgICAgdXBwTGltaXQgPSB0aGlzLm5QYWdlcztcbiAgICB9IGVsc2Uge1xuICAgICAgbG93TGltaXQgPSB0aGlzLnBhZ2UgLSAyO1xuICAgICAgdXBwTGltaXQgPSB0aGlzLnBhZ2UgKyAyO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gbG93TGltaXQ7IGkgPD0gdXBwTGltaXQ7IGkrKykge1xuICAgICAgdGhpcy5wYWdlTnVtcyA9IHRoaXMucGFnZU51bXMuY29uY2F0KFtpXSk7XG4gICAgfVxuICAgIHRoaXMucm93T3JkZXJpbmcgPSB0aGlzLmNvbmNlcHRzRmlsdGVyZWQuc2xpY2UoKTtcbiAgICBpZiAoIXRoaXMucGFnZVNpemUpIHtcbiAgICAgIC8vIE5vIHBhZ2luZyByZXF1aXJlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnJvd09yZGVyaW5nID0gdGhpcy5yb3dPcmRlcmluZy5zbGljZSgodGhpcy5wYWdlIC0gMSkgKiB0aGlzLnBhZ2VTaXplLCB0aGlzLnBhZ2UgKiB0aGlzLnBhZ2VTaXplKTtcbiAgfVxuXG4gIG9uQ2hhbmdlKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkQ29uY2VwdHMgPSBldmVudDtcbiAgICB0aGlzLmdldFJvd3NUb1Nob3coKTtcbiAgfVxuXG4gIGNvdW50ZXIoaTogbnVtYmVyKTogQXJyYXk8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBBcnJheShpKTtcbiAgfVxuXG4gIHRvZ2dsZVNvcnQodGFza0lkPzogbnVtYmVyLCBjb2x1bW4/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXRhc2tJZCB8fCAhY29sdW1uKSB7XG4gICAgICBsZXQgZGlyZWN0aW9uID0gJ2FzYyc7XG4gICAgICBpZiAodGhpcy5zb3J0Q3JpdGVyaWEuZGlyZWN0aW9uID09PSAnYXNjJykge1xuICAgICAgICBkaXJlY3Rpb24gPSAnZGVzYyc7XG4gICAgICB9XG4gICAgICB0aGlzLnNvcnRDcml0ZXJpYSA9IHsgZGlyZWN0aW9uIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBkaXJlY3Rpb24gPSAnZGVzYyc7XG4gICAgICBpZiAodGhpcy5zb3J0Q3JpdGVyaWEudGFza0lkID09PSB0YXNrSWQgJiYgdGhpcy5zb3J0Q3JpdGVyaWEuY29sdW1uID09PSBjb2x1bW5cbiAgICAgICAgICAmJiB0aGlzLnNvcnRDcml0ZXJpYS5kaXJlY3Rpb24gPT09ICdkZXNjJykge1xuICAgICAgICBkaXJlY3Rpb24gPSAnYXNjJztcbiAgICAgIH1cbiAgICAgIHRoaXMuc29ydENyaXRlcmlhID0geyBjb2x1bW4sIHRhc2tJZCwgZGlyZWN0aW9uIH07XG4gICAgfVxuICAgIHRoaXMuc29ydFJvd3MoKTtcbiAgfVxuXG4gIGdldFRhYmxlRGF0YSgpIHtcbiAgICBjb25zdCBjb21iaW5lZENvbHVtbnMgPSB0aGlzLmF2ZXJhZ2VhYmxlQ29sdW1ucy5jb25jYXQodGhpcy5zdW1tYWJsZUNvbHVtbnMpO1xuICAgIGNvbnN0IHRhYmxlSGVhZGVyID0gWydjb25jZXB0J10uY29uY2F0KGNvbWJpbmVkQ29sdW1ucyk7XG4gICAgY29uc3QgdGFibGVEYXRhID0gW107XG4gICAgZm9yIChjb25zdCBjb25jZXB0IG9mIHRoaXMuY29uY2VwdHNGaWx0ZXJlZCkge1xuICAgICAgY29uc3Qgcm93ID0geyBjb25jZXB0IH07XG4gICAgICBmb3IgKGNvbnN0IGNvbHVtbiBvZiBjb21iaW5lZENvbHVtbnMpIHtcbiAgICAgICAgcm93W2NvbHVtbl0gPSB0aGlzLnRhc2tJZHMubWFwKHRhc2tJZCA9PiB0aGlzLmRhdGFbdGFza0lkXS5tZXRyaWNzW2NvbHVtbl1bY29uY2VwdF0pLmpvaW4oJyAvICcpO1xuICAgICAgfVxuICAgICAgdGFibGVEYXRhLnB1c2gocm93KTtcbiAgICB9XG4gICAgdGhpcy50YWJsZUV4cG9ydC5lbWl0KHsgdGFibGVIZWFkZXIsIHRhYmxlRGF0YSB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIERlY2ltYWwgcHRzIG11c3QgYmUgYmV0d2VlbiAwLTggaW5jbHVzaXZlXG4gICAgdGhpcy5kZWNpbWFsUHRzID0gTWF0aC5taW4oTWF0aC5tYXgodGhpcy5kZWNpbWFsUHRzLCAwKSwgOCk7XG5cbiAgICAvLyBQYWdlIHNpemUgbXVzdCBiZSBub24temVybzsgcGFnZSBzaXplID0gMCBtZWFucyBhbGwgdG8gYmUgZGlzcGxheWVkIHdpdGhvdXQgcGFnaW5nXG4gICAgdGhpcy5wYWdlU2l6ZSA9IE1hdGgubWF4KHRoaXMucGFnZVNpemUsIDApO1xuXG4gICAgdGhpcy5pbml0aWFsaXplKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXMuZGF0YSkge1xuICAgICAgdGhpcy5pbml0aWFsaXplKCk7XG4gICAgfVxuICB9XG5cbiAgaW5pdGlhbGl6ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnRhc2tJZHMgPSBPYmplY3Qua2V5cyh0aGlzLmRhdGEpO1xuICAgIHRoaXMuc29ydENyaXRlcmlhID0ge307XG4gICAgdGhpcy5zZWxlY3RlZENvbmNlcHRzID0gW107XG5cbiAgICBsZXQgY29uY2VwdHNDb21iaW5lZCA9IFtdO1xuICAgIGZvciAoY29uc3QgdGFza0lkIG9mIHRoaXMudGFza0lkcykge1xuICAgICAgY29uY2VwdHNDb21iaW5lZCA9IGNvbmNlcHRzQ29tYmluZWQuY29uY2F0KHRoaXMuZGF0YVt0YXNrSWRdLmNvbmNlcHRzKTtcbiAgICB9XG4gICAgdGhpcy5jb25jZXB0cyA9IEFycmF5LmZyb20obmV3IFNldChjb25jZXB0c0NvbWJpbmVkKSk7XG5cbiAgICBmb3IgKGNvbnN0IHRhc2tJZCBvZiB0aGlzLnRhc2tJZHMpIHtcbiAgICAgIGZvciAoY29uc3QgY29sdW1uIG9mIHRoaXMuYXZlcmFnZWFibGVDb2x1bW5zLmNvbmNhdCh0aGlzLnN1bW1hYmxlQ29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5kYXRhW3Rhc2tJZF0ubWV0cmljc1tjb2x1bW5dID0gdGhpcy5kYXRhW3Rhc2tJZF0ubWV0cmljc1tjb2x1bW5dIHx8IHt9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZ2V0Um93c1RvU2hvdygpO1xuICB9XG5cbn1cbiJdfQ==