SimulationCraft
SimulationCraft is a tool to explore combat mechanics in the popular MMO RPG World of Warcraft (tm).
timespan.hpp
1 // ==========================================================================
2 // Dedmonwakeen's Raid DPS/TPS Simulator.
3 // Send questions to [email protected]
4 // ==========================================================================
5 
6 // ==========================================================================
7 // Custom Time class
8 // ==========================================================================
9 
10 #ifndef SC_TIMESPAN_HPP
11 #define SC_TIMESPAN_HPP
12 
13 #include "config.hpp"
14 
15 #include <cmath>
16 #include <numeric>
17 #include <limits>
18 #include <type_traits>
19 #include <cassert>
20 #include <cstdint>
21 #include "util/format.hpp"
22 
23 // if timespan_t is in the global namespace, there's a name lookup issue with
24 // one of the Qt headers. Problem is avoided by defining in a sub-namespace
25 // and then lifting into the global namespace with a using declaration.
26 namespace simc
27 {
28 
37  class timespan_t
38  {
39  private:
40  using time_t = int_least64_t;
41 
42  time_t time;
43 
44  template<typename Rep>
45  explicit constexpr timespan_t(Rep t) :
46  time(static_cast<time_t>(t))
47  {
48  }
49 
50  public:
51  constexpr timespan_t() : time( 0 )
52  { }
53 
54  constexpr double total_minutes() const
55  {
56  return static_cast<double>(time) * (1.0 / (60 * 1000));
57  }
58  constexpr double total_seconds() const
59  {
60  return static_cast<double>(time) * (1.0 / 1000);
61  }
62  constexpr time_t total_millis() const
63  {
64  return time;
65  }
66 
67  template <typename Rep, typename = std::enable_if_t<std::is_arithmetic<Rep>::value>>
68  static constexpr timespan_t from_millis(Rep millis)
69  {
70  return timespan_t(millis);
71  }
72 
73  template <typename Rep, typename = std::enable_if_t<std::is_arithmetic<Rep>::value>>
74  static constexpr timespan_t from_seconds(Rep seconds)
75  {
76  return timespan_t(static_cast<time_t>(seconds * 1000));
77  }
78 
79  template <typename Rep, typename = std::enable_if_t<std::is_arithmetic<Rep>::value>>
80  static constexpr timespan_t from_minutes(Rep minutes)
81  {
82  return timespan_t(static_cast<time_t>(minutes * (60 * 1000)));
83  }
84 
85  constexpr bool operator==(timespan_t right) const
86  {
87  return time == right.time;
88  }
89  constexpr bool operator!=(timespan_t right) const
90  {
91  return time != right.time;
92  }
93 
94  constexpr bool operator>(timespan_t right) const
95  {
96  return time > right.time;
97  }
98  constexpr bool operator>=(timespan_t right) const
99  {
100  return time >= right.time;
101  }
102  constexpr bool operator<(timespan_t right) const
103  {
104  return time < right.time;
105  }
106  constexpr bool operator<=(timespan_t right) const
107  {
108  return time <= right.time;
109  }
110 
111  constexpr timespan_t& operator+=(timespan_t right)
112  {
113  assert(right < zero() || *this < zero() || *this <= max() - right);
114  assert(right > zero() || *this >= min() - right);
115  time += right.time;
116  return *this;
117  }
118  constexpr timespan_t& operator-=(timespan_t right)
119  {
120  assert(right < zero() || *this >= right + min());
121  assert(right > zero() || *this <= right + max());
122  time -= right.time;
123  return *this;
124  }
125  constexpr timespan_t& operator %=(timespan_t right)
126  {
127  time %= right.time;
128  return *this;
129  }
130 
131  template <typename Rep, typename = std::enable_if_t<std::is_arithmetic<Rep>::value>>
132  constexpr timespan_t& operator*=(Rep right)
133  {
134  time = static_cast<time_t>(time * right);
135  return *this;
136  }
137 
138  template <typename Rep, typename = std::enable_if_t<std::is_arithmetic<Rep>::value>>
139  constexpr timespan_t& operator/=(Rep right)
140  {
141  time = static_cast<time_t>(time / right);
142  return *this;
143  }
144 
145  friend constexpr timespan_t operator+(timespan_t right)
146  {
147  return right;
148  }
149  friend constexpr timespan_t operator-(timespan_t right)
150  {
151  return timespan_t(-right.time);
152  }
153 
154  friend constexpr timespan_t operator+(timespan_t left, timespan_t right)
155  {
156  return left += right;
157  }
158 
159  friend constexpr timespan_t operator-(timespan_t left, timespan_t right)
160  {
161  return left -= right;
162  }
163 
164  template <typename Rep>
165  friend constexpr auto operator*(timespan_t left, Rep right) -> std::enable_if_t<std::is_arithmetic<Rep>::value, timespan_t>
166  {
167  return left *= right;
168  }
169 
170  template <typename Rep>
171  friend constexpr auto operator*(Rep left, timespan_t right) -> std::enable_if_t<std::is_arithmetic<Rep>::value, timespan_t>
172  {
173  return right *= left;
174  }
175 
176  template <typename Rep>
177  friend constexpr auto operator/(timespan_t left, Rep right) -> std::enable_if_t<std::is_arithmetic<Rep>::value, timespan_t>
178  {
179  return left /= right;
180  }
181 
182  friend constexpr double operator/(timespan_t left, timespan_t right)
183  {
184  return static_cast<double>(left.time) / right.time;
185  }
186 
187  friend constexpr timespan_t operator%(timespan_t left, timespan_t right)
188  {
189  return left %= right;
190  }
191 
192  using native_t = time_t;
193 
194  // Only to be used to convert without loss of precision for a computation
195  // that will later be converted back via from_native().
196  static constexpr native_t to_native(timespan_t t)
197  {
198  return t.time;
199  }
200 
201  // Only to be used to convert the result of to_native().
202  template<typename Rep>
203  static constexpr timespan_t from_native(Rep t)
204  {
205  return timespan_t(t);
206  }
207 
208  static constexpr timespan_t zero()
209  {
210  return {};
211  }
212  static constexpr timespan_t max()
213  {
214  return timespan_t( std::numeric_limits<time_t>::max() );
215  }
216  static constexpr timespan_t min()
217  {
218  static_assert( !std::is_floating_point<time_t>::value );
219  return timespan_t( std::numeric_limits<time_t>::min() );
220  }
221 
222  friend void sc_format_to( timespan_t, fmt::format_context::iterator );
223  };
224 
225 } // namespace simc
226 
227 using simc::timespan_t;
228 
229 constexpr timespan_t operator"" _ms( unsigned long long time )
230 {
231  return timespan_t::from_millis( time );
232 }
233 
234 constexpr timespan_t operator"" _s( unsigned long long time )
235 {
236  return timespan_t::from_seconds( time );
237 }
238 
239 constexpr timespan_t operator"" _s( long double time )
240 {
241  return timespan_t::from_seconds( time );
242 }
243 
244 constexpr timespan_t operator"" _min( unsigned long long time )
245 {
246  return timespan_t::from_minutes( time );
247 }
248 
249 constexpr timespan_t operator"" _min( long double time )
250 {
251  return timespan_t::from_minutes( time );
252 }
253 
254 #endif // SC_TIMESPAN_HPP
Definition: timespan.cpp:10
Class for representing InGame time.
Definition: timespan.hpp:37