UNPKG

ontimize-web-ngx

Version:
333 lines 54.6 kB
import { __decorate, __metadata } from "tslib"; import { Component, ElementRef, forwardRef, Inject, Injector, Optional, ViewChild, ViewEncapsulation } from '@angular/core'; import { MediaObserver } from '@angular/flex-layout'; import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; import { MatDatepicker, MatDatepickerInput } from '@angular/material/datepicker'; import moment from 'moment'; import { BooleanInputConverter } from '../../../decorators/input-converter'; import { MomentService } from '../../../services/moment.service'; import { OntimizeMomentDateAdapter } from '../../../shared/material/date/ontimize-moment-date-adapter'; import { SQLTypes } from '../../../util/sqltypes'; import { Util } from '../../../util/util'; import { OFormValue } from '../../form/o-form-value'; import { OFormComponent } from '../../form/o-form.component'; import { OFormDataComponent } from '../../o-form-data-component.class'; import { OValueChangeEvent } from '../../o-value-change-event.class'; import * as i0 from "@angular/core"; import * as i1 from "@angular/material/core"; import * as i2 from "@angular/common"; import * as i3 from "@angular/flex-layout/flex"; import * as i4 from "@angular/forms"; import * as i5 from "../../../directives/o-mat-error.directive"; import * as i6 from "@angular/material/button"; import * as i7 from "@angular/material/datepicker"; import * as i8 from "@angular/material/icon"; import * as i9 from "@angular/material/input"; import * as i10 from "@angular/material/form-field"; import * as i11 from "@angular/material/tooltip"; import * as i12 from "../../../pipes/o-translate.pipe"; import * as i13 from "../../form/o-form.component"; export const DEFAULT_INPUTS_O_DATE_INPUT = [ 'valueType: value-type', 'oformat: format', 'olocale: locale', 'oStartView: start-view', 'oMinDate: min', 'oMaxDate: max', 'oTouchUi: touch-ui', 'oStartAt: start-at', 'filterDate: filter-date', 'textInputEnabled: text-input-enabled', 'dateClass: date-class', ]; export class ODateInputComponent extends OFormDataComponent { set oMinDate(value) { if (value) { const momentD = this.getValueAsMoment(value); if (Util.isDefined(momentD)) { this.datepickerInput.min = momentD.toDate(); this.minDateString = momentD.format(this.oformat); } } } set oMaxDate(value) { if (value) { const momentD = this.getValueAsMoment(value); if (Util.isDefined(momentD)) { this.datepickerInput.max = momentD.toDate(); this.maxDateString = momentD.format(this.oformat); } } } constructor(form, dateAdapter, elRef, injector) { super(form, elRef, injector); this.textInputEnabled = true; this._oformat = 'L'; this.updateLocaleOnChange = false; this.oStartView = 'month'; this._valueType = 'timestamp'; this.momentDateAdapter = dateAdapter; this._defaultSQLTypeKey = 'DATE'; this.momentSrv = this.injector.get(MomentService); this.media = this.injector.get(MediaObserver); } ngOnInit() { this.initialize(); if (!this.olocale) { this.updateLocaleOnChange = true; this.olocale = this.momentSrv.getLocale(); } if (this.oformat) { this.momentDateAdapter.oFormat = this.oformat; } this.momentDateAdapter.setLocale(this.olocale); if (this.oStartView) { this.datepicker.startView = this.oStartView; } if (this.oStartAt) { this.datepicker.startAt = new Date(this.oStartAt); } if (this.updateLocaleOnChange) { this.onLanguageChangeSubscription = this.translateService.onLanguageChanged.subscribe(() => { this.momentDateAdapter.setLocale(this.translateService.getCurrentLang()); this.setValue(this.getValue()); }); } this.subscribeToMediaChanges(); } subscribeToMediaChanges() { this.mediaSubscription = this.media.asObservable().subscribe((change) => { if (['xs', 'sm'].indexOf(change[0].mqAlias) !== -1) { this.touchUi = Util.isDefined(this.oTouchUi) ? this.oTouchUi : true; } if (['md', 'lg', 'xl'].indexOf(change[0].mqAlias) !== -1) { this.touchUi = Util.isDefined(this.oTouchUi) ? this.oTouchUi : false; } }); } ngOnDestroy() { super.ngOnDestroy(); if (this.mediaSubscription) { this.mediaSubscription.unsubscribe(); } if (this.onLanguageChangeSubscription) { this.onLanguageChangeSubscription.unsubscribe(); } } getValueAsDate() { return this.dateValue; } getValue() { let timestampValue = super.getValue(); if (timestampValue && timestampValue instanceof Date) { timestampValue = timestampValue.getTime(); } return timestampValue; } get showClearButton() { return this.clearButton && !this.isReadOnly && this.enabled && this.matInputRef.nativeElement.value; } open() { if (!this.isReadOnly && this.enabled) { this.datepicker.open(); } } clearValue(options, setDirty = false) { super.clearValue(options, setDirty); this.dateValue = void 0; } onChangeEvent(event) { const isValid = event.value && event.value.isValid && event.value.isValid(); let val = isValid ? event.value.valueOf() : event.value; const parsedVal = Util.parseByValueType(val, this.valueType, this.oformat); this.setValue(parsedVal, { changeType: OValueChangeEvent.USER_CHANGE, emitEvent: false, emitModelToViewChange: false }); } onClickInput(e) { if (!this.textInputEnabled) { this.open(); } } get filterDate() { return this._filterDate; } set filterDate(val) { this._filterDate = val; } get dateClass() { return this._dateClass; } set dateClass(val) { this._dateClass = val; } get oformat() { return this._oformat; } set oformat(val) { this._oformat = val; } get minDateString() { return this._minDateString; } set minDateString(val) { this._minDateString = val; } get maxDateString() { return this._maxDateString; } set maxDateString(val) { this._maxDateString = val; } get touchUi() { return this.oTouchUi || false; } set touchUi(val) { this.oTouchUi = val; this.datepicker.touchUi = this.touchUi; } ensureODateValueType(val) { if (!Util.isDefined(val)) { return val; } let result = val; switch (this.valueType) { case 'string': if (typeof val === 'string') { const m = moment(val, this.oformat); if (m.isValid()) { this.dateValue = new Date(m.valueOf()); } } else { result = undefined; } break; case 'date': if ((val instanceof Date)) { this.dateValue = val; } else { result = undefined; } break; case 'timestamp': if (typeof val === 'number') { this.dateValue = new Date(val); } else { result = undefined; } break; case 'iso-8601': if (typeof val !== 'string') { const acceptTimestamp = typeof val === 'number' && this.getSQLType() === SQLTypes.TIMESTAMP; if (acceptTimestamp) { this.dateValue = new Date(val); } else { result = undefined; } } else { const m = moment(val); if (m.isValid()) { this.dateValue = new Date(m.valueOf()); } else { result = undefined; } } break; default: break; } if (!Util.isDefined(result)) { console.warn(`ODateInputComponent value (${val}) is not consistent with value-type (${this.valueType})`); } return result; } setFormValue(val, options, setDirty = false) { let value = val; if (val instanceof OFormValue) { value = val.value; } this.ensureODateValueType(value); super.setFormValue(value, options, setDirty); } set valueType(val) { this._valueType = Util.convertToODateValueType(val); } get valueType() { return this._valueType; } createFormControl(cfg, validators) { this._fControl = super.createFormControl(cfg, validators); if (!this.isEmpty() && !this.form.isInInsertMode()) { this._fControl.markAsTouched(); } return this._fControl; } getValueAsMoment(val) { if (!Util.isDefined(val)) { return val; } let result; switch (true) { case this.valueType === 'string' && typeof val === 'string': result = moment(val, this.oformat); break; case this.valueType === 'date' && val instanceof Date: case this.valueType === 'timestamp' && typeof val === 'number': case this.valueType === 'iso-8601' && typeof val === 'string': result = moment(val); break; case this.valueType === 'iso-8601': if (typeof val !== 'string') { const acceptTimestamp = typeof val === 'number' && this.getSQLType() === SQLTypes.TIMESTAMP; if (acceptTimestamp) { result = moment(val); } } break; default: break; } return Util.isDefined(result) && result.isValid() ? result : undefined; } } ODateInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ODateInputComponent, deps: [{ token: forwardRef(() => OFormComponent), optional: true }, { token: i1.DateAdapter }, { token: i0.ElementRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); ODateInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ODateInputComponent, selector: "o-date-input", inputs: { valueType: ["value-type", "valueType"], oformat: ["format", "oformat"], olocale: ["locale", "olocale"], oStartView: ["start-view", "oStartView"], oMinDate: ["min", "oMinDate"], oMaxDate: ["max", "oMaxDate"], oTouchUi: ["touch-ui", "oTouchUi"], oStartAt: ["start-at", "oStartAt"], filterDate: ["filter-date", "filterDate"], textInputEnabled: ["text-input-enabled", "textInputEnabled"], dateClass: ["date-class", "dateClass"] }, providers: [ { provide: DateAdapter, useClass: OntimizeMomentDateAdapter, deps: [MAT_DATE_LOCALE] } ], viewQueries: [{ propertyName: "datepicker", first: true, predicate: ["picker"], descendants: true, static: true }, { propertyName: "datepickerInput", first: true, predicate: MatDatepickerInput, descendants: true, static: true }, { propertyName: "matInputRef", first: true, predicate: ["matInputRef"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, ngImport: i0, template: "<div fxLayout=\"row\" fxLayoutAlign=\"space-between center\" [formGroup]=\"getFormGroup()\" [matTooltip]=\"tooltip\"\n [matTooltipClass]=\"tooltipClass\" [matTooltipPosition]=\"tooltipPosition\" [matTooltipShowDelay]=\"tooltipShowDelay\"\n [matTooltipHideDelay]=\"tooltipHideDelay\" (click)=\"onClickInput($event)\">\n <mat-form-field [appearance]=\"appearance\" [floatLabel]=\"floatLabel\" [hideRequiredMarker]=\"hideRequiredMarker\"\n [class.custom-width]=\"hasCustomWidth\" class=\"icon-field\" fxFlexFill [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <input matInput #matInputRef [matDatepicker]=\"picker\" [id]=\"getAttribute()\" [formControlName]=\"getAttribute()\"\n [placeholder]=\"placeHolder\" [readonly]=\"isReadOnly || !textInputEnabled\" (focus)=\"innerOnFocus($event)\"\n (blur)=\"innerOnBlur($event)\" [matDatepickerFilter]=\"filterDate\" (dateChange)=\"onChangeEvent($event)\"\n [required]=\"isRequired\" [value]=\"getValueAsDate()\">\n\n <button type=\"button\" *ngIf=\"showClearButton\" matSuffix mat-icon-button (click)=\"onClickClearValue($event)\">\n <mat-icon svgIcon=\"ontimize:close\"></mat-icon>\n </button>\n <mat-datepicker-toggle matSuffix [disabled]=\"isReadOnly || !enabled\" [class.read-only]=\"isReadOnly\" [for]=\"picker\">\n <mat-icon matDatepickerToggleIcon>today</mat-icon>\n </mat-datepicker-toggle>\n <mat-datepicker #picker [disabled]=\"isReadOnly || !enabled\" [dateClass]=\"dateClass\"></mat-datepicker>\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerParse')\">\n {{ 'FORM_VALIDATION.DATE_PARSE' | oTranslate }} {{ oformat }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerFilter')\">\n {{ 'FORM_VALIDATION.DATE_FILTER' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerMin')\">\n {{ 'FORM_VALIDATION.DATE_MIN' | oTranslate }} {{ minDateString }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerMax')\">\n {{ 'FORM_VALIDATION.DATE_MAX' | oTranslate }} {{ maxDateString }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n</div>", dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i3.FlexFillDirective, selector: "[fxFill], [fxFlexFill]" }, { kind: "directive", type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i5.OMatErrorDirective, selector: "[oMatError]", inputs: ["oMatError"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i7.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i7.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i7.MatDatepickerToggleIcon, selector: "[matDatepickerToggleIcon]" }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i9.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: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "pipe", type: i12.OTranslatePipe, name: "oTranslate" }], encapsulation: i0.ViewEncapsulation.None }); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], ODateInputComponent.prototype, "textInputEnabled", void 0); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], ODateInputComponent.prototype, "oTouchUi", void 0); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ODateInputComponent, decorators: [{ type: Component, args: [{ selector: 'o-date-input', inputs: DEFAULT_INPUTS_O_DATE_INPUT, encapsulation: ViewEncapsulation.None, providers: [ { provide: DateAdapter, useClass: OntimizeMomentDateAdapter, deps: [MAT_DATE_LOCALE] } ], template: "<div fxLayout=\"row\" fxLayoutAlign=\"space-between center\" [formGroup]=\"getFormGroup()\" [matTooltip]=\"tooltip\"\n [matTooltipClass]=\"tooltipClass\" [matTooltipPosition]=\"tooltipPosition\" [matTooltipShowDelay]=\"tooltipShowDelay\"\n [matTooltipHideDelay]=\"tooltipHideDelay\" (click)=\"onClickInput($event)\">\n <mat-form-field [appearance]=\"appearance\" [floatLabel]=\"floatLabel\" [hideRequiredMarker]=\"hideRequiredMarker\"\n [class.custom-width]=\"hasCustomWidth\" class=\"icon-field\" fxFlexFill [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <input matInput #matInputRef [matDatepicker]=\"picker\" [id]=\"getAttribute()\" [formControlName]=\"getAttribute()\"\n [placeholder]=\"placeHolder\" [readonly]=\"isReadOnly || !textInputEnabled\" (focus)=\"innerOnFocus($event)\"\n (blur)=\"innerOnBlur($event)\" [matDatepickerFilter]=\"filterDate\" (dateChange)=\"onChangeEvent($event)\"\n [required]=\"isRequired\" [value]=\"getValueAsDate()\">\n\n <button type=\"button\" *ngIf=\"showClearButton\" matSuffix mat-icon-button (click)=\"onClickClearValue($event)\">\n <mat-icon svgIcon=\"ontimize:close\"></mat-icon>\n </button>\n <mat-datepicker-toggle matSuffix [disabled]=\"isReadOnly || !enabled\" [class.read-only]=\"isReadOnly\" [for]=\"picker\">\n <mat-icon matDatepickerToggleIcon>today</mat-icon>\n </mat-datepicker-toggle>\n <mat-datepicker #picker [disabled]=\"isReadOnly || !enabled\" [dateClass]=\"dateClass\"></mat-datepicker>\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerParse')\">\n {{ 'FORM_VALIDATION.DATE_PARSE' | oTranslate }} {{ oformat }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerFilter')\">\n {{ 'FORM_VALIDATION.DATE_FILTER' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerMin')\">\n {{ 'FORM_VALIDATION.DATE_MIN' | oTranslate }} {{ minDateString }}\n </mat-error>\n <mat-error *oMatError=\"hasError('matDatepickerMax')\">\n {{ 'FORM_VALIDATION.DATE_MAX' | oTranslate }} {{ maxDateString }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n</div>" }] }], ctorParameters: function () { return [{ type: i13.OFormComponent, decorators: [{ type: Optional }, { type: Inject, args: [forwardRef(() => OFormComponent)] }] }, { type: i1.DateAdapter }, { type: i0.ElementRef }, { type: i0.Injector }]; }, propDecorators: { textInputEnabled: [], oTouchUi: [], datepicker: [{ type: ViewChild, args: ['picker', { static: true }] }], datepickerInput: [{ type: ViewChild, args: [MatDatepickerInput, { static: true }] }], matInputRef: [{ type: ViewChild, args: ['matInputRef', { read: ElementRef, static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiby1kYXRlLWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L2RhdGUtaW5wdXQvby1kYXRlLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L2RhdGUtaW5wdXQvby1kYXRlLWlucHV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBcUIsUUFBUSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvSSxPQUFPLEVBQWUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFbEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN0RSxPQUFPLEVBQUUsYUFBYSxFQUFFLGtCQUFrQixFQUEyQixNQUFNLDhCQUE4QixDQUFDO0FBQzFHLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUc1QixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDakUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sNERBQTRELENBQUM7QUFLdkcsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUFFLGNBQWMsRUFB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cmRSZWYsIEluamVjdCwgSW5qZWN0b3IsIE9uRGVzdHJveSwgT25Jbml0LCBPcHRpb25hbCwgVmlld0NoaWxkLCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTWVkaWFDaGFuZ2UsIE1lZGlhT2JzZXJ2ZXIgfSBmcm9tICdAYW5ndWxhci9mbGV4LWxheW91dCc7XG5pbXBvcnQgeyBNb21lbnREYXRlQWRhcHRlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsLW1vbWVudC1hZGFwdGVyJztcbmltcG9ydCB7IERhdGVBZGFwdGVyLCBNQVRfREFURV9MT0NBTEUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jb3JlJztcbmltcG9ydCB7IE1hdERhdGVwaWNrZXIsIE1hdERhdGVwaWNrZXJJbnB1dCwgTWF0RGF0ZXBpY2tlcklucHV0RXZlbnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kYXRlcGlja2VyJztcbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBCb29sZWFuSW5wdXRDb252ZXJ0ZXIgfSBmcm9tICcuLi8uLi8uLi9kZWNvcmF0b3JzL2lucHV0LWNvbnZlcnRlcic7XG5pbXBvcnQgeyBNb21lbnRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvbW9tZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgT250aW1pemVNb21lbnREYXRlQWRhcHRlciB9IGZyb20gJy4uLy4uLy4uL3NoYXJlZC9tYXRlcmlhbC9kYXRlL29udGltaXplLW1vbWVudC1kYXRlLWFkYXB0ZXInO1xuaW1wb3J0IHsgRGF0ZUN1c3RvbUNsYXNzRnVuY3Rpb24gfSBmcm9tICcuLi8uLi8uLi90eXBlcy9kYXRlLWN1c3RvbS1jbGFzcy50eXBlJztcbmltcG9ydCB7IERhdGVGaWx0ZXJGdW5jdGlvbiB9IGZyb20gJy4uLy4uLy4uL3R5cGVzL2RhdGUtZmlsdGVyLWZ1bmN0aW9uLnR5cGUnO1xuaW1wb3J0IHsgRm9ybVZhbHVlT3B0aW9ucyB9IGZyb20gJy4uLy4uLy4uL3R5cGVzL2Zvcm0tdmFsdWUtb3B0aW9ucy50eXBlJztcbmltcG9ydCB7IE9EYXRlVmFsdWVUeXBlIH0gZnJvbSAnLi4vLi4vLi4vdHlwZXMvby1kYXRlLXZhbHVlLnR5cGUnO1xuaW1wb3J0IHsgU1FMVHlwZXMgfSBmcm9tICcuLi8uLi8uLi91dGlsL3NxbHR5cGVzJztcbmltcG9ydCB7IFV0aWwgfSBmcm9tICcuLi8uLi8uLi91dGlsL3V0aWwnO1xuaW1wb3J0IHsgT0Zvcm1WYWx1ZSB9IGZyb20gJy4uLy4uL2Zvcm0vby1mb3JtLXZhbHVlJztcbmltcG9ydCB7IE9Gb3JtQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vZm9ybS9vLWZvcm0uY29tcG9uZW50JztcbmltcG9ydCB7IE9Gb3JtRGF0YUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL28tZm9ybS1kYXRhLWNvbXBvbmVudC5jbGFzcyc7XG5pbXBvcnQgeyBPVmFsdWVDaGFuZ2VFdmVudCB9IGZyb20gJy4uLy4uL28tdmFsdWUtY2hhbmdlLWV2ZW50LmNsYXNzJztcbmltcG9ydCB7IE9Gb3JtQ29udHJvbCB9IGZyb20gJy4uL28tZm9ybS1jb250cm9sLmNsYXNzJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfSU5QVVRTX09fREFURV9JTlBVVCA9IFtcbiAgJ3ZhbHVlVHlwZTogdmFsdWUtdHlwZScsXG4gICdvZm9ybWF0OiBmb3JtYXQnLFxuICAnb2xvY2FsZTogbG9jYWxlJyxcbiAgJ29TdGFydFZpZXc6IHN0YXJ0LXZpZXcnLFxuICAnb01pbkRhdGU6IG1pbicsXG4gICdvTWF4RGF0ZTogbWF4JyxcbiAgJ29Ub3VjaFVpOiB0b3VjaC11aScsXG4gICdvU3RhcnRBdDogc3RhcnQtYXQnLFxuICAnZmlsdGVyRGF0ZTogZmlsdGVyLWRhdGUnLFxuICAndGV4dElucHV0RW5hYmxlZDogdGV4dC1pbnB1dC1lbmFibGVkJyxcbiAgJ2RhdGVDbGFzczogZGF0ZS1jbGFzcycsXG5dO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdvLWRhdGUtaW5wdXQnLFxuICB0ZW1wbGF0ZVVybDogJy4vby1kYXRlLWlucHV0LmNvbXBvbmVudC5odG1sJyxcbiAgaW5wdXRzOiBERUZBVUxUX0lOUFVUU19PX0RBVEVfSU5QVVQsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHByb3ZpZGVyczogW1xuICAgIHsgcHJvdmlkZTogRGF0ZUFkYXB0ZXIsIHVzZUNsYXNzOiBPbnRpbWl6ZU1vbWVudERhdGVBZGFwdGVyLCBkZXBzOiBbTUFUX0RBVEVfTE9DQUxFXSB9XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgT0RhdGVJbnB1dENvbXBvbmVudCBleHRlbmRzIE9Gb3JtRGF0YUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSwgT25Jbml0IHtcblxuICBAQm9vbGVhbklucHV0Q29udmVydGVyKClcbiAgcHVibGljIHRleHRJbnB1dEVuYWJsZWQ6IGJvb2xlYW4gPSB0cnVlO1xuICBwcm90ZWN0ZWQgX29mb3JtYXQ6IHN0cmluZyA9ICdMJztcbiAgcHJvdGVjdGVkIG9sb2NhbGU6IHN0cmluZztcbiAgcHJvdGVjdGVkIHVwZGF0ZUxvY2FsZU9uQ2hhbmdlOiBib29sZWFuID0gZmFsc2U7XG4gIHByb3RlY3RlZCBvU3RhcnRWaWV3OiAnbW9udGgnIHwgJ3llYXInID0gJ21vbnRoJztcbiAgc2V0IG9NaW5EYXRlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGNvbnN0IG1vbWVudEQgPSB0aGlzLmdldFZhbHVlQXNNb21lbnQodmFsdWUpXG4gICAgICBpZiAoVXRpbC5pc0RlZmluZWQobW9tZW50RCkpIHtcbiAgICAgICAgdGhpcy5kYXRlcGlja2VySW5wdXQubWluID0gbW9tZW50RC50b0RhdGUoKTtcbiAgICAgICAgdGhpcy5taW5EYXRlU3RyaW5nID0gbW9tZW50RC5mb3JtYXQodGhpcy5vZm9ybWF0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgc2V0IG9NYXhEYXRlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGNvbnN0IG1vbWVudEQgPSB0aGlzLmdldFZhbHVlQXNNb21lbnQodmFsdWUpXG4gICAgICBpZiAoVXRpbC5pc0RlZmluZWQobW9tZW50RCkpIHtcbiAgICAgICAgdGhpcy5kYXRlcGlja2VySW5wdXQubWF4ID0gbW9tZW50RC50b0RhdGUoKTtcbiAgICAgICAgdGhpcy5tYXhEYXRlU3RyaW5nID0gbW9tZW50RC5mb3JtYXQodGhpcy5vZm9ybWF0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgQEJvb2xlYW5JbnB1dENvbnZlcnRlcigpXG4gIHByb3RlY3RlZCBvVG91Y2hVaTogYm9vbGVhbjtcbiAgcHJvdGVjdGVkIG9TdGFydEF0OiBzdHJpbmc7XG4gIHByb3RlY3RlZCBfZmlsdGVyRGF0ZTogRGF0ZUZpbHRlckZ1bmN0aW9uO1xuICBwcm90ZWN0ZWQgX2RhdGVDbGFzczogRGF0ZUN1c3RvbUNsYXNzRnVuY3Rpb25cbiAgcHJvdGVjdGVkIF92YWx1ZVR5cGU6IE9EYXRlVmFsdWVUeXBlID0gJ3RpbWVzdGFtcCc7XG5cbiAgcHJvdGVjdGVkIF9taW5EYXRlU3RyaW5nOiBzdHJpbmc7XG4gIHByb3RlY3RlZCBfbWF4RGF0ZVN0cmluZzogc3RyaW5nO1xuXG4gIHByb3RlY3RlZCBtZWRpYTogTWVkaWFPYnNlcnZlcjtcbiAgcHJvdGVjdGVkIG1lZGlhU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gIHByb3RlY3RlZCBvbkxhbmd1YWdlQ2hhbmdlU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gIHByb3RlY3RlZCBkYXRlVmFsdWU6IERhdGU7XG5cbiAgQFZpZXdDaGlsZCgncGlja2VyJywgeyBzdGF0aWM6IHRydWUgfSlcbiAgcHVibGljIGRhdGVwaWNrZXI6IE1hdERhdGVwaWNrZXI8RGF0ZT47XG5cbiAgQFZpZXdDaGlsZChNYXREYXRlcGlja2VySW5wdXQsIHsgc3RhdGljOiB0cnVlIH0pXG4gIHB1YmxpYyBkYXRlcGlja2VySW5wdXQ6IE1hdERhdGVwaWNrZXJJbnB1dDxEYXRlPjtcblxuICBAVmlld0NoaWxkKCdtYXRJbnB1dFJlZicsIHsgcmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiB0cnVlIH0pXG4gIHByaXZhdGUgbWF0SW5wdXRSZWYhOiBFbGVtZW50UmVmO1xuXG4gIHByaXZhdGUgbW9tZW50U3J2OiBNb21lbnRTZXJ2aWNlO1xuICBwcml2YXRlIG1vbWVudERhdGVBZGFwdGVyOiBEYXRlQWRhcHRlcjxNb21lbnREYXRlQWRhcHRlcj47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChmb3J3YXJkUmVmKCgpID0+IE9Gb3JtQ29tcG9uZW50KSkgZm9ybTogT0Zvcm1Db21wb25lbnQsXG4gICAgZGF0ZUFkYXB0ZXI6IERhdGVBZGFwdGVyPE9udGltaXplTW9tZW50RGF0ZUFkYXB0ZXI+LFxuICAgIGVsUmVmOiBFbGVtZW50UmVmLFxuICAgIGluamVjdG9yOiBJbmplY3RvclxuICApIHtcbiAgICBzdXBlcihmb3JtLCBlbFJlZiwgaW5qZWN0b3IpO1xuICAgIHRoaXMubW9tZW50RGF0ZUFkYXB0ZXIgPSBkYXRlQWRhcHRlcjtcbiAgICB0aGlzLl9kZWZhdWx0U1FMVHlwZUtleSA9ICdEQVRFJztcbiAgICB0aGlzLm1vbWVudFNydiA9IHRoaXMuaW5qZWN0b3IuZ2V0KE1vbWVudFNlcnZpY2UpO1xuICAgIHRoaXMubWVkaWEgPSB0aGlzLmluamVjdG9yLmdldChNZWRpYU9ic2VydmVyKTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmluaXRpYWxpemUoKTtcblxuICAgIGlmICghdGhpcy5vbG9jYWxlKSB7XG4gICAgICB0aGlzLnVwZGF0ZUxvY2FsZU9uQ2hhbmdlID0gdHJ1ZTtcbiAgICAgIHRoaXMub2xvY2FsZSA9IHRoaXMubW9tZW50U3J2LmdldExvY2FsZSgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9mb3JtYXQpIHtcbiAgICAgICh0aGlzLm1vbWVudERhdGVBZGFwdGVyIGFzIGFueSkub0Zvcm1hdCA9IHRoaXMub2Zvcm1hdDtcbiAgICB9XG5cbiAgICB0aGlzLm1vbWVudERhdGVBZGFwdGVyLnNldExvY2FsZSh0aGlzLm9sb2NhbGUpO1xuXG4gICAgaWYgKHRoaXMub1N0YXJ0Vmlldykge1xuICAgICAgdGhpcy5kYXRlcGlja2VyLnN0YXJ0VmlldyA9IHRoaXMub1N0YXJ0VmlldztcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vU3RhcnRBdCkge1xuICAgICAgdGhpcy5kYXRlcGlja2VyLnN0YXJ0QXQgPSBuZXcgRGF0ZSh0aGlzLm9TdGFydEF0KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy51cGRhdGVMb2NhbGVPbkNoYW5nZSkge1xuICAgICAgdGhpcy5vbkxhbmd1YWdlQ2hhbmdlU3Vic2NyaXB0aW9uID0gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLm9uTGFuZ3VhZ2VDaGFuZ2VkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMubW9tZW50RGF0ZUFkYXB0ZXIuc2V0TG9jYWxlKHRoaXMudHJhbnNsYXRlU2VydmljZS5nZXRDdXJyZW50TGFuZygpKTtcbiAgICAgICAgdGhpcy5zZXRWYWx1ZSh0aGlzLmdldFZhbHVlKCkpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5zdWJzY3JpYmVUb01lZGlhQ2hhbmdlcygpO1xuICB9XG5cbiAgcHVibGljIHN1YnNjcmliZVRvTWVkaWFDaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMubWVkaWFTdWJzY3JpcHRpb24gPSB0aGlzLm1lZGlhLmFzT2JzZXJ2YWJsZSgpLnN1YnNjcmliZSgoY2hhbmdlOiBNZWRpYUNoYW5nZVtdKSA9PiB7XG4gICAgICBpZiAoWyd4cycsICdzbSddLmluZGV4T2YoY2hhbmdlWzBdLm1xQWxpYXMpICE9PSAtMSkge1xuICAgICAgICB0aGlzLnRvdWNoVWkgPSBVdGlsLmlzRGVmaW5lZCh0aGlzLm9Ub3VjaFVpKSA/IHRoaXMub1RvdWNoVWkgOiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKFsnbWQnLCAnbGcnLCAneGwnXS5pbmRleE9mKGNoYW5nZVswXS5tcUFsaWFzKSAhPT0gLTEpIHtcbiAgICAgICAgdGhpcy50b3VjaFVpID0gVXRpbC5pc0RlZmluZWQodGhpcy5vVG91Y2hVaSkgPyB0aGlzLm9Ub3VjaFVpIDogZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgc3VwZXIubmdPbkRlc3Ryb3koKTtcbiAgICBpZiAodGhpcy5tZWRpYVN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5tZWRpYVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5vbkxhbmd1YWdlQ2hhbmdlU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLm9uTGFuZ3VhZ2VDaGFuZ2VTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0VmFsdWVBc0RhdGUoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5kYXRlVmFsdWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0VmFsdWUoKTogYW55IHtcbiAgICBsZXQgdGltZXN0YW1wVmFsdWUgPSBzdXBlci5nZXRWYWx1ZSgpO1xuICAgIGlmICh0aW1lc3RhbXBWYWx1ZSAmJiB0aW1lc3RhbXBWYWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgIHRpbWVzdGFtcFZhbHVlID0gdGltZXN0YW1wVmFsdWUuZ2V0VGltZSgpO1xuICAgIH1cbiAgICByZXR1cm4gdGltZXN0YW1wVmFsdWU7XG4gIH1cblxuICBnZXQgc2hvd0NsZWFyQnV0dG9uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNsZWFyQnV0dG9uICYmICF0aGlzLmlzUmVhZE9ubHkgJiYgdGhpcy5lbmFibGVkICYmIHRoaXMubWF0SW5wdXRSZWYubmF0aXZlRWxlbWVudC52YWx1ZTtcbiAgfVxuXG4gIHB1YmxpYyBvcGVuKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc1JlYWRPbmx5ICYmIHRoaXMuZW5hYmxlZCkge1xuICAgICAgdGhpcy5kYXRlcGlja2VyLm9wZW4oKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgY2xlYXJWYWx1ZShvcHRpb25zPzogRm9ybVZhbHVlT3B0aW9ucywgc2V0RGlydHk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIHN1cGVyLmNsZWFyVmFsdWUob3B0aW9ucywgc2V0RGlydHkpO1xuICAgIHRoaXMuZGF0ZVZhbHVlID0gdm9pZCAwO1xuICB9XG5cbiAgcHVibGljIG9uQ2hhbmdlRXZlbnQoZXZlbnQ6IE1hdERhdGVwaWNrZXJJbnB1dEV2ZW50PGFueT4pOiB2b2lkIHtcbiAgICBjb25zdCBpc1ZhbGlkID0gZXZlbnQudmFsdWUgJiYgZXZlbnQudmFsdWUuaXNWYWxpZCAmJiBldmVudC52YWx1ZS5pc1ZhbGlkKCk7XG4gICAgbGV0IHZhbCA9IGlzVmFsaWQgPyBldmVudC52YWx1ZS52YWx1ZU9mKCkgOiBldmVudC52YWx1ZTtcbiAgICBjb25zdCBwYXJzZWRWYWwgPSBVdGlsLnBhcnNlQnlWYWx1ZVR5cGUodmFsLCB0aGlzLnZhbHVlVHlwZSwgdGhpcy5vZm9ybWF0KTtcbiAgICB0aGlzLnNldFZhbHVlKHBhcnNlZFZhbCwge1xuICAgICAgY2hhbmdlVHlwZTogT1ZhbHVlQ2hhbmdlRXZlbnQuVVNFUl9DSEFOR0UsXG4gICAgICBlbWl0RXZlbnQ6IGZhbHNlLFxuICAgICAgZW1pdE1vZGVsVG9WaWV3Q2hhbmdlOiBmYWxzZVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG9uQ2xpY2tJbnB1dChlOiBFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy50ZXh0SW5wdXRFbmFibGVkKSB7XG4gICAgICB0aGlzLm9wZW4oKTtcbiAgICB9XG4gIH1cblxuICBnZXQgZmlsdGVyRGF0ZSgpOiBEYXRlRmlsdGVyRnVuY3Rpb24ge1xuICAgIHJldHVybiB0aGlzLl9maWx0ZXJEYXRlO1xuICB9XG5cbiAgc2V0IGZpbHRlckRhdGUodmFsOiBEYXRlRmlsdGVyRnVuY3Rpb24pIHtcbiAgICB0aGlzLl9maWx0ZXJEYXRlID0gdmFsO1xuICB9XG5cbiAgZ2V0IGRhdGVDbGFzcygpOiBEYXRlQ3VzdG9tQ2xhc3NGdW5jdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGVDbGFzcztcbiAgfVxuXG4gIHNldCBkYXRlQ2xhc3ModmFsOiBEYXRlQ3VzdG9tQ2xhc3NGdW5jdGlvbikge1xuICAgIHRoaXMuX2RhdGVDbGFzcyA9IHZhbDtcbiAgfVxuICBnZXQgb2Zvcm1hdCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9vZm9ybWF0O1xuICB9XG5cbiAgc2V0IG9mb3JtYXQodmFsOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9vZm9ybWF0ID0gdmFsO1xuICB9XG5cbiAgZ2V0IG1pbkRhdGVTdHJpbmcoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fbWluRGF0ZVN0cmluZztcbiAgfVxuXG4gIHNldCBtaW5EYXRlU3RyaW5nKHZhbDogc3RyaW5nKSB7XG4gICAgdGhpcy5fbWluRGF0ZVN0cmluZyA9IHZhbDtcbiAgfVxuXG4gIGdldCBtYXhEYXRlU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX21heERhdGVTdHJpbmc7XG4gIH1cblxuICBzZXQgbWF4RGF0ZVN0cmluZyh2YWw6IHN0cmluZykge1xuICAgIHRoaXMuX21heERhdGVTdHJpbmcgPSB2YWw7XG4gIH1cblxuICBnZXQgdG91Y2hVaSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5vVG91Y2hVaSB8fCBmYWxzZTtcbiAgfVxuXG4gIHNldCB0b3VjaFVpKHZhbDogYm9vbGVhbikge1xuICAgIHRoaXMub1RvdWNoVWkgPSB2YWw7XG4gICAgdGhpcy5kYXRlcGlja2VyLnRvdWNoVWkgPSB0aGlzLnRvdWNoVWk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZW5zdXJlT0RhdGVWYWx1ZVR5cGUodmFsOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoIVV0aWwuaXNEZWZpbmVkKHZhbCkpIHtcbiAgICAgIHJldHVybiB2YWw7XG4gICAgfVxuICAgIGxldCByZXN1bHQgPSB2YWw7XG4gICAgc3dpdGNoICh0aGlzLnZhbHVlVHlwZSkge1xuICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgY29uc3QgbSA9IG1vbWVudCh2YWwsIHRoaXMub2Zvcm1hdCk7XG4gICAgICAgICAgaWYgKG0uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGVWYWx1ZSA9IG5ldyBEYXRlKG0udmFsdWVPZigpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZGF0ZSc6XG4gICAgICAgIGlmICgodmFsIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICB0aGlzLmRhdGVWYWx1ZSA9IHZhbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0aW1lc3RhbXAnOlxuICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICB0aGlzLmRhdGVWYWx1ZSA9IG5ldyBEYXRlKHZhbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaXNvLTg2MDEnOlxuICAgICAgICBpZiAodHlwZW9mIHZhbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjb25zdCBhY2NlcHRUaW1lc3RhbXAgPSB0eXBlb2YgdmFsID09PSAnbnVtYmVyJyAmJiB0aGlzLmdldFNRTFR5cGUoKSA9PT0gU1FMVHlwZXMuVElNRVNUQU1QO1xuICAgICAgICAgIGlmIChhY2NlcHRUaW1lc3RhbXApIHtcbiAgICAgICAgICAgIHRoaXMuZGF0ZVZhbHVlID0gbmV3IERhdGUodmFsKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBtID0gbW9tZW50KHZhbCk7XG4gICAgICAgICAgaWYgKG0uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGVWYWx1ZSA9IG5ldyBEYXRlKG0udmFsdWVPZigpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBpZiAoIVV0aWwuaXNEZWZpbmVkKHJlc3VsdCkpIHtcbiAgICAgIGNvbnNvbGUud2FybihgT0RhdGVJbnB1dENvbXBvbmVudCB2YWx1ZSAoJHt2YWx9KSBpcyBub3QgY29uc2lzdGVudCB3aXRoIHZhbHVlLXR5cGUgKCR7dGhpcy52YWx1ZVR5cGV9KWApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldEZvcm1WYWx1ZSh2YWw6IGFueSwgb3B0aW9ucz86IEZvcm1WYWx1ZU9wdGlvbnMsIHNldERpcnR5OiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcbiAgICBsZXQgdmFsdWUgPSB2YWw7XG4gICAgaWYgKHZhbCBpbnN0YW5jZW9mIE9Gb3JtVmFsdWUpIHtcbiAgICAgIHZhbHVlID0gdmFsLnZhbHVlO1xuICAgIH1cbiAgICB0aGlzLmVuc3VyZU9EYXRlVmFsdWVUeXBlKHZhbHVlKTtcbiAgICBzdXBlci5zZXRGb3JtVmFsdWUodmFsdWUsIG9wdGlvbnMsIHNldERpcnR5KTtcbiAgfVxuXG4gIHNldCB2YWx1ZVR5cGUodmFsOiBhbnkpIHtcbiAgICB0aGlzLl92YWx1ZVR5cGUgPSBVdGlsLmNvbnZlcnRUb09EYXRlVmFsdWVUeXBlKHZhbCk7XG4gIH1cblxuICBnZXQgdmFsdWVUeXBlKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlVHlwZTtcbiAgfVxuXG4gIHB1YmxpYyBjcmVhdGVGb3JtQ29udHJvbChjZmcsIHZhbGlkYXRvcnMpOiBPRm9ybUNvbnRyb2wge1xuICAgIHRoaXMuX2ZDb250cm9sID0gc3VwZXIuY3JlYXRlRm9ybUNvbnRyb2woY2ZnLCB2YWxpZGF0b3JzKTtcbiAgICBpZiAoIXRoaXMuaXNFbXB0eSgpICYmICF0aGlzLmZvcm0uaXNJbkluc2VydE1v