Rule

Struct Rule 

Source
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: String

The unique name of the rule

§description: Option<String>

Optional description of what the rule does

§salience: i32

Priority of the rule (higher values execute first)

§enabled: bool

Whether the rule is enabled for execution

§conditions: ConditionGroup

The 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

Source

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
Hide additional 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}
Source

pub fn with_description(self, description: String) -> Self

Add a description to the rule

Source

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
Hide additional 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}
Source

pub fn with_priority(self, priority: i32) -> Self

Set the priority of the rule (alias for salience)

Source

pub fn matches(&self, facts: &HashMap<String, Value>) -> bool

Check if this rule matches the given facts

Trait Implementations§

Source§

impl Clone for Rule

Source§

fn clone(&self) -> Rule

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Rule

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.