Files
yourpart3/src/politics_worker.cpp

252 lines
8.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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;
}