1use 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 resolver.register_source(atk_id.clone(), Box::new(ConstantSource(100.0)));
22 println!("ATK base: 100");
23
24 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 resolver.register_source(def_id.clone(), Box::new(ConstantSource(80.0)));
35 println!("DEF base: 80");
36
37 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 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 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 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 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 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}