1use rkyv::{Archive, Deserialize, Serialize};
4use std::fmt;
5use std::ops::{Add, AddAssign, Sub, SubAssign};
6
7#[derive(Archive, Deserialize, Serialize, Clone, Copy, PartialEq, Default)]
9#[rkyv(compare(PartialEq))]
10pub struct SimTime(pub f64);
11
12impl SimTime {
13 pub const ZERO: SimTime = SimTime(0.0);
15
16 pub const MAX: SimTime = SimTime(f64::MAX);
18
19 #[inline]
21 pub fn from_seconds(s: f64) -> Self {
22 SimTime(s)
23 }
24
25 #[inline]
27 pub fn from_minutes(m: f64) -> Self {
28 SimTime(m * 60.0)
29 }
30
31 #[inline]
33 pub fn from_hours(h: f64) -> Self {
34 SimTime(h * 3600.0)
35 }
36
37 #[inline]
39 pub fn as_seconds(&self) -> f64 {
40 self.0
41 }
42
43 #[inline]
45 pub fn as_minutes(&self) -> f64 {
46 self.0 / 60.0
47 }
48
49 #[inline]
51 pub fn as_hours(&self) -> f64 {
52 self.0 / 3600.0
53 }
54
55 #[inline]
57 pub fn is_zero(&self) -> bool {
58 self.0 == 0.0
59 }
60}
61
62impl Add for SimTime {
63 type Output = SimTime;
64
65 #[inline]
66 fn add(self, rhs: SimTime) -> SimTime {
67 SimTime(self.0 + rhs.0)
68 }
69}
70
71impl Sub for SimTime {
72 type Output = SimTime;
73
74 #[inline]
75 fn sub(self, rhs: SimTime) -> SimTime {
76 SimTime(self.0 - rhs.0)
77 }
78}
79
80impl AddAssign for SimTime {
81 #[inline]
82 fn add_assign(&mut self, rhs: SimTime) {
83 self.0 += rhs.0;
84 }
85}
86
87impl SubAssign for SimTime {
88 #[inline]
89 fn sub_assign(&mut self, rhs: SimTime) {
90 self.0 -= rhs.0;
91 }
92}
93
94impl PartialOrd for SimTime {
95 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
96 self.0.partial_cmp(&other.0)
97 }
98}
99
100impl fmt::Debug for SimTime {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "SimTime({:.3}s)", self.0)
103 }
104}
105
106impl fmt::Display for SimTime {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 if self.0 >= 3600.0 {
109 write!(f, "{:.2}h", self.as_hours())
110 } else if self.0 >= 60.0 {
111 write!(f, "{:.2}m", self.as_minutes())
112 } else {
113 write!(f, "{:.2}s", self.0)
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_time_conversions() {
124 let t = SimTime::from_minutes(1.5);
125 assert_eq!(t.as_seconds(), 90.0);
126 assert_eq!(t.as_minutes(), 1.5);
127 }
128
129 #[test]
130 fn test_time_arithmetic() {
131 let t1 = SimTime::from_seconds(10.0);
132 let t2 = SimTime::from_seconds(5.0);
133 assert_eq!((t1 + t2).as_seconds(), 15.0);
134 assert_eq!((t1 - t2).as_seconds(), 5.0);
135 }
136}