sdk-datagrid
Version:
Customizable (Angular) datagrid with data options for manipulation, and charts for visualization.
109 lines • 40.1 kB
JavaScript
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { SDKDataGridMessage } from '../../models/datagrid-message';
import { Clone } from '../../utils/clone';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class SDKDataGridChartOptionComponent {
constructor() {
this.columns = [];
this.chart = "";
this.closeEvent = new EventEmitter();
this.applyEvent = new EventEmitter();
this.chartType = "bar";
this.columnLabel = "";
this.columnDataX = "";
this.columnDataY = "";
this.dataOption = false;
this._columns = [];
/**************************************************************************
* Message Variable
**************************************************************************/
this.showMessage = false;
this.message = new SDKDataGridMessage();
}
ngOnChanges(_args) {
this._columns = Clone.deepCopy(this.columns);
this.initialize();
}
initialize() {
this._columns = this._columns.filter((column) => column.isVisible && !column.isAction);
if (this.chart === "") {
this.chart = {
Type: "bar",
Show: false,
Label: "",
DataX: "",
DataY: "",
Option: false
};
}
this.chartType = this.chart.Type;
this.columnLabel = this.chart.Label;
this.columnDataX = this.chart.DataX;
this.columnDataY = this.chart.DataY;
this.dataOption = this.chart.Option;
}
getColumnOriginalName(column) {
let originalName = column.Name;
if (column.FriendlyName && column.FriendlyName !== "") {
originalName = column.FriendlyName;
}
else if (column.DisplayName && column.DisplayName !== "") {
originalName = column.DisplayName;
}
return originalName;
}
getValue(event) {
return event.target.value;
}
reset() {
this.message = {
Title: "Reset Chart",
Text: "Are you sure?",
OKText: "YES",
CancelText: "NO",
OK: () => {
this.chart = "";
this.initialize();
},
Cancel: () => {
this.showMessage = false;
}
};
this.showMessage = true;
}
apply() {
let show = true;
if (['bar', 'line', 'radar'].indexOf(this.chartType) > -1 && (this.columnLabel === "" || this.columnDataX === "" || this.columnDataY === ""))
show = false;
if (['doughnut', 'pie', 'polarArea'].indexOf(this.chartType) > -1 && (this.columnLabel === "" || this.columnDataY === ""))
show = false;
this.chart = {
Type: this.chartType,
Show: show,
Label: this.columnLabel,
DataX: this.columnDataX,
DataY: this.columnDataY,
Option: this.dataOption
};
this.applyEvent.emit(this.chart);
}
close() {
this.closeEvent.emit();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SDKDataGridChartOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SDKDataGridChartOptionComponent, selector: "sdk-datagrid-chart-option", inputs: { columns: "columns", chart: "chart" }, outputs: { closeEvent: "closeEvent", applyEvent: "applyEvent" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"sdk-datagrid-window\">\r\n <div class=\"header\">\r\n <span class=\"title\">Chart</span>\r\n <span title=\"Close\" class=\"sdk-icon close\" (click)=\"close()\">close</span>\r\n </div>\r\n <div class=\"content no-actions\">\r\n <div class=\"no-box\">\r\n <div class=\"section\">\r\n <span>Chart Type</span>\r\n <select class=\"column\" (change)=\"chartType = getValue($event)\">\r\n <option value=\"bar\" [selected]=\"(chartType === 'bar') ? 'selected' : ''\">Bar</option>\r\n <option value=\"doughnut\" [selected]=\"(chartType === 'doughnut') ? 'selected' : ''\">Doughnut</option>\r\n <option value=\"line\" [selected]=\"(chartType === 'line') ? 'selected' : ''\">Line</option>\r\n <option value=\"pie\" [selected]=\"(chartType === 'pie') ? 'selected' : ''\">Pie</option>\r\n <option value=\"polarArea\" [selected]=\"(chartType === 'polarArea') ? 'selected' : ''\">Polar Area</option>\r\n <option value=\"radar\" [selected]=\"(chartType === 'radar') ? 'selected' : ''\">Radar</option>\r\n </select>\r\n </div>\r\n <div class=\"section\">\r\n <span *ngIf=\"['bar', 'line', 'radar'].indexOf(chartType) > -1\">Column for Grouping</span>\r\n <span *ngIf=\"['doughnut', 'pie', 'polarArea'].indexOf(chartType) > -1\">Column for Sections</span>\r\n <select class=\"column\" (change)=\"columnLabel = getValue($event)\">\r\n <option selected value=\"\"></option>\r\n <ng-container *ngFor=\"let column of _columns\">\r\n <option [value]=\"column.Name\" [selected]=\"(columnLabel === column.Name) ? 'selected' : ''\">{{ getColumnOriginalName(column) }}</option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div *ngIf=\"['bar', 'line', 'radar'].indexOf(chartType) > -1\" class=\"section\">\r\n <span>Column for X-Axis (Bottom)</span>\r\n <span class=\"note\">(typically a timespan)</span>\r\n <select class=\"column\" (change)=\"columnDataX = getValue($event)\">\r\n <option selected value=\"\"></option>\r\n <ng-container *ngFor=\"let column of _columns\">\r\n <option [value]=\"column.Name\" [selected]=\"(columnDataX === column.Name) ? 'selected' : ''\">{{ getColumnOriginalName(column) }}</option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div class=\"section\">\r\n <div *ngIf=\"['bar', 'line', 'radar'].indexOf(chartType) > -1\">\r\n <span>Column for Y-Axis (Left Side)</span>\r\n <span class=\"note\">(typically a number)</span>\r\n </div>\r\n <div *ngIf=\"['doughnut', 'pie', 'polarArea'].indexOf(chartType) > -1\">\r\n <span>Column to Summarize</span>\r\n <span class=\"note\">(must be a number)</span>\r\n </div>\r\n <select class=\"column\" (change)=\"columnDataY = getValue($event)\">\r\n <option selected value=\"\"></option>\r\n <ng-container *ngFor=\"let column of _columns\">\r\n <option [value]=\"column.Name\" [selected]=\"(columnDataY === column.Name) ? 'selected' : ''\">{{ getColumnOriginalName(column) }}</option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div *ngIf=\"['bar'].indexOf(chartType) > -1\" class=\"section\">\r\n <div style=\"display: inline-block;\">\r\n <span class=\"data-label\" (click)=\"dataOption = !dataOption\">Stack Data?</span>\r\n <input class=\"data-option\" type=\"checkbox\" [checked]=\"dataOption\" (change)=\"dataOption = !dataOption\">\r\n </div>\r\n </div>\r\n <div *ngIf=\"['line'].indexOf(chartType) > -1\" class=\"section\">\r\n <div style=\"display: inline-block;\">\r\n <span class=\"data-label\" (click)=\"dataOption = !dataOption\">Fill Data?</span>\r\n <input class=\"data-option\" type=\"checkbox\" [checked]=\"dataOption\" (change)=\"dataOption = !dataOption\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"footer\">\r\n <button class=\"sdk-button delete\" (click)=\"reset()\">Reset</button>\r\n <button class=\"sdk-button\" (click)=\"apply()\">Apply</button>\r\n </div>\r\n</div>\r\n\r\n<!-- Lock -->\r\n<div *ngIf=\"showMessage\" title=\"\" class=\"sdk-datagrid-windows-lock\"></div>\r\n\r\n<!-- Message -->\r\n<div *ngIf=\"showMessage\" title=\"\" class=\"sdk-datagrid-message\">\r\n <div class=\"title\">{{ message.Title }}</div>\r\n <div class=\"text\" [innerHtml]=\"message.Text\"></div>\r\n <div class=\"action\">\r\n <button class=\"sdk-button\" (click)=\"message.OK()\">{{ message.OKText }}</button>\r\n <button class=\"sdk-button cancel\" (click)=\"message.Cancel()\">{{ message.CancelText }}</button>\r\n </div>\r\n</div>\r\n", styles: [".sdk-datagrid-window{position:absolute;inset:10px;overflow:hidden}.sdk-datagrid-window .header{position:absolute;top:0;right:0;left:0;height:50px}.sdk-datagrid-window .header .title{position:absolute;top:0;left:0;font-size:large;font-weight:600}.sdk-datagrid-window .header .sdk-icon.close{position:absolute;top:0;right:0}.sdk-datagrid-window .actions{position:absolute;top:50px;right:0;left:0;margin-top:5px;height:50px;width:100%}.sdk-datagrid-window .actions .button-left{float:left;margin:0}.sdk-datagrid-window .actions .button-right{float:right;margin:0 5px 0 0}.sdk-datagrid-window .content{position:absolute;inset:100px 0 50px;border:1px solid var(--sdk-border-dark);display:block;background:var(--sdk-white);border-radius:4px;margin-top:0;overflow:auto;text-align:left}.sdk-datagrid-window .content.no-actions{top:50px}.sdk-datagrid-window .content .keyword{position:relative;padding:5px 10px}.sdk-datagrid-window .content .no-box{position:relative;background-color:var(--sdk-white);text-align:left;margin:4px;box-sizing:border-box;cursor:default}.sdk-datagrid-window .content .no-box input{border-radius:unset;border-width:unset;margin:unset;padding:unset;width:unset}.sdk-datagrid-window .content .no-box input.data-option{padding:0;margin:0 5px 0 0;vertical-align:middle;cursor:pointer}.sdk-datagrid-window .content .no-box .data-label{padding:0;margin:0 10px 0 0;display:inline;vertical-align:middle;text-transform:uppercase;font-weight:600;font-size:small;cursor:pointer}.sdk-datagrid-window .content .box{position:relative;border:1px solid var(--sdk-border);background-color:var(--sdk-white);text-align:left;margin:4px;box-sizing:border-box;cursor:default}.sdk-datagrid-window .content .cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.sdk-datagrid-window .content .cdk-drag-placeholder{opacity:0}.sdk-datagrid-window .content .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.sdk-datagrid-window .content .list.cdk-drop-list-dragging .box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.sdk-datagrid-window .content .section{margin:10px 10px 20px}.sdk-datagrid-window .content .section span{margin-bottom:5px;display:block;font-weight:600}.sdk-datagrid-window .content .section .column{display:block;padding:5px;width:100%}.sdk-datagrid-window .content .section .note{margin:-10px 0 5px;font-size:small;font-style:italic;font-weight:400}.sdk-datagrid-window .content .no-records{height:100%;width:100%;display:table;text-align:center;align-items:center}.sdk-datagrid-window .content .no-records span{display:table-cell;vertical-align:middle;font-size:large;font-weight:600;color:var(--sdk-red)}.sdk-datagrid-window .content .error{display:table;text-align:left;vertical-align:top;padding:20px;color:var(--sdk-red)}.sdk-datagrid-window .footer{position:absolute;right:0;left:0;bottom:0;height:40px;width:100%;text-align:center}.sdk-datagrid-window input,.sdk-datagrid-window select{border-radius:5px;border-width:.5px;margin:0;padding:5px;width:100%}.sdk-datagrid-window input:hover,.sdk-datagrid-window select:hover{border-width:1px}.sdk-datagrid-windows-lock{position:absolute;inset:0;z-index:8;overflow:hidden;background-color:var(--sdk-black);opacity:.33}.sdk-datagrid-message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);height:200px;width:300px;background-color:var(--sdk-white);border-top:.5px solid var(--sdk-gray);border-left:.5px solid var(--sdk-gray);border-bottom:.5px solid var(--sdk-gray);box-shadow:5px 5px 10px #606060;z-index:10}.sdk-datagrid-message .title{position:absolute;top:0;left:0;right:0;height:50px;padding-top:10px;color:var(--sdk-blue);font-size:1.5em;font-weight:600;text-align:center}.sdk-datagrid-message .text{position:absolute;inset:50px 0;padding:0 10px;text-align:center}.sdk-datagrid-message .action{position:absolute;left:0;right:0;bottom:0;height:50px;text-align:center}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SDKDataGridChartOptionComponent, decorators: [{
type: Component,
args: [{ selector: 'sdk-datagrid-chart-option', template: "<div class=\"sdk-datagrid-window\">\r\n <div class=\"header\">\r\n <span class=\"title\">Chart</span>\r\n <span title=\"Close\" class=\"sdk-icon close\" (click)=\"close()\">close</span>\r\n </div>\r\n <div class=\"content no-actions\">\r\n <div class=\"no-box\">\r\n <div class=\"section\">\r\n <span>Chart Type</span>\r\n <select class=\"column\" (change)=\"chartType = getValue($event)\">\r\n <option value=\"bar\" [selected]=\"(chartType === 'bar') ? 'selected' : ''\">Bar</option>\r\n <option value=\"doughnut\" [selected]=\"(chartType === 'doughnut') ? 'selected' : ''\">Doughnut</option>\r\n <option value=\"line\" [selected]=\"(chartType === 'line') ? 'selected' : ''\">Line</option>\r\n <option value=\"pie\" [selected]=\"(chartType === 'pie') ? 'selected' : ''\">Pie</option>\r\n <option value=\"polarArea\" [selected]=\"(chartType === 'polarArea') ? 'selected' : ''\">Polar Area</option>\r\n <option value=\"radar\" [selected]=\"(chartType === 'radar') ? 'selected' : ''\">Radar</option>\r\n </select>\r\n </div>\r\n <div class=\"section\">\r\n <span *ngIf=\"['bar', 'line', 'radar'].indexOf(chartType) > -1\">Column for Grouping</span>\r\n <span *ngIf=\"['doughnut', 'pie', 'polarArea'].indexOf(chartType) > -1\">Column for Sections</span>\r\n <select class=\"column\" (change)=\"columnLabel = getValue($event)\">\r\n <option selected value=\"\"></option>\r\n <ng-container *ngFor=\"let column of _columns\">\r\n <option [value]=\"column.Name\" [selected]=\"(columnLabel === column.Name) ? 'selected' : ''\">{{ getColumnOriginalName(column) }}</option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div *ngIf=\"['bar', 'line', 'radar'].indexOf(chartType) > -1\" class=\"section\">\r\n <span>Column for X-Axis (Bottom)</span>\r\n <span class=\"note\">(typically a timespan)</span>\r\n <select class=\"column\" (change)=\"columnDataX = getValue($event)\">\r\n <option selected value=\"\"></option>\r\n <ng-container *ngFor=\"let column of _columns\">\r\n <option [value]=\"column.Name\" [selected]=\"(columnDataX === column.Name) ? 'selected' : ''\">{{ getColumnOriginalName(column) }}</option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div class=\"section\">\r\n <div *ngIf=\"['bar', 'line', 'radar'].indexOf(chartType) > -1\">\r\n <span>Column for Y-Axis (Left Side)</span>\r\n <span class=\"note\">(typically a number)</span>\r\n </div>\r\n <div *ngIf=\"['doughnut', 'pie', 'polarArea'].indexOf(chartType) > -1\">\r\n <span>Column to Summarize</span>\r\n <span class=\"note\">(must be a number)</span>\r\n </div>\r\n <select class=\"column\" (change)=\"columnDataY = getValue($event)\">\r\n <option selected value=\"\"></option>\r\n <ng-container *ngFor=\"let column of _columns\">\r\n <option [value]=\"column.Name\" [selected]=\"(columnDataY === column.Name) ? 'selected' : ''\">{{ getColumnOriginalName(column) }}</option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div *ngIf=\"['bar'].indexOf(chartType) > -1\" class=\"section\">\r\n <div style=\"display: inline-block;\">\r\n <span class=\"data-label\" (click)=\"dataOption = !dataOption\">Stack Data?</span>\r\n <input class=\"data-option\" type=\"checkbox\" [checked]=\"dataOption\" (change)=\"dataOption = !dataOption\">\r\n </div>\r\n </div>\r\n <div *ngIf=\"['line'].indexOf(chartType) > -1\" class=\"section\">\r\n <div style=\"display: inline-block;\">\r\n <span class=\"data-label\" (click)=\"dataOption = !dataOption\">Fill Data?</span>\r\n <input class=\"data-option\" type=\"checkbox\" [checked]=\"dataOption\" (change)=\"dataOption = !dataOption\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"footer\">\r\n <button class=\"sdk-button delete\" (click)=\"reset()\">Reset</button>\r\n <button class=\"sdk-button\" (click)=\"apply()\">Apply</button>\r\n </div>\r\n</div>\r\n\r\n<!-- Lock -->\r\n<div *ngIf=\"showMessage\" title=\"\" class=\"sdk-datagrid-windows-lock\"></div>\r\n\r\n<!-- Message -->\r\n<div *ngIf=\"showMessage\" title=\"\" class=\"sdk-datagrid-message\">\r\n <div class=\"title\">{{ message.Title }}</div>\r\n <div class=\"text\" [innerHtml]=\"message.Text\"></div>\r\n <div class=\"action\">\r\n <button class=\"sdk-button\" (click)=\"message.OK()\">{{ message.OKText }}</button>\r\n <button class=\"sdk-button cancel\" (click)=\"message.Cancel()\">{{ message.CancelText }}</button>\r\n </div>\r\n</div>\r\n", styles: [".sdk-datagrid-window{position:absolute;inset:10px;overflow:hidden}.sdk-datagrid-window .header{position:absolute;top:0;right:0;left:0;height:50px}.sdk-datagrid-window .header .title{position:absolute;top:0;left:0;font-size:large;font-weight:600}.sdk-datagrid-window .header .sdk-icon.close{position:absolute;top:0;right:0}.sdk-datagrid-window .actions{position:absolute;top:50px;right:0;left:0;margin-top:5px;height:50px;width:100%}.sdk-datagrid-window .actions .button-left{float:left;margin:0}.sdk-datagrid-window .actions .button-right{float:right;margin:0 5px 0 0}.sdk-datagrid-window .content{position:absolute;inset:100px 0 50px;border:1px solid var(--sdk-border-dark);display:block;background:var(--sdk-white);border-radius:4px;margin-top:0;overflow:auto;text-align:left}.sdk-datagrid-window .content.no-actions{top:50px}.sdk-datagrid-window .content .keyword{position:relative;padding:5px 10px}.sdk-datagrid-window .content .no-box{position:relative;background-color:var(--sdk-white);text-align:left;margin:4px;box-sizing:border-box;cursor:default}.sdk-datagrid-window .content .no-box input{border-radius:unset;border-width:unset;margin:unset;padding:unset;width:unset}.sdk-datagrid-window .content .no-box input.data-option{padding:0;margin:0 5px 0 0;vertical-align:middle;cursor:pointer}.sdk-datagrid-window .content .no-box .data-label{padding:0;margin:0 10px 0 0;display:inline;vertical-align:middle;text-transform:uppercase;font-weight:600;font-size:small;cursor:pointer}.sdk-datagrid-window .content .box{position:relative;border:1px solid var(--sdk-border);background-color:var(--sdk-white);text-align:left;margin:4px;box-sizing:border-box;cursor:default}.sdk-datagrid-window .content .cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.sdk-datagrid-window .content .cdk-drag-placeholder{opacity:0}.sdk-datagrid-window .content .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.sdk-datagrid-window .content .list.cdk-drop-list-dragging .box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.sdk-datagrid-window .content .section{margin:10px 10px 20px}.sdk-datagrid-window .content .section span{margin-bottom:5px;display:block;font-weight:600}.sdk-datagrid-window .content .section .column{display:block;padding:5px;width:100%}.sdk-datagrid-window .content .section .note{margin:-10px 0 5px;font-size:small;font-style:italic;font-weight:400}.sdk-datagrid-window .content .no-records{height:100%;width:100%;display:table;text-align:center;align-items:center}.sdk-datagrid-window .content .no-records span{display:table-cell;vertical-align:middle;font-size:large;font-weight:600;color:var(--sdk-red)}.sdk-datagrid-window .content .error{display:table;text-align:left;vertical-align:top;padding:20px;color:var(--sdk-red)}.sdk-datagrid-window .footer{position:absolute;right:0;left:0;bottom:0;height:40px;width:100%;text-align:center}.sdk-datagrid-window input,.sdk-datagrid-window select{border-radius:5px;border-width:.5px;margin:0;padding:5px;width:100%}.sdk-datagrid-window input:hover,.sdk-datagrid-window select:hover{border-width:1px}.sdk-datagrid-windows-lock{position:absolute;inset:0;z-index:8;overflow:hidden;background-color:var(--sdk-black);opacity:.33}.sdk-datagrid-message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);height:200px;width:300px;background-color:var(--sdk-white);border-top:.5px solid var(--sdk-gray);border-left:.5px solid var(--sdk-gray);border-bottom:.5px solid var(--sdk-gray);box-shadow:5px 5px 10px #606060;z-index:10}.sdk-datagrid-message .title{position:absolute;top:0;left:0;right:0;height:50px;padding-top:10px;color:var(--sdk-blue);font-size:1.5em;font-weight:600;text-align:center}.sdk-datagrid-message .text{position:absolute;inset:50px 0;padding:0 10px;text-align:center}.sdk-datagrid-message .action{position:absolute;left:0;right:0;bottom:0;height:50px;text-align:center}\n"] }]
}], propDecorators: { columns: [{
type: Input
}], chart: [{
type: Input
}], closeEvent: [{
type: Output
}], applyEvent: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQtb3B0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3Nkay1kYXRhZ3JpZC9zcmMvbGliL29wdGlvbnMvY2hhcnQvY2hhcnQtb3B0aW9uLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3Nkay1kYXRhZ3JpZC9zcmMvbGliL29wdGlvbnMvY2hhcnQvY2hhcnQtb3B0aW9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHL0UsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFbkUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLG1CQUFtQixDQUFDOzs7QUFRMUMsTUFBTSxPQUFPLCtCQUErQjtJQU41QztRQU9hLFlBQU8sR0FBd0IsRUFBRSxDQUFDO1FBQ2xDLFVBQUssR0FBUSxFQUFFLENBQUM7UUFDZixlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNoQyxlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUVuQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLGdCQUFXLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLGdCQUFXLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLGdCQUFXLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFFaEIsYUFBUSxHQUF3QixFQUFFLENBQUM7UUFFN0M7O21GQUUyRTtRQUNqRSxnQkFBVyxHQUFZLEtBQUssQ0FBQztRQUM3QixZQUFPLEdBQXVCLElBQUksa0JBQWtCLEVBQUUsQ0FBQztLQXFGcEU7SUFuRlUsV0FBVyxDQUFDLEtBQVU7UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFB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QVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsS0FBSyxFQUFFLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxFQUFFLENBQUM7WUFBRSxJQUFJLEdBQUcsS0FBSyxDQUFDO1FBRXhJLElBQUksQ0FBQyxLQUFLLEdBQUc7WUFDVCxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDcEIsSUFBSSxFQUFFLElBQUk7WUFDVixLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDdkIsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXO1lBQ3ZCLEtBQUssRUFBRSxJQUFJLENBQUMsV0FBVztZQUN2QixNQUFNLEVBQUUsSUFBSSxDQUFDLFVBQVU7U0FDMUIsQ0FBQztRQUVGLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRU0sS0FBSztRQUNSLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDM0IsQ0FBQzsrR0F0R1EsK0JBQStCO21HQUEvQiwrQkFBK0IsdU1DYjVDLG13S0FzRkE7OzRGRHpFYSwrQkFBK0I7a0JBTjNDLFNBQVM7K0JBQ0ksMkJBQTJCOzhCQU01QixPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLO2dCQUNJLFVBQVU7c0JBQW5CLE1BQU07Z0JBQ0csVUFBVTtzQkFBbkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25Jbml0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCB7IFNES0RhdGFHcmlkQ29sdW1uIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2RhdGFncmlkLWNvbHVtbic7XHJcbmltcG9ydCB7IFNES0RhdGFHcmlkTWVzc2FnZSB9IGZyb20gJy4uLy4uL21vZGVscy9kYXRhZ3JpZC1tZXNzYWdlJztcclxuXHJcbmltcG9ydCB7IENsb25lIH0gZnJvbSAnLi4vLi4vdXRpbHMvY2xvbmUnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3Nkay1kYXRhZ3JpZC1jaGFydC1vcHRpb24nLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL2NoYXJ0LW9wdGlvbi5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybHM6IFsnLi9jaGFydC1vcHRpb24uY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5cclxuZXhwb3J0IGNsYXNzIFNES0RhdGFHcmlkQ2hhcnRPcHRpb25Db21wb25lbnQge1xyXG4gICAgQElucHV0KCkgY29sdW1uczogU0RLRGF0YUdyaWRDb2x1bW5bXSA9IFtdO1xyXG4gICAgQElucHV0KCkgY2hhcnQ6IGFueSA9IFwiXCI7XHJcbiAgICBAT3V0cHV0KCkgY2xvc2VFdmVudCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuICAgIEBPdXRwdXQoKSBhcHBseUV2ZW50ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xyXG5cclxuICAgIHB1YmxpYyBjaGFydFR5cGUgPSBcImJhclwiO1xyXG4gICAgcHVibGljIGNvbHVtbkxhYmVsID0gXCJcIjtcclxuICAgIHB1YmxpYyBjb2x1bW5EYXRhWCA9IFwiXCI7XHJcbiAgICBwdWJsaWMgY29sdW1uRGF0YVkgPSBcIlwiO1xyXG4gICAgcHVibGljIGRhdGFPcHRpb24gPSBmYWxzZTtcclxuXHJcbiAgICBwcm90ZWN0ZWQgX2NvbHVtbnM6IFNES0RhdGFHcmlkQ29sdW1uW10gPSBbXTtcclxuXHJcbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICogTWVzc2FnZSBWYXJpYWJsZVxyXG4gICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcbiAgICBwcm90ZWN0ZWQgc2hvd01lc3NhZ2U6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIHByb3RlY3RlZCBtZXNzYWdlOiBTREtEYXRhR3JpZE1lc3NhZ2UgPSBuZXcgU0RLRGF0YUdyaWRNZXNzYWdlKCk7XHJcblxyXG4gICAgcHVibGljIG5nT25DaGFuZ2VzKF9hcmdzOiBhbnkpIHtcclxuICAgICAgICB0aGlzLl9jb2x1bW5zID0gQ2xvbmUuZGVlcENvcHkodGhpcy5jb2x1bW5zKTtcclxuXHJcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBpbml0aWFsaXplKCkge1xyXG4gICAgICAgIHRoaXMuX2NvbHVtbnMgPSB0aGlzLl9jb2x1bW5zLmZpbHRlcigoY29sdW1uOiBTREtEYXRhR3JpZENvbHVtbikgPT4gY29sdW1uLmlzVmlzaWJsZSAmJiAhY29sdW1uLmlzQWN0aW9uKTtcclxuICAgICAgICBcclxuICAgICAgICBpZiAodGhpcy5jaGFydCA9PT0gXCJcIikge1xyXG4gICAgICAgICAgICB0aGlzLmNoYXJ0ID0ge1xyXG4gICAgICAgICAgICAgICAgVHlwZTogXCJiYXJcIixcclxuICAgICAgICAgICAgICAgIFNob3c6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgTGFiZWw6IFwiXCIsXHJcbiAgICAgICAgICAgICAgICBEYXRhWDogXCJcIixcclxuICAgICAgICAgICAgICAgIERhdGFZOiBcIlwiLFxyXG4gICAgICAgICAgICAgICAgT3B0aW9uOiBmYWxzZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5jaGFydFR5cGUgPSB0aGlzLmNoYXJ0LlR5cGU7XHJcbiAgICAgICAgdGhpcy5jb2x1bW5MYWJlbCA9IHRoaXMuY2hhcnQuTGFiZWw7XHJcbiAgICAgICAgdGhpcy5jb2x1bW5EYXRhWCA9IHRoaXMuY2hhcnQuRGF0YVg7XHJcbiAgICAgICAgdGhpcy5jb2x1bW5EYXRhWSA9IHRoaXMuY2hhcnQuRGF0YVk7XHJcbiAgICAgICAgdGhpcy5kYXRhT3B0aW9uID0gdGhpcy5jaGFydC5PcHRpb247XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldENvbHVtbk9yaWdpbmFsTmFtZShjb2x1bW46IFNES0RhdGFHcmlkQ29sdW1uKSB7XHJcbiAgICAgICAgbGV0IG9yaWdpbmFsTmFtZSA9IGNvbHVtbi5OYW1lO1xyXG5cclxuICAgICAgICBpZiAoY29sdW1uLkZyaWVuZGx5TmFtZSAmJiBjb2x1bW4uRnJpZW5kbHlOYW1lICE9PSBcIlwiKSB7XHJcbiAgICAgICAgICAgIG9yaWdpbmFsTmFtZSA9IGNvbHVtbi5GcmllbmRseU5hbWU7XHJcbiAgICAgICAgfSBlbHNlIGlmIChjb2x1bW4uRGlzcGxheU5hbWUgJiYgY29sdW1uLkRpc3BsYXlOYW1lICE9PSBcIlwiKSB7XHJcbiAgICAgICAgICAgIG9yaWdpbmFsTmFtZSA9IGNvbHVtbi5EaXNwbGF5TmFtZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBvcmlnaW5hbE5hbWU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldFZhbHVlKGV2ZW50OiBhbnkpIHtcclxuICAgICAgICByZXR1cm4gZXZlbnQudGFyZ2V0LnZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyByZXNldCgpIHtcclxuICAgICAgICB0aGlzLm1lc3NhZ2UgPSB7XHJcbiAgICAgICAgICAgIFRpdGxlOiBcIlJlc2V0IENoYXJ0XCIsXHJcbiAgICAgICAgICAgIFRleHQ6IFwiQXJlIHlvdSBzdXJlP1wiLFxyXG4gICAgICAgICAgICBPS1RleHQ6IFwiWUVTXCIsXHJcbiAgICAgICAgICAgIENhbmNlbFRleHQ6IFwiTk9cIixcclxuICAgICAgICAgICAgT0s6ICgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2hhcnQgPSBcIlwiO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBDYW5jZWw6ICgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2hvd01lc3NhZ2UgPSBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuc2hvd01lc3NhZ2UgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhcHBseSgpIHtcclxuICAgICAgICBsZXQgc2hvdyA9IHRydWU7XHJcblxyXG4gICAgICAgIGlmIChbJ2JhcicsICdsaW5lJywgJ3JhZGFyJ10uaW5kZXhPZih0aGlzLmNoYXJ0VHlwZSkgPiAtMSAmJiAodGhpcy5jb2x1bW5MYWJlbCA9PT0gXCJcIiB8fCB0aGlzLmNvbHVtbkRhdGFYID09PSBcIlwiIHx8IHRoaXMuY29sdW1uRGF0YVkgPT09IFwiXCIpKSBzaG93ID0gZmFsc2U7XHJcbiAgICAgICAgaWYgKFsnZG91Z2hudXQnLCAncGllJywgJ3BvbGFyQXJlYSddLmluZGV4T2YodGhpcy5jaGFydFR5cGUpID4gLTEgJiYgKHRoaXMuY29sdW1uTGFiZWwgPT09IFwiXCIgfHwgdGhpcy5jb2x1bW5EYXRhWSA9PT0gXCJcIikpIHNob3cgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgdGhpcy5jaGFydCA9IHtcclxuICAgICAgICAgICAgVHlwZTogdGhpcy5jaGFydFR5cGUsXHJcbiAgICAgICAgICAgIFNob3c6IHNob3csXHJcbiAgICAgICAgICAgIExhYmVsOiB0aGlzLmNvbHVtbkxhYmVsLFxyXG4gICAgICAgICAgICBEYXRhWDogdGhpcy5jb2x1bW5EYXRhWCxcclxuICAgICAgICAgICAgRGF0YVk6IHRoaXMuY29sdW1uRGF0YVksXHJcbiAgICAgICAgICAgIE9wdGlvbjogdGhpcy5kYXRhT3B0aW9uXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5hcHBseUV2ZW50LmVtaXQodGhpcy5jaGFydCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGNsb3NlKCkge1xyXG4gICAgICAgIHRoaXMuY2xvc2VFdmVudC5lbWl0KCk7XHJcbiAgICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cInNkay1kYXRhZ3JpZC13aW5kb3dcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJoZWFkZXJcIj5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cInRpdGxlXCI+Q2hhcnQ8L3NwYW4+XHJcbiAgICAgICAgPHNwYW4gdGl0bGU9XCJDbG9zZVwiIGNsYXNzPVwic2RrLWljb24gY2xvc2VcIiAoY2xpY2spPVwiY2xvc2UoKVwiPmNsb3NlPC9zcGFuPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29udGVudCBuby1hY3Rpb25zXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cIm5vLWJveFwiPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VjdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4+Q2hhcnQgVHlwZTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9XCJjb2x1bW5cIiAoY2hhbmdlKT1cImNoYXJ0VHlwZSA9IGdldFZhbHVlKCRldmVudClcIj5cclxuICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwiYmFyXCIgW3NlbGVjdGVkXT1cIihjaGFydFR5cGUgPT09ICdiYXInKSA/ICdzZWxlY3RlZCcgOiAnJ1wiPkJhcjwvb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9XCJkb3VnaG51dFwiIFtzZWxlY3RlZF09XCIoY2hhcnRUeXBlID09PSAnZG91Z2hudXQnKSA/ICdzZWxlY3RlZCcgOiAnJ1wiPkRvdWdobnV0PC9vcHRpb24+XHJcbiAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cImxpbmVcIiBbc2VsZWN0ZWRdPVwiKGNoYXJ0VHlwZSA9PT0gJ2xpbmUnKSA/ICdzZWxlY3RlZCcgOiAnJ1wiPkxpbmU8L29wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwicGllXCIgW3NlbGVjdGVkXT1cIihjaGFydFR5cGUgPT09ICdwaWUnKSA/ICdzZWxlY3RlZCcgOiAnJ1wiPlBpZTwvb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9XCJwb2xhckFyZWFcIiBbc2VsZWN0ZWRdPVwiKGNoYXJ0VHlwZSA9PT0gJ3BvbGFyQXJlYScpID8gJ3NlbGVjdGVkJyA6ICcnXCI+UG9sYXIgQXJlYTwvb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9XCJyYWRhclwiIFtzZWxlY3RlZF09XCIoY2hhcnRUeXBlID09PSAncmFkYXInKSA/ICdzZWxlY3RlZCcgOiAnJ1wiPlJhZGFyPC9vcHRpb24+XHJcbiAgICAgICAgICAgICAgICA8L3NlbGVjdD5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uXCI+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIlsnYmFyJywgJ2xpbmUnLCAncmFkYXInXS5pbmRleE9mKGNoYXJ0VHlwZSkgPiAtMVwiPkNvbHVtbiBmb3IgR3JvdXBpbmc8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIlsnZG91Z2hudXQnLCAncGllJywgJ3BvbGFyQXJlYSddLmluZGV4T2YoY2hhcnRUeXBlKSA+IC0xXCI+Q29sdW1uIGZvciBTZWN0aW9uczwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9XCJjb2x1bW5cIiAoY2hhbmdlKT1cImNvbHVtbkxhYmVsID0gZ2V0VmFsdWUoJGV2ZW50KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxvcHRpb24gc2VsZWN0ZWQgdmFsdWU9XCJcIj48L29wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgX2NvbHVtbnNcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiY29sdW1uLk5hbWVcIiBbc2VsZWN0ZWRdPVwiKGNvbHVtbkxhYmVsID09PSBjb2x1bW4uTmFtZSkgPyAnc2VsZWN0ZWQnIDogJydcIj57eyBnZXRDb2x1bW5PcmlnaW5hbE5hbWUoY29sdW1uKSAgfX08L29wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIlsnYmFyJywgJ2xpbmUnLCAncmFkYXInXS5pbmRleE9mKGNoYXJ0VHlwZSkgPiAtMVwiIGNsYXNzPVwic2VjdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4+Q29sdW1uIGZvciBYLUF4aXMgKEJvdHRvbSk8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5vdGVcIj4odHlwaWNhbGx5IGEgdGltZXNwYW4pPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz1cImNvbHVtblwiIChjaGFuZ2UpPVwiY29sdW1uRGF0YVggPSBnZXRWYWx1ZSgkZXZlbnQpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBzZWxlY3RlZCB2YWx1ZT1cIlwiPjwvb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGNvbHVtbiBvZiBfY29sdW1uc1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCJjb2x1bW4uTmFtZVwiIFtzZWxlY3RlZF09XCIoY29sdW1uRGF0YVggPT09IGNvbHVtbi5OYW1lKSA/ICdzZWxlY3RlZCcgOiAnJ1wiPnt7IGdldENvbHVtbk9yaWdpbmFsTmFtZShjb2x1bW4pIH19PC9vcHRpb24+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8L3NlbGVjdD5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiWydiYXInLCAnbGluZScsICdyYWRhciddLmluZGV4T2YoY2hhcnRUeXBlKSA+IC0xXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+Q29sdW1uIGZvciBZLUF4aXMgKExlZnQgU2lkZSk8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJub3RlXCI+KHR5cGljYWxseSBhIG51bWJlcik8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJbJ2RvdWdobnV0JywgJ3BpZScsICdwb2xhckFyZWEnXS5pbmRleE9mKGNoYXJ0VHlwZSkgPiAtMVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxzcGFuPkNvbHVtbiB0byBTdW1tYXJpemU8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJub3RlXCI+KG11c3QgYmUgYSBudW1iZXIpPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwiY29sdW1uXCIgKGNoYW5nZSk9XCJjb2x1bW5EYXRhWSA9IGdldFZhbHVlKCRldmVudClcIj5cclxuICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHNlbGVjdGVkIHZhbHVlPVwiXCI+PC9vcHRpb24+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgY29sdW1uIG9mIF9jb2x1bW5zXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cImNvbHVtbi5OYW1lXCIgW3NlbGVjdGVkXT1cIihjb2x1bW5EYXRhWSA9PT0gY29sdW1uLk5hbWUpID8gJ3NlbGVjdGVkJyA6ICcnXCI+e3sgZ2V0Q29sdW1uT3JpZ2luYWxOYW1lKGNvbHVtbikgfX08L29wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIlsnYmFyJ10uaW5kZXhPZihjaGFydFR5cGUpID4gLTFcIiBjbGFzcz1cInNlY3Rpb25cIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkYXRhLWxhYmVsXCIgKGNsaWNrKT1cImRhdGFPcHRpb24gPSAhZGF0YU9wdGlvblwiPlN0YWNrIERhdGE/PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImRhdGEtb3B0aW9uXCIgdHlwZT1cImNoZWNrYm94XCIgW2NoZWNrZWRdPVwiZGF0YU9wdGlvblwiIChjaGFuZ2UpPVwiZGF0YU9wdGlvbiA9ICFkYXRhT3B0aW9uXCI+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJbJ2xpbmUnXS5pbmRleE9mKGNoYXJ0VHlwZSkgPiAtMVwiIGNsYXNzPVwic2VjdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImRpc3BsYXk6IGlubGluZS1ibG9jaztcIj5cclxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImRhdGEtbGFiZWxcIiAoY2xpY2spPVwiZGF0YU9wdGlvbiA9ICFkYXRhT3B0aW9uXCI+RmlsbCBEYXRhPzwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJkYXRhLW9wdGlvblwiIHR5cGU9XCJjaGVja2JveFwiIFtjaGVja2VkXT1cImRhdGFPcHRpb25cIiAoY2hhbmdlKT1cImRhdGFPcHRpb24gPSAhZGF0YU9wdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwiZm9vdGVyXCI+XHJcbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInNkay1idXR0b24gZGVsZXRlXCIgKGNsaWNrKT1cInJlc2V0KClcIj5SZXNldDwvYnV0dG9uPlxyXG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJzZGstYnV0dG9uXCIgKGNsaWNrKT1cImFwcGx5KClcIj5BcHBseTwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuPCEtLSBMb2NrIC0tPlxyXG48ZGl2ICpuZ0lmPVwic2hvd01lc3NhZ2VcIiB0aXRsZT1cIlwiIGNsYXNzPVwic2RrLWRhdGFncmlkLXdpbmRvd3MtbG9ja1wiPjwvZGl2PlxyXG5cclxuPCEtLSBNZXNzYWdlIC0tPlxyXG48ZGl2ICpuZ0lmPVwic2hvd01lc3NhZ2VcIiB0aXRsZT1cIlwiIGNsYXNzPVwic2RrLWRhdGFncmlkLW1lc3NhZ2VcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJ0aXRsZVwiPnt7IG1lc3NhZ2UuVGl0bGUgfX08L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJ0ZXh0XCIgW2lubmVySHRtbF09XCJtZXNzYWdlLlRleHRcIj48L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJhY3Rpb25cIj5cclxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwic2RrLWJ1dHRvblwiIChjbGljayk9XCJtZXNzYWdlLk9LKClcIj57eyBtZXNzYWdlLk9LVGV4dCB9fTwvYnV0dG9uPlxyXG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJzZGstYnV0dG9uIGNhbmNlbFwiIChjbGljayk9XCJtZXNzYWdlLkNhbmNlbCgpXCI+e3sgbWVzc2FnZS5DYW5jZWxUZXh0IH19PC9idXR0b24+XHJcbiAgICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==