@nova-ui/bits
Version:
SolarWinds Nova Framework
273 lines • 49.3 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { Component, ElementRef, EventEmitter, forwardRef, Input, Output, ViewChild, ViewEncapsulation, } from "@angular/core";
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, } from "@angular/forms";
import isNumber from "lodash/isNumber";
import isUndefined from "lodash/isUndefined";
import round from "lodash/round";
import { KEYBOARD_CODE } from "../../../constants/keycode.constants";
import { regexpValidation } from "../../../constants/regex.constants";
import { NuiFormFieldControl } from "../../form-field/public-api";
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "../../button/button.component";
import * as i3 from "@angular/forms";
// <example-url>./../examples/index.html#/textbox/textbox-number</example-url>
export class TextboxNumberComponent {
constructor() {
/**
* Value that is exposed through ControlValueAccessor
*/
this.value = null;
/**
* The option to disable the textboxNumber.
*/
this.disabled = false;
/**
* Value used as a placeholder for the text box.
*/
this.placeholder = "";
/**
* The option to make the textboxNumber read only.
*/
this.readonly = false;
/**
* Step by which the value are increased/decreased
* when clicking on up/down buttons
*/
this.step = 1;
/**
* The decimal precision to use for rounding each step increase/decrease
* when clicking the up/down buttons
*/
this.stepPrecision = 10;
/**
* Input to apply error state styles
*/
this.isInErrorState = false; // TODO: do we need to hook this up?
/**
* Input to set aria label text
*/
this.ariaLabel = "Textbox number input";
/**
* Event fired when textBoxNumber is focused out.
*/
this.blurred = new EventEmitter();
this.valueChange = new EventEmitter();
this.isRepeatable = true;
}
static createRangeValidator(min, max) {
const rangeValidator = (c) => {
if (!c.value && c.value !== 0) {
return null;
}
if ((!isUndefined(max) && c.value > max) ||
(!isUndefined(min) && c.value < min)) {
return {
range: {
given: c.value,
max,
min,
},
};
}
return null;
};
return rangeValidator;
}
ngOnChanges(changes) {
if (changes["minValue"] || changes["maxValue"]) {
this.validatorFn = TextboxNumberComponent.createRangeValidator(this.minValue, this.maxValue);
}
}
onBlurEventEmit() {
this.onTouched();
this.blurred.emit(this.value);
}
addNumber(valueChange) {
if (isUndefined(this.value) || isNaN(this.value)) {
this.value = 0;
}
// Explicitly converting current value to number because it can also be a string, and cause issues, like NUI-5599
const newValue = this.clampToRange(Number(this.value) + valueChange);
this.onValueChange(round(newValue, this.stepPrecision));
}
onValueChange(value) {
this.value = value;
setTimeout(() => {
this.onChange(this.value);
this.valueChange.emit(this.value);
this.onTouched();
});
}
onChange(value) { }
onTouched() { }
writeValue(value) {
this.value = value;
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
compareMin() {
return this.value <= this.minValue;
}
compareMax() {
return this.value >= this.maxValue;
}
validate(c) {
this.formControl = c;
return ((this.validatorFn ? this.validatorFn(c) : null) ||
this.nativeValidator());
}
hasError() {
return ((this.formControl?.touched || this.formControl?.dirty) &&
!this.formControl?.valid);
}
nativeValidator() {
if (this.input.nativeElement.validity.valid) {
return null;
}
return { format: "Invalid input" };
}
clampToRange(value) {
if (!isNumber(value)) {
return value;
}
if (value > this.maxValue) {
return this.maxValue;
}
if (value < this.minValue) {
return this.minValue;
}
return value;
}
// We need to restrict user input because safari does not prevent non numerical input in type 'number'
preventNonNumericalPaste(event) {
const pastedString = event.clipboardData?.getData("text/plain");
if (!pastedString) {
throw new Error("Unable to parse clipboardData");
}
this.preventDefaultEventBehavior(event, pastedString, regexpValidation.multiCharNumeric);
}
preventNonNumericalInput(event) {
const inputString = event.key;
if (!this.isMetaKey(event)) {
this.preventDefaultEventBehavior(event, inputString, regexpValidation.singleCharNumeric);
}
}
preventDefaultEventBehavior(event, inputString, regexp) {
if (!inputString?.match(regexp)) {
event.preventDefault();
}
}
isMetaKey(event) {
return (event.ctrlKey ||
event.metaKey ||
event.code === KEYBOARD_CODE.BACKSPACE ||
event.code === KEYBOARD_CODE.DELETE ||
event.code === KEYBOARD_CODE.TAB ||
event.code === KEYBOARD_CODE.ARROW_DOWN ||
event.code === KEYBOARD_CODE.ARROW_LEFT ||
event.code === KEYBOARD_CODE.ARROW_RIGHT ||
event.code === KEYBOARD_CODE.ARROW_UP);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextboxNumberComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TextboxNumberComponent, selector: "nui-textbox-number", inputs: { value: "value", customBoxWidth: "customBoxWidth", disabled: "disabled", name: "name", placeholder: "placeholder", readonly: "readonly", step: "step", stepPrecision: "stepPrecision", isInErrorState: "isInErrorState", ariaLabel: "ariaLabel", minValue: "minValue", maxValue: "maxValue" }, outputs: { blurred: "blurred", valueChange: "valueChange" }, host: { attributes: { "role": "spinbutton" }, properties: { "attr.aria-label": "ariaLabel", "attr.aria-valuemin": "minValue || null", "attr.aria-valuemax": "maxValue || null", "attr.aria-valuenow": "value || 0" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextboxNumberComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => TextboxNumberComponent),
multi: true,
},
{
provide: NuiFormFieldControl,
useExisting: forwardRef(() => TextboxNumberComponent),
multi: true,
},
], viewQueries: [{ propertyName: "input", first: true, predicate: ["numberInput"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"nui-textbox nui-textbox-number\"\n [class.nui-textbox--disabled]=\"disabled\"\n [class.has-error]=\"hasError() || isInErrorState\"\n>\n <div\n class=\"has-feedback\"\n [ngStyle]=\"{ maxWidth: customBoxWidth, minWidth: customBoxWidth }\"\n >\n <input\n class=\"form-control input-control nui-textbox__input\"\n #numberInput\n step=\"any\"\n [disabled]=\"disabled\"\n type=\"number\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [attr.name]=\"name\"\n (blur)=\"onBlurEventEmit()\"\n (keydown)=\"preventNonNumericalInput($event)\"\n (paste)=\"preventNonNumericalPaste($event)\"\n [placeholder]=\"placeholder\"\n [readonly]=\"readonly\"\n aria-label=\"Textbox number input\"\n />\n </div>\n <span class=\"nui-textbox-number__buttons\">\n <span class=\"nui-textbox-number__updown nui-textbox-number__up-button\">\n <button\n nui-button\n type=\"button\"\n displayStyle=\"action\"\n icon=\"caret-up\"\n [isRepeat]=\"isRepeatable\"\n [disabled]=\"readonly || disabled || compareMax()\"\n (click)=\"addNumber(+step)\"\n aria-label=\"Up\"\n ></button>\n </span>\n <span\n class=\"nui-textbox-number__updown nui-textbox-number__updown-divider\"\n ></span>\n <span\n class=\"nui-textbox-number__updown nui-textbox-number__down-button\"\n >\n <button\n nui-button\n type=\"button\"\n displayStyle=\"action\"\n icon=\"caret-down\"\n [isRepeat]=\"isRepeatable\"\n [disabled]=\"readonly || disabled || compareMin()\"\n (click)=\"addNumber(-step)\"\n aria-label=\"Down\"\n ></button>\n </span>\n </span>\n</div>\n", styles: [".nui .nui-textbox--disabled .has-feedback .input-control,.nui .nui-textbox--disabled .has-feedback .input-control:hover{color:var(--nui-color-text-disabled,rgba(17, 17, 17, .3))}.nui .nui-textbox--bold .nui-textbox__input{line-height:18px;font-size:13px;font-weight:600;color:#111;color:var(--nui-color-text-default,#111)}.nui .nui-textbox__input{min-height:30px}.nui .nui-textbox .has-feedback{position:relative}.nui .nui-textbox .has-feedback .input-control{padding:5px 10px;overflow-y:hidden}.nui .nui-textbox .has-feedback .input-control.nui-textbox__input--multiline{padding-top:5px}.nui .nui-textbox .has-feedback .input-control:focus{outline:none;z-index:500;box-shadow:0 0 0 2px #00c4d280}.nui .nui .nui-textbox--centered .has-feedback .input-control{padding:0;text-align:center}.nui .nui-textbox .input-control{resize:vertical}.nui .nui-textbox .input-control[hidden]{display:none!important}.nui .nui-textbox.has-error .help-block,.nui .nui-textbox.has-error .control-label,.nui .nui-textbox.has-error .radio,.nui .nui-textbox.has-error .checkbox,.nui .nui-textbox.has-error .radio-inline,.nui .nui-textbox.has-error .checkbox-inline,.nui .nui-textbox.has-error.nui-radio label,.nui .nui-textbox.has-error.checkbox label,.nui .nui-textbox.has-error.radio-inline label,.nui .nui-textbox.has-error.checkbox-inline label{color:var(--nui-color-text-default,#111)}.nui .nui-textbox.has-error .nui-validation>div{padding:5px 0;color:var(--nui-color-text-default,#111)}.nui .nui-textbox.has-error .input-group-addon{color:var(--nui-color-text-default,#111);border-color:var(--nui-color-line-critical,#dd2c00);background-color:var(--nui-color-bg-content,#fff)}.nui .nui-textbox.has-error .form-control-feedback{color:var(--nui-color-text-default,#111)}.nui .nui-textbox .form-control-feedback{top:12px;margin:0 7px 0 0;position:absolute;right:0;z-index:2;display:block;width:30px;height:30px;line-height:30px;text-align:center;pointer-events:none}.nui .nui-textbox .form-control-feedback.nui-textbox__busy{top:0;margin:0 1px 0 0}.nui .nui-textbox .form-control-feedback svg{position:relative;bottom:3px}.nui .textarea-scrollable .has-feedback .input-control{overflow-y:auto}\n", ".nui .nui-textbox input[type=number]::-webkit-inner-spin-button{display:none}.nui .nui-textbox input[type=number]{-moz-appearance:textfield}.nui .nui-textbox--disabled .nui-textbox-number__buttons,.nui .nui-textbox--disabled .nui-textbox-number__updown-divider{border-color:var(--nui-color-disabled-light,#e9e9e9)}.nui .nui-textbox-number{display:flex}.nui .nui-textbox-number__buttons{display:inline-flex;height:30px;border:solid 1px;border-color:var(--nui-color-line-default,#d9d9d9);border-top-right-radius:3px;border-bottom-right-radius:3px;border-left:none}.nui .nui-textbox-number__updown{display:block;line-height:1;height:30px;top:1px;text-align:center}.nui .nui-textbox-number__updown button.nui-button{padding-left:5px;padding-top:7px;width:30px;height:28px;min-height:28px}.nui .nui-textbox-number__updown button.nui-button:focus{outline:none}.nui .nui-textbox-number__updown-divider{z-index:1;height:28px;top:1px;right:30px;width:0;border-right:solid 1px;border-right-color:var(--nui-color-line-default,#d9d9d9)}.nui .nui-textbox-number__up-button{right:1px}.nui .nui-textbox-number__down-button{right:30px}.nui .nui-textbox-number .has-feedback{flex:1}.nui .nui-textbox-number .input-control{border-top-right-radius:0;border-bottom-right-radius:0}.nui .nui-textbox-number input[type=number]~nui-icon>.form-control-feedback{margin:0 65px 0 0}.nui .nui-textbox-number input[type=number]~nui-icon>.form-control-feedback.nui-textbox__busy{top:0;margin:0 59px 0 0}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.ButtonComponent, selector: "[nui-button]", inputs: ["displayStyle", "icon", "iconColor", "iconRight", "isBusy", "isEmpty", "ariaLabel", "isRepeat", "size"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextboxNumberComponent, decorators: [{
type: Component,
args: [{ selector: "nui-textbox-number", providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextboxNumberComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => TextboxNumberComponent),
multi: true,
},
{
provide: NuiFormFieldControl,
useExisting: forwardRef(() => TextboxNumberComponent),
multi: true,
},
], encapsulation: ViewEncapsulation.None, host: {
role: "spinbutton",
"[attr.aria-label]": "ariaLabel",
"[attr.aria-valuemin]": "minValue || null",
"[attr.aria-valuemax]": "maxValue || null",
"[attr.aria-valuenow]": "value || 0",
}, template: "<div\n class=\"nui-textbox nui-textbox-number\"\n [class.nui-textbox--disabled]=\"disabled\"\n [class.has-error]=\"hasError() || isInErrorState\"\n>\n <div\n class=\"has-feedback\"\n [ngStyle]=\"{ maxWidth: customBoxWidth, minWidth: customBoxWidth }\"\n >\n <input\n class=\"form-control input-control nui-textbox__input\"\n #numberInput\n step=\"any\"\n [disabled]=\"disabled\"\n type=\"number\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [attr.name]=\"name\"\n (blur)=\"onBlurEventEmit()\"\n (keydown)=\"preventNonNumericalInput($event)\"\n (paste)=\"preventNonNumericalPaste($event)\"\n [placeholder]=\"placeholder\"\n [readonly]=\"readonly\"\n aria-label=\"Textbox number input\"\n />\n </div>\n <span class=\"nui-textbox-number__buttons\">\n <span class=\"nui-textbox-number__updown nui-textbox-number__up-button\">\n <button\n nui-button\n type=\"button\"\n displayStyle=\"action\"\n icon=\"caret-up\"\n [isRepeat]=\"isRepeatable\"\n [disabled]=\"readonly || disabled || compareMax()\"\n (click)=\"addNumber(+step)\"\n aria-label=\"Up\"\n ></button>\n </span>\n <span\n class=\"nui-textbox-number__updown nui-textbox-number__updown-divider\"\n ></span>\n <span\n class=\"nui-textbox-number__updown nui-textbox-number__down-button\"\n >\n <button\n nui-button\n type=\"button\"\n displayStyle=\"action\"\n icon=\"caret-down\"\n [isRepeat]=\"isRepeatable\"\n [disabled]=\"readonly || disabled || compareMin()\"\n (click)=\"addNumber(-step)\"\n aria-label=\"Down\"\n ></button>\n </span>\n </span>\n</div>\n", styles: [".nui .nui-textbox--disabled .has-feedback .input-control,.nui .nui-textbox--disabled .has-feedback .input-control:hover{color:var(--nui-color-text-disabled,rgba(17, 17, 17, .3))}.nui .nui-textbox--bold .nui-textbox__input{line-height:18px;font-size:13px;font-weight:600;color:#111;color:var(--nui-color-text-default,#111)}.nui .nui-textbox__input{min-height:30px}.nui .nui-textbox .has-feedback{position:relative}.nui .nui-textbox .has-feedback .input-control{padding:5px 10px;overflow-y:hidden}.nui .nui-textbox .has-feedback .input-control.nui-textbox__input--multiline{padding-top:5px}.nui .nui-textbox .has-feedback .input-control:focus{outline:none;z-index:500;box-shadow:0 0 0 2px #00c4d280}.nui .nui .nui-textbox--centered .has-feedback .input-control{padding:0;text-align:center}.nui .nui-textbox .input-control{resize:vertical}.nui .nui-textbox .input-control[hidden]{display:none!important}.nui .nui-textbox.has-error .help-block,.nui .nui-textbox.has-error .control-label,.nui .nui-textbox.has-error .radio,.nui .nui-textbox.has-error .checkbox,.nui .nui-textbox.has-error .radio-inline,.nui .nui-textbox.has-error .checkbox-inline,.nui .nui-textbox.has-error.nui-radio label,.nui .nui-textbox.has-error.checkbox label,.nui .nui-textbox.has-error.radio-inline label,.nui .nui-textbox.has-error.checkbox-inline label{color:var(--nui-color-text-default,#111)}.nui .nui-textbox.has-error .nui-validation>div{padding:5px 0;color:var(--nui-color-text-default,#111)}.nui .nui-textbox.has-error .input-group-addon{color:var(--nui-color-text-default,#111);border-color:var(--nui-color-line-critical,#dd2c00);background-color:var(--nui-color-bg-content,#fff)}.nui .nui-textbox.has-error .form-control-feedback{color:var(--nui-color-text-default,#111)}.nui .nui-textbox .form-control-feedback{top:12px;margin:0 7px 0 0;position:absolute;right:0;z-index:2;display:block;width:30px;height:30px;line-height:30px;text-align:center;pointer-events:none}.nui .nui-textbox .form-control-feedback.nui-textbox__busy{top:0;margin:0 1px 0 0}.nui .nui-textbox .form-control-feedback svg{position:relative;bottom:3px}.nui .textarea-scrollable .has-feedback .input-control{overflow-y:auto}\n", ".nui .nui-textbox input[type=number]::-webkit-inner-spin-button{display:none}.nui .nui-textbox input[type=number]{-moz-appearance:textfield}.nui .nui-textbox--disabled .nui-textbox-number__buttons,.nui .nui-textbox--disabled .nui-textbox-number__updown-divider{border-color:var(--nui-color-disabled-light,#e9e9e9)}.nui .nui-textbox-number{display:flex}.nui .nui-textbox-number__buttons{display:inline-flex;height:30px;border:solid 1px;border-color:var(--nui-color-line-default,#d9d9d9);border-top-right-radius:3px;border-bottom-right-radius:3px;border-left:none}.nui .nui-textbox-number__updown{display:block;line-height:1;height:30px;top:1px;text-align:center}.nui .nui-textbox-number__updown button.nui-button{padding-left:5px;padding-top:7px;width:30px;height:28px;min-height:28px}.nui .nui-textbox-number__updown button.nui-button:focus{outline:none}.nui .nui-textbox-number__updown-divider{z-index:1;height:28px;top:1px;right:30px;width:0;border-right:solid 1px;border-right-color:var(--nui-color-line-default,#d9d9d9)}.nui .nui-textbox-number__up-button{right:1px}.nui .nui-textbox-number__down-button{right:30px}.nui .nui-textbox-number .has-feedback{flex:1}.nui .nui-textbox-number .input-control{border-top-right-radius:0;border-bottom-right-radius:0}.nui .nui-textbox-number input[type=number]~nui-icon>.form-control-feedback{margin:0 65px 0 0}.nui .nui-textbox-number input[type=number]~nui-icon>.form-control-feedback.nui-textbox__busy{top:0;margin:0 59px 0 0}\n"] }]
}], propDecorators: { value: [{
type: Input
}], customBoxWidth: [{
type: Input
}], disabled: [{
type: Input
}], name: [{
type: Input
}], placeholder: [{
type: Input
}], readonly: [{
type: Input
}], step: [{
type: Input
}], stepPrecision: [{
type: Input
}], isInErrorState: [{
type: Input
}], ariaLabel: [{
type: Input
}], minValue: [{
type: Input
}], maxValue: [{
type: Input
}], blurred: [{
type: Output
}], valueChange: [{
type: Output
}], input: [{
type: ViewChild,
args: ["numberInput", { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dGJveC1udW1iZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90ZXh0Ym94L3RleHRib3gtbnVtYmVyL3RleHRib3gtbnVtYmVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdGV4dGJveC90ZXh0Ym94LW51bWJlci90ZXh0Ym94LW51bWJlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBRUwsTUFBTSxFQUVOLFNBQVMsRUFDVCxpQkFBaUIsR0FDcEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUdILGFBQWEsRUFDYixpQkFBaUIsR0FFcEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQztBQUN2QyxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQztBQUM3QyxPQUFPLEtBQUssTUFBTSxjQUFjLENBQUM7QUFFakMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDOzs7OztBQUVsRSw4RUFBOEU7QUFnQzlFLE1BQU0sT0FBTyxzQkFBc0I7SUE5Qm5DO1FBNkRJOztXQUVHO1FBQ2EsVUFBSyxHQUFRLElBQUksQ0FBQztRQU1sQzs7V0FFRztRQUNhLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFLakM7O1dBRUc7UUFDYSxnQkFBVyxHQUFHLEVBQUUsQ0FBQztRQUNqQzs7V0FFRztRQUNhLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFFakM7OztXQUdHO1FBQ00sU0FBSSxHQUFXLENBQUMsQ0FBQztRQUUxQjs7O1dBR0c7UUFDTSxrQkFBYSxHQUFXLEVBQUUsQ0FBQztRQUVwQzs7V0FFRztRQUNhLG1CQUFjLEdBQVksS0FBSyxDQUFDLENBQUMsb0NBQW9DO1FBRXJGOztXQUVHO1FBQ2EsY0FBUyxHQUFXLHNCQUFzQixDQUFDO1FBVTNEOztXQUVHO1FBQ08sWUFBTyxHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFDO1FBRXJELGdCQUFXLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7UUFPbEUsaUJBQVksR0FBRyxJQUFJLENBQUM7S0F1SjlCO0lBdlBXLE1BQU0sQ0FBQyxvQkFBb0IsQ0FDL0IsR0FBVyxFQUNYLEdBQVc7UUFFWCxNQUFNLGNBQWMsR0FBRyxDQUFDLENBQWMsRUFBRSxFQUFFO1lBQ3RDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxFQUFFO2dCQUMzQixPQUFPLElBQUksQ0FBQzthQUNmO1lBRUQsSUFDSSxDQUFDLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDO2dCQUNwQyxDQUFDLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLEVBQ3RDO2dCQUNFLE9BQU87b0JBQ0gsS0FBSyxFQUFFO3dCQUNILEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSzt3QkFDZCxHQUFHO3dCQUNILEdBQUc7cUJBQ047aUJBQ0osQ0FBQzthQUNMO1lBRUQsT0FBTyxJQUFJLENBQUM7UUFDaEIsQ0FBQyxDQUFDO1FBRUYsT0FBTyxjQUFjLENBQUM7SUFDMUIsQ0FBQztJQTBFTSxXQUFXLENBQUMsT0FBc0I7UUFDckMsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQzVDLElBQUksQ0FBQyxXQUFXLEdBQUcsc0JBQXNCLENBQUMsb0JBQW9CLENBQzFELElBQUksQ0FBQyxRQUFRLEVBQ2IsSUFBSSxDQUFDLFFBQVEsQ0FDaEIsQ0FBQztTQUNMO0lBQ0wsQ0FBQztJQUVNLGVBQWU7UUFDbEIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRU0sU0FBUyxDQUFDLFdBQW1CO1FBQ2hDLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQzlDLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1NBQ2xCO1FBQ0QsaUhBQWlIO1FBQ2pILE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxXQUFXLENBQUMsQ0FBQztRQUVyRSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVNLGFBQWEsQ0FBQyxLQUFVO1FBQzNCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBRW5CLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDWixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMxQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFbEMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3JCLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVNLFFBQVEsQ0FBQyxLQUFVLElBQVMsQ0FBQztJQUU3QixTQUFTLEtBQVUsQ0FBQztJQUVwQixVQUFVLENBQUMsS0FBVTtRQUN4QixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUN2QixDQUFDO0lBRU0sZ0JBQWdCLENBQUMsRUFBd0I7UUFDNUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVNLGlCQUFpQixDQUFDLEVBQWM7UUFDbkMsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVNLGdCQUFnQixDQUFDLFVBQW1CO1FBQ3ZDLElBQUksQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO0lBQy9CLENBQUM7SUFFTSxVQUFVO1FBQ2IsT0FBTyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkMsQ0FBQztJQUVNLFVBQVU7UUFDYixPQUFPLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN2QyxDQUFDO0lBRU0sUUFBUSxDQUFDLENBQWM7UUFDMUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDckIsT0FBTyxDQUNILENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQy9DLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FDekIsQ0FBQztJQUNOLENBQUM7SUFFTSxRQUFRO1FBQ1gsT0FBTyxDQUNILENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUM7WUFDdEQsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FDM0IsQ0FBQztJQUNOLENBQUM7SUFFTyxlQUFlO1FBQ25CLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRTtZQUN6QyxPQUFPLElBQUksQ0FBQztTQUNmO1FBRUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsQ0FBQztJQUN2QyxDQUFDO0lBRU8sWUFBWSxDQUFDLEtBQWE7UUFDOUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNsQixPQUFPLEtBQUssQ0FBQztTQUNoQjtRQUNELElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDdkIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO1NBQ3hCO1FBQ0QsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUN2QixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7U0FDeEI7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBRUQsc0dBQXNHO0lBQy9GLHdCQUF3QixDQUFDLEtBQXFCO1FBQ2pELE1BQU0sWUFBWSxHQUNkLEtBQUssQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDZixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7U0FDcEQ7UUFDRCxJQUFJLENBQUMsMkJBQTJCLENBQzVCLEtBQUssRUFDTCxZQUFZLEVBQ1osZ0JBQWdCLENBQUMsZ0JBQWdCLENBQ3BDLENBQUM7SUFDTixDQUFDO0lBRU0sd0JBQXdCLENBQUMsS0FBb0I7UUFDaEQsTUFBTSxXQUFXLEdBQVcsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUN0QyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUN4QixJQUFJLENBQUMsMkJBQTJCLENBQzVCLEtBQUssRUFDTCxXQUFXLEVBQ1gsZ0JBQWdCLENBQUMsaUJBQWlCLENBQ3JDLENBQUM7U0FDTDtJQUNMLENBQUM7SUFFTywyQkFBMkIsQ0FDL0IsS0FBcUMsRUFDckMsV0FBbUIsRUFDbkIsTUFBYztRQUVkLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzdCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztTQUMxQjtJQUNMLENBQUM7SUFFTyxTQUFTLENBQUMsS0FBb0I7UUFDbEMsT0FBTyxDQUNILEtBQUssQ0FBQyxPQUFPO1lBQ2IsS0FBSyxDQUFDLE9BQU87WUFDYixLQUFLLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQyxTQUFTO1lBQ3RDLEtBQUssQ0FBQyxJQUFJLEtBQUssYUFBYSxDQUFDLE1BQU07WUFDbkMsS0FBSyxDQUFDLElBQUksS0FBSyxhQUFhLENBQUMsR0FBRztZQUNoQyxLQUFLLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQyxVQUFVO1lBQ3ZDLEtBQUssQ0FBQyxJQUFJLEtBQUssYUFBYSxDQUFDLFVBQVU7WUFDdkMsS0FBSyxDQUFDLElBQUksS0FBSyxhQUFhLENBQUMsV0FBVztZQUN4QyxLQUFLLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQyxRQUFRLENBQ3hDLENBQUM7SUFDTixDQUFDOytHQXpQUSxzQkFBc0I7bUdBQXRCLHNCQUFzQiwwbUJBM0JwQjtZQUNQO2dCQUNJLE9BQU8sRUFBRSxpQkFBaUI7Z0JBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsc0JBQXNCLENBQUM7Z0JBQ3JELEtBQUssRUFBRSxJQUFJO2FBQ2Q7WUFDRDtnQkFDSSxPQUFPLEVBQUUsYUFBYTtnQkFDdEIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztnQkFDckQsS0FBSyxFQUFFLElBQUk7YUFDZDtZQUNEO2dCQUNJLE9BQU8sRUFBRSxtQkFBbUI7Z0JBQzVCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsc0JBQXNCLENBQUM7Z0JBQ3JELEtBQUssRUFBRSxJQUFJO2FBQ2Q7U0FDSixtS0NwRUwseXFFQTZEQTs7NEZEa0JhLHNCQUFzQjtrQkE5QmxDLFNBQVM7K0JBQ0ksb0JBQW9CLGFBRW5CO3dCQUNQOzRCQUNJLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHVCQUF1QixDQUFDOzRCQUNyRCxLQUFLLEVBQUUsSUFBSTt5QkFDZDt3QkFDRDs0QkFDSSxPQUFPLEVBQUUsYUFBYTs0QkFDdEIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsdUJBQXVCLENBQUM7NEJBQ3JELEtBQUssRUFBRSxJQUFJO3lCQUNkO3dCQUNEOzRCQUNJLE9BQU8sRUFBRSxtQkFBbUI7NEJBQzVCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHVCQUF1QixDQUFDOzRCQUNyRCxLQUFLLEVBQUUsSUFBSTt5QkFDZDtxQkFDSixpQkFFYyxpQkFBaUIsQ0FBQyxJQUFJLFFBQy9CO3dCQUNGLElBQUksRUFBRSxZQUFZO3dCQUNsQixtQkFBbUIsRUFBRSxXQUFXO3dCQUNoQyxzQkFBc0IsRUFBRSxrQkFBa0I7d0JBQzFDLHNCQUFzQixFQUFFLGtCQUFrQjt3QkFDMUMsc0JBQXNCLEVBQUUsWUFBWTtxQkFDdkM7OEJBb0NlLEtBQUs7c0JBQXBCLEtBQUs7Z0JBS1UsY0FBYztzQkFBN0IsS0FBSztnQkFJVSxRQUFRO3NCQUF2QixLQUFLO2dCQUlVLElBQUk7c0JBQW5CLEtBQUs7Z0JBSVUsV0FBVztzQkFBMUIsS0FBSztnQkFJVSxRQUFRO3NCQUF2QixLQUFLO2dCQU1HLElBQUk7c0JBQVosS0FBSztnQkFNRyxhQUFhO3NCQUFyQixLQUFLO2dCQUtVLGNBQWM7c0JBQTdCLEtBQUs7Z0JBS1UsU0FBUztzQkFBeEIsS0FBSztnQkFLVSxRQUFRO3NCQUF2QixLQUFLO2dCQUlVLFFBQVE7c0JBQXZCLEtBQUs7Z0JBSUksT0FBTztzQkFBaEIsTUFBTTtnQkFFRyxXQUFXO3NCQUFwQixNQUFNO2dCQUdDLEtBQUs7c0JBRFosU0FBUzt1QkFBQyxhQUFhLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIGZvcndhcmRSZWYsXG4gICAgSW5wdXQsXG4gICAgT25DaGFuZ2VzLFxuICAgIE91dHB1dCxcbiAgICBTaW1wbGVDaGFuZ2VzLFxuICAgIFZpZXdDaGlsZCxcbiAgICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7XG4gICAgQ29udHJvbFZhbHVlQWNjZXNzb3IsXG4gICAgRm9ybUNvbnRyb2wsXG4gICAgTkdfVkFMSURBVE9SUyxcbiAgICBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICBWYWxpZGF0aW9uRXJyb3JzLFxufSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCBpc051bWJlciBmcm9tIFwibG9kYXNoL2lzTnVtYmVyXCI7XG5pbXBvcnQgaXNVbmRlZmluZWQgZnJvbSBcImxvZGFzaC9pc1VuZGVmaW5lZFwiO1xuaW1wb3J0IHJvdW5kIGZyb20gXCJsb2Rhc2gvcm91bmRcIjtcblxuaW1wb3J0IHsgS0VZQk9BUkRfQ09ERSB9IGZyb20gXCIuLi8uLi8uLi9jb25zdGFudHMva2V5Y29kZS5jb25zdGFudHNcIjtcbmltcG9ydCB7IHJlZ2V4cFZhbGlkYXRpb24gfSBmcm9tIFwiLi4vLi4vLi4vY29uc3RhbnRzL3JlZ2V4LmNvbnN0YW50c1wiO1xuaW1wb3J0IHsgTnVpRm9ybUZpZWxkQ29udHJvbCB9IGZyb20gXCIuLi8uLi9mb3JtLWZpZWxkL3B1YmxpYy1hcGlcIjtcblxuLy8gPGV4YW1wbGUtdXJsPi4vLi4vZXhhbXBsZXMvaW5kZXguaHRtbCMvdGV4dGJveC90ZXh0Ym94LW51bWJlcjwvZXhhbXBsZS11cmw+XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiBcIm51aS10ZXh0Ym94LW51bWJlclwiLFxuICAgIHRlbXBsYXRlVXJsOiBcIi4vdGV4dGJveC1udW1iZXIuY29tcG9uZW50Lmh0bWxcIixcbiAgICBwcm92aWRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBUZXh0Ym94TnVtYmVyQ29tcG9uZW50KSxcbiAgICAgICAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVGV4dGJveE51bWJlckNvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgcHJvdmlkZTogTnVpRm9ybUZpZWxkQ29udHJvbCxcbiAgICAgICAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFRleHRib3hOdW1iZXJDb21wb25lbnQpLFxuICAgICAgICAgICAgbXVsdGk6IHRydWUsXG4gICAgICAgIH0sXG4gICAgXSxcbiAgICBzdHlsZVVybHM6IFtcIi4uL3RleHRib3guY29tcG9uZW50Lmxlc3NcIiwgXCIuL3RleHRib3gtbnVtYmVyLmNvbXBvbmVudC5sZXNzXCJdLFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gICAgaG9zdDoge1xuICAgICAgICByb2xlOiBcInNwaW5idXR0b25cIixcbiAgICAgICAgXCJbYXR0ci5hcmlhLWxhYmVsXVwiOiBcImFyaWFMYWJlbFwiLFxuICAgICAgICBcIlthdHRyLmFyaWEtdmFsdWVtaW5dXCI6IFwibWluVmFsdWUgfHwgbnVsbFwiLFxuICAgICAgICBcIlthdHRyLmFyaWEtdmFsdWVtYXhdXCI6IFwibWF4VmFsdWUgfHwgbnVsbFwiLFxuICAgICAgICBcIlthdHRyLmFyaWEtdmFsdWVub3ddXCI6IFwidmFsdWUgfHwgMFwiLFxuICAgIH0sXG59KVxuZXhwb3J0IGNsYXNzIFRleHRib3hOdW1iZXJDb21wb25lbnRcbiAgICBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOdWlGb3JtRmllbGRDb250cm9sLCBPbkNoYW5nZXNcbntcbiAgICBwcml2YXRlIHN0YXRpYyBjcmVhdGVSYW5nZVZhbGlkYXRvcihcbiAgICAgICAgbWluOiBudW1iZXIsXG4gICAgICAgIG1heDogbnVtYmVyXG4gICAgKTogKGM6IEZvcm1Db250cm9sKSA9PiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgICAgIGNvbnN0IHJhbmdlVmFsaWRhdG9yID0gKGM6IEZvcm1Db250cm9sKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWMudmFsdWUgJiYgYy52YWx1ZSAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKCFpc1VuZGVmaW5lZChtYXgpICYmIGMudmFsdWUgPiBtYXgpIHx8XG4gICAgICAgICAgICAgICAgKCFpc1VuZGVmaW5lZChtaW4pICYmIGMudmFsdWUgPCBtaW4pXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICByYW5nZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2l2ZW46IGMudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW4sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHJhbmdlVmFsaWRhdG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFZhbHVlIHRoYXQgaXMgZXhwb3NlZCB0aHJvdWdoIENvbnRyb2xWYWx1ZUFjY2Vzc29yXG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIHZhbHVlOiBhbnkgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogVXNlIHRvIHNldCBhIGN1c3RvbSB3aWR0aCBmb3IgdGhlIGlucHV0IGZpZWxkLlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBjdXN0b21Cb3hXaWR0aDogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIFRoZSBvcHRpb24gdG8gZGlzYWJsZSB0aGUgdGV4dGJveE51bWJlci5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBOYW1lIG9mIHRoZSBlbGVtZW50LlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBuYW1lOiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogVmFsdWUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciB0aGUgdGV4dCBib3guXG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIHBsYWNlaG9sZGVyID0gXCJcIjtcbiAgICAvKipcbiAgICAgKiBUaGUgb3B0aW9uIHRvIG1ha2UgdGhlIHRleHRib3hOdW1iZXIgcmVhZCBvbmx5LlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyByZWFkb25seSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogU3RlcCBieSB3aGljaCB0aGUgdmFsdWUgYXJlIGluY3JlYXNlZC9kZWNyZWFzZWRcbiAgICAgKiB3aGVuIGNsaWNraW5nIG9uIHVwL2Rvd24gYnV0dG9uc1xuICAgICAqL1xuICAgIEBJbnB1dCgpIHN0ZXA6IG51bWJlciA9IDE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGVjaW1hbCBwcmVjaXNpb24gdG8gdXNlIGZvciByb3VuZGluZyBlYWNoIHN0ZXAgaW5jcmVhc2UvZGVjcmVhc2VcbiAgICAgKiB3aGVuIGNsaWNraW5nIHRoZSB1cC9kb3duIGJ1dHRvbnNcbiAgICAgKi9cbiAgICBASW5wdXQoKSBzdGVwUHJlY2lzaW9uOiBudW1iZXIgPSAxMDtcblxuICAgIC8qKlxuICAgICAqIElucHV0IHRvIGFwcGx5IGVycm9yIHN0YXRlIHN0eWxlc1xuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBpc0luRXJyb3JTdGF0ZTogYm9vbGVhbiA9IGZhbHNlOyAvLyBUT0RPOiBkbyB3ZSBuZWVkIHRvIGhvb2sgdGhpcyB1cD9cblxuICAgIC8qKlxuICAgICAqIElucHV0IHRvIHNldCBhcmlhIGxhYmVsIHRleHRcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgYXJpYUxhYmVsOiBzdHJpbmcgPSBcIlRleHRib3ggbnVtYmVyIGlucHV0XCI7XG5cbiAgICAvKipcbiAgICAgKiBNaW5pbXVtIHZhbHVlIG9mIHRleHRCb3hOdW1iZXIgY29tcG9uZW50XG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIG1pblZhbHVlOiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogTWF4aW11bSB2YWx1ZSBvZiB0ZXh0Qm94TnVtYmVyIGNvbXBvbmVudFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBtYXhWYWx1ZTogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIEV2ZW50IGZpcmVkIHdoZW4gdGV4dEJveE51bWJlciBpcyBmb2N1c2VkIG91dC5cbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgYmx1cnJlZDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICAgIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZTogRXZlbnRFbWl0dGVyPG51bWJlcj4gPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcblxuICAgIEBWaWV3Q2hpbGQoXCJudW1iZXJJbnB1dFwiLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHByaXZhdGUgaW5wdXQ6IEVsZW1lbnRSZWY8SFRNTEZpZWxkU2V0RWxlbWVudD47XG5cbiAgICBwdWJsaWMgZm9ybUNvbnRyb2w6IEZvcm1Db250cm9sO1xuXG4gICAgcHVibGljIGlzUmVwZWF0YWJsZSA9IHRydWU7XG5cbiAgICBwcml2YXRlIHZhbGlkYXRvckZuOiAoYzogRm9ybUNvbnRyb2wpID0+IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsO1xuXG4gICAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICAgICAgaWYgKGNoYW5nZXNbXCJtaW5WYWx1ZVwiXSB8fCBjaGFuZ2VzW1wibWF4VmFsdWVcIl0pIHtcbiAgICAgICAgICAgIHRoaXMudmFsaWRhdG9yRm4gPSBUZXh0Ym94TnVtYmVyQ29tcG9uZW50LmNyZWF0ZVJhbmdlVmFsaWRhdG9yKFxuICAgICAgICAgICAgICAgIHRoaXMubWluVmFsdWUsXG4gICAgICAgICAgICAgICAgdGhpcy5tYXhWYWx1ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBvbkJsdXJFdmVudEVtaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgICAgIHRoaXMuYmx1cnJlZC5lbWl0KHRoaXMudmFsdWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhZGROdW1iZXIodmFsdWVDaGFuZ2U6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBpZiAoaXNVbmRlZmluZWQodGhpcy52YWx1ZSkgfHwgaXNOYU4odGhpcy52YWx1ZSkpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIEV4cGxpY2l0bHkgY29udmVydGluZyBjdXJyZW50IHZhbHVlIHRvIG51bWJlciBiZWNhdXNlIGl0IGNhbiBhbHNvIGJlIGEgc3RyaW5nLCBhbmQgY2F1c2UgaXNzdWVzLCBsaWtlIE5VSS01NTk5XG4gICAgICAgIGNvbnN0IG5ld1ZhbHVlID0gdGhpcy5jbGFtcFRvUmFuZ2UoTnVtYmVyKHRoaXMudmFsdWUpICsgdmFsdWVDaGFuZ2UpO1xuXG4gICAgICAgIHRoaXMub25WYWx1ZUNoYW5nZShyb3VuZChuZXdWYWx1ZSwgdGhpcy5zdGVwUHJlY2lzaW9uKSk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uVmFsdWVDaGFuZ2UodmFsdWU6IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG5cbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMudmFsdWUpO1xuICAgICAgICAgICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHRoaXMudmFsdWUpO1xuXG4gICAgICAgICAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25DaGFuZ2UodmFsdWU6IGFueSk6IHZvaWQge31cblxuICAgIHB1YmxpYyBvblRvdWNoZWQoKTogdm9pZCB7fVxuXG4gICAgcHVibGljIHdyaXRlVmFsdWUodmFsdWU6IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICh2YWx1ZTogYW55KSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wYXJlTWluKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSA8PSB0aGlzLm1pblZhbHVlO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wYXJlTWF4KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSA+PSB0aGlzLm1heFZhbHVlO1xuICAgIH1cblxuICAgIHB1YmxpYyB2YWxpZGF0ZShjOiBGb3JtQ29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcbiAgICAgICAgdGhpcy5mb3JtQ29udHJvbCA9IGM7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAodGhpcy52YWxpZGF0b3JGbiA/IHRoaXMudmFsaWRhdG9yRm4oYykgOiBudWxsKSB8fFxuICAgICAgICAgICAgdGhpcy5uYXRpdmVWYWxpZGF0b3IoKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBoYXNFcnJvcigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICh0aGlzLmZvcm1Db250cm9sPy50b3VjaGVkIHx8IHRoaXMuZm9ybUNvbnRyb2w/LmRpcnR5KSAmJlxuICAgICAgICAgICAgIXRoaXMuZm9ybUNvbnRyb2w/LnZhbGlkXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBuYXRpdmVWYWxpZGF0b3IoKTogVmFsaWRhdGlvbkVycm9ycyB8IG51bGwge1xuICAgICAgICBpZiAodGhpcy5pbnB1dC5uYXRpdmVFbGVtZW50LnZhbGlkaXR5LnZhbGlkKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGZvcm1hdDogXCJJbnZhbGlkIGlucHV0XCIgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsYW1wVG9SYW5nZSh2YWx1ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKCFpc051bWJlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUgPiB0aGlzLm1heFZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUgPCB0aGlzLm1pblZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5taW5WYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLy8gV2UgbmVlZCB0byByZXN0cmljdCB1c2VyIGlucHV0IGJlY2F1c2Ugc2FmYXJpIGRvZXMgbm90IHByZXZlbnQgbm9uIG51bWVyaWNhbCBpbnB1dCBpbiB0eXBlICdudW1iZXInXG4gICAgcHVibGljIHByZXZlbnROb25OdW1lcmljYWxQYXN0ZShldmVudDogQ2xpcGJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcGFzdGVkU3RyaW5nOiBzdHJpbmcgfCB1bmRlZmluZWQgPVxuICAgICAgICAgICAgZXZlbnQuY2xpcGJvYXJkRGF0YT8uZ2V0RGF0YShcInRleHQvcGxhaW5cIik7XG4gICAgICAgIGlmICghcGFzdGVkU3RyaW5nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcGFyc2UgY2xpcGJvYXJkRGF0YVwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnByZXZlbnREZWZhdWx0RXZlbnRCZWhhdmlvcihcbiAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICAgcGFzdGVkU3RyaW5nLFxuICAgICAgICAgICAgcmVnZXhwVmFsaWRhdGlvbi5tdWx0aUNoYXJOdW1lcmljXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHByZXZlbnROb25OdW1lcmljYWxJbnB1dChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCBpbnB1dFN0cmluZzogc3RyaW5nID0gZXZlbnQua2V5O1xuICAgICAgICBpZiAoIXRoaXMuaXNNZXRhS2V5KGV2ZW50KSkge1xuICAgICAgICAgICAgdGhpcy5wcmV2ZW50RGVmYXVsdEV2ZW50QmVoYXZpb3IoXG4gICAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICAgICAgaW5wdXRTdHJpbmcsXG4gICAgICAgICAgICAgICAgcmVnZXhwVmFsaWRhdGlvbi5zaW5nbGVDaGFyTnVtZXJpY1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcHJldmVudERlZmF1bHRFdmVudEJlaGF2aW9yKFxuICAgICAgICBldmVudDogS2V5Ym9hcmRFdmVudCB8IENsaXBib2FyZEV2ZW50LFxuICAgICAgICBpbnB1dFN0cmluZzogc3RyaW5nLFxuICAgICAgICByZWdleHA6IFJlZ0V4cFxuICAgICk6IHZvaWQge1xuICAgICAgICBpZiAoIWlucHV0U3RyaW5nPy5tYXRjaChyZWdleHApKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc01ldGFLZXkoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGV2ZW50LmN0cmxLZXkgfHxcbiAgICAgICAgICAgIGV2ZW50Lm1ldGFLZXkgfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuQkFDS1NQQUNFIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkRFTEVURSB8fFxuICAgICAgICAgICAgZXZlbnQuY29kZSA9PT0gS0VZQk9BUkRfQ09ERS5UQUIgfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuQVJST1dfRE9XTiB8fFxuICAgICAgICAgICAgZXZlbnQuY29kZSA9PT0gS0VZQk9BUkRfQ09ERS5BUlJPV19MRUZUIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkFSUk9XX1JJR0hUIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkFSUk9XX1VQXG4gICAgICAgICk7XG4gICAgfVxufVxuIiwiPGRpdlxuICAgIGNsYXNzPVwibnVpLXRleHRib3ggbnVpLXRleHRib3gtbnVtYmVyXCJcbiAgICBbY2xhc3MubnVpLXRleHRib3gtLWRpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICBbY2xhc3MuaGFzLWVycm9yXT1cImhhc0Vycm9yKCkgfHwgaXNJbkVycm9yU3RhdGVcIlxuPlxuICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJoYXMtZmVlZGJhY2tcIlxuICAgICAgICBbbmdTdHlsZV09XCJ7IG1heFdpZHRoOiBjdXN0b21Cb3hXaWR0aCwgbWluV2lkdGg6IGN1c3RvbUJveFdpZHRoIH1cIlxuICAgID5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBpbnB1dC1jb250cm9sIG51aS10ZXh0Ym94X19pbnB1dFwiXG4gICAgICAgICAgICAjbnVtYmVySW5wdXRcbiAgICAgICAgICAgIHN0ZXA9XCJhbnlcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgW25nTW9kZWxdPVwidmFsdWVcIlxuICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25WYWx1ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7IHN0YW5kYWxvbmU6IHRydWUgfVwiXG4gICAgICAgICAgICBbbWluXT1cIm1pblZhbHVlXCJcbiAgICAgICAgICAgIFttYXhdPVwibWF4VmFsdWVcIlxuICAgICAgICAgICAgW2F0dHIubmFtZV09XCJuYW1lXCJcbiAgICAgICAgICAgIChibHVyKT1cIm9uQmx1ckV2ZW50RW1pdCgpXCJcbiAgICAgICAgICAgIChrZXlkb3duKT1cInByZXZlbnROb25OdW1lcmljYWxJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChwYXN0ZSk9XCJwcmV2ZW50Tm9uTnVtZXJpY2FsUGFzdGUoJGV2ZW50KVwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgICAgICAgICAgW3JlYWRvbmx5XT1cInJlYWRvbmx5XCJcbiAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJUZXh0Ym94IG51bWJlciBpbnB1dFwiXG4gICAgICAgIC8+XG4gICAgPC9kaXY+XG4gICAgPHNwYW4gY2xhc3M9XCJudWktdGV4dGJveC1udW1iZXJfX2J1dHRvbnNcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJudWktdGV4dGJveC1udW1iZXJfX3VwZG93biBudWktdGV4dGJveC1udW1iZXJfX3VwLWJ1dHRvblwiPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIG51aS1idXR0b25cbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICBkaXNwbGF5U3R5bGU9XCJhY3Rpb25cIlxuICAgICAgICAgICAgICAgIGljb249XCJjYXJldC11cFwiXG4gICAgICAgICAgICAgICAgW2lzUmVwZWF0XT1cImlzUmVwZWF0YWJsZVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cInJlYWRvbmx5IHx8IGRpc2FibGVkIHx8IGNvbXBhcmVNYXgoKVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImFkZE51bWJlcigrc3RlcClcIlxuICAgICAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJVcFwiXG4gICAgICAgICAgICA+PC9idXR0b24+XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPHNwYW5cbiAgICAgICAgICAgIGNsYXNzPVwibnVpLXRleHRib3gtbnVtYmVyX191cGRvd24gbnVpLXRleHRib3gtbnVtYmVyX191cGRvd24tZGl2aWRlclwiXG4gICAgICAgID48L3NwYW4+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgICBjbGFzcz1cIm51aS10ZXh0Ym94LW51bWJlcl9fdXBkb3duIG51aS10ZXh0Ym94LW51bWJlcl9fZG93bi1idXR0b25cIlxuICAgICAgICA+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbnVpLWJ1dHRvblxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgIGRpc3BsYXlTdHlsZT1cImFjdGlvblwiXG4gICAgICAgICAgICAgICAgaWNvbj1cImNhcmV0LWRvd25cIlxuICAgICAgICAgICAgICAgIFtpc1JlcGVhdF09XCJpc1JlcGVhdGFibGVcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJyZWFkb25seSB8fCBkaXNhYmxlZCB8fCBjb21wYXJlTWluKClcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJhZGROdW1iZXIoLXN0ZXApXCJcbiAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiRG93blwiXG4gICAgICAgICAgICA+PC9idXR0b24+XG4gICAgICAgIDwvc3Bhbj5cbiAgICA8L3NwYW4+XG48L2Rpdj5cbiJdfQ==