From ba19db8715be59c18f49426655bdbcc0cd59538b Mon Sep 17 00:00:00 2001 From: jakubg1 <24206305+jakubg1@users.noreply.github.com> Date: Wed, 2 Sep 2026 12:32:35 +0200 Subject: [PATCH] Revert "Remove training card window" This reverts commit 363b50c9c278c5089cc8b8a6895b17ac8def03e2. --- CMakeLists.txt | 1 + application/driveruilayer.cpp | 18 +++- application/driveruilayer.h | 3 + utilities/Globals.cpp | 6 ++ utilities/Globals.h | 1 + widgets/trainingcard.cpp | 196 ++++++++++++++++++++++++++++++++++ widgets/trainingcard.h | 37 +++++++ widgets/vehiclelist.cpp | 15 +++ 8 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 widgets/trainingcard.cpp create mode 100644 widgets/trainingcard.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 03e57224..56cf1bce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,6 +200,7 @@ set(SOURCES "widgets/popup.cpp" "widgets/time.cpp" "widgets/vehicleparams.cpp" +"widgets/trainingcard.cpp" "widgets/perfgraphs.cpp" "${DEPS_DIR}/glad/src/glad.c" diff --git a/application/driveruilayer.cpp b/application/driveruilayer.cpp index 464b275b..0b8463f8 100644 --- a/application/driveruilayer.cpp +++ b/application/driveruilayer.cpp @@ -30,6 +30,7 @@ driver_ui::driver_ui() if (Global.gui_showtranscripts) add_external_panel(&m_transcriptspanel); + add_external_panel(&m_trainingcardpanel); add_external_panel(&m_vehiclelist); add_external_panel(&m_timepanel); add_external_panel(&m_mappanel); @@ -57,6 +58,13 @@ driver_ui::driver_ui() m_aidpanel.is_open = true; m_scenariopanel.is_open = true; } + + if (Global.gui_trainingdefault) + { + m_mappanel.is_open = true; + m_trainingcardpanel.is_open = true; + m_vehiclelist.is_open = true; + } } void driver_ui::render_menu_contents() @@ -71,6 +79,7 @@ void driver_ui::render_menu_contents() ImGui::MenuItem(m_debugpanel.name().c_str(), "F12", &m_debugpanel.is_open); ImGui::MenuItem(m_mappanel.name().c_str(), "Tab", &m_mappanel.is_open); ImGui::MenuItem(m_vehiclelist.name().c_str(), nullptr, &m_vehiclelist.is_open); + ImGui::MenuItem(m_trainingcardpanel.name().c_str(), nullptr, &m_trainingcardpanel.is_open); ImGui::MenuItem(m_cameraviewpanel.name().c_str(), nullptr, &m_cameraviewpanel.is_open); if (DebugModeFlag) ImGui::MenuItem(m_perfgraphpanel.name().c_str(), nullptr, &m_perfgraphpanel.is_open); @@ -228,7 +237,14 @@ void driver_ui::set_cursor(bool const Visible) // render() subclass details void driver_ui::render_() { - m_cameraviewpanel.set_state(false); + const std::string *rec_name = m_trainingcardpanel.is_recording(); + if (rec_name && m_cameraviewpanel.set_state(true)) + { + m_cameraviewpanel.rec_name = *rec_name; + m_cameraviewpanel.is_open = true; + } + else if (!rec_name) + m_cameraviewpanel.set_state(false); // pause/quit modal auto const popupheader{STR_C("Simulation Paused")}; diff --git a/application/driveruilayer.h b/application/driveruilayer.h index 830b4a6e..8ad1d775 100644 --- a/application/driveruilayer.h +++ b/application/driveruilayer.h @@ -14,8 +14,10 @@ http://mozilla.org/MPL/2.0/. #include "input/command.h" #include "widgets/vehiclelist.h" +#include "widgets/vehicleparams.h" #include "widgets/map.h" #include "widgets/time.h" +#include "widgets/trainingcard.h" #include "widgets/perfgraphs.h" #include "widgets/cameraview_extcam.h" @@ -58,6 +60,7 @@ private: timetable_panel m_timetablepanel { "Timetable", false }; debug_panel m_debugpanel { "Debug Data", false }; transcripts_panel m_transcriptspanel { "Transcripts", true }; // voice transcripts + trainingcard_panel m_trainingcardpanel; perfgraph_panel m_perfgraphpanel; bool m_paused { false }; diff --git a/utilities/Globals.cpp b/utilities/Globals.cpp index 379f6efb..332524fb 100644 --- a/utilities/Globals.cpp +++ b/utilities/Globals.cpp @@ -787,6 +787,12 @@ bool global_settings::ConfigParseUI(cParser& Parser, const std::string& token) return true; } + if (token == "gui.trainingdefault") + { + ParseOne(Parser, gui_trainingdefault, 1); + return true; + } + return false; } diff --git a/utilities/Globals.h b/utilities/Globals.h index ce4c2e04..729b7cbc 100644 --- a/utilities/Globals.h +++ b/utilities/Globals.h @@ -245,6 +245,7 @@ struct global_settings { bool crash_damage = true; bool gui_defaultwindows = true; bool gui_showtranscripts = true; + bool gui_trainingdefault = false; std::string extcam_cmd; std::string extcam_rec; diff --git a/widgets/trainingcard.cpp b/widgets/trainingcard.cpp new file mode 100644 index 00000000..d4d11e5b --- /dev/null +++ b/widgets/trainingcard.cpp @@ -0,0 +1,196 @@ +#include "stdafx.h" +#include "widgets/trainingcard.h" +#include "simulation/simulation.h" + +#ifdef __linux__ +#include +#include +#endif + +trainingcard_panel::trainingcard_panel() : ui_panel("Raport szkolenia", false) +{ + // size = {400, 500}; + clear(); +} + +trainingcard_panel::~trainingcard_panel() +{ + if (save_thread.joinable()) + save_thread.join(); +} + +void trainingcard_panel::clear() +{ + start_time_wall.reset(); + state.store(0); + recording_timestamp.clear(); + + place.clear(); + trainee_name.clear(); + trainee_birthdate.clear(); + trainee_company.clear(); + instructor_name.clear(); + track_segment.clear(); + remarks.clear(); + + distance = 0.0f; + + place.resize(256, 0); + trainee_name.resize(256, 0); + trainee_birthdate.resize(256, 0); + trainee_company.resize(256, 0); + instructor_name.resize(256, 0); + track_segment.resize(256, 0); + remarks.resize(4096, 0); +} + +void trainingcard_panel::save_thread_func() +{ + std::tm *tm = std::localtime(&(*start_time_wall)); + std::string date = std::to_string(tm->tm_year + 1900) + "-" + std::to_string(tm->tm_mon + 1) + "-" + std::to_string(tm->tm_mday); + std::string from = std::to_string(tm->tm_hour) + ":" + std::to_string(tm->tm_min); + std::time_t now = std::time(nullptr); + tm = std::localtime(&now); + std::string to = std::to_string(tm->tm_hour) + ":" + std::to_string(tm->tm_min); + + std::fstream temp("reports/" + recording_timestamp + ".html", std::ios_base::out | std::ios_base::binary); + std::fstream input("report_template.html", std::ios_base::in | std::ios_base::binary); + + std::string in_line; + while (std::getline(input, in_line)) + { + const std::string magic("{{CONTENT}}"); + if (in_line.compare(0, magic.size(), magic) == 0) + { + temp << "
Miejsce: " << (std::string(place.c_str())) << "

" << std::endl; + temp << "
Data: " << (date) << "

" << std::endl; + temp << "
Czas: " << (from) << " - " << (to) << "

" << std::endl; + temp << "
Imię (imiona) i nazwisko szkolonego: " << (trainee_name) << "

" << std::endl; + temp << "
Data urodzenia: " << (trainee_birthdate) << "

" << std::endl; + temp << "
Firma: " << (trainee_company) << "

" << std::endl; + temp << "
Imię i nazwisko instruktora: " << (instructor_name) << "

" << std::endl; + temp << "
Odcinek trasy: " << (track_segment) << "

" << std::endl; + if (distance > 0.0f) + temp << "
Przebyta odległość: " << std::round(distance) << " km

" << std::endl; + temp << "
Uwagi:
" << (remarks) << "
" << std::endl; + } + else + { + temp << in_line; + } + } + + input.close(); + temp.close(); + + state.store(EndRecording(recording_timestamp)); +} + +void trainingcard_panel::render_contents() +{ + if (ImGui::BeginPopupModal("Zapisywanie danych")) + { + ImGui::SetWindowSize(ImVec2(-1, -1)); + int s = state.load(); + + if (s == 1) + { + ImGui::CloseCurrentPopup(); + clear(); + } + + if (s < 1) + { + if (s == 0) + ImGui::TextUnformatted("Error occured please contact with administrator!"); + if (s == -1) + ImGui::TextUnformatted("The recording of the training has not been archived, please do not start the next training before manually archiving the file!"); + + if (ImGui::Button("OK")) + { + ImGui::CloseCurrentPopup(); + clear(); + } + } + + if (s == 2) + ImGui::TextUnformatted("Proszę czekać, trwa archiwizacja nagrania..."); + + ImGui::EndPopup(); + } + + if (start_time_wall) + { + std::tm *tm = std::localtime(&(*start_time_wall)); + std::string rep = "Czas rozpoczęcia: " + std::to_string(tm->tm_year + 1900) + "-" + std::to_string(tm->tm_mon + 1) + "-" + std::to_string(tm->tm_mday) + " " + std::to_string(tm->tm_hour) + + ":" + std::to_string(tm->tm_min); + ImGui::TextUnformatted(rep.c_str()); + } + + ImGui::TextUnformatted("Miejsce:"); + ImGui::SameLine(); + ImGui::InputText("##place", &place[0], place.size()); + + ImGui::TextUnformatted("Szkolony:"); + ImGui::SameLine(); + ImGui::InputText("##trainee", &trainee_name[0], trainee_name.size()); + + ImGui::TextUnformatted("Data urodzenia:"); + ImGui::SameLine(); + ImGui::InputText("##birthdate", &trainee_birthdate[0], trainee_birthdate.size()); + + ImGui::TextUnformatted("Firma:"); + ImGui::SameLine(); + ImGui::InputText("##company", &trainee_company[0], trainee_company.size()); + + ImGui::TextUnformatted("Instruktor:"); + ImGui::SameLine(); + ImGui::InputText("##instructor", &instructor_name[0], instructor_name.size()); + + ImGui::TextUnformatted("Odcinek trasy:"); + ImGui::SameLine(); + ImGui::InputText("##segment", &track_segment[0], track_segment.size()); + + ImGui::TextUnformatted("Uwagi"); + ImGui::InputTextMultiline("##remarks", &remarks[0], remarks.size(), ImVec2(-1.0f, 200.0f)); + + if (!start_time_wall) + { + if (ImGui::Button("Rozpocznij szkolenie")) + { + start_time_wall = std::time(nullptr); + std::tm *tm = std::localtime(&(*start_time_wall)); + recording_timestamp = std::to_string(tm->tm_year + 1900) + std::to_string(tm->tm_mon + 1) + std::to_string(tm->tm_mday) + std::to_string(tm->tm_hour) + std::to_string(tm->tm_min) + "_" + + std::string(trainee_name.c_str()) + "_" + std::string(instructor_name.c_str()); + + int ret = StartRecording(); + if (ret != 1) + { + state.store(ret); + ImGui::OpenPopup("Zapisywanie danych"); + } + } + } + else + { + if (ImGui::Button("Zakończ szkolenie")) + { + state.store(2); + if (simulation::Trains.sequence().size() > 0) + distance = simulation::Trains.sequence()[0]->Dynamic()->MoverParameters->DistCounter; + + if (save_thread.joinable()) + save_thread.join(); + save_thread = std::thread(&trainingcard_panel::save_thread_func, this); + ImGui::OpenPopup("Zapisywanie danych"); + } + } +} + +const std::string *trainingcard_panel::is_recording() +{ + if (!start_time_wall) + return nullptr; + + return &recording_timestamp; +} diff --git a/widgets/trainingcard.h b/widgets/trainingcard.h new file mode 100644 index 00000000..9e4eafe9 --- /dev/null +++ b/widgets/trainingcard.h @@ -0,0 +1,37 @@ +#include "application/uilayer.h" + +class trainingcard_panel : public ui_panel +{ + std::string place; + std::string trainee_name; + std::string trainee_birthdate; + std::string trainee_company; + std::string instructor_name; + std::string track_segment; + std::string remarks; + + std::optional start_time_wall; + float distance = 0.0f; + + std::thread save_thread; + std::atomic state; + + void save_thread_func(); + void clear(); + + virtual int StartRecording( void ) { + return 1; + } + virtual int EndRecording( std::string training_identifier ) { + return 1; + } + + public: + trainingcard_panel(); + ~trainingcard_panel(); + + void render_contents() override; + const std::string *is_recording(); + + std::string recording_timestamp; +}; diff --git a/widgets/vehiclelist.cpp b/widgets/vehiclelist.cpp index 2af79086..e8ee1e12 100644 --- a/widgets/vehiclelist.cpp +++ b/widgets/vehiclelist.cpp @@ -11,6 +11,21 @@ ui::vehiclelist_panel::vehiclelist_panel(ui_layer &parent) void ui::vehiclelist_panel::render_contents() { + if (m_first_show && Global.gui_trainingdefault) { + for (TDynamicObject *vehicle : simulation::Vehicles.sequence()) + { + if (!vehicle->Mechanik || vehicle->name() != ToLower(Global.local_start_vehicle)) + continue; + + ui_panel *panel = new vehicleparams_panel(vehicle->name()); + m_parent.add_owned_panel(panel); + } + + m_first_show = false; + is_open = false; + return; + } + for (TDynamicObject *vehicle : simulation::Vehicles.sequence()) { if (!vehicle->Mechanik)