From 2cb9b6fdc38a5df00ade737f90a9daf685ab89c3 Mon Sep 17 00:00:00 2001 From: flu0r1ne Date: Thu, 13 Jul 2023 12:20:29 -0500 Subject: Init commit --- src/models/timer.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/models/timer.cpp (limited to 'src/models/timer.cpp') diff --git a/src/models/timer.cpp b/src/models/timer.cpp new file mode 100644 index 0000000..a05e8c1 --- /dev/null +++ b/src/models/timer.cpp @@ -0,0 +1,153 @@ +#include "timer.hpp" +#include + +#ifdef EMSCRIPTEN +#include +#endif + +#ifdef TEST +#define OVERRIDABLE_DURING_TESTING __attribute__((weak)) +#else +#define OVERRIDABLE_DURING_TESTING static inline +#endif + + +OVERRIDABLE_DURING_TESTING uint64_t monotonic_timestamp_ms() { +#ifdef EMSCRIPTEN + return emscripten_get_now(); +#else + return 0.0; // TODO: unimplemented +#endif +} + +namespace time_const { + static const int64_t MSEC = 1; + static const int64_t SEC = 1000 * MSEC; + static const int64_t MIN = 60 * SEC; + static const int64_t HOUR = 60 * MIN; +}; + +FreqTimer::FreqTimer() { + clear(); +} + +static void _append_ratio(std::string & display_val, int64_t & ms, int64_t ratio, bool two_digit = true) { + int64_t amount = ms / ratio; + ms -= amount * ratio; + + char buf[3]; + + if(two_digit) { + snprintf(buf, sizeof(buf), "%02" PRIi64, amount); + } else { + snprintf(buf, sizeof(buf), "%1" PRIi64, amount); + } + + display_val.append(buf); +} + +std::string FreqTimer::counter_display_value() const { + using namespace time_const; + + int64_t ms = time_ms(); + + std::string display_val; + + if(ms < 0) { + display_val.append("+ "); + ms = -ms; + } + + if(ms > 99 * HOUR) { + return "MAX TIME EXCEEDED"; + } + + _append_ratio(display_val, ms, HOUR); + display_val.append(" : "); + _append_ratio(display_val, ms, MIN); + display_val.append(" : "); + _append_ratio(display_val, ms, SEC); + display_val.append("."); + _append_ratio(display_val, ms, 100 * MSEC, false); + + return display_val; +} + +void FreqTimer::increment_preset_ms(uint64_t amount_ms) { + if(_state != State::SETTING) { + clear(); + } + + _preset_ms += amount_ms; +} + +void FreqTimer::toggleStart() { + if(_state == State::RUNNING) { + _stop(); + } else { + _start(); + } +} + +bool FreqTimer::has_preset() const { + return _preset_ms != 0; +} + +void FreqTimer::reset() { + _time_offset_ms = 0; + _time_start_ms = monotonic_timestamp_ms(); + _state = State::RESET; +} + +void FreqTimer::clear() { + _time_offset_ms = 0; + _time_start_ms = monotonic_timestamp_ms(); + _preset_ms = 0; + _state = State::SETTING; +} + +double FreqTimer::record_floor() const { + + int64_t ms; + if(has_preset()) { + ms = _preset_ms; + } else { + ms = total_duration_ms(); + } + + return 60.0e3 / ms; +} + +double FreqTimer::overtime_record_floor() const { + return 60.0e3 / total_duration_ms(); +} + +uint64_t FreqTimer::_duration_since_last_stop_ms() const { + if(_state != State::RUNNING) { + return 0; + } + + return monotonic_timestamp_ms() - _time_start_ms; +} + +int64_t FreqTimer::time_ms() const { + if (_preset_ms == 0) { + return total_duration_ms(); + } + + return static_cast(_preset_ms) - total_duration_ms(); +} + +uint64_t FreqTimer::total_duration_ms() const { + return _time_offset_ms + _duration_since_last_stop_ms(); +} + +void FreqTimer::_stop() { + _time_offset_ms += _duration_since_last_stop_ms(); + _state = State::STOPPED; +} + +void FreqTimer::_start() { + _time_start_ms = monotonic_timestamp_ms(); + _state = State::RUNNING; +} -- cgit v1.2.3