@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1,603 lines • 222 kB
JavaScript
import { __decorate, __extends, __metadata } from "tslib";
import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, DoCheck, EmbeddedViewRef, EventEmitter, Input, IterableChanges, IterableDiffer, IterableDiffers, NgModule, NgZone, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, TemplateRef, TrackByFunction, ViewContainerRef, ViewRef, AfterViewInit } from '@angular/core';
import { DisplayContainerComponent } from './display.container';
import { HVirtualHelperComponent } from './horizontal.virtual.helper.component';
import { VirtualHelperComponent } from './virtual.helper.component';
import { IgxScrollInertiaModule } from './../scroll-inertia/scroll_inertia.directive';
import { IgxForOfSyncService, IgxForOfScrollSyncService } from './for_of.sync.service';
import { Subject } from 'rxjs';
import { takeUntil, filter, throttleTime, first } from 'rxjs/operators';
import ResizeObserver from 'resize-observer-polyfill';
import { VirtualHelperBaseDirective } from './base.helper.component';
/**
* @publicApi
*/
var IgxForOfContext = /** @class */ (function () {
function IgxForOfContext($implicit, index, count) {
this.$implicit = $implicit;
this.index = index;
this.count = count;
}
Object.defineProperty(IgxForOfContext.prototype, "first", {
/**
* A function that returns whether the element is the first or not
*/
get: function () { return this.index === 0; },
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfContext.prototype, "last", {
/**
* A function that returns whether the element is the last or not
*/
get: function () { return this.index === this.count - 1; },
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfContext.prototype, "even", {
/**
* A function that returns whether the element is even or not
*/
get: function () { return this.index % 2 === 0; },
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfContext.prototype, "odd", {
/**
* A function that returns whether the element is odd or not
*/
get: function () { return !this.even; },
enumerable: true,
configurable: true
});
return IgxForOfContext;
}());
export { IgxForOfContext };
var IgxForOfDirective = /** @class */ (function () {
function IgxForOfDirective(_viewContainer, _template, _differs, resolver, cdr, _zone, syncScrollService) {
this._viewContainer = _viewContainer;
this._template = _template;
this._differs = _differs;
this.resolver = resolver;
this.cdr = cdr;
this._zone = _zone;
this.syncScrollService = syncScrollService;
/**
* An @Input property that specifies the scroll orientation.
* Scroll orientation can be "vertical" or "horizontal".
* ```html
* <ng-template igxFor let-item [igxForOf]="data" [igxForScrollOrientation]="'horizontal'"></ng-template>
* ```
*/
this.igxForScrollOrientation = 'vertical';
/**
* The current state of the directive. It contains `startIndex` and `chunkSize`.
* state.startIndex - The index of the item at which the current visible chunk begins.
* state.chunkSize - The number of items the current visible chunk holds.
* These options can be used when implementing remote virtualization as they provide the necessary state information.
* ```typescript
* const gridState = this.parentVirtDir.state;
* ```
*/
this.state = {
startIndex: 0,
chunkSize: 0
};
/**
* The total count of the virtual data items, when using remote service.
* ```typescript
* this.parentVirtDir.totalItemCount = data.Count;
* ```
*/
this.totalItemCount = null;
/**
* An event that is emitted after a new chunk has been loaded.
* ```html
* <ng-template igxFor [igxForOf]="data" [igxForScrollOrientation]="'horizontal'" (onChunkLoad)="chunkLoad($event)"></ng-template>
* ```
* ```typescript
* chunkLoad(e){
* alert("chunk loaded!");
* }
* ```
*/
this.onChunkLoad = new EventEmitter();
/**
* @hidden @internal
* An event that is emitted when scrollbar visibility has changed.
*/
this.onScrollbarVisibilityChanged = new EventEmitter();
/**
* An event that is emitted after the rendered content size of the igxForOf has been changed.
*/
this.onContentSizeChange = new EventEmitter();
/**
* An event that is emitted after data has been changed.
* ```html
* <ng-template igxFor [igxForOf]="data" [igxForScrollOrientation]="'horizontal'" (onDataChanged)="dataChanged($event)"></ng-template>
* ```
* ```typescript
* dataChanged(e){
* alert("data changed!");
* }
* ```
*/
this.onDataChanged = new EventEmitter();
this.onBeforeViewDestroyed = new EventEmitter();
/**
* An event that is emitted on chunk loading to emit the current state information - startIndex, endIndex, totalCount.
* Can be used for implementing remote load on demand for the igxFor data.
* ```html
* <ng-template igxFor [igxForOf]="data" [igxForScrollOrientation]="'horizontal'" (onChunkPreload)="chunkPreload($event)"></ng-template>
* ```
* ```typescript
* chunkPreload(e){
* alert("chunk is loading!");
* }
* ```
*/
this.onChunkPreload = new EventEmitter();
this._sizesCache = [];
this._differ = null;
this.heightCache = [];
this.MAX_PERF_SCROLL_DIFF = 4;
/** Height that is being virtualized. */
this._virtHeight = 0;
/**
* Ratio for height that's being virtualizaed and the one visible
* If _virtHeightRatio = 1, the visible height and the virtualized are the same, also _maxHeight > _virtHeight.
*/
this._virtHeightRatio = 1;
/** Internal track for scroll top that is being virtualized */
this._virtScrollTop = 0;
/** If the next onScroll event is triggered due to internal setting of scrollTop */
this._bScrollInternal = false;
// End properties related to virtual height handling
this._embeddedViews = [];
this.contentResizeNotify = new Subject();
/**
* @hidden
*/
this.destroy$ = new Subject();
}
Object.defineProperty(IgxForOfDirective.prototype, "displayContainer", {
get: function () {
return this.dc.instance._viewContainer.element.nativeElement;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfDirective.prototype, "virtualHelper", {
get: function () {
return this.scrollComponent.nativeElement;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfDirective.prototype, "sizesCache", {
get: function () {
return this._sizesCache;
},
set: function (value) {
this._sizesCache = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfDirective.prototype, "_isScrolledToBottom", {
get: function () {
if (!this.getScroll()) {
return true;
}
var scrollHeight = this.getScroll().scrollHeight;
// Use === and not >= because `scrollTop + container size` can't be bigger than `scrollHeight`, unless something isn't updated.
// Also use Math.round because Chrome has some inconsistencies and `scrollTop + container` can be float when zooming the page.
return Math.round(this.getScroll().scrollTop + this.igxForContainerSize) === scrollHeight;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfDirective.prototype, "_isAtBottomIndex", {
get: function () {
return this.igxForOf && this.state.startIndex + this.state.chunkSize > this.igxForOf.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfDirective.prototype, "isRemote", {
/**
* @hidden
*/
get: function () {
return this.totalItemCount !== null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxForOfDirective.prototype, "scrollPosition", {
/**
*
* Gets/Sets the scroll position.
* ```typescript
* const position = directive.scrollPosition;
* directive.scrollPosition = value;
* ```
*/
get: function () {
return this.scrollComponent.scrollAmount;
},
set: function (val) {
if (val === this.scrollComponent.scrollAmount) {
return;
}
if (this.igxForScrollOrientation === 'horizontal' && this.scrollComponent) {
this.scrollComponent.nativeElement.scrollLeft = val;
}
else if (this.scrollComponent) {
this.scrollComponent.nativeElement.scrollTop = val;
}
},
enumerable: true,
configurable: true
});
/**
* @hidden
*/
IgxForOfDirective.prototype.removeScrollEventListeners = function () {
var _this = this;
if (this.igxForScrollOrientation === 'horizontal') {
this._zone.runOutsideAngular(function () {
return _this.scrollComponent.nativeElement.removeEventListener('scroll', _this.func);
});
}
else {
this._zone.runOutsideAngular(function () {
return _this.scrollComponent.nativeElement.removeEventListener('scroll', _this.verticalScrollHandler);
});
}
};
IgxForOfDirective.prototype.verticalScrollHandler = function (event) {
this.onScroll(event);
};
IgxForOfDirective.prototype.isScrollable = function () {
return this.scrollComponent.size > parseInt(this.igxForContainerSize, 10);
};
/**
* @hidden
*/
IgxForOfDirective.prototype.ngOnInit = function () {
var _this = this;
var totalSize = 0;
var vc = this.igxForScrollContainer ? this.igxForScrollContainer._viewContainer : this._viewContainer;
this.igxForSizePropName = this.igxForSizePropName || 'width';
var dcFactory = this.resolver.resolveComponentFactory(DisplayContainerComponent);
this.dc = this._viewContainer.createComponent(dcFactory, 0);
this.dc.instance.scrollDirection = this.igxForScrollOrientation;
if (typeof MSGesture === 'function') {
// On Edge and IE when scrolling on touch the page scroll instead of the grid.
this.dc.instance._viewContainer.element.nativeElement.style.touchAction = 'none';
}
if (this.igxForOf && this.igxForOf.length) {
totalSize = this.initSizesCache(this.igxForOf);
this.scrollComponent = this.syncScrollService.getScrollMaster(this.igxForScrollOrientation);
this.state.chunkSize = this._calculateChunkSize();
this.dc.instance.notVirtual = !(this.igxForContainerSize && this.state.chunkSize < this.igxForOf.length);
if (this.scrollComponent) {
this.state.startIndex = Math.min(this.getIndexAt(this.scrollPosition, this.sizesCache, 0), this.igxForOf.length - this.state.chunkSize);
}
for (var i = this.state.startIndex; i < this.state.startIndex + this.state.chunkSize &&
this.igxForOf[i] !== undefined; i++) {
var input = this.igxForOf[i];
var embeddedView = this.dc.instance._vcr.createEmbeddedView(this._template, new IgxForOfContext(input, this.getContextIndex(input), this.igxForOf.length));
this._embeddedViews.push(embeddedView);
}
}
if (this.igxForScrollOrientation === 'vertical') {
this.dc.instance._viewContainer.element.nativeElement.style.top = '0px';
var factory = this.resolver.resolveComponentFactory(VirtualHelperComponent);
this.scrollComponent = vc.createComponent(factory).instance;
this._maxHeight = this._calcMaxBrowserHeight();
this.scrollComponent.size = this.igxForOf ? this._calcHeight() : 0;
this.syncScrollService.setScrollMaster(this.igxForScrollOrientation, this.scrollComponent);
this._zone.runOutsideAngular(function () {
_this.verticalScrollHandler = _this.verticalScrollHandler.bind(_this);
_this.scrollComponent.nativeElement.addEventListener('scroll', _this.verticalScrollHandler);
_this.dc.instance.scrollContainer = _this.scrollComponent.nativeElement;
});
var destructor = takeUntil(this.destroy$);
this.contentResizeNotify.pipe(destructor, filter(function () { return _this.igxForContainerSize && _this.igxForOf && _this.igxForOf.length > 0; }), throttleTime(40))
.subscribe(function () {
_this._zone.runTask(function () {
_this.updateSizes();
});
});
}
if (this.igxForScrollOrientation === 'horizontal') {
this.func = function (evt) { _this.onHScroll(evt); };
this.scrollComponent = this.syncScrollService.getScrollMaster(this.igxForScrollOrientation);
if (!this.scrollComponent) {
var hvFactory = this.resolver.resolveComponentFactory(HVirtualHelperComponent);
this.scrollComponent = vc.createComponent(hvFactory).instance;
this.scrollComponent.size = totalSize;
this.syncScrollService.setScrollMaster(this.igxForScrollOrientation, this.scrollComponent);
this._zone.runOutsideAngular(function () {
_this.scrollComponent.nativeElement.addEventListener('scroll', _this.func);
_this.dc.instance.scrollContainer = _this.scrollComponent.nativeElement;
});
}
else {
this._zone.runOutsideAngular(function () {
_this.scrollComponent.nativeElement.addEventListener('scroll', _this.func);
_this.dc.instance.scrollContainer = _this.scrollComponent.nativeElement;
});
}
this._updateHScrollOffset();
}
};
IgxForOfDirective.prototype.ngAfterViewInit = function () {
var _this = this;
if (this.igxForScrollOrientation === 'vertical') {
this._zone.runOutsideAngular(function () {
_this.contentObserver = new ResizeObserver(function () { return _this.contentResizeNotify.next(); });
_this.contentObserver.observe(_this.dc.instance._viewContainer.element.nativeElement);
});
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype.ngOnDestroy = function () {
this.removeScrollEventListeners();
this.destroy$.next(true);
this.destroy$.complete();
if (this.contentObserver) {
this.contentObserver.disconnect();
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype.ngOnChanges = function (changes) {
var forOf = 'igxForOf';
if (forOf in changes) {
var value = changes[forOf].currentValue;
if (!this._differ && value) {
try {
this._differ = this._differs.find(value).create(this.igxForTrackBy);
}
catch (e) {
throw new Error("Cannot find a differ supporting object \"" + value + "\" of type \"" + getTypeNameForDebugging(value) + "\".\n NgFor only supports binding to Iterables such as Arrays.");
}
}
}
var defaultItemSize = 'igxForItemSize';
if (defaultItemSize in changes && !changes[defaultItemSize].firstChange &&
this.igxForScrollOrientation === 'vertical' && this.igxForOf) {
// handle default item size changed.
this.initSizesCache(this.igxForOf);
this._applyChanges();
}
var containerSize = 'igxForContainerSize';
if (containerSize in changes && !changes[containerSize].firstChange && this.igxForOf) {
this._recalcOnContainerChange(changes);
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype.ngDoCheck = function () {
var _this = this;
if (this._differ) {
var changes = this._differ.diff(this.igxForOf);
if (changes) {
// re-init cache.
if (!this.igxForOf) {
this.igxForOf = [];
}
this._updateSizeCache();
this._zone.run(function () {
_this._applyChanges();
_this.cdr.markForCheck();
_this._updateScrollOffset();
_this.onDataChanged.emit();
});
}
}
};
/**
* Shifts the scroll thumb position.
* ```typescript
* this.parentVirtDir.addScrollTop(5);
* ```
* @param addTop negative value to scroll up and positive to scroll down;
*/
IgxForOfDirective.prototype.addScrollTop = function (addTop) {
if (addTop === 0 && this.igxForScrollOrientation === 'horizontal') {
return false;
}
var originalVirtScrollTop = this._virtScrollTop;
var containerSize = parseInt(this.igxForContainerSize, 10);
var maxVirtScrollTop = this._virtHeight - containerSize;
this._bScrollInternal = true;
this._virtScrollTop += addTop;
this._virtScrollTop = this._virtScrollTop > 0 ?
(this._virtScrollTop < maxVirtScrollTop ? this._virtScrollTop : maxVirtScrollTop) :
0;
this.scrollPosition += addTop / this._virtHeightRatio;
if (Math.abs(addTop / this._virtHeightRatio) < 1) {
// Actual scroll delta that was added is smaller than 1 and onScroll handler doesn't trigger when scrolling < 1px
var scrollOffset = this.fixedUpdateAllElements(this._virtScrollTop);
// scrollOffset = scrollOffset !== parseInt(this.igxForItemSize, 10) ? scrollOffset : 0;
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
}
var maxRealScrollTop = this.scrollComponent.nativeElement.scrollHeight - containerSize;
if ((this._virtScrollTop > 0 && this.scrollPosition === 0) ||
(this._virtScrollTop < maxVirtScrollTop && this.scrollPosition === maxRealScrollTop)) {
// Actual scroll position is at the top or bottom, but virtual one is not at the top or bottom (there's more to scroll)
// Recalculate actual scroll position based on the virtual scroll.
this.scrollPosition = this._virtScrollTop / this._virtHeightRatio;
}
else if (this._virtScrollTop === 0 && this.scrollPosition > 0) {
// Actual scroll position is not at the top, but virtual scroll is. Just update the actual scroll
this.scrollPosition = 0;
}
else if (this._virtScrollTop === maxVirtScrollTop && this.scrollPosition < maxRealScrollTop) {
// Actual scroll position is not at the bottom, but virtual scroll is. Just update the acual scroll
this.scrollPosition = maxRealScrollTop;
}
return this._virtScrollTop !== originalVirtScrollTop;
};
/**
* Scrolls to the specified index.
* ```typescript
* this.parentVirtDir.scrollTo(5);
* ```
* @param index
*/
IgxForOfDirective.prototype.scrollTo = function (index) {
if (index < 0 || index > (this.isRemote ? this.totalItemCount : this.igxForOf.length) - 1) {
return;
}
var containerSize = parseInt(this.igxForContainerSize, 10);
var isPrevItem = index < this.state.startIndex || this.scrollPosition > this.sizesCache[index];
var nextScroll = isPrevItem ? this.sizesCache[index] : this.sizesCache[index + 1] - containerSize;
if (nextScroll < 0) {
return;
}
if (this.igxForScrollOrientation === 'horizontal') {
this.scrollPosition = nextScroll;
}
else {
var maxVirtScrollTop = this._virtHeight - containerSize;
if (nextScroll > maxVirtScrollTop) {
nextScroll = maxVirtScrollTop;
}
this._bScrollInternal = true;
this._virtScrollTop = nextScroll;
this.scrollPosition = this._virtScrollTop / this._virtHeightRatio;
this._adjustToIndex = !isPrevItem ? index : null;
}
};
/**
* Scrolls by one item into the appropriate next direction.
* For "horizontal" orientation that will be the right column and for "vertical" that is the lower row.
* ```typescript
* this.parentVirtDir.scrollNext();
* ```
*/
IgxForOfDirective.prototype.scrollNext = function () {
var scr = Math.ceil(this.scrollPosition);
var endIndex = this.getIndexAt(scr + parseInt(this.igxForContainerSize, 10), this.sizesCache, 0);
this.scrollTo(endIndex);
};
/**
* Scrolls by one item into the appropriate previous direction.
* For "horizontal" orientation that will be the left column and for "vertical" that is the upper row.
* ```typescript
* this.parentVirtDir.scrollPrev();
* ```
*/
IgxForOfDirective.prototype.scrollPrev = function () {
this.scrollTo(this.state.startIndex - 1);
};
/**
* Scrolls by one page into the appropriate next direction.
* For "horizontal" orientation that will be one view to the right and for "vertical" that is one view to the bottom.
* ```typescript
* this.parentVirtDir.scrollNextPage();
* ```
*/
IgxForOfDirective.prototype.scrollNextPage = function () {
if (this.igxForScrollOrientation === 'horizontal') {
this.scrollPosition += parseInt(this.igxForContainerSize, 10);
}
else {
this.addScrollTop(parseInt(this.igxForContainerSize, 10));
}
};
/**
* Scrolls by one page into the appropriate previous direction.
* For "horizontal" orientation that will be one view to the left and for "vertical" that is one view to the top.
* ```typescript
* this.parentVirtDir.scrollPrevPage();
* ```
*/
IgxForOfDirective.prototype.scrollPrevPage = function () {
if (this.igxForScrollOrientation === 'horizontal') {
this.scrollPosition -= parseInt(this.igxForContainerSize, 10);
}
else {
var containerSize = (parseInt(this.igxForContainerSize, 10));
this.addScrollTop(-containerSize);
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype.getColumnScrollLeft = function (colIndex) {
return this.sizesCache[colIndex];
};
/**
* Returns the total number of items that are fully visible.
* ```typescript
* this.parentVirtDir.getItemCountInView();
* ```
*/
IgxForOfDirective.prototype.getItemCountInView = function () {
var startIndex = this.getIndexAt(this.scrollPosition, this.sizesCache, 0);
if (this.scrollPosition - this.sizesCache[startIndex] > 0) {
// fisrt item is not fully in view
startIndex++;
}
var endIndex = this.getIndexAt(this.scrollPosition + parseInt(this.igxForContainerSize, 10), this.sizesCache, 0);
return endIndex - startIndex;
};
/**
* Returns a reference to the scrollbar DOM element.
* This is either a vertical or horizontal scrollbar depending on the specified igxForScrollOrientation.
* ```typescript
* dir.getScroll();
* ```
*/
IgxForOfDirective.prototype.getScroll = function () {
return this.scrollComponent.nativeElement;
};
/**
* Returns the size of the element at the specified index.
* ```typescript
* this.parentVirtDir.getSizeAt(1);
* ```
*/
IgxForOfDirective.prototype.getSizeAt = function (index) {
return this.sizesCache[index + 1] - this.sizesCache[index];
};
/**
* Returns the scroll offset of the element at the specified index.
* ```typescript
* this.parentVirtDir.getScrollForIndex(1);
* ```
*/
IgxForOfDirective.prototype.getScrollForIndex = function (index, bottom) {
var containerSize = parseInt(this.igxForContainerSize, 10);
var scroll = bottom ? Math.max(0, this.sizesCache[index + 1] - containerSize) : this.sizesCache[index];
return scroll;
};
/**
* @hidden
* Function that is called when scrolling vertically
*/
IgxForOfDirective.prototype.onScroll = function (event) {
/* in certain situations this may be called when no scrollbar is visible */
if (!parseInt(this.scrollComponent.nativeElement.style.height, 10)) {
return;
}
var containerSize = parseInt(this.igxForContainerSize, 10);
var maxRealScrollTop = event.target.children[0].scrollHeight - containerSize;
var realPercentScrolled = maxRealScrollTop !== 0 ? event.target.scrollTop / maxRealScrollTop : 0;
if (!this._bScrollInternal) {
var maxVirtScrollTop = this._virtHeight - containerSize;
this._virtScrollTop = realPercentScrolled * maxVirtScrollTop;
}
else {
this._bScrollInternal = false;
}
var prevStartIndex = this.state.startIndex;
var scrollOffset = this.fixedUpdateAllElements(this._virtScrollTop);
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
this.dc.changeDetectorRef.detectChanges();
if (prevStartIndex !== this.state.startIndex) {
this.onChunkLoad.emit(this.state);
}
};
IgxForOfDirective.prototype.updateSizes = function () {
this.recalcUpdateSizes();
this._applyChanges();
this._updateScrollOffset();
this.onContentSizeChange.emit();
};
/**
* @hidden
* Function that recaculates and updates cache sizes.
*/
IgxForOfDirective.prototype.recalcUpdateSizes = function () {
var dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
var diffs = [];
var totalDiff = 0;
var l = this._embeddedViews.length;
var rNodes = this._embeddedViews.map(function (view) {
return view.rootNodes.find(function (node) { return node.nodeType === Node.ELEMENT_NODE; }) || view.rootNodes[0].nextElementSibling;
});
for (var i = 0; i < l; i++) {
var rNode = rNodes[i];
if (rNode) {
var h = rNode.offsetHeight || parseInt(this.igxForItemSize, 10);
var index = this.state.startIndex + i;
if (!this.isRemote && !this.igxForOf[index]) {
continue;
}
var oldVal = dimension === 'height' ? this.heightCache[index] : this.igxForOf[index][dimension];
var newVal = dimension === 'height' ? h : rNode.clientWidth;
if (dimension === 'height') {
this.heightCache[index] = newVal;
}
else {
this.igxForOf[index][dimension] = newVal;
}
var currDiff = newVal - oldVal;
diffs.push(currDiff);
totalDiff += currDiff;
this.sizesCache[index + 1] += totalDiff;
}
}
// update cache
if (Math.abs(totalDiff) > 0) {
for (var j = this.state.startIndex + this.state.chunkSize + 1; j < this.sizesCache.length; j++) {
this.sizesCache[j] += totalDiff;
}
// update scrBar heights/widths
if (this.igxForScrollOrientation === 'horizontal') {
var totalWidth = parseInt(this.scrollComponent.nativeElement.children[0].style.width, 10) + totalDiff;
this.scrollComponent.nativeElement.children[0].style.width = totalWidth + 'px';
}
var reducer = function (acc, val) { return acc + val; };
if (this.igxForScrollOrientation === 'vertical') {
var scrToBottom = this._isScrolledToBottom && !this.dc.instance.notVirtual;
var hSum = this.heightCache.reduce(reducer);
if (hSum > this._maxHeight) {
this._virtHeightRatio = hSum / this._maxHeight;
}
this.scrollComponent.size = Math.min(this.scrollComponent.size + totalDiff, this._maxHeight);
this._virtHeight = hSum;
if (!this.scrollComponent.destroyed) {
this.scrollComponent.cdr.detectChanges();
}
if (scrToBottom && !this._isAtBottomIndex) {
var containerSize = parseInt(this.igxForContainerSize, 10);
var maxVirtScrollTop = this._virtHeight - containerSize;
this._bScrollInternal = true;
this._virtScrollTop = maxVirtScrollTop;
this.scrollPosition = maxVirtScrollTop;
return;
}
if (this._adjustToIndex) {
// in case scrolled to specific index where after scroll heights are changed
// need to adjust the offsets so that item is last in view.
var updatesToIndex = this._adjustToIndex - this.state.startIndex + 1;
var sumDiffs = diffs.slice(0, updatesToIndex).reduce(reducer);
var currOffset = parseInt(this.dc.instance._viewContainer.element.nativeElement.style.top, 10);
this.dc.instance._viewContainer.element.nativeElement.style.top = (currOffset - sumDiffs) + 'px';
this._adjustToIndex = null;
}
}
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype.fixedUpdateAllElements = function (inScrollTop) {
var count = this.isRemote ? this.totalItemCount : this.igxForOf.length;
var newStart = this.getIndexAt(inScrollTop, this.sizesCache, 0);
if (newStart + this.state.chunkSize > count) {
newStart = count - this.state.chunkSize;
}
var prevStart = this.state.startIndex;
var diff = newStart - this.state.startIndex;
this.state.startIndex = newStart;
if (diff) {
this.onChunkPreload.emit(this.state);
if (!this.isRemote) {
/*recalculate and apply page size.*/
if (diff > 0 && diff <= this.MAX_PERF_SCROLL_DIFF) {
this.moveApplyScrollNext(prevStart);
}
else if (diff < 0 && Math.abs(diff) <= this.MAX_PERF_SCROLL_DIFF) {
this.moveApplyScrollPrev(prevStart);
}
else {
this.fixedApplyScroll();
}
}
}
return inScrollTop - this.sizesCache[this.state.startIndex];
};
/**
* @hidden
* The function applies an optimized state change for scrolling down/right employing context change with view rearrangement
*/
IgxForOfDirective.prototype.moveApplyScrollNext = function (prevIndex) {
var start = prevIndex + this.state.chunkSize;
for (var i = start; i < start + this.state.startIndex - prevIndex && this.igxForOf[i] !== undefined; i++) {
var input = this.igxForOf[i];
var embView = this._embeddedViews.shift();
var cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
var view = this.dc.instance._vcr.detach(0);
this.dc.instance._vcr.insert(view);
this._embeddedViews.push(embView);
}
};
/**
* @hidden
* The function applies an optimized state change for scrolling up/left employing context change with view rearrangement
*/
IgxForOfDirective.prototype.moveApplyScrollPrev = function (prevIndex) {
for (var i = prevIndex - 1; i >= this.state.startIndex && this.igxForOf[i] !== undefined; i--) {
var input = this.igxForOf[i];
var embView = this._embeddedViews.pop();
var cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
var view = this.dc.instance._vcr.detach(this.dc.instance._vcr.length - 1);
this.dc.instance._vcr.insert(view, 0);
this._embeddedViews.unshift(embView);
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype.getContextIndex = function (input) {
return this.isRemote ? this.state.startIndex + this.igxForOf.indexOf(input) : this.igxForOf.indexOf(input);
};
/**
* @hidden
* The function applies an optimized state change through context change for each view
*/
IgxForOfDirective.prototype.fixedApplyScroll = function () {
var j = 0;
var endIndex = this.state.startIndex + this.state.chunkSize;
for (var i = this.state.startIndex; i < endIndex && this.igxForOf[i] !== undefined; i++) {
var input = this.igxForOf[i];
var embView = this._embeddedViews[j++];
var cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
}
};
/**
* @hidden
* Function that is called when scrolling horizontally
*/
IgxForOfDirective.prototype.onHScroll = function (event) {
/* in certain situations this may be called when no scrollbar is visible */
if (!parseInt(this.scrollComponent.nativeElement.children[0].style.width, 10)) {
return;
}
var prevStartIndex = this.state.startIndex;
// Updating horizontal chunks
var scrollOffset = this.fixedUpdateAllElements(event.target.scrollLeft);
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
this.dc.changeDetectorRef.detectChanges();
if (prevStartIndex !== this.state.startIndex) {
this.onChunkLoad.emit(this.state);
}
};
Object.defineProperty(IgxForOfDirective.prototype, "igxForTrackBy", {
/**
* Gets the function used to track changes in the items collection.
* By default the object references are compared. However this can be optimized if you have unique identifier
* value that can be used for the comparison instead of the object ref or if you have some other property values
* in the item object that should be tracked for changes.
* This option is similar to ngForTrackBy.
* ```typescript
* const trackFunc = this.parentVirtDir.igxForTrackBy;
* ```
*/
get: function () { return this._trackByFn; },
/**
* Sets the function used to track changes in the items collection.
* This function can be set in scenarios where you want to optimize or
* customize the tracking of changes for the items in the collection.
* The igxForTrackBy function takes the index and the current item as arguments and needs to return the unique identifier for this item.
* ```typescript
* this.parentVirtDir.igxForTrackBy = (index, item) => {
* return item.id + item.width;
* };
* ```
*/
set: function (fn) { this._trackByFn = fn; },
enumerable: true,
configurable: true
});
/**
* @hidden
*/
IgxForOfDirective.prototype._applyChanges = function () {
var prevChunkSize = this.state.chunkSize;
this.applyChunkSizeChange();
this._recalcScrollBarSize();
if (this.igxForOf && this.igxForOf.length && this.dc) {
var embeddedViewCopy = Object.assign([], this._embeddedViews);
var startIndex = this.state.startIndex;
var endIndex = this.state.chunkSize + this.state.startIndex;
if (this.isRemote) {
startIndex = 0;
endIndex = this.igxForOf.length;
}
for (var i = startIndex; i < endIndex && this.igxForOf[i] !== undefined; i++) {
var input = this.igxForOf[i];
var embView = embeddedViewCopy.shift();
var cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
}
if (prevChunkSize !== this.state.chunkSize) {
this.onChunkLoad.emit(this.state);
}
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype._calcMaxBrowserHeight = function () {
var div = document.createElement('div');
var style = div.style;
style.position = 'absolute';
style.top = '9999999999999999px';
document.body.appendChild(div);
var size = Math.abs(div.getBoundingClientRect()['top']);
document.body.removeChild(div);
return size;
};
/**
* @hidden
* Recalculates the chunkSize based on current startIndex and returns the new size.
* This should be called after this.state.startIndex is updated, not before.
*/
IgxForOfDirective.prototype._calculateChunkSize = function () {
var chunkSize = 0;
if (this.igxForContainerSize !== null && this.igxForContainerSize !== undefined) {
if (!this.sizesCache) {
this.initSizesCache(this.igxForOf);
}
chunkSize = this._calcMaxChunkSize();
if (this.igxForOf && chunkSize > this.igxForOf.length) {
chunkSize = this.igxForOf.length;
}
}
else {
if (this.igxForOf) {
chunkSize = this.igxForOf.length;
}
}
return chunkSize;
};
/**
* @hidden
*/
IgxForOfDirective.prototype.getElement = function (viewref, nodeName) {
var elem = viewref.element.nativeElement.parentNode.getElementsByTagName(nodeName);
return elem.length > 0 ? elem[0] : null;
};
/**
* @hidden
*/
IgxForOfDirective.prototype.initSizesCache = function (items) {
var totalSize = 0;
var size = 0;
var dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
var i = 0;
this.sizesCache = [];
this.heightCache = [];
this.sizesCache.push(0);
var count = this.isRemote ? this.totalItemCount : items.length;
for (i; i < count; i++) {
if (dimension === 'height') {
// cols[i][dimension] = parseInt(this.igxForItemSize, 10) || 0;
size = parseInt(this.igxForItemSize, 10) || 0;
this.heightCache.push(size);
}
else {
size = this._getItemSize(items[i], dimension);
}
totalSize += size;
this.sizesCache.push(totalSize);
}
return totalSize;
};
IgxForOfDirective.prototype._updateSizeCache = function () {
if (this.igxForScrollOrientation === 'horizontal') {
this.initSizesCache(this.igxForOf);
return;
}
var oldHeight = this.heightCache.length > 0 ? this.heightCache.reduce(function (acc, val) { return acc + val; }) : 0;
var newHeight = this.initSizesCache(this.igxForOf);
var diff = oldHeight - newHeight;
// if data has been changed while container is scrolled
// should update scroll top/left according to change so that same startIndex is in view
if (Math.abs(diff) > 0 && this.scrollPosition > 0) {
this.recalcUpdateSizes();
var offset = parseInt(this.dc.instance._viewContainer.element.nativeElement.style.top, 10);
this.scrollPosition = this.sizesCache[this.state.startIndex] - offset;
}
};
/**
* @hidden
*/
IgxForOfDirective.prototype._calcMaxChunkSize = function () {
var _this = this;
var i = 0;
var length = 0;
var maxLength = 0;
var arr = [];
var sum = 0;
var availableSize = parseInt(this.igxForContainerSize, 10);
if (!availableSize) {
return 0;
}
var dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
var reducer = function (accumulator, currentItem) { return accumulator + _this._getItemSize(currentItem, dimension); };
for (i; i < this.igxForOf.length; i++) {
var item = this.igxForOf[i];
if (dimension === 'height') {
item = { value: this.igxForOf[i], height: this.heightCache[i] };
}
var size = dimension === 'height' ?
this.heightCache[i] :
this._getItemSize(item, dimension);
sum = arr.reduce(reducer, size);
if (sum < availableSize) {
arr.push(item);
length = arr.length;
if (i === this.igxForOf.length - 1) {
// reached end without exceeding
// include prev items until size is filled or first item is reached.
var curItem = dimension === 'height' ? arr[0].value : arr[0];
var prevIndex = this.igxForOf.indexOf(curItem) - 1;
while (prevIndex >= 0 && sum <= availableSize) {
curItem = dimension === 'height' ? arr[0].value : arr[0];
prevIndex = this.igxForOf.indexOf(curItem) - 1;
var prevItem = this.igxForOf[prevIndex];
var prevSize = dimension === 'height' ?
this.heightCache[prevIndex] :
parseInt(prevItem[dimension], 10);
sum = arr.reduce(reducer, prevSize);
arr.unshift(prevItem);
length = arr.length;
}
}
}
else {
arr.push(item);
length = arr.length + 1;
arr.shift();
}
if (length > maxLength) {
maxLength = length;
}
}
return maxLength;
};
/**
* @hidden
*/
IgxForOfDirective.prototype.getIndexAt = function (left, set, index) {
var start = 0;
var end = set.length - 1;
if (left === 0) {
return 0;
}
while (start <= end) {
var midIdx = Math.floor((start + end) / 2);
var midLeft = set[midIdx];
var cmp = left - midLeft;
if (cmp > 0) {
start = midIdx + 1;
}
else if (cmp < 0) {
end = midIdx - 1;
}
else {
return midIdx;
}
}
return end;
};
IgxForOfDirective.prototype._recalcScrollBarSize = function () {
var count = this.isRemote ? this.totalItemCount : (this.igxForOf ? this.igxForOf.length : 0);
this.dc.instance.notVirtual = !(this.igxForContainerSize && this.dc && this.state.chunkSize < count);
var scrollable = this.isScrollable();
if (this.igxForScrollOrientation === 'horizontal') {
var totalWidth = this.igxForContainerSize ? this.initSizesCache(this.igxForOf) : 0;
this.scrollComponent.nativeElement.style.width = this.igxForContainerSize + 'px';
this.scrollComponent.size = totalWidth;
if (totalWidth <= parseInt(this.igxForContainerSize, 10)) {
this.scrollPosition = 0;
}
}
if (this.igxForScrollOrientation === 'vertical') {
this.scrollComponent.nativeElement.style.height = parseInt(this.igxForContainerSize, 10) + 'px';
this.scrollComponent.size = this._calcHeight();
if (this.scrollComponent.size <= parseInt(this.igxForContainerSize, 10)) {
this.scrollPosition = 0;
}
}
if (scrollable !== this.isScrollable()) {
// scrollbar visibility has changed
this.onScrollbarVisibilityChanged.emit();
}
};
IgxForOfDirective.prototype._calcHeight = function () {
var height;
if (this.heightCache) {
height = this.heightCache.reduce(function (acc, val) { return acc + val; }, 0);
}
else {
height = this.initSizesCache(this.igxForOf);
}
this._virtHeight = height;
if (height > this._maxHeight) {
this._virtHeightRatio = height / this._maxHeight;
height = this._maxHeight;
}
return height;
};
IgxForOfDirective.prototype._recalcOnContainerChange = function (changes) {
this.dc.instance._viewContainer.element.nativeElement.style.top = '0px';
this.dc.instance._viewContainer.element.nativeElement.style.left = '0px';
var prevChunkSize = this.state.chunkSize;
this.applyChunkSizeChange();
this._recalcScrollBarSize();
if (prevChunkSize !== this.state.chunkSize) {
this.onChunkLoad.emit(this.state);
}
if (this.sizesCache && this.igxForScrollOrientation === 'horizontal') {
// Updating horizontal chunks and offsets based on the new scrollLeft
var scrollOffset = this.fixedUpdateAllElements(this.scrollPosition);
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
}
};
/**
* @hidden
* Removes an elemenet from the embedded views and updates chunkSize.
*/
IgxForOfDirective.prototype.removeLastElem = function () {
var oldElem = this._embeddedViews.pop();
this.onBeforeViewDestroyed.emit(oldElem);
// also detach from ViewContainerRef to make absolutely sure this is removed from the view container.
this.dc.instance._vcr.detach(this.dc.instance._vcr.length - 1);
oldElem.destroy();
this.state.chunkSize--;
};
/**
* @hidden
* If there exists an element that we can create embedded view for creates it, appends it and updates chunkSize
*/
IgxForOfDirective.prototype.addLastElem = function () {
var _this = this;
var elemIndex = this.state.startIndex + this.state.chunkSize;
if (!this.isRemote && !this.igxForOf) {
return;
}
if (elemIndex >= this.igxForOf.length) {
elemIndex = this.igxForOf.length - this.state.chunkSize;
}
var input = this.igxForOf[elemIndex];
var embeddedView = this.dc.instance._vcr.createEmbeddedView(this._template, new IgxForOfContext(input, this.getContextIndex(input), this.igxForOf.length));
this._embeddedViews.push(embeddedView);
this.state.chunkSize++;
this._zone.run(function () {
_this.cdr.markForCheck();
});
};
/**
* Recalculates chunkSize and adds/removes elements if need due to the change.
* this.state.chunkSize is updated in @addLastElem() or @removeLastElem()
*/
IgxForOfDirective.prototype.applyChunkSizeChange = function () {
var chunkSize = this.isRemote ? (this.igxForOf ? this.igxForOf.length : 0) : this._calculateChunkSize();
if (chunkSize > this.state.chunkSize) {
var diff = chunkSize - this.state.chunkSize;
for (var i = 0; i < diff; i++) {
this.addLastElem();
}
}
else if (chunkSize < this.state.chunkSize) {
var diff = this.state.chunkSize - chunkSize;
for (var i = 0; i < diff; i++) {
this.removeLastElem();
}
}
};
IgxForOfDirective.prototype._updateScrollOffset = function () {
if (this.igxForScrollOrientation === 'horizontal') {
this._updateHScrollOffset();
}
else {
this._updateVScrollOffset();
}
};
IgxForOfDirective.prototype._updateVScrollOffset = function () {
var scrollOffset = 0;
var vScroll = this.scrollComponent.nativeElement;
scrollOffset = vScroll && this.scrollComponent.size ?
this.scrollPosition - this.sizesCache[this.state.startIndex] : 0;
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
};
IgxForOfDirective.prototype._updateHScrollOffset = function () {
var scrollOffset = 0;
scrollOffset = this.scrollComponent.nativeElement &&
this.scrollComponent.size ?
this.scrollPosition - this.sizesCache[this.state.startIndex] : 0;
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
};
IgxForOfDirective.prototype._getItemSize = function (item, dimension) {
var dim = item[dimension];
return typeof dim === 'number' ? dim : parseInt(this.igxForItemSize, 10) || 0;
};
IgxForOfDirective.ctorParameters = function () { return [
{ type: ViewContainerRef },
{ type: TemplateRef },
{ type: IterableDiffers },
{ type: ComponentFactoryResolver },
{ type: ChangeDetectorRef },
{ type: NgZone },
{ type: IgxForOfScrollSyncService }
]; };
__decorate([
Input(),
__metadata("design:type", Array)
], IgxForOfDirective.prototype, "igxForOf", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForSizePropName", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForScrollOrientation", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForScrollContainer", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForContainerSize", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForItemSize", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onChunkLoad", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onScrollbarVisibilityChanged", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onContentSizeChange", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onDataChanged", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onBeforeViewDestroyed", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onChunkPreload", void 0);
__decorate([
Input(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Function])
], IgxForOfDirective.prototype, "igxForTrackBy", null);
IgxForOfDirective = __decorate([
Directive({ selector: '[igxFor][igxForOf]' }),
__metadata("design:paramtypes", [ViewContainerRef,
TemplateRef,
IterableDiffers,
ComponentFactoryResolver,
ChangeDetectorRef,
NgZone,
IgxForOfScrollSyncService])
], IgxForOfDirective);
return IgxForOfDirective;
}());
export { IgxForOfDirective };
export function getTypeNameForDebugging(type) {
var name = 'name';
return type[name] || typeof type;
}
var IgxGridForOfDirective = /** @class */ (function (_super) {
__extends(IgxGridForOfDirective, _super);
function IgxGridForOfDirective(_viewContainer, _template, _differs, resolver, cdr, _zone, syncScrollService, syncService) {
var _this = _super.call(this, _viewContainer, _template, _differs, resolver, cdr, _zone, syncScrollService) || this;
_this.syncScrollService = syncScrollService;
_this.syncService = syncService;
/**
* @hidden @internal
* An event that is emitted after data has been changed but before the view is refreshed
*/
_this.onDataChanging = new EventEmitter();
return _this;
}
Object.defineProperty(IgxGridForOfDirective.prototype, "igxGridForOf", {
get: function () {
return this.igxForOf;
},
set: function (value) {
this.igxForOf = value;
},
enumerable: true,
configurable: true
});
IgxGridForOfDirective.prototype.ngOnInit = function () {
this.syncService.setMaster(this);
_super.prototype.ngOnInit.call(this);
this.removeScrollEventListeners();
};
IgxGridForOfDirective.prototype.ngOnChanges = function (changes) {
var forOf = 'igxGridForOf';
this.syncService.setMaster(this);
if (forOf in changes) {
var value = changes[forOf].currentValue;
if (!this._differ && value) {
try {
this._differ = this._differs.find(value).create(this.igxForTrackBy);
}
catch (e) {
throw new Error("Cannot find a differ supporting object \"" + value + "\" of type \"" + getTypeNameForDebugging(value) + "\".\n NgFor only supports binding to Iterables such as Arrays.");
}
}
}
var defaultItemSize = 'igxForItemSize';
if (defaultItemSize in changes && !changes[defaultItemSize].firstChange &&
this.igxForScrollOrientation === 'vertical' && this.igxForOf) {
// handle default item size changed.
this.initSizesCache(this.igxForOf);
}
var containerSize = 'igxForContainerSize';
if (containerSize in changes && !changes[containerSize].firstChange && this.igxForOf) {
this._recalcOnContainerChange(changes);
}
};
Object.defineProperty(IgxGridForOfDirective.prototype, "sizesCache", {
/**
* @hidden
* @internal
*/
get: function () {
if (this.syncService.isMaster(this)) {
return this._sizesCache;
}
return this.syncService.sizesCache(this.igxForScrollOrientation);
},
/**
* @hidden
* @internal
*/
set: function (value) {
this._sizesCache = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxGridForOfDirective.prototype, "itemsDimension", {
get: function () {
return this.igxForScrollOrientation === 'horizontal' ? this.igxForSizePropName : 'height';
},
enumerable: true,
configurable: true
});
IgxGridForOfDirective.prototype.getItemSize = function (item) {
var size = 0;
var dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
if (dimension === 'height') {
size = parseInt(this.igxForItemSize, 10) || 0;
if (item && item.summaries) {
size = item.max;
}
else if (item && item.groups && item.height) {
size = item.height;
}
}
else {
size = parseInt(item[dimension], 10) || 0;
}
return size;
};
IgxGridForOfDirective.prototype.initSizesCache = function (items) {
if (!this.syncService.isMaster(this)) {
var masterSizesCache = this.syncService.sizesCache(this.igxForScrollOrientation);
return masterSizesCache[masterSizesCache.length - 1];
}
var totalSize = 0;
var size = 0;
var i = 0;
this.sizesCache = [];
this.heightCache = [];
this.sizesCache.push(0);
var count = this.isRemote ? this.totalItemCount : items.length;
for (i; i < count; i++) {
size = this.getItemSize(items[i]);
if (this.itemsDimension === 'height') {
this.heightCache.push(size);
}
totalSize += size;
this.sizesCache.push(totalSize);
}
return totalSize;
};
IgxGridForOfDirective.prototype._updateSizeCache = function (changes) {
var _this = this;
if (changes === void 0) { changes = null; }
if (this.igxForScrollOrientation === 'horizontal') {
this.initSizesCache(this.igxForOf);
return;
}
var oldHeight = this.heightCache.length > 0 ? this.heightCache.reduce(function (acc, val) { return acc + val; }) : 0;
var newHeight = oldHeight;
if (changes && !this.isRemote) {
newHeight = this.handleCacheChanges(changes);
}
else {
newHeight = this.initSizesCache(this.igxForOf);
}
var diff = oldHeight - newHeight;
// if data has been changed while container is scrolled
// should update scroll top/left according to change so that same startIndex is in view
if (Math.abs(diff) > 0) {
// TODO: This code can be removed. However tests need to be rewritten in a way that they wait for ResizeObserved to complete.
// So leaving as is for the moment.
requestAnimationFrame(function () {
_this.recalcUpdateSizes();
var offset = parseInt(_this.dc.instance._viewContainer.element.nativeElement.style.top, 10);
if (_this.scrollPosition !== 0) {
_this.scrollPosition = _this.sizesCache[_this.state.startIndex] - offset;
}
else {
_this._updateScrollOffset();
}
});
}
};
IgxGridForOfDirective.prototype.handleCacheChanges = function (changes) {
var _this = this;
var identityChanges = [];
var newHeightCache = [];
var newSizesCache = [];
newSizesCache.push(0);
var newHeight = 0;
// When there are more than one removed items the changes are not reliable so those with identity change should be default size.
var numRemovedItems = 0;
changes.forEachRemovedItem(function () { return numRemovedItems++; });
// Get the identity changes to determine later if those that have changed their indexes should be assigned default item size.
changes.forEachIdentityChange(function (item) {
if (item.currentIndex !== item.previousIndex) {
// Filter out ones that have not changed their index.
identityChanges[item.currentIndex] = item;
}
});
// Processing each item that is passed to the igxForOf so far seem to be most reliable. We parse the updated list of items.
changes.forEachItem(function (item) {
if (item.previousIndex !== null &&
(numRemovedItems < 2 || !identityChanges.length || identityChanges[item.currentIndex])) {
// Reuse cache on those who have previousIndex.
// When there are more than one removed items currently the changes are not readable so ones with identity change
// should be racalculated.
newHeightCache[item.currentIndex] = _this.heightCache[item.previousIndex];
}
else {
// Assign default item size.
newHeightCache[item.currentIndex] = _this.getItemSize(item.item);
}
newSizesCache[item.currentIndex + 1] = newSizesCache[item.currentIndex] + newHeightCache[item.currentIndex];
newHeight += newHeightCache[item.currentIndex];
});
this.heightCache = newHeightCache;
this.sizesCache = newSizesCache;
return newHeight;
};
/**
* @hidden
* @internal
*/
IgxGridForOfDirective.prototype.assumeMaster = function () {
this._sizesCache = this.syncService.sizesCache(this.igxForScrollOrientation);
this.syncService.setMaster(this, true);
};
IgxGridForOfDirective.prototype.ngDoCheck = function () {
if (this._differ) {
var changes = this._differ.diff(this.igxForOf);
if (changes) {
var args = {
containerSize: this.igxForContainerSize
};
this.onDataChanging.emit(args);
// re-init cache.
if (!this.igxForOf) {
this.igxForOf = [];
}
/* we need to reset the master dir if all rows are removed
(e.g. because of filtering); if all columns are hidden, rows are
still rendered empty, so we should not reset master */
if (!this.igxForOf.length &&
this.igxForScrollOrientation === 'vertical') {
this.syncService.resetMaster();
}
this.syncService.setMaster(this);
this.igxForContainerSize = args.containerSize;
this._updateSizeCache(changes);
this._applyChanges();
this._updateScrollOffset();
this.onDataChanged.emit();
}
}
};
IgxGridForOfDirective.prototype.onScroll = function (event) {
var _this = this;
if (!parseInt(this.scrollComponent.nativeElement.style.height, 10)) {
return;
}
var containerSize = parseInt(this.igxForContainerSize, 10);
var maxRealScrollTop = event.target.children[0].scrollHeight - containerSize;
var realPercentScrolled = maxRealScrollTop !== 0 ? event.target.scrollTop / maxRealScrollTop : 0;
if (!this._bScrollInternal) {
var maxVirtScrollTop = this._virtHeight - containerSize;
this._virtScrollTop = realPercentScrolled * maxVirtScrollTop;
}
else {
this._bScrollInternal = false;
}
var scrollOffset = this.fixedUpdateAllElements(this._virtScrollTop);
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
this._zone.onStable.pipe(first()).subscribe(function () {
_this.recalcUpdateSizes();
});
this.cdr.markForCheck();
};
IgxGridForOfDirective.prototype.onHScroll = function (scrollAmount) {
/* in certain situations this may be called when no scrollbar is visible */
if (!this.scrollComponent || !parseInt(this.scrollComponent.nativeElement.children[0].style.width, 10)) {
return;
}
// Updating horizontal chunks
var scrollOffset = this.fixedUpdateAllElements(scrollAmount);
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
};
IgxGridForOfDirective.prototype.addLastElem = function () {
var elemIndex = this.state.startIndex + this.state.chunkSize;
if (!this.isRemote && !this.igxForOf) {
return;
}
if (elemIndex >= this.igxForOf.length) {
elemIndex = this.igxForOf.length - this.state.chunkSize;
}
var input = this.igxForOf[elemIndex];
var embeddedView = this.dc.instance._vcr.createEmbeddedView(this._template, new IgxForOfContext(input, this.getContextIndex(input), this.igxForOf.length));
this._embeddedViews.push(embeddedView);
this.state.chunkSize++;
};
IgxGridForOfDirective.prototype._updateViews = function (prevChunkSize) {
if (this.igxForOf && this.igxForOf.length && this.dc) {
var embeddedViewCopy = Object.assign([], this._embeddedViews);
var startIndex = void 0;
var endIndex = void 0;
if (this.isRemote) {
startIndex = 0;
endIndex = this.igxForOf.length;
}
else {
startIndex = this.getIndexAt(this.scrollPosition, this.sizesCache, 0);
if (startIndex + this.state.chunkSize > this.igxForOf.length) {
startIndex = this.igxForOf.length - this.state.chunkSize;
}
this.state.startIndex = startIndex;
endIndex = this.state.chunkSize + this.state.startIndex;
}
for (var i = startIndex; i < endIndex && this.igxForOf[i] !== undefined; i++) {
var input = this.igxForOf[i];
var embView = embeddedViewCopy.shift();
var cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
}
if (prevChunkSize !== this.state.chunkSize) {
this.onChunkLoad.emit(this.state);
}
}
};
IgxGridForOfDirective.prototype._applyChanges = function () {
var prevChunkSize = this.state.chunkSize;
this.applyChunkSizeChange();
this._recalcScrollBarSize();
this._updateViews(prevChunkSize);
};
/**
* @hidden
*/
IgxGridForOfDirective.prototype._calcMaxChunkSize = function () {
if (this.syncService.isMaster(this)) {
return _super.prototype._calcMaxChunkSize.call(this);
}
return this.syncService.chunkSize(this.igxForScrollOrientation);
};
IgxGridForOfDirective.ctorParameters = function () { return [
{ type: ViewContainerRef },
{ type: TemplateRef },
{ type: IterableDiffers },
{ type: ComponentFactoryResolver },
{ type: ChangeDetectorRef },
{ type: NgZone },
{ type: IgxForOfScrollSyncService },
{ type: IgxForOfSyncService }
]; };
__decorate([
Input(),
__metadata("design:type", Object),
__metadata("design:paramtypes", [Object])
], IgxGridForOfDirective.prototype, "igxGridForOf", null);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxGridForOfDirective.prototype, "onDataChanging", void 0);
IgxGridForOfDirective = __decorate([
Directive({
selector: '[igxGridFor][igxGridForOf]'
}),
__metadata("design:paramtypes", [ViewContainerRef,
TemplateRef,
IterableDiffers,
ComponentFactoryResolver,
ChangeDetectorRef,
NgZone,
IgxForOfScrollSyncService,
IgxForOfSyncService])
], IgxGridForOfDirective);
return IgxGridForOfDirective;
}(IgxForOfDirective));
export { IgxGridForOfDirective };
/**
* @hidden
*/
var IgxForOfModule = /** @class */ (function () {
function IgxForOfModule() {
}
IgxForOfModule = __decorate([
NgModule({
declarations: [IgxForOfDirective, IgxGridForOfDirective, DisplayContainerComponent, VirtualHelperComponent,
HVirtualHelperComponent, VirtualHelperBaseDirective],
entryComponents: [DisplayContainerComponent, VirtualHelperComponent, HVirtualHelperComponent],
exports: [IgxForOfDirective, IgxGridForOfDirective],
imports: [IgxScrollInertiaModule, CommonModule]
})
], IgxForOfModule);
return IgxForOfModule;
}());
export { IgxForOfModule };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yX29mLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGlyZWN0aXZlcy9mb3Itb2YvZm9yX29mLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFlBQVksRUFBa0IsTUFBTSxpQkFBaUIsQ0FBQztBQUMvRCxPQUFPLEVBQ0gsaUJBQWlCLEVBQ2pCLGdCQUFnQixFQUNoQix3QkFBd0IsRUFDeEIsWUFBWSxFQUNaLFNBQVMsRUFDVCxPQUFPLEVBQ1AsZUFBZSxFQUNmLFlBQVksRUFDWixLQUFLLEVBQ0wsZUFBZSxFQUNmLGNBQWMsRUFDZCxlQUFlLEVBQ2YsUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sYUFBYSxFQUNiLFdBQVcsRUFDWCxlQUFlLEVBQ2YsZ0JBQWdCLEVBQ2hCLE9BQU8sRUFDUCxhQUFhLEVBQ2hCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQ3RGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hFLE9BQU8sY0FBYyxNQUFNLDBCQUEwQixDQUFDO0FBRXRELE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxN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QUhqQyxTQUFTLENBQUM7WUFDUCxRQUFRLEVBQUUsNEJBQTRCO1NBQ3pDLENBQUM7eUNBSXNCLGdCQUFnQjtZQUNyQixXQUFXO1lBQ1osZUFBZTtZQUNmLHdCQUF3QjtZQUM3QixpQkFBaUI7WUFDZixNQUFNO1lBQ2dCLHlCQUF5QjtZQUMvQixtQkFBbUI7T0FWckMscUJBQXFCLENBa1ZqQztJQUFELDRCQUFDO0NBQUEsQUFsVkQsQ0FBOEMsaUJBQWlCLEdBa1Y5RDtTQWxWWSxxQkFBcUI7QUFvVmxDOztHQUVHO0FBU0g7SUFBQTtJQUNBLENBQUM7SUFEWSxjQUFjO1FBUjFCLFFBQVEsQ0FBQztZQUNOLFlBQVksRUFBRSxDQUFDLGlCQUFpQixFQUFFLHFCQUFxQixFQUFFLHlCQUF5QixFQUFFLHNCQUFzQjtnQkFDckcsdUJBQXVCLEVBQUUsMEJBQTBCLENBQUM7WUFDekQsZUFBZSxFQUFFLENBQUMseUJBQXlCLEVBQUUsc0JBQXNCLEVBQUUsdUJBQXVCLENBQUM7WUFDN0YsT0FBTyxFQUFFLENBQUMsaUJBQWlCLEVBQUUscUJBQXFCLENBQUM7WUFDbkQsT0FBTyxFQUFFLENBQUMsc0JBQXNCLEVBQUUsWUFBWSxDQUFDO1NBQ2xELENBQUM7T0FFVyxjQUFjLENBQzFCO0lBQUQscUJBQUM7Q0FBQSxBQURELElBQ0M7U0FEWSxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlLCBOZ0Zvck9mQ29udGV4dCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICAgIENoYW5nZURldGVjdG9yUmVmLFxuICAgIENvbXBvbmVudEZhY3RvcnksXG4gICAgQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICAgIENvbXBvbmVudFJlZixcbiAgICBEaXJlY3RpdmUsXG4gICAgRG9DaGVjayxcbiAgICBFbWJlZGRlZFZpZXdSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIElucHV0LFxuICAgIEl0ZXJhYmxlQ2hhbmdlcyxcbiAgICBJdGVyYWJsZURpZmZlcixcbiAgICBJdGVyYWJsZURpZmZlcnMsXG4gICAgTmdNb2R1bGUsXG4gICAgTmdab25lLFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkRlc3Ryb3ksXG4gICAgT25Jbml0LFxuICAgIE91dHB1dCxcbiAgICBTaW1wbGVDaGFuZ2VzLFxuICAgIFRlbXBsYXRlUmVmLFxuICAgIFRyYWNrQnlGdW5jdGlvbixcbiAgICBWaWV3Q29udGFpbmVyUmVmLFxuICAgIFZpZXdSZWYsXG4gICAgQWZ0ZXJWaWV3SW5pdFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgRGlzcGxheUNvbnRhaW5lckNvbXBvbmVudCB9IGZyb20gJy4vZGlzcGxheS5jb250YWluZXInO1xuaW1wb3J0IHsgSFZpcnR1YWxIZWxwZXJDb21wb25lbnQgfSBmcm9tICcuL2hvcml6b250YWwudmlydHVhbC5oZWxwZXIuY29tcG9uZW50JztcbmltcG9ydCB7IFZpcnR1YWxIZWxwZXJDb21wb25lbnQgfSBmcm9tICcuL3ZpcnR1YWwuaGVscGVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJZ3hTY3JvbGxJbmVydGlhTW9kdWxlIH0gZnJvbSAnLi8uLi9zY3JvbGwtaW5lcnRpYS9zY3JvbGxfaW5lcnRpYS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSWd4Rm9yT2ZTeW5jU2VydmljZSwgSWd4Rm9yT2ZTY3JvbGxTeW5jU2VydmljZSB9IGZyb20gJy4vZm9yX29mLnN5bmMuc2VydmljZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwsIGZpbHRlciwgdGhyb3R0bGVUaW1lLCBmaXJzdCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCBSZXNpemVPYnNlcnZlciBmcm9tICdyZXNpemUtb2JzZXJ2ZXItcG9seWZpbGwnO1xuaW1wb3J0IHsgSUJhc2VFdmVudEFyZ3MgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWxzJztcbmltcG9ydCB7IFZpcnR1YWxIZWxwZXJCYXNlRGlyZWN0aXZlIH0gZnJvbSAnLi9iYXNlLmhlbHBlci5jb21wb25lbnQnO1xuXG4vKipcbiAqICBAcHVibGljQXBpXG4gKi9cbmV4cG9ydCBjbGFzcyBJZ3hGb3JPZkNvbnRleHQ8VD4ge1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgIHB1YmxpYyAkaW1wbGljaXQ6IFQsXG4gICAgICAgcHVibGljIGluZGV4OiBudW1iZXIsXG4gICAgICAgcHVibGljIGNvdW50OiBudW1iZXJcbiAgICApIHt9XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIHRoZSBmaXJzdCBvciBub3RcbiAgICAgKi9cbiAgICBnZXQgZmlyc3QoKTogYm9vbGVhbiB7IHJldHVybiB0aGlzLmluZGV4ID09PSAwOyB9XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIHRoZSBsYXN0IG9yIG5vdFxuICAgICAqL1xuICAgIGdldCBsYXN0KCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5pbmRleCA9PT0gdGhpcy5jb3VudCAtIDE7IH1cblxuICAgIC8qKlxuICAgICAqIEEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZXZlbiBvciBub3RcbiAgICAgKi9cbiAgICBnZXQgZXZlbigpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMuaW5kZXggJSAyID09PSAwOyB9XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIG9kZCBvciBub3RcbiAgICAgKi9cbiAgICBnZXQgb2RkKCk6IGJvb2xlYW4geyByZXR1cm4gIXRoaXMuZXZlbjsgfVxuXG59XG5cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ1tpZ3hGb3JdW2lneEZvck9mXScgfSlcbmV4cG9ydCBjbGFzcyBJZ3hGb3JPZkRpcmVjdGl2ZTxUPiBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBEb0NoZWNrLCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgc2V0cyB0aGUgZGF0YSB0byBiZSByZW5kZXJlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBsZXQtaXRlbSBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGlneEZvck9mOiBhbnlbXTtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHNldHMgdGhlIHByb3BlcnR5IG5hbWUgZnJvbSB3aGljaCB0byByZWFkIHRoZSBzaXplIGluIHRoZSBkYXRhIG9iamVjdC5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JTaXplUHJvcE5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBzcGVjaWZpZXMgdGhlIHNjcm9sbCBvcmllbnRhdGlvbi5cbiAgICAgKiBTY3JvbGwgb3JpZW50YXRpb24gY2FuIGJlIFwidmVydGljYWxcIiBvciBcImhvcml6b250YWxcIi5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBsZXQtaXRlbSBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGlneEZvclNjcm9sbE9yaWVudGF0aW9uID0gJ3ZlcnRpY2FsJztcblxuICAgIC8qKlxuICAgICAqIE9wdGlvbmFsbHkgcGFzcyB0aGUgcGFyZW50IGBpZ3hGb3JgIGluc3RhbmNlIHRvIGNyZWF0ZSBhIHZpcnR1YWwgdGVtcGxhdGUgc2Nyb2xsaW5nIGJvdGggaG9yaXpvbnRhbGx5IGFuZCB2ZXJ0aWNhbGx5LlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8bmctdGVtcGxhdGUgI3Njcm9sbENvbnRhaW5lciBpZ3hGb3IgbGV0LXJvd0RhdGEgW2lneEZvck9mXT1cImRhdGFcIlxuICAgICAqICAgICAgIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCIndmVydGljYWwnXCJcbiAgICAgKiAgICAgICBbaWd4Rm9yQ29udGFpbmVyU2l6ZV09XCInNTAwcHgnXCJcbiAgICAgKiAgICAgICBbaWd4Rm9ySXRlbVNpemVdPVwiJzUwcHgnXCJcbiAgICAgKiAgICAgICBsZXQtcm93SW5kZXg9XCJpbmRleFwiPlxuICAgICAqICAgICAgIDxkaXYgW3N0eWxlLmRpc3BsYXldPVwiJ2ZsZXgnXCIgW3N0eWxlLmhlaWdodF09XCInNTBweCdcIj5cbiAgICAgKiAgICAgICAgICAgPG5nLXRlbXBsYXRlICNjaGlsZENvbnRhaW5lciBpZ3hGb3IgbGV0LWl0ZW0gW2lneEZvck9mXT1cImRhdGFcIlxuICAgICAqICAgICAgICAgICAgICAgW2lneEZvclNjcm9sbE9yaWVudGF0aW9uXT1cIidob3Jpem9udGFsJ1wiXG4gICAgICogICAgICAgICAgICAgICBbaWd4Rm9yU2Nyb2xsQ29udGFpbmVyXT1cInBhcmVudFZpcnREaXJcIlxuICAgICAqICAgICAgICAgICAgICAgW2lneEZvckNvbnRhaW5lclNpemVdPVwiJzUwMHB4J1wiPlxuICAgICAqICAgICAgICAgICAgICAgICAgIDxkaXYgW3N0eWxlLm1pbi13aWR0aF09XCInNTBweCdcIj57e3Jvd0luZGV4fX0gOiB7e2l0ZW0udGV4dH19PC9kaXY+XG4gICAgICogICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICogICAgICAgPC9kaXY+XG4gICAgICogPC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JTY3JvbGxDb250YWluZXI6IGFueTtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHNldHMgdGhlIHB4LWFmZml4ZWQgc2l6ZSBvZiB0aGUgY29udGFpbmVyIGFsb25nIHRoZSBheGlzIG9mIHNjcm9sbGluZy5cbiAgICAgKiBGb3IgXCJob3Jpem9udGFsXCIgb3JpZW50YXRpb24gdGhpcyB2YWx1ZSBpcyB0aGUgd2lkdGggb2YgdGhlIGNvbnRhaW5lciBhbmQgZm9yIFwidmVydGljYWxcIiBpcyB0aGUgaGVpZ2h0LlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8bmctdGVtcGxhdGUgaWd4Rm9yIGxldC1pdGVtIFtpZ3hGb3JPZl09XCJkYXRhXCIgW2lneEZvckNvbnRhaW5lclNpemVdPVwiJzUwMHB4J1wiXG4gICAgICogICAgICBbaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb25dPVwiJ2hvcml6b250YWwnXCI+XG4gICAgICogPC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JDb250YWluZXJTaXplOiBhbnk7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBzZXRzIHRoZSBweC1hZmZpeGVkIHNpemUgb2YgdGhlIGl0ZW0gYWxvbmcgdGhlIGF4aXMgb2Ygc2Nyb2xsaW5nLlxuICAgICAqIEZvciBcImhvcml6b250YWxcIiBvcmllbnRhdGlvbiB0aGlzIHZhbHVlIGlzIHRoZSB3aWR0aCBvZiB0aGUgY29sdW1uIGFuZCBmb3IgXCJ2ZXJ0aWNhbFwiIGlzIHRoZSBoZWlnaHQgb3IgdGhlIHJvdy5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBsZXQtaXRlbSBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiBbaWd4Rm9ySXRlbVNpemVdPVwiJzUwcHgnXCI+PC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JJdGVtU2l6ZTogYW55O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBkYzogQ29tcG9uZW50UmVmPERpc3BsYXlDb250YWluZXJDb21wb25lbnQ+O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGRpcmVjdGl2ZS4gSXQgY29udGFpbnMgYHN0YXJ0SW5kZXhgIGFuZCBgY2h1bmtTaXplYC5cbiAgICAgKiBzdGF0ZS5zdGFydEluZGV4IC0gVGhlIGluZGV4IG9mIHRoZSBpdGVtIGF0IHdoaWNoIHRoZSBjdXJyZW50IHZpc2libGUgY2h1bmsgYmVnaW5zLlxuICAgICAqIHN0YXRlLmNodW5rU2l6ZSAtIFRoZSBudW1iZXIgb2YgaXRlbXMgdGhlIGN1cnJlbnQgdmlzaWJsZSBjaHVuayBob2xkcy5cbiAgICAgKiBUaGVzZSBvcHRpb25zIGNhbiBiZSB1c2VkIHdoZW4gaW1wbGVtZW50aW5nIHJlbW90ZSB2aXJ0dWFsaXphdGlvbiBhcyB0aGV5IHByb3ZpZGUgdGhlIG5lY2Vzc2FyeSBzdGF0ZSBpbmZvcm1hdGlvbi5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZ3JpZFN0YXRlID0gdGhpcy5wYXJlbnRWaXJ0RGlyLnN0YXRlO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0ZTogSUZvck9mU3RhdGUgPSB7XG4gICAgICAgIHN0YXJ0SW5kZXg6IDAsXG4gICAgICAgIGNodW5rU2l6ZTogMFxuICAgIH07XG4gICAgLyoqXG4gICAgICogVGhlIHRvdGFsIGNvdW50IG9mIHRoZSB2aXJ0dWFsIGRhdGEgaXRlbXMsIHdoZW4gdXNpbmcgcmVtb3RlIHNlcnZpY2UuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci50b3RhbEl0ZW1Db3VudCA9IGRhdGEuQ291bnQ7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHRvdGFsSXRlbUNvdW50OiBudW1iZXIgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIGEgbmV3IGNodW5rIGhhcyBiZWVuIGxvYWRlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiAob25DaHVua0xvYWQpPVwiY2h1bmtMb2FkKCRldmVudClcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjaHVua0xvYWQoZSl7XG4gICAgICogYWxlcnQoXCJjaHVuayBsb2FkZWQhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25DaHVua0xvYWQgPSBuZXcgRXZlbnRFbWl0dGVyPElGb3JPZlN0YXRlPigpO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlbiBAaW50ZXJuYWxcbiAgICAgKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiBzY3JvbGxiYXIgdmlzaWJpbGl0eSBoYXMgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25TY3JvbGxiYXJWaXNpYmlsaXR5Q2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIHRoZSByZW5kZXJlZCBjb250ZW50IHNpemUgb2YgdGhlIGlneEZvck9mIGhhcyBiZWVuIGNoYW5nZWQuXG4gICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25Db250ZW50U2l6ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIGRhdGEgaGFzIGJlZW4gY2hhbmdlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiAob25EYXRhQ2hhbmdlZCk9XCJkYXRhQ2hhbmdlZCgkZXZlbnQpXCI+PC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogZGF0YUNoYW5nZWQoZSl7XG4gICAgICogYWxlcnQoXCJkYXRhIGNoYW5nZWQhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25EYXRhQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uQmVmb3JlVmlld0Rlc3Ryb3llZCA9IG5ldyBFdmVudEVtaXR0ZXI8RW1iZWRkZWRWaWV3UmVmPGFueT4+KCk7XG5cbiAgICAvKipcbiAgICAgKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgb24gY2h1bmsgbG9hZGluZyB0byBlbWl0IHRoZSBjdXJyZW50IHN0YXRlIGluZm9ybWF0aW9uIC0gc3RhcnRJbmRleCwgZW5kSW5kZXgsIHRvdGFsQ291bnQuXG4gICAgICogQ2FuIGJlIHVzZWQgZm9yIGltcGxlbWVudGluZyByZW1vdGUgbG9hZCBvbiBkZW1hbmQgZm9yIHRoZSBpZ3hGb3IgZGF0YS5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiAob25DaHVua1ByZWxvYWQpPVwiY2h1bmtQcmVsb2FkKCRldmVudClcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjaHVua1ByZWxvYWQoZSl7XG4gICAgICogYWxlcnQoXCJjaHVuayBpcyBsb2FkaW5nIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uQ2h1bmtQcmVsb2FkID0gbmV3IEV2ZW50RW1pdHRlcjxJRm9yT2ZTdGF0ZT4oKTtcbiAgICBwcm90ZWN0ZWQgZnVuYztcbiAgICBwcm90ZWN0ZWQgX3NpemVzQ2FjaGU6IG51bWJlcltdID0gW107XG4gICAgcHJvdGVjdGVkIHNjcm9sbENvbXBvbmVudDogVmlydHVhbEhlbHBlckJhc2VEaXJlY3RpdmU7XG4gICAgcHJvdGVjdGVkIF9kaWZmZXI6IEl0ZXJhYmxlRGlmZmVyPFQ+IHwgbnVsbCA9IG51bGw7XG4gICAgcHJvdGVjdGVkIF90cmFja0J5Rm46IFRyYWNrQnlGdW5jdGlvbjxUPjtcbiAgICBwcm90ZWN0ZWQgaGVpZ2h0Q2FjaGUgPSBbXTtcbiAgICBwcml2YXRlIF9hZGp1c3RUb0luZGV4O1xuICAgIHByaXZhdGUgTUFYX1BFUkZfU0NST0xMX0RJRkYgPSA0O1xuXG5cbiAgICBwdWJsaWMgZ2V0IGRpc3BsYXlDb250YWluZXIoKTogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQge1xuICAgICAgICByZXR1cm4gdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCB2aXJ0dWFsSGVscGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IHNpemVzQ2FjaGUoKTogbnVtYmVyW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2l6ZXNDYWNoZTtcbiAgICB9XG4gICAgcHJvdGVjdGVkIHNldCBzaXplc0NhY2hlKHZhbHVlOiBudW1iZXJbXSkge1xuICAgICAgICB0aGlzLl9zaXplc0NhY2hlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgX2lzU2Nyb2xsZWRUb0JvdHRvbSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdldFNjcm9sbCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzY3JvbGxIZWlnaHQgPSB0aGlzLmdldFNjcm9sbCgpLnNjcm9sbEhlaWdodDtcbiAgICAgICAgLy8gVXNlID09PSBhbmQgbm90ID49IGJlY2F1c2UgYHNjcm9sbFRvcCArIGNvbnRhaW5lciBzaXplYCBjYW4ndCBiZSBiaWdnZXIgdGhhbiBgc2Nyb2xsSGVpZ2h0YCwgdW5sZXNzIHNvbWV0aGluZyBpc24ndCB1cGRhdGVkLlxuICAgICAgICAvLyBBbHNvIHVzZSBNYXRoLnJvdW5kIGJlY2F1c2UgQ2hyb21lIGhhcyBzb21lIGluY29uc2lzdGVuY2llcyBhbmQgYHNjcm9sbFRvcCArIGNvbnRhaW5lcmAgY2FuIGJlIGZsb2F0IHdoZW4gem9vbWluZyB0aGUgcGFnZS5cbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQodGhpcy5nZXRTY3JvbGwoKS5zY3JvbGxUb3AgKyB0aGlzLmlneEZvckNvbnRhaW5lclNpemUpID09PSBzY3JvbGxIZWlnaHQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgX2lzQXRCb3R0b21JbmRleCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaWd4Rm9yT2YgJiYgdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5zdGF0ZS5jaHVua1NpemUgPiB0aGlzLmlneEZvck9mLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvLyBTdGFydCBwcm9wZXJ0aWVzIHJlbGF0ZWQgdG8gdmlydHVhbCBoZWlnaHQgaGFuZGxpbmcgZHVlIHRvIGJyb3dzZXIgbGltaXRhdGlvblxuICAgIC8qKiBNYXhpbXVtIGhlaWdodCBmb3IgYW4gZWxlbWVudCBvZiB0aGUgYnJvd3Nlci4gKi9cbiAgICBwcml2YXRlIF9tYXhIZWlnaHQ7XG5cbiAgICAvKiogSGVpZ2h0IHRoYXQgaXMgYmVpbmcgdmlydHVhbGl6ZWQuICovXG4gICAgcHJvdGVjdGVkIF92aXJ0SGVpZ2h0ID0gMDtcblxuICAgIC8qKlxuICAgICAqIFJhdGlvIGZvciBoZWlnaHQgdGhhdCdzIGJlaW5nIHZpcnR1YWxpemFlZCBhbmQgdGhlIG9uZSB2aXNpYmxlXG4gICAgICogSWYgX3ZpcnRIZWlnaHRSYXRpbyA9IDEsIHRoZSB2aXNpYmxlIGhlaWdodCBhbmQgdGhlIHZpcnR1YWxpemVkIGFyZSB0aGUgc2FtZSwgYWxzbyBfbWF4SGVpZ2h0ID4gX3ZpcnRIZWlnaHQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBfdmlydEhlaWdodFJhdGlvID0gMTtcblxuICAgIC8qKiBJbnRlcm5hbCB0cmFjayBmb3Igc2Nyb2xsIHRvcCB0aGF0IGlzIGJlaW5nIHZpcnR1YWxpemVkICovXG4gICAgcHJvdGVjdGVkIF92aXJ0U2Nyb2xsVG9wID0gMDtcblxuICAgIC8qKiBJZiB0aGUgbmV4dCBvblNjcm9sbCBldmVudCBpcyB0cmlnZ2VyZWQgZHVlIHRvIGludGVybmFsIHNldHRpbmcgb2Ygc2Nyb2xsVG9wICovXG4gICAgcHJvdGVjdGVkIF9iU2Nyb2xsSW50ZXJuYWwgPSBmYWxzZTtcbiAgICAvLyBFbmQgcHJvcGVydGllcyByZWxhdGVkIHRvIHZpcnR1YWwgaGVpZ2h0IGhhbmRsaW5nXG5cbiAgICBwcm90ZWN0ZWQgX2VtYmVkZGVkVmlld3M6IEFycmF5PEVtYmVkZGVkVmlld1JlZjxhbnk+PiA9IFtdO1xuXG4gICAgcHJvdGVjdGVkIGNvbnRlbnRSZXNpemVOb3RpZnkgPSBuZXcgU3ViamVjdCgpO1xuICAgIHByb3RlY3RlZCBjb250ZW50T2JzZXJ2ZXI6IFJlc2l6ZU9ic2VydmVyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIF92aWV3Q29udGFpbmVyOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgICAgICBwcm90ZWN0ZWQgX3RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxOZ0Zvck9mQ29udGV4dDxUPj4sXG4gICAgICAgIHByb3RlY3RlZCBfZGlmZmVyczogSXRlcmFibGVEaWZmZXJzLFxuICAgICAgICBwcml2YXRlIHJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgICAgIHB1YmxpYyBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBwcm90ZWN0ZWQgX3pvbmU6IE5nWm9uZSxcbiAgICAgICAgcHJvdGVjdGVkIHN5bmNTY3JvbGxTZXJ2aWNlOiBJZ3hGb3JPZlNjcm9sbFN5bmNTZXJ2aWNlKSB7IH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0IGlzUmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy50b3RhbEl0ZW1Db3VudCAhPT0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEdldHMvU2V0cyB0aGUgc2Nyb2xsIHBvc2l0aW9uLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBwb3NpdGlvbiA9IGRpcmVjdGl2ZS5zY3JvbGxQb3NpdGlvbjtcbiAgICAgKiBkaXJlY3RpdmUuc2Nyb2xsUG9zaXRpb24gPSB2YWx1ZTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHNjcm9sbFBvc2l0aW9uKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbENvbXBvbmVudC5zY3JvbGxBbW91bnQ7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgc2Nyb2xsUG9zaXRpb24odmFsOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKHZhbCA9PT0gdGhpcy5zY3JvbGxDb21wb25lbnQuc2Nyb2xsQW1vdW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJyAmJiB0aGlzLnNjcm9sbENvbXBvbmVudCkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zY3JvbGxMZWZ0ID0gdmFsO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2Nyb2xsQ29tcG9uZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LnNjcm9sbFRvcCA9IHZhbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVtb3ZlU2Nyb2xsRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuX3pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuZnVuYylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl96b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLnZlcnRpY2FsU2Nyb2xsSGFuZGxlcilcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgdmVydGljYWxTY3JvbGxIYW5kbGVyKGV2ZW50KSB7XG4gICAgICAgIHRoaXMub25TY3JvbGwoZXZlbnQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc1Njcm9sbGFibGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbENvbXBvbmVudC5zaXplID4gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgbGV0IHRvdGFsU2l6ZSA9IDA7XG4gICAgICAgIGNvbnN0IHZjID0gdGhpcy5pZ3hGb3JTY3JvbGxDb250YWluZXIgPyB0aGlzLmlneEZvclNjcm9sbENvbnRhaW5lci5fdmlld0NvbnRhaW5lciA6IHRoaXMuX3ZpZXdDb250YWluZXI7XG4gICAgICAgIHRoaXMuaWd4Rm9yU2l6ZVByb3BOYW1lID0gdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgfHwgJ3dpZHRoJztcblxuICAgICAgICBjb25zdCBkY0ZhY3Rvcnk6IENvbXBvbmVudEZhY3Rvcnk8RGlzcGxheUNvbnRhaW5lckNvbXBvbmVudD4gPSB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KERpc3BsYXlDb250YWluZXJDb21wb25lbnQpO1xuICAgICAgICB0aGlzLmRjID0gdGhpcy5fdmlld0NvbnRhaW5lci5jcmVhdGVDb21wb25lbnQoZGNGYWN0b3J5LCAwKTtcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5zY3JvbGxEaXJlY3Rpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uO1xuICAgICAgICBpZiAodHlwZW9mIE1TR2VzdHVyZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgLy8gT24gRWRnZSBhbmQgSUUgd2hlbiBzY3JvbGxpbmcgb24gdG91Y2ggdGhlIHBhZ2Ugc2Nyb2xsIGluc3RlYWQgb2YgdGhlIGdyaWQuXG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3VjaEFjdGlvbiA9ICdub25lJztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pZ3hGb3JPZiAmJiB0aGlzLmlneEZvck9mLmxlbmd0aCkge1xuICAgICAgICAgICAgdG90YWxTaXplID0gdGhpcy5pbml0U2l6ZXNDYWNoZSh0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50ID0gdGhpcy5zeW5jU2Nyb2xsU2VydmljZS5nZXRTY3JvbGxNYXN0ZXIodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbik7XG4gICAgICAgICAgICB0aGlzLnN0YXRlLmNodW5rU2l6ZSA9IHRoaXMuX2NhbGN1bGF0ZUNodW5rU2l6ZSgpO1xuICAgICAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5ub3RWaXJ0dWFsID0gISh0aGlzLmlneEZvckNvbnRhaW5lclNpemUgJiYgdGhpcy5zdGF0ZS5jaHVua1NpemUgPCB0aGlzLmlneEZvck9mLmxlbmd0aCk7XG4gICAgICAgICAgICBpZiAodGhpcy5zY3JvbGxDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggPSBNYXRoLm1pbih0aGlzLmdldEluZGV4QXQodGhpcy5zY3JvbGxQb3NpdGlvbiwgdGhpcy5zaXplc0NhY2hlLCAwKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JPZi5sZW5ndGggLSB0aGlzLnN0YXRlLmNodW5rU2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4OyBpIDwgdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5zdGF0ZS5jaHVua1NpemUgJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JPZltpXSAhPT0gdW5kZWZpbmVkOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgZW1iZWRkZWRWaWV3ID0gdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmNyZWF0ZUVtYmVkZGVkVmlldyhcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgICAgIG5ldyBJZ3hGb3JPZkNvbnRleHQ8VD4oaW5wdXQsIHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KSwgdGhpcy5pZ3hGb3JPZi5sZW5ndGgpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnB1c2goZW1iZWRkZWRWaWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAndmVydGljYWwnKSB7XG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAnMHB4JztcbiAgICAgICAgICAgIGNvbnN0IGZhY3Rvcnk6IENvbXBvbmVudEZhY3Rvcnk8VmlydHVhbEhlbHBlckNvbXBvbmVudD4gPSB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KFZpcnR1YWxIZWxwZXJDb21wb25lbnQpO1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQgPSB2Yy5jcmVhdGVDb21wb25lbnQoZmFjdG9yeSkuaW5zdGFuY2U7XG4gICAgICAgICAgICB0aGlzLl9tYXhIZWlnaHQgPSB0aGlzLl9jYWxjTWF4QnJvd3NlckhlaWdodCgpO1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQuc2l6ZSA9IHRoaXMuaWd4Rm9yT2YgPyB0aGlzLl9jYWxjSGVpZ2h0KCkgOiAwO1xuICAgICAgICAgICAgdGhpcy5zeW5jU2Nyb2xsU2VydmljZS5zZXRTY3JvbGxNYXN0ZXIodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiwgdGhpcy5zY3JvbGxDb21wb25lbnQpO1xuICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy52ZXJ0aWNhbFNjcm9sbEhhbmRsZXIgPSB0aGlzLnZlcnRpY2FsU2Nyb2xsSGFuZGxlci5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy52ZXJ0aWNhbFNjcm9sbEhhbmRsZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2Uuc2Nyb2xsQ29udGFpbmVyID0gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgZGVzdHJ1Y3RvciA9IHRha2VVbnRpbDxhbnk+KHRoaXMuZGVzdHJveSQpO1xuICAgICAgICAgICAgdGhpcy5jb250ZW50UmVzaXplTm90aWZ5LnBpcGUoZGVzdHJ1Y3RvcixcbiAgICAgICAgICAgIGZpbHRlcigoKSA9PiB0aGlzLmlneEZvckNvbnRhaW5lclNpemUgJiYgdGhpcy5pZ3hGb3JPZiAmJiB0aGlzLmlneEZvck9mLmxlbmd0aCA+IDApLCB0aHJvdHRsZVRpbWUoNDApKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5UYXNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTaXplcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICB0aGlzLmZ1bmMgPSAoZXZ0KSA9PiB7IHRoaXMub25IU2Nyb2xsKGV2dCk7IH07XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudCA9IHRoaXMuc3luY1Njcm9sbFNlcnZpY2UuZ2V0U2Nyb2xsTWFzdGVyKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNjcm9sbENvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh2RmFjdG9yeTogQ29tcG9uZW50RmFjdG9yeTxIVmlydHVhbEhlbHBlckNvbXBvbmVudD4gPVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KEhWaXJ0dWFsSGVscGVyQ29tcG9uZW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudCA9IHZjLmNyZWF0ZUNvbXBvbmVudChodkZhY3RvcnkpLmluc3RhbmNlO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgPSB0b3RhbFNpemU7XG4gICAgICAgICAgICAgICAgdGhpcy5zeW5jU2Nyb2xsU2VydmljZS5zZXRTY3JvbGxNYXN0ZXIodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiwgdGhpcy5zY3JvbGxDb21wb25lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuZnVuYyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2Uuc2Nyb2xsQ29udGFpbmVyID0gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5mdW5jKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5zY3JvbGxDb250YWluZXIgPSB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlSFNjcm9sbE9mZnNldCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZW50T2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdGhpcy5jb250ZW50UmVzaXplTm90aWZ5Lm5leHQoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZW50T2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlU2Nyb2xsRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgICAgIGlmICh0aGlzLmNvbnRlbnRPYnNlcnZlcikge1xuICAgICAgICAgICAgdGhpcy5jb250ZW50T2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGZvck9mID0gJ2lneEZvck9mJztcbiAgICAgICAgaWYgKGZvck9mIGluIGNoYW5nZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gY2hhbmdlc1tmb3JPZl0uY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9kaWZmZXIgJiYgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kaWZmZXIgPSB0aGlzLl9kaWZmZXJzLmZpbmQodmFsdWUpLmNyZWF0ZSh0aGlzLmlneEZvclRyYWNrQnkpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYENhbm5vdCBmaW5kIGEgZGlmZmVyIHN1cHBvcnRpbmcgb2JqZWN0IFwiJHt2YWx1ZX1cIiBvZiB0eXBlIFwiJHtnZXRUeXBlTmFtZUZvckRlYnVnZ2luZyh2YWx1ZSl9XCIuXG4gICAgICAgICAgICAgICAgICAgICBOZ0ZvciBvbmx5IHN1cHBvcnRzIGJpbmRpbmcgdG8gSXRlcmFibGVzIHN1Y2ggYXMgQXJyYXlzLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZWZhdWx0SXRlbVNpemUgPSAnaWd4Rm9ySXRlbVNpemUnO1xuICAgICAgICBpZiAoZGVmYXVsdEl0ZW1TaXplIGluIGNoYW5nZXMgJiYgIWNoYW5nZXNbZGVmYXVsdEl0ZW1TaXplXS5maXJzdENoYW5nZSAmJlxuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJyAmJiB0aGlzLmlneEZvck9mKSB7XG4gICAgICAgICAgICAvLyBoYW5kbGUgZGVmYXVsdCBpdGVtIHNpemUgY2hhbmdlZC5cbiAgICAgICAgICAgIHRoaXMuaW5pdFNpemVzQ2FjaGUodGhpcy5pZ3hGb3JPZik7XG4gICAgICAgICAgICB0aGlzLl9hcHBseUNoYW5nZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb250YWluZXJTaXplID0gJ2lneEZvckNvbnRhaW5lclNpemUnO1xuICAgICAgICBpZiAoY29udGFpbmVyU2l6ZSBpbiBjaGFuZ2VzICYmICFjaGFuZ2VzW2NvbnRhaW5lclNpemVdLmZpcnN0Q2hhbmdlICYmIHRoaXMuaWd4Rm9yT2YpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlY2FsY09uQ29udGFpbmVyQ2hhbmdlKGNoYW5nZXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ0RvQ2hlY2soKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLl9kaWZmZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZXMgPSB0aGlzLl9kaWZmZXIuZGlmZih0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgLy8gIHJlLWluaXQgY2FjaGUuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlneEZvck9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWd4Rm9yT2YgPSBbXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlU2l6ZUNhY2hlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9hcHBseUNoYW5nZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVNjcm9sbE9mZnNldCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uRGF0YUNoYW5nZWQuZW1pdCgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hpZnRzIHRoZSBzY3JvbGwgdGh1bWIgcG9zaXRpb24uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5hZGRTY3JvbGxUb3AoNSk7XG4gICAgICogYGBgXG4gICAgICogQHBhcmFtIGFkZFRvcCBuZWdhdGl2ZSB2YWx1ZSB0byBzY3JvbGwgdXAgYW5kIHBvc2l0aXZlIHRvIHNjcm9sbCBkb3duO1xuICAgICAqL1xuICAgIHB1YmxpYyBhZGRTY3JvbGxUb3AoYWRkVG9wOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKGFkZFRvcCA9PT0gMCAmJiB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcmlnaW5hbFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0U2Nyb2xsVG9wO1xuICAgICAgICBjb25zdCBjb250YWluZXJTaXplID0gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCk7XG4gICAgICAgIGNvbnN0IG1heFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0SGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcblxuICAgICAgICB0aGlzLl9iU2Nyb2xsSW50ZXJuYWwgPSB0cnVlO1xuICAgICAgICB0aGlzLl92aXJ0U2Nyb2xsVG9wICs9IGFkZFRvcDtcbiAgICAgICAgdGhpcy5fdmlydFNjcm9sbFRvcCA9IHRoaXMuX3ZpcnRTY3JvbGxUb3AgPiAwID9cbiAgICAgICAgICAgICh0aGlzLl92aXJ0U2Nyb2xsVG9wIDwgbWF4VmlydFNjcm9sbFRvcCA/IHRoaXMuX3ZpcnRTY3JvbGxUb3AgOiBtYXhWaXJ0U2Nyb2xsVG9wKSA6XG4gICAgICAgICAgICAwO1xuXG4gICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gKz0gYWRkVG9wIC8gdGhpcy5fdmlydEhlaWdodFJhdGlvO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYWRkVG9wIC8gdGhpcy5fdmlydEhlaWdodFJhdGlvKSA8IDEpIHtcbiAgICAgICAgICAgIC8vIEFjdHVhbCBzY3JvbGwgZGVsdGEgdGhhdCB3YXMgYWRkZWQgaXMgc21hbGxlciB0aGFuIDEgYW5kIG9uU2Nyb2xsIGhhbmRsZXIgZG9lc24ndCB0cmlnZ2VyIHdoZW4gc2Nyb2xsaW5nIDwgMXB4XG4gICAgICAgICAgICBjb25zdCBzY3JvbGxPZmZzZXQgPSB0aGlzLmZpeGVkVXBkYXRlQWxsRWxlbWVudHModGhpcy5fdmlydFNjcm9sbFRvcCk7XG4gICAgICAgICAgICAvLyBzY3JvbGxPZmZzZXQgPSBzY3JvbGxPZmZzZXQgIT09IHBhcnNlSW50KHRoaXMuaWd4Rm9ySXRlbVNpemUsIDEwKSA/IHNjcm9sbE9mZnNldCA6IDA7XG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAtKHNjcm9sbE9mZnNldCkgKyAncHgnO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbWF4UmVhbFNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsSGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcbiAgICAgICAgaWYgKCh0aGlzLl92aXJ0U2Nyb2xsVG9wID4gMCAmJiB0aGlzLnNjcm9sbFBvc2l0aW9uID09PSAwKSB8fFxuICAgICAgICAgICAgKHRoaXMuX3ZpcnRTY3JvbGxUb3AgPCBtYXhWaXJ0U2Nyb2xsVG9wICYmIHRoaXMuc2Nyb2xsUG9zaXRpb24gPT09IG1heFJlYWxTY3JvbGxUb3ApKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWwgc2Nyb2xsIHBvc2l0aW9uIGlzIGF0IHRoZSB0b3Agb3IgYm90dG9tLCBidXQgdmlydHVhbCBvbmUgaXMgbm90IGF0IHRoZSB0b3Agb3IgYm90dG9tICh0aGVyZSdzIG1vcmUgdG8gc2Nyb2xsKVxuICAgICAgICAgICAgLy8gUmVjYWxjdWxhdGUgYWN0dWFsIHNjcm9sbCBwb3NpdGlvbiBiYXNlZCBvbiB0aGUgdmlydHVhbCBzY3JvbGwuXG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gdGhpcy5fdmlydFNjcm9sbFRvcCAvIHRoaXMuX3ZpcnRIZWlnaHRSYXRpbztcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl92aXJ0U2Nyb2xsVG9wID09PSAwICYmIHRoaXMuc2Nyb2xsUG9zaXRpb24gPiAwKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWwgc2Nyb2xsIHBvc2l0aW9uIGlzIG5vdCBhdCB0aGUgdG9wLCBidXQgdmlydHVhbCBzY3JvbGwgaXMuIEp1c3QgdXBkYXRlIHRoZSBhY3R1YWwgc2Nyb2xsXG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gMDtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl92aXJ0U2Nyb2xsVG9wID09PSBtYXhWaXJ0U2Nyb2xsVG9wICYmIHRoaXMuc2Nyb2xsUG9zaXRpb24gPCBtYXhSZWFsU2Nyb2xsVG9wKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWwgc2Nyb2xsIHBvc2l0aW9uIGlzIG5vdCBhdCB0aGUgYm90dG9tLCBidXQgdmlydHVhbCBzY3JvbGwgaXMuIEp1c3QgdXBkYXRlIHRoZSBhY3VhbCBzY3JvbGxcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gPSBtYXhSZWFsU2Nyb2xsVG9wO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl92aXJ0U2Nyb2xsVG9wICE9PSBvcmlnaW5hbFZpcnRTY3JvbGxUb3A7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2Nyb2xscyB0byB0aGUgc3BlY2lmaWVkIGluZGV4LlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnBhcmVudFZpcnREaXIuc2Nyb2xsVG8oNSk7XG4gICAgICogYGBgXG4gICAgICogQHBhcmFtIGluZGV4XG4gICAgICovXG4gICAgcHVibGljIHNjcm9sbFRvKGluZGV4KSB7XG4gICAgICAgIGlmIChpbmRleCA8IDAgfHwgaW5kZXggPiAodGhpcy5pc1JlbW90ZSA/IHRoaXMudG90YWxJdGVtQ291bnQgOiB0aGlzLmlneEZvck9mLmxlbmd0aCkgLSAxKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICBjb25zdCBpc1ByZXZJdGVtID0gaW5kZXggPCB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggfHwgdGhpcy5zY3JvbGxQb3NpdGlvbiA+IHRoaXMuc2l6ZXNDYWNoZVtpbmRleF07XG4gICAgICAgIGxldCBuZXh0U2Nyb2xsID0gaXNQcmV2SXRlbSA/IHRoaXMuc2l6ZXNDYWNoZVtpbmRleF0gOiB0aGlzLnNpemVzQ2FjaGVbaW5kZXggKyAxXSAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgIGlmIChuZXh0U2Nyb2xsIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gPSBuZXh0U2Nyb2xsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbWF4VmlydFNjcm9sbFRvcCA9IHRoaXMuX3ZpcnRIZWlnaHQgLSBjb250YWluZXJTaXplO1xuICAgICAgICAgICAgaWYgKG5leHRTY3JvbGwgPiBtYXhWaXJ0U2Nyb2xsVG9wKSB7XG4gICAgICAgICAgICAgICAgbmV4dFNjcm9sbCA9IG1heFZpcnRTY3JvbGxUb3A7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9iU2Nyb2xsSW50ZXJuYWwgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fdmlydFNjcm9sbFRvcCA9IG5leHRTY3JvbGw7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gdGhpcy5fdmlydFNjcm9sbFRvcCAvIHRoaXMuX3ZpcnRIZWlnaHRSYXRpbztcbiAgICAgICAgICAgIHRoaXMuX2FkanVzdFRvSW5kZXggPSAhaXNQcmV2SXRlbSA/IGluZGV4IDogbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjcm9sbHMgYnkgb25lIGl0ZW0gaW50byB0aGUgYXBwcm9wcmlhdGUgbmV4dCBkaXJlY3Rpb24uXG4gICAgICogRm9yIFwiaG9yaXpvbnRhbFwiIG9yaWVudGF0aW9uIHRoYXQgd2lsbCBiZSB0aGUgcmlnaHQgY29sdW1uIGFuZCBmb3IgXCJ2ZXJ0aWNhbFwiIHRoYXQgaXMgdGhlIGxvd2VyIHJvdy5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy5wYXJlbnRWaXJ0RGlyLnNjcm9sbE5leHQoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2Nyb2xsTmV4dCgpIHtcbiAgICAgICAgY29uc3Qgc2NyID0gTWF0aC5jZWlsKHRoaXMuc2Nyb2xsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCBlbmRJbmRleCA9IHRoaXMuZ2V0SW5kZXhBdChcbiAgICAgICAgICAgIHNjciArIHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApLFxuICAgICAgICAgICAgdGhpcy5zaXplc0NhY2hlLFxuICAgICAgICAgICAgMFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnNjcm9sbFRvKGVuZEluZGV4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTY3JvbGxzIGJ5IG9uZSBpdGVtIGludG8gdGhlIGFwcHJvcHJpYXRlIHByZXZpb3VzIGRpcmVjdGlvbi5cbiAgICAgKiBGb3IgXCJob3Jpem9udGFsXCIgb3JpZW50YXRpb24gdGhhdCB3aWxsIGJlIHRoZSBsZWZ0IGNvbHVtbiBhbmQgZm9yIFwidmVydGljYWxcIiB0aGF0IGlzIHRoZSB1cHBlciByb3cuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5zY3JvbGxQcmV2KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHNjcm9sbFByZXYoKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsVG8odGhpcy5zdGF0ZS5zdGFydEluZGV4IC0gMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2Nyb2xscyBieSBvbmUgcGFnZSBpbnRvIHRoZSBhcHByb3ByaWF0ZSBuZXh0IGRpcmVjdGlvbi5cbiAgICAgKiBGb3IgXCJob3Jpem9udGFsXCIgb3JpZW50YXRpb24gdGhhdCB3aWxsIGJlIG9uZSB2aWV3IHRvIHRoZSByaWdodCBhbmQgZm9yIFwidmVydGljYWxcIiB0aGF0IGlzIG9uZSB2aWV3IHRvIHRoZSBib3R0b20uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5zY3JvbGxOZXh0UGFnZSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBzY3JvbGxOZXh0UGFnZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbiArPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYWRkU2Nyb2xsVG9wKHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjcm9sbHMgYnkgb25lIHBhZ2UgaW50byB0aGUgYXBwcm9wcmlhdGUgcHJldmlvdXMgZGlyZWN0aW9uLlxuICAgICAqIEZvciBcImhvcml6b250YWxcIiBvcmllbnRhdGlvbiB0aGF0IHdpbGwgYmUgb25lIHZpZXcgdG8gdGhlIGxlZnQgYW5kIGZvciBcInZlcnRpY2FsXCIgdGhhdCBpcyBvbmUgdmlldyB0byB0aGUgdG9wLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnBhcmVudFZpcnREaXIuc2Nyb2xsUHJldlBhZ2UoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2Nyb2xsUHJldlBhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gLT0gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBjb250YWluZXJTaXplID0gKHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApKTtcbiAgICAgICAgICAgIHRoaXMuYWRkU2Nyb2xsVG9wKC1jb250YWluZXJTaXplKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Q29sdW1uU2Nyb2xsTGVmdChjb2xJbmRleCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zaXplc0NhY2hlW2NvbEluZGV4XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgaXRlbXMgdGhhdCBhcmUgZnVsbHkgdmlzaWJsZS5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy5wYXJlbnRWaXJ0RGlyLmdldEl0ZW1Db3VudEluVmlldygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRJdGVtQ291bnRJblZpZXcoKSB7XG4gICAgICAgIGxldCBzdGFydEluZGV4ID0gdGhpcy5nZXRJbmRleEF0KFxuICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbixcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZSxcbiAgICAgICAgICAgIDBcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHRoaXMuc2Nyb2xsUG9zaXRpb24gLSB0aGlzLnNpemVzQ2FjaGVbc3RhcnRJbmRleF0gPiAwKSB7XG4gICAgICAgICAgICAvLyBmaXNydCBpdGVtIGlzIG5vdCBmdWxseSBpbiB2aWV3XG4gICAgICAgICAgICBzdGFydEluZGV4Kys7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZW5kSW5kZXggPSB0aGlzLmdldEluZGV4QXQoXG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uICsgcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCksXG4gICAgICAgICAgICB0aGlzLnNpemVzQ2FjaGUsXG4gICAgICAgICAgICAwXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBlbmRJbmRleCAtIHN0YXJ0SW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgc2Nyb2xsYmFyIERPTSBlbGVtZW50LlxuICAgICAqIFRoaXMgaXMgZWl0aGVyIGEgdmVydGljYWwgb3IgaG9yaXpvbnRhbCBzY3JvbGxiYXIgZGVwZW5kaW5nIG9uIHRoZSBzcGVjaWZpZWQgaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGRpci5nZXRTY3JvbGwoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0U2Nyb2xsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgc2l6ZSBvZiB0aGUgZWxlbWVudCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnBhcmVudFZpcnREaXIuZ2V0U2l6ZUF0KDEpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTaXplQXQoaW5kZXg6IG51bWJlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zaXplc0NhY2hlW2luZGV4ICsgMV0gLSB0aGlzLnNpemVzQ2FjaGVbaW5kZXhdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNjcm9sbCBvZmZzZXQgb2YgdGhlIGVsZW1lbnQgYXQgdGhlIHNwZWNpZmllZCBpbmRleC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy5wYXJlbnRWaXJ0RGlyLmdldFNjcm9sbEZvckluZGV4KDEpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTY3JvbGxGb3JJbmRleChpbmRleDogbnVtYmVyLCBib3R0b20/OiBib29sZWFuKSB7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lclNpemUgPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKTtcbiAgICAgICAgY29uc3Qgc2Nyb2xsID0gYm90dG9tID8gTWF0aC5tYXgoMCwgdGhpcy5zaXplc0NhY2hlW2luZGV4ICsgMV0gLSBjb250YWluZXJTaXplKSA6IHRoaXMuc2l6ZXNDYWNoZVtpbmRleF07XG4gICAgICAgIHJldHVybiBzY3JvbGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIEZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gc2Nyb2xsaW5nIHZlcnRpY2FsbHlcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgb25TY3JvbGwoZXZlbnQpIHtcbiAgICAgICAgLyogaW4gY2VydGFpbiBzaXR1YXRpb25zIHRoaXMgbWF5IGJlIGNhbGxlZCB3aGVuIG5vIHNjcm9sbGJhciBpcyB2aXNpYmxlICovXG4gICAgICAgIGlmICghcGFyc2VJbnQodGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQsIDEwKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICBjb25zdCBtYXhSZWFsU2Nyb2xsVG9wID0gZXZlbnQudGFyZ2V0LmNoaWxkcmVuWzBdLnNjcm9sbEhlaWdodCAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgIGNvbnN0IHJlYWxQZXJjZW50U2Nyb2xsZWQgPSBtYXhSZWFsU2Nyb2xsVG9wICE9PSAwID8gIGV2ZW50LnRhcmdldC5zY3JvbGxUb3AgLyBtYXhSZWFsU2Nyb2xsVG9wIDogMDtcbiAgICAgICAgaWYgKCF0aGlzLl9iU2Nyb2xsSW50ZXJuYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0SGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcbiAgICAgICAgICAgIHRoaXMuX3ZpcnRTY3JvbGxUb3AgPSByZWFsUGVyY2VudFNjcm9sbGVkICogbWF4VmlydFNjcm9sbFRvcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2JTY3JvbGxJbnRlcm5hbCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByZXZTdGFydEluZGV4ID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4O1xuICAgICAgICBjb25zdCBzY3JvbGxPZmZzZXQgPSB0aGlzLmZpeGVkVXBkYXRlQWxsRWxlbWVudHModGhpcy5fdmlydFNjcm9sbFRvcCk7XG5cbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUudG9wID0gLShzY3JvbGxPZmZzZXQpICsgJ3B4JztcblxuICAgICAgICB0aGlzLmRjLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgaWYgKHByZXZTdGFydEluZGV4ICE9PSB0aGlzLnN0YXRlLnN0YXJ0SW5kZXgpIHtcbiAgICAgICAgICAgIHRoaXMub25DaHVua0xvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCB1cGRhdGVTaXplcygpIHtcbiAgICAgICAgdGhpcy5yZWNhbGNVcGRhdGVTaXplcygpO1xuICAgICAgICB0aGlzLl9hcHBseUNoYW5nZXMoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlU2Nyb2xsT2Zmc2V0KCk7XG4gICAgICAgIHRoaXMub25Db250ZW50U2l6ZUNoYW5nZS5lbWl0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIEZ1bmN0aW9uIHRoYXQgcmVjYWN1bGF0ZXMgYW5kIHVwZGF0ZXMgY2FjaGUgc2l6ZXMuXG4gICAgICovXG4gICAgcHVibGljIHJlY2FsY1VwZGF0ZVNpemVzKCkge1xuICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcgP1xuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICAgICAgY29uc3QgZGlmZnMgPSBbXTtcbiAgICAgICAgbGV0IHRvdGFsRGlmZiA9IDA7XG4gICAgICAgIGNvbnN0IGwgPSB0aGlzLl9lbWJlZGRlZFZpZXdzLmxlbmd0aDtcbiAgICAgICAgY29uc3Qgck5vZGVzID0gdGhpcy5fZW1iZWRkZWRWaWV3cy5tYXAodmlldyA9PlxuICAgICAgICAgICAgdmlldy5yb290Tm9kZXMuZmluZChub2RlID0+IG5vZGUubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB8fCB2aWV3LnJvb3ROb2Rlc1swXS5uZXh0RWxlbWVudFNpYmxpbmcpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgck5vZGUgPSByTm9kZXNbaV07XG4gICAgICAgICAgICBpZiAock5vZGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoID0gck5vZGUub2Zmc2V0SGVpZ2h0IHx8IHBhcnNlSW50KHRoaXMuaWd4Rm9ySXRlbVNpemUsIDEwKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIGk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzUmVtb3RlICYmICF0aGlzLmlneEZvck9mW2luZGV4XSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsID0gZGltZW5zaW9uID09PSAnaGVpZ2h0JyA/IHRoaXMuaGVpZ2h0Q2FjaGVbaW5kZXhdIDogdGhpcy5pZ3hGb3JPZltpbmRleF1bZGltZW5zaW9uXTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdWYWwgPSBkaW1lbnNpb24gPT09ICdoZWlnaHQnID8gaCA6IHJOb2RlLmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgICAgIGlmIChkaW1lbnNpb24gPT09ICdoZWlnaHQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0Q2FjaGVbaW5kZXhdID0gbmV3VmFsO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWd4Rm9yT2ZbaW5kZXhdW2RpbWVuc2lvbl0gPSBuZXdWYWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJEaWZmID0gbmV3VmFsIC0gb2xkVmFsO1xuICAgICAgICAgICAgICAgIGRpZmZzLnB1c2goY3VyckRpZmYpO1xuICAgICAgICAgICAgICAgIHRvdGFsRGlmZiArPSBjdXJyRGlmZjtcbiAgICAgICAgICAgICAgICB0aGlzLnNpemVzQ2FjaGVbaW5kZXggKyAxXSArPSB0b3RhbERpZmY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gdXBkYXRlIGNhY2hlXG4gICAgICAgIGlmIChNYXRoLmFicyh0b3RhbERpZmYpID4gMCkge1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIHRoaXMuc3RhdGUuY2h1bmtTaXplICsgMTsgaiA8IHRoaXMuc2l6ZXNDYWNoZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZVtqXSArPSB0b3RhbERpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHVwZGF0ZSBzY3JCYXIgaGVpZ2h0cy93aWR0aHNcbiAgICAgICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0b3RhbFdpZHRoID0gcGFyc2VJbnQodGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5jaGlsZHJlblswXS5zdHlsZS53aWR0aCwgMTApICsgdG90YWxEaWZmO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuY2hpbGRyZW5bMF0uc3R5bGUud2lkdGggPSB0b3RhbFdpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlZHVjZXIgPSAoYWNjLCB2YWwpID0+IGFjYyArIHZhbDtcbiAgICAgICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAndmVydGljYWwnKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NyVG9Cb3R0b20gPSB0aGlzLl9pc1Njcm9sbGVkVG9Cb3R0b20gJiYgIXRoaXMuZGMuaW5zdGFuY2Uubm90VmlydHVhbDtcbiAgICAgICAgICAgICAgICBjb25zdCBoU3VtID0gdGhpcy5oZWlnaHRDYWNoZS5yZWR1Y2UocmVkdWNlcik7XG4gICAgICAgICAgICAgICAgaWYgKGhTdW0gPiB0aGlzLl9tYXhIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlydEhlaWdodFJhdGlvID0gaFN1bSAvIHRoaXMuX21heEhlaWdodDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQuc2l6ZSA9IE1hdGgubWluKHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgKyB0b3RhbERpZmYsIHRoaXMuX21heEhlaWdodCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlydEhlaWdodCA9IGhTdW07XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnNjcm9sbENvbXBvbmVudC5kZXN0cm95ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHNjclRvQm90dG9tICYmICF0aGlzLl9pc0F0Qm90dG9tSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXhWaXJ0U2Nyb2xsVG9wID0gdGhpcy5fdmlydEhlaWdodCAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2JTY3JvbGxJbnRlcm5hbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpcnRTY3JvbGxUb3AgPSBtYXhWaXJ0U2Nyb2xsVG9wO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gbWF4VmlydFNjcm9sbFRvcDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fYWRqdXN0VG9JbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpbiBjYXNlIHNjcm9sbGVkIHRvIHNwZWNpZmljIGluZGV4IHdoZXJlIGFmdGVyIHNjcm9sbCBoZWlnaHRzIGFyZSBjaGFuZ2VkXG4gICAgICAgICAgICAgICAgICAgIC8vIG5lZWQgdG8gYWRqdXN0IHRoZSBvZmZzZXRzIHNvIHRoYXQgaXRlbSBpcyBsYXN0IGluIHZpZXcuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVwZGF0ZXNUb0luZGV4ID0gdGhpcy5fYWRqdXN0VG9JbmRleCAtIHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1bURpZmZzID0gZGlmZnMuc2xpY2UoMCwgdXBkYXRlc1RvSW5kZXgpLnJlZHVjZShyZWR1Y2VyKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY3Vyck9mZnNldCA9IHBhcnNlSW50KHRoaXMuZGMuaW5zdGFuY2UuX3ZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRvcCwgMTApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAoY3Vyck9mZnNldCAtIHN1bURpZmZzKSArICdweCc7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkanVzdFRvSW5kZXggPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZml4ZWRVcGRhdGVBbGxFbGVtZW50cyhpblNjcm9sbFRvcDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmlzUmVtb3RlID8gdGhpcy50b3RhbEl0ZW1Db3VudCA6IHRoaXMuaWd4Rm9yT2YubGVuZ3RoO1xuICAgICAgICBsZXQgbmV3U3RhcnQgPSB0aGlzLmdldEluZGV4QXQoXG4gICAgICAgICAgICBpblNjcm9sbFRvcCxcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZSxcbiAgICAgICAgICAgIDBcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKG5ld1N0YXJ0ICsgdGhpcy5zdGF0ZS5jaHVua1NpemUgPiBjb3VudCkge1xuICAgICAgICAgICAgbmV3U3RhcnQgPSBjb3VudCAtIHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByZXZTdGFydCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleDtcbiAgICAgICAgY29uc3QgZGlmZiA9IG5ld1N0YXJ0IC0gdGhpcy5zdGF0ZS5zdGFydEluZGV4O1xuICAgICAgICB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggPSBuZXdTdGFydDtcbiAgICAgICAgaWYgKGRpZmYpIHtcbiAgICAgICAgICAgIHRoaXMub25DaHVua1ByZWxvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgICAgIC8qcmVjYWxjdWxhdGUgYW5kIGFwcGx5IHBhZ2Ugc2l6ZS4qL1xuICAgICAgICAgICAgICAgIGlmIChkaWZmID4gMCAmJiBkaWZmIDw9IHRoaXMuTUFYX1BFUkZfU0NST0xMX0RJRkYpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlQXBwbHlTY3JvbGxOZXh0KHByZXZTdGFydCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkaWZmIDwgMCAmJiBNYXRoLmFicyhkaWZmKSA8PSB0aGlzLk1BWF9QRVJGX1NDUk9MTF9ESUZGKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubW92ZUFwcGx5U2Nyb2xsUHJldihwcmV2U3RhcnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZml4ZWRBcHBseVNjcm9sbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW5TY3JvbGxUb3AgLSB0aGlzLnNpemVzQ2FjaGVbdGhpcy5zdGF0ZS5zdGFydEluZGV4XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogVGhlIGZ1bmN0aW9uIGFwcGxpZXMgYW4gb3B0aW1pemVkIHN0YXRlIGNoYW5nZSBmb3Igc2Nyb2xsaW5nIGRvd24vcmlnaHQgZW1wbG95aW5nIGNvbnRleHQgY2hhbmdlIHdpdGggdmlldyByZWFycmFuZ2VtZW50XG4gICAgICovXG4gICAgcHJvdGVjdGVkIG1vdmVBcHBseVNjcm9sbE5leHQocHJldkluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc3RhcnQgPSBwcmV2SW5kZXggKyB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggLSBwcmV2SW5kZXggJiYgdGhpcy5pZ3hGb3JPZltpXSAhPT0gdW5kZWZpbmVkOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlucHV0ID0gdGhpcy5pZ3hGb3JPZltpXTtcbiAgICAgICAgICAgIGNvbnN0IGVtYlZpZXcgPSB0aGlzLl9lbWJlZGRlZFZpZXdzLnNoaWZ0KCk7XG4gICAgICAgICAgICBjb25zdCBjbnR4ID0gZW1iVmlldy5jb250ZXh0O1xuICAgICAgICAgICAgY250eC4kaW1wbGljaXQgPSBpbnB1dDtcbiAgICAgICAgICAgIGNudHguaW5kZXggPSB0aGlzLmdldENvbnRleHRJbmRleChpbnB1dCk7XG4gICAgICAgICAgICBjbnR4LmNvdW50ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCB2aWV3OiBWaWV3UmVmID0gdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmRldGFjaCgwKTtcbiAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5pbnNlcnQodmlldyk7XG4gICAgICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnB1c2goZW1iVmlldyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogVGhlIGZ1bmN0aW9uIGFwcGxpZXMgYW4gb3B0aW1pemVkIHN0YXRlIGNoYW5nZSBmb3Igc2Nyb2xsaW5nIHVwL2xlZnQgZW1wbG95aW5nIGNvbnRleHQgY2hhbmdlIHdpdGggdmlldyByZWFycmFuZ2VtZW50XG4gICAgICovXG4gICAgcHJvdGVjdGVkIG1vdmVBcHBseVNjcm9sbFByZXYocHJldkluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHByZXZJbmRleCAtIDE7IGkgPj0gdGhpcy5zdGF0ZS5zdGFydEluZGV4ICYmIHRoaXMuaWd4Rm9yT2ZbaV0gIT09IHVuZGVmaW5lZDsgaS0tKSB7XG4gICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICBjb25zdCBlbWJWaWV3ID0gdGhpcy5fZW1iZWRkZWRWaWV3cy5wb3AoKTtcbiAgICAgICAgICAgIGNvbnN0IGNudHggPSBlbWJWaWV3LmNvbnRleHQ7XG4gICAgICAgICAgICBjbnR4LiRpbXBsaWNpdCA9IGlucHV0O1xuICAgICAgICAgICAgY250eC5pbmRleCA9IHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KTtcbiAgICAgICAgICAgIGNvbnN0IHZpZXc6IFZpZXdSZWYgPSB0aGlzLmRjLmluc3RhbmNlLl92Y3IuZGV0YWNoKHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5pbnNlcnQodmlldywgMCk7XG4gICAgICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnVuc2hpZnQoZW1iVmlldyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0Q29udGV4dEluZGV4KGlucHV0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzUmVtb3RlID8gdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5pZ3hGb3JPZi5pbmRleE9mKGlucHV0KSA6IHRoaXMuaWd4Rm9yT2YuaW5kZXhPZihpbnB1dCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIFRoZSBmdW5jdGlvbiBhcHBsaWVzIGFuIG9wdGltaXplZCBzdGF0ZSBjaGFuZ2UgdGhyb3VnaCBjb250ZXh0IGNoYW5nZSBmb3IgZWFjaCB2aWV3XG4gICAgICovXG4gICAgcHJvdGVjdGVkIGZpeGVkQXBwbHlTY3JvbGwoKTogdm9pZCB7XG4gICAgICAgIGxldCBqID0gMDtcbiAgICAgICAgY29uc3QgZW5kSW5kZXggPSB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggKyB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleDsgaSA8IGVuZEluZGV4ICYmIHRoaXMuaWd4Rm9yT2ZbaV0gIT09IHVuZGVmaW5lZDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICBjb25zdCBlbWJWaWV3ID0gdGhpcy5fZW1iZWRkZWRWaWV3c1tqKytdO1xuICAgICAgICAgICAgY29uc3QgY250eCA9IChlbWJWaWV3IGFzIEVtYmVkZGVkVmlld1JlZjxhbnk+KS5jb250ZXh0O1xuICAgICAgICAgICAgY250eC4kaW1wbGljaXQgPSBpbnB1dDtcbiAgICAgICAgICAgIGNudHguaW5kZXggPSB0aGlzLmdldENvbnRleHRJbmRleChpbnB1dCk7XG4gICAgICAgICAgICBjbnR4LmNvdW50ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiBzY3JvbGxpbmcgaG9yaXpvbnRhbGx5XG4gICAgICovXG4gICAgcHJvdGVjdGVkIG9uSFNjcm9sbChldmVudCkge1xuICAgICAgICAvKiBpbiBjZXJ0YWluIHNpdHVhdGlvbnMgdGhpcyBtYXkgYmUgY2FsbGVkIHdoZW4gbm8gc2Nyb2xsYmFyIGlzIHZpc2libGUgKi9cbiAgICAgICAgaWYgKCFwYXJzZUludCh0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LmNoaWxkcmVuWzBdLnN0eWxlLndpZHRoLCAxMCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcmV2U3RhcnRJbmRleCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleDtcbiAgICAgICAgLy8gVXBkYXRpbmcgaG9yaXpvbnRhbCBjaHVua3NcbiAgICAgICAgY29uc3Qgc2Nyb2xsT2Zmc2V0ID0gdGhpcy5maXhlZFVwZGF0ZUFsbEVsZW1lbnRzKGV2ZW50LnRhcmdldC5zY3JvbGxMZWZ0KTtcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9IC1zY3JvbGxPZmZzZXQgKyAncHgnO1xuXG4gICAgICAgIHRoaXMuZGMuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICBpZiAocHJldlN0YXJ0SW5kZXggIT09IHRoaXMuc3RhdGUuc3RhcnRJbmRleCkge1xuICAgICAgICAgICAgdGhpcy5vbkNodW5rTG9hZC5lbWl0KHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZnVuY3Rpb24gdXNlZCB0byB0cmFjayBjaGFuZ2VzIGluIHRoZSBpdGVtcyBjb2xsZWN0aW9uLlxuICAgICAqIEJ5IGRlZmF1bHQgdGhlIG9iamVjdCByZWZlcmVuY2VzIGFyZSBjb21wYXJlZC4gSG93ZXZlciB0aGlzIGNhbiBiZSBvcHRpbWl6ZWQgaWYgeW91IGhhdmUgdW5pcXVlIGlkZW50aWZpZXJcbiAgICAgKiB2YWx1ZSB0aGF0IGNhbiBiZSB1c2VkIGZvciB0aGUgY29tcGFyaXNvbiBpbnN0ZWFkIG9mIHRoZSBvYmplY3QgcmVmIG9yIGlmIHlvdSBoYXZlIHNvbWUgb3RoZXIgcHJvcGVydHkgdmFsdWVzXG4gICAgICogaW4gdGhlIGl0ZW0gb2JqZWN0IHRoYXQgc2hvdWxkIGJlIHRyYWNrZWQgZm9yIGNoYW5nZXMuXG4gICAgICogVGhpcyBvcHRpb24gaXMgc2ltaWxhciB0byBuZ0ZvclRyYWNrQnkuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IHRyYWNrRnVuYyA9IHRoaXMucGFyZW50VmlydERpci5pZ3hGb3JUcmFja0J5O1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGlneEZvclRyYWNrQnkoKTogVHJhY2tCeUZ1bmN0aW9uPFQ+IHsgcmV0dXJuIHRoaXMuX3RyYWNrQnlGbjsgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgZnVuY3Rpb24gdXNlZCB0byB0cmFjayBjaGFuZ2VzIGluIHRoZSBpdGVtcyBjb2xsZWN0aW9uLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY2FuIGJlIHNldCBpbiBzY2VuYXJpb3Mgd2hlcmUgeW91IHdhbnQgdG8gb3B0aW1pemUgb3JcbiAgICAgKiBjdXN0b21pemUgdGhlIHRyYWNraW5nIG9mIGNoYW5nZXMgZm9yIHRoZSBpdGVtcyBpbiB0aGUgY29sbGVjdGlvbi5cbiAgICAgKiBUaGUgaWd4Rm9yVHJhY2tCeSBmdW5jdGlvbiB0YWtlcyB0aGUgaW5kZXggYW5kIHRoZSBjdXJyZW50IGl0ZW0gYXMgYXJndW1lbnRzIGFuZCBuZWVkcyB0byByZXR1cm4gdGhlIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGlzIGl0ZW0uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5pZ3hGb3JUcmFja0J5ID0gKGluZGV4LCBpdGVtKSA9PiB7XG4gICAgICogICAgICByZXR1cm4gaXRlbS5pZCArIGl0ZW0ud2lkdGg7XG4gICAgICogfTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBzZXQgaWd4Rm9yVHJhY2tCeShmbjogVHJhY2tCeUZ1bmN0aW9uPFQ+KSB7IHRoaXMuX3RyYWNrQnlGbiA9IGZuOyB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9hcHBseUNoYW5nZXMoKSB7XG4gICAgICAgIGNvbnN0IHByZXZDaHVua1NpemUgPSB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgdGhpcy5hcHBseUNodW5rU2l6ZUNoYW5nZSgpO1xuICAgICAgICB0aGlzLl9yZWNhbGNTY3JvbGxCYXJTaXplKCk7XG4gICAgICAgIGlmICh0aGlzLmlneEZvck9mICYmIHRoaXMuaWd4Rm9yT2YubGVuZ3RoICYmIHRoaXMuZGMpIHtcbiAgICAgICAgICAgIGNvbnN0IGVtYmVkZGVkVmlld0NvcHkgPSBPYmplY3QuYXNzaWduKFtdLCB0aGlzLl9lbWJlZGRlZFZpZXdzKTtcbiAgICAgICAgICAgIGxldCBzdGFydEluZGV4ID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4O1xuICAgICAgICAgICAgbGV0IGVuZEluZGV4ID0gdGhpcy5zdGF0ZS5jaHVua1NpemUgKyB0aGlzLnN0YXRlLnN0YXJ0SW5kZXg7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGVuZEluZGV4ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnRJbmRleDsgaSA8IGVuZEluZGV4ICYmIHRoaXMuaWd4Rm9yT2ZbaV0gIT09IHVuZGVmaW5lZDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmlneEZvck9mW2ldO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVtYlZpZXcgPSBlbWJlZGRlZFZpZXdDb3B5LnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY250eCA9IChlbWJWaWV3IGFzIEVtYmVkZGVkVmlld1JlZjxhbnk+KS5jb250ZXh0O1xuICAgICAgICAgICAgICAgIGNudHguJGltcGxpY2l0ID0gaW5wdXQ7XG4gICAgICAgICAgICAgICAgY250eC5pbmRleCA9IHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KTtcbiAgICAgICAgICAgICAgICBjbnR4LmNvdW50ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHJldkNodW5rU2l6ZSAhPT0gdGhpcy5zdGF0ZS5jaHVua1NpemUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ2h1bmtMb2FkLmVtaXQodGhpcy5zdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9jYWxjTWF4QnJvd3NlckhlaWdodCgpOiBudW1iZXIge1xuICAgICAgICBjb25zdCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgY29uc3Qgc3R5bGUgPSBkaXYuc3R5bGU7XG4gICAgICAgIHN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgc3R5bGUudG9wID0gJzk5OTk5OTk5OTk5OTk5OTlweCc7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZGl2KTtcbiAgICAgICAgY29uc3Qgc2l6ZSA9IE1hdGguYWJzKGRpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVsndG9wJ10pO1xuICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGRpdik7XG4gICAgICAgIHJldHVybiBzaXplO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBSZWNhbGN1bGF0ZXMgdGhlIGNodW5rU2l6ZSBiYXNlZCBvbiBjdXJyZW50IHN0YXJ0SW5kZXggYW5kIHJldHVybnMgdGhlIG5ldyBzaXplLlxuICAgICAqIFRoaXMgc2hvdWxkIGJlIGNhbGxlZCBhZnRlciB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggaXMgdXBkYXRlZCwgbm90IGJlZm9yZS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX2NhbGN1bGF0ZUNodW5rU2l6ZSgpOiBudW1iZXIge1xuICAgICAgICBsZXQgY2h1bmtTaXplID0gMDtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSAhPT0gbnVsbCAmJiB0aGlzLmlneEZvckNvbnRhaW5lclNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNpemVzQ2FjaGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2h1bmtTaXplID0gdGhpcy5fY2FsY01heENodW5rU2l6ZSgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaWd4Rm9yT2YgJiYgY2h1bmtTaXplID4gdGhpcy5pZ3hGb3JPZi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjaHVua1NpemUgPSB0aGlzLmlneEZvck9mLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlneEZvck9mKSB7XG4gICAgICAgICAgICAgICAgY2h1bmtTaXplID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNodW5rU2l6ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGdldEVsZW1lbnQodmlld3JlZiwgbm9kZU5hbWUpIHtcbiAgICAgICAgY29uc3QgZWxlbSA9IHZpZXdyZWYuZWxlbWVudC5uYXRpdmVFbGVtZW50LnBhcmVudE5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUobm9kZU5hbWUpO1xuICAgICAgICByZXR1cm4gZWxlbS5sZW5ndGggPiAwID8gZWxlbVswXSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBpbml0U2l6ZXNDYWNoZShpdGVtczogYW55W10pOiBudW1iZXIge1xuICAgICAgICBsZXQgdG90YWxTaXplID0gMDtcbiAgICAgICAgbGV0IHNpemUgPSAwO1xuICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcgP1xuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICB0aGlzLnNpemVzQ2FjaGUgPSBbXTtcbiAgICAgICAgdGhpcy5oZWlnaHRDYWNoZSA9IFtdO1xuICAgICAgICB0aGlzLnNpemVzQ2FjaGUucHVzaCgwKTtcbiAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmlzUmVtb3RlID8gdGhpcy50b3RhbEl0ZW1Db3VudCA6IGl0ZW1zLmxlbmd0aDtcbiAgICAgICAgZm9yIChpOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgaWYgKGRpbWVuc2lvbiA9PT0gJ2hlaWdodCcpIHtcbiAgICAgICAgICAgICAgICAvLyBjb2xzW2ldW2RpbWVuc2lvbl0gPSBwYXJzZUludCh0aGlzLmlneEZvckl0ZW1TaXplLCAxMCkgfHwgMDtcbiAgICAgICAgICAgICAgICBzaXplID0gcGFyc2VJbnQodGhpcy5pZ3hGb3JJdGVtU2l6ZSwgMTApIHx8IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5oZWlnaHRDYWNoZS5wdXNoKHNpemUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaXplID0gdGhpcy5fZ2V0SXRlbVNpemUoaXRlbXNbaV0sIGRpbWVuc2lvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b3RhbFNpemUgKz0gc2l6ZTtcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZS5wdXNoKHRvdGFsU2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRvdGFsU2l6ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVNpemVDYWNoZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgdGhpcy5pbml0U2l6ZXNDYWNoZSh0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSB0aGlzLmhlaWdodENhY2hlLmxlbmd0aCA+IDAgPyB0aGlzLmhlaWdodENhY2hlLnJlZHVjZSgoYWNjLCB2YWwpID0+IGFjYyArIHZhbCkgOiAwO1xuICAgICAgICBjb25zdCBuZXdIZWlnaHQgPSB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuXG4gICAgICAgIGNvbnN0IGRpZmYgPSBvbGRIZWlnaHQgLSBuZXdIZWlnaHQ7XG5cbiAgICAgICAgLy8gaWYgZGF0YSBoYXMgYmVlbiBjaGFuZ2VkIHdoaWxlIGNvbnRhaW5lciBpcyBzY3JvbGxlZFxuICAgICAgICAvLyBzaG91bGQgdXBkYXRlIHNjcm9sbCB0b3AvbGVmdCBhY2NvcmRpbmcgdG8gY2hhbmdlIHNvIHRoYXQgc2FtZSBzdGFydEluZGV4IGlzIGluIHZpZXdcbiAgICAgICAgaWYgKE1hdGguYWJzKGRpZmYpID4gMCAmJiB0aGlzLnNjcm9sbFBvc2l0aW9uID4gMCkge1xuICAgICAgICAgICAgdGhpcy5yZWNhbGNVcGRhdGVTaXplcygpO1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gcGFyc2VJbnQodGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUudG9wLCAxMCk7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gdGhpcy5zaXplc0NhY2hlW3RoaXMuc3RhdGUuc3RhcnRJbmRleF0gLSBvZmZzZXQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9jYWxjTWF4Q2h1bmtTaXplKCk6IG51bWJlciB7XG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgbGV0IGxlbmd0aCA9IDA7XG4gICAgICAgIGxldCBtYXhMZW5ndGggPSAwO1xuICAgICAgICBjb25zdCBhcnIgPSBbXTtcbiAgICAgICAgbGV0IHN1bSA9IDA7XG4gICAgICAgIGNvbnN0IGF2YWlsYWJsZVNpemUgPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKTtcbiAgICAgICAgaWYgKCFhdmFpbGFibGVTaXplKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcgP1xuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICAgICAgY29uc3QgcmVkdWNlciA9IChhY2N1bXVsYXRvciwgY3VycmVudEl0ZW0pID0+IGFjY3VtdWxhdG9yICsgdGhpcy5fZ2V0SXRlbVNpemUoY3VycmVudEl0ZW0sIGRpbWVuc2lvbik7XG4gICAgICAgIGZvciAoaTsgaSA8IHRoaXMuaWd4Rm9yT2YubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxldCBpdGVtID0gdGhpcy5pZ3hGb3JPZltpXTtcbiAgICAgICAgICAgIGlmIChkaW1lbnNpb24gPT09ICdoZWlnaHQnKSB7XG4gICAgICAgICAgICAgICAgaXRlbSA9IHsgdmFsdWU6IHRoaXMuaWd4Rm9yT2ZbaV0sIGhlaWdodDogdGhpcy5oZWlnaHRDYWNoZVtpXSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGRpbWVuc2lvbiA9PT0gJ2hlaWdodCcgP1xuICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0Q2FjaGVbaV0gOlxuICAgICAgICAgICAgICAgIHRoaXMuX2dldEl0ZW1TaXplKGl0ZW0sIGRpbWVuc2lvbik7XG4gICAgICAgICAgICBzdW0gPSBhcnIucmVkdWNlKHJlZHVjZXIsIHNpemUpO1xuICAgICAgICAgICAgaWYgKHN1bSA8IGF2YWlsYWJsZVNpemUpIHtcbiAgICAgICAgICAgICAgICBhcnIucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICBsZW5ndGggPSBhcnIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGlmIChpID09PSB0aGlzLmlneEZvck9mLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVhY2hlZCBlbmQgd2l0aG91dCBleGNlZWRpbmdcbiAgICAgICAgICAgICAgICAgICAgLy8gaW5jbHVkZSBwcmV2IGl0ZW1zIHVudGlsIHNpemUgaXMgZmlsbGVkIG9yIGZpcnN0IGl0ZW0gaXMgcmVhY2hlZC5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGN1ckl0ZW0gPSBkaW1lbnNpb24gPT09ICdoZWlnaHQnID8gYXJyWzBdLnZhbHVlIDogYXJyWzBdO1xuICAgICAgICAgICAgICAgICAgICBsZXQgcHJldkluZGV4ID0gdGhpcy5pZ3hGb3JPZi5pbmRleE9mKGN1ckl0ZW0pIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHByZXZJbmRleCA+PSAwICYmIHN1bSA8PSBhdmFpbGFibGVTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJJdGVtID0gZGltZW5zaW9uID09PSAnaGVpZ2h0JyA/IGFyclswXS52YWx1ZSA6IGFyclswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZJbmRleCA9IHRoaXMuaWd4Rm9yT2YuaW5kZXhPZihjdXJJdGVtKSAtIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwcmV2SXRlbSA9IHRoaXMuaWd4Rm9yT2ZbcHJldkluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZTaXplID0gZGltZW5zaW9uID09PSAnaGVpZ2h0JyA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oZWlnaHRDYWNoZVtwcmV2SW5kZXhdIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJzZUludChwcmV2SXRlbVtkaW1lbnNpb25dLCAxMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdW0gPSBhcnIucmVkdWNlKHJlZHVjZXIsIHByZXZTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyci51bnNoaWZ0KHByZXZJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCA9IGFyci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFyci5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgICAgIGxlbmd0aCA9IGFyci5sZW5ndGggKyAxO1xuICAgICAgICAgICAgICAgIGFyci5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxlbmd0aCA+IG1heExlbmd0aCkge1xuICAgICAgICAgICAgICAgIG1heExlbmd0aCA9IGxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWF4TGVuZ3RoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0SW5kZXhBdChsZWZ0LCBzZXQsIGluZGV4KSB7XG4gICAgICAgIGxldCBzdGFydCA9IDA7XG4gICAgICAgIGxldCBlbmQgPSBzZXQubGVuZ3RoIC0gMTtcbiAgICAgICAgaWYgKGxlZnQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChzdGFydCA8PSBlbmQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1pZElkeCA9IE1hdGguZmxvb3IoKHN0YXJ0ICsgZW5kKSAvIDIpO1xuICAgICAgICAgICAgY29uc3QgbWlkTGVmdCA9IHNldFttaWRJZHhdO1xuICAgICAgICAgICAgY29uc3QgY21wID0gbGVmdCAtIG1pZExlZnQ7XG4gICAgICAgICAgICBpZiAoY21wID4gMCkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gbWlkSWR4ICsgMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY21wIDwgMCkge1xuICAgICAgICAgICAgICAgIGVuZCA9IG1pZElkeCAtIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtaWRJZHg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVuZDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3JlY2FsY1Njcm9sbEJhclNpemUoKSB7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gdGhpcy5pc1JlbW90ZSA/IHRoaXMudG90YWxJdGVtQ291bnQgOiAodGhpcy5pZ3hGb3JPZiA/IHRoaXMuaWd4Rm9yT2YubGVuZ3RoIDogMCk7XG4gICAgICAgIHRoaXMuZGMuaW5zdGFuY2Uubm90VmlydHVhbCA9ICEodGhpcy5pZ3hGb3JDb250YWluZXJTaXplICYmIHRoaXMuZGMgJiYgdGhpcy5zdGF0ZS5jaHVua1NpemUgPCBjb3VudCk7XG4gICAgICAgIGNvbnN0IHNjcm9sbGFibGUgPSB0aGlzLmlzU2Nyb2xsYWJsZSgpO1xuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICBjb25zdCB0b3RhbFdpZHRoID0gdGhpcy5pZ3hGb3JDb250YWluZXJTaXplID8gdGhpcy5pbml0U2l6ZXNDYWNoZSh0aGlzLmlneEZvck9mKSA6IDA7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LnN0eWxlLndpZHRoID0gdGhpcy5pZ3hGb3JDb250YWluZXJTaXplICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgPSB0b3RhbFdpZHRoO1xuICAgICAgICAgICAgaWYgKHRvdGFsV2lkdGggPD0gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKSArICdweCc7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5zaXplID0gdGhpcy5fY2FsY0hlaWdodCgpO1xuICAgICAgICAgICAgaWYgKCB0aGlzLnNjcm9sbENvbXBvbmVudC5zaXplIDw9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNjcm9sbGFibGUgIT09IHRoaXMuaXNTY3JvbGxhYmxlKCkpIHtcbiAgICAgICAgICAgIC8vIHNjcm9sbGJhciB2aXNpYmlsaXR5IGhhcyBjaGFuZ2VkXG4gICAgICAgICAgICB0aGlzLm9uU2Nyb2xsYmFyVmlzaWJpbGl0eUNoYW5nZWQuZW1pdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIF9jYWxjSGVpZ2h0KCk6IG51bWJlciB7XG4gICAgICAgIGxldCBoZWlnaHQ7XG4gICAgICAgIGlmICh0aGlzLmhlaWdodENhY2hlKSB7XG4gICAgICAgICAgICBoZWlnaHQgPSB0aGlzLmhlaWdodENhY2hlLnJlZHVjZSgoYWNjLCB2YWwpID0+IGFjYyArIHZhbCwgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoZWlnaHQgPSB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3ZpcnRIZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGlmIChoZWlnaHQgPiB0aGlzLl9tYXhIZWlnaHQpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZpcnRIZWlnaHRSYXRpbyA9IGhlaWdodCAvIHRoaXMuX21heEhlaWdodDtcbiAgICAgICAgICAgIGhlaWdodCA9IHRoaXMuX21heEhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGVpZ2h0O1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBfcmVjYWxjT25Db250YWluZXJDaGFuZ2UoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAnMHB4JztcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9ICcwcHgnO1xuICAgICAgICBjb25zdCBwcmV2Q2h1bmtTaXplID0gdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgIHRoaXMuYXBwbHlDaHVua1NpemVDaGFuZ2UoKTtcbiAgICAgICAgdGhpcy5fcmVjYWxjU2Nyb2xsQmFyU2l6ZSgpO1xuICAgICAgICBpZiAocHJldkNodW5rU2l6ZSAhPT0gdGhpcy5zdGF0ZS5jaHVua1NpemUpIHtcbiAgICAgICAgICAgIHRoaXMub25DaHVua0xvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zaXplc0NhY2hlICYmIHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgLy8gVXBkYXRpbmcgaG9yaXpvbnRhbCBjaHVua3MgYW5kIG9mZnNldHMgYmFzZWQgb24gdGhlIG5ldyBzY3JvbGxMZWZ0XG4gICAgICAgICAgICBjb25zdCBzY3JvbGxPZmZzZXQgPSB0aGlzLmZpeGVkVXBkYXRlQWxsRWxlbWVudHModGhpcy5zY3JvbGxQb3NpdGlvbik7XG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5sZWZ0ID0gLXNjcm9sbE9mZnNldCArICdweCc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogUmVtb3ZlcyBhbiBlbGVtZW5ldCBmcm9tIHRoZSBlbWJlZGRlZCB2aWV3cyBhbmQgdXBkYXRlcyBjaHVua1NpemUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlbW92ZUxhc3RFbGVtKCkge1xuICAgICAgICBjb25zdCBvbGRFbGVtID0gdGhpcy5fZW1iZWRkZWRWaWV3cy5wb3AoKTtcbiAgICAgICAgdGhpcy5vbkJlZm9yZVZpZXdEZXN0cm95ZWQuZW1pdChvbGRFbGVtKTtcbiAgICAgICAgLy8gYWxzbyBkZXRhY2ggZnJvbSBWaWV3Q29udGFpbmVyUmVmIHRvIG1ha2UgYWJzb2x1dGVseSBzdXJlIHRoaXMgaXMgcmVtb3ZlZCBmcm9tIHRoZSB2aWV3IGNvbnRhaW5lci5cbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmRldGFjaCh0aGlzLmRjLmluc3RhbmNlLl92Y3IubGVuZ3RoIC0gMSk7XG4gICAgICAgIG9sZEVsZW0uZGVzdHJveSgpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUuY2h1bmtTaXplLS07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIElmIHRoZXJlIGV4aXN0cyBhbiBlbGVtZW50IHRoYXQgd2UgY2FuIGNyZWF0ZSBlbWJlZGRlZCB2aWV3IGZvciBjcmVhdGVzIGl0LCBhcHBlbmRzIGl0IGFuZCB1cGRhdGVzIGNodW5rU2l6ZVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhZGRMYXN0RWxlbSgpIHtcbiAgICAgICAgbGV0IGVsZW1JbmRleCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICBpZiAoIXRoaXMuaXNSZW1vdGUgJiYgIXRoaXMuaWd4Rm9yT2YpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlbGVtSW5kZXggPj0gdGhpcy5pZ3hGb3JPZi5sZW5ndGgpIHtcbiAgICAgICAgICAgIGVsZW1JbmRleCA9IHRoaXMuaWd4Rm9yT2YubGVuZ3RoIC0gdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmlneEZvck9mW2VsZW1JbmRleF07XG4gICAgICAgIGNvbnN0IGVtYmVkZGVkVmlldyA9IHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5jcmVhdGVFbWJlZGRlZFZpZXcoXG4gICAgICAgICAgICB0aGlzLl90ZW1wbGF0ZSxcbiAgICAgICAgICAgIG5ldyBJZ3hGb3JPZkNvbnRleHQ8VD4oaW5wdXQsIHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KSwgdGhpcy5pZ3hGb3JPZi5sZW5ndGgpXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5fZW1iZWRkZWRWaWV3cy5wdXNoKGVtYmVkZGVkVmlldyk7XG4gICAgICAgIHRoaXMuc3RhdGUuY2h1bmtTaXplKys7XG5cbiAgICAgICAgdGhpcy5fem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY2FsY3VsYXRlcyBjaHVua1NpemUgYW5kIGFkZHMvcmVtb3ZlcyBlbGVtZW50cyBpZiBuZWVkIGR1ZSB0byB0aGUgY2hhbmdlLlxuICAgICAqIHRoaXMuc3RhdGUuY2h1bmtTaXplIGlzIHVwZGF0ZWQgaW4gQGFkZExhc3RFbGVtKCkgb3IgQHJlbW92ZUxhc3RFbGVtKClcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYXBwbHlDaHVua1NpemVDaGFuZ2UoKSB7XG4gICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IHRoaXMuaXNSZW1vdGUgPyAodGhpcy5pZ3hGb3JPZiA/IHRoaXMuaWd4Rm9yT2YubGVuZ3RoIDogMCkgOiB0aGlzLl9jYWxjdWxhdGVDaHVua1NpemUoKTtcbiAgICAgICAgaWYgKGNodW5rU2l6ZSA+IHRoaXMuc3RhdGUuY2h1bmtTaXplKSB7XG4gICAgICAgICAgICBjb25zdCBkaWZmID0gY2h1bmtTaXplIC0gdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpZmY7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkTGFzdEVsZW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjaHVua1NpemUgPCB0aGlzLnN0YXRlLmNodW5rU2l6ZSkge1xuICAgICAgICAgICAgY29uc3QgZGlmZiA9IHRoaXMuc3RhdGUuY2h1bmtTaXplIC0gY2h1bmtTaXplO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaWZmOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxhc3RFbGVtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVNjcm9sbE9mZnNldCgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlSFNjcm9sbE9mZnNldCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlVlNjcm9sbE9mZnNldCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHByaXZhdGUgX3VwZGF0ZVZTY3JvbGxPZmZzZXQoKSB7XG4gICAgICAgIGxldCBzY3JvbGxPZmZzZXQgPSAwO1xuICAgICAgICBjb25zdCB2U2Nyb2xsID0gIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIHNjcm9sbE9mZnNldCA9IHZTY3JvbGwgJiYgdGhpcy5zY3JvbGxDb21wb25lbnQuc2l6ZSA/XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uIC0gdGhpcy5zaXplc0NhY2hlW3RoaXMuc3RhdGUuc3RhcnRJbmRleF0gOiAwO1xuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAtKHNjcm9sbE9mZnNldCkgKyAncHgnO1xuICAgIH1cbiAgICBwcml2YXRlIF91cGRhdGVIU2Nyb2xsT2Zmc2V0KCkge1xuICAgICAgICBsZXQgc2Nyb2xsT2Zmc2V0ID0gMDtcbiAgICAgICAgc2Nyb2xsT2Zmc2V0ID0gIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQgJiZcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgP1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbiAtIHRoaXMuc2l6ZXNDYWNoZVt0aGlzLnN0YXRlLnN0YXJ0SW5kZXhdIDogMDtcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9IC1zY3JvbGxPZmZzZXQgKyAncHgnO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldEl0ZW1TaXplKGl0ZW0sIGRpbWVuc2lvbjogc3RyaW5nKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgZGltID0gaXRlbVtkaW1lbnNpb25dO1xuICAgICAgICByZXR1cm4gdHlwZW9mIGRpbSA9PT0gJ251bWJlcicgPyBkaW0gOiBwYXJzZUludCh0aGlzLmlneEZvckl0ZW1TaXplLCAxMCkgfHwgMDtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUeXBlTmFtZUZvckRlYnVnZ2luZyh0eXBlOiBhbnkpOiBzdHJpbmcge1xuICAgIGNvbnN0IG5hbWUgPSAnbmFtZSc7XG4gICAgcmV0dXJuIHR5cGVbbmFtZV0gfHwgdHlwZW9mIHR5cGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUZvck9mU3RhdGUgZXh0ZW5kcyBJQmFzZUV2ZW50QXJncyB7XG4gICAgc3RhcnRJbmRleD86IG51bWJlcjtcbiAgICBjaHVua1NpemU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUZvck9mRGF0YUNoYW5naW5nRXZlbnRBcmdzIGV4dGVuZHMgSUJhc2VFdmVudEFyZ3Mge1xuICAgIGNvbnRhaW5lclNpemU6IG51bWJlcjtcbn1cblxuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbaWd4R3JpZEZvcl1baWd4R3JpZEZvck9mXSdcbn0pXG5leHBvcnQgY2xhc3MgSWd4R3JpZEZvck9mRGlyZWN0aXZlPFQ+IGV4dGVuZHMgSWd4Rm9yT2ZEaXJlY3RpdmU8VD4gaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgRG9DaGVjayB7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgX3ZpZXdDb250YWluZXI6IFZpZXdDb250YWluZXJSZWYsXG4gICAgICAgIF90ZW1wbGF0ZTogVGVtcGxhdGVSZWY8TmdGb3JPZkNvbnRleHQ8VD4+LFxuICAgICAgICBfZGlmZmVyczogSXRlcmFibGVEaWZmZXJzLFxuICAgICAgICByZXNvbHZlcjogQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICAgICAgICBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBfem9uZTogTmdab25lLFxuICAgICAgICBwcm90ZWN0ZWQgc3luY1Njcm9sbFNlcnZpY2U6IElneEZvck9mU2Nyb2xsU3luY1NlcnZpY2UsXG4gICAgICAgIHByb3RlY3RlZCBzeW5jU2VydmljZTogSWd4Rm9yT2ZTeW5jU2VydmljZSkge1xuICAgICAgICBzdXBlcihfdmlld0NvbnRhaW5lciwgX3RlbXBsYXRlLCBfZGlmZmVycywgcmVzb2x2ZXIsIGNkciwgX3pvbmUsIHN5bmNTY3JvbGxTZXJ2aWNlKTtcbiAgICB9XG5cbiAgICBASW5wdXQoKVxuICAgIHNldCBpZ3hHcmlkRm9yT2YodmFsdWUpIHtcbiAgICAgICAgdGhpcy5pZ3hGb3JPZiA9IHZhbHVlO1xuICAgIH1cblxuICAgIGdldCBpZ3hHcmlkRm9yT2YoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlneEZvck9mO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW4gQGludGVybmFsXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIGRhdGEgaGFzIGJlZW4gY2hhbmdlZCBidXQgYmVmb3JlIHRoZSB2aWV3IGlzIHJlZnJlc2hlZFxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvbkRhdGFDaGFuZ2luZyA9IG5ldyBFdmVudEVtaXR0ZXI8SUZvck9mRGF0YUNoYW5naW5nRXZlbnRBcmdzPigpO1xuXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuc3luY1NlcnZpY2Uuc2V0TWFzdGVyKHRoaXMpO1xuICAgICAgICBzdXBlci5uZ09uSW5pdCgpO1xuICAgICAgICB0aGlzLnJlbW92ZVNjcm9sbEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgICAgICBjb25zdCBmb3JPZiA9ICdpZ3hHcmlkRm9yT2YnO1xuICAgICAgICB0aGlzLnN5bmNTZXJ2aWNlLnNldE1hc3Rlcih0aGlzKTtcbiAgICAgICAgaWYgKGZvck9mIGluIGNoYW5nZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gY2hhbmdlc1tmb3JPZl0uY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9kaWZmZXIgJiYgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kaWZmZXIgPSB0aGlzLl9kaWZmZXJzLmZpbmQodmFsdWUpLmNyZWF0ZSh0aGlzLmlneEZvclRyYWNrQnkpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYENhbm5vdCBmaW5kIGEgZGlmZmVyIHN1cHBvcnRpbmcgb2JqZWN0IFwiJHt2YWx1ZX1cIiBvZiB0eXBlIFwiJHtnZXRUeXBlTmFtZUZvckRlYnVnZ2luZyh2YWx1ZSl9XCIuXG4gICAgICAgICAgICAgICAgICAgICBOZ0ZvciBvbmx5IHN1cHBvcnRzIGJpbmRpbmcgdG8gSXRlcmFibGVzIHN1Y2ggYXMgQXJyYXlzLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZWZhdWx0SXRlbVNpemUgPSAnaWd4Rm9ySXRlbVNpemUnO1xuICAgICAgICBpZiAoZGVmYXVsdEl0ZW1TaXplIGluIGNoYW5nZXMgJiYgIWNoYW5nZXNbZGVmYXVsdEl0ZW1TaXplXS5maXJzdENoYW5nZSAmJlxuICAgICAgICAgICAgIHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICd2ZXJ0aWNhbCcgJiYgdGhpcy5pZ3hGb3JPZikge1xuICAgICAgICAgICAgLy8gaGFuZGxlIGRlZmF1bHQgaXRlbSBzaXplIGNoYW5nZWQuXG4gICAgICAgICAgICB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lclNpemUgPSAnaWd4Rm9yQ29udGFpbmVyU2l6ZSc7XG4gICAgICAgIGlmIChjb250YWluZXJTaXplIGluIGNoYW5nZXMgJiYgIWNoYW5nZXNbY29udGFpbmVyU2l6ZV0uZmlyc3RDaGFuZ2UgJiYgdGhpcy5pZ3hGb3JPZikge1xuICAgICAgICAgICAgdGhpcy5fcmVjYWxjT25Db250YWluZXJDaGFuZ2UoY2hhbmdlcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIGdldCBzaXplc0NhY2hlKCk6IG51bWJlcltdIHtcbiAgICAgICAgaWYgKHRoaXMuc3luY1NlcnZpY2UuaXNNYXN0ZXIodGhpcykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9zaXplc0NhY2hlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnN5bmNTZXJ2aWNlLnNpemVzQ2FjaGUodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IHNpemVzQ2FjaGUodmFsdWU6IG51bWJlcltdKSB7XG4gICAgICAgIHRoaXMuX3NpemVzQ2FjaGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGl0ZW1zRGltZW5zaW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnID8gdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0SXRlbVNpemUoaXRlbSkge1xuICAgICAgICBsZXQgc2l6ZSA9IDA7XG4gICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJyA/XG4gICAgICAgICAgICB0aGlzLmlneEZvclNpemVQcm9wTmFtZSA6ICdoZWlnaHQnO1xuICAgICAgICBpZiAoZGltZW5zaW9uID09PSAnaGVpZ2h0Jykge1xuICAgICAgICAgICAgc2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9ySXRlbVNpemUsIDEwKSB8fCAwO1xuICAgICAgICAgICAgaWYgKGl0ZW0gJiYgaXRlbS5zdW1tYXJpZXMpIHtcbiAgICAgICAgICAgICAgICBzaXplID0gaXRlbS5tYXg7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGl0ZW0gJiYgaXRlbS5ncm91cHMgJiYgaXRlbS5oZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBzaXplID0gaXRlbS5oZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzaXplID0gcGFyc2VJbnQoaXRlbVtkaW1lbnNpb25dLCAxMCkgfHwgMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2l6ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaW5pdFNpemVzQ2FjaGUoaXRlbXM6IGFueVtdKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKCF0aGlzLnN5bmNTZXJ2aWNlLmlzTWFzdGVyKHRoaXMpKSB7XG4gICAgICAgICAgICBjb25zdCBtYXN0ZXJTaXplc0NhY2hlID0gdGhpcy5zeW5jU2VydmljZS5zaXplc0NhY2hlKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIG1hc3RlclNpemVzQ2FjaGVbbWFzdGVyU2l6ZXNDYWNoZS5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgdG90YWxTaXplID0gMDtcbiAgICAgICAgbGV0IHNpemUgPSAwO1xuICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgIHRoaXMuc2l6ZXNDYWNoZSA9IFtdO1xuICAgICAgICB0aGlzLmhlaWdodENhY2hlID0gW107XG4gICAgICAgIHRoaXMuc2l6ZXNDYWNoZS5wdXNoKDApO1xuICAgICAgICBjb25zdCBjb3VudCA9IHRoaXMuaXNSZW1vdGUgPyB0aGlzLnRvdGFsSXRlbUNvdW50IDogaXRlbXMubGVuZ3RoO1xuICAgICAgICBmb3IgKGk7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBzaXplID0gdGhpcy5nZXRJdGVtU2l6ZShpdGVtc1tpXSk7XG4gICAgICAgICAgICBpZiAodGhpcy5pdGVtc0RpbWVuc2lvbiA9PT0gJ2hlaWdodCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhlaWdodENhY2hlLnB1c2goc2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b3RhbFNpemUgKz0gc2l6ZTtcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZS5wdXNoKHRvdGFsU2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRvdGFsU2l6ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVNpemVDYWNoZShjaGFuZ2VzOiBJdGVyYWJsZUNoYW5nZXM8VD4gPSBudWxsKSB7XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFNpemVzQ2FjaGUodGhpcy5pZ3hGb3JPZik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSB0aGlzLmhlaWdodENhY2hlLmxlbmd0aCA+IDAgPyB0aGlzLmhlaWdodENhY2hlLnJlZHVjZSgoYWNjLCB2YWwpID0+IGFjYyArIHZhbCkgOiAwO1xuICAgICAgICBsZXQgbmV3SGVpZ2h0ID0gb2xkSGVpZ2h0O1xuICAgICAgICBpZiAoY2hhbmdlcyAmJiAhdGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgbmV3SGVpZ2h0ID0gdGhpcy5oYW5kbGVDYWNoZUNoYW5nZXMoY2hhbmdlcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXdIZWlnaHQgPSB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGlmZiA9IG9sZEhlaWdodCAtIG5ld0hlaWdodDtcblxuICAgICAgICAvLyBpZiBkYXRhIGhhcyBiZWVuIGNoYW5nZWQgd2hpbGUgY29udGFpbmVyIGlzIHNjcm9sbGVkXG4gICAgICAgIC8vIHNob3VsZCB1cGRhdGUgc2Nyb2xsIHRvcC9sZWZ0IGFjY29yZGluZyB0byBjaGFuZ2Ugc28gdGhhdCBzYW1lIHN0YXJ0SW5kZXggaXMgaW4gdmlld1xuICAgICAgICBpZiAoTWF0aC5hYnMoZGlmZikgPiAwKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBUaGlzIGNvZGUgY2FuIGJlIHJlbW92ZWQuIEhvd2V2ZXIgdGVzdHMgbmVlZCB0byBiZSByZXdyaXR0ZW4gaW4gYSB3YXkgdGhhdCB0aGV5IHdhaXQgZm9yIFJlc2l6ZU9ic2VydmVkIHRvIGNvbXBsZXRlLlxuICAgICAgICAgICAgLy8gU28gbGVhdmluZyBhcyBpcyBmb3IgdGhlIG1vbWVudC5cbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWNhbGNVcGRhdGVTaXplcygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHBhcnNlSW50KHRoaXMuZGMuaW5zdGFuY2UuX3ZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRvcCwgMTApO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNjcm9sbFBvc2l0aW9uICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gPSB0aGlzLnNpemVzQ2FjaGVbdGhpcy5zdGF0ZS5zdGFydEluZGV4XSAtIG9mZnNldDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVTY3JvbGxPZmZzZXQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBoYW5kbGVDYWNoZUNoYW5nZXMoY2hhbmdlczogSXRlcmFibGVDaGFuZ2VzPFQ+KSB7XG4gICAgICAgIGNvbnN0IGlkZW50aXR5Q2hhbmdlcyA9IFtdO1xuICAgICAgICBjb25zdCBuZXdIZWlnaHRDYWNoZSA9IFtdO1xuICAgICAgICBjb25zdCBuZXdTaXplc0NhY2hlID0gW107XG4gICAgICAgIG5ld1NpemVzQ2FjaGUucHVzaCgwKTtcbiAgICAgICAgbGV0IG5ld0hlaWdodCA9IDA7XG5cbiAgICAgICAgLy8gV2hlbiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSByZW1vdmVkIGl0ZW1zIHRoZSBjaGFuZ2VzIGFyZSBub3QgcmVsaWFibGUgc28gdGhvc2Ugd2l0aCBpZGVudGl0eSBjaGFuZ2Ugc2hvdWxkIGJlIGRlZmF1bHQgc2l6ZS5cbiAgICAgICAgbGV0IG51bVJlbW92ZWRJdGVtcyA9IDA7XG4gICAgICAgIGNoYW5nZXMuZm9yRWFjaFJlbW92ZWRJdGVtKCgpID0+IG51bVJlbW92ZWRJdGVtcysrKTtcblxuICAgICAgICAvLyBHZXQgdGhlIGlkZW50aXR5IGNoYW5nZXMgdG8gZGV0ZXJtaW5lIGxhdGVyIGlmIHRob3NlIHRoYXQgaGF2ZSBjaGFuZ2VkIHRoZWlyIGluZGV4ZXMgc2hvdWxkIGJlIGFzc2lnbmVkIGRlZmF1bHQgaXRlbSBzaXplLlxuICAgICAgICBjaGFuZ2VzLmZvckVhY2hJZGVudGl0eUNoYW5nZSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGl0ZW0uY3VycmVudEluZGV4ICE9PSBpdGVtLnByZXZpb3VzSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBGaWx0ZXIgb3V0IG9uZXMgdGhhdCBoYXZlIG5vdCBjaGFuZ2VkIHRoZWlyIGluZGV4LlxuICAgICAgICAgICAgICAgIGlkZW50aXR5Q2hhbmdlc1tpdGVtLmN1cnJlbnRJbmRleF0gPSBpdGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBQcm9jZXNzaW5nIGVhY2ggaXRlbSB0aGF0IGlzIHBhc3NlZCB0byB0aGUgaWd4Rm9yT2Ygc28gZmFyIHNlZW0gdG8gYmUgbW9zdCByZWxpYWJsZS4gV2UgcGFyc2UgdGhlIHVwZGF0ZWQgbGlzdCBvZiBpdGVtcy5cbiAgICAgICAgY2hhbmdlcy5mb3JFYWNoSXRlbSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGl0ZW0ucHJldmlvdXNJbmRleCAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgIChudW1SZW1vdmVkSXRlbXMgPCAyIHx8ICFpZGVudGl0eUNoYW5nZXMubGVuZ3RoIHx8IGlkZW50aXR5Q2hhbmdlc1tpdGVtLmN1cnJlbnRJbmRleF0pKSB7XG4gICAgICAgICAgICAgICAgLy8gUmV1c2UgY2FjaGUgb24gdGhvc2Ugd2hvIGhhdmUgcHJldmlvdXNJbmRleC5cbiAgICAgICAgICAgICAgICAvLyBXaGVuIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIHJlbW92ZWQgaXRlbXMgY3VycmVudGx5IHRoZSBjaGFuZ2VzIGFyZSBub3QgcmVhZGFibGUgc28gb25lcyB3aXRoIGlkZW50aXR5IGNoYW5nZVxuICAgICAgICAgICAgICAgIC8vIHNob3VsZCBiZSByYWNhbGN1bGF0ZWQuXG4gICAgICAgICAgICAgICAgbmV3SGVpZ2h0Q2FjaGVbaXRlbS5jdXJyZW50SW5kZXhdID0gdGhpcy5oZWlnaHRDYWNoZVtpdGVtLnByZXZpb3VzSW5kZXhdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBBc3NpZ24gZGVmYXVsdCBpdGVtIHNpemUuXG4gICAgICAgICAgICAgICAgbmV3SGVpZ2h0Q2FjaGVbaXRlbS5jdXJyZW50SW5kZXhdID0gdGhpcy5nZXRJdGVtU2l6ZShpdGVtLml0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3U2l6ZXNDYWNoZVtpdGVtLmN1cnJlbnRJbmRleCArIDFdID0gbmV3U2l6ZXNDYWNoZVtpdGVtLmN1cnJlbnRJbmRleF0gKyBuZXdIZWlnaHRDYWNoZVtpdGVtLmN1cnJlbnRJbmRleF07XG4gICAgICAgICAgICBuZXdIZWlnaHQgKz0gbmV3SGVpZ2h0Q2FjaGVbaXRlbS5jdXJyZW50SW5kZXhdO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5oZWlnaHRDYWNoZSA9IG5ld0hlaWdodENhY2hlO1xuICAgICAgICB0aGlzLnNpemVzQ2FjaGUgPSBuZXdTaXplc0NhY2hlO1xuICAgICAgICByZXR1cm4gbmV3SGVpZ2h0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwdWJsaWMgYXNzdW1lTWFzdGVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9zaXplc0NhY2hlID0gdGhpcy5zeW5jU2VydmljZS5zaXplc0NhY2hlKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgICAgICB0aGlzLnN5bmNTZXJ2aWNlLnNldE1hc3Rlcih0aGlzLCB0cnVlKTtcbiAgICB9XG5cbiAgICBuZ0RvQ2hlY2soKSB7XG4gICAgICAgIGlmICh0aGlzLl9kaWZmZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZXMgPSB0aGlzLl9kaWZmZXIuZGlmZih0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYXJnczogSUZvck9mRGF0YUNoYW5naW5nRXZlbnRBcmdzID0ge1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXJTaXplOiB0aGlzLmlneEZvckNvbnRhaW5lclNpemVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMub25EYXRhQ2hhbmdpbmcuZW1pdChhcmdzKTtcbiAgICAgICAgICAgICAgICAvLyAgcmUtaW5pdCBjYWNoZS5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaWd4Rm9yT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JPZiA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvKiB3ZSBuZWVkIHRvIHJlc2V0IHRoZSBtYXN0ZXIgZGlyIGlmIGFsbCByb3dzIGFyZSByZW1vdmVkXG4gICAgICAgICAgICAgICAgKGUuZy4gYmVjYXVzZSBvZiBmaWx0ZXJpbmcpOyBpZiBhbGwgY29sdW1ucyBhcmUgaGlkZGVuLCByb3dzIGFyZVxuICAgICAgICAgICAgICAgIHN0aWxsIHJlbmRlcmVkIGVtcHR5LCBzbyB3ZSBzaG91bGQgbm90IHJlc2V0IG1hc3RlciAqL1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pZ3hGb3JPZi5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN5bmNTZXJ2aWNlLnJlc2V0TWFzdGVyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3luY1NlcnZpY2Uuc2V0TWFzdGVyKHRoaXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSA9IGFyZ3MuY29udGFpbmVyU2l6ZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVTaXplQ2FjaGUoY2hhbmdlcyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fYXBwbHlDaGFuZ2VzKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlU2Nyb2xsT2Zmc2V0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkRhdGFDaGFuZ2VkLmVtaXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uU2Nyb2xsKGV2ZW50KSB7XG4gICAgICAgIGlmICghcGFyc2VJbnQodGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQsIDEwKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICBjb25zdCBtYXhSZWFsU2Nyb2xsVG9wID0gZXZlbnQudGFyZ2V0LmNoaWxkcmVuWzBdLnNjcm9sbEhlaWdodCAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgIGNvbnN0IHJlYWxQZXJjZW50U2Nyb2xsZWQgPSBtYXhSZWFsU2Nyb2xsVG9wICE9PSAwID8gIGV2ZW50LnRhcmdldC5zY3JvbGxUb3AgLyBtYXhSZWFsU2Nyb2xsVG9wIDogMDtcbiAgICAgICAgaWYgKCF0aGlzLl9iU2Nyb2xsSW50ZXJuYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0SGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcbiAgICAgICAgICAgIHRoaXMuX3ZpcnRTY3JvbGxUb3AgPSByZWFsUGVyY2VudFNjcm9sbGVkICogbWF4VmlydFNjcm9sbFRvcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2JTY3JvbGxJbnRlcm5hbCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNjcm9sbE9mZnNldCA9IHRoaXMuZml4ZWRVcGRhdGVBbGxFbGVtZW50cyh0aGlzLl92aXJ0U2Nyb2xsVG9wKTtcblxuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAtKHNjcm9sbE9mZnNldCkgKyAncHgnO1xuXG4gICAgICAgIHRoaXMuX3pvbmUub25TdGFibGUucGlwZShmaXJzdCgpKS5zdWJzY3JpYmUoICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVjYWxjVXBkYXRlU2l6ZXMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cblxuICAgIG9uSFNjcm9sbChzY3JvbGxBbW91bnQpIHtcbiAgICAgICAgLyogaW4gY2VydGFpbiBzaXR1YXRpb25zIHRoaXMgbWF5IGJlIGNhbGxlZCB3aGVuIG5vIHNjcm9sbGJhciBpcyB2aXNpYmxlICovXG4gICAgICAgIGlmICghdGhpcy5zY3JvbGxDb21wb25lbnQgfHwgIXBhcnNlSW50KHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuY2hpbGRyZW5bMF0uc3R5bGUud2lkdGgsIDEwKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFVwZGF0aW5nIGhvcml6b250YWwgY2h1bmtzXG4gICAgICAgIGNvbnN0IHNjcm9sbE9mZnNldCA9IHRoaXMuZml4ZWRVcGRhdGVBbGxFbGVtZW50cyhzY3JvbGxBbW91bnQpO1xuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5sZWZ0ID0gLXNjcm9sbE9mZnNldCArICdweCc7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFkZExhc3RFbGVtKCkge1xuICAgICAgICBsZXQgZWxlbUluZGV4ID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgIGlmICghdGhpcy5pc1JlbW90ZSAmJiAhdGhpcy5pZ3hGb3JPZikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGVsZW1JbmRleCA+PSB0aGlzLmlneEZvck9mLmxlbmd0aCkge1xuICAgICAgICAgICAgZWxlbUluZGV4ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGggLSB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbZWxlbUluZGV4XTtcbiAgICAgICAgY29uc3QgZW1iZWRkZWRWaWV3ID0gdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmNyZWF0ZUVtYmVkZGVkVmlldyhcbiAgICAgICAgICAgIHRoaXMuX3RlbXBsYXRlLFxuICAgICAgICAgICAgbmV3IElneEZvck9mQ29udGV4dDxUPihpbnB1dCwgdGhpcy5nZXRDb250ZXh0SW5kZXgoaW5wdXQpLCB0aGlzLmlneEZvck9mLmxlbmd0aClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnB1c2goZW1iZWRkZWRWaWV3KTtcbiAgICAgICAgdGhpcy5zdGF0ZS5jaHVua1NpemUrKztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVZpZXdzKHByZXZDaHVua1NpemUpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yT2YgJiYgdGhpcy5pZ3hGb3JPZi5sZW5ndGggJiYgdGhpcy5kYykge1xuICAgICAgICAgICAgY29uc3QgZW1iZWRkZWRWaWV3Q29weSA9IE9iamVjdC5hc3NpZ24oW10sIHRoaXMuX2VtYmVkZGVkVmlld3MpO1xuICAgICAgICAgICAgbGV0IHN0YXJ0SW5kZXg7XG4gICAgICAgICAgICBsZXQgZW5kSW5kZXg7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGVuZEluZGV4ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSB0aGlzLmdldEluZGV4QXQoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZSxcbiAgICAgICAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXJ0SW5kZXggKyB0aGlzLnN0YXRlLmNodW5rU2l6ZSA+IHRoaXMuaWd4Rm9yT2YubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSB0aGlzLmlneEZvck9mLmxlbmd0aCAtIHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggPSBzdGFydEluZGV4O1xuICAgICAgICAgICAgICAgIGVuZEluZGV4ID0gdGhpcy5zdGF0ZS5jaHVua1NpemUgKyB0aGlzLnN0YXRlLnN0YXJ0SW5kZXg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgZW5kSW5kZXggJiYgdGhpcy5pZ3hGb3JPZltpXSAhPT0gdW5kZWZpbmVkOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgZW1iVmlldyA9IGVtYmVkZGVkVmlld0NvcHkuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjbnR4ID0gKGVtYlZpZXcgYXMgRW1iZWRkZWRWaWV3UmVmPGFueT4pLmNvbnRleHQ7XG4gICAgICAgICAgICAgICAgY250eC4kaW1wbGljaXQgPSBpbnB1dDtcbiAgICAgICAgICAgICAgICBjbnR4LmluZGV4ID0gdGhpcy5nZXRDb250ZXh0SW5kZXgoaW5wdXQpO1xuICAgICAgICAgICAgICAgIGNudHguY291bnQgPSB0aGlzLmlneEZvck9mLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwcmV2Q2h1bmtTaXplICE9PSB0aGlzLnN0YXRlLmNodW5rU2l6ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMub25DaHVua0xvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBwcm90ZWN0ZWQgX2FwcGx5Q2hhbmdlcygpIHtcbiAgICAgICAgY29uc3QgcHJldkNodW5rU2l6ZSA9IHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICB0aGlzLmFwcGx5Q2h1bmtTaXplQ2hhbmdlKCk7XG4gICAgICAgIHRoaXMuX3JlY2FsY1Njcm9sbEJhclNpemUoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlVmlld3MocHJldkNodW5rU2l6ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBfY2FsY01heENodW5rU2l6ZSgpOiBudW1iZXIge1xuICAgICAgICBpZiAodGhpcy5zeW5jU2VydmljZS5pc01hc3Rlcih0aGlzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHN1cGVyLl9jYWxjTWF4Q2h1bmtTaXplKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY1NlcnZpY2UuY2h1bmtTaXplKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbkBOZ01vZHVsZSh7XG4gICAgZGVjbGFyYXRpb25zOiBbSWd4Rm9yT2ZEaXJlY3RpdmUsIElneEdyaWRGb3JPZkRpcmVjdGl2ZSwgRGlzcGxheUNvbnRhaW5lckNvbXBvbmVudCwgVmlydHVhbEhlbHBlckNvbXBvbmVudCxcbiAgICAgICAgIEhWaXJ0dWFsSGVscGVyQ29tcG9uZW50LCBWaXJ0dWFsSGVscGVyQmFzZURpcmVjdGl2ZV0sXG4gICAgZW50cnlDb21wb25lbnRzOiBbRGlzcGxheUNvbnRhaW5lckNvbXBvbmVudCwgVmlydHVhbEhlbHBlckNvbXBvbmVudCwgSFZpcnR1YWxIZWxwZXJDb21wb25lbnRdLFxuICAgIGV4cG9ydHM6IFtJZ3hGb3JPZkRpcmVjdGl2ZSwgSWd4R3JpZEZvck9mRGlyZWN0aXZlXSxcbiAgICBpbXBvcnRzOiBbSWd4U2Nyb2xsSW5lcnRpYU1vZHVsZSwgQ29tbW9uTW9kdWxlXVxufSlcblxuZXhwb3J0IGNsYXNzIElneEZvck9mTW9kdWxlIHtcbn1cbiJdfQ==