@rinminase/ng-charts
Version:
Reactive, responsive, beautiful charts for Angular based on ng2-charts
453 lines • 59.1 kB
JavaScript
import { Directive, EventEmitter, Input, Output, } from "@angular/core";
import * as chartJs from "chart.js";
import { getColors } from "./get-colors";
import { cloneDeep } from "lodash-es";
import * as i0 from "@angular/core";
import * as i1 from "./theme.service";
var UpdateType;
(function (UpdateType) {
UpdateType[UpdateType["Default"] = 0] = "Default";
UpdateType[UpdateType["Update"] = 1] = "Update";
UpdateType[UpdateType["Refresh"] = 2] = "Refresh";
})(UpdateType || (UpdateType = {}));
export class BaseChartDirective {
constructor(element, themeService) {
this.element = element;
this.themeService = themeService;
this.options = {};
this.chartClick = new EventEmitter();
this.chartHover = new EventEmitter();
this.old = {
dataExists: false,
dataLength: 0,
datasetsExists: false,
datasetsLength: 0,
datasetsDataObjects: [],
datasetsDataLengths: [],
colorsExists: false,
colors: [],
labelsExist: false,
labels: [],
legendExists: false,
legend: {},
};
this.subs = [];
}
/**
* Register a plugin.
*/
static registerPlugin(plugin) {
chartJs.Chart.plugins.register(plugin);
}
static unregisterPlugin(plugin) {
chartJs.Chart.plugins.unregister(plugin);
}
ngOnInit() {
this.ctx = this.element.nativeElement.getContext("2d");
this.refresh();
this.subs.push(this.themeService.colorschemesOptions.subscribe(() => this.themeChanged()));
}
themeChanged() {
this.refresh();
}
ngDoCheck() {
if (!this.chart) {
return;
}
let updateRequired = UpdateType.Default;
const wantUpdate = (x) => {
updateRequired = x > updateRequired ? x : updateRequired;
};
if (!!this.data !== this.old.dataExists) {
this.propagateDataToDatasets(this.data);
this.old.dataExists = !!this.data;
wantUpdate(UpdateType.Update);
}
if (this.data && this.data.length !== this.old.dataLength) {
this.old.dataLength = (this.data && this.data.length) || 0;
wantUpdate(UpdateType.Update);
}
if (!!this.datasets !== this.old.datasetsExists) {
this.old.datasetsExists = !!this.datasets;
wantUpdate(UpdateType.Update);
}
if (this.datasets && this.datasets.length !== this.old.datasetsLength) {
this.old.datasetsLength = (this.datasets && this.datasets.length) || 0;
wantUpdate(UpdateType.Update);
}
if (this.datasets &&
this.datasets.filter((x, i) => x.data !== this.old.datasetsDataObjects[i])
.length) {
this.old.datasetsDataObjects = this.datasets.map((x) => x.data);
wantUpdate(UpdateType.Update);
}
if (this.datasets &&
this.datasets.filter((x, i) => x.data.length !== this.old.datasetsDataLengths[i]).length) {
this.old.datasetsDataLengths = this.datasets.map((x) => x.data.length);
wantUpdate(UpdateType.Update);
}
if (!!this.colors !== this.old.colorsExists) {
this.old.colorsExists = !!this.colors;
this.updateColors();
wantUpdate(UpdateType.Update);
}
// This smells of inefficiency, might need to revisit this
if (this.colors &&
this.colors.filter((x, i) => !this.colorsEqual(x, this.old.colors[i]))
.length) {
this.old.colors = this.colors.map((x) => this.copyColor(x));
this.updateColors();
wantUpdate(UpdateType.Update);
}
if (!!this.labels !== this.old.labelsExist) {
this.old.labelsExist = !!this.labels;
wantUpdate(UpdateType.Update);
}
if (this.labels &&
this.labels.filter((x, i) => !this.labelsEqual(x, this.old.labels[i]))
.length) {
this.old.labels = this.labels.map((x) => this.copyLabel(x));
wantUpdate(UpdateType.Update);
}
if (!!this.options.legend !== this.old.legendExists) {
this.old.legendExists = !!this.options.legend;
wantUpdate(UpdateType.Refresh);
}
if (this.options.legend &&
this.options.legend.position !== this.old.legend.position) {
this.old.legend.position = this.options.legend.position;
wantUpdate(UpdateType.Refresh);
}
switch (updateRequired) {
case UpdateType.Default:
break;
case UpdateType.Update:
this.update();
break;
case UpdateType.Refresh:
this.refresh();
break;
}
}
copyLabel(a) {
if (Array.isArray(a)) {
return [...a];
}
return a;
}
labelsEqual(a, b) {
return (true &&
Array.isArray(a) === Array.isArray(b) &&
(Array.isArray(a) || a === b) &&
(!Array.isArray(a) || a.length === b.length) &&
(!Array.isArray(a) || a.filter((x, i) => x !== b[i]).length === 0));
}
copyColor(a) {
const rc = {
backgroundColor: a.backgroundColor,
borderWidth: a.borderWidth,
borderColor: a.borderColor,
borderCapStyle: a.borderCapStyle,
borderDash: a.borderDash,
borderDashOffset: a.borderDashOffset,
borderJoinStyle: a.borderJoinStyle,
pointBorderColor: a.pointBorderColor,
pointBackgroundColor: a.pointBackgroundColor,
pointBorderWidth: a.pointBorderWidth,
pointRadius: a.pointRadius,
pointHoverRadius: a.pointHoverRadius,
pointHitRadius: a.pointHitRadius,
pointHoverBackgroundColor: a.pointHoverBackgroundColor,
pointHoverBorderColor: a.pointHoverBorderColor,
pointHoverBorderWidth: a.pointHoverBorderWidth,
pointStyle: a.pointStyle,
hoverBackgroundColor: a.hoverBackgroundColor,
hoverBorderColor: a.hoverBorderColor,
hoverBorderWidth: a.hoverBorderWidth,
};
return rc;
}
colorsEqual(a, b) {
if (!a !== !b) {
return false;
}
return (!a ||
(true &&
a.backgroundColor === b.backgroundColor &&
a.borderWidth === b.borderWidth &&
a.borderColor === b.borderColor &&
a.borderCapStyle === b.borderCapStyle &&
a.borderDash === b.borderDash &&
a.borderDashOffset === b.borderDashOffset &&
a.borderJoinStyle === b.borderJoinStyle &&
a.pointBorderColor === b.pointBorderColor &&
a.pointBackgroundColor === b.pointBackgroundColor &&
a.pointBorderWidth === b.pointBorderWidth &&
a.pointRadius === b.pointRadius &&
a.pointHoverRadius === b.pointHoverRadius &&
a.pointHitRadius === b.pointHitRadius &&
a.pointHoverBackgroundColor === b.pointHoverBackgroundColor &&
a.pointHoverBorderColor === b.pointHoverBorderColor &&
a.pointHoverBorderWidth === b.pointHoverBorderWidth &&
a.pointStyle === b.pointStyle &&
a.hoverBackgroundColor === b.hoverBackgroundColor &&
a.hoverBorderColor === b.hoverBorderColor &&
a.hoverBorderWidth === b.hoverBorderWidth));
}
updateColors() {
this.datasets.forEach((elm, index) => {
if (this.colors && this.colors[index]) {
Object.assign(elm, this.colors[index]);
}
else {
Object.assign(elm, getColors(this.chartType, index, elm.data.length), {
...elm,
});
}
});
}
ngOnChanges(changes) {
let updateRequired = UpdateType.Default;
const wantUpdate = (x) => {
updateRequired = x > updateRequired ? x : updateRequired;
};
// Check if the changes are in the data or datasets or labels or legend
if (changes.hasOwnProperty("data") && changes.data.currentValue) {
this.propagateDataToDatasets(changes.data.currentValue);
wantUpdate(UpdateType.Update);
}
if (changes.hasOwnProperty("datasets") && changes.datasets.currentValue) {
this.propagateDatasetsToData(changes.datasets.currentValue);
wantUpdate(UpdateType.Update);
}
if (changes.hasOwnProperty("labels")) {
if (this.chart) {
this.chart.data.labels = changes.labels.currentValue;
}
wantUpdate(UpdateType.Update);
}
if (changes.hasOwnProperty("legend")) {
if (this.chart) {
this.chart.config.options.legend.display = changes.legend.currentValue;
this.chart.generateLegend();
}
wantUpdate(UpdateType.Update);
}
if (changes.hasOwnProperty("options")) {
wantUpdate(UpdateType.Refresh);
}
switch (updateRequired) {
case UpdateType.Update:
this.update();
break;
case UpdateType.Refresh:
case UpdateType.Default:
this.refresh();
break;
}
}
ngOnDestroy() {
if (this.chart) {
this.chart.destroy();
this.chart = void 0;
}
this.subs.forEach((x) => x.unsubscribe());
}
update(duration) {
if (this.chart) {
return this.chart.update(duration);
}
return null;
}
hideDataset(index, hidden) {
this.chart.getDatasetMeta(index).hidden = hidden;
this.chart.update();
}
isDatasetHidden(index) {
return this.chart.getDatasetMeta(index).hidden;
}
toBase64Image() {
return this.chart.toBase64Image();
}
getChartConfiguration() {
const datasets = this.getDatasets();
const options = Object.assign({}, this.options);
if (this.legend === false) {
options.legend = { display: false };
}
// hook for onHover and onClick events
options.hover = options.hover || {};
if (!options.hover.onHover) {
options.hover.onHover = (event, active) => {
if (active && !active.length) {
return;
}
this.chartHover.emit({ event, active });
};
}
if (!options.onClick) {
options.onClick = (event, active) => {
this.chartClick.emit({ event, active });
};
}
const mergedOptions = this.smartMerge(options, this.themeService.getColorschemesOptions());
const chartConfig = {
type: this.chartType,
data: {
labels: this.labels || [],
datasets,
},
plugins: this.plugins,
options: mergedOptions,
};
return chartConfig;
}
getChartBuilder(ctx /*, data:any[], options:any*/) {
const chartConfig = this.getChartConfiguration();
return new chartJs.Chart(ctx, chartConfig);
}
smartMerge(options, overrides, level = 0) {
if (level === 0) {
options = cloneDeep(options);
}
const keysToUpdate = Object.keys(overrides);
keysToUpdate.forEach((key) => {
if (Array.isArray(overrides[key])) {
const arrayElements = options[key];
if (arrayElements) {
arrayElements.forEach((r) => {
this.smartMerge(r, overrides[key][0], level + 1);
});
}
}
else if (typeof overrides[key] === "object") {
if (!(key in options)) {
options[key] = {};
}
this.smartMerge(options[key], overrides[key], level + 1);
}
else {
options[key] = overrides[key];
}
});
if (level === 0) {
return options;
}
}
isMultiLineLabel(label) {
return Array.isArray(label);
}
joinLabel(label) {
if (!label) {
return null;
}
if (this.isMultiLineLabel(label)) {
return label.join(" ");
}
else {
return label;
}
}
propagateDatasetsToData(datasets) {
this.data = this.datasets.map((r) => r.data);
if (this.chart) {
this.chart.data.datasets = datasets;
}
this.updateColors();
}
propagateDataToDatasets(newDataValues) {
if (this.isMultiDataSet(newDataValues)) {
if (this.datasets && newDataValues.length === this.datasets.length) {
this.datasets.forEach((dataset, i) => {
dataset.data = newDataValues[i];
});
}
else {
this.datasets = newDataValues.map((data, index) => {
return {
data,
label: this.joinLabel(this.labels[index]) || `Label ${index}`,
};
});
if (this.chart) {
this.chart.data.datasets = this.datasets;
}
}
}
else {
if (!this.datasets) {
this.datasets = [{ data: newDataValues }];
if (this.chart) {
this.chart.data.datasets = this.datasets;
}
}
else {
this.datasets[0].data = newDataValues;
this.datasets.splice(1); // Remove all elements but the first
}
}
this.updateColors();
}
isMultiDataSet(data) {
return Array.isArray(data[0]);
}
getDatasets() {
if (!this.datasets && !this.data) {
throw new Error(`ng-charts configuration error, data or datasets field are required to render chart ${this.chartType}`);
}
// If `datasets` is defined, use it over the `data` property.
if (this.datasets) {
this.propagateDatasetsToData(this.datasets);
return this.datasets;
}
if (this.data) {
this.propagateDataToDatasets(this.data);
return this.datasets;
}
return null;
}
refresh() {
// if (this.options && this.options.responsive) {
// setTimeout(() => this.refresh(), 50);
// }
// todo: remove this line, it is producing flickering
if (this.chart) {
this.chart.destroy();
this.chart = void 0;
}
if (this.ctx) {
this.chart = this.getChartBuilder(this.ctx /*, data, this.options*/);
}
}
}
BaseChartDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: BaseChartDirective, deps: [{ token: i0.ElementRef }, { token: i1.ThemeService }], target: i0.ɵɵFactoryTarget.Directive });
BaseChartDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0", type: BaseChartDirective, selector: "canvas[baseChart]", inputs: { data: "data", datasets: "datasets", labels: "labels", options: "options", chartType: "chartType", colors: "colors", legend: "legend", plugins: "plugins" }, outputs: { chartClick: "chartClick", chartHover: "chartHover" }, exportAs: ["base-chart"], usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: BaseChartDirective, decorators: [{
type: Directive,
args: [{
// tslint:disable-next-line:directive-selector
selector: "canvas[baseChart]",
exportAs: "base-chart",
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.ThemeService }]; }, propDecorators: { data: [{
type: Input
}], datasets: [{
type: Input
}], labels: [{
type: Input
}], options: [{
type: Input
}], chartType: [{
type: Input
}], colors: [{
type: Input
}], legend: [{
type: Input
}], plugins: [{
type: Input
}], chartClick: [{
type: Output
}], chartHover: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1jaGFydC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2Jhc2UtY2hhcnQuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBR1QsWUFBWSxFQUNaLEtBQUssRUFJTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxLQUFLLE9BQU8sTUFBTSxVQUFVLENBQUM7QUFDcEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUl6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDOzs7QUFtQ3RDLElBQUssVUFJSjtBQUpELFdBQUssVUFBVTtJQUNiLGlEQUFPLENBQUE7SUFDUCwrQ0FBTSxDQUFBO0lBQ04saURBQU8sQ0FBQTtBQUNULENBQUMsRUFKSSxVQUFVLEtBQVYsVUFBVSxRQUlkO0FBT0QsTUFBTSxPQUFPLGtCQUFrQjtJQXVEN0IsWUFDVSxPQUFtQixFQUNuQixZQUEwQjtRQUQxQixZQUFPLEdBQVAsT0FBTyxDQUFZO1FBQ25CLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBcERwQixZQUFPLEdBQWlCLEVBQUUsQ0FBQztRQU0xQixlQUFVLEdBR3RCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDUCxlQUFVLEdBR3RCLElBQUksWUFBWSxFQUFFLENBQUM7UUFLaEIsUUFBRyxHQUFhO1lBQ3RCLFVBQVUsRUFBRSxLQUFLO1lBQ2pCLFVBQVUsRUFBRSxDQUFDO1lBQ2IsY0FBYyxFQUFFLEtBQUs7WUFDckIsY0FBYyxFQUFFLENBQUM7WUFDakIsbUJBQW1CLEVBQUUsRUFBRTtZQUN2QixtQkFBbUIsRUFBRSxFQUFFO1lBQ3ZCLFlBQVksRUFBRSxLQUFLO1lBQ25CLE1BQU0sRUFBRSxFQUFFO1lBQ1YsV0FBVyxFQUFFLEtBQUs7WUFDbEIsTUFBTSxFQUFFLEVBQUU7WUFDVixZQUFZLEVBQUUsS0FBSztZ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WCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDbkUsTUFBTSxFQUNUO1lBQ0EsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUU1RCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFFcEIsVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUMvQjtRQUVELElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUU7WUFDMUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7WUFFckMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUMvQjtRQUVELElBQ0UsSUFBSSxDQUFDLE1BQU07WUFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDbkUsTUFBTSxFQUNUO1lBQ0EsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUU1RCxVQUFVLENB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RTtZQUNkLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQztTQUNyQjtRQUNELElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNaLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLENBQUM7U0FDdEU7SUFDSCxDQUFDOzsrR0E1Z0JVLGtCQUFrQjttR0FBbEIsa0JBQWtCOzJGQUFsQixrQkFBa0I7a0JBTDlCLFNBQVM7bUJBQUM7b0JBQ1QsOENBQThDO29CQUM5QyxRQUFRLEVBQUUsbUJBQW1CO29CQUM3QixRQUFRLEVBQUUsWUFBWTtpQkFDdkI7NEhBR2lCLElBQUk7c0JBQW5CLEtBQUs7Z0JBQ1UsUUFBUTtzQkFBdkIsS0FBSztnQkFDVSxNQUFNO3NCQUFyQixLQUFLO2dCQUNVLE9BQU87c0JBQXRCLEtBQUs7Z0JBQ1UsU0FBUztzQkFBeEIsS0FBSztnQkFDVSxNQUFNO3NCQUFyQixLQUFLO2dCQUNVLE1BQU07c0JBQXJCLEtBQUs7Z0JBQ1UsT0FBTztzQkFBdEIsS0FBSztnQkFFVyxVQUFVO3NCQUExQixNQUFNO2dCQUlVLFVBQVU7c0JBQTFCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBEaXJlY3RpdmUsXG4gIERvQ2hlY2ssXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCAqIGFzIGNoYXJ0SnMgZnJvbSBcImNoYXJ0LmpzXCI7XG5pbXBvcnQgeyBnZXRDb2xvcnMgfSBmcm9tIFwiLi9nZXQtY29sb3JzXCI7XG5pbXBvcnQgeyBEYXRhc2V0Q29sb3IgfSBmcm9tIFwiLi9jb2xvclwiO1xuaW1wb3J0IHsgVGhlbWVTZXJ2aWNlIH0gZnJvbSBcIi4vdGhlbWUuc2VydmljZVwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IGNsb25lRGVlcCB9IGZyb20gXCJsb2Rhc2gtZXNcIjtcblxuZXhwb3J0IHR5cGUgU2luZ2xlRGF0YVNldCA9IG51bWJlcltdIHwgY2hhcnRKcy5DaGFydFBvaW50W107XG5leHBvcnQgdHlwZSBNdWx0aURhdGFTZXQgPSAobnVtYmVyW10gfCBjaGFydEpzLkNoYXJ0UG9pbnRbXSlbXTtcbmV4cG9ydCB0eXBlIFNpbmdsZU9yTXVsdGlEYXRhU2V0ID0gU2luZ2xlRGF0YVNldCB8IE11bHRpRGF0YVNldDtcblxuZXhwb3J0IHR5cGUgUGx1Z2luU2VydmljZUdsb2JhbFJlZ2lzdHJhdGlvbkFuZE9wdGlvbnMgPSBjaGFydEpzLlBsdWdpblNlcnZpY2VHbG9iYWxSZWdpc3RyYXRpb24gJlxuICBjaGFydEpzLlBsdWdpblNlcnZpY2VSZWdpc3RyYXRpb25PcHRpb25zO1xuZXhwb3J0IHR5cGUgU2luZ2xlTGluZUxhYmVsID0gc3RyaW5nO1xuZXhwb3J0IHR5cGUgTXVsdGlMaW5lTGFiZWwgPSBzdHJpbmdbXTtcblxuZXhwb3J0IHR5cGUgQ2hhcnRMYWJlbCA9IFNpbmdsZUxpbmVMYWJlbCB8IE11bHRpTGluZUxhYmVsO1xuZXhwb3J0IHR5cGUgQ2hhcnRDb2xvciA9IERhdGFzZXRDb2xvcltdO1xuZXhwb3J0IHR5cGUgQ2hhcnRUeXBlID0gY2hhcnRKcy5DaGFydFR5cGU7XG5leHBvcnQgdHlwZSBDaGFydERhdGFzZXQgPSBjaGFydEpzLkNoYXJ0RGF0YVNldHM7XG5leHBvcnQgdHlwZSBDaGFydERhdGFzZXRzID0gY2hhcnRKcy5DaGFydERhdGFTZXRzW107XG5leHBvcnQgdHlwZSBDaGFydE9wdGlvbnMgPSBjaGFydEpzLkNoYXJ0T3B0aW9ucztcblxuaW50ZXJmYWNlIE9sZFN0YXRlIHtcbiAgZGF0YUV4aXN0czogYm9vbGVhbjtcbiAgZGF0YUxlbmd0aDogbnVtYmVyO1xuICBkYXRhc2V0c0V4aXN0czogYm9vbGVhbjtcbiAgZGF0YXNldHNMZW5ndGg6IG51bWJlcjtcbiAgZGF0YXNldHNEYXRhT2JqZWN0czogYW55W107XG4gIGRhdGFzZXRzRGF0YUxlbmd0aHM6IG51bWJlcltdO1xuICBjb2xvcnNFeGlzdHM6IGJvb2xlYW47XG4gIGNvbG9yczogRGF0YXNldENvbG9yW107XG4gIGxhYmVsc0V4aXN0OiBib29sZWFuO1xuICBsYWJlbHM6IENoYXJ0TGFiZWxbXTtcbiAgbGVnZW5kRXhpc3RzOiBib29sZWFuO1xuICBsZWdlbmQ6IHtcbiAgICBwb3NpdGlvbj86IHN0cmluZztcbiAgfTtcbn1cblxuZW51bSBVcGRhdGVUeXBlIHtcbiAgRGVmYXVsdCxcbiAgVXBkYXRlLFxuICBSZWZyZXNoLFxufVxuXG5ARGlyZWN0aXZlKHtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmRpcmVjdGl2ZS1zZWxlY3RvclxuICBzZWxlY3RvcjogXCJjYW52YXNbYmFzZUNoYXJ0XVwiLFxuICBleHBvcnRBczogXCJiYXNlLWNoYXJ0XCIsXG59KVxuZXhwb3J0IGNsYXNzIEJhc2VDaGFydERpcmVjdGl2ZVxuICBpbXBsZW1lbnRzIE9uRGVzdHJveSwgT25DaGFuZ2VzLCBPbkluaXQsIE9uRGVzdHJveSwgRG9DaGVjayB7XG4gIEBJbnB1dCgpIHB1YmxpYyBkYXRhOiBTaW5nbGVPck11bHRpRGF0YVNldDtcbiAgQElucHV0KCkgcHVibGljIGRhdGFzZXRzOiBDaGFydERhdGFzZXRzO1xuICBASW5wdXQoKSBwdWJsaWMgbGFiZWxzOiBDaGFydExhYmVsW107XG4gIEBJbnB1dCgpIHB1YmxpYyBvcHRpb25zOiBDaGFydE9wdGlvbnMgPSB7fTtcbiAgQElucHV0KCkgcHVibGljIGNoYXJ0VHlwZTogQ2hhcnRUeXBlO1xuICBASW5wdXQoKSBwdWJsaWMgY29sb3JzOiBEYXRhc2V0Q29sb3JbXTtcbiAgQElucHV0KCkgcHVibGljIGxlZ2VuZDogYm9vbGVhbjtcbiAgQElucHV0KCkgcHVibGljIHBsdWdpbnM6IFBsdWdpblNlcnZpY2VHbG9iYWxSZWdpc3RyYXRpb25BbmRPcHRpb25zW107XG5cbiAgQE91dHB1dCgpIHB1YmxpYyBjaGFydENsaWNrOiBFdmVudEVtaXR0ZXI8e1xuICAgIGV2ZW50PzogTW91c2VFdmVudDtcbiAgICBhY3RpdmU/OiB7fVtdO1xuICB9PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBjaGFydEhvdmVyOiBFdmVudEVtaXR0ZXI8e1xuICAgIGV2ZW50OiBNb3VzZUV2ZW50O1xuICAgIGFjdGl2ZToge31bXTtcbiAgfT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHVibGljIGN0eDogc3RyaW5nO1xuICBwdWJsaWMgY2hhcnQ6IENoYXJ0O1xuXG4gIHByaXZhdGUgb2xkOiBPbGRTdGF0ZSA9IHtcbiAgICBkYXRhRXhpc3RzOiBmYWxzZSxcbiAgICBkYXRhTGVuZ3RoOiAwLFxuICAgIGRhdGFzZXRzRXhpc3RzOiBmYWxzZSxcbiAgICBkYXRhc2V0c0xlbmd0aDogMCxcbiAgICBkYXRhc2V0c0RhdGFPYmplY3RzOiBbXSxcbiAgICBkYXRhc2V0c0RhdGFMZW5ndGhzOiBbXSxcbiAgICBjb2xvcnNFeGlzdHM6IGZhbHNlLFxuICAgIGNvbG9yczogW10sXG4gICAgbGFiZWxzRXhpc3Q6IGZhbHNlLFxuICAgIGxhYmVsczogW10sXG4gICAgbGVnZW5kRXhpc3RzOiBmYWxzZSxcbiAgICBsZWdlbmQ6IHt9LFxuICB9O1xuXG4gIHByaXZhdGUgc3ViczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBwbHVnaW4uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlZ2lzdGVyUGx1Z2luKFxuICAgIHBsdWdpbjogUGx1Z2luU2VydmljZUdsb2JhbFJlZ2lzdHJhdGlvbkFuZE9wdGlvbnNcbiAgKSB7XG4gICAgY2hhcnRKcy5DaGFydC5wbHVnaW5zLnJlZ2lzdGVyKHBsdWdpbik7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIHVucmVnaXN0ZXJQbHVnaW4oXG4gICAgcGx1Z2luOiBQbHVnaW5TZXJ2aWNlR2xvYmFsUmVnaXN0cmF0aW9uQW5kT3B0aW9uc1xuICApIHtcbiAgICBjaGFydEpzLkNoYXJ0LnBsdWdpbnMudW5yZWdpc3RlcihwbHVnaW4pO1xuICB9XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWxlbWVudDogRWxlbWVudFJlZixcbiAgICBwcml2YXRlIHRoZW1lU2VydmljZTogVGhlbWVTZXJ2aWNlXG4gICkge31cblxuICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5jdHggPSB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5nZXRDb250ZXh0KFwiMmRcIik7XG4gICAgdGhpcy5yZWZyZXNoKCk7XG4gICAgdGhpcy5zdWJzLnB1c2goXG4gICAgICB0aGlzLnRoZW1lU2VydmljZS5jb2xvcnNjaGVtZXNPcHRpb25zLnN1YnNjcmliZSgoKSA9PiB0aGlzLnRoZW1lQ2hhbmdlZCgpKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHRoZW1lQ2hhbmdlZCgpIHtcbiAgICB0aGlzLnJlZnJlc2goKTtcbiAgfVxuXG4gIG5nRG9DaGVjaygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2hhcnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IHVwZGF0ZVJlcXVpcmVkID0gVXBkYXRlVHlwZS5EZWZhdWx0O1xuICAgIGNvbnN0IHdhbnRVcGRhdGUgPSAoeDogVXBkYXRlVHlwZSkgPT4ge1xuICAgICAgdXBkYXRlUmVxdWlyZWQgPSB4ID4gdXBkYXRlUmVxdWlyZWQgPyB4IDogdXBkYXRlUmVxdWlyZWQ7XG4gICAgfTtcblxuICAgIGlmICghIXRoaXMuZGF0YSAhPT0gdGhpcy5vbGQuZGF0YUV4aXN0cykge1xuICAgICAgdGhpcy5wcm9wYWdhdGVEYXRhVG9EYXRhc2V0cyh0aGlzLmRhdGEpO1xuXG4gICAgICB0aGlzLm9sZC5kYXRhRXhpc3RzID0gISF0aGlzLmRhdGE7XG5cbiAgICAgIHdhbnRVcGRhdGUoVXBkYXRlVHlwZS5VcGRhdGUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRhdGEgJiYgdGhpcy5kYXRhLmxlbmd0aCAhPT0gdGhpcy5vbGQuZGF0YUxlbmd0aCkge1xuICAgICAgdGhpcy5vbGQuZGF0YUxlbmd0aCA9ICh0aGlzLmRhdGEgJiYgdGhpcy5kYXRhLmxlbmd0aCkgfHwgMDtcblxuICAgICAgd2FudFVwZGF0ZShVcGRhdGVUeXBlLlVwZGF0ZSk7XG4gICAgfVxuXG4gICAgaWYgKCEhdGhpcy5kYXRhc2V0cyAhPT0gdGhpcy5vbGQuZGF0YXNldHNFeGlzdHMpIHtcbiAgICAgIHRoaXMub2xkLmRhdGFzZXRzRXhpc3RzID0gISF0aGlzLmRhdGFzZXRzO1xuXG4gICAgICB3YW50VXBkYXRlKFVwZGF0ZVR5cGUuVXBkYXRlKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kYXRhc2V0cyAmJiB0aGlzLmRhdGFzZXRzLmxlbmd0aCAhPT0gdGhpcy5vbGQuZGF0YXNldHNMZW5ndGgpIHtcbiAgICAgIHRoaXMub2xkLmRhdGFzZXRzTGVuZ3RoID0gKHRoaXMuZGF0YXNldHMgJiYgdGhpcy5kYXRhc2V0cy5sZW5ndGgpIHx8IDA7XG5cbiAgICAgIHdhbnRVcGRhdGUoVXBkYXRlVHlwZS5VcGRhdGUpO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHRoaXMuZGF0YXNldHMgJiZcbiAgICAgIHRoaXMuZGF0YXNldHMuZmlsdGVyKCh4LCBpKSA9PiB4LmRhdGEgIT09IHRoaXMub2xkLmRhdGFzZXRzRGF0YU9iamVjdHNbaV0pXG4gICAgICAgIC5sZW5ndGhcbiAgICApIHtcbiAgICAgIHRoaXMub2xkLmRhdGFzZXRzRGF0YU9iamVjdHMgPSB0aGlzLmRhdGFzZXRzLm1hcCgoeCkgPT4geC5kYXRhKTtcblxuICAgICAgd2FudFVwZGF0ZShVcGRhdGVUeXBlLlVwZGF0ZSk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdGhpcy5kYXRhc2V0cyAmJlxuICAgICAgdGhpcy5kYXRhc2V0cy5maWx0ZXIoXG4gICAgICAgICh4LCBpKSA9PiB4LmRhdGEubGVuZ3RoICE9PSB0aGlzLm9sZC5kYXRhc2V0c0RhdGFMZW5ndGhzW2ldXG4gICAgICApLmxlbmd0aFxuICAgICkge1xuICAgICAgdGhpcy5vbGQuZGF0YXNldHNEYXRhTGVuZ3RocyA9IHRoaXMuZGF0YXNldHMubWFwKCh4KSA9PiB4LmRhdGEubGVuZ3RoKTtcblxuICAgICAgd2FudFVwZGF0ZShVcGRhdGVUeXBlLlVwZGF0ZSk7XG4gICAgfVxuXG4gICAgaWYgKCEhdGhpcy5jb2xvcnMgIT09IHRoaXMub2xkLmNvbG9yc0V4aXN0cykge1xuICAgICAgdGhpcy5vbGQuY29sb3JzRXhpc3RzID0gISF0aGlzLmNvbG9ycztcblxuICAgICAgdGhpcy51cGRhdGVDb2xvcnMoKTtcblxuICAgICAgd2FudFVwZGF0ZShVcGRhdGVUeXBlLlVwZGF0ZSk7XG4gICAgfVxuXG4gICAgLy8gVGhpcyBzbWVsbHMgb2YgaW5lZmZpY2llbmN5LCBtaWdodCBuZWVkIHRvIHJldmlzaXQgdGhpc1xuICAgIGlmIChcbiAgICAgIHRoaXMuY29sb3JzICYmXG4gICAgICB0aGlzLmNvbG9ycy5maWx0ZXIoKHgsIGkpID0+ICF0aGlzLmNvbG9yc0VxdWFsKHgsIHRoaXMub2xkLmNvbG9yc1tpXSkpXG4gICAgICAgIC5sZW5ndGhcbiAgICApIHtcbiAgICAgIHRoaXMub2xkLmNvbG9ycyA9IHRoaXMuY29sb3JzLm1hcCgoeCkgPT4gdGhpcy5jb3B5Q29sb3IoeCkpO1xuXG4gICAgICB0aGlzLnVwZGF0ZUNvbG9ycygpO1xuXG4gICAgICB3YW50VXBkYXRlKFVwZGF0ZVR5cGUuVXBkYXRlKTtcbiAgICB9XG5cbiAgICBpZiAoISF0aGlzLmxhYmVscyAhPT0gdGhpcy5vbGQubGFiZWxzRXhpc3QpIHtcbiAgICAgIHRoaXMub2xkLmxhYmVsc0V4aXN0ID0gISF0aGlzLmxhYmVscztcblxuICAgICAgd2FudFVwZGF0ZShVcGRhdGVUeXBlLlVwZGF0ZSk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdGhpcy5sYWJlbHMgJiZcbiAgICAgIHRoaXMubGFiZWxzLmZpbHRlcigoeCwgaSkgPT4gIXRoaXMubGFiZWxzRXF1YWwoeCwgdGhpcy5vbGQubGFiZWxzW2ldKSlcbiAgICAgICAgLmxlbmd0aFxuICAgICkge1xuICAgICAgdGhpcy5vbGQubGFiZWxzID0gdGhpcy5sYWJlbHMubWFwKCh4KSA9PiB0aGlzLmNvcHlMYWJlbCh4KSk7XG5cbiAgICAgIHdhbnRVcGRhdGUoVXBkYXRlVHlwZS5VcGRhdGUpO1xuICAgIH1cblxuICAgIGlmICghIXRoaXMub3B0aW9ucy5sZWdlbmQgIT09IHRoaXMub2xkLmxlZ2VuZEV4aXN0cykge1xuICAgICAgdGhpcy5vbGQubGVnZW5kRXhpc3RzID0gISF0aGlzLm9wdGlvbnMubGVnZW5kO1xuXG4gICAgICB3YW50VXBkYXRlKFVwZGF0ZVR5cGUuUmVmcmVzaCk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdGhpcy5vcHRpb25zLmxlZ2VuZCAmJlxuICAgICAgdGhpcy5vcHRpb25zLmxlZ2VuZC5wb3NpdGlvbiAhPT0gdGhpcy5vbGQubGVnZW5kLnBvc2l0aW9uXG4gICAgKSB7XG4gICAgICB0aGlzLm9sZC5sZWdlbmQucG9zaXRpb24gPSB0aGlzLm9wdGlvbnMubGVnZW5kLnBvc2l0aW9uO1xuXG4gICAgICB3YW50VXBkYXRlKFVwZGF0ZVR5cGUuUmVmcmVzaCk7XG4gICAgfVxuXG4gICAgc3dpdGNoICh1cGRhdGVSZXF1aXJlZCBhcyBVcGRhdGVUeXBlKSB7XG4gICAgICBjYXNlIFVwZGF0ZVR5cGUuRGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFVwZGF0ZVR5cGUuVXBkYXRlOlxuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVXBkYXRlVHlwZS5SZWZyZXNoOlxuICAgICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY29weUxhYmVsKGE6IENoYXJ0TGFiZWwpOiBDaGFydExhYmVsIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhKSkge1xuICAgICAgcmV0dXJuIFsuLi5hXTtcbiAgICB9XG4gICAgcmV0dXJuIGE7XG4gIH1cblxuICBsYWJlbHNFcXVhbChhOiBDaGFydExhYmVsLCBiOiBDaGFydExhYmVsKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRydWUgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoYSkgPT09IEFycmF5LmlzQXJyYXkoYikgJiZcbiAgICAgIChBcnJheS5pc0FycmF5KGEpIHx8IGEgPT09IGIpICYmXG4gICAgICAoIUFycmF5LmlzQXJyYXkoYSkgfHwgYS5sZW5ndGggPT09IGIubGVuZ3RoKSAmJlxuICAgICAgKCFBcnJheS5pc0FycmF5KGEpIHx8IGEuZmlsdGVyKCh4LCBpKSA9PiB4ICE9PSBiW2ldKS5sZW5ndGggPT09IDApXG4gICAgKTtcbiAgfVxuXG4gIGNvcHlDb2xvcihhOiBEYXRhc2V0Q29sb3IpOiBEYXRhc2V0Q29sb3Ige1xuICAgIGNvbnN0IHJjOiBEYXRhc2V0Q29sb3IgPSB7XG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6IGEuYmFja2dyb3VuZENvbG9yLFxuICAgICAgYm9yZGVyV2lkdGg6IGEuYm9yZGVyV2lkdGgsXG4gICAgICBib3JkZXJDb2xvcjogYS5ib3JkZXJDb2xvcixcbiAgICAgIGJvcmRlckNhcFN0eWxlOiBhLmJvcmRlckNhcFN0eWxlLFxuICAgICAgYm9yZGVyRGFzaDogYS5ib3JkZXJEYXNoLFxuICAgICAgYm9yZGVyRGFzaE9mZnNldDogYS5ib3JkZXJEYXNoT2Zmc2V0LFxuICAgICAgYm9yZGVySm9pblN0eWxlOiBhLmJvcmRlckpvaW5TdHlsZSxcbiAgICAgIHBvaW50Qm9yZGVyQ29sb3I6IGEucG9pbnRCb3JkZXJDb2xvcixcbiAgICAgIHBvaW50QmFja2dyb3VuZENvbG9yOiBhLnBvaW50QmFja2dyb3VuZENvbG9yLFxuICAgICAgcG9pbnRCb3JkZXJXaWR0aDogYS5wb2ludEJvcmRlcldpZHRoLFxuICAgICAgcG9pbnRSYWRpdXM6IGEucG9pbnRSYWRpdXMsXG4gICAgICBwb2ludEhvdmVyUmFkaXVzOiBhLnBvaW50SG92ZXJSYWRpdXMsXG4gICAgICBwb2ludEhpdFJhZGl1czogYS5wb2ludEhpdFJhZGl1cyxcbiAgICAgIHBvaW50SG92ZXJCYWNrZ3JvdW5kQ29sb3I6IGEucG9pbnRIb3ZlckJhY2tncm91bmRDb2xvcixcbiAgICAgIHBvaW50SG92ZXJCb3JkZXJDb2xvcjogYS5wb2ludEhvdmVyQm9yZGVyQ29sb3IsXG4gICAgICBwb2ludEhvdmVyQm9yZGVyV2lkdGg6IGEucG9pbnRIb3ZlckJvcmRlcldpZHRoLFxuICAgICAgcG9pbnRTdHlsZTogYS5wb2ludFN0eWxlLFxuICAgICAgaG92ZXJCYWNrZ3JvdW5kQ29sb3I6IGEuaG92ZXJCYWNrZ3JvdW5kQ29sb3IsXG4gICAgICBob3ZlckJvcmRlckNvbG9yOiBhLmhvdmVyQm9yZGVyQ29sb3IsXG4gICAgICBob3ZlckJvcmRlcldpZHRoOiBhLmhvdmVyQm9yZGVyV2lkdGgsXG4gICAgfTtcblxuICAgIHJldHVybiByYztcbiAgfVxuXG4gIGNvbG9yc0VxdWFsKGE6IERhdGFzZXRDb2xvciwgYjogRGF0YXNldENvbG9yKSB7XG4gICAgaWYgKCFhICE9PSAhYikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gKFxuICAgICAgIWEgfHxcbiAgICAgICh0cnVlICYmXG4gICAgICAgIGEuYmFja2dyb3VuZENvbG9yID09PSBiLmJhY2tncm91bmRDb2xvciAmJlxuICAgICAgICBhLmJvcmRlcldpZHRoID09PSBiLmJvcmRlcldpZHRoICYmXG4gICAgICAgIGEuYm9yZGVyQ29sb3IgPT09IGIuYm9yZGVyQ29sb3IgJiZcbiAgICAgICAgYS5ib3JkZXJDYXBTdHlsZSA9PT0gYi5ib3JkZXJDYXBTdHlsZSAmJlxuICAgICAgICBhLmJvcmRlckRhc2ggPT09IGIuYm9yZGVyRGFzaCAmJlxuICAgICAgICBhLmJvcmRlckRhc2hPZmZzZXQgPT09IGIuYm9yZGVyRGFzaE9mZnNldCAmJlxuICAgICAgICBhLmJvcmRlckpvaW5TdHlsZSA9PT0gYi5ib3JkZXJKb2luU3R5bGUgJiZcbiAgICAgICAgYS5wb2ludEJvcmRlckNvbG9yID09PSBiLnBvaW50Qm9yZGVyQ29sb3IgJiZcbiAgICAgICAgYS5wb2ludEJhY2tncm91bmRDb2xvciA9PT0gYi5wb2ludEJhY2tncm91bmRDb2xvciAmJlxuICAgICAgICBhLnBvaW50Qm9yZGVyV2lkdGggPT09IGIucG9pbnRCb3JkZXJXaWR0aCAmJlxuICAgICAgICBhLnBvaW50UmFkaXVzID09PSBiLnBvaW50UmFkaXVzICYmXG4gICAgICAgIGEucG9pbnRIb3ZlclJhZGl1cyA9PT0gYi5wb2ludEhvdmVyUmFkaXVzICYmXG4gICAgICAgIGEucG9pbnRIaXRSYWRpdXMgPT09IGIucG9pbnRIaXRSYWRpdXMgJiZcbiAgICAgICAgYS5wb2ludEhvdmVyQmFja2dyb3VuZENvbG9yID09PSBiLnBvaW50SG92ZXJCYWNrZ3JvdW5kQ29sb3IgJiZcbiAgICAgICAgYS5wb2ludEhvdmVyQm9yZGVyQ29sb3IgPT09IGIucG9pbnRIb3ZlckJvcmRlckNvbG9yICYmXG4gICAgICAgIGEucG9pbnRIb3ZlckJvcmRlcldpZHRoID09PSBiLnBvaW50SG92ZXJCb3JkZXJXaWR0aCAmJlxuICAgICAgICBhLnBvaW50U3R5bGUgPT09IGIucG9pbnRTdHlsZSAmJlxuICAgICAgICBhLmhvdmVyQmFja2dyb3VuZENvbG9yID09PSBiLmhvdmVyQmFja2dyb3VuZENvbG9yICYmXG4gICAgICAgIGEuaG92ZXJCb3JkZXJDb2xvciA9PT0gYi5ob3ZlckJvcmRlckNvbG9yICYmXG4gICAgICAgIGEuaG92ZXJCb3JkZXJXaWR0aCA9PT0gYi5ob3ZlckJvcmRlcldpZHRoKVxuICAgICk7XG4gIH1cblxuICB1cGRhdGVDb2xvcnMoKSB7XG4gICAgdGhpcy5kYXRhc2V0cy5mb3JFYWNoKChlbG0sIGluZGV4KSA9PiB7XG4gICAgICBpZiAodGhpcy5jb2xvcnMgJiYgdGhpcy5jb2xvcnNbaW5kZXhdKSB7XG4gICAgICAgIE9iamVjdC5hc3NpZ24oZWxtLCB0aGlzLmNvbG9yc1tpbmRleF0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihlbG0sIGdldENvbG9ycyh0aGlzLmNoYXJ0VHlwZSwgaW5kZXgsIGVsbS5kYXRhLmxlbmd0aCksIHtcbiAgICAgICAgICAuLi5lbG0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBsZXQgdXBkYXRlUmVxdWlyZWQgPSBVcGRhdGVUeXBlLkRlZmF1bHQ7XG