UNPKG

axiros-datetime-picker

Version:
379 lines 62.7 kB
/** * date-time-picker-container.component */ import { ChangeDetectionStrategy, Component, Optional, ViewChild } from '@angular/core'; import { OwlCalendarComponent } from './calendar.component'; import { OwlTimerComponent } from './timer.component'; import { Subject } from 'rxjs'; import { owlDateTimePickerAnimations } from './date-time-picker.animations'; import { DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, SPACE, UP_ARROW } from '@angular/cdk/keycodes'; import * as i0 from "@angular/core"; import * as i1 from "./date-time-picker-intl.service"; import * as i2 from "./adapter/date-time-adapter.class"; import * as i3 from "./calendar.component"; import * as i4 from "./timer.component"; import * as i5 from "@angular/cdk/a11y"; import * as i6 from "@angular/common"; export class OwlDateTimeContainerComponent { constructor(cdRef, elmRef, pickerIntl, dateTimeAdapter) { this.cdRef = cdRef; this.elmRef = elmRef; this.pickerIntl = pickerIntl; this.dateTimeAdapter = dateTimeAdapter; this.activeSelectedIndex = 0; // The current active SelectedIndex in range select mode (0: 'from', 1: 'to') /** * Stream emits when try to hide picker */ this.hidePicker$ = new Subject(); /** * Stream emits when try to confirm the selected value */ this.confirmSelected$ = new Subject(); this.pickerOpened$ = new Subject(); } get hidePickerStream() { return this.hidePicker$.asObservable(); } get confirmSelectedStream() { return this.confirmSelected$.asObservable(); } get pickerOpenedStream() { return this.pickerOpened$.asObservable(); } get pickerMoment() { return this._clamPickerMoment; } set pickerMoment(value) { if (value) { this._clamPickerMoment = this.dateTimeAdapter.clampDate(value, this.picker.minDateTime, this.picker.maxDateTime); } this.cdRef.markForCheck(); } get pickerType() { return this.picker.pickerType; } get cancelLabel() { return this.pickerIntl.cancelBtnLabel; } get setLabel() { return this.pickerIntl.setBtnLabel; } /** * The range 'from' label */ get fromLabel() { return this.pickerIntl.rangeFromLabel; } /** * The range 'to' label */ get toLabel() { return this.pickerIntl.rangeToLabel; } /** * The range 'from' formatted value */ get fromFormattedValue() { const value = this.picker.selecteds[0]; return value ? this.dateTimeAdapter.format(value, this.picker.formatString) : ''; } /** * The range 'to' formatted value */ get toFormattedValue() { const value = this.picker.selecteds[1]; return value ? this.dateTimeAdapter.format(value, this.picker.formatString) : ''; } /** * Cases in which the control buttons show in the picker * 1) picker mode is 'dialog' * 2) picker type is NOT 'calendar' and the picker mode is NOT 'inline' */ get showControlButtons() { return (this.picker.pickerMode === 'dialog' || (this.picker.pickerType !== 'calendar' && this.picker.pickerMode !== 'inline')); } get containerElm() { return this.elmRef.nativeElement; } get owlDTContainerClass() { return true; } get owlDTPopupContainerClass() { return this.picker.pickerMode === 'popup'; } get owlDTDialogContainerClass() { return this.picker.pickerMode === 'dialog'; } get owlDTInlineContainerClass() { return this.picker.pickerMode === 'inline'; } get owlDTContainerDisabledClass() { return this.picker.disabled; } get owlDTContainerId() { return this.picker.id; } get owlDTContainerAnimation() { return this.picker.pickerMode === 'inline' ? '' : 'enter'; } ngOnInit() { } ngAfterContentInit() { this.initPicker(); } ngAfterViewInit() { this.focusPicker(); } handleContainerAnimationDone(event) { const toState = event.toState; if (toState === 'enter') { this.pickerOpened$.next(); } } dateSelected(date) { let result; if (this.picker.isInSingleMode) { result = this.dateSelectedInSingleMode(date); if (result) { this.pickerMoment = result; this.picker.select(result); } else { // we close the picker when result is null and pickerType is calendar. if (this.pickerType === 'calendar') { this.hidePicker$.next(null); } } return; } if (this.picker.isInRangeMode) { result = this.dateSelectedInRangeMode(date); if (result) { this.pickerMoment = result[this.activeSelectedIndex]; this.picker.select(result); } } } timeSelected(time) { this.pickerMoment = this.dateTimeAdapter.clone(time); if (!this.picker.dateTimeChecker(this.pickerMoment)) { return; } if (this.picker.isInSingleMode) { this.picker.select(this.pickerMoment); return; } if (this.picker.isInRangeMode) { const selecteds = [...this.picker.selecteds]; // check if the 'from' is after 'to' or 'to'is before 'from' // In this case, we set both the 'from' and 'to' the same value if ((this.activeSelectedIndex === 0 && selecteds[1] && this.dateTimeAdapter.compare(this.pickerMoment, selecteds[1]) === 1) || (this.activeSelectedIndex === 1 && selecteds[0] && this.dateTimeAdapter.compare(this.pickerMoment, selecteds[0]) === -1)) { selecteds[0] = this.pickerMoment; selecteds[1] = this.pickerMoment; } else { selecteds[this.activeSelectedIndex] = this.pickerMoment; } this.picker.select(selecteds); } } /** * Handle click on cancel button */ onCancelClicked(event) { this.hidePicker$.next(null); event.preventDefault(); return; } /** * Handle click on set button */ onSetClicked(event) { if (!this.picker.dateTimeChecker(this.pickerMoment)) { this.hidePicker$.next(null); event.preventDefault(); return; } this.confirmSelected$.next(event); event.preventDefault(); return; } /** * Handle click on inform radio group */ handleClickOnInfoGroup(event, index) { this.setActiveSelectedIndex(index); event.preventDefault(); event.stopPropagation(); } /** * Handle click on inform radio group */ handleKeydownOnInfoGroup(event, next, index) { switch (event.keyCode) { case DOWN_ARROW: case RIGHT_ARROW: case UP_ARROW: case LEFT_ARROW: next.focus(); this.setActiveSelectedIndex(index === 0 ? 1 : 0); event.preventDefault(); event.stopPropagation(); break; case SPACE: this.setActiveSelectedIndex(index); event.preventDefault(); event.stopPropagation(); break; default: return; } } /** * Set the value of activeSelectedIndex */ setActiveSelectedIndex(index) { if (this.picker.selectMode === 'range' && this.activeSelectedIndex !== index) { this.activeSelectedIndex = index; const selected = this.picker.selecteds[this.activeSelectedIndex]; if (this.picker.selecteds && selected) { this.pickerMoment = this.dateTimeAdapter.clone(selected); } } return; } initPicker() { this.pickerMoment = this.picker.startAt || this.dateTimeAdapter.now(); this.activeSelectedIndex = this.picker.selectMode === 'rangeTo' ? 1 : 0; } /** * Select calendar date in single mode, * it returns null when date is not selected. */ dateSelectedInSingleMode(date) { if (this.dateTimeAdapter.isSameDay(date, this.picker.selected)) { return null; } return this.updateAndCheckCalendarDate(date); } /** * Select dates in range Mode */ dateSelectedInRangeMode(date) { let from = this.picker.selecteds[0]; let to = this.picker.selecteds[1]; const result = this.updateAndCheckCalendarDate(date); if (!result) { return null; } // if the given calendar day is after or equal to 'from', // set ths given date as 'to' // otherwise, set it as 'from' and set 'to' to null if (this.picker.selectMode === 'range') { if (this.picker.selecteds && this.picker.selecteds.length && !to && from && this.dateTimeAdapter.differenceInCalendarDays(result, from) >= 0) { to = result; this.activeSelectedIndex = 1; } else { from = result; to = null; this.activeSelectedIndex = 0; } } else if (this.picker.selectMode === 'rangeFrom') { from = result; // if the from value is after the to value, set the to value as null if (to && this.dateTimeAdapter.compare(from, to) > 0) { to = null; } } else if (this.picker.selectMode === 'rangeTo') { to = result; // if the from value is after the to value, set the from value as null if (from && this.dateTimeAdapter.compare(from, to) > 0) { from = null; } } return [from, to]; } /** * Update the given calendar date's time and check if it is valid * Because the calendar date has 00:00:00 as default time, if the picker type is 'both', * we need to update the given calendar date's time before selecting it. * if it is valid, return the updated dateTime * if it is not valid, return null */ updateAndCheckCalendarDate(date) { let result; // if the picker is 'both', update the calendar date's time value if (this.picker.pickerType === 'both') { result = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(date), this.dateTimeAdapter.getMonth(date), this.dateTimeAdapter.getDate(date), this.dateTimeAdapter.getHours(this.pickerMoment), this.dateTimeAdapter.getMinutes(this.pickerMoment), this.dateTimeAdapter.getSeconds(this.pickerMoment)); result = this.dateTimeAdapter.clampDate(result, this.picker.minDateTime, this.picker.maxDateTime); } else { result = this.dateTimeAdapter.clone(date); } // check the updated dateTime return this.picker.dateTimeChecker(result) ? result : null; } /** * Focus to the picker */ focusPicker() { if (this.picker.pickerMode === 'inline') { return; } if (this.calendar) { this.calendar.focusActiveCell(); } else if (this.timer) { this.timer.focus(); } } } /** @nocollapse */ OwlDateTimeContainerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: OwlDateTimeContainerComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i1.OwlDateTimeIntl }, { token: i2.DateTimeAdapter, optional: true }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ OwlDateTimeContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: OwlDateTimeContainerComponent, selector: "owl-date-time-container", host: { listeners: { "@transformPicker.done": "handleContainerAnimationDone($event)" }, properties: { "class.owl-dt-container": "owlDTContainerClass", "class.owl-dt-popup-container": "owlDTPopupContainerClass", "class.owl-dt-dialog-container": "owlDTDialogContainerClass", "class.owl-dt-inline-container": "owlDTInlineContainerClass", "class.owl-dt-container-disabled": "owlDTContainerDisabledClass", "attr.id": "owlDTContainerId", "@transformPicker": "owlDTContainerAnimation" } }, viewQueries: [{ propertyName: "calendar", first: true, predicate: OwlCalendarComponent, descendants: true }, { propertyName: "timer", first: true, predicate: OwlTimerComponent, descendants: true }], exportAs: ["owlDateTimeContainer"], ngImport: i0, template: "<div [cdkTrapFocus]=\"picker.pickerMode !== 'inline'\"\n [@fadeInPicker]=\"picker.pickerMode === 'inline'? '' : 'enter'\"\n class=\"owl-dt-container-inner\">\n\n <owl-date-time-calendar\n *ngIf=\"pickerType === 'both' || pickerType === 'calendar'\"\n class=\"owl-dt-container-row\"\n [firstDayOfWeek]=\"picker.firstDayOfWeek\"\n [(pickerMoment)]=\"pickerMoment\"\n [selected]=\"picker.selected\"\n [selecteds]=\"picker.selecteds\"\n [selectMode]=\"picker.selectMode\"\n [minDate]=\"picker.minDateTime\"\n [maxDate]=\"picker.maxDateTime\"\n [dateFilter]=\"picker.dateTimeFilter\"\n [startView]=\"picker.startView\"\n [hideOtherMonths]=\"picker.hideOtherMonths\"\n (yearSelected)=\"picker.selectYear($event)\"\n (monthSelected)=\"picker.selectMonth($event)\"\n (selectedChange)=\"dateSelected($event)\"></owl-date-time-calendar>\n\n <owl-date-time-timer\n *ngIf=\"pickerType === 'both' || pickerType === 'timer'\"\n class=\"owl-dt-container-row\"\n [pickerMoment]=\"pickerMoment\"\n [minDateTime]=\"picker.minDateTime\"\n [maxDateTime]=\"picker.maxDateTime\"\n [showSecondsTimer]=\"picker.showSecondsTimer\"\n [hour12Timer]=\"picker.hour12Timer\"\n [stepHour]=\"picker.stepHour\"\n [stepMinute]=\"picker.stepMinute\"\n [stepSecond]=\"picker.stepSecond\"\n (selectedChange)=\"timeSelected($event)\"></owl-date-time-timer>\n\n <div *ngIf=\"picker.isInRangeMode\"\n role=\"radiogroup\"\n class=\"owl-dt-container-info owl-dt-container-row\">\n <div role=\"radio\" [tabindex]=\"activeSelectedIndex === 0 ? 0 : -1\"\n [attr.aria-checked]=\"activeSelectedIndex === 0\"\n class=\"owl-dt-control owl-dt-container-range owl-dt-container-from\"\n [ngClass]=\"{'owl-dt-container-info-active': activeSelectedIndex === 0}\"\n (click)=\"handleClickOnInfoGroup($event, 0)\"\n (keydown)=\"handleKeydownOnInfoGroup($event, to, 0)\" #from>\n <span class=\"owl-dt-control-content owl-dt-container-range-content\" tabindex=\"-1\">\n <span class=\"owl-dt-container-info-label\">{{fromLabel}}:</span>\n <span class=\"owl-dt-container-info-value\">{{fromFormattedValue}}</span>\n </span>\n </div>\n <div role=\"radio\" [tabindex]=\"activeSelectedIndex === 1 ? 0 : -1\"\n [attr.aria-checked]=\"activeSelectedIndex === 1\"\n class=\"owl-dt-control owl-dt-container-range owl-dt-container-to\"\n [ngClass]=\"{'owl-dt-container-info-active': activeSelectedIndex === 1}\"\n (click)=\"handleClickOnInfoGroup($event, 1)\"\n (keydown)=\"handleKeydownOnInfoGroup($event, from, 1)\" #to>\n <span class=\"owl-dt-control-content owl-dt-container-range-content\" tabindex=\"-1\">\n <span class=\"owl-dt-container-info-label\">{{toLabel}}:</span>\n <span class=\"owl-dt-container-info-value\">{{toFormattedValue}}</span>\n </span>\n </div>\n </div>\n\n <div *ngIf=\"showControlButtons\" class=\"owl-dt-container-buttons owl-dt-container-row\">\n <button class=\"owl-dt-control owl-dt-control-button owl-dt-container-control-button\"\n type=\"button\" tabindex=\"0\"\n (click)=\"onCancelClicked($event)\">\n <span class=\"owl-dt-control-content owl-dt-control-button-content\" tabindex=\"-1\">\n {{cancelLabel}}\n </span>\n </button>\n <button class=\"owl-dt-control owl-dt-control-button owl-dt-container-control-button\"\n type=\"button\" tabindex=\"0\"\n (click)=\"onSetClicked($event)\">\n <span class=\"owl-dt-control-content owl-dt-control-button-content\" tabindex=\"-1\">\n {{setLabel}}\n </span>\n </button>\n </div>\n</div>\n", styles: [""], components: [{ type: i3.OwlCalendarComponent, selector: "owl-date-time-calendar", inputs: ["dateFilter", "firstDayOfWeek", "minDate", "maxDate", "pickerMoment", "selectMode", "selected", "selecteds", "startView", "hideOtherMonths"], outputs: ["pickerMomentChange", "selectedChange", "userSelection", "yearSelected", "monthSelected"], exportAs: ["owlDateTimeCalendar"] }, { type: i4.OwlTimerComponent, selector: "owl-date-time-timer", inputs: ["pickerMoment", "minDateTime", "maxDateTime", "showSecondsTimer", "hour12Timer", "stepHour", "stepMinute", "stepSecond"], outputs: ["selectedChange"], exportAs: ["owlDateTimeTimer"] }], directives: [{ type: i5.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], animations: [ owlDateTimePickerAnimations.transformPicker, owlDateTimePickerAnimations.fadeInPicker ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: OwlDateTimeContainerComponent, decorators: [{ type: Component, args: [{ exportAs: 'owlDateTimeContainer', selector: 'owl-date-time-container', changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, animations: [ owlDateTimePickerAnimations.transformPicker, owlDateTimePickerAnimations.fadeInPicker ], host: { '(@transformPicker.done)': 'handleContainerAnimationDone($event)', '[class.owl-dt-container]': 'owlDTContainerClass', '[class.owl-dt-popup-container]': 'owlDTPopupContainerClass', '[class.owl-dt-dialog-container]': 'owlDTDialogContainerClass', '[class.owl-dt-inline-container]': 'owlDTInlineContainerClass', '[class.owl-dt-container-disabled]': 'owlDTContainerDisabledClass', '[attr.id]': 'owlDTContainerId', '[@transformPicker]': 'owlDTContainerAnimation', }, template: "<div [cdkTrapFocus]=\"picker.pickerMode !== 'inline'\"\n [@fadeInPicker]=\"picker.pickerMode === 'inline'? '' : 'enter'\"\n class=\"owl-dt-container-inner\">\n\n <owl-date-time-calendar\n *ngIf=\"pickerType === 'both' || pickerType === 'calendar'\"\n class=\"owl-dt-container-row\"\n [firstDayOfWeek]=\"picker.firstDayOfWeek\"\n [(pickerMoment)]=\"pickerMoment\"\n [selected]=\"picker.selected\"\n [selecteds]=\"picker.selecteds\"\n [selectMode]=\"picker.selectMode\"\n [minDate]=\"picker.minDateTime\"\n [maxDate]=\"picker.maxDateTime\"\n [dateFilter]=\"picker.dateTimeFilter\"\n [startView]=\"picker.startView\"\n [hideOtherMonths]=\"picker.hideOtherMonths\"\n (yearSelected)=\"picker.selectYear($event)\"\n (monthSelected)=\"picker.selectMonth($event)\"\n (selectedChange)=\"dateSelected($event)\"></owl-date-time-calendar>\n\n <owl-date-time-timer\n *ngIf=\"pickerType === 'both' || pickerType === 'timer'\"\n class=\"owl-dt-container-row\"\n [pickerMoment]=\"pickerMoment\"\n [minDateTime]=\"picker.minDateTime\"\n [maxDateTime]=\"picker.maxDateTime\"\n [showSecondsTimer]=\"picker.showSecondsTimer\"\n [hour12Timer]=\"picker.hour12Timer\"\n [stepHour]=\"picker.stepHour\"\n [stepMinute]=\"picker.stepMinute\"\n [stepSecond]=\"picker.stepSecond\"\n (selectedChange)=\"timeSelected($event)\"></owl-date-time-timer>\n\n <div *ngIf=\"picker.isInRangeMode\"\n role=\"radiogroup\"\n class=\"owl-dt-container-info owl-dt-container-row\">\n <div role=\"radio\" [tabindex]=\"activeSelectedIndex === 0 ? 0 : -1\"\n [attr.aria-checked]=\"activeSelectedIndex === 0\"\n class=\"owl-dt-control owl-dt-container-range owl-dt-container-from\"\n [ngClass]=\"{'owl-dt-container-info-active': activeSelectedIndex === 0}\"\n (click)=\"handleClickOnInfoGroup($event, 0)\"\n (keydown)=\"handleKeydownOnInfoGroup($event, to, 0)\" #from>\n <span class=\"owl-dt-control-content owl-dt-container-range-content\" tabindex=\"-1\">\n <span class=\"owl-dt-container-info-label\">{{fromLabel}}:</span>\n <span class=\"owl-dt-container-info-value\">{{fromFormattedValue}}</span>\n </span>\n </div>\n <div role=\"radio\" [tabindex]=\"activeSelectedIndex === 1 ? 0 : -1\"\n [attr.aria-checked]=\"activeSelectedIndex === 1\"\n class=\"owl-dt-control owl-dt-container-range owl-dt-container-to\"\n [ngClass]=\"{'owl-dt-container-info-active': activeSelectedIndex === 1}\"\n (click)=\"handleClickOnInfoGroup($event, 1)\"\n (keydown)=\"handleKeydownOnInfoGroup($event, from, 1)\" #to>\n <span class=\"owl-dt-control-content owl-dt-container-range-content\" tabindex=\"-1\">\n <span class=\"owl-dt-container-info-label\">{{toLabel}}:</span>\n <span class=\"owl-dt-container-info-value\">{{toFormattedValue}}</span>\n </span>\n </div>\n </div>\n\n <div *ngIf=\"showControlButtons\" class=\"owl-dt-container-buttons owl-dt-container-row\">\n <button class=\"owl-dt-control owl-dt-control-button owl-dt-container-control-button\"\n type=\"button\" tabindex=\"0\"\n (click)=\"onCancelClicked($event)\">\n <span class=\"owl-dt-control-content owl-dt-control-button-content\" tabindex=\"-1\">\n {{cancelLabel}}\n </span>\n </button>\n <button class=\"owl-dt-control owl-dt-control-button owl-dt-container-control-button\"\n type=\"button\" tabindex=\"0\"\n (click)=\"onSetClicked($event)\">\n <span class=\"owl-dt-control-content owl-dt-control-button-content\" tabindex=\"-1\">\n {{setLabel}}\n </span>\n </button>\n </div>\n</div>\n", styles: [""] }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i1.OwlDateTimeIntl }, { type: i2.DateTimeAdapter, decorators: [{ type: Optional }] }]; }, propDecorators: { calendar: [{ type: ViewChild, args: [OwlCalendarComponent, { static: false }] }], timer: [{ type: ViewChild, args: [OwlTimerComponent, { static: false }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS10aW1lLXBpY2tlci1jb250YWluZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvcGlja2VyL3NyYy9saWIvZGF0ZS10aW1lL2RhdGUtdGltZS1waWNrZXItY29udGFpbmVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3BpY2tlci9zcmMvbGliL2RhdGUtdGltZS9kYXRlLXRpbWUtcGlja2VyLWNvbnRhaW5lci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILE9BQU8sRUFHSCx1QkFBdUIsRUFFdkIsU0FBUyxFQUdULFFBQVEsRUFDUixTQUFTLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDMUQsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFHcEQsT0FBTyxFQUFhLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUN6QyxPQUFPLEVBQUMsMkJBQTJCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUMxRSxPQUFPLEVBQ0gsVUFBVSxFQUNWLFVBQVUsRUFDVixXQUFXLEVBQ1gsS0FBSyxFQUNMLFFBQVEsRUFDWCxNQUFNLHVCQUF1QixDQUFDOzs7Ozs7OztBQXdCL0IsTUFBTSxPQUFPLDZCQUE2QjtJQWlKdEMsWUFBb0IsS0FBd0IsRUFDeEIsTUFBa0IsRUFDbEIsVUFBMkIsRUFDZixlQUFtQztRQUgvQyxVQUFLLEdBQUwsS0FBSyxDQUFtQjtRQUN4QixXQUFNLEdBQU4sTUFBTSxDQUFZO1FBQ2xCLGVBQVUsR0FBVixVQUFVLENBQWlCO1FBQ2Ysb0JBQWUsR0FBZixlQUFlLENBQW9CO1FBN0k1RCx3QkFBbUIsR0FBRyxDQUFDLENBQUMsQ0FBQyw2RUFBNkU7UUFFN0c7O1dBRUc7UUFDSyxnQkFBVyxHQUFHLElBQUksT0FBTyxFQUFPLENBQUM7UUFNekM7O1dBRUc7UUFDSyxxQkFBZ0IsR0FBRyxJQUFJLE9BQU8sRUFBTyxDQUFDO1FBTXRDLGtCQUFhLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQTBINUMsQ0FBQztJQXZJRCxJQUFJLGdCQUFnQjtRQUNoQixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDM0MsQ0FBQztJQU9ELElBQUkscUJBQXFCO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ2hELENBQUM7SUFJRCxJQUFJLGtCQUFrQjtRQUNsQixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQVFELElBQUksWUFBWTtRQUNaLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDO0lBQ2xDLENBQUM7SUFFRCxJQUFJLFlBQVksQ0FBQyxLQUFRO1FBQ3JCLElBQUksS0FBSyxFQUFFO1lBQ1AsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUNuRCxLQUFLLEVBQ0wsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUMxQixDQUFDO1NBQ0w7UUFDRCxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDVixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO0lBQ2xDLENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDWCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO0lBQzFDLENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDUixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksU0FBUztRQUNULE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUM7SUFDMUMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxPQUFPO1FBQ1AsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQztJQUN4QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLGtCQUFrQjtRQUNsQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QyxPQUFPLEtBQUs7WUFDUixDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDO1lBQzlELENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDYixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLGdCQUFnQjtRQUNoQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QyxPQUFPLEtBQUs7WUFDUixDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDO1lBQzlELENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQUksa0JBQWtCO1FBQ2xCLE9BQU8sQ0FDSCxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxRQUFRO1lBQ25DLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssVUFBVTtnQkFDbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssUUFBUSxDQUFDLENBQzNDLENBQUM7SUFDTixDQUFDO0lBRUQsSUFBSSxZQUFZO1FBQ1osT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQztJQUNyQyxDQUFDO0lBRUQsSUFBSSxtQkFBbUI7UUFDbkIsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELElBQUksd0JBQXdCO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssT0FBTyxDQUFDO0lBQzlDLENBQUM7SUFFRCxJQUFJLHlCQUF5QjtRQUN6QixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxLQUFLLFFBQVEsQ0FBQztJQUMvQyxDQUFDO0lBRUQsSUFBSSx5QkFBeUI7UUFDekIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxRQUFRLENBQUM7SUFDL0MsQ0FBQztJQUVELElBQUksMkJBQTJCO1FBQzNCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7SUFDaEMsQ0FBQztJQUVELElBQUksZ0JBQWdCO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELElBQUksdUJBQXVCO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUM5RCxDQUFDO0lBUU0sUUFBUTtJQUNmLENBQUM7SUFFTSxrQkFBa0I7UUFDckIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFTSxlQUFlO1FBQ2xCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRU0sNEJBQTRCLENBQUMsS0FBcUI7UUFDckQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUM5QixJQUFJLE9BQU8sS0FBSyxPQUFPLEVBQUU7WUFDckIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUM3QjtJQUNMLENBQUM7SUFFTSxZQUFZLENBQUMsSUFBTztRQUN2QixJQUFJLE1BQU0sQ0FBQztRQUVYLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUU7WUFDNUIsTUFBTSxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM3QyxJQUFJLE1BQU0sRUFBRTtnQkFDUixJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQztnQkFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDOUI7aUJBQU07Z0JBQ0gsc0VBQXNFO2dCQUN0RSxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFO29CQUNoQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztpQkFDL0I7YUFDSjtZQUNELE9BQU87U0FDVjtRQUVELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUU7WUFDM0IsTUFBTSxHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1QyxJQUFJLE1BQU0sRUFBRTtnQkFDUixJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztnQkFDckQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDOUI7U0FDSjtJQUNMLENBQUM7SUFFTSxZQUFZLENBQUMsSUFBTztRQUN2QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXJELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFDakQsT0FBTztTQUNWO1FBRUQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRTtZQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdEMsT0FBTztTQUNWO1FBRUQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRTtZQUMzQixNQUFNLFNBQVMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUU3Qyw0REFBNEQ7WUFDNUQsK0RBQStEO1lBQy9ELElBQ0ksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEtBQUssQ0FBQztnQkFDM0IsU0FBUyxDQUFDLENBQUMsQ0FBQztnQkFDWixJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FDeEIsSUFBSSxDQUFDLFlBQVksRUFDakIsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUNmLEtBQUssQ0FBQyxDQUFDO2dCQUNaLENBQUMsSUFBSSxDQUFDLG1CQUFtQixLQUFLLENBQUM7b0JBQzNCLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQ1osSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQ3hCLElBQUksQ0FBQyxZQUFZLEVBQ2pCLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FDZixLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQ2Y7Z0JBQ0UsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7Z0JBQ2pDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO2FBQ3BDO2lCQUFNO2dCQUNILFNBQVMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO2FBQzNEO1lBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDakM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxlQUFlLENBQUMsS0FBVTtRQUM3QixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsT0FBTztJQUNYLENBQUM7SUFFRDs7T0FFRztJQUNJLFlBQVksQ0FBQyxLQUFVO1FBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFDakQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUIsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3ZCLE9BQU87U0FDVjtRQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEMsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU87SUFDWCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxzQkFBc0IsQ0FBQyxLQUFVLEVBQUUsS0FBYTtRQUNuRCxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkMsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQ7O09BRUc7SUFDSSx3QkFBd0IsQ0FDM0IsS0FBVSxFQUNWLElBQVMsRUFDVCxLQUFhO1FBRWIsUUFBUSxLQUFLLENBQUMsT0FBTyxFQUFFO1lBQ25CLEtBQUssVUFBVSxDQUFDO1lBQ2hCLEtBQUssV0FBVyxDQUFDO1lBQ2pCLEtBQUssUUFBUSxDQUFDO1lBQ2QsS0FBSyxVQUFVO2dCQUNYLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDYixJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDakQsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN2QixLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3hCLE1BQU07WUFFVixLQUFLLEtBQUs7Z0JBQ04sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNuQyxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQ3ZCLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDeEIsTUFBTTtZQUVWO2dCQUNJLE9BQU87U0FDZDtJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLHNCQUFzQixDQUFDLEtBQWE7UUFDeEMsSUFDSSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxPQUFPO1lBQ2xDLElBQUksQ0FBQyxtQkFBbUIsS0FBSyxLQUFLLEVBQ3BDO1lBQ0UsSUFBSSxDQUFDLG1CQUFtQixHQUFHLEtBQUssQ0FBQztZQUVqQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUNqRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLFFBQVEsRUFBRTtnQkFDbkMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUM1RDtTQUNKO1FBQ0QsT0FBTztJQUNYLENBQUM7SUFFTyxVQUFVO1FBQ2QsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3RFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRDs7O09BR0c7SUFDSyx3QkFBd0IsQ0FBQyxJQUFPO1FBQ3BDLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDNUQsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELE9BQU8sSUFBSSxDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRDs7T0FFRztJQUNLLHVCQUF1QixDQUFDLElBQU87UUFDbkMsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFbEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXJELElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDVCxPQUFPLElBQUksQ0FBQztTQUNmO1FBRUQseURBQXlEO1FBQ3pELDZCQUE2QjtRQUM3QixtREFBbUQ7UUFDbkQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxPQUFPLEVBQUU7WUFDcEMsSUFDSSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVM7Z0JBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU07Z0JBQzVCLENBQUMsRUFBRTtnQkFDSCxJQUFJO2dCQUNKLElBQUksQ0FBQyxlQUFlLENBQUMsd0JBQXdCLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsRUFDbEU7Z0JBQ0UsRUFBRSxHQUFHLE1BQU0sQ0FBQztnQkFDWixJQUFJLENBQUMsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO2FBQ2hDO2lCQUFNO2dCQUNILElBQUksR0FBRyxNQUFNLENBQUM7Z0JBQ2QsRUFBRSxHQUFHLElBQUksQ0FBQztnQkFDVixJQUFJLENBQUMsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO2FBQ2hDO1NBQ0o7YUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxLQUFLLFdBQVcsRUFBRTtZQUMvQyxJQUFJLEdBQUcsTUFBTSxDQUFDO1lBRWQsb0VBQW9FO1lBQ3BFLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQ2xELEVBQUUsR0FBRyxJQUFJLENBQUM7YUFDYjtTQUNKO2FBQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUU7WUFDN0MsRUFBRSxHQUFHLE1BQU0sQ0FBQztZQUVaLHNFQUFzRTtZQUN0RSxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUNwRCxJQUFJLEdBQUcsSUFBSSxDQUFDO2FBQ2Y7U0FDSjtRQUVELE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNLLDBCQUEwQixDQUFDLElBQU87UUFDdEMsSUFBSSxNQUFNLENBQUM7UUFFWCxpRUFBaUU7UUFDakUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxNQUFNLEVBQUU7WUFDbkMsTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUNwQyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFDbEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQ25DLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUNsQyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQ2hELElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFDbEQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUNyRCxDQUFDO1lBQ0YsTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUNuQyxNQUFNLEVBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUMxQixDQUFDO1NBQ0w7YUFBTTtZQUNILE1BQU0sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUM3QztRQUVELDZCQUE2QjtRQUM3QixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUMvRCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxXQUFXO1FBQ2YsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxRQUFRLEVBQUU7WUFDckMsT0FBTztTQUNWO1FBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLEVBQUUsQ0FBQztTQUNuQzthQUFNLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNuQixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ3RCO0lBQ0wsQ0FBQzs7OElBOWFRLDZCQUE2QjtrSUFBN0IsNkJBQTZCLDRrQkFDM0Isb0JBQW9CLHdFQUVwQixpQkFBaUIsb0ZDeERoQywyaUlBOEVBLG04QkR4Q2dCO1FBQ1IsMkJBQTJCLENBQUMsZUFBZTtRQUMzQywyQkFBMkIsQ0FBQyxZQUFZO0tBQzNDOzRGQVlRLDZCQUE2QjtrQkF0QnpDLFNBQVM7K0JBQ0ksc0JBQXNCLFlBQ3RCLHlCQUF5QixtQkFHbEIsdUJBQXVCLENBQUMsTUFBTSx1QkFDMUIsS0FBSyxjQUNkO3dCQUNSLDJCQUEyQixDQUFDLGVBQWU7d0JBQzNDLDJCQUEyQixDQUFDLFlBQVk7cUJBQzNDLFFBQ0s7d0JBQ0YseUJBQXlCLEVBQUUsc0NBQXNDO3dCQUNqRSwwQkFBMEIsRUFBRSxxQkFBcUI7d0JBQ2pELGdDQUFnQyxFQUFFLDBCQUEwQjt3QkFDNUQsaUNBQWlDLEVBQUUsMkJBQTJCO3dCQUM5RCxpQ0FBaUMsRUFBRSwyQkFBMkI7d0JBQzlELG1DQUFtQyxFQUFFLDZCQUE2Qjt3QkFDbEUsV0FBVyxFQUFFLGtCQUFrQjt3QkFDL0Isb0JBQW9CLEVBQUUseUJBQXlCO3FCQUNsRDs7MEJBc0pZLFFBQVE7NENBbEpyQixRQUFRO3NCQURQLFNBQVM7dUJBQUMsb0JBQW9CLEVBQUUsRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFDO2dCQUdoRCxLQUFLO3NCQURKLFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBkYXRlLXRpbWUtcGlja2VyLWNvbnRhaW5lci5jb21wb25lbnRcbiAqL1xuXG5pbXBvcnQge1xuICAgIEFmdGVyQ29udGVudEluaXQsXG4gICAgQWZ0ZXJWaWV3SW5pdCxcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBDb21wb25lbnQsXG4gICAgRWxlbWVudFJlZixcbiAgICBPbkluaXQsXG4gICAgT3B0aW9uYWwsXG4gICAgVmlld0NoaWxkXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtBbmltYXRpb25FdmVudH0gZnJvbSAnQGFuZ3VsYXIvYW5pbWF0aW9ucyc7XG5pbXBvcnQge093bERhdGVUaW1lSW50bH0gZnJvbSAnLi9kYXRlLXRpbWUtcGlja2VyLWludGwuc2VydmljZSc7XG5pbXBvcnQge093bENhbGVuZGFyQ29tcG9uZW50fSBmcm9tICcuL2NhbGVuZGFyLmNvbXBvbmVudCc7XG5pbXBvcnQge093bFRpbWVyQ29tcG9uZW50fSBmcm9tICcuL3RpbWVyLmNvbXBvbmVudCc7XG5pbXBvcnQge0RhdGVUaW1lQWRhcHRlcn0gZnJvbSAnLi9hZGFwdGVyL2RhdGUtdGltZS1hZGFwdGVyLmNsYXNzJztcbmltcG9ydCB7T3dsRGF0ZVRpbWUsIFBpY2tlclR5cGV9IGZyb20gJy4vZGF0ZS10aW1lLmNsYXNzJztcbmltcG9ydCB7T2JzZXJ2YWJsZSwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge293bERhdGVUaW1lUGlja2VyQW5pbWF0aW9uc30gZnJvbSAnLi9kYXRlLXRpbWUtcGlja2VyLmFuaW1hdGlvbnMnO1xuaW1wb3J0IHtcbiAgICBET1dOX0FSUk9XLFxuICAgIExFRlRfQVJST1csXG4gICAgUklHSFRfQVJST1csXG4gICAgU1BBQ0UsXG4gICAgVVBfQVJST1dcbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcblxuQENvbXBvbmVudCh7XG4gICAgZXhwb3J0QXM6ICdvd2xEYXRlVGltZUNvbnRhaW5lcicsXG4gICAgc2VsZWN0b3I6ICdvd2wtZGF0ZS10aW1lLWNvbnRhaW5lcicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2RhdGUtdGltZS1waWNrZXItY29udGFpbmVyLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9kYXRlLXRpbWUtcGlja2VyLWNvbnRhaW5lci5jb21wb25lbnQuc2NzcyddLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIHByZXNlcnZlV2hpdGVzcGFjZXM6IGZhbHNlLFxuICAgIGFuaW1hdGlvbnM6IFtcbiAgICAgICAgb3dsRGF0ZVRpbWVQaWNrZXJBbmltYXRpb25zLnRyYW5zZm9ybVBpY2tlcixcbiAgICAgICAgb3dsRGF0ZVRpbWVQaWNrZXJBbmltYXRpb25zLmZhZGVJblBpY2tlclxuICAgIF0sXG4gICAgaG9zdDoge1xuICAgICAgICAnKEB0cmFuc2Zvcm1QaWNrZXIuZG9uZSknOiAnaGFuZGxlQ29udGFpbmVyQW5pbWF0aW9uRG9uZSgkZXZlbnQpJyxcbiAgICAgICAgJ1tjbGFzcy5vd2wtZHQtY29udGFpbmVyXSc6ICdvd2xEVENvbnRhaW5lckNsYXNzJyxcbiAgICAgICAgJ1tjbGFzcy5vd2wtZHQtcG9wdXAtY29udGFpbmVyXSc6ICdvd2xEVFBvcHVwQ29udGFpbmVyQ2xhc3MnLFxuICAgICAgICAnW2NsYXNzLm93bC1kdC1kaWFsb2ctY29udGFpbmVyXSc6ICdvd2xEVERpYWxvZ0NvbnRhaW5lckNsYXNzJyxcbiAgICAgICAgJ1tjbGFzcy5vd2wtZHQtaW5saW5lLWNvbnRhaW5lcl0nOiAnb3dsRFRJbmxpbmVDb250YWluZXJDbGFzcycsXG4gICAgICAgICdbY2xhc3Mub3dsLWR0LWNvbnRhaW5lci1kaXNhYmxlZF0nOiAnb3dsRFRDb250YWluZXJEaXNhYmxlZENsYXNzJyxcbiAgICAgICAgJ1thdHRyLmlkXSc6ICdvd2xEVENvbnRhaW5lcklkJyxcbiAgICAgICAgJ1tAdHJhbnNmb3JtUGlja2VyXSc6ICdvd2xEVENvbnRhaW5lckFuaW1hdGlvbicsXG4gICAgfVxufSlcbmV4cG9ydCBjbGFzcyBPd2xEYXRlVGltZUNvbnRhaW5lckNvbXBvbmVudDxUPiBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG4gICAgQFZpZXdDaGlsZChPd2xDYWxlbmRhckNvbXBvbmVudCwge3N0YXRpYzogZmFsc2V9KVxuICAgIGNhbGVuZGFyOiBPd2xDYWxlbmRhckNvbXBvbmVudDxUPjtcbiAgICBAVmlld0NoaWxkKE93bFRpbWVyQ29tcG9uZW50LCB7c3RhdGljOiBmYWxzZX0pXG4gICAgdGltZXI6IE93bFRpbWVyQ29tcG9uZW50PFQ+O1xuXG4gICAgcHVibGljIHBpY2tlcjogT3dsRGF0ZVRpbWU8VD47XG4gICAgcHVibGljIGFjdGl2ZVNlbGVjdGVkSW5kZXggPSAwOyAvLyBUaGUgY3VycmVudCBhY3RpdmUgU2VsZWN0ZWRJbmRleCBpbiByYW5nZSBzZWxlY3QgbW9kZSAoMDogJ2Zyb20nLCAxOiAndG8nKVxuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIGVtaXRzIHdoZW4gdHJ5IHRvIGhpZGUgcGlja2VyXG4gICAgICovXG4gICAgcHJpdmF0ZSBoaWRlUGlja2VyJCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICAgIGdldCBoaWRlUGlja2VyU3RyZWFtKCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhpZGVQaWNrZXIkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBlbWl0cyB3aGVuIHRyeSB0byBjb25maXJtIHRoZSBzZWxlY3RlZCB2YWx1ZVxuICAgICAqL1xuICAgIHByaXZhdGUgY29uZmlybVNlbGVjdGVkJCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICAgIGdldCBjb25maXJtU2VsZWN0ZWRTdHJlYW0oKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlybVNlbGVjdGVkJC5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHBpY2tlck9wZW5lZCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgZ2V0IHBpY2tlck9wZW5lZFN0cmVhbSgpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5waWNrZXJPcGVuZWQkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBjdXJyZW50IHBpY2tlciBtb21lbnQuIFRoaXMgZGV0ZXJtaW5lcyB3aGljaCB0aW1lIHBlcmlvZCBpcyBzaG93biBhbmQgd2hpY2ggZGF0ZSBpc1xuICAgICAqIGhpZ2hsaWdodGVkIHdoZW4gdXNpbmcga2V5Ym9hcmQgbmF2aWdhdGlvbi5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9jbGFtUGlja2VyTW9tZW50OiBUO1xuXG4gICAgZ2V0IHBpY2tlck1vbWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NsYW1QaWNrZXJNb21lbnQ7XG4gICAgfVxuXG4gICAgc2V0IHBpY2tlck1vbWVudCh2YWx1ZTogVCkge1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuX2NsYW1QaWNrZXJNb21lbnQgPSB0aGlzLmRhdGVUaW1lQWRhcHRlci5jbGFtcERhdGUoXG4gICAgICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICAgICAgdGhpcy5waWNrZXIubWluRGF0ZVRpbWUsXG4gICAgICAgICAgICAgICAgdGhpcy5waWNrZXIubWF4RGF0ZVRpbWVcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jZFJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG5cbiAgICBnZXQgcGlja2VyVHlwZSgpOiBQaWNrZXJUeXBlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlja2VyLnBpY2tlclR5cGU7XG4gICAgfVxuXG4gICAgZ2V0IGNhbmNlbExhYmVsKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpY2tlckludGwuY2FuY2VsQnRuTGFiZWw7XG4gICAgfVxuXG4gICAgZ2V0IHNldExhYmVsKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpY2tlckludGwuc2V0QnRuTGFiZWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIHJhbmdlICdmcm9tJyBsYWJlbFxuICAgICAqL1xuICAgIGdldCBmcm9tTGFiZWwoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlja2VySW50bC5yYW5nZUZyb21MYWJlbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmFuZ2UgJ3RvJyBsYWJlbFxuICAgICAqL1xuICAgIGdldCB0b0xhYmVsKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpY2tlckludGwucmFuZ2VUb0xhYmVsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSByYW5nZSAnZnJvbScgZm9ybWF0dGVkIHZhbHVlXG4gICAgICovXG4gICAgZ2V0IGZyb21Gb3JtYXR0ZWRWYWx1ZSgpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucGlja2VyLnNlbGVjdGVkc1swXTtcbiAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgICAgICA/IHRoaXMuZGF0ZVRpbWVBZGFwdGVyLmZvcm1hdCh2YWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0U3RyaW5nKVxuICAgICAgICAgICAgOiAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmFuZ2UgJ3RvJyBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgKi9cbiAgICBnZXQgdG9Gb3JtYXR0ZWRWYWx1ZSgpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucGlja2VyLnNlbGVjdGVkc1sxXTtcbiAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgICAgICA/IHRoaXMuZGF0ZVRpbWVBZGFwdGVyLmZvcm1hdCh2YWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0U3RyaW5nKVxuICAgICAgICAgICAgOiAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYXNlcyBpbiB3aGljaCB0aGUgY29udHJvbCBidXR0b25zIHNob3cgaW4gdGhlIHBpY2tlclxuICAgICAqIDEpIHBpY2tlciBtb2RlIGlzICdkaWFsb2cnXG4gICAgICogMikgcGlja2VyIHR5cGUgaXMgTk9UICdjYWxlbmRhcicgYW5kIHRoZSBwaWNrZXIgbW9kZSBpcyBOT1QgJ2lubGluZSdcbiAgICAgKi9cbiAgICBnZXQgc2hvd0NvbnRyb2xCdXR0b25zKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGhpcy5waWNrZXIucGlja2VyTW9kZSA9PT0gJ2RpYWxvZycgfHxcbiAgICAgICAgICAgICh0aGlzLnBpY2tlci5waWNrZXJUeXBlICE9PSAnY2FsZW5kYXInICYmXG4gICAgICAgICAgICAgICAgdGhpcy5waWNrZXIucGlja2VyTW9kZSAhPT0gJ2lubGluZScpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZ2V0IGNvbnRhaW5lckVsbSgpOiBIVE1MRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsbVJlZi5uYXRpdmVFbGVtZW50O1xuICAgIH1cblxuICAgIGdldCBvd2xEVENvbnRhaW5lckNsYXNzKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBnZXQgb3dsRFRQb3B1cENvbnRhaW5lckNsYXNzKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5waWNrZXIucGlja2VyTW9kZSA9PT0gJ3BvcHVwJztcbiAgICB9XG5cbiAgICBnZXQgb3dsRFREaWFsb2dDb250YWluZXJDbGFzcygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlja2VyLnBpY2tlck1vZGUgPT09ICdkaWFsb2cnO1xuICAgIH1cblxuICAgIGdldCBvd2xEVElubGluZUNvbnRhaW5lckNsYXNzKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5waWNrZXIucGlja2VyTW9kZSA9PT0gJ2lubGluZSc7XG4gICAgfVxuXG4gICAgZ2V0IG93bERUQ29udGFpbmVyRGlzYWJsZWRDbGFzcygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlja2VyLmRpc2FibGVkO1xuICAgIH1cblxuICAgIGdldCBvd2xEVENvbnRhaW5lcklkKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpY2tlci5pZDtcbiAgICB9XG5cbiAgICBnZXQgb3dsRFRDb250YWluZXJBbmltYXRpb24oKTogYW55IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlja2VyLnBpY2tlck1vZGUgPT09ICdpbmxpbmUnID8gJycgOiAnZW50ZXInO1xuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgY2RSZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgZWxtUmVmOiBFbGVtZW50UmVmLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgcGlja2VySW50bDogT3dsRGF0ZVRpbWVJbnRsLFxuICAgICAgICAgICAgICAgIEBPcHRpb25hbCgpIHByaXZhdGUgZGF0ZVRpbWVBZGFwdGVyOiBEYXRlVGltZUFkYXB0ZXI8VD4pIHtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgfVxuXG4gICAgcHVibGljIG5nQWZ0ZXJDb250ZW50SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pbml0UGlja2VyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mb2N1c1BpY2tlcigpO1xuICAgIH1cblxuICAgIHB1YmxpYyBoYW5kbGVDb250YWluZXJBbmltYXRpb25Eb25lKGV2ZW50OiBBbmltYXRpb25FdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCB0b1N0YXRlID0gZXZlbnQudG9TdGF0ZTtcbiAgICAgICAgaWYgKHRvU3RhdGUgPT09ICdlbnRlcicpIHtcbiAgICAgICAgICAgIHRoaXMucGlja2VyT3BlbmVkJC5uZXh0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZGF0ZVNlbGVjdGVkKGRhdGU6IFQpOiB2b2lkIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcblxuICAgICAgICBpZiAodGhpcy5waWNrZXIuaXNJblNpbmdsZU1vZGUpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuZGF0ZVNlbGVjdGVkSW5TaW5nbGVNb2RlKGRhdGUpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGlja2VyTW9tZW50ID0gcmVzdWx0O1xuICAgICAgICAgICAgICAgIHRoaXMucGlja2VyLnNlbGVjdChyZXN1bHQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSBjbG9zZSB0aGUgcGlja2VyIHdoZW4gcmVzdWx0IGlzIG51bGwgYW5kIHBpY2tlclR5cGUgaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucGlja2VyVHlwZSA9PT0gJ2NhbGVuZGFyJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGVQaWNrZXIkLm5leHQobnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGlja2VyLmlzSW5SYW5nZU1vZGUpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuZGF0ZVNlbGVjdGVkSW5SYW5nZU1vZGUoZGF0ZSk7XG4gICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5waWNrZXJNb21lbnQgPSByZXN1bHRbdGhpcy5hY3RpdmVTZWxlY3RlZEluZGV4XTtcbiAgICAgICAgICAgICAgICB0aGlzLnBpY2tlci5zZWxlY3QocmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyB0aW1lU2VsZWN0ZWQodGltZTogVCk6IHZvaWQge1xuICAgICAgICB0aGlzLnBpY2tlck1vbWVudCA9IHRoaXMuZGF0ZVRpbWVBZGFwdGVyLmNsb25lKHRpbWUpO1xuXG4gICAgICAgIGlmICghdGhpcy5waWNrZXIuZGF0ZVRpbWVDaGVja2VyKHRoaXMucGlja2VyTW9tZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGlja2VyLmlzSW5TaW5nbGVNb2RlKSB7XG4gICAgICAgICAgICB0aGlzLnBpY2tlci5zZWxlY3QodGhpcy5waWNrZXJNb21lbnQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGlja2VyLmlzSW5SYW5nZU1vZGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkcyA9IFsuLi50aGlzLnBpY2tlci5zZWxlY3RlZHNdO1xuXG4gICAgICAgICAgICAvLyBjaGVjayBpZiB0aGUgJ2Zyb20nIGlzIGFmdGVyICd0bycgb3IgJ3RvJ2lzIGJlZm9yZSAnZnJvbSdcbiAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgd2Ugc2V0IGJvdGggdGhlICdmcm9tJyBhbmQgJ3RvJyB0aGUgc2FtZSB2YWx1ZVxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICh0aGlzLmFjdGl2ZVNlbGVjdGVkSW5kZXggPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRzWzFdICYmXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVRpbWVBZGFwdGVyLmNvbXBhcmUoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBpY2tlck1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkc1sxXVxuICAgICAgICAgICAgICAgICAgICApID09PSAxKSB8fFxuICAgICAgICAgICAgICAgICh0aGlzLmFjdGl2ZVNlbGVjdGVkSW5kZXggPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRzWzBdICYmXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVRpbWVBZGFwdGVyLmNvbXBhcmUoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBpY2tlck1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkc1swXVxuICAgICAgICAgICAgICAgICAgICApID09PSAtMSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkc1swXSA9IHRoaXMucGlja2VyTW9tZW50O1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkc1sxXSA9IHRoaXMucGlja2VyTW9tZW50O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZHNbdGhpcy5hY3RpdmVTZWxlY3RlZEluZGV4XSA9IHRoaXMucGlja2VyTW9tZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBpY2tlci5zZWxlY3Qoc2VsZWN0ZWRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBjbGljayBvbiBjYW5jZWwgYnV0dG9uXG4gICAgICovXG4gICAgcHVibGljIG9uQ2FuY2VsQ2xpY2tlZChldmVudDogYW55KTogdm9pZCB7XG4gICAgICAgIHRoaXMuaGlkZVBpY2tlciQubmV4dChudWxsKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBjbGljayBvbiBzZXQgYnV0dG9uXG4gICAgICovXG4gICAgcHVibGljIG9uU2V0Q2xpY2tlZChldmVudDogYW55KTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5waWNrZXIuZGF0ZVRpbWVDaGVja2VyKHRoaXMucGlja2VyTW9tZW50KSkge1xuICAgICAgICAgICAgdGhpcy5oaWRlUGlja2VyJC5uZXh0KG51bGwpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29uZmlybVNlbGVjdGVkJC5uZXh0KGV2ZW50KTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBjbGljayBvbiBpbmZvcm0gcmFkaW8gZ3JvdXBcbiAgICAgKi9cbiAgICBwdWJsaWMgaGFuZGxlQ2xpY2tPbkluZm9Hcm91cChldmVudDogYW55LCBpb