ngx-mat-shift-selection
Version:
This is a simple date and time selection component design specificly for job shifts etc, with 24-hours available option.
492 lines • 47.9 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: lib/ngx-mat-shift-selection.component.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import * as tslib_1 from "tslib";
import { Component, EventEmitter, Input, Output } from "@angular/core";
import * as _moment from 'moment';
/** @type {?} */
const moment = _moment;
import * as _ from "lodash";
export class NgxMatShiftSelectionComponent {
constructor() {
this.currentDate = moment();
this.dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
this.weeks = [];
this.sortedDates = [];
this.selectAll = false;
this.availableAll = false;
this.time = [
"00:00",
"00:30",
"01:00",
"01:30",
"02:00",
"02:30",
"03:00",
"03:30",
"04:00",
"04:30",
"05:00",
"05:30",
"06:00",
"06:30",
"07:00",
"07:30",
"08:00",
"08:30",
"09:00",
"09:30",
"10:00",
"10:30",
"11:00",
"11:30",
"12:00",
"12:30",
"13:00",
"13:30",
"14:00",
"14:30",
"15:00",
"15:30",
"16:00",
"16:30",
"17:00",
"17:30",
"18:00",
"18:30",
"19:00",
"19:30",
"20:00",
"20:30",
"21:00",
"21:30",
"22:00",
"22:30",
"23:00",
"23:30"
];
this.selectedDates = [];
this.calendarType = "month";
this.class = "";
this.onSelectDate = new EventEmitter();
}
/**
* @return {?}
*/
ngOnInit() {
this.generateCalendar();
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
if (changes.selectedDates &&
changes.selectedDates.currentValue &&
changes.selectedDates.currentValue.length > 1) {
// sort on date changes for better performance when range checking
this.sortedDates = _.sortBy(changes.selectedDates.currentValue, (/**
* @param {?} m
* @return {?}
*/
(m) => m.mDate.valueOf()));
this.generateCalendar();
}
}
/**
* @param {?} date
* @return {?}
*/
selectDate(date) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
date.selected = !date.selected;
date.isFullTime = false;
if (!date.selected) {
yield _.remove(this.selectedDates, (/**
* @param {?} v
* @return {?}
*/
v => {
return v.mDate.format("ll") == date.mDate.format("ll");
}));
}
else {
date.startTime = "";
date.endTime = "";
date.isTimerVisible =
this.weeks[0][1].mDate.week() == date.mDate.week() &&
!this.isPast(date.mDate);
if (!this.isDuplicate(date.mDate))
this.selectedDates.push(date);
}
this.sortedDates = yield _.sortBy(this.selectedDates, (/**
* @param {?} m
* @return {?}
*/
(m) => m.mDate.valueOf()));
this.selectAll = this.areAllSelected();
this.availableAll = this.areAllAvailable();
this.onSelectDate.emit(this.sortedDates);
});
}
// date checkers
/**
* @param {?} date
* @return {?}
*/
isToday(date) {
return moment().isSame(moment(date), "day");
}
/**
* @param {?} date
* @return {?}
*/
isSelected(date) {
return (_.findIndex(this.selectedDates, (/**
* @param {?} selectedDate
* @return {?}
*/
selectedDate => {
return moment(date).isSame(selectedDate.mDate, "day");
})) > -1);
}
/**
* @param {?} date
* @return {?}
*/
isDuplicate(date) {
return (_.findIndex(this.selectedDates, (/**
* @param {?} selectedDate
* @return {?}
*/
selectedDate => {
return moment(date).isSame(selectedDate.mDate, "day");
})) > -1);
}
/**
* @return {?}
*/
areAllSelected() {
for (let v of this.weeks[0]) {
if (!v.selected && !this.isPast(v.mDate))
return false;
}
return true;
}
/**
* @return {?}
*/
areAllAvailable() {
for (let v of this.sortedDates) {
if (!v.isFullTime && v.isTimerVisible)
return false;
}
for (let v of this.weeks[0]) {
if (!v.selected)
return false;
}
return true;
}
/**
* @param {?} date
* @return {?}
*/
isFullTime(date) {
return (_.findIndex(this.selectedDates, (/**
* @param {?} selectedDate
* @return {?}
*/
selectedDate => {
return (moment(date).isSame(selectedDate.mDate, "day") &&
selectedDate.isFullTime);
})) > -1);
}
/**
* @param {?} date
* @return {?}
*/
isSelectedMonth(date) {
return moment(date).isSame(this.currentDate, "month");
}
/**
* @param {?} date
* @return {?}
*/
isPast(date) {
return moment(date).isBefore(moment().subtract(1, "day"));
}
// actions from calendar
/**
* @return {?}
*/
prevMonth() {
this.currentDate = moment(this.currentDate).subtract(1, "months");
this.generateCalendar();
}
/**
* @return {?}
*/
nextMonth() {
this.currentDate = moment(this.currentDate).add(1, "months");
this.generateCalendar();
}
/**
* @return {?}
*/
nextWeek() {
this.currentDate = moment(this.currentDate).add(1, "week");
this.generateCalendar();
}
/**
* @return {?}
*/
prevWeek() {
this.currentDate = moment(this.currentDate).subtract(1, "week");
this.generateCalendar();
}
/**
* @return {?}
*/
firstMonth() {
this.currentDate = moment(this.currentDate).startOf("year");
this.generateCalendar();
}
/**
* @return {?}
*/
lastMonth() {
this.currentDate = moment(this.currentDate).endOf("year");
this.generateCalendar();
}
/**
* @return {?}
*/
prevYear() {
this.currentDate = moment(this.currentDate).subtract(1, "year");
this.generateCalendar();
}
/**
* @return {?}
*/
nextYear() {
this.currentDate = moment(this.currentDate).add(1, "year");
this.generateCalendar();
}
// generate the calendar grid
/**
* @return {?}
*/
generateCalendar() {
/** @type {?} */
const dates = this.fillDates(this.currentDate);
/** @type {?} */
const weeks = [];
while (dates.length > 0) {
weeks.push(dates.splice(0, 7));
}
for (let v of this.sortedDates) {
v.isTimerVisible =
weeks[0][1].mDate.week() == v.mDate.week() && !this.isPast(v.mDate);
}
this.weeks = weeks;
this.selectAll = this.areAllSelected();
this.availableAll = this.areAllAvailable();
}
/**
* @param {?} currentMoment
* @return {?}
*/
fillDates(currentMoment) {
if (this.calendarType == "week") {
/** @type {?} */
const firstOfWeek = moment(currentMoment)
.startOf("week")
.day();
/** @type {?} */
const firstDayOfGrid = moment(currentMoment)
.startOf("week")
.subtract(firstOfWeek, "days");
/** @type {?} */
const start = firstDayOfGrid.date();
return _.range(start, start + 7).map((/**
* @param {?} date
* @return {?}
*/
(date) => {
/** @type {?} */
const d = moment(firstDayOfGrid).date(date);
return {
today: this.isToday(d),
selected: this.isSelected(d),
mDate: d,
startTime: undefined,
endTime: undefined,
isTimerVisible: false,
isFullTime: this.isFullTime(d)
};
}));
}
/** @type {?} */
const firstOfMonth = moment(currentMoment)
.startOf("month")
.day();
/** @type {?} */
const firstDayOfGrid = moment(currentMoment)
.startOf("month")
.subtract(firstOfMonth, "days");
/** @type {?} */
const start = firstDayOfGrid.date();
return _.range(start, start + 35).map((/**
* @param {?} date
* @return {?}
*/
(date) => {
/** @type {?} */
const d = moment(firstDayOfGrid).date(date);
return {
today: this.isToday(d),
selected: this.isSelected(d),
mDate: d,
startTime: undefined,
endTime: undefined,
isTimerVisible: false,
isFullTime: this.isFullTime(d)
};
}));
}
/**
* @param {?} val
* @return {?}
*/
timeChanged(val) {
val.isFullTime =
val.startTime == "00:00" &&
val.endTime == "23:59" &&
this.weeks[0].map((/**
* @param {?} v
* @return {?}
*/
v => {
if (v.mDate.format("ll") == val.mDate.format("ll")) {
v.isFullTime = val.isFullTime;
}
}));
this.availableAll = this.areAllAvailable();
this.onSelectDate.emit(this.sortedDates);
}
/**
* @param {?} val
* @return {?}
*/
fullTimeChecked(val) {
val.startTime = val.isFullTime ? "00:00" : "";
val.endTime = val.isFullTime ? "23:59" : "";
for (let v in this.sortedDates) {
if (this.sortedDates[v].mDate.format("ll") == val.mDate.format("ll")) {
this.sortedDates[v].startTime = val.startTime;
this.sortedDates[v].endTime = val.endTime;
}
}
this.timeChanged(val);
}
/**
* @return {?}
*/
selectAllChecked() {
for (let v of this.weeks[0]) {
v.selected = this.selectAll;
this.selectDate(v);
}
}
/**
* @return {?}
*/
availableAllChecked() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
this.availableAll = !this.availableAll;
for (let v of this.sortedDates) {
v.isFullTime = v.isTimerVisible ? this.availableAll : v.isFullTime;
v.startTime = v.isFullTime ? "00:00" : "";
v.endTime = v.isFullTime ? "23:59" : "";
this.weeks[0].map((/**
* @param {?} val
* @return {?}
*/
val => {
if (val.mDate.format("ll") == v.mDate.format("ll")) {
val.isFullTime = v.isFullTime;
}
}));
}
this.onSelectDate.emit(this.sortedDates);
});
}
/**
* @return {?}
*/
timeSelected() {
this.onSelectDate.emit(this.sortedDates);
}
}
NgxMatShiftSelectionComponent.decorators = [
{ type: Component, args: [{
selector: "ngx-mat-shift-selection",
template: "<div fxLayout=\"column\" [ngClass]=\"class\" class=\"calendar\">\n <div fxLayout=\"column\" class=\"calendar-navs\" *ngIf=\"calendarType != 'week'\">\n <div class=\"month-nav\" fxLayout=\"row\" fxLayoutAlign=\"space-between center\">\n <button mat-icon-button (click)=\"prevMonth()\">\n <mat-icon>arrow_back_ios</mat-icon>\n </button>\n <span class=\"title p4 mt-1\">{{ currentDate.format(\"MMMM\") }}</span>\n <button mat-icon-button (click)=\"nextMonth()\">\n <mat-icon>arrow_forward_ios</mat-icon>\n </button>\n </div>\n <div class=\"year-nav\" fxLayout=\"row\" fxLayoutAlign=\"space-between center\">\n <button mat-icon-button (click)=\"prevYear()\">\n <mat-icon>arrow_back_ios</mat-icon>\n </button>\n <span class=\"mt-1\">{{ currentDate.format(\"YYYY\") }}</span>\n <button mat-icon-button (click)=\"nextYear()\">\n <mat-icon>arrow_forward_ios</mat-icon>\n </button>\n </div>\n </div>\n <div fxLayout=\"column\" class=\"calendar-navs\" *ngIf=\"calendarType == 'week'\">\n <div class=\"month-nav\" fxLayout=\"row\" fxLayoutAlign=\"space-between center\">\n <button mat-icon-button (click)=\"prevWeek()\">\n <mat-icon>arrow_back_ios</mat-icon>\n </button>\n <span class=\"title p4 mt-1\">{{ currentDate.format(\"MMMM YYYY\") }}</span>\n <button mat-icon-button (click)=\"nextWeek()\">\n <mat-icon>arrow_forward_ios</mat-icon>\n </button>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div fxLayout=\"column\" class=\"month-grid\">\n <div class=\"day-names\" fxLayout=\"row\" fxLayoutAlign=\"space-between center\">\n <div\n fxFlex=\"14\"\n *ngFor=\"let name of dayNames\"\n class=\"day-name p9\"\n style=\"text-align: center;\"\n >\n {{ name }}\n </div>\n </div>\n <div class=\"weeks\" fxLayout=\"column\">\n <div\n *ngFor=\"let week of weeks\"\n class=\"week\"\n style=\"text-align: center;\"\n fxLayout=\"row\"\n fxLayoutAlign=\"space-between center\"\n >\n <ng-container *ngFor=\"let day of week\">\n <div fxFlex=\"14\" class=\"week-date disabled\" *ngIf=\"isPast(day.mDate)\">\n <span class=\"date-text\">{{ day.mDate.date() }}</span>\n </div>\n <div\n fxFlex=\"14\"\n class=\"week-date enabled\"\n *ngIf=\"!isPast(day.mDate)\"\n (click)=\"selectDate(day)\"\n >\n <div\n fxLayout=\"row\"\n fxLayoutAlign=\"center center\"\n [ngClass]=\"{\n today: day.today,\n fullTimeSelected: day.isFullTime,\n selected: day.selected\n }\"\n >\n <span class=\"date-text\">{{ day.mDate.date() }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"row justify-content-between p-05\">\n <div class=\"col-12 mb-1\">\n Select All Days\n <mat-checkbox\n [checked]=\"selectAll\"\n (change)=\"selectAllChecked()\"\n ></mat-checkbox>\n </div>\n </div>\n <mat-divider></mat-divider>\n <ng-container *ngIf=\"sortedDates.length > 0\">\n <div class=\"p-05\" fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <div fxFlex=\"50\">Select Available Time</div>\n <div fxFlex=\"50\" class=\"text-right\">\n <mat-checkbox\n [checked]=\"availableAll\"\n (change)=\"availableAllChecked()\"\n >\n </mat-checkbox>\n Available 24 Hours\n </div>\n </div>\n <mat-divider></mat-divider>\n </ng-container>\n <div *ngFor=\"let availableDate of sortedDates\">\n <div class=\"mt-1\" *ngIf=\"availableDate.isTimerVisible\">\n <div fxLayout=\"row\" fxLayoutAlign=\"start center\" class=\"p-05\">\n <div fxFlex=\"50\">{{ availableDate.mDate.format(\"LL\") }}</div>\n <div fxFlex=\"50\" class=\"text-right\">\n <mat-checkbox\n [(ngModel)]=\"availableDate.isFullTime\"\n (ngModelChange)=\"fullTimeChecked(availableDate)\"\n aria-label=\"Checkbox for following text input\"\n >\n </mat-checkbox>\n Available 24 Hours\n </div>\n </div>\n <div\n fxLayout=\"row\"\n fxLayoutAlign=\"start center\"\n *ngIf=\"!availableDate.isFullTime\"\n class=\"p-05\"\n >\n <mat-form-field fxFlex=\"40\">\n <input\n type=\"text\"\n placeholder=\"Start Time\"\n aria-label=\"Number\"\n matInput\n [(ngModel)]=\"availableDate.startTime\"\n [matAutocomplete]=\"auto\"\n (ngModelChange)=\"timeSelected()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let option of time\" [value]=\"option\">\n {{ option }}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n <span class=\"text-center\" fxFlex=\"20\">to</span>\n <mat-form-field fxFlex=\"40\">\n <input\n type=\"text\"\n placeholder=\"End Time\"\n aria-label=\"Number\"\n matInput\n [(ngModel)]=\"availableDate.endTime\"\n [matAutocomplete]=\"auto\"\n (ngModelChange)=\"timeSelected()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let option of time\" [value]=\"option\">\n {{ option }}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n </div>\n <mat-divider></mat-divider>\n </div>\n </div>\n</div>\n",
styles: [".calendar{display:block;min-width:calc(45px * 7);background-color:transparent}.calendar *{box-sizing:border-box}.calendar .calendar-navs{background-color:transparent}.calendar .month-nav{padding:5px;display:flex;flex-direction:row;justify-content:space-between}.calendar .year-nav{padding:5px;display:flex;flex-direction:row;justify-content:space-between;font-family:Montserrat}.calendar .month-grid .day-names{display:flex;flex-direction:row;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.calendar .month-grid .weeks{display:flex;flex-direction:column}.calendar .month-grid .week{display:flex;flex-direction:row}.calendar .month-grid .day-name,.calendar .month-grid .week-date{text-align:center;padding:5px;display:block;width:45px;display:flex;justify-content:center;align-items:center;font-size:1rem}.calendar .month-grid .day-name{color:#28a1e5}.calendar .month-grid .week-date{height:45px;position:relative;border-radius:50%}.calendar .month-grid .week-date .date-text{z-index:10;font-size:1rem;font-family:Montserrat,sans-serif}.calendar .month-grid .week-date::after{content:\"\";height:calc(45px * .9);width:calc(45px * .9);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border-radius:50%;transition:background-color 150ms linear,color 150ms linear;z-index:1}.calendar .month-grid .week-date.enabled{cursor:pointer}.calendar .month-grid .week-date.enabled:hover{opacity:.6}.calendar .month-grid .week-date .selected,.calendar .month-grid .week-date .selected:after{background-color:#28a1e5;color:#fff;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date .selected:hover:after{background-color:transparent;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date .fullTimeSelected,.calendar .month-grid .week-date .fullTimeSelected:after{background-color:#757374!important;color:#fff;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date .fullTimeSelected:hover:after{background-color:transparent;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date.disabled{opacity:.6}.calendar .month-grid .today{font-weight:700}.to-span{padding-top:2.5rem;margin-left:1rem;margin-right:1rem}.p-05{padding:.5rem}.time-selector{display:inline-flex}.title{font-size:1.2rem;font-weight:700}.hr-margin{margin-top:1px;margin-bottom:1px}.text-center{text-align:center}.text-right{text-align:right}*{font-size:.8rem}"]
}] }
];
/** @nocollapse */
NgxMatShiftSelectionComponent.ctorParameters = () => [];
NgxMatShiftSelectionComponent.propDecorators = {
selectedDates: [{ type: Input }],
calendarType: [{ type: Input }],
class: [{ type: Input }],
onSelectDate: [{ type: Output }]
};
if (false) {
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.currentDate;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.dayNames;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.weeks;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.sortedDates;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.selectAll;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.availableAll;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.time;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.selectedDates;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.calendarType;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.class;
/** @type {?} */
NgxMatShiftSelectionComponent.prototype.onSelectDate;
}
/**
* @record
*/
export function CalendarDate() { }
if (false) {
/** @type {?} */
CalendarDate.prototype.mDate;
/** @type {?|undefined} */
CalendarDate.prototype.selected;
/** @type {?|undefined} */
CalendarDate.prototype.today;
/** @type {?} */
CalendarDate.prototype.startTime;
/** @type {?} */
CalendarDate.prototype.endTime;
/** @type {?|undefined} */
CalendarDate.prototype.isTimerVisible;
/** @type {?|undefined} */
CalendarDate.prototype.isFullTime;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hdC1zaGlmdC1zZWxlY3Rpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LW1hdC1zaGlmdC1zZWxlY3Rpb24vIiwic291cmNlcyI6WyJsaWIvbmd4LW1hdC1zaGlmdC1zZWxlY3Rpb24uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBRVAsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxLQUFLLE9BQU8sTUFBTSxRQUFRLENBQUE7O01BQzNCLE1BQU0sR0FBRyxPQUFPO0FBR3RCLE9BQU8sS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBTzVCLE1BQU0sT0FBTyw2QkFBNkI7SUFpRXhDO1FBaEVBLGdCQUFXLEdBQUcsTUFBTSxFQUFFLENBQUM7UUFDdkIsYUFBUSxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0QsVUFBSyxHQUFxQixFQUFFLENBQUM7UUFDN0IsZ0JBQVcsR0FBbUIsRUFBRSxDQUFDO1FBRWpDLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFDM0IsaUJBQVksR0FBWSxLQUFLLENBQUM7UUFFOUIsU0FBSSxHQUFHO1lBQ0wsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1NBQ1IsQ0FBQztRQUVPLGtCQUFhLEdBQW1CLEVBQUUsQ0FBQztRQUNuQyxpQkFBWSxHQUFXLE9BQU8sQ0FBQztRQUMvQixVQUFLLEdBQVcsRUFBRSxDQUFDO1FBQ2xCLGlCQUFZLEdBQUcsSUFBSSxZQUFZLEVBQWtCLENBQUM7SUFFN0MsQ0FBQzs7OztJQUVoQixRQUFRO1FBQ04sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQzs7Ozs7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFDRSxPQUFPLENBQUMsYUFBYTtZQUNyQixPQUFPLENBQUMsYUFBYSxDQUFDLFlBQVk7WUFDbEMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFDN0M7WUFDQSxrRUFBa0U7WUFDbEUsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUN6QixPQUFPLENBQUMsYUFBYSxDQUFDLFlBQVk7Ozs7WUFDbEMsQ0FBQyxDQUFlLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQ3ZDLENBQUM7WUFDRixJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUN6QjtJQUNILENBQUM7Ozs7O0lBRUssVUFBVSxDQUFDLElBQWtCOztZQUNqQyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztZQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtnQkFDbEIsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhOzs7O2dCQUFFLENBQUMsQ0FBQyxFQUFFO29CQUNyQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN6RCxDQUFDLEVBQUMsQ0FBQzthQUNKO2lCQUFNO2dCQUNMLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO2dCQUNwQixJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDbEIsSUFBSSxDQUFDLGNBQWM7b0JBQ2pCLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFO3dCQUNsRCxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO29CQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQ2xFO1lBQ0QsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWE7Ozs7WUFBRSxDQUFDLENBQWUsRUFBRSxFQUFFLENBQ3hFLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQ2xCLENBQUM7WUFDRixJQUFJLENBQUMsU0FBUyxHQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN4QyxJQUFJLENBQUMsWUFBWSxHQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDM0MsQ0FBQztLQUFBOzs7Ozs7SUFJRCxPQUFPLENBQUMsSUFBWTtRQUNsQixPQUFPLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDOUMsQ0FBQzs7Ozs7SUFFRCxVQUFVLENBQUMsSUFBWTtRQUNyQixPQUFPLENBQ0wsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsYUFBYTs7OztRQUFFLFlBQVksQ0FBQyxFQUFFO1lBQzdDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hELENBQUMsRUFBQyxHQUFHLENBQUMsQ0FBQyxDQUNSLENBQUM7SUFDSixDQUFDOzs7OztJQUVELFdBQVcsQ0FBQyxJQUFZO1FBQ3RCLE9BQU8sQ0FDTCxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhOzs7O1FBQUUsWUFBWSxDQUFDLEVBQUU7WUFDN0MsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEQsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxDQUFDLENBQ1IsQ0FBQztJQUNKLENBQUM7Ozs7SUFFRCxjQUFjO1FBQ1osS0FBSyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1NBQ3hEO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDOzs7O0lBRUQsZUFBZTtRQUNiLEtBQUssSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUM5QixJQUFJLENBQUMsQ0FBQyxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUMsY0FBYztnQkFBRSxPQUFPLEtBQUssQ0FBQztTQUNyRDtRQUNELEtBQUssSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUMzQixJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVE7Z0JBQUUsT0FBTyxLQUFLLENBQUM7U0FDL0I7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7Ozs7O0lBRUQsVUFBVSxDQUFDLElBQVk7UUFDckIsT0FBTyxDQUNMLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGFBQWE7Ozs7UUFBRSxZQUFZLENBQUMsRUFBRTtZQUM3QyxPQUFPLENBQ0wsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQztnQkFDOUMsWUFBWSxDQUFDLFVBQVUsQ0FDeEIsQ0FBQztRQUNKLENBQUMsRUFBQyxHQUFHLENBQUMsQ0FBQyxDQUNSLENBQUM7SUFDSixDQUFDOzs7OztJQUVELGVBQWUsQ0FBQyxJQUFZO1FBQzFCLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3hELENBQUM7Ozs7O0lBRUQsTUFBTSxDQUFDLElBQVk7UUFDakIsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUM1RCxDQUFDOzs7OztJQUlELFNBQVM7UUFDUCxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDOzs7O0lBRUQsU0FBUztRQUNQLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQzFCLENBQUM7Ozs7SUFFRCxRQUFRO1FBQ04sSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDM0QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQzs7OztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNoRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDOzs7O0lBRUQsVUFBVTtRQUNSLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQzs7OztJQUVELFNBQVM7UUFDUCxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQzFCLENBQUM7Ozs7SUFFRCxRQUFRO1FBQ04sSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQzs7OztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDOzs7OztJQUlELGdCQUFnQjs7Y0FDUixLQUFLLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDOztjQUN4QyxLQUFLLEdBQXFCLEVBQUU7UUFDbEMsT0FBTyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN2QixLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEM7UUFDRCxLQUFLLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDOUIsQ0FBQyxDQUFDLGNBQWM7Z0JBQ2QsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDdkU7UUFDRCxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUM3QyxDQUFDOzs7OztJQUVELFNBQVMsQ0FBQyxhQUFxQjtRQUM3QixJQUFJLElBQUksQ0FBQyxZQUFZLElBQUksTUFBTSxFQUFFOztrQkFDekIsV0FBVyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUM7aUJBQ3RDLE9BQU8sQ0FBQyxNQUFNLENBQUM7aUJBQ2YsR0FBRyxFQUFFOztrQkFDRixjQUFjLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQztpQkFDekMsT0FBTyxDQUFDLE1BQU0sQ0FBQztpQkFDZixRQUFRLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQzs7a0JBQzFCLEtBQUssR0FBRyxjQUFjLENBQUMsSUFBSSxFQUFFO1lBQ25DLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUc7Ozs7WUFDbEMsQ0FBQyxJQUFZLEVBQWdCLEVBQUU7O3NCQUN2QixDQUFDLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7Z0JBQzNDLE9BQU87b0JBQ0wsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUN0QixRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7b0JBQzVCLEtBQUssRUFBRSxDQUFDO29CQUNSLFNBQVMsRUFBRSxTQUFTO29CQUNwQixPQUFPLEVBQUUsU0FBUztvQkFDbEIsY0FBYyxFQUFFLEtBQUs7b0JBQ3JCLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztpQkFDL0IsQ0FBQztZQUNKLENBQUMsRUFDRixDQUFDO1NBQ0g7O2NBQ0ssWUFBWSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUM7YUFDdkMsT0FBTyxDQUFDLE9BQU8sQ0FBQzthQUNoQixHQUFHLEVBQUU7O2NBQ0YsY0FBYyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUM7YUFDekMsT0FBTyxDQUFDLE9BQU8sQ0FBQzthQUNoQixRQUFRLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQzs7Y0FDM0IsS0FBSyxHQUFHLGNBQWMsQ0FBQyxJQUFJLEVBQUU7UUFDbkMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsRUFBRSxDQUFDLENBQUMsR0FBRzs7OztRQUNuQyxDQUFDLElBQVksRUFBZ0IsRUFBRTs7a0JBQ3ZCLENBQUMsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUMzQyxPQUFPO2dCQUNMLEtBQUssRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDdEIsUUFBUSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO2dCQUM1QixLQUFLLEVBQUUsQ0FBQztnQkFDUixTQUFTLEVBQUUsU0FBUztnQkFDcEIsT0FBTyxFQUFFLFNBQVM7Z0JBQ2xCLGNBQWMsRUFBRSxLQUFLO2dCQUNyQixVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7YUFDL0IsQ0FBQztRQUNKLENBQUMsRUFDRixDQUFDO0lBQ0osQ0FBQzs7Ozs7SUFFRCxXQUFXLENBQUMsR0FBRztRQUNiLEdBQUcsQ0FBQyxVQUFVO1lBQ1osR0FBRyxDQUFDLFNBQVMsSUFBSSxPQUFPO2dCQUN4QixHQUFHLENBQUMsT0FBTyxJQUFJLE9BQU87Z0JBQ3hCLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRzs7OztnQkFBQyxDQUFDLENBQUMsRUFBRTtvQkFDcEIsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRTt3QkFDbEQsQ0FBQyxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDO3FCQUMvQjtnQkFDSCxDQUFDLEVBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQzNDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUMzQyxDQUFDOzs7OztJQUVELGVBQWUsQ0FBQyxHQUFHO1FBQ2pCLEdBQUcsQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDOUMsR0FBRyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUM1QyxLQUFLLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDOUIsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3BFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUM7Z0JBQzlDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUM7YUFDM0M7U0FDRjtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDeEIsQ0FBQzs7OztJQUVELGdCQUFnQjtRQUNkLEtBQUssSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUMzQixDQUFDLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDNUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNwQjtJQUNILENBQUM7Ozs7SUFFSyxtQkFBbUI7O1lBQ3ZCLElBQUksQ0FBQyxZQUFZLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQ3ZDLEtBQUssSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtnQkFDOUIsQ0FBQyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO2dCQUNuRSxDQUFDLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUMxQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN4QyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUc7Ozs7Z0JBQUMsR0FBRyxDQUFDLEVBQUU7b0JBQ3RCLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7d0JBQ2xELEdBQUcsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLFVBQVUsQ0FBQztxQkFDL0I7Z0JBQ0gsQ0FBQyxFQUFDLENBQUM7YUFDSjtZQUNELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMzQyxDQUFDO0tBQUE7Ozs7SUFFRCxZQUFZO1FBQ1YsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzNDLENBQUM7OztZQXZVRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLHlCQUF5QjtnQkFDbkMsbXRMQUF1RDs7YUFFeEQ7Ozs7OzRCQTZERSxLQUFLOzJCQUNMLEtBQUs7b0JBQ0wsS0FBSzsyQkFDTCxNQUFNOzs7O0lBOURQLG9EQUF1Qjs7SUFDdkIsaURBQTZEOztJQUM3RCw4Q0FBNkI7O0lBQzdCLG9EQUFpQzs7SUFFakMsa0RBQTJCOztJQUMzQixxREFBOEI7O0lBRTlCLDZDQWlERTs7SUFFRixzREFBNEM7O0lBQzVDLHFEQUF3Qzs7SUFDeEMsOENBQTRCOztJQUM1QixxREFBNEQ7Ozs7O0FBc1E5RCxrQ0FRQzs7O0lBUEMsNkJBQWM7O0lBQ2QsZ0NBQW1COztJQUNuQiw2QkFBZ0I7O0lBQ2hCLGlDQUFrQjs7SUFDbEIsK0JBQWdCOztJQUNoQixzQ0FBeUI7O0lBQ3pCLGtDQUFxQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlc1xufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuXG5pbXBvcnQgKiBhcyBfbW9tZW50IGZyb20gJ21vbWVudCdcbmNvbnN0IG1vbWVudCA9IF9tb21lbnRcbnR5cGUgTW9tZW50ID0gX21vbWVudC5Nb21lbnRcblxuaW1wb3J0ICogYXMgXyBmcm9tIFwibG9kYXNoXCI7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJuZ3gtbWF0LXNoaWZ0LXNlbGVjdGlvblwiLFxuICB0ZW1wbGF0ZVVybDogXCIuL25neC1tYXQtc2hpZnQtc2VsZWN0aW9uLmNvbXBvbmVudC5odG1sXCIsXG4gIHN0eWxlVXJsczogW1wiLi9uZ3gtbWF0LXNoaWZ0LXNlbGVjdGlvbi5jb21wb25lbnQuc2Nzc1wiXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hNYXRTaGlmdFNlbGVjdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgY3VycmVudERhdGUgPSBtb21lbnQoKTtcbiAgZGF5TmFtZXMgPSBbXCJTdW5cIiwgXCJNb25cIiwgXCJUdWVcIiwgXCJXZWRcIiwgXCJUaHVcIiwgXCJGcmlcIiwgXCJTYXRcIl07XG4gIHdlZWtzOiBDYWxlbmRhckRhdGVbXVtdID0gW107XG4gIHNvcnRlZERhdGVzOiBDYWxlbmRhckRhdGVbXSA9IFtdO1xuXG4gIHNlbGVjdEFsbDogYm9vbGVhbiA9IGZhbHNlO1xuICBhdmFpbGFibGVBbGw6IGJvb2xlYW4gPSBmYWxzZTtcblxuICB0aW1lID0gW1xuICAgIFwiMDA6MDBcIixcbiAgICBcIjAwOjMwXCIsXG4gICAgXCIwMTowMFwiLFxuICAgIFwiMDE6MzBcIixcbiAgICBcIjAyOjAwXCIsXG4gICAgXCIwMjozMFwiLFxuICAgIFwiMDM6MDBcIixcbiAgICBcIjAzOjMwXCIsXG4gICAgXCIwNDowMFwiLFxuICAgIFwiMDQ6MzBcIixcbiAgICBcIjA1OjAwXCIsXG4gICAgXCIwNTozMFwiLFxuICAgIFwiMDY6MDBcIixcbiAgICBcIjA2OjMwXCIsXG4gICAgXCIwNzowMFwiLFxuICAgIFwiMDc6MzBcIixcbiAgICBcIjA4OjAwXCIsXG4gICAgXCIwODozMFwiLFxuICAgIFwiMDk6MDBcIixcbiAgICBcIjA5OjMwXCIsXG4gICAgXCIxMDowMFwiLFxuICAgIFwiMTA6MzBcIixcbiAgICBcIjExOjAwXCIsXG4gICAgXCIxMTozMFwiLFxuICAgIFwiMTI6MDBcIixcbiAgICBcIjEyOjMwXCIsXG4gICAgXCIxMzowMFwiLFxuICAgIFwiMTM6MzBcIixcbiAgICBcIjE0OjAwXCIsXG4gICAgXCIxNDozMFwiLFxuICAgIFwiMTU6MDBcIixcbiAgICBcIjE1OjMwXCIsXG4gICAgXCIxNjowMFwiLFxuICAgIFwiMTY6MzBcIixcbiAgICBcIjE3OjAwXCIsXG4gICAgXCIxNzozMFwiLFxuICAgIFwiMTg6MDBcIixcbiAgICBcIjE4OjMwXCIsXG4gICAgXCIxOTowMFwiLFxuICAgIFwiMTk6MzBcIixcbiAgICBcIjIwOjAwXCIsXG4gICAgXCIyMDozMFwiLFxuICAgIFwiMjE6MDBcIixcbiAgICBcIjIxOjMwXCIsXG4gICAgXCIyMjowMFwiLFxuICAgIFwiMjI6MzBcIixcbiAgICBcIjIzOjAwXCIsXG4gICAgXCIyMzozMFwiXG4gIF07XG5cbiAgQElucHV0KCkgc2VsZWN0ZWREYXRlczogQ2FsZW5kYXJEYXRlW10gPSBbXTtcbiAgQElucHV0KCkgY2FsZW5kYXJUeXBlOiBTdHJpbmcgPSBcIm1vbnRoXCI7XG4gIEBJbnB1dCgpIGNsYXNzOiBTdHJpbmcgPSBcIlwiO1xuICBAT3V0cHV0KCkgb25TZWxlY3REYXRlID0gbmV3IEV2ZW50RW1pdHRlcjxDYWxlbmRhckRhdGVbXT4oKTtcblxuICBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKFxuICAgICAgY2hhbmdlcy5zZWxlY3RlZERhdGVzICYmXG4gICAgICBjaGFuZ2VzLnNlbGVjdGVkRGF0ZXMuY3VycmVudFZhbHVlICYmXG4gICAgICBjaGFuZ2VzLnNlbGVjdGVkRGF0ZXMuY3VycmVudFZhbHVlLmxlbmd0aCA+IDFcbiAgICApIHtcbiAgICAgIC8vIHNvcnQgb24gZGF0ZSBjaGFuZ2VzIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2Ugd2hlbiByYW5nZSBjaGVja2luZ1xuICAgICAgdGhpcy5zb3J0ZWREYXRlcyA9IF8uc29ydEJ5KFxuICAgICAgICBjaGFuZ2VzLnNlbGVjdGVkRGF0ZXMuY3VycmVudFZhbHVlLFxuICAgICAgICAobTogQ2FsZW5kYXJEYXRlKSA9PiBtLm1EYXRlLnZhbHVlT2YoKVxuICAgICAgKTtcbiAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNlbGVjdERhdGUoZGF0ZTogQ2FsZW5kYXJEYXRlKSB7XG4gICAgZGF0ZS5zZWxlY3RlZCA9ICFkYXRlLnNlbGVjdGVkO1xuICAgIGRhdGUuaXNGdWxsVGltZSA9IGZhbHNlO1xuICAgIGlmICghZGF0ZS5zZWxlY3RlZCkge1xuICAgICAgYXdhaXQgXy5yZW1vdmUodGhpcy5zZWxlY3RlZERhdGVzLCB2ID0+IHtcbiAgICAgICAgcmV0dXJuIHYubURhdGUuZm9ybWF0KFwibGxcIikgPT0gZGF0ZS5tRGF0ZS5mb3JtYXQoXCJsbFwiKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBkYXRlLnN0YXJ0VGltZSA9IFwiXCI7XG4gICAgICBkYXRlLmVuZFRpbWUgPSBcIlwiO1xuICAgICAgZGF0ZS5pc1RpbWVyVmlzaWJsZSA9XG4gICAgICAgIHRoaXMud2Vla3NbMF1bMV0ubURhdGUud2VlaygpID09IGRhdGUubURhdGUud2VlaygpICYmXG4gICAgICAgICF0aGlzLmlzUGFzdChkYXRlLm1EYXRlKTtcbiAgICAgIGlmICghdGhpcy5pc0R1cGxpY2F0ZShkYXRlLm1EYXRlKSkgdGhpcy5zZWxlY3RlZERhdGVzLnB1c2goZGF0ZSk7XG4gICAgfVxuICAgIHRoaXMuc29ydGVkRGF0ZXMgPSBhd2FpdCBfLnNvcnRCeSh0aGlzLnNlbGVjdGVkRGF0ZXMsIChtOiBDYWxlbmRhckRhdGUpID0+XG4gICAgICBtLm1EYXRlLnZhbHVlT2YoKVxuICAgICk7XG4gICAgdGhpcy5zZWxlY3RBbGwgPSAgdGhpcy5hcmVBbGxTZWxlY3RlZCgpO1xuICAgIHRoaXMuYXZhaWxhYmxlQWxsID0gIHRoaXMuYXJlQWxsQXZhaWxhYmxlKCk7XG4gICAgdGhpcy5vblNlbGVjdERhdGUuZW1pdCh0aGlzLnNvcnRlZERhdGVzKTtcbiAgfVxuXG4gIC8vIGRhdGUgY2hlY2tlcnNcblxuICBpc1RvZGF5KGRhdGU6IE1vbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBtb21lbnQoKS5pc1NhbWUobW9tZW50KGRhdGUpLCBcImRheVwiKTtcbiAgfVxuXG4gIGlzU2VsZWN0ZWQoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIF8uZmluZEluZGV4KHRoaXMuc2VsZWN0ZWREYXRlcywgc2VsZWN0ZWREYXRlID0+IHtcbiAgICAgICAgcmV0dXJuIG1vbWVudChkYXRlKS5pc1NhbWUoc2VsZWN0ZWREYXRlLm1EYXRlLCBcImRheVwiKTtcbiAgICAgIH0pID4gLTFcbiAgICApO1xuICB9XG5cbiAgaXNEdXBsaWNhdGUoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIF8uZmluZEluZGV4KHRoaXMuc2VsZWN0ZWREYXRlcywgc2VsZWN0ZWREYXRlID0+IHtcbiAgICAgICAgcmV0dXJuIG1vbWVudChkYXRlKS5pc1NhbWUoc2VsZWN0ZWREYXRlLm1EYXRlLCBcImRheVwiKTtcbiAgICAgIH0pID4gLTFcbiAgICApO1xuICB9XG5cbiAgYXJlQWxsU2VsZWN0ZWQoKTogYm9vbGVhbiB7XG4gICAgZm9yIChsZXQgdiBvZiB0aGlzLndlZWtzWzBdKSB7XG4gICAgICBpZiAoIXYuc2VsZWN0ZWQgJiYgIXRoaXMuaXNQYXN0KHYubURhdGUpKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgYXJlQWxsQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGZvciAobGV0IHYgb2YgdGhpcy5zb3J0ZWREYXRlcykge1xuICAgICAgaWYgKCF2LmlzRnVsbFRpbWUgJiYgdi5pc1RpbWVyVmlzaWJsZSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGxldCB2IG9mIHRoaXMud2Vla3NbMF0pIHtcbiAgICAgIGlmICghdi5zZWxlY3RlZCkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlzRnVsbFRpbWUoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIF8uZmluZEluZGV4KHRoaXMuc2VsZWN0ZWREYXRlcywgc2VsZWN0ZWREYXRlID0+IHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBtb21lbnQoZGF0ZSkuaXNTYW1lKHNlbGVjdGVkRGF0ZS5tRGF0ZSwgXCJkYXlcIikgJiZcbiAgICAgICAgICBzZWxlY3RlZERhdGUuaXNGdWxsVGltZVxuICAgICAgICApO1xuICAgICAgfSkgPiAtMVxuICAgICk7XG4gIH1cblxuICBpc1NlbGVjdGVkTW9udGgoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIG1vbWVudChkYXRlKS5pc1NhbWUodGhpcy5jdXJyZW50RGF0ZSwgXCJtb250aFwiKTtcbiAgfVxuXG4gIGlzUGFzdChkYXRlOiBNb21lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gbW9tZW50KGRhdGUpLmlzQmVmb3JlKG1vbWVudCgpLnN1YnRyYWN0KDEsIFwiZGF5XCIpKTtcbiAgfVxuXG4gIC8vIGFjdGlvbnMgZnJvbSBjYWxlbmRhclxuXG4gIHByZXZNb250aCgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnREYXRlID0gbW9tZW50KHRoaXMuY3VycmVudERhdGUpLnN1YnRyYWN0KDEsIFwibW9udGhzXCIpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICB9XG5cbiAgbmV4dE1vbnRoKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudERhdGUgPSBtb21lbnQodGhpcy5jdXJyZW50RGF0ZSkuYWRkKDEsIFwibW9udGhzXCIpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICB9XG5cbiAgbmV4dFdlZWsoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50RGF0ZSA9IG1vbWVudCh0aGlzLmN1cnJlbnREYXRlKS5hZGQoMSwgXCJ3ZWVrXCIpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICB9XG5cbiAgcHJldldlZWsoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50RGF0ZSA9IG1vbWVudCh0aGlzLmN1cnJlbnREYXRlKS5zdWJ0cmFjdCgxLCBcIndlZWtcIik7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBmaXJzdE1vbnRoKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudERhdGUgPSBtb21lbnQodGhpcy5jdXJyZW50RGF0ZSkuc3RhcnRPZihcInllYXJcIik7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBsYXN0TW9udGgoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50RGF0ZSA9IG1vbWVudCh0aGlzLmN1cnJlbnREYXRlKS5lbmRPZihcInllYXJcIik7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBwcmV2WWVhcigpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnREYXRlID0gbW9tZW50KHRoaXMuY3VycmVudERhdGUpLnN1YnRyYWN0KDEsIFwieWVhclwiKTtcbiAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXIoKTtcbiAgfVxuXG4gIG5leHRZZWFyKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudERhdGUgPSBtb21lbnQodGhpcy5jdXJyZW50RGF0ZSkuYWRkKDEsIFwieWVhclwiKTtcbiAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXIoKTtcbiAgfVxuXG4gIC8vIGdlbmVyYXRlIHRoZSBjYWxlbmRhciBncmlkXG5cbiAgZ2VuZXJhdGVDYWxlbmRhcigpOiB2b2lkIHtcbiAgICBjb25zdCBkYXRlcyA9IHRoaXMuZmlsbERhdGVzKHRoaXMuY3VycmVudERhdGUpO1xuICAgIGNvbnN0IHdlZWtzOiBDYWxlbmRhckRhdGVbXVtdID0gW107XG4gICAgd2hpbGUgKGRhdGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHdlZWtzLnB1c2goZGF0ZXMuc3BsaWNlKDAsIDcpKTtcbiAgICB9XG4gICAgZm9yIChsZXQgdiBvZiB0aGlzLnNvcnRlZERhdGVzKSB7XG4gICAgICB2LmlzVGltZXJWaXNpYmxlID1cbiAgICAgICAgd2Vla3NbMF1bMV0ubURhdGUud2VlaygpID09IHYubURhdGUud2VlaygpICYmICF0aGlzLmlzUGFzdCh2Lm1EYXRlKTtcbiAgICB9XG4gICAgdGhpcy53ZWVrcyA9IHdlZWtzO1xuICAgIHRoaXMuc2VsZWN0QWxsID0gdGhpcy5hcmVBbGxTZWxlY3RlZCgpO1xuICAgIHRoaXMuYXZhaWxhYmxlQWxsID0gdGhpcy5hcmVBbGxBdmFpbGFibGUoKTtcbiAgfVxuXG4gIGZpbGxEYXRlcyhjdXJyZW50TW9tZW50OiBNb21lbnQpOiBDYWxlbmRhckRhdGVbXSB7XG4gICAgaWYgKHRoaXMuY2FsZW5kYXJUeXBlID09IFwid2Vla1wiKSB7XG4gICAgICBjb25zdCBmaXJzdE9mV2VlayA9IG1vbWVudChjdXJyZW50TW9tZW50KVxuICAgICAgICAuc3RhcnRPZihcIndlZWtcIilcbiAgICAgICAgLmRheSgpO1xuICAgICAgY29uc3QgZmlyc3REYXlPZkdyaWQgPSBtb21lbnQoY3VycmVudE1vbWVudClcbiAgICAgICAgLnN0YXJ0T2YoXCJ3ZWVrXCIpXG4gICAgICAgIC5zdWJ0cmFjdChmaXJzdE9mV2VlaywgXCJkYXlzXCIpO1xuICAgICAgY29uc3Qgc3RhcnQgPSBmaXJzdERheU9mR3JpZC5kYXRlKCk7XG4gICAgICByZXR1cm4gXy5yYW5nZShzdGFydCwgc3RhcnQgKyA3KS5tYXAoXG4gICAgICAgIChkYXRlOiBudW1iZXIpOiBDYWxlbmRhckRhdGUgPT4ge1xuICAgICAgICAgIGNvbnN0IGQgPSBtb21lbnQoZmlyc3REYXlPZkdyaWQpLmRhdGUoZGF0ZSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRvZGF5OiB0aGlzLmlzVG9kYXkoZCksXG4gICAgICAgICAgICBzZWxlY3RlZDogdGhpcy5pc1NlbGVjdGVkKGQpLFxuICAgICAgICAgICAgbURhdGU6IGQsXG4gICAgICAgICAgICBzdGFydFRpbWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGVuZFRpbWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGlzVGltZXJWaXNpYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGlzRnVsbFRpbWU6IHRoaXMuaXNGdWxsVGltZShkKVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGZpcnN0T2ZNb250aCA9IG1vbWVudChjdXJyZW50TW9tZW50KVxuICAgICAgLnN0YXJ0T2YoXCJtb250aFwiKVxuICAgICAgLmRheSgpO1xuICAgIGNvbnN0IGZpcnN0RGF5T2ZHcmlkID0gbW9tZW50KGN1cnJlbnRNb21lbnQpXG4gICAgICAuc3RhcnRPZihcIm1vbnRoXCIpXG4gICAgICAuc3VidHJhY3QoZmlyc3RPZk1vbnRoLCBcImRheXNcIik7XG4gICAgY29uc3Qgc3RhcnQgPSBmaXJzdERheU9mR3JpZC5kYXRlKCk7XG4gICAgcmV0dXJuIF8ucmFuZ2Uoc3RhcnQsIHN0YXJ0ICsgMzUpLm1hcChcbiAgICAgIChkYXRlOiBudW1iZXIpOiBDYWxlbmRhckRhdGUgPT4ge1xuICAgICAgICBjb25zdCBkID0gbW9tZW50KGZpcnN0RGF5T2ZHcmlkKS5kYXRlKGRhdGUpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHRvZGF5OiB0aGlzLmlzVG9kYXkoZCksXG4gICAgICAgICAgc2VsZWN0ZWQ6IHRoaXMuaXNTZWxlY3RlZChkKSxcbiAgICAgICAgICBtRGF0ZTogZCxcbiAgICAgICAgICBzdGFydFRpbWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICBlbmRUaW1lOiB1bmRlZmluZWQsXG4gICAgICAgICAgaXNUaW1lclZpc2libGU6IGZhbHNlLFxuICAgICAgICAgIGlzRnVsbFRpbWU6IHRoaXMuaXNGdWxsVGltZShkKVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICB0aW1lQ2hhbmdlZCh2YWwpIHtcbiAgICB2YWwuaXNGdWxsVGltZSA9XG4gICAgICB2YWwuc3RhcnRUaW1lID09IFwiMDA6MDBcIiAmJlxuICAgICAgdmFsLmVuZFRpbWUgPT0gXCIyMzo1OVwiICYmXG4gICAgdGhpcy53ZWVrc1swXS5tYXAodiA9PiB7XG4gICAgICBpZiAodi5tRGF0ZS5mb3JtYXQoXCJsbFwiKSA9PSB2YWwubURhdGUuZm9ybWF0KFwibGxcIikpIHtcbiAgICAgICAgdi5pc0Z1bGxUaW1lID0gdmFsLmlzRnVsbFRpbWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5hdmFpbGFibGVBbGwgPSB0aGlzLmFyZUFsbEF2YWlsYWJsZSgpO1xuICAgIHRoaXMub25TZWxlY3REYXRlLmVtaXQodGhpcy5zb3J0ZWREYXRlcyk7XG4gIH1cblxuICBmdWxsVGltZUNoZWNrZWQodmFsKSB7XG4gICAgdmFsLnN0YXJ0VGltZSA9IHZhbC5pc0Z1bGxUaW1lID8gXCIwMDowMFwiIDogXCJcIjtcbiAgICB2YWwuZW5kVGltZSA9IHZhbC5pc0Z1bGxUaW1lID8gXCIyMzo1OVwiIDogXCJcIjtcbiAgICBmb3IgKGxldCB2IGluIHRoaXMuc29ydGVkRGF0ZXMpIHtcbiAgICAgIGlmICh0aGlzLnNvcnRlZERhdGVzW3ZdLm1EYXRlLmZvcm1hdChcImxsXCIpID09IHZhbC5tRGF0ZS5mb3JtYXQoXCJsbFwiKSkge1xuICAgICAgICB0aGlzLnNvcnRlZERhdGVzW3ZdLnN0YXJ0VGltZSA9IHZhbC5zdGFydFRpbWU7XG4gICAgICAgIHRoaXMuc29ydGVkRGF0ZXNbdl0uZW5kVGltZSA9IHZhbC5lbmRUaW1lO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnRpbWVDaGFuZ2VkKHZhbCk7XG4gIH1cblxuICBzZWxlY3RBbGxDaGVja2VkKCkge1xuICAgIGZvciAobGV0IHYgb2YgdGhpcy53ZWVrc1swXSkge1xuICAgICAgdi5zZWxlY3RlZCA9IHRoaXMuc2VsZWN0QWxsO1xuICAgICAgdGhpcy5zZWxlY3REYXRlKHYpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGF2YWlsYWJsZUFsbENoZWNrZWQoKSB7XG4gICAgdGhpcy5hdmFpbGFibGVBbGwgPSAhdGhpcy5hdmFpbGFibGVBbGw7XG4gICAgZm9yIChsZXQgdiBvZiB0aGlzLnNvcnRlZERhdGVzKSB7XG4gICAgICB2LmlzRnVsbFRpbWUgPSB2LmlzVGltZXJWaXNpYmxlID8gdGhpcy5hdmFpbGFibGVBbGwgOiB2LmlzRnVsbFRpbWU7XG4gICAgICB2LnN0YXJ0VGltZSA9IHYuaXNGdWxsVGltZSA/IFwiMDA6MDBcIiA6IFwiXCI7XG4gICAgICB2LmVuZFRpbWUgPSB2LmlzRnVsbFRpbWUgPyBcIjIzOjU5XCIgOiBcIlwiO1xuICAgICAgdGhpcy53ZWVrc1swXS5tYXAodmFsID0+IHtcbiAgICAgICAgaWYgKHZhbC5tRGF0ZS5mb3JtYXQoXCJsbFwiKSA9PSB2Lm1EYXRlLmZvcm1hdChcImxsXCIpKSB7XG4gICAgICAgICAgdmFsLmlzRnVsbFRpbWUgPSB2LmlzRnVsbFRpbWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLm9uU2VsZWN0RGF0ZS5lbWl0KHRoaXMuc29ydGVkRGF0ZXMpO1xuICB9XG5cbiAgdGltZVNlbGVjdGVkKCkge1xuICAgIHRoaXMub25TZWxlY3REYXRlLmVtaXQodGhpcy5zb3J0ZWREYXRlcyk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBDYWxlbmRhckRhdGUge1xuICBtRGF0ZTogTW9tZW50O1xuICBzZWxlY3RlZD86IGJvb2xlYW47XG4gIHRvZGF5PzogYm9vbGVhbjtcbiAgc3RhcnRUaW1lOiBzdHJpbmc7XG4gIGVuZFRpbWU6IHN0cmluZztcbiAgaXNUaW1lclZpc2libGU/OiBib29sZWFuO1xuICBpc0Z1bGxUaW1lPzogYm9vbGVhbjtcbn1cbiJdfQ==