UNPKG

integrity-ngx-easy-table

Version:

Angular easy table

544 lines 151 kB
import { moveItemInArray } from '@angular/cdk/drag-drop';
import { ChangeDetectionStrategy, Component, ContentChild, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild, } from '@angular/core';
import { API, Event } from '../..';
import { DefaultConfigService } from '../../services/config-service';
import { GroupRowsService } from '../../services/group-rows.service';
import { StyleService } from '../../services/style.service';
import { Subject } from 'rxjs';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { filter, takeUntil, throttleTime } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/scrolling";
import * as i2 from "../../services/style.service";
import * as i3 from "@angular/common";
import * as i4 from "@angular/cdk/drag-drop";
import * as i5 from "../pagination/pagination.component";
import * as i6 from "../thead/thead.component";
import * as i7 from "ngx-pagination";
import * as i8 from "../../pipes/search-pipe";
import * as i9 from "../../pipes/render-pipe";
import * as i10 from "../../pipes/global-search-pipe";
import * as i11 from "../../pipes/sort.pipe";
export class BaseComponent {
    onContextMenuClick(targetElement) {
        if (this.contextMenu && !this.contextMenu.nativeElement.contains(targetElement)) {
            this.rowContextMenuPosition = {
                top: null,
                left: null,
                value: null,
            };
        }
    }
    constructor(cdr, scrollDispatcher, styleService) {
        this.cdr = cdr;
        this.scrollDispatcher = scrollDispatcher;
        this.styleService = styleService;
        this.unsubscribe = new Subject();
        this.filterCount = -1;
        this.filteredCountSubject = new Subject();
        this.tableClass = null;
        this.grouped = [];
        this.isSelected = false;
        this.page = 1;
        this.count = 0;
        this.sortState = new Map();
        this.sortKey = null;
        this.rowContextMenuPosition = {
            top: null,
            left: null,
            value: null,
        };
        this.sortBy = {
            key: '',
            order: 'asc',
        };
        this.selectedDetailsTemplateRowId = new Set();
        this.selectedCheckboxes = new Set();
        this.id = 'table';
        this.event = new EventEmitter();
        this.isAllSortEnabled = false;
        this.filteredCountSubject.pipe(takeUntil(this.unsubscribe)).subscribe((count) => {
            setTimeout(() => {
                this.filterCount = count;
                this.cdr.detectChanges();
            });
        });
    }
    ngOnInit() {
        if (!this.columns) {
            console.error('[columns] property required!');
        }
        if (this.configuration) {
            this.config = this.configuration;
        }
        else {
            this.config = DefaultConfigService.config;
        }
        this.limit = this.config.rows;
        if (this.groupRowsBy) {
            this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);
        }
        this.doDecodePersistedState();
    }
    ngOnDestroy() {
        this.unsubscribe.next();
        this.unsubscribe.complete();
    }
    ngAfterViewInit() {
        const throttleValue = this.config.infiniteScrollThrottleTime
            ? this.config.infiniteScrollThrottleTime
            : 200;
        this.scrollDispatcher
            .scrolled()
            .pipe(throttleTime(throttleValue), filter((event) => {
            return (!!event &&
                this.viewPort &&
                this.viewPort.getRenderedRange().end === this.viewPort.getDataLength());
        }), takeUntil(this.unsubscribe))
            .subscribe(() => {
            this.emitEvent(Event.onInfiniteScrollEnd, null);
        });
    }
    ngOnChanges(changes) {
        const { configuration, data, pagination, groupRowsBy } = changes;
        this.toggleRowIndex = changes.toggleRowIndex;
        if (configuration && configuration.currentValue) {
            this.config = configuration.currentValue;
        }
        if (data && data.currentValue) {
            this.doApplyData(data);
        }
        if (pagination && pagination.currentValue) {
            const { count, limit, offset } = pagination.currentValue;
            this.count = count;
            this.limit = limit;
            this.page = offset;
        }
        if (groupRowsBy && groupRowsBy.currentValue) {
            this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);
        }
        if (this.toggleRowIndex && this.toggleRowIndex.currentValue) {
            const row = this.toggleRowIndex.currentValue;
            this.collapseRow(row.index);
        }
    }
    orderBy(column) {
        if (typeof column.orderEnabled !== 'undefined' && !column.orderEnabled) {
            return;
        }
        this.sortKey = column.key;
        if (!this.config.orderEnabled || this.sortKey === '') {
            return;
        }
        this.setColumnOrder(column);
        if (!this.config.orderEventOnly && !column.orderEventOnly) {
            this.sortBy.key = this.sortKey;
            this.sortBy.order = this.sortState.get(this.sortKey);
        }
        else {
            this.sortBy.key = '';
            this.sortBy.order = '';
        }
        if (!this.config.serverPagination) {
            this.data = [...this.data];
            this.sortBy = { ...this.sortBy };
        }
        const value = {
            key: this.sortKey,
            order: this.sortState.get(this.sortKey),
        };
        this.emitEvent(Event.onOrder, value);
    }
    onClick($event, row, key, colIndex, rowIndex) {
        if (this.config.selectRow) {
            this.selectedRow = rowIndex;
        }
        if (this.config.selectCol && `${colIndex}`) {
            this.selectedCol = colIndex;
        }
        if (this.config.selectCell && `${colIndex}`) {
            this.selectedRow = rowIndex;
            this.selectedCol = colIndex;
        }
        if (this.config.clickEvent) {
            const value = {
                event: $event,
                row,
                key,
                rowId: rowIndex,
                colId: colIndex,
            };
            this.emitEvent(Event.onClick, value);
        }
    }
    onDoubleClick($event, row, key, colIndex, rowIndex) {
        const value = {
            event: $event,
            row,
            key,
            rowId: rowIndex,
            colId: colIndex,
        };
        this.emitEvent(Event.onDoubleClick, value);
    }
    onCheckboxSelect($event, row, rowIndex) {
        const value = {
            event: $event,
            row,
            rowId: rowIndex,
        };
        this.emitEvent(Event.onCheckboxSelect, value);
    }
    onRadioSelect($event, row, rowIndex) {
        const value = {
            event: $event,
            row,
            rowId: rowIndex,
        };
        this.emitEvent(Event.onRadioSelect, value);
    }
    onSelectAll() {
        this.isSelected = !this.isSelected;
        this.emitEvent(Event.onSelectAll, this.isSelected);
    }
    onSearch($event) {
        if (!this.config.serverPagination) {
            this.term = $event;
        }
        this.emitEvent(Event.onSearch, $event);
    }
    onGlobalSearch(value) {
        if (!this.config.serverPagination) {
            this.globalSearchTerm = value;
        }
        this.emitEvent(Event.onGlobalSearch, value);
    }
    onPagination(pagination) {
        this.page = pagination.page;
        this.limit = pagination.limit;
        this.config.rows = pagination.limit;
        this.emitEvent(Event.onPagination, pagination);
    }
    toggleCheckbox(rowIndex) {
        this.selectedCheckboxes.has(rowIndex)
            ? this.selectedCheckboxes.delete(rowIndex)
            : this.selectedCheckboxes.add(rowIndex);
    }
    collapseRow(rowIndex) {
        if (this.selectedDetailsTemplateRowId.has(rowIndex)) {
            this.selectedDetailsTemplateRowId.delete(rowIndex);
            this.emitEvent(Event.onRowCollapsedHide, rowIndex);
        }
        else {
            this.selectedDetailsTemplateRowId.add(rowIndex);
            this.emitEvent(Event.onRowCollapsedShow, rowIndex);
        }
    }
    doDecodePersistedState() {
        if (!this.config.persistState) {
            return;
        }
        const pagination = localStorage.getItem(Event.onPagination);
        const sort = localStorage.getItem(Event.onOrder);
        const search = localStorage.getItem(Event.onSearch);
        if (pagination) {
            this.onPagination(JSON.parse(pagination));
        }
        if (sort) {
            const { key, order } = JSON.parse(sort);
            this.bindApi({
                type: API.sortBy,
                value: { column: key, order },
            });
        }
        if (search) {
            this.bindApi({
                type: API.setInputValue,
                value: JSON.parse(search),
            });
        }
    }
    isRowCollapsed(rowIndex) {
        if (this.config.collapseAllRows) {
            return true;
        }
        return this.selectedDetailsTemplateRowId.has(rowIndex);
    }
    get loadingHeight() {
        const table = document.getElementById(this.id);
        if (table && table.rows && table.rows.length > 3) {
            const searchEnabled = this.config.searchEnabled ? 1 : 0;
            const headerEnabled = this.config.headerEnabled ? 1 : 0;
            const borderTrHeight = 1;
            const borderDivHeight = 2;
            return ((table.rows.length - searchEnabled - headerEnabled) *
                (table.rows[3].offsetHeight - borderTrHeight) -
                borderDivHeight);
        }
        return 30;
    }
    get arrowDefinition() {
        return this.config.showDetailsArrow || typeof this.config.showDetailsArrow === 'undefined';
    }
    onRowContextMenu($event, row, key, colIndex, rowIndex) {
        if (!this.config.showContextMenu) {
            return;
        }
        $event.preventDefault();
        const value = {
            event: $event,
            row,
            key,
            rowId: rowIndex,
            colId: colIndex,
        };
        this.rowContextMenuPosition = {
            top: `${$event.pageY - 10}px`,
            left: `${$event.pageX - 10}px`,
            value,
        };
        this.emitEvent(Event.onRowContextMenu, value);
    }
    doApplyData(data) {
        const order = this.columns.find((c) => !!c.orderBy);
        if (order) {
            this.sortState.set(this.sortKey, order.orderBy === 'asc' ? 'desc' : 'asc');
            this.orderBy(order);
        }
        else {
            this.data = [...data.currentValue];
        }
    }
    onDragStart(event) {
        this.emitEvent(Event.onReorderStart, event);
    }
    onDrop(event) {
        this.emitEvent(Event.onRowDrop, event);
        moveItemInArray(this.data, event.previousIndex, event.currentIndex);
    }
    // DO NOT REMOVE. It is called from parent component. See src/app/demo/api-doc/api-doc.component.ts
    apiEvent(event) {
        return this.bindApi(event);
    }
    /* eslint-disable */
    bindApi(event) {
        switch (event.type) {
            case API.rowContextMenuClicked:
                this.rowContextMenuPosition = {
                    top: null,
                    left: null,
                    value: null,
                };
                break;
            case API.toggleRowIndex:
                this.collapseRow(event.value);
                break;
            case API.toggleCheckbox:
                this.toggleCheckbox(event.value);
                break;
            case API.setInputValue:
                if (this.config.searchEnabled) {
                    event.value.forEach((input) => {
                        const element = document.getElementById(`search_${input.key}`);
                        if (!element) {
                            console.error(`Column '${input.key}' not available in the DOM. Have you misspelled a name?`);
                        }
                        else {
                            element.value = input.value;
                        }
                    });
                }
                this.onSearch(event.value);
                this.cdr.markForCheck();
                break;
            case API.onGlobalSearch:
                this.onGlobalSearch(event.value);
                this.cdr.markForCheck();
                break;
            case API.setRowClass:
                if (Array.isArray(event.value)) {
                    event.value.forEach((val) => this.styleService.setRowClass(val));
                    break;
                }
                this.styleService.setRowClass(event.value);
                this.cdr.markForCheck();
                break;
            case API.setCellClass:
                if (Array.isArray(event.value)) {
                    event.value.forEach((val) => this.styleService.setCellClass(val));
                    break;
                }
                this.styleService.setCellClass(event.value);
                break;
            case API.setRowStyle:
                if (Array.isArray(event.value)) {
                    event.value.forEach((val) => this.styleService.setRowStyle(val));
                    break;
                }
                this.styleService.setRowStyle(event.value);
                break;
            case API.setCellStyle:
                if (Array.isArray(event.value)) {
                    event.value.forEach((val) => this.styleService.setCellStyle(val));
                    break;
                }
                this.styleService.setCellStyle(event.value);
                break;
            case API.setTableClass:
                this.tableClass = event.value;
                this.cdr.markForCheck();
                break;
            case API.getPaginationTotalItems:
                return this.paginationComponent.paginationDirective.getTotalItems();
            case API.getPaginationCurrentPage:
                return this.paginationComponent.paginationDirective.getCurrent();
            case API.getPaginationLastPage:
                return this.paginationComponent.paginationDirective.getLastPage();
            case API.getNumberOfRowsPerPage:
                return this.paginationComponent.paginationDirective.isLastPage()
                    ? this.paginationComponent.paginationDirective.getTotalItems() % this.limit
                    : this.limit;
            case API.setPaginationCurrentPage:
                this.paginationComponent.paginationDirective.setCurrent(event.value);
                break;
            case API.setPaginationRange:
                this.paginationComponent.ranges = event.value;
                break;
            case API.setPaginationPreviousLabel:
                this.paginationComponent.previousLabel = event.value;
                break;
            case API.setPaginationNextLabel:
                this.paginationComponent.nextLabel = event.value;
                break;
            case API.setPaginationDisplayLimit:
                this.paginationComponent.changeLimit(event.value, true);
                break;
            case API.sortBy:
                const column = { title: '', key: event.value.column, orderBy: event.value.order };
                this.orderBy(column);
                this.cdr.detectChanges();
                break;
            default:
                break;
        }
    }
    setColumnOrder(column) {
        const key = column.key;
        switch (this.sortState.get(key)) {
            case '':
            case undefined:
                this.sortState.set(key, column.orderBy || 'desc');
                break;
            case 'asc':
                this.config.threeWaySort ? this.sortState.set(key, '') : this.sortState.set(key, 'desc');
                break;
            case 'desc':
                this.sortState.set(key, 'asc');
                break;
        }
        if (this.sortState.size > 1) {
            const temp = this.sortState.get(key);
            this.sortState.clear();
            this.sortState.set(key, temp);
        }
    }
    emitEvent(event, value) {
        this.event.emit({ event, value });
        if (this.config.persistState) {
            localStorage.setItem(event, JSON.stringify(value));
        }
        if (this.config.logger) {
            // eslint-disable-next-line no-console
            console.log({ event, value });
        }
    }
    dragEnter($event) {
        $event.preventDefault();
        $event.stopPropagation();
    }
    dragOver($event) {
        $event.preventDefault();
        $event.stopPropagation();
    }
    dragLeave($event) {
        $event.preventDefault();
        $event.stopPropagation();
    }
    drop($event) {
        $event.preventDefault();
        $event.stopPropagation();
        const file = $event.dataTransfer?.files?.[0];
        if (file?.type !== 'application/json') {
            // eslint-disable-next-line no-console
            console.log('File not allowed');
            return;
        }
        const fileReader = new FileReader();
        fileReader.onload = (event) => {
            this.data = JSON.parse(event?.target?.result);
            this.cdr.markForCheck();
        };
        fileReader.readAsText(file);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.ScrollDispatcher }, { token: i2.StyleService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: BaseComponent, selector: "ngx-table", inputs: { configuration: "configuration", data: "data", pagination: "pagination", groupRowsBy: "groupRowsBy", id: "id", toggleRowIndex: "toggleRowIndex", detailsTemplate: "detailsTemplate", summaryTemplate: "summaryTemplate", groupRowsHeaderTemplate: "groupRowsHeaderTemplate", filtersTemplate: "filtersTemplate", selectAllTemplate: "selectAllTemplate", noResultsTemplate: "noResultsTemplate", loadingTemplate: "loadingTemplate", additionalActionsTemplate: "additionalActionsTemplate", rowContextMenu: "rowContextMenu", columns: "columns", isAllSortEnabled: "isAllSortEnabled" }, outputs: { event: "event" }, host: { listeners: { "document:click": "onContextMenuClick($event.target)" } }, providers: [DefaultConfigService, GroupRowsService, StyleService], queries: [{ propertyName: "rowTemplate", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "paginationComponent", first: true, predicate: ["paginationComponent"], descendants: true }, { propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true }, { propertyName: "table", first: true, predicate: ["table"], descendants: true }, { propertyName: "viewPort", first: true, predicate: CdkVirtualScrollViewport, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\r\n  class=\"ngx-container\"\r\n  [class.ngx-container--dark]=\"config.tableLayout.theme === 'dark'\"\r\n  (dragenter)=\"dragEnter($event)\"\r\n  (dragover)=\"dragOver($event)\"\r\n  (dragleave)=\"dragLeave($event)\"\r\n  (drop)=\"drop($event)\"\r\n>\r\n  <table\r\n    [id]=\"id\"\r\n    #table\r\n    [ngClass]=\"tableClass === null || tableClass === '' ? 'ngx-table' : tableClass\"\r\n    [class.ngx-table__table--tiny]=\"config.tableLayout.style === 'tiny'\"\r\n    [class.ngx-table__table--normal]=\"config.tableLayout.style === 'normal'\"\r\n    [class.ngx-table__table--big]=\"config.tableLayout.style === 'big'\"\r\n    [class.ngx-table__table--borderless]=\"config.tableLayout.borderless\"\r\n    [class.ngx-table__table--dark]=\"config.tableLayout.theme === 'dark'\"\r\n    [class.ngx-table__table--hoverable]=\"config.tableLayout.hover\"\r\n    [class.ngx-table__table--striped]=\"config.tableLayout.striped\"\r\n    [class.ngx-table__horizontal-scroll]=\"config.horizontalScroll && !config.isLoading\"\r\n  >\r\n    <thead\r\n      [class.ngx-infinite-scroll-viewport-thead]=\"config.infiniteScroll\"\r\n      table-thead\r\n      [config]=\"config\"\r\n      [sortKey]=\"sortKey\"\r\n      [sortState]=\"sortState\"\r\n      [selectAllTemplate]=\"selectAllTemplate\"\r\n      [filtersTemplate]=\"filtersTemplate\"\r\n      [additionalActionsTemplate]=\"additionalActionsTemplate\"\r\n      [columns]=\"columns\"\r\n      (selectAll)=\"onSelectAll()\"\r\n      (filter)=\"onSearch($event)\"\r\n      (order)=\"orderBy($event)\"\r\n      (event)=\"emitEvent($event.event, $event.value)\"\r\n    ></thead>\r\n    <tbody *ngIf=\"data && !config.isLoading && !config.rowReorder\">\r\n      <ng-container *ngIf=\"rowTemplate\">\r\n        <ul\r\n          class=\"ngx-table__table-row-context-menu\"\r\n          [ngStyle]=\"{\r\n            position: 'absolute',\r\n            top: rowContextMenuPosition.top,\r\n            left: rowContextMenuPosition.left\r\n          }\"\r\n          *ngIf=\"rowContextMenuPosition.top\"\r\n        >\r\n          <ng-container\r\n            [ngTemplateOutlet]=\"rowContextMenu\"\r\n            [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\r\n          >\r\n          </ng-container>\r\n        </ul>\r\n        <ng-container *ngIf=\"!config.infiniteScroll\">\r\n          <ng-container\r\n            *ngFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject\r\n                | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\r\n            \"\r\n          >\r\n            <tr\r\n              (click)=\"onClick($event, row, '', null, data.indexOf(row))\"\r\n              #contextMenu\r\n              (contextmenu)=\"onRowContextMenu($event, row, '', null, data.indexOf(row))\"\r\n              (dblclick)=\"onDoubleClick($event, row, '', null, data.indexOf(row))\"\r\n              [class.ngx-table__table-row--selected]=\"\r\n                data.indexOf(row) === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <ng-container\r\n                [ngTemplateOutlet]=\"rowTemplate\"\r\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\r\n              >\r\n              </ng-container>\r\n              <td *ngIf=\"config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(data.indexOf(row))\r\n                      ? 'ngx-icon-arrow-down'\r\n                      : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(data.indexOf(row))\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </ng-container>\r\n        <cdk-virtual-scroll-viewport\r\n          itemSize=\"50\"\r\n          *ngIf=\"config.infiniteScroll\"\r\n          class=\"ngx-infinite-scroll-viewport\"\r\n        >\r\n          <ng-container\r\n            *cdkVirtualFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject;\r\n              let rowIndex = index\r\n            \"\r\n          >\r\n            <tr\r\n              (click)=\"onClick($event, row, '', null, rowIndex)\"\r\n              #contextMenu\r\n              (contextmenu)=\"onRowContextMenu($event, row, '', null, rowIndex)\"\r\n              (dblclick)=\"onDoubleClick($event, row, '', null, rowIndex)\"\r\n              [class.ngx-table__table-row--selected]=\"\r\n                rowIndex === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <ng-container\r\n                [ngTemplateOutlet]=\"rowTemplate\"\r\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\r\n              >\r\n              </ng-container>\r\n              <td *ngIf=\"config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(rowIndex)\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </cdk-virtual-scroll-viewport>\r\n      </ng-container>\r\n      <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\r\n        <ul\r\n          class=\"ngx-table__table-row-context-menu\"\r\n          [ngStyle]=\"{\r\n            position: 'absolute',\r\n            top: rowContextMenuPosition.top,\r\n            left: rowContextMenuPosition.left\r\n          }\"\r\n          *ngIf=\"rowContextMenuPosition.top\"\r\n        >\r\n          <ng-container\r\n            [ngTemplateOutlet]=\"rowContextMenu\"\r\n            [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\r\n          >\r\n          </ng-container>\r\n        </ul>\r\n        <ng-container *ngIf=\"!config.infiniteScroll\">\r\n          <ng-container\r\n            *ngFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject\r\n                | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\r\n            \"\r\n          >\r\n            <tr\r\n              [class.ngx-table__table-row--selected]=\"\r\n                data.indexOf(row) === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes\">\r\n                <label class=\"ngx-form-checkbox\">\r\n                  <input\r\n                    type=\"checkbox\"\r\n                    id=\"checkbox-{{ data.indexOf(row) }}\"\r\n                    [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\r\n                    (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\r\n                  />\r\n                  <em class=\"ngx-form-icon\"></em>\r\n                </label>\r\n              </td>\r\n              <td *ngIf=\"config.radio\">\r\n                <label>\r\n                  <input\r\n                    type=\"radio\"\r\n                    id=\"radio-{{ data.indexOf(row) }}\"\r\n                    name=\"radio\"\r\n                    (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\r\n                  />\r\n                </label>\r\n              </td>\r\n              <ng-container *ngFor=\"let column of columns; let colIndex = index\">\r\n                <td\r\n                  (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                  #contextMenu\r\n                  (contextmenu)=\"\r\n                    onRowContextMenu($event, row, column.key, colIndex, data.indexOf(row))\r\n                  \"\r\n                  (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                  [class.pinned-left]=\"column.pinned\"\r\n                  [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\r\n                  [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\r\n                  [class.ngx-table__table-col--selected]=\"\r\n                    colIndex === selectedCol && !config.selectCell\r\n                  \"\r\n                  [class.ngx-table__table-cell--selected]=\"\r\n                    colIndex === selectedCol &&\r\n                    data.indexOf(row) === selectedRow &&\r\n                    !config.selectCol &&\r\n                    !config.selectRow\r\n                  \"\r\n                >\r\n                  <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\r\n                  <ng-container\r\n                    *ngIf=\"column.cellTemplate\"\r\n                    [ngTemplateOutlet]=\"column.cellTemplate\"\r\n                    [ngTemplateOutletContext]=\"{\r\n                      $implicit: row,\r\n                      rowIndex: data.indexOf(row),\r\n                      column: column\r\n                    }\"\r\n                  >\r\n                  </ng-container>\r\n                </td>\r\n              </ng-container>\r\n              <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(data.indexOf(row))\r\n                      ? 'ngx-icon-arrow-down'\r\n                      : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(data.indexOf(row))\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes || config.radio\"></td>\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </ng-container>\r\n        <!-- infinite scroll -->\r\n        <cdk-virtual-scroll-viewport\r\n          itemSize=\"50\"\r\n          *ngIf=\"config.infiniteScroll\"\r\n          class=\"ngx-infinite-scroll-viewport\"\r\n        >\r\n          <ng-container\r\n            *cdkVirtualFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject;\r\n              let rowIndex = index\r\n            \"\r\n          >\r\n            <tr\r\n              [class.ngx-table__table-row--selected]=\"\r\n                rowIndex === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes\" width=\"3%\">\r\n                <label class=\"ngx-form-checkbox\">\r\n                  <input\r\n                    type=\"checkbox\"\r\n                    id=\"checkbox-infinite-scroll-{{ rowIndex }}\"\r\n                    [checked]=\"isSelected || selectedCheckboxes.has(rowIndex)\"\r\n                    (change)=\"onCheckboxSelect($event, row, rowIndex)\"\r\n                  />\r\n                  <em class=\"ngx-form-icon\"></em>\r\n                </label>\r\n              </td>\r\n              <td *ngIf=\"config.radio\" width=\"3%\">\r\n                <label>\r\n                  <input\r\n                    type=\"radio\"\r\n                    id=\"radio-infinite-scroll-{{ rowIndex }}\"\r\n                    name=\"radio\"\r\n                    (change)=\"onRadioSelect($event, row, rowIndex)\"\r\n                  />\r\n                </label>\r\n              </td>\r\n              <ng-container *ngFor=\"let column of columns; let colIndex = index\">\r\n                <td\r\n                  (click)=\"onClick($event, row, column.key, colIndex, rowIndex)\"\r\n                  #contextMenu\r\n                  (contextmenu)=\"onRowContextMenu($event, row, column.key, colIndex, rowIndex)\"\r\n                  (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, rowIndex)\"\r\n                  [class.pinned-left]=\"column.pinned\"\r\n                  [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\r\n                  [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\r\n                  [class.ngx-table__table-col--selected]=\"\r\n                    colIndex === selectedCol && !config.selectCell\r\n                  \"\r\n                  [class.ngx-table__table-cell--selected]=\"\r\n                    colIndex === selectedCol &&\r\n                    rowIndex === selectedRow &&\r\n                    !config.selectCol &&\r\n                    !config.selectRow\r\n                  \"\r\n                >\r\n                  <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\r\n                  <ng-container\r\n                    *ngIf=\"column.cellTemplate\"\r\n                    [ngTemplateOutlet]=\"column.cellTemplate\"\r\n                    [ngTemplateOutletContext]=\"{\r\n                      $implicit: row,\r\n                      rowIndex: rowIndex,\r\n                      column: column\r\n                    }\"\r\n                  >\r\n                  </ng-container>\r\n                </td>\r\n              </ng-container>\r\n              <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(rowIndex)\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes || config.radio\"></td>\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </cdk-virtual-scroll-viewport>\r\n      </ng-container>\r\n      <ng-container *ngIf=\"!rowTemplate && config.groupRows\">\r\n        <ng-container\r\n          *ngFor=\"\r\n            let group of grouped\r\n              | sort: sortBy:config\r\n              | search: term:filteredCountSubject:config\r\n              | global: globalSearchTerm:filteredCountSubject\r\n              | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\r\n            let rowIndex = index\r\n          \"\r\n        >\r\n          <tr>\r\n            <ng-container *ngIf=\"!groupRowsHeaderTemplate\">\r\n              <td [attr.colspan]=\"columns.length\">\r\n                <div>{{ group[0][groupRowsBy] }} ({{ group.length }})</div>\r\n              </td>\r\n            </ng-container>\r\n            <ng-container\r\n              *ngIf=\"groupRowsHeaderTemplate\"\r\n              [ngTemplateOutlet]=\"groupRowsHeaderTemplate\"\r\n              [ngTemplateOutletContext]=\"{\r\n                total: group.length,\r\n                key: groupRowsBy,\r\n                value: group[0] ? group[0][groupRowsBy] : '',\r\n                group: group,\r\n                index: rowIndex\r\n              }\"\r\n            >\r\n            </ng-container>\r\n            <td>\r\n              <span\r\n                class=\"ngx-icon\"\r\n                *ngIf=\"arrowDefinition\"\r\n                [ngClass]=\"\r\n                  isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\r\n                \"\r\n                (click)=\"collapseRow(rowIndex)\"\r\n              >\r\n              </span>\r\n            </td>\r\n          </tr>\r\n          <ng-container *ngIf=\"selectedDetailsTemplateRowId.has(rowIndex)\">\r\n            <tr *ngFor=\"let row of group\">\r\n              <td *ngFor=\"let column of columns\">\r\n                {{ row | render: column.key }}\r\n                <!-- TODO allow users to add groupRowsTemplateRef -->\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n          </ng-container>\r\n        </ng-container>\r\n      </ng-container>\r\n    </tbody>\r\n    <tbody\r\n      *ngIf=\"data && !config.isLoading && config.rowReorder\"\r\n      class=\"ngx-draggable-row-area\"\r\n      cdkDropList\r\n      (cdkDropListDropped)=\"onDrop($event)\"\r\n    >\r\n      <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\r\n        <ng-container\r\n          *ngFor=\"\r\n            let row of data\r\n              | sort: sortBy\r\n              | search: term:filteredCountSubject\r\n              | global: globalSearchTerm:filteredCountSubject\r\n              | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\r\n          \"\r\n        >\r\n          <tr\r\n            class=\"ngx-draggable-row\"\r\n            cdkDrag\r\n            (cdkDragStarted)=\"onDragStart($event)\"\r\n            [cdkDragStartDelay]=\"config.reorderDelay || 0\"\r\n            cdkDragLockAxis=\"y\"\r\n          >\r\n            <td *ngIf=\"config.checkboxes\">\r\n              <label class=\"ngx-form-checkbox\">\r\n                <input\r\n                  type=\"checkbox\"\r\n                  id=\"checkbox-draggable-{{ data.indexOf(row) }}\"\r\n                  [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\r\n                  (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\r\n                />\r\n                <em class=\"ngx-form-icon\"></em>\r\n              </label>\r\n            </td>\r\n            <td *ngIf=\"config.radio\">\r\n              <label>\r\n                <input\r\n                  type=\"radio\"\r\n                  id=\"radio-draggable-{{ data.indexOf(row) }}\"\r\n                  name=\"radio\"\r\n                  (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\r\n                />\r\n              </label>\r\n            </td>\r\n            <ng-container *ngFor=\"let column of columns; let colIndex = index\">\r\n              <td\r\n                (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                [class.ngx-table__table-col--selected]=\"\r\n                  colIndex === selectedCol && !config.selectCell\r\n                \"\r\n                [class.ngx-table__table-cell--selected]=\"\r\n                  colIndex === selectedCol &&\r\n                  data.indexOf(row) === selectedRow &&\r\n                  !config.selectCol &&\r\n                  !config.selectRow\r\n                \"\r\n              >\r\n                <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\r\n                <ng-container\r\n                  *ngIf=\"column.cellTemplate\"\r\n                  [ngTemplateOutlet]=\"column.cellTemplate\"\r\n                  [ngTemplateOutletContext]=\"{\r\n                    $implicit: row,\r\n                    rowIndex: data.indexOf(row),\r\n                    column: column\r\n                  }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </ng-container>\r\n          </tr>\r\n        </ng-container>\r\n      </ng-container>\r\n    </tbody>\r\n    <tbody *ngIf=\"filterCount === 0\">\r\n      <tr class=\"ngx-table__body-empty\">\r\n        <ng-container *ngIf=\"noResultsTemplate\" [ngTemplateOutlet]=\"noResultsTemplate\">\r\n        </ng-container>\r\n        <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!noResultsTemplate\">\r\n          <div class=\"ngx-table__table-no-results\">No results</div>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n    <tbody *ngIf=\"config.isLoading\">\r\n      <tr class=\"ngx-table__body-loading\">\r\n        <ng-container *ngIf=\"loadingTemplate\" [ngTemplateOutlet]=\"loadingTemplate\"> </ng-container>\r\n        <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!loadingTemplate\">\r\n          <div [style.height.px]=\"loadingHeight\" class=\"ngx-table__table-loader-wrapper\">\r\n            <div class=\"ngx-table__table-loader\"></div>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n    <tfoot *ngIf=\"summaryTemplate\">\r\n      <tr>\r\n        <ng-container\r\n          [ngTemplateOutlet]=\"summaryTemplate\"\r\n          [ngTemplateOutletContext]=\"{ total: data.length, limit: limit, page: page }\"\r\n        >\r\n        </ng-container>\r\n      </tr>\r\n    </tfoot>\r\n  </table>\r\n  <pagination\r\n    [attr.id]=\"'pagination' + id\"\r\n    [id]=\"id\"\r\n    #paginationComponent\r\n    [config]=\"config\"\r\n    [pagination]=\"pagination\"\r\n    (updateRange)=\"onPagination($event)\"\r\n  >\r\n  </pagination>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: i5.PaginationComponent, selector: "pagination", inputs: ["pagination", "config", "id"], outputs: ["updateRange"] }, { kind: "component", type: i6.TableTHeadComponent, selector: "[table-thead]", inputs: ["config", "columns", "sortKey", "sortState", "selectAllTemplate", "filtersTemplate", "additionalActionsTemplate", "isAllSortEnabled"], outputs: ["filter", "order", "selectAll", "event"] }, { kind: "pipe", type: i7.PaginatePipe, name: "paginate" }, { kind: "pipe", type: i8.SearchPipe, name: "search" }, { kind: "pipe", type: i9.RenderPipe, name: "render" }, { kind: "pipe", type: i10.GlobalSearchPipe, name: "global" }, { kind: "pipe", type: i11.SortPipe, name: "sort" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ngx-table', providers: [DefaultConfigService, GroupRowsService, StyleService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n  class=\"ngx-container\"\r\n  [class.ngx-container--dark]=\"config.tableLayout.theme === 'dark'\"\r\n  (dragenter)=\"dragEnter($event)\"\r\n  (dragover)=\"dragOver($event)\"\r\n  (dragleave)=\"dragLeave($event)\"\r\n  (drop)=\"drop($event)\"\r\n>\r\n  <table\r\n    [id]=\"id\"\r\n    #table\r\n    [ngClass]=\"tableClass === null || tableClass === '' ? 'ngx-table' : tableClass\"\r\n    [class.ngx-table__table--tiny]=\"config.tableLayout.style === 'tiny'\"\r\n    [class.ngx-table__table--normal]=\"config.tableLayout.style === 'normal'\"\r\n    [class.ngx-table__table--big]=\"config.tableLayout.style === 'big'\"\r\n    [class.ngx-table__table--borderless]=\"config.tableLayout.borderless\"\r\n    [class.ngx-table__table--dark]=\"config.tableLayout.theme === 'dark'\"\r\n    [class.ngx-table__table--hoverable]=\"config.tableLayout.hover\"\r\n    [class.ngx-table__table--striped]=\"config.tableLayout.striped\"\r\n    [class.ngx-table__horizontal-scroll]=\"config.horizontalScroll && !config.isLoading\"\r\n  >\r\n    <thead\r\n      [class.ngx-infinite-scroll-viewport-thead]=\"config.infiniteScroll\"\r\n      table-thead\r\n      [config]=\"config\"\r\n      [sortKey]=\"sortKey\"\r\n      [sortState]=\"sortState\"\r\n      [selectAllTemplate]=\"selectAllTemplate\"\r\n      [filtersTemplate]=\"filtersTemplate\"\r\n      [additionalActionsTemplate]=\"additionalActionsTemplate\"\r\n      [columns]=\"columns\"\r\n      (selectAll)=\"onSelectAll()\"\r\n      (filter)=\"onSearch($event)\"\r\n      (order)=\"orderBy($event)\"\r\n      (event)=\"emitEvent($event.event, $event.value)\"\r\n    ></thead>\r\n    <tbody *ngIf=\"data && !config.isLoading && !config.rowReorder\">\r\n      <ng-container *ngIf=\"rowTemplate\">\r\n        <ul\r\n          class=\"ngx-table__table-row-context-menu\"\r\n          [ngStyle]=\"{\r\n            position: 'absolute',\r\n            top: rowContextMenuPosition.top,\r\n            left: rowContextMenuPosition.left\r\n          }\"\r\n          *ngIf=\"rowContextMenuPosition.top\"\r\n        >\r\n          <ng-container\r\n            [ngTemplateOutlet]=\"rowContextMenu\"\r\n            [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\r\n          >\r\n          </ng-container>\r\n        </ul>\r\n        <ng-container *ngIf=\"!config.infiniteScroll\">\r\n          <ng-container\r\n            *ngFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject\r\n                | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\r\n            \"\r\n          >\r\n            <tr\r\n              (click)=\"onClick($event, row, '', null, data.indexOf(row))\"\r\n              #contextMenu\r\n              (contextmenu)=\"onRowContextMenu($event, row, '', null, data.indexOf(row))\"\r\n              (dblclick)=\"onDoubleClick($event, row, '', null, data.indexOf(row))\"\r\n              [class.ngx-table__table-row--selected]=\"\r\n                data.indexOf(row) === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <ng-container\r\n                [ngTemplateOutlet]=\"rowTemplate\"\r\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\r\n              >\r\n              </ng-container>\r\n              <td *ngIf=\"config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(data.indexOf(row))\r\n                      ? 'ngx-icon-arrow-down'\r\n                      : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(data.indexOf(row))\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </ng-container>\r\n        <cdk-virtual-scroll-viewport\r\n          itemSize=\"50\"\r\n          *ngIf=\"config.infiniteScroll\"\r\n          class=\"ngx-infinite-scroll-viewport\"\r\n        >\r\n          <ng-container\r\n            *cdkVirtualFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject;\r\n              let rowIndex = index\r\n            \"\r\n          >\r\n            <tr\r\n              (click)=\"onClick($event, row, '', null, rowIndex)\"\r\n              #contextMenu\r\n              (contextmenu)=\"onRowContextMenu($event, row, '', null, rowIndex)\"\r\n              (dblclick)=\"onDoubleClick($event, row, '', null, rowIndex)\"\r\n              [class.ngx-table__table-row--selected]=\"\r\n                rowIndex === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <ng-container\r\n                [ngTemplateOutlet]=\"rowTemplate\"\r\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\r\n              >\r\n              </ng-container>\r\n              <td *ngIf=\"config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(rowIndex)\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </cdk-virtual-scroll-viewport>\r\n      </ng-container>\r\n      <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\r\n        <ul\r\n          class=\"ngx-table__table-row-context-menu\"\r\n          [ngStyle]=\"{\r\n            position: 'absolute',\r\n            top: rowContextMenuPosition.top,\r\n            left: rowContextMenuPosition.left\r\n          }\"\r\n          *ngIf=\"rowContextMenuPosition.top\"\r\n        >\r\n          <ng-container\r\n            [ngTemplateOutlet]=\"rowContextMenu\"\r\n            [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\r\n          >\r\n          </ng-container>\r\n        </ul>\r\n        <ng-container *ngIf=\"!config.infiniteScroll\">\r\n          <ng-container\r\n            *ngFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject\r\n                | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\r\n            \"\r\n          >\r\n            <tr\r\n              [class.ngx-table__table-row--selected]=\"\r\n                data.indexOf(row) === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes\">\r\n                <label class=\"ngx-form-checkbox\">\r\n                  <input\r\n                    type=\"checkbox\"\r\n                    id=\"checkbox-{{ data.indexOf(row) }}\"\r\n                    [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\r\n                    (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\r\n                  />\r\n                  <em class=\"ngx-form-icon\"></em>\r\n                </label>\r\n              </td>\r\n              <td *ngIf=\"config.radio\">\r\n                <label>\r\n                  <input\r\n                    type=\"radio\"\r\n                    id=\"radio-{{ data.indexOf(row) }}\"\r\n                    name=\"radio\"\r\n                    (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\r\n                  />\r\n                </label>\r\n              </td>\r\n              <ng-container *ngFor=\"let column of columns; let colIndex = index\">\r\n                <td\r\n                  (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                  #contextMenu\r\n                  (contextmenu)=\"\r\n                    onRowContextMenu($event, row, column.key, colIndex, data.indexOf(row))\r\n                  \"\r\n                  (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                  [class.pinned-left]=\"column.pinned\"\r\n                  [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\r\n                  [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\r\n                  [class.ngx-table__table-col--selected]=\"\r\n                    colIndex === selectedCol && !config.selectCell\r\n                  \"\r\n                  [class.ngx-table__table-cell--selected]=\"\r\n                    colIndex === selectedCol &&\r\n                    data.indexOf(row) === selectedRow &&\r\n                    !config.selectCol &&\r\n                    !config.selectRow\r\n                  \"\r\n                >\r\n                  <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\r\n                  <ng-container\r\n                    *ngIf=\"column.cellTemplate\"\r\n                    [ngTemplateOutlet]=\"column.cellTemplate\"\r\n                    [ngTemplateOutletContext]=\"{\r\n                      $implicit: row,\r\n                      rowIndex: data.indexOf(row),\r\n                      column: column\r\n                    }\"\r\n                  >\r\n                  </ng-container>\r\n                </td>\r\n              </ng-container>\r\n              <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(data.indexOf(row))\r\n                      ? 'ngx-icon-arrow-down'\r\n                      : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(data.indexOf(row))\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes || config.radio\"></td>\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </ng-container>\r\n        <!-- infinite scroll -->\r\n        <cdk-virtual-scroll-viewport\r\n          itemSize=\"50\"\r\n          *ngIf=\"config.infiniteScroll\"\r\n          class=\"ngx-infinite-scroll-viewport\"\r\n        >\r\n          <ng-container\r\n            *cdkVirtualFor=\"\r\n              let row of data\r\n                | sort: sortBy\r\n                | search: term:filteredCountSubject\r\n                | global: globalSearchTerm:filteredCountSubject;\r\n              let rowIndex = index\r\n            \"\r\n          >\r\n            <tr\r\n              [class.ngx-table__table-row--selected]=\"\r\n                rowIndex === selectedRow && !config.selectCell\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes\" width=\"3%\">\r\n                <label class=\"ngx-form-checkbox\">\r\n                  <input\r\n                    type=\"checkbox\"\r\n                    id=\"checkbox-infinite-scroll-{{ rowIndex }}\"\r\n                    [checked]=\"isSelected || selectedCheckboxes.has(rowIndex)\"\r\n                    (change)=\"onCheckboxSelect($event, row, rowIndex)\"\r\n                  />\r\n                  <em class=\"ngx-form-icon\"></em>\r\n                </label>\r\n              </td>\r\n              <td *ngIf=\"config.radio\" width=\"3%\">\r\n                <label>\r\n                  <input\r\n                    type=\"radio\"\r\n                    id=\"radio-infinite-scroll-{{ rowIndex }}\"\r\n                    name=\"radio\"\r\n                    (change)=\"onRadioSelect($event, row, rowIndex)\"\r\n                  />\r\n                </label>\r\n              </td>\r\n              <ng-container *ngFor=\"let column of columns; let colIndex = index\">\r\n                <td\r\n                  (click)=\"onClick($event, row, column.key, colIndex, rowIndex)\"\r\n                  #contextMenu\r\n                  (contextmenu)=\"onRowContextMenu($event, row, column.key, colIndex, rowIndex)\"\r\n                  (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, rowIndex)\"\r\n                  [class.pinned-left]=\"column.pinned\"\r\n                  [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\r\n                  [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\r\n                  [class.ngx-table__table-col--selected]=\"\r\n                    colIndex === selectedCol && !config.selectCell\r\n                  \"\r\n                  [class.ngx-table__table-cell--selected]=\"\r\n                    colIndex === selectedCol &&\r\n                    rowIndex === selectedRow &&\r\n                    !config.selectCol &&\r\n                    !config.selectRow\r\n                  \"\r\n                >\r\n                  <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\r\n                  <ng-container\r\n                    *ngIf=\"column.cellTemplate\"\r\n                    [ngTemplateOutlet]=\"column.cellTemplate\"\r\n                    [ngTemplateOutletContext]=\"{\r\n                      $implicit: row,\r\n                      rowIndex: rowIndex,\r\n                      column: column\r\n                    }\"\r\n                  >\r\n                  </ng-container>\r\n                </td>\r\n              </ng-container>\r\n              <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\r\n                <span\r\n                  class=\"ngx-icon\"\r\n                  *ngIf=\"arrowDefinition\"\r\n                  [ngClass]=\"\r\n                    isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\r\n                  \"\r\n                  (click)=\"collapseRow(rowIndex)\"\r\n                >\r\n                </span>\r\n              </td>\r\n            </tr>\r\n            <tr\r\n              *ngIf=\"\r\n                (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\r\n                config.collapseAllRows\r\n              \"\r\n            >\r\n              <td *ngIf=\"config.checkboxes || config.radio\"></td>\r\n              <td [attr.colspan]=\"columns.length + 1\">\r\n                <ng-container\r\n                  [ngTemplateOutlet]=\"detailsTemplate\"\r\n                  [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </tr>\r\n          </ng-container>\r\n        </cdk-virtual-scroll-viewport>\r\n      </ng-container>\r\n      <ng-container *ngIf=\"!rowTemplate && config.groupRows\">\r\n        <ng-container\r\n          *ngFor=\"\r\n            let group of grouped\r\n              | sort: sortBy:config\r\n              | search: term:filteredCountSubject:config\r\n              | global: globalSearchTerm:filteredCountSubject\r\n              | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\r\n            let rowIndex = index\r\n          \"\r\n        >\r\n          <tr>\r\n            <ng-container *ngIf=\"!groupRowsHeaderTemplate\">\r\n              <td [attr.colspan]=\"columns.length\">\r\n                <div>{{ group[0][groupRowsBy] }} ({{ group.length }})</div>\r\n              </td>\r\n            </ng-container>\r\n            <ng-container\r\n              *ngIf=\"groupRowsHeaderTemplate\"\r\n              [ngTemplateOutlet]=\"groupRowsHeaderTemplate\"\r\n              [ngTemplateOutletContext]=\"{\r\n                total: group.length,\r\n                key: groupRowsBy,\r\n                value: group[0] ? group[0][groupRowsBy] : '',\r\n                group: group,\r\n                index: rowIndex\r\n              }\"\r\n            >\r\n            </ng-container>\r\n            <td>\r\n              <span\r\n                class=\"ngx-icon\"\r\n                *ngIf=\"arrowDefinition\"\r\n                [ngClass]=\"\r\n                  isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\r\n                \"\r\n                (click)=\"collapseRow(rowIndex)\"\r\n              >\r\n              </span>\r\n            </td>\r\n          </tr>\r\n          <ng-container *ngIf=\"selectedDetailsTemplateRowId.has(rowIndex)\">\r\n            <tr *ngFor=\"let row of group\">\r\n              <td *ngFor=\"let column of columns\">\r\n                {{ row | render: column.key }}\r\n                <!-- TODO allow users to add groupRowsTemplateRef -->\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n          </ng-container>\r\n        </ng-container>\r\n      </ng-container>\r\n    </tbody>\r\n    <tbody\r\n      *ngIf=\"data && !config.isLoading && config.rowReorder\"\r\n      class=\"ngx-draggable-row-area\"\r\n      cdkDropList\r\n      (cdkDropListDropped)=\"onDrop($event)\"\r\n    >\r\n      <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\r\n        <ng-container\r\n          *ngFor=\"\r\n            let row of data\r\n              | sort: sortBy\r\n              | search: term:filteredCountSubject\r\n              | global: globalSearchTerm:filteredCountSubject\r\n              | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\r\n          \"\r\n        >\r\n          <tr\r\n            class=\"ngx-draggable-row\"\r\n            cdkDrag\r\n            (cdkDragStarted)=\"onDragStart($event)\"\r\n            [cdkDragStartDelay]=\"config.reorderDelay || 0\"\r\n            cdkDragLockAxis=\"y\"\r\n          >\r\n            <td *ngIf=\"config.checkboxes\">\r\n              <label class=\"ngx-form-checkbox\">\r\n                <input\r\n                  type=\"checkbox\"\r\n                  id=\"checkbox-draggable-{{ data.indexOf(row) }}\"\r\n                  [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\r\n                  (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\r\n                />\r\n                <em class=\"ngx-form-icon\"></em>\r\n              </label>\r\n            </td>\r\n            <td *ngIf=\"config.radio\">\r\n              <label>\r\n                <input\r\n                  type=\"radio\"\r\n                  id=\"radio-draggable-{{ data.indexOf(row) }}\"\r\n                  name=\"radio\"\r\n                  (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\r\n                />\r\n              </label>\r\n            </td>\r\n            <ng-container *ngFor=\"let column of columns; let colIndex = index\">\r\n              <td\r\n                (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\r\n                [class.ngx-table__table-col--selected]=\"\r\n                  colIndex === selectedCol && !config.selectCell\r\n                \"\r\n                [class.ngx-table__table-cell--selected]=\"\r\n                  colIndex === selectedCol &&\r\n                  data.indexOf(row) === selectedRow &&\r\n                  !config.selectCol &&\r\n                  !config.selectRow\r\n                \"\r\n              >\r\n                <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\r\n                <ng-container\r\n                  *ngIf=\"column.cellTemplate\"\r\n                  [ngTemplateOutlet]=\"column.cellTemplate\"\r\n                  [ngTemplateOutletContext]=\"{\r\n                    $implicit: row,\r\n                    rowIndex: data.indexOf(row),\r\n                    column: column\r\n                  }\"\r\n                >\r\n                </ng-container>\r\n              </td>\r\n            </ng-container>\r\n          </tr>\r\n        </ng-container>\r\n      </ng-container>\r\n    </tbody>\r\n    <tbody *ngIf=\"filterCount === 0\">\r\n      <tr class=\"ngx-table__body-empty\">\r\n        <ng-container *ngIf=\"noResultsTemplate\" [ngTemplateOutlet]=\"noResultsTemplate\">\r\n        </ng-container>\r\n        <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!noResultsTemplate\">\r\n          <div class=\"ngx-table__table-no-results\">No results</div>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n    <tbody *ngIf=\"config.isLoading\">\r\n      <tr class=\"ngx-table__body-loading\">\r\n        <ng-container *ngIf=\"loadingTemplate\" [ngTemplateOutlet]=\"loadingTemplate\"> </ng-container>\r\n        <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!loadingTemplate\">\r\n          <div [style.height.px]=\"loadingHeight\" class=\"ngx-table__table-loader-wrapper\">\r\n            <div class=\"ngx-table__table-loader\"></div>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n    <tfoot *ngIf=\"summaryTemplate\">\r\n      <tr>\r\n        <ng-container\r\n          [ngTemplateOutlet]=\"summaryTemplate\"\r\n          [ngTemplateOutletContext]=\"{ total: data.length, limit: limit, page: page }\"\r\n        >\r\n        </ng-container>\r\n      </tr>\r\n    </tfoot>\r\n  </table>\r\n  <pagination\r\n    [attr.id]=\"'pagination' + id\"\r\n    [id]=\"id\"\r\n    #paginationComponent\r\n    [config]=\"config\"\r\n    [pagination]=\"pagination\"\r\n    (updateRange)=\"onPagination($event)\"\r\n  >\r\n  </pagination>\r\n</div>\r\n" }]
        }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.ScrollDispatcher }, { type: i2.StyleService }], propDecorators: { configuration: [{
                type: Input
            }], data: [{
                type: Input
            }], pagination: [{
                type: Input
            }], groupRowsBy: [{
                type: Input
            }], id: [{
                type: Input
            }], toggleRowIndex: [{
                type: Input
            }], detailsTemplate: [{
                type: Input
            }], summaryTemplate: [{
                type: Input
            }], groupRowsHeaderTemplate: [{
                type: Input
            }], filtersTemplate: [{
                type: Input
            }], selectAllTemplate: [{
                type: Input
            }], noResultsTemplate: [{
                type: Input
            }], loadingTemplate: [{
                type: Input
            }], additionalActionsTemplate: [{
                type: Input
            }], rowContextMenu: [{
                type: Input
            }], columns: [{
                type: Input
            }], event: [{
                type: Output
            }], rowTemplate: [{
                type: ContentChild,
                args: [TemplateRef]
            }], paginationComponent: [{
                type: ViewChild,
                args: ['paginationComponent']
            }], contextMenu: [{
                type: ViewChild,
                args: ['contextMenu']
            }], table: [{
                type: ViewChild,
                args: ['table']
            }], viewPort: [{
                type: ViewChild,
                args: [CdkVirtualScrollViewport]
            }], onContextMenuClick: [{
                type: HostListener,
                args: ['document:click', ['$event.target']]
            }], isAllSortEnabled: [{
                type: Input
            }] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWFzeS10YWJsZS9zcmMvbGliL2NvbXBvbmVudHMvYmFzZS9iYXNlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LXRhYmxlL3NyYy9saWIvY29tcG9uZW50cy9iYXNlL2Jhc2UuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUE2QixlQUFlLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNwRixPQUFPLEVBRUwsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osWUFBWSxFQUNaLFlBQVksRUFDWixLQUFLLEVBSUwsTUFBTSxFQUdOLFdBQVcsRUFDWCxTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLEdBQUcsRUFBNEIsS0FBSyxFQUFjLE1BQU0sT0FBTyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRXJFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSx3QkFBd0IsRUFBb0IsTUFBTSx3QkFBd0IsQ0FBQztBQUNwRixPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7Ozs7Ozs7OztBQWdCakUsTUFBTSxPQUFPLGFBQWE7SUFxRGpCLGtCQUFrQixDQUFDLGFBQWtCO1FBQzFDLElBQUksSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ2hGLElBQUksQ0FBQyxzQkFBc0IsR0FBRztnQkFDNUIsR0FBRyxFQUFFLElBQUk7Z0JBQ1QsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsS0FBSyxFQUFFLElBQUk7YUFDWixDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFRCxZQUNtQixHQUFzQixFQUN0QixnQkFBa0MsRUFDbkMsWUFBMEI7UUFGekIsUUFBRyxHQUFILEdBQUcsQ0FBbUI7UUFDdEIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNuQyxpQkFBWSxHQUFaLFlBQVksQ0FBYztRQWpFcEMsZ0JBQVcsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO1FBSW5DLGdCQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDakIseUJBQW9CLEdBQUcsSUFBSSxPQUFPLEVBQVUsQ0FBQztRQUM3QyxlQUFVLEdBQWtCLElBQUksQ0FBQztRQUVqQyxZQUFPLEdBQVEsRUFBRSxDQUFDO1FBQ2xCLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFDbkIsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUNULFVBQUssR0FBRyxDQUFDLENBQUM7UUFDVixjQUFTLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN0QixZQUFPLEdBQWtCLElBQUksQ0FBQztRQUM5QiwyQkFBc0IsR0FBMkI7WUFDdEQsR0FBRyxFQUFFLElBQUk7WUFDVCxJQUFJLEVBQUUsSUFBSTtZQUNWLEtBQUssRUFBRSxJQUFJO1NBQ1osQ0FBQztRQUVLLFdBQU0sR0FBd0M7WUFDbkQsR0FBRyxFQUFFLEVBQUU7WUFDUCxLQUFLLEVBQUUsS0FBSztTQUNiLENBQUM7UUFDSyxpQ0FBNEIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ2pELHVCQUFrQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFPckMsT0FBRSxHQUFHLE9BQU8sQ0FBQztRQVlILFVBQUssR0FBRyxJQUFJLFlBQVksRUFBaUMsQ0FBQztRQXNmcEUscUJBQWdCLEdBQVksS0FBSyxDQUFDO1FBL2R6QyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUM5RSxVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUNkLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO2dCQUN6QixJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzNCLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbEIsT0FBTyxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1FBQ2hELENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7UUFDbkMsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsTUFBTSxHQUFHLG9CQUFvQixDQUFDLE1BQU0sQ0FBQztRQUM1QyxDQUFDO1FBQ0QsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztRQUM5QixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsT0FBTyxHQUFHLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMzRSxDQUFDO1FBQ0QsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7SUFDaEMsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELGVBQWU7UUFDYixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLDBCQUEwQjtZQUMxRCxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQywwQkFBMEI7WUFDeEMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUNSLElBQUksQ0FBQyxnQkFBZ0I7YUFDbEIsUUFBUSxFQUFFO2FBQ1YsSUFBSSxDQUNILFlBQVksQ0FBQyxhQUFhLENBQUMsRUFDM0IsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDZixPQUFPLENBQ0wsQ0FBQyxDQUFDLEtBQUs7Z0JBQ1AsSUFBSSxDQUFDLFFBQVE7Z0JBQ2IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLEdBQUcsS0FBSyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxDQUN2RSxDQUFDO1FBQ0osQ0FBQyxDQUFDLEVBQ0YsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FDNUI7YUFDQSxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsV0FBVyxDQUFDLE9BQXNCO1FBQ2hDLE1BQU0sRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDakUsSUFBSSxDQUFDLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO1FBQzdDLElBQUksYUFBYSxJQUFJLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxZQUFZLENBQUM7UUFDM0MsQ0FBQztRQUNELElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxJQUFJLFVBQVUsSUFBSSxVQUFVLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDMUMsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsVUFBVSxDQUFDLFlBQTBCLENBQUM7WUFDdkUsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7WUFDbkIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7WUFDbkIsSUFBSSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUM7UUFDckIsQ0FBQztRQUNELElBQUksV0FBVyxJQUFJLFdBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsT0FBTyxHQUFHLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMzRSxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDNUQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUM7WUFDN0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDOUIsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLENBQUMsTUFBZTtRQUNyQixJQUFJLE9BQU8sTUFBTSxDQUFDLFlBQVksS0FBSyxXQUFXLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDdkUsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUM7UUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDckQsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUMxRCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1lBQy9CLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2RCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDekIsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNCLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNuQyxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUc7WUFDWixHQUFHLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDakIsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7U0FDeEMsQ0FBQztRQUNGLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsT0FBTyxDQUFDLE1BQWtCLEVBQUUsR0FBUSxFQUFFLEdBQWtCLEVBQUUsUUFBYSxFQUFFLFFBQWdCO1FBQ3ZGLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQztRQUM5QixDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsSUFBSSxHQUFHLFFBQVEsRUFBRSxFQUFFLENBQUM7WUFDM0MsSUFBSSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUM7UUFDOUIsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLElBQUksR0FBRyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQzVDLElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDO1lBQzVCLElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDO1FBQzlCLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDM0IsTUFBTSxLQUFLLEdBQUc7Z0JBQ1osS0FBSyxFQUFFLE1BQU07Z0JBQ2IsR0FBRztnQkFDSCxHQUFHO2dCQUNILEtBQUssRUFBRSxRQUFRO2dCQUNmLEtBQUssRUFBRSxRQUFRO2FBQ2hCLENBQUM7WUFDRixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUM7SUFFRCxhQUFhLENBQ1gsTUFBa0IsRUFDbEIsR0FBUSxFQUNSLEdBQWtCLEVBQ2xCLFFBQWEsRUFDYixRQUFnQjtRQUVoQixNQUFNLEtBQUssR0FBRztZQUNaLEtBQUssRUFBRSxNQUFNO1lBQ2IsR0FBRztZQUNILEdBQUc7WUFDSCxLQUFLLEVBQUUsUUFBUTtZQUNmLEtBQUssRUFBRSxRQUFRO1NBQ2hCLENBQUM7UUFDRixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVELGdCQUFnQixDQUFDLE1BQVcsRUFBRSxHQUFRLEVBQUUsUUFBZ0I7UUFDdEQsTUFBTSxLQUFLLEdBQUc7WUFDWixLQUFLLEVBQUUsTUFBTTtZQUNiLEdBQUc7WUFDSCxLQUFLLEVBQUUsUUFBUTtTQUNoQixDQUFDO1FBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVELGFBQWEsQ0FBQyxNQUFXLEVBQUUsR0FBUSxFQUFFLFFBQWdCO1FBQ25ELE1BQU0sS0FBSyxHQUFHO1lBQ1osS0FBSyxFQUFFLE1BQU07WUFDYixHQUFHO1lBQ0gsS0FBSyxFQUFFLFFBQVE7U0FDaEIsQ0FBQztRQUNGLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELFFBQVEsQ0FBQyxNQUE2QztRQUNwRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVELGNBQWMsQ0FBQyxLQUFhO1FBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztRQUNoQyxDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRCxZQUFZLENBQUMsVUFBMkI7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQzVCLElBQUksQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQztRQUM5QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxVQUFVLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsY0FBYyxDQUFDLFFBQWdCO1FBQzdCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO1lBQ25DLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztZQUMxQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsV0FBVyxDQUFDLFFBQWdCO1FBQzFCLElBQUksSUFBSSxDQUFDLDRCQUE0QixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ3BELElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDckQsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsNEJBQTRCLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2hELElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGtCQUFrQixFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3JELENBQUM7SUFDSCxDQUFDO0lBRU8sc0JBQXNCO1FBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQzlCLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDNUQsTUFBTSxJQUFJLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDcEQsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQzVDLENBQUM7UUFDRCxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1QsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3hDLElBQUksQ0FBQyxPQUFPLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNO2dCQUNoQixLQUFLLEVBQUUsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRTthQUM5QixDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNYLElBQUksQ0FBQyxPQUFPLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLEdBQUcsQ0FBQyxhQUFhO2dCQUN2QixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7YUFDMUIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFFRCxjQUFjLENBQUMsUUFBZ0I7UUFDN0IsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLDRCQUE0QixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQsSUFBSSxhQUFhO1FBQ2YsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFxQixDQUFDO1FBQ25FLElBQUksS0FBSyxJQUFJLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDakQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN4RCxNQUFNLGNBQWMsR0FBRyxDQUFDLENBQUM7WUFDekIsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDO1lBQzFCLE9BQU8sQ0FDTCxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLGFBQWEsR0FBRyxhQUFhLENBQUM7Z0JBQ2pELENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEdBQUcsY0FBYyxDQUFDO2dCQUMvQyxlQUFlLENBQ2hCLENBQUM7UUFDSixDQUFDO1FBRUQsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsSUFBSSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLEtBQUssV0FBVyxDQUFDO0lBQzdGLENBQUM7SUFFRCxnQkFBZ0IsQ0FDZCxNQUFrQixFQUNsQixHQUFRLEVBQ1IsR0FBa0IsRUFDbEIsUUFBYSxFQUNiLFFBQWdCO1FBRWhCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ2pDLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sS0FBSyxHQUFHO1lBQ1osS0FBSyxFQUFFLE1BQU07WUFDYixHQUFHO1lBQ0gsR0FBRztZQUNILEtBQUssRUFBRSxRQUFRO1lBQ2YsS0FBSyxFQUFFLFFBQVE7U0FDaEIsQ0FBQztRQUNGLElBQUksQ0FBQyxzQkFBc0IsR0FBRztZQUM1QixHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxHQUFHLEVBQUUsSUFBSTtZQUM3QixJQUFJLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxHQUFHLEVBQUUsSUFBSTtZQUM5QixLQUFLO1NBQ04sQ0FBQztRQUVGLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFFTyxXQUFXLENBQUMsSUFBa0I7UUFDcEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEQsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDM0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNyQyxDQUFDO0lBQ0gsQ0FBQztJQUVELFdBQVcsQ0FBQyxLQUFtQjtRQUM3QixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUE0QjtRQUNqQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUVELG1HQUFtRztJQUNuRyxRQUFRLENBQUMsS0FBYztRQUNyQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELG9CQUFvQjtJQUNaLE9BQU8sQ0FBQyxLQUFjO1FBQzVCLFFBQVEsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ25CLEtBQUssR0FBRyxDQUFDLHFCQUFxQjtnQkFDNUIsSUFBSSxDQUFDLHNCQUFzQixHQUFHO29CQUM1QixHQUFHLEVBQUUsSUFBSTtvQkFDVCxJQUFJLEVBQUUsSUFBSTtvQkFDVixLQUFLLEVBQUUsSUFBSTtpQkFDWixDQUFDO2dCQUNGLE1BQU07WUFDUixLQUFLLEdBQUcsQ0FBQyxjQUFjO2dCQUNyQixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDOUIsTUFBTTtZQUNSLEtBQUssR0FBRyxDQUFDLGNBQWM7Z0JBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNqQyxNQUFNO1lBQ1IsS0FBSyxHQUFHLENBQUMsYUFBYTtnQkFDcEIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO29CQUM5QixLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO3dCQUM1QixNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLFVBQVUsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFxQixDQUFDO3dCQUNuRixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7NEJBQ2IsT0FBTyxDQUFDLEtBQUssQ0FDWCxXQUFXLEtBQUssQ0FBQyxHQUFHLHlEQUF5RCxDQUM5RSxDQUFDO3dCQUNKLENBQUM7NkJBQU0sQ0FBQzs0QkFDTixPQUFPLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7d0JBQzlCLENBQUM7b0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBQ0wsQ0FBQztnQkFDRCxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDeEIsTUFBTTtZQUNSLEtBQUssR0FBRyxDQUFDLGNBQWM7Z0JBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNqQyxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUN4QixNQUFNO1lBQ1IsS0FBSyxHQUFHLENBQUMsV0FBVztnQkFDbEIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUMvQixLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztvQkFDakUsTUFBTTtnQkFDUixDQUFDO2dCQUNELElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDM0MsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDeEIsTUFBTTtZQUNSLEtBQUssR0FBRyxDQUFDLFlBQVk7Z0JBQ25CLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDL0IsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQ2xFLE1BQU07Z0JBQ1IsQ0FBQztnQkFDRCxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzVDLE1BQU07WUFDUixLQUFLLEdBQUcsQ0FBQyxXQUFXO2dCQUNsQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQy9CLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUNqRSxNQUFNO2dCQUNSLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMzQyxNQUFNO1lBQ1IsS0FBSyxHQUFHLENBQUMsWUFBWTtnQkFDbkIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUMvQixLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztvQkFDbEUsTUFBTTtnQkFDUixDQUFDO2dCQUNELElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDNUMsTUFBTTtZQUNSLEtBQUssR0FBRyxDQUFDLGFBQWE7Z0JBQ3BCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztnQkFDOUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDeEIsTUFBTTtZQUNSLEtBQUssR0FBRyxDQUFDLHVCQUF1QjtnQkFDOUIsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUMsbUJBQW1CLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdEUsS0FBSyxHQUFHLENBQUMsd0JBQXdCO2dCQUMvQixPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNuRSxLQUFLLEdBQUcsQ0FBQyxxQkFBcUI7Z0JBQzVCLE9BQU8sSUFBSSxDQUFDLG1CQUFtQixDQUFDLG1CQUFtQixDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3BFLEtBQUssR0FBRyxDQUFDLHNCQUFzQjtnQkFDN0IsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUMsbUJBQW1CLENBQUMsVUFBVSxFQUFFO29CQUM5RCxDQUFDLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLG1CQUFtQixDQUFDLGFBQWEsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLO29CQUMzRSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUNqQixLQUFLLEdBQUcsQ0FBQyx3QkFBd0I7Z0JBQy9CLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNyRSxNQUFNO1lBQ1IsS0FBSyxHQUFHLENBQUMsa0JBQWtCO2dCQUN6QixJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7Z0JBQzlDLE1BQU07WUFDUixLQUFLLEdBQUcsQ0FBQywwQkFBMEI7Z0JBQ2pDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztnQkFDckQsTUFBTTtZQUNSLEtBQUssR0FBRyxDQUFDLHNCQUFzQjtnQkFDN0IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO2dCQUNqRCxNQUFNO1lBQ1IsS0FBSyxHQUFHLENBQUMseUJBQXlCO2dCQUNoQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3hELE1BQU07WUFDUixLQUFLLEdBQUcsQ0FBQyxNQUFNO2dCQUNiLE1BQU0sTUFBTSxHQUFZLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQzNGLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3JCLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3pCLE1BQU07WUFDUjtnQkFDRSxNQUFNO1FBQ1YsQ0FBQztJQUNILENBQUM7SUFFTyxjQUFjLENBQUMsTUFBZTtRQUNwQyxNQUFNLEdBQUcsR0FBVyxNQUFNLENBQUMsR0FBRyxDQUFDO1FBRS9CLFFBQVEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxLQUFLLEVBQUUsQ0FBQztZQUNSLEtBQUssU0FBUztnQkFDWixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsQ0FBQztnQkFDbEQsTUFBTTtZQUNSLEtBQUssS0FBSztnQkFDUixJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQ3pGLE1BQU07WUFDUixLQUFLLE1BQU07Z0JBQ1QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUMvQixNQUFNO1FBQ1YsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDckMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDaEMsQ0FBQztJQUVILENBQUM7SUFFTSxTQUFTLENBQUMsS0FBYSxFQUFFLEtBQVU7UUFDeEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNsQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDN0IsWUFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdkIsc0NBQXNDO1lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNoQyxDQUFDO0lBQ0gsQ0FBQztJQUVELFNBQVMsQ0FBQyxNQUFpQjtRQUN6QixNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDeEIsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxRQUFRLENBQUMsTUFBaUI7UUFDeEIsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsU0FBUyxDQUFDLE1BQWlCO1FBQ3pCLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN4QixNQUFNLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVELElBQUksQ0FBQyxNQUFpQjtRQUNwQixNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDeEIsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0MsSUFBSSxJQUFJLEVBQUUsSUFBSSxLQUFLLGtCQUFrQixFQUFFLENBQUM7WUFDdEMsc0NBQXNDO1lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUNoQyxPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUM7UUFDcEMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQzVCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQWdCLENBQUMsQ0FBQztZQUN4RCxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzFCLENBQUMsQ0FBQztRQUNGLFVBQVUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUIsQ0FBQzsrR0FqaUJVLGFBQWE7bUdBQWIsYUFBYSxxdEJBSmIsQ0FBQyxvQkFBb0IsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLENBQUMsbUVBa0RuRCxXQUFXLHFYQUlkLHdCQUF3QixxRUM3RnJDLDY1dEJBdWlCQTs7NEZENWZhLGFBQWE7a0JBTnpCLFNBQVM7K0JBQ0UsV0FBVyxhQUNWLENBQUMsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLG1CQUVoRCx1QkFBdUIsQ0FBQyxNQUFNO2dKQStCdEMsYUFBYTtzQkFBckIsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLEVBQUU7c0JBQVYsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyx1QkFBdUI7c0JBQS9CLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0cseUJBQXlCO3NCQUFqQyxLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNhLEtBQUs7c0JBQXZCLE1BQU07Z0JBQzJCLFdBQVc7c0JBQTVDLFlBQVk7dUJBQUMsV0FBVztnQkFDaUIsbUJBQW1CO3NCQUE1RCxTQUFTO3VCQUFDLHFCQUFxQjtnQkFDTixXQUFXO3NCQUFwQyxTQUFTO3VCQUFDLGFBQWE7Z0JBQ0osS0FBSztzQkFBeEIsU0FBUzt1QkFBQyxPQUFPO2dCQUNtQixRQUFRO3NCQUE1QyxTQUFTO3VCQUFDLHdCQUF3QjtnQkFHNUIsa0JBQWtCO3NCQUR4QixZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsZUFBZSxDQUFDO2dCQStleEMsZ0JBQWdCO3NCQUF4QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2RrRHJhZ0Ryb3AsIENka0RyYWdTdGFydCwgbW92ZUl0ZW1JbkFycmF5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XHJcbmltcG9ydCB7XHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBDb21wb25lbnQsXHJcbiAgQ29udGVudENoaWxkLFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBIb3N0TGlzdGVuZXIsXHJcbiAgSW5wdXQsXHJcbiAgT25DaGFuZ2VzLFxyXG4gIE9uRGVzdHJveSxcclxuICBPbkluaXQsXHJcbiAgT3V0cHV0LFxyXG4gIFNpbXBsZUNoYW5nZSxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDaGlsZCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCB7IEFQSSwgQXBpVHlwZSwgQ29sdW1ucywgQ29uZmlnLCBFdmVudCwgUGFnaW5hdGlvbiB9IGZyb20gJy4uLy4uJztcclxuaW1wb3J0IHsgRGVmYXVsdENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9jb25maWctc2VydmljZSc7XHJcbmltcG9ydCB7IFBhZ2luYXRpb25Db21wb25lbnQsIFBhZ2luYXRpb25SYW5nZSB9IGZyb20gJy4uL3BhZ2luYXRpb24vcGFnaW5hdGlvbi5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBHcm91cFJvd3NTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZ3JvdXAtcm93cy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgU3R5bGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvc3R5bGUuc2VydmljZSc7XHJcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0LCBTY3JvbGxEaXNwYXRjaGVyIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3Njcm9sbGluZyc7XHJcbmltcG9ydCB7IGZpbHRlciwgdGFrZVVudGlsLCB0aHJvdHRsZVRpbWUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG50eXBlIENvbHVtbktleVR5cGUgPSBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuO1xyXG5cclxuaW50ZXJmYWNlIFJvd0NvbnRleHRNZW51UG9zaXRpb24ge1xyXG4gIHRvcDogc3RyaW5nIHwgbnVsbDtcclxuICBsZWZ0OiBzdHJpbmcgfCBudWxsO1xyXG4gIHZhbHVlOiBhbnkgfCBudWxsO1xyXG59XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25neC10YWJsZScsXHJcbiAgcHJvdmlkZXJzOiBbRGVmYXVsdENvbmZpZ1NlcnZpY2UsIEdyb3VwUm93c1NlcnZpY2UsIFN0eWxlU2VydmljZV0sXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2Jhc2UuY29tcG9uZW50Lmh0bWwnLFxyXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgQmFzZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xyXG4gIHByaXZhdGUgdW5zdWJzY3JpYmUgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG4gIHB1YmxpYyBzZWxlY3RlZFJvdzogbnVtYmVyO1xyXG4gIHB1YmxpYyBzZWxlY3RlZENvbDogbnVtYmVyO1xyXG4gIHB1YmxpYyB0ZXJtOiBhbnk7XHJcbiAgcHVibGljIGZpbHRlckNvdW50ID0gLTE7XHJcbiAgcHVibGljIGZpbHRlcmVkQ291bnRTdWJqZWN0ID0gbmV3IFN1YmplY3Q8bnVtYmVyPigpO1xyXG4gIHB1YmxpYyB0YWJsZUNsYXNzOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICBwdWJsaWMgZ2xvYmFsU2VhcmNoVGVybTogc3RyaW5nO1xyXG4gIHB1YmxpYyBncm91cGVkOiBhbnkgPSBbXTtcclxuICBwdWJsaWMgaXNTZWxlY3RlZCA9IGZhbHNlO1xyXG4gIHB1YmxpYyBwYWdlID0gMTtcclxuICBwdWJsaWMgY291bnQgPSAwO1xyXG4gIHB1YmxpYyBzb3J0U3RhdGUgPSBuZXcgTWFwKCk7XHJcbiAgcHVibGljIHNvcnRLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gIHB1YmxpYyByb3dDb250ZXh0TWVudVBvc2l0aW9uOiBSb3dDb250ZXh0TWVudVBvc2l0aW9uID0ge1xyXG4gICAgdG9wOiBudWxsLFxyXG4gICAgbGVmdDogbnVsbCxcclxuICAgIHZhbHVlOiBudWxsLFxyXG4gIH07XHJcbiAgcHVibGljIGxpbWl0O1xyXG4gIHB1YmxpYyBzb3J0Qnk6IHsga2V5OiBzdHJpbmcgfSAmIHsgb3JkZXI6IHN0cmluZyB9ID0ge1xyXG4gICAga2V5OiAnJyxcclxuICAgIG9yZGVyOiAnYXNjJyxcclxuICB9O1xyXG4gIHB1YmxpYyBzZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkID0gbmV3IFNldDxudW1iZXI+KCk7XHJcbiAgcHVibGljIHNlbGVjdGVkQ2hlY2tib3hlcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xyXG4gIHB1YmxpYyBjb25maWc6IENvbmZpZztcclxuXHJcbiAgQElucHV0KCkgY29uZmlndXJhdGlvbjogQ29uZmlnO1xyXG4gIEBJbnB1dCgpIGRhdGE6IGFueVtdO1xyXG4gIEBJbnB1dCgpIHBhZ2luYXRpb246IFBhZ2luYXRpb247XHJcbiAgQElucHV0KCkgZ3JvdXBSb3dzQnk6IHN0cmluZztcclxuICBASW5wdXQoKSBpZCA9ICd0YWJsZSc7XHJcbiAgQElucHV0KCkgdG9nZ2xlUm93SW5kZXg7XHJcbiAgQElucHV0KCkgZGV0YWlsc1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBJbnB1dCgpIHN1bW1hcnlUZW1wbGF0ZTogVGVtcGxhdGVSZWY8eyB0b3RhbDogbnVtYmVyOyBsaW1pdDogbnVtYmVyOyBwYWdlOiBudW1iZXIgfT47XHJcbiAgQElucHV0KCkgZ3JvdXBSb3dzSGVhZGVyVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgQElucHV0KCkgZmlsdGVyc1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBJbnB1dCgpIHNlbGVjdEFsbFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBJbnB1dCgpIG5vUmVzdWx0c1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjx2b2lkPjtcclxuICBASW5wdXQoKSBsb2FkaW5nVGVtcGxhdGU6IFRlbXBsYXRlUmVmPHZvaWQ+O1xyXG4gIEBJbnB1dCgpIGFkZGl0aW9uYWxBY3Rpb25zVGVtcGxhdGU6IFRlbXBsYXRlUmVmPHZvaWQ+O1xyXG4gIEBJbnB1dCgpIHJvd0NvbnRleHRNZW51OiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBJbnB1dCgpIGNvbHVtbnM6IENvbHVtbnNbXTtcclxuICBAT3V0cHV0KCkgcmVhZG9ubHkgZXZlbnQgPSBuZXcgRXZlbnRFbWl0dGVyPHsgZXZlbnQ6IHN0cmluZzsgdmFsdWU6IGFueSB9PigpO1xyXG4gIEBDb250ZW50Q2hpbGQoVGVtcGxhdGVSZWYpIHB1YmxpYyByb3dUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcclxuICBAVmlld0NoaWxkKCdwYWdpbmF0aW9uQ29tcG9uZW50JykgcHJpdmF0ZSBwYWdpbmF0aW9uQ29tcG9uZW50OiBQYWdpbmF0aW9uQ29tcG9uZW50O1xyXG4gIEBWaWV3Q2hpbGQoJ2NvbnRleHRNZW51JykgY29udGV4dE1lbnU7XHJcbiAgQFZpZXdDaGlsZCgndGFibGUnKSB0YWJsZTtcclxuICBAVmlld0NoaWxkKENka1ZpcnR1YWxTY3JvbGxWaWV3cG9ydCkgdmlld1BvcnQ6IENka1ZpcnR1YWxTY3JvbGxWaWV3cG9ydDtcclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudC50YXJnZXQnXSlcclxuICBwdWJsaWMgb25Db250ZXh0TWVudUNsaWNrKHRhcmdldEVsZW1lbnQ6IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuY29udGV4dE1lbnUgJiYgIXRoaXMuY29udGV4dE1lbnUubmF0aXZlRWxlbWVudC5jb250YWlucyh0YXJnZXRFbGVtZW50KSkge1xyXG4gICAgICB0aGlzLnJvd0NvbnRleHRNZW51UG9zaXRpb24gPSB7XHJcbiAgICAgICAgdG9wOiBudWxsLFxyXG4gICAgICAgIGxlZnQ6IG51bGwsXHJcbiAgICAgICAgdmFsdWU6IG51bGwsXHJcbiAgICAgIH07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2Nyb2xsRGlzcGF0Y2hlcjogU2Nyb2xsRGlzcGF0Y2hlcixcclxuICAgIHB1YmxpYyByZWFkb25seSBzdHlsZVNlcnZpY2U6IFN0eWxlU2VydmljZVxyXG4gICkge1xyXG4gICAgdGhpcy5maWx0ZXJlZENvdW50U3ViamVjdC5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlKSkuc3Vic2NyaWJlKChjb3VudCkgPT4ge1xyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICB0aGlzLmZpbHRlckNvdW50ID0gY291bnQ7XHJcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY29sdW1ucykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdbY29sdW1uc10gcHJvcGVydHkgcmVxdWlyZWQhJyk7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uKSB7XHJcbiAgICAgIHRoaXMuY29uZmlnID0gdGhpcy5jb25maWd1cmF0aW9uO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5jb25maWcgPSBEZWZhdWx0Q29uZmlnU2VydmljZS5jb25maWc7XHJcbiAgICB9XHJcbiAgICB0aGlzLmxpbWl0ID0gdGhpcy5jb25maWcucm93cztcclxuICAgIGlmICh0aGlzLmdyb3VwUm93c0J5KSB7XHJcbiAgICAgIHRoaXMuZ3JvdXBlZCA9IEdyb3VwUm93c1NlcnZpY2UuZG9Hcm91cFJvd3ModGhpcy5kYXRhLCB0aGlzLmdyb3VwUm93c0J5KTtcclxuICAgIH1cclxuICAgIHRoaXMuZG9EZWNvZGVQZXJzaXN0ZWRTdGF0ZSgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLnVuc3Vic2NyaWJlLm5leHQoKTtcclxuICAgIHRoaXMudW5zdWJzY3JpYmUuY29tcGxldGUoKTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIGNvbnN0IHRocm90dGxlVmFsdWUgPSB0aGlzLmNvbmZpZy5pbmZpbml0ZVNjcm9sbFRocm90dGxlVGltZVxyXG4gICAgICA/IHRoaXMuY29uZmlnLmluZmluaXRlU2Nyb2xsVGhyb3R0bGVUaW1lXHJcbiAgICAgIDogMjAwO1xyXG4gICAgdGhpcy5zY3JvbGxEaXNwYXRjaGVyXHJcbiAgICAgIC5zY3JvbGxlZCgpXHJcbiAgICAgIC5waXBlKFxyXG4gICAgICAgIHRocm90dGxlVGltZSh0aHJvdHRsZVZhbHVlKSxcclxuICAgICAgICBmaWx0ZXIoKGV2ZW50KSA9PiB7XHJcbiAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAhIWV2ZW50ICYmXHJcbiAgICAgICAgICAgIHRoaXMudmlld1BvcnQgJiZcclxuICAgICAgICAgICAgdGhpcy52aWV3UG9ydC5nZXRSZW5kZXJlZFJhbmdlKCkuZW5kID09PSB0aGlzLnZpZXdQb3J0LmdldERhdGFMZW5ndGgoKVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9KSxcclxuICAgICAgICB0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSlcclxuICAgICAgKVxyXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbkluZmluaXRlU2Nyb2xsRW5kLCBudWxsKTtcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBjb25zdCB7IGNvbmZpZ3VyYXRpb24sIGRhdGEsIHBhZ2luYXRpb24sIGdyb3VwUm93c0J5IH0gPSBjaGFuZ2VzO1xyXG4gICAgdGhpcy50b2dnbGVSb3dJbmRleCA9IGNoYW5nZXMudG9nZ2xlUm93SW5kZXg7XHJcbiAgICBpZiAoY29uZmlndXJhdGlvbiAmJiBjb25maWd1cmF0aW9uLmN1cnJlbnRWYWx1ZSkge1xyXG4gICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZ3VyYXRpb24uY3VycmVudFZhbHVlO1xyXG4gICAgfVxyXG4gICAgaWYgKGRhdGEgJiYgZGF0YS5jdXJyZW50VmFsdWUpIHtcclxuICAgICAgdGhpcy5kb0FwcGx5RGF0YShkYXRhKTtcclxuICAgIH1cclxuICAgIGlmIChwYWdpbmF0aW9uICYmIHBhZ2luYXRpb24uY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIGNvbnN0IHsgY291bnQsIGxpbWl0LCBvZmZzZXQgfSA9IHBhZ2luYXRpb24uY3VycmVudFZhbHVlIGFzIFBhZ2luYXRpb247XHJcbiAgICAgIHRoaXMuY291bnQgPSBjb3VudDtcclxuICAgICAgdGhpcy5saW1pdCA9IGxpbWl0O1xyXG4gICAgICB0aGlzLnBhZ2UgPSBvZmZzZXQ7XHJcbiAgICB9XHJcbiAgICBpZiAoZ3JvdXBSb3dzQnkgJiYgZ3JvdXBSb3dzQnkuY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIHRoaXMuZ3JvdXBlZCA9IEdyb3VwUm93c1NlcnZpY2UuZG9Hcm91cFJvd3ModGhpcy5kYXRhLCB0aGlzLmdyb3VwUm93c0J5KTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLnRvZ2dsZVJvd0luZGV4ICYmIHRoaXMudG9nZ2xlUm93SW5kZXguY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIGNvbnN0IHJvdyA9IHRoaXMudG9nZ2xlUm93SW5kZXguY3VycmVudFZhbHVlO1xyXG4gICAgICB0aGlzLmNvbGxhcHNlUm93KHJvdy5pbmRleCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvcmRlckJ5KGNvbHVtbjogQ29sdW1ucyk6IHZvaWQge1xyXG4gICAgaWYgKHR5cGVvZiBjb2x1bW4ub3JkZXJFbmFibGVkICE9PSAndW5kZWZpbmVkJyAmJiAhY29sdW1uLm9yZGVyRW5hYmxlZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnNvcnRLZXkgPSBjb2x1bW4ua2V5O1xyXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5vcmRlckVuYWJsZWQgfHwgdGhpcy5zb3J0S2V5ID09PSAnJykge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5zZXRDb2x1bW5PcmRlcihjb2x1bW4pO1xyXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5vcmRlckV2ZW50T25seSAmJiAhY29sdW1uLm9yZGVyRXZlbnRPbmx5KSB7XHJcbiAgICAgIHRoaXMuc29ydEJ5LmtleSA9IHRoaXMuc29ydEtleTtcclxuICAgICAgdGhpcy5zb3J0Qnkub3JkZXIgPSB0aGlzLnNvcnRTdGF0ZS5nZXQodGhpcy5zb3J0S2V5KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc29ydEJ5LmtleSA9ICcnO1xyXG4gICAgICB0aGlzLnNvcnRCeS5vcmRlciA9ICcnO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5zZXJ2ZXJQYWdpbmF0aW9uKSB7XHJcbiAgICAgIHRoaXMuZGF0YSA9IFsuLi50aGlzLmRhdGFdO1xyXG4gICAgICB0aGlzLnNvcnRCeSA9IHsgLi4udGhpcy5zb3J0QnkgfTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB2YWx1ZSA9IHtcclxuICAgICAga2V5OiB0aGlzLnNvcnRLZXksXHJcbiAgICAgIG9yZGVyOiB0aGlzLnNvcnRTdGF0ZS5nZXQodGhpcy5zb3J0S2V5KSxcclxuICAgIH07XHJcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbk9yZGVyLCB2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICBvbkNsaWNrKCRldmVudDogTW91c2VFdmVudCwgcm93OiBhbnksIGtleTogQ29sdW1uS2V5VHlwZSwgY29sSW5kZXg6IGFueSwgcm93SW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuY29uZmlnLnNlbGVjdFJvdykge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkUm93ID0gcm93SW5kZXg7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5jb25maWcuc2VsZWN0Q29sICYmIGAke2NvbEluZGV4fWApIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZENvbCA9IGNvbEluZGV4O1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuY29uZmlnLnNlbGVjdENlbGwgJiYgYCR7Y29sSW5kZXh9YCkge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkUm93ID0gcm93SW5kZXg7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRDb2wgPSBjb2xJbmRleDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5jb25maWcuY2xpY2tFdmVudCkge1xyXG4gICAgICBjb25zdCB2YWx1ZSA9IHtcclxuICAgICAgICBldmVudDogJGV2ZW50LFxyXG4gICAgICAgIHJvdyxcclxuICAgICAgICBrZXksXHJcbiAgICAgICAgcm93SWQ6IHJvd0luZGV4LFxyXG4gICAgICAgIGNvbElkOiBjb2xJbmRleCxcclxuICAgICAgfTtcclxuICAgICAgdGhpcy5lbWl0RXZlbnQoRXZlbnQub25DbGljaywgdmFsdWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25Eb3VibGVDbGljayhcclxuICAgICRldmVudDogTW91c2VFdmVudCxcclxuICAgIHJvdzogYW55LFxyXG4gICAga2V5OiBDb2x1bW5LZXlUeXBlLFxyXG4gICAgY29sSW5kZXg6IGFueSxcclxuICAgIHJvd0luZGV4OiBudW1iZXJcclxuICApOiB2b2lkIHtcclxuICAgIGNvbnN0IHZhbHVlID0ge1xyXG4gICAgICBldmVudDogJGV2ZW50LFxyXG4gICAgICByb3csXHJcbiAgICAgIGtleSxcclxuICAgICAgcm93SWQ6IHJvd0luZGV4LFxyXG4gICAgICBjb2xJZDogY29sSW5kZXgsXHJcbiAgICB9O1xyXG4gICAgdGhpcy5lbWl0RXZlbnQoRXZlbnQub25Eb3VibGVDbGljaywgdmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgb25DaGVja2JveFNlbGVjdCgkZXZlbnQ6IGFueSwgcm93OiBhbnksIHJvd0luZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGNvbnN0IHZhbHVlID0ge1xyXG4gICAgICBldmVudDogJGV2ZW50LFxyXG4gICAgICByb3csXHJcbiAgICAgIHJvd0lkOiByb3dJbmRleCxcclxuICAgIH07XHJcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbkNoZWNrYm94U2VsZWN0LCB2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICBvblJhZGlvU2VsZWN0KCRldmVudDogYW55LCByb3c6IGFueSwgcm93SW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgY29uc3QgdmFsdWUgPSB7XHJcbiAgICAgIGV2ZW50OiAkZXZlbnQsXHJcbiAgICAgIHJvdyxcclxuICAgICAgcm93SWQ6IHJvd0luZGV4LFxyXG4gICAgfTtcclxuICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uUmFkaW9TZWxlY3QsIHZhbHVlKTtcclxuICB9XHJcblxyXG4gIG9uU2VsZWN0QWxsKCk6IHZvaWQge1xyXG4gICAgdGhpcy5pc1NlbGVjdGVkID0gIXRoaXMuaXNTZWxlY3RlZDtcclxuICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uU2VsZWN0QWxsLCB0aGlzLmlzU2VsZWN0ZWQpO1xyXG4gIH1cclxuXHJcbiAgb25TZWFyY2goJGV2ZW50OiBBcnJheTx7IGtleTogc3RyaW5nOyB2YWx1ZTogc3RyaW5nIH0+KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY29uZmlnLnNlcnZlclBhZ2luYXRpb24pIHtcclxuICAgICAgdGhpcy50ZXJtID0gJGV2ZW50O1xyXG4gICAgfVxyXG4gICAgdGhpcy5lbWl0RXZlbnQoRXZlbnQub25TZWFyY2gsICRldmVudCk7XHJcbiAgfVxyXG5cclxuICBvbkdsb2JhbFNlYXJjaCh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY29uZmlnLnNlcnZlclBhZ2luYXRpb24pIHtcclxuICAgICAgdGhpcy5nbG9iYWxTZWFyY2hUZXJtID0gdmFsdWU7XHJcbiAgICB9XHJcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbkdsb2JhbFNlYXJjaCwgdmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgb25QYWdpbmF0aW9uKHBhZ2luYXRpb246IFBhZ2luYXRpb25SYW5nZSk6IHZvaWQge1xyXG4gICAgdGhpcy5wYWdlID0gcGFnaW5hdGlvbi5wYWdlO1xyXG4gICAgdGhpcy5saW1pdCA9IHBhZ2luYXRpb24ubGltaXQ7XHJcbiAgICB0aGlzLmNvbmZpZy5yb3dzID0gcGFnaW5hdGlvbi5saW1pdDtcclxuICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uUGFnaW5hdGlvbiwgcGFnaW5hdGlvbik7XHJcbiAgfVxyXG5cclxuICB0b2dnbGVDaGVja2JveChyb3dJbmRleDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICB0aGlzLnNlbGVjdGVkQ2hlY2tib3hlcy5oYXMocm93SW5kZXgpXHJcbiAgICAgID8gdGhpcy5zZWxlY3RlZENoZWNrYm94ZXMuZGVsZXRlKHJvd0luZGV4KVxyXG4gICAgICA6IHRoaXMuc2VsZWN0ZWRDaGVja2JveGVzLmFkZChyb3dJbmRleCk7XHJcbiAgfVxyXG5cclxuICBjb2xsYXBzZVJvdyhyb3dJbmRleDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmhhcyhyb3dJbmRleCkpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmRlbGV0ZShyb3dJbmRleCk7XHJcbiAgICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uUm93Q29sbGFwc2VkSGlkZSwgcm93SW5kZXgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmFkZChyb3dJbmRleCk7XHJcbiAgICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uUm93Q29sbGFwc2VkU2hvdywgcm93SW5kZXgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkb0RlY29kZVBlcnNpc3RlZFN0YXRlKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5wZXJzaXN0U3RhdGUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgcGFnaW5hdGlvbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKEV2ZW50Lm9uUGFnaW5hdGlvbik7XHJcbiAgICBjb25zdCBzb3J0ID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oRXZlbnQub25PcmRlcik7XHJcbiAgICBjb25zdCBzZWFyY2ggPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShFdmVudC5vblNlYXJjaCk7XHJcbiAgICBpZiAocGFnaW5hdGlvbikge1xyXG4gICAgICB0aGlzLm9uUGFnaW5hdGlvbihKU09OLnBhcnNlKHBhZ2luYXRpb24pKTtcclxuICAgIH1cclxuICAgIGlmIChzb3J0KSB7XHJcbiAgICAgIGNvbnN0IHsga2V5LCBvcmRlciB9ID0gSlNPTi5wYXJzZShzb3J0KTtcclxuICAgICAgdGhpcy5iaW5kQXBpKHtcclxuICAgICAgICB0eXBlOiBBUEkuc29ydEJ5LFxyXG4gICAgICAgIHZhbHVlOiB7IGNvbHVtbjoga2V5LCBvcmRlciB9LFxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIGlmIChzZWFyY2gpIHtcclxuICAgICAgdGhpcy5iaW5kQXBpKHtcclxuICAgICAgICB0eXBlOiBBUEkuc2V0SW5wdXRWYWx1ZSxcclxuICAgICAgICB2YWx1ZTogSlNPTi5wYXJzZShzZWFyY2gpLFxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlzUm93Q29sbGFwc2VkKHJvd0luZGV4OiBudW1iZXIpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLmNvbmZpZy5jb2xsYXBzZUFsbFJvd3MpIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmhhcyhyb3dJbmRleCk7XHJcbiAgfVxyXG5cclxuICBnZXQgbG9hZGluZ0hlaWdodCgpOiBudW1iZXIge1xyXG4gICAgY29uc3QgdGFibGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmlkKSBhcyBIVE1MVGFibGVFbGVtZW50O1xyXG4gICAgaWYgKHRhYmxlICYmIHRhYmxlLnJvd3MgJiYgdGFibGUucm93cy5sZW5ndGggPiAzKSB7XHJcbiAgICAgIGNvbnN0IHNlYXJjaEVuYWJsZWQgPSB0aGlzLmNvbmZpZy5zZWFyY2hFbmFibGVkID8gMSA6IDA7XHJcbiAgICAgIGNvbnN0IGhlYWRlckVuYWJsZWQgPSB0aGlzLmNvbmZpZy5oZWFkZXJFbmFibGVkID8gMSA6IDA7XHJcbiAgICAgIGNvbnN0IGJvcmRlclRySGVpZ2h0ID0gMTtcclxuICAgICAgY29uc3QgYm9yZGVyRGl2SGVpZ2h0ID0gMjtcclxuICAgICAgcmV0dXJuIChcclxuICAgICAgICAodGFibGUucm93cy5sZW5ndGggLSBzZWFyY2hFbmFibGVkIC0gaGVhZGVyRW5hYmxlZCkgKlxyXG4gICAgICAgICAgKHRhYmxlLnJvd3NbM10ub2Zmc2V0SGVpZ2h0IC0gYm9yZGVyVHJIZWlnaHQpIC1cclxuICAgICAgICBib3JkZXJEaXZIZWlnaHRcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gMzA7XHJcbiAgfVxyXG5cclxuICBnZXQgYXJyb3dEZWZpbml0aW9uKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLnNob3dEZXRhaWxzQXJyb3cgfHwgdHlwZW9mIHRoaXMuY29uZmlnLnNob3dEZXRhaWxzQXJyb3cgPT09ICd1bmRlZmluZWQnO1xyXG4gIH1cclxuXHJcbiAgb25Sb3dDb250ZXh0TWVudShcclxuICAgICRldmVudDogTW91c2VFdmVudCxcclxuICAgIHJvdzogYW55LFxyXG4gICAga2V5OiBDb2x1bW5LZXlUeXBlLFxyXG4gICAgY29sSW5kZXg6IGFueSxcclxuICAgIHJvd0luZGV4OiBudW1iZXJcclxuICApOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5jb25maWcuc2hvd0NvbnRleHRNZW51KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgY29uc3QgdmFsdWUgPSB7XHJcbiAgICAgIGV2ZW50OiAkZXZlbnQsXHJcbiAgICAgIHJvdyxcclxuICAgICAga2V5LFxyXG4gICAgICByb3dJZDogcm93SW5kZXgsXHJcbiAgICAgIGNvbElkOiBjb2xJbmRleCxcclxuICAgIH07XHJcbiAgICB0aGlzLnJvd0NvbnRleHRNZW51UG9zaXRpb24gPSB7XHJcbiAgICAgIHRvcDogYCR7JGV2ZW50LnBhZ2VZIC0gMTB9cHhgLFxyXG4gICAgICBsZWZ0OiBgJHskZXZlbnQucGFnZVggLSAxMH1weGAsXHJcbiAgICAgIHZhbHVlLFxyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vblJvd0NvbnRleHRNZW51LCB2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGRvQXBwbHlEYXRhKGRhdGE6IFNpbXBsZUNoYW5nZSk6IHZvaWQge1xyXG4gICAgY29uc3Qgb3JkZXIgPSB0aGlzLmNvbHVtbnMuZmluZCgoYykgPT4gISFjLm9yZGVyQnkpO1xyXG4gICAgaWYgKG9yZGVyKSB7XHJcbiAgICAgIHRoaXMuc29ydFN0YXRlLnNldCh0aGlzLnNvcnRLZXksIG9yZGVyLm9yZGVyQnkgPT09ICdhc2MnID8gJ2Rlc2MnIDogJ2FzYycpO1xyXG4gICAgICB0aGlzLm9yZGVyQnkob3JkZXIpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5kYXRhID0gWy4uLmRhdGEuY3VycmVudFZhbHVlXTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uRHJhZ1N0YXJ0KGV2ZW50OiBDZGtEcmFnU3RhcnQpOiB2b2lkIHtcclxuICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uUmVvcmRlclN0YXJ0LCBldmVudCk7XHJcbiAgfVxyXG5cclxuICBvbkRyb3AoZXZlbnQ6IENka0RyYWdEcm9wPHN0cmluZ1tdPik6IHZvaWQge1xyXG4gICAgdGhpcy5lbWl0RXZlbnQoRXZlbnQub25Sb3dEcm9wLCBldmVudCk7XHJcbiAgICBtb3ZlSXRlbUluQXJyYXkodGhpcy5kYXRhLCBldmVudC5wcmV2aW91c0luZGV4LCBldmVudC5jdXJyZW50SW5kZXgpO1xyXG4gIH1cclxuXHJcbiAgLy8gRE8gTk9UIFJFTU9WRS4gSXQgaXMgY2FsbGVkIGZyb20gcGFyZW50IGNvbXBvbmVudC4gU2VlIHNyYy9hcHAvZGVtby9hcGktZG9jL2FwaS1kb2MuY29tcG9uZW50LnRzXHJcbiAgYXBpRXZlbnQoZXZlbnQ6IEFwaVR5cGUpOiB2b2lkIHwgbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLmJpbmRBcGkoZXZlbnQpO1xyXG4gIH1cclxuXHJcbiAgLyogZXNsaW50LWRpc2FibGUgKi9cclxuICBwcml2YXRlIGJpbmRBcGkoZXZlbnQ6IEFwaVR5cGUpOiB2b2lkIHwgbnVtYmVyIHtcclxuICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xyXG4gICAgICBjYXNlIEFQSS5yb3dDb250ZXh0TWVudUNsaWNrZWQ6XHJcbiAgICAgICAgdGhpcy5yb3dDb250ZXh0TWVudVBvc2l0aW9uID0ge1xyXG4gICAgICAgICAgdG9wOiBudWxsLFxyXG4gICAgICAgICAgbGVmdDogbnVsbCxcclxuICAgICAgICAgIHZhbHVlOiBudWxsLFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLnRvZ2dsZVJvd0luZGV4OlxyXG4gICAgICAgIHRoaXMuY29sbGFwc2VSb3coZXZlbnQudmFsdWUpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIEFQSS50b2dnbGVDaGVja2JveDpcclxuICAgICAgICB0aGlzLnRvZ2dsZUNoZWNrYm94KGV2ZW50LnZhbHVlKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBBUEkuc2V0SW5wdXRWYWx1ZTpcclxuICAgICAgICBpZiAodGhpcy5jb25maWcuc2VhcmNoRW5hYmxlZCkge1xyXG4gICAgICAgICAgZXZlbnQudmFsdWUuZm9yRWFjaCgoaW5wdXQpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGBzZWFyY2hfJHtpbnB1dC5rZXl9YCkgYXMgSFRNTElucHV0RWxlbWVudDtcclxuICAgICAgICAgICAgaWYgKCFlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcclxuICAgICAgICAgICAgICAgIGBDb2x1bW4gJyR7aW5wdXQua2V5fScgbm90IGF2YWlsYWJsZSBpbiB0aGUgRE9NLiBIYXZlIHlvdSBtaXNzcGVsbGVkIGEgbmFtZT9gXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBlbGVtZW50LnZhbHVlID0gaW5wdXQudmFsdWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm9uU2VhcmNoKGV2ZW50LnZhbHVlKTtcclxuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBBUEkub25HbG9iYWxTZWFyY2g6XHJcbiAgICAgICAgdGhpcy5vbkdsb2JhbFNlYXJjaChldmVudC52YWx1ZSk7XHJcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLnNldFJvd0NsYXNzOlxyXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGV2ZW50LnZhbHVlKSkge1xyXG4gICAgICAgICAgZXZlbnQudmFsdWUuZm9yRWFjaCgodmFsKSA9PiB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dDbGFzcyh2YWwpKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dDbGFzcyhldmVudC52YWx1ZSk7XHJcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLnNldENlbGxDbGFzczpcclxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShldmVudC52YWx1ZSkpIHtcclxuICAgICAgICAgIGV2ZW50LnZhbHVlLmZvckVhY2goKHZhbCkgPT4gdGhpcy5zdHlsZVNlcnZpY2Uuc2V0Q2VsbENsYXNzKHZhbCkpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuc3R5bGVTZXJ2aWNlLnNldENlbGxDbGFzcyhldmVudC52YWx1ZSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLnNldFJvd1N0eWxlOlxyXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGV2ZW50LnZhbHVlKSkge1xyXG4gICAgICAgICAgZXZlbnQudmFsdWUuZm9yRWFjaCgodmFsKSA9PiB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dTdHlsZSh2YWwpKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dTdHlsZShldmVudC52YWx1ZSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLnNldENlbGxTdHlsZTpcclxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShldmVudC52YWx1ZSkpIHtcclxuICAgICAgICAgIGV2ZW50LnZhbHVlLmZvckVhY2goKHZhbCkgPT4gdGhpcy5zdHlsZVNlcnZpY2Uuc2V0Q2VsbFN0eWxlKHZhbCkpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuc3R5bGVTZXJ2aWNlLnNldENlbGxTdHlsZShldmVudC52YWx1ZSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLnNldFRhYmxlQ2xhc3M6XHJcbiAgICAgICAgdGhpcy50YWJsZUNsYXNzID0gZXZlbnQudmFsdWU7XHJcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLmdldFBhZ2luYXRpb25Ub3RhbEl0ZW1zOlxyXG4gICAgICAgIHJldHVybiB0aGlzLnBhZ2luYXRpb25Db21wb25lbnQucGFnaW5hdGlvbkRpcmVjdGl2ZS5nZXRUb3RhbEl0ZW1zKCk7XHJcbiAgICAgIGNhc2UgQVBJLmdldFBhZ2luYXRpb25DdXJyZW50UGFnZTpcclxuICAgICAgICByZXR1cm4gdGhpcy5wYWdpbmF0aW9uQ29tcG9uZW50LnBhZ2luYXRpb25EaXJlY3RpdmUuZ2V0Q3VycmVudCgpO1xyXG4gICAgICBjYXNlIEFQSS5nZXRQYWdpbmF0aW9uTGFzdFBhZ2U6XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvbkNvbXBvbmVudC5wYWdpbmF0aW9uRGlyZWN0aXZlLmdldExhc3RQYWdlKCk7XHJcbiAgICAgIGNhc2UgQVBJLmdldE51bWJlck9mUm93c1BlclBhZ2U6XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvbkNvbXBvbmVudC5wYWdpbmF0aW9uRGlyZWN0aXZlLmlzTGFzdFBhZ2UoKVxyXG4gICAgICAgICAgPyB0aGlzLnBhZ2luYXRpb25Db21wb25lbnQucGFnaW5hdGlvbkRpcmVjdGl2ZS5nZXRUb3RhbEl0ZW1zKCkgJSB0aGlzLmxpbWl0XHJcbiAgICAgICAgICA6IHRoaXMubGltaXQ7XHJcbiAgICAgIGNhc2UgQVBJLnNldFBhZ2luYXRpb25DdXJyZW50UGFnZTpcclxuICAgICAgICB0aGlzLnBhZ2luYXRpb25Db21wb25lbnQucGFnaW5hdGlvbkRpcmVjdGl2ZS5zZXRDdXJyZW50KGV2ZW50LnZhbHVlKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBBUEkuc2V0UGFnaW5hdGlvblJhbmdlOlxyXG4gICAgICAgIHRoaXMucGFnaW5hdGlvbkNvbXBvbmVudC5yYW5nZXMgPSBldmVudC52YWx1ZTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBBUEkuc2V0UGFnaW5hdGlvblByZXZpb3VzTGFiZWw6XHJcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uQ29tcG9uZW50LnByZXZpb3VzTGFiZWwgPSBldmVudC52YWx1ZTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBBUEkuc2V0UGFnaW5hdGlvbk5leHRMYWJlbDpcclxuICAgICAgICB0aGlzLnBhZ2luYXRpb25Db21wb25lbnQubmV4dExhYmVsID0gZXZlbnQudmFsdWU7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgQVBJLnNldFBhZ2luYXRpb25EaXNwbGF5TGltaXQ6XHJcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uQ29tcG9uZW50LmNoYW5nZUxpbWl0KGV2ZW50LnZhbHVlLCB0cnVlKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBBUEkuc29ydEJ5OlxyXG4gICAgICAgIGNvbnN0IGNvbHVtbjogQ29sdW1ucyA9IHsgdGl0bGU6ICcnLCBrZXk6IGV2ZW50LnZhbHVlLmNvbHVtbiwgb3JkZXJCeTogZXZlbnQudmFsdWUub3JkZXIgfTtcclxuICAgICAgICB0aGlzLm9yZGVyQnkoY29sdW1uKTtcclxuICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldENvbHVtbk9yZGVyKGNvbHVtbjogQ29sdW1ucyk6IHZvaWQge1xyXG4gICAgY29uc3Qga2V5OiBzdHJpbmcgPSBjb2x1bW4ua2V5O1xyXG5cclxuICAgIHN3aXRjaCAodGhpcy5zb3J0U3RhdGUuZ2V0KGtleSkpIHtcclxuICAgICAgY2FzZSAnJzpcclxuICAgICAgY2FzZSB1bmRlZmluZWQ6XHJcbiAgICAgICAgdGhpcy5zb3J0U3RhdGUuc2V0KGtleSwgY29sdW1uLm9yZGVyQnkgfHwgJ2Rlc2MnKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSAnYXNjJzpcclxuICAgICAgICB0aGlzLmNvbmZpZy50aHJlZVdheVNvcnQgPyB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCAnJykgOiB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCAnZGVzYycpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlICdkZXNjJzpcclxuICAgICAgICB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCAnYXNjJyk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5zb3J0U3RhdGUuc2l6ZSA+IDEpIHtcclxuICAgICAgY29uc3QgdGVtcCA9IHRoaXMuc29ydFN0YXRlLmdldChrZXkpO1xyXG4gICAgICB0aGlzLnNvcnRTdGF0ZS5jbGVhcigpO1xyXG4gICAgICB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCB0ZW1wKTtcclxuICAgIH1cclxuICAgIFxyXG4gIH1cclxuXHJcbiAgcHVibGljIGVtaXRFdmVudChldmVudDogc3RyaW5nLCB2YWx1ZTogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLmV2ZW50LmVtaXQoeyBldmVudCwgdmFsdWUgfSk7XHJcbiAgICBpZiAodGhpcy5jb25maWcucGVyc2lzdFN0YXRlKSB7XHJcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGV2ZW50LCBKU09OLnN0cmluZ2lmeSh2YWx1ZSkpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuY29uZmlnLmxvZ2dlcikge1xyXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxyXG4gICAgICBjb25zb2xlLmxvZyh7IGV2ZW50LCB2YWx1ZSB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGRyYWdFbnRlcigkZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xyXG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgfVxyXG5cclxuICBkcmFnT3ZlcigkZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xyXG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgfVxyXG5cclxuICBkcmFnTGVhdmUoJGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcclxuICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gIH1cclxuXHJcbiAgZHJvcCgkZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xyXG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICBjb25zdCBmaWxlID0gJGV2ZW50LmRhdGFUcmFuc2Zlcj8uZmlsZXM/LlswXTtcclxuICAgIGlmIChmaWxlPy50eXBlICE9PSAnYXBwbGljYXRpb24vanNvbicpIHtcclxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcclxuICAgICAgY29uc29sZS5sb2coJ0ZpbGUgbm90IGFsbG93ZWQnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgZmlsZVJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICBmaWxlUmVhZGVyLm9ubG9hZCA9IChldmVudCkgPT4ge1xyXG4gICAgICB0aGlzLmRhdGEgPSBKU09OLnBhcnNlKGV2ZW50Py50YXJnZXQ/LnJlc3VsdCBhcyBzdHJpbmcpO1xyXG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICAgIH07XHJcbiAgICBmaWxlUmVhZGVyLnJlYWRBc1RleHQoZmlsZSk7XHJcbiAgfVxyXG5cclxuICBASW5wdXQoKSBpc0FsbFNvcnRFbmFibGVkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG59XHJcbiIsIjxkaXZcclxuICBjbGFzcz1cIm5neC1jb250YWluZXJcIlxyXG4gIFtjbGFzcy5uZ3gtY29udGFpbmVyLS1kYXJrXT1cImNvbmZpZy50YWJsZUxheW91dC50aGVtZSA9PT0gJ2RhcmsnXCJcclxuICAoZHJhZ2VudGVyKT1cImRyYWdFbnRlcigkZXZlbnQpXCJcclxuICAoZHJhZ292ZXIpPVwiZHJhZ092ZXIoJGV2ZW50KVwiXHJcbiAgKGRyYWdsZWF2ZSk9XCJkcmFnTGVhdmUoJGV2ZW50KVwiXHJcbiAgKGRyb3ApPVwiZHJvcCgkZXZlbnQpXCJcclxuPlxyXG4gIDx0YWJsZVxyXG4gICAgW2lkXT1cImlkXCJcclxuICAgICN0YWJsZVxyXG4gICAgW25nQ2xhc3NdPVwidGFibGVDbGFzcyA9PT0gbnVsbCB8fCB0YWJsZUNsYXNzID09PSAnJyA/ICduZ3gtdGFibGUnIDogdGFibGVDbGFzc1wiXHJcbiAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS0tdGlueV09XCJjb25maWcudGFibGVMYXlvdXQuc3R5bGUgPT09ICd0aW55J1wiXHJcbiAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS0tbm9ybWFsXT1cImNvbmZpZy50YWJsZUxheW91dC5zdHlsZSA9PT0gJ25vcm1hbCdcIlxyXG4gICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtLWJpZ109XCJjb25maWcudGFibGVMYXlvdXQuc3R5bGUgPT09ICdiaWcnXCJcclxuICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLS1ib3JkZXJsZXNzXT1cImNvbmZpZy50YWJsZUxheW91dC5ib3JkZXJsZXNzXCJcclxuICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLS1kYXJrXT1cImNvbmZpZy50YWJsZUxheW91dC50aGVtZSA9PT0gJ2RhcmsnXCJcclxuICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLS1ob3ZlcmFibGVdPVwiY29uZmlnLnRhYmxlTGF5b3V0LmhvdmVyXCJcclxuICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLS1zdHJpcGVkXT1cImNvbmZpZy50YWJsZUxheW91dC5zdHJpcGVkXCJcclxuICAgIFtjbGFzcy5uZ3gtdGFibGVfX2hvcml6b250YWwtc2Nyb2xsXT1cImNvbmZpZy5ob3Jpem9udGFsU2Nyb2xsICYmICFjb25maWcuaXNMb2FkaW5nXCJcclxuICA+XHJcbiAgICA8dGhlYWRcclxuICAgICAgW2NsYXNzLm5neC1pbmZpbml0ZS1zY3JvbGwtdmlld3BvcnQtdGhlYWRdPVwiY29uZmlnLmluZmluaXRlU2Nyb2xsXCJcclxuICAgICAgdGFibGUtdGhlYWRcclxuICAgICAgW2NvbmZpZ109XCJjb25maWdcIlxyXG4gICAgICBbc29ydEtleV09XCJzb3J0S2V5XCJcclxuICAgICAgW3NvcnRTdGF0ZV09XCJzb3J0U3RhdGVcIlxyXG4gICAgICBbc2VsZWN0QWxsVGVtcGxhdGVdPVwic2VsZWN0QWxsVGVtcGxhdGVcIlxyXG4gICAgICBbZmlsdGVyc1RlbXBsYXRlXT1cImZpbHRlcnNUZW1wbGF0ZVwiXHJcbiAgICAgIFthZGRpdGlvbmFsQWN0aW9uc1RlbXBsYXRlXT1cImFkZGl0aW9uYWxBY3Rpb25zVGVtcGxhdGVcIlxyXG4gICAgICBbY29sdW1uc109XCJjb2x1bW5zXCJcclxuICAgICAgKHNlbGVjdEFsbCk9XCJvblNlbGVjdEFsbCgpXCJcclxuICAgICAgKGZpbHRlcik9XCJvblNlYXJjaCgkZXZlbnQpXCJcclxuICAgICAgKG9yZGVyKT1cIm9yZGVyQnkoJGV2ZW50KVwiXHJcbiAgICAgIChldmVudCk9XCJlbWl0RXZlbnQoJGV2ZW50LmV2ZW50LCAkZXZlbnQudmFsdWUpXCJcclxuICAgID48L3RoZWFkPlxyXG4gICAgPHRib2R5ICpuZ0lmPVwiZGF0YSAmJiAhY29uZmlnLmlzTG9hZGluZyAmJiAhY29uZmlnLnJvd1Jlb3JkZXJcIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInJvd1RlbXBsYXRlXCI+XHJcbiAgICAgICAgPHVsXHJcbiAgICAgICAgICBjbGFzcz1cIm5neC10YWJsZV9fdGFibGUtcm93LWNvbnRleHQtbWVudVwiXHJcbiAgICAgICAgICBbbmdTdHlsZV09XCJ7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxyXG4gICAgICAgICAgICB0b3A6IHJvd0NvbnRleHRNZW51UG9zaXRpb24udG9wLFxyXG4gICAgICAgICAgICBsZWZ0OiByb3dDb250ZXh0TWVudVBvc2l0aW9uLmxlZnRcclxuICAgICAgICAgIH1cIlxyXG4gICAgICAgICAgKm5nSWY9XCJyb3dDb250ZXh0TWVudVBvc2l0aW9uLnRvcFwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJyb3dDb250ZXh0TWVudVwiXHJcbiAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogcm93Q29udGV4dE1lbnVQb3NpdGlvbi52YWx1ZSB9XCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvdWw+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFjb25maWcuaW5maW5pdGVTY3JvbGxcIj5cclxuICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgKm5nRm9yPVwiXHJcbiAgICAgICAgICAgICAgbGV0IHJvdyBvZiBkYXRhXHJcbiAgICAgICAgICAgICAgICB8IHNvcnQ6IHNvcnRCeVxyXG4gICAgICAgICAgICAgICAgfCBzZWFyY2g6IHRlcm06ZmlsdGVyZWRDb3VudFN1YmplY3RcclxuICAgICAgICAgICAgICAgIHwgZ2xvYmFsOiBnbG9iYWxTZWFyY2hUZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0XHJcbiAgICAgICAgICAgICAgICB8IHBhZ2luYXRlOiB7IGl0ZW1zUGVyUGFnZTogbGltaXQsIGN1cnJlbnRQYWdlOiBwYWdlLCB0b3RhbEl0ZW1zOiBjb3VudCwgaWQ6IGlkIH1cclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPHRyXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQ2xpY2soJGV2ZW50LCByb3csICcnLCBudWxsLCBkYXRhLmluZGV4T2Yocm93KSlcIlxyXG4gICAgICAgICAgICAgICNjb250ZXh0TWVudVxyXG4gICAgICAgICAgICAgIChjb250ZXh0bWVudSk9XCJvblJvd0NvbnRleHRNZW51KCRldmVudCwgcm93LCAnJywgbnVsbCwgZGF0YS5pbmRleE9mKHJvdykpXCJcclxuICAgICAgICAgICAgICAoZGJsY2xpY2spPVwib25Eb3VibGVDbGljaygkZXZlbnQsIHJvdywgJycsIG51bGwsIGRhdGEuaW5kZXhPZihyb3cpKVwiXHJcbiAgICAgICAgICAgICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtcm93LS1zZWxlY3RlZF09XCJcclxuICAgICAgICAgICAgICAgIGRhdGEuaW5kZXhPZihyb3cpID09PSBzZWxlY3RlZFJvdyAmJiAhY29uZmlnLnNlbGVjdENlbGxcclxuICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwicm93VGVtcGxhdGVcIlxyXG4gICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiByb3csIGluZGV4OiBkYXRhLmluZGV4T2Yocm93KSB9XCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgPHRkICpuZ0lmPVwiY29uZmlnLmRldGFpbHNUZW1wbGF0ZVwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW5cclxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJuZ3gtaWNvblwiXHJcbiAgICAgICAgICAgICAgICAgICpuZ0lmPVwiYXJyb3dEZWZpbml0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgaXNSb3dDb2xsYXBzZWQoZGF0YS5pbmRleE9mKHJvdykpXHJcbiAgICAgICAgICAgICAgICAgICAgICA/ICduZ3gtaWNvbi1hcnJvdy1kb3duJ1xyXG4gICAgICAgICAgICAgICAgICAgICAgOiAnbmd4LWljb24tYXJyb3ctcmlnaHQnXHJcbiAgICAgICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb2xsYXBzZVJvdyhkYXRhLmluZGV4T2Yocm93KSlcIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDx0clxyXG4gICAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgICAoY29uZmlnLmRldGFpbHNUZW1wbGF0ZSAmJiBzZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmhhcyhkYXRhLmluZGV4T2Yocm93KSkpIHx8XHJcbiAgICAgICAgICAgICAgICBjb25maWcuY29sbGFwc2VBbGxSb3dzXHJcbiAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMubGVuZ3RoICsgMVwiPlxyXG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJkZXRhaWxzVGVtcGxhdGVcIlxyXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHJvdywgaW5kZXg6IGRhdGEuaW5kZXhPZihyb3cpIH1cIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDxjZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnRcclxuICAgICAgICAgIGl0ZW1TaXplPVwiNTBcIlxyXG4gICAgICAgICAgKm5nSWY9XCJjb25maWcuaW5maW5pdGVTY3JvbGxcIlxyXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtaW5maW5pdGUtc2Nyb2xsLXZpZXdwb3J0XCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAgICpjZGtWaXJ0dWFsRm9yPVwiXHJcbiAgICAgICAgICAgICAgbGV0IHJvdyBvZiBkYXRhXHJcbiAgICAgICAgICAgICAgICB8IHNvcnQ6IHNvcnRCeVxyXG4gICAgICAgICAgICAgICAgfCBzZWFyY2g6IHRlcm06ZmlsdGVyZWRDb3VudFN1YmplY3RcclxuICAgICAgICAgICAgICAgIHwgZ2xvYmFsOiBnbG9iYWxTZWFyY2hUZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0O1xyXG4gICAgICAgICAgICAgIGxldCByb3dJbmRleCA9IGluZGV4XHJcbiAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDx0clxyXG4gICAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgcm93LCAnJywgbnVsbCwgcm93SW5kZXgpXCJcclxuICAgICAgICAgICAgICAjY29udGV4dE1lbnVcclxuICAgICAgICAgICAgICAoY29udGV4dG1lbnUpPVwib25Sb3dDb250ZXh0TWVudSgkZXZlbnQsIHJvdywgJycsIG51bGwsIHJvd0luZGV4KVwiXHJcbiAgICAgICAgICAgICAgKGRibGNsaWNrKT1cIm9uRG91YmxlQ2xpY2soJGV2ZW50LCByb3csICcnLCBudWxsLCByb3dJbmRleClcIlxyXG4gICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLXJvdy0tc2VsZWN0ZWRdPVwiXHJcbiAgICAgICAgICAgICAgICByb3dJbmRleCA9PT0gc2VsZWN0ZWRSb3cgJiYgIWNvbmZpZy5zZWxlY3RDZWxsXHJcbiAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInJvd1RlbXBsYXRlXCJcclxuICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogcm93LCBpbmRleDogcm93SW5kZXggfVwiXHJcbiAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5kZXRhaWxzVGVtcGxhdGVcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwibmd4LWljb25cIlxyXG4gICAgICAgICAgICAgICAgICAqbmdJZj1cImFycm93RGVmaW5pdGlvblwiXHJcbiAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cIlxyXG4gICAgICAgICAgICAgICAgICAgIGlzUm93Q29sbGFwc2VkKHJvd0luZGV4KSA/ICduZ3gtaWNvbi1hcnJvdy1kb3duJyA6ICduZ3gtaWNvbi1hcnJvdy1yaWdodCdcclxuICAgICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbGxhcHNlUm93KHJvd0luZGV4KVwiXHJcbiAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgPHRyXHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJcclxuICAgICAgICAgICAgICAgIChjb25maWcuZGV0YWlsc1RlbXBsYXRlICYmIHNlbGVjdGVkRGV0YWlsc1RlbXBsYXRlUm93SWQuaGFzKHJvd0luZGV4KSkgfHxcclxuICAgICAgICAgICAgICAgIGNvbmZpZy5jb2xsYXBzZUFsbFJvd3NcclxuICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPHRkIFthdHRyLmNvbHNwYW5dPVwiY29sdW1ucy5sZW5ndGggKyAxXCI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImRldGFpbHNUZW1wbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogcm93LCBpbmRleDogcm93SW5kZXggfVwiXHJcbiAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XHJcbiAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIXJvd1RlbXBsYXRlICYmICFjb25maWcuZ3JvdXBSb3dzXCI+XHJcbiAgICAgICAgPHVsXHJcbiAgICAgICAgICBjbGFzcz1cIm5neC10YWJsZV9fdGFibGUtcm93LWNvbnRleHQtbWVudVwiXHJcbiAgICAgICAgICBbbmdTdHlsZV09XCJ7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxyXG4gICAgICAgICAgICB0b3A6IHJvd0NvbnRleHRNZW51UG9zaXRpb24udG9wLFxyXG4gICAgICAgICAgICBsZWZ0OiByb3dDb250ZXh0TWVudVBvc2l0aW9uLmxlZnRcclxuICAgICAgICAgIH1cIlxyXG4gICAgICAgICAgKm5nSWY9XCJyb3dDb250ZXh0TWVudVBvc2l0aW9uLnRvcFwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJyb3dDb250ZXh0TWVudVwiXHJcbiAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogcm93Q29udGV4dE1lbnVQb3NpdGlvbi52YWx1ZSB9XCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvdWw+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFjb25maWcuaW5maW5pdGVTY3JvbGxcIj5cclxuICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgKm5nRm9yPVwiXHJcbiAgICAgICAgICAgICAgbGV0IHJvdyBvZiBkYXRhXHJcbiAgICAgICAgICAgICAgICB8IHNvcnQ6IHNvcnRCeVxyXG4gICAgICAgICAgICAgICAgfCBzZWFyY2g6IHRlcm06ZmlsdGVyZWRDb3VudFN1YmplY3RcclxuICAgICAgICAgICAgICAgIHwgZ2xvYmFsOiBnbG9iYWxTZWFyY2hUZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0XHJcbiAgICAgICAgICAgICAgICB8IHBhZ2luYXRlOiB7IGl0ZW1zUGVyUGFnZTogbGltaXQsIGN1cnJlbnRQYWdlOiBwYWdlLCB0b3RhbEl0ZW1zOiBjb3VudCwgaWQ6IGlkIH1cclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPHRyXHJcbiAgICAgICAgICAgICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtcm93LS1zZWxlY3RlZF09XCJcclxuICAgICAgICAgICAgICAgIGRhdGEuaW5kZXhPZihyb3cpID09PSBzZWxlY3RlZFJvdyAmJiAhY29uZmlnLnNlbGVjdENlbGxcclxuICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPHRkICpuZ0lmPVwiY29uZmlnLmNoZWNrYm94ZXNcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cIm5neC1mb3JtLWNoZWNrYm94XCI+XHJcbiAgICAgICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXHJcbiAgICAgICAgICAgICAgICAgICAgaWQ9XCJjaGVja2JveC17eyBkYXRhLmluZGV4T2Yocm93KSB9fVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwiaXNTZWxlY3RlZCB8fCBzZWxlY3RlZENoZWNrYm94ZXMuaGFzKGRhdGEuaW5kZXhPZihyb3cpKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkNoZWNrYm94U2VsZWN0KCRldmVudCwgcm93LCBkYXRhLmluZGV4T2Yocm93KSlcIlxyXG4gICAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgICAgICA8ZW0gY2xhc3M9XCJuZ3gtZm9ybS1pY29uXCI+PC9lbT5cclxuICAgICAgICAgICAgICAgIDwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcucmFkaW9cIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbD5cclxuICAgICAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cInJhZGlvXCJcclxuICAgICAgICAgICAgICAgICAgICBpZD1cInJhZGlvLXt7IGRhdGEuaW5kZXhPZihyb3cpIH19XCJcclxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicmFkaW9cIlxyXG4gICAgICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwib25SYWRpb1NlbGVjdCgkZXZlbnQsIHJvdywgZGF0YS5pbmRleE9mKHJvdykpXCJcclxuICAgICAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgICAgIDwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29sdW1uczsgbGV0IGNvbEluZGV4ID0gaW5kZXhcIj5cclxuICAgICAgICAgICAgICAgIDx0ZFxyXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25DbGljaygkZXZlbnQsIHJvdywgY29sdW1uLmtleSwgY29sSW5kZXgsIGRhdGEuaW5kZXhPZihyb3cpKVwiXHJcbiAgICAgICAgICAgICAgICAgICNjb250ZXh0TWVudVxyXG4gICAgICAgICAgICAgICAgICAoY29udGV4dG1lbnUpPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgb25Sb3dDb250ZXh0TWVudSgkZXZlbnQsIHJvdywgY29sdW1uLmtleSwgY29sSW5kZXgsIGRhdGEuaW5kZXhPZihyb3cpKVxyXG4gICAgICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICAgICAgICAoZGJsY2xpY2spPVwib25Eb3VibGVDbGljaygkZXZlbnQsIHJvdywgY29sdW1uLmtleSwgY29sSW5kZXgsIGRhdGEuaW5kZXhPZihyb3cpKVwiXHJcbiAgICAgICAgICAgICAgICAgIFtjbGFzcy5waW5uZWQtbGVmdF09XCJjb2x1bW4ucGlubmVkXCJcclxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiY29sdW1uLmNzc0NsYXNzID8gY29sdW1uLmNzc0NsYXNzLm5hbWUgOiAnJ1wiXHJcbiAgICAgICAgICAgICAgICAgIFtzdHlsZS5sZWZ0XT1cInN0eWxlU2VydmljZS5waW5uZWRXaWR0aChjb2x1bW4ucGlubmVkLCBjb2xJbmRleClcIlxyXG4gICAgICAgICAgICAgICAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS1jb2wtLXNlbGVjdGVkXT1cIlxyXG4gICAgICAgICAgICAgICAgICAgIGNvbEluZGV4ID09PSBzZWxlY3RlZENvbCAmJiAhY29uZmlnLnNlbGVjdENlbGxcclxuICAgICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAgICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtY2VsbC0tc2VsZWN0ZWRdPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgY29sSW5kZXggPT09IHNlbGVjdGVkQ29sICYmXHJcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5pbmRleE9mKHJvdykgPT09IHNlbGVjdGVkUm93ICYmXHJcbiAgICAgICAgICAgICAgICAgICAgIWNvbmZpZy5zZWxlY3RDb2wgJiZcclxuICAgICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdFJvd1xyXG4gICAgICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWNvbHVtbi5jZWxsVGVtcGxhdGVcIj57eyByb3cgfCByZW5kZXI6IGNvbHVtbi5rZXkgfX08L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiY29sdW1uLmNlbGxUZW1wbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29sdW1uLmNlbGxUZW1wbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntcclxuICAgICAgICAgICAgICAgICAgICAgICRpbXBsaWNpdDogcm93LFxyXG4gICAgICAgICAgICAgICAgICAgICAgcm93SW5kZXg6IGRhdGEuaW5kZXhPZihyb3cpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW5cclxuICAgICAgICAgICAgICAgICAgICB9XCJcclxuICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgPHRkICpuZ0lmPVwiY29uZmlnLmFkZGl0aW9uYWxBY3Rpb25zIHx8IGNvbmZpZy5kZXRhaWxzVGVtcGxhdGVcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwibmd4LWljb25cIlxyXG4gICAgICAgICAgICAgICAgICAqbmdJZj1cImFycm93RGVmaW5pdGlvblwiXHJcbiAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cIlxyXG4gICAgICAgICAgICAgICAgICAgIGlzUm93Q29sbGFwc2VkKGRhdGEuaW5kZXhPZihyb3cpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgPyAnbmd4LWljb24tYXJyb3ctZG93bidcclxuICAgICAgICAgICAgICAgICAgICAgIDogJ25neC1pY29uLWFycm93LXJpZ2h0J1xyXG4gICAgICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwiY29sbGFwc2VSb3coZGF0YS5pbmRleE9mKHJvdykpXCJcclxuICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgICA8dHJcclxuICAgICAgICAgICAgICAqbmdJZj1cIlxyXG4gICAgICAgICAgICAgICAgKGNvbmZpZy5kZXRhaWxzVGVtcGxhdGUgJiYgc2VsZWN0ZWREZXRhaWxzVGVtcGxhdGVSb3dJZC5oYXMoZGF0YS5pbmRleE9mKHJvdykpKSB8fFxyXG4gICAgICAgICAgICAgICAgY29uZmlnLmNvbGxhcHNlQWxsUm93c1xyXG4gICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcuY2hlY2tib3hlcyB8fCBjb25maWcucmFkaW9cIj48L3RkPlxyXG4gICAgICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMubGVuZ3RoICsgMVwiPlxyXG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJkZXRhaWxzVGVtcGxhdGVcIlxyXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHJvdywgaW5kZXg6IGRhdGEuaW5kZXhPZihyb3cpIH1cIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwhLS0gaW5maW5pdGUgc2Nyb2xsIC0tPlxyXG4gICAgICAgIDxjZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnRcclxuICAgICAgICAgIGl0ZW1TaXplPVwiNTBcIlxyXG4gICAgICAgICAgKm5nSWY9XCJjb25maWcuaW5maW5pdGVTY3JvbGxcIlxyXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtaW5maW5pdGUtc2Nyb2xsLXZpZXdwb3J0XCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAgICpjZGtWaXJ0dWFsRm9yPVwiXHJcbiAgICAgICAgICAgICAgbGV0IHJvdyBvZiBkYXRhXHJcbiAgICAgICAgICAgICAgICB8IHNvcnQ6IHNvcnRCeVxyXG4gICAgICAgICAgICAgICAgfCBzZWFyY2g6IHRlcm06ZmlsdGVyZWRDb3VudFN1YmplY3RcclxuICAgICAgICAgICAgICAgIHwgZ2xvYmFsOiBnbG9iYWxTZWFyY2hUZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0O1xyXG4gICAgICAgICAgICAgIGxldCByb3dJbmRleCA9IGluZGV4XHJcbiAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDx0clxyXG4gICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLXJvdy0tc2VsZWN0ZWRdPVwiXHJcbiAgICAgICAgICAgICAgICByb3dJbmRleCA9PT0gc2VsZWN0ZWRSb3cgJiYgIWNvbmZpZy5zZWxlY3RDZWxsXHJcbiAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5jaGVja2JveGVzXCIgd2lkdGg9XCIzJVwiPlxyXG4gICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZvcm0tY2hlY2tib3hcIj5cclxuICAgICAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcclxuICAgICAgICAgICAgICAgICAgICBpZD1cImNoZWNrYm94LWluZmluaXRlLXNjcm9sbC17eyByb3dJbmRleCB9fVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwiaXNTZWxlY3RlZCB8fCBzZWxlY3RlZENoZWNrYm94ZXMuaGFzKHJvd0luZGV4KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkNoZWNrYm94U2VsZWN0KCRldmVudCwgcm93LCByb3dJbmRleClcIlxyXG4gICAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgICAgICA8ZW0gY2xhc3M9XCJuZ3gtZm9ybS1pY29uXCI+PC9lbT5cclxuICAgICAgICAgICAgICAgIDwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcucmFkaW9cIiB3aWR0aD1cIjMlXCI+XHJcbiAgICAgICAgICAgICAgICA8bGFiZWw+XHJcbiAgICAgICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJyYWRpb1wiXHJcbiAgICAgICAgICAgICAgICAgICAgaWQ9XCJyYWRpby1pbmZpbml0ZS1zY3JvbGwte3sgcm93SW5kZXggfX1cIlxyXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJyYWRpb1wiXHJcbiAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvblJhZGlvU2VsZWN0KCRldmVudCwgcm93LCByb3dJbmRleClcIlxyXG4gICAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgICAgPC9sYWJlbD5cclxuICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGNvbHVtbiBvZiBjb2x1bW5zOyBsZXQgY29sSW5kZXggPSBpbmRleFwiPlxyXG4gICAgICAgICAgICAgICAgPHRkXHJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgcm93SW5kZXgpXCJcclxuICAgICAgICAgICAgICAgICAgI2NvbnRleHRNZW51XHJcbiAgICAgICAgICAgICAgICAgIChjb250ZXh0bWVudSk9XCJvblJvd0NvbnRleHRNZW51KCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgcm93SW5kZXgpXCJcclxuICAgICAgICAgICAgICAgICAgKGRibGNsaWNrKT1cIm9uRG91YmxlQ2xpY2soJGV2ZW50LCByb3csIGNvbHVtbi5rZXksIGNvbEluZGV4LCByb3dJbmRleClcIlxyXG4gICAgICAgICAgICAgICAgICBbY2xhc3MucGlubmVkLWxlZnRdPVwiY29sdW1uLnBpbm5lZFwiXHJcbiAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cImNvbHVtbi5jc3NDbGFzcyA/IGNvbHVtbi5jc3NDbGFzcy5uYW1lIDogJydcIlxyXG4gICAgICAgICAgICAgICAgICBbc3R5bGUubGVmdF09XCJzdHlsZVNlcnZpY2UucGlubmVkV2lkdGgoY29sdW1uLnBpbm5lZCwgY29sSW5kZXgpXCJcclxuICAgICAgICAgICAgICAgICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtY29sLS1zZWxlY3RlZF09XCJcclxuICAgICAgICAgICAgICAgICAgICBjb2xJbmRleCA9PT0gc2VsZWN0ZWRDb2wgJiYgIWNvbmZpZy5zZWxlY3RDZWxsXHJcbiAgICAgICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLWNlbGwtLXNlbGVjdGVkXT1cIlxyXG4gICAgICAgICAgICAgICAgICAgIGNvbEluZGV4ID09PSBzZWxlY3RlZENvbCAmJlxyXG4gICAgICAgICAgICAgICAgICAgIHJvd0luZGV4ID09PSBzZWxlY3RlZFJvdyAmJlxyXG4gICAgICAgICAgICAgICAgICAgICFjb25maWcuc2VsZWN0Q29sICYmXHJcbiAgICAgICAgICAgICAgICAgICAgIWNvbmZpZy5zZWxlY3RSb3dcclxuICAgICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIiFjb2x1bW4uY2VsbFRlbXBsYXRlXCI+e3sgcm93IHwgcmVuZGVyOiBjb2x1bW4ua2V5IH19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImNvbHVtbi5jZWxsVGVtcGxhdGVcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNvbHVtbi5jZWxsVGVtcGxhdGVcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAkaW1wbGljaXQ6IHJvdyxcclxuICAgICAgICAgICAgICAgICAgICAgIHJvd0luZGV4OiByb3dJbmRleCxcclxuICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbjogY29sdW1uXHJcbiAgICAgICAgICAgICAgICAgICAgfVwiXHJcbiAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5hZGRpdGlvbmFsQWN0aW9ucyB8fCBjb25maWcuZGV0YWlsc1RlbXBsYXRlXCI+XHJcbiAgICAgICAgICAgICAgICA8c3BhblxyXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cIm5neC1pY29uXCJcclxuICAgICAgICAgICAgICAgICAgKm5nSWY9XCJhcnJvd0RlZmluaXRpb25cIlxyXG4gICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJcclxuICAgICAgICAgICAgICAgICAgICBpc1Jvd0NvbGxhcHNlZChyb3dJbmRleCkgPyAnbmd4LWljb24tYXJyb3ctZG93bicgOiAnbmd4LWljb24tYXJyb3ctcmlnaHQnXHJcbiAgICAgICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb2xsYXBzZVJvdyhyb3dJbmRleClcIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDx0clxyXG4gICAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgICAoY29uZmlnLmRldGFpbHNUZW1wbGF0ZSAmJiBzZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmhhcyhyb3dJbmRleCkpIHx8XHJcbiAgICAgICAgICAgICAgICBjb25maWcuY29sbGFwc2VBbGxSb3dzXHJcbiAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5jaGVja2JveGVzIHx8IGNvbmZpZy5yYWRpb1wiPjwvdGQ+XHJcbiAgICAgICAgICAgICAgPHRkIFthdHRyLmNvbHNwYW5dPVwiY29sdW1ucy5sZW5ndGggKyAxXCI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImRldGFpbHNUZW1wbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogcm93LCBpbmRleDogcm93SW5kZXggfVwiXHJcbiAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XHJcbiAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIXJvd1RlbXBsYXRlICYmIGNvbmZpZy5ncm91cFJvd3NcIj5cclxuICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAqbmdGb3I9XCJcclxuICAgICAgICAgICAgbGV0IGdyb3VwIG9mIGdyb3VwZWRcclxuICAgICAgICAgICAgICB8IHNvcnQ6IHNvcnRCeTpjb25maWdcclxuICAgICAgICAgICAgICB8IHNlYXJjaDogdGVybTpmaWx0ZXJlZENvdW50U3ViamVjdDpjb25maWdcclxuICAgICAgICAgICAgICB8IGdsb2JhbDogZ2xvYmFsU2VhcmNoVGVybTpmaWx0ZXJlZENvdW50U3ViamVjdFxyXG4gICAgICAgICAgICAgIHwgcGFnaW5hdGU6IHsgaXRlbXNQZXJQYWdlOiBsaW1pdCwgY3VycmVudFBhZ2U6IHBhZ2UsIHRvdGFsSXRlbXM6IGNvdW50LCBpZDogaWQgfTtcclxuICAgICAgICAgICAgbGV0IHJvd0luZGV4ID0gaW5kZXhcclxuICAgICAgICAgIFwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWdyb3VwUm93c0hlYWRlclRlbXBsYXRlXCI+XHJcbiAgICAgICAgICAgICAgPHRkIFthdHRyLmNvbHNwYW5dPVwiY29sdW1ucy5sZW5ndGhcIj5cclxuICAgICAgICAgICAgICAgIDxkaXY+e3sgZ3JvdXBbMF1bZ3JvdXBSb3dzQnldIH19ICh7eyBncm91cC5sZW5ndGggfX0pPC9kaXY+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAqbmdJZj1cImdyb3VwUm93c0hlYWRlclRlbXBsYXRlXCJcclxuICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJncm91cFJvd3NIZWFkZXJUZW1wbGF0ZVwiXHJcbiAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntcclxuICAgICAgICAgICAgICAgIHRvdGFsOiBncm91cC5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgICBrZXk6IGdyb3VwUm93c0J5LFxyXG4gICAgICAgICAgICAgICAgdmFsdWU6IGdyb3VwWzBdID8gZ3JvdXBbMF1bZ3JvdXBSb3dzQnldIDogJycsXHJcbiAgICAgICAgICAgICAgICBncm91cDogZ3JvdXAsXHJcbiAgICAgICAgICAgICAgICBpbmRleDogcm93SW5kZXhcclxuICAgICAgICAgICAgICB9XCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgICBjbGFzcz1cIm5neC1pY29uXCJcclxuICAgICAgICAgICAgICAgICpuZ0lmPVwiYXJyb3dEZWZpbml0aW9uXCJcclxuICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cIlxyXG4gICAgICAgICAgICAgICAgICBpc1Jvd0NvbGxhcHNlZChyb3dJbmRleCkgPyAnbmd4LWljb24tYXJyb3ctZG93bicgOiAnbmd4LWljb24tYXJyb3ctcmlnaHQnXHJcbiAgICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbGxhcHNlUm93KHJvd0luZGV4KVwiXHJcbiAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwic2VsZWN0ZWREZXRhaWxzVGVtcGxhdGVSb3dJZC5oYXMocm93SW5kZXgpXCI+XHJcbiAgICAgICAgICAgIDx0ciAqbmdGb3I9XCJsZXQgcm93IG9mIGdyb3VwXCI+XHJcbiAgICAgICAgICAgICAgPHRkICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29sdW1uc1wiPlxyXG4gICAgICAgICAgICAgICAge3sgcm93IHwgcmVuZGVyOiBjb2x1bW4ua2V5IH19XHJcbiAgICAgICAgICAgICAgICA8IS0tIFRPRE8gYWxsb3cgdXNlcnMgdG8gYWRkIGdyb3VwUm93c1RlbXBsYXRlUmVmIC0tPlxyXG4gICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgPHRkPjwvdGQ+XHJcbiAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICA8L3Rib2R5PlxyXG4gICAgPHRib2R5XHJcbiAgICAgICpuZ0lmPVwiZGF0YSAmJiAhY29uZmlnLmlzTG9hZGluZyAmJiBjb25maWcucm93UmVvcmRlclwiXHJcbiAgICAgIGNsYXNzPVwibmd4LWRyYWdnYWJsZS1yb3ctYXJlYVwiXHJcbiAgICAgIGNka0Ryb3BMaXN0XHJcbiAgICAgIChjZGtEcm9wTGlzdERyb3BwZWQpPVwib25Ecm9wKCRldmVudClcIlxyXG4gICAgPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIXJvd1RlbXBsYXRlICYmICFjb25maWcuZ3JvdXBSb3dzXCI+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgKm5nRm9yPVwiXHJcbiAgICAgICAgICAgIGxldCByb3cgb2YgZGF0YVxyXG4gICAgICAgICAgICAgIHwgc29ydDogc29ydEJ5XHJcbiAgICAgICAgICAgICAgfCBzZWFyY2g6IHRlcm06ZmlsdGVyZWRDb3VudFN1YmplY3RcclxuICAgICAgICAgICAgICB8IGdsb2JhbDogZ2xvYmFsU2VhcmNoVGVybTpmaWx0ZXJlZENvdW50U3ViamVjdFxyXG4gICAgICAgICAgICAgIHwgcGFnaW5hdGU6IHsgaXRlbXNQZXJQYWdlOiBsaW1pdCwgY3VycmVudFBhZ2U6IHBhZ2UsIHRvdGFsSXRlbXM6IGNvdW50LCBpZDogaWQgfVxyXG4gICAgICAgICAgXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8dHJcclxuICAgICAgICAgICAgY2xhc3M9XCJuZ3gtZHJhZ2dhYmxlLXJvd1wiXHJcbiAgICAgICAgICAgIGNka0RyYWdcclxuICAgICAgICAgICAgKGNka0RyYWdTdGFydGVkKT1cIm9uRHJhZ1N0YXJ0KCRldmVudClcIlxyXG4gICAgICAgICAgICBbY2RrRHJhZ1N0YXJ0RGVsYXldPVwiY29uZmlnLnJlb3JkZXJEZWxheSB8fCAwXCJcclxuICAgICAgICAgICAgY2RrRHJhZ0xvY2tBeGlzPVwieVwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5jaGVja2JveGVzXCI+XHJcbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZvcm0tY2hlY2tib3hcIj5cclxuICAgICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxyXG4gICAgICAgICAgICAgICAgICBpZD1cImNoZWNrYm94LWRyYWdnYWJsZS17eyBkYXRhLmluZGV4T2Yocm93KSB9fVwiXHJcbiAgICAgICAgICAgICAgICAgIFtjaGVja2VkXT1cImlzU2VsZWN0ZWQgfHwgc2VsZWN0ZWRDaGVja2JveGVzLmhhcyhkYXRhLmluZGV4T2Yocm93KSlcIlxyXG4gICAgICAgICAgICAgICAgICAoY2hhbmdlKT1cIm9uQ2hlY2tib3hTZWxlY3QoJGV2ZW50LCByb3csIGRhdGEuaW5kZXhPZihyb3cpKVwiXHJcbiAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgICAgPGVtIGNsYXNzPVwibmd4LWZvcm0taWNvblwiPjwvZW0+XHJcbiAgICAgICAgICAgICAgPC9sYWJlbD5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPHRkICpuZ0lmPVwiY29uZmlnLnJhZGlvXCI+XHJcbiAgICAgICAgICAgICAgPGxhYmVsPlxyXG4gICAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJyYWRpb1wiXHJcbiAgICAgICAgICAgICAgICAgIGlkPVwicmFkaW8tZHJhZ2dhYmxlLXt7IGRhdGEuaW5kZXhPZihyb3cpIH19XCJcclxuICAgICAgICAgICAgICAgICAgbmFtZT1cInJhZGlvXCJcclxuICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvblJhZGlvU2VsZWN0KCRldmVudCwgcm93LCBkYXRhLmluZGV4T2Yocm93KSlcIlxyXG4gICAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgICA8L2xhYmVsPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29sdW1uczsgbGV0IGNvbEluZGV4ID0gaW5kZXhcIj5cclxuICAgICAgICAgICAgICA8dGRcclxuICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgZGF0YS5pbmRleE9mKHJvdykpXCJcclxuICAgICAgICAgICAgICAgIChkYmxjbGljayk9XCJvbkRvdWJsZUNsaWNrKCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgZGF0YS5pbmRleE9mKHJvdykpXCJcclxuICAgICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLWNvbC0tc2VsZWN0ZWRdPVwiXHJcbiAgICAgICAgICAgICAgICAgIGNvbEluZGV4ID09PSBzZWxlY3RlZENvbCAmJiAhY29uZmlnLnNlbGVjdENlbGxcclxuICAgICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS1jZWxsLS1zZWxlY3RlZF09XCJcclxuICAgICAgICAgICAgICAgICAgY29sSW5kZXggPT09IHNlbGVjdGVkQ29sICYmXHJcbiAgICAgICAgICAgICAgICAgIGRhdGEuaW5kZXhPZihyb3cpID09PSBzZWxlY3RlZFJvdyAmJlxyXG4gICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdENvbCAmJlxyXG4gICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdFJvd1xyXG4gICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWNvbHVtbi5jZWxsVGVtcGxhdGVcIj57eyByb3cgfCByZW5kZXI6IGNvbHVtbi5rZXkgfX08L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAgICAgKm5nSWY9XCJjb2x1bW4uY2VsbFRlbXBsYXRlXCJcclxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29sdW1uLmNlbGxUZW1wbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7XHJcbiAgICAgICAgICAgICAgICAgICAgJGltcGxpY2l0OiByb3csXHJcbiAgICAgICAgICAgICAgICAgICAgcm93SW5kZXg6IGRhdGEuaW5kZXhPZihyb3cpLFxyXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbjogY29sdW1uXHJcbiAgICAgICAgICAgICAgICAgIH1cIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgIDwvdGJvZHk+XHJcbiAgICA8dGJvZHkgKm5nSWY9XCJmaWx0ZXJDb3VudCA9PT0gMFwiPlxyXG4gICAgICA8dHIgY2xhc3M9XCJuZ3gtdGFibGVfX2JvZHktZW1wdHlcIj5cclxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwibm9SZXN1bHRzVGVtcGxhdGVcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJub1Jlc3VsdHNUZW1wbGF0ZVwiPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMgJiYgY29sdW1ucy5sZW5ndGggKyAxXCIgKm5nSWY9XCIhbm9SZXN1bHRzVGVtcGxhdGVcIj5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtdGFibGVfX3RhYmxlLW5vLXJlc3VsdHNcIj5ObyByZXN1bHRzPC9kaXY+XHJcbiAgICAgICAgPC90ZD5cclxuICAgICAgPC90cj5cclxuICAgIDwvdGJvZHk+XHJcbiAgICA8dGJvZHkgKm5nSWY9XCJjb25maWcuaXNMb2FkaW5nXCI+XHJcbiAgICAgIDx0ciBjbGFzcz1cIm5neC10YWJsZV9fYm9keS1sb2FkaW5nXCI+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImxvYWRpbmdUZW1wbGF0ZVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImxvYWRpbmdUZW1wbGF0ZVwiPiA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICA8dGQgW2F0dHIuY29sc3Bhbl09XCJjb2x1bW5zICYmIGNvbHVtbnMubGVuZ3RoICsgMVwiICpuZ0lmPVwiIWxvYWRpbmdUZW1wbGF0ZVwiPlxyXG4gICAgICAgICAgPGRpdiBbc3R5bGUuaGVpZ2h0LnB4XT1cImxvYWRpbmdIZWlnaHRcIiBjbGFzcz1cIm5neC10YWJsZV9fdGFibGUtbG9hZGVyLXdyYXBwZXJcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5neC10YWJsZV9fdGFibGUtbG9hZGVyXCI+PC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L3RkPlxyXG4gICAgICA8L3RyPlxyXG4gICAgPC90Ym9keT5cclxuICAgIDx0Zm9vdCAqbmdJZj1cInN1bW1hcnlUZW1wbGF0ZVwiPlxyXG4gICAgICA8dHI+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwic3VtbWFyeVRlbXBsYXRlXCJcclxuICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHRvdGFsOiBkYXRhLmxlbmd0aCwgbGltaXQ6IGxpbWl0LCBwYWdlOiBwYWdlIH1cIlxyXG4gICAgICAgID5cclxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgPC90cj5cclxuICAgIDwvdGZvb3Q+XHJcbiAgPC90YWJsZT5cclxuICA8cGFnaW5hdGlvblxyXG4gICAgW2F0dHIuaWRdPVwiJ3BhZ2luYXRpb24nICsgaWRcIlxyXG4gICAgW2lkXT1cImlkXCJcclxuICAgICNwYWdpbmF0aW9uQ29tcG9uZW50XHJcbiAgICBbY29uZmlnXT1cImNvbmZpZ1wiXHJcbiAgICBbcGFnaW5hdGlvbl09XCJwYWdpbmF0aW9uXCJcclxuICAgICh1cGRhdGVSYW5nZSk9XCJvblBhZ2luYXRpb24oJGV2ZW50KVwiXHJcbiAgPlxyXG4gIDwvcGFnaW5hdGlvbj5cclxuPC9kaXY+XHJcbiJdfQ==