UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

302 lines 48.3 kB
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, forwardRef, inject, Input, Output, ViewEncapsulation, } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import * as i0 from "@angular/core"; import * as i1 from "../../directives/accessibility/focus-indicator/default-focus-indicator.directive"; import * as i2 from "../spin-button/spin-button.component"; import * as i3 from "@angular/common"; export const TIME_PICKER_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TimePickerComponent), multi: true, }; export class TimePickerComponent { constructor() { this._changeDetector = inject(ChangeDetectorRef); /** Whether the arrow keys can be used to increment or decrement the selected time component. */ this.arrowkeys = true; /** Whether the mouse scroll wheel can be used to increment or decrement the selected time component. */ this.mousewheel = true; /** Whether the control is disabled. */ this.disabled = false; /** Whether the control is readonly. */ this.readOnly = false; /** Whether to show the meridian (AM/PM) selector. If this is false, the 24-hour clock will be used. */ this.showMeridian = false; /** Whether to show the hour selector. */ this.showHours = true; /** Whether to show the minute selector. */ this.showMinutes = true; /** Whether to show the second selector. */ this.showSeconds = false; /** Whether to show increment and decrement buttons in the time picker. */ this.showSpinners = true; /** The number of hours to increment or decrement by when using the spinner buttons, arrow keys, or mouse scroll wheel. */ this.hourStep = 1; /** The number of minutes to increment or decrement by when using the spinner buttons, arrow keys, or mouse scroll wheel. */ this.minuteStep = 1; /** The number of seconds to increment or decrement by when using the spinner buttons, arrow keys, or mouse scroll wheel. */ this.secondStep = 1; /** An array containing the labels to show in the meridian selector. */ this.meridians = ['AM', 'PM']; /** Emitted when the `value` changes. */ this.valueChange = new EventEmitter(); /** Emitted when the validity of the control changes. */ this.isValid = new EventEmitter(); // eslint-disable-next-line @typescript-eslint/no-empty-function this.onTouchedCallback = () => { }; // eslint-disable-next-line @typescript-eslint/no-empty-function this.onChangeCallback = () => { }; this._value = new Date(); this._isValid = true; } /** The value to display. */ set value(value) { this._value = new Date(value); this.valueChange.emit(this._value); this.onChangeCallback(this._value); this.onTouchedCallback(); } get value() { return new Date(this._value); } get _meridian() { return this._value.getHours() < 12 ? this.meridians[0] : this.meridians[1]; } get _valid() { return this.checkValidity(this._value); } get isValidDate() { return this.value instanceof Date && !isNaN(this.value.getTime()); } writeValue(value) { this.value = value; this._changeDetector.markForCheck(); } registerOnChange(fn) { this.onChangeCallback = fn; } registerOnTouched(fn) { this.onTouchedCallback = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this._changeDetector.markForCheck(); } getMeridianTime(hour) { return hour > 12 ? hour - 12 : hour; } setHour(hour) { const date = this.value; date.setHours(hour ? hour : 0); this.value = date; } setMinute(minute) { const date = this.value; date.setMinutes(minute ? minute : 0); this.value = date; } setSeconds(seconds) { const date = this.value; date.setSeconds(seconds ? seconds : 0); this.value = date; } incrementHour(arrowkey = false) { if (this.disabled || (arrowkey && !this.arrowkeys)) { return; } this.setHour(this.value.getHours() + this.hourStep); } decrementHour(arrowkey = false) { if (this.disabled || (arrowkey && !this.arrowkeys)) { return; } this.setHour(this.value.getHours() - this.hourStep); } incrementMinute(arrowkey = false) { if (this.disabled || (arrowkey && !this.arrowkeys)) { return; } this.setMinute(this.value.getMinutes() + this.minuteStep); } decrementMinute(arrowkey = false) { if (this.disabled || (arrowkey && !this.arrowkeys)) { return; } this.setMinute(this.value.getMinutes() - this.minuteStep); } incrementSecond(arrowkey = false) { if (this.disabled || (arrowkey && !this.arrowkeys)) { return; } this.setSeconds(this.value.getSeconds() + this.secondStep); } decrementSecond(arrowkey = false) { if (this.disabled || (arrowkey && !this.arrowkeys)) { return; } this.setSeconds(this.value.getSeconds() - this.secondStep); } selectMeridian(meridian) { // get the current time const hour = this.value.getHours(); // if we have selected AM if (meridian === this.meridians[0]) { if (hour >= 12) { this.setHour(hour - 12); } } // if we have selected PM if (meridian === this.meridians[1]) { if (hour < 12) { this.setHour(hour + 12); } } } checkValidity(date) { let valid = true; // Fix min and max date components in order to compare time only const min = this.normalizeDate(this.min, date); const max = this.normalizeDate(this.max, date); if ((min && date.getTime() < min.getTime()) || (max && date.getTime() > max.getTime())) { valid = false; } // if the valid state has changed then emit the isValid output if (valid !== this._isValid) { this._isValid = valid; this.isValid.emit(valid); } return valid; } hourChange(value) { // if the value is empty then emit nothing if (value && typeof value === 'string' && value.trim() === '') { return; } // convert the string to a number let hour = typeof value === 'number' ? value : parseInt(value); // ensure the hours is valid if (!isNaN(hour)) { if (hour < 0) { hour = 0; } if (hour > (this.showMeridian ? 12 : 23)) { hour = this.showMeridian ? 12 : 23; } } const currentHour = this.value.getHours(); // if the value hasn't changed, do nothing if (hour === currentHour) { return; } hour = isNaN(hour) ? currentHour : hour; if (this.showMeridian) { // if the number is invalid then restore it to the previous value if (this._meridian === this.meridians[0]) { if (hour >= 12) { hour -= 12; } } // if we have selected PM if (this._meridian === this.meridians[1]) { if (hour < 12) { hour += 12; } } } this.setHour(hour); } minuteChange(value) { // convert the string to a number let minute = typeof value === 'number' ? value : parseInt(value); const currentMinute = this.value.getMinutes(); // if the value hasn't changed, do nothing if (minute === currentMinute) { return; } // ensure the hours is valid if (!isNaN(minute)) { if (minute < 0) { minute = 59; } if (minute > 59) { minute = 0; } } // if the number is invalid then restore it to the previous value this.setMinute(isNaN(minute) ? currentMinute : minute); } secondChange(value) { // convert the string to a number let second = typeof value === 'number' ? value : parseInt(value); const currentSecond = this.value.getSeconds(); // if the value hasn't changed, do nothing if (second === currentSecond) { return; } // ensure the hours is valid if (!isNaN(second)) { if (second < 0) { second = 0; } if (second > 59) { second = 59; } } // if the number is invalid then restore it to the previous value this.setSeconds(isNaN(second) ? currentSecond : second); } /** Normalise a date's year/month/date components. */ normalizeDate(date, reference) { if (!date) { return null; } const normalized = new Date(date); normalized.setFullYear(reference.getFullYear()); normalized.setMonth(reference.getMonth()); normalized.setDate(reference.getDate()); return normalized; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: TimePickerComponent, selector: "ux-time-picker", inputs: { arrowkeys: "arrowkeys", mousewheel: "mousewheel", disabled: "disabled", readOnly: "readOnly", showMeridian: "showMeridian", showHours: "showHours", showMinutes: "showMinutes", showSeconds: "showSeconds", showSpinners: "showSpinners", hourStep: "hourStep", minuteStep: "minuteStep", secondStep: "secondStep", min: "min", max: "max", meridians: "meridians", value: "value" }, outputs: { valueChange: "valueChange", isValid: "isValid" }, providers: [TIME_PICKER_VALUE_ACCESSOR], ngImport: i0, template: "<div class=\"time-picker\">\n @if (showHours) {\n <div class=\"time-picker-column time-hours-picker\" [class.has-error]=\"!_valid\">\n <ux-spin-button\n type=\"number\"\n class=\"time-spinner\"\n placeholder=\"HH\"\n [maxLength]=\"2\"\n [min]=\"0\"\n [max]=\"showMeridian ? 12 : 23\"\n [value]=\"isValidDate ? (value | date: (showMeridian ? 'h' : 'HH')) : ''\"\n (valueChange)=\"hourChange($event)\"\n [spinners]=\"showSpinners\"\n [disabled]=\"disabled\"\n [readOnly]=\"readOnly\"\n inputAriaLabel=\"hour\"\n incrementAriaLabel=\"Increment the hour\"\n decrementAriaLabel=\"Decrement the hour\"\n (increment)=\"incrementHour()\"\n (decrement)=\"decrementHour()\"\n >\n </ux-spin-button>\n </div>\n }\n\n @if (showMinutes) {\n <div class=\"time-picker-separator\">:</div>\n }\n\n @if (showMinutes) {\n <div class=\"time-picker-column time-minutes-picker\" [class.has-error]=\"!_valid\">\n <ux-spin-button\n type=\"number\"\n class=\"time-spinner\"\n placeholder=\"MM\"\n [maxLength]=\"2\"\n [min]=\"0\"\n [max]=\"59\"\n [value]=\"isValidDate ? (value | date: 'mm') : ''\"\n (valueChange)=\"minuteChange($event)\"\n [spinners]=\"showSpinners\"\n [disabled]=\"disabled\"\n [readOnly]=\"readOnly\"\n inputAriaLabel=\"minute\"\n incrementAriaLabel=\"Increment the minute\"\n decrementAriaLabel=\"Decrement the minute\"\n (increment)=\"incrementMinute()\"\n (decrement)=\"decrementMinute()\"\n >\n </ux-spin-button>\n </div>\n }\n\n @if (showSeconds) {\n <div class=\"time-picker-separator\">:</div>\n }\n\n @if (showSeconds) {\n <div class=\"time-picker-column time-seconds-picker\" [class.has-error]=\"!_valid\">\n <ux-spin-button\n type=\"number\"\n class=\"time-spinner\"\n placeholder=\"SS\"\n [maxLength]=\"2\"\n [min]=\"0\"\n [max]=\"59\"\n [value]=\"isValidDate ? (value | date: 'ss') : ''\"\n (valueChange)=\"secondChange($event)\"\n [spinners]=\"showSpinners\"\n [disabled]=\"disabled\"\n [readOnly]=\"readOnly\"\n inputAriaLabel=\"seconds\"\n incrementAriaLabel=\"Increment the second\"\n decrementAriaLabel=\"Decrement the second\"\n (increment)=\"incrementSecond()\"\n (decrement)=\"decrementSecond()\"\n >\n </ux-spin-button>\n </div>\n }\n</div>\n\n@if (showMeridian) {\n <div class=\"time-picker-meridian\">\n <div class=\"btn-group\" role=\"radiogroup\">\n @for (meridian of meridians; track meridian) {\n <button\n type=\"button\"\n class=\"btn button-toggle-accent\"\n role=\"radio\"\n tabindex=\"0\"\n [disabled]=\"disabled\"\n (click)=\"selectMeridian(meridian)\"\n [class.active]=\"meridian === _meridian\"\n [attr.aria-label]=\"meridian\"\n [attr.aria-checked]=\"meridian === _meridian\"\n [attr.aria-disabled]=\"disabled\"\n >\n {{ meridian }}\n </button>\n }\n </div>\n </div>\n}\n", dependencies: [{ kind: "directive", type: i1.DefaultFocusIndicatorDirective, selector: ".btn:not([uxFocusIndicator]):not([uxMenuNavigationToggle]):not([uxMenuTriggerFor]), a[href]:not([uxFocusIndicator]):not([uxMenuNavigationToggle]):not([uxMenuTriggerFor])" }, { kind: "component", type: i2.SpinButtonComponent, selector: "ux-spin-button", inputs: ["value", "type", "min", "max", "placeholder", "disabled", "spinners", "readOnly", "scrolling", "arrowkeys", "maxLength", "incrementAriaLabel", "inputAriaLabel", "decrementAriaLabel"], outputs: ["valueChange", "increment", "decrement"] }, { kind: "pipe", type: i3.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TimePickerComponent, decorators: [{ type: Component, args: [{ selector: 'ux-time-picker', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [TIME_PICKER_VALUE_ACCESSOR], template: "<div class=\"time-picker\">\n @if (showHours) {\n <div class=\"time-picker-column time-hours-picker\" [class.has-error]=\"!_valid\">\n <ux-spin-button\n type=\"number\"\n class=\"time-spinner\"\n placeholder=\"HH\"\n [maxLength]=\"2\"\n [min]=\"0\"\n [max]=\"showMeridian ? 12 : 23\"\n [value]=\"isValidDate ? (value | date: (showMeridian ? 'h' : 'HH')) : ''\"\n (valueChange)=\"hourChange($event)\"\n [spinners]=\"showSpinners\"\n [disabled]=\"disabled\"\n [readOnly]=\"readOnly\"\n inputAriaLabel=\"hour\"\n incrementAriaLabel=\"Increment the hour\"\n decrementAriaLabel=\"Decrement the hour\"\n (increment)=\"incrementHour()\"\n (decrement)=\"decrementHour()\"\n >\n </ux-spin-button>\n </div>\n }\n\n @if (showMinutes) {\n <div class=\"time-picker-separator\">:</div>\n }\n\n @if (showMinutes) {\n <div class=\"time-picker-column time-minutes-picker\" [class.has-error]=\"!_valid\">\n <ux-spin-button\n type=\"number\"\n class=\"time-spinner\"\n placeholder=\"MM\"\n [maxLength]=\"2\"\n [min]=\"0\"\n [max]=\"59\"\n [value]=\"isValidDate ? (value | date: 'mm') : ''\"\n (valueChange)=\"minuteChange($event)\"\n [spinners]=\"showSpinners\"\n [disabled]=\"disabled\"\n [readOnly]=\"readOnly\"\n inputAriaLabel=\"minute\"\n incrementAriaLabel=\"Increment the minute\"\n decrementAriaLabel=\"Decrement the minute\"\n (increment)=\"incrementMinute()\"\n (decrement)=\"decrementMinute()\"\n >\n </ux-spin-button>\n </div>\n }\n\n @if (showSeconds) {\n <div class=\"time-picker-separator\">:</div>\n }\n\n @if (showSeconds) {\n <div class=\"time-picker-column time-seconds-picker\" [class.has-error]=\"!_valid\">\n <ux-spin-button\n type=\"number\"\n class=\"time-spinner\"\n placeholder=\"SS\"\n [maxLength]=\"2\"\n [min]=\"0\"\n [max]=\"59\"\n [value]=\"isValidDate ? (value | date: 'ss') : ''\"\n (valueChange)=\"secondChange($event)\"\n [spinners]=\"showSpinners\"\n [disabled]=\"disabled\"\n [readOnly]=\"readOnly\"\n inputAriaLabel=\"seconds\"\n incrementAriaLabel=\"Increment the second\"\n decrementAriaLabel=\"Decrement the second\"\n (increment)=\"incrementSecond()\"\n (decrement)=\"decrementSecond()\"\n >\n </ux-spin-button>\n </div>\n }\n</div>\n\n@if (showMeridian) {\n <div class=\"time-picker-meridian\">\n <div class=\"btn-group\" role=\"radiogroup\">\n @for (meridian of meridians; track meridian) {\n <button\n type=\"button\"\n class=\"btn button-toggle-accent\"\n role=\"radio\"\n tabindex=\"0\"\n [disabled]=\"disabled\"\n (click)=\"selectMeridian(meridian)\"\n [class.active]=\"meridian === _meridian\"\n [attr.aria-label]=\"meridian\"\n [attr.aria-checked]=\"meridian === _meridian\"\n [attr.aria-disabled]=\"disabled\"\n >\n {{ meridian }}\n </button>\n }\n </div>\n </div>\n}\n" }] }], propDecorators: { arrowkeys: [{ type: Input }], mousewheel: [{ type: Input }], disabled: [{ type: Input }], readOnly: [{ type: Input }], showMeridian: [{ type: Input }], showHours: [{ type: Input }], showMinutes: [{ type: Input }], showSeconds: [{ type: Input }], showSpinners: [{ type: Input }], hourStep: [{ type: Input }], minuteStep: [{ type: Input }], secondStep: [{ type: Input }], min: [{ type: Input }], max: [{ type: Input }], meridians: [{ type: Input }], value: [{ type: Input }], valueChange: [{ type: Output }], isValid: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdGltZS1waWNrZXIvdGltZS1waWNrZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdGltZS1waWNrZXIvdGltZS1waWNrZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1YsTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBQ04saUJBQWlCLEdBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7QUFFekUsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUc7SUFDeEMsT0FBTyxFQUFFLGlCQUFpQjtJQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixDQUFDO0lBQ2xELEtBQUssRUFBRSxJQUFJO0NBQ1osQ0FBQztBQVNGLE1BQU0sT0FBTyxtQkFBbUI7SUFQaEM7UUFRbUIsb0JBQWUsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUU3RCxnR0FBZ0c7UUFDdkYsY0FBUyxHQUFZLElBQUksQ0FBQztRQUVuQyx3R0FBd0c7UUFDL0YsZUFBVSxHQUFZLElBQUksQ0FBQztRQUVwQyx1Q0FBdUM7UUFDOUIsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUVuQyx1Q0FBdUM7UUFDOUIsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUVuQyx1R0FBdUc7UUFDOUYsaUJBQVksR0FBWSxLQUFLLENBQUM7UUFFdkMseUNBQXlDO1FBQ2hDLGNBQVMsR0FBWSxJQUFJLENBQUM7UUFFbkMsMkNBQTJDO1FBQ2xDLGdCQUFXLEdBQVksSUFBSSxD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RGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBmb3J3YXJkUmVmLFxuICBpbmplY3QsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuZXhwb3J0IGNvbnN0IFRJTUVfUElDS0VSX1ZBTFVFX0FDQ0VTU09SID0ge1xuICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVGltZVBpY2tlckNvbXBvbmVudCksXG4gIG11bHRpOiB0cnVlLFxufTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndXgtdGltZS1waWNrZXInLFxuICB0ZW1wbGF0ZVVybDogJy4vdGltZS1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgcHJvdmlkZXJzOiBbVElNRV9QSUNLRVJfVkFMVUVfQUNDRVNTT1JdLFxufSlcbmV4cG9ydCBjbGFzcyBUaW1lUGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuICBwcml2YXRlIHJlYWRvbmx5IF9jaGFuZ2VEZXRlY3RvciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIGFycm93IGtleXMgY2FuIGJlIHVzZWQgdG8gaW5jcmVtZW50IG9yIGRlY3JlbWVudCB0aGUgc2VsZWN0ZWQgdGltZSBjb21wb25lbnQuICovXG4gIEBJbnB1dCgpIGFycm93a2V5czogYm9vbGVhbiA9IHRydWU7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIG1vdXNlIHNjcm9sbCB3aGVlbCBjYW4gYmUgdXNlZCB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IHRoZSBzZWxlY3RlZCB0aW1lIGNvbXBvbmVudC4gKi9cbiAgQElucHV0KCkgbW91c2V3aGVlbDogYm9vbGVhbiA9IHRydWU7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIGNvbnRyb2wgaXMgZGlzYWJsZWQuICovXG4gIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIGNvbnRyb2wgaXMgcmVhZG9ubHkuICovXG4gIEBJbnB1dCgpIHJlYWRPbmx5OiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIFdoZXRoZXIgdG8gc2hvdyB0aGUgbWVyaWRpYW4gKEFNL1BNKSBzZWxlY3Rvci4gSWYgdGhpcyBpcyBmYWxzZSwgdGhlIDI0LWhvdXIgY2xvY2sgd2lsbCBiZSB1c2VkLiAqL1xuICBASW5wdXQoKSBzaG93TWVyaWRpYW46IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogV2hldGhlciB0byBzaG93IHRoZSBob3VyIHNlbGVjdG9yLiAqL1xuICBASW5wdXQoKSBzaG93SG91cnM6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgdGhlIG1pbnV0ZSBzZWxlY3Rvci4gKi9cbiAgQElucHV0KCkgc2hvd01pbnV0ZXM6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgdGhlIHNlY29uZCBzZWxlY3Rvci4gKi9cbiAgQElucHV0KCkgc2hvd1NlY29uZHM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogV2hldGhlciB0byBzaG93IGluY3JlbWVudCBhbmQgZGVjcmVtZW50IGJ1dHRvbnMgaW4gdGhlIHRpbWUgcGlja2VyLiAqL1xuICBASW5wdXQoKSBzaG93U3Bpbm5lcnM6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKiBUaGUgbnVtYmVyIG9mIGhvdXJzIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgYnkgd2hlbiB1c2luZyB0aGUgc3Bpbm5lciBidXR0b25zLCBhcnJvdyBrZXlzLCBvciBtb3VzZSBzY3JvbGwgd2hlZWwuICovXG4gIEBJbnB1dCgpIGhvdXJTdGVwOiBudW1iZXIgPSAxO1xuXG4gIC8qKiBUaGUgbnVtYmVyIG9mIG1pbnV0ZXMgdG8gaW5jcmVtZW50IG9yIGRlY3JlbWVudCBieSB3aGVuIHVzaW5nIHRoZSBzcGlubmVyIGJ1dHRvbnMsIGFycm93IGtleXMsIG9yIG1vdXNlIHNjcm9sbCB3aGVlbC4gKi9cbiAgQElucHV0KCkgbWludXRlU3RlcDogbnVtYmVyID0gMTtcblxuICAvKiogVGhlIG51bWJlciBvZiBzZWNvbmRzIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgYnkgd2hlbiB1c2luZyB0aGUgc3Bpbm5lciBidXR0b25zLCBhcnJvdyBrZXlzLCBvciBtb3VzZSBzY3JvbGwgd2hlZWwuICovXG4gIEBJbnB1dCgpIHNlY29uZFN0ZXA6IG51bWJlciA9IDE7XG5cbiAgLyoqIFRoZSBtaW5pbXVtIHZhbHVlIHRoYXQgdGhlIGNvbXBvbmVudCB3aWxsIGFsbG93LiAqL1xuICBASW5wdXQoKSBtaW46IERhdGU7XG5cbiAgLyoqIFRoZSBtYXhpbXVtIHZhbHVlIHRoYXQgdGhlIGNvbXBvbmVudCB3aWxsIGFsbG93LiAqL1xuICBASW5wdXQoKSBtYXg6IERhdGU7XG5cbiAgLyoqIEFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGxhYmVscyB0byBzaG93IGluIHRoZSBtZXJpZGlhbiBzZWxlY3Rvci4gKi9cbiAgQElucHV0KCkgbWVyaWRpYW5zOiBzdHJpbmdbXSA9IFsnQU0nLCAnUE0nXTtcblxuICAvKiogVGhlIHZhbHVlIHRvIGRpc3BsYXkuICovXG4gIEBJbnB1dCgpIHNldCB2YWx1ZSh2YWx1ZTogRGF0ZSkge1xuICAgIHRoaXMuX3ZhbHVlID0gbmV3IERhdGUodmFsdWUpO1xuICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh0aGlzLl92YWx1ZSk7XG5cbiAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sodGhpcy5fdmFsdWUpO1xuICAgIHRoaXMub25Ub3VjaGVkQ2FsbGJhY2soKTtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpOiBEYXRlIHtcbiAgICByZXR1cm4gbmV3IERhdGUodGhpcy5fdmFsdWUpO1xuICB9XG5cbiAgZ2V0IF9tZXJpZGlhbigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl92YWx1ZS5nZXRIb3VycygpIDwgMTIgPyB0aGlzLm1lcmlkaWFuc1swXSA6IHRoaXMubWVyaWRpYW5zWzFdO1xuICB9XG5cbiAgZ2V0IF92YWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jaGVja1ZhbGlkaXR5KHRoaXMuX3ZhbHVlKTtcbiAgfVxuXG4gIC8qKiBFbWl0dGVkIHdoZW4gdGhlIGB2YWx1ZWAgY2hhbmdlcy4gKi9cbiAgQE91dHB1dCgpIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xuXG4gIC8qKiBFbWl0dGVkIHdoZW4gdGhlIHZhbGlkaXR5IG9mIHRoZSBjb250cm9sIGNoYW5nZXMuICovXG4gIEBPdXRwdXQoKSBpc1ZhbGlkID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgb25Ub3VjaGVkQ2FsbGJhY2s6ICgpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICBvbkNoYW5nZUNhbGxiYWNrOiAoXzogRGF0ZSkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gIHByaXZhdGUgX3ZhbHVlID0gbmV3IERhdGUoKTtcbiAgcHJpdmF0ZSBfaXNWYWxpZDogYm9vbGVhbiA9IHRydWU7XG5cbiAgcHJvdGVjdGVkIGdldCBpc1ZhbGlkRGF0ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZSBpbnN0YW5jZW9mIERhdGUgJiYgIWlzTmFOKHRoaXMudmFsdWUuZ2V0VGltZSgpKTtcbiAgfVxuXG4gIHdyaXRlVmFsdWUodmFsdWU6IERhdGUpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAoXzogRGF0ZSkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25DaGFuZ2VDYWxsYmFjayA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZENhbGxiYWNrID0gZm47XG4gIH1cblxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICB0aGlzLl9jaGFuZ2VEZXRlY3Rvci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIGdldE1lcmlkaWFuVGltZShob3VyOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiBob3VyID4gMTIgPyBob3VyIC0gMTIgOiBob3VyO1xuICB9XG5cbiAgc2V0SG91cihob3VyOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBkYXRlID0gdGhpcy52YWx1ZTtcbiAgICBkYXRlLnNldEhvdXJzKGhvdXIgPyBob3VyIDogMCk7XG5cbiAgICB0aGlzLnZhbHVlID0gZGF0ZTtcbiAgfVxuXG4gIHNldE1pbnV0ZShtaW51dGU6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGRhdGUgPSB0aGlzLnZhbHVlO1xuICAgIGRhdGUuc2V0TWludXRlcyhtaW51dGUgPyBtaW51dGUgOiAwKTtcblxuICAgIHRoaXMudmFsdWUgPSBkYXRlO1xuICB9XG5cbiAgc2V0U2Vjb25kcyhzZWNvbmRzOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBkYXRlID0gdGhpcy52YWx1ZTtcbiAgICBkYXRlLnNldFNlY29uZHMoc2Vjb25kcyA/IHNlY29uZHMgOiAwKTtcblxuICAgIHRoaXMudmFsdWUgPSBkYXRlO1xuICB9XG5cbiAgaW5jcmVtZW50SG91cihhcnJvd2tleTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgKGFycm93a2V5ICYmICF0aGlzLmFycm93a2V5cykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNldEhvdXIodGhpcy52YWx1ZS5nZXRIb3VycygpICsgdGhpcy5ob3VyU3RlcCk7XG4gIH1cblxuICBkZWNyZW1lbnRIb3VyKGFycm93a2V5OiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCAoYXJyb3drZXkgJiYgIXRoaXMuYXJyb3drZXlzKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2V0SG91cih0aGlzLnZhbHVlLmdldEhvdXJzKCkgLSB0aGlzLmhvdXJTdGVwKTtcbiAgfVxuXG4gIGluY3JlbWVudE1pbnV0ZShhcnJvd2tleTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgKGFycm93a2V5ICYmICF0aGlzLmFycm93a2V5cykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNldE1pbnV0ZSh0aGlzLnZhbHVlLmdldE1pbnV0ZXMoKSArIHRoaXMubWludXRlU3RlcCk7XG4gIH1cblxuICBkZWNyZW1lbnRNaW51dGUoYXJyb3drZXk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IChhcnJvd2tleSAmJiAhdGhpcy5hcnJvd2tleXMpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zZXRNaW51dGUodGhpcy52YWx1ZS5nZXRNaW51dGVzKCkgLSB0aGlzLm1pbnV0ZVN0ZXApO1xuICB9XG5cbiAgaW5jcmVtZW50U2Vjb25kKGFycm93a2V5OiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCAoYXJyb3drZXkgJiYgIXRoaXMuYXJyb3drZXlzKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2V0U2Vjb25kcyh0aGlzLnZhbHVlLmdldFNlY29uZHMoKSArIHRoaXMuc2Vjb25kU3RlcCk7XG4gIH1cblxuICBkZWNyZW1lbnRTZWNvbmQoYXJyb3drZXk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IChhcnJvd2tleSAmJiAhdGhpcy5hcnJvd2tleXMpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zZXRTZWNvbmRzKHRoaXMudmFsdWUuZ2V0U2Vjb25kcygpIC0gdGhpcy5zZWNvbmRTdGVwKTtcbiAgfVxuXG4gIHNlbGVjdE1lcmlkaWFuKG1lcmlkaWFuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBnZXQgdGhlIGN1cnJlbnQgdGltZVxuICAgIGNvbnN0IGhvdXIgPSB0aGlzLnZhbHVlLmdldEhvdXJzKCk7XG5cbiAgICAvLyBpZiB3ZSBoYXZlIHNlbGVjdGVkIEFNXG4gICAgaWYgKG1lcmlkaWFuID09PSB0aGlzLm1lcmlkaWFuc1swXSkge1xuICAgICAgaWYgKGhvdXIgPj0gMTIpIHtcbiAgICAgICAgdGhpcy5zZXRIb3VyKGhvdXIgLSAxMik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gaWYgd2UgaGF2ZSBzZWxlY3RlZCBQTVxuICAgIGlmIChtZXJpZGlhbiA9PT0gdGhpcy5tZXJpZGlhbnNbMV0pIHtcbiAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgdGhpcy5zZXRIb3VyKGhvdXIgKyAxMik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY2hlY2tWYWxpZGl0eShkYXRlOiBEYXRlKTogYm9vbGVhbiB7XG4gICAgbGV0IHZhbGlkID0gdHJ1ZTtcblxuICAgIC8vIEZpeCBtaW4gYW5kIG1heCBkYXRlIGNvbXBvbmVudHMgaW4gb3JkZXIgdG8gY29tcGFyZSB0aW1lIG9ubHlcbiAgICBjb25zdCBtaW4gPSB0aGlzLm5vcm1hbGl6ZURhdGUodGhpcy5taW4sIGRhdGUpO1xuICAgIGNvbnN0IG1heCA9IHRoaXMubm9ybWFsaXplRGF0ZSh0aGlzLm1heCwgZGF0ZSk7XG5cbiAgICBpZiAoKG1pbiAmJiBkYXRlLmdldFRpbWUoKSA8IG1pbi5nZXRUaW1lKCkpIHx8IChtYXggJiYgZGF0ZS5nZXRUaW1lKCkgPiBtYXguZ2V0VGltZSgpKSkge1xuICAgICAgdmFsaWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgdmFsaWQgc3RhdGUgaGFzIGNoYW5nZWQgdGhlbiBlbWl0IHRoZSBpc1ZhbGlkIG91dHB1dFxuICAgIGlmICh2YWxpZCAhPT0gdGhpcy5faXNWYWxpZCkge1xuICAgICAgdGhpcy5faXNWYWxpZCA9IHZhbGlkO1xuICAgICAgdGhpcy5pc1ZhbGlkLmVtaXQodmFsaWQpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWxpZDtcbiAgfVxuXG4gIGhvdXJDaGFuZ2UodmFsdWU6IHN0cmluZyB8IG51bWJlcik6IHZvaWQge1xuICAgIC8vIGlmIHRoZSB2YWx1ZSBpcyBlbXB0eSB0aGVuIGVtaXQgbm90aGluZ1xuICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjb252ZXJ0IHRoZSBzdHJpbmcgdG8gYSBudW1iZXJcbiAgICBsZXQgaG91ciA9IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyB2YWx1ZSA6IHBhcnNlSW50KHZhbHVlKTtcblxuICAgIC8vIGVuc3VyZSB0aGUgaG91cnMgaXMgdmFsaWRcbiAgICBpZiAoIWlzTmFOKGhvdXIpKSB7XG4gICAgICBpZiAoaG91ciA8IDApIHtcbiAgICAgICAgaG91ciA9IDA7XG4gICAgICB9XG5cbiAgICAgIGlmIChob3VyID4gKHRoaXMuc2hvd01lcmlkaWFuID8gMTIgOiAyMykpIHtcbiAgICAgICAgaG91ciA9IHRoaXMuc2hvd01lcmlkaWFuID8gMTIgOiAyMztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50SG91ciA9IHRoaXMudmFsdWUuZ2V0SG91cnMoKTtcblxuICAgIC8vIGlmIHRoZSB2YWx1ZSBoYXNuJ3QgY2hhbmdlZCwgZG8gbm90aGluZ1xuICAgIGlmIChob3VyID09PSBjdXJyZW50SG91cikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGhvdXIgPSBpc05hTihob3VyKSA/IGN1cnJlbnRIb3VyIDogaG91cjtcblxuICAgIGlmICh0aGlzLnNob3dNZXJpZGlhbikge1xuICAgICAgLy8gaWYgdGhlIG51bWJlciBpcyBpbnZhbGlkIHRoZW4gcmVzdG9yZSBpdCB0byB0aGUgcHJldmlvdXMgdmFsdWVcbiAgICAgIGlmICh0aGlzLl9tZXJpZGlhbiA9PT0gdGhpcy5tZXJpZGlhbnNbMF0pIHtcbiAgICAgICAgaWYgKGhvdXIgPj0gMTIpIHtcbiAgICAgICAgICBob3VyIC09IDEyO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIGlmIHdlIGhhdmUgc2VsZWN0ZWQgUE1cbiAgICAgIGlmICh0aGlzLl9tZXJpZGlhbiA9PT0gdGhpcy5tZXJpZGlhbnNbMV0pIHtcbiAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgIGhvdXIgKz0gMTI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnNldEhvdXIoaG91cik7XG4gIH1cblxuICBtaW51dGVDaGFuZ2UodmFsdWU6IHN0cmluZyB8IG51bWJlcik6IHZvaWQge1xuICAgIC8vIGNvbnZlcnQgdGhlIHN0cmluZyB0byBhIG51bWJlclxuICAgIGxldCBtaW51dGUgPSB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInID8gdmFsdWUgOiBwYXJzZUludCh2YWx1ZSk7XG4gICAgY29uc3QgY3VycmVudE1pbnV0ZSA9IHRoaXMudmFsdWUuZ2V0TWludXRlcygpO1xuXG4gICAgLy8gaWYgdGhlIHZhbHVlIGhhc24ndCBjaGFuZ2VkLCBkbyBub3RoaW5nXG4gICAgaWYgKG1pbnV0ZSA9PT0gY3VycmVudE1pbnV0ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGVuc3VyZSB0aGUgaG91cnMgaXMgdmFsaWRcbiAgICBpZiAoIWlzTmFOKG1pbnV0ZSkpIHtcbiAgICAgIGlmIChtaW51dGUgPCAwKSB7XG4gICAgICAgIG1pbnV0ZSA9IDU5O1xuICAgICAgfVxuXG4gICAgICBpZiAobWludXRlID4gNTkpIHtcbiAgICAgICAgbWludXRlID0gMDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgbnVtYmVyIGlzIGludmFsaWQgdGhlbiByZXN0b3JlIGl0IHRvIHRoZSBwcmV2aW91cyB2YWx1ZVxuICAgIHRoaXMuc2V0TWludXRlKGlzTmFOKG1pbnV0ZSkgPyBjdXJyZW50TWludXRlIDogbWludXRlKTtcbiAgfVxuXG4gIHNlY29uZENoYW5nZSh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyKTogdm9pZCB7XG4gICAgLy8gY29udmVydCB0aGUgc3RyaW5nIHRvIGEgbnVtYmVyXG4gICAgbGV0IHNlY29uZCA9IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyB2YWx1ZSA6IHBhcnNlSW50KHZhbHVlKTtcbiAgICBjb25zdCBjdXJyZW50U2Vjb25kID0gdGhpcy52YWx1ZS5nZXRTZWNvbmRzKCk7XG5cbiAgICAvLyBpZiB0aGUgdmFsdWUgaGFzbid0IGNoYW5nZWQsIGRvIG5vdGhpbmdcbiAgICBpZiAoc2Vjb25kID09PSBjdXJyZW50U2Vjb25kKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZW5zdXJlIHRoZSBob3VycyBpcyB2YWxpZFxuICAgIGlmICghaXNOYU4oc2Vjb25kKSkge1xuICAgICAgaWYgKHNlY29uZCA8IDApIHtcbiAgICAgICAgc2Vjb25kID0gMDtcbiAgICAgIH1cblxuICAgICAgaWYgKHNlY29uZCA+IDU5KSB7XG4gICAgICAgIHNlY29uZCA9IDU5O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIHRoZSBudW1iZXIgaXMgaW52YWxpZCB0aGVuIHJlc3RvcmUgaXQgdG8gdGhlIHByZXZpb3VzIHZhbHVlXG4gICAgdGhpcy5zZXRTZWNvbmRzKGlzTmFOKHNlY29uZCkgPyBjdXJyZW50U2Vjb25kIDogc2Vjb25kKTtcbiAgfVxuXG4gIC8qKiBOb3JtYWxpc2UgYSBkYXRlJ3MgeWVhci9tb250aC9kYXRlIGNvbXBvbmVudHMuICovXG4gIHByaXZhdGUgbm9ybWFsaXplRGF0ZShkYXRlOiBEYXRlLCByZWZlcmVuY2U6IERhdGUpOiBEYXRlIHtcbiAgICBpZiAoIWRhdGUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBuZXcgRGF0ZShkYXRlKTtcbiAgICBub3JtYWxpemVkLnNldEZ1bGxZZWFyKHJlZmVyZW5jZS5nZXRGdWxsWWVhcigpKTtcbiAgICBub3JtYWxpemVkLnNldE1vbnRoKHJlZmVyZW5jZS5nZXRNb250aCgpKTtcbiAgICBub3JtYWxpemVkLnNldERhdGUocmVmZXJlbmNlLmdldERhdGUoKSk7XG5cbiAgICByZXR1cm4gbm9ybWFsaXplZDtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cInRpbWUtcGlja2VyXCI+XG4gIEBpZiAoc2hvd0hvdXJzKSB7XG4gICAgPGRpdiBjbGFzcz1cInRpbWUtcGlja2VyLWNvbHVtbiB0aW1lLWhvdXJzLXBpY2tlclwiIFtjbGFzcy5oYXMtZXJyb3JdPVwiIV92YWxpZFwiPlxuICAgICAgPHV4LXNwaW4tYnV0dG9uXG4gICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICBjbGFzcz1cInRpbWUtc3Bpbm5lclwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwiSEhcIlxuICAgICAgICBbbWF4TGVuZ3RoXT1cIjJcIlxuICAgICAgICBbbWluXT1cIjBcIlxuICAgICAgICBbbWF4XT1cInNob3dNZXJpZGlhbiA/IDEyIDogMjNcIlxuICAgICAgICBbdmFsdWVdPVwiaXNWYWxpZERhdGUgPyAodmFsdWUgfCBkYXRlOiAoc2hvd01lcmlkaWFuID8gJ2gnIDogJ0hIJykpIDogJydcIlxuICAgICAgICAodmFsdWVDaGFuZ2UpPVwiaG91ckNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgW3NwaW5uZXJzXT1cInNob3dTcGlubmVyc1wiXG4gICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgIFtyZWFkT25seV09XCJyZWFkT25seVwiXG4gICAgICAgIGlucHV0QXJpYUxhYmVsPVwiaG91clwiXG4gICAgICAgIGluY3JlbWVudEFyaWFMYWJlbD1cIkluY3JlbWVudCB0aGUgaG91clwiXG4gICAgICAgIGRlY3JlbWVudEFyaWFMYWJlbD1cIkRlY3JlbWVudCB0aGUgaG91clwiXG4gICAgICAgIChpbmNyZW1lbnQpPVwiaW5jcmVtZW50SG91cigpXCJcbiAgICAgICAgKGRlY3JlbWVudCk9XCJkZWNyZW1lbnRIb3VyKClcIlxuICAgICAgPlxuICAgICAgPC91eC1zcGluLWJ1dHRvbj5cbiAgICA8L2Rpdj5cbiAgfVxuXG4gIEBpZiAoc2hvd01pbnV0ZXMpIHtcbiAgICA8ZGl2IGNsYXNzPVwidGltZS1waWNrZXItc2VwYXJhdG9yXCI+OjwvZGl2PlxuICB9XG5cbiAgQGlmIChzaG93TWludXRlcykge1xuICAgIDxkaXYgY2xhc3M9XCJ0aW1lLXBpY2tlci1jb2x1bW4gdGltZS1taW51dGVzLXBpY2tlclwiIFtjbGFzcy5oYXMtZXJyb3JdPVwiIV92YWxpZFwiPlxuICAgICAgPHV4LXNwaW4tYnV0dG9uXG4gICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICBjbGFzcz1cInRpbWUtc3Bpbm5lclwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwiTU1cIlxuICAgICAgICBbbWF4TGVuZ3RoXT1cIjJcIlxuICAgICAgICBbbWluXT1cIjBcIlxuICAgICAgICBbbWF4XT1cIjU5XCJcbiAgICAgICAgW3ZhbHVlXT1cImlzVmFsaWREYXRlID8gKHZhbHVlIHwgZGF0ZTogJ21tJykgOiAnJ1wiXG4gICAgICAgICh2YWx1ZUNoYW5nZSk9XCJtaW51dGVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgIFtzcGlubmVyc109XCJzaG93U3Bpbm5lcnNcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICBbcmVhZE9ubHldPVwicmVhZE9ubHlcIlxuICAgICAgICBpbnB1dEFyaWFMYWJlbD1cIm1pbnV0ZVwiXG4gICAgICAgIGluY3JlbWVudEFyaWFMYWJlbD1cIkluY3JlbWVudCB0aGUgbWludXRlXCJcbiAgICAgICAgZGVjcmVtZW50QXJpYUxhYmVsPVwiRGVjcmVtZW50IHRoZSBtaW51dGVcIlxuICAgICAgICAoaW5jcmVtZW50KT1cImluY3JlbWVudE1pbnV0ZSgpXCJcbiAgICAgICAgKGRlY3JlbWVudCk9XCJkZWNyZW1lbnRNaW51dGUoKVwiXG4gICAgICA+XG4gICAgICA8L3V4LXNwaW4tYnV0dG9uPlxuICAgIDwvZGl2PlxuICB9XG5cbiAgQGlmIChzaG93U2Vjb25kcykge1xuICAgIDxkaXYgY2xhc3M9XCJ0aW1lLXBpY2tlci1zZXBhcmF0b3JcIj46PC9kaXY+XG4gIH1cblxuICBAaWYgKHNob3dTZWNvbmRzKSB7XG4gICAgPGRpdiBjbGFzcz1cInRpbWUtcGlja2VyLWNvbHVtbiB0aW1lLXNlY29uZHMtcGlja2VyXCIgW2NsYXNzLmhhcy1lcnJvcl09XCIhX3ZhbGlkXCI+XG4gICAgICA8dXgtc3Bpbi1idXR0b25cbiAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgIGNsYXNzPVwidGltZS1zcGlubmVyXCJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJTU1wiXG4gICAgICAgIFttYXhMZW5ndGhdPVwiMlwiXG4gICAgICAgIFttaW5dPVwiMFwiXG4gICAgICAgIFttYXhdPVwiNTlcIlxuICAgICAgICBbdmFsdWVdPVwiaXNWYWxpZERhdGUgPyAodmFsdWUgfCBkYXRlOiAnc3MnKSA6ICcnXCJcbiAgICAgICAgKHZhbHVlQ2hhbmdlKT1cInNlY29uZENoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgW3NwaW5uZXJzXT1cInNob3dTcGlubmVyc1wiXG4gICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgIFtyZWFkT25seV09XCJyZWFkT25seVwiXG4gICAgICAgIGlucHV0QXJpYUxhYmVsPVwic2Vjb25kc1wiXG4gICAgICAgIGluY3JlbWVudEFyaWFMYWJlbD1cIkluY3JlbWVudCB0aGUgc2Vjb25kXCJcbiAgICAgICAgZGVjcmVtZW50QXJpYUxhYmVsPVwiRGVjcmVtZW50IHRoZSBzZWNvbmRcIlxuICAgICAgICAoaW5jcmVtZW50KT1cImluY3JlbWVudFNlY29uZCgpXCJcbiAgICAgICAgKGRlY3JlbWVudCk9XCJkZWNyZW1lbnRTZWNvbmQoKVwiXG4gICAgICA+XG4gICAgICA8L3V4LXNwaW4tYnV0dG9uPlxuICAgIDwvZGl2PlxuICB9XG48L2Rpdj5cblxuQGlmIChzaG93TWVyaWRpYW4pIHtcbiAgPGRpdiBjbGFzcz1cInRpbWUtcGlja2VyLW1lcmlkaWFuXCI+XG4gICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cFwiIHJvbGU9XCJyYWRpb2dyb3VwXCI+XG4gICAgICBAZm9yIChtZXJpZGlhbiBvZiBtZXJpZGlhbnM7IHRyYWNrIG1lcmlkaWFuKSB7XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBjbGFzcz1cImJ0biBidXR0b24tdG9nZ2xlLWFjY2VudFwiXG4gICAgICAgICAgcm9sZT1cInJhZGlvXCJcbiAgICAgICAgICB0YWJpbmRleD1cIjBcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgKGNsaWNrKT1cInNlbGVjdE1lcmlkaWFuKG1lcmlkaWFuKVwiXG4gICAgICAgICAgW2NsYXNzLmFjdGl2ZV09XCJtZXJpZGlhbiA9PT0gX21lcmlkaWFuXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIm1lcmlkaWFuXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWNoZWNrZWRdPVwibWVyaWRpYW4gPT09IF9tZXJpZGlhblwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyBtZXJpZGlhbiB9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG59XG4iXX0=