@hpe/angular-toolkit
Version:
Hewlett-Packard Enterprise : Angular toolkit for rapid project development
715 lines (700 loc) • 80.5 kB
JavaScript
import { Component, Input, NgModule } from '@angular/core';
import { __extends } from 'tslib';
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
*/
var FormColumn = /** @class */ (function () {
function FormColumn() {
}
FormColumn.decorators = [
{ type: Component, args: [{
selector: 'hpe-form-column',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<div class=\"formColumn\" [style.width]=\"width\">\n <ng-content></ng-content>\n</div>\n",
styles: [".formColumn{display:flex;flex-direction:column;align-content:center;justify-content:flex-start;margin:8px}"],
},] },
];
/** @nocollapse */
FormColumn.propDecorators = {
"width": [{ type: Input },],
};
return FormColumn;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FormLabel = /** @class */ (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function FormLabel() {
}
FormLabel.decorators = [
{ type: Component, args: [{
selector: 'hpe-form-label',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<span class=\"ui-inputgroup-addon label\">\n\t<hpe-icon name=\"{{icon}}\"></hpe-icon> {{label}}\n</span>\n",
styles: [".label{width:12rem;text-align:start!important}:host ::ng-deep .iconStyle{vertical-align:baseline}"],
},] },
];
//-------------------------------------------------------------------------
//---
//--- API methods
//---
//-------------------------------------------------------------------------
/** @nocollapse */
FormLabel.ctorParameters = function () { return []; };
FormLabel.propDecorators = {
"icon": [{ type: Input },],
"label": [{ type: Input },],
};
return FormLabel;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FormPanel = /** @class */ (function () {
function FormPanel() {
}
FormPanel.decorators = [
{ type: Component, args: [{
selector: 'hpe-form-panel',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<div class=\"formBody\">\n\t<ng-content></ng-content>\n</div>\n",
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}"],
},] },
];
return FormPanel;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FormText = /** @class */ (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function FormText() {
}
Object.defineProperty(FormText.prototype, "value", {
get: /**
* @return {?}
*/
function () {
return this._value;
},
//-------------------------------------------------------------------------
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
if (this.transcoder && value != null) {
value = this.transcoder.transcode(value);
}
this._value = value;
},
enumerable: true,
configurable: true
});
FormText.decorators = [
{ type: Component, args: [{
selector: 'hpe-form-text',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<div class=\"ui-inputgroup spacing\">\n\t<hpe-form-label [icon]=\"icon\" [label]=\"label\"></hpe-form-label>\n\t<span class=\"ui-inputgroup-addon text\">{{value}}</span>\n</div>\n",
styles: [".spacing{margin-bottom:1rem}.text{background-color:#f5f5f5;width:100%;color:#202020}"]
},] },
];
/** @nocollapse */
FormText.ctorParameters = function () { return []; };
FormText.propDecorators = {
"icon": [{ type: Input },],
"label": [{ type: Input },],
"transcoder": [{ type: Input },],
"value": [{ type: Input },],
};
return FormText;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @abstract
*/
var AbstractFormComponent = /** @class */ (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function AbstractFormComponent() {
this.enabled = true;
this._required = false;
}
//-------------------------------------------------------------------------
//---
//--- API methods
//---
//-------------------------------------------------------------------------
/**
* @param {?} fn
* @return {?}
*/
AbstractFormComponent.prototype.registerOnChange = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onChange = fn;
};
//-------------------------------------------------------------------------
/**
* @param {?} fn
* @return {?}
*/
AbstractFormComponent.prototype.registerOnTouched = /**
* @param {?} fn
* @return {?}
*/
function (fn) { };
/**
* @return {?}
*/
AbstractFormComponent.prototype.getComponentClass = /**
* @return {?}
*/
function () {
var /** @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;
};
Object.defineProperty(AbstractFormComponent.prototype, "required", {
get: /**
* @return {?}
*/
function () {
return this._required;
},
//-------------------------------------------------------------------------
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
var /** @type {?} */ str = "" + value;
if (str == "") {
//--- Ok, '' means value not provided --> true
value = true;
}
this._required = value;
},
enumerable: true,
configurable: true
});
AbstractFormComponent.propDecorators = {
"icon": [{ type: Input },],
"label": [{ type: Input },],
"enabled": [{ type: Input },],
"required": [{ type: Input },],
};
return AbstractFormComponent;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var InputText = /** @class */ (function (_super) {
__extends(InputText, _super);
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function InputText() {
return _super.call(this) || this;
}
/**
* @param {?} value
* @return {?}
*/
InputText.prototype.writeValue = /**
* @param {?} value
* @return {?}
*/
function (value) {
this._value = value;
};
Object.defineProperty(InputText.prototype, "value", {
//-------------------------------------------------------------------------
get: /**
* @return {?}
*/
function () {
return this._value;
},
//-------------------------------------------------------------------------
set: /**
* @param {?} newValue
* @return {?}
*/
function (newValue) {
if (newValue == "") {
newValue = null;
}
this._value = newValue;
this.onChange(newValue);
},
enumerable: true,
configurable: true
});
//-------------------------------------------------------------------------
//---
//--- Protected methods
//---
//-------------------------------------------------------------------------
/**
* @return {?}
*/
InputText.prototype.isProvided = /**
* @return {?}
*/
function () {
return Lib.str.isProvided(this.value);
};
InputText.decorators = [
{ type: Component, args: [{
selector: 'hpe-input-text',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<div class=\"ui-inputgroup spacing\">\n <hpe-form-label [icon]=\"icon\" [label]=\"label\"></hpe-form-label>\n\t<input pInputText [(ngModel)]=\"value\" [ngClass]=\"getComponentClass()\" [disabled]=\"!enabled\">\n</div>\n\n",
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 = function () { return []; };
return InputText;
}(AbstractFormComponent));
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var InputArea = /** @class */ (function (_super) {
__extends(InputArea, _super);
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function InputArea() {
return _super.call(this) || this;
}
InputArea.decorators = [
{ type: Component, args: [{
selector: 'hpe-input-area',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<div class=\"ui-inputgroup spacing\" >\n\t<hpe-form-label [icon]=\"icon\" [label]=\"label\"></hpe-form-label>\n <textarea pInputTextarea [style.height]=\"height\" [(ngModel)]=\"value\" [ngClass]=\"getComponentClass()\" [disabled]=\"!enabled\"></textarea>\n</div>\n",
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 = function () { return []; };
InputArea.propDecorators = {
"height": [{ type: Input },],
};
return InputArea;
}(InputText));
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var InputCheckbox = /** @class */ (function (_super) {
__extends(InputCheckbox, _super);
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function InputCheckbox() {
return _super.call(this) || this;
}
InputCheckbox.decorators = [
{ type: Component, args: [{
selector: 'hpe-input-checkbox',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<div class=\"ui-inputgroup spacing\">\n\t<hpe-form-label [icon]=\"icon\" [label]=\"label\"></hpe-form-label>\n\t<mat-checkbox [(ngModel)]=\"value\" [ngClass]=\"getComponentClass()\" [disabled]=\"!enabled\"></mat-checkbox>\n</div>\n",
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 = function () { return []; };
return InputCheckbox;
}(InputText));
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var InputCombo = /** @class */ (function (_super) {
__extends(InputCombo, _super);
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function InputCombo() {
return _super.call(this) || this;
}
Object.defineProperty(InputCombo.prototype, "dataMap", {
get: /**
* @return {?}
*/
function () {
return this._dataMap;
},
//-------------------------------------------------------------------------
set: /**
* @param {?} map
* @return {?}
*/
function (map) {
this._dataMap = map;
this.key = "id";
this.value = "value";
var /** @type {?} */ list = [];
if (!this.required) {
list.push({
"id": null,
"value": null
});
}
for (var /** @type {?} */ key in map) {
var /** @type {?} */ name_1 = Number(key);
var /** @type {?} */ value = map[key];
if (isNaN(name_1)) {
name_1 = key;
}
list.push({
"id": name_1,
"value": value
});
}
this.data = list;
},
enumerable: true,
configurable: true
});
/**
* @param {?} keyValue
* @return {?}
*/
InputCombo.prototype.writeValue = /**
* @param {?} keyValue
* @return {?}
*/
function (keyValue) {
var _this = this;
var /** @type {?} */ item = this.data.find(function (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;
};
Object.defineProperty(InputCombo.prototype, "selectedItem", {
//-------------------------------------------------------------------------
get: /**
* @return {?}
*/
function () {
return this._selectedItem;
},
//-------------------------------------------------------------------------
set: /**
* @param {?} newItem
* @return {?}
*/
function (newItem) {
this._selectedItem = newItem;
this.onChange(newItem[this.key]);
},
enumerable: true,
configurable: true
});
//-------------------------------------------------------------------------
//---
//--- Protected methods
//---
//-------------------------------------------------------------------------
/**
* @return {?}
*/
InputCombo.prototype.isProvided = /**
* @return {?}
*/
function () {
return (this.selectedItem != null && this.selectedItem[this.key] != null);
};
InputCombo.decorators = [
{ type: Component, args: [{
selector: 'hpe-input-combo',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<div class=\"ui-inputgroup spacing\">\n\t<hpe-form-label [icon]=\"icon\" [label]=\"label\"></hpe-form-label>\n\n\t<p-dropdown [options] = \"data\"\n\t\t\t\t[dataKey] = \"key\"\n\t\t\t\t[optionLabel]= \"value\"\n\t\t\t\t[(ngModel)] = \"selectedItem\"\n\t\t\t\t[ngClass] = \"getComponentClass()\"\n\t\t\t\t[style] = \"{ 'width':'100%' }\"\n\t\t\t\t[disabled] = \"!enabled\">\n\t</p-dropdown>\n</div>\n",
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 = function () { return []; };
InputCombo.propDecorators = {
"key": [{ type: Input },],
"value": [{ type: Input },],
"data": [{ type: Input },],
"dataMap": [{ type: Input },],
};
return InputCombo;
}(AbstractFormComponent));
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var LoginPanel = /** @class */ (function (_super) {
__extends(LoginPanel, _super);
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function LoginPanel(eventBusService, sessionService, notificationService, labelService, httpService) {
var _this = _super.call(this, eventBusService) || this;
_this.sessionService = sessionService;
_this.notificationService = notificationService;
_this.labelService = labelService;
_this.httpService = httpService;
//-------------------------------------------------------------------------
//---
//--- Variables
//---
//-------------------------------------------------------------------------
_this.cred = new Credentials();
_super.prototype.subscribeToApp.call(_this, AppEvent.LOGIN_FAILED, function (event) { return _this.onLoginFailed(event); });
return _this;
}
/**
* @return {?}
*/
LoginPanel.prototype.login = /**
* @return {?}
*/
function () {
if (!this.areCredentialsValid()) {
var /** @type {?} */ msg = this.labelService.getLabel("login-panel", "missing.info");
this.notificationService.showWarn(msg["title"], msg["descr"]);
}
else {
this.sessionService.login(this.cred);
}
};
Object.defineProperty(LoginPanel.prototype, "title", {
//-------------------------------------------------------------------------
//--- Localized strings
//-------------------------------------------------------------------------
get: /**
* @return {?}
*/
function () {
return this.loc("title");
},
enumerable: true,
configurable: true
});
Object.defineProperty(LoginPanel.prototype, "username", {
//-------------------------------------------------------------------------
get: /**
* @return {?}
*/
function () {
return this.loc("username");
},
enumerable: true,
configurable: true
});
Object.defineProperty(LoginPanel.prototype, "password", {
//-------------------------------------------------------------------------
get: /**
* @return {?}
*/
function () {
return this.loc("password");
},
enumerable: true,
configurable: true
});
Object.defineProperty(LoginPanel.prototype, "button", {
//-------------------------------------------------------------------------
get: /**
* @return {?}
*/
function () {
return this.loc("button");
},
enumerable: true,
configurable: true
});
/**
* @param {?} event
* @return {?}
*/
LoginPanel.prototype.onLoginFailed = /**
* @param {?} event
* @return {?}
*/
function (event) {
var /** @type {?} */ msg = this.labelService.getLabel("login-panel", "login.error");
this.notificationService.showError(msg["title"], msg["descr"]);
};
/**
* @return {?}
*/
LoginPanel.prototype.areCredentialsValid = /**
* @return {?}
*/
function () {
return Lib.str.isProvided(this.cred.username) && Lib.str.isProvided(this.cred.password);
};
/**
* @param {?} code
* @return {?}
*/
LoginPanel.prototype.loc = /**
* @param {?} code
* @return {?}
*/
function (code) {
return this.labelService.getLabel("login-panel", code);
};
LoginPanel.decorators = [
{ type: Component, args: [{
selector: 'hpe-login',
template: "<!--\n=============================================================================\n===\n=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.\n===\n=== Use of this source code is governed by an MIT-style license that can be\n=== found in the LICENSE file\n=============================================================================\n-->\n\n<hpe-card-panel icon=\"fa-sign-in\" [title]=\"title\" [toggleButton]=\"false\">\n\t<div cpBody>\n\t\t<hpe-form-panel>\n\n\t\t\t<hpe-form-column width=\"500px\">\n\t\t\t\t<hpe-input-text icon=\"fa-user\" [label]=\"username\" [(ngModel)]=\"cred.username\" required></hpe-input-text>\n\t\t\t\t<hpe-input-text icon=\"fa-key\" [label]=\"password\" [(ngModel)]=\"cred.password\" required></hpe-input-text>\n\t\t\t</hpe-form-column>\n\n\t\t</hpe-form-panel>\n\n\t\t<hpe-button-panel>\n\t\t\t<div class=\"spinner\" *ngIf=\"httpService.loading\">\n\t\t\t\t<i class=\"fa fa-circle-o-notch fa-pulse\"></i>\n\t\t\t</div>\n\t\t\t<button mat-button hpeButton (click)=\"login()\">{{button}}</button>\n\t\t</hpe-button-panel>\n\t</div>\n</hpe-card-panel>\n\n\n\n",
styles: [".spinner{position:absolute;left:16px;bottom:16px;font-size:32px}"]
},] },
];
/** @nocollapse */
LoginPanel.ctorParameters = function () { return [
{ type: EventBusService, },
{ type: SessionService, },
{ type: NotificationService, },
{ type: LabelService, },
{ type: HttpService, },
]; };
return LoginPanel;
}(AbstractSubscriber));
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var HpeFormModule = /** @class */ (function () {
function 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: [],
},] },
];
return HpeFormModule;
}());
//=============================================================================
/**
* @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+XG48L2Rpdj5cblxuYCxcblx0c3R5bGVzOiBbYC5zcGFjaW5ne21hcmdpbi1ib3R0b206MXJlbX0uY29udHJvbHt3aWR0aDoxMDAlfS5yZXF1aXJlZCwucmVxdWlyZWQ6Zm9jdXN7Ym9yZGVyLXJpZ2h0OjVweCBzb2xpZCAjZmY4ZDZkfS5wcm92aWRlZCwucHJvdmlkZWQ6Zm9jdXN7Ym9yZGVyLXJpZ2h0OjVweCBzb2xpZCAjMDBhOTgyfWBdLFxuXHRwcm92aWRlcnMgICA6IFsge1xuXHRcdHByb3ZpZGUgICAgOiBOR19WQUxVRV9BQ0NFU1NPUixcblx0XHR1c2VFeGlzdGluZzogSW5wdXRUZXh0LFxuXHRcdG11bHRpICAgICAgOiB0cnVlXG5cdH1dXG59KVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBJbnB1dFRleHQgZXh0ZW5kcyBBYnN0cmFjdEZvcm1Db21wb25lbnQge1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBWYXJpYWJsZXNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSBfdmFsdWUgOiBzdHJpbmc7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIENvbnN0cnVjdG9yXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQVBJIG1ldGhvZHNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIHdyaXRlVmFsdWUodmFsdWUpIHtcblx0XHR0aGlzLl92YWx1ZSA9IHZhbHVlO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Z2V0IHZhbHVlKCkgOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLl92YWx1ZTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHNldCB2YWx1ZShuZXdWYWx1ZSkge1xuXHRcdGlmKG5ld1ZhbHVlPT1cIlwiKXtcbiAgICAgICAgICAgIG5ld1ZhbHVlPW51bGw7XG4gICAgICAgIH1cblx0XHR0aGlzLl92YWx1ZSA9IG5ld1ZhbHVlO1xuXHRcdHRoaXMub25DaGFuZ2UobmV3VmFsdWUpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFByb3RlY3RlZCBtZXRob2RzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByb3RlY3RlZCBpc1Byb3ZpZGVkKCkgOiBib29sZWFuIHtcblx0XHRyZXR1cm4gTGliLnN0ci5pc1Byb3ZpZGVkKHRoaXMudmFsdWUpO1xuXHR9XG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsIi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vPT09XG4vLz09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG4vLz09PVxuLy89PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbi8vPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtDb21wb25lbnQsIElucHV0fSAgZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge05HX1ZBTFVFX0FDQ0VTU09SfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7SW5wdXRUZXh0fSBmcm9tIFwiLi4vaW5wdXQtdGV4dC9pbnB1dC10ZXh0XCI7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICAgICAgJ2hwZS1pbnB1dC1hcmVhJyxcbiAgICB0ZW1wbGF0ZTogYDwhLS1cbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG49PT1cbj09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG49PT1cbj09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0