UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

258 lines 47.1 kB
import { ChangeDetectorRef, Component, EventEmitter, forwardRef, Input, Output, ViewChild } from '@angular/core'; import { FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { first, takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { gettext } from '../i18n'; import { BsDatepickerDirective, BsDatepickerModule } from 'ngx-bootstrap/datepicker'; import { NgSwitch, NgSwitchCase } from '@angular/common'; import { CloseDatePickerDirective } from './close-date-picker.directive'; import { TimepickerModule } from 'ngx-bootstrap/timepicker'; import { DatePickerComponent } from '../date-picker/date-picker.component'; import { C8yTranslatePipe } from '../i18n/c8y-translate.pipe'; import * as i0 from "@angular/core"; import * as i1 from "ngx-bootstrap/datepicker"; import * as i2 from "@angular/forms"; import * as i3 from "ngx-bootstrap/timepicker"; export class DateTimePickerComponent { set _minDate(value) { this.minDate = value ? new Date(value) : undefined; } set _maxDate(value) { this.maxDate = value ? new Date(value) : undefined; } constructor(cd) { this.cd = cd; this.dateInputFormat = 'YYYY-MM-DD'; this.adaptivePosition = false; /** * Specifies the type of date input. * * @param DateAndTime - Display both date and time. * @param Date - Display only the date without the time. * @param DateRange - Specify a range of dates. * @param SingleDateRequired - Require the selection of a single date. * @param Time - Display only the time without the date. * * @defaultValue 'DateAndTime' */ this.dateType = 'DateAndTime'; this.config = { showMeridian: false, showMinutes: true, showSeconds: false, showSpinners: false }; this.onDateSelected = new EventEmitter(); this.defaultPlaceholder = gettext('Select a date'); this.previousTimePickerValues = {}; this.destroy$ = new Subject(); // eslint-disable-next-line @typescript-eslint/no-empty-function this.onChange = () => { }; // eslint-disable-next-line @typescript-eslint/no-empty-function this.onTouched = () => { }; this.form = new FormGroup({}); this.form.addControl('date', new FormControl(null)); this.form.addControl('time', new FormControl(null)); this.form.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => { this.setDatetime(value); this.previousValue = value; }); this.form.statusChanges .pipe(first()) .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.onTouched(); }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } ngAfterViewInit() { this.cd.detectChanges(); } /** * Control Value Accessor - If form value changes by external factor, update date property and internal form with new value. */ writeValue(value) { if (typeof value === 'string' && value.length) { this.date = new Date(value); this.form.setValue({ date: new Date(value), time: this.date }, { emitEvent: false }); } else { this.form.setValue({ date: null, time: null }, { emitEvent: false }); } this.previousValue = this.form.value; } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(onTouched) { this.onTouched = onTouched; } setDisabledState(disabled) { if (disabled === this.form?.disabled) { return; } disabled ? this.form.disable() : this.form.enable(); } validate(_control) { if (this.date?.getTime() < new Date(this.minDate).getTime()) { return { dateBeforeRangeMin: true }; } else if (this.date?.getTime() > new Date(this.maxDate).getTime()) { return { dateAfterRangeMax: true }; } else if (this.form.invalid) { return { invalidDateTime: true }; } else { return null; } } previousDay() { const isOpen = this.datepicker.isOpen; this.date.setDate(this.date.getDate() - 1); this.setDatetime({ date: this.date, time: this.form.get('time').value }); if (isOpen) { this.datepicker.show(); } } nextDay() { const isOpen = this.datepicker.isOpen; this.date.setDate(this.date.getDate() + 1); this.setDatetime({ date: this.date, time: this.form.get('time').value }); if (isOpen) { this.datepicker.show(); } } hide() { this.datepicker.hide(); } handleMouseWheel(event) { const hours = this.form.get('time').value.getHours(); const minutes = this.form.get('time').value.getMinutes(); // down event.preventDefault(); if (event.deltaY > 0) { if (Number(hours) === 23 && this.previousTimePickerValues.hours !== 23) { this.previousDay(); } } // up if (event.deltaY < 0) { if (this.previousTimePickerValues.hours === undefined) { // scrolling up on empty form should not result in increasing day. } else if (Number(hours) === 0 && this.previousTimePickerValues.hours !== 0) { this.nextDay(); } } this.previousTimePickerValues = { hours, minutes }; } /** * If internal form changes its value, then combine date and time into one Date and pass its ISO string value to onChange method * @param dateTime * @private */ setDatetime(dateTime) { // if date input is cleared from a previous correct value, clear form value: if (this.isInputCleared(dateTime)) { this.form.get('date').setValue(undefined, { emitEvent: false }); this.form.get('time').setValue(undefined, { emitEvent: false }); this.onChange(null); return; } // if both date and time is invalid, do set form value to null and stop: if (!this.verifyDate(dateTime.date) && !this.verifyDate(dateTime.time)) { this.onChange(null); return; } // If only time is provided, set Date to today: if (!this.verifyDate(dateTime.date) && this.verifyDate(dateTime.time)) { dateTime.date = new Date(dateTime.time); } // If only date is provided, set time to 00:00: if (this.verifyDate(dateTime.date) && !this.verifyDate(dateTime.time)) { dateTime.time = new Date(dateTime.date.getFullYear(), dateTime.date.getMonth(), dateTime.date.getDate(), 0, 0, 0); this.form.get('time').setValue(dateTime.time, { emitEvent: false }); } // Merge date and time, and emit as new form value: this.date = new Date(dateTime.date); this.date.setHours(dateTime.time.getHours(), dateTime.time.getMinutes()); this.form.get('date').setValue(dateTime.date, { emitEvent: false }); this.onChange(this.date.toISOString()); } verifyDate(value) { const date = value; return date instanceof Date && !isNaN(date.getTime()); } isInputCleared(value) { return this.previousValue?.date && value.date === undefined; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DateTimePickerComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DateTimePickerComponent, isStandalone: true, selector: "c8y-date-time-picker", inputs: { _minDate: ["minDate", "_minDate"], _maxDate: ["maxDate", "_maxDate"], placeholder: "placeholder", dateInputFormat: "dateInputFormat", adaptivePosition: "adaptivePosition", size: "size", dateType: "dateType", config: "config" }, outputs: { onDateSelected: "onDateSelected" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimePickerComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => DateTimePickerComponent), multi: true } ], viewQueries: [{ propertyName: "datepicker", first: true, predicate: BsDatepickerDirective, descendants: true }], ngImport: i0, template: "<div\n class=\"datetime-picker\"\n [ngSwitch]=\"dateType\"\n>\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'DateAndTime'\"\n [closeDatepicker]=\"datepicker\"\n >\n <div class=\"form-group datepicker {{ size ? 'form-group-' + size : '' }}\">\n <input\n class=\"form-control\"\n style=\"min-width: 120px\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [outsideClick]=\"false\"\n [bsConfig]=\"{\n customTodayClass: 'today',\n dateInputFormat: dateInputFormat,\n adaptivePosition: adaptivePosition\n }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n <timepicker\n class=\"form-group {{ size ? 'form-group-' + size : '' }}\"\n [formControl]=\"form.get('time')\"\n [showSeconds]=\"config.showSeconds\"\n [showSpinners]=\"config.showSpinners\"\n [showMeridian]=\"config.showMeridian\"\n (wheel)=\"handleMouseWheel($event)\"\n ></timepicker>\n </div>\n\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'Date'\"\n [closeDatepicker]=\"datepicker\"\n >\n <div class=\"form-group datepicker {{ size ? 'form-group-' + size : '' }}\">\n <input\n class=\"form-control\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [outsideClick]=\"false\"\n [bsConfig]=\"{\n customTodayClass: 'today',\n dateInputFormat: dateInputFormat,\n adaptivePosition: adaptivePosition\n }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n </div>\n\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'DateRange'\"\n >\n <div class=\"form-group datepicker {{ size ? 'form-group-' + size : '' }}\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Select a date range' | translate }}\"\n [formControl]=\"form.get('date')\"\n [bsConfig]=\"{\n customTodayClass: 'today',\n adaptivePosition: true,\n rangeInputFormat: dateInputFormat\n }\"\n bsDaterangepicker\n />\n </div>\n </div>\n\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'Time'\"\n >\n <timepicker\n class=\"form-group {{ size ? 'form-group-' + size : '' }}\"\n [formControl]=\"form.get('time')\"\n [showSeconds]=\"config.showSeconds\"\n [showSpinners]=\"config.showSpinners\"\n [showMeridian]=\"config.showMeridian\"\n [minutesPlaceholder]=\"'MM`MINUTES`' | translate\"\n [hoursPlaceholder]=\"'HH`HOURS`' | translate\"\n [secondsPlaceholder]=\"'SS`SECONDS`' | translate\"\n (wheel)=\"handleMouseWheel($event)\"\n ></timepicker>\n </div>\n\n <div *ngSwitchCase=\"'SingleDateRequired'\">\n <div class=\"form-group {{ size ? 'form-group-' + size : '' }}\">\n <c8y-date-picker (onDateSelected)=\"onDateSelected.emit($event)\"></c8y-date-picker>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: CloseDatePickerDirective, selector: "[closeDatepicker]", inputs: ["closeDatepicker"] }, { kind: "ngmodule", type: BsDatepickerModule }, { kind: "directive", type: i1.BsDatepickerDirective, selector: "[bsDatepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isDisabled", "minDate", "maxDate", "minMode", "daysDisabled", "datesDisabled", "datesEnabled", "dateCustomClasses", "dateTooltipTexts", "isOpen", "bsValue", "bsConfig"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDatepicker"] }, { kind: "directive", type: i1.BsDatepickerInputDirective, selector: "input[bsDatepicker]" }, { kind: "directive", type: i1.BsDaterangepickerDirective, selector: "[bsDaterangepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isOpen", "bsValue", "bsConfig", "isDisabled", "minDate", "maxDate", "dateCustomClasses", "daysDisabled", "datesDisabled", "datesEnabled"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDaterangepicker"] }, { kind: "directive", type: i1.BsDaterangepickerInputDirective, selector: "input[bsDaterangepicker]" }, { kind: "ngmodule", type: FormsModule }, { 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: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TimepickerModule }, { kind: "component", type: i3.TimepickerComponent, selector: "timepicker", inputs: ["hourStep", "minuteStep", "secondsStep", "readonlyInput", "disabled", "mousewheel", "arrowkeys", "showSpinners", "showMeridian", "showMinutes", "showSeconds", "meridians", "min", "max", "hoursPlaceholder", "minutesPlaceholder", "secondsPlaceholder"], outputs: ["isValid", "meridianChange"] }, { kind: "component", type: DatePickerComponent, selector: "c8y-date-picker", inputs: ["placeholder"], outputs: ["onDateSelected"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DateTimePickerComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-date-time-picker', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimePickerComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => DateTimePickerComponent), multi: true } ], standalone: true, imports: [ NgSwitch, NgSwitchCase, CloseDatePickerDirective, BsDatepickerModule, FormsModule, ReactiveFormsModule, TimepickerModule, DatePickerComponent, C8yTranslatePipe ], template: "<div\n class=\"datetime-picker\"\n [ngSwitch]=\"dateType\"\n>\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'DateAndTime'\"\n [closeDatepicker]=\"datepicker\"\n >\n <div class=\"form-group datepicker {{ size ? 'form-group-' + size : '' }}\">\n <input\n class=\"form-control\"\n style=\"min-width: 120px\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [outsideClick]=\"false\"\n [bsConfig]=\"{\n customTodayClass: 'today',\n dateInputFormat: dateInputFormat,\n adaptivePosition: adaptivePosition\n }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n <timepicker\n class=\"form-group {{ size ? 'form-group-' + size : '' }}\"\n [formControl]=\"form.get('time')\"\n [showSeconds]=\"config.showSeconds\"\n [showSpinners]=\"config.showSpinners\"\n [showMeridian]=\"config.showMeridian\"\n (wheel)=\"handleMouseWheel($event)\"\n ></timepicker>\n </div>\n\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'Date'\"\n [closeDatepicker]=\"datepicker\"\n >\n <div class=\"form-group datepicker {{ size ? 'form-group-' + size : '' }}\">\n <input\n class=\"form-control\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [outsideClick]=\"false\"\n [bsConfig]=\"{\n customTodayClass: 'today',\n dateInputFormat: dateInputFormat,\n adaptivePosition: adaptivePosition\n }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n </div>\n\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'DateRange'\"\n >\n <div class=\"form-group datepicker {{ size ? 'form-group-' + size : '' }}\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Select a date range' | translate }}\"\n [formControl]=\"form.get('date')\"\n [bsConfig]=\"{\n customTodayClass: 'today',\n adaptivePosition: true,\n rangeInputFormat: dateInputFormat\n }\"\n bsDaterangepicker\n />\n </div>\n </div>\n\n <div\n class=\"d-contents\"\n *ngSwitchCase=\"'Time'\"\n >\n <timepicker\n class=\"form-group {{ size ? 'form-group-' + size : '' }}\"\n [formControl]=\"form.get('time')\"\n [showSeconds]=\"config.showSeconds\"\n [showSpinners]=\"config.showSpinners\"\n [showMeridian]=\"config.showMeridian\"\n [minutesPlaceholder]=\"'MM`MINUTES`' | translate\"\n [hoursPlaceholder]=\"'HH`HOURS`' | translate\"\n [secondsPlaceholder]=\"'SS`SECONDS`' | translate\"\n (wheel)=\"handleMouseWheel($event)\"\n ></timepicker>\n </div>\n\n <div *ngSwitchCase=\"'SingleDateRequired'\">\n <div class=\"form-group {{ size ? 'form-group-' + size : '' }}\">\n <c8y-date-picker (onDateSelected)=\"onDateSelected.emit($event)\"></c8y-date-picker>\n </div>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { _minDate: [{ type: Input, args: ['minDate'] }], _maxDate: [{ type: Input, args: ['maxDate'] }], placeholder: [{ type: Input }], dateInputFormat: [{ type: Input }], adaptivePosition: [{ type: Input }], size: [{ type: Input }], dateType: [{ type: Input }], config: [{ type: Input }], onDateSelected: [{ type: Output }], datepicker: [{ type: ViewChild, args: [BsDatepickerDirective] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL2RhdGUtdGltZS1waWNrZXIvZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9jb3JlL2RhdGUtdGltZS1waWNrZXIvZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFHTCxXQUFXLEVBQ1gsU0FBUyxFQUNULGFBQWEsRUFDYixpQkFBaUIsRUFHakIsV0FBVyxFQUNYLG1CQUFtQixFQUNwQixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXJGLE9BQU8sRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDekUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDNUQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDM0UsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7O0FBNEM5RCxNQUFNLE9BQU8sdUJBQXVCO0lBR2xDLElBQ0ksUUFBUSxDQUFDLEtBQWE7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDckQsQ0FBQztJQUlELElBQ0ksUUFBUSxDQUFDLEtBQWE7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDckQsQ0FBQztJQWtERCxZQUFvQixFQUFxQjtRQUFyQixPQUFFLEdBQUYsRUFBRSxDQUFtQjtRQTVDekMsb0JBQWUsR0FBRyxZQUFZLENBQUM7UUFHL0IscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBS3pCOzs7Ozs7Ozs7O1dBVUc7UUFFSCxhQUFRLEdBQWEsYUFBYSxDQUFDO1FBR25DLFdBQU0sR0FBdUI7WUFDM0IsWUFBWSxFQUFFLEtBQUs7WUFDbkIsV0FBVyxFQUFFLElBQUk7WUFDakIsV0FBVyxFQUFFLEtBQUs7WUFDbEIsWUFBWSxFQUFFLEtBQUs7U0FDcEIsQ0FBQztRQUdGLG1CQUFjLEdBQThCLElBQUksWUFBWSxFQUFFLENBQUM7UUFLL0QsdUJBQWtCLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFLdkMsNkJBQXdCLEdBQXlDLEVBQUUsQ0FBQztRQUNwRSxhQUFRLEdBQWtCLElBQUksT0FBTyxFQUFFLENBQUM7UUFrQmhELGdFQUFnRTtRQUNoRSxhQUFRLEdBQTRCLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztRQUM3QyxnRUFBZ0U7UUFDaEUsY0FBUyxHQUFlLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztRQWxCL0IsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQWtCLEVBQUUsRUFBRTtZQUNyRixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzdCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhO2FBQ3BCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNiLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQzlCLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBT0QsV0FBVztRQUNULElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsVUFBVSxDQUFDLEtBQWE7UUFDdEIsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzlDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQ2hCO2dCQUNFLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUM7Z0JBQ3JCLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTthQUNoQixFQUNELEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUNyQixDQUFDO1FBQ0osQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDdkUsQ0FBQztRQUNELElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDdkMsQ0FBQztJQUVELGdCQUFnQixDQUFDLEVBQU87UUFDdEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVELGlCQUFpQixDQUFDLFNBQWM7UUFDOUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7SUFDN0IsQ0FBQztJQUVELGdCQUFnQixDQUFDLFFBQWlCO1FBQ2hDLElBQUksUUFBUSxLQUFLLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7WUFDckMsT0FBTztRQUNULENBQUM7UUFDRCxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQUVELFFBQVEsQ0FBQyxRQUF5QjtRQUNoQyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDNUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxDQUFDO1FBQ3RDLENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDbkUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLElBQUksRUFBRSxDQUFDO1FBQ3JDLENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDN0IsT0FBTyxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUNuQyxDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekUsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNYLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDekIsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPO1FBQ0wsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekUsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNYLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDekIsQ0FBQztJQUNILENBQUM7SUFFRCxJQUFJO1FBQ0YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQsZ0JBQWdCLENBQUMsS0FBaUI7UUFDaEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN6RCxPQUFPO1FBQ1AsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNyQixJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksSUFBSSxDQUFDLHdCQUF3QixDQUFDLEtBQUssS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDdkUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO1FBRUQsS0FBSztRQUNMLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNyQixJQUFJLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3RELGtFQUFrRTtZQUNwRSxDQUFDO2lCQUFNLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsd0JBQXdCLENBQUMsS0FBSyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUM1RSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakIsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLENBQUMsd0JBQXdCLEdBQUcsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDckQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxXQUFXLENBQUMsUUFBcUI7UUFDdkMsNEVBQTRFO1FBQzVFLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUNoRSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDaEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNwQixPQUFPO1FBQ1QsQ0FBQztRQUVELHdFQUF3RTtRQUN4RSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3ZFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEIsT0FBTztRQUNULENBQUM7UUFDRCwrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDdEUsUUFBUSxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUMsQ0FBQztRQUVELCtDQUErQztRQUMvQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN0RSxRQUFRLENBQUMsSUFBSSxHQUFHLElBQUksSUFBSSxDQUN0QixRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUMzQixRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUN4QixRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUN2QixDQUFDLEVBQ0QsQ0FBQyxFQUNELENBQUMsQ0FDRixDQUFDO1lBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUN0RSxDQUFDO1FBRUQsbURBQW1EO1FBQ25ELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ3pFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDcEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVPLFVBQVUsQ0FBQyxLQUFXO1FBQzVCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQztRQUNuQixPQUFPLElBQUksWUFBWSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVPLGNBQWMsQ0FBQyxLQUFrQjtRQUN2QyxPQUFPLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDO0lBQzlELENBQUM7K0dBMU9VLHVCQUF1QjttR0FBdkIsdUJBQXVCLGdXQXpCdkI7WUFDVDtnQkFDRSxPQUFPLEVBQUUsaUJBQWlCO2dCQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLHVCQUF1QixDQUFDO2dCQUN0RCxLQUFLLEVBQUUsSUFBSTthQUNaO1lBQ0Q7Z0JBQ0UsT0FBTyxFQUFFLGFBQWE7Z0JBQ3RCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsdUJBQXVCLENBQUM7Z0JBQ3RELEtBQUssRUFBRSxJQUFJO2FBQ1o7U0FDRixzRUF1RVUscUJBQXFCLGdEQ3BJbEMsaW5HQXVHQSw0Q0R2Q0ksUUFBUSw2RUFDUixZQUFZLHFGQUNaLHdCQUF3QiwwRkFDeEIsa0JBQWtCLHNnQ0FDbEIsV0FBVyxzWkFDWCxtQkFBbUIsaU5BQ25CLGdCQUFnQix3WkFDaEIsbUJBQW1CLDZHQUNuQixnQkFBZ0I7OzRGQUdQLHVCQUF1QjtrQkE1Qm5DLFNBQVM7K0JBQ0Usc0JBQXNCLGFBRXJCO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHdCQUF3QixDQUFDOzRCQUN0RCxLQUFLLEVBQUUsSUFBSTt5QkFDWjt3QkFDRDs0QkFDRSxPQUFPLEVBQUUsYUFBYTs0QkFDdEIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsd0JBQXdCLENBQUM7NEJBQ3RELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGLGNBQ1csSUFBSSxXQUNQO3dCQUNQLFFBQVE7d0JBQ1IsWUFBWTt3QkFDWix3QkFBd0I7d0JBQ3hCLGtCQUFrQjt3QkFDbEIsV0FBVzt3QkFDWCxtQkFBbUI7d0JBQ25CLGdCQUFnQjt3QkFDaEIsbUJBQW1CO3dCQUNuQixnQkFBZ0I7cUJBQ2pCO3NGQU1HLFFBQVE7c0JBRFgsS0FBSzt1QkFBQyxTQUFTO2dCQVFaLFFBQVE7c0JBRFgsS0FBSzt1QkFBQyxTQUFTO2dCQU1oQixXQUFXO3NCQURWLEtBQUs7Z0JBSU4sZUFBZTtzQkFEZCxLQUFLO2dCQUlOLGdCQUFnQjtzQkFEZixLQUFLO2dCQUlOLElBQUk7c0JBREgsS0FBSztnQkFlTixRQUFRO3NCQURQLEtBQUs7Z0JBSU4sTUFBTTtzQkFETCxLQUFLO2dCQVNOLGNBQWM7c0JBRGIsTUFBTTtnQkFRMkIsVUFBVTtzQkFBM0MsU0FBUzt1QkFBQyxxQkFBcUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RDb250cm9sLFxuICBDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgRm9ybUNvbnRyb2wsXG4gIEZvcm1Hcm91cCxcbiAgTkdfVkFMSURBVE9SUyxcbiAgTkdfVkFMVUVfQUNDRVNTT1IsXG4gIFZhbGlkYXRpb25FcnJvcnMsXG4gIFZhbGlkYXRvcixcbiAgRm9ybXNNb2R1bGUsXG4gIFJlYWN0aXZlRm9ybXNNb2R1bGVcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgZmlyc3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICcuLi9pMThuJztcbmltcG9ydCB7IEJzRGF0ZXBpY2tlckRpcmVjdGl2ZSwgQnNEYXRlcGlja2VyTW9kdWxlIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9kYXRlcGlja2VyJztcbmltcG9ydCB7IFBpY2tlZERhdGVzIH0gZnJvbSAnLi4vZGF0ZS1waWNrZXInO1xuaW1wb3J0IHsgTmdTd2l0Y2gsIE5nU3dpdGNoQ2FzZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDbG9zZURhdGVQaWNrZXJEaXJlY3RpdmUgfSBmcm9tICcuL2Nsb3NlLWRhdGUtcGlja2VyLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBUaW1lcGlja2VyTW9kdWxlIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC90aW1lcGlja2VyJztcbmltcG9ydCB7IERhdGVQaWNrZXJDb21wb25lbnQgfSBmcm9tICcuLi9kYXRlLXBpY2tlci9kYXRlLXBpY2tlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgQzh5VHJhbnNsYXRlUGlwZSB9IGZyb20gJy4uL2kxOG4vYzh5LXRyYW5zbGF0ZS5waXBlJztcblxuaW50ZXJmYWNlIERhdGVBbmRUaW1lIHtcbiAgZGF0ZTogRGF0ZTtcbiAgdGltZTogRGF0ZTtcbn1cblxuaW50ZXJmYWNlIERhdGVBbmRUaW1lT3B0aW9ucyB7XG4gIHNob3dTcGlubmVycz86IGJvb2xlYW47XG4gIHNob3dNZXJpZGlhbj86IGJvb2xlYW47XG4gIHNob3dNaW51dGVzPzogYm9vbGVhbjtcbiAgc2hvd1NlY29uZHM/OiBib29sZWFuO1xufVxuXG5leHBvcnQgdHlwZSBEYXRlVHlwZSA9ICdEYXRlQW5kVGltZScgfCAnRGF0ZScgfCAnRGF0ZVJhbmdlJyB8ICdTaW5nbGVEYXRlUmVxdWlyZWQnIHwgJ1RpbWUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktZGF0ZS10aW1lLXBpY2tlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9kYXRlLXRpbWUtcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBEYXRlVGltZVBpY2tlckNvbXBvbmVudCksXG4gICAgICBtdWx0aTogdHJ1ZVxuICAgIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMSURBVE9SUyxcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVUaW1lUGlja2VyQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgTmdTd2l0Y2gsXG4gICAgTmdTd2l0Y2hDYXNlLFxuICAgIENsb3NlRGF0ZVBpY2tlckRpcmVjdGl2ZSxcbiAgICBCc0RhdGVwaWNrZXJNb2R1bGUsXG4gICAgRm9ybXNNb2R1bGUsXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICBUaW1lcGlja2VyTW9kdWxlLFxuICAgIERhdGVQaWNrZXJDb21wb25lbnQsXG4gICAgQzh5VHJhbnNsYXRlUGlwZVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIERhdGVUaW1lUGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIFZhbGlkYXRvciwgT25EZXN0cm95IHtcbiAgbWluRGF0ZTogRGF0ZTtcblxuICBASW5wdXQoJ21pbkRhdGUnKVxuICBzZXQgX21pbkRhdGUodmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMubWluRGF0ZSA9IHZhbHVlID8gbmV3IERhdGUodmFsdWUpIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgbWF4RGF0ZTogRGF0ZTtcblxuICBASW5wdXQoJ21heERhdGUnKVxuICBzZXQgX21heERhdGUodmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMubWF4RGF0ZSA9IHZhbHVlID8gbmV3IERhdGUodmFsdWUpIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgQElucHV0KClcbiAgcGxhY2Vob2xkZXI6IHN0cmluZztcblxuICBASW5wdXQoKVxuICBkYXRlSW5wdXRGb3JtYXQgPSAnWVlZWS1NTS1ERCc7XG5cbiAgQElucHV0KClcbiAgYWRhcHRpdmVQb3NpdGlvbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpXG4gIHNpemU6IHN0cmluZztcblxuICAvKipcbiAgICogU3BlY2lmaWVzIHRoZSB0eXBlIG9mIGRhdGUgaW5wdXQuXG4gICAqXG4gICAqIEBwYXJhbSBEYXRlQW5kVGltZSAtIERpc3BsYXkgYm90aCBkYXRlIGFuZCB0aW1lLlxuICAgKiBAcGFyYW0gRGF0ZSAtIERpc3BsYXkgb25seSB0aGUgZGF0ZSB3aXRob3V0IHRoZSB0aW1lLlxuICAgKiBAcGFyYW0gRGF0ZVJhbmdlIC0gU3BlY2lmeSBhIHJhbmdlIG9mIGRhdGVzLlxuICAgKiBAcGFyYW0gU2luZ2xlRGF0ZVJlcXVpcmVkIC0gUmVxdWlyZSB0aGUgc2VsZWN0aW9uIG9mIGEgc2luZ2xlIGRhdGUuXG4gICAqIEBwYXJhbSBUaW1lIC0gRGlzcGxheSBvbmx5IHRoZSB0aW1lIHdpdGhvdXQgdGhlIGRhdGUuXG4gICAqXG4gICAqIEBkZWZhdWx0VmFsdWUgJ0RhdGVBbmRUaW1lJ1xuICAgKi9cbiAgQElucHV0KClcbiAgZGF0ZVR5cGU6IERhdGVUeXBlID0gJ0RhdGVBbmRUaW1lJztcblxuICBASW5wdXQoKVxuICBjb25maWc6IERhdGVBbmRUaW1lT3B0aW9ucyA9IHtcbiAgICBzaG93TWVyaWRpYW46IGZhbHNlLFxuICAgIHNob3dNaW51dGVzOiB0cnVlLFxuICAgIHNob3dTZWNvbmRzOiBmYWxzZSxcbiAgICBzaG93U3Bpbm5lcnM6IGZhbHNlXG4gIH07XG5cbiAgQE91dHB1dCgpXG4gIG9uRGF0ZVNlbGVjdGVkOiBFdmVudEVtaXR0ZXI8UGlja2VkRGF0ZXM+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGRhdGU6IERhdGU7XG4gIGZvcm06IEZvcm1Hcm91cDtcblxuICBkZWZhdWx0UGxhY2Vob2xkZXIgPSBnZXR0ZXh0KCdTZWxlY3QgYSBkYXRl4oCmJyk7XG5cbiAgQFZpZXdDaGlsZChCc0RhdGVwaWNrZXJEaXJlY3RpdmUpIGRhdGVwaWNrZXI6IEJzRGF0ZXBpY2tlckRpcmVjdGl2ZTtcblxuICBwcml2YXRlIHByZXZpb3VzVmFsdWU6IERhdGVBbmRUaW1lO1xuICBwcml2YXRlIHByZXZpb3VzVGltZVBpY2tlclZhbHVlczogeyBob3Vycz86IG51bWJlcjsgbWludXRlcz86IG51bWJlciB9ID0ge307XG4gIHByaXZhdGUgZGVzdHJveSQ6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2Q6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgdGhpcy5mb3JtID0gbmV3IEZvcm1Hcm91cCh7fSk7XG4gICAgdGhpcy5mb3JtLmFkZENvbnRyb2woJ2RhdGUnLCBuZXcgRm9ybUNvbnRyb2wobnVsbCkpO1xuICAgIHRoaXMuZm9ybS5hZGRDb250cm9sKCd0aW1lJywgbmV3IEZvcm1Db250cm9sKG51bGwpKTtcbiAgICB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoKHZhbHVlOiBEYXRlQW5kVGltZSkgPT4ge1xuICAgICAgdGhpcy5zZXREYXRldGltZSh2YWx1ZSk7XG4gICAgICB0aGlzLnByZXZpb3VzVmFsdWUgPSB2YWx1ZTtcbiAgICB9KTtcbiAgICB0aGlzLmZvcm0uc3RhdHVzQ2hhbmdlc1xuICAgICAgLnBpcGUoZmlyc3QoKSlcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG4gIG9uQ2hhbmdlOiAodmFsdWU6IHN0cmluZykgPT4gdm9pZCA9ICgpID0+IHt9O1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG4gIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb250cm9sIFZhbHVlIEFjY2Vzc29yIC0gSWYgZm9ybSB2YWx1ZSBjaGFuZ2VzIGJ5IGV4dGVybmFsIGZhY3RvciwgdXBkYXRlIGRhdGUgcHJvcGVydHkgYW5kIGludGVybmFsIGZvcm0gd2l0aCBuZXcgdmFsdWUuXG4gICAqL1xuICB3cml0ZVZhbHVlKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZGF0ZSA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICAgIHRoaXMuZm9ybS5zZXRWYWx1ZShcbiAgICAgICAge1xuICAgICAgICAgIGRhdGU6IG5ldyBEYXRlKHZhbHVlKSxcbiAgICAgICAgICB0aW1lOiB0aGlzLmRhdGVcbiAgICAgICAgfSxcbiAgICAgICAgeyBlbWl0RXZlbnQ6IGZhbHNlIH1cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZm9ybS5zZXRWYWx1ZSh7IGRhdGU6IG51bGwsIHRpbWU6IG51bGwgfSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH1cbiAgICB0aGlzLnByZXZpb3VzVmFsdWUgPSB0aGlzLmZvcm0udmFsdWU7XG4gIH1cblxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChvblRvdWNoZWQ6IGFueSkge1xuICAgIHRoaXMub25Ub3VjaGVkID0gb25Ub3VjaGVkO1xuICB9XG5cbiAgc2V0RGlzYWJsZWRTdGF0ZShkaXNhYmxlZDogYm9vbGVhbikge1xuICAgIGlmIChkaXNhYmxlZCA9PT0gdGhpcy5mb3JtPy5kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkaXNhYmxlZCA/IHRoaXMuZm9ybS5kaXNhYmxlKCkgOiB0aGlzLmZvcm0uZW5hYmxlKCk7XG4gIH1cblxuICB2YWxpZGF0ZShfY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogVmFsaWRhdGlvbkVycm9ycyB8IG51bGwge1xuICAgIGlmICh0aGlzLmRhdGU/LmdldFRpbWUoKSA8IG5ldyBEYXRlKHRoaXMubWluRGF0ZSkuZ2V0VGltZSgpKSB7XG4gICAgICByZXR1cm4geyBkYXRlQmVmb3JlUmFuZ2VNaW46IHRydWUgfTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZGF0ZT8uZ2V0VGltZSgpID4gbmV3IERhdGUodGhpcy5tYXhEYXRlKS5nZXRUaW1lKCkpIHtcbiAgICAgIHJldHVybiB7IGRhdGVBZnRlclJhbmdlTWF4OiB0cnVlIH07XG4gICAgfSBlbHNlIGlmICh0aGlzLmZvcm0uaW52YWxpZCkge1xuICAgICAgcmV0dXJuIHsgaW52YWxpZERhdGVUaW1lOiB0cnVlIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHByZXZpb3VzRGF5KCkge1xuICAgIGNvbnN0IGlzT3BlbiA9IHRoaXMuZGF0ZXBpY2tlci5pc09wZW47XG4gICAgdGhpcy5kYXRlLnNldERhdGUodGhpcy5kYXRlLmdldERhdGUoKSAtIDEpO1xuICAgIHRoaXMuc2V0RGF0ZXRpbWUoeyBkYXRlOiB0aGlzLmRhdGUsIHRpbWU6IHRoaXMuZm9ybS5nZXQoJ3RpbWUnKS52YWx1ZSB9KTtcbiAgICBpZiAoaXNPcGVuKSB7XG4gICAgICB0aGlzLmRhdGVwaWNrZXIuc2hvdygpO1xuICAgIH1cbiAgfVxuXG4gIG5leHREYXkoKSB7XG4gICAgY29uc3QgaXNPcGVuID0gdGhpcy5kYXRlcGlja2VyLmlzT3BlbjtcbiAgICB0aGlzLmRhdGUuc2V0RGF0ZSh0aGlzLmRhdGUuZ2V0RGF0ZSgpICsgMSk7XG4gICAgdGhpcy5zZXREYXRldGltZSh7IGRhdGU6IHRoaXMuZGF0ZSwgdGltZTogdGhpcy5mb3JtLmdldCgndGltZScpLnZhbHVlIH0pO1xuICAgIGlmIChpc09wZW4pIHtcbiAgICAgIHRoaXMuZGF0ZXBpY2tlci5zaG93KCk7XG4gICAgfVxuICB9XG5cbiAgaGlkZSgpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGVwaWNrZXIuaGlkZSgpO1xuICB9XG5cbiAgaGFuZGxlTW91c2VXaGVlbChldmVudDogV2hlZWxFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGhvdXJzID0gdGhpcy5mb3JtLmdldCgndGltZScpLnZhbHVlLmdldEhvdXJzKCk7XG4gICAgY29uc3QgbWludXRlcyA9IHRoaXMuZm9ybS5nZXQoJ3RpbWUnKS52YWx1ZS5nZXRNaW51dGVzKCk7XG4gICAgLy8gZG93blxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgaWYgKGV2ZW50LmRlbHRhWSA+IDApIHtcbiAgICAgIGlmIChOdW1iZXIoaG91cnMpID09PSAyMyAmJiB0aGlzLnByZXZpb3VzVGltZVBpY2tlclZhbHVlcy5ob3VycyAhPT0gMjMpIHtcbiAgICAgICAgdGhpcy5wcmV2aW91c0RheSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHVwXG4gICAgaWYgKGV2ZW50LmRlbHRhWSA8IDApIHtcbiAgICAgIGlmICh0aGlzLnByZXZpb3VzVGltZVBpY2tlclZhbHVlcy5ob3VycyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIHNjcm9sbGluZyB1cCBvbiBlbXB0eSBmb3JtIHNob3VsZCBub3QgcmVzdWx0IGluIGluY3JlYXNpbmcgZGF5LlxuICAgICAgfSBlbHNlIGlmIChOdW1iZXIoaG91cnMpID09PSAwICYmIHRoaXMucHJldmlvdXNUaW1lUGlja2VyVmFsdWVzLmhvdXJzICE9PSAwKSB7XG4gICAgICAgIHRoaXMubmV4dERheSgpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnByZXZpb3VzVGltZVBpY2tlclZhbHVlcyA9IHsgaG91cnMsIG1pbnV0ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiBpbnRlcm5hbCBmb3JtIGNoYW5nZXMgaXRzIHZhbHVlLCB0aGVuIGNvbWJpbmUgZGF0ZSBhbmQgdGltZSBpbnRvIG9uZSBEYXRlIGFuZCBwYXNzIGl0cyBJU08gc3RyaW5nIHZhbHVlIHRvIG9uQ2hhbmdlIG1ldGhvZFxuICAgKiBAcGFyYW0gZGF0ZVRpbWVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgc2V0RGF0ZXRpbWUoZGF0ZVRpbWU6IERhdGVBbmRUaW1lKSB7XG4gICAgLy8gaWYgZGF0ZSBpbnB1dCBpcyBjbGVhcmVkIGZyb20gYSBwcmV2aW91cyBjb3JyZWN0IHZhbHVlLCBjbGVhciBmb3JtIHZhbHVlOlxuICAgIGlmICh0aGlzLmlzSW5wdXRDbGVhcmVkKGRhdGVUaW1lKSkge1xuICAgICAgdGhpcy5mb3JtLmdldCgnZGF0ZScpLnNldFZhbHVlKHVuZGVmaW5lZCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgdGhpcy5mb3JtLmdldCgndGltZScpLnNldFZhbHVlKHVuZGVmaW5lZCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgdGhpcy5vbkNoYW5nZShudWxsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBpZiBib3RoIGRhdGUgYW5kIHRpbWUgaXMgaW52YWxpZCwgZG8gc2V0IGZvcm0gdmFsdWUgdG8gbnVsbCBhbmQgc3RvcDpcbiAgICBpZiAoIXRoaXMudmVyaWZ5RGF0ZShkYXRlVGltZS5kYXRlKSAmJiAhdGhpcy52ZXJpZnlEYXRlKGRhdGVUaW1lLnRpbWUpKSB7XG4gICAgICB0aGlzLm9uQ2hhbmdlKG51bGwpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBJZiBvbmx5IHRpbWUgaXMgcHJvdmlkZWQsIHNldCBEYXRlIHRvIHRvZGF5OlxuICAgIGlmICghdGhpcy52ZXJpZnlEYXRlKGRhdGVUaW1lLmRhdGUpICYmIHRoaXMudmVyaWZ5RGF0ZShkYXRlVGltZS50aW1lKSkge1xuICAgICAgZGF0ZVRpbWUuZGF0ZSA9IG5ldyBEYXRlKGRhdGVUaW1lLnRpbWUpO1xuICAgIH1cblxuICAgIC8vIElmIG9ubHkgZGF0ZSBpcyBwcm92aWRlZCwgc2V0IHRpbWUgdG8gMDA6MDA6XG4gICAgaWYgKHRoaXMudmVyaWZ5RGF0ZShkYXRlVGltZS5kYXRlKSAmJiAhdGhpcy52ZXJpZnlEYXRlKGRhdGVUaW1lLnRpbWUpKSB7XG4gICAgICBkYXRlVGltZS50aW1lID0gbmV3IERhdGUoXG4gICAgICAgIGRhdGVUaW1lLmRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgICAgZGF0ZVRpbWUuZGF0ZS5nZXRNb250aCgpLFxuICAgICAgICBkYXRlVGltZS5kYXRlLmdldERhdGUoKSxcbiAgICAgICAgMCxcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgKTtcbiAgICAgIHRoaXMuZm9ybS5nZXQoJ3RpbWUnKS5zZXRWYWx1ZShkYXRlVGltZS50aW1lLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgfVxuXG4gICAgLy8gTWVyZ2UgZGF0ZSBhbmQgdGltZSwgYW5kIGVtaXQgYXMgbmV3IGZvcm0gdmFsdWU6XG4gICAgdGhpcy5kYXRlID0gbmV3IERhdGUoZGF0ZVRpbWUuZGF0ZSk7XG4gICAgdGhpcy5kYXRlLnNldEhvdXJzKGRhdGVUaW1lLnRpbWUuZ2V0SG91cnMoKSwgZGF0ZVRpbWUudGltZS5nZXRNaW51dGVzKCkpO1xuICAgIHRoaXMuZm9ybS5nZXQoJ2RhdGUnKS5zZXRWYWx1ZShkYXRlVGltZS5kYXRlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgdGhpcy5vbkNoYW5nZSh0aGlzLmRhdGUudG9JU09TdHJpbmcoKSk7XG4gIH1cblxuICBwcml2YXRlIHZlcmlmeURhdGUodmFsdWU6IERhdGUpOiBib29sZWFuIHtcbiAgICBjb25zdCBkYXRlID0gdmFsdWU7XG4gICAgcmV0dXJuIGRhdGUgaW5zdGFuY2VvZiBEYXRlICYmICFpc05hTihkYXRlLmdldFRpbWUoKSk7XG4gIH1cblxuICBwcml2YXRlIGlzSW5wdXRDbGVhcmVkKHZhbHVlOiBEYXRlQW5kVGltZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnByZXZpb3VzVmFsdWU/LmRhdGUgJiYgdmFsdWUuZGF0ZSA9PT0gdW5kZWZpbmVkO1xuICB9XG59XG4iLCI8ZGl2XG4gIGNsYXNzPVwiZGF0ZXRpbWUtcGlja2VyXCJcbiAgW25nU3dpdGNoXT1cImRhdGVUeXBlXCJcbj5cbiAgPGRpdlxuICAgIGNsYXNzPVwiZC1jb250ZW50c1wiXG4gICAgKm5nU3dpdGNoQ2FzZT1cIidEYXRlQW5kVGltZSdcIlxuICAgIFtjbG9zZURhdGVwaWNrZXJdPVwiZGF0ZXBpY2tlclwiXG4gID5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBkYXRlcGlja2VyIHt7IHNpemUgPyAnZm9ybS1ncm91cC0nICsgc2l6ZSA6ICcnIH19XCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICBzdHlsZT1cIm1pbi13aWR0aDogMTIwcHhcIlxuICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXIgfHwgZGVmYXVsdFBsYWNlaG9sZGVyIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgYnNEYXRlcGlja2VyXG4gICAgICAgIFtvdXRzaWRlQ2xpY2tdPVwiZmFsc2VcIlxuICAgICAgICBbYnNDb25maWddPVwie1xuICAgICAgICAgIGN1c3RvbVRvZGF5Q2xhc3M6ICd0b2RheScsXG4gICAgICAgICAgZGF0ZUlucHV0Rm9ybWF0OiBkYXRlSW5wdXRGb3JtYXQsXG4gICAgICAgICAgYWRhcHRpdmVQb3NpdGlvbjogYWRhcHRpdmVQb3NpdGlvblxuICAgICAgICB9XCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KCdkYXRlJylcIlxuICAgICAgICAoYmx1cik9XCJvblRvdWNoZWQoKVwiXG4gICAgICAgIFttaW5EYXRlXT1cIm1pbkRhdGVcIlxuICAgICAgICBbbWF4RGF0ZV09XCJtYXhEYXRlXCJcbiAgICAgIC8+XG4gICAgPC9kaXY+XG4gICAgPHRpbWVwaWNrZXJcbiAgICAgIGNsYXNzPVwiZm9ybS1ncm91cCB7eyBzaXplID8gJ2Zvcm0tZ3JvdXAtJyArIHNpemUgOiAnJyB9fVwiXG4gICAgICBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoJ3RpbWUnKVwiXG4gICAgICBbc2hvd1NlY29uZHNdPVwiY29uZmlnLnNob3dTZWNvbmRzXCJcbiAgICAgIFtzaG93U3Bpbm5lcnNdPVwiY29uZmlnLnNob3dTcGlubmVyc1wiXG4gICAgICBbc2hvd01lcmlkaWFuXT1cImNvbmZpZy5zaG93TWVyaWRpYW5cIlxuICAgICAgKHdoZWVsKT1cImhhbmRsZU1vdXNlV2hlZWwoJGV2ZW50KVwiXG4gICAgPjwvdGltZXBpY2tlcj5cbiAgPC9kaXY+XG5cbiAgPGRpdlxuICAgIGNsYXNzPVwiZC1jb250ZW50c1wiXG4gICAgKm5nU3dpdGNoQ2FzZT1cIidEYXRlJ1wiXG4gICAgW2Nsb3NlRGF0ZXBpY2tlcl09XCJkYXRlcGlja2VyXCJcbiAgPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwIGRhdGVwaWNrZXIge3sgc2l6ZSA/ICdmb3JtLWdyb3VwLScgKyBzaXplIDogJycgfX1cIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlciB8fCBkZWZhdWx0UGxhY2Vob2xkZXIgfCB0cmFuc2xhdGVcIlxuICAgICAgICBic0RhdGVwaWNrZXJcbiAgICAgICAgW291dHNpZGVDbGlja109XCJmYWxzZVwiXG4gICAgICAgIFtic0NvbmZpZ109XCJ7XG4gICAgICAgICAgY3VzdG9tVG9kYXlDbGFzczogJ3RvZGF5JyxcbiAgICAgICAgICBkYXRlSW5wdXRGb3JtYXQ6IGRhdGVJbnB1dEZvcm1hdCxcbiAgICAgICAgICBhZGFwdGl2ZVBvc2l0aW9uOiBhZGFwdGl2ZVBvc2l0aW9uXG4gICAgICAgIH1cIlxuICAgICAgICBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoJ2RhdGUnKVwiXG4gICAgICAgIChibHVyKT1cIm9uVG91Y2hlZCgpXCJcbiAgICAgICAgW21pbkRhdGVdPVwibWluRGF0ZVwiXG4gICAgICAgIFttYXhEYXRlXT1cIm1heERhdGVcIlxuICAgICAgLz5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPGRpdlxuICAgIGNsYXNzPVwiZC1jb250ZW50c1wiXG4gICAgKm5nU3dpdGNoQ2FzZT1cIidEYXRlUmFuZ2UnXCJcbiAgPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwIGRhdGVwaWNrZXIge3sgc2l6ZSA/ICdmb3JtLWdyb3VwLScgKyBzaXplIDogJycgfX1cIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ1NlbGVjdCBhIGRhdGUgcmFuZ2UnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KCdkYXRlJylcIlxuICAgICAgICBbYnNDb25maWddPVwie1xuICAgICAgICAgIGN1c3RvbVRvZGF5Q2xhc3M6ICd0b2RheScsXG4gICAgICAgICAgYWRhcHRpdmVQb3NpdGlvbjogdHJ1ZSxcbiAgICAgICAgICByYW5nZUlucHV0Rm9ybWF0OiBkYXRlSW5wdXRGb3JtYXRcbiAgICAgICAgfVwiXG4gICAgICAgIGJzRGF0ZXJhbmdlcGlja2VyXG4gICAgICAvPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuICA8ZGl2XG4gICAgY2xhc3M9XCJkLWNvbnRlbnRzXCJcbiAgICAqbmdTd2l0Y2hDYXNlPVwiJ1RpbWUnXCJcbiAgPlxuICAgIDx0aW1lcGlja2VyXG4gICAgICBjbGFzcz1cImZvcm0tZ3JvdXAge3sgc2l6ZSA/ICdmb3JtLWdyb3VwLScgKyBzaXplIDogJycgfX1cIlxuICAgICAgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KCd0aW1lJylcIlxuICAgICAgW3Nob3dTZWNvbmRzXT1cImNvbmZpZy5zaG93U2Vjb25kc1wiXG4gICAgICBbc2hvd1NwaW5uZXJzXT1cImNvbmZpZy5zaG93U3Bpbm5lcnNcIlxuICAgICAgW3Nob3dNZXJpZGlhbl09XCJjb25maWcuc2hvd01lcmlkaWFuXCJcbiAgICAgIFttaW51dGVzUGxhY2Vob2xkZXJdPVwiJ01NYE1JTlVURVNgJyB8IHRyYW5zbGF0ZVwiXG4gICAgICBbaG91cnNQbGFjZWhvbGRlcl09XCInSEhgSE9VUlNgJyB8IHRyYW5zbGF0ZVwiXG4gICAgICBbc2Vjb25kc1BsYWNlaG9sZGVyXT1cIidTU2BTRUNPTkRTYCcgfCB0cmFuc2xhdGVcIlxuICAgICAgKHdoZWVsKT1cImhhbmRsZU1vdXNlV2hlZWwoJGV2ZW50KVwiXG4gICAgPjwvdGltZXBpY2tlcj5cbiAgPC9kaXY+XG5cbiAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ1NpbmdsZURhdGVSZXF1aXJlZCdcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCB7eyBzaXplID8gJ2Zvcm0tZ3JvdXAtJyArIHNpemUgOiAnJyB9fVwiPlxuICAgICAgPGM4eS1kYXRlLXBpY2tlciAob25EYXRlU2VsZWN0ZWQpPVwib25EYXRlU2VsZWN0ZWQuZW1pdCgkZXZlbnQpXCI+PC9jOHktZGF0ZS1waWNrZXI+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=