@igor2017/sat-popover
Version:
Popover component for Angular
397 lines • 56.7 kB
JavaScript
import { ElementRef, Injectable, Optional } from '@angular/core';
import { ConnectionPositionPair, OverlayConfig } from '@angular/cdk/overlay';
import { ESCAPE } from '@angular/cdk/keycodes';
import { TemplatePortal } from '@angular/cdk/portal';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Subject } from 'rxjs';
import { takeUntil, take, filter, tap } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/overlay";
import * as i2 from "@angular/cdk/bidi";
class SatPopoverAnchoringService {
_overlay;
_ngZone;
_dir;
/** Emits when the popover is opened. */
popoverOpened = new Subject();
/** Emits when the popover is closed. */
popoverClosed = new Subject();
/** Reference to the overlay containing the popover component. */
_overlayRef;
/** Reference to the target popover. */
_popover;
/** Reference to the view container for the popover template. */
_viewContainerRef;
/** Reference to the anchor element. */
_anchor;
/** Reference to a template portal where the overlay will be attached. */
_portal;
/** Single subscription to notifications service events. */
_notificationsSubscription;
/** Single subscription to position changes. */
_positionChangeSubscription;
/** Whether the popover is presently open. */
_popoverOpen = false;
/** Emits when the service is destroyed. */
_onDestroy = new Subject();
constructor(_overlay, _ngZone, _dir) {
this._overlay = _overlay;
this._ngZone = _ngZone;
this._dir = _dir;
}
ngOnDestroy() {
// Destroy popover before terminating subscriptions so that any resulting
// detachments update 'closed state'
this._destroyPopover();
// Terminate subscriptions
if (this._notificationsSubscription) {
this._notificationsSubscription.unsubscribe();
}
if (this._positionChangeSubscription) {
this._positionChangeSubscription.unsubscribe();
}
this._onDestroy.next();
this._onDestroy.complete();
this.popoverOpened.complete();
this.popoverClosed.complete();
}
/** Anchor a popover instance to a view and connection element. */
anchor(popover, viewContainerRef, anchor) {
// If we're just changing the anchor element and the overlayRef already exists,
// simply update the existing _overlayRef's anchor.
if (this._popover === popover && this._viewContainerRef === viewContainerRef && this._overlayRef) {
this._anchor = anchor instanceof ElementRef ? anchor.nativeElement : anchor;
const config = this._overlayRef.getConfig();
const strategy = config.positionStrategy;
strategy.setOrigin(this._anchor);
this._overlayRef.updatePosition();
return;
}
// Destroy any previous popovers
this._destroyPopover();
// Assign local refs
this._popover = popover;
this._viewContainerRef = viewContainerRef;
this._anchor = anchor instanceof ElementRef ? anchor.nativeElement : anchor;
}
/** Gets whether the popover is presently open. */
isPopoverOpen() {
return this._popoverOpen;
}
/** Toggles the popover between the open and closed states. */
togglePopover() {
return this._popoverOpen ? this.closePopover() : this.openPopover();
}
/** Opens the popover. */
openPopover(options = {}) {
if (!this._popoverOpen) {
this._applyOpenOptions(options);
this._createOverlay();
this._subscribeToBackdrop();
this._subscribeToEscape();
this._subscribeToDetachments();
this._saveOpenedState();
}
}
/** Closes the popover. */
closePopover(value) {
if (this._overlayRef) {
this._saveClosedState(value);
this._overlayRef.detach();
}
}
/** TODO: implement when the overlay's position can be dynamically changed */
repositionPopover() {
this.updatePopoverConfig();
}
/** TODO: when the overlay's position can be dynamically changed, do not destroy */
updatePopoverConfig() {
this._destroyPopoverOnceClosed();
}
/** Realign the popover to the anchor. */
realignPopoverToAnchor() {
if (this._overlayRef) {
const config = this._overlayRef.getConfig();
const strategy = config.positionStrategy;
strategy.reapplyLastPosition();
}
}
/** Get a reference to the anchor element. */
getAnchorElement() {
return this._anchor;
}
/** Apply behavior properties on the popover based on the open options. */
_applyOpenOptions(options) {
// Only override restoreFocus as `false` if the option is explicitly `false`
const restoreFocus = options.restoreFocus !== false;
this._popover._restoreFocusOverride = restoreFocus;
// Only override autoFocus as `false` if the option is explicitly `false`
const autoFocus = options.autoFocus !== false;
this._popover._autoFocusOverride = autoFocus;
}
/** Create an overlay to be attached to the portal. */
_createOverlay() {
// Create overlay if it doesn't yet exist
if (!this._overlayRef) {
this._portal = new TemplatePortal(this._popover._templateRef, this._viewContainerRef);
const popoverConfig = {
horizontalAlign: this._popover.horizontalAlign,
verticalAlign: this._popover.verticalAlign,
hasBackdrop: coerceBooleanProperty(this._popover.hasBackdrop),
backdropClass: this._popover.backdropClass,
scrollStrategy: this._popover.scrollStrategy,
forceAlignment: coerceBooleanProperty(this._popover.forceAlignment),
lockAlignment: coerceBooleanProperty(this._popover.lockAlignment),
panelClass: this._popover.panelClass
};
const overlayConfig = this._getOverlayConfig(popoverConfig, this._anchor);
this._subscribeToPositionChanges(overlayConfig.positionStrategy);
this._overlayRef = this._overlay.create(overlayConfig);
}
// Actually open the popover
this._overlayRef.attach(this._portal);
return this._overlayRef;
}
/** Removes the popover from the DOM. Does NOT update open state. */
_destroyPopover() {
if (this._overlayRef) {
this._overlayRef.dispose();
this._overlayRef = null;
}
}
/**
* Destroys the popover immediately if it is closed, or waits until it
* has been closed to destroy it.
*/
_destroyPopoverOnceClosed() {
if (this.isPopoverOpen() && this._overlayRef) {
this._overlayRef
.detachments()
.pipe(take(1), takeUntil(this._onDestroy))
.subscribe(() => this._destroyPopover());
}
else {
this._destroyPopover();
}
}
/** Close popover when backdrop is clicked. */
_subscribeToBackdrop() {
this._overlayRef
.backdropClick()
.pipe(tap(() => this._popover.backdropClicked.emit()), filter(() => this._popover.interactiveClose), takeUntil(this.popoverClosed), takeUntil(this._onDestroy))
.subscribe(() => this.closePopover());
}
/** Close popover when escape keydown event occurs. */
_subscribeToEscape() {
this._overlayRef
.keydownEvents()
.pipe(tap((event) => this._popover.overlayKeydown.emit(event)), filter((event) => event.keyCode === ESCAPE), filter(() => this._popover.interactiveClose), takeUntil(this.popoverClosed), takeUntil(this._onDestroy))
.subscribe(() => this.closePopover());
}
/** Set state back to closed when detached. */
_subscribeToDetachments() {
this._overlayRef
.detachments()
.pipe(takeUntil(this._onDestroy))
.subscribe(() => this._saveClosedState());
}
/** Save the opened state of the popover and emit. */
_saveOpenedState() {
if (!this._popoverOpen) {
this._popover._state = 'enter';
this._popover._open = this._popoverOpen = true;
this.popoverOpened.next();
this._popover.opened.emit();
}
}
/** Save the closed state of the popover and emit. */
_saveClosedState(value) {
if (this._popoverOpen) {
this._popover._open = this._popoverOpen = false;
this._popover._startExitAnimation();
this.popoverClosed.next(value);
this._popover.closed.emit(value);
}
}
/** Gets the text direction of the containing app. */
_getDirection() {
return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';
}
/** Create and return a config for creating the overlay. */
_getOverlayConfig(config, anchor) {
return new OverlayConfig({
positionStrategy: this._getPositionStrategy(config.horizontalAlign, config.verticalAlign, config.forceAlignment, config.lockAlignment, anchor),
hasBackdrop: config.hasBackdrop,
backdropClass: config.backdropClass || 'cdk-overlay-transparent-backdrop',
scrollStrategy: this._getScrollStrategyInstance(config.scrollStrategy),
direction: this._getDirection(),
panelClass: config.panelClass
});
}
/**
* Listen to changes in the position of the overlay and set the correct alignment classes,
* ensuring that the animation origin is correct, even with a fallback position.
*/
_subscribeToPositionChanges(position) {
if (this._positionChangeSubscription) {
this._positionChangeSubscription.unsubscribe();
}
this._positionChangeSubscription = position.positionChanges.pipe(takeUntil(this._onDestroy)).subscribe((change) => {
// Position changes may occur outside the Angular zone
this._ngZone.run(() => {
this._popover._setAlignmentClasses(getHorizontalPopoverAlignment(change.connectionPair.overlayX), getVerticalPopoverAlignment(change.connectionPair.overlayY));
});
});
}
/** Map a scroll strategy string type to an instance of a scroll strategy. */
_getScrollStrategyInstance(strategy) {
switch (strategy) {
case 'block':
return this._overlay.scrollStrategies.block();
case 'reposition':
return this._overlay.scrollStrategies.reposition();
case 'close':
return this._overlay.scrollStrategies.close();
case 'noop':
default:
return this._overlay.scrollStrategies.noop();
}
}
/** Create and return a position strategy based on config provided to the component instance. */
_getPositionStrategy(horizontalTarget, verticalTarget, forceAlignment, lockAlignment, anchor) {
// Attach the overlay at the preferred position
const targetPosition = getPosition(horizontalTarget, verticalTarget);
const positions = [targetPosition];
const strategy = this._overlay
.position()
.flexibleConnectedTo(anchor)
.withFlexibleDimensions(false)
.withPush(false)
.withViewportMargin(0)
.withLockedPosition(lockAlignment);
// Unless the alignment is forced, add fallbacks based on the preferred positions
if (!forceAlignment) {
const fallbacks = this._getFallbacks(horizontalTarget, verticalTarget);
positions.push(...fallbacks);
}
return strategy.withPositions(positions);
}
/** Get fallback positions based around target alignments. */
_getFallbacks(hTarget, vTarget) {
// Determine if the target alignments overlap the anchor
const horizontalOverlapAllowed = hTarget !== 'before' && hTarget !== 'after';
const verticalOverlapAllowed = vTarget !== 'above' && vTarget !== 'below';
// If a target alignment doesn't cover the anchor, don't let any of the fallback alignments
// cover the anchor
const possibleHorizontalAlignments = horizontalOverlapAllowed
? ['before', 'start', 'center', 'end', 'after']
: ['before', 'after'];
const possibleVerticalAlignments = verticalOverlapAllowed
? ['above', 'start', 'center', 'end', 'below']
: ['above', 'below'];
// Create fallbacks for each allowed prioritized fallback alignment combo
const fallbacks = [];
prioritizeAroundTarget(hTarget, possibleHorizontalAlignments).forEach((h) => {
prioritizeAroundTarget(vTarget, possibleVerticalAlignments).forEach((v) => {
fallbacks.push(getPosition(h, v));
});
});
// Remove the first item since it will be the target alignment and isn't considered a fallback
return fallbacks.slice(1, fallbacks.length);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: SatPopoverAnchoringService, deps: [{ token: i1.Overlay }, { token: i0.NgZone }, { token: i2.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: SatPopoverAnchoringService });
}
export { SatPopoverAnchoringService };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: SatPopoverAnchoringService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.Overlay }, { type: i0.NgZone }, { type: i2.Directionality, decorators: [{
type: Optional
}] }]; } });
/** Helper function to get a cdk position pair from SatPopover alignments. */
function getPosition(h, v) {
const { originX, overlayX } = getHorizontalConnectionPosPair(h);
const { originY, overlayY } = getVerticalConnectionPosPair(v);
return new ConnectionPositionPair({ originX, originY }, { overlayX, overlayY });
}
/** Helper function to convert an overlay connection position to equivalent popover alignment. */
function getHorizontalPopoverAlignment(h) {
if (h === 'start') {
return 'after';
}
if (h === 'end') {
return 'before';
}
return 'center';
}
/** Helper function to convert an overlay connection position to equivalent popover alignment. */
function getVerticalPopoverAlignment(v) {
if (v === 'top') {
return 'below';
}
if (v === 'bottom') {
return 'above';
}
return 'center';
}
/** Helper function to convert alignment to origin/overlay position pair. */
function getHorizontalConnectionPosPair(h) {
switch (h) {
case 'before':
return { originX: 'start', overlayX: 'end' };
case 'start':
return { originX: 'start', overlayX: 'start' };
case 'end':
return { originX: 'end', overlayX: 'end' };
case 'after':
return { originX: 'end', overlayX: 'start' };
default:
return { originX: 'center', overlayX: 'center' };
}
}
/** Helper function to convert alignment to origin/overlay position pair. */
function getVerticalConnectionPosPair(v) {
switch (v) {
case 'above':
return { originY: 'top', overlayY: 'bottom' };
case 'start':
return { originY: 'top', overlayY: 'top' };
case 'end':
return { originY: 'bottom', overlayY: 'bottom' };
case 'below':
return { originY: 'bottom', overlayY: 'top' };
default:
return { originY: 'center', overlayY: 'center' };
}
}
/**
* Helper function that takes an ordered array options and returns a reorderded
* array around the target item. e.g.:
*
* target: 3; options: [1, 2, 3, 4, 5, 6, 7];
*
* return: [3, 4, 2, 5, 1, 6, 7]
*/
function prioritizeAroundTarget(target, options) {
const targetIndex = options.indexOf(target);
// Set the first item to be the target
const reordered = [target];
// Make left and right stacks where the highest priority item is last
const left = options.slice(0, targetIndex);
const right = options.slice(targetIndex + 1, options.length).reverse();
// Alternate between stacks until one is empty
while (left.length && right.length) {
reordered.push(right.pop());
reordered.push(left.pop());
}
// Flush out right side
while (right.length) {
reordered.push(right.pop());
}
// Flush out left side
while (left.length) {
reordered.push(left.pop());
}
return reordered;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wb3Zlci1hbmNob3Jpbmcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvcG9wb3Zlci9wb3BvdmVyLWFuY2hvcmluZy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFxQixRQUFRLEVBQW9CLE1BQU0sZUFBZSxDQUFDO0FBQ3RHLE9BQU8sRUFDTCxzQkFBc0IsRUFJdEIsYUFBYSxFQUlkLE1BQU0sc0JBQXNCLENBQUM7QUFFOUIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQy9DLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM5RCxPQUFPLEVBQWdCLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3QyxPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUF5QjlELE1BQ2EsMEJBQTBCO0lBa0NqQjtJQUEyQjtJQUFxQztJQWpDcEYsd0NBQXdDO0lBQ3hDLGFBQWEsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0lBRXBDLHdDQUF3QztJQUN4QyxhQUFhLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQUVwQyxpRUFBaUU7SUFDakUsV0FBVyxDQUFhO0lBRXhCLHVDQUF1QztJQUMvQixRQUFRLENBQWE7SUFFN0IsZ0VBQWdFO0lBQ3hELGlCQUFpQixDQUFtQjtJQUU1Qyx1Q0FBdUM7SUFDL0IsT0FBTyxDQUFjO0lBRTdCLHlFQUF5RTtJQUNqRSxPQUFPLENBQXNCO0lBRXJDLDJEQUEyRDtJQUNuRCwwQkFBMEIsQ0FBZTtJQUVqRCwrQ0FBK0M7SUFDdkMsMkJBQTJCLENBQWU7SUFFbEQsNkNBQTZDO0lBQ3JDLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFN0IsMkNBQTJDO0lBQ25DLFVBQVUsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0lBRXpDLFlBQW9CLFFBQWlCLEVBQVUsT0FBZSxFQUFzQixJQUFvQjtRQUFwRixhQUFRLEdBQVIsUUFBUSxDQUFTO1FBQVUsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUFzQixTQUFJLEdBQUosSUFBSSxDQUFnQjtJQUFHLENBQUM7SUFFNUcsV0FBVztRQUNULHlFQUF5RTtRQUN6RSxvQ0FBb0M7UUFDcEMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRXZCLDBCQUEwQjtRQUMxQixJQUFJLElBQUksQ0FBQywwQkFBMEIsRUFBRTtZQUNuQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDL0M7UUFDRCxJQUFJLElBQUksQ0FBQywyQkFBMkIsRUFBRTtZQUNwQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDaEQ7UUFDRCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFM0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFRCxrRUFBa0U7SUFDbEUsTUFBTSxDQUFDLE9BQW1CLEVBQUUsZ0JBQWtDLEVBQUUsTUFBZ0M7UUFDOUYsK0VBQStFO1FBQy9FLG1EQUFtRDtRQUNuRCxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssT0FBTyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsS0FBSyxnQkFBZ0IsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ2hHLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxZQUFZLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1lBQzVFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDNUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLGdCQUFxRCxDQUFDO1lBQzlFLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDbEMsT0FBTztTQUNSO1FBRUQsZ0NBQWdDO1FBQ2hDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUV2QixvQkFBb0I7UUFDcEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7UUFDeEIsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGdCQUFnQixDQUFDO1FBQzFDLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxZQUFZLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQzlFLENBQUM7SUFFRCxrREFBa0Q7SUFDbEQsYUFBYTtRQUNYLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBRUQsOERBQThEO0lBQzlELGFBQWE7UUFDWCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3RFLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsV0FBVyxDQUFDLFVBQWlDLEVBQUU7UUFDN0MsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDdEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0QixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztZQUM1QixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztZQUMvQixJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUN6QjtJQUNILENBQUM7SUFFRCwwQkFBMEI7SUFDMUIsWUFBWSxDQUFDLEtBQVc7UUFDdEIsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3BCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQzNCO0lBQ0gsQ0FBQztJQUVELDZFQUE2RTtJQUM3RSxpQkFBaUI7UUFDZixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRUQsbUZBQW1GO0lBQ25GLG1CQUFtQjtRQUNqQixJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQseUNBQXlDO0lBQ3pDLHNCQUFzQjtRQUNwQixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDcEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUM1QyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsZ0JBQXFELENBQUM7WUFDOUUsUUFBUSxDQUFDLG1CQUFtQixFQUFFLENBQUM7U0FDaEM7SUFDSCxDQUFDO0lBRUQsNkNBQTZDO0lBQzdDLGdCQUFnQjtRQUNkLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0lBRUQsMEVBQTBFO0lBQ2xFLGlCQUFpQixDQUFDLE9BQThCO1FBQ3RELDRFQUE0RTtRQUM1RSxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsWUFBWSxLQUFLLEtBQUssQ0FBQztRQUNwRCxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixHQUFHLFlBQVksQ0FBQztRQUVuRCx5RUFBeUU7UUFDekUsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUM7UUFDOUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsR0FBRyxTQUFTLENBQUM7SUFDL0MsQ0FBQztJQUVELHNEQUFzRDtJQUM5QyxjQUFjO1FBQ3BCLHlDQUF5QztRQUN6QyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNyQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBRXRGLE1BQU0sYUFBYSxHQUFrQjtnQkFDbkMsZUFBZSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZTtnQkFDOUMsYUFBYSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYTtnQkFDMUMsV0FBVyxFQUFFLHFCQUFxQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDO2dCQUM3RCxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhO2dCQUMxQyxjQUFjLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjO2dCQUM1QyxjQUFjLEVBQUUscUJBQXFCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7Z0JBQ25FLGFBQWEsRUFBRSxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQztnQkFDakUsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVTthQUNyQyxDQUFDO1lBRUYsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFMUUsSUFBSSxDQUFDLDJCQUEyQixDQUFDLGFBQWEsQ0FBQyxnQkFBcUQsQ0FBQyxDQUFDO1lBRXRHLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDeEQ7UUFFRCw0QkFBNEI7UUFDNUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUMxQixDQUFDO0lBRUQsb0VBQW9FO0lBQzVELGVBQWU7UUFDckIsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3BCLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDM0IsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7U0FDekI7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0sseUJBQXlCO1FBQy9CLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDNUMsSUFBSSxDQUFDLFdBQVc7aUJBQ2IsV0FBVyxFQUFFO2lCQUNiLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztpQkFDekMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDO1NBQzVDO2FBQU07WUFDTCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7U0FDeEI7SUFDSCxDQUFDO0lBRUQsOENBQThDO0lBQ3RDLG9CQUFvQjtRQUMxQixJQUFJLENBQUMsV0FBVzthQUNiLGFBQWEsRUFBRTthQUNmLElBQUksQ0FDSCxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLENBQUMsRUFDL0MsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsRUFDNUMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFDN0IsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDM0I7YUFDQSxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVELHNEQUFzRDtJQUM5QyxrQkFBa0I7UUFDeEIsSUFBSSxDQUFDLFdBQVc7YUFDYixhQUFhLEVBQUU7YUFDZixJQUFJLENBQ0gsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFDeEQsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxLQUFLLE1BQU0sQ0FBQyxFQUMzQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUM1QyxTQUFTLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUM3QixTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUMzQjthQUNBLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsOENBQThDO0lBQ3RDLHVCQUF1QjtRQUM3QixJQUFJLENBQUMsV0FBVzthQUNiLFdBQVcsRUFBRTthQUNiLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ2hDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRCxxREFBcUQ7SUFDN0MsZ0JBQWdCO1FBQ3RCLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3RCLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQztZQUMvQixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztZQUUvQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1NBQzdCO0lBQ0gsQ0FBQztJQUVELHFEQUFxRDtJQUM3QyxnQkFBZ0IsQ0FBQyxLQUFXO1FBQ2xDLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztZQUVoRCxJQUFJLENBQUMsUUFBUSxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ2xDO0lBQ0gsQ0FBQztJQUVELHFEQUFxRDtJQUM3QyxhQUFhO1FBQ25CLE9BQU8sSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQ2hFLENBQUM7SUFFRCwyREFBMkQ7SUFDbkQsaUJBQWlCLENBQUMsTUFBcUIsRUFBRSxNQUFtQjtRQUNsRSxPQUFPLElBQUksYUFBYSxDQUFDO1lBQ3ZCLGdCQUFnQixFQUFFLElBQUksQ0FBQyxvQkFBb0IsQ0FDekMsTUFBTSxDQUFDLGVBQWUsRUFDdEIsTUFBTSxDQUFDLGFBQWEsRUFDcEIsTUFBTSxDQUFDLGNBQWMsRUFDckIsTUFBTSxDQUFDLGFBQWEsRUFDcEIsTUFBTSxDQUNQO1lBQ0QsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO1lBQy9CLGFBQWEsRUFBRSxNQUFNLENBQUMsYUFBYSxJQUFJLGtDQUFrQztZQUN6RSxjQUFjLEVBQUUsSUFBSSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUM7WUFDdEUsU0FBUyxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUU7WUFDL0IsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO1NBQzlCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSywyQkFBMkIsQ0FBQyxRQUEyQztRQUM3RSxJQUFJLElBQUksQ0FBQywyQkFBMkIsRUFBRTtZQUNwQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDaEQ7UUFFRCxJQUFJLENBQUMsMkJBQTJCLEdBQUcsUUFBUSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ2hILHNEQUFzRDtZQUN0RCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQ2hDLDZCQUE2QixDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEVBQzdELDJCQUEyQixDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQzVELENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDZFQUE2RTtJQUNyRSwwQkFBMEIsQ0FBQyxRQUFrQztRQUNuRSxRQUFRLFFBQVEsRUFBRTtZQUNoQixLQUFLLE9BQU87Z0JBQ1YsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2hELEtBQUssWUFBWTtnQkFDZixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDckQsS0FBSyxPQUFPO2dCQUNWLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNoRCxLQUFLLE1BQU0sQ0FBQztZQUNaO2dCQUNFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUNoRDtJQUNILENBQUM7SUFFRCxnR0FBZ0c7SUFDeEYsb0JBQW9CLENBQzFCLGdCQUEyQyxFQUMzQyxjQUF1QyxFQUN2QyxjQUF1QixFQUN2QixhQUFzQixFQUN0QixNQUFtQjtRQUVuQiwrQ0FBK0M7UUFDL0MsTUFBTSxjQUFjLEdBQUcsV0FBVyxDQUFDLGdCQUFnQixFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sU0FBUyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFbkMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVE7YUFDM0IsUUFBUSxFQUFFO2FBQ1YsbUJBQW1CLENBQUMsTUFBTSxDQUFDO2FBQzNCLHNCQUFzQixDQUFDLEtBQUssQ0FBQzthQUM3QixRQUFRLENBQUMsS0FBSyxDQUFDO2FBQ2Ysa0JBQWtCLENBQUMsQ0FBQyxDQUFDO2FBQ3JCLGtCQUFrQixDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRXJDLGlGQUFpRjtRQUNqRixJQUFJLENBQUMsY0FBYyxFQUFFO1lBQ25CLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLEVBQUUsY0FBYyxDQUFDLENBQUM7WUFDdkUsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDO1NBQzlCO1FBRUQsT0FBTyxRQUFRLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRCw2REFBNkQ7SUFDckQsYUFBYSxDQUNuQixPQUFrQyxFQUNsQyxPQUFnQztRQUVoQyx3REFBd0Q7UUFDeEQsTUFBTSx3QkFBd0IsR0FBRyxPQUFPLEtBQUssUUFBUSxJQUFJLE9BQU8sS0FBSyxPQUFPLENBQUM7UUFDN0UsTUFBTSxzQkFBc0IsR0FBRyxPQUFPLEtBQUssT0FBTyxJQUFJLE9BQU8sS0FBSyxPQUFPLENBQUM7UUFFMUUsMkZBQTJGO1FBQzNGLG1CQUFtQjtRQUNuQixNQUFNLDRCQUE0QixHQUFnQyx3QkFBd0I7WUFDeEYsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQztZQUMvQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDeEIsTUFBTSwwQkFBMEIsR0FBOEIsc0JBQXNCO1lBQ2xGLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUM7WUFDOUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXZCLHlFQUF5RTtRQUN6RSxNQUFNLFNBQVMsR0FBNkIsRUFBRSxDQUFDO1FBQy9DLHNCQUFzQixDQUFDLE9BQU8sRUFBRSw0QkFBNEIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQzFFLHNCQUFzQixDQUFDLE9BQU8sRUFBRSwwQkFBMEIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO2dCQUN4RSxTQUFTLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwQyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsOEZBQThGO1FBQzlGLE9BQU8sU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlDLENBQUM7dUdBOVdVLDBCQUEwQjsyR0FBMUIsMEJBQTBCOztTQUExQiwwQkFBMEI7MkZBQTFCLDBCQUEwQjtrQkFEdEMsVUFBVTs7MEJBbUN3RCxRQUFROztBQStVM0UsNkVBQTZFO0FBQzdFLFNBQVMsV0FBVyxDQUFDLENBQTRCLEVBQUUsQ0FBMEI7SUFDM0UsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsR0FBRyw4QkFBOEIsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNoRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxHQUFHLDRCQUE0QixDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlELE9BQU8sSUFBSSxzQkFBc0IsQ0FBQyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0FBQ2xGLENBQUM7QUFFRCxpR0FBaUc7QUFDakcsU0FBUyw2QkFBNkIsQ0FBQyxDQUEwQjtJQUMvRCxJQUFJLENBQUMsS0FBSyxPQUFPLEVBQUU7UUFDakIsT0FBTyxPQUFPLENBQUM7S0FDaEI7SUFFRCxJQUFJLENBQUMsS0FBSyxLQUFLLEVBQUU7UUFDZixPQUFPLFFBQVEsQ0FBQztLQUNqQjtJQUVELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxpR0FBaUc7QUFDakcsU0FBUywyQkFBMkIsQ0FBQyxDQUF3QjtJQUMzRCxJQUFJLENBQUMsS0FBSyxLQUFLLEVBQUU7UUFDZixPQUFPLE9BQU8sQ0FBQztLQUNoQjtJQUVELElBQUksQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUNsQixPQUFPLE9BQU8sQ0FBQztLQUNoQjtJQUVELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsU0FBUyw4QkFBOEIsQ0FBQyxDQUE0QjtJQUlsRSxRQUFRLENBQUMsRUFBRTtRQUNULEtBQUssUUFBUTtZQUNYLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUMvQyxLQUFLLE9BQU87WUFDVixPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDakQsS0FBSyxLQUFLO1lBQ1IsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQzdDLEtBQUssT0FBTztZQUNWLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQztRQUMvQztZQUNFLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQztLQUNwRDtBQUNILENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsU0FBUyw0QkFBNEIsQ0FBQyxDQUEwQjtJQUk5RCxRQUFRLENBQUMsRUFBRTtRQUNULEtBQUssT0FBTztZQUNWLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQztRQUNoRCxLQUFLLE9BQU87WUFDVixPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDN0MsS0FBSyxLQUFLO1lBQ1IsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxDQUFDO1FBQ25ELEtBQUssT0FBTztZQUNWLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUNoRDtZQUNFLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQztLQUNwRDtBQUNILENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsU0FBUyxzQkFBc0IsQ0FBSSxNQUFTLEVBQUUsT0FBWTtJQUN4RCxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTVDLHNDQUFzQztJQUN0QyxNQUFNLFNBQVMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTNCLHFFQUFxRTtJQUNyRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUMzQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsR0FBRyxDQUFDLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBRXZFLDhDQUE4QztJQUM5QyxPQUFPLElBQUksQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRTtRQUNsQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQzVCLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7S0FDNUI7SUFFRCx1QkFBdUI7SUFDdkIsT0FBTyxLQUFLLENBQUMsTUFBTSxFQUFFO1FBQ25CLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7S0FDN0I7SUFFRCxzQkFBc0I7SUFDdEIsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ2xCLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7S0FDNUI7SUFFRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRWxlbWVudFJlZiwgSW5qZWN0YWJsZSwgTmdab25lLCBPbkRlc3Ryb3ksIE9wdGlvbmFsLCBWaWV3Q29udGFpbmVyUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBDb25uZWN0aW9uUG9zaXRpb25QYWlyLFxuICBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3ksXG4gIEhvcml6b250YWxDb25uZWN0aW9uUG9zLFxuICBPdmVybGF5LFxuICBPdmVybGF5Q29uZmlnLFxuICBPdmVybGF5UmVmLFxuICBTY3JvbGxTdHJhdGVneSxcbiAgVmVydGljYWxDb25uZWN0aW9uUG9zXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcbmltcG9ydCB7IERpcmVjdGlvbmFsaXR5LCBEaXJlY3Rpb24gfSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQgeyBFU0NBUEUgfSBmcm9tICdAYW5ndWxhci9jZGsva2V5Y29kZXMnO1xuaW1wb3J0IHsgVGVtcGxhdGVQb3J0YWwgfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcbmltcG9ydCB7IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCwgdGFrZSwgZmlsdGVyLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFNhdFBvcG92ZXIgfSBmcm9tICcuL3BvcG92ZXIuY29tcG9uZW50JztcbmltcG9ydCB7XG4gIFNhdFBvcG92ZXJIb3Jpem9udGFsQWxpZ24sXG4gIFNhdFBvcG92ZXJWZXJ0aWNhbEFsaWduLFxuICBTYXRQb3BvdmVyU2Nyb2xsU3RyYXRlZ3ksXG4gIFNhdFBvcG92ZXJPcGVuT3B0aW9uc1xufSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIHByb3ZpZGVkIGJ5IHRoZSBwb3BvdmVyIGZvciB0aGUgYW5jaG9yaW5nIHNlcnZpY2VcbiAqIHRvIGJ1aWxkIHRoZSBjb3JyZWN0IG92ZXJsYXkgY29uZmlnLlxuICovXG5pbnRlcmZhY2UgUG9wb3ZlckNvbmZpZyB7XG4gIGhvcml6b250YWxBbGlnbjogU2F0UG9wb3Zlckhvcml6b250YWxBbGlnbjtcbiAgdmVydGljYWxBbGlnbjogU2F0UG9wb3ZlclZlcnRpY2FsQWxpZ247XG4gIGhhc0JhY2tkcm9wOiBib29sZWFuO1xuICBiYWNrZHJvcENsYXNzOiBzdHJpbmc7XG4gIHNjcm9sbFN0cmF0ZWd5OiBTYXRQb3BvdmVyU2Nyb2xsU3RyYXRlZ3k7XG4gIGZvcmNlQWxpZ25tZW50OiBib29sZWFuO1xuICBsb2NrQWxpZ25tZW50OiBib29sZWFuO1xuICBwYW5lbENsYXNzOiBzdHJpbmcgfCBzdHJpbmdbXTtcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFNhdFBvcG92ZXJBbmNob3JpbmdTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHBvcG92ZXIgaXMgb3BlbmVkLiAqL1xuICBwb3BvdmVyT3BlbmVkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKiogRW1pdHMgd2hlbiB0aGUgcG9wb3ZlciBpcyBjbG9zZWQuICovXG4gIHBvcG92ZXJDbG9zZWQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIG92ZXJsYXkgY29udGFpbmluZyB0aGUgcG9wb3ZlciBjb21wb25lbnQuICovXG4gIF9vdmVybGF5UmVmOiBPdmVybGF5UmVmO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIHRhcmdldCBwb3BvdmVyLiAqL1xuICBwcml2YXRlIF9wb3BvdmVyOiBTYXRQb3BvdmVyO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIHZpZXcgY29udGFpbmVyIGZvciB0aGUgcG9wb3ZlciB0ZW1wbGF0ZS4gKi9cbiAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZjtcblxuICAvKiogUmVmZXJlbmNlIHRvIHRoZSBhbmNob3IgZWxlbWVudC4gKi9cbiAgcHJpdmF0ZSBfYW5jaG9yOiBIVE1MRWxlbWVudDtcblxuICAvKiogUmVmZXJlbmNlIHRvIGEgdGVtcGxhdGUgcG9ydGFsIHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgYmUgYXR0YWNoZWQuICovXG4gIHByaXZhdGUgX3BvcnRhbDogVGVtcGxhdGVQb3J0YWw8YW55PjtcblxuICAvKiogU2luZ2xlIHN1YnNjcmlwdGlvbiB0byBub3RpZmljYXRpb25zIHNlcnZpY2UgZXZlbnRzLiAqL1xuICBwcml2YXRlIF9ub3RpZmljYXRpb25zU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgLyoqIFNpbmdsZSBzdWJzY3JpcHRpb24gdG8gcG9zaXRpb24gY2hhbmdlcy4gKi9cbiAgcHJpdmF0ZSBfcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcblxuICAvKiogV2hldGhlciB0aGUgcG9wb3ZlciBpcyBwcmVzZW50bHkgb3Blbi4gKi9cbiAgcHJpdmF0ZSBfcG9wb3Zlck9wZW4gPSBmYWxzZTtcblxuICAvKiogRW1pdHMgd2hlbiB0aGUgc2VydmljZSBpcyBkZXN0cm95ZWQuICovXG4gIHByaXZhdGUgX29uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfb3ZlcmxheTogT3ZlcmxheSwgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUsIEBPcHRpb25hbCgpIHByaXZhdGUgX2RpcjogRGlyZWN0aW9uYWxpdHkpIHt9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgLy8gRGVzdHJveSBwb3BvdmVyIGJlZm9yZSB0ZXJtaW5hdGluZyBzdWJzY3JpcHRpb25zIHNvIHRoYXQgYW55IHJlc3VsdGluZ1xuICAgIC8vIGRldGFjaG1lbnRzIHVwZGF0ZSAnY2xvc2VkIHN0YXRlJ1xuICAgIHRoaXMuX2Rlc3Ryb3lQb3BvdmVyKCk7XG5cbiAgICAvLyBUZXJtaW5hdGUgc3Vic2NyaXB0aW9uc1xuICAgIGlmICh0aGlzLl9ub3RpZmljYXRpb25zU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9ub3RpZmljYXRpb25zU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9wb3NpdGlvbkNoYW5nZVN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5fcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICB0aGlzLl9vbkRlc3Ryb3kuY29tcGxldGUoKTtcblxuICAgIHRoaXMucG9wb3Zlck9wZW5lZC5jb21wbGV0ZSgpO1xuICAgIHRoaXMucG9wb3ZlckNsb3NlZC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgLyoqIEFuY2hvciBhIHBvcG92ZXIgaW5zdGFuY2UgdG8gYSB2aWV3IGFuZCBjb25uZWN0aW9uIGVsZW1lbnQuICovXG4gIGFuY2hvcihwb3BvdmVyOiBTYXRQb3BvdmVyLCB2aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLCBhbmNob3I6IEVsZW1lbnRSZWYgfCBIVE1MRWxlbWVudCk6IHZvaWQge1xuICAgIC8vIElmIHdlJ3JlIGp1c3QgY2hhbmdpbmcgdGhlIGFuY2hvciBlbGVtZW50IGFuZCB0aGUgb3ZlcmxheVJlZiBhbHJlYWR5IGV4aXN0cyxcbiAgICAvLyBzaW1wbHkgdXBkYXRlIHRoZSBleGlzdGluZyBfb3ZlcmxheVJlZidzIGFuY2hvci5cbiAgICBpZiAodGhpcy5fcG9wb3ZlciA9PT0gcG9wb3ZlciAmJiB0aGlzLl92aWV3Q29udGFpbmVyUmVmID09PSB2aWV3Q29udGFpbmVyUmVmICYmIHRoaXMuX292ZXJsYXlSZWYpIHtcbiAgICAgIHRoaXMuX2FuY2hvciA9IGFuY2hvciBpbnN0YW5jZW9mIEVsZW1lbnRSZWYgPyBhbmNob3IubmF0aXZlRWxlbWVudCA6IGFuY2hvcjtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuX292ZXJsYXlSZWYuZ2V0Q29uZmlnKCk7XG4gICAgICBjb25zdCBzdHJhdGVneSA9IGNvbmZpZy5wb3NpdGlvblN0cmF0ZWd5IGFzIEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneTtcbiAgICAgIHN0cmF0ZWd5LnNldE9yaWdpbih0aGlzLl9hbmNob3IpO1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZi51cGRhdGVQb3NpdGlvbigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIERlc3Ryb3kgYW55IHByZXZpb3VzIHBvcG92ZXJzXG4gICAgdGhpcy5fZGVzdHJveVBvcG92ZXIoKTtcblxuICAgIC8vIEFzc2lnbiBsb2NhbCByZWZzXG4gICAgdGhpcy5fcG9wb3ZlciA9IHBvcG92ZXI7XG4gICAgdGhpcy5fdmlld0NvbnRhaW5lclJlZiA9IHZpZXdDb250YWluZXJSZWY7XG4gICAgdGhpcy5fYW5jaG9yID0gYW5jaG9yIGluc3RhbmNlb2YgRWxlbWVudFJlZiA/IGFuY2hvci5uYXRpdmVFbGVtZW50IDogYW5jaG9yO1xuICB9XG5cbiAgLyoqIEdldHMgd2hldGhlciB0aGUgcG9wb3ZlciBpcyBwcmVzZW50bHkgb3Blbi4gKi9cbiAgaXNQb3BvdmVyT3BlbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fcG9wb3Zlck9wZW47XG4gIH1cblxuICAvKiogVG9nZ2xlcyB0aGUgcG9wb3ZlciBiZXR3ZWVuIHRoZSBvcGVuIGFuZCBjbG9zZWQgc3RhdGVzLiAqL1xuICB0b2dnbGVQb3BvdmVyKCk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLl9wb3BvdmVyT3BlbiA/IHRoaXMuY2xvc2VQb3BvdmVyKCkgOiB0aGlzLm9wZW5Qb3BvdmVyKCk7XG4gIH1cblxuICAvKiogT3BlbnMgdGhlIHBvcG92ZXIuICovXG4gIG9wZW5Qb3BvdmVyKG9wdGlvbnM6IFNhdFBvcG92ZXJPcGVuT3B0aW9ucyA9IHt9KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9wb3BvdmVyT3Blbikge1xuICAgICAgdGhpcy5fYXBwbHlPcGVuT3B0aW9ucyhvcHRpb25zKTtcbiAgICAgIHRoaXMuX2NyZWF0ZU92ZXJsYXkoKTtcbiAgICAgIHRoaXMuX3N1YnNjcmliZVRvQmFja2Ryb3AoKTtcbiAgICAgIHRoaXMuX3N1YnNjcmliZVRvRXNjYXBlKCk7XG4gICAgICB0aGlzLl9zdWJzY3JpYmVUb0RldGFjaG1lbnRzKCk7XG4gICAgICB0aGlzLl9zYXZlT3BlbmVkU3RhdGUoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2xvc2VzIHRoZSBwb3BvdmVyLiAqL1xuICBjbG9zZVBvcG92ZXIodmFsdWU/OiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgdGhpcy5fc2F2ZUNsb3NlZFN0YXRlKHZhbHVlKTtcbiAgICAgIHRoaXMuX292ZXJsYXlSZWYuZGV0YWNoKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFRPRE86IGltcGxlbWVudCB3aGVuIHRoZSBvdmVybGF5J3MgcG9zaXRpb24gY2FuIGJlIGR5bmFtaWNhbGx5IGNoYW5nZWQgKi9cbiAgcmVwb3NpdGlvblBvcG92ZXIoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVQb3BvdmVyQ29uZmlnKCk7XG4gIH1cblxuICAvKiogVE9ETzogd2hlbiB0aGUgb3ZlcmxheSdzIHBvc2l0aW9uIGNhbiBiZSBkeW5hbWljYWxseSBjaGFuZ2VkLCBkbyBub3QgZGVzdHJveSAqL1xuICB1cGRhdGVQb3BvdmVyQ29uZmlnKCk6IHZvaWQge1xuICAgIHRoaXMuX2Rlc3Ryb3lQb3BvdmVyT25jZUNsb3NlZCgpO1xuICB9XG5cbiAgLyoqIFJlYWxpZ24gdGhlIHBvcG92ZXIgdG8gdGhlIGFuY2hvci4gKi9cbiAgcmVhbGlnblBvcG92ZXJUb0FuY2hvcigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgY29uc3QgY29uZmlnID0gdGhpcy5fb3ZlcmxheVJlZi5nZXRDb25maWcoKTtcbiAgICAgIGNvbnN0IHN0cmF0ZWd5ID0gY29uZmlnLnBvc2l0aW9uU3RyYXRlZ3kgYXMgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5O1xuICAgICAgc3RyYXRlZ3kucmVhcHBseUxhc3RQb3NpdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBHZXQgYSByZWZlcmVuY2UgdG8gdGhlIGFuY2hvciBlbGVtZW50LiAqL1xuICBnZXRBbmNob3JFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5fYW5jaG9yO1xuICB9XG5cbiAgLyoqIEFwcGx5IGJlaGF2aW9yIHByb3BlcnRpZXMgb24gdGhlIHBvcG92ZXIgYmFzZWQgb24gdGhlIG9wZW4gb3B0aW9ucy4gKi9cbiAgcHJpdmF0ZSBfYXBwbHlPcGVuT3B0aW9ucyhvcHRpb25zOiBTYXRQb3BvdmVyT3Blbk9wdGlvbnMpOiB2b2lkIHtcbiAgICAvLyBPbmx5IG92ZXJyaWRlIHJlc3RvcmVGb2N1cyBhcyBgZmFsc2VgIGlmIHRoZSBvcHRpb24gaXMgZXhwbGljaXRseSBgZmFsc2VgXG4gICAgY29uc3QgcmVzdG9yZUZvY3VzID0gb3B0aW9ucy5yZXN0b3JlRm9jdXMgIT09IGZhbHNlO1xuICAgIHRoaXMuX3BvcG92ZXIuX3Jlc3RvcmVGb2N1c092ZXJyaWRlID0gcmVzdG9yZUZvY3VzO1xuXG4gICAgLy8gT25seSBvdmVycmlkZSBhdXRvRm9jdXMgYXMgYGZhbHNlYCBpZiB0aGUgb3B0aW9uIGlzIGV4cGxpY2l0bHkgYGZhbHNlYFxuICAgIGNvbnN0IGF1dG9Gb2N1cyA9IG9wdGlvbnMuYXV0b0ZvY3VzICE9PSBmYWxzZTtcbiAgICB0aGlzLl9wb3BvdmVyLl9hdXRvRm9jdXNPdmVycmlkZSA9IGF1dG9Gb2N1cztcbiAgfVxuXG4gIC8qKiBDcmVhdGUgYW4gb3ZlcmxheSB0byBiZSBhdHRhY2hlZCB0byB0aGUgcG9ydGFsLiAqL1xuICBwcml2YXRlIF9jcmVhdGVPdmVybGF5KCk6IE92ZXJsYXlSZWYge1xuICAgIC8vIENyZWF0ZSBvdmVybGF5IGlmIGl0IGRvZXNuJ3QgeWV0IGV4aXN0XG4gICAgaWYgKCF0aGlzLl9vdmVybGF5UmVmKSB7XG4gICAgICB0aGlzLl9wb3J0YWwgPSBuZXcgVGVtcGxhdGVQb3J0YWwodGhpcy5fcG9wb3Zlci5fdGVtcGxhdGVSZWYsIHRoaXMuX3ZpZXdDb250YWluZXJSZWYpO1xuXG4gICAgICBjb25zdCBwb3BvdmVyQ29uZmlnOiBQb3BvdmVyQ29uZmlnID0ge1xuICAgICAgICBob3Jpem9udGFsQWxpZ246IHRoaXMuX3BvcG92ZXIuaG9yaXpvbnRhbEFsaWduLFxuICAgICAgICB2ZXJ0aWNhbEFsaWduOiB0aGlzLl9wb3BvdmVyLnZlcnRpY2FsQWxpZ24sXG4gICAgICAgIGhhc0JhY2tkcm9wOiBjb2VyY2VCb29sZWFuUHJvcGVydHkodGhpcy5fcG9wb3Zlci5oYXNCYWNrZHJvcCksXG4gICAgICAgIGJhY2tkcm9wQ2xhc3M6IHRoaXMuX3BvcG92ZXIuYmFja2Ryb3BDbGFzcyxcbiAgICAgICAgc2Nyb2xsU3RyYXRlZ3k6IHRoaXMuX3BvcG92ZXIuc2Nyb2xsU3RyYXRlZ3ksXG4gICAgICAgIGZvcmNlQWxpZ25tZW50OiBjb2VyY2VCb29sZWFuUHJvcGVydHkodGhpcy5fcG9wb3Zlci5mb3JjZUFsaWdubWVudCksXG4gICAgICAgIGxvY2tBbGlnbm1lbnQ6IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh0aGlzLl9wb3BvdmVyLmxvY2tBbGlnbm1lbnQpLFxuICAgICAgICBwYW5lbENsYXNzOiB0aGlzLl9wb3BvdmVyLnBhbmVsQ2xhc3NcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG92ZXJsYXlDb25maWcgPSB0aGlzLl9nZXRPdmVybGF5Q29uZmlnKHBvcG92ZXJDb25maWcsIHRoaXMuX2FuY2hvcik7XG5cbiAgICAgIHRoaXMuX3N1YnNjcmliZVRvUG9zaXRpb25DaGFuZ2VzKG92ZXJsYXlDb25maWcucG9zaXRpb25TdHJhdGVneSBhcyBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kpO1xuXG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gdGhpcy5fb3ZlcmxheS5jcmVhdGUob3ZlcmxheUNvbmZpZyk7XG4gICAgfVxuXG4gICAgLy8gQWN0dWFsbHkgb3BlbiB0aGUgcG9wb3ZlclxuICAgIHRoaXMuX292ZXJsYXlSZWYuYXR0YWNoKHRoaXMuX3BvcnRhbCk7XG4gICAgcmV0dXJuIHRoaXMuX292ZXJsYXlSZWY7XG4gIH1cblxuICAvKiogUmVtb3ZlcyB0aGUgcG9wb3ZlciBmcm9tIHRoZSBET00uIERvZXMgTk9UIHVwZGF0ZSBvcGVuIHN0YXRlLiAqL1xuICBwcml2YXRlIF9kZXN0cm95UG9wb3ZlcigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZi5kaXNwb3NlKCk7XG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVzdHJveXMgdGhlIHBvcG92ZXIgaW1tZWRpYXRlbHkgaWYgaXQgaXMgY2xvc2VkLCBvciB3YWl0cyB1bnRpbCBpdFxuICAgKiBoYXMgYmVlbiBjbG9zZWQgdG8gZGVzdHJveSBpdC5cbiAgICovXG4gIHByaXZhdGUgX2Rlc3Ryb3lQb3BvdmVyT25jZUNsb3NlZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc1BvcG92ZXJPcGVuKCkgJiYgdGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZlxuICAgICAgICAuZGV0YWNobWVudHMoKVxuICAgICAgICAucGlwZSh0YWtlKDEpLCB0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9kZXN0cm95UG9wb3ZlcigpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZGVzdHJveVBvcG92ZXIoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2xvc2UgcG9wb3ZlciB3aGVuIGJhY2tkcm9wIGlzIGNsaWNrZWQuICovXG4gIHByaXZhdGUgX3N1YnNjcmliZVRvQmFja2Ryb3AoKTogdm9pZCB7XG4gICAgdGhpcy5fb3ZlcmxheVJlZlxuICAgICAgLmJhY2tkcm9wQ2xpY2soKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgoKSA9PiB0aGlzLl9wb3BvdmVyLmJhY2tkcm9wQ2xpY2tlZC5lbWl0KCkpLFxuICAgICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5fcG9wb3Zlci5pbnRlcmFjdGl2ZUNsb3NlKSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMucG9wb3ZlckNsb3NlZCksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuY2xvc2VQb3BvdmVyKCkpO1xuICB9XG5cbiAgLyoqIENsb3NlIHBvcG92ZXIgd2hlbiBlc2NhcGUga2V5ZG93biBldmVudCBvY2N1cnMuICovXG4gIHByaXZhdGUgX3N1YnNjcmliZVRvRXNjYXBlKCk6IHZvaWQge1xuICAgIHRoaXMuX292ZXJsYXlSZWZcbiAgICAgIC5rZXlkb3duRXZlbnRzKClcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKGV2ZW50KSA9PiB0aGlzLl9wb3BvdmVyLm92ZXJsYXlLZXlkb3duLmVtaXQoZXZlbnQpKSxcbiAgICAgICAgZmlsdGVyKChldmVudCkgPT4gZXZlbnQua2V5Q29kZSA9PT0gRVNDQVBFKSxcbiAgICAgICAgZmlsdGVyKCgpID0+IHRoaXMuX3BvcG92ZXIuaW50ZXJhY3RpdmVDbG9zZSksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLnBvcG92ZXJDbG9zZWQpLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmNsb3NlUG9wb3ZlcigpKTtcbiAgfVxuXG4gIC8qKiBTZXQgc3RhdGUgYmFjayB0byBjbG9zZWQgd2hlbiBkZXRhY2hlZC4gKi9cbiAgcHJpdmF0ZSBfc3Vic2NyaWJlVG9EZXRhY2htZW50cygpOiB2b2lkIHtcbiAgICB0aGlzLl9vdmVybGF5UmVmXG4gICAgICAuZGV0YWNobWVudHMoKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuX3NhdmVDbG9zZWRTdGF0ZSgpKTtcbiAgfVxuXG4gIC8qKiBTYXZlIHRoZSBvcGVuZWQgc3RhdGUgb2YgdGhlIHBvcG92ZXIgYW5kIGVtaXQuICovXG4gIHByaXZhdGUgX3NhdmVPcGVuZWRTdGF0ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX3BvcG92ZXJPcGVuKSB7XG4gICAgICB0aGlzLl9wb3BvdmVyLl9zdGF0ZSA9ICdlbnRlcic7XG4gICAgICB0aGlzLl9wb3BvdmVyLl9vcGVuID0gdGhpcy5fcG9wb3Zlck9wZW4gPSB0cnVlO1xuXG4gICAgICB0aGlzLnBvcG92ZXJPcGVuZWQubmV4dCgpO1xuICAgICAgdGhpcy5fcG9wb3Zlci5vcGVuZWQuZW1pdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBTYXZlIHRoZSBjbG9zZWQgc3RhdGUgb2YgdGhlIHBvcG92ZXIgYW5kIGVtaXQuICovXG4gIHByaXZhdGUgX3NhdmVDbG9zZWRTdGF0ZSh2YWx1ZT86IGFueSk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9wb3BvdmVyT3Blbikge1xuICAgICAgdGhpcy5fcG9wb3Zlci5fb3BlbiA9IHRoaXMuX3BvcG92ZXJPcGVuID0gZmFsc2U7XG5cbiAgICAgIHRoaXMuX3BvcG92ZXIuX3N0YXJ0RXhpdEFuaW1hdGlvbigpO1xuICAgICAgdGhpcy5wb3BvdmVyQ2xvc2VkLm5leHQodmFsdWUpO1xuICAgICAgdGhpcy5fcG9wb3Zlci5jbG9zZWQuZW1pdCh2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEdldHMgdGhlIHRleHQgZGlyZWN0aW9uIG9mIHRoZSBjb250YWluaW5nIGFwcC4gKi9cbiAgcHJpdmF0ZSBfZ2V0RGlyZWN0aW9uKCk6IERpcmVjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX2RpciAmJiB0aGlzLl9kaXIudmFsdWUgPT09ICdydGwnID8gJ3J0bCcgOiAnbHRyJztcbiAgfVxuXG4gIC8qKiBDcmVhdGUgYW5kIHJldHVybiBhIGNvbmZpZyBmb3IgY3JlYXRpbmcgdGhlIG92ZXJsYXkuICovXG4gIHByaXZhdGUgX2dldE92ZXJsYXlDb25maWcoY29uZmlnOiBQb3BvdmVyQ29uZmlnLCBhbmNob3I6IEhUTUxFbGVtZW50KTogT3ZlcmxheUNvbmZpZyB7XG4gICAgcmV0dXJuIG5ldyBPdmVybGF5Q29uZmlnKHtcbiAgICAgIHBvc2l0aW9uU3RyYXRlZ3k6IHRoaXMuX2dldFBvc2l0aW9uU3RyYXRlZ3koXG4gICAgICAgIGNvbmZpZy5ob3Jpem9udGFsQWxpZ24sXG4gICAgICAgIGNvbmZpZy52ZXJ0aWNhbEFsaWduLFxuICAgICAgICBjb25maWcuZm9yY2VBbGlnbm1lbnQsXG4gICAgICAgIGNvbmZpZy5sb2NrQWxpZ25tZW50LFxuICAgICAgICBhbmNob3JcbiAgICAgICksXG4gICAgICBoYXNCYWNrZHJvcDogY29uZmlnLmhhc0JhY2tkcm9wLFxuICAgICAgYmFja2Ryb3BDbGFzczogY29uZmlnLmJhY2tkcm9wQ2xhc3MgfHwgJ2Nkay1vdmVybGF5LXRyYW5zcGFyZW50LWJhY2tkcm9wJyxcbiAgICAgIHNjcm9sbFN0cmF0ZWd5OiB0aGlzLl9nZXRTY3JvbGxTdHJhdGVneUluc3RhbmNlKGNvbmZpZy5zY3JvbGxTdHJhdGVneSksXG4gICAgICBkaXJlY3Rpb246IHRoaXMuX2dldERpcmVjdGlvbigpLFxuICAgICAgcGFuZWxDbGFzczogY29uZmlnLnBhbmVsQ2xhc3NcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0ZW4gdG8gY2hhbmdlcyBpbiB0aGUgcG9zaXRpb24gb2YgdGhlIG92ZXJsYXkgYW5kIHNldCB0aGUgY29ycmVjdCBhbGlnbm1lbnQgY2xhc3NlcyxcbiAgICogZW5zdXJpbmcgdGhhdCB0aGUgYW5pbWF0aW9uIG9yaWdpbiBpcyBjb3JyZWN0LCBldmVuIHdpdGggYSBmYWxsYmFjayBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgX3N1YnNjcmliZVRvUG9zaXRpb25DaGFuZ2VzKHBvc2l0aW9uOiBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuX3Bvc2l0aW9uQ2hhbmdlU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb24gPSBwb3NpdGlvbi5wb3NpdGlvbkNoYW5nZXMucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKChjaGFuZ2UpID0+IHtcbiAgICAgIC8vIFBvc2l0aW9uIGNoYW5nZXMgbWF5IG9jY3VyIG91dHNpZGUgdGhlIEFuZ3VsYXIgem9uZVxuICAgICAgdGhpcy5fbmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgIHRoaXMuX3BvcG92ZXIuX3NldEFsaWdubWVudENsYXNzZXMoXG4gICAgICAgICAgZ2V0SG9yaXpvbnRhbFBvcG92ZXJBbGlnbm1lbnQoY2hhbmdlLmNvbm5lY3Rpb25QYWlyLm92ZXJsYXlYKSxcbiAgICAgICAgICBnZXRWZXJ0aWNhbFBvcG92ZXJBbGlnbm1lbnQoY2hhbmdlLmNvbm5lY3Rpb25QYWlyLm92ZXJsYXlZKVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogTWFwIGEgc2Nyb2xsIHN0cmF0ZWd5IHN0cmluZyB0eXBlIHRvIGFuIGluc3RhbmNlIG9mIGEgc2Nyb2xsIHN0cmF0ZWd5LiAqL1xuICBwcml2YXRlIF9nZXRTY3JvbGxTdHJhdGVneUluc3RhbmNlKHN0cmF0ZWd5OiBTYXRQb3BvdmVyU2Nyb2xsU3RyYXRlZ3kpOiBTY3JvbGxTdHJhdGVneSB7XG4gICAgc3dpdGNoIChzdHJhdGVneSkge1xuICAgICAgY2FzZSAnYmxvY2snOlxuICAgICAgICByZXR1cm4gdGhpcy5fb3ZlcmxheS5zY3JvbGxTdHJhdGVnaWVzLmJsb2NrKCk7XG4gICAgICBjYXNlICdyZXBvc2l0aW9uJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuX292ZXJsYXkuc2Nyb2xsU3RyYXRlZ2llcy5yZXBvc2l0aW9uKCk7XG4gICAgICBjYXNlICdjbG9zZSc6XG4gICAgICAgIHJldHVybiB0aGlzLl9vdmVybGF5LnNjcm9sbFN0cmF0ZWdpZXMuY2xvc2UoKTtcbiAgICAgIGNhc2UgJ25vb3AnOlxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHRoaXMuX292ZXJsYXkuc2Nyb2xsU3RyYXRlZ2llcy5ub29wKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIENyZWF0ZSBhbmQgcmV0dXJuIGEgcG9zaXRpb24gc3RyYXRlZ3kgYmFzZWQgb24gY29uZmlnIHByb3ZpZGVkIHRvIHRoZSBjb21wb25lbnQgaW5zdGFuY2UuICovXG4gIHByaXZhdGUgX2dldFBvc2l0aW9uU3RyYXRlZ3koXG4gICAgaG9yaXpvbnRhbFRhcmdldDogU2F0UG9wb3Zlckhvcml6b250YWxBbGlnbixcbiAgICB2ZXJ0aWNhbFRhcmdldDogU2F0UG9wb3ZlclZlcnRpY2FsQWxpZ24sXG4gICAgZm9yY2VBbGlnbm1lbnQ6IGJvb2xlYW4sXG4gICAgbG9ja0FsaWdubWVudDogYm9vbGVhbixcbiAgICBhbmNob3I6IEhUTUxFbGVtZW50XG4gICk6IEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneSB7XG4gICAgLy8gQXR0YWNoIHRoZSBvdmVybGF5IGF0IHRoZSBwcmVmZXJyZWQgcG9zaXRpb25cbiAgICBjb25zdCB0YXJnZXRQb3NpdGlvbiA9IGdldFBvc2l0aW9uKGhvcml6b250YWxUYXJnZXQsIHZlcnRpY2FsVGFyZ2V0KTtcbiAgICBjb25zdCBwb3NpdGlvbnMgPSBbdGFyZ2V0UG9zaXRpb25dO1xuXG4gICAgY29uc3Qgc3RyYXRlZ3kgPSB0aGlzLl9vdmVybGF5XG4gICAgICAucG9zaXRpb24oKVxuICAgICAgLmZsZXhpYmxlQ29ubmVjdGVkVG8oYW5jaG9yKVxuICAgICAgLndpdGhGbGV4aWJsZURpbWVuc2lvbnMoZmFsc2UpXG4gICAgICAud2l0aFB1c2goZmFsc2UpXG4gICAgICAud2l0aFZpZXdwb3J0TWFyZ2luKDApXG4gICAgICAud2l0aExvY2tlZFBvc2l0aW9uKGxvY2tBbGlnbm1lbnQ