UNPKG

@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

185 lines 26.3 kB
// © 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 { extent } from "d3"; import defaultsDeep from "lodash/defaultsDeep"; import each from "lodash/each"; import get from "lodash/get"; import { DATA_POINT_NOT_FOUND, STANDARD_RENDER_LAYERS } from "../../constants"; import { EMPTY_CONTINUOUS_DOMAIN } from "./scales/types"; import { RenderLayerName, RenderState, } from "../../renderers/types"; /** * The abstract base class for chart renderers with some limited default functionality */ // For why the "dynamic" decorator is used see https://github.com/ng-packagr/ng-packagr/issues/641 // @dynamic export class Renderer { config; static DEFAULT_CONFIG = { stateStyles: { [RenderState.default]: { opacity: 1, }, [RenderState.hidden]: { opacity: 0, }, [RenderState.deemphasized]: { opacity: 0.1, }, [RenderState.emphasized]: { opacity: 1, }, }, }; constructor(config = {}) { this.config = config; // setting default values to the properties that were not set by user this.config = defaultsDeep(this.config, Renderer.DEFAULT_CONFIG); } interaction = {}; /** * Based on provided values, return the nearest data point that the given coordinates represent. This is used for mouse hover behavior * * @param {IDataSeries} series series from which to determine the index corresponding to the specified values * @param {{ [axis: string]: any }} values the values from which a data point index can be determined * @param {Scales} scales the scales to be used in the index calculation * * @returns {number} negative value means that index is not found */ getDataPointIndex(series, values, scales) { return DATA_POINT_NOT_FOUND; } /** * Highlight the data point corresponding to the specified data point index * * @param {IRenderSeries} renderSeries The series on which to render the data point highlight * @param {number} dataPointIndex index of the highlighted point within the data series (pass -1 to remove the highlight marker) * @param {Subject<IRendererEventPayload>} rendererSubject A subject to optionally invoke for emitting events regarding a data point */ highlightDataPoint(renderSeries, dataPointIndex, rendererSubject) { } /** * Get the style attributes for the specified state that we need to apply to a series container * * @param {RenderState} state the state for which to retrieve container styles * * @returns {ValueMap<any, any>} the container styles for the specified state */ getContainerStateStyles = (state) => { if (!this.config.stateStyles) { throw new Error("stateStyles property is not defined"); } return this.config.stateStyles[state || RenderState.default]; }; /** * Set the RenderState of the target data series * * @param {IRenderContainers} renderContainers the render containers of the series * @param {RenderState} state The new state for the target series */ setSeriesState(renderContainers, state) { } /** * Set the RenderState of the target data point * * @param {D3Selection} target the target data point * @param {RenderState} state The new state for the target data point */ setDataPointState(target, state) { } /** * Calculate domain for data filtered by given filterScales * * @param dataSeries * @param filterScales * @param scaleKey * @param scale * @returns array of datapoints from <code>dataSeries</code> filtered by domains of given <code>filterScale</code>s */ getDomainOfFilteredData(dataSeries, filterScales, scaleKey, scale) { let filteredData = dataSeries.data; for (const fixedScaleKey of Object.keys(filterScales)) { const filterScale = filterScales[fixedScaleKey]; if (!filterScale.isDomainFixed || !filterScale.isContinuous()) { continue; } filteredData = this.filterDataByDomain(filteredData, dataSeries, fixedScaleKey, filterScale.domain()); } return this.getDomain(filteredData, dataSeries, scaleKey, scale); } /** * Calculate the domain using the data of a series * * @param {any[]} data source data, can be filtered * @param dataSeries related data series * @param {string} scaleName name of the scale for which domain calculation is needed * @param scale * * @returns {[any, any]} min and max values as an array */ getDomain(data, dataSeries, scaleName, scale) { if (!data || data.length === 0) { return EMPTY_CONTINUOUS_DOMAIN; } return extent(data, (datum, index, arr) => dataSeries.accessors.data?.[scaleName]?.(datum, index, Array.from(arr), dataSeries)); } /** * Filters given dataset by domain of provided scale * * @param data * @param dataSeries * @param scaleName * @param domain */ filterDataByDomain(data, dataSeries, scaleName, domain) { const accessor = dataSeries.accessors.data?.[scaleName]; // if (isNil(accessor)) { // throw new Error("accessor is not defined"); // } return data.filter((d, i) => { // @ts-ignore const value = accessor(d, i, data, dataSeries); return value >= domain[0] && value <= domain[1]; }); } /** * Get the definitions of lasagna layers required for visualizing data * * @returns {ILasagnaLayer[]} lasagna layer definitions */ getRequiredLayers() { return [STANDARD_RENDER_LAYERS[RenderLayerName.data]]; } setupInteraction(path, nativeEvent, target, dataPointSubject, dataPoint) { const eventList = get(this.interaction, path, {})[nativeEvent]; if (!eventList) { return; } each(eventList, (targetEvent) => { target.on(nativeEvent, () => { const bbox = target.node().getBoundingClientRect(); dataPointSubject.next({ eventName: targetEvent, data: { ...dataPoint, position: bbox, }, }); }); }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29yZS9jb21tb24vcmVuZGVyZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFBRSxNQUFNLEVBQVcsTUFBTSxJQUFJLENBQUM7QUFHckMsT0FBTyxZQUFZLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxJQUFJLE1BQU0sYUFBYSxDQUFDO0FBQy9CLE9BQU8sR0FBRyxNQUFNLFlBQVksQ0FBQztBQUc3QixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvRSxPQUFPLEVBQUUsdUJBQXVCLEVBQWtCLE1BQU0sZ0JBQWdCLENBQUM7QUFZekUsT0FBTyxFQUVILGVBQWUsRUFDZixXQUFXLEdBQ2QsTUFBTSx1QkFBdUIsQ0FBQztBQUUvQjs7R0FFRztBQUNILGtHQUFrRztBQUNsRyxXQUFXO0FBQ1gsTUFBTSxPQUFnQixRQUFRO0lBa0JQO0lBakJaLE1BQU0sQ0FBVSxjQUFjLEdBQW9CO1FBQ3JELFdBQVcsRUFBRTtZQUNULENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNuQixPQUFPLEVBQUUsQ0FBQzthQUNiO1lBQ0QsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQ2xCLE9BQU8sRUFBRSxDQUFDO2FBQ2I7WUFDRCxDQUFDLFdBQVcs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SUFBSTtxQkFDakI7aUJBQ0osQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHsgZXh0ZW50LCBOdW1lcmljIH0gZnJvbSBcImQzXCI7XG5pbXBvcnQgeyBTZWxlY3Rpb24gfSBmcm9tIFwiZDMtc2VsZWN0aW9uXCI7XG5pbXBvcnQgeyBWYWx1ZU1hcCB9IGZyb20gXCJkMy1zZWxlY3Rpb24tbXVsdGlcIjtcbmltcG9ydCBkZWZhdWx0c0RlZXAgZnJvbSBcImxvZGFzaC9kZWZhdWx0c0RlZXBcIjtcbmltcG9ydCBlYWNoIGZyb20gXCJsb2Rhc2gvZWFjaFwiO1xuaW1wb3J0IGdldCBmcm9tIFwibG9kYXNoL2dldFwiO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCJyeGpzXCI7XG5cbmltcG9ydCB7IERBVEFfUE9JTlRfTk9UX0ZPVU5ELCBTVEFOREFSRF9SRU5ERVJfTEFZRVJTIH0gZnJvbSBcIi4uLy4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgRU1QVFlfQ09OVElOVU9VU19ET01BSU4sIElTY2FsZSwgU2NhbGVzIH0gZnJvbSBcIi4vc2NhbGVzL3R5cGVzXCI7XG5pbXBvcnQge1xuICAgIEQzU2VsZWN0aW9uLFxuICAgIElBY2Nlc3NvcnMsXG4gICAgSURhdGFQb2ludCxcbiAgICBJRGF0YVNlcmllcyxcbiAgICBJTGFzYWduYUxheWVyLFxuICAgIElQb3NpdGlvbixcbiAgICBJUmVuZGVyQ29udGFpbmVycyxcbiAgICBJUmVuZGVyZXJDb25maWcsXG4gICAgSVJlbmRlcmVyRXZlbnRQYXlsb2FkLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHtcbiAgICBJUmVuZGVyU2VyaWVzLFxuICAgIFJlbmRlckxheWVyTmFtZSxcbiAgICBSZW5kZXJTdGF0ZSxcbn0gZnJvbSBcIi4uLy4uL3JlbmRlcmVycy90eXBlc1wiO1xuXG4vKipcbiAqIFRoZSBhYnN0cmFjdCBiYXNlIGNsYXNzIGZvciBjaGFydCByZW5kZXJlcnMgd2l0aCBzb21lIGxpbWl0ZWQgZGVmYXVsdCBmdW5jdGlvbmFsaXR5XG4gKi9cbi8vIEZvciB3aHkgdGhlIFwiZHluYW1pY1wiIGRlY29yYXRvciBpcyB1c2VkIHNlZSBodHRwczovL2dpdGh1Yi5jb20vbmctcGFja2Fnci9uZy1wYWNrYWdyL2lzc3Vlcy82NDFcbi8vIEBkeW5hbWljXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUmVuZGVyZXI8VEEgZXh0ZW5kcyBJQWNjZXNzb3JzPiB7XG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0NPTkZJRzogSVJlbmRlcmVyQ29uZmlnID0ge1xuICAgICAgICBzdGF0ZVN0eWxlczoge1xuICAgICAgICAgICAgW1JlbmRlclN0YXRlLmRlZmF1bHRdOiB7XG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBbUmVuZGVyU3RhdGUuaGlkZGVuXToge1xuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW1JlbmRlclN0YXRlLmRlZW1waGFzaXplZF06IHtcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAwLjEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW1JlbmRlclN0YXRlLmVtcGhhc2l6ZWRdOiB7XG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBjb25maWc6IElSZW5kZXJlckNvbmZpZyA9IHt9KSB7XG4gICAgICAgIC8vIHNldHRpbmcgZGVmYXVsdCB2YWx1ZXMgdG8gdGhlIHByb3BlcnRpZXMgdGhhdCB3ZXJlIG5vdCBzZXQgYnkgdXNlclxuICAgICAgICB0aGlzLmNvbmZpZyA9IGRlZmF1bHRzRGVlcCh0aGlzLmNvbmZpZywgUmVuZGVyZXIuREVGQVVMVF9DT05GSUcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbnRlcmFjdGlvbjogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogRHJhdyB0aGUgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwcm92aWRlZCBkYXRhIHNlcmllc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtJUmVuZGVyU2VyaWVzfSByZW5kZXJTZXJpZXMgVGhlIHNlcmllcyB0byByZW5kZXJcbiAgICAgKiBAcGFyYW0ge1N1YmplY3Q8SVJlbmRlcmVyRXZlbnRQYXlsb2FkPn0gcmVuZGVyZXJTdWJqZWN0IEEgc3ViamVjdCB0byBvcHRpb25hbGx5IGludm9rZSBmb3IgZW1pdHRpbmcgZXZlbnRzIHJlZ2FyZGluZyBhIGRhdGEgcG9pbnRcbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgZHJhdyhcbiAgICAgICAgcmVuZGVyU2VyaWVzOiBJUmVuZGVyU2VyaWVzPFRBPixcbiAgICAgICAgcmVuZGVyZXJTdWJqZWN0OiBTdWJqZWN0PElSZW5kZXJlckV2ZW50UGF5bG9hZD5cbiAgICApOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHBvc2l0aW9uIG9mIGEgc3BlY2lmaWVkIGRhdGFwb2ludFxuICAgICAqXG4gICAgICogQHBhcmFtIHtJRGF0YVNlcmllc30gZGF0YVNlcmllc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleFxuICAgICAqIEBwYXJhbSB7U2NhbGVzfSBzY2FsZXNcbiAgICAgKiBAcmV0dXJucyB7SVBvc2l0aW9ufVxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBnZXREYXRhUG9pbnRQb3NpdGlvbihcbiAgICAgICAgZGF0YVNlcmllczogSURhdGFTZXJpZXM8VEE+LFxuICAgICAgICBpbmRleDogbnVtYmVyLFxuICAgICAgICBzY2FsZXM6IFNjYWxlc1xuICAgICk6IElQb3NpdGlvbiB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEJhc2VkIG9uIHByb3ZpZGVkIHZhbHVlcywgcmV0dXJuIHRoZSBuZWFyZXN0IGRhdGEgcG9pbnQgdGhhdCB0aGUgZ2l2ZW4gY29vcmRpbmF0ZXMgcmVwcmVzZW50LiBUaGlzIGlzIHVzZWQgZm9yIG1vdXNlIGhvdmVyIGJlaGF2aW9yXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0lEYXRhU2VyaWVzfSBzZXJpZXMgc2VyaWVzIGZyb20gd2hpY2ggdG8gZGV0ZXJtaW5lIHRoZSBpbmRleCBjb3JyZXNwb25kaW5nIHRvIHRoZSBzcGVjaWZpZWQgdmFsdWVzXG4gICAgICogQHBhcmFtIHt7IFtheGlzOiBzdHJpbmddOiBhbnkgfX0gdmFsdWVzIHRoZSB2YWx1ZXMgZnJvbSB3aGljaCBhIGRhdGEgcG9pbnQgaW5kZXggY2FuIGJlIGRldGVybWluZWRcbiAgICAgKiBAcGFyYW0ge1NjYWxlc30gc2NhbGVzIHRoZSBzY2FsZXMgdG8gYmUgdXNlZCBpbiB0aGUgaW5kZXggY2FsY3VsYXRpb25cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IG5lZ2F0aXZlIHZhbHVlIG1lYW5zIHRoYXQgaW5kZXggaXMgbm90IGZvdW5kXG4gICAgICovXG4gICAgcHVibGljIGdldERhdGFQb2ludEluZGV4KFxuICAgICAgICBzZXJpZXM6IElEYXRhU2VyaWVzPFRBPixcbiAgICAgICAgdmFsdWVzOiB7IFtheGlzOiBzdHJpbmddOiBhbnkgfSxcbiAgICAgICAgc2NhbGVzOiBTY2FsZXNcbiAgICApOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gREFUQV9QT0lOVF9OT1RfRk9VTkQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGlnaGxpZ2h0IHRoZSBkYXRhIHBvaW50IGNvcnJlc3BvbmRpbmcgdG8gdGhlIHNwZWNpZmllZCBkYXRhIHBvaW50IGluZGV4XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0lSZW5kZXJTZXJpZXN9IHJlbmRlclNlcmllcyBUaGUgc2VyaWVzIG9uIHdoaWNoIHRvIHJlbmRlciB0aGUgZGF0YSBwb2ludCBoaWdobGlnaHRcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZGF0YVBvaW50SW5kZXggaW5kZXggb2YgdGhlIGhpZ2hsaWdodGVkIHBvaW50IHdpdGhpbiB0aGUgZGF0YSBzZXJpZXMgKHBhc3MgLTEgdG8gcmVtb3ZlIHRoZSBoaWdobGlnaHQgbWFya2VyKVxuICAgICAqIEBwYXJhbSB7U3ViamVjdDxJUmVuZGVyZXJFdmVudFBheWxvYWQ+fSByZW5kZXJlclN1YmplY3QgQSBzdWJqZWN0IHRvIG9wdGlvbmFsbHkgaW52b2tlIGZvciBlbWl0dGluZyBldmVudHMgcmVnYXJkaW5nIGEgZGF0YSBwb2ludFxuICAgICAqL1xuICAgIHB1YmxpYyBoaWdobGlnaHREYXRhUG9pbnQoXG4gICAgICAgIHJlbmRlclNlcmllczogSVJlbmRlclNlcmllczxUQT4sXG4gICAgICAgIGRhdGFQb2ludEluZGV4OiBudW1iZXIsXG4gICAgICAgIHJlbmRlcmVyU3ViamVjdDogU3ViamVjdDxJUmVuZGVyZXJFdmVudFBheWxvYWQ+XG4gICAgKTogdm9pZCB7fVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBzdHlsZSBhdHRyaWJ1dGVzIGZvciB0aGUgc3BlY2lmaWVkIHN0YXRlIHRoYXQgd2UgbmVlZCB0byBhcHBseSB0byBhIHNlcmllcyBjb250YWluZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7UmVuZGVyU3RhdGV9IHN0YXRlIHRoZSBzdGF0ZSBmb3Igd2hpY2ggdG8gcmV0cmlldmUgY29udGFpbmVyIHN0eWxlc1xuICAgICAqXG4gICAgICogQHJldHVybnMge1ZhbHVlTWFwPGFueSwgYW55Pn0gdGhlIGNvbnRhaW5lciBzdHlsZXMgZm9yIHRoZSBzcGVjaWZpZWQgc3RhdGVcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Q29udGFpbmVyU3RhdGVTdHlsZXMgPSAoXG4gICAgICAgIHN0YXRlOiBSZW5kZXJTdGF0ZVxuICAgICk6IFZhbHVlTWFwPGFueSwgYW55PiA9PiB7XG4gICAgICAgIGlmICghdGhpcy5jb25maWcuc3RhdGVTdHlsZXMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInN0YXRlU3R5bGVzIHByb3BlcnR5IGlzIG5vdCBkZWZpbmVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5zdGF0ZVN0eWxlc1tzdGF0ZSB8fCBSZW5kZXJTdGF0ZS5kZWZhdWx0XTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBSZW5kZXJTdGF0ZSBvZiB0aGUgdGFyZ2V0IGRhdGEgc2VyaWVzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0lSZW5kZXJDb250YWluZXJzfSByZW5kZXJDb250YWluZXJzIHRoZSByZW5kZXIgY29udGFpbmVycyBvZiB0aGUgc2VyaWVzXG4gICAgICogQHBhcmFtIHtSZW5kZXJTdGF0ZX0gc3RhdGUgVGhlIG5ldyBzdGF0ZSBmb3IgdGhlIHRhcmdldCBzZXJpZXNcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0U2VyaWVzU3RhdGUoXG4gICAgICAgIHJlbmRlckNvbnRhaW5lcnM6IElSZW5kZXJDb250YWluZXJzLFxuICAgICAgICBzdGF0ZTogUmVuZGVyU3RhdGVcbiAgICApOiB2b2lkIHt9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIFJlbmRlclN0YXRlIG9mIHRoZSB0YXJnZXQgZGF0YSBwb2ludFxuICAgICAqXG4gICAgICogQHBhcmFtIHtEM1NlbGVjdGlvbn0gdGFyZ2V0IHRoZSB0YXJnZXQgZGF0YSBwb2ludFxuICAgICAqIEBwYXJhbSB7UmVuZGVyU3RhdGV9IHN0YXRlIFRoZSBuZXcgc3RhdGUgZm9yIHRoZSB0YXJnZXQgZGF0YSBwb2ludFxuICAgICAqL1xuICAgIHB1YmxpYyBzZXREYXRhUG9pbnRTdGF0ZSh0YXJnZXQ6IEQzU2VsZWN0aW9uLCBzdGF0ZTogUmVuZGVyU3RhdGUpOiB2b2lkIHt9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGUgZG9tYWluIGZvciBkYXRhIGZpbHRlcmVkIGJ5IGdpdmVuIGZpbHRlclNjYWxlc1xuICAgICAqXG4gICAgICogQHBhcmFtIGRhdGFTZXJpZXNcbiAgICAgKiBAcGFyYW0gZmlsdGVyU2NhbGVzXG4gICAgICogQHBhcmFtIHNjYWxlS2V5XG4gICAgICogQHBhcmFtIHNjYWxlXG4gICAgICogQHJldHVybnMgYXJyYXkgb2YgZGF0YXBvaW50cyBmcm9tIDxjb2RlPmRhdGFTZXJpZXM8L2NvZGU+IGZpbHRlcmVkIGJ5IGRvbWFpbnMgb2YgZ2l2ZW4gPGNvZGU+ZmlsdGVyU2NhbGU8L2NvZGU+c1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXREb21haW5PZkZpbHRlcmVkRGF0YShcbiAgICAgICAgZGF0YVNlcmllczogSURhdGFTZXJpZXM8VEE+LFxuICAgICAgICBmaWx0ZXJTY2FsZXM6IFJlY29yZDxzdHJpbmcsIElTY2FsZTxhbnk+PixcbiAgICAgICAgc2NhbGVLZXk6IHN0cmluZyxcbiAgICAgICAgc2NhbGU6IElTY2FsZTxhbnk+XG4gICAgKTogYW55W10ge1xuICAgICAgICBsZXQgZmlsdGVyZWREYXRhID0gZGF0YVNlcmllcy5kYXRhO1xuICAgICAgICBmb3IgKGNvbnN0IGZpeGVkU2NhbGVLZXkgb2YgT2JqZWN0LmtleXMoZmlsdGVyU2NhbGVzKSkge1xuICAgICAgICAgICAgY29uc3QgZmlsdGVyU2NhbGUgPSBmaWx0ZXJTY2FsZXNbZml4ZWRTY2FsZUtleV07XG4gICAgICAgICAgICBpZiAoIWZpbHRlclNjYWxlLmlzRG9tYWluRml4ZWQgfHwgIWZpbHRlclNjYWxlLmlzQ29udGludW91cygpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZpbHRlcmVkRGF0YSA9IHRoaXMuZmlsdGVyRGF0YUJ5RG9tYWluKFxuICAgICAgICAgICAgICAgIGZpbHRlcmVkRGF0YSxcbiAgICAgICAgICAgICAgICBkYXRhU2VyaWVzLFxuICAgICAgICAgICAgICAgIGZpeGVkU2NhbGVLZXksXG4gICAgICAgICAgICAgICAgZmlsdGVyU2NhbGUuZG9tYWluKClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5nZXREb21haW4oZmlsdGVyZWREYXRhLCBkYXRhU2VyaWVzLCBzY2FsZUtleSwgc2NhbGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgZG9tYWluIHVzaW5nIHRoZSBkYXRhIG9mIGEgc2VyaWVzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBkYXRhIHNvdXJjZSBkYXRhLCBjYW4gYmUgZmlsdGVyZWRcbiAgICAgKiBAcGFyYW0gZGF0YVNlcmllcyByZWxhdGVkIGRhdGEgc2VyaWVzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNjYWxlTmFtZSBuYW1lIG9mIHRoZSBzY2FsZSBmb3Igd2hpY2ggZG9tYWluIGNhbGN1bGF0aW9uIGlzIG5lZWRlZFxuICAgICAqIEBwYXJhbSBzY2FsZVxuICAgICAqXG4gICAgICogQHJldHVybnMge1thbnksIGFueV19IG1pbiBhbmQgbWF4IHZhbHVlcyBhcyBhbiBhcnJheVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXREb21haW4oXG4gICAgICAgIGRhdGE6IGFueVtdLFxuICAgICAgICBkYXRhU2VyaWVzOiBJRGF0YVNlcmllczxUQT4sXG4gICAgICAgIHNjYWxlTmFtZTogc3RyaW5nLFxuICAgICAgICBzY2FsZTogSVNjYWxlPGFueT5cbiAgICApOiBhbnlbXSB7XG4gICAgICAgIGlmICghZGF0YSB8fCBkYXRhLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIEVNUFRZX0NPTlRJTlVPVVNfRE9NQUlOO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGV4dGVudDxOdW1lcmljLCBOdW1lcmljPihkYXRhLCAoZGF0dW0sIGluZGV4LCBhcnIpID0+XG4gICAgICAgICAgICBkYXRhU2VyaWVzLmFjY2Vzc29ycy5kYXRhPy5bc2NhbGVOYW1lXT8uKFxuICAgICAgICAgICAgICAgIGRhdHVtLFxuICAgICAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgICAgIEFycmF5LmZyb20oYXJyKSxcbiAgICAgICAgICAgICAgICBkYXRhU2VyaWVzXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmlsdGVycyBnaXZlbiBkYXRhc2V0IGJ5IGRvbWFpbiBvZiBwcm92aWRlZCBzY2FsZVxuICAgICAqXG4gICAgICogQHBhcmFtIGRhdGFcbiAgICAgKiBAcGFyYW0gZGF0YVNlcmllc1xuICAgICAqIEBwYXJhbSBzY2FsZU5hbWVcbiAgICAgKiBAcGFyYW0gZG9tYWluXG4gICAgICovXG4gICAgcHVibGljIGZpbHRlckRhdGFCeURvbWFpbihcbiAgICAgICAgZGF0YTogYW55W10sXG4gICAgICAgIGRhdGFTZXJpZXM6IElEYXRhU2VyaWVzPFRBPixcbiAgICAgICAgc2NhbGVOYW1lOiBzdHJpbmcsXG4gICAgICAgIGRvbWFpbjogYW55W11cbiAgICApOiBhbnlbXSB7XG4gICAgICAgIGNvbnN0IGFjY2Vzc29yID0gZGF0YVNlcmllcy5hY2Nlc3NvcnMuZGF0YT8uW3NjYWxlTmFtZV07XG5cbiAgICAgICAgLy8gaWYgKGlzTmlsKGFjY2Vzc29yKSkge1xuICAgICAgICAvLyAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWNjZXNzb3IgaXMgbm90IGRlZmluZWRcIik7XG4gICAgICAgIC8vIH1cblxuICAgICAgICByZXR1cm4gZGF0YS5maWx0ZXIoKGQsIGkpID0+IHtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gYWNjZXNzb3IoZCwgaSwgZGF0YSwgZGF0YVNlcmllcyk7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUgPj0gZG9tYWluWzBdICYmIHZhbHVlIDw9IGRvbWFpblsxXTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBkZWZpbml0aW9ucyBvZiBsYXNhZ25hIGxheWVycyByZXF1aXJlZCBmb3IgdmlzdWFsaXppbmcgZGF0YVxuICAgICAqXG4gICAgICogQHJldHVybnMge0lMYXNhZ25hTGF5ZXJbXX0gbGFzYWduYSBsYXllciBkZWZpbml0aW9uc1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXRSZXF1aXJlZExheWVycygpOiBJTGFzYWduYUxheWVyW10ge1xuICAgICAgICByZXR1cm4gW1NUQU5EQVJEX1JFTkRFUl9MQVlFUlNbUmVuZGVyTGF5ZXJOYW1lLmRhdGFdXTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2V0dXBJbnRlcmFjdGlvbihcbiAgICAgICAgcGF0aDogc3RyaW5nW10sXG4gICAgICAgIG5hdGl2ZUV2ZW50OiBzdHJpbmcsXG4gICAgICAgIHRhcmdldDogU2VsZWN0aW9uPGFueSwgYW55LCBhbnksIGFueT4sXG4gICAgICAgIGRhdGFQb2ludFN1YmplY3Q6IFN1YmplY3Q8SVJlbmRlcmVyRXZlbnRQYXlsb2FkPixcbiAgICAgICAgZGF0YVBvaW50OiBQYXJ0aWFsPElEYXRhUG9pbnQ+XG4gICAgKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGV2ZW50TGlzdDogc3RyaW5nW10gPSBnZXQodGhpcy5pbnRlcmFjdGlvbiwgcGF0aCwge30pW1xuICAgICAgICAgICAgbmF0aXZlRXZlbnRcbiAgICAgICAgXTtcbiAgICAgICAgaWYgKCFldmVudExpc3QpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGVhY2goZXZlbnRMaXN0LCAodGFyZ2V0RXZlbnQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGFyZ2V0Lm9uKG5hdGl2ZUV2ZW50LCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgYmJveCA9IHRhcmdldC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgZGF0YVBvaW50U3ViamVjdC5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnROYW1lOiB0YXJnZXRFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogPElEYXRhUG9pbnQ+e1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uZGF0YVBvaW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IGJib3gsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuIl19