@angular-material-extensions/google-maps-autocomplete
Version:
Autocomplete input component and directive for google-maps built with angular and material design
228 lines • 47.6 kB
JavaScript
import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
import { NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { parseGermanAddress } from '../../helpers/parser';
import { Appearance } from '../mat-google-maps-autocomplete.component';
import { InputAnimations } from '../../animations';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/common";
import * as i3 from "@angular/flex-layout/flex";
import * as i4 from "@angular/material/input";
import * as i5 from "@angular/material/form-field";
import * as i6 from "@angular/material/icon";
import * as i7 from "../../directives/mat-google-maps-autocomplete.directive";
export class MatSearchGoogleMapsAutocompleteComponent {
formBuilder;
constructor(formBuilder) {
this.formBuilder = formBuilder;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
searchBarAppearance;
appearance = Appearance.STANDARD;
searchAddressLabel = 'Search Address';
streetNameLabel = 'Street';
streetNumberLabel = 'Nr.';
postalCodeLabel = 'PLZ';
localityLabel = 'Locality';
vicinityLabel = 'Vicinity';
showVicinity;
country;
placeIdOnly;
strictBounds;
types;
// types: string[] = ['address'];
type;
readonly;
disableSearch;
_value;
onGermanAddressMapped = new EventEmitter();
germanAddress;
addressFormGroup;
firstInit = true;
// Private
_unsubscribeAll;
propagateChange = (_) => {
};
get value() {
return this._value;
}
set value(value) {
this._value = value;
this.propagateChange(this.value);
}
ngOnInit() {
this.createAddressFormGroup();
this.enableCustomInput();
}
createAddressFormGroup() {
this.addressFormGroup = this.formBuilder.group({
streetName: [this.value && this.value.streetName ? this.value.streetName : null, Validators.required],
streetNumber: [this.value && this.value.streetNumber ? this.value.streetNumber : null, Validators.required],
postalCode: [this.value && this.value.postalCode ? this.value.postalCode : null, Validators.required],
vicinity: [this.value && this.value.vicinity ? this.value.vicinity : null],
locality: this.formBuilder.group({
long: [this.value && this.value.locality && this.value.locality.long ? this.value.locality.long : null, Validators.required],
}),
});
}
enableCustomInput() {
this.addressFormGroup
.get('streetName')
.valueChanges
.pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll))
.subscribe(streetName => {
!this.value ? this.value = { streetName } : this.value.streetName = streetName;
this.value.displayAddress = this.parseDisplayAddress();
this.propagateChange(this.value);
});
this.addressFormGroup
.get('streetNumber')
.valueChanges
.pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll))
.subscribe(streetNumber => {
!this.value ? this.value = { streetNumber } : this.value.streetNumber = streetNumber;
this.value.displayAddress = this.parseDisplayAddress();
this.propagateChange(this.value);
});
this.addressFormGroup
.get('postalCode')
.valueChanges
.pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll))
.subscribe(postalCode => {
!this.value ? this.value = { postalCode } : this.value.postalCode = postalCode;
this.value.displayAddress = this.parseDisplayAddress();
this.propagateChange(this.value);
});
this.addressFormGroup
.get('vicinity')
.valueChanges
.pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll))
.subscribe(vicinity => {
!this.value ? this.value = { vicinity } : this.value.vicinity = vicinity;
this.value.displayAddress = this.parseDisplayAddress();
this.propagateChange(this.value);
});
this.addressFormGroup
.get('locality')
.valueChanges
.pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll))
.subscribe(locality => {
!this.value ? this.value = { locality } : this.value.locality = locality;
this.value.displayAddress = this.parseDisplayAddress();
this.propagateChange(this.value);
});
}
parseDisplayAddress() {
return `${this.value?.streetName ? this.value?.streetName : ''} ${this.value?.streetNumber ? this.value?.streetNumber : ''}${this.value?.postalCode || this.value?.locality?.long ? ', ' : ''}${this.value?.postalCode ? this.value?.postalCode : ''} ${this.value?.locality?.long ? this.value?.locality?.long : ''}`;
}
syncAutoComplete($event) {
if (this.germanAddress) {
this.addressFormGroup.reset();
}
const germanAddress = parseGermanAddress($event);
this.germanAddress = germanAddress;
if (germanAddress.vicinity) {
this.addressFormGroup.get('vicinity').patchValue(germanAddress.vicinity, { emitEvent: false, onlySelf: true });
}
if (germanAddress.streetName) {
this.addressFormGroup.get('streetName').patchValue(germanAddress.streetName, { emitEvent: false, onlySelf: true });
}
if (germanAddress.streetNumber) {
this.addressFormGroup.get('streetNumber').patchValue(germanAddress.streetNumber.toString(), {
emitEvent: false,
onlySelf: true
});
}
if (germanAddress.postalCode) {
this.addressFormGroup.get('postalCode').patchValue(germanAddress.postalCode, { emitEvent: false, onlySelf: true });
}
if (germanAddress.locality && germanAddress.locality.long) {
this.addressFormGroup.get('locality.long').patchValue(germanAddress.locality.long, {
emitEvent: false,
onlySelf: true
});
}
this.value = germanAddress;
this.onGermanAddressMapped.emit(germanAddress);
}
writeValue(obj) {
let shouldRecreateFG = false;
if (obj) {
if (!this.value && this.firstInit) {
shouldRecreateFG = true;
}
this.value = obj;
if (shouldRecreateFG) {
this.createAddressFormGroup();
this.firstInit = false;
}
}
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched(fn) {
}
setDisabledState(isDisabled) {
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: MatSearchGoogleMapsAutocompleteComponent, deps: [{ token: i1.UntypedFormBuilder }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.2", type: MatSearchGoogleMapsAutocompleteComponent, selector: "mat-search-google-maps-autocomplete", inputs: { searchBarAppearance: "searchBarAppearance", appearance: "appearance", searchAddressLabel: "searchAddressLabel", streetNameLabel: "streetNameLabel", streetNumberLabel: "streetNumberLabel", postalCodeLabel: "postalCodeLabel", localityLabel: "localityLabel", vicinityLabel: "vicinityLabel", showVicinity: "showVicinity", country: "country", placeIdOnly: "placeIdOnly", strictBounds: "strictBounds", types: "types", type: "type", readonly: "readonly", disableSearch: "disableSearch", _value: "_value", value: "value" }, outputs: { onGermanAddressMapped: "onGermanAddressMapped" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MatSearchGoogleMapsAutocompleteComponent),
multi: true
}
], ngImport: i0, template: "<div fxLayout=\"column\">\n <div *ngIf=\"!disableSearch\" fxFlex=\"100\">\n <!--search address-->\n <mat-form-field fxFlex=\"auto\" [appearance]=\"searchBarAppearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{searchAddressLabel}}</mat-label>\n <input\n (onAutocompleteSelected)=\"syncAutoComplete($event)\"\n [country]=\"country\"\n [placeIdOnly]=\"placeIdOnly\"\n [strictBounds]=\"strictBounds\"\n [types]=\"types\"\n [type]=\"type\"\n matGoogleMapsAutocomplete\n matInput\n required\n />\n <mat-icon color=\"primary\" matSuffix>search</mat-icon>\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n </div>\n\n <form [formGroup]=\"addressFormGroup\" fxFlex fxLayoutGap=\"10px\">\n <div fxLayout=\"row\" fxLayoutGap=\"10px\">\n <mat-form-field fxFlex=\"80\"\n [appearance]=\"appearance\"\n [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{streetNameLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"streetName\"\n matInput\n required\n />\n <!-- <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>-->\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n <mat-form-field fxFlex=\"20\" [appearance]=\"appearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{streetNumberLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"streetNumber\"\n matInput\n required\n />\n <!-- <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>-->\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n </div>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\">\n <mat-form-field fxFlex=\"20\" [appearance]=\"appearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{postalCodeLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"postalCode\"\n type=\"number\"\n matInput\n required\n />\n <!-- <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>-->\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n <mat-form-field *ngIf=\"showVicinity\" fxFlex=\"auto\"\n [appearance]=\"appearance\"\n [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{vicinityLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n matInput\n formControlName=\"vicinity\"\n />\n </mat-form-field>\n <div formGroupName=\"locality\" fxFlex=\"auto\">\n <mat-form-field fxFlex=\"auto\" [appearance]=\"appearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{localityLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"long\"\n matInput\n required\n />\n <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n </div>\n </div>\n </form>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i3.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i3.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i3.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.MatGoogleMapsAutocompleteDirective, selector: "[matGoogleMapsAutocomplete]", inputs: ["address", "country", "placeIdOnly", "strictBounds", "types", "type", "autoCompleteOptions", "value"], outputs: ["onChange", "onAutocompleteSelected", "onGermanAddressMapped", "onLocationSelected"], exportAs: ["matGoogleMapsAutocomplete"] }], animations: InputAnimations });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: MatSearchGoogleMapsAutocompleteComponent, decorators: [{
type: Component,
args: [{ selector: 'mat-search-google-maps-autocomplete', animations: InputAnimations, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MatSearchGoogleMapsAutocompleteComponent),
multi: true
}
], template: "<div fxLayout=\"column\">\n <div *ngIf=\"!disableSearch\" fxFlex=\"100\">\n <!--search address-->\n <mat-form-field fxFlex=\"auto\" [appearance]=\"searchBarAppearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{searchAddressLabel}}</mat-label>\n <input\n (onAutocompleteSelected)=\"syncAutoComplete($event)\"\n [country]=\"country\"\n [placeIdOnly]=\"placeIdOnly\"\n [strictBounds]=\"strictBounds\"\n [types]=\"types\"\n [type]=\"type\"\n matGoogleMapsAutocomplete\n matInput\n required\n />\n <mat-icon color=\"primary\" matSuffix>search</mat-icon>\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n </div>\n\n <form [formGroup]=\"addressFormGroup\" fxFlex fxLayoutGap=\"10px\">\n <div fxLayout=\"row\" fxLayoutGap=\"10px\">\n <mat-form-field fxFlex=\"80\"\n [appearance]=\"appearance\"\n [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{streetNameLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"streetName\"\n matInput\n required\n />\n <!-- <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>-->\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n <mat-form-field fxFlex=\"20\" [appearance]=\"appearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{streetNumberLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"streetNumber\"\n matInput\n required\n />\n <!-- <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>-->\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n </div>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\">\n <mat-form-field fxFlex=\"20\" [appearance]=\"appearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{postalCodeLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"postalCode\"\n type=\"number\"\n matInput\n required\n />\n <!-- <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>-->\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n <mat-form-field *ngIf=\"showVicinity\" fxFlex=\"auto\"\n [appearance]=\"appearance\"\n [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{vicinityLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n matInput\n formControlName=\"vicinity\"\n />\n </mat-form-field>\n <div formGroupName=\"locality\" fxFlex=\"auto\">\n <mat-form-field fxFlex=\"auto\" [appearance]=\"appearance\" [@animate]=\"{ value: '*', params: { y: '100%' } }\">\n <mat-label>{{localityLabel}}</mat-label>\n <input\n [readonly]=\"readonly\"\n formControlName=\"long\"\n matInput\n required\n />\n <mat-icon color=\"primary\" matSuffix>add_location</mat-icon>\n <!-- <mat-error>{{ 'msa.contactData.currentAddress.error' | translate }}</mat-error>-->\n </mat-form-field>\n </div>\n </div>\n </form>\n</div>\n" }]
}], ctorParameters: function () { return [{ type: i1.UntypedFormBuilder }]; }, propDecorators: { searchBarAppearance: [{
type: Input
}], appearance: [{
type: Input
}], searchAddressLabel: [{
type: Input
}], streetNameLabel: [{
type: Input
}], streetNumberLabel: [{
type: Input
}], postalCodeLabel: [{
type: Input
}], localityLabel: [{
type: Input
}], vicinityLabel: [{
type: Input
}], showVicinity: [{
type: Input
}], country: [{
type: Input
}], placeIdOnly: [{
type: Input
}], strictBounds: [{
type: Input
}], types: [{
type: Input
}], type: [{
type: Input
}], readonly: [{
type: Input
}], disableSearch: [{
type: Input
}], _value: [{
type: Input
}], onGermanAddressMapped: [{
type: Output
}], value: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0LXNlYXJjaC1nb29nbGUtbWFwcy1hdXRvY29tcGxldGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1tYXRlcmlhbC1leHRlbnNpb25zL2dvb2dsZS1tYXBzLWF1dG9jb21wbGV0ZS9zcmMvbGliL2NvbXBvbmVudC9tYXQtc2VhcmNoLWdvb2dsZS1tYXBzLWF1dG9jb21wbGV0ZS9tYXQtc2VhcmNoLWdvb2dsZS1tYXBzLWF1dG9jb21wbGV0ZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLW1hdGVyaWFsLWV4dGVuc2lvbnMvZ29vZ2xlLW1hcHMtYXV0b2NvbXBsZXRlL3NyYy9saWIvY29tcG9uZW50L21hdC1zZWFyY2gtZ29vZ2xlLW1hcHMtYXV0b2NvbXBsZXRlL21hdC1zZWFyY2gtZ29vZ2xlLW1hcHMtYXV0b2NvbXBsZXRlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3pGLE9BQU8sRUFFTCxpQkFBaUIsRUFHakIsVUFBVSxFQUNYLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFFeEQsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLDJDQUEyQyxDQUFDO0FBQ3JFLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQUMsWUFBWSxFQUFFLG9CQUFvQixFQUFFLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzdFLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7OztBQWU3QixNQUFNLE9BQU8sd0NBQXdDO0lBRS9CO0lBQXBCLFlBQW9CLFdBQStCO1FBQS9CLGdCQUFXLEdBQVgsV0FBVyxDQUFvQjtRQUNqRCwyQkFBMkI7UUFDM0IsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBQ3ZDLENBQUM7SUFHRCxtQkFBbUIsQ0FBc0I7SUFHekMsVUFBVSxHQUF3QixVQUFVLENBQUMsUUFBUSxDQUFDO0lBR3RELGtCQUFrQixHQUFHLGdCQUFnQixDQUFDO0lBR3RDLGVBQWUsR0FBRyxRQUFRLENBQUM7SUFHM0IsaUJBQWlCLEdBQUcsS0FBSyxDQUFDO0lBRzFCLGVBQWUsR0FBRyxLQUFLLENBQUM7SUFHeEIsYUFBYSxHQUFHLFVBQVUsQ0FBQztJQUczQixhQUFhLEdBQUcsVUFBVSxDQUFDO0lBRzNCLFlBQVksQ0FBVTtJQUd0QixPQUFPLENBQW9CO0lBRzNCLFdBQVcsQ0FBVztJQUd0QixZQUFZLENBQVc7SUFHdkIsS0FBSyxDQUFZO0lBQ2pCLGlDQUFpQztJQUdqQyxJQUFJLENBQVU7SUFHZCxRQUFRLENBQVU7SUFHbEIsYUFBYSxDQUFVO0lBRU4sTUFBTSxDQUFnQjtJQUd2QyxxQkFBcUIsR0FBZ0MsSUFBSSxZQUFZLEVBQWlCLENBQUM7SUFFdkYsYUFBYSxDQUFnQjtJQUM3QixnQkFBZ0IsQ0FBbUI7SUFFbkMsU0FBUyxHQUFHLElBQUksQ0FBQztJQUVqQixVQUFVO0lBQ0YsZUFBZSxDQUFlO0lBRXRDLGVBQWUsR0FBRyxDQUFDLENBQU0sRUFBRSxFQUFFO0lBQzdCLENBQUMsQ0FBQztJQUdGLElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQsSUFDSSxLQUFLLENBQUMsS0FBb0I7UUFDNUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsc0JBQXNCO1FBQ3BCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQztZQUM3QyxVQUFVLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUM7WUFDckcsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDO1lBQzNHLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQztZQUNyRyxRQUFRLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzFFLFFBQVEsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQztnQkFDL0IsSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElB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bml0LCBPdXRwdXR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQ29udHJvbFZhbHVlQWNjZXNzb3IsXG4gIE5HX1ZBTFVFX0FDQ0VTU09SLFxuICBVbnR5cGVkRm9ybUJ1aWxkZXIsXG4gIFVudHlwZWRGb3JtR3JvdXAsXG4gIFZhbGlkYXRvcnNcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQge3BhcnNlR2VybWFuQWRkcmVzc30gZnJvbSAnLi4vLi4vaGVscGVycy9wYXJzZXInO1xuaW1wb3J0IHtHZXJtYW5BZGRyZXNzfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzJztcbmltcG9ydCB7QXBwZWFyYW5jZX0gZnJvbSAnLi4vbWF0LWdvb2dsZS1tYXBzLWF1dG9jb21wbGV0ZS5jb21wb25lbnQnO1xuaW1wb3J0IHtJbnB1dEFuaW1hdGlvbnN9IGZyb20gJy4uLy4uL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHtkZWJvdW5jZVRpbWUsIGRpc3RpbmN0VW50aWxDaGFuZ2VkLCB0YWtlVW50aWx9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7U3ViamVjdH0gZnJvbSAncnhqcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ21hdC1zZWFyY2gtZ29vZ2xlLW1hcHMtYXV0b2NvbXBsZXRlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL21hdC1zZWFyY2gtZ29vZ2xlLW1hcHMtYXV0b2NvbXBsZXRlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vbWF0LXNlYXJjaC1nb29nbGUtbWFwcy1hdXRvY29tcGxldGUuY29tcG9uZW50LnNjc3MnXSxcbiAgYW5pbWF0aW9uczogSW5wdXRBbmltYXRpb25zLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE1hdFNlYXJjaEdvb2dsZU1hcHNBdXRvY29tcGxldGVDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTWF0U2VhcmNoR29vZ2xlTWFwc0F1dG9jb21wbGV0ZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZm9ybUJ1aWxkZXI6IFVudHlwZWRGb3JtQnVpbGRlcikge1xuICAgIC8vIFNldCB0aGUgcHJpdmF0ZSBkZWZhdWx0c1xuICAgIHRoaXMuX3Vuc3Vic2NyaWJlQWxsID0gbmV3IFN1YmplY3QoKTtcbiAgfVxuXG4gIEBJbnB1dCgpXG4gIHNlYXJjaEJhckFwcGVhcmFuY2U6IHN0cmluZyB8IEFwcGVhcmFuY2U7XG5cbiAgQElucHV0KClcbiAgYXBwZWFyYW5jZTogc3RyaW5nIHwgQXBwZWFyYW5jZSA9IEFwcGVhcmFuY2UuU1RBTkRBUkQ7XG5cbiAgQElucHV0KClcbiAgc2VhcmNoQWRkcmVzc0xhYmVsID0gJ1NlYXJjaCBBZGRyZXNzJztcblxuICBASW5wdXQoKVxuICBzdHJlZXROYW1lTGFiZWwgPSAnU3RyZWV0JztcblxuICBASW5wdXQoKVxuICBzdHJlZXROdW1iZXJMYWJlbCA9ICdOci4nO1xuXG4gIEBJbnB1dCgpXG4gIHBvc3RhbENvZGVMYWJlbCA9ICdQTFonO1xuXG4gIEBJbnB1dCgpXG4gIGxvY2FsaXR5TGFiZWwgPSAnTG9jYWxpdHknO1xuXG4gIEBJbnB1dCgpXG4gIHZpY2luaXR5TGFiZWwgPSAnVmljaW5pdHknO1xuXG4gIEBJbnB1dCgpXG4gIHNob3dWaWNpbml0eTogYm9vbGVhbjtcblxuICBASW5wdXQoKVxuICBjb3VudHJ5OiBzdHJpbmcgfCBzdHJpbmdbXTtcblxuICBASW5wdXQoKVxuICBwbGFjZUlkT25seT86IGJvb2xlYW47XG5cbiAgQElucHV0KClcbiAgc3RyaWN0Qm91bmRzPzogYm9vbGVhbjtcblxuICBASW5wdXQoKVxuICB0eXBlcz86IHN0cmluZ1tdO1xuICAvLyB0eXBlczogc3RyaW5nW10gPSBbJ2FkZHJlc3MnXTtcblxuICBASW5wdXQoKVxuICB0eXBlPzogc3RyaW5nO1xuXG4gIEBJbnB1dCgpXG4gIHJlYWRvbmx5OiBib29sZWFuO1xuXG4gIEBJbnB1dCgpXG4gIGRpc2FibGVTZWFyY2g6IGJvb2xlYW47XG5cbiAgQElucHV0KCkgcHJpdmF0ZSBfdmFsdWU6IEdlcm1hbkFkZHJlc3M7XG5cbiAgQE91dHB1dCgpXG4gIG9uR2VybWFuQWRkcmVzc01hcHBlZDogRXZlbnRFbWl0dGVyPEdlcm1hbkFkZHJlc3M+ID0gbmV3IEV2ZW50RW1pdHRlcjxHZXJtYW5BZGRyZXNzPigpO1xuXG4gIGdlcm1hbkFkZHJlc3M6IEdlcm1hbkFkZHJlc3M7XG4gIGFkZHJlc3NGb3JtR3JvdXA6IFVudHlwZWRGb3JtR3JvdXA7XG5cbiAgZmlyc3RJbml0ID0gdHJ1ZTtcblxuICAvLyBQcml2YXRlXG4gIHByaXZhdGUgX3Vuc3Vic2NyaWJlQWxsOiBTdWJqZWN0PGFueT47XG5cbiAgcHJvcGFnYXRlQ2hhbmdlID0gKF86IGFueSkgPT4ge1xuICB9O1xuXG5cbiAgZ2V0IHZhbHVlKCk6IEdlcm1hbkFkZHJlc3Mge1xuICAgIHJldHVybiB0aGlzLl92YWx1ZTtcbiAgfVxuXG4gIEBJbnB1dCgpXG4gIHNldCB2YWx1ZSh2YWx1ZTogR2VybWFuQWRkcmVzcykge1xuICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy52YWx1ZSk7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmNyZWF0ZUFkZHJlc3NGb3JtR3JvdXAoKTtcbiAgICB0aGlzLmVuYWJsZUN1c3RvbUlucHV0KCk7XG4gIH1cblxuICBjcmVhdGVBZGRyZXNzRm9ybUdyb3VwKCk6IHZvaWQge1xuICAgIHRoaXMuYWRkcmVzc0Zvcm1Hcm91cCA9IHRoaXMuZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgc3RyZWV0TmFtZTogW3RoaXMudmFsdWUgJiYgdGhpcy52YWx1ZS5zdHJlZXROYW1lID8gdGhpcy52YWx1ZS5zdHJlZXROYW1lIDogbnVsbCwgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICBzdHJlZXROdW1iZXI6IFt0aGlzLnZhbHVlICYmIHRoaXMudmFsdWUuc3RyZWV0TnVtYmVyID8gdGhpcy52YWx1ZS5zdHJlZXROdW1iZXIgOiBudWxsLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgIHBvc3RhbENvZGU6IFt0aGlzLnZhbHVlICYmIHRoaXMudmFsdWUucG9zdGFsQ29kZSA/IHRoaXMudmFsdWUucG9zdGFsQ29kZSA6IG51bGwsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgdmljaW5pdHk6IFt0aGlzLnZhbHVlICYmIHRoaXMudmFsdWUudmljaW5pdHkgPyB0aGlzLnZhbHVlLnZpY2luaXR5IDogbnVsbF0sXG4gICAgICBsb2NhbGl0eTogdGhpcy5mb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICAgIGxvbmc6IFt0aGlzLnZhbHVlICYmIHRoaXMudmFsdWUubG9jYWxpdHkgJiYgdGhpcy52YWx1ZS5sb2NhbGl0eS5sb25nID8gdGhpcy52YWx1ZS5sb2NhbGl0eS5sb25nIDogbnVsbCwgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIGVuYWJsZUN1c3RvbUlucHV0KCkge1xuICAgIHRoaXMuYWRkcmVzc0Zvcm1Hcm91cFxuICAgICAgLmdldCgnc3RyZWV0TmFtZScpXG4gICAgICAudmFsdWVDaGFuZ2VzXG4gICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLCBkZWJvdW5jZVRpbWUoNDAwKSwgdGFrZVVudGlsKHRoaXMuX3Vuc3Vic2NyaWJlQWxsKSlcbiAgICAgIC5zdWJzY3JpYmUoc3RyZWV0TmFtZSA9PiB7XG4gICAgICAgICF0aGlzLnZhbHVlID8gdGhpcy52YWx1ZSA9IHtzdHJlZXROYW1lfSA6IHRoaXMudmFsdWUuc3RyZWV0TmFtZSA9IHN0cmVldE5hbWU7XG4gICAgICAgIHRoaXMudmFsdWUuZGlzcGxheUFkZHJlc3MgPSB0aGlzLnBhcnNlRGlzcGxheUFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy52YWx1ZSk7XG4gICAgICB9KTtcbiAgICB0aGlzLmFkZHJlc3NGb3JtR3JvdXBcbiAgICAgIC5nZXQoJ3N0cmVldE51bWJlcicpXG4gICAgICAudmFsdWVDaGFuZ2VzXG4gICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLCBkZWJvdW5jZVRpbWUoNDAwKSwgdGFrZVVudGlsKHRoaXMuX3Vuc3Vic2NyaWJlQWxsKSlcbiAgICAgIC5zdWJzY3JpYmUoc3RyZWV0TnVtYmVyID0+IHtcbiAgICAgICAgIXRoaXMudmFsdWUgPyB0aGlzLnZhbHVlID0ge3N0cmVldE51bWJlcn0gOiB0aGlzLnZhbHVlLnN0cmVldE51bWJlciA9IHN0cmVldE51bWJlcjtcbiAgICAgICAgdGhpcy52YWx1ZS5kaXNwbGF5QWRkcmVzcyA9IHRoaXMucGFyc2VEaXNwbGF5QWRkcmVzcygpO1xuICAgICAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSh0aGlzLnZhbHVlKTtcbiAgICAgIH0pO1xuICAgIHRoaXMuYWRkcmVzc0Zvcm1Hcm91cFxuICAgICAgLmdldCgncG9zdGFsQ29kZScpXG4gICAgICAudmFsdWVDaGFuZ2VzXG4gICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLCBkZWJvdW5jZVRpbWUoNDAwKSwgdGFrZVVudGlsKHRoaXMuX3Vuc3Vic2NyaWJlQWxsKSlcbiAgICAgIC5zdWJzY3JpYmUocG9zdGFsQ29kZSA9PiB7XG4gICAgICAgICF0aGlzLnZhbHVlID8gdGhpcy52YWx1ZSA9IHtwb3N0YWxDb2RlfSA6IHRoaXMudmFsdWUucG9zdGFsQ29kZSA9IHBvc3RhbENvZGU7XG4gICAgICAgIHRoaXMudmFsdWUuZGlzcGxheUFkZHJlc3MgPSB0aGlzLnBhcnNlRGlzcGxheUFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy52YWx1ZSk7XG4gICAgICB9KTtcbiAgICB0aGlzLmFkZHJlc3NGb3JtR3JvdXBcbiAgICAgIC5nZXQoJ3ZpY2luaXR5JylcbiAgICAgIC52YWx1ZUNoYW5nZXNcbiAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSg0MDApLCB0YWtlVW50aWwodGhpcy5fdW5zdWJzY3JpYmVBbGwpKVxuICAgICAgLnN1YnNjcmliZSh2aWNpbml0eSA9PiB7XG4gICAgICAgICF0aGlzLnZhbHVlID8gdGhpcy52YWx1ZSA9IHt2aWNpbml0eX0gOiB0aGlzLnZhbHVlLnZpY2luaXR5ID0gdmljaW5pdHk7XG4gICAgICAgIHRoaXMudmFsdWUuZGlzcGxheUFkZHJlc3MgPSB0aGlzLnBhcnNlRGlzcGxheUFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy52YWx1ZSk7XG4gICAgICB9KTtcbiAgICB0aGlzLmFkZHJlc3NGb3JtR3JvdXBcbiAgICAgIC5nZXQoJ2xvY2FsaXR5JylcbiAgICAgIC52YWx1ZUNoYW5nZXNcbiAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSg0MDApLCB0YWtlVW50aWwodGhpcy5fdW5zdWJzY3JpYmVBbGwpKVxuICAgICAgLnN1YnNjcmliZShsb2NhbGl0eSA9PiB7XG4gICAgICAgICF0aGlzLnZhbHVlID8gdGhpcy52YWx1ZSA9IHtsb2NhbGl0eX0gOiB0aGlzLnZhbHVlLmxvY2FsaXR5ID0gbG9jYWxpdHk7XG4gICAgICAgIHRoaXMudmFsdWUuZGlzcGxheUFkZHJlc3MgPSB0aGlzLnBhcnNlRGlzcGxheUFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy52YWx1ZSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHBhcnNlRGlzcGxheUFkZHJlc3MoKSB7XG4gICAgcmV0dXJuIGAke3RoaXMudmFsdWU/LnN0cmVldE5hbWUgPyB0aGlzLnZhbHVlPy5zdHJlZXROYW1lIDogJyd9ICR7dGhpcy52YWx1ZT8uc3RyZWV0TnVtYmVyID8gdGhpcy52YWx1ZT8uc3RyZWV0TnVtYmVyIDogJyd9JHt0aGlzLnZhbHVlPy5wb3N0YWxDb2RlIHx8IHRoaXMudmFsdWU/LmxvY2FsaXR5Py5sb25nID8gJywgJyA6ICcnfSR7dGhpcy52YWx1ZT8ucG9zdGFsQ29kZSA/IHRoaXMudmFsdWU/LnBvc3RhbENvZGUgOiAnJ30gJHt0aGlzLnZhbHVlPy5sb2NhbGl0eT8ubG9uZyA/IHRoaXMudmFsdWU/LmxvY2FsaXR5Py5sb25nIDogJyd9YFxuICB9XG5cbiAgc3luY0F1dG9Db21wbGV0ZSgkZXZlbnQ6IGdvb2dsZS5tYXBzLnBsYWNlcy5QbGFjZVJlc3VsdCkge1xuICAgIGlmICh0aGlzLmdlcm1hbkFkZHJlc3MpIHtcbiAgICAgIHRoaXMuYWRkcmVzc0Zvcm1Hcm91cC5yZXNldCgpO1xuICAgIH1cbiAgICBjb25zdCBnZXJtYW5BZGRyZXNzOiBHZXJtYW5BZGRyZXNzID0gcGFyc2VHZXJtYW5BZGRyZXNzKCRldmVudCk7XG4gICAgdGhpcy5nZXJtYW5BZGRyZXNzID0gZ2VybWFuQWRkcmVzcztcbiAgICBpZiAoZ2VybWFuQWRkcmVzcy52aWNpbml0eSkge1xuICAgICAgdGhpcy5hZGRyZXNzRm9ybUdyb3VwLmdldCgndmljaW5pdHknKS5wYXRjaFZhbHVlKGdlcm1hbkFkZHJlc3MudmljaW5pdHksIHtlbWl0RXZlbnQ6IGZhbHNlLCBvbmx5U2VsZjogdHJ1ZX0pO1xuICAgIH1cbiAgICBpZiAoZ2VybWFuQWRkcmVzcy5zdHJlZXROYW1lKSB7XG4gICAgICB0aGlzLmFkZHJlc3NGb3JtR3JvdXAuZ2V0KCdzdHJlZXROYW1lJykucGF0Y2hWYWx1ZShnZXJtYW5BZGRyZXNzLnN0cmVldE5hbWUsIHtlbWl0RXZlbnQ6IGZhbHNlLCBvbmx5U2VsZjogdHJ1ZX0pO1xuICAgIH1cbiAgICBpZiAoZ2VybWFuQWRkcmVzcy5zdHJlZXROdW1iZXIpIHtcbiAgICAgIHRoaXMuYWRkcmVzc0Zvcm1Hcm91cC5nZXQoJ3N0cmVldE51bWJlcicpLnBhdGNoVmFsdWUoZ2VybWFuQWRkcmVzcy5zdHJlZXROdW1iZXIudG9TdHJpbmcoKSwge1xuICAgICAgICBlbWl0RXZlbnQ6IGZhbHNlLFxuICAgICAgICBvbmx5U2VsZjogdHJ1ZVxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChnZXJtYW5BZGRyZXNzLnBvc3RhbENvZGUpIHtcbiAgICAgIHRoaXMuYWRkcmVzc0Zvcm1Hcm91cC5nZXQoJ3Bvc3RhbENvZGUnKS5wYXRjaFZhbHVlKGdlcm1hbkFkZHJlc3MucG9zdGFsQ29kZSwge2VtaXRFdmVudDogZmFsc2UsIG9ubHlTZWxmOiB0cnVlfSk7XG4gICAgfVxuICAgIGlmIChnZXJtYW5BZGRyZXNzLmxvY2FsaXR5ICYmIGdlcm1hbkFkZHJlc3MubG9jYWxpdHkubG9uZykge1xuICAgICAgdGhpcy5hZGRyZXNzRm9ybUdyb3VwLmdldCgnbG9jYWxpdHkubG9uZycpLnBhdGNoVmFsdWUoZ2VybWFuQWRkcmVzcy5sb2NhbGl0eS5sb25nLCB7XG4gICAgICAgIGVtaXRFdmVudDogZmFsc2UsXG4gICAgICAgIG9ubHlTZWxmOiB0cnVlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbHVlID0gZ2VybWFuQWRkcmVzcztcbiAgICB0aGlzLm9uR2VybWFuQWRkcmVzc01hcHBlZC5lbWl0KGdlcm1hbkFkZHJlc3MpO1xuICB9XG5cbiAgd3JpdGVWYWx1ZShvYmo6IGFueSk6IHZvaWQge1xuICAgIGxldCBzaG91bGRSZWNyZWF0ZUZHID0gZmFsc2U7XG4gICAgaWYgKG9iaikge1xuICAgICAgaWYgKCF0aGlzLnZhbHVlICYmIHRoaXMuZmlyc3RJbml0KSB7XG4gICAgICAgIHNob3VsZFJlY3JlYXRlRkcgPSB0cnVlO1xuICAgICAgfVxuICAgICAgdGhpcy52YWx1ZSA9IG9iajtcbiAgICAgIGlmIChzaG91bGRSZWNyZWF0ZUZHKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlQWRkcmVzc0Zvcm1Hcm91cCgpO1xuICAgICAgICB0aGlzLmZpcnN0SW5pdCA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xuICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7XG4gIH1cblxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgfVxuXG59XG4iLCI8ZGl2IGZ4TGF5b3V0PVwiY29sdW1uXCI+XG4gIDxkaXYgKm5nSWY9XCIhZGlzYWJsZVNlYXJjaFwiIGZ4RmxleD1cIjEwMFwiPlxuICAgIDwhLS1zZWFyY2ggYWRkcmVzcy0tPlxuICAgIDxtYXQtZm9ybS1maWVsZCBmeEZsZXg9XCJhdXRvXCIgW2FwcGVhcmFuY2VdPVwic2VhcmNoQmFyQXBwZWFyYW5jZVwiIFtAYW5pbWF0ZV09XCJ7IHZhbHVlOiAnKicsIHBhcmFtczogeyB5OiAnMTAwJScgfSB9XCI+XG4gICAgICA8bWF0LWxhYmVsPnt7c2VhcmNoQWRkcmVzc0xhYmVsfX08L21hdC1sYWJlbD5cbiAgICAgIDxpbnB1dFxuICAgICAgICAob25BdXRvY29tcGxldGVTZWxlY3RlZCk9XCJzeW5jQXV0b0NvbXBsZXRlKCRldmVudClcIlxuICAgICAgICBbY291bnRyeV09XCJjb3VudHJ5XCJcbiAgICAgICAgW3BsYWNlSWRPbmx5XT1cInBsYWNlSWRPbmx5XCJcbiAgICAgICAgW3N0cmljdEJvdW5kc109XCJzdHJpY3RCb3VuZHNcIlxuICAgICAgICBbdHlwZXNdPVwidHlwZXNcIlxuICAgICAgICBbdHlwZV09XCJ0eXBlXCJcbiAgICAgICAgbWF0R29vZ2xlTWFwc0F1dG9jb21wbGV0ZVxuICAgICAgICBtYXRJbnB1dFxuICAgICAgICByZXF1aXJlZFxuICAgICAgLz5cbiAgICAgIDxtYXQtaWNvbiBjb2xvcj1cInByaW1hcnlcIiBtYXRTdWZmaXg+c2VhcmNoPC9tYXQtaWNvbj5cbiAgICAgIDwhLS0gICAgPG1hdC1lcnJvcj57eyAnbXNhLmNvbnRhY3REYXRhLmN1cnJlbnRBZGRyZXNzLmVycm9yJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWVycm9yPi0tPlxuICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gIDwvZGl2PlxuXG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiYWRkcmVzc0Zvcm1Hcm91cFwiIGZ4RmxleCBmeExheW91dEdhcD1cIjEwcHhcIj5cbiAgICA8ZGl2IGZ4TGF5b3V0PVwicm93XCIgZnhMYXlvdXRHYXA9XCIxMHB4XCI+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgZnhGbGV4PVwiODBcIlxuICAgICAgICAgICAgICAgICAgICAgIFthcHBlYXJhbmNlXT1cImFwcGVhcmFuY2VcIlxuICAgICAgICAgICAgICAgICAgICAgIFtAYW5pbWF0ZV09XCJ7IHZhbHVlOiAnKicsIHBhcmFtczogeyB5OiAnMTAwJScgfSB9XCI+XG4gICAgICAgIDxtYXQtbGFiZWw+e3tzdHJlZXROYW1lTGFiZWx9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInN0cmVldE5hbWVcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgLz5cbiAgICAgICAgPCEtLSAgICAgICAgPG1hdC1pY29uIGNvbG9yPVwicHJpbWFyeVwiIG1hdFN1ZmZpeD5hZGRfbG9jYXRpb248L21hdC1pY29uPi0tPlxuICAgICAgICA8IS0tICAgIDxtYXQtZXJyb3I+e3sgJ21zYS5jb250YWN0RGF0YS5jdXJyZW50QWRkcmVzcy5lcnJvcicgfCB0cmFuc2xhdGUgfX08L21hdC1lcnJvcj4tLT5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgZnhGbGV4PVwiMjBcIiBbYXBwZWFyYW5jZV09XCJhcHBlYXJhbmNlXCIgW0BhbmltYXRlXT1cInsgdmFsdWU6ICcqJywgcGFyYW1zOiB7IHk6ICcxMDAlJyB9IH1cIj5cbiAgICAgICAgPG1hdC1sYWJlbD57e3N0cmVldE51bWJlckxhYmVsfX08L21hdC1sYWJlbD5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgW3JlYWRvbmx5XT1cInJlYWRvbmx5XCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJzdHJlZXROdW1iZXJcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgLz5cbiAgICAgICAgPCEtLSAgICAgICAgPG1hdC1pY29uIGNvbG9yPVwicHJpbWFyeVwiIG1hdFN1ZmZpeD5hZGRfbG9jYXRpb248L21hdC1pY29uPi0tPlxuICAgICAgICA8IS0tICAgIDxtYXQtZXJyb3I+e3sgJ21zYS5jb250YWN0RGF0YS5jdXJyZW50QWRkcmVzcy5lcnJvcicgfCB0cmFuc2xhdGUgfX08L21hdC1lcnJvcj4tLT5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBmeExheW91dD1cInJvd1wiIGZ4TGF5b3V0R2FwPVwiMTBweFwiPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkIGZ4RmxleD1cIjIwXCIgW2FwcGVhcmFuY2VdPVwiYXBwZWFyYW5jZVwiIFtAYW5pbWF0ZV09XCJ7IHZhbHVlOiAnKicsIHBhcmFtczogeyB5OiAnMTAwJScgfSB9XCI+XG4gICAgICAgIDxtYXQtbGFiZWw+e3twb3N0YWxDb2RlTGFiZWx9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInBvc3RhbENvZGVcIlxuICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgLz5cbiAgICAgICAgPCEtLSAgICAgICAgPG1hdC1pY29uIGNvbG9yPVwicHJpbWFyeVwiIG1hdFN1ZmZpeD5hZGRfbG9jYXRpb248L21hdC1pY29uPi0tPlxuICAgICAgICA8IS0tICAgIDxtYXQtZXJyb3I+e3sgJ21zYS5jb250YWN0RGF0YS5jdXJyZW50QWRkcmVzcy5lcnJvcicgfCB0cmFuc2xhdGUgfX08L21hdC1lcnJvcj4tLT5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJzaG93VmljaW5pdHlcIiBmeEZsZXg9XCJhdXRvXCJcbiAgICAgICAgICAgICAgICAgICAgICBbYXBwZWFyYW5jZV09XCJhcHBlYXJhbmNlXCJcbiAgICAgICAgICAgICAgICAgICAgICBbQGFuaW1hdGVdPVwieyB2YWx1ZTogJyonLCBwYXJhbXM6IHsgeTogJzEwMCUnIH0gfVwiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7dmljaW5pdHlMYWJlbH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIFtyZWFkb25seV09XCJyZWFkb25seVwiXG4gICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ2aWNpbml0eVwiXG4gICAgICAgIC8+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgPGRpdiBmb3JtR3JvdXBOYW1lPVwibG9jYWxpdHlcIiBmeEZsZXg9XCJhdXRvXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBmeEZsZXg9XCJhdXRvXCIgW2FwcGVhcmFuY2VdPVwiYXBwZWFyYW5jZVwiIFtAYW5pbWF0ZV09XCJ7IHZhbHVlOiAnKicsIHBhcmFtczogeyB5OiAnMTAwJScgfSB9XCI+XG4gICAgICAgICAgPG1hdC1sYWJlbD57e2xvY2FsaXR5TGFiZWx9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgW3JlYWRvbmx5XT1cInJlYWRvbmx5XCJcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImxvbmdcIlxuICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8bWF0LWljb24gY29sb3I9XCJwcmltYXJ5XCIgbWF0U3VmZml4PmFkZF9sb2NhdGlvbjwvbWF0LWljb24+XG4gICAgICAgICAgPCEtLSAgICA8bWF0LWVycm9yPnt7ICdtc2EuY29udGFjdERhdGEuY3VycmVudEFkZHJlc3MuZXJyb3InIHwgdHJhbnNsYXRlIH19PC9tYXQtZXJyb3I+LS0+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9mb3JtPlxuPC9kaXY+XG4iXX0=