1use std::collections::BTreeMap;
4
5#[cfg(test)]
6use googletest::{Result as GtestResult, prelude::*};
7use wowlab_common::sim::intent::{INTENT_VERSION, SimConfigIntent};
8use wowlab_types::{game::SpecId, sim::EncounterDefinition};
9
10pub(crate) const CANONICAL_PATCHWERK_ENEMY_LEVEL: u16 = 80;
11pub(crate) const CANONICAL_PATCHWERK_EXPANSION_ID: u32 = 11;
13pub(crate) const DEFAULT_PLAYER_LEVEL: u16 = 80;
14pub(crate) const PLAYER_EXPANSION_ID: u32 = 11;
15
16pub(crate) fn canonical_patchwerk_intent(
17 spec: SpecId,
18 rotation_id: impl Into<String>,
19 duration_s: f64,
20) -> anyhow::Result<SimConfigIntent> {
21 patchwerk_intent_with_context(
22 spec,
23 rotation_id,
24 duration_s,
25 CANONICAL_PATCHWERK_ENEMY_LEVEL,
26 CANONICAL_PATCHWERK_EXPANSION_ID,
27 )
28}
29
30fn patchwerk_intent_with_context(
31 spec: SpecId,
32 rotation_id: impl Into<String>,
33 duration_s: f64,
34 target_level: u16,
35 target_expansion_id: u32,
36) -> anyhow::Result<SimConfigIntent> {
37 let encounter = EncounterDefinition::patchwerk(duration_s, target_level, target_expansion_id)?;
38
39 Ok(SimConfigIntent {
40 intent_version: INTENT_VERSION.to_string(),
41 spec: spec.wow_spec_id(),
42 rotation_id: rotation_id.into(),
43 loadout: None,
44 expansion_talents: BTreeMap::new(),
45 player_level: DEFAULT_PLAYER_LEVEL,
46 player_expansion_id: PLAYER_EXPANSION_ID,
47 encounter,
48 settings: BTreeMap::new(),
49 gear: Vec::new(),
50 })
51}
52
53#[cfg(test)]
54mod tests {
55 use wowlab_common::sim::intent::{parse_sim_config, serialize_sim_config};
56 use wowlab_types::sim::{DifficultyContext, EnemyDefinition};
57
58 use super::*;
59
60 #[gtest]
61 fn patchwerk_intent_round_trips_with_typed_non_default_encounter_context() -> GtestResult<()> {
62 let intent = patchwerk_intent_with_context(
63 SpecId::Assassination,
64 "assassination_rogue_assisted",
65 137.5,
66 72,
67 10,
68 )
69 .or_fail()?;
70 let serialized = serialize_sim_config(&intent).or_fail()?;
71 let parsed = parse_sim_config(&serialized).or_fail()?;
72
73 verify_that!(
74 &parsed,
75 matches_pattern!(SimConfigIntent {
76 intent_version: eq(INTENT_VERSION),
77 spec: eq(&259),
78 rotation_id: eq("assassination_rogue_assisted"),
79 encounter: matches_pattern!(EncounterDefinition {
80 fixed_duration_s: eq(&Some(137.5)),
81 enemies: elements_are![matches_pattern!(EnemyDefinition {
82 level: eq(&72),
83 difficulty: eq(&DifficultyContext::Generic { expansion_id: 10 }),
84 ..
85 })],
86 ..
87 }),
88 ..
89 })
90 )?;
91 verify_true!(parsed.settings.is_empty())?;
92 verify_true!(parsed.gear.is_empty())?;
93
94 Ok(())
95 }
96
97 #[gtest]
98 fn patchwerk_intent_uses_supplied_spec() -> GtestResult<()> {
99 let intent =
100 canonical_patchwerk_intent(SpecId::Fire, "fire_mage_assisted", 60.0).or_fail()?;
101
102 verify_that!(intent.spec, eq(63))?;
103 verify_that!(intent.rotation_id, eq("fire_mage_assisted"))?;
104 verify_that!(
105 intent.encounter.enemies[0].level,
106 eq(CANONICAL_PATCHWERK_ENEMY_LEVEL)
107 )?;
108
109 Ok(())
110 }
111}