UNPKG

@hpe/angular-toolkit

Version:

Hewlett-Packard Enterprise : Angular toolkit for rapid project development

711 lines (679 loc) 73 kB
import { Component, Input, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { Lib } from '@hpe/angular-toolkit/lib'; import { AppEvent, Credentials } from '@hpe/angular-toolkit/model'; import { AbstractSubscriber, EventBusService, HttpService, LabelService, NotificationService, SessionService, HpeServiceModule } from '@hpe/angular-toolkit/service'; import { CommonModule } from '@angular/common'; import { MatCheckboxModule, MatButtonModule } from '@angular/material'; import { DropdownModule, InputTextModule } from 'primeng/primeng'; import { HpePanelModule } from '@hpe/angular-toolkit/gui/panel'; import { HpeDirectiveModule } from '@hpe/angular-toolkit/gui/directive'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class FormColumn { } FormColumn.decorators = [ { type: Component, args: [{ selector: 'hpe-form-column', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <div class="formColumn" [style.width]="width"> <ng-content></ng-content> </div> `, styles: [`.formColumn{display:flex;flex-direction:column;align-content:center;justify-content:flex-start;margin:8px}`], },] }, ]; /** @nocollapse */ FormColumn.propDecorators = { "width": [{ type: Input },], }; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class FormLabel { constructor() { } } FormLabel.decorators = [ { type: Component, args: [{ selector: 'hpe-form-label', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <span class="ui-inputgroup-addon label"> <hpe-icon name="{{icon}}"></hpe-icon> {{label}} </span> `, styles: [`.label{width:12rem;text-align:start!important}:host ::ng-deep .iconStyle{vertical-align:baseline}`], },] }, ]; //------------------------------------------------------------------------- //--- //--- API methods //--- //------------------------------------------------------------------------- /** @nocollapse */ FormLabel.ctorParameters = () => []; FormLabel.propDecorators = { "icon": [{ type: Input },], "label": [{ type: Input },], }; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class FormPanel { } FormPanel.decorators = [ { type: Component, args: [{ selector: 'hpe-form-panel', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <div class="formBody"> <ng-content></ng-content> </div> `, styles: [`.formBody{display:flex;align-content:center;justify-content:center;flex-wrap:wrap;box-sizing:border-box;width:100%;max-width:100%;padding:1rem;background:#fafafa;color:#000;font-size:1rem}`], },] }, ]; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class FormText { constructor() { } /** * @return {?} */ get value() { return this._value; } /** * @param {?} value * @return {?} */ set value(value) { if (this.transcoder && value != null) { value = this.transcoder.transcode(value); } this._value = value; } } FormText.decorators = [ { type: Component, args: [{ selector: 'hpe-form-text', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <div class="ui-inputgroup spacing"> <hpe-form-label [icon]="icon" [label]="label"></hpe-form-label> <span class="ui-inputgroup-addon text">{{value}}</span> </div> `, styles: [`.spacing{margin-bottom:1rem}.text{background-color:#f5f5f5;width:100%;color:#202020}`] },] }, ]; /** @nocollapse */ FormText.ctorParameters = () => []; FormText.propDecorators = { "icon": [{ type: Input },], "label": [{ type: Input },], "transcoder": [{ type: Input },], "value": [{ type: Input },], }; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class AbstractFormComponent { constructor() { this.enabled = true; this._required = false; } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { } /** * @return {?} */ getComponentClass() { let /** @type {?} */ styles = ['control']; if (this.enabled) { if (this.required) { if (this.isProvided()) { styles.push("provided"); } else { styles.push("required"); } } } else { styles.push("disabled"); } return styles; } /** * @return {?} */ get required() { return this._required; } /** * @param {?} value * @return {?} */ set required(value) { let /** @type {?} */ str = "" + value; if (str == "") { //--- Ok, '' means value not provided --> true value = true; } this._required = value; } } AbstractFormComponent.propDecorators = { "icon": [{ type: Input },], "label": [{ type: Input },], "enabled": [{ type: Input },], "required": [{ type: Input },], }; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class InputText extends AbstractFormComponent { constructor() { super(); } /** * @param {?} value * @return {?} */ writeValue(value) { this._value = value; } /** * @return {?} */ get value() { return this._value; } /** * @param {?} newValue * @return {?} */ set value(newValue) { if (newValue == "") { newValue = null; } this._value = newValue; this.onChange(newValue); } /** * @return {?} */ isProvided() { return Lib.str.isProvided(this.value); } } InputText.decorators = [ { type: Component, args: [{ selector: 'hpe-input-text', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <div class="ui-inputgroup spacing"> <hpe-form-label [icon]="icon" [label]="label"></hpe-form-label> <input pInputText [(ngModel)]="value" [ngClass]="getComponentClass()" [disabled]="!enabled"> </div> `, styles: [`.spacing{margin-bottom:1rem}.control{width:100%}.required,.required:focus{border-right:5px solid #ff8d6d}.provided,.provided:focus{border-right:5px solid #00a982}`], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: InputText, multi: true }] },] }, ]; /** @nocollapse */ InputText.ctorParameters = () => []; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class InputArea extends InputText { constructor() { super(); } } InputArea.decorators = [ { type: Component, args: [{ selector: 'hpe-input-area', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <div class="ui-inputgroup spacing" > <hpe-form-label [icon]="icon" [label]="label"></hpe-form-label> <textarea pInputTextarea [style.height]="height" [(ngModel)]="value" [ngClass]="getComponentClass()" [disabled]="!enabled"></textarea> </div> `, styles: [`.spacing{margin-bottom:1rem}.control{width:100%}.required,.required:focus{border-right:5px solid #ff8d6d}.provided,.provided:focus{border-right:5px solid #00a982}`], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: InputArea, multi: true }] },] }, ]; /** @nocollapse */ InputArea.ctorParameters = () => []; InputArea.propDecorators = { "height": [{ type: Input },], }; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class InputCheckbox extends InputText { constructor() { super(); } } InputCheckbox.decorators = [ { type: Component, args: [{ selector: 'hpe-input-checkbox', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <div class="ui-inputgroup spacing"> <hpe-form-label [icon]="icon" [label]="label"></hpe-form-label> <mat-checkbox [(ngModel)]="value" [ngClass]="getComponentClass()" [disabled]="!enabled"></mat-checkbox> </div> `, styles: [`.spacing{margin-bottom:1rem}.control{width:100%;margin-top:4px;margin-left:10px}.required{border-right:5px solid #ff8d6d}.provided{border-right:5px solid #00a982}:host ::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background{background-color:#80746e}`], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: InputCheckbox, multi: true }] },] }, ]; /** @nocollapse */ InputCheckbox.ctorParameters = () => []; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class InputCombo extends AbstractFormComponent { constructor() { super(); } /** * @return {?} */ get dataMap() { return this._dataMap; } /** * @param {?} map * @return {?} */ set dataMap(map) { this._dataMap = map; this.key = "id"; this.value = "value"; let /** @type {?} */ list = []; if (!this.required) { list.push({ "id": null, "value": null }); } for (let /** @type {?} */ key in map) { let /** @type {?} */ name = Number(key); let /** @type {?} */ value = map[key]; if (isNaN(name)) { name = key; } list.push({ "id": name, "value": value }); } this.data = list; } /** * @param {?} keyValue * @return {?} */ writeValue(keyValue) { let /** @type {?} */ item = this.data.find((item) => { return (item[this.key] == keyValue); }); //--- Select first entry in case there is no match if (item == null) { if (this.data != null && this.data.length > 0) { item = this.data[0]; } } this._selectedItem = item; } /** * @return {?} */ get selectedItem() { return this._selectedItem; } /** * @param {?} newItem * @return {?} */ set selectedItem(newItem) { this._selectedItem = newItem; this.onChange(newItem[this.key]); } /** * @return {?} */ isProvided() { return (this.selectedItem != null && this.selectedItem[this.key] != null); } } InputCombo.decorators = [ { type: Component, args: [{ selector: 'hpe-input-combo', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <div class="ui-inputgroup spacing"> <hpe-form-label [icon]="icon" [label]="label"></hpe-form-label> <p-dropdown [options] = "data" [dataKey] = "key" [optionLabel]= "value" [(ngModel)] = "selectedItem" [ngClass] = "getComponentClass()" [style] = "{ 'width':'100%' }" [disabled] = "!enabled"> </p-dropdown> </div> `, styles: [`.spacing{margin-bottom:1rem}.control{width:100%}.required{border-right:5px solid #ff8d6d}.provided{border-right:5px solid #00a982}`], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: InputCombo, multi: true }] },] }, ]; /** @nocollapse */ InputCombo.ctorParameters = () => []; InputCombo.propDecorators = { "key": [{ type: Input },], "value": [{ type: Input },], "data": [{ type: Input },], "dataMap": [{ type: Input },], }; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class LoginPanel extends AbstractSubscriber { /** * @param {?} eventBusService * @param {?} sessionService * @param {?} notificationService * @param {?} labelService * @param {?} httpService */ constructor(eventBusService, sessionService, notificationService, labelService, httpService) { super(eventBusService); this.sessionService = sessionService; this.notificationService = notificationService; this.labelService = labelService; this.httpService = httpService; //------------------------------------------------------------------------- //--- //--- Variables //--- //------------------------------------------------------------------------- this.cred = new Credentials(); super.subscribeToApp(AppEvent.LOGIN_FAILED, event => this.onLoginFailed(event)); } /** * @return {?} */ login() { if (!this.areCredentialsValid()) { let /** @type {?} */ msg = this.labelService.getLabel("login-panel", "missing.info"); this.notificationService.showWarn(msg["title"], msg["descr"]); } else { this.sessionService.login(this.cred); } } /** * @return {?} */ get title() { return this.loc("title"); } /** * @return {?} */ get username() { return this.loc("username"); } /** * @return {?} */ get password() { return this.loc("password"); } /** * @return {?} */ get button() { return this.loc("button"); } /** * @param {?} event * @return {?} */ onLoginFailed(event) { let /** @type {?} */ msg = this.labelService.getLabel("login-panel", "login.error"); this.notificationService.showError(msg["title"], msg["descr"]); } /** * @return {?} */ areCredentialsValid() { return Lib.str.isProvided(this.cred.username) && Lib.str.isProvided(this.cred.password); } /** * @param {?} code * @return {?} */ loc(code) { return this.labelService.getLabel("login-panel", code); } } LoginPanel.decorators = [ { type: Component, args: [{ selector: 'hpe-login', template: `<!-- ============================================================================= === === (C) Copyright 2018 Hewlett Packard Enterprise Development LP. === === Use of this source code is governed by an MIT-style license that can be === found in the LICENSE file ============================================================================= --> <hpe-card-panel icon="fa-sign-in" [title]="title" [toggleButton]="false"> <div cpBody> <hpe-form-panel> <hpe-form-column width="500px"> <hpe-input-text icon="fa-user" [label]="username" [(ngModel)]="cred.username" required></hpe-input-text> <hpe-input-text icon="fa-key" [label]="password" [(ngModel)]="cred.password" required></hpe-input-text> </hpe-form-column> </hpe-form-panel> <hpe-button-panel> <div class="spinner" *ngIf="httpService.loading"> <i class="fa fa-circle-o-notch fa-pulse"></i> </div> <button mat-button hpeButton (click)="login()">{{button}}</button> </hpe-button-panel> </div> </hpe-card-panel> `, styles: [`.spinner{position:absolute;left:16px;bottom:16px;font-size:32px}`] },] }, ]; /** @nocollapse */ LoginPanel.ctorParameters = () => [ { type: EventBusService, }, { type: SessionService, }, { type: NotificationService, }, { type: LabelService, }, { type: HttpService, }, ]; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= class HpeFormModule { } HpeFormModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, FormsModule, MatCheckboxModule, MatButtonModule, DropdownModule, InputTextModule, HpePanelModule, HpeDirectiveModule, HpeServiceModule ], declarations: [ FormColumn, FormLabel, FormPanel, FormText, InputArea, InputCheckbox, InputCombo, InputText, LoginPanel ], exports: [ FormColumn, FormLabel, FormPanel, FormText, InputArea, InputCheckbox, InputCombo, InputText, LoginPanel ], providers: [], },] }, ]; //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ //============================================================================= /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ export { HpeFormModule, FormColumn, FormLabel, FormPanel, FormText, InputArea, InputCheckbox, InputCombo, InputText, LoginPanel, AbstractFormComponent as ɵa }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHBlLWFuZ3VsYXItdG9vbGtpdC1ndWktZm9ybS5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvZ3VpL2Zvcm0vZm9ybS1jb2x1bW4vZm9ybS1jb2x1bW4udHMiLCJuZzovL0BocGUvYW5ndWxhci10b29sa2l0L2d1aS9mb3JtL2Zvcm0tbGFiZWwvZm9ybS1sYWJlbC50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvZ3VpL2Zvcm0vZm9ybS1wYW5lbC9mb3JtLXBhbmVsLnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9ndWkvZm9ybS9mb3JtLXRleHQvZm9ybS10ZXh0LnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9ndWkvZm9ybS9hYnN0cmFjdC1mb3JtLWNvbXBvbmVudC50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvZ3VpL2Zvcm0vaW5wdXQtdGV4dC9pbnB1dC10ZXh0LnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9ndWkvZm9ybS9pbnB1dC1hcmVhL2lucHV0LWFyZWEudHMiLCJuZzovL0BocGUvYW5ndWxhci10b29sa2l0L2d1aS9mb3JtL2lucHV0LWNoZWNrYm94L2lucHV0LWNoZWNrYm94LnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9ndWkvZm9ybS9pbnB1dC1jb21iby9pbnB1dC1jb21iby50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvZ3VpL2Zvcm0vbG9naW4vbG9naW4udHMiLCJuZzovL0BocGUvYW5ndWxhci10b29sa2l0L2d1aS9mb3JtL21vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLz09PVxuLy89PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuLy89PT1cbi8vPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4vLz09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmltcG9ydCB7Q29tcG9uZW50LCBJbnB1dH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yICAgIDogICAgICdocGUtZm9ybS1jb2x1bW4nLFxuXHR0ZW1wbGF0ZTogYDwhLS1cbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG49PT1cbj09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG49PT1cbj09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4tLT5cblxuPGRpdiBjbGFzcz1cImZvcm1Db2x1bW5cIiBbc3R5bGUud2lkdGhdPVwid2lkdGhcIj5cbiAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG48L2Rpdj5cbmAsXG5cdHN0eWxlczogW2AuZm9ybUNvbHVtbntkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246Y29sdW1uO2FsaWduLWNvbnRlbnQ6Y2VudGVyO2p1c3RpZnktY29udGVudDpmbGV4LXN0YXJ0O21hcmdpbjo4cHh9YF0sXG59KVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBGb3JtQ29sdW1uICAgIHtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gVmFyaWFibGVzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdEBJbnB1dCgpIHdpZHRoIDogc3RyaW5nO1xufVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iLCIvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLz09PVxuLy89PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuLy89PT1cbi8vPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4vLz09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmltcG9ydCB7Q29tcG9uZW50LCBJbnB1dH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yICAgIDogICAgICdocGUtZm9ybS1sYWJlbCcsXG5cdHRlbXBsYXRlOiBgPCEtLVxuPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbj09PVxuPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbj09PVxuPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG49PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi0tPlxuXG48c3BhbiBjbGFzcz1cInVpLWlucHV0Z3JvdXAtYWRkb24gbGFiZWxcIj5cblx0PGhwZS1pY29uIG5hbWU9XCJ7e2ljb259fVwiPjwvaHBlLWljb24+IHt7bGFiZWx9fVxuPC9zcGFuPlxuYCxcblx0c3R5bGVzOiBbYC5sYWJlbHt3aWR0aDoxMnJlbTt0ZXh0LWFsaWduOnN0YXJ0IWltcG9ydGFudH06aG9zdCA6Om5nLWRlZXAgLmljb25TdHlsZXt2ZXJ0aWNhbC1hbGlnbjpiYXNlbGluZX1gXSxcbn0pXG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGNsYXNzIEZvcm1MYWJlbCAgICB7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFZhcmlhYmxlc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRASW5wdXQoKSBpY29uICA6IHN0cmluZztcblx0QElucHV0KCkgbGFiZWwgOiBzdHJpbmc7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIENvbnN0cnVjdG9yXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGNvbnN0cnVjdG9yKCkge31cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQVBJIG1ldGhvZHNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsIi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vPT09XG4vLz09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG4vLz09PVxuLy89PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbi8vPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtDb21wb25lbnR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvciAgICA6ICAgICAnaHBlLWZvcm0tcGFuZWwnLFxuXHR0ZW1wbGF0ZTogYDwhLS1cbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG49PT1cbj09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG49PT1cbj09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4tLT5cblxuPGRpdiBjbGFzcz1cImZvcm1Cb2R5XCI+XG5cdDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbjwvZGl2PlxuYCxcblx0c3R5bGVzOiBbYC5mb3JtQm9keXtkaXNwbGF5OmZsZXg7YWxpZ24tY29udGVudDpjZW50ZXI7anVzdGlmeS1jb250ZW50OmNlbnRlcjtmbGV4LXdyYXA6d3JhcDtib3gtc2l6aW5nOmJvcmRlci1ib3g7d2lkdGg6MTAwJTttYXgtd2lkdGg6MTAwJTtwYWRkaW5nOjFyZW07YmFja2dyb3VuZDojZmFmYWZhO2NvbG9yOiMwMDA7Zm9udC1zaXplOjFyZW19YF0sXG59KVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBGb3JtUGFuZWwgICAge1xufVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iLCIvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLz09PVxuLy89PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuLy89PT1cbi8vPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4vLz09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmltcG9ydCB7Q29tcG9uZW50LElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1RyYW5zY29kZXJ9ICAgICAgIGZyb20gXCJAaHBlL2FuZ3VsYXItdG9vbGtpdC9tb2RlbFwiO1xuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvciAgICA6ICAgICAnaHBlLWZvcm0tdGV4dCcsXG5cdHRlbXBsYXRlOiBgPCEtLVxuPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbj09PVxuPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbj09PVxuPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG49PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi0tPlxuXG48ZGl2IGNsYXNzPVwidWktaW5wdXRncm91cCBzcGFjaW5nXCI+XG5cdDxocGUtZm9ybS1sYWJlbCBbaWNvbl09XCJpY29uXCIgW2xhYmVsXT1cImxhYmVsXCI+PC9ocGUtZm9ybS1sYWJlbD5cblx0PHNwYW4gY2xhc3M9XCJ1aS1pbnB1dGdyb3VwLWFkZG9uIHRleHRcIj57e3ZhbHVlfX08L3NwYW4+XG48L2Rpdj5cbmAsXG5cdHN0eWxlczogW2Auc3BhY2luZ3ttYXJnaW4tYm90dG9tOjFyZW19LnRleHR7YmFja2dyb3VuZC1jb2xvcjojZjVmNWY1O3dpZHRoOjEwMCU7Y29sb3I6IzIwMjAyMH1gXVxufSlcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgY2xhc3MgRm9ybVRleHQge1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBWYXJpYWJsZXNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0QElucHV0KCkgaWNvbiAgICAgICA6IHN0cmluZztcblx0QElucHV0KCkgbGFiZWwgICAgICA6IHN0cmluZztcblx0QElucHV0KCkgdHJhbnNjb2RlciA6IFRyYW5zY29kZXI7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSBfdmFsdWUgOiBzdHJpbmc7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIENvbnN0cnVjdG9yXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGNvbnN0cnVjdG9yKCkge31cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQVBJIG1ldGhvZHNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0QElucHV0KClcblx0Z2V0IHZhbHVlKCkgOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLl92YWx1ZTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHNldCB2YWx1ZSh2YWx1ZSkge1xuXG5cdFx0aWYgKHRoaXMudHJhbnNjb2RlciAmJiB2YWx1ZSE9bnVsbCkge1xuXHRcdFx0dmFsdWUgPSAgdGhpcy50cmFuc2NvZGVyLnRyYW5zY29kZSh2YWx1ZSk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fdmFsdWUgPSB2YWx1ZTtcblx0fVxufVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iLCIvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLz09PVxuLy89PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuLy89PT1cbi8vPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4vLz09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmltcG9ydCB7SW5wdXR9ICAgICAgICAgICAgICAgIGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtDb250cm9sVmFsdWVBY2Nlc3Nvcn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBBYnN0cmFjdEZvcm1Db21wb25lbnQgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFZhcmlhYmxlc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRASW5wdXQoKSBpY29uICAgIDogc3RyaW5nO1xuXHRASW5wdXQoKSBsYWJlbCAgIDogc3RyaW5nO1xuXHRASW5wdXQoKSBlbmFibGVkIDogYm9vbGVhbjtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIF9yZXF1aXJlZCA6IGJvb2xlYW47XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJvdGVjdGVkIG9uQ2hhbmdlIDogYW55O1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBDb25zdHJ1Y3RvclxuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHR0aGlzLmVuYWJsZWQgICA9IHRydWU7XG5cdFx0dGhpcy5fcmVxdWlyZWQgPSBmYWxzZTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBBUEkgbWV0aG9kc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRyZWdpc3Rlck9uQ2hhbmdlKGZuKSB7XG5cdFx0dGhpcy5vbkNoYW5nZSA9IGZuO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cmVnaXN0ZXJPblRvdWNoZWQoZm4pIHt9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIGdldENvbXBvbmVudENsYXNzKCkgOiBzdHJpbmdbXSB7XG5cblx0XHRsZXQgc3R5bGVzIDogc3RyaW5nW10gPSBbICdjb250cm9sJyBdO1xuXG5cdFx0aWYgKHRoaXMuZW5hYmxlZCkge1xuXHRcdFx0aWYgKHRoaXMucmVxdWlyZWQpIHtcblx0XHRcdFx0aWYgKHRoaXMuaXNQcm92aWRlZCgpKSB7XG5cdFx0XHRcdFx0c3R5bGVzLnB1c2goXCJwcm92aWRlZFwiKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRzdHlsZXMucHVzaChcInJlcXVpcmVkXCIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0c3R5bGVzLnB1c2goXCJkaXNhYmxlZFwiKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gc3R5bGVzO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tICdyZXF1aXJlZCcgYXR0cmlidXRlXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdEBJbnB1dCgpXG5cdGdldCByZXF1aXJlZCgpIDogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX3JlcXVpcmVkO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0c2V0IHJlcXVpcmVkKHZhbHVlOmJvb2xlYW4pIHtcblxuXHRcdGxldCBzdHIgOiBzdHJpbmcgPSBcIlwiK3ZhbHVlO1xuXG5cdFx0aWYgKHN0ciA9PSBcIlwiKSB7XG5cdFx0XHQvLy0tLSBPaywgJycgbWVhbnMgdmFsdWUgbm90IHByb3ZpZGVkIC0tPiB0cnVlXG5cdFx0XHR2YWx1ZSA9IHRydWU7XG5cdFx0fVxuXG5cdFx0dGhpcy5fcmVxdWlyZWQgPSB2YWx1ZTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLSBBYnN0cmFjdCBtZXRob2RzXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBhYnN0cmFjdCB3cml0ZVZhbHVlKHZhbHVlKSA6IHZvaWQ7XG5cblx0cHJvdGVjdGVkIGFic3RyYWN0IGlzUHJvdmlkZWQoKSA6IGJvb2xlYW47XG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsIi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vPT09XG4vLz09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG4vLz09PVxuLy89PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbi8vPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtDb21wb25lbnQgfSAgICAgICAgZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge05HX1ZBTFVFX0FDQ0VTU09SfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge0xpYn0gICAgICAgICAgICAgICBmcm9tIFwiQGhwZS9hbmd1bGFyLXRvb2xraXQvbGliXCI7XG5cbmltcG9ydCB7QWJzdHJhY3RGb3JtQ29tcG9uZW50fSBmcm9tIFwiLi4vYWJzdHJhY3QtZm9ybS1jb21wb25lbnRcIjtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3IgICAgOiAgICAgJ2hwZS1pbnB1dC10ZXh0Jyxcblx0dGVtcGxhdGU6IGA8IS0tXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuPT09XG49PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuPT09XG49PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbj09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLS0+XG5cbjxkaXYgY2xhc3M9XCJ1aS1pbnB1dGdyb3VwIHNwYWNpbmdcIj5cbiAgICA8aHBlLWZvcm0tbGFiZWwgW2ljb25dPVwiaWNvblwiIFtsYWJlbF09XCJsYWJlbFwiPjwvaHBlLWZvcm0tbGFiZWw+XG5cdDxpbnB1dCBwSW5wdXRUZXh0IFsobmdNb2RlbCldPVwidmFsdWVcIiBbbmdDbGFzc109XCJnZXRDb21wb25lbnRDbGFzcygpXCIgW2Rpc2FibGVkXT1cIiFlbmFibGVkXCI+XG48L2Rpdj5cblxuYCxcblx0c3R5bGVzOiBbYC5zcGFjaW5ne21hcmdpbi1ib3R0b206MXJlbX0uY29udHJvbHt3aWR0aDoxMDAlfS5yZXF1aXJlZCwucmVxdWlyZWQ6Zm9jdXN7Ym9yZGVyLXJpZ2h0OjVweCBzb2xpZCAjZmY4ZDZkfS5wcm92aWRlZCwucHJvdmlkZWQ6Zm9jdXN7Ym9yZGVyLXJpZ2h0OjVweCBzb2xpZCAjMDBhOTgyfWBdLFxuXHRwcm92aWRlcnMgICA6IFsge1xuXHRcdHByb3ZpZGUgICAgOiBOR19WQUxVRV9BQ0NFU1NPUixcblx0XHR1c2VFeGlzdGluZzogSW5wdXRUZXh0LFxuXHRcdG11bHRpICAgICAgOiB0cnVlXG5cdH1dXG59KVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBJbnB1dFRleHQgZXh0ZW5kcyBBYnN0cmFjdEZvcm1Db21wb25lbnQge1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBWYXJpYWJsZXNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSBfdmFsdWUgOiBzdHJpbmc7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIENvbnN0cnVjdG9yXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQVBJIG1ldGhvZHNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIHdyaXRlVmFsdWUodmFsdWUpIHtcblx0XHR0aGlzLl92YWx1ZSA9IHZhbHVlO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Z2V0IHZhbHVlKCkgOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLl92YWx1ZTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHNldCB2YWx1ZShuZXdWYWx1ZSkge1xuXHRcdGlmKG5ld1ZhbHVlPT1cIlwiKXtcbiAgICAgICAgICAgIG5ld1ZhbHVlPW51bGw7XG4gICAgICAgIH1cblx0XHR0aGlzLl92YWx1ZSA9IG5ld1ZhbHVlO1xuXHRcdHRoaXMub25DaGFuZ2UobmV3VmFsdWUpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFByb3RlY3RlZCBtZXRob2RzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByb3RlY3RlZCBpc1Byb3ZpZGVkKCkgOiBib29sZWFuIHtcblx0XHRyZXR1cm4gTGliLnN0ci5pc1Byb3ZpZGVkKHRoaXMudmFsdWUpO1xuXHR9XG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsIi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vPT09XG4vLz09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG4vLz09PVxuLy89PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbi8vPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtDb21wb25lbnQsIElucHV0fSAgZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge05HX1ZBTFVFX0FDQ0VTU09SfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7SW5wdXRUZXh0fSBmcm9tIFwiLi4vaW5wdXQtdGV4dC9pbnB1dC10ZXh0XCI7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICAgICAgJ2hwZS1pbnB1dC1hcmVhJyxcbiAgICB0ZW1wbGF0ZTogYDwhLS1cbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG49PT1cbj09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG49PT1cbj09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4tLT5cblxuPGRpdiBjbGFzcz1cInVpLWlucHV0Z3JvdXAgc3BhY2luZ1wiID5cblx0PGhwZS1mb3JtLWxhYmVsIFtpY29uXT1cImljb25cIiBbbGFiZWxdPVwibGFiZWxcIj48L2hwZS1mb3JtLWxhYmVsPlxuICAgIDx0ZXh0YXJlYSBwSW5wdXRUZXh0YXJlYSBbc3R5bGUuaGVpZ2h0XT1cImhlaWdodFwiIFsobmdNb2RlbCldPVwidmFsdWVcIiBbbmdDbGFzc109XCJnZXRDb21wb25lbnRDbGFzcygpXCIgW2Rpc2FibGVkXT1cIiFlbmFibGVkXCI+PC90ZXh0YXJlYT5cbjwvZGl2PlxuYCxcbiAgICBzdHlsZXM6IFtgLnNwYWNpbmd7bWFyZ2luLWJvdHRvbToxcmVtfS5jb250cm9se3dpZHRoOjEwMCV9LnJlcXVpcmVkLC5yZXF1aXJlZDpmb2N1c3tib3JkZXItcmlnaHQ6NXB4IHNvbGlkICNmZjhkNmR9LnByb3ZpZGVkLC5wcm92aWRlZDpmb2N1c3tib3JkZXItcmlnaHQ6NXB4IHNvbGlkICMwMGE5ODJ9YF0sXG4gICAgcHJvdmlkZXJzOiBbe1xuICAgICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgICAgdXNlRXhpc3Rpbmc6IElucHV0QXJlYSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9XVxufSlcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgY2xhc3MgSW5wdXRBcmVhIGV4dGVuZHMgSW5wdXRUZXh0IHtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gVmFyaWFibGVzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgQElucHV0KCkgaGVpZ2h0OiBzdHJpbmc7XG5cbiAgICAvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLy0tLVxuICAgIC8vLS0tIENvbnN0cnVjdG9yXG4gICAgLy8tLS1cbiAgICAvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcigpO1xuICAgIH1cbn1cblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIiwiLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy89PT1cbi8vPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbi8vPT09XG4vLz09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuLy89PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5pbXBvcnQge0NvbXBvbmVudH0gICAgICAgICBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7TkdfVkFMVUVfQUNDRVNTT1J9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7SW5wdXRUZXh0fSAgICAgICAgIGZyb20gXCIuLi9pbnB1dC10ZXh0L2lucHV0LXRleHRcIjtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3IgICAgOiAgICAgJ2hwZS1pbnB1dC1jaGVja2JveCcsXG5cdHRlbXBsYXRlOiBgPCEtLVxuPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbj09PVxuPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbj09PVxuPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG49PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi0tPlxuXG48ZGl2IGNsYXNzPVwidWktaW5wdXRncm91cCBzcGFjaW5nXCI+XG5cdDxocGUtZm9ybS1sYWJlbCBbaWNvbl09XCJpY29uXCIgW2xhYmVsXT1cImxhYmVsXCI+PC9ocGUtZm9ybS1sYWJlbD5cblx0PG1hdC1jaGVja2JveCBbKG5nTW9kZWwpXT1cInZhbHVlXCIgW25nQ2xhc3NdPVwiZ2V0Q29tcG9uZW50Q2xhc3MoKVwiIFtkaXNhYmxlZF09XCIhZW5hYmxlZFwiPjwvbWF0LWNoZWNrYm94PlxuPC9kaXY+XG5gLFxuXHRzdHlsZXM6IFtgLnNwYWNpbmd7bWFyZ2luLWJvdHRvbToxcmVtfS5jb250cm9se3dpZHRoOjEwMCU7bWFyZ2luLXRvcDo0cHg7bWFyZ2luLWxlZnQ6MTBweH0ucmVxdWlyZWR7Ym9yZGVyLXJpZ2h0OjVweCBzb2xpZCAjZmY4ZDZkfS5wcm92aWRlZHtib3JkZXItcmlnaHQ6NXB4IHNvbGlkICMwMGE5ODJ9Omhvc3QgOjpuZy1kZWVwIC5tYXQtY2hlY2tib3gtY2hlY2tlZC5tYXQtYWNjZW50IC5tYXQtY2hlY2tib3gtYmFja2dyb3VuZHtiYWNrZ3JvdW5kLWNvbG9yOiM4MDc0NmV9YF0sXG5cdHByb3ZpZGVycyAgIDogWyB7XG5cdFx0cHJvdmlkZSAgICA6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuXHRcdHVzZUV4aXN0aW5nOiBJbnB1dENoZWNrYm94LFxuXHRcdG11bHRpICAgICAgOiB0cnVlXG5cdH1dXG59KVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBJbnB1dENoZWNrYm94IGV4dGVuZHMgSW5wdXRUZXh0IHtcblxuICAgIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vLS0tXG4gICAgLy8tLS0gQ29uc3RydWN0b3JcbiAgICAvLy0tLVxuICAgIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgfVxufVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iLCIvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLz09PVxuLy89PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuLy89PT1cbi8vPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4vLz09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmltcG9ydCB7Q29tcG9uZW50LCBJbnB1dH0gICAgICBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7TkdfVkFMVUVfQUNDRVNTT1J9ICAgICBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge0Fic3RyYWN0Rm9ybUNvbXBvbmVudH0gZnJvbSBcIi4uL2Fic3RyYWN0LWZvcm0tY29tcG9uZW50XCI7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yICAgIDogICAnaHBlLWlucHV0LWNvbWJvJyxcblx0dGVtcGxhdGU6IGA8IS0tXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuPT09XG49PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuPT09XG49PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbj09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLS0+XG5cbjxkaXYgY2xhc3M9XCJ1aS1pbnB1dGdyb3VwIHNwYWNpbmdcIj5cblx0PGhwZS1mb3JtLWxhYmVsIFtpY29uXT1cImljb25cIiBbbGFiZWxdPVwibGFiZWxcIj48L2hwZS1mb3JtLWxhYmVsPlxuXG5cdDxwLWRyb3Bkb3duIFtvcHRpb25zXSAgICA9IFwiZGF0YVwiXG5cdFx0XHRcdFtkYXRhS2V5XSAgICA9IFwia2V5XCJcblx0XHRcdFx0W29wdGlvbkxhYmVsXT0gXCJ2YWx1ZVwiXG5cdFx0XHRcdFsobmdNb2RlbCldICA9IFwic2VsZWN0ZWRJdGVtXCJcblx0XHRcdFx0W25nQ2xhc3NdICAgID0gXCJnZXRDb21wb25lbnRDbGFzcygpXCJcblx0XHRcdFx0W3N0eWxlXSAgICAgID0gXCJ7ICd3aWR0aCc6JzEwMCUnIH1cIlxuXHRcdFx0XHRbZGlzYWJsZWRdICAgPSBcIiFlbmFibGVkXCI+XG5cdDwvcC1kcm9wZG93bj5cbjwvZGl2PlxuYCxcblx0c3R5bGVzOiBbYC5zcGFjaW5ne21hcmdpbi1ib3R0b206MXJlbX0uY29udHJvbHt3aWR0aDoxMDAlfS5yZXF1aXJlZHtib3JkZXItcmlnaHQ6NXB4IHNvbGlkICNmZjhkNmR9LnByb3ZpZGVke2JvcmRlci1yaWdodDo1cHggc29saWQgIzAwYTk4Mn1gXSxcblx0cHJvdmlkZXJzICAgOiBbIHtcblx0XHRwcm92aWRlICAgIDogTkdfVkFMVUVfQUNDRVNTT1IsXG5cdFx0dXNlRXhpc3Rpbmc6IElucHV0Q29tYm8sXG5cdFx0bXVsdGkgICAgICA6IHRydWVcblx0fV1cbn0pXG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGNsYXNzIElucHV0Q29tYm8gZXh0ZW5kcyBBYnN0cmFjdEZvcm1Db21wb25lbnQge1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t