@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
453 lines • 67.2 kB
JavaScript
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