ngx-surveys
Version:
Angular 18+ survey / form builder
139 lines • 40.2 kB
JavaScript
import { Component, Input, EventEmitter, Output } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { moveItemInArray } from '@angular/cdk/drag-drop';
import { ItemOptionStateMatcher } from '../error-state.matcher';
import { FormItem } from '../form-item';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
import * as i3 from "@angular/material/button";
import * as i4 from "@angular/material/input";
import * as i5 from "@angular/material/form-field";
import * as i6 from "@angular/material/tooltip";
import * as i7 from "@angular/material/icon";
import * as i8 from "@angular/material/table";
import * as i9 from "@angular/cdk/drag-drop";
import * as i10 from "@angular/material/checkbox";
import * as i11 from "@angular/material/slide-toggle";
export class FormItemOptionsEditor extends FormItem {
constructor() {
super(...arguments);
this.hasOptions = true;
this.useCustomOptionValues = false;
this.allowCustomOptionValues = true;
this.allowCustomAnswers = true;
this.multiple = false;
this.fieldValidations = {
rules: [
{
"optionKeyValues": true
}
]
};
}
}
export class FormItemOptionsEditorComponent {
constructor() {
this.editable = true;
this.changes = new EventEmitter();
this.matcher = new ItemOptionStateMatcher();
this.dataSource = new MatTableDataSource([]);
this.useCustomValues = false;
this.allowCustomValues = true;
this.allowCustomAnswers = true;
}
ngOnInit() {
if (!this.item.value) {
this.item.value = [];
}
this.dataSource.data = this.item.value;
this.useCustomValues = this.item.useCustomOptionValues;
this.allowCustomValues = this.item.allowCustomOptionValues;
this.allowCustomAnswers = this.item.allowCustomAnswers;
this.setColumns();
this.item.value.forEach(option => {
option.selected = this.isOptionSelected(option);
});
console.log(this.item);
}
setColumns() {
this.columns = this.useCustomValues ? ['selectedByDefault', 'optionValue', 'label', 'actions'] : ['selectedByDefault', 'label', 'actions'];
}
onUseCustomValuesChange(ev) {
this.useCustomValues = ev.checked;
this.item.useCustomOptionValues = this.useCustomValues;
this.setColumns();
}
onValueChange(value) {
this.item.value = value;
//console.log(this.item);
if (this.useCustomValues) {
(this.item.value || []).forEach(field => {
field.optionValue = field.label;
});
}
this.changes.emit(this.item);
}
isOptionSelected(option) {
//console.log(option);
const item = this.item;
return item.multiple ? (item.defaultValue || []).indexOf(option.optionValue) >= 0 : item.defaultValue === option.optionValue;
}
setDefaultValue(option, checked) {
const item = this.item;
if (item.multiple) {
let value = [...item.defaultValue];
const selectedIndex = value.indexOf(option.optionValue);
if (selectedIndex >= 0) {
checked ? value.push(option.optionValue) : value = value.filter((str, index) => index !== selectedIndex);
}
else if (checked) {
value.push(option.optionValue);
}
item.defaultValue = value;
}
else {
item.defaultValue = checked ? option.optionValue : '';
}
(this.item.value || []).forEach(option => {
option.selected = this.isOptionSelected(option);
});
this.changes.emit(this.item);
}
onOptionLabelChange(value, option) {
if (!this.useCustomValues) {
option.optionValue = value;
}
}
addOption() {
const obj = {};
this.item.value.push(obj);
this.dataSource.data = this.item.value;
}
removeOption(option) {
this.item.value = this.item.value.filter((op, index) => index !== this.item.value.indexOf(option));
this.dataSource.data = this.item.value;
}
onListDropped(event) {
const previousIndex = this.dataSource.data.findIndex(row => row === event.item.data);
moveItemInArray(this.dataSource.data, previousIndex, event.currentIndex);
this.dataSource.data = this.dataSource.data.slice();
//console.log('dropped', JSON.stringify(this.dataSource.data), JSON.stringify(this.item.value));
}
toggleExplanationField(option) {
option.showExplanation = !option.showExplanation;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FormItemOptionsEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: FormItemOptionsEditorComponent, selector: "ammo-form-item-options-editor", inputs: { item: "item", editable: "editable" }, outputs: { changes: "changes" }, ngImport: i0, template: "<div>\n <mat-label>{{item.label}}</mat-label>\n\n <mat-slide-toggle *ngIf=\"allowCustomValues\"\n class=\"example-margin\"\n [color]=\"'primary'\"\n [checked]=\"useCustomValues\"\n [disabled]=\"!editable\"\n (change)=\"onUseCustomValuesChange($event)\"\n >\n Use custom option values\n </mat-slide-toggle>\n\n <table mat-table [dataSource]=\"dataSource\" class=\"mat-elevation-z8\"\n cdkDropList\n [cdkDropListData]=\"dataSource\"\n (cdkDropListDropped)=\"onListDropped($event)\"\n [cdkDropListDisabled]=\"!editable\"\n >\n\n <ng-container matColumnDef=\"selectedByDefault\">\n <th mat-header-cell *matHeaderCellDef> Selected </th>\n <td mat-cell *matCellDef=\"let element\">\n <mat-checkbox\n [checked]=\"element.selected\"\n [color]=\"'primary'\"\n (change)=\"setDefaultValue(element, $event.checked)\"\n ></mat-checkbox>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"optionValue\">\n <th mat-header-cell *matHeaderCellDef> Value </th>\n <td mat-cell *matCellDef=\"let element\">\n <mat-form-field class=\"example-full-width\">\n <input #inputField\n matInput\n [(ngModel)]=\"element.optionValue\"\n [errorStateMatcher]=\"matcher\"\n [disabled]=\"!editable\"\n >\n </mat-form-field>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"label\">\n <th mat-header-cell *matHeaderCellDef> Label </th>\n <td mat-cell *matCellDef=\"let element\" class=\"row-actions\">\n <mat-form-field class=\"example-full-width\">\n <input #inputField\n matInput\n [(ngModel)]=\"element.label\"\n (ngModelChange)=\"onOptionLabelChange($event, element)\"\n [errorStateMatcher]=\"matcher\"\n [disabled]=\"!editable\"\n >\n </mat-form-field>\n\n <mat-form-field class=\"explanation-field\" *ngIf=\"element.showExplanation\">\n <mat-label>Explanation field label</mat-label>\n <input #inputField\n matInput\n [(ngModel)]=\"element.explanationLabel\"\n [disabled]=\"!editable\"\n >\n </mat-form-field>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let element\">\n <button mat-icon-button class=\"form-item-actions-button\" aria-label=\"Show text field with custom value\" *ngIf=\"allowCustomAnswers && !item.multiple\" (click)=\"toggleExplanationField(element)\" type=\"button\"\n matTooltip=\"Show explanation text field\"\n [disabled]=\"!editable\"\n >\n <mat-icon [color]=\"element.showExplanation ? 'primary' : 'disabled'\">comment</mat-icon>\n </button>\n\n <button mat-icon-button class=\"form-item-actions-button\" aria-label=\"Remove Option\" (click)=\"removeOption(element)\" type=\"button\"\n matTooltip=\"Remove Option\"\n [disabled]=\"!editable\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: columns;\"\n cdkDrag\n [cdkDragData]=row\n ></tr>\n <tr class=\"mat-row\" *matNoDataRow>\n <td class=\"mat-cell\" colspan=\"3\">No options</td>\n </tr>\n </table>\n <mat-error *ngIf=\"item.errors && item.errors.length\">\n <div *ngFor=\"let error of item.errors\">{{error.message}}</div>\n </mat-error>\n <mat-hint align=\"start\" *ngIf=\"!(item.errors && item.errors.length)\"><strong>{{item.hint}}</strong> </mat-hint>\n <button mat-raised-button color=\"primary\" aria-label=\"Add Option\" (click)=\"addOption()\" type=\"button\" matTooltip=\"Add Option\" [disabled]=\"!editable\">\n Add Option\n </button>\n</div>\n\n\n", styles: [".mat-mdc-form-field{display:block}::ng-deep .mat-table{box-shadow:none;width:100%}::ng-deep .mat-table .mat-cell{cursor:move}::ng-deep .mat-table .mat-cell .mat-mdc-form-field-infix{width:100%}::ng-deep .mat-table .mat-input-element{width:95%}::ng-deep .mat-table .mat-column-optionValue{padding-right:10px}::ng-deep .mat-table .cdk-column-actions{text-align:right}::ng-deep .mat-table .explanation-field{padding-left:20px}::ng-deep .mat-slide-toggle{display:block!important}\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"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i5.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "directive", type: i9.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: i9.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: "component", type: i10.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FormItemOptionsEditorComponent, decorators: [{
type: Component,
args: [{ selector: 'ammo-form-item-options-editor', template: "<div>\n <mat-label>{{item.label}}</mat-label>\n\n <mat-slide-toggle *ngIf=\"allowCustomValues\"\n class=\"example-margin\"\n [color]=\"'primary'\"\n [checked]=\"useCustomValues\"\n [disabled]=\"!editable\"\n (change)=\"onUseCustomValuesChange($event)\"\n >\n Use custom option values\n </mat-slide-toggle>\n\n <table mat-table [dataSource]=\"dataSource\" class=\"mat-elevation-z8\"\n cdkDropList\n [cdkDropListData]=\"dataSource\"\n (cdkDropListDropped)=\"onListDropped($event)\"\n [cdkDropListDisabled]=\"!editable\"\n >\n\n <ng-container matColumnDef=\"selectedByDefault\">\n <th mat-header-cell *matHeaderCellDef> Selected </th>\n <td mat-cell *matCellDef=\"let element\">\n <mat-checkbox\n [checked]=\"element.selected\"\n [color]=\"'primary'\"\n (change)=\"setDefaultValue(element, $event.checked)\"\n ></mat-checkbox>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"optionValue\">\n <th mat-header-cell *matHeaderCellDef> Value </th>\n <td mat-cell *matCellDef=\"let element\">\n <mat-form-field class=\"example-full-width\">\n <input #inputField\n matInput\n [(ngModel)]=\"element.optionValue\"\n [errorStateMatcher]=\"matcher\"\n [disabled]=\"!editable\"\n >\n </mat-form-field>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"label\">\n <th mat-header-cell *matHeaderCellDef> Label </th>\n <td mat-cell *matCellDef=\"let element\" class=\"row-actions\">\n <mat-form-field class=\"example-full-width\">\n <input #inputField\n matInput\n [(ngModel)]=\"element.label\"\n (ngModelChange)=\"onOptionLabelChange($event, element)\"\n [errorStateMatcher]=\"matcher\"\n [disabled]=\"!editable\"\n >\n </mat-form-field>\n\n <mat-form-field class=\"explanation-field\" *ngIf=\"element.showExplanation\">\n <mat-label>Explanation field label</mat-label>\n <input #inputField\n matInput\n [(ngModel)]=\"element.explanationLabel\"\n [disabled]=\"!editable\"\n >\n </mat-form-field>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let element\">\n <button mat-icon-button class=\"form-item-actions-button\" aria-label=\"Show text field with custom value\" *ngIf=\"allowCustomAnswers && !item.multiple\" (click)=\"toggleExplanationField(element)\" type=\"button\"\n matTooltip=\"Show explanation text field\"\n [disabled]=\"!editable\"\n >\n <mat-icon [color]=\"element.showExplanation ? 'primary' : 'disabled'\">comment</mat-icon>\n </button>\n\n <button mat-icon-button class=\"form-item-actions-button\" aria-label=\"Remove Option\" (click)=\"removeOption(element)\" type=\"button\"\n matTooltip=\"Remove Option\"\n [disabled]=\"!editable\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: columns;\"\n cdkDrag\n [cdkDragData]=row\n ></tr>\n <tr class=\"mat-row\" *matNoDataRow>\n <td class=\"mat-cell\" colspan=\"3\">No options</td>\n </tr>\n </table>\n <mat-error *ngIf=\"item.errors && item.errors.length\">\n <div *ngFor=\"let error of item.errors\">{{error.message}}</div>\n </mat-error>\n <mat-hint align=\"start\" *ngIf=\"!(item.errors && item.errors.length)\"><strong>{{item.hint}}</strong> </mat-hint>\n <button mat-raised-button color=\"primary\" aria-label=\"Add Option\" (click)=\"addOption()\" type=\"button\" matTooltip=\"Add Option\" [disabled]=\"!editable\">\n Add Option\n </button>\n</div>\n\n\n", styles: [".mat-mdc-form-field{display:block}::ng-deep .mat-table{box-shadow:none;width:100%}::ng-deep .mat-table .mat-cell{cursor:move}::ng-deep .mat-table .mat-cell .mat-mdc-form-field-infix{width:100%}::ng-deep .mat-table .mat-input-element{width:95%}::ng-deep .mat-table .mat-column-optionValue{padding-right:10px}::ng-deep .mat-table .cdk-column-actions{text-align:right}::ng-deep .mat-table .explanation-field{padding-left:20px}::ng-deep .mat-slide-toggle{display:block!important}\n"] }]
}], ctorParameters: () => [], propDecorators: { item: [{
type: Input
}], editable: [{
type: Input
}], changes: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1pdGVtLW9wdGlvbnMtZWRpdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zdXJ2ZXlzL3NyYy9saWIvZm9ybS1pdGVtL2Zvcm0taXRlbS1vcHRpb25zLWVkaXRvci9mb3JtLWl0ZW0tb3B0aW9ucy1lZGl0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXN1cnZleXMvc3JjL2xpYi9mb3JtLWl0ZW0vZm9ybS1pdGVtLW9wdGlvbnMtZWRpdG9yL2Zvcm0taXRlbS1vcHRpb25zLWVkaXRvci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9FLE9BQU8sRUFDTCxrQkFBa0IsRUFDbkIsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQWUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdEUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFFBQVEsRUFBbUYsTUFBTSxjQUFjLENBQUM7Ozs7Ozs7Ozs7Ozs7QUFFekgsTUFBTSxPQUFPLHFCQUFzQixTQUFRLFFBQVE7SUFBbkQ7O1FBRUksZUFBVSxHQUFVLElBQUksQ0FBQztRQUN6QiwwQkFBcUIsR0FBVyxLQUFLLENBQUM7UUFDdEMsNEJBQXVCLEdBQVcsSUFBSSxDQUFDO1FBQ3ZDLHVCQUFrQixHQUFXLElBQUksQ0FBQztRQUNsQyxhQUFRLEdBQVcsS0FBSyxDQUFDO1FBRXpCLHFCQUFnQixHQUFxQjtZQUNqQyxLQUFLLEVBQThCO2dCQUMvQjtvQkFDSSxpQkFBaUIsRUFBRSxJQUFJO2lCQUMxQjthQUNKO1NBQ0osQ0FBQztJQUNOLENBQUM7Q0FBQTtBQU9ELE1B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QUFVLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3BELGdHQUFnRztJQUNwRyxDQUFDO0lBRUQsc0JBQXNCLENBQUUsTUFBTTtRQUMxQixNQUFNLENBQUMsZUFBZSxHQUFDLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQztJQUNuRCxDQUFDOytHQTFHUSw4QkFBOEI7bUdBQTlCLDhCQUE4QixzSkM5QjNDLDAvSUEwR0E7OzRGRDVFYSw4QkFBOEI7a0JBTDFDLFNBQVM7K0JBQ0UsK0JBQStCO3dEQU05QixJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDSSxPQUFPO3NCQUFoQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBFdmVudEVtaXR0ZXIsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgTWF0VGFibGVEYXRhU291cmNlXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3RhYmxlJztcbmltcG9ydCB7IENka0RyYWdEcm9wLCBtb3ZlSXRlbUluQXJyYXkgfSBmcm9tICdAYW5ndWxhci9jZGsvZHJhZy1kcm9wJztcbmltcG9ydCB7IEl0ZW1PcHRpb25TdGF0ZU1hdGNoZXIgfSBmcm9tICcuLi9lcnJvci1zdGF0ZS5tYXRjaGVyJztcbmltcG9ydCB7IEZvcm1JdGVtLCBGb3JtSXRlbU9wdGlvbkl0ZW0sIEZvcm1JdGVtV2lkZ2V0LCBGb3JtSXRlbVZhbGlkYXRpb24sIEZvcm1JdGVtVmFsaWRhdGlvblJ1bGVzIH0gZnJvbSAnLi4vZm9ybS1pdGVtJztcblxuZXhwb3J0IGNsYXNzIEZvcm1JdGVtT3B0aW9uc0VkaXRvciBleHRlbmRzIEZvcm1JdGVtIHtcbiAgICB2YWx1ZTogRm9ybUl0ZW1PcHRpb25JdGVtW107XG4gICAgaGFzT3B0aW9uczogYm9vbGVhbj10cnVlO1xuICAgIHVzZUN1c3RvbU9wdGlvblZhbHVlczogIGJvb2xlYW49ZmFsc2U7XG4gICAgYWxsb3dDdXN0b21PcHRpb25WYWx1ZXM6ICBib29sZWFuPXRydWU7XG4gICAgYWxsb3dDdXN0b21BbnN3ZXJzOiAgYm9vbGVhbj10cnVlO1xuICAgIG11bHRpcGxlOiAgYm9vbGVhbj1mYWxzZTtcbiAgICBkZWZhdWx0VmFsdWU6IHN0cmluZyB8IHN0cmluZ1tdO1xuICAgIGZpZWxkVmFsaWRhdGlvbnM6IEZvcm1JdGVtVmFsaWRhdGlvbj17XG4gICAgICAgIHJ1bGVzOiA8Rm9ybUl0ZW1WYWxpZGF0aW9uUnVsZXNbXT4gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIFwib3B0aW9uS2V5VmFsdWVzXCI6IHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgXVxuICAgIH07XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FtbW8tZm9ybS1pdGVtLW9wdGlvbnMtZWRpdG9yJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2Zvcm0taXRlbS1vcHRpb25zLWVkaXRvci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2Zvcm0taXRlbS1vcHRpb25zLWVkaXRvci5jb21wb25lbnQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIEZvcm1JdGVtT3B0aW9uc0VkaXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIEZvcm1JdGVtV2lkZ2V0LCBPbkluaXQge1xuXG4gICAgQElucHV0KCkgaXRlbTogRm9ybUl0ZW1PcHRpb25zRWRpdG9yO1xuICAgIEBJbnB1dCgpIGVkaXRhYmxlOiBib29sZWFuPXRydWU7XG4gICAgQE91dHB1dCgpIGNoYW5nZXMgPSBuZXcgRXZlbnRFbWl0dGVyPEZvcm1JdGVtT3B0aW9uc0VkaXRvcj4oKTtcbiAgICBtYXRjaGVyID0gbmV3IEl0ZW1PcHRpb25TdGF0ZU1hdGNoZXIoKTtcbiAgICBkYXRhU291cmNlID0gbmV3IE1hdFRhYmxlRGF0YVNvdXJjZTxGb3JtSXRlbU9wdGlvbkl0ZW0+KFtdKTtcbiAgICBwdWJsaWMgY29sdW1uczogc3RyaW5nW107XG5cbiAgICBwdWJsaWMgdXNlQ3VzdG9tVmFsdWVzOmJvb2xlYW49ZmFsc2U7XG4gICAgcHVibGljIGFsbG93Q3VzdG9tVmFsdWVzOmJvb2xlYW49dHJ1ZTtcbiAgICBwdWJsaWMgYWxsb3dDdXN0b21BbnN3ZXJzOmJvb2xlYW49dHJ1ZTtcblxuICAgIGNvbnN0cnVjdG9yKCkgeyB9XG5cbiAgICBuZ09uSW5pdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLml0ZW0udmFsdWUpe1xuICAgICAgICAgICAgdGhpcy5pdGVtLnZhbHVlPVtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGF0YVNvdXJjZS5kYXRhPXRoaXMuaXRlbS52YWx1ZTtcbiAgICAgICAgdGhpcy51c2VDdXN0b21WYWx1ZXM9dGhpcy5pdGVtLnVzZUN1c3RvbU9wdGlvblZhbHVlcztcbiAgICAgICAgdGhpcy5hbGxvd0N1c3RvbVZhbHVlcz10aGlzLml0ZW0uYWxsb3dDdXN0b21PcHRpb25WYWx1ZXM7XG4gICAgICAgIHRoaXMuYWxsb3dDdXN0b21BbnN3ZXJzPXRoaXMuaXRlbS5hbGxvd0N1c3RvbUFuc3dlcnM7XG4gICAgICAgIHRoaXMuc2V0Q29sdW1ucygpO1xuICAgICAgICB0aGlzLml0ZW0udmFsdWUuZm9yRWFjaChvcHRpb249PntcbiAgICAgICAgICAgIG9wdGlvbi5zZWxlY3RlZD10aGlzLmlzT3B0aW9uU2VsZWN0ZWQob3B0aW9uKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMuaXRlbSk7XG5cbiAgICB9XG5cbiAgICBzZXRDb2x1bW5zKCl7XG4gICAgICAgIHRoaXMuY29sdW1ucz10aGlzLnVzZUN1c3RvbVZhbHVlcyA/IFsnc2VsZWN0ZWRCeURlZmF1bHQnLCAnb3B0aW9uVmFsdWUnLCAnbGFiZWwnLCAnYWN0aW9ucyddIDogWydzZWxlY3RlZEJ5RGVmYXVsdCcsICdsYWJlbCcsICdhY3Rpb25zJ107XG4gICAgfVxuXG4gICAgb25Vc2VDdXN0b21WYWx1ZXNDaGFuZ2UoZXYpe1xuICAgICAgICB0aGlzLnVzZUN1c3RvbVZhbHVlcz1ldi5jaGVja2VkO1xuICAgICAgICB0aGlzLml0ZW0udXNlQ3VzdG9tT3B0aW9uVmFsdWVzPXRoaXMudXNlQ3VzdG9tVmFsdWVzO1xuICAgICAgICB0aGlzLnNldENvbHVtbnMoKTtcbiAgICB9XG5cbiAgICBvblZhbHVlQ2hhbmdlKHZhbHVlKXtcbiAgICAgICAgdGhpcy5pdGVtLnZhbHVlPXZhbHVlO1xuICAgICAgICAvL2NvbnNvbGUubG9nKHRoaXMuaXRlbSk7XG4gICAgICAgIGlmICh0aGlzLnVzZUN1c3RvbVZhbHVlcyl7XG4gICAgICAgICAgICAodGhpcy5pdGVtLnZhbHVlIHx8IFtdKS5mb3JFYWNoKGZpZWxkPT57XG4gICAgICAgICAgICAgICAgZmllbGQub3B0aW9uVmFsdWU9ZmllbGQubGFiZWw7XG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2hhbmdlcy5lbWl0KHRoaXMuaXRlbSk7XG4gICAgfVxuXG4gICAgaXNPcHRpb25TZWxlY3RlZChvcHRpb24pe1xuICAgICAgICAvL2NvbnNvbGUubG9nKG9wdGlvbik7XG4gICAgICAgIGNvbnN0IGl0ZW09dGhpcy5pdGVtO1xuICAgICAgICByZXR1cm4gaXRlbS5tdWx0aXBsZSA/IChpdGVtLmRlZmF1bHRWYWx1ZSB8fCBbXSkuaW5kZXhPZihvcHRpb24ub3B0aW9uVmFsdWUpID49MCA6IGl0ZW0uZGVmYXVsdFZhbHVlPT09b3B0aW9uLm9wdGlvblZhbHVlO1xuICAgIH1cbiAgICBzZXREZWZhdWx0VmFsdWUob3B0aW9uLCBjaGVja2VkKSB7XG4gICAgICAgIGNvbnN0IGl0ZW09dGhpcy5pdGVtO1xuICAgICAgICBpZiAoaXRlbS5tdWx0aXBsZSl7XG4gICAgICAgICAgICBsZXQgdmFsdWU9Wy4uLml0ZW0uZGVmYXVsdFZhbHVlXTtcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkSW5kZXg9dmFsdWUuaW5kZXhPZihvcHRpb24ub3B0aW9uVmFsdWUpO1xuICAgICAgICAgICAgaWYgKHNlbGVjdGVkSW5kZXg+PTApe1xuICAgICAgICAgICAgICAgIGNoZWNrZWQgPyB2YWx1ZS5wdXNoKG9wdGlvbi5vcHRpb25WYWx1ZSkgOiB2YWx1ZT12YWx1ZS5maWx0ZXIoKHN0ciwgaW5kZXgpPT5pbmRleCE9PXNlbGVjdGVkSW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2tlZCkge1xuICAgICAgICAgICAgICAgIHZhbHVlLnB1c2gob3B0aW9uLm9wdGlvblZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGl0ZW0uZGVmYXVsdFZhbHVlPXZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaXRlbS5kZWZhdWx0VmFsdWU9Y2hlY2tlZCA/IG9wdGlvbi5vcHRpb25WYWx1ZSA6ICcnO1xuICAgICAgICB9XG4gICAgICAgICh0aGlzLml0ZW0udmFsdWUgfHwgW10pLmZvckVhY2gob3B0aW9uPT57XG4gICAgICAgICAgICBvcHRpb24uc2VsZWN0ZWQ9dGhpcy5pc09wdGlvblNlbGVjdGVkKG9wdGlvbik7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNoYW5nZXMuZW1pdCh0aGlzLml0ZW0pO1xuICAgIH1cblxuICAgIG9uT3B0aW9uTGFiZWxDaGFuZ2UodmFsdWUsIG9wdGlvbikge1xuICAgICAgICBpZiAoIXRoaXMudXNlQ3VzdG9tVmFsdWVzKXtcbiAgICAgICAgICAgIG9wdGlvbi5vcHRpb25WYWx1ZT12YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFkZE9wdGlvbigpe1xuICAgICAgICBjb25zdCBvYmo9PEZvcm1JdGVtT3B0aW9uSXRlbT57fTtcblxuICAgICAgICB0aGlzLml0ZW0udmFsdWUucHVzaChvYmopO1xuICAgICAgICB0aGlzLmRhdGFTb3VyY2UuZGF0YT10aGlzLml0ZW0udmFsdWU7XG4gICAgfVxuXG4gICAgcmVtb3ZlT3B0aW9uKG9wdGlvbil7XG4gICAgICAgIHRoaXMuaXRlbS52YWx1ZT10aGlzLml0ZW0udmFsdWUuZmlsdGVyKChvcCwgaW5kZXgpPT5pbmRleCE9PXRoaXMuaXRlbS52YWx1ZS5pbmRleE9mKG9wdGlvbikpO1xuICAgICAgICB0aGlzLmRhdGFTb3VyY2UuZGF0YT10aGlzLml0ZW0udmFsdWU7XG4gICAgfVxuXG4gICAgb25MaXN0RHJvcHBlZChldmVudDogQ2RrRHJhZ0Ryb3A8Rm9ybUl0ZW1PcHRpb25JdGVtW10+KSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzSW5kZXggPSB0aGlzLmRhdGFTb3VyY2UuZGF0YS5maW5kSW5kZXgocm93ID0+IHJvdyA9PT0gZXZlbnQuaXRlbS5kYXRhKTtcbiAgICAgICAgbW92ZUl0ZW1JbkFycmF5KHRoaXMuZGF0YVNvdXJjZS5kYXRhLHByZXZpb3VzSW5kZXgsIGV2ZW50LmN1cnJlbnRJbmRleCk7XG4gICAgICAgIHRoaXMuZGF0YVNvdXJjZS5kYXRhID0gdGhpcy5kYXRhU291cmNlLmRhdGEuc2xpY2UoKTtcbiAgICAgICAgLy9jb25zb2xlLmxvZygnZHJvcHBlZCcsIEpTT04uc3RyaW5naWZ5KHRoaXMuZGF0YVNvdXJjZS5kYXRhKSwgSlNPTi5zdHJpbmdpZnkodGhpcy5pdGVtLnZhbHVlKSk7XG4gICAgfVxuXG4gICAgdG9nZ2xlRXhwbGFuYXRpb25GaWVsZCAob3B0aW9uKSB7XG4gICAgICAgIG9wdGlvbi5zaG93RXhwbGFuYXRpb249IW9wdGlvbi5zaG93RXhwbGFuYXRpb247XG4gICAgfVxufVxuIiwiPGRpdj5cbiAgICA8bWF0LWxhYmVsPnt7aXRlbS5sYWJlbH19PC9tYXQtbGFiZWw+XG5cbiAgICA8bWF0LXNsaWRlLXRvZ2dsZSAqbmdJZj1cImFsbG93Q3VzdG9tVmFsdWVzXCJcbiAgICAgIGNsYXNzPVwiZXhhbXBsZS1tYXJnaW5cIlxuICAgICAgW2NvbG9yXT1cIidwcmltYXJ5J1wiXG4gICAgICBbY2hlY2tlZF09XCJ1c2VDdXN0b21WYWx1ZXNcIlxuICAgICAgW2Rpc2FibGVkXT1cIiFlZGl0YWJsZVwiXG4gICAgICAoY2hhbmdlKT1cIm9uVXNlQ3VzdG9tVmFsdWVzQ2hhbmdlKCRldmVudClcIlxuICAgID5cbiAgICBVc2UgY3VzdG9tIG9wdGlvbiB2YWx1ZXNcbiAgICA8L21hdC1zbGlkZS10b2dnbGU+XG5cbiAgICA8dGFibGUgbWF0LXRhYmxlIFtkYXRhU291cmNlXT1cImRhdGFTb3VyY2VcIiBjbGFzcz1cIm1hdC1lbGV2YXRpb24tejhcIlxuICAgICAgICBjZGtEcm9wTGlzdFxuICAgICAgICBbY2RrRHJvcExpc3REYXRhXT1cImRhdGFTb3VyY2VcIlxuICAgICAgICAoY2RrRHJvcExpc3REcm9wcGVkKT1cIm9uTGlzdERyb3BwZWQoJGV2ZW50KVwiXG4gICAgICAgIFtjZGtEcm9wTGlzdERpc2FibGVkXT1cIiFlZGl0YWJsZVwiXG4gICAgPlxuXG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwic2VsZWN0ZWRCeURlZmF1bHRcIj5cbiAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IFNlbGVjdGVkIDwvdGg+XG4gICAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtY2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwiZWxlbWVudC5zZWxlY3RlZFwiXG4gICAgICAgICAgICAgICAgICAgIFtjb2xvcl09XCIncHJpbWFyeSdcIlxuICAgICAgICAgICAgICAgICAgICAoY2hhbmdlKT1cInNldERlZmF1bHRWYWx1ZShlbGVtZW50LCAkZXZlbnQuY2hlY2tlZClcIlxuICAgICAgICAgICAgICAgID48L21hdC1jaGVja2JveD5cbiAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwib3B0aW9uVmFsdWVcIj5cbiAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IFZhbHVlIDwvdGg+XG4gICAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImV4YW1wbGUtZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgI2lucHV0RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVsZW1lbnQub3B0aW9uVmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2Vycm9yU3RhdGVNYXRjaGVyXT1cIm1hdGNoZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFlZGl0YWJsZVwiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJsYWJlbFwiPlxuICAgICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj4gTGFiZWwgPC90aD5cbiAgICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCIgY2xhc3M9XCJyb3ctYWN0aW9uc1wiPlxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImV4YW1wbGUtZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgI2lucHV0RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVsZW1lbnQubGFiZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25PcHRpb25MYWJlbENoYW5nZSgkZXZlbnQsIGVsZW1lbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtlcnJvclN0YXRlTWF0Y2hlcl09XCJtYXRjaGVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZWRpdGFibGVcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImV4cGxhbmF0aW9uLWZpZWxkXCIgKm5nSWY9XCJlbGVtZW50LnNob3dFeHBsYW5hdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPkV4cGxhbmF0aW9uIGZpZWxkIGxhYmVsPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCAjaW5wdXRGaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZWxlbWVudC5leHBsYW5hdGlvbkxhYmVsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZWRpdGFibGVcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImFjdGlvbnNcIj5cbiAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+PC90aD5cbiAgICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCI+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gY2xhc3M9XCJmb3JtLWl0ZW0tYWN0aW9ucy1idXR0b25cIiBhcmlhLWxhYmVsPVwiU2hvdyB0ZXh0IGZpZWxkIHdpdGggY3VzdG9tIHZhbHVlXCIgKm5nSWY9XCJhbGxvd0N1c3RvbUFuc3dlcnMgJiYgIWl0ZW0ubXVsdGlwbGVcIiAoY2xpY2spPVwidG9nZ2xlRXhwbGFuYXRpb25GaWVsZChlbGVtZW50KVwiIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiU2hvdyBleHBsYW5hdGlvbiB0ZXh0IGZpZWxkXCJcbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFlZGl0YWJsZVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIFtjb2xvcl09XCJlbGVtZW50LnNob3dFeHBsYW5hdGlvbiA/ICdwcmltYXJ5JyA6ICdkaXNhYmxlZCdcIj5jb21tZW50PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIGNsYXNzPVwiZm9ybS1pdGVtLWFjdGlvbnMtYnV0dG9uXCIgYXJpYS1sYWJlbD1cIlJlbW92ZSBPcHRpb25cIiAoY2xpY2spPVwicmVtb3ZlT3B0aW9uKGVsZW1lbnQpXCIgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJSZW1vdmUgT3B0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFlZGl0YWJsZVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmRlbGV0ZTwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImNvbHVtbnNcIj48L3RyPlxuICAgICAgICA8dHIgbWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogY29sdW1ucztcIlxuICAgICAgICAgICAgY2RrRHJhZ1xuICAgICAgICAgICAgW2Nka0RyYWdEYXRhXT1yb3dcbiAgICAgICAgPjwvdHI+XG4gICAgICAgIDx0ciBjbGFzcz1cIm1hdC1yb3dcIiAqbWF0Tm9EYXRhUm93PlxuICAgICAgICAgICAgPHRkIGNsYXNzPVwibWF0LWNlbGxcIiBjb2xzcGFuPVwiM1wiPk5vIG9wdGlvbnM8L3RkPlxuICAgICAgICA8L3RyPlxuICAgIDwvdGFibGU+XG4gICAgPG1hdC1lcnJvciAqbmdJZj1cIml0ZW0uZXJyb3JzICYmIGl0ZW0uZXJyb3JzLmxlbmd0aFwiPlxuICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBlcnJvciBvZiBpdGVtLmVycm9yc1wiPnt7ZXJyb3IubWVzc2FnZX19PC9kaXY+XG4gICAgPC9tYXQtZXJyb3I+XG4gICAgPG1hdC1oaW50IGFsaWduPVwic3RhcnRcIiAqbmdJZj1cIiEoaXRlbS5lcnJvcnMgJiYgaXRlbS5lcnJvcnMubGVuZ3RoKVwiPjxzdHJvbmc+e3tpdGVtLmhpbnR9fTwvc3Ryb25nPiA8L21hdC1oaW50PlxuICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCIgYXJpYS1sYWJlbD1cIkFkZCBPcHRpb25cIiAoY2xpY2spPVwiYWRkT3B0aW9uKClcIiB0eXBlPVwiYnV0dG9uXCIgbWF0VG9vbHRpcD1cIkFkZCBPcHRpb25cIiBbZGlzYWJsZWRdPVwiIWVkaXRhYmxlXCI+XG4gICAgICAgIEFkZCBPcHRpb25cbiAgICA8L2J1dHRvbj5cbjwvZGl2PlxuXG5cbiJdfQ==