ontimize-web-ngx
Version:
Ontimize Web framework using Angular 15
274 lines • 48.1 kB
JavaScript
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=