ionic4-tooltips
Version:
Tooltips module for Ionic 2+ and Angular 8+ apps
280 lines • 32.1 kB
JavaScript
import { ApplicationRef, ComponentFactoryResolver, Directive, ElementRef, HostListener, Input, ViewContainerRef, } from '@angular/core';
import { Platform } from '@ionic/angular';
import { TooltipBoxComponent } from '../components/tooltip-box/tooltip-box.component';
import { TooltipController } from '../controllers/tooltip.cotroller';
import { TooltipEvent } from '../models/tooltip-event.model';
export class TooltipDirective {
constructor(el, appRef, platform, cfr, tooltipCtrl, vcr) {
this.el = el;
this.appRef = appRef;
this.platform = platform;
this.cfr = cfr;
this.tooltipCtrl = tooltipCtrl;
this.vcr = vcr;
this._active = false;
this._arrow = false;
this._canShow = true;
this._debouncedPromise = null;
this._navTooltip = false;
this.debounce = 0;
this.desktopEvent = TooltipEvent.HOVER;
this.duration = 3000;
this.tooltipStyles = {};
}
set navTooltip(val) {
this._navTooltip = typeof val !== 'boolean' || val !== false;
}
get navTooltip() {
return this._navTooltip;
}
set arrow(val) {
this._arrow = typeof val !== 'boolean' || val !== false;
}
get arrow() {
return this._arrow;
}
set active(val) {
this._active = typeof val !== 'boolean' || val !== false;
this._active && this.canShow ?
this.showTooltip() : this.removeTooltip();
}
get active() {
return this._active;
}
ngOnInit() {
if (typeof this.event === 'undefined') {
this.event = this.platform.is('mobile') ?
this.mobileEvent : this.desktopEvent;
}
// if the timer hasn't expired or active is true when the component gets destroyed, the tooltip will remain in the DOM
// this removes it
this.removeTooltip();
}
/**
* Show the tooltip immediately after initiating view if set to
*/
ngAfterViewInit() {
if (this._active) {
this.trigger();
}
}
ngOnDestroy() {
if (this._tooltipElement && typeof this._tooltipElement.destroy === 'function') {
this._tooltipElement.destroy();
}
}
/**
* Set the canShow property
* Ensure that tooltip is shown only if the tooltip string is not falsey
*/
set canShow(show) {
this._canShow = show;
}
/**
* @return TRUE if the tooltip can be shown
*/
get canShow() {
return this._canShow &&
((typeof this.tooltip === 'string' && this.tooltip !== '')
|| (typeof this.tooltipHtml === 'string' && this.tooltipHtml !== ''));
}
/**
* Handles the click/press event and shows a tooltip.
* If a tooltip already exists, it will just reset it's timer.
*/
trigger() {
if (this.canShow) {
if (this._tooltipElement) {
this._resetTimer();
}
else {
this.showTooltip();
}
}
}
/**
* Creates a new tooltip component and adjusts it's properties to show properly.
*/
showTooltip() {
this._debouncedPromise = setTimeout(() => {
this._debouncedPromise = null;
this._createTooltipComponent();
const tooltipComponent = this._tooltipElement.instance;
tooltipComponent.role = this.role;
tooltipComponent.text = this.tooltip;
tooltipComponent.tooltipStyles = this.tooltipStyles;
tooltipComponent.tooltipHtml = this.tooltipHtml;
tooltipComponent.init.then(() => {
const tooltipPosition = this._getTooltipPosition();
tooltipComponent.posLeft = tooltipPosition.left;
tooltipComponent.posTop = tooltipPosition.top;
tooltipComponent.fadeState = 'visible';
if (this.arrow) {
let arrowPosition;
if (this.positionV === 'top') {
arrowPosition = 'bottom';
}
else if (this.positionV === 'bottom') {
arrowPosition = 'top';
}
else if (this.positionH === 'left') {
arrowPosition = 'right';
}
else {
arrowPosition = 'left';
}
tooltipComponent.arrow = arrowPosition;
}
if (!this._active) {
this._tooltipTimeout = setTimeout(this.removeTooltip.bind(this), this.duration);
}
});
}, this.debounce);
}
onClick() {
if (this.event === TooltipEvent.CLICK) {
this.trigger();
}
}
onPress() {
if (this.event === TooltipEvent.PRESS) {
this.trigger();
}
}
onMouseEnter() {
if (this.event === TooltipEvent.HOVER) {
this.active = true;
}
}
onMouseLeave() {
if (this.event === TooltipEvent.HOVER) {
this.active = false;
}
}
_createTooltipComponent() {
const componentFactory = this.cfr.resolveComponentFactory(TooltipBoxComponent);
this._tooltipElement = this.vcr.createComponent(componentFactory);
this.tooltipCtrl.addTooltip(this);
}
_getTooltipPosition() {
const tooltipNativeElement = this._tooltipElement.instance.getNativeElement(), el = this.el.nativeElement, rect = el.getBoundingClientRect();
let positionLeft, positionTop, spacing = 10;
if (this.navTooltip) {
this.positionV = 'bottom';
this.arrow = false;
spacing = 20;
}
if (this.positionH === 'right') {
positionLeft = rect.right + spacing;
}
else if (this.positionH === 'left') {
positionLeft = rect.left - spacing - tooltipNativeElement.offsetWidth;
// -79, 19
}
else if (this.navTooltip) {
positionLeft = rect.left + el.offsetWidth / 2;
}
else {
positionLeft = rect.left;
}
if (this.positionV === 'top') {
positionTop = rect.top - spacing - tooltipNativeElement.offsetHeight;
}
else if (this.positionV === 'bottom') {
positionTop = rect.bottom + spacing;
}
else {
positionTop = rect.top + el.offsetHeight / 2 - tooltipNativeElement.offsetHeight / 2;
}
this.topOffset++;
if (this.topOffset) {
positionTop += +this.topOffset;
}
this.leftOffset++;
if (this.leftOffset) {
positionLeft += +this.leftOffset;
}
if (positionLeft + tooltipNativeElement.offsetWidth + spacing > this.platform.width()) {
positionLeft = this.platform.width() - tooltipNativeElement.offsetWidth - spacing;
}
else if (positionLeft + tooltipNativeElement.offsetWidth - spacing < 0) {
positionLeft = spacing;
}
if (positionTop + tooltipNativeElement.offsetHeight + spacing > this.platform.height()) {
positionTop = this.platform.height() - tooltipNativeElement.offsetHeight - spacing;
}
else if (positionTop + tooltipNativeElement.offsetHeight - spacing < 0) {
positionTop = spacing;
}
return {
left: positionLeft,
top: positionTop,
};
}
removeTooltip() {
if (this._debouncedPromise) {
clearTimeout(this._debouncedPromise);
this._debouncedPromise = null;
}
if (!this._tooltipElement) {
this._tooltipElement = undefined;
this._tooltipTimeout = undefined;
return;
}
this._tooltipElement.instance.fadeState = 'invisible';
this.canShow = false;
// wait for animation to finish then clear everything out
setTimeout(() => {
if (this._tooltipElement &&
typeof this._tooltipElement.destroy === 'function') {
this._tooltipElement.destroy();
}
this.tooltipCtrl.removeTooltip(this);
this._tooltipElement = this._tooltipTimeout = undefined;
this.canShow = true;
}, 300);
}
_resetTimer() {
clearTimeout(this._tooltipTimeout);
this._tooltipTimeout = setTimeout(() => {
this.active = false;
}, this.duration);
}
}
TooltipDirective.decorators = [
{ type: Directive, args: [{
selector: '[tooltip]',
},] }
];
TooltipDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: ApplicationRef },
{ type: Platform },
{ type: ComponentFactoryResolver },
{ type: TooltipController },
{ type: ViewContainerRef }
];
TooltipDirective.propDecorators = {
debounce: [{ type: Input }],
desktopEvent: [{ type: Input }],
duration: [{ type: Input }],
event: [{ type: Input }],
hideOthers: [{ type: Input }],
leftOffset: [{ type: Input }],
mobileEvent: [{ type: Input }],
positionV: [{ type: Input }],
positionH: [{ type: Input }],
role: [{ type: Input }],
tooltip: [{ type: Input }],
tooltipHtml: [{ type: Input }],
tooltipStyles: [{ type: Input }],
topOffset: [{ type: Input }],
navTooltip: [{ type: Input }],
arrow: [{ type: Input }],
active: [{ type: Input }],
onClick: [{ type: HostListener, args: ['click',] }],
onPress: [{ type: HostListener, args: ['press',] }],
onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }]
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiLi4vLi4vLi4vc3JjLyIsInNvdXJjZXMiOlsiZGlyZWN0aXZlcy90b29sdGlwLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsY0FBYyxFQUNkLHdCQUF3QixFQUV4QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBR0wsZ0JBQWdCLEdBQ2pCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QyxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSxpREFBaUQsQ0FBQztBQUNwRixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxrQ0FBa0MsQ0FBQztBQUNuRSxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sK0JBQStCLENBQUM7QUFLM0QsTUFBTSxPQUFPLGdCQUFnQjtJQXNEM0IsWUFDVSxFQUFhLEVBQ2IsTUFBcUIsRUFDckIsUUFBaUIsRUFDakIsR0FBNEIsRUFDNUIsV0FBNkIsRUFDN0IsR0FBb0I7UUFMcEIsT0FBRSxHQUFGLEVBQUUsQ0FBVztRQUNiLFdBQU0sR0FBTixNQUFNLENBQWU7UUFDckIsYUFBUSxHQUFSLFFBQVEsQ0FBUztRQUNqQixRQUFHLEdBQUgsR0FBRyxDQUF5QjtRQUM1QixnQkFBVyxHQUFYLFdBQVcsQ0FBa0I7UUFDN0IsUUFBRyxHQUFILEdBQUcsQ0FBaUI7UUEzRHRCLFlBQU8sR0FBVyxLQUFLLENBQUM7UUFDeEIsV0FBTSxHQUFXLEtBQUssQ0FBQztRQUN2QixhQUFRLEdBQVcsSUFBSSxDQUFDO1FBQ3hCLHNCQUFpQixHQUFHLElBQUksQ0FBQztRQUN6QixnQkFBVyxHQUFXLEtBQUssQ0FBQztRQUkzQixhQUFRLEdBQVUsQ0FBQyxDQUFDO1FBQ3BCLGlCQUFZLEdBQWdCLFlBQVksQ0FBQyxLQUFLLENBQUM7UUFDL0MsYUFBUSxHQUFHLElBQUksQ0FBQztRQVVoQixrQkFBYSxHQUE0QixFQUFFLENBQUM7SUEwQ3JELENBQUM7SUF2Q0QsSUFDSSxVQUFVLENBQUMsR0FBVztRQUN4QixJQUFJLENBQUMsV0FBVyxHQUFHLE9BQU8sR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLEtBQUssS0FBSyxDQUFDO0lBQy9ELENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDWixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQztJQUVELElBQ0ksS0FBSyxDQUFDLEdBQVc7UUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLEtBQUssQ0FBQztJQUMxRCxDQUFDO0lBRUQsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUNJLE1BQU0sQ0FBQyxHQUFXO1FBQ3BCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxHQUFHLEtBQUssU0FBUyxJQUFJLEdBQUcsS0FBSyxLQUFLLENBQUM7UUFFekQsSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDOUMsQ0FBQztJQUVELElBQUksTUFBTTtRQUNSLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0lBYUQsUUFBUTtRQUNOLElBQUksT0FBTyxJQUFJLENBQUMsS0FBSyxLQUFLLFdBQVcsRUFBRTtZQUNyQyxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7U0FDeEM7UUFFRCxzSEFBc0g7UUFDdEgsa0JBQWtCO1FBQ2xCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxlQUFlO1FBQ2IsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2hCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNoQjtJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxJQUFJLENBQUMsZUFBZSxJQUFJLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEtBQUssVUFBVSxFQUFFO1lBQzlFLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDaEM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBSSxPQUFPLENBQUMsSUFBYTtRQUN2QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxRQUFRO1lBQ2xCLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxPQUFPLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssRUFBRSxDQUFDO21CQUNyRCxDQUFDLE9BQU8sSUFBSSxDQUFDLFdBQVcsS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRDs7O09BR0c7SUFDSCxPQUFPO1FBQ0wsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2hCLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRTtnQkFDeEIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2FBQ3BCO2lCQUFNO2dCQUNMLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQzthQUNwQjtTQUNGO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNULElBQUksQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQ2pDLEdBQUcsRUFBRTtZQUNILElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7WUFFOUIsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFFL0IsTUFBTSxnQkFBZ0IsR0FBd0IsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUM7WUFFNUUsZ0JBQWdCLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDbEMsZ0JBQWdCLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDckMsZ0JBQWdCLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7WUFDcEQsZ0JBQWdCLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7WUFDaEQsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQzlCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO2dCQUVuRCxnQkFBZ0IsQ0FBQyxPQUFPLEdBQUcsZUFBZSxDQUFDLElBQUksQ0FBQztnQkFDaEQsZ0JBQWdCLENBQUMsTUFBTSxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUM7Z0JBRTlDLGdCQUFnQixDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7Z0JBRXZDLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtvQkFDZCxJQUFJLGFBQWEsQ0FBQztvQkFDbEIsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLEtBQUssRUFBRTt3QkFDNUIsYUFBYSxHQUFHLFFBQVEsQ0FBQztxQkFDMUI7eUJBQU0sSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFFBQVEsRUFBRTt3QkFDdEMsYUFBYSxHQUFHLEtBQUssQ0FBQztxQkFDdkI7eUJBQU0sSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLE1BQU0sRUFBRTt3QkFDcEMsYUFBYSxHQUFHLE9BQU8sQ0FBQztxQkFDekI7eUJBQU07d0JBQ0wsYUFBYSxHQUFHLE1BQU0sQ0FBQztxQkFDeEI7b0JBQ0QsZ0JBQWdCLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQztpQkFDeEM7Z0JBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7b0JBQ2pCLElBQUksQ0FBQyxlQUFlLEdBQUcsVUFBVSxDQUMvQixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFDN0IsSUFBSSxDQUFDLFFBQVEsQ0FDZCxDQUFDO2lCQUNIO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLEVBQ0QsSUFBSSxDQUFDLFFBQVEsQ0FDZCxDQUFDO0lBQ0osQ0FBQztJQUdELE9BQU87UUFDTCxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDLEtBQUssRUFBRTtZQUNyQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDaEI7SUFDSCxDQUFDO0lBR0QsT0FBTztRQUNMLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUMsS0FBSyxFQUFFO1lBQ3JDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNoQjtJQUNILENBQUM7SUFHRCxZQUFZO1FBQ1YsSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLFlBQVksQ0FBQyxLQUFLLEVBQUU7WUFDckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7U0FDcEI7SUFDSCxDQUFDO0lBR0QsWUFBWTtRQUNWLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxZQUFZLENBQUMsS0FBSyxFQUFFO1lBQ3JDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1NBQ3JCO0lBQ0gsQ0FBQztJQUVPLHVCQUF1QjtRQUM3QixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUMvRSxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUVPLG1CQUFtQjtRQUN6QixNQUFNLG9CQUFvQixHQUFlLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLGdCQUFnQixFQUFFLEVBQ3ZGLEVBQUUsR0FBZSxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFDdEMsSUFBSSxHQUFjLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBRS9DLElBQUksWUFBbUIsRUFDckIsV0FBa0IsRUFDbEIsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUVmLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQztZQUMxQixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztZQUNuQixPQUFPLEdBQUcsRUFBRSxDQUFDO1NBQ2Q7UUFFRCxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssT0FBTyxFQUFFO1lBQzlCLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQztTQUNyQzthQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxNQUFNLEVBQUU7WUFDcEMsWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxHQUFHLG9CQUFvQixDQUFDLFdBQVcsQ0FBQztZQUN0RSxVQUFVO1NBQ1g7YUFBTSxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDMUIsWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7U0FDL0M7YUFBTTtZQUNMLFlBQVksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1NBQzFCO1FBR0QsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLEtBQUssRUFBRTtZQUM1QixXQUFXLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxPQUFPLEdBQUcsb0JBQW9CLENBQUMsWUFBWSxDQUFDO1NBQ3RFO2FBQU0sSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFFBQVEsRUFBRTtZQUN0QyxXQUFXLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUM7U0FDckM7YUFBTTtZQUNMLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxZQUFZLEdBQUcsQ0FBQyxHQUFHLG9CQUFvQixDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7U0FDdEY7UUFFRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDakIsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2xCLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7U0FDaEM7UUFFRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ25CLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7U0FDbEM7UUFFRCxJQUFJLFlBQVksR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLEdBQUcsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDckYsWUFBWSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEdBQUcsb0JBQW9CLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQztTQUNuRjthQUFNLElBQUksWUFBWSxHQUFHLG9CQUFvQixDQUFDLFdBQVcsR0FBRyxPQUFPLEdBQUcsQ0FBQyxFQUFFO1lBQ3hFLFlBQVksR0FBRyxPQUFPLENBQUM7U0FDeEI7UUFFRCxJQUFJLFdBQVcsR0FBRyxvQkFBb0IsQ0FBQyxZQUFZLEdBQUcsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDdEYsV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLEdBQUcsb0JBQW9CLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQztTQUNwRjthQUFNLElBQUksV0FBVyxHQUFHLG9CQUFvQixDQUFDLFlBQVksR0FBRyxPQUFPLEdBQUcsQ0FBQyxFQUFFO1lBQ3hFLFdBQVcsR0FBRyxPQUFPLENBQUM7U0FDdkI7UUFFRCxPQUFPO1lBQ0wsSUFBSSxFQUFFLFlBQVk7WUFDbEIsR0FBRyxFQUFHLFdBQVc7U0FDbEIsQ0FBQztJQUNKLENBQUM7SUFFRCxhQUFhO1FBQ1gsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUU7WUFDMUIsWUFBWSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBRXJDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7U0FDL0I7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUN6QixJQUFJLENBQUMsZUFBZSxHQUFHLFNBQVMsQ0FBQztZQUNqQyxJQUFJLENBQUMsZUFBZSxHQUFHLFNBQVMsQ0FBQztZQUNqQyxPQUFPO1NBQ1I7UUFFRCxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDO1FBRXRELElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBRXJCLHlEQUF5RDtRQUN6RCxVQUFVLENBQ1IsR0FBRyxFQUFFO1lBQ0gsSUFDRSxJQUFJLENBQUMsZUFBZTtnQkFDcEIsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sS0FBSyxVQUFVLEVBQ2xEO2dCQUNBLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDaEM7WUFDRCxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNyQyxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLEdBQUcsU0FBUyxDQUFDO1lBQ3hELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLENBQUMsRUFDRCxHQUFHLENBQ0osQ0FBQztJQUNKLENBQUM7SUFFTyxXQUFXO1FBQ2pCLFlBQVksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ3JDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3RCLENBQUMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDcEIsQ0FBQzs7O1lBdlRGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsV0FBVzthQUN0Qjs7O1lBaEJDLFVBQVU7WUFKVixjQUFjO1lBWVIsUUFBUTtZQVhkLHdCQUF3QjtZQWNsQixpQkFBaUI7WUFOdkIsZ0JBQWdCOzs7dUJBcUJmLEtBQUs7MkJBQ0wsS0FBSzt1QkFDTCxLQUFLO29CQUNMLEtBQUs7eUJBQ0wsS0FBSzt5QkFDTCxLQUFLOzBCQUNMLEtBQUs7d0JBQ0wsS0FBSzt3QkFDTCxLQUFLO21CQUNMLEtBQUs7c0JBQ0wsS0FBSzswQkFDTCxLQUFLOzRCQUNMLEtBQUs7d0JBQ0wsS0FBSzt5QkFFTCxLQUFLO29CQVNMLEtBQUs7cUJBU0wsS0FBSztzQkFrSUwsWUFBWSxTQUFDLE9BQU87c0JBT3BCLFlBQVksU0FBQyxPQUFPOzJCQU9wQixZQUFZLFNBQUMsWUFBWTsyQkFPekIsWUFBWSxTQUFDLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBBcHBsaWNhdGlvblJlZixcbiAgQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICBDb21wb25lbnRSZWYsXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIFZpZXdDb250YWluZXJSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge1BsYXRmb3JtfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5cbmltcG9ydCB7VG9vbHRpcEJveENvbXBvbmVudH0gZnJvbSAnLi4vY29tcG9uZW50cy90b29sdGlwLWJveC90b29sdGlwLWJveC5jb21wb25lbnQnO1xuaW1wb3J0IHtUb29sdGlwQ29udHJvbGxlcn0gZnJvbSAnLi4vY29udHJvbGxlcnMvdG9vbHRpcC5jb3Ryb2xsZXInO1xuaW1wb3J0IHtUb29sdGlwRXZlbnR9IGZyb20gJy4uL21vZGVscy90b29sdGlwLWV2ZW50Lm1vZGVsJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW3Rvb2x0aXBdJyxcbn0pXG5leHBvcnQgY2xhc3MgVG9vbHRpcERpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSBfYWN0aXZlOmJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBfYXJyb3c6Ym9vbGVhbiA9IGZhbHNlO1xuICBwcml2YXRlIF9jYW5TaG93OmJvb2xlYW4gPSB0cnVlO1xuICBwcml2YXRlIF9kZWJvdW5jZWRQcm9taXNlID0gbnVsbDtcbiAgcHJpdmF0ZSBfbmF2VG9vbHRpcDpib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgX3Rvb2x0aXBFbGVtZW50OkNvbXBvbmVudFJlZjxUb29sdGlwQm94Q29tcG9uZW50PjtcbiAgcHJpdmF0ZSBfdG9vbHRpcFRpbWVvdXQ6YW55O1xuXG4gIEBJbnB1dCgpIGRlYm91bmNlOm51bWJlciA9IDA7XG4gIEBJbnB1dCgpIGRlc2t0b3BFdmVudDpUb29sdGlwRXZlbnQgPSBUb29sdGlwRXZlbnQuSE9WRVI7XG4gIEBJbnB1dCgpIGR1cmF0aW9uID0gMzAwMDtcbiAgQElucHV0KCkgZXZlbnQ6VG9vbHRpcEV2ZW50O1xuICBASW5wdXQoKSBoaWRlT3RoZXJzOmJvb2xlYW47XG4gIEBJbnB1dCgpIGxlZnRPZmZzZXQ6bnVtYmVyO1xuICBASW5wdXQoKSBtb2JpbGVFdmVudDpUb29sdGlwRXZlbnQ7XG4gIEBJbnB1dCgpIHBvc2l0aW9uVjpzdHJpbmc7XG4gIEBJbnB1dCgpIHBvc2l0aW9uSDpzdHJpbmc7XG4gIEBJbnB1dCgpIHJvbGU6c3RyaW5nO1xuICBASW5wdXQoKSB0b29sdGlwOnN0cmluZztcbiAgQElucHV0KCkgdG9vbHRpcEh0bWw6c3RyaW5nO1xuICBASW5wdXQoKSB0b29sdGlwU3R5bGVzOnsgW2tleTpzdHJpbmddOnN0cmluZzsgfSA9IHt9O1xuICBASW5wdXQoKSB0b3BPZmZzZXQ6bnVtYmVyO1xuXG4gIEBJbnB1dCgpXG4gIHNldCBuYXZUb29sdGlwKHZhbDpib29sZWFuKSB7XG4gICAgdGhpcy5fbmF2VG9vbHRpcCA9IHR5cGVvZiB2YWwgIT09ICdib29sZWFuJyB8fCB2YWwgIT09IGZhbHNlO1xuICB9XG5cbiAgZ2V0IG5hdlRvb2x0aXAoKTpib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fbmF2VG9vbHRpcDtcbiAgfVxuXG4gIEBJbnB1dCgpXG4gIHNldCBhcnJvdyh2YWw6Ym9vbGVhbikge1xuICAgIHRoaXMuX2Fycm93ID0gdHlwZW9mIHZhbCAhPT0gJ2Jvb2xlYW4nIHx8IHZhbCAhPT0gZmFsc2U7XG4gIH1cblxuICBnZXQgYXJyb3coKTpib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fYXJyb3c7XG4gIH1cblxuICBASW5wdXQoKVxuICBzZXQgYWN0aXZlKHZhbDpib29sZWFuKSB7XG4gICAgdGhpcy5fYWN0aXZlID0gdHlwZW9mIHZhbCAhPT0gJ2Jvb2xlYW4nIHx8IHZhbCAhPT0gZmFsc2U7XG5cbiAgICB0aGlzLl9hY3RpdmUgJiYgdGhpcy5jYW5TaG93ID9cbiAgICAgIHRoaXMuc2hvd1Rvb2x0aXAoKSA6IHRoaXMucmVtb3ZlVG9vbHRpcCgpO1xuICB9XG5cbiAgZ2V0IGFjdGl2ZSgpOmJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9hY3RpdmU7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsOkVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBhcHBSZWY6QXBwbGljYXRpb25SZWYsXG4gICAgcHJpdmF0ZSBwbGF0Zm9ybTpQbGF0Zm9ybSxcbiAgICBwcml2YXRlIGNmcjpDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSB0b29sdGlwQ3RybDpUb29sdGlwQ29udHJvbGxlcixcbiAgICBwcml2YXRlIHZjcjpWaWV3Q29udGFpbmVyUmVmLFxuICApIHtcblxuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzLmV2ZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5ldmVudCA9IHRoaXMucGxhdGZvcm0uaXMoJ21vYmlsZScpID9cbiAgICAgICAgdGhpcy5tb2JpbGVFdmVudCA6IHRoaXMuZGVza3RvcEV2ZW50O1xuICAgIH1cblxuICAgIC8vIGlmIHRoZSB0aW1lciBoYXNuJ3QgZXhwaXJlZCBvciBhY3RpdmUgaXMgdHJ1ZSB3aGVuIHRoZSBjb21wb25lbnQgZ2V0cyBkZXN0cm95ZWQsIHRoZSB0b29sdGlwIHdpbGwgcmVtYWluIGluIHRoZSBET01cbiAgICAvLyB0aGlzIHJlbW92ZXMgaXRcbiAgICB0aGlzLnJlbW92ZVRvb2x0aXAoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaG93IHRoZSB0b29sdGlwIGltbWVkaWF0ZWx5IGFmdGVyIGluaXRpYXRpbmcgdmlldyBpZiBzZXQgdG9cbiAgICovXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICBpZiAodGhpcy5fYWN0aXZlKSB7XG4gICAgICB0aGlzLnRyaWdnZXIoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5fdG9vbHRpcEVsZW1lbnQgJiYgdHlwZW9mIHRoaXMuX3Rvb2x0aXBFbGVtZW50LmRlc3Ryb3kgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRoaXMuX3Rvb2x0aXBFbGVtZW50LmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBjYW5TaG93IHByb3BlcnR5XG4gICAqIEVuc3VyZSB0aGF0IHRvb2x0aXAgaXMgc2hvd24gb25seSBpZiB0aGUgdG9vbHRpcCBzdHJpbmcgaXMgbm90IGZhbHNleVxuICAgKi9cbiAgc2V0IGNhblNob3coc2hvdzogYm9vbGVhbikge1xuICAgIHRoaXMuX2NhblNob3cgPSBzaG93O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4gVFJVRSBpZiB0aGUgdG9vbHRpcCBjYW4gYmUgc2hvd25cbiAgICovXG4gIGdldCBjYW5TaG93KCk6Ym9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2NhblNob3cgJiZcbiAgICAgICgodHlwZW9mIHRoaXMudG9vbHRpcCA9PT0gJ3N0cmluZycgJiYgdGhpcy50b29sdGlwICE9PSAnJylcbiAgICAgICAgfHwgKHR5cGVvZiB0aGlzLnRvb2x0aXBIdG1sID09PSAnc3RyaW5nJyAmJiB0aGlzLnRvb2x0aXBIdG1sICE9PSAnJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdGhlIGNsaWNrL3ByZXNzIGV2ZW50IGFuZCBzaG93cyBhIHRvb2x0aXAuXG4gICAqIElmIGEgdG9vbHRpcCBhbHJlYWR5IGV4aXN0cywgaXQgd2lsbCBqdXN0IHJlc2V0IGl0J3MgdGltZXIuXG4gICAqL1xuICB0cmlnZ2VyKCk6dm9pZCB7XG4gICAgaWYgKHRoaXMuY2FuU2hvdykge1xuICAgICAgaWYgKHRoaXMuX3Rvb2x0aXBFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuX3Jlc2V0VGltZXIoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2hvd1Rvb2x0aXAoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyB0b29sdGlwIGNvbXBvbmVudCBhbmQgYWRqdXN0cyBpdCdzIHByb3BlcnRpZXMgdG8gc2hvdyBwcm9wZXJseS5cbiAgICovXG4gIHNob3dUb29sdGlwKCk6dm9pZCB7XG4gICAgdGhpcy5fZGVib3VuY2VkUHJvbWlzZSA9IHNldFRpbWVvdXQoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHRoaXMuX2RlYm91bmNlZFByb21pc2UgPSBudWxsO1xuXG4gICAgICAgIHRoaXMuX2NyZWF0ZVRvb2x0aXBDb21wb25lbnQoKTtcblxuICAgICAgICBjb25zdCB0b29sdGlwQ29tcG9uZW50OiBUb29sdGlwQm94Q29tcG9uZW50ID0gdGhpcy5fdG9vbHRpcEVsZW1lbnQuaW5zdGFuY2U7XG5cbiAgICAgICAgdG9vbHRpcENvbXBvbmVudC5yb2xlID0gdGhpcy5yb2xlO1xuICAgICAgICB0b29sdGlwQ29tcG9uZW50LnRleHQgPSB0aGlzLnRvb2x0aXA7XG4gICAgICAgIHRvb2x0aXBDb21wb25lbnQudG9vbHRpcFN0eWxlcyA9IHRoaXMudG9vbHRpcFN0eWxlcztcbiAgICAgICAgdG9vbHRpcENvbXBvbmVudC50b29sdGlwSHRtbCA9IHRoaXMudG9vbHRpcEh0bWw7XG4gICAgICAgIHRvb2x0aXBDb21wb25lbnQuaW5pdC50aGVuKCgpID0+IHtcbiAgICAgICAgICBjb25zdCB0b29sdGlwUG9zaXRpb24gPSB0aGlzLl9nZXRUb29sdGlwUG9zaXRpb24oKTtcblxuICAgICAgICAgIHRvb2x0aXBDb21wb25lbnQucG9zTGVmdCA9IHRvb2x0aXBQb3NpdGlvbi5sZWZ0O1xuICAgICAgICAgIHRvb2x0aXBDb21wb25lbnQucG9zVG9wID0gdG9vbHRpcFBvc2l0aW9uLnRvcDtcblxuICAgICAgICAgIHRvb2x0aXBDb21wb25lbnQuZmFkZVN0YXRlID0gJ3Zpc2libGUnO1xuXG4gICAgICAgICAgaWYgKHRoaXMuYXJyb3cpIHtcbiAgICAgICAgICAgIGxldCBhcnJvd1Bvc2l0aW9uO1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zaXRpb25WID09PSAndG9wJykge1xuICAgICAgICAgICAgICBhcnJvd1Bvc2l0aW9uID0gJ2JvdHRvbSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucG9zaXRpb25WID09PSAnYm90dG9tJykge1xuICAgICAgICAgICAgICBhcnJvd1Bvc2l0aW9uID0gJ3RvcCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucG9zaXRpb25IID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgYXJyb3dQb3NpdGlvbiA9ICdyaWdodCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhcnJvd1Bvc2l0aW9uID0gJ2xlZnQnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdG9vbHRpcENvbXBvbmVudC5hcnJvdyA9IGFycm93UG9zaXRpb247XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCF0aGlzLl9hY3RpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuX3Rvb2x0aXBUaW1lb3V0ID0gc2V0VGltZW91dChcbiAgICAgICAgICAgICAgdGhpcy5yZW1vdmVUb29sdGlwLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgIHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgdGhpcy5kZWJvdW5jZVxuICAgICk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdjbGljaycpXG4gIG9uQ2xpY2soKTp2b2lkIHtcbiAgICBpZiAodGhpcy5ldmVudCA9PT0gVG9vbHRpcEV2ZW50LkNMSUNLKSB7XG4gICAgICB0aGlzLnRyaWdnZXIoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdwcmVzcycpXG4gIG9uUHJlc3MoKTp2b2lkIHtcbiAgICBpZiAodGhpcy5ldmVudCA9PT0gVG9vbHRpcEV2ZW50LlBSRVNTKSB7XG4gICAgICB0aGlzLnRyaWdnZXIoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdtb3VzZWVudGVyJylcbiAgb25Nb3VzZUVudGVyKCk6dm9pZCB7XG4gICAgaWYgKHRoaXMuZXZlbnQgPT09IFRvb2x0aXBFdmVudC5IT1ZFUikge1xuICAgICAgdGhpcy5hY3RpdmUgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbGVhdmUnKVxuICBvbk1vdXNlTGVhdmUoKTp2b2lkIHtcbiAgICBpZiAodGhpcy5ldmVudCA9PT0gVG9vbHRpcEV2ZW50LkhPVkVSKSB7XG4gICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2NyZWF0ZVRvb2x0aXBDb21wb25lbnQoKSB7XG4gICAgY29uc3QgY29tcG9uZW50RmFjdG9yeSA9IHRoaXMuY2ZyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KFRvb2x0aXBCb3hDb21wb25lbnQpO1xuICAgIHRoaXMuX3Rvb2x0aXBFbGVtZW50ID0gdGhpcy52Y3IuY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudEZhY3RvcnkpO1xuICAgIHRoaXMudG9vbHRpcEN0cmwuYWRkVG9vbHRpcCh0aGlzKTtcbiAgfVxuXG4gIHByaXZhdGUgX2dldFRvb2x0aXBQb3NpdGlvbigpIHtcbiAgICBjb25zdCB0b29sdGlwTmF0aXZlRWxlbWVudDpIVE1MRWxlbWVudCA9IHRoaXMuX3Rvb2x0aXBFbGVtZW50Lmluc3RhbmNlLmdldE5hdGl2ZUVsZW1lbnQoKSxcbiAgICAgIGVsOkhUTUxFbGVtZW50ID0gdGhpcy5lbC5uYXRpdmVFbGVtZW50LFxuICAgICAgcmVjdDpDbGllbnRSZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICBsZXQgcG9zaXRpb25MZWZ0Om51bWJlcixcbiAgICAgIHBvc2l0aW9uVG9wOm51bWJlcixcbiAgICAgIHNwYWNpbmcgPSAxMDtcblxuICAgIGlmICh0aGlzLm5hdlRvb2x0aXApIHtcbiAgICAgIHRoaXMucG9zaXRpb25WID0gJ2JvdHRvbSc7XG4gICAgICB0aGlzLmFycm93ID0gZmFsc2U7XG4gICAgICBzcGFjaW5nID0gMjA7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucG9zaXRpb25IID09PSAncmlnaHQnKSB7XG4gICAgICBwb3NpdGlvbkxlZnQgPSByZWN0LnJpZ2h0ICsgc3BhY2luZztcbiAgICB9IGVsc2UgaWYgKHRoaXMucG9zaXRpb25IID09PSAnbGVmdCcpIHtcbiAgICAgIHBvc2l0aW9uTGVmdCA9IHJlY3QubGVmdCAtIHNwYWNpbmcgLSB0b29sdGlwTmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgIC8vIC03OSwgMTlcbiAgICB9IGVsc2UgaWYgKHRoaXMubmF2VG9vbHRpcCkge1xuICAgICAgcG9zaXRpb25MZWZ0ID0gcmVjdC5sZWZ0ICsgZWwub2Zmc2V0V2lkdGggLyAyO1xuICAgIH0gZWxzZSB7XG4gICAgICBwb3NpdGlvbkxlZnQgPSByZWN0LmxlZnQ7XG4gICAgfVxuXG5cbiAgICBpZiAodGhpcy5wb3NpdGlvblYgPT09ICd0b3AnKSB7XG4gICAgICBwb3NpdGlvblRvcCA9IHJlY3QudG9wIC0gc3BhY2luZyAtIHRvb2x0aXBOYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICB9IGVsc2UgaWYgKHRoaXMucG9zaXRpb25WID09PSAnYm90dG9tJykge1xuICAgICAgcG9zaXRpb25Ub3AgPSByZWN0LmJvdHRvbSArIHNwYWNpbmc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBvc2l0aW9uVG9wID0gcmVjdC50b3AgKyBlbC5vZmZzZXRIZWlnaHQgLyAyIC0gdG9vbHRpcE5hdGl2ZUVsZW1lbnQub2Zmc2V0SGVpZ2h0IC8gMjtcbiAgICB9XG5cbiAgICB0aGlzLnRvcE9mZnNldCsrO1xuICAgIGlmICh0aGlzLnRvcE9mZnNldCkge1xuICAgICAgcG9zaXRpb25Ub3AgKz0gK3RoaXMudG9wT2Zmc2V0O1xuICAgIH1cblxuICAgIHRoaXMubGVmdE9mZnNldCsrO1xuICAgIGlmICh0aGlzLmxlZnRPZmZzZXQpIHtcbiAgICAgIHBvc2l0aW9uTGVmdCArPSArdGhpcy5sZWZ0T2Zmc2V0O1xuICAgIH1cblxuICAgIGlmIChwb3NpdGlvbkxlZnQgKyB0b29sdGlwTmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aCArIHNwYWNpbmcgPiB0aGlzLnBsYXRmb3JtLndpZHRoKCkpIHtcbiAgICAgIHBvc2l0aW9uTGVmdCA9IHRoaXMucGxhdGZvcm0ud2lkdGgoKSAtIHRvb2x0aXBOYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoIC0gc3BhY2luZztcbiAgICB9IGVsc2UgaWYgKHBvc2l0aW9uTGVmdCArIHRvb2x0aXBOYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoIC0gc3BhY2luZyA8IDApIHtcbiAgICAgIHBvc2l0aW9uTGVmdCA9IHNwYWNpbmc7XG4gICAgfVxuXG4gICAgaWYgKHBvc2l0aW9uVG9wICsgdG9vbHRpcE5hdGl2ZUVsZW1lbnQub2Zmc2V0SGVpZ2h0ICsgc3BhY2luZyA+IHRoaXMucGxhdGZvcm0uaGVpZ2h0KCkpIHtcbiAgICAgIHBvc2l0aW9uVG9wID0gdGhpcy5wbGF0Zm9ybS5oZWlnaHQoKSAtIHRvb2x0aXBOYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCAtIHNwYWNpbmc7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvblRvcCArIHRvb2x0aXBOYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCAtIHNwYWNpbmcgPCAwKSB7XG4gICAgICBwb3NpdGlvblRvcCA9IHNwYWNpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxlZnQ6IHBvc2l0aW9uTGVmdCxcbiAgICAgIHRvcDogIHBvc2l0aW9uVG9wLFxuICAgIH07XG4gIH1cblxuICByZW1vdmVUb29sdGlwKCkge1xuICAgIGlmICh0aGlzLl9kZWJvdW5jZWRQcm9taXNlKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5fZGVib3VuY2VkUHJvbWlzZSk7XG5cbiAgICAgIHRoaXMuX2RlYm91bmNlZFByb21pc2UgPSBudWxsO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fdG9vbHRpcEVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX3Rvb2x0aXBFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5fdG9vbHRpcFRpbWVvdXQgPSB1bmRlZmluZWQ7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fdG9vbHRpcEVsZW1lbnQuaW5zdGFuY2UuZmFkZVN0YXRlID0gJ2ludmlzaWJsZSc7XG5cbiAgICB0aGlzLmNhblNob3cgPSBmYWxzZTtcblxuICAgIC8vIHdhaXQgZm9yIGFuaW1hdGlvbiB0byBmaW5pc2ggdGhlbiBjbGVhciBldmVyeXRoaW5nIG91dFxuICAgIHNldFRpbWVvdXQoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLl90b29sdGlwRWxlbWVudCAmJlxuICAgICAgICAgIHR5cGVvZiB0aGlzLl90b29sdGlwRWxlbWVudC5kZXN0cm95ID09PSAnZnVuY3Rpb24nXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMuX3Rvb2x0aXBFbGVtZW50LmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRvb2x0aXBDdHJsLnJlbW92ZVRvb2x0aXAodGhpcyk7XG4gICAgICAgIHRoaXMuX3Rvb2x0aXBFbGVtZW50ID0gdGhpcy5fdG9vbHRpcFRpbWVvdXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuY2FuU2hvdyA9IHRydWU7XG4gICAgICB9LFxuICAgICAgMzAwXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgX3Jlc2V0VGltZXIoKTp2b2lkIHtcbiAgICBjbGVhclRpbWVvdXQodGhpcy5fdG9vbHRpcFRpbWVvdXQpO1xuICAgIHRoaXMuX3Rvb2x0aXBUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgIH0sIHRoaXMuZHVyYXRpb24pO1xuICB9XG59XG4iXX0=