From b1ceee88ff01fd20d39533b52d80f8fd29f15c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=A1=D1=82?= =?UTF-8?q?=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Sun, 14 May 2023 14:15:17 +0300 Subject: [PATCH] Create mvp for http_server, http_client and gui --- client/internal/CMakeLists.txt | 10 ++-- client/internal/core/CMakeLists.txt | 6 +- client/internal/core/include/Core.h | 9 ++- client/internal/core/src/Core.cpp | 22 +++++-- client/internal/entities/include/Solution.h | 1 + client/internal/entities/src/Task.cpp | 2 +- client/internal/gui/CMakeLists.txt | 4 +- client/internal/gui/include/AddTaskDialog.h | 29 +++++++++ client/internal/gui/include/SolutionsWindow.h | 2 +- client/internal/gui/include/TasksWindow.h | 3 + client/internal/gui/src/AddTaskDialog.cpp | 60 +++++++++++++++++++ client/internal/gui/src/AuthDialog.cpp | 8 +-- client/internal/gui/src/SignUpDialog.cpp | 19 +++--- client/internal/gui/src/SolutionsWindow.cpp | 15 ++--- client/internal/gui/src/TasksWindow.cpp | 48 +++++++++------ .../internal/httpClient/include/HttpClient.h | 3 +- .../httpClient/include/HttpClientManager.h | 5 +- .../internal/httpClient/include/Serializer.h | 7 +++ client/internal/httpClient/src/HttpClient.cpp | 15 +++-- .../httpClient/src/HttpClientManager.cpp | 37 +++++++++--- client/internal/httpClient/src/Serializer.cpp | 49 +++++++++++++++ .../internal/httpServer/include/Serializer.h | 1 + .../httpServer/include/SolutionManager.h | 1 - .../internal/httpServer/include/TaskManager.h | 5 +- .../httpServer/include/TmpSolutionService.h | 25 ++++++++ .../httpServer/include/TmpTaskService.h | 40 +++++++++++++ .../httpServer/include/TmpUserService.h | 34 +++++++++++ server/internal/httpServer/src/Router.cpp | 4 -- server/internal/httpServer/src/Serializer.cpp | 12 +++- .../httpServer/src/SolutionManager.cpp | 25 ++------ .../internal/httpServer/src/TaskManager.cpp | 7 ++- .../internal/httpServer/src/UserManager.cpp | 22 +++---- .../httpServer/virtual/ISolutionManager.h | 1 - 33 files changed, 405 insertions(+), 126 deletions(-) create mode 100644 client/internal/gui/include/AddTaskDialog.h create mode 100644 client/internal/gui/src/AddTaskDialog.cpp create mode 100644 server/internal/httpServer/include/TmpSolutionService.h create mode 100644 server/internal/httpServer/include/TmpTaskService.h create mode 100644 server/internal/httpServer/include/TmpUserService.h diff --git a/client/internal/CMakeLists.txt b/client/internal/CMakeLists.txt index 790ec14..b540366 100644 --- a/client/internal/CMakeLists.txt +++ b/client/internal/CMakeLists.txt @@ -1,7 +1,7 @@ add_subdirectory(entities) add_subdirectory(httpClient) -add_subdirectory(gui) add_subdirectory(core) +add_subdirectory(gui) set(libClientEntities_LIB ${libClientEntities_LIB} PARENT_SCOPE) set(libClientEntities_INCLUDE_DIRS ${libClientEntities_INCLUDE_DIRS} PARENT_SCOPE) @@ -9,8 +9,8 @@ set(libClientEntities_INCLUDE_DIRS ${libClientEntities_INCLUDE_DIRS} PARENT_SCOP set(HTTPCLIENT_lib_LIB ${HTTPCLIENT_lib_LIB} PARENT_SCOPE) set(HTTPCLIENT_lib_INCLUDE_DIRS ${HTTPCLIENT_lib_INCLUDE_DIRS} PARENT_SCOPE) -set(GUI_lib_LIB ${GUI_lib_LIB} PARENT_SCOPE) -set(GUI_lib_INCLUDE_DIRS ${GUI_lib_INCLUDE_DIRS} PARENT_SCOPE) - set(CORE_lib_LIB ${CORE_lib_LIB} PARENT_SCOPE) -set(CORE_lib_INCLUDE_DIRS ${CORE_lib_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file +set(CORE_lib_INCLUDE_DIRS ${CORE_lib_INCLUDE_DIRS} PARENT_SCOPE) + +set(GUI_lib_LIB ${GUI_lib_LIB} PARENT_SCOPE) +set(GUI_lib_INCLUDE_DIRS ${GUI_lib_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file diff --git a/client/internal/core/CMakeLists.txt b/client/internal/core/CMakeLists.txt index 8a2af66..a493beb 100644 --- a/client/internal/core/CMakeLists.txt +++ b/client/internal/core/CMakeLists.txt @@ -6,13 +6,13 @@ file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) file(GLOB INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) file(GLOB INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) -include_directories(${INCLUDE_DIRS} ${libClientEntities_INCLUDE_DIRS} ${HTTPCLIENT_lib_INCLUDE_DIRS}) +include_directories(${INCLUDE_DIRS} ${libClientEntities_INCLUDE_DIRS} ${HTTPCLIENT_lib_INCLUDE_DIRS} ${Boost_INCLUDE_DIR}) add_library(${PROJECT_NAME} ${SOURCES} ${INCLUDES}) -target_link_libraries(${PROJECT_NAME} ${libClientEntities_LIB} ${HTTPCLIENT_lib_LIB}) +target_link_libraries(${PROJECT_NAME} ${libClientEntities_LIB} ${HTTPCLIENT_lib_LIB} ${Boost_LIBRARIES}) set(CORE_lib_LIB ${PROJECT_NAME}) set(CORE_lib_LIB ${CORE_lib_LIB} PARENT_SCOPE) -set(CORE_lib_INCLUDE_DIRS ${INCLUDE_DIRS}) +set(CORE_lib_INCLUDE_DIRS ${LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/include) set(CORE_lib_INCLUDE_DIRS ${CORE_lib_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file diff --git a/client/internal/core/include/Core.h b/client/internal/core/include/Core.h index d88af4d..f28be4a 100644 --- a/client/internal/core/include/Core.h +++ b/client/internal/core/include/Core.h @@ -4,15 +4,20 @@ #include #include "Task.h" +#include "Solution.h" class Core { public: - Core() { user_id = -1; }; - static unsigned signUp(const std::string &login, const std::string &username, const std::string &pass); static unsigned login(const std::string &login, const std::string &pass); + static std::vector getAllTasks(); + + static Solution submitSolution(const int& task_id, const std::string& path_to_file); + + static unsigned int createTask(const std::string &desc); + static void logout(); private: diff --git a/client/internal/core/src/Core.cpp b/client/internal/core/src/Core.cpp index bf3d43d..52baa40 100644 --- a/client/internal/core/src/Core.cpp +++ b/client/internal/core/src/Core.cpp @@ -5,22 +5,36 @@ #include "HttpClientManager.h" const std::string CLIENT_IP = "0.0.0.0"; -const std::string CLIENT_PORT = "80"; +const std::string CLIENT_PORT = "8080"; HttpClientManager client(CLIENT_IP, CLIENT_PORT); +std::size_t Core::user_id = -1; + unsigned Core::signUp(const std::string &login, const std::string &username, const std::string &pass) { auto res = client.registerUser(login, username, pass); - user_id = res.second.id; + Core::user_id = res.second.id; return res.first; } unsigned Core::login(const std::string &login, const std::string &pass) { auto res = client.loginUser(login, pass); - user_id = res.second.id; + Core::user_id = res.second.id; return res.first; } void Core::logout() { - user_id = -1; + Core::user_id = -1; +} + +std::vector Core::getAllTasks() { + return client.getAllTasks(); +} + +Solution Core::submitSolution(const int &task_id, const std::string &path_to_file) { + return client.submitSolution(user_id, task_id, path_to_file); +} + +unsigned int Core::createTask(const std::string &desc) { + return client.createTask(desc); } diff --git a/client/internal/entities/include/Solution.h b/client/internal/entities/include/Solution.h index 384e648..4cf7061 100644 --- a/client/internal/entities/include/Solution.h +++ b/client/internal/entities/include/Solution.h @@ -7,4 +7,5 @@ struct Solution { size_t id; std::string source; + std::string result; }; \ No newline at end of file diff --git a/client/internal/entities/src/Task.cpp b/client/internal/entities/src/Task.cpp index 496fddc..e1de440 100644 --- a/client/internal/entities/src/Task.cpp +++ b/client/internal/entities/src/Task.cpp @@ -1,3 +1,3 @@ #include "Task.h" -Task::Task(std::size_t id, std::string_view desc) : id(id), description(desc); \ No newline at end of file +Task::Task(std::size_t id, std::string_view desc) : id(id), description(desc) {}; \ No newline at end of file diff --git a/client/internal/gui/CMakeLists.txt b/client/internal/gui/CMakeLists.txt index 1f206bf..419c4dd 100644 --- a/client/internal/gui/CMakeLists.txt +++ b/client/internal/gui/CMakeLists.txt @@ -12,10 +12,10 @@ file(GLOB INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) set(CMAKE_PREFIX_PATH "~/Qt/6.5.0/macos/lib/cmake") find_package(Qt6 REQUIRED COMPONENTS Widgets Core Gui) -include_directories(${INCLUDE_DIRS} ${libClientEntities_INCLUDE_DIRS}) +include_directories(${INCLUDE_DIRS} ${libClientEntities_INCLUDE_DIRS} ${CORE_lib_INCLUDE_DIRS}) add_library(${PROJECT_NAME} ${SOURCES} ${INCLUDES}) -target_link_libraries(${PROJECT_NAME} ${libClientEntities_LIB} Qt6::Widgets Qt6::Core Qt6::Gui) +target_link_libraries(${PROJECT_NAME} ${libClientEntities_LIB} ${CORE_lib_LIB} Qt6::Widgets Qt6::Core Qt6::Gui) set(GUI_lib_LIB ${PROJECT_NAME}) set(GUI_lib_LIB ${GUI_lib_LIB} PARENT_SCOPE) diff --git a/client/internal/gui/include/AddTaskDialog.h b/client/internal/gui/include/AddTaskDialog.h new file mode 100644 index 0000000..c5b6547 --- /dev/null +++ b/client/internal/gui/include/AddTaskDialog.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +class AddTaskDialog : public QDialog { +Q_OBJECT + +public: + explicit AddTaskDialog(QWidget *parent = nullptr); + +public slots: + void on_createButton_clicked(); + void on_backButton_clicked(); + +private: + QVBoxLayout* verticalLayout = nullptr; + QLabel* label = nullptr; + QTextEdit* editor = nullptr; + QPushButton *createButton = nullptr; + QPushButton *backButton = nullptr; + + void setupUi(QDialog *AddTaskDialog); +}; diff --git a/client/internal/gui/include/SolutionsWindow.h b/client/internal/gui/include/SolutionsWindow.h index 103c2fb..80544e5 100644 --- a/client/internal/gui/include/SolutionsWindow.h +++ b/client/internal/gui/include/SolutionsWindow.h @@ -26,7 +26,7 @@ private slots: private: Task task; - std::string source; + std::string path_to_file; QWidget *centralwidget = nullptr; QGroupBox* taskBox = nullptr; diff --git a/client/internal/gui/include/TasksWindow.h b/client/internal/gui/include/TasksWindow.h index c8f96bd..1a897fd 100644 --- a/client/internal/gui/include/TasksWindow.h +++ b/client/internal/gui/include/TasksWindow.h @@ -20,6 +20,7 @@ public: public slots: void on_backButton_clicked(); + void on_addTaskButton_clicked(); void on_goToTaskButton_clicked(); void indexChanged(); @@ -33,6 +34,7 @@ private: QComboBox* tasks = nullptr; QLabel* taskDescription = nullptr; QPushButton* goToTaskButton = nullptr; + QPushButton* addTaskButton = nullptr; QPushButton* backButton = nullptr; QWidget* buttonsWidget = nullptr; QHBoxLayout* buttonsLayout = nullptr; @@ -40,6 +42,7 @@ private: std::vector tasks_vector; void setupUi(QMainWindow *UserWindow); + void updateTasks(); }; #endif // USERWINDOW_H diff --git a/client/internal/gui/src/AddTaskDialog.cpp b/client/internal/gui/src/AddTaskDialog.cpp new file mode 100644 index 0000000..3fefa31 --- /dev/null +++ b/client/internal/gui/src/AddTaskDialog.cpp @@ -0,0 +1,60 @@ +#include "AddTaskDialog.h" + +#include +#include + +#include "Core.h" + +AddTaskDialog::AddTaskDialog(QWidget *parent) : QDialog(parent) { + setupUi(this); + + connect(createButton, &QPushButton::clicked, this, &AddTaskDialog::on_createButton_clicked); + connect(backButton, &QPushButton::clicked, this, &AddTaskDialog::on_backButton_clicked); +} + +void AddTaskDialog::setupUi(QDialog *AddTaskDialog) { + QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(AddTaskDialog->sizePolicy().hasHeightForWidth()); + AddTaskDialog->setSizePolicy(sizePolicy); + + verticalLayout = new QVBoxLayout(AddTaskDialog); + + label = new QLabel(AddTaskDialog); + label->setText(QString::fromUtf8("Введите текст задания")); + verticalLayout->addWidget(label); + + editor = new QTextEdit(AddTaskDialog); + verticalLayout->addWidget(editor); + + createButton = new QPushButton(AddTaskDialog); + createButton->setText(QString::fromUtf8("Создать задание")); + verticalLayout->addWidget(createButton); + + backButton = new QPushButton(AddTaskDialog); + backButton->setText(QString::fromUtf8("Назад")); + verticalLayout->addWidget(backButton); +} + +void AddTaskDialog::on_createButton_clicked() { + std::string desc = editor->toPlainText().toUtf8().constData(); + if (desc.empty()) { + QMessageBox::warning(this, "Ошибка отправки", "Описание не может быть пустыми"); + return; + } + unsigned result = Core::createTask(desc); + switch (result) { + case 200: + accept(); + close(); + break; + default: + QMessageBox::critical(this, "Отправка невозможна", "Нет соединения с сервером"); + } +} + +void AddTaskDialog::on_backButton_clicked() { + reject(); + close(); +} diff --git a/client/internal/gui/src/AuthDialog.cpp b/client/internal/gui/src/AuthDialog.cpp index 5227149..2f35768 100644 --- a/client/internal/gui/src/AuthDialog.cpp +++ b/client/internal/gui/src/AuthDialog.cpp @@ -3,6 +3,8 @@ #include #include +#include "Core.h" + AuthDialog::AuthDialog(QWidget *parent) : QDialog(parent) { setupUi(this); } @@ -64,15 +66,13 @@ void AuthDialog::on_loginButton_clicked() { QMessageBox::warning(this, "Ошибка авторизации", "Логин и пароль не могут быть пустыми"); return; } -// unsigned result = Core::login(log, pass); - unsigned result = 200; + unsigned result = Core::login(std::string(log), std::string(pass)); switch (result) { case 200: - QMessageBox::warning(this, "Успешная авторизации", "Работает"); accept(); close(); break; - case 403: + case 404: QMessageBox::warning(this, "Ошибка авторизации","Неправильный логин или пароль"); break; default: diff --git a/client/internal/gui/src/SignUpDialog.cpp b/client/internal/gui/src/SignUpDialog.cpp index 015f65f..1cdc2a3 100644 --- a/client/internal/gui/src/SignUpDialog.cpp +++ b/client/internal/gui/src/SignUpDialog.cpp @@ -4,7 +4,7 @@ #include #include -//#include "Core.h" +#include "Core.h" SignUpDialog::SignUpDialog(QWidget *parent) : QDialog(parent) { setupUi(this); @@ -74,13 +74,12 @@ void SignUpDialog::retranslateUi(QDialog *SignUpDialog) { } void SignUpDialog::on_signUpButton_clicked() { - std::string login = this->login->text().toUtf8().constData(); - std::string username = this->username->text().toUtf8().constData(); - std::string password = this->password->text().toUtf8().constData(); - std::string passwordRepeat = this->passwordRepeat->text().toUtf8().constData(); - if (password == passwordRepeat && !login.empty() && !username.empty()) { -// unsigned response = Core::signUp(log.toStdString(), pass.toStdString()); - unsigned response = 200; + std::string log = this->login->text().toUtf8().constData(); + std::string usr = this->username->text().toUtf8().constData(); + std::string pass = this->password->text().toUtf8().constData(); + std::string passRepeat = this->passwordRepeat->text().toUtf8().constData(); + if (pass == passRepeat && !log.empty() && !usr.empty()) { + unsigned response = Core::signUp(log, usr, pass); switch (response) { case 200: QMessageBox::information(this, "Успех!", "Вы успешно зарегистрированы!"); @@ -94,9 +93,9 @@ void SignUpDialog::on_signUpButton_clicked() { QMessageBox::critical(this, "Регистрация невозможна!", "Нет соединения с сервером!"); } - } else if (login.empty()) { + } else if (log.empty()) { QMessageBox::warning(this, "Ошибка!", "Логин не может быть пустым!"); - } else if (username.empty()) { + } else if (usr.empty()) { QMessageBox::warning(this, "Ошибка!", "Имя не может быть пустым!"); } else { QMessageBox::warning(this, "Ошибка!", "Пароли не совпадают!"); diff --git a/client/internal/gui/src/SolutionsWindow.cpp b/client/internal/gui/src/SolutionsWindow.cpp index 33743ee..17832a3 100644 --- a/client/internal/gui/src/SolutionsWindow.cpp +++ b/client/internal/gui/src/SolutionsWindow.cpp @@ -5,6 +5,9 @@ #include #include +#include "Solution.h" +#include "Core.h" + SolutionsWindow::SolutionsWindow(Task task, QWidget *parent) : QMainWindow(parent), task(std::move(task)) { setupUi(this); connect(backButton, &QPushButton::clicked, this, &SolutionsWindow::on_backButton_clicked); @@ -63,18 +66,12 @@ void SolutionsWindow::on_backButton_clicked() { void SolutionsWindow::on_chooseFileButton_clicked() { QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to send"), QDir::homePath()); filename->setText(QFileInfo(fileName).fileName()); - std::ifstream file(fileName.toUtf8().constData()); - std::ostringstream sstr; - sstr << file.rdbuf(); - source = sstr.str(); + path_to_file = fileName.toUtf8().constData(); } void SolutionsWindow::on_sendButton_clicked() { - if (source.empty()) { - QMessageBox::warning(this, "Ошибка отправки", "Нельзя отправить пустое решение"); - return; - } - std::cout << source; + Solution sol = Core::submitSolution(task.id, path_to_file); + result->setText(QString::fromStdString(sol.result)); } diff --git a/client/internal/gui/src/TasksWindow.cpp b/client/internal/gui/src/TasksWindow.cpp index f5c4884..04cebc7 100644 --- a/client/internal/gui/src/TasksWindow.cpp +++ b/client/internal/gui/src/TasksWindow.cpp @@ -5,36 +5,23 @@ #include #include "SolutionsWindow.h" +#include "AddTaskDialog.h" #include "UIManager.h" +#include "Core.h" TasksWindow::TasksWindow(QWidget *parent) : QMainWindow(parent) { - tasks_vector.push_back({1, "1 description 1\n" - "1\n" - "2\n" - "3\n" - "4\n" - "5\n" - "6\n" - "7\n" - "8\n" - "9\n" - "10\n" - "11\n" - "12\n" - "13\n" - "14\n"}); - tasks_vector.push_back({2, "2 description"}); - tasks_vector.push_back({3, "3 description"}); - setupUi(this); connect(tasks, &QComboBox::currentIndexChanged, this, &TasksWindow::indexChanged); connect(goToTaskButton, &QPushButton::clicked, this, &TasksWindow::on_goToTaskButton_clicked); connect(backButton, &QPushButton::clicked, this, &TasksWindow::on_backButton_clicked); + connect(addTaskButton, &QPushButton::clicked, this, &TasksWindow::on_addTaskButton_clicked); } void TasksWindow::setupUi(QMainWindow *UserWindow) { + tasks_vector = Core::getAllTasks(); + QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); @@ -76,10 +63,14 @@ void TasksWindow::setupUi(QMainWindow *UserWindow) { goToTaskButton = new QPushButton(this); goToTaskButton->setText(QString::fromUtf8("Перейти к сдаче")); + addTaskButton = new QPushButton(this); + addTaskButton->setText(QString::fromUtf8("Добавить задание")); + backButton = new QPushButton(this); backButton->setText(QString::fromUtf8("Выйти")); buttonsLayout->addWidget(goToTaskButton); + buttonsLayout->addWidget(addTaskButton); buttonsLayout->addWidget(backButton); verticalLayout->addWidget(taskChooseGroupBox); @@ -95,7 +86,7 @@ void TasksWindow::indexChanged() { } void TasksWindow::on_backButton_clicked() { - // Core::logout(); + Core::logout(); close(); qobject_cast(parent())->showEntryWindow(); } @@ -105,3 +96,22 @@ void TasksWindow::on_goToTaskButton_clicked() { auto* solutionsWindow = new SolutionsWindow(tasks_vector[tasks->currentIndex()], this); solutionsWindow->show(); } + +void TasksWindow::on_addTaskButton_clicked() { + AddTaskDialog addTaskDialog(this); + if (addTaskDialog.exec() == QDialog::Accepted) { + updateTasks(); + } +} + +void TasksWindow::updateTasks() { + tasks_vector = Core::getAllTasks(); + tasks->clear(); + for (int i = 0; i < tasks_vector.size(); i++) { + tasks->insertItem(i, QString::number(tasks_vector[i].id)); + } + tasks->setCurrentIndex(0); + + std::string description = tasks_vector[0].description; + taskDescription->setText(QString(description.c_str())); +} diff --git a/client/internal/httpClient/include/HttpClient.h b/client/internal/httpClient/include/HttpClient.h index 058c2b4..42c5f6d 100644 --- a/client/internal/httpClient/include/HttpClient.h +++ b/client/internal/httpClient/include/HttpClient.h @@ -16,7 +16,7 @@ using tcp = net::ip::tcp; class HttpClient : public IHttpClient { public: - HttpClient(std::string_view host, std::string_view port); + HttpClient(std::string_view host_, std::string_view port_); http::response makeGetRequest(std::string_view target, std::string_view body) override; http::response makePostRequest(std::string_view target, std::string_view body) override; @@ -29,6 +29,7 @@ private: tcp::resolver resolver; beast::tcp_stream stream; std::string host; + std::string port; }; diff --git a/client/internal/httpClient/include/HttpClientManager.h b/client/internal/httpClient/include/HttpClientManager.h index eb93fcb..80e73b9 100644 --- a/client/internal/httpClient/include/HttpClientManager.h +++ b/client/internal/httpClient/include/HttpClientManager.h @@ -19,10 +19,11 @@ public: std::pair loginUser(const std::string &login, const std::string &password); std::pair registerUser(const std::string &login, const std::string &username, const std::string &password); - unsigned int submitSolution(const int& user_id, const std::string &path_to_solution); + Solution submitSolution(const int& user_id, const int &task_id, const std::string &path_to_solution); unsigned int getAllSolutionsForTask(const int& user_id, const int& task_id); std::vector getAllTasks(); - std::vector getMetrics(const int& sol_id); + unsigned int createTask(const std::string& desc); +// std::vector getMetrics(const int& sol_id); void setHttpClient(std::shared_ptr client_); private: std::string host; diff --git a/client/internal/httpClient/include/Serializer.h b/client/internal/httpClient/include/Serializer.h index 42be6c8..80bdb42 100644 --- a/client/internal/httpClient/include/Serializer.h +++ b/client/internal/httpClient/include/Serializer.h @@ -4,11 +4,18 @@ #include #include #include "User.h" +#include "Task.h" +#include "Solution.h" class Serializer { public: std::string serialLoginData(std::string_view login, std::string_view password); std::string serialRegisterData(std::string_view login, std::string_view username, std::string_view password); + std::string serialSolutionData(const int& user_id, const int& task_id, const std::string& path_to_file); + std::string serialNewTaskData(std::string_view desc); + User deserialUserData(std::string_view body); + Solution deserialSolutionData(std::string_view body); + std::vector deserialAllTasks(std::string_view body); }; diff --git a/client/internal/httpClient/src/HttpClient.cpp b/client/internal/httpClient/src/HttpClient.cpp index d9f09fe..2dd0245 100644 --- a/client/internal/httpClient/src/HttpClient.cpp +++ b/client/internal/httpClient/src/HttpClient.cpp @@ -3,20 +3,23 @@ #include #include -HttpClient::HttpClient(std::string_view host_, std::string_view port) : +HttpClient::HttpClient(std::string_view host_, std::string_view port_) : host(host_), + port(port_), resolver(io_context), - stream(io_context) { - auto const results = resolver.resolve(host, port); - stream.connect(results); -} + stream(io_context) {} http::response HttpClient::makeRequest(std::string_view target, http::verb method, std::string_view body) { - http::request req{http::verb::get, target, 10}; + auto const results = resolver.resolve(host, port); + stream.connect(results); + http::request req{http::verb::get, target, 11}; req.set(http::field::host, host); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + req.set(http::field::content_type, "text/plain"); + req.content_length(body.size()); + req.body() = body; http::write(stream, req); diff --git a/client/internal/httpClient/src/HttpClientManager.cpp b/client/internal/httpClient/src/HttpClientManager.cpp index a269f65..7d6da4f 100644 --- a/client/internal/httpClient/src/HttpClientManager.cpp +++ b/client/internal/httpClient/src/HttpClientManager.cpp @@ -20,7 +20,9 @@ std::pair HttpClientManager::loginUser(const std::string &login, auto* cbuf = boost::asio::buffer_cast(seq); res_body.append(cbuf, boost::asio::buffer_size(seq)); } - User user = serializer->deserialUserData(res_body); + User user{0, "", "", ""}; + if (status == 200) + user = serializer->deserialUserData(res_body); return {status, user}; } @@ -38,22 +40,41 @@ std::pair HttpClientManager::registerUser(const std::string &log return {status, user}; } -unsigned int HttpClientManager::submitSolution(const int &user_id, const std::string &path_to_sound) { - return 0; +Solution HttpClientManager::submitSolution(const int &user_id, const int &task_id, const std::string &path_to_sound) { + std::string body = serializer->serialSolutionData(user_id, task_id, path_to_sound); + http::response res = client->makeGetRequest("/solution/submit", body); + unsigned status = res.result_int(); + std::string res_body; + for (auto seq : res.body().data()) { + auto* cbuf = boost::asio::buffer_cast(seq); + res_body.append(cbuf, boost::asio::buffer_size(seq)); + } + Solution sol = serializer->deserialSolutionData(res_body); + return sol; } unsigned int HttpClientManager::getAllSolutionsForTask(const int &user_id, const int &task_id) { return 0; } -std::vector HttpClientManager::getMetrics(const int &sol_id) { - return std::vector(); -} - void HttpClientManager::setHttpClient(std::shared_ptr client_) { client = client_; } std::vector HttpClientManager::getAllTasks() { - return std::vector(); + http::response res = client->makeGetRequest("/task/all", ""); + std::string res_body; + for (auto seq : res.body().data()) { + auto* cbuf = boost::asio::buffer_cast(seq); + res_body.append(cbuf, boost::asio::buffer_size(seq)); + } + std::vector tasks = serializer->deserialAllTasks(res_body); + return tasks; +} + +unsigned int HttpClientManager::createTask(const std::string &desc) { + std::string body = serializer->serialNewTaskData(desc); + http::response res = client->makeGetRequest("/task/create", body); + unsigned int result = res.result_int(); + return result; } diff --git a/client/internal/httpClient/src/Serializer.cpp b/client/internal/httpClient/src/Serializer.cpp index c2d5567..e76eca4 100644 --- a/client/internal/httpClient/src/Serializer.cpp +++ b/client/internal/httpClient/src/Serializer.cpp @@ -1,6 +1,7 @@ #include "Serializer.h" #include +#include #include #include @@ -37,3 +38,51 @@ Serializer::serialRegisterData(std::string_view login, std::string_view username boost::property_tree::write_json(out, json); return out.str(); } + +std::vector Serializer::deserialAllTasks(std::string_view body) { + std::stringstream ss; + ss << body; + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + std::vector tasks; + for (auto &sound : json.get_child("tasks")) { + Task new_task(sound.second.get("task_id"), sound.second.get("description")); + tasks.push_back(new_task); + } + return tasks; +} + +std::string Serializer::serialSolutionData(const int &user_id, const int &task_id, const std::string& path_to_file) { + boost::property_tree::ptree json; + json.put("user_id", user_id); + json.put("task_id", task_id); + std::ifstream file(path_to_file); + std::ostringstream sstr; + sstr << file.rdbuf(); + std::string source = sstr.str(); + json.put("source", source); + std::stringstream out; + boost::property_tree::write_json(out, json); + return out.str(); +} + +Solution Serializer::deserialSolutionData(std::string_view body) { + std::stringstream ss; + ss << body; + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + Solution res = { + json.get("sol_id"), + json.get("source"), + json.get("result"), + }; + return res; +} + +std::string Serializer::serialNewTaskData(std::string_view desc) { + boost::property_tree::ptree json; + json.put("description", desc); + std::stringstream out; + boost::property_tree::write_json(out, json); + return out.str(); +} diff --git a/server/internal/httpServer/include/Serializer.h b/server/internal/httpServer/include/Serializer.h index 9af1b01..19120d1 100644 --- a/server/internal/httpServer/include/Serializer.h +++ b/server/internal/httpServer/include/Serializer.h @@ -21,6 +21,7 @@ public: std::string serialSolutions(const std::vector& solutions); std::string serialAllTasks(const std::vector& tasks); std::string serialUserData(const User& user); + std::string serialSolution(const Solution& sol); }; diff --git a/server/internal/httpServer/include/SolutionManager.h b/server/internal/httpServer/include/SolutionManager.h index 2c69a61..166aee3 100644 --- a/server/internal/httpServer/include/SolutionManager.h +++ b/server/internal/httpServer/include/SolutionManager.h @@ -17,7 +17,6 @@ class SolutionManager : public ISolutionManager { SolutionManager(); http::message_generator getAllSolutions(http::request&& req) override; http::message_generator createSolution(http::request&& req) override; - http::message_generator getMetrics(http::request&& req) override; void setService(std::shared_ptr service); private: diff --git a/server/internal/httpServer/include/TaskManager.h b/server/internal/httpServer/include/TaskManager.h index 3adecd4..361c7a8 100644 --- a/server/internal/httpServer/include/TaskManager.h +++ b/server/internal/httpServer/include/TaskManager.h @@ -1,5 +1,4 @@ -#ifndef APP_HTTPSERVER_HTTPSERVER_MANAGERS_TaskMANAGER_H_ -#define APP_HTTPSERVER_HTTPSERVER_MANAGERS_TaskMANAGER_H_ +#pragma once #include #include @@ -18,5 +17,3 @@ private: std::shared_ptr taskService; std::shared_ptr serializer; }; - -#endif // APP_HTTPSERVER_HTTPSERVER_MANAGERS_TaskMANAGER_H_ diff --git a/server/internal/httpServer/include/TmpSolutionService.h b/server/internal/httpServer/include/TmpSolutionService.h new file mode 100644 index 0000000..63cab8d --- /dev/null +++ b/server/internal/httpServer/include/TmpSolutionService.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include "Solution.hpp" + +class TmpSolutionService { +public: + static Solution createSolution(std::size_t user_id, std::size_t task_id, std::string source) { + count++; + Solution sol(count, "", user_id, source, "", "", task_id, "ok"); + for (auto& i: solutions) { + if (i.getSource() == source && i.getTaskId() == task_id && i.getSenderId() != user_id) + sol.setResult("plagiat"); + } + solutions.push_back(sol); + return sol; + } + + static std::size_t count; + static std::vector solutions; +}; + +std::vector TmpSolutionService::solutions = {}; +std::size_t TmpSolutionService::count = 3; diff --git a/server/internal/httpServer/include/TmpTaskService.h b/server/internal/httpServer/include/TmpTaskService.h new file mode 100644 index 0000000..90f2f76 --- /dev/null +++ b/server/internal/httpServer/include/TmpTaskService.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include "Task.hpp" + +class TmpTaskService { +public: + static void createTask(std::string description) { + count++; + Task task(count, description); + tasks.push_back(task); + } + + static std::vector getAllTasks() { + return tasks; + } + + static std::size_t count; + static std::vector tasks; +}; + +std::vector TmpTaskService::tasks = {Task(1, "1 description 1\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "14\n"), + Task(2, "2 description"), + Task(3, "3 description")}; +std::size_t TmpTaskService::count = 3; \ No newline at end of file diff --git a/server/internal/httpServer/include/TmpUserService.h b/server/internal/httpServer/include/TmpUserService.h new file mode 100644 index 0000000..cd60903 --- /dev/null +++ b/server/internal/httpServer/include/TmpUserService.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include "User.hpp" + +class TmpUserService { +public: + static std::pair login(std::string_view login, std::string_view password) { + bool found = false; + User user; + for (const auto& i : tasks) { + if (i.getPassword() == password && i.getLogin() == login && !found) { + user = i; + found = true; + } + } + return {user, found}; + } + + static User registerUser(std::string login, std::string password, std::string username) { + count++; + User user(count, login, password, username); + std::cout << user << std::endl; + tasks.push_back(user); + return user; + } + + static std::size_t count; + static std::vector tasks; +}; + +std::vector TmpUserService::tasks = {}; +std::size_t TmpUserService::count = 0; diff --git a/server/internal/httpServer/src/Router.cpp b/server/internal/httpServer/src/Router.cpp index 59b5791..88d83c2 100644 --- a/server/internal/httpServer/src/Router.cpp +++ b/server/internal/httpServer/src/Router.cpp @@ -33,12 +33,8 @@ http::message_generator Router::handleRequest(http::request & return getBadRequest(req, "Illegal request-target"); } - std::cout << req.target() << std::endl; - if (req.target() == "/solution/submit") { return solutionManager->createSolution(std::move(req)); - } else if (req.target() == "/solution/metrics") { - return solutionManager->getMetrics(std::move(req)); } else if (req.target() == "/solution/all") { return solutionManager->getAllSolutions(std::move(req)); } else if (req.target() == "/user/register") { diff --git a/server/internal/httpServer/src/Serializer.cpp b/server/internal/httpServer/src/Serializer.cpp index 108430a..8d1905c 100644 --- a/server/internal/httpServer/src/Serializer.cpp +++ b/server/internal/httpServer/src/Serializer.cpp @@ -104,7 +104,7 @@ std::string Serializer::serialAllTasks(const std::vector &tasks) { std::string Serializer::serialUserData(const User &user) { boost::property_tree::ptree json; - json.put("id", user.getId()); + json.put("user_id", user.getId()); json.put("login", user.getLogin()); json.put("username", user.getUsername()); json.put("password", user.getPassword()); @@ -112,3 +112,13 @@ std::string Serializer::serialUserData(const User &user) { boost::property_tree::write_json(out, json); return out.str(); } + +std::string Serializer::serialSolution(const Solution &sol) { + boost::property_tree::ptree json; + json.put("sol_id", sol.getId()); + json.put("source", sol.getSource()); + json.put("result", sol.getResult()); + std::stringstream out; + boost::property_tree::write_json(out, json); + return out.str(); +} diff --git a/server/internal/httpServer/src/SolutionManager.cpp b/server/internal/httpServer/src/SolutionManager.cpp index e83c027..c85dc98 100644 --- a/server/internal/httpServer/src/SolutionManager.cpp +++ b/server/internal/httpServer/src/SolutionManager.cpp @@ -4,6 +4,7 @@ #include "SolutionManager.h" #include +#include "TmpSolutionService.h" SolutionManager::SolutionManager() : serializer(std::make_shared()) {}; @@ -13,17 +14,16 @@ void SolutionManager::setService(std::shared_ptr service) { } http::message_generator SolutionManager::createSolution(http::request&& req) { - size_t user_id, task_id; std::string source; std::tie(user_id, source, task_id) = serializer->deserialNewSolutionData(req.body()); - Solution sol; - sol = solutionService->createSolution(user_id, task_id, source); + Solution sol = TmpSolutionService::createSolution(user_id, task_id, source); +// sol = solutionService->createSolution(user_id, task_id, source); http::response res{http::status::ok, req.version()}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/plain"); res.keep_alive(req.keep_alive()); - res.body() = std::to_string(sol.getId()); + res.body() = serializer->serialSolution(sol); res.prepare_payload(); return res; } @@ -40,22 +40,5 @@ http::message_generator SolutionManager::getAllSolutions(http::requestserialSolutions(solutions); res.prepare_payload(); return res; - -} - -http::message_generator SolutionManager::getMetrics(http::request&& req) { - auto const bad_request = - [&req](beast::string_view why) - { - http::response res{http::status::bad_request, req.version()}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, "text/html"); - res.keep_alive(req.keep_alive()); - res.body() = std::string(why); - res.prepare_payload(); - return res; - }; - - return bad_request("123"); } diff --git a/server/internal/httpServer/src/TaskManager.cpp b/server/internal/httpServer/src/TaskManager.cpp index 2b45867..91ca64b 100644 --- a/server/internal/httpServer/src/TaskManager.cpp +++ b/server/internal/httpServer/src/TaskManager.cpp @@ -2,6 +2,7 @@ // Created by Николай Степанов on 03.05.2023. // #include "TaskManager.h" +#include "TmpTaskService.h" TaskManager::TaskManager() : serializer(std::make_shared()) {} @@ -11,7 +12,8 @@ void TaskManager::setService(std::shared_ptr service) { http::message_generator TaskManager::createTask(http::request &&req) { std::string description = serializer->deserialNewTaskData(req.body()); - taskService->createTask(description); +// taskService->createTask(description); + TmpTaskService::createTask(description); http::response res{http::status::ok, req.version()}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/plain"); @@ -21,7 +23,8 @@ http::message_generator TaskManager::createTask(http::request &&req) { - std::vector tasks = taskService->getAllTasks(); +// std::vector tasks = taskService->getAllTasks(); + std::vector tasks = TmpTaskService::getAllTasks(); http::response res{http::status::ok, req.version()}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/plain"); diff --git a/server/internal/httpServer/src/UserManager.cpp b/server/internal/httpServer/src/UserManager.cpp index 335ad4d..dcff74b 100644 --- a/server/internal/httpServer/src/UserManager.cpp +++ b/server/internal/httpServer/src/UserManager.cpp @@ -1,5 +1,7 @@ #include "UserManager.h" +#include "TmpUserService.h" + UserManager::UserManager() : serializer(std::make_shared()) {} void UserManager::setService(std::shared_ptr service) { @@ -10,20 +12,13 @@ http::message_generator UserManager::loginUser(http::request std::string login, password; std::tie(login, password) = serializer->deserialUserData(req.body()); - bool found = false; - User user; - for (const auto& i : users) { - if (i.getPassword() == password && i.getLogin() == login && !found) { - user = i; - found = true; - } - } - if (found) { + auto result = TmpUserService::login(login, password); + if (result.second) { http::response res{http::status::ok, req.version()}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/plain"); res.keep_alive(req.keep_alive()); - res.body() = serializer->serialUserData(user); + res.body() = serializer->serialUserData(result.first); res.prepare_payload(); return res; } else { @@ -31,7 +26,7 @@ http::message_generator UserManager::loginUser(http::request res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/plain"); res.keep_alive(req.keep_alive()); - res.body() = serializer->serialUserData(user); + res.body() = serializer->serialUserData(result.first); res.prepare_payload(); return res; } @@ -41,10 +36,7 @@ http::message_generator UserManager::registerUser(http::request deserialNewUserData(req.body()); // User user = userService->createUser(login, username, password); - count++; - User user = User(count, login, password, username); - std::cout << user << std::endl; - users.push_back(user); + User user = TmpUserService::registerUser(login, password, username); http::response res{http::status::ok, req.version()}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/plain"); diff --git a/server/internal/httpServer/virtual/ISolutionManager.h b/server/internal/httpServer/virtual/ISolutionManager.h index ab86bc6..62f0f2a 100644 --- a/server/internal/httpServer/virtual/ISolutionManager.h +++ b/server/internal/httpServer/virtual/ISolutionManager.h @@ -10,7 +10,6 @@ class ISolutionManager { public: virtual http::message_generator getAllSolutions(http::request&& req) = 0; virtual http::message_generator createSolution(http::request&& req) = 0; - virtual http::message_generator getMetrics(http::request&& req) = 0; }; #endif // APP_HTTPSERVER_HTTPSERVER_MANAGERS_ISolutionMANAGER_H_ -- GitLab