ngx-pluto
Version:
693 lines • 55.9 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ViewEncapsulation, Input, ContentChild, ContentChildren, QueryList, Output, EventEmitter } from "@angular/core";
import { NpColumnDirective } from "./column.directive";
import { NpEmptyDirective } from "./empty.directive";
import { NpHeaderDirective } from './header.directive';
import { Utils } from "../common/utils";
/**
* 可分页表格组件 - 支持分页、自定义列名、自定义列内容等。对于多语言,支持通过·\@Input·属性自定义。
*
* <example-url>https://stackblitz.com/edit/np-table-sample?embed=1&file=src/app/app.component.html</example-url>
*/
export class NpTable {
constructor() {
/**
* 数据总条数
*/
this.total = 0;
/**
* 每页显示条数,默认20条
*/
this.pageSize = 20; // Default is 20 rows per page
// Default is 20 rows per page
/**
* 是否在表头第一列展示多选框,默认不展示
*/
this.showCheckbox = false; // Indicate whether show checkbox or not, default is not
// Indicate whether show checkbox or not, default is not
/**
* 是否显示分页组件,默认显示
*/
this.showPager = true;
/**
* 是否服务器端排序,默认false,即客户端排序
*/
this.serverSideSort = false;
/**
* 首页按钮文字
*/
this.firstBtnText = '首页';
/**
* 上一页按钮文字
*/
this.preBtnText = '上一页';
/**
* 下一页按钮文字
*/
this.nextBtnText = '下一页';
/**
* 尾页按钮文字
*/
this.lastBtnText = '尾页';
/**
* 共
*/
this.totalText = '共';
/**
* 条,每页显示条数
*/
this.itemsPerPageText = '条,每页显示条数';
/**
* 没有数据按钮文字
*/
this.noDataLabel = "没有数据";
/**
* 当前页码
*/
this.pageNumber = 1;
/**
* 页码改变事件,即翻页事件 (双向绑定)
*/
this.pageNumberChange = new EventEmitter();
/**
* 页码改变事件,即翻页事件
*/
this.onPageChanged = new EventEmitter();
/**
* 每页显示条数改变事件
*/
this.onPageSizeChanged = new EventEmitter();
/**
* Will be deprecated, use onRows instead
*/
this.onRowsChecked = new EventEmitter();
/**
* Will be deprecated, use onRows instead
*
* 为了向后兼容,故没有修改onRowsChecked逻辑,增加此output事件
*
* 当前行uncheck时触发此事件
*/
this.onRowsUnchecked = new EventEmitter();
/**
* 当选择服务器端排序(即serverSideSort = true)时,根据当前点击列内容及排序,传给backend api返回服务器端排序数据赋值给datasource及total字段即可
*/
this.onServerSideSorted = new EventEmitter();
/**
* 当前处理的行row/rows,选中/非选中状态
*
* 如点击全选按钮,则处理的是当前页的所有行rows
*/
this.onRows = new EventEmitter();
this.projectedTemplates = [];
this.headerTemplates = [];
this.internalColumns = [];
/**
* 此字段后续会废弃 will be deprecated
*/
this.selectedRows = [];
this.datasourceSortedByDefault = [];
}
/**
* @return {?}
*/
ngOnInit() {
this.datasourceSortedByDefault = [...this.datasource];
if (this.showCheckbox) {
this.internalColumns = [];
this.internalColumns.push({
headerName: 'chk',
headerDisplayName: '',
width: '50px',
isCheckbox: true
});
}
this.mergeToInternalColumns();
this.onServerSideSorted.subscribe((/**
* @param {?} res
* @return {?}
*/
res => {
console.log('onServerSideSorted: ', res);
this.buildServerSideSort(res.col);
}));
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
if (changes.columns && changes.columns.currentValue &&
changes.columns.currentValue.length > 0 &&
changes.columns.previousValue &&
changes.columns.previousValue.length > 0 &&
changes.columns.currentValue !== changes.columns.previousValue) {
this.mergeToInternalColumns();
this.projectTemplate();
}
if (changes.datasource && changes.datasource.currentValue && changes.datasource.currentValue.length > 0) {
this.datasourceSortedByDefault = [...changes.datasource.currentValue];
this.initUniqueIdForDatasource();
}
if (changes.total && changes.total.currentValue) {
this.total = +changes.total.currentValue;
}
if (changes.pageNumber && !changes.pageNumber.firstChange && changes.pageNumber.currentValue) {
/** @type {?} */
const pageNumber = +changes.pageNumber.currentValue;
this.pageNumber = pageNumber;
this.pageNumberChange.emit(pageNumber);
this.selectAll(false);
}
}
/**
* @return {?}
*/
ngAfterContentInit() {
this.projectTemplate();
}
/**
* @param {?} currentPageNumber
* @return {?}
*/
onTablePageChanged(currentPageNumber) {
this.pageNumber = currentPageNumber;
this.pageNumberChange.emit(this.pageNumber);
this.onPageChanged.next(currentPageNumber);
this.selectAll(false);
}
/**
* @param {?} currentPageSize
* @return {?}
*/
onTablePageSizeChanged(currentPageSize) {
this.pageSize = currentPageSize;
this.onPageSizeChanged.next(currentPageSize);
this.selectAll(false);
}
/**
* @param {?} isChecked
* @return {?}
*/
onSelectAllChecked(isChecked) {
this.selectAll(isChecked);
/** @type {?} */
let rows = [];
if (this.datasource && this.datasource.length > 0) {
this.datasource.forEach((/**
* @param {?} row
* @return {?}
*/
row => {
rows.push(row);
}));
}
this.onRows.emit(rows);
}
/**
* @param {?} row
* @return {?}
*/
onRowSelectChecked(row) {
/** @type {?} */
const colChk = this.internalColumns.find((/**
* @param {?} f
* @return {?}
*/
f => f.headerName === 'chk'));
if (row.checked) {
if (!this.selectedRows.find((/**
* @param {?} f
* @return {?}
*/
f => f.dt_id === row.dt_id))) {
this.selectedRows.push(row);
}
}
else {
this.selectedRows = this.selectedRows.filter((/**
* @param {?} f
* @return {?}
*/
f => f.dt_id !== row.dt_id));
this.onRowsUnchecked.next(row);
}
if (colChk) {
colChk.checked = this.selectedRows.length === this.pageSize;
}
if (this.selectedRows.length === 0) {
this.selectAll(false);
}
this.onRowsChecked.next(this.selectedRows);
this.onRows.emit(row);
}
/**
* @param {?} item
* @return {?}
*/
onSort(item) {
if (!item.sort) {
return;
}
if (this.serverSideSort) {
this.onServerSideSorted.emit({ col: item, sortedBy: item.sortedBy });
return;
}
this.buildClientSideSort(item);
}
//#region Private methods
/**
* @private
* @param {?} item
* @return {?}
*/
buildServerSideSort(item) {
this.setNextSortedBy(item);
this.resetOtherSortedColumns(item);
}
/**
* @private
* @param {?} item
* @return {?}
*/
buildClientSideSort(item) {
this.setNextSortedBy(item);
if (item.sortedBy === 'default') {
this.datasource = [...this.datasourceSortedByDefault];
}
else {
this.datasource.sort(Utils.compareValues(item.headerName, item.sortedBy));
}
this.resetOtherSortedColumns(item);
}
/**
* @private
* @param {?} item
* @return {?}
*/
setNextSortedBy(item) {
switch (item.sortedBy) {
case 'default':
item.sortedBy = 'asc';
break;
case 'asc':
item.sortedBy = 'desc';
break;
case 'desc':
item.sortedBy = 'default';
break;
default:
break;
}
}
/**
* @private
* @return {?}
*/
initUniqueIdForDatasource() {
this.datasource.forEach((/**
* @param {?} row
* @return {?}
*/
row => {
row['dt_id'] = this.ID();
}));
}
/**
* @private
* @return {?}
*/
projectTemplate() {
if (this.columnComponents) {
this.columnComponents.forEach((/**
* @param {?} item
* @return {?}
*/
item => {
if (!this.projectedTemplates.find((/**
* @param {?} f
* @return {?}
*/
f => f.name === item.name))) {
this.projectedTemplates.push({ name: item.name, template: item.cellTemplate });
}
}));
this.internalColumns.forEach((/**
* @param {?} column
* @return {?}
*/
column => {
/** @type {?} */
const projectTemplate = this.projectedTemplates.find((/**
* @param {?} f
* @return {?}
*/
f => f.name === column.headerName));
if (projectTemplate) {
column['template'] = projectTemplate.template;
}
}));
}
if (this.headerComponents) {
this.headerComponents.forEach((/**
* @param {?} item
* @return {?}
*/
item => {
if (!this.headerTemplates.find((/**
* @param {?} f
* @return {?}
*/
f => f.name === item.name))) {
this.headerTemplates.push({ name: item.name, template: item.headerTemplate });
}
}));
this.internalColumns.forEach((/**
* @param {?} column
* @return {?}
*/
column => {
/** @type {?} */
const projectTemplate = this.headerTemplates.find((/**
* @param {?} f
* @return {?}
*/
f => f.name === column.headerName));
if (projectTemplate) {
column['headerTemplate'] = projectTemplate.template;
}
}));
}
}
/**
* @private
* @return {?}
*/
mergeToInternalColumns() {
if (this.internalColumns.length === 0) {
this.internalColumns = [...this.columns];
this.setSortedByToDefault();
return;
}
this.columns.forEach((/**
* @param {?} replaceColumn
* @return {?}
*/
replaceColumn => {
/** @type {?} */
let existColumn = this.internalColumns.find((/**
* @param {?} f
* @return {?}
*/
f => f.headerName === replaceColumn.headerName));
if (existColumn) {
existColumn = Object.assign({}, replaceColumn);
}
else {
this.internalColumns.push(Object.assign({}, replaceColumn));
}
}));
this.setSortedByToDefault();
}
/**
* @private
* @return {?}
*/
setSortedByToDefault() {
for (let i = 0; i < this.internalColumns.length; i++) {
if (this.internalColumns[i].sort) {
this.internalColumns[i].sortedBy = 'default';
}
}
}
/**
* @private
* @return {?}
*/
ID() {
// Math.random should be unique because of its seeding algorithm.
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
// after the decimal.
return '_' + Math.random().toString(36).substr(2, 9);
}
/**
* @private
* @param {?} isSelect
* @return {?}
*/
selectAll(isSelect) {
/** @type {?} */
const colChk = this.internalColumns.find((/**
* @param {?} f
* @return {?}
*/
f => f.headerName === 'chk'));
if (colChk) {
colChk.checked = isSelect;
this.selectedRows = [];
if (this.datasource && this.datasource.length > 0) {
this.datasource.forEach((/**
* @param {?} row
* @return {?}
*/
row => {
row.checked = isSelect;
if (isSelect) {
this.selectedRows.push(row);
}
}));
}
this.onRowsChecked.next(this.selectedRows);
}
}
/**
* @private
* @param {?} item
* @return {?}
*/
resetOtherSortedColumns(item) {
this.internalColumns.forEach((/**
* @param {?} col
* @return {?}
*/
col => {
if (col.headerName !== item.headerName && col.sort) {
col.sortedBy = 'default';
}
}));
}
}
NpTable.decorators = [
{ type: Component, args: [{
selector: `np-table`,
template: "<div class=\"np-table-wrapper\">\r\n <div class=\"table-header flex-wrap row-flex\">\r\n <span *ngFor=\"let item of internalColumns\" [style.flex]=\"'0 1 ' + item.width\">\r\n <ng-container *ngIf=\"item.isCheckbox\">\r\n <!-- We need to re-style or re-design the checkbox control, its ugly and not easy to use -->\r\n <span style=\"width: 100%; height: 34px; display: flex; justify-content: center;\">\r\n <np-checkbox style=\"width: 5px;\" [(ngModel)]=\"item.checked\"\r\n (inputModelChange)=\"onSelectAllChecked(item.checked)\"></np-checkbox>\r\n </span>\r\n </ng-container>\r\n <span *ngIf=\"!item.isCheckbox\">\r\n <ng-container *ngIf=\"!item.headerTemplate\">\r\n <div class=\"flex-wrap row-flex table-header-text\" [ngStyle]=\"{'cursor': item.sort ? 'pointer': 'inherit'}\"\r\n (click)=\"onSort(item)\">\r\n <span>{{ item.headerDisplayName }}</span>\r\n <i *ngIf=\"['default', 'asc', 'desc'].indexOf(item.sortedBy) > -1\" class=\"fas fa-arrow-up\" [ngClass]=\"{\r\n 'table-header-arrow-default': item.sortedBy === 'default', \r\n 'table-header-arrow-up': item.sortedBy === 'asc', \r\n 'table-header-arrow-down': item.sortedBy === 'desc'}\"></i>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"item.headerTemplate\">\r\n <div class=\"flex-wrap row-flex table-header-text\" [ngStyle]=\"{'cursor': item.sort ? 'pointer': 'inherit'}\"\r\n (click)=\"onSort(item)\">\r\n <ng-container *ngTemplateOutlet=\"item.headerTemplate; context: { row: item }\">\r\n </ng-container>\r\n <i *ngIf=\"['default', 'asc', 'desc'].indexOf(item.sortedBy) > -1\" class=\"fas fa-arrow-up\" [ngClass]=\"{\r\n 'table-header-arrow-default': item.sortedBy === 'default', \r\n 'table-header-arrow-up': item.sortedBy === 'asc', \r\n 'table-header-arrow-down': item.sortedBy === 'desc'}\"></i>\r\n </div>\r\n </ng-container>\r\n </span>\r\n </span>\r\n </div>\r\n <div class=\"table-body flex-wrap col-flex\">\r\n <div class=\"table-body-row flex-wrap row-flex\" *ngFor=\"let row of datasource\">\r\n <ng-container *ngFor=\"let column of internalColumns\">\r\n <ng-container *ngIf=\"column.isCheckbox\">\r\n <!-- We need to re-style or re-design the checkbox control, its ugly and not easy to use -->\r\n <span [style.flex]=\"'0 1 ' + column.width\"\r\n style=\"width: 100%; height: 34px; display: flex; justify-content: center;\">\r\n <np-checkbox style=\"width: 5px;\" [(ngModel)]=\"row.checked\" (inputModelChange)=\"onRowSelectChecked(row)\">\r\n </np-checkbox>\r\n </span>\r\n </ng-container>\r\n <span *ngIf=\"!column.isCheckbox\" [style.flex]=\"'0 1 ' + column.width\">\r\n <ng-container *ngIf=\"!column.template\">{{ row[column.headerName] }}</ng-container>\r\n <ng-container *ngIf=\"column.template\">\r\n <ng-container *ngTemplateOutlet=\"column.template; context: { row: row }\">\r\n </ng-container>\r\n </ng-container>\r\n </span>\r\n </ng-container>\r\n </div>\r\n <div *ngIf=\"!datasource || datasource.length === 0\" class=\"table-body-row flex-wrap row-flex middle-flex\">\r\n <ng-container *ngIf=\"!emptyContent || !emptyContent.template\">\r\n <span class=\"no-data\">{{ noDataLabel }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"emptyContent && emptyContent.template\">\r\n <ng-container *ngTemplateOutlet=\"emptyContent.template;\">\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"table-footer flex-wrap row-flex\" *ngIf=\"showPager && datasource && datasource.length > 0\">\r\n <np-paginator [size]=\"pageSize\" [total]=\"total\" [pageNumber]=\"pageNumber\" [firstBtnText]=\"firstBtnText\"\r\n [preBtnText]=\"preBtnText\" [nextBtnText]=\"nextBtnText\" [lastBtnText]=\"lastBtnText\" [totalText]=\"totalText\"\r\n [itemsPerPageText]=\"itemsPerPageText\" (onPageChanged)=\"onTablePageChanged($event)\"\r\n (onPageSizeChanged)=\"onTablePageSizeChanged($event)\"></np-paginator>\r\n </div>\r\n</div>\r\n",
encapsulation: ViewEncapsulation.None,
styles: [".backdrop-transparent{opacity:0}.flex-wrap{display:flex}.wrap{flex-wrap:wrap}.col-flex{flex-direction:column}.row-flex{flex-direction:row}.middle-flex{justify-content:center;align-items:center}.space-between{justify-content:space-between;align-items:center}.align-center{align-items:center}.np-row{display:flex;flex-direction:row;flex-wrap:wrap;width:100%}.np-column{display:flex;flex-direction:column;flex-basis:100%;flex:1}.np-table-wrapper{width:100%;display:block}.np-table-wrapper .table-header{height:34px;line-height:34px;font-weight:700}.np-table-wrapper .table-header>span{flex:1 1 0;text-align:center;-ms-grid-row-align:center;align-self:center}.np-table-wrapper .table-header .table-header-text{align-items:center;justify-content:center}.np-table-wrapper .table-header .table-header-text>.fas.fa-arrow-down,.np-table-wrapper .table-header .table-header-text>.fas.fa-arrow-up{margin-left:6px;transition:.2s ease-in}.np-table-wrapper .table-header .table-header-text>.table-header-arrow-default{opacity:.54}.np-table-wrapper .table-header .table-header-text>.table-header-arrow-down{transform:rotateZ(180deg)}.np-table-wrapper .table-body>.table-body-row{padding:5px 0}.np-table-wrapper .table-body>.table-body-row>span{flex:1 1 0;text-align:center;-ms-grid-row-align:center;align-self:center}.np-table-wrapper .table-footer{justify-content:flex-end;padding:20px 5px 20px 0}"]
}] }
];
/** @nocollapse */
NpTable.ctorParameters = () => [];
NpTable.propDecorators = {
columns: [{ type: Input }],
datasource: [{ type: Input }],
total: [{ type: Input }],
pageSize: [{ type: Input }],
showCheckbox: [{ type: Input }],
showPager: [{ type: Input }],
serverSideSort: [{ type: Input }],
firstBtnText: [{ type: Input }],
preBtnText: [{ type: Input }],
nextBtnText: [{ type: Input }],
lastBtnText: [{ type: Input }],
totalText: [{ type: Input }],
itemsPerPageText: [{ type: Input }],
noDataLabel: [{ type: Input }],
pageNumber: [{ type: Input }],
pageNumberChange: [{ type: Output }],
onPageChanged: [{ type: Output }],
onPageSizeChanged: [{ type: Output }],
onRowsChecked: [{ type: Output }],
onRowsUnchecked: [{ type: Output }],
onServerSideSorted: [{ type: Output }],
onRows: [{ type: Output }],
columnComponents: [{ type: ContentChildren, args: [NpColumnDirective,] }],
headerComponents: [{ type: ContentChildren, args: [NpHeaderDirective,] }],
emptyContent: [{ type: ContentChild, args: [NpEmptyDirective,] }]
};
if (false) {
/**
* 定义列名称(即数据源datasource对象属性名称),列显示名称,列宽度(可选,默认每列自适应等宽)
* @type {?}
*/
NpTable.prototype.columns;
/**
* 表格组件数据源,数据源为一个对象数组,对象的属性名称必须与表格列名称相同,否则不会展示此列
* @type {?}
*/
NpTable.prototype.datasource;
/**
* 数据总条数
* @type {?}
*/
NpTable.prototype.total;
/**
* 每页显示条数,默认20条
* @type {?}
*/
NpTable.prototype.pageSize;
/**
* 是否在表头第一列展示多选框,默认不展示
* @type {?}
*/
NpTable.prototype.showCheckbox;
/**
* 是否显示分页组件,默认显示
* @type {?}
*/
NpTable.prototype.showPager;
/**
* 是否服务器端排序,默认false,即客户端排序
* @type {?}
*/
NpTable.prototype.serverSideSort;
/**
* 首页按钮文字
* @type {?}
*/
NpTable.prototype.firstBtnText;
/**
* 上一页按钮文字
* @type {?}
*/
NpTable.prototype.preBtnText;
/**
* 下一页按钮文字
* @type {?}
*/
NpTable.prototype.nextBtnText;
/**
* 尾页按钮文字
* @type {?}
*/
NpTable.prototype.lastBtnText;
/**
* 共
* @type {?}
*/
NpTable.prototype.totalText;
/**
* 条,每页显示条数
* @type {?}
*/
NpTable.prototype.itemsPerPageText;
/**
* 没有数据按钮文字
* @type {?}
*/
NpTable.prototype.noDataLabel;
/**
* 当前页码
* @type {?}
*/
NpTable.prototype.pageNumber;
/**
* 页码改变事件,即翻页事件 (双向绑定)
* @type {?}
*/
NpTable.prototype.pageNumberChange;
/**
* 页码改变事件,即翻页事件
* @type {?}
*/
NpTable.prototype.onPageChanged;
/**
* 每页显示条数改变事件
* @type {?}
*/
NpTable.prototype.onPageSizeChanged;
/**
* Will be deprecated, use onRows instead
* @type {?}
*/
NpTable.prototype.onRowsChecked;
/**
* Will be deprecated, use onRows instead
*
* 为了向后兼容,故没有修改onRowsChecked逻辑,增加此output事件
*
* 当前行uncheck时触发此事件
* @type {?}
*/
NpTable.prototype.onRowsUnchecked;
/**
* 当选择服务器端排序(即serverSideSort = true)时,根据当前点击列内容及排序,传给backend api返回服务器端排序数据赋值给datasource及total字段即可
* @type {?}
*/
NpTable.prototype.onServerSideSorted;
/**
* 当前处理的行row/rows,选中/非选中状态
*
* 如点击全选按钮,则处理的是当前页的所有行rows
* @type {?}
*/
NpTable.prototype.onRows;
/** @type {?} */
NpTable.prototype.columnComponents;
/** @type {?} */
NpTable.prototype.headerComponents;
/** @type {?} */
NpTable.prototype.emptyContent;
/** @type {?} */
NpTable.prototype.projectedTemplates;
/** @type {?} */
NpTable.prototype.headerTemplates;
/** @type {?} */
NpTable.prototype.internalColumns;
/**
* 此字段后续会废弃 will be deprecated
* @type {?}
*/
NpTable.prototype.selectedRows;
/** @type {?} */
NpTable.prototype.datasourceSortedByDefault;
}
/**
* @record
*/
export function ColumnDef() { }
if (false) {
/**
* 列名称
* @type {?}
*/
ColumnDef.prototype.headerName;
/**
* 列显示名称
* @type {?}
*/
ColumnDef.prototype.headerDisplayName;
/**
* 列宽度
* @type {?|undefined}
*/
ColumnDef.prototype.width;
/** @type {?|undefined} */
ColumnDef.prototype.sort;
}
/**
* @ignore
* @record
*/
function InternalColumnDef() { }
if (false) {
/** @type {?|undefined} */
InternalColumnDef.prototype.isCheckbox;
/** @type {?|undefined} */
InternalColumnDef.prototype.checked;
/** @type {?|undefined} */
InternalColumnDef.prototype.sortedBy;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LXBsdXRvLyIsInNvdXJjZXMiOlsibGliL3RhYmxlL3RhYmxlLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBVSxLQUFLLEVBQUUsWUFBWSxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQTRCLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdEssT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdkQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDckQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdkQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7QUFjeEMsTUFBTSxPQUFPLE9BQU87SUF5RWxCOzs7O1FBbEVTLFVBQUssR0FBVyxDQUFDLENBQUM7Ozs7UUFFbEIsYUFBUSxHQUFXLEVBQUUsQ0FBQyxDQUFhLDhCQUE4Qjs7Ozs7UUFFakUsaUJBQVksR0FBWSxLQUFLLENBQUMsQ0FBSyx3REFBd0Q7Ozs7O1FBRTNGLGNBQVMsR0FBWSxJQUFJLENBQUM7Ozs7UUFHMUIsbUJBQWMsR0FBWSxLQUFLLENBQUM7Ozs7UUFHaEMsaUJBQVksR0FBVyxJQUFJLENBQUM7Ozs7UUFFNUIsZUFBVSxHQUFXLEtBQUssQ0FBQzs7OztRQUUzQixnQkFBVyxHQUFXLEtBQUssQ0FBQzs7OztRQUU1QixnQkFBVyxHQUFXLElBQUksQ0FBQzs7OztRQUUzQixjQUFTLEdBQVcsR0FBRyxDQUFDOzs7O1FBRXhCLHFCQUFnQixHQUFXLFVBQVUsQ0FBQzs7OztRQUV0QyxnQkFBVyxHQUFXLE1BQU0sQ0FBQzs7OztRQUU3QixlQUFVLEdBQVcsQ0FBQyxDQUFDOzs7O1FBRXRCLHFCQUFnQixHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7Ozs7UUFHOUMsa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDOzs7O1FBRTNDLHNCQUFpQixHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7Ozs7UUFJL0Msa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDOzs7Ozs7OztRQVF4QyxvQkFBZSxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7Ozs7UUFFMUMsdUJBQWtCLEdBQUcsSUFBSSxZQUFZLEVBQTRELENBQUM7Ozs7OztRQU1sRyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQU0zQyx1QkFBa0IsR0FBMkMsRUFBRSxDQUFDO1FBQ2hFLG9CQUFlLEdBQTJDLEVBQUUsQ0FBQztRQUM3RCxvQkFBZSxHQUE2QixFQUFFLENBQUM7Ozs7UUFFL0MsaUJBQVksR0FBZSxFQUFFLENBQUM7UUFDOUIsOEJBQXlCLEdBQWUsRUFBRSxDQUFDO0lBRTNCLENBQUM7Ozs7SUFFakIsUUFBUTtRQUNOLElBQUksQ0FBQyx5QkFBeUIsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRXRELElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQztnQkFDeEIsVUFBVSxFQUFFLEtBQUs7Z0JBQ2pCLGlCQUFpQixFQUFFLEVBQUU7Z0JBQ3JCLEtBQUssRUFBRSxNQUFNO2dCQUNiLFVBQVUsRUFBRSxJQUFJO2FBQ2pCLENBQUMsQ0FBQztTQUNKO1FBRUQsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFFOUIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFNBQVM7Ozs7UUFBQyxHQUFHLENBQUMsRUFBRTtZQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEMsQ0FBQyxFQUFDLENBQUM7SUFDTCxDQUFDOzs7OztJQUVELFdBQVcsQ0FBQyxPQUFzQjtRQUNoQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxZQUFZO1lBQ2pELE9BQU8sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDO1lBQ3ZDLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFBYTtZQUM3QixPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUN4QyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksS0FBSyxPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRTtZQUNoRSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7U0FDeEI7UUFFRCxJQUFJLE9BQU8sQ0FBQyxVQUFVLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxZQUFZLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN2RyxJQUFJLENBQUMseUJBQXlCLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdEUsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7U0FDbEM7UUFFRCxJQUFJLE9BQU8sQ0FBQyxLQUFLLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUU7WUFDL0MsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDO1NBQzFDO1FBRUQsSUFBSSxPQUFPLENBQUMsVUFBVSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxXQUFXLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUU7O2tCQUN0RixVQUFVLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFlBQVk7WUFDbkQsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7WUFDN0IsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUV2QyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3ZCO0lBQ0gsQ0FBQzs7OztJQUVELGtCQUFrQjtRQUNoQixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDekIsQ0FBQzs7Ozs7SUFFRCxrQkFBa0IsQ0FBQyxpQkFBeUI7UUFDMUMsSUFBSSxDQUFDLFVBQVUsR0FBRyxpQkFBaUIsQ0FBQztRQUNwQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUU1QyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBRTNDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDeEIsQ0FBQzs7Ozs7SUFFRCxzQkFBc0IsQ0FBQyxlQUF1QjtRQUM1QyxJQUFJLENBQUMsUUFBUSxHQUFHLGVBQWUsQ0FBQztRQUNoQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBRTdDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDeEIsQ0FBQzs7Ozs7SUFFRCxrQkFBa0IsQ0FBQyxTQUFrQjtRQUNuQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDOztZQUV0QixJQUFJLEdBQUcsRUFBRTtRQUNiLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDakQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPOzs7O1lBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakIsQ0FBQyxFQUFDLENBQUM7U0FDSjtRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pCLENBQUM7Ozs7O0lBRUQsa0JBQWtCLENBQUMsR0FBUTs7Y0FDbkIsTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSTs7OztRQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsS0FBSyxLQUFLLEVBQUM7UUFDckUsSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFO1lBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSTs7OztZQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxHQUFHLENBQUMsS0FBSyxFQUFDLEVBQUU7Z0JBQ3ZELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQzdCO1NBQ0Y7YUFBTTtZQUNMLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNOzs7O1lBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLEdBQUcsQ0FBQyxLQUFLLEVBQUMsQ0FBQztZQUN6RSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUNoQztRQUVELElBQUksTUFBTSxFQUFFO1lBQ1YsTUFBTSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsUUFBUSxDQUFDO1NBQzdEO1FBRUQsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDbEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUN2QjtRQUVELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN4QixDQUFDOzs7OztJQUVELE1BQU0sQ0FBQyxJQUF1QjtRQUM1QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLE9BQU87U0FDUjtRQUVELElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUN2QixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDckUsT0FBTztTQUNSO1FBRUQsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7Ozs7Ozs7SUFHTyxtQkFBbUIsQ0FBQyxJQUF1QjtRQUNqRCxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNyQyxDQUFDOzs7Ozs7SUFFTyxtQkFBbUIsQ0FBQyxJQUF1QjtRQUNqRCxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNCLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUU7WUFDL0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUM7U0FDdkQ7YUFBTTtZQUNMLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztTQUMzRTtRQUVELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNyQyxDQUFDOzs7Ozs7SUFFTyxlQUFlLENBQUMsSUFBdUI7UUFDN0MsUUFBUSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ3JCLEtBQUssU0FBUztnQkFDWixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztnQkFDdEIsTUFBTTtZQUNSLEtBQUssS0FBSztnQkFDUixJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztnQkFDdkIsTUFBTTtZQUNSLEtBQUssTUFBTTtnQkFDVCxJQUFJLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQztnQkFDMUIsTUFBTTtZQUNSO2dCQUNFLE1BQU07U0FDVDtJQUNILENBQUM7Ozs7O0lBRU8seUJBQXlCO1FBQy9CLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTzs7OztRQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQzVCLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDM0IsQ0FBQyxFQUFDLENBQUM7SUFDTCxDQUFDOzs7OztJQUVPLGVBQWU7UUFDckIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDekIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU87Ozs7WUFBQyxJQUFJLENBQUMsRUFBRTtnQkFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJOzs7O2dCQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFDLEVBQUU7b0JBQzVELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUM7aUJBQ2hGO1lBQ0gsQ0FBQyxFQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU87Ozs7WUFBQyxNQUFNLENBQUMsRUFBRTs7c0JBQzlCLGVBQWUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSTs7OztnQkFBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLFVBQVUsRUFBQztnQkFDdkYsSUFBSSxlQUFlLEVBQUU7b0JBQ25CLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxlQUFlLENBQUMsUUFBUSxDQUFDO2lCQUMvQztZQUNILENBQUMsRUFBQyxDQUFDO1NBQ0o7UUFDRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtZQUN6QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTzs7OztZQUFDLElBQUksQ0FBQyxFQUFFO2dCQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJOzs7O2dCQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFDLEVBQUU7b0JBQ3pELElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO2lCQUMvRTtZQUNILENBQUMsRUFBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPOzs7O1lBQUMsTUFBTSxDQUFDLEVBQUU7O3NCQUM5QixlQUFlLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJOzs7O2dCQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFDO2dCQUNwRixJQUFJLGVBQWUsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsZUFBZSxDQUFDLFFBQVEsQ0FBQztpQkFDckQ7WUFDSCxDQUFDLEVBQUMsQ0FBQztTQUNKO0lBQ0gsQ0FBQzs7Ozs7SUFFTyxzQkFBc0I7UUFDNUIsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDckMsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBQzVCLE9BQU87U0FDUjtRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTzs7OztRQUFDLGFBQWEsQ0FBQyxFQUFFOztnQkFDL0IsV0FBVyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSTs7OztZQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsS0FBSyxhQUFhLENBQUMsVUFBVSxFQUFDO1lBQzNGLElBQUksV0FBVyxFQUFFO2dCQUNmLFdBQVcscUJBQVEsYUFBYSxDQUFFLENBQUM7YUFDcEM7aUJBQU07Z0JBQ0wsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLG1CQUFNLGFBQWEsRUFBRyxDQUFDO2FBQ2pEO1FBQ0gsQ0FBQyxFQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztJQUM5QixDQUFDOzs7OztJQUVPLG9CQUFvQjtRQUMxQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDcEQsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRTtnQkFDaEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDO2FBQzlDO1NBQ0Y7SUFDSCxDQUFDOzs7OztJQUVPLEVBQUU7UUFDUixpRUFBaUU7UUFDakUsNkVBQTZFO1FBQzdFLHFCQUFxQjtRQUNyQixPQUFPLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsQ0FBQzs7Ozs7O0lBRU8sU0FBUyxDQUFDLFFBQWlCOztjQUMzQixNQUFNLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJOzs7O1FBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxLQUFLLEtBQUssRUFBQztRQUNyRSxJQUFJLE1BQU0sRUFBRTtZQUNWLE1BQU0sQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDO1lBRTFCLElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxDQUFDO1lBQ3ZCLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ2pELElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTzs7OztnQkFBQyxHQUFHLENBQUMsRUFBRTtvQkFDNUIsR0FBRyxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUM7b0JBQ3ZCLElBQUksUUFBUSxFQUFFO3dCQUNaLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO3FCQUM3QjtnQkFDSCxDQUFDLEVBQUMsQ0FBQzthQUNKO1lBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQzVDO0lBQ0gsQ0FBQzs7Ozs7O0lBRU8sdUJBQXVCLENBQUMsSUFBdUI7UUFDckQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPOzs7O1FBQUMsR0FBRyxDQUFDLEVBQUU7WUFDakMsSUFBSSxHQUFHLENBQUMsVUFBVSxLQUFLLElBQUksQ0FBQyxVQUFVLElBQUksR0FBRyxDQUFDLElBQUksRUFBRTtnQkFDbEQsR0FBRyxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUM7YUFDMUI7UUFDSCxDQUFDLEVBQUMsQ0FBQztJQUNMLENBQUM7OztZQTFVRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLFVBQVU7Z0JBQ3BCLDJ3SUFBeUI7Z0JBRXpCLGFBQWEsRUFBRSxpQkFBaUIsQ0FBQyxJQUFJOzthQUN0Qzs7Ozs7c0JBS0UsS0FBSzt5QkFFTCxLQUFLO29CQUVMLEtBQUs7dUJBRUwsS0FBSzsyQkFFTCxLQUFLO3dCQUVMLEtBQUs7NkJBR0wsS0FBSzsyQkFHTCxLQUFLO3lCQUVMLEtBQUs7MEJBRUwsS0FBSzswQkFFTCxLQUFLO3dCQUVMLEtBQUs7K0JBRUwsS0FBSzswQkFFTCxLQUFLO3lCQUVMLEtBQUs7K0JBRUwsTUFBTTs0QkFHTixNQUFNO2dDQUVOLE1BQU07NEJBSU4sTUFBTTs4QkFRTixNQUFNO2lDQUVOLE1BQU07cUJBTU4sTUFBTTsrQkFFTixlQUFlLFNBQUMsaUJBQWlCOytCQUNqQyxlQUFlLFNBQUMsaUJBQWlCOzJCQUNqQyxZQUFZLFNBQUMsZ0JBQWdCOzs7Ozs7O0lBN0Q5QiwwQkFBbUM7Ozs7O0lBRW5DLDZCQUFnQzs7Ozs7SUFFaEMsd0JBQTJCOzs7OztJQUUzQiwyQkFBK0I7Ozs7O0lBRS9CLCtCQUF1Qzs7Ozs7SUFFdkMsNEJBQW1DOzs7OztJQUduQyxpQ0FBeUM7Ozs7O0lBR3pDLCtCQUFxQzs7Ozs7SUFFckMsNkJBQW9DOzs7OztJQUVwQyw4QkFBcUM7Ozs7O0lBRXJDLDhCQUFvQzs7Ozs7SUFFcEMsNEJBQWlDOzs7OztJQUVqQyxtQ0FBK0M7Ozs7O0lBRS9DLDhCQUFzQzs7Ozs7SUFFdEMsNkJBQWdDOzs7OztJQUVoQyxtQ0FBd0Q7Ozs7O0lBR3hELGdDQUFxRDs7Ozs7SUFFckQsb0NBQXlEOzs7OztJQUl6RCxnQ0FBa0Q7Ozs7Ozs7OztJQVFsRCxrQ0FBb0Q7Ozs7O0lBRXBELHFDQUE0Rzs7Ozs7OztJQU01Ryx5QkFBMkM7O0lBRTNDLG1DQUFtRjs7SUFDbkYsbUNBQW1GOztJQUNuRiwrQkFBK0Q7O0lBRS9ELHFDQUFnRTs7SUFDaEUsa0NBQTZEOztJQUM3RCxrQ0FBK0M7Ozs7O0lBRS9DLCtCQUE4Qjs7SUFDOUIsNENBQTJDOzs7OztBQWdRN0MsK0JBUUM7Ozs7OztJQU5DLCtCQUFtQjs7Ozs7SUFFbkIsc0NBQTBCOzs7OztJQUUxQiwwQkFBZTs7SUFDZix5QkFBZTs7Ozs7O0FBTWpCLGdDQUlDOzs7SUFIQyx1Q0FBcUI7O0lBQ3JCLG9DQUFrQjs7SUFDbEIscUNBQXNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBWaWV3RW5jYXBzdWxhdGlvbiwgT25Jbml0LCBJbnB1dCwgQ29udGVudENoaWxkLCBDb250ZW50Q2hpbGRyZW4sIFF1ZXJ5TGlzdCwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzLCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IE5wQ29sdW1uRGlyZWN0aXZlIH0gZnJvbSBcIi4vY29sdW1uLmRpcmVjdGl2ZVwiO1xyXG5pbXBvcnQgeyBOcEVtcHR5RGlyZWN0aXZlIH0gZnJvbSBcIi4vZW1wdHkuZGlyZWN0aXZlXCI7XHJcbmltcG9ydCB7IE5wSGVhZGVyRGlyZWN0aXZlIH0gZnJvbSAnLi9oZWFkZXIuZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgVXRpbHMgfSBmcm9tIFwiLi4vY29tbW9uL3V0aWxzXCI7XHJcblxyXG4vKipcclxuICog5Y+v5YiG6aG16KGo5qC857uE5Lu2IC0g5pSv5oyB5YiG6aG144CB6Ieq5a6a5LmJ5YiX5ZCN44CB6Ieq5a6a5LmJ5YiX5YaF5a65562J44CC5a+55LqO5aSa6K+t6KiA77yM5pSv5oyB6YCa6L+HwrdASW5wdXTCt+WxnuaAp+iHquWumuS5ieOAglxyXG4gKlxyXG4gKiA8ZXhhbXBsZS11cmw+aHR0cHM6Ly9zdGFja2JsaXR6LmNvbS9lZGl0L25wLXRhYmxlLXNhbXBsZT9lbWJlZD0xJmZpbGU9c3JjL2FwcC9hcHAuY29tcG9uZW50Lmh0bWw8L2V4YW1wbGUtdXJsPlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6IGBucC10YWJsZWAsXHJcbiAgdGVtcGxhdGVVcmw6ICd0YWJsZS5odG1sJyxcclxuICBzdHlsZVVybHM6IFsndGFibGUuc2NzcyddLFxyXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmVcclxufSlcclxuXHJcbmV4cG9ydCBjbGFzcyBOcFRhYmxlIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xyXG5cclxuICAvKirlrprkuYnliJflkI3np7DvvIjljbPmlbDmja7mupBkYXRhc291cmNl5a+56LGh5bGe5oCn5ZCN56ew77yJ77yM5YiX5pi+56S65ZCN56ew77yM5YiX5a695bqm77yI5Y+v6YCJ77yM6buY6K6k5q+P5YiX6Ieq6YCC5bqU562J5a6977yJICovXHJcbiAgQElucHV0KCkgY29sdW1uczogQXJyYXk8Q29sdW1uRGVmPjtcclxuICAvKirooajmoLznu4Tku7bmlbDmja7mupDvvIzmlbDmja7mupDkuLrkuIDkuKrlr7nosaHmlbDnu4TvvIzlr7nosaHnmoTlsZ7mgKflkI3np7Dlv4XpobvkuI7ooajmoLzliJflkI3np7Dnm7jlkIzvvIzlkKbliJnkuI3kvJrlsZXnpLrmraTliJcgKi9cclxuICBASW5wdXQoKSBkYXRhc291cmNlOiBBcnJheTxhbnk+O1xyXG4gIC8qKuaVsOaNruaAu+adoeaVsCAqL1xyXG4gIEBJbnB1dCgpIHRvdGFsOiBudW1iZXIgPSAwO1xyXG4gIC8qKuavj+mhteaYvuekuuadoeaVsO+8jOm7mOiupDIw5p2hICovXHJcbiAgQElucHV0KCkgcGFnZVNpemU6IG51bWJlciA9IDIwOyAgICAgICAgICAgICAvLyBEZWZhdWx0IGlzIDIwIHJvd3MgcGVyIHBhZ2VcclxuICAvKirmmK/lkKblnKjooajlpLTnrKzkuIDliJflsZXnpLrlpJrpgInmoYbvvIzpu5jorqTkuI3lsZXnpLogKi9cclxuICBASW5wdXQoKSBzaG93Q2hlY2tib3g6IGJvb2xlYW4gPSBmYWxzZTsgICAgIC8vIEluZGljYXRlIHdoZXRoZXIgc2hvdyBjaGVja2JveCBvciBub3QsIGRlZmF1bHQgaXMgbm90XHJcbiAgLyoq5piv5ZCm5pi+56S65YiG6aG157uE5Lu277yM6buY6K6k5pi+56S6ICovXHJcbiAgQElucHV0KCkgc2hvd1BhZ2VyOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoq5piv5ZCm5pyN5Yqh5Zmo56uv5o6S5bqP77yM6buY6K6kZmFsc2XvvIzljbPlrqLmiLfnq6/mjpLluo8gKi9cclxuICBASW5wdXQoKSBzZXJ2ZXJTaWRlU29ydDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKirpppbpobXmjInpkq7mloflrZcgKi9cclxuICBASW5wdXQoKSBmaXJzdEJ0blRleHQ6IHN0cmluZyA9ICfpppbpobUnO1xyXG4gIC8qKuS4iuS4gOmhteaMiemSruaWh+WtlyAqL1xyXG4gIEBJbnB1dCgpIHByZUJ0blRleHQ6IHN0cmluZyA9ICfkuIrkuIDpobUnO1xyXG4gIC8qKuS4i+S4gOmhteaMiemSruaWh+WtlyAqL1xyXG4gIEBJbnB1dCgpIG5leHRCdG5UZXh0OiBzdHJpbmcgPSAn5LiL5LiA6aG1JztcclxuICAvKirlsL7pobXmjInpkq7mloflrZcgKi9cclxuICBASW5wdXQoKSBsYXN0QnRuVGV4dDogc3RyaW5nID0gJ+WwvumhtSc7XHJcbiAgLyoq5YWxICovXHJcbiAgQElucHV0KCkgdG90YWxUZXh0OiBzdHJpbmcgPSAn5YWxJztcclxuICAvKirmnaHvvIzmr4/pobXmmL7npLrmnaHmlbAgKi9cclxuICBASW5wdXQoKSBpdGVtc1BlclBhZ2VUZXh0OiBzdHJpbmcgPSAn5p2h77yM5q+P6aG15pi+56S65p2h5pWwJztcclxuICAvKirmsqHmnInmlbDmja7mjInpkq7mloflrZcgKi9cclxuICBASW5wdXQoKSBub0RhdGFMYWJlbDogc3RyaW5nID0gXCLmsqHmnInmlbDmja5cIjtcclxuICAvKirlvZPliY3pobXnoIEgKi9cclxuICBASW5wdXQoKSBwYWdlTnVtYmVyOiBudW1iZXIgPSAxO1xyXG4gIC8qKumhteeggeaUueWPmOS6i+S7tu+8jOWNs+e/u+mhteS6i+S7tiDvvIjlj4zlkJHnu5HlrprvvIkgKi9cclxuICBAT3V0cHV0KCkgcGFnZU51bWJlckNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xyXG5cclxuICAvKirpobXnoIHmlLnlj5jkuovku7bvvIzljbPnv7vpobXkuovku7YgKi9cclxuICBAT3V0cHV0KCkgb25QYWdlQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xyXG4gIC8qKuavj+mhteaYvuekuuadoeaVsOaUueWPmOS6i+S7tiAqL1xyXG4gIEBPdXRwdXQoKSBvblBhZ2VTaXplQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xyXG4gIC8qKlxyXG4gICAqIFdpbGwgYmUgZGVwcmVjYXRlZCwgdXNlIG9uUm93cyBpbnN0ZWFkXHJcbiAgICovXHJcbiAgQE91dHB1dCgpIG9uUm93c0NoZWNrZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuICAvKipcclxuICAgKiBXaWxsIGJlIGRlcHJlY2F0ZWQsIHVzZSBvblJvd3MgaW5zdGVhZFxyXG4gICAqIFxyXG4gICAqIOS4uuS6huWQkeWQjuWFvOWuue+8jOaVheayoeacieS/ruaUuW9uUm93c0NoZWNrZWTpgLvovpHvvIzlop7liqDmraRvdXRwdXTkuovku7ZcclxuICAgKiBcclxuICAgKiDlvZPliY3ooYx1bmNoZWNr5pe26Kem5Y+R5q2k5LqL5Lu2XHJcbiAgICovXHJcbiAgQE91dHB1dCgpIG9uUm93c1VuY2hlY2tlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG4gIC8qKuW9k+mAieaLqeacjeWKoeWZqOerr+aOkuW6j++8iOWNs3NlcnZlclNpZGVTb3J0ID0gdHJ1Ze+8ieaXtu+8jOagueaNruW9k+WJjeeCueWHu+WIl+WGheWuueWPiuaOkuW6j++8jOS8oOe7mWJhY2tlbmQgYXBp6L+U5Zue5pyN5Yqh5Zmo56uv5o6S5bqP5pWw5o2u6LWL5YC857uZZGF0YXNvdXJjZeWPinRvdGFs5a2X5q615Y2z5Y+vICovXHJcbiAgQE91dHB1dCgpIG9uU2VydmVyU2lkZVNvcnRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBjb2w6IENvbHVtbkRlZiwgc29ydGVkQnk6ICdkZWZhdWx0JyB8ICdhc2MnIHwgJ2Rlc2MnIH0+KCk7XHJcbiAgLyoqXHJcbiAgICog5b2T5YmN5aSE55CG55qE6KGMcm93L3Jvd3PvvIzpgInkuK0v6Z2e6YCJ5Lit54q25oCBXHJcbiAgICogXHJcbiAgICog5aaC54K55Ye75YWo6YCJ5oyJ6ZKu77yM5YiZ5aSE55CG55qE5piv5b2T5YmN6aG155qE5omA5pyJ6KGMcm93c1xyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBvblJvd3MgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgQENvbnRlbnRDaGlsZHJlbihOcENvbHVtbkRpcmVjdGl2ZSkgY29sdW1uQ29tcG9uZW50czogUXVlcnlMaXN0PE5wQ29sdW1uRGlyZWN0aXZlPjtcclxuICBAQ29udGVudENoaWxkcmVuKE5wSGVhZGVyRGlyZWN0aXZlKSBoZWFkZXJDb21wb25lbnRzOiBRdWVyeUxpc3Q8TnBIZWFkZXJEaXJlY3RpdmU+O1xyXG4gIEBDb250ZW50Q2hpbGQoTnBFbXB0eURpcmVjdGl2ZSkgZW1wdHlDb250ZW50OiBOcEVtcHR5RGlyZWN0aXZlO1xyXG5cclxuICBwcm9qZWN0ZWRUZW1wbGF0ZXM6IEFycmF5PHsgbmFtZTogc3RyaW5nLCB0ZW1wbGF0ZTogYW55IH0+ID0gW107XHJcbiAgaGVhZGVyVGVtcGxhdGVzOiBBcnJheTx7IG5hbWU6IHN0cmluZywgdGVtcGxhdGU6IGFueSB9PiA9IFtdO1xyXG4gIGludGVybmFsQ29sdW1uczogQXJyYXk8SW50ZXJuYWxDb2x1bW5EZWY+ID0gW107XHJcbiAgLyoq5q2k5a2X5q615ZCO57ut5Lya5bqf5byDIHdpbGwgYmUgZGVwcmVjYXRlZCAqL1xyXG4gIHNlbGVjdGVkUm93czogQXJyYXk8YW55PiA9IFtdO1xyXG4gIGRhdGFzb3VyY2VTb3J0ZWRCeURlZmF1bHQ6IEFycmF5PGFueT4gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IoKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLmRhdGFzb3VyY2VTb3J0ZWRCeURlZmF1bHQgPSBbLi4udGhpcy5kYXRhc291cmNlXTtcclxuXHJcbiAgICBpZiAodGhpcy5zaG93Q2hlY2tib3gpIHtcclxuICAgICAgdGhpcy5pbnRlcm5hbENvbHVtbnMgPSBbXTtcclxuICAgICAgdGhpcy5pbnRlcm5hbENvbHVtbnMucHVzaCh7XHJcbiAgICAgICAgaGVhZGVyTmFtZTogJ2NoaycsXHJcbiAgICAgICAgaGVhZGVyRGlzcGxheU5hbWU6ICcnLFxyXG4gICAgICAgIHdpZHRoOiAnNTBweCcsXHJcbiAgICAgICAgaXNDaGVja2JveDogdHJ1ZVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLm1lcmdlVG9JbnRlcm5hbENvbHVtbnMoKTtcclxuXHJcbiAgICB0aGlzLm9uU2VydmVyU2lkZVNvcnRlZC5zdWJzY3JpYmUocmVzID0+IHtcclxuICAgICAgY29uc29sZS5sb2coJ29uU2VydmVyU2lkZVNvcnRlZDogJywgcmVzKTtcclxuICAgICAgdGhpcy5idWlsZFNlcnZlclNpZGVTb3J0KHJlcy5jb2wpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBpZiAoY2hhbmdlcy5jb2x1bW5zICYmIGNoYW5nZXMuY29sdW1ucy5jdXJyZW50VmFsdWUgJiZcclxuICAgICAgY2hhbmdlcy5jb2x1bW5zLmN1cnJlbnRWYWx1ZS5sZW5ndGggPiAwICYmXHJcbiAgICAgIGNoYW5nZXMuY29sdW1ucy5wcmV2aW91c1ZhbHVlICYmXHJcbiAgICAgIGNoYW5nZXMuY29sdW1ucy5wcmV2aW91c1ZhbHVlLmxlbmd0aCA+IDAgJiZcclxuICAgICAgY2hhbmdlcy5jb2x1bW5zLmN1cnJlbnRWYWx1ZSAhPT0gY2hhbmdlcy5jb2x1bW5zLnByZXZpb3VzVmFsdWUpIHtcclxuICAgICAgdGhpcy5tZXJnZVRvSW50ZXJuYWxDb2x1bW5zKCk7XHJcbiAgICAgIHRoaXMucHJvamVjdFRlbXBsYXRlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNoYW5nZXMuZGF0YXNvdXJjZSAmJiBjaGFuZ2VzLmRhdGFzb3VyY2UuY3VycmVudFZhbHVlICYmIGNoYW5nZXMuZGF0YXNvdXJjZS5jdXJyZW50VmFsdWUubGVuZ3RoID4gMCkge1xyXG4gICAgICB0aGlzLmRhdGFzb3VyY2VTb3J0ZWRCeURlZmF1bHQgPSBbLi4uY2hhbmdlcy5kYXRhc291cmNlLmN1cnJlbnRWYWx1ZV07XHJcbiAgICAgIHRoaXMuaW5pdFVuaXF1ZUlkRm9yRGF0YXNvdXJjZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChjaGFuZ2VzLnRvdGFsICYmIGNoYW5nZXMudG90YWwuY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIHRoaXMudG90YWwgPSArY2hhbmdlcy50b3RhbC5jdXJyZW50VmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNoYW5nZXMucGFnZU51bWJlciAmJiAhY2hhbmdlcy5wYWdlTnVtYmVyLmZpcnN0Q2hhbmdlICYmIGNoYW5nZXMucGFnZU51bWJlci5jdXJyZW50VmFsdWUpIHtcclxuICAgICAgY29uc3QgcGFnZU51bWJlciA9ICtjaGFuZ2VzLnBhZ2VOdW1iZXIuY3VycmVudFZhbHVlO1xyXG4gICAgICB0aGlzLnBhZ2VOdW1iZXIgPSBwYWdlTnVtYmVyO1xyXG4gICAgICB0aGlzLnBhZ2VOdW1iZXJDaGFuZ2UuZW1pdChwYWdlTnVtYmVyKTtcclxuXHJcbiAgICAgIHRoaXMuc2VsZWN0QWxsKGZhbHNlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcclxuICAgIHRoaXMucHJvamVjdFRlbXBsYXRlKCk7XHJcbiAgfVxyXG5cclxuICBvblRhYmxlUGFnZUNoYW5nZWQoY3VycmVudFBhZ2VOdW1iZXI6IG51bWJlcikge1xyXG4gICAgdGhpcy5wYWdlTnVtYmVyID0gY3VycmVudFBhZ2VOdW1iZXI7XHJcbiAgICB0aGlzLnBhZ2VOdW1iZXJDaGFuZ2UuZW1pdCh0aGlzLnBhZ2VOdW1iZXIpO1xyXG5cclxuICAgIHRoaXMub25QYWdlQ2hhbmdlZC5uZXh0KGN1cnJlbnRQYWdlTnVtYmVyKTtcclxuXHJcbiAgICB0aGlzLnNlbGVjdEFsbChmYWxzZSk7XHJcbiAgfVxyXG5cclxuICBvblRhYmxlUGFnZVNpemVDaGFuZ2VkKGN1cnJlbnRQYWdlU2l6ZTogbnVtYmVyKSB7XHJcbiAgICB0aGlzLnBhZ2VTaXplID0gY3VycmVudFBhZ2VTaXplO1xyXG4gICAgdGhpcy5vblBhZ2VTaXplQ2hhbmdlZC5uZXh0KGN1cnJlbnRQYWdlU2l6ZSk7XHJcblxyXG4gICAgdGhpcy5zZWxlY3RBbGwoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgb25TZWxlY3RBbGxDaGVja2VkKGlzQ2hlY2tlZDogYm9vbGVhbikge1xyXG4gICAgdGhpcy5zZWxlY3RBbGwoaXNDaGVja2VkKTtcclxuXHJcbiAgICBsZXQgcm93cyA9IFtdO1xyXG4gICAgaWYgKHRoaXMuZGF0YXNvdXJjZSAmJiB0aGlzLmRhdGFzb3VyY2UubGVuZ3RoID4gMCkge1xyXG4gICAgICB0aGlzLmRhdGFzb3VyY2UuZm9yRWFjaChyb3cgPT4ge1xyXG4gICAgICAgIHJvd3MucHVzaChyb3cpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLm9uUm93cy5lbWl0KHJvd3MpO1xyXG4gIH1cclxuXHJcbiAgb25Sb3dTZWxlY3RDaGVja2VkKHJvdzogYW55KSB7XHJcbiAgICBjb25zdCBjb2xDaGsgPSB0aGlzLmludGVybmFsQ29sdW1ucy5maW5kKGYgPT4gZi5oZWFkZXJOYW1lID09PSAnY2hrJyk7XHJcbiAgICBpZiAocm93LmNoZWNrZWQpIHtcclxuICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkUm93cy5maW5kKGYgPT4gZi5kdF9pZCA9PT0gcm93LmR0X2lkKSkge1xyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRSb3dzLnB1c2gocm93KTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZFJvd3MgPSB0aGlzLnNlbGVjdGVkUm93cy5maWx0ZXIoZiA9PiBmLmR0X2lkICE9PSByb3cuZHRfaWQpO1xyXG4gICAgICB0aGlzLm9uUm93c1VuY2hlY2tlZC5uZXh0KHJvdyk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNvbENoaykge1xyXG4gICAgICBjb2xDaGsuY2hlY2tlZCA9IHRoaXMuc2VsZWN0ZWRSb3dzLmxlbmd0aCA9PT0gdGhpcy5wYWdlU2l6ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZFJvd3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0QWxsKGZhbHNlKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLm9uUm93c0NoZWNrZWQubmV4dCh0aGlzLnNlbGVjdGVkUm93cyk7XHJcblxyXG4gICAgdGhpcy5vblJvd3MuZW1pdChyb3cpO1xyXG4gIH1cclxuXHJcbiAgb25Tb3J0KGl0ZW06IEludGVybmFsQ29sdW1uRGVmKSB7XHJcbiAgICBpZiAoIWl0ZW0uc29ydCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuc2VydmVyU2lkZVNvcnQpIHtcclxuICAgICAgdGhpcy5vblNlcnZlclNpZGVTb3J0ZWQuZW1pdCh7IGNvbDogaXRlbSwgc29ydGVkQnk6IGl0ZW0uc29ydGVkQnkgfSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmJ1aWxkQ2xpZW50U2lkZVNvcnQoaXRlbSk7XHJcbiAgfVxyXG5cclxuICAvLyNyZWdpb24gUHJpdmF0ZSBtZXRob2RzXHJcbiAgcHJpdmF0ZSBidWlsZFNlcnZlclNpZGVTb3J0KGl0ZW06IEludGVybmFsQ29sdW1uRGVmKSB7XHJcbiAgICB0aGlzLnNldE5leHRTb3J0ZWRCeShpdGVtKTtcclxuICAgIHRoaXMucmVzZXRPdGhlclNvcnRlZENvbHVtbnMoaXRlbSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJ1aWxkQ2xpZW50U2lkZVNvcnQoaXRlbTogSW50ZXJuYWxDb2x1bW5EZWYpIHtcclxuICAgIHRoaXMuc2V0TmV4dFNvcnRlZEJ5KGl0ZW0pO1xyXG4gICAgaWYgKGl0ZW0uc29ydGVkQnkgPT09ICdkZWZhdWx0Jykge1xyXG4gICAgICB0aGlzLmRhdGFzb3VyY2UgPSBbLi4udGhpcy5kYXRhc291cmNlU29ydGVkQnlEZWZhdWx0XTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZGF0YXNvdXJjZS5zb3J0KFV0aWxzLmNvbXBhcmVWYWx1ZXMoaXRlbS5oZWFkZXJOYW1lLCBpdGVtLnNvcnRlZEJ5KSk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5yZXNldE90aGVyU29ydGVkQ29sdW1ucyhpdGVtKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0TmV4dFNvcnRlZEJ5KGl0ZW06IEludGVybmFsQ29sdW1uRGVmKSB7XHJcbiAgICBzd2l0Y2ggKGl0ZW0uc29ydGVkQnkpIHtcclxuICAgICAgY2FzZSAnZGVmYXVsdCc6XHJcbiAgICAgICAgaXRlbS5zb3J0ZWRCeSA9ICdhc2MnO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlICdhc2MnOlxyXG4gICAgICAgIGl0ZW0uc29ydGVkQnkgPSAnZGVzYyc7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgJ2Rlc2MnOlxyXG4gICAgICAgIGl0ZW0uc29ydGVkQnkgPSAnZGVmYXVsdCc7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGluaXRVbmlxdWVJZEZvckRhdGFzb3VyY2UoKSB7XHJcbiAgICB0aGlzLmRhdGFzb3VyY2UuZm9yRWFjaChyb3cgPT4ge1xyXG4gICAgICByb3dbJ2R0X2lkJ10gPSB0aGlzLklEKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJvamVjdFRlbXBsYXRlKCkge1xyXG4gICAgaWYgKHRoaXMuY29sdW1uQ29tcG9uZW50cykge1xyXG4gICAgICB0aGlzLmNvbHVtbkNvbXBvbmVudHMuZm9yRWFjaChpdGVtID0+IHtcclxuICAgICAgICBpZiAoIXRoaXMucHJvamVjdGVkVGVtcGxhdGVzLmZpbmQoZiA9PiBmLm5hbWUgPT09IGl0ZW0ubmFtZSkpIHtcclxuICAgICAgICAgIHRoaXMucHJvamVjdGVkVGVtcGxhdGVzLnB1c2goeyBuYW1lOiBpdGVtLm5hbWUsIHRlbXBsYXRlOiBpdGVtLmNlbGxUZW1wbGF0ZSB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy5pbnRlcm5hbENvbHVtbnMuZm9yRWFjaChjb2x1bW4gPT4ge1xyXG4gICAgICAgIGNvbnN0IHByb2plY3RUZW1wbGF0ZSA9IHRoaXMucHJvamVjdGVkVGVtcGxhdGVzLmZpbmQoZiA9PiBmLm5hbWUgPT09IGNvbHVtbi5oZWFkZXJOYW1lKTtcclxuICAgICAgICBpZiAocHJvamVjdFRlbXBsYXRlKSB7XHJcbiAgICAgICAgICBjb2x1bW5bJ3RlbXBsYXRlJ10gPSBwcm9qZWN0VGVtcGxhdGUudGVtcGxhdGU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmhlYWRlckNvbXBvbmVudHMpIHtcclxuICAgICAgdGhpcy5oZWFkZXJDb21wb25lbnRzLmZvckVhY2goaXRlbSA9PiB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmhlYWRlclRlbXBsYXRlcy5maW5kKGYgPT4gZi5uYW1lID09PSBpdGVtLm5hbWUpKSB7XHJcbiAgICAgICAgICB0aGlzLmhlYWRlclRlbXBsYXRlcy5wdXNoKHsgbmFtZTogaXRlbS5uYW1lLCB0ZW1wbGF0ZTogaXRlbS5oZWFkZXJUZW1wbGF0ZSB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy5pbnRlcm5hbENvbHVtbnMuZm9yRWFjaChjb2x1bW4gPT4ge1xyXG4gICAgICAgIGNvbnN0IHByb2plY3RUZW1wbGF0ZSA9IHRoaXMuaGVhZGVyVGVtcGxhdGVzLmZpbmQoZiA9PiBmLm5hbWUgPT09IGNvbHVtbi5oZWFkZXJOYW1lKTtcclxuICAgICAgICBpZiAocHJvamVjdFRlbXBsYXRlKSB7XHJcbiAgICAgICAgICBjb2x1bW5bJ2hlYWRlclRlbXBsYXRlJ10gPSBwcm9qZWN0VGVtcGxhdGUudGVtcGxhdGU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgbWVyZ2VUb0ludGVybmFsQ29sdW1ucygpIHtcclxuICAgIGlmICh0aGlzLmludGVybmFsQ29sdW1ucy5sZW5ndGggPT09IDApIHtcclxuICAgICAgdGhpcy5pbnRlcm5hbENvbHVtbnMgPSBbLi4udGhpcy5jb2x1bW5zXTtcclxuICAgICAgdGhpcy5zZXRTb3J0ZWRCeVRvRGVmYXVsdCgpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5jb2x1bW5zLmZvckVhY2gocmVwbGFjZUNvbHVtbiA9PiB7XHJcbiAgICAgIGxldCBleGlzdENvbHVtbiA9IHRoaXMuaW50ZXJuYWxDb2x1bW5zLmZpbmQoZiA9PiBmLmhlYWRlck5hbWUgPT09IHJlcGxhY2VDb2x1bW4uaGVhZGVyTmFtZSk7XHJcbiAgICAgIGlmIChleGlzdENvbHVtbikge1xyXG4gICAgICAgIGV4aXN0Q29sdW1uID0geyAuLi5yZXBsYWNlQ29sdW1uIH07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5pbnRlcm5hbENvbHVtbnMucHVzaCh7IC4uLnJlcGxhY2VDb2x1bW4gfSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuc2V0U29ydGVkQnlUb0RlZmF1bHQoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0U29ydGVkQnlUb0RlZmF1bHQoKSB7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaW50ZXJuYWxDb2x1bW5zLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGlmICh0aGlzLmludGVybmFsQ29sdW1uc1tpXS5zb3J0KSB7XHJcbiAgICAgICAgdGhpcy5pbnRlcm5hbENvbHVtbnNbaV0uc29ydGVkQnkgPSAnZGVmYXVsdCc7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgSUQoKSB7XHJcbiAgICAvLyBNYXRoLnJhbmRvbSBzaG91bGQgYmUgdW5pcXVlIGJlY2F1c2Ugb2YgaXRzIHNlZWRpbmcgYWxnb3JpdGhtLlxyXG4gICAgLy8gQ29udmVydCBpdCB0byBiYXNlIDM2IChudW1iZXJzICsgbGV0dGVycyksIGFuZCBncmFiIHRoZSBmaXJzdCA5IGNoYXJhY3RlcnNcclxuICAgIC8vIGFmdGVyIHRoZSBkZWNpbWFsLlxyXG4gICAgcmV0dXJuICdfJyArIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cigyLCA5KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2VsZWN0QWxsKGlzU2VsZWN0OiBib29sZWFuKSB7XHJcbiAgICBjb25zdCBjb2xDaGsgPSB0aGlzLmludGVybmFsQ29sdW1ucy5maW5kKGYgPT4gZi5oZWFkZXJOYW1lID09PSAnY2hrJyk7XHJcbiAgICBpZiAoY29sQ2hrKSB7XHJcbiAgICAgIGNvbENoay5jaGVja2VkID0gaXNTZWxlY3Q7XHJcblxyXG4gICAgICB0aGlzLnNlbGVjdGVkUm93cyA9IFtdO1xyXG4gICAgICBpZiAodGhpcy5kYXRhc291cmNlICYmIHRoaXMuZGF0YXNvdXJjZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgdGhpcy5kYXRhc291cmNlLmZvckVhY2gocm93ID0+IHtcclxuICAgICAgICAgIHJvdy5jaGVja2VkID0gaXNTZWxlY3Q7XHJcbiAgICAgICAgICBpZiAoaXNTZWxlY3QpIHtcclxuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFJvd3MucHVzaChyb3cpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLm9uUm93c0NoZWNrZWQubmV4dCh0aGlzLnNlbGVjdGVkUm93cyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlc2V0T3RoZXJTb3J0ZWRDb2x1bW5zKGl0ZW06IEludGVybmFsQ29sdW1uRGVmKSB7XHJcbiAgICB0aGlzLmludGVybmFsQ29sdW1ucy5mb3JFYWNoKGNvbCA9PiB7XHJcbiAgICAgIGlmIChjb2wuaGVhZGVyTmFtZSAhPT0gaXRlbS5oZWFkZXJOYW1lICYmIGNvbC5zb3J0KSB7XHJcbiAgICAgICAgY29sLnNvcnRlZEJ5ID0gJ2RlZmF1bHQnO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uXHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29sdW1uRGVmIHtcclxuICAvKirliJflkI3np7AgKi9cclxuICBoZWFkZXJOYW1lOiBzdHJpbmc7XHJcbiAgLyoq5YiX5pi+56S65ZCN56ewICovXHJcbiAgaGVhZGVyRGlzcGxheU5hbWU6IHN0cmluZztcclxuICAvKirliJflrr3luqYgKi9cclxuICB3aWR0aD86IHN0cmluZztcclxuICBzb3J0PzogYm9vbGVhbjtcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpZ25vcmVcclxuICovXHJcbmludGVyZmFjZSBJbnRlcm5hbENvbHVtbkRlZiBleHRlbmRzIENvbHVtbkRlZiB7XHJcbiAgaXNDaGVja2JveD86IGJvb2xlYW47XHJcbiAgY2hlY2tlZD86IGJvb2xlYW47XHJcbiAgc29ydGVkQnk/OiAnZGVmYXVsdCcgfCAnYXNjJyB8ICdkZXNjJztcclxufVxyXG5cclxuIl19