pub struct Rule {
pub name: String,
pub description: Option<String>,
pub salience: i32,
pub enabled: bool,
pub conditions: ConditionGroup,
pub actions: Vec<ActionType>,
}Expand description
A rule with conditions and actions
Fields§
§name: StringThe unique name of the rule
description: Option<String>Optional description of what the rule does
salience: i32Priority of the rule (higher values execute first)
enabled: boolWhether the rule is enabled for execution
conditions: ConditionGroupThe conditions that must be met for the rule to fire
actions: Vec<ActionType>The actions to execute when the rule fires
Implementations§
Source§impl Rule
impl Rule
Sourcepub fn new(
name: String,
conditions: ConditionGroup,
actions: Vec<ActionType>,
) -> Self
pub fn new( name: String, conditions: ConditionGroup, actions: Vec<ActionType>, ) -> Self
Create a new rule with the given name, conditions, and actions
Examples found in repository?
examples/generic_method_calls.rs (lines 40-52)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("=== Demo: Generic Method Calls ===\n");
10
11 // Create objects with various properties
12 let mut car_props = HashMap::new();
13 car_props.insert("Speed".to_string(), Value::Number(50.0));
14 car_props.insert("Fuel".to_string(), Value::Number(80.0));
15 car_props.insert("Brand".to_string(), Value::String("Toyota".to_string()));
16
17 let mut account_props = HashMap::new();
18 account_props.insert("Balance".to_string(), Value::Number(1000.0));
19 account_props.insert("Owner".to_string(), Value::String("John Doe".to_string()));
20 account_props.insert("Active".to_string(), Value::Boolean(true));
21
22 // Create facts
23 let facts = Facts::new();
24 facts.add_value("Car", Value::Object(car_props))?;
25 facts.add_value("Account", Value::Object(account_props))?;
26
27 println!("🏁 Initial state:");
28 if let Some(car) = facts.get("Car") {
29 println!(" Car = {car:?}");
30 }
31 if let Some(account) = facts.get("Account") {
32 println!(" Account = {account:?}");
33 }
34 println!();
35
36 // Create knowledge base
37 let mut kb = KnowledgeBase::new("GenericMethodDemo");
38
39 // Rule 1: Speed up car if speed < 60
40 let speed_rule = Rule::new(
41 "SpeedUpCar".to_string(),
42 ConditionGroup::single(Condition::new(
43 "Car.Speed".to_string(),
44 Operator::LessThan,
45 Value::Number(60.0),
46 )),
47 vec![ActionType::MethodCall {
48 object: "Car".to_string(),
49 method: "setSpeed".to_string(), // Generic setter
50 args: vec![Value::Number(75.0)],
51 }],
52 )
53 .with_salience(10);
54
55 // Rule 2: Withdraw from account if balance > 500
56 let withdraw_rule = Rule::new(
57 "WithdrawMoney".to_string(),
58 ConditionGroup::single(Condition::new(
59 "Account.Balance".to_string(),
60 Operator::GreaterThan,
61 Value::Number(500.0),
62 )),
63 vec![ActionType::MethodCall {
64 object: "Account".to_string(),
65 method: "setBalance".to_string(), // Generic setter
66 args: vec![Value::Number(800.0)],
67 }],
68 )
69 .with_salience(5);
70
71 // Rule 3: Update car brand using generic setter
72 let brand_rule = Rule::new(
73 "UpdateBrand".to_string(),
74 ConditionGroup::single(Condition::new(
75 "Car.Brand".to_string(),
76 Operator::Equal,
77 Value::String("Toyota".to_string()),
78 )),
79 vec![ActionType::MethodCall {
80 object: "Car".to_string(),
81 method: "setBrand".to_string(), // Generic setter
82 args: vec![Value::String("Honda".to_string())],
83 }],
84 )
85 .with_salience(3);
86
87 // Add rules to knowledge base
88 let _ = kb.add_rule(speed_rule);
89 let _ = kb.add_rule(withdraw_rule);
90 let _ = kb.add_rule(brand_rule);
91
92 // Create engine with debug mode
93 let config = EngineConfig {
94 debug_mode: true,
95 max_cycles: 10,
96 ..Default::default()
97 };
98 let engine = RustRuleEngine::with_config(kb, config);
99
100 // Execute rules
101 println!("🚀 Executing rules with generic method calls...");
102 let result = engine.execute(&facts)?;
103
104 println!("\n📊 Execution Results:");
105 println!(" Cycles: {}", result.cycle_count);
106 println!(" Rules evaluated: {}", result.rules_evaluated);
107 println!(" Rules fired: {}", result.rules_fired);
108 println!(" Execution time: {:?}", result.execution_time);
109
110 println!("\n🏁 Final state:");
111 if let Some(car) = facts.get("Car") {
112 println!(" Car = {car:?}");
113 }
114 if let Some(account) = facts.get("Account") {
115 println!(" Account = {account:?}");
116 }
117
118 // Demonstrate generic getters
119 println!("\n🔍 Testing generic getters:");
120 if let Some(car_value) = facts.get("Car") {
121 if let Value::Object(car_obj) = car_value {
122 println!(
123 " Car.Speed via getter would return: {:?}",
124 car_obj.get("Speed")
125 );
126 println!(
127 " Car.Brand via getter would return: {:?}",
128 car_obj.get("Brand")
129 );
130 println!(
131 " Car.Fuel via getter would return: {:?}",
132 car_obj.get("Fuel")
133 );
134 }
135 }
136
137 Ok(())
138}More examples
examples/grule_demo.rs (lines 89-119)
68fn demo_engine_execution() -> std::result::Result<(), Box<dyn std::error::Error>> {
69 println!("🚀 Demo 3: Engine Execution");
70 println!("---------------------------");
71
72 // Create facts
73 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 // Create knowledge base
86 let mut kb = KnowledgeBase::new("UserRules");
87
88 // Rule 1: Adult Check (salience 10)
89 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 // Rule 2: VIP Check (salience 20)
123 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 // Rule 3: Senior Discount (salience 15)
164 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 // Add rules to knowledge base
191 let _ = kb.add_rule(adult_rule);
192 let _ = kb.add_rule(vip_rule);
193 let _ = kb.add_rule(senior_rule);
194
195 // Create engine
196 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 // Execute rules
210 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 // Create facts
233 let facts = Facts::new();
234
235 // Customer data
236 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 // Order data
247 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 // Create knowledge base
261 let mut kb = KnowledgeBase::new("EcommerceRules");
262
263 // Rule 1: New Customer Discount
264 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 // Rule 2: Calculate Final Amount
298 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 // Add rules
315 let _ = kb.add_rule(new_customer_rule);
316 let _ = kb.add_rule(calculate_final_rule);
317
318 // Create engine
319 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 // Execute rules
336 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}examples/function_calls_demo.rs (lines 47-61)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("=== Demo: Generic Function Calls ===\n");
10
11 // Create test data
12 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 // Create facts
26 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 // Create knowledge base
44 let mut kb = KnowledgeBase::new("FunctionCallDemo");
45
46 // Rule 1: Log message if user is active
47 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 // Rule 2: Calculate statistics if score > 80
65 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 // Rule 3: String manipulation
102 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 // Rule 4: Mathematical functions
134 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 // Rule 5: Utility functions
163 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 // Add rules to knowledge base
195 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 // Create engine with debug mode
202 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 // Execute rules
210 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}examples/custom_functions_demo.rs (lines 44-64)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("🎯 Custom Function Calls Demo");
10 println!("=============================\n");
11
12 // Create facts
13 let facts = Facts::new();
14
15 // Car data
16 let mut car_props = HashMap::new();
17 car_props.insert("Speed".to_string(), Value::Number(60.0));
18 car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
19 car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
20 car_props.insert("IsRunning".to_string(), Value::Boolean(true));
21
22 // Driver data
23 let mut driver_props = HashMap::new();
24 driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
25 driver_props.insert("Experience".to_string(), Value::Integer(5));
26 driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
27
28 facts.add_value("Car", Value::Object(car_props))?;
29 facts.add_value("Driver", Value::Object(driver_props))?;
30
31 println!("🏁 Initial state:");
32 if let Some(car) = facts.get("Car") {
33 println!(" Car = {car:?}");
34 }
35 if let Some(driver) = facts.get("Driver") {
36 println!(" Driver = {driver:?}");
37 }
38 println!();
39
40 // Create knowledge base
41 let mut kb = KnowledgeBase::new("CustomFunctionRules");
42
43 // Rule 1: Speed Check with custom function
44 let speed_check_rule = Rule::new(
45 "SpeedCheck".to_string(),
46 ConditionGroup::single(Condition::new(
47 "Car.Speed".to_string(),
48 Operator::GreaterThan,
49 Value::Number(80.0),
50 )),
51 vec![
52 ActionType::Call {
53 function: "checkSpeedLimit".to_string(),
54 args: vec![Value::String("Car.Speed".to_string()), Value::Number(80.0)],
55 },
56 ActionType::Call {
57 function: "sendAlert".to_string(),
58 args: vec![
59 Value::String("Speed limit exceeded!".to_string()),
60 Value::String("Driver.Name".to_string()),
61 ],
62 },
63 ],
64 )
65 .with_salience(20);
66
67 // Rule 2: Driver validation
68 let driver_validation_rule = Rule::new(
69 "DriverValidation".to_string(),
70 ConditionGroup::single(Condition::new(
71 "Driver.License".to_string(),
72 Operator::Equal,
73 Value::String("VALID".to_string()),
74 )),
75 vec![
76 ActionType::Call {
77 function: "validateDriver".to_string(),
78 args: vec![
79 Value::String("Driver.Name".to_string()),
80 Value::String("Driver.Experience".to_string()),
81 ],
82 },
83 ActionType::Call {
84 function: "calculateInsurance".to_string(),
85 args: vec![
86 Value::String("Driver.Experience".to_string()),
87 Value::String("Car.Engine".to_string()),
88 ],
89 },
90 ],
91 )
92 .with_salience(15);
93
94 // Rule 3: Engine diagnostics
95 let engine_diagnostics_rule = Rule::new(
96 "EngineDiagnostics".to_string(),
97 ConditionGroup::single(Condition::new(
98 "Car.IsRunning".to_string(),
99 Operator::Equal,
100 Value::Boolean(true),
101 )),
102 vec![
103 ActionType::Call {
104 function: "performDiagnostics".to_string(),
105 args: vec![
106 Value::String("Car.Engine".to_string()),
107 Value::String("Car.Speed".to_string()),
108 ],
109 },
110 ActionType::Call {
111 function: "optimizePerformance".to_string(),
112 args: vec![
113 Value::String("Car.Speed".to_string()),
114 Value::String("Car.MaxSpeed".to_string()),
115 ],
116 },
117 ],
118 )
119 .with_salience(10);
120
121 // Add rules to knowledge base
122 let _ = kb.add_rule(speed_check_rule);
123 let _ = kb.add_rule(driver_validation_rule);
124 let _ = kb.add_rule(engine_diagnostics_rule);
125
126 // Create engine
127 let config = EngineConfig {
128 debug_mode: true,
129 max_cycles: 3,
130 ..Default::default()
131 };
132 let mut engine = RustRuleEngine::with_config(kb, config);
133
134 // Register custom functions
135 println!("📝 Registering custom functions...");
136
137 // Function 1: Check speed limit
138 engine.register_function("checkSpeedLimit", |args, facts| {
139 let speed_field = args.get(0).unwrap().to_string();
140 let limit = args.get(1).unwrap();
141
142 // Get actual speed value from facts
143 let speed = if let Some(car) = facts.get("Car") {
144 if let Value::Object(obj) = car {
145 obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
146 } else {
147 Value::Number(0.0)
148 }
149 } else {
150 Value::Number(0.0)
151 };
152
153 let result = format!("Speed check: {:?} vs limit {:?}", speed, limit);
154 println!("🚦 {}", result);
155 Ok(Value::String(result))
156 });
157
158 // Function 2: Send alert
159 engine.register_function("sendAlert", |args, facts| {
160 let message = args.get(0).unwrap().to_string();
161 let driver_field = args.get(1).unwrap().to_string();
162
163 // Get driver name from facts
164 let driver_name = if let Some(driver) = facts.get("Driver") {
165 if let Value::Object(obj) = driver {
166 obj.get("Name")
167 .cloned()
168 .unwrap_or(Value::String("Unknown".to_string()))
169 } else {
170 Value::String("Unknown".to_string())
171 }
172 } else {
173 Value::String("Unknown".to_string())
174 };
175
176 let alert = format!("🚨 ALERT to {:?}: {}", driver_name, message);
177 println!("{}", alert);
178 Ok(Value::String(alert))
179 });
180
181 // Function 3: Validate driver
182 engine.register_function("validateDriver", |args, _facts| {
183 let name_field = args.get(0).unwrap().to_string();
184 let exp_field = args.get(1).unwrap().to_string();
185
186 let result = format!(
187 "✅ Driver validation passed for {} (experience: {})",
188 name_field, exp_field
189 );
190 println!("{}", result);
191 Ok(Value::String(result))
192 });
193
194 // Function 4: Calculate insurance
195 engine.register_function("calculateInsurance", |args, _facts| {
196 let exp_field = args.get(0).unwrap().to_string();
197 let engine_field = args.get(1).unwrap().to_string();
198
199 let result = format!(
200 "💰 Insurance calculated: Experience {} + Engine {} = Premium rate",
201 exp_field, engine_field
202 );
203 println!("{}", result);
204 Ok(Value::String(result))
205 });
206
207 // Function 5: Perform diagnostics
208 engine.register_function("performDiagnostics", |args, _facts| {
209 let engine_field = args.get(0).unwrap().to_string();
210 let speed_field = args.get(1).unwrap().to_string();
211
212 let result = format!(
213 "🔧 Diagnostics: Engine {} running at speed {} - All systems OK",
214 engine_field, speed_field
215 );
216 println!("{}", result);
217 Ok(Value::String(result))
218 });
219
220 // Function 6: Optimize performance
221 engine.register_function("optimizePerformance", |args, _facts| {
222 let current_speed = args.get(0).unwrap().to_string();
223 let max_speed = args.get(1).unwrap().to_string();
224
225 let result = format!(
226 "⚡ Performance optimization: Current {} / Max {} - Efficiency tuned",
227 current_speed, max_speed
228 );
229 println!("{}", result);
230 Ok(Value::String(result))
231 });
232
233 println!("✅ Registered {} custom functions:", 6);
234 println!(" 🚦 checkSpeedLimit - Check if speed exceeds limit");
235 println!(" 🚨 sendAlert - Send alert message to driver");
236 println!(" ✅ validateDriver - Validate driver credentials");
237 println!(" 💰 calculateInsurance - Calculate insurance premium");
238 println!(" 🔧 performDiagnostics - Run engine diagnostics");
239 println!(" ⚡ optimizePerformance - Optimize engine performance");
240 println!();
241
242 // Execute rules
243 println!("🚀 Executing rules with custom functions...");
244 let result = engine.execute(&facts)?;
245
246 println!("\n📊 Custom Function Execution Results:");
247 println!(" Cycles: {}", result.cycle_count);
248 println!(" Rules evaluated: {}", result.rules_evaluated);
249 println!(" Rules fired: {}", result.rules_fired);
250 println!(" Execution time: {:?}", result.execution_time);
251
252 println!("\n🏁 Final state:");
253 if let Some(car) = facts.get("Car") {
254 println!(" Car = {car:?}");
255 }
256 if let Some(driver) = facts.get("Driver") {
257 println!(" Driver = {driver:?}");
258 }
259
260 println!("\n🎯 Custom Function Calls Demonstrated:");
261 println!(" 📞 User-defined functions called from rules");
262 println!(" 🔧 Custom business logic execution");
263 println!(" 🎪 Function registry system");
264 println!(" 📋 Rule-based custom function invocation");
265 println!(" ⚡ Real-time function parameter resolution");
266
267 Ok(())
268}examples/fraud_detection.rs (lines 59-90)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("=== Demo: Fraud Detection System ===\n");
10
11 // Create transaction data
12 let mut transaction_props = HashMap::new();
13 transaction_props.insert("Amount".to_string(), Value::Number(5000.0));
14 transaction_props.insert("Location".to_string(), Value::String("FOREIGN".to_string()));
15 transaction_props.insert("Time".to_string(), Value::String("02:30".to_string()));
16 transaction_props.insert("CardType".to_string(), Value::String("CREDIT".to_string()));
17 transaction_props.insert(
18 "MerchantCategory".to_string(),
19 Value::String("CASINO".to_string()),
20 );
21
22 let mut account_props = HashMap::new();
23 account_props.insert("Balance".to_string(), Value::Number(2000.0));
24 account_props.insert("DailyLimit".to_string(), Value::Number(3000.0));
25 account_props.insert("RiskLevel".to_string(), Value::String("LOW".to_string()));
26 account_props.insert("IsActive".to_string(), Value::Boolean(true));
27 account_props.insert(
28 "LastLoginLocation".to_string(),
29 Value::String("DOMESTIC".to_string()),
30 );
31
32 let mut alert_props = HashMap::new();
33 alert_props.insert("FraudScore".to_string(), Value::Number(0.0));
34 alert_props.insert("Status".to_string(), Value::String("PENDING".to_string()));
35 alert_props.insert("Alerts".to_string(), Value::Array(vec![]));
36
37 // Create facts
38 let facts = Facts::new();
39 facts.add_value("Transaction", Value::Object(transaction_props))?;
40 facts.add_value("Account", Value::Object(account_props))?;
41 facts.add_value("Alert", Value::Object(alert_props))?;
42
43 println!("🏁 Initial transaction data:");
44 if let Some(transaction) = facts.get("Transaction") {
45 println!(" Transaction = {transaction:?}");
46 }
47 if let Some(account) = facts.get("Account") {
48 println!(" Account = {account:?}");
49 }
50 if let Some(alert) = facts.get("Alert") {
51 println!(" Alert = {alert:?}");
52 }
53 println!();
54
55 // Create knowledge base
56 let mut kb = KnowledgeBase::new("FraudDetectionSystem");
57
58 // Rule 1: High Amount Transaction Alert
59 let high_amount_rule = Rule::new(
60 "HighAmountAlert".to_string(),
61 ConditionGroup::and(
62 ConditionGroup::single(Condition::new(
63 "Transaction.Amount".to_string(),
64 Operator::GreaterThan,
65 Value::Number(3000.0),
66 )),
67 ConditionGroup::single(Condition::new(
68 "Account.DailyLimit".to_string(),
69 Operator::LessThan,
70 Value::String("Transaction.Amount".to_string()),
71 )),
72 ),
73 vec![
74 ActionType::Call {
75 function: "log".to_string(),
76 args: vec![Value::String(
77 "HIGH AMOUNT ALERT: Transaction exceeds daily limit".to_string(),
78 )],
79 },
80 ActionType::MethodCall {
81 object: "Alert".to_string(),
82 method: "setFraudScore".to_string(),
83 args: vec![Value::Number(50.0)],
84 },
85 ActionType::Set {
86 field: "Alert.Status".to_string(),
87 value: Value::String("FLAGGED".to_string()),
88 },
89 ],
90 )
91 .with_salience(10);
92
93 // Rule 2: Foreign Location Alert
94 let foreign_location_rule = Rule::new(
95 "ForeignLocationAlert".to_string(),
96 ConditionGroup::and(
97 ConditionGroup::single(Condition::new(
98 "Transaction.Location".to_string(),
99 Operator::Equal,
100 Value::String("FOREIGN".to_string()),
101 )),
102 ConditionGroup::single(Condition::new(
103 "Account.LastLoginLocation".to_string(),
104 Operator::Equal,
105 Value::String("DOMESTIC".to_string()),
106 )),
107 ),
108 vec![
109 ActionType::Call {
110 function: "log".to_string(),
111 args: vec![Value::String(
112 "LOCATION ALERT: Foreign transaction detected".to_string(),
113 )],
114 },
115 ActionType::Call {
116 function: "sum".to_string(),
117 args: vec![
118 Value::String("Alert.FraudScore".to_string()),
119 Value::Number(30.0),
120 ],
121 },
122 ],
123 )
124 .with_salience(8);
125
126 // Rule 3: Late Night Transaction Alert
127 let late_night_rule = Rule::new(
128 "LateNightAlert".to_string(),
129 ConditionGroup::single(Condition::new(
130 "Transaction.Time".to_string(),
131 Operator::Contains,
132 Value::String("02:".to_string()),
133 )),
134 vec![
135 ActionType::Call {
136 function: "log".to_string(),
137 args: vec![Value::String(
138 "TIME ALERT: Late night transaction".to_string(),
139 )],
140 },
141 ActionType::MethodCall {
142 object: "Alert".to_string(),
143 method: "setFraudScore".to_string(),
144 args: vec![Value::Number(20.0)],
145 },
146 ],
147 )
148 .with_salience(6);
149
150 // Rule 4: High Risk Merchant Category
151 let high_risk_merchant_rule = Rule::new(
152 "HighRiskMerchantAlert".to_string(),
153 ConditionGroup::single(Condition::new(
154 "Transaction.MerchantCategory".to_string(),
155 Operator::Equal,
156 Value::String("CASINO".to_string()),
157 )),
158 vec![
159 ActionType::Call {
160 function: "log".to_string(),
161 args: vec![Value::String(
162 "MERCHANT ALERT: High-risk merchant category".to_string(),
163 )],
164 },
165 ActionType::MethodCall {
166 object: "Alert".to_string(),
167 method: "setFraudScore".to_string(),
168 args: vec![Value::Number(40.0)],
169 },
170 ],
171 )
172 .with_salience(7);
173
174 // Rule 5: Critical Fraud Score Alert
175 let critical_fraud_rule = Rule::new(
176 "CriticalFraudAlert".to_string(),
177 ConditionGroup::single(Condition::new(
178 "Alert.FraudScore".to_string(),
179 Operator::GreaterThanOrEqual,
180 Value::Number(70.0),
181 )),
182 vec![
183 ActionType::Call {
184 function: "log".to_string(),
185 args: vec![Value::String(
186 "🚨 CRITICAL FRAUD ALERT! Blocking transaction!".to_string(),
187 )],
188 },
189 ActionType::Set {
190 field: "Alert.Status".to_string(),
191 value: Value::String("BLOCKED".to_string()),
192 },
193 ActionType::Call {
194 function: "format".to_string(),
195 args: vec![
196 Value::String("Transaction #{0} BLOCKED - Fraud Score: {1}".to_string()),
197 Value::String("TX123456".to_string()),
198 Value::String("Alert.FraudScore".to_string()),
199 ],
200 },
201 ],
202 )
203 .with_salience(15);
204
205 // Rule 6: Account Insufficient Funds
206 let insufficient_funds_rule = Rule::new(
207 "InsufficientFundsAlert".to_string(),
208 ConditionGroup::single(Condition::new(
209 "Account.Balance".to_string(),
210 Operator::LessThan,
211 Value::String("Transaction.Amount".to_string()),
212 )),
213 vec![
214 ActionType::Call {
215 function: "log".to_string(),
216 args: vec![Value::String(
217 "💰 INSUFFICIENT FUNDS: Transaction declined".to_string(),
218 )],
219 },
220 ActionType::Set {
221 field: "Alert.Status".to_string(),
222 value: Value::String("DECLINED".to_string()),
223 },
224 ],
225 )
226 .with_salience(20); // Highest priority
227
228 // Add rules to knowledge base
229 let _ = kb.add_rule(high_amount_rule);
230 let _ = kb.add_rule(foreign_location_rule);
231 let _ = kb.add_rule(late_night_rule);
232 let _ = kb.add_rule(high_risk_merchant_rule);
233 let _ = kb.add_rule(critical_fraud_rule);
234 let _ = kb.add_rule(insufficient_funds_rule);
235
236 // Create engine with debug mode
237 let config = EngineConfig {
238 debug_mode: true,
239 max_cycles: 10,
240 ..Default::default()
241 };
242 let engine = RustRuleEngine::with_config(kb, config);
243
244 println!("🔍 Running fraud detection analysis...");
245 let result = engine.execute(&facts)?;
246
247 println!("\n📊 Fraud Detection Results:");
248 println!(" Cycles: {}", result.cycle_count);
249 println!(" Rules evaluated: {}", result.rules_evaluated);
250 println!(" Rules fired: {}", result.rules_fired);
251 println!(" Execution time: {:?}", result.execution_time);
252
253 println!("\n🏁 Final analysis:");
254 if let Some(transaction) = facts.get("Transaction") {
255 println!(" Transaction = {transaction:?}");
256 }
257 if let Some(account) = facts.get("Account") {
258 println!(" Account = {account:?}");
259 }
260 if let Some(alert) = facts.get("Alert") {
261 println!(" Alert = {alert:?}");
262 }
263
264 println!("\n🎯 Fraud Detection Rules Demonstrated:");
265 println!(" 🚨 High Amount Transactions");
266 println!(" 🌍 Foreign Location Detection");
267 println!(" 🌙 Late Night Activity");
268 println!(" 🎰 High-Risk Merchant Categories");
269 println!(" ⚠️ Critical Fraud Score Alerts");
270 println!(" 💰 Insufficient Funds Checks");
271
272 Ok(())
273}examples/ecommerce.rs (lines 65-102)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("=== E-commerce Rules Demo ===");
10 println!("==============================\n");
11
12 // Create customer data
13 let mut customer_props = HashMap::new();
14 customer_props.insert("IsNew".to_string(), Value::Boolean(true));
15 customer_props.insert(
16 "Membership".to_string(),
17 Value::String("standard".to_string()),
18 );
19 customer_props.insert("TotalSpent".to_string(), Value::Number(750.0));
20 customer_props.insert("WelcomeEmailSent".to_string(), Value::Boolean(false));
21
22 // Create order data
23 let mut order_props = HashMap::new();
24 order_props.insert("Total".to_string(), Value::Number(75.0));
25 order_props.insert("ItemCount".to_string(), Value::Integer(2));
26 order_props.insert(
27 "Category".to_string(),
28 Value::String("clothing".to_string()),
29 );
30 order_props.insert("DiscountRate".to_string(), Value::Number(0.0));
31 order_props.insert("FreeShipping".to_string(), Value::Boolean(false));
32 order_props.insert(
33 "DiscountType".to_string(),
34 Value::String("none".to_string()),
35 );
36
37 // Create promotion data
38 let mut promotion_props = HashMap::new();
39 promotion_props.insert("SeasonalDiscount".to_string(), Value::Number(0.05));
40 promotion_props.insert("BulkDiscount".to_string(), Value::Number(0.10));
41 promotion_props.insert("Active".to_string(), Value::Boolean(true));
42
43 // Create facts
44 let facts = Facts::new();
45 facts.add_value("Customer", Value::Object(customer_props))?;
46 facts.add_value("Order", Value::Object(order_props))?;
47 facts.add_value("Promotion", Value::Object(promotion_props))?;
48
49 println!("🏁 Initial e-commerce data:");
50 if let Some(customer) = facts.get("Customer") {
51 println!(" Customer = {customer:?}");
52 }
53 if let Some(order) = facts.get("Order") {
54 println!(" Order = {order:?}");
55 }
56 if let Some(promotion) = facts.get("Promotion") {
57 println!(" Promotion = {promotion:?}");
58 }
59 println!();
60
61 // Create knowledge base
62 let mut kb = KnowledgeBase::new("EcommerceRules");
63
64 // Rule 1: New Customer Discount (salience 25)
65 let new_customer_rule = Rule::new(
66 "NewCustomerDiscount".to_string(),
67 ConditionGroup::and(
68 ConditionGroup::single(Condition::new(
69 "Customer.IsNew".to_string(),
70 Operator::Equal,
71 Value::Boolean(true),
72 )),
73 ConditionGroup::single(Condition::new(
74 "Order.Total".to_string(),
75 Operator::GreaterThan,
76 Value::Number(50.0),
77 )),
78 ),
79 vec![
80 ActionType::MethodCall {
81 object: "Order".to_string(),
82 method: "setDiscountRate".to_string(),
83 args: vec![Value::Number(0.10)],
84 },
85 ActionType::MethodCall {
86 object: "Order".to_string(),
87 method: "setDiscountType".to_string(),
88 args: vec![Value::String("welcome".to_string())],
89 },
90 ActionType::MethodCall {
91 object: "Customer".to_string(),
92 method: "setWelcomeEmailSent".to_string(),
93 args: vec![Value::Boolean(true)],
94 },
95 ActionType::Call {
96 function: "log".to_string(),
97 args: vec![Value::String(
98 "New customer welcome discount applied".to_string(),
99 )],
100 },
101 ],
102 )
103 .with_salience(25);
104
105 // Rule 2: Premium Member Benefits (salience 20)
106 let premium_member_rule = Rule::new(
107 "PremiumMemberBenefits".to_string(),
108 ConditionGroup::and(
109 ConditionGroup::single(Condition::new(
110 "Customer.Membership".to_string(),
111 Operator::Equal,
112 Value::String("premium".to_string()),
113 )),
114 ConditionGroup::single(Condition::new(
115 "Order.Total".to_string(),
116 Operator::GreaterThan,
117 Value::Number(100.0),
118 )),
119 ),
120 vec![
121 ActionType::MethodCall {
122 object: "Order".to_string(),
123 method: "setDiscountRate".to_string(),
124 args: vec![Value::Number(0.15)],
125 },
126 ActionType::MethodCall {
127 object: "Order".to_string(),
128 method: "setFreeShipping".to_string(),
129 args: vec![Value::Boolean(true)],
130 },
131 ActionType::Call {
132 function: "log".to_string(),
133 args: vec![Value::String("Premium member benefits applied".to_string())],
134 },
135 ],
136 )
137 .with_salience(20);
138
139 // Rule 3: VIP Upgrade (salience 30)
140 let vip_upgrade_rule = Rule::new(
141 "VIPUpgrade".to_string(),
142 ConditionGroup::and(
143 ConditionGroup::single(Condition::new(
144 "Customer.TotalSpent".to_string(),
145 Operator::GreaterThan,
146 Value::Number(1000.0),
147 )),
148 ConditionGroup::single(Condition::new(
149 "Customer.Membership".to_string(),
150 Operator::NotEqual,
151 Value::String("VIP".to_string()),
152 )),
153 ),
154 vec![
155 ActionType::MethodCall {
156 object: "Customer".to_string(),
157 method: "setMembership".to_string(),
158 args: vec![Value::String("VIP".to_string())],
159 },
160 ActionType::MethodCall {
161 object: "Order".to_string(),
162 method: "setDiscountRate".to_string(),
163 args: vec![Value::Number(0.25)],
164 },
165 ActionType::Call {
166 function: "log".to_string(),
167 args: vec![Value::String(
168 "Customer upgraded to VIP membership".to_string(),
169 )],
170 },
171 ],
172 )
173 .with_salience(30);
174
175 // Rule 4: Free Shipping for Large Orders (salience 15)
176 let free_shipping_rule = Rule::new(
177 "FreeShippingLargeOrders".to_string(),
178 ConditionGroup::single(Condition::new(
179 "Order.Total".to_string(),
180 Operator::GreaterThanOrEqual,
181 Value::Number(100.0),
182 )),
183 vec![
184 ActionType::MethodCall {
185 object: "Order".to_string(),
186 method: "setFreeShipping".to_string(),
187 args: vec![Value::Boolean(true)],
188 },
189 ActionType::Call {
190 function: "log".to_string(),
191 args: vec![Value::String(
192 "Free shipping applied for large order".to_string(),
193 )],
194 },
195 ],
196 )
197 .with_salience(15);
198
199 // Rule 5: Bulk Discount (salience 12)
200 let bulk_discount_rule = Rule::new(
201 "BulkDiscount".to_string(),
202 ConditionGroup::single(Condition::new(
203 "Order.ItemCount".to_string(),
204 Operator::GreaterThanOrEqual,
205 Value::Integer(5),
206 )),
207 vec![
208 ActionType::Call {
209 function: "max".to_string(),
210 args: vec![
211 Value::String("Order.DiscountRate".to_string()),
212 Value::Number(0.10),
213 ],
214 },
215 ActionType::Call {
216 function: "log".to_string(),
217 args: vec![Value::String("Bulk discount applied".to_string())],
218 },
219 ],
220 )
221 .with_salience(12);
222
223 // Rule 6: Seasonal Promotion (salience 10)
224 let seasonal_promotion_rule = Rule::new(
225 "SeasonalPromotion".to_string(),
226 ConditionGroup::and(
227 ConditionGroup::single(Condition::new(
228 "Promotion.Active".to_string(),
229 Operator::Equal,
230 Value::Boolean(true),
231 )),
232 ConditionGroup::single(Condition::new(
233 "Order.Category".to_string(),
234 Operator::Equal,
235 Value::String("clothing".to_string()),
236 )),
237 ),
238 vec![
239 ActionType::Call {
240 function: "max".to_string(),
241 args: vec![
242 Value::String("Order.DiscountRate".to_string()),
243 Value::String("Promotion.SeasonalDiscount".to_string()),
244 ],
245 },
246 ActionType::Call {
247 function: "log".to_string(),
248 args: vec![Value::String("Seasonal promotion applied".to_string())],
249 },
250 ],
251 )
252 .with_salience(10);
253
254 // Add rules to knowledge base
255 let _ = kb.add_rule(new_customer_rule);
256 let _ = kb.add_rule(premium_member_rule);
257 let _ = kb.add_rule(vip_upgrade_rule);
258 let _ = kb.add_rule(free_shipping_rule);
259 let _ = kb.add_rule(bulk_discount_rule);
260 let _ = kb.add_rule(seasonal_promotion_rule);
261
262 println!(
263 "📚 Knowledge Base loaded with {} rules",
264 kb.get_statistics().total_rules
265 );
266 println!("🔥 Rules: {:?}\n", kb.get_rule_names());
267
268 // Create engine with debug mode
269 let config = EngineConfig {
270 debug_mode: true,
271 max_cycles: 5,
272 ..Default::default()
273 };
274 let engine = RustRuleEngine::with_config(kb, config);
275
276 // Execute rules
277 println!("🚀 Executing e-commerce rules...");
278 let result = engine.execute(&facts)?;
279
280 println!("\n📊 E-commerce Execution Results:");
281 println!(" Cycles: {}", result.cycle_count);
282 println!(" Rules evaluated: {}", result.rules_evaluated);
283 println!(" Rules fired: {}", result.rules_fired);
284 println!(" Execution time: {:?}", result.execution_time);
285
286 println!("\n🏁 Final e-commerce state:");
287 if let Some(customer) = facts.get("Customer") {
288 println!(" Customer = {customer:?}");
289 }
290 if let Some(order) = facts.get("Order") {
291 println!(" Order = {order:?}");
292 }
293 if let Some(promotion) = facts.get("Promotion") {
294 println!(" Promotion = {promotion:?}");
295 }
296
297 println!("\n🎯 E-commerce Rules Demonstrated:");
298 println!(" 🎁 New Customer Welcome Discount");
299 println!(" 💎 Premium Member Benefits");
300 println!(" 🌟 VIP Membership Upgrades");
301 println!(" 🚚 Free Shipping Rules");
302 println!(" 📦 Bulk Purchase Discounts");
303 println!(" 🏷️ Seasonal Promotions");
304
305 Ok(())
306}Sourcepub fn with_description(self, description: String) -> Self
pub fn with_description(self, description: String) -> Self
Add a description to the rule
Sourcepub fn with_salience(self, salience: i32) -> Self
pub fn with_salience(self, salience: i32) -> Self
Set the salience (priority) of the rule
Examples found in repository?
examples/generic_method_calls.rs (line 53)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("=== Demo: Generic Method Calls ===\n");
10
11 // Create objects with various properties
12 let mut car_props = HashMap::new();
13 car_props.insert("Speed".to_string(), Value::Number(50.0));
14 car_props.insert("Fuel".to_string(), Value::Number(80.0));
15 car_props.insert("Brand".to_string(), Value::String("Toyota".to_string()));
16
17 let mut account_props = HashMap::new();
18 account_props.insert("Balance".to_string(), Value::Number(1000.0));
19 account_props.insert("Owner".to_string(), Value::String("John Doe".to_string()));
20 account_props.insert("Active".to_string(), Value::Boolean(true));
21
22 // Create facts
23 let facts = Facts::new();
24 facts.add_value("Car", Value::Object(car_props))?;
25 facts.add_value("Account", Value::Object(account_props))?;
26
27 println!("🏁 Initial state:");
28 if let Some(car) = facts.get("Car") {
29 println!(" Car = {car:?}");
30 }
31 if let Some(account) = facts.get("Account") {
32 println!(" Account = {account:?}");
33 }
34 println!();
35
36 // Create knowledge base
37 let mut kb = KnowledgeBase::new("GenericMethodDemo");
38
39 // Rule 1: Speed up car if speed < 60
40 let speed_rule = Rule::new(
41 "SpeedUpCar".to_string(),
42 ConditionGroup::single(Condition::new(
43 "Car.Speed".to_string(),
44 Operator::LessThan,
45 Value::Number(60.0),
46 )),
47 vec![ActionType::MethodCall {
48 object: "Car".to_string(),
49 method: "setSpeed".to_string(), // Generic setter
50 args: vec![Value::Number(75.0)],
51 }],
52 )
53 .with_salience(10);
54
55 // Rule 2: Withdraw from account if balance > 500
56 let withdraw_rule = Rule::new(
57 "WithdrawMoney".to_string(),
58 ConditionGroup::single(Condition::new(
59 "Account.Balance".to_string(),
60 Operator::GreaterThan,
61 Value::Number(500.0),
62 )),
63 vec![ActionType::MethodCall {
64 object: "Account".to_string(),
65 method: "setBalance".to_string(), // Generic setter
66 args: vec![Value::Number(800.0)],
67 }],
68 )
69 .with_salience(5);
70
71 // Rule 3: Update car brand using generic setter
72 let brand_rule = Rule::new(
73 "UpdateBrand".to_string(),
74 ConditionGroup::single(Condition::new(
75 "Car.Brand".to_string(),
76 Operator::Equal,
77 Value::String("Toyota".to_string()),
78 )),
79 vec![ActionType::MethodCall {
80 object: "Car".to_string(),
81 method: "setBrand".to_string(), // Generic setter
82 args: vec![Value::String("Honda".to_string())],
83 }],
84 )
85 .with_salience(3);
86
87 // Add rules to knowledge base
88 let _ = kb.add_rule(speed_rule);
89 let _ = kb.add_rule(withdraw_rule);
90 let _ = kb.add_rule(brand_rule);
91
92 // Create engine with debug mode
93 let config = EngineConfig {
94 debug_mode: true,
95 max_cycles: 10,
96 ..Default::default()
97 };
98 let engine = RustRuleEngine::with_config(kb, config);
99
100 // Execute rules
101 println!("🚀 Executing rules with generic method calls...");
102 let result = engine.execute(&facts)?;
103
104 println!("\n📊 Execution Results:");
105 println!(" Cycles: {}", result.cycle_count);
106 println!(" Rules evaluated: {}", result.rules_evaluated);
107 println!(" Rules fired: {}", result.rules_fired);
108 println!(" Execution time: {:?}", result.execution_time);
109
110 println!("\n🏁 Final state:");
111 if let Some(car) = facts.get("Car") {
112 println!(" Car = {car:?}");
113 }
114 if let Some(account) = facts.get("Account") {
115 println!(" Account = {account:?}");
116 }
117
118 // Demonstrate generic getters
119 println!("\n🔍 Testing generic getters:");
120 if let Some(car_value) = facts.get("Car") {
121 if let Value::Object(car_obj) = car_value {
122 println!(
123 " Car.Speed via getter would return: {:?}",
124 car_obj.get("Speed")
125 );
126 println!(
127 " Car.Brand via getter would return: {:?}",
128 car_obj.get("Brand")
129 );
130 println!(
131 " Car.Fuel via getter would return: {:?}",
132 car_obj.get("Fuel")
133 );
134 }
135 }
136
137 Ok(())
138}More examples
examples/grule_demo.rs (line 120)
68fn demo_engine_execution() -> std::result::Result<(), Box<dyn std::error::Error>> {
69 println!("🚀 Demo 3: Engine Execution");
70 println!("---------------------------");
71
72 // Create facts
73 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 // Create knowledge base
86 let mut kb = KnowledgeBase::new("UserRules");
87
88 // Rule 1: Adult Check (salience 10)
89 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 // Rule 2: VIP Check (salience 20)
123 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 // Rule 3: Senior Discount (salience 15)
164 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 // Add rules to knowledge base
191 let _ = kb.add_rule(adult_rule);
192 let _ = kb.add_rule(vip_rule);
193 let _ = kb.add_rule(senior_rule);
194
195 // Create engine
196 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 // Execute rules
210 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 // Create facts
233 let facts = Facts::new();
234
235 // Customer data
236 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 // Order data
247 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 // Create knowledge base
261 let mut kb = KnowledgeBase::new("EcommerceRules");
262
263 // Rule 1: New Customer Discount
264 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 // Rule 2: Calculate Final Amount
298 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 // Add rules
315 let _ = kb.add_rule(new_customer_rule);
316 let _ = kb.add_rule(calculate_final_rule);
317
318 // Create engine
319 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 // Execute rules
336 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}examples/function_calls_demo.rs (line 62)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("=== Demo: Generic Function Calls ===\n");
10
11 // Create test data
12 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 // Create facts
26 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 // Create knowledge base
44 let mut kb = KnowledgeBase::new("FunctionCallDemo");
45
46 // Rule 1: Log message if user is active
47 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 // Rule 2: Calculate statistics if score > 80
65 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 // Rule 3: String manipulation
102 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 // Rule 4: Mathematical functions
134 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 // Rule 5: Utility functions
163 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 // Add rules to knowledge base
195 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 // Create engine with debug mode
202 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 // Execute rules
210 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}examples/custom_functions_demo.rs (line 65)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("🎯 Custom Function Calls Demo");
10 println!("=============================\n");
11
12 // Create facts
13 let facts = Facts::new();
14
15 // Car data
16 let mut car_props = HashMap::new();
17 car_props.insert("Speed".to_string(), Value::Number(60.0));
18 car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
19 car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
20 car_props.insert("IsRunning".to_string(), Value::Boolean(true));
21
22 // Driver data
23 let mut driver_props = HashMap::new();
24 driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
25 driver_props.insert("Experience".to_string(), Value::Integer(5));
26 driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
27
28 facts.add_value("Car", Value::Object(car_props))?;
29 facts.add_value("Driver", Value::Object(driver_props))?;
30
31 println!("🏁 Initial state:");
32 if let Some(car) = facts.get("Car") {
33 println!(" Car = {car:?}");
34 }
35 if let Some(driver) = facts.get("Driver") {
36 println!(" Driver = {driver:?}");
37 }
38 println!();
39
40 // Create knowledge base
41 let mut kb = KnowledgeBase::new("CustomFunctionRules");
42
43 // Rule 1: Speed Check with custom function
44 let speed_check_rule = Rule::new(
45 "SpeedCheck".to_string(),
46 ConditionGroup::single(Condition::new(
47 "Car.Speed".to_string(),
48 Operator::GreaterThan,
49 Value::Number(80.0),
50 )),
51 vec![
52 ActionType::Call {
53 function: "checkSpeedLimit".to_string(),
54 args: vec![Value::String("Car.Speed".to_string()), Value::Number(80.0)],
55 },
56 ActionType::Call {
57 function: "sendAlert".to_string(),
58 args: vec![
59 Value::String("Speed limit exceeded!".to_string()),
60 Value::String("Driver.Name".to_string()),
61 ],
62 },
63 ],
64 )
65 .with_salience(20);
66
67 // Rule 2: Driver validation
68 let driver_validation_rule = Rule::new(
69 "DriverValidation".to_string(),
70 ConditionGroup::single(Condition::new(
71 "Driver.License".to_string(),
72 Operator::Equal,
73 Value::String("VALID".to_string()),
74 )),
75 vec![
76 ActionType::Call {
77 function: "validateDriver".to_string(),
78 args: vec![
79 Value::String("Driver.Name".to_string()),
80 Value::String("Driver.Experience".to_string()),
81 ],
82 },
83 ActionType::Call {
84 function: "calculateInsurance".to_string(),
85 args: vec![
86 Value::String("Driver.Experience".to_string()),
87 Value::String("Car.Engine".to_string()),
88 ],
89 },
90 ],
91 )
92 .with_salience(15);
93
94 // Rule 3: Engine diagnostics
95 let engine_diagnostics_rule = Rule::new(
96 "EngineDiagnostics".to_string(),
97 ConditionGroup::single(Condition::new(
98 "Car.IsRunning".to_string(),
99 Operator::Equal,
100 Value::Boolean(true),
101 )),
102 vec![
103 ActionType::Call {
104 function: "performDiagnostics".to_string(),
105 args: vec![
106 Value::String("Car.Engine".to_string()),
107 Value::String("Car.Speed".to_string()),
108 ],
109 },
110 ActionType::Call {
111 function: "optimizePerformance".to_string(),
112 args: vec![
113 Value::String("Car.Speed".to_string()),
114 Value::String("Car.MaxSpeed".to_string()),
115 ],
116 },
117 ],
118 )
119 .with_salience(10);
120
121 // Add rules to knowledge base
122 let _ = kb.add_rule(speed_check_rule);
123 let _ = kb.add_rule(driver_validation_rule);
124 let _ = kb.add_rule(engine_diagnostics_rule);
125
126 // Create engine
127 let config = EngineConfig {
128 debug_mode: true,
129 max_cycles: 3,
130 ..Default::default()
131 };
132 let mut engine = RustRuleEngine::with_config(kb, config);
133
134 // Register custom functions
135 println!("📝 Registering custom functions...");
136
137 // Function 1: Check speed limit
138 engine.register_function("checkSpeedLimit", |args, facts| {
139 let speed_field = args.get(0).unwrap().to_string();
140 let limit = args.get(1).unwrap();
141
142 // Get actual speed value from facts
143 let speed = if let Some(car) = facts.get("Car") {
144 if let Value::Object(obj) = car {
145 obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
146 } else {
147 Value::Number(0.0)
148 }
149 } else {
150 Value::Number(0.0)
151 };
152
153 let result = format!("Speed check: {:?} vs limit {:?}", speed, limit);
154 println!("🚦 {}", result);
155 Ok(Value::String(result))
156 });
157
158 // Function 2: Send alert
159 engine.register_function("sendAlert", |args, facts| {
160 let message = args.get(0).unwrap().to_string();
161 let driver_field = args.get(1).unwrap().to_string();
162
163 // Get driver name from facts
164 let driver_name = if let Some(driver) = facts.get("Driver") {
165 if let Value::Object(obj) = driver {
166 obj.get("Name")
167 .cloned()
168 .unwrap_or(Value::String("Unknown".to_string()))
169 } else {
170 Value::String("Unknown".to_string())
171 }
172 } else {
173 Value::String("Unknown".to_string())
174 };
175
176 let alert = format!("🚨 ALERT to {:?}: {}", driver_name, message);
177 println!("{}", alert);
178 Ok(Value::String(alert))
179 });
180
181 // Function 3: Validate driver
182 engine.register_function("validateDriver", |args, _facts| {
183 let name_field = args.get(0).unwrap().to_string();
184 let exp_field = args.get(1).unwrap().to_string();
185
186 let result = format!(
187 "✅ Driver validation passed for {} (experience: {})",
188 name_field, exp_field
189 );
190 println!("{}", result);
191 Ok(Value::String(result))
192 });
193
194 // Function 4: Calculate insurance
195 engine.register_function("calculateInsurance", |args, _facts| {
196 let exp_field = args.get(0).unwrap().to_string();
197 let engine_field = args.get(1).unwrap().to_string();
198
199 let result = format!(
200 "💰 Insurance calculated: Experience {} + Engine {} = Premium rate",
201 exp_field, engine_field
202 );
203 println!("{}", result);
204 Ok(Value::String(result))
205 });
206
207 // Function 5: Perform diagnostics
208 engine.register_function("performDiagnostics", |args, _facts| {
209 let engine_field = args.get(0).unwrap().to_string();
210 let speed_field = args.get(1).unwrap().to_string();
211
212 let result = format!(
213 "🔧 Diagnostics: Engine {} running at speed {} - All systems OK",
214 engine_field, speed_field
215 );
216 println!("{}", result);
217 Ok(Value::String(result))
218 });
219
220 // Function 6: Optimize performance
221 engine.register_function("optimizePerformance", |args, _facts| {
222 let current_speed = args.get(0).unwrap().to_string();
223 let max_speed = args.get(1).unwrap().to_string();
224
225 let result = format!(
226 "⚡ Performance optimization: Current {} / Max {} - Efficiency tuned",
227 current_speed, max_speed
228 );
229 println!("{}", result);
230 Ok(Value::String(result))
231 });
232
233 println!("✅ Registered {} custom functions:", 6);
234 println!(" 🚦 checkSpeedLimit - Check if speed exceeds limit");
235 println!(" 🚨 sendAlert - Send alert message to driver");
236 println!(" ✅ validateDriver - Validate driver credentials");
237 println!(" 💰 calculateInsurance - Calculate insurance premium");
238 println!(" 🔧 performDiagnostics - Run engine diagnostics");
239 println!(" ⚡ optimizePerformance - Optimize engine performance");
240 println!();
241
242 // Execute rules
243 println!("🚀 Executing rules with custom functions...");
244 let result = engine.execute(&facts)?;
245
246 println!("\n📊 Custom Function Execution Results:");
247 println!(" Cycles: {}", result.cycle_count);
248 println!(" Rules evaluated: {}", result.rules_evaluated);
249 println!(" Rules fired: {}", result.rules_fired);
250 println!(" Execution time: {:?}", result.execution_time);
251
252 println!("\n🏁 Final state:");
253 if let Some(car) = facts.get("Car") {
254 println!(" Car = {car:?}");
255 }
256 if let Some(driver) = facts.get("Driver") {
257 println!(" Driver = {driver:?}");
258 }
259
260 println!("\n🎯 Custom Function Calls Demonstrated:");
261 println!(" 📞 User-defined functions called from rules");
262 println!(" 🔧 Custom business logic execution");
263 println!(" 🎪 Function registry system");
264 println!(" 📋 Rule-based custom function invocation");
265 println!(" ⚡ Real-time function parameter resolution");
266
267 Ok(())
268}examples/fraud_detection.rs (line 91)
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("=== Demo: Fraud Detection System ===\n");
10
11 // Create transaction data
12 let mut transaction_props = HashMap::new();
13 transaction_props.insert("Amount".to_string(), Value::Number(5000.0));
14 transaction_props.insert("Location".to_string(), Value::String("FOREIGN".to_string()));
15 transaction_props.insert("Time".to_string(), Value::String("02:30".to_string()));
16 transaction_props.insert("CardType".to_string(), Value::String("CREDIT".to_string()));
17 transaction_props.insert(
18 "MerchantCategory".to_string(),
19 Value::String("CASINO".to_string()),
20 );
21
22 let mut account_props = HashMap::new();
23 account_props.insert("Balance".to_string(), Value::Number(2000.0));
24 account_props.insert("DailyLimit".to_string(), Value::Number(3000.0));
25 account_props.insert("RiskLevel".to_string(), Value::String("LOW".to_string()));
26 account_props.insert("IsActive".to_string(), Value::Boolean(true));
27 account_props.insert(
28 "LastLoginLocation".to_string(),
29 Value::String("DOMESTIC".to_string()),
30 );
31
32 let mut alert_props = HashMap::new();
33 alert_props.insert("FraudScore".to_string(), Value::Number(0.0));
34 alert_props.insert("Status".to_string(), Value::String("PENDING".to_string()));
35 alert_props.insert("Alerts".to_string(), Value::Array(vec![]));
36
37 // Create facts
38 let facts = Facts::new();
39 facts.add_value("Transaction", Value::Object(transaction_props))?;
40 facts.add_value("Account", Value::Object(account_props))?;
41 facts.add_value("Alert", Value::Object(alert_props))?;
42
43 println!("🏁 Initial transaction data:");
44 if let Some(transaction) = facts.get("Transaction") {
45 println!(" Transaction = {transaction:?}");
46 }
47 if let Some(account) = facts.get("Account") {
48 println!(" Account = {account:?}");
49 }
50 if let Some(alert) = facts.get("Alert") {
51 println!(" Alert = {alert:?}");
52 }
53 println!();
54
55 // Create knowledge base
56 let mut kb = KnowledgeBase::new("FraudDetectionSystem");
57
58 // Rule 1: High Amount Transaction Alert
59 let high_amount_rule = Rule::new(
60 "HighAmountAlert".to_string(),
61 ConditionGroup::and(
62 ConditionGroup::single(Condition::new(
63 "Transaction.Amount".to_string(),
64 Operator::GreaterThan,
65 Value::Number(3000.0),
66 )),
67 ConditionGroup::single(Condition::new(
68 "Account.DailyLimit".to_string(),
69 Operator::LessThan,
70 Value::String("Transaction.Amount".to_string()),
71 )),
72 ),
73 vec![
74 ActionType::Call {
75 function: "log".to_string(),
76 args: vec![Value::String(
77 "HIGH AMOUNT ALERT: Transaction exceeds daily limit".to_string(),
78 )],
79 },
80 ActionType::MethodCall {
81 object: "Alert".to_string(),
82 method: "setFraudScore".to_string(),
83 args: vec![Value::Number(50.0)],
84 },
85 ActionType::Set {
86 field: "Alert.Status".to_string(),
87 value: Value::String("FLAGGED".to_string()),
88 },
89 ],
90 )
91 .with_salience(10);
92
93 // Rule 2: Foreign Location Alert
94 let foreign_location_rule = Rule::new(
95 "ForeignLocationAlert".to_string(),
96 ConditionGroup::and(
97 ConditionGroup::single(Condition::new(
98 "Transaction.Location".to_string(),
99 Operator::Equal,
100 Value::String("FOREIGN".to_string()),
101 )),
102 ConditionGroup::single(Condition::new(
103 "Account.LastLoginLocation".to_string(),
104 Operator::Equal,
105 Value::String("DOMESTIC".to_string()),
106 )),
107 ),
108 vec![
109 ActionType::Call {
110 function: "log".to_string(),
111 args: vec![Value::String(
112 "LOCATION ALERT: Foreign transaction detected".to_string(),
113 )],
114 },
115 ActionType::Call {
116 function: "sum".to_string(),
117 args: vec![
118 Value::String("Alert.FraudScore".to_string()),
119 Value::Number(30.0),
120 ],
121 },
122 ],
123 )
124 .with_salience(8);
125
126 // Rule 3: Late Night Transaction Alert
127 let late_night_rule = Rule::new(
128 "LateNightAlert".to_string(),
129 ConditionGroup::single(Condition::new(
130 "Transaction.Time".to_string(),
131 Operator::Contains,
132 Value::String("02:".to_string()),
133 )),
134 vec![
135 ActionType::Call {
136 function: "log".to_string(),
137 args: vec![Value::String(
138 "TIME ALERT: Late night transaction".to_string(),
139 )],
140 },
141 ActionType::MethodCall {
142 object: "Alert".to_string(),
143 method: "setFraudScore".to_string(),
144 args: vec![Value::Number(20.0)],
145 },
146 ],
147 )
148 .with_salience(6);
149
150 // Rule 4: High Risk Merchant Category
151 let high_risk_merchant_rule = Rule::new(
152 "HighRiskMerchantAlert".to_string(),
153 ConditionGroup::single(Condition::new(
154 "Transaction.MerchantCategory".to_string(),
155 Operator::Equal,
156 Value::String("CASINO".to_string()),
157 )),
158 vec![
159 ActionType::Call {
160 function: "log".to_string(),
161 args: vec![Value::String(
162 "MERCHANT ALERT: High-risk merchant category".to_string(),
163 )],
164 },
165 ActionType::MethodCall {
166 object: "Alert".to_string(),
167 method: "setFraudScore".to_string(),
168 args: vec![Value::Number(40.0)],
169 },
170 ],
171 )
172 .with_salience(7);
173
174 // Rule 5: Critical Fraud Score Alert
175 let critical_fraud_rule = Rule::new(
176 "CriticalFraudAlert".to_string(),
177 ConditionGroup::single(Condition::new(
178 "Alert.FraudScore".to_string(),
179 Operator::GreaterThanOrEqual,
180 Value::Number(70.0),
181 )),
182 vec![
183 ActionType::Call {
184 function: "log".to_string(),
185 args: vec![Value::String(
186 "🚨 CRITICAL FRAUD ALERT! Blocking transaction!".to_string(),
187 )],
188 },
189 ActionType::Set {
190 field: "Alert.Status".to_string(),
191 value: Value::String("BLOCKED".to_string()),
192 },
193 ActionType::Call {
194 function: "format".to_string(),
195 args: vec![
196 Value::String("Transaction #{0} BLOCKED - Fraud Score: {1}".to_string()),
197 Value::String("TX123456".to_string()),
198 Value::String("Alert.FraudScore".to_string()),
199 ],
200 },
201 ],
202 )
203 .with_salience(15);
204
205 // Rule 6: Account Insufficient Funds
206 let insufficient_funds_rule = Rule::new(
207 "InsufficientFundsAlert".to_string(),
208 ConditionGroup::single(Condition::new(
209 "Account.Balance".to_string(),
210 Operator::LessThan,
211 Value::String("Transaction.Amount".to_string()),
212 )),
213 vec![
214 ActionType::Call {
215 function: "log".to_string(),
216 args: vec![Value::String(
217 "💰 INSUFFICIENT FUNDS: Transaction declined".to_string(),
218 )],
219 },
220 ActionType::Set {
221 field: "Alert.Status".to_string(),
222 value: Value::String("DECLINED".to_string()),
223 },
224 ],
225 )
226 .with_salience(20); // Highest priority
227
228 // Add rules to knowledge base
229 let _ = kb.add_rule(high_amount_rule);
230 let _ = kb.add_rule(foreign_location_rule);
231 let _ = kb.add_rule(late_night_rule);
232 let _ = kb.add_rule(high_risk_merchant_rule);
233 let _ = kb.add_rule(critical_fraud_rule);
234 let _ = kb.add_rule(insufficient_funds_rule);
235
236 // Create engine with debug mode
237 let config = EngineConfig {
238 debug_mode: true,
239 max_cycles: 10,
240 ..Default::default()
241 };
242 let engine = RustRuleEngine::with_config(kb, config);
243
244 println!("🔍 Running fraud detection analysis...");
245 let result = engine.execute(&facts)?;
246
247 println!("\n📊 Fraud Detection Results:");
248 println!(" Cycles: {}", result.cycle_count);
249 println!(" Rules evaluated: {}", result.rules_evaluated);
250 println!(" Rules fired: {}", result.rules_fired);
251 println!(" Execution time: {:?}", result.execution_time);
252
253 println!("\n🏁 Final analysis:");
254 if let Some(transaction) = facts.get("Transaction") {
255 println!(" Transaction = {transaction:?}");
256 }
257 if let Some(account) = facts.get("Account") {
258 println!(" Account = {account:?}");
259 }
260 if let Some(alert) = facts.get("Alert") {
261 println!(" Alert = {alert:?}");
262 }
263
264 println!("\n🎯 Fraud Detection Rules Demonstrated:");
265 println!(" 🚨 High Amount Transactions");
266 println!(" 🌍 Foreign Location Detection");
267 println!(" 🌙 Late Night Activity");
268 println!(" 🎰 High-Risk Merchant Categories");
269 println!(" ⚠️ Critical Fraud Score Alerts");
270 println!(" 💰 Insufficient Funds Checks");
271
272 Ok(())
273}examples/ecommerce.rs (line 103)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("=== E-commerce Rules Demo ===");
10 println!("==============================\n");
11
12 // Create customer data
13 let mut customer_props = HashMap::new();
14 customer_props.insert("IsNew".to_string(), Value::Boolean(true));
15 customer_props.insert(
16 "Membership".to_string(),
17 Value::String("standard".to_string()),
18 );
19 customer_props.insert("TotalSpent".to_string(), Value::Number(750.0));
20 customer_props.insert("WelcomeEmailSent".to_string(), Value::Boolean(false));
21
22 // Create order data
23 let mut order_props = HashMap::new();
24 order_props.insert("Total".to_string(), Value::Number(75.0));
25 order_props.insert("ItemCount".to_string(), Value::Integer(2));
26 order_props.insert(
27 "Category".to_string(),
28 Value::String("clothing".to_string()),
29 );
30 order_props.insert("DiscountRate".to_string(), Value::Number(0.0));
31 order_props.insert("FreeShipping".to_string(), Value::Boolean(false));
32 order_props.insert(
33 "DiscountType".to_string(),
34 Value::String("none".to_string()),
35 );
36
37 // Create promotion data
38 let mut promotion_props = HashMap::new();
39 promotion_props.insert("SeasonalDiscount".to_string(), Value::Number(0.05));
40 promotion_props.insert("BulkDiscount".to_string(), Value::Number(0.10));
41 promotion_props.insert("Active".to_string(), Value::Boolean(true));
42
43 // Create facts
44 let facts = Facts::new();
45 facts.add_value("Customer", Value::Object(customer_props))?;
46 facts.add_value("Order", Value::Object(order_props))?;
47 facts.add_value("Promotion", Value::Object(promotion_props))?;
48
49 println!("🏁 Initial e-commerce data:");
50 if let Some(customer) = facts.get("Customer") {
51 println!(" Customer = {customer:?}");
52 }
53 if let Some(order) = facts.get("Order") {
54 println!(" Order = {order:?}");
55 }
56 if let Some(promotion) = facts.get("Promotion") {
57 println!(" Promotion = {promotion:?}");
58 }
59 println!();
60
61 // Create knowledge base
62 let mut kb = KnowledgeBase::new("EcommerceRules");
63
64 // Rule 1: New Customer Discount (salience 25)
65 let new_customer_rule = Rule::new(
66 "NewCustomerDiscount".to_string(),
67 ConditionGroup::and(
68 ConditionGroup::single(Condition::new(
69 "Customer.IsNew".to_string(),
70 Operator::Equal,
71 Value::Boolean(true),
72 )),
73 ConditionGroup::single(Condition::new(
74 "Order.Total".to_string(),
75 Operator::GreaterThan,
76 Value::Number(50.0),
77 )),
78 ),
79 vec![
80 ActionType::MethodCall {
81 object: "Order".to_string(),
82 method: "setDiscountRate".to_string(),
83 args: vec![Value::Number(0.10)],
84 },
85 ActionType::MethodCall {
86 object: "Order".to_string(),
87 method: "setDiscountType".to_string(),
88 args: vec![Value::String("welcome".to_string())],
89 },
90 ActionType::MethodCall {
91 object: "Customer".to_string(),
92 method: "setWelcomeEmailSent".to_string(),
93 args: vec![Value::Boolean(true)],
94 },
95 ActionType::Call {
96 function: "log".to_string(),
97 args: vec![Value::String(
98 "New customer welcome discount applied".to_string(),
99 )],
100 },
101 ],
102 )
103 .with_salience(25);
104
105 // Rule 2: Premium Member Benefits (salience 20)
106 let premium_member_rule = Rule::new(
107 "PremiumMemberBenefits".to_string(),
108 ConditionGroup::and(
109 ConditionGroup::single(Condition::new(
110 "Customer.Membership".to_string(),
111 Operator::Equal,
112 Value::String("premium".to_string()),
113 )),
114 ConditionGroup::single(Condition::new(
115 "Order.Total".to_string(),
116 Operator::GreaterThan,
117 Value::Number(100.0),
118 )),
119 ),
120 vec![
121 ActionType::MethodCall {
122 object: "Order".to_string(),
123 method: "setDiscountRate".to_string(),
124 args: vec![Value::Number(0.15)],
125 },
126 ActionType::MethodCall {
127 object: "Order".to_string(),
128 method: "setFreeShipping".to_string(),
129 args: vec![Value::Boolean(true)],
130 },
131 ActionType::Call {
132 function: "log".to_string(),
133 args: vec![Value::String("Premium member benefits applied".to_string())],
134 },
135 ],
136 )
137 .with_salience(20);
138
139 // Rule 3: VIP Upgrade (salience 30)
140 let vip_upgrade_rule = Rule::new(
141 "VIPUpgrade".to_string(),
142 ConditionGroup::and(
143 ConditionGroup::single(Condition::new(
144 "Customer.TotalSpent".to_string(),
145 Operator::GreaterThan,
146 Value::Number(1000.0),
147 )),
148 ConditionGroup::single(Condition::new(
149 "Customer.Membership".to_string(),
150 Operator::NotEqual,
151 Value::String("VIP".to_string()),
152 )),
153 ),
154 vec![
155 ActionType::MethodCall {
156 object: "Customer".to_string(),
157 method: "setMembership".to_string(),
158 args: vec![Value::String("VIP".to_string())],
159 },
160 ActionType::MethodCall {
161 object: "Order".to_string(),
162 method: "setDiscountRate".to_string(),
163 args: vec![Value::Number(0.25)],
164 },
165 ActionType::Call {
166 function: "log".to_string(),
167 args: vec![Value::String(
168 "Customer upgraded to VIP membership".to_string(),
169 )],
170 },
171 ],
172 )
173 .with_salience(30);
174
175 // Rule 4: Free Shipping for Large Orders (salience 15)
176 let free_shipping_rule = Rule::new(
177 "FreeShippingLargeOrders".to_string(),
178 ConditionGroup::single(Condition::new(
179 "Order.Total".to_string(),
180 Operator::GreaterThanOrEqual,
181 Value::Number(100.0),
182 )),
183 vec![
184 ActionType::MethodCall {
185 object: "Order".to_string(),
186 method: "setFreeShipping".to_string(),
187 args: vec![Value::Boolean(true)],
188 },
189 ActionType::Call {
190 function: "log".to_string(),
191 args: vec![Value::String(
192 "Free shipping applied for large order".to_string(),
193 )],
194 },
195 ],
196 )
197 .with_salience(15);
198
199 // Rule 5: Bulk Discount (salience 12)
200 let bulk_discount_rule = Rule::new(
201 "BulkDiscount".to_string(),
202 ConditionGroup::single(Condition::new(
203 "Order.ItemCount".to_string(),
204 Operator::GreaterThanOrEqual,
205 Value::Integer(5),
206 )),
207 vec![
208 ActionType::Call {
209 function: "max".to_string(),
210 args: vec![
211 Value::String("Order.DiscountRate".to_string()),
212 Value::Number(0.10),
213 ],
214 },
215 ActionType::Call {
216 function: "log".to_string(),
217 args: vec![Value::String("Bulk discount applied".to_string())],
218 },
219 ],
220 )
221 .with_salience(12);
222
223 // Rule 6: Seasonal Promotion (salience 10)
224 let seasonal_promotion_rule = Rule::new(
225 "SeasonalPromotion".to_string(),
226 ConditionGroup::and(
227 ConditionGroup::single(Condition::new(
228 "Promotion.Active".to_string(),
229 Operator::Equal,
230 Value::Boolean(true),
231 )),
232 ConditionGroup::single(Condition::new(
233 "Order.Category".to_string(),
234 Operator::Equal,
235 Value::String("clothing".to_string()),
236 )),
237 ),
238 vec![
239 ActionType::Call {
240 function: "max".to_string(),
241 args: vec![
242 Value::String("Order.DiscountRate".to_string()),
243 Value::String("Promotion.SeasonalDiscount".to_string()),
244 ],
245 },
246 ActionType::Call {
247 function: "log".to_string(),
248 args: vec![Value::String("Seasonal promotion applied".to_string())],
249 },
250 ],
251 )
252 .with_salience(10);
253
254 // Add rules to knowledge base
255 let _ = kb.add_rule(new_customer_rule);
256 let _ = kb.add_rule(premium_member_rule);
257 let _ = kb.add_rule(vip_upgrade_rule);
258 let _ = kb.add_rule(free_shipping_rule);
259 let _ = kb.add_rule(bulk_discount_rule);
260 let _ = kb.add_rule(seasonal_promotion_rule);
261
262 println!(
263 "📚 Knowledge Base loaded with {} rules",
264 kb.get_statistics().total_rules
265 );
266 println!("🔥 Rules: {:?}\n", kb.get_rule_names());
267
268 // Create engine with debug mode
269 let config = EngineConfig {
270 debug_mode: true,
271 max_cycles: 5,
272 ..Default::default()
273 };
274 let engine = RustRuleEngine::with_config(kb, config);
275
276 // Execute rules
277 println!("🚀 Executing e-commerce rules...");
278 let result = engine.execute(&facts)?;
279
280 println!("\n📊 E-commerce Execution Results:");
281 println!(" Cycles: {}", result.cycle_count);
282 println!(" Rules evaluated: {}", result.rules_evaluated);
283 println!(" Rules fired: {}", result.rules_fired);
284 println!(" Execution time: {:?}", result.execution_time);
285
286 println!("\n🏁 Final e-commerce state:");
287 if let Some(customer) = facts.get("Customer") {
288 println!(" Customer = {customer:?}");
289 }
290 if let Some(order) = facts.get("Order") {
291 println!(" Order = {order:?}");
292 }
293 if let Some(promotion) = facts.get("Promotion") {
294 println!(" Promotion = {promotion:?}");
295 }
296
297 println!("\n🎯 E-commerce Rules Demonstrated:");
298 println!(" 🎁 New Customer Welcome Discount");
299 println!(" 💎 Premium Member Benefits");
300 println!(" 🌟 VIP Membership Upgrades");
301 println!(" 🚚 Free Shipping Rules");
302 println!(" 📦 Bulk Purchase Discounts");
303 println!(" 🏷️ Seasonal Promotions");
304
305 Ok(())
306}Sourcepub fn with_priority(self, priority: i32) -> Self
pub fn with_priority(self, priority: i32) -> Self
Set the priority of the rule (alias for salience)
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Rule
impl RefUnwindSafe for Rule
impl Send for Rule
impl Sync for Rule
impl Unpin for Rule
impl UnwindSafe for Rule
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more