1use std::collections::BTreeMap;
4
5use crate::run::RunParameters;
6
7#[derive(Clone, Debug)]
8pub(crate) struct ComparisonConfig {
9 pub spec: wowlab_types::game::SpecId,
10 pub parameters: RunParameters,
11 pub race: Option<String>,
12 pub bugs: bool,
14 pub simc_debug: bool,
16}
17
18#[derive(Clone, Debug)]
19pub(crate) struct SimOutput {
20 pub dps: f64,
21 pub spells: BTreeMap<String, SpellResult>,
22 pub timeline: Vec<CastEntry>,
23 pub encounter_debug: Option<crate::encounter_debug::EncounterDebugReport>,
24 pub resource_gains: BTreeMap<String, ResourceGain>,
26}
27
28impl SimOutput {
29 pub(crate) fn new(
31 dps: f64,
32 spells: Vec<(String, SpellResult)>,
33 timeline: Vec<CastEntry>,
34 ) -> Self {
35 let mut merged: BTreeMap<String, SpellResult> = BTreeMap::new();
36
37 for (name, result) in spells {
38 let entry = merged.entry(name).or_default();
39
40 entry.dps += result.dps;
41 entry.casts += result.casts;
42 entry.hits += result.hits;
43 entry.pct += result.pct;
44 }
45
46 let mut spells = merged;
47
48 let mut timeline_casts: BTreeMap<&str, u32> = BTreeMap::new();
49
50 for cast in &timeline {
51 *timeline_casts.entry(cast.spell_name.as_str()).or_insert(0) += 1;
52 }
53
54 for (name, casts) in timeline_casts {
55 if let Some(spell) = spells.get_mut(name) {
56 if spell.casts == 0 {
57 spell.casts = casts;
58 }
59 } else {
60 let key = String::from(name);
61
62 spells.insert(
63 key,
64 SpellResult {
65 casts,
66 ..SpellResult::default()
67 },
68 );
69 }
70 }
71
72 Self {
73 dps,
74 spells,
75 timeline,
76 encounter_debug: None,
77 resource_gains: BTreeMap::new(),
78 }
79 }
80
81 #[must_use]
82 pub(crate) fn with_encounter_debug(
83 mut self,
84 report: crate::encounter_debug::EncounterDebugReport,
85 ) -> Self {
86 self.encounter_debug = Some(report);
87
88 self
89 }
90}
91
92#[derive(Clone, Copy, Debug, Default)]
94pub(crate) struct ResourceGain {
96 pub gained: f64,
97 pub wasted: f64,
98}
99
100#[derive(Clone, Debug, Default)]
101pub(crate) struct SpellResult {
102 pub dps: f64,
103 pub casts: u32,
104 pub hits: u32,
109 pub pct: f64,
110}
111
112#[derive(Clone, Debug)]
113pub(crate) struct CastEntry {
114 pub time_secs: f64,
115 pub spell_name: String,
116}
117
118pub(crate) trait SimProvider {
119 fn name(&self) -> &str;
120 fn run(&self, config: &ComparisonConfig) -> anyhow::Result<SimOutput>;
121}