aboutsummaryrefslogtreecommitdiff
path: root/src/models/timer.cpp
diff options
context:
space:
mode:
authorflu0r1ne <flu0r1ne@flu0r1ne.net>2023-07-13 12:20:29 -0500
committerflu0r1ne <flu0r1ne@flu0r1ne.net>2023-07-13 12:20:29 -0500
commit2cb9b6fdc38a5df00ade737f90a9daf685ab89c3 (patch)
tree0a01a5fff4785520ae1a8d400b36f6bcdf84c532 /src/models/timer.cpp
downloadfreqtimer-web-2cb9b6fdc38a5df00ade737f90a9daf685ab89c3.tar.xz
freqtimer-web-2cb9b6fdc38a5df00ade737f90a9daf685ab89c3.zip
Init commit
Diffstat (limited to 'src/models/timer.cpp')
-rw-r--r--src/models/timer.cpp153
1 files changed, 153 insertions, 0 deletions
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 <cinttypes>
+
+#ifdef EMSCRIPTEN
+#include <emscripten/html5.h>
+#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<int64_t>(_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;
+}