UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

278 lines 59.1 kB
import { LiveAnnouncer } from '@angular/cdk/a11y'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject } from '@angular/core'; import { merge, Subject } from 'rxjs'; import { delay, filter, takeUntil } from 'rxjs/operators'; import { FocusIndicatorOriginService } from '../../../directives/accessibility/index'; import { DateRangeOptions } from '../../date-range-picker/date-range-picker.directive'; import { DateRangePicker, DateRangeService } from '../../date-range-picker/date-range.service'; import { DatePickerHeaderEvent, DateTimePickerService } from '../date-time-picker.service'; import { compareDays, isDateAfter, isDateBefore } from '../date-time-picker.utils'; import { DayViewService } from './day-view.service'; import * as i0 from "@angular/core"; import * as i1 from "../../../directives/accessibility/focus-indicator/focus-indicator.directive"; import * as i2 from "../../../directives/accessibility/focus-indicator/focus-indicator-origin/focus-indicator-origin.directive"; import * as i3 from "../../../directives/focus-if/focus-if.directive"; import * as i4 from "@angular/common"; import * as i5 from "../pipes/weekday-sort.pipe"; export class DayViewComponent { /** Determine if we are in range selection mode */ get _isRangeMode() { return !!this._rangeOptions; } /** Determine if this picker is the start picker */ get _isRangeStart() { return this._isRangeMode && this._rangeOptions.picker === DateRangePicker.Start; } /** Determine if this picker is the end picker */ get _isRangeEnd() { return this._isRangeMode && this._rangeOptions.picker === DateRangePicker.End; } get _rangeStart() { return this._isRangeMode && this._rangeService ? this._rangeService.start : null; } get _rangeEnd() { return this._isRangeMode && this._rangeService ? this._rangeService.end : null; } constructor() { this.datePicker = inject(DateTimePickerService); this.dayService = inject(DayViewService); this._changeDetector = inject(ChangeDetectorRef); this._focusOrigin = inject(FocusIndicatorOriginService); this._liveAnnouncer = inject(LiveAnnouncer); this._rangeService = inject(DateRangeService, { optional: true }); this._rangeOptions = inject(DateRangeOptions, { optional: true }); this._onDestroy = new Subject(); this.datePicker.headerEvent$.pipe(takeUntil(this._onDestroy)) .subscribe(event => event === DatePickerHeaderEvent.Next ? this.next() : this.previous()); // if we are a range picker then we also want to subscribe to range changes if (this._rangeService) { merge(this._rangeService.onRangeChange, this._rangeService.onHoverChange).pipe(takeUntil(this._onDestroy)) .subscribe(() => this._changeDetector.detectChanges()); // subscribe to changes to the start date this._rangeService.onStartChange .pipe(takeUntil(this._onDestroy), filter(date => !!date && this._isRangeEnd && this.datePicker.initialised), delay(0)) .subscribe(date => this.onRangeChange(date)); // subscribe to changes to the end date this._rangeService.onEndChange .pipe(takeUntil(this._onDestroy), filter(date => !!date && this._isRangeStart && this.datePicker.initialised), delay(0)) .subscribe(date => this.onRangeChange(date)); // when the range is cleared reset the selected date so we can click on the same date again if we want to this._rangeService.onClear.pipe(takeUntil(this._onDestroy)).subscribe(() => this.datePicker.selected$.next(null)); } } ngAfterViewInit() { // update when there are changes to the min/max values merge(this.datePicker.min$, this.datePicker.max$).pipe(takeUntil(this._onDestroy)) .subscribe(() => this._changeDetector.detectChanges()); // if we open and the range start is already selected, ensure that we move the end picker to a month with options if (!this.datePicker.initialised && this._rangeStart && !this._rangeEnd && this._isRangeEnd) { this.onRangeChange(this._rangeStart); } // if we open and the range end is already selected, ensure that we move the start picker to a month with options if (!this.datePicker.initialised && this._rangeEnd && !this._rangeStart && this._isRangeStart) { this.onRangeChange(this._rangeEnd); } } ngOnDestroy() { this._onDestroy.next(); this._onDestroy.complete(); } /** * Navigate to the previous page of dates */ previous() { this.datePicker.setViewportMonth(this.datePicker.month$.value - 1); } /** * Navigate to the next page of dates */ next() { this.datePicker.setViewportMonth(this.datePicker.month$.value + 1); } /** * Select a particular date * @param date the date to select */ select(date) { // if we are the start range picker and we click the already selected day deselect it if (this._isRangeMode && this._isRangeStart && this._rangeStart && compareDays(this._rangeStart, date)) { this._rangeService.setStartDate(null); this.datePicker.selected$.next(null); return; } // if we are the end range picker and we click the already selected day deselect it if (this._isRangeMode && this._isRangeEnd && this._rangeEnd && compareDays(this._rangeEnd, date)) { this._rangeService.setEndDate(null); this.datePicker.selected$.next(null); return; } // if we are in range mode ensure we include the time from the time picker if (this._isRangeMode) { // update the current date object if (this._isRangeStart && !this._rangeService.showTime) { this.datePicker.setDate(date.getDate(), date.getMonth(), date.getFullYear(), 0, 0, 0); } else if (this._isRangeEnd && !this._rangeService.showTime) { this.datePicker.setDate(date.getDate(), date.getMonth(), date.getFullYear(), 23, 59, 59); } else { this.datePicker.setDate(date.getDate(), date.getMonth(), date.getFullYear(), this.datePicker.hours, this.datePicker.minutes, this.datePicker.seconds); } } else { // update the current date object this.datePicker.setDate(date.getDate(), date.getMonth(), date.getFullYear()); } // focus the newly selected date this.dayService.setFocus(date.getDate(), date.getMonth(), date.getFullYear()); // if we select a start date that is after the end date then clear the end date if (this._isRangeMode && this._isRangeStart && this._rangeStart && this._rangeEnd) { if (this._rangeStart.getTime() > this._rangeEnd.getTime()) { this._rangeService.setEndDate(null); } } // if we select a end date that is before the start date then clear the start date if (this._isRangeMode && this._isRangeEnd && this._rangeStart && this._rangeEnd) { if (this._rangeEnd.getTime() < this._rangeStart.getTime()) { this._rangeService.setStartDate(null); } } } trackWeekByFn(index) { return index; } trackDayByFn(_index, item) { return `${item.day} ${item.month} ${item.year}`; } focusDate(item, dayOffset) { // determine the date of the day const target = new Date(item.date.setDate(item.date.getDate() + dayOffset)); // we should force the origin to be keyboard this._focusOrigin.setOrigin('keyboard'); // identify which date should be focused this.dayService.setFocus(target.getDate(), target.getMonth(), target.getFullYear()); } getTabbable(item) { const focused = this.dayService.focused$.value; const grid = this.dayService.grid$.value; const month = this.datePicker.month$.value; // if there is a focused month check if this is it if (focused) { // check if the focused day is visible const isFocusedDayVisible = !!grid.find(row => !!row.find(_item => _item.day === focused.day && _item.month === focused.month && _item.year === focused.year && _item.month === month)); if (isFocusedDayVisible) { return focused.day === item.day && focused.month === item.month && focused.year === item.year; } } // if there is no focusable day then check if there is a selected day const isSelectedDayVisible = !!grid.find(row => !!row.find(day => day.isActive)); if (isSelectedDayVisible) { return item.isActive; } // find the first non disabled day that is part of the current month for (const row of grid) { for (const column of row) { if (column === item && column.month === month && !this.getDisabled(column.date)) { return true; } } } return false; } getDisabled(date) { // if we are not in range mode then it will always be enabled if (this._isRangeMode) { // if we are range start and dates are after the range end then they should also be disabled if (this._isRangeStart && !this._rangeStart && this._rangeEnd && isDateAfter(date, this._rangeEnd)) { return true; } // if we are range end and dates are before the range start then they should also be disabled if (this._isRangeEnd && !this._rangeEnd && this._rangeStart && isDateBefore(date, this._rangeStart)) { return true; } } if (this.datePicker.min$.value && isDateBefore(date, this.datePicker.min$.value)) { return true; } if (this.datePicker.max$.value && isDateAfter(date, this.datePicker.max$.value)) { return true; } return false; } isRangeStartDate(date) { return this._isRangeMode && this._rangeStart && compareDays(date, this._rangeStart); } isRangeEndDate(date) { return this._isRangeMode && this._rangeEnd && compareDays(date, this._rangeEnd); } isWithinRange(date) { return this._isRangeMode && this._rangeStart && isDateAfter(date, this._rangeStart) && isDateBefore(date, this._rangeEnd); } isDateHovered(date) { // if we are not in range mode or both start and end dates are selected then dont show range hover if (!this._isRangeMode || !this._rangeService.hover || this._rangeStart && this._rangeEnd) { return; } return this._rangeStart && isDateAfter(date, this._rangeStart) && isDateBefore(date, this._rangeService.hover, true) || this._rangeEnd && isDateBefore(date, this._rangeEnd) && isDateAfter(date, this._rangeService.hover, true); } isItemActive(date, isActive) { if (!this._isRangeMode) { return isActive; } return this._isRangeStart && this._rangeStart && compareDays(this._rangeStart, date) || this._isRangeEnd && this._rangeEnd && compareDays(this._rangeEnd, date); } onRangeMouseEnter(date) { if (this._isRangeMode) { this._rangeService.setDateMouseEnter(date); } } onRangeMouseLeave(date) { if (this._isRangeMode) { this._rangeService.setDateMouseLeave(date); } } /** Announce the date when we focus on a date */ announceRangeMode() { if (this._isRangeMode) { this._liveAnnouncer.announce(this._isRangeStart ? this._rangeService.startPickerAriaLabel : this._rangeService.endPickerAriaLabel); } } /** Determine if we should focus a date */ shouldFocus(item) { // if we are opening the popover initially we never want to focus a date in the range end picker if (!this.datePicker.initialised && this._isRangeEnd || this._rangeService && this._rangeService.isChangingTime) { return false; } // extract the current focused dates const { day, month, year } = this.dayService.focused$.value; // check if the current date is the focused date and it is in the viewport date return day === item.day && month === item.month && year === item.year && item.isCurrentMonth; } /** Update the viewport when the range changes to ensure focus is present on a valid item */ onRangeChange(date) { if (!(this._isRangeStart && !this._rangeStart || this._isRangeEnd && !this._rangeEnd)) { return; } // get the month showing on the other date range picker const currentDate = new Date(this.datePicker.year$.value, this.datePicker.month$.value); // if we are the start date and we are after the end date - ONLY then should be change the visible month the match the end date const startShouldUpdate = this._isRangeStart && !this._rangeStart && (currentDate.getFullYear() > date.getFullYear() || currentDate.getFullYear() === date.getFullYear() && currentDate.getMonth() > date.getMonth()); // if we are the end date and we are before the start date - ONLY then should be change the visible month the match the start date const endShouldUpdate = this._isRangeEnd && !this._rangeEnd && (currentDate.getFullYear() < date.getFullYear() || currentDate.getFullYear() === date.getFullYear() && currentDate.getMonth() < date.getMonth()); if (startShouldUpdate || endShouldUpdate) { this.datePicker.setViewportMonth(date.getMonth()); this.datePicker.setViewportYear(date.getFullYear()); this.dayService.setFocus(date.getDate(), date.getMonth(), date.getFullYear()); this._changeDetector.detectChanges(); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DayViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: DayViewComponent, selector: "ux-date-time-picker-day-view", providers: [DayViewService], ngImport: i0, template: "<table class=\"calendar\">\n <thead>\n <tr>\n @for (\n day of datePicker.weekdays$ | async | weekDaySort: (datePicker.startOfWeek$ | async);\n let index = $index;\n track index\n ) {\n <th class=\"weekday\" [attr.aria-label]=\"day\">{{ day }}</th>\n }\n </tr>\n </thead>\n\n <tbody role=\"grid\">\n @for (row of dayService.grid$ | async; track trackWeekByFn($index)) {\n <tr role=\"row\">\n @for (item of row; track trackDayByFn($index, item)) {\n <td class=\"date-cell\">\n <button\n type=\"button\"\n uxFocusIndicator\n uxFocusIndicatorOrigin\n class=\"date-button\"\n role=\"gridcell\"\n [class.range-start]=\"isRangeStartDate(item.date)\"\n [class.range-between]=\"isWithinRange(item.date) || isDateHovered(item.date)\"\n [class.range-end]=\"isRangeEndDate(item.date)\"\n [focusIf]=\"shouldFocus(item)\"\n [attr.aria-label]=\"item.date | date\"\n [attr.aria-selected]=\"isItemActive(item.date, item.isActive)\"\n [attr.aria-hidden]=\"!item.isCurrentMonth\"\n [class.current]=\"item.isToday\"\n [class.active]=\"isItemActive(item.date, item.isActive) && !getDisabled(item.date)\"\n [class.preview]=\"!item.isCurrentMonth\"\n [tabindex]=\"getTabbable(item) ? 0 : -1\"\n [disabled]=\"getDisabled(item.date)\"\n (click)=\"select(item.date); $event.stopPropagation()\"\n (mouseenter)=\"onRangeMouseEnter(item.date)\"\n (mouseleave)=\"onRangeMouseLeave(item.date)\"\n (keydown.ArrowLeft)=\"focusDate(item, -1); $event.preventDefault()\"\n (keydown.ArrowRight)=\"focusDate(item, 1); $event.preventDefault()\"\n (keydown.ArrowUp)=\"focusDate(item, -7); $event.preventDefault()\"\n (keydown.ArrowDown)=\"focusDate(item, 7); $event.preventDefault()\"\n (focus)=\"announceRangeMode()\"\n >\n {{ item.date.getDate() }}\n </button>\n </td>\n }\n </tr>\n }\n </tbody>\n</table>\n", dependencies: [{ kind: "directive", type: i1.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "directive", type: i2.FocusIndicatorOriginDirective, selector: "[uxFocusIndicatorOrigin]" }, { kind: "directive", type: i3.FocusIfDirective, selector: "[focusIf]", inputs: ["focusIfDelay", "focusIfScroll", "focusIf"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.DatePipe, name: "date" }, { kind: "pipe", type: i5.WeekDaySortPipe, name: "weekDaySort" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DayViewComponent, decorators: [{ type: Component, args: [{ selector: 'ux-date-time-picker-day-view', providers: [DayViewService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<table class=\"calendar\">\n <thead>\n <tr>\n @for (\n day of datePicker.weekdays$ | async | weekDaySort: (datePicker.startOfWeek$ | async);\n let index = $index;\n track index\n ) {\n <th class=\"weekday\" [attr.aria-label]=\"day\">{{ day }}</th>\n }\n </tr>\n </thead>\n\n <tbody role=\"grid\">\n @for (row of dayService.grid$ | async; track trackWeekByFn($index)) {\n <tr role=\"row\">\n @for (item of row; track trackDayByFn($index, item)) {\n <td class=\"date-cell\">\n <button\n type=\"button\"\n uxFocusIndicator\n uxFocusIndicatorOrigin\n class=\"date-button\"\n role=\"gridcell\"\n [class.range-start]=\"isRangeStartDate(item.date)\"\n [class.range-between]=\"isWithinRange(item.date) || isDateHovered(item.date)\"\n [class.range-end]=\"isRangeEndDate(item.date)\"\n [focusIf]=\"shouldFocus(item)\"\n [attr.aria-label]=\"item.date | date\"\n [attr.aria-selected]=\"isItemActive(item.date, item.isActive)\"\n [attr.aria-hidden]=\"!item.isCurrentMonth\"\n [class.current]=\"item.isToday\"\n [class.active]=\"isItemActive(item.date, item.isActive) && !getDisabled(item.date)\"\n [class.preview]=\"!item.isCurrentMonth\"\n [tabindex]=\"getTabbable(item) ? 0 : -1\"\n [disabled]=\"getDisabled(item.date)\"\n (click)=\"select(item.date); $event.stopPropagation()\"\n (mouseenter)=\"onRangeMouseEnter(item.date)\"\n (mouseleave)=\"onRangeMouseLeave(item.date)\"\n (keydown.ArrowLeft)=\"focusDate(item, -1); $event.preventDefault()\"\n (keydown.ArrowRight)=\"focusDate(item, 1); $event.preventDefault()\"\n (keydown.ArrowUp)=\"focusDate(item, -7); $event.preventDefault()\"\n (keydown.ArrowDown)=\"focusDate(item, 7); $event.preventDefault()\"\n (focus)=\"announceRangeMode()\"\n >\n {{ item.date.getDate() }}\n </button>\n </td>\n }\n </tr>\n }\n </tbody>\n</table>\n" }] }], ctorParameters: () => [] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF5LXZpZXcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvZGF0ZS10aW1lLXBpY2tlci9kYXktdmlldy9kYXktdmlldy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9kYXRlLXRpbWUtcGlja2VyL2RheS12aWV3L2RheS12aWV3LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNsRCxPQUFPLEVBQWlCLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFDeEgsT0FBTyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUQsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDdEYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scURBQXFELENBQUM7QUFDdkYsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQy9GLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzNGLE9BQU8sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ25GLE9BQU8sRUFBZSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7Ozs7OztBQVFqRSxNQUFNLE9BQU8sZ0JBQWdCO0lBZXpCLGtEQUFrRDtJQUNsRCxJQUFJLFlBQVk7UUFDWixPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFD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QUM7WUFDdkMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUNsRCxJQUFJLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUNwRCxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQzlFLElBQUksQ0FBQyxlQUFlLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDekMsQ0FBQztJQUNMLENBQUM7K0dBblVRLGdCQUFnQjttR0FBaEIsZ0JBQWdCLHVEQUhkLENBQUMsY0FBYyxDQUFDLDBCQ2QvQixtc0VBcURBOzs0RkRwQ2EsZ0JBQWdCO2tCQU41QixTQUFTOytCQUNJLDhCQUE4QixhQUU3QixDQUFDLGNBQWMsQ0FBQyxtQkFDVix1QkFBdUIsQ0FBQyxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTGl2ZUFubm91bmNlciB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBpbmplY3QsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgbWVyZ2UsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRlbGF5LCBmaWx0ZXIsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEZvY3VzSW5kaWNhdG9yT3JpZ2luU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2RpcmVjdGl2ZXMvYWNjZXNzaWJpbGl0eS9pbmRleCc7XG5pbXBvcnQgeyBEYXRlUmFuZ2VPcHRpb25zIH0gZnJvbSAnLi4vLi4vZGF0ZS1yYW5nZS1waWNrZXIvZGF0ZS1yYW5nZS1waWNrZXIuZGlyZWN0aXZlJztcbmltcG9ydCB7IERhdGVSYW5nZVBpY2tlciwgRGF0ZVJhbmdlU2VydmljZSB9IGZyb20gJy4uLy4uL2RhdGUtcmFuZ2UtcGlja2VyL2RhdGUtcmFuZ2Uuc2VydmljZSc7XG5pbXBvcnQgeyBEYXRlUGlja2VySGVhZGVyRXZlbnQsIERhdGVUaW1lUGlja2VyU2VydmljZSB9IGZyb20gJy4uL2RhdGUtdGltZS1waWNrZXIuc2VydmljZSc7XG5pbXBvcnQgeyBjb21wYXJlRGF5cywgaXNEYXRlQWZ0ZXIsIGlzRGF0ZUJlZm9yZSB9IGZyb20gJy4uL2RhdGUtdGltZS1waWNrZXIudXRpbHMnO1xuaW1wb3J0IHsgRGF5Vmlld0l0ZW0sIERheVZpZXdTZXJ2aWNlIH0gZnJvbSAnLi9kYXktdmlldy5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICd1eC1kYXRlLXRpbWUtcGlja2VyLWRheS12aWV3JyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZGF5LXZpZXcuY29tcG9uZW50Lmh0bWwnLFxuICAgIHByb3ZpZGVyczogW0RheVZpZXdTZXJ2aWNlXSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBEYXlWaWV3Q29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgICByZWFkb25seSBkYXRlUGlja2VyID0gaW5qZWN0KERhdGVUaW1lUGlja2VyU2VydmljZSk7XG5cbiAgICByZWFkb25seSBkYXlTZXJ2aWNlID0gaW5qZWN0KERheVZpZXdTZXJ2aWNlKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NoYW5nZURldGVjdG9yID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2ZvY3VzT3JpZ2luID0gaW5qZWN0KEZvY3VzSW5kaWNhdG9yT3JpZ2luU2VydmljZSk7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9saXZlQW5ub3VuY2VyID0gaW5qZWN0KExpdmVBbm5vdW5jZXIpO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBfcmFuZ2VTZXJ2aWNlID0gaW5qZWN0KERhdGVSYW5nZVNlcnZpY2UsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9yYW5nZU9wdGlvbnMgPSBpbmplY3QoRGF0ZVJhbmdlT3B0aW9ucywgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICAgIC8qKiBEZXRlcm1pbmUgaWYgd2UgYXJlIGluIHJhbmdlIHNlbGVjdGlvbiBtb2RlICovXG4gICAgZ2V0IF9pc1JhbmdlTW9kZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fcmFuZ2VPcHRpb25zO1xuICAgIH1cblxuICAgIC8qKiBEZXRlcm1pbmUgaWYgdGhpcyBwaWNrZXIgaXMgdGhlIHN0YXJ0IHBpY2tlciAqL1xuICAgIGdldCBfaXNSYW5nZVN0YXJ0KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNSYW5nZU1vZGUgJiYgdGhpcy5fcmFuZ2VPcHRpb25zLnBpY2tlciA9PT0gRGF0ZVJhbmdlUGlja2VyLlN0YXJ0O1xuICAgIH1cblxuICAgIC8qKiBEZXRlcm1pbmUgaWYgdGhpcyBwaWNrZXIgaXMgdGhlIGVuZCBwaWNrZXIgKi9cbiAgICBnZXQgX2lzUmFuZ2VFbmQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1JhbmdlTW9kZSAmJiB0aGlzLl9yYW5nZU9wdGlvbnMucGlja2VyID09PSBEYXRlUmFuZ2VQaWNrZXIuRW5kO1xuICAgIH1cblxuICAgIGdldCBfcmFuZ2VTdGFydCgpOiBEYXRlIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1JhbmdlTW9kZSAmJiB0aGlzLl9yYW5nZVNlcnZpY2UgPyB0aGlzLl9yYW5nZVNlcnZpY2Uuc3RhcnQgOiBudWxsO1xuICAgIH1cblxuICAgIGdldCBfcmFuZ2VFbmQoKTogRGF0ZSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNSYW5nZU1vZGUgJiYgdGhpcy5fcmFuZ2VTZXJ2aWNlID8gdGhpcy5fcmFuZ2VTZXJ2aWNlLmVuZCA6IG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZWFkb25seSBfb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuXG4gICAgICAgIHRoaXMuZGF0ZVBpY2tlci5oZWFkZXJFdmVudCQucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoZXZlbnQgPT4gZXZlbnQgPT09IERhdGVQaWNrZXJIZWFkZXJFdmVudC5OZXh0ID8gdGhpcy5uZXh0KCkgOiB0aGlzLnByZXZpb3VzKCkpO1xuXG4gICAgICAgIC8vIGlmIHdlIGFyZSBhIHJhbmdlIHBpY2tlciB0aGVuIHdlIGFsc28gd2FudCB0byBzdWJzY3JpYmUgdG8gcmFuZ2UgY2hhbmdlc1xuICAgICAgICBpZiAodGhpcy5fcmFuZ2VTZXJ2aWNlKSB7XG4gICAgICAgICAgICBtZXJnZSh0aGlzLl9yYW5nZVNlcnZpY2Uub25SYW5nZUNoYW5nZSwgdGhpcy5fcmFuZ2VTZXJ2aWNlLm9uSG92ZXJDaGFuZ2UpLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCkpO1xuXG4gICAgICAgICAgICAvLyBzdWJzY3JpYmUgdG8gY2hhbmdlcyB0byB0aGUgc3RhcnQgZGF0ZVxuICAgICAgICAgICAgdGhpcy5fcmFuZ2VTZXJ2aWNlLm9uU3RhcnRDaGFuZ2VcbiAgICAgICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSwgZmlsdGVyKGRhdGUgPT4gISFkYXRlICYmIHRoaXMuX2lzUmFuZ2VFbmQgJiYgdGhpcy5kYXRlUGlja2VyLmluaXRpYWxpc2VkKSwgZGVsYXkoMCkpXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZShkYXRlID0+IHRoaXMub25SYW5nZUNoYW5nZShkYXRlKSk7XG5cbiAgICAgICAgICAgIC8vIHN1YnNjcmliZSB0byBjaGFuZ2VzIHRvIHRoZSBlbmQgZGF0ZVxuICAgICAgICAgICAgdGhpcy5fcmFuZ2VTZXJ2aWNlLm9uRW5kQ2hhbmdlXG4gICAgICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSksIGZpbHRlcihkYXRlID0+ICEhZGF0ZSAmJiB0aGlzLl9pc1JhbmdlU3RhcnQgJiYgdGhpcy5kYXRlUGlja2VyLmluaXRpYWxpc2VkKSwgZGVsYXkoMCkpXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZShkYXRlID0+IHRoaXMub25SYW5nZUNoYW5nZShkYXRlKSk7XG5cbiAgICAgICAgICAgIC8vIHdoZW4gdGhlIHJhbmdlIGlzIGNsZWFyZWQgcmVzZXQgdGhlIHNlbGVjdGVkIGRhdGUgc28gd2UgY2FuIGNsaWNrIG9uIHRoZSBzYW1lIGRhdGUgYWdhaW4gaWYgd2Ugd2FudCB0b1xuICAgICAgICAgICAgdGhpcy5fcmFuZ2VTZXJ2aWNlLm9uQ2xlYXIucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKCgpID0+IHRoaXMuZGF0ZVBpY2tlci5zZWxlY3RlZCQubmV4dChudWxsKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG5cbiAgICAgICAgLy8gdXBkYXRlIHdoZW4gdGhlcmUgYXJlIGNoYW5nZXMgdG8gdGhlIG1pbi9tYXggdmFsdWVzXG4gICAgICAgIG1lcmdlKHRoaXMuZGF0ZVBpY2tlci5taW4kLCB0aGlzLmRhdGVQaWNrZXIubWF4JCkucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fY2hhbmdlRGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpKTtcblxuICAgICAgICAvLyBpZiB3ZSBvcGVuIGFuZCB0aGUgcmFuZ2Ugc3RhcnQgaXMgYWxyZWFkeSBzZWxlY3RlZCwgZW5zdXJlIHRoYXQgd2UgbW92ZSB0aGUgZW5kIHBpY2tlciB0byBhIG1vbnRoIHdpdGggb3B0aW9uc1xuICAgICAgICBpZiAoIXRoaXMuZGF0ZVBpY2tlci5pbml0aWFsaXNlZCAmJiB0aGlzLl9yYW5nZVN0YXJ0ICYmICF0aGlzLl9yYW5nZUVuZCAmJiB0aGlzLl9pc1JhbmdlRW5kKSB7XG4gICAgICAgICAgICB0aGlzLm9uUmFuZ2VDaGFuZ2UodGhpcy5fcmFuZ2VTdGFydCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB3ZSBvcGVuIGFuZCB0aGUgcmFuZ2UgZW5kIGlzIGFscmVhZHkgc2VsZWN0ZWQsIGVuc3VyZSB0aGF0IHdlIG1vdmUgdGhlIHN0YXJ0IHBpY2tlciB0byBhIG1vbnRoIHdpdGggb3B0aW9uc1xuICAgICAgICBpZiAoIXRoaXMuZGF0ZVBpY2tlci5pbml0aWFsaXNlZCAmJiB0aGlzLl9yYW5nZUVuZCAmJiAhdGhpcy5fcmFuZ2VTdGFydCAmJiB0aGlzLl9pc1JhbmdlU3RhcnQpIHtcbiAgICAgICAgICAgIHRoaXMub25SYW5nZUNoYW5nZSh0aGlzLl9yYW5nZUVuZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95LmNvbXBsZXRlKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE5hdmlnYXRlIHRvIHRoZSBwcmV2aW91cyBwYWdlIG9mIGRhdGVzXG4gICAgICovXG4gICAgcHJldmlvdXMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGF0ZVBpY2tlci5zZXRWaWV3cG9ydE1vbnRoKHRoaXMuZGF0ZVBpY2tlci5tb250aCQudmFsdWUgLSAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBOYXZpZ2F0ZSB0byB0aGUgbmV4dCBwYWdlIG9mIGRhdGVzXG4gICAgICovXG4gICAgbmV4dCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kYXRlUGlja2VyLnNldFZpZXdwb3J0TW9udGgodGhpcy5kYXRlUGlja2VyLm1vbnRoJC52YWx1ZSArIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdCBhIHBhcnRpY3VsYXIgZGF0ZVxuICAgICAqIEBwYXJhbSBkYXRlIHRoZSBkYXRlIHRvIHNlbGVjdFxuICAgICAqL1xuICAgIHNlbGVjdChkYXRlOiBEYXRlKTogdm9pZCB7XG5cbiAgICAgICAgLy8gaWYgd2UgYXJlIHRoZSBzdGFydCByYW5nZSBwaWNrZXIgYW5kIHdlIGNsaWNrIHRoZSBhbHJlYWR5IHNlbGVjdGVkIGRheSBkZXNlbGVjdCBpdFxuICAgICAgICBpZiAodGhpcy5faXNSYW5nZU1vZGUgJiYgdGhpcy5faXNSYW5nZVN0YXJ0ICYmIHRoaXMuX3JhbmdlU3RhcnQgJiYgY29tcGFyZURheXModGhpcy5fcmFuZ2VTdGFydCwgZGF0ZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX3JhbmdlU2VydmljZS5zZXRTdGFydERhdGUobnVsbCk7XG4gICAgICAgICAgICB0aGlzLmRhdGVQaWNrZXIuc2VsZWN0ZWQkLm5leHQobnVsbCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB3ZSBhcmUgdGhlIGVuZCByYW5nZSBwaWNrZXIgYW5kIHdlIGNsaWNrIHRoZSBhbHJlYWR5IHNlbGVjdGVkIGRheSBkZXNlbGVjdCBpdFxuICAgICAgICBpZiAodGhpcy5faXNSYW5nZU1vZGUgJiYgdGhpcy5faXNSYW5nZUVuZCAmJiB0aGlzLl9yYW5nZUVuZCAmJiBjb21wYXJlRGF5cyh0aGlzLl9yYW5nZUVuZCwgZGF0ZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX3JhbmdlU2VydmljZS5zZXRFbmREYXRlKG51bGwpO1xuICAgICAgICAgICAgdGhpcy5kYXRlUGlja2VyLnNlbGVjdGVkJC5uZXh0KG51bGwpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgd2UgYXJlIGluIHJhbmdlIG1vZGUgZW5zdXJlIHdlIGluY2x1ZGUgdGhlIHRpbWUgZnJvbSB0aGUgdGltZSBwaWNrZXJcbiAgICAgICAgaWYgKHRoaXMuX2lzUmFuZ2VNb2RlKSB7XG4gICAgICAgICAgICAvLyB1cGRhdGUgdGhlIGN1cnJlbnQgZGF0ZSBvYmplY3RcbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1JhbmdlU3RhcnQgJiYgIXRoaXMuX3JhbmdlU2VydmljZS5zaG93VGltZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVBpY2tlci5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RnVsbFllYXIoKSwgMCwgMCwgMCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2lzUmFuZ2VFbmQgJiYgIXRoaXMuX3JhbmdlU2VydmljZS5zaG93VGltZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVBpY2tlci5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RnVsbFllYXIoKSwgMjMsIDU5LCA1OSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVBpY2tlci5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RnVsbFllYXIoKSwgdGhpcy5kYXRlUGlja2VyLmhvdXJzLCB0aGlzLmRhdGVQaWNrZXIubWludXRlcywgdGhpcy5kYXRlUGlja2VyLnNlY29uZHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSBjdXJyZW50IGRhdGUgb2JqZWN0XG4gICAgICAgICAgICB0aGlzLmRhdGVQaWNrZXIuc2V0RGF0ZShkYXRlLmdldERhdGUoKSwgZGF0ZS5nZXRNb250aCgpLCBkYXRlLmdldEZ1bGxZZWFyKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZm9jdXMgdGhlIG5ld2x5IHNlbGVjdGVkIGRhdGVcbiAgICAgICAgdGhpcy5kYXlTZXJ2aWNlLnNldEZvY3VzKGRhdGUuZ2V0RGF0ZSgpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RnVsbFllYXIoKSk7XG5cbiAgICAgICAgLy8gaWYgd2Ugc2VsZWN0IGEgc3RhcnQgZGF0ZSB0aGF0IGlzIGFmdGVyIHRoZSBlbmQgZGF0ZSB0aGVuIGNsZWFyIHRoZSBlbmQgZGF0ZVxuICAgICAgICBpZiAodGhpcy5faXNSYW5nZU1vZGUgJiYgdGhpcy5faXNSYW5nZVN0YXJ0ICYmIHRoaXMuX3JhbmdlU3RhcnQgJiYgdGhpcy5fcmFuZ2VFbmQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9yYW5nZVN0YXJ0LmdldFRpbWUoKSA+IHRoaXMuX3JhbmdlRW5kLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JhbmdlU2VydmljZS5zZXRFbmREYXRlKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgd2Ugc2VsZWN0IGEgZW5kIGRhdGUgdGhhdCBpcyBiZWZvcmUgdGhlIHN0YXJ0IGRhdGUgdGhlbiBjbGVhciB0aGUgc3RhcnQgZGF0ZVxuICAgICAgICBpZiAodGhpcy5faXNSYW5nZU1vZGUgJiYgdGhpcy5faXNSYW5nZUVuZCAmJiB0aGlzLl9yYW5nZVN0YXJ0ICYmIHRoaXMuX3JhbmdlRW5kKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fcmFuZ2VFbmQuZ2V0VGltZSgpIDwgdGhpcy5fcmFuZ2VTdGFydC5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yYW5nZVNlcnZpY2Uuc2V0U3RhcnREYXRlKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdHJhY2tXZWVrQnlGbihpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cblxuICAgIHRyYWNrRGF5QnlGbihfaW5kZXg6IG51bWJlciwgaXRlbTogRGF5Vmlld0l0ZW0pOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYCR7aXRlbS5kYXl9ICR7aXRlbS5tb250aH0gJHtpdGVtLnllYXJ9YDtcbiAgICB9XG5cbiAgICBmb2N1c0RhdGUoaXRlbTogRGF5Vmlld0l0ZW0sIGRheU9mZnNldDogbnVtYmVyKTogdm9pZCB7XG5cbiAgICAgICAgLy8gZGV0ZXJtaW5lIHRoZSBkYXRlIG9mIHRoZSBkYXlcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gbmV3IERhdGUoaXRlbS5kYXRlLnNldERhdGUoaXRlbS5kYXRlLmdldERhdGUoKSArIGRheU9mZnNldCkpO1xuXG4gICAgICAgIC8vIHdlIHNob3VsZCBmb3JjZSB0aGUgb3JpZ2luIHRvIGJlIGtleWJvYXJkXG4gICAgICAgIHRoaXMuX2ZvY3VzT3JpZ2luLnNldE9yaWdpbigna2V5Ym9hcmQnKTtcblxuICAgICAgICAvLyBpZGVudGlmeSB3aGljaCBkYXRlIHNob3VsZCBiZSBmb2N1c2VkXG4gICAgICAgIHRoaXMuZGF5U2VydmljZS5zZXRGb2N1cyh0YXJnZXQuZ2V0RGF0ZSgpLCB0YXJnZXQuZ2V0TW9udGgoKSwgdGFyZ2V0LmdldEZ1bGxZZWFyKCkpO1xuICAgIH1cblxuICAgIGdldFRhYmJhYmxlKGl0ZW06IERheVZpZXdJdGVtKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGZvY3VzZWQgPSB0aGlzLmRheVNlcnZpY2UuZm9jdXNlZCQudmFsdWU7XG4gICAgICAgIGNvbnN0IGdyaWQgPSB0aGlzLmRheVNlcnZpY2UuZ3JpZCQudmFsdWU7XG4gICAgICAgIGNvbnN0IG1vbnRoID0gdGhpcy5kYXRlUGlja2VyLm1vbnRoJC52YWx1ZTtcblxuICAgICAgICAvLyBpZiB0aGVyZSBpcyBhIGZvY3VzZWQgbW9udGggY2hlY2sgaWYgdGhpcyBpcyBpdFxuICAgICAgICBpZiAoZm9jdXNlZCkge1xuXG4gICAgICAgICAgICAvLyBjaGVjayBpZiB0aGUgZm9jdXNlZCBkYXkgaXMgdmlzaWJsZVxuICAgICAgICAgICAgY29uc3QgaXNGb2N1c2VkRGF5VmlzaWJsZSA9ICEhZ3JpZC5maW5kKHJvdyA9PiAhIXJvdy5maW5kKF9pdGVtID0+IF9pdGVtLmRheSA9PT0gZm9jdXNlZC5kYXkgJiYgX2l0ZW0ubW9udGggPT09IGZvY3VzZWQubW9udGggJiYgX2l0ZW0ueWVhciA9PT0gZm9jdXNlZC55ZWFyICYmIF9pdGVtLm1vbnRoID09PSBtb250aCkpO1xuXG4gICAgICAgICAgICBpZiAoaXNGb2N1c2VkRGF5VmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmb2N1c2VkLmRheSA9PT0gaXRlbS5kYXkgJiYgZm9jdXNlZC5tb250aCA9PT0gaXRlbS5tb250aCAmJiBmb2N1c2VkLnllYXIgPT09IGl0ZW0ueWVhcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIHRoZXJlIGlzIG5vIGZvY3VzYWJsZSBkYXkgdGhlbiBjaGVjayBpZiB0aGVyZSBpcyBhIHNlbGVjdGVkIGRheVxuICAgICAgICBjb25zdCBpc1NlbGVjdGVkRGF5VmlzaWJsZSA9ICEhZ3JpZC5maW5kKHJvdyA9PiAhIXJvdy5maW5kKGRheSA9PiBkYXkuaXNBY3RpdmUpKTtcblxuICAgICAgICBpZiAoaXNTZWxlY3RlZERheVZpc2libGUpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLmlzQWN0aXZlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluZCB0aGUgZmlyc3Qgbm9uIGRpc2FibGVkIGRheSB0aGF0IGlzIHBhcnQgb2YgdGhlIGN1cnJlbnQgbW9udGhcbiAgICAgICAgZm9yIChjb25zdCByb3cgb2YgZ3JpZCkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2Ygcm93KSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbiA9PT0gaXRlbSAmJiBjb2x1bW4ubW9udGggPT09IG1vbnRoICYmICF0aGlzLmdldERpc2FibGVkKGNvbHVtbi5kYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0RGlzYWJsZWQoZGF0ZTogRGF0ZSk6IGJvb2xlYW4ge1xuXG4gICAgICAgIC8vIGlmIHdlIGFyZSBub3QgaW4gcmFuZ2UgbW9kZSB0aGVuIGl0IHdpbGwgYWx3YXlzIGJlIGVuYWJsZWRcbiAgICAgICAgaWYgKHRoaXMuX2lzUmFuZ2VNb2RlKSB7XG5cbiAgICAgICAgICAgIC8vIGlmIHdlIGFyZSByYW5nZSBzdGFydCBhbmQgZGF0ZXMgYXJlIGFmdGVyIHRoZSByYW5nZSBlbmQgdGhlbiB0aGV5IHNob3VsZCBhbHNvIGJlIGRpc2FibGVkXG4gICAgICAgICAgICBpZiAodGhpcy5faXNSYW5nZVN0YXJ0ICYmICF0aGlzLl9yYW5nZVN0YXJ0ICYmIHRoaXMuX3JhbmdlRW5kICYmIGlzRGF0ZUFmdGVyKGRhdGUsIHRoaXMuX3JhbmdlRW5kKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiB3ZSBhcmUgcmFuZ2UgZW5kIGFuZCBkYXRlcyBhcmUgYmVmb3JlIHRoZSByYW5nZSBzdGFydCB0aGVuIHRoZXkgc2hvdWxkIGFsc28gYmUgZGlzYWJsZWRcbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1JhbmdlRW5kICYmICF0aGlzLl9yYW5nZUVuZCAmJiB0aGlzLl9yYW5nZV