inline_rules_demo/
inline_rules_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::grl_parser::GRLParser;
5use rust_rule_engine::types::Value;
6use std::collections::HashMap;
7
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9    println!("šŸŽÆ Inline GRL Rules Demo");
10    println!("========================\n");
11
12    // Define rules directly in code as strings
13    let grl_rules = r#"
14        rule "HighValueCustomer" salience 20 {
15            when
16                Customer.TotalSpent > 1000.0
17            then
18                sendWelcomeEmail(Customer.Email, "GOLD");
19                Customer.setTier("GOLD");
20                log("Customer upgraded to GOLD tier");
21        }
22
23        rule "LoyaltyBonus" salience 15 {
24            when
25                Customer.OrderCount >= 10
26            then
27                applyLoyaltyBonus(Customer.Id, 50.0);
28                Customer.setLoyaltyBonusApplied(true);
29                log("Loyalty bonus applied");
30        }
31
32        rule "NewCustomerWelcome" salience 10 {
33            when
34                Customer.IsNew == false && Customer.WelcomeEmailSent == false
35            then
36                sendWelcomeEmail(Customer.Email, "EXISTING");
37                Customer.setWelcomeEmailSent(true);
38                log("Welcome email sent to existing customer");
39        }
40
41        rule "LowRiskTransaction" salience 5 {
42            when
43                Transaction.Amount < 1000.0 && Transaction.RiskProcessed == false
44            then
45                Transaction.setRiskProcessed(true);
46                log("Low-risk transaction processed");
47        }
48    "#;
49
50    println!("šŸ“‹ Inline GRL Rules:");
51    println!("---");
52    println!("{}", grl_rules.trim());
53    println!("---\n");
54
55    // Create facts
56    let facts = Facts::new();
57
58    // Customer data
59    let mut customer_props = HashMap::new();
60    customer_props.insert("Id".to_string(), Value::String("CUST001".to_string()));
61    customer_props.insert(
62        "Email".to_string(),
63        Value::String("john.doe@example.com".to_string()),
64    );
65    customer_props.insert("TotalSpent".to_string(), Value::Number(1250.0)); // Qualifies for GOLD
66    customer_props.insert("YearsActive".to_string(), Value::Integer(4)); // Long-time customer
67    customer_props.insert("OrderCount".to_string(), Value::Integer(12)); // Qualifies for loyalty
68    customer_props.insert("Tier".to_string(), Value::String("SILVER".to_string()));
69    customer_props.insert("IsNew".to_string(), Value::Boolean(false));
70    customer_props.insert("RiskScore".to_string(), Value::Integer(35)); // Low risk
71    customer_props.insert("WelcomeEmailSent".to_string(), Value::Boolean(false));
72    customer_props.insert("LoyaltyBonusApplied".to_string(), Value::Boolean(false));
73
74    // Transaction data
75    let mut transaction_props = HashMap::new();
76    transaction_props.insert("Id".to_string(), Value::String("TXN001".to_string()));
77    transaction_props.insert("Amount".to_string(), Value::Number(750.0)); // Normal amount
78    transaction_props.insert("Currency".to_string(), Value::String("USD".to_string()));
79    transaction_props.insert("RiskProcessed".to_string(), Value::Boolean(false));
80
81    facts.add_value("Customer", Value::Object(customer_props))?;
82    facts.add_value("Transaction", Value::Object(transaction_props))?;
83
84    println!("šŸ Initial state:");
85    if let Some(customer) = facts.get("Customer") {
86        println!("   Customer = {customer:?}");
87    }
88    if let Some(transaction) = facts.get("Transaction") {
89        println!("   Transaction = {transaction:?}");
90    }
91    println!();
92
93    // Create knowledge base and parse inline rules
94    let kb = KnowledgeBase::new("InlineRulesDemo");
95
96    println!("šŸ”§ Parsing inline GRL rules...");
97    let parsed_rules = GRLParser::parse_rules(grl_rules)
98        .map_err(|e| format!("Failed to parse inline GRL rules: {:?}", e))?;
99
100    println!(
101        "āœ… Successfully parsed {} rules from inline strings",
102        parsed_rules.len()
103    );
104    for rule in parsed_rules {
105        println!("   šŸ“‹ Rule: {} (salience: {})", rule.name, rule.salience);
106        let _ = kb.add_rule(rule);
107    }
108    println!();
109
110    // Create engine with configuration
111    let config = EngineConfig {
112        debug_mode: true,
113        max_cycles: 1, // PREVENT INFINITE LOOPS by limiting to 1 cycle
114        ..Default::default()
115    };
116    let mut engine = RustRuleEngine::with_config(kb, config);
117
118    // Register custom functions called from the inline rules
119    println!("šŸ“ Registering custom functions for inline rules...");
120
121    // Customer tier management
122    engine.register_function("Customer.setTier", |args, facts| {
123        let new_tier = args.get(0).unwrap().to_string();
124
125        // ACTUALLY UPDATE THE FACTS in memory
126        facts
127            .set_nested("Customer.Tier", Value::String(new_tier.clone()))
128            .unwrap();
129
130        let result = format!("šŸ† Customer tier updated to: {}", new_tier);
131        println!("  {}", result);
132        Ok(Value::String(result))
133    });
134
135    // Loyalty bonus management
136    engine.register_function("Customer.setLoyaltyBonusApplied", |args, facts| {
137        let applied = args.get(0).unwrap();
138
139        // ACTUALLY UPDATE THE FACTS in memory
140        facts
141            .set_nested("Customer.LoyaltyBonusApplied", applied.clone())
142            .unwrap();
143
144        let result = format!("šŸŽÆ Loyalty bonus status updated: {:?}", applied);
145        println!("  {}", result);
146        Ok(Value::String(result))
147    });
148
149    // Email service
150    engine.register_function("sendWelcomeEmail", |args, _facts| {
151        let email = args.get(0).unwrap().to_string();
152        let tier = args.get(1).unwrap().to_string();
153
154        let result = format!("šŸ“§ Welcome email sent to {} for {} tier", email, tier);
155        println!("  {}", result);
156        Ok(Value::String(result))
157    });
158
159    // Loyalty system
160    engine.register_function("applyLoyaltyBonus", |args, _facts| {
161        let customer_id = args.get(0).unwrap().to_string();
162        let bonus_amount = args.get(1).unwrap();
163
164        let result = format!(
165            "šŸ’° Loyalty bonus of {:?} applied to customer {}",
166            bonus_amount, customer_id
167        );
168        println!("  {}", result);
169        Ok(Value::String(result))
170    });
171
172    // Security functions
173    engine.register_function("flagForReview", |args, _facts| {
174        let transaction_id = args.get(0).unwrap().to_string();
175
176        let result = format!(
177            "🚨 Transaction {} flagged for manual review",
178            transaction_id
179        );
180        println!("  {}", result);
181        Ok(Value::String(result))
182    });
183
184    engine.register_function("notifySecurityTeam", |args, _facts| {
185        let customer_id = args.get(0).unwrap().to_string();
186        let amount = args.get(1).unwrap();
187
188        let result = format!(
189            "šŸ”’ Security team notified: Customer {} - Amount {:?}",
190            customer_id, amount
191        );
192        println!("  {}", result);
193        Ok(Value::String(result))
194    });
195
196    // Customer status updates
197    engine.register_function("Customer.setWelcomeEmailSent", |args, facts| {
198        let sent = args.get(0).unwrap();
199
200        // ACTUALLY UPDATE THE FACTS in memory
201        facts
202            .set_nested("Customer.WelcomeEmailSent", sent.clone())
203            .unwrap();
204
205        let result = format!("āœ… Welcome email status updated: {:?}", sent);
206        println!("  {}", result);
207        Ok(Value::String(result))
208    });
209
210    // Transaction status updates
211    engine.register_function("Transaction.setRiskProcessed", |args, facts| {
212        let processed = args.get(0).unwrap();
213
214        // ACTUALLY UPDATE THE FACTS in memory
215        facts
216            .set_nested("Transaction.RiskProcessed", processed.clone())
217            .unwrap();
218
219        let result = format!("āœ… Transaction risk processing completed: {:?}", processed);
220        println!("  {}", result);
221        Ok(Value::String(result))
222    });
223
224    println!("āœ… Registered 8 custom functions for inline rules:");
225    println!("   šŸ† Customer.setTier");
226    println!("   šŸŽÆ Customer.setLoyaltyBonusApplied");
227    println!("   šŸ“§ sendWelcomeEmail");
228    println!("   šŸ’° applyLoyaltyBonus");
229    println!("   🚨 flagForReview");
230    println!("   šŸ”’ notifySecurityTeam");
231    println!("   āœ… Customer.setWelcomeEmailSent");
232    println!("   āœ… Transaction.setRiskProcessed");
233    println!();
234
235    // Execute the inline rules
236    println!("šŸš€ Executing inline GRL rules...");
237    let result = engine.execute(&facts)?;
238
239    println!("\nšŸ“Š Inline Rules Execution Results:");
240    println!("   Cycles: {}", result.cycle_count);
241    println!("   Rules evaluated: {}", result.rules_evaluated);
242    println!("   Rules fired: {}", result.rules_fired);
243    println!("   Execution time: {:?}", result.execution_time);
244
245    println!("\nšŸ Final state:");
246    if let Some(customer) = facts.get("Customer") {
247        println!("   Customer = {customer:?}");
248    }
249    if let Some(transaction) = facts.get("Transaction") {
250        println!("   Transaction = {transaction:?}");
251    }
252
253    println!("\nšŸŽÆ Inline GRL Rules Demonstrated:");
254    println!("   šŸ“ Rules defined as strings directly in code");
255    println!("   šŸ”§ No external files needed");
256    println!("   ⚔ Quick prototyping and testing");
257    println!("   šŸ† Customer tier management");
258    println!("   šŸ’° Loyalty bonus system");
259    println!("   šŸ”’ Security and fraud detection");
260    println!("   šŸ“§ Email notification system");
261
262    Ok(())
263}