@ajsf/bootstrap4
Version:
Angular JSON Schema Form builder using Bootstrap 4 UI
220 lines • 45.5 kB
JavaScript
import { Component, Input } from '@angular/core';
import cloneDeep from 'lodash/cloneDeep';
import map from 'lodash/map';
import { addClasses, inArray } from '@ajsf/core';
import * as i0 from "@angular/core";
import * as i1 from "@ajsf/core";
import * as i2 from "@angular/common";
/**
* Bootstrap 4 framework for Angular JSON Schema Form.
*
*/
export class Bootstrap4FrameworkComponent {
constructor(changeDetector, jsf) {
this.changeDetector = changeDetector;
this.jsf = jsf;
this.frameworkInitialized = false;
this.formControl = null;
this.debugOutput = '';
this.debug = '';
this.parentArray = null;
this.isOrderable = false;
}
get showRemoveButton() {
if (!this.options.removable || this.options.readonly ||
this.layoutNode.type === '$ref') {
return false;
}
if (this.layoutNode.recursiveReference) {
return true;
}
if (!this.layoutNode.arrayItem || !this.parentArray) {
return false;
}
// If array length <= minItems, don't allow removing any items
return this.parentArray.items.length - 1 <= this.parentArray.options.minItems ? false :
// For removable list items, allow removing any item
this.layoutNode.arrayItemType === 'list' ? true :
// For removable tuple items, only allow removing last item in list
this.layoutIndex[this.layoutIndex.length - 1] === this.parentArray.items.length - 2;
}
ngOnInit() {
this.initializeFramework();
if (this.layoutNode.arrayItem && this.layoutNode.type !== '$ref') {
this.parentArray = this.jsf.getParentNode(this);
if (this.parentArray) {
this.isOrderable = this.layoutNode.arrayItemType === 'list' &&
!this.options.readonly && this.parentArray.options.orderable;
}
}
}
ngOnChanges() {
if (!this.frameworkInitialized) {
this.initializeFramework();
}
}
initializeFramework() {
if (this.layoutNode) {
this.options = cloneDeep(this.layoutNode.options);
this.widgetLayoutNode = {
...this.layoutNode,
options: cloneDeep(this.layoutNode.options)
};
this.widgetOptions = this.widgetLayoutNode.options;
this.formControl = this.jsf.getFormControl(this);
this.options.isInputWidget = inArray(this.layoutNode.type, [
'button', 'checkbox', 'checkboxes-inline', 'checkboxes', 'color',
'date', 'datetime-local', 'datetime', 'email', 'file', 'hidden',
'image', 'integer', 'month', 'number', 'password', 'radio',
'radiobuttons', 'radios-inline', 'radios', 'range', 'reset', 'search',
'select', 'submit', 'tel', 'text', 'textarea', 'time', 'url', 'week'
]);
this.options.title = this.setTitle();
this.options.htmlClass =
addClasses(this.options.htmlClass, 'schema-form-' + this.layoutNode.type);
this.options.htmlClass =
this.layoutNode.type === 'array' ?
addClasses(this.options.htmlClass, 'list-group') :
this.layoutNode.arrayItem && this.layoutNode.type !== '$ref' ?
addClasses(this.options.htmlClass, 'list-group-item') :
addClasses(this.options.htmlClass, 'form-group');
this.widgetOptions.htmlClass = '';
this.options.labelHtmlClass =
addClasses(this.options.labelHtmlClass, 'control-label');
this.widgetOptions.activeClass =
addClasses(this.widgetOptions.activeClass, 'active');
this.options.fieldAddonLeft =
this.options.fieldAddonLeft || this.options.prepend;
this.options.fieldAddonRight =
this.options.fieldAddonRight || this.options.append;
// Add asterisk to titles if required
if (this.options.title && this.layoutNode.type !== 'tab' &&
!this.options.notitle && this.options.required &&
!this.options.title.includes('*')) {
this.options.title += ' <strong class="text-danger">*</strong>';
}
// Set miscelaneous styles and settings for each control type
switch (this.layoutNode.type) {
// Checkbox controls
case 'checkbox':
case 'checkboxes':
this.widgetOptions.htmlClass = addClasses(this.widgetOptions.htmlClass, 'checkbox');
break;
case 'checkboxes-inline':
this.widgetOptions.htmlClass = addClasses(this.widgetOptions.htmlClass, 'checkbox');
this.widgetOptions.itemLabelHtmlClass = addClasses(this.widgetOptions.itemLabelHtmlClass, 'checkbox-inline');
break;
// Radio controls
case 'radio':
case 'radios':
this.widgetOptions.htmlClass = addClasses(this.widgetOptions.htmlClass, 'radio');
break;
case 'radios-inline':
this.widgetOptions.htmlClass = addClasses(this.widgetOptions.htmlClass, 'radio');
this.widgetOptions.itemLabelHtmlClass = addClasses(this.widgetOptions.itemLabelHtmlClass, 'radio-inline');
break;
// Button sets - checkboxbuttons and radiobuttons
case 'checkboxbuttons':
case 'radiobuttons':
this.widgetOptions.htmlClass = addClasses(this.widgetOptions.htmlClass, 'btn-group');
this.widgetOptions.itemLabelHtmlClass = addClasses(this.widgetOptions.itemLabelHtmlClass, 'btn');
this.widgetOptions.itemLabelHtmlClass = addClasses(this.widgetOptions.itemLabelHtmlClass, this.options.style || 'btn-default');
this.widgetOptions.fieldHtmlClass = addClasses(this.widgetOptions.fieldHtmlClass, 'sr-only');
break;
// Single button controls
case 'button':
case 'submit':
this.widgetOptions.fieldHtmlClass = addClasses(this.widgetOptions.fieldHtmlClass, 'btn');
this.widgetOptions.fieldHtmlClass = addClasses(this.widgetOptions.fieldHtmlClass, this.options.style || 'btn-info');
break;
// Containers - arrays and fieldsets
case 'array':
case 'fieldset':
case 'section':
case 'conditional':
case 'advancedfieldset':
case 'authfieldset':
case 'selectfieldset':
case 'optionfieldset':
this.options.messageLocation = 'top';
break;
case 'tabarray':
case 'tabs':
this.widgetOptions.htmlClass = addClasses(this.widgetOptions.htmlClass, 'tab-content');
this.widgetOptions.fieldHtmlClass = addClasses(this.widgetOptions.fieldHtmlClass, 'tab-pane');
this.widgetOptions.labelHtmlClass = addClasses(this.widgetOptions.labelHtmlClass, 'nav nav-tabs');
break;
// 'Add' buttons - references
case '$ref':
this.widgetOptions.fieldHtmlClass = addClasses(this.widgetOptions.fieldHtmlClass, 'btn pull-right');
this.widgetOptions.fieldHtmlClass = addClasses(this.widgetOptions.fieldHtmlClass, this.options.style || 'btn-default');
this.options.icon = 'glyphicon glyphicon-plus';
break;
// Default - including regular inputs
default:
this.widgetOptions.fieldHtmlClass = addClasses(this.widgetOptions.fieldHtmlClass, 'form-control');
}
if (this.formControl) {
this.updateHelpBlock(this.formControl.status);
this.formControl.statusChanges.subscribe(status => this.updateHelpBlock(status));
if (this.options.debug) {
const vars = [];
this.debugOutput = map(vars, thisVar => JSON.stringify(thisVar, null, 2)).join('\n');
}
}
this.frameworkInitialized = true;
}
}
updateHelpBlock(status) {
this.options.helpBlock = status === 'INVALID' &&
this.options.enableErrorState && this.formControl.errors &&
(this.formControl.dirty || this.options.feedbackOnRender) ?
this.jsf.formatErrors(this.formControl.errors, this.options.validationMessages) :
this.options.description || this.options.help || null;
}
setTitle() {
switch (this.layoutNode.type) {
case 'button':
case 'checkbox':
case 'section':
case 'help':
case 'msg':
case 'submit':
case 'message':
case 'tabarray':
case 'tabs':
case '$ref':
return null;
case 'advancedfieldset':
this.widgetOptions.expandable = true;
this.widgetOptions.title = 'Advanced options';
return null;
case 'authfieldset':
this.widgetOptions.expandable = true;
this.widgetOptions.title = 'Authentication settings';
return null;
case 'fieldset':
this.widgetOptions.title = this.options.title;
return null;
default:
this.widgetOptions.title = null;
return this.jsf.setItemTitle(this);
}
}
removeItem() {
this.jsf.removeItem(this);
}
}
Bootstrap4FrameworkComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: Bootstrap4FrameworkComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.JsonSchemaFormService }], target: i0.ɵɵFactoryTarget.Component });
Bootstrap4FrameworkComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.0", type: Bootstrap4FrameworkComponent, selector: "bootstrap-4-framework", inputs: { layoutNode: "layoutNode", layoutIndex: "layoutIndex", dataIndex: "dataIndex" }, usesOnChanges: true, ngImport: i0, template: "<div\n [class]=\"options?.htmlClass || ''\"\n [class.has-feedback]=\"options?.feedback && options?.isInputWidget &&\n (formControl?.dirty || options?.feedbackOnRender)\"\n [class.has-error]=\"options?.enableErrorState && formControl?.errors &&\n (formControl?.dirty || options?.feedbackOnRender)\"\n [class.has-success]=\"options?.enableSuccessState && !formControl?.errors &&\n (formControl?.dirty || options?.feedbackOnRender)\">\n\n <button *ngIf=\"showRemoveButton\"\n class=\"close pull-right\"\n type=\"button\"\n (click)=\"removeItem()\">\n <span aria-hidden=\"true\">×</span>\n <span class=\"sr-only\">Close</span>\n </button>\n <div *ngIf=\"options?.messageLocation === 'top'\">\n <p *ngIf=\"options?.helpBlock\"\n class=\"help-block\"\n [innerHTML]=\"options?.helpBlock\"></p>\n </div>\n\n <label *ngIf=\"options?.title && layoutNode?.type !== 'tab'\"\n [attr.for]=\"'control' + layoutNode?._id\"\n [class]=\"options?.labelHtmlClass || ''\"\n [class.sr-only]=\"options?.notitle\"\n [innerHTML]=\"options?.title\"></label>\n <p *ngIf=\"layoutNode?.type === 'submit' && jsf?.formOptions?.fieldsRequired\">\n <strong class=\"text-danger\">*</strong> = required fields\n </p>\n <div [class.input-group]=\"options?.fieldAddonLeft || options?.fieldAddonRight\">\n <span *ngIf=\"options?.fieldAddonLeft\"\n class=\"input-group-addon\"\n [innerHTML]=\"options?.fieldAddonLeft\"></span>\n\n <select-widget-widget\n [layoutNode]=\"widgetLayoutNode\"\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"></select-widget-widget>\n\n <span *ngIf=\"options?.fieldAddonRight\"\n class=\"input-group-addon\"\n [innerHTML]=\"options?.fieldAddonRight\"></span>\n </div>\n\n <span *ngIf=\"options?.feedback && options?.isInputWidget &&\n !options?.fieldAddonRight && !layoutNode.arrayItem &&\n (formControl?.dirty || options?.feedbackOnRender)\"\n [class.glyphicon-ok]=\"options?.enableSuccessState && !formControl?.errors\"\n [class.glyphicon-remove]=\"options?.enableErrorState && formControl?.errors\"\n aria-hidden=\"true\"\n class=\"form-control-feedback glyphicon\"></span>\n <div *ngIf=\"options?.messageLocation !== 'top'\">\n <p *ngIf=\"options?.helpBlock\"\n class=\"help-block\"\n [innerHTML]=\"options?.helpBlock\"></p>\n </div>\n</div>\n\n<div *ngIf=\"debug && debugOutput\">debug:\n <pre>{{debugOutput}}</pre>\n</div>\n", styles: [":host ::ng-deep .list-group-item .form-control-feedback{top:40px}:host ::ng-deep .checkbox,:host ::ng-deep .radio{margin-top:0;margin-bottom:0}:host ::ng-deep .checkbox-inline,:host ::ng-deep .checkbox-inline+.checkbox-inline,:host ::ng-deep .checkbox-inline+.radio-inline,:host ::ng-deep .radio-inline,:host ::ng-deep .radio-inline+.radio-inline,:host ::ng-deep .radio-inline+.checkbox-inline{margin-left:0;margin-right:10px}:host ::ng-deep .checkbox-inline:last-child,:host ::ng-deep .radio-inline:last-child{margin-right:0}:host ::ng-deep .ng-invalid.ng-touched{border:1px solid #f44336}\n"], dependencies: [{ kind: "component", type: i1.SelectWidgetComponent, selector: "select-widget-widget", inputs: ["layoutNode", "layoutIndex", "dataIndex"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: Bootstrap4FrameworkComponent, decorators: [{
type: Component,
args: [{ selector: 'bootstrap-4-framework', template: "<div\n [class]=\"options?.htmlClass || ''\"\n [class.has-feedback]=\"options?.feedback && options?.isInputWidget &&\n (formControl?.dirty || options?.feedbackOnRender)\"\n [class.has-error]=\"options?.enableErrorState && formControl?.errors &&\n (formControl?.dirty || options?.feedbackOnRender)\"\n [class.has-success]=\"options?.enableSuccessState && !formControl?.errors &&\n (formControl?.dirty || options?.feedbackOnRender)\">\n\n <button *ngIf=\"showRemoveButton\"\n class=\"close pull-right\"\n type=\"button\"\n (click)=\"removeItem()\">\n <span aria-hidden=\"true\">×</span>\n <span class=\"sr-only\">Close</span>\n </button>\n <div *ngIf=\"options?.messageLocation === 'top'\">\n <p *ngIf=\"options?.helpBlock\"\n class=\"help-block\"\n [innerHTML]=\"options?.helpBlock\"></p>\n </div>\n\n <label *ngIf=\"options?.title && layoutNode?.type !== 'tab'\"\n [attr.for]=\"'control' + layoutNode?._id\"\n [class]=\"options?.labelHtmlClass || ''\"\n [class.sr-only]=\"options?.notitle\"\n [innerHTML]=\"options?.title\"></label>\n <p *ngIf=\"layoutNode?.type === 'submit' && jsf?.formOptions?.fieldsRequired\">\n <strong class=\"text-danger\">*</strong> = required fields\n </p>\n <div [class.input-group]=\"options?.fieldAddonLeft || options?.fieldAddonRight\">\n <span *ngIf=\"options?.fieldAddonLeft\"\n class=\"input-group-addon\"\n [innerHTML]=\"options?.fieldAddonLeft\"></span>\n\n <select-widget-widget\n [layoutNode]=\"widgetLayoutNode\"\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"></select-widget-widget>\n\n <span *ngIf=\"options?.fieldAddonRight\"\n class=\"input-group-addon\"\n [innerHTML]=\"options?.fieldAddonRight\"></span>\n </div>\n\n <span *ngIf=\"options?.feedback && options?.isInputWidget &&\n !options?.fieldAddonRight && !layoutNode.arrayItem &&\n (formControl?.dirty || options?.feedbackOnRender)\"\n [class.glyphicon-ok]=\"options?.enableSuccessState && !formControl?.errors\"\n [class.glyphicon-remove]=\"options?.enableErrorState && formControl?.errors\"\n aria-hidden=\"true\"\n class=\"form-control-feedback glyphicon\"></span>\n <div *ngIf=\"options?.messageLocation !== 'top'\">\n <p *ngIf=\"options?.helpBlock\"\n class=\"help-block\"\n [innerHTML]=\"options?.helpBlock\"></p>\n </div>\n</div>\n\n<div *ngIf=\"debug && debugOutput\">debug:\n <pre>{{debugOutput}}</pre>\n</div>\n", styles: [":host ::ng-deep .list-group-item .form-control-feedback{top:40px}:host ::ng-deep .checkbox,:host ::ng-deep .radio{margin-top:0;margin-bottom:0}:host ::ng-deep .checkbox-inline,:host ::ng-deep .checkbox-inline+.checkbox-inline,:host ::ng-deep .checkbox-inline+.radio-inline,:host ::ng-deep .radio-inline,:host ::ng-deep .radio-inline+.radio-inline,:host ::ng-deep .radio-inline+.checkbox-inline{margin-left:0;margin-right:10px}:host ::ng-deep .checkbox-inline:last-child,:host ::ng-deep .radio-inline:last-child{margin-right:0}:host ::ng-deep .ng-invalid.ng-touched{border:1px solid #f44336}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.JsonSchemaFormService }]; }, propDecorators: { layoutNode: [{
type: Input
}], layoutIndex: [{
type: Input
}], dataIndex: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwNC1mcmFtZXdvcmsuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYWpzZi1ib290c3RyYXA0L3NyYy9saWIvYm9vdHN0cmFwNC1mcmFtZXdvcmsuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYWpzZi1ib290c3RyYXA0L3NyYy9saWIvYm9vdHN0cmFwNC1mcmFtZXdvcmsuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLFNBQVMsRUFDVCxLQUFLLEVBR04sTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxTQUFTLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxHQUFHLE1BQU0sWUFBWSxDQUFDO0FBQzdCLE9BQU8sRUFBd0IsVUFBVSxFQUFFLE9BQU8sRUFBQyxNQUFNLFlBQVksQ0FBQzs7OztBQUV0RTs7O0dBR0c7QUFPSCxNQUFNLE9BQU8sNEJBQTRCO0lBY3ZDLFlBQ1MsY0FBaUMsRUFDakMsR0FBMEI7UUFEMUIsbUJBQWMsR0FBZCxjQUFjLENBQW1CO1FBQ2pDLFFBQUcsR0FBSCxHQUFHLENBQXVCO1FBZm5DLHlCQUFvQixHQUFHLEtBQUssQ0FBQztRQUk3QixnQkFBVyxHQUFRLElBQUksQ0FBQztRQUN4QixnQkFBVyxHQUFRLEVBQUUsQ0FBQztRQUN0QixVQUFLLEdBQVEsRUFBRSxDQUFDO1FBQ2hCLGdCQUFXLEdBQVEsSUFBSSxDQUFDO1FBQ3hCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO0lBU3BCLENBQUM7SUFFRCxJQUFJLGdCQUFnQjtRQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRO1lBQ2xELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFDL0I7WUFDQSxPQUFPLEtBQUssQ0FBQztTQUNkO1FBQ0QsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGtCQUFrQixFQUFFO1lBQ3RDLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ25ELE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFDRCw4REFBOEQ7UUFDOUQsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckYsb0RBQW9EO1lBQ3BELElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQy9DLG1FQUFtRTtnQkFDbkUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFRCxRQUFRO1FBQ04sSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDM0IsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7WUFDaEUsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNoRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEtBQUssTUFBTTtvQkFDekQsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7YUFDaEU7U0FDRjtJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRTtZQUM5QixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztTQUM1QjtJQUNILENBQUM7SUFFRCxtQkFBbUI7UUFDakIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLGdCQUFnQixHQUFHO2dCQUN0QixHQUFHLElBQUksQ0FBQyxVQUFVO2dCQUNsQixPQUFPLEVBQUUsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO2FBQzVDLENBQUM7WUFDRixJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7WUFDbkQsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUVqRCxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUU7Z0JBQ3pELFFBQVEsRUFBRSxVQUFVLEVBQUUsbUJBQW1CLEVBQUUsWUFBWSxFQUFFLE9BQU87Z0JBQ2hFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRO2dCQUMvRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU87Z0JBQzFELGNBQWMsRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUTtnQkFDckUsUUFBUSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU07YUFDckUsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBRXJDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUztnQkFDcEIsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLGNBQWMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVFLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUztnQkFDcEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEtBQUssT0FBTyxDQUFDLENBQUM7b0JBQ2hDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO29CQUNsRCxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQzt3QkFDNUQsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQzt3QkFDdkQsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ3ZELElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWM7Z0JBQ3pCLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxlQUFlLENBQUMsQ0FBQztZQUMzRCxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVc7Z0JBQzVCLFVBQVUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUN2RCxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWM7Z0JBQ3pCLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO1lBQ3RELElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZTtnQkFDMUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7WUFFdEQscUNBQXFDO1lBQ3JDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEtBQUssS0FBSztnQkFDdEQsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVE7Z0JBQzlDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUNqQztnQkFDQSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSx5Q0FBeUMsQ0FBQzthQUNqRTtZQUNELDZEQUE2RDtZQUM3RCxRQUFRLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFO2dCQUM1QixvQkFBb0I7Z0JBQ3BCLEtBQUssVUFBVSxDQUFDO2dCQUNoQixLQUFLLFlBQVk7b0JBQ2YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUN2QyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQztvQkFDNUMsTUFBTTtnQkFDUixLQUFLLG1CQUFtQjtvQkFDdEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUN2QyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQztvQkFDNUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsR0FBRyxVQUFVLENBQ2hELElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztvQkFDNUQsTUFBTTtnQkFDUixpQkFBaUI7Z0JBQ2pCLEtBQUssT0FBTyxDQUFDO2dCQUNiLEtBQUssUUFBUTtvQkFDWCxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxVQUFVLENBQ3ZDLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO29CQUN6QyxNQUFNO2dCQUNSLEtBQUssZUFBZTtvQkFDbEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUN2QyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDekMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsR0FBRyxVQUFVLENBQ2hELElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLEVBQUUsY0FBYyxDQUFDLENBQUM7b0JBQ3pELE1BQU07Z0JBQ1IsaURBQWlEO2dCQUNqRCxLQUFLLGlCQUFpQixDQUFDO2dCQUN2QixLQUFLLGNBQWM7b0JBQ2pCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FDdkMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFDLENBQUM7b0JBQzdDLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLEdBQUcsVUFBVSxDQUNoRCxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUNoRCxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixHQUFHLFVBQVUsQ0FDaEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxhQUFhLENBQUMsQ0FBQztvQkFDOUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUM1QyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRSxTQUFTLENBQUMsQ0FBQztvQkFDaEQsTUFBTTtnQkFDUix5QkFBeUI7Z0JBQ3pCLEtBQUssUUFBUSxDQUFDO2dCQUNkLEtBQUssUUFBUTtvQkFDWCxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsR0FBRyxVQUFVLENBQzVDLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUM1QyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsR0FBRyxVQUFVLENBQzVDLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLFVBQVUsQ0FBQyxDQUFDO29CQUN2RSxNQUFNO2dCQUNSLG9DQUFvQztnQkFDcEMsS0FBSyxPQUFPLENBQUM7Z0JBQ2IsS0FBSyxVQUFVLENBQUM7Z0JBQ2hCLEtBQUssU0FBUyxDQUFDO2dCQUNmLEtBQUssYUFBYSxDQUFDO2dCQUNuQixLQUFLLGtCQUFrQixDQUFDO2dCQUN4QixLQUFLLGNBQWMsQ0FBQztnQkFDcEIsS0FBSyxnQkFBZ0IsQ0FBQztnQkFDdEIsS0FBSyxnQkFBZ0I7b0JBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQztvQkFDckMsTUFBTTtnQkFDUixLQUFLLFVBQVUsQ0FBQztnQkFDaEIsS0FBSyxNQUFNO29CQUNULElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FDdkMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsYUFBYSxDQUFDLENBQUM7b0JBQy9DLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FDNUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUM7b0JBQ2pELElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FDNUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDLENBQUM7b0JBQ3JELE1BQU07Z0JBQ1IsNkJBQTZCO2dCQUM3QixLQUFLLE1BQU07b0JBQ1QsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUM1QyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO29CQUN2RCxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsR0FBRyxVQUFVLENBQzVDLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLGFBQWEsQ0FBQyxDQUFDO29CQUMxRSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRywwQkFBMEIsQ0FBQztvQkFDL0MsTUFBTTtnQkFDUixxQ0FBcUM7Z0JBQ3JDO29CQUNFLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FDNUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDLENBQUM7YUFDeEQ7WUFFRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDOUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUVqRixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFO29CQUN0QixNQUFNLElBQUksR0FBVSxFQUFFLENBQUM7b0JBQ3ZCLElBQUksQ0FBQyxXQUFXLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztpQkFDdEY7YUFDRjtZQUNELElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUM7U0FDbEM7SUFFSCxDQUFDO0lBRUQsZUFBZSxDQUFDLE1BQU07UUFDcEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsTUFBTSxLQUFLLFNBQVM7WUFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU07WUFDeEQsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztZQUN6RCxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztZQUNqRixJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUM7SUFDMUQsQ0FBQztJQUVELFFBQVE7UUFDTixRQUFRLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFO1lBQzVCLEtBQUssUUFBUSxDQUFDO1lBQ2QsS0FBSyxVQUFVLENBQUM7WUFDaEIsS0FBSyxTQUFTLENBQUM7WUFDZixLQUFLLE1BQU0sQ0FBQztZQUNaLEtBQUssS0FBSyxDQUFDO1lBQ1gsS0FBSyxRQUFRLENBQUM7WUFDZCxLQUFLLFNBQVMsQ0FBQztZQUNmLEtBQUssVUFBVSxDQUFDO1lBQ2hCLEtBQUssTUFBTSxDQUFDO1lBQ1osS0FBSyxNQUFNO2dCQUNULE9BQU8sSUFBSSxDQUFDO1lBQ2QsS0FBSyxrQkFBa0I7Z0JBQ3JCLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztnQkFDckMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsa0JBQWtCLENBQUM7Z0JBQzlDLE9BQU8sSUFBSSxDQUFDO1lBQ2QsS0FBSyxjQUFjO2dCQUNqQixJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7Z0JBQ3JDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxHQUFHLHlCQUF5QixDQUFDO2dCQUNyRCxPQUFPLElBQUksQ0FBQztZQUNkLEtBQUssVUFBVTtnQkFDYixJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztnQkFDOUMsT0FBTyxJQUFJLENBQUM7WUFDZDtnQkFDRSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7Z0JBQ2hDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDdEM7SUFDSCxDQUFDO0lBRUQsVUFBVTtRQUNSLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVCLENBQUM7O3lIQTVPVSw0QkFBNEI7NkdBQTVCLDRCQUE0Qiw0S0NyQnpDLGlpRkE4REE7MkZEekNhLDRCQUE0QjtrQkFOeEMsU0FBUzsrQkFFRSx1QkFBdUI7NElBY3hCLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25Jbml0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IGNsb25lRGVlcCBmcm9tICdsb2Rhc2gvY2xvbmVEZWVwJztcbmltcG9ydCBtYXAgZnJvbSAnbG9kYXNoL21hcCc7XG5pbXBvcnQge0pzb25TY2hlbWFGb3JtU2VydmljZSwgYWRkQ2xhc3NlcywgaW5BcnJheX0gZnJvbSAnQGFqc2YvY29yZSc7XG5cbi8qKlxuICogQm9vdHN0cmFwIDQgZnJhbWV3b3JrIGZvciBBbmd1bGFyIEpTT04gU2NoZW1hIEZvcm0uXG4gKlxuICovXG5AQ29tcG9uZW50KHtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxuICBzZWxlY3RvcjogJ2Jvb3RzdHJhcC00LWZyYW1ld29yaycsXG4gIHRlbXBsYXRlVXJsOiAnLi9ib290c3RyYXA0LWZyYW1ld29yay5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2Jvb3RzdHJhcDQtZnJhbWV3b3JrLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIEJvb3RzdHJhcDRGcmFtZXdvcmtDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcyB7XG4gIGZyYW1ld29ya0luaXRpYWxpemVkID0gZmFsc2U7XG4gIHdpZGdldE9wdGlvbnM6IGFueTsgLy8gT3B0aW9ucyBwYXNzZWQgdG8gY2hpbGQgd2lkZ2V0XG4gIHdpZGdldExheW91dE5vZGU6IGFueTsgLy8gbGF5b3V0Tm9kZSBwYXNzZWQgdG8gY2hpbGQgd2lkZ2V0XG4gIG9wdGlvbnM6IGFueTsgLy8gT3B0aW9ucyB1c2VkIGluIHRoaXMgZnJhbWV3b3JrXG4gIGZvcm1Db250cm9sOiBhbnkgPSBudWxsO1xuICBkZWJ1Z091dHB1dDogYW55ID0gJyc7XG4gIGRlYnVnOiBhbnkgPSAnJztcbiAgcGFyZW50QXJyYXk6IGFueSA9IG51bGw7XG4gIGlzT3JkZXJhYmxlID0gZmFsc2U7XG4gIEBJbnB1dCgpIGxheW91dE5vZGU6IGFueTtcbiAgQElucHV0KCkgbGF5b3V0SW5kZXg6IG51bWJlcltdO1xuICBASW5wdXQoKSBkYXRhSW5kZXg6IG51bWJlcltdO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBjaGFuZ2VEZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHVibGljIGpzZjogSnNvblNjaGVtYUZvcm1TZXJ2aWNlXG4gICkge1xuICB9XG5cbiAgZ2V0IHNob3dSZW1vdmVCdXR0b24oKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMucmVtb3ZhYmxlIHx8IHRoaXMub3B0aW9ucy5yZWFkb25seSB8fFxuICAgICAgdGhpcy5sYXlvdXROb2RlLnR5cGUgPT09ICckcmVmJ1xuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAodGhpcy5sYXlvdXROb2RlLnJlY3Vyc2l2ZVJlZmVyZW5jZSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICghdGhpcy5sYXlvdXROb2RlLmFycmF5SXRlbSB8fCAhdGhpcy5wYXJlbnRBcnJheSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBJZiBhcnJheSBsZW5ndGggPD0gbWluSXRlbXMsIGRvbid0IGFsbG93IHJlbW92aW5nIGFueSBpdGVtc1xuICAgIHJldHVybiB0aGlzLnBhcmVudEFycmF5Lml0ZW1zLmxlbmd0aCAtIDEgPD0gdGhpcy5wYXJlbnRBcnJheS5vcHRpb25zLm1pbkl0ZW1zID8gZmFsc2UgOlxuICAgICAgLy8gRm9yIHJlbW92YWJsZSBsaXN0IGl0ZW1zLCBhbGxvdyByZW1vdmluZyBhbnkgaXRlbVxuICAgICAgdGhpcy5sYXlvdXROb2RlLmFycmF5SXRlbVR5cGUgPT09ICdsaXN0JyA/IHRydWUgOlxuICAgICAgICAvLyBGb3IgcmVtb3ZhYmxlIHR1cGxlIGl0ZW1zLCBvbmx5IGFsbG93IHJlbW92aW5nIGxhc3QgaXRlbSBpbiBsaXN0XG4gICAgICAgIHRoaXMubGF5b3V0SW5kZXhbdGhpcy5sYXlvdXRJbmRleC5sZW5ndGggLSAxXSA9PT0gdGhpcy5wYXJlbnRBcnJheS5pdGVtcy5sZW5ndGggLSAyO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5pbml0aWFsaXplRnJhbWV3b3JrKCk7XG4gICAgaWYgKHRoaXMubGF5b3V0Tm9kZS5hcnJheUl0ZW0gJiYgdGhpcy5sYXlvdXROb2RlLnR5cGUgIT09ICckcmVmJykge1xuICAgICAgdGhpcy5wYXJlbnRBcnJheSA9IHRoaXMuanNmLmdldFBhcmVudE5vZGUodGhpcyk7XG4gICAgICBpZiAodGhpcy5wYXJlbnRBcnJheSkge1xuICAgICAgICB0aGlzLmlzT3JkZXJhYmxlID0gdGhpcy5sYXlvdXROb2RlLmFycmF5SXRlbVR5cGUgPT09ICdsaXN0JyAmJlxuICAgICAgICAgICF0aGlzLm9wdGlvbnMucmVhZG9ubHkgJiYgdGhpcy5wYXJlbnRBcnJheS5vcHRpb25zLm9yZGVyYWJsZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuZ09uQ2hhbmdlcygpIHtcbiAgICBpZiAoIXRoaXMuZnJhbWV3b3JrSW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZUZyYW1ld29yaygpO1xuICAgIH1cbiAgfVxuXG4gIGluaXRpYWxpemVGcmFtZXdvcmsoKSB7XG4gICAgaWYgKHRoaXMubGF5b3V0Tm9kZSkge1xuICAgICAgdGhpcy5vcHRpb25zID0gY2xvbmVEZWVwKHRoaXMubGF5b3V0Tm9kZS5vcHRpb25zKTtcbiAgICAgIHRoaXMud2lkZ2V0TGF5b3V0Tm9kZSA9IHtcbiAgICAgICAgLi4udGhpcy5sYXlvdXROb2RlLFxuICAgICAgICBvcHRpb25zOiBjbG9uZURlZXAodGhpcy5sYXlvdXROb2RlLm9wdGlvbnMpXG4gICAgICB9O1xuICAgICAgdGhpcy53aWRnZXRPcHRpb25zID0gdGhpcy53aWRnZXRMYXlvdXROb2RlLm9wdGlvbnM7XG4gICAgICB0aGlzLmZvcm1Db250cm9sID0gdGhpcy5qc2YuZ2V0Rm9ybUNvbnRyb2wodGhpcyk7XG5cbiAgICAgIHRoaXMub3B0aW9ucy5pc0lucHV0V2lkZ2V0ID0gaW5BcnJheSh0aGlzLmxheW91dE5vZGUudHlwZSwgW1xuICAgICAgICAnYnV0dG9uJywgJ2NoZWNrYm94JywgJ2NoZWNrYm94ZXMtaW5saW5lJywgJ2NoZWNrYm94ZXMnLCAnY29sb3InLFxuICAgICAgICAnZGF0ZScsICdkYXRldGltZS1sb2NhbCcsICdkYXRldGltZScsICdlbWFpbCcsICdmaWxlJywgJ2hpZGRlbicsXG4gICAgICAgICdpbWFnZScsICdpbnRlZ2VyJywgJ21vbnRoJywgJ251bWJlcicsICdwYXNzd29yZCcsICdyYWRpbycsXG4gICAgICAgICdyYWRpb2J1dHRvbnMnLCAncmFkaW9zLWlubGluZScsICdyYWRpb3MnLCAncmFuZ2UnLCAncmVzZXQnLCAnc2VhcmNoJyxcbiAgICAgICAgJ3NlbGVjdCcsICdzdWJtaXQnLCAndGVsJywgJ3RleHQnLCAndGV4dGFyZWEnLCAndGltZScsICd1cmwnLCAnd2VlaydcbiAgICAgIF0pO1xuXG4gICAgICB0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLnNldFRpdGxlKCk7XG5cbiAgICAgIHRoaXMub3B0aW9ucy5odG1sQ2xhc3MgPVxuICAgICAgICBhZGRDbGFzc2VzKHRoaXMub3B0aW9ucy5odG1sQ2xhc3MsICdzY2hlbWEtZm9ybS0nICsgdGhpcy5sYXlvdXROb2RlLnR5cGUpO1xuICAgICAgdGhpcy5vcHRpb25zLmh0bWxDbGFzcyA9XG4gICAgICAgIHRoaXMubGF5b3V0Tm9kZS50eXBlID09PSAnYXJyYXknID9cbiAgICAgICAgICBhZGRDbGFzc2VzKHRoaXMub3B0aW9ucy5odG1sQ2xhc3MsICdsaXN0LWdyb3VwJykgOlxuICAgICAgICAgIHRoaXMubGF5b3V0Tm9kZS5hcnJheUl0ZW0gJiYgdGhpcy5sYXlvdXROb2RlLnR5cGUgIT09ICckcmVmJyA/XG4gICAgICAgICAgICBhZGRDbGFzc2VzKHRoaXMub3B0aW9ucy5odG1sQ2xhc3MsICdsaXN0LWdyb3VwLWl0ZW0nKSA6XG4gICAgICAgICAgICBhZGRDbGFzc2VzKHRoaXMub3B0aW9ucy5odG1sQ2xhc3MsICdmb3JtLWdyb3VwJyk7XG4gICAgICB0aGlzLndpZGdldE9wdGlvbnMuaHRtbENsYXNzID0gJyc7XG4gICAgICB0aGlzLm9wdGlvbnMubGFiZWxIdG1sQ2xhc3MgPVxuICAgICAgICBhZGRDbGFzc2VzKHRoaXMub3B0aW9ucy5sYWJlbEh0bWxDbGFzcywgJ2NvbnRyb2wtbGFiZWwnKTtcbiAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5hY3RpdmVDbGFzcyA9XG4gICAgICAgIGFkZENsYXNzZXModGhpcy53aWRnZXRPcHRpb25zLmFjdGl2ZUNsYXNzLCAnYWN0aXZlJyk7XG4gICAgICB0aGlzLm9wdGlvbnMuZmllbGRBZGRvbkxlZnQgPVxuICAgICAgICB0aGlzLm9wdGlvbnMuZmllbGRBZGRvbkxlZnQgfHwgdGhpcy5vcHRpb25zLnByZXBlbmQ7XG4gICAgICB0aGlzLm9wdGlvbnMuZmllbGRBZGRvblJpZ2h0ID1cbiAgICAgICAgdGhpcy5vcHRpb25zLmZpZWxkQWRkb25SaWdodCB8fCB0aGlzLm9wdGlvbnMuYXBwZW5kO1xuXG4gICAgICAvLyBBZGQgYXN0ZXJpc2sgdG8gdGl0bGVzIGlmIHJlcXVpcmVkXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnRpdGxlICYmIHRoaXMubGF5b3V0Tm9kZS50eXBlICE9PSAndGFiJyAmJlxuICAgICAgICAhdGhpcy5vcHRpb25zLm5vdGl0bGUgJiYgdGhpcy5vcHRpb25zLnJlcXVpcmVkICYmXG4gICAgICAgICF0aGlzLm9wdGlvbnMudGl0bGUuaW5jbHVkZXMoJyonKVxuICAgICAgKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucy50aXRsZSArPSAnIDxzdHJvbmcgY2xhc3M9XCJ0ZXh0LWRhbmdlclwiPio8L3N0cm9uZz4nO1xuICAgICAgfVxuICAgICAgLy8gU2V0IG1pc2NlbGFuZW91cyBzdHlsZXMgYW5kIHNldHRpbmdzIGZvciBlYWNoIGNvbnRyb2wgdHlwZVxuICAgICAgc3dpdGNoICh0aGlzLmxheW91dE5vZGUudHlwZSkge1xuICAgICAgICAvLyBDaGVja2JveCBjb250cm9sc1xuICAgICAgICBjYXNlICdjaGVja2JveCc6XG4gICAgICAgIGNhc2UgJ2NoZWNrYm94ZXMnOlxuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5odG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmh0bWxDbGFzcywgJ2NoZWNrYm94Jyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2NoZWNrYm94ZXMtaW5saW5lJzpcbiAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuaHRtbENsYXNzID0gYWRkQ2xhc3NlcyhcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5odG1sQ2xhc3MsICdjaGVja2JveCcpO1xuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5pdGVtTGFiZWxIdG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLml0ZW1MYWJlbEh0bWxDbGFzcywgJ2NoZWNrYm94LWlubGluZScpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICAvLyBSYWRpbyBjb250cm9sc1xuICAgICAgICBjYXNlICdyYWRpbyc6XG4gICAgICAgIGNhc2UgJ3JhZGlvcyc6XG4gICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmh0bWxDbGFzcyA9IGFkZENsYXNzZXMoXG4gICAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuaHRtbENsYXNzLCAncmFkaW8nKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncmFkaW9zLWlubGluZSc6XG4gICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmh0bWxDbGFzcyA9IGFkZENsYXNzZXMoXG4gICAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuaHRtbENsYXNzLCAncmFkaW8nKTtcbiAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuaXRlbUxhYmVsSHRtbENsYXNzID0gYWRkQ2xhc3NlcyhcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5pdGVtTGFiZWxIdG1sQ2xhc3MsICdyYWRpby1pbmxpbmUnKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgLy8gQnV0dG9uIHNldHMgLSBjaGVja2JveGJ1dHRvbnMgYW5kIHJhZGlvYnV0dG9uc1xuICAgICAgICBjYXNlICdjaGVja2JveGJ1dHRvbnMnOlxuICAgICAgICBjYXNlICdyYWRpb2J1dHRvbnMnOlxuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5odG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmh0bWxDbGFzcywgJ2J0bi1ncm91cCcpO1xuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5pdGVtTGFiZWxIdG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLml0ZW1MYWJlbEh0bWxDbGFzcywgJ2J0bicpO1xuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5pdGVtTGFiZWxIdG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLml0ZW1MYWJlbEh0bWxDbGFzcywgdGhpcy5vcHRpb25zLnN0eWxlIHx8ICdidG4tZGVmYXVsdCcpO1xuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5maWVsZEh0bWxDbGFzcyA9IGFkZENsYXNzZXMoXG4gICAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuZmllbGRIdG1sQ2xhc3MsICdzci1vbmx5Jyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIFNpbmdsZSBidXR0b24gY29udHJvbHNcbiAgICAgICAgY2FzZSAnYnV0dG9uJzpcbiAgICAgICAgY2FzZSAnc3VibWl0JzpcbiAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuZmllbGRIdG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmZpZWxkSHRtbENsYXNzLCAnYnRuJyk7XG4gICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmZpZWxkSHRtbENsYXNzID0gYWRkQ2xhc3NlcyhcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5maWVsZEh0bWxDbGFzcywgdGhpcy5vcHRpb25zLnN0eWxlIHx8ICdidG4taW5mbycpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICAvLyBDb250YWluZXJzIC0gYXJyYXlzIGFuZCBmaWVsZHNldHNcbiAgICAgICAgY2FzZSAnYXJyYXknOlxuICAgICAgICBjYXNlICdmaWVsZHNldCc6XG4gICAgICAgIGNhc2UgJ3NlY3Rpb24nOlxuICAgICAgICBjYXNlICdjb25kaXRpb25hbCc6XG4gICAgICAgIGNhc2UgJ2FkdmFuY2VkZmllbGRzZXQnOlxuICAgICAgICBjYXNlICdhdXRoZmllbGRzZXQnOlxuICAgICAgICBjYXNlICdzZWxlY3RmaWVsZHNldCc6XG4gICAgICAgIGNhc2UgJ29wdGlvbmZpZWxkc2V0JzpcbiAgICAgICAgICB0aGlzLm9wdGlvbnMubWVzc2FnZUxvY2F0aW9uID0gJ3RvcCc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3RhYmFycmF5JzpcbiAgICAgICAgY2FzZSAndGFicyc6XG4gICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmh0bWxDbGFzcyA9IGFkZENsYXNzZXMoXG4gICAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuaHRtbENsYXNzLCAndGFiLWNvbnRlbnQnKTtcbiAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuZmllbGRIdG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmZpZWxkSHRtbENsYXNzLCAndGFiLXBhbmUnKTtcbiAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMubGFiZWxIdG1sQ2xhc3MgPSBhZGRDbGFzc2VzKFxuICAgICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmxhYmVsSHRtbENsYXNzLCAnbmF2IG5hdi10YWJzJyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vICdBZGQnIGJ1dHRvbnMgLSByZWZlcmVuY2VzXG4gICAgICAgIGNhc2UgJyRyZWYnOlxuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5maWVsZEh0bWxDbGFzcyA9IGFkZENsYXNzZXMoXG4gICAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuZmllbGRIdG1sQ2xhc3MsICdidG4gcHVsbC1yaWdodCcpO1xuICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5maWVsZEh0bWxDbGFzcyA9IGFkZENsYXNzZXMoXG4gICAgICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMuZmllbGRIdG1sQ2xhc3MsIHRoaXMub3B0aW9ucy5zdHlsZSB8fCAnYnRuLWRlZmF1bHQnKTtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuaWNvbiA9ICdnbHlwaGljb24gZ2x5cGhpY29uLXBsdXMnO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICAvLyBEZWZhdWx0IC0gaW5jbHVkaW5nIHJlZ3VsYXIgaW5wdXRzXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLmZpZWxkSHRtbENsYXNzID0gYWRkQ2xhc3NlcyhcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5maWVsZEh0bWxDbGFzcywgJ2Zvcm0tY29udHJvbCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5mb3JtQ29udHJvbCkge1xuICAgICAgICB0aGlzLnVwZGF0ZUhlbHBCbG9jayh0aGlzLmZvcm1Db250cm9sLnN0YXR1cyk7XG4gICAgICAgIHRoaXMuZm9ybUNvbnRyb2wuc3RhdHVzQ2hhbmdlcy5zdWJzY3JpYmUoc3RhdHVzID0+IHRoaXMudXBkYXRlSGVscEJsb2NrKHN0YXR1cykpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGVidWcpIHtcbiAgICAgICAgICBjb25zdCB2YXJzOiBhbnlbXSA9IFtdO1xuICAgICAgICAgIHRoaXMuZGVidWdPdXRwdXQgPSBtYXAodmFycywgdGhpc1ZhciA9PiBKU09OLnN0cmluZ2lmeSh0aGlzVmFyLCBudWxsLCAyKSkuam9pbignXFxuJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuZnJhbWV3b3JrSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH1cblxuICB9XG5cbiAgdXBkYXRlSGVscEJsb2NrKHN0YXR1cykge1xuICAgIHRoaXMub3B0aW9ucy5oZWxwQmxvY2sgPSBzdGF0dXMgPT09ICdJTlZBTElEJyAmJlxuICAgIHRoaXMub3B0aW9ucy5lbmFibGVFcnJvclN0YXRlICYmIHRoaXMuZm9ybUNvbnRyb2wuZXJyb3JzICYmXG4gICAgKHRoaXMuZm9ybUNvbnRyb2wuZGlydHkgfHwgdGhpcy5vcHRpb25zLmZlZWRiYWNrT25SZW5kZXIpID9cbiAgICAgIHRoaXMuanNmLmZvcm1hdEVycm9ycyh0aGlzLmZvcm1Db250cm9sLmVycm9ycywgdGhpcy5vcHRpb25zLnZhbGlkYXRpb25NZXNzYWdlcykgOlxuICAgICAgdGhpcy5vcHRpb25zLmRlc2NyaXB0aW9uIHx8IHRoaXMub3B0aW9ucy5oZWxwIHx8IG51bGw7XG4gIH1cblxuICBzZXRUaXRsZSgpOiBzdHJpbmcge1xuICAgIHN3aXRjaCAodGhpcy5sYXlvdXROb2RlLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2J1dHRvbic6XG4gICAgICBjYXNlICdjaGVja2JveCc6XG4gICAgICBjYXNlICdzZWN0aW9uJzpcbiAgICAgIGNhc2UgJ2hlbHAnOlxuICAgICAgY2FzZSAnbXNnJzpcbiAgICAgIGNhc2UgJ3N1Ym1pdCc6XG4gICAgICBjYXNlICdtZXNzYWdlJzpcbiAgICAgIGNhc2UgJ3RhYmFycmF5JzpcbiAgICAgIGNhc2UgJ3RhYnMnOlxuICAgICAgY2FzZSAnJHJlZic6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgY2FzZSAnYWR2YW5jZWRmaWVsZHNldCc6XG4gICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5leHBhbmRhYmxlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLnRpdGxlID0gJ0FkdmFuY2VkIG9wdGlvbnMnO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGNhc2UgJ2F1dGhmaWVsZHNldCc6XG4gICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy5leHBhbmRhYmxlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy53aWRnZXRPcHRpb25zLnRpdGxlID0gJ0F1dGhlbnRpY2F0aW9uIHNldHRpbmdzJztcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBjYXNlICdmaWVsZHNldCc6XG4gICAgICAgIHRoaXMud2lkZ2V0T3B0aW9ucy50aXRsZSA9IHRoaXMub3B0aW9ucy50aXRsZTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aGlzLndpZGdldE9wdGlvbnMudGl0bGUgPSBudWxsO1xuICAgICAgICByZXR1cm4gdGhpcy5qc2Yuc2V0SXRlbVRpdGxlKHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHJlbW92ZUl0ZW0oKSB7XG4gICAgdGhpcy5qc2YucmVtb3ZlSXRlbSh0aGlzKTtcbiAgfVxufVxuIiwiPGRpdlxuICBbY2xhc3NdPVwib3B0aW9ucz8uaHRtbENsYXNzIHx8ICcnXCJcbiAgW2NsYXNzLmhhcy1mZWVkYmFja109XCJvcHRpb25zPy5mZWVkYmFjayAmJiBvcHRpb25zPy5pc0lucHV0V2lkZ2V0ICYmXG4gICAgICAgIChmb3JtQ29udHJvbD8uZGlydHkgfHwgb3B0aW9ucz8uZmVlZGJhY2tPblJlbmRlcilcIlxuICBbY2xhc3MuaGFzLWVycm9yXT1cIm9wdGlvbnM/LmVuYWJsZUVycm9yU3RhdGUgJiYgZm9ybUNvbnRyb2w/LmVycm9ycyAmJlxuICAgICAgICAoZm9ybUNvbnRyb2w/LmRpcnR5IHx8IG9wdGlvbnM/LmZlZWRiYWNrT25SZW5kZXIpXCJcbiAgW2NsYXNzLmhhcy1zdWNjZXNzXT1cIm9wdGlvbnM/LmVuYWJsZVN1Y2Nlc3NTdGF0ZSAmJiAhZm9ybUNvbnRyb2w/LmVycm9ycyAmJlxuICAgICAgICAoZm9ybUNvbnRyb2w/LmRpcnR5IHx8IG9wdGlvbnM/LmZlZWRiYWNrT25SZW5kZXIpXCI+XG5cbiAgPGJ1dHRvbiAqbmdJZj1cInNob3dSZW1vdmVCdXR0b25cIlxuICAgICAgICAgIGNsYXNzPVwiY2xvc2UgcHVsbC1yaWdodFwiXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgKGNsaWNrKT1cInJlbW92ZUl0ZW0oKVwiPlxuICAgIDxzcGFuIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPiZ0aW1lczs8L3NwYW4+XG4gICAgPHNwYW4gY2xhc3M9XCJzci1vbmx5XCI+Q2xvc2U8L3NwYW4+XG4gIDwvYnV0dG9uPlxuICA8ZGl2ICpuZ0lmPVwib3B0aW9ucz8ubWVzc2FnZUxvY2F0aW9uID09PSAndG9wJ1wiPlxuICAgIDxwICpuZ0lmPVwib3B0aW9ucz8uaGVscEJsb2NrXCJcbiAgICAgICBjbGFzcz1cImhlbHAtYmxvY2tcIlxuICAgICAgIFtpbm5lckhUTUxdPVwib3B0aW9ucz8uaGVscEJsb2NrXCI+PC9wPlxuICA8L2Rpdj5cblxuICA8bGFiZWwgKm5nSWY9XCJvcHRpb25zPy50aXRsZSAmJiBsYXlvdXROb2RlPy50eXBlICE9PSAndGFiJ1wiXG4gICAgICAgICBbYXR0ci5mb3JdPVwiJ2NvbnRyb2wnICsgbGF5b3V0Tm9kZT8uX2lkXCJcbiAgICAgICAgIFtjbGFzc109XCJvcHRpb25zPy5sYWJlbEh0bWxDbGFzcyB8fCAnJ1wiXG4gICAgICAgICBbY2xhc3Muc3Itb25seV09XCJvcHRpb25zPy5ub3RpdGxlXCJcbiAgICAgICAgIFtpbm5lckhUTUxdPVwib3B0aW9ucz8udGl0bGVcIj48L2xhYmVsPlxuICA8cCAqbmdJZj1cImxheW91dE5vZGU/LnR5cGUgPT09ICdzdWJtaXQnICYmIGpzZj8uZm9ybU9wdGlvbnM/LmZpZWxkc1JlcXVpcmVkXCI+XG4gICAgPHN0cm9uZyBjbGFzcz1cInRleHQtZGFuZ2VyXCI+Kjwvc3Ryb25nPiA9IHJlcXVpcmVkIGZpZWxkc1xuICA8L3A+XG4gIDxkaXYgW2NsYXNzLmlucHV0LWdyb3VwXT1cIm9wdGlvbnM/LmZpZWxkQWRkb25MZWZ0IHx8IG9wdGlvbnM/LmZpZWxkQWRkb25SaWdodFwiPlxuICAgICAgICA8c3BhbiAqbmdJZj1cIm9wdGlvbnM/LmZpZWxkQWRkb25MZWZ0XCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJpbnB1dC1ncm91cC1hZGRvblwiXG4gICAgICAgICAgICAgIFtpbm5lckhUTUxdPVwib3B0aW9ucz8uZmllbGRBZGRvbkxlZnRcIj48L3NwYW4+XG5cbiAgICA8c2VsZWN0LXdpZGdldC13aWRnZXRcbiAgICAgIFtsYXlvdXROb2RlXT1cIndpZGdldExheW91dE5vZGVcIlxuICAgICAgW2RhdGFJbmRleF09XCJkYXRhSW5kZXhcIlxuICAgICAgW2xheW91dEluZGV4XT1cImxheW91dEluZGV4XCI+PC9zZWxlY3Qtd2lkZ2V0LXdpZGdldD5cblxuICAgIDxzcGFuICpuZ0lmPVwib3B0aW9ucz8uZmllbGRBZGRvblJpZ2h0XCJcbiAgICAgICAgICBjbGFzcz1cImlucHV0LWdyb3VwLWFkZG9uXCJcbiAgICAgICAgICBbaW5uZXJIVE1MXT1cIm9wdGlvbnM/LmZpZWxkQWRkb25SaWdodFwiPjwvc3Bhbj5cbiAgPC9kaXY+XG5cbiAgPHNwYW4gKm5nSWY9XCJvcHRpb25zPy5mZWVkYmFjayAmJiBvcHRpb25zPy5pc0lucHV0V2lkZ2V0ICYmXG4gICAgICAgICAgIW9wdGlvbnM/LmZpZWxkQWRkb25SaWdodCAmJiAhbGF5b3V0Tm9kZS5hcnJheUl0ZW0gJiZcbiAgICAgICAgICAoZm9ybUNvbnRyb2w/LmRpcnR5IHx8IG9wdGlvbnM/LmZlZWRiYWNrT25SZW5kZXIpXCJcbiAgICAgICAgW2NsYXNzLmdseXBoaWNvbi1va109XCJvcHRpb25zPy5lbmFibGVTdWNjZXNzU3RhdGUgJiYgIWZvcm1Db250cm9sPy5lcnJvcnNcIlxuICAgICAgICBbY2xhc3MuZ2x5cGhpY29uLXJlbW92ZV09XCJvcHRpb25zPy5lbmFibGVFcnJvclN0YXRlICYmIGZvcm1Db250cm9sPy5lcnJvcnNcIlxuICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbC1mZWVkYmFjayBnbHlwaGljb25cIj48L3NwYW4+XG4gIDxkaXYgKm5nSWY9XCJvcHRpb25zPy5tZXNzYWdlTG9jYXRpb24gIT09ICd0b3AnXCI+XG4gICAgPHAgKm5nSWY9XCJvcHRpb25zPy5oZWxwQmxvY2tcIlxuICAgICAgIGNsYXNzPVwiaGVscC1ibG9ja1wiXG4gICAgICAgW2lubmVySFRNTF09XCJvcHRpb25zPy5oZWxwQmxvY2tcIj48L3A+XG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJkZWJ1ZyAmJiBkZWJ1Z091dHB1dFwiPmRlYnVnOlxuICA8cHJlPnt7ZGVidWdPdXRwdXR9fTwvcHJlPlxuPC9kaXY+XG4iXX0=