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() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("š Grule-Style Rule Engine Demo");
10 println!("================================\n");
11
12 demo_knowledge_base()?;
14
15 demo_facts_manipulation()?;
17
18 demo_engine_execution()?;
20
21 demo_ecommerce_scenario()?;
23
24 Ok(())
25}
26
27fn demo_knowledge_base() -> std::result::Result<(), Box<dyn std::error::Error>> {
28 println!("š Demo 1: Knowledge Base with Code-based Rules");
29 println!("-----------------------------------------------");
30
31 let kb = KnowledgeBase::new("UserRules");
33
34 println!("ā
Knowledge Base created: {}", kb.get_statistics().name);
35 println!(" Total rules: {}", kb.get_statistics().total_rules);
36 println!(" Version: {}\n", kb.get_statistics().version);
37
38 Ok(())
39}
40
41fn demo_facts_manipulation() -> std::result::Result<(), Box<dyn std::error::Error>> {
42 println!("šļø Demo 2: Facts Manipulation");
43 println!("-----------------------------");
44
45 let facts = Facts::new();
47
48 let mut user_props = HashMap::new();
50 user_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
51 user_props.insert("Age".to_string(), Value::Integer(25));
52 user_props.insert("Country".to_string(), Value::String("US".to_string()));
53 user_props.insert("SpendingTotal".to_string(), Value::Number(1500.0));
54 user_props.insert("IsAdult".to_string(), Value::Boolean(false));
55 user_props.insert("IsVIP".to_string(), Value::Boolean(false));
56
57 facts.add_value("User", Value::Object(user_props))?;
58
59 println!("ā
Facts created and populated:");
60 if let Some(user) = facts.get("User") {
61 println!(" User = {user:?}");
62 }
63 println!();
64
65 Ok(())
66}
67
68fn demo_engine_execution() -> std::result::Result<(), Box<dyn std::error::Error>> {
69 println!("š Demo 3: Engine Execution");
70 println!("---------------------------");
71
72 let facts = Facts::new();
74 let mut user_props = HashMap::new();
75 user_props.insert("Age".to_string(), Value::Integer(25));
76 user_props.insert("Country".to_string(), Value::String("US".to_string()));
77 user_props.insert("SpendingTotal".to_string(), Value::Number(1500.0));
78 user_props.insert("IsAdult".to_string(), Value::Boolean(false));
79 user_props.insert("IsVIP".to_string(), Value::Boolean(false));
80 user_props.insert("Category".to_string(), Value::String("unknown".to_string()));
81 user_props.insert("DiscountRate".to_string(), Value::Number(0.0));
82
83 facts.add_value("User", Value::Object(user_props))?;
84
85 let mut kb = KnowledgeBase::new("UserRules");
87
88 let adult_rule = Rule::new(
90 "AdultCheck".to_string(),
91 ConditionGroup::and(
92 ConditionGroup::single(Condition::new(
93 "User.Age".to_string(),
94 Operator::GreaterThanOrEqual,
95 Value::Integer(18),
96 )),
97 ConditionGroup::single(Condition::new(
98 "User.Country".to_string(),
99 Operator::Equal,
100 Value::String("US".to_string()),
101 )),
102 ),
103 vec![
104 ActionType::MethodCall {
105 object: "User".to_string(),
106 method: "setIsAdult".to_string(),
107 args: vec![Value::Boolean(true)],
108 },
109 ActionType::MethodCall {
110 object: "User".to_string(),
111 method: "setCategory".to_string(),
112 args: vec![Value::String("Adult".to_string())],
113 },
114 ActionType::Call {
115 function: "log".to_string(),
116 args: vec![Value::String("User qualified as adult".to_string())],
117 },
118 ],
119 )
120 .with_salience(10);
121
122 let vip_rule = Rule::new(
124 "VIPCheck".to_string(),
125 ConditionGroup::and(
126 ConditionGroup::and(
127 ConditionGroup::single(Condition::new(
128 "User.Age".to_string(),
129 Operator::GreaterThanOrEqual,
130 Value::Integer(21),
131 )),
132 ConditionGroup::single(Condition::new(
133 "User.IsAdult".to_string(),
134 Operator::Equal,
135 Value::Boolean(true),
136 )),
137 ),
138 ConditionGroup::single(Condition::new(
139 "User.SpendingTotal".to_string(),
140 Operator::GreaterThan,
141 Value::Number(1000.0),
142 )),
143 ),
144 vec![
145 ActionType::MethodCall {
146 object: "User".to_string(),
147 method: "setIsVIP".to_string(),
148 args: vec![Value::Boolean(true)],
149 },
150 ActionType::MethodCall {
151 object: "User".to_string(),
152 method: "setDiscountRate".to_string(),
153 args: vec![Value::Number(0.15)],
154 },
155 ActionType::Call {
156 function: "log".to_string(),
157 args: vec![Value::String("User upgraded to VIP".to_string())],
158 },
159 ],
160 )
161 .with_salience(20);
162
163 let senior_rule = Rule::new(
165 "SeniorDiscount".to_string(),
166 ConditionGroup::single(Condition::new(
167 "User.Age".to_string(),
168 Operator::GreaterThanOrEqual,
169 Value::Integer(65),
170 )),
171 vec![
172 ActionType::MethodCall {
173 object: "User".to_string(),
174 method: "setDiscountRate".to_string(),
175 args: vec![Value::Number(0.20)],
176 },
177 ActionType::MethodCall {
178 object: "User".to_string(),
179 method: "setCategory".to_string(),
180 args: vec![Value::String("Senior".to_string())],
181 },
182 ActionType::Call {
183 function: "log".to_string(),
184 args: vec![Value::String("Senior discount applied".to_string())],
185 },
186 ],
187 )
188 .with_salience(15);
189
190 let _ = kb.add_rule(adult_rule);
192 let _ = kb.add_rule(vip_rule);
193 let _ = kb.add_rule(senior_rule);
194
195 let config = EngineConfig {
197 debug_mode: true,
198 max_cycles: 3,
199 ..Default::default()
200 };
201 let engine = RustRuleEngine::with_config(kb, config);
202
203 println!("š Initial state:");
204 if let Some(user) = facts.get("User") {
205 println!(" User = {user:?}");
206 }
207 println!();
208
209 println!("š Executing rules...");
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š Final state:");
220 if let Some(user) = facts.get("User") {
221 println!(" User = {user:?}");
222 }
223 println!();
224
225 Ok(())
226}
227
228fn demo_ecommerce_scenario() -> std::result::Result<(), Box<dyn std::error::Error>> {
229 println!("š Demo 4: E-commerce Scenario");
230 println!("------------------------------");
231
232 let facts = Facts::new();
234
235 let mut customer_props = HashMap::new();
237 customer_props.insert(
238 "Email".to_string(),
239 Value::String("customer@example.com".to_string()),
240 );
241 customer_props.insert("Age".to_string(), Value::Integer(28));
242 customer_props.insert("IsNew".to_string(), Value::Boolean(true));
243 customer_props.insert("LoyaltyPoints".to_string(), Value::Integer(0));
244 customer_props.insert("TotalSpent".to_string(), Value::Number(0.0));
245
246 let mut order_props = HashMap::new();
248 order_props.insert("Id".to_string(), Value::String("ORD-12345".to_string()));
249 order_props.insert("Amount".to_string(), Value::Number(150.0));
250 order_props.insert(
251 "Category".to_string(),
252 Value::String("electronics".to_string()),
253 );
254 order_props.insert("DiscountPercent".to_string(), Value::Number(0.0));
255 order_props.insert("FinalAmount".to_string(), Value::Number(150.0));
256
257 facts.add_value("Customer", Value::Object(customer_props))?;
258 facts.add_value("Order", Value::Object(order_props))?;
259
260 let mut kb = KnowledgeBase::new("EcommerceRules");
262
263 let new_customer_rule = Rule::new(
265 "NewCustomerDiscount".to_string(),
266 ConditionGroup::and(
267 ConditionGroup::single(Condition::new(
268 "Customer.IsNew".to_string(),
269 Operator::Equal,
270 Value::Boolean(true),
271 )),
272 ConditionGroup::single(Condition::new(
273 "Order.Amount".to_string(),
274 Operator::GreaterThan,
275 Value::Number(100.0),
276 )),
277 ),
278 vec![
279 ActionType::MethodCall {
280 object: "Order".to_string(),
281 method: "setDiscountPercent".to_string(),
282 args: vec![Value::Number(10.0)],
283 },
284 ActionType::MethodCall {
285 object: "Customer".to_string(),
286 method: "setLoyaltyPoints".to_string(),
287 args: vec![Value::Integer(100)],
288 },
289 ActionType::Call {
290 function: "log".to_string(),
291 args: vec![Value::String("New customer discount applied".to_string())],
292 },
293 ],
294 )
295 .with_salience(10);
296
297 let calculate_final_rule = Rule::new(
299 "CalculateFinalAmount".to_string(),
300 ConditionGroup::single(Condition::new(
301 "Order.DiscountPercent".to_string(),
302 Operator::GreaterThan,
303 Value::Number(0.0),
304 )),
305 vec![ActionType::Call {
306 function: "log".to_string(),
307 args: vec![Value::String(
308 "Calculating final amount with discount".to_string(),
309 )],
310 }],
311 )
312 .with_salience(5);
313
314 let _ = kb.add_rule(new_customer_rule);
316 let _ = kb.add_rule(calculate_final_rule);
317
318 let config = EngineConfig {
320 debug_mode: true,
321 max_cycles: 3,
322 ..Default::default()
323 };
324 let engine = RustRuleEngine::with_config(kb, config);
325
326 println!("š Initial e-commerce state:");
327 if let Some(customer) = facts.get("Customer") {
328 println!(" Customer = {customer:?}");
329 }
330 if let Some(order) = facts.get("Order") {
331 println!(" Order = {order:?}");
332 }
333 println!();
334
335 println!("š Executing e-commerce rules...");
337 let result = engine.execute(&facts)?;
338
339 println!("\nš E-commerce Results:");
340 println!(" Cycles: {}", result.cycle_count);
341 println!(" Rules evaluated: {}", result.rules_evaluated);
342 println!(" Rules fired: {}", result.rules_fired);
343 println!(" Execution time: {:?}", result.execution_time);
344
345 println!("\nš Final e-commerce state:");
346 if let Some(customer) = facts.get("Customer") {
347 println!(" Customer = {customer:?}");
348 }
349 if let Some(order) = facts.get("Order") {
350 println!(" Order = {order:?}");
351 }
352
353 println!("\nšÆ Demo Completed Successfully!");
354 println!(" ā
Knowledge Base management");
355 println!(" ā
Facts manipulation");
356 println!(" ā
Rule execution engine");
357 println!(" ā
E-commerce scenario");
358 println!(" ā
Method calls and function calls");
359 println!(" ā
Salience-based rule ordering");
360
361 Ok(())
362}