ontimize-web-ngx
Version:
Ontimize Web framework using Angular 15
245 lines • 43.8 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Component, ElementRef, forwardRef, Inject, Injector, 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 * 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 "../../../pipes/o-translate.pipe";
import * as i12 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._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();
}
onKeyDown(e) {
if (!Codes.isHourInputAllowed(e)) {
e.preventDefault();
}
}
innerOnBlur(event) {
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;
});
}
}
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 [ngxTimepicker]=\"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: ["ESC", "hoursOnly", "ngxMaterialTimepickerTheme", "format", "minutesGap", "cancelBtnTmpl", "editableHintTmpl", "confirmBtnTmpl", "enableKeyboardInput", "preventOverlayClick", "disableAnimation", "appendToInput", "defaultTime", "timepickerClass", "theme"], outputs: ["timeSet", "opened", "closed", "hourSelected", "timeChanged"] }, { kind: "directive", type: i10.TimepickerDirective, selector: "[ngxTimepicker]", inputs: ["format", "value", "min", "max", "ngxTimepicker", "disabled", "disableClick"] }, { kind: "directive", type: i10.NgxMaterialTimepickerToggleIconDirective, selector: "[ngxMaterialTimepickerToggleIcon]" }, { kind: "pipe", type: i11.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 [ngxTimepicker]=\"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: i12.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiby1ob3VyLWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L2hvdXItaW5wdXQvby1ob3VyLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L2hvdXItaW5wdXQvby1ob3VyLWlucHV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQWlCLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQVUsUUFBUSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuSixPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFekUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBRTdGLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQy9ELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDdkUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7Ozs7Ozs7Ozs7Ozs7O0FBS3JFLE1BQU0sQ0FBQyxNQUFN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QU07MkJBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGNBQWMsQ0FBQzs0RkFYL0MsZ0JBQWdCLE1BUWhCLE1BQU07c0JBRFosU0FBUzt1QkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBmb3J3YXJkUmVmLCBJbmplY3QsIEluamVjdG9yLCBPbkluaXQsIE9wdGlvbmFsLCBWaWV3Q2hpbGQsIFZpZXdFbmNhcHN1bGF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBWYWxpZGF0b3JGbiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IE5neE1hdGVyaWFsVGltZXBpY2tlckNvbXBvbmVudCB9IGZyb20gJ25neC1tYXRlcmlhbC10aW1lcGlja2VyJztcblxuaW1wb3J0IHsgQm9vbGVhbklucHV0Q29udmVydGVyLCBOdW1iZXJDb252ZXJ0ZXIgfSBmcm9tICcuLi8uLi8uLi9kZWNvcmF0b3JzL2lucHV0LWNvbnZlcnRlcic7XG5pbXBvcnQgeyBGb3JtVmFsdWVPcHRpb25zIH0gZnJvbSAnLi4vLi4vLi4vdHlwZXMvZm9ybS12YWx1ZS1vcHRpb25zLnR5cGUnO1xuaW1wb3J0IHsgQ29kZXMgfSBmcm9tICcuLi8uLi8uLi91dGlsL2NvZGVzJztcbmltcG9ydCB7IFV0aWwgfSBmcm9tICcuLi8uLi8uLi91dGlsL3V0aWwnO1xuaW1wb3J0IHsgT1ZhbGlkYXRvcnMgfSBmcm9tICcuLi8uLi8uLi92YWxpZGF0b3JzL28tdmFsaWRhdG9ycyc7XG5pbXBvcnQgeyBPRm9ybVZhbHVlIH0gZnJvbSAnLi4vLi4vZm9ybS9vLWZvcm0tdmFsdWUnO1xuaW1wb3J0IHsgT0Zvcm1Db21wb25lbnQgfSBmcm9tICcuLi8uLi9mb3JtL28tZm9ybS5jb21wb25lbnQnO1xuaW1wb3J0IHsgT0Zvcm1EYXRhQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vby1mb3JtLWRhdGEtY29tcG9uZW50LmNsYXNzJztcbmltcG9ydCB7IE9WYWx1ZUNoYW5nZUV2ZW50IH0gZnJvbSAnLi4vLi4vby12YWx1ZS1jaGFuZ2UtZXZlbnQuY2xhc3MnO1xuaW1wb3J0IHsgT0Zvcm1Db250cm9sIH0gZnJvbSAnLi4vby1mb3JtLWNvbnRyb2wuY2xhc3MnO1xuXG5leHBvcnQgdHlwZSBPSG91clZhbHVlVHlwZSA9ICdzdHJpbmcnIHwgJ3RpbWVzdGFtcCc7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0lOUFVUU19PX0hPVVJfSU5QVVQgPSBbXG4gICdmb3JtYXQnLFxuICAndGV4dElucHV0RW5hYmxlZDogdGV4dC1pbnB1dC1lbmFibGVkJyxcbiAgJ21pbicsXG4gICdtYXgnLFxuICAndmFsdWVUeXBlOiB2YWx1ZS10eXBlJ1xuXTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnby1ob3VyLWlucHV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL28taG91ci1pbnB1dC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL28taG91ci1pbnB1dC5jb21wb25lbnQuc2NzcyddLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBpbnB1dHM6IERFRkFVTFRfSU5QVVRTX09fSE9VUl9JTlBVVCxcbiAgaG9zdDoge1xuICAgICdbY2xhc3Muby1ob3VyLWlucHV0XSc6ICd0cnVlJ1xuICB9XG59KVxuZXhwb3J0IGNsYXNzIE9Ib3VySW5wdXRDb21wb25lbnQgZXh0ZW5kcyBPRm9ybURhdGFDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gIEBCb29sZWFuSW5wdXRDb252ZXJ0ZXIoKVxuICBwdWJsaWMgdGV4dElucHV0RW5hYmxlZDogYm9vbGVhbiA9IHRydWU7XG4gIHB1YmxpYyBtaW46IHN0cmluZztcbiAgcHVibGljIG1heDogc3RyaW5nO1xuICBwcm90ZWN0ZWQgX2Zvcm1hdDogbnVtYmVyID0gQ29kZXMuVFdFTlRZX0ZPVVJfSE9VUl9GT1JNQVQ7XG4gIHByb3RlY3RlZCBvbktleWJvYXJkSW5wdXREb25lID0gZmFsc2U7XG4gIHByb3RlY3RlZCBfdmFsdWVUeXBlOiBPSG91clZhbHVlVHlwZSA9ICd0aW1lc3RhbXAnO1xuXG4gIEBWaWV3Q2hpbGQoJ3BpY2tlcicpXG4gIHB1YmxpYyBwaWNrZXI6IE5neE1hdGVyaWFsVGltZXBpY2tlckNvbXBvbmVudDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gT0Zvcm1Db21wb25lbnQpKSBmb3JtOiBPRm9ybUNvbXBvbmVudCxcbiAgICBlbFJlZjogRWxlbWVudFJlZixcbiAgICBpbmplY3RvcjogSW5qZWN0b3JcbiAgKSB7XG4gICAgc3VwZXIoZm9ybSwgZWxSZWYsIGluamVjdG9yKTtcbiAgICB0aGlzLl9kZWZhdWx0U1FMVHlwZUtleSA9ICdUSU1FU1RBTVAnO1xuICB9XG5cbiAgaW5pdGlhbGl6ZSgpOiB2b2lkIHtcbiAgICBzdXBlci5pbml0aWFsaXplKCk7XG4gICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmdldEZvcm1Db250cm9sKCkgYXMgT0Zvcm1Db250cm9sO1xuICAgIGlmIChmb3JtQ29udHJvbCkge1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICBmb3JtQ29udHJvbC5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHNlbGYuZ2V0VmFsdWUoKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBzdXBlci5uZ0FmdGVyVmlld0luaXQoKTtcbiAgICB0aGlzLm1vZGlmeVBpY2tlck1ldGhvZHMoKTtcbiAgfVxuXG4gIHB1YmxpYyBvbktleURvd24oZTogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICghQ29kZXMuaXNIb3VySW5wdXRBbGxvd2VkKGUpKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGlubmVyT25CbHVyKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5vbktleWJvYXJkSW5wdXREb25lKSB7XG4gICAgICB0aGlzLnVwZGF0ZVZhbGVPbklucHV0Q2hhbmdlKGV2ZW50KTtcbiAgICB9XG4gICAgc3VwZXIuaW5uZXJPbkJsdXIoZXZlbnQpO1xuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyT25Gb3JtQ29udHJvbENoYW5nZSgpOiB2b2lkIHtcbiAgICAvLyBUaGlzIGNvbXBvbmVudCBkb2VzIG5vdCBuZWVkIHRoaXMgc3Vic2NyaXB0aW9uXG4gIH1cblxuICBnZXQgZm9ybWF0U3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICh0aGlzLmZvcm1hdCA9PT0gQ29kZXMuVFdFTlRZX0ZPVVJfSE9VUl9GT1JNQVQgPyBDb2Rlcy5Ib3VyRm9ybWF0LlRXRU5UWV9GT1VSIDogQ29kZXMuSG91ckZvcm1hdC5UV0VMVkUpO1xuICB9XG5cbiAgcHVibGljIG9wZW4oZT86IEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKFV0aWwuaXNEZWZpbmVkKGUpKSB7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cbiAgICBpZiAodGhpcy5waWNrZXIpIHtcbiAgICAgIHRoaXMucGlja2VyLm9wZW4oKTtcbiAgICB9XG4gIH1cblxuICBzZXRUaW1lKGV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAvLyBnZXR0aW5nIHZhbHVlIGZyb20gc3VwZXIgc28gd2UgY2FuIGFsd2F5cyBnZXQgYSBzdHJpbmcgdmFsdWVcbiAgICBjb25zdCB2YWx1ZSA9IHN1cGVyLmdldFZhbHVlKCk7XG4gICAgdGhpcy5waWNrZXIudXBkYXRlVGltZSh2YWx1ZSk7XG4gIH1cblxuICBwdWJsaWMgc2V0VGltZXN0YW1wVmFsdWUodmFsdWU6IGFueSwgb3B0aW9ucz86IEZvcm1WYWx1ZU9wdGlvbnMpOiB2b2lkIHtcbiAgICBsZXQgcGFyc2VkVmFsdWU7XG4gICAgY29uc3QgbW9tZW50ViA9IFV0aWwuaXNEZWZpbmVkKHZhbHVlKSA/IG1vbWVudCh2YWx1ZSkgOiB2YWx1ZTtcbiAgICBpZiAobW9tZW50ViAmJiBtb21lbnRWLmlzVmFsaWQoKSkge1xuICAgICAgcGFyc2VkVmFsdWUgPSBtb21lbnRWLnV0Y09mZnNldCgwKS5mb3JtYXQodGhpcy5mb3JtYXRTdHJpbmcpO1xuICAgIH1cbiAgICB0aGlzLnNldFZhbHVlKHBhcnNlZFZhbHVlLCBvcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyByZXNvbHZlVmFsaWRhdG9ycygpOiBWYWxpZGF0b3JGbltdIHtcbiAgICBjb25zdCB2YWxpZGF0b3JzOiBWYWxpZGF0b3JGbltdID0gc3VwZXIucmVzb2x2ZVZhbGlkYXRvcnMoKTtcbiAgICBpZiAodGhpcy5mb3JtYXQgPT09IENvZGVzLlRXRU5UWV9GT1VSX0hPVVJfRk9STUFUKSB7XG4gICAgICB2YWxpZGF0b3JzLnB1c2goT1ZhbGlkYXRvcnMudHdlbnR5Rm91ckhvdXJGb3JtYXRWYWxpZGF0b3IpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWxpZGF0b3JzLnB1c2goT1ZhbGlkYXRvcnMudHdlbHZlSG91ckZvcm1hdFZhbGlkYXRvcik7XG4gICAgfVxuICAgIHJldHVybiB2YWxpZGF0b3JzO1xuICB9XG5cbiAgc2V0IGZvcm1hdCh2YWw6IG51bWJlcikge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMuX2Zvcm1hdDtcbiAgICBsZXQgcGFyc2VkVmFsID0gTnVtYmVyQ29udmVydGVyKHZhbCk7XG4gICAgaWYgKHBhcnNlZFZhbCAhPT0gQ29kZXMuVFdFTFZFX0ZPVVJfSE9VUl9GT1JNQVQgJiYgcGFyc2VkVmFsICE9PSBDb2Rlcy5UV0VOVFlfRk9VUl9IT1VSX0ZPUk1BVCkge1xuICAgICAgcGFyc2VkVmFsID0gQ29kZXMuVFdFTlRZX0ZPVVJfSE9VUl9GT1JNQVQ7XG4gICAgfVxuICAgIHRoaXMuX2Zvcm1hdCA9IHBhcnNlZFZhbDtcbiAgICBpZiAocGFyc2VkVmFsICE9PSBvbGQpIHtcbiAgICAgIHRoaXMudXBkYXRlVmFsaWRhdG9ycygpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBmb3JtYXQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fZm9ybWF0O1xuICB9XG5cbiAgc2V0IHZhbHVlVHlwZSh2YWw6IGFueSkge1xuICAgIHRoaXMuX3ZhbHVlVHlwZSA9IHRoaXMuY29udmVydFRvT0hvdXJWYWx1ZVR5cGUodmFsKTtcbiAgfVxuXG4gIGdldCB2YWx1ZVR5cGUoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5fdmFsdWVUeXBlO1xuICB9XG5cbiAgcHVibGljIGNvbnZlcnRUb09Ib3VyVmFsdWVUeXBlKHZhbDogYW55KTogT0hvdXJWYWx1ZVR5cGUge1xuICAgIGNvbnN0IHJlc3VsdDogT0hvdXJWYWx1ZVR5cGUgPSAnc3RyaW5nJztcbiAgICBjb25zdCBsb3dlclZhbCA9ICh2YWwgfHwgJycpLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKGxvd2VyVmFsID09PSAnc3RyaW5nJyB8fCBsb3dlclZhbCA9PT0gJ3RpbWVzdGFtcCcpIHtcbiAgICAgIHJldHVybiBsb3dlclZhbDtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHB1YmxpYyBvbkNoYW5nZUV2ZW50KGFyZzogYW55KTogdm9pZCB7XG4gICAgdGhpcy5vblRpbWVwaWNrZXJDaGFuZ2UoYXJnLnRhcmdldC52YWx1ZSk7XG4gIH1cblxuICBwdWJsaWMgb25UaW1lcGlja2VyQ2hhbmdlKGV2ZW50OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBsZXQgdmFsdWU6IGFueSA9IGV2ZW50O1xuICAgIGlmIChVdGlsLmlzRGVmaW5lZCh2YWx1ZSkgJiYgdGhpcy52YWx1ZVR5cGUgPT09ICd0aW1lc3RhbXAnKSB7XG4gICAgICBjb25zdCB2YWx1ZVRpbWVzdGFtcCA9IG1vbWVudCh2YWx1ZSwgdGhpcy5mb3JtYXRTdHJpbmcpLnZhbHVlT2YoKTtcbiAgICAgIGlmICghaXNOYU4odmFsdWVUaW1lc3RhbXApKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWVUaW1lc3RhbXA7XG4gICAgICB9XG4gICAgfVxuICAgIC8qKiBlbWl0TW9kZWxUb1ZpZXdDaGFuZ2U6IGZhbHNlICBiZWNhdXNlIG9uQ2hhbmdlIGV2ZW50IGlzIHRyaWdnZXIgaW4gbmdNb2RlbENoYW5nZSAqL1xuICAgIHRoaXMuc2V0VmFsdWUodmFsdWUsIHtcbiAgICAgIGNoYW5nZVR5cGU6IE9WYWx1ZUNoYW5nZUV2ZW50LlVTRVJfQ0hBTkdFLFxuICAgICAgZW1pdEV2ZW50OiBmYWxzZSxcbiAgICAgIGVtaXRNb2RlbFRvVmlld0NoYW5nZTogZmFsc2VcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBtb2RpZnlQaWNrZXJNZXRob2RzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnBpY2tlciAmJiB0aGlzLnBpY2tlci5pbnB1dEVsZW1lbnQpIHtcbiAgICAgIHRoaXMucGlja2VyLmlucHV0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgIHRoaXMub25LZXlib2FyZElucHV0RG9uZSA9IHRydWU7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0Rm9ybVZhbHVlKHZhbDogYW55LCBvcHRpb25zPzogRm9ybVZhbHVlT3B0aW9ucywgc2V0RGlydHk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIGxldCBzdHJpbmdWYWx1ZSA9IHZhbDtcbiAgICBpZiAoVXRpbC5pc0RlZmluZWQodmFsKSAmJiB0aGlzLnZhbHVlVHlwZSA9PT0gJ3RpbWVzdGFtcCcpIHtcbiAgICAgIC8vIGJlY2F1c2Ugb2YgdGhlIG5neC1tYXRlcmlhbC10aW1lcGlja2VyIGVzcGVjaWZpY2F0aW9uLCBpdHMgc3RvcmVkIHZhbHVlIG11c3QgYmUgYWx3YXlzIGEgc3RyaW5nXG4gICAgICBsZXQgdmFsdWUgPSB2YWwgaW5zdGFuY2VvZiBPRm9ybVZhbHVlID8gdmFsLnZhbHVlIDogdmFsO1xuICAgICAgc3RyaW5nVmFsdWUgPSB0aGlzLmdldFZhbHVlQXNTdHJpbmcodmFsdWUpO1xuICAgIH1cbiAgICB0aGlzLmVuc3VyZU9Gb3JtVmFsdWUodmFsKTtcbiAgICBpZiAoIXRoaXMuX2ZDb250cm9sKSB7XG4gICAgICAvLyBlbnN1cmluZyBfZkNvbnRyb2wgY3JlYXRpb25cbiAgICAgIHRoaXMuX2ZDb250cm9sID0gdGhpcy5nZXRDb250cm9sKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9mQ29udHJvbCkge1xuICAgICAgdGhpcy51cGRhdGVPRm9ybUNvbnRyb2xWYWx1ZShzdHJpbmdWYWx1ZSwgb3B0aW9ucywgc2V0RGlydHkpO1xuICAgIH1cbiAgICB0aGlzLm9sZFZhbHVlID0gdGhpcy52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCB1cGRhdGVWYWxlT25JbnB1dENoYW5nZShibHVyRXZlbnQ6IGFueSk6IHZvaWQge1xuICAgIGlmICh0aGlzLm9uS2V5Ym9hcmRJbnB1dERvbmUpIHtcbiAgICAgIC8vIG5neC1tYXRlcmlhbC10aW1lcGlja2VyIGRvZXMgbm90IGFsbG93IHdyaXRpbmcgY2hhcmFjdGVycyBvbiBpbnB1dCwgc28gd2UgYWRkICdBTS9QTScgaW4gb3JkZXIgdG8gbWFrZSB2YWxpZGF0aW9uIHdvcmsgcHJvcGVybHlcbiAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5wYXJzZUhvdXIoYmx1ckV2ZW50LmN1cnJlbnRUYXJnZXQudmFsdWUpO1xuICAgICAgdGhpcy5zZXRWYWx1ZSh2YWx1ZSk7XG4gICAgfVxuICAgIHRoaXMub25LZXlib2FyZElucHV0RG9uZSA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY2VpdmVzIGFuIGhvdXIgaW5wdXQgaW50cm9kdWNlZCBieSB0aGUgdXNlciBhbmQgcmV0dXJucyB0aGUgaG91ciBmb3JtYXRlZCBhY29yZGluZyBjdXJyZW50IGZvcm1hdFxuICAgKiBAcGFyYW0gdmFsdWVcbiAgICovXG4gIHByb3RlY3RlZCBwYXJzZUhvdXIodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3Qgc3RyQXJyYXkgPSB2YWx1ZS5zcGxpdCgnOicpO1xuICAgIGxldCBob3VyOiBhbnkgPSBzdHJBcnJheVswXTtcblxuICAgIGlmIChDb2Rlcy5UV0VMVkVfRk9VUl9IT1VSX0ZPUk1BVCA9PT0gdGhpcy5mb3JtYXQpIHtcbiAgICAgIGlmIChob3VyKSB7XG4gICAgICAgIGhvdXIgPSBwYXJzZUludChob3VyLCAxMCk7XG4gICAgICAgIGNvbnN0IHBlcmlvZCA9IGhvdXIgPD0gMTIgPyAnIEFNJyA6ICcgUE0nO1xuICAgICAgICBpZiAoaG91ciA+IDEyKSB7XG4gICAgICAgICAgaG91ciA9IGhvdXIgLSAxMjtcbiAgICAgICAgfVxuICAgICAgICBzdHJBcnJheVswXSA9IGhvdXI7XG4gICAgICAgIHZhbHVlID0gc3RyQXJyYXkuam9pbignOicpICsgcGVyaW9kO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoQ29kZXMuVFdFTlRZX0ZPVVJfSE9VUl9GT1JNQVQgPT09IHRoaXMuZm9ybWF0KSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBlbWl0T25WYWx1ZUNoYW5nZSh0eXBlLCBuZXdWYWx1ZSwgb2xkVmFsdWUpOiB2b2lkIHtcbiAgICB0aGlzLm9uQ2hhbmdlLmVtaXQobmV3VmFsdWUpO1xuICAgIHN1cGVyLmVtaXRPblZhbHVlQ2hhbmdlKHR5cGUsIG5ld1ZhbHVlLCBvbGRWYWx1ZSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VmFsdWVBc1N0cmluZyh2YWw6IGFueSk6IHN0cmluZyB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgICAgdmFsdWUgPSBtb21lbnQodmFsKS5mb3JtYXQodGhpcy5mb3JtYXRTdHJpbmcpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSA9IHRoaXMuY29udmVydFRvRm9ybWF0U3RyaW5nKHZhbCk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjb252ZXJ0VG9Gb3JtYXRTdHJpbmcodmFsdWUpOiBzdHJpbmcge1xuICAgIGlmICh2YWx1ZSA9PT0gJzAwOjAwJyB8fCAhVXRpbC5pc0RlZmluZWQodmFsdWUpKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICAgIGNvbnN0IGZvcm1hdFN0ciA9IHRoaXMuZm9ybWF0ID09PSBDb2Rlcy5UV0VOVFlfRk9VUl9IT1VSX0ZPUk1BVCA/ICdISDptbScgOiAnaGg6bW0gYSc7XG4gICAgbGV0IHJlc3VsdDtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcmVzdWx0ID0gbW9tZW50KHZhbHVlKS5mb3JtYXQoZm9ybWF0U3RyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0ID0gdmFsdWUgPyBtb21lbnQodmFsdWUsICdoOm1tIEEnKS5mb3JtYXQoZm9ybWF0U3RyKSA6IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iLCI8ZGl2IGZ4TGF5b3V0PVwicm93XCIgZnhMYXlvdXRBbGlnbj1cInNwYWNlLWJldHdlZW4gY2VudGVyXCIgW2Zvcm1Hcm91cF09XCJnZXRGb3JtR3JvdXAoKVwiIFttYXRUb29sdGlwXT1cInRvb2x0aXBcIiBbbWF0VG9vbHRpcENsYXNzXT1cInRvb2x0aXBDbGFzc1wiXG4gIFttYXRUb29sdGlwUG9zaXRpb25dPVwidG9vbHRpcFBvc2l0aW9uXCIgW21hdFRvb2x0aXBTaG93RGVsYXldPVwidG9vbHRpcFNob3dEZWxheVwiIFttYXRUb29sdGlwSGlkZURlbGF5XT1cInRvb2x0aXBIaWRlRGVsYXlcIj5cbiAgPG1hdC1mb3JtLWZpZWxkIFthcHBlYXJhbmNlXT1cImFwcGVhcmFuY2VcIiBbZmxvYXRMYWJlbF09XCJmbG9hdExhYmVsXCIgZnhGaWxsIFtoaWRlUmVxdWlyZWRNYXJrZXJdPVwiaGlkZVJlcXVpcmVkTWFya2VyXCIgY2xhc3M9XCJpY29uLWZpZWxkXCJcbiAgICBbc3Vic2NyaXB0U2l6aW5nXT1cInN1YnNjcmlwdFNpemluZ1wiPlxuICAgIDxtYXQtbGFiZWwgKm5nSWY9XCJsYWJlbFZpc2libGVcIj57eyBvbGFiZWwgfCBvVHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgPGlucHV0IG1hdElucHV0IFtuZ3hUaW1lcGlja2VyXT1cInBpY2tlclwiIFtpZF09XCJnZXRBdHRyaWJ1dGUoKVwiIFtwbGFjZWhvbGRlcl09XCJwbGFjZUhvbGRlclwiIFtmb3JtQ29udHJvbE5hbWVdPVwiZ2V0QXR0cmlidXRlKClcIlxuICAgICAgW3JlYWRvbmx5XT1cImlzUmVhZE9ubHkgfHwgIXRleHRJbnB1dEVuYWJsZWRcIiAoZm9jdXMpPVwiaW5uZXJPbkZvY3VzKCRldmVudClcIiAoYmx1cik9XCJpbm5lck9uQmx1cigkZXZlbnQpXCIgW3JlcXVpcmVkXT1cImlzUmVxdWlyZWRcIlxuICAgICAgKGNoYW5nZSk9XCJvbkNoYW5nZUV2ZW50KCRldmVudClcIiBbbWluXT1cIm1pblwiIFttYXhdPVwibWF4XCIgKGtleWRvd24pPVwib25LZXlEb3duKCRldmVudClcIiBbZm9ybWF0XT1cImZvcm1hdFwiIFtkaXNhYmxlQ2xpY2tdPVwidHJ1ZVwiPlxuXG4gICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKm5nSWY9XCJzaG93Q2xlYXJCdXR0b25cIiBtYXRTdWZmaXggbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJvbkNsaWNrQ2xlYXJWYWx1ZSgkZXZlbnQpXCI+XG4gICAgICA8bWF0LWljb24gc3ZnSWNvbj1cIm9udGltaXplOmNsb3NlXCI+PC9tYXQtaWNvbj5cbiAgICA8L2J1dHRvbj5cbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBtYXRTdWZmaXggbWF0LWljb24tYnV0dG9uIFtkaXNhYmxlZF09XCJpc1JlYWRPbmx5IHx8ICFlbmFibGVkXCIgKGNsaWNrKT1cIm9wZW4oJGV2ZW50KVwiPlxuICAgICAgPG1hdC1pY29uIG5neE1hdGVyaWFsVGltZXBpY2tlclRvZ2dsZUljb24gc3ZnSWNvbj1cIm9udGltaXplOmNsb2NrXCI+PC9tYXQtaWNvbj5cbiAgICA8L2J1dHRvbj5cblxuICAgIDxtYXQtZXJyb3IgKm9NYXRFcnJvcj1cImhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICB7eyAnRk9STV9WQUxJREFUSU9OLlJFUVVJUkVEJyB8IG9UcmFuc2xhdGUgfX1cbiAgICA8L21hdC1lcnJvcj5cbiAgICA8bWF0LWVycm9yICpvTWF0RXJyb3I9XCJoYXNFcnJvcignaW52YWxpZEZvcm1hdEhvdXInKVwiPlxuICAgICAge3sgJ0ZPUk1fVkFMSURBVElPTi5IT1VSX0ZPUk1BVCcgfCBvVHJhbnNsYXRlIH19IHt7IGZvcm1hdFN0cmluZyB9fVxuICAgIDwvbWF0LWVycm9yPlxuICAgIDxtYXQtZXJyb3IgKm5nRm9yPVwibGV0IG9FcnJvciBvZiBnZXRBY3RpdmVPRXJyb3JzKClcIj5cbiAgICAgIHt7IG9FcnJvci50ZXh0IHwgb1RyYW5zbGF0ZSB9fVxuICAgIDwvbWF0LWVycm9yPlxuICA8L21hdC1mb3JtLWZpZWxkPlxuPC9kaXY+XG5cbjxuZ3gtbWF0ZXJpYWwtdGltZXBpY2tlciAjcGlja2VyICh0aW1lU2V0KT1cIm9uVGltZXBpY2tlckNoYW5nZSgkZXZlbnQpXCIgW2NvbmZpcm1CdG5UbXBsXT1cImNvbmZpcm1CdG5cIiBbY2FuY2VsQnRuVG1wbF09XCJjYW5jZWxCdG5cIj5cbjwvbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXI+XG5cbjxuZy10ZW1wbGF0ZSAjY29uZmlybUJ0bj5cbiAgPGJ1dHRvbiBtYXQtc3Ryb2tlZC1idXR0b24gdHlwZT1cImJ1dHRvblwiPjxzcGFuPnt7J09LJyB8IG9UcmFuc2xhdGV9fTwvc3Bhbj48L2J1dHRvbj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjY2FuY2VsQnRuPlxuICA8YnV0dG9uIG1hdC1zdHJva2VkLWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCI+PHNwYW4+e3snQ0FOQ0VMJyB8IG9UcmFuc2xhdGV9fTwvc3Bhbj48L2J1dHRvbj5cbjwvbmctdGVtcGxhdGU+XG4iXX0=