├── .gitignore ├── .vs └── dmn │ └── v16 │ └── .suo ├── API.d.ts ├── API.js ├── API.js.map ├── API.ts ├── Addins.js ├── Addins.js.map ├── DecisionTable.d.ts ├── DecisionTable.js ├── DecisionTable.js.map ├── DecisionTable.ts ├── Expression.d.ts ├── Expression.js ├── Expression.js.map ├── Expression.ts ├── LICENSE ├── README.md ├── Rule.d.ts ├── Rule.js ├── Rule.js.map ├── Rule.ts ├── Tester.js ├── Tester.js.map ├── Tester1.js ├── Tester1.js.map ├── Tester2.js ├── Tester2.js.map ├── app.js ├── bundle.js ├── common.d.ts ├── common.js ├── common.js.map ├── common.ts ├── credentials.json ├── docs ├── DMN_client_category_table.jpg ├── anatomyofdt.png ├── dt-and-tests.png └── lifeInsuracne.png ├── google.d.ts ├── google.js ├── google.js.map ├── google.ts ├── index.d.ts ├── index.html ├── index.js ├── index.js.map ├── index.ts ├── package-lock.json ├── package.json ├── process.js ├── table.dmn ├── test.js ├── test.js.map ├── test.txt.errors.json ├── test.txt.json ├── test.txterrors.json ├── testDT.d.ts ├── testDT.js ├── testDT.js.map ├── testDT.ts ├── testGoogle.d.ts ├── testGoogle.js ├── testGoogle.js.map ├── testGoogle.ts ├── testcalc ├── tests ├── Condition-Numbers.bak ├── Condition-Numbers.txt.json ├── Condition-Strings.txt.json ├── Expressions.txt.json ├── Expressions2.txt.json ├── Vacation.json ├── debug.txt.json ├── parsing.bak ├── parsing.txt.json ├── test.bak └── test.txt.json ├── testsVacation.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /obj 3 | *.log 4 | *.cmd 5 | *.sln 6 | *.njsproj 7 | *.njsproj.user 8 | *.txt 9 | *.txt.errors 10 | /bin 11 | /'.vs' 12 | /jison 13 | token.json -------------------------------------------------------------------------------- /.vs/dmn/v16/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralphhanna/dmn-engine/2484626411fdbbf8f889b42f9ad57a389d229033/.vs/dmn/v16/.suo -------------------------------------------------------------------------------- /API.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /API.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const Expression_1 = require("./Expression"); 4 | const DecisionTable_1 = require("./DecisionTable"); 5 | api(); 6 | function api() { 7 | const context = { name: 'John', job: 'Analyst', salary: 50000 }; 8 | let exprResult, condResult, ruleOutput, dtOutput; 9 | const expr = new Expression_1.Expression(`salary* 1.05`); 10 | console.log(expr.evaluate(context)); 11 | const cond = new Expression_1.Condition(`>40000`, 'salary'); 12 | console.log(cond.evaluate(context)); 13 | const decisionTable = new DecisionTable_1.DecisionTable({ 14 | name: 'Raise', 15 | conditionVars: [ 16 | // ['name','string'], 17 | ['job', 'string'], 18 | ['salary', 'money'] 19 | ], 20 | actionVars: [ 21 | ['raise', 'money'] 22 | ], 23 | rules: [ 24 | [1, '-', `>40000`, `salary *1.05`], 25 | [2, '-', `>30000`, `salary *1.1`] 26 | ], 27 | hitPolicy: DecisionTable_1.HIT_POLICY.Unique 28 | }); 29 | dtOutput = decisionTable.evaluate(context); 30 | console.log(dtOutput); 31 | } 32 | /* */ 33 | //# sourceMappingURL=API.js.map -------------------------------------------------------------------------------- /API.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"API.js","sourceRoot":"","sources":["API.ts"],"names":[],"mappings":";;AAAA,6CAAsD;AACtD,mDAA4D;AAE5D,GAAG,EAAE,CAAC;AACN,SAAS,GAAG;IAEX,MAAM,OAAO,GAAG,EAAE,IAAI,EAAC,MAAM,EAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAC,CAAC;IAE7D,IAAI,UAAU,EAAC,UAAU,EAAC,UAAU,EAAE,QAAQ,CAAC;IAE/C,MAAM,IAAI,GAAC,IAAI,uBAAU,CAAC,cAAc,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAGpC,MAAM,IAAI,GAAC,IAAI,sBAAS,CAAC,QAAQ,EAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAGpC,MAAM,aAAa,GAAG,IAAI,6BAAa,CACtC;QACC,IAAI,EAAE,OAAO;QACf,aAAa,EAAC;YACf,uBAAuB;YACpB,CAAC,KAAK,EAAC,QAAQ,CAAC;YAChB,CAAC,QAAQ,EAAC,OAAO,CAAC;SAChB;QACJ,UAAU,EAAE;YACV,CAAC,OAAO,EAAC,OAAO,CAAC;SAChB;QACH,KAAK,EAAE;YACL,CAAC,CAAC,EAAC,GAAG,EAAC,QAAQ,EAAC,cAAc,CAAC;YAC/B,CAAC,CAAC,EAAC,GAAG,EAAC,QAAQ,EAAC,aAAa,CAAC;SAC7B;QACH,SAAS,EAAE,0BAAU,CAAC,MAAM;KAAC,CAAC,CAAC;IAE/B,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC;AAGD,KAAK"} -------------------------------------------------------------------------------- /API.ts: -------------------------------------------------------------------------------- 1 | import { Expression , Condition } from "./Expression"; 2 | import { DecisionTable, HIT_POLICY } from "./DecisionTable"; 3 | 4 | api(); 5 | function api() { 6 | 7 | const context = { name:'John',job: 'Analyst', salary: 50000}; 8 | 9 | let exprResult,condResult,ruleOutput, dtOutput; 10 | 11 | const expr=new Expression(`salary* 1.05`); 12 | console.log(expr.evaluate(context)); 13 | 14 | 15 | const cond=new Condition(`>40000`,'salary'); 16 | console.log(cond.evaluate(context)); 17 | 18 | 19 | const decisionTable = new DecisionTable( 20 | { 21 | name: 'Raise', 22 | conditionVars:[ 23 | // ['name','string'], 24 | ['job','string'], 25 | ['salary','money'] 26 | ], 27 | actionVars: [ 28 | ['raise','money'] 29 | ], 30 | rules: [ 31 | [1,'-',`>40000`,`salary *1.05`], 32 | [2,'-',`>30000`,`salary *1.1`] 33 | ], 34 | hitPolicy: HIT_POLICY.Unique}); 35 | 36 | dtOutput = decisionTable.evaluate(context); 37 | 38 | console.log(dtOutput); 39 | } 40 | 41 | 42 | /* */ -------------------------------------------------------------------------------- /Addins.js: -------------------------------------------------------------------------------- 1 | //# sourceMappingURL=Addins.js.map -------------------------------------------------------------------------------- /Addins.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Addins.js","sourceRoot":"","sources":["Addins.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /DecisionTable.d.ts: -------------------------------------------------------------------------------- 1 | import { Rule } from "./Rule"; 2 | export declare enum HIT_POLICY { 3 | Unique = "Unique", 4 | Any = "Any", 5 | First = "First", 6 | RuleOrder = "Order", 7 | Collect = "Collect+" 8 | } 9 | export declare class DTOutput { 10 | input: {}; 11 | rules: any[]; 12 | successCount: number; 13 | actions: {}; 14 | } 15 | export declare class DTVariable { 16 | name: any; 17 | type: 'String' | 'Number' | 'Money' | 'Date'; 18 | } 19 | export declare class DecisionTable { 20 | name: any; 21 | conditionVars: DTVariable[]; 22 | actionVars: DTVariable[]; 23 | rules: Rule[]; 24 | hitPolicy: HIT_POLICY; 25 | private processAll; 26 | constructor({ name, conditionVars, actionVars, rules, hitPolicy }: { 27 | name: any; 28 | conditionVars: any; 29 | actionVars: any; 30 | rules: any; 31 | hitPolicy: any; 32 | }); 33 | /** 34 | * Execute a DT on the fly, passing multiple records 35 | * used for WebAPI 36 | * @param dtDefinition 37 | * @param data 38 | */ 39 | static execute(dtDefinition: any, data: any): Promise<{ 40 | decisionTable: DecisionTable; 41 | results: any[]; 42 | }>; 43 | compile(): { 44 | rules: any[]; 45 | }; 46 | evaluate(data: any): Promise; 47 | private processResults; 48 | save(fileName: any): void; 49 | static load(fileName: any): DecisionTable; 50 | asJson(): string; 51 | } 52 | -------------------------------------------------------------------------------- /DecisionTable.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.DecisionTable = exports.DTVariable = exports.DTOutput = exports.HIT_POLICY = void 0; 13 | const Rule_1 = require("./Rule"); 14 | const fs = require('fs'); 15 | var HIT_POLICY; 16 | (function (HIT_POLICY) { 17 | HIT_POLICY["Unique"] = "Unique"; 18 | HIT_POLICY["Any"] = "Any"; 19 | HIT_POLICY["First"] = "First"; 20 | HIT_POLICY["RuleOrder"] = "Order"; 21 | HIT_POLICY["Collect"] = "Collect+"; 22 | })(HIT_POLICY = exports.HIT_POLICY || (exports.HIT_POLICY = {})); 23 | class DTOutput { 24 | constructor() { 25 | this.input = {}; 26 | this.rules = []; 27 | this.successCount = 0; 28 | this.actions = {}; 29 | } 30 | } 31 | exports.DTOutput = DTOutput; 32 | class DTVariable { 33 | } 34 | exports.DTVariable = DTVariable; 35 | class DecisionTable { 36 | constructor({ name, conditionVars, actionVars, rules, hitPolicy }) { 37 | this.name = name; 38 | const condCount = conditionVars.length; 39 | const actioCount = actionVars.length; 40 | this.conditionVars = conditionVars; 41 | this.actionVars = actionVars; 42 | this.hitPolicy = hitPolicy; 43 | let id = 1; 44 | this.rules = []; 45 | rules.forEach(rule => { 46 | this.rules.push(new Rule_1.Rule(rule[0], rule.slice(1, condCount + 1), rule.slice(condCount + 1), conditionVars, actionVars)); 47 | }); 48 | } 49 | processAll() { 50 | if (this.hitPolicy == 'Collect+') 51 | return true; 52 | else 53 | return false; 54 | } 55 | /** 56 | * Execute a DT on the fly, passing multiple records 57 | * used for WebAPI 58 | * @param dtDefinition 59 | * @param data 60 | */ 61 | static execute(dtDefinition, data) { 62 | return __awaiter(this, void 0, void 0, function* () { 63 | const dt = new DecisionTable(dtDefinition); 64 | const response = []; 65 | let i; 66 | for (i = 0; i < data.length; i++) { 67 | const record = data[i]; 68 | response.push(yield dt.evaluate(record)); 69 | } 70 | return { decisionTable: dt, results: response }; 71 | }); 72 | } 73 | compile() { 74 | const image = { rules: [] }; 75 | this.rules.forEach(rule => { 76 | image.rules.push(rule.compile()); 77 | }); 78 | return image; 79 | } 80 | evaluate(data) { 81 | return __awaiter(this, void 0, void 0, function* () { 82 | const output = new DTOutput(); //= { _results: [], _success: 0 }; 83 | var r = 0; 84 | output.input = data; 85 | const rules = this.rules; 86 | let ret; 87 | for (r = 0; r < rules.length; r++) { 88 | let rule = rules[r]; 89 | const result = { ruleId: rule.id }; 90 | ret = yield rule.evaluate(data, result); 91 | if (ret) { 92 | // console.log(" Rule #" + rule.id + " has returned"); 93 | output.successCount++; 94 | output.rules.push(result); 95 | if (!this.processAll) 96 | break; 97 | } 98 | else { 99 | // console.log(" Rule #" + rule.id + " has failed on " + result['failedCondition'] +" condition"); 100 | output.rules.push(result); 101 | } 102 | } 103 | //console.log(results); 104 | return yield this.processResults(output); 105 | //console.log("**No Rule has returned**"); 106 | }); 107 | } 108 | processResults(output) { 109 | let operation = (this.hitPolicy == 'Collect+') ? '+' : ''; 110 | let i; 111 | for (i = 0; i < output.rules.length; i++) { 112 | const result = output.rules[i]; 113 | if (result.output) { 114 | // console.log("output:"); 115 | // console.log(result.output) 116 | this.actionVars.forEach(action => { 117 | switch (operation) { 118 | case '': 119 | output.actions[action.name] = result.output[action.name]; 120 | break; 121 | case '+': 122 | if (output.actions[action.name]) 123 | output.actions[action.name] += result.output[action.name]; 124 | else 125 | output.actions[action.name] = result.output[action.name]; 126 | break; 127 | } 128 | }); 129 | if (!this.processAll) { 130 | return output; 131 | } 132 | } 133 | } 134 | // console.log(output); 135 | return output; 136 | } 137 | save(fileName) { 138 | fs.writeFileSync(fileName, this.asJson(), function (err) { }); 139 | } 140 | static load(fileName) { 141 | const json = fs.readFileSync(fileName, { encoding: 'utf8', flag: 'r' }); 142 | // console.log(json); 143 | return new DecisionTable(JSON.parse(json)); 144 | } 145 | asJson() { 146 | const rules = []; 147 | this.rules.forEach(rule => { 148 | // console.log(rule.asJson()); 149 | rules.push(rule.asJson()); 150 | }); 151 | const obj = { 152 | name: this.name, 153 | hitPolicy: this.hitPolicy, 154 | conditionVars: this.conditionVars, 155 | actionVars: this.actionVars, 156 | rules: rules 157 | }; 158 | // console.log(obj); 159 | return JSON.stringify(obj, null, 2); 160 | } 161 | } 162 | exports.DecisionTable = DecisionTable; 163 | function trimParam(param) { 164 | if (param.startsWith('"') && param.endsWith('"')) 165 | return param.substring(1, param.length - 1); 166 | if (param.startsWith("'") && param.endsWith("'")) 167 | return param.substring(1, param.length - 1); 168 | else 169 | return param.trim(); 170 | } 171 | //# sourceMappingURL=DecisionTable.js.map -------------------------------------------------------------------------------- /DecisionTable.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"DecisionTable.js","sourceRoot":"","sources":["DecisionTable.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /DecisionTable.ts: -------------------------------------------------------------------------------- 1 | import { Rule } from "./Rule"; 2 | const fs = require('fs'); 3 | 4 | export enum HIT_POLICY { 5 | Unique = 'Unique', 6 | Any = 'Any', 7 | First = 'First', 8 | RuleOrder = 'Order', 9 | Collect = 'Collect+' 10 | } 11 | export class DTOutput { 12 | input = {}; 13 | rules=[]; 14 | successCount = 0; 15 | actions = {}; 16 | 17 | } 18 | export class DTVariable { 19 | name; 20 | type: 'String'|'Number'|'Money'|'Date'; 21 | } 22 | export class DecisionTable { 23 | name; 24 | conditionVars: DTVariable[]; 25 | actionVars: DTVariable[]; 26 | rules: Rule[]; 27 | hitPolicy: HIT_POLICY; 28 | private processAll() { 29 | 30 | if (this.hitPolicy == 'Collect+') 31 | return true; 32 | else 33 | return false; 34 | 35 | } 36 | 37 | constructor({ name, conditionVars, actionVars , rules, hitPolicy }) { 38 | 39 | this.name = name; 40 | const condCount = conditionVars.length; 41 | const actioCount = actionVars.length 42 | this.conditionVars = conditionVars; 43 | this.actionVars = actionVars; 44 | this.hitPolicy = hitPolicy; 45 | 46 | let id = 1; 47 | this.rules = []; 48 | rules.forEach(rule => { 49 | this.rules.push(new Rule(rule[0], rule.slice(1,condCount+1),rule.slice(condCount+1),conditionVars,actionVars)); 50 | }); 51 | } 52 | /** 53 | * Execute a DT on the fly, passing multiple records 54 | * used for WebAPI 55 | * @param dtDefinition 56 | * @param data 57 | */ 58 | static async execute(dtDefinition, data) { 59 | const dt = new DecisionTable(dtDefinition); 60 | const response = []; 61 | let i; 62 | for (i = 0; i < data.length; i++) { 63 | const record = data[i]; 64 | response.push(await dt.evaluate(record)); 65 | } 66 | return { decisionTable: dt, results: response }; 67 | } 68 | compile() { 69 | const image = { rules: [] }; 70 | this.rules.forEach(rule => { 71 | image.rules.push(rule.compile()); 72 | }); 73 | return image; 74 | } 75 | async evaluate(data) { 76 | const output = new DTOutput(); //= { _results: [], _success: 0 }; 77 | var r = 0; 78 | output.input = data; 79 | const rules = this.rules; 80 | let ret; 81 | for (r = 0; r < rules.length; r++) { 82 | let rule = rules[r]; 83 | const result = { ruleId: rule.id }; 84 | ret = await rule.evaluate(data, result); 85 | if (ret) { 86 | // console.log(" Rule #" + rule.id + " has returned"); 87 | output.successCount++; 88 | output.rules.push(result); 89 | if (!this.processAll) 90 | break; 91 | } 92 | else { 93 | // console.log(" Rule #" + rule.id + " has failed on " + result['failedCondition'] +" condition"); 94 | output.rules.push(result); 95 | } 96 | } 97 | //console.log(results); 98 | return await this.processResults(output); 99 | //console.log("**No Rule has returned**"); 100 | 101 | } 102 | private processResults(output) { 103 | let operation = (this.hitPolicy == 'Collect+') ? '+' : ''; 104 | let i; 105 | for (i = 0; i < output.rules.length; i++) { 106 | const result = output.rules[i]; 107 | if (result.output) { 108 | // console.log("output:"); 109 | // console.log(result.output) 110 | 111 | this.actionVars.forEach(action => { 112 | switch (operation) { 113 | case '': 114 | output.actions[action.name] = result.output[action.name]; 115 | break; 116 | case '+': 117 | if (output.actions[action.name]) 118 | output.actions[action.name] += result.output[action.name]; 119 | else 120 | output.actions[action.name] = result.output[action.name]; 121 | 122 | break; 123 | } 124 | }); 125 | if (!this.processAll) { 126 | return output; 127 | } 128 | } 129 | 130 | } 131 | // console.log(output); 132 | return output; 133 | } 134 | save(fileName) { 135 | fs.writeFileSync(fileName, this.asJson(), function (err) { }); 136 | 137 | } 138 | static load(fileName) { 139 | const json= fs.readFileSync(fileName, 140 | { encoding: 'utf8', flag: 'r' }); 141 | 142 | // console.log(json); 143 | return new DecisionTable(JSON.parse(json)); 144 | 145 | } 146 | asJson() { 147 | const rules=[]; 148 | this.rules.forEach(rule => { 149 | // console.log(rule.asJson()); 150 | rules.push(rule.asJson()); 151 | }); 152 | const obj = { 153 | name: this.name, 154 | hitPolicy: this.hitPolicy, 155 | conditionVars: this.conditionVars, 156 | actionVars: this.actionVars, 157 | rules: rules 158 | }; 159 | // console.log(obj); 160 | return JSON.stringify(obj, null, 2); 161 | } 162 | } 163 | 164 | function trimParam(param) { 165 | if (param.startsWith('"') && param.endsWith('"')) 166 | return param.substring(1, param.length - 1); 167 | if (param.startsWith("'") && param.endsWith("'")) 168 | return param.substring(1, param.length - 1); 169 | else 170 | return param.trim(); 171 | } 172 | -------------------------------------------------------------------------------- /Expression.d.ts: -------------------------------------------------------------------------------- 1 | export declare class Expression { 2 | script: any; 3 | ast: any; 4 | constructor(script: any); 5 | get isCondition(): Boolean; 6 | static load(json: any): Expression; 7 | compile(): Promise; 8 | getState(): this; 9 | display(): void; 10 | evaluate(data: any): Promise; 11 | } 12 | export declare class Condition extends Expression { 13 | get isCondition(): Boolean; 14 | variableName: any; 15 | constructor(script: any, variableName: any); 16 | compile(): Promise; 17 | evaluate(data: any): Promise; 18 | } 19 | -------------------------------------------------------------------------------- /Expression.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.Condition = exports.Expression = void 0; 13 | const feel = require('js-feel/dist/feel'); 14 | const FEEL = feel; 15 | class Expression { 16 | constructor(script) { 17 | this.script = script; 18 | } 19 | get isCondition() { return false; } 20 | static load(json) { 21 | const inst = new Expression(json); 22 | return inst; 23 | } 24 | compile() { 25 | return __awaiter(this, void 0, void 0, function* () { 26 | this.ast = yield parse(this.script); 27 | // this.ast = parser.compile(this.script, this.isCondition); 28 | }); 29 | } 30 | getState() { 31 | return this; 32 | } 33 | display() { 34 | // this.rootNode.displayExpression(); 35 | } 36 | evaluate(data) { 37 | return __awaiter(this, void 0, void 0, function* () { 38 | if (!this.ast) 39 | yield this.compile(); 40 | if (this.ast) { 41 | const result = yield this.ast.build(data); 42 | return result; 43 | } 44 | return null; 45 | // const executor = new Executor(data); 46 | //return executor.evaluateCondition(this.rootNode, null, false); 47 | }); 48 | } 49 | } 50 | exports.Expression = Expression; 51 | function parse(script, options = {}) { 52 | return __awaiter(this, void 0, void 0, function* () { 53 | try { 54 | const ast = yield FEEL.parse(script, options); 55 | return ast; 56 | } 57 | catch (exc) { 58 | console.log("Error in parsing " + script); 59 | console.log(exc.message); 60 | return null; 61 | } 62 | }); 63 | } 64 | class Condition extends Expression { 65 | constructor(script, variableName) { 66 | super(script); 67 | this.variableName = variableName; 68 | } 69 | get isCondition() { return true; } 70 | compile() { 71 | return __awaiter(this, void 0, void 0, function* () { 72 | this.ast = yield parse(this.script, { startRule: 'SimpleUnaryTests' }); 73 | // this.ast = parser.compile(this.script, this.isCondition); 74 | }); 75 | } 76 | /* 77 | const condition = await feel.parse(conditionScript, { startRule: 'SimpleUnaryTests' }); 78 | const funct = await condition.build(context, {}, 'input'); 79 | const out = funct(inputValue); 80 | */ 81 | evaluate(data) { 82 | return __awaiter(this, void 0, void 0, function* () { 83 | let value, funct, out; 84 | if (!this.ast) 85 | yield this.compile(); 86 | if (!this.ast) 87 | return null; 88 | try { 89 | funct = yield this.ast.build(data, {}, 'input'); 90 | value = getValue(data[this.variableName]); 91 | out = funct(value); 92 | return out; 93 | } 94 | catch (exc) { 95 | console.log(`Error in evaluating '${this.script}' for value: '${value}'`); 96 | console.log(`--- generated function '${funct.toString()}'`); 97 | console.log(data); 98 | console.log(exc.message); 99 | return out; 100 | } 101 | //return executor.evaluateCondition(this.rootNode, value, true); 102 | }); 103 | } 104 | } 105 | exports.Condition = Condition; 106 | function getValue(value) { 107 | let val = parseFloat(value); 108 | if (!isNaN(val)) 109 | return val; 110 | else 111 | return value; 112 | } 113 | //# sourceMappingURL=Expression.js.map -------------------------------------------------------------------------------- /Expression.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Expression.js","sourceRoot":"","sources":["Expression.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /Expression.ts: -------------------------------------------------------------------------------- 1 | const feel = require('js-feel/dist/feel'); 2 | 3 | 4 | const FEEL = feel; 5 | 6 | export class Expression { 7 | script; 8 | ast; // ExpressionNode; 9 | constructor(script) { 10 | this.script = script; 11 | } 12 | get isCondition(): Boolean { return false; } 13 | 14 | static load(json): Expression { 15 | const inst = new Expression(json); 16 | return inst; 17 | 18 | } 19 | async compile() { 20 | 21 | this.ast = await parse(this.script); 22 | 23 | // this.ast = parser.compile(this.script, this.isCondition); 24 | } 25 | getState() { 26 | return this; 27 | } 28 | display() { 29 | // this.rootNode.displayExpression(); 30 | } 31 | async evaluate(data) { 32 | if (!this.ast) 33 | await this.compile(); 34 | if (this.ast) { 35 | const result = await this.ast.build(data); 36 | return result; 37 | } 38 | return null; 39 | // const executor = new Executor(data); 40 | //return executor.evaluateCondition(this.rootNode, null, false); 41 | } 42 | } 43 | async function parse(script, options = {}) { 44 | 45 | try { 46 | const ast = await FEEL.parse(script, options); 47 | return ast; 48 | } 49 | catch (exc) { 50 | console.log("Error in parsing " + script); 51 | console.log(exc.message); 52 | return null; 53 | } 54 | 55 | } 56 | export class Condition extends Expression { 57 | get isCondition(): Boolean { return true; } 58 | variableName; 59 | 60 | constructor(script, variableName) { 61 | super(script); 62 | this.variableName = variableName; 63 | } 64 | async compile() { 65 | 66 | this.ast = await parse(this.script, { startRule: 'SimpleUnaryTests' }); 67 | // this.ast = parser.compile(this.script, this.isCondition); 68 | } 69 | /* 70 | const condition = await feel.parse(conditionScript, { startRule: 'SimpleUnaryTests' }); 71 | const funct = await condition.build(context, {}, 'input'); 72 | const out = funct(inputValue); 73 | */ 74 | async evaluate(data) { 75 | 76 | let value, funct, out; 77 | if (!this.ast) 78 | await this.compile(); 79 | 80 | if (!this.ast) 81 | return null; 82 | 83 | try { 84 | funct = await this.ast.build(data, {}, 'input'); 85 | value = getValue(data[this.variableName]); 86 | out = funct(value); 87 | return out; 88 | } 89 | catch (exc) { 90 | console.log(`Error in evaluating '${this.script}' for value: '${value}'`); 91 | console.log(`--- generated function '${funct.toString()}'`); 92 | console.log(data); 93 | console.log(exc.message); 94 | return out; 95 | } 96 | //return executor.evaluateCondition(this.rootNode, value, true); 97 | } 98 | } 99 | function getValue(value) { 100 | let val = parseFloat(value); 101 | if (!isNaN(val)) 102 | return val; 103 | else 104 | return value; 105 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 ralphhanna 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Business-Rules Engine 2 | =========== 3 | 4 | ## Condition Symbols 5 | 6 | - Column Value: `$$` example DateDiff($$,@now) 7 | - variable symbol: `$`example: `$caseId` this is needed since we allow multi words operations like `starts with` 8 | - Is null value or empty: `Null` or `Empty` 9 | - Any Value: `-` 10 | 11 | - All types: 12 | - `null` or `empty` 13 | - `not null` 14 | - `true` or `false` 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
Type SyntaxExamples
Numbersvalue500
compare operator>500
<500
between 500 and 700
StringvalueLow-Income
Quoted Value'Low-Income'
string operatorsstarts with 'Low'
ends with 'Income'
contains 'Income'
not 'Low-Income'
DateQuoted value'2020/12/01'
Date operatorsafter '2020/12/01'
>30 days
<10 years
contains 'Income'
not 'Low-Income'
40 | 41 | [![Project Status: Active - The project has reached a stable, usable state and is being actively developed.](http://www.repostatus.org/badges/latest/active.svg)](http://www.repostatus.org/#active) 42 | 43 | ## Introduction 44 | Is a Business Rules Engine supporting DMN Decision Tables. 45 | Allowing developers to integrate Rules into JavaScript or Node.js applications. 46 | 47 | This solution utilizes deterministic rules vs Rete based solutions that are non-deterministic. 48 | 49 | This package is designed specifically for Node.js and TypeScript 50 | 51 | As an example of Decisition Table 52 | ![Example](./docs/DMN_client_category_table.jpg) 53 | 54 | ![Anatomy](./docs/anatomyofdt.png) 55 | 56 | ## Usage 57 | ### Definition 58 | 59 | Decision table can be defined as a JSON or CSV file 60 | ### Invoke 61 | To invoke the above example 62 | ```js 63 | const Rules=requires('./business-rules.json')' 64 | const dt= Rules.load('client-category); 65 | let result=dt.run({type:'Private', deposit: 500 , netWorth: 500}); 66 | 67 | console.log(result.category); 68 | ``` 69 | ### Testing 70 | ```js 71 | const tester=Rules.loadTest('./client-category-tests.json'); 72 | let results=tester.run(); 73 | console.log(results.summary); 74 | ``` 75 | ![tests](./docs/dt-and-tests.png) 76 | ### UI for Testing and expeirmenting 77 | 78 | 79 | ## Rule Syntax 80 | 81 | ### Conditions 82 | #### Expression Language 83 | 84 | #### Simple Conditions shortcuts 85 | 86 | - Literal values with or without quotes, so `"high"` and `high` are acceptable 87 | 88 | - coditional operators and functions without referencing the variable like `>500` 89 | 90 | - Empty Condition or `-` indicates all values are true 91 | - For numeric variables: 92 | - > 500 93 | - between 500 and 700 94 | - For Date variables, functions like: 95 | - `> 30 days` , `> 50 minutes` , `< 10 years` etc. 96 | - `before '2018/01/01'` or `after '2018/03/01'` 97 | - `between '2018/01/01' and '2019/12/31'` 98 | - 99 | #### Complex Conditions 100 | - And , Or and Not operators, brackets `()` can also be used 101 | - 102 | - complex operations and functions can reference the variable using `@` symbol 103 | 104 | ### Output 105 | Output expressions can use the full expression language and reference any input or ouput variable. 106 | 107 | ## Expression Engine 108 | ```js 109 | 110 | const exp=new Expression(`2+3*4`); 111 | const result= expr.evaluate(); 112 | console.log(result); 113 | 114 | ``` 115 | Expressions are compiled into AST 116 | ```js 117 | const exp=new Expression(`2+3*4`); 118 | const compiled= expr.compile(); 119 | 120 | // or reloaed 121 | 122 | const expr=Expression.load(compiled); 123 | const result= expr.evaluate(); 124 | 125 | console.log(result); 126 | ``` 127 | 128 | # Language Constructs 129 | ## Literals 130 | - Strings: 'John' 131 | - Numbers: 123.25 132 | 133 | ## Words 134 | salary 135 | 136 | customer.address 137 | 138 | ## Operators 139 | The package already defines a set of operators but you can add your own 140 | ### Operator Symbols 141 | `+` `-' `*` `/` etcs. 142 | 143 | ### Word Operators 144 | `between` is defined as a word operator 145 | 146 | 147 | ## Functions 148 | 149 | ## Keywords 150 | 151 | The following literals are defined as Keywords 152 | 153 | -`true` 154 | -`false` 155 | -`null` 156 | 157 | -------------------------------------------------------------------------------- /Rule.d.ts: -------------------------------------------------------------------------------- 1 | import { Expression, Condition } from './Expression'; 2 | import { DTVariable } from './DecisionTable'; 3 | export declare class Rule { 4 | id: any; 5 | conditions: Condition[]; 6 | actions: Expression[]; 7 | conditionVars: DTVariable[]; 8 | actionVars: DTVariable[]; 9 | constructor(id: any, conditions: string[], actions: string[], conditionVars: DTVariable[], actionVars: DTVariable[]); 10 | asJson(): any[]; 11 | compile(): any; 12 | evaluate(data: any, result: any): Promise; 13 | } 14 | -------------------------------------------------------------------------------- /Rule.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.Rule = void 0; 13 | const Expression_1 = require("./Expression"); 14 | class Rule { 15 | constructor(id, conditions, actions, conditionVars, actionVars) { 16 | this.conditionVars = conditionVars; 17 | this.actionVars = actionVars; 18 | this.id = id; 19 | let i; 20 | this.conditions = []; 21 | this.actions = []; 22 | for (i = 0; i < conditions.length; i++) { 23 | const cond = conditions[i]; 24 | const varName = this.conditionVars[i].name; 25 | this.conditions.push(new Expression_1.Condition(cond, varName)); 26 | } 27 | for (i = 0; i < this.actionVars.length; i++) { 28 | const action = actions[i]; 29 | this.actions.push(new Expression_1.Expression(action)); 30 | } 31 | } 32 | asJson() { 33 | const list = []; 34 | list.push(this.id); 35 | this.conditions.forEach(cond => { list.push(cond.script); }); 36 | this.actions.forEach(action => { list.push(action.script); }); 37 | return list; 38 | } 39 | compile() { 40 | this.conditions.forEach(cond => { cond.compile(); }); 41 | this.actions.forEach(action => { action.compile(); }); 42 | return null; 43 | } 44 | evaluate(data, result) { 45 | return __awaiter(this, void 0, void 0, function* () { 46 | let values = data; 47 | var allTrue = true; 48 | var c; 49 | for (c = 0; c < this.conditions.length; c++) { 50 | const cond = this.conditions[c]; 51 | const varName = cond.variableName; 52 | const val = data[varName]; 53 | const ret = yield cond.evaluate(data); 54 | if (!ret) { 55 | // console.log('condition:' + varName + " " + cond.script + "vs: " + val + ' not true .. skipping'); 56 | allTrue = false; 57 | result.failedCondition = c; 58 | break; 59 | } 60 | // else 61 | // console.log('condition:' + varName + " " + cond.script+ "vs: " + val + ' true'); 62 | } 63 | if (allTrue) { 64 | result.output = {}; 65 | for (c = 0; c < this.actions.length; c++) { 66 | const action = this.actions[c]; 67 | const outVar = this.actionVars[c]; 68 | const ret = yield action.evaluate(data); 69 | result.output[outVar.name] = ret; 70 | } 71 | return true; 72 | } 73 | else 74 | return false; 75 | }); 76 | } 77 | } 78 | exports.Rule = Rule; 79 | //# sourceMappingURL=Rule.js.map -------------------------------------------------------------------------------- /Rule.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Rule.js","sourceRoot":"","sources":["Rule.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /Rule.ts: -------------------------------------------------------------------------------- 1 | import { Expression, Condition } from './Expression'; 2 | import { DecisionTable, DTVariable} from './DecisionTable'; 3 | 4 | 5 | export class Rule { 6 | id; 7 | conditions: Condition[]; 8 | actions: Expression[]; 9 | conditionVars: DTVariable []; 10 | actionVars: DTVariable[]; 11 | 12 | constructor(id, conditions: string[], actions: string[], conditionVars: DTVariable[],actionVars: DTVariable[]) { 13 | this.conditionVars = conditionVars; 14 | this.actionVars = actionVars; 15 | this.id = id; 16 | let i; 17 | this.conditions = []; 18 | this.actions = []; 19 | for (i = 0; i < conditions.length; i++) { 20 | const cond: String = conditions[i]; 21 | const varName = this.conditionVars[i].name; 22 | this.conditions.push(new Condition(cond, varName)); 23 | } 24 | for (i = 0; i < this.actionVars.length; i++) { 25 | const action: String = actions[i]; 26 | this.actions.push(new Expression(action)); 27 | } 28 | } 29 | asJson() { 30 | const list = []; 31 | list.push(this.id); 32 | this.conditions.forEach(cond => {list.push(cond.script); }); 33 | this.actions.forEach(action=> { list.push(action.script); }); 34 | return list; 35 | } 36 | compile() { 37 | this.conditions.forEach(cond => { cond.compile(); }); 38 | this.actions.forEach(action=> { action.compile(); }); 39 | 40 | return null; 41 | } 42 | async evaluate(data, result) { 43 | let values = data; 44 | var allTrue = true; 45 | var c; 46 | 47 | for (c = 0; c < this.conditions.length; c++) { 48 | const cond:Condition = this.conditions[c]; 49 | const varName = cond.variableName; 50 | const val = data[varName]; 51 | const ret =await cond.evaluate(data); 52 | if (!ret) { 53 | // console.log('condition:' + varName + " " + cond.script + "vs: " + val + ' not true .. skipping'); 54 | allTrue = false; 55 | result.failedCondition = c; 56 | break; 57 | } 58 | // else 59 | // console.log('condition:' + varName + " " + cond.script+ "vs: " + val + ' true'); 60 | 61 | } 62 | if (allTrue) { 63 | result.output = {}; 64 | for (c = 0; c < this.actions.length; c++) { 65 | const action: Expression = this.actions[c]; 66 | const outVar = this.actionVars[c]; 67 | const ret = await action.evaluate(data); 68 | result.output[outVar.name] = ret; 69 | } 70 | return true; 71 | } 72 | else 73 | return false; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Tester1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const common_1 = require("./common"); 4 | const ExpressionEngine_1 = require("./ExpressionEngine"); 5 | function testCond(expr, value, res) { 6 | const engine = new ExpressionEngine_1.ExpressionEngine(); 7 | const ret = engine.evaluateCondition(expr, value); 8 | if (ret !== res) { 9 | console.log("***Error -" + expr + " for " + value + "result: " + ret + "expecting:" + res); 10 | common_1.logger.log("***Error -" + expr + " for " + value + "result: " + ret + "expecting:" + res); 11 | } 12 | return; 13 | } 14 | function testExp(expr, res) { 15 | console.log('expecting: ' + res); 16 | common_1.logger.log('expecting: ' + res); 17 | const engine = new ExpressionEngine_1.ExpressionEngine(); 18 | const ret = engine.evaluate(expr); 19 | if (ret !== res) { 20 | common_1.Options.debugExecution = true; 21 | common_1.Options.debugExpression = true; 22 | // parser.evaluateCondition(expr, value); 23 | console.log("***Error -" + expr + "result: " + ret + "expecting:" + res); 24 | common_1.logger.log("***Error -" + expr + "result: " + ret + "expecting:" + res); 25 | // throw Error("Error -" + expr + " failed for " + value); 26 | } 27 | return; 28 | } 29 | function runTest(list, category = '') { 30 | console.log(list); 31 | list.forEach(item => { 32 | const cat = item.category; 33 | console.log("Running " + cat.name); 34 | if (cat.expressions) { 35 | cat.expressions.forEach(expr => { 36 | console.log(expr); 37 | try { 38 | testExp(expr[0], expr[1]); 39 | } 40 | catch (exc) { 41 | console.log(exc); 42 | common_1.logger.log(exc.message); 43 | } 44 | }); 45 | } 46 | if (cat.conditions) { 47 | cat.conditions.forEach(expr => { 48 | console.log(expr); 49 | try { 50 | testCond(expr[0], expr[1], expr[2]); 51 | } 52 | catch (exc) { 53 | console.log(exc); 54 | common_1.logger.log(exc.message); 55 | } 56 | }); 57 | } 58 | }); 59 | } 60 | // Structure for Expression 61 | var scripts = [{ 62 | category: { 63 | name: 'tokens syntax', 64 | expressions: [ 65 | [`2 + 3 'test' > and < == or function - * () []`, 20], 66 | ["caseId", 1001], 67 | [`2 + 3`, 5], 68 | [`(2 + 3) * 4`, 20], 69 | [`4 * (2 + 3)`, 20], 70 | [`4 * (2 + (3+0))`, 20], 71 | [`2 + 3 * 4`, 14], 72 | [`3 * 4 +2`, 14], 73 | ['"high"', 'high'], 74 | [`2+3`, 5] 75 | ] 76 | } 77 | } 78 | ]; 79 | var conditions = [{ 80 | category: { 81 | name: 'tokens syntax', 82 | conditions: [ 83 | ["> 200 or < 500", 20, true], 84 | ["-20", '55', false], 85 | ["20+35", '55', true], 86 | ["> 200 or < 500", 20, true], 87 | [`'High'`, 'High', true], 88 | [`High`, 'Low', false], 89 | ["> 200 or < 500", 20, true], 90 | ["(> 200) or (< 500)", 20, true], 91 | ["(in ('abc','xyz-abc')", 'abc', true], 92 | ["(in ('abc','xyz-abc') ) and startsWith('a')", 'abc', true], 93 | ["in ('abc','xyz-abc','another entry', 9)", "abc", true], 94 | ["(2+3)", '5', true], 95 | ["2+3", '5', true], 96 | ["2*4", '8', true], 97 | ["(2+3)*4", '20', true], 98 | ["(in (abc,'xyz-abc') ) and startsWith('a')", 'abc', true], 99 | ["in (abc,'xyz-abc') and startsWith('a')", 'abc', true], 100 | ["75.25", '75', false], 101 | //["75.25", '75.25', true], 102 | ["2,075.25", '75', false], 103 | ["2,075.25", '2075.25', true], 104 | ["-20", '-20', true], 105 | [">=75", '75', true], 106 | ["<=55", '55', true], 107 | ["==55", '55', true], 108 | ["2 + 3", '5', true], 109 | ["> 200 or < 500", 20, true], 110 | ["object.fun('test')", '75', true], 111 | ["5 + object.fun('test')", '75', true], 112 | ["in (abc,'xyz-abc','another entry')", "abc", true], 113 | ["not in (abc,'xyz-abc') ", 'abc', true], 114 | ["in (abc,'xyz-abc') and startsWith('a') ", 'abc', true], 115 | ["in (abc,'xyz-abc') and not startsWith('a') ", 'abc', false], 116 | ["in (abc,'xyz-abc') and startsWith('a') and 3 ", 'abc', false], 117 | ["75", 'not 75', false], 118 | ["'High'", 'High', true], 119 | ["in (abc,'xyz-abc','another entry')", "abc", true], 120 | ["between ( 95 , 2500.0 )", 200, true], 121 | ] 122 | } 123 | } 124 | ]; 125 | common_1.Options.debugTokens = true; 126 | common_1.Options.debugExpression = true; 127 | common_1.Options.debugExecution = true; 128 | testCond(`$ not 10 and $<500`, 20, true); 129 | //testExp(`20 <500 `, true); 130 | //testExp(`2 + 3`, true); 131 | //main(); 132 | //testExp(` in ('1','2','3')`, null); 133 | //testExp(` (1> $v1) and funct (v1 , 2 , 3) startsWith "abc12$@!3z"`, null); 134 | //testExp(` (1>2) and funct (v1 , 2 , 3) `, null); 135 | //testExp(` between a and b `, null); 136 | // make between an operator 137 | // operators: type: 138 | // L 0-1 139 | // R 0-2 140 | /*console.log(process.argv); 141 | var args = process.argv; 142 | if (args.length > 4) { 143 | console.log('testing condition ' + args[2], args[3], args[4]); 144 | // testCond(args[2], args[3], args[4]); 145 | } 146 | else if (args.length > 3) { 147 | console.log('testing expression' + args[2], args[3]); 148 | // testExp(args[2], args[3]); 149 | } 150 | */ 151 | function main() { 152 | common_1.logger.log("starting"); 153 | runTest(scripts); 154 | runTest(conditions); 155 | common_1.logger.save("./parser.log"); 156 | } 157 | //# sourceMappingURL=Tester1.js.map -------------------------------------------------------------------------------- /Tester1.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Tester1.js","sourceRoot":"","sources":["Tester1.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /Tester2.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Tester2.js","sourceRoot":"","sources":["Tester2.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const readline = require('readline'); 4 | const path = require('path') 5 | 6 | console.log('Hello, welcome to BPMN-Engine Samples'); 7 | 8 | var files = [] 9 | 10 | displayFiles(); 11 | 12 | var log = console.log; 13 | 14 | var rl = readline.createInterface({ 15 | input: process.stdin, 16 | output: process.stdout 17 | }); 18 | var lastFile; 19 | 20 | var recursiveAsyncReadLine = function () { 21 | console.log(`Select a file from the list or "exit" or ? for list`); 22 | rl.question('Command: ', function (answer) { 23 | if (answer == 'exit') //we need some base case, for recursion 24 | return rl.close(); //closing RL and returning from function. 25 | if (answer == '?') //we need some base case, for recursion 26 | displayFiles(); 27 | log('Got it! Your answer was: "', answer, '"'); 28 | 29 | let file = files[answer - 1]; 30 | if (file) { 31 | if (lastFile) 32 | delete require.cache[require.resolve('./engine-samples/' + lastFile)] 33 | console.log(" invoking file: " + file); 34 | let test = require('./engine-samples/' + file); 35 | lastFile = file; 36 | 37 | } 38 | 39 | recursiveAsyncReadLine(); //Calling this function again to ask new question 40 | }); 41 | }; 42 | 43 | recursiveAsyncReadLine(); //we have to actually start our recursion somehow 44 | 45 | 46 | function displayFiles() { 47 | 48 | console.log(__dirname); 49 | 50 | const testFolder = __dirname + '/engine-samples'; 51 | const fs = require('fs'); 52 | files = []; 53 | let i = 0; 54 | fs.readdirSync(testFolder).forEach(file => { 55 | if (path.extname(file) == '.js') { 56 | console.log("" + (++i) + " " + file); 57 | files.push(file); 58 | } 59 | }); 60 | } 61 | 62 | 63 | 64 | /* 65 | 66 | 67 | const rl = readline.createInterface({ 68 | input: process.stdin, 69 | output: process.stdout 70 | }); 71 | 72 | 73 | while ( checkInput()) { } 74 | 75 | 76 | async function checkInput() { 77 | 78 | 79 | readLine('testing?', function (answer) { 80 | // TODO: Log the answer in a database 81 | console.log(`Select a file from the list or "exit" ${answer}`); 82 | 83 | if (answer== 'exit') 84 | return null; 85 | 86 | let file = files[answer - 1]; 87 | 88 | if (file) { 89 | console.log(" invoking file: " + file); 90 | // var sample = require('./engine-samples/' + file); 91 | 92 | } 93 | 94 | 95 | return answer; 96 | }); 97 | } 98 | 99 | 100 | function readLine(question, callback) { 101 | 102 | 103 | rl.question('What do you think of Node.js? ', (answer) => { callback(answer); }); 104 | 105 | 106 | } 107 | */ 108 | -------------------------------------------------------------------------------- /common.d.ts: -------------------------------------------------------------------------------- 1 | export declare class Options { 2 | static debugTokens: boolean; 3 | static debugExpression: boolean; 4 | static debugExecution: boolean; 5 | static debugTree: boolean; 6 | static delegate: any; 7 | } 8 | export declare function debug(type: any, title: any, obj?: any): void; 9 | export declare class Logger { 10 | debugMsgs: any[]; 11 | toConsole: boolean; 12 | toFile: any; 13 | callback: any; 14 | constructor({ toConsole, toFile, callback }: { 15 | toConsole?: boolean; 16 | toFile?: string; 17 | callback?: any; 18 | }); 19 | setOptions({ toConsole, toFile, callback }: { 20 | toConsole: any; 21 | toFile: any; 22 | callback: any; 23 | }): void; 24 | msg(message: any, type?: string): void; 25 | clear(): void; 26 | get(): any[]; 27 | debug(message: any): void; 28 | warn(message: any): void; 29 | log(message: any): void; 30 | error(err: any): void; 31 | save(filename: any): Promise; 32 | } 33 | export declare const logger: Logger; 34 | -------------------------------------------------------------------------------- /common.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.logger = exports.Logger = exports.debug = exports.Options = void 0; 13 | const FS = require('fs'); 14 | class Options { 15 | } 16 | exports.Options = Options; 17 | Options.debugTokens = false; 18 | Options.debugExpression = true; 19 | Options.debugExecution = false; 20 | Options.debugTree = false; 21 | function debug(type, title, obj = null) { 22 | exports.logger.log(title); 23 | if (type == 'execution' && !Options.debugExecution) 24 | return; 25 | if (type == 'tokens' && !Options.debugTokens) 26 | return; 27 | if (type == 'tree' && !Options.debugTree) 28 | return; 29 | console.log(title); 30 | if (obj) { 31 | console.log(obj); 32 | exports.logger.log(JSON.stringify(obj)); 33 | } 34 | } 35 | exports.debug = debug; 36 | class Logger { 37 | constructor({ toConsole = true, toFile = '', callback = null }) { 38 | this.debugMsgs = []; 39 | this.toConsole = true; 40 | this.toFile = null; 41 | this.callback = null; 42 | this.setOptions({ toConsole, toFile, callback }); 43 | } 44 | setOptions({ toConsole, toFile, callback }) { 45 | this.toConsole = toConsole; 46 | this.toFile = toFile; 47 | this.callback = callback; 48 | } 49 | msg(message, type = 'log') { 50 | if (this.toConsole) 51 | console.log(message); 52 | if (this.callback) { 53 | this.callback(message, type); 54 | } 55 | this.debugMsgs.push({ message, type }); 56 | } 57 | clear() { 58 | this.debugMsgs = []; 59 | } 60 | get() { 61 | return this.debugMsgs; 62 | } 63 | debug(message) { 64 | this.msg(message, 'debug'); 65 | } 66 | warn(message) { 67 | this.msg(message, 'warn'); 68 | } 69 | log(message) { 70 | this.msg(message); 71 | } 72 | error(err) { 73 | if (typeof err === 'object') { 74 | if (err.message) { 75 | this.msg(err.message, 'error'); 76 | console.log('\nError Message: ' + err.message); 77 | } 78 | if (err.stack) { 79 | console.log('\nStacktrace:'); 80 | console.log('===================='); 81 | console.log(err.stack); 82 | this.log(err.stack); 83 | } 84 | } 85 | else { 86 | this.msg(err, 'error'); 87 | } 88 | throw new Error(err); 89 | } 90 | save(filename) { 91 | return __awaiter(this, void 0, void 0, function* () { 92 | console.log("writing to:" + filename + " " + this.debugMsgs.length); 93 | let id = FS.openSync(filename, 'w', 666); 94 | { 95 | FS.writeSync(id, 'Started at: ' + new Date().toISOString() + "\n", null, 'utf8'); 96 | let l = 0; 97 | for (l = 0; l < this.debugMsgs.length; l++) { 98 | let msg = this.debugMsgs[l]; 99 | if (msg.type == 'error') { 100 | let line = msg.type + ": at line " + (l + 1) + " " + msg.message; 101 | FS.writeSync(id, line + "\n", null, 'utf8'); 102 | } 103 | } 104 | for (l = 0; l < this.debugMsgs.length; l++) { 105 | let msg = this.debugMsgs[l]; 106 | let line; 107 | if (msg.type == 'eror') 108 | line = msg.type + ":" + msg.message; 109 | else 110 | line = msg.message; 111 | FS.writeSync(id, line + "\n", null, 'utf8'); 112 | } 113 | FS.closeSync(id); 114 | this.clear(); 115 | } 116 | }); 117 | } 118 | } 119 | exports.Logger = Logger; 120 | exports.logger = new Logger({ toConsole: false }); 121 | //# sourceMappingURL=common.js.map -------------------------------------------------------------------------------- /common.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"common.js","sourceRoot":"","sources":["common.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /common.ts: -------------------------------------------------------------------------------- 1 | 2 | const FS = require('fs'); 3 | 4 | export class Options { 5 | static debugTokens = false; 6 | static debugExpression = true; 7 | static debugExecution = false; 8 | static debugTree = false; 9 | static delegate; 10 | } 11 | 12 | export function debug(type, title, obj = null) { 13 | 14 | logger.log(title); 15 | 16 | if (type == 'execution' && !Options.debugExecution) 17 | return; 18 | if (type == 'tokens' && !Options.debugTokens) 19 | return; 20 | 21 | if (type == 'tree' && !Options.debugTree) 22 | return; 23 | 24 | console.log(title); 25 | if (obj) { 26 | console.log(obj); 27 | logger.log(JSON.stringify(obj)); 28 | 29 | } 30 | } 31 | 32 | export class Logger { 33 | 34 | debugMsgs = []; 35 | toConsole = true; 36 | toFile = null; 37 | callback = null; 38 | 39 | constructor({ toConsole = true, toFile = '', callback = null }) { 40 | this.setOptions({ toConsole, toFile, callback }); 41 | } 42 | setOptions({ toConsole, toFile, callback }) { 43 | 44 | this.toConsole = toConsole; 45 | this.toFile = toFile; 46 | this.callback = callback; 47 | } 48 | msg(message, type = 'log') { 49 | if (this.toConsole) 50 | console.log(message); 51 | if (this.callback) { 52 | this.callback(message, type); 53 | } 54 | this.debugMsgs.push({ message, type }); 55 | } 56 | clear() { 57 | 58 | this.debugMsgs = []; 59 | } 60 | get() { 61 | 62 | return this.debugMsgs; 63 | } 64 | debug(message) { 65 | this.msg(message, 'debug'); 66 | } 67 | warn(message) { 68 | this.msg(message, 'warn'); 69 | } 70 | log(message) { 71 | this.msg(message); 72 | } 73 | error(err) { 74 | if (typeof err === 'object') { 75 | if (err.message) { 76 | this.msg(err.message, 'error'); 77 | console.log('\nError Message: ' + err.message) 78 | } 79 | if (err.stack) { 80 | console.log('\nStacktrace:') 81 | console.log('====================') 82 | console.log(err.stack); 83 | this.log(err.stack); 84 | } 85 | } else { 86 | this.msg(err, 'error'); 87 | } 88 | 89 | throw new Error(err); 90 | } 91 | async save(filename) { 92 | console.log("writing to:" + filename + " " + this.debugMsgs.length); 93 | let id = FS.openSync(filename, 'w', 666); 94 | { 95 | FS.writeSync(id, 'Started at: ' + new Date().toISOString() + "\n", null, 'utf8'); 96 | 97 | let l = 0; 98 | for (l = 0; l < this.debugMsgs.length; l++) { 99 | let msg = this.debugMsgs[l]; 100 | if (msg.type == 'error') { 101 | let line = msg.type + ": at line " + (l + 1) + " " + msg.message; 102 | FS.writeSync(id, line + "\n", null, 'utf8'); 103 | } 104 | } 105 | for (l = 0; l < this.debugMsgs.length; l++) { 106 | let msg = this.debugMsgs[l]; 107 | let line; 108 | if (msg.type == 'eror') 109 | line = msg.type + ":" + msg.message; 110 | else 111 | line = msg.message; 112 | FS.writeSync(id, line + "\n", null, 'utf8'); 113 | } 114 | 115 | FS.closeSync(id); 116 | this.clear(); 117 | 118 | } 119 | } 120 | } 121 | 122 | export const logger = new Logger({ toConsole: false }); 123 | 124 | -------------------------------------------------------------------------------- /credentials.json: -------------------------------------------------------------------------------- 1 | {"installed":{"client_id":"1087725509991-gefmrrbrqam1b2cmcng5ui5ujc2gm16t.apps.googleusercontent.com","project_id":"quickstart-1596492255596","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"AmlCgseSBO1203FVatAyNjND","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}} -------------------------------------------------------------------------------- /docs/DMN_client_category_table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralphhanna/dmn-engine/2484626411fdbbf8f889b42f9ad57a389d229033/docs/DMN_client_category_table.jpg -------------------------------------------------------------------------------- /docs/anatomyofdt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralphhanna/dmn-engine/2484626411fdbbf8f889b42f9ad57a389d229033/docs/anatomyofdt.png -------------------------------------------------------------------------------- /docs/dt-and-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralphhanna/dmn-engine/2484626411fdbbf8f889b42f9ad57a389d229033/docs/dt-and-tests.png -------------------------------------------------------------------------------- /docs/lifeInsuracne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralphhanna/dmn-engine/2484626411fdbbf8f889b42f9ad57a389d229033/docs/lifeInsuracne.png -------------------------------------------------------------------------------- /google.d.ts: -------------------------------------------------------------------------------- 1 | export declare class GoogleSheets { 2 | auth: any; 3 | constructor(); 4 | init(): Promise; 5 | getRule(spreadsheetId: any, range: any): Promise<{ 6 | decisionTable: { 7 | name: any; 8 | hitPolicy: any; 9 | conditionVars: any[]; 10 | actionVars: any[]; 11 | rules: any[]; 12 | }; 13 | tests: any[]; 14 | }>; 15 | getData(spreadsheetId: any, range: any): Promise; 16 | /** 17 | * Create an OAuth2 client with the given credentials, and then execute the 18 | * given callback function. 19 | * @param {Object} credentials The authorization client credentials. 20 | * @param {function} callback The callback to call with the authorized client. 21 | */ 22 | authorizeAsync(credentials: any): Promise; 23 | } 24 | -------------------------------------------------------------------------------- /google.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.GoogleSheets = void 0; 13 | const fs = require('fs'); 14 | const readline = require('readline'); 15 | const { google } = require('googleapis'); 16 | /* 17 | * Decison Vaction Allowance Hit Policy Collect+ 18 | Variables Input Input Output Annotation 19 | Variable YearsOfService EmployeeType Vacation Annotation 20 | data type integer string integer 21 | Rules: 22 | 1 - "Contract" 0 23 | 2 - 'Executive" 4 24 | 3 - 'Employee" 2 25 | 4 >10 in ['Employee','Executive'] 1 Additional Week for 10 years 26 | 5 >20 in ['Employee','Executive'] 1 Another week after 20 years 27 | 28 | 29 | 30 | Tests 5 "Employee" 31 | */ 32 | class CSVReader { 33 | static parseRule(rows) { 34 | const dt = { name: null, hitPolicy: null, conditionVars: [], actionVars: [], rules: [] }; 35 | const tests = []; 36 | let varTypes = null; 37 | let c, inputStart, outputStart, annotationStart, hitPolicyPosition; 38 | let r = 1; 39 | let mode = ''; 40 | rows.forEach(row => { 41 | // console.log(row) 42 | if (row.length > 0) { 43 | const title = row[0]; 44 | // console.log('row ' + r + " " + title + " mode: " + mode); 45 | switch (title) { 46 | case 'Decision': 47 | for (c = 1; c < row.length; c++) { 48 | if (row[c] == 'Hit Policy') 49 | hitPolicyPosition = c; 50 | } 51 | mode = 'Decision'; 52 | break; 53 | case 'Variables': 54 | mode = 'VariableTypes'; 55 | break; 56 | case 'Rules:': 57 | mode = 'Rules'; 58 | break; 59 | case 'Tests:': 60 | mode = 'Tests'; 61 | break; 62 | default: 63 | switch (mode) { 64 | case 'Decision': 65 | dt.name = row[0]; 66 | dt.hitPolicy = row[hitPolicyPosition]; 67 | break; 68 | case 'VariableTypes': 69 | for (c = 1; c < row.length; c++) { 70 | if (row[c] == 'Input') 71 | inputStart = c; 72 | else if (row[c] == 'Output') 73 | outputStart = c; 74 | else if (row[c] == 'Annotation') 75 | annotationStart = c; 76 | } 77 | mode = 'Variables'; 78 | break; 79 | case 'Variables': 80 | for (c = inputStart; c < outputStart; c++) { 81 | dt.conditionVars.push({ name: row[c] }); 82 | } 83 | for (c = outputStart; c < annotationStart && c < row.length; c++) { 84 | dt.actionVars.push({ name: row[c] }); 85 | } 86 | mode = ''; 87 | break; 88 | case 'Rules': 89 | dt.rules.push(row); 90 | break; 91 | case 'Tests': 92 | let i; 93 | const record = {}; 94 | for (i = 0; i < dt.conditionVars.length; i++) { 95 | const varName = dt.conditionVars[i].name; 96 | record[varName] = CSVReader.trimParam(row[i + 1]); 97 | } 98 | record['__ID'] = r; 99 | tests.push(record); 100 | break; 101 | } 102 | break; 103 | } 104 | } 105 | else 106 | mode = ''; 107 | r++; 108 | }); 109 | //console.log(dt); 110 | // console.log(dt.tests); 111 | return { decisionTable: dt, tests }; 112 | } 113 | static trimParam(param) { 114 | if (param.startsWith('"') && param.endsWith('"')) 115 | return param.substring(1, param.length - 1); 116 | if (param.startsWith("'") && param.endsWith("'")) 117 | return param.substring(1, param.length - 1); 118 | else 119 | return param.trim(); 120 | } 121 | } 122 | class GoogleSheets { 123 | constructor() { 124 | this.auth = null; 125 | } 126 | init() { 127 | return __awaiter(this, void 0, void 0, function* () { 128 | let content = fs.readFileSync('credentials.json'); 129 | // if (err) return console.log('Error loading client secret file:', err); 130 | // Authorize a client with credentials, then call the Google Sheets API. 131 | // authorize(JSON.parse(content), listMajors); 132 | // authorize(JSON.parse(content), doIt); 133 | let token = yield this.authorizeAsync(JSON.parse(content)); 134 | this.auth = token; 135 | }); 136 | } 137 | getRule(spreadsheetId, range) { 138 | return __awaiter(this, void 0, void 0, function* () { 139 | const rows = yield this.getData(spreadsheetId, range); 140 | // console.log(rows); 141 | return CSVReader.parseRule(rows); 142 | }); 143 | } 144 | getData(spreadsheetId, range) { 145 | return __awaiter(this, void 0, void 0, function* () { 146 | return new Promise((resolve, reject) => { 147 | const sheets = google.sheets({ version: 'v4', auth: this.auth }); 148 | sheets.spreadsheets.values.get({ 149 | // spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms', 150 | spreadsheetId: spreadsheetId, 151 | range: range, 152 | }, (err, res) => { 153 | if (err) 154 | return reject('The API returned an error: ' + err); 155 | const rows = res.data.values; 156 | resolve(rows); 157 | let r = 1; 158 | if (rows.length) { 159 | // console.log('Range:' + range); 160 | // Print columns A and E, which correspond to indices 0 and 4. 161 | rows.map((row) => { 162 | // console.log('Row: ', r++, row); 163 | // console.log(`${row[0]}, ${row[4]}`); 164 | }); 165 | } 166 | else { 167 | console.log('No data found.'); 168 | } 169 | }); 170 | }); 171 | }); 172 | } 173 | /** 174 | * Create an OAuth2 client with the given credentials, and then execute the 175 | * given callback function. 176 | * @param {Object} credentials The authorization client credentials. 177 | * @param {function} callback The callback to call with the authorized client. 178 | */ 179 | authorizeAsync(credentials) { 180 | return __awaiter(this, void 0, void 0, function* () { 181 | const { client_secret, client_id, redirect_uris } = credentials.installed; 182 | /* 183 | return new Promise((resolve, reject) => { 184 | ... 185 | resolve(data) 186 | }) 187 | }); */ 188 | return new Promise((resolve, reject) => { 189 | const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]); 190 | // Check if we have previously stored a token. 191 | fs.readFile(TOKEN_PATH, (err, token) => { 192 | if (err) { 193 | // return getNewToken(oAuth2Client, callback); 194 | } 195 | oAuth2Client.setCredentials(JSON.parse(token)); 196 | // callback(oAuth2Client); 197 | resolve(oAuth2Client); 198 | }); 199 | }); 200 | }); 201 | } 202 | } 203 | exports.GoogleSheets = GoogleSheets; 204 | // If modifying these scopes, delete token.json. 205 | const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']; 206 | // The file token.json stores the user's access and refresh tokens, and is 207 | // created automatically when the authorization flow completes for the first 208 | // time. 209 | const TOKEN_PATH = 'token.json'; 210 | /* 211 | // Load client secrets from a local file. 212 | fs.readFile('credentials.json', (err, content) => { 213 | if (err) return console.log('Error loading client secret file:', err); 214 | // Authorize a client with credentials, then call the Google Sheets API. 215 | // authorize(JSON.parse(content), listMajors); 216 | authorize(JSON.parse(content), doIt); 217 | 218 | }); 219 | */ 220 | //# sourceMappingURL=google.js.map -------------------------------------------------------------------------------- /google.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"google.js","sourceRoot":"","sources":["google.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /google.ts: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const readline = require('readline'); 3 | const { google } = require('googleapis'); 4 | 5 | import { DecisionTable } from './DecisionTable'; 6 | 7 | /* 8 | * Decison Vaction Allowance Hit Policy Collect+ 9 | Variables Input Input Output Annotation 10 | Variable YearsOfService EmployeeType Vacation Annotation 11 | data type integer string integer 12 | Rules: 13 | 1 - "Contract" 0 14 | 2 - 'Executive" 4 15 | 3 - 'Employee" 2 16 | 4 >10 in ['Employee','Executive'] 1 Additional Week for 10 years 17 | 5 >20 in ['Employee','Executive'] 1 Another week after 20 years 18 | 19 | 20 | 21 | Tests 5 "Employee" 22 | */ 23 | class CSVReader { 24 | 25 | static parseRule(rows) { 26 | const dt = { name: null, hitPolicy: null, conditionVars: [], actionVars: [], rules: [] }; 27 | const tests = []; 28 | let varTypes = null; 29 | let c, inputStart, outputStart, annotationStart, hitPolicyPosition; 30 | let r = 1; 31 | let mode = ''; 32 | rows.forEach(row => { 33 | // console.log(row) 34 | if (row.length > 0) { 35 | const title = row[0]; 36 | // console.log('row ' + r + " " + title + " mode: " + mode); 37 | switch (title) { 38 | case 'Decision': 39 | for (c = 1; c < row.length; c++) { 40 | if (row[c] == 'Hit Policy') 41 | hitPolicyPosition = c; 42 | } 43 | mode = 'Decision'; 44 | break; 45 | case 'Variables': 46 | mode = 'VariableTypes'; 47 | break; 48 | case 'Rules:': 49 | mode = 'Rules'; 50 | break; 51 | case 'Tests:': 52 | mode = 'Tests'; 53 | break; 54 | default: 55 | switch (mode) { 56 | case 'Decision': 57 | dt.name = row[0]; 58 | dt.hitPolicy = row[hitPolicyPosition]; 59 | break; 60 | case 'VariableTypes': 61 | 62 | for (c = 1; c < row.length; c++) { 63 | if (row[c] == 'Input') 64 | inputStart = c; 65 | else if (row[c] == 'Output') 66 | outputStart = c; 67 | else if (row[c] == 'Annotation') 68 | annotationStart = c; 69 | } 70 | mode = 'Variables'; 71 | break; 72 | case 'Variables': 73 | for (c = inputStart; c < outputStart; c++) { 74 | dt.conditionVars.push({ name: row[c] }); 75 | } 76 | for (c = outputStart; c < annotationStart && c < row.length; c++) { 77 | dt.actionVars.push({ name: row[c] }); 78 | } 79 | mode = ''; 80 | break; 81 | case 'Rules': 82 | dt.rules.push(row); 83 | break; 84 | case 'Tests': 85 | let i; 86 | const record = {}; 87 | for (i = 0; i < dt.conditionVars.length; i++) { 88 | const varName = dt.conditionVars[i].name; 89 | record[varName] = CSVReader.trimParam(row[i + 1]); 90 | } 91 | record['__ID'] = r; 92 | 93 | tests.push(record); 94 | break; 95 | } 96 | 97 | break; 98 | 99 | } 100 | 101 | } 102 | else 103 | mode = ''; 104 | r++; 105 | }); 106 | //console.log(dt); 107 | // console.log(dt.tests); 108 | return {decisionTable: dt, tests} 109 | } 110 | static trimParam(param) { 111 | if (param.startsWith('"') && param.endsWith('"')) 112 | return param.substring(1, param.length - 1); 113 | if (param.startsWith("'") && param.endsWith("'")) 114 | return param.substring(1, param.length - 1); 115 | else 116 | return param.trim(); 117 | } 118 | } 119 | 120 | export class GoogleSheets { 121 | 122 | auth=null; 123 | constructor() { 124 | } 125 | async init() { 126 | let content = fs.readFileSync('credentials.json'); 127 | // if (err) return console.log('Error loading client secret file:', err); 128 | // Authorize a client with credentials, then call the Google Sheets API. 129 | // authorize(JSON.parse(content), listMajors); 130 | // authorize(JSON.parse(content), doIt); 131 | let token = await this.authorizeAsync(JSON.parse(content)); 132 | this.auth=token; 133 | } 134 | async getRule(spreadsheetId, range) { 135 | const rows = await this.getData(spreadsheetId, range); 136 | // console.log(rows); 137 | return CSVReader.parseRule(rows); 138 | } 139 | async getData(spreadsheetId, range) { 140 | 141 | return new Promise((resolve, reject) => { 142 | 143 | const sheets = google.sheets({ version: 'v4', auth: this.auth }); 144 | sheets.spreadsheets.values.get({ 145 | // spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms', 146 | spreadsheetId: spreadsheetId, 147 | range: range, 148 | }, (err, res) => { 149 | if (err) return reject('The API returned an error: ' + err); 150 | const rows = res.data.values; 151 | resolve(rows); 152 | let r = 1; 153 | 154 | if (rows.length) { 155 | // console.log('Range:' + range); 156 | // Print columns A and E, which correspond to indices 0 and 4. 157 | rows.map((row) => { 158 | // console.log('Row: ', r++, row); 159 | // console.log(`${row[0]}, ${row[4]}`); 160 | }); 161 | } else { 162 | console.log('No data found.'); 163 | } 164 | 165 | }); 166 | }); 167 | } 168 | /** 169 | * Create an OAuth2 client with the given credentials, and then execute the 170 | * given callback function. 171 | * @param {Object} credentials The authorization client credentials. 172 | * @param {function} callback The callback to call with the authorized client. 173 | */ 174 | async authorizeAsync(credentials) { 175 | const { client_secret, client_id, redirect_uris } = credentials.installed; 176 | 177 | /* 178 | return new Promise((resolve, reject) => { 179 | ... 180 | resolve(data) 181 | }) 182 | }); */ 183 | 184 | return new Promise((resolve, reject) => { 185 | 186 | const oAuth2Client = new google.auth.OAuth2( 187 | client_id, client_secret, redirect_uris[0]); 188 | 189 | // Check if we have previously stored a token. 190 | fs.readFile(TOKEN_PATH, (err, token) => { 191 | if (err) { 192 | // return getNewToken(oAuth2Client, callback); 193 | } 194 | oAuth2Client.setCredentials(JSON.parse(token)); 195 | // callback(oAuth2Client); 196 | resolve(oAuth2Client) 197 | }); 198 | 199 | }); 200 | 201 | } 202 | } 203 | 204 | // If modifying these scopes, delete token.json. 205 | const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']; 206 | // The file token.json stores the user's access and refresh tokens, and is 207 | // created automatically when the authorization flow completes for the first 208 | // time. 209 | const TOKEN_PATH = 'token.json'; 210 | /* 211 | // Load client secrets from a local file. 212 | fs.readFile('credentials.json', (err, content) => { 213 | if (err) return console.log('Error loading client secret file:', err); 214 | // Authorize a client with credentials, then call the Google Sheets API. 215 | // authorize(JSON.parse(content), listMajors); 216 | authorize(JSON.parse(content), doIt); 217 | 218 | }); 219 | */ 220 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './common'; 2 | export declare function ExecuteCondition(script: any, variable: any, context: any): Promise; 3 | export declare function ExecuteExpression(script: any, context: any): Promise; 4 | export declare function ExecuteDecisionTable({ definition, data, options, loadFrom }: { 5 | definition: any; 6 | data: any; 7 | options: any; 8 | loadFrom: any; 9 | }): Promise; 10 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
Expression: 5 |
Input Value: 6 |
Input expected: 7 |
Input Result: 8 | 9 |
Input Value: 14 |
15 | 16 | 17 |
18 |
19 | Tree: 20 |
21 | 62 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 10 | for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); 11 | }; 12 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 13 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 14 | return new (P || (P = Promise))(function (resolve, reject) { 15 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 16 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 17 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 18 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 19 | }); 20 | }; 21 | Object.defineProperty(exports, "__esModule", { value: true }); 22 | exports.ExecuteDecisionTable = exports.ExecuteExpression = exports.ExecuteCondition = void 0; 23 | const DecisionTable_1 = require("./DecisionTable"); 24 | const Expression_1 = require("./Expression"); 25 | __exportStar(require("./common"), exports); 26 | function ExecuteCondition(script, variable, context) { 27 | return __awaiter(this, void 0, void 0, function* () { 28 | const cond = new Expression_1.Condition(script, variable); 29 | return yield cond.evaluate(context); 30 | }); 31 | } 32 | exports.ExecuteCondition = ExecuteCondition; 33 | function ExecuteExpression(script, context) { 34 | return __awaiter(this, void 0, void 0, function* () { 35 | const expr = new Expression_1.Expression(script); 36 | return yield expr.evaluate(context); 37 | }); 38 | } 39 | exports.ExecuteExpression = ExecuteExpression; 40 | function ExecuteDecisionTable({ definition, data, options, loadFrom }) { 41 | console.log(definition); 42 | console.log(data); 43 | console.log(options); 44 | console.log(loadFrom); 45 | const dt = new DecisionTable_1.DecisionTable(definition); 46 | const res = dt.evaluate(data); 47 | return res; 48 | } 49 | exports.ExecuteDecisionTable = ExecuteDecisionTable; 50 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,mDAAgD;AAChD,6CAAoD;AACpD,2CAAyB;AAEzB,SAAsB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO;;QAC/D,MAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC7C,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;CAAA;AAHD,4CAGC;AACD,SAAsB,iBAAiB,CAAC,MAAM,EAAC,OAAO;;QACrD,MAAM,IAAI,GAAG,IAAI,uBAAU,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;CAAA;AAHD,8CAGC;AACD,SAAgB,oBAAoB,CACnC,EAAE,UAAU,EACX,IAAI,EACJ,OAAO,EACP,QAAQ,EACR;IACD,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAGlB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,MAAM,EAAE,GAAG,IAAI,6BAAa,CAAC,UAAU,CAAC,CAAC;IAEzC,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC;AAGZ,CAAC;AAnBD,oDAmBC"} -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { DecisionTable } from './DecisionTable'; 2 | import { Condition,Expression } from './Expression'; 3 | export * from './common'; 4 | 5 | export async function ExecuteCondition(script, variable, context) { 6 | const cond = new Condition(script, variable); 7 | return await cond.evaluate(context); 8 | } 9 | export async function ExecuteExpression(script,context) { 10 | const expr = new Expression(script); 11 | return await expr.evaluate(context); 12 | } 13 | export function ExecuteDecisionTable( 14 | { definition, 15 | data, 16 | options, 17 | loadFrom 18 | }) { 19 | console.log(definition); 20 | console.log(data); 21 | 22 | 23 | console.log(options); 24 | console.log(loadFrom); 25 | 26 | const dt = new DecisionTable(definition); 27 | 28 | const res = dt.evaluate(data); 29 | return res; 30 | 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dmn-engine", 3 | "version": "1.0.5", 4 | "description": "Business Rules Engine for Javascript and Node.js, with built-in Expression Language supporting DMN Decision Table", 5 | "main": "index.js", 6 | "author": { 7 | "name": "" 8 | }, 9 | "devDependencies": { 10 | "tsc": "^1.20150623.0", 11 | "typescript": "^3.9.7" 12 | }, 13 | "scripts": { 14 | "build": "tsc --build", 15 | "clean": "tsc --build --clean", 16 | "start:watch": "nodemon app", 17 | "start": "node app.ts", 18 | "test": "mocha -R dot", 19 | "posttest": "eslint . --cache && npm run toc", 20 | "wintest": "node_modules/.bin/mocha", 21 | "toc": "node scripts/generate-api-toc ./docs/API.md,./docs/Examples.md", 22 | "test-md": "node scripts/test-markdown.js ./docs/API.md && node scripts/test-markdown.js ./docs/Examples.md", 23 | "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", 24 | "lint": "tslint -p tsconfig.json" 25 | }, 26 | "dependencies": { 27 | "@types/node": "^14.0.27", 28 | "dmn-moddle": "^9.1.0", 29 | "googleapis": "^39.2.0", 30 | "iso8601-duration": "^1.2.0", 31 | "js-feel": "^1.4.5" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /process.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | const configuration_1 = require("../configuration"); 13 | const __1 = require(".."); 14 | const logger = new __1.Logger({ toConsole: true }); 15 | let name = 'ds'; 16 | let process; 17 | let needsRepairs = true; 18 | let needsCleaning = true; 19 | let response; 20 | let items; 21 | let item; 22 | let query, query1; 23 | let server; 24 | let instanceId; 25 | load('Buy Used Car'); 26 | // importAll(); 27 | //importModel('multiStart'); 28 | //build(); 29 | function test() { 30 | return __awaiter(this, void 0, void 0, function* () { 31 | let events = yield findEvents({ "events.subType": 'Timer' }); 32 | }); 33 | } 34 | function build() { 35 | return __awaiter(this, void 0, void 0, function* () { 36 | const server = new __1.BPMNServer(configuration_1.configuration, logger); 37 | const mds = server.definitions; 38 | mds.install(); 39 | }); 40 | } 41 | function load(name) { 42 | return __awaiter(this, void 0, void 0, function* () { 43 | // called from Execution 44 | const server = new __1.BPMNServer(configuration_1.configuration, logger); 45 | const mds = server.definitions; 46 | const list = yield mds.getList(); 47 | // two objects are needed here: 48 | //1 49 | let definition; // this definition holds nodes and flows, fundemental to execution 50 | let bpmnModelData; // name,source and so one 51 | definition = yield mds.load(name); 52 | bpmnModelData = yield mds.loadModel(name); 53 | let source = yield mds.getSource(name); 54 | let svg = yield mds.getSVG(name); 55 | yield mds.save(name, source, svg); 56 | mds.saveModel(bpmnModelData); 57 | console.log(bpmnModelData.name); 58 | // definition = new Definition(BpmnModelData.name, bpmnModelData.source, logger); 59 | console.log(definition); 60 | return definition; 61 | }); 62 | } 63 | function importAll() { 64 | return __awaiter(this, void 0, void 0, function* () { 65 | const server = new __1.BPMNServer(configuration_1.configuration, logger); 66 | const defs = server.definitions; 67 | const list = yield defs.getList(); 68 | list.forEach(model => { 69 | importModel(model); 70 | }); 71 | }); 72 | } 73 | function importModel(name) { 74 | return __awaiter(this, void 0, void 0, function* () { 75 | const server = new __1.BPMNServer(configuration_1.configuration, logger); 76 | const defs = server.definitions; 77 | const source = yield defs.getSource(name); 78 | const svg = yield defs.getSVG(name); 79 | const mds = server.definitions; 80 | mds.save(name, source, svg); 81 | }); 82 | } 83 | function findEvents(query) { 84 | return __awaiter(this, void 0, void 0, function* () { 85 | const server = new __1.BPMNServer(configuration_1.configuration, logger); 86 | const mds = server.definitions; 87 | const list = yield mds.findEvents(query); 88 | console.log(list); 89 | return list; 90 | }); 91 | } 92 | //# sourceMappingURL=process.js.map -------------------------------------------------------------------------------- /table.dmn: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 10"]]> 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 10"]]> 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const common_1 = require("./common"); 4 | const ExpressionEngine_1 = require("./ExpressionEngine"); 5 | function testCond(expr, value, res) { 6 | const engine = new ExpressionEngine_1.ExpressionEngine(); 7 | const ret = engine.evaluateCondition(expr, value); 8 | if (ret !== res) { 9 | console.log("***Error -" + expr + " for " + value + "result: " + ret + "expecting:" + res); 10 | common_1.logger.log("***Error -" + expr + " for " + value + "result: " + ret + "expecting:" + res); 11 | } 12 | return; 13 | } 14 | function testExp(expr, res) { 15 | console.log('expecting: ' + res); 16 | common_1.logger.log('expecting: ' + res); 17 | const engine = new ExpressionEngine_1.ExpressionEngine(); 18 | const ret = engine.evaluate(expr); 19 | if (ret !== res) { 20 | common_1.Options.debugExecution = true; 21 | common_1.Options.debugExpression = true; 22 | // parser.evaluateCondition(expr, value); 23 | console.log("***Error -" + expr + "result: " + ret + "expecting:" + res); 24 | common_1.logger.log("***Error -" + expr + "result: " + ret + "expecting:" + res); 25 | // throw Error("Error -" + expr + " failed for " + value); 26 | } 27 | return; 28 | } 29 | function runTest(list, category = '') { 30 | console.log(list); 31 | list.forEach(item => { 32 | const cat = item.category; 33 | console.log("Running " + cat.name); 34 | if (cat.expressions) { 35 | cat.expressions.forEach(expr => { 36 | console.log(expr); 37 | try { 38 | testExp(expr[0], expr[1]); 39 | } 40 | catch (exc) { 41 | console.log(exc); 42 | common_1.logger.log(exc.message); 43 | } 44 | }); 45 | } 46 | if (cat.conditions) { 47 | cat.conditions.forEach(expr => { 48 | console.log(expr); 49 | try { 50 | testCond(expr[0], expr[1], expr[2]); 51 | } 52 | catch (exc) { 53 | console.log(exc); 54 | common_1.logger.log(exc.message); 55 | } 56 | }); 57 | } 58 | }); 59 | } 60 | // Structure for Expression 61 | var scripts = [{ 62 | category: { 63 | name: 'tokens syntax', 64 | expressions: [ 65 | [`2 + 3 'test' > and < == or function - * () []`, 20], 66 | ["caseId", 1001], 67 | [`2 + 3`, 5], 68 | [`(2 + 3) * 4`, 20], 69 | [`4 * (2 + 3)`, 20], 70 | [`4 * (2 + (3+0))`, 20], 71 | [`2 + 3 * 4`, 14], 72 | [`3 * 4 +2`, 14], 73 | ['"high"', 'high'], 74 | [`2+3`, 5] 75 | ] 76 | } 77 | } 78 | ]; 79 | var conditions = [{ 80 | category: { 81 | name: 'tokens syntax', 82 | conditions: [ 83 | ["> 200 or < 500", 20, true], 84 | ["-20", '55', false], 85 | ["20+35", '55', true], 86 | ["> 200 or < 500", 20, true], 87 | [`'High'`, 'High', true], 88 | [`High`, 'Low', false], 89 | ["> 200 or < 500", 20, true], 90 | ["(> 200) or (< 500)", 20, true], 91 | ["(in ('abc','xyz-abc')", 'abc', true], 92 | ["(in ('abc','xyz-abc') ) and startsWith('a')", 'abc', true], 93 | ["in ('abc','xyz-abc','another entry', 9)", "abc", true], 94 | ["(2+3)", '5', true], 95 | ["2+3", '5', true], 96 | ["2*4", '8', true], 97 | ["(2+3)*4", '20', true], 98 | ["(in (abc,'xyz-abc') ) and startsWith('a')", 'abc', true], 99 | ["in (abc,'xyz-abc') and startsWith('a')", 'abc', true], 100 | ["75.25", '75', false], 101 | //["75.25", '75.25', true], 102 | ["2,075.25", '75', false], 103 | ["2,075.25", '2075.25', true], 104 | ["-20", '-20', true], 105 | [">=75", '75', true], 106 | ["<=55", '55', true], 107 | ["==55", '55', true], 108 | ["2 + 3", '5', true], 109 | ["> 200 or < 500", 20, true], 110 | ["object.fun('test')", '75', true], 111 | ["5 + object.fun('test')", '75', true], 112 | ["in (abc,'xyz-abc','another entry')", "abc", true], 113 | ["not in (abc,'xyz-abc') ", 'abc', true], 114 | ["in (abc,'xyz-abc') and startsWith('a') ", 'abc', true], 115 | ["in (abc,'xyz-abc') and not startsWith('a') ", 'abc', false], 116 | ["in (abc,'xyz-abc') and startsWith('a') and 3 ", 'abc', false], 117 | ["75", 'not 75', false], 118 | ["'High'", 'High', true], 119 | ["in (abc,'xyz-abc','another entry')", "abc", true], 120 | ["between ( 95 , 2500.0 )", 200, true], 121 | ] 122 | } 123 | } 124 | ]; 125 | common_1.Options.debugTokens = true; 126 | common_1.Options.debugExpression = true; 127 | common_1.Options.debugExecution = true; 128 | testCond(`$ not 10 and $<500`, 20, true); 129 | //testExp(`20 <500 `, true); 130 | //testExp(`2 + 3`, true); 131 | //main(); 132 | //testExp(` in ('1','2','3')`, null); 133 | //testExp(` (1> $v1) and funct (v1 , 2 , 3) startsWith "abc12$@!3z"`, null); 134 | //testExp(` (1>2) and funct (v1 , 2 , 3) `, null); 135 | //testExp(` between a and b `, null); 136 | // make between an operator 137 | // operators: type: 138 | // L 0-1 139 | // R 0-2 140 | /*console.log(process.argv); 141 | var args = process.argv; 142 | if (args.length > 4) { 143 | console.log('testing condition ' + args[2], args[3], args[4]); 144 | // testCond(args[2], args[3], args[4]); 145 | } 146 | else if (args.length > 3) { 147 | console.log('testing expression' + args[2], args[3]); 148 | // testExp(args[2], args[3]); 149 | } 150 | */ 151 | function main() { 152 | common_1.logger.log("starting"); 153 | runTest(scripts); 154 | runTest(conditions); 155 | common_1.logger.save("./parser.log"); 156 | } 157 | //# sourceMappingURL=test.js.map -------------------------------------------------------------------------------- /test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"test.js","sourceRoot":"","sources":["test.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /test.txt.errors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "tree": [ 4 | "0->Root #0 ", 5 | "1-->Binary #7 and ", 6 | "2--->Call #1 in ", 7 | "3---->Bracket #2 ( ", 8 | "4----->Literal #3 abc ", 9 | "4----->Operator #4 , ", 10 | "4----->Literal #5 xyz-abc ", 11 | "2--->Call #8 startsWith ", 12 | "3---->Bracket #9 ( ", 13 | "4----->Literal #10 a " 14 | ], 15 | "newTree": [], 16 | "tests": [ 17 | "'75', true", 18 | "//", 19 | "//" 20 | ], 21 | "errors": [ 22 | "***Error -in ('abc','xyz-abc') and startsWith('a') for 75 result: false expecting:" 23 | ], 24 | "type": "Condition", 25 | "comments": [], 26 | "expr": "in ('abc','xyz-abc') and startsWith('a')", 27 | "newMask": "aa ##aaa###aaa#aaa## aaa aaaaaaaaaa##a##", 28 | "maskDiff": "", 29 | "mask": "aa ##aaa###aaa#aaa## aaa aaaaaaaaaa##a##" 30 | }, 31 | { 32 | "tree": [], 33 | "newTree": [], 34 | "tests": [ 35 | "'75', true" 36 | ], 37 | "errors": [ 38 | "Cannot read property 'funt' of undefined" 39 | ], 40 | "type": "Condition", 41 | "comments": [], 42 | "expr": "obj.funt('test')", 43 | "mask": "aaaaaaaa##aaaa##", 44 | "newMask": "aaaaaaaa##aaaa##", 45 | "maskDiff": "" 46 | }, 47 | { 48 | "tree": [ 49 | "0->Root #0 result= ", 50 | "1-->Call #1 object.fun result= ", 51 | "2--->Bracket #2 ( ", 52 | "3---->Literal #3 test " 53 | ], 54 | "newTree": [], 55 | "tests": [ 56 | "'75', true" 57 | ], 58 | "errors": [], 59 | "type": "Condition", 60 | "comments": [], 61 | "expr": "object.fun('test')", 62 | "mask": "aaaaaaaaaa##aaaa##", 63 | "newMask": "aaaaaaaaaa##aaaa##", 64 | "maskDiff": "" 65 | }, 66 | { 67 | "tree": [ 68 | "0->Root #0 ", 69 | "1-->Operator #2 + result=<6> ", 70 | "2--->Literal #1 5 ", 71 | "2--->Call #3 object.fun result= ", 72 | "3---->Bracket #4 ( ", 73 | "4----->Literal #5 test " 74 | ], 75 | "newTree": [], 76 | "tests": [ 77 | "'75', true" 78 | ], 79 | "errors": [ 80 | "***Error -5 + object.fun('test') for 75 result: false expecting:" 81 | ], 82 | "type": "Condition", 83 | "comments": [ 84 | "", 85 | "" 86 | ], 87 | "expr": "5 + object.fun('test')", 88 | "mask": "N # aaaaaaaaaa##aaaa##", 89 | "newMask": "N # aaaaaaaaaa##aaaa##", 90 | "maskDiff": "" 91 | } 92 | ] -------------------------------------------------------------------------------- /test.txterrors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "tree": [ 4 | "0->Root #0 ", 5 | "1-->Bracket #1 (", 6 | "1-->Call #2 in", 7 | "2--->Bracket #3 (", 8 | "3---->Literal #4 abc", 9 | "3---->Operator #5 ,", 10 | "3---->Literal #6 xyz-abc", 11 | "1-->Binary #9 and", 12 | "2--->Call #10 startsWith", 13 | "3---->Bracket #11 (", 14 | "4----->Literal #12 a", 15 | "2--->Operator #8 )" 16 | ], 17 | "newTree": [], 18 | "tests": [ 19 | "'abc', true ", 20 | "" 21 | ], 22 | "errors": [ 23 | "***Error -(in ('abc','xyz-abc') ) and startsWith('a') for abc result: undefined expecting:" 24 | ], 25 | "type": "Condition", 26 | "comments": [ 27 | "-", 28 | "-" 29 | ], 30 | "expr": "(in ('abc','xyz-abc') ) and startsWith('a')", 31 | "mask": "#aa ##aaa###aaa#aaa## # aaa aaaaaaaaaa##a##", 32 | "newMask": "#aa ##aaa###aaa#aaa## # aaa aaaaaaaaaa##a##" 33 | }, 34 | { 35 | "tree": [ 36 | "0->Root #0 ", 37 | "1-->Bracket #1 (", 38 | "1-->Call #2 in", 39 | "2--->Bracket #3 (", 40 | "3---->Text #4 abc", 41 | "3---->Operator #5 ,", 42 | "3---->Literal #6 xyz-abc", 43 | "1-->Binary #9 and", 44 | "2--->Call #10 startsWith", 45 | "3---->Bracket #11 (", 46 | "4----->Literal #12 a", 47 | "2--->Operator #8 )" 48 | ], 49 | "newTree": [], 50 | "tests": [ 51 | "'abc', true " 52 | ], 53 | "errors": [ 54 | "***Error -(in (abc,'xyz-abc') ) and startsWith('a') for abc result: undefined expecting:" 55 | ], 56 | "type": "Condition", 57 | "comments": [ 58 | "-", 59 | "-" 60 | ], 61 | "expr": "(in (abc,'xyz-abc') ) and startsWith('a')", 62 | "mask": "#aa #aaa##aaa#aaa## # aaa aaaaaaaaaa##a##", 63 | "newMask": "#aa #aaa##aaa#aaa## # aaa aaaaaaaaaa##a##" 64 | }, 65 | { 66 | "tree": [ 67 | "0->Root #0 ", 68 | "1-->Operator #1 ==", 69 | "1-->Literal #2 55" 70 | ], 71 | "newTree": [], 72 | "tests": [ 73 | "'55', true", 74 | "" 75 | ], 76 | "errors": [ 77 | "***Error -==55 for 55 result: false expecting:" 78 | ], 79 | "type": "Condition", 80 | "comments": [ 81 | "-", 82 | "-" 83 | ], 84 | "expr": "==55", 85 | "mask": "##NN", 86 | "newMask": "##NN" 87 | }, 88 | { 89 | "tree": [ 90 | "0->Root #0 ", 91 | "1-->Call #1 object.fun", 92 | "2--->Bracket #2 (", 93 | "3---->Literal #3 test" 94 | ], 95 | "newTree": [], 96 | "tests": [ 97 | "'75', true" 98 | ], 99 | "errors": [ 100 | "***Error -object.fun('test') for 75 result: undefined expecting:" 101 | ], 102 | "type": "Condition", 103 | "comments": [ 104 | "-", 105 | "-" 106 | ], 107 | "expr": "object.fun('test')", 108 | "mask": "aaaaaaaaaa##aaaa##", 109 | "newMask": "aaaaaaaaaa##aaaa##" 110 | }, 111 | { 112 | "tree": [ 113 | "0->Root #0 ", 114 | "1-->Operator #2 +", 115 | "2--->Call #3 object.fun", 116 | "3---->Bracket #4 (", 117 | "4----->Literal #5 test", 118 | "2--->Literal #1 5" 119 | ], 120 | "newTree": [], 121 | "tests": [ 122 | "'75', true", 123 | "" 124 | ], 125 | "errors": [ 126 | "***Error -5 + object.fun('test') for 75 result: object.fun5 expecting:" 127 | ], 128 | "type": "Condition", 129 | "comments": [ 130 | "-", 131 | "-" 132 | ], 133 | "expr": "5 + object.fun('test')", 134 | "mask": "N # aaaaaaaaaa##aaaa##", 135 | "newMask": "N # aaaaaaaaaa##aaaa##" 136 | }, 137 | { 138 | "tree": [ 139 | "0->Root #0 ", 140 | "1-->Binary #1 not", 141 | "2--->Call #2 in", 142 | "3---->Bracket #3 (", 143 | "4----->Text #4 abc", 144 | "4----->Operator #5 ,", 145 | "4----->Literal #6 xyz-abc" 146 | ], 147 | "newTree": [], 148 | "tests": [ 149 | "'abc', true" 150 | ], 151 | "errors": [ 152 | "***Error -not in (abc,'xyz-abc') for abc result: false expecting:" 153 | ], 154 | "type": "Condition", 155 | "comments": [ 156 | "-", 157 | "-" 158 | ], 159 | "expr": "not in (abc,'xyz-abc') ", 160 | "mask": "aaa aa #aaa##aaa#aaa## ", 161 | "newMask": "aaa aa #aaa##aaa#aaa## " 162 | }, 163 | { 164 | "tree": [ 165 | "0->Root #0 ", 166 | "1-->Binary #7 and", 167 | "2--->Call #8 startsWith", 168 | "3---->Bracket #9 (", 169 | "4----->Literal #10 a", 170 | "2--->Call #1 in", 171 | "3---->Bracket #2 (", 172 | "4----->Text #3 abc", 173 | "4----->Operator #4 ,", 174 | "4----->Literal #5 xyz-abc" 175 | ], 176 | "newTree": [], 177 | "tests": [ 178 | "'abc', true // not , in, 'abc', 'xyz-abc'" 179 | ], 180 | "errors": [ 181 | "***Error -in (abc,'xyz-abc') and startsWith('a') for abc result: true expecting:" 182 | ], 183 | "type": "Condition", 184 | "comments": [ 185 | "-", 186 | "-" 187 | ], 188 | "expr": "in (abc,'xyz-abc') and startsWith('a') ", 189 | "mask": "aa #aaa##aaa#aaa## aaa aaaaaaaaaa##a## ", 190 | "newMask": "aa #aaa##aaa#aaa## aaa aaaaaaaaaa##a## " 191 | }, 192 | { 193 | "tree": [ 194 | "0->Root #0 ", 195 | "1-->Binary #7 and", 196 | "2--->Binary #8 not", 197 | "3---->Call #1 in", 198 | "4----->Bracket #2 (", 199 | "5------>Text #3 abc", 200 | "5------>Operator #4 ,", 201 | "5------>Literal #5 xyz-abc", 202 | "1-->Call #9 startsWith", 203 | "2--->Bracket #10 (", 204 | "3---->Literal #11 a" 205 | ], 206 | "newTree": [], 207 | "tests": [ 208 | "'abc', false // not , in, 'abc', 'xyz-abc'" 209 | ], 210 | "errors": [ 211 | "***Error -in (abc,'xyz-abc') and not startsWith('a') for abc result: false expecting:" 212 | ], 213 | "type": "Condition", 214 | "comments": [ 215 | "-", 216 | "-" 217 | ], 218 | "expr": "in (abc,'xyz-abc') and not startsWith('a') ", 219 | "mask": "aa #aaa##aaa#aaa## aaa aaa aaaaaaaaaa##a## ", 220 | "newMask": "aa #aaa##aaa#aaa## aaa aaa aaaaaaaaaa##a## " 221 | } 222 | ] -------------------------------------------------------------------------------- /testDT.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /testDT.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | const DecisionTable_1 = require("./DecisionTable"); 13 | const simple = require("dmn-moddle"); 14 | const index_1 = require("./index"); 15 | const fs = require('fs'); 16 | const DmnModdle = simple(); 17 | //test(); 18 | //testDT(); 19 | testExprs(); 20 | function testExprs() { 21 | return __awaiter(this, void 0, void 0, function* () { 22 | const exprs = [ 23 | ['1>5', false], 24 | ['3=5', false], 25 | ['3=3', true], 26 | ['2 in[1..3]', true], 27 | ['2 in(1,2,3)', true], 28 | ['8 in(1,2,3)', false], 29 | ['25 between 20 and 5000', true], 30 | ['25000.25 between 20 and 5000', false], 31 | ['a in[1..3]', true, { a: 2 }], 32 | ['function(age)( age < 21)', true, { a: 2 }], 33 | ]; 34 | const conds = [ 35 | ['>5', 1, false], 36 | ['5', 3, false], 37 | ['not (5)', 3, true], 38 | ['not ("Manager")', "Employee", true], 39 | // ['=3',3, true], failed in parsing 40 | // ['2 in[1..3]',2, true], failed 41 | ["'Low','Medium','High'", 'Medium', true], 42 | ]; 43 | var i; 44 | for (i = 0; i < exprs.length; i++) { 45 | const expr = exprs[i][0]; 46 | const exp = exprs[i][1]; 47 | let context = {}; 48 | if (exprs[i][2]) { 49 | context = exprs[i][2]; 50 | console.log(context); 51 | } 52 | const res = yield index_1.ExecuteExpression(expr, context); 53 | console.log(`expr: ${expr} res: ${res.toString()} vs ${exp}`); 54 | } 55 | for (i = 0; i < conds.length; i++) { 56 | const cond = conds[i][0]; 57 | const val = conds[i][1]; 58 | const exp = conds[i][2]; 59 | let context = {}; 60 | if (exprs[i][3]) { 61 | context = exprs[i][3]; 62 | console.log(context); 63 | } 64 | else { 65 | context = { input: val }; 66 | } 67 | console.log(cond); 68 | console.log(context); 69 | const res = yield index_1.ExecuteCondition(cond, 'input', context); 70 | if (res !== null) 71 | console.log(`condition: ${cond} res: ${res.toString()} vs ${exp}`); 72 | } 73 | }); 74 | } 75 | function test() { 76 | return __awaiter(this, void 0, void 0, function* () { 77 | console.log('testDT'); 78 | // console.log(simple); 79 | //testDT(); 80 | // console.log(simple()); 81 | const defs = yield read('table.dmn', 'definitions'); 82 | console.log(defs); 83 | }); 84 | } 85 | function read(fileName, root = 'dmn:Definitions') { 86 | return __awaiter(this, void 0, void 0, function* () { 87 | return new Promise((resolve, reject) => { 88 | const file = fs.readFileSync(fileName, 'utf8'); 89 | DmnModdle.fromXML(file, root, (err, definitions) => { 90 | if (err) { 91 | reject(err); 92 | } 93 | resolve(definitions); 94 | }); 95 | }); 96 | }); 97 | } 98 | function testDT() { 99 | console.log('====='); 100 | const dt1Json = { 101 | name: "Banking", 102 | hitPolicy: DecisionTable_1.HIT_POLICY.Any, 103 | conditionVars: [ 104 | { name: 'clientType', type: 'string' }, 105 | { name: 'onDeposit', type: 'money' }, 106 | { name: 'netWorth', type: 'money' }, 107 | ], 108 | actionVars: [ 109 | { name: 'category', type: 'string' } 110 | ], 111 | rules: [ 112 | // clientType, OnDeposit, NetWorth, -> category 113 | [1, `"Business"`, `<100000 `, `"High"`, `"High Value Business"`], 114 | [2, `"Business"`, `>=100000 `, `not "High"`, `"High Value Business"`], 115 | [3, `"Business"`, `<100000 `, `not ("High")`, `Business Standard"`], 116 | [4, `"Private"`, `>=20000 `, ` "High"`, `"Personal Wealth Management"`], 117 | [5, `"Private"`, `>=20000 `, `not ("High")`, `"Personal Wealth Management"`], 118 | [6, `"Private"`, `<20000 `, `-`, `"Personal Standard"`] 119 | ] 120 | }; 121 | const dt2Json = { 122 | name: 'sample', 123 | hitPolicy: 'Unqiue', 124 | "conditionVars": [ 125 | { 126 | "name": "clientType", 127 | "type": "string" 128 | }, 129 | { 130 | "name": "onDeposit", 131 | "type": "money" 132 | }, 133 | { 134 | "name": "netWorth", 135 | "type": "money" 136 | } 137 | ], 138 | "actionVars": [ 139 | { 140 | "name": "category", 141 | "type": "string" 142 | } 143 | ], 144 | "rules": [ 145 | [ 146 | 1, 147 | "\"Business\"", 148 | "<100000 ", 149 | "\"High\"", 150 | "\"High Value Business\"" 151 | ], 152 | [2, 153 | "\"Business\"", 154 | ">=100000 ", 155 | "not \"High\"", 156 | "\"High Value Business\"" 157 | ], 158 | [ 159 | 3, 160 | "\"Business\"", 161 | "<100000 ", 162 | "not (\"High\")", 163 | "Business Standard\"" 164 | ], 165 | [ 166 | 4, 167 | "\"Private\"", 168 | ">=20000 ", 169 | " \"High\"", 170 | "\"Personal Wealth Management\"" 171 | ], 172 | [ 173 | 5, 174 | "\"Private\"", 175 | ">=20000 ", 176 | "not (\"High\")", 177 | "\"Personal Wealth Management\"" 178 | ], 179 | [ 180 | 6, 181 | "\"Private\"", 182 | "<20000 ", 183 | "-", 184 | "\"Personal Standard\"" 185 | ] 186 | ] 187 | }; 188 | const values = { clientType: 'Business', onDeposit: 50000, netWorth: 'High' }; 189 | const dt1 = new DecisionTable_1.DecisionTable(dt1Json); 190 | const res1 = dt1.evaluate(values); 191 | console.log('compile'); 192 | //console.log(decisionTable.compile()); 193 | //console.log(decisionTable.saveAsJson()); 194 | const res = index_1.ExecuteDecisionTable({ definition: dt2Json, data: values, options: null, loadFrom: null }); 195 | console.log(res); 196 | return; 197 | const dt2 = new DecisionTable_1.DecisionTable(dt2Json); 198 | const res2 = dt2.evaluate(values); 199 | console.log(JSON.stringify(res1, null, 2)); 200 | console.log(JSON.stringify(res2, null, 2)); 201 | } 202 | /* Syntax: 203 | Strings: 204 | ------- quotes are optional if no space 205 | () are optional 206 | value: 207 | 'value' 208 | value 209 | "value" 210 | condition: 211 | value means == value 212 | in (val1,val2,val3) 213 | not in (val1,val2,val3) 214 | startsWith('abc') 215 | endsWith('abc') 216 | contains('abc') 217 | 218 | and 219 | or 220 | 221 | numbers: 222 | value: 223 | numeric value 224 | , are ignored 225 | $ is ignored 226 | > value 227 | < value 228 | <= 229 | >= 230 | between value1, value2 231 | between value1 and value2 232 | 233 | symbols 234 | 235 | */ 236 | function trimParam(param) { 237 | if (param.startsWith('"') && param.endsWith('"')) 238 | return param.substring(1, param.length - 1); 239 | if (param.startsWith("'") && param.endsWith("'")) 240 | return param.substring(1, param.length - 1); 241 | else 242 | return param.trim(); 243 | } 244 | //# sourceMappingURL=testDT.js.map -------------------------------------------------------------------------------- /testDT.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"testDT.js","sourceRoot":"","sources":["testDT.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /testDT.ts: -------------------------------------------------------------------------------- 1 | import { HIT_POLICY, DecisionTable } from "./DecisionTable"; 2 | import * as simple from 'dmn-moddle'; 3 | import { ExecuteDecisionTable , ExecuteExpression , ExecuteCondition } from './index'; 4 | 5 | const fs = require('fs'); 6 | const DmnModdle = simple(); 7 | 8 | //test(); 9 | //testDT(); 10 | testExprs(); 11 | async function testExprs() { 12 | const exprs = [ 13 | ['1>5', false], 14 | ['3=5', false], 15 | ['3=3', true ], 16 | ['2 in[1..3]', true], 17 | ['2 in(1,2,3)', true], 18 | ['8 in(1,2,3)', false], 19 | ['25 between 20 and 5000', true], 20 | ['25000.25 between 20 and 5000', false], 21 | ['a in[1..3]', true, { a: 2 }], 22 | ['function(age)( age < 21)', true, { a: 2 }], 23 | 24 | 25 | ]; 26 | const conds = [ 27 | ['>5', 1, false], 28 | ['5',3, false], 29 | ['not (5)', 3, true], 30 | ['not ("Manager")', "Employee", true], 31 | // ['=3',3, true], failed in parsing 32 | // ['2 in[1..3]',2, true], failed 33 | ["'Low','Medium','High'",'Medium', true], 34 | // ['in(1,2,3)',7, false], 35 | // ['between 20 and 5000', 25, true], 36 | // ['between 20 and 5000',25000, false], */ 37 | ]; 38 | var i; 39 | for (i = 0; i < exprs.length; i++) { 40 | const expr = exprs[i][0]; 41 | const exp = exprs[i][1]; 42 | let context = {}; 43 | if (exprs[i][2]) { 44 | context = exprs[i][2]; 45 | console.log(context); 46 | } 47 | const res = await ExecuteExpression(expr,context); 48 | console.log(`expr: ${expr} res: ${res.toString()} vs ${exp}`); 49 | } 50 | for (i = 0; i < conds.length; i++) { 51 | const cond = conds[i][0]; 52 | const val = conds[i][1]; 53 | const exp = conds[i][2]; 54 | let context = {}; 55 | if (exprs[i][3]) { 56 | context = exprs[i][3]; 57 | console.log(context); 58 | } 59 | else { 60 | context = { input: val }; 61 | } 62 | console.log(cond); 63 | console.log(context); 64 | const res = await ExecuteCondition(cond, 'input', context); 65 | if (res!==null) 66 | console.log(`condition: ${cond} res: ${res.toString()} vs ${exp}`); 67 | } 68 | } 69 | async function test() { 70 | console.log('testDT'); 71 | // console.log(simple); 72 | //testDT(); 73 | 74 | // console.log(simple()); 75 | 76 | const defs = await read('table.dmn','definitions'); 77 | 78 | 79 | console.log(defs); 80 | } 81 | 82 | 83 | async function read(fileName, root = 'dmn:Definitions') { 84 | return new Promise((resolve, reject) => { 85 | const file = fs.readFileSync(fileName, 'utf8'); 86 | 87 | DmnModdle.fromXML(file, root, (err, definitions) => { 88 | if (err) { 89 | reject(err); 90 | } 91 | 92 | resolve(definitions); 93 | }); 94 | }); 95 | } 96 | function testDT() { 97 | console.log('====='); 98 | 99 | const dt1Json = 100 | { 101 | name: "Banking", 102 | hitPolicy: HIT_POLICY.Any, 103 | conditionVars: 104 | [ 105 | { name: 'clientType', type: 'string' }, 106 | { name: 'onDeposit', type: 'money' }, 107 | { name: 'netWorth', type: 'money' }, 108 | ], 109 | actionVars: 110 | [ 111 | { name: 'category', type: 'string' } 112 | ] , 113 | rules: [ 114 | // clientType, OnDeposit, NetWorth, -> category 115 | [1, `"Business"`, `<100000 `, `"High"`, `"High Value Business"`], 116 | [2, `"Business"`, `>=100000 `, `not "High"`, `"High Value Business"`], 117 | [3, `"Business"`, `<100000 `, `not ("High")`, `Business Standard"`], 118 | [4, `"Private"`, `>=20000 `, ` "High"`, `"Personal Wealth Management"`], 119 | [5, `"Private"`, `>=20000 `, `not ("High")`, `"Personal Wealth Management"`], 120 | [6, `"Private"`, `<20000 `, `-`, `"Personal Standard"`] 121 | ] 122 | }; 123 | 124 | const dt2Json = 125 | { 126 | name: 'sample', 127 | hitPolicy: 'Unqiue', 128 | "conditionVars": [ 129 | { 130 | "name": "clientType", 131 | "type": "string" 132 | }, 133 | { 134 | "name": "onDeposit", 135 | "type": "money" 136 | }, 137 | { 138 | "name": "netWorth", 139 | "type": "money" 140 | } 141 | ], 142 | "actionVars": [ 143 | { 144 | "name": "category", 145 | "type": "string" 146 | } 147 | ] , 148 | "rules": [ 149 | [ 150 | 1, 151 | "\"Business\"", 152 | "<100000 ", 153 | "\"High\"", 154 | "\"High Value Business\"" 155 | ], 156 | [ 2, 157 | "\"Business\"", 158 | ">=100000 ", 159 | "not \"High\"", 160 | "\"High Value Business\"" 161 | ], 162 | [ 163 | 3, 164 | "\"Business\"", 165 | "<100000 ", 166 | "not (\"High\")", 167 | "Business Standard\"" 168 | ], 169 | [ 170 | 4, 171 | "\"Private\"", 172 | ">=20000 ", 173 | " \"High\"", 174 | "\"Personal Wealth Management\"" 175 | ], 176 | [ 177 | 5, 178 | "\"Private\"", 179 | ">=20000 ", 180 | "not (\"High\")", 181 | "\"Personal Wealth Management\"" 182 | ], 183 | [ 184 | 6, 185 | "\"Private\"", 186 | "<20000 ", 187 | "-", 188 | "\"Personal Standard\"" 189 | ] 190 | ] 191 | }; 192 | 193 | const values = { clientType: 'Business', onDeposit: 50000, netWorth: 'High' }; 194 | 195 | 196 | const dt1= new DecisionTable(dt1Json); 197 | 198 | const res1 = dt1.evaluate(values); 199 | 200 | console.log('compile'); 201 | 202 | //console.log(decisionTable.compile()); 203 | 204 | //console.log(decisionTable.saveAsJson()); 205 | 206 | const res = ExecuteDecisionTable({ definition: dt2Json, data: values , options: null , loadFrom: null }); 207 | console.log(res); 208 | return; 209 | const dt2 = new DecisionTable(dt2Json); 210 | 211 | const res2=dt2.evaluate(values); 212 | 213 | console.log(JSON.stringify(res1,null,2)); 214 | console.log(JSON.stringify(res2, null, 2)); 215 | 216 | } 217 | 218 | /* Syntax: 219 | Strings: 220 | ------- quotes are optional if no space 221 | () are optional 222 | value: 223 | 'value' 224 | value 225 | "value" 226 | condition: 227 | value means == value 228 | in (val1,val2,val3) 229 | not in (val1,val2,val3) 230 | startsWith('abc') 231 | endsWith('abc') 232 | contains('abc') 233 | 234 | and 235 | or 236 | 237 | numbers: 238 | value: 239 | numeric value 240 | , are ignored 241 | $ is ignored 242 | > value 243 | < value 244 | <= 245 | >= 246 | between value1, value2 247 | between value1 and value2 248 | 249 | symbols 250 | 251 | */ 252 | 253 | function trimParam(param) { 254 | if (param.startsWith('"') && param.endsWith('"')) 255 | return param.substring(1, param.length - 1); 256 | if (param.startsWith("'") && param.endsWith("'")) 257 | return param.substring(1, param.length - 1); 258 | else 259 | return param.trim(); 260 | } 261 | -------------------------------------------------------------------------------- /testGoogle.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /testGoogle.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | const google_1 = require("./google"); 13 | const DecisionTable_1 = require("./DecisionTable"); 14 | /* 15 | * Decison Vaction Allowance Hit Policy Collect+ 16 | Variables Input Input Output Annotation 17 | Variable YearsOfService EmployeeType Vacation Annotation 18 | data type integer string integer 19 | Rules: 20 | 1 - "Contract" 0 21 | 2 - 'Executive" 4 22 | 3 - 'Employee" 2 23 | 4 >10 in ['Employee','Executive'] 1 Additional Week for 10 years 24 | 5 >20 in ['Employee','Executive'] 1 Another week after 20 years 25 | 26 | 27 | 28 | Tests 5 "Employee" 29 | */ 30 | function main() { 31 | return __awaiter(this, void 0, void 0, function* () { 32 | const importer = new google_1.GoogleSheets(); 33 | yield importer.init(); 34 | var id = '13O_4UhOKB6YPybQaoRdhMqopqa0RjG8qXIIyRU7Q890'; ///edit#gid=1076308066'; 35 | var sheetId = '1076308066'; 36 | var { decisionTable: dtDefinition, tests } = yield importer.getRule(id, 'Vacation'); 37 | console.log('main start1'); 38 | console.log(dtDefinition); 39 | console.log('tests'); 40 | console.log(tests); 41 | var { decisionTable, results } = yield DecisionTable_1.DecisionTable.execute(dtDefinition, tests); 42 | console.log('results'); 43 | console.log(results); 44 | results.forEach(record => { 45 | console.log(record.input); 46 | console.log(record); 47 | // console.log("Vacation:" + record.actions.Vacation + " for row # " + record.input['__ID']); 48 | }); 49 | const fileName = 'tests\\Vacation.json'; 50 | //fs.writeFile(fileName , decisionTable.asJson() , function (err) { }); 51 | decisionTable.save(fileName); 52 | const dt2 = DecisionTable_1.DecisionTable.load(fileName); 53 | //dt2.evaluate(tests[0]); 54 | }); 55 | } 56 | main(); 57 | //# sourceMappingURL=testGoogle.js.map -------------------------------------------------------------------------------- /testGoogle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"testGoogle.js","sourceRoot":"","sources":["testGoogle.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,qCAAwC;AAExC,mDAAgD;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,SAAe,IAAI;;QAGf,MAAM,QAAQ,GAAG,IAAI,qBAAY,EAAE,CAAC;QACpC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEtB,IAAI,EAAE,GAAG,8CAA8C,CAAC,CAAA,wBAAwB;QAChF,IAAI,OAAO,GAAG,YAAY,CAAC;QAC3B,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACpF,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,MAAM,6BAAa,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAClF,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACtB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACrB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC5B,oGAAoG;QAChG,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,sBAAsB,CAAC;QACxC,uEAAuE;QACvE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,6BAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,yBAAyB;IAE7B,CAAC;CAAA;AAED,IAAI,EAAE,CAAC"} -------------------------------------------------------------------------------- /testGoogle.ts: -------------------------------------------------------------------------------- 1 | import { GoogleSheets } from './google'; 2 | 3 | import { DecisionTable } from './DecisionTable'; 4 | 5 | /* 6 | * Decison Vaction Allowance Hit Policy Collect+ 7 | Variables Input Input Output Annotation 8 | Variable YearsOfService EmployeeType Vacation Annotation 9 | data type integer string integer 10 | Rules: 11 | 1 - "Contract" 0 12 | 2 - 'Executive" 4 13 | 3 - 'Employee" 2 14 | 4 >10 in ['Employee','Executive'] 1 Additional Week for 10 years 15 | 5 >20 in ['Employee','Executive'] 1 Another week after 20 years 16 | 17 | 18 | 19 | Tests 5 "Employee" 20 | */ 21 | async function main() { 22 | 23 | 24 | const importer = new GoogleSheets(); 25 | await importer.init(); 26 | 27 | var id = '13O_4UhOKB6YPybQaoRdhMqopqa0RjG8qXIIyRU7Q890';///edit#gid=1076308066'; 28 | var sheetId = '1076308066'; 29 | var { decisionTable: dtDefinition, tests } = await importer.getRule(id, 'Vacation'); 30 | console.log('main start1'); 31 | console.log(dtDefinition); 32 | console.log('tests'); 33 | console.log(tests); 34 | var { decisionTable, results } = await DecisionTable.execute(dtDefinition, tests); 35 | console.log('results') 36 | console.log(results); 37 | results.forEach(record => { 38 | console.log(record.input); 39 | console.log(record); 40 | // console.log("Vacation:" + record.actions.Vacation + " for row # " + record.input['__ID']); 41 | }); 42 | const fileName = 'tests\\Vacation.json'; 43 | //fs.writeFile(fileName , decisionTable.asJson() , function (err) { }); 44 | decisionTable.save(fileName); 45 | const dt2 = DecisionTable.load(fileName); 46 | //dt2.evaluate(tests[0]); 47 | 48 | } 49 | 50 | main(); -------------------------------------------------------------------------------- /testcalc: -------------------------------------------------------------------------------- 1 | 2+3 -------------------------------------------------------------------------------- /tests/Condition-Numbers.bak: -------------------------------------------------------------------------------- 1 | $Condition 2 | not 3 3 | $Tests 4 | $mask 5 | aaa N 6 | $Tree 7 | 0->Root #0 8 | 1-->Binary #1 not 9 | 2--->Literal #2 3 10 | $Condition 11 | 3+5 12 | $Tests 13 | 5,false 14 | 8,true 15 | 10,false 16 | $mask 17 | N#N 18 | $Tree 19 | 0->Root #0 20 | 1-->Operator #2 + result=<8> 21 | 2--->Literal #1 3 22 | 2--->Literal #3 5 23 | $Condition 24 | >20 25 | $Tests 26 | 5,false 27 | 25,true 28 | $mask 29 | #NN 30 | $Tree 31 | 0->Root #0 result= 32 | 1-->Operator #1 > result= 33 | 2--->Literal #2 20 34 | $Condition 35 | >30 and < 50 36 | $Tests 37 | 40,true 38 | 10,false 39 | $mask 40 | #NN aaa # NN 41 | $Tree 42 | 0->Root #0 43 | 1-->Binary #3 and 44 | 2--->Operator #1 > 45 | 3---->Literal #2 30 46 | 2--->Operator #4 < result= 47 | 3---->Literal #5 50 48 | $Condition 49 | > 200 or < 500 50 | $Tests 51 | 20, true 52 | $mask 53 | # NNN aa # NNN 54 | $Tree 55 | 0->Root #0 result= 56 | 1-->Binary #3 or result= 57 | 2--->Operator #1 > 58 | 3---->Literal #2 200 59 | 2--->Operator #4 < result= 60 | 3---->Literal #5 500 61 | $Condition 62 | 50 63 | $Tests 64 | 55, false 65 | $mask 66 | NN 67 | $Tree 68 | 0->Root #0 69 | 1-->Literal #1 50 70 | $Condition 71 | 20+35 72 | $Tests 73 | 55, true 74 | $mask 75 | NN#NN 76 | $Tree 77 | 0->Root #0 result= 78 | 1-->Operator #2 + result=<55> 79 | 2--->Literal #1 20 80 | 2--->Literal #3 35 81 | $Condition 82 | > 200 or < 500 83 | $Tests 84 | 20, true 85 | $mask 86 | # NNN aa # NNN 87 | $Tree 88 | 0->Root #0 result= 89 | 1-->Binary #3 or result= 90 | 2--->Operator #1 > 91 | 3---->Literal #2 200 92 | 2--->Operator #4 < result= 93 | 3---->Literal #5 500 94 | $Condition 95 | > 200 or < 500 96 | $Tests 97 | 20, true 98 | $mask 99 | # NNN aa # NNN 100 | $Tree 101 | 0->Root #0 result= 102 | 1-->Binary #3 or result= 103 | 2--->Operator #1 > 104 | 3---->Literal #2 200 105 | 2--->Operator #4 < result= 106 | 3---->Literal #5 500 107 | $Condition 108 | (> 200) or (< 500) 109 | $Tests 110 | 20, true 111 | $mask 112 | ## NNN# aa ## NNN# 113 | $Tree 114 | 0->Root #0 result= 115 | 1-->Binary #5 or result= 116 | 2--->Bracket #1 ( 117 | 3---->Operator #2 > 118 | 4----->Literal #3 200 119 | 2--->Bracket #6 ( result= 120 | 3---->Operator #7 < result= 121 | 4----->Literal #8 500 122 | $Condition 123 | (2+3) 124 | $Tests 125 | 5, true 126 | $mask 127 | #N#N# 128 | $Tree 129 | 0->Root #0 result= 130 | 1-->Bracket #1 ( result=<5> 131 | 2--->Operator #3 + result=<5> 132 | 3---->Literal #2 2 133 | 3---->Literal #4 3 134 | $Condition 135 | 2+3 136 | $Tests 137 | 5, true 138 | $mask 139 | N#N 140 | $Tree 141 | 0->Root #0 result= 142 | 1-->Operator #2 + result=<5> 143 | 2--->Literal #1 2 144 | 2--->Literal #3 3 145 | $Condition 146 | 2*4 147 | $Tests 148 | 8, true 149 | 150 | $mask 151 | N#N 152 | $Tree 153 | 0->Root #0 result= 154 | 1-->Operator #2 * result=<8> 155 | 2--->Literal #1 2 156 | 2--->Literal #3 4 157 | $Condition 158 | (2+3)*4 159 | $Tests 160 | 20, true 161 | 162 | $mask 163 | #N#N##N 164 | $Tree 165 | 0->Root #0 result= 166 | 1-->Operator #6 * result=<20> 167 | 2--->Bracket #1 ( result=<5> 168 | 3---->Operator #3 + result=<5> 169 | 4----->Literal #2 2 170 | 4----->Literal #4 3 171 | 2--->Literal #7 4 172 | $Condition 173 | 75.25 174 | $Tests 175 | 75, false 176 | 75.25, true 177 | $mask 178 | NNNNN 179 | $Tree 180 | 0->Root #0 result= 181 | 1-->Literal #1 75.25 result= 182 | $Condition 183 | 2,075.25 184 | $Tests 185 | 75, false 186 | $mask 187 | N#NNNNNN 188 | $Tree 189 | 0->Root #0 190 | 1-->Literal #1 2075.25 191 | $Condition 192 | 2,075.25 193 | $Tests 194 | 2075.25, true 195 | $mask 196 | N#NNNNNN 197 | $Tree 198 | 0->Root #0 result= 199 | 1-->Literal #1 2075.25 result= 200 | $Condition 201 | - 202 | $Tests 203 | '-20', true 204 | 205 | $mask 206 | # 207 | $Tree 208 | 0->True #0 result= 209 | $Condition 210 | >=75 211 | $Tests 212 | '75', true 213 | $mask 214 | ##NN 215 | $Tree 216 | 0->Root #0 result= 217 | 1-->Operator #1 >= result= 218 | 2--->Literal #2 75 219 | $Condition 220 | <=55 221 | $Tests 222 | '55', true 223 | $mask 224 | ##NN 225 | $Tree 226 | 0->Root #0 result= 227 | 1-->Operator #1 <= result= 228 | 2--->Literal #2 55 229 | $Condition 230 | ==55 231 | $Tests 232 | '55', true 233 | 234 | $mask 235 | ##NN 236 | $Tree 237 | 0->Root #0 result= 238 | 1-->Operator #1 == result= 239 | 2--->Literal #2 55 240 | $Condition 241 | 2 + 3 242 | $Tests 243 | '5', true 244 | 245 | $mask 246 | N # N 247 | $Tree 248 | 0->Root #0 result= 249 | 1-->Operator #2 + result=<5> 250 | 2--->Literal #1 2 251 | 2--->Literal #3 3 252 | $Condition 253 | > 200 or < 500 254 | $Tests 255 | 20, true 256 | 257 | $mask 258 | # NNN aa # NNN 259 | $Tree 260 | 0->Root #0 result= 261 | 1-->Binary #3 or result= 262 | 2--->Operator #1 > 263 | 3---->Literal #2 200 264 | 2--->Operator #4 < result= 265 | 3---->Literal #5 500 266 | $Condition 267 | object.fun('test') 268 | $Tests 269 | '75', true 270 | $mask 271 | aaaaaaaaaa##aaaa## 272 | $Tree 273 | 0->Root #0 result= 274 | 1-->Call #1 object.fun result= 275 | 2--->Bracket #2 ( 276 | 3---->Literal #3 test 277 | $Condition 278 | 5 + object.fun('test') 279 | $Tests 280 | '75', true 281 | 282 | $mask 283 | N # aaaaaaaaaa##aaaa## 284 | $Tree 285 | 0->Root #0 286 | 1-->Operator #2 + result=<6> 287 | 2--->Literal #1 5 288 | 2--->Call #3 object.fun result= 289 | 3---->Bracket #4 ( 290 | 4----->Literal #5 test 291 | $Errors 292 | ***Error -5 + object.fun('test') for 75 result: false expecting: -------------------------------------------------------------------------------- /tests/Expressions2.txt.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "tree": [ 4 | "0->Root #0 result= ", 5 | "1-->Text #1 contact.name result= " 6 | ], 7 | "newTree": [ 8 | "0->Root #0 ", 9 | "1-->Text #1 contact.name " 10 | ], 11 | "tests": [ 12 | "'Mr. Hanna'" 13 | ], 14 | "errors": [ 15 | "***Error -contact.name result: undefined expecting:Mr. Hanna" 16 | ], 17 | "type": "Expression", 18 | "comments": [], 19 | "expr": "contact.name", 20 | "mask": "aaaaaaaaaaaa", 21 | "newMask": "aaaaaaaaaaaa", 22 | "maskDiff": "" 23 | }, 24 | { 25 | "tree": [ 26 | "0->Root #0 ", 27 | "1-->Bracket #1 ( ", 28 | "2--->Operator #2 > ", 29 | "3---->Literal #3 2 " 30 | ], 31 | "newTree": [], 32 | "tests": [ 33 | "5" 34 | ], 35 | "errors": [], 36 | "type": "Condition", 37 | "comments": [ 38 | "", 39 | "", 40 | "" 41 | ], 42 | "expr": "( > 2)", 43 | "mask": "# # N#", 44 | "newMask": "# # N#", 45 | "maskDiff": "" 46 | }, 47 | { 48 | "tree": [ 49 | "0->Root #0 result= ", 50 | "1-->Text #1 name result= " 51 | ], 52 | "newTree": [ 53 | "0->Root #0 ", 54 | "1-->Text #1 customer " 55 | ], 56 | "tests": [ 57 | "'Mr. Hanna'" 58 | ], 59 | "errors": [ 60 | "***Error -customer result: undefined expecting:Mr. Hanna" 61 | ], 62 | "type": "Expression", 63 | "comments": [ 64 | "", 65 | "", 66 | "" 67 | ], 68 | "expr": "customer", 69 | "mask": "aaaa", 70 | "newMask": "aaaaaaaa", 71 | "maskDiff": " XXXX" 72 | }, 73 | { 74 | "tree": [ 75 | "0->Root #0 ", 76 | "1-->Bracket #1 ( ", 77 | "2--->Binary #3 and ", 78 | "3---->Literal #2 3 ", 79 | "3---->Literal #4 2 " 80 | ], 81 | "newTree": [], 82 | "tests": [], 83 | "errors": [], 84 | "type": "Expression", 85 | "comments": [], 86 | "expr": "(3 and 2)", 87 | "mask": "#N aaa N#", 88 | "newMask": "#N aaa N#", 89 | "maskDiff": "" 90 | }, 91 | { 92 | "tree": [ 93 | "0->Root #0 result=<3> ", 94 | "1-->Bracket #1 ( result=<3> ", 95 | "2--->Literal #2 3 result=<3> ", 96 | "2--->Operator #3 > ", 97 | "3---->Literal #4 2 " 98 | ], 99 | "newTree": [ 100 | "0->Root #0 ", 101 | "1-->Bracket #1 ( ", 102 | "2--->Operator #3 > ", 103 | "3---->Literal #2 3 ", 104 | "3---->Literal #4 2 " 105 | ], 106 | "tests": [ 107 | "true" 108 | ], 109 | "errors": [ 110 | "***Error -(3 > 2) result: false expecting:true" 111 | ], 112 | "type": "Expression", 113 | "comments": [ 114 | "", 115 | "" 116 | ], 117 | "expr": "(3 > 2)", 118 | "mask": "#aa #aaa##aaa#aaa## aaa # N #", 119 | "newMask": "#N # N#", 120 | "maskDiff": " XXXXXX" 121 | }, 122 | { 123 | "tree": [ 124 | "0->Root #0 result=<600> ", 125 | "1-->Operator #8 * result=<600> ", 126 | "2--->Bracket #1 ( result=<6> ", 127 | "3---->Operator #3 + result=<6> ", 128 | "4----->Literal #2 4 ", 129 | "4----->Operator #5 - result=<2> ", 130 | "5------>Literal #4 3 ", 131 | "5------>Literal #6 1 ", 132 | "2--->Operator #10 ^ result=<100> ", 133 | "3---->Literal #9 10 ", 134 | "3---->Literal #11 2 " 135 | ], 136 | "newTree": [], 137 | "tests": [ 138 | "600" 139 | ], 140 | "errors": [], 141 | "type": "Expression", 142 | "comments": [ 143 | "" 144 | ], 145 | "expr": "(4 + 3 - 1) * 10 ^2", 146 | "mask": "#N # N # N# # NN #N", 147 | "newMask": "#N # N # N# # NN #N", 148 | "maskDiff": "" 149 | } 150 | ] -------------------------------------------------------------------------------- /tests/Vacation.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vacation Allowance", 3 | "hitPolicy": "Collect+", 4 | "conditionVars": [ 5 | { 6 | "name": "YearsOfService" 7 | }, 8 | { 9 | "name": "EmployeeType" 10 | } 11 | ], 12 | "actionVars": [ 13 | { 14 | "name": "Vacation" 15 | } 16 | ], 17 | "rules": [ 18 | [ 19 | "6", 20 | "-", 21 | "\"Contract\"", 22 | "0" 23 | ], 24 | [ 25 | "7", 26 | "-", 27 | "\"Executive\"", 28 | "4" 29 | ], 30 | [ 31 | "8", 32 | "-", 33 | "\"Employee\"", 34 | "2" 35 | ], 36 | [ 37 | "9", 38 | ">10", 39 | "\"Employee\",\"Executive\"", 40 | "1" 41 | ], 42 | [ 43 | "10", 44 | ">20", 45 | "\"Employee\",\"Executive\"", 46 | "1" 47 | ] 48 | ] 49 | } -------------------------------------------------------------------------------- /tests/debug.txt.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "tree": [ 4 | "0->Root #0 ", 5 | "1-->Binary #9 and ", 6 | "2--->Bracket #1 ( ", 7 | "3---->Call #2 in ", 8 | "4----->Bracket #3 ( ", 9 | "5------>Literal #4 abc ", 10 | "5------>Operator #5 , ", 11 | "5------>Literal #6 xyz-abc ", 12 | "2--->Call #10 startsWith ", 13 | "3---->Bracket #11 ( ", 14 | "4----->Literal #12 a " 15 | ], 16 | "newTree": [], 17 | "tests": [], 18 | "errors": [], 19 | "type": "Expression", 20 | "comments": [], 21 | "expr": "(in ('abc','xyz-abc') ) and startsWith('a')", 22 | "mask": "#aa ##aaa###aaa#aaa## # aaa aaaaaaaaaa##a##", 23 | "newMask": "#aa ##aaa###aaa#aaa## # aaa aaaaaaaaaa##a##", 24 | "maskDiff": "" 25 | }, 26 | { 27 | "tree": [ 28 | "0->Root id:0", 29 | "1-->Number 2 id:1", 30 | "1-->Operator * id:2", 31 | "1-->Number 3 id:3", 32 | "1-->Operator * id:4", 33 | "1-->Bracket ( id:5", 34 | "2--->Number 3 id:6", 35 | "2--->Operator + id:7", 36 | "2--->Bracket ( id:8", 37 | "3---->Number 2 id:9", 38 | "3---->Operator - id:10", 39 | "3---->Number 1 id:11", 40 | "0->Root id:0", 41 | "1-->Operator * id:2", 42 | "\t1-->Number 2 id:1", 43 | "\t1-->Number 3 id:3", 44 | "1-->Operator * id:4", 45 | "1-->Bracket ( id:5", 46 | "2--->Operator + id:7", 47 | "\t2--->Number 3 id:6", 48 | "\t2--->Bracket ( id:8", 49 | "3---->Operator - id:10", 50 | "\t3---->Number 2 id:9", 51 | "\t3---->Number 1 id:11", 52 | "0-->Operator * id:2", 53 | "2--->Number 2 id:1", 54 | "2--->Number 3 id:3", 55 | "1-->Operator * id:4", 56 | "1-->Bracket ( id:5", 57 | "2--->Operator + id:7", 58 | "3---->Number 3 id:6", 59 | "3---->Bracket ( id:8", 60 | "4----->Operator - id:10", 61 | "5------>Number 2 id:9", 62 | "5------>Number 1 id:11", 63 | "0->Root #0 ", 64 | "1-->Operator #2 * ", 65 | "2--->Number #1 2 result=<2> ", 66 | "1-->Operator #4 * ", 67 | "2--->Number #3 3 ", 68 | "2--->Bracket #5 ( ", 69 | "3---->Operator #7 + ", 70 | "4----->Number #6 3 ", 71 | "4----->Bracket #8 ( ", 72 | "5------>Operator #10 - ", 73 | "6------->Number #9 2 ", 74 | "6------->Number #11 1 " 75 | ], 76 | "newTree": [ 77 | "0->Root #0 result=<24> ", 78 | "1-->Operator #2 * result=<24> ", 79 | "2--->Number #1 2 result=<2> ", 80 | "2--->Operator #4 * result=<12> ", 81 | "3---->Number #3 3 result=<3> ", 82 | "3---->Bracket #5 ( result=<4> ", 83 | "4----->Operator #7 + result=<4> ", 84 | "5------>Number #6 3 result=<3> ", 85 | "5------>Bracket #8 ( result=<1> ", 86 | "6------->Operator #10 - result=<1> ", 87 | "7-------->Number #9 2 result=<2> ", 88 | "7-------->Number #11 1 result=<1> " 89 | ], 90 | "tests": [ 91 | "24" 92 | ], 93 | "errors": [], 94 | "type": "Expression", 95 | "comments": [ 96 | "", 97 | "" 98 | ], 99 | "expr": "2*3* (3+ ( 2-1))", 100 | "mask": "N#N# #N# # N#N##", 101 | "newMask": "N#N# #N# # N#N##", 102 | "maskDiff": "" 103 | } 104 | ] -------------------------------------------------------------------------------- /tests/parsing.bak: -------------------------------------------------------------------------------- 1 | $Condition 2 | "text"' 3 | $Tests 4 | $mask 5 | #aaaa## 6 | $Tree 7 | 0->Root #0 8 | 1-->Literal #1 text 9 | 10 | $Condition 11 | '"text"' 12 | $Tests 13 | $mask 14 | #aaaa## 15 | $maskDiff 16 | X X X 17 | $newMask 18 | ##aaaa## 19 | $Tree 20 | 0->Root #0 21 | 1-->Literal #1 "text" 22 | 23 | $Condition 24 | "text" 25 | $Tests 26 | $mask 27 | #aaaa# 28 | $Tree 29 | 0->Root #0 30 | 1-->Literal #1 text 31 | 32 | $Condition 33 | "te'xt" 34 | $Tests 35 | $mask 36 | #aa#aa# 37 | $Tree 38 | 0->Root #0 39 | 1-->Literal #1 te'xt 40 | 41 | $Condition 42 | 'te"xt' 43 | $Tests 44 | $mask 45 | #aa#aa# 46 | $Tree 47 | 0->Root #0 48 | 1-->Literal #1 te"xt 49 | 50 | $Condition 51 | - 52 | $Tests 53 | $mask 54 | # 55 | $Tree 56 | 0->True #0 57 | 58 | $Condition 59 | (in (abc,'xyz-abc') and 2 > 1 ) 60 | $Tests 61 | $mask 62 | #aa #aaa##aaa#aaa## aaa N # N # 63 | $Tree 64 | 0->Root #0 65 | 1-->Bracket #1 ( 66 | 2--->Binary #8 and 67 | 3---->Call #2 in 68 | 4----->Bracket #3 ( 69 | 5------>Call #4 abc 70 | 6------->Operator #5 , 71 | 5------>Literal #6 xyz-abc 72 | 3---->Literal #9 2 73 | 2--->Operator #10 > 74 | 3---->Literal #11 1 75 | 76 | $Condition 77 | not 3 78 | $Tests 79 | $mask 80 | aaa N 81 | $Tree 82 | 0->Root #0 83 | 1-->Binary #1 not 84 | 2--->Literal #2 3 85 | 86 | $Condition 87 | (in (abc,'xyz-abc') and > 1 ) 88 | $Tests 89 | $mask 90 | #aa #aaa##aaa#aaa## aaa # N # 91 | $Tree 92 | 0->Root #0 93 | 1-->Bracket #1 ( 94 | 2--->Binary #8 and 95 | 3---->Call #2 in 96 | 4----->Bracket #3 ( 97 | 5------>Call #4 abc 98 | 6------->Operator #5 , 99 | 5------>Literal #6 xyz-abc 100 | 3---->Operator #9 > 101 | 4----->Literal #10 1 102 | 103 | $Expression 104 | (4 + 3 - 1) * 10 ^2 105 | $Tests 106 | 600 107 | $mask 108 | #N # N # N# # NN #N 109 | $Tree 110 | 0->Root #0 result=<600> 111 | 1-->Operator #8 * result=<600> 112 | 2--->Bracket #1 ( result=<6> 113 | 3---->Operator #3 + result=<6> 114 | 4----->Literal #2 4 115 | 4----->Operator #5 - result=<2> 116 | 5------>Literal #4 3 117 | 5------>Literal #6 1 118 | 2--->Operator #10 ^ result=<100> 119 | 3---->Literal #9 10 120 | 3---->Literal #11 2 121 | 122 | $Expression 123 | 4 + 3 - 1 * 10 ^2 124 | $Tests 125 | $mask 126 | N # N # N # NN #N 127 | $Tree 128 | 0->Root #0 129 | 1-->Operator #2 + 130 | 2--->Literal #1 4 131 | 2--->Operator #4 - 132 | 3---->Literal #3 3 133 | 3---->Operator #6 * 134 | 4----->Literal #5 1 135 | 4----->Operator #8 ^ 136 | 5------>Literal #7 10 137 | 5------>Literal #9 2 138 | 139 | $Expression 140 | 'qouted string with $ / \ _ +' 141 | $Tests 142 | $mask 143 | #aaaaaa aaaaaa aaaa # # # a ## 144 | $Tree 145 | 0->Root #0 146 | 1-->Literal #1 qouted string with $ / \ _ + 147 | $Expression 148 | 3+5 149 | $Tests 150 | 8 151 | $mask 152 | N#N 153 | $Tree 154 | 0->Root #0 result=<8> 155 | 1-->Operator #2 + result=<8> 156 | 2--->Literal #1 3 157 | 2--->Literal #3 5 158 | 159 | -------------------------------------------------------------------------------- /tests/test.bak: -------------------------------------------------------------------------------- 1 | 2 | $Condition 3 | not 3 4 | $Tests 5 | $mask 6 | aaa N 7 | $Tree 8 | 0->Root #0 9 | 1-->Binary #1 not 10 | 2--->Literal #2 3 11 | 12 | $Condition 13 | 3+5 14 | $Tests 15 | 5,false 16 | 8,true 17 | 10,false 18 | $mask 19 | N#N 20 | $Tree 21 | 0->Root #0 result=<8> 22 | 1-->Operator #2 + result=<8> 23 | 2--->Literal #1 3 24 | 2--->Literal #3 5 25 | 26 | $Condition 27 | >20 28 | $Tests 29 | 5,false 30 | 25,true 31 | $mask 32 | #NN 33 | $Tree 34 | 0->Root #0 result= 35 | 1-->Operator #1 > result= 36 | 2--->Literal #2 20 37 | $Condition 38 | 39 | >30 and < 50 40 | $Tests 41 | 40,true 42 | 10,false 43 | $mask 44 | #NN aaa # NN 45 | $Tree 46 | 0->Root #0 47 | 1-->Binary #3 and 48 | 2--->Operator #1 > 49 | 3---->Literal #2 30 50 | 2--->Operator #4 < result= 51 | 3---->Literal #5 50 52 | 53 | $Condition 54 | > 200 or < 500 55 | $Tests 56 | 20, true 57 | $mask 58 | # NNN aa # NNN 59 | $Tree 60 | 0->Root #0 result= 61 | 1-->Binary #3 or result= 62 | 2--->Operator #1 > 63 | 3---->Literal #2 200 64 | 2--->Operator #4 < result= 65 | 3---->Literal #5 500 66 | 67 | $Condition 68 | 50 69 | $Tests 70 | 55, false 71 | $mask 72 | NN 73 | $Tree 74 | 0->Root #0 75 | 1-->Literal #1 50 76 | $Condition 77 | 20+35 78 | $Tests 79 | 55, true 80 | $mask 81 | NN#NN 82 | $Tree 83 | 0->Root #0 result= 84 | 1-->Operator #2 + result=<55> 85 | 2--->Literal #1 20 86 | 2--->Literal #3 35 87 | 88 | $Condition 89 | > 200 or < 500 90 | $Tests 91 | 20, true 92 | $mask 93 | # NNN aa # NNN 94 | $Tree 95 | 0->Root #0 result= 96 | 1-->Binary #3 or result= 97 | 2--->Operator #1 > 98 | 3---->Literal #2 200 99 | 2--->Operator #4 < result= 100 | 3---->Literal #5 500 101 | 102 | $Condition 103 | > 200 or < 500 104 | $Tests 105 | 20, true 106 | $mask 107 | # NNN aa # NNN 108 | $Tree 109 | 0->Root #0 result= 110 | 1-->Binary #3 or result= 111 | 2--->Operator #1 > 112 | 3---->Literal #2 200 113 | 2--->Operator #4 < result= 114 | 3---->Literal #5 500 115 | 116 | $Condition 117 | (> 200) or (< 500) 118 | $Tests 119 | 20, true 120 | $mask 121 | ## NNN# aa ## NNN# 122 | $Tree 123 | 0->Root #0 result= 124 | 1-->Binary #5 or result= 125 | 2--->Bracket #1 ( 126 | 3---->Operator #2 > 127 | 4----->Literal #3 200 128 | 2--->Bracket #6 ( result= 129 | 3---->Operator #7 < result= 130 | 4----->Literal #8 500 131 | 132 | 133 | $Condition 134 | (2+3) 135 | $Tests 136 | 5, true 137 | $mask 138 | #N#N# 139 | $Tree 140 | 0->Root #0 result= 141 | 1-->Bracket #1 ( result=<5> 142 | 2--->Operator #3 + result=<5> 143 | 3---->Literal #2 2 144 | 3---->Literal #4 3 145 | 146 | 147 | $Condition 148 | 2+3 149 | $Tests 150 | 5, true 151 | $mask 152 | N#N 153 | $Tree 154 | 0->Root #0 result= 155 | 1-->Operator #2 + result=<5> 156 | 2--->Literal #1 2 157 | 2--->Literal #3 3 158 | 159 | 160 | $Condition 161 | 2*4 162 | $Tests 163 | 8, true 164 | 165 | $mask 166 | N#N 167 | $Tree 168 | 0->Root #0 result= 169 | 1-->Operator #2 * result=<8> 170 | 2--->Literal #1 2 171 | 2--->Literal #3 4 172 | 173 | 174 | $Condition 175 | (2+3)*4 176 | $Tests 177 | 20, true 178 | 179 | $mask 180 | #N#N##N 181 | $Tree 182 | 0->Root #0 result= 183 | 1-->Operator #6 * result=<20> 184 | 2--->Bracket #1 ( result=<5> 185 | 3---->Operator #3 + result=<5> 186 | 4----->Literal #2 2 187 | 4----->Literal #4 3 188 | 2--->Literal #7 4 189 | 190 | $Condition 191 | 75.25 192 | $Tests 193 | 75, false 194 | 75.25, true 195 | $mask 196 | NNNNN 197 | $Tree 198 | 0->Root #0 result= 199 | 1-->Literal #1 75.25 result= 200 | 201 | 202 | $Condition 203 | 2,075.25 204 | $Tests 205 | 75, false 206 | $mask 207 | N#NNNNNN 208 | $Tree 209 | 0->Root #0 210 | 1-->Literal #1 2075.25 211 | 212 | 213 | $Condition 214 | 2,075.25 215 | $Tests 216 | 2075.25, true 217 | $mask 218 | N#NNNNNN 219 | $Tree 220 | 0->Root #0 result= 221 | 1-->Literal #1 2075.25 result= 222 | $Condition 223 | 224 | $Tests 225 | '-20', true 226 | 227 | $mask 228 | 229 | $Tree 230 | $Errors 231 | 232 | $Condition 233 | >=75 234 | $Tests 235 | '75', true 236 | $mask 237 | ##NN 238 | $Tree 239 | 0->Root #0 result= 240 | 1-->Operator #1 >= result= 241 | 2--->Literal #2 75 242 | $Condition 243 | <=55 244 | $Tests 245 | '55', true 246 | $mask 247 | ##NN 248 | $Tree 249 | 0->Root #0 result= 250 | 1-->Operator #1 <= result= 251 | 2--->Literal #2 55 252 | 253 | 254 | $Condition 255 | ==55 256 | $Tests 257 | '55', true 258 | 259 | $mask 260 | ##NN 261 | $Tree 262 | 0->Root #0 result= 263 | 1-->Operator #1 == result= 264 | 2--->Literal #2 55 265 | 266 | 267 | $Condition 268 | 2 + 3 269 | $Tests 270 | '5', true 271 | 272 | $mask 273 | N # N 274 | $Tree 275 | 0->Root #0 result= 276 | 1-->Operator #2 + result=<5> 277 | 2--->Literal #1 2 278 | 2--->Literal #3 3 279 | 280 | 281 | $Condition 282 | > 200 or < 500 283 | $Tests 284 | 20, true 285 | 286 | $mask 287 | # NNN aa # NNN 288 | $Tree 289 | 0->Root #0 result= 290 | 1-->Binary #3 or result= 291 | 2--->Operator #1 > 292 | 3---->Literal #2 200 293 | 2--->Operator #4 < result= 294 | 3---->Literal #5 500 295 | 296 | 297 | $Condition 298 | object.fun('test') 299 | $Tests 300 | '75', true 301 | $mask 302 | aaaaaaaaaa##aaaa## 303 | $Tree 304 | 0->Root #0 result= 305 | 1-->Call #1 object.fun result= 306 | 2--->Bracket #2 ( 307 | 3---->Literal #3 test 308 | $Condition 309 | 5 + object.fun('test') 310 | $Tests 311 | '75', true 312 | 313 | $mask 314 | N # aaaaaaaaaa##aaaa## 315 | $Tree 316 | 0->Root #0 317 | 1-->Operator #2 + result=<6> 318 | 2--->Literal #1 5 319 | 2--->Call #3 object.fun result= 320 | 3---->Bracket #4 ( 321 | 4----->Literal #5 test 322 | $Errors 323 | ***Error -5 + object.fun('test') for 75 result: false expecting: 324 | 325 | -------------------------------------------------------------------------------- /testsVacation.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vacation Allowance", 3 | "hitPolicy": "Collect+", 4 | "conditionVars": [ 5 | { 6 | "name": "YearsOfService" 7 | }, 8 | { 9 | "name": "EmployeeType" 10 | } 11 | ], 12 | "actionVars": [ 13 | { 14 | "name": "Vacation" 15 | } 16 | ], 17 | "rules": [ 18 | [ 19 | "6", 20 | [ 21 | "-", 22 | "\"Contract\"" 23 | ], 24 | [ 25 | "0" 26 | ] 27 | ], 28 | [ 29 | "7", 30 | [ 31 | "-", 32 | "\"Executive\"" 33 | ], 34 | [ 35 | "4" 36 | ] 37 | ], 38 | [ 39 | "8", 40 | [ 41 | "-", 42 | "\"Employee\"" 43 | ], 44 | [ 45 | "2" 46 | ] 47 | ], 48 | [ 49 | "9", 50 | [ 51 | ">10", 52 | "in ('Employee','Executive')" 53 | ], 54 | [ 55 | "1" 56 | ] 57 | ], 58 | [ 59 | "10", 60 | [ 61 | ">20", 62 | "in ('Employee','Executive')" 63 | ], 64 | [ 65 | "1" 66 | ] 67 | ] 68 | ] 69 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "lib": [ "es6", "dom" ], 6 | "sourceMap": true, 7 | "declaration": true 8 | }, 9 | "include": [ 10 | "**/*.ts" 11 | ], 12 | "exclude": [ 13 | "node_modules" , "./lib" , "./bu" 14 | ] 15 | } 16 | --------------------------------------------------------------------------------