diff --git a/.env b/.env new file mode 100644 index 0000000000000000000000000000000000000000..3281990c5368da3253bc04d71467225fffdf2d2b --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +PGHOSTADDR=0.0.0.0 +PGPORT=5432 +PGDATABASE=mydb +PGUSER=postgres +PGPASSWORD=root +POOLSIZE=10 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 29e77ea83792192b3109a26f972995fc12e75084..6e8ea51f25bf1280f30035b24ac47446ab4031d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /cmake-build-debug/ /build/ .idea +server/build/ +log.txt +/server/cpp-dotenv CMakeUserPresets.json diff --git a/CMakeLists.txt b/CMakeLists.txt index bdb1810c7b391a75e4698cda543484a29daccb31..90ae8b6e9170d48b324111d6381ffd7baa7196b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,40 @@ -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) cmake_minimum_required(VERSION 3.19) -set(CMAKE_PREFIX_PATH build) -project(SourcedOut CXX) -find_package(antlr4-runtime REQUIRED) -find_package(Boost 1.8.1 REQUIRED) -find_package(libpqxx REQUIRED) -find_package(GTest REQUIRED) -message(STATUS ${Boost_LIBRARIES}) -add_executable(${PROJECT_NAME} src/main.cpp) -#add_executable(${PROJECT_NAME} text-basic-metrics/tbm_main.cpp text-basic-metrics/tbm_main.cpp) строка для запуска моей части в text-basic-metrics -target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} ${antlr4-runtime_LIBRARIES} ${libpqxx_LIBRARIES} ${GTest_LIBRARIES}) \ No newline at end of file + +set(PROJECT_NAME "SourcedOut") + +project(${PROJECT_NAME}) + + +set(BUILD_DEV TRUE CACHE BOOL "build dev version") +set(SANITIZE_BUILD TRUE CACHE BOOL "build with sanitizers") + +if(BUILD_DEV) + enable_testing() + message("Building dev version") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -O0 -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wextra -pedantic -Wformat=2 -Wfloat-equal -Wconversion \ + -Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align -lpq -lpqxx") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage -lgcov") + + if(SANITIZE_BUILD) + message("Sanitizers ON") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-sanitize-recover=all -fsanitize-undefined-trap-on-error") + endif(SANITIZE_BUILD) +endif(BUILD_DEV) + +set(BUILD_SERVER "BUILD_SERVER") +set(BUILD_CLIENT "BUILD_CLIENT") +set(BUILD_ALL "BUILD_ALL") + + +message("${BUILD_DEV} ${SANITIZE_BUILD} ${CMAKE_EXE_LINKER_FLAGS}") +set(BUILD_MODE ${BUILD_SERVER}) + +if((BUILD_MODE STREQUAL ${BUILD_CLIENT}) OR (BUILD_MODE STREQUAL ${BUILD_ALL})) + add_subdirectory(client) +endif() + +if((BUILD_MODE STREQUAL ${BUILD_SERVER}) OR (BUILD_MODE STREQUAL ${BUILD_ALL})) + add_subdirectory(server) +endif() diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/log.txt b/log.txt new file mode 100644 index 0000000000000000000000000000000000000000..d72fd2988823140d02a82d7cd5b1b30c53e0fbf3 --- /dev/null +++ b/log.txt @@ -0,0 +1,21 @@ +Opened database successfully: mydb +Opened database successfully: mydb +Opened database successfully: mydb +Opened database successfully: mydb +OK +Opened database successfully: mydb +OK +Opened database successfully: mydb +Opened database successfully: mydb +OK +Opened database successfully: mydb +OK +Opened database successfully: mydb +Opened database successfully: mydb +OK +Opened database successfully: mydb +OK +Opened database successfully: mydb +OK +Opened database successfully: mydb +OK diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e7bc4e06ed8f34b20499ab54431bdcc11c11d804 --- /dev/null +++ b/server/CMakeLists.txt @@ -0,0 +1,15 @@ +set(CMAKE_CXX_STANDARD 20) +cmake_minimum_required(VERSION 3.19) +set(CMAKE_PREFIX_PATH build) +project(SourcedOut CXX) +find_package(antlr4-runtime REQUIRED) +find_package(Boost 1.8.1 REQUIRED) +find_package(libpqxx REQUIRED) +find_package(GTest REQUIRED) +find_package(nlohmann_json REQUIRED) +message(STATUS ${nlohmann_json_LIBRARIES}) +add_subdirectory(internal) +add_subdirectory(cmd) +#add_subdirectory(cpp-dotenv) +#add_executable(${PROJECT_NAME} text-basic-metrics/tbm_main.cpp text-basic-metrics/tbm_main.cpp) строка для запуска моей части в text-basic-metrics +#target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} ${antlr4-runtime_LIBRARIES} ${libpqxx_LIBRARIES} ${GTest_LIBRARIES} nlohmann_json::nlohmann_json) diff --git a/server/cmd/.env b/server/cmd/.env new file mode 100644 index 0000000000000000000000000000000000000000..7cac90d91390a5f095999d7b06b7b0e61d0ffc0a --- /dev/null +++ b/server/cmd/.env @@ -0,0 +1,6 @@ +PGHOSTADDR=0.0.0.0 +PGPORT=5432 +PGDATABASE=mydb +PGUSER=postgres +PGPASSWORD=root +POOL_SIZE=10 \ No newline at end of file diff --git a/server/cmd/CMakeLists.txt b/server/cmd/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7b7c4687a15ec3d3cada06753b2b9f102b3bf47a --- /dev/null +++ b/server/cmd/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.19) + +set(CMAKE_CXX_STANDARD 20) + +set(PROJECT_NAME "Server") + +project(${PROJECT_NAME}) + +add_executable(Server main.cpp) +message(STATUS ${libusers}) +target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} ${antlr4-runtime_LIBRARIES} ${libpqxx_LIBRARIES} ${libEntities_LIB} ${libRepository_LIB}) +target_include_directories(Server PUBLIC ${libusers_INCLUDE_DIRS}) +message("Built server") + diff --git a/server/cmd/main.cpp b/server/cmd/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10b8775fd9eac91626db49ddfad30e0daf4bbf6c --- /dev/null +++ b/server/cmd/main.cpp @@ -0,0 +1,10 @@ +//#include "dotenv.h" +#include "UserRepository.hpp" +#include "User.hpp" + +//using namespace dotenv; +int main(){ + User user{"qwerty200468@gmail.com", "123", "tolik"}; + UserRepository repo; + std::cout< +//#include "dotenv.h" +//using namespace dotenv; +class dbConnection { +public: + dbConnection(); + [[nodiscard]] std::shared_ptr connection() const; +private: + void establish_connection(); + + std::string m_dbhost = "localhost"; + int m_dbport = 5432; + std::string m_dbname = "demo"; + std::string m_dbuser = "postgres"; + std::string m_dbpass = "postgres"; + + std::shared_ptr m_connection; + +}; + + +#endif //SOURCEDOUT_DBCONNECTION_HPP diff --git a/server/internal/dbManager/include/dbManager.hpp b/server/internal/dbManager/include/dbManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d17e9ab7ff1807c17f6f4006de27f3cc4002124f --- /dev/null +++ b/server/internal/dbManager/include/dbManager.hpp @@ -0,0 +1,34 @@ +#ifndef SOURCEDOUT_DBMANAGER_HPP +#define SOURCEDOUT_DBMANAGER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "dotenv.h" +//using namespace dotenv; +class dbManager { +public: + dbManager(); + + std::shared_ptr connection(); + + void freeConnection(const std::shared_ptr &); + +private: + const size_t POOL_SIZE = 10; + std::condition_variable m_condition; + + void createPool(); + + std::queue> connection_pool; + std::mutex m_mutex; +}; + + +#endif //SOURCEDOUT_DBMANAGER_HPP diff --git a/server/internal/dbManager/src/dbConnection.cpp b/server/internal/dbManager/src/dbConnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe9c04dd92cf7d315635f09b9633cb98b6490245 --- /dev/null +++ b/server/internal/dbManager/src/dbConnection.cpp @@ -0,0 +1,20 @@ +// +// Created by qwert on 01.05.2023. +// + +#include +#include "../include/dbConnection.hpp" + +dbConnection::dbConnection() { + establish_connection(); +} + +std::shared_ptr dbConnection::connection() const { + return m_connection; +} + +void dbConnection::establish_connection() { + pqxx::connection c("dbname =mydb" "user = postgres password =root hostaddr =172.28.224.1 port = 5432"); + m_connection.reset(&c); + +} diff --git a/server/internal/dbManager/src/dbManager.cpp b/server/internal/dbManager/src/dbManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1ff7664582f4efce05967bd10f3d0eb811154cf --- /dev/null +++ b/server/internal/dbManager/src/dbManager.cpp @@ -0,0 +1,39 @@ + +#include "dbManager.hpp" + + +dbManager::dbManager() { + createPool(); +} + +void dbManager::createPool() { + std::lock_guard locker_(m_mutex); + + for (auto i = 0; i < POOL_SIZE; i++) { + connection_pool.emplace(std::make_shared( + "dbname =mydb user = postgres password =root hostaddr =172.28.224.1 port = 5432")); + } +} + +std::shared_ptr dbManager::connection() { + std::unique_lock lock_(m_mutex); + + while (connection_pool.empty()) { + m_condition.wait(lock_); + } + + auto conn_ = connection_pool.front(); + connection_pool.pop(); + + return conn_; +} + +void dbManager::freeConnection(const std::shared_ptr &conn_) { + std::unique_lock lock_(m_mutex); + + connection_pool.push(conn_); + + lock_.unlock(); + + m_condition.notify_one(); +} diff --git a/server/internal/entities/CMakeLists.txt b/server/internal/entities/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..08858c7e652e13d26b92360cf52bc6e7511ffd54 --- /dev/null +++ b/server/internal/entities/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.19) + +project("EntitiesLib") + +set(LIB_NAME libEntities) + +file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) + +message("SOURCES = ${SOURCES}") +message("HEADERS = ${HEADERS}") + + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wextra -O2 -pedantic -Wformat=2 -Wfloat-equal -Wconversion \ +-Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align") + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lboost_filesystem") + + +add_library(${LIB_NAME} ${SOURCES} ${HEADERS}) +target_include_directories(${LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +#target_link_libraries(${LIB_NAME} ${Boost_LIBRARIES} nlohmann_json::nlohmann_json) + +set(libEntities_LIB ${LIB_NAME}) +set(libEntities_LIB ${libEntities_LIB} PARENT_SCOPE) +set(libEntities_INCLUDE_DIRS ${LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/include) +set(libEntities_INCLUDE_DIRS ${libEntities_INCLUDE_DIRS} PARENT_SCOPE) + +message("libEntities_LIB = ${libEntities_LIB}") +message("libEntities_INCLUDE_DIRS = ${libEntities_INCLUDE_DIRS}") + +enable_testing() +add_subdirectory(tests) \ No newline at end of file diff --git a/server/internal/entities/include/MetricStat.hpp b/server/internal/entities/include/MetricStat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..491abb7dd3297cc8d2ed31c4c6b010289324932e --- /dev/null +++ b/server/internal/entities/include/MetricStat.hpp @@ -0,0 +1,58 @@ +#ifndef SOURCEDOUT_METRICSTAT_HPP +#define SOURCEDOUT_METRICSTAT_HPP + +#include + +class MetricStat { +public: + MetricStat() noexcept; + + MetricStat(size_t solutionId, float textBasedRes, float tokenBasedRes, float treeBasedRes, bool verdict, + float meanRes) noexcept; + + MetricStat(size_t id, size_t solutionId, float textBasedRes, float tokenBasedRes, float treeBasedRes, bool verdict, + float meanRes) noexcept; + + [[nodiscard]] size_t getId() const noexcept; + + void setId(size_t id); + + [[nodiscard]] size_t getSolutionId() const noexcept; + + void setSolutionId(size_t solutionId) noexcept; + + [[nodiscard]] float getTextBasedRes() const noexcept; + + void setTextBasedRes(float textBasedRes) noexcept; + + [[nodiscard]] float getTokenBasedRes() const noexcept; + + void setTokenBasedRes(float tokenBasedRes) noexcept; + + [[nodiscard]] float getTreeBasedRes() const noexcept; + + void setTreeBasedRes(float treeBasedRes) noexcept; + + [[nodiscard]] bool isVerdict() const noexcept; + + void setVerdict(bool verdict) noexcept; + + [[nodiscard]] float getMeanRes() const noexcept; + + void setMeanRes(float meanRes) noexcept; + + bool operator==(const MetricStat &rhs) const noexcept; + + bool operator!=(const MetricStat &rhs) const noexcept; + +private: + size_t id; + size_t solution_id; + float text_based_res; + float token_based_res; + float tree_based_res; + bool verdict; + float mean_res; +}; + +#endif //SOURCEDOUT_METRICSTAT_HPP diff --git a/server/internal/entities/include/Solution.hpp b/server/internal/entities/include/Solution.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f2cdda03cbba5bcd23c16819e521db8968e14185 --- /dev/null +++ b/server/internal/entities/include/Solution.hpp @@ -0,0 +1,76 @@ +#ifndef SOURCEDOUT_SOLUTION_HPP +#define SOURCEDOUT_SOLUTION_HPP + +#include +#include +#include + +class Solution { +public: + Solution(size_t id, std::string sendDate, size_t senderId, + std::string source, size_t taskId, std::string result, + std::string tokens, std::string astTree, + size_t orig_solution) noexcept; + + Solution(std::string sendDate, size_t senderId, + std::string source, size_t taskId, std::string result, + std::string tokens, std::string astTree, + size_t orig_solution) noexcept; + + Solution() noexcept; + + [[nodiscard]] size_t getId() const noexcept; + + + [[nodiscard]] const std::string &getSendDate() const noexcept; + + void setSendDate(const std::string &sendDate) noexcept; + + [[nodiscard]] size_t getSenderId() const noexcept; + + void setSenderId(size_t senderId) noexcept; + + [[nodiscard]] const std::string &getSource() const noexcept; + + void setSource(const std::string &source) noexcept; + + [[nodiscard]] const std::string &getTokens() const noexcept; + + void setTokens(const std::string &tokens) noexcept; + + [[nodiscard]] const std::string &getAstTree() const noexcept; + + void setAstTree(const std::string &astTree) noexcept; + + [[nodiscard]] size_t getTaskId() const noexcept; + + void setTaskId(size_t taskId) noexcept; + + [[nodiscard]] const std::string &getResult() const noexcept; + + void setResult(const std::string &result) noexcept; + + [[nodiscard]] size_t getOrigSolution() const; + + void setOrigSolution(size_t origSolution); + + void setId(size_t id) noexcept; + + bool operator==(const Solution &rhs) const noexcept; + + bool operator!=(const Solution &rhs) const noexcept; + +private: + size_t id; + std::string send_date; + size_t sender_id; + std::string source; + std::string tokens; + std::string astTree; + size_t task_id; + std::string result; + size_t orig_solution = 0; + +}; + +#endif //SOURCEDOUT_SOLUTION_HPP diff --git a/server/internal/entities/include/Task.hpp b/server/internal/entities/include/Task.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e5518044893195135864aee103adbed6f16bb82f --- /dev/null +++ b/server/internal/entities/include/Task.hpp @@ -0,0 +1,35 @@ +#ifndef SOURCEDOUT_TASK_HPP +#define SOURCEDOUT_TASK_HPP +#include +#include +class Task{ +private: + size_t id; + std::string description; + float treshhold; + +public: + Task(size_t id, std::string description_, float treshold_) noexcept; + + Task(std::string description_, float treshold_) noexcept; + + Task() noexcept; + + [[nodiscard]] size_t getId() const noexcept; + + [[nodiscard]] const std::string &getDescription() const noexcept; + + float getTreshhold() const noexcept; + + void setTreshhold(float treshhold) noexcept; + + void setDescription(const std::string &description) noexcept; + + void setId(size_t id) noexcept; + + bool operator==(const Task &rhs) const noexcept; + + bool operator!=(const Task &rhs) const noexcept; + +}; +#endif //SOURCEDOUT_TASK_HPP diff --git a/server/internal/entities/include/User.hpp b/server/internal/entities/include/User.hpp new file mode 100644 index 0000000000000000000000000000000000000000..82e659f9095148269b76d334b43b36117629349b --- /dev/null +++ b/server/internal/entities/include/User.hpp @@ -0,0 +1,45 @@ +#ifndef SOURCEDOUT_USER_HPP + +#include +#include + +#define SOURCEDOUT_USER_HPP + +class User { +private: + size_t id; + std::string login; + std::string password; + std::string username; + +public: + User(size_t id_, std::string login_, std::string password_, std::string username_) noexcept; + + User(std::string login_, std::string password_, std::string username_) noexcept; + + User() noexcept; + + [[nodiscard]] const std::string &getLogin() const noexcept; + + void setLogin(const std::string &login) noexcept; + + [[nodiscard]] const std::string &getPassword() const noexcept; + + void setPassword(const std::string &password) noexcept; + + [[nodiscard]] const std::string &getUsername() const noexcept; + + void setUsername(const std::string &username) noexcept; + + [[nodiscard]] size_t getId() const noexcept; + + friend std::ostream &operator<<(std::ostream &os, const User &user) noexcept; + + void setId(size_t id) noexcept; + + bool operator==(const User &rhs) const noexcept; + + bool operator!=(const User &rhs) const noexcept; +}; + +#endif //SOURCEDOUT_USER_HPP diff --git a/server/internal/entities/src/MetricStat.cpp b/server/internal/entities/src/MetricStat.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa0befc71722ddc28778494c1e9d8b3989a249ce --- /dev/null +++ b/server/internal/entities/src/MetricStat.cpp @@ -0,0 +1,81 @@ + +#include "MetricStat.hpp" + +MetricStat::MetricStat(unsigned long solutionId, float textBasedRes, float tokenBasedRes, float treeBasedRes, + bool verdict, float meanRes) noexcept : id(0), solution_id(solutionId), + text_based_res(textBasedRes), token_based_res(tokenBasedRes), + tree_based_res(treeBasedRes), verdict(verdict), + mean_res(meanRes) {} + +MetricStat::MetricStat(size_t id, size_t solutionId, float textBasedRes, float tokenBasedRes, float treeBasedRes, + bool verdict, float meanRes) noexcept : id(id), solution_id(solutionId), text_based_res(textBasedRes), + token_based_res(tokenBasedRes), tree_based_res(treeBasedRes), + verdict(verdict), mean_res(meanRes) {} + +MetricStat::MetricStat() noexcept : id(0), solution_id(0), text_based_res(0), token_based_res(0), tree_based_res(), + verdict(true), mean_res(0) { +} + +size_t MetricStat::getId() const noexcept { + return id; +} + +void MetricStat::setId(size_t id_) { + id = id_; +} + +size_t MetricStat::getSolutionId() const noexcept { + return solution_id; +} + +void MetricStat::setSolutionId(size_t solutionId) noexcept { + solution_id = solutionId; +} + +float MetricStat::getTextBasedRes() const noexcept { + return text_based_res; +} + +void MetricStat::setTextBasedRes(float textBasedRes) noexcept { + text_based_res = textBasedRes; +} + +float MetricStat::getTokenBasedRes() const noexcept { + return token_based_res; +} + +void MetricStat::setTokenBasedRes(float tokenBasedRes) noexcept { + token_based_res = tokenBasedRes; +} + +float MetricStat::getTreeBasedRes() const noexcept { + return tree_based_res; +} + +void MetricStat::setTreeBasedRes(float treeBasedRes) noexcept { + tree_based_res = treeBasedRes; +} + +bool MetricStat::isVerdict() const noexcept { + return verdict; +} + +void MetricStat::setVerdict(bool verdict_) noexcept { + verdict = verdict_; +} + +float MetricStat::getMeanRes() const noexcept { + return mean_res; +} + +void MetricStat::setMeanRes(float meanRes) noexcept { + mean_res = meanRes; +} + +bool MetricStat::operator==(const MetricStat &rhs) const noexcept { + return id == rhs.id; +} + +bool MetricStat::operator!=(const MetricStat &rhs) const noexcept { + return !(rhs == *this); +} diff --git a/server/internal/entities/src/Solution.cpp b/server/internal/entities/src/Solution.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca5fa0dd17d71487aec0c17a846d6bd5a24a9001 --- /dev/null +++ b/server/internal/entities/src/Solution.cpp @@ -0,0 +1,108 @@ + +#include +#include +#include "Solution.hpp" + +Solution::Solution(size_t id, std::string sendDate, size_t senderId, + std::string source, size_t taskId, std::string result, + std::string tokens, std::string astTree, + size_t orig_solution) noexcept: + id(id), send_date(std::move(sendDate)), sender_id(senderId), + source(std::move(source)), tokens(std::move(tokens)), + astTree(std::move(astTree)), + task_id(taskId), result(std::move(result)), orig_solution(orig_solution) {} + +Solution::Solution(std::string sendDate, size_t senderId, + std::string source, size_t taskId, std::string result, + std::string tokens, std::string astTree, + size_t orig_solution) noexcept: + id(0), send_date(std::move(sendDate)), sender_id(senderId), + source(std::move(source)), tokens(std::move(tokens)), + astTree(std::move(astTree)), + task_id(taskId), result(std::move(result)), orig_solution(orig_solution) {} + + +size_t Solution::getId() const noexcept { + return id; +} + +void Solution::setId(size_t id_) noexcept { + id = id_; +} + +const std::string &Solution::getSendDate() const noexcept { + return send_date; +} + +void Solution::setSendDate(const std::string &sendDate) noexcept { + send_date = sendDate; +} + +size_t Solution::getSenderId() const noexcept { + return sender_id; +} + +void Solution::setSenderId(size_t senderId) noexcept { + sender_id = senderId; +} + +const std::string &Solution::getSource() const noexcept { + return source; +} + +void Solution::setSource(const std::string &source_) noexcept { + Solution::source = source_; +} + +const std::string &Solution::getTokens() const noexcept { + return tokens; +} + +void Solution::setTokens(const std::string &tokens_) noexcept { + Solution::tokens = tokens_; +} + +const std::string &Solution::getAstTree() const noexcept { + return astTree; +} + +void Solution::setAstTree(const std::string &astTree_) noexcept { + Solution::astTree = astTree_; +} + +size_t Solution::getTaskId() const noexcept { + return task_id; +} + +void Solution::setTaskId(size_t taskId) noexcept { + task_id = taskId; +} + +const std::string &Solution::getResult() const noexcept { + return result; +} + +void Solution::setResult(const std::string &result_) noexcept { + Solution::result = result_; +} + +bool Solution::operator==(const Solution &rhs) const noexcept { + return id == rhs.id; +} + +bool Solution::operator!=(const Solution &rhs) const noexcept { + return !(rhs == *this); +} + +size_t Solution::getOrigSolution() const { + return orig_solution; +} + +void Solution::setOrigSolution(size_t origSolution) { + orig_solution = origSolution; +} + +Solution::Solution()noexcept :id(0), sender_id(0), task_id(0){ + +} + diff --git a/server/internal/entities/src/Task.cpp b/server/internal/entities/src/Task.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0fc10733fc4a2ab85888c8b2893c81bd51faded --- /dev/null +++ b/server/internal/entities/src/Task.cpp @@ -0,0 +1,43 @@ +#include "Task.hpp" +#include + +Task::Task(std::string description_, float treshold_) noexcept : id(0), description(std::move(description_)), + treshhold(treshold_) {} + +Task::Task(size_t id, std::string description_, float treshold_) noexcept : id(id), description(std::move(description_)), + treshhold(treshold_) {} +Task::Task() noexcept:id(0), treshhold(0) { +} + +unsigned long Task::getId() const noexcept { + return id; +} + +const std::string &Task::getDescription() const noexcept { + return description; +} + +void Task::setId(size_t id_) noexcept { + id = id_; +} + +void Task::setDescription(const std::string &description_) noexcept { + Task::description = description_; +} + +bool Task::operator==(const Task &rhs) const noexcept { + return id == rhs.id; +} + +bool Task::operator!=(const Task &rhs) const noexcept { + return !(rhs == *this); +} + +float Task::getTreshhold() const noexcept { + return treshhold; +} + +void Task::setTreshhold(float treshhold_) noexcept { + Task::treshhold = treshhold_; +} + diff --git a/server/internal/entities/src/User.cpp b/server/internal/entities/src/User.cpp new file mode 100644 index 0000000000000000000000000000000000000000..67f2620dc4a925944d4fd349532eee764af4f57b --- /dev/null +++ b/server/internal/entities/src/User.cpp @@ -0,0 +1,59 @@ +#include +#include "../include/User.hpp" + +User::User(size_t id_, std::string login_, std::string password_, std::string username_) noexcept : + id(id_), login(std::move(login_)), password(std::move(password_)), username(std::move(username_)) { +} + +User::User(std::string login_, std::string password_, std::string username_) noexcept : + id(0), login(std::move(login_)), password(std::move(password_)), username(std::move(username_)) { +} + +User::User() noexcept : id(0) { +} + +const std::string &User::getLogin() const noexcept { + return login; +} + +void User::setId(size_t id_) noexcept { + id = id_; +} + +void User::setLogin(const std::string &login_) noexcept { + User::login = login_; +} + +const std::string &User::getPassword() const noexcept { + return password; +} + +void User::setPassword(const std::string &password_) noexcept { + User::password = password_; +} + +const std::string &User::getUsername() const noexcept { + return username; +} + +void User::setUsername(const std::string &username_) noexcept { + User::username = username_; +} + +size_t User::getId() const noexcept { + return id; +} + +std::ostream &operator<<(std::ostream &os, const User &user) noexcept { + os << "id: " << user.id << " login: " << user.login << " password: " << user.password << " username: " + << user.username; + return os; +} + +bool User::operator==(const User &rhs) const noexcept { + return id == rhs.id; +} + +bool User::operator!=(const User &rhs) const noexcept { + return !(rhs == *this); +} diff --git a/server/internal/entities/tests/CMakeLists.txt b/server/internal/entities/tests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/server/internal/repository/CMakeLists.txt b/server/internal/repository/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d7309fa4dd34dabb3ea3cb3d6264e564c09118ef --- /dev/null +++ b/server/internal/repository/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.19) + +project("RepositoryLib") + +set(LIB_NAME libRepository) + +file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) + +message("SOURCES = ${SOURCES}") +message("HEADERS = ${HEADERS}") + + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wextra -O2 -pedantic -Wformat=2 -Wfloat-equal -Wconversion \ +-Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align -ftest-coverage") + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lboost_filesystem") + +add_custom_target( + ${PROJECT_NAME}_COVERAGE + COMMAND gcovr ${CMAKE_CURRENT_BINARY_DIR} -r ${CMAKE_CURRENT_SOURCE_DIR} +) +add_custom_target( + ${PROJECT_NAME}_COVERAGE_FILE + COMMAND rm -r ${CMAKE_CURRENT_BINARY_DIR}/report || echo "There are no reports" + COMMAND mkdir ${CMAKE_CURRENT_BINARY_DIR}/report + COMMAND gcovr ${CMAKE_CURRENT_BINARY_DIR} -r ${CMAKE_CURRENT_SOURCE_DIR} --html-details report/report.html +) +add_library(${LIB_NAME} ${SOURCES} ${HEADERS}) +target_include_directories(${LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/virtual) +target_link_libraries(${LIB_NAME} ${Boost_LIBRARIES} ${libpqxx_LIBRARIES} ${libEntities_LIB} ${libDbManager_LIB}) + +set(libRepository_LIB ${LIB_NAME}) +set(libRepository_LIB ${libRepository_LIB} PARENT_SCOPE) + +set(libRepository_INCLUDE_DIRS ${LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/include) +set(libRepository_INCLUDE_DIRS ${libRepository_INCLUDE_DIRS} PARENT_SCOPE) + + +message(Entities_LIB = "${libEntities_LIB}") +message(dbManager = "${libDbManager_LIB}") +message("libRepository_LIB = ${libRepository_LIB}") +message("libRepository_INCLUDE_DIRS = ${libRepository_INCLUDE_DIRS}") + +enable_testing() +add_subdirectory(tests) \ No newline at end of file diff --git a/server/internal/repository/include/MetricRepository.hpp b/server/internal/repository/include/MetricRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6e23e90db56c7b6fc1594f1fd614e2c07507bff1 --- /dev/null +++ b/server/internal/repository/include/MetricRepository.hpp @@ -0,0 +1,31 @@ +#ifndef SOURCEDOUT_METRICREPOSITORY_HPP +#define SOURCEDOUT_METRICREPOSITORY_HPP + +#include "IMetricRepository.hpp" +#include "dbManager.hpp" +#include +#include + +using namespace pqxx; + +class MetricRepository :public IMetricRepository { +public: + explicit MetricRepository(); + + std::optional getById(size_t id) override; + + size_t storeMetric(MetricStat metric) override; + + void updateMetric(MetricStat metric) override; + + void deleteMetric(MetricStat metric) override; + + void deleteMetricById(size_t id) override; + +private: + std::shared_ptr manager; + + static MetricStat makeMetric(const result::const_iterator &c); +}; + +#endif //SOURCEDOUT_METRICREPOSITORY_HPP diff --git a/server/internal/repository/include/SolutionRepository.hpp b/server/internal/repository/include/SolutionRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8e178cf72ae6c9b0c7ad737080b2ae486bc3948d --- /dev/null +++ b/server/internal/repository/include/SolutionRepository.hpp @@ -0,0 +1,41 @@ +#ifndef SOURCEDOUT_SOLUTIONREPOSITORY_HPP +#define SOURCEDOUT_SOLUTIONREPOSITORY_HPP + +#include +#include +#include +#include +#include "ISolutionRepository.hpp" +#include "dbManager.hpp" +#include + + +using namespace pqxx; + +class SolutionRepository : public ISolutionRepository { +public: + explicit SolutionRepository(); + + std::optional getSolutionById(size_t id) override; + + std::vector getSolutionsBySenderId(size_t sender_id) override; + + std::vector getSolutionsByTaskId(size_t task_id) override; + + size_t storeSolution(Solution solution) override; + + void updateSolution(Solution solution) override; + + void deleteSolutionById(size_t id) override; + + void deleteSolution(Solution solution) override; + + std::optional getOriginalSolution(size_t id) override; + +private: + static Solution makeSolution(const result::const_iterator &c); + + std::shared_ptr manager; +}; + +#endif diff --git a/server/internal/repository/include/TaskRepository.hpp b/server/internal/repository/include/TaskRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..467fadd02d4bb3521f39ec08e049774804965d36 --- /dev/null +++ b/server/internal/repository/include/TaskRepository.hpp @@ -0,0 +1,34 @@ +#ifndef SOURCEDOUT_TASKREPOSITORY_HPP +#define SOURCEDOUT_TASKREPOSITORY_HPP + +#include +#include +#include "ITaskRepository.hpp" +#include "pqxx/pqxx" +#include "dbManager.hpp" +#include + +using namespace pqxx; + +class TaskRepository :public ITaskRepository { +public: + explicit TaskRepository(); + std::optional getTaskById(size_t id) override; + + std::vector getAllTasks() override; + + void updateTask(const Task& task) override; + + size_t storeTask(Task task) override; + + void deleteTask(Task task) override; + + void deleteTaskById(size_t task_id) override; + +private: + static Task makeTask(const result::const_iterator &c); + + std::shared_ptr manager; +}; + +#endif //SOURCEDOUT_TASKREPOSITORY_HPP diff --git a/server/internal/repository/include/UserRepository.hpp b/server/internal/repository/include/UserRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..70ceaf08a047f7d3a543c3ac32a437b86f9a77f9 --- /dev/null +++ b/server/internal/repository/include/UserRepository.hpp @@ -0,0 +1,39 @@ +#ifndef SOURCEDOUT_USERREPOSITORY_HPP +#define SOURCEDOUT_USERREPOSITORY_HPP + +#include +#include "IUserRepository.hpp" +#include "dbManager.hpp" +#include +#include +#include +#include + +using namespace pqxx; + +class UserRepository :public IUserRepository { +public: + explicit UserRepository(); + + std::optional getUserById(size_t id) override; + + std::optional getUserByLogin(std::string login) override; + + size_t makeUser(User user) override; + + void deleteUser(User user) override; + + void deleteByUserId(size_t user_id) override; + + std::vector getAllUsers() override; + + void update(User user) override; + + +private: + static User makeUser(const result::const_iterator &c); + + std::shared_ptr manager; +}; + +#endif //SOURCEDOUT_USERREPOSITORY_HPP diff --git a/server/internal/repository/src/MetricRepository.cpp b/server/internal/repository/src/MetricRepository.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6d265a9da042672d8178cb9c39bd223abd384c6 --- /dev/null +++ b/server/internal/repository/src/MetricRepository.cpp @@ -0,0 +1,90 @@ +#include "MetricStat.hpp" +#include "MetricRepository.hpp" +#include + +std::optional MetricRepository::getById(size_t id) { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM metricStat WHERE id=" + std::to_string(id); + nontransaction n(*c); + result r(n.exec(sql)); + manager->freeConnection(c); + if(r.empty()) + return std::nullopt; + return makeMetric(r.begin()); + } catch (...) { + + throw; + } +} + + +size_t MetricRepository::storeMetric(MetricStat metric) { + try { + auto c = manager->connection(); + + std::string sql = ( + boost::format( + "INSERT INTO metricStat (solution_id, text_based_res, token_based_res, tree_based_res, verdict, mean_res) " \ + "VALUES ('%s', '%s', '%s', '%s', '%s', '%s') RETURNING id; ") % metric.getSolutionId() % + metric.getTextBasedRes() % metric.getTokenBasedRes() % metric.getTreeBasedRes() % metric.isVerdict() % + metric.getMeanRes()).str(); + work w(*c); + row r = (w.exec1(sql)); + w.commit(); + manager->freeConnection(c); + return r["id"].as(); + } catch (...) { + + throw; + } +} + +void MetricRepository::updateMetric(MetricStat metric) { + try { + auto c = manager->connection(); + + std::string sql = (boost::format( + "UPDATE metricStat SET solution_id = '%s', text_based_res = '%s', token_based_res = '%s', tree_based_res = '%s', verdict = '%s', mean_res = '%s';") + % metric.getSolutionId() % metric.getTextBasedRes() % metric.getTokenBasedRes() % + metric.getTreeBasedRes() % metric.isVerdict() % metric.getMeanRes()).str(); + work w(*c); + w.exec(sql); + manager->freeConnection(c); + } catch (...) { + + throw; + } +} + +void MetricRepository::deleteMetric(MetricStat metric) { + deleteMetricById(metric.getId()); +} + +void MetricRepository::deleteMetricById(size_t id) { + try { + auto c = manager->connection(); + std::string sql = "DELETE FROM metricStat WHERE id=" + std::to_string(id); + work w(*c); + w.exec(sql); + w.commit(); + manager->freeConnection(c); + } catch (...) { + throw; + } +} + +MetricStat MetricRepository::makeMetric(const result::const_iterator &c) { + return {c.at(c.column_number("id")).as(), + c.at(c.column_number("solution_id")).as(), + c.at(c.column_number("text_based_res")).as(), + c.at(c.column_number("token_based_res")).as(), + c.at(c.column_number("tree_based_res")).as(), + c.at(c.column_number("verdict")).as(), + c.at(c.column_number("mean_res")).as() + }; +} + +MetricRepository::MetricRepository() { + manager = std::make_shared(); +} diff --git a/server/internal/repository/src/SolutionRepository.cpp b/server/internal/repository/src/SolutionRepository.cpp new file mode 100644 index 0000000000000000000000000000000000000000..353ad9b94cda2de28b074b81787e551f7eab441c --- /dev/null +++ b/server/internal/repository/src/SolutionRepository.cpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include "Solution.hpp" +#include "SolutionRepository.hpp" + +using namespace pqxx; + +std::optional SolutionRepository::getSolutionById(size_t id) { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM solutions WHERE id=" + std::to_string(id); + nontransaction n(*c); + result r(n.exec(sql)); + manager->freeConnection(c); + if (r.empty()) + return std::nullopt; + return makeSolution(r.begin()); + } catch (...) { + + throw; + } +} + +std::vector SolutionRepository::getSolutionsBySenderId(size_t sender_id) { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM solutions WHERE sender_id=" + std::to_string(sender_id); + nontransaction n(*c); + auto stream = stream_from::query(n, sql); + std::vector solutions; + std::tuple row; + while (stream >> row) { + solutions.emplace_back( + get<0>(row), get<1>(row), + get<2>(row), get<3>(row), + get<4>(row), get<5>(row), + get<6>(row), get<7>(row), get<8>(row)); + } + stream.complete(); + manager->freeConnection(c); + return solutions; + } catch (...) { + + throw; + } +} + +std::vector SolutionRepository::getSolutionsByTaskId(size_t task_id) { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM solutions WHERE task_id=" + std::to_string(task_id); + nontransaction n(*c); + auto stream = stream_from::query(n, sql); + std::vector solutions; + std::tuple row; + while (stream >> row) { + solutions.emplace_back( + get<0>(row), get<1>(row), + get<2>(row), get<3>(row), + get<4>(row), get<5>(row), + get<6>(row), get<7>(row), get<8>(row)); + } + stream.complete(); + manager->freeConnection(c); + return solutions; + } catch (...) { + + throw; + } +} + +std::optional SolutionRepository::getOriginalSolution(size_t id) { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM solutions WHERE original_solution_id=" + std::to_string(id); + nontransaction n(*c); + result r(n.exec(sql)); + manager->freeConnection(c); + if (r.empty()) + return std::nullopt; + return makeSolution(r.begin()); + } catch (...) { + + throw; + } +} + + +size_t SolutionRepository::storeSolution(Solution solution) { + try { + auto c = manager->connection(); + + std::string sql = ( + boost::format("INSERT INTO solutions (send_date,sender_id, source, task_id, result, tokens, astTree, original_solution_id) " \ + "VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') RETURNING id; ") % solution.getSendDate() % + solution.getSenderId() % solution.getSource() % solution.getTaskId() % solution.getResult() % + solution.getTokens() % solution.getAstTree() % solution.getOrigSolution()).str(); + work w(*c); + row r = (w.exec1(sql)); + w.commit(); + manager->freeConnection(c); + return r["id"].as(); + } catch (...) { + throw; + } +} + +void SolutionRepository::updateSolution(Solution solution) { + try { + auto c = manager->connection(); + + std::string sql = (boost::format( + "UPDATE solutions SET send_date = '%s', sender_id = '%s', source = '%s'," + " task_id = '%s', result = '%s', tokens = '%s', astTree = '%s', original_solution_id = '%s';") + % solution.getSendDate() % solution.getSenderId() % solution.getSource() % + solution.getTaskId() % solution.getResult() % solution.getTokens() % + solution.getAstTree() % solution.getOrigSolution()).str(); + work w(*c); + w.exec(sql); + manager->freeConnection(c); + } catch (...) { + + throw; + } +} + +void SolutionRepository::deleteSolutionById(size_t id) { + try { + auto c = manager->connection(); + std::string sql = "DELETE FROM solutions WHERE id=" + std::to_string(id); + work w(*c); + w.exec(sql); + w.commit(); + manager->freeConnection(c); + } catch (...) { + + throw; + } +} + +void SolutionRepository::deleteSolution(Solution solution) { + deleteSolutionById(solution.getId()); +} + + +Solution SolutionRepository::makeSolution(const result::const_iterator &c) { + return {c.at(c.column_number("id")).as(), + c.at(c.column_number("send_date")).as(), + c.at(c.column_number("sender_id")).as(), + c.at(c.column_number("source")).as(), + c.at(c.column_number("task_id")).as(), + c.at(c.column_number("result")).as(), + c.at(c.column_number("tokens")).as(), + c.at(c.column_number("astTree")).as(), + c.at(c.column_number("original_solution_id")).as()}; +} + +SolutionRepository::SolutionRepository() { + manager = std::make_shared(); +} diff --git a/server/internal/repository/src/TaskRepository.cpp b/server/internal/repository/src/TaskRepository.cpp new file mode 100644 index 0000000000000000000000000000000000000000..261436c9b59172faee82a1ac5595f2cdec85ed63 --- /dev/null +++ b/server/internal/repository/src/TaskRepository.cpp @@ -0,0 +1,97 @@ +#include +#include "Task.hpp" +#include +#include +#include "TaskRepository.hpp" + +std::optional TaskRepository::getTaskById(size_t id) { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM tasks WHERE id=" + std::to_string(id); + nontransaction n(*c); + result r(n.exec(sql)); + manager->freeConnection(c); + if (r.empty()) { + return std::nullopt; + } + return makeTask(r.begin()); + } catch (...) { + throw; + } +} + +std::vector TaskRepository::getAllTasks() { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM tasks"; + nontransaction n(*c); + auto stream = stream_from::query(n, sql); + std::vector tasks; + std::tuple row; + while(stream >> row){ + tasks.emplace_back(get<0>(row), get<1>(row), get<2>(row)); + } + stream.complete(); + manager->freeConnection(c); + return tasks; + } catch (...) { + + throw; + } +} + +void TaskRepository::updateTask(const Task &task) { + try { + auto c = manager->connection(); + std::string sql = (boost::format("UPDATE tasks SET description = '%s', treshold = '%s';") % + task.getDescription() % task.getTreshhold()).str(); + work w(*c); + w.exec(sql); + manager->freeConnection(c); + } catch (...) { + throw; + } +} + +size_t TaskRepository::storeTask(Task task) { + try { + auto c = manager->connection(); + std::string sql = (boost::format("INSERT INTO tasks (description, treshold) " \ + "VALUES ('%s', '%s') RETURNING id; ") % task.getDescription() % task.getTreshhold()).str(); + work w(*c); + row r = w.exec1(sql); + w.commit(); + manager->freeConnection(c); + return r["id"].as(); + } catch (...) { + throw; + } +} + +void TaskRepository::deleteTask(Task task) { + deleteTaskById(task.getId()); +} + +void TaskRepository::deleteTaskById(size_t task_id) { + try { + auto c = manager->connection(); + std::string sql = "DELETE FROM tasks WHERE id=" + std::to_string(task_id); + work w(*c); + w.exec(sql); + w.commit(); + manager->freeConnection(c); + } catch (...) { + throw; + } +} + +Task TaskRepository::makeTask(const result::const_iterator &c) { + return {c.at(c.column_number("id")).as(), + c.at(c.column_number("description")).as(), + c.at(c.column_number("treshold")).as()}; +} + + +TaskRepository::TaskRepository() { + manager = std::make_shared(); +} diff --git a/server/internal/repository/src/UserRepository.cpp b/server/internal/repository/src/UserRepository.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71e05a550fe0a8b1a565f3e7667573a4739dc1c4 --- /dev/null +++ b/server/internal/repository/src/UserRepository.cpp @@ -0,0 +1,122 @@ + +#include +#include "User.hpp" +#include "UserRepository.hpp" +#include "dbManager.hpp" +#include + +std::optional UserRepository::getUserById(size_t id) { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM Users WHERE id=" + std::to_string(id); + nontransaction n(*c); + result r(n.exec(sql)); + manager->freeConnection(c); + if (r.empty()) + return std::nullopt; + return makeUser(r.begin()); + } catch (...) { + + throw; + } +} + +std::optional UserRepository::getUserByLogin(std::string login) { + try { + auto c = manager->connection(); + std::string sql = (boost::format("SELECT * FROM Users WHERE login= '%s'") % login).str(); + nontransaction n(*c); + result r(n.exec(sql)); + manager->freeConnection(c); + if(r.empty()) + return std::nullopt; + return makeUser(r.begin()); + } catch (...) { + + throw; + } +} + +size_t UserRepository::makeUser(User user) { + try { + auto c = manager->connection(); + + std::string sql = (boost::format("INSERT INTO users (login,password,username) " \ + "VALUES ('%s', '%s', '%s') RETURNING id; ") % user.getLogin() % user.getPassword() % + user.getUsername()).str(); + work w(*c); + row r = w.exec1(sql); + w.commit(); + manager->freeConnection(c); + return r["id"].as(); + } catch (...) { + + throw; + } +} + +void UserRepository::deleteByUserId(size_t user_id) { + try { + auto c = manager->connection(); + std::string sql = "DELETE FROM Users WHERE id=" + std::to_string(user_id); + work w(*c); + w.exec(sql); + w.commit(); + manager->freeConnection(c); + } catch (...) { + + throw; + } +} + + +void UserRepository::deleteUser(User user) { + deleteByUserId(user.getId()); +} + +std::vector UserRepository::getAllUsers() { + try { + auto c = manager->connection(); + std::string sql = "SELECT * FROM Users"; + nontransaction n(*c); + auto stream = stream_from::query(n, sql); + std::vector users; + std::tuple row; + while(stream >> row){ + users.emplace_back(get<0>(row), get<1>(row), get<2>(row), get<3>(row)); + } + stream.complete(); + manager->freeConnection(c); + return users; + } catch (...) { + + throw; + } +} + +User UserRepository::makeUser(const result::const_iterator &c) { + return {c.at(c.column_number("id")).as(), + c.at(c.column_number("login")).as(), + c.at(c.column_number("password")).as(), + c.at(c.column_number("username")).as()}; +} + +UserRepository::UserRepository() { + manager = std::make_shared(); +} + +void UserRepository::update(User user) { + try { + auto c = manager->connection(); + + std::string sql = (boost::format( + "UPDATE Users SET login = '%s', password = '%s', username = '%s';") + % user.getLogin() % user.getPassword() % user.getUsername()).str(); + work w(*c); + w.exec(sql); + manager->freeConnection(c); + } catch (...) { + + throw; + } +} diff --git a/server/internal/repository/tests/CMakeLists.txt b/server/internal/repository/tests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..23379e51ffad6c7ea1c1a2e9f15782c50f9c16b8 --- /dev/null +++ b/server/internal/repository/tests/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.19) + +project("RepositoryTests") + +set(CMAKE_CXX_STANDARD 20) + +file(GLOB SOURCES *.cpp) + +if(BUILD_TYPE) + set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fprofile-arcs -ftest-coverage -O0 -g") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage -lgcov" ) +endif(BUILD_TYPE) + + +file(GLOB TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +message("${TEST_SOURCES}") +add_executable(${PROJECT_NAME} ${TEST_SOURCES}) + +target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} ${libpqxx_LIBRARIES} ${libEntities_LIB} ${libDbManager_LIB} ${GTest_LIBRARIES} ${libRepository_LIB}) +target_include_directories(${PROJECT_NAME} PUBLIC ${libRepository_INCLUDE_DIRS}) + +target_compile_options(${PROJECT_NAME} PUBLIC --coverage) +target_link_options(${PROJECT_NAME} PUBLIC --coverage) + +gtest_discover_tests(${PROJECT_NAME}) + +add_custom_target( + ${PROJECT_NAME}_TEST + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} +) + + +add_custom_target( + ${PROJECT_NAME}_VALGRIND + COMMAND valgrind -s --leak-check=full --show-leak-kinds=all ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} +) + + + diff --git a/server/internal/repository/tests/RepositoryTests.cpp b/server/internal/repository/tests/RepositoryTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa77602c192c88d19177e777b6188fbda684cb4a --- /dev/null +++ b/server/internal/repository/tests/RepositoryTests.cpp @@ -0,0 +1,176 @@ +#include +#include +#include "MetricRepository.hpp" +#include "UserRepository.hpp" +#include "SolutionRepository.hpp" +#include "TaskRepository.hpp" +#include + +TEST(UserRepository_CRUD_Test, CRUD) { + UserRepository rep; + + EXPECT_NO_FATAL_FAILURE(rep.getUserById(1)); + + User user("test@test.com", "test", "testuser"); + size_t id = rep.makeUser(user); + user.setId(id); + std::optional new_user_opt = rep.getUserById(id); + User new_user; + if (new_user_opt) { + new_user = new_user_opt.value(); + } + EXPECT_EQ(user, new_user); + new_user.setUsername("new_test_user"); + EXPECT_NO_FATAL_FAILURE(rep.update(new_user)); + + EXPECT_NO_FATAL_FAILURE(rep.deleteUser(new_user)); +} + +TEST(TaskRepository_CRUD_Test, CRUD) { + TaskRepository rep; + + Task task("test task", 0.5); + size_t id = rep.storeTask(task); + EXPECT_NO_FATAL_FAILURE(rep.getTaskById(1)); + task.setId(id); + std::optional new_task_opt = rep.getTaskById(id); + Task new_task; + if (new_task_opt) + new_task = new_task_opt.value(); + EXPECT_EQ(task, new_task); + new_task.setDescription("new_test_description"); + EXPECT_NO_FATAL_FAILURE(rep.updateTask(new_task)); + EXPECT_NO_FATAL_FAILURE(rep.deleteTask(new_task)); +} + +TEST(SolutionRepository_CRUD_Test, CRUD) { + SolutionRepository rep; + + Solution solution("01.01.1970", 1, ":/C/Users", 1, "result", "tokens.txt", "tree.txt", 1); + size_t id = rep.storeSolution(solution); + EXPECT_NO_FATAL_FAILURE(rep.getSolutionById(163)); + solution.setId(id); + std::optional new_solution_opt = rep.getSolutionById(id); + Solution new_solution; + if (new_solution_opt) + new_solution = new_solution_opt.value(); + EXPECT_EQ(solution, new_solution); + new_solution.setSource(":/D"); + EXPECT_NO_FATAL_FAILURE(rep.updateSolution(new_solution)); + EXPECT_NO_FATAL_FAILURE(rep.deleteSolution(new_solution)); +} + +TEST(MetricRepository_CRUD_Test, CRUD) { + MetricRepository rep; + MetricStat metricStat(1, 0.8f, 0.9f, 0.89f, true, 0.85f); + size_t id = rep.storeMetric(metricStat); + EXPECT_NO_FATAL_FAILURE(rep.getById(1)); + metricStat.setId(id); + std::optional new_stat_opt = rep.getById(id); + MetricStat new_stat; + if (new_stat_opt) + new_stat = new_stat_opt.value(); + EXPECT_EQ(metricStat, new_stat); + new_stat.setMeanRes(1); + EXPECT_NO_FATAL_FAILURE(rep.updateMetric(new_stat)); + EXPECT_NO_FATAL_FAILURE(rep.deleteMetric(new_stat)); +} + +TEST(UserRepository_CRUD_Test, getAllUsers) { + UserRepository rep; + std::vector v = {{"test@test.com", "test", "testuser"}, + {"test2@test.com", "test2", "testuser2"}}; + EXPECT_NO_FATAL_FAILURE(rep.getAllUsers()); + std::vector new_v = rep.getAllUsers(); + EXPECT_EQ(v, new_v); +} + +TEST(UserRepository_CRUD_Test, loginLikeId) { + UserRepository rep; + User user("test@test.com", "test", "testuser"); + size_t id = rep.makeUser(user); + user.setId(id); + std::optional new_user_id = rep.getUserById(id); + std::optional new_user_login = rep.getUserByLogin(user.getLogin()); + User new_user; + EXPECT_EQ(new_user_id, new_user_login); + EXPECT_NO_FATAL_FAILURE(rep.deleteUser(user)); + +} + +TEST(SolutionRepository_CRUD_Test, CRUD_getSolutionsBySenderId) { + SolutionRepository rep; + + Solution solution1("01.01.1970", 1, ":/C/Users", 1, "result", "tokens.txt", "tree.txt", 1); + Solution solution2("01.01.1970", 1, "home/usr", 1, "result", "tokens.txt", "tree.txt", 1); + + + size_t id1 = rep.storeSolution(solution1); + solution1.setId(id1); + EXPECT_EQ(solution1, rep.getSolutionById(id1)); + size_t id2 = rep.storeSolution(solution2); + solution2.setId(id2); + EXPECT_EQ(solution2, rep.getSolutionById(id2)); + std::vector v = {{id1, "01.01.1970", 1, ":/C/Users", 1, "result", "tokens.txt", "tree.txt", 1}, + {id2, "01.01.1970", 1, "home/usr", 1, "result", "tokens.txt", "tree.txt", 1}}; + std::vector new_v = rep.getSolutionsBySenderId(solution1.getSenderId()); + EXPECT_EQ(v, new_v); + EXPECT_NO_FATAL_FAILURE(rep.deleteSolution(solution1)); + EXPECT_NO_FATAL_FAILURE(rep.deleteSolution(solution2)); + +} + +TEST(SolutionRepository_CRUD_Test, CRUD_getSolutionsByTaskId) { + SolutionRepository rep; + + Solution solution1("01.01.1970", 1, ":/C/Users", 1, "result", "tokens.txt", "tree.txt", 1); + Solution solution2("01.01.1970", 1, "home/usr", 1, "result", "tokens.txt", "tree.txt", 1); + + + size_t id1 = rep.storeSolution(solution1); + solution1.setId(id1); + size_t id2 = rep.storeSolution(solution2); + solution2.setId(id2); + std::vector v = {solution1, solution2}; + std::vector new_v = rep.getSolutionsByTaskId(solution1.getTaskId()); + EXPECT_EQ(v, new_v); + EXPECT_NO_FATAL_FAILURE(rep.deleteSolution(solution1)); + EXPECT_NO_FATAL_FAILURE(rep.deleteSolution(solution2)); + +} + +TEST(SolutionRepository_CRUD_Test, tryToAddWithNotExistingTask) { + SolutionRepository rep; + Solution solution("01.01.1970", 1, ":/C/Users", 100500, "result", "tokens.txt", "tree.txt", 1); + try { + rep.storeSolution(solution); + } catch (pqxx::foreign_key_violation &e) { + std::cout << e.what(); + } +} + +TEST(SolutionRepository_CRUD_Test, tryToStoreWithNotExistingSender) { + SolutionRepository rep; + + Solution solution("01.01.1970", 100500, ":/C/Users", 100500, "result", "tokens.txt", "tree.txt", 1); + try { + rep.storeSolution(solution); + } catch (pqxx::foreign_key_violation &keyViolation) { + std::cout << keyViolation.what(); + } +} + +TEST(MetricRepository_CRUD_Test, tryToStoreWithNotExistingSolution) { + MetricRepository rep; + MetricStat metricStat(100500, 0.8f, 0.9f, 0.89f, true, 0.85f); + try { + rep.storeMetric(metricStat); + } catch (pqxx::foreign_key_violation &keyViolation) { + std::cout << keyViolation.what(); + } +} + +int main(int argc, char **argv) { + ::testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/server/internal/repository/virtual/IMetricRepository.hpp b/server/internal/repository/virtual/IMetricRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fcd92fe7e4acf5f413a3937bc09cdb2117c25485 --- /dev/null +++ b/server/internal/repository/virtual/IMetricRepository.hpp @@ -0,0 +1,22 @@ +#ifndef SOURCEDOUT_IMETRICREPOSITORY_HPP +#define SOURCEDOUT_IMETRICREPOSITORY_HPP + + +#include +#include +#include "MetricStat.hpp" + +class IMetricRepository { +public: + virtual std::optional getById(size_t id) = 0; + + virtual size_t storeMetric(MetricStat metric) = 0; + + virtual void updateMetric(MetricStat metric) = 0; + + virtual void deleteMetric(MetricStat metric) = 0; + + virtual void deleteMetricById(size_t id) = 0; +}; + +#endif //SOURCEDOUT_IMETRICREPOSITORY_HPP diff --git a/server/internal/repository/virtual/ISolutionRepository.hpp b/server/internal/repository/virtual/ISolutionRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a634f4707c0593c8b62c8de1c0e53179038ccb0c --- /dev/null +++ b/server/internal/repository/virtual/ISolutionRepository.hpp @@ -0,0 +1,28 @@ +#ifndef SOURCEDOUT_ISOLUTIONREPOSITORY_HPP +#define SOURCEDOUT_ISOLUTIONREPOSITORY_HPP + +#include +#include +#include "Solution.hpp" +#include + +class ISolutionRepository { +public: + virtual std::optional getSolutionById(size_t id) = 0; + + virtual std::vector getSolutionsBySenderId(size_t sender_id) = 0; + + virtual std::vector getSolutionsByTaskId(size_t task_id) = 0; + + virtual size_t storeSolution(Solution solution) = 0; + + virtual void updateSolution(Solution solution) = 0; + + virtual void deleteSolutionById(size_t id) = 0; + + virtual void deleteSolution(Solution solution) = 0; + + virtual std::optional getOriginalSolution(size_t id) = 0; +}; + +#endif //SOURCEDOUT_ISOLUTIONREPOSITORY_HPP diff --git a/server/internal/repository/virtual/ITaskRepository.hpp b/server/internal/repository/virtual/ITaskRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dec4862a50c57a020362a7c8dfc2f1df081cac66 --- /dev/null +++ b/server/internal/repository/virtual/ITaskRepository.hpp @@ -0,0 +1,23 @@ +#ifndef SOURCEDOUT_ITASKREPOSITORY_HPP +#define SOURCEDOUT_ITASKREPOSITORY_HPP + +#include +#include "Task.hpp" +#include + +class ITaskRepository { +public: + virtual std::optional getTaskById(size_t id) = 0; + + virtual std::vector getAllTasks() = 0; + + virtual void updateTask(const Task& task) = 0; + + virtual size_t storeTask(Task task) = 0; + + virtual void deleteTask(Task task) = 0; + + virtual void deleteTaskById(size_t task_id) = 0; +}; + +#endif //SOURCEDOUT_ITASKREPOSITORY_HPP diff --git a/server/internal/repository/virtual/IUserRepository.hpp b/server/internal/repository/virtual/IUserRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..62127214a7969a99f1e8444d106a0a3d1d2858e1 --- /dev/null +++ b/server/internal/repository/virtual/IUserRepository.hpp @@ -0,0 +1,26 @@ +#ifndef SOURCEDOUT_IUSERREPOSITORY_HPP +#define SOURCEDOUT_IUSERREPOSITORY_HPP + +#include +#include "User.hpp" +#include + +class IUserRepository { +public: + virtual std::optional getUserById(size_t id) = 0; + + virtual std::optional getUserByLogin(std::string login) = 0; + + virtual size_t makeUser(User user) = 0; + + virtual void deleteUser(User user) = 0; + + virtual void update(User user) = 0; + + virtual void deleteByUserId(size_t user_id) = 0; + + virtual std::vector getAllUsers() = 0; + +}; + +#endif //SOURCEDOUT_IUSERREPOSITORY_HPP diff --git a/sql/database.sql b/sql/database.sql new file mode 100644 index 0000000000000000000000000000000000000000..5266ba29fb1382f95517cabc1e311fdf56803729 --- /dev/null +++ b/sql/database.sql @@ -0,0 +1,678 @@ +-- +-- PostgreSQL database cluster dump +-- + +-- Started on 2023-05-15 22:49:08 + +SET default_transaction_read_only = off; + +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; + +-- +-- Roles +-- + +CREATE ROLE postgres; +ALTER ROLE postgres WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN REPLICATION BYPASSRLS PASSWORD 'SCRAM-SHA-256$4096:nOmjHrNPdaIcnCeed7FgbQ==$U+pukPiYK1tBvbNsPjn4d9zV4IXLekf/OMW5+ZDzgrY=:1f9vBcPgoAcX5hmUUOkjkXLp0FRCqsnlQRmYs2U29pU='; + +-- +-- User Configurations +-- + + + + + + + + +-- +-- Databases +-- + +-- +-- Database "template1" dump +-- + +\connect template1 + +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 15.2 +-- Dumped by pg_dump version 15.2 + +-- Started on 2023-05-15 22:49:08 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- Completed on 2023-05-15 22:49:08 + +-- +-- PostgreSQL database dump complete +-- + +-- +-- Database "mydb" dump +-- + +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 15.2 +-- Dumped by pg_dump version 15.2 + +-- Started on 2023-05-15 22:49:08 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- TOC entry 3362 (class 1262 OID 16565) +-- Name: mydb; Type: DATABASE; Schema: -; Owner: postgres +-- + +CREATE DATABASE mydb WITH TEMPLATE = template0 ENCODING = 'UTF8' LOCALE_PROVIDER = libc LOCALE = 'Russian_Russia.1251'; + + +ALTER DATABASE mydb OWNER TO postgres; + +\connect mydb + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- TOC entry 215 (class 1259 OID 16574) +-- Name: users; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.users ( + id integer NOT NULL, + login character varying(255), + password character varying(255), + username character varying(255) +); + + +ALTER TABLE public.users OWNER TO postgres; + +-- +-- TOC entry 214 (class 1259 OID 16573) +-- Name: Users_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public."Users_id_seq" + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public."Users_id_seq" OWNER TO postgres; + +-- +-- TOC entry 3363 (class 0 OID 0) +-- Dependencies: 214 +-- Name: Users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public."Users_id_seq" OWNED BY public.users.id; + + +-- +-- TOC entry 219 (class 1259 OID 16613) +-- Name: metricstat; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.metricstat ( + id integer NOT NULL, + solution_id integer, + text_based_res real, + token_based_res real, + tree_based_res real, + verdict boolean, + mean_res real +); + + +ALTER TABLE public.metricstat OWNER TO postgres; + +-- +-- TOC entry 221 (class 1259 OID 16626) +-- Name: metricstat_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.metricstat_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + MAXVALUE 2147483647 + CACHE 1; + + +ALTER TABLE public.metricstat_id_seq OWNER TO postgres; + +-- +-- TOC entry 3364 (class 0 OID 0) +-- Dependencies: 221 +-- Name: metricstat_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.metricstat_id_seq OWNED BY public.metricstat.id; + + +-- +-- TOC entry 217 (class 1259 OID 16583) +-- Name: solutions; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.solutions ( + id integer NOT NULL, + send_date date NOT NULL, + sender_id integer, + source character varying(255), + task_id integer, + result character varying, + tokens character varying, + asttree character varying, + original_solution_id integer +); + + +ALTER TABLE public.solutions OWNER TO postgres; + +-- +-- TOC entry 216 (class 1259 OID 16582) +-- Name: solutions_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.solutions_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.solutions_id_seq OWNER TO postgres; + +-- +-- TOC entry 3365 (class 0 OID 0) +-- Dependencies: 216 +-- Name: solutions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.solutions_id_seq OWNED BY public.solutions.id; + + +-- +-- TOC entry 218 (class 1259 OID 16598) +-- Name: tasks; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.tasks ( + id integer NOT NULL, + description text, + treshold real +); + + +ALTER TABLE public.tasks OWNER TO postgres; + +-- +-- TOC entry 220 (class 1259 OID 16623) +-- Name: tasks_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.tasks_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + MAXVALUE 2147483647 + CACHE 1; + + +ALTER TABLE public.tasks_id_seq OWNER TO postgres; + +-- +-- TOC entry 3366 (class 0 OID 0) +-- Dependencies: 220 +-- Name: tasks_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.tasks_id_seq OWNED BY public.tasks.id; + + +-- +-- TOC entry 3191 (class 2604 OID 16628) +-- Name: metricstat id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.metricstat ALTER COLUMN id SET DEFAULT nextval('public.metricstat_id_seq'::regclass); + + +-- +-- TOC entry 3189 (class 2604 OID 16586) +-- Name: solutions id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.solutions ALTER COLUMN id SET DEFAULT nextval('public.solutions_id_seq'::regclass); + + +-- +-- TOC entry 3190 (class 2604 OID 16625) +-- Name: tasks id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.tasks ALTER COLUMN id SET DEFAULT nextval('public.tasks_id_seq'::regclass); + + +-- +-- TOC entry 3188 (class 2604 OID 16577) +-- Name: users id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public."Users_id_seq"'::regclass); + + +-- +-- TOC entry 3354 (class 0 OID 16613) +-- Dependencies: 219 +-- Data for Name: metricstat; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +COPY public.metricstat (id, solution_id, text_based_res, token_based_res, tree_based_res, verdict, mean_res) FROM stdin; +15 1 1 1 1 t 1 +\. + + +-- +-- TOC entry 3352 (class 0 OID 16583) +-- Dependencies: 217 +-- Data for Name: solutions; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +COPY public.solutions (id, send_date, sender_id, source, task_id, result, tokens, asttree, original_solution_id) FROM stdin; +1 2023-05-02 10 0.1 27 0.1 0.1 0.1 1 +\. + + +-- +-- TOC entry 3353 (class 0 OID 16598) +-- Dependencies: 218 +-- Data for Name: tasks; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +COPY public.tasks (id, description, treshold) FROM stdin; +27 orher_description 0.1 +1 description 0.5 +\. + + +-- +-- TOC entry 3350 (class 0 OID 16574) +-- Dependencies: 215 +-- Data for Name: users; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +COPY public.users (id, login, password, username) FROM stdin; +1 qwerty200468@gmail.com 123 tolik +2 qwerty200468@gmail.com 123 tolik +3 qwerty200468@gmail.com 123 tolik +4 qwerty200468@gmail.com 123 tolik +5 qwerty200468@gmail.com 123 tolik +6 qwerty200468@gmail.com 123 tolik +7 qwerty200468@gmail.com 123 tolik +8 qwerty200468@gmail.com 123 tolik +9 qwerty200468@gmail.com 123 tolik +10 qwerty200468@gmail.com 123 tolik +52 qwerty200468@gmail.com 123 tolik +\. + + +-- +-- TOC entry 3367 (class 0 OID 0) +-- Dependencies: 214 +-- Name: Users_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public."Users_id_seq"', 78, true); + + +-- +-- TOC entry 3368 (class 0 OID 0) +-- Dependencies: 221 +-- Name: metricstat_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.metricstat_id_seq', 36, true); + + +-- +-- TOC entry 3369 (class 0 OID 0) +-- Dependencies: 216 +-- Name: solutions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.solutions_id_seq', 150, true); + + +-- +-- TOC entry 3370 (class 0 OID 0) +-- Dependencies: 220 +-- Name: tasks_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.tasks_id_seq', 34, true); + + +-- +-- TOC entry 3193 (class 2606 OID 16581) +-- Name: users Users_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT "Users_pkey" PRIMARY KEY (id); + + +-- +-- TOC entry 3202 (class 2606 OID 16617) +-- Name: metricstat metricStat_pk; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.metricstat + ADD CONSTRAINT "metricStat_pk" PRIMARY KEY (id); + + +-- +-- TOC entry 3198 (class 2606 OID 16588) +-- Name: solutions solutions_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT solutions_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3200 (class 2606 OID 16604) +-- Name: tasks tasks_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.tasks + ADD CONSTRAINT tasks_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3194 (class 1259 OID 16637) +-- Name: fki_original_solution_id; Type: INDEX; Schema: public; Owner: postgres +-- + +CREATE INDEX fki_original_solution_id ON public.solutions USING btree (original_solution_id); + + +-- +-- TOC entry 3195 (class 1259 OID 16594) +-- Name: fki_sender_id; Type: INDEX; Schema: public; Owner: postgres +-- + +CREATE INDEX fki_sender_id ON public.solutions USING btree (sender_id); + + +-- +-- TOC entry 3196 (class 1259 OID 16610) +-- Name: fki_task_id; Type: INDEX; Schema: public; Owner: postgres +-- + +CREATE INDEX fki_task_id ON public.solutions USING btree (task_id); + + +-- +-- TOC entry 3203 (class 2606 OID 16632) +-- Name: solutions original_solution_id; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT original_solution_id FOREIGN KEY (original_solution_id) REFERENCES public.solutions(id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + + +-- +-- TOC entry 3204 (class 2606 OID 16589) +-- Name: solutions sender_id; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT sender_id FOREIGN KEY (sender_id) REFERENCES public.users(id) ON UPDATE RESTRICT ON DELETE CASCADE NOT VALID; + + +-- +-- TOC entry 3206 (class 2606 OID 16618) +-- Name: metricstat solutions_id; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.metricstat + ADD CONSTRAINT solutions_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id); + + +-- +-- TOC entry 3205 (class 2606 OID 16605) +-- Name: solutions task_id; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT task_id FOREIGN KEY (task_id) REFERENCES public.tasks(id) NOT VALID; + + +-- Completed on 2023-05-15 22:49:09 + +-- +-- PostgreSQL database dump complete +-- + +-- +-- Database "postgres" dump +-- + +\connect postgres + +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 15.2 +-- Dumped by pg_dump version 15.2 + +-- Started on 2023-05-15 22:49:09 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- TOC entry 8 (class 2615 OID 16398) +-- Name: pgagent; Type: SCHEMA; Schema: -; Owner: postgres +-- + +CREATE SCHEMA pgagent; + + +ALTER SCHEMA pgagent OWNER TO postgres; + +-- +-- TOC entry 3437 (class 0 OID 0) +-- Dependencies: 8 +-- Name: SCHEMA pgagent; Type: COMMENT; Schema: -; Owner: postgres +-- + +COMMENT ON SCHEMA pgagent IS 'pgAgent system tables'; + + +-- +-- TOC entry 2 (class 3079 OID 16384) +-- Name: adminpack; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS adminpack WITH SCHEMA pg_catalog; + + +-- +-- TOC entry 3438 (class 0 OID 0) +-- Dependencies: 2 +-- Name: EXTENSION adminpack; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION adminpack IS 'administrative functions for PostgreSQL'; + + +-- +-- TOC entry 3 (class 3079 OID 16399) +-- Name: pgagent; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pgagent WITH SCHEMA pgagent; + + +-- +-- TOC entry 3439 (class 0 OID 0) +-- Dependencies: 3 +-- Name: EXTENSION pgagent; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pgagent IS 'A PostgreSQL job scheduler'; + + +-- +-- TOC entry 3218 (class 0 OID 16400) +-- Dependencies: 219 +-- Data for Name: pga_jobagent; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_jobagent (jagpid, jaglogintime, jagstation) FROM stdin; +7380 2023-05-09 17:32:50.44529+03 DESKTOP-CLI5MDC +\. + + +-- +-- TOC entry 3219 (class 0 OID 16409) +-- Dependencies: 221 +-- Data for Name: pga_jobclass; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_jobclass (jclid, jclname) FROM stdin; +\. + + +-- +-- TOC entry 3220 (class 0 OID 16419) +-- Dependencies: 223 +-- Data for Name: pga_job; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_job (jobid, jobjclid, jobname, jobdesc, jobhostagent, jobenabled, jobcreated, jobchanged, jobagentid, jobnextrun, joblastrun) FROM stdin; +\. + + +-- +-- TOC entry 3222 (class 0 OID 16467) +-- Dependencies: 227 +-- Data for Name: pga_schedule; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_schedule (jscid, jscjobid, jscname, jscdesc, jscenabled, jscstart, jscend, jscminutes, jschours, jscweekdays, jscmonthdays, jscmonths) FROM stdin; +\. + + +-- +-- TOC entry 3223 (class 0 OID 16495) +-- Dependencies: 229 +-- Data for Name: pga_exception; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_exception (jexid, jexscid, jexdate, jextime) FROM stdin; +\. + + +-- +-- TOC entry 3224 (class 0 OID 16509) +-- Dependencies: 231 +-- Data for Name: pga_joblog; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_joblog (jlgid, jlgjobid, jlgstatus, jlgstart, jlgduration) FROM stdin; +\. + + +-- +-- TOC entry 3221 (class 0 OID 16443) +-- Dependencies: 225 +-- Data for Name: pga_jobstep; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_jobstep (jstid, jstjobid, jstname, jstdesc, jstenabled, jstkind, jstcode, jstconnstr, jstdbname, jstonerror, jscnextrun) FROM stdin; +\. + + +-- +-- TOC entry 3225 (class 0 OID 16525) +-- Dependencies: 233 +-- Data for Name: pga_jobsteplog; Type: TABLE DATA; Schema: pgagent; Owner: postgres +-- + +COPY pgagent.pga_jobsteplog (jslid, jsljlgid, jsljstid, jslstatus, jslresult, jslstart, jslduration, jsloutput) FROM stdin; +\. + + +-- Completed on 2023-05-15 22:49:09 + +-- +-- PostgreSQL database dump complete +-- + +-- Completed on 2023-05-15 22:49:09 + +-- +-- PostgreSQL database cluster dump complete +-- + diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index a222488a58895354eb7cb45f7d88ebc36a23a799..0000000000000000000000000000000000000000 --- a/src/main.cpp +++ /dev/null @@ -1,321 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace beast = boost::beast; // from -namespace http = beast::http; // from -namespace net = boost::asio; // from -using tcp = boost::asio::ip::tcp; // from - -//------------------------------------------------------------------------------ - -// Return a reasonable mime type based on the extension of a file. -beast::string_view -mime_type(beast::string_view path) -{ - using beast::iequals; - auto const ext = [&path] - { - auto const pos = path.rfind("."); - if(pos == beast::string_view::npos) - return beast::string_view{}; - return path.substr(pos); - }(); - if(iequals(ext, ".htm")) return "text/html"; - if(iequals(ext, ".html")) return "text/html"; - if(iequals(ext, ".php")) return "text/html"; - if(iequals(ext, ".css")) return "text/css"; - if(iequals(ext, ".txt")) return "text/plain"; - if(iequals(ext, ".js")) return "application/javascript"; - if(iequals(ext, ".json")) return "application/json"; - if(iequals(ext, ".xml")) return "application/xml"; - if(iequals(ext, ".swf")) return "application/x-shockwave-flash"; - if(iequals(ext, ".flv")) return "video/x-flv"; - if(iequals(ext, ".png")) return "image/png"; - if(iequals(ext, ".jpe")) return "image/jpeg"; - if(iequals(ext, ".jpeg")) return "image/jpeg"; - if(iequals(ext, ".jpg")) return "image/jpeg"; - if(iequals(ext, ".gif")) return "image/gif"; - if(iequals(ext, ".bmp")) return "image/bmp"; - if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; - if(iequals(ext, ".tiff")) return "image/tiff"; - if(iequals(ext, ".tif")) return "image/tiff"; - if(iequals(ext, ".svg")) return "image/svg+xml"; - if(iequals(ext, ".svgz")) return "image/svg+xml"; - return "application/text"; -} - -// Append an HTTP rel-path to a local filesystem path. -// The returned path is normalized for the platform. -std::string -path_cat( - beast::string_view base, - beast::string_view path) -{ - if (base.empty()) - return std::string(path); - std::string result(base); -#ifdef BOOST_MSVC - char constexpr path_separator = '\\'; - if(result.back() == path_separator) - result.resize(result.size() - 1); - result.append(path.data(), path.size()); - for(auto& c : result) - if(c == '/') - c = path_separator; -#else - char constexpr path_separator = '/'; - if(result.back() == path_separator) - result.resize(result.size() - 1); - result.append(path.data(), path.size()); -#endif - return result; -} - -// This function produces an HTTP response for the given -// request. The type of the response object depends on the -// contents of the request, so the interface requires the -// caller to pass a generic lambda for receiving the response. -template< - class Body, class Allocator, - class Send> -void -handle_request( - beast::string_view doc_root, - http::request>&& req, - Send&& send) -{ - // Returns a bad request response - 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; - }; - - // Returns a not found response - auto const not_found = - [&req](beast::string_view target) - { - http::response res{http::status::not_found, 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() = "The resource '" + std::string(target) + "' was not found."; - res.prepare_payload(); - return res; - }; - - // Returns a server error response - auto const server_error = - [&req](beast::string_view what) - { - http::response res{http::status::internal_server_error, 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() = "An error occurred: '" + std::string(what) + "'"; - res.prepare_payload(); - return res; - }; - - // Make sure we can handle the method - if( req.method() != http::verb::get && - req.method() != http::verb::head) - return send(bad_request("Unknown HTTP-method")); - - // Request path must be absolute and not contain "..". - if( req.target().empty() || - req.target()[0] != '/' || - req.target().find("..") != beast::string_view::npos) - return send(bad_request("Illegal request-target")); - - // Build the path to the requested file - std::string path = path_cat(doc_root, req.target()); - if(req.target().back() == '/') - path.append("index.html"); - - // Attempt to open the file - beast::error_code ec; - http::file_body::value_type body; - body.open(path.c_str(), beast::file_mode::scan, ec); - - // Handle the case where the file doesn't exist - if(ec == beast::errc::no_such_file_or_directory) - return send(not_found(req.target())); - - // Handle an unknown error - if(ec) - return send(server_error(ec.message())); - - // Cache the size since we need it after the move - auto const size = body.size(); - - // Respond to HEAD request - if(req.method() == http::verb::head) - { - http::response res{http::status::ok, req.version()}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, mime_type(path)); - res.content_length(size); - res.keep_alive(req.keep_alive()); - return send(std::move(res)); - } - - // Respond to GET request - http::response res{ - std::piecewise_construct, - std::make_tuple(std::move(body)), - std::make_tuple(http::status::ok, req.version())}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, mime_type(path)); - res.content_length(size); - res.keep_alive(req.keep_alive()); - return send(std::move(res)); -} - -//------------------------------------------------------------------------------ - -// Report a failure -void -fail(beast::error_code ec, char const* what) -{ - std::cerr << what << ": " << ec.message() << "\n"; -} - -// This is the C++11 equivalent of a generic lambda. -// The function object is used to send an HTTP message. -template -struct send_lambda -{ - Stream& stream_; - bool& close_; - beast::error_code& ec_; - - explicit - send_lambda( - Stream& stream, - bool& close, - beast::error_code& ec) - : stream_(stream) - , close_(close) - , ec_(ec) - { - } - - template - void - operator()(http::message&& msg) const - { - // Determine if we should close the connection after - close_ = msg.need_eof(); - - // We need the serializer here because the serializer requires - // a non-const file_body, and the message oriented version of - // http::write only works with const messages. - http::serializer sr{msg}; - http::write(stream_, sr, ec_); - } -}; - -// Handles an HTTP server connection -void -do_session( - tcp::socket& socket, - std::shared_ptr const& doc_root) -{ - bool close = false; - beast::error_code ec; - - // This buffer is required to persist across reads - beast::flat_buffer buffer; - - // This lambda is used to send messages - send_lambda lambda{socket, close, ec}; - - for(;;) - { - // Read a request - http::request req; - http::read(socket, buffer, req, ec); - if(ec == http::error::end_of_stream) - break; - if(ec) - return fail(ec, "read"); - - // Send the response - handle_request(*doc_root, std::move(req), lambda); - if(ec) - return fail(ec, "write"); - if(close) - { - // This means we should close the connection, usually because - // the response indicated the "Connection: close" semantic. - break; - } - } - - // Send a TCP shutdown - socket.shutdown(tcp::socket::shutdown_send, ec); - - // At this point the connection is closed gracefully -} - -//------------------------------------------------------------------------------ - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 4) - { - std::cerr << - "Usage: http-server-sync
\n" << - "Example:\n" << - " http-server-sync 0.0.0.0 8080 .\n"; - return EXIT_FAILURE; - } - auto const address = net::ip::make_address(argv[1]); - auto const port = static_cast(std::atoi(argv[2])); - auto const doc_root = std::make_shared(argv[3]); - - // The io_context is required for all I/O - net::io_context ioc{1}; - - // The acceptor receives incoming connections - tcp::acceptor acceptor{ioc, {address, port}}; - for(;;) - { - // This will receive the new connection - tcp::socket socket{ioc}; - - // Block until we get a connection - acceptor.accept(socket); - - // Launch the session, transferring ownership of the socket - std::thread{std::bind( - &do_session, - std::move(socket), - doc_root)}.detach(); - } - } - catch (const std::exception& e) - { - std::cerr << "Error: " << e.what() << std::endl; - return EXIT_FAILURE; - } -} \ No newline at end of file diff --git a/text-basic-metrics/code1.txt b/text-basic-metrics/code1.txt deleted file mode 100644 index 5fa95b8f8462b43d7b70943fc4b1f5d124dec881..0000000000000000000000000000000000000000 --- a/text-basic-metrics/code1.txt +++ /dev/null @@ -1,29 +0,0 @@ -// однострочный комментарий -// еще один -// вау еще один - -#include -#include -#include - -using namespace std; - -/* многострочный комм - * // внутри него однострочный - * - */ - - -int main() { - stringstream ss; - string res; - // ещё в код напихаю комментов - ss << "a bwfw ce "; - while(getline(ss, res, ' ')){ //комментарий после строки с кодом - /* - * летс гоу - * худшее место для многострочного коммента - */ - cout << res << endl; /* многострочный однострочно */ - } -} diff --git a/text-basic-metrics/code2.txt b/text-basic-metrics/code2.txt deleted file mode 100644 index 2115b76e6866f8af7e14dbd7de1ed6fe3a2c9ec2..0000000000000000000000000000000000000000 --- a/text-basic-metrics/code2.txt +++ /dev/null @@ -1,29 +0,0 @@ -// однострочный комментарий -// еще один -// вау еще один - -#include -#include -#include - -using namespace std; - -/* многострочный комм - * // внутри него однострочный - * - */ - - -int main() { - stringstream ss1; - string res1; - // ещё в код напихаю комментов - ss1 << "a bwfw ce "; - while(getline(ss, res1, ' ')){ //комментарий после строки с кодом - /* - * летс гоу - * худшее место для многострочного коммента - */ - cout << res1 << endl; /* многострочный однострочно */ - } -} \ No newline at end of file diff --git a/text-basic-metrics/tbm_main.cpp b/text-basic-metrics/tbm_main.cpp deleted file mode 100644 index fdd4253768b6369af5fe434526e26cbb9fc30bcd..0000000000000000000000000000000000000000 --- a/text-basic-metrics/tbm_main.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// Created by march on 21.04.2023. -// - -#include -#include -#include -#include -#include -#include -#include - -#include - - -std::string deleteComms(const std::string& text){ - std::string modif; - std::string res; - - std::stringstream ss; - std::string line; - - ss << text; - - while(getline(ss, line)){ - line.pop_back(); - line.push_back('\0'); - modif += line; - } - - bool s_comm = false; - bool m_comm = false; - - for (int i = 0; i < modif.size(); i++){ - if (s_comm && modif[i] == '\0') - s_comm = false; - else if (m_comm && modif[i] == '*' && modif[i + 1] == '/') - m_comm = false, i++; - else if (s_comm || m_comm) - continue; - else if (modif[i] == '/' && modif[i+1] == '/') - s_comm = true, i++; - else if (modif[i] == '/' && modif[i+1] == '*') - m_comm = true, i++; - - else if (modif[i] != '\0') - res += modif[i]; - else{ - res += '\n'; - } - } - return res; -} - -std::vector tbm_tokenizer(const std::string &text){ - boost::char_separator sep(" {}();,\"\0\'"); - std::vector res; - boost::tokenizer < boost::char_separator > tokens(text, sep); - - for (const std::string &s: tokens) { - if (!s.empty() && s[0] != '\n' && s[0] != '\0'){ - res.push_back(s); - } - } - return res; -} - -// % = intersection(A, B) / union(A, B) -double Jaccard_metric(const std::vector & tokens1, const std::vector & tokens2){ - std::set s1; - std::set s2; - - for (auto &i : tokens1) s1.insert(i); - for (auto &i : tokens2) s2.insert(i); - - - std::set intersect_sets; - set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), - std::inserter(intersect_sets, intersect_sets.begin())); - - std::set union_sets; - set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), - std::inserter(union_sets, union_sets.begin())); - - std::cout << intersect_sets.size() << " " << union_sets.size() << std::endl; - - return static_cast (intersect_sets.size()) / static_cast (union_sets.size()); -} - -double Livenstain_dist(std::vector tokens1, std::vector tokens2){ - unsigned long n = tokens1.size(); - unsigned long m = tokens2.size(); - int x, y, z; - - std::vector > lev (n, std::vector (m, 0)); - - for (int i = 0; i < n; i++){ - for (int j = 0; j < m; j++){ - if (std::min(i, j) == 0){ - lev[i][j] = std::max(i, j); - } - else{ - x = lev[i-1][j]; - y = lev[i][j-1]; - z = lev[i-1][j-1]; - lev[i][j] = std::min(x, std::min(y, z)); - if (tokens1[i] != tokens2[j]){ - lev[i][j]++; - } - } - } - } - - return lev[n-1][m-1]; -} - -std::pair textCompare(std::istream& fin1, std::istream& fin2){ - std::string line; - - std::string text1( (std::istreambuf_iterator(fin1) ), - (std::istreambuf_iterator() ) ); - - std::string text2( (std::istreambuf_iterator(fin2) ), - (std::istreambuf_iterator() ) ); - - std::string non_comm_text1 = deleteComms(text1); - std::string non_comm_text2 = deleteComms(text2); - - std::vector tokens1 = tbm_tokenizer(non_comm_text1); - std::vector tokens2 = tbm_tokenizer(non_comm_text2); - - double res1 = Jaccard_metric(tokens1, tokens2); - double res2 = 1 - Livenstain_dist(tokens1, tokens2) / std::max(tokens1.size(), tokens2.size()); - - return {res1, res2}; -} - -int main(){ - - std::ifstream fin1; - fin1.open("text-basic-metrics/code1.txt"); - assert(fin1.is_open()); - - std::ifstream fin2; - fin2.open("text-basic-metrics/code2.txt"); - assert(fin2.is_open()); - - std::pair metrics_res = textCompare(fin1, fin2); - - std::cout << "Jaccard metric "<< metrics_res.first << "\nLivenstein distance: " << metrics_res.second; - fin1.close(); - fin2.close(); -} \ No newline at end of file