diff options
| author | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-07-13 12:20:29 -0500 | 
|---|---|---|
| committer | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-07-13 12:20:29 -0500 | 
| commit | 2cb9b6fdc38a5df00ade737f90a9daf685ab89c3 (patch) | |
| tree | 0a01a5fff4785520ae1a8d400b36f6bcdf84c532 /src/models | |
| download | freqtimer-web-2cb9b6fdc38a5df00ade737f90a9daf685ab89c3.tar.xz freqtimer-web-2cb9b6fdc38a5df00ade737f90a9daf685ab89c3.zip | |
Init commit
Diffstat (limited to 'src/models')
| -rw-r--r-- | src/models/counter.cpp | 35 | ||||
| -rw-r--r-- | src/models/counter.hpp | 33 | ||||
| -rw-r--r-- | src/models/timer.cpp | 153 | ||||
| -rw-r--r-- | src/models/timer.hpp | 126 | 
4 files changed, 347 insertions, 0 deletions
| diff --git a/src/models/counter.cpp b/src/models/counter.cpp new file mode 100644 index 0000000..4855c24 --- /dev/null +++ b/src/models/counter.cpp @@ -0,0 +1,35 @@ +#include "models/counter.hpp" + +double FreqCounter::rate() const { +	uint64_t ms = _timer->total_duration_ms(); + +	if(_timer->overtime()) { +		ms = _timer->preset_ms(); +	} + +	return static_cast<double>(_cnt) / (ms / 60.0e3); +} + + +double FreqCounter::overtime_rate() const { +	return static_cast<double>(_overtime_cnt) / (_timer->total_duration_ms() / 60.0e3); +} + +std::string FreqCounter::display_value() const { +	if(_cnt == UINT32_MAX) { +		return "ERR"; +	} + +	return std::to_string(_cnt); +} + +void FreqCounter::inc() { + +	if(_overtime_cnt != UINT32_MAX) +		_overtime_cnt++; + +	if(!_timer->overtime()) { +		_cnt = _overtime_cnt; +	} + +} diff --git a/src/models/counter.hpp b/src/models/counter.hpp new file mode 100644 index 0000000..d1b68fc --- /dev/null +++ b/src/models/counter.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include <inttypes.h> +#include <string> +#include "models/timer.hpp" + +class FreqCounter { + +	public: + +	FreqCounter(FreqTimer const & timer) +		: _timer(&timer) +	{} + +	void reset() { _cnt = _overtime_cnt = 0; } + +	void inc(); + +	uint32_t cnt() const { return _cnt; } + +	[[nodiscard]] double rate() const; + +	[[nodiscard]] double overtime_rate() const; + +	[[nodiscard]] std::string display_value() const; + + +	private: + +	uint32_t _cnt; +	uint32_t _overtime_cnt; +	FreqTimer const * _timer; +}; 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; +} diff --git a/src/models/timer.hpp b/src/models/timer.hpp new file mode 100644 index 0000000..0b0a978 --- /dev/null +++ b/src/models/timer.hpp @@ -0,0 +1,126 @@ +#pragma once + +#include <stdint.h> +#include <string> + +class FreqTimer { +	public: + +	FreqTimer(); + +	/* +	 * Starts the timer if stopped +	 */ +	void toggleStart(); + +	/* +	 * Timer is running +	 */ +	[[nodiscard]] bool running() const { return _state == State::RUNNING; } + +	/* +	 * Timer has been started +	 */ +	[[nodiscard]] bool started() const { +		return _state == State::RUNNING or _state == State::STOPPED; +	} + +	/* +	 * Current preset in ms +	 */ +	[[nodiscard]] int64_t preset_ms() const noexcept { return _preset_ms; } + +	/* +	 * Whether the preset time has been exceeded +	 */ +	[[nodiscard]] bool overtime() const { return time_ms() < 0; } + +	/* +	 * Reset the time +	 */ +	void reset(); + +	/* +	 * Reset the time and preset +	 */ +	void clear(); + +	[[nodiscard]] std::string counter_display_value() const; + +	/* +	 * Lowest frequency which can be measured +	 * in the interval (as measured in events/min +	 * or multiples of 60 Hz) +	 */ +	[[nodiscard]] double record_floor() const; + + +	[[nodiscard]] double overtime_record_floor() const; + +	/* +	 * Without a preset, the timer acts like a +	 * stopwatch and counts freely from zero. +	 * With a preset, the timer acts like a timer +	 * counting down to zero, then counts up to +	 * measure the number of seconds since the +	 * timing has ended. +	 */ +	[[nodiscard]] bool has_preset() const; + +	/* +	 * The current duration in milliseconds. +	 * +	 * If the timer has exceeded the preset, +	 * this time will be negative. +	 */ +	[[nodiscard]] int64_t time_ms() const; + +	[[nodiscard]] uint64_t total_duration_ms() const; + + +	/* +	 * Increment the timer's preset by the specified +	 * amount (in milisec.) Subsequent calls between +	 * timings increment the time. Incrementing a +	 * timing after a timing has been restarted will +	 * reset the timing and start from zero. +	 */ +	void increment_preset_ms(uint64_t amount_ms); + +	private: + +	enum class State { +		// The timer initially starts in +		// "setting" mode and the preset +		// can be modified by incrementing +		// it by values (measured in seconds) +		// +		// Once it is started, this preset +		// is "sticky" and a reset returns +		// the timer to the preset value. +		// Incrementing the preset or clearing +		// the timer moves the timer back +		// into setting mode. +		SETTING, +		// Timer is active +		RUNNING, +		// Timer is temporarily stopped +		STOPPED, +		// Reset +		RESET, +	}; + +	State _state; + +	uint64_t _time_offset_ms; +	uint64_t _time_start_ms; + +	int64_t _preset_ms; + +	[[nodiscard]] uint64_t _duration_since_last_stop_ms() const; + + +	void _stop(); +	void _start(); + +}; | 
