rule_file_functions_demo/
rule_file_functions_demo.rs

1use rust_rule_engine::engine::facts::Facts;
2use rust_rule_engine::engine::knowledge_base::KnowledgeBase;
3use rust_rule_engine::engine::{EngineConfig, RustRuleEngine};
4use rust_rule_engine::parser::SimpleGRLParser;
5use rust_rule_engine::types::Value;
6use std::collections::HashMap;
7use std::fs;
8
9fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
10    println!("šŸŽÆ Custom Functions from Rule File Demo");
11    println!("=======================================\n");
12
13    // Read rules from file
14    let rule_file_path = "examples/rules/car_functions.grl";
15    println!("šŸ“„ Reading rules from file: {}", rule_file_path);
16
17    let rule_content = fs::read_to_string(rule_file_path)
18        .map_err(|e| format!("Failed to read rule file: {}", e))?;
19
20    println!("šŸ“‹ Rule file content:");
21    println!("---");
22    println!("{}", rule_content);
23    println!("---\n");
24
25    // Create facts
26    let facts = Facts::new();
27
28    // Car data - set speed > 80 to trigger speed limit rule
29    let mut car_props = HashMap::new();
30    car_props.insert("Speed".to_string(), Value::Number(95.0)); // Above speed limit
31    car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
32    car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
33    car_props.insert("IsRunning".to_string(), Value::Boolean(true));
34
35    // Driver data
36    let mut driver_props = HashMap::new();
37    driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
38    driver_props.insert("Experience".to_string(), Value::Integer(7)); // Experienced driver
39    driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
40
41    facts.add_value("Car", Value::Object(car_props))?;
42    facts.add_value("Driver", Value::Object(driver_props))?;
43
44    println!("šŸ Initial state:");
45    if let Some(car) = facts.get("Car") {
46        println!("   Car = {car:?}");
47    }
48    if let Some(driver) = facts.get("Driver") {
49        println!("   Driver = {driver:?}");
50    }
51    println!();
52
53    // Create knowledge base
54    let mut kb = KnowledgeBase::new("RuleFileDemo");
55
56    // Parse GRL file and add rules to knowledge base
57    println!("šŸ”§ Parsing GRL file content...");
58    let parsed_rules = SimpleGRLParser::parse_rules(&rule_content)
59        .map_err(|e| format!("Failed to parse GRL file: {:?}", e))?;
60
61    println!(
62        "āœ… Successfully parsed {} rules from file",
63        parsed_rules.len()
64    );
65    for rule in parsed_rules {
66        println!("   šŸ“‹ Rule: {} (salience: {})", rule.name, rule.salience);
67        let _ = kb.add_rule(rule);
68    }
69    println!();
70
71    // Create engine
72    let config = EngineConfig {
73        debug_mode: true,
74        max_cycles: 3,
75        ..Default::default()
76    };
77    let mut engine = RustRuleEngine::with_config(kb, config);
78
79    // Register all custom functions called from the rule file
80    println!("šŸ“ Registering custom functions from rule file...");
81
82    // Functions from SpeedLimitCheck rule
83    engine.register_function("checkSpeedLimit", |args, facts| {
84        let speed_field = args.get(0).unwrap().to_string();
85        let limit = args.get(1).unwrap();
86
87        let speed = if let Some(car) = facts.get("Car") {
88            if let Value::Object(obj) = car {
89                obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
90            } else {
91                Value::Number(0.0)
92            }
93        } else {
94            Value::Number(0.0)
95        };
96
97        let result = format!("🚦 Speed check: {:?} vs limit {:?}", speed, limit);
98        println!("{}", result);
99        Ok(Value::String(result))
100    });
101
102    engine.register_function("sendAlert", |args, facts| {
103        let message = args.get(0).unwrap().to_string();
104        let driver_field = args.get(1).unwrap().to_string();
105
106        let driver_name = if let Some(driver) = facts.get("Driver") {
107            if let Value::Object(obj) = driver {
108                obj.get("Name")
109                    .cloned()
110                    .unwrap_or(Value::String("Unknown".to_string()))
111            } else {
112                Value::String("Unknown".to_string())
113            }
114        } else {
115            Value::String("Unknown".to_string())
116        };
117
118        let alert = format!("🚨 ALERT to {:?}: {}", driver_name, message);
119        println!("{}", alert);
120        Ok(Value::String(alert))
121    });
122
123    // Functions from DriverValidation rule
124    engine.register_function("validateDriver", |args, _facts| {
125        let name_field = args.get(0).unwrap().to_string();
126        let exp_field = args.get(1).unwrap().to_string();
127
128        let result = format!(
129            "āœ… Driver validation: {} (experience: {})",
130            name_field, exp_field
131        );
132        println!("{}", result);
133        Ok(Value::String(result))
134    });
135
136    engine.register_function("calculateInsurance", |args, _facts| {
137        let exp_field = args.get(0).unwrap().to_string();
138        let engine_field = args.get(1).unwrap().to_string();
139
140        let result = format!(
141            "šŸ’° Insurance: Experience {} + Engine {} = Premium",
142            exp_field, engine_field
143        );
144        println!("{}", result);
145        Ok(Value::String(result))
146    });
147
148    // Functions from EngineDiagnostics rule
149    engine.register_function("performDiagnostics", |args, _facts| {
150        let engine_field = args.get(0).unwrap().to_string();
151        let speed_field = args.get(1).unwrap().to_string();
152
153        let result = format!(
154            "šŸ”§ Diagnostics: Engine {} at speed {} - OK",
155            engine_field, speed_field
156        );
157        println!("{}", result);
158        Ok(Value::String(result))
159    });
160
161    engine.register_function("optimizePerformance", |args, _facts| {
162        let current_speed = args.get(0).unwrap().to_string();
163        let max_speed = args.get(1).unwrap().to_string();
164
165        let result = format!(
166            "⚔ Performance: {} / {} - Optimized",
167            current_speed, max_speed
168        );
169        println!("{}", result);
170        Ok(Value::String(result))
171    });
172
173    // Functions from MaintenanceCheck rule
174    engine.register_function("scheduleMaintenanceCheck", |args, _facts| {
175        let engine_field = args.get(0).unwrap().to_string();
176        let exp_field = args.get(1).unwrap().to_string();
177
178        let result = format!(
179            "šŸ”§ Maintenance scheduled: Engine {} (driver exp: {})",
180            engine_field, exp_field
181        );
182        println!("{}", result);
183        Ok(Value::String(result))
184    });
185
186    engine.register_function("updateMaintenanceRecord", |args, _facts| {
187        let name_field = args.get(0).unwrap().to_string();
188        let engine_field = args.get(1).unwrap().to_string();
189
190        let result = format!("šŸ“‹ Record updated: {} - {}", name_field, engine_field);
191        println!("{}", result);
192        Ok(Value::String(result))
193    });
194
195    println!("āœ… Registered {} custom functions from rule file:", 8);
196    println!("   🚦 checkSpeedLimit");
197    println!("   🚨 sendAlert");
198    println!("   āœ… validateDriver");
199    println!("   šŸ’° calculateInsurance");
200    println!("   šŸ”§ performDiagnostics");
201    println!("   ⚔ optimizePerformance");
202    println!("   šŸ”§ scheduleMaintenanceCheck");
203    println!("   šŸ“‹ updateMaintenanceRecord");
204    println!();
205
206    // Execute rules
207    println!("šŸš€ Executing rules from file...");
208    let result = engine.execute(&facts)?;
209
210    println!("\nšŸ“Š Rule File Execution Results:");
211    println!("   Cycles: {}", result.cycle_count);
212    println!("   Rules evaluated: {}", result.rules_evaluated);
213    println!("   Rules fired: {}", result.rules_fired);
214    println!("   Execution time: {:?}", result.execution_time);
215
216    println!("\nšŸ Final state:");
217    if let Some(car) = facts.get("Car") {
218        println!("   Car = {car:?}");
219    }
220    if let Some(driver) = facts.get("Driver") {
221        println!("   Driver = {driver:?}");
222    }
223
224    println!("\nšŸŽÆ Rule File Custom Functions Demonstrated:");
225    println!("   šŸ“„ Rules defined in external .grl file");
226    println!("   šŸ“ž Custom functions called from rule file");
227    println!("   šŸ”§ Business logic separated from rule definitions");
228    println!("   šŸ“‹ File-based rule management");
229    println!("   ⚔ Function registry with rule file integration");
230
231    Ok(())
232}