1use rust_rule_engine::engine::facts::Facts;
2use rust_rule_engine::engine::knowledge_base::KnowledgeBase;
3use rust_rule_engine::engine::rule::{Condition, ConditionGroup, Rule};
4use rust_rule_engine::engine::{EngineConfig, RustRuleEngine};
5use rust_rule_engine::types::{ActionType, Operator, Value};
6use std::collections::HashMap;
7
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("šÆ Custom Function Calls Demo");
10 println!("=============================\n");
11
12 let facts = Facts::new();
14
15 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 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 let mut kb = KnowledgeBase::new("CustomFunctionRules");
42
43 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 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 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 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 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 println!("š Registering custom functions...");
136
137 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 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 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 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 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 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 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 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 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}