fraud_detection/
fraud_detection.rs

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, LogicalOperator, Operator, Value};
6use std::collections::HashMap;
7
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}