ng-devui
Version:
DevUI components based on Angular
261 lines • 51.4 kB
JavaScript
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { I18nService } from 'ng-devui/i18n';
import { fromEvent } from 'rxjs';
import { GanttScaleUnit } from '../gantt.model';
import { GanttService } from '../gantt.service';
import * as i0 from "@angular/core";
import * as i1 from "../gantt.service";
import * as i2 from "ng-devui/i18n";
import * as i3 from "@angular/common";
import * as i4 from "../gantt-marker.directive";
export class GanttScaleComponent {
constructor(ganttService, i18n) {
this.ganttService = ganttService;
this.i18n = i18n;
this.viewScaleRange = [0, 0];
this.viewSCaleData = [];
this.SCALE_START_LABLE_OFFSET = 7;
this.scaleWidth = {
day: 40,
week: 30,
month: 20,
};
this.unit = GanttScaleUnit.day;
this.showDaySplitLine = false;
this.addMilestoneEvent = new EventEmitter();
}
ngOnInit() {
this.i18nText = this.i18n.getI18nText().gantt;
this.i18nCommonText = this.i18n.getI18nText().common;
this.i18nLocale = this.i18n.getI18nText().locale;
this.i18nSubscription = this.i18n.langChange().subscribe((data) => {
this.i18nText = data.gantt;
this.i18nCommonText = data.common;
this.i18nLocale = data.locale;
});
this.ganttBarStatusHandler = this.ganttService.ganttBarStatusChange.subscribe((status) => {
this.ganttBarStatusChange(status);
});
this.ganttSacleConfigHandler = this.ganttService.ganttScaleConfigChange.subscribe((config) => {
if (config.startDate) {
this.startDate = config.startDate;
}
if (config.endDate) {
this.endDate = config.endDate;
}
if (config.startDate || config.endDate) {
this.scaleData = this.generateScaleData(this.startDate, this.endDate);
this.getViewScaleData();
}
if (config.unit) {
if (this.unit === GanttScaleUnit.day && (config.unit === GanttScaleUnit.month || config.unit === GanttScaleUnit.week)) {
this.clearDaySplitLine();
}
this.unit = config.unit;
this.getViewScaleData();
}
if (config.viewChange) {
this.getViewScaleData();
}
});
}
ngOnChanges(changes) {
if (Object.prototype.hasOwnProperty.call(changes, 'scrollElement')) {
this.registerScrollEvent();
}
}
registerScrollEvent() {
if (!this.scrollHandler && this.scrollElement) {
this.scrollHandler = fromEvent(this.scrollElement, 'scroll').subscribe(e => {
this.getViewScaleData();
});
}
}
getViewScaleData() {
if (this.scrollElement) {
const containerWidth = this.scrollElement.clientWidth;
const scrollLeft = this.scrollElement.scrollLeft;
const start = Math.floor(scrollLeft / this.scaleWidth[this.unit]);
const offset = Math.ceil(containerWidth / this.scaleWidth[this.unit]);
this.viewScaleRange = [start - 2, start + offset + 2];
this.viewSCaleData = this.scaleData.filter((i) => {
return i.index >= this.viewScaleRange[0] && i.index <= this.viewScaleRange[1];
});
}
}
generateScaleData(startDate, endDate) {
if (startDate && endDate) {
const scaleData = [];
let handleDate = startDate;
let index = 0;
while (!this.ganttService.isSomeDate(handleDate, endDate)) {
const dateInfo = this.generateDateInfo(handleDate, index);
scaleData.push(dateInfo);
handleDate = this.getNextDay(new Date(handleDate));
index++;
}
return scaleData;
}
}
getNextDay(date) {
const nextDayDate = date.setDate(date.getDate() + 1);
return new Date(nextDayDate);
}
generateDateInfo(date, index) {
const dateInfo = {
dayOfMonthLabel: '',
dayOfWeekLabel: '',
monthLabel: '',
yearLabel: '',
date: date,
monthStart: false,
weekend: false,
today: false,
milestone: '',
highlightStart: false,
scaleStartVisable: true,
index
};
const dayOfMonth = date.getDate();
dateInfo.dayOfMonthLabel = String(dayOfMonth);
if (dayOfMonth === 1) {
dateInfo.monthStart = true;
}
const dayOfWeek = date.getDay();
dateInfo.dayOfWeekLabel = String(dayOfWeek);
if (dayOfWeek === 6) {
dateInfo.weekend = true;
}
const month = date.getMonth() + 1;
dateInfo.monthLabel = String(month);
const year = date.getFullYear();
dateInfo.yearLabel = String(year);
if (this.ganttService.isSomeDate(date, new Date())) {
dateInfo.today = true;
}
if (new Date(year, month - 1, dayOfMonth + this.SCALE_START_LABLE_OFFSET).getMonth() > month - 1) {
dateInfo.scaleStartVisable = false;
}
if (this.milestoneList) {
this.milestoneList.forEach((milestone) => {
if (milestone.date) {
if (this.ganttService.isSomeDate(milestone.date, dateInfo.date)) {
dateInfo.milestone = milestone.lable;
}
}
});
}
return dateInfo;
}
trackByFn(index, item) {
return index;
}
ganttBarStatusChange(status) {
this.highlight = status.focused;
if (this.highlight) {
this.scaleData.forEach((dateInfo, index) => {
if (dateInfo.date >= status.startDate && dateInfo.date <= status.endDate) {
dateInfo.highlight = true;
}
else {
dateInfo.highlight = false;
}
dateInfo.highlightStart = false;
});
const highlightBarStartIndex = this.scaleData.findIndex((data) => {
return data.highlight;
});
if (highlightBarStartIndex > -1) {
this.scaleData[highlightBarStartIndex].highlightStart = true;
}
const highlightData = this.scaleData.filter((data) => {
return data.highlight;
});
if (highlightData.length === 0) {
return;
}
if (highlightData.length === 1) {
const startData = highlightData[0];
this.highlightStartText =
this.prefixZero(parseInt(startData.monthLabel, 10)) + '-' + this.prefixZero(parseInt(startData.dayOfMonthLabel, 10));
const highlightWidth = this.ganttService.getScaleUnitPixel();
if (highlightWidth < 40) {
this.highlightMinWidth = 40;
}
else {
this.highlightMinWidth = highlightWidth;
}
}
else {
const startData = highlightData[0];
const endData = highlightData[highlightData.length - 1];
this.highlightStartText =
this.prefixZero(parseInt(startData.monthLabel, 10)) + '-' + this.prefixZero(parseInt(startData.dayOfMonthLabel, 10));
this.highlightEndText =
this.prefixZero(parseInt(endData.monthLabel, 10)) + '-' + this.prefixZero(parseInt(endData.dayOfMonthLabel, 10));
const highlightWidth = highlightData.length * this.ganttService.getScaleUnitPixel();
if (highlightWidth < 84) {
this.highlightMinWidth = 84;
}
else {
this.highlightMinWidth = highlightWidth;
}
}
}
}
prefixZero(num) {
return (Array(2).join('0') + num).slice(-2);
}
addMilestone(info) {
this.addMilestoneEvent.emit(info);
}
clearDaySplitLine() {
if (this.showDaySplitLine && this.ganttBarContainerElement) {
const dayLines = this.ganttBarContainerElement.querySelectorAll('.devui-day-split-line');
dayLines.forEach(item => {
const parent = item.parentElement;
parent.removeChild(item);
});
}
}
ngOnDestroy() {
if (this.ganttBarStatusHandler) {
this.ganttBarStatusHandler.unsubscribe();
this.ganttBarStatusHandler = null;
}
if (this.ganttSacleConfigHandler) {
this.ganttSacleConfigHandler.unsubscribe();
this.ganttSacleConfigHandler = null;
}
if (this.scrollHandler) {
this.scrollHandler.unsubscribe();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GanttScaleComponent, deps: [{ token: i1.GanttService }, { token: i2.I18nService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GanttScaleComponent, selector: "d-gantt-scale", inputs: { unit: "unit", height: "height", startDate: "startDate", endDate: "endDate", ganttBarContainerElement: "ganttBarContainerElement", ganttScaleContainerOffsetLeft: "ganttScaleContainerOffsetLeft", milestoneList: "milestoneList", scrollElement: "scrollElement", showDaySplitLine: "showDaySplitLine" }, outputs: { addMilestoneEvent: "addMilestoneEvent" }, usesOnChanges: true, ngImport: i0, template: "<div\n class=\"devui-gantt-scale {{ unit }}\"\n *ngFor=\"let data of viewSCaleData; trackBy: trackByFn; let first = first; let last = last\"\n [ngClass]=\"{ today: data.today, milestone: data.milestone }\"\n [style.left]=\"scaleWidth[unit] * data.index + 'px'\"\n [style.width]=\"scaleWidth[unit] + 'px'\"\n dGanttMarker\n [monthMark]=\"data.monthStart\"\n [weekend]=\"data.weekend\"\n [milestone]=\"data.milestone\"\n [today]=\"data.today\"\n [index]=\"data.index\"\n [showDaySplitLine]=\"showDaySplitLine\"\n [date]=\"data.date\"\n [unit]=\"unit\"\n [last]=\"last\"\n [ganttScaleContainerOffsetLeft]=\"ganttScaleContainerOffsetLeft\"\n [ganttBarContainerElement]=\"ganttBarContainerElement\"\n>\n <div class=\"devui-scale-start\" [ngClass]=\"{ milestone: data.milestone }\" [title]=\"data.milestone || ''\">\n <ng-container *ngIf=\"data.milestone && unit === 'day'\">\n {{ data.milestone }}\n </ng-container>\n <ng-container *ngIf=\"!data.milestone || unit !== 'day'\">\n {{\n data.scaleStartVisable && (first || data.monthStart)\n ? unit === 'month'\n ? i18nText?.yearDisplay(data.yearLabel)\n : i18nText?.yearAndMonthDisplay(data.yearLabel, data.monthLabel)\n : ''\n }}\n </ng-container>\n </div>\n <div class=\"devui-scale-unit\">\n <div *ngIf=\"highlight && data.highlightStart\" class=\"scale-highlight\" [style.minWidth]=\"highlightMinWidth + 'px'\">\n <div style=\"float: left\">{{ highlightStartText }}</div>\n <div style=\"float: right\">{{ highlightEndText }}</div>\n <div style=\"clear: both\"></div>\n </div>\n <ng-container *ngIf=\"!highlight || !data.highlight\">\n <div *ngIf=\"unit === 'day'\" class=\"border-left\" [ngClass]=\"{ today: data.today }\">\n {{ data.today ? i18nText?.today : data.dayOfMonthLabel }}\n </div>\n <div *ngIf=\"unit === 'week'\" [ngClass]=\"{ 'border-left': first || data.weekend }\">\n {{ first || data.weekend ? data.dayOfMonthLabel : '' }}\n </div>\n <div *ngIf=\"unit === 'month'\" [ngClass]=\"{ 'border-left': first || data.monthStart }\">\n {{ first || data.monthStart ? i18nText?.monthDisplay(data.monthLabel) : '' }}\n </div>\n </ng-container>\n </div>\n <div class=\"milestone-new {{ unit }}\" [title]=\"i18nText?.milestone\" (click)=\"addMilestone(data)\">\n <div class=\"icon-add\"></div>\n </div>\n</div>\n", styles: [".devui-font-size-base{font-size:var(--devui-font-size, 12px)}.devui-font-base{font-size:var(--devui-font-size, 12px);font-weight:var(--devui-font-content-weight, normal);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-modal-title{font-size:var(--devui-font-size-modal-title, 18px)}.devui-font-modal-title{font-size:var(--devui-font-size-modal-title, 18px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-page-title{font-size:var(--devui-font-size-page-title, 16px)}.devui-font-page-title{font-size:var(--devui-font-size-page-title, 16px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-secondary-title{font-size:var(--devui-font-size-card-title, 14px)}.devui-font-secondary-title{font-size:var(--devui-font-size-card-title, 14px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}:host{display:block;height:36px;line-height:18px}.devui-gantt-scale{display:inline-block;color:var(--devui-placeholder, #808080);text-align:center;position:absolute;height:36px;font-weight:400}.devui-gantt-scale.day:not(.milestone):hover .devui-scale-start{display:none}.devui-gantt-scale.day.milestone{background-image:linear-gradient(180deg,#fecc5500,#3ecca61a)}.devui-gantt-scale .devui-scale-start{width:100%;height:18px;position:absolute;left:1px;white-space:nowrap}.devui-gantt-scale .devui-scale-start.milestone{color:var(--devui-success, #058358)}.devui-gantt-scale .devui-scale-unit{height:18px;position:absolute;top:18px;width:100%}.devui-gantt-scale .devui-scale-unit .border-left{height:18px;border-left:1px solid var(--devui-list-item-selected-bg, #cedefd)}.devui-gantt-scale .devui-scale-unit .scale-highlight{position:absolute;height:18px;border-radius:var(--devui-border-radius, 2px);background-color:var(--devui-brand, #0a59f7);padding:0 4px}.devui-gantt-scale .devui-scale-unit .scale-highlight div{color:var(--devui-base-bg, #ffffff);font-size:var(--devui-font-size, 12px);font-weight:400}.devui-gantt-scale .devui-scale-unit .today{background:#ff790e33;border-radius:var(--devui-border-radius, 2px);height:16px}.devui-gantt-scale .milestone-new{display:none;position:absolute;width:18px;height:18px;margin-left:16px;border:1px solid var(--devui-list-item-selected-bg, #cedefd);cursor:pointer}.devui-gantt-scale .milestone-new div{line-height:16px}.devui-gantt-scale:not(.milestone):hover .milestone-new.day{display:block}.devui-day-split-line{position:absolute;top:0;bottom:0;width:1px;z-index:1;background:var(--devui-area, #f3f3f3);opacity:1}.devui-mark-line{position:absolute;top:0;bottom:0;width:2px;z-index:1;background:var(--devui-line, #dbdbdb);opacity:.5}.devui-mark-line.today{opacity:.2;background:#ff790e}.devui-mark-line.today.day{width:40px}.devui-mark-line.today.week{margin-left:9px}.devui-mark-line.today.month{margin-left:4px}.devui-mark-line.milestone{opacity:.2;background:var(--devui-success, #058358)}.devui-mark-line.milestone.day{margin-left:24px}.devui-mark-line.milestone.week{margin-left:9px}.devui-mark-line.milestone.month{margin-left:4px}.devui-mark-stripe{position:absolute;top:0;bottom:0;z-index:1;background:var(--devui-area, #f3f3f3);background-size:6px 6px}.devui-mark-stripe.day{width:80px}.devui-mark-stripe.week{width:40px}.devui-mark-stripe.month{width:20px}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.GanttMarkerDirective, selector: "[dGanttMarker]", inputs: ["ganttBarContainerElement", "ganttScaleContainerOffsetLeft", "monthMark", "weekend", "today", "index", "milestone", "unit", "date", "last", "showDaySplitLine"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GanttScaleComponent, decorators: [{
type: Component,
args: [{ selector: 'd-gantt-scale', template: "<div\n class=\"devui-gantt-scale {{ unit }}\"\n *ngFor=\"let data of viewSCaleData; trackBy: trackByFn; let first = first; let last = last\"\n [ngClass]=\"{ today: data.today, milestone: data.milestone }\"\n [style.left]=\"scaleWidth[unit] * data.index + 'px'\"\n [style.width]=\"scaleWidth[unit] + 'px'\"\n dGanttMarker\n [monthMark]=\"data.monthStart\"\n [weekend]=\"data.weekend\"\n [milestone]=\"data.milestone\"\n [today]=\"data.today\"\n [index]=\"data.index\"\n [showDaySplitLine]=\"showDaySplitLine\"\n [date]=\"data.date\"\n [unit]=\"unit\"\n [last]=\"last\"\n [ganttScaleContainerOffsetLeft]=\"ganttScaleContainerOffsetLeft\"\n [ganttBarContainerElement]=\"ganttBarContainerElement\"\n>\n <div class=\"devui-scale-start\" [ngClass]=\"{ milestone: data.milestone }\" [title]=\"data.milestone || ''\">\n <ng-container *ngIf=\"data.milestone && unit === 'day'\">\n {{ data.milestone }}\n </ng-container>\n <ng-container *ngIf=\"!data.milestone || unit !== 'day'\">\n {{\n data.scaleStartVisable && (first || data.monthStart)\n ? unit === 'month'\n ? i18nText?.yearDisplay(data.yearLabel)\n : i18nText?.yearAndMonthDisplay(data.yearLabel, data.monthLabel)\n : ''\n }}\n </ng-container>\n </div>\n <div class=\"devui-scale-unit\">\n <div *ngIf=\"highlight && data.highlightStart\" class=\"scale-highlight\" [style.minWidth]=\"highlightMinWidth + 'px'\">\n <div style=\"float: left\">{{ highlightStartText }}</div>\n <div style=\"float: right\">{{ highlightEndText }}</div>\n <div style=\"clear: both\"></div>\n </div>\n <ng-container *ngIf=\"!highlight || !data.highlight\">\n <div *ngIf=\"unit === 'day'\" class=\"border-left\" [ngClass]=\"{ today: data.today }\">\n {{ data.today ? i18nText?.today : data.dayOfMonthLabel }}\n </div>\n <div *ngIf=\"unit === 'week'\" [ngClass]=\"{ 'border-left': first || data.weekend }\">\n {{ first || data.weekend ? data.dayOfMonthLabel : '' }}\n </div>\n <div *ngIf=\"unit === 'month'\" [ngClass]=\"{ 'border-left': first || data.monthStart }\">\n {{ first || data.monthStart ? i18nText?.monthDisplay(data.monthLabel) : '' }}\n </div>\n </ng-container>\n </div>\n <div class=\"milestone-new {{ unit }}\" [title]=\"i18nText?.milestone\" (click)=\"addMilestone(data)\">\n <div class=\"icon-add\"></div>\n </div>\n</div>\n", styles: [".devui-font-size-base{font-size:var(--devui-font-size, 12px)}.devui-font-base{font-size:var(--devui-font-size, 12px);font-weight:var(--devui-font-content-weight, normal);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-modal-title{font-size:var(--devui-font-size-modal-title, 18px)}.devui-font-modal-title{font-size:var(--devui-font-size-modal-title, 18px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-page-title{font-size:var(--devui-font-size-page-title, 16px)}.devui-font-page-title{font-size:var(--devui-font-size-page-title, 16px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-secondary-title{font-size:var(--devui-font-size-card-title, 14px)}.devui-font-secondary-title{font-size:var(--devui-font-size-card-title, 14px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}:host{display:block;height:36px;line-height:18px}.devui-gantt-scale{display:inline-block;color:var(--devui-placeholder, #808080);text-align:center;position:absolute;height:36px;font-weight:400}.devui-gantt-scale.day:not(.milestone):hover .devui-scale-start{display:none}.devui-gantt-scale.day.milestone{background-image:linear-gradient(180deg,#fecc5500,#3ecca61a)}.devui-gantt-scale .devui-scale-start{width:100%;height:18px;position:absolute;left:1px;white-space:nowrap}.devui-gantt-scale .devui-scale-start.milestone{color:var(--devui-success, #058358)}.devui-gantt-scale .devui-scale-unit{height:18px;position:absolute;top:18px;width:100%}.devui-gantt-scale .devui-scale-unit .border-left{height:18px;border-left:1px solid var(--devui-list-item-selected-bg, #cedefd)}.devui-gantt-scale .devui-scale-unit .scale-highlight{position:absolute;height:18px;border-radius:var(--devui-border-radius, 2px);background-color:var(--devui-brand, #0a59f7);padding:0 4px}.devui-gantt-scale .devui-scale-unit .scale-highlight div{color:var(--devui-base-bg, #ffffff);font-size:var(--devui-font-size, 12px);font-weight:400}.devui-gantt-scale .devui-scale-unit .today{background:#ff790e33;border-radius:var(--devui-border-radius, 2px);height:16px}.devui-gantt-scale .milestone-new{display:none;position:absolute;width:18px;height:18px;margin-left:16px;border:1px solid var(--devui-list-item-selected-bg, #cedefd);cursor:pointer}.devui-gantt-scale .milestone-new div{line-height:16px}.devui-gantt-scale:not(.milestone):hover .milestone-new.day{display:block}.devui-day-split-line{position:absolute;top:0;bottom:0;width:1px;z-index:1;background:var(--devui-area, #f3f3f3);opacity:1}.devui-mark-line{position:absolute;top:0;bottom:0;width:2px;z-index:1;background:var(--devui-line, #dbdbdb);opacity:.5}.devui-mark-line.today{opacity:.2;background:#ff790e}.devui-mark-line.today.day{width:40px}.devui-mark-line.today.week{margin-left:9px}.devui-mark-line.today.month{margin-left:4px}.devui-mark-line.milestone{opacity:.2;background:var(--devui-success, #058358)}.devui-mark-line.milestone.day{margin-left:24px}.devui-mark-line.milestone.week{margin-left:9px}.devui-mark-line.milestone.month{margin-left:4px}.devui-mark-stripe{position:absolute;top:0;bottom:0;z-index:1;background:var(--devui-area, #f3f3f3);background-size:6px 6px}.devui-mark-stripe.day{width:80px}.devui-mark-stripe.week{width:40px}.devui-mark-stripe.month{width:20px}\n"] }]
}], ctorParameters: () => [{ type: i1.GanttService }, { type: i2.I18nService }], propDecorators: { unit: [{
type: Input
}], height: [{
type: Input
}], startDate: [{
type: Input
}], endDate: [{
type: Input
}], ganttBarContainerElement: [{
type: Input
}], ganttScaleContainerOffsetLeft: [{
type: Input
}], milestoneList: [{
type: Input
}], scrollElement: [{
type: Input
}], showDaySplitLine: [{
type: Input
}], addMilestoneEvent: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FudHQtc2NhbGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vZGV2dWkvZ2FudHQvZ2FudHQtc2NhbGUvZ2FudHQtc2NhbGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vZGV2dWkvZ2FudHQvZ2FudHQtc2NhbGUvZ2FudHQtc2NhbGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFBRSxZQUFZLEVBQ3ZCLEtBQUssRUFJTCxNQUFNLEVBRVAsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFpQixXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0QsT0FBTyxFQUFFLFNBQVMsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDL0MsT0FBTyxFQUFzRCxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7Ozs7OztBQU1oRCxNQUFNLE9BQU8sbUJBQW1CO0lBbUM5QixZQUFvQixZQUEwQixFQUFVLElBQWlCO1FBQXJELGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBYTtRQWpDekUsbUJBQWMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN4QixrQkFBYSxHQUF5QixFQUFFLENBQUM7UUFRekMsNkJBQXdCLEdBQUcsQ0FBQyxDQUFDO1FBRTdCLGVBQVUsR0FBRztZQUNYLEdBQUcsRUFBRSxFQUFFO1lBQ1AsSUFBSSxFQUFFLEVBQUU7WUFDUixLQUFLLEVBQUUsRUFBRTtTQUNWLENBQUM7UUFDTyxTQUFJLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQztRQVExQixxQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFDeEIsc0JBQWlCLEdBQUcsSUFBSSxZQUFZLEVBQXNCLENBQUM7SUFRUSxDQUFDO0lBRTlFLFFBQVE7UUFDTixJQUFJ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eEIsS0FBSztnQkFDSSxpQkFBaUI7c0JBQTFCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLFxyXG4gIElucHV0LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBPbkRlc3Ryb3ksXHJcbiAgT25Jbml0LFxyXG4gIE91dHB1dCxcclxuICBTaW1wbGVDaGFuZ2VzXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEkxOG5JbnRlcmZhY2UsIEkxOG5TZXJ2aWNlIH0gZnJvbSAnbmctZGV2dWkvaTE4bic7XHJcbmltcG9ydCB7IGZyb21FdmVudCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IEdhbnR0QmFyU3RhdHVzLCBHYW50dE1pbGVzdG9uZSwgR2FudHRTY2FsZURhdGVJbmZvLCBHYW50dFNjYWxlVW5pdCB9IGZyb20gJy4uL2dhbnR0Lm1vZGVsJztcclxuaW1wb3J0IHsgR2FudHRTZXJ2aWNlIH0gZnJvbSAnLi4vZ2FudHQuc2VydmljZSc7XHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZC1nYW50dC1zY2FsZScsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2dhbnR0LXNjYWxlLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9nYW50dC1zY2FsZS5jb21wb25lbnQuc2NzcyddLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgR2FudHRTY2FsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xyXG4gIHNjYWxlRGF0YTogR2FudHRTY2FsZURhdGVJbmZvW107XHJcbiAgdmlld1NjYWxlUmFuZ2UgPSBbMCwgMF07XHJcbiAgdmlld1NDYWxlRGF0YTogR2FudHRTY2FsZURhdGVJbmZvW10gPSBbXTtcclxuICBnYW50dEJhclN0YXR1c0hhbmRsZXI6IFN1YnNjcmlwdGlvbjtcclxuICBnYW50dFNhY2xlQ29uZmlnSGFuZGxlcjogU3Vic2NyaXB0aW9uO1xyXG4gIGhpZ2hsaWdodDogYm9vbGVhbjtcclxuICBoaWdobGlnaHRTdGFydFRleHQ6IHN0cmluZztcclxuICBoaWdobGlnaHRFbmRUZXh0OiBzdHJpbmc7XHJcbiAgaGlnaGxpZ2h0TWluV2lkdGg6IG51bWJlcjtcclxuXHJcbiAgU0NBTEVfU1RBUlRfTEFCTEVfT0ZGU0VUID0gNztcclxuXHJcbiAgc2NhbGVXaWR0aCA9IHtcclxuICAgIGRheTogNDAsXHJcbiAgICB3ZWVrOiAzMCxcclxuICAgIG1vbnRoOiAyMCxcclxuICB9O1xyXG4gIEBJbnB1dCgpIHVuaXQgPSBHYW50dFNjYWxlVW5pdC5kYXk7XHJcbiAgQElucHV0KCkgaGVpZ2h0OiBudW1iZXI7XHJcbiAgQElucHV0KCkgc3RhcnREYXRlOiBEYXRlO1xyXG4gIEBJbnB1dCgpIGVuZERhdGU6IERhdGU7XHJcbiAgQElucHV0KCkgZ2FudHRCYXJDb250YWluZXJFbGVtZW50OiBIVE1MRWxlbWVudDtcclxuICBASW5wdXQoKSBnYW50dFNjYWxlQ29udGFpbmVyT2Zmc2V0TGVmdDogbnVtYmVyO1xyXG4gIEBJbnB1dCgpIG1pbGVzdG9uZUxpc3Q6IEdhbnR0TWlsZXN0b25lW107XHJcbiAgQElucHV0KCkgc2Nyb2xsRWxlbWVudDogSFRNTEVsZW1lbnQ7XHJcbiAgQElucHV0KCkgc2hvd0RheVNwbGl0TGluZSA9IGZhbHNlO1xyXG4gIEBPdXRwdXQoKSBhZGRNaWxlc3RvbmVFdmVudCA9IG5ldyBFdmVudEVtaXR0ZXI8R2FudHRTY2FsZURhdGVJbmZvPigpO1xyXG5cclxuICBwcml2YXRlIHNjcm9sbEhhbmRsZXI6IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgaTE4blRleHQ6IEkxOG5JbnRlcmZhY2VbJ2dhbnR0J107XHJcbiAgaTE4bkxvY2FsZTogSTE4bkludGVyZmFjZVsnbG9jYWxlJ107XHJcbiAgaTE4bkNvbW1vblRleHQ6IEkxOG5JbnRlcmZhY2VbJ2NvbW1vbiddO1xyXG4gIGkxOG5TdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGdhbnR0U2VydmljZTogR2FudHRTZXJ2aWNlLCBwcml2YXRlIGkxOG46IEkxOG5TZXJ2aWNlKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLmkxOG5UZXh0ID0gdGhpcy5pMThuLmdldEkxOG5UZXh0KCkuZ2FudHQ7XHJcbiAgICB0aGlzLmkxOG5Db21tb25UZXh0ID0gdGhpcy5pMThuLmdldEkxOG5UZXh0KCkuY29tbW9uO1xyXG4gICAgdGhpcy5pMThuTG9jYWxlID0gdGhpcy5pMThuLmdldEkxOG5UZXh0KCkubG9jYWxlO1xyXG4gICAgdGhpcy5pMThuU3Vic2NyaXB0aW9uID0gdGhpcy5pMThuLmxhbmdDaGFuZ2UoKS5zdWJzY3JpYmUoKGRhdGEpID0+IHtcclxuICAgICAgdGhpcy5pMThuVGV4dCA9IGRhdGEuZ2FudHQ7XHJcbiAgICAgIHRoaXMuaTE4bkNvbW1vblRleHQgPSBkYXRhLmNvbW1vbjtcclxuICAgICAgdGhpcy5pMThuTG9jYWxlID0gZGF0YS5sb2NhbGU7XHJcbiAgICB9KTtcclxuICAgIHRoaXMuZ2FudHRCYXJTdGF0dXNIYW5kbGVyID0gdGhpcy5nYW50dFNlcnZpY2UuZ2FudHRCYXJTdGF0dXNDaGFuZ2Uuc3Vic2NyaWJlKChzdGF0dXMpID0+IHtcclxuICAgICAgdGhpcy5nYW50dEJhclN0YXR1c0NoYW5nZShzdGF0dXMpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5nYW50dFNhY2xlQ29uZmlnSGFuZGxlciA9IHRoaXMuZ2FudHRTZXJ2aWNlLmdhbnR0U2NhbGVDb25maWdDaGFuZ2Uuc3Vic2NyaWJlKChjb25maWcpID0+IHtcclxuICAgICAgaWYgKGNvbmZpZy5zdGFydERhdGUpIHtcclxuICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IGNvbmZpZy5zdGFydERhdGU7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGNvbmZpZy5lbmREYXRlKSB7XHJcbiAgICAgICAgdGhpcy5lbmREYXRlID0gY29uZmlnLmVuZERhdGU7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGNvbmZpZy5zdGFydERhdGUgfHwgY29uZmlnLmVuZERhdGUpIHtcclxuICAgICAgICB0aGlzLnNjYWxlRGF0YSA9IHRoaXMuZ2VuZXJhdGVTY2FsZURhdGEodGhpcy5zdGFydERhdGUsIHRoaXMuZW5kRGF0ZSk7XHJcbiAgICAgICAgdGhpcy5nZXRWaWV3U2NhbGVEYXRhKCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGNvbmZpZy51bml0KSB7XHJcbiAgICAgICAgaWYodGhpcy51bml0ID09PSBHYW50dFNjYWxlVW5pdC5kYXkgJiYgKGNvbmZpZy51bml0ID09PSBHYW50dFNjYWxlVW5pdC5tb250aCB8fCBjb25maWcudW5pdCA9PT0gR2FudHRTY2FsZVVuaXQud2VlaykpIHtcclxuICAgICAgICAgIHRoaXMuY2xlYXJEYXlTcGxpdExpbmUoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy51bml0ID0gY29uZmlnLnVuaXQ7XHJcbiAgICAgICAgdGhpcy5nZXRWaWV3U2NhbGVEYXRhKCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGNvbmZpZy52aWV3Q2hhbmdlKXtcclxuICAgICAgICB0aGlzLmdldFZpZXdTY2FsZURhdGEoKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGNoYW5nZXMsICdzY3JvbGxFbGVtZW50JykpIHtcclxuICAgICAgdGhpcy5yZWdpc3RlclNjcm9sbEV2ZW50KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZWdpc3RlclNjcm9sbEV2ZW50ICgpIHtcclxuICAgIGlmICghdGhpcy5zY3JvbGxIYW5kbGVyICYmIHRoaXMuc2Nyb2xsRWxlbWVudCkge1xyXG4gICAgICB0aGlzLnNjcm9sbEhhbmRsZXIgPSBmcm9tRXZlbnQodGhpcy5zY3JvbGxFbGVtZW50LCAnc2Nyb2xsJykuc3Vic2NyaWJlKGUgPT4ge1xyXG4gICAgICAgIHRoaXMuZ2V0Vmlld1NjYWxlRGF0YSgpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldFZpZXdTY2FsZURhdGEoKSB7XHJcbiAgICBpZiAodGhpcy5zY3JvbGxFbGVtZW50KSB7XHJcbiAgICAgIGNvbnN0IGNvbnRhaW5lcldpZHRoID0gdGhpcy5zY3JvbGxFbGVtZW50LmNsaWVudFdpZHRoO1xyXG4gICAgICBjb25zdCBzY3JvbGxMZWZ0ID0gdGhpcy5zY3JvbGxFbGVtZW50LnNjcm9sbExlZnQ7XHJcbiAgICAgIGNvbnN0IHN0YXJ0ID0gTWF0aC5mbG9vcihzY3JvbGxMZWZ0IC8gdGhpcy5zY2FsZVdpZHRoW3RoaXMudW5pdF0pO1xyXG4gICAgICBjb25zdCBvZmZzZXQgPSBNYXRoLmNlaWwoY29udGFpbmVyV2lkdGggLyB0aGlzLnNjYWxlV2lkdGhbdGhpcy51bml0XSk7XHJcbiAgICAgIHRoaXMudmlld1NjYWxlUmFuZ2UgPSBbc3RhcnQgLSAyLCBzdGFydCArIG9mZnNldCArIDJdO1xyXG4gICAgICB0aGlzLnZpZXdTQ2FsZURhdGEgPSB0aGlzLnNjYWxlRGF0YS5maWx0ZXIoKGk6IEdhbnR0U2NhbGVEYXRlSW5mbykgPT4ge1xyXG4gICAgICAgIHJldHVybiBpLmluZGV4ID49IHRoaXMudmlld1NjYWxlUmFuZ2VbMF0gJiYgaS5pbmRleCA8PSB0aGlzLnZpZXdTY2FsZVJhbmdlWzFdO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2VuZXJhdGVTY2FsZURhdGEoc3RhcnREYXRlOiBEYXRlLCBlbmREYXRlOiBEYXRlKTogR2FudHRTY2FsZURhdGVJbmZvW10ge1xyXG4gICAgaWYgKHN0YXJ0RGF0ZSAmJiBlbmREYXRlKSB7XHJcbiAgICAgIGNvbnN0IHNjYWxlRGF0YSA9IFtdO1xyXG4gICAgICBsZXQgaGFuZGxlRGF0ZSA9IHN0YXJ0RGF0ZTtcclxuICAgICAgbGV0IGluZGV4ID0gMDtcclxuICAgICAgd2hpbGUgKCF0aGlzLmdhbnR0U2VydmljZS5pc1NvbWVEYXRlKGhhbmRsZURhdGUsIGVuZERhdGUpKSB7XHJcbiAgICAgICAgY29uc3QgZGF0ZUluZm8gPSB0aGlzLmdlbmVyYXRlRGF0ZUluZm8oaGFuZGxlRGF0ZSwgaW5kZXgpO1xyXG4gICAgICAgIHNjYWxlRGF0YS5wdXNoKGRhdGVJbmZvKTtcclxuICAgICAgICBoYW5kbGVEYXRlID0gdGhpcy5nZXROZXh0RGF5KG5ldyBEYXRlKGhhbmRsZURhdGUpKTtcclxuICAgICAgICBpbmRleCsrO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBzY2FsZURhdGE7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldE5leHREYXkoZGF0ZTogRGF0ZSkge1xyXG4gICAgY29uc3QgbmV4dERheURhdGUgPSBkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgKyAxKTtcclxuICAgIHJldHVybiBuZXcgRGF0ZShuZXh0RGF5RGF0ZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbmVyYXRlRGF0ZUluZm8oZGF0ZTogRGF0ZSwgaW5kZXgpOiBHYW50dFNjYWxlRGF0ZUluZm8ge1xyXG4gICAgY29uc3QgZGF0ZUluZm86IEdhbnR0U2NhbGVEYXRlSW5mbyA9IHtcclxuICAgICAgZGF5T2ZNb250aExhYmVsOiAnJyxcclxuICAgICAgZGF5T2ZXZWVrTGFiZWw6ICcnLFxyXG4gICAgICBtb250aExhYmVsOiAnJyxcclxuICAgICAgeWVhckxhYmVsOiAnJyxcclxuICAgICAgZGF0ZTogZGF0ZSxcclxuICAgICAgbW9udGhTdGFydDogZmFsc2UsXHJcbiAgICAgIHdlZWtlbmQ6IGZhbHNlLFxyXG4gICAgICB0b2RheTogZmFsc2UsXHJcbiAgICAgIG1pbGVzdG9uZTogJycsXHJcbiAgICAgIGhpZ2hsaWdodFN0YXJ0OiBmYWxzZSxcclxuICAgICAgc2NhbGVTdGFydFZpc2FibGU6IHRydWUsXHJcbiAgICAgIGluZGV4XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGRheU9mTW9udGggPSBkYXRlLmdldERhdGUoKTtcclxuICAgIGRhdGVJbmZvLmRheU9mTW9udGhMYWJlbCA9IFN0cmluZyhkYXlPZk1vbnRoKTtcclxuICAgIGlmIChkYXlPZk1vbnRoID09PSAxKSB7XHJcbiAgICAgIGRhdGVJbmZvLm1vbnRoU3RhcnQgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGRheU9mV2VlayA9IGRhdGUuZ2V0RGF5KCk7XHJcbiAgICBkYXRlSW5mby5kYXlPZldlZWtMYWJlbCA9IFN0cmluZyhkYXlPZldlZWspO1xyXG4gICAgaWYgKGRheU9mV2VlayA9PT0gNikge1xyXG4gICAgICBkYXRlSW5mby53ZWVrZW5kID0gdHJ1ZTtcclxuICAgIH1cclxuICAgIGNvbnN0IG1vbnRoID0gZGF0ZS5nZXRNb250aCgpICsgMTtcclxuICAgIGRhdGVJbmZvLm1vbnRoTGFiZWwgPSBTdHJpbmcobW9udGgpO1xyXG4gICAgY29uc3QgeWVhciA9IGRhdGUuZ2V0RnVsbFllYXIoKTtcclxuICAgIGRhdGVJbmZvLnllYXJMYWJlbCA9IFN0cmluZyh5ZWFyKTtcclxuICAgIGlmICh0aGlzLmdhbnR0U2VydmljZS5pc1NvbWVEYXRlKGRhdGUsIG5ldyBEYXRlKCkpKSB7XHJcbiAgICAgIGRhdGVJbmZvLnRvZGF5ID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAobmV3IERhdGUoeWVhciwgbW9udGggLSAxLCBkYXlPZk1vbnRoICsgdGhpcy5TQ0FMRV9TVEFSVF9MQUJMRV9PRkZTRVQpLmdldE1vbnRoKCkgPiBtb250aCAtIDEpIHtcclxuICAgICAgZGF0ZUluZm8uc2NhbGVTdGFydFZpc2FibGUgPSBmYWxzZTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLm1pbGVzdG9uZUxpc3QpIHtcclxuICAgICAgdGhpcy5taWxlc3RvbmVMaXN0LmZvckVhY2goKG1pbGVzdG9uZSkgPT4ge1xyXG4gICAgICAgIGlmIChtaWxlc3RvbmUuZGF0ZSkge1xyXG4gICAgICAgICAgaWYgKHRoaXMuZ2FudHRTZXJ2aWNlLmlzU29tZURhdGUobWlsZXN0b25lLmRhdGUsIGRhdGVJbmZvLmRhdGUpKSB7XHJcbiAgICAgICAgICAgIGRhdGVJbmZvLm1pbGVzdG9uZSA9IG1pbGVzdG9uZS5sYWJsZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBkYXRlSW5mbztcclxuICB9XHJcblxyXG4gIHRyYWNrQnlGbihpbmRleCwgaXRlbSkge1xyXG4gICAgcmV0dXJuIGluZGV4O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnYW50dEJhclN0YXR1c0NoYW5nZShzdGF0dXM6IEdhbnR0QmFyU3RhdHVzKSB7XHJcbiAgICB0aGlzLmhpZ2hsaWdodCA9IHN0YXR1cy5mb2N1c2VkO1xyXG4gICAgaWYgKHRoaXMuaGlnaGxpZ2h0KSB7XHJcbiAgICAgIHRoaXMuc2NhbGVEYXRhLmZvckVhY2goKGRhdGVJbmZvLCBpbmRleCkgPT4ge1xyXG4gICAgICAgIGlmIChkYXRlSW5mby5kYXRlID49IHN0YXR1cy5zdGFydERhdGUgJiYgZGF0ZUluZm8uZGF0ZSA8PSBzdGF0dXMuZW5kRGF0ZSkge1xyXG4gICAgICAgICAgZGF0ZUluZm8uaGlnaGxpZ2h0ID0gdHJ1ZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgZGF0ZUluZm8uaGlnaGxpZ2h0ID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGRhdGVJbmZvLmhpZ2hsaWdodFN0YXJ0ID0gZmFsc2U7XHJcbiAgICAgIH0pO1xyXG4gICAgICBjb25zdCBoaWdobGlnaHRCYXJTdGFydEluZGV4ID0gIHRoaXMuc2NhbGVEYXRhLmZpbmRJbmRleCgoZGF0YSkgPT4ge1xyXG4gICAgICAgIHJldHVybiBkYXRhLmhpZ2hsaWdodDtcclxuICAgICAgfSk7XHJcbiAgICAgIGlmIChoaWdobGlnaHRCYXJTdGFydEluZGV4ID4gLTEpIHtcclxuICAgICAgICB0aGlzLnNjYWxlRGF0YVtoaWdobGlnaHRCYXJTdGFydEluZGV4XS5oaWdobGlnaHRTdGFydCA9IHRydWU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGhpZ2hsaWdodERhdGEgPSB0aGlzLnNjYWxlRGF0YS5maWx0ZXIoKGRhdGEpID0+IHtcclxuICAgICAgICByZXR1cm4gZGF0YS5oaWdobGlnaHQ7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgaWYgKGhpZ2hsaWdodERhdGEubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoaGlnaGxpZ2h0RGF0YS5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICBjb25zdCBzdGFydERhdGEgPSBoaWdobGlnaHREYXRhWzBdO1xyXG4gICAgICAgIHRoaXMuaGlnaGxpZ2h0U3RhcnRUZXh0ID1cclxuICAgICAgICAgIHRoaXMucHJlZml4WmVybyhwYXJzZUludChzdGFydERhdGEubW9udGhMYWJlbCwgMTApKSArICctJyArIHRoaXMucHJlZml4WmVybyhwYXJzZUludChzdGFydERhdGEuZGF5T2ZNb250aExhYmVsLCAxMCkpO1xyXG4gICAgICAgIGNvbnN0IGhpZ2hsaWdodFdpZHRoID0gdGhpcy5nYW50dFNlcnZpY2UuZ2V0U2NhbGVVbml0UGl4ZWwoKTtcclxuICAgICAgICBpZiAoaGlnaGxpZ2h0V2lkdGggPCA0MCkge1xyXG4gICAgICAgICAgdGhpcy5oaWdobGlnaHRNaW5XaWR0aCA9IDQwO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLmhpZ2hsaWdodE1pbldpZHRoID0gaGlnaGxpZ2h0V2lkdGg7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IHN0YXJ0RGF0YSA9IGhpZ2hsaWdodERhdGFbMF07XHJcbiAgICAgICAgY29uc3QgZW5kRGF0YSA9IGhpZ2hsaWdodERhdGFbaGlnaGxpZ2h0RGF0YS5sZW5ndGggLSAxXTtcclxuICAgICAgICB0aGlzLmhpZ2hsaWdodFN0YXJ0VGV4dCA9XHJcbiAgICAgICAgICB0aGlzLnByZWZpeFplcm8ocGFyc2VJbnQoc3RhcnREYXRhLm1vbnRoTGFiZWwsIDEwKSkgKyAnLScgKyB0aGlzLnByZWZpeFplcm8ocGFyc2VJbnQoc3RhcnREYXRhLmRheU9mTW9udGhMYWJlbCwgMTApKTtcclxuICAgICAgICB0aGlzLmhpZ2hsaWdodEVuZFRleHQgPVxyXG4gICAgICAgICAgdGhpcy5wcmVmaXhaZXJvKHBhcnNlSW50KGVuZERhdGEubW9udGhMYWJlbCwgMTApKSArICctJyArIHRoaXMucHJlZml4WmVybyhwYXJzZUludChlbmREYXRhLmRheU9mTW9udGhMYWJlbCwgMTApKTtcclxuICAgICAgICBjb25zdCBoaWdobGlnaHRXaWR0aCA9IGhpZ2hsaWdodERhdGEubGVuZ3RoICogdGhpcy5nYW50dFNlcnZpY2UuZ2V0U2NhbGVVbml0UGl4ZWwoKTtcclxuICAgICAgICBpZiAoaGlnaGxpZ2h0V2lkdGggPCA4NCkge1xyXG4gICAgICAgICAgdGhpcy5oaWdobGlnaHRNaW5XaWR0aCA9IDg0O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLmhpZ2hsaWdodE1pbldpZHRoID0gaGlnaGxpZ2h0V2lkdGg7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcmVmaXhaZXJvKG51bTogbnVtYmVyKSB7XHJcbiAgICByZXR1cm4gKEFycmF5KDIpLmpvaW4oJzAnKSArIG51bSkuc2xpY2UoLTIpO1xyXG4gIH1cclxuXHJcbiAgYWRkTWlsZXN0b25lKGluZm86IEdhbnR0U2NhbGVEYXRlSW5mbykge1xyXG4gICAgdGhpcy5hZGRNaWxlc3RvbmVFdmVudC5lbWl0KGluZm8pO1xyXG4gIH1cclxuXHJcbiAgY2xlYXJEYXlTcGxpdExpbmUoKSB7XHJcbiAgICBpZih0aGlzLnNob3dEYXlTcGxpdExpbmUgJiYgdGhpcy5nYW50dEJhckNvbnRhaW5lckVsZW1lbnQpIHtcclxuICAgICAgY29uc3QgZGF5TGluZXMgPSB0aGlzLmdhbnR0QmFyQ29udGFpbmVyRWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZGV2dWktZGF5LXNwbGl0LWxpbmUnKTtcclxuICAgICAgZGF5TGluZXMuZm9yRWFjaChpdGVtID0+IHtcclxuICAgICAgICBjb25zdCBwYXJlbnQgPSBpdGVtLnBhcmVudEVsZW1lbnQ7XHJcbiAgICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKGl0ZW0pO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gICAgaWYgKHRoaXMuZ2FudHRCYXJTdGF0dXNIYW5kbGVyKSB7XHJcbiAgICAgIHRoaXMuZ2FudHRCYXJTdGF0dXNIYW5kbGVyLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgIHRoaXMuZ2FudHRCYXJTdGF0dXNIYW5kbGVyID0gbnVsbDtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmdhbnR0U2FjbGVDb25maWdIYW5kbGVyKSB7XHJcbiAgICAgIHRoaXMuZ2FudHRTYWNsZUNvbmZpZ0hhbmRsZXIudW5zdWJzY3JpYmUoKTtcclxuICAgICAgdGhpcy5nYW50dFNhY2xlQ29uZmlnSGFuZGxlciA9IG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5zY3JvbGxIYW5kbGVyKSB7XHJcbiAgICAgIHRoaXMuc2Nyb2xsSGFuZGxlci51bnN1YnNjcmliZSgpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCI8ZGl2XG4gIGNsYXNzPVwiZGV2dWktZ2FudHQtc2NhbGUge3sgdW5pdCB9fVwiXG4gICpuZ0Zvcj1cImxldCBkYXRhIG9mIHZpZXdTQ2FsZURhdGE7IHRyYWNrQnk6IHRyYWNrQnlGbjsgbGV0IGZpcnN0ID0gZmlyc3Q7IGxldCBsYXN0ID0gbGFzdFwiXG4gIFtuZ0NsYXNzXT1cInsgdG9kYXk6IGRhdGEudG9kYXksIG1pbGVzdG9uZTogZGF0YS5taWxlc3RvbmUgfVwiXG4gIFtzdHlsZS5sZWZ0XT1cInNjYWxlV2lkdGhbdW5pdF0gKiBkYXRhLmluZGV4ICsgJ3B4J1wiXG4gIFtzdHlsZS53aWR0aF09XCJzY2FsZVdpZHRoW3VuaXRdICsgJ3B4J1wiXG4gIGRHYW50dE1hcmtlclxuICBbbW9udGhNYXJrXT1cImRhdGEubW9udGhTdGFydFwiXG4gIFt3ZWVrZW5kXT1cImRhdGEud2Vla2VuZFwiXG4gIFttaWxlc3RvbmVdPVwiZGF0YS5taWxlc3RvbmVcIlxuICBbdG9kYXldPVwiZGF0YS50b2RheVwiXG4gIFtpbmRleF09XCJkYXRhLmluZGV4XCJcbiAgW3Nob3dEYXlTcGxpdExpbmVdPVwic2hvd0RheVNwbGl0TGluZVwiXG4gIFtkYXRlXT1cImRhdGEuZGF0ZVwiXG4gIFt1bml0XT1cInVuaXRcIlxuICBbbGFzdF09XCJsYXN0XCJcbiAgW2dhbnR0U2NhbGVDb250YWluZXJPZmZzZXRMZWZ0XT1cImdhbnR0U2NhbGVDb250YWluZXJPZmZzZXRMZWZ0XCJcbiAgW2dhbnR0QmFyQ29udGFpbmVyRWxlbWVudF09XCJnYW50dEJhckNvbnRhaW5lckVsZW1lbnRcIlxuPlxuICA8ZGl2IGNsYXNzPVwiZGV2dWktc2NhbGUtc3RhcnRcIiBbbmdDbGFzc109XCJ7IG1pbGVzdG9uZTogZGF0YS5taWxlc3RvbmUgfVwiIFt0aXRsZV09XCJkYXRhLm1pbGVzdG9uZSB8fCAnJ1wiPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJkYXRhLm1pbGVzdG9uZSAmJiB1bml0ID09PSAnZGF5J1wiPlxuICAgICAge3sgZGF0YS5taWxlc3RvbmUgfX1cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWRhdGEubWlsZXN0b25lIHx8IHVuaXQgIT09ICdkYXknXCI+XG4gICAgICB7e1xuICAgICAgICBkYXRhLnNjYWxlU3RhcnRWaXNhYmxlICYmIChmaXJzdCB8fCBkYXRhLm1vbnRoU3RhcnQpXG4gICAgICAgICAgPyB1bml0ID09PSAnbW9udGgnXG4gICAgICAgICAgICA/IGkxOG5UZXh0Py55ZWFyRGlzcGxheShkYXRhLnllYXJMYWJlbClcbiAgICAgICAgICAgIDogaTE4blRleHQ/LnllYXJBbmRNb250aERpc3BsYXkoZGF0YS55ZWFyTGFiZWwsIGRhdGEubW9udGhMYWJlbClcbiAgICAgICAgICA6ICcnXG4gICAgICB9fVxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImRldnVpLXNjYWxlLXVuaXRcIj5cbiAgICA8ZGl2ICpuZ0lmPVwiaGlnaGxpZ2h0ICYmIGRhdGEuaGlnaGxpZ2h0