acr-assist-simulator-module
Version:
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.7.4.
426 lines (425 loc) • 59.8 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import { Injectable } from '@angular/core';
import { SimulatorState } from '../models/simulator-state.model';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { DataElementValues } from '../dataelementvalues';
import { ArithmeticExpression } from '../models/arithmetic-expression.model';
import { isArray } from 'util';
const /** @type {?} */ expressionParser = require('expr-eval').Parser;
export class SimulatorEngineService {
constructor() {
this.endOfRoadReached = false;
this.lastConditionMetBranchLevel = 1;
this.nonRelevantDataElementIds = new Array();
this.simulatorStateChanged = new BehaviorSubject(new SimulatorState());
this.dataElementValues = new Map();
this.dataElementTexts = new Map();
this.nonRelevantDataElementIds = new Array();
}
/**
* @return {?}
*/
getTemplate() {
return this.template;
}
/**
* @return {?}
*/
getAllDataElementValues() {
return this.dataElementValues;
}
/**
* @return {?}
*/
getAllDataElementTexts() {
return this.dataElementTexts;
}
/**
* @param {?} dataElementId
* @return {?}
*/
getDataElementValue(dataElementId) {
return this.dataElementValues[dataElementId];
}
/**
* @param {?} dataElementId
* @return {?}
*/
getDataElementText(dataElementId) {
return this.dataElementTexts[dataElementId];
}
/**
* @param {?} dataElementId
* @param {?} value
* @param {?} text
* @return {?}
*/
addOrUpdateDataElement(dataElementId, value, text) {
this.dataElementValues[dataElementId] = value;
this.dataElementTexts[dataElementId] = text;
this.evaluateDecisionPoints();
}
/**
* @param {?} decisionPoint
* @param {?} branchingLevel
* @return {?}
*/
evaluateDecisionPoint(decisionPoint, branchingLevel) {
let /** @type {?} */ currentBranchCount = 0;
const /** @type {?} */ totalBranchesInDecisionPoint = decisionPoint.branches.length;
for (const /** @type {?} */ branch of decisionPoint.branches) {
currentBranchCount++;
let /** @type {?} */ conditionMet = false;
if (this.endOfRoadReached) {
break;
}
if (branch.compositeCondition !== undefined) {
conditionMet = branch.compositeCondition.evaluate(new DataElementValues(this.dataElementValues));
}
else if (branch.condition !== undefined) {
conditionMet = branch.condition.evaluate(new DataElementValues(this.dataElementValues));
}
if (conditionMet) {
this.lastConditionMetBranchLevel = branchingLevel;
// if (nonRelevantDataElementIds === undefined) {
// nonRelevantDataElementIds = new Array<string>();
// }
// if (branch.notRelevantDataElements !== undefined) {
// for (const nonRelevantDataElementReference of branch.notRelevantDataElements.dataElementReferences) {
// nonRelevantDataElementIds.push(nonRelevantDataElementReference.dataElementId);
// }
// }
if (branch.decisionPoints !== undefined) {
for (const /** @type {?} */ branchDecisionPoint of branch.decisionPoints) {
const /** @type {?} */ newBranchingLevel = branchingLevel + 1;
// this.evaluateDecisionPoint(branchDecisionPoint, newBranchingLevel, nonRelevantDataElementIds);
this.evaluateDecisionPoint(branchDecisionPoint, newBranchingLevel);
}
}
else if (branch.endPointRef !== undefined) {
const /** @type {?} */ simulatorState = new SimulatorState();
simulatorState.endPointId = branch.endPointRef.endPointId;
// simulatorState.nonRelevantDataElementIds = nonRelevantDataElementIds;
simulatorState.selectedBranchLabel = branch.label;
simulatorState.selectedDecisionPointId = decisionPoint.id;
simulatorState.selectedDecisionPointLabel = decisionPoint.label;
// this.resetValuesOfNonRelevantDataElements(nonRelevantDataElementIds);
this.simulatorStateChanged.next(simulatorState);
this.endOfRoadReached = true;
break;
}
}
else {
if (currentBranchCount >= totalBranchesInDecisionPoint) {
this.endOfRoadReached = true;
const /** @type {?} */ simulatorState = new SimulatorState();
// simulatorState.nonRelevantDataElementIds = nonRelevantDataElementIds;
// this.resetValuesOfNonRelevantDataElements(nonRelevantDataElementIds);
this.simulatorStateChanged.next(simulatorState);
return;
}
else {
continue;
}
}
}
}
/**
* @param {?} nonRelevantDataElementIds
* @return {?}
*/
resetValuesOfNonRelevantDataElements(nonRelevantDataElementIds) {
// console.log(this.template.dataElements);
if (nonRelevantDataElementIds !== undefined) {
for (const /** @type {?} */ nonRelevantDataElementId of nonRelevantDataElementIds) {
let /** @type {?} */ defaultValue;
for (const /** @type {?} */ dataElement of this.template.dataElements) {
if (dataElement.id === nonRelevantDataElementId) {
defaultValue = dataElement.defaultValue;
break;
}
}
this.dataElementValues[nonRelevantDataElementId] = defaultValue;
}
}
}
/**
* @param {?} elementId
* @param {?} decisionPoint
* @param {?} branchingLevel
* @return {?}
*/
evaluateComputedElementDecisionPoint(elementId, decisionPoint, branchingLevel) {
let /** @type {?} */ currentBranchCount = 0;
const /** @type {?} */ totalBranchesInDecisionPoint = decisionPoint.branches.length;
for (const /** @type {?} */ branch of decisionPoint.branches) {
currentBranchCount++;
let /** @type {?} */ conditionMet = false;
if (this.endOfRoadReached) {
break;
}
if (branch.compositeCondition !== undefined) {
conditionMet = branch.compositeCondition.evaluate(new DataElementValues(this.dataElementValues));
}
else if (branch.condition !== undefined) {
conditionMet = branch.condition.evaluate(new DataElementValues(this.dataElementValues));
}
if (conditionMet) {
this.lastConditionMetBranchLevel = branchingLevel;
if (branch.decisionPoints !== undefined) {
for (const /** @type {?} */ branchDecisionPoint of branch.decisionPoints) {
const /** @type {?} */ newBranchingLevel = branchingLevel + 1;
this.evaluateComputedElementDecisionPoint(elementId, branchDecisionPoint, newBranchingLevel);
}
}
else if (branch.computedValue !== undefined) {
this.dataElementValues[elementId] = branch.computedValue.expressionText;
this.endOfRoadReached = true;
if (branch.computedValue instanceof ArithmeticExpression) {
this.dataElementValues[elementId] = this.evaluateArithmeticExpression(branch.computedValue.expressionText);
this.endOfRoadReached = true;
}
else {
this.dataElementValues[elementId] = branch.computedValue.expressionText;
this.endOfRoadReached = true;
}
break;
}
}
else {
if (currentBranchCount >= totalBranchesInDecisionPoint) {
this.endOfRoadReached = true;
this.dataElementValues[elementId] = undefined;
return;
}
else {
continue;
}
}
}
}
/**
* @param {?} computedValue
* @return {?}
*/
evaluateArithmeticExpression(computedValue) {
let /** @type {?} */ startIndex = 0;
let /** @type {?} */ endIndex = 0;
while (startIndex !== -1 && endIndex !== -1) {
startIndex = computedValue.indexOf('{');
endIndex = computedValue.indexOf('}');
if (startIndex !== -1 && endIndex !== -1) {
const /** @type {?} */ dataElementId = computedValue.substring(startIndex + 1, endIndex);
const /** @type {?} */ replacingValue = computedValue.substring(startIndex, endIndex + 1);
let /** @type {?} */ dataElementValue = this.dataElementValues[dataElementId];
if (isArray(dataElementValue)) {
let /** @type {?} */ sum = 0;
dataElementValue.forEach(val => {
sum += +val;
});
dataElementValue = sum;
}
computedValue = computedValue.replace(replacingValue, dataElementValue);
}
}
return expressionParser.evaluate(computedValue).toString();
}
/**
* @return {?}
*/
evaluateComputedExpressions() {
this.endOfRoadReached = false;
let /** @type {?} */ expressionValue;
for (const /** @type {?} */ element of this.template.dataElements) {
if (element.dataElementType === 'ComputedDataElement') {
expressionValue = undefined;
const /** @type {?} */ computedElement = /** @type {?} */ (element);
for (const /** @type {?} */ decisionPoint of computedElement.decisionPoints) {
this.evaluateComputedElementDecisionPoint(element.id, decisionPoint, 1);
if (this.dataElementValues[element.id] === undefined && decisionPoint.defaultBranch &&
decisionPoint.defaultBranch.computedValue) {
this.dataElementValues[element.id] = decisionPoint.defaultBranch.computedValue.expressionText;
}
this.endOfRoadReached = false;
}
}
}
}
/**
* @param {?} dataelement
* @param {?=} nonRelevantDataElementIds
* @return {?}
*/
evaluateConditionalProperty(dataelement, nonRelevantDataElementIds = []) {
if (dataelement.conditionalProperties !== undefined) {
let /** @type {?} */ conditionMet = false;
let /** @type {?} */ isCompositeCondition = false;
for (const /** @type {?} */ conditionalProperty of dataelement.conditionalProperties) {
if (conditionalProperty.condition !== undefined) {
conditionMet = conditionalProperty.condition.evaluate(new DataElementValues(this.dataElementValues));
isCompositeCondition = false;
}
else if (conditionalProperty.compositeCondition !== undefined) {
conditionMet = conditionalProperty.compositeCondition.evaluate(new DataElementValues(this.dataElementValues));
isCompositeCondition = true;
}
if (conditionMet) {
if (nonRelevantDataElementIds === undefined) {
this.nonRelevantDataElementIds = new Array();
}
if (conditionalProperty.isRelevant === 'false') {
this.nonRelevantDataElementIds.push(dataelement.id);
}
else {
dataelement.displaySequence = conditionalProperty.DisplaySequence;
dataelement.isRequired = conditionalProperty.isRequired !== undefined ?
(conditionalProperty.isRequired.toLowerCase() === 'true' ? true : false)
: true;
if (conditionalProperty.Minimum !== undefined && conditionalProperty.Minimum != null) {
dataelement.minimum = +conditionalProperty.Minimum;
}
if (conditionalProperty.Maximum !== undefined && conditionalProperty.Maximum != null) {
dataelement.maximum = +conditionalProperty.Maximum;
}
if (dataelement.dataElementType === 'ChoiceDataElement') {
(/** @type {?} */ (dataelement)).ChoiceNotRelevant = conditionalProperty.ChoiceNotRelevant;
}
if (dataelement.dataElementType === 'MultiChoiceDataElement') {
(/** @type {?} */ (dataelement)).ChoiceNotRelevant = conditionalProperty.ChoiceNotRelevant;
}
if (dataelement.dataElementType === 'DurationDataElement') {
(/** @type {?} */ (dataelement)).MinimumDay = +conditionalProperty.MinimumDay;
(/** @type {?} */ (dataelement)).MaximumDay = +conditionalProperty.MaximumDay;
(/** @type {?} */ (dataelement)).MinimumHours = +conditionalProperty.MinimumHours;
(/** @type {?} */ (dataelement)).MaximumHours = +conditionalProperty.MaximumHours;
(/** @type {?} */ (dataelement)).MinimumMinutes = +conditionalProperty.MinimumMinutes;
(/** @type {?} */ (dataelement)).MaxmimumMinutes = +conditionalProperty.MaxmimumMinutes;
}
}
return this.nonRelevantDataElementIds;
}
else {
if (dataelement.dataElementType === 'ChoiceDataElement') {
(/** @type {?} */ (dataelement)).ChoiceNotRelevant = new Array();
}
if (dataelement.dataElementType === 'MultiChoiceDataElement') {
(/** @type {?} */ (dataelement)).ChoiceNotRelevant = new Array();
}
}
}
}
else {
// temp code
// if (this.nonRelevantDataElementIds.length === 0) {
// dataelement.isRequired = true;
// }
}
}
/**
* @return {?}
*/
isCondtionMet() {
for (const /** @type {?} */ dataelement of this.template.dataElements) {
if (dataelement.conditionalProperties !== undefined) {
let /** @type {?} */ conditionMet = false;
let /** @type {?} */ isCompositeCondition = false;
for (const /** @type {?} */ conditionalProperty of dataelement.conditionalProperties) {
if (conditionalProperty.condition !== undefined) {
conditionMet = conditionalProperty.condition.evaluate(new DataElementValues(this.dataElementValues));
isCompositeCondition = false;
}
else if (conditionalProperty.compositeCondition !== undefined) {
conditionMet = conditionalProperty.compositeCondition.evaluate(new DataElementValues(this.dataElementValues));
isCompositeCondition = true;
}
if (conditionMet) {
return true;
}
return false;
}
}
}
}
/**
* @return {?}
*/
evaluateDecisionAndConditionalProperty() {
this.nonRelevantDataElementIds = new Array();
this.RevertConditionValues();
for (const /** @type {?} */ dataelement of this.template.dataElements) {
this.evaluateConditionalProperty(dataelement, new Array());
}
this.resetValuesOfNonRelevantDataElements(this.nonRelevantDataElementIds);
return this.nonRelevantDataElementIds;
}
/**
* @return {?}
*/
RevertConditionValues() {
for (const /** @type {?} */ dataelement of this.template.dataElements) {
dataelement.isRequired = dataelement.isRequiredOverrider;
dataelement.displaySequence = dataelement.displaySequenceOverrider;
if (dataelement.dataElementType === 'NumericDataElement') {
(/** @type {?} */ (dataelement)).minimum = +(/** @type {?} */ (dataelement)).minimumOverrider;
(/** @type {?} */ (dataelement)).maximum = +(/** @type {?} */ (dataelement)).maximumOverrider;
}
if (dataelement.dataElementType === 'IntegerDataElement') {
(/** @type {?} */ (dataelement)).minimum = +(/** @type {?} */ (dataelement)).minimumOverrider;
(/** @type {?} */ (dataelement)).maximum = +(/** @type {?} */ (dataelement)).maximumOverrider;
}
if (dataelement.dataElementType === 'DurationDataElement') {
(/** @type {?} */ (dataelement)).MinimumDay = +(/** @type {?} */ (dataelement)).MinimumDayOverrider;
(/** @type {?} */ (dataelement)).MaximumDay = +(/** @type {?} */ (dataelement)).MaximumDayOverrider;
(/** @type {?} */ (dataelement)).MinimumHours = +(/** @type {?} */ (dataelement)).MinimumHoursOverrider;
(/** @type {?} */ (dataelement)).MaximumHours = +(/** @type {?} */ (dataelement)).MaximumHoursOverrider;
(/** @type {?} */ (dataelement)).MinimumMinutes = +(/** @type {?} */ (dataelement)).MinimumMinutesOverrider;
(/** @type {?} */ (dataelement)).MaxmimumMinutes = +(/** @type {?} */ (dataelement)).MaxmimumMinutesOverrider;
}
}
}
/**
* @return {?}
*/
evaluateDecisionPoints() {
this.evaluateComputedExpressions();
this.endOfRoadReached = false;
for (const /** @type {?} */ decisionPoint of this.template.rules.decisionPoints) {
this.evaluateDecisionPoint(decisionPoint, 1);
}
}
/**
* @param {?} template
* @return {?}
*/
initialize(template) {
this.template = template;
for (const /** @type {?} */ dataElement of this.template.dataElements) {
this.dataElementValues[dataElement.id] = dataElement.currentValue;
}
}
}
SimulatorEngineService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
SimulatorEngineService.ctorParameters = () => [];
function SimulatorEngineService_tsickle_Closure_declarations() {
/** @type {?} */
SimulatorEngineService.prototype.template;
/** @type {?} */
SimulatorEngineService.prototype.dataElementValues;
/** @type {?} */
SimulatorEngineService.prototype.dataElementTexts;
/** @type {?} */
SimulatorEngineService.prototype.endOfRoadReached;
/** @type {?} */
SimulatorEngineService.prototype.lastConditionMetBranchLevel;
/** @type {?} */
SimulatorEngineService.prototype.nonRelevantDataElementIds;
/** @type {?} */
SimulatorEngineService.prototype.simulatorStateChanged;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltdWxhdG9yLWVuZ2luZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYWNyLWFzc2lzdC1zaW11bGF0b3ItbW9kdWxlLyIsInNvdXJjZXMiOlsic3JjL2FwcC9tb2R1bGVzL2NvcmUvc2VydmljZXMvc2ltdWxhdG9yLWVuZ2luZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFekQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDN0UsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQU0vQix1QkFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDO0FBR3JELE1BQU07SUFXSjtnQ0FOMkIsS0FBSzsyQ0FDTSxDQUFDO3lDQUNILElBQUksS0FBSyxFQUFVO3FDQUUvQixJQUFJLGVBQWUsQ0FBaUIsSUFBSSxjQUFjLEVBQUUsQ0FBQztRQUcvRSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQWUsQ0FBQztRQUNoRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxHQUFHLEVBQWUsQ0FBQztRQUMvQyxJQUFJLENBQUMseUJBQXlCLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztLQUN0RDs7OztJQUVELFdBQVc7UUFDVCxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztLQUN0Qjs7OztJQUVELHVCQUF1QjtRQUNyQixNQUFNLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDO0tBQy9COzs7O0lBRUQsc0JBQXNCO1FBQ3BC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QUFDLG1CQUFDLFdBQWtDLEVBQUMsQ0FBQyxxQkFBcUIsQ0FBQztnQkFDaEgsbUJBQUMsV0FBa0MsRUFBQyxDQUFDLGNBQWMsR0FBRyxDQUFDLG1CQUFDLFdBQWtDLEVBQUMsQ0FBQyx1QkFBdUIsQ0FBQztnQkFDcEgsbUJBQUMsV0FBa0MsRUFBQyxDQUFDLGVBQWUsR0FBRyxDQUFDLG1CQUFDLFdBQWtDLEVBQUMsQ0FBQyx3QkFBd0IsQ0FBQzthQUN2SDtTQUNGOzs7OztJQUdLLHNCQUFzQjtRQUM1QixJQUFJLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztRQUNuQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO1FBQzlCLEdBQUcsQ0FBQyxDQUFDLHVCQUFNLGFBQWEsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1lBQy9ELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDOUM7Ozs7OztJQUdILFVBQVUsQ0FBQyxRQUFrQjtRQUMzQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixHQUFHLENBQUMsQ0FBQyx1QkFBTSxXQUFXLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQ3JELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLEdBQUcsV0FBVyxDQUFDLFlBQVksQ0FBQztTQUNuRTtLQUNGOzs7WUF0V0YsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgVGVtcGxhdGUgfSBmcm9tICcuLi9tb2RlbHMvdGVtcGxhdGUubW9kZWwnO1xyXG5pbXBvcnQgeyBTaW11bGF0b3JTdGF0ZSB9IGZyb20gJy4uL21vZGVscy9zaW11bGF0b3Itc3RhdGUubW9kZWwnO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzL0JlaGF2aW9yU3ViamVjdCc7XHJcbmltcG9ydCB7IERlY2lzaW9uUG9pbnQgfSBmcm9tICcuLi9tb2RlbHMvZGVjaXNpb25wb2ludC5tb2RlbCc7XHJcbmltcG9ydCB7IERhdGFFbGVtZW50VmFsdWVzIH0gZnJvbSAnLi4vZGF0YWVsZW1lbnR2YWx1ZXMnO1xyXG5pbXBvcnQgeyBDb21wdXRlZERhdGFFbGVtZW50IH0gZnJvbSAnLi4vZWxlbWVudHMvbW9kZWxzL2NvbXB1dGVkLWRhdGEtZWxlbWVudC1tb2RlbCc7XHJcbmltcG9ydCB7IEFyaXRobWV0aWNFeHByZXNzaW9uIH0gZnJvbSAnLi4vbW9kZWxzL2FyaXRobWV0aWMtZXhwcmVzc2lvbi5tb2RlbCc7XHJcbmltcG9ydCB7IGlzQXJyYXkgfSBmcm9tICd1dGlsJztcclxuaW1wb3J0IHsgQ2hvaWNlRGF0YUVsZW1lbnQgfSBmcm9tICcuLi9lbGVtZW50cy9tb2RlbHMvY2hvaWNlLWRhdGEtZWxlbWVudC1tb2RlbCc7XHJcbmltcG9ydCB7IE51bWVyaWNEYXRhRWxlbWVudCB9IGZyb20gJy4uL2VsZW1lbnRzL21vZGVscy9udW1lcmljLWRhdGEtZWxlbWVudC5tb2RlbCc7XHJcbmltcG9ydCB7IEludGVnZXJEYXRhRWxlbWVudCB9IGZyb20gJy4uL2VsZW1lbnRzL21vZGVscy9pbnRlZ2VyLWRhdGEtZWxlbWVudC5tb2RlbCc7XHJcbmltcG9ydCB7IER1cmF0aW9uRGF0YUVsZW1lbnQgfSBmcm9tICcuLi9lbGVtZW50cy9tb2RlbHMvZHVyYXRpb24tZGF0YS1lbGVtZW50Lm1vZGVsJztcclxuaW1wb3J0IHsgTXVsdGlDaG9pY2VEYXRhRWxlbWVudCB9IGZyb20gJy4uL2VsZW1lbnRzL21vZGVscy9tdWx0aS1jaG9pY2UtZGF0YS1lbGVtZW50JztcclxuY29uc3QgZXhwcmVzc2lvblBhcnNlciA9IHJlcXVpcmUoJ2V4cHItZXZhbCcpLlBhcnNlcjtcclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIFNpbXVsYXRvckVuZ2luZVNlcnZpY2Uge1xyXG5cclxuICBwcml2YXRlIHRlbXBsYXRlOiBUZW1wbGF0ZTtcclxuICBwcml2YXRlIGRhdGFFbGVtZW50VmFsdWVzOiBNYXA8c3RyaW5nLCBhbnk+O1xyXG4gIHByaXZhdGUgZGF0YUVsZW1lbnRUZXh0czogTWFwPHN0cmluZywgYW55PjtcclxuICBwcml2YXRlIGVuZE9mUm9hZFJlYWNoZWQgPSBmYWxzZTtcclxuICBwcml2YXRlIGxhc3RDb25kaXRpb25NZXRCcmFuY2hMZXZlbCA9IDE7XHJcbiAgcHJpdmF0ZSBub25SZWxldmFudERhdGFFbGVtZW50SWRzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcclxuXHJcbiAgc2ltdWxhdG9yU3RhdGVDaGFuZ2VkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxTaW11bGF0b3JTdGF0ZT4obmV3IFNpbXVsYXRvclN0YXRlKCkpO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICAgIHRoaXMuZGF0YUVsZW1lbnRWYWx1ZXMgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xyXG4gICAgdGhpcy5kYXRhRWxlbWVudFRleHRzID0gbmV3IE1hcDxzdHJpbmcsIGFueT4oKTtcclxuICAgIHRoaXMubm9uUmVsZXZhbnREYXRhRWxlbWVudElkcyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XHJcbiAgfVxyXG5cclxuICBnZXRUZW1wbGF0ZSgpOiBUZW1wbGF0ZSB7XHJcbiAgICByZXR1cm4gdGhpcy50ZW1wbGF0ZTtcclxuICB9XHJcblxyXG4gIGdldEFsbERhdGFFbGVtZW50VmFsdWVzKCk6IE1hcDxzdHJpbmcsIGFueT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZGF0YUVsZW1lbnRWYWx1ZXM7XHJcbiAgfVxyXG5cclxuICBnZXRBbGxEYXRhRWxlbWVudFRleHRzKCk6IE1hcDxzdHJpbmcsIGFueT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZGF0YUVsZW1lbnRUZXh0cztcclxuICB9XHJcblxyXG4gIGdldERhdGFFbGVtZW50VmFsdWUoZGF0YUVsZW1lbnRJZDogc3RyaW5nKTogYW55IHtcclxuICAgIHJldHVybiB0aGlzLmRhdGFFbGVtZW50VmFsdWVzW2RhdGFFbGVtZW50SWRdO1xyXG4gIH1cclxuXHJcbiAgZ2V0RGF0YUVsZW1lbnRUZXh0KGRhdGFFbGVtZW50SWQ6IHN0cmluZyk6IGFueSB7XHJcbiAgICByZXR1cm4gdGhpcy5kYXRhRWxlbWVudFRleHRzW2RhdGFFbGVtZW50SWRdO1xyXG4gIH1cclxuXHJcbiAgYWRkT3JVcGRhdGVEYXRhRWxlbWVudChkYXRhRWxlbWVudElkOiBzdHJpbmcsIHZhbHVlOiBhbnksIHRleHQ6IGFueSkge1xyXG4gICAgdGhpcy5kYXRhRWxlbWVudFZhbHVlc1tkYXRhRWxlbWVudElkXSA9IHZhbHVlO1xyXG4gICAgdGhpcy5kYXRhRWxlbWVudFRleHRzW2RhdGFFbGVtZW50SWRdID0gdGV4dDtcclxuICAgIHRoaXMuZXZhbHVhdGVEZWNpc2lvblBvaW50cygpO1xyXG4gIH1cclxuXHJcblxyXG4gIGV2YWx1YXRlRGVjaXNpb25Qb2ludChkZWNpc2lvblBvaW50OiBEZWNpc2lvblBvaW50LCBicmFuY2hpbmdMZXZlbCkge1xyXG4gICAgbGV0IGN1cnJlbnRCcmFuY2hDb3VudCA9IDA7XHJcbiAgICBjb25zdCB0b3RhbEJyYW5jaGVzSW5EZWNpc2lvblBvaW50ID0gZGVjaXNpb25Qb2ludC5icmFuY2hlcy5sZW5ndGg7XHJcbiAgICBmb3IgKGNvbnN0IGJyYW5jaCBvZiBkZWNpc2lvblBvaW50LmJyYW5jaGVzKSB7XHJcbiAgICAgIGN1cnJlbnRCcmFuY2hDb3VudCsrO1xyXG4gICAgICBsZXQgY29uZGl0aW9uTWV0ID0gZmFsc2U7XHJcbiAgICAgIGlmICh0aGlzLmVuZE9mUm9hZFJlYWNoZWQpIHtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKGJyYW5jaC5jb21wb3NpdGVDb25kaXRpb24gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIGNvbmRpdGlvbk1ldCA9IGJyYW5jaC5jb21wb3NpdGVDb25kaXRpb24uZXZhbHVhdGUobmV3IERhdGFFbGVtZW50VmFsdWVzKHRoaXMuZGF0YUVsZW1lbnRWYWx1ZXMpKTtcclxuICAgICAgfSBlbHNlIGlmIChicmFuY2guY29uZGl0aW9uICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICBjb25kaXRpb25NZXQgPSBicmFuY2guY29uZGl0aW9uLmV2YWx1YXRlKG5ldyBEYXRhRWxlbWVudFZhbHVlcyh0aGlzLmRhdGFFbGVtZW50VmFsdWVzKSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChjb25kaXRpb25NZXQpIHtcclxuICAgICAgICB0aGlzLmxhc3RDb25kaXRpb25NZXRCcmFuY2hMZXZlbCA9IGJyYW5jaGluZ0xldmVsO1xyXG4gICAgICAgIC8vIGlmIChub25SZWxldmFudERhdGFFbGVtZW50SWRzID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAvLyAgIG5vblJlbGV2YW50RGF0YUVsZW1lbnRJZHMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xyXG4gICAgICAgIC8vIH1cclxuICAgICAgICAvLyBpZiAoYnJhbmNoLm5vdFJlbGV2YW50RGF0YUVsZW1lbnRzICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAvLyAgIGZvciAoY29uc3Qgbm9uUmVsZXZhbnREYXRhRWxlbWVudFJlZmVyZW5jZSBvZiBicmFuY2gubm90UmVsZXZhbnREYXRhRWxlbWVudHMuZGF0YUVsZW1lbnRSZWZlcmVuY2VzKSB7XHJcbiAgICAgICAgLy8gICAgIG5vblJlbGV2YW50RGF0YUVsZW1lbnRJZHMucHVzaChub25SZWxldmFudERhdGFFbGVtZW50UmVmZXJlbmNlLmRhdGFFbGVtZW50SWQpO1xyXG4gICAgICAgIC8vICAgfVxyXG4gICAgICAgIC8vIH1cclxuXHJcbiAgICAgICAgaWYgKGJyYW5jaC5kZWNpc2lvblBvaW50cyAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IGJyYW5jaERlY2lzaW9uUG9pbnQgb2YgYnJhbmNoLmRlY2lzaW9uUG9pbnRzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG5ld0JyYW5jaGluZ0xldmVsID0gYnJhbmNoaW5nTGV2ZWwgKyAxO1xyXG4gICAgICAgICAgICAvLyB0aGlzLmV2YWx1YXRlRGVjaXNpb25Qb2ludChicmFuY2hEZWNpc2lvblBvaW50LCBuZXdCcmFuY2hpbmdMZXZlbCwgbm9uUmVsZXZhbnREYXRhRWxlbWVudElkcyk7XHJcbiAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVEZWNpc2lvblBvaW50KGJyYW5jaERlY2lzaW9uUG9pbnQsIG5ld0JyYW5jaGluZ0xldmVsKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2UgaWYgKGJyYW5jaC5lbmRQb2ludFJlZiAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICBjb25zdCBzaW11bGF0b3JTdGF0ZSA9IG5ldyBTaW11bGF0b3JTdGF0ZSgpO1xyXG4gICAgICAgICAgc2ltdWxhdG9yU3RhdGUuZW5kUG9pbnRJZCA9IGJyYW5jaC5lbmRQb2ludFJlZi5lbmRQb2ludElkO1xyXG4gICAgICAgICAgLy8gc2ltdWxhdG9yU3RhdGUubm9uUmVsZXZhbnREYXRhRWxlbWVudElkcyA9IG5vblJlbGV2YW50RGF0YUVsZW1lbnRJZHM7XHJcbiAgICAgICAgICBzaW11bGF0b3JTdGF0ZS5zZWxlY3RlZEJyYW5jaExhYmVsID0gYnJhbmNoLmxhYmVsO1xyXG4gICAgICAgICAgc2ltdWxhdG9yU3RhdGUuc2VsZWN0ZWREZWNpc2lvblBvaW50SWQgPSBkZWNpc2lvblBvaW50LmlkO1xyXG4gICAgICAgICAgc2ltdWxhdG9yU3RhdGUuc2VsZWN0ZWREZWNpc2lvblBvaW50TGFiZWwgPSBkZWNpc2lvblBvaW50LmxhYmVsO1xyXG4gICAgICAgICAgLy8gdGhpcy5yZXNldFZhbHVlc09mTm9uUmVsZXZhbnREYXRhRWxlbWVudHMobm9uUmVsZXZhbnREYXRhRWxlbWVudElkcyk7XHJcblxyXG4gICAgICAgICAgdGhpcy5zaW11bGF0b3JTdGF0ZUNoYW5nZWQubmV4dChzaW11bGF0b3JTdGF0ZSk7XHJcbiAgICAgICAgICB0aGlzLmVuZE9mUm9hZFJlYWNoZWQgPSB0cnVlO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmIChjdXJyZW50QnJhbmNoQ291bnQgPj0gdG90YWxCcmFuY2hlc0luRGVjaXNpb25Qb2ludCkge1xyXG4gICAgICAgICAgdGhpcy5lbmRPZlJvYWRSZWFjaGVkID0gdHJ1ZTtcclxuICAgICAgICAgIGNvbnN0IHNpbXVsYXRvclN0YXRlID0gbmV3IFNpbXVsYXRvclN0YXRlKCk7XHJcbiAgICAgICAgICAvLyBzaW11bGF0b3JTdGF0ZS5ub25SZWxldmFudERhdGFFbGVtZW50SWRzID0gbm9uUmVsZXZhbnREYXRhRWxlbWVudElkcztcclxuICAgICAgICAgIC8vIHRoaXMucmVzZXRWYWx1ZXNPZk5vblJlbGV2YW50RGF0YUVsZW1lbnRzKG5vblJlbGV2YW50RGF0YUVsZW1lbnRJZHMpO1xyXG4gICAgICAgICAgdGhpcy5zaW11bGF0b3JTdGF0ZUNoYW5nZWQubmV4dChzaW11bGF0b3JTdGF0ZSk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZXNldFZhbHVlc09mTm9uUmVsZXZhbnREYXRhRWxlbWVudHMobm9uUmVsZXZhbnREYXRhRWxlbWVudElkczogc3RyaW5nW10pIHtcclxuICAgLy8gY29uc29sZS5sb2codGhpcy50ZW1wbGF0ZS5kYXRhRWxlbWVudHMpO1xyXG4gICAgaWYgKG5vblJlbGV2YW50RGF0YUVsZW1lbnRJZHMgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBmb3IgKGNvbnN0IG5vblJlbGV2YW50RGF0YUVsZW1lbnRJZCBvZiBub25SZWxldmFudERhdGFFbGVtZW50SWRzKSB7XHJcbiAgICAgICAgbGV0IGRlZmF1bHRWYWx1ZTogYW55O1xyXG4gICAgICAgIGZvciAoY29uc3QgZGF0YUVsZW1lbnQgb2YgdGhpcy50ZW1wbGF0ZS5kYXRhRWxlbWVudHMpIHtcclxuICAgICAgICAgIGlmIChkYXRhRWxlbWVudC5pZCA9PT0gbm9uUmVsZXZhbnREYXRhRWxlbWVudElkKSB7XHJcbiAgICAgICAgICAgIGRlZmF1bHRWYWx1ZSA9IGRhdGFFbGVtZW50LmRlZmF1bHRWYWx1ZTtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmRhdGFFbGVtZW50VmFsdWVzW25vblJlbGV2YW50RGF0YUVsZW1lbnRJZF0gPSBkZWZhdWx0VmFsdWU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGV2YWx1YXRlQ29tcHV0ZWRFbGVtZW50RGVjaXNpb25Qb2ludChlbGVtZW50SWQ6IHN0cmluZywgZGVjaXNpb25Qb2ludDogRGVjaXNpb25Qb2ludCwgYnJhbmNoaW5nTGV2ZWwpIHtcclxuICAgIGxldCBjdXJyZW50QnJhbmNoQ291bnQgPSAwO1xyXG4gICAgY29uc3QgdG90YWxCcmFuY2hlc0luRGVjaXNpb25Qb2ludCA9IGRlY2lzaW9uUG9pbnQuYnJhbmNoZXMubGVuZ3RoO1xyXG4gICAgZm9yIChjb25zdCBicmFuY2ggb2YgZGVjaXNpb25Qb2ludC5icmFuY2hlcykge1xyXG5cclxuICAgICAgY3VycmVudEJyYW5jaENvdW50Kys7XHJcbiAgICAgIGxldCBjb25kaXRpb25NZXQgPSBmYWxzZTtcclxuICAgICAgaWYgKHRoaXMuZW5kT2ZSb2FkUmVhY2hlZCkge1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChicmFuY2guY29tcG9zaXRlQ29uZGl0aW9uICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICBjb25kaXRpb25NZXQgPSBicmFuY2guY29tcG9zaXRlQ29uZGl0aW9uLmV2YWx1YXRlKG5ldyBEYXRhRWxlbWVudFZhbHVlcyh0aGlzLmRhdGFFbGVtZW50VmFsdWVzKSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoYnJhbmNoLmNvbmRpdGlvbiAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgY29uZGl0aW9uTWV0ID0gYnJhbmNoLmNvbmRpdGlvbi5ldmFsdWF0ZShuZXcgRGF0YUVsZW1lbnRWYWx1ZXModGhpcy5kYXRhRWxlbWVudFZhbHVlcykpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoY29uZGl0aW9uTWV0KSB7XHJcbiAgICAgICAgdGhpcy5sYXN0Q29uZGl0aW9uTWV0QnJhbmNoTGV2ZWwgPSBicmFuY2hpbmdMZXZlbDtcclxuICAgICAgICBpZiAoYnJhbmNoLmRlY2lzaW9uUG9pbnRzICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgIGZvciAoY29uc3QgYnJhbmNoRGVjaXNpb25Qb2ludCBvZiBicmFuY2guZGVjaXNpb25Qb2ludHMpIHtcclxuICAgICAgICAgICAgY29uc3QgbmV3QnJhbmNoaW5nTGV2ZWwgPSBicmFuY2hpbmdMZXZlbCArIDE7XHJcbiAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVDb21wdXRlZEVsZW1lbnREZWNpc2lvblBvaW50KGVsZW1lbnRJZCwgYnJhbmNoRGVjaXNpb25Qb2ludCwgbmV3QnJhbmNoaW5nTGV2ZWwpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSBpZiAoYnJhbmNoLmNvbXB1dGVkVmFsdWUgIT09IHVuZGVmaW5lZCkge1xyXG5cclxuICAgICAgICAgIHRoaXMuZGF0YUVsZW1lbnRWYWx1ZXNbZWxlbWVudElkXSA9IGJyYW5jaC5jb21wdXRlZFZhbHVlLmV4cHJlc3Npb25UZXh0O1xyXG4gICAgICAgICAgdGhpcy5lbmRPZlJvYWRSZWFjaGVkID0gdHJ1ZTtcclxuICAgICAgICAgIGlmIChicmFuY2guY29tcHV0ZWRWYWx1ZSBpbnN0YW5jZW9mIEFyaXRobWV0aWNFeHByZXNzaW9uKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZGF0YUVsZW1lbnRWYWx1ZXNbZWxlbWVudElkXSA9IHRoaXMuZXZhbHVhdGVBcml0aG1ldGljRXhwcmVzc2lvbihicmFuY2guY29tcHV0ZWRWYWx1ZS5leHByZXNzaW9uVGV4dCk7XHJcbiAgICAgICAgICAgIHRoaXMuZW5kT2ZSb2FkUmVhY2hlZCA9IHRydWU7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmRhdGFFbGVtZW50VmFsdWVzW2VsZW1lbnRJZF0gPSBicmFuY2guY29tcHV0ZWRWYWx1ZS5leHByZXNzaW9uVGV4dDtcclxuICAgICAgICAgICAgdGhpcy5lbmRPZlJvYWRSZWFjaGVkID0gdHJ1ZTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKGN1cnJlbnRCcmFuY2hDb3VudCA+PSB0b3RhbEJyYW5jaGVzSW5EZWNpc2lvblBvaW50KSB7XHJcbiAgICAgICAgICB0aGlzLmVuZE9mUm9hZFJlYWNoZWQgPSB0cnVlO1xyXG4gICAgICAgICAgdGhpcy5kYXRhRWxlbWVudFZhbHVlc1tlbGVtZW50SWRdID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZXZhbHVhdGVBcml0aG1ldGljRXhwcmVzc2lvbihjb21wdXRlZFZhbHVlOiBzdHJpbmcpOiBhbnkge1xyXG4gICAgbGV0IHN0YXJ0SW5kZXggPSAwO1xyXG4gICAgbGV0IGVuZEluZGV4ID0gMDtcclxuICAgIHdoaWxlIChzdGFydEluZGV4ICE9PSAtMSAmJiBlbmRJbmRleCAhPT0gLTEpIHtcclxuICAgICAgc3RhcnRJbmRleCA9IGNvbXB1dGVkVmFsdWUuaW5kZXhPZigneycpO1xyXG4gICAgICBlbmRJbmRleCA9IGNvbXB1dGVkVmFsdWUuaW5kZXhPZignfScpO1xyXG4gICAgICBpZiAoc3RhcnRJbmRleCAhPT0gLTEgJiYgZW5kSW5kZXggIT09IC0xKSB7XHJcbiAgICAgICAgY29uc3QgZGF0YUVsZW1lbnRJZCA9IGNvbXB1dGVkVmFsdWUuc3Vic3RyaW5nKHN0YXJ0SW5kZXggKyAxLCBlbmRJbmRleCk7XHJcbiAgICAgICAgY29uc3QgcmVwbGFjaW5nVmFsdWUgPSBjb21wdXRlZFZhbHVlLnN1YnN0cmluZyhzdGFydEluZGV4LCBlbmRJbmRleCArIDEpO1xyXG4gICAgICAgIGxldCBkYXRhRWxlbWVudFZhbHVlID0gdGhpcy5kYXRhRWxlbWVudFZhbHVlc1tkYXRhRWxlbWVudElkXTtcclxuICAgICAgICBpZiAoaXNBcnJheShkYXRhRWxlbWVudFZhbHVlKSkge1xyXG4gICAgICAgICAgbGV0IHN1bSA9IDA7XHJcbiAgICAgICAgICBkYXRhRWxlbWVudFZhbHVlLmZvckVhY2godmFsID0+IHtcclxuICAgICAgICAgICAgc3VtICs9ICt2YWw7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIGRhdGFFbGVtZW50VmFsdWUgPSBzdW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb21wdXRlZFZhbHVlID0gY29tcHV0ZWRWYWx1ZS5yZXBsYWNlKHJlcGxhY2luZ1ZhbHVlLCBkYXRhRWxlbWVudFZhbHVlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBleHByZXNzaW9uUGFyc2VyLmV2YWx1YXRlKGNvbXB1dGVkVmFsdWUpLnRvU3RyaW5nKCk7XHJcbiAgfVxyXG5cclxuXHJcbiAgcHJpdmF0ZSBldmFsdWF0ZUNvbXB1dGVkRXhwcmVzc2lvbnMoKSB7XHJcbiAgICB0aGlzLmVuZE9mUm9hZFJlYWNoZWQgPSBmYWxzZTtcclxuICAgIGxldCBleHByZXNzaW9uVmFsdWU6IGFueTtcclxuICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLnRlbXBsYXRlLmRhdGFFbGVtZW50cykge1xyXG4gICAgICBpZiAoZWxlbWVudC5kYXRhRWxlbWVudFR5cGUgPT09ICdDb21wdXRlZERhdGFFbGVtZW50Jykge1xyXG4gICAgICAgIGV4cHJlc3Npb25WYWx1ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICBjb25zdCBjb21wdXRlZEVsZW1lbnQ6IENvbXB1dGVkRGF0YUVsZW1lbnQgPSBlbGVtZW50IGFzIENvbXB1dGVkRGF0YUVsZW1lbnQ7XHJcbiAgICAgICAgZm9yIChjb25zdCBkZWNpc2lvblBvaW50IG9mIGNvbXB1dGVkRWxlbWVudC5kZWNpc2lvblBvaW50cykge1xyXG4gICAgICAgICAgdGhpcy5ldmFsdWF0ZUNvbXB1dGVkRWxlbWVudERlY2lzaW9uUG9pbnQoZWxlbWVudC5pZCwgZGVjaXNpb25Qb2ludCwgMSk7XHJcbiAgICAgICAgICBpZiAodGhpcy5kYXRhRWxlbWVudFZhbHVlc1tlbGVtZW50LmlkXSA9PT0gdW5kZWZpbmVkICYmIGRlY2lzaW9uUG9pbnQuZGVmYXVsdEJyYW5jaCAmJlxyXG4gICAgICAgICAgICBkZWNpc2lvblBvaW50LmRlZmF1bHRCcmFuY2guY29tcHV0ZWRWYWx1ZSkge1xyXG4gICAgICAgICAgICB0aGlzLmRhdGFFbGVtZW50VmFsdWVzW2VsZW1lbnQuaWRdID0gZGVjaXNpb25Qb2ludC5kZWZhdWx0QnJhbmNoLmNvbXB1dGVkVmFsdWUuZXhwcmVzc2lvblRleHQ7XHJcbiAgICAgICAgIC