smart-tooltip-angular
Version:
A package that allows you tooltip to show intelligently base on where it is
421 lines • 56.2 kB
JavaScript
import { __decorate } from "tslib";
import { OnInit, Directive, HostBinding, HostListener, ElementRef } from '@angular/core';
let SmartTooltipAngularDirective = class SmartTooltipAngularDirective {
constructor(elementRef) {
this.elementRef = elementRef;
this.classes = ["right", "right-t", "right-b", "left", "left-t", "left-b", "bottom", "bottom-r", "bottom-l", "top", "top-r", "top-l"];
this.offSetValue = 5;
let tooltipContainer = elementRef.nativeElement;
tooltipContainer.classList.add("smart-tooltip-container");
}
mouseEnter() {
//Run the code on click if the element doesn't have the clicktoshow class
if (!this.elementRef.nativeElement.classList.contains("clicktoshow")) {
this.myfunc(this.elementRef);
}
}
click() {
//Run the code on click if the element has the clicktoshow class
if (this.elementRef.nativeElement.classList.contains("clicktoshow")) {
//Get access to the tooltip element
let tooltip = this.elementRef.nativeElement.querySelector(".smart-tooltip");
//Add the stick class to allow the element to stay when it's clicked
tooltip.classList.add("stick");
this.myfunc(this.elementRef);
}
}
mouseLeave() {
this.mouseLeft(this.elementRef);
}
ngOnInit() {
let tooltipContainer = this.elementRef.nativeElement;
let tooltip = tooltipContainer.querySelector(".smart-tooltip");
//Assign tabIndex to allow element to be focusable
if (tooltip) {
tooltip.tabIndex = 1;
tooltip.addEventListener("blur", (event) => {
this.toolTipBlured(event.target);
});
tooltip.addEventListener("mouseleave", (event) => {
this.tooltipMouseLeft(event.target);
});
tooltip.addEventListener("mouseenter", (event) => {
this.tooltipMouseEnter(event.target);
});
}
}
toolTipBlured(tooltip) {
//console.log("toolTipBlured");
if (this.removeOverlayClass(tooltip)) {
let tooltipRect = tooltip.getBoundingClientRect();
//Reset Inline Styles
tooltip.style.position = "";
tooltip.style.top = "";
tooltip.style.left = "";
tooltip.style.bottom = "";
tooltip.style.right = "";
tooltip.classList.add("overlay");
}
tooltip.style.visibility = "collapse";
tooltip.style.opacity = "0";
tooltip.style.display = "none";
}
myfunc(elementRef) {
clearTimeout(this.mouseLeftTimeOut);
let root = this;
let btn = elementRef.nativeElement;
if (!btn)
return;
//var body = document.querySelector("body");
let tooltip = btn.querySelector(".smart-tooltip");
if (!tooltip)
return;
tooltip.style.visibility = "visible";
tooltip.style.opacity = "1";
tooltip.style.display = "block";
var tooltipclient = tooltip.getBoundingClientRect();
var btnclient = btn.getBoundingClientRect();
//var bodyclient = body.getClientRects()[0];
let windowWidth = window.innerWidth;
let windowHeight = window.innerHeight;
var spaces = {
left: btnclient.left > tooltipclient.width,
right: (windowWidth - btnclient.right) > tooltipclient.width,
top: btnclient.top > tooltipclient.height,
bottom: (windowHeight - btnclient.bottom) > tooltipclient.height,
getSpace: function (key) {
let stayClass = root.getStayClass(tooltip);
// debugger;
if (stayClass) {
if (stayClass == key)
return true;
else
return false;
}
return this[key];
}
};
this.removeTooltipClass(tooltip);
if (spaces.getSpace("left")) {
let topHalf = (btnclient.bottom - (btnclient.height / 2));
let bottomHalf = windowHeight - topHalf;
let halfTooltip = (tooltipclient.height / 2);
let isContainerBigger = btnclient.height >= tooltipclient.height;
if (isContainerBigger || ((topHalf > halfTooltip) && (bottomHalf > halfTooltip))) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "left")) {
tooltip.classList.add('left');
}
}
else if (topHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "left-b")) {
tooltip.classList.add('left-b');
}
}
else if (bottomHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "left-t")) {
tooltip.classList.add('left-t');
}
}
}
else if (spaces.getSpace("right")) {
let topHalf = (btnclient.bottom - (btnclient.height / 2));
let bottomHalf = windowHeight - topHalf;
let halfTooltip = (tooltipclient.height / 2);
let isContainerBigger = btnclient.height >= tooltipclient.height;
if (isContainerBigger || ((topHalf > halfTooltip) && (bottomHalf > halfTooltip))) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "right")) {
tooltip.classList.add('right');
}
}
else if (topHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "right-b")) {
tooltip.classList.add('right-b');
}
}
else if (bottomHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "right-t")) {
tooltip.classList.add('right-t');
}
}
}
else if (spaces.getSpace("top")) {
let leftHalf = (btnclient.right - (btnclient.width / 2));
let rightHalf = windowWidth - leftHalf;
let halfTooltip = (tooltipclient.width / 2);
let isContainerBigger = btnclient.width >= tooltipclient.width;
if (isContainerBigger || ((leftHalf > halfTooltip) && (rightHalf > halfTooltip))) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "top")) {
tooltip.classList.add('top');
}
}
else if (leftHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "top-r")) {
tooltip.classList.add('top-r');
}
}
else if (rightHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "top-l")) {
tooltip.classList.add('top-l');
}
}
}
else if (spaces.getSpace("bottom")) {
// debugger;
let leftHalf = (btnclient.right - (btnclient.width / 2));
let rightHalf = windowWidth - leftHalf;
let halfTooltip = (tooltipclient.width / 2);
let isContainerBigger = btnclient.width >= tooltipclient.width;
if (isContainerBigger || ((leftHalf > halfTooltip) && (rightHalf > halfTooltip))) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom")) {
tooltip.classList.add('bottom');
}
}
else if (leftHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom-r")) {
tooltip.classList.add('bottom-r');
}
}
else if (rightHalf <= halfTooltip) {
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom-l")) {
tooltip.classList.add('bottom-l');
}
}
}
else {
// debugger;
if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom")) {
tooltip.classList.add('bottom');
}
}
}
removeTooltipClass(tooltip) {
let classList = tooltip.classList;
classList.forEach(element => {
if (this.classes.includes(element)) {
classList.remove(element);
}
});
}
getStayClass(tooltip) {
var classList = tooltip.classList;
let stayPosition;
classList.forEach(element => {
if (element.includes(`stay-`)) {
stayPosition = element.split("-")[1];
}
});
return stayPosition;
}
mouseLeft(elementRef) {
// console.log("mouseLeft");
let btn = elementRef.nativeElement;
if (!btn)
return;
let tooltip = btn.querySelector(".smart-tooltip");
if (!tooltip)
return;
var stickyTime = this.getStickyTime(tooltip);
if (!isNaN(stickyTime)) {
this.mouseLeftTimeOut = setTimeout(() => {
if (tooltip.classList.contains("hovered"))
return;
if (this.removeOverlayClass(tooltip)) {
let tooltipRect = tooltip.getBoundingClientRect();
//Reset Inline Styles
tooltip.style.position = "";
tooltip.style.top = "";
tooltip.style.left = "";
tooltip.style.bottom = "";
tooltip.style.right = "";
tooltip.classList.add("overlay");
}
//Make sure its not visible after mouse has left
tooltip.style.visibility = "collapse";
tooltip.style.opacity = "0";
tooltip.style.display = "none";
}, stickyTime);
}
else {
tooltip.focus();
}
}
removeOverlayClass(tooltip) {
let hasOverlay = false;
if (tooltip.classList.contains("overlayed")) {
hasOverlay = true;
tooltip.classList.remove("overlayed");
}
return hasOverlay;
}
removeOverlayMarkClass(tooltip) {
let hasOverlay = false;
if (tooltip.classList.contains("overlay")) {
hasOverlay = true;
tooltip.classList.remove("overlay");
}
return hasOverlay;
}
/**
* Calculate the position of the tooltip based on the fixed position of the container
* @param {DOMClientRect} btnclient The Rectangle that defines the button element
* @param {string} tooltipPostion The position the tooltip should be displayed
*/
getOverlayCoordinates(btnclient, tooltipclient, tooltipPostion) {
// let body:any = document.querySelector("body");
// let bodyclient = body.getClientRects()[0];
let windowWidth = window.innerWidth;
let windowHeight = window.innerHeight;
if (tooltipPostion.includes("right")) {
let overlayCoordinates = {
left: btnclient.right + this.offSetValue,
top: (btnclient.top + (btnclient.height / 2)) - (tooltipclient.height / 2),
props: ["left", "top"]
};
if (tooltipPostion == "right-t") {
overlayCoordinates.bottom = windowHeight - btnclient.bottom;
overlayCoordinates.props = ["left", "bottom"];
}
else if (tooltipPostion == "right-b") {
overlayCoordinates.top = btnclient.top + this.offSetValue;
}
return overlayCoordinates;
}
else if (tooltipPostion.includes("left")) {
let overlayCoordinates = {
right: (windowWidth - btnclient.left) + this.offSetValue,
top: (btnclient.top + (btnclient.height / 2)) - (tooltipclient.height / 2),
props: ["right", "top"]
};
if (tooltipPostion == "left-t") {
overlayCoordinates.bottom = windowHeight - btnclient.bottom;
overlayCoordinates.props = ["right", "bottom"];
}
else if (tooltipPostion == "left-b") {
overlayCoordinates.top = btnclient.top + this.offSetValue;
}
return overlayCoordinates;
}
else if (tooltipPostion.includes("top")) {
let overlayCoordinates = {
left: (btnclient.right - (btnclient.width / 2)) - (tooltipclient.width / 2),
bottom: (windowHeight - btnclient.top) + this.offSetValue,
props: ["left", "bottom"]
};
if (tooltipPostion == "top-l") {
overlayCoordinates.right = (windowWidth - btnclient.right) + this.offSetValue;
overlayCoordinates.props = ["right", "bottom"];
}
else if (tooltipPostion == "top-r") {
overlayCoordinates.left = btnclient.left + this.offSetValue;
}
return overlayCoordinates;
}
else if (tooltipPostion.includes("bottom")) {
let overlayCoordinates = {
left: (btnclient.right - (btnclient.width / 2)) - (tooltipclient.width / 2),
top: btnclient.bottom + this.offSetValue,
props: ["left", "top"]
};
if (tooltipPostion == "bottom-l") {
overlayCoordinates.right = (windowWidth - btnclient.right) + this.offSetValue;
overlayCoordinates.props = ["right", "top"];
}
else if (tooltipPostion == "bottom-r") {
overlayCoordinates.left = btnclient.left + this.offSetValue;
}
return overlayCoordinates;
}
}
/**
* Checks for overlay class and manipulate it
* @param {any} tooltip the tooltip element
* @param {string} position the string that show which side the tooltip is
*/
manipulateOverlayIfPresent(btnBClientRect, tooltip, tooltipPosition) {
//removeOverlayMarkClass checks for the presence of the overlay mark i.e
//overlay .. remove it and add the overlayed class which has the css declarations
//debugger;
if (this.removeOverlayMarkClass(tooltip)) {
// debugger;
//Get the overlay coordinates
let overlayCoordinates = this.getOverlayCoordinates(btnBClientRect, tooltip.getBoundingClientRect(), tooltipPosition);
//Get the set properties base the tooltip position based on the tooltipPosition
//Overlay styles to tooltip control
tooltip.style.position = "fixed";
for (let prop of overlayCoordinates.props) {
tooltip.style[prop] = overlayCoordinates[prop] + "px";
}
//Add the actual overlayed class which resets old styles
tooltip.classList.add("overlayed");
return true;
}
return false;
}
/**
* Get the sticky time on the tooltip or returns zero if none is found
* @param {HtmlElement} tooltip The tooltip element
*/
getStickyTime(tooltip) {
try {
for (let item of tooltip.classList) {
if (item.includes("stick")) {
if (item.includes("-")) {
let numberstring = item.split("-")[1];
return +numberstring;
}
else {
return Number.NaN;
}
}
}
}
catch (_a) {
return 0;
}
//return zero if tooltip doesn't have a sticky class
return 0;
}
tooltipMouseLeft(tooltip) {
//console.log("tooltipMouseLeft");
if (tooltip.classList.contains('hovered')) {
if (!isNaN(this.getStickyTime(tooltip))) {
tooltip.classList.add("stayonhover");
tooltip.classList.remove('hovered');
//console.log("blured");
//tooltip.blur();
}
}
}
tooltipMouseEnter(tooltip) {
//console.log("tooltipMouseEnter");
if (tooltip.classList.contains('stayonhover')) {
if (!isNaN(this.getStickyTime(tooltip))) {
tooltip.classList.remove("stayonhover");
tooltip.classList.add('hovered');
//tooltip.focus();
}
}
}
};
SmartTooltipAngularDirective.ctorParameters = () => [
{ type: ElementRef }
];
__decorate([
HostBinding("style.position")
], SmartTooltipAngularDirective.prototype, "position", void 0);
__decorate([
HostListener("mouseenter")
], SmartTooltipAngularDirective.prototype, "mouseEnter", null);
__decorate([
HostListener("click")
], SmartTooltipAngularDirective.prototype, "click", null);
__decorate([
HostListener("mouseleave")
], SmartTooltipAngularDirective.prototype, "mouseLeave", null);
SmartTooltipAngularDirective = __decorate([
Directive({
selector: '[smart-tooltip-container]',
})
], SmartTooltipAngularDirective);
export { SmartTooltipAngularDirective };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnQtdG9vbHRpcC1hbmd1bGFyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3NtYXJ0LXRvb2x0aXAtYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9zbWFydC10b29sdGlwLWFuZ3VsYXIuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQU96RixJQUFhLDRCQUE0QixHQUF6QyxNQUFhLDRCQUE0QjtJQWlDdkMsWUFBb0IsVUFBc0I7UUFBdEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQS9CMUMsWUFBTyxHQUFHLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUVqSSxnQkFBVyxHQUFHLENBQUMsQ0FBQztRQThCZCxJQUFJLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxhQUFhLENBQUM7UUFDaEQsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUExQjJCLFVBQVU7UUFDcEMseUVBQXlFO1FBQ3pFLElBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFDO1lBQ2xFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQzlCO0lBQ0gsQ0FBQztJQUVzQixLQUFLO1FBQzFCLGdFQUFnRTtRQUNoRSxJQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEVBQUM7WUFDakUsbUNBQW1DO1lBQ25DLElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQzVFLG9FQUFvRTtZQUNwRSxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUUvQixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUM5QjtJQUNILENBQUM7SUFFMkIsVUFBVTtRQUNwQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBT0QsUUFBUTtRQUNOLElBQUksZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7UUFDckQsSUFBSSxPQUFPLEdBQUcsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDL0Qsa0RBQWtEO1FBQ2xELElBQUksT0FBTyxFQUFFO1lBQ1gsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7WUFFckIsT0FBTyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFO2dCQUN6QyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNuQyxDQUFDLENBQUMsQ0FBQztZQUVILE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDL0MsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUNyQyxDQUFDLENBQUMsQ0FBQztZQUVILE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDL0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN2QyxDQUFDLENBQUMsQ0FBQztTQUVKO0lBQ0gsQ0FBQztJQUdELGFBQWEsQ0FBQyxPQUFPO1FBQ25CLCtCQUErQjtRQUMvQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUVwQyxJQUFJLFdBQVcsR0FBRyxPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUVsRCxxQkFBcUI7WUFDckIsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUN2QixPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7WUFDeEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDO1lBQzFCLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztZQUV6QixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUNsQztRQUVELE9BQU8sQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQTtRQUNyQyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUM7UUFDNUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDO0lBRWpDLENBQUM7SUFHRCxNQUFNLENBQUMsVUFBc0I7UUFDM0IsWUFBWSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BDLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQztRQUVoQixJQUFJLEdBQUcsR0FBRyxVQUFVLENBQUMsYUFBYSxDQUFDO1FBQ25DLElBQUksQ0FBQyxHQUFHO1lBQUUsT0FBTztRQUNqQiw0Q0FBNEM7UUFFNUMsSUFBSSxPQUFPLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRWxELElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTztRQUVyQixPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUM7UUFDckMsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDO1FBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUVoQyxJQUFJLGFBQWEsR0FBRyxPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNwRCxJQUFJLFNBQVMsR0FBRyxHQUFHLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUM1Qyw0Q0FBNEM7UUFFNUMsSUFBSSxXQUFXLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUNwQyxJQUFJLFlBQVksR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDO1FBRXRDLElBQUksTUFBTSxHQUFHO1lBQ1gsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJLEdBQUcsYUFBYSxDQUFDLEtBQUs7WUFDMUMsS0FBSyxFQUFFLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxhQUFhLENBQUMsS0FBSztZQUM1RCxHQUFHLEVBQUUsU0FBUyxDQUFDLEdBQUcsR0FBRyxhQUFhLENBQUMsTUFBTTtZQUN6QyxNQUFNLEVBQUUsQ0FBQyxZQUFZLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLGFBQWEsQ0FBQyxNQUFNO1lBQ2hFLFFBQVEsRUFBRSxVQUFVLEdBQUc7Z0JBQ3JCLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzNDLFlBQVk7Z0JBQ1osSUFBSSxTQUFTLEVBQUU7b0JBQ2IsSUFBSSxTQUFTLElBQUksR0FBRzt3QkFDbEIsT0FBTyxJQUFJLENBQUM7O3dCQUVaLE9BQU8sS0FBSyxDQUFDO2lCQUNoQjtnQkFDRCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNuQixDQUFDO1NBQ0YsQ0FBQTtRQUVELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFFM0IsSUFBSSxPQUFPLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFELElBQUksVUFBVSxHQUFHLFlBQVksR0FBRyxPQUFPLENBQUM7WUFDeEMsSUFBSSxXQUFXLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBRTdDLElBQUksaUJBQWlCLEdBQUcsU0FBUyxDQUFDLE1BQU0sSUFBSSxhQUFhLENBQUMsTUFBTSxDQUFDO1lBRWpFLElBQUksaUJBQWlCLElBQUksQ0FBQyxDQUFDLE9BQU8sR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUMsQ0FBQyxFQUFFO2dCQUNoRixJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLEVBQUU7b0JBQ2hFLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2lCQUMvQjthQUNGO2lCQUFNLElBQUksT0FBTyxJQUFJLFdBQVcsRUFBRTtnQkFDakMsSUFBSSxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxFQUFFO29CQUNsRSxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztpQkFDakM7YUFFRjtpQkFBTSxJQUFJLFVBQVUsSUFBSSxXQUFXLEVBQUU7Z0JBQ3BDLElBQUksQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsRUFBRTtvQkFDbEUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7aUJBQ2pDO2FBRUY7U0FFRjthQUFNLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUVuQyxJQUFJLE9BQU8sR0FBRyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUQsSUFBSSxVQUFVLEdBQUcsWUFBWSxHQUFHLE9BQU8sQ0FBQztZQUN4QyxJQUFJLFdBQVcsR0FBRyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFFN0MsSUFBSSxpQkFBaUIsR0FBRyxTQUFTLENBQUMsTUFBTSxJQUFJLGFBQWEsQ0FBQyxNQUFNLENBQUM7WUFFakUsSUFBSSxpQkFBaUIsSUFBSSxDQUFDLENBQUMsT0FBTyxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLFdBQVcsQ0FBQyxDQUFDLEVBQUU7Z0JBQ2hGLElBQUksQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRTtvQkFDakUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQ2hDO2FBQ0Y7aUJBQU0sSUFBSSxPQUFPLElBQUksV0FBVyxFQUFFO2dCQUNqQyxJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBUyxDQUFDLEVBQUU7b0JBQ25FLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2lCQUNsQzthQUNGO2lCQUFNLElBQUksVUFBVSxJQUFJLFdBQVcsRUFBRTtnQkFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxFQUFFO29CQUNuRSxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztpQkFDbEM7YUFDRjtTQUVGO2FBQU0sSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBRWpDLElBQUksUUFBUSxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN6RCxJQUFJLFNBQVMsR0FBRyxXQUFXLEdBQUcsUUFBUSxDQUFDO1lBQ3ZDLElBQUksV0FBVyxHQUFHLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztZQUU1QyxJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FBQyxLQUFLLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQztZQUUvRCxJQUFJLGlCQUFpQixJQUFJLENBQUMsQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDLENBQUMsRUFBRTtnQkFDaEYsSUFBSSxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxFQUFFO29CQUMvRCxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDOUI7YUFDRjtpQkFBTSxJQUFJLFFBQVEsSUFBSSxXQUFXLEVBQUU7Z0JBQ2xDLElBQUksQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRTtvQkFDakUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQ2hDO2FBRUY7aUJBQU0sSUFBSSxTQUFTLElBQUksV0FBVyxFQUFFO2dCQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLEVBQUU7b0JBQ2pFLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUNoQzthQUNGO1NBRUY7YUFBTSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDcEMsWUFBWTtZQUNaLElBQUksUUFBUSxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN6RCxJQUFJLFNBQVMsR0FBRyxXQUFXLEdBQUcsUUFBUSxDQUFDO1lBQ3ZDLElBQUksV0FBVyxHQUFHLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztZQUU1QyxJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FBQyxLQUFLLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQztZQUkvRCxJQUFJLGlCQUFpQixJQUFJLENBQUMsQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDLENBQUMsRUFBRTtnQkFDaEYsSUFBSSxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxFQUFFO29CQUNsRSxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztpQkFDakM7YUFFRjtpQkFBTSxJQUFJLFFBQVEsSUFBSSxXQUFXLEVBQUU7Z0JBQ2xDLElBQUksQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsRUFBRTtvQkFDcEUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7aUJBQ25DO2FBRUY7aUJBQU0sSUFBSSxTQUFTLElBQUksV0FBVyxFQUFFO2dCQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLEVBQUU7b0JBQ3BFLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2lCQUNuQzthQUNGO1NBR0Y7YUFBTTtZQUNMLFlBQVk7WUFDWixJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLEVBQUU7Z0JBQ2xFLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ2pDO1NBQ0Y7SUFFSCxDQUFDO0lBRUQsa0JBQWtCLENBQUMsT0FBTztRQUN4QixJQUFJLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDO1FBQ2xDLFNBQVMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDMUIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDbEMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUMzQjtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFlBQVksQ0FBQyxPQUFPO1FBQ2xCLElBQUksU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFDbEMsSUFBSSxZQUFZLENBQUM7UUFDakIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUMxQixJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQzdCLFlBQVksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3RDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDO0lBR0QsU0FBUyxDQUFDLFVBQXNCO1FBQy9CLDRCQUE0QjtRQUMzQixJQUFJLEdBQUcsR0FBRyxVQUFVLENBQUMsYUFBYSxDQUFDO1FBQ25DLElBQUksQ0FBQyxHQUFHO1lBQUUsT0FBTztRQUVqQixJQUFJLE9BQU8sR0FBRyxHQUFHLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFFbEQsSUFBSSxDQUFDLE9BQU87WUFBRSxPQUFPO1FBR3JCLElBQUksVUFBVSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFJN0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUN0QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtnQkFFdEMsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7b0JBQ3ZDLE9BQU87Z0JBRVQsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLEVBQUU7b0JBRXBDLElBQUksV0FBVyxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO29CQUdsRCxxQkFBcUI7b0JBQ3JCLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztvQkFDNUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDO29CQUN2QixPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ3hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztvQkFDMUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUl6QixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztpQkFDbEM7Z0JBRUQsZ0RBQWdEO2dCQUNoRCxPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUE7Z0JBQ3JDLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQztnQkFDNUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDO1lBRWpDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztTQUNoQjthQUFNO1lBQ0wsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2pCO0lBR0gsQ0FBQztJQUVELGtCQUFrQixDQUFDLE9BQU87UUFDeEIsSUFBSSxVQUFVLEdBQUcsS0FBSyxDQUFBO1FBRXRCLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUU7WUFDM0MsVUFBVSxHQUFHLElBQUksQ0FBQztZQUNsQixPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztTQUN2QztRQUVELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxzQkFBc0IsQ0FBQyxPQUFPO1FBQzVCLElBQUksVUFBVSxHQUFHLEtBQUssQ0FBQTtRQUV0QixJQUFJLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQ3pDLFVBQVUsR0FBRyxJQUFJLENBQUM7WUFDbEIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDckM7UUFFRCxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILHFCQUFxQixDQUFDLFNBQVMsRUFBRSxhQUFhLEVBQUUsY0FBYztRQUM1RCxpREFBaUQ7UUFDakQsNkNBQTZDO1FBRTdDLElBQUksV0FBVyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUM7UUFDcEMsSUFBSSxZQUFZLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQztRQUV0QyxJQUFJLGNBQWMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFFcEMsSUFBSSxrQkFBa0IsR0FBUTtnQkFDNUIsSUFBSSxFQUFFLFNBQVMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVc7Z0JBQ3hDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztnQkFDMUUsS0FBSyxFQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQzthQUN2QixDQUFBO1lBRUQsSUFBSSxjQUFjLElBQUksU0FBUyxFQUFFO2dCQUMvQixrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsWUFBWSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7Z0JBQzVELGtCQUFrQixDQUFDLEtBQUssR0FBRyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQzthQUMvQztpQkFBTSxJQUFJLGNBQWMsSUFBSSxTQUFTLEVBQUU7Z0JBQ3RDLGtCQUFrQixDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7YUFDM0Q7WUFFRCxPQUFPLGtCQUFrQixDQUFDO1NBQzNCO2FBQU0sSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBRTFDLElBQUksa0JBQWtCLEdBQVE7Z0JBQzVCLEtBQUssRUFBRSxDQUFDLFdBQVcsR0FBRyxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVc7Z0JBQ3hELEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztnQkFDMUUsS0FBSyxFQUFFLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQzthQUN4QixDQUFBO1lBRUQsSUFBSSxjQUFjLElBQUksUUFBUSxFQUFFO2dCQUM5QixrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsWUFBWSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7Z0JBQzVELGtCQUFrQixDQUFDLEtBQUssR0FBRyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQzthQUNoRDtpQkFBTSxJQUFJLGNBQWMsSUFBSSxRQUFRLEVBQUU7Z0JBQ3JDLGtCQUFrQixDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7YUFDM0Q7WUFFRCxPQUFPLGtCQUFrQixDQUFDO1NBQzNCO2FBQU0sSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBRXpDLElBQUksa0JBQWtCLEdBQVE7Z0JBQzVCLElBQUksRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztnQkFDM0UsTUFBTSxFQUFFLENBQUMsWUFBWSxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVztnQkFDekQsS0FBSyxFQUFFLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQzthQUMxQixDQUFBO1lBRUQsSUFBSSxjQUFjLElBQUksT0FBTyxFQUFFO2dCQUM3QixrQkFBa0IsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7Z0JBQzlFLGtCQUFrQixDQUFDLEtBQUssR0FBRyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQTthQUMvQztpQkFBTSxJQUFJLGNBQWMsSUFBSSxPQUFPLEVBQUU7Z0JBQ3BDLGtCQUFrQixDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7YUFDN0Q7WUFFRCxPQUFPLGtCQUFrQixDQUFDO1NBQzNCO2FBQU0sSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBRTVDLElBQUksa0JBQWtCLEdBQVE7Z0JBQzVCLElBQUksRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztnQkFDM0UsR0FBRyxFQUFFLFNBQVMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVc7Z0JBQ3hDLEtBQUssRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUM7YUFDdkIsQ0FBQTtZQUVELElBQUksY0FBYyxJQUFJLFVBQVUsRUFBRTtnQkFDaEMsa0JBQWtCLENBQUMsS0FBSyxHQUFHLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO2dCQUM5RSxrQkFBa0IsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUE7YUFDNUM7aUJBQU0sSUFBSSxjQUFjLElBQUksVUFBVSxFQUFFO2dCQUN2QyxrQkFBa0IsQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO2FBQzdEO1lBRUQsT0FBTyxrQkFBa0IsQ0FBQztTQUMzQjtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsMEJBQTBCLENBQUMsY0FBYyxFQUFFLE9BQU8sRUFBRSxlQUFlO1FBQ2pFLHdFQUF3RTtRQUN4RSxpRkFBaUY7UUFDakYsV0FBVztRQUNYLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBRXhDLFlBQVk7WUFDWiw2QkFBNkI7WUFDN0IsSUFBSSxrQkFBa0IsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1lBRXRILCtFQUErRTtZQUUvRSxtQ0FBbUM7WUFDbkMsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1lBRWpDLEtBQUssSUFBSSxJQUFJLElBQUksa0JBQWtCLENBQUMsS0FBSyxFQUFFO2dCQUN6QyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQzthQUN2RDtZQUdELHdEQUF3RDtZQUN4RCxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUVuQyxPQUFPLElBQUksQ0FBQztTQUNiO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsYUFBYSxDQUFDLE9BQU87UUFFbkIsSUFBSTtZQUNGLEtBQUssSUFBSSxJQUFJLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRTtnQkFDbEMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO29CQUMxQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUU7d0JBQ3RCLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQ3RDLE9BQU8sQ0FBQyxZQUFZLENBQUM7cUJBQ3RCO3lCQUFNO3dCQUNMLE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBQztxQkFDbkI7aUJBQ0Y7YUFDRjtTQUNGO1FBQUMsV0FBSztZQUNMLE9BQU8sQ0FBQyxDQUFDO1NBQ1Y7UUFFRCxvREFBb0Q7UUFDcEQsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBRUQsZ0JBQWdCLENBQUMsT0FBTztRQUN0QixrQ0FBa0M7UUFDbEMsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUV6QyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRTtnQkFDdkMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQ3JDLE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNwQyx3QkFBd0I7Z0JBQ3hCLGlCQUFpQjthQUNsQjtTQUVGO0lBQ0gsQ0FBQztJQUVELGlCQUFpQixDQUFDLE9BQU87UUFDdkIsbUNBQW1DO1FBQ25DLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDN0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUU7Z0JBQ3ZDLE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUN4QyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDakMsa0JBQWtCO2FBQ25CO1NBQ0Y7SUFDSCxDQUFDO0NBRUYsQ0FBQTs7WUF4Y2lDLFVBQVU7O0FBekJYO0lBQTlCLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQzs4REFBVTtBQUVaO0lBQTNCLFlBQVksQ0FBQyxZQUFZLENBQUM7OERBSzFCO0FBRXNCO0lBQXRCLFlBQVksQ0FBQyxPQUFPLENBQUM7eURBVXJCO0FBRTJCO0lBQTNCLFlBQVksQ0FBQyxZQUFZLENBQUM7OERBRTFCO0FBL0JVLDRCQUE0QjtJQUp4QyxTQUFTLENBQUM7UUFDVCxRQUFRLEVBQUUsMkJBQTJCO0tBRXRDLENBQUM7R0FDVyw0QkFBNEIsQ0F5ZXhDO1NBemVZLDRCQUE0QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9uSW5pdCwgRGlyZWN0aXZlLCBIb3N0QmluZGluZywgSG9zdExpc3RlbmVyLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBlbGVtZW50IH0gZnJvbSAncHJvdHJhY3Rvcic7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tzbWFydC10b29sdGlwLWNvbnRhaW5lcl0nLFxuXG59KVxuZXhwb3J0IGNsYXNzIFNtYXJ0VG9vbHRpcEFuZ3VsYXJEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIGNsYXNzZXMgPSBbXCJyaWdodFwiLCBcInJpZ2h0LXRcIiwgXCJyaWdodC1iXCIsIFwibGVmdFwiLCBcImxlZnQtdFwiLCBcImxlZnQtYlwiLCBcImJvdHRvbVwiLCBcImJvdHRvbS1yXCIsIFwiYm90dG9tLWxcIiwgXCJ0b3BcIiwgXCJ0b3AtclwiLCBcInRvcC1sXCJdO1xuXG4gIG9mZlNldFZhbHVlID0gNTtcblxuICBtb3VzZUxlZnRUaW1lT3V0O1xuXG4gIEBIb3N0QmluZGluZyhcInN0eWxlLnBvc2l0aW9uXCIpIHBvc2l0aW9uO1xuXG4gIEBIb3N0TGlzdGVuZXIoXCJtb3VzZWVudGVyXCIpIG1vdXNlRW50ZXIoKSB7XG4gICAgLy9SdW4gdGhlIGNvZGUgb24gY2xpY2sgaWYgdGhlIGVsZW1lbnQgZG9lc24ndCBoYXZlIHRoZSBjbGlja3Rvc2hvdyBjbGFzc1xuICAgIGlmKCF0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoXCJjbGlja3Rvc2hvd1wiKSl7XG4gICAgICB0aGlzLm15ZnVuYyh0aGlzLmVsZW1lbnRSZWYpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoXCJjbGlja1wiKSBjbGljaygpIHtcbiAgICAvL1J1biB0aGUgY29kZSBvbiBjbGljayBpZiB0aGUgZWxlbWVudCBoYXMgdGhlIGNsaWNrdG9zaG93IGNsYXNzXG4gICAgaWYodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKFwiY2xpY2t0b3Nob3dcIikpe1xuICAgICAgLy9HZXQgYWNjZXNzIHRvIHRoZSB0b29sdGlwIGVsZW1lbnRcbiAgICAgIGxldCB0b29sdGlwID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihcIi5zbWFydC10b29sdGlwXCIpO1xuICAgICAgLy9BZGQgdGhlIHN0aWNrIGNsYXNzIHRvIGFsbG93IHRoZSBlbGVtZW50IHRvIHN0YXkgd2hlbiBpdCdzIGNsaWNrZWRcbiAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZChcInN0aWNrXCIpO1xuXG4gICAgICB0aGlzLm15ZnVuYyh0aGlzLmVsZW1lbnRSZWYpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoXCJtb3VzZWxlYXZlXCIpIG1vdXNlTGVhdmUoKSB7XG4gICAgdGhpcy5tb3VzZUxlZnQodGhpcy5lbGVtZW50UmVmKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICAgIGxldCB0b29sdGlwQ29udGFpbmVyID0gZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIHRvb2x0aXBDb250YWluZXIuY2xhc3NMaXN0LmFkZChcInNtYXJ0LXRvb2x0aXAtY29udGFpbmVyXCIpO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgbGV0IHRvb2x0aXBDb250YWluZXIgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICBsZXQgdG9vbHRpcCA9IHRvb2x0aXBDb250YWluZXIucXVlcnlTZWxlY3RvcihcIi5zbWFydC10b29sdGlwXCIpO1xuICAgIC8vQXNzaWduIHRhYkluZGV4IHRvIGFsbG93IGVsZW1lbnQgdG8gYmUgZm9jdXNhYmxlXG4gICAgaWYgKHRvb2x0aXApIHtcbiAgICAgIHRvb2x0aXAudGFiSW5kZXggPSAxO1xuXG4gICAgICB0b29sdGlwLmFkZEV2ZW50TGlzdGVuZXIoXCJibHVyXCIsIChldmVudCkgPT4ge1xuICAgICAgICB0aGlzLnRvb2xUaXBCbHVyZWQoZXZlbnQudGFyZ2V0KTtcbiAgICAgIH0pO1xuXG4gICAgICB0b29sdGlwLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZWxlYXZlXCIsIChldmVudCkgPT4ge1xuICAgICAgICB0aGlzLnRvb2x0aXBNb3VzZUxlZnQoZXZlbnQudGFyZ2V0KVxuICAgICAgfSk7XG5cbiAgICAgIHRvb2x0aXAuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlZW50ZXJcIiwgKGV2ZW50KSA9PiB7XG4gICAgICAgIHRoaXMudG9vbHRpcE1vdXNlRW50ZXIoZXZlbnQudGFyZ2V0KTtcbiAgICAgIH0pO1xuXG4gICAgfVxuICB9XG5cblxuICB0b29sVGlwQmx1cmVkKHRvb2x0aXApIHtcbiAgICAvL2NvbnNvbGUubG9nKFwidG9vbFRpcEJsdXJlZFwiKTtcbiAgICBpZiAodGhpcy5yZW1vdmVPdmVybGF5Q2xhc3ModG9vbHRpcCkpIHtcblxuICAgICAgbGV0IHRvb2x0aXBSZWN0ID0gdG9vbHRpcC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgLy9SZXNldCBJbmxpbmUgU3R5bGVzXG4gICAgICB0b29sdGlwLnN0eWxlLnBvc2l0aW9uID0gXCJcIjtcbiAgICAgIHRvb2x0aXAuc3R5bGUudG9wID0gXCJcIjtcbiAgICAgIHRvb2x0aXAuc3R5bGUubGVmdCA9IFwiXCI7XG4gICAgICB0b29sdGlwLnN0eWxlLmJvdHRvbSA9IFwiXCI7XG4gICAgICB0b29sdGlwLnN0eWxlLnJpZ2h0ID0gXCJcIjtcblxuICAgICAgdG9vbHRpcC5jbGFzc0xpc3QuYWRkKFwib3ZlcmxheVwiKTtcbiAgICB9XG5cbiAgICB0b29sdGlwLnN0eWxlLnZpc2liaWxpdHkgPSBcImNvbGxhcHNlXCJcbiAgICB0b29sdGlwLnN0eWxlLm9wYWNpdHkgPSBcIjBcIjtcbiAgICB0b29sdGlwLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcblxuICB9XG5cblxuICBteWZ1bmMoZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICAgIGNsZWFyVGltZW91dCh0aGlzLm1vdXNlTGVmdFRpbWVPdXQpO1xuICAgIGxldCByb290ID0gdGhpcztcblxuICAgIGxldCBidG4gPSBlbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKCFidG4pIHJldHVybjtcbiAgICAvL3ZhciBib2R5ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcImJvZHlcIik7XG5cbiAgICBsZXQgdG9vbHRpcCA9IGJ0bi5xdWVyeVNlbGVjdG9yKFwiLnNtYXJ0LXRvb2x0aXBcIik7XG5cbiAgICBpZiAoIXRvb2x0aXApIHJldHVybjtcblxuICAgIHRvb2x0aXAuc3R5bGUudmlzaWJpbGl0eSA9IFwidmlzaWJsZVwiO1xuICAgIHRvb2x0aXAuc3R5bGUub3BhY2l0eSA9IFwiMVwiO1xuICAgIHRvb2x0aXAuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcblxuICAgIHZhciB0b29sdGlwY2xpZW50ID0gdG9vbHRpcC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgYnRuY2xpZW50ID0gYnRuLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIC8vdmFyIGJvZHljbGllbnQgPSBib2R5LmdldENsaWVudFJlY3RzKClbMF07XG5cbiAgICBsZXQgd2luZG93V2lkdGggPSB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICBsZXQgd2luZG93SGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xuXG4gICAgdmFyIHNwYWNlcyA9IHtcbiAgICAgIGxlZnQ6IGJ0bmNsaWVudC5sZWZ0ID4gdG9vbHRpcGNsaWVudC53aWR0aCxcbiAgICAgIHJpZ2h0OiAod2luZG93V2lkdGggLSBidG5jbGllbnQucmlnaHQpID4gdG9vbHRpcGNsaWVudC53aWR0aCxcbiAgICAgIHRvcDogYnRuY2xpZW50LnRvcCA+IHRvb2x0aXBjbGllbnQuaGVpZ2h0LFxuICAgICAgYm90dG9tOiAod2luZG93SGVpZ2h0IC0gYnRuY2xpZW50LmJvdHRvbSkgPiB0b29sdGlwY2xpZW50LmhlaWdodCxcbiAgICAgIGdldFNwYWNlOiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIGxldCBzdGF5Q2xhc3MgPSByb290LmdldFN0YXlDbGFzcyh0b29sdGlwKTtcbiAgICAgICAgLy8gZGVidWdnZXI7XG4gICAgICAgIGlmIChzdGF5Q2xhc3MpIHtcbiAgICAgICAgICBpZiAoc3RheUNsYXNzID09IGtleSlcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpc1trZXldO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucmVtb3ZlVG9vbHRpcENsYXNzKHRvb2x0aXApO1xuXG4gICAgaWYgKHNwYWNlcy5nZXRTcGFjZShcImxlZnRcIikpIHtcblxuICAgICAgbGV0IHRvcEhhbGYgPSAoYnRuY2xpZW50LmJvdHRvbSAtIChidG5jbGllbnQuaGVpZ2h0IC8gMikpO1xuICAgICAgbGV0IGJvdHRvbUhhbGYgPSB3aW5kb3dIZWlnaHQgLSB0b3BIYWxmO1xuICAgICAgbGV0IGhhbGZUb29sdGlwID0gKHRvb2x0aXBjbGllbnQuaGVpZ2h0IC8gMik7XG5cbiAgICAgIGxldCBpc0NvbnRhaW5lckJpZ2dlciA9IGJ0bmNsaWVudC5oZWlnaHQgPj0gdG9vbHRpcGNsaWVudC5oZWlnaHQ7XG5cbiAgICAgIGlmIChpc0NvbnRhaW5lckJpZ2dlciB8fCAoKHRvcEhhbGYgPiBoYWxmVG9vbHRpcCkgJiYgKGJvdHRvbUhhbGYgPiBoYWxmVG9vbHRpcCkpKSB7XG4gICAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwibGVmdFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnbGVmdCcpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHRvcEhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJsZWZ0LWJcIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ2xlZnQtYicpO1xuICAgICAgICB9XG5cbiAgICAgIH0gZWxzZSBpZiAoYm90dG9tSGFsZiA8PSBoYWxmVG9vbHRpcCkge1xuICAgICAgICBpZiAoIXRoaXMubWFuaXB1bGF0ZU92ZXJsYXlJZlByZXNlbnQoYnRuY2xpZW50LCB0b29sdGlwLCBcImxlZnQtdFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnbGVmdC10Jyk7XG4gICAgICAgIH1cblxuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChzcGFjZXMuZ2V0U3BhY2UoXCJyaWdodFwiKSkge1xuXG4gICAgICBsZXQgdG9wSGFsZiA9IChidG5jbGllbnQuYm90dG9tIC0gKGJ0bmNsaWVudC5oZWlnaHQgLyAyKSk7XG4gICAgICBsZXQgYm90dG9tSGFsZiA9IHdpbmRvd0hlaWdodCAtIHRvcEhhbGY7XG4gICAgICBsZXQgaGFsZlRvb2x0aXAgPSAodG9vbHRpcGNsaWVudC5oZWlnaHQgLyAyKTtcblxuICAgICAgbGV0IGlzQ29udGFpbmVyQmlnZ2VyID0gYnRuY2xpZW50LmhlaWdodCA+PSB0b29sdGlwY2xpZW50LmhlaWdodDtcblxuICAgICAgaWYgKGlzQ29udGFpbmVyQmlnZ2VyIHx8ICgodG9wSGFsZiA+IGhhbGZUb29sdGlwKSAmJiAoYm90dG9tSGFsZiA+IGhhbGZUb29sdGlwKSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJyaWdodFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgncmlnaHQnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0b3BIYWxmIDw9IGhhbGZUb29sdGlwKSB7XG4gICAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwicmlnaHQtYlwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgncmlnaHQtYicpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGJvdHRvbUhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJyaWdodC10XCIpKSB7XG4gICAgICAgICAgdG9vbHRpcC5jbGFzc0xpc3QuYWRkKCdyaWdodC10Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgIH0gZWxzZSBpZiAoc3BhY2VzLmdldFNwYWNlKFwidG9wXCIpKSB7XG5cbiAgICAgIGxldCBsZWZ0SGFsZiA9IChidG5jbGllbnQucmlnaHQgLSAoYnRuY2xpZW50LndpZHRoIC8gMikpO1xuICAgICAgbGV0IHJpZ2h0SGFsZiA9IHdpbmRvd1dpZHRoIC0gbGVmdEhhbGY7XG4gICAgICBsZXQgaGFsZlRvb2x0aXAgPSAodG9vbHRpcGNsaWVudC53aWR0aCAvIDIpO1xuXG4gICAgICBsZXQgaXNDb250YWluZXJCaWdnZXIgPSBidG5jbGllbnQud2lkdGggPj0gdG9vbHRpcGNsaWVudC53aWR0aDtcblxuICAgICAgaWYgKGlzQ29udGFpbmVyQmlnZ2VyIHx8ICgobGVmdEhhbGYgPiBoYWxmVG9vbHRpcCkgJiYgKHJpZ2h0SGFsZiA+IGhhbGZUb29sdGlwKSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJ0b3BcIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ3RvcCcpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGxlZnRIYWxmIDw9IGhhbGZUb29sdGlwKSB7XG4gICAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwidG9wLXJcIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ3RvcC1yJyk7XG4gICAgICAgIH1cblxuICAgICAgfSBlbHNlIGlmIChyaWdodEhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJ0b3AtbFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgndG9wLWwnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChzcGFjZXMuZ2V0U3BhY2UoXCJib3R0b21cIikpIHtcbiAgICAgIC8vIGRlYnVnZ2VyO1xuICAgICAgbGV0IGxlZnRIYWxmID0gKGJ0bmNsaWVudC5yaWdodCAtIChidG5jbGllbnQud2lkdGggLyAyKSk7XG4gICAgICBsZXQgcmlnaHRIYWxmID0gd2luZG93V2lkdGggLSBsZWZ0SGFsZjtcbiAgICAgIGxldCBoYWxmVG9vbHRpcCA9ICh0b29sdGlwY2xpZW50LndpZHRoIC8gMik7XG5cbiAgICAgIGxldCBpc0NvbnRhaW5lckJpZ2dlciA9IGJ0bmNsaWVudC53aWR0aCA+PSB0b29sdGlwY2xpZW50LndpZHRoO1xuXG5cblxuICAgICAgaWYgKGlzQ29udGFpbmVyQmlnZ2VyIHx8ICgobGVmdEhhbGYgPiBoYWxmVG9vbHRpcCkgJiYgKHJpZ2h0SGFsZiA+IGhhbGZUb29sdGlwKSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJib3R0b21cIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ2JvdHRvbScpO1xuICAgICAgICB9XG5cbiAgICAgIH0gZWxzZSBpZiAobGVmdEhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJib3R0b20tclwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnYm90dG9tLXInKTtcbiAgICAgICAgfVxuXG4gICAgICB9IGVsc2UgaWYgKHJpZ2h0SGFsZiA8PSBoYWxmVG9vbHRpcCkge1xuICAgICAgICBpZiAoIXRoaXMubWFuaXB1bGF0ZU92ZXJsYXlJZlByZXNlbnQoYnRuY2xpZW50LCB0b29sdGlwLCBcImJvdHRvbS1sXCIpKSB7XG4gICAgICAgICAgdG9vbHRpcC5jbGFzc0xpc3QuYWRkKCdib3R0b20tbCcpO1xuICAgICAgICB9XG4gICAgICB9XG5cblxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBkZWJ1Z2dlcjtcbiAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwiYm90dG9tXCIpKSB7XG4gICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnYm90dG9tJyk7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICByZW1vdmVUb29sdGlwQ2xhc3ModG9vbHRpcCkge1xuICAgIGxldCBjbGFzc0xpc3QgPSB0b29sdGlwLmNsYXNzTGlzdDtcbiAgICBjbGFzc0xpc3QuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIGlmICh0aGlzLmNsYXNzZXMuaW5jbHVkZXMoZWxlbWVudCkpIHtcbiAgICAgICAgY2xhc3NMaXN0LnJlbW92ZShlbGVtZW50KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGdldFN0YXlDbGFzcyh0b29sdGlwKSB7XG4gICAgdmFyIGNsYXNzTGlzdCA9IHRvb2x0aXAuY2xhc3NMaXN0O1xuICAgIGxldCBzdGF5UG9zaXRpb247XG4gICAgY2xhc3NMaXN0LmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICBpZiAoZWxlbWVudC5pbmNsdWRlcyhgc3RheS1gKSkge1xuICAgICAgICBzdGF5UG9zaXRpb24gPSBlbGVtZW50LnNwbGl0KFwiLVwiKVsxXTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBzdGF5UG9zaXRpb247XG4gIH1cblxuXG4gIG1vdXNlTGVmdChlbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7XG4gICAvLyBjb25zb2xlLmxvZyhcIm1vdXNlTGVmdFwiKTtcbiAgICBsZXQgYnRuID0gZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGlmICghYnRuKSByZXR1cm47XG5cbiAgICBsZXQgdG9vbHRpcCA9IGJ0bi5xdWVyeVNlbGVjdG9yKFwiLnNtYXJ0LXRvb2x0aXBcIik7XG5cbiAgICBpZiAoIXRvb2x0aXApIHJldHVybjtcblxuXG4gICAgdmFyIHN0aWNreVRpbWUgPSB0aGlzLmdldFN0aWNreVRpbWUodG9vbHRpcCk7XG5cbiAgICBcblxuICAgIGlmICghaXNOYU4oc3RpY2t5VGltZSkpIHtcbiAgICAgIHRoaXMubW91c2VMZWZ0VGltZU91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuXG4gICAgICAgIGlmICh0b29sdGlwLmNsYXNzTGlzdC5jb250YWlucyhcImhvdmVyZWRcIikpXG4gICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmICh0aGlzLnJlbW92ZU92ZXJsYXlDbGFzcyh0b29sdGlwKSkge1xuXG4gICAgICAgICAgbGV0IHRvb2x0aXBSZWN0ID0gdG9vbHRpcC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXG4gICAgICAgICAgLy9SZXNldCBJbmxpbmUgU3R5bGVzXG4gICAgICAgICAgdG9vbHRpcC5zdHlsZS5wb3NpdGlvbiA9IFwiXCI7XG4gICAgICAgICAgdG9vbHRpcC5zdHlsZS50b3AgPSBcIlwiO1xuICAgICAgICAgIHRvb2x0aXAuc3R5bGUubGVmdCA9IFwiXCI7XG4gICAgICAgICAgdG9vbHRpcC5zdHlsZS5ib3R0b20gPSBcIlwiO1xuICAgICAgICAgIHRvb2x0aXAuc3R5bGUucmlnaHQgPSBcIlwiO1xuXG5cblxuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZChcIm92ZXJsYXlcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvL01ha2Ugc3VyZSBpdHMgbm90IHZpc2libGUgYWZ0ZXIgbW91c2UgaGFzIGxlZnRcbiAgICAgICAgdG9vbHRpcC5zdHlsZS52aXNpYmlsaXR5ID0gXCJjb2xsYXBzZVwiXG4gICAgICAgIHRvb2x0aXAuc3R5bGUub3BhY2l0eSA9IFwiMFwiO1xuICAgICAgICB0b29sdGlwLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcblxuICAgICAgfSwgc3RpY2t5VGltZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRvb2x0aXAuZm9jdXMoKTtcbiAgICB9XG5cblxuICB9XG5cbiAgcmVtb3ZlT3ZlcmxheUNsYXNzKHRvb2x0aXApIHtcbiAgICBsZXQgaGFzT3ZlcmxheSA9IGZhbHNlXG5cbiAgICBpZiAodG9vbHRpcC5jbGFzc0xpc3QuY29udGFpbnMoXCJvdmVybGF5ZWRcIikpIHtcbiAgICAgIGhhc092ZXJsYXkgPSB0cnVlO1xuICAgICAgdG9vbHRpcC5jbGFzc0xpc3QucmVtb3ZlKFwib3ZlcmxheWVkXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBoYXNPdmVybGF5O1xuICB9XG5cbiAgcmVtb3ZlT3ZlcmxheU1hcmtDbGFzcyh0b29sdGlwKSB7XG4gICAgbGV0IGhhc092ZXJsYXkgPSBmYWxzZVxuXG4gICAgaWYgKHRvb2x0aXAuY2xhc3NMaXN0LmNvbnRhaW5zKFwib3ZlcmxheVwiKSkge1xuICAgICAgaGFzT3ZlcmxheSA9IHRydWU7XG4gICAgICB0b29sdGlwLmNsYXNzTGlzdC5yZW1vdmUoXCJvdmVybGF5XCIpO1xuICAgIH1cblxuICAgIHJldHVybiBoYXNPdmVybGF5O1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIHRvb2x0aXAgYmFzZWQgb24gdGhlIGZpeGVkIHBvc2l0aW9uIG9mIHRoZSBjb250YWluZXJcbiAgICogQHBhcmFtIHtET01DbGllbnRSZWN0fSBidG5jbGllbnQgVGhlIFJlY3RhbmdsZSB0aGF0IGRlZmluZXMgdGhlIGJ1dHRvbiBlbGVtZW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0b29sdGlwUG9zdGlvbiBUaGUgcG9zaXRpb24gdGhlIHRvb2x0aXAgc2hvdWxkIGJlIGRpc3BsYXllZFxuICAgKi9cbiAgZ2V0T3ZlcmxheUNvb3JkaW5hdGVzKGJ0bmNsaWVudCwgdG9vbHRpcGNsaWVudCwgdG9vbHRpcFBvc3Rpb24pIHtcbiAgICAvLyBsZXQgYm9keTphbnkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiYm9keVwiKTtcbiAgICAvLyBsZXQgYm9keWNsaWVudCA9IGJvZHkuZ2V0Q2xpZW50UmVjdHMoKVswXTtcblxuICAgIGxldCB3aW5kb3dXaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoO1xuICAgIGxldCB3aW5kb3dIZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cbiAgICBpZiAodG9vbHRpcFBvc3Rpb24uaW5jbHVkZXMoXCJyaWdodFwiKSkge1xuXG4gICAgICBsZXQgb3ZlcmxheUNvb3JkaW5hdGVzOiBhbnkgPSB7XG4gICAgICAgIGxlZnQ6IGJ0bmNsaWVudC5yaWdodCArIHRoaXMub2ZmU2V0VmFsdWUsXG4gICAgICAgIHRvcDogKGJ0bmNsaWVudC50b3AgKyAoYnRuY2xpZW50LmhlaWdodCAvIDIpKSAtICh0b29sdGlwY2xpZW50LmhlaWdodCAvIDIpLFxuICAgICAgICBwcm9wczogW1wibGVmdFwiLCBcInRvcFwiXVxuICAgICAgfVxuXG4gICAgICBpZiAodG9vbHRpcFBvc3Rpb24gPT0gXCJyaWdodC10XC