From 2cb9b6fdc38a5df00ade737f90a9daf685ab89c3 Mon Sep 17 00:00:00 2001 From: flu0r1ne Date: Thu, 13 Jul 2023 12:20:29 -0500 Subject: Init commit --- src/controllers/timer_view.cpp | 238 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 src/controllers/timer_view.cpp (limited to 'src/controllers') diff --git a/src/controllers/timer_view.cpp b/src/controllers/timer_view.cpp new file mode 100644 index 0000000..28abd5c --- /dev/null +++ b/src/controllers/timer_view.cpp @@ -0,0 +1,238 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include "models/timer.hpp" +#include "models/counter.hpp" +#include "utils/utils.hpp" + +using emval = emscripten::val; + +thread_local const emval document = emval::global("document"); + +class TimerView { + + public: + + TimerView() + : _counters { FreqCounter(_timer), FreqCounter(_timer) } + , _alarm_sound_triggered(false) + { } + + /* + * Timer + */ + + void timer_display_text(std::string const & text) { + set_inner_text_by_id("time-display", text); + } + + void timer_record_floor(std::string const & text) { + set_inner_text_by_id("record-floor", text); + } + + void timer_start_stop_button_label(std::string const & text) { + set_inner_text_by_id("start-stop-btn", text); + } + + void timer_clear_reset_button_label(std::string const & text) { + set_inner_text_by_id("clear-reset-btn", text); + } + + void handle_inc_time(uint32_t amount) { + _timer.increment_preset_ms(amount * 1000); + + _update_start_stop_label(); + _update_clear_reset_btn_label(); + _update_clear_reset_btn(); + } + + void handle_start_stop() { + _timer.toggleStart(); + + _update_start_stop_label(); + _update_clear_reset_btn_label(); + _update_clear_reset_btn(); + } + + void handle_clear_reset() { + if(_clear_reset_btn_clears()) { + clear(); + } else { + reset(); + } + + _update_clear_reset_btn_label(); + } + + /* + * Counter + */ + + void counter_display_text(uint32_t counter_num, std::string const & counter_text, std::string const & rate_text) { + std::string counter_id = "counter-"; + counter_id.append(std::to_string(counter_num)); + + std::string rate_id = "rate-"; + rate_id.append(std::to_string(counter_num)); + + set_inner_text_by_id(counter_id, counter_text); + set_inner_text_by_id(rate_id, rate_text); + } + + void handle_inc_counter(uint32_t counter_num) { + _counters[counter_num].inc(); + + _update_counter(counter_num); + } + + void handle_timer_update() { + + std::string value = _timer.counter_display_value(); + + timer_display_text(value); + + double record_floor = _timer.record_floor(); + + std::string rec_floor_text; + format_rate(rec_floor_text, record_floor); + + if(_timer.overtime()) { + std::string rec_floor_overtime; + format_rate(rec_floor_overtime, _timer.overtime_record_floor()); + rec_floor_text.append(", "); + rec_floor_text.append(rec_floor_overtime); + } + + timer_record_floor(rec_floor_text); + + for(size_t i = 0; i < _counters.size(); i++) + _update_counter(i); + + if(_timer.overtime() && !_alarm_sound_triggered) { + _play_alarm(); + _alarm_sound_triggered = true; + } + } + + private: + + FreqTimer _timer; + std::array _counters; + bool _alarm_sound_triggered; + + static void set_inner_text_by_id(std::string const & id, std::string const & text) { + emval timer_display = document.call("getElementById", emval(id.c_str())); + timer_display.set("innerText", text.c_str()); + } + + static void set_button_disabled(std::string const & id, bool disabled) { + emval timer_display = document.call("getElementById", emval(id.c_str())); + timer_display.set("disabled", disabled); + } + + void _update_counter(uint32_t counter_num) { + FreqCounter & counter = _counters[counter_num]; + + std::string text = counter.display_value(); + double rate = counter.rate(); + + std::string rate_val; + format_rate(rate_val, rate); + + if(_timer.overtime()) { + std::string rate_overtime; + format_rate(rate_overtime, counter.overtime_rate()); + rate_val.append(", "); + rate_val.append(rate_overtime); + } + + counter_display_text(counter_num, text, rate_val); + } + + static void _play_alarm() { + + EM_ASM({ + const handle = document.getElementById("sound-handle"); + + const duration = Math.round(handle.duration * 1000.0); + + handle.currentTime = 0; + handle.play().then(() => { + setTimeout(() => { + handle.pause(); + }, duration); + }); + }); + + } + + void _update_start_stop_label() { + if(_timer.running()) { + timer_start_stop_button_label("Stop"); + } else { + timer_start_stop_button_label("Start"); + } + } + + bool _clear_reset_btn_clears() const { + return _timer.has_preset() and !_timer.started(); + } + + void _update_clear_reset_btn_label() { + if(_clear_reset_btn_clears()) { + timer_clear_reset_button_label("Clear"); + } else { + timer_clear_reset_button_label("Reset"); + } + } + + void _update_clear_reset_btn() { + set_button_disabled("clear-reset-btn", _timer.running()); + } + + void clear() { + _timer.clear(); + + for(FreqCounter & counter : _counters) + counter.reset(); + + _alarm_sound_triggered = false; + } + + void reset() { + _timer.reset(); + + for(FreqCounter & counter : _counters) + counter.reset(); + + _alarm_sound_triggered = false; + } + +}; + + +EMSCRIPTEN_BINDINGS(timer_view) { + emscripten::class_("TimerView") + .constructor() + .function("handle_start_stop", + &TimerView::handle_start_stop + ) + .function("handle_clear_reset", + &TimerView::handle_clear_reset + ) + .function("handle_inc_counter", + &TimerView::handle_inc_counter + ) + .function("handle_inc_time", + &TimerView::handle_inc_time + ) + .function("handle_timer_update", + &TimerView::handle_timer_update + ); +} -- cgit v1.2.3