UNPKG

@ng-bootstrap/ng-bootstrap

Version:
557 lines 58.3 kB
import { ApplicationRef, ContentChild, ContentChildren, Directive, ElementRef, EventEmitter, forwardRef, inject, Inject, Input, Output, TemplateRef, } from '@angular/core'; import { NgbCollapse } from '../collapse/collapse'; import { isString } from '../util/util'; import * as i0 from "@angular/core"; import * as i1 from "../collapse/collapse"; import * as i2 from "./accordion-config"; let nextId = 0; /** * A directive that wraps the content of an accordion item's collapsible body. * * The actual content is provided in a child `ng-template` element. * Depending on the state of the accordion, the template will be either inserted or removed from the DOM. * * @since 14.1.0 */ class NgbAccordionBody { constructor() { this._appRef = inject(ApplicationRef); this._element = inject((ElementRef)).nativeElement; this._item = inject(NgbAccordionItem); this._viewRef = null; } ngAfterContentChecked() { if (this._bodyTpl) { if (this._item.animatingBodyCollapse || !this._item.destroyOnHide) { this._createViewIfNotExists(); } else { this._destroyViewIfExists(); } } } ngOnDestroy() { this._destroyViewIfExists(); } _destroyViewIfExists() { if (this._viewRef) { this._appRef.detachView(this._viewRef); this._viewRef.destroy(); this._viewRef = null; } } _createViewIfNotExists() { if (!this._viewRef) { this._viewRef = this._bodyTpl.createEmbeddedView(null); this._viewRef.detectChanges(); this._appRef.attachView(this._viewRef); for (const node of this._viewRef.rootNodes) { this._element.appendChild(node); } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionBody, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.6", type: NgbAccordionBody, isStandalone: true, selector: "[ngbAccordionBody]", host: { properties: { "class.accordion-body": "true" } }, queries: [{ propertyName: "_bodyTpl", first: true, predicate: TemplateRef, descendants: true, static: true }], ngImport: i0 }); } } export { NgbAccordionBody }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionBody, decorators: [{ type: Directive, args: [{ selector: '[ngbAccordionBody]', standalone: true, host: { '[class.accordion-body]': 'true' }, }] }], propDecorators: { _bodyTpl: [{ type: ContentChild, args: [TemplateRef, { static: true }] }] } }); /** * A directive that wraps the collapsible item's content of the accordion. * * Internally it reuses the [`NgbCollapse` directive](#/components/collapse) * * @since 14.1.0 */ class NgbAccordionCollapse { constructor(item, ngbCollapse) { this.item = item; this.ngbCollapse = ngbCollapse; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionCollapse, deps: [{ token: forwardRef(() => NgbAccordionItem) }, { token: i1.NgbCollapse }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.6", type: NgbAccordionCollapse, isStandalone: true, selector: "[ngbAccordionCollapse]", host: { attributes: { "role": "region" }, properties: { "class.accordion-collapse": "true", "id": "item.collapseId", "attr.aria-labelledby": "item.toggleId" } }, exportAs: ["ngbAccordionCollapse"], hostDirectives: [{ directive: i1.NgbCollapse }], ngImport: i0 }); } } export { NgbAccordionCollapse }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionCollapse, decorators: [{ type: Directive, args: [{ exportAs: 'ngbAccordionCollapse', standalone: true, selector: '[ngbAccordionCollapse]', host: { role: 'region', '[class.accordion-collapse]': 'true', '[id]': 'item.collapseId', '[attr.aria-labelledby]': 'item.toggleId', }, hostDirectives: [ { directive: NgbCollapse, }, ], }] }], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{ type: Inject, args: [forwardRef(() => NgbAccordionItem)] }] }, { type: i1.NgbCollapse }]; } }); /** * A directive to put on a toggling element inside the accordion item's header. * It will register click handlers that toggle the associated panel and will handle accessibility attributes. * * This directive is used internally by the [`NgbAccordionButton` directive](#/components/accordion/api#NgbAccordionButton). * * @since 14.1.0 */ class NgbAccordionToggle { constructor(item, accordion) { this.item = item; this.accordion = accordion; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionToggle, deps: [{ token: forwardRef(() => NgbAccordionItem) }, { token: forwardRef(() => NgbAccordionDirective) }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.6", type: NgbAccordionToggle, isStandalone: true, selector: "[ngbAccordionToggle]", host: { listeners: { "click": "!item.disabled && accordion.toggle(item.id)" }, properties: { "id": "item.toggleId", "class.collapsed": "item.collapsed", "attr.aria-controls": "item.collapseId", "attr.aria-expanded": "!item.collapsed" } }, ngImport: i0 }); } } export { NgbAccordionToggle }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionToggle, decorators: [{ type: Directive, args: [{ selector: '[ngbAccordionToggle]', standalone: true, host: { '[id]': 'item.toggleId', '[class.collapsed]': 'item.collapsed', '[attr.aria-controls]': 'item.collapseId', '[attr.aria-expanded]': '!item.collapsed', '(click)': '!item.disabled && accordion.toggle(item.id)', }, }] }], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{ type: Inject, args: [forwardRef(() => NgbAccordionItem)] }] }, { type: NgbAccordionDirective, decorators: [{ type: Inject, args: [forwardRef(() => NgbAccordionDirective)] }] }]; } }); /** * A directive to put on a button element inside an accordion item's header. * * If you want a custom markup for the header, you can also use the [`NgbAccordionToggle` directive](#/components/accordion/api#NgbAccordionToggle). * * @since 14.1.0 */ class NgbAccordionButton { constructor(item) { this.item = item; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionButton, deps: [{ token: forwardRef(() => NgbAccordionItem) }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.6", type: NgbAccordionButton, isStandalone: true, selector: "button[ngbAccordionButton]", host: { attributes: { "type": "button" }, properties: { "disabled": "item.disabled", "class.accordion-button": "true" } }, hostDirectives: [{ directive: NgbAccordionToggle }], ngImport: i0 }); } } export { NgbAccordionButton }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionButton, decorators: [{ type: Directive, args: [{ selector: 'button[ngbAccordionButton]', standalone: true, host: { '[disabled]': 'item.disabled', '[class.accordion-button]': 'true', type: 'button', }, hostDirectives: [ { directive: NgbAccordionToggle, }, ], }] }], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{ type: Inject, args: [forwardRef(() => NgbAccordionItem)] }] }]; } }); /** * A directive that wraps an accordion item's header. * * @since 14.1.0 */ class NgbAccordionHeader { constructor(item) { this.item = item; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionHeader, deps: [{ token: forwardRef(() => NgbAccordionItem) }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.6", type: NgbAccordionHeader, isStandalone: true, selector: "[ngbAccordionHeader]", host: { attributes: { "role": "heading" }, properties: { "class.accordion-header": "true", "class.collapsed": "item.collapsed" } }, ngImport: i0 }); } } export { NgbAccordionHeader }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionHeader, decorators: [{ type: Directive, args: [{ selector: '[ngbAccordionHeader]', standalone: true, host: { role: 'heading', '[class.accordion-header]': 'true', '[class.collapsed]': 'item.collapsed', }, }] }], ctorParameters: function () { return [{ type: NgbAccordionItem, decorators: [{ type: Inject, args: [forwardRef(() => NgbAccordionItem)] }] }]; } }); /** * A directive that wraps an accordion item: a toggleable header + body that collapses. * * You can get hold of the `NgbAccordionItem` instance in the template with `#item="ngbAccordionItem"`. * It allows to check if the item is collapsed or not, toggle the collapse state, etc. * * Every accordion item has a string ID that is automatically generated in the `ngb-accordion-item-XX` format, unless provided explicitly. * * @since 14.1.0 */ class NgbAccordionItem { constructor(_accordion, _cd) { this._accordion = _accordion; this._cd = _cd; this._subscriptions = []; this._collapsed = true; this._id = `ngb-accordion-item-${nextId++}`; this.animatingBodyCollapse = false; /** * If `true`, the accordion item will be disabled. * It won't react to user's clicks, but still will be toggelable programmatically. */ this.disabled = false; /** * Event emitted before the expanding animation starts. It has no payload. * * @since 15.1.0 */ this.show = new EventEmitter(); /** * Event emitted when the expanding animation is finished. It has no payload. */ this.shown = new EventEmitter(); /** * Event emitted before the collapsing animation starts. It has no payload. * * @since 15.1.0 */ this.hide = new EventEmitter(); /** * Event emitted when the collapsing animation is finished and before the content is removed from DOM. * It has no payload. */ this.hidden = new EventEmitter(); } /** * Sets the custom ID of the accordion item. It must be unique for the document. * * @param id The ID of the accordion item, must be a non-empty string */ set id(id) { if (isString(id) && id !== '') { this._id = id; } } /** * If `true`, the content of the accordion item's body will be removed from the DOM. It will be just hidden otherwise. * * This property can also be set up on the parent [`NgbAccordion` directive](#/components/accordion/api#NgbAccordionDirective). */ set destroyOnHide(destroyOnHide) { this._destroyOnHide = destroyOnHide; } get destroyOnHide() { return this._destroyOnHide === undefined ? this._accordion.destroyOnHide : this._destroyOnHide; } /** * If `true`, the accordion item will be collapsed. Otherwise, it will be expanded. * * @param collapsed New state of the accordion item. */ set collapsed(collapsed) { if (this.collapsed !== collapsed) { // checking if accordion allows to expand the panel in respect to 'closeOthers' flag if (this.collapsed && !this._accordion._ensureCanExpand(this)) { return; } // changing the collapsed state this._collapsed = collapsed; this._cd.markForCheck(); // need if the accordion is used inside a component having OnPush change detection strategy // we need force CD to get template into DOM before starting animation to calculate its height correctly if (!this.collapsed) { this.animatingBodyCollapse = true; this._cd.detectChanges(); } // firing events before starting animations if (!this.collapsed) { this.show.emit(); this._accordion.show.emit(this.id); } else { this.hide.emit(); this._accordion.hide.emit(this.id); } // we also need to make sure 'animation' flag is up-to- date this._collapse.ngbCollapse.animation = this._accordion.animation; this._collapse.ngbCollapse.collapsed = this.collapsed; } } get collapsed() { return this._collapsed; } get id() { return `${this._id}`; } get toggleId() { return `${this.id}-toggle`; } get collapseId() { return `${this.id}-collapse`; } ngAfterContentInit() { const { ngbCollapse } = this._collapse; // we need to disable the animation for the first init ngbCollapse.animation = false; ngbCollapse.collapsed = this.collapsed; // we set the animation to the default of the accordion ngbCollapse.animation = this._accordion.animation; // event forwarding from 'ngbCollapse' to 'ngbAccordion' this._subscriptions.push(ngbCollapse.hidden.subscribe(() => { // when the animation finishes we can remove the template from DOM this.animatingBodyCollapse = false; this.hidden.emit(); this._accordion.hidden.emit(this.id); }), ngbCollapse.shown.subscribe(() => { this.shown.emit(); this._accordion.shown.emit(this.id); })); } ngOnDestroy() { this._subscriptions.forEach((s) => s.unsubscribe()); } /** * Toggles an accordion item. */ toggle() { this.collapsed = !this.collapsed; } /** * Expands an accordion item. */ expand() { this.collapsed = false; } /** * Collapses an accordion item. */ collapse() { this.collapsed = true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionItem, deps: [{ token: forwardRef(() => NgbAccordionDirective) }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.6", type: NgbAccordionItem, isStandalone: true, selector: "[ngbAccordionItem]", inputs: { id: ["ngbAccordionItem", "id"], destroyOnHide: "destroyOnHide", disabled: "disabled", collapsed: "collapsed" }, outputs: { show: "show", shown: "shown", hide: "hide", hidden: "hidden" }, host: { properties: { "class.accordion-item": "true", "id": "id" } }, queries: [{ propertyName: "_collapse", first: true, predicate: NgbAccordionCollapse, descendants: true, static: true }], exportAs: ["ngbAccordionItem"], ngImport: i0 }); } } export { NgbAccordionItem }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionItem, decorators: [{ type: Directive, args: [{ selector: '[ngbAccordionItem]', exportAs: 'ngbAccordionItem', standalone: true, host: { '[class.accordion-item]': 'true', '[id]': 'id', }, }] }], ctorParameters: function () { return [{ type: NgbAccordionDirective, decorators: [{ type: Inject, args: [forwardRef(() => NgbAccordionDirective)] }] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { _collapse: [{ type: ContentChild, args: [NgbAccordionCollapse, { static: true }] }], id: [{ type: Input, args: ['ngbAccordionItem'] }], destroyOnHide: [{ type: Input }], disabled: [{ type: Input }], collapsed: [{ type: Input }], show: [{ type: Output }], shown: [{ type: Output }], hide: [{ type: Output }], hidden: [{ type: Output }] } }); /** * Accordion is a stack of cards that have a header and collapsible body. * * This directive is a container for these items and provides an API to handle them. * * @since 14.1.0 */ class NgbAccordionDirective { constructor(config) { /** * If `true`, the content of the accordion items body will be removed from the DOM. It will be just hidden otherwise. * * This property can be overwritten at the [`NgbAccordionItem`](#/components/accordion/api#NgbAccordionItem) level */ this.destroyOnHide = true; /** * Event emitted before expanding animation starts. The payload is the id of shown accordion item. * * @since 15.1.0 */ this.show = new EventEmitter(); /** * Event emitted when the expanding animation is finished. The payload is the id of shown accordion item. */ this.shown = new EventEmitter(); /** * Event emitted before the collapsing animation starts. The payload is the id of hidden accordion item. * * @since 15.1.0 */ this.hide = new EventEmitter(); /** * Event emitted when the collapsing animation is finished and before the content is removed from DOM. * The payload is the id of hidden accordion item. */ this.hidden = new EventEmitter(); this._anItemWasAlreadyExpandedDuringInitialisation = false; this.animation = config.animation; this.closeOthers = config.closeOthers; } /** * Toggles an item with the given id. * * It will toggle an item, even if it is disabled. * * @param itemId The id of the item to toggle. */ toggle(itemId) { this._getItem(itemId)?.toggle(); } /** * Expands an item with the given id. * * If `closeOthers` is `true`, it will collapse other panels. * * @param itemId The id of the item to expand. */ expand(itemId) { this._getItem(itemId)?.expand(); } /** * Expands all items. * * If `closeOthers` is `true` and all items are closed, it will open the first one. Otherwise, it will keep the opened one. */ expandAll() { if (this._items) { if (this.closeOthers) { // we check if there is an item open and if it is not we can expand the first item // (otherwise we toggle nothing) if (!this._items.find((item) => !item.collapsed)) { this._items.first.expand(); } } else { this._items.forEach((item) => item.expand()); } } } /** * Collapses an item with the given id. * * Has no effect if the `itemId` does not correspond to any item. * * @param itemId The id of the item to collapse. */ collapse(itemId) { this._getItem(itemId)?.collapse(); } /** * Collapses all items. */ collapseAll() { this._items?.forEach((item) => item.collapse()); } /** * Checks if an item with the given id is expanded. * * If the `itemId` does not correspond to any item, it returns `false`. * * @param itemId The id of the item to check. */ isExpanded(itemId) { const item = this._getItem(itemId); return item ? !item.collapsed : false; } /** * It checks, if the item can be expanded in the current state of the accordion. * With `closeOthers` there can be only one expanded item at a time. * * @internal */ _ensureCanExpand(toExpand) { if (!this.closeOthers) { return true; } // special case during the initialization of the [collapse]="false" inputs // `this._items` QueryList is not yet initialized, but we need to ensure only one item can be expanded at a time if (!this._items) { if (!this._anItemWasAlreadyExpandedDuringInitialisation) { this._anItemWasAlreadyExpandedDuringInitialisation = true; return true; } return false; } // if there is an expanded item, we need to collapse it first this._items.find((item) => !item.collapsed && toExpand !== item)?.collapse(); return true; } _getItem(itemId) { return this._items?.find((item) => item.id === itemId); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionDirective, deps: [{ token: i2.NgbAccordionConfig }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.6", type: NgbAccordionDirective, isStandalone: true, selector: "[ngbAccordion]", inputs: { animation: "animation", closeOthers: "closeOthers", destroyOnHide: "destroyOnHide" }, outputs: { show: "show", shown: "shown", hide: "hide", hidden: "hidden" }, host: { properties: { "class.accordion": "true" } }, queries: [{ propertyName: "_items", predicate: NgbAccordionItem }], exportAs: ["ngbAccordion"], ngImport: i0 }); } } export { NgbAccordionDirective }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.6", ngImport: i0, type: NgbAccordionDirective, decorators: [{ type: Directive, args: [{ selector: '[ngbAccordion]', standalone: true, exportAs: 'ngbAccordion', host: { '[class.accordion]': 'true' }, }] }], ctorParameters: function () { return [{ type: i2.NgbAccordionConfig }]; }, propDecorators: { _items: [{ type: ContentChildren, args: [NgbAccordionItem, { descendants: false }] }], animation: [{ type: Input }], closeOthers: [{ type: Input }], destroyOnHide: [{ type: Input }], show: [{ type: Output }], shown: [{ type: Output }], hide: [{ type: Output }], hidden: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3JkaW9uLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hY2NvcmRpb24vYWNjb3JkaW9uLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR04sY0FBYyxFQUVkLFlBQVksRUFDWixlQUFlLEVBQ2YsU0FBUyxFQUNULFVBQVUsRUFFVixZQUFZLEVBQ1osVUFBVSxFQUNWLE1BQU0sRUFDTixNQUFNLEVBQ04sS0FBSyxFQUVMLE1BQU0sRUFFTixXQUFXLEdBQ1gsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxjQUFjLENBQUM7Ozs7QUFFeEMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBRWY7Ozs7Ozs7R0FPRztBQUNILE1BS2EsZ0JBQWdCO0lBTDdCO1FBTVMsWUFBTyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNqQyxhQUFRLEdBQUcsTUFBTSxDQUFDLENBQUEsVUFBdUIsQ0FBQSxDQUFDLENBQUMsYUFBYSxDQUFDO1FBQ3pELFVBQUssR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUVqQyxhQUFRLEdBQWdDLElBQUksQ0FBQztLQW9DckQ7SUFoQ0EscUJBQXFCO1FBQ3BCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNsQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMscUJBQXFCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRTtnQkFDbEUsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7YUFDOUI7aUJBQU07Z0JBQ04sSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7YUFDNUI7U0FDRDtJQUNGLENBQUM7SUFFRCxXQUFXO1FBQ1YsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVPLG9CQUFvQjtRQUMzQixJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7U0FDckI7SUFDRixDQUFDO0lBRU8sc0JBQXNCO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ25CLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN2RCxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN2QyxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFO2dCQUMzQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUNoQztTQUNEO0lBQ0YsQ0FBQzs4R0F4Q1csZ0JBQWdCO2tHQUFoQixnQkFBZ0IsOEtBT2QsV0FBVzs7U0FQYixnQkFBZ0I7MkZBQWhCLGdCQUFnQjtrQkFMNUIsU0FBUzttQkFBQztvQkFDVixRQUFRLEVBQUUsb0JBQW9CO29CQUM5QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsSUFBSSxFQUFFLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxFQUFFO2lCQUMxQzs4QkFRcUQsUUFBUTtzQkFBNUQsWUFBWTt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFOztBQW9DNUM7Ozs7OztHQU1HO0FBQ0gsTUFnQmEsb0JBQW9CO0lBQ2hDLFlBQ29ELElBQXNCLEVBQ2xFLFdBQXdCO1FBRG9CLFNBQUksR0FBSixJQUFJLENBQWtCO1FBQ2xFLGdCQUFXLEdBQVgsV0FBVyxDQUFhO0lBQzdCLENBQUM7OEdBSlEsb0JBQW9CLGtCQUV2QixVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7a0dBRi9CLG9CQUFvQjs7U0FBcEIsb0JBQW9COzJGQUFwQixvQkFBb0I7a0JBaEJoQyxTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSxzQkFBc0I7b0JBQ2hDLFVBQVUsRUFBRSxJQUFJO29CQUNoQixRQUFRLEVBQUUsd0JBQXdCO29CQUNsQyxJQUFJLEVBQUU7d0JBQ0wsSUFBSSxFQUFFLFFBQVE7d0JBQ2QsNEJBQTRCLEVBQUUsTUFBTTt3QkFDcEMsTUFBTSxFQUFFLGlCQUFpQjt3QkFDekIsd0JBQXdCLEVBQUUsZUFBZTtxQkFDekM7b0JBQ0QsY0FBYyxFQUFFO3dCQUNmOzRCQUNDLFNBQVMsRUFBRSxXQUFXO3lCQUN0QjtxQkFDRDtpQkFDRDs7MEJBR0UsTUFBTTsyQkFBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7O0FBSzVDOzs7Ozs7O0dBT0c7QUFDSCxNQVdhLGtCQUFrQjtJQUM5QixZQUNvRCxJQUFzQixFQUNqQixTQUFnQztRQURyQyxTQUFJLEdBQUosSUFBSSxDQUFrQjtRQUNqQixjQUFTLEdBQVQsU0FBUyxDQUF1QjtJQUN0RixDQUFDOzhHQUpRLGtCQUFrQixrQkFFckIsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUFDLGFBQ2xDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztrR0FIcEMsa0JBQWtCOztTQUFsQixrQkFBa0I7MkZBQWxCLGtCQUFrQjtrQkFYOUIsU0FBUzttQkFBQztvQkFDVixRQUFRLEVBQUUsc0JBQXNCO29CQUNoQyxVQUFVLEVBQUUsSUFBSTtvQkFDaEIsSUFBSSxFQUFFO3dCQUNMLE1BQU0sRUFBRSxlQUFlO3dCQUN2QixtQkFBbUIsRUFBRSxnQkFBZ0I7d0JBQ3JDLHNCQUFzQixFQUFFLGlCQUFpQjt3QkFDekMsc0JBQXNCLEVBQUUsaUJBQWlCO3dCQUN6QyxTQUFTLEVBQUUsNkNBQTZDO3FCQUN4RDtpQkFDRDs7MEJBR0UsTUFBTTsyQkFBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7OzBCQUN6QyxNQUFNOzJCQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQzs7QUFJakQ7Ozs7OztHQU1HO0FBQ0gsTUFjYSxrQkFBa0I7SUFDOUIsWUFBK0QsSUFBc0I7UUFBdEIsU0FBSSxHQUFKLElBQUksQ0FBa0I7SUFBRyxDQUFDOzhHQUQ3RSxrQkFBa0Isa0JBQ1YsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUFDO2tHQUQxQyxrQkFBa0IsdU5BNUJsQixrQkFBa0I7O1NBNEJsQixrQkFBa0I7MkZBQWxCLGtCQUFrQjtrQkFkOUIsU0FBUzttQkFBQztvQkFDVixRQUFRLEVBQUUsNEJBQTRCO29CQUN0QyxVQUFVLEVBQUUsSUFBSTtvQkFDaEIsSUFBSSxFQUFFO3dCQUNMLFlBQVksRUFBRSxlQUFlO3dCQUM3QiwwQkFBMEIsRUFBRSxNQUFNO3dCQUNsQyxJQUFJLEVBQUUsUUFBUTtxQkFDZDtvQkFDRCxjQUFjLEVBQUU7d0JBQ2Y7NEJBQ0MsU0FBUyxFQUFFLGtCQUFrQjt5QkFDN0I7cUJBQ0Q7aUJBQ0Q7OzBCQUVhLE1BQU07MkJBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUFDOztBQUd2RDs7OztHQUlHO0FBQ0gsTUFTYSxrQkFBa0I7SUFDOUIsWUFBK0QsSUFBc0I7UUFBdEIsU0FBSSxHQUFKLElBQUksQ0FBa0I7SUFBRyxDQUFDOzhHQUQ3RSxrQkFBa0Isa0JBQ1YsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUFDO2tHQUQxQyxrQkFBa0I7O1NBQWxCLGtCQUFrQjsyRkFBbEIsa0JBQWtCO2tCQVQ5QixTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSxzQkFBc0I7b0JBQ2hDLFVBQVUsRUFBRSxJQUFJO29CQUNoQixJQUFJLEVBQUU7d0JBQ0wsSUFBSSxFQUFFLFNBQVM7d0JBQ2YsMEJBQTBCLEVBQUUsTUFBTTt3QkFDbEMsbUJBQW1CLEVBQUUsZ0JBQWdCO3FCQUNyQztpQkFDRDs7MEJBRWEsTUFBTTsyQkFBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7O0FBR3ZEOzs7Ozs7Ozs7R0FTRztBQUNILE1BU2EsZ0JBQWdCO0lBQzVCLFlBQzBELFVBQWlDLEVBQ2xGLEdBQXNCO1FBRDJCLGVBQVUsR0FBVixVQUFVLENBQXVCO1FBQ2xGLFFBQUcsR0FBSCxHQUFHLENBQW1CO1FBR3ZCLG1CQUFjLEdBQW1CLEVBQUUsQ0FBQztRQUNwQyxlQUFVLEdBQUcsSUFBSSxDQUFDO1FBQ2xCLFFBQUcsR0FBRyxzQkFBc0IsTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUcvQywwQkFBcUIsR0FBRyxLQUFLLENBQUM7UUE0QjlCOzs7V0FHRztRQUNNLGFBQVEsR0FBRyxLQUFLLENBQUM7UUF1QzFCOzs7O1dBSUc7UUFDTyxTQUFJLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztRQUUxQzs7V0FFRztRQUNPLFVBQUssR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBRTNDOzs7O1dBSUc7UUFDTyxTQUFJLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztRQUUxQzs7O1dBR0c7UUFDTyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztJQXJHekMsQ0FBQztJQVdKOzs7O09BSUc7SUFDSCxJQUErQixFQUFFLENBQUMsRUFBVTtRQUMzQyxJQUFJLFFBQVEsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQzlCLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDO1NBQ2Q7SUFDRixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQWEsYUFBYSxDQUFDLGFBQXNCO1FBQ2hELElBQUksQ0FBQyxjQUFjLEdBQUcsYUFBYSxDQUFDO0lBQ3JDLENBQUM7SUFFRCxJQUFJLGFBQWE7UUFDaEIsT0FBTyxJQUFJLENBQUMsY0FBYyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFlLENBQUM7SUFDakcsQ0FBQztJQVFEOzs7O09BSUc7SUFDSCxJQUFhLFNBQVMsQ0FBQyxTQUFrQjtRQUN4QyxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFO1lBQ2pDLG9GQUFvRjtZQUNwRixJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUM5RCxPQUFPO2FBQ1A7WUFFRCwrQkFBK0I7WUFDL0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUM7WUFFNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLDJGQUEyRjtZQUNwSCx3R0FBd0c7WUFDeEcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7YUFDekI7WUFFRCwyQ0FBMkM7WUFDM0MsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2pCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDbkM7aUJBQU07Z0JBQ04sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDakIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUNuQztZQUVELDREQUE0RDtZQUM1RCxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7WUFDakUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7U0FDdEQ7SUFDRixDQUFDO0lBMkJELElBQUksU0FBUztRQUNaLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN4QixDQUFDO0lBRUQsSUFBSSxFQUFFO1FBQ0wsT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1gsT0FBTyxHQUFHLElBQUksQ0FBQyxFQUFFLFNBQVMsQ0FBQztJQUM1QixDQUFDO0lBRUQsSUFBSSxVQUFVO1FBQ2IsT0FBTyxHQUFHLElBQUksQ0FBQyxFQUFFLFdBQVcsQ0FBQztJQUM5QixDQUFDO0lBRUQsa0JBQWtCO1FBQ2pCLE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBQ3ZDLHNEQUFzRDtRQUN0RCxXQUFXLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUM5QixXQUFXLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDdkMsdURBQXVEO1FBQ3ZELFdBQVcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFDbEQsd0RBQXdEO1FBQ3hELElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUN2QixXQUFXLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDakMsa0VBQWtFO1lBQ2xFLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxLQUFLLENBQUM7WUFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxFQUNGLFdBQVcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUNoQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDckMsQ0FBQyxDQUFDLENBQ0YsQ0FBQztJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1YsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU07UUFDTCxJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUNsQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNO1FBQ0wsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDeEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsUUFBUTtRQUNQLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO0lBQ3ZCLENBQUM7OEdBeEtXLGdCQUFnQixrQkFFbkIsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDO2tHQUZwQyxnQkFBZ0IsZ1lBYWQsb0JBQW9COztTQWJ0QixnQkFBZ0I7MkZBQWhCLGdCQUFnQjtrQkFUNUIsU0FBUzttQkFBQztvQkFDVixRQUFRLEVBQUUsb0JBQW9CO29CQUM5QixRQUFRLEVBQUUsa0JBQWtCO29CQUM1QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsSUFBSSxFQUFFO3dCQUNMLHdCQUF3QixFQUFFLE1BQU07d0JBQ2hDLE1BQU0sRUFBRSxJQUFJO3FCQUNaO2lCQUNEOzswQkFHRSxNQUFNOzJCQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQzs0RUFXYyxTQUFTO3NCQUF0RSxZQUFZO3VCQUFDLG9CQUFvQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFPckIsRUFBRTtzQkFBaEMsS0FBSzt1QkFBQyxrQkFBa0I7Z0JBV1osYUFBYTtzQkFBekIsS0FBSztnQkFZRyxRQUFRO3NCQUFoQixLQUFLO2dCQU9PLFNBQVM7c0JBQXJCLEtBQUs7Z0JBcUNJLElBQUk7c0JBQWIsTUFBTTtnQkFLRyxLQUFLO3NCQUFkLE1BQU07Z0JBT0csSUFBSTtzQkFBYixNQUFNO2dCQU1HLE1BQU07c0JBQWYsTUFBTTs7QUFrRVI7Ozs7OztHQU1HO0FBQ0gsTUFNYSxxQkFBcUI7SUE4Q2pDLFlBQVksTUFBMEI7UUFsQ3RDOzs7O1dBSUc7UUFDTSxrQkFBYSxHQUFHLElBQUksQ0FBQztRQUU5Qjs7OztXQUlHO1FBQ08sU0FBSSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFNUM7O1dBRUc7UUFDTyxVQUFLLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUU3Qzs7OztXQUlHO1FBQ08sU0FBSSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFNUM7OztXQUdHO1FBQ08sV0FBTSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFdEMsa0RBQTZDLEdBQUcsS0FBSyxDQUFDO1FBRzdELElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQztRQUNsQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUM7SUFDdkMsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE1BQU0sQ0FBQyxNQUFjO1FBQ3BCLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE1BQU0sQ0FBQyxNQUFjO1FBQ3BCLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxTQUFTO1FBQ1IsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2hCLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtnQkFDckIsa0ZBQWtGO2dCQUNsRixnQ0FBZ0M7Z0JBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUU7b0JBQ2pELElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO2lCQUMzQjthQUNEO2lCQUFNO2dCQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQzthQUM3QztTQUNEO0lBQ0YsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILFFBQVEsQ0FBQyxNQUFjO1FBQ3RCLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUM7SUFDbkMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNWLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsVUFBVSxDQUFDLE1BQWM7UUFDeEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNuQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDdkMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZ0JBQWdCLENBQUMsUUFBMEI7UUFDMUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDdEIsT0FBTyxJQUFJLENBQUM7U0FDWjtRQUVELDBFQUEwRTtRQUMxRSxnSEFBZ0g7UUFDaEgsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDakIsSUFBSSxDQUFDLElBQUksQ0FBQyw2Q0FBNkMsRUFBRTtnQkFDeEQsSUFBSSxDQUFDLDZDQUE2QyxHQUFHLElBQUksQ0FBQztnQkFDMUQsT0FBTyxJQUFJLENBQUM7YUFDWjtZQUNELE9BQU8sS0FBSyxDQUFDO1NBQ2I7UUFFRCw2REFBNkQ7UUFDN0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxRQUFRLEtBQUssSUFBSSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUM7UUFFN0UsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRU8sUUFBUSxDQUFDLE1BQWM7UUFDOUIsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxNQUFNLENBQUMsQ0FBQztJQUN4RCxDQUFDOzhHQXZKVyxxQkFBcUI7a0dBQXJCLHFCQUFxQixpVUFDaEIsZ0JBQWdCOztTQURyQixxQkFBcUI7MkZBQXJCLHFCQUFxQjtrQkFOakMsU0FBUzttQkFBQztvQkFDVixRQUFRLEVBQUUsZ0JBQWdCO29CQUMxQixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsUUFBUSxFQUFFLGNBQWM7b0JBQ3hCLElBQUksRUFBRSxFQUFFLG1CQUFtQixFQUFFLE1BQU0sRUFBRTtpQkFDckM7eUdBRW1FLE1BQU07c0JBQXhFLGVBQWU7dUJBQUMsZ0JBQWdCLEVBQUUsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFO2dCQUloRCxTQUFTO3NCQUFqQixLQUFLO2dCQUtHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBT0csYUFBYTtzQkFBckIsS0FBSztnQkFPSSxJQUFJO3NCQUFiLE1BQU07Z0JBS0csS0FBSztzQkFBZCxNQUFNO2dCQU9HLElBQUk7c0JBQWIsTUFBTTtnQkFNRyxNQUFNO3NCQUFmLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuXHRBZnRlckNvbnRlbnRDaGVja2VkLFxuXHRBZnRlckNvbnRlbnRJbml0LFxuXHRBcHBsaWNhdGlvblJlZixcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXG5cdENvbnRlbnRDaGlsZCxcblx0Q29udGVudENoaWxkcmVuLFxuXHREaXJlY3RpdmUsXG5cdEVsZW1lbnRSZWYsXG5cdEVtYmVkZGVkVmlld1JlZixcblx0RXZlbnRFbWl0dGVyLFxuXHRmb3J3YXJkUmVmLFxuXHRpbmplY3QsXG5cdEluamVjdCxcblx0SW5wdXQsXG5cdE9uRGVzdHJveSxcblx0T3V0cHV0LFxuXHRRdWVyeUxpc3QsXG5cdFRlbXBsYXRlUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTmdiQWNjb3JkaW9uQ29uZmlnIH0gZnJvbSAnLi9hY2NvcmRpb24tY29uZmlnJztcbmltcG9ydCB7IE5nYkNvbGxhcHNlIH0gZnJvbSAnLi4vY29sbGFwc2UvY29sbGFwc2UnO1xuaW1wb3J0IHsgaXNTdHJpbmcgfSBmcm9tICcuLi91dGlsL3V0aWwnO1xuXG5sZXQgbmV4dElkID0gMDtcblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0aGF0IHdyYXBzIHRoZSBjb250ZW50IG9mIGFuIGFjY29yZGlvbiBpdGVtJ3MgY29sbGFwc2libGUgYm9keS5cbiAqXG4gKiBUaGUgYWN0dWFsIGNvbnRlbnQgaXMgcHJvdmlkZWQgaW4gYSBjaGlsZCBgbmctdGVtcGxhdGVgIGVsZW1lbnQuXG4gKiBEZXBlbmRpbmcgb24gdGhlIHN0YXRlIG9mIHRoZSBhY2NvcmRpb24sIHRoZSB0ZW1wbGF0ZSB3aWxsIGJlIGVpdGhlciBpbnNlcnRlZCBvciByZW1vdmVkIGZyb20gdGhlIERPTS5cbiAqXG4gKiBAc2luY2UgMTQuMS4wXG4gKi9cbkBEaXJlY3RpdmUoe1xuXHRzZWxlY3RvcjogJ1tuZ2JBY2NvcmRpb25Cb2R5XScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGhvc3Q6IHsgJ1tjbGFzcy5hY2NvcmRpb24tYm9keV0nOiAndHJ1ZScgfSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiQWNjb3JkaW9uQm9keSBpbXBsZW1lbnRzIEFmdGVyQ29udGVudENoZWNrZWQsIE9uRGVzdHJveSB7XG5cdHByaXZhdGUgX2FwcFJlZiA9IGluamVjdChBcHBsaWNhdGlvblJlZik7XG5cdHByaXZhdGUgX2VsZW1lbnQgPSBpbmplY3QoRWxlbWVudFJlZjxIVE1MRWxlbWVudD4pLm5hdGl2ZUVsZW1lbnQ7XG5cdHByaXZhdGUgX2l0ZW0gPSBpbmplY3QoTmdiQWNjb3JkaW9uSXRlbSk7XG5cblx0cHJpdmF0ZSBfdmlld1JlZjogRW1iZWRkZWRWaWV3UmVmPGFueT4gfCBudWxsID0gbnVsbDtcblxuXHRAQ29udGVudENoaWxkKFRlbXBsYXRlUmVmLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIF9ib2R5VHBsOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG5cdG5nQWZ0ZXJDb250ZW50Q2hlY2tlZCgpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5fYm9keVRwbCkge1xuXHRcdFx0aWYgKHRoaXMuX2l0ZW0uYW5pbWF0aW5nQm9keUNvbGxhcHNlIHx8ICF0aGlzLl9pdGVtLmRlc3Ryb3lPbkhpZGUpIHtcblx0XHRcdFx0dGhpcy5fY3JlYXRlVmlld0lmTm90RXhpc3RzKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLl9kZXN0cm95Vmlld0lmRXhpc3RzKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0bmdPbkRlc3Ryb3koKTogdm9pZCB7XG5cdFx0dGhpcy5fZGVzdHJveVZpZXdJZkV4aXN0cygpO1xuXHR9XG5cblx0cHJpdmF0ZSBfZGVzdHJveVZpZXdJZkV4aXN0cygpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5fdmlld1JlZikge1xuXHRcdFx0dGhpcy5fYXBwUmVmLmRldGFjaFZpZXcodGhpcy5fdmlld1JlZik7XG5cdFx0XHR0aGlzLl92aWV3UmVmLmRlc3Ryb3koKTtcblx0XHRcdHRoaXMuX3ZpZXdSZWYgPSBudWxsO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgX2NyZWF0ZVZpZXdJZk5vdEV4aXN0cygpOiB2b2lkIHtcblx0XHRpZiAoIXRoaXMuX3ZpZXdSZWYpIHtcblx0XHRcdHRoaXMuX3ZpZXdSZWYgPSB0aGlzLl9ib2R5VHBsLmNyZWF0ZUVtYmVkZGVkVmlldyhudWxsKTtcblx0XHRcdHRoaXMuX3ZpZXdSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuXHRcdFx0dGhpcy5fYXBwUmVmLmF0dGFjaFZpZXcodGhpcy5fdmlld1JlZik7XG5cdFx0XHRmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fdmlld1JlZi5yb290Tm9kZXMpIHtcblx0XHRcdFx0dGhpcy5fZWxlbWVudC5hcHBlbmRDaGlsZChub2RlKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0aGF0IHdyYXBzIHRoZSBjb2xsYXBzaWJsZSBpdGVtJ3MgY29udGVudCBvZiB0aGUgYWNjb3JkaW9uLlxuICpcbiAqIEludGVybmFsbHkgaXQgcmV1c2VzIHRoZSBbYE5nYkNvbGxhcHNlYCBkaXJlY3RpdmVdKCMvY29tcG9uZW50cy9jb2xsYXBzZSlcbiAqXG4gKiBAc2luY2UgMTQuMS4wXG4gKi9cbkBEaXJlY3RpdmUoe1xuXHRleHBvcnRBczogJ25nYkFjY29yZGlvbkNvbGxhcHNlJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0c2VsZWN0b3I6ICdbbmdiQWNjb3JkaW9uQ29sbGFwc2VdJyxcblx0aG9zdDoge1xuXHRcdHJvbGU6ICdyZWdpb24nLFxuXHRcdCdbY2xhc3MuYWNjb3JkaW9uLWNvbGxhcHNlXSc6ICd0cnVlJyxcblx0XHQnW2lkXSc6ICdpdGVtLmNvbGxhcHNlSWQnLFxuXHRcdCdbYXR0ci5hcmlhLWxhYmVsbGVkYnldJzogJ2l0ZW0udG9nZ2xlSWQnLFxuXHR9LFxuXHRob3N0RGlyZWN0aXZlczogW1xuXHRcdHtcblx0XHRcdGRpcmVjdGl2ZTogTmdiQ29sbGFwc2UsXG5cdFx0fSxcblx0XSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiQWNjb3JkaW9uQ29sbGFwc2Uge1xuXHRjb25zdHJ1Y3Rvcihcblx0XHRASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gTmdiQWNjb3JkaW9uSXRlbSkpIHB1YmxpYyBpdGVtOiBOZ2JBY2NvcmRpb25JdGVtLFxuXHRcdHB1YmxpYyBuZ2JDb2xsYXBzZTogTmdiQ29sbGFwc2UsXG5cdCkge31cbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0byBwdXQgb24gYSB0b2dnbGluZyBlbGVtZW50IGluc2lkZSB0aGUgYWNjb3JkaW9uIGl0ZW0ncyBoZWFkZXIuXG4gKiBJdCB3aWxsIHJlZ2lzdGVyIGNsaWNrIGhhbmRsZXJzIHRoYXQgdG9nZ2xlIHRoZSBhc3NvY2lhdGVkIHBhbmVsIGFuZCB3aWxsIGhhbmRsZSBhY2Nlc3NpYmlsaXR5IGF0dHJpYnV0ZXMuXG4gKlxuICogVGhpcyBkaXJlY3RpdmUgaXMgdXNlZCBpbnRlcm5hbGx5IGJ5IHRoZSBbYE5nYkFjY29yZGlvbkJ1dHRvbmAgZGlyZWN0aXZlXSgjL2NvbXBvbmVudHMvYWNjb3JkaW9uL2FwaSNOZ2JBY2NvcmRpb25CdXR0b24pLlxuICpcbiAqIEBzaW5jZSAxNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnW25nYkFjY29yZGlvblRvZ2dsZV0nLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRob3N0OiB7XG5cdFx0J1tpZF0nOiAnaXRlbS50b2dnbGVJZCcsXG5cdFx0J1tjbGFzcy5jb2xsYXBzZWRdJzogJ2l0ZW0uY29sbGFwc2VkJyxcblx0XHQnW2F0dHIuYXJpYS1jb250cm9sc10nOiAnaXRlbS5jb2xsYXBzZUlkJyxcblx0XHQnW2F0dHIuYXJpYS1leHBhbmRlZF0nOiAnIWl0ZW0uY29sbGFwc2VkJyxcblx0XHQnKGNsaWNrKSc6ICchaXRlbS5kaXNhYmxlZCAmJiBhY2NvcmRpb24udG9nZ2xlKGl0ZW0uaWQpJyxcblx0fSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiQWNjb3JkaW9uVG9nZ2xlIHtcblx0Y29uc3RydWN0b3IoXG5cdFx0QEluamVjdChmb3J3YXJkUmVmKCgpID0+IE5nYkFjY29yZGlvbkl0ZW0pKSBwdWJsaWMgaXRlbTogTmdiQWNjb3JkaW9uSXRlbSxcblx0XHRASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gTmdiQWNjb3JkaW9uRGlyZWN0aXZlKSkgcHVibGljIGFjY29yZGlvbjogTmdiQWNjb3JkaW9uRGlyZWN0aXZlLFxuXHQpIHt9XG59XG5cbi8qKlxuICogQSBkaXJlY3RpdmUgdG8gcHV0IG9uIGEgYnV0dG9uIGVsZW1lbnQgaW5zaWRlIGFuIGFjY29yZGlvbiBpdGVtJ3MgaGVhZGVyLlxuICpcbiAqIElmIHlvdSB3YW50IGEgY3VzdG9tIG1hcmt1cCBmb3IgdGhlIGhlYWRlciwgeW91IGNhbiBhbHNvIHVzZSB0aGUgW2BOZ2JBY2NvcmRpb25Ub2dnbGVgIGRpcmVjdGl2ZV0oIy9jb21wb25lbnRzL2FjY29yZGlvbi9hcGkjTmdiQWNjb3JkaW9uVG9nZ2xlKS5cbiAqXG4gKiBAc2luY2UgMTQuMS4wXG4gKi9cbkBEaXJlY3RpdmUoe1xuXHRzZWxlY3RvcjogJ2J1dHRvbltuZ2JBY2NvcmRpb25CdXR0b25dJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0aG9zdDoge1xuXHRcdCdbZGlzYWJsZWRdJzogJ2l0ZW0uZGlzYWJsZWQnLFxuXHRcdCdbY2xhc3MuYWNjb3JkaW9uLWJ1dHRvbl0nOiAndHJ1ZScsXG5cdFx0dHlwZTogJ2J1dHRvbicsXG5cdH0sXG5cdGhvc3REaXJlY3RpdmVzOiBbXG5cdFx0e1xuXHRcdFx0ZGlyZWN0aXZlOiBOZ2JBY2NvcmRpb25Ub2dnbGUsXG5cdFx0fSxcblx0XSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiQWNjb3JkaW9uQnV0dG9uIHtcblx0Y29uc3RydWN0b3IoQEluamVjdChmb3J3YXJkUmVmKCgpID0+IE5nYkFjY29yZGlvbkl0ZW0pKSBwdWJsaWMgaXRlbTogTmdiQWNjb3JkaW9uSXRlbSkge31cbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0aGF0IHdyYXBzIGFuIGFjY29yZGlvbiBpdGVtJ3MgaGVhZGVyLlxuICpcbiAqIEBzaW5jZSAxNC4xLjBcbiAqL1xuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnW25nYkFjY29yZGlvbkhlYWRlcl0nLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRob3N0OiB7XG5cdFx0cm9sZTogJ2hlYWRpbmcnLFxuXHRcdCdbY2xhc3MuYWNjb3JkaW9uLWhlYWRlcl0nOiAndHJ1ZScsXG5cdFx0J1tjbGFzcy5jb2xsYXBzZWRdJzogJ2l0ZW0uY29sbGFwc2VkJyxcblx0fSxcbn0pXG5leHBvcnQgY2xhc3MgTmdiQWNjb3JkaW9uSGVhZGVyIHtcblx0Y29uc3RydWN0b3IoQEluamVjdChmb3J3YXJkUmVmKCgpID0+IE5nYkFjY29yZGlvbkl0ZW0pKSBwdWJsaWMgaXRlbTogTmdiQWNjb3JkaW9uSXRlbSkge31cbn1cblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0aGF0IHdyYXBzIGFuIGFjY29yZGlvbiBpdGVtOiBhIHRvZ2dsZWFibGUgaGVhZGVyICsgYm9keSB0aGF0IGNvbGxhcHNlcy5cbiAqXG4gKiBZb3UgY2FuIGdldCBob2xkIG9mIHRoZSBgTmdiQWNjb3JkaW9uSXRlbWAgaW5zdGFuY2UgaW4gdGhlIHRlbXBsYXRlIHdpdGggYCNpdGVtPVwibmdiQWNjb3JkaW9uSXRlbVwiYC5cbiAqIEl0IGFsbG93cyB0byBjaGVjayBpZiB0aGUgaXRlbSBpcyBjb2xsYXBzZWQgb3Igbm90LCB0b2dnbGUgdGhlIGNvbGxhcHNlIHN0YXRlLCBldGMuXG4gKlxuICogRXZlcnkgYWNjb3JkaW9uIGl0ZW0gaGFzIGEgc3RyaW5nIElEIHRoYXQgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgaW4gdGhlIGBuZ2ItYWNjb3JkaW9uLWl0ZW0tWFhgIGZvcm1hdCwgdW5sZXNzIHByb3ZpZGVkIGV4cGxpY2l0bHkuXG4gKlxuICogQHNpbmNlIDE0LjEuMFxuICovXG5ARGlyZWN0aXZlKHtcblx0c2VsZWN0b3I6ICdbbmdiQWNjb3JkaW9uSXRlbV0nLFxuXHRleHBvcnRBczogJ25nYkFjY29yZGlvbkl0ZW0nLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRob3N0OiB7XG5cdFx0J1tjbGFzcy5hY2NvcmRpb24taXRlbV0nOiAndHJ1ZScsXG5cdFx0J1tpZF0nOiAnaWQnLFxuXHR9LFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JBY2NvcmRpb25JdGVtIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95IHtcblx0Y29uc3RydWN0b3IoXG5cdFx0QEluamVjdChmb3J3YXJkUmVmKCgpID0+IE5nYkFjY29yZGlvbkRpcmVjdGl2ZSkpIHByaXZhdGUgX2FjY29yZGlvbjogTmdiQWNjb3JkaW9uRGlyZWN0aXZlLFxuXHRcdHByaXZhdGUgX2NkOiBDaGFuZ2VEZXRlY3RvclJlZixcblx0KSB7fVxuXG5cdHByaXZhdGUgX3N1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG5cdHByaXZhdGUgX2NvbGxhcHNlZCA9IHRydWU7XG5cdHByaXZhdGUgX2lkID0gYG5nYi1hY2NvcmRpb24taXRlbS0ke25leHRJZCsrfWA7XG5cdHByaXZhdGUgX2Rlc3Ryb3lPbkhpZGU6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG5cblx0YW5pbWF0aW5nQm9keUNvbGxhcHNlID0gZmFsc2U7XG5cblx0QENvbnRlbnRDaGlsZChOZ2JBY2NvcmRpb25Db2xsYXBzZSwgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSBfY29sbGFwc2U6IE5nYkFjY29yZGlvbkNvbGxhcHNlO1xuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBjdXN0b20gSUQgb2YgdGhlIGFjY29yZGlvbiBpdGVtLiBJdCBtdXN0IGJlIHVuaXF1ZSBmb3IgdGhlIGRvY3VtZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0gaWQgVGhlIElEIG9mIHRoZSBhY2NvcmRpb24gaXRlbSwgbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmdcblx0ICovXG5cdEBJbnB1dCgnbmdiQWNjb3JkaW9uSXRlbScpIHNldCBpZChpZDogc3RyaW5nKSB7XG5cdFx0aWYgKGlzU3RyaW5nKGlkKSAmJiBpZCAhPT0gJycpIHtcblx0XHRcdHRoaXMuX2lkID0gaWQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIElmIGB0cnVlYCwgdGhlIGNvbnRlbnQgb2YgdGhlIGFjY29yZGlvbiBpdGVtJ3MgYm9keSB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgRE9NLiBJdCB3aWxsIGJlIGp1c3QgaGlkZGVuIG90aGVyd2lzZS5cblx0ICpcblx0ICogVGhpcyBwcm9wZXJ0eSBjYW4gYWxzbyBiZSBzZXQgdXAgb24gdGhlIHBhcmVudCBbYE5nYkFjY29yZGlvbmAgZGlyZWN0aXZlXSgjL2NvbXBvbmVudHMvYWNjb3JkaW9uL2FwaSNOZ2JBY2NvcmRpb25EaXJlY3RpdmUpLlxuXHQgKi9cblx0QElucHV0KCkgc2V0IGRlc3Ryb3lPbkhpZGUoZGVzdHJveU9uSGlkZTogYm9vbGVhbikge1xuXHRcdHRoaXMuX2Rlc3Ryb3lPbkhpZGUgPSBkZXN0cm95T25IaWRlO1xuXHR9XG5cblx0Z2V0IGRlc3Ryb3lPbkhpZGUoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX2Rlc3Ryb3lPbkhpZGUgPT09IHVuZGVmaW5lZCA/IHRoaXMuX2FjY29yZGlvbi5kZXN0cm95T25IaWRlIDogdGhpcy5fZGVzdHJveU9uSGlkZSE7XG5cdH1cblxuXHQvKipcblx0ICogSWYgYHRydWVgLCB0aGUgYWNjb3JkaW9uIGl0ZW0gd2lsbCBiZSBkaXNhYmxlZC5cblx0ICogSXQgd29uJ3QgcmVhY3QgdG8gdXNlcidzIGNsaWNrcywgYnV0IHN0aWxsIHdpbGwgYmUgdG9nZ2VsYWJsZSBwcm9ncmFtbWF0aWNhbGx5LlxuXHQgKi9cblx0QElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcblxuXHQvKipcblx0ICpcdElmIGB0cnVlYCwgdGhlIGFjY29yZGlvbiBpdGVtIHdpbGwgYmUgY29sbGFwc2VkLiBPdGhlcndpc2UsIGl0IHdpbGwgYmUgZXhwYW5kZWQuXG5cdCAqXG5cdCAqIEBwYXJhbSBjb2xsYXBzZWQgTmV3IHN0YXRlIG9mIHRoZSBhY2NvcmRpb24gaXRlbS5cblx0ICovXG5cdEBJbnB1dCgpIHNldCBjb2xsYXBzZWQoY29sbGFwc2VkOiBib29sZWFuKSB7XG5cdFx0aWYgKHRoaXMuY29sbGFwc2VkICE9PSBjb2xsYXBzZWQpIHtcblx0XHRcdC8vIGNoZWNraW5nIGlmIGFjY29yZGlvbiBhbGxvd3MgdG8gZXhwYW5kIHRoZSBwYW5lbCBpbiByZXNwZWN0IHRvICdjbG9zZU90aGVycycgZmxhZ1xuXHRcdFx0aWYgKHRoaXMuY29sbGFwc2VkICYmICF0aGlzLl9hY2NvcmRpb24uX2Vuc3VyZUNhbkV4cGFuZCh0aGlzKSkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIGNoYW5naW5nIHRoZSBjb2xsYXBzZWQgc3RhdGVcblx0XHRcdHRoaXMuX2NvbGxhcHNlZCA9IGNvbGxhcHNlZDtcblxuXHRcdFx0dGhpcy5fY2QubWFya0ZvckNoZWNrKCk7IC8vIG5lZWQgaWYgdGhlIGFjY29yZGlvbiBpcyB1c2VkIGluc2lkZSBhIGNvbXBvbmVudCBoYXZpbmcgT25QdXNoIGNoYW5nZSBkZXRlY3Rpb24gc3RyYXRlZ3lcblx0XHRcdC8vIHdlIG5lZWQgZm9yY2UgQ0QgdG8gZ2V0IHRlbXBsYXRlIGludG8gRE9NIGJlZm9yZSBzdGFydGluZyBhbmltYXRpb24gdG8gY2FsY3VsYXRlIGl0cyBoZWlnaHQgY29ycmVjdGx5XG5cdFx0XHRpZiAoIXRoaXMuY29sbGFwc2VkKSB7XG5cdFx0XHRcdHRoaXMuYW5pbWF0aW5nQm9keUNvbGxhcHNlID0gdHJ1ZTtcblx0XHRcdFx0dGhpcy5fY2QuZGV0ZWN0Q2hhbmdlcygpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBmaXJpbmcgZXZlbnRzIGJlZm9yZSBzdGFydGluZyBhbmltYXRpb25zXG5cdFx0XHRpZiAoIXRoaXMuY29sbGFwc2VkKSB7XG5cdFx0XHRcdHRoaXMuc2hvdy5lbWl0KCk7XG5cdFx0XHRcdHRoaXMuX2FjY29yZGlvbi5zaG93LmVtaXQodGhpcy5pZCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmhpZGUuZW1pdCgpO1xuXHRcdFx0XHR0aGlzLl9hY2NvcmRpb24uaGlkZS5lbWl0KHRoaXMuaWQpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB3ZSBhbHNvIG5lZWQgdG8gbWFrZSBzdXJlICdhbmltYXRpb24nIGZsYWcgaXMgdXAtdG8tIGRhdGVcblx0XHRcdHRoaXMuX2NvbGxhcHNlLm5nYkNvbGxhcHNlLmFuaW1hdGlvbiA9IHRoaXMuX2FjY29yZGlvbi5hbmltYXRpb247XG5cdFx0XHR0aGlzLl9jb2xsYXBzZS5uZ2JDb2xsYXBzZS5jb2xsYXBzZWQgPSB0aGlzLmNvbGxhcHNlZDtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogRXZlbnQgZW1pdHRlZCBiZWZvcmUgdGhlIGV4cGFuZGluZyBhbmltYXRpb24gc3RhcnRzLiBJdCBoYXMgbm8gcGF5bG9hZC5cblx0ICpcblx0ICogQHNpbmNlIDE1LjEuMFxuXHQgKi9cblx0QE91dHB1dCgpIHNob3cgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cblx0LyoqXG5cdCAqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgZXhwYW5kaW5nIGFuaW1hdGlvbiBpcyBmaW5pc2hlZC4gSXQgaGFzIG5vIHBheWxvYWQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgc2hvd24gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cblx0LyoqXG5cdCAqIEV2ZW50IGVtaXR0ZWQgYmVmb3JlIHRoZSBjb2xsYXBzaW5nIGFuaW1hdGlvbiBzdGFydHMuIEl0IGhhcyBubyBwYXlsb2FkLlxuXHQgKlxuXHQgKiBAc2luY2UgMTUuMS4wXG5cdCAqL1xuXHRAT3V0cHV0KCkgaGlkZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuXHQvKipcblx0ICogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBjb2xsYXBzaW5nIGFuaW1hdGlvbiBpcyBmaW5pc2hlZCBhbmQgYmVmb3JlIHRoZSBjb250ZW50IGlzIHJlbW92ZWQgZnJvbSBET00uXG5cdCAqIEl0IGhhcyBubyBwYXlsb2FkLlxuXHQgKi9cblx0QE91dHB1dCgpIGhpZGRlbiA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuXHRnZXQgY29sbGFwc2VkKCkge1xuXHRcdHJldHVybiB0aGlzLl9jb2xsYXBzZWQ7XG5cdH1cblxuXHRnZXQgaWQoKSB7XG5cdFx0cmV0dXJuIGA