diff --git a/client/internal/CMakeLists.txt b/client/internal/CMakeLists.txt index 790ec143130bef8ba27e526a4f50cdc9e8907cb4..b5403669e61b8f7e3b480e846cbb51aa358cf07e 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 8a2af6623c90b54e3a1719fd9206b2ebd723306c..a493bebffe9d6c3c3afdda10485001c78a04876d 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 d88af4de561aba58bb1c97077e1ae5bd0ff44010..f28be4a31b44bf597b2a95ea750674361a5f6feb 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 bf3d43dbd11bf0eb2b29af5fa71cb8bff771483b..52baa40f99bdad30d68747c29654a45101f44542 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 384e648c4b1c3647776396c1a1da467758839748..4cf7061a36531ecf61daf2c070eed8a569958042 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 496fddceead02a74be19079d28d93bef9641d1e2..e1de440dac9588b853a6a748a7b5fc68c5db1848 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 1f206bfcf0f9068c3c7b7cb79d36248f3fd86bbb..419c4dd5e925504b3455a42a991af42ab5c7bb12 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 0000000000000000000000000000000000000000..c5b6547938e1d78a2b6b6e47afa745dcd32702ab --- /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 103c2fb862dbda49ecf8defbe5cb85eef40a3fc9..80544e56dbaf0462fb120dd46b6a0d04c850e5c3 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 c8f96bd0ceb1d0f0302c82f84045abd1b1736bb2..1a897fd8a86d06d0eaada4bb4c46dfe8fbb4d237 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 0000000000000000000000000000000000000000..3fefa3190ba17f0bcbbf1fb965a6113686ef6e73 --- /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 522714937c8dedd395b4db8c916a74c1e1a89635..2f3576806f3565779ea82020f1d1e301aad59098 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 015f65f9299615f620d0c1cf7f16f56d02d84dfe..1cdc2a31a2432c3fc72eb885c5153fdc999325f1 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 33743eec22269a34a8768cc859178e94b0c97ccf..17832a3d99d5a33d902696b66c46db0b36f9442d 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 f5c4884999dcdb546fff736f457d5d7875e4a20f..04cebc72dd2ac2632797f1d98e095c77d98fa1bf 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 058c2b4cd7387b6d6a645dcc6c82c884e0a1d0b2..42c5f6dcaf17be01c356a07040684fae932bb308 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 eb93fcb01ee452bd0db18918760ab8f4fd7cbc51..80e73b9a25e2764ae812444499ea4ee24e20e9fb 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 42be6c840fb20f92e06a50248c737a9fef90f3c6..80bdb423865f9b9e4dc6f8951518858df0109c07 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 d9f09feab291645a3420ffaec98832e107dab559..2dd02453ad3ba76c2e309a8e637f7eadee6339db 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 a269f65a6a2ce3c831859d8c4c7d0fbc80980348..7d6da4fb5b6c8c06aa9e88a0046cb999d403a86d 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 c2d556799fb6933f1b49735e6905b70700c9d641..e76eca476e2955f77143f404990258b322516c8e 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 9af1b0175ca4974fddf4def890fe852df7e77fe8..19120d1b9e17e5235ed21824df76f08fe47c8743 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 2c69a61d46601c2c6e965e4af7168f3d18113620..166aee3bc623dc02905b81a5a8da7eb34e78ef7f 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 3adecd4fe119feca0a2242da370acc8e8535a5c9..361c7a82572e101f2653e9ba224470c2ba359eef 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 0000000000000000000000000000000000000000..63cab8dae66e67ff0a6d5e2312e939127c575829 --- /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 0000000000000000000000000000000000000000..90f2f76515e4e853092057d2a69224afbe78bd5a --- /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 0000000000000000000000000000000000000000..cd60903829065b6f9b3d87a895903c7fbe228e87 --- /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 59b579156c5f1490990c841f722cf2fdd7817480..88d83c2175245ba374229f4a7145a5a28f864800 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 108430ab109129efe98ca806e869cec0b629bab7..8d1905c37a37a252ccdf1410c45f747f76ee7a82 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 e83c027e426dcabd1aa5a59f191c4407069e3145..c85dc980445b3549731f5358a1ba5bb12a8f97c4 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 2b45867bcf8c3b08b7ec727c2e951428aadabd94..91ca64b5f6710388ed30b7569cce01361528ba81 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 335ad4da0e5fd3c2d51a9d3db022582c7bd31ee0..dcff74b49ab76bc69f1d737cf8e88b64b60e1526 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 ab86bc671ca10a5ddb4f8936de5d46fbbf840509..62f0f2a4ffa540e55621184b63394cff6aed0d8a 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_