vix-ui
Version:
473 lines • 46.8 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import * as tslib_1 from "tslib";
import { Component, EventEmitter, Input, Output } from '@angular/core';
var VixPerformanceStatsComponent = /** @class */ (function () {
function VixPerformanceStatsComponent() {
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 {?}
*/
VixPerformanceStatsComponent.prototype.getRowsToShow = /**
* @return {?}
*/
function () {
var _this = this;
this.conceptsFiltered = this.concepts.slice();
if (this.selectedConcepts.length) {
this.conceptsFiltered = this.conceptsFiltered.filter(function (concept) { return _this.selectedConcepts.indexOf(concept) !== -1; });
}
this.nPages = this.pageSize ? Math.ceil(this.conceptsFiltered.length / this.pageSize) : 1;
this.computeAverage();
this.sortRows();
};
/**
* @return {?}
*/
VixPerformanceStatsComponent.prototype.sortRows = /**
* @return {?}
*/
function () {
var _this = this;
if (!this.sortCriteria || !this.sortCriteria.column || !this.sortCriteria.taskId) {
this.conceptsFiltered.sort();
if (this.sortCriteria && this.sortCriteria.direction === 'desc') {
this.conceptsFiltered.reverse();
}
}
else {
/** @type {?} */
var direction_1 = this.sortCriteria.direction || 'desc';
this.conceptsFiltered.sort(function (a, b) {
/** @type {?} */
var first = _this.data[_this.sortCriteria.taskId].metrics[_this.sortCriteria.column][a] || 0;
/** @type {?} */
var second = _this.data[_this.sortCriteria.taskId].metrics[_this.sortCriteria.column][b] || 0;
return (first - second) * (direction_1 === 'desc' ? -1 : 1);
});
}
this.page = 1;
this.changePage();
};
/**
* @return {?}
*/
VixPerformanceStatsComponent.prototype.computeAverage = /**
* @return {?}
*/
function () {
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
this.summaries = {};
try {
for (var _g = tslib_1.__values(Object.keys(this.data)), _h = _g.next(); !_h.done; _h = _g.next()) {
var id = _h.value;
this.summaries[id] = this.summaries[id] || {};
try {
for (var _j = tslib_1.__values(this.averageableColumns), _k = _j.next(); !_k.done; _k = _j.next()) {
var metric = _k.value;
this.summaries[id][metric] = this.summaries[id][metric] || {};
/** @type {?} */
var values = [];
/** @type {?} */
var weights = [];
var weightColumn = this.data[id].weightColumn;
try {
for (var _l = tslib_1.__values(Object.keys(this.data[id].metrics[metric])), _m = _l.next(); !_m.done; _m = _l.next()) {
var concept = _m.value;
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);
}
}
}
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_m && !_m.done && (_c = _l.return)) _c.call(_l);
}
finally { if (e_3) throw e_3.error; }
}
/** @type {?} */
var weightedSumOfMetrics = 0;
/** @type {?} */
var sum = 0;
for (var 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;
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
}
finally { if (e_2) throw e_2.error; }
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
}
finally { if (e_1) throw e_1.error; }
}
try {
for (var _o = tslib_1.__values(Object.keys(this.data)), _p = _o.next(); !_p.done; _p = _o.next()) {
var id = _p.value;
this.summaries[id] = this.summaries[id] || {};
try {
for (var _q = tslib_1.__values(this.summableColumns), _r = _q.next(); !_r.done; _r = _q.next()) {
var metric = _r.value;
this.summaries[id][metric] = this.summaries[id][metric] || {};
/** @type {?} */
var values = [];
try {
for (var _s = tslib_1.__values(Object.keys(this.data[id].metrics[metric])), _t = _s.next(); !_t.done; _t = _s.next()) {
var concept = _t.value;
if (!this.selectedConcepts.length || this.selectedConcepts.indexOf(concept) > -1) {
values.push(this.data[id].metrics[metric][concept]);
}
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_t && !_t.done && (_f = _s.return)) _f.call(_s);
}
finally { if (e_6) throw e_6.error; }
}
this.summaries[id][metric].sum = values.reduce(function (a, b) { return a + (b || 0); }, 0);
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_r && !_r.done && (_e = _q.return)) _e.call(_q);
}
finally { if (e_5) throw e_5.error; }
}
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_p && !_p.done && (_d = _o.return)) _d.call(_o);
}
finally { if (e_4) throw e_4.error; }
}
};
/**
* @param {?=} page
* @return {?}
*/
VixPerformanceStatsComponent.prototype.changePage = /**
* @param {?=} page
* @return {?}
*/
function (page) {
if (page) {
this.page = page;
}
this.page = Math.min(Math.max(+this.page, 1), this.nPages);
this.pageNums = [];
/** @type {?} */
var lowLimit;
/** @type {?} */
var 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 (var 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 {?}
*/
VixPerformanceStatsComponent.prototype.onChange = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.selectedConcepts = event;
this.getRowsToShow();
};
/**
* @param {?} i
* @return {?}
*/
VixPerformanceStatsComponent.prototype.counter = /**
* @param {?} i
* @return {?}
*/
function (i) {
return new Array(i);
};
/**
* @param {?=} taskId
* @param {?=} column
* @return {?}
*/
VixPerformanceStatsComponent.prototype.toggleSort = /**
* @param {?=} taskId
* @param {?=} column
* @return {?}
*/
function (taskId, column) {
if (!taskId || !column) {
/** @type {?} */
var direction = 'asc';
if (this.sortCriteria.direction === 'asc') {
direction = 'desc';
}
this.sortCriteria = { direction: direction };
}
else {
/** @type {?} */
var direction = 'desc';
if (this.sortCriteria.taskId === taskId && this.sortCriteria.column === column
&& this.sortCriteria.direction === 'desc') {
direction = 'asc';
}
this.sortCriteria = { column: column, taskId: taskId, direction: direction };
}
this.sortRows();
};
/**
* @return {?}
*/
VixPerformanceStatsComponent.prototype.getTableData = /**
* @return {?}
*/
function () {
var _this = this;
var e_7, _a;
/** @type {?} */
var combinedColumns = this.averageableColumns.concat(this.summableColumns);
/** @type {?} */
var tableHeader = ['concept'].concat(combinedColumns);
/** @type {?} */
var tableData = [];
var _loop_1 = function (concept) {
var e_8, _a;
/** @type {?} */
var row = { concept: concept };
var _loop_2 = function (column) {
row[column] = this_1.taskIds.map(function (taskId) { return _this.data[taskId].metrics[column][concept]; }).join(' / ');
};
try {
for (var combinedColumns_1 = tslib_1.__values(combinedColumns), combinedColumns_1_1 = combinedColumns_1.next(); !combinedColumns_1_1.done; combinedColumns_1_1 = combinedColumns_1.next()) {
var column = combinedColumns_1_1.value;
_loop_2(column);
}
}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {
try {
if (combinedColumns_1_1 && !combinedColumns_1_1.done && (_a = combinedColumns_1.return)) _a.call(combinedColumns_1);
}
finally { if (e_8) throw e_8.error; }
}
tableData.push(row);
};
var this_1 = this;
try {
for (var _b = tslib_1.__values(this.conceptsFiltered), _c = _b.next(); !_c.done; _c = _b.next()) {
var concept = _c.value;
_loop_1(concept);
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_7) throw e_7.error; }
}
this.tableExport.emit({ tableHeader: tableHeader, tableData: tableData });
};
/**
* @return {?}
*/
VixPerformanceStatsComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
// 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 {?}
*/
VixPerformanceStatsComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if (changes.data) {
this.initialize();
}
};
/**
* @return {?}
*/
VixPerformanceStatsComponent.prototype.initialize = /**
* @return {?}
*/
function () {
var e_9, _a, e_10, _b, e_11, _c;
this.taskIds = Object.keys(this.data);
this.sortCriteria = {};
this.selectedConcepts = [];
/** @type {?} */
var conceptsCombined = [];
try {
for (var _d = tslib_1.__values(this.taskIds), _e = _d.next(); !_e.done; _e = _d.next()) {
var taskId = _e.value;
conceptsCombined = conceptsCombined.concat(this.data[taskId].concepts);
}
}
catch (e_9_1) { e_9 = { error: e_9_1 }; }
finally {
try {
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
}
finally { if (e_9) throw e_9.error; }
}
this.concepts = Array.from(new Set(conceptsCombined));
try {
for (var _f = tslib_1.__values(this.taskIds), _g = _f.next(); !_g.done; _g = _f.next()) {
var taskId = _g.value;
try {
for (var _h = tslib_1.__values(this.averageableColumns.concat(this.summableColumns)), _j = _h.next(); !_j.done; _j = _h.next()) {
var column = _j.value;
this.data[taskId].metrics[column] = this.data[taskId].metrics[column] || {};
}
}
catch (e_11_1) { e_11 = { error: e_11_1 }; }
finally {
try {
if (_j && !_j.done && (_c = _h.return)) _c.call(_h);
}
finally { if (e_11) throw e_11.error; }
}
}
}
catch (e_10_1) { e_10 = { error: e_10_1 }; }
finally {
try {
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
}
finally { if (e_10) throw e_10.error; }
}
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 = function () { return []; };
VixPerformanceStatsComponent.propDecorators = {
averageableColumns: [{ type: Input }],
summableColumns: [{ type: Input }],
decimalPts: [{ type: Input }],
onConceptClick: [{ type: Input }],
pageSize: [{ type: Input }],
data: [{ type: Input }],
tableExport: [{ type: Output }]
};
return VixPerformanceStatsComponent;
}());
export { VixPerformanceStatsComponent };
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidml4LXBlcmZvcm1hbmNlLXN0YXRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3ZpeC11aS8iLCJzb3VyY2VzIjpbInZpeC1wZXJmb3JtYW5jZS1zdGF0cy92aXgtcGVyZm9ybWFuY2Utc3RhdHMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBb0MsTUFBTSxlQUFlLENBQUM7QUFFekc7SUE2QkU7UUF0QlMsdUJBQWtCLEdBQWEsRUFBRSxDQUFDO1FBQ2xDLG9CQUFlLEdBQWEsRUFBRSxDQUFDO1FBQy9CLGVBQVUsR0FBSyxDQUFDLENBQUM7UUFDakIsbUJBQWMsR0FBc0IsSUFBSSxDQUFDO1FBQ3pDLGFBQVEsR0FBRyxDQUFDLENBQUM7UUFDYixTQUFJLEdBQVEsRUFBRSxDQUFDO1FBRWQsZ0JBQVcsR0FBc0IsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUVuRSxhQUFRLEdBQWEsRUFBRSxDQUFDO1FBQ3hCLHFCQUFnQixHQUFhLEVBQUUsQ0FBQztRQUNoQyxXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsYUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNkLGNBQVMsR0FBUSxFQUFFLENBQUM7UUFDcEIsZ0JBQVcsR0FBRyxVQUFVLENBQUM7UUFDekIsWUFBTyxHQUFVLEVBQUUsQ0FBQztRQUNwQixnQkFBVyxHQUFhLEVBQUUsQ0FBQztRQUMzQixTQUFJLEdBQUcsQ0FBQyxDQUFDO1FBRUQscUJBQWdCLEdBQWEsRUFBRSxDQUFDO1FBQ2hDLGlCQUFZLEdBQVEsRUFBRSxDQUFDO0lBRWhCLENBQUM7Ozs7SUFFUixvREFBYTs7O0lBQXJCO1FBQUEsaUJBV0M7UUFWQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUU5QyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVB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QUNMLEtBQUs7aUNBQ0wsS0FBSzsyQkFDTCxLQUFLO3VCQUNMLEtBQUs7OEJBRUwsTUFBTTs7SUF5TVQsbUNBQUM7Q0FBQSxBQXZORCxJQXVOQztTQWxOWSw0QkFBNEI7OztJQUV2QywwREFBMkM7O0lBQzNDLHVEQUF3Qzs7SUFDeEMsa0RBQTBCOztJQUMxQixzREFBa0Q7O0lBQ2xELGdEQUFzQjs7SUFDdEIsNENBQXdCOztJQUV4QixtREFBbUU7O0lBRW5FLGdEQUF3Qjs7SUFDeEIsd0RBQWdDOztJQUNoQyw4Q0FBVzs7SUFDWCxnREFBYzs7SUFDZCxpREFBb0I7O0lBQ3BCLG1EQUF5Qjs7SUFDekIsK0NBQW9COztJQUNwQixtREFBMkI7O0lBQzNCLDRDQUFTOztJQUVULHdEQUF3Qzs7SUFDeEMsb0RBQStCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPdXRwdXQsIE9uQ2hhbmdlcywgT25Jbml0LCBTaW1wbGVDaGFuZ2VzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZpeC1wZXJmb3JtYW5jZS1zdGF0cycsXG4gIHRlbXBsYXRlVXJsOiAnLi92aXgtcGVyZm9ybWFuY2Utc3RhdHMuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi92aXgtcGVyZm9ybWFuY2Utc3RhdHMuY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgVml4UGVyZm9ybWFuY2VTdGF0c0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBASW5wdXQoKSBhdmVyYWdlYWJsZUNvbHVtbnM6IHN0cmluZ1tdID0gW107XG4gIEBJbnB1dCgpIHN1bW1hYmxlQ29sdW1uczogc3RyaW5nW10gPSBbXTtcbiAgQElucHV0KCkgZGVjaW1hbFB0cyA/ID0gNDtcbiAgQElucHV0KCkgb25Db25jZXB0Q2xpY2s/OiAoc3RyaW5nKSA9PiB2b2lkID0gbnVsbDtcbiAgQElucHV0KCkgcGFnZVNpemUgPSAwO1xuICBASW5wdXQoKSBkYXRhOiBhbnkgPSB7fTtcblxuICBAT3V0cHV0KCkgdGFibGVFeHBvcnQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgY29uY2VwdHM6IHN0cmluZ1tdID0gW107XG4gIHNlbGVjdGVkQ29uY2VwdHM6IHN0cmluZ1tdID0gW107XG4gIG5QYWdlcyA9IDE7XG4gIHBhZ2VOdW1zID0gW107XG4gIHN1bW1hcmllczogYW55ID0ge307XG4gIGF2ZXJhZ2VUeXBlID0gJ3dlaWdodGVkJztcbiAgdGFza0lkczogYW55W10gPSBbXTtcbiAgcm93T3JkZXJpbmc6IHN0cmluZ1tdID0gW107XG4gIHBhZ2UgPSAxO1xuXG4gIHByaXZhdGUgY29uY2VwdHNGaWx0ZXJlZDogc3RyaW5nW10gPSBbXTtcbiAgcHJpdmF0ZSBzb3J0Q3JpdGVyaWE6IGFueSA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKCkge31cblxuICBwcml2YXRlIGdldFJvd3NUb1Nob3coKTogdm9pZCB7XG4gICAgdGhpcy5jb25jZXB0c0ZpbHRlcmVkID0gdGhpcy5jb25jZXB0cy5zbGljZSgpO1xuXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRDb25jZXB0cy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuY29uY2VwdHNGaWx0ZXJlZCA9IHRoaXMuY29uY2VwdHNGaWx0ZXJlZC5maWx0ZXIoXG4gICAgICAgICAgY29uY2VwdCA9PiB0aGlzLnNlbGVjdGVkQ29uY2VwdHMuaW5kZXhPZihjb25jZXB0KSAhPT0gLTEpO1xuICAgIH1cblxuICAgIHRoaXMublBhZ2VzID0gdGhpcy5wYWdlU2l6ZSA/IE1hdGguY2VpbCh0aGlzLmNvbmNlcHRzRmlsdGVyZWQubGVuZ3RoIC8gdGhpcy5wYWdlU2l6ZSkgOiAxO1xuICAgIHRoaXMuY29tcHV0ZUF2ZXJhZ2UoKTtcbiAgICB0aGlzLnNvcnRSb3dzKCk7XG4gIH1cblxuICBwcml2YXRlIHNvcnRSb3dzKCkge1xuICAgIGlmICghdGhpcy5zb3J0Q3JpdGVyaWEgfHwgIXRoaXMuc29ydENyaXRlcmlhLmNvbHVtbiB8fCAhdGhpcy5zb3J0Q3JpdGVyaWEudGFza0lkKSB7XG4gICAgICB0aGlzLmNvbmNlcHRzRmlsdGVyZWQuc29ydCgpO1xuICAgICAgaWYgKHRoaXMuc29ydENyaXRlcmlhICYmIHRoaXMuc29ydENyaXRlcmlhLmRpcmVjdGlvbiA9PT0gJ2Rlc2MnKSB7XG4gICAgICAgIHRoaXMuY29uY2VwdHNGaWx0ZXJlZC5yZXZlcnNlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IHRoaXMuc29ydENyaXRlcmlhLmRpcmVjdGlvbiB8fCAnZGVzYyc7XG4gICAgICB0aGlzLmNvbmNlcHRzRmlsdGVyZWQuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICBjb25zdCBmaXJzdCA9IHRoaXMuZGF0YVt0aGlzLnNvcnRDcml0ZXJpYS50YXNrSWRdLm1ldHJpY3NbdGhpcy5zb3J0Q3JpdGVyaWEuY29sdW1uXVthXSB8fCAwO1xuICAgICAgICBjb25zdCBzZWNvbmQgPSB0aGlzLmRhdGFbdGhpcy5zb3J0Q3JpdGVyaWEudGFza0lkXS5tZXRyaWNzW3RoaXMuc29ydENyaXRlcmlhLmNvbHVtbl1bYl0gfHwgMDtcbiAgICAgICAgcmV0dXJuIChmaXJzdCAtIHNlY29uZCkgKiAoZGlyZWN0aW9uID09PSAnZGVzYycgPyAtMSA6IDEpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5wYWdlID0gMTtcbiAgICB0aGlzLmNoYW5nZVBhZ2UoKTtcbiAgfVxuXG4gIGNvbXB1dGVBdmVyYWdlKCk6IHZvaWQge1xuICAgIHRoaXMuc3VtbWFyaWVzID0ge307XG4gICAgZm9yIChjb25zdCBpZCBvZiBPYmplY3Qua2V5cyh0aGlzLmRhdGEpKSB7XG4gICAgICB0aGlzLnN1bW1hcmllc1tpZF0gPSB0aGlzLnN1bW1hcmllc1tpZF0gfHwge307XG4gICAgICBmb3IgKGNvbnN0IG1ldHJpYyBvZiB0aGlzLmF2ZXJhZ2VhYmxlQ29sdW1ucykge1xuICAgICAgICB0aGlzLnN1bW1hcmllc1tpZF1bbWV0cmljXSA9IHRoaXMuc3VtbWFyaWVzW2lkXVttZXRyaWNdIHx8IHt9O1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBbXTtcbiAgICAgICAgY29uc3Qgd2VpZ2h0cyA9IFtdO1xuICAgICAgICBjb25zdCB7IHdlaWdodENvbHVtbiB9ID0gdGhpcy5kYXRhW2lkXTtcbiAgICAgICAgZm9yIChjb25zdCBjb25jZXB0IG9mIE9iamVjdC5rZXlzKHRoaXMuZGF0YVtpZF0ubWV0cmljc1ttZXRyaWNdKSkge1xuICAgICAgICAgIGlmICghdGhpcy5zZWxlY3RlZENvbmNlcHRzLmxlbmd0aCB8fCB0aGlzLnNlbGVjdGVkQ29uY2VwdHMuaW5kZXhPZihjb25jZXB0KSA+IC0xKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuZGF0YVtpZF0ubWV0cmljc1ttZXRyaWNdW2NvbmNlcHRdID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICB2YWx1ZXMucHVzaCh0aGlzLmRhdGFbaWRdLm1ldHJpY3NbbWV0cmljXVtjb25jZXB0XSk7XG4gICAgICAgICAgICAgIGlmICh3ZWlnaHRDb2x1bW4gJiYgdGhpcy5hdmVyYWdlVHlwZSA9PT0gJ3dlaWdodGVkJykge1xuICAgICAgICAgICAgICAgIHdlaWdodHMucHVzaCgrdGhpcy5kYXRhW2lkXS5tZXRyaWNzW3dlaWdodENvbHVtbl1bY29uY2VwdF0gfHwgMCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgd2VpZ2h0cy5wdXNoKDEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHdlaWdodGVkU3VtT2ZNZXRyaWNzID0gMDtcbiAgICAgICAgbGV0IHN1bSA9IDA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgd2VpZ2h0ZWRTdW1PZk1ldHJpY3MgKz0gKHZhbHVlc1tpXSB8fCAwKSAqIHdlaWdodHNbaV07XG4gICAgICAgICAgc3VtICs9IHdlaWdodHNbaV07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdW1tYXJpZXNbaWRdW21ldHJpY10uc2ltcGxlQXZlcmFnZSA9IHZhbHVlcy5sZW5ndGggPyB3ZWlnaHRlZFN1bU9mTWV0cmljcyAvIHN1bSA6IDA7XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoY29uc3QgaWQgb2YgT2JqZWN0LmtleXModGhpcy5kYXRhKSkge1xuICAgICAgdGhpcy5zdW1tYXJpZXNbaWRdID0gdGhpcy5zdW1tYXJpZXNbaWRdIHx8IHt9O1xuICAgICAgZm9yIChjb25zdCBtZXRyaWMgb2YgdGhpcy5zdW1tYWJsZUNvbHVtbnMpIHtcbiAgICAgICAgdGhpcy5zdW1tYXJpZXNbaWRdW21ldHJpY10gPSB0aGlzLnN1bW1hcmllc1tpZF1bbWV0cmljXSB8fCB7fTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gW107XG4gICAgICAgIGZvciAoY29uc3QgY29uY2VwdCBvZiBPYmplY3Qua2V5cyh0aGlzLmRhdGFbaWRdLm1ldHJpY3NbbWV0cmljXSkpIHtcbiAgICAgICAgICBpZiAoIXRoaXMuc2VsZWN0ZWRDb25jZXB0cy5sZW5ndGggfHwgdGhpcy5zZWxlY3RlZENvbmNlcHRzLmluZGV4T2YoY29uY2VwdCkgPiAtMSkge1xuICAgICAgICAgICAgdmFsdWVzLnB1c2godGhpcy5kYXRhW2lkXS5tZXRyaWNzW21ldHJpY11bY29uY2VwdF0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN1bW1hcmllc1tpZF1bbWV0cmljXS5zdW0gPSB2YWx1ZXMucmVkdWNlKChhOiBudW1iZXIsIGI6IG51bWJlcikgPT4gYSArIChiIHx8IDApLCAwKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjaGFuZ2VQYWdlKHBhZ2U/OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAocGFnZSkge1xuICAgICAgdGhpcy5wYWdlID0gcGFnZTtcbiAgICB9XG4gICAgdGhpcy5wYWdlID0gTWF0aC5taW4oTWF0aC5tYXgoK3RoaXMucGFnZSwgMSksIHRoaXMublBhZ2VzKTtcbiAgICB0aGlzLnBhZ2VOdW1zID0gW107XG4gICAgbGV0IGxvd0xpbWl0O1xuICAgIGxldCB1cHBMaW1pdDtcbiAgICBpZiAodGhpcy5wYWdlIDw9IDIpIHtcbiAgICAgIGxvd0xpbWl0ID0gMTtcbiAgICAgIHVwcExpbWl0ID0gTWF0aC5taW4oNSwgdGhpcy5uUGFnZXMpO1xuICAgIH0gZWxzZSBpZiAoTWF0aC5hYnModGhpcy5wYWdlIC0gdGhpcy5uUGFnZXMpIDw9IDEpIHtcbiAgICAgIGxvd0xpbWl0ID0gTWF0aC5tYXgoMSwgdGhpcy5uUGFnZXMgLSA0KTtcbiAgICAgIHVwcExpbWl0ID0gdGhpcy5uUGFnZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvd0xpbWl0ID0gdGhpcy5wYWdlIC0gMjtcbiAgICAgIHVwcExpbWl0ID0gdGhpcy5wYWdlICsgMjtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IGxvd0xpbWl0OyBpIDw9IHVwcExpbWl0OyBpKyspIHtcbiAgICAgIHRoaXMucGFnZU51bXMgPSB0aGlzLnBhZ2VOdW1zLmNvbmNhdChbaV0pO1xuICAgIH1cbiAgICB0aGlzLnJvd09yZGVyaW5nID0gdGhpcy5jb25jZXB0c0ZpbHRlcmVkLnNsaWNlKCk7XG4gICAgaWYgKCF0aGlzLnBhZ2VTaXplKSB7XG4gICAgICAvLyBObyBwYWdpbmcgcmVxdWlyZWRcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yb3dPcmRlcmluZyA9IHRoaXMucm93T3JkZXJpbmcuc2xpY2UoKHRoaXMucGFnZSAtIDEpICogdGhpcy5wYWdlU2l6ZSwgdGhpcy5wYWdlICogdGhpcy5wYWdlU2l6ZSk7XG4gIH1cblxuICBvbkNoYW5nZShldmVudDogYW55KTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZENvbmNlcHRzID0gZXZlbnQ7XG4gICAgdGhpcy5nZXRSb3dzVG9TaG93KCk7XG4gIH1cblxuICBjb3VudGVyKGk6IG51bWJlcik6IEFycmF5PGFueT4ge1xuICAgIHJldHVybiBuZXcgQXJyYXkoaSk7XG4gIH1cblxuICB0b2dnbGVTb3J0KHRhc2tJZD86IG51bWJlciwgY29sdW1uPzogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0YXNrSWQgfHwgIWNvbHVtbikge1xuICAgICAgbGV0IGRpcmVjdGlvbiA9ICdhc2MnO1xuICAgICAgaWYgKHRoaXMuc29ydENyaXRlcmlhLmRpcmVjdGlvbiA9PT0gJ2FzYycpIHtcbiAgICAgICAgZGlyZWN0aW9uID0gJ2Rlc2MnO1xuICAgICAgfVxuICAgICAgdGhpcy5zb3J0Q3JpdGVyaWEgPSB7IGRpcmVjdGlvbiB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgZGlyZWN0aW9uID0gJ2Rlc2MnO1xuICAgICAgaWYgKHRoaXMuc29ydENyaXRlcmlhLnRhc2tJZCA9PT0gdGFza0lkICYmIHRoaXMuc29ydENyaXRlcmlhLmNvbHVtbiA9PT0gY29sdW1uXG4gICAgICAgICAgJiYgdGhpcy5zb3J0Q3JpdGVyaWEuZGlyZWN0aW9uID09PSAnZGVzYycpIHtcbiAgICAgICAgZGlyZWN0aW9uID0gJ2FzYyc7XG4gICAgICB9XG4gICAgICB0aGlzLnNvcnRDcml0ZXJpYSA9IHsgY29sdW1uLCB0YXNrSWQsIGRpcmVjdGlvbiB9O1xuICAgIH1cbiAgICB0aGlzLnNvcnRSb3dzKCk7XG4gIH1cblxuICBnZXRUYWJsZURhdGEoKSB7XG4gICAgY29uc3QgY29tYmluZWRDb2x1bW5zID0gdGhpcy5hdmVyYWdlYWJsZUNvbHVtbnMuY29uY2F0KHRoaXMuc3VtbWFibGVDb2x1bW5zKTtcbiAgICBjb25zdCB0YWJsZUhlYWRlciA9IFsnY29uY2VwdCddLmNvbmNhdChjb21iaW5lZENvbHVtbnMpO1xuICAgIGNvbnN0IHRhYmxlRGF0YSA9IFtdO1xuICAgIGZvciAoY29uc3QgY29uY2VwdCBvZiB0aGlzLmNvbmNlcHRzRmlsdGVyZWQpIHtcbiAgICAgIGNvbnN0IHJvdyA9IHsgY29uY2VwdCB9O1xuICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2YgY29tYmluZWRDb2x1bW5zKSB7XG4gICAgICAgIHJvd1tjb2x1bW5dID0gdGhpcy50YXNrSWRzLm1hcCh0YXNrSWQgPT4gdGhpcy5kYXRhW3Rhc2tJZF0ubWV0cmljc1tjb2x1bW5dW2NvbmNlcHRdKS5qb2luKCcgLyAnKTtcbiAgICAgIH1cbiAgICAgIHRhYmxlRGF0YS5wdXNoKHJvdyk7XG4gICAgfVxuICAgIHRoaXMudGFibGVFeHBvcnQuZW1pdCh7IHRhYmxlSGVhZGVyLCB0YWJsZURhdGEgfSk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBEZWNpbWFsIHB0cyBtdXN0IGJlIGJldHdlZW4gMC04IGluY2x1c2l2ZVxuICAgIHRoaXMuZGVjaW1hbFB0cyA9IE1hdGgubWluKE1hdGgubWF4KHRoaXMuZGVjaW1hbFB0cywgMCksIDgpO1xuXG4gICAgLy8gUGFnZSBzaXplIG11c3QgYmUgbm9uLXplcm87IHBhZ2Ugc2l6ZSA9IDAgbWVhbnMgYWxsIHRvIGJlIGRpc3BsYXllZCB3aXRob3V0IHBhZ2luZ1xuICAgIHRoaXMucGFnZVNpemUgPSBNYXRoLm1heCh0aGlzLnBhZ2VTaXplLCAwKTtcblxuICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzLmRhdGEpIHtcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICAgIH1cbiAgfVxuXG4gIGluaXRpYWxpemUoKTogdm9pZCB7XG4gICAgdGhpcy50YXNrSWRzID0gT2JqZWN0LmtleXModGhpcy5kYXRhKTtcbiAgICB0aGlzLnNvcnRDcml0ZXJpYSA9IHt9O1xuICAgIHRoaXMuc2VsZWN0ZWRDb25jZXB0cyA9IFtdO1xuXG4gICAgbGV0IGNvbmNlcHRzQ29tYmluZWQgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHRhc2tJZCBvZiB0aGlzLnRhc2tJZHMpIHtcbiAgICAgIGNvbmNlcHRzQ29tYmluZWQgPSBjb25jZXB0c0NvbWJpbmVkLmNvbmNhdCh0aGlzLmRhdGFbdGFza0lkXS5jb25jZXB0cyk7XG4gICAgfVxuICAgIHRoaXMuY29uY2VwdHMgPSBBcnJheS5mcm9tKG5ldyBTZXQoY29uY2VwdHNDb21iaW5lZCkpO1xuXG4gICAgZm9yIChjb25zdCB0YXNrSWQgb2YgdGhpcy50YXNrSWRzKSB7XG4gICAgICBmb3IgKGNvbnN0IGNvbHVtbiBvZiB0aGlzLmF2ZXJhZ2VhYmxlQ29sdW1ucy5jb25jYXQodGhpcy5zdW1tYWJsZUNvbHVtbnMpKSB7XG4gICAgICAgIHRoaXMuZGF0YVt0YXNrSWRdLm1ldHJpY3NbY29sdW1uXSA9IHRoaXMuZGF0YVt0YXNrSWRdLm1ldHJpY3NbY29sdW1uXSB8fCB7fTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmdldFJvd3NUb1Nob3coKTtcbiAgfVxuXG59XG4iXX0=