ngx-bootstrap
Version:
Angular Bootstrap
261 lines • 50.2 kB
JavaScript
import { Component, ElementRef, EventEmitter, HostBinding, Renderer2, ViewChild } from '@angular/core';
import { take } from 'rxjs/operators';
import { getFullYear, getMonth } from 'ngx-bootstrap/chronos';
import { PositioningService } from 'ngx-bootstrap/positioning';
import { TimepickerComponent } from 'ngx-bootstrap/timepicker';
import { BsDatepickerAbstractComponent } from '../../base/bs-datepicker-container';
import { BsDatepickerConfig } from '../../bs-datepicker.config';
import { BsDatepickerActions } from '../../reducer/bs-datepicker.actions';
import { BsDatepickerEffects } from '../../reducer/bs-datepicker.effects';
import { BsDatepickerStore } from '../../reducer/bs-datepicker.store';
import { datepickerAnimation } from '../../datepicker-animations';
import { dayInMilliseconds } from '../../reducer/_defaults';
import * as i0 from "@angular/core";
import * as i1 from "../../bs-datepicker.config";
import * as i2 from "../../reducer/bs-datepicker.store";
import * as i3 from "../../reducer/bs-datepicker.actions";
import * as i4 from "../../reducer/bs-datepicker.effects";
import * as i5 from "ngx-bootstrap/positioning";
import * as i6 from "@angular/common";
import * as i7 from "ngx-bootstrap/timepicker";
import * as i8 from "./bs-custom-dates-view.component";
import * as i9 from "./bs-days-calendar-view.component";
import * as i10 from "./bs-months-calendar-view.component";
import * as i11 from "./bs-years-calendar-view.component";
export class BsDaterangepickerContainerComponent extends BsDatepickerAbstractComponent {
set value(value) {
this._effects?.setRangeValue(value);
}
get isDatePickerDisabled() {
return !!this._config.isDisabled;
}
get isDatepickerDisabled() {
return this.isDatePickerDisabled ? '' : null;
}
get isDatepickerReadonly() {
return this.isDatePickerDisabled ? '' : null;
}
constructor(_renderer, _config, _store, _element, _actions, _effects, _positionService) {
super();
this._config = _config;
this._store = _store;
this._element = _element;
this._actions = _actions;
this._positionService = _positionService;
this.valueChange = new EventEmitter();
this.animationState = 'void';
this._rangeStack = [];
this.chosenRange = [];
this._subs = [];
this.isRangePicker = true;
this._effects = _effects;
this.customRanges = this._config.ranges || [];
this.customRangeBtnLbl = this._config.customRangeButtonLabel;
_renderer.setStyle(_element.nativeElement, 'display', 'block');
_renderer.setStyle(_element.nativeElement, 'position', 'absolute');
}
ngOnInit() {
this._positionService.setOptions({
modifiers: {
flip: {
enabled: this._config.adaptivePosition
},
preventOverflow: {
enabled: this._config.adaptivePosition
}
},
allowedPositions: this._config.allowedPositions
});
this._positionService.event$?.pipe(take(1))
.subscribe(() => {
this._positionService.disable();
if (this._config.isAnimated) {
this.animationState = this.isTopPosition ? 'animated-up' : 'animated-down';
return;
}
this.animationState = 'unanimated';
});
this.containerClass = this._config.containerClass;
this.isOtherMonthsActive = this._config.selectFromOtherMonth;
this.withTimepicker = this._config.withTimepicker;
this._effects?.init(this._store)
// intial state options
// todo: fix this, split configs
.setOptions(this._config)
// data binding view --> model
.setBindings(this)
// set event handlers
.setEventHandlers(this)
.registerDatepickerSideEffects();
let currentDate;
// todo: move it somewhere else
// on selected date change
this._subs.push(this._store
.select(state => state.selectedRange)
.subscribe(dateRange => {
currentDate = dateRange;
this.valueChange.emit(dateRange);
this.chosenRange = dateRange || [];
}));
this._subs.push(this._store
.select(state => state.selectedTime)
.subscribe((time) => {
if ((!time[0] || !time[1]) ||
(!(time[0] instanceof Date) || !(time[1] instanceof Date)) ||
(currentDate && (time[0] === currentDate[0] && time[1] === currentDate[1]))) {
return;
}
this.valueChange.emit(time);
this.chosenRange = time || [];
}));
}
ngAfterViewInit() {
this.selectedTimeSub.add(this.selectedTime?.subscribe((val) => {
if (Array.isArray(val) && val.length >= 2) {
this.startTimepicker?.writeValue(val[0]);
this.endTimepicker?.writeValue(val[1]);
}
}));
this.startTimepicker?.registerOnChange((val) => {
this.timeSelectHandler(val, 0);
});
this.endTimepicker?.registerOnChange((val) => {
this.timeSelectHandler(val, 1);
});
}
get isTopPosition() {
return this._element.nativeElement.classList.contains('top');
}
positionServiceEnable() {
this._positionService.enable();
}
timeSelectHandler(date, index) {
this._store.dispatch(this._actions.selectTime(date, index));
}
daySelectHandler(day) {
if (!day) {
return;
}
const isDisabled = this.isOtherMonthsActive ? day.isDisabled : (day.isOtherMonth || day.isDisabled);
if (isDisabled) {
return;
}
this.rangesProcessing(day);
}
monthSelectHandler(day) {
if (!day || day.isDisabled) {
return;
}
day.isSelected = true;
if (this._config.minMode !== 'month') {
if (day.isDisabled) {
return;
}
this._store.dispatch(this._actions.navigateTo({
unit: {
month: getMonth(day.date),
year: getFullYear(day.date)
},
viewMode: 'day'
}));
return;
}
this.rangesProcessing(day);
}
yearSelectHandler(day) {
if (!day || day.isDisabled) {
return;
}
day.isSelected = true;
if (this._config.minMode !== 'year') {
if (day.isDisabled) {
return;
}
this._store.dispatch(this._actions.navigateTo({
unit: {
year: getFullYear(day.date)
},
viewMode: 'month'
}));
return;
}
this.rangesProcessing(day);
}
rangesProcessing(day) {
// if only one date is already selected
// and user clicks on previous date
// start selection from new date
// but if new date is after initial one
// than finish selection
if (this._rangeStack.length === 1) {
this._rangeStack =
day.date >= this._rangeStack[0]
? [this._rangeStack[0], day.date]
: [day.date];
}
if (this._config.maxDateRange) {
this.setMaxDateRangeOnCalendar(day.date);
}
if (this._rangeStack.length === 0) {
this._rangeStack = [day.date];
if (this._config.maxDateRange) {
this.setMaxDateRangeOnCalendar(day.date);
}
}
this._store.dispatch(this._actions.selectRange(this._rangeStack));
if (this._rangeStack.length === 2) {
this._rangeStack = [];
}
}
ngOnDestroy() {
for (const sub of this._subs) {
sub.unsubscribe();
}
this.selectedTimeSub.unsubscribe();
this._effects?.destroy();
}
setRangeOnCalendar(dates) {
if (dates) {
this._rangeStack = dates.value instanceof Date ? [dates.value] : dates.value;
}
this._store.dispatch(this._actions.selectRange(this._rangeStack));
}
setMaxDateRangeOnCalendar(currentSelection) {
let maxDateRange = new Date(currentSelection);
if (this._config.maxDate) {
const maxDateValueInMilliseconds = this._config.maxDate.getTime();
const maxDateRangeInMilliseconds = currentSelection.getTime() + ((this._config.maxDateRange || 0) * dayInMilliseconds);
maxDateRange = maxDateRangeInMilliseconds > maxDateValueInMilliseconds ?
new Date(this._config.maxDate) :
new Date(maxDateRangeInMilliseconds);
}
else {
maxDateRange.setDate(currentSelection.getDate() + (this._config.maxDateRange || 0));
}
this._effects?.setMaxDate(maxDateRange);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.4", ngImport: i0, type: BsDaterangepickerContainerComponent, deps: [{ token: i0.Renderer2 }, { token: i1.BsDatepickerConfig }, { token: i2.BsDatepickerStore }, { token: i0.ElementRef }, { token: i3.BsDatepickerActions }, { token: i4.BsDatepickerEffects }, { token: i5.PositioningService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.4", type: BsDaterangepickerContainerComponent, selector: "bs-daterangepicker-container", host: { attributes: { "role": "dialog", "aria-label": "calendar" }, listeners: { "click": "_stopPropagation($event)" }, properties: { "attr.disabled": "this.isDatepickerDisabled", "attr.readonly": "this.isDatepickerReadonly" }, classAttribute: "bottom" }, providers: [BsDatepickerStore, BsDatepickerEffects], viewQueries: [{ propertyName: "startTimepicker", first: true, predicate: ["startTP"], descendants: true }, { propertyName: "endTimepicker", first: true, predicate: ["endTP"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<!-- days calendar view mode -->\n<div class=\"bs-datepicker\" [ngClass]=\"containerClass\" *ngIf=\"viewMode | async\">\n <div class=\"bs-datepicker-container\"\n [@datepickerAnimation]=\"animationState\"\n (@datepickerAnimation.done)=\"positionServiceEnable()\">\n <!--calendars-->\n <div class=\"bs-calendar-container\" [ngSwitch]=\"viewMode | async\" role=\"application\">\n <!--days calendar-->\n <ng-container *ngSwitchCase=\"'day'\">\n <div class=\"bs-media-container\">\n <bs-days-calendar-view\n *ngFor=\"let calendar of daysCalendar$ | async\"\n [class.bs-datepicker-multiple]=\"multipleCalendars\"\n [calendar]=\"calendar\"\n [isDisabled]=\"isDatePickerDisabled\"\n [options]=\"options$ | async\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"dayHoverHandler($event)\"\n (onHoverWeek)=\"weekHoverHandler($event)\"\n (onSelect)=\"daySelectHandler($event)\">\n </bs-days-calendar-view>\n </div>\n <div *ngIf=\"withTimepicker\" class=\"bs-timepicker-in-datepicker-container\">\n <timepicker #startTP [disabled]=\"isDatePickerDisabled\"></timepicker>\n <timepicker #endTP *ngIf=\"isRangePicker\" [disabled]=\"isDatePickerDisabled\"></timepicker>\n </div>\n </ng-container>\n\n <!--months calendar-->\n <div *ngSwitchCase=\"'month'\" class=\"bs-media-container\">\n <bs-month-calendar-view\n *ngFor=\"let calendar of monthsCalendar | async\"\n [class.bs-datepicker-multiple]=\"multipleCalendars\"\n [calendar]=\"calendar\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"monthHoverHandler($event)\"\n (onSelect)=\"monthSelectHandler($event)\">\n </bs-month-calendar-view>\n </div>\n\n <!--years calendar-->\n <div *ngSwitchCase=\"'year'\" class=\"bs-media-container\">\n <bs-years-calendar-view\n *ngFor=\"let calendar of yearsCalendar | async\"\n [class.bs-datepicker-multiple]=\"multipleCalendars\"\n [calendar]=\"calendar\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"yearHoverHandler($event)\"\n (onSelect)=\"yearSelectHandler($event)\">\n </bs-years-calendar-view>\n </div>\n </div>\n\n <!--applycancel buttons-->\n <div class=\"bs-datepicker-buttons\" *ngIf=\"false\">\n <button class=\"btn btn-success\" type=\"button\">Apply</button>\n <button class=\"btn btn-default\" type=\"button\">Cancel</button>\n </div>\n\n <div class=\"bs-datepicker-buttons\" *ngIf=\"showTodayBtn || showClearBtn\">\n <div class=\"btn-today-wrapper\"\n [class.today-left]=\"todayPos === 'left'\"\n [class.today-right]=\"todayPos === 'right'\"\n [class.today-center]=\"todayPos === 'center'\"\n *ngIf=\"showTodayBtn\">\n <button class=\"btn btn-success\" (click)=\"setToday()\">{{todayBtnLbl}}</button>\n </div>\n\n <div class=\"btn-clear-wrapper\"\n [class.clear-left]=\"clearPos === 'left'\"\n [class.clear-right]=\"clearPos === 'right'\"\n [class.clear-center]=\"clearPos === 'center'\"\n *ngIf=\"showClearBtn\">\n <button class=\"btn btn-success\" (click)=\"clearDate()\">{{clearBtnLbl}}</button>\n </div>\n </div>\n\n </div>\n\n <!--custom dates or date ranges picker-->\n <div class=\"bs-datepicker-custom-range\" *ngIf=\"customRanges && customRanges.length > 0\">\n <bs-custom-date-view\n [selectedRange]=\"chosenRange\"\n [ranges]=\"customRanges\"\n [customRangeLabel]=\"customRangeBtnLbl\"\n (onSelect)=\"setRangeOnCalendar($event)\">\n </bs-custom-date-view>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i6.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i7.TimepickerComponent, selector: "timepicker", inputs: ["hourStep", "minuteStep", "secondsStep", "readonlyInput", "disabled", "mousewheel", "arrowkeys", "showSpinners", "showMeridian", "showMinutes", "showSeconds", "meridians", "min", "max", "hoursPlaceholder", "minutesPlaceholder", "secondsPlaceholder"], outputs: ["isValid", "meridianChange"] }, { kind: "component", type: i8.BsCustomDatesViewComponent, selector: "bs-custom-date-view", inputs: ["ranges", "selectedRange", "customRangeLabel"], outputs: ["onSelect"] }, { kind: "component", type: i9.BsDaysCalendarViewComponent, selector: "bs-days-calendar-view", inputs: ["calendar", "options", "isDisabled"], outputs: ["onNavigate", "onViewMode", "onSelect", "onHover", "onHoverWeek"] }, { kind: "component", type: i10.BsMonthCalendarViewComponent, selector: "bs-month-calendar-view", inputs: ["calendar"], outputs: ["onNavigate", "onViewMode", "onSelect", "onHover"] }, { kind: "component", type: i11.BsYearsCalendarViewComponent, selector: "bs-years-calendar-view", inputs: ["calendar"], outputs: ["onNavigate", "onViewMode", "onSelect", "onHover"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }], animations: [datepickerAnimation] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.4", ngImport: i0, type: BsDaterangepickerContainerComponent, decorators: [{
type: Component,
args: [{ selector: 'bs-daterangepicker-container', providers: [BsDatepickerStore, BsDatepickerEffects], host: {
class: 'bottom',
'(click)': '_stopPropagation($event)',
role: 'dialog',
'aria-label': 'calendar'
}, animations: [datepickerAnimation], template: "<!-- days calendar view mode -->\n<div class=\"bs-datepicker\" [ngClass]=\"containerClass\" *ngIf=\"viewMode | async\">\n <div class=\"bs-datepicker-container\"\n [@datepickerAnimation]=\"animationState\"\n (@datepickerAnimation.done)=\"positionServiceEnable()\">\n <!--calendars-->\n <div class=\"bs-calendar-container\" [ngSwitch]=\"viewMode | async\" role=\"application\">\n <!--days calendar-->\n <ng-container *ngSwitchCase=\"'day'\">\n <div class=\"bs-media-container\">\n <bs-days-calendar-view\n *ngFor=\"let calendar of daysCalendar$ | async\"\n [class.bs-datepicker-multiple]=\"multipleCalendars\"\n [calendar]=\"calendar\"\n [isDisabled]=\"isDatePickerDisabled\"\n [options]=\"options$ | async\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"dayHoverHandler($event)\"\n (onHoverWeek)=\"weekHoverHandler($event)\"\n (onSelect)=\"daySelectHandler($event)\">\n </bs-days-calendar-view>\n </div>\n <div *ngIf=\"withTimepicker\" class=\"bs-timepicker-in-datepicker-container\">\n <timepicker #startTP [disabled]=\"isDatePickerDisabled\"></timepicker>\n <timepicker #endTP *ngIf=\"isRangePicker\" [disabled]=\"isDatePickerDisabled\"></timepicker>\n </div>\n </ng-container>\n\n <!--months calendar-->\n <div *ngSwitchCase=\"'month'\" class=\"bs-media-container\">\n <bs-month-calendar-view\n *ngFor=\"let calendar of monthsCalendar | async\"\n [class.bs-datepicker-multiple]=\"multipleCalendars\"\n [calendar]=\"calendar\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"monthHoverHandler($event)\"\n (onSelect)=\"monthSelectHandler($event)\">\n </bs-month-calendar-view>\n </div>\n\n <!--years calendar-->\n <div *ngSwitchCase=\"'year'\" class=\"bs-media-container\">\n <bs-years-calendar-view\n *ngFor=\"let calendar of yearsCalendar | async\"\n [class.bs-datepicker-multiple]=\"multipleCalendars\"\n [calendar]=\"calendar\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"yearHoverHandler($event)\"\n (onSelect)=\"yearSelectHandler($event)\">\n </bs-years-calendar-view>\n </div>\n </div>\n\n <!--applycancel buttons-->\n <div class=\"bs-datepicker-buttons\" *ngIf=\"false\">\n <button class=\"btn btn-success\" type=\"button\">Apply</button>\n <button class=\"btn btn-default\" type=\"button\">Cancel</button>\n </div>\n\n <div class=\"bs-datepicker-buttons\" *ngIf=\"showTodayBtn || showClearBtn\">\n <div class=\"btn-today-wrapper\"\n [class.today-left]=\"todayPos === 'left'\"\n [class.today-right]=\"todayPos === 'right'\"\n [class.today-center]=\"todayPos === 'center'\"\n *ngIf=\"showTodayBtn\">\n <button class=\"btn btn-success\" (click)=\"setToday()\">{{todayBtnLbl}}</button>\n </div>\n\n <div class=\"btn-clear-wrapper\"\n [class.clear-left]=\"clearPos === 'left'\"\n [class.clear-right]=\"clearPos === 'right'\"\n [class.clear-center]=\"clearPos === 'center'\"\n *ngIf=\"showClearBtn\">\n <button class=\"btn btn-success\" (click)=\"clearDate()\">{{clearBtnLbl}}</button>\n </div>\n </div>\n\n </div>\n\n <!--custom dates or date ranges picker-->\n <div class=\"bs-datepicker-custom-range\" *ngIf=\"customRanges && customRanges.length > 0\">\n <bs-custom-date-view\n [selectedRange]=\"chosenRange\"\n [ranges]=\"customRanges\"\n [customRangeLabel]=\"customRangeBtnLbl\"\n (onSelect)=\"setRangeOnCalendar($event)\">\n </bs-custom-date-view>\n </div>\n</div>\n" }]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i1.BsDatepickerConfig }, { type: i2.BsDatepickerStore }, { type: i0.ElementRef }, { type: i3.BsDatepickerActions }, { type: i4.BsDatepickerEffects }, { type: i5.PositioningService }]; }, propDecorators: { startTimepicker: [{
type: ViewChild,
args: ['startTP']
}], endTimepicker: [{
type: ViewChild,
args: ['endTP']
}], isDatepickerDisabled: [{
type: HostBinding,
args: ['attr.disabled']
}], isDatepickerReadonly: [{
type: HostBinding,
args: ['attr.readonly']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnMtZGF0ZXJhbmdlcGlja2VyLWNvbnRhaW5lci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvZGF0ZXBpY2tlci90aGVtZXMvYnMvYnMtZGF0ZXJhbmdlcGlja2VyLWNvbnRhaW5lci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvZGF0ZXBpY2tlci90aGVtZXMvYnMvYnMtZGF0ZXBpY2tlci12aWV3Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUFFLFdBQVcsRUFHekIsU0FBUyxFQUNULFNBQVMsRUFDVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHdEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUUvRCxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUNuRixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUMxRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUMxRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVsRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQzs7Ozs7Ozs7Ozs7OztBQWM1RCxNQUFNLE9BQU8sbUNBQW9DLFNB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VSxtQ0FBbUM7a0dBQW5DLG1DQUFtQyx1VEFWbkMsQ0FBQyxpQkFBaUIsRUFBRSxtQkFBbUIsQ0FBQyxzUEM5QnJELDQzSEE0RkEsOHJERHREYyxDQUFDLG1CQUFtQixDQUFDOzsyRkFFdEIsbUNBQW1DO2tCQVovQyxTQUFTOytCQUNFLDhCQUE4QixhQUM3QixDQUFDLGlCQUFpQixFQUFFLG1CQUFtQixDQUFDLFFBRTdDO3dCQUNKLEtBQUssRUFBRSxRQUFRO3dCQUNmLFNBQVMsRUFBRSwwQkFBMEI7d0JBQ3JDLElBQUksRUFBRSxRQUFRO3dCQUNkLFlBQVksRUFBRSxVQUFVO3FCQUN6QixjQUNXLENBQUMsbUJBQW1CLENBQUM7K1JBaUJYLGVBQWU7c0JBQXBDLFNBQVM7dUJBQUMsU0FBUztnQkFDQSxhQUFhO3NCQUFoQyxTQUFTO3VCQUFDLE9BQU87Z0JBTWlCLG9CQUFvQjtzQkFBdEQsV0FBVzt1QkFBRSxlQUFlO2dCQUlNLG9CQUFvQjtzQkFBdEQsV0FBVzt1QkFBRSxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsIEhvc3RCaW5kaW5nLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgUmVuZGVyZXIyLFxuICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IHRha2UgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgZ2V0RnVsbFllYXIsIGdldE1vbnRoIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9jaHJvbm9zJztcbmltcG9ydCB7IFBvc2l0aW9uaW5nU2VydmljZSB9IGZyb20gJ25neC1ib290c3RyYXAvcG9zaXRpb25pbmcnO1xuaW1wb3J0IHsgVGltZXBpY2tlckNvbXBvbmVudCB9IGZyb20gJ25neC1ib290c3RyYXAvdGltZXBpY2tlcic7XG5cbmltcG9ydCB7IEJzRGF0ZXBpY2tlckFic3RyYWN0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vYmFzZS9icy1kYXRlcGlja2VyLWNvbnRhaW5lcic7XG5pbXBvcnQgeyBCc0RhdGVwaWNrZXJDb25maWcgfSBmcm9tICcuLi8uLi9icy1kYXRlcGlja2VyLmNvbmZpZyc7XG5pbXBvcnQgeyBDYWxlbmRhckNlbGxWaWV3TW9kZWwsIERheVZpZXdNb2RlbCB9IGZyb20gJy4uLy4uL21vZGVscyc7XG5pbXBvcnQgeyBCc0RhdGVwaWNrZXJBY3Rpb25zIH0gZnJvbSAnLi4vLi4vcmVkdWNlci9icy1kYXRlcGlja2VyLmFjdGlvbnMnO1xuaW1wb3J0IHsgQnNEYXRlcGlja2VyRWZmZWN0cyB9IGZyb20gJy4uLy4uL3JlZHVjZXIvYnMtZGF0ZXBpY2tlci5lZmZlY3RzJztcbmltcG9ydCB7IEJzRGF0ZXBpY2tlclN0b3JlIH0gZnJvbSAnLi4vLi4vcmVkdWNlci9icy1kYXRlcGlja2VyLnN0b3JlJztcbmltcG9ydCB7IGRhdGVwaWNrZXJBbmltYXRpb24gfSBmcm9tICcuLi8uLi9kYXRlcGlja2VyLWFuaW1hdGlvbnMnO1xuaW1wb3J0IHsgQnNDdXN0b21EYXRlcyB9IGZyb20gJy4vYnMtY3VzdG9tLWRhdGVzLXZpZXcuY29tcG9uZW50JztcbmltcG9ydCB7IGRheUluTWlsbGlzZWNvbmRzIH0gZnJvbSAnLi4vLi4vcmVkdWNlci9fZGVmYXVsdHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdicy1kYXRlcmFuZ2VwaWNrZXItY29udGFpbmVyJyxcbiAgcHJvdmlkZXJzOiBbQnNEYXRlcGlja2VyU3RvcmUsIEJzRGF0ZXBpY2tlckVmZmVjdHNdLFxuICB0ZW1wbGF0ZVVybDogJy4vYnMtZGF0ZXBpY2tlci12aWV3Lmh0bWwnLFxuICBob3N0OiB7XG4gICAgY2xhc3M6ICdib3R0b20nLFxuICAgICcoY2xpY2spJzogJ19zdG9wUHJvcGFnYXRpb24oJGV2ZW50KScsXG4gICAgcm9sZTogJ2RpYWxvZycsXG4gICAgJ2FyaWEtbGFiZWwnOiAnY2FsZW5kYXInXG4gIH0sXG4gIGFuaW1hdGlvbnM6IFtkYXRlcGlja2VyQW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBCc0RhdGVyYW5nZXBpY2tlckNvbnRhaW5lckNvbXBvbmVudCBleHRlbmRzIEJzRGF0ZXBpY2tlckFic3RyYWN0Q29tcG9uZW50XG4gIGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuXG4gIHNldCB2YWx1ZSh2YWx1ZTogKERhdGV8dW5kZWZpbmVkKVtdIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fZWZmZWN0cz8uc2V0UmFuZ2VWYWx1ZSh2YWx1ZSk7XG4gIH1cblxuICB2YWx1ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0ZVtdPigpO1xuICBhbmltYXRpb25TdGF0ZSA9ICd2b2lkJztcblxuICBfcmFuZ2VTdGFjazogRGF0ZVtdID0gW107XG4gIG92ZXJyaWRlIGNob3NlblJhbmdlOiBEYXRlW10gPSBbXTtcbiAgX3N1YnM6IFN1YnNjcmlwdGlvbltdID0gW107XG4gIG92ZXJyaWRlIGlzUmFuZ2VQaWNrZXIgPSB0cnVlO1xuXG4gIEBWaWV3Q2hpbGQoJ3N0YXJ0VFAnKSBzdGFydFRpbWVwaWNrZXI/OiBUaW1lcGlja2VyQ29tcG9uZW50O1xuICBAVmlld0NoaWxkKCdlbmRUUCcpIGVuZFRpbWVwaWNrZXI/OiBUaW1lcGlja2VyQ29tcG9uZW50O1xuXG4gIGdldCBpc0RhdGVQaWNrZXJEaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLl9jb25maWcuaXNEaXNhYmxlZDtcbiAgfVxuXG4gIEBIb3N0QmluZGluZyAoJ2F0dHIuZGlzYWJsZWQnKSBnZXQgaXNEYXRlcGlja2VyRGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNEYXRlUGlja2VyRGlzYWJsZWQgPyAnJyA6IG51bGw7XG4gIH1cblxuICBASG9zdEJpbmRpbmcgKCdhdHRyLnJlYWRvbmx5JykgZ2V0IGlzRGF0ZXBpY2tlclJlYWRvbmx5KCkge1xuICAgIHJldHVybiB0aGlzLmlzRGF0ZVBpY2tlckRpc2FibGVkID8gJycgOiBudWxsO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgX3JlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgcHJpdmF0ZSBfY29uZmlnOiBCc0RhdGVwaWNrZXJDb25maWcsXG4gICAgcHJpdmF0ZSBfc3RvcmU6IEJzRGF0ZXBpY2tlclN0b3JlLFxuICAgIHByaXZhdGUgX2VsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBfYWN0aW9uczogQnNEYXRlcGlja2VyQWN0aW9ucyxcbiAgICBfZWZmZWN0czogQnNEYXRlcGlja2VyRWZmZWN0cyxcbiAgICBwcml2YXRlIF9wb3NpdGlvblNlcnZpY2U6IFBvc2l0aW9uaW5nU2VydmljZVxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuX2VmZmVjdHMgPSBfZWZmZWN0cztcblxuICAgIHRoaXMuY3VzdG9tUmFuZ2VzID0gdGhpcy5fY29uZmlnLnJhbmdlcyB8fCBbXTtcbiAgICB0aGlzLmN1c3RvbVJhbmdlQnRuTGJsID0gdGhpcy5fY29uZmlnLmN1c3RvbVJhbmdlQnV0dG9uTGFiZWw7XG5cbiAgICBfcmVuZGVyZXIuc2V0U3R5bGUoX2VsZW1lbnQubmF0aXZlRWxlbWVudCwgJ2Rpc3BsYXknLCAnYmxvY2snKTtcbiAgICBfcmVuZGVyZXIuc2V0U3R5bGUoX2VsZW1lbnQubmF0aXZlRWxlbWVudCwgJ3Bvc2l0aW9uJywgJ2Fic29sdXRlJyk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLl9wb3NpdGlvblNlcnZpY2Uuc2V0T3B0aW9ucyh7XG4gICAgICBtb2RpZmllcnM6IHtcbiAgICAgICAgZmxpcDoge1xuICAgICAgICAgIGVuYWJsZWQ6IHRoaXMuX2NvbmZpZy5hZGFwdGl2ZVBvc2l0aW9uXG4gICAgICAgIH0sXG4gICAgICAgIHByZXZlbnRPdmVyZmxvdzoge1xuICAgICAgICAgIGVuYWJsZWQ6IHRoaXMuX2NvbmZpZy5hZGFwdGl2ZVBvc2l0aW9uXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBhbGxvd2VkUG9zaXRpb25zOiB0aGlzLl9jb25maWcuYWxsb3dlZFBvc2l0aW9uc1xuICAgIH0pO1xuXG4gICAgdGhpcy5fcG9zaXRpb25TZXJ2aWNlLmV2ZW50JD8ucGlwZSh0YWtlKDEpKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX3Bvc2l0aW9uU2VydmljZS5kaXNhYmxlKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5pc0FuaW1hdGVkKSB7XG4gICAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IHRoaXMuaXNUb3BQb3NpdGlvbiA/ICdhbmltYXRlZC11cCcgOiAnYW5pbWF0ZWQtZG93bic7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gJ3VuYW5pbWF0ZWQnO1xuICAgICAgfSk7XG4gICAgdGhpcy5jb250YWluZXJDbGFzcyA9IHRoaXMuX2NvbmZpZy5jb250YWluZXJDbGFzcztcbiAgICB0aGlzLmlzT3RoZXJNb250aHNBY3RpdmUgPSB0aGlzLl9jb25maWcuc2VsZWN0RnJvbU90aGVyTW9udGg7XG4gICAgdGhpcy53aXRoVGltZXBpY2tlciA9IHRoaXMuX2NvbmZpZy53aXRoVGltZXBpY2tlcjtcbiAgICB0aGlzLl9lZmZlY3RzPy5pbml0KHRoaXMuX3N0b3JlKVxuICAgICAgLy8gaW50aWFsIHN0YXRlIG9wdGlvbnNcbiAgICAgIC8vIHRvZG86IGZpeCB0aGlzLCBzcGxpdCBjb25maWdzXG4gICAgICAuc2V0T3B0aW9ucyh0aGlzLl9jb25maWcpXG4gICAgICAvLyBkYXRhIGJpbmRpbmcgdmlldyAtLT4gbW9kZWxcbiAgICAgIC5zZXRCaW5kaW5ncyh0aGlzKVxuICAgICAgLy8gc2V0IGV2ZW50IGhhbmRsZXJzXG4gICAgICAuc2V0RXZlbnRIYW5kbGVycyh0aGlzKVxuICAgICAgLnJlZ2lzdGVyRGF0ZXBpY2tlclNpZGVFZmZlY3RzKCk7XG4gICAgbGV0IGN1cnJlbnREYXRlOiBEYXRlW10gfCB1bmRlZmluZWQ7XG4gICAgLy8gdG9kbzogbW92ZSBpdCBzb21ld2hlcmUgZWxzZVxuICAgIC8vIG9uIHNlbGVjdGVkIGRhdGUgY2hhbmdlXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxuICAgICAgdGhpcy5fc3RvcmVcbiAgICAgICAgLnNlbGVjdChzdGF0ZSA9PiBzdGF0ZS5zZWxlY3RlZFJhbmdlKVxuICAgICAgICAuc3Vic2NyaWJlKGRhdGVSYW5nZSA9PiB7XG4gICAgICAgICAgY3VycmVudERhdGUgPSBkYXRlUmFuZ2U7XG4gICAgICAgICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KGRhdGVSYW5nZSk7XG4gICAgICAgICAgdGhpcy5jaG9zZW5SYW5nZSA9IGRhdGVSYW5nZSB8fCBbXTtcbiAgICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxuICAgICAgdGhpcy5fc3RvcmVcbiAgICAgICAgLnNlbGVjdChzdGF0ZSA9PiBzdGF0ZS5zZWxlY3RlZFRpbWUpXG4gICAgICAgIC5zdWJzY3JpYmUoKHRpbWU6YW55KSA9PiB7XG4gICAgICAgICAgaWYgKCghdGltZVswXSB8fCAhdGltZVsxXSkgfHxcbiAgICAgICAgICAgICAoISh0aW1lWzBdIGluc3RhbmNlb2YgRGF0ZSkgfHwgISh0aW1lWzFdIGluc3RhbmNlb2YgRGF0ZSkpIHx8XG4gICAgICAgICAgICAgKGN1cnJlbnREYXRlICYmICh0aW1lWzBdID09PSBjdXJyZW50RGF0ZVswXSAmJiB0aW1lWzFdID09PSBjdXJyZW50RGF0ZVsxXSkpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHRpbWUpO1xuICAgICAgICAgIHRoaXMuY2hvc2VuUmFuZ2UgPSB0aW1lIHx8IFtdO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZFRpbWVTdWIuYWRkKHRoaXMuc2VsZWN0ZWRUaW1lPy5zdWJzY3JpYmUoKHZhbCkgPT4ge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsKSAmJiB2YWwubGVuZ3RoID49IDIpIHtcbiAgICAgICAgdGhpcy5zdGFydFRpbWVwaWNrZXI/LndyaXRlVmFsdWUodmFsWzBdKTtcbiAgICAgICAgdGhpcy5lbmRUaW1lcGlja2VyPy53cml0ZVZhbHVlKHZhbFsxXSk7XG4gICAgICB9XG4gICAgfSkpO1xuICAgIHRoaXMuc3RhcnRUaW1lcGlja2VyPy5yZWdpc3Rlck9uQ2hhbmdlKCh2YWwpID0+IHtcbiAgICAgIHRoaXMudGltZVNlbGVjdEhhbmRsZXIodmFsLCAwKTtcbiAgICB9KTtcbiAgICB0aGlzLmVuZFRpbWVwaWNrZXI/LnJlZ2lzdGVyT25DaGFuZ2UoKHZhbCkgPT4ge1xuICAgICAgdGhpcy50aW1lU2VsZWN0SGFuZGxlcih2YWwsIDEpO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0IGlzVG9wUG9zaXRpb24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ3RvcCcpO1xuICB9XG5cbiAgcG9zaXRpb25TZXJ2aWNlRW5hYmxlKCk6IHZvaWQge1xuICAgIHRoaXMuX3Bvc2l0aW9uU2VydmljZS5lbmFibGUoKTtcbiAgfVxuXG4gIG92ZXJyaWRlIHRpbWVTZWxlY3RIYW5kbGVyKGRhdGU6IERhdGUsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLl9zdG9yZS5kaXNwYXRjaCh0aGlzLl9hY3Rpb25zLnNlbGVjdFRpbWUoZGF0ZSwgaW5kZXgpKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGRheVNlbGVjdEhhbmRsZXIoZGF5OiBEYXlWaWV3TW9kZWwpOiB2b2lkIHtcbiAgICBpZiAoIWRheSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpc0Rpc2FibGVkID0gdGhpcy5pc090aGVyTW9udGhzQWN0aXZlID8gZGF5LmlzRGlzYWJsZWQgOiAoZGF5LmlzT3RoZXJNb250aCB8fCBkYXkuaXNEaXNhYmxlZCk7XG5cbiAgICBpZiAoaXNEaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnJhbmdlc1Byb2Nlc3NpbmcoZGF5KTtcbiAgfVxuXG4gIG92ZXJyaWRlIG1vbnRoU2VsZWN0SGFuZGxlcihkYXk6IENhbGVuZGFyQ2VsbFZpZXdNb2RlbCk6IHZvaWQge1xuICAgIGlmICghZGF5IHx8IGRheS5pc0Rpc2FibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZGF5LmlzU2VsZWN0ZWQgPSB0cnVlO1xuXG4gICAgaWYgKHRoaXMuX2NvbmZpZy5taW5Nb2RlICE9PSAnbW9udGgnKSB7XG4gICAgICBpZiAoZGF5LmlzRGlzYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5fc3RvcmUuZGlzcGF0Y2goXG4gICAgICAgIHRoaXMuX2FjdGlvbnMubmF2aWdhdGVUbyh7XG4gICAgICAgICAgdW5pdDoge1xuICAgICAgICAgICAgbW9udGg6IGdldE1vbnRoKGRheS5kYXRlKSxcbiAgICAgICAgICAgIHllYXI6IGdldEZ1bGxZZWFyKGRheS5kYXRlKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgdmlld01vZGU6ICdkYXknXG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMucmFuZ2VzUHJvY2Vzc2luZyhkYXkpO1xuICB9XG5cbiAgb3ZlcnJpZGUgeWVhclNlbGVjdEhhbmRsZXIoZGF5OiBDYWxlbmRhckNlbGxWaWV3TW9kZWwpOiB2b2lkIHtcbiAgICBpZiAoIWRheSB8fCBkYXkuaXNEaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGRheS5pc1NlbGVjdGVkID0gdHJ1ZTtcblxuICAgIGlmICh0aGlzLl9jb25maWcubWluTW9kZSAhPT0gJ3llYXInKSB7XG4gICAgICBpZiAoZGF5LmlzRGlzYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5fc3RvcmUuZGlzcGF0Y2goXG4gICAgICAgIHRoaXMuX2FjdGlvbnMubmF2aWdhdGVUbyh7XG4gICAgICAgICAgdW5pdDoge1xuICAgICAgICAgICAgeWVhcjogZ2V0RnVsbFllYXIoZGF5LmRhdGUpXG4gICAgICAgICAgfSxcbiAgICAgICAgICB2aWV3TW9kZTogJ21vbnRoJ1xuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnJhbmdlc1Byb2Nlc3NpbmcoZGF5KTtcbiAgfVxuXG4gIHJhbmdlc1Byb2Nlc3NpbmcoZGF5OiBDYWxlbmRhckNlbGxWaWV3TW9kZWwpOiB2b2lkIHtcbiAgICAvLyBpZiBvbmx5IG9uZSBkYXRlIGlzIGFscmVhZHkgc2VsZWN0ZWRcbiAgICAvLyBhbmQgdXNlciBjbGlja3Mgb24gcHJldmlvdXMgZGF0ZVxuICAgIC8vIHN0YXJ0IHNlbGVjdGlvbiBmcm9tIG5ldyBkYXRlXG4gICAgLy8gYnV0IGlmIG5ldyBkYXRlIGlzIGFmdGVyIGluaXRpYWwgb25lXG4gICAgLy8gdGhhbiBmaW5pc2ggc2VsZWN0aW9uXG5cbiAgICBpZiAodGhpcy5fcmFuZ2VTdGFjay5sZW5ndGggPT09IDEpIHtcbiAgICAgIHRoaXMuX3JhbmdlU3RhY2sgPVxuICAgICAgICBkYXkuZGF0ZSA+PSB0aGlzLl9yYW5nZVN0YWNrWzBdXG4gICAgICAgICAgPyBbdGhpcy5fcmFuZ2VTdGFja1swXSwgZGF5LmRhdGVdXG4gICAgICAgICAgOiAgW2RheS5kYXRlXTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fY29uZmlnLm1heERhdGVSYW5nZSkge1xuICAgICAgdGhpcy5zZXRNYXhEYXRlUmFuZ2VPbkNhbGVuZGFyKGRheS5kYXRlKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fcmFuZ2VTdGFjay5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMuX3JhbmdlU3RhY2sgPSBbZGF5LmRhdGVdO1xuXG4gICAgICBpZiAodGhpcy5fY29uZmlnLm1heERhdGVSYW5nZSkge1xuICAgICAgICB0aGlzLnNldE1heERhdGVSYW5nZU9uQ2FsZW5kYXIoZGF5LmRhdGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX3N0b3JlLmRpc3BhdGNoKHRoaXMuX2FjdGlvbnMuc2VsZWN0UmFuZ2UodGhpcy5fcmFuZ2VTdGFjaykpO1xuXG4gICAgaWYgKHRoaXMuX3JhbmdlU3RhY2subGVuZ3RoID09PSAyKSB7XG4gICAgICB0aGlzLl9yYW5nZVN0YWNrID0gW107XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBzdWIgb2YgdGhpcy5fc3Vicykge1xuICAgICAgc3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIHRoaXMuc2VsZWN0ZWRUaW1lU3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fZWZmZWN0cz8uZGVzdHJveSgpO1xuICB9XG5cbiAgb3ZlcnJpZGUgc2V0UmFuZ2VPbkNhbGVuZGFyKGRhdGVzOiBCc0N1c3RvbURhdGVzKTogdm9pZCB7XG4gICAgaWYgKGRhdGVzKSB7XG4gICAgICB0aGlzLl9yYW5nZVN0YWNrID0gZGF0ZXMudmFsdWUgaW5zdGFuY2VvZiBEYXRlID8gW2RhdGVzLnZhbHVlXSA6IGRhdGVzLnZhbHVlO1xuICAgIH1cbiAgICB0aGlzLl9zdG9yZS5kaXNwYXRjaCh0aGlzLl9hY3Rpb25zLnNlbGVjdFJhbmdlKHRoaXMuX3JhbmdlU3RhY2spKTtcbiAgfVxuXG4gIHNldE1heERhdGVSYW5nZU9uQ2FsZW5kYXIoY3VycmVudFNlbGVjdGlvbjogRGF0ZSk6IHZvaWQge1xuICAgIGxldCBtYXhEYXRlUmFuZ2UgPSBuZXcgRGF0ZShjdXJyZW50U2VsZWN0aW9uKTtcblxuICAgIGlmICh0aGlzLl9jb25maWcubWF4RGF0ZSkge1xuICAgICAgY29uc3QgbWF4RGF0ZVZhbHVlSW5NaWxsaXNlY29uZHMgPSB0aGlzLl9jb25maWcubWF4RGF0ZS5nZXRUaW1lKCk7XG4gICAgICBjb25zdCBtYXhEYXRlUmFuZ2VJbk1pbGxpc2Vjb25kcyA9IGN1cnJlbnRTZWxlY3Rpb24uZ2V0VGltZSgpICsgKCh0aGlzLl9jb25maWcubWF4RGF0ZVJhbmdlIHx8IDApICogZGF5SW5NaWxsaXNlY29uZHMgKTtcbiAgICAgIG1heERhdGVSYW5nZSA9IG1heERhdGVSYW5nZUluTWlsbGlzZWNvbmRzID4gbWF4RGF0ZVZhbHVlSW5NaWxsaXNlY29uZHMgP1xuICAgICAgICBuZXcgRGF0ZSh0aGlzLl9jb25maWcubWF4RGF0ZSkgOlxuICAgICAgICBuZXcgRGF0ZShtYXhEYXRlUmFuZ2VJbk1pbGxpc2Vjb25kcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1heERhdGVSYW5nZS5zZXREYXRlKGN1cnJlbnRTZWxlY3Rpb24uZ2V0RGF0ZSgpICsgKHRoaXMuX2NvbmZpZy5tYXhEYXRlUmFuZ2UgfHwgMCkpO1xuICAgIH1cblxuICAgIHRoaXMuX2VmZmVjdHM/LnNldE1heERhdGUobWF4RGF0ZVJhbmdlKTtcbiAgfVxufVxuIiwiPCEtLSBkYXlzIGNhbGVuZGFyIHZpZXcgbW9kZSAtLT5cbjxkaXYgY2xhc3M9XCJicy1kYXRlcGlja2VyXCIgW25nQ2xhc3NdPVwiY29udGFpbmVyQ2xhc3NcIiAqbmdJZj1cInZpZXdNb2RlIHwgYXN5bmNcIj5cbiAgPGRpdiBjbGFzcz1cImJzLWRhdGVwaWNrZXItY29udGFpbmVyXCJcbiAgICBbQGRhdGVwaWNrZXJBbmltYXRpb25dPVwiYW5pbWF0aW9uU3RhdGVcIlxuICAgIChAZGF0ZXBpY2tlckFuaW1hdGlvbi5kb25lKT1cInBvc2l0aW9uU2VydmljZUVuYWJsZSgpXCI+XG4gICAgPCEtLWNhbGVuZGFycy0tPlxuICAgIDxkaXYgY2xhc3M9XCJicy1jYWxlbmRhci1jb250YWluZXJcIiBbbmdTd2l0Y2hdPVwidmlld01vZGUgfCBhc3luY1wiIHJvbGU9XCJhcHBsaWNhdGlvblwiPlxuICAgICAgPCEtLWRheXMgY2FsZW5kYXItLT5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidkYXknXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJicy1tZWRpYS1jb250YWluZXJcIj5cbiAgICAgICAgICA8YnMtZGF5cy1jYWxlbmRhci12aWV3XG4gICAgICAgICAgICAqbmdGb3I9XCJsZXQgY2FsZW5kYXIgb2YgZGF5c0NhbGVuZGFyJCB8IGFzeW5jXCJcbiAgICAgICAgICAgIFtjbGFzcy5icy1kYXRlcGlja2VyLW11bHRpcGxlXT1cIm11bHRpcGxlQ2FsZW5kYXJzXCJcbiAgICAgICAgICAgIFtjYWxlbmRhcl09XCJjYWxlbmRhclwiXG4gICAgICAgICAgICBbaXNEaXNhYmxlZF09XCJpc0RhdGVQaWNrZXJEaXNhYmxlZFwiXG4gICAgICAgICAgICBbb3B0aW9uc109XCJvcHRpb25zJCB8IGFzeW5jXCJcbiAgICAgICAgICAgIChvbk5hdmlnYXRlKT1cIm5hdmlnYXRlVG8oJGV2ZW50KVwiXG4gICAgICAgICAgICAob25WaWV3TW9kZSk9XCJzZXRWaWV3TW9kZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIChvbkhvdmVyKT1cImRheUhvdmVySGFuZGxlcigkZXZlbnQpXCJcbiAgICAgICAgICAgIChvbkhvdmVyV2Vlayk9XCJ3ZWVrSG92ZXJIYW5kbGVyKCRldmVudClcIlxuICAgICAgICAgICAgKG9uU2VsZWN0KT1cImRheVNlbGVjdEhhbmRsZXIoJGV2ZW50KVwiPlxuICAgICAgICAgIDwvYnMtZGF5cy1jYWxlbmRhci12aWV3PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiAqbmdJZj1cIndpdGhUaW1lcGlja2VyXCIgY2xhc3M9XCJicy10aW1lcGlja2VyLWluLWRhdGVwaWNrZXItY29udGFpbmVyXCI+XG4gICAgICAgICAgPHRpbWVwaWNrZXIgI3N0YXJ0VFAgW2Rpc2FibGVkXT1cImlzRGF0ZVBpY2tlckRpc2FibGVkXCI+PC90aW1lcGlja2VyPlxuICAgICAgICAgIDx0aW1lcGlja2VyICNlbmRUUCAqbmdJZj1cImlzUmFuZ2VQaWNrZXJcIiBbZGlzYWJsZWRdPVwiaXNEYXRlUGlja2VyRGlzYWJsZWRcIj48L3RpbWVwaWNrZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS1tb250aHMgY2FsZW5kYXItLT5cbiAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidtb250aCdcIiBjbGFzcz1cImJzLW1lZGlhLWNvbnRhaW5lclwiPlxuICAgICAgICA8YnMtbW9udGgtY2FsZW5kYXItdmlld1xuICAgICAgICAgICpuZ0Zvcj1cImxldCBjYWxlbmRhciBvZiBtb250aHNDYWxlbmRhciB8IGFzeW5jXCJcbiAgICAgICAgICBbY2xhc3MuYnMtZGF0ZXBpY2tlci1tdWx0aXBsZV09XCJtdWx0aXBsZUNhbGVuZGFyc1wiXG4gICAgICAgICAgW2NhbGVuZGFyXT1cImNhbGVuZGFyXCJcbiAgICAgICAgICAob25OYXZpZ2F0ZSk9XCJuYXZpZ2F0ZVRvKCRldmVudClcIlxuICAgICAgICAgIChvblZpZXdNb2RlKT1cInNldFZpZXdNb2RlKCRldmVudClcIlxuICAgICAgICAgIChvbkhvdmVyKT1cIm1vbnRoSG92ZXJIYW5kbGVyKCRldmVudClcIlxuICAgICAgICAgIChvblNlbGVjdCk9XCJtb250aFNlbGVjdEhhbmRsZXIoJGV2ZW50KVwiPlxuICAgICAgICA8L2JzLW1vbnRoLWNhbGVuZGFyLXZpZXc+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLXllYXJzIGNhbGVuZGFyLS0+XG4gICAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCIneWVhcidcIiBjbGFzcz1cImJzLW1lZGlhLWNvbnRhaW5lclwiPlxuICAgICAgICA8YnMteWVhcnMtY2FsZW5kYXItdmlld1xuICAgICAgICAgICpuZ0Zvcj1cImxldCBjYWxlbmRhciBvZiB5ZWFyc0NhbGVuZGFyIHwgYXN5bmNcIlxuICAgICAgICAgIFtjbGFzcy5icy1kYXRlcGlja2VyLW11bHRpcGxlXT1cIm11bHRpcGxlQ2FsZW5kYXJzXCJcbiAgICAgICAgICBbY2FsZW5kYXJdPVwiY2FsZW5kYXJcIlxuICAgICAgICAgIChvbk5hdmlnYXRlKT1cIm5hdmlnYXRlVG8oJGV2ZW50KVwiXG4gICAgICAgICAgKG9uVmlld01vZGUpPVwic2V0Vmlld01vZGUoJGV2ZW50KVwiXG4gICAgICAgICAgKG9uSG92ZXIpPVwieWVhckhvdmVySGFuZGxlcigkZXZlbnQpXCJcbiAgICAgICAgICAob25TZWxlY3QpPVwieWVhclNlbGVjdEhhbmRsZXIoJGV2ZW50KVwiPlxuICAgICAgICA8L2JzLXllYXJzLWNhbGVuZGFyLXZpZXc+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS1hcHBseWNhbmNlbCBidXR0b25zLS0+XG4gICAgPGRpdiBjbGFzcz1cImJzLWRhdGVwaWNrZXItYnV0dG9uc1wiICpuZ0lmPVwiZmFsc2VcIj5cbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXN1Y2Nlc3NcIiB0eXBlPVwiYnV0dG9uXCI+QXBwbHk8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLWRlZmF1bHRcIiB0eXBlPVwiYnV0dG9uXCI+Q2FuY2VsPC9idXR0b24+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiYnMtZGF0ZXBpY2tlci1idXR0b25zXCIgKm5nSWY9XCJzaG93VG9kYXlCdG4gfHwgc2hvd0NsZWFyQnRuXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiYnRuLXRvZGF5LXdyYXBwZXJcIlxuICAgICAgICAgICBbY2xhc3MudG9kYXktbGVmdF09XCJ0b2RheVBvcyA9PT0gJ2xlZnQnXCJcbiAgICAgICAgICAgW2NsYXNzLnRvZGF5LXJpZ2h0XT1cInRvZGF5UG9zID09PSAncmlnaHQnXCJcbiAgICAgICAgICAgW2NsYXNzLnRvZGF5LWNlbnRlcl09XCJ0b2RheVBvcyA9PT0gJ2NlbnRlcidcIlxuICAgICAgICAgICAqbmdJZj1cInNob3dUb2RheUJ0blwiPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzXCIgKGNsaWNrKT1cInNldFRvZGF5KClcIj57e3RvZGF5QnRuTGJsfX08L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJidG4tY2xlYXItd3JhcHBlclwiXG4gICAgICAgIFtjbGFzcy5jbGVhci1sZWZ0XT1cImNsZWFyUG9zID09PSAnbGVmdCdcIlxuICAgICAgICBbY2xhc3MuY2xlYXItcmlnaHRdPVwiY2xlYXJQb3MgPT09ICdyaWdodCdcIlxuICAgICAgICBbY2xhc3MuY2xlYXItY2VudGVyXT1cImNsZWFyUG9zID09PSAnY2VudGVyJ1wiXG4gICAgICAgICpuZ0lmPVwic2hvd0NsZWFyQnRuXCI+XG4gICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tc3VjY2Vzc1wiIChjbGljayk9XCJjbGVhckRhdGUoKVwiPnt7Y2xlYXJCdG5MYmx9fTwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICA8L2Rpdj5cblxuICA8IS0tY3VzdG9tIGRhdGVzIG9yIGRhdGUgcmFuZ2VzIHBpY2tlci0tPlxuICA8ZGl2IGNsYXNzPVwiYnMtZGF0ZXBpY2tlci1jdXN0b20tcmFuZ2VcIiAqbmdJZj1cImN1c3RvbVJhbmdlcyAmJiBjdXN0b21SYW5nZXMubGVuZ3RoID4gMFwiPlxuICAgIDxicy1jdXN0b20tZGF0ZS12aWV3XG4gICAgICBbc2VsZWN0ZWRSYW5nZV09XCJjaG9zZW5SYW5nZVwiXG4gICAgICBbcmFuZ2VzXT1cImN1c3RvbVJhbmdlc1wiXG4gICAgICBbY3VzdG9tUmFuZ2VMYWJlbF09XCJjdXN0b