UNPKG

@nova-ui/dashboards

Version:

Nova Dashboards is a framework designed to provide feature developers with a common solution for presenting data coming from various sources within a single view, as well as a set of predefined widget visualizations that are 100% configuration-driven and

347 lines 51.1 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 { ChangeDetectorRef, Inject, Injectable, Optional, } from "@angular/core"; // eslint-disable-next-line import/no-deprecated import { merge } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { EventBus } from "@nova-ui/bits"; import { ChartPalette, defaultColorProvider, INTERACTION_DATA_POINTS_EVENT, INTERACTION_VALUES_EVENT, InteractionType, SequentialColorProvider, SET_DOMAIN_EVENT, XYRenderer, XYAccessors, } from "@nova-ui/charts"; import { INTERACTION, SET_TIMEFRAME } from "../../../../services/types"; import { DATA_SOURCE, PIZZAGNA_EVENT_BUS, } from "../../../../types"; import { LegendPlacement } from "../../../../widget-types/common/widget/legend"; import { SUMMARY_LEGEND_BCG_COLOR, SUMMARY_LEGEND_COLOR, } from "../../timeseries-helpers"; import { TimeseriesScalesService } from "../../timeseries-scales.service"; import { transformChangePoint, transformDifference, transformFloatingAverage, transformLinReg, transformLoessSmoothing, transformLoessStandardize, transformNormalize, transformPercentileStd, transformStandardize, } from "../../transformer/public-api"; import { TimeseriesChartPreset, TimeseriesChartTypes, TimeseriesInteractionType, TimeseriesTransformer, TimeseriesWidgetProjectType, } from "../../types"; import { TimeseriesChartComponent } from "../timeseries-chart.component"; import * as i0 from "@angular/core"; import * as i1 from "../../timeseries-scales.service"; import * as i2 from "@nova-ui/bits"; export class XYChartComponent extends TimeseriesChartComponent { constructor(eventBus, dataSource, timeseriesScalesService, changeDetector) { super(eventBus, timeseriesScalesService, dataSource); this.eventBus = eventBus; this.timeseriesScalesService = timeseriesScalesService; this.changeDetector = changeDetector; this.valueAccessorKey = "y"; this.collectionId = ""; this.timeseriesChartTypes = TimeseriesChartTypes; this.summaryLegendBcgColor = SUMMARY_LEGEND_BCG_COLOR; this.summaryLegendColor = SUMMARY_LEGEND_COLOR; this.transformers = new Map([ [ TimeseriesTransformer.None, { displayName: $localize `None`, transformer: undefined }, ], [ TimeseriesTransformer.ChangePoint, { displayName: $localize `Change Point`, transformer: transformChangePoint, }, ], [ TimeseriesTransformer.Difference, { displayName: $localize `Difference`, transformer: transformDifference, }, ], [ TimeseriesTransformer.FloatingAverage, { displayName: $localize `Floating Average`, transformer: transformFloatingAverage, }, ], [ TimeseriesTransformer.Linear, { displayName: $localize `Linear`, transformer: transformLinReg }, ], [ TimeseriesTransformer.Normalize, { displayName: $localize `Normalize`, transformer: transformNormalize, }, ], [ TimeseriesTransformer.PercentileStd, { displayName: $localize `Percentile Standardized`, transformer: transformPercentileStd, }, ], [ TimeseriesTransformer.Smoothing, { displayName: $localize `Smoothing`, transformer: transformLoessSmoothing, }, ], [ TimeseriesTransformer.LoessStandardize, { displayName: $localize `Smoothing Standardized`, transformer: transformLoessStandardize, }, ], [ TimeseriesTransformer.Standardize, { displayName: $localize `Standardize`, transformer: transformStandardize, }, ], ]); } mapSeriesSet(data, scales) { const yScales = [scales.y]; if (scales.yRight) { yScales.push(scales.yRight); } const dataMapped = data.map((series) => { // matches scale units to the metric unit for either left y-axis scale or right y-axis scale let yScale = yScales.find((yScale) => yScale.scaleUnits === series.metricUnits); if (!yScale) { yScale = yScales.find((yScale) => yScale.scaleUnits === "generic") ?? scales.y; } return { ...series, scales: { x: scales.x, y: yScale, }, renderer: this.renderer, accessors: this.accessors, }; }); if (this.widgetData.summarySerie) { this.summarySerie = { ...this.widgetData.summarySerie, accessors: new XYAccessors(), renderer: new XYRenderer({ ignoreForDomainCalculation: true, }), scales: { x: scales.x, y: scales.y, }, showInLegend: false, preprocess: false, }; dataMapped.push(this.summarySerie); } return dataMapped; } /** Checks if legend should be shown. */ hasLegend() { return (this.configuration.legendPlacement && this.configuration.legendPlacement !== LegendPlacement.None); } /** Checks if legend should be aligned to right. */ legendShouldBeAlignedRight() { return this.configuration.legendPlacement === LegendPlacement.Right; } onPrimaryDescClick(event, legendSeries) { if (!this.seriesInteractive) { return; } event.stopPropagation(); this.eventBus.getStream(INTERACTION).next({ payload: { data: legendSeries, interactionType: TimeseriesInteractionType.Series, }, }); } /** Updates chart data. */ updateChartData() { const grid = this.chartAssist.chart.getGrid(); if (this.scales.y?.id) { grid.leftScaleId = this.scales.y.id; } if ((this.scales.yRight && this.widgetData.series.length === 1) || (this.scales.y && this.scales.yRight && this.scales.y.scaleUnits === this.scales.yRight.scaleUnits)) { // if there is only one series to display, or if the left y-axis and right y-axis have the same units, both y-axises are same this.scales.yRight = this.scales.y; grid.rightScaleId = this.scales.y.id; } else { if (this.scales.yRight?.id) { grid.rightScaleId = this.scales.yRight.id; } } const gridConfig = grid.config(); // hides botom axis if it's not last chart in the group gridConfig.axis.bottom.visible = !this.configuration?.hasAdjacentChart; gridConfig.borders.bottom.visible = !this.configuration?.hasAdjacentChart; this.chartAssist.update(this.mapSeriesSet(this.widgetData.series, this.scales)); } /** * Initialize chart */ buildChart() { this.buildChart$.next(); const colorProvider = this.configuration.chartColors && this.configuration.chartColors?.length > 0 ? new SequentialColorProvider(this.configuration.chartColors) : defaultColorProvider(); const palette = new ChartPalette(colorProvider); this.accessors = this.createAccessors(palette.standardColors); this.chartAssist = this.createChartAssist(palette); const chart = this.chartAssist.chart; const gridConfig = chart.getGrid().config(); if (this.configuration.gridConfig?.xAxisTicksCount) { gridConfig.axis.bottom.approximateTicks = this.configuration.gridConfig.xAxisTicksCount; } if (gridConfig.dimension.marginLocked && this.configuration.gridConfig?.sideMarginLocked) { gridConfig.dimension.marginLocked.left = true; gridConfig.dimension.marginLocked.right = true; } if (this.configuration.gridConfig?.sideMargin) { gridConfig.dimension.margin.left = this.configuration.gridConfig.sideMargin; gridConfig.dimension.margin.right = this.configuration.gridConfig.sideMargin; } if (this.configuration.enableZoom && this.zoomPlugins.length) { chart.addPlugin(this.zoomPlugins[0]); } chart .getEventBus() .getStream(SET_DOMAIN_EVENT) // eslint-disable-next-line import/no-deprecated .pipe(takeUntil(merge(this.destroy$, this.buildChart$))) .subscribe((event) => { const payload = event.data; const newDomain = payload[Object.keys(payload)[0]]; this.eventBus.getStream(SET_TIMEFRAME).next({ payload: { startDatetime: newDomain[0], endDatetime: newDomain[1], selectedPresetId: undefined, }, }); }); this.setupInteraction(); } /** * Subscribe to chart events and emit */ setupInteraction() { // interaction with chart data points this.chartAssist.chart .getEventBus() .getStream(INTERACTION_DATA_POINTS_EVENT) // eslint-disable-next-line import/no-deprecated .pipe(takeUntil(merge(this.destroy$, this.buildChart$))) .subscribe((values) => { const payload = values.data; if (payload.interactionType === InteractionType.Click) { this.eventBus.getStream(INTERACTION).next({ payload: { data: payload.dataPoints, interactionType: TimeseriesInteractionType.DataPoints, }, }); } }); // interaction with values this.chartAssist.chart .getEventBus() .getStream(INTERACTION_VALUES_EVENT) // eslint-disable-next-line import/no-deprecated .pipe(takeUntil(merge(this.destroy$, this.buildChart$))) .subscribe((values) => { const payload = values.data; if (payload.interactionType === InteractionType.Click) { this.eventBus.getStream(INTERACTION).next({ payload: { data: payload.values, interactionType: TimeseriesInteractionType.Values, }, }); } }); } displayLegendMenu() { return (this.configuration.preset === TimeseriesChartPreset.Line && !!this.configuration.allowLegendMenu && this.configuration.projectType === TimeseriesWidgetProjectType.PerfstackApp); } displayDeleteButton() { return (this.configuration.preset !== TimeseriesChartPreset.Line && !!this.configuration.allowLegendMenu && this.configuration.projectType === TimeseriesWidgetProjectType.PerfstackApp); } transformData(metricId, trId) { const serie = this.widgetData.series.find((s) => s.id === metricId); if (!serie) { return; } serie.transformer = this.transformers.get(trId)?.transformer; if (serie.rawData) { if (serie.transformer === undefined) { // revert transformed data serie.data = serie.rawData; this.updateYAxisDomain(); } else { this.transformSeriesData(serie); } } this.updateChartData(); } getLegendValue(legendSeries, valueAccessorKey) { const val = this.chartAssist.getHighlightedValue(legendSeries, "y", "tick", valueAccessorKey); if (this.configuration.projectType === TimeseriesWidgetProjectType.PerfstackApp && this.configuration.preset === TimeseriesChartPreset.StackedArea && this.configuration.units === "percent") { const submetricsCount = this.chartAssist.legendSeriesSet.length; const strVal = `${val ?? 0}`; return `${parseFloat(strVal ?? "0") * submetricsCount} %`; } return val; } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: XYChartComponent, deps: [{ token: PIZZAGNA_EVENT_BUS }, { token: DATA_SOURCE, optional: true }, { token: i1.TimeseriesScalesService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Injectable }); } /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: XYChartComponent }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: XYChartComponent, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i2.EventBus, decorators: [{ type: Inject, args: [PIZZAGNA_EVENT_BUS] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DATA_SOURCE] }] }, { type: i1.TimeseriesScalesService }, { type: i0.ChangeDetectorRef }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieHktY2hhcnQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3RpbWVzZXJpZXMtd2lkZ2V0L2NoYXJ0LXByZXNldHMveHktY2hhcnQveHktY2hhcnQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlEQUF5RDtBQUN6RCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0REFBNEQ7QUFDNUQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSx1REFBdUQ7QUFDdkQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLDBFQUEwRTtBQUMxRSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLGlCQUFpQjtBQUVqQixPQUFPLEVBQ0gsaUJBQWlCLEVBQ2pCLE1BQU0sRUFDTixVQUFVLEVBR1YsUUFBUSxHQUNYLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLGdEQUFnRDtBQUNoRCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUUsUUFBUSxFQUF1QixNQUFNLGVBQWUsQ0FBQztBQUM5RCxPQUFPLEVBRUgsWUFBWSxFQUNaLG9CQUFvQixFQU9wQiw2QkFBNkIsRUFDN0Isd0JBQXdCLEVBQ3hCLGVBQWUsRUFPZix1QkFBdUIsRUFDdkIsZ0JBQWdCLEVBRWhCLFVBQVUsRUFDVixXQUFXLEdBQ2QsTUFBTSxpQkFBaUIsQ0FBQztBQUV6QixPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3hFLE9BQU8sRUFDSCxXQUFXLEVBRVgsa0JBQWtCLEdBQ3JCLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBQ2hGLE9BQU8sRUFDSCx3QkFBd0IsRUFDeEIsb0JBQW9CLEdBQ3ZCLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUNILG9CQUFvQixFQUNwQixtQkFBbUIsRUFDbkIsd0JBQXdCLEVBQ3hCLGVBQWUsRUFDZix1QkFBdUIsRUFDdkIseUJBQXlCLEVBQ3pCLGtCQUFrQixFQUNsQixzQkFBc0IsRUFDdEIsb0JBQW9CLEdBQ3ZCLE1BQU0sOEJBQThCLENBQUM7QUFDdEMsT0FBTyxFQUVILHFCQUFxQixFQUNyQixvQkFBb0IsRUFDcEIseUJBQXlCLEVBQ3pCLHFCQUFxQixFQUVyQiwyQkFBMkIsR0FDOUIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sK0JBQStCLENBQUM7Ozs7QUFXekUsTUFBTSxPQUFnQixnQkFDbEIsU0FBUSx3QkFBd0I7SUFzRmhDLFlBQzBDLFFBQTBCLEVBQy9CLFVBQXVCLEVBQ2pELHVCQUFnRCxFQUNoRCxjQUFpQztRQUV4QyxLQUFLLENBQUMsUUFBUSxFQUFFLHVCQUF1QixFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBTGYsYUFBUSxHQUFSLFFBQVEsQ0FBa0I7UUFFekQsNEJBQXVCLEdBQXZCLHVCQUF1QixDQUF5QjtRQUNoRCxtQkFBYyxHQUFkLGNBQWMsQ0FBbUI7UUF0RnJDLHFCQUFnQixHQUFXLEdBQUcsQ0FBQztRQUMvQixpQkFBWSxHQUFXLEVBQUUsQ0FBQztRQU0xQix5QkFBb0IsR0FBRyxvQkFBb0IsQ0FBQztRQUU1QywwQkFBcUIsR0FBRyx3QkFBd0IsQ0FBQztRQUNqRCx1QkFBa0IsR0FBRyxvQkFBb0IsQ0FBQztRQUUxQyxpQkFBWSxHQUFHLElBQUksR0FBRyxDQUczQjtZQUNFO2dCQUNJLHFCQUFxQixDQUFDLElBQUk7Z0JBQzFCLEVBQUUsV0FBVyxFQUFFLFNBQVMsQ0FBQSxNQUFNLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRTthQUMzRDtZQUNEO2dCQUNJLHFCQUFxQixDQUFDLFdBQVc7Z0JBQ2pDO29CQUNJLFdBQVcsRUFBRSxTQUFTLENBQUEsY0FBYztvQkFDcEMsV0FBVyxFQUFFLG9CQUFvQjtpQkFDcEM7YUFDSjtZQUNEO2dCQUNJLHFCQUFxQixDQUFDLFVBQVU7Z0JBQ2hDO29CQUNJLFdBQVcsRUFBRSxTQUFTLENBQUEsWUFBWTtvQkFDbEMsV0FBVyxFQUFFLG1CQUFtQjtpQkFDbkM7YUFDSjtZQUNEO2dCQUNJLHFCQUFxQixDQUFDLGVBQWU7Z0JBQ3JDO29CQUNJLFdBQVcsRUFBRSxTQUFTLENBQUEsa0JBQWtCO29CQUN4QyxXQUFXLEVBQUUsd0JBQXdCO2lCQUN4QzthQUNKO1lBQ0Q7Z0JBQ0kscUJBQXFCLENBQUMsTUFBTTtnQkFDNUIsRUFBRSxXQUFXLEVBQUUsU0FBUyxDQUFBLFFBQVEsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFO2FBQ25FO1lBQ0Q7Z0JBQ0kscUJBQXFCLENBQUMsU0FBUztnQkFDL0I7b0JBQ0ksV0FBVyxFQUFFLFNBQVMsQ0FBQSxXQUFXO29CQUNqQyxXQUFXLEVBQUUsa0JBQWtCO2lCQUNsQzthQUNKO1lBQ0Q7Z0JBQ0kscUJBQXFCLENBQUMsYUFBYTtnQkFDbkM7b0JBQ0ksV0FBVyxFQUFFLFNBQVMsQ0FBQSx5QkFBeUI7b0JBQy9DLFdBQVcsRUFBRSxzQkFBc0I7aUJBQ3RDO2FBQ0o7WUFDRDtnQkFDSSxxQkFBcUIsQ0FBQyxTQUFTO2dCQUMvQjtvQkFDSSxXQUFXLEVBQUUsU0FBUyxDQUFBLFdBQVc7b0JBQ2pDLFdBQVcsRUFBRSx1QkFBdUI7aUJBQ3ZDO2FBQ0o7WUFDRDtnQkFDSSxxQkFBcUIsQ0FBQyxnQkFBZ0I7Z0JBQ3RDO29CQUNJLFdBQVcsRUFBRSxTQUFTLENBQUEsd0JBQXdCO29CQUM5QyxXQUFXLEVBQUUseUJBQXlCO2lCQUN6QzthQUNKO1lBQ0Q7Z0JBQ0kscUJBQXFCLENBQUMsV0FBVztnQkFDakM7b0JBQ0ksV0FBVyxFQUFFLFNBQVMsQ0FBQSxhQUFhO29CQUNuQyxXQUFXLEVBQUUsb0JBQW9CO2lCQUNwQzthQUNKO1NBQ0osQ0FBQyxDQUFDO0lBU0gsQ0FBQztJQVFNLFlBQVksQ0FDZixJQUFXLEVBQ1gsTUFBaUI7UUFFakIsTUFBTSxPQUFPLEdBQWtCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFDLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUNmLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQy9CO1FBQ0QsTUFBTSxVQUFVLEdBQXFDLElBQUksQ0FBQyxHQUFHLENBQ3pELENBQUMsTUFBVyxFQUFFLEVBQUU7WUFDWiw0RkFBNEY7WUFDNUYsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FDckIsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssTUFBTSxDQUFDLFdBQVcsQ0FDdkQsQ0FBQztZQUNGLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQ1QsTUFBTTtvQkFDRixPQUFPLENBQUMsSUFBSSxDQUNSLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxLQUFLLFNBQVMsQ0FDOUMsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDO2FBQ3JCO1lBRUQsT0FBTztnQkFDSCxHQUFHLE1BQU07Z0JBQ1QsTUFBTSxFQUFFO29CQUNKLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztvQkFDWCxDQUFDLEVBQUUsTUFBTTtpQkFDWjtnQkFDRCxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7Z0JBQ3ZCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUzthQUM1QixDQUFDO1FBQ04sQ0FBQyxDQUNKLENBQUM7UUFFRixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFO1lBQzlCLElBQUksQ0FBQyxZQUFZLEdBQUc7Z0JBQ2hCLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZO2dCQUMvQixTQUFTLEVBQUUsSUFBSSxXQUFXLEVBQUU7Z0JBQzVCLFFBQVEsRUFBRSxJQUFJLFVBQVUsQ0FBQztvQkFDckIsMEJBQTBCLEVBQUUsSUFBSTtpQkFDbkMsQ0FBQztnQkFDRixNQUFNLEVBQUU7b0JBQ0osQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO29CQUNYLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztpQkFDZDtnQkFDRCxZQUFZLEVBQUUsS0FBSztnQkFDbkIsVUFBVSxFQUFFLEtBQUs7YUFDcEIsQ0FBQztZQUNGLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ3RDO1FBRUQsT0FBTyxVQUFVLENBQUM7SUFDdEIsQ0FBQztJQUVELHdDQUF3QztJQUNqQyxTQUFTO1FBQ1osT0FBTyxDQUNILElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZTtZQUNsQyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsS0FBSyxlQUFlLENBQUMsSUFBSSxDQUM5RCxDQUFDO0lBQ04sQ0FBQztJQUVELG1EQUFtRDtJQUM1QywwQkFBMEI7UUFDN0IsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsS0FBSyxlQUFlLENBQUMsS0FBSyxDQUFDO0lBQ3hFLENBQUM7SUFFTSxrQkFBa0IsQ0FDckIsS0FBaUIsRUFDakIsWUFBNEM7UUFFNUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtZQUN6QixPQUFPO1NBQ1Y7UUFFRCxLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3RDLE9BQU8sRUFBRTtnQkFDTCxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsZUFBZSxFQUFFLHlCQUF5QixDQUFDLE1BQU07YUFDcEQ7U0FDSixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsMEJBQTBCO0lBQ2hCLGVBQWU7UUFDckIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFZLENBQUM7UUFDeEQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUU7WUFDbkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDdkM7UUFFRCxJQUNJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztZQUMzRCxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDVixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU07Z0JBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFVBQVUsS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFDakU7WUFDRSw2SEFBNkg7WUFDN0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDbkMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDeEM7YUFBTTtZQUNILElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFO2dCQUN4QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQzthQUM3QztTQUNKO1FBRUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2pDLHVEQUF1RDtRQUN2RCxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLGdCQUFnQixDQUFDO1FBQ3ZFLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU87WUFDN0IsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLGdCQUFnQixDQUFDO1FBRTFDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUNuQixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FDekQsQ0FBQztJQUNOLENBQUM7SUFFRDs7T0FFRztJQUNPLFVBQVU7UUFDaEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV4QixNQUFNLGFBQWEsR0FDZixJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVc7WUFDOUIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsTUFBTSxHQUFHLENBQUM7WUFDdEMsQ0FBQyxDQUFDLElBQUksdUJBQXVCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUM7WUFDN0QsQ0FBQyxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFFakMsTUFBTSxPQUFPLEdBQUcsSUFBSSxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVuRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQztRQUNyQyxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBTSxFQUFtQixDQUFDO1FBRTdELElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLEVBQUUsZUFBZSxFQUFFO1lBQ2hELFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQjtnQkFDbkMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDO1NBQ3JEO1FBRUQsSUFDSSxVQUFVLENBQUMsU0FBUyxDQUFDLFlBQVk7WUFDakMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLEVBQ2pEO1lBQ0UsVUFBVSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztZQUM5QyxVQUFVLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1NBQ2xEO1FBRUQsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUU7WUFDM0MsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSTtnQkFDNUIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1lBQzdDLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUs7Z0JBQzdCLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztTQUNoRDtRQUVELElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUU7WUFDMUQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDeEM7UUFFRCxLQUFLO2FBQ0EsV0FBVyxFQUFFO2FBQ2IsU0FBUyxDQUFDLGdCQUFnQixDQUFDO1lBQzVCLGdEQUFnRDthQUMvQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO2FBQ3ZELFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ2pCLE1BQU0sT0FBTyxHQUEyQixLQUFLLENBQUMsSUFBSSxDQUFDO1lBQ25ELE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUN4QyxPQUFPLEVBQUU7b0JBQ0wsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQzNCLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO29CQUN6QixnQkFBZ0IsRUFBRSxTQUFTO2lCQUM5QjthQUNKLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQyxDQUFDO1FBRVAsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVEOztPQUVHO0lBQ08sZ0JBQWdCO1FBQ3RCLHFDQUFxQztRQUNyQyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUs7YUFDakIsV0FBVyxFQUFFO2FBQ2IsU0FBUyxDQUFDLDZCQUE2QixDQUFDO1lBQ3pDLGdEQUFnRDthQUMvQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO2FBQ3ZELFNBQVMsQ0FBQyxDQUFDLE1BQW1CLEVBQUUsRUFBRTtZQUMvQixNQUFNLE9BQU8sR0FBZ0MsTUFBTSxDQUFDLElBQUksQ0FBQztZQUN6RCxJQUFJLE9BQU8sQ0FBQyxlQUFlLEtBQUssZUFBZSxDQUFDLEtBQUssRUFBRTtnQkFDbkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDO29CQUN0QyxPQUFPLEVBQUU7d0JBQ0wsSUFBSSxFQUFFLE9BQU8sQ0FBQyxVQUFnQzt3QkFDOUMsZUFBZSxFQUNYLHlCQUF5QixDQUFDLFVBQVU7cUJBQzNDO2lCQUNKLENBQUMsQ0FBQzthQUNOO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFUCwwQkFBMEI7UUFDMUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLO2FBQ2pCLFdBQVcsRUFBRTthQUNiLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQztZQUNwQyxnREFBZ0Q7YUFDL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQzthQUN2RCxTQUFTLENBQUMsQ0FBQyxNQUFtQixFQUFFLEVBQUU7WUFDL0IsTUFBTSxPQUFPLEdBQThCLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDdkQsSUFBSSxPQUFPLENBQUMsZUFBZSxLQUFLLGVBQWUsQ0FBQyxLQUFLLEVBQUU7Z0JBQ25ELElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQztvQkFDdEMsT0FBTyxFQUFFO3dCQUNMLElBQUksRUFBRSxPQUFPLENBQUMsTUFBTTt3QkFDcEIsZUFBZSxFQUFFLHlCQUF5QixDQUFDLE1BQU07cUJBQ3BEO2lCQUNKLENBQUMsQ0FBQzthQUNOO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBRU0saUJBQWlCO1FBQ3BCLE9BQU8sQ0FDSCxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sS0FBSyxxQkFBcUIsQ0FBQyxJQUFJO1lBQ3hELENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWU7WUFDcEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXO2dCQUMxQiwyQkFBMkIsQ0FBQyxZQUFZLENBQy9DLENBQUM7SUFDTixDQUFDO0lBRU0sbUJBQW1CO1FBQ3RCLE9BQU8sQ0FDSCxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sS0FBSyxxQkFBcUIsQ0FBQyxJQUFJO1lBQ3hELENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWU7WUFDcEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXO2dCQUMxQiwyQkFBMkIsQ0FBQyxZQUFZLENBQy9DLENBQUM7SUFDTixDQUFDO0lBRU0sYUFBYSxDQUFDLFFBQWdCLEVBQUUsSUFBMkI7UUFDOUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLFFBQVEsQ0FBQyxDQUFDO1FBQ3BFLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDUixPQUFPO1NBQ1Y7UUFDRCxLQUFLLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLFdBQVcsQ0FBQztRQUU3RCxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUU7WUFDZixJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssU0FBUyxFQUFFO2dCQUNqQywwQkFBMEI7Z0JBQzFCLEtBQUssQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztnQkFDM0IsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7YUFDNUI7aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ25DO1NBQ0o7UUFDRCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVNLGNBQWMsQ0FDakIsWUFBaUQsRUFDakQsZ0JBQXdCO1FBRXhCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQzVDLFlBQVksRUFDWixHQUFHLEVBQ0gsTUFBTSxFQUNOLGdCQUFnQixDQUNuQixDQUFDO1FBRUYsSUFDSSxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVc7WUFDMUIsMkJBQTJCLENBQUMsWUFBWTtZQUM1QyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sS0FBSyxxQkFBcUIsQ0FBQyxXQUFXO1lBQy9ELElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxLQUFLLFNBQVMsRUFDeEM7WUFDRSxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUM7WUFDaEUsTUFBTSxNQUFNLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7WUFFN0IsT0FBTyxHQUFHLFVBQVUsQ0FBQyxNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsZUFBZSxJQUFJLENBQUM7U0FDN0Q7UUFFRCxPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7a0lBaFlpQixnQkFBZ0Isa0JBd0Z0QixrQkFBa0IsYUFDTixXQUFXO3NJQXpGakIsZ0JBQWdCOzs0RkFBaEIsZ0JBQWdCO2tCQURyQyxVQUFVOzswQkF5RkYsTUFBTTsyQkFBQyxrQkFBa0I7OzBCQUN6QixRQUFROzswQkFBSSxNQUFNOzJCQUFDLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtcbiAgICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBJbmplY3QsXG4gICAgSW5qZWN0YWJsZSxcbiAgICBPbkNoYW5nZXMsXG4gICAgT25EZXN0cm95LFxuICAgIE9wdGlvbmFsLFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1kZXByZWNhdGVkXG5pbXBvcnQgeyBtZXJnZSB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcblxuaW1wb3J0IHsgRXZlbnRCdXMsIElEYXRhU291cmNlLCBJRXZlbnQgfSBmcm9tIFwiQG5vdmEtdWkvYml0c1wiO1xuaW1wb3J0IHtcbiAgICBDaGFydEFzc2lzdCxcbiAgICBDaGFydFBhbGV0dGUsXG4gICAgZGVmYXVsdENvbG9yUHJvdmlkZXIsXG4gICAgSUFjY2Vzc29ycyxcbiAgICBJQ2hhcnRBc3Npc3RTZXJpZXMsXG4gICAgSUNoYXJ0RXZlbnQsXG4gICAgSURhdGFQb2ludHNQYXlsb2FkLFxuICAgIElJbnRlcmFjdGlvbkRhdGFQb2ludHNFdmVudCxcbiAgICBJSW50ZXJhY3Rpb25WYWx1ZXNQYXlsb2FkLFxuICAgIElOVEVSQUNUSU9OX0RBVEFfUE9JTlRTX0VWRU5ULFxuICAgIElOVEVSQUNUSU9OX1ZBTFVFU19FVkVOVCxcbiAgICBJbnRlcmFjdGlvblR5cGUsXG4gICAgSVNjYWxlLFxuICAgIElTZXREb21haW5FdmVudFBheWxvYWQsXG4gICAgSVZhbHVlUHJvdmlkZXIsXG4gICAgSVhZR3JpZENvbmZpZyxcbiAgICBJWFlTY2FsZXMsXG4gICAgUmVuZGVyZXIsXG4gICAgU2VxdWVudGlhbENvbG9yUHJvdmlkZXIsXG4gICAgU0VUX0RPTUFJTl9FVkVOVCxcbiAgICBYWUdyaWQsXG4gICAgWFlSZW5kZXJlcixcbiAgICBYWUFjY2Vzc29ycyxcbn0gZnJvbSBcIkBub3ZhLXVpL2NoYXJ0c1wiO1xuXG5pbXBvcnQgeyBJTlRFUkFDVElPTiwgU0VUX1RJTUVGUkFNRSB9IGZyb20gXCIuLi8uLi8uLi8uLi9zZXJ2aWNlcy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgICBEQVRBX1NPVVJDRSxcbiAgICBJSGFzQ2hhbmdlRGV0ZWN0b3IsXG4gICAgUElaWkFHTkFfRVZFTlRfQlVTLFxufSBmcm9tIFwiLi4vLi4vLi4vLi4vdHlwZXNcIjtcbmltcG9ydCB7IExlZ2VuZFBsYWNlbWVudCB9IGZyb20gXCIuLi8uLi8uLi8uLi93aWRnZXQtdHlwZXMvY29tbW9uL3dpZGdldC9sZWdlbmRcIjtcbmltcG9ydCB7XG4gICAgU1VNTUFSWV9MRUdFTkRfQkNHX0NPTE9SLFxuICAgIFNVTU1BUllfTEVHRU5EX0NPTE9SLFxufSBmcm9tIFwiLi4vLi4vdGltZXNlcmllcy1oZWxwZXJzXCI7XG5pbXBvcnQgeyBUaW1lc2VyaWVzU2NhbGVzU2VydmljZSB9IGZyb20gXCIuLi8uLi90aW1lc2VyaWVzLXNjYWxlcy5zZXJ2aWNlXCI7XG5pbXBvcnQge1xuICAgIHRyYW5zZm9ybUNoYW5nZVBvaW50LFxuICAgIHRyYW5zZm9ybURpZmZlcmVuY2UsXG4gICAgdHJhbnNmb3JtRmxvYXRpbmdBdmVyYWdlLFxuICAgIHRyYW5zZm9ybUxpblJlZyxcbiAgICB0cmFuc2Zvcm1Mb2Vzc1Ntb290aGluZyxcbiAgICB0cmFuc2Zvcm1Mb2Vzc1N0YW5kYXJkaXplLFxuICAgIHRyYW5zZm9ybU5vcm1hbGl6ZSxcbiAgICB0cmFuc2Zvcm1QZXJjZW50aWxlU3RkLFxuICAgIHRyYW5zZm9ybVN0YW5kYXJkaXplLFxufSBmcm9tIFwiLi4vLi4vdHJhbnNmb3JtZXIvcHVibGljLWFwaVwiO1xuaW1wb3J0IHtcbiAgICBJVGltZXNlcmllc1dpZGdldFNlcmllc0RhdGEsXG4gICAgVGltZXNlcmllc0NoYXJ0UHJlc2V0LFxuICAgIFRpbWVzZXJpZXNDaGFydFR5cGVzLFxuICAgIFRpbWVzZXJpZXNJbnRlcmFjdGlvblR5cGUsXG4gICAgVGltZXNlcmllc1RyYW5zZm9ybWVyLFxuICAgIFRpbWVzZXJpZXNXaWRnZXRab29tUGx1Z2luLFxuICAgIFRpbWVzZXJpZXNXaWRnZXRQcm9qZWN0VHlwZSxcbn0gZnJvbSBcIi4uLy4uL3R5cGVzXCI7XG5pbXBvcnQgeyBUaW1lc2VyaWVzQ2hhcnRDb21wb25lbnQgfSBmcm9tIFwiLi4vdGltZXNlcmllcy1jaGFydC5jb21wb25lbnRcIjtcblxuaW50ZXJmYWNlIElUcmFuc2Zvcm1lckRlc2NyaXB0aW9uIHtcbiAgICBkaXNwbGF5TmFtZTogc3RyaW5nO1xuICAgIHRyYW5zZm9ybWVyPzogKFxuICAgICAgICBkYXRhOiBJVGltZXNlcmllc1dpZGdldFNlcmllc0RhdGFbXSxcbiAgICAgICAgaGFzUGVyY2VudGlsZT86IGJvb2xlYW5cbiAgICApID0+IElUaW1lc2VyaWVzV2lkZ2V0U2VyaWVzRGF0YVtdO1xufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgWFlDaGFydENvbXBvbmVudFxuICAgIGV4dGVuZHMgVGltZXNlcmllc0NoYXJ0Q29tcG9uZW50XG4gICAgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uRGVzdHJveSwgSUhhc0NoYW5nZURldGVjdG9yXG57XG4gICAgcHVibGljIGNoYXJ0QXNzaXN0OiBDaGFydEFzc2lzdDtcbiAgICBwdWJsaWMgdmFsdWVBY2Nlc3NvcktleTogc3RyaW5nID0gXCJ5XCI7XG4gICAgcHVibGljIGNvbGxlY3Rpb25JZDogc3RyaW5nID0gXCJcIjtcbiAgICBwdWJsaWMgem9vbVBsdWdpbnM6IFRpbWVzZXJpZXNXaWRnZXRab29tUGx1Z2luW107XG5cbiAgICBwcm90ZWN0ZWQgcmVuZGVyZXI6IFJlbmRlcmVyPElBY2Nlc3NvcnM+O1xuICAgIHByb3RlY3RlZCBhY2Nlc3NvcnM6IElBY2Nlc3NvcnM7XG5cbiAgICBwdWJsaWMgdGltZXNlcmllc0NoYXJ0VHlwZXMgPSBUaW1lc2VyaWVzQ2hhcnRUeXBlcztcbiAgICBwdWJsaWMgc3VtbWFyeVNlcmllOiBJQ2hhcnRBc3Npc3RTZXJpZXM8SUFjY2Vzc29ycz47XG4gICAgcHVibGljIHN1bW1hcnlMZWdlbmRCY2dDb2xvciA9IFNVTU1BUllfTEVHRU5EX0JDR19DT0xPUjtcbiAgICBwdWJsaWMgc3VtbWFyeUxlZ2VuZENvbG9yID0gU1VNTUFSWV9MRUdFTkRfQ09MT1I7XG5cbiAgICBwdWJsaWMgdHJhbnNmb3JtZXJzID0gbmV3IE1hcDxcbiAgICAgICAgVGltZXNlcmllc1RyYW5zZm9ybWVyLFxuICAgICAgICBJVHJhbnNmb3JtZXJEZXNjcmlwdGlvblxuICAgID4oW1xuICAgICAgICBbXG4gICAgICAgICAgICBUaW1lc2VyaWVzVHJhbnNmb3JtZXIuTm9uZSxcbiAgICAgICAgICAgIHsgZGlzcGxheU5hbWU6ICRsb2NhbGl6ZWBOb25lYCwgdHJhbnNmb3JtZXI6IHVuZGVmaW5lZCB9LFxuICAgICAgICBdLFxuICAgICAgICBbXG4gICAgICAgICAgICBUaW1lc2VyaWVzVHJhbnNmb3JtZXIuQ2hhbmdlUG9pbnQsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6ICRsb2NhbGl6ZWBDaGFuZ2UgUG9pbnRgLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWVyOiB0cmFuc2Zvcm1DaGFuZ2VQb2ludCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICAgIFRpbWVzZXJpZXNUcmFuc2Zvcm1lci5EaWZmZXJlbmNlLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAkbG9jYWxpemVgRGlmZmVyZW5jZWAsXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtZXI6IHRyYW5zZm9ybURpZmZlcmVuY2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBbXG4gICAgICAgICAgICBUaW1lc2VyaWVzVHJhbnNmb3JtZXIuRmxvYXRpbmdBdmVyYWdlLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAkbG9jYWxpemVgRmxvYXRpbmcgQXZlcmFnZWAsXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtZXI6IHRyYW5zZm9ybUZsb2F0aW5nQXZlcmFnZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICAgIFRpbWVzZXJpZXNUcmFuc2Zvcm1lci5MaW5lYXIsXG4gICAgICAgICAgICB7IGRpc3BsYXlOYW1lOiAkbG9jYWxpemVgTGluZWFyYCwgdHJhbnNmb3JtZXI6IHRyYW5zZm9ybUxpblJlZyB9LFxuICAgICAgICBdLFxuICAgICAgICBbXG4gICAgICAgICAgICBUaW1lc2VyaWVzVHJhbnNmb3JtZXIuTm9ybWFsaXplLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAkbG9jYWxpemVgTm9ybWFsaXplYCxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1lcjogdHJhbnNmb3JtTm9ybWFsaXplLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgW1xuICAgICAgICAgICAgVGltZXNlcmllc1RyYW5zZm9ybWVyLlBlcmNlbnRpbGVTdGQsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6ICRsb2NhbGl6ZWBQZXJjZW50aWxlIFN0YW5kYXJkaXplZGAsXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtZXI6IHRyYW5zZm9ybVBlcmNlbnRpbGVTdGQsXG4gICAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBbXG4gICAgICAgICAgICBUaW1lc2VyaWVzVHJhbnNmb3JtZXIuU21vb3RoaW5nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAkbG9jYWxpemVgU21vb3RoaW5nYCxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1lcjogdHJhbnNmb3JtTG9lc3NTbW9vdGhpbmcsXG4gICAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBbXG4gICAgICAgICAgICBUaW1lc2VyaWVzVHJhbnNmb3JtZXIuTG9lc3NTdGFuZGFyZGl6ZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5TmFtZTogJGxvY2FsaXplYFNtb290aGluZyBTdGFuZGFyZGl6ZWRgLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWVyOiB0cmFuc2Zvcm1Mb2Vzc1N0YW5kYXJkaXplLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgW1xuICAgICAgICAgICAgVGltZXNlcmllc1RyYW5zZm9ybWVyLlN0YW5kYXJkaXplLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAkbG9jYWxpemVgU3RhbmRhcmRpemVgLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWVyOiB0cmFuc2Zvcm1TdGFuZGFyZGl6ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgXSk7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgQEluamVjdChQSVpaQUdOQV9FVkVOVF9CVVMpIHByb3RlY3RlZCBldmVudEJ1czogRXZlbnRCdXM8SUV2ZW50PixcbiAgICAgICAgQE9wdGlvbmFsKCkgQEluamVjdChEQVRBX1NPVVJDRSkgZGF0YVNvdXJjZTogSURhdGFTb3VyY2UsXG4gICAgICAgIHB1YmxpYyB0aW1lc2VyaWVzU2NhbGVzU2VydmljZTogVGltZXNlcmllc1NjYWxlc1NlcnZpY2UsXG4gICAgICAgIHB1YmxpYyBjaGFuZ2VEZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWZcbiAgICApIHtcbiAgICAgICAgc3VwZXIoZXZlbnRCdXMsIHRpbWVzZXJpZXNTY2FsZXNTZXJ2aWNlLCBkYXRhU291cmNlKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgY3JlYXRlQWNjZXNzb3JzKFxuICAgICAgICBjb2xvclByb3ZpZGVyOiBJVmFsdWVQcm92aWRlcjxzdHJpbmc+XG4gICAgKTogSUFjY2Vzc29ycztcblxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBjcmVhdGVDaGFydEFzc2lzdChwYWxldHRlOiBDaGFydFBhbGV0dGUpOiBDaGFydEFzc2lzdDtcblxuICAgIHB1YmxpYyBtYXBTZXJpZXNTZXQoXG4gICAgICAgIGRhdGE6IGFueVtdLFxuICAgICAgICBzY2FsZXM6IElYWVNjYWxlc1xuICAgICk6IElDaGFydEFzc2lzdFNlcmllczxJQWNjZXNzb3JzPltdIHtcbiAgICAgICAgY29uc3QgeVNjYWxlczogSVNjYWxlPGFueT5bXSA9IFtzY2FsZXMueV07XG4gICAgICAgIGlmIChzY2FsZXMueVJpZ2h0KSB7XG4gICAgICAgICAgICB5U2NhbGVzLnB1c2goc2NhbGVzLnlSaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YU1hcHBlZDogSUNoYXJ0QXNzaXN0U2VyaWVzPElBY2Nlc3NvcnM+W10gPSBkYXRhLm1hcChcbiAgICAgICAgICAgIChzZXJpZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIG1hdGNoZXMgc2NhbGUgdW5pdHMgdG8gdGhlIG1ldHJpYyB1bml0IGZvciBlaXRoZXIgbGVmdCB5LWF4aXMgc2NhbGUgb3IgcmlnaHQgeS1heGlzIHNjYWxlXG4gICAgICAgICAgICAgICAgbGV0IHlTY2FsZSA9IHlTY2FsZXMuZmluZChcbiAgICAgICAgICAgICAgICAgICAgKHlTY2FsZSkgPT4geVNjYWxlLnNjYWxlVW5pdHMgPT09IHNlcmllcy5tZXRyaWNVbml0c1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKCF5U2NhbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgeVNjYWxlID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHlTY2FsZXMuZmluZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoeVNjYWxlKSA9PiB5U2NhbGUuc2NhbGVVbml0cyA9PT0gXCJnZW5lcmljXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICkgPz8gc2NhbGVzLnk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgLi4uc2VyaWVzLFxuICAgICAgICAgICAgICAgICAgICBzY2FsZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IHNjYWxlcy54LFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogeVNjYWxlLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICByZW5kZXJlcjogdGhpcy5yZW5kZXJlcixcbiAgICAgICAgICAgICAgICAgICAgYWNjZXNzb3JzOiB0aGlzLmFjY2Vzc29ycyxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIGlmICh0aGlzLndpZGdldERhdGEuc3VtbWFyeVNlcmllKSB7XG4gICAgICAgICAgICB0aGlzLnN1bW1hcnlTZXJpZSA9IHtcbiAgICAgICAgICAgICAgICAuLi50aGlzLndpZGdldERhdGEuc3VtbWFyeVNlcmllLFxuICAgICAgICAgICAgICAgIGFjY2Vzc29yczogbmV3IFhZQWNjZXNzb3JzKCksXG4gICAgICAgICAgICAgICAgcmVuZGVyZXI6IG5ldyBYWVJlbmRlcmVyKHtcbiAgICAgICAgICAgICAgICAgICAgaWdub3JlRm9yRG9tYWluQ2FsY3VsYXRpb246IHRydWUsXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgc2NhbGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIHg6IHNjYWxlcy54LFxuICAgICAgICAgICAgICAgICAgICB5OiBzY2FsZXMueSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNob3dJbkxlZ2VuZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgcHJlcHJvY2VzczogZmFsc2UsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZGF0YU1hcHBlZC5wdXNoKHRoaXMuc3VtbWFyeVNlcmllKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhTWFwcGVkO1xuICAgIH1cblxuICAgIC8qKiBDaGVja3MgaWYgbGVnZW5kIHNob3VsZCBiZSBzaG93bi4gKi9cbiAgICBwdWJsaWMgaGFzTGVnZW5kKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmxlZ2VuZFBsYWNlbWVudCAmJlxuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmxlZ2VuZFBsYWNlbWVudCAhPT0gTGVnZW5kUGxhY2VtZW50Lk5vbmVcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKiogQ2hlY2tzIGlmIGxlZ2VuZCBzaG91bGQgYmUgYWxpZ25lZCB0byByaWdodC4gKi9cbiAgICBwdWJsaWMgbGVnZW5kU2hvdWxkQmVBbGlnbmVkUmlnaHQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZ3VyYXRpb24ubGVnZW5kUGxhY2VtZW50ID09PSBMZWdlbmRQbGFjZW1lbnQuUmlnaHQ7XG4gICAgfVxuXG4gICAgcHVibGljIG9uUHJpbWFyeURlc2NDbGljayhcbiAgICAgICAgZXZlbnQ6IE1vdXNlRXZlbnQsXG4gICAgICAgIGxlZ2VuZFNlcmllczogSUNoYXJ0QXNzaXN0U2VyaWVzPElBY2Nlc3NvcnM+XG4gICAgKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5zZXJpZXNJbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMuZ2V0U3RyZWFtKElOVEVSQUNUSU9OKS5uZXh0KHtcbiAgICAgICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICAgICAgICBkYXRhOiBsZWdlbmRTZXJpZXMsXG4gICAgICAgICAgICAgICAgaW50ZXJhY3Rpb25UeXBlOiBUaW1lc2VyaWVzSW50ZXJhY3Rpb25UeXBlLlNlcmllcyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBVcGRhdGVzIGNoYXJ0IGRhdGEuICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUNoYXJ0RGF0YSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZ3JpZCA9IHRoaXMuY2hhcnRBc3Npc3QuY2hhcnQuZ2V0R3JpZCgpIGFzIFhZR3JpZDtcbiAgICAgICAgaWYgKHRoaXMuc2NhbGVzLnk/LmlkKSB7XG4gICAgICAgICAgICBncmlkLmxlZnRTY2FsZUlkID0gdGhpcy5zY2FsZXMueS5pZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgICh0aGlzLnNjYWxlcy55UmlnaHQgJiYgdGhpcy53aWRnZXREYXRhLnNlcmllcy5sZW5ndGggPT09IDEpIHx8XG4gICAgICAgICAgICAodGhpcy5zY2FsZXMueSAmJlxuICAgICAgICAgICAgICAgIHRoaXMuc2NhbGVzLnlSaWdodCAmJlxuICAgICAgICAgICAgICAgIHRoaXMuc2NhbGVzLnkuc2NhbGVVbml0cyA9PT0gdGhpcy5zY2FsZXMueVJpZ2h0LnNjYWxlVW5pdHMpXG4gICAgICAgICkge1xuICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgb25seSBvbmUgc2VyaWVzIHRvIGRpc3BsYXksIG9yIGlmIHRoZSBsZWZ0IHktYXhpcyBhbmQgcmlnaHQgeS1heGlzIGhhdmUgdGhlIHNhbWUgdW5pdHMsIGJvdGggeS1heGlzZXMgYXJlIHNhbWVcbiAgICAgICAgICAgIHRoaXMuc2NhbGVzLnlSaWdodCA9IHRoaXMuc2NhbGVzLnk7XG4gICAgICAgICAgICBncmlkLnJpZ2h0U2NhbGVJZCA9IHRoaXMuc2NhbGVzLnkuaWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zY2FsZXMueVJpZ2h0Py5pZCkge1xuICAgICAgICAgICAgICAgIGdyaWQucmlnaHRTY2FsZUlkID0gdGhpcy5zY2FsZXMueVJpZ2h0LmlkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZ3JpZENvbmZpZyA9IGdyaWQuY29uZmlnKCk7XG4gICAgICAgIC8vIGhpZGVzIGJvdG9tIGF4aXMgaWYgaXQncyBub3QgbGFzdCBjaGFydCBpbiB0aGUgZ3JvdXBcbiAgICAgICAgZ3JpZENvbmZpZy5heGlzLmJvdHRvbS52aXNpYmxlID0gIXRoaXMuY29uZmlndXJhdGlvbj8uaGFzQWRqYWNlbnRDaGFydDtcbiAgICAgICAgZ3JpZENvbmZpZy5ib3JkZXJzLmJvdHRvbS52aXNpYmxlID1cbiAgICAgICAgICAgICF0aGlzLmNvbmZpZ3VyYXRpb24/Lmhhc0FkamFjZW50Q2hhcnQ7XG5cbiAgICAgICAgdGhpcy5jaGFydEFzc2lzdC51cGRhdGUoXG4gICAgICAgICAgICB0aGlzLm1hcFNlcmllc1NldCh0aGlzLndpZGdldERhdGEuc2VyaWVzLCB0aGlzLnNjYWxlcylcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIGNoYXJ0XG4gICAgICovXG4gICAgcHJvdGVjdGVkIGJ1aWxkQ2hhcnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYnVpbGRDaGFydCQubmV4dCgpO1xuXG4gICAgICAgIGNvbnN0IGNvbG9yUHJvdmlkZXIgPVxuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmNoYXJ0Q29sb3JzICYmXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uY2hhcnRDb2xvcnM/Lmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICA/IG5ldyBTZXF1ZW50aWFsQ29sb3JQcm92aWRlcih0aGlzLmNvbmZpZ3VyYXRpb24uY2hhcnRDb2xvcnMpXG4gICAgICAgICAgICAgICAgOiBkZWZhdWx0Q29sb3JQcm92aWRlcigpO1xuXG4gICAgICAgIGNvbnN0IHBhbGV0dGUgPSBuZXcgQ2hhcnRQYWxldHRlKGNvbG9yUHJvdmlkZXIpO1xuICAgICAgICB0aGlzLmFjY2Vzc29ycyA9IHRoaXMuY3JlYXRlQWNjZXNzb3JzKHBhbGV0dGUuc3RhbmRhcmRDb2xvcnMpO1xuICAgICAgICB0aGlzLmNoYXJ0QXNzaXN0ID0gdGhpcy5jcmVhdGVDaGFydEFzc2lzdChwYWxldHRlKTtcblxuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnRBc3Npc3QuY2hhcnQ7XG4gICAgICAgIGNvbnN0IGdyaWRDb25maWcgPSBjaGFydC5nZXRHcmlkKCkuY29uZmlnKCkgYXMgSVhZR3JpZENvbmZpZztcblxuICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLmdyaWRDb25maWc/LnhBeGlzVGlja3NDb3VudCkge1xuICAgICAgICAgICAgZ3JpZENvbmZpZy5heGlzLmJvdHRvbS5hcHByb3hpbWF0ZVRpY2tzID1cbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uZ3JpZENvbmZpZy54QXhpc1RpY2tzQ291bnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBncmlkQ29uZmlnLmRpbWVuc2lvbi5tYXJnaW5Mb2NrZWQgJiZcbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5ncmlkQ29uZmlnPy5zaWRlTWFyZ2luTG9ja2VkXG4gICAgICAgICkge1xuICAgICAgICAgICAgZ3JpZENvbmZpZy5kaW1lbnNpb24ubWFyZ2luTG9ja2VkLmxlZnQgPSB0cnVlO1xuICAgICAgICAgICAgZ3JpZENvbmZpZy5kaW1lbnNpb24ubWFyZ2luTG9ja2VkLnJpZ2h0ID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24uZ3JpZENvbmZpZz8uc2lkZU1hcmdpbikge1xuICAgICAgICAgICAgZ3JpZENvbmZpZy5kaW1lbnNpb24ubWFyZ2luLmxlZnQgPVxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5ncmlkQ29uZmlnLnNpZGVNYXJnaW47XG4gICAgICAgICAgICBncmlkQ29uZmlnLmRpbWVuc2lvbi5tYXJnaW4ucmlnaHQgPVxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5ncmlkQ29uZmlnLnNpZGVNYXJnaW47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLmVuYWJsZVpvb20gJiYgdGhpcy56b29tUGx1Z2lucy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNoYXJ0LmFkZFBsdWdpbih0aGlzLnpvb21QbHVnaW5zWzBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNoYXJ0XG4gICAgICAgICAgICAuZ2V0RXZlbnRCdXMoKVxuICAgICAgICAgICAgLmdldFN0cmVhbShTRVRfRE9NQUlOX0VWRU5UKVxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1kZXByZWNhdGVkXG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWwobWVyZ2UodGhpcy5kZXN0cm95JCwgdGhpcy5idWlsZENoYXJ0JCkpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gPElTZXREb21haW5FdmVudFBheWxvYWQ+ZXZlbnQuZGF0YTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdEb21haW4gPSBwYXlsb2FkW09iamVjdC5rZXlzKHBheWxvYWQpWzBdXTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmdldFN0cmVhbShTRVRfVElNRUZSQU1FKS5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnREYXRldGltZTogbmV3RG9tYWluWzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kRGF0ZXRpbWU6IG5ld0RvbWFpblsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkUHJlc2V0SWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuc2V0dXBJbnRlcmFjdGlvbigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSB0byBjaGFydCBldmVudHMgYW5kIGVtaXRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc2V0dXBJbnRlcmFjdGlvbigpOiB2b2lkIHtcbiAgICAgICAgLy8gaW50ZXJhY3Rpb24gd2l0aCBjaGFydCBkYXRhIHBvaW50c1xuICAgICAgICB0aGlzLmNoYXJ0QXNzaXN0LmNoYXJ0XG4gICAgICAgICAgICAuZ2V0RXZlbnRCdXMoKVxuICAgICAgICAgICAgLmdldFN0cmVhbShJTlRFUkFDVElPTl9EQVRBX1BPSU5UU19FVkVOVClcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZGVwcmVjYXRlZFxuICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKG1lcmdlKHRoaXMuZGVzdHJveSQsIHRoaXMuYnVpbGRDaGFydCQpKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKHZhbHVlczogSUNoYXJ0RXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkOiBJSW50ZXJhY3Rpb25EYXRhUG9pbnRzRXZlbnQgPSB2YWx1ZXMuZGF0YTtcbiAgICAgICAgICAgICAgICBpZiAocGF5bG9hZC5pbnRlcmFjdGlvblR5cGUgPT09IEludGVyYWN0aW9uVHlwZS5DbGljaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmdldFN0cmVhbShJTlRFUkFDVElPTikubmV4dCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogcGF5bG9hZC5kYXRhUG9pbnRzIGFzIElEYXRhUG9pbnRzUGF5bG9hZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGlvblR5cGU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRpbWVzZXJpZXNJbnRlcmFjdGlvblR5cGUuRGF0YVBvaW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIGludGVyYWN0aW9uIHdpdGggdmFsdWVzXG4gICAgICAgIHRoaXMuY2hhcnRBc3Npc3QuY2hhcnRcbiAgICAgICAgICAgIC5nZXRFdmVudEJ1cygpXG4gICAgICAgICAgICAuZ2V0U3RyZWFtKElOVEVSQUNUSU9OX1ZBTFVFU19FVkVOVClcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZGVwcmVjYXRlZFxuICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKG1lcmdlKHRoaXMuZGVzdHJveSQsIHRoaXMuYnVpbGRDaGFydCQpKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKHZhbHVlczogSUNoYXJ0RXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkOiBJSW50ZXJhY3Rpb25WYWx1ZXNQYXlsb2FkID0gdmFsdWVzLmRhdGE7XG4gICAgICAgICAgICAgICAgaWYgKHBheWxvYWQuaW50ZXJhY3Rpb25UeXBlID09PSBJbnRlcmFjdGlvblR5cGUuQ2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5nZXRTdHJlYW0oSU5URVJBQ1RJT04pLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHBheWxvYWQudmFsdWVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uVHlwZTogVGltZXNlcmllc0ludGVyYWN0aW9uVHlwZS5WYWx1ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGlzcGxheUxlZ2VuZE1lbnUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ucHJlc2V0ID09PSBUaW1lc2VyaWVzQ2hhcnRQcmVzZXQuTGluZSAmJlxuICAgICAgICAgICAgISF0aGlzLmNvbmZpZ3VyYXRpb24uYWxsb3dMZWdlbmRNZW51ICYmXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ucHJvamVjdFR5cGUgPT09XG4gICAgICAgICAgICAgICAgVGltZXNlcmllc1dpZGdldFByb2plY3RUeXBlLlBlcmZzdGFja0FwcFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBkaXNwbGF5RGVsZXRlQnV0dG9uKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnByZXNldCAhPT0gVGltZXNlcmllc0NoYXJ0UHJlc2V0LkxpbmUgJiZcbiAgICAgICAgICAgICEhdGhpcy5jb25maWd1cmF0aW9uLmFsbG93TGVnZW5kTWVudSAmJlxuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnByb2plY3RUeXBlID09PVxuICAgICAgICAgICAgICAgIFRpbWVzZXJpZXNXaWRnZXRQcm9qZWN0VHlwZS5QZXJmc3RhY2tBcHBcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdHJhbnNmb3JtRGF0YShtZXRyaWNJZDogc3RyaW5nLCB0cklkOiBUaW1lc2VyaWVzVHJhbnNmb3JtZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc2VyaWUgPSB0aGlzLndpZGdldERhdGEuc2VyaWVzLmZpbmQoKHMpID0+IHMuaWQgPT09IG1ldHJpY0lkKTtcbiAgICAgICAgaWYgKCFzZXJpZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHNlcmllLnRyYW5zZm9ybWVyID0gdGhpcy50cmFuc2Zvcm1lcnMuZ2V0KHRySWQpPy50cmFuc2Zvcm1lcjtcblxuICAgICAgICBpZiAoc2VyaWUucmF3RGF0YSkge1xuICAgICAgICAgICAgaWYgKHNlcmllLnRyYW5zZm9ybWVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAvLyByZXZlcnQgdHJhbnNmb3JtZWQgZGF0YVxuICAgICAgICAgICAgICAgIHNlcmllLmRhdGEgPSBzZXJpZS5yYXdEYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlWUF4aXNEb21haW4oKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm1TZXJpZXNEYXRhKHNlcmllKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZUNoYXJ0RGF0YSgpO1xuICAgI