context/
context.rs

1//! Context example: Using StatContext for conditional stat calculations
2//!
3//! This example demonstrates:
4//! - Using StatContext to pass game state
5//! - Conditional transforms based on context
6//! - Different stat values in different contexts
7
8use zzstat::source::ConstantSource;
9use zzstat::transform::{ConditionalTransform, MultiplicativeTransform};
10use zzstat::*;
11
12fn main() -> Result<(), StatError> {
13    let mut resolver = StatResolver::new();
14
15    let atk_id = StatId::from_str("ATK");
16    let def_id = StatId::from_str("DEF");
17
18    println!("=== Setting up stats with context-dependent transforms ===\n");
19
20    // Base ATK
21    resolver.register_source(atk_id.clone(), Box::new(ConstantSource(100.0)));
22    println!("ATK base: 100");
23
24    // ATK gets +50% bonus in combat
25    let combat_bonus = ConditionalTransform::new(
26        |ctx| ctx.get::<bool>("in_combat").unwrap_or(false),
27        Box::new(MultiplicativeTransform::new(1.5)),
28        "Combat bonus +50%",
29    );
30    resolver.register_transform(atk_id.clone(), Box::new(combat_bonus));
31    println!("ATK: +50% when in combat");
32
33    // Base DEF
34    resolver.register_source(def_id.clone(), Box::new(ConstantSource(80.0)));
35    println!("DEF base: 80");
36
37    // DEF gets +25% bonus in PvP zones
38    let pvp_bonus = ConditionalTransform::new(
39        |ctx| {
40            ctx.get::<String>("zone_type")
41                .map(|z| z == "pvp")
42                .unwrap_or(false)
43        },
44        Box::new(MultiplicativeTransform::new(1.25)),
45        "PvP zone bonus +25%",
46    );
47    resolver.register_transform(def_id.clone(), Box::new(pvp_bonus));
48    println!("DEF: +25% in PvP zones");
49
50    // Scenario 1: Out of combat, normal zone
51    println!("\n=== Scenario 1: Out of combat, normal zone ===");
52    let mut context1 = StatContext::new();
53    context1.set("in_combat", false);
54    context1.set("zone_type", "normal");
55
56    let atk1 = resolver.resolve(&atk_id, &context1)?;
57    let def1 = resolver.resolve(&def_id, &context1)?;
58
59    println!("ATK: {:.2} (no bonuses)", atk1.value);
60    println!("DEF: {:.2} (no bonuses)", def1.value);
61
62    // Scenario 2: In combat, normal zone
63    println!("\n=== Scenario 2: In combat, normal zone ===");
64    let mut context2 = StatContext::new();
65    context2.set("in_combat", true);
66    context2.set("zone_type", "normal");
67
68    // Invalidate cache to force recalculation
69    resolver.invalidate(&atk_id);
70    resolver.invalidate(&def_id);
71
72    let atk2 = resolver.resolve(&atk_id, &context2)?;
73    let def2 = resolver.resolve(&def_id, &context2)?;
74
75    println!("ATK: {:.2} (combat bonus: 100 * 1.5)", atk2.value);
76    println!("DEF: {:.2} (no bonuses)", def2.value);
77
78    // Scenario 3: Out of combat, PvP zone
79    println!("\n=== Scenario 3: Out of combat, PvP zone ===");
80    let mut context3 = StatContext::new();
81    context3.set("in_combat", false);
82    context3.set("zone_type", "pvp");
83
84    resolver.invalidate(&atk_id);
85    resolver.invalidate(&def_id);
86
87    let atk3 = resolver.resolve(&atk_id, &context3)?;
88    let def3 = resolver.resolve(&def_id, &context3)?;
89
90    println!("ATK: {:.2} (no bonuses)", atk3.value);
91    println!("DEF: {:.2} (PvP bonus: 80 * 1.25)", def3.value);
92
93    // Scenario 4: In combat, PvP zone
94    println!("\n=== Scenario 4: In combat, PvP zone ===");
95    let mut context4 = StatContext::new();
96    context4.set("in_combat", true);
97    context4.set("zone_type", "pvp");
98
99    resolver.invalidate(&atk_id);
100    resolver.invalidate(&def_id);
101
102    let atk4 = resolver.resolve(&atk_id, &context4)?;
103    let def4 = resolver.resolve(&def_id, &context4)?;
104
105    println!("ATK: {:.2} (combat bonus: 100 * 1.5)", atk4.value);
106    println!("DEF: {:.2} (PvP bonus: 80 * 1.25)", def4.value);
107
108    println!("\n=== Summary ===");
109    println!("Context allows stats to vary based on game state:");
110    println!("  - Combat state affects ATK");
111    println!("  - Zone type affects DEF");
112    println!("  - Stats are recalculated when context changes");
113
114    Ok(())
115}