Last active
July 11, 2018 01:37
-
-
Save kenwebb/39f5f62962bb9b5641b35f249f096e5d to your computer and use it in GitHub Desktop.
JavaScript Rule Engines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Tue Jul 10 2018 21:36:51 GMT-0400 (Eastern Daylight Time)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: JavaScript Rule Engines | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 39f5f62962bb9b5641b35f249f096e5d | |
Keywords: | |
My Notes | |
-------- | |
July 5, 2018 | |
see my notebook for July 4 | |
I would like to use json-rules-engine with Xholon, as an alternate way of doing recipes. | |
To make json-rules-engine available as a browser script I can use from Xholon: | |
------------------------------------------------------- | |
cd ~nodespace | |
mkdir jsonrulesengine | |
cd jsonrulesengine | |
npm install -g browserify | |
npm install json-rules-engine | |
- I created a simple main.js, and package.json | |
browserify main.js -o json-rules-engine.js | |
HTML file can include: | |
--------------------- | |
<script src="json-rules-engine.js"></script> | |
To use the recipe with json-rules-engine (from Dev Tools): | |
---------------------------------------- | |
// this works | |
console.log(window.JsonRulesEngine); | |
var rserv = xh.service("RecipeService"); | |
var rbname = "RecipeService-JsonRulesEngineRecipeBook-Island"; | |
var recipebook = null; | |
if (rserv) { | |
console.log(rserv.name()); | |
var rmsg = rserv.call(-3897, rbname, xh.root()); | |
console.log(rmsg) | |
recipebook = rmsg.data; | |
console.log(recipebook); | |
} | |
let engine = new window.JsonRulesEngine.Engine(); | |
let rule = recipebook; // only one rule structure for now | |
engine.addRule(rule); | |
let avatarFacts = { | |
inventory: ['Stick','Hook','String','Fish','Fruit','Lumber'], | |
wants: 'FishingRod' | |
} | |
engine | |
.run(avatarFacts) | |
.then(events => { // run() returns events with truthy conditions | |
events.map(event => console.log(event.params.message)) | |
}) | |
References | |
---------- | |
(1) https://www.npmjs.com/search?q=keywords%3Arules%20engine&ranking=quality | |
36 packages found | |
(2) https://www.npmjs.com/package/json-rules-engine | |
) https://github.com/CacheControl/json-rules-engine | |
A rules engine expressed in JSON | |
json-rules-engine is a powerful, lightweight rules engine. Rules are composed of simple json structures, making them human readable and easy to persist. | |
(3) https://en.wikipedia.org/wiki/Rete_algorithm | |
(4) https://en.wikipedia.org/wiki/Rule-based_system | |
(5) https://en.wikipedia.org/wiki/Drools | |
(6) https://github.com/noolsjs/nools | |
(7) https://en.wikipedia.org/wiki/RuleML | |
(8) https://github.com/CacheControl/json-rules-engine/blob/master/examples/09-rule-results.js | |
"This is a basic example demonstrating how to leverage the metadata supplied by rule results" | |
(9) https://github.com/chrisamaphone/interactive-lp/blob/master/examples/3lp.cep | |
Ceptre - Three little pigs | |
(10) https://graphicallinearalgebra.net/ | |
Graphical Linear Algebra | |
Pawel Sobocinski | |
]]></Notes> | |
<_-.XholonClass> | |
<PhysicalSystem/> | |
<!--<JsonRulesEngineRecipeBook/> this is a Xholon built-in class --> | |
<JsonRulesEngineTester/> | |
<Items/> | |
<ItemsRoot/> | |
<Stick/> | |
<String/> | |
<Hook/> | |
<FishingRod/> | |
<Twig/> | |
<Vine/> | |
<Thorn/> | |
<Cat/> | |
<Fish/> | |
<Lumber/> | |
<LumberJackCat/> | |
<Number/> | |
<Egg/> | |
<Sugar/> | |
<Mascarpone/> | |
<White/> | |
<Yolk/> | |
<WhiskedWhites/> | |
<YolkyPaste/> | |
<ThickPaste/> | |
<CremaDiMascarpone/> | |
<!-- Three Little Pigs [ref 9] | |
pig : pred. | |
wolf : pred. | |
sticks : pred. | |
bricks : pred. | |
straw : pred. | |
stickhouse : pred. | |
brickhouse : pred. | |
strawhouse : pred. | |
--> | |
<Pig/> | |
<Wolf/> | |
<Sticks/> | |
<Bricks/> | |
<Straw/> | |
<StickHouse/> | |
<BrickHouse/> | |
<StrawHouse/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
<Avatar><Color>red</Color></Avatar> | |
<Items><Color>green</Color></Items> | |
<JsonRulesEngineTester><Color>indigo</Color></JsonRulesEngineTester> | |
</xholonClassDetails> | |
<PhysicalSystem> | |
<ItemsRoot> | |
<!-- all the ingredients necessary to make a FishingRod --> | |
<Items> | |
<String/> | |
<Stick/> | |
<Hook/> | |
</Items> | |
<!-- all the ingredients necessary to make 2 FishingRod, each from different materials --> | |
<Items> | |
<String/> | |
<Twig/> | |
<Stick/> | |
<Vine/> | |
<Hook/> | |
<Thorn/> | |
</Items> | |
<!-- all the ingredients necessary to make a FishingRod, plus more --> | |
<Items> | |
<Cat/> | |
<String/> | |
<Stick multiplicity="2"/> | |
<Lumber multiplicity="13"/> | |
<Hook/> | |
<Fish/> | |
</Items> | |
<!-- insufficient ingredients to make a FishingRod --> | |
<Items> | |
<String/> | |
<Cat/> | |
<Hook/> | |
</Items> | |
<!-- integers --> | |
<Items> | |
<Number roleName="1"/> | |
<Number roleName="2"/> | |
<Number roleName="3"/> | |
</Items> | |
<!-- Pawel Sobocinski - Graphical Linear Algebra (GLA) [ref 10] --> | |
<Items roleName="GLA"> | |
<Egg multiplicity="2"> | |
<White/> | |
<Yolk/> | |
</Egg> | |
<Sugar/> | |
<Mascarpone/> | |
</Items> | |
<!-- Three Little Pigs [ref 9] | |
context init = | |
{pig, pig, pig, wolf, straw, sticks, bricks}. | |
--> | |
<Items roleName="Pigs"> | |
<Pig multiplicity="3"/> | |
<Wolf/> | |
<Straw/> | |
<Sticks/> | |
<Bricks/> | |
</Items> | |
</ItemsRoot> | |
<!-- alternative to MinecraftStyleRecipeBook --> | |
<JsonRulesEngineRecipeBook roleName="Island"><Attribute_String><![CDATA[ | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Stick", | |
"fate": "embed" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "String", | |
"fate": "embed" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Hook", | |
"fate": "embed" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "FishingRod" | |
}] | |
}, | |
{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Twig", | |
"fate": "retain" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Vine", | |
"fate": "drop" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Thorn", | |
"fate": "remove" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "FishingRod" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "fishingRod", | |
"params": { | |
"message": "A FishingRod can be created." | |
} | |
} | |
} | |
]]></Attribute_String></JsonRulesEngineRecipeBook> | |
<JsonRulesEngineRecipeBook roleName="Hawaii"><Attribute_String><![CDATA[ | |
[ | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Cat" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Lumber" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "LumberJackCat" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "lumberishy", | |
"params": { | |
"message": "A LumberJackCat can be created." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "containsMultiple", | |
"value": "Lumber,5" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "Cat" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "catty", | |
"params": { | |
"message": "A Cat can be created." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "1", | |
"fate": "embed" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "3", | |
"fate": "embed" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "Number", | |
"role": "4" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "numeric", | |
"params": { | |
"message": "A Number 4 can be created." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "2", | |
"fate": "embed" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "4", | |
"fate": "embed" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "Number", | |
"role": "6" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "numeric", | |
"params": { | |
"message": "A Number 6 can be created." | |
} | |
} | |
} | |
] | |
]]></Attribute_String></JsonRulesEngineRecipeBook> | |
<JsonRulesEngineRecipeBook roleName="Isola"><Attribute_String><![CDATA[ | |
[ | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Egg", | |
"fate": "smash" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "null" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "CrackEgg", | |
"params": { | |
"message": "An Egg can be cracked." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "containsMultiple", | |
"value": "White,2" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "WhiskedWhites" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "Whisk", | |
"params": { | |
"message": "Two Whites can be whisked." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "containsMultiple", | |
"value": "Yolk,2" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Sugar" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "YolkyPaste" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "Beat", | |
"params": { | |
"message": "Two Yolks can be beaten." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "YolkyPaste" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Mascarpone" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "ThickPaste" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "Stir", | |
"params": { | |
"message": "Ingredients can be stirred." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "WhiskedWhites" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "ThickPaste" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "CremaDiMascarpone" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "Fold", | |
"params": { | |
"message": "Ingredients can be folded." | |
} | |
} | |
} | |
] | |
]]></Attribute_String></JsonRulesEngineRecipeBook> | |
<!-- Three Little Pigs [ref 9] | |
stage go = { | |
build_straw : pig * straw -o strawhouse. | |
build_stick : pig * sticks -o stickhouse. | |
build_brick : pig * bricks -o brickhouse. | |
blow_straw : wolf * strawhouse -o wolf. | |
blow_stick : wolf * stickhouse -o wolf. | |
blow_brick : wolf * brickhouse -o brickhouse. | |
} | |
I have added fate: embed in the first 3 rules | |
--> | |
<JsonRulesEngineRecipeBook roleName="Pigs"><Attribute_String><![CDATA[ | |
[ | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Pig", | |
"fate": "embed" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Straw" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "StrawHouse" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "build_straw", | |
"params": { | |
"message": "A StrawHouse can be created." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Pig", | |
"fate": "embed" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Sticks" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "StickHouse" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "build_stick", | |
"params": { | |
"message": "A StickHouse can be created." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Pig", | |
"fate": "embed" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Bricks" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "BrickHouse" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "build_brick", | |
"params": { | |
"message": "A BrickHouse can be created." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Wolf", | |
"fate": "retain" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "StrawHouse", | |
"fate": "smash" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "null" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "blow_straw", | |
"params": { | |
"message": "A StrawHouse can be blown down." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Wolf", | |
"fate": "retain" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "StickHouse", | |
"fate": "smash" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "null" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "blow_stick", | |
"params": { | |
"message": "A StickHouse can be blown down." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Wolf" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "BrickHouse", | |
"fate": "retain" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "null" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "blow_brick", | |
"params": { | |
"message": "A BrickHouse can defeat the wolf." | |
} | |
} | |
}, | |
{ | |
"conditions": { | |
"any": [{ | |
"all": [{ | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Wolf", | |
"fate": "retain" | |
}, { | |
"fact": "inventory", | |
"operator": "contains", | |
"value": "Pig", | |
"fate": "eat" | |
}, { | |
"fact": "wants", | |
"operator": "equal", | |
"value": "null" | |
}] | |
}] | |
}, | |
"event": { | |
"type": "blow_brick", | |
"params": { | |
"message": "A Wolf can eat a Pig." | |
} | |
} | |
} | |
] | |
]]></Attribute_String></JsonRulesEngineRecipeBook> | |
<!-- specify a specific "wants" for testing --> | |
<JsonRulesEngineTester roleName="Island" rbname="RecipeService-JsonRulesEngineRecipeBook-Island" wants="FishingRod"/> | |
<JsonRulesEngineTester roleName="Hawaii" rbname="RecipeService-JsonRulesEngineRecipeBook-Hawaii" wants="LumberJackCat,Cat,Number"/> | |
<JsonRulesEngineTester roleName="Isola" rbname="RecipeService-JsonRulesEngineRecipeBook-Isola" wants="null,WhiskedWhites,YolkyPaste,ThickPaste,CremaDiMascarpone"/> | |
<JsonRulesEngineTester roleName="Pigs" rbname="RecipeService-JsonRulesEngineRecipeBook-Pigs" wants="StrawHouse,StickHouse,BrickHouse,null"/> | |
<Animate selection='#xhgraph' duration='1'/> | |
</PhysicalSystem> | |
<JsonRulesEngineTesterbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
const DEFAULT_FATE = "remove"; // by default, recipes should remove inventory items when there's a match | |
var me, engine, ready, ava, defaultFate, wantsAll, beh = { | |
postConfigure: function() { | |
me = this.cnode.parent(); | |
me.println(me["rbname"]); | |
engine = null; | |
ready = false; | |
wantsAll = me["wants"].split(","); | |
if ($wnd.xh.html["selectTab"]) { | |
$wnd.xh.html.selectTab(0); // display contents of the "out" tab | |
} | |
ava = $wnd.xh.avatar(); | |
if (ava.parent() == null) { | |
ava.action("appear;where;enter;enter;enter;where;look;"); | |
} | |
this.initAvatarKeyMap(); | |
ava.val(-1); | |
}, | |
initAvatarKeyMap: function() { | |
var akm = $wnd.JSON.parse($wnd.xh.avatarKeyMap()); | |
akm["0"] = "become this val 0;step;"; | |
akm["1"] = "become this val 1;step;"; | |
akm["2"] = "become this val 2;step;"; | |
akm["3"] = "become this val 3;step;"; | |
akm["4"] = "become this val 4;step;"; | |
akm["5"] = "become this val 5;step;"; | |
akm["6"] = "become this val 6;step;"; | |
akm["7"] = "become this val 7;step;"; | |
akm["8"] = "become this val 8;step;"; | |
akm["9"] = "become this val 9;step;"; | |
$wnd.xh.avatarKeyMap($wnd.JSON.stringify(akm)); | |
}, | |
act: function() { | |
if (!ready && $wnd["JsonRulesEngine"]) { | |
ready = true; | |
var rserv = $wnd.xh.service("RecipeService"); | |
var rbname = me["rbname"]; //"RecipeService-JsonRulesEngineRecipeBook-Island"; | |
var recipebook = null; | |
if (rserv) { | |
var rmsg = rserv.call(-3897, rbname, me); | |
recipebook = rmsg.data; | |
} | |
if (Array.isArray(recipebook)) { | |
engine = new $wnd.JsonRulesEngine.Engine(recipebook); | |
} | |
else { | |
engine = new $wnd.JsonRulesEngine.Engine(); | |
//let rule = recipebook; // all rules are in the one rule structure for now | |
engine.addRule(recipebook); | |
} | |
// Define a 'containsMultiple' custom operator, for use in later rules | |
engine.addOperator('containsMultiple', (factValue, ruleValue) => { | |
var ruleValueArr = ruleValue.split(","); // ex: "Lumber,2" | |
var count = 0; | |
for (var i = 0; i < factValue.length; i++) { | |
var fval = factValue[i]; | |
if (fval == ruleValueArr[0]) { | |
count++; | |
} | |
} | |
return count >= ruleValueArr[1]; | |
}) | |
engine.on('success', (event, almanac, ruleResult) => { | |
me.println(event.params.message); | |
beh.render(ruleResult); | |
}) | |
//engine.on('failure', function(event, almanac, ruleResult) { | |
// $wnd.console.log(event); | |
//}) | |
ava.action("script;param repeat true;\ntake;\nwait 3;\ndrop;\nnext;"); | |
} | |
if (ready) { | |
// update avatarFacts every timestep | |
var rnum = ava.val(); // user may have pressed [0-9] | |
if ((rnum == -1) || (rnum >= wantsAll.length)) { | |
rnum = Math.floor(Math.random() * wantsAll.length); | |
} | |
else { | |
me.println(wantsAll + " " + rnum); | |
} | |
var invArr = this.createAvaInvArr(); | |
let avatarFacts = { | |
inventory: invArr, | |
wants: wantsAll[rnum] //me["wants"] | |
} | |
engine.run(avatarFacts); | |
ava.val(-1); | |
} | |
}, | |
createAvaInvArr: function() { | |
// create an Avatar inventory array | |
var iarr = []; | |
var node = ava.first(); | |
while (node) { | |
iarr.push(node.name("R^^^^^")); | |
node = node.next(); | |
} | |
return iarr; | |
}, | |
render: function(ruleResult) { | |
// render the results from engine.on('success' | |
var anyconds = ruleResult.conditions.any; | |
for (var i = 0; i < anyconds.length; i++) { | |
var anycond = anyconds[i]; | |
if (anycond.result) { | |
var conds = anycond.all; | |
var embedArr = []; | |
conds.forEach(function(cond) { | |
if (cond.fact == "inventory") { | |
// handle cond.operator == "containsMultiple" ex: cond.value = "Lumber,2" | |
var itemNum = 1; | |
var itemName = cond.value; | |
var fate = cond["fate"] || DEFAULT_FATE; | |
//me.println("fate: " + fate); | |
if (cond.operator == "containsMultiple") { | |
valArr = itemName.split(",") | |
itemName = valArr[0]; | |
itemNum = valArr[1]; | |
} | |
itemName = itemName.charAt(0).toLowerCase() + itemName.substring(1); | |
for (var j = 0; j < itemNum; j++) { | |
ava.action("x " + itemName + ";"); | |
switch (fate) { | |
case "retain": // retain this item in the inventory | |
break; | |
case "drop": // drop this inventory item | |
ava.action("drop " + itemName + ";"); | |
break; | |
case "embed": // embed this inventory item into the "wants" node once it's built | |
embedArr.push(itemName); | |
break; | |
case "smash": | |
ava.action("drop " + itemName + ";" + "smash " + itemName + ";"); | |
break; | |
case "eat": | |
ava.action("eat " + itemName + ";"); | |
break; | |
case "remove": // remove this inventory item from the game | |
default: | |
ava.action("unbuild " + itemName + ";"); | |
break; | |
} | |
} | |
} | |
else if (cond.fact == "wants") { | |
var itemName = cond.value; | |
if (itemName == "null") { | |
// do nothing | |
} | |
else { | |
var roleName = cond["role"]; | |
var roleNameStr = ""; | |
if (roleName) { | |
roleNameStr = " role " + roleName; | |
} | |
else { | |
roleName = ""; | |
} | |
me.println("about to build a " + itemName + roleNameStr); | |
ava.action("build " + itemName + roleNameStr + ";"); | |
if (embedArr) { | |
itemName = itemName.charAt(0).toLowerCase() + itemName.substring(1); | |
if (roleName) { | |
roleName = roleName + ":"; | |
} | |
embedArr.forEach(function(embedName) { | |
ava.action("put " + embedName + " in " + roleName + itemName + ";"); | |
}); | |
embedArr = []; | |
} | |
} | |
} | |
}); | |
break; // break out of for loop | |
} // end if | |
} // end for loop | |
} | |
} | |
//# sourceURL=JsonRulesEngineTesterbehavior.js | |
]]></JsonRulesEngineTesterbehavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>JsonRulesEngineTester</title> | |
<rect id="PhysicalSystem/JsonRulesEngineTester" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment