Skip to main content

wowlab_engine/cli/sim/
progress.rs

1use std::sync::{
2    Mutex,
3    atomic::{AtomicU32, Ordering},
4};
5
6use wowlab_common::output;
7use wowlab_engine_ports::{ProgressDone, ProgressSink, ProgressStart, ProgressTick};
8use wowlab_types::sim::FastMap;
9
10pub(super) struct ConsoleProgress {
11    bar: Option<output::ProgressBar>,
12    completed: AtomicU32,
13    per_chunk: Mutex<FastMap<String, u32>>,
14}
15
16impl ConsoleProgress {
17    pub(super) fn new(total: u32, show_progress: bool) -> Self {
18        Self {
19            bar: show_progress.then(|| output::ProgressBar::new(u64::from(total), "Simulating...")),
20            completed: AtomicU32::new(0),
21            per_chunk: Mutex::new(FastMap::default()),
22        }
23    }
24
25    pub(super) fn finish(&self) {
26        if let Some(ref bar) = self.bar {
27            bar.finish("");
28        }
29    }
30
31    fn advance(&self, chunk_id: &str, chunk_completed: u32) -> u32 {
32        let delta = {
33            let mut guard = self
34                .per_chunk
35                .lock()
36                .unwrap_or_else(std::sync::PoisonError::into_inner);
37            let prev = guard.entry(chunk_id.to_string()).or_insert(0);
38            let delta = chunk_completed.saturating_sub(*prev);
39
40            *prev = chunk_completed;
41
42            delta
43        };
44
45        self.completed.fetch_add(delta, Ordering::Relaxed) + delta
46    }
47}
48
49impl ProgressSink for ConsoleProgress {
50    fn on_start(&self, _meta: ProgressStart) {}
51
52    fn on_tick(&self, tick: ProgressTick) {
53        let global = self.advance(&tick.chunk_id, tick.iterations_completed);
54
55        if let Some(ref bar) = self.bar {
56            match (tick.running_mean_dps, tick.throughput_sps) {
57                (Some(mean), Some(tp)) => bar.tick_with_stats(u64::from(global), mean, tp),
58                _ => bar.tick(u64::from(global)),
59            }
60        }
61    }
62
63    fn on_complete(&self, done: ProgressDone) {
64        let global = self.advance(&done.chunk_id, done.iterations_completed);
65
66        if let Some(ref bar) = self.bar {
67            bar.tick(u64::from(global));
68        }
69    }
70}