1use rust_rule_engine::engine::facts::Facts;
2use rust_rule_engine::engine::knowledge_base::KnowledgeBase;
3use rust_rule_engine::engine::rule::{Condition, ConditionGroup, Rule};
4use rust_rule_engine::engine::{EngineConfig, RustRuleEngine};
5use rust_rule_engine::types::{ActionType, Operator, Value};
6use std::collections::HashMap;
7
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("=== Demo: Generic Function Calls ===\n");
10
11 let mut user_props = HashMap::new();
13 user_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
14 user_props.insert("Score".to_string(), Value::Number(85.5));
15 user_props.insert("Active".to_string(), Value::Boolean(true));
16
17 let numbers = vec![
18 Value::Number(10.0),
19 Value::Number(20.0),
20 Value::Number(30.0),
21 Value::Number(15.5),
22 Value::Number(25.2),
23 ];
24
25 let facts = Facts::new();
27 facts.add_value("User", Value::Object(user_props))?;
28 facts.add_value("Numbers", Value::Array(numbers))?;
29 facts.add_value("Message", Value::String("Hello World".to_string()))?;
30
31 println!("š Initial state:");
32 if let Some(user) = facts.get("User") {
33 println!(" User = {user:?}");
34 }
35 if let Some(numbers) = facts.get("Numbers") {
36 println!(" Numbers = {numbers:?}");
37 }
38 if let Some(message) = facts.get("Message") {
39 println!(" Message = {message:?}");
40 }
41 println!();
42
43 let mut kb = KnowledgeBase::new("FunctionCallDemo");
45
46 let log_rule = Rule::new(
48 "LogUserInfo".to_string(),
49 ConditionGroup::single(Condition::new(
50 "User.Active".to_string(),
51 Operator::Equal,
52 Value::Boolean(true),
53 )),
54 vec![ActionType::Call {
55 function: "log".to_string(),
56 args: vec![
57 Value::String("User is active!".to_string()),
58 Value::String("Processing user data...".to_string()),
59 ],
60 }],
61 )
62 .with_salience(10);
63
64 let stats_rule = Rule::new(
66 "CalculateStats".to_string(),
67 ConditionGroup::single(Condition::new(
68 "User.Score".to_string(),
69 Operator::GreaterThan,
70 Value::Number(80.0),
71 )),
72 vec![
73 ActionType::Call {
74 function: "sum".to_string(),
75 args: vec![
76 Value::Number(10.0),
77 Value::Number(20.0),
78 Value::Number(30.0),
79 ],
80 },
81 ActionType::Call {
82 function: "max".to_string(),
83 args: vec![
84 Value::Number(85.5),
85 Value::Number(90.0),
86 Value::Number(78.2),
87 ],
88 },
89 ActionType::Call {
90 function: "average".to_string(),
91 args: vec![
92 Value::Number(85.5),
93 Value::Number(90.0),
94 Value::Number(78.2),
95 ],
96 },
97 ],
98 )
99 .with_salience(8);
100
101 let string_rule = Rule::new(
103 "StringManipulation".to_string(),
104 ConditionGroup::single(Condition::new(
105 "Message".to_string(),
106 Operator::Contains,
107 Value::String("Hello".to_string()),
108 )),
109 vec![
110 ActionType::Call {
111 function: "uppercase".to_string(),
112 args: vec![Value::String("hello world".to_string())],
113 },
114 ActionType::Call {
115 function: "contains".to_string(),
116 args: vec![
117 Value::String("Hello World".to_string()),
118 Value::String("World".to_string()),
119 ],
120 },
121 ActionType::Call {
122 function: "format".to_string(),
123 args: vec![
124 Value::String("User {0} has score {1}".to_string()),
125 Value::String("John Doe".to_string()),
126 Value::Number(85.5),
127 ],
128 },
129 ],
130 )
131 .with_salience(6);
132
133 let math_rule = Rule::new(
135 "MathFunctions".to_string(),
136 ConditionGroup::single(Condition::new(
137 "User.Score".to_string(),
138 Operator::GreaterThanOrEqual,
139 Value::Number(80.0),
140 )),
141 vec![
142 ActionType::Call {
143 function: "round".to_string(),
144 args: vec![Value::Number(85.7)],
145 },
146 ActionType::Call {
147 function: "floor".to_string(),
148 args: vec![Value::Number(85.7)],
149 },
150 ActionType::Call {
151 function: "ceil".to_string(),
152 args: vec![Value::Number(85.2)],
153 },
154 ActionType::Call {
155 function: "abs".to_string(),
156 args: vec![Value::Number(-42.5)],
157 },
158 ],
159 )
160 .with_salience(4);
161
162 let utility_rule = Rule::new(
164 "UtilityFunctions".to_string(),
165 ConditionGroup::single(Condition::new(
166 "User.Name".to_string(),
167 Operator::NotEqual,
168 Value::String("".to_string()),
169 )),
170 vec![
171 ActionType::Call {
172 function: "timestamp".to_string(),
173 args: vec![],
174 },
175 ActionType::Call {
176 function: "random".to_string(),
177 args: vec![Value::Number(100.0)],
178 },
179 ActionType::Call {
180 function: "length".to_string(),
181 args: vec![Value::String("Hello World".to_string())],
182 },
183 ActionType::Call {
184 function: "split".to_string(),
185 args: vec![
186 Value::String("apple,banana,cherry".to_string()),
187 Value::String(",".to_string()),
188 ],
189 },
190 ],
191 )
192 .with_salience(2);
193
194 let _ = kb.add_rule(log_rule);
196 let _ = kb.add_rule(stats_rule);
197 let _ = kb.add_rule(string_rule);
198 let _ = kb.add_rule(math_rule);
199 let _ = kb.add_rule(utility_rule);
200
201 let config = EngineConfig {
203 debug_mode: true,
204 max_cycles: 5,
205 ..Default::default()
206 };
207 let engine = RustRuleEngine::with_config(kb, config);
208
209 println!("š Executing rules with generic function calls...");
211 let result = engine.execute(&facts)?;
212
213 println!("\nš Execution Results:");
214 println!(" Cycles: {}", result.cycle_count);
215 println!(" Rules evaluated: {}", result.rules_evaluated);
216 println!(" Rules fired: {}", result.rules_fired);
217 println!(" Execution time: {:?}", result.execution_time);
218
219 println!("\nšÆ Function call examples demonstrated:");
220 println!(" š Logging: log(), print()");
221 println!(" š¢ Math: sum(), max(), average(), round(), floor(), ceil(), abs()");
222 println!(" š String: uppercase(), contains(), format(), length(), split()");
223 println!(" š ļø Utility: timestamp(), random(), update()");
224 println!(" šØ Custom: Any user-defined function names");
225
226 Ok(())
227}