#include "director_worker.h" #include DirectorWorker::DirectorWorker(ConnectionPool &pool, MessageBroker &broker) : Worker(pool, broker, "DirectorWorker") { } DirectorWorker::~DirectorWorker() { } void DirectorWorker::run() { auto lastExecutionTime = std::chrono::steady_clock::now(); while (runningWorker) { signalActivity(); auto now = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast(now - lastExecutionTime).count(); if (elapsed >= 60) { try { performTask(); paySalary(); calculateSatisfaction(); lastExecutionTime = now; } catch (const std::exception &e) { std::cerr << "[DirectorWorker] Fehler beim Ausführen der Aufgabe: " << e.what() << std::endl; } } std::this_thread::sleep_for(std::chrono::seconds(1)); } } void DirectorWorker::performTask() { try { setCurrentStep("Get Database Connection"); ConnectionGuard connGuard(pool); auto &db = connGuard.get(); setCurrentStep("Get director actions"); db.prepare("QUERY_GET_DIRECTORS", QUERY_GET_DIRECTORS); const auto directors = db.execute("QUERY_GET_DIRECTORS"); // Use const references and string_view for better performance for (const auto &director: directors) { const auto& mayProduce = director.at("may_produce"); const auto& mayTransport = director.at("may_start_transport"); const auto& maySell = director.at("may_sell"); if (mayProduce == "t") { startProductions(director); } if (mayTransport == "t") { startTransports(director); } if (maySell == "t") { startSellings(director); } } } catch (const std::exception &e) { std::cerr << "[DirectorWorker] Fehler bei der Datenbankoperation: " << e.what() << std::endl; } } void DirectorWorker::startProductions(std::unordered_map director) { auto parseIntOrZero = [&](const std::string &s){ if (s.empty() || s == "null") return 0; try { return std::stoi(s); } catch(...) { return 0; } }; setCurrentStep("Get Database Connection - Production"); ConnectionGuard connGuard(pool); auto &db = connGuard.get(); setCurrentStep("Get to produce"); db.prepare("get_to_produce", QUERY_GET_BEST_PRODUCTION); const auto productions = db.execute("get_to_produce", { director.at("id") }); if (productions.empty()) return; const auto &production = productions.at(0); int runningProductions = parseIntOrZero(production.at("running_productions")); if (runningProductions >= 2) { return; } setCurrentStep("Add production to DB"); int availableStock = parseIntOrZero(production.at("stock_size")); int usedStock = parseIntOrZero(production.at("used_in_stock")); int freeCapacity = availableStock - usedStock - runningProductions; int certificate = parseIntOrZero(production.at("certificate")); int onePieceCost = certificate * 6; int money = parseIntOrZero(production.at("money")); int maxMoneyProduction = onePieceCost > 0 ? money / onePieceCost : 0; int toProduce = std::min(std::min(freeCapacity, maxMoneyProduction), 300); if (toProduce < 1) { return; } int falukantUserId = parseIntOrZero(production.at("falukant_user_id")); int productionCost = toProduce * onePieceCost; nlohmann::json msg1 = { { "event", "falukantUpdateStatus" } }; setCurrentStep("Update money"); changeFalukantUserMoney(falukantUserId, -productionCost, "director starts production", msg1); setCurrentStep("Insert production"); db.prepare("insert_production", QUERY_INSERT_PRODUCTION); int remaining = toProduce; while (remaining > 0) { int batch = std::min(100, remaining); db.execute("insert_production", { production.at("branch_id"), production.at("product_id"), std::to_string(batch) }); remaining -= batch; } nlohmann::json msg2 = { { "event", "production_started" }, { "branch_id", production.at("branch_id") } }; sendMessageToFalukantUsers(falukantUserId, msg2); } void DirectorWorker::startTransports(std::unordered_map) { } void DirectorWorker::startSellings(std::unordered_map director) { setCurrentStep("Get Database Connection - Production"); ConnectionGuard connGuard(pool); auto &db = connGuard.get(); setCurrentStep("Get to sell"); db.prepare("get_to_sell", QUERY_GET_INVENTORY); const auto inventory = db.execute("get_to_sell", { director.at("id") }); for (const auto &item: inventory) { const auto inventoryId = std::stoi(item.at("id")); const auto productId = std::stoi(item.at("product_id")); const auto quantity = std::stoi(item.at("quantity")); const auto quality = std::stoi(item.at("quality")); const auto maxSellPrice = std::stod(item.at("sell_cost")); auto falukantUserId = std::stoi(item.at("user_id")); const auto regionId = std::stoi(item.at("region_id")); if (quantity > 0) { const auto minPrice = maxSellPrice * 0.6; const auto pieceSellPrice = minPrice + (double)(maxSellPrice - minPrice) * (quality / 100.0); const auto sellPrice = pieceSellPrice * quantity; const nlohmann::json changeMessage = { { "productId", productId }, { "event", "falukantUpdateStatus" } }; changeFalukantUserMoney(falukantUserId, sellPrice, "sell products", changeMessage); db.prepare("QUERY_ADD_SELL_LOG", QUERY_ADD_SELL_LOG); db.execute("QUERY_ADD_SELL_LOG", { std::to_string(regionId), std::to_string(productId), std::to_string(quantity), std::to_string(falukantUserId) }); } db.prepare("remove_inventory", QUERY_REMOVE_INVENTORY); db.execute("remove_inventory", { std::to_string(inventoryId) }); nlohmann::json message = { { "event", "selled_items" }, { "branch_id", item.at("branch_id") }, }; sendMessageToFalukantUsers(falukantUserId, message); } } void DirectorWorker::paySalary() { setCurrentStep("salary - load to pay"); ConnectionGuard connGuard(pool); auto &db = connGuard.get(); db.prepare("QUERY_GET_SALARY_TO_PAY", QUERY_GET_SALARY_TO_PAY); const auto &salariesToPay = db.execute("QUERY_GET_SALARY_TO_PAY"); nlohmann::json message = { { "event", "falukantUpdateStatus" } }; for (auto const &item: salariesToPay) { changeFalukantUserMoney(std::stoi(item.at("employer_user_id")), -std::stoi(item.at("income")), "director payed out", message); db.prepare("QUERY_SET_SALARY_PAYED", QUERY_SET_SALARY_PAYED); db.execute("QUERY_SET_SALARY_PAYED", { std::to_string(std::stoi(item.at("id"))) }); } } void DirectorWorker::calculateSatisfaction() { ConnectionGuard connGuard(pool); auto &db = connGuard.get(); db.prepare("QUERY_UPDATE_SATISFACTION", QUERY_UPDATE_SATISFACTION); const auto &changedDirectors = db.execute("QUERY_UPDATE_SATISFACTION"); nlohmann::json message = { { "event", "directorchanged" } }; for (auto const &director: changedDirectors) { sendMessageToFalukantUsers(std::stoi(director.at("employer_user_id")), message); } }