#ifndef PSC_GLOBAL_INCLUDE_H #define PSC_GLOBAL_INCLUDE_H #include #include #include #include #include #include #include #include #include #include #include #include #include "Core/Statistics/Statistics.h" #include "Core/socket/ByteOrder.h" #include "SSR/export.h" class Global; class Invalid_Http_Param final : public std::runtime_error { public: using std::runtime_error::runtime_error; }; [[noreturn]] inline void throw_invalid_http_param(const char* detail) { throw Invalid_Http_Param(detail); } #define CHECK_JSON_PARAM \ auto o_params = Psc::try_parse_json(req->body().data()); \ if (!o_params.has_value()) { \ throw_invalid_http_param("request body is not valid JSON"); \ } \ auto& params = o_params.value(); \ auto that_json = ¶ms; #define HTTP_REQUIRE_VALUE(NAME, EXPRESSION) \ auto o_http_##NAME = (EXPRESSION); \ if (!o_http_##NAME.has_value()) { \ throw_invalid_http_param(#NAME); \ } \ auto NAME = std::move(o_http_##NAME).value(); #define HTTP_REQUIRE_PTR(NAME, EXPRESSION) \ auto NAME = (EXPRESSION); \ if ((NAME) == nullptr) { \ throw_invalid_http_param(#NAME); \ } #define HTTP_REQUIRE_TRUE(EXPRESSION, DETAIL) \ if (!(EXPRESSION)) { \ throw_invalid_http_param(DETAIL); \ } template class Ordered_List { public: void swap(size_t i, size_t j) { std::lock_guard g(mtx); if (i >= _list.size() || j >= _list.size()) return; std::swap(_list[i], _list[j]); } void push_back(Value_Type value) { std::lock_guard g(mtx); _list.push_back(value); // 添加默认值 } void insert(int i, Value_Type value) { std::lock_guard g(mtx); _list.insert(_list.begin() + i, value); } Value_Type get(size_t i) { return _list[i]; } void remove(size_t i) { std::lock_guard g(mtx); if (i >= _list.size()) return; _list.erase(_list.begin() + i); } std::vector list() { std::lock_guard g(mtx); return this->_list; } void clear() { list().clear(); } protected: std::mutex mtx; std::vector _list; }; template class Ordered_Map { public: std::optional get(Key_Type key) { std::lock_guard g(mtx); auto it = _map.find(key); if (it != _map.end()) { return it->second; } return std::nullopt; } bool swap(size_t i, size_t j) { std::lock_guard g(mtx); if (i >= _list.size() || j >= _list.size()) return false; std::swap(_list[i], _list[j]); // 更新 map 中的 value,假设你可以从 Value 中获取 key Key_Type key_i = _list[i]->key; Key_Type key_j = _list[j]->key; _map[key_i] = _list[i]; _map[key_j] = _list[j]; return true; } void push_back(Value_Type value) { std::lock_guard g(mtx); _list.push_back(value); // 添加默认值 _map[value->key] = value; // 插入到 map } bool insert(int i, Value_Type value) { std::lock_guard g(mtx); if (i < 0 || static_cast(i) > _list.size()) return false; _list.insert(_list.begin() + i, value); _map[value->key] = value; return true; } Value_Type get(size_t i) { return _list[i]; } std::optional try_get(size_t i) { std::lock_guard g(mtx); if (i >= _list.size()) return std::nullopt; return _list[i]; } bool remove(size_t i) { std::lock_guard g(mtx); if (i >= _list.size()) return false; Key_Type& key = _list[i]->key; _map.erase(key); _list.erase(_list.begin() + i); return true; } std::vector list() { std::lock_guard g(mtx); return this->_list; } // std::map map(){ // std::lock_guard g(mtx); // return this->_map; // } void clear() { list().clear(); _map.clear(); } protected: std::mutex mtx; std::vector _list; std::map _map; }; class Mode_AC_Statistic_Data { public: Psc::JSON to_json() { std::lock_guard g(mtx); Psc::JSON ret = Psc::JSON::object(); Ret_J(pre_second_num); Ret_J(total_num); Ret_J(length_error_num); // Ret_J(speed); return ret; } void add() { std::lock_guard g(mtx); add_inter(); // speed.update(1); } void add_length_error() { std::lock_guard g(mtx); add_inter(); length_error_num++; } protected: std::atomic length_error_num{}; void add_inter() { total_num++; auto cur_time = std::time(nullptr); if (cur_time != utc) { utc = cur_time; pre_second_num = 0; } pre_second_num++; } std::mutex mtx; size_t pre_second_num{}; size_t total_num{}; time_t utc{}; // Psc::Speed_Statistics speed; }; class Statistic_Data { public: time_t utc{}; size_t pre_second_num{}; size_t total_num{}; [[nodiscard]] Psc::JSON to_json() const { Psc::JSON ret = Psc::JSON::object(); Ret_J(pre_second_num); Ret_J(total_num); return ret; } Statistic_Data() = default; }; class DF_Statistic_Data { public: time_t utc{}; size_t pre_second_num{}; size_t total_num{}; size_t crc_error_num{}; Psc::JSON to_json() { Psc::JSON ret = Psc::JSON::object(); Ret_J(pre_second_num); Ret_J(total_num); Ret_J(crc_error_num); // Ret_J(speed); std::string t = "null"; if (total_num != 0) { t = std::to_string(static_cast(crc_error_num) / static_cast(total_num)) + "%"; } ret.append({"crc误码率", t}); for (auto& cur : statistic_map) { ret.append({cur.first, cur.second.to_json()}); } return ret; } void add() { add_inter(); } void add_crc_error() { crc_error_num++; } void add_sub_part(std::string_view key) { add_sub_part_inter(key); } // Psc::Speed_Statistics speed; protected: void add_inter() { total_num++; auto cur_time = std::time(nullptr); if (cur_time != utc) { utc = cur_time; pre_second_num = 0; } pre_second_num++; // speed.update(1); } void add_sub_part_inter(std::string_view key) { auto t = get_create_statistic_data(key); t->total_num++; auto cur_time = std::time(nullptr); if (cur_time != t->utc) { t->utc = cur_time; t->pre_second_num = 0; } t->pre_second_num++; } Statistic_Data* get_create_statistic_data(std::string_view key) { Statistic_Data* t; auto key_string = std::string(key); auto iter = statistic_map.find(key_string); if (iter == statistic_map.end()) { Statistic_Data cur{}; statistic_map.insert(std::make_pair(key_string, cur)); } t = &statistic_map[key_string]; return t; } std::map statistic_map; }; class CPR_Percentage_Statistic_Data { public: void add(SSR::CPR_Type cpr_type, SSR::CPR_Ret_Type result_type) { switch (result_type) { case SSR::CPR_Ret_Type::Speed_Error: case SSR::CPR_Ret_Type::Parse_OK: case SSR::CPR_Ret_Type::Inter_Error: case SSR::CPR_Ret_Type::Time_Space_Too_Long: break; case SSR::CPR_Ret_Type::Lack_Other_Msg: case SSR::CPR_Ret_Type::Lack_Old_Pos: case SSR::CPR_Ret_Type::Base: return; } auto& statistic = statistic_map[cpr_type]; ++statistic.total_num; ++statistic.result_num[result_type]; } Psc::JSON to_json() const { Psc::JSON result = Psc::JSON::object(); for (const auto& [cpr_type, statistic] : statistic_map) { Psc::JSON type_result = Psc::JSON::object(); type_result.append({"总计数", statistic.total_num}); for (auto result_type : statistic_types) { size_t num = 0; auto iter = statistic.result_num.find(result_type); if (iter != statistic.result_num.end()) { num = iter->second; } double rate = static_cast(num) / static_cast(statistic.total_num) * 100.0; type_result.append({Psc::to_string(result_type), std::format("{} {:.2f}%", num, rate)}); } result.append({Psc::to_string(cpr_type), type_result}); } return result; } protected: struct Statistic_Data { size_t total_num{}; std::map result_num; }; inline static constexpr std::array statistic_types{ SSR::CPR_Ret_Type::Speed_Error, SSR::CPR_Ret_Type::Parse_OK, SSR::CPR_Ret_Type::Inter_Error, SSR::CPR_Ret_Type::Time_Space_Too_Long, SSR::CPR_Ret_Type::Out_of_Maximum_Detection_Range}; std::map statistic_map; }; class Mode_S_Statistic_Data { public: Psc::JSON to_json() { size_t total_num = get_total_num(); size_t crc_error_num = get_crc_error_num(); Psc::JSON ret = Psc::JSON::object(); ret.append({"每秒数量", get_total_pre_second_num()}); Ret_J(length_error_num); Ret_J(total_num); std::string t = "null"; if (total_num != 0) { t = std::format("{}%", static_cast(crc_error_num) / static_cast(total_num)); } Ret_J(crc_error_num); ret.append({"crc_error_rate", t}); Psc::JSON df_sub_type = Psc::JSON::object(); for (auto& cur : DF_Statistic_Data_map) { df_sub_type.append({Psc::to_string(cur.first) + " [" + std::to_string(static_cast(cur.first)) + "]", cur.second.to_json()}); } ret.append({"DF子类型", df_sub_type}); ret.append({"CPR统计信息", cpr_statistic_data.to_json()}); return ret; } void add_length_error(std::string_view key) { ++length_error_num; } void add_cpr_error(SSR::CPR_Type cpr_type, SSR::CPR_Ret_Type result_type) { cpr_statistic_data.add(cpr_type, result_type); } DF_Statistic_Data* get_create_df_statistic_data(const SSR::Downlink_Format& key) { DF_Statistic_Data* t; auto iter = DF_Statistic_Data_map.find(key); if (iter == DF_Statistic_Data_map.end()) { DF_Statistic_Data cur{}; DF_Statistic_Data_map.insert(std::make_pair(key, cur)); } t = &DF_Statistic_Data_map[key]; return t; } size_t get_total_pre_second_num() { size_t ret = 0; for (auto& cur : DF_Statistic_Data_map) { ret += cur.second.pre_second_num; } return ret; } size_t get_total_num() { size_t ret = 0; for (auto& cur : DF_Statistic_Data_map) { ret += cur.second.total_num; } return ret; } size_t get_crc_error_num() { size_t ret = 0; for (auto& cur : DF_Statistic_Data_map) { ret += cur.second.crc_error_num; } return ret; } protected: std::atomic length_error_num{}; std::map DF_Statistic_Data_map; CPR_Percentage_Statistic_Data cpr_statistic_data; }; template class Immutable : public T {}; #endif