UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

453 lines 67.2 kB
import { Component, EventEmitter, HostBinding, HostListener, Injector, Input, Output } from '@angular/core'; import { KeyCode } from '@microsoft/windows-admin-center-sdk/core/data/accessibility-manager'; import { LogLevel } from '@microsoft/windows-admin-center-sdk/core/diagnostics/log-level'; import { CoreBaseComponent } from '../common/base.component'; import * as i0 from "@angular/core"; /** * Resizer component */ export class ResizerComponent extends CoreBaseComponent { /** * Initializes a new instance of the @see ResizerComponent class. * @param injector The angular injection service. required by @see SmeInjectableBase decorator in the @see BaseComponent class */ constructor(injector) { super(injector); this.isResizing = false; this._orientation = 'bottom'; /** * It indicates whether to show the half transparent cover ont he resizer host. * In some case (like Data Table column resizer), the cover is not needed since data table would handle the UI of resizing by itself. */ this.showResizerCover = true; /** * It indicates whether to let the screen reader to read this resizer control. * In some case (like Data Table column resizer), we don't want the screen reader to read it as part of the column header. */ this.visibleToScreenReader = true; /** * Determines if the resizer is accessible to the screen readers */ this.focusable = false; /** * It's fired then the resizing is finished. */ this.resized = new EventEmitter(); /** * It's fired then the resizing is happening. */ this.resizing = new EventEmitter(); } /** * The source name to use for logging */ get logSourceName() { return 'ResizerComponent'; } /** * It defines the orientation of the element which holds the resizer in the resizing layout. */ set orientation(newOrientation) { if (this._orientation !== newOrientation) { this._orientation = newOrientation; if (this.resizerHostBodyElement?.parentNode) { this.resizerHostBodyElement.parentNode.removeChild(this.resizerHostBodyElement); } if (this.resizerIndicatorElement?.parentNode) { this.resizerIndicatorElement.parentNode.removeChild(this.resizerIndicatorElement); } // To support orientation changes by window size changes // Reset all the parameters and re-build the resizer elements setTimeout(() => { this.resizerHostElement = undefined; this.resizerHostBodyElement = undefined; this.resizerIndicatorElement = undefined; this.offsetX = undefined; this.offsetY = undefined; this.originalX = undefined; this.originalY = undefined; this.ngOnInit(); }); } } get orientation() { return this._orientation; } /** * Indicates that the resizer should be aligned to the top */ get alignTop() { return this.isOriented('bottom', 'left', 'right'); } /** * Indicates that the resizer should be aligned to the bottom */ get alignBottom() { return this.isOriented('top', 'left', 'right'); } /** * Indicates that the resizer should be aligned to the left */ get alignLeft() { return this.isOriented('top', 'bottom', 'right'); } /** * Indicates that the resizer should be aligned to the right */ get alignRight() { return this.isOriented('top', 'bottom', 'left'); } /** * Indicates that the resizer moves vertically */ get isVertical() { return this.isOriented('top', 'bottom'); } /** * Indicates that the resizer moves horizontally */ get isHorizontal() { return this.isOriented('left', 'right'); } /** * Describes the orientation for aria users. */ get ariaOrientation() { return this.isVertical ? 'vertical' : 'horizontal'; } /** * Defines the cursor style the resizer should have */ get cursor() { switch (this.orientation) { case 'top': return 'n-resize'; case 'bottom': return 's-resize'; case 'left': return 'e-resize'; case 'right': return 'w-resize'; } } /** * Angular lifecycle hook. */ ngOnInit() { super.ngOnInit(); // This is a special implementation for Microsoft Edge. // In Microsoft Edge, if the resizer div is transparent and it's overlay on the scrollbar, // the mouse events will be messed up. // So we need to apply a very transparent but not 100% transparent color to it. // It won't impact the look and feel, when the browser renders this special color, // basically no color will be actually rendered. this.hostElement.nativeElement.style.background = 'rgba(255,255,255,0.003)'; if (this.visibleToScreenReader) { this.setAttribute('role', 'separator'); this.setAttribute('aria-label', this.strings.MsftSmeShell.Angular.Resizer.Splitter); } this.setAttribute('tabindex', this.focusable ? '0' : '-1'); this.setAttribute('aria-hidden', this.focusable ? 'false' : 'true'); if (!this.resizerHostSelector) { this.log('resizerHostSelector is not set.', LogLevel.Warning); } else { let currentParentElement = this.hostElement.nativeElement.parentElement; while (!this.resizerHostElement && currentParentElement) { // Deal with nested html tag, for instance, sme-split-view contains of nested sme-split-view // Without this if logic, the resizer will be attached to the wrong location because of the querySelector function. if (currentParentElement.tagName.toLowerCase() === this.resizerHostSelector.toLowerCase()) { this.resizerHostElement = currentParentElement; break; } else { this.resizerHostElement = currentParentElement.querySelector(this.resizerHostSelector); currentParentElement = currentParentElement.parentElement; } } this.resizerHostBodyElement = document.createElement('DIV'); this.resizerHostBodyElement.setAttribute('role', 'presentation'); this.resizerHostBodyElement.classList.add('sme-resizer-host-body'); this.resizerHostBodyElement.classList.add('sme-layout-absolute'); this.resizerHostBodyElement.classList.add('sme-position-inset-none'); this.resizerHostBodyElement.classList.add('sme-layer-above'); this.resizerHostBodyElement.classList.add('sme-layout-none'); this.resizerIndicatorElement = document.createElement('DIV'); this.resizerIndicatorElement.classList.add('sme-resizer-indicator'); this.resizerIndicatorElement.classList.add('sme-layout-none'); this.resizerIndicatorElement.classList.add('sme-layout-absolute'); this.resizerIndicatorElement.classList.add('sme-layer-over'); if (this.showResizerCover) { this.resizerHostBodyElement.classList.add('sme-background-color-base'); this.resizerHostBodyElement.style.opacity = '0.5'; this.resizerIndicatorElement.classList.add('sme-background-color-base-80'); } switch (this.orientation) { case 'top': this.resizerHostBodyElement.style.cursor = 'n-resize'; this.resizerIndicatorElement.classList.add('sme-position-stretch-h'); this.resizerIndicatorElement.classList.add('sme-height-xxs'); break; case 'bottom': this.resizerHostBodyElement.style.cursor = 's-resize'; this.resizerIndicatorElement.classList.add('sme-position-stretch-h'); this.resizerIndicatorElement.classList.add('sme-height-xxs'); break; case 'left': this.resizerHostBodyElement.style.cursor = 'e-resize'; this.resizerIndicatorElement.classList.add('sme-width-xxs'); this.resizerIndicatorElement.classList.add('sme-position-stretch-v'); break; case 'right': this.resizerHostBodyElement.style.cursor = 'w-resize'; this.resizerIndicatorElement.classList.add('sme-width-xxs'); this.resizerIndicatorElement.classList.add('sme-position-stretch-v'); break; } let foundExistingResizerHostBody = false; if (this.resizerHostElement && this.resizerHostElement.childElementCount) { for (let i = 0; i < this.resizerHostElement.children.length; i++) { if (this.resizerHostElement.children[i].classList.contains('sme-resizer-host-body')) { // remove the resizer host element if it doesn't contain resizer indicator and re-create. // this issue mostly due to component not initialized before the resizer was initialized. if (!this.resizerHostBodyElement.querySelector('.sme-resizer-indicator')) { this.resizerHostElement.children[i].parentNode.removeChild(this.resizerHostElement.children[i]); } else { foundExistingResizerHostBody = true; this.resizerHostBodyElement = this.resizerHostElement.children[i]; this.resizerIndicatorElement = this.resizerHostBodyElement.querySelector('.sme-resizer-indicator'); break; } } } } if (!foundExistingResizerHostBody) { this.resizerHostElement.appendChild(this.resizerHostBodyElement); this.resizerHostBodyElement.appendChild(this.resizerIndicatorElement); } this.onStartingResizeEventHandler = this.onStartingResizing.bind(this); this.onResizingEventHandler = this.onResizing.bind(this); this.onFinishingResizeEventHandler = this.onFinishingResizing.bind(this); } } /** * It handles the event when mouse down happens on the resizer. */ onResizeElementMouseDown() { this.isResizing = true; document.body.addEventListener('mousedown', this.onStartingResizeEventHandler); document.body.addEventListener('mousemove', this.onResizingEventHandler); document.body.addEventListener('mouseup', this.onFinishingResizeEventHandler); } onResizeElementKeyDown($event) { if (this.isHorizontal) { switch ($event.keyCode) { case KeyCode.LeftArrow: this.resized.emit({ x: -ResizerComponent.keyboardDelta, y: 0 }); break; case KeyCode.RightArrow: this.resized.emit({ x: ResizerComponent.keyboardDelta, y: 0 }); break; } } else if (this.isVertical) { switch ($event.keyCode) { case KeyCode.UpArrow: this.resized.emit({ x: 0, y: -ResizerComponent.keyboardDelta }); break; case KeyCode.DownArrow: this.resized.emit({ x: 0, y: ResizerComponent.keyboardDelta }); break; } } } startResize(offsetX, offsetY) { this.isResizing = true; this.offsetX = offsetX; this.offsetY = offsetY; document.body.style.userSelect = 'none'; this.resizerHostBodyElement.classList.remove('sme-layout-none'); this.resizerIndicatorElement.classList.remove('sme-layout-none'); const resizerHostRect = this.resizerHostBodyElement.getBoundingClientRect(); const resizerElementRect = this.hostElement.nativeElement.getBoundingClientRect(); this.originalX = resizerElementRect.left - resizerHostRect.left; this.originalY = resizerElementRect.top - resizerHostRect.top; } onStartingResizing(event) { if (this.isResizing) { this.startResize(event.clientX, event.clientY); this.onResizing(event); event.preventDefault(); } } onResizing(event) { if (this.isResizing) { const resizerHostRect = this.resizerHostBodyElement.getBoundingClientRect(); let indicatorX; let indicatorY; let newX; let newY; switch (this.orientation) { case 'top': newY = this.hostElement.nativeElement.offsetTop + event.clientY - this.offsetY; this.offsetY = event.clientY; this.hostElement.nativeElement.style.top = newY + 'px'; indicatorY = resizerHostRect.top === 0 ? this.hostElement.nativeElement.parentElement.offsetTop + newY : this.hostElement.nativeElement.parentElement.getBoundingClientRect().top - resizerHostRect.top + newY; this.resizerIndicatorElement.style.top = indicatorY + 'px'; break; case 'bottom': newY = this.hostElement.nativeElement.offsetTop + event.clientY - this.offsetY; this.offsetY = event.clientY; this.hostElement.nativeElement.style.top = newY + 'px'; indicatorY = this.originalY + newY; this.resizerIndicatorElement.style.top = indicatorY + 'px'; break; case 'left': newX = this.hostElement.nativeElement.offsetLeft + event.clientX - this.offsetX; this.offsetX = event.clientX; this.hostElement.nativeElement.style.left = newX + 'px'; indicatorX = resizerHostRect.left === 0 ? this.hostElement.nativeElement.parentElement.offsetLeft + newX : this.hostElement.nativeElement.parentElement.getBoundingClientRect().left - resizerHostRect.left + newX; this.resizerIndicatorElement.style.left = indicatorX + 'px'; break; case 'right': newX = this.hostElement.nativeElement.offsetLeft + event.clientX - this.offsetX; this.offsetX = event.clientX; this.hostElement.nativeElement.style.left = newX + 'px'; indicatorX = this.originalX + newX; this.resizerIndicatorElement.style.left = indicatorX + 'px'; break; } this.resizing.emit({ x: indicatorX, y: indicatorY }); } } onFinishingResizing() { if (this.isResizing) { document.body.removeEventListener('mousedown', this.onStartingResizeEventHandler); document.body.removeEventListener('mousemove', this.onResizingEventHandler); document.body.removeEventListener('mouseup', this.onFinishingResizeEventHandler); this.isResizing = false; let deltaX; let deltaY; const resizerHostRect = this.resizerHostBodyElement.getBoundingClientRect(); const resizerElementRect = this.hostElement.nativeElement.getBoundingClientRect(); const newX = resizerElementRect.left - resizerHostRect.left; const newY = resizerElementRect.top - resizerHostRect.top; switch (this.orientation) { case 'left': deltaX = newX - this.originalX; deltaY = 0; break; case 'right': deltaX = newX - this.originalX; deltaY = 0; break; case 'top': deltaX = 0; deltaY = newY - this.originalY; break; case 'bottom': deltaX = 0; deltaY = newY - this.originalY; break; } this.resized.emit({ x: deltaX, y: deltaY }); this.resizerHostBodyElement.classList.add('sme-layout-none'); document.body.style.userSelect = 'auto'; this.resizerHostBodyElement.classList.add('sme-layout-none'); this.resizerIndicatorElement.classList.add('sme-layout-none'); this.hostElement.nativeElement.style.left = ''; this.hostElement.nativeElement.style.top = ''; } } isOriented(...orientations) { return orientations.some(o => o === this.orientation); } getInitialHostClasses() { return super.getInitialHostClasses() .concat([ 'sme-layout-absolute', 'sme-layer-over' ]); } } ResizerComponent.keyboardDelta = 20; /** @nocollapse */ ResizerComponent.ɵfac = function ResizerComponent_Factory(t) { return new (t || ResizerComponent)(i0.ɵɵdirectiveInject(i0.Injector)); }; /** @nocollapse */ ResizerComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: ResizerComponent, selectors: [["sme-resizer"]], hostVars: 15, hostBindings: function ResizerComponent_HostBindings(rf, ctx) { if (rf & 1) { i0.ɵɵlistener("mousedown", function ResizerComponent_mousedown_HostBindingHandler() { return ctx.onResizeElementMouseDown(); })("keydown", function ResizerComponent_keydown_HostBindingHandler($event) { return ctx.onResizeElementKeyDown($event); }); } if (rf & 2) { i0.ɵɵattribute("aria-orientation", ctx.ariaOrientation); i0.ɵɵstyleProp("cursor", ctx.cursor); i0.ɵɵclassProp("sme-position-top-none", ctx.alignTop)("sme-position-bottom-none", ctx.alignBottom)("sme-position-left-none", ctx.alignLeft)("sme-position-right-none", ctx.alignRight)("sme-height-xxs", ctx.isVertical)("sme-width-xxs", ctx.isHorizontal); } }, inputs: { resizerHostSelector: "resizerHostSelector", showResizerCover: "showResizerCover", visibleToScreenReader: "visibleToScreenReader", orientation: "orientation", focusable: "focusable" }, outputs: { resized: "resized", resizing: "resizing" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 0, vars: 0, template: function ResizerComponent_Template(rf, ctx) { }, encapsulation: 2 }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ResizerComponent, [{ type: Component, args: [{ selector: 'sme-resizer', template: '' }] }], function () { return [{ type: i0.Injector }]; }, { resizerHostSelector: [{ type: Input }], showResizerCover: [{ type: Input }], visibleToScreenReader: [{ type: Input }], orientation: [{ type: Input }], focusable: [{ type: Input }], resized: [{ type: Output }], resizing: [{ type: Output }], alignTop: [{ type: HostBinding, args: ['class.sme-position-top-none'] }], alignBottom: [{ type: HostBinding, args: ['class.sme-position-bottom-none'] }], alignLeft: [{ type: HostBinding, args: ['class.sme-position-left-none'] }], alignRight: [{ type: HostBinding, args: ['class.sme-position-right-none'] }], isVertical: [{ type: HostBinding, args: ['class.sme-height-xxs'] }], isHorizontal: [{ type: HostBinding, args: ['class.sme-width-xxs'] }], ariaOrientation: [{ type: HostBinding, args: ['attr.aria-orientation'] }], cursor: [{ type: HostBinding, args: ['style.cursor'] }], onResizeElementMouseDown: [{ type: HostListener, args: ['mousedown'] }], onResizeElementKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9yZXNpemVyL3Jlc2l6ZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDcEgsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFFQUFxRSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnRUFBZ0UsQ0FBQztBQUMxRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7QUFFN0Q7O0dBRUc7QUFLSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsaUJBQWlCO0lBMEtuRDs7O09BR0c7SUFDSCxZQUFZLFFBQWtCO1FBQzFCLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQXBLWixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBUW5CLGlCQUFZLEdBQUcsUUFBUSxDQUFDO1FBWWhDOzs7V0FHRztRQUVJLHFCQUFnQixHQUFHLElBQUksQ0FBQztRQUUvQjs7O1dBR0c7UUFFSSwwQkFBcUIsR0FBRyxJQUFJLENBQUM7UUFvQ3BDOztXQUVHO1FBRUksY0FBUyxHQUFHLEtBQUssQ0FBQztRQUV6Qjs7V0FFRztRQUVJLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBNEIsQ0FBQztRQUU5RDs7V0FFRztRQUVJLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBNEIsQ0FBQztJQWlGL0QsQ0FBQztJQTlLRDs7T0FFRztJQUNILElBQWMsYUFBYTtRQUN2QixPQUFPLGtCQUFrQixDQUFDO0lBQzlCLENBQUM7SUFzQ0Q7O09BRUc7SUFDSCxJQUNXLFdBQVcsQ0FBQyxjQUFzQjtRQUN6QyxJQUFJLElBQUksQ0FBQyxZQUFZLEtBQUssY0FBYyxFQUFFO1lBQ3RDLElBQUksQ0FBQyxZQUFZLEdBQUcsY0FBYyxDQUFDO1lBRW5DLElBQUksSUFBSSxDQUFDLHNCQUFzQixFQUFFLFVBQVUsRUFBRTtnQkFDekMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUM7YUFDbkY7WUFFRCxJQUFJLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxVQUFVLEVBQUU7Z0JBQzFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO2FBQ3JGO1lBQ0Qsd0RBQXdEO1lBQ3hELDZEQUE2RDtZQUM3RCxVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUNaLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxTQUFTLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxTQUFTLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxTQUFTLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDO2dCQUN6QixJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQztnQkFDekIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO2dCQUMzQixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEIsQ0FBQyxDQUFDLENBQUM7U0FDTjtJQUNMLENBQUM7SUFFRCxJQUFXLFdBQVc7UUFDbEIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzdCLENBQUM7SUFvQkQ7O09BRUc7SUFDSCxJQUNXLFFBQVE7UUFDZixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUNXLFdBQVc7UUFDbEIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFDVyxTQUFTO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRDs7T0FFRztJQUNILElBQ1csVUFBVTtRQUNqQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUNXLFVBQVU7UUFDakIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUNXLFlBQVk7UUFDbkIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUNXLGVBQWU7UUFDdEIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQztJQUN2RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUNXLE1BQU07UUFDYixRQUFRLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDdEIsS0FBSyxLQUFLO2dCQUNOLE9BQU8sVUFBVSxDQUFDO1lBQ3RCLEtBQUssUUFBUTtnQkFDVCxPQUFPLFVBQVUsQ0FBQztZQUN0QixLQUFLLE1BQU07Z0JBQ1AsT0FBTyxVQUFVLENBQUM7WUFDdEIsS0FBSyxPQUFPO2dCQUNSLE9BQU8sVUFBVSxDQUFDO1NBQ3pCO0lBQ0wsQ0FBQztJQVVEOztPQUVHO0lBQ0ksUUFBUTtRQUNYLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUVqQix1REFBdUQ7UUFDdkQsMEZBQTBGO1FBQzFGLHNDQUFzQztRQUN0QywrRUFBK0U7UUFDL0Usa0ZBQWtGO1FBQ2xGLGdEQUFnRDtRQUNoRCxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLHlCQUF5QixDQUFDO1FBRTVFLElBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFO1lBQzVCLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDdkY7UUFFRCxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFcEUsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRTtZQUMzQixJQUFJLENBQUMsR0FBRyxDQUFDLGlDQUFpQyxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNqRTthQUFNO1lBQ0gsSUFBSSxvQkFBb0IsR0FBaUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFjLENBQUMsYUFBYSxDQUFDO1lBQ3ZGLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLElBQUksb0JBQW9CLEVBQUU7Z0JBQ3JELDRGQUE0RjtnQkFDNUYsbUhBQW1IO2dCQUNuSCxJQUFJLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsS0FBSyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLEVBQUU7b0JBQ3ZGLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxvQkFBb0IsQ0FBQztvQkFDL0MsTUFBTTtpQkFDVDtxQkFBTTtvQkFDSCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsb0JBQW9CLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO29CQUN2RixvQkFBb0IsR0FBRyxvQkFBb0IsQ0FBQyxhQUFhLENBQUM7aUJBQzdEO2FBQ0o7WUFFRCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1RCxJQUFJLENBQUMsc0JBQXNCLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQztZQUNqRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1lBQ25FLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDakUsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMseUJBQXlCLENBQUMsQ0FBQztZQUNyRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzdELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFFN0QsSUFBSSxDQUFDLHVCQUF1QixHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDN0QsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQztZQUNwRSxJQUFJLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzlELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDbEUsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUU3RCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtnQkFDdkIsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsMkJBQTJCLENBQUMsQ0FBQztnQkFDdkUsSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO2dCQUNsRCxJQUFJLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO2FBQzlFO1lBRUQsUUFBUSxJQUFJLENBQUMsV0FBVyxFQUFFO2dCQUN0QixLQUFLLEtBQUs7b0JBQ04sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDO29CQUN0RCxJQUFJLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO29CQUNyRSxJQUFJLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO29CQUM3RCxNQUFNO2dCQUNWLEtBQUssUUFBUTtvQkFDVCxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUM7b0JBQ3RELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLENBQUM7b0JBQ3JFLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7b0JBQzdELE1BQU07Z0JBQ1YsS0FBSyxNQUFNO29CQUNQLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQztvQkFDdEQsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7b0JBQzVELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLENBQUM7b0JBQ3JFLE1BQU07Z0JBQ1YsS0FBSyxPQUFPO29CQUNSLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQztvQkFDdEQsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7b0JBQzVELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLENBQUM7b0JBQ3JFLE1BQU07YUFDYjtZQUVELElBQUksNEJBQTRCLEdBQUcsS0FBSyxDQUFDO1lBQ3pDLElBQUksSUFBSSxDQUFDLGtCQUFrQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxpQkFBaUIsRUFBRTtnQkFDdEUsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO29CQUM5RCxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFO3dCQUNqRix5RkFBeUY7d0JBQ3pGLHlGQUF5Rjt3QkFDekYsSUFBSSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxhQUFhLENBQUMsd0JBQXdCLENBQUMsRUFBRTs0QkFDdEUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzt5QkFDbkc7NkJBQU07NEJBQ0gsNEJBQTRCLEdBQUcsSUFBSSxDQUFDOzRCQUNwQyxJQUFJLENBQUMsc0JBQXNCLEdBQWdCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7NEJBQy9FLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDLENBQUM7NEJBQ25HLE1BQU07eUJBQ1Q7cUJBQ0o7aUJBQ0o7YUFDSjtZQUVELElBQUksQ0FBQyw0QkFBNEIsRUFBRTtnQkFDL0IsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztnQkFDakUsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQzthQUN6RTtZQUVELElBQUksQ0FBQyw0QkFBNEIsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3ZFLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN6RCxJQUFJLENBQUMsNkJBQTZCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUM1RTtJQUNMLENBQUM7SUFFRDs7T0FFRztJQUVJLHdCQUF3QjtRQUMzQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN2QixRQUFRLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQztRQUMvRSxRQUFRLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUN6RSxRQUFRLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUNsRixDQUFDO0lBR00sc0JBQXNCLENBQUMsTUFBTTtRQUNoQyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDbkIsUUFBUSxNQUFNLENBQUMsT0FBTyxFQUFFO2dCQUNwQixLQUFLLE9BQU8sQ0FBQyxTQUFTO29CQUNsQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQzt3QkFDZCxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhO3dCQUNsQyxDQUFDLEVBQUUsQ0FBQztxQkFDUCxDQUFDLENBQUM7b0JBQ0gsTUFBTTtnQkFDVixLQUFLLE9BQU8sQ0FBQyxVQUFVO29CQUNuQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQzt3QkFDZCxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsYUFBYTt3QkFDakMsQ0FBQyxFQUFFLENBQUM7cUJBQ1AsQ0FBQyxDQUFDO29CQUNILE1BQU07YUFDYjtTQUNKO2FBQU0sSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ3hCLFFBQVEsTUFBTSxDQUFDLE9BQU8sRUFBRTtnQkFDcEIsS0FBSyxPQUFPLENBQUMsT0FBTztvQkFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7d0JBQ2QsQ0FBQyxFQUFFLENBQUM7d0JBQ0osQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsYUFBYTtxQkFDckMsQ0FBQyxDQUFDO29CQUNILE1BQU07Z0JBQ1YsS0FBSyxPQUFPLENBQUMsU0FBUztvQkFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7d0JBQ2QsQ0FBQyxFQUFFLENBQUM7d0JBQ0osQ0FBQyxFQUFFLGdCQUFnQixDQUFDLGFBQWE7cUJBQ3BDLENBQUMsQ0FBQztvQkFDSCxNQUFNO2FBQ2I7U0FDSjtJQUNMLENBQUM7SUFFTyxXQUFXLENBQUMsT0FBZSxFQUFFLE9BQWU7UUFDaEQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztRQUN4QyxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFakUsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDNUUsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBRWxGLElBQUksQ0FBQyxTQUFTLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUM7UUFDaEUsSUFBSSxDQUFDLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQztJQUNsRSxDQUFDO0lBRU8sa0JBQWtCLENBQUMsS0FBaUI7UUFDeEMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ2pCLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDL0MsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2QixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7U0FDMUI7SUFDTCxDQUFDO0lBRU8sVUFBVSxDQUFDLEtBQWlCO1FBQ2hDLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNqQixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUM1RSxJQUFJLFVBQWtCLENBQUM7WUFDdkIsSUFBSSxVQUFrQixDQUFDO1lBRXZCLElBQUksSUFBWSxDQUFDO1lBQ2pCLElBQUksSUFBWSxDQUFDO1lBQ2pCLFFBQVEsSUFBSSxDQUFDLFdBQVcsRUFBRTtnQkFDdEIsS0FBSyxLQUFLO29CQUNOLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO29CQUMvRSxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7b0JBQzdCLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztvQkFDdkQsVUFBVSxHQUFHLGVBQWUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7d0JBQ3BDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLENBQUM7d0JBQy9ELElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLEdBQUcsR0FBRyxlQUFlLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztvQkFDMUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsVUFBVSxHQUFHLElBQUksQ0FBQztvQkFDM0QsTUFBTTtnQkFDVixLQUFLLFFBQVE7b0JBQ1QsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7b0JBQy9FLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztvQkFDN0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO29CQUN2RCxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7b0JBQ25DLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUM7b0JBQzNELE1BQU07Z0JBQ1YsS0FBSyxNQUFNO29CQUNQLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO29CQUNoRixJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7b0JBQzdCLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztvQkFDeEQsVUFBVSxHQUFHLGVBQWUsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7d0JBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLENBQUM7d0JBQ2hFLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLElBQUksR0FBRyxlQUFlLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztvQkFDNUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsVUFBVSxHQUFHLElBQUksQ0FBQztvQkFDNUQsTUFBTTtnQkFDVixLQUFLLE9BQU87b0JBQ1IsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7b0JBQ2hGLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztvQkFDN0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO29CQUN4RCxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7b0JBQ25DLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUM7b0JBQzVELE1BQU07YUFDYjtZQUVELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztTQUN4RDtJQUNMLENBQUM7SUFFTyxtQkFBbUI7UUFDdkIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ2pCLFFBQVEsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO1lBQ2xGLFFBQVEsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQzVFLFFBQVEsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBRWpGLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1lBRXhCLElBQUksTUFBYyxDQUFDO1lBQ25CLElBQUksTUFBYyxDQUFDO1lBRW5CLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzVFLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUVsRixNQUFNLElBQUksR0FBRyxrQkFBa0IsQ0FBQyxJQUFJLEdBQUcsZUFBZSxDQUFDLElBQUksQ0FBQztZQUM1RCxNQUFNLElBQUksR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQztZQUUxRCxRQUFRLElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ3RCLEtBQUssTUFBTTtvQkFDUCxNQUFNLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQy9CLE1BQU0sR0FBRyxDQUFDLENBQUM7b0JBQ1gsTUFBTTtnQkFDVixLQUFLLE9BQU87b0JBQ1IsTUFBTSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUMvQixNQUFNLEdBQUcsQ0FBQyxDQUFDO29CQUNYLE1BQU07Z0JBQ1YsS0FBSyxLQUFLO29CQUNOLE1BQU0sR0FBRyxDQUFDLENBQUM7b0JBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUMvQixNQUFNO2dCQUNWLEtBQUssUUFBUTtvQkFDVCxNQUFNLEdBQUcsQ0FBQyxDQUFDO29CQUNYLE1BQU0sR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDL0IsTUFBTTthQUNiO1lBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0JBQ2QsQ0FBQyxFQUFFLE1BQU07Z0JBQ1QsQ0FBQyxFQUFFLE1BQU07YUFDWixDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzdELFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUM7WUFDeEMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUM3RCxJQUFJLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBRTlELElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQy9DLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDO1NBQ2pEO0lBQ0wsQ0FBQztJQUVPLFVBQVUsQ0FBQyxHQUFHLFlBQXNCO1FBQ3hDLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVTLHFCQUFxQjtRQUMzQixPQUFPLEtBQUssQ0FBQyxxQkFBcUIsRUFBRTthQUMvQixNQUFNLENBQUM7WUFDSixxQkFBcUI7WUFDckIsZ0JBQWdCO1NBQ25CLENBQUMsQ0FBQztJQUNYLENBQUM7O0FBeGNjLDhCQUFhLEdBQUcsRUFBRSxDQUFDO21HQVR6QixnQkFBZ0I7a0dBQWhCLGdCQUFnQjtxR0FBaEIsOEJBQTBCLHNGQUExQixrQ0FBOEI7Ozs7Ozt1RkFBOUIsZ0JBQWdCO2NBSjVCLFNBQVM7ZUFBQztnQkFDUCxRQUFRLEVBQUUsYUFBYTtnQkFDdkIsUUFBUSxFQUFFLEVBQUU7YUFDZjsyREE4QlUsbUJBQW1CO2tCQUR6QixLQUFLO1lBUUMsZ0JBQWdCO2tCQUR0QixLQUFLO1lBUUMscUJBQXFCO2tCQUQzQixLQUFLO1lBT0ssV0FBVztrQkFEckIsS0FBSztZQW1DQyxTQUFTO2tCQURmLEtBQUs7WUFPQyxPQUFPO2tCQURiLE1BQU07WUFPQSxRQUFRO2tCQURkLE1BQU07WUFPSSxRQUFRO2tCQURsQixXQUFXO21CQUFDLDZCQUE2QjtZQVMvQixXQUFXO2tCQURyQixXQUFXO21CQUFDLGdDQUFnQztZQVNsQyxTQUFTO2tCQURuQixXQUFXO21CQUFDLDhCQUE4QjtZQVNoQyxVQUFVO2tCQURwQixXQUFXO21CQUFDLCtCQUErQjtZQVNqQyxVQUFVO2tCQURwQixXQUFXO21CQUFDLHNCQUFzQjtZQVN4QixZQUFZO2tCQUR0QixXQUFXO21CQUFDLHFCQUFxQjtZQVN2QixlQUFlO2tCQUR6QixXQUFXO21CQUFDLHVCQUF1QjtZQVN6QixNQUFNO2tCQURoQixXQUFXO21CQUFDLGNBQWM7WUF3SXBCLHdCQUF3QjtrQkFEOUIsWUFBWTttQkFBQyxXQUFXO1lBU2xCLHNCQUFzQjtrQkFENUIsWUFBWTttQkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgSW5qZWN0b3IsIElucHV0LCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBLZXlDb2RlIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kYXRhL2FjY2Vzc2liaWxpdHktbWFuYWdlcic7XHJcbmltcG9ydCB7IExvZ0xldmVsIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kaWFnbm9zdGljcy9sb2ctbGV2ZWwnO1xyXG5pbXBvcnQgeyBDb3JlQmFzZUNvbXBvbmVudCB9IGZyb20gJy4uL2NvbW1vbi9iYXNlLmNvbXBvbmVudCc7XHJcblxyXG4vKipcclxuICogUmVzaXplciBjb21wb25lbnRcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdzbWUtcmVzaXplcicsXHJcbiAgICB0ZW1wbGF0ZTogJydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc2l6ZXJDb21wb25lbnQgZXh0ZW5kcyBDb3JlQmFzZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgc291cmNlIG5hbWUgdG8gdXNlIGZvciBsb2dnaW5nXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBnZXQgbG9nU291cmNlTmFtZSgpIHtcclxuICAgICAgICByZXR1cm4gJ1Jlc2l6ZXJDb21wb25lbnQnO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIGtleWJvYXJkRGVsdGEgPSAyMDtcclxuXHJcbiAgICBwcml2YXRlIGlzUmVzaXppbmcgPSBmYWxzZTtcclxuICAgIHByaXZhdGUgcmVzaXplckhvc3RFbGVtZW50OiBFbGVtZW50O1xyXG4gICAgcHJpdmF0ZSByZXNpemVySG9zdEJvZHlFbGVtZW50OiBIVE1MRWxlbWVudDtcclxuICAgIHByaXZhdGUgcmVzaXplckluZGljYXRvckVsZW1lbnQ6IEhUTUxFbGVtZW50O1xyXG4gICAgcHJpdmF0ZSBvZmZzZXRYOiBudW1iZXI7XHJcbiAgICBwcml2YXRlIG9mZnNldFk6IG51bWJlcjtcclxuICAgIHByaXZhdGUgb3JpZ2luYWxYOiBudW1iZXI7XHJcbiAgICBwcml2YXRlIG9yaWdpbmFsWTogbnVtYmVyO1xyXG4gICAgcHJpdmF0ZSBfb3JpZW50YXRpb24gPSAnYm90dG9tJztcclxuXHJcbiAgICBwcml2YXRlIG9uU3RhcnRpbmdSZXNpemVFdmVudEhhbmRsZXI6IChldmVudDogTW91c2VFdmVudCkgPT4gdm9pZDtcclxuICAgIHByaXZhdGUgb25SZXNpemluZ0V2ZW50SGFuZGxlcjogKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB2b2lkO1xyXG4gICAgcHJpdmF0ZSBvbkZpbmlzaGluZ1Jlc2l6ZUV2ZW50SGFuZGxlcjogKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB2b2lkO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSXQncyB1c2VkIHRvIGxvY2F0ZSB0aGUgcmVzaXppbmcgaG9zdCB3aGljaCBkZWZpbmVzIHRoZSBhcmVhIHdoZXJlIHRoZSByZXNpemVyIGNhbiBtb3ZlIGFyb3VuZC5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyByZXNpemVySG9zdFNlbGVjdG9yOiBzdHJpbmc7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJdCBpbmRpY2F0ZXMgd2hldGhlciB0byBzaG93IHRoZSBoYWxmIHRyYW5zcGFyZW50IGNvdmVyIG9udCBoZSByZXNpemVyIGhvc3QuXHJcbiAgICAgKiBJbiBzb21lIGNhc2UgKGxpa2UgRGF0YSBUYWJsZSBjb2x1bW4gcmVzaXplciksIHRoZSBjb3ZlciBpcyBub3QgbmVlZGVkIHNpbmNlIGRhdGEgdGFibGUgd291bGQgaGFuZGxlIHRoZSBVSSBvZiByZXNpemluZyBieSBpdHNlbGYuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2hvd1Jlc2l6ZXJDb3ZlciA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJdCBpbmRpY2F0ZXMgd2hldGhlciB0byBsZXQgdGhlIHNjcmVlbiByZWFkZXIgdG8gcmVhZCB0aGlzIHJlc2l6ZXIgY29udHJvbC5cclxuICAgICAqIEluIHNvbWUgY2FzZSAobGlrZSBEYXRhIFRhYmxlIGNvbHVtbiByZXNpemVyKSwgd2UgZG9uJ3Qgd2FudCB0aGUgc2NyZWVuIHJlYWRlciB0byByZWFkIGl0IGFzIHBhcnQgb2YgdGhlIGNvbHVtbiBoZWFkZXIuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgdmlzaWJsZVRvU2NyZWVuUmVhZGVyID0gdHJ1ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEl0IGRlZmluZXMgdGhlIG9yaWVudGF0aW9uIG9mIHRoZSBlbGVtZW50IHdoaWNoIGhvbGRzIHRoZSByZXNpemVyIGluIHRoZSByZXNpemluZyBsYXlvdXQuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IG9yaWVudGF0aW9uKG5ld09yaWVudGF0aW9uOiBzdHJpbmcpIHtcclxuICAgICAgICBpZiAodGhpcy5fb3JpZW50YXRpb24gIT09IG5ld09yaWVudGF0aW9uKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX29yaWVudGF0aW9uID0gbmV3T3JpZW50YXRpb247XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5yZXNpemVySG9zdEJvZHlFbGVtZW50Py5wYXJlbnROb2RlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZXJIb3N0Qm9keUVsZW1lbnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLnJlc2l6ZXJIb3N0Qm9keUVsZW1lbnQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5yZXNpemVySW5kaWNhdG9yRWxlbWVudD8ucGFyZW50Tm9kZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVySW5kaWNhdG9yRWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMucmVzaXplckluZGljYXRvckVsZW1lbnQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIFRvIHN1cHBvcnQgb3JpZW50YXRpb24gY2hhbmdlcyBieSB3aW5kb3cgc2l6ZSBjaGFuZ2VzXHJcbiAgICAgICAgICAgIC8vIFJlc2V0IGFsbCB0aGUgcGFyYW1ldGVycyBhbmQgcmUtYnVpbGQgdGhlIHJlc2l6ZXIgZWxlbWVudHNcclxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZXJIb3N0RWxlbWVudCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplckhvc3RCb2R5RWxlbWVudCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplckluZGljYXRvckVsZW1lbnQgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9mZnNldFggPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9mZnNldFkgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9yaWdpbmFsWCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgICAgIHRoaXMub3JpZ2luYWxZID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5uZ09uSW5pdCgpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBvcmllbnRhdGlvbigpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9vcmllbnRhdGlvbjtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERldGVybWluZXMgaWYgdGhlIHJlc2l6ZXIgaXMgYWNjZXNzaWJsZSB0byB0aGUgc2NyZWVuIHJlYWRlcnNcclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBmb2N1c2FibGUgPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEl0J3MgZmlyZWQgdGhlbiB0aGUgcmVzaXppbmcgaXMgZmluaXNoZWQuXHJcbiAgICAgKi9cclxuICAgIEBPdXRwdXQoKVxyXG4gICAgcHVibGljIHJlc2l6ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHsgeDogbnVtYmVyLCB5OiBudW1iZXIgfT4oKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEl0J3MgZmlyZWQgdGhlbiB0aGUgcmVzaXppbmcgaXMgaGFwcGVuaW5nLlxyXG4gICAgICovXHJcbiAgICBAT3V0cHV0KClcclxuICAgIHB1YmxpYyByZXNpemluZyA9IG5ldyBFdmVudEVtaXR0ZXI8eyB4OiBudW1iZXIsIHk6IG51bWJlciB9PigpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5kaWNhdGVzIHRoYXQgdGhlIHJlc2l6ZXIgc2hvdWxkIGJlIGFsaWduZWQgdG8gdGhlIHRvcFxyXG4gICAgICovXHJcbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLnNtZS1wb3NpdGlvbi10b3Atbm9uZScpXHJcbiAgICBwdWJsaWMgZ2V0IGFsaWduVG9wKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmlzT3JpZW50ZWQoJ2JvdHRvbScsICdsZWZ0JywgJ3JpZ2h0Jyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgcmVzaXplciBzaG91bGQgYmUgYWxpZ25lZCB0byB0aGUgYm90dG9tXHJcbiAgICAgKi9cclxuICAgIEBIb3N0QmluZGluZygnY2xhc3Muc21lLXBvc2l0aW9uLWJvdHRvbS1ub25lJylcclxuICAgIHB1YmxpYyBnZXQgYWxpZ25Cb3R0b20oKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNPcmllbnRlZCgndG9wJywgJ2xlZnQnLCAncmlnaHQnKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSByZXNpemVyIHNob3VsZCBiZSBhbGlnbmVkIHRvIHRoZSBsZWZ0XHJcbiAgICAgKi9cclxuICAgIEBIb3N0QmluZGluZygnY2xhc3Muc21lLXBvc2l0aW9uLWxlZnQtbm9uZScpXHJcbiAgICBwdWJsaWMgZ2V0IGFsaWduTGVmdCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pc09yaWVudGVkKCd0b3AnLCAnYm90dG9tJywgJ3JpZ2h0Jyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgcmVzaXplciBzaG91bGQgYmUgYWxpZ25lZCB0byB0aGUgcmlnaHRcclxuICAgICAqL1xyXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5zbWUtcG9zaXRpb24tcmlnaHQtbm9uZScpXHJcbiAgICBwdWJsaWMgZ2V0IGFsaWduUmlnaHQoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNPcmllbnRlZCgndG9wJywgJ2JvdHRvbScsICdsZWZ0Jyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgcmVzaXplciBtb3ZlcyB2ZXJ0aWNhbGx5XHJcbiAgICAgKi9cclxuICAgIEBIb3N0QmluZGluZygnY2xhc3Muc21lLWhlaWdodC14eHMnKVxyXG4gICAgcHVibGljIGdldCBpc1ZlcnRpY2FsKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmlzT3JpZW50ZWQoJ3RvcCcsICdib3R0b20nKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSByZXNpemVyIG1vdmVzIGhvcml6b250YWxseVxyXG4gICAgICovXHJcbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLnNtZS13aWR0aC14eHMnKVxyXG4gICAgcHVibGljIGdldCBpc0hvcml6b250YWwoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNPcmllbnRlZCgnbGVmdCcsICdyaWdodCcpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVzY3JpYmVzIHRoZSBvcmllbnRhdGlvbiBmb3IgYXJpYSB1c2Vycy5cclxuICAgICAqL1xyXG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLmFyaWEtb3JpZW50YXRpb24nKVxyXG4gICAgcHVibGljIGdldCBhcmlhT3JpZW50YXRpb24oKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWZXJ0aWNhbCA/ICd2ZXJ0aWNhbCcgOiAnaG9yaXpvbnRhbCc7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHRoZSBjdXJzb3Igc3R5bGUgdGhlIHJlc2l6ZXIgc2hvdWxkIGhhdmVcclxuICAgICAqL1xyXG4gICAgQEhvc3RCaW5kaW5nKCdzdHlsZS5jdXJzb3InKVxyXG4gICAgcHVibGljIGdldCBjdXJzb3IoKSB7XHJcbiAgICAgICAgc3dpdGNoICh0aGlzLm9yaWVudGF0aW9uKSB7XHJcbiAgICAgICAgICAgIGNhc2UgJ3RvcCc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ24tcmVzaXplJztcclxuICAgICAgICAgICAgY2FzZSAnYm90dG9tJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAncy1yZXNpemUnO1xyXG4gICAgICAgICAgICBjYXNlICdsZWZ0JzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAnZS1yZXNpemUnO1xyXG4gICAgICAgICAgICBjYXNlICdyaWdodCc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3ctcmVzaXplJztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbml0aWFsaXplcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgQHNlZSBSZXNpemVyQ29tcG9uZW50IGNsYXNzLlxyXG4gICAgICogQHBhcmFtIGluamVjdG9yIFRoZSBhbmd1bGFyIGluamVjdGlvbiBzZXJ2aWNlLiByZXF1aXJlZCBieSBAc2VlIFNtZUluamVjdGFibGVCYXNlIGRlY29yYXRvciBpbiB0aGUgQHNlZSBCYXNlQ29tcG9uZW50IGNsYXNzXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGluamVjdG9yOiBJbmplY3Rvcikge1xyXG4gICAgICAgIHN1cGVyKGluamVjdG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFuZ3VsYXIgbGlmZWN5Y2xlIGhvb2suXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgICAgICBzdXBlci5uZ09uSW5pdCgpO1xyXG5cclxuICAgICAgICAvLyBUaGlzIGlzIGEgc3BlY2lhbCBpbXBsZW1lbnRhdGlvbiBmb3IgTWljcm9zb2Z0IEVkZ2UuXHJcbiAgICAgICAgLy8gSW4gTWljcm9zb2Z0IEVkZ2UsIGlmIHRoZSByZXNpemVyIGRpdiBpcyB0cmFuc3BhcmVudCBhbmQgaXQncyBvdmVybGF5IG9uIHRoZSBzY3JvbGxiYXIsXHJcbiAgICAgICAgLy8gdGhlIG1vdXNlIGV2ZW50cyB3aWxsIGJlIG1lc3NlZCB1cC5cclxuICAgICAgICAvLyBTbyB3ZSBuZWVkIHRvIGFwcGx5IGEgdmVyeSB0cmFuc3BhcmVudCBidXQgbm90IDEwMCUgdHJhbnNwYXJlbnQgY29sb3IgdG8gaXQuXHJcbiAgICAgICAgLy8gSXQgd29uJ3QgaW1wYWN0IHRoZSBsb29rIGFuZCBmZWVsLCB3aGVuIHRoZSBicm93c2VyIHJlbmRlcnMgdGhpcyBzcGVjaWFsIGNvbG9yLFxyXG4gICAgICAgIC8vIGJhc2ljYWxseSBubyBjb2xvciB3aWxsIGJlIGFjdHVhbGx5IHJlbmRlcmVkLlxyXG4gICAgICAgIHRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kID0gJ3JnYmEoMjU1LDI1NSwyNTUsMC4wMDMpJztcclxuXHJcbiAgICAgICAgaWYgKHRoaXMudmlzaWJsZVRvU2NyZWVuUmVhZGVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3NlcGFyYXRvcicpO1xyXG4gICAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsIHRoaXMuc3RyaW5ncy5Nc2Z0U21lU2hlbGwuQW5ndWxhci5SZXNpemVyLlNwbGl0dGVyKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIHRoaXMuZm9jdXNhYmxlID8gJzAnIDogJy0xJyk7XHJcbiAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgdGhpcy5mb2N1c2FibGUgPyAnZmFsc2UnIDogJ3RydWUnKTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLnJlc2l6ZXJIb3N0U2VsZWN0b3IpIHtcclxuICAgICAgICAgICAgdGhpcy5sb2coJ3Jlc2l6ZXJIb3N0U2VsZWN0b3IgaXMgbm90IHNldC4nLCBMb2dMZXZlbC5XYXJuaW5nKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBsZXQgY3VycmVudFBhcmVudEVsZW1lbnQgPSAoPEhUTUxFbGVtZW50PnRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudCkucGFyZW50RWxlbWVudDtcclxuICAgICAgICAgICAgd2hpbGUgKCF0aGlzLnJlc2l6ZXJIb3N0RWxlbWVudCAmJiBjdXJyZW50UGFyZW50RWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgLy8gRGVhbCB3aXRoIG5lc3RlZCBodG1sIHRhZywgZm9yIGluc3RhbmNlLCBzbWUtc3BsaXQtdmlldyBjb250YWlucyBvZiBuZXN0ZWQgc21lLXNwbGl0LXZpZXdcclxuICAgICAgICAgICAgICAgIC8vIFdpdGhvdXQgdGhpcyBpZiBsb2dpYywgdGhlIHJ