cdk-monitoring-constructs
Version:
[](https://badge.fury.io/js/cdk-monitoring-constructs) [](https://m
288 lines • 59.3 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RdsClusterMonitoring = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
const RdsClusterMetricFactory_1 = require("./RdsClusterMetricFactory");
const common_1 = require("../../common");
const dashboard_1 = require("../../dashboard");
const DefaultLatencyTypesToRender = [
common_1.LatencyType.P50,
common_1.LatencyType.P90,
common_1.LatencyType.P99,
];
class RdsClusterMonitoring extends common_1.Monitoring {
constructor(scope, props) {
super(scope, props);
const metricFactory = new RdsClusterMetricFactory_1.RdsClusterMetricFactory(scope.createMetricFactory(), props);
this.connectionsMetric = metricFactory.metricTotalConnectionCount();
this.diskSpaceUsageMetric = metricFactory.metricDiskSpaceUsageInPercent();
this.cpuUsageMetric = metricFactory.metricAverageCpuUsageInPercent();
this.readIopsMetric = metricFactory.metricReadIOPS();
this.writeIopsMetric = metricFactory.metricWriteIOPS();
this.selectLatencyMetrics = {};
this.insertLatencyMetrics = {};
this.updateLatencyMetrics = {};
this.deleteLatencyMetrics = {};
this.commitLatencyMetrics = {};
this.latencyTypesToRender = [
...(props.latencyTypesToRender ?? DefaultLatencyTypesToRender),
];
Object.values(common_1.LatencyType).forEach((latencyType) => {
this.selectLatencyMetrics[latencyType] =
metricFactory.metricSelectLatencyInMillis(latencyType);
this.insertLatencyMetrics[latencyType] =
metricFactory.metricInsertLatencyInMillis(latencyType);
this.updateLatencyMetrics[latencyType] =
metricFactory.metricUpdateLatencyInMillis(latencyType);
this.deleteLatencyMetrics[latencyType] =
metricFactory.metricDeleteLatencyInMillis(latencyType);
this.commitLatencyMetrics[latencyType] =
metricFactory.metricCommitLatencyInMillis(latencyType);
});
const namingStrategy = new dashboard_1.MonitoringNamingStrategy({
...props,
fallbackConstructName: metricFactory.clusterIdentifier,
namedConstruct: props.cluster,
});
this.title = namingStrategy.resolveHumanReadableName();
this.url = scope
.createAwsConsoleUrlFactory()
.getRdsClusterUrl(metricFactory.clusterIdentifier);
const alarmFactory = this.createAlarmFactory(namingStrategy.resolveAlarmFriendlyName());
this.usageAlarmFactory = new common_1.UsageAlarmFactory(alarmFactory);
this.connectionAlarmFactory = new common_1.ConnectionAlarmFactory(alarmFactory);
this.latencyAlarmFactory = new common_1.LatencyAlarmFactory(alarmFactory);
this.usageAnnotations = [];
this.connectionAnnotations = [];
this.readLatencyAnnotations = [];
this.writeLatencyAnnotations = [];
this.iopsAnnotations = [];
for (const disambiguator in props.addDiskSpaceUsageAlarm) {
const alarmProps = props.addDiskSpaceUsageAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxDiskUsagePercentAlarm(this.diskSpaceUsageMetric, alarmProps, disambiguator);
this.usageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addCpuUsageAlarm) {
const alarmProps = props.addCpuUsageAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxCpuUsagePercentAlarm(this.cpuUsageMetric, alarmProps, disambiguator);
this.usageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addMinConnectionCountAlarm) {
const alarmProps = props.addMinConnectionCountAlarm[disambiguator];
const createdAlarm = this.connectionAlarmFactory.addMinConnectionCountAlarm(this.connectionsMetric, alarmProps, disambiguator);
this.connectionAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addMaxConnectionCountAlarm) {
const alarmProps = props.addMaxConnectionCountAlarm[disambiguator];
const createdAlarm = this.connectionAlarmFactory.addMaxConnectionCountAlarm(this.connectionsMetric, alarmProps, disambiguator);
this.connectionAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
const selectLatencyAlarmDefinitions = {
[common_1.LatencyType.P50]: props.addSelectLatencyP50Alarm,
[common_1.LatencyType.P70]: props.addSelectLatencyP70Alarm,
[common_1.LatencyType.P90]: props.addSelectLatencyP90Alarm,
[common_1.LatencyType.P95]: props.addSelectLatencyP95Alarm,
[common_1.LatencyType.P99]: props.addSelectLatencyP99Alarm,
[common_1.LatencyType.P999]: props.addSelectLatencyP999Alarm,
[common_1.LatencyType.P9999]: props.addSelectLatencyP9999Alarm,
[common_1.LatencyType.P100]: props.addSelectLatencyP100Alarm,
[common_1.LatencyType.AVERAGE]: props.addSelectLatencyAverageAlarm,
};
const insertLatencyAlarmDefinitions = {
[common_1.LatencyType.P50]: props.addInsertLatencyP50Alarm,
[common_1.LatencyType.P70]: props.addInsertLatencyP70Alarm,
[common_1.LatencyType.P90]: props.addInsertLatencyP90Alarm,
[common_1.LatencyType.P95]: props.addInsertLatencyP95Alarm,
[common_1.LatencyType.P99]: props.addInsertLatencyP99Alarm,
[common_1.LatencyType.P999]: props.addInsertLatencyP999Alarm,
[common_1.LatencyType.P9999]: props.addInsertLatencyP9999Alarm,
[common_1.LatencyType.P100]: props.addInsertLatencyP100Alarm,
[common_1.LatencyType.AVERAGE]: props.addInsertLatencyAverageAlarm,
};
const updateLatencyAlarmDefinitions = {
[common_1.LatencyType.P50]: props.addUpdateLatencyP50Alarm,
[common_1.LatencyType.P70]: props.addUpdateLatencyP70Alarm,
[common_1.LatencyType.P90]: props.addUpdateLatencyP90Alarm,
[common_1.LatencyType.P95]: props.addUpdateLatencyP95Alarm,
[common_1.LatencyType.P99]: props.addUpdateLatencyP99Alarm,
[common_1.LatencyType.P999]: props.addUpdateLatencyP999Alarm,
[common_1.LatencyType.P9999]: props.addUpdateLatencyP9999Alarm,
[common_1.LatencyType.P100]: props.addUpdateLatencyP100Alarm,
[common_1.LatencyType.AVERAGE]: props.addUpdateLatencyAverageAlarm,
};
const deleteLatencyAlarmDefinitions = {
[common_1.LatencyType.P50]: props.addDeleteLatencyP50Alarm,
[common_1.LatencyType.P70]: props.addDeleteLatencyP70Alarm,
[common_1.LatencyType.P90]: props.addDeleteLatencyP90Alarm,
[common_1.LatencyType.P95]: props.addDeleteLatencyP95Alarm,
[common_1.LatencyType.P99]: props.addDeleteLatencyP99Alarm,
[common_1.LatencyType.P999]: props.addDeleteLatencyP999Alarm,
[common_1.LatencyType.P9999]: props.addDeleteLatencyP9999Alarm,
[common_1.LatencyType.P100]: props.addDeleteLatencyP100Alarm,
[common_1.LatencyType.AVERAGE]: props.addDeleteLatencyAverageAlarm,
};
const commitLatencyAlarmDefinitions = {
[common_1.LatencyType.P50]: props.addCommitLatencyP50Alarm,
[common_1.LatencyType.P70]: props.addCommitLatencyP70Alarm,
[common_1.LatencyType.P90]: props.addCommitLatencyP90Alarm,
[common_1.LatencyType.P95]: props.addCommitLatencyP95Alarm,
[common_1.LatencyType.P99]: props.addCommitLatencyP99Alarm,
[common_1.LatencyType.P999]: props.addCommitLatencyP999Alarm,
[common_1.LatencyType.P9999]: props.addCommitLatencyP9999Alarm,
[common_1.LatencyType.P100]: props.addCommitLatencyP100Alarm,
[common_1.LatencyType.AVERAGE]: props.addCommitLatencyAverageAlarm,
};
for (const [latencyType, alarmDefinition] of Object.entries(selectLatencyAlarmDefinitions)) {
for (const disambiguator in alarmDefinition) {
const alarmProps = alarmDefinition[disambiguator];
const latencyTypeEnum = latencyType;
const metric = this.selectLatencyMetrics[latencyTypeEnum];
const createdAlarm = this.latencyAlarmFactory.addLatencyAlarm(metric, latencyTypeEnum, alarmProps, disambiguator, "Select");
this.readLatencyAnnotations.push(createdAlarm.annotation);
this.latencyTypesToRender.push(latencyTypeEnum);
this.addAlarm(createdAlarm);
}
}
for (const [latencyType, alarmDefinition] of Object.entries(insertLatencyAlarmDefinitions)) {
for (const disambiguator in alarmDefinition) {
const alarmProps = alarmDefinition[disambiguator];
const latencyTypeEnum = latencyType;
const metric = this.insertLatencyMetrics[latencyTypeEnum];
const createdAlarm = this.latencyAlarmFactory.addLatencyAlarm(metric, latencyTypeEnum, alarmProps, disambiguator, "Insert");
this.writeLatencyAnnotations.push(createdAlarm.annotation);
this.latencyTypesToRender.push(latencyTypeEnum);
this.addAlarm(createdAlarm);
}
}
for (const [latencyType, alarmDefinition] of Object.entries(updateLatencyAlarmDefinitions)) {
for (const disambiguator in alarmDefinition) {
const alarmProps = alarmDefinition[disambiguator];
const latencyTypeEnum = latencyType;
const metric = this.updateLatencyMetrics[latencyTypeEnum];
const createdAlarm = this.latencyAlarmFactory.addLatencyAlarm(metric, latencyTypeEnum, alarmProps, disambiguator, "Update");
this.writeLatencyAnnotations.push(createdAlarm.annotation);
this.latencyTypesToRender.push(latencyTypeEnum);
this.addAlarm(createdAlarm);
}
}
for (const [latencyType, alarmDefinition] of Object.entries(deleteLatencyAlarmDefinitions)) {
for (const disambiguator in alarmDefinition) {
const alarmProps = alarmDefinition[disambiguator];
const latencyTypeEnum = latencyType;
const metric = this.deleteLatencyMetrics[latencyTypeEnum];
const createdAlarm = this.latencyAlarmFactory.addLatencyAlarm(metric, latencyTypeEnum, alarmProps, disambiguator, "Delete");
this.writeLatencyAnnotations.push(createdAlarm.annotation);
this.latencyTypesToRender.push(latencyTypeEnum);
this.addAlarm(createdAlarm);
}
}
for (const [latencyType, alarmDefinition] of Object.entries(commitLatencyAlarmDefinitions)) {
for (const disambiguator in alarmDefinition) {
const alarmProps = alarmDefinition[disambiguator];
const latencyTypeEnum = latencyType;
const metric = this.commitLatencyMetrics[latencyTypeEnum];
const createdAlarm = this.latencyAlarmFactory.addLatencyAlarm(metric, latencyTypeEnum, alarmProps, disambiguator, "Commit");
this.writeLatencyAnnotations.push(createdAlarm.annotation);
this.latencyTypesToRender.push(latencyTypeEnum);
this.addAlarm(createdAlarm);
}
}
for (const disambiguator in props.addReadIOPSAlarm) {
const alarmProps = props.addReadIOPSAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxReadIOPSAlarm(this.readIopsMetric, alarmProps, disambiguator);
this.usageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addWriteIOPSAlarm) {
const alarmProps = props.addWriteIOPSAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxWriteIOPSAlarm(this.writeIopsMetric, alarmProps, disambiguator);
this.usageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
props.useCreatedAlarms?.consume(this.createdAlarms());
}
summaryWidgets() {
return [
this.createTitleWidget(),
this.createCpuAndDiskUsageWidget(common_1.QuarterWidth, common_1.DefaultSummaryWidgetHeight),
this.createConnectionsWidget(common_1.QuarterWidth, common_1.DefaultSummaryWidgetHeight),
this.createLatencyWidget(common_1.QuarterWidth, common_1.DefaultSummaryWidgetHeight),
this.createIOPSWidget(common_1.QuarterWidth, common_1.DefaultSummaryWidgetHeight),
];
}
widgets() {
return [
this.createTitleWidget(),
this.createCpuAndDiskUsageWidget(common_1.QuarterWidth, common_1.DefaultGraphWidgetHeight),
this.createConnectionsWidget(common_1.QuarterWidth, common_1.DefaultGraphWidgetHeight),
this.createLatencyWidget(common_1.QuarterWidth, common_1.DefaultGraphWidgetHeight),
this.createIOPSWidget(common_1.QuarterWidth, common_1.DefaultGraphWidgetHeight),
];
}
createTitleWidget() {
return new dashboard_1.MonitoringHeaderWidget({
family: "RDS Cluster",
title: this.title,
goToLinkUrl: this.url,
});
}
createCpuAndDiskUsageWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "CPU/Disk Usage",
left: [this.cpuUsageMetric, this.diskSpaceUsageMetric],
leftYAxis: common_1.PercentageAxisFromZeroToHundred,
leftAnnotations: this.usageAnnotations,
});
}
createConnectionsWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Connections",
left: [this.connectionsMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.connectionAnnotations,
});
}
createLatencyWidget(width, height) {
const left = Array.from(new Set(this.latencyTypesToRender))
.sort()
.reduce((metrics, type) => {
metrics.push(this.selectLatencyMetrics[type], this.insertLatencyMetrics[type], this.updateLatencyMetrics[type], this.deleteLatencyMetrics[type], this.commitLatencyMetrics[type]);
return metrics;
}, []);
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Query Duration",
left,
leftYAxis: common_1.TimeAxisMillisFromZero,
leftAnnotations: [
...this.readLatencyAnnotations,
...this.writeLatencyAnnotations,
],
});
}
createIOPSWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "IOPS",
left: [this.readIopsMetric, this.writeIopsMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.iopsAnnotations,
});
}
}
exports.RdsClusterMonitoring = RdsClusterMonitoring;
_a = JSII_RTTI_SYMBOL_1;
RdsClusterMonitoring[_a] = { fqn: "cdk-monitoring-constructs.RdsClusterMonitoring", version: "9.19.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmRzQ2x1c3Rlck1vbml0b3JpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJSZHNDbHVzdGVyTW9uaXRvcmluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLCtEQUlvQztBQUVwQyx1RUFHbUM7QUFDbkMseUNBb0JzQjtBQUN0QiwrQ0FHeUI7QUFFekIsTUFBTSwyQkFBMkIsR0FBRztJQUNsQyxvQkFBVyxDQUFDLEdBQUc7SUFDZixvQkFBVyxDQUFDLEdBQUc7SUFDZixvQkFBVyxDQUFDLEdBQUc7Q0FDaEIsQ0FBQztBQWdGRixNQUFhLG9CQUFxQixTQUFRLG1CQUFVO0lBMkJsRCxZQUFZLEtBQXNCLEVBQUUsS0FBZ0M7UUFDbEUsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUVwQixNQUFNLGFBQWEsR0FBRyxJQUFJLGlEQUF1QixDQUMvQyxLQUFLLENBQUMsbUJBQW1CLEVBQUUsRUFDM0IsS0FBSyxDQUNOLENBQUM7UUFDRixJQUFJLENBQUMsaUJBQWlCLEdBQUcsYUFBYSxDQUFDLDBCQUEwQixFQUFFLENBQUM7UUFDcEUsSUFBSSxDQUFDLG9CQUFvQixHQUFHLGFBQWEsQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO1FBQzFFLElBQUksQ0FBQyxjQUFjLEdBQUcsYUFBYSxDQUFDLDhCQUE4QixFQUFFLENBQUM7UUFDckUsSUFBSSxDQUFDLGNBQWMsR0FBRyxhQUFhLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDckQsSUFBSSxDQUFDLGVBQWUsR0FBRyxhQUFhLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFdkQsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsb0JBQW9CLEdBQUcsRUFBRSxDQUFDO1FBQy9CLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsb0JBQW9CLEdB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QUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyx5QkFBeUI7WUFDbkQsQ0FBQyxvQkFBVyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQywwQkFBMEI7WUFDckQsQ0FBQyxvQkFBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyx5QkFBeUI7WUFDbkQsQ0FBQyxvQkFBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyw0QkFBNEI7U0FDMUQsQ0FBQztRQUVGLE1BQU0sNkJBQTZCLEdBQUc7WUFDcEMsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyx5QkFBeUI7WUFDbkQsQ0FBQyxvQkFBVyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQywwQkFBMEI7WUFDckQsQ0FBQyxvQkFBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyx5QkFBeUI7WUFDbkQsQ0FBQyxvQkFBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyw0QkFBNEI7U0FDMUQsQ0FBQztRQUVGLE1BQU0sNkJBQTZCLEdBQUc7WUFDcEMsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyx5QkFBeUI7WUFDbkQsQ0FBQyxvQkFBVyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQywwQkFBMEI7WUFDckQsQ0FBQyxvQkFBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyx5QkFBeUI7WUFDbkQsQ0FBQyxvQkFBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyw0QkFBNEI7U0FDMUQsQ0FBQztRQUVGLE1BQU0sNkJBQTZCLEdBQUc7WUFDcEMsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyx3QkFBd0I7WUFDakQsQ0FBQyxvQkFBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyx5QkFB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LENBQUMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDeEIsT0FBTyxDQUFDLElBQUksQ0FDVixJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEVBQy9CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsRUFDL0IsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxFQUMvQixJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEVBQy9CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FDaEMsQ0FBQztZQUNGLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLENBQUMsRUFBRSxFQUE4QixDQUFDLENBQUM7UUFFckMsT0FBTyxJQUFJLDRCQUFXLENBQUM7WUFDckIsS0FBSztZQUNMLE1BQU07WUFDTixLQUFLLEVBQUUsZ0JBQWdCO1lBQ3ZCLElBQUk7WUFDSixTQUFTLEVBQUUsK0JBQXNCO1lBQ2pDLGVBQWUsRUFBRTtnQkFDZixHQUFHLElBQUksQ0FBQyxzQkFBc0I7Z0JBQzlCLEdBQUcsSUFBSSxDQUFDLHVCQUF1QjthQUNoQztTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxLQUFhLEVBQUUsTUFBYztRQUM1QyxPQUFPLElBQUksNEJBQVcsQ0FBQztZQUNyQixLQUFLO1lBQ0wsTUFBTTtZQUNOLEtBQUssRUFBRSxNQUFNO1lBQ2IsSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDO1lBQ2pELFNBQVMsRUFBRSwwQkFBaUI7WUFDNUIsZUFBZSxFQUFFLElBQUksQ0FBQyxlQUFlO1NBQ3RDLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBcFpILG9EQXFaQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEdyYXBoV2lkZ2V0LFxuICBIb3Jpem9udGFsQW5ub3RhdGlvbixcbiAgSVdpZGdldCxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoXCI7XG5cbmltcG9ydCB7XG4gIFJkc0NsdXN0ZXJNZXRyaWNGYWN0b3J5LFxuICBSZHNDbHVzdGVyTWV0cmljRmFjdG9yeVByb3BzLFxufSBmcm9tIFwiLi9SZHNDbHVzdGVyTWV0cmljRmFjdG9yeVwiO1xuaW1wb3J0IHtcbiAgQmFzZU1vbml0b3JpbmdQcm9wcyxcbiAgQ29ubmVjdGlvbkFsYXJtRmFjdG9yeSxcbiAgQ291bnRBeGlzRnJvbVplcm8sXG4gIERlZmF1bHRHcmFwaFdpZGdldEhlaWdodCxcbiAgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQsXG4gIEhpZ2hDb25uZWN0aW9uQ291bnRUaHJlc2hvbGQsXG4gIExhdGVuY3lBbGFybUZhY3RvcnksXG4gIExhdGVuY3lUaHJlc2hvbGQsXG4gIExhdGVuY3lUeXBlLFxuICBMb3dDb25uZWN0aW9uQ291bnRUaHJlc2hvbGQsXG4gIE1heFVzYWdlQ291bnRUaHJlc2hvbGQsXG4gIE1ldHJpY1dpdGhBbGFybVN1cHBvcnQsXG4gIE1vbml0b3JpbmcsXG4gIE1vbml0b3JpbmdTY29wZSxcbiAgUGVyY2VudGFnZUF4aXNGcm9tWmVyb1RvSHVuZHJlZCxcbiAgUXVhcnRlcldpZHRoLFxuICBUaW1lQXhpc01pbGxpc0Zyb21aZXJvLFxuICBVc2FnZUFsYXJtRmFjdG9yeSxcbiAgVXNhZ2VUaHJlc2hvbGQsXG59IGZyb20gXCIuLi8uLi9jb21tb25cIjtcbmltcG9ydCB7XG4gIE1vbml0b3JpbmdIZWFkZXJXaWRnZXQsXG4gIE1vbml0b3JpbmdOYW1pbmdTdHJhdGVneSxcbn0gZnJvbSBcIi4uLy4uL2Rhc2hib2FyZFwiO1xuXG5jb25zdCBEZWZhdWx0TGF0ZW5jeVR5cGVzVG9SZW5kZXIgPSBbXG4gIExhdGVuY3lUeXBlLlA1MCxcbiAgTGF0ZW5jeVR5cGUuUDkwLFxuICBMYXRlbmN5VHlwZS5QOTksXG5dO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJkc0NsdXN0ZXJNb25pdG9yaW5nT3B0aW9ucyBleHRlbmRzIEJhc2VNb25pdG9yaW5nUHJvcHMge1xuICByZWFkb25seSBhZGREaXNrU3BhY2VVc2FnZUFsYXJtPzogUmVjb3JkPHN0cmluZywgVXNhZ2VUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRDcHVVc2FnZUFsYXJtPzogUmVjb3JkPHN0cmluZywgVXNhZ2VUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRNaW5Db25uZWN0aW9uQ291bnRBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTG93Q29ubmVjdGlvbkNvdW50VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZE1heENvbm5lY3Rpb25Db3VudEFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBIaWdoQ29ubmVjdGlvbkNvdW50VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZFJlYWRJT1BTQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBNYXhVc2FnZUNvdW50VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkV3JpdGVJT1BTQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBNYXhVc2FnZUNvdW50VGhyZXNob2xkPjtcblxuICByZWFkb25seSBhZGRTZWxlY3RMYXRlbmN5UDUwQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkU2VsZWN0TGF0ZW5jeVA3MEFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZFNlbGVjdExhdGVuY3lQOTBBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRTZWxlY3RMYXRlbmN5UDk1QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkU2VsZWN0TGF0ZW5jeVA5OUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZFNlbGVjdExhdGVuY3lQOTk5QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkU2VsZWN0TGF0ZW5jeVA5OTk5QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkU2VsZWN0TGF0ZW5jeVAxMDBBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRTZWxlY3RMYXRlbmN5QXZlcmFnZUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG5cbiAgcmVhZG9ubHkgYWRkSW5zZXJ0TGF0ZW5jeVA1MEFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZEluc2VydExhdGVuY3lQNzBBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRJbnNlcnRMYXRlbmN5UDkwQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkSW5zZXJ0TGF0ZW5jeVA5NUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZEluc2VydExhdGVuY3lQOTlBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRJbnNlcnRMYXRlbmN5UDk5OUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZEluc2VydExhdGVuY3lQOTk5OUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZEluc2VydExhdGVuY3lQMTAwQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkSW5zZXJ0TGF0ZW5jeUF2ZXJhZ2VBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuXG4gIHJlYWRvbmx5IGFkZFVwZGF0ZUxhdGVuY3lQNTBBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRVcGRhdGVMYXRlbmN5UDcwQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkVXBkYXRlTGF0ZW5jeVA5MEFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZFVwZGF0ZUxhdGVuY3lQOTVBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRVcGRhdGVMYXRlbmN5UDk5QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkVXBkYXRlTGF0ZW5jeVA5OTlBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRVcGRhdGVMYXRlbmN5UDk5OTlBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRVcGRhdGVMYXRlbmN5UDEwMEFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZFVwZGF0ZUxhdGVuY3lBdmVyYWdlQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcblxuICByZWFkb25seSBhZGREZWxldGVMYXRlbmN5UDUwQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkRGVsZXRlTGF0ZW5jeVA3MEFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZERlbGV0ZUxhdGVuY3lQOTBBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGREZWxldGVMYXRlbmN5UDk1QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkRGVsZXRlTGF0ZW5jeVA5OUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZERlbGV0ZUxhdGVuY3lQOTk5QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkRGVsZXRlTGF0ZW5jeVA5OTk5QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkRGVsZXRlTGF0ZW5jeVAxMDBBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGREZWxldGVMYXRlbmN5QXZlcmFnZUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG5cbiAgcmVhZG9ubHkgYWRkQ29tbWl0TGF0ZW5jeVA1MEFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZENvbW1pdExhdGVuY3lQNzBBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRDb21taXRMYXRlbmN5UDkwQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkQ29tbWl0TGF0ZW5jeVA5NUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZENvbW1pdExhdGVuY3lQOTlBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRDb21taXRMYXRlbmN5UDk5OUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZENvbW1pdExhdGVuY3lQOTk5OUFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZENvbW1pdExhdGVuY3lQMTAwQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkQ29tbWl0TGF0ZW5jeUF2ZXJhZ2VBbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+O1xuXG4gIC8qKlxuICAgKiBZb3UgY2FuIHNwZWNpZnkgd2hhdCBsYXRlbmN5IHR5cGVzIHlvdSB3YW50IHRvIGJlIHJlbmRlcmVkIGluIHRoZSBkYXNoYm9hcmRzLlxuICAgKiBOb3RlOiBhbnkgbGF0ZW5jeSB0eXBlIHdpdGggYW4gYWxhcm0gd2lsbCBiZSBhbHNvIGFkZGVkIGF1dG9tYXRpY2FsbHkuXG4gICAqIElmIHRoZSBsaXN0IGlzIHVuZGVmaW5lZCwgZGVmYXVsdCB2YWx1ZXMgd2lsbCBiZSBzaG93bi5cbiAgICogSWYgdGhlIGxpc3QgaXMgZW1wdHksIG9ubHkgdGhlIGxhdGVuY3kgdHlwZXMgd2l0aCBhbiBhbGFybSB3aWxsIGJlIHNob3duIChpZiBhbnkpLlxuICAgKiBAZGVmYXVsdCAtIHA5MCBmb3IgYWxsIG9wZXJhdGlvbiB0eXBlc1xuICAgKi9cbiAgcmVhZG9ubHkgbGF0ZW5jeVR5cGVzVG9SZW5kZXI/OiBMYXRlbmN5VHlwZVtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJkc0NsdXN0ZXJNb25pdG9yaW5nUHJvcHNcbiAgZXh0ZW5kcyBSZHNDbHVzdGVyTWV0cmljRmFjdG9yeVByb3BzLFxuICAgIFJkc0NsdXN0ZXJNb25pdG9yaW5nT3B0aW9ucyB7fVxuXG5leHBvcnQgY2xhc3MgUmRzQ2x1c3Rlck1vbml0b3JpbmcgZXh0ZW5kcyBNb25pdG9yaW5nIHtcbiAgcmVhZG9ubHkgdGl0bGU6IHN0cmluZztcbiAgcmVhZG9ubHkgdXJsPzogc3RyaW5nO1xuXG4gIHJlYWRvbmx5IHVzYWdlQWxhcm1GYWN0b3J5OiBVc2FnZUFsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgY29ubmVjdGlvbkFsYXJtRmFjdG9yeTogQ29ubmVjdGlvbkFsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgbGF0ZW5jeUFsYXJtRmFjdG9yeTogTGF0ZW5jeUFsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgdXNhZ2VBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcbiAgcmVhZG9ubHkgY29ubmVjdGlvbkFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSByZWFkTGF0ZW5jeUFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSB3cml0ZUxhdGVuY3lBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcbiAgcmVhZG9ubHkgaW9wc0Fubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuXG4gIHJlYWRvbmx5IGNvbm5lY3Rpb25zTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBkaXNrU3BhY2VVc2FnZU1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgY3B1VXNhZ2VNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IHJlYWRJb3BzTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSB3cml0ZUlvcHNNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG5cbiAgLy8ga2V5cyBhcmUgTGF0ZW5jeVR5cGUsIGJ1dCBKU0lJIGRvZXNuJ3QgbGlrZSBub24tc3RyaW5nIHR5cGVzXG4gIHJlYWRvbmx5IHNlbGVjdExhdGVuY3lNZXRyaWNzOiBSZWNvcmQ8c3RyaW5nLCBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0PjtcbiAgcmVhZG9ubHkgaW5zZXJ0TGF0ZW5jeU1ldHJpY3M6IFJlY29yZDxzdHJpbmcsIE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ+O1xuICByZWFkb25seSB1cGRhdGVMYXRlbmN5TWV0cmljczogUmVjb3JkPHN0cmluZywgTWV0cmljV2l0aEFsYXJtU3VwcG9ydD47XG4gIHJlYWRvbmx5IGRlbGV0ZUxhdGVuY3lNZXRyaWNzOiBSZWNvcmQ8c3RyaW5nLCBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0PjtcbiAgcmVhZG9ubHkgY29tbWl0TGF0ZW5jeU1ldHJpY3M6IFJlY29yZDxzdHJpbmcsIE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ+O1xuICByZWFkb25seSBsYXRlbmN5VHlwZXNUb1JlbmRlcjogc3RyaW5nW107XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IE1vbml0b3JpbmdTY29wZSwgcHJvcHM6IFJkc0NsdXN0ZXJNb25pdG9yaW5nUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgcHJvcHMpO1xuXG4gICAgY29uc3QgbWV0cmljRmFjdG9yeSA9IG5ldyBSZHNDbHVzdGVyTWV0cmljRmFjdG9yeShcbiAgICAgIHNjb3BlLmNyZWF0ZU1ldHJpY0ZhY3RvcnkoKSxcbiAgICAgIHByb3BzLFxuICAgICk7XG4gICAgdGhpcy5jb25uZWN0aW9uc01ldHJpYyA9IG1ldHJpY0ZhY3RvcnkubWV0cmljVG90YWxDb25uZWN0aW9uQ291bnQoKTtcbiAgICB0aGlzLmRpc2tTcGFjZVVzYWdlTWV0cmljID0gbWV0cmljRmFjdG9yeS5tZXRyaWNEaXNrU3BhY2VVc2FnZUluUGVyY2VudCgpO1xuICAgIHRoaXMuY3B1VXNhZ2VNZXRyaWMgPSBtZXRyaWNGYWN0b3J5Lm1ldHJpY0F2ZXJhZ2VDcHVVc2FnZUluUGVyY2VudCgpO1xuICAgIHRoaXMucmVhZElvcHNNZXRyaWMgPSBtZXRyaWNGYWN0b3J5Lm1ldHJpY1JlYWRJT1BTKCk7XG4gICAgdGhpcy53cml0ZUlvcHNNZXRyaWMgPSBtZXRyaWNGYWN0b3J5Lm1ldHJpY1dyaXRlSU9QUygpO1xuXG4gICAgdGhpcy5zZWxlY3RMYXRlbmN5TWV0cmljcyA9IHt9O1xuICAgIHRoaXMuaW5zZXJ0TGF0ZW5jeU1ldHJpY3MgPSB7fTtcbiAgICB0aGlzLnVwZGF0ZUxhdGVuY3lNZXRyaWNzID0ge307XG4gICAgdGhpcy5kZWxldGVMYXRlbmN5TWV0cmljcyA9IHt9O1xuICAgIHRoaXMuY29tbWl0TGF0ZW5jeU1ldHJpY3MgPSB7fTtcbiAgICB0aGlzLmxhdGVuY3lUeXBlc1RvUmVuZGVyID0gW1xuICAgICAgLi4uKHByb3BzLmxhdGVuY3lUeXBlc1RvUmVuZGVyID8/IERlZmF1bHRMYXRlbmN5VHlwZXNUb1JlbmRlciksXG4gICAgXTtcblxuICAgIE9iamVjdC52YWx1ZXMoTGF0ZW5jeVR5cGUpLmZvckVhY2goKGxhdGVuY3lUeXBlKSA9PiB7XG4gICAgICB0aGlzLnNlbGVjdExhdGVuY3lNZXRyaWNzW2xhdGVuY3lUeXBlXSA9XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljU2VsZWN0TGF0ZW5jeUluTWlsbGlzKGxhdGVuY3lUeXBlKTtcbiAgICAgIHRoaXMuaW5zZXJ0TGF0ZW5jeU1ldHJpY3NbbGF0ZW5jeVR5cGVdID1cbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNJbnNlcnRMYXRlbmN5SW5NaWxsaXMobGF0ZW5jeVR5cGUpO1xuICAgICAgdGhpcy51cGRhdGVMYXRlbmN5TWV0cmljc1tsYXRlbmN5VHlwZV0gPVxuICAgICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY1VwZGF0ZUxhdGVuY3lJbk1pbGxpcyhsYXRlbmN5VHlwZSk7XG4gICAgICB0aGlzLmRlbGV0ZUxhdGVuY3lNZXRyaWNzW2xhdGVuY3lUeXBlXSA9XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljRGVsZXRlTGF0ZW5jeUluTWlsbGlzKGxhdGVuY3lUeXBlKTtcbiAgICAgIHRoaXMuY29tbWl0TGF0ZW5jeU1ldHJpY3NbbGF0ZW5jeVR5cGVdID1cbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNDb21taXRMYXRlbmN5SW5NaWxsaXMobGF0ZW5jeVR5cGUpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgbmFtaW5nU3RyYXRlZ3kgPSBuZXcgTW9uaXRvcmluZ05hbWluZ1N0cmF0ZWd5KHtcbiAgICAgIC4uLnByb3BzLFxuICAgICAgZmFsbGJhY2tDb25zdHJ1Y3ROYW1lOiBtZXRyaWNGYWN0b3J5LmNsdXN0ZXJJZGVudGlmaWVyLFxuICAgICAgbmFtZWRDb25zdHJ1Y3Q6IHByb3BzLmNsdXN0ZXIsXG4gICAgfSk7XG4gICAgdGhpcy50aXRsZSA9IG5hbWluZ1N0cmF0ZWd5LnJlc29sdmVIdW1hblJlYWRhYmxlTmFtZSgpO1xuICAgIHRoaXMudXJsID0gc2NvcGVcbiAgICAgIC5jcmVhdGVBd3NDb25zb2xlVXJsRmFjdG9yeSgpXG4gICAgICAuZ2V0UmRzQ2x1c3RlclVybChtZXRyaWNGYWN0b3J5LmNsdXN0ZXJJZGVudGlmaWVyKTtcbiAgICBjb25zdCBhbGFybUZhY3RvcnkgPSB0aGlzLmNyZWF0ZUFsYXJtRmFjdG9yeShcbiAgICAgIG5hbWluZ1N0cmF0ZWd5LnJlc29sdmVBbGFybUZyaWVuZGx5TmFtZSgpLFxuICAgICk7XG4gICAgdGhpcy51c2FnZUFsYXJtRmFjdG9yeSA9IG5ldyBVc2FnZUFsYXJtRmFjdG9yeShhbGFybUZhY3RvcnkpO1xuICAgIHRoaXMuY29ubmVjdGlvbkFsYXJtRmFjdG9yeSA9IG5ldyBDb25uZWN0aW9uQWxhcm1GYWN0b3J5KGFsYXJtRmFjdG9yeSk7XG4gICAgdGhpcy5sYXRlbmN5QWxhcm1GYWN0b3J5ID0gbmV3IExhdGVuY3lBbGFybUZhY3RvcnkoYWxhcm1GYWN0b3J5KTtcblxuICAgIHRoaXMudXNhZ2VBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMuY29ubmVjdGlvbkFubm90YXRpb25zID0gW107XG4gICAgdGhpcy5yZWFkTGF0ZW5jeUFubm90YXRpb25zID0gW107XG4gICAgdGhpcy53cml0ZUxhdGVuY3lBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMuaW9wc0Fubm90YXRpb25zID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkRGlza1NwYWNlVXNhZ2VBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZERpc2tTcGFjZVVzYWdlQWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnVzYWdlQWxhcm1GYWN0b3J5LmFkZE1heERpc2tVc2FnZVBlcmNlbnRBbGFybShcbiAgICAgICAgdGhpcy5kaXNrU3BhY2VVc2FnZU1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICk7XG4gICAgICB0aGlzLnVzYWdlQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZENwdVVzYWdlQWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRDcHVVc2FnZUFsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy51c2FnZUFsYXJtRmFjdG9yeS5hZGRNYXhDcHVVc2FnZVBlcmNlbnRBbGFybShcbiAgICAgICAgdGhpcy5jcHVVc2FnZU1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICk7XG4gICAgICB0aGlzLnVzYWdlQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZE1pbkNvbm5lY3Rpb25Db3VudEFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkTWluQ29ubmVjdGlvbkNvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPVxuICAgICAgICB0aGlzLmNvbm5lY3Rpb25BbGFybUZhY3RvcnkuYWRkTWluQ29ubmVjdGlvbkNvdW50QWxhcm0oXG4gICAgICAgICAgdGhpcy5jb25uZWN0aW9uc01ldHJpYyxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICk7XG4gICAgICB0aGlzLmNvbm5lY3Rpb25Bbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkTWF4Q29ubmVjdGlvbkNvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRNYXhDb25uZWN0aW9uQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbkFsYXJtRmFjdG9yeS5hZGRNYXhDb25uZWN0aW9uQ291bnRBbGFybShcbiAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25zTWV0cmljLFxuICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgKTtcbiAgICAgIHRoaXMuY29ubmVjdGlvbkFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cblxuICAgIGNvbnN0IHNlbGVjdExhdGVuY3lBbGFybURlZmluaXRpb25zID0ge1xuICAgICAgW0xhdGVuY3lUeXBlLlA1MF06IHByb3BzLmFkZFNlbGVjdExhdGVuY3lQNTBBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QNzBdOiBwcm9wcy5hZGRTZWxlY3RMYXRlbmN5UDcwQWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDkwXTogcHJvcHMuYWRkU2VsZWN0TGF0ZW5jeVA5MEFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA5NV06IHByb3BzLmFkZFNlbGVjdExhdGVuY3lQOTVBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTldOiBwcm9wcy5hZGRTZWxlY3RMYXRlbmN5UDk5QWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDk5OV06IHByb3BzLmFkZFNlbGVjdExhdGVuY3lQOTk5QWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDk5OTldOiBwcm9wcy5hZGRTZWxlY3RMYXRlbmN5UDk5OTlBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QMTAwXTogcHJvcHMuYWRkU2VsZWN0TGF0ZW5jeVAxMDBBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5BVkVSQUdFXTogcHJvcHMuYWRkU2VsZWN0TGF0ZW5jeUF2ZXJhZ2VBbGFybSxcbiAgICB9O1xuXG4gICAgY29uc3QgaW5zZXJ0TGF0ZW5jeUFsYXJtRGVmaW5pdGlvbnMgPSB7XG4gICAgICBbTGF0ZW5jeVR5cGUuUDUwXTogcHJvcHMuYWRkSW5zZXJ0TGF0ZW5jeVA1MEFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA3MF06IHByb3BzLmFkZEluc2VydExhdGVuY3lQNzBBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTBdOiBwcm9wcy5hZGRJbnNlcnRMYXRlbmN5UDkwQWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDk1XTogcHJvcHMuYWRkSW5zZXJ0TGF0ZW5jeVA5NUFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA5OV06IHByb3BzLmFkZEluc2VydExhdGVuY3lQOTlBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTk5XTogcHJvcHMuYWRkSW5zZXJ0TGF0ZW5jeVA5OTlBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTk5OV06IHByb3BzLmFkZEluc2VydExhdGVuY3lQOTk5OUFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlAxMDBdOiBwcm9wcy5hZGRJbnNlcnRMYXRlbmN5UDEwMEFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLkFWRVJBR0VdOiBwcm9wcy5hZGRJbnNlcnRMYXRlbmN5QXZlcmFnZUFsYXJtLFxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVMYXRlbmN5QWxhcm1EZWZpbml0aW9ucyA9IHtcbiAgICAgIFtMYXRlbmN5VHlwZS5QNTBdOiBwcm9wcy5hZGRVcGRhdGVMYXRlbmN5UDUwQWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDcwXTogcHJvcHMuYWRkVXBkYXRlTGF0ZW5jeVA3MEFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA5MF06IHByb3BzLmFkZFVwZGF0ZUxhdGVuY3lQOTBBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTVdOiBwcm9wcy5hZGRVcGRhdGVMYXRlbmN5UDk1QWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDk5XTogcHJvcHMuYWRkVXBkYXRlTGF0ZW5jeVA5OUFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA5OTldOiBwcm9wcy5hZGRVcGRhdGVMYXRlbmN5UDk5OUFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA5OTk5XTogcHJvcHMuYWRkVXBkYXRlTGF0ZW5jeVA5OTk5QWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDEwMF06IHByb3BzLmFkZFVwZGF0ZUxhdGVuY3lQMTAwQWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuQVZFUkFHRV06IHByb3BzLmFkZFVwZGF0ZUxhdGVuY3lBdmVyYWdlQWxhcm0sXG4gICAgfTtcblxuICAgIGNvbnN0IGRlbGV0ZUxhdGVuY3lBbGFybURlZmluaXRpb25zID0ge1xuICAgICAgW0xhdGVuY3lUeXBlLlA1MF06IHByb3BzLmFkZERlbGV0ZUxhdGVuY3lQNTBBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QNzBdOiBwcm9wcy5hZGREZWxldGVMYXRlbmN5UDcwQWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDkwXTogcHJvcHMuYWRkRGVsZXRlTGF0ZW5jeVA5MEFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA5NV06IHByb3BzLmFkZERlbGV0ZUxhdGVuY3lQOTVBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTldOiBwcm9wcy5hZGREZWxldGVMYXRlbmN5UDk5QWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDk5OV06IHByb3BzLmFkZERlbGV0ZUxhdGVuY3lQOTk5QWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDk5OTldOiBwcm9wcy5hZGREZWxldGVMYXRlbmN5UDk5OTlBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QMTAwXTogcHJvcHMuYWRkRGVsZXRlTGF0ZW5jeVAxMDBBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5BVkVSQUdFXTogcHJvcHMuYWRkRGVsZXRlTGF0ZW5jeUF2ZXJhZ2VBbGFybSxcbiAgICB9O1xuXG4gICAgY29uc3QgY29tbWl0TGF0ZW5jeUFsYXJtRGVmaW5pdGlvbnMgPSB7XG4gICAgICBbTGF0ZW5jeVR5cGUuUDUwXTogcHJvcHMuYWRkQ29tbWl0TGF0ZW5jeVA1MEFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA3MF06IHByb3BzLmFkZENvbW1pdExhdGVuY3lQNzBBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTBdOiBwcm9wcy5hZGRDb21taXRMYXRlbmN5UDkwQWxhcm0sXG4gICAgICBbTGF0ZW5jeVR5cGUuUDk1XTogcHJvcHMuYWRkQ29tbWl0TGF0ZW5jeVA5NUFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlA5OV06IHByb3BzLmFkZENvbW1pdExhdGVuY3lQOTlBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTk5XTogcHJvcHMuYWRkQ29tbWl0TGF0ZW5jeVA5OTlBbGFybSxcbiAgICAgIFtMYXRlbmN5VHlwZS5QOTk5OV06IHByb3BzLmFkZENvbW1pdExhdGVuY3lQOTk5OUFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLlAxMDBdOiBwcm9wcy5hZGRDb21taXRMYXRlbmN5UDEwMEFsYXJtLFxuICAgICAgW0xhdGVuY3lUeXBlLkFWRVJBR0VdOiBwcm9wcy5hZGRDb21taXRMYXRlbmN5QXZlcmFnZUFsYXJtLFxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IFtsYXRlbmN5VHlwZSwgYWxhcm1EZWZpbml0aW9uXSBvZiBPYmplY3QuZW50cmllcyhcbiAgICAgIHNlbGVjdExhdGVuY3lBbGFybURlZmluaXRpb25zLFxuICAgICkpIHtcbiAgICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBhbGFybURlZmluaXRpb24pIHtcbiAgICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IGFsYXJtRGVmaW5pdGlvbltkaXNhbWJpZ3VhdG9yXTtcbiAgICAgICAgY29uc3QgbGF0ZW5jeVR5cGVFbnVtID0gbGF0ZW5jeVR5cGUgYXMgTGF0ZW5jeVR5cGU7XG4gICAgICAgIGNvbnN0IG1ldHJpYyA9IHRoaXMuc2VsZWN0TGF0ZW5jeU1ldHJpY3NbbGF0ZW5jeVR5cGVFbnVtXTtcbiAgICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy5sYXRlbmN5QWxhcm1GYWN0b3J5LmFkZExhdGVuY3lBbGFybShcbiAgICAgICAgICBtZXRyaWMsXG4gICAgICAgICAgbGF0ZW5jeVR5cGVFbnVtLFxuICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgICBcIlNlbGVjdFwiLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnJlYWRMYXRlbmN5QW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICAgIHRoaXMubGF0ZW5jeVR5cGVzVG9SZW5kZXIucHVzaChsYXRlbmN5VHlwZUVudW0pO1xuICAgICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBbbGF0ZW5jeVR5cGUsIGFsYXJtRGVmaW5pdGlvbl0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICBpbnNlcnRMYXRlbmN5QWxhcm1EZWZpbml0aW9ucyxcbiAgICApKSB7XG4gICAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gYWxhcm1EZWZpbml0aW9uKSB7XG4gICAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBhbGFybURlZmluaXRpb25bZGlzYW1iaWd1YXRvcl07XG4gICAgICAgIGNvbnN0IGxhdGVuY3lUeXBlRW51bSA9IGxhdGVuY3lUeXBlIGFzIExhdGVuY3lUeXBlO1xuICAgICAgICBjb25zdCBtZXRyaWMgPSB0aGlzLmluc2VydExhdGVuY3lNZXRyaWNzW2xhdGVuY3lUeXBlRW51bV07XG4gICAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9IHRoaXMubGF0ZW5jeUFsYXJtRmFjdG9yeS5hZGRMYXRlbmN5QWxhcm0oXG4gICAgICAgICAgbWV0cmljLFxuICAgICAgICAgIGxhdGVuY3lUeXBlRW51bSxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICAgXCJJbnNlcnRcIixcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy53cml0ZUxhdGVuY3lBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgICAgdGhpcy5sYXRlbmN5VHlwZXNUb1JlbmRlci5wdXNoKGxhdGVuY3lUeXBlRW51bSk7XG4gICAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtsYXRlbmN5VHlwZSwgYWxhcm1EZWZpbml0aW9uXSBvZiBPYmplY3QuZW50cmllcyhcbiAgICAgIHVwZGF0ZUxhdGVuY3lBbGFybURlZmluaXRpb25zLFxuICAgICkpIHtcbiAgICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBhbGFybURlZmluaXRpb24pIHtcbiAgICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IGFsYXJtRGVmaW5pdGlvbltkaXNhbWJpZ3VhdG9yXTtcbiAgICAgICAgY29uc3QgbGF0ZW5jeVR5cGVFbnVtID0gbGF0ZW5jeVR5cGUgYXMgTGF0ZW5jeVR5cGU7XG4gICAgICAgIGNvbnN0IG1ldHJpYyA9IHRoaXMudXBkYXRlTGF0ZW5jeU1ldHJpY3NbbGF0ZW5jeVR5cGVFbnVtXTtcbiAgICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy5sYXRlbmN5QWxhcm1GYWN0b3J5LmFkZExhdGVuY3lBbGFybShcbiAgICAgICAgICBtZXRyaWMsXG4gICAgICAgICAgbGF0ZW5jeVR5cGVFbnVtLFxuICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgICBcIlVwZGF0ZVwiLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLndyaXRlTGF0ZW5jeUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgICB0aGlzLmxhdGVuY3lUeXBlc1RvUmVuZGVyLnB1c2gobGF0ZW5jeVR5cGVFbnVtKTtcbiAgICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgW2xhdGVuY3lUeXBlLCBhbGFybURlZmluaXRpb25dIG9mIE9iamVjdC5lbnRyaWVzKFxuICAgICAgZGVsZXRlTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbnMsXG4gICAgKSkge1xuICAgICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIGFsYXJtRGVmaW5pdGlvbikge1xuICAgICAgICBjb25zdCBhbGFybVByb3BzID0gYWxhcm1EZWZpbml0aW9uW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgICBjb25zdCBsYXRlbmN5VHlwZUVudW0gPSBsYXRlbmN5VHlwZSBhcyBMYXRlbmN5VHlwZTtcbiAgICAgICAgY29uc3QgbWV0cmljID0gdGhpcy5kZWxldGVMYXRlbmN5TWV0cmljc1tsYXRlbmN5VHlwZUVudW1dO1xuICAgICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLmxhdGVuY3lBbGFybUZhY3RvcnkuYWRkTGF0ZW5jeUFsYXJtKFxuICAgICAgICAgIG1ldHJpYyxcbiAgICAgICAgICBsYXRlbmN5VHlwZUVudW0sXG4gICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICAgIFwiRGVsZXRlXCIsXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMud3JpdGVMYXRlbmN5QW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICAgIHRoaXMubGF0ZW5jeVR5cGVzVG9SZW5kZXIucHVzaChsYXRlbmN5VHlwZUVudW0pO1xuICAgICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBbbGF0ZW5jeVR5cGUsIGFsYXJtRGVmaW5pdGlvbl0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICBjb21taXRMYXRlbmN5QWxhcm1EZWZpbml0aW9ucyxcbiAgICApKSB7XG4gICAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gYWxhcm1EZWZpbml0aW9uKSB7XG4gICAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBhbGFybURlZmluaXRpb25bZGlzYW1iaWd1YXRvcl07XG4gICAgICAgIGNvbnN0IGxhdGVuY3lUeXBlRW51bSA9IGxhdGVuY3lUeXBlIGFzIExhdGVuY3lUeXBlO1xuICAgICAgICBjb25zdCBtZXRyaWMgPSB0aGlzLmNvbW1pdExhdGVuY3lNZXRyaWNzW2xhdGVuY3lUeXBlRW51bV07XG4gICAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9IHRoaXMubGF0ZW5jeUFsYXJtRmFjdG9yeS5hZGRMYXRlbmN5QWxhcm0oXG4gICAgICAgICAgbWV0cmljLFxuICAgICAgICAgIGxhdGVuY3lUeXBlRW51bSxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICAgXCJDb21taXRcIixcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy53cml0ZUxhdGVuY3lBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgICAgdGhpcy5sYXRlbmN5VHlwZXNUb1JlbmRlci5wdXNoKGxhdGVuY3lUeXBlRW51bSk7XG4gICAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkUmVhZElPUFNBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZFJlYWRJT1BTQWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnVzYWdlQWxhcm1GYWN0b3J5LmFkZE1heFJlYWRJT1BTQWxhcm0oXG4gICAgICAgIHRoaXMucmVhZElvcHNNZXRyaWMsXG4gICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICApO1xuICAgICAgdGhpcy51c2FnZUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRXcml0ZUlPUFNBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZFdyaXRlSU9QU0FsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy51c2FnZUFsYXJtRmFjdG9yeS5hZGRNYXhXcml0ZUlPUFNBbGFybShcbiAgICAgICAgdGhpcy53cml0ZUlvcHNNZXRyaWMsXG4gICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICApO1xuICAgICAgdGhpcy51c2FnZUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cblxuICAgIHByb3BzLnVzZUNyZWF0ZWRBbGFybXM/LmNvbnN1bWUodGhpcy5jcmVhdGVkQWxhcm1zKCkpO1xuICB9XG5cbiAgc3VtbWFyeVdpZGdldHMoKTogSVdpZGdldFtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgdGhpcy5jcmVhdGVUaXRsZVdpZGdldCgpLFxuICAgICAgdGhpcy5jcmVhdGVDcHVBbmREaXNrVXNhZ2VXaWRnZXQoXG4gICAgICAgIFF1YXJ0ZXJXaWR0aCxcbiAgICAgICAgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQsXG4gICAgICApLFxuICAgICAgdGhpcy5jcmVhdGVDb25uZWN0aW9uc1dpZGdldChRdWFydGVyV2lkdGgsIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0KSxcbiAgICAgIHRoaXMuY3JlYXRlTGF0ZW5jeVdpZGdldChRdWFydGVyV2lkdGgsIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0KSxcbiAgICAgIHRoaXMuY3JlYXRlSU9QU1dpZGdldChRdWFydGVyV2lkdGgsIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0KSxcbiAgICBdO1xuICB9XG5cbiAgd2lkZ2V0cygpOiBJV2lkZ2V0W10ge1xuICAgIHJldHVybiBbXG4gICAgICB0aGlzLmNyZWF0ZVRpdGxlV2lkZ2V0KCksXG4gICAgICB0aGlzLmNyZWF0ZUNwdUFuZERpc2tVc2FnZVdpZGdldChRdWFydGVyV2lkdGgsIERlZmF1bHRHcmFwaFdpZGdldEhlaWdodCksXG4gICAgICB0aGlzLmNyZWF0ZUNvbm5lY3Rpb25zV2lkZ2V0KFF1YXJ0ZXJXaWR0aCwgRGVmYXVsdEdyYXBoV2lkZ2V0SGVpZ2h0KSxcbiAgICAgIHRoaXMuY3JlYXRlTGF0ZW5jeVdpZGdldChRdWFydGVyV2lkdGgsIERlZmF1bHRHcmFwaFdpZGdldEhlaWdodCksXG4gICAgICB0aGlzLmNyZWF0ZUlPUFNXaWRnZXQoUXVhcnRlcldpZHRoLCBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQpLFxuICAgIF07XG4gIH1cblxuICBjcmVhdGVUaXRsZVdpZGdldCgpIHtcbiAgICByZXR1cm4gbmV3IE1vbml0b3JpbmdIZWFkZXJXaWRnZXQoe1xuICAgICAgZmFtaWx5OiBcIlJEUyBDbHVzdGVyXCIsXG4gICAgICB0aXRsZTogdGhpcy50aXRsZSxcbiAgICAgIGdvVG9MaW5rVXJsOiB0aGlzLnVybCxcbiAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZUNwdUFuZERpc2tVc2FnZVdpZGdldCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikge1xuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogXCJDUFUvRGlzayBVc2FnZVwiLFxuICAgICAgbGVmdDogW3RoaXMuY3B1VXNhZ2VNZXRyaWMsIHRoaXMuZGlza1NwYWNlVXNhZ2VNZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLnVzYWdlQW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVDb25uZWN0aW9uc1dpZGdldCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikge1xuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogXCJDb25uZWN0aW9uc1wiLFxuICAgICAgbGVmdDogW3RoaXMuY29ubmVjdGlvbnNNZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBDb3VudEF4aXNGcm9tWmVybyxcbiAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5jb25uZWN0aW9uQW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVMYXRlbmN5V2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgY29uc3QgbGVmdCA9IEFycmF5LmZyb20obmV3IFNldCh0aGlzLmxhdGVuY3lUeXBlc1RvUmVuZGVyKSlcbiAgICAgIC5zb3J0KClcbiAgICAgIC5yZWR1Y2UoKG1ldHJpY3MsIHR5cGUpID0+IHtcbiAgICAgICAgbWV0cmljcy5wdXNoKFxuICAgICAgICAgIHRoaXMuc2VsZWN0TGF0ZW5jeU1ldHJpY3NbdHlwZV0sXG4gICAgICAgICAgdGhpcy5pbnNlcnRMYXRlbmN5TWV0cmljc1t0eXBlXSxcbiAgICAgICAgICB0aGlzLnVwZGF0ZUxhdGVuY3lNZXRyaWNzW3R5cGVdLFxuICAgICAgICAgIHRoaXMuZGVsZXRlTGF0ZW5jeU1ldHJpY3NbdHlwZV0sXG4gICAgICAgICAgdGhpcy5jb21taXRMYXRlbmN5TWV0cmljc1t0eXBlXSxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG1ldHJpY3M7XG4gICAgICB9LCBbXSBhcyBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0W10pO1xuXG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIlF1ZXJ5IER1cmF0aW9uXCIsXG4gICAgICBsZWZ0LFxuICAgICAgbGVmdFlBeGlzOiBUaW1lQXhpc01pbGxpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiBbXG4gICAgICAgIC4uLnRoaXMucmVhZExhdGVuY3lBbm5vdGF0aW9ucyxcbiAgICAgICAgLi4udGhpcy53cml0ZUxhdGVuY3lBbm5vdGF0aW9ucyxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVJT1BTV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIklPUFNcIixcbiAgICAgIGxlZnQ6IFt0aGlzLnJlYWRJb3BzTWV0cmljLCB0aGlzLndyaXRlSW9wc01ldHJpY10sXG4gICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLmlvcHNBbm5vdGF0aW9ucyxcbiAgICB9KTtcbiAgfVxufVxuIl19