truly-ui
Version:
Web Components for Desktop Applications.
468 lines (466 loc) • 66.7 kB
JavaScript
/*
MIT License
Copyright (c) 2019 Temainfo Software
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, ContentChild, ContentChildren, EventEmitter, forwardRef, Input, Output, ViewChild, } from '@angular/core';
import { KeyEvent } from '../core/enums/key-events';
import { TlInput } from '../input/input';
import { UntypedFormGroup, NgForm, NgModel } from '@angular/forms';
import { TlButton } from '../button/button';
import { FormSubmitDirective } from './form-submit.directive';
import { ModalService } from '../modal/services/modal.service';
import { ActionsModal } from '../core/enums/actions-modal';
import { Subscription } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "../i18n/i18n.service";
import * as i2 from "@angular/common";
import * as i3 from "../loader/loader";
import * as i4 from "../button/button";
import * as i5 from "@angular/forms";
import * as i6 from "../shortcut/shortcut.directive";
import * as i7 from "../modal/directives/modal-result.directive";
let componentFormIndex;
export class TlForm {
set initialFocus(value) {
if (value) {
this._initialFocus = value;
this.change.detectChanges();
this.setInitialFocus();
}
}
get initialFocus() {
return this._initialFocus;
}
constructor(renderer, i18n, change, injector) {
this.renderer = renderer;
this.i18n = i18n;
this.change = change;
this.injector = injector;
this.showConfirmOnChange = false;
this.isLoading = false;
this.submitOnLastField = false;
this.primaryKey = '';
this.messageDialogConfirmation = 'Are you sure ?';
this.submitShortcut = '';
this.cancelShortcut = 'escape';
this.mode = 'modal';
this.textConfirm = this.i18n.getLocale().Form.textOk;
this.textCancel = this.i18n.getLocale().Form.textCancel;
this.padding = '10px';
this.formLoaded = new EventEmitter();
this.submitForm = new EventEmitter();
this.actionForm = new EventEmitter();
this.changeForm = new EventEmitter();
this.focusElements = [];
this.elementsWithTabIndex = [];
this.subscription = new Subscription();
this.modalInstance = this.injector.get(ModalService);
}
get valid() {
return this.form.valid;
}
get formInstance() {
return this.formGroup ? this.formGroup : this.form.form;
}
ngOnInit() {
componentFormIndex = -1;
}
ngAfterContentInit() {
this.handleFormGroupValues();
this.handleSmartFormAction();
this.setPrimaryKeyDisabled();
this.addControls();
}
handleSmartFormAction() {
if (this.modalInstance.modalConfiguration) {
this.actionForm.emit(this.modalInstance.modalConfiguration.executeAction);
}
}
ngAfterViewInit() {
this.getElementsOfForm();
this.formLoaded.emit(this.formInstance);
this.setInitialFocus();
this.listenSubmitDirective();
this.listenFormChanges();
}
listenSubmitDirective() {
if (this.submitDirective) {
this.subscription.add(this.submitDirective.submit.subscribe(() => {
this.submitForm.emit(this.formInstance.value);
}));
}
}
listenFormChanges() {
this.subscription.add(this.formInstance.valueChanges.subscribe(() => {
this.changeForm.emit(this.formInstance);
this.change.detectChanges();
}));
}
handleFormGroupValues() {
if (this.formGroup) {
if (this.modalInstance.modalConfiguration &&
this.modalInstance.modalConfiguration.executeAction !== ActionsModal.INSERT &&
this.modalInstance.modalConfiguration.dataForm && this.mode === 'modal') {
this.patchDataForm();
}
if (this.modalInstance.modalConfiguration &&
this.modalInstance.modalConfiguration.executeAction === ActionsModal.INSERT &&
this.modalInstance.modalConfiguration.initialDataForm && this.mode === 'modal') {
this.patchInitialDataForm();
}
}
}
patchDataForm() {
this.formGroup.patchValue(this.modalInstance.modalConfiguration.dataForm);
this.markAllAsTouched(this.formGroup.controls);
this.change.detectChanges();
}
patchInitialDataForm() {
this.formGroup.patchValue(this.modalInstance.modalConfiguration.initialDataForm);
this.markAllAsTouched(this.formGroup.controls);
this.change.detectChanges();
}
markAllAsTouched(controls) {
Object.keys(controls).forEach(key => {
if (controls[key] instanceof UntypedFormGroup) {
this.markAllAsTouched(controls[key].controls);
}
else {
controls[key].markAsTouched();
}
});
}
setPrimaryKeyDisabled() {
if (this.primaryKey && this.formGroup) {
this.formGroup.get(this.primaryKey).disable();
}
}
addControls() {
if (!this.formGroup) {
this.models.toArray().forEach((item, index, array) => {
this.form.addControl(item);
});
}
}
onSubmitForm() {
this.handleFormPrimaryKey();
this.formResult = this.formInstance.value;
this.submitForm.emit(this.formInstance.value);
this.change.detectChanges();
}
handleFormPrimaryKey() {
if (this.primaryKey && this.modalInstance.modalConfiguration.executeAction === ActionsModal.UPDATE) {
this.formInstance.get(this.primaryKey).enable();
}
}
getElementsOfForm() {
const listFormComponents = this.content.nativeElement.querySelectorAll('*');
for (let childFormComponents = 0; childFormComponents < listFormComponents.length; childFormComponents++) {
if ((listFormComponents[childFormComponents].tagName === 'INPUT'
|| listFormComponents[childFormComponents].tagName === 'TEXTAREA'
|| listFormComponents[childFormComponents].classList.contains('ui-editor-content')) &&
!this.taggedNotForm(listFormComponents[childFormComponents])) {
this.focusElements.push(listFormComponents[childFormComponents]);
}
}
this.addButtonsOfFormToListElements();
this.handleTabIndexComponentsOfForm();
}
taggedNotForm(element) {
for (let item = 0; item < element.attributes.length; item++) {
if (element.attributes[item].nodeValue === 'notform' || element.attributes[item].nodeName === 'notform') {
return true;
}
}
return false;
}
addButtonsOfFormToListElements() {
if (this.mode === 'inline') {
this.buttonList.forEach((item, index, array) => {
index === 0 ? this.buttonFormOk = item : this.buttonFormCancel = item;
});
}
if (this.buttonFormOk) {
this.focusElements.push(this.buttonFormOk.buttonElement.nativeElement);
}
if (this.buttonFormCancel) {
this.focusElements.push(this.buttonFormCancel.buttonElement.nativeElement);
}
}
handleTabIndexComponentsOfForm() {
setTimeout(() => {
this.getElementsWithTabIndex();
this.generateTabIndexOfElements();
this.orderElements();
this.validateTabIndexByElements();
}, 10);
}
setTabIndex(element) {
if (!element.tabIndex) {
componentFormIndex++;
this.notExistTabIndexInserted() ? element.setAttribute('tabIndex', componentFormIndex)
: this.setTabIndex(element);
}
}
isLastTabIndexElement(element, index, array) {
if (index === array.length - 1) {
this.lastTabIndex = element.tabIndex;
}
}
generateTabIndexOfElements() {
this.focusElements.forEach((element, index, array) => {
this.setTabIndex(element);
this.isLastTabIndexElement(element, index, array);
});
}
getElementsWithTabIndex() {
this.focusElements.forEach((element) => {
if (element.tabIndex) {
this.validateDuplicatedTabIndex(element);
this.elementsWithTabIndex.push(element.tabIndex);
}
});
}
validateDuplicatedTabIndex(element) {
if (this.existTabIndexInserted(element)) {
throw new EvalError('Exist an element with tabIndex duplicated! TabIndex : ' + element.tabIndex);
}
}
validateTabIndexByElements() {
const formElementsDefault = 3;
if (Math.max(...this.elementsWithTabIndex) > this.focusElements.length - formElementsDefault) {
throw new EvalError('The form doesn\'t have the number' +
' of elements enough according with TabIndex passed : ' + Math.max(...this.elementsWithTabIndex));
}
}
notExistTabIndexInserted() {
return this.elementsWithTabIndex.indexOf(componentFormIndex) < 0;
}
existTabIndexInserted(element) {
return this.elementsWithTabIndex.indexOf(element.tabIndex) >= 0;
}
orderElements() {
let order;
order = this.focusElements.sort(function (a, b) {
return a.getAttribute('tabindex') - b.getAttribute('tabindex');
});
this.focusElements = order;
}
handleKeysForm($event) {
if ($event.code === KeyEvent.TAB && $event.shiftKey) {
$event.preventDefault();
this.backwardTabbing();
return;
}
switch ($event.code) {
case KeyEvent.ARROWUP:
$event.preventDefault();
this.backwardTabbing();
break;
case KeyEvent.ARROWDOWN:
$event.preventDefault();
this.forwardTabbing();
break;
case KeyEvent.ARROWRIGHT:
this.setFocusOK();
break;
case KeyEvent.ARROWLEFT:
this.setFocusCancel();
break;
case KeyEvent.TAB:
if (!this.isTextArea()) {
$event.preventDefault();
}
this.forwardTabbing();
break;
case KeyEvent.ENTER:
if (!this.isTextArea()) {
$event.preventDefault();
}
this.forwardTabbing('enter');
break;
case KeyEvent.NUMPADENTER:
if (!this.isTextArea()) {
$event.preventDefault();
}
this.forwardTabbing('enter');
break;
}
}
backwardTabbing() {
this.change.detectChanges();
if (this.isFirstTabIndexOfForm()) {
return this.focusElements[this.lastTabIndex].focus();
}
if (!this.validateFirstElement()) {
const previousElement = document.activeElement.tabIndex - 1;
for (let element = previousElement; element < this.focusElements.length && (element >= 0); element--) {
if (!this.isElementDisabled(this.focusElements[element])) {
return this.focusElements[element].focus();
}
}
}
}
validateFirstElement() {
return (this.focusElements[0].getAttribute('disabled')) && (this.focusElements[1] === document.activeElement);
}
forwardTabbing(keyEnter) {
this.change.detectChanges();
if (this.isLastTabIndexOfForm()) {
return this.focusElements[0].focus();
}
if (this.isTextArea()) {
return;
}
const nextElement = document.activeElement.tabIndex + 1;
for (let element = nextElement; element < this.focusElements.length; element++) {
if (this.focusElements[element].localName === 'button' && this.submitOnLastField && keyEnter) {
this.onSubmitForm();
return;
}
if (!this.isElementDisabled(this.focusElements[element])) {
return this.focusElements[element].focus();
}
}
}
isTextArea() {
return document.activeElement.localName === 'textarea';
}
isLastTabIndexOfForm() {
return document.activeElement.tabIndex === this.lastTabIndex;
}
isFirstTabIndexOfForm() {
return document.activeElement.tabIndex === 0;
}
isElementDisabled(element) {
if (element === undefined) {
return false;
}
return element.disabled;
}
setInitialFocus() {
setTimeout(() => {
this.initialFocus ? this.initialFocus.getNativeInput().focus()
: this.setFocusOnFirstInput();
}, 250);
}
setFocusOK() {
if (this.isActiveElementButtonCancel() && this.buttonFormOk) {
this.buttonFormOk.buttonElement.nativeElement.focus();
}
}
setFocusCancel() {
if (this.isActiveElementButtonOk() && this.buttonFormCancel) {
this.buttonFormCancel.buttonElement.nativeElement.focus();
}
}
setFocusOnFirstInput() {
const enableElement = this.inputArray.filter((value) => !value.disabled);
if (enableElement.length > 0) {
enableElement[0].focus();
}
}
get inputArray() {
return this.inputList.map((item) => item.getNativeInput());
}
isActiveElementButtonOk() {
if (!this.buttonFormOk) {
return false;
}
return document.activeElement === this.buttonFormOk.buttonElement.nativeElement;
}
isActiveElementButtonCancel() {
if (!this.buttonFormCancel) {
return false;
}
return document.activeElement === this.buttonFormCancel.buttonElement.nativeElement;
}
destroyListeners() {
this.subscription.unsubscribe();
}
ngOnDestroy() {
this.destroyListeners();
}
}
/** @nocollapse */ TlForm.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlForm, deps: [{ token: i0.Renderer2 }, { token: i1.I18nService }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TlForm.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlForm, selector: "tl-form", inputs: { initialFocus: "initialFocus", showConfirmOnChange: "showConfirmOnChange", isLoading: "isLoading", submitOnLastField: "submitOnLastField", primaryKey: "primaryKey", messageDialogConfirmation: "messageDialogConfirmation", submitShortcut: "submitShortcut", cancelShortcut: "cancelShortcut", mode: "mode", textConfirm: "textConfirm", textCancel: "textCancel", padding: "padding", formGroup: "formGroup" }, outputs: { formLoaded: "formLoaded", submitForm: "submitForm", actionForm: "actionForm", changeForm: "changeForm" }, queries: [{ propertyName: "submitDirective", first: true, predicate: FormSubmitDirective, descendants: true, static: true }, { propertyName: "inputList", predicate: i0.forwardRef(function () { return TlInput; }), descendants: true }, { propertyName: "buttonList", predicate: i0.forwardRef(function () { return TlButton; }), descendants: true }, { propertyName: "models", predicate: i0.forwardRef(function () { return NgModel; }), descendants: true }], viewQueries: [{ propertyName: "form", first: true, predicate: NgForm, descendants: true, static: true }, { propertyName: "buttonFormOk", first: true, predicate: ["buttonFormOk"], descendants: true }, { propertyName: "buttonFormCancel", first: true, predicate: ["buttonFormCancel"], descendants: true }, { propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"formBox\" (keydown)=\"handleKeysForm($event)\">\n <div class=\"loading\" *ngIf=\"isLoading\">\n <div class=\"loader\">\n <tl-loader></tl-loader>\n </div>\n </div>\n <div class=\"formContent\" #content [style.padding]=\"padding\">\n <form novalidate #form=\"ngForm\">\n <ng-content></ng-content>\n </form>\n </div>\n <div [ngClass]=\"{'clearfix': mode !== 'inline'}\"></div>\n <div [ngClass]=\"{'forFooter': mode !== 'inline'}\">\n <div class=\"controls\" *ngIf=\"mode !== 'inline'\">\n <tl-button #buttonFormCancel\n [text]=\"textCancel\"\n [width]=\"'120px'\"\n mdResult=\"MRCANCEL\"\n [color]=\"'basic'\"\n [style.padding-right]=\"'5px'\"\n [shortcut]=\"cancelShortcut\"\n [formResult]=\"formResult\"\n [iconAddonBefore]=\"'fas fa-times'\">\n </tl-button>\n <tl-button #buttonFormOk\n [text]=\"textConfirm\"\n [isLoading]=\"isLoading\"\n mdResult=\"MROK\"\n (click)=\"onSubmitForm()\"\n (keydown.enter)=\"onSubmitForm()\"\n [width]=\"'120px'\"\n [color]=\"'success'\"\n [shortcut]=\"submitShortcut\"\n [disabled]=\"isLoading ? true : !formInstance.valid\"\n [formResult]=\"formResult\"\n [iconAddonBefore]=\"'fas fa-check'\">\n </tl-button>\n </div>\n </div>\n</div>\n", styles: [".formBox{position:relative}.formContent{position:relative;height:calc(100% - 34px)}.loading{z-index:1;width:100%;height:100%;position:absolute;display:flex;align-items:center;justify-content:center}.loading .loader{width:50px;height:50px}.forFooter{position:absolute;right:0;bottom:0;left:0;padding:.3rem;text-align:center}.clearfix{height:60px}.controls{text-align:left;float:right;padding:10px;display:flex}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.TlLoader, selector: "tl-loader", inputs: ["color", "strokeWidth"] }, { kind: "component", type: i4.TlButton, selector: "tl-button", inputs: ["text", "iconAddonBefore", "iconAddonAfter", "iconBeforeText", "iconAfterText", "height", "width", "disabled", "flatBorder", "colorIconBefore", "colorIconAfter", "template", "outline", "color", "loaderColor", "isLoading", "indexShortcut", "textLoading"], outputs: ["selected"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.ShortcutDirective, selector: "[shortcut]", inputs: ["shortcut"] }, { kind: "directive", type: i7.ModalResultDirective, selector: "[mdResult]", inputs: ["mdResult", "formResult"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlForm, decorators: [{
type: Component,
args: [{ selector: 'tl-form', template: "<div class=\"formBox\" (keydown)=\"handleKeysForm($event)\">\n <div class=\"loading\" *ngIf=\"isLoading\">\n <div class=\"loader\">\n <tl-loader></tl-loader>\n </div>\n </div>\n <div class=\"formContent\" #content [style.padding]=\"padding\">\n <form novalidate #form=\"ngForm\">\n <ng-content></ng-content>\n </form>\n </div>\n <div [ngClass]=\"{'clearfix': mode !== 'inline'}\"></div>\n <div [ngClass]=\"{'forFooter': mode !== 'inline'}\">\n <div class=\"controls\" *ngIf=\"mode !== 'inline'\">\n <tl-button #buttonFormCancel\n [text]=\"textCancel\"\n [width]=\"'120px'\"\n mdResult=\"MRCANCEL\"\n [color]=\"'basic'\"\n [style.padding-right]=\"'5px'\"\n [shortcut]=\"cancelShortcut\"\n [formResult]=\"formResult\"\n [iconAddonBefore]=\"'fas fa-times'\">\n </tl-button>\n <tl-button #buttonFormOk\n [text]=\"textConfirm\"\n [isLoading]=\"isLoading\"\n mdResult=\"MROK\"\n (click)=\"onSubmitForm()\"\n (keydown.enter)=\"onSubmitForm()\"\n [width]=\"'120px'\"\n [color]=\"'success'\"\n [shortcut]=\"submitShortcut\"\n [disabled]=\"isLoading ? true : !formInstance.valid\"\n [formResult]=\"formResult\"\n [iconAddonBefore]=\"'fas fa-check'\">\n </tl-button>\n </div>\n </div>\n</div>\n", styles: [".formBox{position:relative}.formContent{position:relative;height:calc(100% - 34px)}.loading{z-index:1;width:100%;height:100%;position:absolute;display:flex;align-items:center;justify-content:center}.loading .loader{width:50px;height:50px}.forFooter{position:absolute;right:0;bottom:0;left:0;padding:.3rem;text-align:center}.clearfix{height:60px}.controls{text-align:left;float:right;padding:10px;display:flex}\n"] }]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i1.I18nService }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }]; }, propDecorators: { initialFocus: [{
type: Input,
args: ['initialFocus']
}], showConfirmOnChange: [{
type: Input
}], isLoading: [{
type: Input
}], submitOnLastField: [{
type: Input
}], primaryKey: [{
type: Input
}], messageDialogConfirmation: [{
type: Input
}], submitShortcut: [{
type: Input
}], cancelShortcut: [{
type: Input
}], mode: [{
type: Input
}], textConfirm: [{
type: Input
}], textCancel: [{
type: Input
}], padding: [{
type: Input
}], formLoaded: [{
type: Output
}], submitForm: [{
type: Output
}], actionForm: [{
type: Output
}], changeForm: [{
type: Output
}], formGroup: [{
type: Input,
args: ['formGroup']
}], form: [{
type: ViewChild,
args: [NgForm, { static: true }]
}], inputList: [{
type: ContentChildren,
args: [forwardRef(() => TlInput), { descendants: true }]
}], buttonList: [{
type: ContentChildren,
args: [forwardRef(() => TlButton), { descendants: true }]
}], models: [{
type: ContentChildren,
args: [forwardRef(() => NgModel), { descendants: true }]
}], submitDirective: [{
type: ContentChild,
args: [FormSubmitDirective, { static: true }]
}], buttonFormOk: [{
type: ViewChild,
args: ['buttonFormOk', { static: false }]
}], buttonFormCancel: [{
type: ViewChild,
args: ['buttonFormCancel', { static: false }]
}], content: [{
type: ViewChild,
args: ['content', { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL2Zvcm0vZm9ybS50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL2Zvcm0vZm9ybS5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9CRztBQUNILE9BQU8sRUFLTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLGVBQWUsRUFDZixZQUFZLEVBQ1osVUFBVSxFQUVWLEtBQUssRUFHTCxNQUFNLEVBR04sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUVsRCxPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkMsT0FBTyxFQUFDLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRSxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDMUMsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlDQUFpQyxDQUFDO0FBQzdELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSw2QkFBNkIsQ0FBQztBQUN6RCxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sTUFBTSxDQUFDOzs7Ozs7Ozs7QUFFbEMsSUFBSSxrQkFBa0IsQ0FBQztBQU92QixNQUFNLE9BQU8sTUFBTTtJQUVqQixJQUNJLFlBQVksQ0FBRSxLQUFLO1FBQ3JCLElBQUssS0FBSyxFQUFHO1lBQ1gsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7WUFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM1QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7U0FDeEI7SUFDSCxDQUFDO0lBRUQsSUFBSSxZQUFZO1FBQ2QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFnRUQsWUFBcUIsUUFBbUIsRUFBVSxJQUFpQixFQUM5QyxNQUF5QixFQUN6QixRQUFrQjtRQUZsQixhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBYTtRQUM5QyxXQUFNLEdBQU4sTUFBTSxDQUFtQjtRQUN6QixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBaEU5Qix3QkFBbUIsR0FBRyxLQUFLLENBQUM7UUFFNUIsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUVsQixzQkFBaUIsR0FBRyxLQUFLLENBQUM7UUFFMUIsZUFBVSxHQUFHLEVBQUUsQ0FBQztRQUVoQiw4QkFBeUIsR0FBRyxnQkFBZ0IsQ0FBQztRQUU3QyxtQkFBYyxHQUFHLEVBQUUsQ0FBQztRQUVwQixtQkFBYyxHQUFHLFFBQVEsQ0FBQztRQUUxQixTQUFJLEdBQXVCLE9BQU8sQ0FBQztRQUVuQyxnQkFBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUVoRCxlQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBRW5ELFlBQU8sR0FBRyxNQUFNLENBQUM7UUFFaEIsZUFBVSxHQUFtQyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBRWhFLGVBQVUsR0FBeUIsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUV0RCxlQUFVLEdBQStCLElBQUksWUFBWSxFQUFFLENBQUM7UUFFNUQsZUFBVSxHQUFtQyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBd0JsRSxrQkFBYSxHQUFHLEVBQUUsQ0FBQztRQUVuQix5QkFBb0IsR0FBRyxFQUFFLENBQUM7UUFJMUIsaUJBQVksR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBT3hDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUUsWUFBWSxDQUFFLENBQUM7SUFDekQsQ0FBQztJQUVELElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDekIsQ0FBQztJQUVELElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDMUQsQ0FBQztJQUVELFFBQVE7UUFDTixrQkFBa0IsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQscUJBQXFCO1FBQ25CLElBQUssSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsRUFBRztZQUMzQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBRSxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLGFBQWEsQ0FBRSxDQUFDO1NBQzdFO0lBQ0gsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBRSxJQUFJLENBQUMsWUFBWSxDQUFFLENBQUM7UUFDMUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxxQkFBcUI7UUFDbkIsSUFBSyxJQUFJLENBQUMsZUFBZSxFQUFHO1lBQzFCLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2hFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFFLENBQUM7WUFDbEQsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNMO0lBQ0gsQ0FBQztJQUVELGlCQUFpQjtRQUNmLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDbkUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUUsSUFBSSxDQUFDLFlBQVksQ0FBRSxDQUFDO1lBQzFDLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDOUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNOLENBQUM7SUFFRCxxQkFBcUI7UUFDbkIsSUFBSyxJQUFJLENBQUMsU0FBUyxFQUFHO1lBQ3BCLElBQUssSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0I7Z0JBQ3hDLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLENBQUMsYUFBYSxLQUFLLFlBQVksQ0FBQyxNQUFNO2dCQUMzRSxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRTtnQkFDekUsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO2FBQ3RCO1lBQ0QsSUFBSyxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQjtnQkFDeEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLEtBQUssWUFBWSxDQUFDLE1BQU07Z0JBQzNFLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLENBQUMsZUFBZSxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFFO2dCQUNoRixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQzthQUM3QjtTQUNGO0lBQ0gsQ0FBQztJQUVELGFBQWE7UUFDWCxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBRSxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsQ0FBRSxDQUFDO1FBQzVFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBRSxDQUFDO1FBQ2pELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELG9CQUFvQjtRQUNsQixJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBRSxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLGVBQWUsQ0FBRSxDQUFDO1FBQ25GLElBQUksQ0FBQyxnQkFBZ0IsQ0FBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBRSxDQUFDO1FBQ2pELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELGdCQUFnQixDQUFFLFFBQVE7UUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBRSxRQUFRLENBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDcEMsSUFBSyxRQUFRLENBQUMsR0FBRyxDQUFDLFlBQVksZ0JBQWdCLEVBQUc7Z0JBQzlDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBRSxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFFLENBQUM7YUFDbEQ7aUJBQU07Z0JBQ0wsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO2FBQy9CO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQscUJBQXFCO1FBQ25CLElBQUssSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFHO1lBQ3ZDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFFLElBQUksQ0FBQyxVQUFVLENBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNqRDtJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUc7WUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUUsQ0FBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRyxFQUFFO2dCQUN0RCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBRSxJQUFJLENBQUUsQ0FBQztZQUMvQixDQUFDLENBQUUsQ0FBQztTQUNMO0lBQ0gsQ0FBQztJQUVELFlBQVk7UUFDVixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDO1FBQzFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFFLENBQUM7UUFDaEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQsb0JBQW9CO1FBQ2xCLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLGFBQWEsS0FBSyxZQUFZLENBQUMsTUFBTSxFQUFFO1lBQ2xHLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUNqRDtJQUNILENBQUM7SUFFRCxpQkFBaUI7UUFDZixNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFFLEdBQUcsQ0FBRSxDQUFDO1FBQzlFLEtBQU0sSUFBSSxtQkFBbUIsR0FBRyxDQUFDLEVBQUUsbUJBQW1CLEdBQUcsa0JBQWtCLENBQUMsTUFBTSxFQUFFLG1CQUFtQixFQUFFLEVBQUc7WUFDMUcsSUFBSyxDQUFDLGtCQUFrQixDQUFFLG1CQUFtQixDQUFFLENBQUMsT0FBTyxLQUFLLE9BQU87bUJBQzlELGtCQUFrQixDQUFFLG1CQUFtQixDQUFFLENBQUMsT0FBTyxLQUFLLFVBQVU7bUJBQ2hFLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO2dCQUNuRixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUUsa0JBQWtCLENBQUUsbUJBQW1CLENBQUUsQ0FBRSxFQUFHO2dCQUNuRSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBRSxrQkFBa0IsQ0FBRSxtQkFBbUIsQ0FBRSxDQUFFLENBQUM7YUFDdEU7U0FDRjtRQUNELElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO1FBQ3RDLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFRCxhQUFhLENBQUUsT0FBb0I7UUFDakMsS0FBTSxJQUFJLElBQUksR0FBRyxDQUFDLEVBQUUsSUFBSSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFHO1lBQzdELElBQUssT0FBTyxDQUFDLFVBQVUsQ0FBRSxJQUFJLENBQUUsQ0FBQyxTQUFTLEtBQUssU0FBUyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUUsSUFBSSxDQUFFLENBQUMsUUFBUSxLQUFLLFNBQVMsRUFBRztnQkFDN0csT0FBTyxJQUFJLENBQUM7YUFDYjtTQUNGO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsOEJBQThCO1FBQzVCLElBQUssSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUc7WUFDNUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUUsQ0FBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRyxFQUFFO2dCQUNoRCxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztZQUN4RSxDQUFDLENBQUUsQ0FBQztTQUNMO1FBRUQsSUFBSyxJQUFJLENBQUMsWUFBWSxFQUFHO1lBQ3ZCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBRSxDQUFDO1NBQzFFO1FBQ0QsSUFBSyxJQUFJLENBQUMsZ0JBQWdCLEVBQUc7WUFDM0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUUsQ0FBQztTQUM5RTtJQUNILENBQUM7SUFFRCw4QkFBOEI7UUFDNUIsVUFBVSxDQUFFLEdBQUcsRUFBRTtZQUNmLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUNwQyxDQUFDLEVBQUUsRUFBRSxDQUFFLENBQUM7SUFDVixDQUFDO0lBRUQsV0FBVyxDQUFFLE9BQW9CO1FBQy9CLElBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFHO1lBQ3ZCLGtCQUFrQixFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUUsVUFBVSxFQUFFLGtCQUFrQixDQUFFO2dCQUN0RixDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBRSxPQUFPLENBQUUsQ0FBQztTQUNqQztJQUNILENBQUM7SUFFRCxxQkFBcUIsQ0FBRSxPQUFvQixFQUFFLEtBQUssRUFBRSxLQUFLO1FBQ3ZELElBQUssS0FBSyxLQUFLLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFHO1lBQ2hDLElBQUksQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztTQUN0QztJQUNILENBQUM7SUFFRCwwQkFBMEI7UUFDeEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUUsQ0FBRSxPQUFvQixFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUcsRUFBRTtZQUNqRSxJQUFJLENBQUMsV0FBVyxDQUFFLE9BQU8sQ0FBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxxQkFBcUIsQ0FBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBRSxDQUFDO1FBQ3RELENBQUMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELHVCQUF1QjtRQUNyQixJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBRSxDQUFFLE9BQW9CLEVBQUcsRUFBRTtZQUNyRCxJQUFLLE9BQU8sQ0FBQyxRQUFRLEVBQUc7Z0JBQ3RCLElBQUksQ0FBQywwQkFBMEIsQ0FBRSxPQUFPLENBQUUsQ0FBQztnQkFDM0MsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBRSxPQUFPLENBQUMsUUFBUSxDQUFFLENBQUM7YUFDcEQ7UUFDSCxDQUFDLENBQUUsQ0FBQztJQUNOLENBQUM7SUFFRCwwQkFBMEIsQ0FBRSxPQUFvQjtRQUM5QyxJQUFLLElBQUksQ0FBQyxxQkFBcUIsQ0FBRSxPQUFPLENBQUUsRUFBRztZQUMzQyxNQUFNLElBQUksU0FBUyxDQUFFLHdEQUF3RCxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUUsQ0FBQztTQUNwRztJQUNILENBQUM7SUFFRCwwQkFBMEI7UUFDeEIsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLENBQUM7UUFDOUIsSUFBSyxJQUFJLENBQUMsR0FBRyxDQUFFLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsbUJBQW1CLEVBQUc7WUFDaEcsTUFBTSxJQUFJLFNBQVMsQ0FBRSxtQ0FBbUM7Z0JBQ3RELHVEQUF1RCxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUUsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUUsQ0FBRSxDQUFDO1NBQ3hHO0lBQ0gsQ0FBQztJQUVELHdCQUF3QjtRQUN0QixPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUUsa0JBQWtCLENBQUUsR0FBRyxDQUFDLENBQUM7SUFDckUsQ0FBQztJQUVELHFCQUFxQixDQUFFLE9BQW9CO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLE9BQU8sQ0FBRSxPQUFPLENBQUMsUUFBUSxDQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFRCxhQUFhO1FBQ1gsSUFBSSxLQUFLLENBQUM7UUFDVixLQUFLLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUUsVUFBVyxDQUFDLEVBQUUsQ0FBQztZQUM5QyxPQUFPLENBQUMsQ0FBQyxZQUFZLENBQUUsVUFBVSxDQUFFLEdBQUcsQ0FBQyxDQUFDLFlBQVksQ0FBRSxVQUFVLENBQUUsQ0FBQztRQUNyRSxDQUFDLENBQUUsQ0FBQztRQUNKLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO0lBQzdCLENBQUM7SUFFRCxjQUFjLENBQUUsTUFBcUI7UUFDbkMsSUFBSyxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxHQUFHLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRztZQUNyRCxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3ZCLE9BQU87U0FDUjtRQUNELFFBQVMsTUFBTSxDQUFDLElBQUksRUFBRztZQUNyQixLQUFLLFFBQVEsQ0FBQyxPQUFPO2dCQUNuQixNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDdkIsTUFBTTtZQUNSLEtBQUssUUFBUSxDQUFDLFNBQVM7Z0JBQ3JCLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDeEIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN0QixNQUFNO1lBQ1IsS0FBSyxRQUFRLENBQUMsVUFBVTtnQkFDdEIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNsQixNQUFNO1lBQ1IsS0FBSyxRQUFRLENBQUMsU0FBUztnQkFDckIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN0QixNQUFNO1lBQ1IsS0FBSyxRQUFRLENBQUMsR0FBRztnQkFDZixJQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxFQUFHO29CQUN4QixNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7aUJBQ3pCO2dCQUNELElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDdEIsTUFBTTtZQUNSLEtBQUssUUFBUSxDQUFDLEtBQUs7Z0JBQ2pCLElBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUc7b0JBQ3hCLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztpQkFDekI7Z0JBQ0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDN0IsTUFBTTtZQUNSLEtBQUssUUFBUSxDQUFDLFdBQVc7Z0JBQ3ZCLElBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUc7b0JBQ3hCLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztpQkFDekI7Z0JBQ0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDN0IsTUFBTTtTQUNUO0lBQ0gsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzVCLElBQUssSUFBSSxDQUFDLHFCQUFxQixFQUFFLEVBQUc7WUFDbEMsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFFLElBQUksQ0FBQyxZQUFZLENBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUN4RDtRQUNELElBQUssQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsRUFBRztZQUNsQyxNQUFNLGVBQWUsR0FBSSxRQUFRLENBQUMsYUFBNkIsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO1lBRTdFLEtBQU0sSUFBSSxPQUFPLEdBQUcsZUFBZSxFQUFFLE9BQU8sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRztnQkFDdEcsSUFBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBRSxJQUFJLENBQUMsYUFBYSxDQUFFLE9BQU8sQ0FBRSxDQUFFLEVBQUc7b0JBQzlELE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBRSxPQUFPLENBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztpQkFDOUM7YUFDRjtTQUNGO0lBQ0gsQ0FBQztJQUVELG9CQUFvQjtRQUNsQixPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBRSxDQUFDLENBQUUsQ0FBQyxZQUFZLENBQUUsVUFBVSxDQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUUsQ0FBQyxDQUFFLEtBQUssUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3RILENBQUM7SUFFRCxjQUFjLENBQUUsUUFBaUI7UUFDL0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUM1QixJQUFLLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxFQUFHO1lBQ2pDLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBRSxDQUFDLENBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUN4QztRQUNELElBQUssSUFBSSxDQUFDLFVBQVUsRUFBRSxFQUFHO1lBQ3ZCLE9BQU87U0FDUjtRQUNELE1BQU0sV0FBVyxHQUFJLFFBQVEsQ0FBQyxhQUE2QixDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDekUsS0FBTSxJQUFJLE9BQU8sR0FBRyxXQUFXLEVBQUUsT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxFQUFHO1lBQ2hGLElBQUssSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxRQUFRLEVBQUU7Z0JBQzdGLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDcEIsT0FBTzthQUNSO1lBQ0QsSUFBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBRSxJQUFJLENBQUMsYUFBYSxDQUFFLE9BQU8sQ0FBRSxDQUFFLEVBQUc7Z0JBQzlELE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBRSxPQUFPLENBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUM5QztTQUNGO0lBQ0gsQ0FBQztJQUVELFVBQVU7UUFDUixPQUFRLFFBQVEsQ0FBQyxhQUE2QixDQUFDLFNBQVMsS0FBSyxVQUFVLENBQUM7SUFDMUUsQ0FBQztJQUVELG9CQUFvQjtRQUNsQixPQUFRLFFBQVEsQ0FBQyxhQUE2QixDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQ2hGLENBQUM7SUFFRCxxQkFBcUI7UUFDbkIsT0FBUSxRQUFRLENBQUMsYUFBNkIsQ0FBQyxRQUFRLEtBQUssQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRCxpQkFBaUIsQ0FBRSxPQUFPO1FBQ3hCLElBQUssT0FBTyxLQUFLLFNBQVMsRUFBRztZQUMzQixPQUFPLEtBQUssQ0FBQztTQUNkO1FBQ0QsT0FBTyxPQUFPLENBQUMsUUFBUSxDQUFDO0lBQzFCLENBQUM7SUFFRCxlQUFlO1FBQ2IsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLENBQUMsS0FBSyxFQUFFO2dCQUM1RCxDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDbEMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsQ0FBQztJQUVELFVBQVU7UUFDUixJQUFLLElBQUksQ0FBQywyQkFBMkIsRUFBRSxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUc7WUFDN0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ3ZEO0lBQ0gsQ0FBQztJQUVELGNBQWM7UUFDWixJQUFLLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRztZQUM3RCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUMzRDtJQUNILENBQUM7SUFFRCxvQkFBb0I7UUFDbEIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUUsQ0FBRSxLQUFLLEVBQUcsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBRSxDQUFDO1FBQzdFLElBQUssYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUc7WUFDOUIsYUFBYSxDQUFFLENBQUMsQ0FBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQzVCO0lBQ0gsQ0FBQztJQUVELElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUUsQ0FBRSxJQUFJLEVBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBRSxDQUFDO0lBQ2pFLENBQUM7SUFFRCx1QkFBdUI7UUFDckIsSUFBSyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUc7WUFDeEIsT0FBTyxLQUFLLENBQUM7U0FDZDtRQUNELE9BQU8sUUFBUSxDQUFDLGFBQWEsS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUM7SUFDbEYsQ0FBQztJQUVELDJCQUEyQjtRQUN6QixJQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFHO1lBQzVCLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFDRCxPQUFPLFFBQVEsQ0FBQyxhQUFhLEtBQUssSUFBSSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUM7SUFDdEYsQ0FBQztJQUVELGdCQUFnQjtRQUNkLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbEMsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDOzt1SEF0Y1UsTUFBTTsyR0FBTixNQUFNLDZtQkF1REYsbUJBQW1CLGdIQU5FLE9BQU8sdUdBRVAsUUFBUSxtR0FFUixPQUFPLDBGQU4vQixNQUFNLHVXQ3hHcEIsMHFEQXdDQTs0RkRpQmEsTUFBTTtrQkFMbEIsU0FBUzsrQkFDRSxTQUFTO2lMQU9mLFlBQVk7c0JBRGYsS0FBSzt1QkFBRSxjQUFjO2dCQWFiLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLHlCQUF5QjtzQkFBakMsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsSUFBSTtzQkFBWixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxPQUFPO3NCQUFmLEtBQUs7Z0JBRUksVUFBVTtzQkFBbkIsTUFBTTtnQkFFRyxVQUFVO3NCQUFuQixNQUFNO2dCQUVHLFVBQVU7c0JBQW5CLE1BQU07Z0JBRUcsVUFBVTtzQkFBbkIsTUFBTTtnQkFFZSxTQUFTO3NCQUE5QixLQUFLO3VCQUFFLFdBQVc7Z0JBRTBCLElBQUk7c0JBQWhELFNBQVM7dUJBQUUsTUFBTSxFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQztnQkFFcUMsU0FBUztzQkFBL0UsZUFBZTt1QkFBRSxVQUFVLENBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFFLEVBQUUsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFO2dCQUVJLFVBQVU7c0JBQWpGLGVBQWU7dUJBQUUsVUFBVSxDQUFFLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRTtnQkFFRSxNQUFNO3NCQUE1RSxlQUFlO3VCQUFFLFVBQVUsQ0FBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUU7Z0JBRWQsZUFBZTtzQkFBcEUsWUFBWTt1QkFBRSxtQkFBbUIsRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUM7Z0JBRUgsWUFBWTtzQkFBMUQsU0FBUzt1QkFBRSxjQUFjLEVBQUUsRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFDO2dCQUVRLGdCQUFnQjtzQkFBbEUsU0FBUzt1QkFBRSxrQkFBa0IsRUFBRSxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUM7Z0JBRU4sT0FBTztzQkFBL0MsU0FBUzt1QkFBRSxTQUFTLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiBNSVQgTGljZW5zZVxuXG4gQ29weXJpZ2h0IChjKSAyMDE5IFRlbWFpbmZvIFNvZnR3YXJlXG5cbiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbiBhbGxcbiBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRVxuIFNPRlRXQVJFLlxuICovXG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRJbml0LFxuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkLFxuICBDb250ZW50Q2hpbGRyZW4sXG4gIEV2ZW50RW1pdHRlcixcbiAgZm9yd2FyZFJlZixcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBRdWVyeUxpc3QsXG4gIFJlbmRlcmVyMixcbiAgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7S2V5RXZlbnR9IGZyb20gJy4uL2NvcmUvZW51bXMva2V5LWV2ZW50cyc7XG5pbXBvcnQge0kxOG5TZXJ2aWNlfSBmcm9tICcuLi9pMThuL2kxOG4uc2VydmljZSc7XG5pbXBvcnQge1RsSW5wdXR9IGZyb20gJy4uL2lucHV0L2lucHV0JztcbmltcG9ydCB7VW50eXBlZEZvcm1Hcm91cCwgTmdGb3JtLCBOZ01vZGVsfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge1RsQnV0dG9ufSBmcm9tICcuLi9idXR0b24vYnV0dG9uJztcbmltcG9ydCB7Rm9ybVN1Ym1pdERpcmVjdGl2ZX0gZnJvbSAnLi9mb3JtLXN1Ym1pdC5kaXJlY3RpdmUnO1xuaW1wb3J0IHtNb2RhbFNlcnZpY2V9IGZyb20gJy4uL21vZGFsL3NlcnZpY2VzL21vZGFsLnNlcnZpY2UnO1xuaW1wb3J0IHtBY3Rpb25zTW9kYWx9IGZyb20gJy4uL2NvcmUvZW51bXMvYWN0aW9ucy1tb2RhbCc7XG5pbXBvcnQge1N1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5cbmxldCBjb21wb25lbnRGb3JtSW5kZXg7XG5cbkBDb21wb25lbnQoIHtcbiAgc2VsZWN0b3I6ICd0bC1mb3JtJyxcbiAgdGVtcGxhdGVVcmw6ICcuLi9mb3JtL2Zvcm0uaHRtbCcsXG4gIHN0eWxlVXJsczogWyAnLi4vZm9ybS9mb3JtLnNjc3MnIF0sXG59IClcbmV4cG9ydCBjbGFzcyBUbEZvcm0gaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG5cbiAgQElucHV0KCAnaW5pdGlhbEZvY3VzJyApXG4gIHNldCBpbml0aWFsRm9jdXMoIHZhbHVlICkge1xuICAgIGlmICggdmFsdWUgKSB7XG4gICAgICB0aGlzLl9pbml0aWFsRm9jdXMgPSB2YWx1ZTtcbiAgICAgIHRoaXMuY2hhbmdlLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHRoaXMuc2V0SW5pdGlhbEZvY3VzKCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGluaXRpYWxGb2N1cygpIHtcbiAgICByZXR1cm4gdGhpcy5faW5pdGlhbEZvY3VzO1xuICB9XG5cbiAgQElucHV0KCkgc2hvd0NvbmZpcm1PbkNoYW5nZSA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIGlzTG9hZGluZyA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIHN1Ym1pdE9uTGFzdEZpZWxkID0gZmFsc2U7XG5cbiAgQElucHV0KCkgcHJpbWFyeUtleSA9ICcnO1xuXG4gIEBJbnB1dCgpIG1lc3NhZ2VEaWFsb2dDb25maXJtYXRpb24gPSAnQXJlIHlvdSBzdXJlID8nO1xuXG4gIEBJbnB1dCgpIHN1Ym1pdFNob3J0Y3V0ID0gJyc7XG5cbiAgQElucHV0KCkgY2FuY2VsU2hvcnRjdXQgPSAnZXNjYXBlJztcblxuICBASW5wdXQoKSBtb2RlOiAnaW5saW5lJyB8ICdtb2RhbCcgPSAnbW9kYWwnO1xuXG4gIEBJbnB1dCgpIHRleHRDb25maXJtID0gdGhpcy5pMThuLmdldExvY2FsZSgpLkZvcm0udGV4dE9rO1xuXG4gIEBJbnB1dCgpIHRleHRDYW5jZWwgPSB0aGlzLmkxOG4uZ2V0TG9jYWxlKCkuRm9ybS50ZXh0Q2FuY2VsO1xuXG4gIEBJbnB1dCgpIHBhZGRpbmcgPSAnMTBweCc7XG5cbiAgQE91dHB1dCgpIGZvcm1Mb2FkZWQ6IEV2ZW50RW1pdHRlcjxVbnR5cGVkRm9ybUdyb3VwPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgc3VibWl0Rm9ybTogRXZlbnRFbWl0dGVyPE5nRm9ybT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIGFjdGlvbkZvcm06IEV2ZW50RW1pdHRlcjxBY3Rpb25zTW9kYWw+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKSBjaGFuZ2VGb3JtOiBFdmVudEVtaXR0ZXI8VW50eXBlZEZvcm1Hcm91cD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQElucHV0KCAnZm9ybUdyb3VwJyApIGZvcm1Hcm91cDogVW50eXBlZEZvcm1Hcm91cDtcblxuICBAVmlld0NoaWxkKCBOZ0Zvcm0sIHtzdGF0aWM6IHRydWV9ICApIHB1YmxpYyBmb3JtOiBOZ0Zvcm07XG5cbiAgQENvbnRlbnRDaGlsZHJlbiggZm9yd2FyZFJlZiggKCkgPT4gVGxJbnB1dCApLCB7IGRlc2NlbmRhbnRzOiB0cnVlIH0gKSBpbnB1dExpc3Q6IFF1ZXJ5TGlzdDxUbElucHV0PjtcblxuICBAQ29udGVudENoaWxkcmVuKCBmb3J3YXJkUmVmKCAoKSA9PiBUbEJ1dHRvbiApLCB7IGRlc2NlbmRhbnRzOiB0cnVlIH0gKSBidXR0b25MaXN0OiBRdWVyeUxpc3Q8VGxCdXR0b24+O1xuXG4gIEBDb250ZW50Q2hpbGRyZW4oIGZvcndhcmRSZWYoICgpID0+IE5nTW9kZWwgKSwgeyBkZXNjZW5kYW50czogdHJ1ZSB9ICkgbW9kZWxzOiBRdWVyeUxpc3Q8TmdNb2RlbD47XG5cbiAgQENvbnRlbnRDaGlsZCggRm9ybVN1Ym1pdERpcmVjdGl2ZSwge3N0YXRpYzogdHJ1ZX0gICkgc3VibWl0RGlyZWN0aXZlOiBGb3JtU3VibWl0RGlyZWN0aXZlO1xuXG4gIEBWaWV3Q2hpbGQoICdidXR0b25Gb3JtT2snLCB7c3RhdGljOiBmYWxzZX0gICkgYnV0dG9uRm9ybU9rO1xuXG4gIEBWaWV3Q2hpbGQoICdidXR0b25Gb3JtQ2FuY2VsJywge3N0YXRpYzogZmFsc2V9ICApIGJ1dHRvbkZvcm1DYW5jZWw7XG5cbiAgQFZpZXdDaGlsZCggJ2NvbnRlbnQnLCB7c3RhdGljOiB0cnVlfSAgKSBjb250ZW50O1xuXG4gIHB1YmxpYyBmb3JtUmVzdWx0O1xuXG4gIHByaXZhdGUgbGFzdFRhYkluZGV4OiBudW1iZXI7XG5cbiAgcHJpdmF0ZSBmb2N1c0VsZW1lbnRzID0gW107XG5cbiAgcHJpdmF0ZSBlbGVtZW50c1dpdGhUYWJJbmRleCA9IFtdO1xuXG4gIHByaXZhdGUgX2luaXRpYWxGb2N1cztcblxuICBwcml2YXRlIHN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBwcml2YXRlIG1vZGFsSW5zdGFuY2U7XG5cbiAgY29uc3RydWN0b3IoIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMiwgcHJpdmF0ZSBpMThuOiBJMThuU2VydmljZSxcbiAgICAgICAgICAgICAgIHByaXZhdGUgY2hhbmdlOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgICAgICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yICkge1xuICAgIHRoaXMubW9kYWxJbnN0YW5jZSA9IHRoaXMuaW5qZWN0b3IuZ2V0KCBNb2RhbFNlcnZpY2UgKTtcbiAgfVxuXG4gIGdldCB2YWxpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5mb3JtLnZhbGlkO1xuICB9XG5cbiAgZ2V0IGZvcm1JbnN0YW5jZSgpIHtcbiAgICByZXR1cm4gdGhpcy5mb3JtR3JvdXAgPyB0aGlzLmZvcm1Hcm91cCA6IHRoaXMuZm9ybS5mb3JtO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgY29tcG9uZW50Rm9ybUluZGV4ID0gLTE7XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XG4gICAgdGhpcy5oYW5kbGVGb3JtR3JvdXBWYWx1ZXMoKTtcbiAgICB0aGlzLmhhbmRsZVNtYXJ0Rm9ybUFjdGlvbigpO1xuICAgIHRoaXMuc2V0UHJpbWFyeUtleURpc2FibGVkKCk7XG4gICAgdGhpcy5hZGRDb250cm9scygpO1xuICB9XG5cbiAgaGFuZGxlU21hcnRGb3JtQWN0aW9uKCkge1xuICAgIGlmICggdGhpcy5tb2RhbEluc3RhbmNlLm1vZGFsQ29uZmlndXJhdGlvbiApIHtcbiAgICAgIHRoaXMuYWN0aW9uRm9ybS5lbWl0KCB0aGlzLm1vZGFsSW5zdGFuY2UubW9kYWxDb25maWd1cmF0aW9uLmV4ZWN1dGVBY3Rpb24gKT