From 726abda4c0dd6bb512c4c24c20a54e98a1572beb Mon Sep 17 00:00:00 2001 From: krivoshein Date: Wed, 30 Jul 2025 12:34:34 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B0=D0=B9=D0=BC=D0=B8=D0=BD=D0=B3.=20?= =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82.=20=D0=9F?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=B2=D0=B0=D1=80=D0=B8=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=BE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DataBaseLMS/CMakeLists.txt | 2 + DataBaseLMS/databaselms.cpp | 52 +++++++++++++ DataBaseLMS/databaselms.h | 6 ++ DataBaseLMS/interfacedatabaselms.cpp | 82 +++++++++++++++++++++ DataBaseLMS/interfacedatabaselms.h | 5 ++ DataBaseLMS/timingoftrainee.cpp | 6 ++ DataBaseLMS/timingoftrainee.h | 34 +++++++++ ServerLMS/Data/Client.h | 11 +++ ServerLMS/Data/PacketType.h | 2 +- ServerLMS/Systems/Parsers/processparser.cpp | 2 +- ServerLMS/Systems/Parsers/processparser.h | 3 +- ServerLMS/Systems/processingsystem.cpp | 51 +++++++++++++ ServerLMS/Systems/processingsystem.h | 3 + ServerLMS/Systems/recognizesystem.cpp | 5 +- ServerLMS/Systems/recognizesystem.h | 2 +- ServerLMS/Systems/tools.h | 1 + ServerLMS/providerdblms.cpp | 16 ++++ ServerLMS/providerdblms.h | 4 + ServerLMS/serverlmswidget.cpp | 14 +++- 19 files changed, 292 insertions(+), 9 deletions(-) create mode 100644 DataBaseLMS/timingoftrainee.cpp create mode 100644 DataBaseLMS/timingoftrainee.h diff --git a/DataBaseLMS/CMakeLists.txt b/DataBaseLMS/CMakeLists.txt index fb0c152..b5c50e1 100644 --- a/DataBaseLMS/CMakeLists.txt +++ b/DataBaseLMS/CMakeLists.txt @@ -25,6 +25,8 @@ add_library(DataBaseLMS SHARED tasksAmmFim.cpp tasksAmmFim.h typeQueryToDB.h + timingoftrainee.cpp + timingoftrainee.h ) target_link_libraries(DataBaseLMS PRIVATE Qt5::Widgets) diff --git a/DataBaseLMS/databaselms.cpp b/DataBaseLMS/databaselms.cpp index 64aa5f3..a32aa1a 100644 --- a/DataBaseLMS/databaselms.cpp +++ b/DataBaseLMS/databaselms.cpp @@ -1691,6 +1691,58 @@ int DataBaseLMS::updateTrainee(Trainee trainee) return queryExecInt(queryStr); } +int DataBaseLMS::insertTimingTrainee(int id_trainee) +{ + QString queryStr = QString("INSERT INTO public.timings (entry_time, exit_time, operating_time, timing_trainee) " + "VALUES (DEFAULT, DEFAULT, DEFAULT, %1) " + "RETURNING timings.timing_id").arg( + QString::number(id_trainee)); + + return queryExecInt(queryStr); +} + +int DataBaseLMS::updateTimingTrainee(int id_trainee, TimingOfTrainee timing) +{ + QString queryStr = QString("UPDATE public.timings " + "SET entry_time = '%1', exit_time = '%2', operating_time = '%3', timing_trainee = %4 " + "WHERE timing_id = %5 " + "RETURNING timings.timing_id").arg( + timing.getEntryTime(), + timing.getExitTime(), + timing.getOperatingTime(), + QString::number(id_trainee), + QString::number(timing.getID()) ); + + return queryExecInt(queryStr); +} + +TimingOfTrainee DataBaseLMS::selectTimingTrainee(int id_trainee) +{ + TimingOfTrainee timing; + + QString queryStr; + + queryStr = QString("SELECT timings.timing_id, timings.entry_time, timings.exit_time, timings.operating_time, timings.timing_trainee " + "FROM public.timings " + "WHERE timing_trainee = '%1'").arg(id_trainee); + + QSqlQuery querySel = QSqlQuery(*db); + + if(queryExec(queryStr, &querySel)) + { + if (querySel.first()) + {//Тайминг + timing.setID(querySel.value(0).toInt()); + timing.setEntryTime(querySel.value(1).toDateTime().toString()); + timing.setExitTime(querySel.value(2).toDateTime().toString()); + timing.setOperatingTime(querySel.value(3).toTime().toString()); + timing.setTraineeID(querySel.value(4).toInt()); + } + } + + return timing; +} + int DataBaseLMS::queryExecInt(QString queryStr) { QSqlQuery query = QSqlQuery(*db); diff --git a/DataBaseLMS/databaselms.h b/DataBaseLMS/databaselms.h index b431be4..0f0568f 100644 --- a/DataBaseLMS/databaselms.h +++ b/DataBaseLMS/databaselms.h @@ -8,6 +8,7 @@ #include "trainee.h" #include "group.h" #include "tasksAmmFim.h" +#include "timingoftrainee.h" class DataBaseSettings { @@ -101,6 +102,11 @@ protected: int deleteTrainee(int id_trainee); int updateTrainee(Trainee trainee); + //Тайминг + int insertTimingTrainee(int id_trainee); + int updateTimingTrainee(int id_trainee, TimingOfTrainee timing); + TimingOfTrainee selectTimingTrainee(int id_trainee); + private: DataBaseSettings getDataBaseSettings(); int queryExecInt(QString queryStr); diff --git a/DataBaseLMS/interfacedatabaselms.cpp b/DataBaseLMS/interfacedatabaselms.cpp index 988f457..f3e42a8 100644 --- a/DataBaseLMS/interfacedatabaselms.cpp +++ b/DataBaseLMS/interfacedatabaselms.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "interfacedatabaselms.h" InterfaceDataBaseLMS::InterfaceDataBaseLMS(QWidget* parent): @@ -218,6 +220,86 @@ bool InterfaceDataBaseLMS::deAuthorizationAllTrainees() return updateAllTraineesLoggedIn(false); } +int InterfaceDataBaseLMS::entryTraineeOnSimulator(int id_trainee) +{ + TimingOfTrainee timing; + + QDateTime dataTime_entry = QDateTime::currentDateTime(); + QDateTime dataTime_exit; + int interval; + + QString dataTimeStr_entry = dataTime_entry.toString("yyyy-MM-dd hh:mm:ss.zzz"); + QString dataTimeStr_exit = ""; + QString intervalStr = ""; + + timing = selectTimingTrainee(id_trainee); + + if(timing.getID()) + {//Запись уже есть в базе + dataTime_exit = QDateTime::fromString(timing.getExitTime()); + dataTimeStr_exit = dataTime_exit.toString("yyyy-MM-dd hh:mm:ss.zzz"); + intervalStr = timing.getOperatingTime(); + } + else + {//Еще нет записи + int timing_id = insertTimingTrainee(id_trainee); + timing.setID(timing_id); + + dataTime_exit = dataTime_entry; + interval = dataTime_entry.secsTo(dataTime_exit); + dataTimeStr_exit = dataTime_exit.toString("yyyy-MM-dd hh:mm:ss.zzz"); + intervalStr = QString::number(interval); + } + + timing.setTraineeID(id_trainee); + timing.setEntryTime(dataTimeStr_entry); + timing.setExitTime(dataTimeStr_exit); + timing.setOperatingTime(intervalStr); + + return updateTimingTrainee(id_trainee, timing); +} + +int InterfaceDataBaseLMS::exitTraineeFromSimulator(int id_trainee) +{ + TimingOfTrainee timing; + + QDateTime dataTime_entry; + QDateTime dataTime_exit = QDateTime::currentDateTime(); + int interval; + + QString dataTimeStr_entry = ""; + QString dataTimeStr_exit = dataTime_exit.toString("yyyy-MM-dd hh:mm:ss.zzz"); + QString intervalStr = ""; + + timing = selectTimingTrainee(id_trainee); + + if(timing.getID()) + {//Запись уже есть в базе + dataTime_entry = QDateTime::fromString(timing.getEntryTime()); + dataTimeStr_entry = dataTime_entry.toString("yyyy-MM-dd hh:mm:ss.zzz"); + interval = QTime::fromString(timing.getOperatingTime()).second() + dataTime_entry.secsTo(dataTime_exit); + //interval = dataTime_entry.secsTo(dataTime_exit); + intervalStr = QString::number(interval); + } + else + {//Еще нет записи + int timing_id = insertTimingTrainee(id_trainee); + timing.setID(timing_id); + + dataTime_entry = dataTime_exit; + interval = dataTime_entry.secsTo(dataTime_exit); + dataTimeStr_entry = dataTime_entry.toString("yyyy-MM-dd hh:mm:ss.zzz"); + intervalStr = QString::number(interval); + } + + timing.setTraineeID(id_trainee); + timing.setEntryTime(dataTimeStr_entry); + timing.setExitTime(dataTimeStr_exit); + timing.setOperatingTime(intervalStr); + + return updateTimingTrainee(id_trainee, timing); +} + QString InterfaceDataBaseLMS::getNameTraineeOnComputer(QString computer_name) { return selectTraineeNameOnComputer(computer_name); diff --git a/DataBaseLMS/interfacedatabaselms.h b/DataBaseLMS/interfacedatabaselms.h index 701e55e..e7484d3 100644 --- a/DataBaseLMS/interfacedatabaselms.h +++ b/DataBaseLMS/interfacedatabaselms.h @@ -51,6 +51,11 @@ public: bool deAuthorizationTrainee(QString login); bool deAuthorizationAllTrainees(); + //Регистрация тайминга Обучаемого + int entryTraineeOnSimulator(int id_trainee); + int exitTraineeFromSimulator(int id_trainee); + + //void setTasks(QString login, QStringList tasks); QString getNameTraineeOnComputer(QString computer_name); diff --git a/DataBaseLMS/timingoftrainee.cpp b/DataBaseLMS/timingoftrainee.cpp new file mode 100644 index 0000000..b69f436 --- /dev/null +++ b/DataBaseLMS/timingoftrainee.cpp @@ -0,0 +1,6 @@ +#include "timingoftrainee.h" + +TimingOfTrainee::TimingOfTrainee() +{ + +} diff --git a/DataBaseLMS/timingoftrainee.h b/DataBaseLMS/timingoftrainee.h new file mode 100644 index 0000000..d588eb7 --- /dev/null +++ b/DataBaseLMS/timingoftrainee.h @@ -0,0 +1,34 @@ +#ifndef TIMINGOFTRAINEE_H +#define TIMINGOFTRAINEE_H + +#include + +class TimingOfTrainee +{ +public: + TimingOfTrainee(); + + void setID(int timing_id){this->timing_id = timing_id;} + int getID(){return timing_id;} + + void setEntryTime(QString entry_time){this->entry_time = entry_time;} + QString getEntryTime(){return entry_time;} + + void setExitTime(QString exit_time){this->exit_time = exit_time;} + QString getExitTime(){return exit_time;} + + void setOperatingTime(QString operating_time){this->operating_time = operating_time;} + QString getOperatingTime(){return operating_time;} + + void setTraineeID(int trainee_id){this->trainee_id = trainee_id;} + int getTraineeID(){return trainee_id;} + +private: + int timing_id = 0; + QString entry_time = ""; + QString exit_time = ""; + QString operating_time = ""; + int trainee_id = 0; +}; + +#endif // TIMINGOFTRAINEE_H diff --git a/ServerLMS/Data/Client.h b/ServerLMS/Data/Client.h index 1dfebb1..d10446d 100644 --- a/ServerLMS/Data/Client.h +++ b/ServerLMS/Data/Client.h @@ -96,6 +96,16 @@ public: isLoggedIn = value; } + void setAccessType(QString type) + { + accessType = type; + } + QString getAccessType() + { + return accessType; + } + + private: QString name; @@ -109,6 +119,7 @@ private: bool isUnity = false; TypeClientAutorization TypeClient; + QString accessType = ""; }; #endif // CLIENT_H diff --git a/ServerLMS/Data/PacketType.h b/ServerLMS/Data/PacketType.h index b141ff0..381e267 100644 --- a/ServerLMS/Data/PacketType.h +++ b/ServerLMS/Data/PacketType.h @@ -19,7 +19,7 @@ enum PacketType TYPE_FILESIZE = 20, TYPE_BIGXML = 21, - TYPE_XMLANSWER_MESSAGE_FOR_GUI = 90, + TYPE_XMLANSWER_MESSAGE_FOR_GUI = 90, //xml-ответы на запросы к БД TYPE_XMLANSWER_QUERY_DB__LIST_INSTRUCTORS = 100, diff --git a/ServerLMS/Systems/Parsers/processparser.cpp b/ServerLMS/Systems/Parsers/processparser.cpp index ad72b3e..7971874 100644 --- a/ServerLMS/Systems/Parsers/processparser.cpp +++ b/ServerLMS/Systems/Parsers/processparser.cpp @@ -11,7 +11,7 @@ void ProcessParser::initialize(ProcessingSystem *processingSystem) this->processingSystem = processingSystem; } -void ProcessParser::read(ClientHandler *client, QByteArray array) +void ProcessParser::slot_read(ClientHandler *client, QByteArray array) { QXmlStreamReader xmlReader(array); diff --git a/ServerLMS/Systems/Parsers/processparser.h b/ServerLMS/Systems/Parsers/processparser.h index 63fb1ab..01a39b4 100644 --- a/ServerLMS/Systems/Parsers/processparser.h +++ b/ServerLMS/Systems/Parsers/processparser.h @@ -12,8 +12,9 @@ class ProcessParser : public QObject public: explicit ProcessParser(QObject *parent = nullptr); void initialize(ProcessingSystem *processingSystem); - void read(ClientHandler *client, QByteArray array); +public slots: + void slot_read(ClientHandler *client, QByteArray array); signals: void sigLogMessage(QString text); diff --git a/ServerLMS/Systems/processingsystem.cpp b/ServerLMS/Systems/processingsystem.cpp index ab52f47..63c11f3 100644 --- a/ServerLMS/Systems/processingsystem.cpp +++ b/ServerLMS/Systems/processingsystem.cpp @@ -58,6 +58,7 @@ void ProcessingSystem::processingClientAutorization(ClientHandler *client, Clien {//Авторизуется инструктор client->getClient()->setLogin(clientAutorization.Login); + client->getClient()->setAccessType("instructor"); client->getClient()->setTypeClient(clientAutorization.TypeClient); emit sigUpdateListClients(); @@ -72,6 +73,7 @@ void ProcessingSystem::processingClientAutorization(ClientHandler *client, Clien {//Авторизуется обучаемый client->getClient()->setLogin(clientAutorization.Login); + client->getClient()->setAccessType("trainee"); emit sigUpdateListClients(); //KAV redact @@ -120,6 +122,7 @@ void ProcessingSystem::processingClientDeAutorization(ClientHandler *client, Cli {//ДеАвторизуется обучаемый client->getClient()->setLogin(""); + client->getClient()->setAccessType(""); emit sigUpdateListClients(); arrayAnswer = dataParser->ClientAnswer()->deAuthorization(true, clientDeAutorization.Login); @@ -128,6 +131,7 @@ void ProcessingSystem::processingClientDeAutorization(ClientHandler *client, Cli {//ДеАвторизуется инструктор client->getClient()->setLogin(""); + client->getClient()->setAccessType(""); emit sigUpdateListClients(); arrayAnswer = dataParser->ClientAnswer()->deAuthorization(true, clientDeAutorization.Login); @@ -160,6 +164,38 @@ void ProcessingSystem::processingClientDeAutorization(QString login) } } +void ProcessingSystem::processingEntryUnityClient(ClientHandler *client) +{ + QString login = client->getClient()->getLogin(); + QString accessType = client->getClient()->getAccessType(); + + if(accessType == "trainee") + { + int id_trainee = providerDBLMS->getIdTraineeByLogin(login); + providerDBLMS->entryTraineeOnSimulator(id_trainee); + } + else if(accessType == "instructor") + { + //Здесь пока ничего не происходит + } +} + +void ProcessingSystem::processingExitUnityClient(ClientHandler *client) +{ + QString login = client->getClient()->getLogin(); + QString accessType = client->getClient()->getAccessType(); + + if(accessType == "trainee") + { + int id_trainee = providerDBLMS->getIdTraineeByLogin(login); + providerDBLMS->exitTraineeFromSimulator(id_trainee); + } + else if(accessType == "instructor") + { + //Здесь пока ничего не происходит + } +} + void ProcessingSystem::processingClientQueryToDB(ClientHandler *client, ClientQueryToDB clientQueryToDB, int id, void* data) { qDebug() << "ProcessingQueryThread " << QThread::currentThreadId(); @@ -477,9 +513,24 @@ void ProcessingSystem::processingClientNotify(ClientHandler *client, ClientNotif sendTaskListToUnity(client); client->getSocket()->flush(); } + else if(clientNotify.Code == commandStartTimerClient) + { + //Фиксируем время входа Юнити-клиента + if (client->getClient()->getIsUnity()) + { + processingEntryUnityClient(client); + } + } else if(clientNotify.Code == commandDisableClient) { qDebug() << "processing thread: " << QThread::currentThreadId(); + + //Фиксируем время выхода Юнити-клиента + if (client->getClient()->getIsUnity()) + { + processingExitUnityClient(client); + } + client->sendDisable(); } else if(clientNotify.Code == commandGetServerDataList) diff --git a/ServerLMS/Systems/processingsystem.h b/ServerLMS/Systems/processingsystem.h index dbb7dee..c4a2d84 100644 --- a/ServerLMS/Systems/processingsystem.h +++ b/ServerLMS/Systems/processingsystem.h @@ -51,6 +51,9 @@ public: ClientHandler* getUnityClientById(int id); void processingClientDeAutorization(QString login); + + void processingEntryUnityClient(ClientHandler *client); + void processingExitUnityClient(ClientHandler *client); signals: void sigUpdateListClients(); void sigListsInstructorsTraineesChanged(); diff --git a/ServerLMS/Systems/recognizesystem.cpp b/ServerLMS/Systems/recognizesystem.cpp index 31f1710..85a5ed8 100644 --- a/ServerLMS/Systems/recognizesystem.cpp +++ b/ServerLMS/Systems/recognizesystem.cpp @@ -28,7 +28,7 @@ void RecognizeSystem::initialize(UpdateController *updateController,DataParser* connect(this,&RecognizeSystem::sigChangeVersion,updateController,&UpdateController::changeAssetVersion,Qt::AutoConnection); connect(this,&RecognizeSystem::sigDeleteVersion,updateController,&UpdateController::deleteAssetVersion,Qt::AutoConnection); connect(this,&RecognizeSystem::sigCopyVersion,updateController,&UpdateController::createCopyVersion,Qt::AutoConnection); - connect(this,&RecognizeSystem::sigXmlParser,dataParser->getProcessParser(),&ProcessParser::read,Qt::DirectConnection); + connect(this,&RecognizeSystem::sigXmlParser,dataParser->getProcessParser(),&ProcessParser::slot_read,Qt::DirectConnection); qDebug() << "Recognize init thread ID " << QThread::currentThreadId(); } @@ -435,7 +435,7 @@ void RecognizeSystem::recognize() if(packetType == PacketType::TYPE_DISABLE) { - clientHandler->sendDisable(); + clientHandler->sendDisable(); } packetType = PacketType::TYPE_NONE; @@ -455,6 +455,7 @@ void RecognizeSystem::packetTypeInit(PacketType packet,Client *client) else if (packet == PacketType::TYPE_UNITY) { client->setUnity(true); + //Фиксируем время входа Юнити-клиента } isPackageTypeInited = true; diff --git a/ServerLMS/Systems/recognizesystem.h b/ServerLMS/Systems/recognizesystem.h index 7d54af4..84a4283 100644 --- a/ServerLMS/Systems/recognizesystem.h +++ b/ServerLMS/Systems/recognizesystem.h @@ -59,7 +59,7 @@ private: bool isPackageTypeInited; void packetTypeInit(PacketType packet,Client *client); - void packetTypeInit(PacketType type); + //void packetTypeInit(PacketType type); bool checkIsChangeable(); }; diff --git a/ServerLMS/Systems/tools.h b/ServerLMS/Systems/tools.h index 327f37a..78dc068 100644 --- a/ServerLMS/Systems/tools.h +++ b/ServerLMS/Systems/tools.h @@ -39,6 +39,7 @@ static const QString commandGetServerDataList = "GETSERVERDATALIST"; static const QString commandCheckVersionList = "CHECKVERSIONLIST"; static const QString commandReadyClient = "READY"; static const QString commandDisableClient = "DISABLE"; +static const QString commandStartTimerClient = "UNITYSTARTTIMER"; static const QString commandDuplicateVerName = "DUPLICATEVERNAME"; static const QString commandHashCompleteClient = "HASHSENDCOMPLETE"; static const QString commandCanChangeVersion = "CANCHANGE"; diff --git a/ServerLMS/providerdblms.cpp b/ServerLMS/providerdblms.cpp index bc98394..2576e5e 100644 --- a/ServerLMS/providerdblms.cpp +++ b/ServerLMS/providerdblms.cpp @@ -222,6 +222,22 @@ bool ProviderDBLMS::deAuthorizationAll() return res1 && res2; } +bool ProviderDBLMS::entryTraineeOnSimulator(int id_trainee) +{ + if(dbLMS->entryTraineeOnSimulator(id_trainee)) + return true; + else + return false; +} + +bool ProviderDBLMS::exitTraineeFromSimulator(int id_trainee) +{ + if(dbLMS->exitTraineeFromSimulator(id_trainee)) + return true; + else + return false; +} + int ProviderDBLMS::getIdTraineeByLogin(QString login) { int id_trainee = 0; diff --git a/ServerLMS/providerdblms.h b/ServerLMS/providerdblms.h index cd081df..58835b3 100644 --- a/ServerLMS/providerdblms.h +++ b/ServerLMS/providerdblms.h @@ -28,6 +28,10 @@ public: //Общая деавторизация bool deAuthorizationAll(); + //Регистрация тайминга Обучаемого + bool entryTraineeOnSimulator(int id_trainee); + bool exitTraineeFromSimulator(int id_trainee); + // int getIdTraineeByLogin(QString login); int getIdInstructorByLogin(QString login); diff --git a/ServerLMS/serverlmswidget.cpp b/ServerLMS/serverlmswidget.cpp index 770652b..871d7b5 100644 --- a/ServerLMS/serverlmswidget.cpp +++ b/ServerLMS/serverlmswidget.cpp @@ -130,16 +130,24 @@ bool ServerLMSWidget::stopServer() //Закрываем все открытые сокеты foreach(int idSocket, clientsMap.keys()) { - clientsMap[idSocket]->sigSendXmlAnswer(arrayAnswer,PacketType::TYPE_XMLANSWER); + ClientHandler* clientHandlerOpen = clientsMap[idSocket]; + + //Фиксируем время выхода Юнити-клиента + if(clientHandlerOpen->getClient()->getIsUnity()) + { + processingSystem->processingExitUnityClient(clientHandlerOpen); + } + + clientHandlerOpen->sigSendXmlAnswer(arrayAnswer, PacketType::TYPE_XMLANSWER); //while (!clientsMap[idSocket]->sigSocketFlush()) {} QString str = QString(arrayAnswer); emit sigLog("To Client: " + str); //slotDisconnectClient(clientsMap[idSocket]->get, QString peerPort) - processingSystem->processingClientDeAutorization(clientsMap[idSocket]->getClient()->getLogin()); + processingSystem->processingClientDeAutorization(clientHandlerOpen->getClient()->getLogin()); - clientsMap[idSocket]->sigSocketClose(); + clientHandlerOpen->sigSocketClose(); //clientsMap.remove(idSocket); removeClient(idSocket); }