fundamental-ngx
Version:
SAP Fiori Fundamentals, implemented in Angular
716 lines • 53.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ElementRef, EventEmitter, forwardRef, HostListener, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { TimeComponent } from '../time/time.component';
import { DateTimeFormatParser } from './format/datetime-parser';
/**
* The datetime picker component is an opinionated composition of the fd-popover,
* fd-calendar and fd-time components to accomplish the UI pattern for picking a date and time.
*/
var DatetimePickerComponent = /** @class */ (function () {
/** @hidden */
function DatetimePickerComponent(elRef, dateTimeAdapter) {
this.elRef = elRef;
this.dateTimeAdapter = dateTimeAdapter;
/**
* Placeholder for the inner input element.
*/
this.placeholder = 'mm/dd/yyyy, hh:mm:ss am';
/**
* Whether the component should be in compact mode.
*/
this.compact = false;
/**
* The placement of the popover. It can be one of: top, top-start, top-end, bottom,
* bottom-start, bottom-end, right, right-start, right-end, left, left-start, left-end.
*/
this.placement = 'bottom-start';
/**
* Whether the time component should be meridian (am/pm).
*/
this.meridian = true;
/**
* Whether the time component shows spinners for changing the time.
*/
this.spinners = true;
/**
* Whether the time component shows seconds.
*/
this.displaySeconds = true;
/**
* Whether to perform visual validation on the picker input.
*/
this.validate = true;
/**
* Current selected date. Two-way binding is supported.
*/
this.date = new Date();
/**
* Whether the popover is open. Two-way binding is supported.
*/
this.isOpen = false;
/**
* The disableFunction for the calendar.
*/
this.startingDayOfWeek = 0;
/**
* Aria label for the datetime picker input.
*/
this.datetimeInputLabel = 'Datetime input';
/**
* Aria label for the button to show/hide the calendar.
*/
this.displayDatetimeToggleLabel = 'Display calendar toggle';
/**
* Whether a null input is considered valid.
*/
this.allowNull = true;
/**
* Event emitted when the date changes. This can be a time or day change.
*/
this.dateChange = new EventEmitter();
/**
* Event emitted when the day changes from the calendar.
*/
this.calendarChange = new EventEmitter();
/**
* Event emitted when the time changes from the time component.
*/
this.timeChange = new EventEmitter();
/**
* Event emitted when popover closes.
*/
this.onClose = new EventEmitter();
/**
* @hidden Date of the input field. Internal use.
* For programmatic selection, use two-way binding on the date input.
*/
this.inputFieldDate = null;
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
*/
this.isInvalidDateInput = false;
/**
* @hidden Observable used internally.
*/
this.dateFromInput = new Subject();
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
*/
this.time = { hour: 0, minute: 0, second: 0 };
/**
* @hidden The CalendarDay object which interacts with the inner Calendar component. Internal use.
*/
this.selectedDay = {
date: null
};
this.disableFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* The blockFunction for the calendar.
*/
this.blockFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.disableRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.disableRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.blockRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.blockRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* @hidden
*/
this.onChange = (/**
* @return {?}
*/
function () { });
/**
* @hidden
*/
this.onTouched = (/**
* @return {?}
*/
function () { });
}
/** Toggles the popover. */
/**
* Toggles the popover.
* @return {?}
*/
DatetimePickerComponent.prototype.togglePopover = /**
* Toggles the popover.
* @return {?}
*/
function () {
this.onTouched(this.selectedDay.date);
if (this.isOpen) {
this.closePopover();
}
else {
this.openPopover();
}
};
/** Opens the popover. */
/**
* Opens the popover.
* @param {?=} inputFieldDate
* @return {?}
*/
DatetimePickerComponent.prototype.openPopover = /**
* Opens the popover.
* @param {?=} inputFieldDate
* @return {?}
*/
function (inputFieldDate) {
if (!this.isOpen && !this.disabled) {
this.onTouched(this.selectedDay.date);
this.isOpen = true;
if (inputFieldDate !== null && inputFieldDate !== '' && !this.isInvalidDateInput) {
this.inputValueChange(this.date);
}
}
};
/** Closes the popover */
/**
* Closes the popover
* @return {?}
*/
DatetimePickerComponent.prototype.closePopover = /**
* Closes the popover
* @return {?}
*/
function () {
if (this.isOpen) {
this.onClose.emit(this.date);
this.isOpen = false;
}
};
/**
* @param {?} d
* @return {?}
*/
DatetimePickerComponent.prototype.updatePickerInputHandler = /**
* @param {?} d
* @return {?}
*/
function (d) {
if (d.selectedDay && d.selectedDay.date) {
d.selectedDay.date.setHours(this.date.getHours());
d.selectedDay.date.setMinutes(this.date.getMinutes());
d.selectedDay.date.setSeconds(this.date.getSeconds());
d.selectedDay.date.setMilliseconds(this.date.getMilliseconds());
/** @type {?} */
var previous = this.date.getTime();
this.selectedDay = d.selectedDay;
this.date = d.selectedDay.date;
this.inputFieldDate = this.dateTimeAdapter.format(this.date);
this.time = { hour: this.date.getHours(), minute: this.date.getMinutes(), second: this.date.getSeconds() };
if (this.date.getTime() !== previous) {
this.calendarChange.emit(this.date);
this.dateChange.emit(this.date);
this.onChange(this.date);
}
}
else if (d === '') {
this.selectedDay.date = null;
this.selectedDay.selected = null;
this.time.second = null;
this.time.minute = null;
this.time.hour = null;
this.timeComponent.displayedHour = null;
this.timeComponent.period = 'am';
this.timeComponent.oldPeriod = 'am';
this.calendarChange.emit(null);
this.timeChange.emit(null);
this.dateChange.emit(null);
this.onChange(this.selectedDay.date);
}
};
/** @hidden */
/**
* @hidden
* @param {?} e
* @return {?}
*/
DatetimePickerComponent.prototype.isInvalidDateInputHandler = /**
* @hidden
* @param {?} e
* @return {?}
*/
function (e) {
this.isInvalidDateInput = e;
};
/** @hidden */
/**
* @hidden
* @param {?} e
* @return {?}
*/
DatetimePickerComponent.prototype.inputValueChange = /**
* @hidden
* @param {?} e
* @return {?}
*/
function (e) {
/** @type {?} */
var temp;
if (typeof e === 'string') {
temp = this.dateTimeAdapter.parse(e);
}
else {
temp = new Date(e);
}
/*
Need to check if current locale toDateString contains AM or PM. If the current locale has it and it is absent
from the user's input, the meridian should be considered invalid
*/
/** @type {?} */
var localeMeridian = new Date().toLocaleTimeString().slice(-2);
/** @type {?} */
var meridianValid = true;
if ((localeMeridian === 'AM' || localeMeridian === 'PM') &&
(typeof e === 'string' && e.slice(-2) !== 'AM' && e.slice(-2) !== 'PM')) {
meridianValid = false;
}
if (meridianValid && temp && temp.toLocaleDateString() !== 'Invalid Date') {
/** @type {?} */
var newValue = { hour: temp.getHours(), minute: temp.getMinutes(), second: temp.getSeconds() };
if (newValue.hour !== this.time.hour || newValue.minute !== this.time.minute || newValue.second !== this.time.second) {
this.time = newValue;
this.setTime(true);
}
this.dateFromInput.next(temp.toLocaleDateString());
}
else if (e === '' && this.allowNull) {
this.isInvalidDateInput = false;
this.dateFromInput.next('');
}
else {
this.isInvalidDateInput = true;
}
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
DatetimePickerComponent.prototype.onEscapeKeydownHandler = /**
* @hidden
* @return {?}
*/
function () {
this.closePopover();
};
/** @hidden */
/**
* @hidden
* @param {?} event
* @return {?}
*/
DatetimePickerComponent.prototype.onGlobalClick = /**
* @hidden
* @param {?} event
* @return {?}
*/
function (event) {
if (!this.elRef.nativeElement.contains(event.target)) {
this.closePopover();
}
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
DatetimePickerComponent.prototype.ngOnInit = /**
* @hidden
* @return {?}
*/
function () {
var _this = this;
if (this.date && this.inputFieldDate !== null) {
this.selectedDay.date = this.date;
this.time = { hour: this.date.getHours(), minute: this.date.getMinutes(), second: this.date.getSeconds() };
}
if (this.dateFromInput) {
this.dateFromInputSubscription = this.dateFromInput.subscribe((/**
* @param {?} date
* @return {?}
*/
function (date) {
_this.updatePickerInputHandler(date);
}));
}
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
DatetimePickerComponent.prototype.ngOnDestroy = /**
* @hidden
* @return {?}
*/
function () {
if (this.dateFromInputSubscription) {
this.dateFromInputSubscription.unsubscribe();
}
};
/** @hidden */
/**
* @hidden
* @param {?} fn
* @return {?}
*/
DatetimePickerComponent.prototype.registerOnChange = /**
* @hidden
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onChange = fn;
};
/** @hidden */
/**
* @hidden
* @param {?} fn
* @return {?}
*/
DatetimePickerComponent.prototype.registerOnTouched = /**
* @hidden
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onTouched = fn;
};
/** @hidden */
/**
* @hidden
* @param {?} isDisabled
* @return {?}
*/
DatetimePickerComponent.prototype.setDisabledState = /**
* @hidden
* @param {?} isDisabled
* @return {?}
*/
function (isDisabled) {
this.disabled = isDisabled;
};
/** @hidden */
/**
* @hidden
* @param {?} selected
* @return {?}
*/
DatetimePickerComponent.prototype.writeValue = /**
* @hidden
* @param {?} selected
* @return {?}
*/
function (selected) {
if (!selected) {
return;
}
this.selectedDay.date = selected;
this.time = { hour: selected.getHours(), minute: selected.getMinutes(), second: selected.getSeconds() };
this.date = this.selectedDay.date;
this.setTime();
};
/** @hidden */
/**
* @hidden
* @param {?=} fireEvents
* @return {?}
*/
DatetimePickerComponent.prototype.setTime = /**
* @hidden
* @param {?=} fireEvents
* @return {?}
*/
function (fireEvents) {
if (fireEvents === void 0) { fireEvents = false; }
this.date.setHours(this.time.hour);
this.date.setMinutes(this.time.minute);
this.date.setSeconds(this.time.second);
this.inputFieldDate = this.dateTimeAdapter.format(this.date);
if (fireEvents) {
this.timeChange.emit(this.date);
this.dateChange.emit(this.date);
this.onChange(this.date);
}
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
DatetimePickerComponent.prototype.focusArrowLeft = /**
* @hidden
* @return {?}
*/
function () {
this.elRef.nativeElement.querySelector('#arrowLeft').focus();
};
DatetimePickerComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-datetime-picker',
template: "<div class=\"fd-datetime\">\n <fd-popover [(isOpen)]=\"isOpen\"\n [closeOnOutsideClick]=\"false\"\n [closeOnEscapeKey]=\"false\"\n [triggers]=\"[]\"\n [disabled]=\"disabled\"\n [placement]=\"placement\">\n <fd-popover-control>\n <div class=\"fd-input-group fd-input-group--after\"\n [ngClass]=\"{'fd-input-group--compact' : compact}\">\n <input type=\"text\"\n [attr.aria-label]=\"datetimeInputLabel\"\n [(ngModel)]=\"inputFieldDate\"\n [placeholder]=\"placeholder\"\n (keyup.enter)=\"inputValueChange(inputFieldDate)\"\n (blur)=\"inputValueChange(inputFieldDate)\"\n (click)=\"openPopover(inputFieldDate)\"\n [ngClass]=\"{ 'fd-input--compact': compact, 'is-invalid': isInvalidDateInput && validate }\"\n [disabled]=\"disabled\">\n <span class=\"fd-input-group__addon fd-input-group__addon--after fd-input-group__addon--button\">\n <button class=\"fd-popover__control fd-button--icon fd-button--light sap-icon--date-time\"\n (click)=\"togglePopover()\" [attr.aria-label]=\"displayDatetimeToggleLabel\"\n [attr.aria-expanded]=\"isOpen\" type=\"button\" [disabled]=\"disabled\"></button>\n </span>\n </div>\n </fd-popover-control>\n <fd-popover-body\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-hidden]=\"!isOpen\"\n [style.display]=\"'block'\">\n <div class=\"fd-datetime__container\">\n <fd-calendar calType=\"single\"\n (closeCalendar)=\"closePopover()\"\n [disableFunction]=\"disableFunction ? disableFunction : null\"\n [blockFunction]=\"blockFunction ? blockFunction : null\"\n [disableRangeStartFunction]=\"disableRangeStartFunction ? disableRangeStartFunction : null\"\n [disableRangeEndFunction]=\"disableRangeEndFunction ? disableRangeEndFunction : null\"\n [blockRangeStartFunction]=\"blockRangeStartFunction ? blockRangeStartFunction : null\"\n [blockRangeEndFunction]=\"blockRangeEndFunction ? blockRangeEndFunction : null\"\n [(selectedDay)]=\"selectedDay\"\n (isInvalidDateInput)=\"isInvalidDateInputHandler($event)\"\n [dateFromDatePicker]=\"dateFromInput\"\n [allowFocusEscape]=\"true\"\n [startingDayOfWeek]=\"startingDayOfWeek\"></fd-calendar>\n <div class=\"fd-datetime__separator\"></div>\n <fd-time [disabled]=\"disabled\"\n [meridian]=\"meridian\"\n [(ngModel)]=\"time\"\n (ngModelChange)=\"setTime(true)\"\n [spinners]=\"spinners\"\n [displaySeconds]=\"displaySeconds\"\n (focusArrowLeft)=\"focusArrowLeft()\"></fd-time>\n </div>\n </fd-popover-body>\n </fd-popover>\n</div>\n",
host: {
'(blur)': 'onTouched()',
'[class.fd-datetime-host]': 'true'
},
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((/**
* @return {?}
*/
function () { return DatetimePickerComponent; })),
multi: true
}
],
encapsulation: ViewEncapsulation.None,
styles: [".fd-datetime-host{display:inline-block;width:230px}.fd-datetime-host .fd-datetime{display:block}.fd-datetime-host .fd-datetime__container{display:flex;align-items:center;margin:0 16px}.fd-datetime-host .fd-datetime__separator{background-color:#d3d3d3;width:1px;margin:42px 28px;-ms-grid-row-align:stretch;align-self:stretch}.fd-datetime-host .fd-datetime fd-popover{display:block}.fd-datetime-host .fd-datetime fd-time{width:auto}"]
}] }
];
/** @nocollapse */
DatetimePickerComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: DateTimeFormatParser }
]; };
DatetimePickerComponent.propDecorators = {
timeComponent: [{ type: ViewChild, args: [TimeComponent,] }],
placeholder: [{ type: Input }],
compact: [{ type: Input }],
placement: [{ type: Input }],
meridian: [{ type: Input }],
disabled: [{ type: Input }],
spinners: [{ type: Input }],
displaySeconds: [{ type: Input }],
validate: [{ type: Input }],
date: [{ type: Input }],
isOpen: [{ type: Input }],
startingDayOfWeek: [{ type: Input }],
datetimeInputLabel: [{ type: Input }],
displayDatetimeToggleLabel: [{ type: Input }],
allowNull: [{ type: Input }],
dateChange: [{ type: Output }],
calendarChange: [{ type: Output }],
timeChange: [{ type: Output }],
onClose: [{ type: Output }],
disableFunction: [{ type: Input }],
blockFunction: [{ type: Input }],
disableRangeStartFunction: [{ type: Input }],
disableRangeEndFunction: [{ type: Input }],
blockRangeStartFunction: [{ type: Input }],
blockRangeEndFunction: [{ type: Input }],
onEscapeKeydownHandler: [{ type: HostListener, args: ['document:keydown.escape', [],] }],
onGlobalClick: [{ type: HostListener, args: ['document:click', ['$event'],] }]
};
return DatetimePickerComponent;
}());
export { DatetimePickerComponent };
if (false) {
/**
* @hidden Reference to the inner time component.
* @type {?}
*/
DatetimePickerComponent.prototype.timeComponent;
/**
* Placeholder for the inner input element.
* @type {?}
*/
DatetimePickerComponent.prototype.placeholder;
/**
* Whether the component should be in compact mode.
* @type {?}
*/
DatetimePickerComponent.prototype.compact;
/**
* The placement of the popover. It can be one of: top, top-start, top-end, bottom,
* bottom-start, bottom-end, right, right-start, right-end, left, left-start, left-end.
* @type {?}
*/
DatetimePickerComponent.prototype.placement;
/**
* Whether the time component should be meridian (am/pm).
* @type {?}
*/
DatetimePickerComponent.prototype.meridian;
/**
* Whether the component is disabled.
* @type {?}
*/
DatetimePickerComponent.prototype.disabled;
/**
* Whether the time component shows spinners for changing the time.
* @type {?}
*/
DatetimePickerComponent.prototype.spinners;
/**
* Whether the time component shows seconds.
* @type {?}
*/
DatetimePickerComponent.prototype.displaySeconds;
/**
* Whether to perform visual validation on the picker input.
* @type {?}
*/
DatetimePickerComponent.prototype.validate;
/**
* Current selected date. Two-way binding is supported.
* @type {?}
*/
DatetimePickerComponent.prototype.date;
/**
* Whether the popover is open. Two-way binding is supported.
* @type {?}
*/
DatetimePickerComponent.prototype.isOpen;
/**
* The disableFunction for the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.startingDayOfWeek;
/**
* Aria label for the datetime picker input.
* @type {?}
*/
DatetimePickerComponent.prototype.datetimeInputLabel;
/**
* Aria label for the button to show/hide the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.displayDatetimeToggleLabel;
/**
* Whether a null input is considered valid.
* @type {?}
*/
DatetimePickerComponent.prototype.allowNull;
/**
* Event emitted when the date changes. This can be a time or day change.
* @type {?}
*/
DatetimePickerComponent.prototype.dateChange;
/**
* Event emitted when the day changes from the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.calendarChange;
/**
* Event emitted when the time changes from the time component.
* @type {?}
*/
DatetimePickerComponent.prototype.timeChange;
/**
* Event emitted when popover closes.
* @type {?}
*/
DatetimePickerComponent.prototype.onClose;
/**
* @hidden Date of the input field. Internal use.
* For programmatic selection, use two-way binding on the date input.
* @type {?}
*/
DatetimePickerComponent.prototype.inputFieldDate;
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
* @type {?}
*/
DatetimePickerComponent.prototype.isInvalidDateInput;
/**
* @hidden Observable used internally.
* @type {?}
*/
DatetimePickerComponent.prototype.dateFromInput;
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
* @type {?}
*/
DatetimePickerComponent.prototype.time;
/**
* @hidden The CalendarDay object which interacts with the inner Calendar component. Internal use.
* @type {?}
*/
DatetimePickerComponent.prototype.selectedDay;
/**
* Subscription of the dateFromInput.
* @type {?}
* @private
*/
DatetimePickerComponent.prototype.dateFromInputSubscription;
/** @type {?} */
DatetimePickerComponent.prototype.disableFunction;
/**
* The blockFunction for the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.blockFunction;
/** @type {?} */
DatetimePickerComponent.prototype.disableRangeStartFunction;
/** @type {?} */
DatetimePickerComponent.prototype.disableRangeEndFunction;
/** @type {?} */
DatetimePickerComponent.prototype.blockRangeStartFunction;
/** @type {?} */
DatetimePickerComponent.prototype.blockRangeEndFunction;
/**
* @hidden
* @type {?}
*/
DatetimePickerComponent.prototype.onChange;
/**
* @hidden
* @type {?}
*/
DatetimePickerComponent.prototype.onTouched;
/**
* @type {?}
* @private
*/
DatetimePickerComponent.prototype.elRef;
/**
* @type {?}
* @private
*/
DatetimePickerComponent.prototype.dateTimeAdapter;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXRpbWUtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2Z1bmRhbWVudGFsLW5neC8iLCJzb3VyY2VzIjpbImxpYi9kYXRldGltZS1waWNrZXIvZGF0ZXRpbWUtcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sRUFDTixTQUFTLEVBQ1QsaUJBQWlCLEVBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUU3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFdkQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7Ozs7O0FBTWhFO0lBOFJJLGNBQWM7SUFDZCxpQ0FBb0IsS0FBaUIsRUFDakIsZUFBcUM7UUFEckMsVUFBSyxHQUFMLEtBQUssQ0FBWTtRQUNqQixvQkFBZSxHQUFmLGVBQWUsQ0FBc0I7Ozs7UUF2UXpELGdCQUFXLEdBQVcseUJBQXlCLENBQUM7Ozs7UUFJaEQsWUFBTyxHQUFZLEtBQUssQ0FBQzs7Ozs7UUFLekIsY0FBUyxHQUFjLGNBQWMsQ0FBQzs7OztRQUl0QyxhQUFRLEdBQVksSUFBSSxDQUFDOzs7O1FBUXpCLGFBQVEsR0FBWSxJQUFJLENBQUM7Ozs7UUFJekIsbUJBQWMsR0FBWSxJQUFJLENBQUM7Ozs7UUFJL0IsYUFBUSxHQUFZLElBQUksQ0FBQzs7OztRQUl6QixTQUFJLEdBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQzs7OztRQUl4QixXQUFNLEdBQVksS0FBSyxDQUFDOzs7O1FBSXhCLHNCQUFpQixHQUFXLENBQUMsQ0FBQzs7OztRQUk5Qix1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RSw2Q0FDbUU7Ozs7O0lBR25FLDBDQUNnRTs7Ozs7O0lBTWhFLGlEQUFzQjs7Ozs7SUFHdEIscURBQW9DOzs7OztJQUdwQyxnREFBK0M7Ozs7O0lBRy9DLHVDQUFxRDs7Ozs7SUFHckQsOENBRUU7Ozs7OztJQUdGLDREQUFnRDs7SUFFaEQsa0RBR0U7Ozs7O0lBR0YsZ0RBR0U7O0lBQ0YsNERBR0U7O0lBQ0YsMERBR0U7O0lBQ0YsMERBR0U7O0lBQ0Ysd0RBR0U7Ozs7O0lBR0YsMkNBQXlCOzs7OztJQUd6Qiw0Q0FBMEI7Ozs7O0lBeUlkLHdDQUF5Qjs7Ozs7SUFDekIsa0RBQTZDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBDb21wb25lbnQsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgZm9yd2FyZFJlZiwgSG9zdEJpbmRpbmcsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIElucHV0LFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFZpZXdDaGlsZCxcbiAgICBWaWV3RW5jYXBzdWxhdGlvblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENhbGVuZGFyRGF5IH0gZnJvbSAnLi4vY2FsZW5kYXIvY2FsZW5kYXIuY29tcG9uZW50JztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgVGltZU9iamVjdCB9IGZyb20gJy4uL3RpbWUvdGltZS1vYmplY3QnO1xuaW1wb3J0IHsgVGltZUNvbXBvbmVudCB9IGZyb20gJy4uL3RpbWUvdGltZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgUGxhY2VtZW50IH0gZnJvbSAncG9wcGVyLmpzJztcbmltcG9ydCB7IERhdGVUaW1lRm9ybWF0UGFyc2VyIH0gZnJvbSAnLi9mb3JtYXQvZGF0ZXRpbWUtcGFyc2VyJztcblxuLyoqXG4gKiBUaGUgZGF0ZXRpbWUgcGlja2VyIGNvbXBvbmVudCBpcyBhbiBvcGluaW9uYXRlZCBjb21wb3NpdGlvbiBvZiB0aGUgZmQtcG9wb3ZlcixcbiAqIGZkLWNhbGVuZGFyIGFuZCBmZC10aW1lIGNvbXBvbmVudHMgdG8gYWNjb21wbGlzaCB0aGUgVUkgcGF0dGVybiBmb3IgcGlja2luZyBhIGRhdGUgYW5kIHRpbWUuXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnZmQtZGF0ZXRpbWUtcGlja2VyJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZGF0ZXRpbWUtcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9kYXRldGltZS1waWNrZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgICBob3N0OiB7XG4gICAgICAgICcoYmx1ciknOiAnb25Ub3VjaGVkKCknLFxuICAgICAgICAnW2NsYXNzLmZkLWRhdGV0aW1lLWhvc3RdJzogJ3RydWUnXG4gICAgfSxcbiAgICBwcm92aWRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBEYXRldGltZVBpY2tlckNvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZVxuICAgICAgICB9XG4gICAgXSxcbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXG59KVxuZXhwb3J0IGNsYXNzIERhdGV0aW1lUGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcblxuICAgIC8qKiBAaGlkZGVuIFJlZmVyZW5jZSB0byB0aGUgaW5uZXIgdGltZSBjb21wb25lbnQuICovXG4gICAgQFZpZXdDaGlsZChUaW1lQ29tcG9uZW50KVxuICAgIHRpbWVDb21wb25lbnQ6IFRpbWVDb21wb25lbnQ7XG5cbiAgICAvKiogUGxhY2Vob2xkZXIgZm9yIHRoZSBpbm5lciBpbnB1dCBlbGVtZW50LiAqL1xuICAgIEBJbnB1dCgpXG4gICAgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICdtbS9kZC95eXl5LCBoaDptbTpzcyBhbSc7XG5cbiAgICAvKiogV2hldGhlciB0aGUgY29tcG9uZW50IHNob3VsZCBiZSBpbiBjb21wYWN0IG1vZGUuICovXG4gICAgQElucHV0KClcbiAgICBjb21wYWN0OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogVGhlIHBsYWNlbWVudCBvZiB0aGUgcG9wb3Zlci4gSXQgY2FuIGJlIG9uZSBvZjogdG9wLCB0b3Atc3RhcnQsIHRvcC1lbmQsIGJvdHRvbSxcbiAgICAgKiAgYm90dG9tLXN0YXJ0LCBib3R0b20tZW5kLCByaWdodCwgcmlnaHQtc3RhcnQsIHJpZ2h0LWVuZCwgbGVmdCwgbGVmdC1zdGFydCwgbGVmdC1lbmQuICovXG4gICAgQElucHV0KClcbiAgICBwbGFjZW1lbnQ6IFBsYWNlbWVudCA9ICdib3R0b20tc3RhcnQnO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIHRpbWUgY29tcG9uZW50IHNob3VsZCBiZSBtZXJpZGlhbiAoYW0vcG0pLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgbWVyaWRpYW46IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGNvbXBvbmVudCBpcyBkaXNhYmxlZC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRpc2FibGVkOiBib29sZWFuO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIHRpbWUgY29tcG9uZW50IHNob3dzIHNwaW5uZXJzIGZvciBjaGFuZ2luZyB0aGUgdGltZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIHNwaW5uZXJzOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSB0aW1lIGNvbXBvbmVudCBzaG93cyBzZWNvbmRzLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZGlzcGxheVNlY29uZHM6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIFdoZXRoZXIgdG8gcGVyZm9ybSB2aXN1YWwgdmFsaWRhdGlvbiBvbiB0aGUgcGlja2VyIGlucHV0LiAqL1xuICAgIEBJbnB1dCgpXG4gICAgdmFsaWRhdGU6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIEN1cnJlbnQgc2VsZWN0ZWQgZGF0ZS4gVHdvLXdheSBiaW5kaW5nIGlzIHN1cHBvcnRlZC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRhdGU6IERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIHBvcG92ZXIgaXMgb3Blbi4gVHdvLXdheSBiaW5kaW5nIGlzIHN1cHBvcnRlZC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGlzT3BlbjogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIFRoZSBkaXNhYmxlRnVuY3Rpb24gZm9yIHRoZSBjYWxlbmRhci4gKi9cbiAgICBASW5wdXQoKVxuICAgIHN0YXJ0aW5nRGF5T2ZXZWVrOiBudW1iZXIgPSAwO1xuXG4gICAgLyoqIEFyaWEgbGFiZWwgZm9yIHRoZSBkYXRldGltZSBwaWNrZXIgaW5wdXQuICovXG4gICAgQElucHV0KClcbiAgICBkYXRldGltZUlucHV0TGFiZWw6IHN0cmluZyA9ICdEYXRldGltZSBpbnB1dCc7XG5cbiAgICAvKiogQXJpYSBsYWJlbCBmb3IgdGhlIGJ1dHRvbiB0byBzaG93L2hpZGUgdGhlIGNhbGVuZGFyLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZGlzcGxheURhdGV0aW1lVG9nZ2xlTGFiZWw6IHN0cmluZyA9ICdEaXNwbGF5IGNhbGVuZGFyIHRvZ2dsZSc7XG5cbiAgICAvKiogV2hldGhlciBhIG51bGwgaW5wdXQgaXMgY29uc2lkZXJlZCB2YWxpZC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGFsbG93TnVsbDogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBkYXRlIGNoYW5nZXMuIFRoaXMgY2FuIGJlIGEgdGltZSBvciBkYXkgY2hhbmdlLiAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHJlYWRvbmx5IGRhdGVDaGFuZ2U6IEV2ZW50RW1pdHRlcjxEYXRlPiA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0ZT4oKTtcblxuICAgIC8qKiBFdmVudCBlbWl0dGVkIHdoZW4gdGhlIGRheSBjaGFuZ2VzIGZyb20gdGhlIGNhbGVuZGFyLiAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHJlYWRvbmx5IGNhbGVuZGFyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8RGF0ZT4gPSBuZXcgRXZlbnRFbWl0dGVyPERhdGU+KCk7XG5cbiAgICAvKiogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSB0aW1lIGNoYW5nZXMgZnJvbSB0aGUgdGltZSBjb21wb25lbnQuICovXG4gICAgQE91dHB1dCgpXG4gICAgcmVhZG9ubHkgdGltZUNoYW5nZTogRXZlbnRFbWl0dGVyPERhdGU+ID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xuXG4gICAgLyoqIEV2ZW50IGVtaXR0ZWQgd2hlbiBwb3BvdmVyIGNsb3Nlcy4gKi9cbiAgICBAT3V0cHV0KClcbiAgICByZWFkb25seSBvbkNsb3NlOiBFdmVudEVtaXR0ZXI8RGF0ZT4gPSBuZXcgRXZlbnRFbWl0dGVyPERhdGU+KCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIERhdGUgb2YgdGhlIGlucHV0IGZpZWxkLiBJbnRlcm5hbCB1c2UuXG4gICAgICogRm9yIHByb2dyYW1tYXRpYyBzZWxlY3Rpb24sIHVzZSB0d28td2F5IGJpbmRpbmcgb24gdGhlIGRhdGUgaW5wdXQuXG4gICAgICovXG4gICAgaW5wdXRGaWVsZERhdGUgPSBudWxsO1xuXG4gICAgLyoqIEBoaWRkZW4gVGhlIFRpbWUgb2JqZWN0IHdoaWNoIGludGVyYWN0cyB3aXRoIHRoZSBpbm5lciBUaW1lIGNvbXBvbmVudC4gSW50ZXJuYWwgdXNlLiAqL1xuICAgIGlzSW52YWxpZERhdGVJbnB1dDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIEBoaWRkZW4gT2JzZXJ2YWJsZSB1c2VkIGludGVybmFsbHkuICovXG4gICAgZGF0ZUZyb21JbnB1dDogU3ViamVjdDxzdHJpbmc+ID0gbmV3IFN1YmplY3QoKTtcblxuICAgIC8qKiBAaGlkZGVuIFRoZSBUaW1lIG9iamVjdCB3aGljaCBpbnRlcmFjdHMgd2l0aCB0aGUgaW5uZXIgVGltZSBjb21wb25lbnQuIEludGVybmFsIHVzZS4gKi9cbiAgICB0aW1lOiBUaW1lT2JqZWN0ID0geyBob3VyOiAwLCBtaW51dGU6IDAsIHNlY29uZDogMCB9O1xuXG4gICAgLyoqIEBoaWRkZW4gVGhlIENhbGVuZGFyRGF5IG9iamVjdCB3aGljaCBpbnRlcmFjdHMgd2l0aCB0aGUgaW5uZXIgQ2FsZW5kYXIgY29tcG9uZW50LiBJbnRlcm5hbCB1c2UuICovXG4gICAgc2VsZWN0ZWREYXk6IENhbGVuZGFyRGF5ID0ge1xuICAgICAgICBkYXRlOiBudWxsXG4gICAgfTtcblxuICAgIC8qKiBTdWJzY3JpcHRpb24gb2YgdGhlIGRhdGVGcm9tSW5wdXQuICovXG4gICAgcHJpdmF0ZSBkYXRlRnJvbUlucHV0U3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgICBASW5wdXQoKVxuICAgIGRpc2FibGVGdW5jdGlvbiA9IGZ1bmN0aW9uKGQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICAvKiogVGhlIGJsb2NrRnVuY3Rpb24gZm9yIHRoZSBjYWxlbmRhci4gKi9cbiAgICBASW5wdXQoKVxuICAgIGJsb2NrRnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEBJbnB1dCgpXG4gICAgZGlzYWJsZVJhbmdlU3RhcnRGdW5jdGlvbiA9IGZ1bmN0aW9uKGQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQElucHV0KClcbiAgICBkaXNhYmxlUmFuZ2VFbmRGdW5jdGlvbiA9IGZ1bmN0aW9uKGQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQElucHV0KClcbiAgICBibG9ja1JhbmdlU3RhcnRGdW5jdGlvbiA9IGZ1bmN0aW9uKGQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQElucHV0KClcbiAgICBibG9ja1JhbmdlRW5kRnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBvbkNoYW5nZTogYW55ID0gKCkgPT4ge307XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uVG91Y2hlZDogYW55ID0gKCkgPT4ge307XG5cbiAgICAvKiogVG9nZ2xlcyB0aGUgcG9wb3Zlci4gKi9cbiAgICB0b2dnbGVQb3BvdmVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCh0aGlzLnNlbGVjdGVkRGF5LmRhdGUpO1xuICAgICAgICBpZiAodGhpcy5pc09wZW4pIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VQb3BvdmVyKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5Qb3BvdmVyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogT3BlbnMgdGhlIHBvcG92ZXIuICovXG4gICAgb3BlblBvcG92ZXIoaW5wdXRGaWVsZERhdGU/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzT3BlbiAmJiAhdGhpcy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5vblRvdWNoZWQodGhpcy5zZWxlY3RlZERheS5kYXRlKTtcbiAgICAgICAgICAgIHRoaXMuaXNPcGVuID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChpbnB1dEZpZWxkRGF0ZSAhPT0gbnVsbCAmJiBpbnB1dEZpZWxkRGF0ZSAhPT0gJycgJiYgIXRoaXMuaXNJbnZhbGlkRGF0ZUlucHV0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dFZhbHVlQ2hhbmdlKHRoaXMuZGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQ2xvc2VzIHRoZSBwb3BvdmVyICovXG4gICAgY2xvc2VQb3BvdmVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pc09wZW4pIHtcbiAgICAgICAgICAgIHRoaXMub25DbG9zZS5lbWl0KHRoaXMuZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdXBkYXRlUGlja2VySW5wdXRIYW5kbGVyKGQpOiB2b2lkIHtcbiAgICAgICAgaWYgKGQuc2VsZWN0ZWREYXkgJiYgZC5zZWxlY3RlZERheS5kYXRlKSB7XG4gICAgICAgICAgICBkLnNlbGVjdGVkRGF5LmRhdGUuc2V0SG91cnModGhpcy5kYXRlLmdldEhvdXJzKCkpO1xuICAgICAgICAgICAgZC5zZWxlY3RlZERheS5kYXRlLnNldE1pbnV0ZXModGhpcy5kYXRlLmdldE1pbnV0ZXMoKSk7XG4gICAgICAgICAgICBkLnNlbGVjdGVkRGF5LmRhdGUuc2V0U2Vjb25kcyh0aGlzLmRhdGUuZ2V0U2Vjb25kcygpKTtcbiAgICAgICAgICAgIGQuc2VsZWN0ZWREYXkuZGF0ZS5zZXRNaWxsaXNlY29uZHModGhpcy5kYXRlLmdldE1pbGxpc2Vjb25kcygpKTtcbiAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzID0gdGhpcy5kYXRlLmdldFRpbWUoKTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXkgPSBkLnNlbGVjdGVkRGF5O1xuICAgICAgICAgICAgdGhpcy5kYXRlID0gZC5zZWxlY3RlZERheS5kYXRlO1xuICAgICAgICAgICAgdGhpcy5pbnB1dEZpZWxkRGF0ZSA9IHRoaXMuZGF0ZVRpbWVBZGFwdGVyLmZvcm1hdCh0aGlzLmRhdGUpO1xuICAgICAgICAgICAgdGhpcy50aW1lID0ge2hvdXI6IHRoaXMuZGF0ZS5nZXRIb3VycygpLCBtaW51dGU6IHRoaXMuZGF0ZS5nZXRNaW51dGVzKCksIHNlY29uZDogdGhpcy5kYXRlLmdldFNlY29uZHMoKX07XG4gICAgICAgICAgICBpZiAodGhpcy5kYXRlLmdldFRpbWUoKSAhPT0gcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGVuZGFyQ2hhbmdlLmVtaXQodGhpcy5kYXRlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGVDaGFuZ2UuZW1pdCh0aGlzLmRhdGUpO1xuICAgICAgICAgICAgICAgIHRoaXMub25DaGFuZ2UodGhpcy5kYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChkID09PSAnJykge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERheS5kYXRlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXkuc2VsZWN0ZWQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy50aW1lLnNlY29uZCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnRpbWUubWludXRlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudGltZS5ob3VyID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudGltZUNvbXBvbmVudC5kaXNwbGF5ZWRIb3VyID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudGltZUNvbXBvbmVudC5wZXJpb2QgPSAnYW0nO1xuICAgICAgICAgICAgdGhpcy50aW1lQ29tcG9uZW50Lm9sZFBlcmlvZCA9ICdhbSc7XG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyQ2hhbmdlLmVtaXQobnVsbCk7XG4gICAgICAgICAgICB0aGlzLnRpbWVDaGFuZ2UuZW1pdChudWxsKTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUNoYW5nZS5lbWl0KG51bGwpO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSh0aGlzLnNlbGVjdGVkRGF5LmRhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBpc0ludmFsaWREYXRlSW5wdXRIYW5kbGVyKGUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc0ludmFsaWREYXRlSW5wdXQgPSBlO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgaW5wdXRWYWx1ZUNoYW5nZShlKTogdm9pZCB7XG4gICAgICAgIGxldCB0ZW1wO1xuICAgICAgICBpZiAodHlwZW9mIGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0ZW1wID0gdGhpcy5kYXRlVGltZUFkYXB0ZXIucGFyc2UoZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZW1wID0gbmV3IERhdGUoZSk7XG4gICAgICAgIH1cbiAgICAgICAgLypcbiAgICAgICAgIE5lZWQgdG8gY2hlY2sgaWYgY3VycmVudCBsb2NhbGUgdG9EYXRlU3RyaW5nIGNvbnRhaW5zIEFNIG9yIFBNLiBJZiB0aGUgY3VycmVudCBsb2NhbGUgaGFzIGl0IGFuZCBpdCBpcyBhYnNlbnRcbiAgICAgICAgIGZyb20gdGhlIHVzZXIncyBpbnB1dCwgdGhlIG1lcmlkaWFuIHNob3VsZCBiZSBjb25zaWRlcmVkIGludmFsaWRcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0IGxvY2FsZU1lcmlkaWFuID0gbmV3IERhdGUoKS50b0xvY2FsZVRpbWVTdHJpbmcoKS5zbGljZSgtMik7XG4gICAgICAgIGxldCBtZXJpZGlhblZhbGlkID0gdHJ1ZTtcbiAgICAgICAgaWYgKChsb2NhbGVNZXJpZGlhbiA9PT0gJ0FNJyB8fCBsb2NhbGVNZXJpZGlhbiA9PT0gJ1BNJykgJiZcbiAgICAgICAgICAgICh0eXBlb2YgZSA9PT0gJ3N0cmluZycgJiYgZS5zbGljZSgtMikgIT09ICdBTScgJiYgZS5zbGljZSgtMikgIT09ICdQTScpKSB7XG4gICAgICAgICAgICBtZXJpZGlhblZhbGlkID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWVyaWRpYW5WYWxpZCAmJiB0ZW1wICYmIHRlbXAudG9Mb2NhbGVEYXRlU3RyaW5nKCkgIT09ICdJbnZhbGlkIERhdGUnKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdWYWx1ZSA9IHtob3VyOiB0ZW1wLmdldEhvdXJzKCksIG1pbnV0ZTogdGVtcC5nZXRNaW51dGVzKCksIHNlY29uZDogdGVtcC5nZXRTZWNvbmRzKCl9O1xuICAgICAgICAgICAgaWYgKG5ld1ZhbHVlLmhvdXIgIT09IHRoaXMudGltZS5ob3VyIHx8IG5ld1ZhbHVlLm1pbnV0ZSAhPT0gdGhpcy50aW1lLm1pbnV0ZSB8fCBuZXdWYWx1ZS5zZWNvbmQgIT09IHRoaXMudGltZS5zZWNvbmQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFRpbWUodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAg