angular-bootstrap-datetimepicker
Version:
Native Angular (8+) datetime picker component styled by Twitter Bootstrap 4.
532 lines • 55.9 kB
JavaScript
/**
* @license
* Copyright 2013-present Dale Lotts All Rights Reserved.
* http://www.dalelotts.com
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/dalelotts/angular-bootstrap-datetimepicker/blob/master/LICENSE
*/
import * as tslib_1 from "tslib";
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, NgZone, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import * as _moment from 'moment';
import { take } from 'rxjs/operators';
import { DlDateAdapter } from '../core/public-api';
import { DlDateTimePickerChange } from './dl-date-time-picker-change';
import { DlDayModelProvider } from './dl-model-provider-day';
import { DlHourModelProvider } from './dl-model-provider-hour';
import { DlMinuteModelProvider } from './dl-model-provider-minute';
import { DlMonthModelProvider } from './dl-model-provider-month';
import { DlYearModelProvider } from './dl-model-provider-year';
/**
* Work around for moment namespace conflict when used with webpack and rollup.
* See https://github.com/dherges/ng-packagr/issues/163
*
* Depending on whether rollup is used, moment needs to be imported differently.
* Since Moment.js doesn't have a default export, we normally need to import using
* the `* as`syntax.
*
* rollup creates a synthetic default module and we thus need to import it using
* the `default as` syntax.
*
* @internal
**/
var moment = _moment;
/**
* Maps key codes to the model provider function name
* that should be called to perform the action.
*
* @internal
**/
var keyCodeToModelProviderMethod = {
'ArrowDown': 'goDown',
'ArrowLeft': 'goLeft',
'ArrowRight': 'goRight',
'ArrowUp': 'goUp',
'Down': 'goDown',
'End': 'goEnd',
'Home': 'goHome',
'Left': 'goLeft',
'PageDown': 'pageDown',
'PageUp': 'pageUp',
'Right': 'goRight',
'Up': 'goUp',
33: 'pageUp',
34: 'pageDown',
35: 'goEnd',
36: 'goHome',
37: 'goLeft',
38: 'goUp',
39: 'goRight',
40: 'goDown',
};
/**
* List of view names for the calendar.
*
* This list must be in order from
* smallest increment of time to largest increment of time.
*
* @internal
**/
var VIEWS = [
'minute',
'hour',
'day',
'month',
'year'
];
/**
* Component that provides all of the user facing functionality of the date/time picker.
*/
var DlDateTimePickerComponent = /** @class */ (function () {
/**
* Used to construct a new instance of a date/time picker.
*
* @param _elementRef
* reference to this element.
* @param _ngZone
* reference to an NgZone instance used to select the active element outside of angular.
* @param _dateAdapter
* date adapter for the date type in the model.
* @param yearModelComponent
* provider for the year view model.
* @param monthModelComponent
* provider for the month view model.
* @param dayModelComponent
* provider for the day view model.
* @param hourModelComponent
* provider for the hour view model.
* @param minuteModelComponent
* provider for the minute view model.
*/
function DlDateTimePickerComponent(_elementRef, _ngZone, _dateAdapter,
// @ts-ignore
yearModelComponent,
// @ts-ignore
monthModelComponent,
// @ts-ignore
dayModelComponent,
// @ts-ignore
hourModelComponent,
// @ts-ignore
minuteModelComponent) {
this._elementRef = _elementRef;
this._ngZone = _ngZone;
this._dateAdapter = _dateAdapter;
this.yearModelComponent = yearModelComponent;
this.monthModelComponent = monthModelComponent;
this.dayModelComponent = dayModelComponent;
this.hourModelComponent = hourModelComponent;
this.minuteModelComponent = minuteModelComponent;
/**
* Change listener callback functions registered
* via `registerOnChange`
* @internal
**/
this._changed = [];
/**
* Maps view name to the next view (the view for the next smallest increment of time).
* @internal
**/
this._nextView = {
'year': 'month',
'month': 'day',
'day': 'hour',
'hour': 'minute'
};
/**
* Maps view name to the previous view (the view for the next largest increment of time).
* @internal
**/
this._previousView = {
'minute': 'hour',
'hour': 'day',
'day': 'month',
'month': 'year'
};
/**
* Touch listener callback functions registered
* via `registerOnChange`
* @internal
**/
this._touched = [];
/**
* Emits when a `change` event when date/time is selected or
* the value of the date/time picker changes.
**/
this.change = new EventEmitter();
/**
* Specifies the classes used to display the left icon.
*
* This component uses OPENICONIC https://useiconic.com/open
* by default but any icon library may be used.
*/
this.leftIconClass = [
'oi',
'oi-chevron-left'
];
/**
* The highest view that the date/time picker can show.
* Setting this to a view less than year could make it more
* difficult for the end-user to navigate to certain dates.
*/
this.maxView = 'year';
/**
* The view that will be used for date/time selection.
*
* The default of `minute means that selection will not happen
* until the end-user clicks on a cell in the minute view.
*
* for example, if you want the end-user to select a only day (date),
* setting `minView` to `day` will cause selection to happen when the
* end-user selects a cell in the day view.
*
* NOTE: This must be set lower than or equal to `startView'
*/
this.minView = 'minute';
/**
* The number of minutes between each `.dl-abdtp-minute` button.
*
* Must be greater than `0` and less than `60`.
*/
this.minuteStep = 5;
/**
* Specifies the classes used to display the right icon.
*
* This component uses OPENICONIC https://useiconic.com/open
* by default but any icon library may be used.
*/
this.rightIconClass = [
'oi',
'oi-chevron-right'
];
/* tslint:disable:member-ordering */
/**
* Determine whether or not the `DateButton` is selectable by the end user.
*/
this.selectFilter = function () { return true; };
/**
* The initial view that the date/time picker will show.
* The picker will also return to this view after a date/time
* is selected.
*
* NOTE: This must be set lower than or equal to `maxView'
*/
this.startView = 'day';
/**
* Specifies the classes used to display the up icon.
*
* This component uses OPENICONIC https://useiconic.com/open
* by default but any icon library may be used.
*/
this.upIconClass = [
'oi',
'oi-chevron-top'
];
this._viewToModelProvider = {
year: yearModelComponent,
month: monthModelComponent,
day: dayModelComponent,
hour: hourModelComponent,
minute: minuteModelComponent,
};
}
DlDateTimePickerComponent_1 = DlDateTimePickerComponent;
Object.defineProperty(DlDateTimePickerComponent.prototype, "model", {
/* tslint:enable:member-ordering */
/**
* Set's the model for the current view after applying the selection filter.
*
* @internal
**/
set: function (model) {
this._model = this.applySelectFilter(model);
},
enumerable: true,
configurable: true
});
Object.defineProperty(DlDateTimePickerComponent.prototype, "value", {
/**
* Returns `D` value of the date/time picker or undefined/null if no value is set.
**/
get: function () {
return this._value;
},
/**
* Sets value of the date/time picker and emits a change event if the
* new value is different from the previous value.
**/
set: function (value) {
if (this._value !== value) {
this._value = value;
this.model = this._viewToModelProvider[this._model.viewName].getModel(this.getStartDate(), this.valueOf);
this._changed.forEach(function (f) { return f(value); });
this.change.emit(new DlDateTimePickerChange(value));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(DlDateTimePickerComponent.prototype, "valueOf", {
/**
* Returns `milliseconds` value of the date/time picker or undefined/null if no value is set.
**/
get: function () {
return this._dateAdapter.toMilliseconds(this._value);
},
enumerable: true,
configurable: true
});
/**
* Applies the `selectionFilter` by adding the `dl-abdtp-disabled`
* class to any `DateButton` where `selectFilter` returned false.
*
* @param model
* the new model
*
* @returns
* the supplied model with zero or more `DateButton`'s
* having the `dl-abdtp-disabled` class set to `true` if the
* selection for that date should be disabled.
*
* @internal
*/
DlDateTimePickerComponent.prototype.applySelectFilter = function (model) {
var _this = this;
if (this.selectFilter) {
model.rows = model.rows.map(function (row) {
row.cells.map(function (dateButton) {
var disabled = !_this.selectFilter(dateButton, model.viewName);
dateButton.classes['dl-abdtp-disabled'] = disabled;
if (disabled) {
dateButton.classes['aria-disabled'] = true;
}
return dateButton;
});
return row;
});
}
return model;
};
/**
* Focuses the `.dl-abdtp-active` cell after the microtask queue is empty.
* @internal
**/
DlDateTimePickerComponent.prototype.focusActiveCell = function () {
var _this = this;
this._ngZone.runOutsideAngular(function () {
_this._ngZone.onStable.asObservable().pipe(take(1)).subscribe(function () {
_this._elementRef.nativeElement.querySelector('.dl-abdtp-active').focus();
});
});
};
/**
* Determines the start date for the picker.
* @internal
**/
DlDateTimePickerComponent.prototype.getStartDate = function () {
if (hasValue(this._value)) {
return this._dateAdapter.toMilliseconds(this._value);
}
if (hasValue(this.startDate)) {
return this.startDate;
}
return moment().valueOf();
};
/**
* Determine the start view for the picker
* @returns
* the largest time increment view between the `minView` or `minute` view and the `startView` or `day` view.
*/
DlDateTimePickerComponent.prototype.getStartView = function () {
var startIndex = Math.max(VIEWS.indexOf(this.minView || 'minute'), VIEWS.indexOf(this.startView || 'day'));
return VIEWS[startIndex];
};
/**
* Calls all registered `touch` callback functions.
* @internal
**/
DlDateTimePickerComponent.prototype.onTouch = function () {
this._touched.forEach(function (onTouched) { return onTouched(); });
};
/**
* Receives configuration changes detected by Angular and passes the changes on
* to the model providers so the provider is aware of any necessary configuration
* changes (i.e. minuteStep)
*
* @param changes
* the input changes detected by Angular.
*/
DlDateTimePickerComponent.prototype.ngOnChanges = function (changes) {
Object.values(this._viewToModelProvider).forEach(function (provider) { return provider.onChanges(changes); });
if (this._model) { // only update the model after ngOnInit has set it the first time.
this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.activeDate, this.valueOf);
}
};
/**
* Sets the initial model.
*
* @internal
**/
DlDateTimePickerComponent.prototype.ngOnInit = function () {
this.model = this._viewToModelProvider[this.getStartView()].getModel(this.getStartDate(), this.valueOf);
};
/**
* Handles click (and enter & space key down) events on the date elements.
*
* If the current view is the minimum view then the date value is selected
* and the picker returns to the start view.
*
* Otherwise the picker displays the next view with the next
* smallest time increment.
*
* @internal
**/
DlDateTimePickerComponent.prototype._onDateClick = function (dateButton) {
if (dateButton.classes['dl-abdtp-disabled']) {
return;
}
var nextView = this._nextView[this._model.viewName];
if ((this.minView || 'minute') === this._model.viewName) {
this.value = this._dateAdapter.fromMilliseconds(dateButton.value);
nextView = this.startView;
}
this.model = this._viewToModelProvider[nextView].getModel(dateButton.value, this.valueOf);
this.onTouch();
};
/**
* Handles click (and enter & space key down) events on the left button.
*
* Changes the displayed time range of the picker to the previous time range.
* For example, in year view, the previous decade is displayed.
*
* @internal
**/
DlDateTimePickerComponent.prototype._onLeftClick = function () {
this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.leftButton.value, this.valueOf);
this.onTouch();
};
/**
* Handles click (and enter & space key down) events on the up button.
*
* Changes the view of the picker to the next largest time increment.
* For example, in day view, the next view displayed will be month view.
*
* @internal
**/
DlDateTimePickerComponent.prototype._onUpClick = function () {
this.model = this._viewToModelProvider[this._previousView[this._model.viewName]].getModel(this._model.upButton.value, this.valueOf);
};
/**
* Handles click (and enter & space key down) events on the right button.
*
* Changes the displayed time range of the picker to the next time range.
* For example, in year view, the next decade is displayed.
*
* @internal
**/
DlDateTimePickerComponent.prototype._onRightClick = function () {
this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.rightButton.value, this.valueOf);
this.onTouch();
};
/**
* Handles various key down events to move the `active date` around the calendar.
*
* @internal
**/
DlDateTimePickerComponent.prototype._handleKeyDown = function ($event) {
var functionName = keyCodeToModelProviderMethod[$event.key];
if (functionName) {
var modelProvider = this._viewToModelProvider[this._model.viewName];
this.model = modelProvider[functionName](this._model.activeDate, this.valueOf);
this.focusActiveCell();
// Prevent unexpected default actions such as form submission.
$event.preventDefault();
}
};
/**
* Implements ControlValueAccessor.registerOnChange to register change listeners.
* @internal
**/
DlDateTimePickerComponent.prototype.registerOnChange = function (fn) {
this._changed.push(fn);
};
/**
* Implements ControlValueAccessor.registerOnTouched to register touch listeners.
* @internal
**/
DlDateTimePickerComponent.prototype.registerOnTouched = function (fn) {
this._touched.push(fn);
};
/**
* Implements ControlValueAccessor.writeValue to store the value from the model.
* @internal
**/
DlDateTimePickerComponent.prototype.writeValue = function (value) {
this.value = value;
};
var DlDateTimePickerComponent_1;
DlDateTimePickerComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: NgZone },
{ type: DlDateAdapter },
{ type: DlYearModelProvider },
{ type: DlMonthModelProvider },
{ type: DlDayModelProvider },
{ type: DlHourModelProvider },
{ type: DlMinuteModelProvider }
]; };
tslib_1.__decorate([
Output()
], DlDateTimePickerComponent.prototype, "change", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "leftIconClass", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "maxView", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "minView", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "minuteStep", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "rightIconClass", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "selectFilter", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "startDate", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "startView", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "upIconClass", void 0);
DlDateTimePickerComponent = DlDateTimePickerComponent_1 = tslib_1.__decorate([
Component({
changeDetection: ChangeDetectionStrategy.OnPush,
preserveWhitespaces: false,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: DlDateTimePickerComponent_1,
multi: true
}
],
selector: 'dl-date-time-picker',
template: "<div class=\"text-center dl-abdtp-{{_model.viewName}}-view\" [attr.data-dl-abdtp-view]=\"_model.viewName\">\n <div class=\"row align-items-center no-gutters\">\n <button class=\"col dl-abdtp-left-button align-items-center\"\n type=\"button\"\n [attr.aria-label]=\"_model.leftButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.leftButton.value\"\n [attr.title]=\"_model.leftButton.ariaLabel\"\n (click)=\"_onLeftClick()\"\n ><span class=\"left-icon\" [ngClass]=\"leftIconClass\"></span>\n </button>\n\n <div *ngIf=\"_model.viewName === (this.maxView || 'year'); then maxViewLabel else defaultViewLabel;\"></div>\n\n <button class=\"col dl-abdtp-right-button\"\n type=\"button\"\n [attr.aria-label]=\"_model.rightButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.rightButton.value\"\n [attr.title]=\"_model.rightButton.ariaLabel\"\n (click)=\"_onRightClick()\"\n ><span class=\"right-icon\" [ngClass]=\"rightIconClass\"></span>\n </button>\n </div>\n <div (keydown)=\"_handleKeyDown($event)\">\n <div *ngIf=\"_model.rowLabels?.length\" class=\"row no-gutters\">\n <div *ngFor=\"let label of _model.rowLabels\"\n class=\"col align-items-center no-gutters dl-abdtp-col-label\">{{label}}</div>\n </div>\n <div *ngFor=\"let row of _model.rows\" class=\"row align-items-center no-gutters\">\n <div *ngFor=\"let cell of row.cells\"\n role=\"gridcell\"\n class=\"col dl-abdtp-date-button dl-abdtp-{{_model.viewName}}\"\n [ngClass]=\"cell.classes\"\n [attr.aria-label]=\"cell.ariaLabel\"\n [attr.aria-disabled]=\"cell.classes['dl-abdtp-disabled']\"\n [attr.dl-abdtp-value]=\"cell.value\"\n [attr.tabindex]=\"cell.classes['dl-abdtp-active'] ? 0 : -1\"\n (click)=\"_onDateClick(cell)\"\n (keydown.space)=\"_onDateClick(cell)\"\n (keydown.enter)=\"_onDateClick(cell)\"\n >{{cell.display}}</div>\n </div>\n </div>\n</div>\n\n<ng-template #maxViewLabel>\n <div class=\"col-10 dl-abdtp-view-label\">{{_model.viewLabel}}</div>\n</ng-template>\n<ng-template #defaultViewLabel>\n <button class=\"col-10 dl-abdtp-view-label dl-abdtp-up-button\"\n type=\"button\"\n [attr.aria-label]=\"_model.upButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.upButton.value\"\n [attr.title]=\"_model.upButton.ariaLabel\"\n (click)=\"_onUpClick()\"\n [ngClass]=\"_model.upButton.classes\"\n >{{_model.viewLabel}} <span class=\"up-icon\" [ngClass]=\"upIconClass\"></span>\n </button>\n</ng-template>\n",
styles: [":host{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dl-abdtp-col-label,.dl-abdtp-view-label{font-weight:700}.dl-abdtp-date-button,.dl-abdtp-left-button,.dl-abdtp-right-button,.dl-abdtp-view-label{padding:5px;border-radius:999px;cursor:pointer;color:rgba(0,0,0,.87);outline:0}.dl-abdtp-date-button,.dl-abdtp-left-button,.dl-abdtp-right-button,.dl-abdtp-up-button{border-width:0}.dl-abdtp-active:focus,.dl-abdtp-date-button:focus,.dl-abdtp-date-button:hover,.dl-abdtp-left-button:focus,.dl-abdtp-left-button:hover,.dl-abdtp-right-button:focus,.dl-abdtp-right-button:hover,.dl-abdtp-up-button:focus,.dl-abdtp-up-button:hover,.dl-abdtp-view-label:focus{background:rgba(0,0,0,.04)}.dl-abdtp-future,.dl-abdtp-past{color:rgba(0,0,0,.04)}.dl-abdtp-now,.dl-abdtp-now.disabled,.dl-abdtp-now.disabled:hover,.dl-abdtp-now:hover{border-radius:999px;border:1px solid rgba(0,0,0,.25)}.dl-abdtp-selected{color:#fff;background:rgba(0,82,204,.75)}.dl-abdtp-selected:focus,.dl-abdtp-selected:hover{background:#0052cc}.dl-abdtp-disabled{cursor:default;color:rgba(0,0,0,.25)}"]
})
], DlDateTimePickerComponent);
return DlDateTimePickerComponent;
}());
export { DlDateTimePickerComponent };
/** @internal */
function hasValue(value) {
return (typeof value !== 'undefined') && (value !== null);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGwtZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9hbmd1bGFyLWJvb3RzdHJhcC1kYXRldGltZXBpY2tlci8iLCJzb3VyY2VzIjpbImRsLWRhdGUtdGltZS1waWNrZXIvZGwtZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRzs7QUFFSCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sYUFBYSxFQUNkLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBdUIsaUJBQWlCLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUN2RSxPQUFPLEtBQUssT0FBTyxNQUFNLFFBQVEsQ0FBQztBQUNsQyxPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQ2pELE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBSXBFLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBQzNELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBQzdELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQ2pFLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQy9ELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBRTdEOzs7Ozs7Ozs7Ozs7SUFZSTtBQUNKLElBQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQztBQUd2Qjs7Ozs7SUFLSTtBQUVKLElBQU0sNEJBQTRCLEdBQUc7SUFDbkMsV0FBVyxFQUFFLFFBQVE7SUFDckIsV0FBVyxFQUFFLFFBQVE7SUFDckIsWUFBWSxFQUFFLFNBQVM7SUFDdkIsU0FBUyxFQUFFLE1BQU07SUFDakIsTUFBTSxFQUFFLFFBQVE7SUFDaEIsS0FBSyxFQUFFLE9BQU87SUFDZCxNQUFNLEVBQUUsUUFBUTtJQUNoQixNQUFNLEVBQUUsUUFBUTtJQUNoQixVQUFVLEVBQUUsVUFBVTtJQUN0QixRQUFRLEVBQUUsUUFBUTtJQUNsQixPQUFPLEVBQUUsU0FBUztJQUNsQixJQUFJLEVBQUUsTUFBTTtJQUNaLEVBQUUsRUFBRSxRQUFRO0lBQ1osRUFBRSxFQUFFLFVBQVU7SUFDZCxFQUFFLEVBQUUsT0FBTztJQUNYLEVBQUUsRUFBRSxRQUFRO0lBQ1osRUFBRSxFQUFFLFFBQVE7SUFDWixFQUFFLEVBQUUsTUFBTTtJQUNWLEVBQUUsRUFBRSxTQUFTO0lBQ2IsRUFBRSxFQUFFLFFBQVE7Q0FDYixDQUFDO0FBR0Y7Ozs7Ozs7SUFPSTtBQUNKLElBQU0sS0FBSyxHQUFHO0lBQ1osUUFBUTtJQUNSLE1BQU07SUFDTixLQUFLO0lBQ0wsT0FBTztJQUNQLE1BQU07Q0FDUCxDQUFDO0FBRUY7O0dBRUc7QUFnQkg7SUFvSkU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FtQkc7SUFDSCxtQ0FBb0IsV0FBdUIsRUFDdkIsT0FBZSxFQUNmLFlBQThCO0lBQ3RDLGFBQWE7SUFDTCxrQkFBdUM7SUFDL0MsYUFBYTtJQUNMLG1CQUF5QztJQUNqRCxhQUFhO0lBQ0wsaUJBQXFDO0lBQzdDLGFBQWE7SUFDTCxrQkFBdUM7SUFDL0MsYUFBYTtJQUNMLG9CQUEyQztRQVozQyxnQkFBVyxHQUFYLFdBQVcsQ0FBWTtRQUN2QixZQUFPLEdBQVAsT0FBTyxDQUFRO1FBQ2YsaUJBQVksR0FBWixZQUFZLENBQWtCO1FBRTlCLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBcUI7UUFFdkMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFzQjtRQUV6QyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW9CO1FBRXJDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBcUI7UUFFdkMseUJBQW9CLEdBQXBCLG9CQUFvQixDQUF1QjtRQWxML0Q7Ozs7WUFJSTtRQUNJLGFBQVEsR0FBMkIsRUFBRSxDQUFDO1FBTzlDOzs7WUFHSTtRQUNJLGNBQVMsR0FBRztZQUNsQixNQUFNLEVBQUUsT0FBTztZQUNmLE9BQU8sRUFBRSxLQUFLO1lBQ2QsS0FBSyxFQUFFLE1BQU07WUFDYixNQUFNLEVBQUUsUUFBUTtTQUNqQixDQUFDO1FBQ0Y7OztZQUdJO1FBQ0ksa0JBQWEsR0FBRztZQUN0QixRQUFRLEVBQUUsTUFBTTtZQUNoQixNQUFNLEVBQUUsS0FBSztZQUNiLEtBQUssRUFBRSxPQUFPO1lBQ2QsT0FBTyxFQUFFLE1BQU07U0FDaEIsQ0FBQztRQUNGOzs7O1lBSUk7UUFDSSxhQUFRLEdBQW1CLEVBQUUsQ0FBQztRQWlCdEM7OztZQUdJO1FBRUssV0FBTSxHQUFHLElBQUksWUFBWSxFQUE2QixDQUFDO1FBQ2hFOzs7OztXQUtHO1FBRUgsa0JBQWEsR0FBeUM7WUFDcEQsSUFBSTtZQUNKLGlCQUFpQjtTQUNsQixDQUFDO1FBQ0Y7Ozs7V0FJRztRQUVILFlBQU8sR0FBaUQsTUFBTSxDQUFDO1FBQy9EOzs7Ozs7Ozs7OztXQVdHO1FBRUgsWUFBTyxHQUFpRCxRQUFRLENBQUM7UUFDakU7Ozs7V0FJRztRQUVILGVBQVUsR0FBRyxDQUFDLENBQUM7UUFDZjs7Ozs7V0FLRztRQUVILG1CQUFjLEdBQUc7WUFDZixJQUFJO1lBQ0osa0JBQWtCO1NBQ25CLENBQUM7UUFFRixvQ0FBb0M7UUFDcEM7O1dBRUc7UUFFSCxpQkFBWSxHQUEwRCxjQUFNLE9BQUEsSUFBSSxFQUFKLENBQUksQ0FBQTtRQVFoRjs7Ozs7O1dBTUc7UUFFSCxjQUFTLEdBQWlELEtBQUssQ0FBQztRQUVoRTs7Ozs7V0FLRztRQUVILGdCQUFXLEdBQUc7WUFDWixJQUFJO1lBQ0osZ0JBQWdCO1NBQ2pCLENBQUM7UUFvQ0EsSUFBSSxDQUFDLG9CQUFvQixHQUFHO1lBQzFCLElBQUksRUFBRSxrQkFBa0I7WUFDeEIsS0FBSyxFQUFFLG1CQUFtQjtZQUMxQixHQUFHLEVBQUUsaUJBQWlCO1lBQ3RCLElBQUksRUFBRSxrQkFBa0I7WUFDeEIsTUFBTSxFQUFFLG9CQUFvQjtTQUM3QixDQUFDO0lBQ0osQ0FBQztrQ0E3TFUseUJBQXlCO0lBcU1wQyxzQkFBWSw0Q0FBSztRQU5qQixtQ0FBbUM7UUFDbkM7Ozs7WUFJSTthQUNKLFVBQWtCLEtBQTRCO1lBQzVDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlDLENBQUM7OztPQUFBO0lBS0Qsc0JBQUksNENBQUs7UUFIVDs7WUFFSTthQUNKO1lBQ0UsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQ3JCLENBQUM7UUFFRDs7O1lBR0k7YUFDSixVQUFVLEtBQVE7WUFDaEIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLEtBQUssRUFBRTtnQkFDekIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7Z0JBQ3BCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3pHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFVBQUEsQ0FBQyxJQUFJLE9BQUEsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFSLENBQVEsQ0FBQyxDQUFDO2dCQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLHNCQUFzQixDQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7YUFDeEQ7UUFDSCxDQUFDOzs7T0FiQTtJQWtCRCxzQkFBSSw4Q0FBTztRQUhYOztZQUVJO2FBQ0o7WUFDRSxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2RCxDQUFDOzs7T0FBQTtJQUVEOzs7Ozs7Ozs7Ozs7O09BYUc7SUFDSyxxREFBaUIsR0FBekIsVUFBMEIsS0FBNEI7UUFBdEQsaUJBZ0JDO1FBZkMsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3JCLEtBQUssQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBQyxHQUFHO2dCQUM5QixHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxVQUFDLFVBQXNCO29CQUNuQyxJQUFNLFFBQVEsR0FBRyxDQUFDLEtBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDaEUsVUFBVSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLFFBQVEsQ0FBQztvQkFDbkQsSUFBSSxRQUFRLEVBQUU7d0JBQ1osVUFBVSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsR0FBRyxJQUFJLENBQUM7cUJBQzVDO29CQUNELE9BQU8sVUFBVSxDQUFDO2dCQUNwQixDQUFDLENBQUMsQ0FBQztnQkFDSCxPQUFPLEdBQUcsQ0FBQztZQUNiLENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7O1FBR0k7SUFDSSxtREFBZSxHQUF2QjtRQUFBLGlCQU1DO1FBTEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztZQUM3QixLQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO2dCQUMzRCxLQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMzRSxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7UUFHSTtJQUNJLGdEQUFZLEdBQXBCO1FBQ0UsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ3pCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3REO1FBQ0QsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQzVCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztTQUN2QjtRQUNELE9BQU8sTUFBTSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxnREFBWSxHQUFwQjtRQUNFLElBQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLFFBQVEsQ0FBQyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzdHLE9BQU8sS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFRDs7O1FBR0k7SUFDSSwyQ0FBTyxHQUFmO1FBQ0UsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBQyxTQUFTLElBQUssT0FBQSxTQUFTLEVBQUUsRUFBWCxDQUFXLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILCtDQUFXLEdBQVgsVUFBWSxPQUFzQjtRQUNoQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFDLFFBQXlCLElBQUssT0FBQSxRQUFRLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUEzQixDQUEyQixDQUFDLENBQUM7UUFFN0csSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsa0VBQWtFO1lBQ25GLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUM3RztJQUNILENBQUM7SUFFRDs7OztRQUlJO0lBQ0osNENBQVEsR0FBUjtRQUNFLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFHLENBQUM7SUFFRDs7Ozs7Ozs7OztRQVVJO0lBQ0osZ0RBQVksR0FBWixVQUFhLFVBQXNCO1FBQ2pDLElBQUksVUFBVSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFO1lBQzNDLE9BQU87U0FDUjtRQUVELElBQUksUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVwRCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxRQUFRLENBQUMsS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtZQUN2RCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xFLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1NBQzNCO1FBRUQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTFGLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRUQ7Ozs7Ozs7UUFPSTtJQUNKLGdEQUFZLEdBQVo7UUFDRSxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xILElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRUQ7Ozs7Ozs7UUFPSTtJQUNKLDhDQUFVLEdBQVY7UUFDRSxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0SSxDQUFDO0lBRUQ7Ozs7Ozs7UUFPSTtJQUNKLGlEQUFhLEdBQWI7UUFDRSxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25ILElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRUQ7Ozs7UUFJSTtJQUNKLGtEQUFjLEdBQWQsVUFBZSxNQUFxQjtRQUNsQyxJQUFNLFlBQVksR0FBRyw0QkFBNEIsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFOUQsSUFBSSxZQUFZLEVBQUU7WUFDaEIsSUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdEUsSUFBSSxDQUFDLEtBQUssR0FBRyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRS9FLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN2Qiw4REFBOEQ7WUFDOUQsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1NBQ3pCO0lBQ0gsQ0FBQztJQUVEOzs7UUFHSTtJQUNKLG9EQUFnQixHQUFoQixVQUFpQixFQUFzQjtRQUNyQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6QixDQUFDO0lBRUQ7OztRQUdJO0lBQ0oscURBQWlCLEdBQWpCLFVBQWtCLEVBQWM7UUFDOUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7UUFHSTtJQUNKLDhDQUFVLEdBQVYsVUFBVyxLQUFRO1FBQ2pCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLENBQUM7OztnQkEzUWdDLFVBQVU7Z0JBQ2QsTUFBTTtnQkFDRCxhQUFhO2dCQUVQLG1CQUFtQjtnQkFFbEIsb0JBQW9CO2dCQUV0QixrQkFBa0I7Z0JBRWpCLG1CQUFtQjtnQkFFakIscUJBQXFCOztJQXZIL0Q7UUFEQyxNQUFNLEVBQUU7NkRBQ3VEO0lBUWhFO1FBREMsS0FBSyxFQUFFO29FQUlOO0lBT0Y7UUFEQyxLQUFLLEVBQUU7OERBQ3VEO0lBYy9EO1FBREMsS0FBSyxFQUFFOzhEQUN5RDtJQU9qRTtRQURDLEtBQUssRUFBRTtpRUFDTztJQVFmO1FBREMsS0FBSyxFQUFFO3FFQUlOO0lBT0Y7UUFEQyxLQUFLLEVBQUU7bUVBQ3dFO0lBTWhGO1FBREMsS0FBSyxFQUFFO2dFQUNVO0lBVWxCO1FBREMsS0FBSyxFQUFFO2dFQUN3RDtJQVNoRTtRQURDLEtBQUssRUFBRTtrRUFJTjtJQWxKUyx5QkFBeUI7UUFkckMsU0FBUyxDQUFDO1lBQ1QsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07WUFDL0MsbUJBQW1CLEVBQUUsS0FBSztZQUMxQixTQUFTLEVBQUU7Z0JBQ1Q7b0JBQ0UsT0FBTyxFQUFFLGlCQUFpQjtvQkFDMUIsV0FBVyxFQUFFLDJCQUF5QjtvQkFDdEMsS0FBSyxFQUFFLElBQUk7aUJBQ1o7YUFDRjtZQUNELFFBQVEsRUFBRSxxQkFBcUI7WUFFL0IsNHBGQUFtRDs7U0FDcEQsQ0FBQztPQUNXLHlCQUF5QixDQXFickM7SUFBRCxnQ0FBQztDQUFBLEFBcmJELElBcWJDO1NBcmJZLHlCQUF5QjtBQXVidEMsZ0JBQWdCO0FBQ2hCLFNBQVMsUUFBUSxDQUFDLEtBQVU7SUFDMUIsT0FBTyxDQUFDLE9BQU8sS0FBSyxLQUFLLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDO0FBQzVELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxMy1wcmVzZW50IERhbGUgTG90dHMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIGh0dHA6Ly93d3cuZGFsZWxvdHRzLmNvbVxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9kYWxlbG90dHMvYW5ndWxhci1ib290c3RyYXAtZGF0ZXRpbWVwaWNrZXIvYmxvYi9tYXN0ZXIvTElDRU5TRVxuICovXG5cbmltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlc1xufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1J9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCAqIGFzIF9tb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7dGFrZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtEbERhdGVBZGFwdGVyfSBmcm9tICcuLi9jb3JlL3B1YmxpYy1hcGknO1xuaW1wb3J0IHtEbERhdGVUaW1lUGlja2VyQ2hhbmdlfSBmcm9tICcuL2RsLWRhdGUtdGltZS1waWNrZXItY2hhbmdlJztcbmltcG9ydCB7RGF0ZUJ1dHRvbn0gZnJvbSAnLi9kbC1kYXRlLXRpbWUtcGlja2VyLWRhdGUtYnV0dG9uJztcbmltcG9ydCB7RGxEYXRlVGltZVBpY2tlck1vZGVsfSBmcm9tICcuL2RsLWRhdGUtdGltZS1waWNrZXItbW9kZWwnO1xuaW1wb3J0IHtEbE1vZGVsUHJvdmlkZXJ9IGZyb20gJy4vZGwtbW9kZWwtcHJvdmlkZXInO1xuaW1wb3J0IHtEbERheU1vZGVsUHJvdmlkZXJ9IGZyb20gJy4vZGwtbW9kZWwtcHJvdmlkZXItZGF5JztcbmltcG9ydCB7RGxIb3VyTW9kZWxQcm92aWRlcn0gZnJvbSAnLi9kbC1tb2RlbC1wcm92aWRlci1ob3VyJztcbmltcG9ydCB7RGxNaW51dGVNb2RlbFByb3ZpZGVyfSBmcm9tICcuL2RsLW1vZGVsLXByb3ZpZGVyLW1pbnV0ZSc7XG5pbXBvcnQge0RsTW9udGhNb2RlbFByb3ZpZGVyfSBmcm9tICcuL2RsLW1vZGVsLXByb3ZpZGVyLW1vbnRoJztcbmltcG9ydCB7RGxZZWFyTW9kZWxQcm92aWRlcn0gZnJvbSAnLi9kbC1tb2RlbC1wcm92aWRlci15ZWFyJztcblxuLyoqXG4gKiBXb3JrIGFyb3VuZCBmb3IgbW9tZW50IG5hbWVzcGFjZSBjb25mbGljdCB3aGVuIHVzZWQgd2l0aCB3ZWJwYWNrIGFuZCByb2xsdXAuXG4gKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2RoZXJnZXMvbmctcGFja2Fnci9pc3N1ZXMvMTYzXG4gKlxuICogRGVwZW5kaW5nIG9uIHdoZXRoZXIgcm9sbHVwIGlzIHVzZWQsIG1vbWVudCBuZWVkcyB0byBiZSBpbXBvcnRlZCBkaWZmZXJlbnRseS5cbiAqIFNpbmNlIE1vbWVudC5qcyBkb2Vzbid0IGhhdmUgYSBkZWZhdWx0IGV4cG9ydCwgd2Ugbm9ybWFsbHkgbmVlZCB0byBpbXBvcnQgdXNpbmdcbiAqIHRoZSBgKiBhc2BzeW50YXguXG4gKlxuICogcm9sbHVwIGNyZWF0ZXMgYSBzeW50aGV0aWMgZGVmYXVsdCBtb2R1bGUgYW5kIHdlIHRodXMgbmVlZCB0byBpbXBvcnQgaXQgdXNpbmdcbiAqIHRoZSBgZGVmYXVsdCBhc2Agc3ludGF4LlxuICpcbiAqIEBpbnRlcm5hbFxuICoqL1xuY29uc3QgbW9tZW50ID0gX21vbWVudDtcblxuXG4vKipcbiAqIE1hcHMga2V5IGNvZGVzIHRvIHRoZSBtb2RlbCBwcm92aWRlciBmdW5jdGlvbiBuYW1lXG4gKiB0aGF0IHNob3VsZCBiZSBjYWxsZWQgdG8gcGVyZm9ybSB0aGUgYWN0aW9uLlxuICpcbiAqIEBpbnRlcm5hbFxuICoqL1xuXG5jb25zdCBrZXlDb2RlVG9Nb2RlbFByb3ZpZGVyTWV0aG9kID0ge1xuICAnQXJyb3dEb3duJzogJ2dvRG93bicsXG4gICdBcnJvd0xlZnQnOiAnZ29MZWZ0JyxcbiAgJ0Fycm93UmlnaHQnOiAnZ29SaWdodCcsXG4gICdBcnJvd1VwJzogJ2dvVXAnLFxuICAnRG93bic6ICdnb0Rvd24nLFxuICAnRW5kJzogJ2dvRW5kJyxcbiAgJ0hvbWUnOiAnZ29Ib21lJyxcbiAgJ0xlZnQnOiAnZ29MZWZ0JyxcbiAgJ1BhZ2VEb3duJzogJ3BhZ2VEb3duJyxcbiAgJ1BhZ2VVcCc6ICdwYWdlVXAnLFxuICAnUmlnaHQnOiAnZ29SaWdodCcsXG4gICdVcCc6ICdnb1VwJyxcbiAgMzM6ICdwYWdlVXAnLFxuICAzNDogJ3BhZ2VEb3duJyxcbiAgMzU6ICdnb0VuZCcsXG4gIDM2OiAnZ29Ib21lJyxcbiAgMzc6ICdnb0xlZnQnLFxuICAzODogJ2dvVXAnLFxuICAzOTogJ2dvUmlnaHQnLFxuICA0MDogJ2dvRG93bicsXG59O1xuXG5cbi8qKlxuICogTGlzdCBvZiB2aWV3IG5hbWVzIGZvciB0aGUgY2FsZW5kYXIuXG4gKlxuICogVGhpcyBsaXN0IG11c3QgYmUgaW4gb3JkZXIgZnJvbVxuICogc21hbGxlc3QgaW5jcmVtZW50IG9mIHRpbWUgdG8gbGFyZ2VzdCBpbmNyZW1lbnQgb2YgdGltZS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqKi9cbmNvbnN0IFZJRVdTID0gW1xuICAnbWludXRlJyxcbiAgJ2hvdXInLFxuICAnZGF5JyxcbiAgJ21vbnRoJyxcbiAgJ3llYXInXG5dO1xuXG4vKipcbiAqIENvbXBvbmVudCB0aGF0IHByb3ZpZGVzIGFsbCBvZiB0aGUgdXNlciBmYWNpbmcgZnVuY3Rpb25hbGl0eSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlci5cbiAqL1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByZXNlcnZlV2hpdGVzcGFjZXM6IGZhbHNlLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBEbERhdGVUaW1lUGlja2VyQ29tcG9uZW50LFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9XG4gIF0sXG4gIHNlbGVjdG9yOiAnZGwtZGF0ZS10aW1lLXBpY2tlcicsXG4gIHN0eWxlVXJsczogWycuL2RsLWRhdGUtdGltZS1waWNrZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2RsLWRhdGUtdGltZS1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxufSlcbmV4cG9ydCBjbGFzcyBEbERhdGVUaW1lUGlja2VyQ29tcG9uZW50PEQ+IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcblxuICAvKipcbiAgICogQ2hhbmdlIGxpc3RlbmVyIGNhbGxiYWNrIGZ1bmN0aW9ucyByZWdpc3RlcmVkXG4gICAqIHZpYSBgcmVnaXN0ZXJPbkNoYW5nZWBcbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfY2hhbmdlZDogKCh2YWx1ZTogRCkgPT4gdm9pZClbXSA9IFtdO1xuICAvKipcbiAgICogTW9kZWwgZm9yIHRoZSBjdXJyZW50IHZpZXcuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIF9tb2RlbDogRGxEYXRlVGltZVBpY2tlck1vZGVsO1xuICAvKipcbiAgICogTWFwcyB2aWV3IG5hbWUgdG8gdGhlIG5leHQgdmlldyAodGhlIHZpZXcgZm9yIHRoZSBuZXh0IHNtYWxsZXN0IGluY3JlbWVudCBvZiB0aW1lKS5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfbmV4dFZpZXcgPSB7XG4gICAgJ3llYXInOiAnbW9udGgnLFxuICAgICdtb250aCc6ICdkYXknLFxuICAgICdkYXknOiAnaG91cicsXG4gICAgJ2hvdXInOiAnbWludXRlJ1xuICB9O1xuICAvKipcbiAgICogTWFwcyB2aWV3IG5hbWUgdG8gdGhlIHByZXZpb3VzIHZpZXcgKHRoZSB2aWV3IGZvciB0aGUgbmV4dCBsYXJnZXN0IGluY3JlbWVudCBvZiB0aW1lKS5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfcHJldmlvdXNWaWV3ID0ge1xuICAgICdtaW51dGUnOiAnaG91cicsXG4gICAgJ2hvdXInOiAnZGF5JyxcbiAgICAnZGF5JzogJ21vbnRoJyxcbiAgICAnbW9udGgnOiAneWVhcidcbiAgfTtcbiAgLyoqXG4gICAqIFRvdWNoIGxpc3RlbmVyIGNhbGxiYWNrIGZ1bmN0aW9ucyByZWdpc3RlcmVkXG4gICAqIHZpYSBgcmVnaXN0ZXJPbkNoYW5nZWBcbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfdG91Y2hlZDogKCgpID0+IHZvaWQpW10gPSBbXTtcbiAgLyoqXG4gICAqIFN0b3JlcyB0aGUgc2VsZWN0ZWQgdmFsdWUgZm9yIHRoaXMgcGlja2VyLlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBwcml2YXRlIF92YWx1ZTogRDtcbiAgLyoqXG4gICAqIE1hcHMgdmlldyBuYW1lIHRvIHRoZSBtb2RlbCBwcm92aWRlciBmb3IgdGhhdCB2aWV3LlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBwcml2YXRlIHJlYWRvbmx5IF92aWV3VG9Nb2RlbFByb3ZpZGVyOiB7XG4gICAgeWVhcjogRGxNb2RlbFByb3ZpZGVyO1xuICAgIG1vbnRoOiBEbE1vZGVsUHJvdmlkZXI7XG4gICAgZGF5OiBEbE1vZGVsUHJvdmlkZXI7XG4gICAgaG91cjogRGxNb2RlbFByb3ZpZGVyO1xuICAgIG1pbnV0ZTogRGxNb2RlbFByb3ZpZGVyO1xuICB9O1xuICAvKipcbiAgICogRW1pdHMgd2hlbiBhIGBjaGFuZ2VgIGV2ZW50IHdoZW4gZGF0ZS90aW1lIGlzIHNlbGVjdGVkIG9yXG4gICAqIHRoZSB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlciBjaGFuZ2VzLlxuICAgKiovXG4gIEBPdXRwdXQoKVxuICByZWFkb25seSBjaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPERsRGF0ZVRpbWVQaWNrZXJDaGFuZ2U8RD4+KCk7XG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIGNsYXNzZXMgdXNlZCB0byBkaXNwbGF5IHRoZSBsZWZ0IGljb24uXG4gICAqXG4gICAqIFRoaXMgY29tcG9uZW50IHVzZXMgT1BFTklDT05JQyBodHRwczovL3VzZWljb25pYy5jb20vb3BlblxuICAgKiBieSBkZWZhdWx0IGJ1dCBhbnkgaWNvbiBsaWJyYXJ5IG1heSBiZSB1c2VkLlxuICAgKi9cbiAgQElucHV0KClcbiAgbGVmdEljb25DbGFzczogc3RyaW5nIHwgc3RyaW5nW10gfCBTZXQ8c3RyaW5nPiB8IHt9ID0gW1xuICAgICdvaScsXG4gICAgJ29pLWNoZXZyb24tbGVmdCdcbiAgXTtcbiAgLyoqXG4gICAqIFRoZSBoaWdoZXN0IHZpZXcgdGhhdCB0aGUgZGF0ZS90aW1lIHBpY2tlciBjYW4gc2hvdy5cbiAgICogU2V0dGluZyB0aGlzIHRvIGEgdmlldyBsZXNzIHRoYW4geWVhciBjb3VsZCBtYWtlIGl0IG1vcmVcbiAgICogZGlmZmljdWx0IGZvciB0aGUgZW5kLXVzZXIgdG8gbmF2aWdhdGUgdG8gY2VydGFpbiBkYXRlcy5cbiAgICovXG4gIEBJbnB1dCgpXG4gIG1heFZpZXc6ICd5ZWFyJyB8ICdtb250aCcgfCAnZGF5JyB8ICdob3VyJyB8ICdtaW51dGUnID0gJ3llYXInO1xuICAvKipcbiAgICogVGhlIHZpZXcgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIGRhdGUvdGltZSBzZWxlY3Rpb24uXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IG9mIGBtaW51dGUgIG1lYW5zIHRoYXQgc2VsZWN0aW9uIHdpbGwgbm90IGhhcHBlblxuICAgKiB1bnRpbCB0aGUgZW5kLXVzZXIgY2xpY2tzIG9uIGEgY2VsbCBpbiB0aGUgbWludXRlIHZpZXcuXG4gICAqXG4gICAqIGZvciBleGFtcGxlLCBpZiB5b3Ugd2FudCB0aGUgZW5kLXVzZXIgdG8gc2VsZWN0IGEgb25seSBkYXkgKGRhdGUpLFxuICAgKiBzZXR0aW5nIGBtaW5WaWV3YCB0byBgZGF5YCB3aWxsIGNhdXNlIHNlbGVjdGlvbiB0byBoYXBwZW4gd2hlbiB0aGVcbiAgICogZW5kLXVzZXIgc2VsZWN0cyBhIGNlbGwgaW4gdGhlIGRheSB2aWV3LlxuICAgKlxuICAgKiBOT1RFOiBUaGlzIG11c3QgYmUgc2V0IGxvd2VyIHRoYW4gb3IgZXF1YWwgdG8gYHN0YXJ0VmlldydcbiAgICovXG4gIEBJbnB1dCgpXG4gIG1pblZpZXc6ICd5ZWFyJyB8ICdtb250aCcgfCAnZGF5JyB8ICdob3VyJyB8ICdtaW51dGUnID0gJ21pbnV0ZSc7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIG1pbnV0ZXMgYmV0d2VlbiBlYWNoIGAuZGwtYWJkdHAtbWludXRlYCBidXR0b24uXG4gICAqXG4gICAqIE11c3QgYmUgZ3JlYXRlciB0aGFuIGAwYCBhbmQgbGVzcyB0aGFuIGA2MGAuXG4gICAqL1xuICBASW5wdXQoKVxuICBtaW51dGVTdGVwID0gNTtcbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgY2xhc3NlcyB1c2VkIHRvIGRpc3BsYXkgdGhlIHJpZ2h0IGljb24uXG4gICAqXG4gICAqIFRoaXMgY29tcG9uZW50IHVzZXMgT1BFTklDT05JQyBodHRwczovL3VzZWljb25pYy5jb20vb3BlblxuICAgKiBieSBkZWZhdWx0IGJ1dCBhbnkgaWNvbiBsaWJyYXJ5IG1heSBiZSB1c2VkLlxuICAgKi9cbiAgQElucHV0KClcbiAgcmlnaHRJY29uQ2xhc3MgPSBbXG4gICAgJ29pJyxcbiAgICAnb2ktY2hldnJvbi1yaWdodCdcbiAgXTtcblxuICAvKiB0c2xpbnQ6ZGlzYWJsZTptZW1iZXItb3JkZXJpbmcgKi9cbiAgLyoqXG4gICAqICBEZXRlcm1pbmUgd2hldGhlciBvciBub3QgdGhlIGBEYXRlQnV0dG9uYCBpcyBzZWxlY3RhYmxlIGJ5IHRoZSBlbmQgdXNlci5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHNlbGVjdEZpbHRlcjogKGRhdGVCdXR0b246IERhdGVCdXR0b24sIHZpZXdOYW1lOiBzdHJpbmcpID0+IGJvb2xlYW4gPSAoKSA9PiB0cnVlXG5cbiAgLyoqXG4gICAqICBTdGFydCBhdCB0aGUgdmlldyBjb250YWluaW5nIHN0YXJ0RGF0ZSB3aGVuIG5vIHZhbHVlIGlzIHNlbGVjdGVkLlxuICAgKi9cbiAgQElucHV0KClcbiAgc3RhcnREYXRlOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBpbml0aWFsIHZpZXcgdGhhdCB0aGUgZGF0ZS90aW1lIHBpY2tlciB3aWxsIHNob3cuXG4gICAqIFRoZSBwaWNrZXIgd2lsbCBhbHNvIHJldHVybiB0byB0aGlzIHZpZXcgYWZ0ZXIgYSBkYXRlL3RpbWVcbiAgICogaXMgc2VsZWN0ZWQuXG4gICAqXG4gICAqIE5PVEU6IFRoaXMgbXVzdCBiZSBzZXQgbG93ZXIgdGhhbiBvciBlcXVhbCB0byBgbWF4VmlldydcbiAgICovXG4gIEBJbnB1dCgpXG4gIHN0YXJ0VmlldzogJ3llYXInIHwgJ21vbnRoJyB8ICdkYXknIHwgJ2hvdXInIHwgJ21pbnV0ZScgPSAnZGF5JztcblxuICAvKipcbiAgICogU3BlY2lmaWVzIHRoZSBjbGFzc2VzIHVzZWQgdG8gZGlzcGxheSB0aGUgdXAgaWNvbi5cbiAgICpcbiAgICogVGhpcyBjb21wb25lbnQgdXNlcyBPUEVOSUNPTklDIGh0dHBzOi8vdXNlaWNvbmljLmNvbS9vcGVuXG4gICAqIGJ5IGRlZmF1bHQgYnV0IGFueSBpY29uIGxpYnJhcnkgbWF5IGJlIHVzZWQuXG4gICAqL1xuICBASW5wdXQoKVxuICB1cEljb25DbGFzcyA9IFtcbiAgICAnb2knLFxuICAgICdvaS1jaGV2cm9uLXRvcCdcbiAgXTtcblxuICAvKipcbiAgICogVXNlZCB0byBjb25zdHJ1Y3QgYSBuZXcgaW5zdGFuY2Ugb2YgYSBkYXRlL3RpbWUgcGlja2VyLlxuICAgKlxuICAgKiBAcGFyYW0gX2VsZW1lbnRSZWZcbiAgICogIHJlZmVyZW5jZSB0byB0aGlzIGVsZW1lbnQuXG4gICAqIEBwYXJhbSBfbmdab25lXG4gICAqICByZWZlcmVuY2UgdG8gYW4gTmdab25lIGluc3RhbmNlIHVzZWQgdG8gc2VsZWN0IHRoZSBhY3RpdmUgZWxlbWVudCBvdXRzaWRlIG9mIGFuZ3VsYXIuXG4gICAqIEBwYXJhbSBfZGF0ZUFkYXB0ZXJcbiAgICogIGRhdGUgYWRhcHRlciBmb3IgdGhlIGRhdGUgdHlwZSBpbiB0aGUgbW9kZWwuXG4gICAqIEBwYXJhbSB5ZWFyTW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgeWVhciB2aWV3IG1vZGVsLlxuICAgKiBAcGFyYW0gbW9udGhNb2RlbENvbXBvbmVudFxuICAgKiAgcHJvdmlkZXIgZm9yIHRoZSBtb250aCB2aWV3IG1vZGVsLlxuICAgKiBAcGFyYW0gZGF5TW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgZGF5IHZpZXcgbW9kZWwuXG4gICAqIEBwYXJhbSBob3VyTW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgaG91ciB2aWV3IG1vZGVsLlxuICAgKiBAcGFyYW0gbWludXRlTW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgbWludXRlIHZpZXcgbW9kZWwuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9lbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICAgICAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfZGF0ZUFkYXB0ZXI6IERsRGF0ZUFkYXB0ZXI8RD4sXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSB5ZWFyTW9kZWxDb21wb25lbnQ6IERsWWVhck1vZGVsUHJvdmlkZXIsXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSBtb250aE1vZGVsQ29tcG9uZW50OiBEbE1vbnRoTW9kZWxQcm92aWRlcixcbiAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICBwcml2YXRlIGRheU1vZGVsQ29tcG9uZW50OiBEbERheU1vZGVsUHJvdmlkZXIsXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSBob3VyTW9kZWxDb21wb25lbnQ6IERsSG91ck1vZGVsUHJvdmlkZXIsXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSBtaW51dGVNb2RlbENvbXBvbmVudDogRGxNaW51dGVNb2RlbFByb3ZpZGVyKSB7XG5cbiAgICB0aGlzLl92aWV3VG9Nb2RlbFByb3ZpZGVyID0ge1xuICAgICAgeWVhcjogeWVhck1vZGVsQ29tcG9uZW50LFxuICAgICAgbW9udGg6IG1vbnRoTW9kZWxDb21wb25lbnQsXG4gICAgICBkYXk6IGRheU1vZGVsQ29tcG9uZW50LFxuICAgICAgaG91cjogaG91ck1vZGVsQ29tcG9uZW50LFxuICAgICAgbWludXRlOiBtaW51dGVNb2RlbENvbXBvbmVudCxcbiAgICB9O1xuICB9XG5cbiAgLyogdHNsaW50OmVuYWJsZTptZW1iZXItb3JkZXJpbmcgKi9cbiAgLyoqXG4gICAqIFNldCdzIHRoZSBtb2RlbCBmb3IgdGhlIGN1cnJlbnQgdmlldyBhZnRlciBhcHBseWluZyB0aGUgc2VsZWN0aW9uIGZpbHRlci5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBzZXQgbW9kZWwobW9kZWw6IERsRGF0ZVRpbWVQaWNrZXJNb2RlbCkge1xuICAgIHRoaXMuX21vZGVsID0gdGhpcy5hcHBseVNlbGVjdEZpbHRlcihtb2RlbCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBgRGAgdmFsdWUgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIgb3IgdW5kZWZpbmVkL251bGwgaWYgbm8gdmFsdWUgaXMgc2V0LlxuICAgKiovXG4gIGdldCB2YWx1ZSgpOiBEIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlciBhbmQgZW1pdHMgYSBjaGFuZ2UgZXZlbnQgaWYgdGhlXG4gICAqIG5ldyB2YWx1ZSBpcyBkaWZmZXJlbnQgZnJvbSB0aGUgcHJldmlvdXMgdmFsdWUuXG4gICAqKi9cbiAgc2V0IHZhbHVlKHZhbHVlOiBEKSB7XG4gICAgaWYgKHRoaXMuX3ZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcbiAgICAgIHRoaXMubW9kZWwgPSB0aGlzLl92aWV3VG9Nb2RlbFByb3ZpZGVyW3RoaXMuX21vZGVsLnZpZXdOYW1lXS5nZXRNb2RlbCh0aGlzLmdldFN0YXJ0RGF0ZSgpLCB0aGlzLnZhbHVlT2YpO1xuICAgICAgdGhpcy5fY2hhbmdlZC5mb3JFYWNoKGYgPT4gZih2YWx1ZSkpO1xuICAgICAgdGhpcy5jaGFuZ2UuZW1pdChuZXcgRGxEYXRlVGltZVBpY2tlckNoYW5nZTxEPih2YWx1ZSkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGBtaWxsaXNlY29uZHNgIHZhbHVlIG9mIHRoZSBkYXRlL3RpbWUgcGlja2VyIG9yIHVuZGVmaW5lZC9udWxsIGlmIG5vIHZhbHVlIGlzIHNldC5cbiAgICoqL1xuICBnZXQgdmFsdWVPZigpOiBudW1iZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0ZUFkYXB0ZXIudG9NaWxsaXNlY29uZHModGhpcy5fdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgdGhlIGBzZWxlY3Rpb25GaWx0ZXJgIGJ5IGFkZGluZyB0aGUgYGRsLWFiZHRwLWRpc2FibGVkYFxuICAgKiBjbGFzcyB0byBhbnkgYERhdGVCdXR0b25gIHdoZXJlIGBzZWxlY3RGaWx0ZXJgIHJldHVybmVkIGZhbHNlLlxuICAgKlxuICAgKiBAcGFyYW0gbW9kZWxcbiAgICogIHRoZSBuZXcgbW9kZWxcbiAgICpcbiAgICogQHJldHVybnNcbiAgICogIHRoZSBzdXBwbGllZCBtb2RlbCB3aXRoIHplcm8gb3IgbW9yZSBgRGF0ZUJ1dHRvbmAnc1xuICAgKiAgaGF2aW5nIHRoZSBgZGwtYWJkdHAtZGlzYWJsZWRgIGNsYXNzIHNldCB0byBgdHJ1ZWAgaWYgdGhlXG4gICAqICBzZWxlY3Rpb24gZm9yIHRoYXQgZGF0ZSBzaG91bGQgYmUgZGlzYWJsZWQuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseVNlbGVjdEZpbHRlcihtb2RlbDogRGxEYXRlVGltZVBpY2tlck1vZGVsKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICBpZiAodGhpcy5zZWxlY3RGaWx0ZXIpIHtcbiAgICAgIG1vZGVsLnJvd3MgPSBtb2RlbC5yb3dzLm1hcCgocm93KSA9PiB7XG4gICAgICAgIHJvdy5jZWxscy5tYXAoKGRhdGVCdXR0b246IERhdGVCdXR0b24pID0+IHtcbiAgICAgICAgICBjb25zdCBkaXNhYmxlZCA9ICF0aGlzLnNlbGVjdEZpbHRlcihkYXRlQnV0dG9uLCBtb2RlbC52aWV3TmFtZSk7XG4gICAgICAgICAgZGF0ZUJ1dHRvbi5jbGFzc2VzWydkbC1hYmR0cC1kaXNhYmxlZCddID0gZGlzYWJsZWQ7XG4gICAgICAgICAgaWYgKGRpc2FibGVkKSB7XG4gICAgICAgICAgICBkYXRlQnV0dG9uLmNsYXNzZXNbJ2FyaWEtZGlzYWJsZWQnXSA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBkYXRlQnV0dG9uO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb2N1c2VzIHRoZSBgLmRsLWFiZHRwLWFjdGl2ZWAgY2VsbCBhZnRlciB0aGUgbWljcm90YXNrIHF1ZXVlIGlzIGVtcHR5LlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBwcml2YXRlIGZvY3VzQWN0aXZlQ2VsbCgpIHtcbiAgICB0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgdGhpcy5fbmdab25lLm9uU3RhYmxlLmFzT2JzZXJ2YWJsZSgpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5kbC1hYmR0cC1hY3RpdmUnKS5mb2N1cygpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgc3RhcnQgZGF0ZSBmb3IgdGhlIHBpY2tlci5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBnZXRTdGFydERhdGUoKSB7XG4gICAgaWYgKGhhc1ZhbHVlKHRoaXMuX3ZhbHVlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2RhdGVBZGFwdGVyLnRvTWlsbGlzZWNvbmRzKHRoaXMuX3ZhbHVlKTtcbiAgICB9XG4gICAgaWYgKGhhc1ZhbHVlKHRoaXMuc3RhcnREYXRlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuc3RhcnREYXRlO1xuICAgIH1cbiAgICByZXR1cm4gbW9tZW50KCkudmFsdWVPZigpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZSB0aGUgc3RhcnQgdmlldyBmb3IgdGhlIHBpY2tlclxuICAgKiBAcmV0dXJuc1xuICAgKiAgdGhlIGxhcmdlc3QgdGltZSBpbmNyZW1lbnQgdmlldyBiZXR3ZWVuIHRoZSBgbWluVmlld2Agb3IgYG1pbnV0ZWAgdmlldyBhbmQgdGhlIGBzdGFydFZpZXdgIG9yIGBkYXlgIHZpZXcuXG4gICAqL1xuICBwcml2YXRlIGdldFN0YXJ0VmlldygpOiBzdHJpbmcge1xuICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBNYXRoLm1heChWSUVXUy5pbmRleE9mKHRoaXMubWluVmlldyB8fCAnbWludXRlJyksIFZJRVdTLmluZGV4T2YodGhpcy5zdGFydFZpZXcgfHwgJ2RheScpKTtcbiAgICByZXR1cm4gVklFV1Nbc3RhcnRJbmRleF07XG4gIH1cblxuICAvKipcbiAgICogQ2FsbHMgYWxsIHJlZ2lzdGVyZWQgYHRvdWNoYCBjYWxsYmFjayBmdW5