#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(scheduledDuration).count(); now_tm.tm_min = std::chrono::duration_cast(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 ®ionsWithSells = db.execute("QUERY_GET_SELL_REGIONS"); const nlohmann::json message = { { "event", "price_update" } }; for (const auto ®ion: 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); }