In this example the decision tree processing functions and the root shape have been removed from the page and been placed within separate files.
There is a decision shape that calls itself until the value data.a > 10
at which point it terminates and calls the complete function.
This browser example splits the code into separate files.
App.js contains all the functions that the decision tree will use to manipulate the object
Json.js contains a JSON object for the root shape
We are overwritting the app.js log function within the page so we can write the logs to the results layer in the test page.
//add a log function to show on screen
TestApp.log = function (msg) {
document.getElementById("results").innerHTML += msg + "
";
}
We create a new object to process. This object is passed to the decision tree and is altered by the functions in the tree.
Any functions processing the object should be aware of it's structure or handle incorrect objects by throwing an error.
//create a data object to process
var data = { "a": 1 };
Every decision tree requires a root shape to start processing at. This example has it stored in the json.js file.
The process and decision functions in the shape are set using processName and decideName and are referencing functions in the TestApp e.g. "processName": "TestApp.add"
and "decideName": "TestApp.checkValue"
var shape = {
"shapeType": "Entry",
"id": 1,
"description": "Start",
"nextShape": {
"shapeType": "Operation",
"id": 2,
"description": "Adding value 2",
"nextShape": {
"shapeType": "Decision",
"id": 3,
"description": "Adding value 2",
"paths": [{
"value": true,
"selected": false,
"nextShape": null,
"nextShapeId": 3
},
{
"value": false,
"selected": false,
"nextShape":
{
"shapeType": "Operation",
"id": 5,
"description": "Adding nothing",
"nextShape": null,
"properties": { "value": 0 },
"processName": "TestApp.add"
},
"nextShapeId": 0
}],
"properties": { "value": 2, "decision": 10 },
"processName": "TestApp.add",
"nextShape": null,
"decideName": "TestApp.checkValue"
},
"properties": { "value": 2 },
"processName": "TestApp.add"
}
};
The runTest() function calls the decisionTree.execute
function passing in the root shape, the data object to process and sets a callback function to be called on complete.
function runTest() {
//execute the tree on the root shape
decisionTree.execute(shape, data, TestApp.complete);
}
<script src="decisiontree.min.js"></script>
<script src="app.js"></script>
<script src="json.js"></script>
<script type="text/javascript">
//add a log function to show on screen
TestApp.log = function (msg) {
document.getElementById("results").innerHTML += msg + "
";
}
//create a data object to process
var data = { "a": 1 };
function runTest() {
//execute the tree on the root shape
decisionTree.execute(shape, data, TestApp.complete);
}
</script>
<input type="button" class="btn btn-primary" onclick="runTest();" value="Run Test" />
<h2>Results</h2>
<div id="results"></div>
var TestApp;
(function (TestApp) {
//logs messages to the console
TestApp.log = function (message) {
console.log(message);
};
//add function
function add(data, shape, callback) {
try {
TestApp.log("*************");
TestApp.log("add function called");
TestApp.log("data.a=" + data.a);
var v = Number(shape.properties.value);
if(isNaN(v)) {
throw new Error("'" + v + "' is not a number");
}
TestApp.log("adding: " + v);
data.a += v;
TestApp.log("data.a=" + data.a);
callback(null, shape);
} catch (e) {
callback(e, shape);
}
}
TestApp.add = add;
//check value function
function checkValue(data, shape, callback) {
try {
TestApp.log("*************");
TestApp.log("checkValue function called");
TestApp.log("checking data.a (" + data.a + ") is less than shape.properties.decision (" + shape.properties.decision + ")");
if(data.a < shape.properties.decision) {
TestApp.log("data.a < shape.properties.decision selecting path[0]");
shape.paths[0].selected = true;
shape.paths[1].selected = false;
} else {
TestApp.log("data.a >= shape.properties.decision selecting path[1]");
shape.paths[0].selected = false;
shape.paths[1].selected = true;
}
callback(null, shape);
} catch (e) {
callback(e, shape);
}
}
TestApp.checkValue = checkValue;
//complete function
function complete(err, result, processedShapes) {
TestApp.log("*************");
TestApp.log("complete function called");
TestApp.log("error: " + err);
TestApp.log("result: " + result.a);
for(var x = 0; x < processedShapes.length; x++) {
TestApp.log("processed Shape: " + processedShapes[x].description + " id:" + processedShapes[x].id);
}
}
TestApp.complete = complete;
})(TestApp || (TestApp = {}));
var shape = {
"shapeType": "Entry",
"id": 1,
"description": "Start",
"nextShape": {
"shapeType": "Operation",
"id": 2,
"description": "Adding value 2",
"nextShape": {
"shapeType": "Decision",
"id": 3,
"description": "Adding value 2",
"paths": [{
"value": true,
"selected": false,
"nextShape": null,
"nextShapeId": 3
},
{
"value": false,
"selected": false,
"nextShape":
{
"shapeType": "Operation",
"id": 5,
"description": "Adding nothing",
"nextShape": null,
"properties": { "value": 0 },
"processName": "TestApp.add"
},
"nextShapeId": 0
}],
"properties": { "value": 2, "decision": 10 },
"processName": "TestApp.add",
"nextShape": null,
"decideName": "TestApp.checkValue"
},
"properties": { "value": 2 },
"processName": "TestApp.add"
}
};
You haven't run the test yet!