UNPKG

@dbg-riskit/angular-testing

Version:

556 lines 67.6 kB
import { Component } from '@angular/core'; import { MatAnchor, MatButton } from '@angular/material/button'; import { MatButtonToggle } from '@angular/material/button-toggle'; import { MatIcon } from '@angular/material/icon'; import { MatTooltip } from '@angular/material/tooltip'; import { By } from '@angular/platform-browser'; import { secureRandom } from '@dbg-riskit/common'; import { DataTableComponent, DataTableRowDetailExpanderComponent, HIGHLIGHTER_CLASS, PagingComponent } from '@dbg-riskit/angular-datatable'; import { click } from '../events'; import { Page } from './page.base'; import * as i0 from "@angular/core"; import * as i1 from "@dbg-riskit/angular-datatable"; export class DataTableDefinition { constructor(debugElement, page) { this.debugElement = debugElement; this.page = page; } get component() { return this.debugElement.componentInstance; } get data() { return this.component.plainData; } get element() { return this.debugElement.query(By.css('.risk-data-table-wrapper > table')); } get header() { return new TableHeader(this.debugElement.query((de) => de.references.mainHeader), this.page); } get sorting() { return new TableSorting(this, this.page); } get body() { return new TableBody(this.debugElement.query((de) => de.references.mainBody), this.page); } get footer() { return new TableFooter(this.debugElement.query((de) => de.references.mainFooter)); } get recordsCount() { return new RecordsCount(this.debugElement.query(By.css('.risk-data-table-page-count'))); } get pager() { return new Pager(this.debugElement.query(By.directive(PagingComponent)), this.page); } } // <editor-fold defaultstate="collapsed" desc="Table header"> export class TableHeader { constructor(element, page) { this.element = element; this.page = page; } get rows() { return this.element.queryAll(By.css('tr')).map((element) => { return new TableHeaderRow(element, this.page); }); } get cells() { return this.element.queryAll(By.css('th')).map((element) => { return new TableHeaderCell(element, this.page); }); } } export class TableHeaderRow { constructor(element, page) { this.element = element; this.page = page; } get cells() { return this.element.queryAll(By.css('th')).map((element) => { return new TableHeaderCell(element, this.page); }); } } export class TableHeaderCell { constructor(element, page) { this.element = element; this.page = page; } get sortingHandle() { const handle = this.element.query(By.directive(MatButton)); if (handle) { return new SortingHandle(this.page, handle); } return null; } get tooltip() { const handle = this.element.query(By.directive(MatTooltip)); if (handle) { return handle.injector.get(MatTooltip).message; } return null; } get title() { const textNode = this.element.childNodes.find((node) => node.nativeNode.nodeType === Node.TEXT_NODE); if (textNode != null) { return textNode .nativeNode.textContent.trim(); } return ''; } get colspan() { return this.element.nativeElement.colspan; } get rowspan() { return this.element.nativeElement.rowspan; } } // <editor-fold defaultstate="collapsed" desc="Sorting"> export class TableSorting { constructor(table, page) { this.table = table; this.page = page; } get handles() { const handles = this.table.debugElement.query((de) => de.references.mainHeader) .queryAll(By.directive(MatButton)); if (!handles) { return []; } return handles.map((handle) => { return new SortingHandle(this.page, handle); }); } get detailRowHandles() { const handles = this.table.debugElement.query(By.css('.risk-data-table-detail')).query(By.css('thead')) .queryAll(By.directive(MatButton)); if (!handles) { return null; } return handles.map((handle) => { return new SortingHandle(this.page, handle); }); } get currentOrdering() { return this.table.component.ordering; } checkSorting(firstNRows = this.table.component.rows.length, criterium) { // WARN: call data once as it calls .map on all table rows const data = this.table.data; let ordering; if (criterium) { ordering = [criterium].concat(this.table.component._defaultOrdering); } else { ordering = this.currentOrdering; } for (let i = 1; i < Math.min(data.length, firstNRows); i++) { ordering.some((criteria) => { //noinspection EqualityComparisonWithCoercionJS const valueA = criteria.get(data[i - 1]); const valueB = criteria.get(data[i]); if (valueA == null && valueB == null) { return false; } expect(valueA).not.toBeNull(); expect(valueA).not.toBeUndefined(); if (valueB != null) { if (criteria.descending) { expect(valueA >= valueB) .toBeTruthy('Expect: ' + valueA + ' >= ' + valueB); } else { expect(valueA <= valueB) .toBeTruthy('Expect: ' + valueA + ' <= ' + valueB); } } return valueA !== valueB; }); } } } export class SortingHandle { constructor(page, handle) { this.page = page; this.handle = handle; } click() { click(this.handle); this.page.detectChanges(); } } // </editor-fold> // </editor-fold> // <editor-fold defaultstate="collapsed" desc="Table body"> export class TableBody { constructor(element, page) { this.element = element; this.page = page; } get rows() { return this.element.queryAll((de) => de.references.masterRow).map((element) => { return new TableBodyRow(element, this.page); }); } get cells() { let cells = []; this.element.queryAll((de) => de.references.masterRow).forEach((row) => { cells = cells.concat(row.queryAll(By.css('td')).map((cell) => { return new TableBodyCell(cell); })); }); return cells; } } export class TableBodyRow { constructor(element, page) { this.element = element; this.page = page; } expandRow() { click(this.element); this.page.detectChanges(); } get expander() { return new RowExpander(this.element.query(By.directive(DataTableRowDetailExpanderComponent)).query(By.directive(MatAnchor))); } get cells() { return this.element.queryAll(By.css('td')).map((element) => { return new TableBodyCell(element); }); } get rowDetail() { const parent = this.element.parent; if (parent != null) { const next = parent.children[parent.children.indexOf(this.element) + 1]; if (next && !next.references.masterRow) { return new TableBodyDetail(next, this.page); } } return null; } get highlighted() { return this.element.nativeElement.classList.contains(HIGHLIGHTER_CLASS); } } export class RowExpander { constructor(element) { this.element = element; } get icon() { return this.element.query(By.directive(MatIcon)).nativeElement.textContent.trim(); } get opened() { return this.icon === 'expand_less'; } get closed() { return this.icon === 'expand_more'; } } export class TableBodyCell { constructor(element) { this.element = element; } get colspan() { return this.element.nativeElement.colspan; } get rowspan() { return this.element.nativeElement.rowspan; } } // <editor-fold defaultstate="collapsed" desc="Row detail"> export class TableBodyDetail { constructor(element, page) { this.element = element; this.page = page; } header() { return new TableHeader(this.element.query(By.css('thead')), this.page); } get body() { return new TableBodyDetailBody(this.element.query(By.css('tbody'))); } get highlighted() { return this.element.nativeElement.classList.contains(HIGHLIGHTER_CLASS); } get colspan() { return this.element.children[0].nativeElement.colspan; } } export class TableBodyDetailBody { constructor(element) { this.element = element; } get rows() { return this.element.queryAll(By.css('tr')).map((element) => { return new TableBodyDetailRow(element); }); } get cells() { let cells = []; this.element.queryAll(By.css('tr')).forEach((row) => { cells = cells.concat(row.queryAll(By.css('td')).map((cell) => { return new TableBodyCell(cell); })); }); return cells; } } export class TableBodyDetailRow { constructor(element) { this.element = element; } get cells() { return this.element.queryAll(By.css('td')).map((element) => { return new TableBodyCell(element); }); } } // </editor-fold> // </editor-fold> // <editor-fold defaultstate="collapsed" desc="Table footer"> export class TableFooter { constructor(element) { this.element = element; } get rows() { return this.element.queryAll(By.css('tr')).map((element) => { return new TableFooterRow(element); }); } get cells() { let cells = []; this.element.queryAll(By.css('tr')).forEach((row) => { cells = cells.concat(row.queryAll(By.css('th')).map((cell) => { return new TableBodyCell(cell); })); }); return cells; } } export class TableFooterRow { constructor(element) { this.element = element; } get cells() { return this.element.queryAll(By.css('th')).map((element) => { return new TableBodyCell(element); }); } } // </editor-fold> export class RecordsCount { constructor(element) { this.element = element; } get message() { return this.element.nativeElement.textContent; } } export class Pager { constructor(element, page) { this.element = element; this.page = page; } get pageButtons() { return this.element.queryAll(By.directive(MatButtonToggle)); } expectLeadingButtonsDisabled() { for (let i = 0; i < 2; i++) { expect(this.pageButtons[i].classes['mat-button-toggle-disabled']) .toBe(true, 'First two are disabled.'); } } expectLeadingButtonsNotDisabled() { for (let i = 0; i < 2; i++) { expect(this.pageButtons[i].classes['mat-button-toggle-disabled']) .not.toBe(true, 'First two are not disabled.'); } } expectTrailingButtonsDisabled() { for (let i = this.pageButtons.length - 1; i > this.pageButtons.length - 3; i--) { expect(this.pageButtons[i].classes['mat-button-toggle-disabled']) .toBe(true, 'Last two are disabled.'); } } expectTrailingButtonsNotDisabled() { for (let i = this.pageButtons.length - 1; i > this.pageButtons.length - 3; i--) { expect(this.pageButtons[i].classes['mat-button-toggle-disabled']) .not.toBe(true, 'Last two are not disabled.'); } } expectButtonNumbers(numbers) { for (let i = 0; i < numbers.length; i++) { expect(this.pageButtons[i + 2].query(By.css('.mat-button-toggle-label-content')) .nativeElement.textContent.trim()) .toEqual(numbers[i] + '', 'Button numbers are correct'); } } expectButtonActive(index) { expect(this.pageButtons[index].classes['mat-button-toggle-checked']) .toBe(true, 'Button is active.'); } click(index) { click(this.pageButtons[index].query(By.css('.mat-button-toggle-label-content')).nativeElement); this.page.detectChanges(); this.page.advanceAndDetectChanges(); } } export function chceckSorting(page, criteria) { page.dataTable.sorting.checkSorting(150); page.dataTable.sorting.handles.forEach((handle, index) => { // Tigger sort based on a handle handle.click(); page.detectChanges(); // Check the sorting page.dataTable.sorting.checkSorting(150, { get: criteria[index] }); // Tigger sort based on a handle handle.click(); page.detectChanges(); // Check the sorting page.dataTable.sorting.checkSorting(150, { get: criteria[index], descending: true }); }); } export class DataTableDefinitionHosted extends Page { constructor(fixture) { super(fixture); } get dataTable() { return new DataTableDefinition(this.debugElement.query(By.directive(DataTableComponent)), this); } } export class TestDataTableHostComponent { constructor() { this.data = []; for (let i = 0; i < 500; i++) { this.data.push({ value1: Math.floor(secureRandom() * 20) + ' - value 1', value2: Math.floor(secureRandom() * 20) + ' - value 2', value3: Math.floor(secureRandom() * 20) + ' - value 3' }); } this.footer = this.data[0]; } get defaultOrdering() { return [ { get: (record) => { return record.value3; }, descending: true }, (record) => { return record.value2; } ]; } get valueGetter() { return (record) => { return record.value1; }; } } TestDataTableHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestDataTableHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); TestDataTableHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.6", type: TestDataTableHostComponent, selector: "ng-component", ngImport: i0, template: ` <risk-data-table [data]="data" [footer]="footer" [pageSize]="20" [defaultOrdering]="defaultOrdering" [striped]="true"> <risk-data-table-column title="Test Column 1" [sortingKey]="valueGetter"> <ng-template let-record="row" risk-data-table-cell> {{record.value1}} </ng-template> </risk-data-table-column> <risk-data-table-column> <ng-template risk-data-table-cell let-record="row" let-expanded="expanded"> <risk-data-table-detail-expander [expanded]="expanded"></risk-data-table-detail-expander> </ng-template> <ng-template risk-data-table-footer-cell let-footer="footer"> {{footer.value1}} </ng-template> </risk-data-table-column> <!-- Sub detail --> <risk-data-table-detail-row> <risk-data-table-column-group> <risk-data-table-column title="Test Detail Column 1" [sortingKey]="valueGetter"> <ng-template risk-data-table-cell let-record="row"> {{record.value1}} </ng-template> </risk-data-table-column> </risk-data-table-column-group> <risk-data-table-column-group> <risk-data-table-column title="Test Detail Column 2"> <ng-template risk-data-table-cell let-record="row"> {{record.value2}} </ng-template> </risk-data-table-column> <risk-data-table-column title="Test Detail Column 3"> <ng-template risk-data-table-cell let-record="row"> {{record.value3}} </ng-template> </risk-data-table-column> </risk-data-table-column-group> <risk-data-table-column-group></risk-data-table-column-group> </risk-data-table-detail-row> </risk-data-table>`, isInline: true, components: [{ type: i1.DataTableComponent, selector: "risk-data-table", inputs: ["footer", "pageSize", "striped", "showFooter", "allowEmpty", "trackByRowKey", "highlighting", "stickyHeader", "stickyHeaderOffsetTopPx", "data", "defaultOrdering"], exportAs: ["dataTable"] }, { type: i1.DataTableRowDetailExpanderComponent, selector: "risk-data-table-detail-expander", inputs: ["expanded"] }], directives: [{ type: i1.ɵDataTableColumnDirective, selector: "risk-data-table-column", inputs: ["title", "sortingKey", "tooltip", "contentAlign", "headerAlign", "footerAlign", "class"] }, { type: i1.ɵDataTableColumnCellDirective, selector: "[risk-data-table-cell]" }, { type: i1.ɵDataTableColumnFooterDirective, selector: "[risk-data-table-footer-cell]" }, { type: i1.ɵDataTableRowDetailDirective, selector: "risk-data-table-detail-row" }, { type: i1.ɵDataTableColumnGroupDirective, selector: "risk-data-table-column-group" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestDataTableHostComponent, decorators: [{ type: Component, args: [{ template: ` <risk-data-table [data]="data" [footer]="footer" [pageSize]="20" [defaultOrdering]="defaultOrdering" [striped]="true"> <risk-data-table-column title="Test Column 1" [sortingKey]="valueGetter"> <ng-template let-record="row" risk-data-table-cell> {{record.value1}} </ng-template> </risk-data-table-column> <risk-data-table-column> <ng-template risk-data-table-cell let-record="row" let-expanded="expanded"> <risk-data-table-detail-expander [expanded]="expanded"></risk-data-table-detail-expander> </ng-template> <ng-template risk-data-table-footer-cell let-footer="footer"> {{footer.value1}} </ng-template> </risk-data-table-column> <!-- Sub detail --> <risk-data-table-detail-row> <risk-data-table-column-group> <risk-data-table-column title="Test Detail Column 1" [sortingKey]="valueGetter"> <ng-template risk-data-table-cell let-record="row"> {{record.value1}} </ng-template> </risk-data-table-column> </risk-data-table-column-group> <risk-data-table-column-group> <risk-data-table-column title="Test Detail Column 2"> <ng-template risk-data-table-cell let-record="row"> {{record.value2}} </ng-template> </risk-data-table-column> <risk-data-table-column title="Test Detail Column 3"> <ng-template risk-data-table-cell let-record="row"> {{record.value3}} </ng-template> </risk-data-table-column> </risk-data-table-column-group> <risk-data-table-column-group></risk-data-table-column-group> </risk-data-table-detail-row> </risk-data-table>` }] }], ctorParameters: function () { return []; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS50YWJsZS5kZWZpbml0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGtnL2RiZy1yaXNraXQvYW5ndWxhci10ZXN0aW5nL3NyYy9saWIvZGVmaW5pdGlvbnMvZGF0YS50YWJsZS5kZWZpbml0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxTQUFTLEVBQTBCLE1BQU0sZUFBZSxDQUFDO0FBRWpFLE9BQU8sRUFBQyxTQUFTLEVBQUUsU0FBUyxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDOUQsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLGlDQUFpQyxDQUFDO0FBQ2hFLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUMvQyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFDLEVBQUUsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQzdDLE9BQU8sRUFBYyxZQUFZLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUM3RCxPQUFPLEVBQ0gsa0JBQWtCLEVBQ2xCLG1DQUFtQyxFQUNuQyxpQkFBaUIsRUFFakIsZUFBZSxFQUNsQixNQUFNLCtCQUErQixDQUFDO0FBQ3ZDLE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDaEMsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGFBQWEsQ0FBQzs7O0FBRWpDLE1BQU0sT0FBTyxtQkFBbUI7SUFFNUIsWUFBMEIsWUFBMEIsRUFDekIsSUFBd0U7UUFEekUsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDekIsU0FBSSxHQUFKLElBQUksQ0FBb0U7SUFDbkcsQ0FBQztJQUVELElBQVcsU0FBUztRQUNoQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUM7SUFDL0MsQ0FBQztJQUVELElBQVcsSUFBSTtRQUNYLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUM7SUFDcEMsQ0FBQztJQUVELElBQVcsT0FBTztRQUNkLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUVELElBQVcsTUFBTTtRQUNiLE9BQU8sSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pHLENBQUM7SUFFRCxJQUFXLE9BQU87UUFDZCxPQUFPLElBQUksWUFBWSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVELElBQVcsSUFBSTtRQUNYLE9BQU8sSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdGLENBQUM7SUFFRCxJQUFXLE1BQU07UUFDYixPQUFPLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDdEYsQ0FBQztJQUVELElBQVcsWUFBWTtRQUNuQixPQUFPLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsNkJBQTZCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUYsQ0FBQztJQUVELElBQVcsS0FBSztRQUNaLE9BQU8sSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4RixDQUFDO0NBQ0o7QUFFRCw2REFBNkQ7QUFFN0QsTUFBTSxPQUFPLFdBQVc7SUFFcEIsWUFBMEIsT0FBcUIsRUFBVSxJQUFtQztRQUFsRSxZQUFPLEdBQVAsT0FBTyxDQUFjO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBK0I7SUFDNUYsQ0FBQztJQUVELElBQVcsSUFBSTtRQUNYLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQXFCLEVBQUUsRUFBRTtZQUNyRSxPQUFPLElBQUksY0FBYyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsSUFBVyxLQUFLO1FBQ1osT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBcUIsRUFBRSxFQUFFO1lBQ3JFLE9BQU8sSUFBSSxlQUFlLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FFSjtBQUVELE1BQU0sT0FBTyxjQUFjO0lBQ3ZCLFlBQTBCLE9BQXFCLEVBQVUsSUFBbUM7UUFBbEUsWUFBTyxHQUFQLE9BQU8sQ0FBYztRQUFVLFNBQUksR0FBSixJQUFJLENBQStCO0lBQzVGLENBQUM7SUFFRCxJQUFXLEtBQUs7UUFDWixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFxQixFQUFFLEVBQUU7WUFDckUsT0FBTyxJQUFJLGVBQWUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25ELENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztDQUNKO0FBRUQsTUFBTSxPQUFPLGVBQWU7SUFFeEIsWUFBMEIsT0FBcUIsRUFBVSxJQUFtQztRQUFsRSxZQUFPLEdBQVAsT0FBTyxDQUFjO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBK0I7SUFDNUYsQ0FBQztJQUVELElBQVcsYUFBYTtRQUNwQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxNQUFNLEVBQUU7WUFDUixPQUFPLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDL0M7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsSUFBVyxPQUFPO1FBQ2QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQzVELElBQUksTUFBTSxFQUFFO1lBQ1IsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxPQUFPLENBQUM7U0FDbEQ7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsSUFBVyxLQUFLO1FBQ1osTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBZSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDaEgsSUFBSSxRQUFRLElBQUksSUFBSSxFQUFFO1lBQ2xCLE9BQU8sUUFBUTtpQkFDVixVQUFVLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3RDO1FBQ0QsT0FBTyxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsSUFBVyxPQUFPO1FBQ2QsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUM7SUFDOUMsQ0FBQztJQUVELElBQVcsT0FBTztRQUNkLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDO0lBQzlDLENBQUM7Q0FFSjtBQUVELHdEQUF3RDtBQUV4RCxNQUFNLE9BQU8sWUFBWTtJQUVyQixZQUEyQixLQUEwQixFQUFVLElBQW1DO1FBQXZFLFVBQUssR0FBTCxLQUFLLENBQXFCO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBK0I7SUFDbEcsQ0FBQztJQUVELElBQVcsT0FBTztRQUNkLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7YUFDMUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1YsT0FBTyxFQUFFLENBQUM7U0FDYjtRQUNELE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQW9CLEVBQUUsRUFBRTtZQUN4QyxPQUFPLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDaEQsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsSUFBVyxnQkFBZ0I7UUFDdkIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQ2xHLFFBQVEsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNWLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFDRCxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFvQixFQUFFLEVBQUU7WUFDeEMsT0FBTyxJQUFJLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2hELENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELElBQVcsZUFBZTtRQUN0QixPQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBaUIsQ0FBQyxRQUFRLENBQUM7SUFDbEQsQ0FBQztJQUVNLFlBQVksQ0FBQyxhQUFxQixJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUNyRCxTQUFpQztRQUNqRCwwREFBMEQ7UUFDMUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7UUFFN0IsSUFBSSxRQUFzQyxDQUFDO1FBQzNDLElBQUksU0FBUyxFQUFFO1lBQ1gsUUFBUSxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1NBQ2pGO2FBQU07WUFDSCxRQUFRLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQztTQUNuQztRQUNELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDeEQsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQStCLEVBQUUsRUFBRTtnQkFDOUMsK0NBQStDO2dCQUMvQyxNQUFNLE1BQU0sR0FBUSxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDOUMsTUFBTSxNQUFNLEdBQVEsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDMUMsSUFBSSxNQUFNLElBQUksSUFBSSxJQUFJLE1BQU0sSUFBSSxJQUFJLEVBQUU7b0JBQ2xDLE9BQU8sS0FBSyxDQUFDO2lCQUNoQjtnQkFDRCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUM5QixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUNuQyxJQUFJLE1BQU0sSUFBSSxJQUFJLEVBQUU7b0JBQ2hCLElBQUksUUFBUSxDQUFDLFVBQVUsRUFBRTt3QkFDckIsTUFBTSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUM7NkJBQ25CLFVBQVUsQ0FBQyxVQUFVLEdBQUcsTUFBTSxHQUFHLE1BQU07OEJBQzFCLE1BQU0sQ0FBQyxDQUFDO3FCQUM3Qjt5QkFBTTt3QkFDSCxNQUFNLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQzs2QkFDbkIsVUFBVSxDQUFDLFVBQVUsR0FBRyxNQUFNLEdBQUcsTUFBTTs4QkFDMUIsTUFBTSxDQUFDLENBQUM7cUJBQzdCO2lCQUNKO2dCQUNELE9BQU8sTUFBTSxLQUFLLE1BQU0sQ0FBQztZQUM3QixDQUFDLENBQUMsQ0FBQztTQUNOO0lBQ0wsQ0FBQztDQUNKO0FBRUQsTUFBTSxPQUFPLGFBQWE7SUFFdEIsWUFBMkIsSUFBbUMsRUFBVSxNQUFvQjtRQUFqRSxTQUFJLEdBQUosSUFBSSxDQUErQjtRQUFVLFdBQU0sR0FBTixNQUFNLENBQWM7SUFDNUYsQ0FBQztJQUVNLEtBQUs7UUFDUixLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDOUIsQ0FBQztDQUNKO0FBRUQsaUJBQWlCO0FBRWpCLGlCQUFpQjtBQUVqQiwyREFBMkQ7QUFFM0QsTUFBTSxPQUFPLFNBQVM7SUFFbEIsWUFBMEIsT0FBcUIsRUFBVSxJQUFtQztRQUFsRSxZQUFPLEdBQVAsT0FBTyxDQUFjO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBK0I7SUFDNUYsQ0FBQztJQUVELElBQVcsSUFBSTtRQUNYLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBcUIsRUFBRSxFQUFFO1lBQ3hGLE9BQU8sSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxJQUFXLEtBQUs7UUFDWixJQUFJLEtBQUssR0FBb0IsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQWlCLEVBQUUsRUFBRTtZQUNqRixLQUFLLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFrQixFQUFFLEVBQUU7Z0JBQ3ZFLE9BQU8sSUFBSSxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNSLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztDQUNKO0FBRUQsTUFBTSxPQUFPLFlBQVk7SUFFckIsWUFBMEIsT0FBcUIsRUFBVSxJQUFtQztRQUFsRSxZQUFPLEdBQVAsT0FBTyxDQUFjO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBK0I7SUFDNUYsQ0FBQztJQUVNLFNBQVM7UUFDWixLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELElBQVcsUUFBUTtRQUNmLE9BQU8sSUFBSSxXQUFXLENBQ2xCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5RyxDQUFDO0lBRUQsSUFBVyxLQUFLO1FBQ1osT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBcUIsRUFBRSxFQUFFO1lBQ3JFLE9BQU8sSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdEMsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsSUFBVyxTQUFTO1FBQ2hCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQ25DLElBQUksTUFBTSxJQUFJLElBQUksRUFBRTtZQUNoQixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUN4RSxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFO2dCQUNwQyxPQUFPLElBQUksZUFBZSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDL0M7U0FDSjtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxJQUFXLFdBQVc7UUFDbEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDNUUsQ0FBQztDQUNKO0FBRUQsTUFBTSxPQUFPLFdBQVc7SUFDcEIsWUFBMEIsT0FBcUI7UUFBckIsWUFBTyxHQUFQLE9BQU8sQ0FBYztJQUMvQyxDQUFDO0lBRUQsSUFBVyxJQUFJO1FBQ1gsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN0RixDQUFDO0lBRUQsSUFBVyxNQUFNO1FBQ2IsT0FBTyxJQUFJLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQztJQUN2QyxDQUFDO0lBRUQsSUFBVyxNQUFNO1FBQ2IsT0FBTyxJQUFJLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQztJQUN2QyxDQUFDO0NBQ0o7QUFFRCxNQUFNLE9BQU8sYUFBYTtJQUV0QixZQUEwQixPQUFxQjtRQUFyQixZQUFPLEdBQVAsT0FBTyxDQUFjO0lBQy9DLENBQUM7SUFFRCxJQUFXLE9BQU87UUFDZCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQztJQUM5QyxDQUFDO0lBRUQsSUFBVyxPQUFPO1FBQ2QsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUM7SUFDOUMsQ0FBQztDQUNKO0FBRUQsMkRBQTJEO0FBRTNELE1BQU0sT0FBTyxlQUFlO0lBRXhCLFlBQTBCLE9BQXFCLEVBQVUsSUFBbUM7UUFBbEUsWUFBTyxHQUFQLE9BQU8sQ0FBYztRQUFVLFNBQUksR0FBSixJQUFJLENBQStCO0lBQzVGLENBQUM7SUFFTSxNQUFNO1FBQ1QsT0FBTyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNFLENBQUM7SUFFRCxJQUFXLElBQUk7UUFDWCxPQUFPLElBQUksbUJBQW1CLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVELElBQVcsV0FBVztRQUNsQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQsSUFBVyxPQUFPO1FBQ2QsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDO0lBQzFELENBQUM7Q0FDSjtBQUVELE1BQU0sT0FBTyxtQkFBbUI7SUFFNUIsWUFBMEIsT0FBcUI7UUFBckIsWUFBTyxHQUFQLE9BQU8sQ0FBYztJQUMvQyxDQUFDO0lBRUQsSUFBVyxJQUFJO1FBQ1gsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBcUIsRUFBRSxFQUFFO1lBQ3JFLE9BQU8sSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxJQUFXLEtBQUs7UUFDWixJQUFJLEtBQUssR0FBb0IsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFpQixFQUFFLEVBQUU7WUFDOUQsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBa0IsRUFBRSxFQUFFO2dCQUN2RSxPQUFPLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ25DLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDUixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7Q0FDSjtBQUVELE1BQU0sT0FBTyxrQkFBa0I7SUFFM0IsWUFBMEIsT0FBcUI7UUFBckIsWUFBTyxHQUFQLE9BQU8sQ0FBYztJQUMvQyxDQUFDO0lBRUQsSUFBVyxLQUFLO1FBQ1osT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBcUIsRUFBRSxFQUFFO1lBQ3JFLE9BQU8sSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdEMsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0NBQ0o7QUFFRCxpQkFBaUI7QUFFakIsaUJBQWlCO0FBRWpCLDZEQUE2RDtBQUU3RCxNQUFNLE9BQU8sV0FBVztJQUVwQixZQUEwQixPQUFxQjtRQUFyQixZQUFPLEdBQVAsT0FBTyxDQUFjO0lBQy9DLENBQUM7SUFFRCxJQUFXLElBQUk7UUFDWCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFxQixFQUFFLEVBQUU7WUFDckUsT0FBTyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxJQUFXLEtBQUs7UUFDWixJQUFJLEtBQUssR0FBb0IsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFpQixFQUFFLEVBQUU7WUFDOUQsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBa0IsRUFBRSxFQUFFO2dCQUN2RSxPQUFPLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ25DLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDUixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7Q0FDSjtBQUVELE1BQU0sT0FBTyxjQUFjO0lBRXZCLFlBQTBCLE9BQXFCO1FBQXJCLFlBQU8sR0FBUCxPQUFPLENBQWM7SUFDL0MsQ0FBQztJQUVELElBQVcsS0FBSztRQUNaLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQXFCLEVBQUUsRUFBRTtZQUNyRSxPQUFPLElBQUksYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztDQUNKO0FBRUQsaUJBQWlCO0FBRWpCLE1BQU0sT0FBTyxZQUFZO0lBRXJCLFlBQTBCLE9BQXFCO1FBQXJCLFlBQU8sR0FBUCxPQUFPLENBQWM7SUFDL0MsQ0FBQztJQUVELElBQVcsT0FBTztRQUNkLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO0lBQ2xELENBQUM7Q0FDSjtBQUVELE1BQU0sT0FBTyxLQUFLO0lBRWQsWUFBMEIsT0FBcUIsRUFDcEIsSUFBd0U7UUFEekUsWUFBTyxHQUFQLE9BQU8sQ0FBYztRQUNwQixTQUFJLEdBQUosSUFBSSxDQUFvRTtJQUNuRyxDQUFDO0lBRUQsSUFBVyxXQUFXO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFTSw0QkFBNEI7UUFDL0IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN4QixNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0FBQztpQkFDNUQsSUFBSSxDQUFDLElBQUksRUFBRSx5QkFBeUIsQ0FBQyxDQUFDO1NBQzlDO0lBQ0wsQ0FBQztJQUVNLCtCQUErQjtRQUNsQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3hCLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO2lCQUM1RCxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSw2QkFBNkIsQ0FBQyxDQUFDO1NBQ3REO0lBQ0wsQ0FBQztJQUVNLDZCQUE2QjtRQUNoQyxLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzVFLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO2lCQUM1RCxJQUFJLENBQUMsSUFBSSxFQUFFLHdCQUF3QixDQUFDLENBQUM7U0FDN0M7SUFDTCxDQUFDO0lBRU0sZ0NBQWdDO1FBQ25DLEtBQUssSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDNUUsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLDRCQUE0QixDQUFDLENBQUM7aUJBQzVELEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLDRCQUE0QixDQUFDLENBQUM7U0FDckQ7SUFDTCxDQUFDO0lBRU0sbUJBQW1CLENBQUMsT0FBaUI7UUFDeEMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDckMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7aUJBQzNFLGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7aUJBQ2pDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLDRCQUE0QixDQUFDLENBQUM7U0FDL0Q7SUFDTCxDQUFDO0lBRU0sa0JBQWtCLENBQUMsS0FBYTtRQUNuQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FBQzthQUMvRCxJQUFJLENBQUMsSUFBSSxFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVNLEtBQUssQ0FBQyxLQUFhO1FBQ3RCLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLGtDQUFrQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUMvRixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0NBQ0o7QUFFRCxNQUFNLFVBQVUsYUFBYSxDQUFDLElBQW1FLEVBQ25FLFFBQWlDO0lBQzNELElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUV6QyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBcUIsRUFBRSxLQUFhLEVBQUUsRUFBRTtRQUM1RSxnQ0FBZ0M7UUFDaEMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBRXJCLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFO1lBQ3JDLEdBQUcsRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDO1NBQ3ZCLENBQUMsQ0FBQztRQUVILGdDQUFnQztRQUNoQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFFckIsb0JBQW9CO1FBQ3BCLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUU7WUFDckMsR0FBRyxFQUFTLFFBQVEsQ0FBQyxLQUFLLENBQUM7WUFDM0IsVUFBVSxFQUFFLElBQUk7U0FDbkIsQ0FBQyxDQUFDO0lBQ1AsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDO0FBRUQsTUFBTSxPQUFPLHlCQUEwQixTQUFRLElBQWdDO0lBRTNFLFlBQW1CLE9BQXFEO1FBQ3BFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBVyxTQUFTO1FBQ2hCLE9BQU8sSUFBSSxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwRyxDQUFDO0NBQ0o7QUFpREQsTUFBTSxPQUFPLDBCQUEwQjtJQU1uQztRQUNJLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2YsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUMxQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDWCxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxZQUFZO2dCQUN0RCxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxZQUFZO2dCQUN0RCxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxZQUFZO2FBQ3pELENBQUMsQ0FBQztTQUNOO1FBQ0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRCxJQUFXLGVBQWU7UUFDdEIsT0FBTztZQUNIO2dCQUNJLEdBQUcsRUFBUyxDQUFDLE1BQVcsRUFBRSxFQUFFO29CQUN4QixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQ3pCLENBQUM7Z0JBQ0QsVUFBVSxFQUFFLElBQUk7YUFDbkI7WUFDRCxDQUFDLE1BQVcsRUFBRSxFQUFFO2dCQUNaLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQztZQUN6QixDQUFDO1NBQ0osQ0FBQztJQUNOLENBQUM7SUFFRCxJQUFXLFdBQVc7UUFDbEIsT0FBTyxDQUFDLE1BQVcsRUFBRSxFQUFFO1lBQ25CLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUN6QixDQUFDLENBQUM7SUFDTixDQUFDOzt1SEFwQ1EsMEJBQTBCOzJHQUExQiwwQkFBMEIsb0RBOUN6Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7MkJBNENhOzJGQUVkLDBCQUEwQjtrQkEvQ3RDLFNBQVM7bUJBQUM7b0JBQ1AsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsyQkE0Q2E7aUJBQzFCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtDb21wb25lbnQsIERlYnVnRWxlbWVudCwgRGVidWdOb2RlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Q29tcG9uZW50Rml4dHVyZX0gZnJvbSAnQGFuZ3VsYXIvY29yZS90ZXN0aW5nJztcbmltcG9ydCB7TWF0QW5jaG9yLCBNYXRCdXR0b259IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XG5pbXBvcnQge01hdEJ1dHRvblRvZ2dsZX0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uLXRvZ2dsZSc7XG5pbXBvcnQge01hdEljb259IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nO1xuaW1wb3J0IHtNYXRUb29sdGlwfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90b29sdGlwJztcbmltcG9ydCB7Qnl9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xuaW1wb3J0IHtWYWx1ZUdldHRlciwgc2VjdXJlUmFuZG9tfSBmcm9tICdAZGJnLXJpc2tpdC9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBEYXRhVGFibGVDb21wb25lbnQsXG4gICAgRGF0YVRhYmxlUm93RGV0YWlsRXhwYW5kZXJDb21wb25lbnQsXG4gICAgSElHSExJR0hURVJfQ0xBU1MsXG4gICAgT3JkZXJpbmdDcml0ZXJpYSxcbiAgICBQYWdpbmdDb21wb25lbnRcbn0gZnJvbSAnQGRiZy1yaXNraXQvYW5ndWxhci1kYXRhdGFibGUnO1xuaW1wb3J0IHtjbGlja30gZnJvbSAnLi4vZXZlbnRzJztcbmltcG9ydCB7UGFnZX0gZnJvbSAnLi9wYWdlLmJhc2UnO1xuXG5leHBvcnQgY2xhc3MgRGF0YVRhYmxlRGVmaW5pdGlvbiB7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIGRlYnVnRWxlbWVudDogRGVidWdFbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICBwcml2YXRlIHBhZ2U6IHsgZGV0ZWN0Q2hhbmdlczogKCkgPT4gdm9pZCwgYWR2YW5jZUFuZERldGVjdENoYW5nZXM6ICgpID0+IHZvaWQgfSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgY29tcG9uZW50KCk6IERhdGFUYWJsZUNvbXBvbmVudDx1bmtub3duLCB1bmtub3duPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmRlYnVnRWxlbWVudC5jb21wb25lbnRJbnN0YW5jZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGRhdGEoKTogYW55W10ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21wb25lbnQucGxhaW5EYXRhO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgZWxlbWVudCgpOiBEZWJ1Z0VsZW1lbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5kZWJ1Z0VsZW1lbnQucXVlcnkoQnkuY3NzKCcucmlzay1kYXRhLXRhYmxlLXdyYXBwZXIgPiB0YWJsZScpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGhlYWRlcigpOiBUYWJsZUhlYWRlciB7XG4gICAgICAgIHJldHVybiBuZXcgVGFibGVIZWFkZXIodGhpcy5kZWJ1Z0VsZW1lbnQucXVlcnkoKGRlKSA9PiBkZS5yZWZlcmVuY2VzLm1haW5IZWFkZXIpLCB0aGlzLnBhZ2UpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgc29ydGluZygpOiBUYWJsZVNvcnRpbmcge1xuICAgICAgICByZXR1cm4gbmV3IFRhYmxlU29ydGluZyh0aGlzLCB0aGlzLnBhZ2UpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgYm9keSgpOiBUYWJsZUJvZHkge1xuICAgICAgICByZXR1cm4gbmV3IFRhYmxlQm9keSh0aGlzLmRlYnVnRWxlbWVudC5xdWVyeSgoZGUpID0+IGRlLnJlZmVyZW5jZXMubWFpbkJvZHkpLCB0aGlzLnBhZ2UpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgZm9vdGVyKCk6IFRhYmxlRm9vdGVyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUYWJsZUZvb3Rlcih0aGlzLmRlYnVnRWxlbWVudC5xdWVyeSgoZGUpID0+IGRlLnJlZmVyZW5jZXMubWFpbkZvb3RlcikpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgcmVjb3Jkc0NvdW50KCk6IFJlY29yZHNDb3VudCB7XG4gICAgICAgIHJldHVybiBuZXcgUmVjb3Jkc0NvdW50KHRoaXMuZGVidWdFbGVtZW50LnF1ZXJ5KEJ5LmNzcygnLnJpc2stZGF0YS10YWJsZS1wYWdlLWNvdW50JykpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHBhZ2VyKCk6IFBhZ2VyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQYWdlcih0aGlzLmRlYnVnRWxlbWVudC5xdWVyeShCeS5kaXJlY3RpdmUoUGFnaW5nQ29tcG9uZW50KSksIHRoaXMucGFnZSk7XG4gICAgfVxufVxuXG4vLyA8ZWRpdG9yLWZvbGQgZGVmYXVsdHN0YXRlPVwiY29sbGFwc2VkXCIgZGVzYz1cIlRhYmxlIGhlYWRlclwiPlxuXG5leHBvcnQgY2xhc3MgVGFibGVIZWFkZXIge1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyBlbGVtZW50OiBEZWJ1Z0VsZW1lbnQsIHByaXZhdGUgcGFnZTogeyBkZXRlY3RDaGFuZ2VzOiAoKSA9PiB2b2lkIH0pIHtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHJvd3MoKTogVGFibGVIZWFkZXJSb3dbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnQucXVlcnlBbGwoQnkuY3NzKCd0cicpKS5tYXAoKGVsZW1lbnQ6IERlYnVnRWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBUYWJsZUhlYWRlclJvdyhlbGVtZW50LCB0aGlzLnBhZ2UpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGNlbGxzKCk6IFRhYmxlSGVhZGVyQ2VsbFtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5xdWVyeUFsbChCeS5jc3MoJ3RoJykpLm1hcCgoZWxlbWVudDogRGVidWdFbGVtZW50KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFRhYmxlSGVhZGVyQ2VsbChlbGVtZW50LCB0aGlzLnBhZ2UpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbn1cblxuZXhwb3J0IGNsYXNzIFRhYmxlSGVhZGVyUm93IHtcbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIGVsZW1lbnQ6IERlYnVnRWxlbWVudCwgcHJpdmF0ZSBwYWdlOiB7IGRldGVjdENoYW5nZXM6ICgpID0+IHZvaWQgfSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgY2VsbHMoKTogVGFibGVIZWFkZXJDZWxsW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50LnF1ZXJ5QWxsKEJ5LmNzcygndGgnKSkubWFwKChlbGVtZW50OiBEZWJ1Z0VsZW1lbnQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgVGFibGVIZWFkZXJDZWxsKGVsZW1lbnQsIHRoaXMucGFnZSk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRhYmxlSGVhZGVyQ2VsbCB7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIGVsZW1lbnQ6IERlYnVnRWxlbWVudCwgcHJpdmF0ZSBwYWdlOiB7IGRldGVjdENoYW5nZXM6ICgpID0+IHZvaWQgfSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgc29ydGluZ0hhbmRsZSgpOiBTb3J0aW5nSGFuZGxlIHwgbnVsbCB7XG4gICAgICAgIGNvbnN0IGhhbmRsZSA9IHRoaXMuZWxlbWVudC5xdWVyeShCeS5kaXJlY3RpdmUoTWF0QnV0dG9uKSk7XG4gICAgICAgIGlmIChoYW5kbGUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU29ydGluZ0hhbmRsZSh0aGlzLnBhZ2UsIGhhbmRsZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCB0b29sdGlwKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICBjb25zdCBoYW5kbGUgPSB0aGlzLmVsZW1lbnQucXVlcnkoQnkuZGlyZWN0aXZlKE1hdFRvb2x0aXApKTtcbiAgICAgICAgaWYgKGhhbmRsZSkge1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZS5pbmplY3Rvci5nZXQoTWF0VG9vbHRpcCkubWVzc2FnZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHRpdGxlKCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHRleHROb2RlID0gdGhpcy5lbGVtZW50LmNoaWxkTm9kZXMuZmluZCgobm9kZTogRGVidWdOb2RlKSA9PiBub2RlLm5hdGl2ZU5vZGUubm9kZVR5cGUgPT09IE5vZGUuVEVYVF9OT0RFKTtcbiAgICAgICAgaWYgKHRleHROb2RlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0ZXh0Tm9kZVxuICAgICAgICAgICAgICAgIC5uYXRpdmVOb2RlLnRleHRDb250ZW50LnRyaW0oKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBjb2xzcGFuKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5jb2xzcGFuO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgcm93c3BhbigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQucm93c3BhbjtcbiAgICB9XG5cbn1cblxuLy8gPGVkaXRvci1mb2xkIGRlZmF1bHRzdGF0ZT1cImNvbGxhcHNlZFwiIGRlc2M9XCJTb3J0aW5nXCI+XG5cbmV4cG9ydCBjbGFzcyBUYWJsZVNvcnRpbmcge1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgdGFibGU6IERhdGFUYWJsZURlZmluaXRpb24sIHByaXZhdGUgcGFnZTogeyBkZXRlY3RDaGFuZ2VzOiAoKSA9PiB2b2lkIH0pIHtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGhhbmRsZXMoKTogU29ydGluZ0hhbmRsZVtdIHtcbiAgICAgICAgY29uc3QgaGFuZGxlcyA9IHRoaXMudGFibGUuZGVidWdFbGVtZW50LnF1ZXJ5KChkZSkgPT4gZGUucmVmZXJlbmNlcy5tYWluSGVhZGVyKVxuICAgICAgICAgICAgLnF1ZXJ5QWxsKEJ5LmRpcmVjdGl2ZShNYXRCdXR0b24pKTtcbiAgICAgICAgaWYgKCFoYW5kbGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGhhbmRsZXMubWFwKChoYW5kbGU6IERlYnVnRWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTb3J0aW5nSGFuZGxlKHRoaXMucGFnZSwgaGFuZGxlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBkZXRhaWxSb3dIYW5kbGVzKCk6IFNvcnRpbmdIYW5kbGVbXSB8IG51bGwge1xuICAgICAgICBjb25zdCBoYW5kbGVzID0gdGhpcy50YWJsZS5kZWJ1Z0VsZW1lbnQucXVlcnkoQnkuY3NzKCcucmlzay1kYXRhLXRhYmxlLWRldGFpbCcpKS5xdWVyeShCeS5jc3MoJ3RoZWFkJykpXG4gICAgICAgICAgICAucXVlcnlBbGwoQnkuZGlyZWN0aXZlKE1hdEJ1dHRvbikpO1xuICAgICAgICBpZiAoIWhhbmRsZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoYW5kbGVzLm1hcCgoaGFuZGxlOiBEZWJ1Z0VsZW1lbnQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU29ydGluZ0hhbmRsZSh0aGlzLnBhZ2UsIGhhbmRsZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgY3VycmVudE9yZGVyaW5nKCk6IEFycmF5PE9yZGVyaW5nQ3JpdGVyaWE8YW55Pj4ge1xuICAgICAgICByZXR1cm4gKHRoaXMudGFibGUuY29tcG9uZW50IGFzIGFueSkub3JkZXJpbmc7XG4gICAgfVxuXG4gICAgcHVibGljIGNoZWNrU29ydGluZyhmaXJzdE5Sb3dzOiBudW1iZXIgPSB0aGlzLnRhYmxlLmNvbXBvbmVudC5yb3dzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNyaXRlcml1bT86IE9yZGVyaW5nQ3JpdGVyaWE8YW55Pik6IHZvaWQge1xuICAgICAgICAvLyBXQVJOOiBjYWxsIGRhdGEgb25jZSBhcyBpdCBjYWxscyAubWFwIG9uIGFsbCB0YWJsZSByb3dzXG4gICAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLnRhYmxlLmRhdGE7XG5cbiAgICAgICAgbGV0IG9yZGVyaW5nOiBBcnJheTxPcmRlcmluZ0NyaXRlcmlhPGFueT4+O1xuICAgICAgICBpZiAoY3JpdGVyaXVtKSB7XG4gICAgICAgICAgICBvcmRlcmluZyA9IFtjcml0ZXJpdW1dLmNvbmNhdCgodGhpcy50YWJsZS5jb21wb25lbnQgYXMgYW55KS5fZGVmYXVsdE9yZGVyaW5nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9yZGVyaW5nID0gdGhpcy5jdXJyZW50T3JkZXJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBNYXRoLm1pbihkYXRhLmxlbmd0aCwgZmlyc3ROUm93cyk7IGkrKykge1xuICAgICAgICAgICAgb3JkZXJpbmcuc29tZSgoY3JpdGVyaWE6IE9yZGVyaW5nQ3JpdGVyaWE8YW55PikgPT4ge1xuICAgICAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEVxdWFsaXR5Q29tcGFyaXNvbldpdGhDb2VyY2lvbkpTXG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWVBOiBhbnkgPSBjcml0ZXJpYS5nZXQoZGF0YVtpIC0gMV0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlQjogYW55ID0gY3JpdGVyaWEuZ2V0KGRhdGFbaV0pO1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZUEgPT0gbnVsbCAmJiB2YWx1ZUIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGV4cGVjdCh2YWx1ZUEpLm5vdC50b0JlTnVsbCgpO1xuICAgICAgICAgICAgICAgIGV4cGVjdCh2YWx1ZUEpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlQiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjcml0ZXJpYS5kZXNjZW5kaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3QodmFsdWVBID49IHZhbHVlQilcbiAgICAgICAgICAgICAgICAgICAgIC