UNPKG

@noaestudio/forms

Version:

Dynamic forms extension for Covalent

534 lines (509 loc) 67.2 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ import { Component, forwardRef, ChangeDetectorRef } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { AbstractControlValueAccessor } from '../abstract-control-value-accesor'; import { TranslateService } from '@ngx-translate/core'; import { MatDialog } from '@angular/material'; import { moveItemInArray } from '@angular/cdk/drag-drop'; import * as lodash_ from 'lodash'; import { ErrorDialogComponent } from '../../dialogs/error-dialog/error-dialog.component'; import { ConfirmDialogComponent } from '../../dialogs/confirm-dialog/confirm-dialog.component'; const /** @type {?} */ lodash = lodash_; export const /** @type {?} */ INPUT_INPUT_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => EditableTableComponent), multi: true, }; export class EditableTableComponent extends AbstractControlValueAccessor { /** * @param {?} translator * @param {?} dialog * @param {?} changeDetector */ constructor(translator, dialog, changeDetector) { super(); this.translator = translator; this.dialog = dialog; this.changeDetector = changeDetector; /** * Component Attributes */ this.label = ''; //Elementos a devolver this.outputItems = []; //Esquema this.schema = null; //Puede ser draggable this.draggable = false; //New Element this.newElement = {}; //Extras this.extras = null; this.showDelete = true; this.addTitle = 'Nuevo elemento'; } /** * @return {?} */ ngOnInit() { //Inicializamos el value si no llega nada por defecto if (this.value == undefined) { this.value = []; } //Creamos el newElement en base al esquema for (let /** @type {?} */ i = 0; i < this.schema.length; i++) { this.newElement[this.schema[i].name] = null; } //Cargamos los extras if (this.extras) { //Puede eliminar registros en la tabla? if (this.extras.showDelete != undefined && this.extras.showDelete != null) { this.showDelete = this.extras.showDelete; } if (this.extras.addTitle != undefined && this.extras.addTitle != null) { this.addTitle = this.extras.addTitle; } } } /** * @return {?} */ addItem() { this.value.push(this.cloneObject(this.newElement)); this.control.setValue(this.value); this.checkRequired(); this.checkValidators(); } /** * @param {?} index * @return {?} */ removeItem(index) { let /** @type {?} */ deleteItem = () => { this.value.splice(index, 1); this.control.setValue(this.value); this.checkRequired(); this.checkValidators(); this.changeDetector.detectChanges(); }; this.openConfirm().then(confirm => { if (confirm) { if (this.extras != undefined && this.extras != null && this.extras.deleteAction != undefined) { this.extras.deleteAction(this.value[index]).then(result => { if (result) { deleteItem(); } }).catch(err => { let /** @type {?} */ errorMessage = err.error.message; this.openDialog("Error", errorMessage); }); } else { deleteItem(); } } }); } /** * @param {?} obj * @return {?} */ cloneObject(obj) { let /** @type {?} */ cloneLodash = lodash.cloneDeep(obj); return cloneLodash; } /** * @param {?} $event * @return {?} */ changesOut($event) { this.control.setValue(this.value); this.checkRequired(); this.checkValidators(); } /** * @param {?} event * @return {?} */ drop(event) { moveItemInArray(this.value, event.previousIndex, event.currentIndex); this.control.setValue(this.value); } /** * @return {?} */ checkRequired() { this.value.forEach(field => { Object.keys(field).forEach(key => { let /** @type {?} */ schema = this.getFieldSchema(key); if (schema != null) { if (schema.required != undefined && schema.required && field[key] == null) { this.control.setErrors({ required: true }); } } }); }); } /** * @param {?} name * @return {?} */ getFieldSchema(name) { let /** @type {?} */ schema = null; this.schema.forEach(item => { if (item.name == name) { schema = item; } }); return schema; } /** * @return {?} */ checkValidators() { if (this.extras.rowValidator) { for (let /** @type {?} */ item of this.value) { let /** @type {?} */ errors = this.extras.rowValidator(item); if (errors) { this.control.setErrors(errors.errorList); } } } } /** * @param {?} item * @param {?} field * @return {?} */ isValid(item, field) { let /** @type {?} */ valid = true; if (this.extras.rowValidator) { let /** @type {?} */ errors = this.extras.rowValidator(item); if (errors) { for (let /** @type {?} */ i = 0; i < errors.errorFields.length; i++) { if (errors.errorFields[i].field == field) { valid = false; } } } } return valid; } /** * @param {?} item * @param {?} field * @return {?} */ fieldErrorMessage(item, field) { let /** @type {?} */ message = ""; if (this.extras.rowValidator) { let /** @type {?} */ errors = this.extras.rowValidator(item); if (errors) { for (let /** @type {?} */ i = 0; i < errors.errorFields.length; i++) { if (errors.errorFields[i].field == field) { message = errors.errorFields[i].message; } } } } return message; } /** * @param {?} title * @param {?} message * @return {?} */ openDialog(title, message) { let /** @type {?} */ data = { title: title, message: message }; this.dialog.open(ErrorDialogComponent, { data: data }); } /** * @return {?} */ openConfirm() { let /** @type {?} */ dialogRef = this.dialog.open(ConfirmDialogComponent); return dialogRef.afterClosed().toPromise(); } } EditableTableComponent.decorators = [ { type: Component, args: [{ providers: [INPUT_INPUT_CONTROL_VALUE_ACCESSOR], selector: 'editable-table', styles: [`td{padding:10px}.td-dynamic-input-wrapper{-ms-flex-direction:row;flex-direction:row;display:-ms-flexbox;display:flex;box-sizing:border-box}.td-dynamic-input-wrapper .td-dynamic-input-field{-ms-flex:1;flex:1;box-sizing:border-box}.td-dynamic-input-wrapper .ngx-editor{margin-top:10px}.label{padding:10px 0;display:inline-block;width:50%}.container{overflow:auto;border:1px solid #f3f3f3;border-radius:5px 5px 0 0}.selected-items{padding:5px;display:block;background:#f3f3f3;border-radius:0 0 5px 5px;min-height:30px}.selected-items span{background:#689f38;margin:2px;padding:5px;border-radius:5px;color:#fff;display:inline-block}.buttons{display:inline-block;width:50%;text-align:right}.buttons button{padding:0;width:30px!important;min-width:30px;border-radius:50px;height:30px}.buttons button mat-icon{position:relative!important;top:-4px!important}.main-container{border:1px solid #f3f3f3;border-radius:5px;padding:5px 10px 20px;overflow:auto}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}.dragger{text-align:center;background:#f3f3f3;height:24px;border-radius:5px;width:36px;margin:auto 8px auto auto;border:1px solid #ddd;cursor:move}.error-validate{color:#e53934;font-size:75%;top:33px;position:absolute;left:0}.error-validate.boolean{position:relative!important;top:9px;width:100%;display:inline-block}.error-validate.datetime{position:relative!important;top:9px;padding-bottom:10px;width:100%;display:inline-block}.editable-field{min-width:100%}table{width:100%;border-collapse:collapse;border-spacing:0}tr th{text-align:left}tr:nth-child(even){background:#fafafa}tr:nth-child(even) input{background:#fafafa!important}/deep/ .time-field label{display:block;color:#929292;margin-top:-12px}/deep/ .time-field input{border:0;border-bottom:1px solid #9e9f9e;font-size:14px}/deep/ .mat-datepicker-toggle button{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12);border-radius:3px!important}/deep/ .time-field{margin-bottom:4px}.details{font-size:11px;padding:5px 0}`], template: `<div class="label">{{label}}</div> <div class="main-container"> <table td-data-table> <thead> <tr td-data-table-column-row> <th td-data-table-column> {{addTitle}} </th> </tr> </thead> <tbody> <tr td-data-table-row> <td td-data-table-cell *ngFor="let item of schema; let i=index"> <ng-container *ngIf="item.type == 'string'"> <mat-form-field class="editable-field"> <input matInput autocomplete="off" placeholder="{{item.label}}" [(ngModel)]="newElement[item.name]"> </mat-form-field> </ng-container> <ng-container *ngIf="item.type == 'date'"> <mat-form-field class="editable-field"> <input matInput autocomplete="off" [matDatepicker]="i" placeholder="{{item.label}}" [attr.id]="'dtPicker' + i" [(ngModel)]="newElement[item.name]"> <mat-datepicker-toggle matSuffix [for]="i"></mat-datepicker-toggle><mat-datepicker #i></mat-datepicker> </mat-form-field> </ng-container> <ng-container *ngIf="item.type == 'time'"> <div class="time-field"> <label class="timeLabel">Hora</label> <input aria-label="default time" autocomplete="off" [ngxTimepicker]="defaultTime" [(ngModel)]="newElement[item.name]"> <ngx-material-timepicker #defaultTime></ngx-material-timepicker> </div> </ng-container> <ng-container *ngIf="item.type == 'dateTime'"> <date-time-picker [min]="item.min" [max]="item.max" [(myModel)]="newElement[item.name]"></date-time-picker> </ng-container> <ng-container *ngIf="item.type == 'number'"> <mat-form-field class="editable-field"> <input matInput type="number" autocomplete="off" placeholder="{{item.label}}" [(ngModel)]="newElement[item.name]" min="{{item.min}}" max="{{item.max}}"> </mat-form-field> </ng-container> <ng-container *ngIf="item.type == 'boolean'"> <mat-checkbox [(ngModel)]="newElement[item.name]">{{item.label}}</mat-checkbox> </ng-container> <ng-container *ngIf="item.type == 'select'"> <mat-form-field class="editable-field"> <mat-select placeholder="{{item.label}}" [(value)]="newElement[item.name]"> <mat-option>...</mat-option> <mat-option value="{{item.value}}" *ngFor="let item of item.items;">{{item.label}}</mat-option> </mat-select> </mat-form-field> </ng-container> </td> <td> <button mat-button color="primary" (click)="addItem()">Añadir</button> </td> </tr> </tbody> </table> <hr /> <table td-data-table> <thead> <tr td-data-table-column-row> <th td-data-table-column *ngIf="draggable"></th> <th td-data-table-column *ngFor="let column of schema"> {{column.label}} </th> </tr> </thead> <tbody cdkDropList class="example-list" (cdkDropListDropped)="drop($event)"> <ng-container *ngIf="draggable"> <!--DRAGGABLE: ISSUE #13893--> <tr td-data-table-row *ngFor="let row of value; let z=index" cdkDrag> <td> <div class="dragger" cdkDragHandle> <mat-icon>drag_handle</mat-icon> </div> </td> <td td-data-table-cell *ngFor="let attr of schema; let i=index"> <ng-container *ngIf="attr.type == 'string'"> <mat-form-field class="editable-field"> <input matInput placeholder="{{attr.label}}" [(ngModel)]="row[attr.name]" autocomplete="off" (ngModelChange)="changesOut($event)" [required]="attr.required"> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> <ng-container *ngIf="attr.type == 'date'"> <mat-form-field class="editable-field"> <input matInput autocomplete="off" [matDatepicker]="j" placeholder="{{attr.label}}" [attr.id]="'dtPicker' + j" [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)" [required]="attr.required"> <mat-datepicker-toggle matSuffix [for]="j"></mat-datepicker-toggle><mat-datepicker #j></mat-datepicker> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> <ng-container *ngIf="attr.type == 'time'"> <div class="time-field"> <label class="timeLabel">Hora</label> <input autocomplete="off" aria-label="default time" [ngxTimepicker]="defaultTime" [value]="row[attr.name]" readonly (ngModelChange)="changesOut($event)"> <ngx-material-timepicker #defaultTime></ngx-material-timepicker> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </div> </ng-container> <ng-container *ngIf="attr.type == 'dateTime'"> <date-time-picker [min]="attr.min" [max]="attr.max" [(myModel)]="newElement[attr.name]" (myModelChange)="changesOut($event)"></date-time-picker> <span class="error-validate datetime" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </ng-container> <ng-container *ngIf="attr.type == 'number'"> <mat-form-field class="editable-field"> <input matInput type="number" autocomplete="off" placeholder="{{attr.label}}" [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)" min="{{attr.min}}" max="{{attr.max}}" [required]="attr.required"> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> <ng-container *ngIf="attr.type == 'boolean'"> <mat-checkbox [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)" [required]="attr.required">{{attr.label}}</mat-checkbox> <span class="error-validate boolean" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </ng-container> <ng-container *ngIf="attr.type == 'select'"> <mat-form-field class="editable-field"> <mat-select [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)" [required]="attr.required"> <mat-option>...</mat-option> <mat-option value="{{item.value}}" *ngFor="let item of attr.items;">{{item.label}}</mat-option> </mat-select> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> </td> <td *ngIf="showDelete"> <button mat-button color="primary" (click)="removeItem(z)">Eliminar</button> </td> </tr> </ng-container> <!--NO DRAGGABLE--> <ng-container *ngIf="!draggable"> <tr td-data-table-row *ngFor="let row of value; let z=index"> <td td-data-table-cell *ngFor="let attr of schema; let i=index"> <ng-container *ngIf="attr.type == 'string'"> <mat-form-field class="editable-field"> <input matInput autocomplete="off" placeholder="{{attr.label}}" [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)"> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> <ng-container *ngIf="attr.type == 'date'"> <mat-form-field class="editable-field"> <input matInput autocomplete="off" [matDatepicker]="j" placeholder="{{attr.label}}" [attr.id]="'dtPicker' + j" [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)"> <mat-datepicker-toggle matSuffix [for]="j"></mat-datepicker-toggle><mat-datepicker #j></mat-datepicker> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> <ng-container *ngIf="attr.type == 'time'"> <div class="time-field"> <label class="timeLabel">Hora</label> <input autocomplete="off" aria-label="default time" [ngxTimepicker]="defaultTime" [value]="row[attr.name]" readonly (ngModelChange)="changesOut($event)"> <ngx-material-timepicker #defaultTime></ngx-material-timepicker> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </div> </ng-container> <ng-container *ngIf="attr.type == 'dateTime'"> <date-time-picker [min]="attr.min" [max]="attr.max" [(myModel)]="row[attr.name]" (myModelChange)="changesOut($event)"></date-time-picker> <span class="error-validate datetime" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </ng-container> <ng-container *ngIf="attr.type == 'number'"> <mat-form-field class="editable-field"> <input matInput type="number" autocomplete="off" placeholder="{{attr.label}}" [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)"> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> <ng-container *ngIf="attr.type == 'boolean'"> <mat-checkbox [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)">{{attr.label}}</mat-checkbox> <span class="error-validate boolean" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </ng-container> <ng-container *ngIf="attr.type == 'select'"> <mat-form-field class="editable-field"> <mat-select [(ngModel)]="row[attr.name]" (ngModelChange)="changesOut($event)"> <mat-option>...</mat-option> <mat-option value="{{item.value}}" *ngFor="let item of attr.items;">{{item.label}}</mat-option> </mat-select> <span class="error-validate" *ngIf="!isValid(row, attr.name)"> {{fieldErrorMessage(row, attr.name) | translate}} </span> </mat-form-field> </ng-container> </td> <td *ngIf="showDelete"> <button mat-button color="primary" (click)="removeItem(z)">Eliminar</button> </td> </tr> </ng-container> </tbody> </table> </div> <div class="details"> {{extras.infoDetail}} </div> ` },] }, ]; /** @nocollapse */ EditableTableComponent.ctorParameters = () => [ { type: TranslateService, }, { type: MatDialog, }, { type: ChangeDetectorRef, }, ]; function EditableTableComponent_tsickle_Closure_declarations() { /** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */ EditableTableComponent.decorators; /** * @nocollapse * @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>} */ EditableTableComponent.ctorParameters; /** @type {?} */ EditableTableComponent.prototype.control; /** * Component Attributes * @type {?} */ EditableTableComponent.prototype.label; /** @type {?} */ EditableTableComponent.prototype.outputItems; /** @type {?} */ EditableTableComponent.prototype.schema; /** @type {?} */ EditableTableComponent.prototype.draggable; /** @type {?} */ EditableTableComponent.prototype.newElement; /** @type {?} */ EditableTableComponent.prototype.extras; /** @type {?} */ EditableTableComponent.prototype.showDelete; /** @type {?} */ EditableTableComponent.prototype.addTitle; /** @type {?} */ EditableTableComponent.prototype.translator; /** @type {?} */ EditableTableComponent.prototype.dialog; /** @type {?} */ EditableTableComponent.prototype.changeDetector; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRpdGFibGUtdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGNvdmFsZW50L2R5bmFtaWMtZm9ybXMvIiwic291cmNlcyI6WyJkeW5hbWljLWVsZW1lbnRzL2VkaXRhYmxlLXRhYmxlL2VkaXRhYmxlLXRhYmxlLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsaUJBQWlCLEVBQTZCLE1BQU0sZUFBZSxDQUFDO0FBQ3BHLE9BQU8sRUFBRSxpQkFBaUIsRUFBaUQsTUFBTSxnQkFBZ0IsQ0FBQztBQUVsRyxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUlqRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsU0FBUyxFQUFtQixNQUFNLG1CQUFtQixDQUFDO0FBSS9ELE9BQU8sRUFBYyxlQUFlLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRSxPQUFPLEtBQUssT0FBTyxNQUFNLFFBQVEsQ0FBQztBQUNsQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUN6RixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx1REFBdUQsQ0FBQztBQUUvRix1QkFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDO0FBRXZCLE1BQU0sQ0FBQyx1QkFBTSxrQ0FBa0MsR0FBUTtJQUN0RCxPQUFPLEVBQUUsaUJBQWlCO0lBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsc0JBQXNCLENBQUM7SUFDckQsS0FBSyxFQUFFLElBQUk7Q0FDWCxDQUFDO0FBaVFGLE1BQU0sNkJBQThCLFNBQVEsNEJBQTRCOzs7Ozs7SUFrQ3ZFLFlBQW9CLFVBQTRCLEVBQVMsTUFBaUIsRUFBVSxjQUFpQztRQUNwSCxLQUFLLEVBQUUsQ0FBQztRQURXLGVBQVUsR0FBVixVQUFVLENBQWtCO1FBQVMsV0FBTSxHQUFOLE1BQU0sQ0FBVztRQUFVLG1CQUFjLEdBQWQsY0FBYyxDQUFtQjs7OztxQkEzQnJHLEVBQUU7OzJCQUdNLEVBQUU7O3NCQUdaLElBQUk7O3lCQUdHLEtBQUs7OzBCQUdSLEVBQUU7O3NCQVNoQixJQUFJOzBCQUVjLElBQUk7d0JBRVAsZ0JBQWdCO0tBSWxDOzs7O0lBRUQsUUFBUTs7UUFFUCxFQUFFLENBQUEsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7U0FDaEI7O1FBRUQsR0FBRyxDQUFDLENBQUMscUJBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM3QyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDO1NBQzVDOztRQUdELEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDOztZQUVqQixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDM0UsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQzthQUN6QztZQUNELEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxJQUFJLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUN2RSxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO2FBQ3JDO1NBQ0Q7S0FDRDs7OztJQUVELE9BQU87UUFDTixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0tBQ3ZCOzs7OztJQUVELFVBQVUsQ0FBQyxLQUFLO1FBRWYscUJBQUksVUFBVSxHQUFHLEdBQUcsRUFBRTtZQUNyQixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztTQUNwQyxDQUFBO1FBRUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBRSxPQUFPLENBQUMsRUFBRTtZQUNsQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUNiLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksU0FBUyxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQzlGLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7d0JBQ3pELEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7NEJBQ1osVUFBVSxFQUFFLENBQUM7eUJBQ2I7cUJBQ0QsQ0FBQyxDQUFDLEtBQUssQ0FBRSxHQUFHLENBQUMsRUFBRTt3QkFDZixxQkFBSSxZQUFZLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUM7d0JBQ3JDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO3FCQUN2QyxDQUFDLENBQUM7aUJBQ0g7Z0JBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ1AsVUFBVSxFQUFFLENBQUM7aUJBQ2I7YUFDRDtTQUNELENBQUMsQ0FBQztLQUVIOzs7OztJQUVELFdBQVcsQ0FBQyxHQUFHO1FBQ2QscUJBQUksV0FBVyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFeEMsTUFBTSxDQUFDLFdBQVcsQ0FBQztLQUNuQjs7Ozs7SUFFRCxVQUFVLENBQUMsTUFBTTtRQUVoQixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztLQUV2Qjs7Ozs7SUFFRCxJQUFJLENBQUMsS0FBNEI7UUFFaEMsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQ2xDOzs7O0lBRUQsYUFBYTtRQUVaLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQzFCLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUNoQyxxQkFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDdEMsRUFBRSxDQUFBLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxDQUFBLENBQUM7b0JBQ2xCLEVBQUUsQ0FBQSxDQUFDLE1BQU0sQ0FBQyxRQUFRLElBQUksU0FBUyxJQUFJLE1BQU0sQ0FBQyxRQUFRLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUM7d0JBQzFFLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7cUJBQ3pDO2lCQUNEO2FBQ0QsQ0FBQyxDQUFDO1NBQ0csQ0FBQyxDQUFDO0tBQ1Q7Ozs7O0lBRU8sY0FBYyxDQUFDLElBQUk7UUFFMUIscUJBQUksTUFBTSxHQUFHLElBQUksQ0FBQztRQUNsQixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNqQixFQUFFLENBQUEsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ25CLE1BQU0sR0FBRyxJQUFJLENBQUM7YUFDakI7U0FDVixDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsTUFBTSxDQUFDOzs7OztJQUdmLGVBQWU7UUFDZCxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7WUFDOUIsR0FBRyxDQUFBLENBQUMscUJBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUM1QixxQkFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzVDLEVBQUUsQ0FBQSxDQUFDLE1BQU0sQ0FBQyxDQUFBLENBQUM7b0JBQ1YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2lCQUN6QzthQUNEO1NBQ0Q7S0FDRDs7Ozs7O0lBRUQsT0FBTyxDQUFDLElBQUksRUFBRSxLQUFLO1FBQ2xCLHFCQUFJLEtBQUssR0FBRyxJQUFJLENBQUM7UUFDakIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQzlCLHFCQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1QyxFQUFFLENBQUEsQ0FBQyxNQUFNLENBQUMsQ0FBQSxDQUFDO2dCQUNWLEdBQUcsQ0FBQSxDQUFDLHFCQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7b0JBQ25ELEVBQUUsQ0FBQSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7d0JBQ3pDLEtBQUssR0FBRyxLQUFLLENBQUM7cUJBQ2Q7aUJBQ0Q7YUFDRDtTQUNEO1FBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQztLQUNiOzs7Ozs7SUFFRCxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsS0FBSztRQUM1QixxQkFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLEVBQUUsQ0FBQSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztZQUM3QixxQkFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsRUFBRSxDQUFBLENBQUMsTUFBTSxDQUFDLENBQUEsQ0FBQztnQkFDVixHQUFHLENBQUEsQ0FBQyxxQkFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO29CQUNuRCxFQUFFLENBQUEsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUN6QyxPQUFPLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7cUJBQ3hDO2lCQUNEO2FBQ0Q7U0FDRDtRQUNELE1BQU0sQ0FBQyxPQUFPLENBQUM7S0FDZjs7Ozs7O0lBRUQsVUFBVSxDQUFDLEtBQWEsRUFBRSxPQUFlO1FBQ3hDLHFCQUFJLElBQUksR0FBUztZQUNoQixLQUFLLEVBQUUsS0FBSztZQUNaLE9BQU8sRUFBRyxPQUFPO1NBQ2pCLENBQUM7UUFDRixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLElBQUksRUFBRyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0tBQ3hEOzs7O0lBRUQsV0FBVztRQUNWLHFCQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7S0FDM0M7OztZQWhjRCxTQUFTLFNBQUM7Z0JBQ1YsU0FBUyxFQUFFLENBQUUsa0NBQWtDLENBQUU7Z0JBQ2pELFFBQVEsRUFBRSxnQkFBZ0I7Z0JBQzFCLE1BQU0sRUFBRSxDQUFDLHVnRUFBdWdFLENBQUM7Z0JBQ2poRSxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXlQVjthQUNBOzs7O1lBalJRLGdCQUFnQjtZQUNoQixTQUFTO1lBUmMsaUJBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBmb3J3YXJkUmVmLCBDaGFuZ2VEZXRlY3RvclJlZiwgVmlld0VuY2Fwc3VsYXRpb24sIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiwgQ29udHJvbFZhbHVlQWNjZXNzb3IsIEZvcm1Db250cm9sLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sVmFsdWVBY2Nlc3NvciB9IGZyb20gJy4uL2Fic3RyYWN0LWNvbnRyb2wtdmFsdWUtYWNjZXNvcic7XHJcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuXHJcbmltcG9ydCB7IFNlbGVjdGlvbk1vZGVsIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvbGxlY3Rpb25zJztcclxuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xyXG5pbXBvcnQgeyBNYXREaWFsb2csIE1BVF9ESUFMT0dfREFUQSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsJztcclxuXHJcbmltcG9ydCB7b2YgYXMgb2JzZXJ2YWJsZU9mfSBmcm9tICdyeGpzJztcclxuXHJcbmltcG9ydCB7Q2RrRHJhZ0Ryb3AsIG1vdmVJdGVtSW5BcnJheX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XHJcblxyXG5pbXBvcnQgKiBhcyBsb2Rhc2hfIGZyb20gJ2xvZGFzaCc7XHJcbmltcG9ydCB7IEVycm9yRGlhbG9nQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vZGlhbG9ncy9lcnJvci1kaWFsb2cvZXJyb3ItZGlhbG9nLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IENvbmZpcm1EaWFsb2dDb21wb25lbnQgfSBmcm9tICcuLi8uLi9kaWFsb2dzL2NvbmZpcm0tZGlhbG9nL2NvbmZpcm0tZGlhbG9nLmNvbXBvbmVudCc7XHJcblxyXG5jb25zdCBsb2Rhc2ggPSBsb2Rhc2hfO1xyXG5cclxuZXhwb3J0IGNvbnN0IElOUFVUX0lOUFVUX0NPTlRST0xfVkFMVUVfQUNDRVNTT1I6IGFueSA9IHtcclxuXHRwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuXHR1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBFZGl0YWJsZVRhYmxlQ29tcG9uZW50KSxcclxuXHRtdWx0aTogdHJ1ZSxcclxufTtcclxuXHJcbkBDb21wb25lbnQoe1xyXG5cdHByb3ZpZGVyczogWyBJTlBVVF9JTlBVVF9DT05UUk9MX1ZBTFVFX0FDQ0VTU09SIF0sXHJcblx0c2VsZWN0b3I6ICdlZGl0YWJsZS10YWJsZScsXHJcblx0c3R5bGVzOiBbYHRke3BhZGRpbmc6MTBweH0udGQtZHluYW1pYy1pbnB1dC13cmFwcGVyey1tcy1mbGV4LWRpcmVjdGlvbjpyb3c7ZmxleC1kaXJlY3Rpb246cm93O2Rpc3BsYXk6LW1zLWZsZXhib3g7ZGlzcGxheTpmbGV4O2JveC1zaXppbmc6Ym9yZGVyLWJveH0udGQtZHluYW1pYy1pbnB1dC13cmFwcGVyIC50ZC1keW5hbWljLWlucHV0LWZpZWxkey1tcy1mbGV4OjE7ZmxleDoxO2JveC1zaXppbmc6Ym9yZGVyLWJveH0udGQtZHluYW1pYy1pbnB1dC13cmFwcGVyIC5uZ3gtZWRpdG9ye21hcmdpbi10b3A6MTBweH0ubGFiZWx7cGFkZGluZzoxMHB4IDA7ZGlzcGxheTppbmxpbmUtYmxvY2s7d2lkdGg6NTAlfS5jb250YWluZXJ7b3ZlcmZsb3c6YXV0bztib3JkZXI6MXB4IHNvbGlkICNmM2YzZjM7Ym9yZGVyLXJhZGl1czo1cHggNXB4IDAgMH0uc2VsZWN0ZWQtaXRlbXN7cGFkZGluZzo1cHg7ZGlzcGxheTpibG9jaztiYWNrZ3JvdW5kOiNmM2YzZjM7Ym9yZGVyLXJhZGl1czowIDAgNXB4IDVweDttaW4taGVpZ2h0OjMwcHh9LnNlbGVjdGVkLWl0ZW1zIHNwYW57YmFja2dyb3VuZDojNjg5ZjM4O21hcmdpbjoycHg7cGFkZGluZzo1cHg7Ym9yZGVyLXJhZGl1czo1cHg7Y29sb3I6I2ZmZjtkaXNwbGF5OmlubGluZS1ibG9ja30uYnV0dG9uc3tkaXNwbGF5OmlubGluZS1ibG9jazt3aWR0aDo1MCU7dGV4dC1hbGlnbjpyaWdodH0uYnV0dG9ucyBidXR0b257cGFkZGluZzowO3dpZHRoOjMwcHghaW1wb3J0YW50O21pbi13aWR0aDozMHB4O2JvcmRlci1yYWRpdXM6NTBweDtoZWlnaHQ6MzBweH0uYnV0dG9ucyBidXR0b24gbWF0LWljb257cG9zaXRpb246cmVsYXRpdmUhaW1wb3J0YW50O3RvcDotNHB4IWltcG9ydGFudH0ubWFpbi1jb250YWluZXJ7Ym9yZGVyOjFweCBzb2xpZCAjZjNmM2YzO2JvcmRlci1yYWRpdXM6NXB4O3BhZGRpbmc6NXB4IDEwcHggMjBweDtvdmVyZmxvdzphdXRvfWhye2Rpc3BsYXk6YmxvY2s7aGVpZ2h0OjFweDtib3JkZXI6MDtib3JkZXItdG9wOjFweCBzb2xpZCAjY2NjO21hcmdpbjoxZW0gMDtwYWRkaW5nOjB9LmRyYWdnZXJ7dGV4dC1hbGlnbjpjZW50ZXI7YmFja2dyb3VuZDojZjNmM2YzO2hlaWdodDoyNHB4O2JvcmRlci1yYWRpdXM6NXB4O3dpZHRoOjM2cHg7bWFyZ2luOmF1dG8gOHB4IGF1dG8gYXV0bztib3JkZXI6MXB4IHNvbGlkICNkZGQ7Y3Vyc29yOm1vdmV9LmVycm9yLXZhbGlkYXRle2NvbG9yOiNlNTM5MzQ7Zm9udC1zaXplOjc1JTt0b3A6MzNweDtwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0OjB9LmVycm9yLXZhbGlkYXRlLmJvb2xlYW57cG9zaXRpb246cmVsYXRpdmUhaW1wb3J0YW50O3RvcDo5cHg7d2lkdGg6MTAwJTtkaXNwbGF5OmlubGluZS1ibG9ja30uZXJyb3ItdmFsaWRhdGUuZGF0ZXRpbWV7cG9zaXRpb246cmVsYXRpdmUhaW1wb3J0YW50O3RvcDo5cHg7cGFkZGluZy1ib3R0b206MTBweDt3aWR0aDoxMDAlO2Rpc3BsYXk6aW5saW5lLWJsb2NrfS5lZGl0YWJsZS1maWVsZHttaW4td2lkdGg6MTAwJX10YWJsZXt3aWR0aDoxMDAlO2JvcmRlci1jb2xsYXBzZTpjb2xsYXBzZTtib3JkZXItc3BhY2luZzowfXRyIHRoe3RleHQtYWxpZ246bGVmdH10cjpudGgtY2hpbGQoZXZlbil7YmFja2dyb3VuZDojZmFmYWZhfXRyOm50aC1jaGlsZChldmVuKSBpbnB1dHtiYWNrZ3JvdW5kOiNmYWZhZmEhaW1wb3J0YW50fS9kZWVwLyAudGltZS1maWVsZCBsYWJlbHtkaXNwbGF5OmJsb2NrO2NvbG9yOiM5MjkyOTI7bWFyZ2luLXRvcDotMTJweH0vZGVlcC8gLnRpbWUtZmllbGQgaW5wdXR7Ym9yZGVyOjA7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgIzllOWY5ZTtmb250LXNpemU6MTRweH0vZGVlcC8gLm1hdC1kYXRlcGlja2VyLXRvZ2dsZSBidXR0b257Ym94LXNoYWRvdzowIDNweCAxcHggLTJweCByZ2JhKDAsMCwwLC4yKSwwIDJweCAycHggMCByZ2JhKDAsMCwwLC4xNCksMCAxcHggNXB4IDAgcmdiYSgwLDAsMCwuMTIpO2JvcmRlci1yYWRpdXM6M3B4IWltcG9ydGFudH0vZGVlcC8gLnRpbWUtZmllbGR7bWFyZ2luLWJvdHRvbTo0cHh9LmRldGFpbHN7Zm9udC1zaXplOjExcHg7cGFkZGluZzo1cHggMH1gXSxcclxuXHR0ZW1wbGF0ZTogYDxkaXYgY2xhc3M9XCJsYWJlbFwiPnt7bGFiZWx9fTwvZGl2PlxyXG48ZGl2IGNsYXNzPVwibWFpbi1jb250YWluZXJcIj5cclxuICAgIDx0YWJsZSB0ZC1kYXRhLXRhYmxlPlxyXG4gICAgICAgIDx0aGVhZD5cclxuICAgICAgICAgICAgPHRyIHRkLWRhdGEtdGFibGUtY29sdW1uLXJvdz5cclxuICAgICAgICAgICAgICAgIDx0aCB0ZC1kYXRhLXRhYmxlLWNvbHVtbj5cclxuICAgICAgICAgICAgICAgICAgICB7e2FkZFRpdGxlfX1cclxuICAgICAgICAgICAgICAgIDwvdGg+XHJcbiAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgPC90aGVhZD5cclxuICAgICAgICA8dGJvZHk+XHJcbiAgICAgICAgICAgIDx0ciB0ZC1kYXRhLXRhYmxlLXJvdz5cclxuICAgICAgICAgICAgICAgIDx0ZCB0ZC1kYXRhLXRhYmxlLWNlbGwgKm5nRm9yPVwibGV0IGl0ZW0gb2Ygc2NoZW1hOyBsZXQgaT1pbmRleFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpdGVtLnR5cGUgPT0gJ3N0cmluZydcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZWRpdGFibGUtZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBhdXRvY29tcGxldGU9XCJvZmZcIiBwbGFjZWhvbGRlcj1cInt7aXRlbS5sYWJlbH19XCIgWyhuZ01vZGVsKV09XCJuZXdFbGVtZW50W2l0ZW0ubmFtZV1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW0udHlwZSA9PSAnZGF0ZSdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZWRpdGFibGUtZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBhdXRvY29tcGxldGU9XCJvZmZcIiBbbWF0RGF0ZXBpY2tlcl09XCJpXCIgcGxhY2Vob2xkZXI9XCJ7e2l0ZW0ubGFiZWx9fVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuaWRdPVwiJ2R0UGlja2VyJyArIGlcIiBbKG5nTW9kZWwpXT1cIm5ld0VsZW1lbnRbaXRlbS5uYW1lXVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1kYXRlcGlja2VyLXRvZ2dsZSBtYXRTdWZmaXggW2Zvcl09XCJpXCI+PC9tYXQtZGF0ZXBpY2tlci10b2dnbGU+PG1hdC1kYXRlcGlja2VyICNpPjwvbWF0LWRhdGVwaWNrZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpdGVtLnR5cGUgPT0gJ3RpbWUnXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lLWZpZWxkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJ0aW1lTGFiZWxcIj5Ib3JhPC9sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBhcmlhLWxhYmVsPVwiZGVmYXVsdCB0aW1lXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCIgW25neFRpbWVwaWNrZXJdPVwiZGVmYXVsdFRpbWVcIiBbKG5nTW9kZWwpXT1cIm5ld0VsZW1lbnRbaXRlbS5uYW1lXVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5neC1tYXRlcmlhbC10aW1lcGlja2VyICNkZWZhdWx0VGltZT48L25neC1tYXRlcmlhbC10aW1lcGlja2VyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcblx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiaXRlbS50eXBlID09ICdkYXRlVGltZSdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRhdGUtdGltZS1waWNrZXIgW21pbl09XCJpdGVtLm1pblwiIFttYXhdPVwiaXRlbS5tYXhcIiBbKG15TW9kZWwpXT1cIm5ld0VsZW1lbnRbaXRlbS5uYW1lXVwiPjwvZGF0ZS10aW1lLXBpY2tlcj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW0udHlwZSA9PSAnbnVtYmVyJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJlZGl0YWJsZS1maWVsZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IHR5cGU9XCJudW1iZXJcIiBhdXRvY29tcGxldGU9XCJvZmZcIiBwbGFjZWhvbGRlcj1cInt7aXRlbS5sYWJlbH19XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cIm5ld0VsZW1lbnRbaXRlbS5uYW1lXVwiIG1pbj1cInt7aXRlbS5taW59fVwiIG1heD1cInt7aXRlbS5tYXh9fVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXRlbS50eXBlID09ICdib29sZWFuJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWNoZWNrYm94IFsobmdNb2RlbCldPVwibmV3RWxlbWVudFtpdGVtLm5hbWVdXCI+e3tpdGVtLmxhYmVsfX08L21hdC1jaGVja2JveD5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW0udHlwZSA9PSAnc2VsZWN0J1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJlZGl0YWJsZS1maWVsZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zZWxlY3QgcGxhY2Vob2xkZXI9XCJ7e2l0ZW0ubGFiZWx9fVwiIFsodmFsdWUpXT1cIm5ld0VsZW1lbnRbaXRlbS5uYW1lXVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uPi4uLjwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cInt7aXRlbS52YWx1ZX19XCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgaXRlbS5pdGVtcztcIj57e2l0ZW0ubGFiZWx9fTwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiAoY2xpY2spPVwiYWRkSXRlbSgpXCI+QcOxYWRpcjwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC90cj5cclxuICAgICAgICA8L3Rib2R5PlxyXG4gICAgPC90YWJsZT5cclxuXHJcbiAgICA8aHIgLz5cclxuXHJcbiAgICA8dGFibGUgdGQtZGF0YS10YWJsZT5cclxuICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICAgIDx0ciB0ZC1kYXRhLXRhYmxlLWNvbHVtbi1yb3c+XHJcbiAgICAgICAgICAgICAgICA8dGggdGQtZGF0YS10YWJsZS1jb2x1bW4gKm5nSWY9XCJkcmFnZ2FibGVcIj48L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoIHRkLWRhdGEtdGFibGUtY29sdW1uXHJcbiAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGNvbHVtbiBvZiBzY2hlbWFcIj5cclxuICAgICAgICAgICAgICAgICAgICB7e2NvbHVtbi5sYWJlbH19XHJcbiAgICAgICAgICAgICAgICA8L3RoPlxyXG4gICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgIDwvdGhlYWQ+XHJcbiAgICAgICAgPHRib2R5IGNka0Ryb3BMaXN0IGNsYXNzPVwiZXhhbXBsZS1saXN0XCIgKGNka0Ryb3BMaXN0RHJvcHBlZCk9XCJkcm9wKCRldmVudClcIj5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImRyYWdnYWJsZVwiPlxyXG4gICAgICAgICAgICAgICAgPCEtLURSQUdHQUJMRTogSVNTVUUgIzEzODkzLS0+XHJcbiAgICAgICAgICAgICAgICA8dHIgdGQtZGF0YS10YWJsZS1yb3cgKm5nRm9yPVwibGV0IHJvdyBvZiB2YWx1ZTsgbGV0IHo9aW5kZXhcIiBjZGtEcmFnPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0ZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRyYWdnZXJcIiBjZGtEcmFnSGFuZGxlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmRyYWdfaGFuZGxlPC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgICAgICA8dGQgdGQtZGF0YS10YWJsZS1jZWxsICpuZ0Zvcj1cImxldCBhdHRyIG9mIHNjaGVtYTsgbGV0IGk9aW5kZXhcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImF0dHIudHlwZSA9PSAnc3RyaW5nJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZWRpdGFibGUtZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgcGxhY2Vob2xkZXI9XCJ7e2F0dHIubGFiZWx9fVwiIFsobmdNb2RlbCldPVwicm93W2F0dHIubmFtZV1cIiBhdXRvY29tcGxldGU9XCJvZmZcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJjaGFuZ2VzT3V0KCRldmVudClcIiBbcmVxdWlyZWRdPVwiYXR0ci5yZXF1aXJlZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZXJyb3ItdmFsaWRhdGVcIiAqbmdJZj1cIiFpc1ZhbGlkKHJvdywgYXR0ci5uYW1lKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2ZpZWxkRXJyb3JNZXNzYWdlKHJvdywgYXR0ci5uYW1lKSB8IHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiYXR0ci50eXBlID09ICdkYXRlJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZWRpdGFibGUtZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgYXV0b2NvbXBsZXRlPVwib2ZmXCIgW21hdERhdGVwaWNrZXJdPVwialwiIHBsYWNlaG9sZGVyPVwie3thdHRyLmxhYmVsfX1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5pZF09XCInZHRQaWNrZXInICsgalwiIFsobmdNb2RlbCldPVwicm93W2F0dHIubmFtZV1cIiAobmdNb2RlbENoYW5nZSk9XCJjaGFuZ2VzT3V0KCRldmVudClcIiBbcmVxdWlyZWRdPVwiYXR0ci5yZXF1aXJlZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZGF0ZXBpY2tlci10b2dnbGUgbWF0U3VmZml4IFtmb3JdPVwialwiPjwvbWF0LWRhdGVwaWNrZXItdG9nZ2xlPjxtYXQtZGF0ZXBpY2tlciAjaj48L21hdC1kYXRlcGlja2VyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZXJyb3ItdmFsaWRhdGVcIiAqbmdJZj1cIiFpc1ZhbGlkKHJvdywgYXR0ci5uYW1lKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2ZpZWxkRXJyb3JNZXNzYWdlKHJvdywgYXR0ci5uYW1lKSB8IHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG5cdFx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiYXR0ci50eXBlID09ICd0aW1lJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpbWUtZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJ0aW1lTGFiZWxcIj5Ib3JhPC9sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgYXV0b2NvbXBsZXRlPVwib2ZmXCIgYXJpYS1sYWJlbD1cImRlZmF1bHQgdGltZVwiIFtuZ3hUaW1lcGlja2VyXT1cImRlZmF1bHRUaW1lXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInJvd1thdHRyLm5hbWVdXCIgcmVhZG9ubHkgKG5nTW9kZWxDaGFuZ2UpPVwiY2hhbmdlc091dCgkZXZlbnQpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5neC1tYXRlcmlhbC10aW1lcGlja2VyICNkZWZhdWx0VGltZT48L25neC1tYXRlcmlhbC10aW1lcGlja2VyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZXJyb3ItdmFsaWRhdGVcIiAqbmdJZj1cIiFpc1ZhbGlkKHJvdywgYXR0ci5uYW1lKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2ZpZWxkRXJyb3JNZXNzYWdlKHJvdywgYXR0ci5uYW1lKSB8IHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcblx0ICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcblx0XHRcdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCJhdHRyLnR5cGUgPT0gJ2RhdGVUaW1lJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRhdGUtdGltZS1waWNrZXIgW21pbl09XCJhdHRyLm1pblwiIFttYXhdPVwiYXR0ci5tYXhcIiBbKG15TW9kZWwpXT1cIm5ld0VsZW1lbnRbYXR0ci5uYW1lXVwiIChteU1vZGVsQ2hhbmdlKT1cImNoYW5nZXNPdXQoJGV2ZW50KVwiPjwvZGF0ZS10aW1lLXBpY2tlcj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZXJyb3ItdmFsaWRhdGUgZGF0ZXRpbWVcIiAqbmdJZj1cIiFpc1ZhbGlkKHJvdywgYXR0ci5uYW1lKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7ZmllbGRFcnJvck1lc3NhZ2Uocm93LCBhdHRyLm5hbWUpIHwgdHJhbnNsYXRlfX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cclxuXHQgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImF0dHIudHlwZSA9PSAnbnVtYmVyJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZWRpdGFibGUtZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgdHlwZT1cIm51bWJlclwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiIHBsYWNlaG9sZGVyPVwie3thdHRyLmxhYmVsfX1cIiBbKG5nTW9kZWwpXT1cInJvd1thdHRyLm5hbWVdXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiY2hhbmdlc091dCgkZXZlbnQpXCIgbWluPVwie3thdHRyLm1pbn19XCIgbWF4PVwie3thdHRyLm1heH19XCIgW3JlcXVpcmVkXT1cImF0dHIucmVxdWlyZWRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImVycm9yLXZhbGlkYXRlXCIgKm5nSWY9XCIhaXNWYWxpZChyb3csIGF0dHIubmFtZSlcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tmaWVsZEVycm9yTWVzc2FnZShyb3csIGF0dHIubmFtZSkgfCB0cmFuc2xhdGV9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+