@nova-ui/charts
Version:
Nova Charts is a library created to provide potential consumers with solutions for various data visualizations that conform with the Nova Design Language. It's designed to solve common patterns identified by UX designers, but also be very flexible so that
171 lines • 26.6 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import cloneDeep from "lodash/cloneDeep";
import defaultsDeep from "lodash/defaultsDeep";
import isUndefined from "lodash/isUndefined";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
import { GAUGE_LABELS_CONTAINER_CLASS, GAUGE_LABEL_FORMATTER_NAME_DEFAULT, GAUGE_THRESHOLD_LABEL_CLASS, } from "./constants";
import { MOUSE_ACTIVE_EVENT, STANDARD_RENDER_LAYERS } from "../../../constants";
import { GAUGE_THRESHOLD_MARKERS_SERIES_ID } from "../../../gauge/constants";
import { RenderLayerName } from "../../../renderers/types";
import { ChartPlugin } from "../../common/chart-plugin";
import { LinearScale } from "../../common/scales/linear-scale";
/**
* A chart plugin that handles the rendering of labels for a donut gauge
*/
export class LinearGaugeLabelsPlugin extends ChartPlugin {
config;
/** The default plugin configuration */
DEFAULT_CONFIG = {
padding: 5,
formatterName: GAUGE_LABEL_FORMATTER_NAME_DEFAULT,
disableThresholdLabels: false,
flippedLabels: false,
};
destroy$ = new Subject();
lasagnaLayer;
isHorizontal = true;
thresholdsSeries;
constructor(config = {}) {
super();
this.config = config;
this.config = defaultsDeep(this.config, this.DEFAULT_CONFIG);
}
initialize() {
this.lasagnaLayer = this.chart.getGrid().getLasagna().addLayer({
name: GAUGE_LABELS_CONTAINER_CLASS,
order: STANDARD_RENDER_LAYERS[RenderLayerName.data].order,
clipped: false,
});
this.chart
.getEventBus()
.getStream(MOUSE_ACTIVE_EVENT)
.pipe(takeUntil(this.destroy$))
.subscribe((event) => {
const gaugeThresholdLabelsGroup = this.lasagnaLayer.select(`.${GAUGE_LABELS_CONTAINER_CLASS}`);
if (!gaugeThresholdLabelsGroup.empty()) {
gaugeThresholdLabelsGroup.style("opacity", event.data ? 1 : 0);
}
});
}
update() {
this.updateData();
this.drawThresholdLabels();
}
updateDimensions() {
this.updateData();
this.drawThresholdLabels();
}
destroy() {
if (this.destroy$) {
this.destroy$.next();
this.destroy$.complete();
}
}
updateData() {
this.thresholdsSeries = this.chart
.getDataManager()
.chartSeriesSet.find((series) => series.id === GAUGE_THRESHOLD_MARKERS_SERIES_ID);
this.isHorizontal =
this.thresholdsSeries?.scales.x instanceof LinearScale;
}
drawThresholdLabels() {
if (isUndefined(this.thresholdsSeries)) {
console.warn("Threshold series is undefined. As a result, threshold labels for the linear gauge will not be rendered.");
return;
}
let gaugeThresholdsLabelsGroup = this.lasagnaLayer.select(`.${GAUGE_LABELS_CONTAINER_CLASS}`);
if (gaugeThresholdsLabelsGroup.empty()) {
gaugeThresholdsLabelsGroup = this.lasagnaLayer
.append("svg:g")
.attr("class", GAUGE_LABELS_CONTAINER_CLASS)
.style("opacity", 0);
}
const data = cloneDeep(this.config.disableThresholdLabels
? []
: this.thresholdsSeries?.data);
if (isUndefined(data)) {
throw new Error("Gauge threshold series data is undefined");
}
// last value in the thresholds series is the max value of the gauge (needed by RadialGaugeThresholdsRenderer).
// removing this value to avoid rendering a label for it
data.pop();
const formatter = this.thresholdsSeries?.scales[this.isHorizontal ? "x" : "y"]
.formatters[this.config.formatterName] ?? ((d) => d);
const labelSelection = gaugeThresholdsLabelsGroup
.selectAll(`text.${GAUGE_THRESHOLD_LABEL_CLASS}`)
.data(data);
labelSelection.exit().remove();
labelSelection
.enter()
.append("text")
.attr("class", GAUGE_THRESHOLD_LABEL_CLASS)
.merge(labelSelection)
.attr("transform", (d, i) => `translate(${this.xTranslate(d, i)}, ${this.yTranslate(d, i)})`)
.attr("title", (d, i) => formatter(data[i].value))
.style("text-anchor", (d) => this.getTextAnchor())
.style("dominant-baseline", (d) => this.getAlignmentBaseline())
.text((d, i) => formatter(data[i].value));
}
xTranslate = (d, i) => {
if (this.isHorizontal) {
const thresholdsSeries = this
.thresholdsSeries;
const value = this.thresholdsSeries?.accessors?.data?.value?.(d, i, thresholdsSeries?.data, thresholdsSeries);
return this.thresholdsSeries?.scales.x.convert(value);
}
return this.getLabelOffset();
};
yTranslate = (d, i) => {
if (this.isHorizontal) {
return this.getLabelOffset();
}
const thresholdsSeries = this
.thresholdsSeries;
const value = this.thresholdsSeries?.accessors?.data?.value?.(d, i, thresholdsSeries?.data, thresholdsSeries);
return this.thresholdsSeries?.scales.y.convert(value);
};
getLabelOffset() {
let labelStart = 0;
if (!this.config.flippedLabels) {
const gridDimensions = this.chart.getGrid().config().dimension;
labelStart = this.isHorizontal
? gridDimensions.height()
: gridDimensions.width();
}
let padding = this.config.padding;
padding = this.config.flippedLabels ? -padding : padding;
return labelStart + padding;
}
getTextAnchor() {
if (this.isHorizontal) {
return "middle";
}
return this.config.flippedLabels ? "end" : "start";
}
getAlignmentBaseline() {
if (this.isHorizontal) {
return this.config.flippedLabels ? "text-after-edge" : "hanging";
}
return "central";
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluZWFyLWdhdWdlLWxhYmVscy1wbHVnaW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvY29yZS9wbHVnaW5zL2dhdWdlL2xpbmVhci1nYXVnZS1sYWJlbHMtcGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlEQUF5RDtBQUN6RCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0REFBNEQ7QUFDNUQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSx1REFBdUQ7QUFDdkQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLDBFQUEwRTtBQUMxRSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLGlCQUFpQjtBQUVqQixPQUFPLFNBQVMsTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLFlBQVksTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQ0gsNEJBQTRCLEVBQzVCLGtDQUFrQyxFQUNsQywyQkFBMkIsR0FDOUIsTUFBTSxhQUFhLENBQUM7QUFFckIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLHNCQUFzQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEYsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDN0UsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFTL0Q7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O1FBQ3pELE9BQU8sVUFBVSxHQUFHLE9BQU8sQ0FBQztJQUNoQyxDQUFDO0lBRU8sYUFBYTtRQUNqQixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDbkIsT0FBTyxRQUFRLENBQUM7U0FDbkI7UUFFRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUN2RCxDQUFDO0lBRU8sb0JBQW9CO1FBQ3hCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNuQixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1NBQ3BFO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDckIsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBjbG9uZURlZXAgZnJvbSBcImxvZGFzaC9jbG9uZURlZXBcIjtcbmltcG9ydCBkZWZhdWx0c0RlZXAgZnJvbSBcImxvZGFzaC9kZWZhdWx0c0RlZXBcIjtcbmltcG9ydCBpc1VuZGVmaW5lZCBmcm9tIFwibG9kYXNoL2lzVW5kZWZpbmVkXCI7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xuXG5pbXBvcnQge1xuICAgIEdBVUdFX0xBQkVMU19DT05UQUlORVJfQ0xBU1MsXG4gICAgR0FVR0VfTEFCRUxfRk9STUFUVEVSX05BTUVfREVGQVVMVCxcbiAgICBHQVVHRV9USFJFU0hPTERfTEFCRUxfQ0xBU1MsXG59IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSUdhdWdlTGFiZWxzUGx1Z2luQ29uZmlnIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IE1PVVNFX0FDVElWRV9FVkVOVCwgU1RBTkRBUkRfUkVOREVSX0xBWUVSUyB9IGZyb20gXCIuLi8uLi8uLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IEdBVUdFX1RIUkVTSE9MRF9NQVJLRVJTX1NFUklFU19JRCB9IGZyb20gXCIuLi8uLi8uLi9nYXVnZS9jb25zdGFudHNcIjtcbmltcG9ydCB7IFJlbmRlckxheWVyTmFtZSB9IGZyb20gXCIuLi8uLi8uLi9yZW5kZXJlcnMvdHlwZXNcIjtcbmltcG9ydCB7IENoYXJ0UGx1Z2luIH0gZnJvbSBcIi4uLy4uL2NvbW1vbi9jaGFydC1wbHVnaW5cIjtcbmltcG9ydCB7IExpbmVhclNjYWxlIH0gZnJvbSBcIi4uLy4uL2NvbW1vbi9zY2FsZXMvbGluZWFyLXNjYWxlXCI7XG5pbXBvcnQge1xuICAgIEQzU2VsZWN0aW9uLFxuICAgIElBY2Nlc3NvcnMsXG4gICAgSUNoYXJ0RXZlbnQsXG4gICAgSUNoYXJ0U2VyaWVzLFxuICAgIElEYXRhU2VyaWVzLFxufSBmcm9tIFwiLi4vLi4vY29tbW9uL3R5cGVzXCI7XG5cbi8qKlxuICogQSBjaGFydCBwbHVnaW4gdGhhdCBoYW5kbGVzIHRoZSByZW5kZXJpbmcgb2YgbGFiZWxzIGZvciBhIGRvbnV0IGdhdWdlXG4gKi9cbmV4cG9ydCBjbGFzcyBMaW5lYXJHYXVnZUxhYmVsc1BsdWdpbiBleHRlbmRzIENoYXJ0UGx1Z2luIHtcbiAgICAvKiogVGhlIGRlZmF1bHQgcGx1Z2luIGNvbmZpZ3VyYXRpb24gKi9cbiAgICBwdWJsaWMgREVGQVVMVF9DT05GSUc6IElHYXVnZUxhYmVsc1BsdWdpbkNvbmZpZyA9IHtcbiAgICAgICAgcGFkZGluZzogNSxcbiAgICAgICAgZm9ybWF0dGVyTmFtZTogR0FVR0VfTEFCRUxfRk9STUFUVEVSX05BTUVfREVGQVVMVCxcbiAgICAgICAgZGlzYWJsZVRocmVzaG9sZExhYmVsczogZmFsc2UsXG4gICAgICAgIGZsaXBwZWRMYWJlbHM6IGZhbHNlLFxuICAgIH07XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgICBwcml2YXRlIGxhc2FnbmFMYXllcjogRDNTZWxlY3Rpb248U1ZHRWxlbWVudD47XG4gICAgcHJpdmF0ZSBpc0hvcml6b250YWwgPSB0cnVlO1xuICAgIHByaXZhdGUgdGhyZXNob2xkc1NlcmllczogSUNoYXJ0U2VyaWVzPElBY2Nlc3NvcnM8YW55Pj4gfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgY29uZmlnOiBJR2F1Z2VMYWJlbHNQbHVnaW5Db25maWcgPSB7fSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGRlZmF1bHRzRGVlcCh0aGlzLmNvbmZpZywgdGhpcy5ERUZBVUxUX0NPTkZJRyk7XG4gICAgfVxuXG4gICAgcHVibGljIGluaXRpYWxpemUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubGFzYWduYUxheWVyID0gdGhpcy5jaGFydC5nZXRHcmlkKCkuZ2V0TGFzYWduYSgpLmFkZExheWVyKHtcbiAgICAgICAgICAgIG5hbWU6IEdBVUdFX0xBQkVMU19DT05UQUlORVJfQ0xBU1MsXG4gICAgICAgICAgICBvcmRlcjogU1RBTkRBUkRfUkVOREVSX0xBWUVSU1tSZW5kZXJMYXllck5hbWUuZGF0YV0ub3JkZXIsXG4gICAgICAgICAgICBjbGlwcGVkOiBmYWxzZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5jaGFydFxuICAgICAgICAgICAgLmdldEV2ZW50QnVzKClcbiAgICAgICAgICAgIC5nZXRTdHJlYW0oTU9VU0VfQUNUSVZFX0VWRU5UIGFzIHN0cmluZylcbiAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKGV2ZW50OiBJQ2hhcnRFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGdhdWdlVGhyZXNob2xkTGFiZWxzR3JvdXAgPSB0aGlzLmxhc2FnbmFMYXllci5zZWxlY3QoXG4gICAgICAgICAgICAgICAgICAgIGAuJHtHQVVHRV9MQUJFTFNfQ09OVEFJTkVSX0NMQVNTfWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmICghZ2F1Z2VUaHJlc2hvbGRMYWJlbHNHcm91cC5lbXB0eSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGdhdWdlVGhyZXNob2xkTGFiZWxzR3JvdXAuc3R5bGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBcIm9wYWNpdHlcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LmRhdGEgPyAxIDogMFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXBkYXRlRGF0YSgpO1xuICAgICAgICB0aGlzLmRyYXdUaHJlc2hvbGRMYWJlbHMoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlRGltZW5zaW9ucygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy51cGRhdGVEYXRhKCk7XG4gICAgICAgIHRoaXMuZHJhd1RocmVzaG9sZExhYmVscygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBkZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5kZXN0cm95JCkge1xuICAgICAgICAgICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgIHRoaXMudGhyZXNob2xkc1NlcmllcyA9IHRoaXMuY2hhcnRcbiAgICAgICAgICAgIC5nZXREYXRhTWFuYWdlcigpXG4gICAgICAgICAgICAuY2hhcnRTZXJpZXNTZXQuZmluZChcbiAgICAgICAgICAgICAgICAoc2VyaWVzOiBJQ2hhcnRTZXJpZXM8SUFjY2Vzc29yczxhbnk+PikgPT5cbiAgICAgICAgICAgICAgICAgICAgc2VyaWVzLmlkID09PSBHQVVHRV9USFJFU0hPTERfTUFSS0VSU19TRVJJRVNfSURcbiAgICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuaXNIb3Jpem9udGFsID1cbiAgICAgICAgICAgIHRoaXMudGhyZXNob2xkc1Nlcmllcz8uc2NhbGVzLnggaW5zdGFuY2VvZiBMaW5lYXJTY2FsZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGRyYXdUaHJlc2hvbGRMYWJlbHMoKSB7XG4gICAgICAgIGlmIChpc1VuZGVmaW5lZCh0aGlzLnRocmVzaG9sZHNTZXJpZXMpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgXCJUaHJlc2hvbGQgc2VyaWVzIGlzIHVuZGVmaW5lZC4gQXMgYSByZXN1bHQsIHRocmVzaG9sZCBsYWJlbHMgZm9yIHRoZSBsaW5lYXIgZ2F1Z2Ugd2lsbCBub3QgYmUgcmVuZGVyZWQuXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZ2F1Z2VUaHJlc2hvbGRzTGFiZWxzR3JvdXAgPSB0aGlzLmxhc2FnbmFMYXllci5zZWxlY3QoXG4gICAgICAgICAgICBgLiR7R0FVR0VfTEFCRUxTX0NPTlRBSU5FUl9DTEFTU31gXG4gICAgICAgICk7XG4gICAgICAgIGlmIChnYXVnZVRocmVzaG9sZHNMYWJlbHNHcm91cC5lbXB0eSgpKSB7XG4gICAgICAgICAgICBnYXVnZVRocmVzaG9sZHNMYWJlbHNHcm91cCA9IHRoaXMubGFzYWduYUxheWVyXG4gICAgICAgICAgICAgICAgLmFwcGVuZChcInN2ZzpnXCIpXG4gICAgICAgICAgICAgICAgLmF0dHIoXCJjbGFzc1wiLCBHQVVHRV9MQUJFTFNfQ09OVEFJTkVSX0NMQVNTKVxuICAgICAgICAgICAgICAgIC5zdHlsZShcIm9wYWNpdHlcIiwgMCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkYXRhID0gY2xvbmVEZWVwKFxuICAgICAgICAgICAgdGhpcy5jb25maWcuZGlzYWJsZVRocmVzaG9sZExhYmVsc1xuICAgICAgICAgICAgICAgID8gW11cbiAgICAgICAgICAgICAgICA6IHRoaXMudGhyZXNob2xkc1Nlcmllcz8uZGF0YVxuICAgICAgICApO1xuICAgICAgICBpZiAoaXNVbmRlZmluZWQoZGF0YSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdhdWdlIHRocmVzaG9sZCBzZXJpZXMgZGF0YSBpcyB1bmRlZmluZWRcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBsYXN0IHZhbHVlIGluIHRoZSB0aHJlc2hvbGRzIHNlcmllcyBpcyB0aGUgbWF4IHZhbHVlIG9mIHRoZSBnYXVnZSAobmVlZGVkIGJ5IFJhZGlhbEdhdWdlVGhyZXNob2xkc1JlbmRlcmVyKS5cbiAgICAgICAgLy8gcmVtb3ZpbmcgdGhpcyB2YWx1ZSB0byBhdm9pZCByZW5kZXJpbmcgYSBsYWJlbCBmb3IgaXRcbiAgICAgICAgZGF0YS5wb3AoKTtcblxuICAgICAgICBjb25zdCBmb3JtYXR0ZXIgPVxuICAgICAgICAgICAgdGhpcy50aHJlc2hvbGRzU2VyaWVzPy5zY2FsZXNbdGhpcy5pc0hvcml6b250YWwgPyBcInhcIiA6IFwieVwiXVxuICAgICAgICAgICAgICAgIC5mb3JtYXR0ZXJzW3RoaXMuY29uZmlnLmZvcm1hdHRlck5hbWUgYXMgc3RyaW5nXSA/PyAoKGQpID0+IGQpO1xuICAgICAgICBjb25zdCBsYWJlbFNlbGVjdGlvbiA9IGdhdWdlVGhyZXNob2xkc0xhYmVsc0dyb3VwXG4gICAgICAgICAgICAuc2VsZWN0QWxsKGB0ZXh0LiR7R0FVR0VfVEhSRVNIT0xEX0xBQkVMX0NMQVNTfWApXG4gICAgICAgICAgICAuZGF0YShkYXRhKTtcblxuICAgICAgICBsYWJlbFNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIGxhYmVsU2VsZWN0aW9uXG4gICAgICAgICAgICAuZW50ZXIoKVxuICAgICAgICAgICAgLmFwcGVuZChcInRleHRcIilcbiAgICAgICAgICAgIC5hdHRyKFwiY2xhc3NcIiwgR0FVR0VfVEhSRVNIT0xEX0xBQkVMX0NMQVNTKVxuICAgICAgICAgICAgLm1lcmdlKGxhYmVsU2VsZWN0aW9uIGFzIGFueSlcbiAgICAgICAgICAgIC5hdHRyKFxuICAgICAgICAgICAgICAgIFwidHJhbnNmb3JtXCIsXG4gICAgICAgICAgICAgICAgKGQsIGkpID0+XG4gICAgICAgICAgICAgICAgICAgIGB0cmFuc2xhdGUoJHt0aGlzLnhUcmFuc2xhdGUoZCwgaSl9LCAke3RoaXMueVRyYW5zbGF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIGQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpXG4gICAgICAgICAgICAgICAgICAgICl9KWBcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5hdHRyKFwidGl0bGVcIiwgKGQsIGkpID0+IGZvcm1hdHRlcihkYXRhW2ldLnZhbHVlKSlcbiAgICAgICAgICAgIC5zdHlsZShcInRleHQtYW5jaG9yXCIsIChkKSA9PiB0aGlzLmdldFRleHRBbmNob3IoKSlcbiAgICAgICAgICAgIC5zdHlsZShcImRvbWluYW50LWJhc2VsaW5lXCIsIChkKSA9PiB0aGlzLmdldEFsaWdubWVudEJhc2VsaW5lKCkpXG4gICAgICAgICAgICAudGV4dCgoZCwgaSkgPT4gZm9ybWF0dGVyKGRhdGFbaV0udmFsdWUpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHhUcmFuc2xhdGUgPSAoZDogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICBjb25zdCB0aHJlc2hvbGRzU2VyaWVzID0gdGhpc1xuICAgICAgICAgICAgICAgIC50aHJlc2hvbGRzU2VyaWVzIGFzIElEYXRhU2VyaWVzPElBY2Nlc3NvcnM+O1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnRocmVzaG9sZHNTZXJpZXM/LmFjY2Vzc29ycz8uZGF0YT8udmFsdWU/LihcbiAgICAgICAgICAgICAgICBkLFxuICAgICAgICAgICAgICAgIGksXG4gICAgICAgICAgICAgICAgdGhyZXNob2xkc1Nlcmllcz8uZGF0YSBhcyBhbnlbXSxcbiAgICAgICAgICAgICAgICB0aHJlc2hvbGRzU2VyaWVzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGhyZXNob2xkc1Nlcmllcz8uc2NhbGVzLnguY29udmVydCh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRMYWJlbE9mZnNldCgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHlUcmFuc2xhdGUgPSAoZDogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRMYWJlbE9mZnNldCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGhyZXNob2xkc1NlcmllcyA9IHRoaXNcbiAgICAgICAgICAgIC50aHJlc2hvbGRzU2VyaWVzIGFzIElEYXRhU2VyaWVzPElBY2Nlc3NvcnM+O1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMudGhyZXNob2xkc1Nlcmllcz8uYWNjZXNzb3JzPy5kYXRhPy52YWx1ZT8uKFxuICAgICAgICAgICAgZCxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICB0aHJlc2hvbGRzU2VyaWVzPy5kYXRhIGFzIGFueVtdLFxuICAgICAgICAgICAgdGhyZXNob2xkc1Nlcmllc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdGhpcy50aHJlc2hvbGRzU2VyaWVzPy5zY2FsZXMueS5jb252ZXJ0KHZhbHVlKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBnZXRMYWJlbE9mZnNldCgpIHtcbiAgICAgICAgbGV0IGxhYmVsU3RhcnQgPSAwO1xuICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmZsaXBwZWRMYWJlbHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGdyaWREaW1lbnNpb25zID0gdGhpcy5jaGFydC5nZXRHcmlkKCkuY29uZmlnKCkuZGltZW5zaW9uO1xuICAgICAgICAgICAgbGFiZWxTdGFydCA9IHRoaXMuaXNIb3Jpem9udGFsXG4gICAgICAgICAgICAgICAgPyBncmlkRGltZW5zaW9ucy5oZWlnaHQoKVxuICAgICAgICAgICAgICAgIDogZ3JpZERpbWVuc2lvbnMud2lkdGgoKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcGFkZGluZyA9IHRoaXMuY29uZmlnLnBhZGRpbmcgYXMgbnVtYmVyO1xuICAgICAgICBwYWRkaW5nID0gdGhpcy5jb25maWcuZmxpcHBlZExhYmVscyA/IC1wYWRkaW5nIDogcGFkZGluZztcbiAgICAgICAgcmV0dXJuIGxhYmVsU3RhcnQgKyBwYWRkaW5nO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0VGV4dEFuY2hvcigpOiBzdHJpbmcge1xuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBcIm1pZGRsZVwiO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmZsaXBwZWRMYWJlbHMgPyBcImVuZFwiIDogXCJzdGFydFwiO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0QWxpZ25tZW50QmFzZWxpbmUoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZmxpcHBlZExhYmVscyA/IFwidGV4dC1hZnRlci1lZGdlXCIgOiBcImhhbmdpbmdcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBcImNlbnRyYWxcIjtcbiAgICB9XG59XG4iXX0=