// File: politics_worker.cpp #include "politics_worker.h" #include #include PoliticsWorker::PoliticsWorker(ConnectionPool &pool, MessageBroker &broker) : Worker(pool, broker, "PoliticsWorker") { } PoliticsWorker::~PoliticsWorker() { } void PoliticsWorker::run() { auto lastExecutionDate = std::chrono::system_clock::time_point{}; while (runningWorker) { signalActivity(); auto now = std::chrono::system_clock::now(); auto todayFloor = std::chrono::floor(now); auto targetTime = todayFloor + std::chrono::hours(3); // 03:00 Uhr if (now >= targetTime && lastExecutionDate < todayFloor) { signalActivity(); performDailyPoliticsTask(); lastExecutionDate = todayFloor; } for (int i = 0; i < 5 && runningWorker.load(); ++i) { signalActivity(); std::this_thread::sleep_for(std::chrono::seconds(1)); } } } void PoliticsWorker::performDailyPoliticsTask() { try { // … (Schritte für Notifications und evaluatePoliticalPositions) … // 3) Elections anlegen und **je 2 × posts_to_fill** Kandidaten hinzufügen { setCurrentStep("Schedule Elections and Insert Candidates"); // 3a) Neue Elections erzeugen (liefert jetzt auch posts_to_fill) auto elections = scheduleElections(); if (!elections.empty()) { for (auto const & tpl : elections) { int electionId = std::get<0>(tpl); int regionId = std::get<1>(tpl); int postsToFill = std::get<2>(tpl); ConnectionGuard connGuard(pool); auto &db = connGuard.get(); db.prepare("INSERT_CANDIDATES", QUERY_INSERT_CANDIDATES); // $1 = electionId, $2 = regionId, $3 = postsToFill db.execute("INSERT_CANDIDATES", { std::to_string(electionId), std::to_string(regionId), std::to_string(postsToFill) }); } } } // … nach scheduleElections() & Kandidaten … { setCurrentStep("Process Elections After 3 Days"); auto newOffices = processElections(); for (auto const &tup : newOffices) { notifyOfficeFilled({tup}); } } } catch (std::exception const & e) { std::cerr << "[PoliticsWorker] Fehler bei performDailyPoliticsTask: " << e.what() << "\n"; } } void PoliticsWorker::evaluatePoliticalPositions( std::unordered_map& requiredPerRegion, std::unordered_map& occupiedPerRegion ) { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); signalActivity(); db.prepare("COUNT_OFFICES_PER_REGION", QUERY_COUNT_OFFICES_PER_REGION); signalActivity(); const auto result = db.execute("COUNT_OFFICES_PER_REGION"); signalActivity(); for (const auto &row : result) { int regionId = std::stoi(row.at("region_id")); int reqCount = std::stoi(row.at("required_count")); int occCount = std::stoi(row.at("occupied_count")); requiredPerRegion[regionId] = reqCount; occupiedPerRegion[regionId] = occCount; signalActivity(); } } // politics_worker.cpp (Auszug) std::vector> PoliticsWorker::scheduleElections() { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); signalActivity(); db.prepare("SELECT_NEEDED_ELECTIONS", QUERY_SELECT_NEEDED_ELECTIONS); signalActivity(); auto result = db.execute("SELECT_NEEDED_ELECTIONS"); signalActivity(); std::vector> created; created.reserve(result.size()); for (auto const & row : result) { int electionId = std::stoi(row.at("election_id")); int regionId = std::stoi(row.at("region_id")); int postsToFill = std::stoi(row.at("posts_to_fill")); created.emplace_back(electionId, regionId, postsToFill); signalActivity(); } return created; } std::vector> PoliticsWorker::processExpiredOfficesAndFill() { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); signalActivity(); db.prepare("PROCESS_EXPIRED_AND_FILL", QUERY_PROCESS_EXPIRED_AND_FILL); signalActivity(); const auto result = db.execute("PROCESS_EXPIRED_AND_FILL"); signalActivity(); std::vector> created; for (const auto &row : result) { int officeId = std::stoi(row.at("office_id")); int officeTypeId = std::stoi(row.at("office_type_id")); int characterId = std::stoi(row.at("character_id")); int regionId = std::stoi(row.at("region_id")); created.emplace_back(officeId, officeTypeId, characterId, regionId); signalActivity(); } return created; } std::vector PoliticsWorker::getUserIdsInCitiesOfRegions(const std::vector& regionIds) { if (regionIds.empty()) { return {}; } ConnectionGuard connGuard(pool); auto &db = connGuard.get(); std::vector userIds; for (int rid : regionIds) { signalActivity(); db.prepare("GET_USERS_IN_CITIES", QUERY_USERS_IN_CITIES_OF_REGIONS); signalActivity(); const auto rows = db.execute("GET_USERS_IN_CITIES", { std::to_string(rid) }); signalActivity(); for (const auto &row : rows) { int uid = std::stoi(row.at("user_id")); userIds.push_back(uid); signalActivity(); } } return userIds; } void PoliticsWorker::notifyOfficeExpirations() { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); signalActivity(); db.prepare("NOTIFY_OFFICE_EXPIRATION", QUERY_NOTIFY_OFFICE_EXPIRATION); signalActivity(); db.execute("NOTIFY_OFFICE_EXPIRATION"); signalActivity(); // Sende falukantUpdateStatus an alle betroffenen Benutzer db.prepare("GET_USERS_WITH_EXPIRING_OFFICES", QUERY_GET_USERS_WITH_EXPIRING_OFFICES); const auto affectedUsers = db.execute("GET_USERS_WITH_EXPIRING_OFFICES"); for (const auto &user : affectedUsers) { int userId = std::stoi(user.at("user_id")); nlohmann::json message = { { "event", "falukantUpdateStatus" } }; sendMessageToFalukantUsers(userId, message); } } void PoliticsWorker::notifyElectionCreated(const std::vector>& elections) { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); db.prepare("NOTIFY_ELECTION_CREATED", QUERY_NOTIFY_ELECTION_CREATED); for (const auto &pr : elections) { signalActivity(); db.execute("NOTIFY_ELECTION_CREATED", { std::to_string(pr.first) }); signalActivity(); } // Sende falukantUpdateStatus an alle betroffenen Benutzer db.prepare("GET_USERS_IN_REGIONS_WITH_ELECTIONS", QUERY_GET_USERS_IN_REGIONS_WITH_ELECTIONS); const auto affectedUsers = db.execute("GET_USERS_IN_REGIONS_WITH_ELECTIONS"); for (const auto &user : affectedUsers) { int userId = std::stoi(user.at("user_id")); nlohmann::json message = { { "event", "falukantUpdateStatus" } }; sendMessageToFalukantUsers(userId, message); } } void PoliticsWorker::notifyOfficeFilled(const std::vector>& newOffices) { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); db.prepare("NOTIFY_OFFICE_FILLED", QUERY_NOTIFY_OFFICE_FILLED); for (const auto &tup : newOffices) { int characterId = std::get<2>(tup); signalActivity(); db.execute("NOTIFY_OFFICE_FILLED", { std::to_string(characterId) }); signalActivity(); } // Sende falukantUpdateStatus an alle betroffenen Benutzer db.prepare("GET_USERS_WITH_FILLED_OFFICES", QUERY_GET_USERS_WITH_FILLED_OFFICES); const auto affectedUsers = db.execute("GET_USERS_WITH_FILLED_OFFICES"); for (const auto &user : affectedUsers) { int userId = std::stoi(user.at("user_id")); nlohmann::json message = { { "event", "falukantUpdateStatus" } }; sendMessageToFalukantUsers(userId, message); } } std::vector> PoliticsWorker::processElections() { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); db.prepare("PROCESS_ELECTIONS", QUERY_PROCESS_ELECTIONS); auto result = db.execute("PROCESS_ELECTIONS", {}); std::vector> created; for (auto const &row : result) { int officeId = std::stoi(row.at("office_id")); int officeTypeId = std::stoi(row.at("office_type_id")); int characterId = std::stoi(row.at("character_id")); int regionId = std::stoi(row.at("region_id")); created.emplace_back(officeId, officeTypeId, characterId, regionId); } return created; }