@renovosolutions/cdk-library-cloudwatch-alarms
Version:
AWS CDK Construct Library to automatically create CloudWatch Alarms for resources in a CDK app based on resource type.
384 lines • 69.9 kB
JavaScript
"use strict";
var _a, _b, _c, _d, _e, _f, _g;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationLoadBalancerRecommendedAlarmsAspect = exports.ApplicationLoadBalancer = exports.ApplicationLoadBalancerRecommendedAlarms = exports.ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm = exports.ApplicationLoadBalancerHttpCode5xxCountAlarm = exports.ApplicationLoadBalancerHttpCode4xxCountAlarm = exports.ApplicationLoadBalancerRejectedConnectionCountAlarm = exports.ApplicationLoadBalancerRecommendedAlarmsMetrics = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs_1 = require("constructs");
const common_1 = require("./common");
/**
* The recommended metrics for ApplicationLoadBalancer alarms.
*/
var ApplicationLoadBalancerRecommendedAlarmsMetrics;
(function (ApplicationLoadBalancerRecommendedAlarmsMetrics) {
/**
* The number of connection requests that were rejected because the load balancer had reached its maximum connections.
*/
ApplicationLoadBalancerRecommendedAlarmsMetrics["REJECTED_CONNECTION_COUNT"] = "RejectedConnectionCount";
/**
* The number of HTTP 4XX client error codes generated by the load balancer.
*/
ApplicationLoadBalancerRecommendedAlarmsMetrics["HTTP_CODE_ELB_4XX_COUNT"] = "HTTPCode_ELB_4XX_Count";
/**
* The number of HTTP 5XX server error codes generated by the load balancer.
*/
ApplicationLoadBalancerRecommendedAlarmsMetrics["HTTP_CODE_ELB_5XX_COUNT"] = "HTTPCode_ELB_5XX_Count";
/**
* The number of HTTP 5XX server error codes generated by the targets.
*/
ApplicationLoadBalancerRecommendedAlarmsMetrics["HTTP_CODE_TARGET_5XX_COUNT"] = "HTTPCode_Target_5XX_Count";
})(ApplicationLoadBalancerRecommendedAlarmsMetrics || (exports.ApplicationLoadBalancerRecommendedAlarmsMetrics = ApplicationLoadBalancerRecommendedAlarmsMetrics = {}));
/**
* This alarm is used to detect when the load balancer is rejecting connections.
*
* Rejected connections can indicate that the load balancer has reached its maximum connection limit.
*
* The alarm is triggered when the number of rejected connections is greater than threshold.
*/
class ApplicationLoadBalancerRejectedConnectionCountAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm {
constructor(scope, id, props) {
const alarmName = props.alarmName ?? `${props.loadBalancer.loadBalancerName} - ${ApplicationLoadBalancerRecommendedAlarmsMetrics.REJECTED_CONNECTION_COUNT}`;
const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1);
const evaluationPeriods = props.evaluationPeriods ?? 3;
const datapointsToAlarm = props.datapointsToAlarm ?? 3;
const threshold = props.threshold ?? 0;
const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING;
const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect when the load balancer is rejecting connections.'
+ ' Rejected connections can indicate that the load balancer has reached its maximum connection limit.';
(0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName);
super(scope, id, {
alarmName,
metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({
namespace: 'AWS/ApplicationELB',
metricName: ApplicationLoadBalancerRecommendedAlarmsMetrics.REJECTED_CONNECTION_COUNT,
dimensionsMap: {
LoadBalancer: props.loadBalancer.loadBalancerFullName,
},
statistic: 'Sum',
period,
}),
threshold,
evaluationPeriods,
datapointsToAlarm,
treatMissingData,
comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
alarmDescription,
});
if (props.alarmAction)
this.addAlarmAction(props.alarmAction);
if (props.okAction)
this.addOkAction(props.okAction);
if (props.insufficientDataAction)
this.addInsufficientDataAction(props.insufficientDataAction);
}
}
exports.ApplicationLoadBalancerRejectedConnectionCountAlarm = ApplicationLoadBalancerRejectedConnectionCountAlarm;
_a = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancerRejectedConnectionCountAlarm[_a] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.ApplicationLoadBalancerRejectedConnectionCountAlarm", version: "0.0.17" };
/**
* This anomaly detection alarm is used to detect when the load balancer is generating
* unusually many 4XX errors.
*
* A high number of 4XX errors can indicate client-side issues or misconfigured requests.
*
* The alarm is triggered when the number of 4XX errors is outside the upper threshold
* of the anomaly detection band.
*/
class ApplicationLoadBalancerHttpCode4xxCountAlarm extends aws_cdk_lib_1.aws_cloudwatch.AnomalyDetectionAlarm {
constructor(scope, id, props) {
const alarmName = props.alarmName ?? `${props.loadBalancer.loadBalancerName} - ${ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_ELB_4XX_COUNT}`;
const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1);
const evaluationPeriods = props.evaluationPeriods ?? 3;
const datapointsToAlarm = props.datapointsToAlarm ?? 3;
const stdDevs = props.stdDevs ?? 8;
const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING;
const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect when the load balancer is generating 4XX errors.'
+ ' A high number of 4XX errors can indicate client-side issues or misconfigured requests.';
(0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName);
super(scope, id, {
alarmName,
metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({
namespace: 'AWS/ApplicationELB',
metricName: ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_ELB_4XX_COUNT,
dimensionsMap: {
LoadBalancer: props.loadBalancer.loadBalancerFullName,
},
statistic: 'Average',
}),
stdDevs,
evaluationPeriods,
datapointsToAlarm,
treatMissingData,
comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_UPPER_THRESHOLD,
alarmDescription,
});
if (props.alarmAction)
this.addAlarmAction(props.alarmAction);
if (props.okAction)
this.addOkAction(props.okAction);
if (props.insufficientDataAction)
this.addInsufficientDataAction(props.insufficientDataAction);
}
}
exports.ApplicationLoadBalancerHttpCode4xxCountAlarm = ApplicationLoadBalancerHttpCode4xxCountAlarm;
_b = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancerHttpCode4xxCountAlarm[_b] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.ApplicationLoadBalancerHttpCode4xxCountAlarm", version: "0.0.17" };
/**
* This anomaly detection alarm is used to detect when the load balancer is generating
* unusually many 5XX errors.
*
* A high number of 5XX errors can indicate issues with the load balancer itself.
*
* The alarm is triggered when the number of 5XX errors is outside the upper threshold
* of the anomaly detection band.
*/
class ApplicationLoadBalancerHttpCode5xxCountAlarm extends aws_cdk_lib_1.aws_cloudwatch.AnomalyDetectionAlarm {
constructor(scope, id, props) {
const alarmName = props.alarmName ?? `${props.loadBalancer.loadBalancerName} - ${ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_ELB_5XX_COUNT}`;
const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1);
const evaluationPeriods = props.evaluationPeriods ?? 3;
const datapointsToAlarm = props.datapointsToAlarm ?? 3;
const stdDevs = props.stdDevs ?? 8;
const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING;
const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect when the load balancer is generating 5XX errors.'
+ ' A high number of 5XX errors can indicate issues with the load balancer itself.';
(0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName);
super(scope, id, {
alarmName,
metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({
namespace: 'AWS/ApplicationELB',
metricName: ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_ELB_5XX_COUNT,
dimensionsMap: {
LoadBalancer: props.loadBalancer.loadBalancerFullName,
},
statistic: 'Average',
}),
stdDevs,
evaluationPeriods,
datapointsToAlarm,
treatMissingData,
comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_UPPER_THRESHOLD,
alarmDescription,
});
if (props.alarmAction)
this.addAlarmAction(props.alarmAction);
if (props.okAction)
this.addOkAction(props.okAction);
if (props.insufficientDataAction)
this.addInsufficientDataAction(props.insufficientDataAction);
}
}
exports.ApplicationLoadBalancerHttpCode5xxCountAlarm = ApplicationLoadBalancerHttpCode5xxCountAlarm;
_c = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancerHttpCode5xxCountAlarm[_c] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.ApplicationLoadBalancerHttpCode5xxCountAlarm", version: "0.0.17" };
/**
* This alarm is used to detect when the targets are generating 5XX errors.
*
* A high number of 5XX errors can indicate issues with the application or backend services.
*
* The alarm is triggered when the number of 5XX errors from targets is greater than threshold.
*/
class ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm {
constructor(scope, id, props) {
const alarmName = props.alarmName ?? `${props.loadBalancer.loadBalancerName} - ${ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_TARGET_5XX_COUNT}`;
const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1);
const evaluationPeriods = props.evaluationPeriods ?? 3;
const datapointsToAlarm = props.datapointsToAlarm ?? 3;
const threshold = props.threshold ?? 0;
const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING;
const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect when the targets are generating 5XX errors.'
+ ' A high number of 5XX errors can indicate issues with the application or backend services.';
(0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName);
super(scope, id, {
alarmName,
metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({
namespace: 'AWS/ApplicationELB',
metricName: ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_TARGET_5XX_COUNT,
dimensionsMap: {
LoadBalancer: props.loadBalancer.loadBalancerFullName,
},
statistic: 'Sum',
period,
}),
threshold,
evaluationPeriods,
datapointsToAlarm,
treatMissingData,
comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
alarmDescription,
});
if (props.alarmAction)
this.addAlarmAction(props.alarmAction);
if (props.okAction)
this.addOkAction(props.okAction);
if (props.insufficientDataAction)
this.addInsufficientDataAction(props.insufficientDataAction);
}
}
exports.ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm = ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm;
_d = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm[_d] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm", version: "0.0.17" };
/**
* A construct that creates the recommended alarms for an ApplicationLoadBalancer.
*
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elb-metricscollected.html
*/
class ApplicationLoadBalancerRecommendedAlarms extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
if (!props.excludeAlarms?.includes(ApplicationLoadBalancerRecommendedAlarmsMetrics.REJECTED_CONNECTION_COUNT)) {
this.alarmRejectedConnectionCount = new ApplicationLoadBalancerRejectedConnectionCountAlarm(this, `${props.loadBalancer.node.id}_RejectedConnectionCount`, {
loadBalancer: props.loadBalancer,
treatMissingData: props.treatMissingData,
...props.configRejectedConnectionCountAlarm,
});
if (props.defaultAlarmAction && !props.configRejectedConnectionCountAlarm?.alarmAction) {
this.alarmRejectedConnectionCount.addAlarmAction(props.defaultAlarmAction);
}
if (props.defaultOkAction && !props.configRejectedConnectionCountAlarm?.okAction) {
this.alarmRejectedConnectionCount.addOkAction(props.defaultOkAction);
}
if (props.defaultInsufficientDataAction && !props.configRejectedConnectionCountAlarm?.insufficientDataAction) {
this.alarmRejectedConnectionCount.addInsufficientDataAction(props.defaultInsufficientDataAction);
}
}
if (!props.excludeAlarms?.includes(ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_ELB_4XX_COUNT)) {
this.alarmHttpCode4xxCount = new ApplicationLoadBalancerHttpCode4xxCountAlarm(this, `${props.loadBalancer.node.id}_HttpCode4xxCount`, {
loadBalancer: props.loadBalancer,
treatMissingData: props.treatMissingData,
...props.configHttpCode4xxCountAlarm,
});
if (props.defaultAlarmAction && !props.configHttpCode4xxCountAlarm?.alarmAction) {
this.alarmHttpCode4xxCount.addAlarmAction(props.defaultAlarmAction);
}
if (props.defaultOkAction && !props.configHttpCode4xxCountAlarm?.okAction) {
this.alarmHttpCode4xxCount.addOkAction(props.defaultOkAction);
}
if (props.defaultInsufficientDataAction && !props.configHttpCode4xxCountAlarm?.insufficientDataAction) {
this.alarmHttpCode4xxCount.addInsufficientDataAction(props.defaultInsufficientDataAction);
}
}
if (!props.excludeAlarms?.includes(ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_ELB_5XX_COUNT)) {
this.alarmHttpCode5xxCount = new ApplicationLoadBalancerHttpCode5xxCountAlarm(this, `${props.loadBalancer.node.id}_HttpCode5xxCount`, {
loadBalancer: props.loadBalancer,
treatMissingData: props.treatMissingData,
...props.configHttpCode5xxCountAlarm,
});
if (props.defaultAlarmAction && !props.configHttpCode5xxCountAlarm?.alarmAction) {
this.alarmHttpCode5xxCount.addAlarmAction(props.defaultAlarmAction);
}
if (props.defaultOkAction && !props.configHttpCode5xxCountAlarm?.okAction) {
this.alarmHttpCode5xxCount.addOkAction(props.defaultOkAction);
}
if (props.defaultInsufficientDataAction && !props.configHttpCode5xxCountAlarm?.insufficientDataAction) {
this.alarmHttpCode5xxCount.addInsufficientDataAction(props.defaultInsufficientDataAction);
}
}
if (!props.excludeAlarms?.includes(ApplicationLoadBalancerRecommendedAlarmsMetrics.HTTP_CODE_TARGET_5XX_COUNT)) {
this.alarmHttpCodeTarget5xxCount = new ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm(this, `${props.loadBalancer.node.id}_HttpCodeTarget5xxCount`, {
loadBalancer: props.loadBalancer,
treatMissingData: props.treatMissingData,
...props.configHttpCodeTarget5xxCountAlarm,
});
if (props.defaultAlarmAction && !props.configHttpCodeTarget5xxCountAlarm?.alarmAction) {
this.alarmHttpCodeTarget5xxCount.addAlarmAction(props.defaultAlarmAction);
}
if (props.defaultOkAction && !props.configHttpCodeTarget5xxCountAlarm?.okAction) {
this.alarmHttpCodeTarget5xxCount.addOkAction(props.defaultOkAction);
}
if (props.defaultInsufficientDataAction && !props.configHttpCodeTarget5xxCountAlarm?.insufficientDataAction) {
this.alarmHttpCodeTarget5xxCount.addInsufficientDataAction(props.defaultInsufficientDataAction);
}
}
}
}
exports.ApplicationLoadBalancerRecommendedAlarms = ApplicationLoadBalancerRecommendedAlarms;
_e = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancerRecommendedAlarms[_e] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.ApplicationLoadBalancerRecommendedAlarms", version: "0.0.17" };
/**
* An extension for the ApplicationLoadBalancer construct that provides methods
* to create recommended alarms.
*/
class ApplicationLoadBalancer extends aws_cdk_lib_1.aws_elasticloadbalancingv2.ApplicationLoadBalancer {
constructor(scope, id, props) {
super(scope, id, props);
}
/**
* Creates an alarm that monitors the rejected connection count for the ApplicationLoadBalancer.
*/
alarmRejectedConnectionCount(props) {
return new ApplicationLoadBalancerRejectedConnectionCountAlarm(this, 'RejectedConnectionCountAlarm', {
loadBalancer: this,
...props,
});
}
/**
* Creates an alarm that monitors the HTTP 4XX error count for the ApplicationLoadBalancer.
*/
alarmHttpCode4xxCount(props) {
return new ApplicationLoadBalancerHttpCode4xxCountAlarm(this, 'HttpCode4xxCountAlarm', {
loadBalancer: this,
...props,
});
}
/**
* Creates an alarm that monitors the HTTP 5XX error count for the ApplicationLoadBalancer.
*/
alarmHttpCode5xxCount(props) {
return new ApplicationLoadBalancerHttpCode5xxCountAlarm(this, 'HttpCode5xxCountAlarm', {
loadBalancer: this,
...props,
});
}
/**
* Creates an alarm that monitors the HTTP 5XX error count from targets for the ApplicationLoadBalancer.
*/
alarmHttpCodeTarget5xxCount(props) {
return new ApplicationLoadBalancerHttpCodeTarget5xxCountAlarm(this, 'HttpCodeTarget5xxCountAlarm', {
loadBalancer: this,
...props,
});
}
/**
* Creates the recommended alarms for the ApplicationLoadBalancer.
*
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elb-metricscollected.html
*/
applyRecommendedAlarms(props) {
return new ApplicationLoadBalancerRecommendedAlarms(this, 'ApplicationLoadBalancerRecommendedAlarms', {
loadBalancer: this,
...props,
});
}
}
exports.ApplicationLoadBalancer = ApplicationLoadBalancer;
_f = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancer[_f] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.ApplicationLoadBalancer", version: "0.0.17" };
/**
* Configures the recommended alarms for an ApplicationLoadBalancer.
*
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elb-metricscollected.html
*/
class ApplicationLoadBalancerRecommendedAlarmsAspect {
constructor(props) {
this.props = props;
}
visit(node) {
if (node instanceof aws_cdk_lib_1.aws_elasticloadbalancingv2.ApplicationLoadBalancer) {
if (this.props.excludeResources && this.props.excludeResources.includes(node.node.id)) {
return;
}
else {
const loadBalancer = node;
new ApplicationLoadBalancerRecommendedAlarms(loadBalancer, 'ApplicationLoadBalancerRecommendedAlarmsFromAspect', {
loadBalancer,
...this.props,
});
}
}
}
}
exports.ApplicationLoadBalancerRecommendedAlarmsAspect = ApplicationLoadBalancerRecommendedAlarmsAspect;
_g = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancerRecommendedAlarmsAspect[_g] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.ApplicationLoadBalancerRecommendedAlarmsAspect", version: "0.0.17" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb25sb2FkYmFsYW5jZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYXBwbGljYXRpb25sb2FkYmFsYW5jZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FLcUI7QUFDckIsMkNBQW1EO0FBQ25ELHFDQUFvRTtBQUVwRTs7R0FFRztBQUNILElBQVksK0NBaUJYO0FBakJELFdBQVksK0NBQStDO0lBQ3pEOztPQUVHO0lBQ0gsd0dBQXFELENBQUE7SUFDckQ7O09BRUc7SUFDSCxxR0FBa0QsQ0FBQTtJQUNsRDs7T0FFRztJQUNILHFHQUFrRCxDQUFBO0lBQ2xEOztPQUVHO0lBQ0gsMkdBQXdELENBQUE7QUFDMUQsQ0FBQyxFQWpCVywrQ0FBK0MsK0RBQS9DLCtDQUErQyxRQWlCMUQ7QUFvRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBYSxtREFBb0QsU0FBUSw0QkFBVSxDQUFDLEtBQUs7SUFDdkYsWUFBWSxLQUFpQixFQUFFLEVBQVUsRUFBRSxLQUErRDtRQUN4RyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxJQUFJLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsTUFBTSwrQ0FBK0MsQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1FBQzdKLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsaUJBQWlCLElBQUksQ0FBQyxDQUFDO1FBQ3ZELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxJQUFJLENBQUMsQ0FBQztRQUN2QyxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSw0QkFBVSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQztRQUN2RixNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSwrRUFBK0U7Y0FDOUgscUdBQXFHLENBQUM7UUFFMUcsSUFBQSxpQ0FBd0IsRUFBQyxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFFL0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixTQUFTO1lBQ1QsTUFBTSxFQUFFLElBQUksNEJBQVUsQ0FBQyxNQUFNLENBQUM7Z0JBQzVCLFNBQVMsRUFBRSxvQkFBb0I7Z0JBQy9CLFVBQVUsRUFBRSwrQ0FBK0MsQ0FBQyx5QkFBeUI7Z0JBQ3JGLGFBQWEsRUFBRTtvQkFDYixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxvQkFBb0I7aUJBQ3REO2dCQUNELFNBQVMsRUFBRSxLQUFLO2dCQUNoQixNQUFNO2FBQ1AsQ0FBQztZQUNGLFNBQVM7WUFDVCxpQkFBaUI7WUFDakIsaUJBQWlCO1lBQ2pCLGdCQUFnQjtZQUNoQixrQkFBa0IsRUFBRSw0QkFBVSxDQUFDLGtCQUFrQixDQUFDLHNCQUFzQjtZQUN4RSxnQkFBZ0I7U0FDakIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxLQUFLLENBQUMsV0FBVztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzlELElBQUksS0FBSyxDQUFDLFFBQVE7WUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyRCxJQUFJLEtBQUssQ0FBQyxzQkFBc0I7WUFBRSxJQUFJLENBQUMseUJBQXlCLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUM7SUFDakcsQ0FBQzs7QUFuQ0gsa0hBb0NDOzs7QUE4Q0Q7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFhLDRDQUE2QyxTQUFRLDRCQUFVLENBQUMscUJBQXFCO0lBQ2hHLFlBQVksS0FBaUIsRUFBRSxFQUFVLEVBQUUsS0FBd0Q7UUFDakcsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsSUFBSSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLE1BQU0sK0NBQStDLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUMzSixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLHNCQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLENBQUM7UUFDdkQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sSUFBSSxDQUFDLENBQUM7UUFDbkMsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLElBQUksNEJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFDdkYsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLElBQUksK0VBQStFO2NBQzlILHlGQUF5RixDQUFDO1FBRTlGLElBQUEsaUNBQXdCLEVBQUMsTUFBTSxFQUFFLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBRS9ELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ2YsU0FBUztZQUNULE1BQU0sRUFBRSxJQUFJLDRCQUFVLENBQUMsTUFBTSxDQUFDO2dCQUM1QixTQUFTLEVBQUUsb0JBQW9CO2dCQUMvQixVQUFVLEVBQUUsK0NBQStDLENBQUMsdUJBQXVCO2dCQUNuRixhQUFhLEVBQUU7b0JBQ2IsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLENBQUMsb0JBQW9CO2lCQUN0RDtnQkFDRCxTQUFTLEVBQUUsU0FBUzthQUNyQixDQUFDO1lBQ0YsT0FBTztZQUNQLGlCQUFpQjtZQUNqQixpQkFBaUI7WUFDakIsZ0JBQWdCO1lBQ2hCLGtCQUFrQixFQUFFLDRCQUFVLENBQUMsa0JBQWtCLENBQUMsNEJBQTRCO1lBQzlFLGdCQUFnQjtTQUNqQixDQUFDLENBQUM7UUFFSCxJQUFJLEtBQUssQ0FBQyxXQUFXO1lBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDOUQsSUFBSSxLQUFLLENBQUMsUUFBUTtZQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JELElBQUksS0FBSyxDQUFDLHNCQUFzQjtZQUFFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQztJQUNqRyxDQUFDOztBQWxDSCxvR0FtQ0M7OztBQTZDRDs7Ozs7Ozs7R0FRRztBQUNILE1BQWEsNENBQTZDLFNBQVEsNEJBQVUsQ0FBQyxxQkFBcUI7SUFDaEcsWUFBWSxLQUFpQixFQUFFLEVBQVUsRUFBRSxLQUF3RDtRQUNqRyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxJQUFJLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsTUFBTSwrQ0FBK0MsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQzNKLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsaUJBQWlCLElBQUksQ0FBQyxDQUFDO1FBQ3ZELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQztRQUNuQyxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSw0QkFBVSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQztRQUN2RixNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSwrRUFBK0U7Y0FDOUgsaUZBQWlGLENBQUM7UUFFdEYsSUFBQSxpQ0FBd0IsRUFBQyxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFFL0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixTQUFTO1lBQ1QsTUFBTSxFQUFFLElBQUksNEJBQVUsQ0FBQyxNQUFNLENBQUM7Z0JBQzVCLFNBQVMsRUFBRSxvQkFBb0I7Z0JBQy9CLFVBQVUsRUFBRSwrQ0FBK0MsQ0FBQyx1QkFBdUI7Z0JBQ25GLGFBQWEsRUFBRTtvQkFDYixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxvQkFBb0I7aUJBQ3REO2dCQUNELFNBQVMsRUFBRSxTQUFTO2FBQ3JCLENBQUM7WUFDRixPQUFPO1lBQ1AsaUJBQWlCO1lBQ2pCLGlCQUFpQjtZQUNqQixnQkFBZ0I7WUFDaEIsa0JBQWtCLEVBQUUsNEJBQVUsQ0FBQyxrQkFBa0IsQ0FBQyw0QkFBNEI7WUFDOUUsZ0JBQWdCO1NBQ2pCLENBQUMsQ0FBQztRQUVILElBQUksS0FBSyxDQUFDLFdBQVc7WUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5RCxJQUFJLEtBQUssQ0FBQyxRQUFRO1lBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDckQsSUFBSSxLQUFLLENBQUMsc0JBQXNCO1lBQUUsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7O0FBbENILG9HQW1DQzs7O0FBOENEOzs7Ozs7R0FNRztBQUNILE1BQWEsa0RBQW1ELFNBQVEsNEJBQVUsQ0FBQyxLQUFLO0lBQ3RGLFlBQVksS0FBaUIsRUFBRSxFQUFVLEVBQUUsS0FBOEQ7UUFDdkcsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsSUFBSSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLE1BQU0sK0NBQStDLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUM5SixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLHNCQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLENBQUM7UUFDdkQsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUM7UUFDdkMsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLElBQUksNEJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFDdkYsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLElBQUksMEVBQTBFO2NBQ3pILDRGQUE0RixDQUFDO1FBRWpHLElBQUEsaUNBQXdCLEVBQUMsTUFBTSxFQUFFLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBRS9ELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ2YsU0FBUztZQUNULE1BQU0sRUFBRSxJQUFJLDRCQUFVLENBQUMsTUFBTSxDQUFDO2dCQUM1QixTQUFTLEVBQUUsb0JBQW9CO2dCQUMvQixVQUFVLEVBQUUsK0NBQStDLENBQUMsMEJBQTBCO2dCQUN0RixhQUFhLEVBQUU7b0JBQ2IsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLENBQUMsb0JBQW9CO2lCQUN0RDtnQkFDRCxTQUFTLEVBQUUsS0FBSztnQkFDaEIsTUFBTTthQUNQLENBQUM7WUFDRixTQUFTO1lBQ1QsaUJBQWlCO1lBQ2pCLGlCQUFpQjtZQUNqQixnQkFBZ0I7WUFDaEIsa0JBQWtCLEVBQUUsNEJBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxzQkFBc0I7WUFDeEUsZ0JBQWdCO1NBQ2pCLENBQUMsQ0FBQztRQUVILElBQUksS0FBSyxDQUFDLFdBQVc7WUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5RCxJQUFJLEtBQUssQ0FBQyxRQUFRO1lBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDckQsSUFBSSxLQUFLLENBQUMsc0JBQXNCO1lBQUUsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7O0FBbkNILGdIQW9DQzs7O0FBeUVEOzs7O0dBSUc7QUFDSCxNQUFhLHdDQUF5QyxTQUFRLHNCQUFTO0lBcUJyRSxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQW9EO1FBQzVGLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLCtDQUErQyxDQUFDLHlCQUF5QixDQUFDLEVBQUUsQ0FBQztZQUM5RyxJQUFJLENBQUMsNEJBQTRCLEdBQUcsSUFBSSxtREFBbUQsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLDBCQUEwQixFQUFFO2dCQUN6SixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7Z0JBQ2hDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0I7Z0JBQ3hDLEdBQUcsS0FBSyxDQUFDLGtDQUFrQzthQUM1QyxDQUFDLENBQUM7WUFFSCxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQ0FBa0MsRUFBRSxXQUFXLEVBQUUsQ0FBQztnQkFDdkYsSUFBSSxDQUFDLDRCQUE0QixDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUM3RSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsZUFBZSxJQUFJLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxFQUFFLFFBQVEsRUFBRSxDQUFDO2dCQUNqRixJQUFJLENBQUMsNEJBQTRCLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUN2RSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsNkJBQTZCLElBQUksQ0FBQyxLQUFLLENBQUMsa0NBQWtDLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQztnQkFDN0csSUFBSSxDQUFDLDRCQUE0QixDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBQ25HLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLCtDQUErQyxDQUFDLHVCQUF1QixDQUFDLEVBQUUsQ0FBQztZQUM1RyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSw0Q0FBNEMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLG1CQUFtQixFQUFFO2dCQUNwSSxZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7Z0JBQ2hDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0I7Z0JBQ3hDLEdBQUcsS0FBSyxDQUFDLDJCQUEyQjthQUNyQyxDQUFDLENBQUM7WUFFSCxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLEtBQUssQ0FBQywyQkFBMkIsRUFBRSxXQUFXLEVBQUUsQ0FBQztnQkFDaEYsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUN0RSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsZUFBZSxJQUFJLENBQUMsS0FBSyxDQUFDLDJCQUEyQixFQUFFLFFBQVEsRUFBRSxDQUFDO2dCQUMxRSxJQUFJLENBQUMscUJBQXFCLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNoRSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsNkJBQTZCLElBQUksQ0FBQyxLQUFLLENBQUMsMkJBQTJCLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQztnQkFDdEcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBQzVGLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLCtDQUErQyxDQUFDLHVCQUF1QixDQUFDLEVBQUUsQ0FBQztZQUM1RyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSw0Q0FBNEMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLG1CQUFtQixFQUFFO2dCQUNwSSxZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7Z0JBQ2hDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0I7Z0JBQ3hDLEdBQUcsS0FBSyxDQUFDLDJCQUEyQjthQUNyQyxDQUFDLENBQUM7WUFFSCxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLEtBQUssQ0FBQywyQkFBMkIsRUFBRSxXQUFXLEVBQUUsQ0FBQztnQkFDaEYsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUN0RSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsZUFBZSxJQUFJLENBQUMsS0FBSyxDQUFDLDJCQUEyQixFQUFFLFFBQVEsRUFBRSxDQUFDO2dCQUMxRSxJQUFJLENBQUMscUJBQXFCLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNoRSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsNkJBQTZCLElBQUksQ0FBQyxLQUFLLENBQUMsMkJBQTJCLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQztnQkFDdEcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBQzVGLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLCtDQUErQyxDQUFDLDBCQUEwQixDQUFDLEVBQUUsQ0FBQztZQUMvRyxJQUFJLENBQUMsMkJBQTJCLEdBQUcsSUFBSSxrREFBa0QsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLHlCQUF5QixFQUFFO2dCQUN0SixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7Z0JBQ2hDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0I7Z0JBQ3hDLEdBQUcsS0FBSyxDQUFDLGlDQUFpQzthQUMzQyxDQUFDLENBQUM7WUFFSCxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsRUFBRSxXQUFXLEVBQUUsQ0FBQztnQkFDdEYsSUFBSSxDQUFDLDJCQUEyQixDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUM1RSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsZUFBZSxJQUFJLENBQUMsS0FBSyxDQUFDLGlDQUFpQyxFQUFFLFFBQVEsRUFBRSxDQUFDO2dCQUNoRixJQUFJLENBQUMsMkJBQTJCLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUN0RSxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsNkJBQTZCLElBQUksQ0FBQyxLQUFLLENBQUMsaUNBQWlDLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQztnQkFDNUcsSUFBSSxDQUFDLDJCQUEyQixDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBQ2xHLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQzs7QUF2R0gsNEZBd0dDOzs7QUFFRDs7O0dBR0c7QUFDSCxNQUFhLHVCQUF3QixTQUFRLHdDQUFLLENBQUMsdUJBQXVCO0lBQ3hFLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBeUM7UUFDakYsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksNEJBQTRCLENBQUMsS0FBaUU7UUFFbkcsT0FBTyxJQUFJLG1EQUFtRCxDQUFDLElBQUksRUFBRSw4QkFBOEIsRUFBRTtZQUNuRyxZQUFZLEVBQUUsSUFBSTtZQUNsQixHQUFHLEtBQUs7U0FDVCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxxQkFBcUIsQ0FBQyxLQUEwRDtRQUNyRixPQUFPLElBQUksNENBQTRDLENBQUMsSUFBSSxFQUFFLHVCQUF1QixFQUFFO1lBQ3JGLFlBQVksRUFBRSxJQUFJO1lBQ2xCLEdBQUcsS0FBSztTQUNULENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLHFCQUFxQixDQUFDLEtBQTBEO1FBQ3JGLE9BQU8sSUFBSSw0Q0FBNEMsQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLEVBQUU7WUFDckYsWUFBWSxFQUFFLElBQUk7WUFDbEIsR0FBRyxLQUFLO1NBQ1QsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ksMkJBQTJCLENBQUMsS0FBZ0U7UUFFakcsT0FBTyxJQUFJLGtEQUFrRCxDQUFDLElBQUksRUFBRSw2QkFBNkIsRUFBRTtZQUNqRyxZQUFZLEVBQUUsSUFBSTtZQUNsQixHQUFHLEtBQUs7U0FDVCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLHNCQUFzQixDQUFDLEtBQXFEO1FBQ2pGLE9BQU8sSUFBSSx3Q0FBd0MsQ0FBQyxJQUFJLEVBQUUsMENBQTBDLEVBQUU7WUFDcEcsWUFBWSxFQUFFLElBQUk7WUFDbEIsR0FBRyxLQUFLO1NBQ1QsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUF6REgsMERBMERDOzs7QUFFRDs7OztHQUlHO0FBQ0gsTUFBYSw4Q0FBOEM7SUFDekQsWUFBNkIsS0FBcUQ7UUFBckQsVUFBSyxHQUFMLEtBQUssQ0FBZ0Q7SUFBRyxDQUFDO0lBRS9FLEtBQUssQ0FBQyxJQUFnQjtRQUMzQixJQUFJLElBQUksWUFBWSx3Q0FBSyxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFDbEQsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDdEYsT0FBTztZQUNULENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLFlBQVksR0FBRyxJQUFxQyxDQUFDO2dCQUUzRCxJQUFJLHdDQUF3QyxDQUFDLFlBQVksRUFBRSxvREFBb0QsRUFBRTtvQkFDL0csWUFBWTtvQkFDWixHQUFHLElBQUksQ0FBQyxLQUFLO2lCQUNkLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQzs7QUFoQkgsd0dBaUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgSUFzcGVjdCxcbiAgYXdzX2VsYXN0aWNsb2FkYmFsYW5jaW5ndjIgYXMgZWxidjIsXG4gIGF3c19jbG91ZHdhdGNoIGFzIGNsb3Vkd2F0Y2gsXG4gIER1cmF0aW9uLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEFsYXJtQmFzZVByb3BzLCB2YWxpZGF0ZVRvdGFsQWxhcm1QZXJpb2QgfSBmcm9tICcuL2NvbW1vbic7XG5cbi8qKlxuICogVGhlIHJlY29tbWVuZGVkIG1ldHJpY3MgZm9yIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyIGFsYXJtcy5cbiAqL1xuZXhwb3J0IGVudW0gQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJSZWNvbW1lbmRlZEFsYXJtc01ldHJpY3Mge1xuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBjb25uZWN0aW9uIHJlcXVlc3RzIHRoYXQgd2VyZSByZWplY3RlZCBiZWNhdXNlIHRoZSBsb2FkIGJhbGFuY2VyIGhhZCByZWFjaGVkIGl0cyBtYXhpbXVtIGNvbm5lY3Rpb25zLlxuICAgKi9cbiAgUkVKRUNURURfQ09OTkVDVElPTl9DT1VOVCA9ICdSZWplY3RlZENvbm5lY3Rpb25Db3VudCcsXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIEhUVFAgNFhYIGNsaWVudCBlcnJvciBjb2RlcyBnZW5lcmF0ZWQgYnkgdGhlIGxvYWQgYmFsYW5jZXIuXG4gICAqL1xuICBIVFRQX0NPREVfRUxCXzRYWF9DT1VOVCA9ICdIVFRQQ29kZV9FTEJfNFhYX0NvdW50JyxcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgSFRUUCA1WFggc2VydmVyIGVycm9yIGNvZGVzIGdlbmVyYXRlZCBieSB0aGUgbG9hZCBiYWxhbmNlci5cbiAgICovXG4gIEhUVFBfQ09ERV9FTEJfNVhYX0NPVU5UID0gJ0hUVFBDb2RlX0VMQl81WFhfQ291bnQnLFxuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBIVFRQIDVYWCBzZXJ2ZXIgZXJyb3IgY29kZXMgZ2VuZXJhdGVkIGJ5IHRoZSB0YXJnZXRzLlxuICAgKi9cbiAgSFRUUF9DT0RFX1RBUkdFVF81WFhfQ09VTlQgPSAnSFRUUENvZGVfVGFyZ2V0XzVYWF9Db3VudCcsXG59XG5cbi8qKlxuICogVGhlIGNvbW1vbiBvcHRpb25hbCBjb25maWd1cmF0aW9uIGZvciB0aGUgYWxhcm1zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyQWxhcm1CYXNlQ29uZmlnIGV4dGVuZHMgQWxhcm1CYXNlUHJvcHMge1xuICAvKipcbiAgICogVGhlIHBlcmlvZCBvdmVyIHdoaWNoIHRoZSBzcGVjaWZpZWQgc3RhdGlzdGljIGlzIGFwcGxpZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IER1cmF0aW9uLm1pbnV0ZXMoMSlcbiAgICovXG4gIHJlYWRvbmx5IHBlcmlvZD86IER1cmF0aW9uO1xufVxuXG4vKipcbiAqIFRoZSBjb21tb24gcHJvcGVydGllcyBmb3IgdGhlIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyIGFsYXJtcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckFsYXJtUHJvcHMge1xuICAvKipcbiAgICogVGhlIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyIHRvIG1vbml0b3IuXG4gICAqL1xuICByZWFkb25seSBsb2FkQmFsYW5jZXI6IGVsYnYyLkFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBSZWplY3RlZENvbm5lY3Rpb25Db3VudCBhbGFybS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlclJlamVjdGVkQ29ubmVjdGlvbkNvdW50QWxhcm1Db25maWcgZXh0ZW5kcyBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckFsYXJtQmFzZUNvbmZpZyB7XG4gIC8qKlxuICAgKiBUaGUgdmFsdWUgYWdhaW5zdCB3aGljaCB0aGUgc3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBjb21wYXJlZC5cbiAgICogWW91IHNob3VsZCBzZXQgdGhpcyB0aHJlc2hvbGQgYmFzZWQgb24gdGhlIGFjY2VwdGFibGUgbnVtYmVyIG9mIHJlamVjdGVkIGNvbm5lY3Rpb25zLlxuICAgKlxuICAgKiBAZGVmYXVsdCAwXG4gICAqL1xuICByZWFkb25seSB0aHJlc2hvbGQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHBlcmlvZHMgb3ZlciB3aGljaCBkYXRhIGlzIGNvbXBhcmVkIHRvIHRoZSBzcGVjaWZpZWQgdGhyZXNob2xkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAzXG4gICAqL1xuICByZWFkb25seSBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdGhhdCBtdXN0IGJlIGJyZWFjaGluZyB0byB0cmlnZ2VyIHRoZSBhbGFybS5cbiAgICpcbiAgICogQGRlZmF1bHQgM1xuICAgKi9cbiAgcmVhZG9ubHkgZGF0YXBvaW50c1RvQWxhcm0/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgYWxhcm0gbmFtZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBsb2FkQmFsYW5jZXJOYW1lICsgJyAtIFJlamVjdGVkQ29ubmVjdGlvbkNvdW50J1xuICAgKi9cbiAgcmVhZG9ubHkgYWxhcm1OYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBhbGFybS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBUaGlzIGFsYXJtIGlzIHVzZWQgdG8gZGV0ZWN0IHdoZW4gdGhlIGxvYWQgYmFsYW5jZXIgaXMgcmVqZWN0aW5nIGNvbm5lY3Rpb25zLlxuICAgKiBSZWplY3RlZCBjb25uZWN0aW9ucyBjYW4gaW5kaWNhdGUgdGhhdCB0aGUgbG9hZCBiYWxhbmNlciBoYXMgcmVhY2hlZCBpdHMgbWF4aW11bSBjb25uZWN0aW9uIGxpbWl0LlxuICAgKi9cbiAgcmVhZG9ubHkgYWxhcm1EZXNjcmlwdGlvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGUgcHJvcGVydGllcyBmb3IgdGhlIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUmVqZWN0ZWRDb25uZWN0aW9uQ291bnRBbGFybSBjb25zdHJ1Y3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJSZWplY3RlZENvbm5lY3Rpb25Db3VudEFsYXJtUHJvcHMgZXh0ZW5kc1xuICBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckFsYXJtUHJvcHMsIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUmVqZWN0ZWRDb25uZWN0aW9uQ291bnRBbGFybUNvbmZpZyB7fVxuXG4vKipcbiAqIFRoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3Qgd2hlbiB0aGUgbG9hZCBiYWxhbmNlciBpcyByZWplY3RpbmcgY29ubmVjdGlvbnMuXG4gKlxuICogUmVqZWN0ZWQgY29ubmVjdGlvbnMgY2FuIGluZGljYXRlIHRoYXQgdGhlIGxvYWQgYmFsYW5jZXIgaGFzIHJlYWNoZWQgaXRzIG1heGltdW0gY29ubmVjdGlvbiBsaW1pdC5cbiAqXG4gKiBUaGUgYWxhcm0gaXMgdHJpZ2dlcmVkIHdoZW4gdGhlIG51bWJlciBvZiByZWplY3RlZCBjb25uZWN0aW9ucyBpcyBncmVhdGVyIHRoYW4gdGhyZXNob2xkLlxuICovXG5leHBvcnQgY2xhc3MgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJSZWplY3RlZENvbm5lY3Rpb25Db3VudEFsYXJtIGV4dGVuZHMgY2xvdWR3YXRjaC5BbGFybSB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBJQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJSZWplY3RlZENvbm5lY3Rpb25Db3VudEFsYXJtUHJvcHMpIHtcbiAgICBjb25zdCBhbGFybU5hbWUgPSBwcm9wcy5hbGFybU5hbWUgPz8gYCR7cHJvcHMubG9hZEJhbGFuY2VyLmxvYWRCYWxhbmNlck5hbWV9IC0gJHtBcHBsaWNhdGlvbkxvYWRCYWxhbmNlclJlY29tbWVuZGVkQWxhcm1zTWV0cmljcy5SRUpFQ1RFRF9DT05ORUNUSU9OX0NPVU5UfWA7XG4gICAgY29uc3QgcGVyaW9kID0gcHJvcHMucGVyaW9kID8/IER1cmF0aW9uLm1pbnV0ZXMoMSk7XG4gICAgY29uc3QgZXZhbHVhdGlvblBlcmlvZHMgPSBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyA/PyAzO1xuICAgIGNvbnN0IGRhdGFwb2ludHNUb0FsYXJtID0gcHJvcHMuZGF0YXBvaW50c1RvQWxhcm0gPz8gMztcbiAgICBjb25zdCB0aHJlc2hvbGQgPSBwcm9wcy50aHJlc2hvbGQgPz8gMDtcbiAgICBjb25zdCB0cmVhdE1pc3NpbmdEYXRhID0gcHJvcHMudHJlYXRNaXNzaW5nRGF0YSA/PyBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuTUlTU0lORztcbiAgICBjb25zdCBhbGFybURlc2NyaXB0aW9uID0gcHJvcHMuYWxhcm1EZXNjcmlwdGlvbiA/PyAnVGhpcyBhbGFybSBpcyB1c2VkIHRvIGRldGVjdCB3aGVuIHRoZSBsb2FkIGJhbGFuY2VyIGlzIHJlamVjdGluZyBjb25uZWN0aW9ucy4nXG4gICAgICArICcgUmVqZWN0ZWQgY29ubmVjdGlvbnMgY2FuIGluZGljYXRlIHRoYXQgdGhlIGxvYWQgYmFsYW5jZXIgaGFzIHJlYWNoZWQgaXRzIG1heGltdW0gY29ubmVjdGlvbiBsaW1pdC4nO1xuXG4gICAgdmFsaWRhdGVUb3RhbEFsYXJtUGVyaW9kKHBlcmlvZCwgZXZhbHVhdGlvblBlcmlvZHMsIGFsYXJtTmFtZSk7XG5cbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIGFsYXJtTmFtZSxcbiAgICAgIG1ldHJpYzogbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgICAgbmFtZXNwYWNlOiAnQVdTL0FwcGxpY2F0aW9uRUxCJyxcbiAgICAgICAgbWV0cmljTmFtZTogQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJSZWNvbW1lbmRlZEFsYXJtc01ldHJpY3MuUkVKRUNURURfQ09OTkVDVElPTl9DT1VOVCxcbiAgICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICAgIExvYWRCYWxhbmNlcjogcHJvcHMubG9hZEJhbGFuY2VyLmxvYWRCYWxhbmNlckZ1bGxOYW1lLFxuICAgICAgICB9LFxuICAgICAgICBzdGF0aXN0aWM6ICdTdW0nLFxuICAgICAgICBwZXJpb2QsXG4gICAgICB9KSxcbiAgICAgIHRocmVzaG9sZCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBjbG91ZHdhdGNoLkNvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgYWxhcm1EZXNjcmlwdGlvbixcbiAgICB9KTtcblxuICAgIGlmIChwcm9wcy5hbGFybUFjdGlvbikgdGhpcy5hZGRBbGFybUFjdGlvbihwcm9wcy5hbGFybUFjdGlvbik7XG4gICAgaWYgKHByb3BzLm9rQWN0aW9uKSB0aGlzLmFkZE9rQWN0aW9uKHByb3BzLm9rQWN0aW9uKTtcbiAgICBpZiAocHJvcHMuaW5zdWZmaWNpZW50RGF0YUFjdGlvbikgdGhpcy5hZGRJbnN1ZmZpY2llbnREYXRhQWN0aW9uKHByb3BzLmluc3VmZmljaWVudERhdGFBY3Rpb24pO1xuICB9XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIEhUVFBDb2RlX0VMQl80WFhfQ291bnQgYWxhcm0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJIdHRwQ29kZTR4eENvdW50QWxhcm1Db25maWcgZXh0ZW5kc1xuICBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckFsYXJtQmFzZUNvbmZpZyB7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHBlcmlvZHMgb3ZlciB3aGljaCBkYXRhIGlzIGNvbXBhcmVkIHRvIHRoZSBzcGVjaWZpZWQgdGhyZXNob2xkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAzXG4gICAqL1xuICByZWFkb25seSBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdGhhdCBtdXN0IGJlIGJyZWFjaGluZyB0byB0cmlnZ2VyIHRoZSBhbGFybS5cbiAgICpcbiAgICogQGRlZmF1bHQgM1xuICAgKi9cbiAgcmVhZG9ubHkgZGF0YXBvaW50c1RvQWxhcm0/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgd2lkdGggb2YgdGhlIGFub21hbHkgZGV0ZWN0aW9uIGJhbmQsIGV4cHJlc3NlZCBhcyBhIG51bWJlciBvZiBzdGFuZGFyZCBkZXZpYXRpb25zIGZyb20gdGhlIG1ldHJpYydzIG1lYW4uXG4gICAqXG4gICAqIEBkZWZhdWx0IDhcbiAgICovXG4gIHJlYWRvbmx5IHN0ZERldnM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgYWxhcm0gbmFtZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBsb2FkQmFsYW5jZXJOYW1lICsgJyAtIEhUVFBDb2RlX0VMQl80WFhfQ291bnQnXG4gICAqL1xuICByZWFkb25seSBhbGFybU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZGVzY3JpcHRpb24gb2YgdGhlIGFsYXJtLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3Qgd2hlbiB0aGUgbG9hZCBiYWxhbmNlciBpcyBnZW5lcmF0aW5nIDRYWCBlcnJvcnMuXG4gICAqIEEgaGlnaCBudW1iZXIgb2YgNFhYIGVycm9ycyBjYW4gaW5kaWNhdGUgY2xpZW50LXNpZGUgaXNzdWVzIG9yIG1pc2NvbmZpZ3VyZWQgcmVxdWVzdHMuXG4gICAqL1xuICByZWFkb25seSBhbGFybURlc2NyaXB0aW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwcm9wZXJ0aWVzIGZvciB0aGUgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJIdHRwQ29kZTR4eENvdW50QWxhcm0gY29uc3RydWN0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VySHR0cENvZGU0eHhDb3VudEFsYXJtUHJvcHMgZXh0ZW5kc1xuICBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckFsYXJtUHJvcHMsIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VySHR0cENvZGU0eHhDb3VudEFsYXJtQ29uZmlnIHt9XG5cbi8qKlxuICogVGhpcyBhbm9tYWx5IGRldGVjdGlvbiBhbGFybSBpcyB1c2VkIHRvIGRldGVjdCB3aGVuIHRoZSBsb2FkIGJhbGFuY2VyIGlzIGdlbmVyYXRpbmdcbiAqIHVudXN1YWxseSBtYW55IDRYWCBlcnJvcnMuXG4gKlxuICogQSBoaWdoIG51bWJlciBvZiA0WFggZXJyb3JzIGNhbiBpbmRpY2F0ZSBjbGllbnQtc2lkZSBpc3N1ZXMgb3IgbWlzY29uZmlndXJlZCByZXF1ZXN0cy5cbiAqXG4gKiBUaGUgYWxhcm0gaXMgdHJpZ2dlcmVkIHdoZW4gdGhlIG51bWJlciBvZiA0WFggZXJyb3JzIGlzIG91dHNpZGUgdGhlIHVwcGVyIHRocmVzaG9sZFxuICogb2YgdGhlIGFub21hbHkgZGV0ZWN0aW9uIGJhbmQuXG4gKi9cbmV4cG9ydCBjbGFzcyBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckh0dHBDb2RlNHh4Q291bnRBbGFybSBleHRlbmRzIGNsb3Vkd2F0Y2guQW5vbWFseURldGVjdGlvbkFsYXJtIHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IElDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckh0dHBDb2RlNHh4Q291bnRBbGFybVByb3BzKSB7XG4gICAgY29uc3QgYWxhcm1OYW1lID0gcHJvcHMuYWxhcm1OYW1lID8/IGAke3Byb3BzLmxvYWRCYWxhbmNlci5sb2FkQmFsYW5jZXJOYW1lfSAtICR7QXBwbGljYXRpb25Mb2FkQmFsYW5jZXJSZWNvbW1lbmRlZEFsYXJtc01ldHJpY3MuSFRUUF9DT0RFX0VMQl80WFhfQ09VTlR9YDtcbiAgICBjb25zdCBwZXJpb2QgPSBwcm9wcy5wZXJpb2QgPz8gRHVyYXRpb24ubWludXRlcygxKTtcbiAgICBjb25zdCBldmFsdWF0aW9uUGVyaW9kcyA9IHByb3BzLmV2YWx1YXRpb25QZXJpb2RzID8/IDM7XG4gICAgY29uc3QgZGF0YXBvaW50c1RvQWxhcm0gPSBwcm9wcy5kYXRhcG9pbnRzVG9BbGFybSA/PyAzO1xuICAgIGNvbnN0IHN0ZERldnMgPSBwcm9wcy5zdGREZXZzID8/IDg7XG4gICAgY29uc3QgdHJlYXRNaXNzaW5nRGF0YSA9IHByb3BzLnRyZWF0TWlzc2luZ0RhdGEgPz8gY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLk1JU1NJTkc7XG4gICAgY29uc3QgYWxhcm1EZXNjcmlwdGlvbiA9IHByb3BzLmFsYXJtRGVzY3JpcHRpb24gPz8gJ1RoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3Qgd2hlbiB0aGUgbG9hZCBiYWxhbmNlciBpcyBnZW5lcmF0aW5nIDRYWCBlcnJvcnMuJ1xuICAgICAgKyAnIEEgaGlnaCBudW1iZXIgb2YgNFhYIGVycm9ycyBjYW4gaW5kaWNhdGUgY2xpZW50LXNpZGUgaXNzdWVzIG9yIG1pc2NvbmZpZ3VyZWQgcmVxdWVzdHMuJztcblxuICAgIHZhbGlkYXRlVG90YWxBbGFybVBlcmlvZChwZXJpb2QsIGV2YWx1YXRpb25QZXJpb2RzLCBhbGFybU5hbWUpO1xuXG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBhbGFybU5hbWUsXG4gICAgICBtZXRyaWM6IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICAgIG5hbWVzcGFjZTogJ0FXUy9BcHBsaWNhdGlvbkVMQicsXG4gICAgICAgIG1ldHJpY05hbWU6IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUmVjb21tZW5kZWRBbGFybXNNZXRyaWNzLkhUVFBfQ09ERV9FTEJfNFhYX0NPVU5ULFxuICAgICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgICAgTG9hZEJhbGFuY2VyOiBwcm9wcy5sb2FkQmFsYW5jZXIubG9hZEJhbGFuY2VyRnVsbE5hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIHN0YXRpc3RpYzogJ0F2ZXJhZ2UnLFxuICAgICAgfSksXG4gICAgICBzdGREZXZzLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICBkYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGEsXG4gICAgICBjb21wYXJpc29uT3BlcmF0b3I6IGNsb3Vkd2F0Y2guQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9VUFBFUl9USFJFU0hPTEQsXG4gICAgICBhbGFybURlc2NyaXB0aW9uLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLmFsYXJtQWN0aW9uKSB0aGlzLmFkZEFsYXJtQWN0aW9uKHByb3BzLmFsYXJtQWN0aW9uKTtcbiAgICBpZiAocHJvcHMub2tBY3Rpb24pIHRoaXMuYWRkT2tBY3Rpb24ocHJvcHMub2tBY3Rpb24pO1xuICAgIGlmIChwcm9wcy5pbnN1ZmZpY2llbnREYXRhQWN0aW9uKSB0aGlzLmFkZEluc3VmZmljaWVudERhdGFBY3Rpb24ocHJvcHMuaW5zdWZmaWNpZW50RGF0YUFjdGlvbik7XG4gIH1cbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciB0aGUgSFRUUENvZGVfRUxCXzVYWF9Db3VudCBhbGFybS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckh0dHBDb2RlNXh4Q291bnRBbGFybUNvbmZpZyBleHRlbmRzIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyQWxhcm1CYXNlQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgcGVyaW9kcyBvdmVyIHdoaWNoIGRhdGEgaXMgY29tcGFyZWQgdG8gdGhlIHNwZWNpZmllZCB0aHJlc2hvbGQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDNcbiAgICovXG4gIHJlYWRvbmx5IGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBkYXRhIHBvaW50cyB0aGF0IG11c3QgYmUgYnJlYWNoaW5nIHRvIHRyaWdnZXIgdGhlIGFsYXJtLlxuICAgKlxuICAgKiBAZGVmYXVsdCAzXG4gICAqL1xuICByZWFkb25seSBkYXRhcG9pbnRzVG9BbGFybT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBhbGFybSBuYW1lLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGxvYWRCYWxhbmNlck5hbWUgKyAnIC0gSFRUUENvZGVfRUxCXzVYWF9Db3VudCdcbiAgICovXG4gIHJlYWRvbmx5IGFsYXJtTmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSB3aWR0aCBvZiB0aGUgYW5vbWFseSBkZXRlY3Rpb24gYmFuZCwgZXhwcmVzc2VkIGFzIGEgbnVtYmVyIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgZnJvbSB0aGUgbWV0cmljJ3MgbWVhbi5cbiAgICpcbiAgICogQGRlZmF1bHQgOFxuICAgKi9cbiAgcmVhZG9ubHkgc3RkRGV2cz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBkZXNjcmlwdGlvbiBvZiB0aGUgYWxhcm0uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhpcyBhbGFybSBpcyB1c2VkIHRvIGRldGVjdCB3aGVuIHRoZSBsb2FkIGJhbGFuY2VyIGlzIGdlbmVyYXRpbmcgNVhYIGVycm9ycy5cbiAgICogQSBoaWdoIG51bWJlciBvZiA1WFggZXJyb3JzIGNhbiBpbmRpY2F0ZSBpc3N1ZXMgd2l0aCB0aGUgbG9hZCBiYWxhbmNlciBpdHNlbGYuXG4gICAqL1xuICByZWFkb25seSBhbGFybURlc2NyaXB0aW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwcm9wZXJ0aWVzIGZvciB0aGUgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJIdHRwQ29kZTV4eENvdW50QWxhcm0gY29uc3RydWN0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VySHR0cENvZGU1eHhDb3VudEFsYXJtUHJvcHMgZXh0ZW5kc1xuICBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckFsYXJtUHJvcHMsIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VySHR0cENvZGU1eHhDb3VudEFsYXJtQ29uZmlnIHt9XG5cbi8qKlxuICogVGhpcyBhbm9tYWx5IGRldGVjdGlvbiBhbGFybSBpcyB1c2VkIHRvIGRldGVjdCB3aGVuIHRoZSBsb2FkIGJhbGFuY2VyIGlzIGdlbmVyYXRpbmdcbiAqIHVudXN1YWxseSBtYW55IDVYWCBlcnJvcnMuXG4gKlxuICogQSBoaWdoIG51bWJlciBvZiA1WFggZXJyb3JzIGNhbiBpbmRpY2F0ZSBpc3N1ZXMgd2l0aCB0aGUgbG9hZCBiYWxhbmNlciBpdHNlbGYuXG4gKlxuICogVGhlIGFsYXJtIGlzIHRyaWdnZXJlZCB3aGVuIHRoZSBudW1iZXIgb2YgNVhYIGVycm9ycyBpcyBvdXRzaWRlIHRoZSB1cHBlciB0aHJlc2hvbGRcbiAqIG9mIHRoZSBhbm9tYWx5IGRldGVjdGlvbiBiYW5kLlxuICovXG5leHBvcnQgY2xhc3MgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJIdHRwQ29kZTV4eENvdW50QWxhcm0gZXh0ZW5kcyBjbG91ZHdhdGNoLkFub21hbHlEZXRlY3Rpb25BbGFybSB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBJQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJIdHRwQ29kZTV4eENvdW50QWxhcm1Qcm9wcykge1xuICAgIGNvbnN0IGFsYXJtTmFtZSA9IHByb3BzLmFsYXJtTmFtZSA/PyBgJHtwcm9wcy5sb2FkQmFsYW5jZXIubG9hZEJhbGFuY2VyTmFtZX0gLSAke0FwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUmVjb21tZW5kZWRBbGFybXNNZXRyaWNzLkhUVFBfQ09ERV9FTEJfNVhYX0NPVU5UfWA7XG4gICAgY29uc3QgcGVyaW9kID0gcHJvcHMucGVyaW9kID8/IER1cmF0aW9uLm1pbnV0ZXMoMSk7XG4gICAgY29uc3QgZXZhbHVhdGlvblBlcmlvZHMgPSBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyA/PyAzO1xuICAgIGNvbnN0IGRhdGFwb2ludHNUb0FsYXJtID0gcHJvcHMuZGF0YXBvaW50c1RvQWxhcm0gPz8gMztcbiAgICBjb25zdCBzdGREZXZzID0gcHJvcHMuc3RkRGV2cyA/PyA4O1xuICAgIGNvbnN0IHRyZWF0TWlzc2luZ0RhdGEgPSBwcm9wcy50cmVhdE1pc3NpbmdEYXRhID8/IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5NSVNTSU5HO1xuICAgIGNvbnN0IGFsYXJtRGVzY3JpcHRpb24gPSBwcm9wcy5hbGFybURlc2NyaXB0aW9uID8/ICdUaGlzIGFsYXJtIGlzIHVzZWQgdG8gZGV0ZWN0IHdoZW4gdGhlIGxvYWQgYmFsYW5jZXIgaXMgZ2VuZXJhdGluZyA1WFggZXJyb3JzLidcbiAgICAgICsgJyBBIGhpZ2ggbnVtYmVyIG9mIDVYWCBlcnJvcnMgY2FuIGluZGljYXRlIGlzc3VlcyB3aXRoIHRoZSBsb2FkIGJhbGFuY2VyIGl0c2VsZi4nO1xuXG4gICAgdmFsaWRhdGVUb3RhbEFsYXJtUGVyaW9kKHBlcmlvZCwgZXZhbHVhdGlvblBlcmlvZHMsIGFsYXJtTmFtZSk7XG5cbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIGFsYXJtTmFtZSxcbiAgICAgIG1ldHJpYzogbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgICAgbmFtZXNwYWNlOiAnQVdTL0FwcGxpY2F0aW9uRUxCJyxcbiAgICAgICAgbWV0cmljTmFtZTogQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJSZWNvbW1lbmRlZEFsYXJtc01ldHJpY3MuSFRUUF9DT0RFX0VMQl81WFhfQ09VTlQsXG4gICAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgICBMb2FkQ