livesplit_core/analysis/
total_playtime.rs

1//! Provides functionality to calculate the total playtime for either a
2//! [`Run`] or a [`Timer`]. For a [`Run`], all the durations stored in the attempt
3//! history are summed together. For a [`Timer`], the current attempt's duration
4//! is also factored in.
5
6use crate::{Run, TimeSpan, Timer, TimingMethod};
7/// Allows calculating the total playtime.
8pub trait TotalPlaytime {
9    /// Calculates the total playtime.
10    fn total_playtime(&self) -> TimeSpan;
11}
12
13impl TotalPlaytime for Run {
14    fn total_playtime(&self) -> TimeSpan {
15        let mut total_playtime = TimeSpan::zero();
16
17        for attempt in self.attempt_history() {
18            if let Some(duration) = attempt.duration() {
19                // Either >= 1.6.0 or a finished run
20                total_playtime += duration;
21                if let Some(pause_time) = attempt.pause_time() {
22                    total_playtime -= pause_time;
23                }
24            } else {
25                // Must be < 1.6.0 and a reset
26                // Calculate the sum of the segments for that run
27                for segment in self.segments() {
28                    if let Some(segment_time) = segment
29                        .segment_history()
30                        .get(attempt.index())
31                        .and_then(|s| s[TimingMethod::RealTime])
32                    {
33                        total_playtime += segment_time;
34                    }
35                }
36            }
37        }
38
39        total_playtime
40    }
41}
42
43impl TotalPlaytime for Timer {
44    fn total_playtime(&self) -> TimeSpan {
45        let timer_play_time =
46            self.current_attempt_duration() - self.get_pause_time().unwrap_or_default();
47        let run_play_time = self.run().total_playtime();
48
49        timer_play_time + run_play_time
50    }
51}
52
53impl<'a, T: 'a + TotalPlaytime> TotalPlaytime for &'a T {
54    fn total_playtime(&self) -> TimeSpan {
55        (*self).total_playtime()
56    }
57}
58
59/// Calculates the total playtime. The source can be a [`Run`], [`Timer`] or any
60/// other type that implements the [`TotalPlaytime`] trait.
61pub fn calculate<T: TotalPlaytime>(source: T) -> TimeSpan {
62    source.total_playtime()
63}