UNPKG

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
/** * @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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hdC1zaGlmdC1zZWxlY3Rpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LW1hdC1zaGlmdC1zZWxlY3Rpb24vIiwic291cmNlcyI6WyJsaWIvbmd4LW1hdC1zaGlmdC1zZWxlY3Rpb24uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBRVAsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxLQUFLLE9BQU8sTUFBTSxRQUFRLENBQUE7O01BQzNCLE1BQU0sR0FBRyxPQUFPO0FBR3RCLE9BQU8sS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBTzVCLE1BQU0sT0FBTyw2QkFBNkI7SUFpRXhDO1FBaEVBLGdCQUFXLEdBQUcsTUFBTSxFQUFFLENBQUM7UUFDdkIsYUFBUSxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0QsVUFBSyxHQUFxQixFQUFFLENBQUM7UUFDN0IsZ0JBQVcsR0FBbUIsRUFBRSxDQUFDO1FBRWpDLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFDM0IsaUJBQVksR0FBWSxLQUFLLENBQUM7UUFFOUIsU0FBSSxHQUFHO1lBQ0wsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxPQUFPO1lBQ1AsT0FBTztZQUNQLE9BQU87WUFDUCxP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dCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlc1xufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuXG5pbXBvcnQgKiBhcyBfbW9tZW50IGZyb20gJ21vbWVudCdcbmNvbnN0IG1vbWVudCA9IF9tb21lbnRcbnR5cGUgTW9tZW50ID0gX21vbWVudC5Nb21lbnRcblxuaW1wb3J0ICogYXMgXyBmcm9tIFwibG9kYXNoXCI7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJuZ3gtbWF0LXNoaWZ0LXNlbGVjdGlvblwiLFxuICB0ZW1wbGF0ZVVybDogXCIuL25neC1tYXQtc2hpZnQtc2VsZWN0aW9uLmNvbXBvbmVudC5odG1sXCIsXG4gIHN0eWxlVXJsczogW1wiLi9uZ3gtbWF0LXNoaWZ0LXNlbGVjdGlvbi5jb21wb25lbnQuc2Nzc1wiXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hNYXRTaGlmdFNlbGVjdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgY3VycmVudERhdGUgPSBtb21lbnQoKTtcbiAgZGF5TmFtZXMgPSBbXCJTdW5cIiwgXCJNb25cIiwgXCJUdWVcIiwgXCJXZWRcIiwgXCJUaHVcIiwgXCJGcmlcIiwgXCJTYXRcIl07XG4gIHdlZWtzOiBDYWxlbmRhckRhdGVbXVtdID0gW107XG4gIHNvcnRlZERhdGVzOiBDYWxlbmRhckRhdGVbXSA9IFtdO1xuXG4gIHNlbGVjdEFsbDogYm9vbGVhbiA9IGZhbHNlO1xuICBhdmFpbGFibGVBbGw6IGJvb2xlYW4gPSBmYWxzZTtcblxuICB0aW1lID0gW1xuICAgIFwiMDA6MDBcIixcbiAgICBcIjAwOjMwXCIsXG4gICAgXCIwMTowMFwiLFxuICAgIFwiMDE6MzBcIixcbiAgICBcIjAyOjAwXCIsXG4gICAgXCIwMjozMFwiLFxuICAgIFwiMDM6MDBcIixcbiAgICBcIjAzOjMwXCIsXG4gICAgXCIwNDowMFwiLFxuICAgIFwiMDQ6MzBcIixcbiAgICBcIjA1OjAwXCIsXG4gICAgXCIwNTozMFwiLFxuICAgIFwiMDY6MDBcIixcbiAgICBcIjA2OjMwXCIsXG4gICAgXCIwNzowMFwiLFxuICAgIFwiMDc6MzBcIixcbiAgICBcIjA4OjAwXCIsXG4gICAgXCIwODozMFwiLFxuICAgIFwiMDk6MDBcIixcbiAgICBcIjA5OjMwXCIsXG4gICAgXCIxMDowMFwiLFxuICAgIFwiMTA6MzBcIixcbiAgICBcIjExOjAwXCIsXG4gICAgXCIxMTozMFwiLFxuICAgIFwiMTI6MDBcIixcbiAgICBcIjEyOjMwXCIsXG4gICAgXCIxMzowMFwiLFxuICAgIFwiMTM6MzBcIixcbiAgICBcIjE0OjAwXCIsXG4gICAgXCIxNDozMFwiLFxuICAgIFwiMTU6MDBcIixcbiAgICBcIjE1OjMwXCIsXG4gICAgXCIxNjowMFwiLFxuICAgIFwiMTY6MzBcIixcbiAgICBcIjE3OjAwXCIsXG4gICAgXCIxNzozMFwiLFxuICAgIFwiMTg6MDBcIixcbiAgICBcIjE4OjMwXCIsXG4gICAgXCIxOTowMFwiLFxuICAgIFwiMTk6MzBcIixcbiAgICBcIjIwOjAwXCIsXG4gICAgXCIyMDozMFwiLFxuICAgIFwiMjE6MDBcIixcbiAgICBcIjIxOjMwXCIsXG4gICAgXCIyMjowMFwiLFxuICAgIFwiMjI6MzBcIixcbiAgICBcIjIzOjAwXCIsXG4gICAgXCIyMzozMFwiXG4gIF07XG5cbiAgQElucHV0KCkgc2VsZWN0ZWREYXRlczogQ2FsZW5kYXJEYXRlW10gPSBbXTtcbiAgQElucHV0KCkgY2FsZW5kYXJUeXBlOiBTdHJpbmcgPSBcIm1vbnRoXCI7XG4gIEBJbnB1dCgpIGNsYXNzOiBTdHJpbmcgPSBcIlwiO1xuICBAT3V0cHV0KCkgb25TZWxlY3REYXRlID0gbmV3IEV2ZW50RW1pdHRlcjxDYWxlbmRhckRhdGVbXT4oKTtcblxuICBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKFxuICAgICAgY2hhbmdlcy5zZWxlY3RlZERhdGVzICYmXG4gICAgICBjaGFuZ2VzLnNlbGVjdGVkRGF0ZXMuY3VycmVudFZhbHVlICYmXG4gICAgICBjaGFuZ2VzLnNlbGVjdGVkRGF0ZXMuY3VycmVudFZhbHVlLmxlbmd0aCA+IDFcbiAgICApIHtcbiAgICAgIC8vIHNvcnQgb24gZGF0ZSBjaGFuZ2VzIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2Ugd2hlbiByYW5nZSBjaGVja2luZ1xuICAgICAgdGhpcy5zb3J0ZWREYXRlcyA9IF8uc29ydEJ5KFxuICAgICAgICBjaGFuZ2VzLnNlbGVjdGVkRGF0ZXMuY3VycmVudFZhbHVlLFxuICAgICAgICAobTogQ2FsZW5kYXJEYXRlKSA9PiBtLm1EYXRlLnZhbHVlT2YoKVxuICAgICAgKTtcbiAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNlbGVjdERhdGUoZGF0ZTogQ2FsZW5kYXJEYXRlKSB7XG4gICAgZGF0ZS5zZWxlY3RlZCA9ICFkYXRlLnNlbGVjdGVkO1xuICAgIGRhdGUuaXNGdWxsVGltZSA9IGZhbHNlO1xuICAgIGlmICghZGF0ZS5zZWxlY3RlZCkge1xuICAgICAgYXdhaXQgXy5yZW1vdmUodGhpcy5zZWxlY3RlZERhdGVzLCB2ID0+IHtcbiAgICAgICAgcmV0dXJuIHYubURhdGUuZm9ybWF0KFwibGxcIikgPT0gZGF0ZS5tRGF0ZS5mb3JtYXQoXCJsbFwiKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBkYXRlLnN0YXJ0VGltZSA9IFwiXCI7XG4gICAgICBkYXRlLmVuZFRpbWUgPSBcIlwiO1xuICAgICAgZGF0ZS5pc1RpbWVyVmlzaWJsZSA9XG4gICAgICAgIHRoaXMud2Vla3NbMF1bMV0ubURhdGUud2VlaygpID09IGRhdGUubURhdGUud2VlaygpICYmXG4gICAgICAgICF0aGlzLmlzUGFzdChkYXRlLm1EYXRlKTtcbiAgICAgIGlmICghdGhpcy5pc0R1cGxpY2F0ZShkYXRlLm1EYXRlKSkgdGhpcy5zZWxlY3RlZERhdGVzLnB1c2goZGF0ZSk7XG4gICAgfVxuICAgIHRoaXMuc29ydGVkRGF0ZXMgPSBhd2FpdCBfLnNvcnRCeSh0aGlzLnNlbGVjdGVkRGF0ZXMsIChtOiBDYWxlbmRhckRhdGUpID0+XG4gICAgICBtLm1EYXRlLnZhbHVlT2YoKVxuICAgICk7XG4gICAgdGhpcy5zZWxlY3RBbGwgPSAgdGhpcy5hcmVBbGxTZWxlY3RlZCgpO1xuICAgIHRoaXMuYXZhaWxhYmxlQWxsID0gIHRoaXMuYXJlQWxsQXZhaWxhYmxlKCk7XG4gICAgdGhpcy5vblNlbGVjdERhdGUuZW1pdCh0aGlzLnNvcnRlZERhdGVzKTtcbiAgfVxuXG4gIC8vIGRhdGUgY2hlY2tlcnNcblxuICBpc1RvZGF5KGRhdGU6IE1vbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBtb21lbnQoKS5pc1NhbWUobW9tZW50KGRhdGUpLCBcImRheVwiKTtcbiAgfVxuXG4gIGlzU2VsZWN0ZWQoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIF8uZmluZEluZGV4KHRoaXMuc2VsZWN0ZWREYXRlcywgc2VsZWN0ZWREYXRlID0+IHtcbiAgICAgICAgcmV0dXJuIG1vbWVudChkYXRlKS5pc1NhbWUoc2VsZWN0ZWREYXRlLm1EYXRlLCBcImRheVwiKTtcbiAgICAgIH0pID4gLTFcbiAgICApO1xuICB9XG5cbiAgaXNEdXBsaWNhdGUoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIF8uZmluZEluZGV4KHRoaXMuc2VsZWN0ZWREYXRlcywgc2VsZWN0ZWREYXRlID0+IHtcbiAgICAgICAgcmV0dXJuIG1vbWVudChkYXRlKS5pc1NhbWUoc2VsZWN0ZWREYXRlLm1EYXRlLCBcImRheVwiKTtcbiAgICAgIH0pID4gLTFcbiAgICApO1xuICB9XG5cbiAgYXJlQWxsU2VsZWN0ZWQoKTogYm9vbGVhbiB7XG4gICAgZm9yIChsZXQgdiBvZiB0aGlzLndlZWtzWzBdKSB7XG4gICAgICBpZiAoIXYuc2VsZWN0ZWQgJiYgIXRoaXMuaXNQYXN0KHYubURhdGUpKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgYXJlQWxsQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGZvciAobGV0IHYgb2YgdGhpcy5zb3J0ZWREYXRlcykge1xuICAgICAgaWYgKCF2LmlzRnVsbFRpbWUgJiYgdi5pc1RpbWVyVmlzaWJsZSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGxldCB2IG9mIHRoaXMud2Vla3NbMF0pIHtcbiAgICAgIGlmICghdi5zZWxlY3RlZCkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlzRnVsbFRpbWUoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIF8uZmluZEluZGV4KHRoaXMuc2VsZWN0ZWREYXRlcywgc2VsZWN0ZWREYXRlID0+IHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBtb21lbnQoZGF0ZSkuaXNTYW1lKHNlbGVjdGVkRGF0ZS5tRGF0ZSwgXCJkYXlcIikgJiZcbiAgICAgICAgICBzZWxlY3RlZERhdGUuaXNGdWxsVGltZVxuICAgICAgICApO1xuICAgICAgfSkgPiAtMVxuICAgICk7XG4gIH1cblxuICBpc1NlbGVjdGVkTW9udGgoZGF0ZTogTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIG1vbWVudChkYXRlKS5pc1NhbWUodGhpcy5jdXJyZW50RGF0ZSwgXCJtb250aFwiKTtcbiAgfVxuXG4gIGlzUGFzdChkYXRlOiBNb21lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gbW9tZW50KGRhdGUpLmlzQmVmb3JlKG1vbWVudCgpLnN1YnRyYWN0KDEsIFwiZGF5XCIpKTtcbiAgfVxuXG4gIC8vIGFjdGlvbnMgZnJvbSBjYWxlbmRhclxuXG4gIHByZXZNb250aCgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnREYXRlID0gbW9tZW50KHRoaXMuY3VycmVudERhdGUpLnN1YnRyYWN0KDEsIFwibW9udGhzXCIpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICB9XG5cbiAgbmV4dE1vbnRoKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudERhdGUgPSBtb21lbnQodGhpcy5jdXJyZW50RGF0ZSkuYWRkKDEsIFwibW9udGhzXCIpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICB9XG5cbiAgbmV4dFdlZWsoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50RGF0ZSA9IG1vbWVudCh0aGlzLmN1cnJlbnREYXRlKS5hZGQoMSwgXCJ3ZWVrXCIpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcigpO1xuICB9XG5cbiAgcHJldldlZWsoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50RGF0ZSA9IG1vbWVudCh0aGlzLmN1cnJlbnREYXRlKS5zdWJ0cmFjdCgxLCBcIndlZWtcIik7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBmaXJzdE1vbnRoKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudERhdGUgPSBtb21lbnQodGhpcy5jdXJyZW50RGF0ZSkuc3RhcnRPZihcInllYXJcIik7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBsYXN0TW9udGgoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50RGF0ZSA9IG1vbWVudCh0aGlzLmN1cnJlbnREYXRlKS5lbmRPZihcInllYXJcIik7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFyKCk7XG4gIH1cblxuICBwcmV2WWVhcigpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnREYXRlID0gbW9tZW50KHRoaXMuY3VycmVudERhdGUpLnN1YnRyYWN0KDEsIFwieWVhclwiKTtcbiAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXIoKTtcbiAgfVxuXG4gIG5leHRZZWFyKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudERhdGUgPSBtb21lbnQodGhpcy5jdXJyZW50RGF0ZSkuYWRkKDEsIFwieWVhclwiKTtcbiAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXIoKTtcbiAgfVxuXG4gIC8vIGdlbmVyYXRlIHRoZSBjYWxlbmRhciBncmlkXG5cbiAgZ2VuZXJhdGVDYWxlbmRhcigpOiB2b2lkIHtcbiAgICBjb25zdCBkYXRlcyA9IHRoaXMuZmlsbERhdGVzKHRoaXMuY3VycmVudERhdGUpO1xuICAgIGNvbnN0IHdlZWtzOiBDYWxlbmRhckRhdGVbXVtdID0gW107XG4gICAgd2hpbGUgKGRhdGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHdlZWtzLnB1c2goZGF0ZXMuc3BsaWNlKDAsIDcpKTtcbiAgICB9XG4gICAgZm9yIChsZXQgdiBvZiB0aGlzLnNvcnRlZERhdGVzKSB7XG4gICAgICB2LmlzVGltZXJWaXNpYmxlID1cbiAgICAgICAgd2Vla3NbMF1bMV0ubURhdGUud2VlaygpID09IHYubURhdGUud2VlaygpICYmICF0aGlzLmlzUGFzdCh2Lm1EYXRlKTtcbiAgICB9XG4gICAgdGhpcy53ZWVrcyA9IHdlZWtzO1xuICAgIHRoaXMuc2VsZWN0QWxsID0gdGhpcy5hcmVBbGxTZWxlY3RlZCgpO1xuICAgIHRoaXMuYXZhaWxhYmxlQWxsID0gdGhpcy5hcmVBbGxBdmFpbGFibGUoKTtcbiAgfVxuXG4gIGZpbGxEYXRlcyhjdXJyZW50TW9tZW50OiBNb21lbnQpOiBDYWxlbmRhckRhdGVbXSB7XG4gICAgaWYgKHRoaXMuY2FsZW5kYXJUeXBlID09IFwid2Vla1wiKSB7XG4gICAgICBjb25zdCBmaXJzdE9mV2VlayA9IG1vbWVudChjdXJyZW50TW9tZW50KVxuICAgICAgICAuc3RhcnRPZihcIndlZWtcIilcbiAgICAgICAgLmRheSgpO1xuICAgICAgY29uc3QgZmlyc3REYXlPZkdyaWQgPSBtb21lbnQoY3VycmVudE1vbWVudClcbiAgICAgICAgLnN0YXJ0T2YoXCJ3ZWVrXCIpXG4gICAgICAgIC5zdWJ0cmFjdChmaXJzdE9mV2VlaywgXCJkYXlzXCIpO1xuICAgICAgY29uc3Qgc3RhcnQgPSBmaXJzdERheU9mR3JpZC5kYXRlKCk7XG4gICAgICByZXR1cm4gXy5yYW5nZShzdGFydCwgc3RhcnQgKyA3KS5tYXAoXG4gICAgICAgIChkYXRlOiBudW1iZXIpOiBDYWxlbmRhckRhdGUgPT4ge1xuICAgICAgICAgIGNvbnN0IGQgPSBtb21lbnQoZmlyc3REYXlPZkdyaWQpLmRhdGUoZGF0ZSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRvZGF5OiB0aGlzLmlzVG9kYXkoZCksXG4gICAgICAgICAgICBzZWxlY3RlZDogdGhpcy5pc1NlbGVjdGVkKGQpLFxuICAgICAgICAgICAgbURhdGU6IGQsXG4gICAgICAgICAgICBzdGFydFRpbWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGVuZFRpbWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGlzVGltZXJWaXNpYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGlzRnVsbFRpbWU6IHRoaXMuaXNGdWxsVGltZShkKVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGZpcnN0T2ZNb250aCA9IG1vbWVudChjdXJyZW50TW9tZW50KVxuICAgICAgLnN0YXJ0T2YoXCJtb250aFwiKVxuICAgICAgLmRheSgpO1xuICAgIGNvbnN0IGZpcnN0RGF5T2ZHcmlkID0gbW9tZW50KGN1cnJlbnRNb21lbnQpXG4gICAgICAuc3RhcnRPZihcIm1vbnRoXCIpXG4gICAgICAuc3VidHJhY3QoZmlyc3RPZk1vbnRoLCBcImRheXNcIik7XG4gICAgY29uc3Qgc3RhcnQgPSBmaXJzdERheU9mR3JpZC5kYXRlKCk7XG4gICAgcmV0dXJuIF8ucmFuZ2Uoc3RhcnQsIHN0YXJ0ICsgMzUpLm1hcChcbiAgICAgIChkYXRlOiBudW1iZXIpOiBDYWxlbmRhckRhdGUgPT4ge1xuICAgICAgICBjb25zdCBkID0gbW9tZW50KGZpcnN0RGF5T2ZHcmlkKS5kYXRlKGRhdGUpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHRvZGF5OiB0aGlzLmlzVG9kYXkoZCksXG4gICAgICAgICAgc2VsZWN0ZWQ6IHRoaXMuaXNTZWxlY3RlZChkKSxcbiAgICAgICAgICBtRGF0ZTogZCxcbiAgICAgICAgICBzdGFydFRpbWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICBlbmRUaW1lOiB1bmRlZmluZWQsXG4gICAgICAgICAgaXNUaW1lclZpc2libGU6IGZhbHNlLFxuICAgICAgICAgIGlzRnVsbFRpbWU6IHRoaXMuaXNGdWxsVGltZShkKVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICB0aW1lQ2hhbmdlZCh2YWwpIHtcbiAgICB2YWwuaXNGdWxsVGltZSA9XG4gICAgICB2YWwuc3RhcnRUaW1lID09IFwiMDA6MDBcIiAmJlxuICAgICAgdmFsLmVuZFRpbWUgPT0gXCIyMzo1OVwiICYmXG4gICAgdGhpcy53ZWVrc1swXS5tYXAodiA9PiB7XG4gICAgICBpZiAodi5tRGF0ZS5mb3JtYXQoXCJsbFwiKSA9PSB2YWwubURhdGUuZm9ybWF0KFwibGxcIikpIHtcbiAgICAgICAgdi5pc0Z1bGxUaW1lID0gdmFsLmlzRnVsbFRpbWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5hdmFpbGFibGVBbGwgPSB0aGlzLmFyZUFsbEF2YWlsYWJsZSgpO1xuICAgIHRoaXMub25TZWxlY3REYXRlLmVtaXQodGhpcy5zb3J0ZWREYXRlcyk7XG4gIH1cblxuICBmdWxsVGltZUNoZWNrZWQodmFsKSB7XG4gICAgdmFsLnN0YXJ0VGltZSA9IHZhbC5pc0Z1bGxUaW1lID8gXCIwMDowMFwiIDogXCJcIjtcbiAgICB2YWwuZW5kVGltZSA9IHZhbC5pc0Z1bGxUaW1lID8gXCIyMzo1OVwiIDogXCJcIjtcbiAgICBmb3IgKGxldCB2IGluIHRoaXMuc29ydGVkRGF0ZXMpIHtcbiAgICAgIGlmICh0aGlzLnNvcnRlZERhdGVzW3ZdLm1EYXRlLmZvcm1hdChcImxsXCIpID09IHZhbC5tRGF0ZS5mb3JtYXQoXCJsbFwiKSkge1xuICAgICAgICB0aGlzLnNvcnRlZERhdGVzW3ZdLnN0YXJ0VGltZSA9IHZhbC5zdGFydFRpbWU7XG4gICAgICAgIHRoaXMuc29ydGVkRGF0ZXNbdl0uZW5kVGltZSA9IHZhbC5lbmRUaW1lO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnRpbWVDaGFuZ2VkKHZhbCk7XG4gIH1cblxuICBzZWxlY3RBbGxDaGVja2VkKCkge1xuICAgIGZvciAobGV0IHYgb2YgdGhpcy53ZWVrc1swXSkge1xuICAgICAgdi5zZWxlY3RlZCA9IHRoaXMuc2VsZWN0QWxsO1xuICAgICAgdGhpcy5zZWxlY3REYXRlKHYpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGF2YWlsYWJsZUFsbENoZWNrZWQoKSB7XG4gICAgdGhpcy5hdmFpbGFibGVBbGwgPSAhdGhpcy5hdmFpbGFibGVBbGw7XG4gICAgZm9yIChsZXQgdiBvZiB0aGlzLnNvcnRlZERhdGVzKSB7XG4gICAgICB2LmlzRnVsbFRpbWUgPSB2LmlzVGltZXJWaXNpYmxlID8gdGhpcy5hdmFpbGFibGVBbGwgOiB2LmlzRnVsbFRpbWU7XG4gICAgICB2LnN0YXJ0VGltZSA9IHYuaXNGdWxsVGltZSA/IFwiMDA6MDBcIiA6IFwiXCI7XG4gICAgICB2LmVuZFRpbWUgPSB2LmlzRnVsbFRpbWUgPyBcIjIzOjU5XCIgOiBcIlwiO1xuICAgICAgdGhpcy53ZWVrc1swXS5tYXAodmFsID0+IHtcbiAgICAgICAgaWYgKHZhbC5tRGF0ZS5mb3JtYXQoXCJsbFwiKSA9PSB2Lm1EYXRlLmZvcm1hdChcImxsXCIpKSB7XG4gICAgICAgICAgdmFsLmlzRnVsbFRpbWUgPSB2LmlzRnVsbFRpbWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLm9uU2VsZWN0RGF0ZS5lbWl0KHRoaXMuc29ydGVkRGF0ZXMpO1xuICB9XG5cbiAgdGltZVNlbGVjdGVkKCkge1xuICAgIHRoaXMub25TZWxlY3REYXRlLmVtaXQodGhpcy5zb3J0ZWREYXRlcyk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBDYWxlbmRhckRhdGUge1xuICBtRGF0ZTogTW9tZW50O1xuICBzZWxlY3RlZD86IGJvb2xlYW47XG4gIHRvZGF5PzogYm9vbGVhbjtcbiAgc3RhcnRUaW1lOiBzdHJpbmc7XG4gIGVuZFRpbWU6IHN0cmluZztcbiAgaXNUaW1lclZpc2libGU/OiBib29sZWFuO1xuICBpc0Z1bGxUaW1lPzogYm9vbGVhbjtcbn1cbiJdfQ==