@hpe/angular-toolkit
Version:
Hewlett-Packard Enterprise : Angular toolkit for rapid project development
711 lines (679 loc) • 73 kB
JavaScript
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