This commit is contained in:
Crylia
2024-07-08 23:52:36 +02:00
parent 5bce421326
commit 701a8c3a98
15 changed files with 463 additions and 433 deletions

View File

@@ -5,32 +5,28 @@ EinsatzplanFrameController::EinsatzplanFrameController(QString id, bool admin)
m_admin(admin) {
const std::map<std::string, std::string> config = load_config( );
m_connectionString = fmt::format(
m_dbHandler = std::make_unique<DBHandler>(fmt::format(
"host={} port={} dbname={} user={} password={}",
config.at("DB_HOST"),
config.at("DB_PORT"),
config.at("DB_NAME"),
config.at("DB_USER"),
config.at("DB_PASSWORD")
);
));
}
void EinsatzplanFrameController::deleteMember(QString id) {
DBHandler* db = new DBHandler(m_connectionString);
db->deleteVeranstalter(id.toStdString( ));
m_dbHandler->deleteVeranstalter(id.toStdString( ));
}
void EinsatzplanFrameController::deleteVeranstaltung(QString veranstaltungsname) {
DBHandler* db = new DBHandler(m_connectionString);
db->deleteVeranstaltung(veranstaltungsname.toStdString( ));
m_dbHandler->deleteVeranstaltung(veranstaltungsname.toStdString( ));
}
void EinsatzplanFrameController::createMember(QString name, QString email, QString passwort, bool admin) {
DBHandler* db = new DBHandler(m_connectionString);
db->createVeranstalter(email.toStdString( ), name.toStdString( ), passwort.toStdString( ), admin ? "TRUE" : "FALSE");
m_dbHandler->createVeranstalter(name.toStdString( ), email.toStdString( ), passwort.toStdString( ), admin);
}
void EinsatzplanFrameController::createVeranstaltung(QString name, QString raum, QString campus, QString time) {
DBHandler* db = new DBHandler(m_connectionString);
db->createVeranstaltung(name.toStdString( ), std::to_string((char)time.toStdString( ).at(0) - 48), campus.toStdString( ), raum.toStdString( ));
m_dbHandler->createVeranstaltung(name.toStdString( ), campus.toStdString( ), raum.toStdString( ), std::to_string((char)time.toStdString( ).at(0) - 48));
}

View File

@@ -3,12 +3,12 @@
#include <QString>
#include <fmt/format.h>
#include "../../Core/DBHandler/DBHandler/DBHandler.hpp"
#include "../../Core/DBHandler/DBHandler.hpp"
#include "../../Core/config/config.hpp"
class EinsatzplanFrameController {
private:
std::string m_connectionString;
std::unique_ptr<DBHandler> m_dbHandler;
protected:
QString m_id;
@@ -20,4 +20,5 @@ public:
void deleteVeranstaltung(QString veranstaltungsname);
void createMember(QString name, QString email, QString passwort, bool admin);
void createVeranstaltung(QString name, QString raum, QString campus, QString time);
};

View File

@@ -3,18 +3,16 @@
LoginFrameController::LoginFrameController( ) {
auto config = load_config( );
m_connectionString = fmt::format(
m_dbHandler = std::make_unique<DBHandler>(fmt::format(
"host={} port={} dbname={} user={} password={}",
config.at("DB_HOST"),
config.at("DB_PORT"),
config.at("DB_NAME"),
config.at("DB_USER"),
config.at("DB_PASSWORD")
);
));
}
int LoginFrameController::tryLogin(QString id, QString password) {
DBLogin* loginHandler = new DBLogin(m_connectionString);
return loginHandler->checkValidLogin(id.toStdString( ), password.toStdString( ));
return m_dbHandler->tryAuthenticate(id.toStdString( ), password.toStdString( ));
}

View File

@@ -4,13 +4,16 @@
#include <QString>
#include <fmt/core.h>
#include "../../Core/DBHandler/DBLogin/DBLogin.hpp"
#include "../../Core/DBHandler/DBHandler.hpp"
#include "../../Core/config/config.hpp"
class LoginFrameController {
private:
std::string m_connectionString;
std::unique_ptr<DBHandler> m_dbHandler;
public:
LoginFrameController( );
int tryLogin(QString id, QString password);
};

View File

@@ -17,20 +17,18 @@ PlanGridController::PlanGridController( ) {
const std::map<std::string, std::string> config = load_config( );
m_connectionString = fmt::format(
m_dbHandler = std::make_unique<DBHandler>(fmt::format(
"host={} port={} dbname={} user={} password={}",
config.at("DB_HOST"),
config.at("DB_PORT"),
config.at("DB_NAME"),
config.at("DB_USER"),
config.at("DB_PASSWORD")
);
));
}
QMap<QPair<QString, QString>, QWidget*>* PlanGridController::getVeranstaltungen( ) {
DBHandler* db = new DBHandler(m_connectionString);
std::vector<std::string> planData = db->getVeranstaltung( );
std::vector<std::string> planData = m_dbHandler->getPlan( );
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 5; ++j) {
@@ -118,17 +116,35 @@ QMap<QPair<QString, QString>, QWidget*>* PlanGridController::getVeranstaltungen(
)"));
container->setFixedSize(240, 100);
planMap->insert(qMakePair(
weekdays[std::stoi(infoVector.at(0)) - 1],
QString::fromStdString(infoVector.at(1).erase(5, 8))),
container);
if (infoVector.at(8) == "4") {
planMap->insert(qMakePair(
weekdays[std::stoi(infoVector.at(0)) - 1],
QString::fromStdString(infoVector.at(1).erase(5, 8))),
container);
std::string originalString = infoVector.at(1);
if (originalString.length( ) >= 2) {
char secondChar = originalString[1];
secondChar += 2;
originalString[1] = secondChar;
}
planMap->insert(qMakePair(
weekdays[std::stoi(infoVector.at(0)) - 1],
QString::fromStdString(originalString)),
container);
} else {
planMap->insert(qMakePair(
weekdays[std::stoi(infoVector.at(0)) - 1],
QString::fromStdString(infoVector.at(1).erase(5, 8))),
container);
}
}
return planMap;
}
void PlanGridController::Krankmelden(const int id, int tag, int stunde) {
DBHandler db(m_connectionString);
db.meldeKrank(std::to_string(id), std::to_string(tag), std::to_string(stunde));
void PlanGridController::Krankmelden(const int id, const int tag, const std::string& uhrzeit) {
m_dbHandler->krankmelden(std::to_string(id), uhrzeit, tag);
}

View File

@@ -7,12 +7,13 @@
#include <QPushButton>
#include "../../Core/config/config.hpp"
#include "../../Core/DBHandler/DBHandler/DBHandler.hpp"
#include "../../Core/DBHandler/DBHandler.hpp"
class PlanGridController : public QObject {
Q_OBJECT
private:
std::string m_connectionString;
std::unique_ptr<DBHandler> m_dbHandler;
protected:
QString weekdays[5];
QString times[5];
@@ -22,5 +23,5 @@ public:
PlanGridController( );
QMap<QPair<QString, QString>, QWidget*>* getVeranstaltungen( );
void Krankmelden(const int id, const int tag, const int stunde);
void Krankmelden(const int id, const int tag, const std::string& uhrzeit);
};

View File

@@ -0,0 +1,168 @@
#include "DBHandler.hpp"
DBHandler::DBHandler(const std::string& connStr) :
m_dbConnection(std::make_unique<pqxx::connection>(connStr.c_str( ))) {
try {
m_dbConnection->is_open( ) ?
fmt::print("Databased connected") :
fmt::print("Failed to connect to Databased");
}
catch (const std::exception& e) {
fmt::print(e.what( ));
}
};
int DBHandler::tryAuthenticate(std::string id, std::string pw) {
try {
pqxx::work W(*m_dbConnection.get( ));
std::string query =
"SELECT admin FROM veranstalter WHERE id = $1 AND passwort = $2";
pqxx::result response = W.exec_params(query, id, pw);
return response.affected_rows( ) > 0 ? response[0][0].as<bool>( ) : -1;
}
catch (const std::exception& e) {
fmt::print(e.what( ));
}
return -1;
}
bool DBHandler::createVeranstalter(const std::string& name, const std::string& email, const std::string& password, bool admin) {
try {
pqxx::work W(*m_dbConnection.get( ));
std::string admin_value = admin ? "TRUE" : "FALSE";
std::string query = fmt::format(
"INSERT INTO Veranstalter (name, email, passwort, admin) VALUES ({}, {}, {}, {})",
W.quote(name), W.quote(email), W.quote(password), admin_value
);
W.exec(query);
W.commit( );
return true;
}
catch (const std::exception& e) {
fmt::print(e.what( ));
return false;
}
}
bool DBHandler::deleteVeranstalter(int id) {
try {
pqxx::work W(*m_dbConnection.get( ));
std::string query = fmt::format(
"DELETE FROM Veranstalter WHERE ID = {}", W.quote(id)
);
W.exec(query);
W.commit( );
return true;
}
catch (const std::exception& e) {
fmt::print(e.what( ));
return false;
}
}
bool DBHandler::deleteVeranstalter(const std::string& name) {
try {
pqxx::work W(*m_dbConnection.get( ));
std::string query = fmt::format(
"DELETE FROM Veranstalter WHERE name = {}", W.quote(name)
);
W.exec(query);
W.commit( );
return true;
}
catch (const std::exception& e) {
fmt::print(e.what( ));
return false;
}
}
bool DBHandler::createVeranstaltung(const std::string& name, const std::string& campus, const std::string& raum, const std::string& dauer) {
try {
pqxx::work W(*m_dbConnection.get( ));
std::string cmp(1, campus.back( ));
std::string query = fmt::format(
"INSERT INTO Veranstaltung (name, ort, raum, dauer) VALUES ({}, {}, {}, {})",
W.quote(name), W.quote(cmp), W.quote(raum), W.quote(dauer)
);
fmt::println(query);
W.exec(query);
W.commit( );
return true;
}
catch (const std::exception& e) {
fmt::print(e.what( ));
return false;
}
}
bool DBHandler::deleteVeranstaltung(const std::string& name) {
try {
pqxx::work W(*m_dbConnection.get( ));
std::string query = fmt::format(
"DELETE FROM Veranstaltung WHERE name = {}", W.quote(name)
);
W.exec(query);
W.commit( );
return true;
}
catch (const std::exception& e) {
fmt::print(e.what( ));
return false;
}
}
bool DBHandler::krankmelden(const std::string& veranstalter, const std::string& uhrzeit, int tag) {
try {
pqxx::work W(*m_dbConnection.get( ));
std::string query =
"INSERT INTO Krank (stundeImPlan_uhrzeit, stundeImPlan_tag, veranstalter, krank) "
"SELECT SIP.uhrzeit, SIP.tag, V.ID, TRUE "
"FROM StundeImPlan SIP "
"JOIN Veranstalter V ON SIP.veranstalter = V.ID "
"JOIN Uhrzeit U ON SIP.uhrzeit = U.ID "
"JOIN Veranstaltung VA ON SIP.veranstaltung = VA.name "
"WHERE V.id = " + W.quote(veranstalter) +
" AND U.anfangszeit = " + W.quote(std::string(uhrzeit + ":00")) +
" AND SIP.tag = " + W.quote(tag) + ";";
W.exec(query);
W.commit( );
return true;
}
catch (const std::exception& e) {
fmt::print(e.what( ));
return false;
}
}
std::vector<std::string> DBHandler::getPlan( ) {
std::vector<std::string> plan;
try {
pqxx::nontransaction N(*m_dbConnection.get( ));
std::string query =
R"(SELECT SIP.tag, U.anfangszeit, U.endzeit, VA.ort, VA.name AS veranstaltungsname, V.name AS veranstaltername, VA.raum, SIP.veranstalter, VA.dauer
FROM StundeImPlan SIP
JOIN Uhrzeit U ON SIP.uhrzeit = U.ID
JOIN Veranstaltung VA ON SIP.veranstaltung = VA.name
JOIN Veranstalter V ON SIP.veranstalter = V.ID
ORDER BY U.anfangszeit)";
pqxx::result R(N.exec(query));
for (auto row : R) {
std::string entry = fmt::format(
"{},{},{},{},{},{},{},{},{}",
row["tag"].c_str( ), row["anfangszeit"].c_str( ), row["endzeit"].c_str( ), row["ort"].c_str( ),
row["veranstaltungsname"].c_str( ), row["veranstaltername"].c_str( ), row["raum"].c_str( ), row["veranstalter"].c_str( ), row["dauer"].c_str( )
);
plan.push_back(entry);
}
}
catch (const std::exception& e) {
fmt::print(e.what( ));
}
return plan;
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include <pqxx/pqxx>
#include <string>
#include <fmt/core.h>
#include <random>
#include <ctime>
class DBHandler {
private:
std::unique_ptr<pqxx::connection> m_dbConnection;
public:
DBHandler(const std::string& connStr);
/**
* @brief Tries to login the user
* @param id user id
* @param pw user password
* @return returns 1 if admin and 0 if not
*/
int tryAuthenticate(std::string id, std::string pw);
bool createVeranstalter(const std::string& name, const std::string& email, const std::string& password, bool admin);
bool deleteVeranstalter(int id);
bool deleteVeranstalter(const std::string& name);
bool createVeranstaltung(const std::string& name, const std::string& campus, const std::string& time, const std::string& veranstalter);
bool deleteVeranstaltung(const std::string& name);
bool krankmelden(const std::string& veranstalter, const std::string& uhrzeit, int tag);
std::vector<std::string> getPlan( );
};

View File

@@ -1,204 +0,0 @@
#include "DBHandler.hpp"
DBHandler::DBHandler(std::string connStr) :
connectionObject(connStr.c_str( )) {
try {
if (connectionObject.is_open( ))
fmt::print("Databased connected");
else
fmt::print("Failed to connect to Databased");
}
catch (const std::exception& e) {
fmt::print(e.what( ));
}
};
void DBHandler::deleteVeranstalter(std::string id){
try {
pqxx::work worker(connectionObject);
std::string query = fmt::format("DELETE FROM Student WHERE id = {0}",id);
worker.exec(query);
worker.commit();
query = fmt::format("DELETE FROM Veranstalter WHERE id = {0}",id);
worker.exec_params(query);
worker.commit();
fmt::print("Veranstalter with ID {} deleted successfully.\n", id);
}
catch (const std::exception& e) {
fmt::print("ERROR: {0}", e.what( ));
}
}
void DBHandler::deleteVeranstaltung(std::string name) {
try {
pqxx::work worker(connectionObject);
std::string query = fmt::format("DELETE FROM Veranstaltung WHERE name = '{0}'", name);
worker.exec(query);
worker.commit();
fmt::print("Veranstaltung with name '{}' deleted successfully.\n", name);
} catch (const std::exception& e) {
fmt::print(stderr, "Error deleting Veranstaltung: {}\n", e.what());
}
}
void DBHandler::createVeranstalter(std::string email, std::string name, std::string passwort, std::string admin) {
try {
pqxx::work worker(connectionObject);
std::string query = fmt::format(
"INSERT INTO Veranstalter (email, name, passwort, admin) VALUES ('{}', '{}', '{}', {})",
email, name, passwort, admin
);
worker.exec(query);
worker.commit();
fmt::print("Veranstalter {} created successfully.\n", name);
} catch (const std::exception& e) {
fmt::print(stderr, "Error creating Veranstalter: {}\n", e.what());
}
}
void DBHandler::createVeranstaltung(std::string name, std::string uhrzeit, std::string standort, std::string raum) {
try {
pqxx::work worker(connectionObject);
std::string query = fmt::format(
"INSERT INTO Veranstaltung (name, uhrzeit, standort, raum) VALUES ('{}', '{}', '{}', '{}')",
name, uhrzeit, standort, raum
);
worker.exec(query);
worker.commit();
fmt::print("Veranstaltung {} created successfully.\n", name);
} catch (const std::exception& e) {
fmt::print(stderr, "Error creating Veranstaltung: {}\n", e.what());
}
}
void DBHandler::createEinsatzplan() {
try {
pqxx::work worker(connectionObject);
// Fetch all Veranstaltungen
pqxx::result veranstaltungen = worker.exec("SELECT ID, dauer, used FROM Veranstaltung");
// Fetch all available Uhrzeiten
std::vector<int> uhrzeiten = {1, 2, 3, 4, 5}; // Representing 1 to 5 time slots
// Fetch all available Veranstalter
pqxx::result veranstalter = worker.exec("SELECT ID FROM Veranstalter");
std::mt19937 rng(static_cast<unsigned int>(std::time(nullptr))); // Random number generator
std::uniform_int_distribution<int> day_dist(1, 5); // Random days between 1 and 5 (Monday to Friday)
for (auto row : veranstaltungen) {
int veranstaltungID = row["id"].as<int>();
int dauer = row["dauer"].as<int>();
int used = row["used"].as<int>();
while (used < dauer) {
// Randomly select a day
int day = day_dist(rng);
// Randomly select a Uhrzeit
std::uniform_int_distribution<int> uhrzeit_dist(0, uhrzeiten.size() - 1);
int uhrzeitIndex = uhrzeit_dist(rng);
int uhrzeitID = uhrzeiten[uhrzeitIndex];
// Randomly select a Veranstalter
std::uniform_int_distribution<int> veranstalter_dist(0, veranstalter.size() - 1);
int veranstalterIndex = veranstalter_dist(rng);
int veranstalterID = veranstalter[veranstalterIndex]["id"].as<int>();
// Check if the selected Veranstalter is valid for the selected time and location
std::string checkQuery = fmt::format(
"SELECT COUNT(*) FROM StundenImPlan sip "
"JOIN Veranstaltung v ON sip.veranstaltung_ID = v.ID "
"WHERE sip.tag = {} AND (sip.uhrzeit_ID = {} OR sip.uhrzeit_ID = {} - 1) "
"AND v.ort != (SELECT ort FROM Veranstaltung WHERE ID = {}) "
"AND sip.veranstalter_ID = {}",
day, uhrzeitID, uhrzeitID, veranstaltungID, veranstalterID);
pqxx::result checkResult = worker.exec(checkQuery);
int count = checkResult[0][0].as<int>();
if (count == 0) {
// Assign to StundenImPlan
std::string query = fmt::format(
"INSERT INTO StundenImPlan (uhrzeit_ID, tag, veranstalter_ID, veranstaltung_ID) VALUES ({}, {}, {}, {})",
uhrzeitID, day, veranstalterID, veranstaltungID
);
worker.exec(query);
// Update used count
used += 2;
std::string updateQuery = fmt::format(
"UPDATE Veranstaltung SET used = {} WHERE ID = {}",
used, veranstaltungID
);
worker.exec(updateQuery);
}
}
}
worker.commit();
fmt::print("Random schedule assigned successfully.\n");
} catch (const std::exception& e) {
fmt::print(stderr, "Error assigning random schedule: {}\n", e.what());
}
}
std::vector<std::string> DBHandler::getVeranstaltung() {
std::vector<std::string> results;
try {
pqxx::work txn(connectionObject);
// Check if StundenImPlan is empty
std::string checkQuery = "SELECT COUNT(*) FROM StundenImPlan";
pqxx::result countResult = txn.exec(checkQuery);
int count = countResult[0][0].as<int>();
if (count == 0) {
createEinsatzplan();
}
// Fetch data from StundenImPlan
pqxx::result stundenImPlanResult = txn.exec(
"SELECT sip.tag, u.anfangszeit, u.endzeit, v.ort, v.name AS veranstaltungsname, "
"a.name AS veranstaltername, v.raum, sip.veranstalter_ID "
"FROM StundenImPlan sip "
"JOIN Uhrzeit u ON sip.uhrzeit_ID = u.ID "
"JOIN Veranstaltung v ON sip.veranstaltung_ID = v.ID "
"JOIN Veranstalter a ON sip.veranstalter_ID = a.ID"
);
// Format the results
for (const auto &row : stundenImPlanResult) {
std::string result = fmt::format("{},{},{},{},{},{},{},{}",
row["tag"].as<int>(),
row["anfangszeit"].as<std::string>(),
row["endzeit"].as<std::string>(),
row["ort"].as<std::string>(),
row["veranstaltungsname"].as<std::string>(),
row["veranstaltername"].as<std::string>(),
row["raum"].as<std::string>(),
row["veranstalter_id"].as<int>());
results.push_back(result);
}
} catch (const std::exception& e) {
fmt::print(stderr, "Error retrieving Veranstaltung data: {}\n", e.what());
}
return results;
}
void DBHandler::meldeKrank(std::string id, std::string tag, std::string stunde){
try {
pqxx::work worker(connectionObject);
std::string query = fmt::format("Update StundeImPlan SET veranstalter_ID = NULL WHERE veranstalter_ID = {0}",id);
worker.exec(query);
worker.commit();
fmt::print("Veranstalter with ID {} marked ill successfully.\n", id);
}
catch (const std::exception& e) {
fmt::print("ERROR: {0}", e.what( ));
}
}

View File

@@ -1,22 +0,0 @@
#pragma once
#include <pqxx/pqxx>
#include <string>
#include <fmt/core.h>
#include <random>
#include <ctime>
class DBHandler {
protected:
pqxx::connection connectionObject;
void createEinsatzplan();
public:
DBHandler(std::string connStr);
void deleteVeranstalter(std::string id);
void deleteVeranstaltung(std::string name);
void createVeranstalter(std::string email, std::string name, std::string passwort, std::string admin);
void createVeranstaltung(std::string name, std::string uhrzeit, std::string standort, std::string raum);
std::vector<std::string> getVeranstaltung();
void meldeKrank(std::string id, std::string tag, std::string stunde);
};

View File

@@ -1,22 +0,0 @@
#include "DBLogin.hpp"
DBLogin::DBLogin(std::string connStr) : DBHandler(connStr) { };
int DBLogin::checkValidLogin(std::string id, std::string pw) {
try {
pqxx::work worker(connectionObject);
std::string query =
"SELECT admin FROM studenten_veranstalter WHERE id = $1 AND passwort = $2";
pqxx::result response = worker.exec_params(query, id, pw);
return response.affected_rows( ) > 0 ? response[0][0].as<bool>( ) : -1;
}
catch (const std::exception& e) {
fmt::printf("ERROR: %s", e.what( ));
}
return -1;
}

View File

@@ -1,18 +0,0 @@
#pragma once
#include <fmt/printf.h>
#include "../DBHandler/DBHandler.hpp"
class DBLogin : public DBHandler {
public:
DBLogin(std::string connStr);
/**
* @brief Tries to login the user
* @param id user id
* @param pw user password
* @return returns 1 if admin and 0 if not
*/
int checkValidLogin(std::string id, std::string pw);
};

View File

@@ -210,6 +210,8 @@ void EinsatzplanFrame::createVeranstaltung( ) {
QString campus = dialog.getCampus( );
QString time = dialog.getTime( );
m_controller->createVeranstaltung(name, raum, campus, time);
m_planGrid->setPlanMap(m_planGrid->planGridController->getVeranstaltungen( ));
m_planGrid->populateGrid( );
}
}

View File

@@ -115,7 +115,7 @@ void PlanGrid::populateGrid( ) {
planGridController->Krankmelden(
id,
i + 1,
j + 1
m_times[j].toStdString( )
);
}
planMap = planGridController->getVeranstaltungen( );