mirror of
https://github.com/yawaflua/tzeva-adom.git
synced 2025-12-09 20:09:26 +02:00
Add localization, add plays sound when alert starting and pictures
This commit is contained in:
@@ -10,14 +10,37 @@ find_package(CURL REQUIRED)
|
|||||||
find_package(nlohmann_json 3.2.0 REQUIRED)
|
find_package(nlohmann_json 3.2.0 REQUIRED)
|
||||||
|
|
||||||
# Определяем исполняемый файл
|
# Определяем исполняемый файл
|
||||||
add_executable(tzeva_adom main.cpp)
|
add_executable(tzeva_adom main.cpp
|
||||||
|
models/AlertResponse.cpp
|
||||||
|
utils/image_downloader.cpp
|
||||||
|
utils/audio_play.cpp
|
||||||
|
locale/localization_get.cpp
|
||||||
|
utils/localization_manager.h
|
||||||
|
utils/localization_manager.h
|
||||||
|
)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(GLIB REQUIRED glib-2.0)
|
pkg_check_modules(GLIB REQUIRED glib-2.0)
|
||||||
pkg_check_modules(NOTIFY REQUIRED libnotify)
|
pkg_check_modules(NOTIFY REQUIRED libnotify)
|
||||||
|
pkg_check_modules(SDL REQUIRED libnotify)
|
||||||
find_package(fmt REQUIRED)
|
find_package(fmt REQUIRED)
|
||||||
|
|
||||||
|
include_directories(lang)
|
||||||
include_directories(${GLIB_INCLUDE_DIRS})
|
include_directories(${GLIB_INCLUDE_DIRS})
|
||||||
include_directories(${NOTIFY_INCLUDE_DIRS})
|
include_directories(${NOTIFY_INCLUDE_DIRS})
|
||||||
include_directories(${CURL_INCLUDE_DIRS})
|
include_directories(${CURL_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
find_package(SDL2_mixer REQUIRED)
|
||||||
|
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_MIXER_INCLUDE_DIRS})
|
||||||
|
find_package(Boost REQUIRED COMPONENTS filesystem)
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
|
||||||
# Линкуем библиотеки
|
# Линкуем библиотеки
|
||||||
target_link_libraries(tzeva_adom PRIVATE CURL::libcurl nlohmann_json::nlohmann_json ${GLIB_LIBRARIES} fmt::fmt ${NOTIFY_LIBRARIES} ${CURL_LIBRARIES})
|
target_include_directories(tzeva_adom PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} "lang/")
|
||||||
|
target_link_libraries(tzeva_adom PRIVATE SDL2 SDL2_mixer ${Boost_LIBRARIES} CURL::libcurl nlohmann_json::nlohmann_json ${GLIB_LIBRARIES} fmt::fmt ${NOTIFY_LIBRARIES} ${CURL_LIBRARIES})
|
||||||
|
|
||||||
|
add_custom_command(TARGET tzeva_adom POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_SOURCE_DIR}/lang $<TARGET_FILE_DIR:tzeva_adom>/lang
|
||||||
|
)
|
||||||
19
lang/en.json
Normal file
19
lang/en.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"threat_0": "Red alert",
|
||||||
|
"threat_1": "Hazardous Materials Incident",
|
||||||
|
"threat_2": "Fear of Terrorists infiltration",
|
||||||
|
"threat_3": "Earthquake",
|
||||||
|
"threat_4": "Fear of a tsunami",
|
||||||
|
"threat_5": "Hostile aircraft intrusion",
|
||||||
|
"threat_6": "Fear of a Radiological incident",
|
||||||
|
"threat_7": "Non-conventional missile",
|
||||||
|
"threat_8": "Alert",
|
||||||
|
"threat_9": "Home Front Command Drill",
|
||||||
|
"default": "Unnamed",
|
||||||
|
"drill": "Drill: ",
|
||||||
|
"true": "yes",
|
||||||
|
"false": "no",
|
||||||
|
"threat": "Threat: ",
|
||||||
|
"cities": "Cities: "
|
||||||
|
|
||||||
|
}
|
||||||
18
lang/he.json
Normal file
18
lang/he.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"threat_0": "צבע אדום",
|
||||||
|
"threat_1": "אירוע חומרים מסוכנים",
|
||||||
|
"threat_2": "חשש לחדירת מחבלים",
|
||||||
|
"threat_3": "רעידת אדמה",
|
||||||
|
"threat_4": "חשש לצונאמי",
|
||||||
|
"threat_5": "חדירת כלי טיס עוין",
|
||||||
|
"threat_6": "חשש לאירוע רדיולוגי",
|
||||||
|
"threat_7": "ירי בלתי קונבנציונלי",
|
||||||
|
"threat_8": "התרעה",
|
||||||
|
"threat_9": "תרגיל פיקוד העורף",
|
||||||
|
"default": "ללא שם",
|
||||||
|
"drill": "תרגיל: ",
|
||||||
|
"true": "כן",
|
||||||
|
"false": "לא",
|
||||||
|
"threat": "איום: ",
|
||||||
|
"cities": "הסדר: "
|
||||||
|
}
|
||||||
18
lang/ru.json
Normal file
18
lang/ru.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"threat_0": "Цева адом",
|
||||||
|
"threat_1": "Утечка опасных веществ",
|
||||||
|
"threat_2": "Подозрение на проникновение террористов",
|
||||||
|
"threat_3": "Землетрясение",
|
||||||
|
"threat_4": "Угроза цунами",
|
||||||
|
"threat_5": "Проникновение беспилотного самолета",
|
||||||
|
"threat_6": "Радиоактивная опасность",
|
||||||
|
"threat_7": "Неконвенциональная ракета",
|
||||||
|
"threat_8": "предупреждение",
|
||||||
|
"threat_9": "Учения Службы Тыла",
|
||||||
|
"default": "Неназвано",
|
||||||
|
"drill": "упражнения: ",
|
||||||
|
"true": "да",
|
||||||
|
"false": "нет",
|
||||||
|
"threat": "Тип: ",
|
||||||
|
"cities": "Города: "
|
||||||
|
}
|
||||||
3
locale/localization_get.cpp
Normal file
3
locale/localization_get.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
//
|
||||||
|
// Created by yawaflua on 29/10/2024.
|
||||||
|
//
|
||||||
190
main.cpp
190
main.cpp
@@ -4,16 +4,30 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <complex>
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <libnotify/notify.h>
|
#include <libnotify/notify.h>
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include "utils/audio_play.cpp"
|
||||||
|
#include "models/AlertResponse.cpp"
|
||||||
|
#include "utils/image_downloader.cpp"
|
||||||
|
#include "utils/localization_manager.h"
|
||||||
|
|
||||||
|
class AlertResponse;
|
||||||
|
|
||||||
|
tzeva_adom::LocalizationManager localization_manager;
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
int16_t lastId = 0;
|
int16_t lastId = 0;
|
||||||
json cities_n_areas_list;
|
json cities_n_areas_list;
|
||||||
bool is_cities_loaded = false;
|
bool is_cities_loaded = false;
|
||||||
|
bool is_test = false;
|
||||||
|
std::string this_path = boost::filesystem::current_path().c_str();
|
||||||
|
std::string lang = "en";
|
||||||
|
std::vector<tzeva_adom::Alert> test_alert_variable;
|
||||||
|
|
||||||
// Функция для записи данных от curl
|
// Функция для записи данных от curl
|
||||||
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
|
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
|
||||||
output->append(static_cast<char*>(contents), size * nmemb);
|
output->append(static_cast<char*>(contents), size * nmemb);
|
||||||
@@ -38,91 +52,90 @@ void process_alert(const std::string& data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spdlog::debug("Get first object from answer");
|
spdlog::debug("Get first object from answer");
|
||||||
// Извлекаем первый объект из массива
|
auto* first_alert = new tzeva_adom::AlertResponseElement(response.at(0));
|
||||||
const json& first_alert = response[0];
|
|
||||||
|
|
||||||
spdlog::debug("Answer: {}", first_alert);
|
spdlog::debug("Answer: {}", first_alert->get_id());
|
||||||
|
|
||||||
auto id = first_alert["id"].get<int>();
|
auto id = first_alert->get_id();
|
||||||
|
|
||||||
if (lastId == 0 || id == lastId) {
|
if (lastId == 0 || id == lastId) {
|
||||||
lastId = id;
|
lastId = id;
|
||||||
} else {
|
} else {
|
||||||
is_alert = !is_alert;
|
is_alert = !is_alert;
|
||||||
|
lastId = id;
|
||||||
spdlog::debug("This is alert!");
|
spdlog::debug("This is alert!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_alert) {
|
if (is_alert || is_test) {
|
||||||
auto description = first_alert["description"].is_string() ? first_alert["description"].get<std::string>() : "";
|
is_test = !is_test;
|
||||||
|
// auto description = first_alert["description"].is_string() ?"": first_alert["description"].get<std::string>() ;
|
||||||
|
std::string description = "";
|
||||||
|
const std::vector<tzeva_adom::Alert> alerts_array = is_test ? test_alert_variable : first_alert->get_alerts();
|
||||||
|
std::vector<std::string> cities;
|
||||||
|
std::vector<int> threats;
|
||||||
|
|
||||||
for (auto alerts: first_alert["alerts"]) {
|
for (auto alerts: alerts_array) {
|
||||||
auto time = alerts["time"].get<long>();
|
auto time = alerts.get_time();
|
||||||
auto cities = alerts["cities"].get<std::vector<std::string>>();
|
for (auto city: alerts.get_cities()) {
|
||||||
auto threat = alerts["threat"].get<int>();
|
cities.insert(cities.begin(), city);
|
||||||
auto isDrill = alerts["isDrill"].get<bool>();
|
}
|
||||||
|
|
||||||
spdlog::debug("Time: {}", time);
|
threats.insert(threats.begin(), alerts.get_threat());
|
||||||
spdlog::debug("Cities: {}", fmt::join(cities, ", "));
|
auto isDrill = alerts.get_is_drill();
|
||||||
|
|
||||||
spdlog::debug("Threat Level: {}", threat);
|
|
||||||
spdlog::debug("Is Drill: {}", isDrill);
|
|
||||||
|
|
||||||
|
|
||||||
is_png = threat == 0;
|
|
||||||
std::string icon_url = fmt::format("https://www.tzevaadom.co.il/static/images/threat{}.{}", std::to_string(threat), is_png ? ".png" : ".svg");
|
|
||||||
|
|
||||||
switch (threat) {
|
spdlog::debug("Time: {}", time);
|
||||||
case 0:
|
spdlog::debug("Cities: {}", fmt::join(cities, ", "));
|
||||||
type_of_threat = "Red Alert";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
type_of_threat = "Fear of Terrorists infiltration";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
type_of_threat = "Earthquakes warning";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
type_of_threat = "Tsunami warning";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
type_of_threat = "Hostile aircraft intrusion";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
type_of_threat = "Unnamed";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string localised_cities_names = "";
|
spdlog::debug("Threat Level: {}", alerts.get_threat());
|
||||||
for (auto city: cities) {
|
spdlog::debug("Is Drill: {}", isDrill);
|
||||||
localised_cities_names += fmt::format("{} ", cities_n_areas_list["cities"][city]["ru"]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
notify_init("Tzeva Adom!");
|
int threat = *std::max_element( threats.begin(), threats.end() );
|
||||||
NotifyNotification* n = notify_notification_new (type_of_threat.c_str(),
|
std::string icon_url = boost::filesystem::current_path().c_str()+fmt::format("/threat{}.{}", std::to_string(threat), threat == 0 ? "png" : "svg");
|
||||||
fmt::format(
|
|
||||||
"Cities: {}\n"\
|
|
||||||
"Threat: {}\n"\
|
|
||||||
"Is it drill: {}",
|
|
||||||
localised_cities_names,
|
|
||||||
type_of_threat,
|
|
||||||
std::to_string(is_drill)
|
|
||||||
).c_str(),
|
|
||||||
icon_url.c_str()
|
|
||||||
);
|
|
||||||
notify_notification_set_timeout(n, 10000); // 10 seconds
|
|
||||||
|
|
||||||
if (!notify_notification_show(n, 0))
|
spdlog::debug("Threat: {}", threat);
|
||||||
{
|
spdlog::debug("Threat name: {}", localization_manager.getString(fmt::format("threat_{}", threat)));
|
||||||
std::cerr << "show has failed" << std::endl;
|
spdlog::debug("Language: {}", lang);
|
||||||
return;
|
spdlog::debug("Icon path: {}", icon_url);
|
||||||
}
|
|
||||||
|
std::string localised_cities_names = "";
|
||||||
|
for (auto city: cities) {
|
||||||
|
localised_cities_names += fmt::format("{} ", cities_n_areas_list["cities"][city][lang]);
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::debug("Init notification");
|
||||||
|
notify_init(localization_manager.getString(fmt::format("threat_{}", std::to_string(threat))).c_str());
|
||||||
|
NotifyNotification* n = notify_notification_new (localization_manager.getString(fmt::format("threat_{}", std::to_string(threat))).c_str(),
|
||||||
|
fmt::format(
|
||||||
|
"{}: {}\n"\
|
||||||
|
"{}: {}\n"\
|
||||||
|
"{}: {}",
|
||||||
|
localization_manager.getString("cities"),
|
||||||
|
localised_cities_names,
|
||||||
|
localization_manager.getString("threat"),
|
||||||
|
localization_manager.getString(fmt::format("threat_{}", std::to_string(threat))),
|
||||||
|
localization_manager.getString("drill"),
|
||||||
|
localization_manager.getString(is_drill ? "true" : "false")
|
||||||
|
).c_str(),
|
||||||
|
icon_url.c_str()
|
||||||
|
);
|
||||||
|
tzeva_adom::playAudioAsync((this_path + std::string("/bell.mp3")).c_str());
|
||||||
|
notify_notification_set_timeout(n, 10000); // 10 seconds
|
||||||
|
|
||||||
|
if (!notify_notification_show(n, 0))
|
||||||
|
{
|
||||||
|
std::cerr << "show has failed" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::error("Alert error: {}", e.what());
|
spdlog::error("Alert error: {}", e.what());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -150,7 +163,7 @@ void fetch_alerts_history(std::atomic<bool>& running) {
|
|||||||
} else {
|
} else {
|
||||||
cities_n_areas_list = json::parse(readBuffer);
|
cities_n_areas_list = json::parse(readBuffer);
|
||||||
}
|
}
|
||||||
curl_easy_cleanup(curl);
|
curl_global_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curl) {
|
if (curl) {
|
||||||
@@ -191,9 +204,35 @@ int main(int argc, char** argv) {
|
|||||||
spdlog::info("=========================================================");
|
spdlog::info("=========================================================");
|
||||||
spdlog::set_level(spdlog::level::info); // Set global log level to info by default
|
spdlog::set_level(spdlog::level::info); // Set global log level to info by default
|
||||||
|
|
||||||
|
std::string last_flag = "";
|
||||||
|
bool is_accept_values = false;
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
|
|
||||||
if (argv[i] == "-d"sv || argv[i] == "--debug")
|
if (argv[i] == "-d"sv || argv[i] == "--debug")
|
||||||
spdlog::set_level(spdlog::level::debug); // Set global log level to debug if provided --debug
|
spdlog::set_level(spdlog::level::debug); // Set global log level to debug if provided --debug
|
||||||
|
else if (argv[i] == "-t"sv || argv[i] == "--test") {
|
||||||
|
is_test = true; // Set tested variable is true
|
||||||
|
std::vector alert_to_array {tzeva_adom::Alert()};
|
||||||
|
const auto p1 = std::chrono::system_clock::now();
|
||||||
|
ulong t = std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
|
p1.time_since_epoch()).count();
|
||||||
|
std::vector<std::string> city_vectors{"אשדוד -יא,יב,טו,יז,מרינה,סיט", "אשדוד - ח,ט,י,יג,יד,טז"};
|
||||||
|
alert_to_array[0].set_cities(city_vectors);
|
||||||
|
alert_to_array[0].set_time(t);
|
||||||
|
alert_to_array[0].set_threat(0);
|
||||||
|
test_alert_variable.push_back(alert_to_array[0]);
|
||||||
|
}
|
||||||
|
else if (argv[i] == "-l"sv || argv[i] == "--lang"sv) {
|
||||||
|
is_accept_values = true;
|
||||||
|
spdlog::debug("Take lang arg");
|
||||||
|
}
|
||||||
|
else if ((last_flag == "-l"sv || last_flag == "--lang"sv) && is_accept_values == true) {
|
||||||
|
is_accept_values = false;
|
||||||
|
lang = argv[i];
|
||||||
|
spdlog::debug("Language setted to {}", lang);
|
||||||
|
|
||||||
|
}
|
||||||
else if (argv[i] == "-h"sv || argv[i] == "--help"sv) {
|
else if (argv[i] == "-h"sv || argv[i] == "--help"sv) {
|
||||||
spdlog::info(
|
spdlog::info(
|
||||||
"Tzeva-Adom PC 1.0 by yawaflua\n\n"\
|
"Tzeva-Adom PC 1.0 by yawaflua\n\n"\
|
||||||
@@ -201,9 +240,34 @@ int main(int argc, char** argv) {
|
|||||||
" -h --help: Show this message\n"\
|
" -h --help: Show this message\n"\
|
||||||
" -d --debug: Show debug messages\n"\
|
" -d --debug: Show debug messages\n"\
|
||||||
" -t --test: Create test alert end exit\n"\
|
" -t --test: Create test alert end exit\n"\
|
||||||
|
" -l --lang: Choose language: ru, en, he,"
|
||||||
"");
|
"");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
last_flag = argv[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::debug("Path: {}", boost::filesystem::current_path().c_str());
|
||||||
|
|
||||||
|
for (int i = 0; i <= 5; i++) {
|
||||||
|
if (!boost::filesystem::exists(this_path+fmt::format("/threat{}.{}", std::to_string(i), i == 0 ? "png" : "svg"))) {
|
||||||
|
tzeva_adom::download_file(
|
||||||
|
fmt::format(
|
||||||
|
"https://www.tzevaadom.co.il/static/images/threat{}.{}",
|
||||||
|
std::to_string(i), i == 0 ? "png" : "svg"),
|
||||||
|
fmt::format("threat{}.{}", std::to_string(i), i == 0 ? "png" : "svg")
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localization_manager = tzeva_adom::LocalizationManager();
|
||||||
|
localization_manager.setCurrentLanguage(lang);
|
||||||
|
//Download tzeva-adom bell sound
|
||||||
|
if (!boost::filesystem::exists(this_path+fmt::format("/bell.mp3"))) {
|
||||||
|
tzeva_adom::download_file(
|
||||||
|
"https://www.tzevaadom.co.il/static/sounds/bell.mp3",
|
||||||
|
fmt::format("bell.mp3")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Флаг для контроля остановки потока
|
// Флаг для контроля остановки потока
|
||||||
|
|||||||
124
models/AlertResponse.cpp
Normal file
124
models/AlertResponse.cpp
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// To parse this JSON data, first install
|
||||||
|
//
|
||||||
|
// Boost http://www.boost.org
|
||||||
|
// json.hpp https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// Then include this file, and then do
|
||||||
|
//
|
||||||
|
// AlertResponse data = nlohmann::json::parse(jsonString);
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <regex>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
namespace tzeva_adom {
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
|
#ifndef NLOHMANN_UNTYPED_tzeva_adom_HELPER
|
||||||
|
#define NLOHMANN_UNTYPED_tzeva_adom_HELPER
|
||||||
|
inline json get_untyped(const json& j, const char * property) {
|
||||||
|
if (j.find(property) != j.end()) {
|
||||||
|
return j.at(property).get<json>();
|
||||||
|
}
|
||||||
|
return json();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline json get_untyped(const json & j, std::string property) {
|
||||||
|
return get_untyped(j, property.data());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Alert {
|
||||||
|
public:
|
||||||
|
Alert() = default;
|
||||||
|
virtual ~Alert() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t time;
|
||||||
|
std::vector<std::string> cities;
|
||||||
|
int64_t threat;
|
||||||
|
bool is_drill;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const int64_t & get_time() const { return time; }
|
||||||
|
int64_t & get_mutable_time() { return time; }
|
||||||
|
void set_time(const int64_t & value) { this->time = value; }
|
||||||
|
|
||||||
|
const std::vector<std::string> & get_cities() const { return cities; }
|
||||||
|
std::vector<std::string> & get_mutable_cities() { return cities; }
|
||||||
|
void set_cities(const std::vector<std::string> & value) { this->cities = value; }
|
||||||
|
|
||||||
|
const int64_t & get_threat() const { return threat; }
|
||||||
|
int64_t & get_mutable_threat() { return threat; }
|
||||||
|
void set_threat(const int64_t & value) { this->threat = value; }
|
||||||
|
|
||||||
|
const bool & get_is_drill() const { return is_drill; }
|
||||||
|
bool & get_mutable_is_drill() { return is_drill; }
|
||||||
|
void set_is_drill(const bool & value) { this->is_drill = value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class AlertResponseElement {
|
||||||
|
public:
|
||||||
|
AlertResponseElement() = default;
|
||||||
|
virtual ~AlertResponseElement() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t id;
|
||||||
|
nlohmann::json description;
|
||||||
|
std::vector<Alert> alerts;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const int64_t & get_id() const { return id; }
|
||||||
|
int64_t & get_mutable_id() { return id; }
|
||||||
|
void set_id(const int64_t & value) { this->id = value; }
|
||||||
|
|
||||||
|
const nlohmann::json & get_description() const { return description; }
|
||||||
|
nlohmann::json & get_mutable_description() { return description; }
|
||||||
|
void set_description(const nlohmann::json & value) { this->description = value; }
|
||||||
|
|
||||||
|
const std::vector<Alert> & get_alerts() const { return alerts; }
|
||||||
|
std::vector<Alert> & get_mutable_alerts() { return alerts; }
|
||||||
|
void set_alerts(const std::vector<Alert> & value) { this->alerts = value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
using AlertResponse = std::vector<AlertResponseElement>;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace tzeva_adom {
|
||||||
|
void from_json(const json & j, Alert & x);
|
||||||
|
void to_json(json & j, const Alert & x);
|
||||||
|
|
||||||
|
void from_json(const json & j, AlertResponseElement & x);
|
||||||
|
void to_json(json & j, const AlertResponseElement & x);
|
||||||
|
|
||||||
|
inline void from_json(const json & j, Alert& x) {
|
||||||
|
x.set_time(j.at("time").get<int64_t>());
|
||||||
|
x.set_cities(j.at("cities").get<std::vector<std::string>>());
|
||||||
|
x.set_threat(j.at("threat").get<int64_t>());
|
||||||
|
x.set_is_drill(j.at("isDrill").get<bool>());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void to_json(json & j, const Alert & x) {
|
||||||
|
j = json::object();
|
||||||
|
j["time"] = x.get_time();
|
||||||
|
j["cities"] = x.get_cities();
|
||||||
|
j["threat"] = x.get_threat();
|
||||||
|
j["isDrill"] = x.get_is_drill();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void from_json(const json & j, AlertResponseElement& x) {
|
||||||
|
x.set_id(j.at("id").get<int64_t>());
|
||||||
|
x.set_description(get_untyped(j, "description"));
|
||||||
|
x.set_alerts(j.at("alerts").get<std::vector<Alert>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void to_json(json & j, const AlertResponseElement & x) {
|
||||||
|
j = json::object();
|
||||||
|
j["id"] = x.get_id();
|
||||||
|
j["description"] = x.get_description();
|
||||||
|
j["alerts"] = x.get_alerts();
|
||||||
|
}
|
||||||
|
}
|
||||||
45
utils/audio_play.cpp
Normal file
45
utils/audio_play.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace tzeva_adom {
|
||||||
|
inline std::pmr::string filename;
|
||||||
|
// Асинхронная функция для воспроизведения аудио
|
||||||
|
inline void playAudio() {
|
||||||
|
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||||
|
std::cerr << "Ошибка инициализации SDL: " << SDL_GetError() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
|
||||||
|
std::cerr << "Ошибка открытия аудио: " << Mix_GetError() << std::endl;
|
||||||
|
SDL_Quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mix_Music* music = Mix_LoadMUS(filename.c_str());
|
||||||
|
if (!music) {
|
||||||
|
std::cerr << "Ошибка загрузки MP3: " << Mix_GetError() << std::endl;
|
||||||
|
} else {
|
||||||
|
Mix_PlayMusic(music, 1);
|
||||||
|
|
||||||
|
// Ожидание завершения воспроизведения
|
||||||
|
while (Mix_PlayingMusic() != 0) {
|
||||||
|
SDL_Delay(100); // Пауза для проверки состояния воспроизведения
|
||||||
|
}
|
||||||
|
|
||||||
|
Mix_FreeMusic(music);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mix_CloseAudio();
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для запуска воспроизведения аудио в отдельном потоке
|
||||||
|
inline void playAudioAsync(std::pmr::string file) {
|
||||||
|
filename = file;
|
||||||
|
std::thread audioThread(playAudio);
|
||||||
|
audioThread.detach(); // Отделяем поток, чтобы он работал асинхронно
|
||||||
|
}
|
||||||
|
}
|
||||||
34
utils/image_downloader.cpp
Normal file
34
utils/image_downloader.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Created by yawaflua on 29/10/2024.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
namespace tzeva_adom {
|
||||||
|
inline size_t writeImageData(void* ptr, size_t size, size_t nmemb, FILE* stream) {
|
||||||
|
size_t written = fwrite(ptr, size, nmemb, stream);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void download_file(std::string url, std::string filename) {
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
if (curl) {
|
||||||
|
FILE* fp = fopen(filename.c_str(), "wb");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeImageData);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
|
||||||
|
CURLcode res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
std::cout << "Failed to download image: " << curl_easy_strerror(res) << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Image downloaded successfully: " << filename << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
utils/localization_manager.h
Normal file
58
utils/localization_manager.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef LOCALIZATION_MANAGER_H
|
||||||
|
#define LOCALIZATION_MANAGER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <nlohmann/json.hpp> // Подключение библиотеки JSON
|
||||||
|
|
||||||
|
namespace tzeva_adom {
|
||||||
|
class LocalizationManager {
|
||||||
|
public:
|
||||||
|
LocalizationManager() : currentLanguage("en") {}
|
||||||
|
|
||||||
|
// Загрузить языковой файл
|
||||||
|
bool loadLanguage(std::string lang) {
|
||||||
|
std::string path = std::filesystem::current_path().c_str() + fmt::format("/lang/{}.json", lang);
|
||||||
|
std::ifstream file(path);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
std::cerr << "Failed to open localization file: " << lang << std::endl;
|
||||||
|
std::cerr << "Failed to open localization file: " << path << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json json;
|
||||||
|
file >> json;
|
||||||
|
translations[lang] = json;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Установить текущий язык
|
||||||
|
void setCurrentLanguage(const std::string& langCode) {
|
||||||
|
loadLanguage(langCode);
|
||||||
|
if (translations.find(langCode) != translations.end()) {
|
||||||
|
currentLanguage = langCode;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::cerr << "Language code not loaded: " << langCode << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получить переведенную строку по ключу
|
||||||
|
std::string getString(const std::string& key) const {
|
||||||
|
if (!translations.find(currentLanguage)->second.empty()) {
|
||||||
|
auto& langData = translations.at(currentLanguage);
|
||||||
|
if (langData.contains(key)) {
|
||||||
|
return langData[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "Translation not found";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, nlohmann::json> translations;
|
||||||
|
std::string currentLanguage;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // LOCALIZATION_MANAGER_H
|
||||||
Reference in New Issue
Block a user