198 lines
7.7 KiB
C++
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);
|
|
}
|
|
}
|