Files
yourpart3/src/director_worker.cpp

198 lines
7.7 KiB
C++

#include "director_worker.h"
#include <iostream>
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<std::chrono::seconds>(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<std::string, std::string> 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<std::string, std::string>) {
}
void DirectorWorker::startSellings(std::unordered_map<std::string, std::string> 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);
}
}