src/rule.js
import { Criteria } from './criteria.js';
import { Behavior } from './behavior.js';
export class Rule {
constructor(name, criteria, criteriaMustSatisfy, behaviors, children, skipBehaviors, valueMap, depth) {
this.name = name;
this.criteria = criteria;
this.criteriaMustSatisfy = criteriaMustSatisfy;
this.behaviors = behaviors;
this.children = children;
this.skipBehaviors = skipBehaviors;
this.valueMap = valueMap;
this.depth = depth;
}
process() {
let result = '\n' + this.pad(this.depth) + '-- ' + this.name + ' rule ####';
let criteriaNames = this.criteriaNames(this.criteria) ? this.criteriaNames(this.criteria) : 'none';
result += '\n' + this.pad(this.depth) + '-- criteria: ' + criteriaNames;
if (this.criteriaNamesNotRegistered(this.criteria) !== '') {
console.error('Criteria not registered: ' + this.criteriaNamesNotRegistered(this.criteria));
}
if (this.anyCriteriaForRuleRegistered(this.criteria)) {
result += '\n' + this.pad(this.depth) + 'if ' + this.processCriteria(this.criteria, this.valueMap) + ' then';
}
if (this.behaviors && typeof this.behaviors !== 'undefined' && this.behaviors.length > 0) {
result += this.pad(this.depth + 1) +
this.processBehaviors(this.behaviors, this.valueMap, this.skipBehaviors) + '\n';
}
let that = this;
this.children.forEach(function (childRule) {
let rule = new Rule(
childRule.name,
childRule.criteria,
childRule.criteriaMustSatisfy,
childRule.behaviors,
childRule.children,
that.skipBehaviors,
that.valueMap,
that.depth + 1
);
result += rule.process();
});
if (this.anyCriteriaForRuleRegistered(this.criteria)) {
result += this.pad(this.depth) + 'end\n';
}
return result;
}
anyCriteriaForRuleRegistered(criteria) {
if (!criteria) return false;
let anyCriteriaRegistered = false;
criteria.forEach((criteria) => {
if (Criteria.isRegistered(criteria.name)) {
anyCriteriaRegistered = true;
}
});
return anyCriteriaRegistered;
}
criteriaNames(criteria) {
if (!criteria) return '';
let criteriaNameArray = [];
criteria.forEach((criteria) => {
criteriaNameArray.push(criteria.name);
});
return '(' + criteriaNameArray.join(this.criteriaJoiner()) + ')';
}
criteriaNamesNotRegistered(criteria) {
if (!criteria) return '';
let criteriaNameArray = [];
criteria.forEach((criteria) => {
if (!Criteria.isRegistered(criteria.name)) {
criteriaNameArray.push(criteria.name);
}
});
return criteriaNameArray.join(', ');
}
processCriteria(criteria, valueMap) {
if (!criteria) return null;
let criteriaArray = [];
criteria.forEach((criteria) => {
if (Criteria.isRegistered(criteria.name)) {
let item = new Criteria(criteria.name, criteria.options, valueMap);
criteriaArray.push(item.process());
}
});
return '(' + criteriaArray.join(this.criteriaJoiner()) + ')';
}
processBehaviors(behaviors, valueMap, skipBehaviors) {
if (!behaviors) return null;
let behaviorArray = [];
behaviors.forEach((behavior) => {
let item = new Behavior(behavior.name, behavior.options, valueMap);
if (skipBehaviors.includes(behavior.name)) {
behaviorArray.push('-- ' + behavior.name + ' behavior (skipped)');
} else {
behaviorArray.push('-- ' + behavior.name + ' behavior');
let behaviourResult = item.process();
if (behaviourResult) {
if (Array.isArray(behaviourResult)) {
behaviorArray = [...behaviorArray, ...behaviourResult];
} else {
behaviorArray.push(behaviourResult);
}
}
}
});
return '\n' + this.pad(this.depth+1) + behaviorArray.join('\n' + this.pad(this.depth+1));
}
criteriaJoiner() {
let joiner = ') and (';
switch (this.criteriaMustSatisfy) {
case 'all':
joiner = ') and (';
break;
case 'any':
joiner = ') or (';
break;
}
return joiner;
}
pad(count) {
if (!count || count <0) {count=0;}
return (new Array(count + 1)).join('\t');
}
}