#pragma once #include "../Base/global_include.h" #include "global.h" namespace Psc { class Base_Statistics { protected: uint64_t start_time; [[nodiscard]] static uint64_t get_current_ms() { using namespace std::chrono; return static_cast(duration_cast(steady_clock::now().time_since_epoch()).count()); } public: Base_Statistics() : start_time(get_current_ms()) {} [[nodiscard]] virtual JSON to_json() const = 0; virtual ~Base_Statistics() = default; [[nodiscard]] unsigned int get_start_time() const { return static_cast(start_time); } }; class Speed_Statistics : public Base_Statistics { public: double cur_total{}; double instant_speed{}; double average_speed{}; size_t times{}; bool init{}; Speed_Statistics() { clear(); } Speed_Statistics& operator+=(const Speed_Statistics& rhs) { cur_total += rhs.cur_total; instant_speed += rhs.instant_speed; average_speed += rhs.average_speed; times += rhs.times; init = init || rhs.init; return *this; } void clear() { cur_total = 0.0; instant_speed = 0.0; average_speed = 0.0; times = 0; init = false; start_time = get_current_ms(); } [[nodiscard]] JSON to_json() const override { JSON ret = JSON::object(); Ret_J(instant_speed) Ret_J(average_speed) Ret_J(times) return ret; } [[nodiscard]] std::string to_string() const { return VAR_STR_4(instant_speed, average_speed, cur_total, times); } void update(unsigned int len) { constexpr uint64_t period_ms = 100; constexpr double average_times = 10.0; const uint64_t now = get_current_ms(); cur_total += static_cast(len); ++times; const uint64_t true_period_ms = now - start_time; if (true_period_ms <= period_ms) { return; } instant_speed = cur_total / static_cast(true_period_ms) * 1000.0; if (init) { average_speed = average_speed * (average_times - 1.0) / average_times + instant_speed / average_times; } else { average_speed = instant_speed; init = true; } start_time = now; cur_total = 0.0; } }; class Value_Statistics : public Base_Statistics { public: double max{}; double min{}; double average{}; double instant{}; size_t times{}; bool init{}; Value_Statistics() { clear(); } void clear() { max = 0.0; min = 0.0; average = 0.0; instant = 0.0; times = 0; init = false; } [[nodiscard]] JSON to_json() const override { JSON ret = JSON::object(); Ret_J(max) Ret_J(min) Ret_J(average) Ret_J(instant) return ret; } [[nodiscard]] std::string to_string() const { return VAR_STR_5(min, max, average, instant, times); } void update(double value) { constexpr double average_times = 10.0; instant = value; if (!init) { max = value; min = value; average = value; init = true; } else { max = std::max(max, value); min = std::min(min, value); average = average * (average_times - 1.0) / average_times + instant / average_times; } ++times; } }; class Probability_Statistics : public Base_Statistics { public: unsigned short instant{}; unsigned short average{}; unsigned int count{}; unsigned int total{}; unsigned int total_max{}; Probability_Statistics() { clear(); } void clear() { instant = 0; average = 0; count = 0; total = 0; total_max = 10; } [[nodiscard]] JSON to_json() const override { JSON ret = JSON::object(); Ret_J(instant) Ret_J(average) Ret_J(count) Ret_J(total) Ret_J(total_max) return ret; } void update(bool value) { value ? update(1) : update(-1); } void update(int count_change) { if (count_change == 0) { count_change = -1; } if (count_change > 0) { const auto change = static_cast(count_change); count += change; total += change; } else { total += static_cast(-static_cast(count_change)); } if (total < total_max) { return; } instant = static_cast((count * 1000U) / total); if (average == 0) { average = instant; } else { average = static_cast(((static_cast(average) << 3U) - average + instant) >> 3U); } count = 0; total = 0; } }; }