UNPKG

vix-ui

Version:

433 lines 40.8 kB
/** * @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'; import * as _ from 'lodash'; var VixConfusionMatrixComponent = /** @class */ (function () { function VixConfusionMatrixComponent() { this.pageSize = 0; this.data = {}; this.tableExport = new EventEmitter(); this.concepts = []; this.selectedConcepts = []; this.nPages = 1; this.pageNums = []; this.summaries = {}; this.overallSummaries = {}; this.summaryRows = ['TP', 'FP', 'FN', 'Support']; this.sortCriteria = {}; this.rowOrdering = []; this.taskIds = []; this.page = 1; this.conceptsFiltered = []; } /** * @param {?=} init * @return {?} */ VixConfusionMatrixComponent.prototype.getRowsToShow = /** * @param {?=} init * @return {?} */ function (init) { var _this = this; if (init === void 0) { init = false; } 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; if (!init && this.conceptsFiltered.length === this.concepts.length) { // Use overall summary which is cached in-memory this.summaries = _.cloneDeep(this.overallSummaries); } else { this.computeSummary(init); } this.toggleSort(); }; /** * @return {?} */ VixConfusionMatrixComponent.prototype.toggleSort = /** * @return {?} */ function () { var _this = this; if (this.sortCriteria.criteria === 'alpha') { this.conceptsFiltered.sort(); if (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.summaries[_this.sortCriteria.taskId][_this.sortCriteria.criteria][a] || 0; /** @type {?} */ var second = _this.summaries[_this.sortCriteria.taskId][_this.sortCriteria.criteria][b] || 0; return (first - second) * (direction_1 === 'desc' ? -1 : 1); }); } this.page = 1; this.changePage(); }; /** * @param {?} init * @return {?} */ VixConfusionMatrixComponent.prototype.computeSummary = /** * @param {?} init * @return {?} */ function (init) { var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e; this.summaries = {}; try { for (var _f = tslib_1.__values(this.taskIds), _g = _f.next(); !_g.done; _g = _f.next()) { var taskId = _g.value; this.summaries[taskId] = { TP: {}, FP: {}, FN: {}, Support: {}, }; try { for (var _h = tslib_1.__values(this.conceptsFiltered), _j = _h.next(); !_j.done; _j = _h.next()) { var concept = _j.value; this.summaries[taskId].TP[concept] = 0; this.summaries[taskId].FP[concept] = 0; this.summaries[taskId].FN[concept] = 0; this.summaries[taskId].Support[concept] = 0; } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_j && !_j.done && (_b = _h.return)) _b.call(_h); } finally { if (e_2) throw e_2.error; } } try { for (var _k = tslib_1.__values(this.conceptsFiltered), _l = _k.next(); !_l.done; _l = _k.next()) { var concept1 = _l.value; try { for (var _m = tslib_1.__values(this.conceptsFiltered), _o = _m.next(); !_o.done; _o = _m.next()) { var concept2 = _o.value; /** @type {?} */ var count = void 0; if (this.data[taskId].matrix[concept1]) { count = this.data[taskId].matrix[concept1][concept2] || 0; } else { count = 0; } if (concept1 === concept2) { this.summaries[taskId].TP[concept1] += count; } else { this.summaries[taskId].FN[concept1] += count; this.summaries[taskId].FP[concept2] += count; } this.summaries[taskId].Support[concept1] += count; } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (_o && !_o.done && (_d = _m.return)) _d.call(_m); } finally { if (e_4) throw e_4.error; } } } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_l && !_l.done && (_c = _k.return)) _c.call(_k); } finally { if (e_3) throw e_3.error; } } if (init) { this.overallSummaries[taskId] = { TP: {}, FP: {}, FN: {}, Support: {}, }; try { for (var _p = tslib_1.__values(this.conceptsFiltered), _q = _p.next(); !_q.done; _q = _p.next()) { var concept = _q.value; this.overallSummaries[taskId].TP[concept] = this.summaries[taskId].TP[concept]; this.overallSummaries[taskId].FP[concept] = this.summaries[taskId].FP[concept]; this.overallSummaries[taskId].FN[concept] = this.summaries[taskId].FN[concept]; this.overallSummaries[taskId].Support[concept] = this.summaries[taskId].Support[concept]; } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (_q && !_q.done && (_e = _p.return)) _e.call(_p); } finally { if (e_5) throw e_5.error; } } } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_g && !_g.done && (_a = _f.return)) _a.call(_f); } finally { if (e_1) throw e_1.error; } } }; /** * @param {?=} page * @return {?} */ VixConfusionMatrixComponent.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 {?} */ VixConfusionMatrixComponent.prototype.onChange = /** * @param {?} event * @return {?} */ function (event) { this.selectedConcepts = event; this.getRowsToShow(); }; /** * @param {?} i * @return {?} */ VixConfusionMatrixComponent.prototype.counter = /** * @param {?} i * @return {?} */ function (i) { return new Array(i); }; /** * @return {?} */ VixConfusionMatrixComponent.prototype.getTableData = /** * @return {?} */ function () { var _this = this; var e_6, _a; /** @type {?} */ var tableHeader = ['concept'].concat(this.conceptsFiltered); /** @type {?} */ var tableData = []; var _loop_1 = function (concept) { var e_7, _a; /** @type {?} */ var row = { concept: concept }; var _loop_2 = function (concept1) { row[concept1] = this_1.taskIds.map(function (taskId) { /** @type {?} */ var count = _this.data[taskId].matrix[concept][concept1]; return count == null ? '-' : count; }).join(' / '); }; try { for (var _b = tslib_1.__values(this_1.conceptsFiltered), _c = _b.next(); !_c.done; _c = _b.next()) { var concept1 = _c.value; _loop_2(concept1); } } 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; } } 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_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_6) throw e_6.error; } } this.tableExport.emit({ tableHeader: tableHeader, tableData: tableData }); }; /** * @return {?} */ VixConfusionMatrixComponent.prototype.ngOnInit = /** * @return {?} */ function () { // 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(); }; /** * @return {?} */ VixConfusionMatrixComponent.prototype.ngOnChanges = /** * @return {?} */ function () { this.initialize(); }; /** * @return {?} */ VixConfusionMatrixComponent.prototype.initialize = /** * @return {?} */ function () { var e_8, _a, e_9, _b, e_10, _c; this.taskIds = Object.keys(this.data); this.sortCriteria = { criteria: 'alpha', direction: 'asc', taskId: this.taskIds[0], }; 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_8_1) { e_8 = { error: e_8_1 }; } finally { try { if (_e && !_e.done && (_a = _d.return)) _a.call(_d); } finally { if (e_8) throw e_8.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.concepts), _j = _h.next(); !_j.done; _j = _h.next()) { var concept = _j.value; this.data[taskId].matrix[concept] = this.data[taskId].matrix[concept] || {}; } } catch (e_10_1) { e_10 = { error: e_10_1 }; } finally { try { if (_j && !_j.done && (_c = _h.return)) _c.call(_h); } finally { if (e_10) throw e_10.error; } } } } catch (e_9_1) { e_9 = { error: e_9_1 }; } finally { try { if (_g && !_g.done && (_b = _f.return)) _b.call(_f); } finally { if (e_9) throw e_9.error; } } this.getRowsToShow(true); }; VixConfusionMatrixComponent.decorators = [ { type: Component, args: [{ selector: 'vix-confusion-matrix', 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 style=\"margin-bottom: 15px;\">\n Sort by\n <select *ngIf=\"taskIds.length > 1\" [disabled]=\"sortCriteria.criteria == 'alpha'\" [(ngModel)]=\"sortCriteria.taskId\" (ngModelChange)=\"toggleSort()\">\n <option *ngFor=\"let taskId of taskIds\" value=\"{{ taskId }}\">Task {{ taskId }}</option>\n </select>\n <select [(ngModel)]=\"sortCriteria.criteria\" (ngModelChange)=\"toggleSort()\">\n <option value=\"alpha\">Alphabetical</option>\n <option *ngFor=\"let row of summaryRows\" value=\"{{ row }}\">{{ row }}</option>\n </select>\n <select [(ngModel)]=\"sortCriteria.direction\" (ngModelChange)=\"toggleSort()\">\n <option value=\"asc\">ascending</option>\n <option value=\"desc\">descending</option>\n </select>\n</div>\n<div class=\"table-container\">\n <table class=\"confusion-matrix-table\">\n <thead>\n <tr class=\"first-row\">\n <th class=\"first-col\">\n Concept\n <span *ngIf=\"taskIds.length > 1\">\n <br>\n ( {{ taskIds[0] }}\n <span *ngFor=\"let taskId of taskIds; let i = index\"><span *ngIf=\"i !== 0\">/ {{ taskId }}</span></span>\n )\n </span>\n </th>\n <th *ngFor=\"let concept of rowOrdering\">\n <div class=\"concept-header\" [ngbTooltip]=\"concept\">{{ concept }}</div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let concept1 of rowOrdering\">\n <td class=\"first-col\">{{ concept1 }}</td>\n <td *ngFor=\"let concept2 of rowOrdering\" [ngClass]=\"{ 'single-number': taskIds.length === 1 }\">\n <div>\n <span *ngFor=\"let taskId of taskIds; let i = index\">\n <span *ngIf=\"i !== 0\"> / </span>{{ data[taskId].matrix[concept1][concept2] | noEntry }}\n </span>\n </div>\n <div>\n <ngb-progressbar *ngIf=\"taskIds.length === 1\"\n type=\"{{ concept1 === concept2 ? 'success' : 'warning' }}\"\n [value]=\"data[taskIds[0]].matrix[concept1][concept2] / summaries[taskIds[0]].Support[concept1] * 100\"\n height=\"0.5rem\">\n </ngb-progressbar>\n </div>\n </td>\n </tr>\n <!-- Summary row -->\n <tr style=\"height: 15px;\"></tr>\n <tr class=\"summary-row\" *ngFor=\"let row of summaryRows\">\n <td class=\"first-col\">{{ row }}</td>\n <td *ngFor=\"let concept of rowOrdering\">\n <span *ngFor=\"let taskId of taskIds; let i = index\">\n <span *ngIf=\"i !== 0\"> / </span>{{ summaries[taskId][row][concept] }}\n </span>\n </td>\n </tr>\n </tbody>\n </table>\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}.confusion-matrix-table{border:1px solid gray}.confusion-matrix-table td,.confusion-matrix-table th{border:1px solid #d7d7d7;font-size:12px;min-width:60px;padding:6px}.confusion-matrix-table .single-number{padding:0}.confusion-matrix-table .single-number div:nth-child(1){padding:6px}.confusion-matrix-table th{text-align:center}.confusion-matrix-table .first-col{background-color:#f5f6f7}.confusion-matrix-table .summary-row .first-col{font-weight:600}.confusion-matrix-table .first-row{background-color:#f5f6f7;font-size:13px;font-weight:600}.confusion-matrix-table .concept-header{max-width:60px;overflow-x:hidden;text-overflow:ellipsis}.paginator{padding-left:7px;padding-right:7px}.paginator:hover{background-color:#eee;cursor:pointer}.paginator.active{background-color:#ddd}:host /deep/ .progress{background-color:#fff}: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}"] }] } ]; VixConfusionMatrixComponent.ctorParameters = function () { return []; }; VixConfusionMatrixComponent.propDecorators = { pageSize: [{ type: Input }], data: [{ type: Input }], tableExport: [{ type: Output }] }; return VixConfusionMatrixComponent; }()); export { VixConfusionMatrixComponent }; if (false) { /** @type {?} */ VixConfusionMatrixComponent.prototype.pageSize; /** @type {?} */ VixConfusionMatrixComponent.prototype.data; /** @type {?} */ VixConfusionMatrixComponent.prototype.tableExport; /** @type {?} */ VixConfusionMatrixComponent.prototype.concepts; /** @type {?} */ VixConfusionMatrixComponent.prototype.selectedConcepts; /** @type {?} */ VixConfusionMatrixComponent.prototype.nPages; /** @type {?} */ VixConfusionMatrixComponent.prototype.pageNums; /** @type {?} */ VixConfusionMatrixComponent.prototype.summaries; /** @type {?} */ VixConfusionMatrixComponent.prototype.overallSummaries; /** @type {?} */ VixConfusionMatrixComponent.prototype.summaryRows; /** @type {?} */ VixConfusionMatrixComponent.prototype.sortCriteria; /** @type {?} */ VixConfusionMatrixComponent.prototype.rowOrdering; /** @type {?} */ VixConfusionMatrixComponent.prototype.taskIds; /** @type {?} */ VixConfusionMatrixComponent.prototype.page; /** @type {?} */ VixConfusionMatrixComponent.prototype.conceptsFiltered; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidml4LWNvbmZ1c2lvbi1tYXRyaXguY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vdml4LXVpLyIsInNvdXJjZXMiOlsidml4LWNvbmZ1c2lvbi1tYXRyaXgvdml4LWNvbmZ1c2lvbi1tYXRyaXguY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFxQixNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUYsT0FBTyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUM7QUFFNUI7SUEwQkU7UUFuQlMsYUFBUSxHQUFHLENBQUMsQ0FBQztRQUNiLFNBQUksR0FBUSxFQUFFLENBQUM7UUFFZCxnQkFBVyxHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFDO1FBRW5FLGFBQVEsR0FBYSxFQUFFLENBQUM7UUFDeEIscUJBQWdCLEdBQWEsRUFBRSxDQUFDO1FBQ2hDLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFDWCxhQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ2QsY0FBUyxHQUFRLEVBQUUsQ0FBQztRQUNwQixxQkFBZ0IsR0FBUSxFQUFFLENBQUM7UUFDM0IsZ0JBQVcsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzVDLGlCQUFZLEdBQVEsRUFBRSxDQUFDO1FBQ3ZCLGdCQUFXLEdBQWEsRUFBRSxDQUFDO1FBQzNCLFlBQU8sR0FBVSxFQUFFLENBQUM7UUFDcEIsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUVELHFCQUFnQixHQUFhLEVBQUUsQ0FBQztJQUV6QixDQUFDOzs7OztJQUVSLG1EQUFhOzs7O0lBQXJCLFVBQXNCLElBQVk7UUFBbEMsaUJBZ0JDO1FBaEJxQixxQkFBQSxFQUFBLFlBQVk7UUFDaEMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFOUMsSUFB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QTNNRCxJQTJNQztTQXRNWSwyQkFBMkI7OztJQUV0QywrQ0FBc0I7O0lBQ3RCLDJDQUF3Qjs7SUFFeEIsa0RBQW1FOztJQUVuRSwrQ0FBd0I7O0lBQ3hCLHVEQUFnQzs7SUFDaEMsNkNBQVc7O0lBQ1gsK0NBQWM7O0lBQ2QsZ0RBQW9COztJQUNwQix1REFBMkI7O0lBQzNCLGtEQUE0Qzs7SUFDNUMsbURBQXVCOztJQUN2QixrREFBMkI7O0lBQzNCLDhDQUFvQjs7SUFDcEIsMkNBQVM7O0lBRVQsdURBQXdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkNoYW5nZXMsIE9uSW5pdCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZpeC1jb25mdXNpb24tbWF0cml4JyxcbiAgdGVtcGxhdGVVcmw6ICcuL3ZpeC1jb25mdXNpb24tbWF0cml4LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vdml4LWNvbmZ1c2lvbi1tYXRyaXguY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgVml4Q29uZnVzaW9uTWF0cml4Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuXG4gIEBJbnB1dCgpIHBhZ2VTaXplID0gMDtcbiAgQElucHV0KCkgZGF0YTogYW55ID0ge307XG5cbiAgQE91dHB1dCgpIHRhYmxlRXhwb3J0OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIGNvbmNlcHRzOiBzdHJpbmdbXSA9IFtdO1xuICBzZWxlY3RlZENvbmNlcHRzOiBzdHJpbmdbXSA9IFtdO1xuICBuUGFnZXMgPSAxO1xuICBwYWdlTnVtcyA9IFtdO1xuICBzdW1tYXJpZXM6IGFueSA9IHt9O1xuICBvdmVyYWxsU3VtbWFyaWVzOiBhbnkgPSB7fTtcbiAgc3VtbWFyeVJvd3MgPSBbJ1RQJywgJ0ZQJywgJ0ZOJywgJ1N1cHBvcnQnXTtcbiAgc29ydENyaXRlcmlhOiBhbnkgPSB7fTtcbiAgcm93T3JkZXJpbmc6IHN0cmluZ1tdID0gW107XG4gIHRhc2tJZHM6IGFueVtdID0gW107XG4gIHBhZ2UgPSAxO1xuXG4gIHByaXZhdGUgY29uY2VwdHNGaWx0ZXJlZDogc3RyaW5nW10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgcHJpdmF0ZSBnZXRSb3dzVG9TaG93KGluaXQgPSBmYWxzZSk6IHZvaWQge1xuICAgIHRoaXMuY29uY2VwdHNGaWx0ZXJlZCA9IHRoaXMuY29uY2VwdHMuc2xpY2UoKTtcblxuICAgIGlmICh0aGlzLnNlbGVjdGVkQ29uY2VwdHMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmNvbmNlcHRzRmlsdGVyZWQgPSB0aGlzLmNvbmNlcHRzRmlsdGVyZWQuZmlsdGVyKFxuICAgICAgICAgIGNvbmNlcHQgPT4gdGhpcy5zZWxlY3RlZENvbmNlcHRzLmluZGV4T2YoY29uY2VwdCkgIT09IC0xKTtcbiAgICB9XG5cbiAgICB0aGlzLm5QYWdlcyA9IHRoaXMucGFnZVNpemUgPyBNYXRoLmNlaWwodGhpcy5jb25jZXB0c0ZpbHRlcmVkLmxlbmd0aCAvIHRoaXMucGFnZVNpemUpIDogMTtcbiAgICBpZiAoIWluaXQgJiYgdGhpcy5jb25jZXB0c0ZpbHRlcmVkLmxlbmd0aCA9PT0gdGhpcy5jb25jZXB0cy5sZW5ndGgpIHtcbiAgICAgIC8vIFVzZSBvdmVyYWxsIHN1bW1hcnkgd2hpY2ggaXMgY2FjaGVkIGluLW1lbW9yeVxuICAgICAgdGhpcy5zdW1tYXJpZXMgPSBfLmNsb25lRGVlcCh0aGlzLm92ZXJhbGxTdW1tYXJpZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNvbXB1dGVTdW1tYXJ5KGluaXQpO1xuICAgIH1cbiAgICB0aGlzLnRvZ2dsZVNvcnQoKTtcbiAgfVxuXG4gIHRvZ2dsZVNvcnQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc29ydENyaXRlcmlhLmNyaXRlcmlhID09PSAnYWxwaGEnKSB7XG4gICAgICB0aGlzLmNvbmNlcHRzRmlsdGVyZWQuc29ydCgpO1xuICAgICAgaWYgKHRoaXMuc29ydENyaXRlcmlhLmRpcmVjdGlvbiA9PT0gJ2Rlc2MnKSB7XG4gICAgICAgIHRoaXMuY29uY2VwdHNGaWx0ZXJlZC5yZXZlcnNlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IHRoaXMuc29ydENyaXRlcmlhLmRpcmVjdGlvbiB8fCAnZGVzYyc7XG4gICAgICB0aGlzLmNvbmNlcHRzRmlsdGVyZWQuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICBjb25zdCBmaXJzdCA9IHRoaXMuc3VtbWFyaWVzW3RoaXMuc29ydENyaXRlcmlhLnRhc2tJZF1bdGhpcy5zb3J0Q3JpdGVyaWEuY3JpdGVyaWFdW2FdIHx8IDA7XG4gICAgICAgIGNvbnN0IHNlY29uZCA9IHRoaXMuc3VtbWFyaWVzW3RoaXMuc29ydENyaXRlcmlhLnRhc2tJZF1bdGhpcy5zb3J0Q3JpdGVyaWEuY3JpdGVyaWFdW2JdIHx8IDA7XG4gICAgICAgIHJldHVybiAoZmlyc3QgLSBzZWNvbmQpICogKGRpcmVjdGlvbiA9PT0gJ2Rlc2MnID8gLTEgOiAxKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMucGFnZSA9IDE7XG4gICAgdGhpcy5jaGFuZ2VQYWdlKCk7XG4gIH1cblxuICBjb21wdXRlU3VtbWFyeShpbml0OiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5zdW1tYXJpZXMgPSB7fTtcbiAgICBmb3IgKGNvbnN0IHRhc2tJZCBvZiB0aGlzLnRhc2tJZHMpIHtcbiAgICAgIHRoaXMuc3VtbWFyaWVzW3Rhc2tJZF0gPSB7XG4gICAgICAgIFRQOiB7fSxcbiAgICAgICAgRlA6IHt9LFxuICAgICAgICBGTjoge30sXG4gICAgICAgIFN1cHBvcnQ6IHt9LFxuICAgICAgfTtcbiAgICAgIGZvciAoY29uc3QgY29uY2VwdCBvZiB0aGlzLmNvbmNlcHRzRmlsdGVyZWQpIHtcbiAgICAgICAgdGhpcy5zdW1tYXJpZXNbdGFza0lkXS5UUFtjb25jZXB0XSA9IDA7XG4gICAgICAgIHRoaXMuc3VtbWFyaWVzW3Rhc2tJZF0uRlBbY29uY2VwdF0gPSAwO1xuICAgICAgICB0aGlzLnN1bW1hcmllc1t0YXNrSWRdLkZOW2NvbmNlcHRdID0gMDtcbiAgICAgICAgdGhpcy5zdW1tYXJpZXNbdGFza0lkXS5TdXBwb3J0W2NvbmNlcHRdID0gMDtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgY29uY2VwdDEgb2YgdGhpcy5jb25jZXB0c0ZpbHRlcmVkKSB7XG4gICAgICAgIGZvciAoY29uc3QgY29uY2VwdDIgb2YgdGhpcy5jb25jZXB0c0ZpbHRlcmVkKSB7XG4gICAgICAgICAgbGV0IGNvdW50O1xuICAgICAgICAgIGlmICh0aGlzLmRhdGFbdGFza0lkXS5tYXRyaXhbY29uY2VwdDFdKSB7XG4gICAgICAgICAgICBjb3VudCA9IHRoaXMuZGF0YVt0YXNrSWRdLm1hdHJpeFtjb25jZXB0MV1bY29uY2VwdDJdIHx8IDA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvdW50ID0gMDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGNvbmNlcHQxID09PSBjb25jZXB0Mikge1xuICAgICAgICAgICAgdGhpcy5zdW1tYXJpZXNbdGFza0lkXS5UUFtjb25jZXB0MV0gKz0gY291bnQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3VtbWFyaWVzW3Rhc2tJZF0uRk5bY29uY2VwdDFdICs9IGNvdW50O1xuICAgICAgICAgICAgdGhpcy5zdW1tYXJpZXNbdGFza0lkXS5GUFtjb25jZXB0Ml0gKz0gY291bnQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuc3VtbWFyaWVzW3Rhc2tJZF0uU3VwcG9ydFtjb25jZXB0MV0gKz0gY291bnQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChpbml0KSB7XG4gICAgICAgIHRoaXMub3ZlcmFsbFN1bW1hcmllc1t0YXNrSWRdID0ge1xuICAgICAgICAgIFRQOiB7fSxcbiAgICAgICAgICBGUDoge30sXG4gICAgICAgICAgRk46IHt9LFxuICAgICAgICAgIFN1cHBvcnQ6IHt9LFxuICAgICAgICB9O1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmNlcHQgb2YgdGhpcy5jb25jZXB0c0ZpbHRlcmVkKSB7XG4gICAgICAgICAgdGhpcy5vdmVyYWxsU3VtbWFyaWVzW3Rhc2tJZF0uVFBbY29uY2VwdF0gPSB0aGlzLnN1bW1hcmllc1t0YXNrSWRdLlRQW2NvbmNlcHRdO1xuICAgICAgICAgIHRoaXMub3ZlcmFsbFN1bW1hcmllc1t0YXNrSWRdLkZQW2NvbmNlcHRdID0gdGhpcy5zdW1tYXJpZXNbdGFza0lkXS5GUFtjb25jZXB0XTtcbiAgICAgICAgICB0aGlzLm92ZXJhbGxTdW1tYXJpZXNbdGFza0lkXS5GTltjb25jZXB0XSA9IHRoaXMuc3VtbWFyaWVzW3Rhc2tJZF0uRk5bY29uY2VwdF07XG4gICAgICAgICAgdGhpcy5vdmVyYWxsU3VtbWFyaWVzW3Rhc2tJZF0uU3VwcG9ydFtjb25jZXB0XSA9IHRoaXMuc3VtbWFyaWVzW3Rhc2tJZF0uU3VwcG9ydFtjb25jZXB0XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNoYW5nZVBhZ2UocGFnZT86IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChwYWdlKSB7XG4gICAgICB0aGlzLnBhZ2UgPSBwYWdlO1xuICAgIH1cbiAgICB0aGlzLnBhZ2UgPSBNYXRoLm1pbihNYXRoLm1heCgrdGhpcy5wYWdlLCAxKSwgdGhpcy5uUGFnZXMpO1xuICAgIHRoaXMucGFnZU51bXMgPSBbXTtcbiAgICBsZXQgbG93TGltaXQ7XG4gICAgbGV0IHVwcExpbWl0O1xuICAgIGlmICh0aGlzLnBhZ2UgPD0gMikge1xuICAgICAgbG93TGltaXQgPSAxO1xuICAgICAgdXBwTGltaXQgPSBNYXRoLm1pbig1LCB0aGlzLm5QYWdlcyk7XG4gICAgfSBlbHNlIGlmIChNYXRoLmFicyh0aGlzLnBhZ2UgLSB0aGlzLm5QYWdlcykgPD0gMSkge1xuICAgICAgbG93TGltaXQgPSBNYXRoLm1heCgxLCB0aGlzLm5QYWdlcyAtIDQpO1xuICAgICAgdXBwTGltaXQgPSB0aGlzLm5QYWdlcztcbiAgICB9IGVsc2Uge1xuICAgICAgbG93TGltaXQgPSB0aGlzLnBhZ2UgLSAyO1xuICAgICAgdXBwTGltaXQgPSB0aGlzLnBhZ2UgKyAyO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gbG93TGltaXQ7IGkgPD0gdXBwTGltaXQ7IGkrKykge1xuICAgICAgdGhpcy5wYWdlTnVtcyA9IHRoaXMucGFnZU51bXMuY29uY2F0KFtpXSk7XG4gICAgfVxuICAgIHRoaXMucm93T3JkZXJpbmcgPSB0aGlzLmNvbmNlcHRzRmlsdGVyZWQuc2xpY2UoKTtcbiAgICBpZiAoIXRoaXMucGFnZVNpemUpIHtcbiAgICAgIC8vIE5vIHBhZ2luZyByZXF1aXJlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnJvd09yZGVyaW5nID0gdGhpcy5yb3dPcmRlcmluZy5zbGljZSgodGhpcy5wYWdlIC0gMSkgKiB0aGlzLnBhZ2VTaXplLCB0aGlzLnBhZ2UgKiB0aGlzLnBhZ2VTaXplKTtcbiAgfVxuXG4gIG9uQ2hhbmdlKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkQ29uY2VwdHMgPSBldmVudDtcbiAgICB0aGlzLmdldFJvd3NUb1Nob3coKTtcbiAgfVxuXG4gIGNvdW50ZXIoaTogbnVtYmVyKTogQXJyYXk8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBBcnJheShpKTtcbiAgfVxuXG4gIGdldFRhYmxlRGF0YSgpIHtcbiAgICBjb25zdCB0YWJsZUhlYWRlciA9IFsnY29uY2VwdCddLmNvbmNhdCh0aGlzLmNvbmNlcHRzRmlsdGVyZWQpO1xuICAgIGNvbnN0IHRhYmxlRGF0YSA9IFtdO1xuICAgIGZvciAoY29uc3QgY29uY2VwdCBvZiB0aGlzLmNvbmNlcHRzRmlsdGVyZWQpIHtcbiAgICAgIGNvbnN0IHJvdyA9IHsgY29uY2VwdCB9O1xuICAgICAgZm9yIChjb25zdCBjb25jZXB0MSBvZiB0aGlzLmNvbmNlcHRzRmlsdGVyZWQpIHtcbiAgICAgICAgcm93W2NvbmNlcHQxXSA9IHRoaXMudGFza0lkcy5tYXAodGFza0lkID0+IHtcbiAgICAgICAgICBjb25zdCBjb3VudCA9IHRoaXMuZGF0YVt0YXNrSWRdLm1hdHJpeFtjb25jZXB0XVtjb25jZXB0MV07XG4gICAgICAgICAgcmV0dXJuIGNvdW50ID09IG51bGwgPyAnLScgOiBjb3VudDtcbiAgICAgICAgfSkuam9pbignIC8gJyk7XG4gICAgICB9XG4gICAgICB0YWJsZURhdGEucHVzaChyb3cpO1xuICAgIH1cbiAgICB0aGlzLnRhYmxlRXhwb3J0LmVtaXQoeyB0YWJsZUhlYWRlciwgdGFibGVEYXRhIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgLy8gUGFnZSBzaXplIG11c3QgYmUgbm9uLXplcm87IHBhZ2Ugc2l6ZSA9IDAgbWVhbnMgYWxsIHRvIGJlIGRpc3BsYXllZCB3aXRob3V0IHBhZ2luZ1xuICAgIHRoaXMucGFnZVNpemUgPSBNYXRoLm1heCh0aGlzLnBhZ2VTaXplLCAwKTtcblxuICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5pbml0aWFsaXplKCk7XG4gIH1cblxuICBpbml0aWFsaXplKCk6IHZvaWQge1xuICAgIHRoaXMudGFza0lkcyA9IE9iamVjdC5rZXlzKHRoaXMuZGF0YSk7XG4gICAgdGhpcy5zb3J0Q3JpdGVyaWEgPSB7XG4gICAgICBjcml0ZXJpYTogJ2FscGhhJyxcbiAgICAgIGRpcmVjdGlvbjogJ2FzYycsXG4gICAgICB0YXNrSWQ6IHRoaXMudGFza0lkc1swXSxcbiAgICB9O1xuICAgIHRoaXMuc2VsZWN0ZWRDb25jZXB0cyA9IFtdO1xuXG4gICAgbGV0IGNvbmNlcHRzQ29tYmluZWQgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHRhc2tJZCBvZiB0aGlzLnRhc2tJZHMpIHtcbiAgICAgIGNvbmNlcHRzQ29tYmluZWQgPSBjb25jZXB0c0NvbWJpbmVkLmNvbmNhdCh0aGlzLmRhdGFbdGFza0lkXS5jb25jZXB0cyk7XG4gICAgfVxuICAgIHRoaXMuY29uY2VwdHMgPSBBcnJheS5mcm9tKG5ldyBTZXQoY29uY2VwdHNDb21iaW5lZCkpO1xuXG4gICAgZm9yIChjb25zdCB0YXNrSWQgb2YgdGhpcy50YXNrSWRzKSB7XG4gICAgICBmb3IgKGNvbnN0IGNvbmNlcHQgb2YgdGhpcy5jb25jZXB0cykge1xuICAgICAgICB0aGlzLmRhdGFbdGFza0lkXS5tYXRyaXhbY29uY2VwdF0gPSB0aGlzLmRhdGFbdGFza0lkXS5tYXRyaXhbY29uY2VwdF0gfHwge307XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5nZXRSb3dzVG9TaG93KHRydWUpO1xuICB9XG5cbn1cbiJdfQ==