Files
yourpart3/src/valuerecalculationworker.cpp
Torsten Schulz 1451225978 stabilized app
2026-01-14 14:37:21 +01:00

169 lines
7.5 KiB
C++

#include "valuerecalculationworker.h"
ValueRecalculationWorker::ValueRecalculationWorker(ConnectionPool &pool, MessageBroker &broker)
: Worker(pool, broker, "ValueRecalculationWorker"),
activities{
{"productKnowledge", Activity(std::chrono::system_clock::from_time_t(0),
[this]() { calculateProductKnowledge(); },
std::chrono::hours(0))}, // 00:00 Uhr
{"regionalSellPrice", Activity(std::chrono::system_clock::from_time_t(0),
[this]() { calculateRegionalSellPrice(); },
std::chrono::hours(12) + std::chrono::minutes(0))} // 12:00 Uhr
}
{
}
ValueRecalculationWorker::~ValueRecalculationWorker() {
}
void ValueRecalculationWorker::run() {
while (runningWorker) {
setCurrentStep("Check if activity has to run");
auto now = std::chrono::system_clock::now();
for (auto &[key, activity] : activities) {
if (shouldRunToday(activity)) {
activity.lastRun = now;
activity.callMethod();
}
}
setCurrentStep("CalculateMarriages");
calculateMarriages();
calculateStudying();
setCurrentStep("Sleep for 60 seconds");
for (int i = 0; i < 60 && runningWorker; ++i) {
std::this_thread::sleep_for(std::chrono::seconds(1));
setCurrentStep("signalActivity()");
signalActivity();
}
setCurrentStep("Loop done");
}
}
bool ValueRecalculationWorker::shouldRunToday(const Activity& activity) {
auto now = std::chrono::system_clock::now();
auto todayScheduledTime = getNextScheduledTime(activity.scheduledTime);
return now >= todayScheduledTime && activity.lastRun < todayScheduledTime;
}
std::chrono::system_clock::time_point ValueRecalculationWorker::getNextScheduledTime(std::chrono::system_clock::duration scheduledDuration) {
auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::tm now_tm = *std::localtime(&now_c);
now_tm.tm_hour = std::chrono::duration_cast<std::chrono::hours>(scheduledDuration).count();
now_tm.tm_min = std::chrono::duration_cast<std::chrono::minutes>(scheduledDuration).count() % 60;
now_tm.tm_sec = 0;
return std::chrono::system_clock::from_time_t(std::mktime(&now_tm));
}
void ValueRecalculationWorker::calculateProductKnowledge() {
ConnectionGuard connGuard(pool);
auto &db = connGuard.get();
db.prepare("QUERY_UPDATE_PRODUCT_KNOWLEDGE_USER", QUERY_UPDATE_PRODUCT_KNOWLEDGE_USER);
db.execute("QUERY_UPDATE_PRODUCT_KNOWLEDGE_USER");
db.prepare("QUERY_GET_PRODUCERS_LAST_DAY", QUERY_GET_PRODUCERS_LAST_DAY);
const auto &usersToInform = db.execute("QUERY_GET_PRODUCERS_LAST_DAY");
const nlohmann::json message = {
{ "event", "price_update" }
};
for (const auto &user: usersToInform) {
const auto userId = std::stoi(user.at("producer_id"));
sendMessageToFalukantUsers(userId, message);
}
db.prepare("QUERY_DELETE_OLD_PRODUCTIONS", QUERY_DELETE_OLD_PRODUCTIONS);
db.execute("QUERY_DELETE_OLD_PRODUCTIONS");
}
void ValueRecalculationWorker::calculateRegionalSellPrice() {
ConnectionGuard connGuard(pool);
auto &db = connGuard.get();
db.prepare("QUERY_UPDATE_REGION_SELL_PRICE", QUERY_UPDATE_REGION_SELL_PRICE);
db.execute("QUERY_UPDATE_REGION_SELL_PRICE");
db.prepare("QUERY_GET_SELL_REGIONS", QUERY_GET_SELL_REGIONS);
const auto &regionsWithSells = db.execute("QUERY_GET_SELL_REGIONS");
const nlohmann::json message = {
{ "event", "price_update" }
};
for (const auto &region: regionsWithSells) {
const auto regionId = std::stoi(region.at("region_id"));
sendMessageToRegionUsers(regionId, message);
}
db.prepare("QUERY_DELETE_REGION_SELL_PRICE", QUERY_DELETE_REGION_SELL_PRICE);
db.execute("QUERY_DELETE_REGION_SELL_PRICE");
}
void ValueRecalculationWorker::calculateMarriages() {
ConnectionGuard connGuard(pool);
auto &db = connGuard.get();
db.prepare("QUERY_SET_MARRIAGES_BY_PARTY", QUERY_SET_MARRIAGES_BY_PARTY);
const auto &usersFromUpdatedRelationships = db.execute("QUERY_SET_MARRIAGES_BY_PARTY");
const nlohmann::json message = {
{ "event", "relationship_changed" }
};
for (const auto &userFromUpdatedRelationships: usersFromUpdatedRelationships) {
if (userFromUpdatedRelationships.at("character1_user") != "") {
const auto user1Id = std::stoi(userFromUpdatedRelationships.at("character1_user"));
sendMessageToRegionUsers(user1Id, message);
}
if (userFromUpdatedRelationships.at("character2_user") != "") {
const auto user2Id = std::stoi(userFromUpdatedRelationships.at("character2_user"));
sendMessageToRegionUsers(user2Id, message);
}
}
}
void ValueRecalculationWorker::calculateStudying() {
ConnectionGuard connGuard(pool);
auto &db = connGuard.get();
db.prepare("QUERY_GET_STUDYINGS_TO_EXECUTE", QUERY_GET_STUDYINGS_TO_EXECUTE);
db.prepare("QUERY_SET_LEARNING_DONE", QUERY_SET_LEARNING_DONE);
const auto studies = db.execute("QUERY_GET_STUDYINGS_TO_EXECUTE");
for (const auto &study: studies) {
if (study.at("tr") == "self") {
calculateStudyingSelf(study);
} else if (study.at("tr") == "children" || study.at("tr") == "director") {
caclulateStudyingForAssociatedCharacter(study);
}
db.execute("QUERY_SET_LEARNING_DONE", {study.at("id")});
}
}
void ValueRecalculationWorker::calculateStudyingSelf(Database::FieldMap entry) {
ConnectionGuard connGuard(pool);
auto &db = connGuard.get();
db.prepare("QUERY_GET_OWN_CHARACTER_ID", QUERY_GET_OWN_CHARACTER_ID);
const auto ownCharacterIdResult = db.execute("QUERY_GET_OWN_CHARACTER_ID", { entry.at("associated_falukant_user_id") });
if (ownCharacterIdResult.size() > 0) {
auto characterId = std::stoi(ownCharacterIdResult.at(0).at("id"));
auto learnAll = entry.at("learn_all_products") == "t" || entry.at("product_id") == "";
int productId = learnAll ? 0 : std::stoi(entry.at("product_id"));
calculateStudyingCharacter(characterId, learnAll, productId, std::stoi(entry.at("learning_recipient_id")));
}
}
void ValueRecalculationWorker::caclulateStudyingForAssociatedCharacter(Database::FieldMap entry) {
auto characterId = std::stoi(entry.at("associated_learning_character_id"));
auto learnAll = entry.at("learn_all_products") == "t" || entry.at("product_id") == "";
int productId = learnAll ? 0 : std::stoi(entry.at("product_id"));
calculateStudyingCharacter(characterId, learnAll, productId, std::stoi(entry.at("learning_recipient_id")));
}
void ValueRecalculationWorker::calculateStudyingCharacter(int characterId, bool all, int productId, int falukantUserId) {
ConnectionGuard connGuard(pool);
auto &db = connGuard.get();
if (all) {
db.prepare("QUERY_INCREASE_ALL_PRODUCTS_KNOWLEDGE", QUERY_INCREASE_ALL_PRODUCTS_KNOWLEDGE);
db.execute("QUERY_INCREASE_ALL_PRODUCTS_KNOWLEDGE", { "1", std::to_string(characterId) });
} else {
db.prepare("QUERY_INCREASE_ONE_PRODUCT_KNOWLEDGE", QUERY_INCREASE_ONE_PRODUCT_KNOWLEDGE);
db.execute("QUERY_INCREASE_ONE_PRODUCT_KNOWLEDGE", { "5", std::to_string(characterId), std::to_string(productId) });
}
const nlohmann::json message = {
{ "event", "knowledge_updated" }
};
sendMessageToFalukantUsers(falukantUserId, message);
}