UNPKG

ontimize-web-ngx

Version:
274 lines 48.1 kB
import { __decorate, __metadata } from "tslib"; import { Component, ElementRef, forwardRef, Inject, Injector, NgZone, Optional, ViewChild, ViewEncapsulation } from '@angular/core'; import moment from 'moment'; import { NgxMaterialTimepickerComponent } from 'ngx-material-timepicker'; import { BooleanInputConverter, NumberConverter } from '../../../decorators/input-converter'; import { Codes } from '../../../util/codes'; import { Util } from '../../../util/util'; import { OValidators } from '../../../validators/o-validators'; 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 { Subject, take, takeUntil } from 'rxjs'; import * as i0 from "@angular/core"; import * as i1 from "@angular/flex-layout/flex"; import * as i2 from "@angular/forms"; import * as i3 from "../../../directives/o-mat-error.directive"; import * as i4 from "@angular/material/button"; import * as i5 from "@angular/material/icon"; import * as i6 from "@angular/material/input"; import * as i7 from "@angular/material/form-field"; import * as i8 from "@angular/material/tooltip"; import * as i9 from "@angular/common"; import * as i10 from "ngx-material-timepicker"; import * as i11 from "./o-hour-input.directive"; import * as i12 from "../../../pipes/o-translate.pipe"; import * as i13 from "../../form/o-form.component"; export const DEFAULT_INPUTS_O_HOUR_INPUT = [ 'format', 'textInputEnabled: text-input-enabled', 'min', 'max', 'valueType: value-type' ]; export class OHourInputComponent extends OFormDataComponent { constructor(form, elRef, injector) { super(form, elRef, injector); this.textInputEnabled = true; this._format = Codes.TWENTY_FOUR_HOUR_FORMAT; this.onKeyboardInputDone = false; this._valueType = 'timestamp'; this.destroy$ = new Subject(); this.skipNextBlur = false; this._defaultSQLTypeKey = 'TIMESTAMP'; } initialize() { super.initialize(); const formControl = this.getFormControl(); if (formControl) { const self = this; formControl.getValue = function () { return self.getValue(); }; } } ngAfterViewInit() { super.ngAfterViewInit(); this.modifyPickerMethods(); } ngOnDestroy() { this.pickerClosedSub?.unsubscribe(); } onKeyDown(e) { if (!Codes.isHourInputAllowed(e)) { e.preventDefault(); } } innerOnBlur(event) { if (this.skipNextBlur) { this.skipNextBlur = false; return; } if (this.onKeyboardInputDone) { this.updateValeOnInputChange(event); } super.innerOnBlur(event); } registerOnFormControlChange() { } get formatString() { return (this.format === Codes.TWENTY_FOUR_HOUR_FORMAT ? Codes.HourFormat.TWENTY_FOUR : Codes.HourFormat.TWELVE); } open(e) { if (Util.isDefined(e)) { e.stopPropagation(); } if (this.picker) { this.picker.open(); } } setTime(event) { event.preventDefault(); event.stopPropagation(); const value = super.getValue(); this.picker.updateTime(value); } setTimestampValue(value, options) { let parsedValue; const momentV = Util.isDefined(value) ? moment(value) : value; if (momentV && momentV.isValid()) { parsedValue = momentV.utcOffset(0).format(this.formatString); } this.setValue(parsedValue, options); } resolveValidators() { const validators = super.resolveValidators(); if (this.format === Codes.TWENTY_FOUR_HOUR_FORMAT) { validators.push(OValidators.twentyFourHourFormatValidator); } else { validators.push(OValidators.twelveHourFormatValidator); } return validators; } set format(val) { const old = this._format; let parsedVal = NumberConverter(val); if (parsedVal !== Codes.TWELVE_FOUR_HOUR_FORMAT && parsedVal !== Codes.TWENTY_FOUR_HOUR_FORMAT) { parsedVal = Codes.TWENTY_FOUR_HOUR_FORMAT; } this._format = parsedVal; if (parsedVal !== old) { this.updateValidators(); } } get format() { return this._format; } set valueType(val) { this._valueType = this.convertToOHourValueType(val); } get valueType() { return this._valueType; } convertToOHourValueType(val) { const result = 'string'; const lowerVal = (val || '').toLowerCase(); if (lowerVal === 'string' || lowerVal === 'timestamp') { return lowerVal; } return result; } onChangeEvent(arg) { this.onTimepickerChange(arg.target.value); } onTimepickerChange(event) { let value = event; if (Util.isDefined(value) && this.valueType === 'timestamp') { const valueTimestamp = moment(value, this.formatString).valueOf(); if (!isNaN(valueTimestamp)) { value = valueTimestamp; } } this.setValue(value, { changeType: OValueChangeEvent.USER_CHANGE, emitEvent: false, emitModelToViewChange: false }); } modifyPickerMethods() { if (this.picker && this.picker.inputElement) { this.picker.inputElement.addEventListener('change', () => { this.onKeyboardInputDone = true; }); } if (this.picker?.closed) { const zone = this.injector.get(NgZone); this.pickerClosedSub = this.picker.closed .pipe(takeUntil(this.destroy$)) .subscribe(() => { zone.onStable .pipe(take(1), takeUntil(this.destroy$)) .subscribe(() => { setTimeout(() => { this.skipNextBlur = true; const input = this.elRef.nativeElement.querySelector('input'); if (input && !this.isReadOnly && this.enabled !== false) { input.focus(); } }, 50); }); }); } } setFormValue(val, options, setDirty = false) { let stringValue = val; if (Util.isDefined(val) && this.valueType === 'timestamp') { let value = val instanceof OFormValue ? val.value : val; stringValue = this.getValueAsString(value); } this.ensureOFormValue(val); if (!this._fControl) { this._fControl = this.getControl(); } if (this._fControl) { this.updateOFormControlValue(stringValue, options, setDirty); } this.oldValue = this.value.value; } updateValeOnInputChange(blurEvent) { if (this.onKeyboardInputDone) { const value = this.parseHour(blurEvent.currentTarget.value); this.setValue(value); } this.onKeyboardInputDone = false; } parseHour(value) { const strArray = value.split(':'); let hour = strArray[0]; if (Codes.TWELVE_FOUR_HOUR_FORMAT === this.format) { if (hour) { hour = parseInt(hour, 10); const period = hour <= 12 ? ' AM' : ' PM'; if (hour > 12) { hour = hour - 12; } strArray[0] = hour; value = strArray.join(':') + period; } } else if (Codes.TWENTY_FOUR_HOUR_FORMAT === this.format) { } return value; } emitOnValueChange(type, newValue, oldValue) { this.onChange.emit(newValue); super.emitOnValueChange(type, newValue, oldValue); } getValueAsString(val) { let value; if (typeof val === 'number') { value = moment(val).format(this.formatString); } else { value = this.convertToFormatString(val); } return value; } convertToFormatString(value) { if (value === '00:00' || !Util.isDefined(value)) { return value; } const formatStr = this.format === Codes.TWENTY_FOUR_HOUR_FORMAT ? 'HH:mm' : 'hh:mm a'; let result; if (typeof value === 'number') { result = moment(value).format(formatStr); } else { result = value ? moment(value, 'h:mm A').format(formatStr) : value; } return result; } } OHourInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OHourInputComponent, deps: [{ token: forwardRef(() => OFormComponent), optional: true }, { token: i0.ElementRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); OHourInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OHourInputComponent, selector: "o-hour-input", inputs: { format: "format", textInputEnabled: ["text-input-enabled", "textInputEnabled"], min: "min", max: "max", valueType: ["value-type", "valueType"] }, host: { properties: { "class.o-hour-input": "true" } }, viewQueries: [{ propertyName: "picker", first: true, predicate: ["picker"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div fxLayout=\"row\" fxLayoutAlign=\"space-between center\" [formGroup]=\"getFormGroup()\" [matTooltip]=\"tooltip\" [matTooltipClass]=\"tooltipClass\"\n [matTooltipPosition]=\"tooltipPosition\" [matTooltipShowDelay]=\"tooltipShowDelay\" [matTooltipHideDelay]=\"tooltipHideDelay\">\n <mat-form-field [appearance]=\"appearance\" [floatLabel]=\"floatLabel\" fxFill [hideRequiredMarker]=\"hideRequiredMarker\" class=\"icon-field\"\n [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <input matInput [oNgxTimepicker]=\"picker\" [id]=\"getAttribute()\" [placeholder]=\"placeHolder\" [formControlName]=\"getAttribute()\"\n [readonly]=\"isReadOnly || !textInputEnabled\" (focus)=\"innerOnFocus($event)\" (blur)=\"innerOnBlur($event)\" [required]=\"isRequired\"\n (change)=\"onChangeEvent($event)\" [min]=\"min\" [max]=\"max\" (keydown)=\"onKeyDown($event)\" [format]=\"format\" [disableClick]=\"true\">\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 <button type=\"button\" matSuffix mat-icon-button [disabled]=\"isReadOnly || !enabled\" (click)=\"open($event)\">\n <mat-icon ngxMaterialTimepickerToggleIcon svgIcon=\"ontimize:clock\"></mat-icon>\n </button>\n\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('invalidFormatHour')\">\n {{ 'FORM_VALIDATION.HOUR_FORMAT' | oTranslate }} {{ formatString }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n</div>\n\n<ngx-material-timepicker #picker (timeSet)=\"onTimepickerChange($event)\" [confirmBtnTmpl]=\"confirmBtn\" [cancelBtnTmpl]=\"cancelBtn\">\n</ngx-material-timepicker>\n\n<ng-template #confirmBtn>\n <button mat-stroked-button type=\"button\"><span>{{'OK' | oTranslate}}</span></button>\n</ng-template>\n\n<ng-template #cancelBtn>\n <button mat-stroked-button type=\"button\"><span>{{'CANCEL' | oTranslate}}</span></button>\n</ng-template>\n", styles: ["ngx-material-timepicker-container button.mat-mdc-outlined-button{margin:0 6px}ngx-material-timepicker-container .timepicker-backdrop-overlay,ngx-material-timepicker-container .timepicker-overlay{z-index:1001!important}\n"], dependencies: [{ kind: "directive", type: i1.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: i1.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: i1.FlexFillDirective, selector: "[fxFill], [fxFlexFill]" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i3.OMatErrorDirective, selector: "[oMatError]", inputs: ["oMatError"] }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i6.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: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i9.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i9.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i10.NgxMaterialTimepickerComponent, selector: "ngx-material-timepicker", inputs: ["cancelBtnTmpl", "editableHintTmpl", "confirmBtnTmpl", "ESC", "enableKeyboardInput", "preventOverlayClick", "disableAnimation", "appendToInput", "hoursOnly", "defaultTime", "timepickerClass", "theme", "min", "max", "ngxMaterialTimepickerTheme", "format", "minutesGap"], outputs: ["timeSet", "opened", "closed", "hourSelected", "timeChanged"] }, { kind: "directive", type: i10.NgxMaterialTimepickerToggleIconDirective, selector: "[ngxMaterialTimepickerToggleIcon]" }, { kind: "directive", type: i11.OHourTimepickerDirective, selector: "[oNgxTimepicker]", inputs: ["oNgxTimepicker"] }, { kind: "pipe", type: i12.OTranslatePipe, name: "oTranslate" }], encapsulation: i0.ViewEncapsulation.None }); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], OHourInputComponent.prototype, "textInputEnabled", void 0); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OHourInputComponent, decorators: [{ type: Component, args: [{ selector: 'o-hour-input', encapsulation: ViewEncapsulation.None, inputs: DEFAULT_INPUTS_O_HOUR_INPUT, host: { '[class.o-hour-input]': 'true' }, template: "<div fxLayout=\"row\" fxLayoutAlign=\"space-between center\" [formGroup]=\"getFormGroup()\" [matTooltip]=\"tooltip\" [matTooltipClass]=\"tooltipClass\"\n [matTooltipPosition]=\"tooltipPosition\" [matTooltipShowDelay]=\"tooltipShowDelay\" [matTooltipHideDelay]=\"tooltipHideDelay\">\n <mat-form-field [appearance]=\"appearance\" [floatLabel]=\"floatLabel\" fxFill [hideRequiredMarker]=\"hideRequiredMarker\" class=\"icon-field\"\n [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <input matInput [oNgxTimepicker]=\"picker\" [id]=\"getAttribute()\" [placeholder]=\"placeHolder\" [formControlName]=\"getAttribute()\"\n [readonly]=\"isReadOnly || !textInputEnabled\" (focus)=\"innerOnFocus($event)\" (blur)=\"innerOnBlur($event)\" [required]=\"isRequired\"\n (change)=\"onChangeEvent($event)\" [min]=\"min\" [max]=\"max\" (keydown)=\"onKeyDown($event)\" [format]=\"format\" [disableClick]=\"true\">\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 <button type=\"button\" matSuffix mat-icon-button [disabled]=\"isReadOnly || !enabled\" (click)=\"open($event)\">\n <mat-icon ngxMaterialTimepickerToggleIcon svgIcon=\"ontimize:clock\"></mat-icon>\n </button>\n\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('invalidFormatHour')\">\n {{ 'FORM_VALIDATION.HOUR_FORMAT' | oTranslate }} {{ formatString }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n</div>\n\n<ngx-material-timepicker #picker (timeSet)=\"onTimepickerChange($event)\" [confirmBtnTmpl]=\"confirmBtn\" [cancelBtnTmpl]=\"cancelBtn\">\n</ngx-material-timepicker>\n\n<ng-template #confirmBtn>\n <button mat-stroked-button type=\"button\"><span>{{'OK' | oTranslate}}</span></button>\n</ng-template>\n\n<ng-template #cancelBtn>\n <button mat-stroked-button type=\"button\"><span>{{'CANCEL' | oTranslate}}</span></button>\n</ng-template>\n", styles: ["ngx-material-timepicker-container button.mat-mdc-outlined-button{margin:0 6px}ngx-material-timepicker-container .timepicker-backdrop-overlay,ngx-material-timepicker-container .timepicker-overlay{z-index:1001!important}\n"] }] }], ctorParameters: function () { return [{ type: i13.OFormComponent, decorators: [{ type: Optional }, { type: Inject, args: [forwardRef(() => OFormComponent)] }] }, { type: i0.ElementRef }, { type: i0.Injector }]; }, propDecorators: { textInputEnabled: [], picker: [{ type: ViewChild, args: ['picker'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiby1ob3VyLWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L2hvdXItaW5wdXQvby1ob3VyLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L2hvdXItaW5wdXQvby1ob3VyLWlucHV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQWlCLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFxQixRQUFRLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXRLLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFFN0YsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDL0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUN2RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUVyRSxPQUFPLEVBQUUsT0FBTyxF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SUFBSSxVQUM3QiwyQkFBMkIsUUFDN0I7d0JBQ0osc0JBQXNCLEVBQUUsTUFBTTtxQkFDL0I7OzBCQW9CRSxRQUFROzswQkFBSSxNQUFNOzJCQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxjQUFjLENBQUM7NEZBZi9DLGdCQUFnQixNQVFoQixNQUFNO3NCQURaLFNBQVM7dUJBQUMsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgZm9yd2FyZFJlZiwgSW5qZWN0LCBJbmplY3RvciwgTmdab25lLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3B0aW9uYWwsIFZpZXdDaGlsZCwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFZhbGlkYXRvckZuIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IG1vbWVudCBmcm9tICdtb21lbnQnO1xuaW1wb3J0IHsgTmd4TWF0ZXJpYWxUaW1lcGlja2VyQ29tcG9uZW50IH0gZnJvbSAnbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXInO1xuXG5pbXBvcnQgeyBCb29sZWFuSW5wdXRDb252ZXJ0ZXIsIE51bWJlckNvbnZlcnRlciB9IGZyb20gJy4uLy4uLy4uL2RlY29yYXRvcnMvaW5wdXQtY29udmVydGVyJztcbmltcG9ydCB7IEZvcm1WYWx1ZU9wdGlvbnMgfSBmcm9tICcuLi8uLi8uLi90eXBlcy9mb3JtLXZhbHVlLW9wdGlvbnMudHlwZSc7XG5pbXBvcnQgeyBDb2RlcyB9IGZyb20gJy4uLy4uLy4uL3V0aWwvY29kZXMnO1xuaW1wb3J0IHsgVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWwvdXRpbCc7XG5pbXBvcnQgeyBPVmFsaWRhdG9ycyB9IGZyb20gJy4uLy4uLy4uL3ZhbGlkYXRvcnMvby12YWxpZGF0b3JzJztcbmltcG9ydCB7IE9Gb3JtVmFsdWUgfSBmcm9tICcuLi8uLi9mb3JtL28tZm9ybS12YWx1ZSc7XG5pbXBvcnQgeyBPRm9ybUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2Zvcm0vby1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBPRm9ybURhdGFDb21wb25lbnQgfSBmcm9tICcuLi8uLi9vLWZvcm0tZGF0YS1jb21wb25lbnQuY2xhc3MnO1xuaW1wb3J0IHsgT1ZhbHVlQ2hhbmdlRXZlbnQgfSBmcm9tICcuLi8uLi9vLXZhbHVlLWNoYW5nZS1ldmVudC5jbGFzcyc7XG5pbXBvcnQgeyBPRm9ybUNvbnRyb2wgfSBmcm9tICcuLi9vLWZvcm0tY29udHJvbC5jbGFzcyc7XG5pbXBvcnQgeyBTdWJqZWN0LCBTdWJzY3JpcHRpb24sIHRha2UsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuXG5leHBvcnQgdHlwZSBPSG91clZhbHVlVHlwZSA9ICdzdHJpbmcnIHwgJ3RpbWVzdGFtcCc7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0lOUFVUU19PX0hPVVJfSU5QVVQgPSBbXG4gICdmb3JtYXQnLFxuICAndGV4dElucHV0RW5hYmxlZDogdGV4dC1pbnB1dC1lbmFibGVkJyxcbiAgJ21pbicsXG4gICdtYXgnLFxuICAndmFsdWVUeXBlOiB2YWx1ZS10eXBlJ1xuXTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnby1ob3VyLWlucHV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL28taG91ci1pbnB1dC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL28taG91ci1pbnB1dC5jb21wb25lbnQuc2NzcyddLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBpbnB1dHM6IERFRkFVTFRfSU5QVVRTX09fSE9VUl9JTlBVVCxcbiAgaG9zdDoge1xuICAgICdbY2xhc3Muby1ob3VyLWlucHV0XSc6ICd0cnVlJ1xuICB9XG59KVxuZXhwb3J0IGNsYXNzIE9Ib3VySW5wdXRDb21wb25lbnQgZXh0ZW5kcyBPRm9ybURhdGFDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG5cbiAgQEJvb2xlYW5JbnB1dENvbnZlcnRlcigpXG4gIHB1YmxpYyB0ZXh0SW5wdXRFbmFibGVkOiBib29sZWFuID0gdHJ1ZTtcbiAgcHVibGljIG1pbjogc3RyaW5nO1xuICBwdWJsaWMgbWF4OiBzdHJpbmc7XG4gIHByb3RlY3RlZCBfZm9ybWF0OiBudW1iZXIgPSBDb2Rlcy5UV0VOVFlfRk9VUl9IT1VSX0ZPUk1BVDtcbiAgcHJvdGVjdGVkIG9uS2V5Ym9hcmRJbnB1dERvbmUgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIF92YWx1ZVR5cGU6IE9Ib3VyVmFsdWVUeXBlID0gJ3RpbWVzdGFtcCc7XG5cbiAgQFZpZXdDaGlsZCgncGlja2VyJylcbiAgcHVibGljIHBpY2tlcjogTmd4TWF0ZXJpYWxUaW1lcGlja2VyQ29tcG9uZW50O1xuXG4gIHByaXZhdGUgcGlja2VyQ2xvc2VkU3ViPzogU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSBza2lwTmV4dEJsdXIgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gT0Zvcm1Db21wb25lbnQpKSBmb3JtOiBPRm9ybUNvbXBvbmVudCxcbiAgICBlbFJlZjogRWxlbWVudFJlZixcbiAgICBpbmplY3RvcjogSW5qZWN0b3JcbiAgKSB7XG4gICAgc3VwZXIoZm9ybSwgZWxSZWYsIGluamVjdG9yKTtcbiAgICB0aGlzLl9kZWZhdWx0U1FMVHlwZUtleSA9ICdUSU1FU1RBTVAnO1xuICB9XG5cbiAgaW5pdGlhbGl6ZSgpOiB2b2lkIHtcbiAgICBzdXBlci5pbml0aWFsaXplKCk7XG4gICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmdldEZvcm1Db250cm9sKCkgYXMgT0Zvcm1Db250cm9sO1xuICAgIGlmIChmb3JtQ29udHJvbCkge1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICBmb3JtQ29udHJvbC5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHNlbGYuZ2V0VmFsdWUoKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBzdXBlci5uZ0FmdGVyVmlld0luaXQoKTtcbiAgICB0aGlzLm1vZGlmeVBpY2tlck1ldGhvZHMoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMucGlja2VyQ2xvc2VkU3ViPy51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHVibGljIG9uS2V5RG93bihlOiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCFDb2Rlcy5pc0hvdXJJbnB1dEFsbG93ZWQoZSkpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgaW5uZXJPbkJsdXIoZXZlbnQ6IGFueSk6IHZvaWQge1xuICAgIC8vIFNraXAgdGhpcyBibHVyIGV2ZW50IGlmIGl0IGhhcHBlbnMgcmlnaHQgYWZ0ZXIgdGhlIHBpY2tlciBjbG9zZXNcbiAgICBpZiAodGhpcy5za2lwTmV4dEJsdXIpIHtcbiAgICAgIHRoaXMuc2tpcE5leHRCbHVyID0gZmFsc2U7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub25LZXlib2FyZElucHV0RG9uZSkge1xuICAgICAgdGhpcy51cGRhdGVWYWxlT25JbnB1dENoYW5nZShldmVudCk7XG4gICAgfVxuICAgIHN1cGVyLmlubmVyT25CbHVyKGV2ZW50KTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3Rlck9uRm9ybUNvbnRyb2xDaGFuZ2UoKTogdm9pZCB7XG4gICAgLy8gVGhpcyBjb21wb25lbnQgZG9lcyBub3QgbmVlZCB0aGlzIHN1YnNjcmlwdGlvblxuICB9XG5cbiAgZ2V0IGZvcm1hdFN0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiAodGhpcy5mb3JtYXQgPT09IENvZGVzLlRXRU5UWV9GT1VSX0hPVVJfRk9STUFUID8gQ29kZXMuSG91ckZvcm1hdC5UV0VOVFlfRk9VUiA6IENvZGVzLkhvdXJGb3JtYXQuVFdFTFZFKTtcbiAgfVxuXG4gIHB1YmxpYyBvcGVuKGU/OiBFdmVudCk6IHZvaWQge1xuICAgIGlmIChVdGlsLmlzRGVmaW5lZChlKSkge1xuICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucGlja2VyKSB7XG4gICAgICB0aGlzLnBpY2tlci5vcGVuKCk7XG4gICAgfVxuICB9XG5cbiAgc2V0VGltZShldmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgLy8gZ2V0dGluZyB2YWx1ZSBmcm9tIHN1cGVyIHNvIHdlIGNhbiBhbHdheXMgZ2V0IGEgc3RyaW5nIHZhbHVlXG4gICAgY29uc3QgdmFsdWUgPSBzdXBlci5nZXRWYWx1ZSgpO1xuICAgIHRoaXMucGlja2VyLnVwZGF0ZVRpbWUodmFsdWUpO1xuICB9XG5cbiAgcHVibGljIHNldFRpbWVzdGFtcFZhbHVlKHZhbHVlOiBhbnksIG9wdGlvbnM/OiBGb3JtVmFsdWVPcHRpb25zKTogdm9pZCB7XG4gICAgbGV0IHBhcnNlZFZhbHVlO1xuICAgIGNvbnN0IG1vbWVudFYgPSBVdGlsLmlzRGVmaW5lZCh2YWx1ZSkgPyBtb21lbnQodmFsdWUpIDogdmFsdWU7XG4gICAgaWYgKG1vbWVudFYgJiYgbW9tZW50Vi5pc1ZhbGlkKCkpIHtcbiAgICAgIHBhcnNlZFZhbHVlID0gbW9tZW50Vi51dGNPZmZzZXQoMCkuZm9ybWF0KHRoaXMuZm9ybWF0U3RyaW5nKTtcbiAgICB9XG4gICAgdGhpcy5zZXRWYWx1ZShwYXJzZWRWYWx1ZSwgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgcmVzb2x2ZVZhbGlkYXRvcnMoKTogVmFsaWRhdG9yRm5bXSB7XG4gICAgY29uc3QgdmFsaWRhdG9yczogVmFsaWRhdG9yRm5bXSA9IHN1cGVyLnJlc29sdmVWYWxpZGF0b3JzKCk7XG4gICAgaWYgKHRoaXMuZm9ybWF0ID09PSBDb2Rlcy5UV0VOVFlfRk9VUl9IT1VSX0ZPUk1BVCkge1xuICAgICAgdmFsaWRhdG9ycy5wdXNoKE9WYWxpZGF0b3JzLnR3ZW50eUZvdXJIb3VyRm9ybWF0VmFsaWRhdG9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsaWRhdG9ycy5wdXNoKE9WYWxpZGF0b3JzLnR3ZWx2ZUhvdXJGb3JtYXRWYWxpZGF0b3IpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsaWRhdG9ycztcbiAgfVxuXG4gIHNldCBmb3JtYXQodmFsOiBudW1iZXIpIHtcbiAgICBjb25zdCBvbGQgPSB0aGlzLl9mb3JtYXQ7XG4gICAgbGV0IHBhcnNlZFZhbCA9IE51bWJlckNvbnZlcnRlcih2YWwpO1xuICAgIGlmIChwYXJzZWRWYWwgIT09IENvZGVzLlRXRUxWRV9GT1VSX0hPVVJfRk9STUFUICYmIHBhcnNlZFZhbCAhPT0gQ29kZXMuVFdFTlRZX0ZPVVJfSE9VUl9GT1JNQVQpIHtcbiAgICAgIHBhcnNlZFZhbCA9IENvZGVzLlRXRU5UWV9GT1VSX0hPVVJfRk9STUFUO1xuICAgIH1cbiAgICB0aGlzLl9mb3JtYXQgPSBwYXJzZWRWYWw7XG4gICAgaWYgKHBhcnNlZFZhbCAhPT0gb2xkKSB7XG4gICAgICB0aGlzLnVwZGF0ZVZhbGlkYXRvcnMoKTtcbiAgICB9XG4gIH1cblxuICBnZXQgZm9ybWF0KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2Zvcm1hdDtcbiAgfVxuXG4gIHNldCB2YWx1ZVR5cGUodmFsOiBhbnkpIHtcbiAgICB0aGlzLl92YWx1ZVR5cGUgPSB0aGlzLmNvbnZlcnRUb09Ib3VyVmFsdWVUeXBlKHZhbCk7XG4gIH1cblxuICBnZXQgdmFsdWVUeXBlKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlVHlwZTtcbiAgfVxuXG4gIHB1YmxpYyBjb252ZXJ0VG9PSG91clZhbHVlVHlwZSh2YWw6IGFueSk6IE9Ib3VyVmFsdWVUeXBlIHtcbiAgICBjb25zdCByZXN1bHQ6IE9Ib3VyVmFsdWVUeXBlID0gJ3N0cmluZyc7XG4gICAgY29uc3QgbG93ZXJWYWwgPSAodmFsIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmIChsb3dlclZhbCA9PT0gJ3N0cmluZycgfHwgbG93ZXJWYWwgPT09ICd0aW1lc3RhbXAnKSB7XG4gICAgICByZXR1cm4gbG93ZXJWYWw7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwdWJsaWMgb25DaGFuZ2VFdmVudChhcmc6IGFueSk6IHZvaWQge1xuICAgIHRoaXMub25UaW1lcGlja2VyQ2hhbmdlKGFyZy50YXJnZXQudmFsdWUpO1xuICB9XG5cbiAgcHVibGljIG9uVGltZXBpY2tlckNoYW5nZShldmVudDogc3RyaW5nKTogdm9pZCB7XG4gICAgbGV0IHZhbHVlOiBhbnkgPSBldmVudDtcbiAgICBpZiAoVXRpbC5pc0RlZmluZWQodmFsdWUpICYmIHRoaXMudmFsdWVUeXBlID09PSAndGltZXN0YW1wJykge1xuICAgICAgY29uc3QgdmFsdWVUaW1lc3RhbXAgPSBtb21lbnQodmFsdWUsIHRoaXMuZm9ybWF0U3RyaW5nKS52YWx1ZU9mKCk7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlVGltZXN0YW1wKSkge1xuICAgICAgICB2YWx1ZSA9IHZhbHVlVGltZXN0YW1wO1xuICAgICAgfVxuICAgIH1cbiAgICAvKiogZW1pdE1vZGVsVG9WaWV3Q2hhbmdlOiBmYWxzZSAgYmVjYXVzZSBvbkNoYW5nZSBldmVudCBpcyB0cmlnZ2VyIGluIG5nTW9kZWxDaGFuZ2UgKi9cbiAgICB0aGlzLnNldFZhbHVlKHZhbHVlLCB7XG4gICAgICBjaGFuZ2VUeXBlOiBPVmFsdWVDaGFuZ2VFdmVudC5VU0VSX0NIQU5HRSxcbiAgICAgIGVtaXRFdmVudDogZmFsc2UsXG4gICAgICBlbWl0TW9kZWxUb1ZpZXdDaGFuZ2U6IGZhbHNlXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgbW9kaWZ5UGlja2VyTWV0aG9kcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5waWNrZXIgJiYgdGhpcy5waWNrZXIuaW5wdXRFbGVtZW50KSB7XG4gICAgICB0aGlzLnBpY2tlci5pbnB1dEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKCkgPT4ge1xuICAgICAgICB0aGlzLm9uS2V5Ym9hcmRJbnB1dERvbmUgPSB0cnVlO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucGlja2VyPy5jbG9zZWQpIHtcbiAgICAgIGNvbnN0IHpvbmUgPSB0aGlzLmluamVjdG9yLmdldChOZ1pvbmUpO1xuICAgICAgdGhpcy5waWNrZXJDbG9zZWRTdWIgPSB0aGlzLnBpY2tlci5jbG9zZWRcbiAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAvLyBXYWl0IHVudGlsIEFuZ3VsYXIgZmluaXNoZXMgc3RhYmlsaXppbmcgdGhlIHZpZXdcbiAgICAgICAgICB6b25lLm9uU3RhYmxlXG4gICAgICAgICAgICAucGlwZSh0YWtlKDEpLCB0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gUHJldmVudCB0aGUgaW1tZWRpYXRlIGJsdXIgZXZlbnQgZnJvbSByZW1vdmluZyBmb2N1c1xuICAgICAgICAgICAgICAgIHRoaXMuc2tpcE5leHRCbHVyID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGlucHV0OiBIVE1MSW5wdXRFbGVtZW50ID0gdGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ2lucHV0Jyk7XG5cbiAgICAgICAgICAgICAgICAvLyBGb2N1cyB0aGUgaW5wdXQgb25seSBpZiBpdCBpcyBhdmFpbGFibGUsIG5vdCByZWFkb25seSwgYW5kIGVuYWJsZWRcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQgJiYgIXRoaXMuaXNSZWFkT25seSAmJiB0aGlzLmVuYWJsZWQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICBpbnB1dC5mb2N1cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSwgNTApOyAvLyBzbWFsbCBkZWxheSB0byBlbnN1cmUgb3ZlcmxheSBpcyBmdWxseSBjbG9zZWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0Rm9ybVZhbHVlKHZhbDogYW55LCBvcHRpb25zPzogRm9ybVZhbHVlT3B0aW9ucywgc2V0RGlydHk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIGxldCBzdHJpbmdWYWx1ZSA9IHZhbDtcbiAgICBpZiAoVXRpbC5pc0RlZmluZWQodmFsKSAmJiB0aGlzLnZhbHVlVHlwZSA9PT0gJ3RpbWVzdGFtcCcpIHtcbiAgICAgIC8vIGJlY2F1c2Ugb2YgdGhlIG5neC1tYXRlcmlhbC10aW1lcGlja2VyIGVzcGVjaWZpY2F0aW9uLCBpdHMgc3RvcmVkIHZhbHVlIG11c3QgYmUgYWx3YXlzIGEgc3RyaW5nXG4gICAgICBsZXQgdmFsdWUgPSB2YWwgaW5zdGFuY2VvZiBPRm9ybVZhbHVlID8gdmFsLnZhbHVlIDogdmFsO1xuICAgICAgc3RyaW5nVmFsdWUgPSB0aGlzLmdldFZhbHVlQXNTdHJpbmcodmFsdWUpO1xuICAgIH1cblxuICAgIHRoaXMuZW5zdXJlT0Zvcm1WYWx1ZSh2YWwpO1xuICAgIGlmICghdGhpcy5fZkNvbnRyb2wpIHtcbiAgICAgIC8vIGVuc3VyaW5nIF9mQ29udHJvbCBjcmVhdGlvblxuICAgICAgdGhpcy5fZkNvbnRyb2wgPSB0aGlzLmdldENvbnRyb2woKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2ZDb250cm9sKSB7XG4gICAgICB0aGlzLnVwZGF0ZU9Gb3JtQ29udHJvbFZhbHVlKHN0cmluZ1ZhbHVlLCBvcHRpb25zLCBzZXREaXJ0eSk7XG4gICAgfVxuICAgIHRoaXMub2xkVmFsdWUgPSB0aGlzLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvdGVjdGVkIHVwZGF0ZVZhbGVPbklucHV0Q2hhbmdlKGJsdXJFdmVudDogYW55KTogdm9pZCB7XG4gICAgaWYgKHRoaXMub25LZXlib2FyZElucHV0RG9uZSkge1xuICAgICAgLy8gbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXIgZG9lcyBub3QgYWxsb3cgd3JpdGluZyBjaGFyYWN0ZXJzIG9uIGlucHV0LCBzbyB3ZSBhZGQgJ0FNL1BNJyBpbiBvcmRlciB0byBtYWtlIHZhbGlkYXRpb24gd29yayBwcm9wZXJseVxuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnBhcnNlSG91cihibHVyRXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgICB0aGlzLnNldFZhbHVlKHZhbHVlKTtcbiAgICB9XG4gICAgdGhpcy5vbktleWJvYXJkSW5wdXREb25lID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmVjZWl2ZXMgYW4gaG91ciBpbnB1dCBpbnRyb2R1Y2VkIGJ5IHRoZSB1c2VyIGFuZCByZXR1cm5zIHRoZSBob3VyIGZvcm1hdGVkIGFjb3JkaW5nIGN1cnJlbnQgZm9ybWF0XG4gICAqIEBwYXJhbSB2YWx1ZVxuICAgKi9cbiAgcHJvdGVjdGVkIHBhcnNlSG91cih2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdHJBcnJheSA9IHZhbHVlLnNwbGl0KCc6Jyk7XG4gICAgbGV0IGhvdXI6IGFueSA9IHN0ckFycmF5WzBdO1xuXG4gICAgaWYgKENvZGVzLlRXRUxWRV9GT1VSX0hPVVJfRk9STUFUID09PSB0aGlzLmZvcm1hdCkge1xuICAgICAgaWYgKGhvdXIpIHtcbiAgICAgICAgaG91ciA9IHBhcnNlSW50KGhvdXIsIDEwKTtcbiAgICAgICAgY29uc3QgcGVyaW9kID0gaG91ciA8PSAxMiA/ICcgQU0nIDogJyBQTSc7XG4gICAgICAgIGlmIChob3VyID4gMTIpIHtcbiAgICAgICAgICBob3VyID0gaG91ciAtIDEyO1xuICAgICAgICB9XG4gICAgICAgIHN0ckFycmF5WzBdID0gaG91cjtcbiAgICAgICAgdmFsdWUgPSBzdHJBcnJheS5qb2luKCc6JykgKyBwZXJpb2Q7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChDb2Rlcy5UV0VOVFlfRk9VUl9IT1VSX0ZPUk1BVCA9PT0gdGhpcy5mb3JtYXQpIHtcbiAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvdGVjdGVkIGVtaXRPblZhbHVlQ2hhbmdlKHR5cGUsIG5ld1ZhbHVlLCBvbGRWYWx1ZSk6IHZvaWQge1xuICAgIHRoaXMub25DaGFuZ2UuZW1pdChuZXdWYWx1ZSk7XG4gICAgc3VwZXIuZW1pdE9uVmFsdWVDaGFuZ2UodHlwZSwgbmV3VmFsdWUsIG9sZFZhbHVlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRWYWx1ZUFzU3RyaW5nKHZhbDogYW55KTogc3RyaW5nIHtcbiAgICBsZXQgdmFsdWU7XG4gICAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgICB2YWx1ZSA9IG1vbWVudCh2YWwpLmZvcm1hdCh0aGlzLmZvcm1hdFN0cmluZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlID0gdGhpcy5jb252ZXJ0VG9Gb3JtYXRTdHJpbmcodmFsKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbnZlcnRUb0Zvcm1hdFN0cmluZyh2YWx1ZSk6IHN0cmluZyB7XG4gICAgaWYgKHZhbHVlID09PSAnMDA6MDAnIHx8ICFVdGlsLmlzRGVmaW5lZCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgY29uc3QgZm9ybWF0U3RyID0gdGhpcy5mb3JtYXQgPT09IENvZGVzLlRXRU5UWV9GT1VSX0hPVVJfRk9STUFUID8gJ0hIOm1tJyA6ICdoaDptbSBhJztcbiAgICBsZXQgcmVzdWx0O1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICByZXN1bHQgPSBtb21lbnQodmFsdWUpLmZvcm1hdChmb3JtYXRTdHIpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgPSB2YWx1ZSA/IG1vbWVudCh2YWx1ZSwgJ2g6bW0gQScpLmZvcm1hdChmb3JtYXRTdHIpIDogdmFsdWU7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cbiIsIjxkaXYgZnhMYXlvdXQ9XCJyb3dcIiBmeExheW91dEFsaWduPVwic3BhY2UtYmV0d2VlbiBjZW50ZXJcIiBbZm9ybUdyb3VwXT1cImdldEZvcm1Hcm91cCgpXCIgW21hdFRvb2x0aXBdPVwidG9vbHRpcFwiIFttYXRUb29sdGlwQ2xhc3NdPVwidG9vbHRpcENsYXNzXCJcbiAgW21hdFRvb2x0aXBQb3NpdGlvbl09XCJ0b29sdGlwUG9zaXRpb25cIiBbbWF0VG9vbHRpcFNob3dEZWxheV09XCJ0b29sdGlwU2hvd0RlbGF5XCIgW21hdFRvb2x0aXBIaWRlRGVsYXldPVwidG9vbHRpcEhpZGVEZWxheVwiPlxuICA8bWF0LWZvcm0tZmllbGQgW2FwcGVhcmFuY2VdPVwiYXBwZWFyYW5jZVwiIFtmbG9hdExhYmVsXT1cImZsb2F0TGFiZWxcIiBmeEZpbGwgW2hpZGVSZXF1aXJlZE1hcmtlcl09XCJoaWRlUmVxdWlyZWRNYXJrZXJcIiBjbGFzcz1cImljb24tZmllbGRcIlxuICAgIFtzdWJzY3JpcHRTaXppbmddPVwic3Vic2NyaXB0U2l6aW5nXCI+XG4gICAgPG1hdC1sYWJlbCAqbmdJZj1cImxhYmVsVmlzaWJsZVwiPnt7IG9sYWJlbCB8IG9UcmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICA8aW5wdXQgbWF0SW5wdXQgW29OZ3hUaW1lcGlja2VyXT1cInBpY2tlclwiIFtpZF09XCJnZXRBdHRyaWJ1dGUoKVwiIFtwbGFjZWhvbGRlcl09XCJwbGFjZUhvbGRlclwiIFtmb3JtQ29udHJvbE5hbWVdPVwiZ2V0QXR0cmlidXRlKClcIlxuICAgICAgW3JlYWRvbmx5XT1cImlzUmVhZE9ubHkgfHwgIXRleHRJbnB1dEVuYWJsZWRcIiAoZm9jdXMpPVwiaW5uZXJPbkZvY3VzKCRldmVudClcIiAoYmx1cik9XCJpbm5lck9uQmx1cigkZXZlbnQpXCIgW3JlcXVpcmVkXT1cImlzUmVxdWlyZWRcIlxuICAgICAgKGNoYW5nZSk9XCJvbkNoYW5nZUV2ZW50KCRldmVudClcIiBbbWluXT1cIm1pblwiIFttYXhdPVwibWF4XCIgKGtleWRvd24pPVwib25LZXlEb3duKCRldmVudClcIiBbZm9ybWF0XT1cImZvcm1hdFwiIFtkaXNhYmxlQ2xpY2tdPVwidHJ1ZVwiPlxuXG4gICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKm5nSWY9XCJzaG93Q2xlYXJCdXR0b25cIiBtYXRTdWZmaXggbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJvbkNsaWNrQ2xlYXJWYWx1ZSgkZXZlbnQpXCI+XG4gICAgICA8bWF0LWljb24gc3ZnSWNvbj1cIm9udGltaXplOmNsb3NlXCI+PC9tYXQtaWNvbj5cbiAgICA8L2J1dHRvbj5cbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBtYXRTdWZmaXggbWF0LWljb24tYnV0dG9uIFtkaXNhYmxlZF09XCJpc1JlYWRPbmx5IHx8ICFlbmFibGVkXCIgKGNsaWNrKT1cIm9wZW4oJGV2ZW50KVwiPlxuICAgICAgPG1hdC1pY29uIG5neE1hdGVyaWFsVGltZXBpY2tlclRvZ2dsZUljb24gc3ZnSWNvbj1cIm9udGltaXplOmNsb2NrXCI+PC9tYXQtaWNvbj5cbiAgICA8L2J1dHRvbj5cblxuICAgIDxtYXQtZXJyb3IgKm9NYXRFcnJvcj1cImhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICB7eyAnRk9STV9WQUxJREFUSU9OLlJFUVVJUkVEJyB8IG9UcmFuc2xhdGUgfX1cbiAgICA8L21hdC1lcnJvcj5cbiAgICA8bWF0LWVycm9yICpvTWF0RXJyb3I9XCJoYXNFcnJvcignaW52YWxpZEZvcm1hdEhvdXInKVwiPlxuICAgICAge3sgJ0ZPUk1fVkFMSURBVElPTi5IT1VSX0ZPUk1BVCcgfCBvVHJhbnNsYXRlIH19IHt7IGZvcm1hdFN0cmluZyB9fVxuICAgIDwvbWF0LWVycm9yPlxuICAgIDxtYXQtZXJyb3IgKm5nRm9yPVwibGV0IG9FcnJvciBvZiBnZXRBY3RpdmVPRXJyb3JzKClcIj5cbiAgICAgIHt7IG9FcnJvci50ZXh0IHwgb1RyYW5zbGF0ZSB9fVxuICAgIDwvbWF0LWVycm9yPlxuICA8L21hdC1mb3JtLWZpZWxkPlxuPC9kaXY+XG5cbjxuZ3gtbWF0ZXJpYWwtdGltZXBpY2tlciAjcGlja2VyICh0aW1lU2V0KT1cIm9uVGltZXBpY2tlckNoYW5nZSgkZXZlbnQpXCIgW2NvbmZpcm1CdG5UbXBsXT1cImNvbmZpcm1CdG5cIiBbY2FuY2VsQnRuVG1wbF09XCJjYW5jZWxCdG5cIj5cbjwvbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXI+XG5cbjxuZy10ZW1wbGF0ZSAjY29uZmlybUJ0bj5cbiAgPGJ1dHRvbiBtYXQtc3Ryb2tlZC1idXR0b24gdHlwZT1cImJ1dHRvblwiPjxzcGFuPnt7J09LJyB8IG9UcmFuc2xhdGV9fTwvc3Bhbj48L2J1dHRvbj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjY2FuY2VsQnRuPlxuICA8YnV0dG9uIG1hdC1zdHJva2VkLWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCI+PHNwYW4+e3snQ0FOQ0VMJyB8IG9UcmFuc2xhdGV9fTwvc3Bhbj48L2J1dHRvbj5cbjwvbmctdGVtcGxhdGU+XG4iXX0=