UNPKG

@vipstorage/material-datetime-picker

Version:
262 lines 50.4 kB
import { Component, forwardRef, Input, Optional, ViewEncapsulation } from '@angular/core'; import { NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { Subject } from 'rxjs'; import { debounceTime, takeUntil } from 'rxjs/operators'; import { createMissingDateImplError, DEFAULT_STEP, formatTwoDigitTimeValue, LIMIT_TIMES, MERIDIANS, NUMERIC_REGEX, PATTERN_INPUT_HOUR, PATTERN_INPUT_MINUTE, PATTERN_INPUT_SECOND } from './utils/date-utils'; import * as i0 from "@angular/core"; import * as i1 from "./core/date-adapter"; import * as i2 from "@angular/forms"; import * as i3 from "@angular/common"; import * as i4 from "@angular/material/input"; import * as i5 from "@angular/material/form-field"; import * as i6 from "@angular/material/icon"; import * as i7 from "@angular/material/button"; export class NgxMatTimepickerComponent { /** Hour */ get hour() { let val = Number(this.form.controls['hour'].value); return isNaN(val) ? 0 : val; } ; get minute() { let val = Number(this.form.controls['minute'].value); return isNaN(val) ? 0 : val; } ; get second() { let val = Number(this.form.controls['second'].value); return isNaN(val) ? 0 : val; } ; /** Whether or not the form is valid */ get valid() { return this.form.valid; } constructor(_dateAdapter, cd, formBuilder) { this._dateAdapter = _dateAdapter; this.cd = cd; this.formBuilder = formBuilder; this.disabled = false; this.showSpinners = true; this.stepHour = DEFAULT_STEP; this.stepMinute = DEFAULT_STEP; this.stepSecond = DEFAULT_STEP; this.showSeconds = false; this.disableMinute = false; this.enableMeridian = false; this.color = 'primary'; this.meridian = MERIDIANS.AM; this._onChange = () => { }; this._onTouched = () => { }; this._destroyed = new Subject(); this.pattern = PATTERN_INPUT_HOUR; if (!this._dateAdapter) { throw createMissingDateImplError('NgxMatDateAdapter'); } this.form = this.formBuilder.group({ hour: [{ value: null, disabled: this.disabled }, [Validators.required, Validators.pattern(PATTERN_INPUT_HOUR)]], minute: [{ value: null, disabled: this.disabled }, [Validators.required, Validators.pattern(PATTERN_INPUT_MINUTE)]], second: [{ value: null, disabled: this.disabled }, [Validators.required, Validators.pattern(PATTERN_INPUT_SECOND)]] }); } ngOnInit() { this.form.valueChanges.pipe(takeUntil(this._destroyed), debounceTime(400)).subscribe(val => { this._updateModel(); }); } ngOnChanges(changes) { if (changes.disabled || changes.disableMinute) { this._setDisableStates(); } } ngOnDestroy() { this._destroyed.next(); this._destroyed.complete(); } /** * Writes a new value to the element. * @param obj */ writeValue(val) { if (val != null) { this._model = val; this._updateHourMinuteSecond(); } } /** Registers a callback function that is called when the control's value changes in the UI. */ registerOnChange(fn) { this._onChange = fn; } /** * Set the function to be called when the control receives a touch event. */ registerOnTouched(fn) { this._onTouched = fn; } /** Enables or disables the appropriate DOM element */ setDisabledState(isDisabled) { this._disabled = isDisabled; this.cd.markForCheck(); } /** * Format input * @param input */ formatInput(input) { input.value = input.value.replace(NUMERIC_REGEX, ''); } /** Toggle meridian */ toggleMeridian() { this.meridian = (this.meridian === MERIDIANS.AM) ? MERIDIANS.PM : MERIDIANS.AM; this.change('hour'); } /** Change property of time */ change(prop, up) { const next = this._getNextValueByProp(prop, up); this.form.controls[prop].setValue(formatTwoDigitTimeValue(next), { onlySelf: false, emitEvent: false }); this._updateModel(); } /** Update controls of form by model */ _updateHourMinuteSecond() { let _hour = this._dateAdapter.getHour(this._model); const _minute = this._dateAdapter.getMinute(this._model); const _second = this._dateAdapter.getSecond(this._model); if (this.enableMeridian) { if (_hour >= LIMIT_TIMES.meridian) { _hour = _hour - LIMIT_TIMES.meridian; this.meridian = MERIDIANS.PM; } else { this.meridian = MERIDIANS.AM; } if (_hour === 0) { _hour = LIMIT_TIMES.meridian; } } this.form.patchValue({ hour: formatTwoDigitTimeValue(_hour), minute: formatTwoDigitTimeValue(_minute), second: formatTwoDigitTimeValue(_second) }, { emitEvent: false }); } /** Update model */ _updateModel() { let _hour = this.hour; if (this.enableMeridian) { if (this.meridian === MERIDIANS.AM && _hour === LIMIT_TIMES.meridian) { _hour = 0; } else if (this.meridian === MERIDIANS.PM && _hour !== LIMIT_TIMES.meridian) { _hour = _hour + LIMIT_TIMES.meridian; } } if (this._model) { const clonedModel = this._dateAdapter.clone(this._model); this._dateAdapter.setHour(clonedModel, _hour); this._dateAdapter.setMinute(clonedModel, this.minute); this._dateAdapter.setSecond(clonedModel, this.second); this._onChange(clonedModel); } } /** * Get next value by property * @param prop * @param up */ _getNextValueByProp(prop, up) { const keyProp = prop[0].toUpperCase() + prop.slice(1); const min = LIMIT_TIMES[`min${keyProp}`]; let max = LIMIT_TIMES[`max${keyProp}`]; if (prop === 'hour' && this.enableMeridian) { max = LIMIT_TIMES.meridian; } let next; if (up == null) { next = this[prop] % (max); if (prop === 'hour' && this.enableMeridian) { if (next === 0) next = max; } } else { next = up ? this[prop] + this[`step${keyProp}`] : this[prop] - this[`step${keyProp}`]; if (prop === 'hour' && this.enableMeridian) { next = next % (max + 1); if (next === 0) next = up ? 1 : max; } else { next = next % max; } if (up) { next = next > max ? (next - max + min) : next; } else { next = next < min ? (next - min + max) : next; } } return next; } /** * Set disable states */ _setDisableStates() { if (this.disabled) { this.form.disable(); } else { this.form.enable(); if (this.disableMinute) { this.form.get('minute').disable(); if (this.showSeconds) { this.form.get('second').disable(); } } } } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NgxMatTimepickerComponent, deps: [{ token: i1.NgxMatDateAdapter, optional: true }, { token: i0.ChangeDetectorRef }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); } /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: NgxMatTimepickerComponent, selector: "ngx-mat-timepicker", inputs: { disabled: "disabled", showSpinners: "showSpinners", stepHour: "stepHour", stepMinute: "stepMinute", stepSecond: "stepSecond", showSeconds: "showSeconds", disableMinute: "disableMinute", enableMeridian: "enableMeridian", defaultTime: "defaultTime", color: "color" }, host: { classAttribute: "ngx-mat-timepicker" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((() => NgxMatTimepickerComponent)), multi: true } ], exportAs: ["ngxMatTimepicker"], usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\">\n <table class=\"ngx-mat-timepicker-table\">\n <tbody class=\"ngx-mat-timepicker-tbody\">\n <tr *ngIf=\"showSpinners\">\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_less icon\" (click)=\"change('hour', true)\"\n [disabled]=\"disabled\">\n <mat-icon>expand_less</mat-icon>\n </button>\n </td>\n <td></td>\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_less icon\" (click)=\"change('minute', true)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_less</mat-icon>\n </button> </td>\n <td></td>\n <td *ngIf=\"showSeconds\">\n <button type=\"button\" mat-icon-button aria-label=\"expand_less icon\" (click)=\"change('second', true)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_less</mat-icon>\n </button>\n </td>\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-spacer\"></td>\n <td *ngIf=\"enableMeridian\"></td>\n </tr>\n\n <tr>\n <td>\n <mat-form-field appearance=\"fill\" [color]=\"color\">\n <input type=\"text\" matInput (input)=\"formatInput($any($event).target)\" maxlength=\"2\" formControlName=\"hour\"\n (keydown.ArrowUp)=\"change('hour', true); $event.preventDefault()\"\n (keydown.ArrowDown)=\"change('hour', false); $event.preventDefault()\" (blur)=\"change('hour')\">\n </mat-form-field>\n </td>\n <td class=\"ngx-mat-timepicker-spacer\">&#58;</td>\n <td>\n <mat-form-field appearance=\"fill\" [color]=\"color\">\n <input type=\"text\" matInput (input)=\"formatInput($any($event).target)\" maxlength=\"2\"\n formControlName=\"minute\" (keydown.ArrowUp)=\"change('minute', true); $event.preventDefault()\"\n (keydown.ArrowDown)=\"change('minute', false); $event.preventDefault()\" (blur)=\"change('minute')\">\n </mat-form-field>\n </td>\n <td *ngIf=\"showSeconds\" class=\"ngx-mat-timepicker-spacer\">&#58;</td>\n <td *ngIf=\"showSeconds\">\n <mat-form-field appearance=\"fill\" [color]=\"color\">\n <input type=\"text\" matInput (input)=\"formatInput($any($event).target)\" maxlength=\"2\"\n formControlName=\"second\" (keydown.ArrowUp)=\"change('second', true); $event.preventDefault()\"\n (keydown.ArrowDown)=\"change('second', false); $event.preventDefault()\" (blur)=\"change('second')\">\n </mat-form-field>\n </td>\n\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-spacer\"></td>\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-meridian\">\n <button mat-button (click)=\"toggleMeridian()\" mat-stroked-button [color]=\"color\" [disabled]=\"disabled\">\n {{meridian}}\n </button>\n </td>\n </tr>\n\n <tr *ngIf=\"showSpinners\">\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_more icon\" (click)=\"change('hour', false)\"\n [disabled]=\"disabled\">\n <mat-icon>expand_more</mat-icon>\n </button> </td>\n <td></td>\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_more icon\" (click)=\"change('minute', false)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_more</mat-icon>\n </button> </td>\n <td *ngIf=\"showSeconds\"></td>\n <td *ngIf=\"showSeconds\">\n <button type=\"button\" mat-icon-button aria-label=\"expand_more icon\" (click)=\"change('second', false)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_more</mat-icon>\n </button>\n </td>\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-spacer\"></td>\n <td *ngIf=\"enableMeridian\"></td>\n </tr>\n </tbody>\n </table>\n</form>", styles: [".ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td{text-align:center}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td.ngx-mat-timepicker-spacer{font-weight:700}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td.ngx-mat-timepicker-meridian .mdc-button{min-width:64px;line-height:36px;min-width:0;border-radius:50%;width:36px;height:36px;padding:0;flex-shrink:0}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-icon-button{height:24px;width:24px;line-height:24px;padding:0}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-icon-button .mat-icon{font-size:24px}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field{width:24px;max-width:24px;text-align:center}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field.mat-focused .mdc-text-field--filled .mat-mdc-form-field-focus-overlay,.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field:hover .mdc-text-field--filled .mat-mdc-form-field-focus-overlay{background-color:transparent}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field .mdc-text-field--filled{background-color:transparent!important;padding:0!important}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field .mdc-text-field--filled .mat-mdc-form-field-infix{padding:4px 0;min-height:1px!important}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field .mdc-text-field--filled .mat-mdc-form-field-infix input{text-align:center;font-size:14px}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NgxMatTimepickerComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-mat-timepicker', host: { 'class': 'ngx-mat-timepicker' }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((() => NgxMatTimepickerComponent)), multi: true } ], exportAs: 'ngxMatTimepicker', encapsulation: ViewEncapsulation.None, template: "<form [formGroup]=\"form\">\n <table class=\"ngx-mat-timepicker-table\">\n <tbody class=\"ngx-mat-timepicker-tbody\">\n <tr *ngIf=\"showSpinners\">\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_less icon\" (click)=\"change('hour', true)\"\n [disabled]=\"disabled\">\n <mat-icon>expand_less</mat-icon>\n </button>\n </td>\n <td></td>\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_less icon\" (click)=\"change('minute', true)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_less</mat-icon>\n </button> </td>\n <td></td>\n <td *ngIf=\"showSeconds\">\n <button type=\"button\" mat-icon-button aria-label=\"expand_less icon\" (click)=\"change('second', true)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_less</mat-icon>\n </button>\n </td>\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-spacer\"></td>\n <td *ngIf=\"enableMeridian\"></td>\n </tr>\n\n <tr>\n <td>\n <mat-form-field appearance=\"fill\" [color]=\"color\">\n <input type=\"text\" matInput (input)=\"formatInput($any($event).target)\" maxlength=\"2\" formControlName=\"hour\"\n (keydown.ArrowUp)=\"change('hour', true); $event.preventDefault()\"\n (keydown.ArrowDown)=\"change('hour', false); $event.preventDefault()\" (blur)=\"change('hour')\">\n </mat-form-field>\n </td>\n <td class=\"ngx-mat-timepicker-spacer\">&#58;</td>\n <td>\n <mat-form-field appearance=\"fill\" [color]=\"color\">\n <input type=\"text\" matInput (input)=\"formatInput($any($event).target)\" maxlength=\"2\"\n formControlName=\"minute\" (keydown.ArrowUp)=\"change('minute', true); $event.preventDefault()\"\n (keydown.ArrowDown)=\"change('minute', false); $event.preventDefault()\" (blur)=\"change('minute')\">\n </mat-form-field>\n </td>\n <td *ngIf=\"showSeconds\" class=\"ngx-mat-timepicker-spacer\">&#58;</td>\n <td *ngIf=\"showSeconds\">\n <mat-form-field appearance=\"fill\" [color]=\"color\">\n <input type=\"text\" matInput (input)=\"formatInput($any($event).target)\" maxlength=\"2\"\n formControlName=\"second\" (keydown.ArrowUp)=\"change('second', true); $event.preventDefault()\"\n (keydown.ArrowDown)=\"change('second', false); $event.preventDefault()\" (blur)=\"change('second')\">\n </mat-form-field>\n </td>\n\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-spacer\"></td>\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-meridian\">\n <button mat-button (click)=\"toggleMeridian()\" mat-stroked-button [color]=\"color\" [disabled]=\"disabled\">\n {{meridian}}\n </button>\n </td>\n </tr>\n\n <tr *ngIf=\"showSpinners\">\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_more icon\" (click)=\"change('hour', false)\"\n [disabled]=\"disabled\">\n <mat-icon>expand_more</mat-icon>\n </button> </td>\n <td></td>\n <td>\n <button type=\"button\" mat-icon-button aria-label=\"expand_more icon\" (click)=\"change('minute', false)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_more</mat-icon>\n </button> </td>\n <td *ngIf=\"showSeconds\"></td>\n <td *ngIf=\"showSeconds\">\n <button type=\"button\" mat-icon-button aria-label=\"expand_more icon\" (click)=\"change('second', false)\"\n [disabled]=\"disabled || disableMinute\">\n <mat-icon>expand_more</mat-icon>\n </button>\n </td>\n <td *ngIf=\"enableMeridian\" class=\"ngx-mat-timepicker-spacer\"></td>\n <td *ngIf=\"enableMeridian\"></td>\n </tr>\n </tbody>\n </table>\n</form>", styles: [".ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td{text-align:center}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td.ngx-mat-timepicker-spacer{font-weight:700}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td.ngx-mat-timepicker-meridian .mdc-button{min-width:64px;line-height:36px;min-width:0;border-radius:50%;width:36px;height:36px;padding:0;flex-shrink:0}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-icon-button{height:24px;width:24px;line-height:24px;padding:0}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-icon-button .mat-icon{font-size:24px}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field{width:24px;max-width:24px;text-align:center}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field.mat-focused .mdc-text-field--filled .mat-mdc-form-field-focus-overlay,.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field:hover .mdc-text-field--filled .mat-mdc-form-field-focus-overlay{background-color:transparent}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field .mdc-text-field--filled{background-color:transparent!important;padding:0!important}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field .mdc-text-field--filled .mat-mdc-form-field-infix{padding:4px 0;min-height:1px!important}.ngx-mat-timepicker form .ngx-mat-timepicker-table .ngx-mat-timepicker-tbody tr td .mat-mdc-form-field .mdc-text-field--filled .mat-mdc-form-field-infix input{text-align:center;font-size:14px}\n"] }] }], ctorParameters: () => [{ type: i1.NgxMatDateAdapter, decorators: [{ type: Optional }] }, { type: i0.ChangeDetectorRef }, { type: i2.FormBuilder }], propDecorators: { disabled: [{ type: Input }], showSpinners: [{ type: Input }], stepHour: [{ type: Input }], stepMinute: [{ type: Input }], stepSecond: [{ type: Input }], showSeconds: [{ type: Input }], disableMinute: [{ type: Input }], enableMeridian: [{ type: Input }], defaultTime: [{ type: Input }], color: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXRldGltZS1waWNrZXIvc3JjL2xpYi90aW1lcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2RhdGV0aW1lLXBpY2tlci9zcmMvbGliL3RpbWVwaWNrZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFxQixTQUFTLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBcUIsUUFBUSxFQUFpQixpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvSSxPQUFPLEVBQWdELGlCQUFpQixFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTdHLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RCxPQUFPLEVBQ0wsMEJBQTBCLEVBQUUsWUFBWSxFQUFFLHVCQUF1QixFQUNqRSxXQUFXLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxrQkFBa0IsRUFBRSxvQkFBb0IsRUFBRSxvQkFBb0IsRUFDdEcsTUFBTSxvQkFBb0IsQ0FBQzs7Ozs7Ozs7O0FBbUI1QixNQUFNLE9BQU8seUJBQXlCO0lBaUJwQyxXQUFXO0lBQ1gsSUFBWSxJQUFJO1FBQ2QsSUFBSSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25ELE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM5QixDQUFDO0lBQUEsQ0FBQztJQUVGLElBQVksTUFBTTtRQUNoQixJQUFJLEdBQUcsR0FBRyxN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RSxVQUFVLEVBQUMsR0FBRyxFQUFFLENBQUMseUJBQXlCLEVBQUM7Z0JBQ3hELEtBQUssRUFBRSxJQUFJO2FBQ1o7U0FDRiwrRUN4QkgsOC9IQW9GTzs7MkZEeERNLHlCQUF5QjtrQkFqQnJDLFNBQVM7K0JBQ0Usb0JBQW9CLFFBR3hCO3dCQUNKLE9BQU8sRUFBRSxvQkFBb0I7cUJBQzlCLGFBQ1U7d0JBQ1Q7NEJBQ0UsT0FBTyxFQUFFLGlCQUFpQjs0QkFDMUIsV0FBVyxFQUFFLFVBQVUsRUFBQyxHQUFHLEVBQUUsMEJBQTBCLEVBQUM7NEJBQ3hELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGLFlBQ1Msa0JBQWtCLGlCQUNiLGlCQUFpQixDQUFDLElBQUk7OzBCQWlEeEIsUUFBUTttR0EzQ1osUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgZm9yd2FyZFJlZiwgSW5wdXQsIE9uQ2hhbmdlcywgT25Jbml0LCBPcHRpb25hbCwgU2ltcGxlQ2hhbmdlcywgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBOR19WQUxVRV9BQ0NFU1NPUiwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFRoZW1lUGFsZXR0ZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBOZ3hNYXREYXRlQWRhcHRlciB9IGZyb20gJy4vY29yZS9kYXRlLWFkYXB0ZXInO1xuaW1wb3J0IHtcbiAgY3JlYXRlTWlzc2luZ0RhdGVJbXBsRXJyb3IsIERFRkFVTFRfU1RFUCwgZm9ybWF0VHdvRGlnaXRUaW1lVmFsdWUsXG4gIExJTUlUX1RJTUVTLCBNRVJJRElBTlMsIE5VTUVSSUNfUkVHRVgsIFBBVFRFUk5fSU5QVVRfSE9VUiwgUEFUVEVSTl9JTlBVVF9NSU5VVEUsIFBBVFRFUk5fSU5QVVRfU0VDT05EXG59IGZyb20gJy4vdXRpbHMvZGF0ZS11dGlscyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1tYXQtdGltZXBpY2tlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi90aW1lcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vdGltZXBpY2tlci5jb21wb25lbnQuc2NzcyddLFxuICBob3N0OiB7XG4gICAgJ2NsYXNzJzogJ25neC1tYXQtdGltZXBpY2tlcidcbiAgfSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOZ3hNYXRUaW1lcGlja2VyQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdLFxuICBleHBvcnRBczogJ25neE1hdFRpbWVwaWNrZXInLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxufSlcbmV4cG9ydCBjbGFzcyBOZ3hNYXRUaW1lcGlja2VyQ29tcG9uZW50PEQ+IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBwdWJsaWMgZm9ybTogRm9ybUdyb3VwO1xuXG4gIEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG4gIEBJbnB1dCgpIHNob3dTcGlubmVycyA9IHRydWU7XG4gIEBJbnB1dCgpIHN0ZXBIb3VyOiBudW1iZXIgPSBERUZBVUxUX1NURVA7XG4gIEBJbnB1dCgpIHN0ZXBNaW51dGU6IG51bWJlciA9IERFRkFVTFRfU1RFUDtcbiAgQElucHV0KCkgc3RlcFNlY29uZDogbnVtYmVyID0gREVGQVVMVF9TVEVQO1xuICBASW5wdXQoKSBzaG93U2Vjb25kcyA9IGZhbHNlO1xuICBASW5wdXQoKSBkaXNhYmxlTWludXRlID0gZmFsc2U7XG4gIEBJbnB1dCgpIGVuYWJsZU1lcmlkaWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIGRlZmF1bHRUaW1lOiBudW1iZXJbXTtcbiAgQElucHV0KCkgY29sb3I6IFRoZW1lUGFsZXR0ZSA9ICdwcmltYXJ5JztcblxuICBwdWJsaWMgbWVyaWRpYW46IHN0cmluZyA9IE1FUklESUFOUy5BTTtcblxuICAvKiogSG91ciAqL1xuICBwcml2YXRlIGdldCBob3VyKCkge1xuICAgIGxldCB2YWwgPSBOdW1iZXIodGhpcy5mb3JtLmNvbnRyb2xzWydob3VyJ10udmFsdWUpO1xuICAgIHJldHVybiBpc05hTih2YWwpID8gMCA6IHZhbDtcbiAgfTtcblxuICBwcml2YXRlIGdldCBtaW51dGUoKSB7XG4gICAgbGV0IHZhbCA9IE51bWJlcih0aGlzLmZvcm0uY29udHJvbHNbJ21pbnV0ZSddLnZhbHVlKTtcbiAgICByZXR1cm4gaXNOYU4odmFsKSA/IDAgOiB2YWw7XG4gIH07XG5cbiAgcHJpdmF0ZSBnZXQgc2Vjb25kKCkge1xuICAgIGxldCB2YWwgPSBOdW1iZXIodGhpcy5mb3JtLmNvbnRyb2xzWydzZWNvbmQnXS52YWx1ZSk7XG4gICAgcmV0dXJuIGlzTmFOKHZhbCkgPyAwIDogdmFsO1xuICB9O1xuXG4gIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgZm9ybSBpcyB2YWxpZCAqL1xuICBwdWJsaWMgZ2V0IHZhbGlkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmZvcm0udmFsaWQ7XG4gIH1cblxuICBwcml2YXRlIF9vbkNoYW5nZTogYW55ID0gKCkgPT4geyB9O1xuICBwcml2YXRlIF9vblRvdWNoZWQ6IGFueSA9ICgpID0+IHsgfTtcbiAgcHJpdmF0ZSBfZGlzYWJsZWQ6IGJvb2xlYW47XG4gIHByaXZhdGUgX21vZGVsOiBEO1xuXG4gIHByaXZhdGUgX2Rlc3Ryb3llZDogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgcHVibGljIHBhdHRlcm4gPSBQQVRURVJOX0lOUFVUX0hPVVI7XG5cbiAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgcHVibGljIF9kYXRlQWRhcHRlcjogTmd4TWF0RGF0ZUFkYXB0ZXI8RD4sXG4gICAgcHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYsIHByaXZhdGUgZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyKSB7XG4gICAgaWYgKCF0aGlzLl9kYXRlQWRhcHRlcikge1xuICAgICAgdGhyb3cgY3JlYXRlTWlzc2luZ0RhdGVJbXBsRXJyb3IoJ05neE1hdERhdGVBZGFwdGVyJyk7XG4gICAgfVxuICAgIHRoaXMuZm9ybSA9IHRoaXMuZm9ybUJ1aWxkZXIuZ3JvdXAoXG4gICAgICB7XG4gICAgICAgIGhvdXI6IFt7IHZhbHVlOiBudWxsLCBkaXNhYmxlZDogdGhpcy5kaXNhYmxlZCB9LCBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5wYXR0ZXJuKFBBVFRFUk5fSU5QVVRfSE9VUildXSxcbiAgICAgICAgbWludXRlOiBbeyB2YWx1ZTogbnVsbCwgZGlzYWJsZWQ6IHRoaXMuZGlzYWJsZWQgfSwgW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMucGF0dGVybihQQVRURVJOX0lOUFVUX01JTlVURSldXSxcbiAgICAgICAgc2Vjb25kOiBbeyB2YWx1ZTogbnVsbCwgZGlzYWJsZWQ6IHRoaXMuZGlzYWJsZWQgfSwgW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMucGF0dGVybihQQVRURVJOX0lOUFVUX1NFQ09ORCldXVxuICAgICAgfSk7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3llZCksIGRlYm91bmNlVGltZSg0MDApKS5zdWJzY3JpYmUodmFsID0+IHtcbiAgICAgIHRoaXMuX3VwZGF0ZU1vZGVsKCk7XG4gICAgfSlcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlcy5kaXNhYmxlZCB8fCBjaGFuZ2VzLmRpc2FibGVNaW51dGUpIHtcbiAgICAgIHRoaXMuX3NldERpc2FibGVTdGF0ZXMoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLl9kZXN0cm95ZWQubmV4dCgpO1xuICAgIHRoaXMuX2Rlc3Ryb3llZC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyaXRlcyBhIG5ldyB2YWx1ZSB0byB0aGUgZWxlbWVudC5cbiAgICogQHBhcmFtIG9ialxuICAgKi9cbiAgd3JpdGVWYWx1ZSh2YWw6IEQpOiB2b2lkIHtcbiAgICBpZiAodmFsICE9IG51bGwpIHtcbiAgICAgIHRoaXMuX21vZGVsID0gdmFsO1xuICAgICAgdGhpcy5fdXBkYXRlSG91ck1pbnV0ZVNlY29uZCgpO1xuICAgIH1cblxuICB9XG5cbiAgLyoqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gdGhlIGNvbnRyb2wncyB2YWx1ZSBjaGFuZ2VzIGluIHRoZSBVSS4gKi9cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKF86IGFueSkgPT4ge30pOiB2b2lkIHtcbiAgICB0aGlzLl9vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGNvbnRyb2wgcmVjZWl2ZXMgYSB0b3VjaCBldmVudC5cbiAgICovXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB7fSk6IHZvaWQge1xuICAgIHRoaXMuX29uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgLyoqIEVuYWJsZXMgb3IgZGlzYWJsZXMgdGhlIGFwcHJvcHJpYXRlIERPTSBlbGVtZW50ICovXG4gIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuX2Rpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICB0aGlzLmNkLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZvcm1hdCBpbnB1dFxuICAgKiBAcGFyYW0gaW5wdXQgXG4gICAqL1xuICBwdWJsaWMgZm9ybWF0SW5wdXQoaW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQpIHtcbiAgICBpbnB1dC52YWx1ZSA9IGlucHV0LnZhbHVlLnJlcGxhY2UoTlVNRVJJQ19SRUdFWCwgJycpO1xuICB9XG5cbiAgLyoqIFRvZ2dsZSBtZXJpZGlhbiAqL1xuICBwdWJsaWMgdG9nZ2xlTWVyaWRpYW4oKSB7XG4gICAgdGhpcy5tZXJpZGlhbiA9ICh0aGlzLm1lcmlkaWFuID09PSBNRVJJRElBTlMuQU0pID8gTUVSSURJQU5TLlBNIDogTUVSSURJQU5TLkFNO1xuICAgIHRoaXMuY2hhbmdlKCdob3VyJyk7XG4gIH1cblxuICAvKiogQ2hhbmdlIHByb3BlcnR5IG9mIHRpbWUgKi9cbiAgcHVibGljIGNoYW5nZShwcm9wOiBzdHJpbmcsIHVwPzogYm9vbGVhbikge1xuICAgIGNvbnN0IG5leHQgPSB0aGlzLl9nZXROZXh0VmFsdWVCeVByb3AocHJvcCwgdXApO1xuICAgIHRoaXMuZm9ybS5jb250cm9sc1twcm9wXS5zZXRWYWx1ZShmb3JtYXRUd29EaWdpdFRpbWVWYWx1ZShuZXh0KSwgeyBvbmx5U2VsZjogZmFsc2UsIGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgdGhpcy5fdXBkYXRlTW9kZWwoKTtcbiAgfVxuXG4gIC8qKiBVcGRhdGUgY29udHJvbHMgb2YgZm9ybSBieSBtb2RlbCAqL1xuICBwcml2YXRlIF91cGRhdGVIb3VyTWludXRlU2Vjb25kKCkge1xuICAgIGxldCBfaG91ciA9IHRoaXMuX2RhdGVBZGFwdGVyLmdldEhvdXIodGhpcy5fbW9kZWwpO1xuICAgIGNvbnN0IF9taW51dGUgPSB0aGlzLl9kYXRlQWRhcHRlci5nZXRNaW51dGUodGhpcy5fbW9kZWwpO1xuICAgIGNvbnN0IF9zZWNvbmQgPSB0aGlzLl9kYXRlQWRhcHRlci5nZXRTZWNvbmQodGhpcy5fbW9kZWwpO1xuXG4gICAgaWYgKHRoaXMuZW5hYmxlTWVyaWRpYW4pIHtcbiAgICAgIGlmIChfaG91ciA+PSBMSU1JVF9USU1FUy5tZXJpZGlhbikge1xuICAgICAgICBfaG91ciA9IF9ob3VyIC0gTElNSVRfVElNRVMubWVyaWRpYW47XG4gICAgICAgIHRoaXMubWVyaWRpYW4gPSBNRVJJRElBTlMuUE07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm1lcmlkaWFuID0gTUVSSURJQU5TLkFNO1xuICAgICAgfVxuICAgICAgaWYgKF9ob3VyID09PSAwKSB7XG4gICAgICAgIF9ob3VyID0gTElNSVRfVElNRVMubWVyaWRpYW47XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5mb3JtLnBhdGNoVmFsdWUoe1xuICAgICAgaG91cjogZm9ybWF0VHdvRGlnaXRUaW1lVmFsdWUoX2hvdXIpLFxuICAgICAgbWludXRlOiBmb3JtYXRUd29EaWdpdFRpbWVWYWx1ZShfbWludXRlKSxcbiAgICAgIHNlY29uZDogZm9ybWF0VHdvRGlnaXRUaW1lVmFsdWUoX3NlY29uZClcbiAgICB9LCB7XG4gICAgICBlbWl0RXZlbnQ6IGZhbHNlXG4gICAgfSlcblxuICB9XG5cbiAgLyoqIFVwZGF0ZSBtb2RlbCAqL1xuICBwcml2YXRlIF91cGRhdGVNb2RlbCgpIHtcbiAgICBsZXQgX2hvdXIgPSB0aGlzLmhvdXI7XG5cbiAgICBpZiAodGhpcy5lbmFibGVNZXJpZGlhbikge1xuICAgICAgaWYgKHRoaXMubWVyaWRpYW4gPT09IE1FUklESUFOUy5BTSAmJiBfaG91ciA9PT0gTElNSVRfVElNRVMubWVyaWRpYW4pIHtcbiAgICAgICAgX2hvdXIgPSAwO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLm1lcmlkaWFuID09PSBNRVJJRElBTlMuUE0gJiYgX2hvdXIgIT09IExJTUlUX1RJTUVTLm1lcmlkaWFuKSB7XG4gICAgICAgIF9ob3VyID0gX2hvdXIgKyBMSU1JVF9USU1FUy5tZXJpZGlhbjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5fbW9kZWwpIHtcbiAgICAgIGNvbnN0IGNsb25lZE1vZGVsID0gdGhpcy5fZGF0ZUFkYXB0ZXIuY2xvbmUodGhpcy5fbW9kZWwpO1xuXG4gICAgICB0aGlzLl9kYXRlQWRhcHRlci5zZXRIb3VyKGNsb25lZE1vZGVsLCBfaG91cik7XG4gICAgICB0aGlzLl9kYXRlQWRhcHRlci5zZXRNaW51dGUoY2xvbmVkTW9kZWwsIHRoaXMubWludXRlKTtcbiAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLnNldFNlY29uZChjbG9uZWRNb2RlbCwgdGhpcy5zZWNvbmQpO1xuICAgICAgdGhpcy5fb25DaGFuZ2UoY2xvbmVkTW9kZWwpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgbmV4dCB2YWx1ZSBieSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0gcHJvcCBcbiAgICogQHBhcmFtIHVwXG4gICAqL1xuICBwcml2YXRlIF9nZXROZXh0VmFsdWVCeVByb3AocHJvcDogc3RyaW5nLCB1cD86IGJvb2xlYW4pOiBudW1iZXIge1xuICAgIGNvbnN0IGtleVByb3AgPSBwcm9wWzBdLnRvVXBwZXJDYXNlKCkgKyBwcm9wLnNsaWNlKDEpO1xuICAgIGNvbnN0IG1pbiA9IExJTUlUX1RJTUVTW2BtaW4ke2tleVByb3B9YF07XG4gICAgbGV0IG1heCA9IExJTUlUX1RJTUVTW2BtYXgke2tleVByb3B9YF07XG5cbiAgICBpZiAocHJvcCA9PT0gJ2hvdXInICYmIHRoaXMuZW5hYmxlTWVyaWRpYW4pIHtcbiAgICAgIG1heCA9IExJTUlUX1RJTUVTLm1lcmlkaWFuO1xuICAgIH1cblxuICAgIGxldCBuZXh0O1xuICAgIGlmICh1cCA9PSBudWxsKSB7XG4gICAgICBuZXh0ID0gdGhpc1twcm9wXSAlIChtYXgpO1xuICAgICAgaWYgKHByb3AgPT09ICdob3VyJyAmJiB0aGlzLmVuYWJsZU1lcmlkaWFuKSB7XG4gICAgICAgIGlmIChuZXh0ID09PSAwKSBuZXh0ID0gbWF4O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBuZXh0ID0gdXAgPyB0aGlzW3Byb3BdICsgdGhpc1tgc3RlcCR7a2V5UHJvcH1gXSA6IHRoaXNbcHJvcF0gLSB0aGlzW2BzdGVwJHtrZXlQcm9wfWBdO1xuICAgICAgaWYgKHByb3AgPT09ICdob3VyJyAmJiB0aGlzLmVuYWJsZU1lcmlkaWFuKSB7XG4gICAgICAgIG5leHQgPSBuZXh0ICUgKG1heCArIDEpO1xuICAgICAgICBpZiAobmV4dCA9PT0gMCkgbmV4dCA9IHVwID8gMSA6IG1heDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5leHQgPSBuZXh0ICUgbWF4O1xuICAgICAgfVxuICAgICAgaWYgKHVwKSB7XG4gICAgICAgIG5leHQgPSBuZXh0ID4gbWF4ID8gKG5leHQgLSBtYXggKyBtaW4pIDogbmV4dDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5leHQgPSBuZXh0IDwgbWluID8gKG5leHQgLSBtaW4gKyBtYXgpIDogbmV4dDtcbiAgICAgIH1cblxuICAgIH1cblxuICAgIHJldHVybiBuZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBkaXNhYmxlIHN0YXRlc1xuICAgKi9cbiAgcHJpdmF0ZSBfc2V0RGlzYWJsZVN0YXRlcygpIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5mb3JtLmRpc2FibGUoKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0aGlzLmZvcm0uZW5hYmxlKCk7XG4gICAgICBpZiAodGhpcy5kaXNhYmxlTWludXRlKSB7XG4gICAgICAgIHRoaXMuZm9ybS5nZXQoJ21pbnV0ZScpLmRpc2FibGUoKTtcbiAgICAgICAgaWYgKHRoaXMuc2hvd1NlY29uZHMpIHtcbiAgICAgICAgICB0aGlzLmZvcm0uZ2V0KCdzZWNvbmQnKS5kaXNhYmxlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxufVxuIiwiPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtXCI+XG4gIDx0YWJsZSBjbGFzcz1cIm5neC1tYXQtdGltZXBpY2tlci10YWJsZVwiPlxuICAgIDx0Ym9keSBjbGFzcz1cIm5neC1tYXQtdGltZXBpY2tlci10Ym9keVwiPlxuICAgICAgPHRyICpuZ0lmPVwic2hvd1NwaW5uZXJzXCI+XG4gICAgICAgIDx0ZD5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBtYXQtaWNvbi1idXR0b24gYXJpYS1sYWJlbD1cImV4cGFuZF9sZXNzIGljb25cIiAoY2xpY2spPVwiY2hhbmdlKCdob3VyJywgdHJ1ZSlcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCI+XG4gICAgICAgICAgICA8bWF0LWljb24+ZXhwYW5kX2xlc3M8L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L3RkPlxuICAgICAgICA8dGQ+PC90ZD5cbiAgICAgICAgPHRkPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIG1hdC1pY29uLWJ1dHRvbiBhcmlhLWxhYmVsPVwiZXhwYW5kX2xlc3MgaWNvblwiIChjbGljayk9XCJjaGFuZ2UoJ21pbnV0ZScsIHRydWUpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBkaXNhYmxlTWludXRlXCI+XG4gICAgICAgICAgICA8bWF0LWljb24+ZXhwYW5kX2xlc3M8L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPiA8L3RkPlxuICAgICAgICA8dGQ+PC90ZD5cbiAgICAgICAgPHRkICpuZ0lmPVwic2hvd1NlY29uZHNcIj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBtYXQtaWNvbi1idXR0b24gYXJpYS1sYWJlbD1cImV4cGFuZF9sZXNzIGljb25cIiAoY2xpY2spPVwiY2hhbmdlKCdzZWNvbmQnLCB0cnVlKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQgfHwgZGlzYWJsZU1pbnV0ZVwiPlxuICAgICAgICAgICAgPG1hdC1pY29uPmV4cGFuZF9sZXNzPC9tYXQtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC90ZD5cbiAgICAgICAgPHRkICpuZ0lmPVwiZW5hYmxlTWVyaWRpYW5cIiBjbGFzcz1cIm5neC1tYXQtdGltZXBpY2tlci1zcGFjZXJcIj48L3RkPlxuICAgICAgICA8dGQgKm5nSWY9XCJlbmFibGVNZXJpZGlhblwiPjwvdGQ+XG4gICAgICA8L3RyPlxuXG4gICAgICA8dHI+XG4gICAgICAgIDx0ZD5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cImZpbGxcIiBbY29sb3JdPVwiY29sb3JcIj5cbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIG1hdElucHV0IChpbnB1dCk9XCJmb3JtYXRJbnB1dCgkYW55KCRldmVudCkudGFyZ2V0KVwiIG1heGxlbmd0aD1cIjJcIiBmb3JtQ29udHJvbE5hbWU9XCJob3VyXCJcbiAgICAgICAgICAgICAgKGtleWRvd24uQXJyb3dVcCk9XCJjaGFuZ2UoJ2hvdXInLCB0cnVlKTsgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIlxuICAgICAgICAgICAgICAoa2V5ZG93bi5BcnJvd0Rvd24pPVwiY2hhbmdlKCdob3VyJywgZmFsc2UpOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiIChibHVyKT1cImNoYW5nZSgnaG91cicpXCI+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPC90ZD5cbiAgICAgICAgPHRkIGNsYXNzPVwibmd4LW1hdC10aW1lcGlja2VyLXNwYWNlclwiPiYjNTg7PC90ZD5cbiAgICAgICAgPHRkPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwiZmlsbFwiIFtjb2xvcl09XCJjb2xvclwiPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgbWF0SW5wdXQgKGlucHV0KT1cImZvcm1hdElucHV0KCRhbnkoJGV2ZW50KS50YXJnZXQpXCIgbWF4bGVuZ3RoPVwiMlwiXG4gICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIm1pbnV0ZVwiIChrZXlkb3duLkFycm93VXApPVwiY2hhbmdlKCdtaW51dGUnLCB0cnVlKTsgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIlxuICAgICAgICAgICAgICAoa2V5ZG93bi5BcnJvd0Rvd24pPVwiY2hhbmdlKCdtaW51dGUnLCBmYWxzZSk7ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXCIgKGJsdXIpPVwiY2hhbmdlKCdtaW51dGUnKVwiPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgIDwvdGQ+XG4gICAgICAgIDx0ZCAqbmdJZj1cInNob3dTZWNvbmRzXCIgY2xhc3M9XCJuZ3gtbWF0LXRpbWVwaWNrZXItc3BhY2VyXCI+JiM1ODs8L3RkPlxuICAgICAgICA8dGQgKm5nSWY9XCJzaG93U2Vjb25kc1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwiZmlsbFwiIFtjb2xvcl09XCJjb2xvclwiPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgbWF0SW5wdXQgKGlucHV0KT1cImZvcm1hdElucHV0KCRhbnkoJGV2ZW50KS50YXJnZXQpXCIgbWF4bGVuZ3RoPVwiMlwiXG4gICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInNlY29uZFwiIChrZXlkb3duLkFycm93VXApPVwiY2hhbmdlKCdzZWNvbmQnLCB0cnVlKTsgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIlxuICAgICAgICAgICAgICAoa2V5ZG93bi5BcnJvd0Rvd24pPVwiY2hhbmdlKCdzZWNvbmQnLCBmYWxzZSk7ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXCIgKGJsdXIpPVwiY2hhbmdlKCdzZWNvbmQnKVwiPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgIDwvdGQ+XG5cbiAgICAgICAgPHRkICpuZ0lmPVwiZW5hYmxlTWVyaWRpYW5cIiBjbGFzcz1cIm5neC1tYXQtdGltZXBpY2tlci1zcGFjZXJcIj48L3RkPlxuICAgICAgICA8dGQgKm5nSWY9XCJlbmFibGVNZXJpZGlhblwiIGNsYXNzPVwibmd4LW1hdC10aW1lcGlja2VyLW1lcmlkaWFuXCI+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJ0b2dnbGVNZXJpZGlhbigpXCIgbWF0LXN0cm9rZWQtYnV0dG9uIFtjb2xvcl09XCJjb2xvclwiIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiPlxuICAgICAgICAgICAge3ttZXJpZGlhbn19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L3RyPlxuXG4gICAgICA8dHIgKm5nSWY9XCJzaG93U3Bpbm5lcnNcIj5cbiAgICAgICAgPHRkPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIG1hdC1pY29uLWJ1dHRvbiBhcmlhLWxhYmVsPVwiZXhwYW5kX21vcmUgaWNvblwiIChjbGljayk9XCJjaGFuZ2UoJ2hvdXInLCBmYWxzZSlcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCI+XG4gICAgICAgICAgICA8bWF0LWljb24+ZXhwYW5kX21vcmU8L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPiA8L3RkPlxuICAgICAgICA8dGQ+PC90ZD5cbiAgICAgICAgPHRkPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIG1hdC1pY29uLWJ1dHRvbiBhcmlhLWxhYmVsPVwiZXhwYW5kX21vcmUgaWNvblwiIChjbGljayk9XCJjaGFuZ2UoJ21pbnV0ZScsIGZhbHNlKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQgfHwgZGlzYWJsZU1pbnV0ZVwiPlxuICAgICAgICAgICAgPG1hdC1pY29uPmV4cGFuZF9tb3JlPC9tYXQtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj4gPC90ZD5cbiAgICAgICAgPHRkICpuZ0lmPVwic2hvd1NlY29uZHNcIj48L3RkPlxuICAgICAgICA8dGQgKm5nSWY9XCJzaG93U2Vjb25kc1wiPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIG1hdC1pY29uLWJ1dHRvbiBhcmlhLWxhYmVsPVwiZXhwYW5kX21vcmUgaWNvblwiIChjbGljayk9XCJjaGFuZ2UoJ3NlY29uZCcsIGZhb