Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ vcpkg_installed/
out/

app.aps

.idea/

external/
22 changes: 17 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ find_package(boost_program_options CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(unofficial-minizip CONFIG REQUIRED)
find_package(indicators CONFIG REQUIRED)
find_package(Drogon CONFIG REQUIRED)
find_package(libpqxx CONFIG REQUIRED)
find_package(yaml-cpp CONFIG REQUIRED)


# Add source to this project's executable.
add_executable (${PROJECT_NAME}
Expand All @@ -23,16 +27,24 @@ add_executable (${PROJECT_NAME}
"src/sim_object.cpp"
"src/tac_file.cpp"
"src/utils.cpp"
"src/tac_file_load.cpp"
"src/tac_file_load.cpp"
"src/TAWAServer.cpp"
"src/data_service.cpp"
"src/server_configuration.cpp"
app.rc
)

target_include_directories(${PROJECT_NAME} PRIVATE "include")

target_link_libraries(${PROJECT_NAME} PRIVATE Boost::program_options)
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
target_link_libraries(${PROJECT_NAME} PRIVATE unofficial::minizip::minizip)
target_link_libraries(${PROJECT_NAME} PRIVATE indicators::indicators)
target_link_libraries(${PROJECT_NAME} PRIVATE
Boost::program_options
nlohmann_json::nlohmann_json
unofficial::minizip::minizip
indicators::indicators
Drogon::Drogon
libpqxx::pqxx
yaml-cpp::yaml-cpp
)

include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/package)
Expand Down
122 changes: 122 additions & 0 deletions docs/DB_schema.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36" version="26.1.1">
<diagram name="Σελίδα-1" id="thPBAzfYCgscxObfsKNT">
<mxGraphModel dx="1322" dy="627" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="TOeSlXEH2KMvcgAng6fR-13" value="TacFile" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="30" y="210" width="200" height="70" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-17" value="Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-13" vertex="1">
<mxGeometry y="30" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-14" value="StartTime : DateTime" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-13" vertex="1">
<mxGeometry y="50" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-19" value="PilotRun" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="610" y="130" width="200" height="210" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-20" value="Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="30" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-33" value="PilotId : Pilot.Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="50" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-39" value="Team : String (Red | Blue)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="70" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-21" value="StartTime : DateTime" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="90" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-23" value="StartTimeRel : TimeDelta" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="110" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-22" value="EndTime : DateTime" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="130" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-24" value="EndTimeRel : TimeDelta" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="150" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-5" value="TacFileId : TacFile.Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="TOeSlXEH2KMvcgAng6fR-19">
<mxGeometry y="170" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-25" value="PositionFile : ServerFile.Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-19" vertex="1">
<mxGeometry y="190" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-26" value="Pilot" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="214" y="90" width="200" height="70" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-27" value="Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-26" vertex="1">
<mxGeometry y="30" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-28" value="Username" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-26" vertex="1">
<mxGeometry y="50" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-34" value="Missile" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="330" y="420" width="200" height="110" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-35" value="Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-34" vertex="1">
<mxGeometry y="30" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-38" value="Type : String" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-34" vertex="1">
<mxGeometry y="50" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-37" value="LauncherId : PilotRun.Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-34" vertex="1">
<mxGeometry y="70" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="TOeSlXEH2KMvcgAng6fR-36" value="TargetId : PilotRun.Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="TOeSlXEH2KMvcgAng6fR-34" vertex="1">
<mxGeometry y="90" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-1" value="ServerFile" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="10" y="390" width="200" height="90" as="geometry" />
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-2" value="Id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="lN982t2cmF7MJWigbtpf-1">
<mxGeometry y="30" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-4" value="Filename" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="lN982t2cmF7MJWigbtpf-1">
<mxGeometry y="50" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-3" value="FilePath" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="lN982t2cmF7MJWigbtpf-1">
<mxGeometry y="70" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="TOeSlXEH2KMvcgAng6fR-25" target="lN982t2cmF7MJWigbtpf-1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="110" y="340" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.58;entryY=0.001;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="TOeSlXEH2KMvcgAng6fR-33" target="TOeSlXEH2KMvcgAng6fR-26">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="lN982t2cmF7MJWigbtpf-5" target="TOeSlXEH2KMvcgAng6fR-13">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="260" y="320" />
<mxPoint x="260" y="190" />
<mxPoint x="130" y="190" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="TOeSlXEH2KMvcgAng6fR-37" target="TOeSlXEH2KMvcgAng6fR-19">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="570" y="500" />
<mxPoint x="570" y="100" />
<mxPoint x="710" y="100" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="lN982t2cmF7MJWigbtpf-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.397;entryY=0.003;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="TOeSlXEH2KMvcgAng6fR-36" target="TOeSlXEH2KMvcgAng6fR-19">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="590" y="520" />
<mxPoint x="590" y="110" />
<mxPoint x="689" y="110" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
21 changes: 21 additions & 0 deletions include/TAWAServer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include <drogon/HttpController.h>

using namespace drogon;
namespace api {
namespace v1 {
class Pilot : public drogon::HttpController<Pilot> {
public:
METHOD_LIST_BEGIN
// use METHOD_ADD to add your custom processing function here;
METHOD_ADD(Pilot::getPilots, "/", Get); // path is /api/v1/Pilot/
METHOD_LIST_END
// your declaration of processing function maybe like this:
void getPilots(const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) const;

public:
Pilot() = default;
};
} // namespace v1
} // namespace api
39 changes: 39 additions & 0 deletions include/data_service.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <iostream>
#include <memory>
#include <mutex>
#include <pqxx/pqxx>
#include <queue>
#include <string_view>
#include <vector>

class DataService {
private:
// Database connection parameters
std::string dbname;
std::string user;
std::string password;
std::string hostaddr;
uint16_t port;
std::vector<std::unique_ptr<pqxx::connection>> connection_pool;
std::queue<pqxx::connection *> connection_queue;
std::mutex connection_queue_lock;

std::unique_ptr<pqxx::connection> CreateConnection();

public:
DataService() = default;
DataService(std::string_view dbname,
std::string_view user,
std::string_view password,
std::string_view hostaddr,
uint16_t port);
~DataService();

void Init(uint16_t count);
bool Test();
void ReleaseConnection(pqxx::connection *conn);
pqxx::connection *GetConnection();
std::unique_ptr<pqxx::result> ExecuteQuery(const std::string &query, const pqxx::params &params = {});
};
8 changes: 8 additions & 0 deletions include/global.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
#pragma once

#include "data_service.hpp"
#include "server_configuration.hpp"

#include <string>
#include <filesystem>
#include <memory>

extern std::filesystem::path exe_path;
extern std::filesystem::path exe_dir;

extern std::unique_ptr<DataService> data_service;
extern std::unique_ptr<ServerConfiguration> server_config;
32 changes: 32 additions & 0 deletions include/server_configuration.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <filesystem>
#include <string>

class ServerConfiguration {
public:
struct DatabaseConfig {
std::string host;
uint16_t port;
std::string username;
std::string password;
std::string database;
};

struct ServerConfig {
std::string host;
uint16_t port;
};

struct LogConfig {
std::filesystem::path log_directory;
int log_level;
};

ServerConfiguration() = default;
bool LoadYamlConfig();
bool LoadYamlConfig(const std::filesystem::path &path);
DatabaseConfig database_config;
ServerConfig web_api_config;
LogConfig log_config;
};
58 changes: 58 additions & 0 deletions sql_scripts/db_setup.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
CREATE TABLE Pilot (
Id SERIAL PRIMARY KEY,
Username VARCHAR(255) NOT NULL
);

CREATE UNIQUE INDEX idx_pilot_username ON Pilot(Username);

CREATE TABLE ServerFile (
Id SERIAL PRIMARY KEY,
Filename VARCHAR(255) NOT NULL,
FilePath VARCHAR(255) NOT NULL
);

CREATE TABLE TacFile (
Id SERIAL PRIMARY KEY,
StartTime TIMESTAMP NOT NULL,
File INT NOT NULL,
FOREIGN KEY (File) REFERENCES ServerFile(Id)
);


CREATE TABLE PilotRun (
Id SERIAL PRIMARY KEY,
Team VARCHAR(10) CHECK (Team IN ('Red', 'Blue')),
PilotId INT NOT NULL,
StartTime TIMESTAMP NOT NULL,
StartTimeRel INTERVAL NOT NULL,
EndTime TIMESTAMP NOT NULL,
EndTimeRel INTERVAL NOT NULL,
TacFileId INT NOT NULL,
PositionFile INT,
FOREIGN KEY (PilotId) REFERENCES Pilot(Id),
FOREIGN KEY (TacFileId) REFERENCES TacFile(Id),
FOREIGN KEY (PositionFile) REFERENCES ServerFile(Id)
);

CREATE INDEX idx_pilotrun_pilotid ON PilotRun(PilotId);
CREATE INDEX idx_pilotrun_tacfile ON PilotRun(TacFileId);

CREATE TABLE Missile (
Id SERIAL PRIMARY KEY,
Type VARCHAR(255) NOT NULL,
Team VARCHAR(10) CHECK (Team IN ('Red', 'Blue')),
LauncherId INT,
TargetId INT,
StartTime TIMESTAMP NOT NULL,
StartTimeRel INTERVAL NOT NULL,
EndTime TIMESTAMP NOT NULL,
EndTimeRel INTERVAL NOT NULL,
TacFileId INT NOT NULL,
PositionFile INT,
FOREIGN KEY (LauncherId) REFERENCES PilotRun(Id),
FOREIGN KEY (TargetId) REFERENCES PilotRun(Id),
FOREIGN KEY (TacFileId) REFERENCES TacFile(Id),
FOREIGN KEY (PositionFile) REFERENCES ServerFile(Id)
);

CREATE INDEX idx_missile_tacfile ON Missile(TacFileId);
Loading