Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/dsm/dsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

static constexpr uint8_t DSM_VERSION_MAJOR = 2;
static constexpr uint8_t DSM_VERSION_MINOR = 2;
static constexpr uint8_t DSM_VERSION_PATCH = 3;
static constexpr uint8_t DSM_VERSION_PATCH = 4;

static auto const DSM_VERSION =
std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH);
Expand Down
11 changes: 10 additions & 1 deletion src/dsm/headers/Graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,16 @@ namespace dsm {
pNode = std::make_unique<Roundabout>(*pNode);
return dynamic_cast<Roundabout&>(*pNode);
}

Station& Graph::makeStation(Id nodeId, const unsigned int managementTime) {
if (!m_nodes.contains(nodeId)) {
throw std::invalid_argument(buildLog("Node does not exist."));
}
auto& pNode = m_nodes[nodeId];
pNode = std::make_unique<Station>(*pNode, managementTime);
return dynamic_cast<Station&>(*pNode);
}

SpireStreet& Graph::makeSpireStreet(Id streetId) {
if (!m_streets.contains(streetId)) {
throw std::invalid_argument(
Expand Down Expand Up @@ -524,5 +534,4 @@ namespace dsm {
const auto& nodePair = m_streets.at(streetId)->nodePair();
return this->street(nodePair.second, nodePair.first);
}

}; // namespace dsm
7 changes: 7 additions & 0 deletions src/dsm/headers/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "Intersection.hpp"
#include "TrafficLight.hpp"
#include "Roundabout.hpp"
#include "Station.hpp"
#include "SparseMatrix.hpp"
#include "Street.hpp"
#include "../utility/DijkstraResult.hpp"
Expand Down Expand Up @@ -183,6 +184,12 @@ namespace dsm {
/// @return A reference to the spire street
/// @throws std::invalid_argument if the street does not exist
SpireStreet& makeSpireStreet(Id streetId);
/// @brief Convert an existing node into a station
/// @param nodeId The id of the node to convert to a station
/// @param managementTime The station's management time
/// @return A reference to the station
/// @throws std::invalid_argument if the node does not exist
Station& makeStation(Id nodeId, const unsigned int managementTime);

/// @brief Add a street to the graph
/// @param street A std::shared_ptr to the street to add
Expand Down
2 changes: 2 additions & 0 deletions src/dsm/headers/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,7 @@ namespace dsm {
virtual bool isIntersection() const noexcept { return false; }
virtual bool isTrafficLight() const noexcept { return false; }
virtual bool isRoundabout() const noexcept { return false; }

virtual bool isStation() const noexcept { return false; }
};
}; // namespace dsm
36 changes: 36 additions & 0 deletions src/dsm/headers/Station.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "Station.hpp"

namespace dsm {
Station::Station(Id id, Delay managementTime)
: Node(id), m_managementTime{managementTime} {}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule

Station::Station(Id id, std::pair<double, double> coords, Delay managementTime)
: Node(id, coords), m_managementTime{managementTime} {}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule

Station::Station(Node const& node, Delay managementTime)
: Node(node), m_managementTime{managementTime} {}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule

Station::Station(Station const& other)
: Node(other), m_managementTime{other.m_managementTime}, m_trains{other.m_trains} {}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule

void Station::enqueue(Id trainId, train_t trainType) {
m_trains.emplace(trainType, trainId);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
}

Id Station::dequeue() {
auto it = m_trains.begin();
Id trainId = it->second;
m_trains.erase(it);
return trainId;
}

Delay Station::managementTime() const { return m_managementTime; }

double Station::density() const {
return static_cast<double>(m_trains.size()) / m_capacity;
}

bool Station::isFull() const { return m_trains.size() >= m_capacity; }

bool Station::isStation() const noexcept { return true; }
} // namespace dsm
56 changes: 56 additions & 0 deletions src/dsm/headers/Station.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/// @file /src/dsm/headers/Station.hpp
/// @brief Defines the Station class.
///
/// @details The Station class represents a train station in the network.
/// It is a derived class of the Node class.

#pragma once

#include "Node.hpp"

#include <map>

namespace dsm {
class Station : public Node {
private:
Delay m_managementTime;
std::multimap<train_t, Id, std::greater<train_t>> m_trains;

public:
/// @brief Construct a new Station object
/// @param id The station's id
/// @param managementTime The time it takes between two train departures/arrivals
Station(Id id, Delay managementTime);
/// @brief Construct a new Station object
/// @param id The station's id
/// @param coords A std::pair containing the station's coordinates (lat, lon)
/// @param managementTime The time it takes between two train departures/arrivals
Station(Id id, std::pair<double, double> coords, Delay managementTime);
/// @brief Construct a new Station object
/// @param node A Node object representing the station
/// @param managementTime The time it takes between two train departures/arrivals
Station(Node const& node, Delay managementTime);
/// @brief Construct a new Station object by copying another Station object
/// @param other The Station object to copy
Station(Station const& other);
/// @brief Enqueue a train in the station
/// @param trainId The id of the train to enqueue
/// @param trainType The type of the train to enqueue
void enqueue(Id trainId, train_t trainType);
/// @brief Dequeue a train from the station
/// @return The id of the dequeued train
Id dequeue();
/// @brief Get the time it takes between two train departures/arrivals
/// @return The management time
Delay managementTime() const;
/// @brief Get the train density of the station
/// @return The train density of the station
double density() const final;
/// @brief Check if the station is full
/// @return True if the station is full, false otherwise
bool isFull() const final;
/// @brief Check if the node is a station
/// @return True
bool isStation() const noexcept final;
};
} // namespace dsm
10 changes: 10 additions & 0 deletions src/dsm/utility/Typedef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,15 @@ namespace dsm {
ANY = 6
};
enum class TrafficLightOptimization : uint8_t { SINGLE_TAIL = 0, DOUBLE_TAIL = 1 };
enum train_t : uint8_t {
BUS = 0, // Autobus
SFM = 1, // Servizio Ferroviario Metropolitano
R = 2, // Regionale
RV = 3, // Regionale Veloce
IC = 4, // InterCity (Notte)
FRECCIA = 5, // Frecciabianca / Frecciargento
FRECCIAROSSA = 6, // Frecciarossa
ES = 7, // Eurostar
};

}; // namespace dsm
68 changes: 68 additions & 0 deletions test/Test_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
#include "Node.hpp"
#include "Intersection.hpp"
#include "TrafficLight.hpp"
#include "Station.hpp"
#include "../utility/Typedef.hpp"

#include "doctest.h"
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

using Intersection = dsm::Intersection;
using TrafficLight = dsm::TrafficLight;
using Station = dsm::Station;

TEST_CASE("Intersection") {
SUBCASE("Constructor") {
Expand Down Expand Up @@ -207,3 +210,68 @@
// }
// }
}

TEST_CASE("Station") {
SUBCASE("Constructors") {
constexpr dsm::Id id = 1;
constexpr dsm::Delay managementTime = 2;
constexpr double lat = 2.5;
constexpr double lon = 3.5;
const std::string name = "S0001";
GIVEN("A Station object") {
WHEN("The Station is created using only an Id") {
Station station{id, managementTime};
THEN("Parameters are set correctly") {
CHECK_EQ(station.id(), id);
CHECK_EQ(station.managementTime(), managementTime);
CHECK_EQ(station.capacity(), 1);
CHECK_EQ(station.transportCapacity(), 1);
CHECK(station.name().empty());
}
}
WHEN("The Station is created using an Id and coordinates") {
Station station{id, std::make_pair(lat, lon), managementTime};

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
THEN("Parameters are set correctly") {
CHECK_EQ(station.id(), id);
CHECK_EQ(station.managementTime(), managementTime);
CHECK_EQ(station.capacity(), 1);
CHECK_EQ(station.transportCapacity(), 1);
CHECK(station.name().empty());
}
}
WHEN("The Station is created using a copy constructor") {
Station base{id, std::make_pair(lat, lon), managementTime};

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
base.setCapacity(2);
base.setTransportCapacity(3);
base.setName(name);
auto copy = base;
THEN("Parameters are set correctly") {
CHECK_EQ(copy.id(), id);
CHECK_EQ(copy.managementTime(), managementTime);
CHECK_EQ(copy.capacity(), 2);
CHECK_EQ(copy.transportCapacity(), 3);
CHECK_EQ(copy.name(), name);
}
}
}
}
SUBCASE("Enqueue and dequeue") {
constexpr dsm::Id id = 1;
constexpr dsm::Delay managementTime = 2;
GIVEN("A Station object") {
Station station{id, managementTime};
WHEN("A train is enqueued") {
station.enqueue(1, dsm::train_t::BUS);
THEN("The train is enqueued correctly") { CHECK_EQ(station.dequeue(), 1); }
}
WHEN("Multiple trains are enqueued") {
station.enqueue(1, dsm::train_t::RV);
station.enqueue(2, dsm::train_t::FRECCIAROSSA);
THEN("The trains are enqueued correctly") {
CHECK_EQ(station.dequeue(), 2);
CHECK_EQ(station.dequeue(), 1);
}
}
}
}
}
Loading