252 lines
8.9 KiB
C++
252 lines
8.9 KiB
C++
// File: politics_worker.cpp
|
||
|
||
#include "politics_worker.h"
|
||
#include <iostream>
|
||
#include <chrono>
|
||
|
||
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<std::chrono::days>(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<int,int>& requiredPerRegion,
|
||
std::unordered_map<int,int>& 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<std::tuple<int,int,int>> 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<std::tuple<int,int,int>> 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<std::tuple<int,int,int,int>> 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<std::tuple<int,int,int,int>> 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<int> PoliticsWorker::getUserIdsInCitiesOfRegions(const std::vector<int>& regionIds) {
|
||
if (regionIds.empty()) {
|
||
return {};
|
||
}
|
||
|
||
ConnectionGuard connGuard(pool);
|
||
auto &db = connGuard.get();
|
||
|
||
std::vector<int> 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<std::pair<int,int>>& 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<std::tuple<int,int,int,int>>& 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<std::tuple<int,int,int,int>> PoliticsWorker::processElections() {
|
||
ConnectionGuard connGuard(pool);
|
||
auto &db = connGuard.get();
|
||
db.prepare("PROCESS_ELECTIONS", QUERY_PROCESS_ELECTIONS);
|
||
auto result = db.execute("PROCESS_ELECTIONS", {});
|
||
std::vector<std::tuple<int,int,int,int>> 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;
|
||
}
|