UNPKG

@ng-bootstrap/ng-bootstrap

Version:
444 lines 61.1 kB
import { ChangeDetectorRef, Directive, ElementRef, EventEmitter, forwardRef, inject, Input, NgZone, Output, ViewContainerRef, } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR, } from '@angular/forms'; import { ngbAutoClose } from '../util/autoclose'; import { ngbFocusTrap } from '../util/focus-trap'; import { ngbPositioning } from '../util/positioning'; import { NgbDateAdapter } from './adapters/ngb-date-adapter'; import { NgbDatepicker } from './datepicker'; import { NgbCalendar } from './ngb-calendar'; import { NgbDate } from './ngb-date'; import { NgbDateParserFormatter } from './ngb-date-parser-formatter'; import { NgbInputDatepickerConfig } from './datepicker-input-config'; import { NgbDatepickerConfig } from './datepicker-config'; import { isString } from '../util/util'; import { Subject } from 'rxjs'; import { addPopperOffset } from '../util/positioning-util'; import * as i0 from "@angular/core"; /** * A directive that allows to stick a datepicker popup to an input field. * * Manages interaction with the input field itself, does value formatting and provides forms integration. */ export class NgbInputDatepicker { constructor() { this._parserFormatter = inject(NgbDateParserFormatter); this._elRef = inject((ElementRef)); this._vcRef = inject(ViewContainerRef); this._ngZone = inject(NgZone); this._calendar = inject(NgbCalendar); this._dateAdapter = inject((NgbDateAdapter)); this._document = inject(DOCUMENT); this._changeDetector = inject(ChangeDetectorRef); this._config = inject(NgbInputDatepickerConfig); this._cRef = null; this._disabled = false; this._elWithFocus = null; this._model = null; this._positioning = ngbPositioning(); this._destroyCloseHandlers$ = new Subject(); /** * Indicates whether the datepicker popup should be closed automatically after date selection / outside click or not. * * * `true` - the popup will close on both date selection and outside click. * * `false` - the popup can only be closed manually via `close()` or `toggle()` methods. * * `"inside"` - the popup will close on date selection, but not outside clicks. * * `"outside"` - the popup will close only on the outside click and not on date selection/inside clicks. * * @since 3.0.0 */ this.autoClose = this._config.autoClose; /** * The preferred placement of the datepicker popup, among the [possible values](#/guides/positioning#api). * * The default order of preference is `"bottom-start bottom-end top-start top-end"` * * Please see the [positioning overview](#/positioning) for more details. */ this.placement = this._config.placement; /** * Allows to change default Popper options when positioning the popup. * Receives current popper options and returns modified ones. * * @since 13.1.0 */ this.popperOptions = this._config.popperOptions; /** * A selector specifying the element the datepicker popup should be appended to. * * Currently only supports `"body"`. */ this.container = this._config.container; /** * A css selector or html element specifying the element the datepicker popup should be positioned against. * * By default the input is used as a target. * * @since 4.2.0 */ this.positionTarget = this._config.positionTarget; /** * An event emitted when user selects a date using keyboard or mouse. * * The payload of the event is currently selected `NgbDate`. * * @since 1.1.1 */ this.dateSelect = new EventEmitter(); /** * Event emitted right after the navigation happens and displayed month changes. * * See [`NgbDatepickerNavigateEvent`](#/components/datepicker/api#NgbDatepickerNavigateEvent) for the payload info. */ this.navigate = new EventEmitter(); /** * An event fired after closing datepicker window. * * @since 4.2.0 */ this.closed = new EventEmitter(); this._onChange = (_) => { }; this._onTouched = () => { }; this._validatorChange = () => { }; } get disabled() { return this._disabled; } set disabled(value) { this._disabled = value === '' || (value && value !== 'false'); if (this.isOpen()) { this._cRef.instance.setDisabledState(this._disabled); } } registerOnChange(fn) { this._onChange = fn; } registerOnTouched(fn) { this._onTouched = fn; } registerOnValidatorChange(fn) { this._validatorChange = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; } validate(c) { const { value } = c; if (value != null) { const ngbDate = this._fromDateStruct(this._dateAdapter.fromModel(value)); if (!ngbDate) { return { ngbDate: { invalid: value } }; } if (this.minDate && ngbDate.before(NgbDate.from(this.minDate))) { return { ngbDate: { minDate: { minDate: this.minDate, actual: value } } }; } if (this.maxDate && ngbDate.after(NgbDate.from(this.maxDate))) { return { ngbDate: { maxDate: { maxDate: this.maxDate, actual: value } } }; } } return null; } writeValue(value) { this._model = this._fromDateStruct(this._dateAdapter.fromModel(value)); this._writeModelValue(this._model); } manualDateChange(value, updateView = false) { const inputValueChanged = value !== this._inputValue; if (inputValueChanged) { this._inputValue = value; this._model = this._fromDateStruct(this._parserFormatter.parse(value)); } if (inputValueChanged || !updateView) { this._onChange(this._model ? this._dateAdapter.toModel(this._model) : value === '' ? null : value); } if (updateView && this._model) { this._writeModelValue(this._model); } } isOpen() { return !!this._cRef; } /** * Opens the datepicker popup. * * If the related form control contains a valid date, the corresponding month will be opened. */ open() { if (!this.isOpen()) { this._cRef = this._vcRef.createComponent(NgbDatepicker); this._applyPopupStyling(this._cRef.location.nativeElement); this._applyDatepickerInputs(this._cRef); this._subscribeForDatepickerOutputs(this._cRef.instance); this._cRef.instance.ngOnInit(); this._cRef.instance.writeValue(this._dateAdapter.toModel(this._model)); // date selection event handling this._cRef.instance.registerOnChange((selectedDate) => { this.writeValue(selectedDate); this._onChange(selectedDate); this._onTouched(); }); this._cRef.changeDetectorRef.detectChanges(); this._cRef.instance.setDisabledState(this.disabled); if (this.container === 'body') { this._document.querySelector(this.container)?.appendChild(this._cRef.location.nativeElement); } // focus handling this._elWithFocus = this._document.activeElement; ngbFocusTrap(this._ngZone, this._cRef.location.nativeElement, this.closed, true); setTimeout(() => this._cRef?.instance.focus()); let hostElement; if (isString(this.positionTarget)) { hostElement = this._document.querySelector(this.positionTarget); } else if (this.positionTarget instanceof HTMLElement) { hostElement = this.positionTarget; } else { hostElement = this._elRef.nativeElement; } if (this.positionTarget && !hostElement) { throw new Error('ngbDatepicker could not find element declared in [positionTarget] to position against.'); } // Setting up popper and scheduling updates when zone is stable this._ngZone.runOutsideAngular(() => { if (this._cRef && hostElement) { this._positioning.createPopper({ hostElement, targetElement: this._cRef.location.nativeElement, placement: this.placement, appendToBody: this.container === 'body', updatePopperOptions: (options) => this.popperOptions(addPopperOffset([0, 2])(options)), }); this._zoneSubscription = this._ngZone.onStable.subscribe(() => this._positioning.update()); } }); this._setCloseHandlers(); } } /** * Closes the datepicker popup. */ close() { if (this.isOpen()) { this._vcRef.remove(this._vcRef.indexOf(this._cRef.hostView)); this._cRef = null; this._positioning.destroy(); this._zoneSubscription?.unsubscribe(); this._destroyCloseHandlers$.next(); this.closed.emit(); this._changeDetector.markForCheck(); // restore focus let elementToFocus = this._elWithFocus; if (isString(this.restoreFocus)) { elementToFocus = this._document.querySelector(this.restoreFocus); } else if (this.restoreFocus !== undefined) { elementToFocus = this.restoreFocus; } // in IE document.activeElement can contain an object without 'focus()' sometimes if (elementToFocus && elementToFocus['focus']) { elementToFocus.focus(); } else { this._document.body.focus(); } } } /** * Toggles the datepicker popup. */ toggle() { if (this.isOpen()) { this.close(); } else { this.open(); } } /** * Navigates to the provided date. * * With the default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec. * If nothing or invalid date provided calendar will open current month. * * Use the `[startDate]` input as an alternative. */ navigateTo(date) { if (this.isOpen()) { this._cRef.instance.navigateTo(date); } } onBlur() { this._onTouched(); } onFocus() { this._elWithFocus = this._elRef.nativeElement; } ngOnChanges(changes) { if (changes['minDate'] || changes['maxDate']) { this._validatorChange(); if (this.isOpen()) { if (changes['minDate']) { this._cRef.setInput('minDate', this.minDate); } if (changes['maxDate']) { this._cRef.setInput('maxDate', this.maxDate); } } } if (changes['datepickerClass']) { const { currentValue, previousValue } = changes['datepickerClass']; this._applyPopupClass(currentValue, previousValue); } if (changes['autoClose'] && this.isOpen()) { this._setCloseHandlers(); } } ngOnDestroy() { this.close(); } _applyDatepickerInputs(datepickerComponentRef) { [ 'contentTemplate', 'dayTemplate', 'dayTemplateData', 'displayMonths', 'firstDayOfWeek', 'footerTemplate', 'markDisabled', 'minDate', 'maxDate', 'navigation', 'outsideDays', 'showNavigation', 'showWeekNumbers', 'weekdays', ].forEach((inputName) => { if (this[inputName] !== undefined) { datepickerComponentRef.setInput(inputName, this[inputName]); } }); datepickerComponentRef.setInput('startDate', this.startDate || this._model); } _applyPopupClass(newClass, oldClass) { const popupEl = this._cRef?.location.nativeElement; if (popupEl) { if (newClass) { popupEl.classList.add(newClass); } if (oldClass) { popupEl.classList.remove(oldClass); } } } _applyPopupStyling(nativeElement) { nativeElement.classList.add('dropdown-menu', 'show'); if (this.container === 'body') { nativeElement.classList.add('ngb-dp-body'); } this._applyPopupClass(this.datepickerClass); } _subscribeForDatepickerOutputs(datepickerInstance) { datepickerInstance.navigate.subscribe((navigateEvent) => this.navigate.emit(navigateEvent)); datepickerInstance.dateSelect.subscribe((date) => { this.dateSelect.emit(date); if (this.autoClose === true || this.autoClose === 'inside') { this.close(); } }); } _writeModelValue(model) { const value = this._parserFormatter.format(model); this._inputValue = value; this._elRef.nativeElement.value = value; if (this.isOpen()) { this._cRef.instance.writeValue(this._dateAdapter.toModel(model)); this._onTouched(); } } _fromDateStruct(date) { const ngbDate = date ? new NgbDate(date.year, date.month, date.day) : null; return this._calendar.isValid(ngbDate) ? ngbDate : null; } _setCloseHandlers() { this._destroyCloseHandlers$.next(); ngbAutoClose(this._ngZone, this._document, this.autoClose, () => this.close(), this._destroyCloseHandlers$, [], [this._elRef.nativeElement, this._cRef.location.nativeElement]); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbInputDatepicker, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbInputDatepicker, isStandalone: true, selector: "input[ngbDatepicker]", inputs: { autoClose: "autoClose", contentTemplate: "contentTemplate", datepickerClass: "datepickerClass", dayTemplate: "dayTemplate", dayTemplateData: "dayTemplateData", displayMonths: "displayMonths", firstDayOfWeek: "firstDayOfWeek", footerTemplate: "footerTemplate", markDisabled: "markDisabled", minDate: "minDate", maxDate: "maxDate", navigation: "navigation", outsideDays: "outsideDays", placement: "placement", popperOptions: "popperOptions", restoreFocus: "restoreFocus", showWeekNumbers: "showWeekNumbers", startDate: "startDate", container: "container", positionTarget: "positionTarget", weekdays: "weekdays", disabled: "disabled" }, outputs: { dateSelect: "dateSelect", navigate: "navigate", closed: "closed" }, host: { listeners: { "input": "manualDateChange($event.target.value)", "change": "manualDateChange($event.target.value, true)", "focus": "onFocus()", "blur": "onBlur()" }, properties: { "disabled": "disabled" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbInputDatepicker), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => NgbInputDatepicker), multi: true }, { provide: NgbDatepickerConfig, useExisting: NgbInputDatepickerConfig }, ], exportAs: ["ngbDatepicker"], usesOnChanges: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbInputDatepicker, decorators: [{ type: Directive, args: [{ selector: 'input[ngbDatepicker]', exportAs: 'ngbDatepicker', standalone: true, host: { '(input)': 'manualDateChange($event.target.value)', '(change)': 'manualDateChange($event.target.value, true)', '(focus)': 'onFocus()', '(blur)': 'onBlur()', '[disabled]': 'disabled', }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbInputDatepicker), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => NgbInputDatepicker), multi: true }, { provide: NgbDatepickerConfig, useExisting: NgbInputDatepickerConfig }, ], }] }], propDecorators: { autoClose: [{ type: Input }], contentTemplate: [{ type: Input }], datepickerClass: [{ type: Input }], dayTemplate: [{ type: Input }], dayTemplateData: [{ type: Input }], displayMonths: [{ type: Input }], firstDayOfWeek: [{ type: Input }], footerTemplate: [{ type: Input }], markDisabled: [{ type: Input }], minDate: [{ type: Input }], maxDate: [{ type: Input }], navigation: [{ type: Input }], outsideDays: [{ type: Input }], placement: [{ type: Input }], popperOptions: [{ type: Input }], restoreFocus: [{ type: Input }], showWeekNumbers: [{ type: Input }], startDate: [{ type: Input }], container: [{ type: Input }], positionTarget: [{ type: Input }], weekdays: [{ type: Input }], dateSelect: [{ type: Output }], navigate: [{ type: Output }], closed: [{ type: Output }], disabled: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci1pbnB1dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kYXRlcGlja2VyL2RhdGVwaWNrZXItaW5wdXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNOLGlCQUFpQixFQUVqQixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBR04sTUFBTSxFQUdOLGdCQUFnQixHQUNoQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFvQixNQUFNLGlCQUFpQixDQUFDO0FBQzdELE9BQU8sRUFHTixhQUFhLEVBQ2IsaUJBQWlCLEdBR2pCLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFckQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sRUFBRSxhQUFhLEVBQThCLE1BQU0sY0FBYyxDQUFDO0FBRXpFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRXJFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzFELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7O0FBRzNEOzs7O0dBSUc7QUFrQkgsTUFBTSxPQUFPLGtCQUFrQjtJQWpCL0I7UUF3QlMscUJBQWdCLEdBQUcsTUFBTSxDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFDbEQsV0FBTSxHQUFHLE1BQU0sQ0FBQyxDQUFBLFVBQTRCLENBQUEsQ0FBQyxDQUFDO1FBQzlDLFdBQU0sR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNsQyxZQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3pCLGNBQVMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDaEMsaUJBQVksR0FBRyxNQUFNLENBQUMsQ0FBQSxjQUFtQixDQUFBLENBQUMsQ0FBQztRQUMzQyxjQUFTLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzdCLG9CQUFlLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDNUMsWUFBTyxHQUFHLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBRTNDLFVBQUssR0FBdUMsSUFBSSxDQUFDO1FBQ2pELGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDbEIsaUJBQVksR0FBdUIsSUFBSSxDQUFDO1FBQ3hDLFdBQU0sR0FBbUIsSUFBSSxDQUFDO1FBRzlCLGlCQUFZLEdBQUcsY0FBYyxFQUFFLENBQUM7UUFDaEMsMkJBQXNCLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUVyRDs7Ozs7Ozs7O1dBU0c7UUFDTSxjQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFxRzVDOzs7Ozs7V0FNRztRQUNNLGNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQztRQUU1Qzs7Ozs7V0FLRztRQUNNLGtCQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7UUEyQnBEOzs7O1dBSUc7UUFDTSxjQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFFNUM7Ozs7OztXQU1HO1FBQ00sbUJBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQztRQWF0RDs7Ozs7O1dBTUc7UUFDTyxlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUVuRDs7OztXQUlHO1FBQ08sYUFBUSxHQUFHLElBQUksWUFBWSxFQUE4QixDQUFDO1FBRXBFOzs7O1dBSUc7UUFDTyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztRQWNwQyxjQUFTLEdBQUcsQ0FBQyxDQUFNLEVBQUUsRUFBRSxHQUFFLENBQUMsQ0FBQztRQUMzQixlQUFVLEdBQUcsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBQ3RCLHFCQUFnQixHQUFHLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztLQWdUcEM7SUE5VEEsSUFDSSxRQUFRO1FBQ1gsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3ZCLENBQUM7SUFDRCxJQUFJLFFBQVEsQ0FBQyxLQUFVO1FBQ3RCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLEtBQUssT0FBTyxDQUFDLENBQUM7UUFFOUQsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDbEIsSUFBSSxDQUFDLEtBQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ3REO0lBQ0YsQ0FBQztJQU1ELGdCQUFnQixDQUFDLEVBQXVCO1FBQ3ZDLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxFQUFhO1FBQzlCLElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRCx5QkFBeUIsQ0FBQyxFQUFjO1FBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVELGdCQUFnQixDQUFDLFVBQW1CO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO0lBQzVCLENBQUM7SUFFRCxRQUFRLENBQUMsQ0FBa0I7UUFDMUIsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUVwQixJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUU7WUFDbEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBRXpFLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ2IsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO2FBQ3ZDO1lBRUQsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRTtnQkFDL0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUM7YUFDMUU7WUFFRCxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFO2dCQUM5RCxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQzthQUMxRTtTQUNEO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRUQsVUFBVSxDQUFDLEtBQUs7UUFDZixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUN2RSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxLQUFhLEVBQUUsVUFBVSxHQUFHLEtBQUs7UUFDakQsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLEtBQUssSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNyRCxJQUFJLGlCQUFpQixFQUFFO1lBQ3RCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDdkU7UUFDRCxJQUFJLGlCQUFpQixJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ3JDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ25HO1FBQ0QsSUFBSSxVQUFVLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUM5QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ25DO0lBQ0YsQ0FBQztJQUVELE1BQU07UUFDTCxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBSTtRQUNILElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDbkIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUV4RCxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDM0QsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4QyxJQUFJLENBQUMsOEJBQThCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN6RCxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMvQixJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFFdkUsZ0NBQWdDO1lBQ2hDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7Z0JBQ3JELElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzlCLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzdCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNuQixDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFFLENBQUM7WUFFN0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRXBELElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxNQUFNLEVBQUU7Z0JBQzlCLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7YUFDN0Y7WUFFRCxpQkFBaUI7WUFDakIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQW1DLENBQUM7WUFDdkUsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDakYsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7WUFFL0MsSUFBSSxXQUErQixDQUFDO1lBQ3BDLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRTtnQkFDbEMsV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQzthQUNoRTtpQkFBTSxJQUFJLElBQUksQ0FBQyxjQUFjLFlBQVksV0FBVyxFQUFFO2dCQUN0RCxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQzthQUNsQztpQkFBTTtnQkFDTixXQUFXLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUM7YUFDeEM7WUFFRCxJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ3hDLE1BQU0sSUFBSSxLQUFLLENBQUMsd0ZBQXdGLENBQUMsQ0FBQzthQUMxRztZQUVELCtEQUErRDtZQUMvRCxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtnQkFDbkMsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLFdBQVcsRUFBRTtvQkFDOUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUM7d0JBQzlCLFdBQVc7d0JBQ1gsYUFBYSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLGFBQWE7d0JBQ2hELFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUzt3QkFDekIsWUFBWSxFQUFFLElBQUksQ0FBQyxTQUFTLEtBQUssTUFBTTt3QkFDdkMsbUJBQW1CLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7cUJBQ3RGLENBQUMsQ0FBQztvQkFFSCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztpQkFDM0Y7WUFDRixDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1NBQ3pCO0lBQ0YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNKLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztZQUM5RCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztZQUNsQixJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsZUFBZSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBRXBDLGdCQUFnQjtZQUNoQixJQUFJLGNBQWMsR0FBdUIsSUFBSSxDQUFDLFlBQVksQ0FBQztZQUMzRCxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUU7Z0JBQ2hDLGNBQWMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDakU7aUJBQU0sSUFBSSxJQUFJLENBQUMsWUFBWSxLQUFLLFNBQVMsRUFBRTtnQkFDM0MsY0FBYyxHQUFHLElBQUksQ0FBQyxZQUEyQixDQUFDO2FBQ2xEO1lBRUQsaUZBQWlGO1lBQ2pGLElBQUksY0FBYyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDOUMsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQ3ZCO2lCQUFNO2dCQUNOLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQzVCO1NBQ0Q7SUFDRixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNO1FBQ0wsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDbEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2I7YUFBTTtZQUNOLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUNaO0lBQ0YsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxVQUFVLENBQUMsSUFBb0Q7UUFDOUQsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDbEIsSUFBSSxDQUFDLEtBQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3RDO0lBQ0YsQ0FBQztJQUVELE1BQU07UUFDTCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU87UUFDTixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDO0lBQy9DLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDakMsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQzdDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBRXhCLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFO2dCQUNsQixJQUFJLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtvQkFDdkIsSUFBSSxDQUFDLEtBQU0sQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztpQkFDOUM7Z0JBQ0QsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUU7b0JBQ3ZCLElBQUksQ0FBQyxLQUFNLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQzlDO2FBQ0Q7U0FDRDtRQUVELElBQUksT0FBTyxDQUFDLGlCQUFpQixDQUFDLEVBQUU7WUFDL0IsTUFBTSxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNuRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1NBQ25EO1FBRUQsSUFBSSxPQUFPLENBQUMsV0FBVyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQzFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1NBQ3pCO0lBQ0YsQ0FBQztJQUVELFdBQVc7UUFDVixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRU8sc0JBQXNCLENBQUMsc0JBQW1EO1FBQ2pGO1lBQ0MsaUJBQWlCO1lBQ2pCLGFBQWE7WUFDYixpQkFBaUI7WUFDakIsZUFBZTtZQUNmLGdCQUFnQjtZQUNoQixnQkFBZ0I7WUFDaEIsY0FBYztZQUNkLFNBQVM7WUFDVCxTQUFTO1lBQ1QsWUFBWTtZQUNaLGFBQWE7WUFDYixnQkFBZ0I7WUFDaEIsaUJBQWlCO1lBQ2pCLFVBQVU7U0FDVixDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQWlCLEVBQUUsRUFBRTtZQUMvQixJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxTQUFTLEVBQUU7Z0JBQ2xDLHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7YUFDNUQ7UUFDRixDQUFDLENBQUMsQ0FBQztRQUNILHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0UsQ0FBQztJQUVPLGdCQUFnQixDQUFDLFFBQWdCLEVBQUUsUUFBaUI7UUFDM0QsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsYUFBNEIsQ0FBQztRQUNsRSxJQUFJLE9BQU8sRUFBRTtZQUNaLElBQUksUUFBUSxFQUFFO2dCQUNiLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ2hDO1lBQ0QsSUFBSSxRQUFRLEVBQUU7Z0JBQ2IsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDbkM7U0FDRDtJQUNGLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxhQUEwQjtRQUNwRCxhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFckQsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLE1BQU0sRUFBRTtZQUM5QixhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUMzQztRQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVPLDhCQUE4QixDQUFDLGtCQUFpQztRQUN2RSxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBQzVGLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNoRCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzQixJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssSUFBSSxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssUUFBUSxFQUFFO2dCQUMzRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7YUFDYjtRQUNGLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVPLGdCQUFnQixDQUFDLEtBQXFCO1FBQzdDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFDekIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUN4QyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNsQixJQUFJLENBQUMsS0FBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUNsRSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDbEI7SUFDRixDQUFDO0lBRU8sZUFBZSxDQUFDLElBQTBCO1FBQ2pELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQzNFLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3pELENBQUM7SUFFTyxpQkFBaUI7UUFDeEIsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksRUFBRSxDQUFDO1FBQ25DLFlBQVksQ0FDWCxJQUFJLENBQUMsT0FBTyxFQUNaLElBQUksQ0FBQyxTQUFTLEVBQ2QsSUFBSSxDQUFDLFNBQVMsRUFDZCxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQ2xCLElBQUksQ0FBQyxzQkFBc0IsRUFDM0IsRUFBRSxFQUNGLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLEtBQU0sQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQy9ELENBQUM7SUFDSCxDQUFDOzhHQWxpQlcsa0JBQWtCO2tHQUFsQixrQkFBa0IsNCtCQU5uQjtZQUNWLEVBQUUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsa0JBQWtCLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO1lBQzlGLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRTtZQUMxRixFQUFFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsd0JBQXdCLEVBQUU7U0FDdkU7OzJGQUVXLGtCQUFrQjtrQkFqQjlCLFNBQVM7bUJBQUM7b0JBQ1YsUUFBUSxFQUFFLHNCQUFzQjtvQkFDaEMsUUFBUSxFQUFFLGVBQWU7b0JBQ3pCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixJQUFJLEVBQUU7d0JBQ0wsU0FBUyxFQUFFLHVDQUF1Qzt3QkFDbEQsVUFBVSxFQUFFLDZDQUE2Qzt3QkFDekQsU0FBUyxFQUFFLFdBQVc7d0JBQ3RCLFFBQVEsRUFBRSxVQUFVO3dCQUNwQixZQUFZLEVBQUUsVUFBVTtxQkFDeEI7b0JBQ0QsU0FBUyxFQUFFO3dCQUNWLEVBQUUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLG1CQUFtQixDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRTt3QkFDOUYsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLG1CQUFtQixDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRTt3QkFDMUYsRUFBRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLHdCQUF3QixFQUFFO3FCQUN2RTtpQkFDRDs4QkFxQ1MsU0FBUztzQkFBakIsS0FBSztnQkFXRyxlQUFlO3NCQUF2QixLQUFLO2dCQU9HLGVBQWU7c0JBQXZCLEtBQUs7Z0JBU0csV0FBVztzQkFBbkIsS0FBSztnQkFVRyxlQUFlO3NCQUF2QixLQUFLO2dCQUtHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBT0csY0FBYztzQkFBdEIsS0FBSztnQkFPRyxjQUFjO3NCQUF0QixLQUFLO2dCQVNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBT0csT0FBTztzQkFBZixLQUFLO2dCQU9HLE9BQU87c0JBQWYsS0FBSztnQkFTRyxVQUFVO3NCQUFsQixLQUFLO2dCQVdHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBU0csU0FBUztzQkFBakIsS0FBSztnQkFRRyxhQUFhO3NCQUFyQixLQUFLO2dCQVVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBS0csZUFBZTtzQkFBdkIsS0FBSztnQkFVRyxTQUFTO3NCQUFqQixLQUFLO2dCQU9HLFNBQVM7c0JBQWpCLEtBQUs7Z0JBU0csY0FBYztzQkFBdEIsS0FBSztnQkFXRyxRQUFRO3NCQUFoQixLQUFLO2dCQVNJLFVBQVU7c0JBQW5CLE1BQU07Z0JBT0csUUFBUTtzQkFBakIsTUFBTTtnQkFPRyxNQUFNO3NCQUFmLE1BQU07Z0JBR0gsUUFBUTtzQkFEWCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXG5cdENvbXBvbmVudFJlZixcblx0RGlyZWN0aXZlLFxuXHRFbGVtZW50UmVmLFxuXHRFdmVudEVtaXR0ZXIsXG5cdGZvcndhcmRSZWYsXG5cdGluamVjdCxcblx0SW5wdXQsXG5cdE5nWm9uZSxcblx0T25DaGFuZ2VzLFxuXHRPbkRlc3Ryb3ksXG5cdE91dHB1dCxcblx0U2ltcGxlQ2hhbmdlcyxcblx0VGVtcGxhdGVSZWYsXG5cdFZpZXdDb250YWluZXJSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRE9DVU1FTlQsIFRyYW5zbGF0aW9uV2lkdGggfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcblx0QWJzdHJhY3RDb250cm9sLFxuXHRDb250cm9sVmFsdWVBY2Nlc3Nvcixcblx0TkdfVkFMSURBVE9SUyxcblx0TkdfVkFMVUVfQUNDRVNTT1IsXG5cdFZhbGlkYXRpb25FcnJvcnMsXG5cdFZhbGlkYXRvcixcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBuZ2JBdXRvQ2xvc2UgfSBmcm9tICcuLi91dGlsL2F1dG9jbG9zZSc7XG5pbXBvcnQgeyBuZ2JGb2N1c1RyYXAgfSBmcm9tICcuLi91dGlsL2ZvY3VzLXRyYXAnO1xuaW1wb3J0IHsgbmdiUG9zaXRpb25pbmcgfSBmcm9tICcuLi91dGlsL3Bvc2l0aW9uaW5nJztcblxuaW1wb3J0IHsgTmdiRGF0ZUFkYXB0ZXIgfSBmcm9tICcuL2FkYXB0ZXJzL25nYi1kYXRlLWFkYXB0ZXInO1xuaW1wb3J0IHsgTmdiRGF0ZXBpY2tlciwgTmdiRGF0ZXBpY2tlck5hdmlnYXRlRXZlbnQgfSBmcm9tICcuL2RhdGVwaWNrZXInO1xuaW1wb3J0IHsgRGF5VGVtcGxhdGVDb250ZXh0IH0gZnJvbSAnLi9kYXRlcGlja2VyLWRheS10ZW1wbGF0ZS1jb250ZXh0JztcbmltcG9ydCB7IE5nYkNhbGVuZGFyIH0gZnJvbSAnLi9uZ2ItY2FsZW5kYXInO1xuaW1wb3J0IHsgTmdiRGF0ZSB9IGZyb20gJy4vbmdiLWRhdGUnO1xuaW1wb3J0IHsgTmdiRGF0ZVBhcnNlckZvcm1hdHRlciB9IGZyb20gJy4vbmdiLWRhdGUtcGFyc2VyLWZvcm1hdHRlcic7XG5pbXBvcnQgeyBOZ2JEYXRlU3RydWN0IH0gZnJvbSAnLi9uZ2ItZGF0ZS1zdHJ1Y3QnO1xuaW1wb3J0IHsgTmdiSW5wdXREYXRlcGlja2VyQ29uZmlnIH0gZnJvbSAnLi9kYXRlcGlja2VyLWlucHV0LWNvbmZpZyc7XG5pbXBvcnQgeyBOZ2JEYXRlcGlja2VyQ29uZmlnIH0gZnJvbSAnLi9kYXRlcGlja2VyLWNvbmZpZyc7XG5pbXBvcnQgeyBpc1N0cmluZyB9IGZyb20gJy4uL3V0aWwvdXRpbCc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBhZGRQb3BwZXJPZmZzZXQgfSBmcm9tICcuLi91dGlsL3Bvc2l0aW9uaW5nLXV0aWwnO1xuaW1wb3J0IHsgQ29udGVudFRlbXBsYXRlQ29udGV4dCB9IGZyb20gJy4vZGF0ZXBpY2tlci1jb250ZW50LXRlbXBsYXRlLWNvbnRleHQnO1xuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRoYXQgYWxsb3dzIHRvIHN0aWNrIGEgZGF0ZXBpY2tlciBwb3B1cCB0byBhbiBpbnB1dCBmaWVsZC5cbiAqXG4gKiBNYW5hZ2VzIGludGVyYWN0aW9uIHdpdGggdGhlIGlucHV0IGZpZWxkIGl0c2VsZiwgZG9lcyB2YWx1ZSBmb3JtYXR0aW5nIGFuZCBwcm92aWRlcyBmb3JtcyBpbnRlZ3JhdGlvbi5cbiAqL1xuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnaW5wdXRbbmdiRGF0ZXBpY2tlcl0nLFxuXHRleHBvcnRBczogJ25nYkRhdGVwaWNrZXInLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRob3N0OiB7XG5cdFx0JyhpbnB1dCknOiAnbWFudWFsRGF0ZUNoYW5nZSgkZXZlbnQudGFyZ2V0LnZhbHVlKScsXG5cdFx0JyhjaGFuZ2UpJzogJ21hbnVhbERhdGVDaGFuZ2UoJGV2ZW50LnRhcmdldC52YWx1ZSwgdHJ1ZSknLFxuXHRcdCcoZm9jdXMpJzogJ29uRm9jdXMoKScsXG5cdFx0JyhibHVyKSc6ICdvbkJsdXIoKScsXG5cdFx0J1tkaXNhYmxlZF0nOiAnZGlzYWJsZWQnLFxuXHR9LFxuXHRwcm92aWRlcnM6IFtcblx0XHR7IHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLCB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOZ2JJbnB1dERhdGVwaWNrZXIpLCBtdWx0aTogdHJ1ZSB9LFxuXHRcdHsgcHJvdmlkZTogTkdfVkFMSURBVE9SUywgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gTmdiSW5wdXREYXRlcGlja2VyKSwgbXVsdGk6IHRydWUgfSxcblx0XHR7IHByb3ZpZGU6IE5nYkRhdGVwaWNrZXJDb25maWcsIHVzZUV4aXN0aW5nOiBOZ2JJbnB1dERhdGVwaWNrZXJDb25maWcgfSxcblx0XSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiSW5wdXREYXRlcGlja2VyIGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBWYWxpZGF0b3Ige1xuXHRzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfYXV0b0Nsb3NlOiBib29sZWFuIHwgc3RyaW5nO1xuXHRzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfZGlzYWJsZWQ6IGJvb2xlYW4gfCAnJztcblx0c3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX25hdmlnYXRpb246IHN0cmluZztcblx0c3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX291dHNpZGVEYXlzOiBzdHJpbmc7XG5cdHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV93ZWVrZGF5czogYm9vbGVhbiB8IG51bWJlcjtcblxuXHRwcml2YXRlIF9wYXJzZXJGb3JtYXR0ZXIgPSBpbmplY3QoTmdiRGF0ZVBhcnNlckZvcm1hdHRlcik7XG5cdHByaXZhdGUgX2VsUmVmID0gaW5qZWN0KEVsZW1lbnRSZWY8SFRNTElucHV0RWxlbWVudD4pO1xuXHRwcml2YXRlIF92Y1JlZiA9IGluamVjdChWaWV3Q29udGFpbmVyUmVmKTtcblx0cHJpdmF0ZSBfbmdab25lID0gaW5qZWN0KE5nWm9uZSk7XG5cdHByaXZhdGUgX2NhbGVuZGFyID0gaW5qZWN0KE5nYkNhbGVuZGFyKTtcblx0cHJpdmF0ZSBfZGF0ZUFkYXB0ZXIgPSBpbmplY3QoTmdiRGF0ZUFkYXB0ZXI8YW55Pik7XG5cdHByaXZhdGUgX2RvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcblx0cHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3IgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXHRwcml2YXRlIF9jb25maWcgPSBpbmplY3QoTmdiSW5wdXREYXRlcGlja2VyQ29uZmlnKTtcblxuXHRwcml2YXRlIF9jUmVmOiBDb21wb25lbnRSZWY8TmdiRGF0ZXBpY2tlcj4gfCBudWxsID0gbnVsbDtcblx0cHJpdmF0ZSBfZGlzYWJsZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSBfZWxXaXRoRm9jdXM6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgX21vZGVsOiBOZ2JEYXRlIHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgX2lucHV0VmFsdWU6IHN0cmluZztcblx0cHJpdmF0ZSBfem9uZVN1YnNjcmlwdGlvbjogYW55O1xuXHRwcml2YXRlIF9wb3NpdGlvbmluZyA9IG5nYlBvc2l0aW9uaW5nKCk7XG5cdHByaXZhdGUgX2Rlc3Ryb3lDbG9zZUhhbmRsZXJzJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cblx0LyoqXG5cdCAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBkYXRlcGlja2VyIHBvcHVwIHNob3VsZCBiZSBjbG9zZWQgYXV0b21hdGljYWxseSBhZnRlciBkYXRlIHNlbGVjdGlvbiAvIG91dHNpZGUgY2xpY2sgb3Igbm90LlxuXHQgKlxuXHQgKiAqIGB0cnVlYCAtIHRoZSBwb3B1cCB3aWxsIGNsb3NlIG9uIGJvdGggZGF0ZSBzZWxlY3Rpb24gYW5kIG91dHNpZGUgY2xpY2suXG5cdCAqICogYGZhbHNlYCAtIHRoZSBwb3B1cCBjYW4gb25seSBiZSBjbG9zZWQgbWFudWFsbHkgdmlhIGBjbG9zZSgpYCBvciBgdG9nZ2xlKClgIG1ldGhvZHMuXG5cdCAqICogYFwiaW5zaWRlXCJgIC0gdGhlIHBvcHVwIHdpbGwgY2xvc2Ugb24gZGF0ZSBzZWxlY3Rpb24sIGJ1dCBub3Qgb3V0c2lkZSBjbGlja3MuXG5cdCAqICogYFwib3V0c2lkZVwiYCAtIHRoZSBwb3B1cCB3aWxsIGNsb3NlIG9ubHkgb24gdGhlIG91dHNpZGUgY2xpY2sgYW5kIG5vdCBvbiBkYXRlIHNlbGVjdGlvbi9pbnNpZGUgY2xpY2tzLlxuXHQgKlxuXHQgKiBAc2luY2UgMy4wLjBcblx0ICovXG5cdEBJbnB1dCgpIGF1dG9DbG9zZSA9IHRoaXMuX2NvbmZpZy5hdXRvQ2xvc2U7XG5cblx0LyoqXG5cdCAqIFRoZSByZWZlcmVuY2UgdG8gYSBjdXN0b20gY29udGVudCB0ZW1wbGF0ZS5cblx0ICpcblx0ICogQWxsb3dzIHRvIGNvbXBsZXRlbHkgb3ZlcnJpZGUgdGhlIHdheSBkYXRlcGlja2VyLlxuXHQgKlxuXHQgKiBTZWUgW2BOZ2JEYXRlcGlja2VyQ29udGVudGBdKCMvY29tcG9uZW50cy9kYXRlcGlja2VyL2FwaSNOZ2JEYXRlcGlja2VyQ29udGVudCkgZm9yIG1vcmUgZGV0YWlscy5cblx0ICpcblx0ICogQHNpbmNlIDE0LjIuMFxuXHQgKi9cblx0QElucHV0KCkgY29udGVudFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxDb250ZW50VGVtcGxhdGVDb250ZXh0PjtcblxuXHQvKipcblx0ICogQW4gb3B0aW9uYWwgY2xhc3MgYXBwbGllZCB0byB0aGUgZGF0ZXBpY2tlciBwb3B1cCBlbGVtZW50LlxuXHQgKlxuXHQgKiBAc2luY2UgOS4xLjBcblx0ICovXG5cdEBJbnB1dCgpIGRhdGVwaWNrZXJDbGFzczogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgcmVmZXJlbmNlIHRvIGEgY3VzdG9tIHRlbXBsYXRlIGZvciB0aGUgZGF5LlxuXHQgKlxuXHQgKiBBbGxvd3MgdG8gY29tcGxldGVseSBvdmVycmlkZSB0aGUgd2F5IGEgZGF5ICdjZWxsJyBpbiB0aGUgY2FsZW5kYXIgaXMgZGlzcGxheWVkLlxuXHQgKlxuXHQgKiBTZWUgW2BEYXlUZW1wbGF0ZUNvbnRleHRgXSgjL2NvbXBvbmVudHMvZGF0ZXBpY2tlci9hcGkjRGF5VGVtcGxhdGVDb250ZXh0KSBmb3IgdGhlIGRhdGEgeW91IGdldCBpbnNpZGUuXG5cdCAqL1xuXHRASW5wdXQoKSBkYXlUZW1wbGF0ZTogVGVtcGxhdGVSZWY8RGF5VGVtcGxhdGVDb250ZXh0PjtcblxuXHQvKipcblx0ICogVGhlIGNhbGxiYWNrIHRvIHBhc3MgYW55IGFyYml0cmFyeSBkYXRhIHRvIHRoZSB0ZW1wbGF0ZSBjZWxsIHZpYSB0aGVcblx0ICogW2BEYXlUZW1wbGF0ZUNvbnRleHRgXSgjL2NvbXBvbmVudHMvZGF0ZXBpY2tlci9hcGkjRGF5VGVtcGxhdGVDb250ZXh0KSdzIGBkYXRhYCBwYXJhbWV0ZXIuXG5cdCAqXG5cdCAqIGBjdXJyZW50YCBpcyB0aGUgbW9udGggdGhhdCBpcyBjdXJyZW50bHkgZGlzcGxheWVkIGJ5IHRoZSBkYXRlcGlja2VyLlxuXHQgKlxuXHQgKiBAc2luY2UgMy4zLjBcblx0ICovXG5cdEBJbnB1dCgpIGRheVRlbXBsYXRlRGF0YTogKGRhdGU6IE5nYkRhdGUsIGN1cnJlbnQ/OiB7IHllYXI6IG51bWJlcjsgbW9udGg6IG51bWJlciB9KSA9PiBhbnk7XG5cblx0LyoqXG5cdCAqIFRoZSBudW1iZXIgb2YgbW9udGhzIHRvIGRpc3BsYXkuXG5cdCAqL1xuXHRASW5wdXQoKSBkaXNwbGF5TW9udGhzOiBudW1iZXI7XG5cblx0LyoqXG5cdCAqIFRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG5cdCAqXG5cdCAqIFdpdGggZGVmYXVsdCBjYWxlbmRhciB3ZSB1c2UgSVNPIDg2MDE6ICd3ZWVrZGF5JyBpcyAxPU1vbiAuLi4gNz1TdW4uXG5cdCAqL1xuXHRASW5wdXQoKSBmaXJzdERheU9mV2VlazogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiBUaGUgcmVmZXJlbmNlIHRvIHRoZSBjdXN0b20gdGVtcGxhdGUgZm9yIHRoZSBkYXRlcGlja2VyIGZvb3Rlci5cblx0ICpcblx0ICogQHNpbmNlIDMuMy4wXG5cdCAqL1xuXHRASW5wdXQoKSBmb290ZXJUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcblxuXHQvKipcblx0ICogVGhlIGNhbGxiYWNrIHRvIG1hcmsgc29tZSBkYXRlcyBhcyBkaXNhYmxlZC5cblx0ICpcblx0ICogSXQgaXMgY2FsbGVkIGZvciBlYWNoIG5ldyBkYXRlIHdoZW4gbmF2aWdhdGluZyB0byBhIGRpZmZlcmVudCBtb250aC5cblx0ICpcblx0ICogYGN1cnJlbnRgIGlzIHRoZSBtb250aCB0aGF0IGlzIGN1cnJlbnRseSBkaXNwbGF5ZWQgYnkgdGhlIGRhdGVwaWNrZXIuXG5cdCAqL1xuXHRASW5wdXQoKSBtYXJrRGlzYWJsZWQ6IChkYXRlOiBOZ2JEYXRlLCBjdXJyZW50PzogeyB5ZWFyOiBudW1iZXI7IG1vbnRoOiBudW1iZXIgfSkgPT4gYm9vbGVhbjtcblxuXHQvKipcblx0ICogVGhlIGVhcmxpZXN0IGRhdGUgdGhhdCBjYW4gYmUgZGlzcGxheWVkIG9yIHNlbGVjdGVkLiBBbHNvIHVzZWQgZm9yIGZvcm0gdmFsaWRhdGlvbi5cblx0ICpcblx0ICogSWYgbm90IHByb3ZpZGVkLCAneWVhcicgc2VsZWN0IGJveCB3aWxsIGRpc3BsYXkgMTAgeWVhcnMgYmVmb3JlIHRoZSBjdXJyZW50IG1vbnRoLlxuXHQgKi9cblx0QElucHV0KCkgbWluRGF0ZTogTmdiRGF0ZVN0cnVjdDtcblxuXHQvKipcblx0ICogVGhlIGxhdGVzdCBkYXRlIHRoYXQgY2FuIGJlIGRpc3BsYXllZCBvciBzZWxlY3RlZC4gQWxzbyB1c2VkIGZvciBmb3JtIHZhbGlkYXRpb24uXG5cdCAqXG5cdCAqIElmIG5vdCBwcm92aWRlZCwgJ3llYXInIHNlbGVjdCBib3ggd2lsbCBkaXNwbGF5IDEwIHllYXJzIGFmdGVyIHRoZSBjdXJyZW50IG1vbnRoLlxuXHQgKi9cblx0QElucHV0KCkgbWF4RGF0ZTogTmdiRGF0ZVN0cnVjdDtcblxuXHQvKipcblx0ICogTmF2aWdhdGlvbiB0eXBlLlxuXHQgKlxuXHQgKiAqIGBcInNlbGVjdFwiYCAtIHNlbGVjdCBib3hlcyBmb3IgbW9udGggYW5kIG5hdmlnYXRpb24gYXJyb3dzXG5cdCAqICogYFwiYXJyb3dzXCJgIC0gb25seSBuYXZpZ2F0aW9uIGFycm93c1xuXHQgKiAqIGBcIm5vbmVcImAgLSBubyBuYXZpZ2F0aW9uIHZpc2libGUgYXQgYWxsXG5cdCAqL1xuXHRASW5wdXQoKSBuYXZpZ2F0aW9uOiAnc2VsZWN0JyB8ICdhcnJvd3MnIHwgJ25vbmUnO1xuXG5cdC8qKlxuXHQgKiBUaGUgd2F5IG9mIGRpc3BsYXlpbmcgZGF5cyB0aGF0IGRvbid0IGJlbG9uZyB0byB0aGUgY3VycmVudCBtb250aC5cblx0ICpcblx0ICogKiBgXCJ2aXNpYmxlXCJgIC0gZGF5cyBhcmUgdmlzaWJsZVxuXHQgKiAqIGBcImhpZGRlblwiYCAtIGRheXMgYXJlIGhpZGRlbiwgd2hpdGUgc3BhY2UgcHJlc2VydmVkXG5cdCAqICogYFwiY29sbGFwc2VkXCJgIC0gZGF5cyBhcmUgY29sbGFwc2VkLCBzbyB0aGUgZGF0ZXBpY2tlciBoZWlnaHQgbWlnaHQgY2hhbmdlIGJldHdlZW4gbW9udGhzXG5cdCAqXG5cdCAqIEZvciB0aGUgMisgbW9udGhzIHZpZXcsIGRheXMgaW4gYmV0d2VlbiBtb250aHMgYXJlIG5ldmVyIHNob3duLlxuXHQgKi9cblx0QElucHV0KCkgb3V0c2lkZURheXM6ICd2aXNpYmxlJyB8ICdjb2xsYXBzZWQnIHwgJ2hpZGRlbic7XG5cblx0LyoqXG5cdCAqIFRoZSBwcmVmZXJyZWQgcGxhY2VtZW50IG9mIHRoZSBkYXRlcGlja2VyIHBvcHVwLCBhbW9uZyB0aGUgW3Bvc3NpYmxlIHZhbHVlc10oIy9ndWlkZXMvcG9zaXRpb25pbmcjYXBpKS5cblx0ICpcblx0ICogVGhlIGRlZmF1bHQgb3JkZXIgb2YgcHJlZmVyZW5jZSBpcyBgXCJib3R0b20tc3RhcnQgYm90dG9tLWVuZCB0b3Atc3RhcnQgdG9wLWVuZFwiYFxuXHQgKlxuXHQgKiBQbGVhc2Ugc2VlIHRoZSBbcG9zaXRpb25pbmcgb3ZlcnZpZXddKCMvcG9zaXRpb25pbmcpIGZvciBtb3JlIGRldGFpbHMuXG5cdCAqL1xuXHRASW5wdXQoKSBwbGFjZW1lbnQgPSB0aGlzLl9jb25maWcucGxhY2VtZW50O1xuXG5cdC8qKlxuXHQgKiBBbGxvd3MgdG8gY2hhbmdlIGRlZmF1bHQgUG9wcGVyIG9wdGlvbnMgd2hlbiBwb3NpdGlvbmluZyB0aGUgcG9wdXAuXG5cdCAqIFJlY2VpdmVzIGN1cnJlbnQgcG9wcGVyIG9wdGlvbnMgYW5kIHJldHVybnMgbW9kaWZpZWQgb25lcy5cblx0ICpcblx0ICogQHNpbmNlIDEzLjEuMFxuXHQgKi9cblx0QElucHV0KCkgcG9wcGVyT3B0aW9ucyA9IHRoaXMuX2NvbmZpZy5wb3BwZXJPcHRpb25zO1xuXG5cdC8qKlxuXHQgKiBJZiBgdHJ1ZWAsIHdoZW4gY2xvc2luZyBkYXRlcGlja2VyIHdpbGwgZm9jdXMgZWxlbWVudCB0aGF0IHdhcyBmb2N1c2VkIGJlZm9yZSBkYXRlcGlja2VyIHdhcyBvcGVuZWQuXG5cdCAqXG5cdCAqIEFsdGVybmF0aXZlbHkgeW91IGNvdWxkIHByb3ZpZGUgYSBzZWxlY3RvciBvciBhbiBgSFRNTEVsZW1lbnRgIHRvIGZvY3VzLiBJZiB0aGUgZWxlbWVudCBkb2Vzbid0IGV4aXN0IG9yIGludmFsaWQsXG5cdCAqIHdlJ2xsIGZhbGxiYWNrIHRvIGZvY3VzIGRvY3VtZW50IGJvZHkuXG5cdCAqXG5cdCAqIEBzaW5jZSA1LjIuMFxuXHQgKi9cblx0QElucHV0KCkgcmVzdG9yZUZvY3VzOiB0cnVlIHwgc3RyaW5nIHwgSFRNTEVsZW1lbnQ7XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgd2VlayBudW1iZXJzIHdpbGwgYmUgZGlzcGxheWVkLlxuXHQgKi9cblx0QElucHV0KCkgc2hvd1dlZWtOdW1iZXJzOiBib29sZWFuO1xuXG5cdC8qKlxuXHQgKiBUaGUgZGF0ZSB0byBvcGVuIGNhbGVuZGFyIHdpdGguXG5cdCAqXG5cdCAqIFdpdGggdGhlIGRlZmF1bHQgY2FsZW5kYXIgd2UgdXNlIElTTyA4NjAxOiAnbW9udGgnIGlzIDE9SmFuIC4uLiAxMj1EZWMuXG5cdCAqIElmIG5vdGhpbmcgb3IgaW52YWxpZCBkYXRlIGlzIHByb3ZpZGVkLCBjYWxlbmRhciB3aWxsIG9wZW4gd2l0aCBjdXJyZW50IG1vbnRoLlxuXHQgKlxuXHQgKiBZb3UgY291bGQgdXNlIGBuYXZpZ2F0ZVRvKGRhdGUpYCBtZXRob2QgYXMgYW4gYWx0ZXJuYXRpdmUuXG5cdCAqL1xuXHRASW5wdXQoKSBzdGFydERhdGU6IHsgeWVhcjogbnVtYmVyOyBtb250aDogbnVtYmVyOyBkYXk/OiBudW1iZXIgfTtcblxuXHQvKipcblx0ICogQSBzZWxlY3RvciBzcGVjaWZ5aW5nIHRoZSBlbGVtZW50IHRoZSBkYXRlcGlja2VyIHBvcHVwIHNob3VsZCBiZSBhcHBlbmRlZCB0by5cblx0ICpcblx0ICogQ3VycmVudGx5IG9ubHkgc3VwcG9ydHMgYFwiYm9keVwiYC5cblx0ICovXG5cdEBJbnB1dCgpIGNvbnRhaW5lciA9IHRoaXMuX2NvbmZpZy5jb250YWluZXI7XG5cblx0LyoqXG5cdCAqIEEgY3NzIHNlbGVjdG9yIG9yIGh0bWwgZWxlbWVudCBzcGVjaWZ5aW5nIHRoZSBlbGVtZW50IHRoZSBkYXRlcGlja2VyIHBvcHVwIHNob3VsZCBiZSBwb3NpdGlvbmVkIGFnYWluc3QuXG5cdCAqXG5cdCAqIEJ5IGRlZmF1bHQgdGhlIGlucHV0IGlzIHVzZWQgYXMgYSB0YXJnZXQuXG5cdCAqXG5cdCAqIEBzaW5jZSA0LjIuMFxuXHQgKi9cblx0QElucHV0KCkgcG9zaXRpb25UYXJnZXQgPSB0aGlzLl9jb25maWcucG9zaXRpb25UYXJnZXQ7XG5cblx0LyoqXG5cdCAqIFRoZSB3YXkgd2Vla2RheXMgc2hvdWxkIGJlIGRpc3BsYXllZC5cblx0ICpcblx0ICogKiBgdHJ1ZWAgLSB3ZWVrZGF5cyBhcmUgZGlzcGxheWVkIHVzaW5nIGRlZmF1bHQgd2lkdGhcblx0ICogKiBgZmFsc2VgIC0gd2Vla2RheXMgYXJlIG5vdCBkaXNwbGF5ZWRcblx0ICogKiBgVHJhbnNsYXRpb25XaWR0aGAgLSB3ZWVrZGF5cyBhcmUgZGlzcGxheWVkIHVzaW5nIHNwZWNpZmllZCB3aWR0aFxuXHQgKlxuXHQgKiBAc2luY2UgOS4xLjBcblx0ICovXG5cdEBJbnB1dCgpIHdlZWtkYXlzOiBUcmFuc2xhdGlvbldpZHRoIHwgYm9vbGVhbjtcblxuXHQvKipcblx0ICogQW4gZXZlbnQgZW1pdHRlZCB3aGVuIHVzZXIgc2VsZWN0cyBhIGRhdGUgdXNpbmcga2V5Ym9hcmQgb3IgbW91c2UuXG5cdCAqXG5cdCAqIFRoZSBwYXlsb2FkIG9mIHRoZSBldmVudCBpcyBjdXJyZW50bHkgc2VsZWN0ZWQgYE5nYkRhdGVgLlxuXHQgKlxuXHQgKiBAc2luY2UgMS4xLjFcblx0ICovXG5cdEBPdXRwdXQoKSBkYXRlU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxOZ2JEYXRlPigpO1xuXG5cdC8qKlxuXHQgKiBFdmVudCBlbWl0dGVkIHJpZ2h0IGFmdGVyIHRoZSBuYXZpZ2F0aW9uIGhhcHBlbnMgYW5kIGRpc3BsYXllZCBtb250aCBjaGFuZ2VzLlxuXHQgKlxuXHQgKiBTZWUgW2BOZ2JEYXRlcGlja2VyTmF2aWdhdGVFdmVudGBdKCMvY29tcG9uZW50cy9kYXRlcGlja2VyL2FwaSNOZ2JEYXRlcGlja2VyTmF2aWdhdGVFdmVudCkgZm9yIHRoZSBwYXlsb2FkIGluZm8uXG5cdCAqL1xuXHRAT3V0cHV0KCkgbmF2aWdhdGUgPSBuZXcgRXZlbnRFbWl0dGVyPE5nYkRhdGVwaWNrZXJOYXZpZ2F0ZUV2ZW50PigpO1xuXG5cdC8qKlxuXHQgKiBBbiBldmVudCBmaXJlZCBhZnRlciBjbG9zaW5nIGRhdGVwaWNrZXIgd2luZG93LlxuXHQgKlxuXHQgKiBAc2luY2UgNC4yLjBcblx0ICovXG5cdEBPdXRwdXQoKSBjbG9zZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cblx0QElucHV0KClcblx0Z2V0IGRpc2FibGVkKCkge1xuXHRcdHJldHVybiB0aGlzLl9kaXNhYmxlZDtcblx0fVxuXHRzZXQgZGlzYWJsZWQodmFsdWU6IGFueSkge1xuXHRcdHRoaXMuX2Rpc2FibGVkID0gdmFsdWUgPT09ICcnIHx8ICh2YWx1ZSAmJiB2YWx1ZSAhPT0gJ2ZhbHNlJyk7XG5cblx0XHRpZiAodGhpcy5pc09wZW4oKSkge1xuXHRcdFx0dGhpcy5fY1JlZiEuaW5zdGFuY2Uuc2V0RGlzYWJsZWRTdGF0ZSh0aGlzLl9kaXNhYmxlZCk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBfb25DaGFuZ2UgPSAoXzogYW55KSA9PiB7fTtcblx0cHJpdmF0ZSBfb25Ub3VjaGVkID0gKCkgPT4ge307XG5cdHByaXZhdGUgX3ZhbGlkYXRvckNoYW5nZSA9ICgpID0+IHt9O1xuXG5cdHJlZ2lzdGVyT25DaGFuZ2UoZm46ICh2YWx1ZTogYW55KSA9PiBhbnkpOiB2b2lkIHtcblx0XHR0aGlzLl9vbkNoYW5nZSA9IGZuO1xuXHR9XG5cblx0cmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IGFueSk6IHZvaWQge1xuXHRcdHRoaXMuX29uVG91Y2hlZCA9IGZuO1xuXHR9XG5cblx0cmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZShmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xuXHRcdHRoaXMuX3ZhbGlkYXRvckNoYW5nZSA9IGZuO1xuXHR9XG5cblx0c2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG5cdFx0dGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG5cdH1cblxuXHR2YWxpZGF0ZShjOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG5cdFx0Y29uc3QgeyB2YWx1ZSB9ID0gYztcblxuXHRcdGlmICh2YWx1ZSAhPSBudWxsKSB7XG5cdFx0XHRjb25zdCBuZ2JEYXRlID0gdGhpcy5fZnJvbURhdGVTdHJ1Y3QodGhpcy5fZGF0ZUFkYXB0ZXIuZnJvbU1vZGVsKHZhbHVlKSk7XG5cblx0XHRcdGlmICghbmdiRGF0ZSkge1xuXHRcdFx0XHRyZXR1cm4geyBuZ2JEYXRlOiB7IGludmFsaWQ6IHZhbHVlIH0gfTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHRoaXMubWluRGF0ZSAmJiBuZ2JEYXRlLmJlZm9yZShOZ2JEYXRlLmZyb20odGhpcy5taW5EYXRlKSkpIHtcblx0XHRcdFx0cmV0dXJuIHsgbmdiRGF0ZTogeyBtaW5EYXRlOiB7IG1pbkRhdGU6IHRoaXMubWluRGF0ZSwgYWN0dWFsOiB2YWx1ZSB9IH0gfTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHRoaXMubWF4RGF0ZSAmJiBuZ2JEYXRlLmFmdGVyKE5nYkRhdGUuZnJvbSh0aGlzL