@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
180 lines • 28.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 { arc } from "d3-shape";
import defaultsDeep from "lodash/defaultsDeep";
import isUndefined from "lodash/isUndefined";
import { DATA_POINT_NOT_FOUND, HIGHLIGHT_DATA_POINT_EVENT, HIGHLIGHT_SERIES_EVENT, INTERACTION_DATA_POINTS_EVENT, SELECT_DATA_POINT_EVENT, } from "../../constants";
import { Renderer } from "../../core/common/renderer";
import { InteractionType, } from "../../core/common/types";
import { RenderLayerName } from "../types";
/**
* Default configuration for Radial Renderer
*/
export const DEFAULT_RADIAL_RENDERER_CONFIG = {
annularWidth: 20,
annularPadding: 5,
maxThickness: 30,
annularGrowth: 0.15,
cursor: "default",
enableSeriesHighlighting: true,
enableDataPointHighlighting: true,
};
/**
* Radial renderer is a generic renderer that is able to draw pie and donut charts
*/
export class RadialRenderer extends Renderer {
config;
segmentWidth;
/**
* Creates an instance of RadialRenderer.
* @param {IRadialRendererConfig} [config]
* Renderer configuration object. Defaults to `DEFAULT_RADIAL_RENDERER_CONFIG` constant value.
*/
constructor(config = {}) {
super(config);
this.config = config;
this.config = defaultsDeep(this.config, DEFAULT_RADIAL_RENDERER_CONFIG);
}
/** See {@link Renderer#draw} */
draw(renderSeries, rendererSubject) {
const dataContainer = renderSeries.containers[RenderLayerName.data];
const data = renderSeries.dataSeries.data;
const accessors = renderSeries.dataSeries.accessors;
// TODO: This handles several data points withing one series as well. Most probably this can be abstracted to other renderer
const arcGenerator = (d, index) => {
const separateArc = this.getArc(renderSeries.scales.r.range(), arc(), index);
return separateArc(d);
};
this.segmentWidth = this.getSegmentWidth(renderSeries);
const g = dataContainer.selectAll("path.arc").data(data);
g.exit().remove();
g.enter()
.append("path")
.attr("class", "arc pointer-events nui-chart--path__outline")
.style("stroke-width", this.config.strokeWidth)
.style("cursor", this.config.cursor)
.on("mouseenter", (d, i) => {
this.emitDataPointHighlight(renderSeries, d, i, rendererSubject);
})
.on("mouseleave", (d, i) => {
this.emitDataPointHighlight(renderSeries, null, DATA_POINT_NOT_FOUND, rendererSubject);
})
// TODO: testing event, remove in favor or generic interaction setup
.on("click", (d, i) => {
rendererSubject.next({
eventName: SELECT_DATA_POINT_EVENT,
data: {
seriesId: renderSeries.dataSeries.id,
index: i,
data: d.data,
position: this.getDataPointPosition(renderSeries.dataSeries, i, renderSeries.scales),
},
});
})
.merge(g)
.attr("d", arcGenerator)
.attr("fill", (d, i) => accessors.data.color
? accessors.data.color(d.data, i, data, renderSeries.dataSeries)
: accessors.series.color?.(renderSeries.dataSeries.id, renderSeries.dataSeries));
}
/** See {@link Renderer#getDataPointPosition} */
getDataPointPosition(dataSeries, index, scales) {
if (index < 0) {
return undefined;
}
const pieArcData = dataSeries.data[index];
const dataPointArc = this.getArc(scales.r.range(), arc(), index);
const centroid = dataPointArc.centroid(pieArcData);
return {
x: centroid[0],
y: centroid[1],
width: 0,
height: 0,
};
}
getInnerRadius(range, index) {
if (isUndefined(this.segmentWidth) ||
isUndefined(this.config.annularPadding)) {
throw new Error("Can't compute inner radius");
}
const calculatedRadius = range[1] -
range[0] -
this.segmentWidth -
index * (this.config.annularPadding + this.segmentWidth);
return calculatedRadius >= 0 ? calculatedRadius : 0;
}
getOuterRadius(range, index) {
if (isUndefined(this.segmentWidth) ||
isUndefined(this.config.annularPadding)) {
throw new Error("Can't compute outer radius");
}
const calculatedRadius = range[1] -
range[0] -
index * (this.config.annularPadding + this.segmentWidth);
return calculatedRadius >= 0 ? calculatedRadius : 0;
}
getArc(range, generatedArc, index) {
const innerRadius = this.getInnerRadius(range, index);
return generatedArc
.outerRadius(this.getOuterRadius(range, index))
.innerRadius(innerRadius);
}
getSegmentWidth(renderSeries) {
if (!(this.config.maxThickness && this.config.annularGrowth)) {
return this.config.annularWidth;
}
return Math.min((renderSeries.scales.r.range()[1] -
renderSeries.scales.r.range()[0]) *
this.config.annularGrowth, this.config.maxThickness);
}
emitDataPointHighlight(renderSeries, data, i, rendererSubject) {
const position = this.getDataPointPosition(renderSeries.dataSeries, i, renderSeries.scales);
const dataPoint = {
seriesId: renderSeries.dataSeries.id,
dataSeries: renderSeries.dataSeries,
index: i,
data: data,
position: position,
};
if (this.config.enableSeriesHighlighting) {
rendererSubject.next({
eventName: HIGHLIGHT_SERIES_EVENT,
data: dataPoint,
});
}
if (this.config.enableDataPointHighlighting) {
rendererSubject.next({
eventName: HIGHLIGHT_DATA_POINT_EVENT,
data: dataPoint,
});
}
// we're emitting this event manually, because it's not triggered by mouse interactive area in this case
rendererSubject.next({
eventName: INTERACTION_DATA_POINTS_EVENT,
data: {
interactionType: InteractionType.MouseMove,
dataPoints: {
[renderSeries.dataSeries.id]: dataPoint,
},
},
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFkaWFsLXJlbmRlcmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3JlbmRlcmVycy9yYWRpYWwvcmFkaWFsLXJlbmRlcmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlEQUF5RDtBQUN6RCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0REFBNEQ7QUFDNUQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSx1REFBdUQ7QUFDdkQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLDBFQUEwRTtBQUMxRSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLGlCQUFpQjtBQUVqQixPQUFPLEVBQU8sR0FBRyxFQUFvQixNQUFNLFVBQVUsQ0FBQztBQUN0RCxPQUFPLFlBQVksTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQztBQUc3QyxPQUFPLEVBQ0gsb0JBQW9CLEVBQ3BCLDBCQUEwQixFQUMxQixzQkFBc0IsRUFDdEIsNkJBQTZCLEVBQzdCLHVCQUF1QixHQUMxQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUV0RCxPQUFPLEVBR0gsZUFBZSxHQUlsQixNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFBaUIsZUFBZSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRzFEOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQTBCO0lBQ2pFLFlBQVksRUFBRSxFQUFFO0lBQ2hCLGNBQWMsRUFBRSxDQUFDO0lBQ2pCLFlBQVksRUFBRSxFQUFFO0lBQ2hCLGFBQWEsRUFBRSxJQUFJO0lBQ25CLE1BQU0sRUFBRSxTQUFTO0lBQ2pCLHdCQUF3QixFQUFFLElBQUk7SUFDOUIsMkJB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UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsMkJBQTJCLEVBQUU7WUFDekMsZUFBZSxDQUFDLElBQUksQ0FBQztnQkFDakIsU0FBUyxFQUFFLDBCQUEwQjtnQkFDckMsSUFBSSxFQUFFLFNBQVM7YUFDbEIsQ0FBQyxDQUFDO1NBQ047UUFFRCx3R0FBd0c7UUFDeEcsZUFBZSxDQUFDLElBQUksQ0FBQztZQUNqQixTQUFTLEVBQUUsNkJBQTZCO1lBQ3hDLElBQUksRUFBRTtnQkFDRixlQUFlLEVBQUUsZUFBZSxDQUFDLFNBQVM7Z0JBQzFDLFVBQVUsRUFBRTtvQkFDUixDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsU0FBUztpQkFDMUM7YUFDSjtTQUNKLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbIi8vIMKpIDIwMjIgU29sYXJXaW5kcyBXb3JsZHdpZGUsIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyAgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG9cbi8vICBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vICBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyAgVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgeyBBcmMsIGFyYywgRGVmYXVsdEFyY09iamVjdCB9IGZyb20gXCJkMy1zaGFwZVwiO1xuaW1wb3J0IGRlZmF1bHRzRGVlcCBmcm9tIFwibG9kYXNoL2RlZmF1bHRzRGVlcFwiO1xuaW1wb3J0IGlzVW5kZWZpbmVkIGZyb20gXCJsb2Rhc2gvaXNVbmRlZmluZWRcIjtcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tIFwicnhqc1wiO1xuXG5pbXBvcnQge1xuICAgIERBVEFfUE9JTlRfTk9UX0ZPVU5ELFxuICAgIEhJR0hMSUdIVF9EQVRBX1BPSU5UX0VWRU5ULFxuICAgIEhJR0hMSUdIVF9TRVJJRVNfRVZFTlQsXG4gICAgSU5URVJBQ1RJT05fREFUQV9QT0lOVFNfRVZFTlQsXG4gICAgU0VMRUNUX0RBVEFfUE9JTlRfRVZFTlQsXG59IGZyb20gXCIuLi8uLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFJlbmRlcmVyIH0gZnJvbSBcIi4uLy4uL2NvcmUvY29tbW9uL3JlbmRlcmVyXCI7XG5pbXBvcnQgeyBTY2FsZXMgfSBmcm9tIFwiLi4vLi4vY29yZS9jb21tb24vc2NhbGVzL3R5cGVzXCI7XG5pbXBvcnQge1xuICAgIElEYXRhUG9pbnQsXG4gICAgSURhdGFTZXJpZXMsXG4gICAgSW50ZXJhY3Rpb25UeXBlLFxuICAgIElQb3NpdGlvbixcbiAgICBJUmFkaWFsUmVuZGVyZXJDb25maWcsXG4gICAgSVJlbmRlcmVyRXZlbnRQYXlsb2FkLFxufSBmcm9tIFwiLi4vLi4vY29yZS9jb21tb24vdHlwZXNcIjtcbmltcG9ydCB7IElSZW5kZXJTZXJpZXMsIFJlbmRlckxheWVyTmFtZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgSVJhZGlhbEFjY2Vzc29ycyB9IGZyb20gXCIuL2FjY2Vzc29ycy9yYWRpYWwtYWNjZXNzb3JzXCI7XG5cbi8qKlxuICogRGVmYXVsdCBjb25maWd1cmF0aW9uIGZvciBSYWRpYWwgUmVuZGVyZXJcbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfUkFESUFMX1JFTkRFUkVSX0NPTkZJRzogSVJhZGlhbFJlbmRlcmVyQ29uZmlnID0ge1xuICAgIGFubnVsYXJXaWR0aDogMjAsXG4gICAgYW5udWxhclBhZGRpbmc6IDUsXG4gICAgbWF4VGhpY2tuZXNzOiAzMCxcbiAgICBhbm51bGFyR3Jvd3RoOiAwLjE1LFxuICAgIGN1cnNvcjogXCJkZWZhdWx0XCIsXG4gICAgZW5hYmxlU2VyaWVzSGlnaGxpZ2h0aW5nOiB0cnVlLFxuICAgIGVuYWJsZURhdGFQb2ludEhpZ2hsaWdodGluZzogdHJ1ZSxcbn07XG5cbi8qKlxuICogUmFkaWFsIHJlbmRlcmVyIGlzIGEgZ2VuZXJpYyByZW5kZXJlciB0aGF0IGlzIGFibGUgdG8gZHJhdyBwaWUgYW5kIGRvbnV0IGNoYXJ0c1xuICovXG5leHBvcnQgY2xhc3MgUmFkaWFsUmVuZGVyZXIgZXh0ZW5kcyBSZW5kZXJlcjxJUmFkaWFsQWNjZXNzb3JzPiB7XG4gICAgcHJvdGVjdGVkIHNlZ21lbnRXaWR0aD86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgUmFkaWFsUmVuZGVyZXIuXG4gICAgICogQHBhcmFtIHtJUmFkaWFsUmVuZGVyZXJDb25maWd9IFtjb25maWddXG4gICAgICogUmVuZGVyZXIgY29uZmlndXJhdGlvbiBvYmplY3QuIERlZmF1bHRzIHRvIGBERUZBVUxUX1JBRElBTF9SRU5ERVJFUl9DT05GSUdgIGNvbnN0YW50IHZhbHVlLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBjb25maWc6IElSYWRpYWxSZW5kZXJlckNvbmZpZyA9IHt9KSB7XG4gICAgICAgIHN1cGVyKGNvbmZpZyk7XG4gICAgICAgIHRoaXMuY29uZmlnID0gZGVmYXVsdHNEZWVwKHRoaXMuY29uZmlnLCBERUZBVUxUX1JBRElBTF9SRU5ERVJFUl9DT05GSUcpO1xuICAgIH1cblxuICAgIC8qKiBTZWUge0BsaW5rIFJlbmRlcmVyI2RyYXd9ICovXG4gICAgcHVibGljIGRyYXcoXG4gICAgICAgIHJlbmRlclNlcmllczogSVJlbmRlclNlcmllczxJUmFkaWFsQWNjZXNzb3JzPixcbiAgICAgICAgcmVuZGVyZXJTdWJqZWN0OiBTdWJqZWN0PElSZW5kZXJlckV2ZW50UGF5bG9hZD5cbiAgICApOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZGF0YUNvbnRhaW5lciA9IHJlbmRlclNlcmllcy5jb250YWluZXJzW1JlbmRlckxheWVyTmFtZS5kYXRhXTtcblxuICAgICAgICBjb25zdCBkYXRhID0gcmVuZGVyU2VyaWVzLmRhdGFTZXJpZXMuZGF0YTtcbiAgICAgICAgY29uc3QgYWNjZXNzb3JzID0gcmVuZGVyU2VyaWVzLmRhdGFTZXJpZXMuYWNjZXNzb3JzO1xuXG4gICAgICAgIC8vIFRPRE86IFRoaXMgaGFuZGxlcyBzZXZlcmFsIGRhdGEgcG9pbnRzIHdpdGhpbmcgb25lIHNlcmllcyBhcyB3ZWxsLiBNb3N0IHByb2JhYmx5IHRoaXMgY2FuIGJlIGFic3RyYWN0ZWQgdG8gb3RoZXIgcmVuZGVyZXJcbiAgICAgICAgY29uc3QgYXJjR2VuZXJhdG9yID0gKGQ6IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2VwYXJhdGVBcmMgPSB0aGlzLmdldEFyYyhcbiAgICAgICAgICAgICAgICByZW5kZXJTZXJpZXMuc2NhbGVzLnIucmFuZ2UoKSxcbiAgICAgICAgICAgICAgICBhcmMoKSxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBzZXBhcmF0ZUFyYyhkKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZWdtZW50V2lkdGggPSB0aGlzLmdldFNlZ21lbnRXaWR0aChyZW5kZXJTZXJpZXMpO1xuXG4gICAgICAgIGNvbnN0IGc6IGFueSA9IGRhdGFDb250YWluZXIuc2VsZWN0QWxsKFwicGF0aC5hcmNcIikuZGF0YShkYXRhKTtcblxuICAgICAgICBnLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICBnLmVudGVyKClcbiAgICAgICAgICAgIC5hcHBlbmQoXCJwYXRoXCIpXG4gICAgICAgICAgICAuYXR0cihcImNsYXNzXCIsIFwiYXJjIHBvaW50ZXItZXZlbnRzIG51aS1jaGFydC0tcGF0aF9fb3V0bGluZVwiKVxuICAgICAgICAgICAgLnN0eWxlKFwic3Ryb2tlLXdpZHRoXCIsIHRoaXMuY29uZmlnLnN0cm9rZVdpZHRoKVxuICAgICAgICAgICAgLnN0eWxlKFwiY3Vyc29yXCIsIHRoaXMuY29uZmlnLmN1cnNvcilcbiAgICAgICAgICAgIC5vbihcIm1vdXNlZW50ZXJcIiwgKGQ6IGFueSwgaTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RGF0YVBvaW50SGlnaGxpZ2h0KFxuICAgICAgICAgICAgICAgICAgICByZW5kZXJTZXJpZXMsXG4gICAgICAgICAgICAgICAgICAgIGQsXG4gICAgICAgICAgICAgICAgICAgIGksXG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVyU3ViamVjdFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKFwibW91c2VsZWF2ZVwiLCAoZDogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXREYXRhUG9pbnRIaWdobGlnaHQoXG4gICAgICAgICAgICAgICAgICAgIHJlbmRlclNlcmllcyxcbiAgICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgREFUQV9QT0lOVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVyU3ViamVjdFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLy8gVE9ETzogdGVzdGluZyBldmVudCwgcmVtb3ZlIGluIGZhdm9yIG9yIGdlbmVyaWMgaW50ZXJhY3Rpb24gc2V0dXBcbiAgICAgICAgICAgIC5vbihcImNsaWNrXCIsIChkOiBhbnksIGk6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgIHJlbmRlcmVyU3ViamVjdC5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnROYW1lOiBTRUxFQ1RfREFUQV9QT0lOVF9FVkVOVCxcbiAgICAgICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VyaWVzSWQ6IHJlbmRlclNlcmllcy5kYXRhU2VyaWVzLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg6IGksXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBkLmRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogdGhpcy5nZXREYXRhUG9pbnRQb3NpdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJTZXJpZXMuZGF0YVNlcmllcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlclNlcmllcy5zY2FsZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm1lcmdlKGcpXG4gICAgICAgICAgICAuYXR0cihcImRcIiwgYXJjR2VuZXJhdG9yKVxuICAgICAgICAgICAgLmF0dHIoXCJmaWxsXCIsIChkOiBhbnksIGk6IG51bWJlcikgPT5cbiAgICAgICAgICAgICAgICBhY2Nlc3NvcnMuZGF0YS5jb2xvclxuICAgICAgICAgICAgICAgICAgICA/IGFjY2Vzc29ycy5kYXRhLmNvbG9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBkLmRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlclNlcmllcy5kYXRhU2VyaWVzXG4gICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICA6IGFjY2Vzc29ycy5zZXJpZXMuY29sb3I/LihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyU2VyaWVzLmRhdGFTZXJpZXMuaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlclNlcmllcy5kYXRhU2VyaWVzXG4gICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKiogU2VlIHtAbGluayBSZW5kZXJlciNnZXREYXRhUG9pbnRQb3NpdGlvbn0gKi9cbiAgICBwdWJsaWMgZ2V0RGF0YVBvaW50UG9zaXRpb24oXG4gICAgICAgIGRhdGFTZXJpZXM6IElEYXRhU2VyaWVzPElSYWRpYWxBY2Nlc3NvcnM+LFxuICAgICAgICBpbmRleDogbnVtYmVyLFxuICAgICAgICBzY2FsZXM6IFNjYWxlc1xuICAgICk6IElQb3NpdGlvbiB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGllQXJjRGF0YTogRGVmYXVsdEFyY09iamVjdCA9IGRhdGFTZXJpZXMuZGF0YVtpbmRleF07XG4gICAgICAgIGNvbnN0IGRhdGFQb2ludEFyYyA9IHRoaXMuZ2V0QXJjKHNjYWxlcy5yLnJhbmdlKCksIGFyYygpLCBpbmRleCk7XG4gICAgICAgIGNvbnN0IGNlbnRyb2lkID0gZGF0YVBvaW50QXJjLmNlbnRyb2lkKHBpZUFyY0RhdGEpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiBjZW50cm9pZFswXSxcbiAgICAgICAgICAgIHk6IGNlbnRyb2lkWzFdLFxuICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICBoZWlnaHQ6IDAsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHVibGljIGdldElubmVyUmFkaXVzKHJhbmdlOiBudW1iZXJbXSwgaW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGlzVW5kZWZpbmVkKHRoaXMuc2VnbWVudFdpZHRoKSB8fFxuICAgICAgICAgICAgaXNVbmRlZmluZWQodGhpcy5jb25maWcuYW5udWxhclBhZGRpbmcpXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgY29tcHV0ZSBpbm5lciByYWRpdXNcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjYWxjdWxhdGVkUmFkaXVzID1cbiAgICAgICAgICAgIHJhbmdlWzFdIC1cbiAgICAgICAgICAgIHJhbmdlWzBdIC1cbiAgICAgICAgICAgIHRoaXMuc2VnbWVudFdpZHRoIC1cbiAgICAgICAgICAgIGluZGV4ICogKHRoaXMuY29uZmlnLmFubnVsYXJQYWRkaW5nICsgdGhpcy5zZWdtZW50V2lkdGgpO1xuICAgICAgICByZXR1cm4gY2FsY3VsYXRlZFJhZGl1cyA+PSAwID8gY2FsY3VsYXRlZFJhZGl1cyA6IDA7XG4gICAgfVxuXG4gICAgcHVibGljIGdldE91dGVyUmFkaXVzKHJhbmdlOiBbbnVtYmVyLCBudW1iZXJdLCBpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgaXNVbmRlZmluZWQodGhpcy5zZWdtZW50V2lkdGgpIHx8XG4gICAgICAgICAgICBpc1VuZGVmaW5lZCh0aGlzLmNvbmZpZy5hbm51bGFyUGFkZGluZylcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4ndCBjb21wdXRlIG91dGVyIHJhZGl1c1wiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNhbGN1bGF0ZWRSYWRpdXMgPVxuICAgICAgICAgICAgcmFuZ2VbMV0gLVxuICAgICAgICAgICAgcmFuZ2VbMF0gLVxuICAgICAgICAgICAgaW5kZXggKiAodGhpcy5jb25maWcuYW5udWxhclBhZGRpbmcgKyB0aGlzLnNlZ21lbnRXaWR0aCk7XG4gICAgICAgIHJldHVybiBjYWxjdWxhdGVkUmFkaXVzID49IDAgPyBjYWxjdWxhdGVkUmFkaXVzIDogMDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0QXJjKFxuICAgICAgICByYW5nZTogW251bWJlciwgbnVtYmVyXSxcbiAgICAgICAgZ2VuZXJhdGVkQXJjOiBBcmM8YW55LCBEZWZhdWx0QXJjT2JqZWN0PixcbiAgICAgICAgaW5kZXg6IG51bWJlclxuICAgICk6IEFyYzxhbnksIERlZmF1bHRBcmNPYmplY3Q+IHtcbiAgICAgICAgY29uc3QgaW5uZXJSYWRpdXMgPSB0aGlzLmdldElubmVyUmFkaXVzKHJhbmdlLCBpbmRleCk7XG4gICAgICAgIHJldHVybiBnZW5lcmF0ZWRBcmNcbiAgICAgICAgICAgIC5vdXRlclJhZGl1cyh0aGlzLmdldE91dGVyUmFkaXVzKHJhbmdlLCBpbmRleCkpXG4gICAgICAgICAgICAuaW5uZXJSYWRpdXMoaW5uZXJSYWRpdXMpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRTZWdtZW50V2lkdGgoXG4gICAgICAgIHJlbmRlclNlcmllczogSVJlbmRlclNlcmllczxJUmFkaWFsQWNjZXNzb3JzPlxuICAgICk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGlmICghKHRoaXMuY29uZmlnLm1heFRoaWNrbmVzcyAmJiB0aGlzLmNvbmZpZy5hbm51bGFyR3Jvd3RoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmFubnVsYXJXaWR0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTWF0aC5taW4oXG4gICAgICAgICAgICAocmVuZGVyU2VyaWVzLnNjYWxlcy5yLnJhbmdlKClbMV0gLVxuICAgICAgICAgICAgICAgIHJlbmRlclNlcmllcy5zY2FsZXMuci5yYW5nZSgpWzBdKSAqXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcuYW5udWxhckdyb3d0aCxcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLm1heFRoaWNrbmVzc1xuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgZW1pdERhdGFQb2ludEhpZ2hsaWdodChcbiAgICAgICAgcmVuZGVyU2VyaWVzOiBJUmVuZGVyU2VyaWVzPElSYWRpYWxBY2Nlc3NvcnM+LFxuICAgICAgICBkYXRhOiBhbnksXG4gICAgICAgIGk6IG51bWJlcixcbiAgICAgICAgcmVuZGVyZXJTdWJqZWN0OiBTdWJqZWN0PElSZW5kZXJlckV2ZW50UGF5bG9hZD5cbiAgICApIHtcbiAgICAgICAgY29uc3QgcG9zaXRpb246IElQb3NpdGlvbiB8IHVuZGVmaW5lZCA9IHRoaXMuZ2V0RGF0YVBvaW50UG9zaXRpb24oXG4gICAgICAgICAgICByZW5kZXJTZXJpZXMuZGF0YVNlcmllcyxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICByZW5kZXJTZXJpZXMuc2NhbGVzXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgZGF0YVBvaW50OiBJRGF0YVBvaW50ID0ge1xuICAgICAgICAgICAgc2VyaWVzSWQ6IHJlbmRlclNlcmllcy5kYXRhU2VyaWVzLmlkLFxuICAgICAgICAgICAgZGF0YVNlcmllczogcmVuZGVyU2VyaWVzLmRhdGFTZXJpZXMsXG4gICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICBwb3NpdGlvbjogcG9zaXRpb24sXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmVuYWJsZVNlcmllc0hpZ2hsaWdodGluZykge1xuICAgICAgICAgICAgcmVuZGVyZXJTdWJqZWN0Lm5leHQoe1xuICAgICAgICAgICAgICAgIGV2ZW50TmFtZTogSElHSExJR0hUX1NFUklFU19FVkVOVCxcbiAgICAgICAgICAgICAgICBkYXRhOiBkYXRhUG9pbnQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5lbmFibGVEYXRhUG9pbnRIaWdobGlnaHRpbmcpIHtcbiAgICAgICAgICAgIHJlbmRlcmVyU3ViamVjdC5uZXh0KHtcbiAgICAgICAgICAgICAgICBldmVudE5hbWU6IEhJR0hMSUdIVF9EQVRBX1BPSU5UX0VWRU5ULFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGFQb2ludCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2UncmUgZW1pdHRpbmcgdGhpcyBldmVudCBtYW51YWxseSwgYmVjYXVzZSBpdCdzIG5vdCB0cmlnZ2VyZWQgYnkgbW91c2UgaW50ZXJhY3RpdmUgYXJlYSBpbiB0aGlzIGNhc2VcbiAgICAgICAgcmVuZGVyZXJTdWJqZWN0Lm5leHQoe1xuICAgICAgICAgICAgZXZlbnROYW1lOiBJTlRFUkFDVElPTl9EQVRBX1BPSU5UU19FVkVOVCxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvblR5cGU6IEludGVyYWN0aW9uVHlwZS5Nb3VzZU1vdmUsXG4gICAgICAgICAgICAgICAgZGF0YVBvaW50czoge1xuICAgICAgICAgICAgICAgICAgICBbcmVuZGVyU2VyaWVzLmRhdGFTZXJpZXMuaWRdOiBkYXRhUG9pbnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiJdfQ==